summaryrefslogtreecommitdiff
path: root/vcl
diff options
context:
space:
mode:
authorZolnai Tamás <tamas.zolnai@collabora.com>2014-03-14 18:51:06 +0100
committerZolnai Tamás <tamas.zolnai@collabora.com>2014-03-14 19:59:22 +0100
commita5d178b424d55f61bb3502bb9cbc7ea96aee2cd7 (patch)
treeaafe2e279b5d467c4c514af40c32b0122e253f95 /vcl
parent04b70c682e2cdc52b144961a83d05fd203de6884 (diff)
Introduce OpenGLContext in vclopengl
Move DummyChart::initOpengl() and DummyChart::initWindow into this class. Change-Id: If3c1bb52cb2819019f0dda626612a164709b17ac
Diffstat (limited to 'vcl')
-rw-r--r--vcl/Library_vclopengl.mk5
-rw-r--r--vcl/source/opengl/OpenGLContext.cxx417
2 files changed, 420 insertions, 2 deletions
diff --git a/vcl/Library_vclopengl.mk b/vcl/Library_vclopengl.mk
index 5c52add5f3aa..f65f89586e44 100644
--- a/vcl/Library_vclopengl.mk
+++ b/vcl/Library_vclopengl.mk
@@ -35,13 +35,14 @@ $(eval $(call gb_Library_use_libraries,vclopengl,\
$(eval $(call gb_Library_add_exception_objects,vclopengl,\
vcl/source/opengl/OpenGLRender \
+ vcl/source/opengl/OpenGLContext \
))
ifeq ($(strip $(OS)),WNT)
$(eval $(call gb_Library_use_system_win32_libs,vclopengl,\
opengl32 \
- gdi32 \
- glu32 \
+ gdi32 \
+ glu32 \
))
else ifeq ($(OS),MACOSX)
$(eval $(call gb_Library_use_system_darwin_frameworks,vclopengl,\
diff --git a/vcl/source/opengl/OpenGLContext.cxx b/vcl/source/opengl/OpenGLContext.cxx
new file mode 100644
index 000000000000..70ec988fc0d8
--- /dev/null
+++ b/vcl/source/opengl/OpenGLContext.cxx
@@ -0,0 +1,417 @@
+/* -*- 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/.
+ */
+
+#include <vcl/OpenGLContext.hxx>
+
+
+using namespace com::sun::star;
+
+namespace {
+
+#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";
+ default:
+ ;
+ }
+
+ return "unkown";
+}
+
+extern "C" void
+#if defined _WIN32
+APIENTRY
+#endif
+debug_callback(GLenum source, GLenum type, GLuint id,
+ GLenum severity, GLsizei , const GLchar* message, GLvoid* )
+{
+ SAL_WARN("vcl.opengl", "OpenGL debug message: source: " << getSourceString(source) << ", type: "
+ << getTypeString(type) << ", id: " << id << ", severity: " << getSeverityString(severity) << " with message: " << message);
+}
+
+}
+
+#endif
+
+#if defined( UNX )
+static bool errorTriggered;
+int oglErrorHandler( Display* /*dpy*/, XErrorEvent* /*evnt*/ )
+{
+ errorTriggered = true;
+
+ return 0;
+}
+
+}
+#endif
+
+bool OpenGLContext::init(OpenGLRender& rGLRender)
+{
+ m_pWindow.reset(new Window(0, WB_NOBORDER|WB_NODIALOGCONTROL));
+ SAL_INFO("vcl.opengl", "OpenGLContext::OpenGLContext----start");
+ initWindow();
+ m_pWindow->setPosSizePixel(0,0,0,0);
+ m_aGLWin.Width = 0;
+ m_aGLWin.Height = 0;
+
+#if defined( WNT )
+ m_aGLWin.hDC = GetDC(m_aGLWin.hWnd);
+#elif defined( MACOSX )
+
+#elif defined( UNX )
+ m_aGLWin.ctx = glXCreateContext(m_aGLWin.dpy,
+ m_aGLWin.vi,
+ 0,
+ GL_TRUE);
+ if( m_aGLWin.ctx == NULL )
+ {
+ OSL_TRACE("unable to create GLX context");
+ return false;
+ }
+#endif
+
+#if defined( WNT )
+ PIXELFORMATDESCRIPTOR PixelFormatFront = // PixelFormat Tells Windows How We Want Things To Be
+ {
+ sizeof(PIXELFORMATDESCRIPTOR),
+ 1, // Version Number
+ PFD_DRAW_TO_WINDOW |
+ PFD_SUPPORT_OPENGL |
+ PFD_DOUBLEBUFFER,
+ 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
+ };
+
+ // we must check whether can set the MSAA
+ int WindowPix;
+ rGLRender.InitMultisample(PixelFormatFront);
+ if (rGLRender.GetMSAASupport())
+ {
+ WindowPix = rGLRender.GetMSAAFormat();
+ }
+ else
+ {
+ WindowPix = ChoosePixelFormat(m_aGLWin.hDC,&PixelFormatFront);
+ }
+ SetPixelFormat(m_aGLWin.hDC,WindowPix,&PixelFormatFront);
+ m_aGLWin.hRC = wglCreateContext(m_aGLWin.hDC);
+ wglMakeCurrent(m_aGLWin.hDC,m_aGLWin.hRC);
+
+#elif defined( MACOSX )
+
+#elif defined( UNX )
+ if( !glXMakeCurrent( m_aGLWin.dpy, m_aGLWin.win, m_aGLWin.ctx ) )
+ {
+ OSL_TRACE("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;
+ OSL_TRACE("available GLX version: %f", nGLXVersion);
+
+ m_aGLWin.GLExtensions = glGetString( GL_EXTENSIONS );
+ OSL_TRACE("available GL extensions: %s", m_aGLWin.GLExtensions);
+
+ 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*/);
+
+ // 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 )
+ OSL_TRACE("error when trying to set swap interval, NVIDIA or Mesa bug?");
+ else
+ OSL_TRACE("set swap interval to 1 (enable vsync)");
+
+ // restore the error handler
+ XSetErrorHandler( oldHandler );
+ }
+ }
+
+#endif
+
+ rGLRender.InitOpenGL(m_aGLWin);
+
+#ifdef DBG_UTIL
+ // only enable debug output in dbgutil build
+ if( GLEW_ARB_debug_output )
+ {
+ glEnable(GL_DEBUG_OUTPUT);
+ glDebugMessageCallback(&debug_callback, NULL);
+ }
+
+#endif
+
+ glEnable(GL_TEXTURE_2D);
+ glEnable(GL_CULL_FACE);
+ glCullFace(GL_BACK);
+ // Enable depth test
+ glEnable(GL_DEPTH_TEST);
+ // Accept fragment if it closer to the camera than the former one
+ glDepthFunc(GL_LESS);
+
+#if defined( WNT )
+ SwapBuffers(m_aGLWin.hDC);
+ glFlush();
+#elif defined( MACOSX )
+
+#elif defined( UNX )
+ glXSwapBuffers(m_aGLWin.dpy, m_aGLWin.win);
+#endif
+ glEnable(GL_LIGHTING);
+ GLfloat light_direction[] = { 0.0 , 0.0 , 1.0 };
+ GLfloat materialDiffuse[] = { 1.0 , 1.0 , 1.0 , 1.0};
+ glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, light_direction);
+ glMaterialfv(GL_FRONT,GL_DIFFUSE,materialDiffuse);
+ glEnable(GL_LIGHT0);
+ glEnable(GL_NORMALIZE);
+ SAL_INFO("vcl.opengl", "OpenGLContext::init----end");
+ return true;
+}
+
+void OpenGLContext::setWinSize(const Size& rSize)
+{
+ m_pWindow->SetSizePixel(rSize);
+ m_pChildWindow->SetSizePixel(rSize);
+}
+
+#if defined( WNT )
+
+bool OpenGLContext::initWindow()
+{
+ const SystemEnvData* sysData(m_pWindow->GetSystemData());
+ m_aGLWin.hWnd = sysData->hWnd;
+ SystemWindowData winData;
+ winData.nSize = sizeof(winData);
+ m_pChildWindow.reset(new SystemChildWindow(m_pWindow.get(), 0, &winData, sal_False));
+
+
+ if( m_pChildWindow )
+ {
+ m_pChildWindow->SetMouseTransparent( sal_True );
+ m_pChildWindow->SetParentClipMode( PARENTCLIPMODE_NOCLIP );
+ m_pChildWindow->EnableEraseBackground( sal_False );
+ m_pChildWindow->SetControlForeground();
+ m_pChildWindow->SetControlBackground();
+ m_pChildWindow->EnablePaint(sal_False);
+ m_aGLWin.hWnd = sysData->hWnd;
+ }
+
+ return true;
+}
+
+#elif defined( MACOSX )
+
+bool OpenGLContext::initWindow()
+{
+ return false;
+}
+
+#elif defined( UNX )
+
+namespace {
+
+// 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");
+
+}
+
+}
+
+bool OpenGLContext::initWindow()
+{
+ const SystemEnvData* sysData(m_pWindow->GetSystemData());
+
+ m_aGLWin.dpy = reinterpret_cast<Display*>(sysData->pDisplay);
+
+ if( !glXQueryExtension( m_aGLWin.dpy, NULL, NULL ) )
+ return false;
+
+ m_aGLWin.win = sysData->aWindow;
+
+ OSL_TRACE("parent window: %d", m_aGLWin.win);
+
+ XWindowAttributes xattr;
+ XGetWindowAttributes( m_aGLWin.dpy, m_aGLWin.win, &xattr );
+
+ m_aGLWin.screen = XScreenNumberOfScreen( xattr.screen );
+
+ static int visual_attribs[] =
+ {
+ 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
+ };
+
+ const SystemEnvData* pChildSysData = NULL;
+ m_pChildWindow.reset();
+
+ initOpenGLFunctionPointers();
+
+ int fbCount = 0;
+ GLXFBConfig* pFBC = glXChooseFBConfig( m_aGLWin.dpy,
+ m_aGLWin.screen,
+ visual_attribs, &fbCount );
+
+ if(!pFBC)
+ {
+ SAL_WARN("vcl.opengl", "no suitable fb format found");
+ return false;
+ }
+
+ int best_fbc = -1, best_num_samp = -1;
+ for(int i = 0; i < fbCount; ++i)
+ {
+ XVisualInfo* pVi = glXGetVisualFromFBConfig( m_aGLWin.dpy, pFBC[i] );
+ if(pVi)
+ {
+ // pick the one with the most samples per pixel
+ int nSampleBuf = 0;
+ int nSamples = 0;
+ glXGetFBConfigAttrib( m_aGLWin.dpy, pFBC[i], GLX_SAMPLE_BUFFERS, &nSampleBuf );
+ glXGetFBConfigAttrib( m_aGLWin.dpy, pFBC[i], GLX_SAMPLES , &nSamples );
+
+ if ( best_fbc < 0 || (nSampleBuf && ( nSamples > best_num_samp )) )
+ {
+ best_fbc = i;
+ best_num_samp = nSamples;
+ }
+ }
+ XFree( pVi );
+ }
+
+ XVisualInfo* vi = glXGetVisualFromFBConfig( m_aGLWin.dpy, pFBC[best_fbc] );
+ if( vi )
+ {
+ SystemWindowData winData;
+ winData.nSize = sizeof(winData);
+ OSL_TRACE("using VisualID %08X", vi->visualid);
+ winData.pVisual = (void*)(vi->visual);
+ m_pChildWindow.reset(new SystemChildWindow(m_pWindow.get(), 0, &winData, false));
+ 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;
+ m_aGLWin.vi = vi;
+ m_aGLWin.GLXExtensions = glXQueryExtensionsString( m_aGLWin.dpy, m_aGLWin.screen );
+ OSL_TRACE("available GLX extensions: %s", m_aGLWin.GLXExtensions);
+
+ return true;
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */