From 6c521cec36a71dd7193da9debb1129b4c041a3a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Asbj=C3=B8rn=20Sloth=20T=C3=B8nnesen?= Date: Sun, 16 Aug 2020 20:21:23 +0000 Subject: initial MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Asbjørn Sloth Tønnesen --- Makefile | 7 ++ owndisplay.c | 308 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 315 insertions(+) create mode 100644 Makefile create mode 100644 owndisplay.c diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..31a2652 --- /dev/null +++ b/Makefile @@ -0,0 +1,7 @@ +CFLAGS+=$(shell libpng-config --cflags) -g +LDFLAGS+=$(shell libpng-config --ldflags) +.PHONY: clean +owndisplay: owndisplay.o + $(CC) -o $@ $^ $(LDFLAGS) +clean: + rm -f owndisplay owndisplay.o diff --git a/owndisplay.c b/owndisplay.c new file mode 100644 index 0000000..e789cf3 --- /dev/null +++ b/owndisplay.c @@ -0,0 +1,308 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define QUEUE_LEN 1000 +#define MSGSIZE (2 + 7 * 160) + +#define DISPLAY_HOST "100.65.0.2" +#define DISPLAY_PORT 5005 +#define DISPLAY_WIDTH 1920 +#define DISPLAY_HEIGHT 1080 + +struct mmsghdr msg[QUEUE_LEN]; +struct iovec iovec[QUEUE_LEN]; +uint8_t bufs[QUEUE_LEN][MSGSIZE]; +int send_next = 0; +int next = 0; +int pos = 0; + +static void +setup(void) +{ + for (int i=0;i> 8) & 0xff; + buf[2] = y & 0xff; + buf[3] = (y >> 8) & 0xff; + buf[4] = r; + buf[5] = b; + buf[6] = g; + if (++pos == 160) { + flush_frame(); + pos = 0; + } +} + +static void +blank_screen(void) +{ + for (int x=0;xpng_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + assert(d->png_ptr); + d->info_ptr = png_create_info_struct(d->png_ptr); + assert(d->info_ptr); + png_init_io(d->png_ptr, fp); + png_set_sig_bytes(d->png_ptr, 8); + png_read_info(d->png_ptr, d->info_ptr); + d->width = png_get_image_width(d->png_ptr, d->info_ptr); + d->height = png_get_image_height(d->png_ptr, d->info_ptr); + d->color_type = png_get_color_type(d->png_ptr, d->info_ptr); + d->bit_depth = png_get_bit_depth(d->png_ptr, d->info_ptr); + + d->number_of_passes = png_set_interlace_handling(d->png_ptr); + png_read_update_info(d->png_ptr, d->info_ptr); + + d->row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * d->height); + for (int y=0; yheight; y++) + d->row_pointers[y] = (png_byte*) malloc(png_get_rowbytes(d->png_ptr,d->info_ptr)); + + png_read_image(d->png_ptr, d->row_pointers); + + fclose(fp); + + return d; +} + +static void +draw_png(struct data_png *d, int x, int y) +{ + for (int sy=0; sy < d->height; sy++) { + png_byte *row = d->row_pointers[sy]; + for (int sx=0; sx < d->width; sx++) { + uint8_t *rbga = &row[sx*4]; + if (rbga[3] > 0) + set_pixel(x+sx, y+sy, rbga[0], rbga[1], rbga[2]); + } + } +} + +struct bb_info { + int x; + int y; + int x1, y1, x2, y2; + int move_x; + int move_y; + int rate; + struct data_png *img; + const char *imgfile; +}; + +static void +bb_init(struct bb_info *bb, struct data_png *img, int x, int y, int w, int h) +{ + bb->img = img; + bb->x1 = x; + bb->y1 = y; + bb->x2 = w - img->width; + bb->y2 = h - img->height; + if (bb->x == -1) bb->x = (bb->x1 + bb->x2) / 2; + if (bb->y == -1) bb->y = (bb->y1 + bb->y2) / 2; +} + +static void +bb_draw(struct bb_info *bb) +{ + draw_png(bb->img, bb->x, bb->y); + + bb->x += bb->move_x; + bb->y += bb->move_y; + + if (bb->x < bb->x1 || bb->x > bb->x2) + bb->move_x *= -1; + if (bb->y < bb->y1 || bb->y > bb->y2) + bb->move_y *= -1; +} + +struct bb_info images[] = { + { + .imgfile = "images/unicorn_cc.png", + .move_x = 13, + .move_y = -10, + .x = -1, + .y = -1, + }, + { + .imgfile = "images/windows_logo.png", + .move_x = -8, + .move_y = 3, + .rate = 2, + .x = -1, + .y = -1, + }, + { + .imgfile = "images/spade.png", + .move_x = 32, + .move_y = -12, + .x = 0, + .y = 0, + }, + { + .imgfile = "images/dvdvideo.png", + .move_x = 200, + .move_y = 60, + .rate = 5, + .x = -1, + .y = -1, + .x = 1000, + .y = 800, + }, + { + .imgfile = "images/hackaday.png", + .move_x = 40, + .move_y = 18, + .rate = 3, + .x = -1, + .y = -1, + .x = 500, + .y = 800, + }, + {} +}; + +static void +draw_frame(unsigned int frameno) +{ + for (struct bb_info *bb = &images[0];bb->img;bb++) { + if (bb->rate && frameno % bb->rate != 0) + continue; + bb_draw(bb); + } + flush_frame(); +} + +static void +send_stuff(int fd) +{ + int retval; + int len; + int from = send_next; + if (next == send_next) { + next = 0; + send_next = 0; + return; + } else if (next > send_next) { + len = next - send_next; + } else { + len = QUEUE_LEN - send_next; + } + + retval = sendmmsg(fd, &msg[from], len, 0); + if (retval == -1) { + perror("sendmmsg()"); + return; + } + + send_next += retval; + if (send_next >= QUEUE_LEN) send_next = 0; + //printf("%d/%d messages sent from %d, continuing from %d\n", retval, len, from, send_next); +} + +int +main(void) +{ + int sockfd; + struct sockaddr_in addr; + struct hostent *hp; + + for (struct bb_info *bb = &images[0];bb->imgfile;bb++) { + bb_init(bb, open_png(bb->imgfile), 0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT); + } + + setup(); + + sockfd = socket(AF_INET, SOCK_DGRAM, 0); + if (sockfd == -1) { + perror("socket()"); + exit(EXIT_FAILURE); + } + + + if ((hp = gethostbyname(DISPLAY_HOST)) == NULL) { + return -1; + } + + addr.sin_family = AF_INET; + addr.sin_port = htons(DISPLAY_PORT); + addr.sin_addr.s_addr = *( u_long * ) hp->h_addr; + + if (connect(sockfd, (struct sockaddr *) &addr, sizeof(addr)) == -1) { + perror("connect()"); + exit(EXIT_FAILURE); + } + + //blank_screen(); + unsigned int frame = 0; + while (1) { + //printf("draw_frame\n"); + draw_frame(frame++); + int old = send_next; + for (int i=0;i<25;i++) { + send_stuff(sockfd); + send_next = old; + //usleep(15000); + } + send_stuff(sockfd); + //usleep(15000); + //break; + } + + exit(0); +} -- cgit v1.2.1