XVisualInfo *qglx_findVisualInfo(Display *display, int screen, const QPlatformWindowFormat &format) { GLXFBConfig config = qglx_findConfig(display,screen,format); XVisualInfo *visualInfo = glXGetVisualFromFBConfig(display,config); return visualInfo; }
static bool gfx_ctx_set_video_mode(void *data, unsigned width, unsigned height, bool fullscreen) { struct sigaction sa = {{0}}; sa.sa_handler = sighandler; sa.sa_flags = SA_RESTART; sigemptyset(&sa.sa_mask); sigaction(SIGINT, &sa, NULL); sigaction(SIGTERM, &sa, NULL); int x_off = 0; int y_off = 0; bool windowed_full = g_settings.video.windowed_fullscreen; bool true_full = false; int (*old_handler)(Display*, XErrorEvent*) = NULL; XSetWindowAttributes swa = {0}; XVisualInfo *vi = glXGetVisualFromFBConfig(g_dpy, g_fbc); if (!vi) goto error; swa.colormap = g_cmap = XCreateColormap(g_dpy, RootWindow(g_dpy, vi->screen), vi->visual, AllocNone); swa.event_mask = StructureNotifyMask | KeyPressMask | KeyReleaseMask; swa.override_redirect = fullscreen ? True : False; if (fullscreen && !windowed_full) { if (x11_enter_fullscreen(g_dpy, width, height, &g_desktop_mode)) { g_should_reset_mode = true; true_full = true; } else RARCH_ERR("[GLX]: Entering true fullscreen failed. Will attempt windowed mode.\n"); } if (g_settings.video.monitor_index) g_screen = g_settings.video.monitor_index - 1; #ifdef HAVE_XINERAMA if (fullscreen || g_screen != 0) { unsigned new_width = width; unsigned new_height = height; if (x11_get_xinerama_coord(g_dpy, g_screen, &x_off, &y_off, &new_width, &new_height)) RARCH_LOG("[GLX]: Using Xinerama on screen #%u.\n", g_screen); else RARCH_LOG("[GLX]: Xinerama is not active on screen.\n"); if (fullscreen) { width = new_width; height = new_height; } } #endif RARCH_LOG("[GLX]: X = %d, Y = %d, W = %u, H = %u.\n", x_off, y_off, width, height); g_win = XCreateWindow(g_dpy, RootWindow(g_dpy, vi->screen), x_off, y_off, width, height, 0, vi->depth, InputOutput, vi->visual, CWBorderPixel | CWColormap | CWEventMask | (true_full ? CWOverrideRedirect : 0), &swa); XSetWindowBackground(g_dpy, g_win, 0); g_glx_win = glXCreateWindow(g_dpy, g_fbc, g_win, 0); x11_set_window_attr(g_dpy, g_win); if (fullscreen) x11_show_mouse(g_dpy, g_win, false); if (true_full) { RARCH_LOG("[GLX]: Using true fullscreen.\n"); XMapRaised(g_dpy, g_win); } else if (fullscreen) // We attempted true fullscreen, but failed. Attempt using windowed fullscreen. { XMapRaised(g_dpy, g_win); RARCH_LOG("[GLX]: Using windowed fullscreen.\n"); // We have to move the window to the screen we want to go fullscreen on first. // x_off and y_off usually get ignored in XCreateWindow(). x11_move_window(g_dpy, g_win, x_off, y_off, width, height); x11_windowed_fullscreen(g_dpy, g_win); } else { XMapWindow(g_dpy, g_win); // If we want to map the window on a different screen, we'll have to do it by force. // Otherwise, we should try to let the window manager sort it out. // x_off and y_off usually get ignored in XCreateWindow(). if (g_screen) x11_move_window(g_dpy, g_win, x_off, y_off, width, height); } XEvent event; XIfEvent(g_dpy, &event, glx_wait_notify, NULL); if (!g_ctx) { if (g_core || g_debug) { int attribs[16]; int *aptr = attribs; if (g_core) { *aptr++ = GLX_CONTEXT_MAJOR_VERSION_ARB; *aptr++ = g_major; *aptr++ = GLX_CONTEXT_MINOR_VERSION_ARB; *aptr++ = g_minor; // Technically, we don't have core/compat until 3.2. // Version 3.1 is either compat or not depending on GL_ARB_compatibility. if ((g_major * 1000 + g_minor) >= 3002) { *aptr++ = GLX_CONTEXT_PROFILE_MASK_ARB; *aptr++ = GLX_CONTEXT_CORE_PROFILE_BIT_ARB; } } if (g_debug) { *aptr++ = GLX_CONTEXT_FLAGS_ARB; *aptr++ = GLX_CONTEXT_DEBUG_BIT_ARB; } *aptr = None; g_ctx = glx_create_context_attribs(g_dpy, g_fbc, NULL, True, attribs); if (g_use_hw_ctx) { RARCH_LOG("[GLX]: Creating shared HW context.\n"); g_hw_ctx = glx_create_context_attribs(g_dpy, g_fbc, g_ctx, True, attribs); if (!g_hw_ctx) RARCH_ERR("[GLX]: Failed to create new shared context.\n"); } } else { g_ctx = glXCreateNewContext(g_dpy, g_fbc, GLX_RGBA_TYPE, 0, True); if (g_use_hw_ctx) { g_hw_ctx = glXCreateNewContext(g_dpy, g_fbc, GLX_RGBA_TYPE, g_ctx, True); if (!g_hw_ctx) RARCH_ERR("[GLX]: Failed to create new shared context.\n"); } } if (!g_ctx) { RARCH_ERR("[GLX]: Failed to create new context.\n"); goto error; } } else { driver.video_cache_context_ack = true; RARCH_LOG("[GLX]: Using cached GL context.\n"); } glXMakeContextCurrent(g_dpy, g_glx_win, g_glx_win, g_ctx); XSync(g_dpy, False); g_quit_atom = XInternAtom(g_dpy, "WM_DELETE_WINDOW", False); if (g_quit_atom) XSetWMProtocols(g_dpy, g_win, &g_quit_atom, 1); int val; glXGetConfig(g_dpy, vi, GLX_DOUBLEBUFFER, &val); g_is_double = val; if (g_is_double) { const char *swap_func = NULL; g_pglSwapIntervalEXT = (void (*)(Display*, GLXDrawable, int))glXGetProcAddress((const GLubyte*)"glXSwapIntervalEXT"); g_pglSwapInterval = (int (*)(int))glXGetProcAddress((const GLubyte*)"glXSwapIntervalMESA"); if (g_pglSwapIntervalEXT) swap_func = "glXSwapIntervalEXT"; else if (g_pglSwapInterval) swap_func = "glXSwapIntervalMESA"; if (!g_pglSwapInterval && !g_pglSwapIntervalEXT) RARCH_WARN("[GLX]: Cannot find swap interval call.\n"); else RARCH_LOG("[GLX]: Found swap function: %s.\n", swap_func); } else RARCH_WARN("[GLX]: Context is not double buffered!.\n"); gfx_ctx_swap_interval(data, g_interval); // This can blow up on some drivers. It's not fatal, so override errors for this call. old_handler = XSetErrorHandler(nul_handler); XSetInputFocus(g_dpy, g_win, RevertToNone, CurrentTime); XSync(g_dpy, False); XSetErrorHandler(old_handler); XFree(vi); g_has_focus = true; g_inited = true; if (!x11_create_input_context(g_dpy, g_win, &g_xim, &g_xic)) goto error; driver.display_type = RARCH_DISPLAY_X11; driver.video_display = (uintptr_t)g_dpy; driver.video_window = (uintptr_t)g_win; g_true_full = true_full; return true; error: if (vi) XFree(vi); gfx_ctx_destroy(data); return false; }
void GetXVisual( XVisualInfo** vi ) { // -- Check the GLX version, 1.3+ added FBConfigs if ( ( x11::glx[0] == 1 && x11::glx[1] < 3 ) || ( x11::glx[0] < 1 ) ) { GLint att[] = { GLX_RGBA, GLX_DOUBLEBUFFER, GLX_RED_SIZE, 8, GLX_GREEN_SIZE, 8, GLX_BLUE_SIZE, 8, GLX_DEPTH_SIZE, 24, None }; if( (*vi = glXChooseVisual( x11::disp, 0, att )) == NULL ) { printf( "Failed to get a legacy XVisualInfo!\n" ); exit( EXIT_FAILURE ); } } else { // -- Make an FBConfig attribute list int visual_attribs[] = { GLX_X_RENDERABLE , True, GLX_DRAWABLE_TYPE , GLX_WINDOW_BIT, GLX_RENDER_TYPE , GLX_RGBA_BIT, GLX_X_VISUAL_TYPE , GLX_TRUE_COLOR, GLX_RED_SIZE , 8, GLX_GREEN_SIZE , 8, GLX_BLUE_SIZE , 8, GLX_DEPTH_SIZE , 24, GLX_DOUBLEBUFFER , True, // -- MSAA //GLX_SAMPLE_BUFFERS , 1, //GLX_SAMPLES , 4, None }; // -- Get a list of matching FrameBuffer Configs int fbcount; GLXFBConfig *fbc = glXChooseFBConfig( x11::disp, DefaultScreen( x11::disp ), visual_attribs, &fbcount ); if ( !fbc ) { printf( "Failed to retrieve a framebuffer config\n" ); exit( EXIT_FAILURE ); } x11::fbconfig = fbc[0]; XFree( fbc ); // -- Get the VisualInfo associated with this Config if ( (*vi = glXGetVisualFromFBConfig( x11::disp, x11::fbconfig )) == 0 ) { printf( "Failed to get the XVisual from the FBConfig!\n" ); exit( EXIT_FAILURE ); } } }
static void make_window( Display *dpy, const char *name, int x, int y, int width, int height, Window *winRet, GLXContext *ctxRet) { int scrnum; XSetWindowAttributes attr; unsigned long mask; Window root; Window win; GLXContext ctx; XVisualInfo *visinfo; scrnum = DefaultScreen( dpy ); root = RootWindow( dpy, scrnum ); // 3.2 support //#ifdef glXCreateContextAttribsARB if (gContextVersionMajor > 2) { // We asked for OpenGL3+, but can we do it? typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*); // Verify GL driver supports glXCreateContextAttribsARB() glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0; // Verify that GLX implementation supports the new context create call if ( strstr( glXQueryExtensionsString( dpy, scrnum ), "GLX_ARB_create_context" ) != 0 ) glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc) glXGetProcAddress( (const GLubyte *) "glXCreateContextAttribsARB" ); if ( !glXCreateContextAttribsARB ) { printf( "Can't create new-style GL context\n" ); } // We need this for OpenGL3 int elemc; GLXFBConfig *fbcfg; int attribs[] = { GLX_RENDER_TYPE, GLX_RGBA_BIT, GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, // ? GLX_RED_SIZE, 1, // 1 = prefer high precision GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1, GLX_ALPHA_SIZE, 1, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None }; int i = 12; if (gMode & GLUT_DOUBLE) { attribs[i++] = GLX_DOUBLEBUFFER; attribs[i++] = 1; } if (gMode & GLUT_DEPTH) { attribs[i++] = GLX_DEPTH_SIZE; attribs[i++] = 1; } if (gMode & GLUT_STENCIL) { attribs[i++] = GLX_STENCIL_SIZE; attribs[i++] = 8; // Smallest available, at least 8. Configurable setting needed! } if (gMode & GLUT_MULTISAMPLE) { attribs[i++] = GLX_SAMPLE_BUFFERS; attribs[i++] = 1; attribs[i++] = GLX_SAMPLES; attribs[i++] = 4; } fbcfg = glXChooseFBConfig(dpy, scrnum, attribs, &elemc); if (!fbcfg) { fbcfg = glXChooseFBConfig(dpy, scrnum, NULL, &elemc); } if (!fbcfg) printf("Couldn't get FB configs\n"); int gl3attr[] = { GLX_CONTEXT_MAJOR_VERSION_ARB, gContextVersionMajor, GLX_CONTEXT_MINOR_VERSION_ARB, gContextVersionMinor, // GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_DEBUG_BIT_ARB, GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, None }; ctx = glXCreateContextAttribsARB(dpy, fbcfg[0], NULL, 1, gl3attr); if (ctx == NULL) printf("No ctx!\n"); visinfo = glXGetVisualFromFBConfig(dpy, fbcfg[0]); if (!visinfo) printf("Error: couldn't create OpenGL window with this pixel format.\n"); } else // old style //#endif { int attribs[] = { GLX_RGBA, GLX_RED_SIZE, 1, // 1 = prefer high precision GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None }; int i = 7; if (gMode & GLUT_DOUBLE) attribs[i++] = GLX_DOUBLEBUFFER; if (gMode & GLUT_DEPTH) { attribs[i++] = GLX_DEPTH_SIZE; attribs[i++] = 1; } if (gMode & GLUT_STENCIL) { attribs[i++] = GLX_STENCIL_SIZE; attribs[i++] = 8; // Smallest available, at least 8. Configurable setting needed! } visinfo = glXChooseVisual( dpy, scrnum, attribs ); if (!visinfo) { printf("Error: couldn't get a visual according to settings\n"); exit(1); } ctx = glXCreateContext( dpy, visinfo, 0, True ); if (ctx == NULL) printf("No ctx!\n"); } /* window attributes */ attr.background_pixel = 0; attr.border_pixel = 0; attr.colormap = XCreateColormap( dpy, root, visinfo->visual, AllocNone); attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPress | ButtonReleaseMask | Button1MotionMask | PointerMotionMask; attr.override_redirect = 0; mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect; win = XCreateWindow( dpy, root, x, y, width, height, 0, visinfo->depth, InputOutput, visinfo->visual, mask, &attr ); // Register delete! wmDeleteMessage = XInternAtom(dpy, "WM_DELETE_WINDOW", False); XSetWMProtocols(dpy, win, &wmDeleteMessage, 1); // Register /* set hints and properties */ XSizeHints sizehints; sizehints.x = x; sizehints.y = y; sizehints.width = width; sizehints.height = height; sizehints.flags = USSize | USPosition; XSetNormalHints(dpy, win, &sizehints); XSetStandardProperties(dpy, win, name, name, None, (char **)NULL, 0, &sizehints); if (!ctx) { printf("Error: glXCreateContext failed\n"); exit(1); } XFree(visinfo); *winRet = win; *ctxRet = ctx; }
static int createContext(_GLFWwindow* window, const _GLFWwndconfig* wndconfig, GLXFBConfigID fbconfigID) { int attribs[40]; GLXFBConfig* fbconfig; GLXContext share = NULL; if (wndconfig->share) share = wndconfig->share->GLX.context; // Retrieve the previously selected GLXFBConfig { int dummy, index = 0; setGLXattrib(GLX_FBCONFIG_ID, (int) fbconfigID); setGLXattrib(None, None); if (_glfwLibrary.GLX.SGIX_fbconfig) { fbconfig = _glfwLibrary.GLX.ChooseFBConfigSGIX(_glfwLibrary.X11.display, _glfwLibrary.X11.screen, attribs, &dummy); } else { fbconfig = glXChooseFBConfig(_glfwLibrary.X11.display, _glfwLibrary.X11.screen, attribs, &dummy); } if (fbconfig == NULL) { _glfwSetError(GLFW_PLATFORM_ERROR, "GLX: Failed to retrieve the selected GLXFBConfig"); return GL_FALSE; } } // Retrieve the corresponding visual if (_glfwLibrary.GLX.SGIX_fbconfig) { window->GLX.visual = _glfwLibrary.GLX.GetVisualFromFBConfigSGIX(_glfwLibrary.X11.display, *fbconfig); } else { window->GLX.visual = glXGetVisualFromFBConfig(_glfwLibrary.X11.display, *fbconfig); } if (window->GLX.visual == NULL) { XFree(fbconfig); _glfwSetError(GLFW_PLATFORM_ERROR, "GLX: Failed to retrieve visual for GLXFBConfig"); return GL_FALSE; } if (wndconfig->clientAPI == GLFW_OPENGL_ES_API) { if (!_glfwLibrary.GLX.ARB_create_context || !_glfwLibrary.GLX.ARB_create_context_profile || !_glfwLibrary.GLX.EXT_create_context_es2_profile) { _glfwSetError(GLFW_VERSION_UNAVAILABLE, "GLX: OpenGL ES requested but " "GLX_EXT_create_context_es2_profile is unavailable"); return GL_FALSE; } } if (wndconfig->glForward) { if (!_glfwLibrary.GLX.ARB_create_context) { _glfwSetError(GLFW_VERSION_UNAVAILABLE, "GLX: Forward compatibility requested but " "GLX_ARB_create_context_profile is unavailable"); return GL_FALSE; } } if (wndconfig->glProfile) { if (!_glfwLibrary.GLX.ARB_create_context || !_glfwLibrary.GLX.ARB_create_context_profile) { _glfwSetError(GLFW_VERSION_UNAVAILABLE, "GLX: An OpenGL profile requested but " "GLX_ARB_create_context_profile is unavailable"); return GL_FALSE; } } if (_glfwLibrary.GLX.ARB_create_context) { int index = 0, mask = 0, flags = 0, strategy = 0; if (wndconfig->clientAPI == GLFW_OPENGL_API) { if (wndconfig->glForward) flags |= GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB; if (wndconfig->glDebug) flags |= GLX_CONTEXT_DEBUG_BIT_ARB; if (wndconfig->glProfile) { if (wndconfig->glProfile == GLFW_OPENGL_CORE_PROFILE) mask |= GLX_CONTEXT_CORE_PROFILE_BIT_ARB; else if (wndconfig->glProfile == GLFW_OPENGL_COMPAT_PROFILE) mask |= GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; } } else mask |= GLX_CONTEXT_ES2_PROFILE_BIT_EXT; if (wndconfig->glRobustness != GLFW_NO_ROBUSTNESS) { if (_glfwLibrary.GLX.ARB_create_context_robustness) { if (wndconfig->glRobustness == GLFW_NO_RESET_NOTIFICATION) strategy = GLX_NO_RESET_NOTIFICATION_ARB; else if (wndconfig->glRobustness == GLFW_LOSE_CONTEXT_ON_RESET) strategy = GLX_LOSE_CONTEXT_ON_RESET_ARB; flags |= GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB; } } if (wndconfig->glMajor != 1 || wndconfig->glMinor != 0) { // NOTE: Only request an explicitly versioned context when // necessary, as explicitly requesting version 1.0 does not always // return the highest available version setGLXattrib(GLX_CONTEXT_MAJOR_VERSION_ARB, wndconfig->glMajor); setGLXattrib(GLX_CONTEXT_MINOR_VERSION_ARB, wndconfig->glMinor); } if (mask) setGLXattrib(GLX_CONTEXT_PROFILE_MASK_ARB, mask); if (flags) setGLXattrib(GLX_CONTEXT_FLAGS_ARB, flags); if (strategy) setGLXattrib(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, strategy); setGLXattrib(None, None); // This is the only place we set an Xlib error handler, and we only do // it because glXCreateContextAttribsARB generates a BadMatch error if // the requested OpenGL version is unavailable (instead of a civilized // response like returning NULL) _glfwErrorCode = Success; XSetErrorHandler(errorHandler); window->GLX.context = _glfwLibrary.GLX.CreateContextAttribsARB(_glfwLibrary.X11.display, *fbconfig, share, True, attribs); // We are done, so unset the error handler again (see above) XSetErrorHandler(NULL); if (window->GLX.context == NULL) { // HACK: This is a fallback for the broken Mesa implementation of // GLX_ARB_create_context_profile, which fails default 1.0 context // creation with a GLXBadProfileARB error in violation of the spec if (_glfwErrorCode == _glfwLibrary.GLX.errorBase + GLXBadProfileARB && wndconfig->clientAPI == GLFW_OPENGL_API && wndconfig->glProfile == GLFW_OPENGL_NO_PROFILE && wndconfig->glForward == GL_FALSE) { createLegacyContext(window, wndconfig, *fbconfig, share); } } } else createLegacyContext(window, wndconfig, *fbconfig, share); XFree(fbconfig); if (window->GLX.context == NULL) { _glfwSetError(GLFW_PLATFORM_ERROR, "GLX: Failed to create context"); return GL_FALSE; } return GL_TRUE; }
int main(int argc, char **argv) { opt_data opts; optproc(argc, argv, &opts); if(audio_init(&opts) < 0) exit(1); int x = 0, y = 0, w, h; if(opts.w < 0 && opts.h < 0) opts.w = opts.h = 512; else if(opts.w < 0) opts.w = opts.h; else if(opts.h < 0) opts.h = opts.w; w = opts.w; h = opts.h; XEvent event; dpy = XOpenDisplay( NULL ); if(dpy == NULL) { printf("Error: couldn't open display %s\n", getenv("DISPLAY")); exit(EXIT_FAILURE); } int glx_major, glx_minor; if(!glXQueryVersion(dpy, &glx_major, &glx_minor)) { printf("GLX extension missing!\n"); XCloseDisplay(dpy); exit(EXIT_FAILURE); } printf("GLX version %i.%i\n", glx_major, glx_minor); int glxErrBase, glxEventBase; glXQueryExtension(dpy, &glxErrBase, &glxEventBase); printf("GLX: errorBase = %i, eventBase = %i\n", glxErrBase, glxEventBase); Window xwin, root; int numReturned; GLXFBConfig *fbConfigs; fbConfigs = glXChooseFBConfig( dpy, DefaultScreen(dpy), fbattrib, &numReturned ); if(fbConfigs == NULL) { //TODO: handle this? printf("No suitable fbconfigs!\n"); exit(EXIT_FAILURE); } XVisualInfo *vinfo = glXGetVisualFromFBConfig( dpy, fbConfigs[0] ); root = DefaultRootWindow(dpy); /* window attributes */ XSetWindowAttributes attrs; attrs.background_pixel = 0; attrs.border_pixel = 0; attrs.colormap = XCreateColormap(dpy, root, vinfo->visual, AllocNone); //attrs.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask; attrs.event_mask = StructureNotifyMask | KeyPressMask; unsigned long mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; xwin = XCreateWindow(dpy, root, x, y, w, h, 0, vinfo->depth, InputOutput, vinfo->visual, mask, &attrs); XFree(vinfo); // Set hints and properties: { XSizeHints sizehints; sizehints.x = x; sizehints.y = y; sizehints.width = w; sizehints.height = h; sizehints.flags = USSize | USPosition; XSetNormalHints(dpy, xwin, &sizehints); XSetStandardProperties(dpy, xwin, "Julia-vis", "Julia-vis", None, (char **)NULL, 0, &sizehints); } /* Create a GLX context for OpenGL rendering */ GLXContext context = glXCreateNewContext(dpy, fbConfigs[0], GLX_RGBA_TYPE, NULL, True ); #if 0 GLXContext context = 0; glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0; glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc)glXGetProcAddressARB( (const GLubyte *) "glXCreateContextAttribsARB" ); if(strstr(glXQueryExtensionsString(dpy, 0), "GLX_ARB_create_context") || !glXCreateContextAttribsARB) { printf("glXCreateContextAttribsARB() not found ... using old-style GLX context\n"); context = glXCreateNewContext(dpy, fbConfigs[0], GLX_RGBA_TYPE, 0, True); } else { const int context_attribs[] = { GLX_RENDER_TYPE, GLX_RGBA_TYPE, GLX_CONTEXT_MAJOR_VERSION_ARB, 2, GLX_CONTEXT_MINOR_VERSION_ARB, 1, None }; context = glXCreateContextAttribsARB(dpy, fbConfigs[0], NULL, True, context_attribs); } if(context == NULL) { printf("Failed to create context!\n"); return EXIT_FAILURE; } #endif glxWin = glXCreateWindow(dpy, fbConfigs[0], xwin, NULL ); XMapWindow(dpy, xwin); XIfEvent(dpy, &event, WaitForNotify, (XPointer) xwin); glXMakeContextCurrent(dpy, glxWin, glxWin, context); init_gl(&opts, w, h); if(strstr(glXQueryExtensionsString(dpy, 0), "GLX_MESA_swap_control")) { PFNGLXSWAPINTERVALMESAPROC swap_interval = glXGetProcAddressARB("glXSwapIntervalMESA"); swap_interval(1); opts.draw_rate = 300; } if(strstr(glXQueryExtensionsString(dpy, 0), "GLX_INTEL_swap_event")) { glXSelectEvent(dpy, glxWin, GLX_BUFFER_SWAP_COMPLETE_INTEL_MASK); have_intel_swap_event = GL_TRUE; } int debug_maxsrc = 0, debug_pal = 0, show_mandel = 0, show_fps_hist = 0; if(have_intel_swap_event) render_frame(debug_maxsrc, debug_pal, show_mandel, show_fps_hist); while(1) { if(!have_intel_swap_event) render_frame(debug_maxsrc, debug_pal, show_mandel, show_fps_hist); int clear_key = 1; while (XPending(dpy) > 0) { XNextEvent(dpy, &event); if(event.type == glxEventBase + GLX_BufferSwapComplete) { render_frame(debug_maxsrc, debug_pal, show_mandel, show_fps_hist); continue; } switch (event.type) { case Expose: /* we'll redraw below */ break; /*case ConfigureNotify: window_w = event.xconfigure.width; window_h = event.xconfigure.height; if (surface_type == EGL_WINDOW_BIT) reshape(window_w, window_h); break;*/ case KeyPress: { clear_key = 0; char buffer[10]; int r, code; code = XLookupKeysym(&event.xkey, 0); if (code == XK_F1) { debug_maxsrc = !debug_maxsrc; } else if (code == XK_F2) { debug_pal = !debug_pal; } else if (code == XK_F3) { show_mandel = !show_mandel; } else if (code == XK_F4) { show_fps_hist = !show_fps_hist; } else { code = XLookupKeysym(&event.xkey, 1); if(code == XK_Escape) { goto glx_main_loop_quit; } } } break; default: //printf("Bar %i!\n", event.type); break; } } } glx_main_loop_quit: audio_shutdown(); XDestroyWindow(dpy, xwin); XCloseDisplay(dpy); return 0; }
GFX_PlatformWindow _gfx_platform_window_create( const GFX_PlatformAttributes* attributes) { /* Setup the x11 window */ GFX_X11_Window window; window.monitor = attributes->monitor; window.context = NULL; window.flags = 0; window.flags |= attributes->flags & GFX_WINDOW_RESIZABLE ? GFX_X11_RESIZABLE : 0; window.flags |= attributes->flags & GFX_WINDOW_HIDDEN ? GFX_X11_HIDDEN : 0; /* Get display mode & position */ GFXDisplayMode mode; int x = window.monitor->x; int y = window.monitor->y; if(attributes->flags & GFX_WINDOW_FULLSCREEN) { window.flags |= GFX_X11_FULLSCREEN; GFX_X11_Mode* it = gfx_vector_at( &_gfx_x11.modes, window.monitor->modes[attributes->mode] ); window.mode = it->id; mode = it->mode; } else { mode.width = attributes->w; mode.height = attributes->h; mode.depth = *attributes->depth; x += attributes->x; y += attributes->y; } /* Get FB Config */ GLXFBConfig* config = _gfx_x11_get_config( window.monitor->screen, &mode.depth, attributes->flags & GFX_WINDOW_DOUBLE_BUFFER ); if(!config) return NULL; /* Get visual from config */ XVisualInfo* visual = glXGetVisualFromFBConfig( _gfx_x11.display, *config ); window.config = *config; XFree(config); /* Create the window attributes */ unsigned long mask = CWColormap | CWEventMask; XSetWindowAttributes attr; if( attributes->flags & GFX_WINDOW_BORDERLESS || attributes->flags & GFX_WINDOW_FULLSCREEN) { /* Borderless window */ mask |= CWBorderPixel; attr.border_pixel = 0; } /* Event mask & Color map */ Window root = XRootWindowOfScreen(window.monitor->screen); attr.event_mask = KeyPressMask | KeyReleaseMask | PointerMotionMask | EnterWindowMask | LeaveWindowMask | ButtonPressMask | ButtonReleaseMask | StructureNotifyMask | FocusChangeMask; attr.colormap = XCreateColormap( _gfx_x11.display, root, visual->visual, AllocNone ); /* Create the actual window */ window.handle = XCreateWindow( _gfx_x11.display, root, x, y, mode.width, mode.height, 0, visual->depth, InputOutput, visual->visual, mask, &attr ); XFree(visual); if(window.handle) { /* Get properties to check for events */ XWindowAttributes get; get.x = 0; get.y = 0; get.width = 0; get.height = 0; XGetWindowAttributes(_gfx_x11.display, window.handle, &get); window.x = get.x; window.y = get.y; window.width = get.width; window.height = get.height; /* Delete protocol & name */ XSetWMProtocols( _gfx_x11.display, window.handle, &_gfx_x11.WM_DELETE_WINDOW, 1); XStoreName( _gfx_x11.display, window.handle, attributes->name); /* Disable decorations */ if(mask & CWBorderPixel) { unsigned long hints[5]; hints[0] = MWM_HINTS_DECORATIONS; hints[2] = 0; XChangeProperty( _gfx_x11.display, window.handle, _gfx_x11.MOTIF_WM_HINTS, _gfx_x11.MOTIF_WM_HINTS, 32, PropModeReplace, (unsigned char*)hints, 5); } /* Bypass compositor */ if(attributes->flags & GFX_WINDOW_FULLSCREEN) { unsigned long bypass = 1; XChangeProperty( _gfx_x11.display, window.handle, _gfx_x11.NET_WM_BYPASS_COMPOSITOR, XA_CARDINAL, 32, PropModeReplace, (unsigned char*)&bypass, 1 ); } /* Set size hints */ if(!(attributes->flags & GFX_WINDOW_RESIZABLE)) { XSizeHints* hints = XAllocSizeHints(); hints->flags = PMinSize | PMaxSize; hints->min_width = mode.width; hints->max_width = mode.width; hints->min_height = mode.height; hints->max_height = mode.height; XSetWMNormalHints(_gfx_x11.display, window.handle, hints); XFree(hints); } /* Add window to vector */ GFXVectorIterator it = gfx_vector_insert( &_gfx_x11.windows, &window, _gfx_x11.windows.end ); if(it != _gfx_x11.windows.end) { /* Make it visible */ /* Triggers FocusIn event for fullscreen */ if(!(attributes->flags & GFX_WINDOW_HIDDEN)) XMapWindow(_gfx_x11.display, window.handle); return GFX_UINT_TO_VOID(window.handle); } XDestroyWindow(_gfx_x11.display, window.handle); } XFreeColormap(_gfx_x11.display, attr.colormap); return NULL; }
void GlContext::create(uint32_t _width, uint32_t _height) { BX_UNUSED(_width, _height); XLockDisplay(s_display); int major, minor; bool version = glXQueryVersion(s_display, &major, &minor); BGFX_FATAL(version, Fatal::UnableToInitialize, "Failed to query GLX version"); BGFX_FATAL( (major == 1 && minor >= 2) || major > 1 , Fatal::UnableToInitialize , "GLX version is not >=1.2 (%d.%d)." , major , minor ); int32_t screen = DefaultScreen(s_display); const char* extensions = glXQueryExtensionsString(s_display, screen); BX_TRACE("GLX extensions:"); dumpExtensions(extensions); const int attrsGlx[] = { GLX_RENDER_TYPE, GLX_RGBA_BIT, GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, GLX_DOUBLEBUFFER, true, GLX_RED_SIZE, 8, GLX_BLUE_SIZE, 8, GLX_GREEN_SIZE, 8, // GLX_ALPHA_SIZE, 8, GLX_DEPTH_SIZE, 24, GLX_STENCIL_SIZE, 8, 0, }; // Find suitable config GLXFBConfig bestConfig = NULL; int numConfigs; GLXFBConfig* configs = glXChooseFBConfig(s_display, screen, attrsGlx, &numConfigs); BX_TRACE("glX num configs %d", numConfigs); XVisualInfo* visualInfo = NULL; for (int ii = 0; ii < numConfigs; ++ii) { visualInfo = glXGetVisualFromFBConfig(s_display, configs[ii]); if (NULL != visualInfo) { BX_TRACE("---"); bool valid = true; for (uint32_t attr = 6; attr < BX_COUNTOF(attrsGlx)-1 && attrsGlx[attr] != None; attr += 2) { int value; glXGetFBConfigAttrib(s_display, configs[ii], attrsGlx[attr], &value); BX_TRACE("glX %d/%d %2d: %4x, %8x (%8x%s)" , ii , numConfigs , attr/2 , attrsGlx[attr] , value , attrsGlx[attr + 1] , value < attrsGlx[attr + 1] ? " *" : "" ); if (value < attrsGlx[attr + 1]) { valid = false; #if !BGFX_CONFIG_DEBUG break; #endif // BGFX_CONFIG_DEBUG } } if (valid) { bestConfig = configs[ii]; BX_TRACE("Best config %d.", ii); break; } } XFree(visualInfo); visualInfo = NULL; } XFree(configs); BGFX_FATAL(visualInfo, Fatal::UnableToInitialize, "Failed to find a suitable X11 display configuration."); BX_TRACE("Create GL 2.1 context."); m_context = glXCreateContext(s_display, visualInfo, 0, GL_TRUE); BGFX_FATAL(NULL != m_context, Fatal::UnableToInitialize, "Failed to create GL 2.1 context."); XFree(visualInfo); #if BGFX_CONFIG_RENDERER_OPENGL >= 31 glXCreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC)glXGetProcAddress( (const GLubyte*)"glXCreateContextAttribsARB"); if (NULL != glXCreateContextAttribsARB) { BX_TRACE("Create GL 3.1 context."); const int contextAttrs[] = { GLX_CONTEXT_MAJOR_VERSION_ARB, 3, GLX_CONTEXT_MINOR_VERSION_ARB, 1, GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, 0, }; GLXContext context = glXCreateContextAttribsARB(s_display, bestConfig, 0, true, contextAttrs); if (NULL != context) { glXDestroyContext(s_display, m_context); m_context = context; } } #else BX_UNUSED(bestConfig); #endif // BGFX_CONFIG_RENDERER_OPENGL >= 31 XUnlockDisplay(s_display); import(); glXMakeCurrent(s_display, s_window, m_context); glXSwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC)glXGetProcAddress( (const GLubyte*)"glXSwapIntervalEXT"); if (NULL != glXSwapIntervalEXT) { BX_TRACE("Using glXSwapIntervalEXT."); glXSwapIntervalEXT(s_display, s_window, 0); } else { glXSwapIntervalMESA = (PFNGLXSWAPINTERVALMESAPROC)glXGetProcAddress( (const GLubyte*)"glXSwapIntervalMESA"); if (NULL != glXSwapIntervalMESA) { BX_TRACE("Using glXSwapIntervalMESA."); glXSwapIntervalMESA(0); } else { glXSwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC)glXGetProcAddress( (const GLubyte*)"glXSwapIntervalSGI"); if (NULL != glXSwapIntervalSGI) { BX_TRACE("Using glXSwapIntervalSGI."); glXSwapIntervalSGI(0); } } } glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); glXSwapBuffers(s_display, s_window); }
void init_display() { int surface_type_id, result, i, value, scrn, num_fbconfigs; GLXFBConfig *fbconfigs; XVisualInfo *visInfo; XSetWindowAttributes attributes; Window root; int attrib_pbuffer[6] = {GLX_PBUFFER_WIDTH, 0, GLX_PBUFFER_HEIGHT, 0, GLX_PRESERVED_CONTENTS, 0}; width = horizontal_size; height = vertical_size; if(chroma_format != CHROMA420) error("we only support 4:2:0 chroma formats\n"); display = XOpenDisplay(NULL); root = XDefaultRootWindow(display); scrn = XDefaultScreen(display); if(!GetPortId(display, &portNum, &surface_type_id)) error("couldn't find a suitable port\n"); #ifdef USE_DLOPEN if(!ResolveFunctions(DLFILENAME)) error("couldn't resolve necessary functions\n"); #endif result = XvMCCreateContext(display, portNum, surface_type_id, coded_picture_width, coded_picture_height, XVMC_DIRECT, &context); if(result != Success) error("couldn't create XvMCContext\n"); for(i = 0; i < numsurfaces; i++) { result = XvMCCreateSurface(display, &context, &surfaces[i]); if(result != Success) { if(i < 4) { XvMCDestroyContext(display, &context); error("couldn't create enough XvMCSurfaces\n"); } else { numsurfaces = i; printf("could only allocate %i surfaces\n", numsurfaces); } } surface_info[i].reference = 0; surface_info[i].sequence_number = 0; } slices = slices * mb_width; XvMCCreateBlocks(display, &context, slices * 6, &blocks); XvMCCreateMacroBlocks(display, &context, slices, ¯o_blocks); fbconfigs = glXChooseFBConfig(display, scrn, attr_fbconfig, &num_fbconfigs); gl_fbconfig = *fbconfigs; /* find the first one with no depth buffer */ for(i = 0; i < num_fbconfigs; i++) { glXGetFBConfigAttrib(display, fbconfigs[i], GLX_DEPTH_SIZE, &value); if(value == 0) { gl_fbconfig = fbconfigs[i]; break; } } PrintVisual(); visInfo = glXGetVisualFromFBConfig(display, gl_fbconfig); attrib_pbuffer[1] = width; attrib_pbuffer[3] = bob ? (height/2) : height; gl_pbuffer = glXCreatePbuffer(display, gl_fbconfig, attrib_pbuffer); gl_context = glXCreateNewContext(display, gl_fbconfig, GLX_RGBA_TYPE, NULL, 1); attributes.colormap = XCreateColormap(display, root, visInfo->visual, AllocNone); window = XCreateWindow(display, root, 0, 0, width, height, 0, visInfo->depth, InputOutput, visInfo->visual, CWColormap, &attributes); gl_window = glXCreateWindow(display, gl_fbconfig, window, NULL); XSelectInput(display, window, KeyPressMask | StructureNotifyMask | Button1MotionMask | ButtonPressMask); XMapWindow(display, window); glXMakeContextCurrent(display, gl_window, gl_pbuffer, gl_context); glDrawBuffer(GL_BACK); glReadBuffer(GL_FRONT_LEFT); tex_w = 1 << PowerOfTwo(width); tex_h = 1 << PowerOfTwo(bob ? (height/2) : height); printf("%i x %i texture\n", tex_w, tex_h); glClearColor (0.0, 0.0, 0.0, 0.0); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glTexImage2D(GL_TEXTURE_2D, 0, 3, tex_w, tex_h, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); glEnable(GL_TEXTURE_2D); glShadeModel(GL_FLAT); glViewport(0, 0, width, height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(-1.0, 1.0, -1.0, 1.0, 2, 18.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(0.0, 0.0, -8); #ifdef USE_NV_FENCE glGenFencesNV(1, &nvFence); glSetFenceNV(&nvFence, GL_ALL_COMPLETED_NV); #endif XSync(display, 0); uiclp = uiclip+512; for (i= -512; i<512; i++) uiclp[i] = (i<-128) ? 0 : ((i>127) ? 255 : i+128); iclp = iclip+512; for (i= -512; i<512; i++) iclp[i] = (i<-128) ? -128 : ((i>127) ? 127 : i); niclp = niclip+512; for (i= -512; i<512; i++) niclp[i] = (i<-256) ? -256 : ((i>255) ? 255 : i); }
int main(void) { glXGetProcAddress_fn glXGetProcAddress_ptr; glXChooseFBConfig_fn glXChooseFBConfig_ptr; glXGetVisualFromFBConfig_fn glXGetVisualFromFBConfig_ptr; glXCreateContext_fn glXCreateContext_ptr; glXMakeCurrent_fn glXMakeCurrent_ptr; glXSwapBuffers_fn glXSwapBuffers_ptr; void *libgl; GLXFBConfig *fbc; int fbcount; int attrib[] = { GLX_RENDER_TYPE, GLX_RGBA_BIT, GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, GLX_DOUBLEBUFFER, True, GLX_RED_SIZE, 8, GLX_GREEN_SIZE, 8, GLX_BLUE_SIZE, 8, GLX_DEPTH_SIZE, 24, GLX_STENCIL_SIZE, 8, None }; XVisualInfo *visinfo; XSetWindowAttributes attr; Display *disp; Window win; GLXContext ctx; libgl = dlopen("libGL.so.1", RTLD_LAZY); glXGetProcAddress = dlsym(libgl, "glXGetProcAddress"); glXChooseFBConfig = (glXChooseFBConfig_fn) glXGetProcAddress((const GLubyte *) "glXChooseFBConfig"); glXGetVisualFromFBConfig = (glXGetVisualFromFBConfig_fn) glXGetProcAddress((const GLubyte *) "glXGetVisualFromFBConfig"); glXCreateContext = (glXCreateContext_fn) glXGetProcAddress((const GLubyte *) "glXCreateContext"); glXMakeCurrent = (glXMakeCurrent_fn) glXGetProcAddress((const GLubyte *) "glXMakeCurrent"); glXSwapBuffers = (glXSwapBuffers_fn) glXGetProcAddress((const GLubyte *) "glXSwapBuffers"); disp = XOpenDisplay(NULL); fbc = glXChooseFBConfig(disp, DefaultScreen(disp), attrib, &fbcount); visinfo = glXGetVisualFromFBConfig(disp, fbc[0]); attr.background_pixel = 0; attr.border_pixel = 0; attr.colormap = XCreateColormap(disp, RootWindow(disp, DefaultScreen(disp)), visinfo->visual, AllocNone); attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask | KeyReleaseMask | PointerMotionMask | ButtonPressMask | ButtonReleaseMask; win = XCreateWindow(disp, RootWindow(disp, DefaultScreen(disp)), 0, 0, 600, 600, 0, visinfo->depth, InputOutput, visinfo->visual, CWBackPixel | CWBorderPixel | CWColormap | CWEventMask, &attr); XMapWindow(disp, win); ctx = glXCreateContext(disp, visinfo, NULL, True); glXMakeCurrent(disp, win, ctx); load_opengl_commands(); while (1) { if (XPending(disp)) { XEvent evt; XNextEvent(disp, &evt); switch (evt.type) { case KeyPress: return 0; } } else { struct timeval tp; float time; gettimeofday(&tp, NULL); time = tp.tv_sec + tp.tv_usec / 1e6; glXSwapBuffers(disp, win); } } }
agpu_device *_agpu_device::open(agpu_device_open_info* openInfo) { // Ensure X11 threads are initialized XInitThreads(); // Create the device. std::unique_ptr<agpu_device> device(new agpu_device); bool failure = false; // Perform the main context creation in device->mainContextJobQueue.start(); AsyncJob contextCreationJob([&] { std::unique_ptr<OpenGLContext> contextWrapper(new OpenGLContext()); const char *displayName = nullptr; if(openInfo->display) displayName = ((Display*)openInfo->display)->display_name; contextWrapper->display = XOpenDisplay(displayName); if(!contextWrapper->display) { failure = true; return; } // Create a simple context. int visualAttributes[] { GLX_X_RENDERABLE, True, GLX_RENDER_TYPE, GLX_RGBA_BIT, GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR, GLX_RED_SIZE, 8, GLX_GREEN_SIZE, 8, GLX_BLUE_SIZE, 8, GLX_ALPHA_SIZE, 8, GLX_DOUBLEBUFFER, True, None, None }; // Find the framebuffer config. GLXFBConfig framebufferConfig; if(!findFramebufferConfig(contextWrapper->display, &visualAttributes[0], framebufferConfig)) { failure = true; return; } contextWrapper->framebufferConfig = framebufferConfig; // Get a visual XVisualInfo *vi = glXGetVisualFromFBConfig( contextWrapper->display, framebufferConfig ); XSetWindowAttributes swa; Colormap cmap; swa.colormap = cmap = XCreateColormap( contextWrapper->display, RootWindow( contextWrapper->display, vi->screen ), vi->visual, AllocNone ); swa.background_pixmap = None ; swa.border_pixel = 0; swa.event_mask = StructureNotifyMask; Window win = XCreateWindow( contextWrapper->display, RootWindow( contextWrapper->display, vi->screen ), 0, 0, 4, 4, 0, vi->depth, InputOutput, vi->visual, CWBorderPixel|CWColormap|CWEventMask, &swa ); if ( !win ) { printf( "Failed to create window.\n" ); failure = true; } // Done with the visual info data XFree( vi ); XStoreName( contextWrapper->display, win, "AGPU dummy window" ); //Store the window in the context wrapper. contextWrapper->ownsWindow = true; contextWrapper->window = win; // Get the default screen's GLX extension list const char *glxExts = glXQueryExtensionsString( contextWrapper->display, DefaultScreen( contextWrapper->display ) ); // NOTE: It is not necessary to create or make current to a context before // calling glXGetProcAddressARB auto glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc) glXGetProcAddressARB( (const GLubyte *) "glXCreateContextAttribsARB" ); contextWrapper->glXCreateContextAttribsARB = glXCreateContextAttribsARB; GLXContext context = 0; // Install an X error handler so the application won't exit if GL 3.0 // context allocation fails. std::unique_lock<std::mutex> l(contextErrorMutex); ctxErrorOccurred = false; auto oldHandler = XSetErrorHandler(&ctxErrorHandler); // Check for the GLX_ARB_create_context extension string and the function. // If either is not present, use GLX 1.3 context creation method. if ( !agpu_device::isExtensionSupported( glxExts, "GLX_ARB_create_context" ) || !glXCreateContextAttribsARB ) { printError("glXCreateContextAttribsARB() not found... using old-style GLX context\n" ); context = glXCreateNewContext( contextWrapper->display, framebufferConfig, GLX_RGBA_TYPE, 0, True ); } else { int contextAttributes[] = { GLX_CONTEXT_MAJOR_VERSION_ARB, 0, GLX_CONTEXT_MINOR_VERSION_ARB, 0, GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, //GLX_CONTEXT_FLAGS_ARB , GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, None }; for(int versionIndex = 0; GLContextVersionPriorities[versionIndex] != OpenGLVersion::Invalid; ++versionIndex) { auto version = (int)GLContextVersionPriorities[versionIndex]; // GLX_CONTEXT_MAJOR_VERSION_ARB contextAttributes[1] = version / 10; // GLX_CONTEXT_MINOR_VERSION_ARB contextAttributes[3] = version % 10; if(contextAttributes[1] < 3) contextAttributes[4] = 0; context = glXCreateContextAttribsARB( contextWrapper->display, framebufferConfig, 0, True, contextAttributes ); // Sync to ensure any errors generated are processed. XSync( contextWrapper->display, False ); // Check for success. if(!ctxErrorOccurred && context) { contextWrapper->version = OpenGLVersion(version); break; } ctxErrorOccurred = false; } // Check failure. if ( ctxErrorOccurred || !context ) { // Couldn't create GL 3.0 context. Fall back to old-style 2.x context. // When a context version below 3.0 is requested, implementations will // return the newest context version compatible with OpenGL versions less // than version 3.0. // GLX_CONTEXT_MAJOR_VERSION_ARB = 1 contextAttributes[1] = 1; // GLX_CONTEXT_MINOR_VERSION_ARB = 0 contextAttributes[3] = 0; contextAttributes[4] = 0; contextWrapper->version = OpenGLVersion::Version10; ctxErrorOccurred = false; context = glXCreateContextAttribsARB( contextWrapper->display, framebufferConfig, 0, True, contextAttributes ); } } // Sync to ensure any errors generated are processed. XSync( contextWrapper->display, False ); // Restore the original error handler XSetErrorHandler( oldHandler ); if ( ctxErrorOccurred || !context ) { printError("Failed to create an OpenGL context\n" ); failure = true; return; } // Store the context in the wrapper. contextWrapper->context = context; if(!contextWrapper->makeCurrent()) { printError("Failed to make current the main OpenGL context.\n"); contextWrapper->destroy(); failure = true; return; } // Initialize the device objects. device->mainContext = contextWrapper.release(); device->mainContext->device = device.get(); device->initializeObjects(); }); device->mainContextJobQueue.addJob(&contextCreationJob); contextCreationJob.wait(); if(failure) return nullptr; return device.release(); }
void GlxContext::createContext(GlxContext* shared) { // Get a working copy of the context settings ContextSettings settings = m_settings; XVisualInfo* visualInfo = NULL; if (m_pbuffer) { unsigned int fbConfigId = 0; glXQueryDrawable(m_display, m_pbuffer, GLX_FBCONFIG_ID, &fbConfigId); int attributes[] = { GLX_FBCONFIG_ID, static_cast<int>(fbConfigId), 0, 0 }; int count = 0; GLXFBConfig* fbconfig = glXChooseFBConfig(m_display, DefaultScreen(m_display), attributes, &count); if (count == 1) visualInfo = glXGetVisualFromFBConfig(m_display, *fbconfig); if (fbconfig) XFree(fbconfig); } else { // Retrieve the attributes of the target window XWindowAttributes windowAttributes; if (XGetWindowAttributes(m_display, m_window, &windowAttributes) == 0) { err() << "Failed to get the window attributes" << std::endl; return; } // Get its visuals XVisualInfo tpl; tpl.screen = DefaultScreen(m_display); tpl.visualid = XVisualIDFromVisual(windowAttributes.visual); int nbVisuals = 0; visualInfo = XGetVisualInfo(m_display, VisualIDMask | VisualScreenMask, &tpl, &nbVisuals); } if (!visualInfo) { err() << "Failed to get visual info" << std::endl; return; } // Get the context to share display lists with GLXContext toShare = shared ? shared->m_context : NULL; // There are no GLX versions prior to 1.0 int major = 0; int minor = 0; if (!glXQueryVersion(m_display, &major, &minor)) err() << "Failed to query GLX version, limited to legacy context creation" << std::endl; // Check if glXCreateContextAttribsARB is available (requires GLX 1.3 or greater) bool hasCreateContextArb = (sfglx_ext_ARB_create_context == sfglx_LOAD_SUCCEEDED) && ((major > 1) || (minor >= 3)); // Create the OpenGL context -- first try using glXCreateContextAttribsARB if (hasCreateContextArb) { // Get a GLXFBConfig that matches the window's visual, for glXCreateContextAttribsARB GLXFBConfig* config = NULL; // We don't supply attributes to match against, since // the visual we are matching against was already // deemed suitable in selectBestVisual() int nbConfigs = 0; GLXFBConfig* configs = glXChooseFBConfig(m_display, DefaultScreen(m_display), NULL, &nbConfigs); for (int i = 0; configs && (i < nbConfigs); ++i) { XVisualInfo* visual = glXGetVisualFromFBConfig(m_display, configs[i]); if (!visual) continue; if (visual->visualid == visualInfo->visualid) { config = &configs[i]; break; } } if (!config) err() << "Failed to get GLXFBConfig which corresponds to the window's visual" << std::endl; while (config && !m_context && m_settings.majorVersion) { std::vector<int> attributes; // Check if the user requested a specific context version (anything > 1.1) if ((m_settings.majorVersion > 1) || ((m_settings.majorVersion == 1) && (m_settings.minorVersion > 1))) { attributes.push_back(GLX_CONTEXT_MAJOR_VERSION_ARB); attributes.push_back(m_settings.majorVersion); attributes.push_back(GLX_CONTEXT_MINOR_VERSION_ARB); attributes.push_back(m_settings.minorVersion); } // Check if setting the profile is supported if (sfglx_ext_ARB_create_context_profile == sfglx_LOAD_SUCCEEDED) { int profile = (m_settings.attributeFlags & ContextSettings::Core) ? GLX_CONTEXT_CORE_PROFILE_BIT_ARB : GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; int debug = (m_settings.attributeFlags & ContextSettings::Debug) ? GLX_CONTEXT_DEBUG_BIT_ARB : 0; attributes.push_back(GLX_CONTEXT_PROFILE_MASK_ARB); attributes.push_back(profile); attributes.push_back(GLX_CONTEXT_FLAGS_ARB); attributes.push_back(debug); } else { if ((m_settings.attributeFlags & ContextSettings::Core) || (m_settings.attributeFlags & ContextSettings::Debug)) err() << "Selecting a profile during context creation is not supported," << "disabling comptibility and debug" << std::endl; m_settings.attributeFlags = ContextSettings::Default; } // Append the terminating 0 attributes.push_back(0); attributes.push_back(0); // RAII GLX error handler (we simply ignore errors here) // On an error, glXCreateContextAttribsARB will return 0 anyway GlxErrorHandler handler(m_display); // Create the context m_context = glXCreateContextAttribsARB(m_display, *config, toShare, true, &attributes[0]); if (!m_context) { // If we couldn't create the context, first try disabling flags, // then lower the version number and try again -- stop at 0.0 // Invalid version numbers will be generated by this algorithm (like 3.9), but we really don't care if (m_settings.attributeFlags != ContextSettings::Default) { m_settings.attributeFlags = ContextSettings::Default; } else if (m_settings.minorVersion > 0) { // If the minor version is not 0, we decrease it and try again m_settings.minorVersion--; m_settings.attributeFlags = settings.attributeFlags; } else { // If the minor version is 0, we decrease the major version m_settings.majorVersion--; m_settings.minorVersion = 9; m_settings.attributeFlags = settings.attributeFlags; } } } if (configs) XFree(configs); } // If glXCreateContextAttribsARB failed, use glXCreateContext if (!m_context) { // set the context version to 2.1 (arbitrary) and disable flags m_settings.majorVersion = 2; m_settings.minorVersion = 1; m_settings.attributeFlags = ContextSettings::Default; #if defined(GLX_DEBUGGING) GlxErrorHandler handler(m_display); #endif // Create the context, using the target window's visual m_context = glXCreateContext(m_display, visualInfo, toShare, true); #if defined(GLX_DEBUGGING) if (glxErrorOccurred) err() << "GLX error in GlxContext::createContext()" << std::endl; #endif } if (!m_context) err() << "Failed to create an OpenGL context for this window" << std::endl; // Free the visual info XFree(visualInfo); }
void GlxContext::createSurface(GlxContext* shared, unsigned int width, unsigned int height, unsigned int bitsPerPixel) { m_display = OpenDisplay(); m_connection = XGetXCBConnection(m_display); // Choose the visual according to the context settings XVisualInfo visualInfo = selectBestVisual(m_display, bitsPerPixel, m_settings); // Check if the shared context already exists and pbuffers are supported if (shared && (sfglx_ext_SGIX_pbuffer == sfglx_LOAD_SUCCEEDED)) { // There are no GLX versions prior to 1.0 int major = 0; int minor = 0; glXQueryVersion(m_display, &major, &minor); // Check if glXCreatePbuffer is available (requires GLX 1.3 or greater) bool hasCreatePbuffer = ((major > 1) || (minor >= 3)); if (hasCreatePbuffer) { // Get a GLXFBConfig that matches the visual GLXFBConfig* config = NULL; // We don't supply attributes to match against, since // the visual we are matching against was already // deemed suitable in selectBestVisual() int nbConfigs = 0; GLXFBConfig* configs = glXChooseFBConfig(m_display, DefaultScreen(m_display), NULL, &nbConfigs); for (int i = 0; configs && (i < nbConfigs); ++i) { XVisualInfo* visual = glXGetVisualFromFBConfig(m_display, configs[i]); if (!visual) continue; if (visual->visualid == visualInfo.visualid) { config = &configs[i]; break; } } if (config) { int attributes[] = { GLX_PBUFFER_WIDTH, static_cast<int>(width), GLX_PBUFFER_HEIGHT, static_cast<int>(height), 0, 0 }; m_pbuffer = glXCreatePbuffer(m_display, *config, attributes); updateSettingsFromVisualInfo(&visualInfo); XFree(configs); return; } if (configs) XFree(configs); } } // If pbuffers are not available we use a hidden window as the off-screen surface to draw to xcb_screen_t* screen = XCBScreenOfDisplay(m_connection, DefaultScreen(m_display)); // Define the window attributes xcb_colormap_t colormap = xcb_generate_id(m_connection); xcb_create_colormap(m_connection, XCB_COLORMAP_ALLOC_NONE, colormap, screen->root, visualInfo.visualid); const uint32_t value_list[] = {colormap}; // Create a dummy window (disabled and hidden) m_window = xcb_generate_id(m_connection); xcb_create_window( m_connection, static_cast<uint8_t>(visualInfo.depth), m_window, screen->root, 0, 0, width, height, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, visualInfo.visualid, XCB_CW_COLORMAP, value_list ); m_ownsWindow = true; updateSettingsFromWindow(); }
bool CStdGLCtx::Init(C4Window * pWindow, C4AbstractApp *) { // safety if (!pGL) return false; // store window this->pWindow = pWindow; Display * const dpy = gdk_x11_display_get_xdisplay(gdk_display_get_default()); InitGLXPointers(); if (!glXGetVisualFromFBConfig || !glXChooseFBConfig || !glXCreateNewContext) { return pGL->Error(" gl: Unable to retrieve GLX 1.4 entry points"); } XVisualInfo *vis_info = glXGetVisualFromFBConfig(dpy, pWindow->Info); // Create base context so we can initialize GLEW GLXContext dummy_ctx = glXCreateContext(dpy, vis_info, 0, True); XFree(vis_info); glXMakeCurrent(dpy, pWindow->renderwnd, dummy_ctx); glewExperimental = GL_TRUE; GLenum err = glewInit(); if (err != GLEW_OK) { return pGL->Error((const char*)glewGetErrorString(err)); } // Create Context with sharing (if this is the main context, our ctx will be 0, so no sharing) const int attribs[] = { GLX_CONTEXT_MAJOR_VERSION_ARB, REQUESTED_GL_CTX_MAJOR, GLX_CONTEXT_MINOR_VERSION_ARB, REQUESTED_GL_CTX_MINOR, GLX_CONTEXT_FLAGS_ARB, (Config.Graphics.DebugOpenGL ? GLX_CONTEXT_DEBUG_BIT_ARB : 0), GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, None }; GLXContext share_context = (pGL->pMainCtx != this) ? static_cast<GLXContext>(pGL->pMainCtx->ctx) : 0; if (glXCreateContextAttribsARB) { int (*oldErrorHandler) (Display *, XErrorEvent *) = XSetErrorHandler(GLXErrorHandler); ctx = glXCreateContextAttribsARB(dpy, pWindow->Info, share_context, True, attribs); XSync(dpy, False); XSetErrorHandler(oldErrorHandler); } if(!ctx) { Log(" gl: falling back to attribute-less context creation."); ctx = glXCreateNewContext(dpy, pWindow->Info, GLX_RGBA_TYPE, share_context, True); } glXMakeCurrent(dpy, None, NULL); glXDestroyContext(dpy, dummy_ctx); // No luck? if (!ctx) return pGL->Error(" gl: Unable to create context"); if (!Select(true)) return pGL->Error(" gl: Unable to select context"); // init extensions glewExperimental = GL_TRUE; err = glewInit(); if (GLEW_OK != err) { // Problem: glewInit failed, something is seriously wrong. return pGL->Error(reinterpret_cast<const char*>(glewGetErrorString(err))); } this_context = contexts.insert(contexts.end(), this); return true; }
static gboolean gst_gl_context_glx_choose_format (GstGLContext * context, GError ** error) { GstGLContextGLX *context_glx; GstGLWindow *window; GstGLWindowX11 *window_x11; gint error_base; gint event_base; Display *device; context_glx = GST_GL_CONTEXT_GLX (context); window = gst_gl_context_get_window (context); window_x11 = GST_GL_WINDOW_X11 (window); device = (Display *) gst_gl_display_get_handle (window->display); if (!glXQueryExtension (device, &error_base, &event_base)) { g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_RESOURCE_UNAVAILABLE, "No GLX extension"); goto failure; } if (!glXQueryVersion (device, &context_glx->priv->glx_major, &context_glx->priv->glx_minor)) { g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_CREATE_CONTEXT, "Failed to query GLX version (glXQueryVersion failed)"); goto failure; } GST_INFO ("GLX Version: %d.%d", context_glx->priv->glx_major, context_glx->priv->glx_minor); /* legacy case */ if (context_glx->priv->glx_major < 1 || (context_glx->priv->glx_major == 1 && context_glx->priv->glx_minor < 3)) { gint attribs[] = { GLX_RGBA, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1, GLX_DEPTH_SIZE, 16, GLX_DOUBLEBUFFER, None }; window_x11->visual_info = glXChooseVisual (device, window_x11->screen_num, attribs); if (!window_x11->visual_info) { g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_WRONG_CONFIG, "Bad attributes in glXChooseVisual"); goto failure; } } else { gint attribs[] = { GLX_RENDER_TYPE, GLX_RGBA_BIT, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1, GLX_DEPTH_SIZE, 16, GLX_DOUBLEBUFFER, True, None }; int fbcount; context_glx->priv->fbconfigs = glXChooseFBConfig (device, DefaultScreen (device), attribs, &fbcount); if (!context_glx->priv->fbconfigs) { g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_WRONG_CONFIG, "Could not find any FBConfig's to use (check attributes?)"); goto failure; } _describe_fbconfig (device, context_glx->priv->fbconfigs[0]); window_x11->visual_info = glXGetVisualFromFBConfig (device, context_glx->priv->fbconfigs[0]); if (!window_x11->visual_info) { g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_WRONG_CONFIG, "Bad attributes in FBConfig"); goto failure; } } gst_gl_window_x11_create_window ((GstGLWindowX11 *) window); gst_object_unref (window); return TRUE; failure: if (window) gst_object_unref (window); return FALSE; }
static int glx_init(struct MPGLContext *ctx, int flags) { struct vo *vo = ctx->vo; struct glx_context *glx_ctx = ctx->priv; if (!vo_x11_init(ctx->vo)) goto uninit; int glx_major, glx_minor; if (!glXQueryVersion(vo->x11->display, &glx_major, &glx_minor)) { MP_ERR(vo, "GLX not found.\n"); goto uninit; } // FBConfigs were added in GLX version 1.3. if (MPGL_VER(glx_major, glx_minor) < MPGL_VER(1, 3)) { MP_ERR(vo, "GLX version older than 1.3.\n"); goto uninit; } int glx_attribs[] = { GLX_X_RENDERABLE, True, GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1, GLX_ALPHA_SIZE, 0, GLX_DOUBLEBUFFER, True, None }; GLXFBConfig fbc = NULL; if (flags & VOFLAG_ALPHA) { set_glx_attrib(glx_attribs, GLX_ALPHA_SIZE, 1); fbc = select_fb_config(vo, glx_attribs, flags); if (!fbc) { set_glx_attrib(glx_attribs, GLX_ALPHA_SIZE, 0); flags &= ~VOFLAG_ALPHA; } } if (!fbc) fbc = select_fb_config(vo, glx_attribs, flags); if (!fbc) { MP_ERR(vo, "no GLX support present\n"); goto uninit; } MP_VERBOSE(vo, "GLX chose FB config with ID 0x%x\n", (int)(intptr_t)fbc); glx_ctx->fbc = fbc; glx_ctx->vinfo = glXGetVisualFromFBConfig(vo->x11->display, fbc); if (glx_ctx->vinfo) { MP_VERBOSE(vo, "GLX chose visual with ID 0x%x\n", (int)glx_ctx->vinfo->visualid); } else { MP_WARN(vo, "Selected GLX FB config has no associated X visual\n"); } if (!vo_x11_create_vo_window(vo, glx_ctx->vinfo, "gl")) goto uninit; bool success = false; if (!(flags & VOFLAG_GLES)) { for (int n = 0; mpgl_preferred_gl_versions[n]; n++) { int version = mpgl_preferred_gl_versions[n]; MP_VERBOSE(vo, "Creating OpenGL %d.%d context...\n", MPGL_VER_P(version)); if (version >= 300) { success = create_context_x11_gl3(ctx, flags, version, false); } else { success = create_context_x11_old(ctx); } if (success) break; } } if (!success) // try ES success = create_context_x11_gl3(ctx, flags, 200, true); if (success && !glXIsDirect(vo->x11->display, glx_ctx->context)) ctx->gl->mpgl_caps |= MPGL_CAP_SW; if (!success) goto uninit; return 0; uninit: glx_uninit(ctx); return -1; }
void GlxContext::createContext(GlxContext* shared, unsigned int bitsPerPixel, const ContextSettings& settings) { XVisualInfo* visualInfo = NULL; // Save the creation settings m_settings = settings; // Get the context to share display lists with GLXContext toShare = shared ? shared->m_context : NULL; // Create the OpenGL context -- first try context versions >= 3.0 if it is requested (they require special code) if (m_settings.majorVersion >= 3) { const GLubyte* name = reinterpret_cast<const GLubyte*>("glXCreateContextAttribsARB"); PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB = reinterpret_cast<PFNGLXCREATECONTEXTATTRIBSARBPROC>(glXGetProcAddress(name)); if (glXCreateContextAttribsARB) { // Select a GLXFB config that matches the requested context settings int nbConfigs = 0; int fbAttributes[] = { GLX_DEPTH_SIZE, static_cast<int>(settings.depthBits), GLX_STENCIL_SIZE, static_cast<int>(settings.stencilBits), GLX_SAMPLE_BUFFERS, settings.antialiasingLevel > 0, GLX_SAMPLES, static_cast<int>(settings.antialiasingLevel), GLX_RED_SIZE, 8, GLX_GREEN_SIZE, 8, GLX_BLUE_SIZE, 8, GLX_ALPHA_SIZE, bitsPerPixel == 32 ? 8 : 0, GLX_DOUBLEBUFFER, True, GLX_X_RENDERABLE, True, GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, GLX_RENDER_TYPE, GLX_RGBA_BIT, GLX_CONFIG_CAVEAT, GLX_NONE, None }; GLXFBConfig* configs = glXChooseFBConfig(m_display, DefaultScreen(m_display), fbAttributes, &nbConfigs); if (configs && nbConfigs) { while (!m_context && (m_settings.majorVersion >= 3)) { // Create the context int attributes[] = { GLX_CONTEXT_MAJOR_VERSION_ARB, static_cast<int>(m_settings.majorVersion), GLX_CONTEXT_MINOR_VERSION_ARB, static_cast<int>(m_settings.minorVersion), GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, 0, 0 }; m_context = glXCreateContextAttribsARB(m_display, configs[0], toShare, true, attributes); if (m_context) { // Ok: retrieve the config's visual visualInfo = glXGetVisualFromFBConfig(m_display, configs[0]); } else { // If we couldn't create the context, lower the version number and try again -- stop at 3.0 // Invalid version numbers will be generated by this algorithm (like 3.9), but we really don't care if (m_settings.minorVersion > 0) { // If the minor version is not 0, we decrease it and try again m_settings.minorVersion--; } else { // If the minor version is 0, we decrease the major version m_settings.majorVersion--; m_settings.minorVersion = 9; } } } XFree(configs); } } } // If the OpenGL >= 3.0 context failed or if we don't want one, create a regular OpenGL 1.x/2.x context if (!m_context) { // set the context version to 2.0 (arbitrary) m_settings.majorVersion = 2; m_settings.minorVersion = 0; // Retrieve the attributes of the target window XWindowAttributes windowAttributes; if (XGetWindowAttributes(m_display, m_window, &windowAttributes) == 0) { err() << "Failed to get the window attributes" << std::endl; return; } // Get its visual XVisualInfo tpl; tpl.screen = DefaultScreen(m_display); tpl.visualid = XVisualIDFromVisual(windowAttributes.visual); int nbVisuals = 0; visualInfo = XGetVisualInfo(m_display, VisualIDMask | VisualScreenMask, &tpl, &nbVisuals); // Create the context, using the target window's visual m_context = glXCreateContext(m_display, visualInfo, toShare, true); if (!m_context) { err() << "Failed to create an OpenGL context for this window" << std::endl; return; } } // Update the creation settings from the chosen format int depth, stencil, multiSampling, samples; glXGetConfig(m_display, visualInfo, GLX_DEPTH_SIZE, &depth); glXGetConfig(m_display, visualInfo, GLX_STENCIL_SIZE, &stencil); glXGetConfig(m_display, visualInfo, GLX_SAMPLE_BUFFERS_ARB, &multiSampling); glXGetConfig(m_display, visualInfo, GLX_SAMPLES_ARB, &samples); m_settings.depthBits = static_cast<unsigned int>(depth); m_settings.stencilBits = static_cast<unsigned int>(stencil); m_settings.antialiasingLevel = multiSampling ? samples : 0; // Free the visual info XFree(visualInfo); }
void __plg_openWindow() { int n, i; XVisualInfo* visual_info; GLXFBConfig fb_config, *fb_configs; XSetWindowAttributes x_attrs; plgCurrentDisplay = XOpenDisplay(0); /* Choose X11 FB Config + Visual */ fb_configs = glXChooseFBConfig( plgCurrentDisplay, DefaultScreen(plgCurrentDisplay), kPLGOpenGLAttrs, &n ); //visual_info = glXChooseVisual( // plgCurrentDisplay, // DefaultScreen(plgCurrentDisplay), // kPLGX11Attrs //); for (i = 0; i < n; i++) { visual_info = glXGetVisualFromFBConfig(plgCurrentDisplay, fb_configs[i]); fb_config = fb_configs[i]; // FIXPAUL choose best if (visual_info) { break; } } assert(visual_info); printf("visual: 0x%x\n", visual_info->visualid); /* Setup X11 window attributes */ x_attrs.event_mask = StructureNotifyMask; x_attrs.border_pixel = 0; x_attrs.background_pixmap = None; x_attrs.colormap = XCreateColormap( plgCurrentDisplay, RootWindow(plgCurrentDisplay, visual_info->screen), visual_info->visual, AllocNone ); /* Open X11 Window */ plgCurrentWindow = XCreateWindow( plgCurrentDisplay, RootWindow(plgCurrentDisplay, visual_info->screen), 0, 0, 1440, 900, 0, visual_info->depth, InputOutput, visual_info->visual, CWBorderPixel|CWColormap|CWEventMask, &x_attrs ); XMapWindow(plgCurrentDisplay, plgCurrentWindow); /* Receive create context function pointer */ glXCreateContextAttribsARBProc glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc) glXGetProcAddressARB((const GLubyte *) "glXCreateContextAttribsARB"); /* Create OpenGL Context */ plgCurrentGLContext = glXCreateContextAttribsARB( plgCurrentDisplay, fb_config, NULL, true, kPLGOpenGLAttrs ); glXMakeCurrent( plgCurrentDisplay, plgCurrentWindow, plgCurrentGLContext ); }
bool gl_platform_init_swapchain(struct gs_swap_chain *swap) { Display *display = swap->wi->display; struct gl_windowinfo *info = swap->wi; struct gl_platform *plat = swap->device->plat; XVisualInfo *vi = 0; Colormap cmap = 0; XSetWindowAttributes swa; XWindowAttributes attrs; XErrorHandler phandler = XSetErrorHandler(err_handler); gl_platform_cleanup_swapchain(swap); if (!XGetWindowAttributes(display, info->id, &attrs)) { blog(LOG_ERROR, "Failed getting window attributes"); goto fail; } vi = glXGetVisualFromFBConfig(display, plat->fbcfg); if (handle_x_error(display, "Failed to get visual from fb config.")) goto fail; cmap = XCreateColormap(display, info->id, vi->visual, AllocNone); if (handle_x_error(display, "Failed creating colormap")) goto fail; swa.colormap = cmap; swa.border_pixel = 0; info->int_id = XCreateWindow(display, info->id, 0, 0, attrs.width, attrs.height, 0, 24, InputOutput, vi->visual, CWBorderPixel|CWColormap, &swa); XMapWindow(display, info->int_id); if (handle_x_error(display, "Failed creating intermediate X window")) goto fail; info->glxid = glXCreateWindow(display, plat->fbcfg, info->int_id, 0); if (handle_x_error(display, "Failed creating intermediate GLX window")) goto fail; XFreeColormap(display, cmap); XFree(vi); return true; fail: gl_platform_cleanup_swapchain(swap); if (cmap) XFreeColormap(display, cmap); if (vi) XFree(vi); XSetErrorHandler(phandler); return false; }
void X11OpenGLWindow::createWindow(const b3gWindowConstructionInfo& ci) { m_data->m_dpy = MyXOpenDisplay(NULL); m_data->m_glWidth = ci.m_width; m_data->m_glHeight = ci.m_height; if(m_data->m_dpy == NULL) { printf("\n\tcannot connect to X server\n\n"); exit(0); } m_data->m_root = DefaultRootWindow(m_data->m_dpy); #ifdef GLEW_DYNAMIC_LOAD_ALL_GLX_FUNCTIONS GLboolean res = glewXInit(); if (res==0) { printf("glewXInit OK\n"); } else { printf("glewXInit failed, exit\n"); exit(0); } #endif //GLEW_DYNAMIC_LOAD_ALL_GLX_FUNCTIONS if (ci.m_openglVersion < 3) { forceOpenGL3 = false; } if (forceOpenGL3) { int glxMinor, glxMajor; if (!glXQueryVersion(m_data->m_dpy,&glxMajor,&glxMinor) || (((glxMajor==1)&&(glxMinor<3)) || (glxMajor<1))) { printf("Invalid GLX version: major %d, minor %d\n",glxMajor,glxMinor); exit(0); } static int visual_attribs[] = { GLX_X_RENDERABLE , True, GLX_DRAWABLE_TYPE , GLX_WINDOW_BIT, GLX_RENDER_TYPE , GLX_RGBA_BIT, GLX_X_VISUAL_TYPE , GLX_TRUE_COLOR, GLX_RED_SIZE , 8, GLX_GREEN_SIZE , 8, GLX_BLUE_SIZE , 8, GLX_ALPHA_SIZE , 8, GLX_DEPTH_SIZE , 24, GLX_STENCIL_SIZE , 8, GLX_DOUBLEBUFFER , True, None }; int fbcount; GLXFBConfig* fbc = glXChooseFBConfig(m_data->m_dpy, DefaultScreen(m_data->m_dpy), visual_attribs, &fbcount); if (!fbc) { printf( "Failed to retrieve a framebuffer config\n" ); exit(1); } ///don't use highest samples, it is really slow on some NVIDIA Quadro cards #ifdef USE_HIGHEST_SAMPLES int best_fbc = -1, worst_fbc = -1, best_num_samp = -1, worst_num_samp = 999; int i; for (i=0; i<fbcount; ++i) { XVisualInfo *vi = glXGetVisualFromFBConfig( m_data->m_dpy, fbc[i] ); if ( vi ) { int samp_buf, samples; glXGetFBConfigAttrib( m_data->m_dpy, fbc[i], GLX_SAMPLE_BUFFERS, &samp_buf ); glXGetFBConfigAttrib( m_data->m_dpy, fbc[i], GLX_SAMPLES , &samples ); //printf( " Matching fbconfig %d, visual ID 0x%2x: SAMPLE_BUFFERS = %d," // " SAMPLES = %d\n", // i, vi -> visualid, samp_buf, samples ); if ( best_fbc < 0 || (samp_buf && (samples > best_num_samp)) ) best_fbc = i, best_num_samp = samples; if ( worst_fbc < 0 || (!samp_buf || (samples < worst_num_samp)) ) worst_fbc = i, worst_num_samp = samples; } MyXFree( vi ); } m_data->m_bestFbc = fbc[ best_fbc ]; #else m_data->m_bestFbc = *fbc; #endif // Be sure to free the FBConfig list allocated by glXChooseFBConfig() MyXFree( fbc ); m_data->m_vi = glXGetVisualFromFBConfig( m_data->m_dpy, m_data->m_bestFbc ); m_data->m_swa.colormap = m_data->m_cmap = MyXCreateColormap( m_data->m_dpy, RootWindow( m_data->m_dpy, m_data->m_vi->screen ), m_data->m_vi->visual, AllocNone ); m_data->m_swa.background_pixmap = None ; m_data->m_swa.border_pixel = 0; m_data->m_swa.event_mask = ExposureMask | KeyReleaseMask | KeyPressMask |ButtonPressMask | ButtonReleaseMask |PointerMotionMask|StructureNotifyMask; ; m_data->m_root = RootWindow( m_data->m_dpy, m_data->m_vi->screen ); m_data->m_win = MyXCreateWindow( m_data->m_dpy, m_data->m_root, 0, 0, ci.m_width, ci.m_height, 0, m_data->m_vi->depth, InputOutput, m_data->m_vi->visual, CWBorderPixel|CWColormap|CWEventMask, &m_data->m_swa ); //m_data->m_win = m_data->m_x11_XCreateWindow(m_data->m_dpy, m_data->m_root, 0, 0, ci.m_width, ci.m_height, 0, m_data->m_vi->depth, InputOutput, m_data->m_vi->visual, CWColormap | CWEventMask, &m_data->m_swa); if (!m_data->m_win) { printf("Cannot create window\n"); exit(0); } MyXMapWindow(m_data->m_dpy, m_data->m_win); MyXStoreName(m_data->m_dpy, m_data->m_win, "OpenGL3 Window"); } else { m_data->m_vi = glXChooseVisual(m_data->m_dpy, 0, att); printf("4\n"); if(m_data->m_vi == NULL) { printf("\n\tno appropriate visual found\n\n"); exit(0); } else { printf("\n\tvisual %p selected\n", (void *)m_data->m_vi->visualid); /* %p creates hexadecimal output like in glxinfo */ } m_data->m_cmap = MyXCreateColormap(m_data->m_dpy, m_data->m_root, m_data->m_vi->visual, AllocNone); m_data->m_swa.colormap = m_data->m_cmap; m_data->m_swa.event_mask = ExposureMask | KeyReleaseMask | KeyPressMask |ButtonPressMask | ButtonReleaseMask |PointerMotionMask|StructureNotifyMask; m_data->m_win = MyXCreateWindow(m_data->m_dpy, m_data->m_root, 0, 0, ci.m_width, ci.m_height, 0, m_data->m_vi->depth, InputOutput, m_data->m_vi->visual, CWColormap | CWEventMask, &m_data->m_swa); MyXMapWindow(m_data->m_dpy, m_data->m_win); MyXStoreName(m_data->m_dpy, m_data->m_win, "OpenGL2 Window"); } enableOpenGL(); }
/* * General settings query method */ int FGAPIENTRY glutGet( GLenum eWhat ) { #if TARGET_HOST_MS_WINDOWS int returnValue ; GLboolean boolValue ; #endif int nsamples = 0; switch (eWhat) { case GLUT_INIT_STATE: return fgState.Initialised; case GLUT_ELAPSED_TIME: return fgElapsedTime(); } FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutGet" ); /* XXX In chronological code add order. (WHY in that order?) */ switch( eWhat ) { /* Following values are stored in fgState and fgDisplay global structures */ case GLUT_SCREEN_WIDTH: return fgDisplay.ScreenWidth ; case GLUT_SCREEN_HEIGHT: return fgDisplay.ScreenHeight ; case GLUT_SCREEN_WIDTH_MM: return fgDisplay.ScreenWidthMM ; case GLUT_SCREEN_HEIGHT_MM: return fgDisplay.ScreenHeightMM; case GLUT_INIT_WINDOW_X: return fgState.Position.Use ? fgState.Position.X : -1 ; case GLUT_INIT_WINDOW_Y: return fgState.Position.Use ? fgState.Position.Y : -1 ; case GLUT_INIT_WINDOW_WIDTH: return fgState.Size.Use ? fgState.Size.X : -1 ; case GLUT_INIT_WINDOW_HEIGHT: return fgState.Size.Use ? fgState.Size.Y : -1 ; case GLUT_INIT_DISPLAY_MODE: return fgState.DisplayMode ; case GLUT_INIT_MAJOR_VERSION: return fgState.MajorVersion ; case GLUT_INIT_MINOR_VERSION: return fgState.MinorVersion ; case GLUT_INIT_FLAGS: return fgState.ContextFlags ; case GLUT_INIT_PROFILE: return fgState.ContextProfile ; #if TARGET_HOST_POSIX_X11 /* * The window/context specific queries are handled mostly by * fghGetConfig(). */ case GLUT_WINDOW_NUM_SAMPLES: #ifdef GLX_VERSION_1_3 glGetIntegerv(GL_SAMPLES, &nsamples); #endif return nsamples; /* * The rest of GLX queries under X are general enough to use a macro to * check them */ # define GLX_QUERY(a,b) case a: return fghGetConfig( b ); GLX_QUERY( GLUT_WINDOW_RGBA, GLX_RGBA ); GLX_QUERY( GLUT_WINDOW_DOUBLEBUFFER, GLX_DOUBLEBUFFER ); GLX_QUERY( GLUT_WINDOW_BUFFER_SIZE, GLX_BUFFER_SIZE ); GLX_QUERY( GLUT_WINDOW_STENCIL_SIZE, GLX_STENCIL_SIZE ); GLX_QUERY( GLUT_WINDOW_DEPTH_SIZE, GLX_DEPTH_SIZE ); GLX_QUERY( GLUT_WINDOW_RED_SIZE, GLX_RED_SIZE ); GLX_QUERY( GLUT_WINDOW_GREEN_SIZE, GLX_GREEN_SIZE ); GLX_QUERY( GLUT_WINDOW_BLUE_SIZE, GLX_BLUE_SIZE ); GLX_QUERY( GLUT_WINDOW_ALPHA_SIZE, GLX_ALPHA_SIZE ); GLX_QUERY( GLUT_WINDOW_ACCUM_RED_SIZE, GLX_ACCUM_RED_SIZE ); GLX_QUERY( GLUT_WINDOW_ACCUM_GREEN_SIZE, GLX_ACCUM_GREEN_SIZE ); GLX_QUERY( GLUT_WINDOW_ACCUM_BLUE_SIZE, GLX_ACCUM_BLUE_SIZE ); GLX_QUERY( GLUT_WINDOW_ACCUM_ALPHA_SIZE, GLX_ACCUM_ALPHA_SIZE ); GLX_QUERY( GLUT_WINDOW_STEREO, GLX_STEREO ); # undef GLX_QUERY /* Colormap size is handled in a bit different way than all the rest */ case GLUT_WINDOW_COLORMAP_SIZE: if( (fghGetConfig( GLX_RGBA )) || (fgStructure.CurrentWindow == NULL) ) { /* * We've got a RGBA visual, so there is no colormap at all. * The other possibility is that we have no current window set. */ return 0; } else { const GLXFBConfig * fbconfig = fgStructure.CurrentWindow->Window.FBConfig; XVisualInfo * visualInfo = glXGetVisualFromFBConfig( fgDisplay.Display, *fbconfig ); const int result = visualInfo->visual->map_entries; XFree(visualInfo); return result; } /* * Those calls are somewhat similiar, as they use XGetWindowAttributes() * function */ case GLUT_WINDOW_X: case GLUT_WINDOW_Y: case GLUT_WINDOW_BORDER_WIDTH: case GLUT_WINDOW_HEADER_HEIGHT: { int x, y; Window w; if( fgStructure.CurrentWindow == NULL ) return 0; XTranslateCoordinates( fgDisplay.Display, fgStructure.CurrentWindow->Window.Handle, fgDisplay.RootWindow, 0, 0, &x, &y, &w); switch ( eWhat ) { case GLUT_WINDOW_X: return x; case GLUT_WINDOW_Y: return y; } if ( w == 0 ) return 0; XTranslateCoordinates( fgDisplay.Display, fgStructure.CurrentWindow->Window.Handle, w, 0, 0, &x, &y, &w); switch ( eWhat ) { case GLUT_WINDOW_BORDER_WIDTH: return x; case GLUT_WINDOW_HEADER_HEIGHT: return y; } } case GLUT_WINDOW_WIDTH: case GLUT_WINDOW_HEIGHT: { XWindowAttributes winAttributes; if( fgStructure.CurrentWindow == NULL ) return 0; XGetWindowAttributes( fgDisplay.Display, fgStructure.CurrentWindow->Window.Handle, &winAttributes ); switch ( eWhat ) { case GLUT_WINDOW_WIDTH: return winAttributes.width ; case GLUT_WINDOW_HEIGHT: return winAttributes.height ; } } /* I do not know yet if there will be a fgChooseVisual() function for Win32 */ case GLUT_DISPLAY_MODE_POSSIBLE: { /* We should not have to call fgChooseFBConfig again here. */ GLXFBConfig * fbconfig; int isPossible; fbconfig = fgChooseFBConfig(); if (fbconfig == NULL) { isPossible = 0; } else { isPossible = 1; XFree(fbconfig); } return isPossible; } /* This is system-dependant */ case GLUT_WINDOW_FORMAT_ID: if( fgStructure.CurrentWindow == NULL ) return 0; return fghGetConfig( GLX_VISUAL_ID ); #elif TARGET_HOST_MS_WINDOWS case GLUT_WINDOW_NUM_SAMPLES: glGetIntegerv(WGL_SAMPLES_ARB, &nsamples); return nsamples; /* Handle the OpenGL inquiries */ case GLUT_WINDOW_RGBA: #if defined(_WIN32_WCE) boolValue = (GLboolean)0; /* WinCE doesn't support this feature */ #else glGetBooleanv ( GL_RGBA_MODE, &boolValue ); returnValue = boolValue ? 1 : 0; #endif return returnValue; case GLUT_WINDOW_DOUBLEBUFFER: #if defined(_WIN32_WCE) boolValue = (GLboolean)0; /* WinCE doesn't support this feature */ #else glGetBooleanv ( GL_DOUBLEBUFFER, &boolValue ); returnValue = boolValue ? 1 : 0; #endif return returnValue; case GLUT_WINDOW_STEREO: #if defined(_WIN32_WCE) boolValue = (GLboolean)0; /* WinCE doesn't support this feature */ #else glGetBooleanv ( GL_STEREO, &boolValue ); returnValue = boolValue ? 1 : 0; #endif return returnValue; case GLUT_WINDOW_RED_SIZE: glGetIntegerv ( GL_RED_BITS, &returnValue ); return returnValue; case GLUT_WINDOW_GREEN_SIZE: glGetIntegerv ( GL_GREEN_BITS, &returnValue ); return returnValue; case GLUT_WINDOW_BLUE_SIZE: glGetIntegerv ( GL_BLUE_BITS, &returnValue ); return returnValue; case GLUT_WINDOW_ALPHA_SIZE: glGetIntegerv ( GL_ALPHA_BITS, &returnValue ); return returnValue; case GLUT_WINDOW_ACCUM_RED_SIZE: #if defined(_WIN32_WCE) returnValue = 0; /* WinCE doesn't support this feature */ #else glGetIntegerv ( GL_ACCUM_RED_BITS, &returnValue ); #endif return returnValue; case GLUT_WINDOW_ACCUM_GREEN_SIZE: #if defined(_WIN32_WCE) returnValue = 0; /* WinCE doesn't support this feature */ #else glGetIntegerv ( GL_ACCUM_GREEN_BITS, &returnValue ); #endif return returnValue; case GLUT_WINDOW_ACCUM_BLUE_SIZE: #if defined(_WIN32_WCE) returnValue = 0; /* WinCE doesn't support this feature */ #else glGetIntegerv ( GL_ACCUM_BLUE_BITS, &returnValue ); #endif return returnValue; case GLUT_WINDOW_ACCUM_ALPHA_SIZE: #if defined(_WIN32_WCE) returnValue = 0; /* WinCE doesn't support this feature */ #else glGetIntegerv ( GL_ACCUM_ALPHA_BITS, &returnValue ); #endif return returnValue; case GLUT_WINDOW_DEPTH_SIZE: glGetIntegerv ( GL_DEPTH_BITS, &returnValue ); return returnValue; case GLUT_WINDOW_BUFFER_SIZE: returnValue = 1 ; /* ????? */ return returnValue; case GLUT_WINDOW_STENCIL_SIZE: returnValue = 0 ; /* ????? */ return returnValue; case GLUT_WINDOW_X: case GLUT_WINDOW_Y: case GLUT_WINDOW_WIDTH: case GLUT_WINDOW_HEIGHT: { /* * There is considerable confusion about the "right thing to * do" concerning window size and position. GLUT itself is * not consistent between Windows and UNIX/X11; since * platform independence is a virtue for "freeglut", we * decided to break with GLUT's behaviour. * * Under UNIX/X11, it is apparently not possible to get the * window border sizes in order to subtract them off the * window's initial position until some time after the window * has been created. Therefore we decided on the following * behaviour, both under Windows and under UNIX/X11: * - When you create a window with position (x,y) and size * (w,h), the upper left hand corner of the outside of the * window is at (x,y) and the size of the drawable area is * (w,h). * - When you query the size and position of the window--as * is happening here for Windows--"freeglut" will return * the size of the drawable area--the (w,h) that you * specified when you created the window--and the coordinates * of the upper left hand corner of the drawable * area--which is NOT the (x,y) you specified. */ RECT winRect; freeglut_return_val_if_fail( fgStructure.CurrentWindow != NULL, 0 ); /* * We need to call GetWindowRect() first... * (this returns the pixel coordinates of the outside of the window) */ GetWindowRect( fgStructure.CurrentWindow->Window.Handle, &winRect ); /* ...then we've got to correct the results we've just received... */ #if !defined(_WIN32_WCE) if ( ( fgStructure.GameModeWindow != fgStructure.CurrentWindow ) && ( fgStructure.CurrentWindow->Parent == NULL ) && ( ! fgStructure.CurrentWindow->IsMenu ) ) { winRect.left += GetSystemMetrics( SM_CXSIZEFRAME ); winRect.right -= GetSystemMetrics( SM_CXSIZEFRAME ); winRect.top += GetSystemMetrics( SM_CYSIZEFRAME ) + GetSystemMetrics( SM_CYCAPTION ); winRect.bottom -= GetSystemMetrics( SM_CYSIZEFRAME ); } #endif /* !defined(_WIN32_WCE) */ switch( eWhat ) { case GLUT_WINDOW_X: return winRect.left ; case GLUT_WINDOW_Y: return winRect.top ; case GLUT_WINDOW_WIDTH: return winRect.right - winRect.left; case GLUT_WINDOW_HEIGHT: return winRect.bottom - winRect.top; } } break; case GLUT_WINDOW_BORDER_WIDTH : #if defined(_WIN32_WCE) return 0; #else return GetSystemMetrics( SM_CXSIZEFRAME ); #endif /* !defined(_WIN32_WCE) */ case GLUT_WINDOW_HEADER_HEIGHT : #if defined(_WIN32_WCE) return 0; #else return GetSystemMetrics( SM_CYCAPTION ); #endif /* defined(_WIN32_WCE) */ case GLUT_DISPLAY_MODE_POSSIBLE: #if defined(_WIN32_WCE) return 0; #else return fgSetupPixelFormat( fgStructure.CurrentWindow, GL_TRUE, PFD_MAIN_PLANE ); #endif /* defined(_WIN32_WCE) */ case GLUT_WINDOW_FORMAT_ID: #if !defined(_WIN32_WCE) if( fgStructure.CurrentWindow != NULL ) return GetPixelFormat( fgStructure.CurrentWindow->Window.Device ); #endif /* defined(_WIN32_WCE) */ return 0; #endif /* The window structure queries */ case GLUT_WINDOW_PARENT: if( fgStructure.CurrentWindow == NULL ) return 0; if( fgStructure.CurrentWindow->Parent == NULL ) return 0; return fgStructure.CurrentWindow->Parent->ID; case GLUT_WINDOW_NUM_CHILDREN: if( fgStructure.CurrentWindow == NULL ) return 0; return fgListLength( &fgStructure.CurrentWindow->Children ); case GLUT_WINDOW_CURSOR: if( fgStructure.CurrentWindow == NULL ) return 0; return fgStructure.CurrentWindow->State.Cursor; case GLUT_MENU_NUM_ITEMS: if( fgStructure.CurrentMenu == NULL ) return 0; return fgListLength( &fgStructure.CurrentMenu->Entries ); case GLUT_ACTION_ON_WINDOW_CLOSE: return fgState.ActionOnWindowClose; case GLUT_VERSION : return VERSION_MAJOR * 10000 + VERSION_MINOR * 100 + VERSION_PATCH; case GLUT_RENDERING_CONTEXT: return fgState.UseCurrentContext ? GLUT_USE_CURRENT_CONTEXT : GLUT_CREATE_NEW_CONTEXT; case GLUT_DIRECT_RENDERING: return fgState.DirectContext; case GLUT_FULL_SCREEN: return fghCheckFullScreen(); case GLUT_AUX: return fgState.AuxiliaryBufferNumber; case GLUT_MULTISAMPLE: return fgState.SampleNumber; default: fgWarning( "glutGet(): missing enum handle %d", eWhat ); break; } return -1; }
/** * Creates a Pixmap and GLXPixmap with tex_data as the contents. */ static GLXPixmap create_pixmap(GLenum format) { static const int rgb_fb_config_attribs[] = { GLX_RENDER_TYPE, GLX_RGBA_BIT, GLX_RED_SIZE, 8, GLX_GREEN_SIZE, 8, GLX_BLUE_SIZE, 8, GLX_ALPHA_SIZE, 0, GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT, GLX_BIND_TO_TEXTURE_RGB_EXT, 1, None }; static const int rgba_fb_config_attribs[] = { GLX_RENDER_TYPE, GLX_RGBA_BIT, GLX_RED_SIZE, 8, GLX_GREEN_SIZE, 8, GLX_BLUE_SIZE, 8, GLX_ALPHA_SIZE, 8, GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT, GLX_BIND_TO_TEXTURE_RGBA_EXT, 1, None }; static const int rgb_pixmap_attribs[] = { GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT, GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGB_EXT, None }; static const int rgba_pixmap_attribs[] = { GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT, GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGBA_EXT, None }; static const int *fb_config_attribs, *pixmap_attribs; GLXFBConfig *fb_configs; GLXFBConfig fb_config; int n_fb_configs; Pixmap pixmap; GLXPixmap glx_pixmap; XVisualInfo *vis; XRenderPictFormat *render_format; Picture picture; if (format == GL_RGBA) { fb_config_attribs = rgba_fb_config_attribs; pixmap_attribs = rgba_pixmap_attribs; render_format = XRenderFindStandardFormat(dpy, PictStandardARGB32); } else { fb_config_attribs = rgb_fb_config_attribs; pixmap_attribs = rgb_pixmap_attribs; render_format = XRenderFindStandardFormat(dpy, PictStandardRGB24); } fb_configs = glXChooseFBConfig(dpy, DefaultScreen(dpy), fb_config_attribs, &n_fb_configs); if (fb_configs == NULL || n_fb_configs < 1) { fprintf(stderr, "No %s TFP FB config found\n", format == GL_RGBA ? "RGBA" : "RGB"); return None; } fb_config = fb_configs[n_fb_configs - 1]; pixmap = XCreatePixmap(dpy, RootWindow(dpy, DefaultScreen(dpy)), 2, 2, render_format->depth); picture = XRenderCreatePicture(dpy, pixmap, render_format, 0, NULL); glx_pixmap = glXCreatePixmap(dpy, fb_config, pixmap, pixmap_attribs); vis = glXGetVisualFromFBConfig(dpy, fb_config); set_pixel(dpy, picture, 0, 0, tex_data[0]); set_pixel(dpy, picture, 1, 0, tex_data[1]); set_pixel(dpy, picture, 0, 1, tex_data[2]); set_pixel(dpy, picture, 1, 1, tex_data[3]); XFree(fb_configs); XFree(vis); return glx_pixmap; }
int main(int argc, char* argv[]) { Display *display = XOpenDisplay(NULL); if (!display) fail("Failed to open X display\n"); checkGlxVersion(display); auto bestFbc = chooseFBConfig(display); // Get a visual XVisualInfo *vi = glXGetVisualFromFBConfig(display, bestFbc); printf("Chosen visual ID = 0x%lx\n", vi->visualid); printf("Creating colormap\n"); XSetWindowAttributes swa; Colormap cmap; swa.colormap = cmap = XCreateColormap(display, RootWindow(display, vi->screen), vi->visual, AllocNone); swa.background_pixmap = None ; swa.border_pixel = 0; swa.event_mask = StructureNotifyMask; printf("Creating window\n"); Window win = XCreateWindow(display, RootWindow(display, vi->screen), 0, 0, 100, 100, 0, vi->depth, InputOutput, vi->visual, CWBorderPixel|CWColormap|CWEventMask, &swa); if (!win) fail("Failed to create window.\n"); // Done with the visual info data XFree(vi); XStoreName(display, win, "GL 3.0 Window"); printf("Mapping window\n"); XMapWindow(display, win); auto context = createContext(display, bestFbc); printf("Making context current\n"); glXMakeCurrent(display, win, context); initGlew(); GLuint tex_; GLuint fbo_; glGenTextures(1, &tex_); glBindTexture(GL_TEXTURE_2D, tex_); glGenFramebuffers(1, &fbo_); glBindFramebuffer(GL_FRAMEBUFFER, fbo_); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex_, 0); printGlErrors(); glBindTexture(GL_TEXTURE_2D, tex_); glTexStorage2D(GL_TEXTURE_2D, 2, GL_RGBA8, 2, 2); char source_pixels[16] = { 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4 }; printGlErrors(); printf("Crash here\n"); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, source_pixels); printf("Crashed :( \n"); printGlErrors(); glCheckFramebufferStatus(GL_FRAMEBUFFER); char pixels[16] = {0}; glReadPixels(0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, pixels); glCheckFramebufferStatus(GL_FRAMEBUFFER); printGlErrors(); glXMakeCurrent(display, 0, 0); glXDestroyContext(display, context); XDestroyWindow(display, win); XFreeColormap(display, cmap); XCloseDisplay(display); printf("Test success\n"); return 0; }
C4Window* C4Window::Init(WindowKind windowKind, C4AbstractApp * pApp, const char * Title, const C4Rect * size) { Active = true; #ifdef GDK_WINDOWING_X11 if(!FindFBConfig(Config.Graphics.MultiSampling, &Info)) { // Disable multisampling if we don't find a visual which // supports the currently configured setting. if(!FindFBConfig(0, &Info)) return NULL; Config.Graphics.MultiSampling = 0; } #endif assert(!window); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); if (windowKind == W_Viewport) { C4ViewportWindow * vw = static_cast<C4ViewportWindow *>(this); // Cannot just use ScrolledWindow because this would just move // the GdkWindow of the DrawingArea. GtkWidget* table = gtk_grid_new(); render_widget = gtk_drawing_area_new(); gtk_widget_set_hexpand(GTK_WIDGET(render_widget), true); gtk_widget_set_vexpand(GTK_WIDGET(render_widget), true); gtk_grid_attach(GTK_GRID(table), GTK_WIDGET(render_widget), 0, 0, 1, 1); vw->h_scrollbar = gtk_scrollbar_new(GTK_ORIENTATION_HORIZONTAL, NULL); gtk_grid_attach(GTK_GRID(table), vw->h_scrollbar, 0, 1, 1, 1); vw->v_scrollbar = gtk_scrollbar_new(GTK_ORIENTATION_VERTICAL, NULL); gtk_grid_attach(GTK_GRID(table), vw->v_scrollbar, 1, 0, 1, 1); GtkAdjustment* adjustment = gtk_range_get_adjustment(GTK_RANGE(vw->h_scrollbar)); g_signal_connect( G_OBJECT(adjustment), "value-changed", G_CALLBACK(OnHScrollStatic), this ); adjustment = gtk_range_get_adjustment(GTK_RANGE(vw->v_scrollbar)); g_signal_connect( G_OBJECT(adjustment), "value-changed", G_CALLBACK(OnVScrollStatic), this ); gtk_container_add(GTK_CONTAINER(window), table); gtk_widget_add_events(GTK_WIDGET(window), GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK | GDK_POINTER_MOTION_MASK); gtk_drag_dest_set(GTK_WIDGET(render_widget), GTK_DEST_DEFAULT_ALL, drag_drop_entries, 1, GDK_ACTION_COPY); g_signal_connect(G_OBJECT(render_widget), "drag-data-received", G_CALLBACK(OnDragDataReceivedStatic), this); g_signal_connect(G_OBJECT(render_widget), "draw", G_CALLBACK(OnExposeStatic), this); g_signal_connect(G_OBJECT(window), "key-press-event", G_CALLBACK(OnKeyPressStatic), this); g_signal_connect(G_OBJECT(window), "key-release-event", G_CALLBACK(OnKeyReleaseStatic), this); g_signal_connect(G_OBJECT(window), "scroll-event", G_CALLBACK(OnScrollVW), this); g_signal_connect(G_OBJECT(window), "button-press-event", G_CALLBACK(OnButtonPressStatic), this); g_signal_connect(G_OBJECT(window), "button-release-event", G_CALLBACK(OnButtonReleaseStatic), this); g_signal_connect(G_OBJECT(window), "motion-notify-event", G_CALLBACK(OnMotionNotifyStatic), this); g_signal_connect(G_OBJECT(window), "key-press-event", G_CALLBACK(OnKeyPress), this); g_signal_connect(G_OBJECT(window), "key-release-event", G_CALLBACK(OnKeyRelease), this); g_signal_connect(G_OBJECT(window), "configure-event", G_CALLBACK(OnConfigureStatic), this); g_signal_connect(G_OBJECT(window), "realize", G_CALLBACK(OnRealizeStatic), this); g_signal_connect_after(G_OBJECT(render_widget), "configure-event", G_CALLBACK(OnConfigureDareaStatic), this); #if !GTK_CHECK_VERSION(3,10,0) // do not draw the default background gtk_widget_set_double_buffered (GTK_WIDGET(render_widget), false); #endif gtk_window_set_transient_for(GTK_WINDOW(window), GTK_WINDOW(Console.window)); #if !GTK_CHECK_VERSION(3,14,0) gtk_window_set_has_resize_grip(GTK_WINDOW(window), false); #endif } else if (windowKind == W_Fullscreen) { render_widget = gtk_drawing_area_new(); gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(render_widget)); g_signal_connect(G_OBJECT(window), "configure-event", G_CALLBACK(OnConfigureNotify), this); g_signal_connect(G_OBJECT(window), "focus-in-event", G_CALLBACK(OnFocusInFS), this); g_signal_connect(G_OBJECT(window), "focus-out-event", G_CALLBACK(OnFocusOutFS), this); g_signal_connect(G_OBJECT(window), "unmap-event", G_CALLBACK(OnFocusOutFS), this); g_signal_connect(G_OBJECT(window), "button-press-event", G_CALLBACK(OnButtonPressFS), this); g_signal_connect(G_OBJECT(window), "button-release-event", G_CALLBACK(OnButtonRelease), this); g_signal_connect(G_OBJECT(window), "motion-notify-event", G_CALLBACK(OnMotionNotify), this); g_signal_connect(G_OBJECT(window), "key-press-event", G_CALLBACK(OnKeyPress), this); g_signal_connect(G_OBJECT(window), "key-release-event", G_CALLBACK(OnKeyRelease), this); g_signal_connect(G_OBJECT(window), "scroll-event", G_CALLBACK(OnScroll), this); gtk_widget_add_events(GTK_WIDGET(window), GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK); #if !GTK_CHECK_VERSION(3,10,0) gtk_widget_set_double_buffered (GTK_WIDGET(render_widget), false); #endif GValue val = {0,{{0}}}; g_value_init (&val, G_TYPE_BOOLEAN); g_value_set_boolean (&val, true); g_object_set_property (G_OBJECT (render_widget), "can-focus", &val); g_object_set_property (G_OBJECT (window), "can-focus", &val); g_value_unset (&val); #if !GTK_CHECK_VERSION(3,14,0) gtk_window_set_has_resize_grip(GTK_WINDOW(window), false); #endif } else if (windowKind == W_GuiWindow) { render_widget = window; g_signal_connect(G_OBJECT(window), "button-press-event", G_CALLBACK(OnButtonPressGD), this); g_signal_connect(G_OBJECT(window), "button-release-event", G_CALLBACK(OnButtonReleaseGD), this); g_signal_connect(G_OBJECT(window), "motion-notify-event", G_CALLBACK(OnMotionNotifyGD), this); g_signal_connect(G_OBJECT(window), "configure-event", G_CALLBACK(OnConfigureGD), this); g_signal_connect(G_OBJECT(window), "scroll-event", G_CALLBACK(OnScroll), this); gtk_window_set_transient_for(GTK_WINDOW(window), GTK_WINDOW(Console.window)); #if !GTK_CHECK_VERSION(3,14,0) gtk_window_set_has_resize_grip(GTK_WINDOW(window), false); #endif } else if (windowKind == W_Console) { render_widget = window; } assert(window); assert(render_widget); // Override gtk's default to match name/class of the XLib windows gtk_window_set_wmclass(GTK_WINDOW(window), C4ENGINENAME, C4ENGINENAME); gtk_window_set_default_size(GTK_WINDOW(window), size->Wdt, size->Hgt); g_signal_connect(G_OBJECT(window), "delete-event", G_CALLBACK(OnDelete), this); handlerDestroy = g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(OnDestroyStatic), this); gtk_widget_add_events(GTK_WIDGET(window), GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_SCROLL_MASK); // TODO: It would be nice to support GDK_SCROLL_SMOOTH_MASK and // smooth scrolling for scrolling in menus, however that should not // change the scroll wheel behaviour ingame for zooming or // inventory change. Note that when both GDK_SCROLL_MASK and // GDK_SMOOTH_SCROLL_MASK are enabled, both type of scroll events // are reported, so one needs to make sure to not double-process them. // It would be nice to have smooth scrolling also e.g. for zooming // ingame, but it probably requires the notion of smooth scrolling // other parts of the engine as well. #ifdef GDK_WINDOWING_X11 GdkScreen * scr = gtk_widget_get_screen(GTK_WIDGET(render_widget)); Display * const dpy = gdk_x11_display_get_xdisplay(gdk_display_get_default()); XVisualInfo *vis_info = glXGetVisualFromFBConfig(dpy, Info); assert(vis_info); GdkVisual * vis = gdk_x11_screen_lookup_visual(scr, vis_info->visualid); XFree(vis_info); gtk_widget_set_visual(GTK_WIDGET(render_widget),vis); #endif gtk_widget_show_all(GTK_WIDGET(window)); // XVisualInfo vitmpl; int blub; // vitmpl.visual = gdk_x11_visual_get_xvisual(gtk_widget_get_visual(window)); // vitmpl.visualid = XVisualIDFromVisual(vitmpl.visual); // Info = XGetVisualInfo(dpy, VisualIDMask, &vitmpl, &blub); // printf("%p\n", gtk_widget_get_visual(render_widget)); // Info = gdk_x11_visual_get_xvisual(gtk_widget_get_visual(render_widget)); // Default icon has been set right after gtk_init(), // so we don't need to take care about setting the icon here. SetTitle(Title); // Wait until window is mapped to get the window's XID gtk_widget_show_now(GTK_WIDGET(window)); GdkWindow* render_gdk_wnd; if (GTK_IS_LAYOUT(render_widget)) render_gdk_wnd = gtk_layout_get_bin_window(GTK_LAYOUT(render_widget)); else render_gdk_wnd = gtk_widget_get_window(GTK_WIDGET(render_widget)); #ifdef GDK_WINDOWING_X11 renderwnd = GDK_WINDOW_XID(render_gdk_wnd); #elif defined(GDK_WINDOWING_WIN32) renderwnd = reinterpret_cast<HWND>(gdk_win32_window_get_handle(render_gdk_wnd)); #endif // Make sure the window is shown and ready to be rendered into, // this avoids an async X error. gdk_flush(); if (windowKind == W_Fullscreen) gdk_window_set_cursor(gtk_widget_get_window(GTK_WIDGET(render_widget)), gdk_cursor_new_for_display(gdk_display_get_default(), GDK_BLANK_CURSOR)); return this; }
const GrGLInterface* SkNativeGLContext::createGLContext() { fDisplay = XOpenDisplay(0); if (!fDisplay) { SkDebugf("Failed to open X display.\n"); this->destroyGLContext(); return NULL; } // Get a matching FB config static int visual_attribs[] = { GLX_X_RENDERABLE , True, GLX_DRAWABLE_TYPE , GLX_PIXMAP_BIT, None }; #ifdef GLX_1_3 //SkDebugf("Getting matching framebuffer configs.\n"); int fbcount; GLXFBConfig *fbc = glXChooseFBConfig(fDisplay, DefaultScreen(fDisplay), visual_attribs, &fbcount); if (!fbc) { SkDebugf("Failed to retrieve a framebuffer config.\n"); this->destroyGLContext(); return NULL; } //SkDebugf("Found %d matching FB configs.\n", fbcount); // Pick the FB config/visual with the most samples per pixel //SkDebugf("Getting XVisualInfos.\n"); int best_fbc = -1, best_num_samp = -1; int i; for (i = 0; i < fbcount; ++i) { XVisualInfo *vi = glXGetVisualFromFBConfig(fDisplay, fbc[i]); if (vi) { int samp_buf, samples; glXGetFBConfigAttrib(fDisplay, fbc[i], GLX_SAMPLE_BUFFERS, &samp_buf); glXGetFBConfigAttrib(fDisplay, fbc[i], GLX_SAMPLES, &samples); //SkDebugf(" Matching fbconfig %d, visual ID 0x%2x: SAMPLE_BUFFERS = %d," // " SAMPLES = %d\n", // i, (unsigned int)vi->visualid, samp_buf, samples); if (best_fbc < 0 || (samp_buf && samples > best_num_samp)) best_fbc = i, best_num_samp = samples; } XFree(vi); } GLXFBConfig bestFbc = fbc[best_fbc]; // Be sure to free the FBConfig list allocated by glXChooseFBConfig() XFree(fbc); // Get a visual XVisualInfo *vi = glXGetVisualFromFBConfig(fDisplay, bestFbc); //SkDebugf("Chosen visual ID = 0x%x\n", (unsigned int)vi->visualid); #else int numVisuals; XVisualInfo visTemplate, *visReturn; visReturn = XGetVisualInfo(fDisplay, VisualNoMask, &visTemplate, &numVisuals); if (NULL == visReturn) { SkDebugf("Failed to get visual information.\n"); this->destroyGLContext(); return NULL; } int best = -1, best_num_samp = -1; for (int i = 0; i < numVisuals; ++i) { int samp_buf, samples; glXGetConfig(fDisplay, &visReturn[i], GLX_SAMPLE_BUFFERS, &samp_buf); glXGetConfig(fDisplay, &visReturn[i], GLX_SAMPLES, &samples); if (best < 0 || (samp_buf && samples > best_num_samp)) best = i, best_num_samp = samples; } XVisualInfo temp = visReturn[best]; XVisualInfo *vi = &temp; XFree(visReturn); #endif fPixmap = XCreatePixmap(fDisplay, RootWindow(fDisplay, vi->screen), 10, 10, vi->depth); if (!fPixmap) { SkDebugf("Failed to create pixmap.\n"); this->destroyGLContext(); return NULL; } fGlxPixmap = glXCreateGLXPixmap(fDisplay, vi, fPixmap); #ifdef GLX_1_3 // Done with the visual info data XFree(vi); #endif // Create the context // Install an X error handler so the application won't exit if GL 3.0 // context allocation fails. // // Note this error handler is global. // All display connections in all threads of a process use the same // error handler, so be sure to guard against other threads issuing // X commands while this code is running. ctxErrorOccurred = false; int (*oldHandler)(Display*, XErrorEvent*) = XSetErrorHandler(&ctxErrorHandler); // Get the default screen's GLX extension list const char *glxExts = glXQueryExtensionsString( fDisplay, DefaultScreen(fDisplay) ); // Check for the GLX_ARB_create_context extension string and the function. // If either is not present, use GLX 1.3 context creation method. if (!gluCheckExtension( reinterpret_cast<const GLubyte*>("GLX_ARB_create_context") , reinterpret_cast<const GLubyte*>(glxExts))) { //SkDebugf("GLX_ARB_create_context not found." // " Using old-style GLX context.\n"); #ifdef GLX_1_3 fContext = glXCreateNewContext(fDisplay, bestFbc, GLX_RGBA_TYPE, 0, True); #else fContext = glXCreateContext(fDisplay, vi, 0, True); #endif } #ifdef GLX_1_3 else { //SkDebugf("Creating context.\n"); PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC) glXGetProcAddressARB((GrGLubyte*)"glXCreateContextAttribsARB"); int context_attribs[] = { GLX_CONTEXT_MAJOR_VERSION_ARB, 3, GLX_CONTEXT_MINOR_VERSION_ARB, 0, //GLX_CONTEXT_FLAGS_ARB , GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, None }; fContext = glXCreateContextAttribsARB( fDisplay, bestFbc, 0, True, context_attribs ); // Sync to ensure any errors generated are processed. XSync(fDisplay, False); if (!ctxErrorOccurred && fContext) { //SkDebugf( "Created GL 3.0 context.\n" ); } else { // Couldn't create GL 3.0 context. // Fall back to old-style 2.x context. // When a context version below 3.0 is requested, // implementations will return the newest context version compatible // with OpenGL versions less than version 3.0. // GLX_CONTEXT_MAJOR_VERSION_ARB = 1 context_attribs[1] = 1; // GLX_CONTEXT_MINOR_VERSION_ARB = 0 context_attribs[3] = 0; ctxErrorOccurred = false; //SkDebugf("Failed to create GL 3.0 context." // " Using old-style GLX context.\n"); fContext = glXCreateContextAttribsARB( fDisplay, bestFbc, 0, True, context_attribs ); } } #endif // Sync to ensure any errors generated are processed. XSync(fDisplay, False); // Restore the original error handler XSetErrorHandler(oldHandler); if (ctxErrorOccurred || !fContext) { SkDebugf("Failed to create an OpenGL context.\n"); this->destroyGLContext(); return NULL; } // Verify that context is a direct context if (!glXIsDirect(fDisplay, fContext)) { //SkDebugf("Indirect GLX rendering context obtained.\n"); } else { //SkDebugf("Direct GLX rendering context obtained.\n"); } //SkDebugf("Making context current.\n"); if (!glXMakeCurrent(fDisplay, fGlxPixmap, fContext)) { SkDebugf("Could not set the context.\n"); this->destroyGLContext(); return NULL; } const GrGLInterface* interface = GrGLCreateNativeInterface(); if (!interface) { SkDebugf("Failed to create gl interface"); this->destroyGLContext(); return NULL; } return interface; }
// Create the OpenGL or OpenGL ES context // int _glfwCreateContext(_GLFWwindow* window, const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig) { int attribs[40]; GLXFBConfig native; GLXContext share = NULL; if (ctxconfig->share) share = ctxconfig->share->glx.context; if (!chooseFBConfig(fbconfig, &native)) { _glfwInputError(GLFW_PLATFORM_ERROR, "GLX: Failed to find a suitable GLXFBConfig"); return GL_FALSE; } // Retrieve the corresponding visual window->glx.visual = glXGetVisualFromFBConfig(_glfw.x11.display, native); if (!window->glx.visual) { _glfwInputError(GLFW_PLATFORM_ERROR, "GLX: Failed to retrieve visual for GLXFBConfig"); return GL_FALSE; } if (ctxconfig->api == GLFW_OPENGL_ES_API) { if (!_glfw.glx.ARB_create_context || !_glfw.glx.ARB_create_context_profile || !_glfw.glx.EXT_create_context_es2_profile) { _glfwInputError(GLFW_API_UNAVAILABLE, "GLX: OpenGL ES requested but GLX_EXT_create_context_es2_profile is unavailable"); return GL_FALSE; } } if (ctxconfig->forward) { if (!_glfw.glx.ARB_create_context) { _glfwInputError(GLFW_VERSION_UNAVAILABLE, "GLX: Forward compatibility requested but GLX_ARB_create_context_profile is unavailable"); return GL_FALSE; } } if (ctxconfig->profile) { if (!_glfw.glx.ARB_create_context || !_glfw.glx.ARB_create_context_profile) { _glfwInputError(GLFW_VERSION_UNAVAILABLE, "GLX: An OpenGL profile requested but GLX_ARB_create_context_profile is unavailable"); return GL_FALSE; } } _glfwGrabXErrorHandler(); if (_glfw.glx.ARB_create_context) { int index = 0, mask = 0, flags = 0, strategy = 0; if (ctxconfig->api == GLFW_OPENGL_API) { if (ctxconfig->forward) flags |= GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB; if (ctxconfig->profile) { if (ctxconfig->profile == GLFW_OPENGL_CORE_PROFILE) mask |= GLX_CONTEXT_CORE_PROFILE_BIT_ARB; else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE) mask |= GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; } } else mask |= GLX_CONTEXT_ES2_PROFILE_BIT_EXT; if (ctxconfig->debug) flags |= GLX_CONTEXT_DEBUG_BIT_ARB; if (ctxconfig->robustness) { if (_glfw.glx.ARB_create_context_robustness) { if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION) strategy = GLX_NO_RESET_NOTIFICATION_ARB; else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET) strategy = GLX_LOSE_CONTEXT_ON_RESET_ARB; flags |= GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB; } } if (ctxconfig->release) { if (_glfw.glx.ARB_context_flush_control) { if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_NONE) { setGLXattrib(GLX_CONTEXT_RELEASE_BEHAVIOR_ARB, GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB); } else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH) { setGLXattrib(GLX_CONTEXT_RELEASE_BEHAVIOR_ARB, GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB); } } } if (ctxconfig->major != 1 || ctxconfig->minor != 0) { // NOTE: Only request an explicitly versioned context when // necessary, as explicitly requesting version 1.0 does not // always return the highest available version setGLXattrib(GLX_CONTEXT_MAJOR_VERSION_ARB, ctxconfig->major); setGLXattrib(GLX_CONTEXT_MINOR_VERSION_ARB, ctxconfig->minor); } if (mask) setGLXattrib(GLX_CONTEXT_PROFILE_MASK_ARB, mask); if (flags) setGLXattrib(GLX_CONTEXT_FLAGS_ARB, flags); if (strategy) setGLXattrib(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, strategy); setGLXattrib(None, None); window->glx.context = _glfw.glx.CreateContextAttribsARB(_glfw.x11.display, native, share, True, attribs); if (!window->glx.context) { // HACK: This is a fallback for the broken Mesa implementation of // GLX_ARB_create_context_profile, which fails default 1.0 // context creation with a GLXBadProfileARB error in violation // of the extension spec if (_glfw.x11.errorCode == _glfw.glx.errorBase + GLXBadProfileARB && ctxconfig->api == GLFW_OPENGL_API && ctxconfig->profile == GLFW_OPENGL_ANY_PROFILE && ctxconfig->forward == GL_FALSE) { window->glx.context = createLegacyContext(window, native, share); } } } else window->glx.context = createLegacyContext(window, native, share); _glfwReleaseXErrorHandler(); if (!window->glx.context) { _glfwInputXError(GLFW_VERSION_UNAVAILABLE, "GLX: Failed to create context"); return GL_FALSE; } return GL_TRUE; }
MyWindow::MyWindow(const std::string &title,int width,int height) : initError(false),clientWidth(0),clientHeight(0),iconified(false),focused(true),sized(false), justCreated(true),mouseMoveCallback(0),inputCallback(0),lockCursor(false),foreground(true) { #ifdef WIN32 hglrc=0; hdc=0; // HINSTANCE hInstance=GetModuleHandle(0); WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance,MAKEINTRESOURCE(IDI_APPLICATION)); wcex.hCursor = LoadCursor(NULL,IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = NULL; #ifdef UNICODE wcex.lpszClassName = L"win32app"; #else wcex.lpszClassName = "win32app"; #endif wcex.hIconSm = LoadIcon(wcex.hInstance,MAKEINTRESOURCE(IDI_APPLICATION)); if(!RegisterClassEx(&wcex)) { std::cout << "MyWindow : Call to RegisterClassEx failed!\n"; } #ifdef UNICODE wchar_t title2[256]; MultiByteToWideChar(CP_ACP,0,title.c_str(),-1,title2,256); #else const char *title2=title.c_str(); #endif hWnd = CreateWindow(wcex.lpszClassName,title2,WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,CW_USEDEFAULT,width,height,NULL,NULL,hInstance,NULL); SetWindowLongPtr(hWnd,GWL_USERDATA,(LONG_PTR)this); ShowWindow(hWnd,SW_SHOW); // hdc= GetDC(hWnd); PIXELFORMATDESCRIPTOR pfd; ZeroMemory(&pfd,sizeof(pfd)); pfd.nSize = sizeof(pfd); pfd.nVersion = 1; pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_GENERIC_ACCELERATED | PFD_DOUBLEBUFFER; pfd.iPixelType = PFD_TYPE_RGBA; pfd.cColorBits = 24; pfd.cRedBits = pfd.cGreenBits = pfd.cBlueBits = 8; pfd.cDepthBits = 32; int iPixelFormat = ChoosePixelFormat(hdc,&pfd); if(iPixelFormat == 0) { std::cout << "MyWindow : ChoosePixelFormat failed.\n"; initError=true; return; } if(SetPixelFormat(hdc,iPixelFormat,&pfd) != TRUE) { std::cout << "MyWindow : SetPixelFormat failed.\n"; initError=true; return; } // HGLRC tempContext = wglCreateContext(hdc); wglMakeCurrent(hdc,tempContext); // PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB= (PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress("wglCreateContextAttribsARB"); PFNWGLSWAPINTERVALEXTPROC wglSwapInterval= (PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress("wglSwapIntervalEXT"); // wglMakeCurrent(0,0); wglDeleteContext(tempContext); // int attribs[] ={ WGL_CONTEXT_MAJOR_VERSION_ARB,3, WGL_CONTEXT_MINOR_VERSION_ARB,3, WGL_CONTEXT_FLAGS_ARB,0, 0 }; hglrc=wglCreateContextAttribsARB(hdc,0,attribs); for(int i=2;i>=0;i--) { if(!hglrc) { attribs[3]=i; hglrc=wglCreateContextAttribsARB(hdc,0,attribs); } } if(!hglrc) { std::cout << "OpenGL 3+ not supported.\n"; initError=true; return; } wglMakeCurrent(hdc,hglrc); wglSwapInterval(1); // RAWINPUTDEVICE Rid[2]; Rid[0].usUsagePage = (USHORT)0x01;//HID_USAGE_PAGE_GENERIC; Rid[0].usUsage = (USHORT)0x02;//HID_USAGE_GENERIC_MOUSE; Rid[0].dwFlags = RIDEV_INPUTSINK; Rid[0].hwndTarget = hWnd; Rid[1].usUsagePage = (USHORT)0x01;//HID_USAGE_PAGE_GENERIC; Rid[1].usUsage = (USHORT)0x06;//HID_USAGE_GENERIC_KEYBOARD; Rid[1].dwFlags = RIDEV_INPUTSINK; Rid[1].hwndTarget = hWnd; RegisterRawInputDevices(Rid,2,sizeof(RAWINPUTDEVICE)); // //inputCodeMap[65]=keyA; //inputCodeMap[68]=keyD; //inputCodeMap[83]=keyS; //inputCodeMap[87]=keyW; #endif #ifdef LINUX // bool ctxErrorOccurred=false; display = XOpenDisplay(NULL); if(!display) { std::cout << "Window : Failed to open X display.\n"; initError=true; return; } static int visual_attribs[] ={ GLX_X_RENDERABLE,True, GLX_DRAWABLE_TYPE,GLX_WINDOW_BIT, GLX_RENDER_TYPE,GLX_RGBA_BIT, GLX_X_VISUAL_TYPE,GLX_TRUE_COLOR, GLX_RED_SIZE,8, GLX_GREEN_SIZE,8, GLX_BLUE_SIZE,8, GLX_ALPHA_SIZE,8, GLX_DEPTH_SIZE,24, GLX_STENCIL_SIZE,8, GLX_DOUBLEBUFFER,True, //GLX_SAMPLE_BUFFERS , 1, //GLX_SAMPLES , 4, None }; int glx_major,glx_minor; if(!glXQueryVersion(display,&glx_major,&glx_minor) || ((glx_major == 1) && (glx_minor < 3)) || (glx_major < 1)) { std::cout << "Window : Invalid GLX version.\n"; initError=true; return; } int fbcount; GLXFBConfig* fbc = glXChooseFBConfig(display,DefaultScreen(display),visual_attribs,&fbcount); if(!fbc) { std::cout << "Window :Failed to retrieve a framebuffer config.\n"; initError=true; return; } int best_fbc = -1,worst_fbc = -1,best_num_samp = -1,worst_num_samp = 999; for(int i=0; i<fbcount; ++i) { XVisualInfo *vi = glXGetVisualFromFBConfig(display,fbc[i]); if(vi) { int samp_buf,samples; glXGetFBConfigAttrib(display,fbc[i],GLX_SAMPLE_BUFFERS,&samp_buf); glXGetFBConfigAttrib(display,fbc[i],GLX_SAMPLES,&samples); std::cout << "Matching fbconfig " << i <<", visual ID 0x" << vi->visualid << ": SAMPLE_BUFFERS = " << samp_buf <<", SAMPLES = " << samples <<"\n"; if(best_fbc < 0 || samp_buf && samples > best_num_samp) { best_fbc = i; best_num_samp = samples; } if(worst_fbc < 0 || !samp_buf || samples < worst_num_samp) { worst_fbc = i; worst_num_samp = samples; } } XFree(vi); } GLXFBConfig bestFbc = fbc[best_fbc]; XFree(fbc); XVisualInfo *vi = glXGetVisualFromFBConfig(display,bestFbc); std::cout << "Chosen visual ID = 0x" << vi->visualid <<"\n"; XSetWindowAttributes swa; swa.colormap = cmap = XCreateColormap(display, RootWindow(display,vi->screen), vi->visual,AllocNone); swa.background_pixmap = None; swa.border_pixel = 0; swa.event_mask = ExposureMask | VisibilityChangeMask |KeyPressMask | PointerMotionMask |StructureNotifyMask; swa.bit_gravity = StaticGravity; win = XCreateWindow(display,RootWindow(display,vi->screen), 0,0,100,100,0,vi->depth,InputOutput, vi->visual, CWBorderPixel|CWColormap|CWEventMask,&swa); if(!win) { std::cout << "Window : Failed to create window.\n"; initError=true; return; } XFree(vi); XStoreName(display,win,title.c_str()); XMapWindow(display,win); const char *glxExts = glXQueryExtensionsString(display,DefaultScreen(display)); glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0; glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc) glXGetProcAddressARB((const GLubyte *) "glXCreateContextAttribsARB"); ctx = 0; ctxErrorOccurred = false; int(*oldHandler)(Display*,XErrorEvent*) = XSetErrorHandler(&ctxErrorHandler); if(!isExtensionSupported(glxExts,"GLX_ARB_create_context") || !glXCreateContextAttribsARB) { std::cout << "Window : glXCreateContextAttribsARB() not found.\n"; initError=true; return; } else { int context_attribs[] ={ GLX_CONTEXT_MAJOR_VERSION_ARB,3, GLX_CONTEXT_MINOR_VERSION_ARB,0, GLX_CONTEXT_FLAGS_ARB,0, None }; ctx = glXCreateContextAttribsARB(display,bestFbc,0, True,context_attribs); XSync(display,False); if(!ctxErrorOccurred && ctx) { std::cout << "Created GL 3.0 context\n"; } else { std::cout << "Window : Failed to create GL 3.0 context.\n"; initError=true; return; } } // XSync(display,False); XSetErrorHandler(oldHandler); if(ctxErrorOccurred || !ctx) { std::cout << "Window : Failed to create an OpenGL context.\n"; initError=true; return; } // Verifying that context is a direct context if(!glXIsDirect(display,ctx)) { std::cout << "Indirect GLX rendering context obtained.\n"; } else { std::cout << "Direct GLX rendering context obtained.\n"; } // glXMakeCurrent(display,win,ctx); if(PFNGLXSWAPINTERVALMESAPROC glXSwapIntervalMESA= (PFNGLXSWAPINTERVALMESAPROC) glXGetProcAddressARB((const GLubyte *)"glXSwapIntervalMESA")) { glXSwapIntervalMESA(1); } else if(PFNGLXSWAPINTERVALEXTPROC glXSwapIntervalEXT= (PFNGLXSWAPINTERVALEXTPROC) glXGetProcAddressARB((const GLubyte *)"glXSwapIntervalEXT")) { glXSwapIntervalEXT(display,glXGetCurrentDrawable(),1); } else if(PFNGLXSWAPINTERVALSGIPROC glXSwapIntervalSGI= (PFNGLXSWAPINTERVALSGIPROC) glXGetProcAddressARB((const GLubyte *)"glXSwapIntervalSGI")) { glXSwapIntervalSGI(1); } #endif }
bool RenderImageImplPBuffer::Create(unsigned int width, unsigned int height, unsigned int, bool depthBuffer) { // Store the dimensions myWidth = width; myHeight = height; // Define the PBuffer attributes int visualAttributes[] = { GLX_RENDER_TYPE, GLX_RGBA_BIT, GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT, GLX_RED_SIZE, 8, GLX_GREEN_SIZE, 8, GLX_BLUE_SIZE, 8, GLX_ALPHA_SIZE, 8, GLX_DEPTH_SIZE, (depthBuffer ? 24 : 0), 0 }; int PBufferAttributes[] = { GLX_PBUFFER_WIDTH, width, GLX_PBUFFER_HEIGHT, height, 0 }; // Get the available FB configurations int nbConfigs = 0; GLXFBConfig* configs = glXChooseFBConfigSGIX(myDisplay, DefaultScreen(myDisplay), visualAttributes, &nbConfigs); if (!configs || !nbConfigs) { Err() << "Impossible to create render image (failed to find a suitable pixel format for PBuffer)" << std::endl; return false; } // Create the P-Buffer myPBuffer = glXCreateGLXPbufferSGIX(myDisplay, configs[0], width, height, PBufferAttributes); if (!myPBuffer) { Err() << "Impossible to create render image (failed to create the OpenGL PBuffer)" << std::endl; XFree(configs); return false; } // Check the actual size of the P-Buffer unsigned int actualWidth, actualHeight; glXQueryGLXPbufferSGIX(myDisplay, myPBuffer, GLX_WIDTH_SGIX, &actualWidth); glXQueryGLXPbufferSGIX(myDisplay, myPBuffer, GLX_HEIGHT_SGIX, &actualHeight); if ((actualWidth != width) || (actualHeight != height)) { Err() << "Impossible to create render image (failed to match the requested size). " << "Size: " << actualWidth << "x" << actualHeight << " - " << "Requested: " << width << "x" << height << std::endl; XFree(configs); return false; } // We'll have to share the P-Buffer context with the current context GLXDrawable currentDrawable = glXGetCurrentDrawable(); GLXContext currentContext = glXGetCurrentContext(); if (currentContext) glXMakeCurrent(myDisplay, NULL, NULL); // Create the context XVisualInfo* visual = glXGetVisualFromFBConfig(myDisplay, configs[0]); myContext = glXCreateContext(myDisplay, visual, currentContext, true); if (!myContext) { Err() << "Impossible to create render image (failed to create the OpenGL context)" << std::endl; XFree(configs); XFree(visual); return false; } // Restore the previous active context if (currentContext) glXMakeCurrent(myDisplay, currentDrawable, currentContext); // Cleanup resources XFree(configs); XFree(visual); return true; }
int fgPlatformGlutGet ( GLenum eWhat ) { switch( eWhat ) { /* * Those calls are somewhat similiar, as they use XGetWindowAttributes() * function */ case GLUT_WINDOW_X: case GLUT_WINDOW_Y: case GLUT_WINDOW_BORDER_WIDTH: case GLUT_WINDOW_HEADER_HEIGHT: { int x, y; Window w; if( fgStructure.CurrentWindow == NULL ) return 0; XTranslateCoordinates( fgDisplay.pDisplay.Display, fgStructure.CurrentWindow->Window.Handle, fgDisplay.pDisplay.RootWindow, 0, 0, &x, &y, &w); switch ( eWhat ) { case GLUT_WINDOW_X: return x; case GLUT_WINDOW_Y: return y; } if ( w == 0 ) return 0; XTranslateCoordinates( fgDisplay.pDisplay.Display, fgStructure.CurrentWindow->Window.Handle, w, 0, 0, &x, &y, &w); switch ( eWhat ) { case GLUT_WINDOW_BORDER_WIDTH: return x; case GLUT_WINDOW_HEADER_HEIGHT: return y; } } case GLUT_WINDOW_WIDTH: case GLUT_WINDOW_HEIGHT: { XWindowAttributes winAttributes; if( fgStructure.CurrentWindow == NULL ) return 0; XGetWindowAttributes( fgDisplay.pDisplay.Display, fgStructure.CurrentWindow->Window.Handle, &winAttributes ); switch ( eWhat ) { case GLUT_WINDOW_WIDTH: return winAttributes.width ; case GLUT_WINDOW_HEIGHT: return winAttributes.height ; } } /* Colormap size is handled in a bit different way than all the rest */ case GLUT_WINDOW_COLORMAP_SIZE: if( #ifndef EGL_VERSION_1_0 fgPlatformGetConfig( GLX_RGBA ) || #endif fgStructure.CurrentWindow == NULL) { /* * We've got a RGBA visual, so there is no colormap at all. * The other possibility is that we have no current window set. */ return 0; } else { XVisualInfo * visualInfo; int result; #ifdef EGL_VERSION_1_0 EGLint vid = 0; XVisualInfo visualTemplate; int num_visuals; if (!eglGetConfigAttrib(fgDisplay.pDisplay.egl.Display, fgStructure.CurrentWindow->Window.pContext.egl.Config, EGL_NATIVE_VISUAL_ID, &vid)) fgError("eglGetConfigAttrib(EGL_NATIVE_VISUAL_ID) failed"); visualTemplate.visualid = vid; visualInfo = XGetVisualInfo(fgDisplay.pDisplay.Display, VisualIDMask, &visualTemplate, &num_visuals); #else { const GLXFBConfig fbconfig = fgStructure.CurrentWindow->Window.pContext.FBConfig; visualInfo = glXGetVisualFromFBConfig( fgDisplay.pDisplay.Display, fbconfig ); } #endif result = visualInfo->visual->map_entries; XFree(visualInfo); return result; } default: #ifdef EGL_VERSION_1_0 return fghPlatformGlutGetEGL(eWhat); #else return fghPlatformGlutGetGLX(eWhat); #endif } }
static bool config_window_x11(struct MPGLContext *ctx, int flags) { struct vo *vo = ctx->vo; struct glx_context *glx_ctx = ctx->priv; int glx_major, glx_minor; if (!glXQueryVersion(vo->x11->display, &glx_major, &glx_minor)) { MP_ERR(vo, "GLX not found.\n"); return false; } // FBConfigs were added in GLX version 1.3. if (MPGL_VER(glx_major, glx_minor) < MPGL_VER(1, 3)) { MP_ERR(vo, "GLX version older than 1.3.\n"); return false; } int glx_attribs[] = { GLX_X_RENDERABLE, True, GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1, GLX_ALPHA_SIZE, 0, GLX_DOUBLEBUFFER, True, None }; GLXFBConfig fbc = NULL; if (flags & VOFLAG_ALPHA) { set_glx_attrib(glx_attribs, GLX_ALPHA_SIZE, 1); fbc = select_fb_config(vo, glx_attribs, flags); if (!fbc) { set_glx_attrib(glx_attribs, GLX_ALPHA_SIZE, 0); flags &= ~VOFLAG_ALPHA; } } if (!fbc) fbc = select_fb_config(vo, glx_attribs, flags); if (!fbc) { MP_ERR(vo, "no GLX support present\n"); return false; } MP_VERBOSE(vo, "GLX chose FB config with ID 0x%x\n", (int)(intptr_t)fbc); glx_ctx->fbc = fbc; glx_ctx->vinfo = glXGetVisualFromFBConfig(vo->x11->display, fbc); if (glx_ctx->vinfo) { MP_VERBOSE(vo, "GLX chose visual with ID 0x%x\n", (int)glx_ctx->vinfo->visualid); } else { MP_WARN(vo, "Selected GLX FB config has no associated X visual\n"); } glXGetFBConfigAttrib(vo->x11->display, fbc, GLX_RED_SIZE, &ctx->depth_r); glXGetFBConfigAttrib(vo->x11->display, fbc, GLX_GREEN_SIZE, &ctx->depth_g); glXGetFBConfigAttrib(vo->x11->display, fbc, GLX_BLUE_SIZE, &ctx->depth_b); vo_x11_config_vo_window(vo, glx_ctx->vinfo, flags | VOFLAG_HIDDEN, "gl"); bool success = false; if (!(flags & VOFLAG_GLES)) { success = create_context_x11_gl3(ctx, flags, 300, false); if (!success) success = create_context_x11_old(ctx); } if (!success) // try ES success = create_context_x11_gl3(ctx, flags, 200, true); if (success && !glXIsDirect(vo->x11->display, glx_ctx->context)) ctx->gl->mpgl_caps |= MPGL_CAP_SW; return success; }