summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--avmedia/source/viewer/mediawindow_impl.cxx2
-rw-r--r--include/vcl/opengl/OpenGLContext.hxx50
-rw-r--r--slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionerImpl.cxx28
-rw-r--r--slideshow/source/engine/shapes/viewmediashape.cxx2
-rw-r--r--vcl/headless/svpinst.cxx11
-rw-r--r--vcl/inc/headless/svpinst.hxx2
-rw-r--r--vcl/inc/opengl/zone.hxx6
-rw-r--r--vcl/inc/osx/salinst.h1
-rw-r--r--vcl/inc/salinst.hxx3
-rw-r--r--vcl/inc/unx/salinst.h1
-rw-r--r--vcl/inc/win/salinst.h1
-rw-r--r--vcl/opengl/win/gdiimpl.cxx479
-rw-r--r--vcl/opengl/x11/gdiimpl.cxx556
-rw-r--r--vcl/osx/salobj.cxx109
-rw-r--r--vcl/source/opengl/OpenGLContext.cxx1074
-rw-r--r--vcl/source/window/openglwin.cxx2
16 files changed, 1230 insertions, 1097 deletions
diff --git a/avmedia/source/viewer/mediawindow_impl.cxx b/avmedia/source/viewer/mediawindow_impl.cxx
index 87080ba0d6e6..1bd55af8659b 100644
--- a/avmedia/source/viewer/mediawindow_impl.cxx
+++ b/avmedia/source/viewer/mediawindow_impl.cxx
@@ -489,7 +489,7 @@ void MediaWindowImpl::onURLChanged()
#if HAVE_FEATURE_GLTF
else if (m_sMimeType == AVMEDIA_MIMETYPE_JSON)
{
- SystemWindowData aWinData = OpenGLContext::generateWinData(this, false);
+ SystemWindowData aWinData = OpenGLContext::Create()->generateWinData(this, false);
mpChildWindow.disposeAndClear();
mpChildWindow.reset(VclPtr<MediaChildWindow>::Create(this,&aWinData));
mbEventTransparent = false;
diff --git a/include/vcl/opengl/OpenGLContext.hxx b/include/vcl/opengl/OpenGLContext.hxx
index 1ca86c7acb61..00368495a332 100644
--- a/include/vcl/opengl/OpenGLContext.hxx
+++ b/include/vcl/opengl/OpenGLContext.hxx
@@ -65,7 +65,7 @@ class OpenGLTests;
class RenderState;
/// Holds the information of our new child window
-struct GLWindow
+struct VCL_DLLPUBLIC GLWindow
{
#if defined( _WIN32 )
HWND hWnd;
@@ -121,16 +121,19 @@ struct GLWindow
{
}
+ bool Synchronize(bool bOnoff) const;
+
~GLWindow();
};
class VCL_DLLPUBLIC OpenGLContext
{
friend class OpenGLTests;
+protected:
OpenGLContext();
public:
static rtl::Reference<OpenGLContext> Create();
- ~OpenGLContext();
+ virtual ~OpenGLContext();
void acquire() { mnRefCount++; }
void release() { if ( --mnRefCount == 0 ) delete this; }
void dispose();
@@ -141,13 +144,6 @@ public:
bool init(vcl::Window* pParent = nullptr);
bool init(SystemChildWindow* pChildWindow);
-// these methods are for the deep platform layer, don't use them in normal code
-// only in vcl's platform code
-#if defined( UNX ) && !defined MACOSX && !defined IOS && !defined ANDROID && !defined(LIBO_HEADLESS)
- bool init(Display* dpy, Window win, int screen);
-#elif defined( _WIN32 )
- bool init( HDC hDC, HWND hWnd );
-#endif
void reset();
// use these methods right after setting a context to make sure drawing happens
@@ -173,7 +169,9 @@ public:
}
/// Is this GL context the current context ?
- bool isCurrent();
+ virtual bool isCurrent();
+ /// Is any GL context the current context ?
+ virtual bool isAnyCurrent();
/// release bound resources from the current context
static void clearCurrent();
/// release contexts etc. before (potentially) allowing another thread run.
@@ -186,13 +184,13 @@ public:
/// fetch any VCL context, creating one if bMakeIfNecessary is set.
static rtl::Reference<OpenGLContext> getVCLContext(bool bMakeIfNecessary = true);
/// make this GL context current - so it is implicit in subsequent GL calls
- void makeCurrent();
+ virtual void makeCurrent();
/// Put this GL context to the end of the context list.
void registerAsCurrent();
/// reset the GL context so this context is not implicit in subsequent GL calls.
- void resetCurrent();
- void swapBuffers();
- void sync();
+ virtual void resetCurrent();
+ virtual void swapBuffers();
+ virtual void sync();
void show();
void setWinPosAndSize(const Point &rPos, const Size& rSize);
@@ -213,23 +211,20 @@ public:
bool supportMultiSampling() const;
- static SystemWindowData generateWinData(vcl::Window* pParent, bool bRequestLegacyContext);
+ virtual SystemWindowData generateWinData(vcl::Window* pParent, bool bRequestLegacyContext);
private:
- SAL_DLLPRIVATE bool InitGLEW();
- SAL_DLLPRIVATE void InitGLEWDebugging();
- SAL_DLLPRIVATE bool initWindow();
- SAL_DLLPRIVATE bool ImplInit();
- SAL_DLLPRIVATE void InitChildWindow(SystemChildWindow *pChildWindow);
-#if defined( UNX ) && !defined MACOSX && !defined IOS && !defined ANDROID && !defined(LIBO_HEADLESS)
- SAL_DLLPRIVATE void initGLWindow(Visual* pVisual);
-#endif
-
-#if defined(MACOSX)
- NSOpenGLView* getOpenGLView();
-#endif
+ virtual bool initWindow();
+ virtual void destroyCurrentContext();
+protected:
GLWindow m_aGLWin;
+ bool InitGLEW();
+ void InitGLEWDebugging();
+ void InitChildWindow(SystemChildWindow *pChildWindow);
+ void BuffersSwapped();
+ virtual bool ImplInit();
+
VclPtr<vcl::Window> m_xWindow;
VclPtr<vcl::Window> mpWindow; //points to m_pWindow or the parent window, don't delete it
VclPtr<SystemChildWindow> m_pChildWindow;
@@ -244,6 +239,7 @@ private:
OpenGLFramebuffer* mpFirstFramebuffer;
OpenGLFramebuffer* mpLastFramebuffer;
+private:
struct ProgramHash
{
size_t operator()( const rtl::OString& aDigest ) const
diff --git a/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionerImpl.cxx b/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionerImpl.cxx
index 5ba940fa1c90..fa4df10f6a80 100644
--- a/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionerImpl.cxx
+++ b/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionerImpl.cxx
@@ -67,11 +67,6 @@
#include "OGLTrans_TransitionImpl.hxx"
-#if defined( UNX ) && !defined( MACOSX )
- #include <X11/keysym.h>
- #include <X11/X.h>
-#endif
-
#include <vcl/sysdata.hxx>
#if OSL_DEBUG_LEVEL > 0
@@ -257,9 +252,7 @@ private:
bool mbFreeLeavingPixmap;
bool mbFreeEnteringPixmap;
#endif
-#if defined( UNX ) && !defined( MACOSX )
bool mbRestoreSync;
-#endif
bool mbUseLeavingPixmap;
bool mbUseEnteringPixmap;
@@ -437,10 +430,9 @@ void OGLTransitionerImpl::impl_prepareSlides()
mbUseLeavingPixmap = false;
mbUseEnteringPixmap = false;
-#if defined( GLX_EXT_texture_from_pixmap )
-
const GLWindow& rGLWindow(mpContext->getOpenGLWindow());
+#if defined( GLX_EXT_texture_from_pixmap )
if( GLXEW_EXT_texture_from_pixmap && xLeavingSet.is() && xEnteringSet.is() && mbHasTFPVisual ) {
Sequence< Any > leaveArgs;
Sequence< Any > enterArgs;
@@ -509,8 +501,8 @@ void OGLTransitionerImpl::impl_prepareSlides()
XSetErrorHandler( oldHandler );
}
}
-
#endif
+
if( !mbUseLeavingPixmap )
maLeavingBytes = mxLeavingBitmap->getData(maSlideBitmapLayout, aSlideRect);
if( !mbUseEnteringPixmap )
@@ -524,13 +516,11 @@ void OGLTransitionerImpl::impl_prepareSlides()
mpContext->sync();
CHECK_GL_ERROR();
-#if defined( UNX ) && !defined( MACOSX )
+
// synchronized X still gives us much smoother play
// I suspect some issues in above code in slideshow
// synchronize whole transition for now
- XSynchronize( rGLWindow.dpy, true );
- mbRestoreSync = true;
-#endif
+ mbRestoreSync = rGLWindow.Synchronize(true);
}
bool OGLTransitionerImpl::impl_prepareTransition()
@@ -1326,13 +1316,11 @@ void OGLTransitionerImpl::disposing()
}
#endif
-#if defined( UNX ) && !defined( MACOSX )
- if( mbRestoreSync && bool(mpContext.is()) ) {
+ if (mbRestoreSync && bool(mpContext.is())) {
// try to reestablish synchronize state
- char* sal_synchronize = getenv("SAL_SYNCHRONIZE");
- XSynchronize( mpContext->getOpenGLWindow().dpy, sal_synchronize && *sal_synchronize == '1' );
+ const char* sal_synchronize = getenv("SAL_SYNCHRONIZE");
+ mpContext->getOpenGLWindow().Synchronize(sal_synchronize && *sal_synchronize == '1' );
}
-#endif
impl_dispose();
@@ -1359,9 +1347,7 @@ OGLTransitionerImpl::OGLTransitionerImpl()
, mbFreeLeavingPixmap(false)
, mbFreeEnteringPixmap(false)
#endif
-#if defined( UNX ) && !defined( MACOSX )
, mbRestoreSync(false)
-#endif
, mbUseLeavingPixmap(false)
, mbUseEnteringPixmap(false)
, maSlideBitmapLayout()
diff --git a/slideshow/source/engine/shapes/viewmediashape.cxx b/slideshow/source/engine/shapes/viewmediashape.cxx
index e0c30a27b139..0db3ea64f91d 100644
--- a/slideshow/source/engine/shapes/viewmediashape.cxx
+++ b/slideshow/source/engine/shapes/viewmediashape.cxx
@@ -463,7 +463,7 @@ namespace slideshow
Size( aAWTRect.Width, aAWTRect.Height ) );
mpEventHandlerParent->EnablePaint(false);
mpEventHandlerParent->Show();
- SystemWindowData aWinData = OpenGLContext::generateWinData(mpEventHandlerParent.get(), false);
+ SystemWindowData aWinData = OpenGLContext::Create()->generateWinData(mpEventHandlerParent.get(), false);
mpMediaWindow = VclPtr<SystemChildWindow>::Create(mpEventHandlerParent.get(), 0, &aWinData);
mpMediaWindow->SetPosSizePixel( Point( 0, 0 ),
Size( aAWTRect.Width, aAWTRect.Height ) );
diff --git a/vcl/headless/svpinst.cxx b/vcl/headless/svpinst.cxx
index 0bd50fe4e59a..2665bb509d70 100644
--- a/vcl/headless/svpinst.cxx
+++ b/vcl/headless/svpinst.cxx
@@ -27,6 +27,7 @@
#include <sal/types.h>
#include <vcl/inputtypes.hxx>
+#include <vcl/opengl/OpenGLContext.hxx>
#include <headless/svpinst.hxx>
#include <headless/svpframe.hxx>
@@ -443,6 +444,16 @@ void SvpSalInstance::AddToRecentDocumentList(const OUString&, const OUString&, c
{
}
+//obviously doesn't actually do anything, its just a nonfunctional stub
+class SvpOpenGLContext : public OpenGLContext
+{
+};
+
+OpenGLContext* SvpSalInstance::CreateOpenGLContext()
+{
+ return new SvpOpenGLContext;
+}
+
SvpSalTimer::~SvpSalTimer()
{
}
diff --git a/vcl/inc/headless/svpinst.hxx b/vcl/inc/headless/svpinst.hxx
index ae23d71fa6ba..932e928fdbfe 100644
--- a/vcl/inc/headless/svpinst.hxx
+++ b/vcl/inc/headless/svpinst.hxx
@@ -163,6 +163,8 @@ public:
// may return NULL to disable session management
virtual SalSession* CreateSalSession() override;
+ virtual OpenGLContext* CreateOpenGLContext() override;
+
virtual void* GetConnectionIdentifier( ConnectionIdentifierType& rReturnedType, int& rReturnedBytes ) override;
virtual void AddToRecentDocumentList(const OUString& rFileUrl, const OUString& rMimeType, const OUString& rDocumentService) override;
diff --git a/vcl/inc/opengl/zone.hxx b/vcl/inc/opengl/zone.hxx
index c6ba0ccc7487..11f6ed00ec3c 100644
--- a/vcl/inc/opengl/zone.hxx
+++ b/vcl/inc/opengl/zone.hxx
@@ -21,7 +21,7 @@ class OpenGLWatchdogThread;
* We want to be able to detect if a given crash came
* from the OpenGL code, so use this helper to track that.
*/
-class OpenGLZone {
+class VCL_DLLPUBLIC OpenGLZone {
friend class OpenGLZoneTest;
friend class OpenGLWatchdogThread;
friend class OpenGLSalGraphicsImpl;
@@ -31,8 +31,8 @@ class OpenGLZone {
/// how many times have we left a new GL zone
static volatile sal_uInt64 gnLeaveCount;
- static VCL_DLLPUBLIC void enter();
- static VCL_DLLPUBLIC void leave();
+ static void enter();
+ static void leave();
public:
OpenGLZone() { gnEnterCount++; }
~OpenGLZone() { gnLeaveCount++; }
diff --git a/vcl/inc/osx/salinst.h b/vcl/inc/osx/salinst.h
index 20f3e3e314d5..61448259c1b9 100644
--- a/vcl/inc/osx/salinst.h
+++ b/vcl/inc/osx/salinst.h
@@ -117,6 +117,7 @@ public:
virtual SalMenuItem* CreateMenuItem( const SalItemParams* pItemData ) override;
virtual void DestroyMenuItem( SalMenuItem* ) override;
virtual SalSession* CreateSalSession() override;
+ virtual OpenGLContext* CreateOpenGLContext() override;
virtual void* GetConnectionIdentifier( ConnectionIdentifierType& rReturnedType,
int& rReturnedBytes ) override;
virtual void AddToRecentDocumentList(const OUString& rFileUrl, const OUString& rMimeType,
diff --git a/vcl/inc/salinst.hxx b/vcl/inc/salinst.hxx
index 6502679d426a..21f7be27711f 100644
--- a/vcl/inc/salinst.hxx
+++ b/vcl/inc/salinst.hxx
@@ -36,6 +36,7 @@ namespace comphelper { class SolarMutex; }
struct SystemParentData;
struct SalPrinterQueueInfo;
struct ImplJobSetup;
+class OpenGLContext;
class SalGraphics;
class SalFrame;
class SalObject;
@@ -145,6 +146,8 @@ public:
// may return NULL to disable session management
virtual SalSession* CreateSalSession() = 0;
+ virtual OpenGLContext* CreateOpenGLContext() = 0;
+
// methods for XDisplayConnection
void SetEventCallback( rtl::Reference< vcl::DisplayConnectionDispatch > const & pInstance )
diff --git a/vcl/inc/unx/salinst.h b/vcl/inc/unx/salinst.h
index cc0e086e5d77..8cb1014fb743 100644
--- a/vcl/inc/unx/salinst.h
+++ b/vcl/inc/unx/salinst.h
@@ -69,6 +69,7 @@ public:
virtual SalSystem* CreateSalSystem() override;
virtual SalBitmap* CreateSalBitmap() override;
virtual SalSession* CreateSalSession() override;
+ virtual OpenGLContext* CreateOpenGLContext() override;
virtual SalYieldResult DoYield(bool bWait, bool bHandleAllCurrentEvents, sal_uLong nReleased) override;
virtual bool AnyInput( VclInputFlags nType ) override;
diff --git a/vcl/inc/win/salinst.h b/vcl/inc/win/salinst.h
index 43c0313efa7d..23c0de7c9568 100644
--- a/vcl/inc/win/salinst.h
+++ b/vcl/inc/win/salinst.h
@@ -71,6 +71,7 @@ public:
virtual SalMenuItem* CreateMenuItem( const SalItemParams* pItemData ) override;
virtual void DestroyMenuItem( SalMenuItem* ) override;
virtual SalSession* CreateSalSession() override;
+ virtual OpenGLContext* CreateOpenGLContext() override;
virtual void* GetConnectionIdentifier( ConnectionIdentifierType& rReturnedType, int& rReturnedBytes ) override;
virtual void AddToRecentDocumentList(const OUString& rFileUrl, const OUString& rMimeType, const OUString& rDocumentService) override;
diff --git a/vcl/opengl/win/gdiimpl.cxx b/vcl/opengl/win/gdiimpl.cxx
index 7fbf8f787639..50fb3928600e 100644
--- a/vcl/opengl/win/gdiimpl.cxx
+++ b/vcl/opengl/win/gdiimpl.cxx
@@ -12,6 +12,477 @@
#include <win/wincomp.hxx>
#include <win/saldata.hxx>
#include <win/salframe.h>
+#include <win/salinst.h>
+
+static std::vector<HGLRC> g_vShareList;
+
+class WinOpenGLContext : public OpenGLContext
+{
+public:
+ bool init( HDC hDC, HWND hWnd );
+ virtual bool initWindow() override;
+private:
+ virtual bool ImplInit() override;
+ virtual void makeCurrent() override;
+ virtual void destroyCurrentContext() override;
+ virtual bool isCurrent() override;
+ virtual bool isAnyCurrent() override;
+ virtual void resetCurrent() override;
+ virtual void swapBuffers() override;
+};
+
+void WinOpenGLContext::swapBuffers()
+{
+ OpenGLZone aZone;
+
+ SwapBuffers(m_aGLWin.hDC);
+
+ BuffersSwapped();
+}
+
+void WinOpenGLContext::resetCurrent()
+{
+ clearCurrent();
+
+ OpenGLZone aZone;
+
+ wglMakeCurrent(NULL, NULL);
+}
+
+bool WinOpenGLContext::isCurrent()
+{
+ OpenGLZone aZone;
+ return wglGetCurrentContext() == m_aGLWin.hRC &&
+ wglGetCurrentDC() == m_aGLWin.hDC;
+}
+
+bool WinOpenGLContext::isAnyCurrent()
+{
+ return wglGetCurrentContext() != NULL;
+}
+
+void WinOpenGLContext::makeCurrent()
+{
+ if (isCurrent())
+ return;
+
+ OpenGLZone aZone;
+
+ clearCurrent();
+
+ if (!wglMakeCurrent(m_aGLWin.hDC, m_aGLWin.hRC))
+ {
+ SAL_WARN("vcl.opengl", "OpenGLContext::makeCurrent(): wglMakeCurrent failed: " << GetLastError());
+ return;
+ }
+
+ registerAsCurrent();
+}
+
+bool WinOpenGLContext::init(HDC hDC, HWND hWnd)
+{
+ if (isInitialized())
+ return false;
+
+ m_aGLWin.hDC = hDC;
+ m_aGLWin.hWnd = hWnd;
+ return ImplInit();
+}
+
+bool WinOpenGLContext::initWindow()
+{
+ if( !m_pChildWindow )
+ {
+ SystemWindowData winData = generateWinData(mpWindow, false);
+ m_pChildWindow = VclPtr<SystemChildWindow>::Create(mpWindow, 0, &winData, false);
+ }
+
+ if (m_pChildWindow)
+ {
+ InitChildWindow(m_pChildWindow.get());
+ const SystemEnvData* sysData(m_pChildWindow->GetSystemData());
+ m_aGLWin.hWnd = sysData->hWnd;
+ }
+
+ m_aGLWin.hDC = GetDC(m_aGLWin.hWnd);
+ return true;
+}
+
+void WinOpenGLContext::destroyCurrentContext()
+{
+ if (m_aGLWin.hRC)
+ {
+ std::vector<HGLRC>::iterator itr = std::remove(g_vShareList.begin(), g_vShareList.end(), m_aGLWin.hRC);
+ if (itr != g_vShareList.end())
+ g_vShareList.erase(itr);
+
+ if (wglGetCurrentContext() != NULL)
+ wglMakeCurrent(NULL, NULL);
+ wglDeleteContext( m_aGLWin.hRC );
+ ReleaseDC( m_aGLWin.hWnd, m_aGLWin.hDC );
+ m_aGLWin.hRC = 0;
+ }
+}
+
+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);
+ }
+}
+
+int InitTempWindow(HWND *hwnd, int width, int height, const PIXELFORMATDESCRIPTOR& inPfd, GLWindow& glWin)
+{
+ OpenGLZone aZone;
+
+ 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;
+ }
+
+ return 0;
+}
+
+bool WGLisExtensionSupported(const char *extension)
+{
+ OpenGLZone aZone;
+
+ 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)
+ return false;
+
+ // 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
+ }
+}
+
+bool InitMultisample(const PIXELFORMATDESCRIPTOR& pfd, int& rPixelFormat,
+ bool bUseDoubleBufferedRendering, bool bRequestVirtualDevice)
+{
+ OpenGLZone aZone;
+
+ HWND hWnd = NULL;
+ GLWindow glWin;
+ // Create a temp window to check whether support multi-sample, if support, get the format
+ if (InitTempWindow(&hWnd, 1, 1, pfd, glWin) < 0)
+ {
+ 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 multisample");
+ return false;
+ }
+ // Get our pixel format
+ PFNWGLCHOOSEPIXELFORMATARBPROC fn_wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB");
+ if (!fn_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 WGL_SAMPLE_BUFFERS_ARB and WGL_SAMPLES_ARB.
+ // These two are going to do the main testing for whether or not
+ // we support multisampling on this hardware.
+ int iAttributes[] =
+ {
+ WGL_DOUBLE_BUFFER_ARB,GL_TRUE,
+ 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,
+ WGL_DEPTH_BITS_ARB,24,
+ WGL_STENCIL_BITS_ARB,0,
+ WGL_SAMPLE_BUFFERS_ARB,GL_TRUE,
+ WGL_SAMPLES_ARB,8,
+ 0,0
+ };
+
+ if (!bUseDoubleBufferedRendering)
+ {
+ // Use asserts to make sure the iAttributes array is not changed without changing these ugly
+ // hardcode indexes into it.
+ assert(iAttributes[0] == WGL_DOUBLE_BUFFER_ARB);
+ iAttributes[1] = GL_FALSE;
+ }
+
+ if (bRequestVirtualDevice)
+ {
+ assert(iAttributes[2] == WGL_DRAW_TO_WINDOW_ARB);
+ iAttributes[2] = WGL_DRAW_TO_BITMAP_ARB;
+ }
+
+ bool bArbMultisampleSupported = false;
+
+ // First we check to see if we can get a pixel format for 8 samples
+ valid = fn_wglChoosePixelFormatARB(hDC, iAttributes, fAttributes, 1, &pixelFormat, &numFormats);
+ // If we returned true, and our format count is greater than 1
+ if (valid && numFormats >= 1)
+ {
+ bArbMultisampleSupported = true;
+ rPixelFormat = pixelFormat;
+ wglMakeCurrent(NULL, NULL);
+ wglDeleteContext(glWin.hRC);
+ ReleaseDC(hWnd, glWin.hDC);
+ DestroyWindow(hWnd);
+ return bArbMultisampleSupported;
+ }
+ // Our pixel format with 8 samples failed, test for 2 samples
+ assert(iAttributes[18] == WGL_SAMPLES_ARB);
+ iAttributes[19] = 2;
+ valid = fn_wglChoosePixelFormatARB(hDC, iAttributes, fAttributes, 1, &pixelFormat, &numFormats);
+ if (valid && numFormats >= 1)
+ {
+ bArbMultisampleSupported = true;
+ rPixelFormat = pixelFormat;
+ wglMakeCurrent(NULL, NULL);
+ wglDeleteContext(glWin.hRC);
+ ReleaseDC(hWnd, glWin.hDC);
+ DestroyWindow(hWnd);
+ return bArbMultisampleSupported;
+ }
+ // Return the valid format
+ wglMakeCurrent(NULL, NULL);
+ wglDeleteContext(glWin.hRC);
+ ReleaseDC(hWnd, glWin.hDC);
+ DestroyWindow(hWnd);
+
+ return bArbMultisampleSupported;
+}
+
+bool WinOpenGLContext::ImplInit()
+{
+ OpenGLZone aZone;
+
+ VCL_GL_INFO("OpenGLContext::ImplInit----start");
+ // PixelFormat tells Windows how we want things to be
+ PIXELFORMATDESCRIPTOR PixelFormatFront =
+ {
+ sizeof(PIXELFORMATDESCRIPTOR),
+ 1, // Version Number
+ PFD_SUPPORT_OPENGL,
+ 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
+ 24, // 24 bit z-buffer
+ 8, // stencil buffer
+ 0, // No Auxiliary Buffer
+ 0, // now ignored
+ 0, // Reserved
+ 0, 0, 0 // Layer Masks Ignored
+ };
+
+ if (mbUseDoubleBufferedRendering)
+ PixelFormatFront.dwFlags |= PFD_DOUBLEBUFFER;
+
+ PixelFormatFront.dwFlags |= PFD_DRAW_TO_WINDOW;
+
+ // we must check whether can set the MSAA
+ int WindowPix = 0;
+ bool bMultiSampleSupport = InitMultisample(PixelFormatFront, WindowPix,
+ mbUseDoubleBufferedRendering, false);
+ if (bMultiSampleSupport && WindowPix != 0)
+ {
+ m_aGLWin.bMultiSampleSupported = true;
+ }
+ else
+ {
+ WindowPix = ChoosePixelFormat(m_aGLWin.hDC, &PixelFormatFront);
+#if OSL_DEBUG_LEVEL > 0
+ PIXELFORMATDESCRIPTOR pfd;
+ DescribePixelFormat(m_aGLWin.hDC, WindowPix, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
+ SAL_WARN("vcl.opengl", "Render Target: Window: " << (int) ((pfd.dwFlags & PFD_DRAW_TO_WINDOW) != 0) << ", Bitmap: " << (int) ((pfd.dwFlags & PFD_DRAW_TO_BITMAP) != 0));
+ SAL_WARN("vcl.opengl", "Supports OpenGL: " << (int) ((pfd.dwFlags & PFD_SUPPORT_OPENGL) != 0));
+#endif
+ }
+
+ if (WindowPix == 0)
+ {
+ SAL_WARN("vcl.opengl", "Invalid pixelformat");
+ return false;
+ }
+
+ if (!SetPixelFormat(m_aGLWin.hDC, WindowPix, &PixelFormatFront))
+ {
+ ImplWriteLastError(GetLastError(), "SetPixelFormat in OpenGLContext::ImplInit");
+ SAL_WARN("vcl.opengl", "SetPixelFormat failed");
+ return false;
+ }
+
+ HGLRC hTempRC = wglCreateContext(m_aGLWin.hDC);
+ if (hTempRC == NULL)
+ {
+ ImplWriteLastError(GetLastError(), "wglCreateContext in OpenGLContext::ImplInit");
+ SAL_WARN("vcl.opengl", "wglCreateContext failed");
+ return false;
+ }
+
+ if (!wglMakeCurrent(m_aGLWin.hDC, hTempRC))
+ {
+ ImplWriteLastError(GetLastError(), "wglMakeCurrent in OpenGLContext::ImplInit");
+ SAL_WARN("vcl.opengl", "wglMakeCurrent failed");
+ return false;
+ }
+
+ if (!InitGLEW())
+ {
+ wglMakeCurrent(NULL, NULL);
+ wglDeleteContext(hTempRC);
+ return false;
+ }
+
+ HGLRC hSharedCtx = 0;
+ if (!g_vShareList.empty())
+ hSharedCtx = g_vShareList.front();
+
+ if (!wglCreateContextAttribsARB)
+ {
+ wglMakeCurrent(NULL, NULL);
+ wglDeleteContext(hTempRC);
+ return false;
+ }
+
+ // now setup the shared context; this needs a temporary context already
+ // set up in order to work
+ int attribs [] =
+ {
+#ifdef DBG_UTIL
+ WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_DEBUG_BIT_ARB,
+#endif
+ 0
+ };
+ m_aGLWin.hRC = wglCreateContextAttribsARB(m_aGLWin.hDC, hSharedCtx, attribs);
+ if (m_aGLWin.hRC == 0)
+ {
+ ImplWriteLastError(GetLastError(), "wglCreateContextAttribsARB in OpenGLContext::ImplInit");
+ SAL_WARN("vcl.opengl", "wglCreateContextAttribsARB failed");
+ wglMakeCurrent(NULL, NULL);
+ wglDeleteContext(hTempRC);
+ 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;
+ }
+
+ InitGLEWDebugging();
+
+ g_vShareList.push_back(m_aGLWin.hRC);
+
+ RECT clientRect;
+ GetClientRect(WindowFromDC(m_aGLWin.hDC), &clientRect);
+ m_aGLWin.Width = clientRect.right - clientRect.left;
+ m_aGLWin.Height = clientRect.bottom - clientRect.top;
+
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
+ registerAsCurrent();
+
+ return true;
+}
+
+OpenGLContext* WinSalInstance::CreateOpenGLContext()
+{
+ return new WinOpenGLContext;
+}
WinOpenGLSalGraphicsImpl::WinOpenGLSalGraphicsImpl(WinSalGraphics& rGraphics,
SalGeometryProvider *mpProvider):
@@ -28,10 +499,10 @@ void WinOpenGLSalGraphicsImpl::copyBits( const SalTwoRect& rPosAry, SalGraphics*
rtl::Reference<OpenGLContext> WinOpenGLSalGraphicsImpl::CreateWinContext()
{
- rtl::Reference<OpenGLContext> pContext = OpenGLContext::Create();
- pContext->setVCLOnly();
- pContext->init( mrParent.mhLocalDC, mrParent.mhWnd );
- return pContext;
+ rtl::Reference<WinOpenGLContext> xContext(new WinOpenGLContext);
+ xContext->setVCLOnly();
+ xContext->init(mrParent.mhLocalDC, mrParent.mhWnd);
+ return rtl::Reference<OpenGLContext>(xContext.get());
}
void WinOpenGLSalGraphicsImpl::Init()
diff --git a/vcl/opengl/x11/gdiimpl.cxx b/vcl/opengl/x11/gdiimpl.cxx
index 61dba9b78db3..1137a3a170c4 100644
--- a/vcl/opengl/x11/gdiimpl.cxx
+++ b/vcl/opengl/x11/gdiimpl.cxx
@@ -16,19 +16,565 @@
#include <unx/saldisp.hxx>
#include <unx/salframe.h>
#include <unx/salgdi.h>
+#include <unx/salinst.h>
#include <unx/salvd.h>
#include <unx/x11/xlimits.hxx>
#include <opengl/texture.hxx>
+#include <opengl/zone.hxx>
+#include <opengl/RenderState.hxx>
#include <opengl/x11/gdiimpl.hxx>
#include <opengl/x11/salvd.hxx>
-#include "opengl/RenderState.hxx"
#include <vcl/opengl/OpenGLContext.hxx>
#include <vcl/opengl/OpenGLHelper.hxx>
#include <o3tl/lru_map.hxx>
+static std::vector<GLXContext> g_vShareList;
+
+class X11OpenGLContext : public OpenGLContext
+{
+public:
+ bool init(Display* dpy, Window win, int screen);
+ virtual bool initWindow() override;
+private:
+ virtual bool ImplInit() override;
+ void initGLWindow(Visual* pVisual);
+ virtual SystemWindowData generateWinData(vcl::Window* pParent, bool bRequestLegacyContext) override;
+ virtual void makeCurrent() override;
+ virtual void destroyCurrentContext() override;
+ virtual bool isCurrent() override;
+ virtual bool isAnyCurrent() override;
+ virtual void sync() override;
+ virtual void resetCurrent() override;
+ virtual void swapBuffers() override;
+};
+
+namespace
+{
+
+#ifdef DBG_UTIL
+ int unxErrorHandler(Display* dpy, XErrorEvent* event)
+ {
+ char err[256];
+ char req[256];
+ char minor[256];
+ XGetErrorText(dpy, event->error_code, err, 256);
+ XGetErrorText(dpy, event->request_code, req, 256);
+ XGetErrorText(dpy, event->minor_code, minor, 256);
+ SAL_WARN("vcl.opengl", "Error: " << err << ", Req: " << req << ", Minor: " << minor);
+ return 0;
+ }
+#endif
+
+ typedef int (*errorHandler)(Display* /*dpy*/, XErrorEvent* /*evnt*/);
+
+ class TempErrorHandler
+ {
+ private:
+ errorHandler oldErrorHandler;
+ Display* mdpy;
+
+ public:
+ TempErrorHandler(Display* dpy, errorHandler newErrorHandler)
+ : oldErrorHandler(nullptr)
+ , mdpy(dpy)
+ {
+ if (mdpy)
+ {
+ XLockDisplay(dpy);
+ XSync(dpy, false);
+ oldErrorHandler = XSetErrorHandler(newErrorHandler);
+ }
+ }
+
+ ~TempErrorHandler()
+ {
+ if (mdpy)
+ {
+ // sync so that we possibly get an XError
+ glXWaitGL();
+ XSync(mdpy, false);
+ XSetErrorHandler(oldErrorHandler);
+ XUnlockDisplay(mdpy);
+ }
+ }
+ };
+
+ static bool errorTriggered;
+ int oglErrorHandler( Display* /*dpy*/, XErrorEvent* /*evnt*/ )
+ {
+ errorTriggered = true;
+
+ return 0;
+ }
+
+ GLXFBConfig* getFBConfig(Display* dpy, Window win, int& nBestFBC, bool bUseDoubleBufferedRendering, bool bWithSameVisualID)
+ {
+ OpenGLZone aZone;
+
+ if( dpy == nullptr || !glXQueryExtension( dpy, nullptr, nullptr ) )
+ return nullptr;
+
+ VCL_GL_INFO("window: " << win);
+
+ XWindowAttributes xattr;
+ if( !XGetWindowAttributes( dpy, win, &xattr ) )
+ {
+ SAL_WARN("vcl.opengl", "Failed to get window attributes for fbconfig " << win);
+ xattr.screen = nullptr;
+ xattr.visual = nullptr;
+ }
+
+ int screen = XScreenNumberOfScreen( xattr.screen );
+
+ // TODO: moggi: Select colour channel depth based on visual attributes, not hardcoded */
+ 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
+ };
+
+ if (!bUseDoubleBufferedRendering)
+ visual_attribs[1] = False;
+
+ int fbCount = 0;
+ GLXFBConfig* pFBC = glXChooseFBConfig( dpy,
+ screen,
+ visual_attribs, &fbCount );
+
+ if(!pFBC)
+ {
+ SAL_WARN("vcl.opengl", "no suitable fb format found");
+ return nullptr;
+ }
+
+ int best_num_samp = -1;
+ for(int i = 0; i < fbCount; ++i)
+ {
+ XVisualInfo* pVi = glXGetVisualFromFBConfig( dpy, pFBC[i] );
+ if(pVi && (!bWithSameVisualID || (xattr.visual && pVi->visualid == xattr.visual->visualid)) )
+ {
+ // 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;
+ }
+
+ // we need them before glew can initialize them
+ // glew needs an OpenGL context so we need to get the address manually
+ void initOpenGLFunctionPointers()
+ {
+ glXChooseFBConfig = reinterpret_cast<GLXFBConfig*(*)(Display *dpy, int screen, const int *attrib_list, int *nelements)>(glXGetProcAddressARB(reinterpret_cast<GLubyte const *>("glXChooseFBConfig")));
+ glXGetVisualFromFBConfig = reinterpret_cast<XVisualInfo*(*)(Display *dpy, GLXFBConfig config)>(glXGetProcAddressARB(reinterpret_cast<GLubyte const *>("glXGetVisualFromFBConfig"))); // try to find a visual for the current set of attributes
+ glXGetFBConfigAttrib = reinterpret_cast<int(*)(Display *dpy, GLXFBConfig config, int attribute, int* value)>(glXGetProcAddressARB(reinterpret_cast<GLubyte const *>("glXGetFBConfigAttrib")));
+ glXCreateContextAttribsARB = reinterpret_cast<GLXContext(*)(Display*, GLXFBConfig, GLXContext, Bool, const int*)>(glXGetProcAddressARB(reinterpret_cast<const GLubyte *>("glXCreateContextAttribsARB")));
+ glXCreatePixmap = reinterpret_cast<GLXPixmap(*)(Display*, GLXFBConfig, Pixmap, const int*)>(glXGetProcAddressARB(reinterpret_cast<const GLubyte *>("glXCreatePixmap")));
+ }
+
+ Visual* getVisual(Display* dpy, Window win)
+ {
+ OpenGLZone aZone;
+
+ initOpenGLFunctionPointers();
+
+ XWindowAttributes xattr;
+ if( !XGetWindowAttributes( dpy, win, &xattr ) )
+ {
+ SAL_WARN("vcl.opengl", "Failed to get window attributes for getVisual " << win);
+ xattr.visual = nullptr;
+ }
+ VCL_GL_INFO("using VisualID " << xattr.visual);
+ return xattr.visual;
+ }
+}
+
+void X11OpenGLContext::sync()
+{
+ OpenGLZone aZone;
+ glXWaitGL();
+ XSync(m_aGLWin.dpy, false);
+}
+
+void X11OpenGLContext::swapBuffers()
+{
+ OpenGLZone aZone;
+
+ glXSwapBuffers(m_aGLWin.dpy, m_aGLWin.win);
+
+ BuffersSwapped();
+}
+
+void X11OpenGLContext::resetCurrent()
+{
+ clearCurrent();
+
+ OpenGLZone aZone;
+
+ if (m_aGLWin.dpy)
+ glXMakeCurrent(m_aGLWin.dpy, None, nullptr);
+}
+
+bool X11OpenGLContext::isCurrent()
+{
+ OpenGLZone aZone;
+ return m_aGLWin.ctx && glXGetCurrentContext() == m_aGLWin.ctx &&
+ glXGetCurrentDrawable() == m_aGLWin.win;
+}
+
+bool X11OpenGLContext::isAnyCurrent()
+{
+ return glXGetCurrentContext() != None;
+}
+
+SystemWindowData X11OpenGLContext::generateWinData(vcl::Window* pParent, bool /*bRequestLegacyContext*/)
+{
+ OpenGLZone aZone;
+
+ SystemWindowData aWinData;
+ aWinData.nSize = sizeof(aWinData);
+ aWinData.pVisual = nullptr;
+
+ const SystemEnvData* sysData(pParent->GetSystemData());
+
+ Display *dpy = static_cast<Display*>(sysData->pDisplay);
+ Window win = sysData->aWindow;
+
+ if( dpy == nullptr || !glXQueryExtension( dpy, nullptr, nullptr ) )
+ return aWinData;
+
+ initOpenGLFunctionPointers();
+
+ int best_fbc = -1;
+ GLXFBConfig* pFBC = getFBConfig(dpy, win, best_fbc, true, false);
+
+ if (!pFBC)
+ return aWinData;
+
+ XVisualInfo* vi = nullptr;
+ if( best_fbc != -1 )
+ vi = glXGetVisualFromFBConfig( dpy, pFBC[best_fbc] );
+
+ XFree(pFBC);
+
+ if( vi )
+ {
+ VCL_GL_INFO("using VisualID " << vi->visualid);
+ aWinData.pVisual = static_cast<void*>(vi->visual);
+ }
+
+ return aWinData;
+}
+
+bool X11OpenGLContext::ImplInit()
+{
+ if (!m_aGLWin.dpy)
+ return false;
+
+ OpenGLZone aZone;
+
+ GLXContext pSharedCtx( nullptr );
+#ifdef DBG_UTIL
+ TempErrorHandler aErrorHandler(m_aGLWin.dpy, unxErrorHandler);
+#endif
+
+ VCL_GL_INFO("OpenGLContext::ImplInit----start");
+
+ if (!g_vShareList.empty())
+ pSharedCtx = g_vShareList.front();
+
+ if (glXCreateContextAttribsARB && !mbRequestLegacyContext)
+ {
+ int best_fbc = -1;
+ GLXFBConfig* pFBC = getFBConfig(m_aGLWin.dpy, m_aGLWin.win, best_fbc, mbUseDoubleBufferedRendering, false);
+
+ if (pFBC && best_fbc != -1)
+ {
+ int pContextAttribs[] =
+ {
+#if 0 // defined(DBG_UTIL)
+ GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
+ GLX_CONTEXT_MINOR_VERSION_ARB, 2,
+#endif
+ None
+
+ };
+ m_aGLWin.ctx = glXCreateContextAttribsARB(m_aGLWin.dpy, pFBC[best_fbc], pSharedCtx, /* direct, not via X */ GL_TRUE, pContextAttribs);
+ SAL_INFO_IF(m_aGLWin.ctx, "vcl.opengl", "created a 3.2 core context");
+ }
+ else
+ SAL_WARN("vcl.opengl", "unable to find correct FBC");
+ }
+
+ if (!m_aGLWin.ctx)
+ {
+ if (!m_aGLWin.vi)
+ return false;
+
+ SAL_WARN("vcl.opengl", "attempting to create a non-double-buffered "
+ "visual matching the context");
+
+ m_aGLWin.ctx = glXCreateContext(m_aGLWin.dpy,
+ m_aGLWin.vi,
+ pSharedCtx,
+ GL_TRUE /* direct, not via X server */);
+ }
+
+ if( m_aGLWin.ctx )
+ {
+ g_vShareList.push_back( m_aGLWin.ctx );
+ }
+ else
+ {
+ SAL_WARN("vcl.opengl", "unable to create GLX context");
+ return false;
+ }
+
+ if( !glXMakeCurrent( m_aGLWin.dpy, m_aGLWin.win, m_aGLWin.ctx ) )
+ {
+ 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 aWinAttr;
+ if( !XGetWindowAttributes( m_aGLWin.dpy, m_aGLWin.win, &aWinAttr ) )
+ {
+ 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 = aWinAttr.width;
+ m_aGLWin.Height = aWinAttr.height;
+ }
+
+ if( m_aGLWin.HasGLXExtension("GLX_SGI_swap_control" ) )
+ {
+ // enable vsync
+ typedef GLint (*glXSwapIntervalProc)(GLint);
+ glXSwapIntervalProc glXSwapInterval = reinterpret_cast<glXSwapIntervalProc>(glXGetProcAddress( reinterpret_cast<const GLubyte*>("glXSwapIntervalSGI") ));
+ if( glXSwapInterval )
+ {
+ TempErrorHandler aLocalErrorHandler(m_aGLWin.dpy, oglErrorHandler);
+
+ errorTriggered = false;
+
+ glXSwapInterval( 1 );
+
+ if( errorTriggered )
+ SAL_WARN("vcl.opengl", "error when trying to set swap interval, NVIDIA or Mesa bug?");
+ else
+ VCL_GL_INFO("set swap interval to 1 (enable vsync)");
+ }
+ }
+
+ bool bRet = InitGLEW();
+ InitGLEWDebugging();
+
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
+ registerAsCurrent();
+
+ return bRet;
+}
+
+void X11OpenGLContext::makeCurrent()
+{
+ if (isCurrent())
+ return;
+
+ OpenGLZone aZone;
+
+ clearCurrent();
+
+#ifdef DBG_UTIL
+ TempErrorHandler aErrorHandler(m_aGLWin.dpy, unxErrorHandler);
+#endif
+
+ if (m_aGLWin.dpy)
+ {
+ if (!glXMakeCurrent( m_aGLWin.dpy, m_aGLWin.win, m_aGLWin.ctx ))
+ {
+ SAL_WARN("vcl.opengl", "OpenGLContext::makeCurrent failed "
+ "on drawable " << m_aGLWin.win);
+ return;
+ }
+ }
+
+ registerAsCurrent();
+}
+
+void X11OpenGLContext::destroyCurrentContext()
+{
+ if(m_aGLWin.ctx)
+ {
+ std::vector<GLXContext>::iterator itr = std::remove( g_vShareList.begin(), g_vShareList.end(), m_aGLWin.ctx );
+ if (itr != g_vShareList.end())
+ g_vShareList.erase(itr);
+
+ glXMakeCurrent(m_aGLWin.dpy, None, nullptr);
+ if( glGetError() != GL_NO_ERROR )
+ {
+ SAL_WARN("vcl.opengl", "glError: " << glGetError());
+ }
+ glXDestroyContext(m_aGLWin.dpy, m_aGLWin.ctx);
+ m_aGLWin.ctx = nullptr;
+ }
+}
+
+bool X11OpenGLContext::init(Display* dpy, Window win, int screen)
+{
+ if (isInitialized())
+ return true;
+
+ if (!dpy)
+ return false;
+
+ OpenGLZone aZone;
+
+ m_aGLWin.dpy = dpy;
+ m_aGLWin.win = win;
+ m_aGLWin.screen = screen;
+
+ Visual* pVisual = getVisual(dpy, win);
+
+ initGLWindow(pVisual);
+
+ return ImplInit();
+}
+
+void X11OpenGLContext::initGLWindow(Visual* pVisual)
+{
+ OpenGLZone aZone;
+
+ // Get visual info
+ {
+ XVisualInfo aTemplate;
+ aTemplate.visualid = XVisualIDFromVisual( pVisual );
+ int nVisuals = 0;
+ XVisualInfo* pInfo = 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 = pInfo;
+ }
+
+ // Check multisample support
+ /* TODO: moggi: This is not necessarily correct in the DBG_UTIL path, as it picks
+ * an FBConfig instead ... */
+ int nSamples = 0;
+ glXGetConfig(m_aGLWin.dpy, m_aGLWin.vi, GLX_SAMPLES, &nSamples);
+ if( nSamples > 0 )
+ m_aGLWin.bMultiSampleSupported = true;
+
+ m_aGLWin.GLXExtensions = glXQueryExtensionsString( m_aGLWin.dpy, m_aGLWin.screen );
+ SAL_INFO("vcl.opengl", "available GLX extensions: " << m_aGLWin.GLXExtensions);
+}
+
+bool X11OpenGLContext::initWindow()
+{
+ const SystemEnvData* pChildSysData = nullptr;
+ SystemWindowData winData = generateWinData(mpWindow, false);
+ if( winData.pVisual )
+ {
+ if( !m_pChildWindow )
+ {
+ m_pChildWindow = VclPtr<SystemChildWindow>::Create(mpWindow, 0, &winData, false);
+ }
+ pChildSysData = m_pChildWindow->GetSystemData();
+ }
+
+ if (!m_pChildWindow || !pChildSysData)
+ return false;
+
+ InitChildWindow(m_pChildWindow.get());
+
+ m_aGLWin.dpy = static_cast<Display*>(pChildSysData->pDisplay);
+ m_aGLWin.win = pChildSysData->aWindow;
+ m_aGLWin.screen = pChildSysData->nScreen;
+
+ Visual* pVisual = static_cast<Visual*>(pChildSysData->pVisual);
+ initGLWindow(pVisual);
+
+ return true;
+}
+
+// Copy of gluCheckExtension(), from the Apache-licensed
+// https://code.google.com/p/glues/source/browse/trunk/glues/source/glues_registry.c
+static GLboolean checkExtension(const GLubyte* extName, const GLubyte* extString)
+{
+ GLboolean flag=GL_FALSE;
+ char* word;
+ char* lookHere;
+ char* deleteThis;
+
+ if (extString==nullptr)
+ {
+ return GL_FALSE;
+ }
+
+ deleteThis=lookHere=static_cast<char*>(malloc(strlen(reinterpret_cast<const char*>(extString))+1));
+ if (lookHere==nullptr)
+ {
+ return GL_FALSE;
+ }
+
+ /* strtok() will modify string, so copy it somewhere */
+ strcpy(lookHere, reinterpret_cast<const char*>(extString));
+
+ while ((word=strtok(lookHere, " "))!=nullptr)
+ {
+ if (strcmp(word, reinterpret_cast<const char*>(extName))==0)
+ {
+ flag=GL_TRUE;
+ break;
+ }
+ lookHere=nullptr; /* get next token */
+ }
+ free(static_cast<void*>(deleteThis));
+
+ return flag;
+}
+
+bool GLWindow::HasGLXExtension( const char* name ) const
+{
+ return checkExtension( reinterpret_cast<const GLubyte*>(name), reinterpret_cast<const GLubyte*>(GLXExtensions) );
+}
+
+OpenGLContext* X11SalInstance::CreateOpenGLContext()
+{
+ return new X11OpenGLContext;
+}
+
X11OpenGLSalGraphicsImpl::X11OpenGLSalGraphicsImpl( X11SalGraphics& rParent ):
OpenGLSalGraphicsImpl(rParent,rParent.GetGeometryProvider()),
mrParent(rParent)
@@ -54,11 +600,11 @@ rtl::Reference<OpenGLContext> X11OpenGLSalGraphicsImpl::CreateWinContext()
return nullptr;
sal_uIntPtr aWin = pProvider->GetNativeWindowHandle();
- rtl::Reference<OpenGLContext> pContext = OpenGLContext::Create();
- pContext->setVCLOnly();
- pContext->init( mrParent.GetXDisplay(), aWin,
+ rtl::Reference<X11OpenGLContext> xContext = new X11OpenGLContext;
+ xContext->setVCLOnly();
+ xContext->init( mrParent.GetXDisplay(), aWin,
mrParent.m_nXScreen.getXScreen() );
- return pContext;
+ return rtl::Reference<OpenGLContext>(xContext.get());
}
void X11OpenGLSalGraphicsImpl::copyBits( const SalTwoRect& rPosAry, SalGraphics* pSrcGraphics )
diff --git a/vcl/osx/salobj.cxx b/vcl/osx/salobj.cxx
index 87edbfa9a1ed..6bbb43aa51a8 100644
--- a/vcl/osx/salobj.cxx
+++ b/vcl/osx/salobj.cxx
@@ -18,10 +18,15 @@
*/
#include <string.h>
+#include <vcl/opengl/OpenGLContext.hxx>
+#include <vcl/opengl/OpenGLHelper.hxx>
+#include <opengl/zone.hxx>
#include "osx/saldata.hxx"
-#include "osx/salobj.h"
#include "osx/salframe.h"
+#include "osx/salinst.h"
+#include "osx/salobj.h"
+
#include <AppKit/NSOpenGLView.h>
AquaSalObject::AquaSalObject( AquaSalFrame* pFrame, SystemWindowData* pWindowData ) :
@@ -226,4 +231,106 @@ const SystemEnvData* AquaSalObject::GetSystemData() const
return &maSysData;
}
+class AquaOpenGLContext : public OpenGLContext
+{
+public:
+ virtual bool initWindow() override;
+private:
+ NSOpenGLView* getOpenGLView();
+ virtual bool ImplInit() override;
+ virtual SystemWindowData generateWinData(vcl::Window* pParent, bool bRequestLegacyContext) override;
+ virtual void makeCurrent() override;
+ virtual void destroyCurrentContext() override;
+ virtual void resetCurrent() override;
+ virtual void swapBuffers() override;
+};
+
+void AquaOpenGLContext::resetCurrent()
+{
+ clearCurrent();
+
+ OpenGLZone aZone;
+
+ (void) this; // loplugin:staticmethods
+ [NSOpenGLContext clearCurrentContext];
+}
+
+void AquaOpenGLContext::makeCurrent()
+{
+ if (isCurrent())
+ return;
+
+ OpenGLZone aZone;
+
+ clearCurrent();
+
+ NSOpenGLView* pView = getOpenGLView();
+ [[pView openGLContext] makeCurrentContext];
+
+ registerAsCurrent();
+}
+
+void AquaOpenGLContext::swapBuffers()
+{
+ OpenGLZone aZone;
+
+ NSOpenGLView* pView = getOpenGLView();
+ [[pView openGLContext] flushBuffer];
+
+ BuffersSwapped();
+}
+
+SystemWindowData AquaOpenGLContext::generateWinData(vcl::Window* /*pParent*/, bool bRequestLegacyContext)
+{
+ SystemWindowData aWinData;
+ aWinData.bOpenGL = true;
+ aWinData.bLegacy = bRequestLegacyContext;
+ aWinData.nSize = sizeof(aWinData);
+ return aWinData;
+}
+
+void AquaOpenGLContext::destroyCurrentContext()
+{
+ [NSOpenGLContext clearCurrentContext];
+}
+
+bool AquaOpenGLContext::initWindow()
+{
+ if( !m_pChildWindow )
+ {
+ SystemWindowData winData = generateWinData(mpWindow, mbRequestLegacyContext);
+ m_pChildWindow = VclPtr<SystemChildWindow>::Create(mpWindow, 0, &winData, false);
+ }
+
+ if (m_pChildWindow)
+ {
+ InitChildWindow(m_pChildWindow.get());
+ }
+
+ return true;
+}
+
+bool AquaOpenGLContext::ImplInit()
+{
+ OpenGLZone aZone;
+
+ VCL_GL_INFO("OpenGLContext::ImplInit----start");
+ NSOpenGLView* pView = getOpenGLView();
+ [[pView openGLContext] makeCurrentContext];
+
+ bool bRet = InitGLEW();
+ InitGLEWDebugging();
+ return bRet;
+}
+
+NSOpenGLView* AquaOpenGLContext::getOpenGLView()
+{
+ return reinterpret_cast<NSOpenGLView*>(m_pChildWindow->GetSystemData()->mpNSView);
+}
+
+OpenGLContext* AquaSalInstance::CreateOpenGLContext()
+{
+ return new AquaOpenGLContext;
+}
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/opengl/OpenGLContext.cxx b/vcl/source/opengl/OpenGLContext.cxx
index f254974727c9..89ce97019be9 100644
--- a/vcl/source/opengl/OpenGLContext.cxx
+++ b/vcl/source/opengl/OpenGLContext.cxx
@@ -22,19 +22,9 @@
#include <osl/thread.hxx>
-#if defined(MACOSX)
-#include <premac.h>
-#include <AppKit/NSOpenGLView.h>
-#include <AppKit/NSOpenGL.h>
-#include <postmac.h>
-#endif
-
-#if defined(_WIN32)
-#include <win/saldata.hxx>
-#endif
-
#include "svdata.hxx"
#include "salgdi.hxx"
+#include "salinst.hxx"
#include <opengl/framebuffer.hxx>
#include <opengl/program.hxx>
@@ -47,13 +37,6 @@ using namespace com::sun::star;
#define MAX_FRAMEBUFFER_COUNT 30
-// TODO use rtl::Static instead of 'static'
-#if defined( UNX ) && !defined MACOSX && !defined IOS && !defined ANDROID && !defined(LIBO_HEADLESS)
-static std::vector<GLXContext> g_vShareList;
-#elif defined(WNT)
-static std::vector<HGLRC> g_vShareList;
-#endif
-
static sal_Int64 nBufferSwapCounter = 0;
GLWindow::~GLWindow()
@@ -63,6 +46,17 @@ GLWindow::~GLWindow()
#endif
}
+bool GLWindow::Synchronize(bool bOnoff) const
+{
+#if defined( UNX ) && !defined MACOSX && !defined IOS && !defined ANDROID && !defined(LIBO_HEADLESS)
+ XSynchronize(dpy, bOnoff);
+ return true;
+#else
+ (void)bOnoff;
+ return false;
+#endif
+}
+
OpenGLContext::OpenGLContext():
mpWindow(nullptr),
m_pChildWindow(nullptr),
@@ -128,7 +122,7 @@ void OpenGLContext::dispose()
rtl::Reference<OpenGLContext> OpenGLContext::Create()
{
- return rtl::Reference<OpenGLContext>(new OpenGLContext);
+ return rtl::Reference<OpenGLContext>(ImplGetSVData()->mpDefInst->CreateOpenGLContext());
}
void OpenGLContext::requestLegacyContext()
@@ -141,222 +135,6 @@ void OpenGLContext::requestSingleBufferedRendering()
mbUseDoubleBufferedRendering = false;
}
-#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);
- }
-}
-
-int InitTempWindow(HWND *hwnd, int width, int height, const PIXELFORMATDESCRIPTOR& inPfd, GLWindow& glWin)
-{
- OpenGLZone aZone;
-
- 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;
- }
-
- return 0;
-}
-
-bool WGLisExtensionSupported(const char *extension)
-{
- OpenGLZone aZone;
-
- 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)
- return false;
-
- // 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
- }
-}
-
-bool InitMultisample(const PIXELFORMATDESCRIPTOR& pfd, int& rPixelFormat,
- bool bUseDoubleBufferedRendering, bool bRequestVirtualDevice)
-{
- OpenGLZone aZone;
-
- HWND hWnd = NULL;
- GLWindow glWin;
- // Create a temp window to check whether support multi-sample, if support, get the format
- if (InitTempWindow(&hWnd, 1, 1, pfd, glWin) < 0)
- {
- 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 multisample");
- return false;
- }
- // Get our pixel format
- PFNWGLCHOOSEPIXELFORMATARBPROC fn_wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB");
- if (!fn_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 WGL_SAMPLE_BUFFERS_ARB and WGL_SAMPLES_ARB.
- // These two are going to do the main testing for whether or not
- // we support multisampling on this hardware.
- int iAttributes[] =
- {
- WGL_DOUBLE_BUFFER_ARB,GL_TRUE,
- 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,
- WGL_DEPTH_BITS_ARB,24,
- WGL_STENCIL_BITS_ARB,0,
- WGL_SAMPLE_BUFFERS_ARB,GL_TRUE,
- WGL_SAMPLES_ARB,8,
- 0,0
- };
-
- if (!bUseDoubleBufferedRendering)
- {
- // Use asserts to make sure the iAttributes array is not changed without changing these ugly
- // hardcode indexes into it.
- assert(iAttributes[0] == WGL_DOUBLE_BUFFER_ARB);
- iAttributes[1] = GL_FALSE;
- }
-
- if (bRequestVirtualDevice)
- {
- assert(iAttributes[2] == WGL_DRAW_TO_WINDOW_ARB);
- iAttributes[2] = WGL_DRAW_TO_BITMAP_ARB;
- }
-
- bool bArbMultisampleSupported = false;
-
- // First we check to see if we can get a pixel format for 8 samples
- valid = fn_wglChoosePixelFormatARB(hDC, iAttributes, fAttributes, 1, &pixelFormat, &numFormats);
- // If we returned true, and our format count is greater than 1
- if (valid && numFormats >= 1)
- {
- bArbMultisampleSupported = true;
- rPixelFormat = pixelFormat;
- wglMakeCurrent(NULL, NULL);
- wglDeleteContext(glWin.hRC);
- ReleaseDC(hWnd, glWin.hDC);
- DestroyWindow(hWnd);
- return bArbMultisampleSupported;
- }
- // Our pixel format with 8 samples failed, test for 2 samples
- assert(iAttributes[18] == WGL_SAMPLES_ARB);
- iAttributes[19] = 2;
- valid = fn_wglChoosePixelFormatARB(hDC, iAttributes, fAttributes, 1, &pixelFormat, &numFormats);
- if (valid && numFormats >= 1)
- {
- bArbMultisampleSupported = true;
- rPixelFormat = pixelFormat;
- wglMakeCurrent(NULL, NULL);
- wglDeleteContext(glWin.hRC);
- ReleaseDC(hWnd, glWin.hDC);
- DestroyWindow(hWnd);
- return bArbMultisampleSupported;
- }
- // Return the valid format
- wglMakeCurrent(NULL, NULL);
- wglDeleteContext(glWin.hRC);
- ReleaseDC(hWnd, glWin.hDC);
- DestroyWindow(hWnd);
-
- return bArbMultisampleSupported;
-}
-#endif
-
#ifdef DBG_UTIL
namespace {
@@ -456,168 +234,6 @@ debug_callback(GLenum source, GLenum type, GLuint id,
#endif
-#if defined UNX && !defined MACOSX && !defined IOS && !defined ANDROID && !defined(LIBO_HEADLESS)
-
-namespace {
-
-#ifdef DBG_UTIL
-int unxErrorHandler(Display* dpy, XErrorEvent* event)
-{
- char err[256];
- char req[256];
- char minor[256];
- XGetErrorText(dpy, event->error_code, err, 256);
- XGetErrorText(dpy, event->request_code, req, 256);
- XGetErrorText(dpy, event->minor_code, minor, 256);
- SAL_WARN("vcl.opengl", "Error: " << err << ", Req: " << req << ", Minor: " << minor);
- return 0;
-}
-#endif
-
-typedef int (*errorHandler)(Display* /*dpy*/, XErrorEvent* /*evnt*/);
-
-class TempErrorHandler
-{
-private:
- errorHandler oldErrorHandler;
- Display* mdpy;
-
-public:
- TempErrorHandler(Display* dpy, errorHandler newErrorHandler)
- : oldErrorHandler(nullptr)
- , mdpy(dpy)
- {
- if (mdpy)
- {
- XLockDisplay(dpy);
- XSync(dpy, false);
- oldErrorHandler = XSetErrorHandler(newErrorHandler);
- }
- }
-
- ~TempErrorHandler()
- {
- if (mdpy)
- {
- // sync so that we possibly get an XError
- glXWaitGL();
- XSync(mdpy, false);
- XSetErrorHandler(oldErrorHandler);
- XUnlockDisplay(mdpy);
- }
- }
-};
-
-static bool errorTriggered;
-int oglErrorHandler( Display* /*dpy*/, XErrorEvent* /*evnt*/ )
-{
- errorTriggered = true;
-
- return 0;
-}
-
-GLXFBConfig* getFBConfig(Display* dpy, Window win, int& nBestFBC, bool bUseDoubleBufferedRendering, bool bWithSameVisualID)
-{
- OpenGLZone aZone;
-
- if( dpy == nullptr || !glXQueryExtension( dpy, nullptr, nullptr ) )
- return nullptr;
-
- VCL_GL_INFO("window: " << win);
-
- XWindowAttributes xattr;
- if( !XGetWindowAttributes( dpy, win, &xattr ) )
- {
- SAL_WARN("vcl.opengl", "Failed to get window attributes for fbconfig " << win);
- xattr.screen = nullptr;
- xattr.visual = nullptr;
- }
-
- int screen = XScreenNumberOfScreen( xattr.screen );
-
- // TODO: moggi: Select colour channel depth based on visual attributes, not hardcoded */
- 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
- };
-
- if (!bUseDoubleBufferedRendering)
- visual_attribs[1] = False;
-
- int fbCount = 0;
- GLXFBConfig* pFBC = glXChooseFBConfig( dpy,
- screen,
- visual_attribs, &fbCount );
-
- if(!pFBC)
- {
- SAL_WARN("vcl.opengl", "no suitable fb format found");
- return nullptr;
- }
-
- int best_num_samp = -1;
- for(int i = 0; i < fbCount; ++i)
- {
- XVisualInfo* pVi = glXGetVisualFromFBConfig( dpy, pFBC[i] );
- if(pVi && (!bWithSameVisualID || (xattr.visual && pVi->visualid == xattr.visual->visualid)) )
- {
- // 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;
-}
-
-// we need them before glew can initialize them
-// glew needs an OpenGL context so we need to get the address manually
-void initOpenGLFunctionPointers()
-{
- glXChooseFBConfig = reinterpret_cast<GLXFBConfig*(*)(Display *dpy, int screen, const int *attrib_list, int *nelements)>(glXGetProcAddressARB(reinterpret_cast<GLubyte const *>("glXChooseFBConfig")));
- glXGetVisualFromFBConfig = reinterpret_cast<XVisualInfo*(*)(Display *dpy, GLXFBConfig config)>(glXGetProcAddressARB(reinterpret_cast<GLubyte const *>("glXGetVisualFromFBConfig"))); // try to find a visual for the current set of attributes
- glXGetFBConfigAttrib = reinterpret_cast<int(*)(Display *dpy, GLXFBConfig config, int attribute, int* value)>(glXGetProcAddressARB(reinterpret_cast<GLubyte const *>("glXGetFBConfigAttrib")));
- glXCreateContextAttribsARB = reinterpret_cast<GLXContext(*)(Display*, GLXFBConfig, GLXContext, Bool, const int*)>(glXGetProcAddressARB(reinterpret_cast<const GLubyte *>("glXCreateContextAttribsARB")));
- glXCreatePixmap = reinterpret_cast<GLXPixmap(*)(Display*, GLXFBConfig, Pixmap, const int*)>(glXGetProcAddressARB(reinterpret_cast<const GLubyte *>("glXCreatePixmap")));
-}
-
-Visual* getVisual(Display* dpy, Window win)
-{
- OpenGLZone aZone;
-
- initOpenGLFunctionPointers();
-
- XWindowAttributes xattr;
- if( !XGetWindowAttributes( dpy, win, &xattr ) )
- {
- SAL_WARN("vcl.opengl", "Failed to get window attributes for getVisual " << win);
- xattr.visual = nullptr;
- }
- VCL_GL_INFO("using VisualID " << xattr.visual);
- return xattr.visual;
-}
-
-}
-
-#endif
-
bool OpenGLContext::init( vcl::Window* pParent )
{
if(mbInitialized)
@@ -650,370 +266,12 @@ bool OpenGLContext::init(SystemChildWindow* pChildWindow)
return ImplInit();
}
-#if defined( UNX ) && !defined MACOSX && !defined IOS && !defined ANDROID && !defined(LIBO_HEADLESS)
-bool OpenGLContext::init(Display* dpy, Window win, int screen)
-{
- if(mbInitialized)
- return true;
-
- if (!dpy)
- return false;
-
- OpenGLZone aZone;
-
- m_aGLWin.dpy = dpy;
- m_aGLWin.win = win;
- m_aGLWin.screen = screen;
-
- Visual* pVisual = getVisual(dpy, win);
-
- initGLWindow(pVisual);
-
- return ImplInit();
-}
-
-// Copy of gluCheckExtension(), from the Apache-licensed
-// https://code.google.com/p/glues/source/browse/trunk/glues/source/glues_registry.c
-static GLboolean checkExtension(const GLubyte* extName, const GLubyte* extString)
-{
- GLboolean flag=GL_FALSE;
- char* word;
- char* lookHere;
- char* deleteThis;
-
- if (extString==nullptr)
- {
- return GL_FALSE;
- }
-
- deleteThis=lookHere=static_cast<char*>(malloc(strlen(reinterpret_cast<const char*>(extString))+1));
- if (lookHere==nullptr)
- {
- return GL_FALSE;
- }
-
- /* strtok() will modify string, so copy it somewhere */
- strcpy(lookHere, reinterpret_cast<const char*>(extString));
-
- while ((word=strtok(lookHere, " "))!=nullptr)
- {
- if (strcmp(word, reinterpret_cast<const char*>(extName))==0)
- {
- flag=GL_TRUE;
- break;
- }
- lookHere=nullptr; /* get next token */
- }
- free(static_cast<void*>(deleteThis));
-
- return flag;
-}
-
-bool GLWindow::HasGLXExtension( const char* name ) const
-{
- return checkExtension( reinterpret_cast<const GLubyte*>(name), reinterpret_cast<const GLubyte*>(GLXExtensions) );
-}
-
-bool OpenGLContext::ImplInit()
-{
- if (!m_aGLWin.dpy)
- return false;
-
- OpenGLZone aZone;
-
- GLXContext pSharedCtx( nullptr );
-#ifdef DBG_UTIL
- TempErrorHandler aErrorHandler(m_aGLWin.dpy, unxErrorHandler);
-#endif
-
- VCL_GL_INFO("OpenGLContext::ImplInit----start");
-
- if (!g_vShareList.empty())
- pSharedCtx = g_vShareList.front();
-
- if (glXCreateContextAttribsARB && !mbRequestLegacyContext)
- {
- int best_fbc = -1;
- GLXFBConfig* pFBC = getFBConfig(m_aGLWin.dpy, m_aGLWin.win, best_fbc, mbUseDoubleBufferedRendering, false);
-
- if (pFBC && best_fbc != -1)
- {
- int pContextAttribs[] =
- {
-#if 0 // defined(DBG_UTIL)
- GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
- GLX_CONTEXT_MINOR_VERSION_ARB, 2,
-#endif
- None
-
- };
- m_aGLWin.ctx = glXCreateContextAttribsARB(m_aGLWin.dpy, pFBC[best_fbc], pSharedCtx, /* direct, not via X */ GL_TRUE, pContextAttribs);
- SAL_INFO_IF(m_aGLWin.ctx, "vcl.opengl", "created a 3.2 core context");
- }
- else
- SAL_WARN("vcl.opengl", "unable to find correct FBC");
- }
-
- if (!m_aGLWin.ctx)
- {
- if (!m_aGLWin.vi)
- return false;
-
- SAL_WARN("vcl.opengl", "attempting to create a non-double-buffered "
- "visual matching the context");
-
- m_aGLWin.ctx = glXCreateContext(m_aGLWin.dpy,
- m_aGLWin.vi,
- pSharedCtx,
- GL_TRUE /* direct, not via X server */);
- }
-
- if( m_aGLWin.ctx )
- {
- g_vShareList.push_back( m_aGLWin.ctx );
- }
- else
- {
- SAL_WARN("vcl.opengl", "unable to create GLX context");
- return false;
- }
-
- if( !glXMakeCurrent( m_aGLWin.dpy, m_aGLWin.win, m_aGLWin.ctx ) )
- {
- 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 aWinAttr;
- if( !XGetWindowAttributes( m_aGLWin.dpy, m_aGLWin.win, &aWinAttr ) )
- {
- 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 = aWinAttr.width;
- m_aGLWin.Height = aWinAttr.height;
- }
-
- if( m_aGLWin.HasGLXExtension("GLX_SGI_swap_control" ) )
- {
- // enable vsync
- typedef GLint (*glXSwapIntervalProc)(GLint);
- glXSwapIntervalProc glXSwapInterval = reinterpret_cast<glXSwapIntervalProc>(glXGetProcAddress( reinterpret_cast<const GLubyte*>("glXSwapIntervalSGI") ));
- if( glXSwapInterval )
- {
- TempErrorHandler aLocalErrorHandler(m_aGLWin.dpy, oglErrorHandler);
-
- errorTriggered = false;
-
- glXSwapInterval( 1 );
-
- if( errorTriggered )
- SAL_WARN("vcl.opengl", "error when trying to set swap interval, NVIDIA or Mesa bug?");
- else
- VCL_GL_INFO("set swap interval to 1 (enable vsync)");
- }
- }
-
- bool bRet = InitGLEW();
- InitGLEWDebugging();
-
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
-
- registerAsCurrent();
-
- return bRet;
-}
-
-#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()
-{
- OpenGLZone aZone;
-
- VCL_GL_INFO("OpenGLContext::ImplInit----start");
- // PixelFormat tells Windows how we want things to be
- PIXELFORMATDESCRIPTOR PixelFormatFront =
- {
- sizeof(PIXELFORMATDESCRIPTOR),
- 1, // Version Number
- PFD_SUPPORT_OPENGL,
- 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
- 24, // 24 bit z-buffer
- 8, // stencil buffer
- 0, // No Auxiliary Buffer
- 0, // now ignored
- 0, // Reserved
- 0, 0, 0 // Layer Masks Ignored
- };
-
- if (mbUseDoubleBufferedRendering)
- PixelFormatFront.dwFlags |= PFD_DOUBLEBUFFER;
-
- PixelFormatFront.dwFlags |= PFD_DRAW_TO_WINDOW;
-
- // we must check whether can set the MSAA
- int WindowPix = 0;
- bool bMultiSampleSupport = InitMultisample(PixelFormatFront, WindowPix,
- mbUseDoubleBufferedRendering, false);
- if (bMultiSampleSupport && WindowPix != 0)
- {
- m_aGLWin.bMultiSampleSupported = true;
- }
- else
- {
- WindowPix = ChoosePixelFormat(m_aGLWin.hDC, &PixelFormatFront);
-#if OSL_DEBUG_LEVEL > 0
- PIXELFORMATDESCRIPTOR pfd;
- DescribePixelFormat(m_aGLWin.hDC, WindowPix, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
- SAL_WARN("vcl.opengl", "Render Target: Window: " << (int) ((pfd.dwFlags & PFD_DRAW_TO_WINDOW) != 0) << ", Bitmap: " << (int) ((pfd.dwFlags & PFD_DRAW_TO_BITMAP) != 0));
- SAL_WARN("vcl.opengl", "Supports OpenGL: " << (int) ((pfd.dwFlags & PFD_SUPPORT_OPENGL) != 0));
-#endif
- }
-
- if (WindowPix == 0)
- {
- SAL_WARN("vcl.opengl", "Invalid pixelformat");
- return false;
- }
-
- if (!SetPixelFormat(m_aGLWin.hDC, WindowPix, &PixelFormatFront))
- {
- ImplWriteLastError(GetLastError(), "SetPixelFormat in OpenGLContext::ImplInit");
- SAL_WARN("vcl.opengl", "SetPixelFormat failed");
- return false;
- }
-
- HGLRC hTempRC = wglCreateContext(m_aGLWin.hDC);
- if (hTempRC == NULL)
- {
- ImplWriteLastError(GetLastError(), "wglCreateContext in OpenGLContext::ImplInit");
- SAL_WARN("vcl.opengl", "wglCreateContext failed");
- return false;
- }
-
- if (!wglMakeCurrent(m_aGLWin.hDC, hTempRC))
- {
- ImplWriteLastError(GetLastError(), "wglMakeCurrent in OpenGLContext::ImplInit");
- SAL_WARN("vcl.opengl", "wglMakeCurrent failed");
- return false;
- }
-
- if (!InitGLEW())
- {
- wglMakeCurrent(NULL, NULL);
- wglDeleteContext(hTempRC);
- return false;
- }
-
- HGLRC hSharedCtx = 0;
- if (!g_vShareList.empty())
- hSharedCtx = g_vShareList.front();
-
- if (!wglCreateContextAttribsARB)
- {
- wglMakeCurrent(NULL, NULL);
- wglDeleteContext(hTempRC);
- return false;
- }
-
- // now setup the shared context; this needs a temporary context already
- // set up in order to work
- int attribs [] =
- {
-#ifdef DBG_UTIL
- WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_DEBUG_BIT_ARB,
-#endif
- 0
- };
- m_aGLWin.hRC = wglCreateContextAttribsARB(m_aGLWin.hDC, hSharedCtx, attribs);
- if (m_aGLWin.hRC == 0)
- {
- ImplWriteLastError(GetLastError(), "wglCreateContextAttribsARB in OpenGLContext::ImplInit");
- SAL_WARN("vcl.opengl", "wglCreateContextAttribsARB failed");
- wglMakeCurrent(NULL, NULL);
- wglDeleteContext(hTempRC);
- 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;
- }
-
- InitGLEWDebugging();
-
- g_vShareList.push_back(m_aGLWin.hRC);
-
- RECT clientRect;
- GetClientRect(WindowFromDC(m_aGLWin.hDC), &clientRect);
- m_aGLWin.Width = clientRect.right - clientRect.left;
- m_aGLWin.Height = clientRect.bottom - clientRect.top;
-
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
-
- registerAsCurrent();
-
- return true;
-}
-
-#elif defined( MACOSX )
-
-bool OpenGLContext::ImplInit()
-{
- OpenGLZone aZone;
-
- VCL_GL_INFO("OpenGLContext::ImplInit----start");
- NSOpenGLView* pView = getOpenGLView();
- [[pView openGLContext] makeCurrentContext];
-
- bool bRet = InitGLEW();
- InitGLEWDebugging();
- return bRet;
-}
-
-#else
-
bool OpenGLContext::ImplInit()
{
VCL_GL_INFO("OpenGLContext not implemented for this platform");
return false;
}
-#endif
-
bool OpenGLContext::InitGLEW()
{
static bool bGlewInit = false;
@@ -1101,111 +359,16 @@ void OpenGLContext::InitChildWindow(SystemChildWindow *pChildWindow)
pChildWindow->SetControlBackground();
}
-#if defined(_WIN32)
-
-bool OpenGLContext::initWindow()
-{
- if( !m_pChildWindow )
- {
- SystemWindowData winData = generateWinData(mpWindow, false);
- m_pChildWindow = VclPtr<SystemChildWindow>::Create(mpWindow, 0, &winData, false);
- }
-
- if (m_pChildWindow)
- {
- InitChildWindow(m_pChildWindow.get());
- const SystemEnvData* sysData(m_pChildWindow->GetSystemData());
- m_aGLWin.hWnd = sysData->hWnd;
- }
-
- m_aGLWin.hDC = GetDC(m_aGLWin.hWnd);
- return true;
-}
-
-#elif defined( MACOSX )
-
-bool OpenGLContext::initWindow()
-{
- if( !m_pChildWindow )
- {
- SystemWindowData winData = generateWinData(mpWindow, mbRequestLegacyContext);
- m_pChildWindow = VclPtr<SystemChildWindow>::Create(mpWindow, 0, &winData, false);
- }
-
- if (m_pChildWindow)
- {
- InitChildWindow(m_pChildWindow.get());
- }
-
- return true;
-}
-
-#elif defined( IOS ) || defined( ANDROID ) || defined(LIBO_HEADLESS)
-
bool OpenGLContext::initWindow()
{
return false;
}
-#elif defined( UNX )
-
-bool OpenGLContext::initWindow()
+void OpenGLContext::destroyCurrentContext()
{
- const SystemEnvData* pChildSysData = nullptr;
- SystemWindowData winData = generateWinData(mpWindow, false);
- if( winData.pVisual )
- {
- if( !m_pChildWindow )
- {
- m_pChildWindow = VclPtr<SystemChildWindow>::Create(mpWindow, 0, &winData, false);
- }
- pChildSysData = m_pChildWindow->GetSystemData();
- }
-
- if (!m_pChildWindow || !pChildSysData)
- return false;
-
- InitChildWindow(m_pChildWindow.get());
-
- m_aGLWin.dpy = static_cast<Display*>(pChildSysData->pDisplay);
- m_aGLWin.win = pChildSysData->aWindow;
- m_aGLWin.screen = pChildSysData->nScreen;
-
- Visual* pVisual = static_cast<Visual*>(pChildSysData->pVisual);
- initGLWindow(pVisual);
-
- return true;
-}
-
-void OpenGLContext::initGLWindow(Visual* pVisual)
-{
- OpenGLZone aZone;
-
- // Get visual info
- {
- XVisualInfo aTemplate;
- aTemplate.visualid = XVisualIDFromVisual( pVisual );
- int nVisuals = 0;
- XVisualInfo* pInfo = 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 = pInfo;
- }
-
- // Check multisample support
- /* TODO: moggi: This is not necessarily correct in the DBG_UTIL path, as it picks
- * an FBConfig instead ... */
- int nSamples = 0;
- glXGetConfig(m_aGLWin.dpy, m_aGLWin.vi, GLX_SAMPLES, &nSamples);
- if( nSamples > 0 )
- m_aGLWin.bMultiSampleSupported = true;
-
- m_aGLWin.GLXExtensions = glXQueryExtensionsString( m_aGLWin.dpy, m_aGLWin.screen );
- SAL_INFO("vcl.opengl", "available GLX extensions: " << m_aGLWin.GLXExtensions);
+ //nothing by default
}
-#endif
-
void OpenGLContext::reset()
{
if( !mbInitialized )
@@ -1249,127 +412,46 @@ void OpenGLContext::reset()
mbInitialized = false;
// destroy the context itself
-#if defined(_WIN32)
- if (m_aGLWin.hRC)
- {
- std::vector<HGLRC>::iterator itr = std::remove(g_vShareList.begin(), g_vShareList.end(), m_aGLWin.hRC);
- if (itr != g_vShareList.end())
- g_vShareList.erase(itr);
-
- if (wglGetCurrentContext() != NULL)
- wglMakeCurrent(NULL, NULL);
- wglDeleteContext( m_aGLWin.hRC );
- ReleaseDC( m_aGLWin.hWnd, m_aGLWin.hDC );
- m_aGLWin.hRC = 0;
- }
-#elif defined( MACOSX )
- [NSOpenGLContext clearCurrentContext];
-#elif defined( IOS ) || defined( ANDROID ) || defined(LIBO_HEADLESS)
- // nothing
-#elif defined( UNX )
- if(m_aGLWin.ctx)
- {
- std::vector<GLXContext>::iterator itr = std::remove( g_vShareList.begin(), g_vShareList.end(), m_aGLWin.ctx );
- if (itr != g_vShareList.end())
- g_vShareList.erase(itr);
-
- glXMakeCurrent(m_aGLWin.dpy, None, nullptr);
- if( glGetError() != GL_NO_ERROR )
- {
- SAL_WARN("vcl.opengl", "glError: " << glGetError());
- }
- glXDestroyContext(m_aGLWin.dpy, m_aGLWin.ctx);
- m_aGLWin.ctx = nullptr;
- }
-#endif
+ destroyCurrentContext();
}
-#if defined(_WIN32) || defined( MACOSX ) || defined( IOS ) || defined( ANDROID )
-
-SystemWindowData OpenGLContext::generateWinData(vcl::Window* /*pParent*/, bool bRequestLegacyContext)
+SystemWindowData OpenGLContext::generateWinData(vcl::Window* /*pParent*/, bool /*bRequestLegacyContext*/)
{
- (void) bRequestLegacyContext;
SystemWindowData aWinData;
-#if defined(MACOSX)
- aWinData.bOpenGL = true;
- aWinData.bLegacy = bRequestLegacyContext;
-#endif
aWinData.nSize = sizeof(aWinData);
return aWinData;
}
-#elif defined( UNX )
-
-SystemWindowData OpenGLContext::generateWinData(vcl::Window* pParent, bool)
+bool OpenGLContext::isCurrent()
{
- OpenGLZone aZone;
-
- SystemWindowData aWinData;
- aWinData.nSize = sizeof(aWinData);
- aWinData.pVisual = nullptr;
-
-#if !defined(LIBO_HEADLESS)
- const SystemEnvData* sysData(pParent->GetSystemData());
-
- Display *dpy = static_cast<Display*>(sysData->pDisplay);
- Window win = sysData->aWindow;
-
- if( dpy == nullptr || !glXQueryExtension( dpy, nullptr, nullptr ) )
- return aWinData;
-
- initOpenGLFunctionPointers();
-
- int best_fbc = -1;
- GLXFBConfig* pFBC = getFBConfig(dpy, win, best_fbc, true, false);
+ (void) this; // loplugin:staticmethods
+ return false;
+}
- if (!pFBC)
- return aWinData;
+void OpenGLContext::makeCurrent()
+{
+ if (isCurrent())
+ return;
- XVisualInfo* vi = nullptr;
- if( best_fbc != -1 )
- vi = glXGetVisualFromFBConfig( dpy, pFBC[best_fbc] );
+ OpenGLZone aZone;
- XFree(pFBC);
+ clearCurrent();
- if( vi )
- {
- VCL_GL_INFO("using VisualID " << vi->visualid);
- aWinData.pVisual = static_cast<void*>(vi->visual);
- }
-#endif
+ // by default nothing else to do
- return aWinData;
+ registerAsCurrent();
}
-#endif
-
-bool OpenGLContext::isCurrent()
+bool OpenGLContext::isAnyCurrent()
{
- OpenGLZone aZone;
-
-#if defined(_WIN32)
- return wglGetCurrentContext() == m_aGLWin.hRC &&
- wglGetCurrentDC() == m_aGLWin.hDC;
-#elif defined( MACOSX )
- (void) this; // loplugin:staticmethods
- return false;
-#elif defined( IOS ) || defined( ANDROID ) || defined(LIBO_HEADLESS)
return false;
-#elif defined( UNX )
- return m_aGLWin.ctx && glXGetCurrentContext() == m_aGLWin.ctx &&
- glXGetCurrentDrawable() == m_aGLWin.win;
-#endif
}
bool OpenGLContext::hasCurrent()
{
-#if defined(_WIN32)
- return wglGetCurrentContext() != NULL;
-#elif defined( MACOSX ) || defined( IOS ) || defined( ANDROID ) || defined(LIBO_HEADLESS)
- return false;
-#elif defined( UNX )
- return glXGetCurrentContext() != None;
-#endif
+ ImplSVData* pSVData = ImplGetSVData();
+ rtl::Reference<OpenGLContext> pCurrentCtx = pSVData->maGDIData.mpLastContext;
+ return pCurrentCtx.is() && pCurrentCtx->isAnyCurrent();
}
void OpenGLContext::clearCurrent()
@@ -1402,45 +484,6 @@ void OpenGLContext::prepareForYield()
assert (!hasCurrent());
}
-void OpenGLContext::makeCurrent()
-{
- if (isCurrent())
- return;
-
- OpenGLZone aZone;
-
- clearCurrent();
-
-#if defined(_WIN32)
- if (!wglMakeCurrent(m_aGLWin.hDC, m_aGLWin.hRC))
- {
- SAL_WARN("vcl.opengl", "OpenGLContext::makeCurrent(): wglMakeCurrent failed: " << GetLastError());
- return;
- }
-#elif defined( MACOSX )
- NSOpenGLView* pView = getOpenGLView();
- [[pView openGLContext] makeCurrentContext];
-#elif defined( IOS ) || defined( ANDROID ) || defined(LIBO_HEADLESS)
- // nothing
-#elif defined( UNX )
-#ifdef DBG_UTIL
- TempErrorHandler aErrorHandler(m_aGLWin.dpy, unxErrorHandler);
-#endif
-
- if (m_aGLWin.dpy)
- {
- if (!glXMakeCurrent( m_aGLWin.dpy, m_aGLWin.win, m_aGLWin.ctx ))
- {
- SAL_WARN("vcl.opengl", "OpenGLContext::makeCurrent failed "
- "on drawable " << m_aGLWin.win);
- return;
- }
- }
-#endif
-
- registerAsCurrent();
-}
-
rtl::Reference<OpenGLContext> OpenGLContext::getVCLContext(bool bMakeIfNecessary)
{
ImplSVData* pSVData = ImplGetSVData();
@@ -1503,37 +546,17 @@ void OpenGLContext::registerAsCurrent()
void OpenGLContext::resetCurrent()
{
clearCurrent();
-
- OpenGLZone aZone;
-
-#if defined(_WIN32)
- wglMakeCurrent(NULL, NULL);
-#elif defined( MACOSX )
- (void) this; // loplugin:staticmethods
- [NSOpenGLContext clearCurrentContext];
-#elif defined( IOS ) || defined( ANDROID ) || defined(LIBO_HEADLESS)
- // nothing
-#elif defined( UNX )
- if (m_aGLWin.dpy)
- glXMakeCurrent(m_aGLWin.dpy, None, nullptr);
-#endif
+ // by default nothing else to do
}
void OpenGLContext::swapBuffers()
{
- OpenGLZone aZone;
-
-#if defined(_WIN32)
- SwapBuffers(m_aGLWin.hDC);
-#elif defined( MACOSX )
- NSOpenGLView* pView = getOpenGLView();
- [[pView openGLContext] flushBuffer];
-#elif defined( IOS ) || defined( ANDROID ) || defined(LIBO_HEADLESS)
- // nothing
-#elif defined( UNX )
- glXSwapBuffers(m_aGLWin.dpy, m_aGLWin.win);
-#endif
+ // by default nothing else to do
+ BuffersSwapped();
+}
+void OpenGLContext::BuffersSwapped()
+{
nBufferSwapCounter++;
static bool bSleep = getenv("SAL_GL_SLEEP_ON_SWAP");
@@ -1544,6 +567,7 @@ void OpenGLContext::swapBuffers()
}
}
+
sal_Int64 OpenGLWrapper::getBufferSwapCounter()
{
return nBufferSwapCounter;
@@ -1551,17 +575,8 @@ sal_Int64 OpenGLWrapper::getBufferSwapCounter()
void OpenGLContext::sync()
{
- OpenGLZone aZone;
-
-#if defined(_WIN32)
- // nothing
-#elif defined( MACOSX ) || defined( IOS ) || defined( ANDROID ) || defined(LIBO_HEADLESS)
+ // default is nothing
(void) this; // loplugin:staticmethods
- // nothing
-#elif defined( UNX )
- glXWaitGL();
- XSync(m_aGLWin.dpy, false);
-#endif
}
void OpenGLContext::show()
@@ -1587,13 +602,6 @@ bool OpenGLContext::supportMultiSampling() const
return m_aGLWin.bMultiSampleSupported;
}
-#if defined(MACOSX)
-NSOpenGLView* OpenGLContext::getOpenGLView()
-{
- return reinterpret_cast<NSOpenGLView*>(m_pChildWindow->GetSystemData()->mpNSView);
-}
-#endif
-
bool OpenGLContext::BindFramebuffer( OpenGLFramebuffer* pFramebuffer )
{
OpenGLZone aZone;
diff --git a/vcl/source/window/openglwin.cxx b/vcl/source/window/openglwin.cxx
index 3f95894181d1..442d1daa6483 100644
--- a/vcl/source/window/openglwin.cxx
+++ b/vcl/source/window/openglwin.cxx
@@ -26,7 +26,7 @@ private:
OpenGLWindowImpl::OpenGLWindowImpl(vcl::Window* pWindow)
: mxContext(OpenGLContext::Create())
{
- SystemWindowData aData = OpenGLContext::generateWinData(pWindow, false);
+ SystemWindowData aData = mxContext->generateWinData(pWindow, false);
mxChildWindow.reset(VclPtr<SystemChildWindow>::Create(pWindow, 0, &aData));
mxChildWindow->Show();
mxContext->init(mxChildWindow.get());