summaryrefslogtreecommitdiffstats
path: root/vcl/source/opengl/win/context.cxx
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--vcl/source/opengl/win/context.cxx663
1 files changed, 663 insertions, 0 deletions
diff --git a/vcl/source/opengl/win/context.cxx b/vcl/source/opengl/win/context.cxx
new file mode 100644
index 000000000..5031ec6f0
--- /dev/null
+++ b/vcl/source/opengl/win/context.cxx
@@ -0,0 +1,663 @@
+/* -*- 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 <memory>
+#include <string_view>
+#include <thread>
+#include <vcl/opengl/OpenGLContext.hxx>
+#include <vcl/opengl/OpenGLHelper.hxx>
+#include <vcl/syschild.hxx>
+
+#include <sal/log.hxx>
+#include <comphelper/windowserrorstring.hxx>
+#include <opengl/zone.hxx>
+#include <win/wincomp.hxx>
+#include <win/saldata.hxx>
+#include <win/salframe.h>
+#include <win/salinst.h>
+#include <epoxy/wgl.h>
+#include <ControlCacheKey.hxx>
+
+static std::vector<HGLRC> g_vShareList;
+static bool g_bAnyCurrent;
+
+namespace {
+
+class GLWinWindow : public GLWindow
+{
+public:
+ HWND hWnd;
+ HDC hDC;
+ HGLRC hRC;
+ GLWinWindow();
+};
+
+}
+
+GLWinWindow::GLWinWindow()
+ : hWnd(nullptr)
+ , hDC(nullptr)
+ , hRC(nullptr)
+{
+}
+
+namespace {
+
+class WinOpenGLContext : public OpenGLContext
+{
+public:
+ virtual void initWindow() override;
+private:
+ GLWinWindow m_aGLWin;
+ virtual const GLWindow& getOpenGLWindow() const override { return m_aGLWin; }
+ virtual GLWindow& getModifiableOpenGLWindow() override { return m_aGLWin; }
+ 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(nullptr, nullptr);
+ g_bAnyCurrent = false;
+}
+
+static void ensureDispatchTable()
+{
+ thread_local bool bEpoxyDispatchMakeCurrentCalled = false;
+ if (!bEpoxyDispatchMakeCurrentCalled)
+ {
+ epoxy_handle_external_wglMakeCurrent();
+ bEpoxyDispatchMakeCurrentCalled = true;
+ }
+}
+
+bool WinOpenGLContext::isCurrent()
+{
+ OpenGLZone aZone;
+ if (!g_bAnyCurrent || !m_aGLWin.hRC)
+ return false;
+ ensureDispatchTable();
+ return wglGetCurrentContext() == m_aGLWin.hRC && wglGetCurrentDC() == m_aGLWin.hDC;
+}
+
+bool WinOpenGLContext::isAnyCurrent()
+{
+ return g_bAnyCurrent && wglGetCurrentContext() != nullptr;
+}
+
+void WinOpenGLContext::makeCurrent()
+{
+ if (isCurrent())
+ return;
+
+ OpenGLZone aZone;
+
+ clearCurrent();
+
+ ensureDispatchTable();
+
+ if (!wglMakeCurrent(m_aGLWin.hDC, m_aGLWin.hRC))
+ {
+ g_bAnyCurrent = false;
+ DWORD nLastError = GetLastError();
+ if (nLastError != ERROR_SUCCESS)
+ SAL_WARN("vcl.opengl", "wglMakeCurrent failed: " << WindowsErrorString(nLastError));
+ return;
+ }
+
+ g_bAnyCurrent = true;
+
+ registerAsCurrent();
+}
+
+void 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);
+}
+
+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() != nullptr)
+ {
+ wglMakeCurrent(nullptr, nullptr);
+ g_bAnyCurrent = false;
+ }
+ wglDeleteContext( m_aGLWin.hRC );
+ ReleaseDC( m_aGLWin.hWnd, m_aGLWin.hDC );
+ m_aGLWin.hRC = nullptr;
+ }
+}
+
+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;
+ default:
+ return DefWindowProcW(hwnd, message, wParam, lParam);
+ }
+}
+
+static bool InitTempWindow(HWND& hwnd, int width, int height, const PIXELFORMATDESCRIPTOR& inPfd, GLWinWindow& glWin)
+{
+ OpenGLZone aZone;
+
+ PIXELFORMATDESCRIPTOR pfd = inPfd;
+ int ret;
+ WNDCLASSW wc;
+ wc.style = 0;
+ wc.lpfnWndProc = WndProc;
+ wc.cbClsExtra = wc.cbWndExtra = 0;
+ wc.hInstance = nullptr;
+ wc.hIcon = nullptr;
+ wc.hCursor = nullptr;
+ wc.hbrBackground = nullptr;
+ wc.lpszMenuName = nullptr;
+ wc.lpszClassName = L"GLRenderer";
+ RegisterClassW(&wc);
+ hwnd = CreateWindowW(wc.lpszClassName, nullptr, WS_DISABLED, 0, 0, width, height, nullptr, nullptr, wc.hInstance, nullptr);
+ glWin.hDC = GetDC(hwnd);
+
+ int nPixelFormat = ChoosePixelFormat(glWin.hDC, &pfd);
+ if (!nPixelFormat)
+ {
+ ReleaseDC(hwnd, glWin.hDC);
+ DestroyWindow(hwnd);
+ return false;
+ }
+ ret = SetPixelFormat(glWin.hDC, nPixelFormat, &pfd);
+ if(!ret)
+ {
+ ReleaseDC(hwnd, glWin.hDC);
+ DestroyWindow(hwnd);
+ return false;
+ }
+ glWin.hRC = wglCreateContext(glWin.hDC);
+ if(!(glWin.hRC))
+ {
+ ReleaseDC(hwnd, glWin.hDC);
+ DestroyWindow(hwnd);
+ return false;
+ }
+ ret = wglMakeCurrent(glWin.hDC, glWin.hRC);
+ if(!ret)
+ {
+ wglMakeCurrent(nullptr, nullptr);
+ g_bAnyCurrent = false;
+ wglDeleteContext(glWin.hRC);
+ ReleaseDC(hwnd, glWin.hDC);
+ DestroyWindow(hwnd);
+ return false;
+ }
+ g_bAnyCurrent = false;
+
+ return true;
+}
+
+static bool WGLisExtensionSupported(const char *extension)
+{
+ OpenGLZone aZone;
+
+ const size_t extlen = strlen(extension);
+ const char *supported = nullptr;
+
+ // Try to use wglGetExtensionStringARB on current DC, if possible
+ PROC wglGetExtString = wglGetProcAddress("wglGetExtensionsStringARB");
+
+ if (wglGetExtString)
+ supported = reinterpret_cast<char*(__stdcall*)(HDC)>(wglGetExtString)(wglGetCurrentDC());
+ // If that failed, try standard OpenGL extensions string
+ if (supported == nullptr)
+ supported = reinterpret_cast<char const *>(glGetString(GL_EXTENSIONS));
+ // If that failed too, must be no extensions supported
+ if (supported == nullptr)
+ 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 == nullptr)
+ return false; // 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 true; // Match
+ }
+}
+
+static bool InitMultisample(const PIXELFORMATDESCRIPTOR& pfd, int& rPixelFormat,
+ bool bUseDoubleBufferedRendering, bool bRequestVirtualDevice)
+{
+ OpenGLZone aZone;
+
+ HWND hWnd = nullptr;
+ GLWinWindow glWin;
+ // Create a temp window to check whether support multi-sample, if support, get the format
+ if (!InitTempWindow(hWnd, 32, 32, pfd, glWin))
+ {
+ 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");
+ wglMakeCurrent(nullptr, nullptr);
+ g_bAnyCurrent = false;
+ wglDeleteContext(glWin.hRC);
+ ReleaseDC(hWnd, glWin.hDC);
+ DestroyWindow(hWnd);
+ return false;
+ }
+ // Get our pixel format
+ PFNWGLCHOOSEPIXELFORMATARBPROC fn_wglChoosePixelFormatARB = reinterpret_cast<PFNWGLCHOOSEPIXELFORMATARBPROC>(wglGetProcAddress("wglChoosePixelFormatARB"));
+ if (!fn_wglChoosePixelFormatARB)
+ {
+ wglMakeCurrent(nullptr, nullptr);
+ g_bAnyCurrent = false;
+ wglDeleteContext(glWin.hRC);
+ ReleaseDC(hWnd, glWin.hDC);
+ DestroyWindow(hWnd);
+ 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(nullptr, nullptr);
+ g_bAnyCurrent = false;
+ 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(nullptr, nullptr);
+ g_bAnyCurrent = false;
+ wglDeleteContext(glWin.hRC);
+ ReleaseDC(hWnd, glWin.hDC);
+ DestroyWindow(hWnd);
+ return bArbMultisampleSupported;
+ }
+ // Return the valid format
+ wglMakeCurrent(nullptr, nullptr);
+ g_bAnyCurrent = false;
+ wglDeleteContext(glWin.hRC);
+ ReleaseDC(hWnd, glWin.hDC);
+ DestroyWindow(hWnd);
+
+ return bArbMultisampleSupported;
+}
+
+namespace
+{
+
+bool tryShaders(const OUString& rVertexShader, const OUString& rFragmentShader, const OUString& rGeometryShader = "", std::string_view rPreamble = "")
+{
+ GLint nId;
+
+ // Somewhat mysteriously, the OpenGLHelper::LoadShaders() API saves a compiled binary of the
+ // shader only if you give it the digest of the shaders. We have API to calculate the digest
+ // only of the combination of vertex and fragment (but not geometry) shader. So if we have a
+ // geometry shader, we should not save the binary.
+ if (rGeometryShader.isEmpty())
+ {
+ nId = OpenGLHelper::LoadShaders(rVertexShader, rFragmentShader, rPreamble, OpenGLHelper::GetDigest( rVertexShader, rFragmentShader, rPreamble));
+ }
+ else
+ {
+ assert(rPreamble.empty());
+ nId = OpenGLHelper::LoadShaders(rVertexShader, rFragmentShader, rGeometryShader);
+ }
+ if (!nId)
+ return false;
+
+ // We're interested in the error returned by glDeleteProgram().
+ glGetError();
+
+ glDeleteProgram(nId);
+ return glGetError() == GL_NO_ERROR;
+}
+
+bool compiledShaderBinariesWork()
+{
+ static bool bBeenHere = false;
+ static bool bResult;
+
+ if (bBeenHere)
+ return bResult;
+
+ bBeenHere = true;
+
+ bResult =
+ (
+#if 0 // Only look at shaders used by slideshow for now
+ // canvas
+ tryShaders("dummyVertexShader", "linearMultiColorGradientFragmentShader") &&
+ tryShaders("dummyVertexShader", "linearTwoColorGradientFragmentShader") &&
+ tryShaders("dummyVertexShader", "radialMultiColorGradientFragmentShader") &&
+ tryShaders("dummyVertexShader", "radialTwoColorGradientFragmentShader") &&
+ tryShaders("dummyVertexShader", "rectangularMultiColorGradientFragmentShader") &&
+ tryShaders("dummyVertexShader", "rectangularTwoColorGradientFragmentShader") &&
+#endif
+ // slideshow
+ tryShaders("reflectionVertexShader", "reflectionFragmentShader") &&
+ tryShaders("basicVertexShader", "basicFragmentShader") &&
+ tryShaders("vortexVertexShader", "vortexFragmentShader", "vortexGeometryShader") &&
+ tryShaders("basicVertexShader", "rippleFragmentShader") &&
+ tryShaders("glitterVertexShader", "glitterFragmentShader") &&
+ tryShaders("honeycombVertexShader", "honeycombFragmentShader", "honeycombGeometryShader"));
+
+ return bResult;
+}
+
+} // unnamed namespace
+
+bool WinOpenGLContext::ImplInit()
+{
+ static bool bFirstCall = true;
+
+ 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
+ };
+
+ PixelFormatFront.dwFlags |= PFD_DOUBLEBUFFER;
+ PixelFormatFront.dwFlags |= PFD_DRAW_TO_WINDOW;
+
+ // we must check whether can set the MSAA
+ int WindowPix = 0;
+ bool bMultiSampleSupport = false;
+
+ bMultiSampleSupport = InitMultisample(PixelFormatFront, WindowPix, /*bUseDoubleBufferedRendering*/true, 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: " << static_cast<int>((pfd.dwFlags & PFD_DRAW_TO_WINDOW) != 0) << ", Bitmap: " << static_cast<int>((pfd.dwFlags & PFD_DRAW_TO_BITMAP) != 0));
+ SAL_WARN("vcl.opengl", "Supports OpenGL: " << static_cast<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))
+ {
+ SAL_WARN("vcl.opengl", "SetPixelFormat failed: " << WindowsErrorString(GetLastError()));
+ return false;
+ }
+
+ HGLRC hTempRC = wglCreateContext(m_aGLWin.hDC);
+ if (hTempRC == nullptr)
+ {
+ SAL_WARN("vcl.opengl", "wglCreateContext failed: "<< WindowsErrorString(GetLastError()));
+ return false;
+ }
+
+ if (!wglMakeCurrent(m_aGLWin.hDC, hTempRC))
+ {
+ g_bAnyCurrent = false;
+ SAL_WARN("vcl.opengl", "wglMakeCurrent failed: "<< WindowsErrorString(GetLastError()));
+ return false;
+ }
+
+ g_bAnyCurrent = true;
+
+ if (!InitGL())
+ {
+ wglMakeCurrent(nullptr, nullptr);
+ g_bAnyCurrent = false;
+ wglDeleteContext(hTempRC);
+ return false;
+ }
+
+ HGLRC hSharedCtx = nullptr;
+ if (!g_vShareList.empty())
+ hSharedCtx = g_vShareList.front();
+
+ if (!wglCreateContextAttribsARB)
+ {
+ wglMakeCurrent(nullptr, nullptr);
+ g_bAnyCurrent = false;
+ wglDeleteContext(hTempRC);
+ return false;
+ }
+
+ // now setup the shared context; this needs a temporary context already
+ // set up in order to work
+ int const 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 == nullptr)
+ {
+ SAL_WARN("vcl.opengl", "wglCreateContextAttribsARB failed: "<< WindowsErrorString(GetLastError()));
+ wglMakeCurrent(nullptr, nullptr);
+ g_bAnyCurrent = false;
+ wglDeleteContext(hTempRC);
+ return false;
+ }
+
+ if (!compiledShaderBinariesWork())
+ {
+ wglMakeCurrent(nullptr, nullptr);
+ g_bAnyCurrent = false;
+ wglDeleteContext(hTempRC);
+ return false;
+ }
+
+ wglMakeCurrent(nullptr, nullptr);
+ g_bAnyCurrent = false;
+ wglDeleteContext(hTempRC);
+
+ if (!wglMakeCurrent(m_aGLWin.hDC, m_aGLWin.hRC))
+ {
+ g_bAnyCurrent = false;
+ SAL_WARN("vcl.opengl", "wglMakeCurrent failed: " << WindowsErrorString(GetLastError()));
+ return false;
+ }
+
+ g_bAnyCurrent = true;
+
+ if (bFirstCall)
+ {
+ // Checking texture size
+ GLint nMaxTextureSize;
+ glGetIntegerv(GL_MAX_TEXTURE_SIZE, &nMaxTextureSize);
+ if (nMaxTextureSize <= 4096)
+ SAL_WARN("vcl.opengl", "Max texture size is " << nMaxTextureSize
+ << ". This may not be enough for normal operation.");
+ else
+ VCL_GL_INFO("Max texture size: " << nMaxTextureSize);
+
+ // Trying to make a texture and check its size
+ for (GLint nWidthHeight = 1023; nWidthHeight < nMaxTextureSize; nWidthHeight += (nWidthHeight + 1))
+ {
+ glTexImage2D(GL_PROXY_TEXTURE_2D, 0, 4, nWidthHeight, nWidthHeight, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, nullptr);
+ CHECK_GL_ERROR();
+ if (glGetError() == GL_NO_ERROR)
+ {
+ GLint nWidth = 0;
+ GLint nHeight = 0;
+ glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &nWidth);
+ glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &nHeight);
+ VCL_GL_INFO("Created texture " << nWidthHeight << "," << nWidthHeight << " reports size: " << nWidth << ", " << nHeight);
+ }
+ else
+ {
+ SAL_WARN("vcl.opengl", "Error when creating a " << nWidthHeight << ", " << nWidthHeight << " test texture.");
+ }
+ }
+ }
+
+ InitGLDebugging();
+
+ 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();
+
+ bFirstCall = false;
+
+ return true;
+}
+
+OpenGLContext* WinSalInstance::CreateOpenGLContext()
+{
+ return new WinOpenGLContext;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */