already_AddRefed<GLContextGLX> GLContextGLX::CreateGLContext( const SurfaceCaps& caps, GLContextGLX* shareContext, bool isOffscreen, Display* display, GLXDrawable drawable, GLXFBConfig cfg, bool deleteDrawable, gfxXlibSurface* pixmap) { GLXLibrary& glx = sGLXLibrary; int db = 0; int err = glx.xGetFBConfigAttrib(display, cfg, LOCAL_GLX_DOUBLEBUFFER, &db); if (LOCAL_GLX_BAD_ATTRIBUTE != err) { #ifdef DEBUG if (DebugMode()) { printf("[GLX] FBConfig is %sdouble-buffered\n", db ? "" : "not "); } #endif } GLXContext context; nsRefPtr<GLContextGLX> glContext; bool error; ScopedXErrorHandler xErrorHandler; TRY_AGAIN_NO_SHARING: error = false; GLXContext glxContext = shareContext ? shareContext->mContext : nullptr; if (glx.HasRobustness()) { int attrib_list[] = { LOCAL_GL_CONTEXT_FLAGS_ARB, LOCAL_GL_CONTEXT_ROBUST_ACCESS_BIT_ARB, LOCAL_GL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, LOCAL_GL_LOSE_CONTEXT_ON_RESET_ARB, 0, }; context = glx.xCreateContextAttribs( display, cfg, glxContext, True, attrib_list); } else { context = glx.xCreateNewContext( display, cfg, LOCAL_GLX_RGBA_TYPE, glxContext, True); } if (context) { glContext = new GLContextGLX(caps, shareContext, isOffscreen, display, drawable, context, deleteDrawable, db, pixmap); if (!glContext->Init()) error = true; } else { error = true; } error |= xErrorHandler.SyncAndGetError(display); if (error) { if (shareContext) { shareContext = nullptr; goto TRY_AGAIN_NO_SHARING; } NS_WARNING("Failed to create GLXContext!"); glContext = nullptr; // note: this must be done while the graceful X error handler is set, // because glxMakeCurrent can give a GLXBadDrawable error } return glContext.forget(); }
already_AddRefed<GLContextGLX> GLContextGLX::CreateGLContext(CreateContextFlags flags, const SurfaceCaps& caps, GLContextGLX* shareContext, bool isOffscreen, Display* display, GLXDrawable drawable, GLXFBConfig cfg, bool deleteDrawable, gfxXlibSurface* pixmap, ContextProfile profile) { GLXLibrary& glx = sGLXLibrary; int db = 0; int err = glx.xGetFBConfigAttrib(display, cfg, LOCAL_GLX_DOUBLEBUFFER, &db); if (LOCAL_GLX_BAD_ATTRIBUTE != err) { if (ShouldSpew()) { printf("[GLX] FBConfig is %sdouble-buffered\n", db ? "" : "not "); } } GLXContext context; RefPtr<GLContextGLX> glContext; bool error; ScopedXErrorHandler xErrorHandler; TRY_AGAIN_NO_SHARING: error = false; GLXContext glxContext = shareContext ? shareContext->mContext : nullptr; if (glx.HasCreateContextAttribs()) { AutoTArray<int, 11> attrib_list; if (glx.HasRobustness()) { int robust_attribs[] = { LOCAL_GL_CONTEXT_FLAGS_ARB, LOCAL_GL_CONTEXT_ROBUST_ACCESS_BIT_ARB, LOCAL_GL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, LOCAL_GL_LOSE_CONTEXT_ON_RESET_ARB, }; attrib_list.AppendElements(robust_attribs, MOZ_ARRAY_LENGTH(robust_attribs)); } if (profile == ContextProfile::OpenGLCore) { int core_attribs[] = { LOCAL_GLX_CONTEXT_MAJOR_VERSION_ARB, 3, LOCAL_GLX_CONTEXT_MINOR_VERSION_ARB, 2, LOCAL_GLX_CONTEXT_FLAGS_ARB, LOCAL_GLX_CONTEXT_CORE_PROFILE_BIT_ARB, }; attrib_list.AppendElements(core_attribs, MOZ_ARRAY_LENGTH(core_attribs)); }; attrib_list.AppendElement(0); context = glx.xCreateContextAttribs( display, cfg, glxContext, True, attrib_list.Elements()); } else { context = glx.xCreateNewContext( display, cfg, LOCAL_GLX_RGBA_TYPE, glxContext, True); } if (context) { glContext = new GLContextGLX(flags, caps, shareContext, isOffscreen, display, drawable, context, deleteDrawable, db, pixmap, profile); if (!glContext->Init()) error = true; } else { error = true; } error |= xErrorHandler.SyncAndGetError(display); if (error) { if (shareContext) { shareContext = nullptr; goto TRY_AGAIN_NO_SHARING; } NS_WARNING("Failed to create GLXContext!"); glContext = nullptr; // note: this must be done while the graceful X error handler is set, // because glxMakeCurrent can give a GLXBadDrawable error } return glContext.forget(); }
static already_AddRefed<GLContextGLX> CreateOffscreenPixmapContext(const gfxIntSize& size) { GLXLibrary& glx = sGLXLibrary; if (!glx.EnsureInitialized()) { return nullptr; } Display *display = DefaultXDisplay(); int xscreen = DefaultScreen(display); int attribs[] = { LOCAL_GLX_DRAWABLE_TYPE, LOCAL_GLX_PIXMAP_BIT, LOCAL_GLX_X_RENDERABLE, True, 0 }; int numConfigs = 0; ScopedXFree<GLXFBConfig> cfgs; cfgs = glx.xChooseFBConfig(display, xscreen, attribs, &numConfigs); if (!cfgs) { return nullptr; } MOZ_ASSERT(numConfigs > 0, "glXChooseFBConfig() failed to match our requested format and " "violated its spec!"); int visid = None; int chosenIndex = 0; for (int i = 0; i < numConfigs; ++i) { int dtype; if (glx.xGetFBConfigAttrib(display, cfgs[i], LOCAL_GLX_DRAWABLE_TYPE, &dtype) != Success || !(dtype & LOCAL_GLX_PIXMAP_BIT)) { continue; } if (glx.xGetFBConfigAttrib(display, cfgs[i], LOCAL_GLX_VISUAL_ID, &visid) != Success || visid == 0) { continue; } chosenIndex = i; break; } if (!visid) { NS_WARNING("glXChooseFBConfig() didn't give us any configs with visuals!"); return nullptr; } Visual *visual; int depth; FindVisualAndDepth(display, visid, &visual, &depth); ScopedXErrorHandler xErrorHandler; GLXPixmap glxpixmap = 0; bool error = false; gfxIntSize dummySize(16, 16); nsRefPtr<gfxXlibSurface> xsurface = gfxXlibSurface::Create(DefaultScreenOfDisplay(display), visual, dummySize); if (xsurface->CairoStatus() != 0) { error = true; goto DONE_CREATING_PIXMAP; } // Handle slightly different signature between glXCreatePixmap and // its pre-GLX-1.3 extension equivalent (though given the ABI, we // might not need to). if (glx.GLXVersionCheck(1, 3)) { glxpixmap = glx.xCreatePixmap(display, cfgs[chosenIndex], xsurface->XDrawable(), nullptr); } else { glxpixmap = glx.xCreateGLXPixmapWithConfig(display, cfgs[chosenIndex], xsurface-> XDrawable()); } if (glxpixmap == 0) { error = true; } DONE_CREATING_PIXMAP: nsRefPtr<GLContextGLX> glContext; bool serverError = xErrorHandler.SyncAndGetError(display); if (!error && // earlier recorded error !serverError) { // We might have an alpha channel, but it doesn't matter. SurfaceCaps dummyCaps = SurfaceCaps::Any(); GLContextGLX* shareContext = GetGlobalContextGLX(); glContext = GLContextGLX::CreateGLContext(dummyCaps, shareContext, true, display, glxpixmap, cfgs[chosenIndex], true, xsurface); } return glContext.forget(); }
static already_AddRefed<GLContextGLX> CreateOffscreenPixmapContext(CreateContextFlags flags, const IntSize& size, const SurfaceCaps& minCaps, nsACString* const out_failureId, ContextProfile profile = ContextProfile::OpenGLCompatibility) { GLXLibrary* glx = &sGLXLibrary; if (!glx->EnsureInitialized()) return nullptr; Display* display = DefaultXDisplay(); int screen = DefaultScreen(display); ScopedXFree<GLXFBConfig> scopedConfigArr; GLXFBConfig config; int visid; if (!ChooseConfig(glx, display, screen, minCaps, &scopedConfigArr, &config, &visid)) { NS_WARNING("Failed to find a compatible config."); return nullptr; } Visual* visual; int depth; FindVisualAndDepth(display, visid, &visual, &depth); ScopedXErrorHandler xErrorHandler; bool error = false; // Must be declared before goto: Drawable drawable; GLXPixmap pixmap; gfx::IntSize dummySize(16, 16); RefPtr<gfxXlibSurface> surface = gfxXlibSurface::Create(DefaultScreenOfDisplay(display), visual, dummySize); if (surface->CairoStatus() != 0) { error = true; goto DONE_CREATING_PIXMAP; } // Handle slightly different signature between glXCreatePixmap and // its pre-GLX-1.3 extension equivalent (though given the ABI, we // might not need to). drawable = surface->XDrawable(); if (glx->GLXVersionCheck(1, 3)) { pixmap = glx->xCreatePixmap(display, config, drawable, nullptr); } else { pixmap = glx->xCreateGLXPixmapWithConfig(display, config, drawable); } if (pixmap == 0) { error = true; } DONE_CREATING_PIXMAP: bool serverError = xErrorHandler.SyncAndGetError(display); if (error || serverError) return nullptr; GLContextGLX* shareContext = GetGlobalContextGLX(); return GLContextGLX::CreateGLContext(flags, minCaps, shareContext, true, display, pixmap, config, true, surface, profile); }