Windows: Fix Open GL formats.
- Add swapInterval as additional format - Query context format correctly and store in separate struct (default vs requested/obtained) - Cosmetics, rename enumerations, structs. Change-Id: I381cf8e1bde33e6624feb549437c7b95dd85e93c Reviewed-by: Friedemann Kleint <Friedemann.Kleint@nokia.com>bb10
parent
a144e0bfdc
commit
82d6518696
|
|
@ -545,49 +545,6 @@ static QSurfaceFormat
|
|||
if (iValues[11])
|
||||
additionalIn->formatFlags |= QWindowsGLOverlay;
|
||||
}
|
||||
// Check version. Known to fail for some drivers
|
||||
if (staticContext.majorVersion > 1) {
|
||||
i = 0;
|
||||
iAttributes[i++] = WGL_CONTEXT_MAJOR_VERSION_ARB; // 0
|
||||
iAttributes[i++] = WGL_CONTEXT_MINOR_VERSION_ARB; // 1
|
||||
if (staticContext.wglGetPixelFormatAttribIVARB(hdc, pixelFormat, 0, i,
|
||||
iAttributes, iValues)) {
|
||||
result.setMajorVersion(iValues[0]);
|
||||
result.setMinorVersion(iValues[1]);
|
||||
} else {
|
||||
qErrnoWarning("%s: wglGetPixelFormatAttribIVARB() failed for version.", __FUNCTION__);
|
||||
}
|
||||
}
|
||||
// Query flags from 3.2 onwards
|
||||
if (staticContext.majorVersion > 3) {
|
||||
i = 0;
|
||||
iAttributes[i++] = WGL_CONTEXT_FLAGS_ARB; // 0
|
||||
if (staticContext.wglGetPixelFormatAttribIVARB(hdc, pixelFormat, 0, i,
|
||||
iAttributes, iValues)) {
|
||||
if (iValues[0] & WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB)
|
||||
result.setOption(QSurfaceFormat::DeprecatedFunctions);
|
||||
if (iValues[0] & WGL_CONTEXT_DEBUG_BIT_ARB)
|
||||
result.setOption(QSurfaceFormat::DebugContext);
|
||||
} else {
|
||||
qErrnoWarning("%s: wglGetPixelFormatAttribIVARB() failed for context flags.", __FUNCTION__);
|
||||
}
|
||||
}
|
||||
// Query profile from 3.2 onwards. Known to fail for some drivers
|
||||
if ((staticContext.majorVersion == 3 && staticContext.minorVersion >= 2)
|
||||
|| staticContext.majorVersion > 3) {
|
||||
i = 0;
|
||||
iAttributes[i++] = WGL_CONTEXT_PROFILE_MASK_ARB; // 0
|
||||
if (staticContext.wglGetPixelFormatAttribIVARB(hdc, pixelFormat, 0, i,
|
||||
iAttributes, iValues)) {
|
||||
if (iValues[0] & WGL_CONTEXT_CORE_PROFILE_BIT_ARB) {
|
||||
result.setProfile(QSurfaceFormat::CoreProfile);
|
||||
} else if (iValues[0] & WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB) {
|
||||
result.setProfile(QSurfaceFormat::CompatibilityProfile);
|
||||
}
|
||||
} else {
|
||||
qErrnoWarning("%s: wglGetPixelFormatAttribIVARB() failed for profile mask.", __FUNCTION__);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -604,22 +561,14 @@ static HGLRC createContext(const QOpenGLStaticContext &staticContext,
|
|||
int attributes[attribSize];
|
||||
int attribIndex = 0;
|
||||
qFill(attributes, attributes + attribSize, int(0));
|
||||
|
||||
const int formatMajorVersion = format.majorVersion();
|
||||
const int formatMinorVersion = format.minorVersion();
|
||||
const bool versionRequested = formatMajorVersion != 1 || formatMinorVersion != 1;
|
||||
const int majorVersion = versionRequested ?
|
||||
formatMajorVersion : staticContext.majorVersion;
|
||||
const int minorVersion = versionRequested ?
|
||||
formatMinorVersion : staticContext.minorVersion;
|
||||
|
||||
if (majorVersion > 1) {
|
||||
const int requestedVersion = (format.majorVersion() << 8) + format.minorVersion();
|
||||
if (requestedVersion > 0x0101) {
|
||||
attributes[attribIndex++] = WGL_CONTEXT_MAJOR_VERSION_ARB;
|
||||
attributes[attribIndex++] = majorVersion;
|
||||
attributes[attribIndex++] = format.majorVersion();
|
||||
attributes[attribIndex++] = WGL_CONTEXT_MINOR_VERSION_ARB;
|
||||
attributes[attribIndex++] = minorVersion;
|
||||
attributes[attribIndex++] = format.minorVersion();
|
||||
}
|
||||
if (majorVersion >= 3) {
|
||||
if (requestedVersion >= 0x0300) {
|
||||
attributes[attribIndex++] = WGL_CONTEXT_FLAGS_ARB;
|
||||
attributes[attribIndex] = 0;
|
||||
if (format.testOption(QSurfaceFormat::DeprecatedFunctions))
|
||||
|
|
@ -628,8 +577,7 @@ static HGLRC createContext(const QOpenGLStaticContext &staticContext,
|
|||
attributes[attribIndex++] |= WGL_CONTEXT_DEBUG_BIT_ARB;
|
||||
attribIndex++;
|
||||
}
|
||||
if ((majorVersion == 3 && minorVersion >= 2)
|
||||
|| majorVersion > 3) {
|
||||
if (requestedVersion >= 0x0302) {
|
||||
switch (format.profile()) {
|
||||
case QSurfaceFormat::NoProfile:
|
||||
break;
|
||||
|
|
@ -645,7 +593,7 @@ static HGLRC createContext(const QOpenGLStaticContext &staticContext,
|
|||
}
|
||||
if (QWindowsContext::verboseGL)
|
||||
qDebug("%s: Creating context version %d.%d with %d attributes",
|
||||
__FUNCTION__, majorVersion, minorVersion, attribIndex / 2);
|
||||
__FUNCTION__, format.majorVersion(), format.minorVersion(), attribIndex / 2);
|
||||
|
||||
const HGLRC result =
|
||||
staticContext.wglCreateContextAttribsARB(hdc, shared, attributes);
|
||||
|
|
@ -707,6 +655,85 @@ static inline QOpenGLContextData createDummyWindowOpenGLContextData()
|
|||
return result;
|
||||
}
|
||||
|
||||
/*!
|
||||
\class QOpenGLContextFormat
|
||||
\brief Format options that are related to the context (not pixelformats)
|
||||
|
||||
Provides utility function to retrieve from currently active
|
||||
context and to apply to a QSurfaceFormat.
|
||||
|
||||
\ingroup qt-lighthouse-win
|
||||
*/
|
||||
|
||||
QWindowsOpenGLContextFormat::QWindowsOpenGLContextFormat() :
|
||||
profile(QSurfaceFormat::NoProfile),
|
||||
version(0),
|
||||
options(0)
|
||||
{
|
||||
}
|
||||
|
||||
QWindowsOpenGLContextFormat QWindowsOpenGLContextFormat::current()
|
||||
{
|
||||
QWindowsOpenGLContextFormat result;
|
||||
const QByteArray version = QOpenGLStaticContext::getGlString(GL_VERSION);
|
||||
const int majorDot = version.indexOf('.');
|
||||
if (majorDot != -1) {
|
||||
int minorDot = version.indexOf('.', majorDot + 1);
|
||||
if (minorDot == -1)
|
||||
minorDot = version.size();
|
||||
result.version = (version.mid(0, majorDot).toInt() << 8)
|
||||
+ version.mid(majorDot + 1, minorDot - majorDot - 1).toInt();
|
||||
}
|
||||
if (result.version < 0x0300) {
|
||||
result.profile = QSurfaceFormat::NoProfile;
|
||||
result.options |= QSurfaceFormat::DeprecatedFunctions;
|
||||
return result;
|
||||
}
|
||||
// v3 onwards
|
||||
GLint value = 0;
|
||||
glGetIntegerv(GL_CONTEXT_FLAGS, &value);
|
||||
if (value & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT)
|
||||
result.options |= QSurfaceFormat::DeprecatedFunctions;
|
||||
if (value & WGL_CONTEXT_DEBUG_BIT_ARB)
|
||||
result.options |= QSurfaceFormat::DebugContext;
|
||||
if (result.version < 0x0302)
|
||||
return result;
|
||||
// v3.2 onwards: Profiles
|
||||
value = 0;
|
||||
glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &value);
|
||||
switch (value) {
|
||||
case WGL_CONTEXT_CORE_PROFILE_BIT_ARB:
|
||||
result.profile = QSurfaceFormat::CoreProfile;
|
||||
break;
|
||||
case WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB:
|
||||
result.profile = QSurfaceFormat::CompatibilityProfile;
|
||||
break;
|
||||
default:
|
||||
result.profile = QSurfaceFormat::NoProfile;
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void QWindowsOpenGLContextFormat::apply(QSurfaceFormat *format) const
|
||||
{
|
||||
format->setMajorVersion(version >> 8);
|
||||
format->setMinorVersion(version & 0xFF);
|
||||
format->setProfile(profile);
|
||||
if (options & QSurfaceFormat::DebugContext)
|
||||
format->setOption(QSurfaceFormat::DebugContext);
|
||||
if (options & QSurfaceFormat::DeprecatedFunctions)
|
||||
format->setOption(QSurfaceFormat::DeprecatedFunctions);
|
||||
}
|
||||
|
||||
QDebug operator<<(QDebug d, const QWindowsOpenGLContextFormat &f)
|
||||
{
|
||||
d.nospace() << "ContextFormat: v" << (f.version >> 8) << '.'
|
||||
<< (f.version & 0xFF) << " profile: " << f.profile
|
||||
<< " options: " << f.options;
|
||||
return d;
|
||||
}
|
||||
|
||||
/*!
|
||||
\class QOpenGLTemporaryContext
|
||||
\brief A temporary context that can be instantiated on the stack.
|
||||
|
|
@ -768,29 +795,17 @@ QOpenGLStaticContext::QOpenGLStaticContext() :
|
|||
vendor(QOpenGLStaticContext::getGlString(GL_VENDOR)),
|
||||
renderer(QOpenGLStaticContext::getGlString(GL_RENDERER)),
|
||||
extensionNames(QOpenGLStaticContext::getGlString(GL_EXTENSIONS)),
|
||||
majorVersion(0), minorVersion(0),
|
||||
extensions(0),
|
||||
defaultFormat(QWindowsOpenGLContextFormat::current()),
|
||||
wglGetPixelFormatAttribIVARB((WglGetPixelFormatAttribIVARB)wglGetProcAddress("wglGetPixelFormatAttribivARB")),
|
||||
wglChoosePixelFormatARB((WglChoosePixelFormatARB)wglGetProcAddress("wglChoosePixelFormatARB")),
|
||||
wglCreateContextAttribsARB((WglCreateContextAttribsARB)wglGetProcAddress("wglCreateContextAttribsARB"))
|
||||
wglCreateContextAttribsARB((WglCreateContextAttribsARB)wglGetProcAddress("wglCreateContextAttribsARB")),
|
||||
wglSwapInternalExt((WglSwapInternalExt)wglGetProcAddress("wglSwapIntervalEXT")),
|
||||
wglGetSwapInternalExt((WglGetSwapInternalExt)wglGetProcAddress("wglGetSwapIntervalEXT"))
|
||||
{
|
||||
if (extensionNames.startsWith(SAMPLE_BUFFER_EXTENSION" ")
|
||||
|| extensionNames.indexOf(" "SAMPLE_BUFFER_EXTENSION" ") != -1)
|
||||
extensions |= SampleBuffers;
|
||||
// Get version
|
||||
do {
|
||||
const QByteArray version = QOpenGLStaticContext::getGlString(GL_VERSION);
|
||||
if (version.isEmpty())
|
||||
break;
|
||||
const int majorDot = version.indexOf('.');
|
||||
if (majorDot == -1)
|
||||
break;
|
||||
int minorDot = version.indexOf('.', majorDot + 1);
|
||||
if (minorDot == -1)
|
||||
minorDot = version.size();
|
||||
majorVersion = version.mid(0, majorDot).toInt();
|
||||
minorVersion = version.mid(majorDot + 1, minorDot - majorDot - 1).toInt();
|
||||
} while (false);
|
||||
}
|
||||
|
||||
QByteArray QOpenGLStaticContext::getGlString(unsigned int which)
|
||||
|
|
@ -815,13 +830,15 @@ QOpenGLStaticContext *QOpenGLStaticContext::create()
|
|||
QDebug operator<<(QDebug d, const QOpenGLStaticContext &s)
|
||||
{
|
||||
QDebug nsp = d.nospace();
|
||||
nsp << "OpenGL: " << s.vendor << ',' << s.renderer << ",v"
|
||||
<< s.majorVersion << '.' << s.minorVersion;
|
||||
nsp << "OpenGL: " << s.vendor << ',' << s.renderer << " default "
|
||||
<< s.defaultFormat;
|
||||
if (s.extensions & QOpenGLStaticContext::SampleBuffers)
|
||||
nsp << ",SampleBuffers";
|
||||
if (s.hasExtensions())
|
||||
nsp << ", Extension-API present";
|
||||
nsp << "\nExtensions: " << s.extensionNames;
|
||||
nsp << "\nExtensions: " << (s.extensionNames.count(' ') + 1);
|
||||
if (QWindowsContext::verboseGL > 1)
|
||||
nsp << s.extensionNames;
|
||||
return d;
|
||||
}
|
||||
|
||||
|
|
@ -872,6 +889,7 @@ QWindowsGLContext::QWindowsGLContext(const QOpenGLStaticContextPtr &staticContex
|
|||
HWND dummyWindow = 0;
|
||||
HDC hdc = 0;
|
||||
bool tryExtensions = false;
|
||||
int obtainedSwapInternal = -1;
|
||||
do {
|
||||
dummyWindow = createDummyGLWindow();
|
||||
if (!dummyWindow)
|
||||
|
|
@ -934,6 +952,21 @@ QWindowsGLContext::QWindowsGLContext(const QOpenGLStaticContextPtr &staticContex
|
|||
qWarning("Unable to create a GL Context.");
|
||||
break;
|
||||
}
|
||||
|
||||
// Query obtained parameters and apply swap interval.
|
||||
if (!wglMakeCurrent(hdc, m_renderingContext)) {
|
||||
qWarning("Failed to make context current.");
|
||||
break;
|
||||
}
|
||||
|
||||
QWindowsOpenGLContextFormat::current().apply(&m_obtainedFormat);
|
||||
|
||||
if (requestedAdditional.swapInterval != -1 && m_staticContext->wglSwapInternalExt) {
|
||||
m_staticContext->wglSwapInternalExt(requestedAdditional.swapInterval);
|
||||
if (m_staticContext->wglGetSwapInternalExt)
|
||||
obtainedSwapInternal = m_staticContext->wglGetSwapInternalExt();
|
||||
}
|
||||
wglMakeCurrent(0, 0);
|
||||
} while (false);
|
||||
if (hdc)
|
||||
ReleaseDC(dummyWindow, hdc);
|
||||
|
|
@ -945,6 +978,8 @@ QWindowsGLContext::QWindowsGLContext(const QOpenGLStaticContextPtr &staticContex
|
|||
<< " requested: " << context->format()
|
||||
<< "\n obtained #" << m_pixelFormat << (m_extensionsUsed ? "ARB" : "GDI")
|
||||
<< m_obtainedFormat << "\n " << m_obtainedPixelFormatDescriptor
|
||||
<< " swap interval: " << obtainedSwapInternal
|
||||
<< "\n default: " << m_staticContext->defaultFormat
|
||||
<< "\n HGLRC=" << m_renderingContext;
|
||||
}
|
||||
|
||||
|
|
@ -1012,13 +1047,15 @@ bool QWindowsGLContext::makeCurrent(QPlatformSurface *surface)
|
|||
return false;
|
||||
// Initialize pixel format first time. This will apply to
|
||||
// the HWND as well and must be done only once.
|
||||
if (!window->testFlag(QWindowsWindow::PixelFormatInitialized)) {
|
||||
if (!window->testFlag(QWindowsWindow::OpenGlPixelFormatInitialized)) {
|
||||
if (!SetPixelFormat(newContext.hdc, m_pixelFormat, &m_obtainedPixelFormatDescriptor)) {
|
||||
qErrnoWarning("%s: SetPixelFormat() failed", __FUNCTION__);
|
||||
ReleaseDC(newContext.hwnd, newContext.hdc);
|
||||
return false;
|
||||
}
|
||||
window->setFlag(QWindowsWindow::PixelFormatInitialized);
|
||||
window->setFlag(QWindowsWindow::OpenGlPixelFormatInitialized);
|
||||
if (m_obtainedFormat.swapBehavior() == QSurfaceFormat::DoubleBuffer)
|
||||
window->setFlag(QWindowsWindow::OpenGLDoubleBuffered);
|
||||
}
|
||||
m_windowContexts.append(newContext);
|
||||
return wglMakeCurrent(newContext.hdc, newContext.renderingContext);
|
||||
|
|
|
|||
|
|
@ -64,10 +64,11 @@ enum QWindowsGLFormatFlags
|
|||
// Additional format information for Windows.
|
||||
struct QWindowsOpenGLAdditionalFormat
|
||||
{
|
||||
QWindowsOpenGLAdditionalFormat(unsigned formatFlagsIn = 0, unsigned pixmapDepthIn = 0) :
|
||||
formatFlags(formatFlagsIn), pixmapDepth(pixmapDepthIn) {}
|
||||
QWindowsOpenGLAdditionalFormat(unsigned formatFlagsIn = 0, unsigned pixmapDepthIn = 0, unsigned swapIntervalIn = -1) :
|
||||
formatFlags(formatFlagsIn), pixmapDepth(pixmapDepthIn), swapInterval(swapIntervalIn) {}
|
||||
unsigned formatFlags; // QWindowsGLFormatFlags.
|
||||
unsigned pixmapDepth; // for QWindowsGLRenderToPixmap
|
||||
int swapInterval;
|
||||
};
|
||||
|
||||
// Per-window data for active OpenGL contexts.
|
||||
|
|
@ -81,6 +82,19 @@ struct QOpenGLContextData
|
|||
HDC hdc;
|
||||
};
|
||||
|
||||
struct QWindowsOpenGLContextFormat
|
||||
{
|
||||
QWindowsOpenGLContextFormat();
|
||||
static QWindowsOpenGLContextFormat current();
|
||||
void apply(QSurfaceFormat *format) const;
|
||||
|
||||
QSurfaceFormat::OpenGLContextProfile profile;
|
||||
int version; //! majorVersion<<8 + minorVersion
|
||||
QSurfaceFormat::FormatOptions options;
|
||||
};
|
||||
|
||||
QDebug operator<<(QDebug d, const QWindowsOpenGLContextFormat &);
|
||||
|
||||
class QOpenGLStaticContext
|
||||
{
|
||||
Q_DISABLE_COPY(QOpenGLStaticContext)
|
||||
|
|
@ -104,6 +118,11 @@ public:
|
|||
typedef HGLRC
|
||||
(APIENTRY *WglCreateContextAttribsARB)(HDC, HGLRC, const int *);
|
||||
|
||||
typedef BOOL
|
||||
(APIENTRY *WglSwapInternalExt)(int interval);
|
||||
typedef int
|
||||
(APIENTRY *WglGetSwapInternalExt)(void);
|
||||
|
||||
bool hasExtensions() const
|
||||
{ return wglGetPixelFormatAttribIVARB && wglChoosePixelFormatARB && wglCreateContextAttribsARB; }
|
||||
|
||||
|
|
@ -113,13 +132,14 @@ public:
|
|||
const QByteArray vendor;
|
||||
const QByteArray renderer;
|
||||
const QByteArray extensionNames;
|
||||
int majorVersion;
|
||||
int minorVersion;
|
||||
unsigned extensions;
|
||||
const QWindowsOpenGLContextFormat defaultFormat;
|
||||
|
||||
WglGetPixelFormatAttribIVARB wglGetPixelFormatAttribIVARB;
|
||||
WglChoosePixelFormatARB wglChoosePixelFormatARB;
|
||||
WglCreateContextAttribsARB wglCreateContextAttribsARB;
|
||||
WglSwapInternalExt wglSwapInternalExt;
|
||||
WglGetSwapInternalExt wglGetSwapInternalExt;
|
||||
};
|
||||
|
||||
QDebug operator<<(QDebug d, const QOpenGLStaticContext &);
|
||||
|
|
|
|||
|
|
@ -617,7 +617,7 @@ QWindowsWindow::QWindowsWindow(QWindow *aWindow, const WindowData &data) :
|
|||
m_dropTarget(0)
|
||||
{
|
||||
if (aWindow->surfaceType() == QWindow::OpenGLSurface)
|
||||
setFlag(OpenGL_Surface);
|
||||
setFlag(OpenGLSurface);
|
||||
QWindowsContext::instance()->addWindow(m_data.hwnd, this);
|
||||
if (aWindow->isTopLevel()) {
|
||||
switch (aWindow->windowType()) {
|
||||
|
|
@ -779,9 +779,14 @@ void QWindowsWindow::setParent_sys(const QPlatformWindow *parent) const
|
|||
parentHWND = parentW->handle();
|
||||
|
||||
}
|
||||
|
||||
const bool wasTopLevel = window()->isTopLevel();
|
||||
const bool isTopLevel = parentHWND == 0;
|
||||
|
||||
setFlag(WithinSetParent);
|
||||
SetParent(m_data.hwnd, parentHWND);
|
||||
clearFlag(WithinSetParent);
|
||||
|
||||
// WS_CHILD/WS_POPUP must be manually set/cleared in addition
|
||||
// to dialog frames, etc (see SetParent() ) if the top level state changes.
|
||||
if (wasTopLevel != isTopLevel) {
|
||||
|
|
@ -841,7 +846,8 @@ void QWindowsWindow::setGeometry(const QRect &rect)
|
|||
|
||||
void QWindowsWindow::handleMoved()
|
||||
{
|
||||
if (!IsIconic(m_data.hwnd)) // Minimize can send nonsensical move events.
|
||||
// Minimize/Set parent can send nonsensical move events.
|
||||
if (!IsIconic(m_data.hwnd) && !testFlag(WithinSetParent))
|
||||
handleGeometryChange();
|
||||
}
|
||||
|
||||
|
|
@ -940,7 +946,7 @@ void QWindowsWindow::handleWmPaint(HWND hwnd, UINT,
|
|||
WPARAM, LPARAM)
|
||||
{
|
||||
PAINTSTRUCT ps;
|
||||
if (testFlag(OpenGL_Surface)) {
|
||||
if (testFlag(OpenGLSurface)) {
|
||||
BeginPaint(hwnd, &ps); // WM_ERASEBKGND needs to be handled.
|
||||
EndPaint(hwnd, &ps);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -95,10 +95,12 @@ class QWindowsWindow : public QPlatformWindow
|
|||
public:
|
||||
enum Flags
|
||||
{
|
||||
OpenGL_Surface = 0x1,
|
||||
WithinWmPaint = 0x2,
|
||||
PixelFormatInitialized = 0x4,
|
||||
FrameDirty = 0x8 //! Frame outdated by setStyle, recalculate in next query.
|
||||
WithinWmPaint = 0x1,
|
||||
WithinSetParent = 0x2,
|
||||
FrameDirty = 0x4, //! Frame outdated by setStyle, recalculate in next query.
|
||||
OpenGLSurface = 0x10,
|
||||
OpenGLDoubleBuffered = 0x20,
|
||||
OpenGlPixelFormatInitialized = 0x40
|
||||
};
|
||||
|
||||
struct WindowData
|
||||
|
|
|
|||
Loading…
Reference in New Issue