LCOV - code coverage report
Current view: top level - vcl/source/opengl - OpenGLContext.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 37 194 19.1 %
Date: 2014-11-03 Functions: 9 25 36.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 <vcl/pngwrite.hxx>
      17             : #include <vcl/bmpacc.hxx>
      18             : #include <vcl/graph.hxx>
      19             : 
      20             : #if defined(MACOSX)
      21             : #include <premac.h>
      22             : #include "OpenGLWrapper.hxx"
      23             : #include <postmac.h>
      24             : #endif
      25             : 
      26             : using namespace com::sun::star;
      27             : 
      28          34 : GLWindow::~GLWindow()
      29             : {
      30             : #if defined( UNX ) && !defined MACOSX && !defined IOS && !defined ANDROID
      31          34 :     XFree(vi);
      32             : #endif
      33          34 : }
      34             : 
      35          34 : OpenGLContext::OpenGLContext():
      36             :     mpWindow(NULL),
      37             :     m_pChildWindow(NULL),
      38             :     mbInitialized(false),
      39          34 :     mbRequestLegacyContext(false)
      40             : {
      41          34 : }
      42             : 
      43          68 : OpenGLContext::~OpenGLContext()
      44             : {
      45             : #if defined( WNT )
      46             :     if (m_aGLWin.hRC)
      47             :     {
      48             :         wglMakeCurrent( m_aGLWin.hDC, 0 );
      49             :         wglDeleteContext( m_aGLWin.hRC );
      50             :         ReleaseDC( m_aGLWin.hWnd, m_aGLWin.hDC );
      51             :     }
      52             : #elif defined( MACOSX )
      53             :     OpenGLWrapper::resetCurrent();
      54             : #elif defined( IOS ) || defined( ANDROID )
      55             :     // nothing
      56             : #elif defined( UNX )
      57          34 :     if(m_aGLWin.ctx)
      58             :     {
      59           0 :         glXMakeCurrent(m_aGLWin.dpy, None, NULL);
      60           0 :         if( glGetError() != GL_NO_ERROR )
      61             :         {
      62             :             SAL_WARN("vcl.opengl", "glError: " << (char *)gluErrorString(glGetError()));
      63             :         }
      64           0 :         glXDestroyContext(m_aGLWin.dpy, m_aGLWin.ctx);
      65             :     }
      66             : #endif
      67          34 : }
      68             : 
      69           0 : void OpenGLContext::requestLegacyContext()
      70             : {
      71           0 :     mbRequestLegacyContext = true;
      72           0 : }
      73             : 
      74             : #if defined( _WIN32 )
      75             : static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
      76             : {
      77             :     switch (message)
      78             :     {
      79             :     case WM_CREATE:
      80             :         return 0;
      81             :     case WM_CLOSE:
      82             :         PostQuitMessage(0);
      83             :         return 0;
      84             :     case WM_DESTROY:
      85             :         return 0;
      86             :     case WM_KEYDOWN:
      87             :         switch(wParam)
      88             :         {
      89             :         case VK_ESCAPE:
      90             :             PostQuitMessage(0);
      91             :             return 0;
      92             : 
      93             :         case VK_SPACE:
      94             :             break;
      95             :         }
      96             :     default:
      97             :         return DefWindowProc(hwnd, message, wParam, lParam);
      98             :     }
      99             : }
     100             : 
     101             : int InitTempWindow(HWND *hwnd, int width, int height, PIXELFORMATDESCRIPTOR inPfd, GLWindow glWin)
     102             : {
     103             :     PIXELFORMATDESCRIPTOR  pfd = inPfd;
     104             :     int  pfmt;
     105             :     int ret;
     106             :     WNDCLASS wc;
     107             :     wc.style = 0;
     108             :     wc.lpfnWndProc = WndProc;
     109             :     wc.cbClsExtra = wc.cbWndExtra = 0;
     110             :     wc.hInstance = NULL;
     111             :     wc.hIcon = NULL;
     112             :     wc.hCursor = NULL;
     113             :     wc.hbrBackground = NULL;
     114             :     wc.lpszMenuName = NULL;
     115             :     wc.lpszClassName = (LPCSTR)"GLRenderer";
     116             :     RegisterClass(&wc);
     117             :     *hwnd = CreateWindow(wc.lpszClassName, NULL, WS_DISABLED, 0, 0, width, height, NULL, NULL, wc.hInstance, NULL);
     118             :     glWin.hDC = GetDC(*hwnd);
     119             :     pfmt = ChoosePixelFormat(glWin.hDC, &pfd);
     120             :     if (!pfmt)
     121             :     {
     122             :         return -1;
     123             :     }
     124             :     ret = SetPixelFormat(glWin.hDC, pfmt, &pfd);
     125             :     if(!ret)
     126             :     {
     127             :         return -1;
     128             :     }
     129             :     glWin.hRC = wglCreateContext(glWin.hDC);
     130             :     if(!(glWin.hRC))
     131             :     {
     132             :         return -1;
     133             :     }
     134             :     ret = wglMakeCurrent(glWin.hDC, glWin.hRC);
     135             :     if(!ret)
     136             :     {
     137             :         return -1;
     138             :     }
     139             :     return 0;
     140             : }
     141             : 
     142             : bool WGLisExtensionSupported(const char *extension)
     143             : {
     144             :     const size_t extlen = strlen(extension);
     145             :     const char *supported = NULL;
     146             : 
     147             :     // Try To Use wglGetExtensionStringARB On Current DC, If Possible
     148             :     PROC wglGetExtString = wglGetProcAddress("wglGetExtensionsStringARB");
     149             : 
     150             :     if (wglGetExtString)
     151             :         supported = ((char*(__stdcall*)(HDC))wglGetExtString)(wglGetCurrentDC());
     152             :     // If That Failed, Try Standard Opengl Extensions String
     153             :     if (supported == NULL)
     154             :         supported = (char*)glGetString(GL_EXTENSIONS);
     155             :     // If That Failed Too, Must Be No Extensions Supported
     156             :     if (supported == NULL)
     157             :         return 0;
     158             : 
     159             :     // Begin Examination At Start Of String, Increment By 1 On False Match
     160             :     for (const char* p = supported; ; p++)
     161             :     {
     162             :         // Advance p Up To The Next Possible Match
     163             :         p = strstr(p, extension);
     164             : 
     165             :         if (p == NULL)
     166             :             return 0; // No Match
     167             : 
     168             :         // Make Sure That Match Is At The Start Of The String Or That
     169             :         // The Previous Char Is A Space, Or Else We Could Accidentally
     170             :         // Match "wglFunkywglExtension" With "wglExtension"
     171             : 
     172             :         // Also, Make Sure That The Following Character Is Space Or NULL
     173             :         // Or Else "wglExtensionTwo" Might Match "wglExtension"
     174             :         if ((p==supported || p[-1]==' ') && (p[extlen]=='\0' || p[extlen]==' '))
     175             :             return 1; // Match
     176             :     }
     177             : }
     178             : 
     179             : bool InitMultisample(PIXELFORMATDESCRIPTOR pfd, int& rPixelFormat)
     180             : {
     181             :     HWND hWnd = NULL;
     182             :     GLWindow glWin;
     183             :     //create a temp windwo to check whether support multi-sample, if support, get the format
     184             :     if (InitTempWindow(&hWnd, 1, 1, pfd, glWin) < 0)
     185             :     {
     186             :         SAL_WARN("vcl.opengl", "Can't create temp window to test");
     187             :         return false;
     188             :     }
     189             : 
     190             :     // See If The String Exists In WGL!
     191             :     if (!WGLisExtensionSupported("WGL_ARB_multisample"))
     192             :     {
     193             :         SAL_WARN("vcl.opengl", "Device doesn't support multi sample");
     194             :         return false;
     195             :     }
     196             :     // Get Our Pixel Format
     197             :     PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB");
     198             :     if (!wglChoosePixelFormatARB)
     199             :     {
     200             :         return false;
     201             :     }
     202             :     // Get Our Current Device Context
     203             :     HDC hDC = GetDC(hWnd);
     204             : 
     205             :     int pixelFormat;
     206             :     int valid;
     207             :     UINT    numFormats;
     208             :     float   fAttributes[] = {0,0};
     209             :     // These Attributes Are The Bits We Want To Test For In Our Sample
     210             :     // Everything Is Pretty Standard, The Only One We Want To
     211             :     // Really Focus On Is The SAMPLE BUFFERS ARB And WGL SAMPLES
     212             :     // These Two Are Going To Do The Main Testing For Whether Or Not
     213             :     // We Support Multisampling On This Hardware.
     214             :     int iAttributes[] =
     215             :     {
     216             :         WGL_DRAW_TO_WINDOW_ARB,GL_TRUE,
     217             :         WGL_SUPPORT_OPENGL_ARB,GL_TRUE,
     218             :         WGL_ACCELERATION_ARB,WGL_FULL_ACCELERATION_ARB,
     219             :         WGL_COLOR_BITS_ARB,24,
     220             :         WGL_ALPHA_BITS_ARB,8,
     221             :         WGL_DEPTH_BITS_ARB,24,
     222             :         WGL_STENCIL_BITS_ARB,0,
     223             :         WGL_DOUBLE_BUFFER_ARB,GL_TRUE,
     224             :         WGL_SAMPLE_BUFFERS_ARB,GL_TRUE,
     225             :         WGL_SAMPLES_ARB,8,
     226             :         0,0
     227             :     };
     228             : 
     229             :     bool bArbMultisampleSupported = true;
     230             : 
     231             :     // First We Check To See If We Can Get A Pixel Format For 4 Samples
     232             :     valid = wglChoosePixelFormatARB(hDC, iAttributes, fAttributes, 1, &pixelFormat, &numFormats);
     233             :     // If We Returned True, And Our Format Count Is Greater Than 1
     234             :     if (valid && numFormats >= 1)
     235             :     {
     236             :         bArbMultisampleSupported = true;
     237             :         rPixelFormat = pixelFormat;
     238             :         wglMakeCurrent(NULL, NULL);
     239             :         wglDeleteContext(glWin.hRC);
     240             :         ReleaseDC(hWnd, glWin.hDC);
     241             :         DestroyWindow(hWnd);
     242             :         return bArbMultisampleSupported;
     243             :     }
     244             :     // Our Pixel Format With 4 Samples Failed, Test For 2 Samples
     245             :     iAttributes[19] = 2;
     246             :     valid = wglChoosePixelFormatARB(hDC, iAttributes, fAttributes, 1, &pixelFormat, &numFormats);
     247             :     if (valid && numFormats >= 1)
     248             :     {
     249             :         bArbMultisampleSupported = true;
     250             :         rPixelFormat = pixelFormat;
     251             :         wglMakeCurrent(NULL, NULL);
     252             :         wglDeleteContext(glWin.hRC);
     253             :         ReleaseDC(hWnd, glWin.hDC);
     254             :         DestroyWindow(hWnd);
     255             :         return bArbMultisampleSupported;
     256             :     }
     257             :     // Return The Valid Format
     258             :     wglMakeCurrent(NULL, NULL);
     259             :     wglDeleteContext(glWin.hRC);
     260             :     ReleaseDC(hWnd, glWin.hDC);
     261             :     DestroyWindow(hWnd);
     262             : 
     263             :     return  bArbMultisampleSupported;
     264             : }
     265             : #endif
     266             : 
     267             : #ifdef DBG_UTIL
     268             : 
     269             : namespace {
     270             : 
     271             : const char* getSeverityString(GLenum severity)
     272             : {
     273             :     switch(severity)
     274             :     {
     275             :         case GL_DEBUG_SEVERITY_LOW:
     276             :             return "low";
     277             :         case GL_DEBUG_SEVERITY_MEDIUM:
     278             :             return "medium";
     279             :         case GL_DEBUG_SEVERITY_HIGH:
     280             :             return "high";
     281             :         default:
     282             :             ;
     283             :     }
     284             : 
     285             :     return "unknown";
     286             : }
     287             : 
     288             : const char* getSourceString(GLenum source)
     289             : {
     290             :     switch(source)
     291             :     {
     292             :         case GL_DEBUG_SOURCE_API:
     293             :             return "API";
     294             :         case GL_DEBUG_SOURCE_SHADER_COMPILER:
     295             :             return "shader compiler";
     296             :         case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
     297             :             return "window system";
     298             :         case GL_DEBUG_SOURCE_THIRD_PARTY:
     299             :             return "third party";
     300             :         case GL_DEBUG_SOURCE_APPLICATION:
     301             :             return "Libreoffice";
     302             :         case GL_DEBUG_SOURCE_OTHER:
     303             :             return "unknown";
     304             :         default:
     305             :             ;
     306             :     }
     307             : 
     308             :     return "unknown";
     309             : }
     310             : 
     311             : const char* getTypeString(GLenum type)
     312             : {
     313             :     switch(type)
     314             :     {
     315             :         case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
     316             :             return "deprecated behavior";
     317             :         case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
     318             :             return "undefined behavior";
     319             :         case GL_DEBUG_TYPE_PERFORMANCE:
     320             :             return "performance";
     321             :         case GL_DEBUG_TYPE_PORTABILITY:
     322             :             return "portability";
     323             :         case GL_DEBUG_TYPE_MARKER:
     324             :             return "marker";
     325             :         case GL_DEBUG_TYPE_PUSH_GROUP:
     326             :             return "push group";
     327             :         case GL_DEBUG_TYPE_POP_GROUP:
     328             :             return "pop group";
     329             :         case GL_DEBUG_TYPE_OTHER:
     330             :             return "other";
     331             :         case GL_DEBUG_TYPE_ERROR:
     332             :             return "error";
     333             :         default:
     334             :             ;
     335             :     }
     336             : 
     337             :     return "unkown";
     338             : }
     339             : 
     340             : extern "C" void
     341             : #if defined _WIN32
     342             : APIENTRY
     343             : #endif
     344             : debug_callback(GLenum source, GLenum type, GLuint id,
     345             :         GLenum severity, GLsizei , const GLchar* message, GLvoid* )
     346             : {
     347             :     // ignore Nvidia's : "Program/shader state performance warning: Fragment Shader is going to be recompiled because the shader key based on GL state mismatches."
     348             :     // the GLSL compiler is a bit too aggressive in optimizing the state based on the current OpenGL state
     349             :     if (id == 131218)
     350             :         return;
     351             : 
     352             :     SAL_WARN("vcl.opengl", "OpenGL debug message: source: " << getSourceString(source) << ", type: "
     353             :             << getTypeString(type) << ", id: " << id << ", severity: " << getSeverityString(severity) << " with message: " << message);
     354             : }
     355             : 
     356             : }
     357             : 
     358             : #endif
     359             : 
     360             : #if defined UNX && !defined MACOSX && !defined IOS && !defined ANDROID
     361             : 
     362             : namespace {
     363             : 
     364             : static bool errorTriggered;
     365           0 : int oglErrorHandler( Display* /*dpy*/, XErrorEvent* /*evnt*/ )
     366             : {
     367           0 :     errorTriggered = true;
     368             : 
     369           0 :     return 0;
     370             : }
     371             : 
     372           0 : GLXFBConfig* getFBConfig(const SystemEnvData* sysData, int& nBestFBC)
     373             : {
     374           0 :     Display *dpy = reinterpret_cast<Display*>(sysData->pDisplay);
     375             : 
     376           0 :     if( dpy == 0 || !glXQueryExtension( dpy, NULL, NULL ) )
     377           0 :         return NULL;
     378             : 
     379           0 :     Window win = sysData->aWindow;
     380             : 
     381             :     SAL_INFO("vcl.opengl", "parent window: " << win);
     382             : 
     383             :     XWindowAttributes xattr;
     384           0 :     XGetWindowAttributes( dpy, win, &xattr );
     385             : 
     386           0 :     int screen = XScreenNumberOfScreen( xattr.screen );
     387             : 
     388             :     static int visual_attribs[] =
     389             :     {
     390             :         GLX_DOUBLEBUFFER,       True,
     391             :         GLX_X_RENDERABLE,       True,
     392             :         GLX_RED_SIZE,           8,
     393             :         GLX_GREEN_SIZE,         8,
     394             :         GLX_BLUE_SIZE,          8,
     395             :         GLX_ALPHA_SIZE,         8,
     396             :         GLX_DEPTH_SIZE,         24,
     397             :         GLX_X_VISUAL_TYPE,      GLX_TRUE_COLOR,
     398             :         None
     399             :     };
     400           0 :     int fbCount = 0;
     401             :     GLXFBConfig* pFBC = glXChooseFBConfig( dpy,
     402             :             screen,
     403           0 :             visual_attribs, &fbCount );
     404             : 
     405           0 :     if(!pFBC)
     406             :     {
     407             :         SAL_WARN("vcl.opengl", "no suitable fb format found");
     408           0 :         return NULL;
     409             :     }
     410             : 
     411           0 :     int best_num_samp = -1;
     412           0 :     for(int i = 0; i < fbCount; ++i)
     413             :     {
     414           0 :         XVisualInfo* pVi = glXGetVisualFromFBConfig( dpy, pFBC[i] );
     415           0 :         if(pVi)
     416             :         {
     417             :             // pick the one with the most samples per pixel
     418           0 :             int nSampleBuf = 0;
     419           0 :             int nSamples = 0;
     420           0 :             glXGetFBConfigAttrib( dpy, pFBC[i], GLX_SAMPLE_BUFFERS, &nSampleBuf );
     421           0 :             glXGetFBConfigAttrib( dpy, pFBC[i], GLX_SAMPLES       , &nSamples  );
     422             : 
     423           0 :             if ( nBestFBC < 0 || (nSampleBuf && ( nSamples > best_num_samp )) )
     424             :             {
     425           0 :                 nBestFBC = i;
     426           0 :                 best_num_samp = nSamples;
     427             :             }
     428             :         }
     429           0 :         XFree( pVi );
     430             :     }
     431             : 
     432           0 :     return pFBC;
     433             : }
     434             : 
     435             : }
     436             : 
     437             : #endif
     438             : 
     439           0 : bool OpenGLContext::init( vcl::Window* pParent )
     440             : {
     441           0 :     if(mbInitialized)
     442           0 :         return true;
     443             : 
     444           0 :     m_pWindow.reset(pParent ? NULL : new vcl::Window(0, WB_NOBORDER|WB_NODIALOGCONTROL));
     445           0 :     mpWindow = pParent ? pParent : m_pWindow.get();
     446           0 :     m_pChildWindow = 0;
     447           0 :     initWindow();
     448           0 :     return ImplInit();
     449             : }
     450             : 
     451          34 : bool OpenGLContext::init(SystemChildWindow* pChildWindow)
     452             : {
     453          34 :     if(mbInitialized)
     454           0 :         return true;
     455             : 
     456          34 :     if( !pChildWindow )
     457           0 :         return false;
     458             : 
     459          34 :     mpWindow = pChildWindow->GetParent();
     460          34 :     m_pChildWindow = pChildWindow;
     461          34 :     initWindow();
     462          34 :     return ImplInit();
     463             : }
     464             : 
     465          34 : bool OpenGLContext::ImplInit()
     466             : {
     467             :     SAL_INFO("vcl.opengl", "OpenGLContext::ImplInit----start");
     468          34 :     if(m_pWindow)
     469           0 :         m_pWindow->setPosSizePixel(0,0,0,0);
     470          34 :     m_aGLWin.Width = 0;
     471          34 :     m_aGLWin.Height = 0;
     472             : 
     473             : #if defined( WNT )
     474             :     m_aGLWin.hDC = GetDC(m_aGLWin.hWnd);
     475             : #elif defined( MACOSX )
     476             : 
     477             : #elif defined( IOS )
     478             : 
     479             :     SAL_INFO("vcl.opengl", "OpenGLContext not implemented yet for iOS");
     480             :     return false;
     481             : 
     482             : #elif defined( ANDROID )
     483             : 
     484             :     SAL_INFO("vcl.opengl", "OpenGLContext not implemented yet for Android");
     485             :     return false;
     486             : 
     487             : #elif defined( UNX )
     488             : #ifdef DBG_UTIL
     489             : 
     490             :     if (glXCreateContextAttribsARB && !mbRequestLegacyContext)
     491             :     {
     492             :         int best_fbc = -1;
     493             :         const SystemEnvData* sysData(m_pChildWindow->GetSystemData());
     494             :         GLXFBConfig* pFBC = getFBConfig(sysData, best_fbc);
     495             :         if (!pFBC)
     496             :             return false;
     497             : 
     498             :         int nContextAttribs[] =
     499             :         {
     500             :             GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
     501             :             GLX_CONTEXT_MINOR_VERSION_ARB, 2,
     502             :             None
     503             :         };
     504             :         m_aGLWin.ctx = glXCreateContextAttribsARB(m_aGLWin.dpy, pFBC[best_fbc], 0, GL_TRUE, nContextAttribs);
     505             : 
     506             :     }
     507             : #endif
     508          34 :     if (!m_aGLWin.ctx)
     509             :     {
     510          34 :         if (!m_aGLWin.dpy || !m_aGLWin.vi)
     511          34 :            return false;
     512             : 
     513           0 :         m_aGLWin.ctx = m_aGLWin.dpy == 0 ? 0 : glXCreateContext(m_aGLWin.dpy,
     514             :                 m_aGLWin.vi,
     515             :                 0,
     516           0 :                 GL_TRUE);
     517             :     }
     518           0 :     if( m_aGLWin.ctx == NULL )
     519             :     {
     520             :         SAL_WARN("vcl.opengl", "unable to create GLX context");
     521           0 :         return false;
     522             :     }
     523             : #endif
     524             : 
     525             : #if defined( WNT )
     526             :     PIXELFORMATDESCRIPTOR PixelFormatFront =                    // PixelFormat Tells Windows How We Want Things To Be
     527             :     {
     528             :         sizeof(PIXELFORMATDESCRIPTOR),
     529             :         1,                              // Version Number
     530             :         PFD_DRAW_TO_WINDOW |
     531             :         PFD_SUPPORT_OPENGL |
     532             :         PFD_DOUBLEBUFFER,
     533             :         PFD_TYPE_RGBA,                  // Request An RGBA Format
     534             :         (BYTE)32,                       // Select Our Color Depth
     535             :         0, 0, 0, 0, 0, 0,               // Color Bits Ignored
     536             :         0,                              // No Alpha Buffer
     537             :         0,                              // Shift Bit Ignored
     538             :         0,                              // No Accumulation Buffer
     539             :         0, 0, 0, 0,                     // Accumulation Bits Ignored
     540             :         64,                             // 32 bit Z-BUFFER
     541             :         0,                              // 0 bit stencil buffer
     542             :         0,                              // No Auxiliary Buffer
     543             :         0,                              // now ignored
     544             :         0,                              // Reserved
     545             :         0, 0, 0                         // Layer Masks Ignored
     546             :     };
     547             : 
     548             :     //  we must check whether can set the MSAA
     549             :     int WindowPix = 0;
     550             :     bool bMultiSampleSupport = InitMultisample(PixelFormatFront, WindowPix);
     551             :     if (bMultiSampleSupport && WindowPix != 0)
     552             :     {
     553             :         m_aGLWin.bMultiSampleSupported = true;
     554             :     }
     555             :     else
     556             :     {
     557             :         WindowPix = ChoosePixelFormat(m_aGLWin.hDC, &PixelFormatFront);
     558             :     }
     559             : 
     560             :     if (WindowPix == 0)
     561             :     {
     562             :         SAL_WARN("vcl.opengl", "Invalid pixelformat");
     563             :         return false;
     564             :     }
     565             : 
     566             :     SetPixelFormat(m_aGLWin.hDC, WindowPix, &PixelFormatFront);
     567             :     m_aGLWin.hRC = wglCreateContext(m_aGLWin.hDC);
     568             :     if (m_aGLWin.hRC == NULL)
     569             :     {
     570             :         SAL_WARN("vcl.opengl", "wglCreateContext failed");
     571             :         return false;
     572             :     }
     573             : 
     574             :     if (!wglMakeCurrent(m_aGLWin.hDC, m_aGLWin.hRC))
     575             :     {
     576             :         SAL_WARN("vcl.opengl", "wglMakeCurrent failed: " << GetLastError());
     577             :         return false;
     578             :     }
     579             : 
     580             : #elif defined( MACOSX )
     581             : 
     582             :     NSOpenGLView* pView = getOpenGLView();
     583             :     OpenGLWrapper::makeCurrent(pView);
     584             : 
     585             : #elif defined( IOS )
     586             : 
     587             : #elif defined( ANDROID )
     588             : 
     589             : #elif defined( UNX )
     590           0 :     if( !glXMakeCurrent( m_aGLWin.dpy, m_aGLWin.win, m_aGLWin.ctx ) )
     591             :     {
     592             :         SAL_INFO("vcl.opengl", "unable to select current GLX context");
     593           0 :         return false;
     594             :     }
     595             : 
     596             :     int glxMinor, glxMajor;
     597           0 :     double nGLXVersion = 0;
     598           0 :     if( glXQueryVersion( m_aGLWin.dpy, &glxMajor, &glxMinor ) )
     599           0 :       nGLXVersion = glxMajor + 0.1*glxMinor;
     600             :     SAL_INFO("vcl.opengl", "available GLX version: " << nGLXVersion);
     601             : 
     602           0 :     m_aGLWin.GLExtensions = glGetString( GL_EXTENSIONS );
     603             :     SAL_INFO("vcl.opengl", "available GL  extensions: " << m_aGLWin.GLExtensions);
     604             : 
     605           0 :     if( m_aGLWin.HasGLXExtension("GLX_SGI_swap_control" ) )
     606             :     {
     607             :         // enable vsync
     608             :         typedef GLint (*glXSwapIntervalProc)(GLint);
     609           0 :         glXSwapIntervalProc glXSwapInterval = (glXSwapIntervalProc) glXGetProcAddress( (const GLubyte*) "glXSwapIntervalSGI" );
     610           0 :         if( glXSwapInterval ) {
     611             :         int (*oldHandler)(Display* /*dpy*/, XErrorEvent* /*evnt*/);
     612             : 
     613             :         // replace error handler temporarily
     614           0 :         oldHandler = XSetErrorHandler( oglErrorHandler );
     615             : 
     616           0 :         errorTriggered = false;
     617             : 
     618           0 :         glXSwapInterval( 1 );
     619             : 
     620             :         // sync so that we possibly get an XError
     621           0 :         glXWaitGL();
     622           0 :         XSync(m_aGLWin.dpy, false);
     623             : 
     624           0 :         if( errorTriggered )
     625             :             SAL_WARN("vcl.opengl", "error when trying to set swap interval, NVIDIA or Mesa bug?");
     626             :         else
     627             :             SAL_INFO("vcl.opengl", "set swap interval to 1 (enable vsync)");
     628             : 
     629             :         // restore the error handler
     630           0 :         XSetErrorHandler( oldHandler );
     631             :         }
     632             :     }
     633             : 
     634             : #endif
     635             : 
     636             :     //rGLRender.InitOpenGL(m_aGLWin);
     637             : 
     638             :     static bool bGlewInit = false;
     639           0 :     if(!bGlewInit)
     640             :     {
     641           0 :         glewExperimental = GL_TRUE;
     642           0 :         GLenum err = glewInit();
     643           0 :         if (err != GLEW_OK)
     644             :         {
     645             :             SAL_WARN("vcl.opengl", "Failed to initialize GLEW: " << glewGetErrorString(err));
     646           0 :             return false;
     647             :         }
     648             :         else
     649           0 :             bGlewInit = true;
     650             :     }
     651             : 
     652             : #ifdef DBG_UTIL
     653             :     // only enable debug output in dbgutil build
     654             :     // somehow there are implementations where the feature is present and the function
     655             :     // pointer is still NULL
     656             :     if( GLEW_ARB_debug_output && glDebugMessageCallback )
     657             :     {
     658             :         glEnable(GL_DEBUG_OUTPUT);
     659             :         glDebugMessageCallback(&debug_callback, NULL);
     660             :     }
     661             : 
     662             : #endif
     663             : 
     664             :     SAL_INFO("vcl.opengl", "OpenGLContext::ImplInit----end");
     665           0 :     mbInitialized = true;
     666           0 :     return true;
     667             : }
     668             : 
     669           0 : void OpenGLContext::setWinPosAndSize(const Point &rPos, const Size& rSize)
     670             : {
     671           0 :     if(m_pWindow)
     672           0 :         m_pWindow->SetPosSizePixel(rPos, rSize);
     673           0 :     if( m_pChildWindow )
     674           0 :         m_pChildWindow->SetPosSizePixel(rPos, rSize);
     675             : 
     676           0 :     m_aGLWin.Width = rSize.Width();
     677           0 :     m_aGLWin.Height = rSize.Height();
     678           0 : }
     679             : 
     680           0 : void OpenGLContext::setWinSize(const Size& rSize)
     681             : {
     682           0 :     if(m_pWindow)
     683           0 :         m_pWindow->SetSizePixel(rSize);
     684           0 :     if( m_pChildWindow )
     685           0 :         m_pChildWindow->SetSizePixel(rSize);
     686             : 
     687           0 :     m_aGLWin.Width = rSize.Width();
     688           0 :     m_aGLWin.Height = rSize.Height();
     689           0 : }
     690             : 
     691             : 
     692           0 : void OpenGLContext::renderToFile()
     693             : {
     694           0 :     int iWidth = m_aGLWin.Width;
     695           0 :     int iHeight = m_aGLWin.Height;
     696             :     static int nIdx = 0;
     697           0 :     OUString aName = OUString( "file:///home/moggi/Documents/work/output" ) + OUString::number( nIdx++ ) + ".png";
     698           0 :     OpenGLHelper::renderToFile(iWidth, iHeight, aName);
     699           0 : }
     700             : 
     701             : #if defined( WNT )
     702             : 
     703             : bool OpenGLContext::initWindow()
     704             : {
     705             :     if( !m_pChildWindow )
     706             :     {
     707             :         SystemWindowData winData = generateWinData(mpWindow, false);
     708             :         m_pChildWindow = new SystemChildWindow(mpWindow, 0, &winData, false);
     709             :         m_pChildWindowGC.reset(m_pChildWindow);
     710             :     }
     711             : 
     712             :     if( m_pChildWindow )
     713             :     {
     714             :         m_pChildWindow->SetMouseTransparent( true );
     715             :         m_pChildWindow->SetParentClipMode(PARENTCLIPMODE_CLIP);
     716             :         m_pChildWindow->EnableEraseBackground( false );
     717             :         m_pChildWindow->SetControlForeground();
     718             :         m_pChildWindow->SetControlBackground();
     719             :         //m_pChildWindow->EnablePaint(false);
     720             : 
     721             :         const SystemEnvData* sysData(m_pChildWindow->GetSystemData());
     722             :         m_aGLWin.hWnd = sysData->hWnd;
     723             :     }
     724             : 
     725             :     return true;
     726             : }
     727             : 
     728             : #elif defined( MACOSX )
     729             : 
     730             : bool OpenGLContext::initWindow()
     731             : {
     732             :     if( !m_pChildWindow )
     733             :     {
     734             :         SystemWindowData winData = generateWinData(mpWindow, mbRequestLegacyContext);
     735             :         m_pChildWindow = new SystemChildWindow(mpWindow, 0, &winData, false);
     736             :         m_pChildWindowGC.reset(m_pChildWindow);
     737             :     }
     738             : 
     739             :     if( m_pChildWindow )
     740             :     {
     741             :         m_pChildWindow->SetMouseTransparent( true );
     742             :         m_pChildWindow->SetParentClipMode(PARENTCLIPMODE_CLIP);
     743             :         m_pChildWindow->EnableEraseBackground( false );
     744             :         m_pChildWindow->SetControlForeground();
     745             :         m_pChildWindow->SetControlBackground();
     746             :         //m_pChildWindow->EnablePaint(false);
     747             : 
     748             :     }
     749             : 
     750             :     return true;
     751             : }
     752             : 
     753             : #elif defined( IOS ) || defined( ANDROID )
     754             : 
     755             : bool OpenGLContext::initWindow()
     756             : {
     757             :     return false;
     758             : }
     759             : 
     760             : #elif defined( UNX )
     761             : 
     762          34 : bool OpenGLContext::initWindow()
     763             : {
     764          34 :     const SystemEnvData* pChildSysData = 0;
     765          34 :     SystemWindowData winData = generateWinData(mpWindow, false);
     766          34 :     if( winData.pVisual )
     767             :     {
     768           0 :         if( !m_pChildWindow )
     769             :         {
     770           0 :             m_pChildWindow = new SystemChildWindow(mpWindow, 0, &winData, false);
     771           0 :             m_pChildWindowGC.reset(m_pChildWindow);
     772             :         }
     773           0 :         pChildSysData = m_pChildWindow->GetSystemData();
     774             :     }
     775             : 
     776          34 :     if (!m_pChildWindow || !pChildSysData)
     777          34 :         return false;
     778             : 
     779           0 :     m_pChildWindow->SetMouseTransparent( true );
     780           0 :     m_pChildWindow->SetParentClipMode( PARENTCLIPMODE_NOCLIP );
     781           0 :     m_pChildWindow->EnableEraseBackground( false );
     782           0 :     m_pChildWindow->SetControlForeground();
     783           0 :     m_pChildWindow->SetControlBackground();
     784             : 
     785           0 :     m_aGLWin.dpy = reinterpret_cast<Display*>(pChildSysData->pDisplay);
     786           0 :     m_aGLWin.win = pChildSysData->aWindow;
     787           0 :     m_aGLWin.screen = pChildSysData->nScreen;
     788             : 
     789             :     // Get visual info
     790             :     {
     791           0 :         Visual* pVisual = (Visual*)pChildSysData->pVisual;
     792             :         XVisualInfo aTemplate;
     793           0 :         aTemplate.visualid = XVisualIDFromVisual( pVisual );
     794           0 :         int nVisuals = 0;
     795           0 :         XVisualInfo* pInfos = XGetVisualInfo( m_aGLWin.dpy, VisualIDMask, &aTemplate, &nVisuals );
     796           0 :         if( nVisuals != 1 )
     797             :             SAL_WARN( "vcl.opengl", "match count for visual id is not 1" );
     798           0 :         m_aGLWin.vi = pInfos;
     799             :     }
     800             : 
     801             :     // Check multi sample support
     802           0 :     int nSamples = 0;
     803           0 :     glXGetConfig(m_aGLWin.dpy, m_aGLWin.vi, GLX_SAMPLES, &nSamples);
     804           0 :     if( nSamples > 0 )
     805           0 :         m_aGLWin.bMultiSampleSupported = true;
     806             : 
     807           0 :     m_aGLWin.GLXExtensions = glXQueryExtensionsString( m_aGLWin.dpy, m_aGLWin.screen );
     808             :     SAL_INFO("vcl.opengl", "available GLX extensions: " << m_aGLWin.GLXExtensions);
     809             : 
     810           0 :     return true;
     811             : }
     812             : 
     813             : #endif
     814             : 
     815             : #if defined( WNT ) || defined( MACOSX ) || defined( IOS ) || defined( ANDROID )
     816             : 
     817             : SystemWindowData OpenGLContext::generateWinData(vcl::Window* /*pParent*/, bool bRequestLegacyContext)
     818             : {
     819             :     (void) bRequestLegacyContext;
     820             :     SystemWindowData aWinData;
     821             : #if defined(MACOSX)
     822             :     aWinData.bOpenGL = true;
     823             :     aWinData.bLegacy = bRequestLegacyContext;
     824             : #endif
     825             :     aWinData.nSize = sizeof(aWinData);
     826             :     return aWinData;
     827             : }
     828             : 
     829             : #elif defined( UNX )
     830             : 
     831             : namespace {
     832             : 
     833             : // we need them before glew can initialize them
     834             : // glew needs an OpenGL context so we need to get the address manually
     835           0 : void initOpenGLFunctionPointers()
     836             : {
     837           0 :     glXChooseFBConfig = (GLXFBConfig*(*)(Display *dpy, int screen, const int *attrib_list, int *nelements))glXGetProcAddressARB((GLubyte*)"glXChooseFBConfig");
     838           0 :     glXGetVisualFromFBConfig = (XVisualInfo*(*)(Display *dpy, GLXFBConfig config))glXGetProcAddressARB((GLubyte*)"glXGetVisualFromFBConfig");    // try to find a visual for the current set of attributes
     839           0 :     glXGetFBConfigAttrib = (int(*)(Display *dpy, GLXFBConfig config, int attribute, int* value))glXGetProcAddressARB((GLubyte*)"glXGetFBConfigAttrib");
     840           0 :     glXCreateContextAttribsARB = (GLXContext(*) (Display*, GLXFBConfig, GLXContext, Bool, const int*)) glXGetProcAddressARB((const GLubyte *) "glXCreateContextAttribsARB");;
     841           0 : }
     842             : 
     843             : }
     844             : 
     845          68 : SystemWindowData OpenGLContext::generateWinData(vcl::Window* pParent, bool)
     846             : {
     847             :     SystemWindowData aWinData;
     848          68 :     aWinData.nSize = sizeof(aWinData);
     849          68 :     aWinData.pVisual = NULL;
     850             : 
     851          68 :     const SystemEnvData* sysData(pParent->GetSystemData());
     852             : 
     853          68 :     Display *dpy = reinterpret_cast<Display*>(sysData->pDisplay);
     854             : 
     855          68 :     if( dpy == 0 || !glXQueryExtension( dpy, NULL, NULL ) )
     856          68 :         return aWinData;
     857             : 
     858           0 :     initOpenGLFunctionPointers();
     859             : 
     860           0 :     int best_fbc = -1;
     861           0 :     GLXFBConfig* pFBC = getFBConfig(sysData, best_fbc);
     862             : 
     863           0 :     XVisualInfo* vi = glXGetVisualFromFBConfig( dpy, pFBC[best_fbc] );
     864           0 :     if( vi )
     865             :     {
     866             :         SAL_INFO("vcl.opengl", "using VisualID " << vi->visualid);
     867           0 :         aWinData.pVisual = (void*)(vi->visual);
     868             :     }
     869             : 
     870           0 :     XFree(pFBC);
     871             : 
     872           0 :     return aWinData;
     873             : }
     874             : 
     875             : #endif
     876             : 
     877           0 : void OpenGLContext::makeCurrent()
     878             : {
     879             : #if defined( WNT )
     880             :     if (!wglMakeCurrent(m_aGLWin.hDC, m_aGLWin.hRC))
     881             :     {
     882             :         SAL_WARN("vcl.opengl", "OpenGLContext::makeCurrent(): wglMakeCurrent failed: " << GetLastError());
     883             :     }
     884             : #elif defined( MACOSX )
     885             :     NSOpenGLView* pView = getOpenGLView();
     886             :     OpenGLWrapper::makeCurrent(pView);
     887             : #elif defined( IOS ) || defined( ANDROID )
     888             :     // nothing
     889             : #elif defined( UNX )
     890           0 :     glXMakeCurrent( m_aGLWin.dpy, m_aGLWin.win, m_aGLWin.ctx );
     891             : #endif
     892           0 : }
     893             : 
     894           0 : void OpenGLContext::resetCurrent()
     895             : {
     896             : #if defined( WNT )
     897             :     wglMakeCurrent( m_aGLWin.hDC, 0 );
     898             : #elif defined( MACOSX )
     899             :     OpenGLWrapper::resetCurrent();
     900             : #elif defined( IOS ) || defined( ANDROID )
     901             :     // nothing
     902             : #elif defined( UNX )
     903           0 :     glXMakeCurrent(m_aGLWin.dpy, None, NULL);
     904             : #endif
     905           0 : }
     906             : 
     907           0 : void OpenGLContext::swapBuffers()
     908             : {
     909             : #if defined( WNT )
     910             :     SwapBuffers(m_aGLWin.hDC);
     911             : #elif defined( MACOSX )
     912             :     NSOpenGLView* pView = getOpenGLView();
     913             :     OpenGLWrapper::swapBuffers(pView);
     914             : #elif defined( IOS ) || defined( ANDROID )
     915             :     // nothing
     916             : #elif defined( UNX )
     917           0 :     glXSwapBuffers(m_aGLWin.dpy, m_aGLWin.win);
     918             : #endif
     919           0 : }
     920             : 
     921           0 : void OpenGLContext::sync()
     922             : {
     923             : #if defined( WNT )
     924             :     // nothing
     925             : #elif defined( MACOSX ) || defined( IOS ) || defined( ANDROID )
     926             :     // nothing
     927             : #elif defined( UNX )
     928           0 :     glXWaitGL();
     929           0 :     XSync(m_aGLWin.dpy, false);
     930             : #endif
     931           0 : }
     932             : 
     933           0 : void OpenGLContext::show()
     934             : {
     935           0 :     if (m_pChildWindow)
     936           0 :         m_pChildWindow->Show();
     937           0 :     else if (m_pWindow)
     938           0 :         m_pWindow->Show();
     939           0 : }
     940             : 
     941           0 : SystemChildWindow* OpenGLContext::getChildWindow()
     942             : {
     943           0 :     return m_pChildWindow;
     944             : }
     945             : 
     946           0 : const SystemChildWindow* OpenGLContext::getChildWindow() const
     947             : {
     948           0 :     return m_pChildWindow;
     949             : }
     950             : 
     951           0 : bool OpenGLContext::supportMultiSampling() const
     952             : {
     953           0 :     return m_aGLWin.bMultiSampleSupported;
     954         651 : }
     955             : 
     956             : #if defined(MACOSX)
     957             : NSOpenGLView* OpenGLContext::getOpenGLView()
     958             : {
     959             :     return reinterpret_cast<NSOpenGLView*>(m_pChildWindow->GetSystemData()->mpNSView);
     960             : }
     961             : #endif
     962             : 
     963             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10