/* -*- 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/.
*/
// Hack: the performance of OpenGL increases with non-child window. // Also, this keeps the backing window opaque on GL context destruction, // which doesn't prevent the flicker (tdf#122737) completely, but at // least doesn't show user desktop during the flicker.
LONG_PTR style = GetWindowLongPtrW(sysData->hWnd, GWL_STYLE);
style &= ~WS_CHILD;
SetWindowLongPtrW(sysData->hWnd, GWL_STYLE, style);
m_aGLWin.hWnd = sysData->hWnd;
m_aGLWin.hDC = GetDC(m_aGLWin.hWnd);
}
void WinOpenGLContext::destroyCurrentContext()
{ if (m_aGLWin.hRC)
{
std::erase(g_vShareList, m_aGLWin.hRC);
// 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<charconst *>(glGetString(GL_EXTENSIONS)); // If that failed too, must be no extensions supported if (supported == nullptr) returnfalse;
// Begin examination at start of string, increment by 1 on false match for (constchar* p = supported; ; p++)
{ // Advance p up to the next possible match
p = strstr(p, extension);
if (p == nullptr) returnfalse; // 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]==' ')) returntrue; // Match
}
}
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"); returnfalse;
}
// 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); returnfalse;
} // 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); returnfalse;
} // 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);
// 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) returnfalse;
// We're interested in the error returned by glDeleteProgram().
glGetError();
// now setup the shared context; this needs a temporary context already // set up in order to work intconst 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: "<< comphelper::WindowsErrorString(GetLastError()));
wglMakeCurrent(nullptr, nullptr);
g_bAnyCurrent = false;
wglDeleteContext(hTempRC); returnfalse;
}
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.");
}
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.