LCOV - code coverage report
Current view: directory - gfx/gl - GLContextProviderOSMesa.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 93 5 5.4 %
Date: 2012-06-02 Functions: 19 4 21.1 %

       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                 :  *   Benoit Jacob <bjacob@mozilla.com>
      21                 :  *   Bas Schouten <bschouten@mozilla.com>
      22                 :  *   Vladimir Vukicevic <vladimir@pobox.com>
      23                 :  *
      24                 :  * Alternatively, the contents of this file may be used under the terms of
      25                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      26                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      27                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      28                 :  * of those above. If you wish to allow use of your version of this file only
      29                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      30                 :  * use your version of this file under the terms of the MPL, indicate your
      31                 :  * decision by deleting the provisions above and replace them with the notice
      32                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      33                 :  * the provisions above, a recipient may use your version of this file under
      34                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      35                 :  *
      36                 :  * ***** END LICENSE BLOCK ***** */
      37                 : 
      38                 : #include "GLContextProvider.h"
      39                 : #include "GLContext.h"
      40                 : #include "nsDebug.h"
      41                 : #include "nsString.h"
      42                 : #include "nsIWidget.h"
      43                 : #include "nsDirectoryServiceUtils.h"
      44                 : #include "nsAppDirectoryServiceDefs.h"
      45                 : #include "nsIConsoleService.h"
      46                 : #include "mozilla/Preferences.h"
      47                 : #include "gfxASurface.h"
      48                 : #include "gfxImageSurface.h"
      49                 : 
      50                 : #include "gfxCrashReporterUtils.h"
      51                 : 
      52                 : // from GL/osmesa.h. We don't include that file so as to avoid having a build-time dependency on OSMesa.
      53                 : #define OSMESA_RGBA     GL_RGBA
      54                 : #define OSMESA_BGRA     0x1
      55                 : #define OSMESA_ARGB     0x2
      56                 : #define OSMESA_RGB      GL_RGB
      57                 : #define OSMESA_BGR      0x4
      58                 : #define OSMESA_RGB_565  0x5
      59                 : #define OSMESA_Y_UP     0x11
      60                 : 
      61                 : namespace mozilla {
      62                 : namespace gl {
      63                 : 
      64               0 : static void LogMessage(const char *msg)
      65                 : {
      66               0 :   nsCOMPtr<nsIConsoleService> console(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
      67               0 :   if (console) {
      68               0 :     console->LogStringMessage(NS_ConvertUTF8toUTF16(nsDependentCString(msg)).get());
      69               0 :     fprintf(stderr, "%s\n", msg);
      70                 :   }
      71               0 : }
      72                 : 
      73                 : typedef void* PrivateOSMesaContext;
      74                 : 
      75                 : class OSMesaLibrary
      76                 : {
      77                 : public:
      78            1464 :     OSMesaLibrary() : mInitialized(false), mOSMesaLibrary(nsnull) {}
      79                 : 
      80                 :     typedef PrivateOSMesaContext (GLAPIENTRY * PFNOSMESACREATECONTEXTEXT) (GLenum, GLint, GLint, GLint, PrivateOSMesaContext);
      81                 :     typedef void (GLAPIENTRY * PFNOSMESADESTROYCONTEXT) (PrivateOSMesaContext);
      82                 :     typedef bool (GLAPIENTRY * PFNOSMESAMAKECURRENT) (PrivateOSMesaContext, void *, GLenum, GLsizei, GLsizei);
      83                 :     typedef PrivateOSMesaContext (GLAPIENTRY * PFNOSMESAGETCURRENTCONTEXT) (void);
      84                 :     typedef void (GLAPIENTRY * PFNOSMESAPIXELSTORE) (GLint, GLint);
      85                 :     typedef PRFuncPtr (GLAPIENTRY * PFNOSMESAGETPROCADDRESS) (const char*);
      86                 : 
      87                 :     PFNOSMESACREATECONTEXTEXT fCreateContextExt;
      88                 :     PFNOSMESADESTROYCONTEXT fDestroyContext;
      89                 :     PFNOSMESAMAKECURRENT fMakeCurrent;
      90                 :     PFNOSMESAGETCURRENTCONTEXT fGetCurrentContext;
      91                 :     PFNOSMESAPIXELSTORE fPixelStore;
      92                 :     PFNOSMESAGETPROCADDRESS fGetProcAddress;
      93                 : 
      94                 :     bool EnsureInitialized();
      95                 : 
      96                 : private:
      97                 :     bool mInitialized;
      98                 :     PRLibrary *mOSMesaLibrary;
      99                 : };
     100                 : 
     101            1464 : OSMesaLibrary sOSMesaLibrary;
     102                 : 
     103                 : bool
     104               0 : OSMesaLibrary::EnsureInitialized()
     105                 : {
     106               0 :     if (mInitialized)
     107               0 :         return true;
     108                 : 
     109               0 :     nsAdoptingCString osmesalib = Preferences::GetCString("webgl.osmesalib");
     110               0 :     if (osmesalib.IsEmpty()) {
     111               0 :         return false;
     112                 :     }
     113                 : 
     114               0 :     mOSMesaLibrary = PR_LoadLibrary(osmesalib.get());
     115                 : 
     116               0 :     if (!mOSMesaLibrary) {
     117               0 :         LogMessage("Couldn't open OSMesa lib for software rendering -- webgl.osmesalib path is incorrect, or not a valid shared library");
     118               0 :         return false;
     119                 :     }
     120                 : 
     121                 :     LibrarySymbolLoader::SymLoadStruct symbols[] = {
     122                 :         { (PRFuncPtr*) &fCreateContextExt, { "OSMesaCreateContextExt", NULL } },
     123                 :         { (PRFuncPtr*) &fMakeCurrent, { "OSMesaMakeCurrent", NULL } },
     124                 :         { (PRFuncPtr*) &fPixelStore, { "OSMesaPixelStore", NULL } },
     125                 :         { (PRFuncPtr*) &fDestroyContext, { "OSMesaDestroyContext", NULL } },
     126                 :         { (PRFuncPtr*) &fGetCurrentContext, { "OSMesaGetCurrentContext", NULL } },
     127                 :         { (PRFuncPtr*) &fMakeCurrent, { "OSMesaMakeCurrent", NULL } },
     128                 :         { (PRFuncPtr*) &fGetProcAddress, { "OSMesaGetProcAddress", NULL } },
     129                 :         { NULL, { NULL } }
     130               0 :     };
     131                 : 
     132               0 :     if (!LibrarySymbolLoader::LoadSymbols(mOSMesaLibrary, &symbols[0])) {
     133               0 :         LogMessage("Couldn't find required entry points in OSMesa libary");
     134               0 :         return false;
     135                 :     }
     136                 : 
     137               0 :     mInitialized = true;
     138               0 :     return true;
     139                 : }
     140                 : 
     141                 : class GLContextOSMesa : public GLContext
     142                 : {
     143                 : public:
     144               0 :     GLContextOSMesa(const ContextFormat& aFormat)
     145                 :         : GLContext(aFormat, true, nsnull),
     146                 :           mThebesSurface(nsnull),
     147               0 :           mContext(nsnull)
     148                 :     {
     149               0 :     }
     150                 : 
     151               0 :     ~GLContextOSMesa()
     152               0 :     {
     153               0 :         MarkDestroyed();
     154                 : 
     155               0 :         if (mContext)
     156               0 :             sOSMesaLibrary.fDestroyContext(mContext);
     157               0 :     }
     158                 : 
     159               0 :     GLContextType GetContextType() {
     160               0 :         return ContextTypeOSMesa;
     161                 :     }
     162                 : 
     163               0 :     bool Init(const gfxIntSize &aSize)
     164                 :     {
     165               0 :         int osmesa_format = -1;
     166               0 :         int gfxasurface_imageformat = -1;
     167               0 :         bool format_accepted = false;
     168                 : 
     169               0 :         if (mCreationFormat.red > 0 &&
     170                 :             mCreationFormat.green > 0 &&
     171                 :             mCreationFormat.blue > 0 &&
     172                 :             mCreationFormat.red <= 8 &&
     173                 :             mCreationFormat.green <= 8 &&
     174                 :             mCreationFormat.blue <= 8)
     175                 :         {
     176               0 :             if (mCreationFormat.alpha == 0) {
     177                 :                 // we can't use OSMESA_BGR because it is packed 24 bits per pixel.
     178                 :                 // So we use OSMESA_BGRA and have to use ImageFormatRGB24
     179                 :                 // to make sure that the dummy alpha channel is ignored.
     180               0 :                 osmesa_format = OSMESA_BGRA;
     181               0 :                 gfxasurface_imageformat = gfxASurface::ImageFormatRGB24;
     182               0 :                 format_accepted = true;
     183               0 :             } else if (mCreationFormat.alpha <= 8) {
     184               0 :                 osmesa_format = OSMESA_BGRA;
     185               0 :                 gfxasurface_imageformat = gfxASurface::ImageFormatARGB32;
     186               0 :                 format_accepted = true;
     187                 :             }
     188                 :         }
     189               0 :         if (!format_accepted) {
     190               0 :             NS_WARNING("Pixel format not supported with OSMesa.");
     191               0 :             return false;
     192                 :         }
     193                 : 
     194               0 :         mThebesSurface = new gfxImageSurface(aSize, gfxASurface::gfxImageFormat(gfxasurface_imageformat));
     195               0 :         if (mThebesSurface->CairoStatus() != 0) {
     196               0 :             NS_WARNING("image surface failed");
     197               0 :             return false;
     198                 :         }
     199                 : 
     200               0 :         mContext = sOSMesaLibrary.fCreateContextExt(osmesa_format, mCreationFormat.depth, mCreationFormat.stencil, 0, NULL);
     201               0 :         if (!mContext) {
     202               0 :             NS_WARNING("OSMesaCreateContextExt failed!");
     203               0 :             return false;
     204                 :         }
     205                 : 
     206               0 :         if (!MakeCurrent()) return false;
     207               0 :         if (!SetupLookupFunction()) return false;
     208                 : 
     209                 :         // OSMesa's different from the other GL providers, it renders to an image surface, not to a pbuffer
     210               0 :         sOSMesaLibrary.fPixelStore(OSMESA_Y_UP, 0);
     211                 : 
     212               0 :         return InitWithPrefix("gl", true);
     213                 :     }
     214                 : 
     215               0 :     bool MakeCurrentImpl(bool aForce = false)
     216                 :     {
     217                 :         bool succeeded
     218               0 :           = sOSMesaLibrary.fMakeCurrent(mContext, mThebesSurface->Data(),
     219                 :                                         LOCAL_GL_UNSIGNED_BYTE,
     220                 :                                         mThebesSurface->Width(),
     221               0 :                                         mThebesSurface->Height());
     222               0 :         NS_ASSERTION(succeeded, "Failed to make OSMesa context current!");
     223                 : 
     224               0 :         return succeeded;
     225                 :     }
     226                 : 
     227               0 :     bool SetupLookupFunction()
     228                 :     {
     229               0 :         mLookupFunc = (PlatformLookupFunction)sOSMesaLibrary.fGetProcAddress;
     230               0 :         return true;
     231                 :     }
     232                 : 
     233               0 :     void *GetNativeData(NativeDataType aType)
     234                 :     {
     235               0 :         switch (aType) {
     236                 :         case NativeImageSurface:
     237               0 :             return mThebesSurface.get();
     238                 :         default:
     239               0 :             return nsnull;
     240                 :         }
     241                 :     }
     242                 : 
     243               0 :     bool SupportsRobustness()
     244                 :     {
     245               0 :         return false;
     246                 :     }
     247                 : 
     248                 : private:
     249                 :     nsRefPtr<gfxImageSurface> mThebesSurface;
     250                 :     PrivateOSMesaContext mContext;
     251                 : };
     252                 : 
     253                 : already_AddRefed<GLContext>
     254               0 : GLContextProviderOSMesa::CreateForWindow(nsIWidget *aWidget)
     255                 : {
     256               0 :     return nsnull;
     257                 : }
     258                 : 
     259                 : already_AddRefed<GLContext>
     260               0 : GLContextProviderOSMesa::CreateOffscreen(const gfxIntSize& aSize,
     261                 :                                          const ContextFormat& aFormat)
     262                 : {
     263               0 :     if (!sOSMesaLibrary.EnsureInitialized()) {
     264               0 :         return nsnull;
     265                 :     }
     266                 : 
     267               0 :     ContextFormat actualFormat(aFormat);
     268               0 :     actualFormat.samples = 0;
     269                 : 
     270               0 :     nsRefPtr<GLContextOSMesa> glContext = new GLContextOSMesa(actualFormat);
     271                 : 
     272               0 :     if (!glContext->Init(aSize))
     273                 :     {
     274               0 :         return nsnull;
     275                 :     }
     276                 : 
     277               0 :     return glContext.forget();
     278                 : }
     279                 : 
     280                 : GLContext *
     281               0 : GLContextProviderOSMesa::GetGlobalContext()
     282                 : {
     283               0 :     return nsnull;
     284                 : }
     285                 : 
     286                 : void
     287               4 : GLContextProviderOSMesa::Shutdown()
     288                 : {
     289               4 : }
     290                 : 
     291                 : } /* namespace gl */
     292            4392 : } /* namespace mozilla */

Generated by: LCOV version 1.7