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
Friedemann Kleint 2011-10-26 16:09:37 +02:00 committed by Qt by Nokia
parent a144e0bfdc
commit 82d6518696
4 changed files with 156 additions and 91 deletions

View File

@ -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);

View File

@ -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 &);

View File

@ -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 {

View File

@ -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