LCOV - code coverage report
Current view: top level - vcl/source/opengl - OpenGLContext.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 80 447 17.9 %
Date: 2015-06-13 12:38:46 Functions: 15 50 30.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  */
       9             : 
      10             : #include <vcl/opengl/OpenGLContext.hxx>
      11             : #include <vcl/opengl/OpenGLHelper.hxx>
      12             : #include <vcl/syschild.hxx>
      13             : #include <vcl/sysdata.hxx>
      14             : 
      15             : #include <boost/scoped_array.hpp>
      16             : #include <boost/make_shared.hpp>
      17             : #include <vcl/pngwrite.hxx>
      18             : #include <vcl/bmpacc.hxx>
      19             : #include <vcl/graph.hxx>
      20             : 
      21             : #if defined(MACOSX)
      22             : #include <premac.h>
      23             : #include "OpenGLWrapper.hxx"
      24             : #include <postmac.h>
      25             : #endif
      26             : 
      27             : #if defined( WNT )
      28             : #include <win/saldata.hxx>
      29             : #endif
      30             : 
      31             : #include "svdata.hxx"
      32             : 
      33             : #include <opengl/framebuffer.hxx>
      34             : #include <opengl/program.hxx>
      35             : #include <opengl/texture.hxx>
      36             : 
      37             : using namespace com::sun::star;
      38             : 
      39             : #define MAX_FRAMEBUFFER_COUNT 30
      40             : 
      41             : // TODO use rtl::Static instead of 'static'
      42             : #if defined( UNX ) && !defined MACOSX && !defined IOS && !defined ANDROID && !defined(LIBO_HEADLESS)
      43         267 : static std::vector<GLXContext> g_vShareList;
      44             : #elif defined(WNT)
      45             : static std::vector<HGLRC> g_vShareList;
      46             : #endif
      47             : 
      48          18 : GLWindow::~GLWindow()
      49             : {
      50             : #if defined( UNX ) && !defined MACOSX && !defined IOS && !defined ANDROID && !defined(LIBO_HEADLESS)
      51          18 :     XFree(vi);
      52             : #endif
      53          18 : }
      54             : 
      55          18 : OpenGLContext::OpenGLContext():
      56             :     mpWindow(NULL),
      57             :     m_pChildWindow(NULL),
      58             :     mbInitialized(false),
      59             :     mnRefCount(1),
      60             :     mbRequestLegacyContext(false),
      61             :     mbUseDoubleBufferedRendering(true),
      62             :     mbRequestVirtualDevice(false),
      63             :     mnFramebufferCount(0),
      64             :     mpCurrentFramebuffer(NULL),
      65             :     mpFirstFramebuffer(NULL),
      66             :     mpLastFramebuffer(NULL),
      67             :     mpCurrentProgram(NULL),
      68             :     mnPainting(0),
      69             :     mpPrevContext(NULL),
      70          18 :     mpNextContext(NULL)
      71             : {
      72             :     SAL_INFO("vcl.opengl", "new context: " << this);
      73             : #if defined( UNX ) && !defined MACOSX && !defined IOS && !defined ANDROID && !defined(LIBO_HEADLESS)
      74          18 :     mbPixmap = false;
      75             : #endif
      76             : 
      77          18 :     ImplSVData* pSVData = ImplGetSVData();
      78          18 :     if( pSVData->maGDIData.mpLastContext )
      79             :     {
      80          14 :         pSVData->maGDIData.mpLastContext->mpNextContext = this;
      81          14 :         mpPrevContext = pSVData->maGDIData.mpLastContext;
      82             :     }
      83             :     else
      84           4 :         pSVData->maGDIData.mpFirstContext = this;
      85          18 :     pSVData->maGDIData.mpLastContext = this;
      86             : 
      87             :     // FIXME: better hope we call 'makeCurrent' soon to preserve
      88             :     // the invariant that the last item is the current context.
      89          18 : }
      90             : 
      91          36 : OpenGLContext::~OpenGLContext()
      92             : {
      93             :     SAL_INFO("vcl.opengl", "delete context: " << this);
      94          18 :     reset();
      95             : 
      96          18 :     ImplSVData* pSVData = ImplGetSVData();
      97          18 :     if( mpPrevContext )
      98          13 :         mpPrevContext->mpNextContext = mpNextContext;
      99             :     else
     100           5 :         pSVData->maGDIData.mpFirstContext = mpNextContext;
     101          18 :     if( mpNextContext )
     102           1 :         mpNextContext->mpPrevContext = mpPrevContext;
     103             :     else
     104          17 :         pSVData->maGDIData.mpLastContext = mpPrevContext;
     105             : 
     106          18 :     m_pChildWindow.disposeAndClear();
     107          18 : }
     108             : 
     109             : #ifdef DBG_UTIL
     110             : void OpenGLContext::AddRef(SalGraphicsImpl* pImpl)
     111             : {
     112             :     assert(mnRefCount > 0);
     113             :     mnRefCount++;
     114             : 
     115             :     maParents.insert(pImpl);
     116             : }
     117             : 
     118             : void OpenGLContext::DeRef(SalGraphicsImpl* pImpl)
     119             : {
     120             : 
     121             :     auto it = maParents.find(pImpl);
     122             :     if(it != maParents.end())
     123             :         maParents.erase(it);
     124             : 
     125             :     assert(mnRefCount > 0);
     126             :     if( --mnRefCount == 0 )
     127             :         delete this;
     128             : }
     129             : #else
     130           0 : void OpenGLContext::AddRef()
     131             : {
     132             :     assert(mnRefCount > 0);
     133           0 :     mnRefCount++;
     134           0 : }
     135             : 
     136           0 : void OpenGLContext::DeRef()
     137             : {
     138             :     assert(mnRefCount > 0);
     139           0 :     if( --mnRefCount == 0 )
     140           0 :         delete this;
     141           0 : }
     142             : #endif
     143             : 
     144           0 : void OpenGLContext::requestLegacyContext()
     145             : {
     146           0 :     mbRequestLegacyContext = true;
     147           0 : }
     148             : 
     149           0 : void OpenGLContext::requestSingleBufferedRendering()
     150             : {
     151           0 :     mbUseDoubleBufferedRendering = false;
     152           0 : }
     153             : 
     154           0 : void OpenGLContext::requestVirtualDevice()
     155             : {
     156           0 :     mbRequestVirtualDevice = true;
     157           0 : }
     158             : 
     159             : #if defined( _WIN32 )
     160             : static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
     161             : {
     162             :     switch (message)
     163             :     {
     164             :     case WM_CREATE:
     165             :         return 0;
     166             :     case WM_CLOSE:
     167             :         PostQuitMessage(0);
     168             :         return 0;
     169             :     case WM_DESTROY:
     170             :         return 0;
     171             :     case WM_KEYDOWN:
     172             :         switch(wParam)
     173             :         {
     174             :         case VK_ESCAPE:
     175             :             PostQuitMessage(0);
     176             :             return 0;
     177             : 
     178             :         case VK_SPACE:
     179             :             break;
     180             :         }
     181             :     default:
     182             :         return DefWindowProc(hwnd, message, wParam, lParam);
     183             :     }
     184             : }
     185             : 
     186             : int InitTempWindow(HWND *hwnd, int width, int height, const PIXELFORMATDESCRIPTOR& inPfd, GLWindow& glWin)
     187             : {
     188             :     PIXELFORMATDESCRIPTOR  pfd = inPfd;
     189             :     int  pfmt;
     190             :     int ret;
     191             :     WNDCLASS wc;
     192             :     wc.style = 0;
     193             :     wc.lpfnWndProc = WndProc;
     194             :     wc.cbClsExtra = wc.cbWndExtra = 0;
     195             :     wc.hInstance = NULL;
     196             :     wc.hIcon = NULL;
     197             :     wc.hCursor = NULL;
     198             :     wc.hbrBackground = NULL;
     199             :     wc.lpszMenuName = NULL;
     200             :     wc.lpszClassName = (LPCSTR)"GLRenderer";
     201             :     RegisterClass(&wc);
     202             :     *hwnd = CreateWindow(wc.lpszClassName, NULL, WS_DISABLED, 0, 0, width, height, NULL, NULL, wc.hInstance, NULL);
     203             :     glWin.hDC = GetDC(*hwnd);
     204             :     pfmt = ChoosePixelFormat(glWin.hDC, &pfd);
     205             :     if (!pfmt)
     206             :     {
     207             :         return -1;
     208             :     }
     209             :     ret = SetPixelFormat(glWin.hDC, pfmt, &pfd);
     210             :     if(!ret)
     211             :     {
     212             :         return -1;
     213             :     }
     214             :     glWin.hRC = wglCreateContext(glWin.hDC);
     215             :     if(!(glWin.hRC))
     216             :     {
     217             :         return -1;
     218             :     }
     219             :     ret = wglMakeCurrent(glWin.hDC, glWin.hRC);
     220             :     if(!ret)
     221             :     {
     222             :         return -1;
     223             :     }
     224             : 
     225             :     CHECK_GL_ERROR();
     226             :     return 0;
     227             : }
     228             : 
     229             : bool WGLisExtensionSupported(const char *extension)
     230             : {
     231             :     const size_t extlen = strlen(extension);
     232             :     const char *supported = NULL;
     233             : 
     234             :     // Try To Use wglGetExtensionStringARB On Current DC, If Possible
     235             :     PROC wglGetExtString = wglGetProcAddress("wglGetExtensionsStringARB");
     236             : 
     237             :     if (wglGetExtString)
     238             :         supported = ((char*(__stdcall*)(HDC))wglGetExtString)(wglGetCurrentDC());
     239             :     // If That Failed, Try Standard Opengl Extensions String
     240             :     if (supported == NULL)
     241             :         supported = (char*)glGetString(GL_EXTENSIONS);
     242             :     // If That Failed Too, Must Be No Extensions Supported
     243             :     if (supported == NULL)
     244             :         return false;
     245             : 
     246             :     // Begin Examination At Start Of String, Increment By 1 On False Match
     247             :     for (const char* p = supported; ; p++)
     248             :     {
     249             :         // Advance p Up To The Next Possible Match
     250             :         p = strstr(p, extension);
     251             : 
     252             :         if (p == NULL)
     253             :             return 0; // No Match
     254             : 
     255             :         // Make Sure That Match Is At The Start Of The String Or That
     256             :         // The Previous Char Is A Space, Or Else We Could Accidentally
     257             :         // Match "wglFunkywglExtension" With "wglExtension"
     258             : 
     259             :         // Also, Make Sure That The Following Character Is Space Or NULL
     260             :         // Or Else "wglExtensionTwo" Might Match "wglExtension"
     261             :         if ((p==supported || p[-1]==' ') && (p[extlen]=='\0' || p[extlen]==' '))
     262             :             return 1; // Match
     263             :     }
     264             : }
     265             : 
     266             : bool InitMultisample(const PIXELFORMATDESCRIPTOR& pfd, int& rPixelFormat,
     267             :         bool bUseDoubleBufferedRendering, bool bRequestVirtualDevice)
     268             : {
     269             :     HWND hWnd = NULL;
     270             :     GLWindow glWin;
     271             :     //create a temp windwo to check whether support multi-sample, if support, get the format
     272             :     if (InitTempWindow(&hWnd, 1, 1, pfd, glWin) < 0)
     273             :     {
     274             :         SAL_WARN("vcl.opengl", "Can't create temp window to test");
     275             :         return false;
     276             :     }
     277             : 
     278             :     // See If The String Exists In WGL!
     279             :     if (!WGLisExtensionSupported("WGL_ARB_multisample"))
     280             :     {
     281             :         SAL_WARN("vcl.opengl", "Device doesn't support multi sample");
     282             :         return false;
     283             :     }
     284             :     // Get Our Pixel Format
     285             :     PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB");
     286             :     if (!wglChoosePixelFormatARB)
     287             :     {
     288             :         return false;
     289             :     }
     290             :     // Get Our Current Device Context
     291             :     HDC hDC = GetDC(hWnd);
     292             : 
     293             :     int pixelFormat;
     294             :     int valid;
     295             :     UINT    numFormats;
     296             :     float   fAttributes[] = {0,0};
     297             :     // These Attributes Are The Bits We Want To Test For In Our Sample
     298             :     // Everything Is Pretty Standard, The Only One We Want To
     299             :     // Really Focus On Is The SAMPLE BUFFERS ARB And WGL SAMPLES
     300             :     // These Two Are Going To Do The Main Testing For Whether Or Not
     301             :     // We Support Multisampling On This Hardware.
     302             :     int iAttributes[] =
     303             :     {
     304             :         WGL_DOUBLE_BUFFER_ARB,GL_TRUE,
     305             :         WGL_DRAW_TO_WINDOW_ARB,GL_TRUE,
     306             :         WGL_SUPPORT_OPENGL_ARB,GL_TRUE,
     307             :         WGL_ACCELERATION_ARB,WGL_FULL_ACCELERATION_ARB,
     308             :         WGL_COLOR_BITS_ARB,24,
     309             :         WGL_ALPHA_BITS_ARB,8,
     310             :         WGL_DEPTH_BITS_ARB,24,
     311             :         WGL_STENCIL_BITS_ARB,0,
     312             :         WGL_SAMPLE_BUFFERS_ARB,GL_TRUE,
     313             :         WGL_SAMPLES_ARB,8,
     314             :         0,0
     315             :     };
     316             : 
     317             :     if (!bUseDoubleBufferedRendering)
     318             :         iAttributes[1] = GL_FALSE;
     319             : 
     320             :     if (bRequestVirtualDevice)
     321             :     {
     322             :         iAttributes[2] = WGL_DRAW_TO_BITMAP_ARB;
     323             :     }
     324             : 
     325             :     bool bArbMultisampleSupported = true;
     326             : 
     327             :     // First We Check To See If We Can Get A Pixel Format For 4 Samples
     328             :     valid = wglChoosePixelFormatARB(hDC, iAttributes, fAttributes, 1, &pixelFormat, &numFormats);
     329             :     // If We Returned True, And Our Format Count Is Greater Than 1
     330             :     if (valid && numFormats >= 1)
     331             :     {
     332             :         bArbMultisampleSupported = true;
     333             :         rPixelFormat = pixelFormat;
     334             :         wglMakeCurrent(NULL, NULL);
     335             :         wglDeleteContext(glWin.hRC);
     336             :         ReleaseDC(hWnd, glWin.hDC);
     337             :         DestroyWindow(hWnd);
     338             :         return bArbMultisampleSupported;
     339             :     }
     340             :     // Our Pixel Format With 4 Samples Failed, Test For 2 Samples
     341             :     iAttributes[19] = 2;
     342             :     valid = wglChoosePixelFormatARB(hDC, iAttributes, fAttributes, 1, &pixelFormat, &numFormats);
     343             :     if (valid && numFormats >= 1)
     344             :     {
     345             :         bArbMultisampleSupported = true;
     346             :         rPixelFormat = pixelFormat;
     347             :         wglMakeCurrent(NULL, NULL);
     348             :         wglDeleteContext(glWin.hRC);
     349             :         ReleaseDC(hWnd, glWin.hDC);
     350             :         DestroyWindow(hWnd);
     351             :         return bArbMultisampleSupported;
     352             :     }
     353             :     // Return The Valid Format
     354             :     wglMakeCurrent(NULL, NULL);
     355             :     wglDeleteContext(glWin.hRC);
     356             :     ReleaseDC(hWnd, glWin.hDC);
     357             :     DestroyWindow(hWnd);
     358             : 
     359             :     return bArbMultisampleSupported;
     360             : }
     361             : #endif
     362             : 
     363             : #ifdef DBG_UTIL
     364             : 
     365             : namespace {
     366             : 
     367             : const char* getSeverityString(GLenum severity)
     368             : {
     369             :     switch(severity)
     370             :     {
     371             :         case GL_DEBUG_SEVERITY_LOW:
     372             :             return "low";
     373             :         case GL_DEBUG_SEVERITY_MEDIUM:
     374             :             return "medium";
     375             :         case GL_DEBUG_SEVERITY_HIGH:
     376             :             return "high";
     377             :         default:
     378             :             ;
     379             :     }
     380             : 
     381             :     return "unknown";
     382             : }
     383             : 
     384             : const char* getSourceString(GLenum source)
     385             : {
     386             :     switch(source)
     387             :     {
     388             :         case GL_DEBUG_SOURCE_API:
     389             :             return "API";
     390             :         case GL_DEBUG_SOURCE_SHADER_COMPILER:
     391             :             return "shader compiler";
     392             :         case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
     393             :             return "window system";
     394             :         case GL_DEBUG_SOURCE_THIRD_PARTY:
     395             :             return "third party";
     396             :         case GL_DEBUG_SOURCE_APPLICATION:
     397             :             return "Libreoffice";
     398             :         case GL_DEBUG_SOURCE_OTHER:
     399             :             return "unknown";
     400             :         default:
     401             :             ;
     402             :     }
     403             : 
     404             :     return "unknown";
     405             : }
     406             : 
     407             : const char* getTypeString(GLenum type)
     408             : {
     409             :     switch(type)
     410             :     {
     411             :         case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
     412             :             return "deprecated behavior";
     413             :         case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
     414             :             return "undefined behavior";
     415             :         case GL_DEBUG_TYPE_PERFORMANCE:
     416             :             return "performance";
     417             :         case GL_DEBUG_TYPE_PORTABILITY:
     418             :             return "portability";
     419             :         case GL_DEBUG_TYPE_MARKER:
     420             :             return "marker";
     421             :         case GL_DEBUG_TYPE_PUSH_GROUP:
     422             :             return "push group";
     423             :         case GL_DEBUG_TYPE_POP_GROUP:
     424             :             return "pop group";
     425             :         case GL_DEBUG_TYPE_OTHER:
     426             :             return "other";
     427             :         case GL_DEBUG_TYPE_ERROR:
     428             :             return "error";
     429             :         default:
     430             :             ;
     431             :     }
     432             : 
     433             :     return "unknown";
     434             : }
     435             : 
     436             : extern "C" void
     437             : #if defined _WIN32
     438             : APIENTRY
     439             : #endif
     440             : debug_callback(GLenum source, GLenum type, GLuint id,
     441             :         GLenum severity, GLsizei , const GLchar* message, GLvoid* )
     442             : {
     443             :     // ignore Nvidia's : "Program/shader state performance warning: Fragment Shader is going to be recompiled because the shader key based on GL state mismatches."
     444             :     // the GLSL compiler is a bit too aggressive in optimizing the state based on the current OpenGL state
     445             :     if (id == 131218)
     446             :         return;
     447             : 
     448             :     SAL_WARN("vcl.opengl", "OpenGL debug message: source: " << getSourceString(source) << ", type: "
     449             :             << getTypeString(type) << ", id: " << id << ", severity: " << getSeverityString(severity) << " with message: " << message);
     450             : }
     451             : 
     452             : }
     453             : 
     454             : #endif
     455             : 
     456             : #if defined UNX && !defined MACOSX && !defined IOS && !defined ANDROID && !defined(LIBO_HEADLESS)
     457             : 
     458             : namespace {
     459             : 
     460             : #ifdef DBG_UTIL
     461             : int unxErrorHandler(Display* dpy, XErrorEvent* event)
     462             : {
     463             :     char err[256];
     464             :     char req[256];
     465             :     char minor[256];
     466             :     XGetErrorText(dpy, event->error_code, err, 256);
     467             :     XGetErrorText(dpy, event->request_code, req, 256);
     468             :     XGetErrorText(dpy, event->minor_code, minor, 256);
     469             :     SAL_WARN("vcl.opengl", "Error: " << err << ", Req: " << req << ", Minor: " << minor);
     470             :     return 0;
     471             : }
     472             : #endif
     473             : 
     474             : typedef int (*errorHandler)(Display* /*dpy*/, XErrorEvent* /*evnt*/);
     475             : 
     476             : class TempErrorHandler
     477             : {
     478             : private:
     479             :     errorHandler oldErrorHandler;
     480             :     Display* mdpy;
     481             : 
     482             : public:
     483           0 :     TempErrorHandler(Display* dpy, errorHandler newErrorHandler):
     484           0 :         mdpy(dpy)
     485             :     {
     486           0 :         XLockDisplay(dpy);
     487           0 :         XSync(dpy, false);
     488           0 :         oldErrorHandler = XSetErrorHandler(newErrorHandler);
     489           0 :     }
     490             : 
     491           0 :     ~TempErrorHandler()
     492             :     {
     493             :         // sync so that we possibly get an XError
     494           0 :         glXWaitGL();
     495           0 :         XSync(mdpy, false);
     496           0 :         XSetErrorHandler(oldErrorHandler);
     497           0 :         XUnlockDisplay(mdpy);
     498           0 :     }
     499             : };
     500             : 
     501             : static bool errorTriggered;
     502           0 : int oglErrorHandler( Display* /*dpy*/, XErrorEvent* /*evnt*/ )
     503             : {
     504           0 :     errorTriggered = true;
     505             : 
     506           0 :     return 0;
     507             : }
     508             : 
     509           0 : GLXFBConfig* getFBConfigForPixmap(Display* dpy, int& nBestFBC, bool bUseDoubleBufferedRendering, int screen)
     510             : {
     511             :     static int visual_attribs[] =
     512             :     {
     513             :         GLX_DOUBLEBUFFER,       False,
     514             :         GLX_DRAWABLE_TYPE,      GLX_PIXMAP_BIT,
     515             :         GLX_X_RENDERABLE,       True,
     516             :         GLX_RED_SIZE,           8,
     517             :         GLX_GREEN_SIZE,         8,
     518             :         GLX_BLUE_SIZE,          8,
     519             :         GLX_ALPHA_SIZE,         8,
     520             :         GLX_DEPTH_SIZE,         24,
     521             :         GLX_X_VISUAL_TYPE,      GLX_TRUE_COLOR,
     522             :         None
     523             :     };
     524             : 
     525           0 :     if (bUseDoubleBufferedRendering)
     526           0 :         visual_attribs[1] = True;
     527             : 
     528           0 :     int fbCount = 0;
     529             :     GLXFBConfig* pFBC = glXChooseFBConfig( dpy,
     530             :             screen,
     531           0 :             visual_attribs, &fbCount );
     532             : 
     533           0 :     if(!pFBC)
     534             :     {
     535             :         SAL_WARN("vcl.opengl", "no suitable fb format found");
     536           0 :         return NULL;
     537             :     }
     538             : 
     539           0 :     int best_num_samp = -1;
     540           0 :     for(int i = 0; i < fbCount; ++i)
     541             :     {
     542             :         // pick the one with the most samples per pixel
     543           0 :         int nSampleBuf = 0;
     544           0 :         int nSamples = 0;
     545           0 :         glXGetFBConfigAttrib( dpy, pFBC[i], GLX_SAMPLE_BUFFERS, &nSampleBuf );
     546           0 :         glXGetFBConfigAttrib( dpy, pFBC[i], GLX_SAMPLES       , &nSamples  );
     547             : 
     548           0 :         if ( nBestFBC < 0 || (nSampleBuf && ( nSamples > best_num_samp )) )
     549             :         {
     550           0 :             nBestFBC = i;
     551           0 :             best_num_samp = nSamples;
     552             :         }
     553             :     }
     554             : 
     555           0 :     CHECK_GL_ERROR();
     556           0 :     return pFBC;
     557             : }
     558             : 
     559           0 : GLXFBConfig* getFBConfig(Display* dpy, Window win, int& nBestFBC, bool bUseDoubleBufferedRendering, bool bWithSameVisualID)
     560             : {
     561           0 :     if( dpy == 0 || !glXQueryExtension( dpy, NULL, NULL ) )
     562           0 :         return NULL;
     563             : 
     564             :     SAL_INFO("vcl.opengl", "window: " << win);
     565             : 
     566             :     XWindowAttributes xattr;
     567           0 :     if( !XGetWindowAttributes( dpy, win, &xattr ) )
     568             :     {
     569             :         SAL_WARN("vcl.opengl", "Failed to get window attributes for fbconfig " << win);
     570           0 :         xattr.screen = 0;
     571           0 :         xattr.visual = NULL;
     572             :     }
     573             : 
     574           0 :     int screen = XScreenNumberOfScreen( xattr.screen );
     575             : 
     576             :     // TODO: moggi: Select colour channel depth based on visual attributes, not hardcoded */
     577             :     static int visual_attribs[] =
     578             :     {
     579             :         GLX_DOUBLEBUFFER,       True,
     580             :         GLX_X_RENDERABLE,       True,
     581             :         GLX_RED_SIZE,           8,
     582             :         GLX_GREEN_SIZE,         8,
     583             :         GLX_BLUE_SIZE,          8,
     584             :         GLX_ALPHA_SIZE,         8,
     585             :         GLX_DEPTH_SIZE,         24,
     586             :         GLX_X_VISUAL_TYPE,      GLX_TRUE_COLOR,
     587             :         None
     588             :     };
     589             : 
     590           0 :     if (!bUseDoubleBufferedRendering)
     591           0 :         visual_attribs[1] = False;
     592             : 
     593           0 :     int fbCount = 0;
     594             :     GLXFBConfig* pFBC = glXChooseFBConfig( dpy,
     595             :             screen,
     596           0 :             visual_attribs, &fbCount );
     597             : 
     598           0 :     if(!pFBC)
     599             :     {
     600             :         SAL_WARN("vcl.opengl", "no suitable fb format found");
     601           0 :         return NULL;
     602             :     }
     603             : 
     604           0 :     int best_num_samp = -1;
     605           0 :     for(int i = 0; i < fbCount; ++i)
     606             :     {
     607           0 :         XVisualInfo* pVi = glXGetVisualFromFBConfig( dpy, pFBC[i] );
     608           0 :         if(pVi && (!bWithSameVisualID || (xattr.visual && pVi->visualid == xattr.visual->visualid)) )
     609             :         {
     610             :             // pick the one with the most samples per pixel
     611           0 :             int nSampleBuf = 0;
     612           0 :             int nSamples = 0;
     613           0 :             glXGetFBConfigAttrib( dpy, pFBC[i], GLX_SAMPLE_BUFFERS, &nSampleBuf );
     614           0 :             glXGetFBConfigAttrib( dpy, pFBC[i], GLX_SAMPLES       , &nSamples  );
     615             : 
     616           0 :             if ( nBestFBC < 0 || (nSampleBuf && ( nSamples > best_num_samp )) )
     617             :             {
     618           0 :                 nBestFBC = i;
     619           0 :                 best_num_samp = nSamples;
     620             :             }
     621             :         }
     622           0 :         XFree( pVi );
     623             :     }
     624             : 
     625           0 :     return pFBC;
     626             : }
     627             : 
     628             : // we need them before glew can initialize them
     629             : // glew needs an OpenGL context so we need to get the address manually
     630           0 : void initOpenGLFunctionPointers()
     631             : {
     632           0 :     glXChooseFBConfig = reinterpret_cast<GLXFBConfig*(*)(Display *dpy, int screen, const int *attrib_list, int *nelements)>(glXGetProcAddressARB(reinterpret_cast<GLubyte const *>("glXChooseFBConfig")));
     633           0 :     glXGetVisualFromFBConfig = reinterpret_cast<XVisualInfo*(*)(Display *dpy, GLXFBConfig config)>(glXGetProcAddressARB(reinterpret_cast<GLubyte const *>("glXGetVisualFromFBConfig")));    // try to find a visual for the current set of attributes
     634           0 :     glXGetFBConfigAttrib = reinterpret_cast<int(*)(Display *dpy, GLXFBConfig config, int attribute, int* value)>(glXGetProcAddressARB(reinterpret_cast<GLubyte const *>("glXGetFBConfigAttrib")));
     635           0 :     glXCreateContextAttribsARB = reinterpret_cast<GLXContext(*)(Display*, GLXFBConfig, GLXContext, Bool, const int*)>(glXGetProcAddressARB(reinterpret_cast<const GLubyte *>("glXCreateContextAttribsARB")));
     636           0 :     glXCreatePixmap = reinterpret_cast<GLXPixmap(*)(Display*, GLXFBConfig, Pixmap, const int*)>(glXGetProcAddressARB(reinterpret_cast<const GLubyte *>("glXCreatePixmap")));
     637           0 : }
     638             : 
     639           0 : Visual* getVisual(Display* dpy, Window win)
     640             : {
     641           0 :     initOpenGLFunctionPointers();
     642             : 
     643             :     XWindowAttributes xattr;
     644           0 :     if( !XGetWindowAttributes( dpy, win, &xattr ) )
     645             :     {
     646             :         SAL_WARN("vcl.opengl", "Failed to get window attributes for getVisual " << win);
     647           0 :         xattr.visual = NULL;
     648             :     }
     649             :     SAL_INFO("vcl.opengl", "using VisualID " << xattr.visual);
     650           0 :     return xattr.visual;
     651             : }
     652             : 
     653             : }
     654             : 
     655             : #endif
     656             : 
     657           1 : bool OpenGLContext::init( vcl::Window* pParent )
     658             : {
     659           1 :     if(mbInitialized)
     660           0 :         return true;
     661             : 
     662           1 :     m_xWindow.reset(pParent ? nullptr : VclPtr<vcl::Window>::Create(nullptr, WB_NOBORDER|WB_NODIALOGCONTROL));
     663           1 :     mpWindow = pParent ? pParent : m_xWindow.get();
     664           1 :     if(m_xWindow)
     665           1 :         m_xWindow->setPosSizePixel(0,0,0,0);
     666           1 :     m_pChildWindow = 0;
     667           1 :     initWindow();
     668           1 :     return ImplInit();
     669             : }
     670             : 
     671          17 : bool OpenGLContext::init(SystemChildWindow* pChildWindow)
     672             : {
     673          17 :     if(mbInitialized)
     674           0 :         return true;
     675             : 
     676          17 :     if( !pChildWindow )
     677           0 :         return false;
     678             : 
     679          17 :     mpWindow = pChildWindow->GetParent();
     680          17 :     m_pChildWindow = pChildWindow;
     681          17 :     initWindow();
     682          17 :     return ImplInit();
     683             : }
     684             : 
     685             : #if defined( UNX ) && !defined MACOSX && !defined IOS && !defined ANDROID && !defined(LIBO_HEADLESS)
     686           0 : bool OpenGLContext::init(Display* dpy, Window win, int screen)
     687             : {
     688           0 :     if(mbInitialized)
     689           0 :         return true;
     690             : 
     691           0 :     if (!dpy)
     692           0 :         return false;
     693             : 
     694           0 :     m_aGLWin.dpy = dpy;
     695           0 :     m_aGLWin.win = win;
     696           0 :     m_aGLWin.screen = screen;
     697             : 
     698           0 :     Visual* pVisual = getVisual(dpy, win);
     699             : 
     700           0 :     initGLWindow(pVisual);
     701             : 
     702           0 :     return ImplInit();
     703             : }
     704             : 
     705           0 : bool OpenGLContext::init(Display* dpy, Pixmap pix, unsigned int width, unsigned int height, int nScreen)
     706             : {
     707           0 :     if(mbInitialized)
     708           0 :         return true;
     709             : 
     710           0 :     if (!dpy)
     711           0 :         return false;
     712             : 
     713           0 :     initOpenGLFunctionPointers();
     714             : 
     715             :     SAL_INFO("vcl.opengl", "init with pixmap");
     716           0 :     m_aGLWin.dpy = dpy;
     717           0 :     m_aGLWin.Width = width;
     718           0 :     m_aGLWin.Height = height;
     719           0 :     m_aGLWin.pix = pix;
     720             :     const int attrib_list[] = { GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGB_EXT,
     721             :           GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
     722           0 :           None};
     723           0 :     int best_fbc = -1;
     724           0 :     GLXFBConfig* config = getFBConfigForPixmap(dpy, best_fbc, mbUseDoubleBufferedRendering, nScreen);
     725           0 :     if (best_fbc == -1)
     726           0 :         return false;
     727             : 
     728           0 :     m_aGLWin.vi = glXGetVisualFromFBConfig( dpy, config[best_fbc] );
     729           0 :     m_aGLWin.glPix = glXCreatePixmap(dpy, config[best_fbc], pix, attrib_list);
     730             : 
     731           0 :     mbPixmap = true;
     732             : 
     733           0 :     return ImplInit();
     734             : }
     735             : 
     736          18 : bool OpenGLContext::ImplInit()
     737             : {
     738          18 :     if (!m_aGLWin.dpy)
     739             :     {
     740          18 :         return false;
     741             :     }
     742             : 
     743           0 :     GLXContext pSharedCtx( NULL );
     744             : #ifdef DBG_UTIL
     745             :     TempErrorHandler aErrorHandler(m_aGLWin.dpy, unxErrorHandler);
     746             : #endif
     747             : 
     748             :     SAL_INFO("vcl.opengl", "OpenGLContext::ImplInit----start");
     749             : 
     750           0 :     if (!g_vShareList.empty())
     751           0 :         pSharedCtx = g_vShareList.front();
     752             : 
     753             : #ifdef DBG_UTIL
     754             :     if (!mbPixmap && glXCreateContextAttribsARB && !mbRequestLegacyContext)
     755             :     {
     756             :         int best_fbc = -1;
     757             :         GLXFBConfig* pFBC = getFBConfig(m_aGLWin.dpy, m_aGLWin.win, best_fbc, mbUseDoubleBufferedRendering, true);
     758             :         if (!pFBC)
     759             :             return false;
     760             : 
     761             :         if (best_fbc != -1)
     762             :         {
     763             :             int pContextAttribs[] =
     764             :             {
     765             :                 GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
     766             :                 GLX_CONTEXT_MINOR_VERSION_ARB, 2,
     767             :                 None
     768             :             };
     769             :             m_aGLWin.ctx = glXCreateContextAttribsARB(m_aGLWin.dpy, pFBC[best_fbc], pSharedCtx, GL_TRUE, pContextAttribs);
     770             :             SAL_INFO_IF(m_aGLWin.ctx, "vcl.opengl", "created a 3.2 core context");
     771             :         }
     772             :         else
     773             :             SAL_WARN("vcl.opengl", "unable to find correct FBC");
     774             : 
     775             :     }
     776             : #endif
     777             : 
     778           0 :     if (!m_aGLWin.ctx)
     779             :     {
     780           0 :         if (!m_aGLWin.vi)
     781           0 :            return false;
     782             : 
     783             :         m_aGLWin.ctx = glXCreateContext(m_aGLWin.dpy,
     784             :                 m_aGLWin.vi,
     785             :                 pSharedCtx,
     786           0 :                 GL_TRUE);
     787             :     }
     788             : 
     789           0 :     if( m_aGLWin.ctx )
     790             :     {
     791           0 :         g_vShareList.push_back( m_aGLWin.ctx );
     792             :     }
     793             :     else
     794             :     {
     795             :         SAL_WARN("vcl.opengl", "unable to create GLX context");
     796           0 :         return false;
     797             :     }
     798             : 
     799           0 :     if( !glXMakeCurrent( m_aGLWin.dpy, mbPixmap ? m_aGLWin.glPix : m_aGLWin.win, m_aGLWin.ctx ) )
     800             :     {
     801             :         SAL_WARN("vcl.opengl", "unable to select current GLX context");
     802           0 :         return false;
     803             :     }
     804             : 
     805             :     int glxMinor, glxMajor;
     806           0 :     double nGLXVersion = 0;
     807           0 :     if( glXQueryVersion( m_aGLWin.dpy, &glxMajor, &glxMinor ) )
     808           0 :       nGLXVersion = glxMajor + 0.1*glxMinor;
     809             :     SAL_INFO("vcl.opengl", "available GLX version: " << nGLXVersion);
     810             : 
     811           0 :     m_aGLWin.GLExtensions = glGetString( GL_EXTENSIONS );
     812             :     SAL_INFO("vcl.opengl", "available GL  extensions: " << m_aGLWin.GLExtensions);
     813             : 
     814             :     XWindowAttributes xWinAttr;
     815           0 :     if( mbPixmap )
     816             :     {
     817           0 :         m_aGLWin.Width = 0; // FIXME: correct ?
     818           0 :         m_aGLWin.Height = 0;
     819             :     }
     820           0 :     else if( !XGetWindowAttributes( m_aGLWin.dpy, m_aGLWin.win, &xWinAttr ) )
     821             :     {
     822             :         SAL_WARN("vcl.opengl", "Failed to get window attributes on " << m_aGLWin.win);
     823           0 :         m_aGLWin.Width = 0;
     824           0 :         m_aGLWin.Height = 0;
     825             :     }
     826             :     else
     827             :     {
     828           0 :         m_aGLWin.Width = xWinAttr.width;
     829           0 :         m_aGLWin.Height = xWinAttr.height;
     830             :     }
     831             : 
     832           0 :     if( m_aGLWin.HasGLXExtension("GLX_SGI_swap_control" ) )
     833             :     {
     834             :         // enable vsync
     835             :         typedef GLint (*glXSwapIntervalProc)(GLint);
     836           0 :         glXSwapIntervalProc glXSwapInterval = reinterpret_cast<glXSwapIntervalProc>(glXGetProcAddress( reinterpret_cast<const GLubyte*>("glXSwapIntervalSGI") ));
     837           0 :         if( glXSwapInterval )
     838             :         {
     839           0 :             TempErrorHandler aLocalErrorHandler(m_aGLWin.dpy, oglErrorHandler);
     840             : 
     841           0 :             errorTriggered = false;
     842             : 
     843           0 :             glXSwapInterval( 1 );
     844             : 
     845           0 :             if( errorTriggered )
     846             :                 SAL_WARN("vcl.opengl", "error when trying to set swap interval, NVIDIA or Mesa bug?");
     847             :             else
     848           0 :                 SAL_INFO("vcl.opengl", "set swap interval to 1 (enable vsync)");
     849             :         }
     850             :     }
     851             : 
     852           0 :     return InitGLEW();
     853             : }
     854             : 
     855             : #elif defined( _WIN32 )
     856             : 
     857             : bool OpenGLContext::init(HDC hDC, HWND hWnd)
     858             : {
     859             :     if (mbInitialized)
     860             :         return false;
     861             : 
     862             :     m_aGLWin.hDC = hDC;
     863             :     m_aGLWin.hWnd = hWnd;
     864             :     return ImplInit();
     865             : }
     866             : 
     867             : bool OpenGLContext::ImplInit()
     868             : {
     869             :     SAL_INFO("vcl.opengl", "OpenGLContext::ImplInit----start");
     870             :     // PixelFormat tells Windows how we want things to be
     871             :     PIXELFORMATDESCRIPTOR PixelFormatFront =
     872             :     {
     873             :         sizeof(PIXELFORMATDESCRIPTOR),
     874             :         1,                              // Version Number
     875             :         PFD_SUPPORT_OPENGL,
     876             :         PFD_TYPE_RGBA,                  // Request An RGBA Format
     877             :         (BYTE)32,                       // Select Our Color Depth
     878             :         0, 0, 0, 0, 0, 0,               // Color Bits Ignored
     879             :         0,                              // No Alpha Buffer
     880             :         0,                              // Shift Bit Ignored
     881             :         0,                              // No Accumulation Buffer
     882             :         0, 0, 0, 0,                     // Accumulation Bits Ignored
     883             :         64,                             // 32 bit Z-BUFFER
     884             :         8,                              // stencil buffer
     885             :         0,                              // No Auxiliary Buffer
     886             :         0,                              // now ignored
     887             :         0,                              // Reserved
     888             :         0, 0, 0                         // Layer Masks Ignored
     889             :     };
     890             : 
     891             :     // interestingly we need this flag being set even if we use single buffer
     892             :     // rendering - otherwise we get errors with virtual devices
     893             :     PixelFormatFront.dwFlags |= PFD_DOUBLEBUFFER;
     894             : 
     895             :     if (mbRequestVirtualDevice)
     896             :         PixelFormatFront.dwFlags |= PFD_DRAW_TO_BITMAP;
     897             :     else
     898             :         PixelFormatFront.dwFlags |= PFD_DRAW_TO_WINDOW;
     899             : 
     900             :     //  we must check whether can set the MSAA
     901             :     int WindowPix = 0;
     902             :     bool bMultiSampleSupport = InitMultisample(PixelFormatFront, WindowPix,
     903             :             mbUseDoubleBufferedRendering, mbRequestVirtualDevice);
     904             :     if (bMultiSampleSupport && WindowPix != 0)
     905             :     {
     906             :         m_aGLWin.bMultiSampleSupported = true;
     907             :     }
     908             :     else
     909             :     {
     910             :         WindowPix = ChoosePixelFormat(m_aGLWin.hDC, &PixelFormatFront);
     911             : #if OSL_DEBUG_LEVEL > 0
     912             :         PIXELFORMATDESCRIPTOR pfd;
     913             :         DescribePixelFormat(m_aGLWin.hDC, WindowPix, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
     914             :         SAL_WARN("vcl.opengl", "Render Target: Window: " << (int) ((pfd.dwFlags & PFD_DRAW_TO_WINDOW) != 0) << ", Bitmap: " << (int) ((pfd.dwFlags & PFD_DRAW_TO_BITMAP) != 0));
     915             :         SAL_WARN("vcl.opengl", "Supports OpenGL: " << (int) ((pfd.dwFlags & PFD_SUPPORT_OPENGL) != 0));
     916             : #endif
     917             :     }
     918             : 
     919             :     if (WindowPix == 0)
     920             :     {
     921             :         SAL_WARN("vcl.opengl", "Invalid pixelformat");
     922             :         return false;
     923             :     }
     924             : 
     925             :     if (!SetPixelFormat(m_aGLWin.hDC, WindowPix, &PixelFormatFront))
     926             :     {
     927             :         ImplWriteLastError(GetLastError(), "SetPixelFormat in OpenGLContext::ImplInit");
     928             :         SAL_WARN("vcl.opengl", "SetPixelFormat failed");
     929             :         return false;
     930             :     }
     931             : 
     932             :     HGLRC hTempRC = wglCreateContext(m_aGLWin.hDC);
     933             :     if (hTempRC == NULL)
     934             :     {
     935             :         ImplWriteLastError(GetLastError(), "wglCreateContext in OpenGLContext::ImplInit");
     936             :         SAL_WARN("vcl.opengl", "wglCreateContext failed");
     937             :         return false;
     938             :     }
     939             : 
     940             :     if (!wglMakeCurrent(m_aGLWin.hDC, hTempRC))
     941             :     {
     942             :         ImplWriteLastError(GetLastError(), "wglMakeCurrent in OpenGLContext::ImplInit");
     943             :         SAL_WARN("vcl.opengl", "wglMakeCurrent failed");
     944             :         return false;
     945             :     }
     946             : 
     947             :     if (!InitGLEW())
     948             :         return false;
     949             : 
     950             :     HGLRC hSharedCtx = 0;
     951             :     if (!g_vShareList.empty())
     952             :         hSharedCtx = g_vShareList.front();
     953             : 
     954             :     if (!wglCreateContextAttribsARB)
     955             :         return false;
     956             : 
     957             :     // now setup the shared context; this needs a temporary context already
     958             :     // set up in order to work
     959             :     m_aGLWin.hRC = wglCreateContextAttribsARB(m_aGLWin.hDC, hSharedCtx, NULL);
     960             :     if (m_aGLWin.hRC == 0)
     961             :     {
     962             :         ImplWriteLastError(GetLastError(), "wglCreateContextAttribsARB in OpenGLContext::ImplInit");
     963             :         SAL_WARN("vcl.opengl", "wglCreateContextAttribsARB failed");
     964             :         return false;
     965             :     }
     966             : 
     967             :     wglMakeCurrent(NULL, NULL);
     968             :     wglDeleteContext(hTempRC);
     969             : 
     970             :     if (!wglMakeCurrent(m_aGLWin.hDC, m_aGLWin.hRC))
     971             :     {
     972             :         ImplWriteLastError(GetLastError(), "wglMakeCurrent (with shared context) in OpenGLContext::ImplInit");
     973             :         SAL_WARN("vcl.opengl", "wglMakeCurrent failed");
     974             :         return false;
     975             :     }
     976             : 
     977             :     g_vShareList.push_back(m_aGLWin.hRC);
     978             : 
     979             :     RECT clientRect;
     980             :     GetClientRect(WindowFromDC(m_aGLWin.hDC), &clientRect);
     981             :     m_aGLWin.Width = clientRect.right - clientRect.left;
     982             :     m_aGLWin.Height = clientRect.bottom - clientRect.top;
     983             : 
     984             :     return true;
     985             : }
     986             : 
     987             : #elif defined( MACOSX )
     988             : 
     989             : bool OpenGLContext::ImplInit()
     990             : {
     991             :     SAL_INFO("vcl.opengl", "OpenGLContext::ImplInit----start");
     992             :     NSOpenGLView* pView = getOpenGLView();
     993             :     OpenGLWrapper::makeCurrent(pView);
     994             : 
     995             :     return InitGLEW();
     996             : }
     997             : 
     998             : #else
     999             : 
    1000             : bool OpenGLContext::ImplInit()
    1001             : {
    1002             :     SAL_INFO("vcl.opengl", "OpenGLContext not implemented for this platform");
    1003             :     return false;
    1004             : }
    1005             : 
    1006             : #endif
    1007             : 
    1008           0 : bool OpenGLContext::InitGLEW()
    1009             : {
    1010             :     static bool bGlewInit = false;
    1011           0 :     if(!bGlewInit)
    1012             :     {
    1013           0 :         glewExperimental = GL_TRUE;
    1014           0 :         GLenum err = glewInit();
    1015           0 :         if (err != GLEW_OK)
    1016             :         {
    1017             :             SAL_WARN("vcl.opengl", "Failed to initialize GLEW: " << glewGetErrorString(err));
    1018           0 :             return false;
    1019             :         }
    1020             :         else
    1021           0 :             bGlewInit = true;
    1022             :     }
    1023             : 
    1024             : #ifdef DBG_UTIL
    1025             :     // only enable debug output in dbgutil build
    1026             :     if( GLEW_ARB_debug_output)
    1027             :     {
    1028             :         if (glDebugMessageCallbackARB)
    1029             :         {
    1030             :             glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
    1031             :             glDebugMessageCallbackARB(&debug_callback, NULL);
    1032             :         }
    1033             :         else if ( glDebugMessageCallback )
    1034             :         {
    1035             :             glEnable(GL_DEBUG_OUTPUT);
    1036             :             glDebugMessageCallback(&debug_callback, NULL);
    1037             :         }
    1038             :     }
    1039             : 
    1040             : #endif
    1041             : 
    1042             :     SAL_INFO("vcl.opengl", "OpenGLContext::ImplInit----end");
    1043           0 :     mbInitialized = true;
    1044           0 :     return true;
    1045             : }
    1046             : 
    1047           0 : void OpenGLContext::setWinPosAndSize(const Point &rPos, const Size& rSize)
    1048             : {
    1049           0 :     if(m_xWindow)
    1050           0 :         m_xWindow->SetPosSizePixel(rPos, rSize);
    1051           0 :     if( m_pChildWindow )
    1052           0 :         m_pChildWindow->SetPosSizePixel(rPos, rSize);
    1053             : 
    1054           0 :     m_aGLWin.Width = rSize.Width();
    1055           0 :     m_aGLWin.Height = rSize.Height();
    1056           0 : }
    1057             : 
    1058           0 : void OpenGLContext::setWinSize(const Size& rSize)
    1059             : {
    1060           0 :     if(m_xWindow)
    1061           0 :         m_xWindow->SetSizePixel(rSize);
    1062           0 :     if( m_pChildWindow )
    1063           0 :         m_pChildWindow->SetSizePixel(rSize);
    1064             : 
    1065           0 :     m_aGLWin.Width = rSize.Width();
    1066           0 :     m_aGLWin.Height = rSize.Height();
    1067           0 : }
    1068             : 
    1069           0 : void OpenGLContext::renderToFile()
    1070             : {
    1071           0 :     int iWidth = m_aGLWin.Width;
    1072           0 :     int iHeight = m_aGLWin.Height;
    1073             :     static int nIdx = 0;
    1074           0 :     OUString aName = "file:///home/moggi/Documents/work/output" + OUString::number( nIdx++ ) + ".png";
    1075           0 :     OpenGLHelper::renderToFile(iWidth, iHeight, aName);
    1076           0 : }
    1077             : 
    1078             : #if defined( WNT )
    1079             : 
    1080             : bool OpenGLContext::initWindow()
    1081             : {
    1082             :     if( !m_pChildWindow )
    1083             :     {
    1084             :         SystemWindowData winData = generateWinData(mpWindow, false);
    1085             :         m_pChildWindow = VclPtr<SystemChildWindow>::Create(mpWindow, 0, &winData, false);
    1086             :     }
    1087             : 
    1088             :     if( m_pChildWindow )
    1089             :     {
    1090             :         m_pChildWindow->SetMouseTransparent( true );
    1091             :         m_pChildWindow->SetParentClipMode(ParentClipMode::Clip);
    1092             :         m_pChildWindow->EnableEraseBackground( false );
    1093             :         m_pChildWindow->SetControlForeground();
    1094             :         m_pChildWindow->SetControlBackground();
    1095             :         //m_pChildWindow->EnablePaint(false);
    1096             : 
    1097             :         const SystemEnvData* sysData(m_pChildWindow->GetSystemData());
    1098             :         m_aGLWin.hWnd = sysData->hWnd;
    1099             :     }
    1100             : 
    1101             :     m_aGLWin.hDC = GetDC(m_aGLWin.hWnd);
    1102             :     return true;
    1103             : }
    1104             : 
    1105             : #elif defined( MACOSX )
    1106             : 
    1107             : bool OpenGLContext::initWindow()
    1108             : {
    1109             :     if( !m_pChildWindow )
    1110             :     {
    1111             :         SystemWindowData winData = generateWinData(mpWindow, mbRequestLegacyContext);
    1112             :         m_pChildWindow = VclPtr<SystemChildWindow>::Create(mpWindow, 0, &winData, false);
    1113             :     }
    1114             : 
    1115             :     if( m_pChildWindow )
    1116             :     {
    1117             :         m_pChildWindow->SetMouseTransparent( true );
    1118             :         m_pChildWindow->SetParentClipMode(ParentClipMode::Clip);
    1119             :         m_pChildWindow->EnableEraseBackground( false );
    1120             :         m_pChildWindow->SetControlForeground();
    1121             :         m_pChildWindow->SetControlBackground();
    1122             :         //m_pChildWindow->EnablePaint(false);
    1123             : 
    1124             :     }
    1125             : 
    1126             :     return true;
    1127             : }
    1128             : 
    1129             : #elif defined( IOS ) || defined( ANDROID ) || defined(LIBO_HEADLESS)
    1130             : 
    1131             : bool OpenGLContext::initWindow()
    1132             : {
    1133             :     return false;
    1134             : }
    1135             : 
    1136             : #elif defined( UNX )
    1137             : 
    1138          18 : bool OpenGLContext::initWindow()
    1139             : {
    1140          18 :     const SystemEnvData* pChildSysData = 0;
    1141          18 :     SystemWindowData winData = generateWinData(mpWindow, false);
    1142          18 :     if( winData.pVisual )
    1143             :     {
    1144           0 :         if( !m_pChildWindow )
    1145             :         {
    1146           0 :             m_pChildWindow = VclPtr<SystemChildWindow>::Create(mpWindow, 0, &winData, false);
    1147             :         }
    1148           0 :         pChildSysData = m_pChildWindow->GetSystemData();
    1149             :     }
    1150             : 
    1151          18 :     if (!m_pChildWindow || !pChildSysData)
    1152          18 :         return false;
    1153             : 
    1154           0 :     m_pChildWindow->SetMouseTransparent( true );
    1155           0 :     m_pChildWindow->SetParentClipMode( ParentClipMode::NoClip );
    1156           0 :     m_pChildWindow->EnableEraseBackground( false );
    1157           0 :     m_pChildWindow->SetControlForeground();
    1158           0 :     m_pChildWindow->SetControlBackground();
    1159             : 
    1160           0 :     m_aGLWin.dpy = static_cast<Display*>(pChildSysData->pDisplay);
    1161           0 :     m_aGLWin.win = pChildSysData->aWindow;
    1162           0 :     m_aGLWin.screen = pChildSysData->nScreen;
    1163             : 
    1164           0 :     Visual* pVisual = static_cast<Visual*>(pChildSysData->pVisual);
    1165           0 :     initGLWindow(pVisual);
    1166             : 
    1167           0 :     return true;
    1168             : }
    1169             : 
    1170           0 : void OpenGLContext::initGLWindow(Visual* pVisual)
    1171             : {
    1172             :     // Get visual info
    1173             :     {
    1174             :         XVisualInfo aTemplate;
    1175           0 :         aTemplate.visualid = XVisualIDFromVisual( pVisual );
    1176           0 :         int nVisuals = 0;
    1177           0 :         XVisualInfo* pInfos = XGetVisualInfo( m_aGLWin.dpy, VisualIDMask, &aTemplate, &nVisuals );
    1178           0 :         if( nVisuals != 1 )
    1179             :             SAL_WARN( "vcl.opengl", "match count for visual id is not 1" );
    1180           0 :         m_aGLWin.vi = pInfos;
    1181             :     }
    1182             : 
    1183             :     // Check multi sample support
    1184             :     /* TODO: moggi: This is not necessarily correct in the DBG_UTIL path, as it picks
    1185             :      *      an FBConfig instead ... */
    1186           0 :     int nSamples = 0;
    1187           0 :     glXGetConfig(m_aGLWin.dpy, m_aGLWin.vi, GLX_SAMPLES, &nSamples);
    1188           0 :     if( nSamples > 0 )
    1189           0 :         m_aGLWin.bMultiSampleSupported = true;
    1190             : 
    1191           0 :     m_aGLWin.GLXExtensions = glXQueryExtensionsString( m_aGLWin.dpy, m_aGLWin.screen );
    1192             :     SAL_INFO("vcl.opengl", "available GLX extensions: " << m_aGLWin.GLXExtensions);
    1193           0 : }
    1194             : 
    1195             : #endif
    1196             : 
    1197          18 : void OpenGLContext::reset()
    1198             : {
    1199          18 :     if( !mbInitialized )
    1200          36 :         return;
    1201             : 
    1202             :     // reset the clip region
    1203           0 :     maClipRegion.SetEmpty();
    1204             : 
    1205             :     // destroy all framebuffers
    1206           0 :     if( mpLastFramebuffer )
    1207             :     {
    1208           0 :         OpenGLFramebuffer* pFramebuffer = mpLastFramebuffer;
    1209             : 
    1210           0 :         makeCurrent();
    1211           0 :         while( pFramebuffer )
    1212             :         {
    1213           0 :             OpenGLFramebuffer* pPrevFramebuffer = pFramebuffer->mpPrevFramebuffer;
    1214           0 :             delete pFramebuffer;
    1215           0 :             pFramebuffer = pPrevFramebuffer;
    1216             :         }
    1217           0 :         mpFirstFramebuffer = NULL;
    1218           0 :         mpLastFramebuffer = NULL;
    1219             :     }
    1220             : 
    1221             :     // destroy all programs
    1222           0 :     if( !maPrograms.empty() )
    1223             :     {
    1224             : 
    1225           0 :         makeCurrent();
    1226           0 :         maPrograms.clear();
    1227             :     }
    1228             : 
    1229           0 :     if( isCurrent() )
    1230           0 :         resetCurrent();
    1231             : 
    1232           0 :     mbInitialized = false;
    1233             : 
    1234             :     // destroy the context itself
    1235             : #if defined( WNT )
    1236             :     if (m_aGLWin.hRC)
    1237             :     {
    1238             :         std::vector<HGLRC>::iterator itr = std::remove(g_vShareList.begin(), g_vShareList.end(), m_aGLWin.hRC);
    1239             :         if (itr != g_vShareList.end())
    1240             :             g_vShareList.erase(itr);
    1241             : 
    1242             :         wglMakeCurrent( m_aGLWin.hDC, 0 );
    1243             :         wglDeleteContext( m_aGLWin.hRC );
    1244             :         ReleaseDC( m_aGLWin.hWnd, m_aGLWin.hDC );
    1245             :     }
    1246             : #elif defined( MACOSX )
    1247             :     OpenGLWrapper::resetCurrent();
    1248             : #elif defined( IOS ) || defined( ANDROID ) || defined(LIBO_HEADLESS)
    1249             :     // nothing
    1250             : #elif defined( UNX )
    1251           0 :     if(m_aGLWin.ctx)
    1252             :     {
    1253           0 :         std::vector<GLXContext>::iterator itr = std::remove( g_vShareList.begin(), g_vShareList.end(), m_aGLWin.ctx );
    1254           0 :         if (itr != g_vShareList.end())
    1255           0 :             g_vShareList.erase(itr);
    1256             : 
    1257           0 :         glXMakeCurrent(m_aGLWin.dpy, None, NULL);
    1258           0 :         if( glGetError() != GL_NO_ERROR )
    1259             :         {
    1260             :             SAL_WARN("vcl.opengl", "glError: " << glGetError());
    1261             :         }
    1262           0 :         glXDestroyContext(m_aGLWin.dpy, m_aGLWin.ctx);
    1263             : 
    1264           0 :         if (mbPixmap && m_aGLWin.glPix != None)
    1265           0 :             glXDestroyPixmap(m_aGLWin.dpy, m_aGLWin.glPix);
    1266             :     }
    1267             : #endif
    1268             : }
    1269             : 
    1270             : #if defined( WNT ) || defined( MACOSX ) || defined( IOS ) || defined( ANDROID )
    1271             : 
    1272             : SystemWindowData OpenGLContext::generateWinData(vcl::Window* /*pParent*/, bool bRequestLegacyContext)
    1273             : {
    1274             :     (void) bRequestLegacyContext;
    1275             :     SystemWindowData aWinData;
    1276             : #if defined(MACOSX)
    1277             :     aWinData.bOpenGL = true;
    1278             :     aWinData.bLegacy = bRequestLegacyContext;
    1279             : #endif
    1280             :     aWinData.nSize = sizeof(aWinData);
    1281             :     return aWinData;
    1282             : }
    1283             : 
    1284             : #elif defined( UNX )
    1285             : 
    1286          35 : SystemWindowData OpenGLContext::generateWinData(vcl::Window* pParent, bool)
    1287             : {
    1288             :     SystemWindowData aWinData;
    1289          35 :     aWinData.nSize = sizeof(aWinData);
    1290          35 :     aWinData.pVisual = NULL;
    1291             : 
    1292             : #if !defined(LIBO_HEADLESS)
    1293          35 :     const SystemEnvData* sysData(pParent->GetSystemData());
    1294             : 
    1295          35 :     Display *dpy = static_cast<Display*>(sysData->pDisplay);
    1296          35 :     Window win = sysData->aWindow;
    1297             : 
    1298          35 :     if( dpy == 0 || !glXQueryExtension( dpy, NULL, NULL ) )
    1299          35 :         return aWinData;
    1300             : 
    1301           0 :     initOpenGLFunctionPointers();
    1302             : 
    1303           0 :     int best_fbc = -1;
    1304           0 :     GLXFBConfig* pFBC = getFBConfig(dpy, win, best_fbc, true, false);
    1305             : 
    1306           0 :     if (!pFBC)
    1307           0 :         return aWinData;
    1308             : 
    1309           0 :     XVisualInfo* vi = 0;
    1310           0 :     if( best_fbc != -1 )
    1311           0 :         vi = glXGetVisualFromFBConfig( dpy, pFBC[best_fbc] );
    1312             : 
    1313           0 :     XFree(pFBC);
    1314             : 
    1315           0 :     if( vi )
    1316             :     {
    1317             :         SAL_INFO("vcl.opengl", "using VisualID " << vi->visualid);
    1318           0 :         aWinData.pVisual = static_cast<void*>(vi->visual);
    1319             :     }
    1320             : #endif
    1321             : 
    1322           0 :     return aWinData;
    1323             : }
    1324             : 
    1325             : #endif
    1326             : 
    1327       45332 : bool OpenGLContext::isCurrent()
    1328             : {
    1329             : #if defined( WNT )
    1330             :     return (wglGetCurrentContext() == m_aGLWin.hRC &&
    1331             :             wglGetCurrentDC() == m_aGLWin.hDC);
    1332             : #elif defined( MACOSX )
    1333             :     (void) this; // loplugin:staticmethods
    1334             :     return false;
    1335             : #elif defined( IOS ) || defined( ANDROID ) || defined(LIBO_HEADLESS)
    1336             :     return false;
    1337             : #elif defined( UNX )
    1338       45332 :     GLXDrawable nDrawable = mbPixmap ? m_aGLWin.glPix : m_aGLWin.win;
    1339       90664 :     return (glXGetCurrentContext() == m_aGLWin.ctx &&
    1340       90664 :             glXGetCurrentDrawable() == nDrawable);
    1341             : #endif
    1342             : }
    1343             : 
    1344    13794207 : void OpenGLContext::clearCurrent()
    1345             : {
    1346    13794207 :     ImplSVData* pSVData = ImplGetSVData();
    1347             : 
    1348             :     // release all framebuffers from the old context so we can re-attach the
    1349             :     // texture in the new context
    1350    13794207 :     OpenGLContext* pCurrentCtx = pSVData->maGDIData.mpLastContext;
    1351    13794207 :     if( pCurrentCtx && pCurrentCtx->isCurrent() )
    1352       45331 :         pCurrentCtx->ReleaseFramebuffers();
    1353    13794207 : }
    1354             : 
    1355           1 : void OpenGLContext::makeCurrent()
    1356             : {
    1357           1 :     ImplSVData* pSVData = ImplGetSVData();
    1358             : 
    1359           1 :     if (isCurrent())
    1360           2 :         return;
    1361             : 
    1362           0 :     clearCurrent();
    1363             : 
    1364             : #if defined( WNT )
    1365             :     if (!wglMakeCurrent(m_aGLWin.hDC, m_aGLWin.hRC))
    1366             :     {
    1367             :         SAL_WARN("vcl.opengl", "OpenGLContext::makeCurrent(): wglMakeCurrent failed: " << GetLastError());
    1368             :         return;
    1369             :     }
    1370             : #elif defined( MACOSX )
    1371             :     NSOpenGLView* pView = getOpenGLView();
    1372             :     OpenGLWrapper::makeCurrent(pView);
    1373             : #elif defined( IOS ) || defined( ANDROID ) || defined(LIBO_HEADLESS)
    1374             :     // nothing
    1375             : #elif defined( UNX )
    1376             : #ifdef DBG_UTIL
    1377             :     TempErrorHandler aErrorHandler(m_aGLWin.dpy, unxErrorHandler);
    1378             : #endif
    1379             : 
    1380           0 :     GLXDrawable nDrawable = mbPixmap ? m_aGLWin.glPix : m_aGLWin.win;
    1381           0 :     if (!glXMakeCurrent( m_aGLWin.dpy, nDrawable, m_aGLWin.ctx ))
    1382             :     {
    1383             :         SAL_WARN("vcl.opengl", "OpenGLContext::makeCurrent failed on drawable " << nDrawable << " pixmap? " << mbPixmap);
    1384           0 :         return;
    1385             :     }
    1386             : #endif
    1387             : 
    1388             :     // move the context to the end of the contexts list
    1389             :     static int nSwitch = 0;
    1390             :     SAL_INFO("vcl.opengl", "******* CONTEXT SWITCH " << ++nSwitch << " *********");
    1391           0 :     if( mpNextContext )
    1392             :     {
    1393           0 :         if( mpPrevContext )
    1394           0 :             mpPrevContext->mpNextContext = mpNextContext;
    1395             :         else
    1396           0 :             pSVData->maGDIData.mpFirstContext = mpNextContext;
    1397           0 :         mpNextContext->mpPrevContext = mpPrevContext;
    1398             : 
    1399           0 :         mpPrevContext = pSVData->maGDIData.mpLastContext;
    1400           0 :         mpNextContext = NULL;
    1401           0 :         pSVData->maGDIData.mpLastContext->mpNextContext = this;
    1402           0 :         pSVData->maGDIData.mpLastContext = this;
    1403             :     }
    1404             : }
    1405             : 
    1406           0 : void OpenGLContext::resetCurrent()
    1407             : {
    1408           0 :     clearCurrent();
    1409             : 
    1410             : #if defined( WNT )
    1411             :     wglMakeCurrent( m_aGLWin.hDC, 0 );
    1412             : #elif defined( MACOSX )
    1413             :     (void) this; // loplugin:staticmethods
    1414             :     OpenGLWrapper::resetCurrent();
    1415             : #elif defined( IOS ) || defined( ANDROID ) || defined(LIBO_HEADLESS)
    1416             :     // nothing
    1417             : #elif defined( UNX )
    1418           0 :     glXMakeCurrent(m_aGLWin.dpy, None, NULL);
    1419             : #endif
    1420           0 : }
    1421             : 
    1422           0 : void OpenGLContext::swapBuffers()
    1423             : {
    1424             : #if defined( WNT )
    1425             :     SwapBuffers(m_aGLWin.hDC);
    1426             : #elif defined( MACOSX )
    1427             :     NSOpenGLView* pView = getOpenGLView();
    1428             :     OpenGLWrapper::swapBuffers(pView);
    1429             : #elif defined( IOS ) || defined( ANDROID ) || defined(LIBO_HEADLESS)
    1430             :     // nothing
    1431             : #elif defined( UNX )
    1432           0 :     glXSwapBuffers(m_aGLWin.dpy, mbPixmap ? m_aGLWin.glPix : m_aGLWin.win);
    1433             : #endif
    1434           0 : }
    1435             : 
    1436           0 : void OpenGLContext::sync()
    1437             : {
    1438             : #if defined( WNT )
    1439             :     // nothing
    1440             : #elif defined( MACOSX ) || defined( IOS ) || defined( ANDROID ) || defined(LIBO_HEADLESS)
    1441             :     (void) this; // loplugin:staticmethods
    1442             :     // nothing
    1443             : #elif defined( UNX )
    1444           0 :     glXWaitGL();
    1445           0 :     XSync(m_aGLWin.dpy, false);
    1446             : #endif
    1447           0 : }
    1448             : 
    1449           0 : void OpenGLContext::show()
    1450             : {
    1451           0 :     if (m_pChildWindow)
    1452           0 :         m_pChildWindow->Show();
    1453           0 :     else if (m_xWindow)
    1454           0 :         m_xWindow->Show();
    1455           0 : }
    1456             : 
    1457           0 : SystemChildWindow* OpenGLContext::getChildWindow()
    1458             : {
    1459           0 :     return m_pChildWindow;
    1460             : }
    1461             : 
    1462           0 : const SystemChildWindow* OpenGLContext::getChildWindow() const
    1463             : {
    1464           0 :     return m_pChildWindow;
    1465             : }
    1466             : 
    1467           0 : bool OpenGLContext::supportMultiSampling() const
    1468             : {
    1469           0 :     return m_aGLWin.bMultiSampleSupported;
    1470             : }
    1471             : 
    1472             : #if defined(MACOSX)
    1473             : NSOpenGLView* OpenGLContext::getOpenGLView()
    1474             : {
    1475             :     return reinterpret_cast<NSOpenGLView*>(m_pChildWindow->GetSystemData()->mpNSView);
    1476             : }
    1477             : #endif
    1478             : 
    1479           0 : bool OpenGLContext::BindFramebuffer( OpenGLFramebuffer* pFramebuffer )
    1480             : {
    1481           0 :     if( pFramebuffer != mpCurrentFramebuffer )
    1482             :     {
    1483           0 :         if( pFramebuffer )
    1484           0 :             pFramebuffer->Bind();
    1485             :         else
    1486           0 :             OpenGLFramebuffer::Unbind();
    1487           0 :         mpCurrentFramebuffer = pFramebuffer;
    1488             :     }
    1489             : 
    1490           0 :     return true;
    1491             : }
    1492             : 
    1493           0 : bool OpenGLContext::AcquireDefaultFramebuffer()
    1494             : {
    1495           0 :     return BindFramebuffer( NULL );
    1496             : }
    1497             : 
    1498           0 : OpenGLFramebuffer* OpenGLContext::AcquireFramebuffer( const OpenGLTexture& rTexture )
    1499             : {
    1500           0 :     OpenGLFramebuffer* pFramebuffer = NULL;
    1501           0 :     OpenGLFramebuffer* pFreeFbo = NULL;
    1502           0 :     OpenGLFramebuffer* pSameSizeFbo = NULL;
    1503             : 
    1504             :     // check if there is already a framebuffer attached to that texture
    1505           0 :     pFramebuffer = mpLastFramebuffer;
    1506           0 :     while( pFramebuffer )
    1507             :     {
    1508           0 :         if( pFramebuffer->IsAttached( rTexture ) )
    1509           0 :             break;
    1510           0 :         if( !pFreeFbo && pFramebuffer->IsFree() )
    1511           0 :             pFreeFbo = pFramebuffer;
    1512           0 :         if( !pSameSizeFbo &&
    1513           0 :             pFramebuffer->GetWidth() == rTexture.GetWidth() &&
    1514           0 :             pFramebuffer->GetHeight() == rTexture.GetHeight() )
    1515           0 :             pSameSizeFbo = pFramebuffer;
    1516           0 :         pFramebuffer = pFramebuffer->mpPrevFramebuffer;
    1517             :     }
    1518             : 
    1519             :     // else use any framebuffer having the same size
    1520           0 :     if( !pFramebuffer && pSameSizeFbo )
    1521           0 :         pFramebuffer = pSameSizeFbo;
    1522             : 
    1523             :     // else use the first free framebuffer
    1524           0 :     if( !pFramebuffer && pFreeFbo )
    1525           0 :         pFramebuffer = pFreeFbo;
    1526             : 
    1527             :     // if there isn't any free one, create a new one if the limit isn't reached
    1528           0 :     if( !pFramebuffer && mnFramebufferCount < MAX_FRAMEBUFFER_COUNT )
    1529             :     {
    1530           0 :         mnFramebufferCount++;
    1531           0 :         pFramebuffer = new OpenGLFramebuffer();
    1532           0 :         if( mpLastFramebuffer )
    1533             :         {
    1534           0 :             pFramebuffer->mpPrevFramebuffer = mpLastFramebuffer;
    1535           0 :             mpLastFramebuffer->mpNextFramebuffer = pFramebuffer;
    1536           0 :             mpLastFramebuffer = pFramebuffer;
    1537             :         }
    1538             :         else
    1539             :         {
    1540           0 :             mpFirstFramebuffer = pFramebuffer;
    1541           0 :             mpLastFramebuffer = pFramebuffer;
    1542             :         }
    1543             :     }
    1544             : 
    1545             :     // last try, use any framebuffer
    1546             :     // TODO order the list of framebuffers as a LRU
    1547           0 :     if( !pFramebuffer )
    1548           0 :         pFramebuffer = mpFirstFramebuffer;
    1549             : 
    1550             :     assert( pFramebuffer );
    1551           0 :     BindFramebuffer( pFramebuffer );
    1552           0 :     pFramebuffer->AttachTexture( rTexture );
    1553           0 :     glViewport( 0, 0, rTexture.GetWidth(), rTexture.GetHeight() );
    1554             : 
    1555           0 :     return pFramebuffer;
    1556             : }
    1557             : 
    1558           0 : void OpenGLContext::ReleaseFramebuffer( OpenGLFramebuffer* pFramebuffer )
    1559             : {
    1560           0 :     if( pFramebuffer )
    1561           0 :         pFramebuffer->DetachTexture();
    1562           0 : }
    1563             : 
    1564           0 : void OpenGLContext::ReleaseFramebuffer( const OpenGLTexture& rTexture )
    1565             : {
    1566           0 :     OpenGLFramebuffer* pFramebuffer = mpLastFramebuffer;
    1567             : 
    1568           0 :     while( pFramebuffer )
    1569             :     {
    1570           0 :         if( pFramebuffer->IsAttached( rTexture ) )
    1571             :         {
    1572           0 :             BindFramebuffer( pFramebuffer );
    1573           0 :             pFramebuffer->DetachTexture();
    1574             :         }
    1575           0 :         pFramebuffer = pFramebuffer->mpPrevFramebuffer;
    1576             :     }
    1577           0 : }
    1578             : 
    1579       45331 : void OpenGLContext::ReleaseFramebuffers()
    1580             : {
    1581       45331 :     OpenGLFramebuffer* pFramebuffer = mpLastFramebuffer;
    1582       90662 :     while( pFramebuffer )
    1583             :     {
    1584           0 :         BindFramebuffer( pFramebuffer );
    1585           0 :         pFramebuffer->DetachTexture();
    1586           0 :         pFramebuffer = pFramebuffer->mpPrevFramebuffer;
    1587             :     }
    1588       45331 : }
    1589             : 
    1590           0 : OpenGLProgram* OpenGLContext::GetProgram( const OUString& rVertexShader, const OUString& rFragmentShader, const OString& preamble )
    1591             : {
    1592           0 :     ProgramKey aKey( rVertexShader, rFragmentShader, preamble );
    1593             : 
    1594             :     std::map< ProgramKey, boost::shared_ptr<OpenGLProgram> >::iterator
    1595           0 :         it = maPrograms.find( aKey );
    1596           0 :     if( it != maPrograms.end() )
    1597           0 :         return it->second.get();
    1598             : 
    1599           0 :     boost::shared_ptr<OpenGLProgram> pProgram = boost::make_shared<OpenGLProgram>();
    1600           0 :     if( !pProgram->Load( rVertexShader, rFragmentShader, preamble ) )
    1601           0 :         return NULL;
    1602             : 
    1603           0 :     maPrograms.insert(std::pair<ProgramKey, boost::shared_ptr<OpenGLProgram> >(aKey, pProgram));
    1604           0 :     return pProgram.get();
    1605             : }
    1606             : 
    1607           0 : OpenGLProgram* OpenGLContext::UseProgram( const OUString& rVertexShader, const OUString& rFragmentShader, const OString& preamble )
    1608             : {
    1609           0 :     OpenGLProgram* pProgram = GetProgram( rVertexShader, rFragmentShader, preamble );
    1610             : 
    1611           0 :     if( pProgram == mpCurrentProgram )
    1612           0 :         return pProgram;
    1613             : 
    1614           0 :     mpCurrentProgram = pProgram;
    1615           0 :     mpCurrentProgram->Use();
    1616             : 
    1617           0 :     return mpCurrentProgram;
    1618             : }
    1619             : 
    1620             : inline
    1621           0 : OpenGLContext::ProgramKey::ProgramKey( const OUString& v, const OUString& f, const OString& p )
    1622           0 : : vertexShader( v ), fragmentShader( f ), preamble( p )
    1623             : {
    1624           0 : }
    1625             : 
    1626             : inline
    1627           0 : bool OpenGLContext::ProgramKey::operator< ( const ProgramKey& other ) const
    1628             : {
    1629           0 :     if( vertexShader != other.vertexShader )
    1630           0 :         return vertexShader < other.vertexShader;
    1631           0 :     if( fragmentShader != other.fragmentShader )
    1632           0 :         return fragmentShader < other.fragmentShader;
    1633           0 :     return preamble < other.preamble;
    1634         801 : }
    1635             : 
    1636             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11