From fe85753859d3994c3d74860258be122a1bb86aa3 Mon Sep 17 00:00:00 2001 From: Wolfgang Draxinger Date: Mon, 14 Dec 2020 18:34:08 +0100 Subject: minimal example for X11 MIT-SHM with Xcb --- samples/OpenGL/compute_shader/main.c | 16 +- samples/OpenGL/minimal_glsl/minimal_glsl.c | 2 +- samples/OpenGL/pocketwatch/pocketwatch.cpp | 4 +- samples/OpenGL/x11argb_opengl_glsl/Makefile | 4 +- .../x11argb_opengl_glsl/x11argb_opengl_glsl.c | 2 +- samples/X11/xcb_shm_image/Makefile | 9 + samples/X11/xcb_shm_image/xcb_shm_image_example.c | 219 +++++++++++++++++++++ 7 files changed, 250 insertions(+), 6 deletions(-) create mode 100644 samples/X11/xcb_shm_image/Makefile create mode 100644 samples/X11/xcb_shm_image/xcb_shm_image_example.c diff --git a/samples/OpenGL/compute_shader/main.c b/samples/OpenGL/compute_shader/main.c index c6acdc3..a519439 100644 --- a/samples/OpenGL/compute_shader/main.c +++ b/samples/OpenGL/compute_shader/main.c @@ -246,6 +246,20 @@ void gldebugcallback( fprintf(stderr, "(GL) %s\n", message); } +static +void glinfodump(void) +{ + printf( + "OpenGL vendor: %s\n" + "OpenGL renderer: %s\n" + "OpenGL version: %s\n", + " GLSL version: %s\n", + glGetString(GL_VENDOR), + glGetString(GL_RENDERER), + glGetString(GL_VERSION), + glGetString(GL_SHADING_LANGUAGE_VERSION) ); +} + int main(int argc, char *argv[]) { glutInit(&argc, argv); @@ -253,7 +267,7 @@ int main(int argc, char *argv[]) glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE); glutInitWindowPosition(0,0); glutInitWindowSize(win_width, win_height); - glutCreateWindow("Compute Shader"); + glutCreateWindow("compute shader point overdraw benchmark"); if( GLEW_OK != glewInit() ) { return 1; } glDebugMessageCallback((GLDEBUGPROC)gldebugcallback, NULL); diff --git a/samples/OpenGL/minimal_glsl/minimal_glsl.c b/samples/OpenGL/minimal_glsl/minimal_glsl.c index 72ba3ff..f8599cb 100644 --- a/samples/OpenGL/minimal_glsl/minimal_glsl.c +++ b/samples/OpenGL/minimal_glsl/minimal_glsl.c @@ -1,7 +1,7 @@ #include #include #include -#include +#include static void pushModelview() { diff --git a/samples/OpenGL/pocketwatch/pocketwatch.cpp b/samples/OpenGL/pocketwatch/pocketwatch.cpp index e04ad0e..f6b49b0 100644 --- a/samples/OpenGL/pocketwatch/pocketwatch.cpp +++ b/samples/OpenGL/pocketwatch/pocketwatch.cpp @@ -14,7 +14,7 @@ void idle(); int main(int argc, char **argv) { glutInit(&argc, argv); - glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE|GLUT_DEPTH); + glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE|GLUT_DEPTH|GLUT_MULTISAMPLE); glutCreateWindow("PocketWatch"); glutDisplayFunc(display); @@ -37,6 +37,8 @@ void init() glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); + + glEnable(GL_MULTISAMPLE); } float light_position[]={-0.5,0.5,1,0}; diff --git a/samples/OpenGL/x11argb_opengl_glsl/Makefile b/samples/OpenGL/x11argb_opengl_glsl/Makefile index 62e3496..b5e461a 100644 --- a/samples/OpenGL/x11argb_opengl_glsl/Makefile +++ b/samples/OpenGL/x11argb_opengl_glsl/Makefile @@ -3,8 +3,8 @@ all: x11argb_opengl_glsl x11argb_opengl_glsl3 x11argb_opengl_glsl: x11argb_opengl_glsl.c Makefile - cc -std=c99 -g3 -o x11argb_opengl_glsl x11argb_opengl_glsl.c -lX11 -lXrender -lGLEW -lm + cc -std=c99 -g3 -o x11argb_opengl_glsl x11argb_opengl_glsl.c -lX11 -lXrender -lGL -lGLEW -lm x11argb_opengl_glsl3: x11argb_opengl_glsl.c Makefile - cc -std=c99 -g3 -o x11argb_opengl_glsl3 -D USE_GLX_CREATE_CONTEXT_ATTRIB x11argb_opengl_glsl.c -lX11 -lXrender -lGLEW -lm + cc -std=c99 -g3 -o x11argb_opengl_glsl3 -D USE_GLX_CREATE_CONTEXT_ATTRIB x11argb_opengl_glsl.c -lX11 -lXrender -lGL -lGLEW -lm diff --git a/samples/OpenGL/x11argb_opengl_glsl/x11argb_opengl_glsl.c b/samples/OpenGL/x11argb_opengl_glsl/x11argb_opengl_glsl.c index 7aae5a8..d64b655 100644 --- a/samples/OpenGL/x11argb_opengl_glsl/x11argb_opengl_glsl.c +++ b/samples/OpenGL/x11argb_opengl_glsl/x11argb_opengl_glsl.c @@ -365,7 +365,7 @@ static void createTheRenderContext() { GLX_CONTEXT_MAJOR_VERSION_ARB, 3, GLX_CONTEXT_MINOR_VERSION_ARB, 0, - //GLX_CONTEXT_FLAGS_ARB , GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, + GLX_CONTEXT_FLAGS_ARB , GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, None }; diff --git a/samples/X11/xcb_shm_image/Makefile b/samples/X11/xcb_shm_image/Makefile new file mode 100644 index 0000000..963a04b --- /dev/null +++ b/samples/X11/xcb_shm_image/Makefile @@ -0,0 +1,9 @@ +.PHONY: all clean + +all: xcb_shm_image_example + +clean: + - rm xcb_shm_image_example xcb_shm_image_example.o + +xcb_shm_image_example: LDFLAGS += -lxcb -lxcb-image -lxcb-shm +xcb_shm_image_example: xcb_shm_image_example.o diff --git a/samples/X11/xcb_shm_image/xcb_shm_image_example.c b/samples/X11/xcb_shm_image/xcb_shm_image_example.c new file mode 100644 index 0000000..4f87e76 --- /dev/null +++ b/samples/X11/xcb_shm_image/xcb_shm_image_example.c @@ -0,0 +1,219 @@ +#include +#include + +#include +#include + +#include +#include +#include + +#if __ORDER_LITTLE_ENDIAN == __BYTE_ORDER__ +# define NATIVE_XCB_IMAGE_ORDER XCB_IMAGE_ORDER_LSB_FIRST +#else +# define NATIVE_XCB_IMAGE_ORDER XCB_IMAGE_ORDER_MSB_FIRST +#endif + +enum { + IMAGE_WIDTH = 512, + IMAGE_HEIGHT = 512, + IMAGE_DEPTH = 24, +}; + +static xcb_format_t const *query_xcb_format_for_depth( + xcb_connection_t *const connection, + unsigned depth ) +{ + xcb_setup_t const *const setup = xcb_get_setup(connection); + xcb_format_iterator_t it; + for( it = xcb_setup_pixmap_formats_iterator(setup) + ; it.rem + ; xcb_format_next(&it) + ){ + xcb_format_t const *const format = it.data; + if( format->depth == depth ){ + return format; + } + } + return NULL; +} + +typedef struct shm_xcb_image_t { + xcb_connection_t *connection; + xcb_image_t *image; + xcb_shm_seg_t shm_seg; + int shm_id; +} shm_xcb_image_t; + +static shm_xcb_image_t *shm_xcb_image_create( + xcb_connection_t *const connection, + unsigned const width, + unsigned const height, + unsigned const depth ) +{ + xcb_generic_error_t *error = NULL; + + shm_xcb_image_t *shmimg = calloc(1, sizeof(*shmimg)); + if( !shmimg ){ goto fail; } + shmimg->connection = connection; + + xcb_format_t const *const format = query_xcb_format_for_depth(connection, depth); + shmimg->image = xcb_image_create( + width, height, + XCB_IMAGE_FORMAT_Z_PIXMAP, + format->scanline_pad, + format->depth, format->bits_per_pixel, 0, + NATIVE_XCB_IMAGE_ORDER, + XCB_IMAGE_ORDER_MSB_FIRST, + NULL, ~0, 0); + if( !shmimg->image ){ + fprintf(stderr, "could not create X11 image structure\n"); + } + size_t const image_segment_size = shmimg->image->stride * shmimg->image->height; + + shmimg->shm_id = shmget(IPC_PRIVATE, image_segment_size, IPC_CREAT | 0600); + if( 0 > shmimg->shm_id ){ goto fail; } + + shmimg->image->data = shmat(shmimg->shm_id, 0, 0); + if( (void*)-1 == (void*)(shmimg->image->data) ){ goto fail; } + + shmimg->shm_seg = xcb_generate_id(connection), + error = xcb_request_check(connection, + xcb_shm_attach_checked( + connection, + shmimg->shm_seg, shmimg->shm_id, 0) ); +fail: + if( shmimg ){ + if( shmimg->image ){ + if( shmimg->image->data && error ){ + shmdt(shmimg->image->data); + shmimg->image->data = NULL; + } + if( !shmimg->image->data ){ + shmctl(shmimg->shm_id, IPC_RMID, 0); + shmimg->shm_id = -1; + } + } + if( 0 > shmimg->shm_id ){ + xcb_image_destroy(shmimg->image); + shmimg->image = NULL; + } + if( !shmimg->image ){ + free(shmimg); + shmimg = NULL; + } + } + free(error); + + return shmimg; +} + +static void shm_xcb_image_destroy(shm_xcb_image_t *shmimg) +{ + xcb_shm_detach(shmimg->connection, shmimg->shm_seg); + shmdt(shmimg->image->data); + shmctl(shmimg->shm_id, IPC_RMID, 0); + xcb_image_destroy(shmimg->image); + free(shmimg); +} + +static void generate_image( + shm_xcb_image_t *shmimg, + unsigned t ) +{ + for( unsigned j = 0; j < shmimg->image->height; ++j ){ + uint8_t *const line = shmimg->image->data + j * shmimg->image->stride; + for( unsigned i = 0; i < shmimg->image->width; ++i ){ + unsigned const bytes_per_pixel = shmimg->image->bpp/8; + uint8_t *pixel = line + i * bytes_per_pixel; + + unsigned const a = (i + t); + unsigned const b = (j + (i >> 8) & 0xFF); + unsigned const c = (j >> 8) & 0xFF; + + switch( bytes_per_pixel ){ + case 4: pixel[3] = 0xFF; /* fallthrough */ + case 3: pixel[2] = a & 0xFF; /* fallthrough */ + case 2: pixel[1] = b & 0xFF; /* fallthrough */ + case 1: pixel[0] = c & 0xFF; /* fallthrough */ + default: break; + } + } + } +} + +int main(int argc, char *argv[]) +{ + /* Open the connection to the X server */ + xcb_connection_t *connection = xcb_connect(NULL, NULL); + + /* Check that X MIT-SHM is available (should be). */ + const xcb_query_extension_reply_t *shm_extension = xcb_get_extension_data(connection, &xcb_shm_id); + if( !shm_extension || !shm_extension->present ){ + fprintf(stderr, "Query for X MIT-SHM extension failed.\n"); + return 1; + } + + shm_xcb_image_t *shmimg = shm_xcb_image_create(connection, IMAGE_WIDTH, IMAGE_HEIGHT, IMAGE_DEPTH); + if( !shmimg ){ + fprintf(stderr, "Creating shared memory image failed"); + } + + /* Get the first screen */ + xcb_screen_t *const screen = xcb_setup_roots_iterator(xcb_get_setup(connection)).data; + + /* Create a window */ + uint32_t const window_mask = XCB_CW_EVENT_MASK; + uint32_t const window_values[] = { XCB_EVENT_MASK_EXPOSURE}; + xcb_drawable_t const window = xcb_generate_id(connection); + xcb_create_window(connection, + XCB_COPY_FROM_PARENT, /* depth */ + window, /* window Id */ + screen->root, /* parent window */ + 0, 0, /* x, y */ + IMAGE_WIDTH, IMAGE_HEIGHT, /* width, height */ + 0, /* border_width */ + XCB_WINDOW_CLASS_INPUT_OUTPUT, /* class */ + screen->root_visual, /* visual */ + window_mask, window_values /* masks */ + ); + + /* Create black (foreground) graphic context */ + xcb_gcontext_t gc = xcb_generate_id( connection ); + uint32_t const gc_mask = XCB_GC_FOREGROUND | XCB_GC_GRAPHICS_EXPOSURES; + uint32_t const gc_values[] = {screen->black_pixel, 0}; + xcb_create_gc(connection, gc, window, gc_mask, gc_values); + + /* Map the window on the screen and flush*/ + xcb_map_window(connection, window); + xcb_flush(connection); + + /* Event loop */ + unsigned counter = 0; + for( xcb_generic_event_t *event + ; (event = xcb_wait_for_event(connection)) + ; free(event) + ){ + switch( event->response_type & ~0x80 ){ + case XCB_EXPOSE: + generate_image(shmimg, counter++); + xcb_shm_put_image(connection, window, gc, + shmimg->image->width, shmimg->image->height, 0, 0, + shmimg->image->width, shmimg->image->height, 0, 0, + shmimg->image->depth, shmimg->image->format, 0, + shmimg->shm_seg, 0); + + /* flush the request */ + xcb_flush(connection); + break; + default: + /* Unknown event type, ignore it */ + break; + } + + } + + shm_xcb_image_destroy(shmimg); + + return 0; +} -- cgit v1.2.3