LCOV - code coverage report
Current view: directory - gfx/gl - GLContextProviderGLX.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 540 7 1.3 %
Date: 2012-06-02 Functions: 71 3 4.2 %

       1                 : /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 : /* ***** BEGIN LICENSE BLOCK *****
       3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       4                 :  *
       5                 :  * The contents of this file are subject to the Mozilla Public License Version
       6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       7                 :  * the License. You may obtain a copy of the License at
       8                 :  * http://www.mozilla.org/MPL/
       9                 :  *
      10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12                 :  * for the specific language governing rights and limitations under the
      13                 :  * License.
      14                 :  *
      15                 :  * The Initial Developer of the Original Code is Mozilla Foundation.
      16                 :  * Portions created by the Initial Developer are Copyright (C) 2010
      17                 :  * the Initial Developer. All Rights Reserved.
      18                 :  *
      19                 :  * Contributor(s):
      20                 :  *   Matt Woodrow <mwoodrow@mozilla.com>
      21                 :  *   Bas Schouten <bschouten@mozilla.com>
      22                 :  *
      23                 :  * Alternatively, the contents of this file may be used under the terms of
      24                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      25                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      26                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      27                 :  * of those above. If you wish to allow use of your version of this file only
      28                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      29                 :  * use your version of this file under the terms of the MPL, indicate your
      30                 :  * decision by deleting the provisions above and replace them with the notice
      31                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      32                 :  * the provisions above, a recipient may use your version of this file under
      33                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      34                 :  *
      35                 :  * ***** END LICENSE BLOCK ***** */
      36                 : 
      37                 : #ifdef MOZ_WIDGET_GTK2
      38                 : #include <gdk/gdk.h>
      39                 : #include <gdk/gdkx.h>
      40                 : #define GET_NATIVE_WINDOW(aWidget) GDK_WINDOW_XID((GdkWindow *) aWidget->GetNativeData(NS_NATIVE_WINDOW))
      41                 : #elif defined(MOZ_WIDGET_QT)
      42                 : #include <QWidget>
      43                 : #include <QX11Info>
      44                 : #define GET_NATIVE_WINDOW(aWidget) static_cast<QWidget*>(aWidget->GetNativeData(NS_NATIVE_SHELLWIDGET))->handle()
      45                 : #endif
      46                 : 
      47                 : #include <X11/Xlib.h>
      48                 : #include <X11/Xutil.h>
      49                 : 
      50                 : #include "mozilla/X11Util.h"
      51                 : 
      52                 : #include "prenv.h"
      53                 : #include "GLContextProvider.h"
      54                 : #include "nsDebug.h"
      55                 : #include "nsIWidget.h"
      56                 : #include "GLXLibrary.h"
      57                 : #include "gfxXlibSurface.h"
      58                 : #include "gfxContext.h"
      59                 : #include "gfxImageSurface.h"
      60                 : #include "gfxPlatform.h"
      61                 : #include "GLContext.h"
      62                 : #include "gfxUtils.h"
      63                 : 
      64                 : #include "gfxCrashReporterUtils.h"
      65                 : 
      66                 : namespace mozilla {
      67                 : namespace gl {
      68                 : 
      69                 : static bool gIsATI = false;
      70                 : static bool gIsChromium = false;
      71                 : static int gGLXMajorVersion = 0, gGLXMinorVersion = 0;
      72                 : 
      73                 : // Check that we have at least version aMajor.aMinor .
      74                 : static inline bool
      75               0 : GLXVersionCheck(int aMajor, int aMinor)
      76                 : {
      77                 :     return aMajor < gGLXMajorVersion ||
      78               0 :            (aMajor == gGLXMajorVersion && aMinor <= gGLXMinorVersion);
      79                 : }
      80                 : 
      81                 : static inline bool
      82               0 : HasExtension(const char* aExtensions, const char* aRequiredExtension)
      83                 : {
      84                 :     return GLContext::ListHasExtension(
      85               0 :         reinterpret_cast<const GLubyte*>(aExtensions), aRequiredExtension);
      86                 : }
      87                 : 
      88                 : bool
      89               0 : GLXLibrary::EnsureInitialized()
      90                 : {
      91               0 :     if (mInitialized) {
      92               0 :         return true;
      93                 :     }
      94                 : 
      95                 :     // Don't repeatedly try to initialize.
      96               0 :     if (mTriedInitializing) {
      97               0 :         return false;
      98                 :     }
      99               0 :     mTriedInitializing = true;
     100                 : 
     101               0 :     if (!mOGLLibrary) {
     102                 :         // see e.g. bug 608526: it is intrinsically interesting to know whether we have dynamically linked to libGL.so.1
     103                 :         // because at least the NVIDIA implementation requires an executable stack, which causes mprotect calls,
     104                 :         // which trigger glibc bug http://sourceware.org/bugzilla/show_bug.cgi?id=12225
     105                 : #ifdef __OpenBSD__
     106                 :         const char *libGLfilename = "libGL.so";
     107                 : #else
     108               0 :         const char *libGLfilename = "libGL.so.1";
     109                 : #endif
     110               0 :         ScopedGfxFeatureReporter reporter(libGLfilename);
     111               0 :         mOGLLibrary = PR_LoadLibrary(libGLfilename);
     112               0 :         if (!mOGLLibrary) {
     113               0 :             NS_WARNING("Couldn't load OpenGL shared library.");
     114               0 :             return false;
     115                 :         }
     116               0 :         reporter.SetSuccessful();
     117                 :     }
     118                 : 
     119               0 :     if (PR_GetEnv("MOZ_GLX_DEBUG")) {
     120               0 :         mDebug = true;
     121                 :     }
     122                 : 
     123                 :     LibrarySymbolLoader::SymLoadStruct symbols[] = {
     124                 :         /* functions that were in GLX 1.0 */
     125                 :         { (PRFuncPtr*) &xDestroyContextInternal, { "glXDestroyContext", NULL } },
     126                 :         { (PRFuncPtr*) &xMakeCurrentInternal, { "glXMakeCurrent", NULL } },
     127                 :         { (PRFuncPtr*) &xSwapBuffersInternal, { "glXSwapBuffers", NULL } },
     128                 :         { (PRFuncPtr*) &xQueryVersionInternal, { "glXQueryVersion", NULL } },
     129                 :         { (PRFuncPtr*) &xGetCurrentContextInternal, { "glXGetCurrentContext", NULL } },
     130                 :         { (PRFuncPtr*) &xWaitGLInternal, { "glXWaitGL", NULL } },
     131                 :         { (PRFuncPtr*) &xWaitXInternal, { "glXWaitX", NULL } },
     132                 :         /* functions introduced in GLX 1.1 */
     133                 :         { (PRFuncPtr*) &xQueryExtensionsStringInternal, { "glXQueryExtensionsString", NULL } },
     134                 :         { (PRFuncPtr*) &xGetClientStringInternal, { "glXGetClientString", NULL } },
     135                 :         { (PRFuncPtr*) &xQueryServerStringInternal, { "glXQueryServerString", NULL } },
     136                 :         { NULL, { NULL } }
     137               0 :     };
     138                 : 
     139                 :     LibrarySymbolLoader::SymLoadStruct symbols13[] = {
     140                 :         /* functions introduced in GLX 1.3 */
     141                 :         { (PRFuncPtr*) &xChooseFBConfigInternal, { "glXChooseFBConfig", NULL } },
     142                 :         { (PRFuncPtr*) &xGetFBConfigAttribInternal, { "glXGetFBConfigAttrib", NULL } },
     143                 :         // WARNING: xGetFBConfigs not set in symbols13_ext
     144                 :         { (PRFuncPtr*) &xGetFBConfigsInternal, { "glXGetFBConfigs", NULL } },
     145                 :         { (PRFuncPtr*) &xGetVisualFromFBConfigInternal, { "glXGetVisualFromFBConfig", NULL } },
     146                 :         // WARNING: symbols13_ext sets xCreateGLXPixmapWithConfig instead
     147                 :         { (PRFuncPtr*) &xCreatePixmapInternal, { "glXCreatePixmap", NULL } },
     148                 :         { (PRFuncPtr*) &xDestroyPixmapInternal, { "glXDestroyPixmap", NULL } },
     149                 :         { (PRFuncPtr*) &xCreateNewContextInternal, { "glXCreateNewContext", NULL } },
     150                 :         { NULL, { NULL } }
     151               0 :     };
     152                 : 
     153                 :     LibrarySymbolLoader::SymLoadStruct symbols13_ext[] = {
     154                 :         /* extension equivalents for functions introduced in GLX 1.3 */
     155                 :         // GLX_SGIX_fbconfig extension
     156                 :         { (PRFuncPtr*) &xChooseFBConfigInternal, { "glXChooseFBConfigSGIX", NULL } },
     157                 :         { (PRFuncPtr*) &xGetFBConfigAttribInternal, { "glXGetFBConfigAttribSGIX", NULL } },
     158                 :         // WARNING: no xGetFBConfigs equivalent in extensions
     159                 :         { (PRFuncPtr*) &xGetVisualFromFBConfigInternal, { "glXGetVisualFromFBConfig", NULL } },
     160                 :         // WARNING: different from symbols13:
     161                 :         { (PRFuncPtr*) &xCreateGLXPixmapWithConfigInternal, { "glXCreateGLXPixmapWithConfigSGIX", NULL } },
     162                 :         { (PRFuncPtr*) &xDestroyPixmapInternal, { "glXDestroyGLXPixmap", NULL } }, // not from ext
     163                 :         { (PRFuncPtr*) &xCreateNewContextInternal, { "glXCreateContextWithConfigSGIX", NULL } },
     164                 :         { NULL, { NULL } }
     165               0 :     };
     166                 : 
     167                 :     LibrarySymbolLoader::SymLoadStruct symbols14[] = {
     168                 :         /* functions introduced in GLX 1.4 */
     169                 :         { (PRFuncPtr*) &xGetProcAddressInternal, { "glXGetProcAddress", NULL } },
     170                 :         { NULL, { NULL } }
     171               0 :     };
     172                 : 
     173                 :     LibrarySymbolLoader::SymLoadStruct symbols14_ext[] = {
     174                 :         /* extension equivalents for functions introduced in GLX 1.4 */
     175                 :         // GLX_ARB_get_proc_address extension
     176                 :         { (PRFuncPtr*) &xGetProcAddressInternal, { "glXGetProcAddressARB", NULL } },
     177                 :         { NULL, { NULL } }
     178               0 :     };
     179                 : 
     180                 :     LibrarySymbolLoader::SymLoadStruct symbols_texturefrompixmap[] = {
     181                 :         { (PRFuncPtr*) &xBindTexImageInternal, { "glXBindTexImageEXT", NULL } },
     182                 :         { (PRFuncPtr*) &xReleaseTexImageInternal, { "glXReleaseTexImageEXT", NULL } },
     183                 :         { NULL, { NULL } }
     184               0 :     };
     185                 : 
     186                 :     LibrarySymbolLoader::SymLoadStruct symbols_robustness[] = {
     187                 :         { (PRFuncPtr*) &xCreateContextAttribsInternal, { "glXCreateContextAttribsARB", NULL } },
     188                 :         { NULL, { NULL } }
     189               0 :     };
     190                 : 
     191               0 :     if (!LibrarySymbolLoader::LoadSymbols(mOGLLibrary, &symbols[0])) {
     192               0 :         NS_WARNING("Couldn't find required entry point in OpenGL shared library");
     193               0 :         return false;
     194                 :     }
     195                 : 
     196               0 :     Display *display = DefaultXDisplay();
     197                 : 
     198               0 :     int screen = DefaultScreen(display);
     199               0 :     const char *serverVendor = NULL;
     200               0 :     const char *serverVersionStr = NULL;
     201               0 :     const char *extensionsStr = NULL;
     202                 : 
     203               0 :     if (!xQueryVersion(display, &gGLXMajorVersion, &gGLXMinorVersion)) {
     204               0 :         gGLXMajorVersion = 0;
     205               0 :         gGLXMinorVersion = 0;
     206               0 :         return false;
     207                 :     }
     208                 : 
     209               0 :     serverVendor = xQueryServerString(display, screen, GLX_VENDOR);
     210               0 :     serverVersionStr = xQueryServerString(display, screen, GLX_VERSION);
     211                 : 
     212               0 :     if (!GLXVersionCheck(1, 1))
     213                 :         // Not possible to query for extensions.
     214               0 :         return false;
     215                 : 
     216               0 :     extensionsStr = xQueryExtensionsString(display, screen);
     217                 : 
     218                 :     LibrarySymbolLoader::SymLoadStruct *sym13;
     219               0 :     if (!GLXVersionCheck(1, 3)) {
     220                 :         // Even if we don't have 1.3, we might have equivalent extensions
     221                 :         // (as on the Intel X server).
     222               0 :         if (!HasExtension(extensionsStr, "GLX_SGIX_fbconfig")) {
     223               0 :             return false;
     224                 :         }
     225               0 :         sym13 = symbols13_ext;
     226                 :     } else {
     227               0 :         sym13 = symbols13;
     228                 :     }
     229               0 :     if (!LibrarySymbolLoader::LoadSymbols(mOGLLibrary, sym13)) {
     230               0 :         NS_WARNING("Couldn't find required entry point in OpenGL shared library");
     231               0 :         return false;
     232                 :     }
     233                 : 
     234                 :     LibrarySymbolLoader::SymLoadStruct *sym14;
     235               0 :     if (!GLXVersionCheck(1, 4)) {
     236                 :         // Even if we don't have 1.4, we might have equivalent extensions
     237                 :         // (as on the Intel X server).
     238               0 :         if (!HasExtension(extensionsStr, "GLX_ARB_get_proc_address")) {
     239               0 :             return false;
     240                 :         }
     241               0 :         sym14 = symbols14_ext;
     242                 :     } else {
     243               0 :         sym14 = symbols14;
     244                 :     }
     245               0 :     if (!LibrarySymbolLoader::LoadSymbols(mOGLLibrary, sym14)) {
     246               0 :         NS_WARNING("Couldn't find required entry point in OpenGL shared library");
     247               0 :         return false;
     248                 :     }
     249                 : 
     250               0 :     if (HasExtension(extensionsStr, "GLX_EXT_texture_from_pixmap") &&
     251                 :         LibrarySymbolLoader::LoadSymbols(mOGLLibrary, symbols_texturefrompixmap, 
     252               0 :                                          (LibrarySymbolLoader::PlatformLookupFunction)&xGetProcAddress))
     253                 :     {
     254               0 :         mHasTextureFromPixmap = true;
     255                 :     } else {
     256               0 :         NS_WARNING("Texture from pixmap disabled");
     257                 :     }
     258                 : 
     259               0 :     if (HasExtension(extensionsStr, "GLX_ARB_create_context_robustness") &&
     260               0 :         LibrarySymbolLoader::LoadSymbols(mOGLLibrary, symbols_robustness)) {
     261               0 :         mHasRobustness = true;
     262                 :     }
     263                 : 
     264               0 :     gIsATI = serverVendor && DoesStringMatch(serverVendor, "ATI");
     265                 :     gIsChromium = (serverVendor &&
     266               0 :                    DoesStringMatch(serverVendor, "Chromium")) ||
     267                 :         (serverVersionStr &&
     268               0 :          DoesStringMatch(serverVersionStr, "Chromium"));
     269                 : 
     270               0 :     mInitialized = true;
     271               0 :     return true;
     272                 : }
     273                 : 
     274                 : bool
     275               0 : GLXLibrary::SupportsTextureFromPixmap(gfxASurface* aSurface)
     276                 : {
     277               0 :     if (!EnsureInitialized()) {
     278               0 :         return false;
     279                 :     }
     280                 :     
     281               0 :     if (aSurface->GetType() != gfxASurface::SurfaceTypeXlib || !mHasTextureFromPixmap) {
     282               0 :         return false;
     283                 :     }
     284                 : 
     285               0 :     return true;
     286                 : }
     287                 : 
     288                 : GLXPixmap 
     289               0 : GLXLibrary::CreatePixmap(gfxASurface* aSurface)
     290                 : {
     291               0 :     if (!SupportsTextureFromPixmap(aSurface)) {
     292               0 :         return 0;
     293                 :     }
     294                 : 
     295                 :     int attribs[] = { GLX_DOUBLEBUFFER, False,
     296                 :                       GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT,
     297                 :                       GLX_BIND_TO_TEXTURE_RGBA_EXT, True,
     298               0 :                       None };
     299                 : 
     300                 :     int numFormats;
     301               0 :     Display *display = DefaultXDisplay();
     302               0 :     int xscreen = DefaultScreen(display);
     303                 : 
     304                 :     ScopedXFree<GLXFBConfig> cfg(xChooseFBConfig(display,
     305                 :                                                  xscreen,
     306                 :                                                  attribs,
     307               0 :                                                  &numFormats));
     308               0 :     if (!cfg) {
     309               0 :         return 0;
     310                 :     }
     311               0 :     NS_ABORT_IF_FALSE(numFormats > 0,
     312                 :                  "glXChooseFBConfig() failed to match our requested format and violated its spec (!)");
     313                 : 
     314               0 :     gfxXlibSurface *xs = static_cast<gfxXlibSurface*>(aSurface);
     315                 : 
     316                 :     int pixmapAttribs[] = { GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
     317                 :                             GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGBA_EXT,
     318               0 :                             None};
     319                 : 
     320                 :     GLXPixmap glxpixmap = xCreatePixmap(display,
     321               0 :                                         cfg[0],
     322                 :                                         xs->XDrawable(),
     323               0 :                                         pixmapAttribs);
     324                 : 
     325               0 :     return glxpixmap;
     326                 : }
     327                 : 
     328                 : void
     329               0 : GLXLibrary::DestroyPixmap(GLXPixmap aPixmap)
     330                 : {
     331               0 :     if (!mHasTextureFromPixmap) {
     332               0 :         return;
     333                 :     }
     334                 : 
     335               0 :     Display *display = DefaultXDisplay();
     336               0 :     xDestroyPixmap(display, aPixmap);
     337                 : }
     338                 : 
     339                 : void
     340               0 : GLXLibrary::BindTexImage(GLXPixmap aPixmap)
     341                 : {    
     342               0 :     if (!mHasTextureFromPixmap) {
     343               0 :         return;
     344                 :     }
     345                 : 
     346               0 :     Display *display = DefaultXDisplay();
     347                 :     // Make sure all X drawing to the surface has finished before binding to a texture.
     348               0 :     xWaitX();
     349               0 :     xBindTexImage(display, aPixmap, GLX_FRONT_LEFT_EXT, NULL);
     350                 : }
     351                 : 
     352                 : void
     353               0 : GLXLibrary::ReleaseTexImage(GLXPixmap aPixmap)
     354                 : {
     355               0 :     if (!mHasTextureFromPixmap) {
     356               0 :         return;
     357                 :     }
     358                 : 
     359               0 :     Display *display = DefaultXDisplay();
     360               0 :     xReleaseTexImage(display, aPixmap, GLX_FRONT_LEFT_EXT);
     361                 : }
     362                 : 
     363                 : #ifdef DEBUG
     364                 : 
     365                 : static int (*sOldErrorHandler)(Display *, XErrorEvent *);
     366            1464 : ScopedXErrorHandler::ErrorEvent sErrorEvent;
     367               0 : static int GLXErrorHandler(Display *display, XErrorEvent *ev)
     368                 : {
     369               0 :     if (!sErrorEvent.mError.error_code) {
     370               0 :         sErrorEvent.mError = *ev;
     371                 :     }
     372               0 :     return 0;
     373                 : }
     374                 : 
     375                 : void
     376               0 : GLXLibrary::BeforeGLXCall()
     377                 : {
     378               0 :     if (mDebug) {
     379               0 :         sOldErrorHandler = XSetErrorHandler(GLXErrorHandler);
     380                 :     }
     381               0 : }
     382                 : 
     383                 : void
     384               0 : GLXLibrary::AfterGLXCall()
     385                 : {
     386               0 :     if (mDebug) {
     387               0 :         XSync(DefaultXDisplay(), False);
     388               0 :         if (sErrorEvent.mError.error_code) {
     389                 :             char buffer[2048];
     390               0 :             XGetErrorText(DefaultXDisplay(), sErrorEvent.mError.error_code, buffer, sizeof(buffer));
     391                 :             printf_stderr("X ERROR: %s (%i) - Request: %i.%i, Serial: %i",
     392                 :                           buffer,
     393                 :                           sErrorEvent.mError.error_code,
     394                 :                           sErrorEvent.mError.request_code,
     395                 :                           sErrorEvent.mError.minor_code,
     396               0 :                           sErrorEvent.mError.serial);
     397               0 :             NS_ABORT();
     398                 :         }
     399               0 :         XSetErrorHandler(sOldErrorHandler);
     400                 :     }
     401               0 : }
     402                 : 
     403                 : #define BEFORE_GLX_CALL do {                     \
     404                 :     sGLXLibrary.BeforeGLXCall();                 \
     405                 : } while (0)
     406                 :     
     407                 : #define AFTER_GLX_CALL do {                      \
     408                 :     sGLXLibrary.AfterGLXCall();                  \
     409                 : } while (0)
     410                 : 
     411                 : #else
     412                 : 
     413                 : #define BEFORE_GLX_CALL do { } while(0)
     414                 : #define AFTER_GLX_CALL do { } while(0)
     415                 : 
     416                 : #endif
     417                 :     
     418                 : void 
     419               0 : GLXLibrary::xDestroyContext(Display* display, GLXContext context)
     420                 : {
     421               0 :     BEFORE_GLX_CALL;
     422               0 :     xDestroyContextInternal(display, context);
     423               0 :     AFTER_GLX_CALL;
     424               0 : }
     425                 : 
     426                 : Bool 
     427               0 : GLXLibrary::xMakeCurrent(Display* display, 
     428                 :                          GLXDrawable drawable, 
     429                 :                          GLXContext context)
     430                 : {
     431               0 :     BEFORE_GLX_CALL;
     432               0 :     Bool result = xMakeCurrentInternal(display, drawable, context);
     433               0 :     AFTER_GLX_CALL;
     434               0 :     return result;
     435                 : }
     436                 : 
     437                 : GLXContext 
     438               0 : GLXLibrary::xGetCurrentContext()
     439                 : {
     440               0 :     BEFORE_GLX_CALL;
     441               0 :     GLXContext result = xGetCurrentContextInternal();
     442               0 :     AFTER_GLX_CALL;
     443               0 :     return result;
     444                 : }
     445                 : 
     446                 : /* static */ void* 
     447               0 : GLXLibrary::xGetProcAddress(const char *procName)
     448                 : {
     449               0 :     BEFORE_GLX_CALL;
     450               0 :     void* result = sGLXLibrary.xGetProcAddressInternal(procName);
     451               0 :     AFTER_GLX_CALL;
     452               0 :     return result;
     453                 : }
     454                 : 
     455                 : GLXFBConfig*
     456               0 : GLXLibrary::xChooseFBConfig(Display* display, 
     457                 :                             int screen, 
     458                 :                             const int *attrib_list, 
     459                 :                             int *nelements)
     460                 : {
     461               0 :     BEFORE_GLX_CALL;
     462               0 :     GLXFBConfig* result = xChooseFBConfigInternal(display, screen, attrib_list, nelements);
     463               0 :     AFTER_GLX_CALL;
     464               0 :     return result;
     465                 : }
     466                 : 
     467                 : GLXFBConfig* 
     468               0 : GLXLibrary::xGetFBConfigs(Display* display, 
     469                 :                           int screen, 
     470                 :                           int *nelements)
     471                 : {
     472               0 :     BEFORE_GLX_CALL;
     473               0 :     GLXFBConfig* result = xGetFBConfigsInternal(display, screen, nelements);
     474               0 :     AFTER_GLX_CALL;
     475               0 :     return result;
     476                 : }
     477                 :     
     478                 : GLXContext
     479               0 : GLXLibrary::xCreateNewContext(Display* display, 
     480                 :                               GLXFBConfig config, 
     481                 :                               int render_type, 
     482                 :                               GLXContext share_list, 
     483                 :                               Bool direct)
     484                 : {
     485               0 :     BEFORE_GLX_CALL;
     486                 :     GLXContext result = xCreateNewContextInternal(display, config, 
     487                 :                                                       render_type,
     488               0 :                                                       share_list, direct);
     489               0 :     AFTER_GLX_CALL;
     490               0 :     return result;
     491                 : }
     492                 : 
     493                 : XVisualInfo*
     494               0 : GLXLibrary::xGetVisualFromFBConfig(Display* display, 
     495                 :                                    GLXFBConfig config)
     496                 : {
     497               0 :     BEFORE_GLX_CALL;
     498               0 :     XVisualInfo* result = xGetVisualFromFBConfigInternal(display, config);
     499               0 :     AFTER_GLX_CALL;
     500               0 :     return result;
     501                 : }
     502                 : 
     503                 : int
     504               0 : GLXLibrary::xGetFBConfigAttrib(Display *display,
     505                 :                                GLXFBConfig config,
     506                 :                                int attribute,
     507                 :                                int *value)
     508                 : {
     509               0 :     BEFORE_GLX_CALL;
     510                 :     int result = xGetFBConfigAttribInternal(display, config,
     511               0 :                                             attribute, value);
     512               0 :     AFTER_GLX_CALL;
     513               0 :     return result;
     514                 : }
     515                 : 
     516                 : void
     517               0 : GLXLibrary::xSwapBuffers(Display *display, GLXDrawable drawable)
     518                 : {
     519               0 :     BEFORE_GLX_CALL;
     520               0 :     xSwapBuffersInternal(display, drawable);
     521               0 :     AFTER_GLX_CALL;
     522               0 : }
     523                 : 
     524                 : const char *
     525               0 : GLXLibrary::xQueryExtensionsString(Display *display,
     526                 :                                    int screen)
     527                 : {
     528               0 :     BEFORE_GLX_CALL;
     529               0 :     const char *result = xQueryExtensionsStringInternal(display, screen);
     530               0 :     AFTER_GLX_CALL;
     531               0 :     return result;
     532                 : }
     533                 : 
     534                 : const char *
     535               0 : GLXLibrary::xGetClientString(Display *display,
     536                 :                              int screen)
     537                 : {
     538               0 :     BEFORE_GLX_CALL;
     539               0 :     const char *result = xGetClientStringInternal(display, screen);
     540               0 :     AFTER_GLX_CALL;
     541               0 :     return result;
     542                 : }
     543                 : 
     544                 : const char *
     545               0 : GLXLibrary::xQueryServerString(Display *display,
     546                 :                                int screen, int name)
     547                 : {
     548               0 :     BEFORE_GLX_CALL;
     549               0 :     const char *result = xQueryServerStringInternal(display, screen, name);
     550               0 :     AFTER_GLX_CALL;
     551               0 :     return result;
     552                 : }
     553                 : 
     554                 : GLXPixmap
     555               0 : GLXLibrary::xCreatePixmap(Display *display, 
     556                 :                           GLXFBConfig config,
     557                 :                           Pixmap pixmap,
     558                 :                           const int *attrib_list)
     559                 : {
     560               0 :     BEFORE_GLX_CALL;
     561                 :     GLXPixmap result = xCreatePixmapInternal(display, config,
     562               0 :                                              pixmap, attrib_list);
     563               0 :     AFTER_GLX_CALL;
     564               0 :     return result;
     565                 : }
     566                 : 
     567                 : GLXPixmap
     568               0 : GLXLibrary::xCreateGLXPixmapWithConfig(Display *display,
     569                 :                                        GLXFBConfig config,
     570                 :                                        Pixmap pixmap)
     571                 : {
     572               0 :     BEFORE_GLX_CALL;
     573               0 :     GLXPixmap result = xCreateGLXPixmapWithConfigInternal(display, config, pixmap);
     574               0 :     AFTER_GLX_CALL;
     575               0 :     return result;
     576                 : }
     577                 : 
     578                 : void
     579               0 : GLXLibrary::xDestroyPixmap(Display *display, GLXPixmap pixmap)
     580                 : {
     581               0 :     BEFORE_GLX_CALL;
     582               0 :     xDestroyPixmapInternal(display, pixmap);
     583               0 :     AFTER_GLX_CALL;
     584               0 : }
     585                 : 
     586                 : GLXContext
     587               0 : GLXLibrary::xCreateContext(Display *display,
     588                 :                            XVisualInfo *vis,
     589                 :                            GLXContext shareList,
     590                 :                            Bool direct)
     591                 : {
     592               0 :     BEFORE_GLX_CALL;
     593               0 :     GLXContext result = xCreateContextInternal(display, vis, shareList, direct);
     594               0 :     AFTER_GLX_CALL;
     595               0 :     return result;
     596                 : }
     597                 : 
     598                 : Bool
     599               0 : GLXLibrary::xQueryVersion(Display *display,
     600                 :                           int *major,
     601                 :                           int *minor)
     602                 : {
     603               0 :     BEFORE_GLX_CALL;
     604               0 :     Bool result = xQueryVersionInternal(display, major, minor);
     605               0 :     AFTER_GLX_CALL;
     606               0 :     return result;
     607                 : }
     608                 : 
     609                 : void
     610               0 : GLXLibrary::xBindTexImage(Display *display,
     611                 :                           GLXDrawable drawable,
     612                 :                           int buffer,
     613                 :                           const int *attrib_list)
     614                 : {
     615               0 :     BEFORE_GLX_CALL;
     616               0 :     xBindTexImageInternal(display, drawable, buffer, attrib_list);
     617               0 :     AFTER_GLX_CALL;
     618               0 : }
     619                 : 
     620                 : void
     621               0 : GLXLibrary::xReleaseTexImage(Display *display,
     622                 :                              GLXDrawable drawable,
     623                 :                              int buffer)
     624                 : {
     625               0 :     BEFORE_GLX_CALL;
     626               0 :     xReleaseTexImageInternal(display, drawable, buffer);
     627               0 :     AFTER_GLX_CALL;
     628               0 : }
     629                 : 
     630                 : void 
     631               0 : GLXLibrary::xWaitGL()
     632                 : {
     633               0 :     BEFORE_GLX_CALL;
     634               0 :     xWaitGLInternal();
     635               0 :     AFTER_GLX_CALL;
     636               0 : }
     637                 : 
     638                 : void
     639               0 : GLXLibrary::xWaitX()
     640                 : {
     641               0 :     BEFORE_GLX_CALL;
     642               0 :     xWaitXInternal();
     643               0 :     AFTER_GLX_CALL;
     644               0 : }
     645                 : 
     646                 : GLXContext
     647               0 : GLXLibrary::xCreateContextAttribs(Display* display, 
     648                 :                                   GLXFBConfig config, 
     649                 :                                   GLXContext share_list, 
     650                 :                                   Bool direct,
     651                 :                                   const int* attrib_list)
     652                 : {
     653               0 :     BEFORE_GLX_CALL;
     654                 :     GLXContext result = xCreateContextAttribsInternal(display, 
     655                 :                                                       config, 
     656                 :                                                       share_list, 
     657                 :                                                       direct,
     658               0 :                                                       attrib_list);
     659               0 :     AFTER_GLX_CALL;
     660               0 :     return result;
     661                 : }
     662                 : 
     663            1464 : GLXLibrary sGLXLibrary;
     664                 : 
     665                 : class GLContextGLX : public GLContext
     666                 : {
     667                 : public:
     668                 :     static already_AddRefed<GLContextGLX>
     669               0 :     CreateGLContext(const ContextFormat& format,
     670                 :                     Display *display,
     671                 :                     GLXDrawable drawable,
     672                 :                     GLXFBConfig cfg,
     673                 :                     XVisualInfo *vinfo,
     674                 :                     GLContextGLX *shareContext,
     675                 :                     bool deleteDrawable,
     676                 :                     gfxXlibSurface *pixmap = nsnull)
     677                 :     {
     678               0 :         int db = 0, err;
     679                 :         err = sGLXLibrary.xGetFBConfigAttrib(display, cfg,
     680               0 :                                              GLX_DOUBLEBUFFER, &db);
     681               0 :         if (GLX_BAD_ATTRIBUTE != err) {
     682                 : #ifdef DEBUG
     683               0 :             printf("[GLX] FBConfig is %sdouble-buffered\n", db ? "" : "not ");
     684                 : #endif
     685                 :         }
     686                 : 
     687                 :         GLXContext context;
     688               0 :         nsRefPtr<GLContextGLX> glContext;
     689                 :         bool error;
     690                 : 
     691               0 :         ScopedXErrorHandler xErrorHandler;
     692                 : 
     693                 : TRY_AGAIN_NO_SHARING:
     694                 : 
     695               0 :         error = false;
     696                 : 
     697               0 :         if (sGLXLibrary.HasRobustness()) {
     698                 :             int attrib_list[] = {
     699                 :                 LOCAL_GL_CONTEXT_FLAGS_ARB, LOCAL_GL_CONTEXT_ROBUST_ACCESS_BIT_ARB,
     700                 :                 LOCAL_GL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, LOCAL_GL_LOSE_CONTEXT_ON_RESET_ARB,
     701                 :                 0,
     702               0 :             };
     703                 : 
     704                 :             context = sGLXLibrary.xCreateContextAttribs(display,
     705                 :                                                         cfg,
     706                 :                                                         shareContext ? shareContext->mContext : NULL,
     707                 :                                                         True,
     708               0 :                                                         attrib_list);
     709                 :         } else {
     710                 :             context = sGLXLibrary.xCreateNewContext(display,
     711                 :                                                     cfg,
     712                 :                                                     GLX_RGBA_TYPE,
     713                 :                                                     shareContext ? shareContext->mContext : NULL,
     714               0 :                                                     True);
     715                 :         }
     716                 : 
     717               0 :         if (context) {
     718                 :             glContext = new GLContextGLX(format,
     719                 :                                         shareContext,
     720                 :                                         display,
     721                 :                                         drawable,
     722                 :                                         context,
     723                 :                                         deleteDrawable,
     724                 :                                         db,
     725               0 :                                         pixmap);
     726               0 :             if (!glContext->Init())
     727               0 :                 error = true;
     728                 :         } else {
     729               0 :             error = true;
     730                 :         }
     731                 : 
     732               0 :         error |= xErrorHandler.SyncAndGetError(display);
     733                 : 
     734               0 :         if (error) {
     735               0 :             if (shareContext) {
     736               0 :                 shareContext = nsnull;
     737               0 :                 goto TRY_AGAIN_NO_SHARING;
     738                 :             }
     739                 : 
     740               0 :             NS_WARNING("Failed to create GLXContext!");
     741               0 :             glContext = nsnull; // note: this must be done while the graceful X error handler is set,
     742                 :                                 // because glxMakeCurrent can give a GLXBadDrawable error
     743                 :         }
     744                 : 
     745               0 :         return glContext.forget();
     746                 :     }
     747                 : 
     748               0 :     ~GLContextGLX()
     749               0 :     {
     750               0 :         MarkDestroyed();
     751                 : 
     752                 :         // see bug 659842 comment 76
     753                 : #ifdef DEBUG
     754                 :         bool success =
     755                 : #endif
     756               0 :         sGLXLibrary.xMakeCurrent(mDisplay, None, nsnull);
     757               0 :         NS_ABORT_IF_FALSE(success,
     758                 :             "glXMakeCurrent failed to release GL context before we call glXDestroyContext!");
     759                 : 
     760               0 :         sGLXLibrary.xDestroyContext(mDisplay, mContext);
     761                 : 
     762               0 :         if (mDeleteDrawable) {
     763               0 :             sGLXLibrary.xDestroyPixmap(mDisplay, mDrawable);
     764                 :         }
     765               0 :     }
     766                 : 
     767               0 :     GLContextType GetContextType() {
     768               0 :         return ContextTypeGLX;
     769                 :     }
     770                 : 
     771               0 :     bool Init()
     772                 :     {
     773               0 :         MakeCurrent();
     774               0 :         SetupLookupFunction();
     775               0 :         if (!InitWithPrefix("gl", true)) {
     776               0 :             return false;
     777                 :         }
     778                 : 
     779               0 :         if (!IsExtensionSupported("GL_EXT_framebuffer_object"))
     780               0 :             return false;
     781                 : 
     782               0 :         InitFramebuffers();
     783                 : 
     784               0 :         return true;
     785                 :     }
     786                 : 
     787               0 :     bool MakeCurrentImpl(bool aForce = false)
     788                 :     {
     789               0 :         bool succeeded = true;
     790                 : 
     791                 :         // With the ATI FGLRX driver, glxMakeCurrent is very slow even when the context doesn't change.
     792                 :         // (This is not the case with other drivers such as NVIDIA).
     793                 :         // So avoid calling it more than necessary. Since GLX documentation says that:
     794                 :         //     "glXGetCurrentContext returns client-side information.
     795                 :         //      It does not make a round trip to the server."
     796                 :         // I assume that it's not worth using our own TLS slot here.
     797               0 :         if (aForce || sGLXLibrary.xGetCurrentContext() != mContext) {
     798               0 :             succeeded = sGLXLibrary.xMakeCurrent(mDisplay, mDrawable, mContext);
     799               0 :             NS_ASSERTION(succeeded, "Failed to make GL context current!");
     800                 :         }
     801                 : 
     802               0 :         return succeeded;
     803                 :     }
     804                 : 
     805               0 :     bool SetupLookupFunction()
     806                 :     {
     807               0 :         mLookupFunc = (PlatformLookupFunction)&GLXLibrary::xGetProcAddress;
     808               0 :         return true;
     809                 :     }
     810                 : 
     811               0 :     void *GetNativeData(NativeDataType aType)
     812                 :     {
     813               0 :         switch(aType) {
     814                 :         case NativeGLContext:
     815               0 :             return mContext;
     816                 :  
     817                 :         case NativeThebesSurface:
     818               0 :             return mPixmap;
     819                 : 
     820                 :         default:
     821               0 :             return nsnull;
     822                 :         }
     823                 :     }
     824                 : 
     825               0 :     bool IsDoubleBuffered()
     826                 :     {
     827               0 :         return mDoubleBuffered;
     828                 :     }
     829                 : 
     830               0 :     bool SupportsRobustness()
     831                 :     {
     832               0 :         return sGLXLibrary.HasRobustness();
     833                 :     }
     834                 : 
     835               0 :     bool SwapBuffers()
     836                 :     {
     837               0 :         if (!mDoubleBuffered)
     838               0 :             return false;
     839               0 :         sGLXLibrary.xSwapBuffers(mDisplay, mDrawable);
     840               0 :         sGLXLibrary.xWaitGL();
     841               0 :         return true;
     842                 :     }
     843                 : 
     844               0 :     bool TextureImageSupportsGetBackingSurface()
     845                 :     {
     846               0 :         return sGLXLibrary.HasTextureFromPixmap();
     847                 :     }
     848                 : 
     849                 :     virtual already_AddRefed<TextureImage>
     850                 :     CreateTextureImage(const nsIntSize& aSize,
     851                 :                        TextureImage::ContentType aContentType,
     852                 :                        GLenum aWrapMode,
     853                 :                        bool aUseNearestFilter = false);
     854                 : 
     855                 : private:
     856                 :     friend class GLContextProviderGLX;
     857                 : 
     858               0 :     GLContextGLX(const ContextFormat& aFormat,
     859                 :                  GLContext *aShareContext,
     860                 :                  Display *aDisplay,
     861                 :                  GLXDrawable aDrawable,
     862                 :                  GLXContext aContext,
     863                 :                  bool aDeleteDrawable,
     864                 :                  bool aDoubleBuffered,
     865                 :                  gfxXlibSurface *aPixmap)
     866                 :         : GLContext(aFormat, aDeleteDrawable ? true : false, aShareContext),
     867                 :           mContext(aContext),
     868                 :           mDisplay(aDisplay),
     869                 :           mDrawable(aDrawable),
     870                 :           mDeleteDrawable(aDeleteDrawable),
     871                 :           mDoubleBuffered(aDoubleBuffered),
     872               0 :           mPixmap(aPixmap)
     873               0 :     { }
     874                 : 
     875                 :     GLXContext mContext;
     876                 :     Display *mDisplay;
     877                 :     GLXDrawable mDrawable;
     878                 :     bool mDeleteDrawable;
     879                 :     bool mDoubleBuffered;
     880                 : 
     881                 :     nsRefPtr<gfxXlibSurface> mPixmap;
     882                 : };
     883                 : 
     884                 : class TextureImageGLX : public TextureImage
     885                 : {
     886                 :     friend already_AddRefed<TextureImage>
     887                 :     GLContextGLX::CreateTextureImage(const nsIntSize&,
     888                 :                                      ContentType,
     889                 :                                      GLenum,
     890                 :                                      bool);
     891                 : 
     892                 : public:
     893               0 :     virtual ~TextureImageGLX()
     894               0 :     {
     895               0 :         mGLContext->MakeCurrent();
     896               0 :         mGLContext->fDeleteTextures(1, &mTexture);
     897               0 :         sGLXLibrary.DestroyPixmap(mPixmap);
     898               0 :     }
     899                 : 
     900               0 :     virtual gfxASurface* BeginUpdate(nsIntRegion& aRegion)
     901                 :     {
     902               0 :         mInUpdate = true;
     903               0 :         return mUpdateSurface;
     904                 :     }
     905                 : 
     906               0 :     virtual void EndUpdate()
     907                 :     {
     908               0 :         mInUpdate = false;
     909               0 :     }
     910                 : 
     911                 : 
     912               0 :     virtual bool DirectUpdate(gfxASurface* aSurface, const nsIntRegion& aRegion, const nsIntPoint& aFrom)
     913                 :     {
     914               0 :         nsRefPtr<gfxContext> ctx = new gfxContext(mUpdateSurface);
     915               0 :         gfxUtils::ClipToRegion(ctx, aRegion);
     916               0 :         ctx->SetSource(aSurface, aFrom);
     917               0 :         ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
     918               0 :         ctx->Paint();
     919               0 :         return true;
     920                 :     }
     921                 : 
     922               0 :     virtual void BindTexture(GLenum aTextureUnit)
     923                 :     {
     924               0 :         mGLContext->fActiveTexture(aTextureUnit);
     925               0 :         mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
     926               0 :         sGLXLibrary.BindTexImage(mPixmap);
     927               0 :         mGLContext->fActiveTexture(LOCAL_GL_TEXTURE0);
     928               0 :     }
     929                 : 
     930               0 :     virtual void ReleaseTexture()
     931                 :     {
     932               0 :         sGLXLibrary.ReleaseTexImage(mPixmap);
     933               0 :     }
     934                 : 
     935               0 :     virtual already_AddRefed<gfxASurface> GetBackingSurface()
     936                 :     {
     937               0 :         nsRefPtr<gfxASurface> copy = mUpdateSurface;
     938               0 :         return copy.forget();
     939                 :     }
     940                 : 
     941               0 :     virtual bool InUpdate() const { return mInUpdate; }
     942                 : 
     943               0 :     virtual GLuint GetTextureID() {
     944               0 :         return mTexture;
     945                 :     };
     946                 : 
     947                 : private:
     948               0 :    TextureImageGLX(GLuint aTexture,
     949                 :                    const nsIntSize& aSize,
     950                 :                    GLenum aWrapMode,
     951                 :                    ContentType aContentType,
     952                 :                    GLContext* aContext,
     953                 :                    gfxASurface* aSurface,
     954                 :                    GLXPixmap aPixmap)
     955                 :         : TextureImage(aSize, aWrapMode, aContentType)
     956                 :         , mGLContext(aContext)
     957                 :         , mUpdateSurface(aSurface)
     958                 :         , mPixmap(aPixmap)
     959                 :         , mInUpdate(false)
     960               0 :         , mTexture(aTexture)
     961                 :     {
     962               0 :         if (aSurface->GetContentType() == gfxASurface::CONTENT_COLOR_ALPHA) {
     963               0 :             mShaderType = gl::RGBALayerProgramType;
     964                 :         } else {
     965               0 :             mShaderType = gl::RGBXLayerProgramType;
     966                 :         }
     967               0 :     }
     968                 : 
     969                 :     GLContext* mGLContext;
     970                 :     nsRefPtr<gfxASurface> mUpdateSurface;
     971                 :     GLXPixmap mPixmap;
     972                 :     bool mInUpdate;
     973                 :     GLuint mTexture;
     974                 : 
     975               0 :     virtual void ApplyFilter()
     976                 :     {
     977               0 :         mGLContext->ApplyFilterToBoundTexture(mFilter);
     978               0 :     }
     979                 : };
     980                 : 
     981                 : already_AddRefed<TextureImage>
     982               0 : GLContextGLX::CreateTextureImage(const nsIntSize& aSize,
     983                 :                                  TextureImage::ContentType aContentType,
     984                 :                                  GLenum aWrapMode,
     985                 :                                  bool aUseNearestFilter)
     986                 : {
     987               0 :     if (!TextureImageSupportsGetBackingSurface()) {
     988                 :         return GLContext::CreateTextureImage(aSize, 
     989                 :                                              aContentType, 
     990                 :                                              aWrapMode, 
     991               0 :                                              aUseNearestFilter);
     992                 :     }
     993                 : 
     994               0 :     Display *display = DefaultXDisplay();
     995               0 :     int xscreen = DefaultScreen(display);
     996               0 :     gfxASurface::gfxImageFormat imageFormat = gfxASurface::FormatFromContent(aContentType);
     997                 : 
     998                 :     XRenderPictFormat* xrenderFormat =
     999               0 :         gfxXlibSurface::FindRenderFormat(display, imageFormat);
    1000               0 :     NS_ASSERTION(xrenderFormat, "Could not find a render format for our display!");
    1001                 : 
    1002                 : 
    1003                 :     nsRefPtr<gfxXlibSurface> surface =
    1004                 :         gfxXlibSurface::Create(ScreenOfDisplay(display, xscreen),
    1005                 :                                xrenderFormat,
    1006               0 :                                gfxIntSize(aSize.width, aSize.height));
    1007               0 :     NS_ASSERTION(surface, "Failed to create xlib surface!");
    1008                 : 
    1009               0 :     if (aContentType == gfxASurface::CONTENT_COLOR_ALPHA) {
    1010               0 :         nsRefPtr<gfxContext> ctx = new gfxContext(surface);
    1011               0 :         ctx->SetOperator(gfxContext::OPERATOR_CLEAR);
    1012               0 :         ctx->Paint();
    1013                 :     }
    1014                 : 
    1015               0 :     MakeCurrent();
    1016               0 :     GLXPixmap pixmap = sGLXLibrary.CreatePixmap(surface);
    1017               0 :     NS_ASSERTION(pixmap, "Failed to create pixmap!");
    1018                 : 
    1019                 :     GLuint texture;
    1020               0 :     fGenTextures(1, &texture);
    1021                 : 
    1022               0 :     fActiveTexture(LOCAL_GL_TEXTURE0);
    1023               0 :     fBindTexture(LOCAL_GL_TEXTURE_2D, texture);
    1024                 : 
    1025                 :     nsRefPtr<TextureImageGLX> teximage =
    1026               0 :         new TextureImageGLX(texture, aSize, aWrapMode, aContentType, this, surface, pixmap);
    1027                 : 
    1028               0 :     GLint texfilter = aUseNearestFilter ? LOCAL_GL_NEAREST : LOCAL_GL_LINEAR;
    1029               0 :     fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, texfilter);
    1030               0 :     fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, texfilter);
    1031               0 :     fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, aWrapMode);
    1032               0 :     fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T, aWrapMode);
    1033                 : 
    1034               0 :     return teximage.forget();
    1035                 : }
    1036                 : 
    1037                 : static GLContextGLX *
    1038               0 : GetGlobalContextGLX()
    1039                 : {
    1040               0 :     return static_cast<GLContextGLX*>(GLContextProviderGLX::GetGlobalContext());
    1041                 : }
    1042                 : 
    1043                 : static bool
    1044               0 : AreCompatibleVisuals(XVisualInfo *one, XVisualInfo *two)
    1045                 : {
    1046               0 :     if (one->c_class != two->c_class) {
    1047               0 :         return false;
    1048                 :     }
    1049                 : 
    1050               0 :     if (one->depth != two->depth) {
    1051               0 :         return false;
    1052                 :     }   
    1053                 : 
    1054               0 :     if (one->red_mask != two->red_mask ||
    1055                 :         one->green_mask != two->green_mask ||
    1056                 :         one->blue_mask != two->blue_mask) {
    1057               0 :         return false;
    1058                 :     }
    1059                 : 
    1060               0 :     if (one->bits_per_rgb != two->bits_per_rgb) {
    1061               0 :         return false;
    1062                 :     }
    1063                 : 
    1064               0 :     return true;
    1065                 : }
    1066                 : 
    1067                 : already_AddRefed<GLContext>
    1068               0 : GLContextProviderGLX::CreateForWindow(nsIWidget *aWidget)
    1069                 : {
    1070               0 :     if (!sGLXLibrary.EnsureInitialized()) {
    1071               0 :         return nsnull;
    1072                 :     }
    1073                 : 
    1074                 :     // Currently, we take whatever Visual the window already has, and
    1075                 :     // try to create an fbconfig for that visual.  This isn't
    1076                 :     // necessarily what we want in the long run; an fbconfig may not
    1077                 :     // be available for the existing visual, or if it is, the GL
    1078                 :     // performance might be suboptimal.  But using the existing visual
    1079                 :     // is a relatively safe intermediate step.
    1080                 : 
    1081               0 :     Display *display = (Display*)aWidget->GetNativeData(NS_NATIVE_DISPLAY); 
    1082               0 :     int xscreen = DefaultScreen(display);
    1083               0 :     Window window = GET_NATIVE_WINDOW(aWidget);
    1084                 : 
    1085                 :     int numConfigs;
    1086               0 :     ScopedXFree<GLXFBConfig> cfgs;
    1087               0 :     if (gIsATI || !GLXVersionCheck(1, 3)) {
    1088                 :         const int attribs[] = {
    1089                 :             GLX_DOUBLEBUFFER, False,
    1090                 :             0
    1091               0 :         };
    1092                 :         cfgs = sGLXLibrary.xChooseFBConfig(display,
    1093                 :                                            xscreen,
    1094                 :                                            attribs,
    1095               0 :                                            &numConfigs);
    1096                 :     } else {
    1097                 :         cfgs = sGLXLibrary.xGetFBConfigs(display,
    1098                 :                                          xscreen,
    1099               0 :                                          &numConfigs);
    1100                 :     }
    1101                 : 
    1102               0 :     if (!cfgs) {
    1103               0 :         NS_WARNING("[GLX] glXGetFBConfigs() failed");
    1104               0 :         return nsnull;
    1105                 :     }
    1106               0 :     NS_ASSERTION(numConfigs > 0, "No FBConfigs found!");
    1107                 : 
    1108                 :     // XXX the visual ID is almost certainly the GLX_FBCONFIG_ID, so
    1109                 :     // we could probably do this first and replace the glXGetFBConfigs
    1110                 :     // with glXChooseConfigs.  Docs are sparklingly clear as always.
    1111                 :     XWindowAttributes widgetAttrs;
    1112               0 :     if (!XGetWindowAttributes(display, window, &widgetAttrs)) {
    1113               0 :         NS_WARNING("[GLX] XGetWindowAttributes() failed");
    1114               0 :         return nsnull;
    1115                 :     }
    1116               0 :     const VisualID widgetVisualID = XVisualIDFromVisual(widgetAttrs.visual);
    1117                 : #ifdef DEBUG
    1118               0 :     printf("[GLX] widget has VisualID 0x%lx\n", widgetVisualID);
    1119                 : #endif
    1120                 : 
    1121               0 :     ScopedXFree<XVisualInfo> vi;
    1122               0 :     if (gIsATI) {
    1123                 :         XVisualInfo vinfo_template;
    1124                 :         int nvisuals;
    1125               0 :         vinfo_template.visual   = widgetAttrs.visual;
    1126               0 :         vinfo_template.visualid = XVisualIDFromVisual(vinfo_template.visual);
    1127               0 :         vinfo_template.depth    = widgetAttrs.depth;
    1128               0 :         vinfo_template.screen   = xscreen;
    1129                 :         vi = XGetVisualInfo(display, VisualIDMask|VisualDepthMask|VisualScreenMask,
    1130               0 :                             &vinfo_template, &nvisuals);
    1131               0 :         NS_ASSERTION(vi && nvisuals == 1, "Could not locate unique matching XVisualInfo for Visual");
    1132                 :     }
    1133                 : 
    1134               0 :     int matchIndex = -1;
    1135               0 :     ScopedXFree<XVisualInfo> vinfo;
    1136                 : 
    1137               0 :     for (int i = 0; i < numConfigs; i++) {
    1138               0 :         vinfo = sGLXLibrary.xGetVisualFromFBConfig(display, cfgs[i]);
    1139               0 :         if (!vinfo) {
    1140               0 :             continue;
    1141                 :         }
    1142               0 :         if (gIsATI) {
    1143               0 :             if (AreCompatibleVisuals(vi, vinfo)) {
    1144               0 :                 matchIndex = i;
    1145               0 :                 break;
    1146                 :             }
    1147                 :         } else {
    1148               0 :             if (widgetVisualID == vinfo->visualid) {
    1149               0 :                 matchIndex = i;
    1150               0 :                 break;
    1151                 :             }
    1152                 :         }
    1153                 :     }
    1154                 : 
    1155               0 :     if (matchIndex == -1) {
    1156               0 :         NS_WARNING("[GLX] Couldn't find a FBConfig matching widget visual");
    1157               0 :         return nsnull;
    1158                 :     }
    1159                 : 
    1160               0 :     GLContextGLX *shareContext = GetGlobalContextGLX();
    1161                 : 
    1162                 :     nsRefPtr<GLContextGLX> glContext = GLContextGLX::CreateGLContext(ContextFormat(ContextFormat::BasicRGB24),
    1163                 :                                                                      display,
    1164                 :                                                                      window,
    1165               0 :                                                                      cfgs[matchIndex],
    1166                 :                                                                      vinfo,
    1167                 :                                                                      shareContext,
    1168               0 :                                                                      false);
    1169                 : 
    1170               0 :     return glContext.forget();
    1171                 : }
    1172                 : 
    1173                 : static already_AddRefed<GLContextGLX>
    1174               0 : CreateOffscreenPixmapContext(const gfxIntSize& aSize,
    1175                 :                              const ContextFormat& aFormat,
    1176                 :                              bool aShare)
    1177                 : {
    1178               0 :     if (!sGLXLibrary.EnsureInitialized()) {
    1179               0 :         return nsnull;
    1180                 :     }
    1181                 : 
    1182               0 :     Display *display = DefaultXDisplay();
    1183               0 :     int xscreen = DefaultScreen(display);
    1184                 : 
    1185                 :     int attribs[] = {
    1186                 :         GLX_DOUBLEBUFFER, False,
    1187                 :         GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT,
    1188                 :         GLX_X_RENDERABLE, True,
    1189                 :         GLX_RED_SIZE, 1,
    1190                 :         GLX_GREEN_SIZE, 1,
    1191                 :         GLX_BLUE_SIZE, 1,
    1192                 :         GLX_ALPHA_SIZE, 0,
    1193                 :         GLX_DEPTH_SIZE, 0,
    1194                 :         0
    1195               0 :     };
    1196               0 :     int numConfigs = 0;
    1197                 : 
    1198               0 :     ScopedXFree<GLXFBConfig> cfgs;
    1199                 :     cfgs = sGLXLibrary.xChooseFBConfig(display,
    1200                 :                                        xscreen,
    1201                 :                                        attribs,
    1202               0 :                                        &numConfigs);
    1203               0 :     if (!cfgs) {
    1204               0 :         return nsnull;
    1205                 :     }
    1206                 : 
    1207               0 :     NS_ASSERTION(numConfigs > 0,
    1208                 :                  "glXChooseFBConfig() failed to match our requested format and violated its spec (!)");
    1209                 : 
    1210               0 :     ScopedXFree<XVisualInfo> vinfo;
    1211               0 :     int chosenIndex = 0;
    1212                 : 
    1213               0 :     for (int i = 0; i < numConfigs; ++i) {
    1214                 :         int dtype, visid;
    1215                 : 
    1216               0 :         if (sGLXLibrary.xGetFBConfigAttrib(display, cfgs[i], GLX_DRAWABLE_TYPE, &dtype) != Success
    1217               0 :             || !(dtype & GLX_PIXMAP_BIT))
    1218                 :         {
    1219               0 :             continue;
    1220                 :         }
    1221               0 :         if (sGLXLibrary.xGetFBConfigAttrib(display, cfgs[i], GLX_VISUAL_ID, &visid) != Success
    1222                 :             || visid == 0)
    1223                 :         {
    1224               0 :             continue;
    1225                 :         }
    1226                 : 
    1227               0 :         vinfo = sGLXLibrary.xGetVisualFromFBConfig(display, cfgs[i]);
    1228                 : 
    1229               0 :         if (vinfo) {
    1230               0 :             chosenIndex = i;
    1231               0 :             break;
    1232                 :         }
    1233                 :     }
    1234                 : 
    1235               0 :     if (!vinfo) {
    1236               0 :         NS_WARNING("glXChooseFBConfig() didn't give us any configs with visuals!");
    1237               0 :         return nsnull;
    1238                 :     }
    1239                 : 
    1240               0 :     ScopedXErrorHandler xErrorHandler;
    1241               0 :     GLXPixmap glxpixmap = 0;
    1242               0 :     bool error = false;
    1243                 : 
    1244                 :     nsRefPtr<gfxXlibSurface> xsurface = gfxXlibSurface::Create(DefaultScreenOfDisplay(display),
    1245               0 :                                                                vinfo->visual,
    1246               0 :                                                                gfxIntSize(16, 16));
    1247               0 :     if (xsurface->CairoStatus() != 0) {
    1248               0 :         error = true;
    1249               0 :         goto DONE_CREATING_PIXMAP;
    1250                 :     }
    1251                 : 
    1252                 :     // Handle slightly different signature between glXCreatePixmap and
    1253                 :     // its pre-GLX-1.3 extension equivalent (though given the ABI, we
    1254                 :     // might not need to).
    1255               0 :     if (GLXVersionCheck(1, 3)) {
    1256                 :         glxpixmap = sGLXLibrary.xCreatePixmap(display,
    1257               0 :                                               cfgs[chosenIndex],
    1258                 :                                               xsurface->XDrawable(),
    1259               0 :                                               NULL);
    1260                 :     } else {
    1261                 :         glxpixmap = sGLXLibrary.xCreateGLXPixmapWithConfig(display,
    1262               0 :                                                            cfgs[chosenIndex],
    1263                 :                                                            xsurface->
    1264               0 :                                                              XDrawable());
    1265                 :     }
    1266               0 :     if (glxpixmap == 0) {
    1267               0 :         error = true;
    1268                 :     }
    1269                 : 
    1270                 : DONE_CREATING_PIXMAP:
    1271                 : 
    1272               0 :     nsRefPtr<GLContextGLX> glContext;
    1273               0 :     bool serverError = xErrorHandler.SyncAndGetError(display);
    1274                 : 
    1275               0 :     if (!error && // earlier recorded error
    1276               0 :         !serverError)
    1277                 :     {
    1278                 :         glContext = GLContextGLX::CreateGLContext(
    1279                 :                         aFormat,
    1280                 :                         display,
    1281                 :                         glxpixmap,
    1282               0 :                         cfgs[chosenIndex],
    1283                 :                         vinfo,
    1284                 :                         aShare ? GetGlobalContextGLX() : nsnull,
    1285                 :                         true,
    1286               0 :                         xsurface);
    1287                 :     }
    1288                 : 
    1289               0 :     return glContext.forget();
    1290                 : }
    1291                 : 
    1292                 : already_AddRefed<GLContext>
    1293               0 : GLContextProviderGLX::CreateOffscreen(const gfxIntSize& aSize,
    1294                 :                                       const ContextFormat& aFormat)
    1295                 : {
    1296                 :     nsRefPtr<GLContextGLX> glContext =
    1297               0 :         CreateOffscreenPixmapContext(aSize, aFormat, true);
    1298                 : 
    1299               0 :     if (!glContext) {
    1300               0 :         return nsnull;
    1301                 :     }
    1302                 : 
    1303               0 :     if (!glContext->GetSharedContext()) {
    1304                 :         // no point in returning anything if sharing failed, we can't
    1305                 :         // render from this
    1306               0 :         return nsnull;
    1307                 :     }
    1308                 : 
    1309               0 :     if (!glContext->ResizeOffscreenFBO(aSize, true)) {
    1310                 :         // we weren't able to create the initial
    1311                 :         // offscreen FBO, so this is dead
    1312               0 :         return nsnull;
    1313                 :     }
    1314                 : 
    1315               0 :     return glContext.forget();
    1316                 : }
    1317                 : 
    1318                 : already_AddRefed<GLContext>
    1319               0 : GLContextProviderGLX::CreateForNativePixmapSurface(gfxASurface *aSurface)
    1320                 : {
    1321               0 :     if (!sGLXLibrary.EnsureInitialized()) {
    1322               0 :         return nsnull;
    1323                 :     }
    1324                 : 
    1325               0 :     if (aSurface->GetType() != gfxASurface::SurfaceTypeXlib) {
    1326               0 :         NS_WARNING("GLContextProviderGLX::CreateForNativePixmapSurface called with non-Xlib surface");
    1327               0 :         return nsnull;
    1328                 :     }
    1329                 : 
    1330               0 :     nsAutoTArray<int, 20> attribs;
    1331                 : 
    1332                 : #define A1_(_x)  do { attribs.AppendElement(_x); } while(0)
    1333                 : #define A2_(_x,_y)  do {                                                \
    1334                 :         attribs.AppendElement(_x);                                      \
    1335                 :         attribs.AppendElement(_y);                                      \
    1336                 :     } while(0)
    1337                 : 
    1338               0 :     A2_(GLX_DOUBLEBUFFER, False);
    1339               0 :     A2_(GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT);
    1340               0 :     A1_(0);
    1341                 : 
    1342                 :     int numFormats;
    1343               0 :     Display *display = DefaultXDisplay();
    1344               0 :     int xscreen = DefaultScreen(display);
    1345                 : 
    1346                 :     ScopedXFree<GLXFBConfig> cfg(sGLXLibrary.xChooseFBConfig(display,
    1347                 :                                                              xscreen,
    1348               0 :                                                              attribs.Elements(),
    1349               0 :                                                              &numFormats));
    1350               0 :     if (!cfg) {
    1351               0 :         return nsnull;
    1352                 :     }
    1353               0 :     NS_ASSERTION(numFormats > 0,
    1354                 :                  "glXChooseFBConfig() failed to match our requested format and violated its spec (!)");
    1355                 : 
    1356               0 :     gfxXlibSurface *xs = static_cast<gfxXlibSurface*>(aSurface);
    1357                 : 
    1358                 :     GLXPixmap glxpixmap = sGLXLibrary.xCreatePixmap(display,
    1359               0 :                                                     cfg[0],
    1360                 :                                                     xs->XDrawable(),
    1361               0 :                                                     NULL);
    1362                 : 
    1363                 :     nsRefPtr<GLContextGLX> glContext = GLContextGLX::CreateGLContext(ContextFormat(ContextFormat::BasicRGB24),
    1364                 :                                                                      display,
    1365                 :                                                                      glxpixmap,
    1366               0 :                                                                      cfg[0],
    1367                 :                                                                      NULL,
    1368                 :                                                                      NULL,
    1369                 :                                                                      false,
    1370               0 :                                                                      xs);
    1371                 : 
    1372               0 :     return glContext.forget();
    1373                 : }
    1374                 : 
    1375            1464 : static nsRefPtr<GLContext> gGlobalContext;
    1376                 : 
    1377                 : GLContext *
    1378               0 : GLContextProviderGLX::GetGlobalContext()
    1379                 : {
    1380                 :     static bool triedToCreateContext = false;
    1381               0 :     if (!triedToCreateContext && !gGlobalContext) {
    1382               0 :         triedToCreateContext = true;
    1383                 :         gGlobalContext = CreateOffscreenPixmapContext(gfxIntSize(1, 1),
    1384                 :                                                       ContextFormat(ContextFormat::BasicRGB24),
    1385               0 :                                                       false);
    1386               0 :         if (gGlobalContext)
    1387               0 :             gGlobalContext->SetIsGlobalSharedContext(true);
    1388                 :     }
    1389                 : 
    1390               0 :     return gGlobalContext;
    1391                 : }
    1392                 : 
    1393                 : void
    1394               4 : GLContextProviderGLX::Shutdown()
    1395                 : {
    1396               4 :     gGlobalContext = nsnull;
    1397               4 : }
    1398                 : 
    1399                 : } /* namespace gl */
    1400            4392 : } /* namespace mozilla */
    1401                 : 

Generated by: LCOV version 1.7