diff options
author | Keith Packard <keithp@keithp.com> | 2013-01-18 16:44:56 -0800 |
---|---|---|
committer | Keith Packard <keithp@keithp.com> | 2013-01-18 16:44:56 -0800 |
commit | 7543c6e258195833daa5f17efdc095ad25489db9 (patch) | |
tree | c3912137693b81f6f9b0d7863f0482ad48532ba1 |
Import MIT-SHM fd passing test program
Signed-off-by: Keith Packard <keithp@keithp.com>
-rw-r--r-- | Makefile | 10 | ||||
-rw-r--r-- | shmfd.c | 202 |
2 files changed, 212 insertions, 0 deletions
diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..73bd712 --- /dev/null +++ b/Makefile @@ -0,0 +1,10 @@ +CFLAGS=-O0 -g $(shell pkg-config --cflags xcb-shm xcb-aux) +LIBS=$(shell pkg-config --libs xcb-shm xcb-aux) + +OBJS=shmfd.o + +shmfd: $(OBJS) + $(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) + +clean: + rm -f shmfd $(OBJS)
\ No newline at end of file @@ -0,0 +1,202 @@ +/* + * Copyright © 2013 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include <stdio.h> +#include <stddef.h> +#include <stdlib.h> +#include <sys/mman.h> +#include <xcb/xcb.h> +#include <xcb/shm.h> +#include <xcb/xcb_aux.h> + +int +make_shm(int size, void **addrp) +{ + void *addr; + char template[] = "/tmp/shmfd-XXXXXX"; + int fd = mkstemp(template); + + if (fd < 0) + return fd; + unlink(template); + ftruncate(fd, size); + addr = mmap (NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); + if (addr == MAP_FAILED) { + close (fd); + return -1; + } + *addrp = addr; + return fd; +} + +void +paint(uint32_t *base, int width, int height, int forward) +{ + int x, y; + uint8_t r, g, b; + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + r = x * 256 / width; + g = 255 - r; + if (forward) + b = y * 256 / height; + else + b = (255 - y) * 256 / height; + base[y * width + x] = (r << 16) | (g << 8) | b; + } + } +} + +#define WIDTH 128 +#define HEIGHT 128 + +int +main (int argc, char **argv) +{ + xcb_connection_t *c; + int screen_num; + xcb_screen_t *screen; + int fd; + void *addr; + void *server_addr; + xcb_shm_seg_t shm_seg; + xcb_shm_seg_t shm_server_seg; + xcb_gc_t gc; + xcb_pixmap_t pixmap; + xcb_window_t window; + xcb_generic_event_t *event; + xcb_generic_error_t *error; + xcb_shm_create_segment_cookie_t shm_create_segment_cookie; + xcb_shm_create_segment_reply_t *shm_create_segment_reply; + xcb_generic_error_t *shm_create_segment_error; + int *shm_create_segment_fds; + uint32_t window_mask; + uint32_t window_values[5]; + uint32_t size = WIDTH * HEIGHT * 4; + + fd = make_shm(size, &addr); /* some memory */ + paint(addr, WIDTH, HEIGHT, 0); + printf ("painted\n"); + c = xcb_connect(NULL, &screen_num); + if (xcb_connection_has_error(c)) { + printf ("connection error\n"); + exit(1); + } + screen = xcb_aux_get_screen(c, screen_num); + + xcb_shm_attach_fd (c, + (shm_seg = xcb_generate_id(c)), + fd, + 1); + + shm_create_segment_cookie = xcb_shm_create_segment(c, + (shm_server_seg = xcb_generate_id(c)), + size, + 1); + shm_create_segment_reply = xcb_shm_create_segment_reply (c, + shm_create_segment_cookie, + &shm_create_segment_error); + if (shm_create_segment_reply) { + shm_create_segment_fds = xcb_shm_create_segment_reply_fds(c, + shm_create_segment_reply); + + server_addr = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, shm_create_segment_fds[0], 0); + close(shm_create_segment_fds[0]); + free(shm_create_segment_reply); + paint(server_addr, WIDTH, HEIGHT, 1); + } + else + server_addr = NULL; + + window_mask = XCB_CW_EVENT_MASK; + window_values[0] = XCB_EVENT_MASK_EXPOSURE; + + xcb_create_window(c, + 0, /* depth */ + (window = xcb_generate_id(c)), /* window */ + screen->root, /* root */ + 0, /* x */ + 0, /* y */ + WIDTH * 2, /* width */ + HEIGHT, /* height */ + 0, /* border_width */ + XCB_WINDOW_CLASS_INPUT_OUTPUT, /* class */ + screen->root_visual, /* visual */ + window_mask, /* mask */ + window_values); /* values */ + xcb_create_gc(c, + (gc = xcb_generate_id(c)), /* gc */ + window, /* drawable */ + 0, /* mask */ + NULL); /* values */ + + xcb_map_window(c, window); + + printf ("mapped\n"); + + for (;;) { + xcb_flush(c); + event = xcb_wait_for_event(c); + switch (event->response_type) { + case XCB_EXPOSE: + xcb_shm_put_image(c, + window, + gc, + WIDTH, + HEIGHT, + 0, + 0, + WIDTH, + HEIGHT, + 0, + 0, + 24, + XCB_IMAGE_FORMAT_Z_PIXMAP, + 0, + shm_seg, + 0); + xcb_shm_put_image(c, + window, + gc, + WIDTH, + HEIGHT, + 0, + 0, + WIDTH, + HEIGHT, + WIDTH, + 0, + 24, + XCB_IMAGE_FORMAT_Z_PIXMAP, + 0, + shm_server_seg, + 0); + break; + case 0: + error = (xcb_generic_error_t *) event; + printf ("error %d major %d minor %d\n", + error->error_code, + error->major_code, + error->minor_code); + break; + default: + printf ("response %d\n", event->response_type); + break; + } + } +} |