extern struct gl_platform *gl_platform_create(gs_device_t *device, uint32_t adapter) { /* There's some trickery here... we're mixing libX11, xcb, and GLX For an explanation see here: http://xcb.freedesktop.org/MixingCalls/ Essentially, GLX requires Xlib. Everything else we use xcb. */ struct gl_platform * plat = bmalloc(sizeof(struct gl_platform)); Display * display = open_windowless_display(); if (!display) { goto fail_display_open; } XSetEventQueueOwner(display, XCBOwnsEventQueue); XSetErrorHandler(x_error_handler); /* We assume later that cur_swap is already set. */ device->plat = plat; plat->display = display; if (!gl_context_create(plat)) { blog(LOG_ERROR, "Failed to create context!"); goto fail_context_create; } if (!glXMakeContextCurrent(plat->display, plat->pbuffer, plat->pbuffer, plat->context)) { blog(LOG_ERROR, "Failed to make context current."); goto fail_make_current; } if (!gladLoadGL()) { blog(LOG_ERROR, "Failed to load OpenGL entry functions."); goto fail_load_gl; } blog(LOG_INFO, "OpenGL version: %s\n", glGetString(GL_VERSION)); goto success; fail_make_current: gl_context_destroy(plat); fail_context_create: fail_load_gl: XCloseDisplay(display); fail_display_open: bfree(plat); plat = NULL; success: UNUSED_PARAMETER(adapter); return plat; }
Handle gl_context_create( Handle widget, GLRequest * request) { int attr_list[64], *attr = attr_list; XVisualInfo * visual; GLXContext context; Context * ret; if ( pguts == NULL ) pguts = (UnixGuts*) apc_system_action("unix_guts"); CLEAR_ERROR; XCHECKPOINT; #define ATTR(in,out) \ if ( request-> in) { \ *(attr++) = out; \ *(attr++) = request-> in; \ } *(attr++) = GLX_USE_GL; if ( request-> pixels == GLREQ_PIXEL_RGBA) *(attr++) = GLX_RGBA; if ( request-> double_buffer == GLREQ_TRUE) *(attr++) = GLX_DOUBLEBUFFER; if ( request-> stereo == GLREQ_TRUE) *(attr++) = GLX_STEREO; ATTR( layer , GLX_LEVEL ) ATTR( color_bits , GLX_BUFFER_SIZE ) ATTR( aux_buffers , GLX_AUX_BUFFERS ) ATTR( red_bits , GLX_RED_SIZE ) ATTR( green_bits , GLX_GREEN_SIZE ) ATTR( blue_bits , GLX_BLUE_SIZE ) ATTR( alpha_bits , GLX_ALPHA_SIZE ) ATTR( depth_bits , GLX_DEPTH_SIZE ) ATTR( stencil_bits , GLX_STENCIL_SIZE ) ATTR( accum_red_bits , GLX_ACCUM_RED_SIZE ) ATTR( accum_green_bits, GLX_ACCUM_GREEN_SIZE ) ATTR( accum_blue_bits , GLX_ACCUM_BLUE_SIZE ) ATTR( accum_alpha_bits, GLX_ACCUM_ALPHA_SIZE ) *(attr++) = 0; if ( request-> target == GLREQ_TARGET_WINDOW && sys-> flags. layered) { visual = sys-> visual; } else if ( !( visual = glXChooseVisual( DISP, SCREEN, attr_list ))) { if ( request-> pixels != GLREQ_PIXEL_RGBA) { /* emulate win32 which does it softly, i.e. if RGBA fails, it proposes PALETTED */ request-> pixels = GLREQ_PIXEL_RGBA; return gl_context_create( widget, request); } if ( request-> double_buffer == GLREQ_DONTCARE) { request-> double_buffer = GLREQ_TRUE; return gl_context_create( widget, request ); } SET_ERROR( ERROR_CHOOSE_VISUAL ); return (Handle) 0; } XCHECKPOINT; if ( !( context = glXCreateContext( DISP, visual, 0, request-> render != GLREQ_RENDER_XSERVER))) { SET_ERROR( ERROR_CREATE_CONTEXT ); return (Handle) 0; } ret = malloc( sizeof( Context )); memset( ret, 0, sizeof( Context)); ret-> context = context; switch ( request-> target) { case GLREQ_TARGET_WINDOW: ret-> drawable = var-> handle; break; case GLREQ_TARGET_APPLICATION: /* doesn't work with gnome and kde anyway */ ret-> drawable = RootWindow( DISP, SCREEN); break; case GLREQ_TARGET_BITMAP: case GLREQ_TARGET_IMAGE: { GLXContext old_context; GLXDrawable old_drawable; Bool success; XCHECKPOINT; ret-> drawable = glXCreateGLXPixmap( DISP, visual, sys-> gdrawable); ret-> pixmap = 1; /* check if pixmaps are supported on this visual at all */ old_context = glXGetCurrentContext(); old_drawable = glXGetCurrentDrawable(); success = glXMakeCurrent( DISP, ret-> drawable, ret-> context); glXMakeCurrent( DISP, old_drawable, old_context); if ( !success ) { SET_ERROR( ERROR_NO_PIXMAPS ); glXDestroyGLXPixmap( DISP, ret-> drawable); glXDestroyContext( DISP, ret-> context ); free(ret); return 0; } break; } case GLREQ_TARGET_PRINTER: SET_ERROR(ERROR_NO_PRINTER); free(ret); return 0; } return (Handle) ret; }
extern struct gl_platform *gl_platform_create(gs_device_t *device, const struct gs_init_data *info) { /* There's some trickery here... we're mixing libX11, xcb, and GLX For an explanation see here: http://xcb.freedesktop.org/MixingCalls/ Essentially, GLX requires Xlib. Everything else we use xcb. */ struct gl_windowinfo *wi = gl_windowinfo_create(info); struct gl_platform * plat = bmalloc(sizeof(struct gl_platform)); Display * display; print_info_stuff(info); if (!wi) { blog(LOG_ERROR, "Failed to create window info!"); goto fail_wi_create; } display = XOpenDisplay(XDisplayString(info->window.display)); if (!display) { blog(LOG_ERROR, "Unable to open new X connection!"); goto fail_display_open; } XSetEventQueueOwner(display, XCBOwnsEventQueue); XSetErrorHandler(x_error_handler); /* We assume later that cur_swap is already set. */ device->cur_swap = &plat->swap; device->plat = plat; plat->display = display; plat->swap.device = device; plat->swap.info = *info; plat->swap.wi = wi; if (!gl_platform_init_swapchain(&plat->swap)) { blog(LOG_ERROR, "Failed to initialize swap chain!"); goto fail_init_swapchain; } if (!gl_context_create(plat)) { blog(LOG_ERROR, "Failed to create context!"); goto fail_context_create; } if (!glXMakeCurrent(plat->display, wi->window, plat->context)) { blog(LOG_ERROR, "Failed to make context current."); goto fail_make_current; } if (!gladLoadGL()) { blog(LOG_ERROR, "Failed to load OpenGL entry functions."); goto fail_load_gl; } blog(LOG_INFO, "OpenGL version: %s\n", glGetString(GL_VERSION)); goto success; fail_make_current: gl_context_destroy(plat); fail_context_create: fail_load_gl: fail_init_swapchain: XCloseDisplay(display); fail_display_open: fail_wi_create: gl_windowinfo_destroy(wi); free(plat); plat = NULL; success: return plat; }
static sgui_context* gl_context_create_share( sgui_context* super ) { sgui_context_gl* this = (sgui_context_gl*)super; return gl_context_create( this->wnd, this->wnd->backend, super ); }