From 5f280e26b131fd5f2b569ce0ff48a2b9cfa9b128 Mon Sep 17 00:00:00 2001 From: Wolfgang Draxinger Date: Tue, 2 Aug 2016 16:39:18 +0200 Subject: xcb --- samples/OpenGL/x11argb_opengl/Makefile | 2 +- samples/OpenGL/x11argb_opengl/x11argb_opengl.c | 3 +- .../x11argb_opengl_glsl/x11argb_opengl_glsl.c | 36 +++- samples/OpenGL/x11xcb_opengl/x11xcb_opengl.c | 238 +++++++++++++++++++++ 4 files changed, 271 insertions(+), 8 deletions(-) create mode 100644 samples/OpenGL/x11xcb_opengl/x11xcb_opengl.c diff --git a/samples/OpenGL/x11argb_opengl/Makefile b/samples/OpenGL/x11argb_opengl/Makefile index abafd5c..5b35c1b 100644 --- a/samples/OpenGL/x11argb_opengl/Makefile +++ b/samples/OpenGL/x11argb_opengl/Makefile @@ -1,3 +1,3 @@ x11argb_opengl: x11argb_opengl.c Makefile - $(CC) -std=c99 -g3 -o x11argb_opengl -DUSE_GLX_CREATE_CONTEXT_ATTRIB=1 x11argb_opengl.c -lX11 -lXrender -lGL -lm + $(CC) -std=c99 -g3 -o x11argb_opengl -DUSE_GLX_CREATE_CONTEXT_ATTRIB=1 -DUSE_GLX_CREATE_WINDOW=1 x11argb_opengl.c -lX11 -lXrender -lGL -lm diff --git a/samples/OpenGL/x11argb_opengl/x11argb_opengl.c b/samples/OpenGL/x11argb_opengl/x11argb_opengl.c index 092c202..bf470b6 100644 --- a/samples/OpenGL/x11argb_opengl/x11argb_opengl.c +++ b/samples/OpenGL/x11argb_opengl/x11argb_opengl.c @@ -210,6 +210,7 @@ static void createTheWindow() } #if USE_GLX_CREATE_WINDOW + fputs("glXCreateWindow ", stderr); int glXattr[] = { None }; glX_window_handle = glXCreateWindow(Xdisplay, fbconfig, window_handle, glXattr); if( !glX_window_handle ) { @@ -471,7 +472,7 @@ static void redrawTheWindow() glXSwapBuffers(Xdisplay, glX_window_handle); clock_gettime(CLOCK_MONOTONIC_RAW, &Tb); - fprintf(stderr, "glXSwapBuffers returned after %f ms\n", 1e3*((double)Tb.tv_sec + 1e-6*(double)Tb.tv_nsec) - 1e3*((double)Ta.tv_sec + 1e-6*(double)Ta.tv_nsec)); + // fprintf(stderr, "glXSwapBuffers returned after %f ms\n", 1e3*((double)Tb.tv_sec + 1e-6*(double)Tb.tv_nsec) - 1e3*((double)Ta.tv_sec + 1e-6*(double)Ta.tv_nsec)); } int main(int argc, char *argv[]) diff --git a/samples/OpenGL/x11argb_opengl_glsl/x11argb_opengl_glsl.c b/samples/OpenGL/x11argb_opengl_glsl/x11argb_opengl_glsl.c index 7aae5a8..2813e11 100644 --- a/samples/OpenGL/x11argb_opengl_glsl/x11argb_opengl_glsl.c +++ b/samples/OpenGL/x11argb_opengl_glsl/x11argb_opengl_glsl.c @@ -26,6 +26,7 @@ #define _GNU_SOURCE +#include #include #include #include @@ -41,8 +42,8 @@ #include #include -#define USE_CHOOSE_FBCONFIG -#define USE_GLX_CREATE_WINDOW +#define USE_GLX_CREATE_WINDOW 1 +#define USE_DOUBLEBUFFER 1 static const GLchar *vertex_shader_source = "#version 120\n" @@ -182,7 +183,11 @@ static int width, height; static int VisData[] = { GLX_RENDER_TYPE, GLX_RGBA_BIT, GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, +#if USE_DOUBLEBUFFER GLX_DOUBLEBUFFER, True, +#else +GLX_DOUBLEBUFFER, False, +#endif GLX_RED_SIZE, 8, GLX_GREEN_SIZE, 8, GLX_BLUE_SIZE, 8, @@ -296,7 +301,7 @@ static void createTheWindow() fatalError("Couldn't create the window\n"); } -#ifdef USE_GLX_CREATE_WINDOW +#if USE_GLX_CREATE_WINDOW int glXattr[] = { None }; glX_window_handle = glXCreateWindow(Xdisplay, fbconfig, window_handle, glXattr); if( !glX_window_handle ) { @@ -578,8 +583,12 @@ static void redrawTheWindow(double T) struct timespec Ta, Tb; +#if USE_DOUBLEBUFFER glXSwapBuffers(Xdisplay, glX_window_handle); - glXWaitGL(); +#else + glFlush(); + usleep(10000); +#endif } static double getftime(void) { @@ -608,8 +617,23 @@ int main(int argc, char *argv[]) if( !init_resources() ) return -1; - while (updateTheMessageQueue()) { - redrawTheWindow(getftime()); + int n_dT_accum = 0; + float dT_accum = 0; + while( updateTheMessageQueue() ) { + float const dT = getftime(); + redrawTheWindow(dT); + + dT_accum += dT; + ++n_dT_accum; + + if( 100 < n_dT_accum ) { + fprintf(stderr, "%d frames in %fs (~%fFPS)\n", + n_dT_accum, + dT_accum, + (float)n_dT_accum / dT_accum); + dT_accum = 0.f; + n_dT_accum = 0; + } } return 0; diff --git a/samples/OpenGL/x11xcb_opengl/x11xcb_opengl.c b/samples/OpenGL/x11xcb_opengl/x11xcb_opengl.c new file mode 100644 index 0000000..e1fc3c3 --- /dev/null +++ b/samples/OpenGL/x11xcb_opengl/x11xcb_opengl.c @@ -0,0 +1,238 @@ +#include +#include +#include + +#include + +/* +If you get linking errors when using C++, you need +to add extern "C" here or in X11-xcb.h, unless +this bug is already fixed in your version: +http://bugs.freedesktop.org/show_bug.cgi?id=22252 +*/ +#include /* for XGetXCBConnection, link with libX11-xcb */ + +#include + +#include +#include + +static +void draw() +{ + glClearColor(0.2, 0.4, 0.9, 1.0); + glClear(GL_COLOR_BUFFER_BIT); +} + +static +int main_loop( + Display *display, + xcb_connection_t *connection, + xcb_window_t window, + GLXDrawable drawable ) +{ + int running = 1; + while(running) { + /* Wait for event */ + xcb_generic_event_t *event = xcb_wait_for_event(connection); + if( !event ) { + fprintf(stderr, "i/o error in xcb_wait_for_event"); + return -1; + } + + switch(event->response_type & ~0x80) { + case XCB_KEY_PRESS: + /* Quit on key press */ + running = 0; + break; + + case XCB_EXPOSE: + /* Handle expose event, draw and swap buffers */ + draw(); + glXSwapBuffers(display, drawable); + break; + + default: + break; + } + + free(event); + } + + return 0; +} + +static +int setup_and_run( + Display* display, + xcb_connection_t *connection, + int default_screen, + xcb_screen_t *screen ) +{ + xcb_generic_error_t *error; + + /* Query framebuffer configurations */ + int num_fb_configs = 0; + GLXFBConfig * const fb_configs = glXGetFBConfigs(display, default_screen, &num_fb_configs); + if( !fb_configs || !num_fb_configs ){ + fprintf(stderr, "glXGetFBConfigs failed\n"); + return -1; + } + + GLXFBConfig fb_config; + int visualID = 0; + for(int i = 0; !visualID && i < num_fb_configs; ++i) { + /* Select first framebuffer config with a valid visual and query visualID */ + fb_config = fb_configs[i]; + XVisualInfo * const visual = glXGetVisualFromFBConfig(display, fb_config); + if( !visual ) { continue; } + visualID = visual->visualid; + } + if( !visualID ) { + return -1; + } + + /* Create OpenGL context */ + GLXContext const context = glXCreateNewContext(display, fb_config, GLX_RGBA_TYPE, 0, True); + if( !context ) { + fprintf(stderr, "glXCreateNewContext failed\n"); + return -1; + } + + /* Create XID's for colormap and window */ + xcb_colormap_t colormap = xcb_generate_id(connection); + xcb_window_t window = xcb_generate_id(connection); + + /* Create colormap */ + if((error = xcb_request_check(connection, xcb_create_colormap_checked( + connection, + XCB_COLORMAP_ALLOC_NONE, + colormap, + screen->root, + visualID) + ) + )){ + fprintf(stderr, "error creating colormap: %d\n", error->error_code); + free(error); + return -1; + } + + /* Create window */ + uint32_t const eventmask = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_KEY_PRESS; + uint32_t const valuelist[] = { eventmask, colormap }; + uint32_t const valuemask = XCB_CW_EVENT_MASK | XCB_CW_COLORMAP; + + if((error= xcb_request_check(connection, xcb_create_window_checked( + connection, + XCB_COPY_FROM_PARENT, + window, + screen->root, + 0, 0, + 150, 150, + 0, + XCB_WINDOW_CLASS_INPUT_OUTPUT, + visualID, + valuemask, + valuelist) + ) + )){ + fprintf(stderr, "error creating window: %d\n", error->error_code); + return -1; + } + + // NOTE: window must be mapped before glXMakeContextCurrent + if((error= xcb_request_check(connection, xcb_map_window(connection, window)) )) { + fprintf(stderr, "error mapping window"); + return -1; + } + + /* Create GLX Window */ + GLXDrawable drawable = 0; + + GLXWindow glxwindow = glXCreateWindow(display, fb_config, window, 0); + if( !window ) { + xcb_destroy_window(connection, window); + glXDestroyContext(display, context); + + fprintf(stderr, "glXDestroyContext failed\n"); + return -1; + } + + drawable = glxwindow; + + /* make OpenGL context current */ + if( !glXMakeContextCurrent(display, drawable, drawable, context) ) { + xcb_destroy_window(connection, window); + glXDestroyContext(display, context); + + fprintf(stderr, "glXMakeContextCurrent failed\n"); + return -1; + } + + /* run main loop */ + int retval = main_loop(display, connection, window, drawable); + + /* Cleanup */ + glXDestroyWindow(display, glxwindow); + xcb_destroy_window(connection, window); + glXDestroyContext(display, context); + + return retval; +} + +static +void screen_from_Xlib_Display( + Display * const display, + xcb_connection_t *connection, + int * const out_screen_num, + xcb_screen_t ** const out_screen) +{ + xcb_screen_iterator_t screen_iter = xcb_setup_roots_iterator(xcb_get_setup(connection)); + int screen_num = DefaultScreen(display); + while( screen_iter.rem && screen_num > 0 ) { + xcb_screen_next(&screen_iter); + --screen_num; + } + *out_screen_num = screen_num; + *out_screen = screen_iter.data; +} + +int main(int argc, char* argv[]) +{ + Display *display; + + /* Open Xlib Display */ + display = XOpenDisplay(0); + if( !display ) { + fprintf(stderr, "Can't open display\n"); + return -1; + } + + + /* Get the XCB connection from the display */ + xcb_connection_t *connection = XGetXCBConnection(display); + if( !connection ) { + XCloseDisplay(display); + fprintf(stderr, "Can't get xcb connection from display\n"); + return -1; + } + + /* Acquire event queue ownership */ + XSetEventQueueOwner(display, XCBOwnsEventQueue); + + /* Find XCB screen */ + int screen_num; + xcb_screen_t *screen = 0; + screen_from_Xlib_Display(display, connection, &screen_num, &screen); + if( !screen ) { + return -1; + } + + /* Initialize window and OpenGL context, run main loop and deinitialize */ + int retval = setup_and_run(display, connection, screen_num, screen); + + /* Cleanup */ + XCloseDisplay(display); + + return retval; +} -- cgit v1.2.3