2014-03-14 18:51:06 +01:00
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project .
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License , v . 2.0 . If a copy of the MPL was not distributed with this
* file , You can obtain one at http : //mozilla.org/MPL/2.0/.
*/
2014-04-15 00:43:50 +02:00
# include <vcl/opengl/OpenGLContext.hxx>
2014-04-27 20:25:52 +02:00
# include <vcl/opengl/OpenGLHelper.hxx>
2014-03-17 05:06:00 +01:00
# include <vcl/syschild.hxx>
# include <vcl/sysdata.hxx>
2014-03-14 18:51:06 +01:00
2014-04-08 02:16:08 +02:00
# include <boost/scoped_array.hpp>
# include <vcl/pngwrite.hxx>
# include <vcl/bmpacc.hxx>
# include <vcl/graph.hxx>
2014-09-01 23:10:54 +02:00
# if defined(MACOSX)
2014-09-01 00:36:15 +02:00
# include <premac.h>
# include "OpenGLWrapper.hxx"
# include <postmac.h>
2014-09-01 23:10:54 +02:00
# endif
2014-09-01 00:36:15 +02:00
2014-11-17 12:29:56 +01:00
# if defined( WNT )
# include <win/saldata.hxx>
# endif
2014-03-14 18:51:06 +01:00
using namespace com : : sun : : star ;
2014-11-18 11:45:40 +01:00
// TODO use rtl::Static instead of 'static'
2014-11-06 05:18:48 +01:00
# if defined( UNX ) && !defined MACOSX && !defined IOS && !defined ANDROID
2014-11-18 11:45:40 +01:00
static std : : vector < GLXContext > vShareList ;
# elif defined(WNT)
static std : : vector < HGLRC > vShareList ;
2014-11-06 05:18:48 +01:00
# endif
2014-11-04 17:32:48 -05:00
2014-05-23 02:11:23 +02:00
GLWindow : : ~ GLWindow ( )
{
2014-05-23 03:01:35 +02:00
# if defined( UNX ) && !defined MACOSX && !defined IOS && !defined ANDROID
2014-05-23 02:11:23 +02:00
XFree ( vi ) ;
# endif
}
2014-04-02 03:31:01 +02:00
OpenGLContext : : OpenGLContext ( ) :
2014-04-02 03:31:38 +02:00
mpWindow ( NULL ) ,
2014-04-29 11:09:05 +01:00
m_pChildWindow ( NULL ) ,
2014-08-16 05:36:30 +02:00
mbInitialized ( false ) ,
2014-10-31 19:19:47 +01:00
mbRequestLegacyContext ( false ) ,
2014-11-04 01:15:30 +01:00
mbUseDoubleBufferedRendering ( true ) ,
2014-11-09 08:43:44 +01:00
mbRequestVirtualDevice ( false )
2014-03-15 07:07:08 +01:00
{
2014-11-09 08:43:44 +01:00
# if defined( UNX ) && !defined MACOSX && !defined IOS && !defined ANDROID
mbPixmap = false ;
# endif
2014-03-15 07:07:08 +01:00
}
OpenGLContext : : ~ OpenGLContext ( )
{
2014-04-28 12:01:37 +02:00
# if defined( WNT )
if ( m_aGLWin . hRC )
{
2014-11-18 11:45:40 +01:00
vShareList . erase ( std : : remove ( vShareList . begin ( ) , vShareList . end ( ) , m_aGLWin . hRC ) ) ;
2014-04-28 12:01:37 +02:00
wglMakeCurrent ( m_aGLWin . hDC , 0 ) ;
wglDeleteContext ( m_aGLWin . hRC ) ;
ReleaseDC ( m_aGLWin . hWnd , m_aGLWin . hDC ) ;
}
2014-07-16 08:02:32 +02:00
# elif defined( MACOSX )
2014-09-01 00:36:15 +02:00
OpenGLWrapper : : resetCurrent ( ) ;
2014-07-16 08:02:32 +02:00
# elif defined( IOS ) || defined( ANDROID )
2014-04-28 12:01:37 +02:00
// nothing
# elif defined( UNX )
if ( m_aGLWin . ctx )
{
2014-11-15 18:39:08 +01:00
vShareList . erase ( std : : remove ( vShareList . begin ( ) , vShareList . end ( ) , m_aGLWin . ctx ) ) ;
2014-11-04 17:32:48 -05:00
2014-04-28 12:01:37 +02:00
glXMakeCurrent ( m_aGLWin . dpy , None , NULL ) ;
if ( glGetError ( ) ! = GL_NO_ERROR )
{
SAL_WARN ( " vcl.opengl " , " glError: " < < ( char * ) gluErrorString ( glGetError ( ) ) ) ;
}
glXDestroyContext ( m_aGLWin . dpy , m_aGLWin . ctx ) ;
2014-11-07 07:32:00 +01:00
if ( mbPixmap )
glXDestroyGLXPixmap ( m_aGLWin . dpy , m_aGLWin . glPix ) ;
2014-04-28 12:01:37 +02:00
}
# endif
2014-03-15 07:07:08 +01:00
}
2014-08-16 05:36:30 +02:00
void OpenGLContext : : requestLegacyContext ( )
{
mbRequestLegacyContext = true ;
}
2014-10-31 19:19:47 +01:00
void OpenGLContext : : requestSingleBufferedRendering ( )
{
mbUseDoubleBufferedRendering = false ;
}
2014-11-04 01:15:30 +01:00
void OpenGLContext : : requestVirtualDevice ( )
{
mbRequestVirtualDevice = true ;
}
2014-03-17 05:13:12 +01:00
# if defined( _WIN32 )
static LRESULT CALLBACK WndProc ( HWND hwnd , UINT message , WPARAM wParam , LPARAM lParam )
{
switch ( message )
{
case WM_CREATE :
return 0 ;
case WM_CLOSE :
PostQuitMessage ( 0 ) ;
return 0 ;
case WM_DESTROY :
return 0 ;
case WM_KEYDOWN :
switch ( wParam )
{
case VK_ESCAPE :
PostQuitMessage ( 0 ) ;
return 0 ;
case VK_SPACE :
break ;
}
default :
return DefWindowProc ( hwnd , message , wParam , lParam ) ;
}
}
2014-03-17 08:11:38 +01:00
int InitTempWindow ( HWND * hwnd , int width , int height , PIXELFORMATDESCRIPTOR inPfd , GLWindow glWin )
2014-03-17 05:13:12 +01:00
{
PIXELFORMATDESCRIPTOR pfd = inPfd ;
int pfmt ;
int ret ;
WNDCLASS wc ;
wc . style = 0 ;
wc . lpfnWndProc = WndProc ;
wc . cbClsExtra = wc . cbWndExtra = 0 ;
wc . hInstance = NULL ;
wc . hIcon = NULL ;
wc . hCursor = NULL ;
wc . hbrBackground = NULL ;
wc . lpszMenuName = NULL ;
wc . lpszClassName = ( LPCSTR ) " GLRenderer " ;
RegisterClass ( & wc ) ;
* hwnd = CreateWindow ( wc . lpszClassName , NULL , WS_DISABLED , 0 , 0 , width , height , NULL , NULL , wc . hInstance , NULL ) ;
glWin . hDC = GetDC ( * hwnd ) ;
pfmt = ChoosePixelFormat ( glWin . hDC , & pfd ) ;
if ( ! pfmt )
{
return - 1 ;
}
ret = SetPixelFormat ( glWin . hDC , pfmt , & pfd ) ;
if ( ! ret )
{
return - 1 ;
}
glWin . hRC = wglCreateContext ( glWin . hDC ) ;
if ( ! ( glWin . hRC ) )
{
return - 1 ;
}
ret = wglMakeCurrent ( glWin . hDC , glWin . hRC ) ;
if ( ! ret )
{
return - 1 ;
}
2014-11-14 15:43:44 +01:00
CHECK_GL_ERROR ( ) ;
2014-03-17 05:13:12 +01:00
return 0 ;
}
bool WGLisExtensionSupported ( const char * extension )
{
const size_t extlen = strlen ( extension ) ;
const char * supported = NULL ;
// Try To Use wglGetExtensionStringARB On Current DC, If Possible
PROC wglGetExtString = wglGetProcAddress ( " wglGetExtensionsStringARB " ) ;
if ( wglGetExtString )
supported = ( ( char * ( __stdcall * ) ( HDC ) ) wglGetExtString ) ( wglGetCurrentDC ( ) ) ;
// If That Failed, Try Standard Opengl Extensions String
if ( supported = = NULL )
supported = ( char * ) glGetString ( GL_EXTENSIONS ) ;
// If That Failed Too, Must Be No Extensions Supported
if ( supported = = NULL )
2014-11-02 02:49:22 +01:00
return false ;
2014-03-17 05:13:12 +01:00
// Begin Examination At Start Of String, Increment By 1 On False Match
for ( const char * p = supported ; ; p + + )
{
// Advance p Up To The Next Possible Match
p = strstr ( p , extension ) ;
if ( p = = NULL )
return 0 ; // No Match
// Make Sure That Match Is At The Start Of The String Or That
// The Previous Char Is A Space, Or Else We Could Accidentally
// Match "wglFunkywglExtension" With "wglExtension"
// Also, Make Sure That The Following Character Is Space Or NULL
// Or Else "wglExtensionTwo" Might Match "wglExtension"
if ( ( p = = supported | | p [ - 1 ] = = ' ' ) & & ( p [ extlen ] = = ' \0 ' | | p [ extlen ] = = ' ' ) )
return 1 ; // Match
}
}
2014-11-04 01:15:30 +01:00
bool InitMultisample ( PIXELFORMATDESCRIPTOR pfd , int & rPixelFormat ,
bool bUseDoubleBufferedRendering , bool bRequestVirtualDevice )
2014-03-17 05:13:12 +01:00
{
HWND hWnd = NULL ;
2014-03-17 08:11:38 +01:00
GLWindow glWin ;
2014-03-17 05:13:12 +01:00
//create a temp windwo to check whether support multi-sample, if support, get the format
2014-03-17 08:11:38 +01:00
if ( InitTempWindow ( & hWnd , 1 , 1 , pfd , glWin ) < 0 )
2014-03-17 05:13:12 +01:00
{
SAL_WARN ( " vcl.opengl " , " Can't create temp window to test " ) ;
return false ;
}
// See If The String Exists In WGL!
if ( ! WGLisExtensionSupported ( " WGL_ARB_multisample " ) )
{
SAL_WARN ( " vcl.opengl " , " Device doesn't support multi sample " ) ;
return false ;
}
// Get Our Pixel Format
PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = ( PFNWGLCHOOSEPIXELFORMATARBPROC ) wglGetProcAddress ( " wglChoosePixelFormatARB " ) ;
if ( ! wglChoosePixelFormatARB )
{
return false ;
}
// Get Our Current Device Context
HDC hDC = GetDC ( hWnd ) ;
int pixelFormat ;
int valid ;
UINT numFormats ;
float fAttributes [ ] = { 0 , 0 } ;
// These Attributes Are The Bits We Want To Test For In Our Sample
// Everything Is Pretty Standard, The Only One We Want To
// Really Focus On Is The SAMPLE BUFFERS ARB And WGL SAMPLES
// These Two Are Going To Do The Main Testing For Whether Or Not
// We Support Multisampling On This Hardware.
int iAttributes [ ] =
{
2014-10-31 19:19:47 +01:00
WGL_DOUBLE_BUFFER_ARB , GL_TRUE ,
2014-03-17 05:13:12 +01:00
WGL_DRAW_TO_WINDOW_ARB , GL_TRUE ,
WGL_SUPPORT_OPENGL_ARB , GL_TRUE ,
WGL_ACCELERATION_ARB , WGL_FULL_ACCELERATION_ARB ,
WGL_COLOR_BITS_ARB , 24 ,
WGL_ALPHA_BITS_ARB , 8 ,
2014-06-09 23:46:03 -07:00
WGL_DEPTH_BITS_ARB , 24 ,
2014-03-17 05:13:12 +01:00
WGL_STENCIL_BITS_ARB , 0 ,
WGL_SAMPLE_BUFFERS_ARB , GL_TRUE ,
WGL_SAMPLES_ARB , 8 ,
0 , 0
} ;
2014-03-17 08:11:38 +01:00
2014-11-02 02:13:16 +01:00
if ( ! bUseDoubleBufferedRendering )
2014-10-31 19:19:47 +01:00
iAttributes [ 1 ] = GL_FALSE ;
2014-11-04 01:15:30 +01:00
if ( bRequestVirtualDevice )
{
iAttributes [ 2 ] = WGL_DRAW_TO_BITMAP_ARB ;
}
2014-03-17 08:11:38 +01:00
bool bArbMultisampleSupported = true ;
2014-03-17 05:13:12 +01:00
// First We Check To See If We Can Get A Pixel Format For 4 Samples
valid = wglChoosePixelFormatARB ( hDC , iAttributes , fAttributes , 1 , & pixelFormat , & numFormats ) ;
// If We Returned True, And Our Format Count Is Greater Than 1
if ( valid & & numFormats > = 1 )
{
2014-03-17 08:11:38 +01:00
bArbMultisampleSupported = true ;
rPixelFormat = pixelFormat ;
2014-03-17 05:13:12 +01:00
wglMakeCurrent ( NULL , NULL ) ;
wglDeleteContext ( glWin . hRC ) ;
ReleaseDC ( hWnd , glWin . hDC ) ;
DestroyWindow ( hWnd ) ;
2014-03-17 08:11:38 +01:00
return bArbMultisampleSupported ;
2014-03-17 05:13:12 +01:00
}
// Our Pixel Format With 4 Samples Failed, Test For 2 Samples
iAttributes [ 19 ] = 2 ;
valid = wglChoosePixelFormatARB ( hDC , iAttributes , fAttributes , 1 , & pixelFormat , & numFormats ) ;
if ( valid & & numFormats > = 1 )
{
2014-03-17 08:11:38 +01:00
bArbMultisampleSupported = true ;
rPixelFormat = pixelFormat ;
2014-03-17 05:13:12 +01:00
wglMakeCurrent ( NULL , NULL ) ;
wglDeleteContext ( glWin . hRC ) ;
ReleaseDC ( hWnd , glWin . hDC ) ;
DestroyWindow ( hWnd ) ;
2014-03-17 08:11:38 +01:00
return bArbMultisampleSupported ;
2014-03-17 05:13:12 +01:00
}
// Return The Valid Format
wglMakeCurrent ( NULL , NULL ) ;
wglDeleteContext ( glWin . hRC ) ;
ReleaseDC ( hWnd , glWin . hDC ) ;
DestroyWindow ( hWnd ) ;
2014-03-17 08:11:38 +01:00
2014-11-14 19:12:11 +01:00
return bArbMultisampleSupported ;
2014-03-17 05:13:12 +01:00
}
# endif
2014-03-14 18:51:06 +01:00
# ifdef DBG_UTIL
namespace {
const char * getSeverityString ( GLenum severity )
{
switch ( severity )
{
case GL_DEBUG_SEVERITY_LOW :
return " low " ;
case GL_DEBUG_SEVERITY_MEDIUM :
return " medium " ;
case GL_DEBUG_SEVERITY_HIGH :
return " high " ;
default :
;
}
return " unknown " ;
}
const char * getSourceString ( GLenum source )
{
switch ( source )
{
case GL_DEBUG_SOURCE_API :
return " API " ;
case GL_DEBUG_SOURCE_SHADER_COMPILER :
return " shader compiler " ;
case GL_DEBUG_SOURCE_WINDOW_SYSTEM :
return " window system " ;
case GL_DEBUG_SOURCE_THIRD_PARTY :
return " third party " ;
case GL_DEBUG_SOURCE_APPLICATION :
return " Libreoffice " ;
case GL_DEBUG_SOURCE_OTHER :
return " unknown " ;
default :
;
}
return " unknown " ;
}
const char * getTypeString ( GLenum type )
{
switch ( type )
{
case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR :
return " deprecated behavior " ;
case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR :
return " undefined behavior " ;
case GL_DEBUG_TYPE_PERFORMANCE :
return " performance " ;
case GL_DEBUG_TYPE_PORTABILITY :
return " portability " ;
case GL_DEBUG_TYPE_MARKER :
return " marker " ;
case GL_DEBUG_TYPE_PUSH_GROUP :
return " push group " ;
case GL_DEBUG_TYPE_POP_GROUP :
return " pop group " ;
case GL_DEBUG_TYPE_OTHER :
return " other " ;
2014-05-17 07:39:46 +02:00
case GL_DEBUG_TYPE_ERROR :
return " error " ;
2014-03-14 18:51:06 +01:00
default :
;
}
2014-11-10 15:05:25 +01:00
return " unknown " ;
2014-03-14 18:51:06 +01:00
}
extern " C " void
# if defined _WIN32
APIENTRY
# endif
debug_callback ( GLenum source , GLenum type , GLuint id ,
GLenum severity , GLsizei , const GLchar * message , GLvoid * )
{
2014-08-28 21:00:42 +02:00
// ignore Nvidia's : "Program/shader state performance warning: Fragment Shader is going to be recompiled because the shader key based on GL state mismatches."
// the GLSL compiler is a bit too aggressive in optimizing the state based on the current OpenGL state
if ( id = = 131218 )
return ;
2014-03-14 18:51:06 +01:00
SAL_WARN ( " vcl.opengl " , " OpenGL debug message: source: " < < getSourceString ( source ) < < " , type: "
< < getTypeString ( type ) < < " , id: " < < id < < " , severity: " < < getSeverityString ( severity ) < < " with message: " < < message ) ;
}
}
# endif
2014-04-08 16:50:48 +03:00
# if defined UNX && !defined MACOSX && !defined IOS && !defined ANDROID
2014-03-14 22:11:29 +01:00
namespace {
2014-03-14 18:51:06 +01:00
static bool errorTriggered ;
int oglErrorHandler ( Display * /*dpy*/ , XErrorEvent * /*evnt*/ )
{
errorTriggered = true ;
return 0 ;
}
2014-11-07 07:32:00 +01:00
GLXFBConfig * getFBConfigForPixmap ( Display * dpy , int & nBestFBC , bool bUseDoubleBufferedRendering , int screen )
{
static int visual_attribs [ ] =
{
2014-11-08 18:55:26 +01:00
GLX_DOUBLEBUFFER , False ,
GLX_DRAWABLE_TYPE , GLX_PIXMAP_BIT ,
2014-11-07 07:32:00 +01:00
GLX_X_RENDERABLE , True ,
GLX_RED_SIZE , 8 ,
GLX_GREEN_SIZE , 8 ,
GLX_BLUE_SIZE , 8 ,
GLX_ALPHA_SIZE , 8 ,
GLX_DEPTH_SIZE , 24 ,
GLX_X_VISUAL_TYPE , GLX_TRUE_COLOR ,
None
} ;
2014-11-08 18:55:26 +01:00
if ( bUseDoubleBufferedRendering )
visual_attribs [ 1 ] = True ;
2014-11-07 07:32:00 +01:00
int fbCount = 0 ;
GLXFBConfig * pFBC = glXChooseFBConfig ( dpy ,
screen ,
visual_attribs , & fbCount ) ;
if ( ! pFBC )
{
SAL_WARN ( " vcl.opengl " , " no suitable fb format found " ) ;
return NULL ;
}
int best_num_samp = - 1 ;
for ( int i = 0 ; i < fbCount ; + + i )
{
// pick the one with the most samples per pixel
int nSampleBuf = 0 ;
int nSamples = 0 ;
glXGetFBConfigAttrib ( dpy , pFBC [ i ] , GLX_SAMPLE_BUFFERS , & nSampleBuf ) ;
glXGetFBConfigAttrib ( dpy , pFBC [ i ] , GLX_SAMPLES , & nSamples ) ;
if ( nBestFBC < 0 | | ( nSampleBuf & & ( nSamples > best_num_samp ) ) )
{
nBestFBC = i ;
best_num_samp = nSamples ;
}
}
2014-11-14 15:43:44 +01:00
CHECK_GL_ERROR ( ) ;
2014-11-07 07:32:00 +01:00
return pFBC ;
}
2014-10-29 13:20:52 +01:00
# ifdef DBG_UTIL
2014-10-31 19:19:47 +01:00
GLXFBConfig * getFBConfig ( Display * dpy , Window win , int & nBestFBC , bool bUseDoubleBufferedRendering )
2014-09-03 14:21:19 +02:00
{
if ( dpy = = 0 | | ! glXQueryExtension ( dpy , NULL , NULL ) )
return NULL ;
2014-10-25 12:39:04 +02:00
SAL_INFO ( " vcl.opengl " , " window: " < < win ) ;
2014-09-03 14:21:19 +02:00
XWindowAttributes xattr ;
2014-11-17 21:07:27 +00:00
if ( ! XGetWindowAttributes ( dpy , win , & xattr ) )
{
SAL_WARN ( " vcl.opengl " , " Failed to get window attributes for fbconfig " < < win ) ;
xattr . screen = 0 ;
xattr . visual = NULL ;
}
2014-09-03 14:21:19 +02:00
int screen = XScreenNumberOfScreen ( xattr . screen ) ;
2014-10-29 13:20:52 +01:00
// TODO: moggi: Select colour channel depth based on visual attributes, not hardcoded */
2014-09-03 14:21:19 +02:00
static int visual_attribs [ ] =
{
GLX_DOUBLEBUFFER , True ,
GLX_X_RENDERABLE , True ,
GLX_RED_SIZE , 8 ,
GLX_GREEN_SIZE , 8 ,
GLX_BLUE_SIZE , 8 ,
GLX_ALPHA_SIZE , 8 ,
GLX_DEPTH_SIZE , 24 ,
GLX_X_VISUAL_TYPE , GLX_TRUE_COLOR ,
None
} ;
2014-10-31 19:19:47 +01:00
if ( ! bUseDoubleBufferedRendering )
visual_attribs [ 1 ] = False ;
2014-09-03 14:21:19 +02:00
int fbCount = 0 ;
GLXFBConfig * pFBC = glXChooseFBConfig ( dpy ,
screen ,
visual_attribs , & fbCount ) ;
if ( ! pFBC )
{
SAL_WARN ( " vcl.opengl " , " no suitable fb format found " ) ;
return NULL ;
}
int best_num_samp = - 1 ;
for ( int i = 0 ; i < fbCount ; + + i )
{
XVisualInfo * pVi = glXGetVisualFromFBConfig ( dpy , pFBC [ i ] ) ;
2014-10-29 13:20:52 +01:00
if ( pVi & & pVi - > visualid = = xattr . visual - > visualid )
2014-09-03 14:21:19 +02:00
{
// pick the one with the most samples per pixel
int nSampleBuf = 0 ;
int nSamples = 0 ;
glXGetFBConfigAttrib ( dpy , pFBC [ i ] , GLX_SAMPLE_BUFFERS , & nSampleBuf ) ;
glXGetFBConfigAttrib ( dpy , pFBC [ i ] , GLX_SAMPLES , & nSamples ) ;
if ( nBestFBC < 0 | | ( nSampleBuf & & ( nSamples > best_num_samp ) ) )
{
nBestFBC = i ;
best_num_samp = nSamples ;
}
}
XFree ( pVi ) ;
}
return pFBC ;
}
2014-10-29 13:20:52 +01:00
# endif
2014-09-03 14:21:19 +02:00
2014-10-24 17:03:39 +02:00
// we need them before glew can initialize them
// glew needs an OpenGL context so we need to get the address manually
void initOpenGLFunctionPointers ( )
{
glXChooseFBConfig = ( GLXFBConfig * ( * ) ( Display * dpy , int screen , const int * attrib_list , int * nelements ) ) glXGetProcAddressARB ( ( GLubyte * ) " glXChooseFBConfig " ) ;
glXGetVisualFromFBConfig = ( XVisualInfo * ( * ) ( Display * dpy , GLXFBConfig config ) ) glXGetProcAddressARB ( ( GLubyte * ) " glXGetVisualFromFBConfig " ) ; // try to find a visual for the current set of attributes
glXGetFBConfigAttrib = ( int ( * ) ( Display * dpy , GLXFBConfig config , int attribute , int * value ) ) glXGetProcAddressARB ( ( GLubyte * ) " glXGetFBConfigAttrib " ) ;
glXCreateContextAttribsARB = ( GLXContext ( * ) ( Display * , GLXFBConfig , GLXContext , Bool , const int * ) ) glXGetProcAddressARB ( ( const GLubyte * ) " glXCreateContextAttribsARB " ) ; ;
}
2014-10-29 13:20:52 +01:00
Visual * getVisual ( Display * dpy , Window win )
2014-10-24 17:03:39 +02:00
{
initOpenGLFunctionPointers ( ) ;
2014-10-29 13:20:52 +01:00
XWindowAttributes xattr ;
2014-11-17 21:07:27 +00:00
if ( ! XGetWindowAttributes ( dpy , win , & xattr ) )
{
SAL_WARN ( " vcl.opengl " , " Failed to get window attributes for getVisual " < < win ) ;
xattr . visual = NULL ;
}
2014-10-29 13:20:52 +01:00
SAL_INFO ( " vcl.opengl " , " using VisualID " < < xattr . visual ) ;
return xattr . visual ;
2014-10-24 17:03:39 +02:00
}
2014-03-14 18:51:06 +01:00
}
2014-03-17 05:06:00 +01:00
2014-03-14 18:51:06 +01:00
# endif
2014-09-23 11:20:40 +02:00
bool OpenGLContext : : init ( vcl : : Window * pParent )
2014-03-14 18:51:06 +01:00
{
2014-04-02 03:31:01 +02:00
if ( mbInitialized )
return true ;
2014-09-23 11:20:40 +02:00
m_pWindow . reset ( pParent ? NULL : new vcl : : Window ( 0 , WB_NOBORDER | WB_NODIALOGCONTROL ) ) ;
2014-04-02 03:31:38 +02:00
mpWindow = pParent ? pParent : m_pWindow . get ( ) ;
2014-11-07 06:13:05 +01:00
if ( m_pWindow )
m_pWindow - > setPosSizePixel ( 0 , 0 , 0 , 0 ) ;
2014-04-27 12:20:13 +02:00
m_pChildWindow = 0 ;
2014-03-14 18:51:06 +01:00
initWindow ( ) ;
2014-04-27 12:20:13 +02:00
return ImplInit ( ) ;
}
bool OpenGLContext : : init ( SystemChildWindow * pChildWindow )
{
if ( mbInitialized )
return true ;
if ( ! pChildWindow )
return false ;
mpWindow = pChildWindow - > GetParent ( ) ;
m_pChildWindow = pChildWindow ;
initWindow ( ) ;
return ImplInit ( ) ;
}
2014-10-24 17:03:39 +02:00
# if defined( UNX ) && !defined MACOSX && !defined IOS && !defined ANDROID
bool OpenGLContext : : init ( Display * dpy , Window win , int screen )
{
if ( mbInitialized )
return true ;
if ( ! dpy )
return false ;
m_aGLWin . dpy = dpy ;
m_aGLWin . win = win ;
m_aGLWin . screen = screen ;
2014-10-29 13:20:52 +01:00
Visual * pVisual = getVisual ( dpy , win ) ;
2014-10-24 17:03:39 +02:00
initGLWindow ( pVisual ) ;
return ImplInit ( ) ;
}
2014-11-20 09:45:16 +00:00
void OpenGLContext : : resetToReInitialize ( )
{
if ( ! mbInitialized )
return ;
resetCurrent ( ) ;
mbInitialized = false ;
}
2014-11-07 07:32:00 +01:00
bool OpenGLContext : : init ( Display * dpy , Pixmap pix , unsigned int width , unsigned int height , int nScreen )
{
if ( mbInitialized )
return true ;
if ( ! dpy )
return false ;
SAL_INFO ( " vcl.opengl " , " init with pixmap " ) ;
m_aGLWin . dpy = dpy ;
m_aGLWin . Width = width ;
m_aGLWin . Height = height ;
m_aGLWin . pix = pix ;
2014-11-08 18:55:26 +01:00
const int attrib_list [ ] = { GLX_TEXTURE_FORMAT_EXT , GLX_TEXTURE_FORMAT_RGB_EXT ,
GLX_TEXTURE_TARGET_EXT , GLX_TEXTURE_2D_EXT ,
None } ;
2014-11-07 07:32:00 +01:00
int best_fbc = - 1 ;
GLXFBConfig * config = getFBConfigForPixmap ( dpy , best_fbc , mbUseDoubleBufferedRendering , nScreen ) ;
if ( best_fbc = = - 1 )
return false ;
m_aGLWin . vi = glXGetVisualFromFBConfig ( dpy , config [ best_fbc ] ) ;
m_aGLWin . glPix = glXCreatePixmap ( dpy , config [ best_fbc ] , pix , attrib_list ) ;
mbPixmap = true ;
initOpenGLFunctionPointers ( ) ;
return ImplInit ( ) ;
}
2014-04-27 12:20:13 +02:00
bool OpenGLContext : : ImplInit ( )
{
2014-11-10 17:13:55 -05:00
GLXContext pSharedCtx ( NULL ) ;
2014-04-27 12:20:13 +02:00
SAL_INFO ( " vcl.opengl " , " OpenGLContext::ImplInit----start " ) ;
2014-11-10 17:13:55 -05:00
if ( ! vShareList . empty ( ) )
pSharedCtx = vShareList . front ( ) ;
2014-09-08 14:16:39 +02:00
# ifdef DBG_UTIL
2014-11-07 07:32:00 +01:00
if ( ! mbPixmap & & glXCreateContextAttribsARB & & ! mbRequestLegacyContext )
2014-09-03 14:21:19 +02:00
{
2014-09-03 14:25:57 +02:00
int best_fbc = - 1 ;
2014-10-31 19:19:47 +01:00
GLXFBConfig * pFBC = getFBConfig ( m_aGLWin . dpy , m_aGLWin . win , best_fbc , mbUseDoubleBufferedRendering ) ;
2014-09-07 19:33:18 +02:00
if ( ! pFBC )
return false ;
2014-11-05 18:29:40 +01:00
if ( best_fbc ! = - 1 )
2014-09-03 14:25:57 +02:00
{
2014-11-18 11:45:40 +01:00
int pContextAttribs [ ] =
2014-11-05 18:29:40 +01:00
{
GLX_CONTEXT_MAJOR_VERSION_ARB , 3 ,
GLX_CONTEXT_MINOR_VERSION_ARB , 2 ,
None
} ;
2014-11-18 11:45:40 +01:00
m_aGLWin . ctx = glXCreateContextAttribsARB ( m_aGLWin . dpy , pFBC [ best_fbc ] , pSharedCtx , GL_TRUE , pContextAttribs ) ;
2014-11-05 18:29:40 +01:00
SAL_INFO_IF ( m_aGLWin . ctx , " vcl.opengl " , " created a 3.2 core context " ) ;
}
else
SAL_WARN ( " vcl.opengl " , " unable to find correct FBC " ) ;
2014-09-03 14:25:57 +02:00
}
2014-09-03 14:21:19 +02:00
# endif
2014-11-07 07:32:00 +01:00
2014-09-03 14:21:19 +02:00
if ( ! m_aGLWin . ctx )
{
2014-09-07 19:33:18 +02:00
if ( ! m_aGLWin . dpy | | ! m_aGLWin . vi )
return false ;
2014-09-03 14:21:19 +02:00
m_aGLWin . ctx = m_aGLWin . dpy = = 0 ? 0 : glXCreateContext ( m_aGLWin . dpy ,
m_aGLWin . vi ,
2014-11-04 17:32:48 -05:00
pSharedCtx ,
2014-09-03 14:21:19 +02:00
GL_TRUE ) ;
}
2014-11-07 07:32:00 +01:00
2014-11-10 17:13:55 -05:00
if ( m_aGLWin . ctx )
{
vShareList . push_back ( m_aGLWin . ctx ) ;
}
else
2014-03-14 18:51:06 +01:00
{
2014-09-03 14:20:36 +02:00
SAL_WARN ( " vcl.opengl " , " unable to create GLX context " ) ;
2014-03-14 18:51:06 +01:00
return false ;
}
2014-11-07 07:32:00 +01:00
if ( ! glXMakeCurrent ( m_aGLWin . dpy , mbPixmap ? m_aGLWin . glPix : m_aGLWin . win , m_aGLWin . ctx ) )
2014-11-07 06:13:05 +01:00
{
SAL_WARN ( " vcl.opengl " , " unable to select current GLX context " ) ;
return false ;
}
int glxMinor , glxMajor ;
double nGLXVersion = 0 ;
if ( glXQueryVersion ( m_aGLWin . dpy , & glxMajor , & glxMinor ) )
nGLXVersion = glxMajor + 0.1 * glxMinor ;
SAL_INFO ( " vcl.opengl " , " available GLX version: " < < nGLXVersion ) ;
m_aGLWin . GLExtensions = glGetString ( GL_EXTENSIONS ) ;
SAL_INFO ( " vcl.opengl " , " available GL extensions: " < < m_aGLWin . GLExtensions ) ;
XWindowAttributes xWinAttr ;
2014-11-20 09:45:16 +00:00
if ( mbPixmap )
{
m_aGLWin . Width = 0 ; // FIXME: correct ?
m_aGLWin . Height = 0 ;
}
else if ( ! XGetWindowAttributes ( m_aGLWin . dpy , m_aGLWin . win , & xWinAttr ) )
2014-11-17 21:07:27 +00:00
{
SAL_WARN ( " vcl.opengl " , " Failed to get window attributes on " < < m_aGLWin . win ) ;
m_aGLWin . Width = 0 ;
m_aGLWin . Height = 0 ;
}
else
{
m_aGLWin . Width = xWinAttr . width ;
m_aGLWin . Height = xWinAttr . height ;
}
2014-11-07 06:13:05 +01:00
if ( m_aGLWin . HasGLXExtension ( " GLX_SGI_swap_control " ) )
{
// enable vsync
typedef GLint ( * glXSwapIntervalProc ) ( GLint ) ;
glXSwapIntervalProc glXSwapInterval = ( glXSwapIntervalProc ) glXGetProcAddress ( ( const GLubyte * ) " glXSwapIntervalSGI " ) ;
if ( glXSwapInterval )
{
int ( * oldHandler ) ( Display * /*dpy*/ , XErrorEvent * /*evnt*/ ) ;
XLockDisplay ( m_aGLWin . dpy ) ;
XSync ( m_aGLWin . dpy , false ) ;
// replace error handler temporarily
oldHandler = XSetErrorHandler ( oglErrorHandler ) ;
errorTriggered = false ;
glXSwapInterval ( 1 ) ;
// sync so that we possibly get an XError
glXWaitGL ( ) ;
XSync ( m_aGLWin . dpy , false ) ;
if ( errorTriggered )
SAL_WARN ( " vcl.opengl " , " error when trying to set swap interval, NVIDIA or Mesa bug? " ) ;
else
SAL_INFO ( " vcl.opengl " , " set swap interval to 1 (enable vsync) " ) ;
// restore the error handler
XSetErrorHandler ( oldHandler ) ;
XUnlockDisplay ( m_aGLWin . dpy ) ;
}
}
return InitGLEW ( ) ;
}
# elif defined( _WIN32 )
bool OpenGLContext : : init ( HDC hDC , HWND hWnd )
{
if ( mbInitialized )
return false ;
m_aGLWin . hDC = hDC ;
m_aGLWin . hWnd = hWnd ;
return ImplInit ( ) ;
}
bool OpenGLContext : : ImplInit ( )
{
SAL_INFO ( " vcl.opengl " , " OpenGLContext::ImplInit----start " ) ;
2014-11-17 12:29:56 +01:00
// PixelFormat tells Windows how we want things to be
PIXELFORMATDESCRIPTOR PixelFormatFront =
2014-03-14 18:51:06 +01:00
{
sizeof ( PIXELFORMATDESCRIPTOR ) ,
1 , // Version Number
2014-11-04 01:15:30 +01:00
PFD_SUPPORT_OPENGL ,
2014-03-14 18:51:06 +01:00
PFD_TYPE_RGBA , // Request An RGBA Format
( BYTE ) 32 , // Select Our Color Depth
0 , 0 , 0 , 0 , 0 , 0 , // Color Bits Ignored
0 , // No Alpha Buffer
0 , // Shift Bit Ignored
0 , // No Accumulation Buffer
0 , 0 , 0 , 0 , // Accumulation Bits Ignored
64 , // 32 bit Z-BUFFER
0 , // 0 bit stencil buffer
0 , // No Auxiliary Buffer
0 , // now ignored
0 , // Reserved
0 , 0 , 0 // Layer Masks Ignored
} ;
2014-11-13 05:58:01 +01:00
// interestingly we need this flag being set even if we use single buffer
// rendering - otherwise we get errors with virtual devices
PixelFormatFront . dwFlags | = PFD_DOUBLEBUFFER ;
2014-11-04 01:15:30 +01:00
if ( mbRequestVirtualDevice )
PixelFormatFront . dwFlags | = PFD_DRAW_TO_BITMAP ;
else
PixelFormatFront . dwFlags | = PFD_DRAW_TO_WINDOW ;
2014-03-14 18:51:06 +01:00
// we must check whether can set the MSAA
2014-05-06 02:27:08 +02:00
int WindowPix = 0 ;
2014-11-04 01:15:30 +01:00
bool bMultiSampleSupport = InitMultisample ( PixelFormatFront , WindowPix ,
mbUseDoubleBufferedRendering , mbRequestVirtualDevice ) ;
2014-05-06 02:27:08 +02:00
if ( bMultiSampleSupport & & WindowPix ! = 0 )
2014-03-14 18:51:06 +01:00
{
2014-03-17 08:24:14 +01:00
m_aGLWin . bMultiSampleSupported = true ;
2014-03-14 18:51:06 +01:00
}
else
{
2014-05-06 02:27:08 +02:00
WindowPix = ChoosePixelFormat ( m_aGLWin . hDC , & PixelFormatFront ) ;
2014-03-14 18:51:06 +01:00
}
2014-05-05 16:46:59 +02:00
2014-05-06 02:27:08 +02:00
if ( WindowPix = = 0 )
2014-05-05 16:46:59 +02:00
{
2014-05-06 02:27:08 +02:00
SAL_WARN ( " vcl.opengl " , " Invalid pixelformat " ) ;
return false ;
}
2014-11-17 12:29:56 +01:00
if ( ! SetPixelFormat ( m_aGLWin . hDC , WindowPix , & PixelFormatFront ) )
{
ImplWriteLastError ( GetLastError ( ) , " SetPixelFormat in OpenGLContext::ImplInit " ) ;
SAL_WARN ( " vcl.opengl " , " SetPixelFormat failed " ) ;
return false ;
}
2014-11-18 11:45:40 +01:00
HGLRC hTempRC = wglCreateContext ( m_aGLWin . hDC ) ;
2014-05-06 02:27:08 +02:00
if ( m_aGLWin . hRC = = NULL )
{
2014-11-17 12:29:56 +01:00
ImplWriteLastError ( GetLastError ( ) , " wglCreateContext in OpenGLContext::ImplInit " ) ;
2014-05-06 02:27:08 +02:00
SAL_WARN ( " vcl.opengl " , " wglCreateContext failed " ) ;
return false ;
}
2014-11-18 11:45:40 +01:00
if ( ! wglMakeCurrent ( m_aGLWin . hDC , hTempRC ) )
2014-05-06 02:27:08 +02:00
{
2014-11-17 12:29:56 +01:00
ImplWriteLastError ( GetLastError ( ) , " wglMakeCurrent in OpenGLContext::ImplInit " ) ;
SAL_WARN ( " vcl.opengl " , " wglMakeCurrent failed " ) ;
2014-05-05 16:46:59 +02:00
return false ;
}
2014-03-14 18:51:06 +01:00
2014-11-18 11:45:40 +01:00
if ( ! InitGLEW ( ) )
return false ;
HGLRC hSharedCtx = 0 ;
if ( ! vShareList . empty ( ) )
hSharedCtx = vShareList . front ( ) ;
// now setup the shared context; this needs a temporary context already
// set up in order to work
m_aGLWin . hRC = wglCreateContextAttribsARB ( m_aGLWin . hDC , hSharedCtx , NULL ) ;
if ( m_aGLWin . hRC = = 0 )
{
ImplWriteLastError ( GetLastError ( ) , " wglCreateContextAttribsARB in OpenGLContext::ImplInit " ) ;
SAL_WARN ( " vcl.opengl " , " wglCreateContextAttribsARB failed " ) ;
return false ;
}
wglMakeCurrent ( NULL , NULL ) ;
wglDeleteContext ( hTempRC ) ;
if ( ! wglMakeCurrent ( m_aGLWin . hDC , m_aGLWin . hRC ) )
{
ImplWriteLastError ( GetLastError ( ) , " wglMakeCurrent (with shared context) in OpenGLContext::ImplInit " ) ;
SAL_WARN ( " vcl.opengl " , " wglMakeCurrent failed " ) ;
return false ;
}
vShareList . push_back ( m_aGLWin . hRC ) ;
2014-11-09 08:43:44 +01:00
RECT clientRect ;
GetClientRect ( WindowFromDC ( m_aGLWin . hDC ) , & clientRect ) ;
2014-11-07 17:56:35 +01:00
m_aGLWin . Width = clientRect . right - clientRect . left ;
m_aGLWin . Height = clientRect . bottom - clientRect . top ;
2014-11-18 11:45:40 +01:00
return true ;
2014-11-07 06:13:05 +01:00
}
2014-03-14 18:51:06 +01:00
# elif defined( MACOSX )
2014-11-07 06:13:05 +01:00
bool OpenGLContext : : ImplInit ( )
{
SAL_INFO ( " vcl.opengl " , " OpenGLContext::ImplInit----start " ) ;
2014-09-01 01:59:57 +02:00
NSOpenGLView * pView = getOpenGLView ( ) ;
OpenGLWrapper : : makeCurrent ( pView ) ;
2014-07-16 08:02:32 +02:00
2014-11-07 06:13:05 +01:00
return InitGLEW ( ) ;
}
2014-03-14 18:51:06 +01:00
2014-11-07 06:13:05 +01:00
# else
2014-03-14 18:51:06 +01:00
2014-11-07 06:13:05 +01:00
bool OpenGLContext : : ImplInit ( )
{
SAL_INFO ( " vcl.opengl " , " OpenGLContext not implemented for this platform " ) ;
return false ;
}
2014-03-14 18:51:06 +01:00
# endif
2014-11-07 06:13:05 +01:00
bool OpenGLContext : : InitGLEW ( )
{
2014-04-08 00:34:29 +02:00
static bool bGlewInit = false ;
if ( ! bGlewInit )
{
glewExperimental = GL_TRUE ;
2014-05-05 16:46:59 +02:00
GLenum err = glewInit ( ) ;
if ( err ! = GLEW_OK )
2014-04-08 00:34:29 +02:00
{
2014-05-05 16:46:59 +02:00
SAL_WARN ( " vcl.opengl " , " Failed to initialize GLEW: " < < glewGetErrorString ( err ) ) ;
2014-04-08 00:34:29 +02:00
return false ;
}
else
bGlewInit = true ;
}
2014-05-09 05:23:12 +02:00
# ifdef DBG_UTIL
// only enable debug output in dbgutil build
2014-05-12 17:49:00 +02:00
// somehow there are implementations where the feature is present and the function
// pointer is still NULL
2014-11-15 10:16:02 +01:00
if ( GLEW_ARB_debug_output )
2014-05-09 05:23:12 +02:00
{
2014-11-15 10:16:02 +01:00
if ( glDebugMessageCallbackARB )
{
2014-11-16 12:33:55 +01:00
glEnable ( GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB ) ;
2014-11-15 10:16:02 +01:00
glDebugMessageCallbackARB ( & debug_callback , NULL ) ;
}
else if ( glDebugMessageCallback )
{
glEnable ( GL_DEBUG_OUTPUT ) ;
glDebugMessageCallback ( & debug_callback , NULL ) ;
}
2014-05-09 05:23:12 +02:00
}
# endif
2014-04-27 12:20:13 +02:00
SAL_INFO ( " vcl.opengl " , " OpenGLContext::ImplInit----end " ) ;
2014-04-02 03:31:01 +02:00
mbInitialized = true ;
2014-03-14 18:51:06 +01:00
return true ;
}
2014-05-19 19:21:29 +02:00
void OpenGLContext : : setWinPosAndSize ( const Point & rPos , const Size & rSize )
{
if ( m_pWindow )
m_pWindow - > SetPosSizePixel ( rPos , rSize ) ;
if ( m_pChildWindow )
m_pChildWindow - > SetPosSizePixel ( rPos , rSize ) ;
m_aGLWin . Width = rSize . Width ( ) ;
m_aGLWin . Height = rSize . Height ( ) ;
}
2014-03-14 18:51:06 +01:00
void OpenGLContext : : setWinSize ( const Size & rSize )
{
2014-04-02 03:31:38 +02:00
if ( m_pWindow )
m_pWindow - > SetSizePixel ( rSize ) ;
2014-04-27 12:20:13 +02:00
if ( m_pChildWindow )
m_pChildWindow - > SetSizePixel ( rSize ) ;
2014-04-08 02:16:08 +02:00
m_aGLWin . Width = rSize . Width ( ) ;
m_aGLWin . Height = rSize . Height ( ) ;
2014-03-14 18:51:06 +01:00
}
2014-04-08 02:16:08 +02:00
void OpenGLContext : : renderToFile ( )
{
int iWidth = m_aGLWin . Width ;
int iHeight = m_aGLWin . Height ;
static int nIdx = 0 ;
2014-05-06 06:35:32 +02:00
OUString aName = OUString ( " file:///home/moggi/Documents/work/output " ) + OUString : : number ( nIdx + + ) + " .png " ;
2014-05-09 00:31:05 +02:00
OpenGLHelper : : renderToFile ( iWidth , iHeight , aName ) ;
2014-04-08 02:16:08 +02:00
}
2014-03-14 18:51:06 +01:00
# if defined( WNT )
bool OpenGLContext : : initWindow ( )
{
2014-04-27 12:20:13 +02:00
if ( ! m_pChildWindow )
{
2014-09-01 23:59:24 +02:00
SystemWindowData winData = generateWinData ( mpWindow , false ) ;
2014-05-06 03:41:01 +02:00
m_pChildWindow = new SystemChildWindow ( mpWindow , 0 , & winData , false ) ;
2014-04-27 12:20:13 +02:00
m_pChildWindowGC . reset ( m_pChildWindow ) ;
}
2014-03-14 18:51:06 +01:00
if ( m_pChildWindow )
{
2014-05-06 03:41:01 +02:00
m_pChildWindow - > SetMouseTransparent ( true ) ;
2014-05-19 22:04:25 +02:00
m_pChildWindow - > SetParentClipMode ( PARENTCLIPMODE_CLIP ) ;
2014-05-06 03:41:01 +02:00
m_pChildWindow - > EnableEraseBackground ( false ) ;
2014-03-14 18:51:06 +01:00
m_pChildWindow - > SetControlForeground ( ) ;
m_pChildWindow - > SetControlBackground ( ) ;
2014-05-19 15:36:06 +02:00
//m_pChildWindow->EnablePaint(false);
2014-05-06 02:22:57 +02:00
const SystemEnvData * sysData ( m_pChildWindow - > GetSystemData ( ) ) ;
2014-03-14 18:51:06 +01:00
m_aGLWin . hWnd = sysData - > hWnd ;
}
2014-11-02 04:12:59 +01:00
m_aGLWin . hDC = GetDC ( m_aGLWin . hWnd ) ;
2014-03-14 18:51:06 +01:00
return true ;
}
2014-07-16 08:02:32 +02:00
# elif defined( MACOSX )
bool OpenGLContext : : initWindow ( )
{
if ( ! m_pChildWindow )
{
2014-09-01 23:59:24 +02:00
SystemWindowData winData = generateWinData ( mpWindow , mbRequestLegacyContext ) ;
2014-07-16 08:02:32 +02:00
m_pChildWindow = new SystemChildWindow ( mpWindow , 0 , & winData , false ) ;
m_pChildWindowGC . reset ( m_pChildWindow ) ;
}
if ( m_pChildWindow )
{
m_pChildWindow - > SetMouseTransparent ( true ) ;
m_pChildWindow - > SetParentClipMode ( PARENTCLIPMODE_CLIP ) ;
m_pChildWindow - > EnableEraseBackground ( false ) ;
m_pChildWindow - > SetControlForeground ( ) ;
m_pChildWindow - > SetControlBackground ( ) ;
//m_pChildWindow->EnablePaint(false);
}
return true ;
}
# elif defined( IOS ) || defined( ANDROID )
2014-03-14 18:51:06 +01:00
bool OpenGLContext : : initWindow ( )
{
return false ;
}
# elif defined( UNX )
bool OpenGLContext : : initWindow ( )
{
2014-04-25 14:41:24 +02:00
const SystemEnvData * pChildSysData = 0 ;
2014-09-01 23:59:24 +02:00
SystemWindowData winData = generateWinData ( mpWindow , false ) ;
2014-04-25 14:41:24 +02:00
if ( winData . pVisual )
2014-03-14 18:51:06 +01:00
{
2014-04-27 12:20:13 +02:00
if ( ! m_pChildWindow )
{
2014-04-27 18:57:50 +03:00
m_pChildWindow = new SystemChildWindow ( mpWindow , 0 , & winData , false ) ;
2014-04-27 12:20:13 +02:00
m_pChildWindowGC . reset ( m_pChildWindow ) ;
}
2014-03-14 18:51:06 +01:00
pChildSysData = m_pChildWindow - > GetSystemData ( ) ;
}
if ( ! m_pChildWindow | | ! pChildSysData )
return false ;
m_pChildWindow - > SetMouseTransparent ( true ) ;
m_pChildWindow - > SetParentClipMode ( PARENTCLIPMODE_NOCLIP ) ;
m_pChildWindow - > EnableEraseBackground ( false ) ;
m_pChildWindow - > SetControlForeground ( ) ;
m_pChildWindow - > SetControlBackground ( ) ;
m_aGLWin . dpy = reinterpret_cast < Display * > ( pChildSysData - > pDisplay ) ;
m_aGLWin . win = pChildSysData - > aWindow ;
2014-04-25 14:41:24 +02:00
m_aGLWin . screen = pChildSysData - > nScreen ;
2014-10-24 16:50:05 +02:00
Visual * pVisual = ( Visual * ) pChildSysData - > pVisual ;
initGLWindow ( pVisual ) ;
return true ;
}
void OpenGLContext : : initGLWindow ( Visual * pVisual )
{
2014-04-25 14:41:24 +02:00
// Get visual info
{
XVisualInfo aTemplate ;
2014-05-26 19:41:16 +02:00
aTemplate . visualid = XVisualIDFromVisual ( pVisual ) ;
2014-04-25 14:41:24 +02:00
int nVisuals = 0 ;
XVisualInfo * pInfos = XGetVisualInfo ( m_aGLWin . dpy , VisualIDMask , & aTemplate , & nVisuals ) ;
if ( nVisuals ! = 1 )
SAL_WARN ( " vcl.opengl " , " match count for visual id is not 1 " ) ;
m_aGLWin . vi = pInfos ;
}
// Check multi sample support
2014-10-29 13:20:52 +01:00
/* TODO: moggi: This is not necessarily correct in the DBG_UTIL path, as it picks
* an FBConfig instead . . . */
2014-04-25 14:41:24 +02:00
int nSamples = 0 ;
glXGetConfig ( m_aGLWin . dpy , m_aGLWin . vi , GLX_SAMPLES , & nSamples ) ;
if ( nSamples > 0 )
m_aGLWin . bMultiSampleSupported = true ;
2014-03-14 18:51:06 +01:00
m_aGLWin . GLXExtensions = glXQueryExtensionsString ( m_aGLWin . dpy , m_aGLWin . screen ) ;
2014-04-02 03:31:38 +02:00
SAL_INFO ( " vcl.opengl " , " available GLX extensions: " < < m_aGLWin . GLXExtensions ) ;
2014-03-14 18:51:06 +01:00
}
# endif
2014-04-27 12:47:52 +02:00
# if defined( WNT ) || defined( MACOSX ) || defined( IOS ) || defined( ANDROID )
2014-04-27 12:09:20 +02:00
2014-09-23 11:20:40 +02:00
SystemWindowData OpenGLContext : : generateWinData ( vcl : : Window * /*pParent*/ , bool bRequestLegacyContext )
2014-04-27 12:09:20 +02:00
{
2014-09-01 23:59:24 +02:00
( void ) bRequestLegacyContext ;
2014-04-27 12:09:20 +02:00
SystemWindowData aWinData ;
2014-09-01 01:18:09 +02:00
# if defined(MACOSX)
aWinData . bOpenGL = true ;
2014-09-01 23:59:24 +02:00
aWinData . bLegacy = bRequestLegacyContext ;
2014-09-01 01:18:09 +02:00
# endif
2014-04-27 12:09:20 +02:00
aWinData . nSize = sizeof ( aWinData ) ;
return aWinData ;
}
# elif defined( UNX )
2014-09-23 11:20:40 +02:00
SystemWindowData OpenGLContext : : generateWinData ( vcl : : Window * pParent , bool )
2014-04-27 12:09:20 +02:00
{
SystemWindowData aWinData ;
aWinData . nSize = sizeof ( aWinData ) ;
2014-04-29 17:10:27 +01:00
aWinData . pVisual = NULL ;
2014-04-27 12:09:20 +02:00
const SystemEnvData * sysData ( pParent - > GetSystemData ( ) ) ;
Display * dpy = reinterpret_cast < Display * > ( sysData - > pDisplay ) ;
2014-10-24 16:35:32 +02:00
Window win = sysData - > aWindow ;
2014-04-27 12:09:20 +02:00
2014-05-20 09:41:59 +02:00
if ( dpy = = 0 | | ! glXQueryExtension ( dpy , NULL , NULL ) )
2014-04-27 12:09:20 +02:00
return aWinData ;
2014-10-29 13:20:52 +01:00
aWinData . pVisual = getVisual ( dpy , win ) ;
2014-04-27 12:09:20 +02:00
return aWinData ;
}
# endif
2014-04-28 09:57:29 +02:00
void OpenGLContext : : makeCurrent ( )
{
# if defined( WNT )
2014-11-18 16:10:51 +00:00
if ( wglGetCurrentContext ( ) = = m_aGLWin . hRC & &
wglGetCurrentDC ( ) = = m_aGLWin . hDC )
2014-11-17 21:51:50 +00:00
{
SAL_INFO ( " vcl.opengl " , " OpenGLContext::makeCurrent(): Avoid setting the same context " ) ;
}
else if ( ! wglMakeCurrent ( m_aGLWin . hDC , m_aGLWin . hRC ) )
2014-05-06 02:27:08 +02:00
{
SAL_WARN ( " vcl.opengl " , " OpenGLContext::makeCurrent(): wglMakeCurrent failed: " < < GetLastError ( ) ) ;
}
2014-07-16 08:02:32 +02:00
# elif defined( MACOSX )
2014-09-01 01:59:57 +02:00
NSOpenGLView * pView = getOpenGLView ( ) ;
OpenGLWrapper : : makeCurrent ( pView ) ;
2014-07-16 08:02:32 +02:00
# elif defined( IOS ) || defined( ANDROID )
2014-04-28 09:57:29 +02:00
// nothing
# elif defined( UNX )
2014-11-18 16:10:51 +00:00
GLXDrawable nDrawable = mbPixmap ? m_aGLWin . glPix : m_aGLWin . win ;
if ( glXGetCurrentContext ( ) = = m_aGLWin . ctx & &
glXGetCurrentDrawable ( ) = = nDrawable )
2014-11-17 21:51:50 +00:00
{
SAL_INFO ( " vcl.opengl " , " OpenGLContext::makeCurrent(): Avoid setting the same context " ) ;
}
2014-11-18 16:10:51 +00:00
else if ( ! glXMakeCurrent ( m_aGLWin . dpy , nDrawable , m_aGLWin . ctx ) )
2014-11-20 09:45:16 +00:00
SAL_WARN ( " vcl.opengl " , " OpenGLContext::makeCurrent failed on drawable " < < nDrawable < < " pixmap? " < < mbPixmap ) ;
2014-04-28 09:57:29 +02:00
# endif
}
2014-07-13 07:52:51 +02:00
void OpenGLContext : : resetCurrent ( )
{
# if defined( WNT )
wglMakeCurrent ( m_aGLWin . hDC , 0 ) ;
2014-07-16 08:02:32 +02:00
# elif defined( MACOSX )
2014-09-01 01:59:57 +02:00
OpenGLWrapper : : resetCurrent ( ) ;
2014-07-16 08:02:32 +02:00
# elif defined( IOS ) || defined( ANDROID )
2014-07-13 07:52:51 +02:00
// nothing
# elif defined( UNX )
glXMakeCurrent ( m_aGLWin . dpy , None , NULL ) ;
# endif
}
2014-04-27 12:20:13 +02:00
void OpenGLContext : : swapBuffers ( )
{
2014-04-27 12:47:52 +02:00
# if defined( WNT )
2014-04-27 12:20:13 +02:00
SwapBuffers ( m_aGLWin . hDC ) ;
2014-07-16 08:02:32 +02:00
# elif defined( MACOSX )
2014-09-01 01:59:57 +02:00
NSOpenGLView * pView = getOpenGLView ( ) ;
OpenGLWrapper : : swapBuffers ( pView ) ;
2014-07-16 08:02:32 +02:00
# elif defined( IOS ) || defined( ANDROID )
2014-04-27 12:47:52 +02:00
// nothing
2014-04-27 12:20:13 +02:00
# elif defined( UNX )
2014-11-07 07:32:00 +01:00
glXSwapBuffers ( m_aGLWin . dpy , mbPixmap ? m_aGLWin . glPix : m_aGLWin . win ) ;
2014-04-27 12:20:13 +02:00
# endif
}
2014-05-19 19:21:29 +02:00
void OpenGLContext : : sync ( )
{
# if defined( WNT )
// nothing
# elif defined( MACOSX ) || defined( IOS ) || defined( ANDROID )
// nothing
# elif defined( UNX )
glXWaitGL ( ) ;
XSync ( m_aGLWin . dpy , false ) ;
# endif
}
void OpenGLContext : : show ( )
{
if ( m_pChildWindow )
m_pChildWindow - > Show ( ) ;
else if ( m_pWindow )
m_pWindow - > Show ( ) ;
}
2014-08-08 01:55:33 +02:00
SystemChildWindow * OpenGLContext : : getChildWindow ( )
{
return m_pChildWindow ;
}
const SystemChildWindow * OpenGLContext : : getChildWindow ( ) const
{
return m_pChildWindow ;
}
2014-08-29 11:55:23 +02:00
bool OpenGLContext : : supportMultiSampling ( ) const
{
return m_aGLWin . bMultiSampleSupported ;
}
2014-09-01 01:59:57 +02:00
# if defined(MACOSX)
NSOpenGLView * OpenGLContext : : getOpenGLView ( )
{
return reinterpret_cast < NSOpenGLView * > ( m_pChildWindow - > GetSystemData ( ) - > mpNSView ) ;
}
# endif
2014-08-29 11:55:23 +02:00
2014-03-14 18:51:06 +01:00
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */