1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/gl/GLContextProviderGLX.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1271 @@ 1.4 +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#ifdef MOZ_WIDGET_GTK 1.10 +#include <gdk/gdk.h> 1.11 +#include <gdk/gdkx.h> 1.12 +#define GET_NATIVE_WINDOW(aWidget) GDK_WINDOW_XID((GdkWindow *) aWidget->GetNativeData(NS_NATIVE_WINDOW)) 1.13 +#elif defined(MOZ_WIDGET_QT) 1.14 +#define GET_NATIVE_WINDOW(aWidget) (Window)(aWidget->GetNativeData(NS_NATIVE_SHAREABLE_WINDOW)) 1.15 +#endif 1.16 + 1.17 +#include <X11/Xlib.h> 1.18 +#include <X11/Xutil.h> 1.19 + 1.20 +#include "mozilla/MathAlgorithms.h" 1.21 +#include "mozilla/StaticPtr.h" 1.22 +#include "mozilla/X11Util.h" 1.23 + 1.24 +#include "prenv.h" 1.25 +#include "GLContextProvider.h" 1.26 +#include "GLLibraryLoader.h" 1.27 +#include "nsDebug.h" 1.28 +#include "nsIWidget.h" 1.29 +#include "GLXLibrary.h" 1.30 +#include "gfxXlibSurface.h" 1.31 +#include "gfxContext.h" 1.32 +#include "gfxPlatform.h" 1.33 +#include "GLContextGLX.h" 1.34 +#include "gfxUtils.h" 1.35 +#include "gfx2DGlue.h" 1.36 + 1.37 +#include "gfxCrashReporterUtils.h" 1.38 + 1.39 +#ifdef MOZ_WIDGET_GTK 1.40 +#include "gfxPlatformGtk.h" 1.41 +#endif 1.42 + 1.43 +using namespace mozilla::gfx; 1.44 + 1.45 +namespace mozilla { 1.46 +namespace gl { 1.47 + 1.48 +GLXLibrary sGLXLibrary; 1.49 + 1.50 +// Check that we have at least version aMajor.aMinor . 1.51 +bool 1.52 +GLXLibrary::GLXVersionCheck(int aMajor, int aMinor) 1.53 +{ 1.54 + return aMajor < mGLXMajorVersion || 1.55 + (aMajor == mGLXMajorVersion && aMinor <= mGLXMinorVersion); 1.56 +} 1.57 + 1.58 +static inline bool 1.59 +HasExtension(const char* aExtensions, const char* aRequiredExtension) 1.60 +{ 1.61 + return GLContext::ListHasExtension( 1.62 + reinterpret_cast<const GLubyte*>(aExtensions), aRequiredExtension); 1.63 +} 1.64 + 1.65 +bool 1.66 +GLXLibrary::EnsureInitialized() 1.67 +{ 1.68 + if (mInitialized) { 1.69 + return true; 1.70 + } 1.71 + 1.72 + // Don't repeatedly try to initialize. 1.73 + if (mTriedInitializing) { 1.74 + return false; 1.75 + } 1.76 + mTriedInitializing = true; 1.77 + 1.78 + // Force enabling s3 texture compression. (Bug 774134) 1.79 + PR_SetEnv("force_s3tc_enable=true"); 1.80 + 1.81 + if (!mOGLLibrary) { 1.82 + const char* libGLfilename = nullptr; 1.83 + bool forceFeatureReport = false; 1.84 + 1.85 + // see e.g. bug 608526: it is intrinsically interesting to know whether we have dynamically linked to libGL.so.1 1.86 + // because at least the NVIDIA implementation requires an executable stack, which causes mprotect calls, 1.87 + // which trigger glibc bug http://sourceware.org/bugzilla/show_bug.cgi?id=12225 1.88 +#ifdef __OpenBSD__ 1.89 + libGLfilename = "libGL.so"; 1.90 +#else 1.91 + libGLfilename = "libGL.so.1"; 1.92 +#endif 1.93 + 1.94 + ScopedGfxFeatureReporter reporter(libGLfilename, forceFeatureReport); 1.95 + mOGLLibrary = PR_LoadLibrary(libGLfilename); 1.96 + if (!mOGLLibrary) { 1.97 + NS_WARNING("Couldn't load OpenGL shared library."); 1.98 + return false; 1.99 + } 1.100 + reporter.SetSuccessful(); 1.101 + } 1.102 + 1.103 + if (PR_GetEnv("MOZ_GLX_DEBUG")) { 1.104 + mDebug = true; 1.105 + } 1.106 + 1.107 + GLLibraryLoader::SymLoadStruct symbols[] = { 1.108 + /* functions that were in GLX 1.0 */ 1.109 + { (PRFuncPtr*) &xDestroyContextInternal, { "glXDestroyContext", nullptr } }, 1.110 + { (PRFuncPtr*) &xMakeCurrentInternal, { "glXMakeCurrent", nullptr } }, 1.111 + { (PRFuncPtr*) &xSwapBuffersInternal, { "glXSwapBuffers", nullptr } }, 1.112 + { (PRFuncPtr*) &xQueryVersionInternal, { "glXQueryVersion", nullptr } }, 1.113 + { (PRFuncPtr*) &xGetCurrentContextInternal, { "glXGetCurrentContext", nullptr } }, 1.114 + { (PRFuncPtr*) &xWaitGLInternal, { "glXWaitGL", nullptr } }, 1.115 + { (PRFuncPtr*) &xWaitXInternal, { "glXWaitX", nullptr } }, 1.116 + /* functions introduced in GLX 1.1 */ 1.117 + { (PRFuncPtr*) &xQueryExtensionsStringInternal, { "glXQueryExtensionsString", nullptr } }, 1.118 + { (PRFuncPtr*) &xGetClientStringInternal, { "glXGetClientString", nullptr } }, 1.119 + { (PRFuncPtr*) &xQueryServerStringInternal, { "glXQueryServerString", nullptr } }, 1.120 + { nullptr, { nullptr } } 1.121 + }; 1.122 + 1.123 + GLLibraryLoader::SymLoadStruct symbols13[] = { 1.124 + /* functions introduced in GLX 1.3 */ 1.125 + { (PRFuncPtr*) &xChooseFBConfigInternal, { "glXChooseFBConfig", nullptr } }, 1.126 + { (PRFuncPtr*) &xGetFBConfigAttribInternal, { "glXGetFBConfigAttrib", nullptr } }, 1.127 + // WARNING: xGetFBConfigs not set in symbols13_ext 1.128 + { (PRFuncPtr*) &xGetFBConfigsInternal, { "glXGetFBConfigs", nullptr } }, 1.129 + // WARNING: symbols13_ext sets xCreateGLXPixmapWithConfig instead 1.130 + { (PRFuncPtr*) &xCreatePixmapInternal, { "glXCreatePixmap", nullptr } }, 1.131 + { (PRFuncPtr*) &xDestroyPixmapInternal, { "glXDestroyPixmap", nullptr } }, 1.132 + { (PRFuncPtr*) &xCreateNewContextInternal, { "glXCreateNewContext", nullptr } }, 1.133 + { nullptr, { nullptr } } 1.134 + }; 1.135 + 1.136 + GLLibraryLoader::SymLoadStruct symbols13_ext[] = { 1.137 + /* extension equivalents for functions introduced in GLX 1.3 */ 1.138 + // GLX_SGIX_fbconfig extension 1.139 + { (PRFuncPtr*) &xChooseFBConfigInternal, { "glXChooseFBConfigSGIX", nullptr } }, 1.140 + { (PRFuncPtr*) &xGetFBConfigAttribInternal, { "glXGetFBConfigAttribSGIX", nullptr } }, 1.141 + // WARNING: no xGetFBConfigs equivalent in extensions 1.142 + // WARNING: different from symbols13: 1.143 + { (PRFuncPtr*) &xCreateGLXPixmapWithConfigInternal, { "glXCreateGLXPixmapWithConfigSGIX", nullptr } }, 1.144 + { (PRFuncPtr*) &xDestroyPixmapInternal, { "glXDestroyGLXPixmap", nullptr } }, // not from ext 1.145 + { (PRFuncPtr*) &xCreateNewContextInternal, { "glXCreateContextWithConfigSGIX", nullptr } }, 1.146 + { nullptr, { nullptr } } 1.147 + }; 1.148 + 1.149 + GLLibraryLoader::SymLoadStruct symbols14[] = { 1.150 + /* functions introduced in GLX 1.4 */ 1.151 + { (PRFuncPtr*) &xGetProcAddressInternal, { "glXGetProcAddress", nullptr } }, 1.152 + { nullptr, { nullptr } } 1.153 + }; 1.154 + 1.155 + GLLibraryLoader::SymLoadStruct symbols14_ext[] = { 1.156 + /* extension equivalents for functions introduced in GLX 1.4 */ 1.157 + // GLX_ARB_get_proc_address extension 1.158 + { (PRFuncPtr*) &xGetProcAddressInternal, { "glXGetProcAddressARB", nullptr } }, 1.159 + { nullptr, { nullptr } } 1.160 + }; 1.161 + 1.162 + GLLibraryLoader::SymLoadStruct symbols_texturefrompixmap[] = { 1.163 + { (PRFuncPtr*) &xBindTexImageInternal, { "glXBindTexImageEXT", nullptr } }, 1.164 + { (PRFuncPtr*) &xReleaseTexImageInternal, { "glXReleaseTexImageEXT", nullptr } }, 1.165 + { nullptr, { nullptr } } 1.166 + }; 1.167 + 1.168 + GLLibraryLoader::SymLoadStruct symbols_robustness[] = { 1.169 + { (PRFuncPtr*) &xCreateContextAttribsInternal, { "glXCreateContextAttribsARB", nullptr } }, 1.170 + { nullptr, { nullptr } } 1.171 + }; 1.172 + 1.173 + if (!GLLibraryLoader::LoadSymbols(mOGLLibrary, &symbols[0])) { 1.174 + NS_WARNING("Couldn't find required entry point in OpenGL shared library"); 1.175 + return false; 1.176 + } 1.177 + 1.178 + Display *display = DefaultXDisplay(); 1.179 + int screen = DefaultScreen(display); 1.180 + 1.181 + if (!xQueryVersion(display, &mGLXMajorVersion, &mGLXMinorVersion)) { 1.182 + mGLXMajorVersion = 0; 1.183 + mGLXMinorVersion = 0; 1.184 + return false; 1.185 + } 1.186 + 1.187 + if (!GLXVersionCheck(1, 1)) 1.188 + // Not possible to query for extensions. 1.189 + return false; 1.190 + 1.191 + const char *clientVendor = xGetClientString(display, LOCAL_GLX_VENDOR); 1.192 + const char *serverVendor = xQueryServerString(display, screen, LOCAL_GLX_VENDOR); 1.193 + const char *extensionsStr = xQueryExtensionsString(display, screen); 1.194 + 1.195 + GLLibraryLoader::SymLoadStruct *sym13; 1.196 + if (!GLXVersionCheck(1, 3)) { 1.197 + // Even if we don't have 1.3, we might have equivalent extensions 1.198 + // (as on the Intel X server). 1.199 + if (!HasExtension(extensionsStr, "GLX_SGIX_fbconfig")) { 1.200 + return false; 1.201 + } 1.202 + sym13 = symbols13_ext; 1.203 + } else { 1.204 + sym13 = symbols13; 1.205 + } 1.206 + if (!GLLibraryLoader::LoadSymbols(mOGLLibrary, sym13)) { 1.207 + NS_WARNING("Couldn't find required entry point in OpenGL shared library"); 1.208 + return false; 1.209 + } 1.210 + 1.211 + GLLibraryLoader::SymLoadStruct *sym14; 1.212 + if (!GLXVersionCheck(1, 4)) { 1.213 + // Even if we don't have 1.4, we might have equivalent extensions 1.214 + // (as on the Intel X server). 1.215 + if (!HasExtension(extensionsStr, "GLX_ARB_get_proc_address")) { 1.216 + return false; 1.217 + } 1.218 + sym14 = symbols14_ext; 1.219 + } else { 1.220 + sym14 = symbols14; 1.221 + } 1.222 + if (!GLLibraryLoader::LoadSymbols(mOGLLibrary, sym14)) { 1.223 + NS_WARNING("Couldn't find required entry point in OpenGL shared library"); 1.224 + return false; 1.225 + } 1.226 + 1.227 + if (HasExtension(extensionsStr, "GLX_EXT_texture_from_pixmap") && 1.228 + GLLibraryLoader::LoadSymbols(mOGLLibrary, symbols_texturefrompixmap, 1.229 + (GLLibraryLoader::PlatformLookupFunction)&xGetProcAddress)) 1.230 + { 1.231 +#ifdef MOZ_WIDGET_GTK 1.232 + mUseTextureFromPixmap = gfxPlatformGtk::GetPlatform()->UseXRender(); 1.233 +#else 1.234 + mUseTextureFromPixmap = true; 1.235 +#endif 1.236 + } else { 1.237 + mUseTextureFromPixmap = false; 1.238 + NS_WARNING("Texture from pixmap disabled"); 1.239 + } 1.240 + 1.241 + if (HasExtension(extensionsStr, "GLX_ARB_create_context_robustness") && 1.242 + GLLibraryLoader::LoadSymbols(mOGLLibrary, symbols_robustness)) { 1.243 + mHasRobustness = true; 1.244 + } 1.245 + 1.246 + mIsATI = serverVendor && DoesStringMatch(serverVendor, "ATI"); 1.247 + mIsNVIDIA = serverVendor && DoesStringMatch(serverVendor, "NVIDIA Corporation"); 1.248 + mClientIsMesa = clientVendor && DoesStringMatch(clientVendor, "Mesa"); 1.249 + 1.250 + mInitialized = true; 1.251 + 1.252 + return true; 1.253 +} 1.254 + 1.255 +bool 1.256 +GLXLibrary::SupportsTextureFromPixmap(gfxASurface* aSurface) 1.257 +{ 1.258 + if (!EnsureInitialized()) { 1.259 + return false; 1.260 + } 1.261 + 1.262 + if (aSurface->GetType() != gfxSurfaceType::Xlib || !mUseTextureFromPixmap) { 1.263 + return false; 1.264 + } 1.265 + 1.266 + return true; 1.267 +} 1.268 + 1.269 +GLXPixmap 1.270 +GLXLibrary::CreatePixmap(gfxASurface* aSurface) 1.271 +{ 1.272 + if (!SupportsTextureFromPixmap(aSurface)) { 1.273 + return None; 1.274 + } 1.275 + 1.276 + gfxXlibSurface *xs = static_cast<gfxXlibSurface*>(aSurface); 1.277 + const XRenderPictFormat *format = xs->XRenderFormat(); 1.278 + if (!format || format->type != PictTypeDirect) { 1.279 + return None; 1.280 + } 1.281 + const XRenderDirectFormat& direct = format->direct; 1.282 + int alphaSize = FloorLog2(direct.alphaMask + 1); 1.283 + NS_ASSERTION((1 << alphaSize) - 1 == direct.alphaMask, 1.284 + "Unexpected render format with non-adjacent alpha bits"); 1.285 + 1.286 + int attribs[] = { LOCAL_GLX_DOUBLEBUFFER, False, 1.287 + LOCAL_GLX_DRAWABLE_TYPE, LOCAL_GLX_PIXMAP_BIT, 1.288 + LOCAL_GLX_ALPHA_SIZE, alphaSize, 1.289 + (alphaSize ? LOCAL_GLX_BIND_TO_TEXTURE_RGBA_EXT 1.290 + : LOCAL_GLX_BIND_TO_TEXTURE_RGB_EXT), True, 1.291 + LOCAL_GLX_RENDER_TYPE, LOCAL_GLX_RGBA_BIT, 1.292 + None }; 1.293 + 1.294 + int numConfigs = 0; 1.295 + Display *display = xs->XDisplay(); 1.296 + int xscreen = DefaultScreen(display); 1.297 + 1.298 + ScopedXFree<GLXFBConfig> cfgs(xChooseFBConfig(display, 1.299 + xscreen, 1.300 + attribs, 1.301 + &numConfigs)); 1.302 + 1.303 + // Find an fbconfig that matches the pixel format used on the Pixmap. 1.304 + int matchIndex = -1; 1.305 + unsigned long redMask = 1.306 + static_cast<unsigned long>(direct.redMask) << direct.red; 1.307 + unsigned long greenMask = 1.308 + static_cast<unsigned long>(direct.greenMask) << direct.green; 1.309 + unsigned long blueMask = 1.310 + static_cast<unsigned long>(direct.blueMask) << direct.blue; 1.311 + // This is true if the Pixmap has bits for alpha or unused bits. 1.312 + bool haveNonColorBits = 1.313 + ~(redMask | greenMask | blueMask) != -1UL << format->depth; 1.314 + 1.315 + for (int i = 0; i < numConfigs; i++) { 1.316 + int id = None; 1.317 + sGLXLibrary.xGetFBConfigAttrib(display, cfgs[i], LOCAL_GLX_VISUAL_ID, &id); 1.318 + Visual *visual; 1.319 + int depth; 1.320 + FindVisualAndDepth(display, id, &visual, &depth); 1.321 + if (!visual || 1.322 + visual->c_class != TrueColor || 1.323 + visual->red_mask != redMask || 1.324 + visual->green_mask != greenMask || 1.325 + visual->blue_mask != blueMask ) { 1.326 + continue; 1.327 + } 1.328 + 1.329 + // Historically Xlib Visuals did not try to represent an alpha channel 1.330 + // and there was no means to use an alpha channel on a Pixmap. The 1.331 + // Xlib Visual from the fbconfig was not intended to have any 1.332 + // information about alpha bits. 1.333 + // 1.334 + // Since then, RENDER has added formats for 32 bit depth Pixmaps. 1.335 + // Some of these formats have bits for alpha and some have unused 1.336 + // bits. 1.337 + // 1.338 + // Then the Composite extension added a 32 bit depth Visual intended 1.339 + // for Windows with an alpha channel, so bits not in the visual color 1.340 + // masks were expected to be treated as alpha bits. 1.341 + // 1.342 + // Usually GLX counts only color bits in the Visual depth, but the 1.343 + // depth of Composite's ARGB Visual includes alpha bits. However, 1.344 + // bits not in the color masks are not necessarily alpha bits because 1.345 + // sometimes (NVIDIA) 32 bit Visuals are added for fbconfigs with 32 1.346 + // bit BUFFER_SIZE but zero alpha bits and 24 color bits (NVIDIA 1.347 + // again). 1.348 + // 1.349 + // This checks that the depth matches in one of the two ways. 1.350 + // NVIDIA now forces format->depth == depth so only the first way 1.351 + // is checked for NVIDIA 1.352 + if (depth != format->depth && 1.353 + (mIsNVIDIA || depth != format->depth - alphaSize) ) { 1.354 + continue; 1.355 + } 1.356 + 1.357 + // If all bits of the Pixmap are color bits and the Pixmap depth 1.358 + // matches the depth of the fbconfig visual, then we can assume that 1.359 + // the driver will do whatever is necessary to ensure that any 1.360 + // GLXPixmap alpha bits are treated as set. We can skip the 1.361 + // ALPHA_SIZE check in this situation. We need to skip this check for 1.362 + // situations (ATI) where there are no fbconfigs without alpha bits. 1.363 + // 1.364 + // glXChooseFBConfig should prefer configs with smaller 1.365 + // LOCAL_GLX_BUFFER_SIZE, so we should still get zero alpha bits if 1.366 + // available, except perhaps with NVIDIA drivers where buffer size is 1.367 + // not the specified sum of the component sizes. 1.368 + if (haveNonColorBits) { 1.369 + // There are bits in the Pixmap format that haven't been matched 1.370 + // against the fbconfig visual. These bits could either represent 1.371 + // alpha or be unused, so just check that the number of alpha bits 1.372 + // matches. 1.373 + int size = 0; 1.374 + sGLXLibrary.xGetFBConfigAttrib(display, cfgs[i], 1.375 + LOCAL_GLX_ALPHA_SIZE, &size); 1.376 + if (size != alphaSize) { 1.377 + continue; 1.378 + } 1.379 + } 1.380 + 1.381 + matchIndex = i; 1.382 + break; 1.383 + } 1.384 + if (matchIndex == -1) { 1.385 + // GLX can't handle A8 surfaces, so this is not really unexpected. The 1.386 + // caller should deal with this situation. 1.387 + NS_WARN_IF_FALSE(format->depth == 8, 1.388 + "[GLX] Couldn't find a FBConfig matching Pixmap format"); 1.389 + return None; 1.390 + } 1.391 + 1.392 + int pixmapAttribs[] = { LOCAL_GLX_TEXTURE_TARGET_EXT, LOCAL_GLX_TEXTURE_2D_EXT, 1.393 + LOCAL_GLX_TEXTURE_FORMAT_EXT, 1.394 + (alphaSize ? LOCAL_GLX_TEXTURE_FORMAT_RGBA_EXT 1.395 + : LOCAL_GLX_TEXTURE_FORMAT_RGB_EXT), 1.396 + None}; 1.397 + 1.398 + GLXPixmap glxpixmap = xCreatePixmap(display, 1.399 + cfgs[matchIndex], 1.400 + xs->XDrawable(), 1.401 + pixmapAttribs); 1.402 + 1.403 + return glxpixmap; 1.404 +} 1.405 + 1.406 +void 1.407 +GLXLibrary::DestroyPixmap(Display* aDisplay, GLXPixmap aPixmap) 1.408 +{ 1.409 + if (!mUseTextureFromPixmap) { 1.410 + return; 1.411 + } 1.412 + 1.413 + xDestroyPixmap(aDisplay, aPixmap); 1.414 +} 1.415 + 1.416 +void 1.417 +GLXLibrary::BindTexImage(Display* aDisplay, GLXPixmap aPixmap) 1.418 +{ 1.419 + if (!mUseTextureFromPixmap) { 1.420 + return; 1.421 + } 1.422 + 1.423 + // Make sure all X drawing to the surface has finished before binding to a texture. 1.424 + if (mClientIsMesa) { 1.425 + // Using XSync instead of Mesa's glXWaitX, because its glxWaitX is a 1.426 + // noop when direct rendering unless the current drawable is a 1.427 + // single-buffer window. 1.428 + FinishX(aDisplay); 1.429 + } else { 1.430 + xWaitX(); 1.431 + } 1.432 + xBindTexImage(aDisplay, aPixmap, LOCAL_GLX_FRONT_LEFT_EXT, nullptr); 1.433 +} 1.434 + 1.435 +void 1.436 +GLXLibrary::ReleaseTexImage(Display* aDisplay, GLXPixmap aPixmap) 1.437 +{ 1.438 + if (!mUseTextureFromPixmap) { 1.439 + return; 1.440 + } 1.441 + 1.442 + xReleaseTexImage(aDisplay, aPixmap, LOCAL_GLX_FRONT_LEFT_EXT); 1.443 +} 1.444 + 1.445 +void 1.446 +GLXLibrary::UpdateTexImage(Display* aDisplay, GLXPixmap aPixmap) 1.447 +{ 1.448 + // NVIDIA drivers don't require a rebind of the pixmap in order 1.449 + // to display an updated image, and it's faster not to do it. 1.450 + if (mIsNVIDIA) { 1.451 + xWaitX(); 1.452 + return; 1.453 + } 1.454 + 1.455 + ReleaseTexImage(aDisplay, aPixmap); 1.456 + BindTexImage(aDisplay, aPixmap); 1.457 +} 1.458 + 1.459 +#ifdef DEBUG 1.460 + 1.461 +static int (*sOldErrorHandler)(Display *, XErrorEvent *); 1.462 +ScopedXErrorHandler::ErrorEvent sErrorEvent; 1.463 +static int GLXErrorHandler(Display *display, XErrorEvent *ev) 1.464 +{ 1.465 + if (!sErrorEvent.mError.error_code) { 1.466 + sErrorEvent.mError = *ev; 1.467 + } 1.468 + return 0; 1.469 +} 1.470 + 1.471 +void 1.472 +GLXLibrary::BeforeGLXCall() 1.473 +{ 1.474 + if (mDebug) { 1.475 + sOldErrorHandler = XSetErrorHandler(GLXErrorHandler); 1.476 + } 1.477 +} 1.478 + 1.479 +void 1.480 +GLXLibrary::AfterGLXCall() 1.481 +{ 1.482 + if (mDebug) { 1.483 + FinishX(DefaultXDisplay()); 1.484 + if (sErrorEvent.mError.error_code) { 1.485 + char buffer[2048]; 1.486 + XGetErrorText(DefaultXDisplay(), sErrorEvent.mError.error_code, buffer, sizeof(buffer)); 1.487 + printf_stderr("X ERROR: %s (%i) - Request: %i.%i, Serial: %i", 1.488 + buffer, 1.489 + sErrorEvent.mError.error_code, 1.490 + sErrorEvent.mError.request_code, 1.491 + sErrorEvent.mError.minor_code, 1.492 + sErrorEvent.mError.serial); 1.493 + NS_ABORT(); 1.494 + } 1.495 + XSetErrorHandler(sOldErrorHandler); 1.496 + } 1.497 +} 1.498 + 1.499 +#define BEFORE_GLX_CALL do { \ 1.500 + sGLXLibrary.BeforeGLXCall(); \ 1.501 +} while (0) 1.502 + 1.503 +#define AFTER_GLX_CALL do { \ 1.504 + sGLXLibrary.AfterGLXCall(); \ 1.505 +} while (0) 1.506 + 1.507 +#else 1.508 + 1.509 +#define BEFORE_GLX_CALL do { } while(0) 1.510 +#define AFTER_GLX_CALL do { } while(0) 1.511 + 1.512 +#endif 1.513 + 1.514 +void 1.515 +GLXLibrary::xDestroyContext(Display* display, GLXContext context) 1.516 +{ 1.517 + BEFORE_GLX_CALL; 1.518 + xDestroyContextInternal(display, context); 1.519 + AFTER_GLX_CALL; 1.520 +} 1.521 + 1.522 +Bool 1.523 +GLXLibrary::xMakeCurrent(Display* display, 1.524 + GLXDrawable drawable, 1.525 + GLXContext context) 1.526 +{ 1.527 + BEFORE_GLX_CALL; 1.528 + Bool result = xMakeCurrentInternal(display, drawable, context); 1.529 + AFTER_GLX_CALL; 1.530 + return result; 1.531 +} 1.532 + 1.533 +GLXContext 1.534 +GLXLibrary::xGetCurrentContext() 1.535 +{ 1.536 + BEFORE_GLX_CALL; 1.537 + GLXContext result = xGetCurrentContextInternal(); 1.538 + AFTER_GLX_CALL; 1.539 + return result; 1.540 +} 1.541 + 1.542 +/* static */ void* 1.543 +GLXLibrary::xGetProcAddress(const char *procName) 1.544 +{ 1.545 + BEFORE_GLX_CALL; 1.546 + void* result = sGLXLibrary.xGetProcAddressInternal(procName); 1.547 + AFTER_GLX_CALL; 1.548 + return result; 1.549 +} 1.550 + 1.551 +GLXFBConfig* 1.552 +GLXLibrary::xChooseFBConfig(Display* display, 1.553 + int screen, 1.554 + const int *attrib_list, 1.555 + int *nelements) 1.556 +{ 1.557 + BEFORE_GLX_CALL; 1.558 + GLXFBConfig* result = xChooseFBConfigInternal(display, screen, attrib_list, nelements); 1.559 + AFTER_GLX_CALL; 1.560 + return result; 1.561 +} 1.562 + 1.563 +GLXFBConfig* 1.564 +GLXLibrary::xGetFBConfigs(Display* display, 1.565 + int screen, 1.566 + int *nelements) 1.567 +{ 1.568 + BEFORE_GLX_CALL; 1.569 + GLXFBConfig* result = xGetFBConfigsInternal(display, screen, nelements); 1.570 + AFTER_GLX_CALL; 1.571 + return result; 1.572 +} 1.573 + 1.574 +GLXContext 1.575 +GLXLibrary::xCreateNewContext(Display* display, 1.576 + GLXFBConfig config, 1.577 + int render_type, 1.578 + GLXContext share_list, 1.579 + Bool direct) 1.580 +{ 1.581 + BEFORE_GLX_CALL; 1.582 + GLXContext result = xCreateNewContextInternal(display, config, 1.583 + render_type, 1.584 + share_list, direct); 1.585 + AFTER_GLX_CALL; 1.586 + return result; 1.587 +} 1.588 + 1.589 +int 1.590 +GLXLibrary::xGetFBConfigAttrib(Display *display, 1.591 + GLXFBConfig config, 1.592 + int attribute, 1.593 + int *value) 1.594 +{ 1.595 + BEFORE_GLX_CALL; 1.596 + int result = xGetFBConfigAttribInternal(display, config, 1.597 + attribute, value); 1.598 + AFTER_GLX_CALL; 1.599 + return result; 1.600 +} 1.601 + 1.602 +void 1.603 +GLXLibrary::xSwapBuffers(Display *display, GLXDrawable drawable) 1.604 +{ 1.605 + BEFORE_GLX_CALL; 1.606 + xSwapBuffersInternal(display, drawable); 1.607 + AFTER_GLX_CALL; 1.608 +} 1.609 + 1.610 +const char * 1.611 +GLXLibrary::xQueryExtensionsString(Display *display, 1.612 + int screen) 1.613 +{ 1.614 + BEFORE_GLX_CALL; 1.615 + const char *result = xQueryExtensionsStringInternal(display, screen); 1.616 + AFTER_GLX_CALL; 1.617 + return result; 1.618 +} 1.619 + 1.620 +const char * 1.621 +GLXLibrary::xGetClientString(Display *display, 1.622 + int screen) 1.623 +{ 1.624 + BEFORE_GLX_CALL; 1.625 + const char *result = xGetClientStringInternal(display, screen); 1.626 + AFTER_GLX_CALL; 1.627 + return result; 1.628 +} 1.629 + 1.630 +const char * 1.631 +GLXLibrary::xQueryServerString(Display *display, 1.632 + int screen, int name) 1.633 +{ 1.634 + BEFORE_GLX_CALL; 1.635 + const char *result = xQueryServerStringInternal(display, screen, name); 1.636 + AFTER_GLX_CALL; 1.637 + return result; 1.638 +} 1.639 + 1.640 +GLXPixmap 1.641 +GLXLibrary::xCreatePixmap(Display *display, 1.642 + GLXFBConfig config, 1.643 + Pixmap pixmap, 1.644 + const int *attrib_list) 1.645 +{ 1.646 + BEFORE_GLX_CALL; 1.647 + GLXPixmap result = xCreatePixmapInternal(display, config, 1.648 + pixmap, attrib_list); 1.649 + AFTER_GLX_CALL; 1.650 + return result; 1.651 +} 1.652 + 1.653 +GLXPixmap 1.654 +GLXLibrary::xCreateGLXPixmapWithConfig(Display *display, 1.655 + GLXFBConfig config, 1.656 + Pixmap pixmap) 1.657 +{ 1.658 + BEFORE_GLX_CALL; 1.659 + GLXPixmap result = xCreateGLXPixmapWithConfigInternal(display, config, pixmap); 1.660 + AFTER_GLX_CALL; 1.661 + return result; 1.662 +} 1.663 + 1.664 +void 1.665 +GLXLibrary::xDestroyPixmap(Display *display, GLXPixmap pixmap) 1.666 +{ 1.667 + BEFORE_GLX_CALL; 1.668 + xDestroyPixmapInternal(display, pixmap); 1.669 + AFTER_GLX_CALL; 1.670 +} 1.671 + 1.672 +Bool 1.673 +GLXLibrary::xQueryVersion(Display *display, 1.674 + int *major, 1.675 + int *minor) 1.676 +{ 1.677 + BEFORE_GLX_CALL; 1.678 + Bool result = xQueryVersionInternal(display, major, minor); 1.679 + AFTER_GLX_CALL; 1.680 + return result; 1.681 +} 1.682 + 1.683 +void 1.684 +GLXLibrary::xBindTexImage(Display *display, 1.685 + GLXDrawable drawable, 1.686 + int buffer, 1.687 + const int *attrib_list) 1.688 +{ 1.689 + BEFORE_GLX_CALL; 1.690 + xBindTexImageInternal(display, drawable, buffer, attrib_list); 1.691 + AFTER_GLX_CALL; 1.692 +} 1.693 + 1.694 +void 1.695 +GLXLibrary::xReleaseTexImage(Display *display, 1.696 + GLXDrawable drawable, 1.697 + int buffer) 1.698 +{ 1.699 + BEFORE_GLX_CALL; 1.700 + xReleaseTexImageInternal(display, drawable, buffer); 1.701 + AFTER_GLX_CALL; 1.702 +} 1.703 + 1.704 +void 1.705 +GLXLibrary::xWaitGL() 1.706 +{ 1.707 + BEFORE_GLX_CALL; 1.708 + xWaitGLInternal(); 1.709 + AFTER_GLX_CALL; 1.710 +} 1.711 + 1.712 +void 1.713 +GLXLibrary::xWaitX() 1.714 +{ 1.715 + BEFORE_GLX_CALL; 1.716 + xWaitXInternal(); 1.717 + AFTER_GLX_CALL; 1.718 +} 1.719 + 1.720 +GLXContext 1.721 +GLXLibrary::xCreateContextAttribs(Display* display, 1.722 + GLXFBConfig config, 1.723 + GLXContext share_list, 1.724 + Bool direct, 1.725 + const int* attrib_list) 1.726 +{ 1.727 + BEFORE_GLX_CALL; 1.728 + GLXContext result = xCreateContextAttribsInternal(display, 1.729 + config, 1.730 + share_list, 1.731 + direct, 1.732 + attrib_list); 1.733 + AFTER_GLX_CALL; 1.734 + return result; 1.735 +} 1.736 + 1.737 +already_AddRefed<GLContextGLX> 1.738 +GLContextGLX::CreateGLContext( 1.739 + const SurfaceCaps& caps, 1.740 + GLContextGLX* shareContext, 1.741 + bool isOffscreen, 1.742 + Display* display, 1.743 + GLXDrawable drawable, 1.744 + GLXFBConfig cfg, 1.745 + bool deleteDrawable, 1.746 + gfxXlibSurface* pixmap) 1.747 +{ 1.748 + GLXLibrary& glx = sGLXLibrary; 1.749 + 1.750 + int db = 0; 1.751 + int err = glx.xGetFBConfigAttrib(display, cfg, 1.752 + LOCAL_GLX_DOUBLEBUFFER, &db); 1.753 + if (LOCAL_GLX_BAD_ATTRIBUTE != err) { 1.754 +#ifdef DEBUG 1.755 + if (DebugMode()) { 1.756 + printf("[GLX] FBConfig is %sdouble-buffered\n", db ? "" : "not "); 1.757 + } 1.758 +#endif 1.759 + } 1.760 + 1.761 + GLXContext context; 1.762 + nsRefPtr<GLContextGLX> glContext; 1.763 + bool error; 1.764 + 1.765 + ScopedXErrorHandler xErrorHandler; 1.766 + 1.767 +TRY_AGAIN_NO_SHARING: 1.768 + 1.769 + error = false; 1.770 + 1.771 + GLXContext glxContext = shareContext ? shareContext->mContext : nullptr; 1.772 + if (glx.HasRobustness()) { 1.773 + int attrib_list[] = { 1.774 + LOCAL_GL_CONTEXT_FLAGS_ARB, LOCAL_GL_CONTEXT_ROBUST_ACCESS_BIT_ARB, 1.775 + LOCAL_GL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, LOCAL_GL_LOSE_CONTEXT_ON_RESET_ARB, 1.776 + 0, 1.777 + }; 1.778 + 1.779 + context = glx.xCreateContextAttribs( 1.780 + display, 1.781 + cfg, 1.782 + glxContext, 1.783 + True, 1.784 + attrib_list); 1.785 + } else { 1.786 + context = glx.xCreateNewContext( 1.787 + display, 1.788 + cfg, 1.789 + LOCAL_GLX_RGBA_TYPE, 1.790 + glxContext, 1.791 + True); 1.792 + } 1.793 + 1.794 + if (context) { 1.795 + glContext = new GLContextGLX(caps, 1.796 + shareContext, 1.797 + isOffscreen, 1.798 + display, 1.799 + drawable, 1.800 + context, 1.801 + deleteDrawable, 1.802 + db, 1.803 + pixmap); 1.804 + if (!glContext->Init()) 1.805 + error = true; 1.806 + } else { 1.807 + error = true; 1.808 + } 1.809 + 1.810 + error |= xErrorHandler.SyncAndGetError(display); 1.811 + 1.812 + if (error) { 1.813 + if (shareContext) { 1.814 + shareContext = nullptr; 1.815 + goto TRY_AGAIN_NO_SHARING; 1.816 + } 1.817 + 1.818 + NS_WARNING("Failed to create GLXContext!"); 1.819 + glContext = nullptr; // note: this must be done while the graceful X error handler is set, 1.820 + // because glxMakeCurrent can give a GLXBadDrawable error 1.821 + } 1.822 + 1.823 + return glContext.forget(); 1.824 +} 1.825 + 1.826 +GLContextGLX::~GLContextGLX() 1.827 +{ 1.828 + MarkDestroyed(); 1.829 + 1.830 + // Wrapped context should not destroy glxContext/Surface 1.831 + if (!mOwnsContext) { 1.832 + return; 1.833 + } 1.834 + 1.835 + // see bug 659842 comment 76 1.836 +#ifdef DEBUG 1.837 + bool success = 1.838 +#endif 1.839 + mGLX->xMakeCurrent(mDisplay, None, nullptr); 1.840 + NS_ABORT_IF_FALSE(success, 1.841 + "glXMakeCurrent failed to release GL context before we call glXDestroyContext!"); 1.842 + 1.843 + mGLX->xDestroyContext(mDisplay, mContext); 1.844 + 1.845 + if (mDeleteDrawable) { 1.846 + mGLX->xDestroyPixmap(mDisplay, mDrawable); 1.847 + } 1.848 +} 1.849 + 1.850 +bool 1.851 +GLContextGLX::Init() 1.852 +{ 1.853 + SetupLookupFunction(); 1.854 + if (!InitWithPrefix("gl", true)) { 1.855 + return false; 1.856 + } 1.857 + 1.858 + if (!IsExtensionSupported(EXT_framebuffer_object)) 1.859 + return false; 1.860 + 1.861 + return true; 1.862 +} 1.863 + 1.864 +bool 1.865 +GLContextGLX::MakeCurrentImpl(bool aForce) 1.866 +{ 1.867 + bool succeeded = true; 1.868 + 1.869 + // With the ATI FGLRX driver, glxMakeCurrent is very slow even when the context doesn't change. 1.870 + // (This is not the case with other drivers such as NVIDIA). 1.871 + // So avoid calling it more than necessary. Since GLX documentation says that: 1.872 + // "glXGetCurrentContext returns client-side information. 1.873 + // It does not make a round trip to the server." 1.874 + // I assume that it's not worth using our own TLS slot here. 1.875 + if (aForce || mGLX->xGetCurrentContext() != mContext) { 1.876 + succeeded = mGLX->xMakeCurrent(mDisplay, mDrawable, mContext); 1.877 + NS_ASSERTION(succeeded, "Failed to make GL context current!"); 1.878 + } 1.879 + 1.880 + return succeeded; 1.881 +} 1.882 + 1.883 +bool 1.884 +GLContextGLX::IsCurrent() { 1.885 + return mGLX->xGetCurrentContext() == mContext; 1.886 +} 1.887 + 1.888 +bool 1.889 +GLContextGLX::SetupLookupFunction() 1.890 +{ 1.891 + mLookupFunc = (PlatformLookupFunction)&GLXLibrary::xGetProcAddress; 1.892 + return true; 1.893 +} 1.894 + 1.895 +bool 1.896 +GLContextGLX::IsDoubleBuffered() const 1.897 +{ 1.898 + return mDoubleBuffered; 1.899 +} 1.900 + 1.901 +bool 1.902 +GLContextGLX::SupportsRobustness() const 1.903 +{ 1.904 + return mGLX->HasRobustness(); 1.905 +} 1.906 + 1.907 +bool 1.908 +GLContextGLX::SwapBuffers() 1.909 +{ 1.910 + if (!mDoubleBuffered) 1.911 + return false; 1.912 + mGLX->xSwapBuffers(mDisplay, mDrawable); 1.913 + mGLX->xWaitGL(); 1.914 + return true; 1.915 +} 1.916 + 1.917 +GLContextGLX::GLContextGLX( 1.918 + const SurfaceCaps& caps, 1.919 + GLContext* shareContext, 1.920 + bool isOffscreen, 1.921 + Display *aDisplay, 1.922 + GLXDrawable aDrawable, 1.923 + GLXContext aContext, 1.924 + bool aDeleteDrawable, 1.925 + bool aDoubleBuffered, 1.926 + gfxXlibSurface *aPixmap) 1.927 + : GLContext(caps, shareContext, isOffscreen),//aDeleteDrawable ? true : false, aShareContext, ), 1.928 + mContext(aContext), 1.929 + mDisplay(aDisplay), 1.930 + mDrawable(aDrawable), 1.931 + mDeleteDrawable(aDeleteDrawable), 1.932 + mDoubleBuffered(aDoubleBuffered), 1.933 + mGLX(&sGLXLibrary), 1.934 + mPixmap(aPixmap), 1.935 + mOwnsContext(true) 1.936 +{ 1.937 + MOZ_ASSERT(mGLX); 1.938 + // See 899855 1.939 + SetProfileVersion(ContextProfile::OpenGLCompatibility, 200); 1.940 +} 1.941 + 1.942 + 1.943 +static GLContextGLX * 1.944 +GetGlobalContextGLX() 1.945 +{ 1.946 + return static_cast<GLContextGLX*>(GLContextProviderGLX::GetGlobalContext()); 1.947 +} 1.948 + 1.949 +static bool 1.950 +AreCompatibleVisuals(Visual *one, Visual *two) 1.951 +{ 1.952 + if (one->c_class != two->c_class) { 1.953 + return false; 1.954 + } 1.955 + 1.956 + if (one->red_mask != two->red_mask || 1.957 + one->green_mask != two->green_mask || 1.958 + one->blue_mask != two->blue_mask) { 1.959 + return false; 1.960 + } 1.961 + 1.962 + if (one->bits_per_rgb != two->bits_per_rgb) { 1.963 + return false; 1.964 + } 1.965 + 1.966 + return true; 1.967 +} 1.968 + 1.969 +static StaticRefPtr<GLContext> gGlobalContext; 1.970 + 1.971 +already_AddRefed<GLContext> 1.972 +GLContextProviderGLX::CreateWrappingExisting(void* aContext, void* aSurface) 1.973 +{ 1.974 + if (!sGLXLibrary.EnsureInitialized()) { 1.975 + return nullptr; 1.976 + } 1.977 + 1.978 + if (aContext && aSurface) { 1.979 + SurfaceCaps caps = SurfaceCaps::Any(); 1.980 + nsRefPtr<GLContextGLX> glContext = 1.981 + new GLContextGLX(caps, 1.982 + nullptr, // SharedContext 1.983 + false, // Offscreen 1.984 + (Display*)DefaultXDisplay(), // Display 1.985 + (GLXDrawable)aSurface, (GLXContext)aContext, 1.986 + false, // aDeleteDrawable, 1.987 + true, 1.988 + (gfxXlibSurface*)nullptr); 1.989 + 1.990 + glContext->mOwnsContext = false; 1.991 + gGlobalContext = glContext; 1.992 + 1.993 + return glContext.forget(); 1.994 + } 1.995 + 1.996 + return nullptr; 1.997 +} 1.998 + 1.999 +already_AddRefed<GLContext> 1.1000 +GLContextProviderGLX::CreateForWindow(nsIWidget *aWidget) 1.1001 +{ 1.1002 + if (!sGLXLibrary.EnsureInitialized()) { 1.1003 + return nullptr; 1.1004 + } 1.1005 + 1.1006 + // Currently, we take whatever Visual the window already has, and 1.1007 + // try to create an fbconfig for that visual. This isn't 1.1008 + // necessarily what we want in the long run; an fbconfig may not 1.1009 + // be available for the existing visual, or if it is, the GL 1.1010 + // performance might be suboptimal. But using the existing visual 1.1011 + // is a relatively safe intermediate step. 1.1012 + 1.1013 + Display *display = (Display*)aWidget->GetNativeData(NS_NATIVE_DISPLAY); 1.1014 + if (!display) { 1.1015 + NS_ERROR("X Display required for GLX Context provider"); 1.1016 + return nullptr; 1.1017 + } 1.1018 + 1.1019 + int xscreen = DefaultScreen(display); 1.1020 + Window window = GET_NATIVE_WINDOW(aWidget); 1.1021 + 1.1022 + int numConfigs; 1.1023 + ScopedXFree<GLXFBConfig> cfgs; 1.1024 + if (sGLXLibrary.IsATI() || 1.1025 + !sGLXLibrary.GLXVersionCheck(1, 3)) { 1.1026 + const int attribs[] = { 1.1027 + LOCAL_GLX_DOUBLEBUFFER, False, 1.1028 + 0 1.1029 + }; 1.1030 + cfgs = sGLXLibrary.xChooseFBConfig(display, 1.1031 + xscreen, 1.1032 + attribs, 1.1033 + &numConfigs); 1.1034 + } else { 1.1035 + cfgs = sGLXLibrary.xGetFBConfigs(display, 1.1036 + xscreen, 1.1037 + &numConfigs); 1.1038 + } 1.1039 + 1.1040 + if (!cfgs) { 1.1041 + NS_WARNING("[GLX] glXGetFBConfigs() failed"); 1.1042 + return nullptr; 1.1043 + } 1.1044 + NS_ASSERTION(numConfigs > 0, "No FBConfigs found!"); 1.1045 + 1.1046 + // XXX the visual ID is almost certainly the LOCAL_GLX_FBCONFIG_ID, so 1.1047 + // we could probably do this first and replace the glXGetFBConfigs 1.1048 + // with glXChooseConfigs. Docs are sparklingly clear as always. 1.1049 + XWindowAttributes widgetAttrs; 1.1050 + if (!XGetWindowAttributes(display, window, &widgetAttrs)) { 1.1051 + NS_WARNING("[GLX] XGetWindowAttributes() failed"); 1.1052 + return nullptr; 1.1053 + } 1.1054 + const VisualID widgetVisualID = XVisualIDFromVisual(widgetAttrs.visual); 1.1055 +#ifdef DEBUG 1.1056 + printf("[GLX] widget has VisualID 0x%lx\n", widgetVisualID); 1.1057 +#endif 1.1058 + 1.1059 + int matchIndex = -1; 1.1060 + 1.1061 + for (int i = 0; i < numConfigs; i++) { 1.1062 + int visid = None; 1.1063 + sGLXLibrary.xGetFBConfigAttrib(display, cfgs[i], LOCAL_GLX_VISUAL_ID, &visid); 1.1064 + if (!visid) { 1.1065 + continue; 1.1066 + } 1.1067 + if (sGLXLibrary.IsATI()) { 1.1068 + int depth; 1.1069 + Visual *visual; 1.1070 + FindVisualAndDepth(display, visid, &visual, &depth); 1.1071 + if (depth == widgetAttrs.depth && 1.1072 + AreCompatibleVisuals(widgetAttrs.visual, visual)) { 1.1073 + matchIndex = i; 1.1074 + break; 1.1075 + } 1.1076 + } else { 1.1077 + if (widgetVisualID == static_cast<VisualID>(visid)) { 1.1078 + matchIndex = i; 1.1079 + break; 1.1080 + } 1.1081 + } 1.1082 + } 1.1083 + 1.1084 + if (matchIndex == -1) { 1.1085 + NS_WARNING("[GLX] Couldn't find a FBConfig matching widget visual"); 1.1086 + return nullptr; 1.1087 + } 1.1088 + 1.1089 + GLContextGLX *shareContext = GetGlobalContextGLX(); 1.1090 + 1.1091 + SurfaceCaps caps = SurfaceCaps::Any(); 1.1092 + nsRefPtr<GLContextGLX> glContext = GLContextGLX::CreateGLContext(caps, 1.1093 + shareContext, 1.1094 + false, 1.1095 + display, 1.1096 + window, 1.1097 + cfgs[matchIndex], 1.1098 + false); 1.1099 + 1.1100 + return glContext.forget(); 1.1101 +} 1.1102 + 1.1103 +static already_AddRefed<GLContextGLX> 1.1104 +CreateOffscreenPixmapContext(const gfxIntSize& size) 1.1105 +{ 1.1106 + GLXLibrary& glx = sGLXLibrary; 1.1107 + if (!glx.EnsureInitialized()) { 1.1108 + return nullptr; 1.1109 + } 1.1110 + 1.1111 + Display *display = DefaultXDisplay(); 1.1112 + int xscreen = DefaultScreen(display); 1.1113 + 1.1114 + int attribs[] = { 1.1115 + LOCAL_GLX_DRAWABLE_TYPE, LOCAL_GLX_PIXMAP_BIT, 1.1116 + LOCAL_GLX_X_RENDERABLE, True, 1.1117 + 0 1.1118 + }; 1.1119 + int numConfigs = 0; 1.1120 + 1.1121 + ScopedXFree<GLXFBConfig> cfgs; 1.1122 + cfgs = glx.xChooseFBConfig(display, 1.1123 + xscreen, 1.1124 + attribs, 1.1125 + &numConfigs); 1.1126 + if (!cfgs) { 1.1127 + return nullptr; 1.1128 + } 1.1129 + 1.1130 + MOZ_ASSERT(numConfigs > 0, 1.1131 + "glXChooseFBConfig() failed to match our requested format and violated its spec!"); 1.1132 + 1.1133 + int visid = None; 1.1134 + int chosenIndex = 0; 1.1135 + 1.1136 + for (int i = 0; i < numConfigs; ++i) { 1.1137 + int dtype; 1.1138 + 1.1139 + if (glx.xGetFBConfigAttrib(display, cfgs[i], LOCAL_GLX_DRAWABLE_TYPE, &dtype) != Success 1.1140 + || !(dtype & LOCAL_GLX_PIXMAP_BIT)) 1.1141 + { 1.1142 + continue; 1.1143 + } 1.1144 + if (glx.xGetFBConfigAttrib(display, cfgs[i], LOCAL_GLX_VISUAL_ID, &visid) != Success 1.1145 + || visid == 0) 1.1146 + { 1.1147 + continue; 1.1148 + } 1.1149 + 1.1150 + chosenIndex = i; 1.1151 + break; 1.1152 + } 1.1153 + 1.1154 + if (!visid) { 1.1155 + NS_WARNING("glXChooseFBConfig() didn't give us any configs with visuals!"); 1.1156 + return nullptr; 1.1157 + } 1.1158 + 1.1159 + Visual *visual; 1.1160 + int depth; 1.1161 + FindVisualAndDepth(display, visid, &visual, &depth); 1.1162 + ScopedXErrorHandler xErrorHandler; 1.1163 + GLXPixmap glxpixmap = 0; 1.1164 + bool error = false; 1.1165 + 1.1166 + gfxIntSize dummySize(16, 16); 1.1167 + nsRefPtr<gfxXlibSurface> xsurface = gfxXlibSurface::Create(DefaultScreenOfDisplay(display), 1.1168 + visual, 1.1169 + dummySize); 1.1170 + if (xsurface->CairoStatus() != 0) { 1.1171 + error = true; 1.1172 + goto DONE_CREATING_PIXMAP; 1.1173 + } 1.1174 + 1.1175 + // Handle slightly different signature between glXCreatePixmap and 1.1176 + // its pre-GLX-1.3 extension equivalent (though given the ABI, we 1.1177 + // might not need to). 1.1178 + if (glx.GLXVersionCheck(1, 3)) { 1.1179 + glxpixmap = glx.xCreatePixmap(display, 1.1180 + cfgs[chosenIndex], 1.1181 + xsurface->XDrawable(), 1.1182 + nullptr); 1.1183 + } else { 1.1184 + glxpixmap = glx.xCreateGLXPixmapWithConfig(display, 1.1185 + cfgs[chosenIndex], 1.1186 + xsurface-> 1.1187 + XDrawable()); 1.1188 + } 1.1189 + if (glxpixmap == 0) { 1.1190 + error = true; 1.1191 + } 1.1192 + 1.1193 +DONE_CREATING_PIXMAP: 1.1194 + 1.1195 + nsRefPtr<GLContextGLX> glContext; 1.1196 + bool serverError = xErrorHandler.SyncAndGetError(display); 1.1197 + 1.1198 + if (!error && // earlier recorded error 1.1199 + !serverError) 1.1200 + { 1.1201 + // We might have an alpha channel, but it doesn't matter. 1.1202 + SurfaceCaps dummyCaps = SurfaceCaps::Any(); 1.1203 + GLContextGLX* shareContext = GetGlobalContextGLX(); 1.1204 + 1.1205 + glContext = GLContextGLX::CreateGLContext(dummyCaps, 1.1206 + shareContext, 1.1207 + true, 1.1208 + display, 1.1209 + glxpixmap, 1.1210 + cfgs[chosenIndex], 1.1211 + true, 1.1212 + xsurface); 1.1213 + } 1.1214 + 1.1215 + return glContext.forget(); 1.1216 +} 1.1217 + 1.1218 +already_AddRefed<GLContext> 1.1219 +GLContextProviderGLX::CreateOffscreen(const gfxIntSize& size, 1.1220 + const SurfaceCaps& caps) 1.1221 +{ 1.1222 + gfxIntSize dummySize = gfxIntSize(16, 16); 1.1223 + nsRefPtr<GLContextGLX> glContext = 1.1224 + CreateOffscreenPixmapContext(dummySize); 1.1225 + 1.1226 + if (!glContext) 1.1227 + return nullptr; 1.1228 + 1.1229 + if (!glContext->InitOffscreen(ToIntSize(size), caps)) 1.1230 + return nullptr; 1.1231 + 1.1232 + return glContext.forget(); 1.1233 +} 1.1234 + 1.1235 +GLContext* 1.1236 +GLContextProviderGLX::GetGlobalContext() 1.1237 +{ 1.1238 + static bool checkedContextSharing = false; 1.1239 + static bool useContextSharing = false; 1.1240 + 1.1241 + if (!checkedContextSharing) { 1.1242 + useContextSharing = getenv("MOZ_DISABLE_CONTEXT_SHARING_GLX") == 0; 1.1243 + checkedContextSharing = true; 1.1244 + } 1.1245 + 1.1246 + // TODO: get GLX context sharing to work well with multiple threads 1.1247 + if (!useContextSharing) { 1.1248 + return nullptr; 1.1249 + } 1.1250 + 1.1251 + static bool triedToCreateContext = false; 1.1252 + if (!triedToCreateContext && !gGlobalContext) { 1.1253 + triedToCreateContext = true; 1.1254 + 1.1255 + gfxIntSize dummySize = gfxIntSize(16, 16); 1.1256 + // StaticPtr doesn't support assignments from already_AddRefed, 1.1257 + // so use a temporary nsRefPtr to make the reference counting 1.1258 + // fall out correctly. 1.1259 + nsRefPtr<GLContext> holder = CreateOffscreenPixmapContext(dummySize); 1.1260 + gGlobalContext = holder; 1.1261 + } 1.1262 + 1.1263 + return gGlobalContext; 1.1264 +} 1.1265 + 1.1266 +void 1.1267 +GLContextProviderGLX::Shutdown() 1.1268 +{ 1.1269 + gGlobalContext = nullptr; 1.1270 +} 1.1271 + 1.1272 +} /* namespace gl */ 1.1273 +} /* namespace mozilla */ 1.1274 +