summaryrefslogtreecommitdiffstats
path: root/src/opengl
diff options
context:
space:
mode:
Diffstat (limited to 'src/opengl')
-rw-r--r--src/opengl/qgl.cpp97
-rw-r--r--src/opengl/qgl.h1
-rw-r--r--src/opengl/qgl_mac.mm110
-rw-r--r--src/opengl/qgl_p.h95
-rw-r--r--src/opengl/qgl_qws.cpp54
-rw-r--r--src/opengl/qgl_win.cpp100
-rw-r--r--src/opengl/qgl_wince.cpp36
-rw-r--r--src/opengl/qgl_x11.cpp138
-rw-r--r--src/opengl/qgl_x11egl.cpp194
-rw-r--r--src/opengl/qglframebufferobject.cpp12
-rw-r--r--src/opengl/qglpixelbuffer_mac.mm4
-rw-r--r--src/opengl/qglpixelbuffer_p.h1
-rw-r--r--src/opengl/qglpixelbuffer_win.cpp14
-rw-r--r--src/opengl/qpaintengine_opengl.cpp46
-rw-r--r--src/opengl/qwindowsurface_gl.cpp7
15 files changed, 475 insertions, 434 deletions
diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp
index 1105028..b7139a2 100644
--- a/src/opengl/qgl.cpp
+++ b/src/opengl/qgl.cpp
@@ -124,9 +124,6 @@ public:
};
Q_GLOBAL_STATIC(QGLDefaultOverlayFormat, defaultOverlayFormatInstance)
-QGLExtensions::Extensions QGLExtensions::glExtensions = 0;
-bool QGLExtensions::nvidiaFboNeedsFinish = false;
-
Q_GLOBAL_STATIC(QGLSignalProxy, theSignalProxy)
QGLSignalProxy *QGLSignalProxy::instance()
{
@@ -154,11 +151,9 @@ public:
// falling back to the GL 1 engine..
static bool mac_x1600_check_done = false;
if (!mac_x1600_check_done) {
- QGLWidget *tmp = 0;
- if (!QGLContext::currentContext()) {
- tmp = new QGLWidget();
- tmp->makeCurrent();
- }
+ QGLTemporaryContext *tmp = 0;
+ if (!QGLContext::currentContext())
+ tmp = new QGLTemporaryContext();
if (strstr((char *) glGetString(GL_RENDERER), "X1600"))
engineType = QPaintEngine::OpenGL;
if (tmp)
@@ -178,7 +173,7 @@ public:
// from an old GL 1.1 server to a GL 2.x client. In that case we can't
// use GL 2.0.
if ((QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_2_0)
- && (QGLExtensions::glExtensions & QGLExtensions::FragmentShader)
+ && (QGLExtensions::glExtensions() & QGLExtensions::FragmentShader)
&& qgetenv("QT_GL_USE_OPENGL1ENGINE").isEmpty())
engineType = QPaintEngine::OpenGL2;
else
@@ -1345,7 +1340,7 @@ QGLFormat::OpenGLVersionFlags QGLFormat::openGLVersionFlags()
static bool cachedDefault = false;
static OpenGLVersionFlags defaultVersionFlags = OpenGL_Version_None;
QGLContext *currentCtx = const_cast<QGLContext *>(QGLContext::currentContext());
- QGLWidget *dummy = 0;
+ QGLTemporaryContext *tmpContext = 0;
if (currentCtx && currentCtx->d_func()->version_flags_cached)
return currentCtx->d_func()->version_flags;
@@ -1356,8 +1351,7 @@ QGLFormat::OpenGLVersionFlags QGLFormat::openGLVersionFlags()
} else {
if (!hasOpenGL())
return defaultVersionFlags;
- dummy = new QGLWidget;
- dummy->makeCurrent(); // glGetString() needs a current context
+ tmpContext = new QGLTemporaryContext;
cachedDefault = true;
}
}
@@ -1368,9 +1362,9 @@ QGLFormat::OpenGLVersionFlags QGLFormat::openGLVersionFlags()
currentCtx->d_func()->version_flags_cached = true;
currentCtx->d_func()->version_flags = versionFlags;
}
- if (dummy) {
+ if (tmpContext) {
defaultVersionFlags = versionFlags;
- delete dummy;
+ delete tmpContext;
}
return versionFlags;
@@ -1594,6 +1588,8 @@ void QGLContextPrivate::init(QPaintDevice *dev, const QGLFormat &format)
max_texture_size = -1;
version_flags_cached = false;
version_flags = QGLFormat::OpenGL_Version_None;
+ extension_flags_cached = false;
+ extension_flags = 0;
current_fbo = 0;
default_fbo = 0;
active_engine = 0;
@@ -2248,7 +2244,7 @@ QGLTexture* QGLContextPrivate::bindTexture(const QImage &image, GLenum target, G
int tx_h = qt_next_power_of_two(image.height());
QImage img = image;
- if (!(QGLExtensions::glExtensions & QGLExtensions::NPOTTextures)
+ if (!(QGLExtensions::glExtensions() & QGLExtensions::NPOTTextures)
&& !(QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_ES_Version_2_0)
&& (target == GL_TEXTURE_2D && (tx_w != image.width() || tx_h != image.height())))
{
@@ -2270,7 +2266,7 @@ QGLTexture* QGLContextPrivate::bindTexture(const QImage &image, GLenum target, G
bool genMipmap = false;
#endif
if (glFormat.directRendering()
- && (QGLExtensions::glExtensions & QGLExtensions::GenerateMipmap)
+ && (QGLExtensions::glExtensions() & QGLExtensions::GenerateMipmap)
&& target == GL_TEXTURE_2D
&& (options & QGLContext::MipmapBindOption))
{
@@ -2298,9 +2294,12 @@ QGLTexture* QGLContextPrivate::bindTexture(const QImage &image, GLenum target, G
bool premul = options & QGLContext::PremultipliedAlphaBindOption;
GLenum externalFormat;
GLuint pixel_type;
- if (QGLExtensions::glExtensions & QGLExtensions::BGRATextureFormat) {
+ if (QGLExtensions::glExtensions() & QGLExtensions::BGRATextureFormat) {
externalFormat = GL_BGRA;
- pixel_type = GL_UNSIGNED_INT_8_8_8_8_REV;
+ if (QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_1_2)
+ pixel_type = GL_UNSIGNED_INT_8_8_8_8_REV;
+ else
+ pixel_type = GL_UNSIGNED_BYTE;
} else {
externalFormat = GL_RGBA;
pixel_type = GL_UNSIGNED_BYTE;
@@ -2379,12 +2378,9 @@ QGLTexture* QGLContextPrivate::bindTexture(const QImage &image, GLenum target, G
qgl_byteSwapImage(img, pixel_type);
}
#ifdef QT_OPENGL_ES
- // OpenGL/ES requires that the internal and external formats be identical.
- // This is typically used to convert GL_RGBA into GL_BGRA.
- // Also, we need to use GL_UNSIGNED_BYTE when the format is GL_BGRA.
+ // OpenGL/ES requires that the internal and external formats be
+ // identical.
internalFormat = externalFormat;
- if (pixel_type == GL_UNSIGNED_INT_8_8_8_8_REV)
- pixel_type = GL_UNSIGNED_BYTE;
#endif
#ifdef QGL_BIND_TEXTURE_DEBUG
printf(" - uploading, image.format=%d, externalFormat=0x%x, internalFormat=0x%x, pixel_type=0x%x\n",
@@ -4969,9 +4965,13 @@ QGLWidget::QGLWidget(QGLContext *context, QWidget *parent,
#endif // QT3_SUPPORT
-void QGLExtensions::init_extensions()
+/*
+ Returns the GL extensions for the current context.
+*/
+QGLExtensions::Extensions QGLExtensions::currentContextExtensions()
{
QGLExtensionMatcher extensions(reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS)));
+ Extensions glExtensions;
if (extensions.match("GL_ARB_texture_rectangle"))
glExtensions |= TextureRectangle;
@@ -5032,6 +5032,46 @@ void QGLExtensions::init_extensions()
if (extensions.match("GL_EXT_bgra"))
glExtensions |= BGRATextureFormat;
+
+ return glExtensions;
+}
+
+/*
+ Returns the GL extensions for the current QGLContext. If there is no
+ current QGLContext, a default context will be created and the extensions
+ for that context will be returned instead.
+*/
+QGLExtensions::Extensions QGLExtensions::glExtensions()
+{
+ QGLTemporaryContext *tmpContext = 0;
+ static bool cachedDefault = false;
+ static Extensions defaultExtensions = 0;
+ QGLContext *currentCtx = const_cast<QGLContext *>(QGLContext::currentContext());
+
+ if (currentCtx && currentCtx->d_func()->extension_flags_cached)
+ return currentCtx->d_func()->extension_flags;
+
+ if (!currentCtx) {
+ if (cachedDefault) {
+ return defaultExtensions;
+ } else {
+ tmpContext = new QGLTemporaryContext;
+ cachedDefault = true;
+ }
+ }
+
+ Extensions extensionFlags = currentContextExtensions();
+ if (currentCtx) {
+ currentCtx->d_func()->extension_flags_cached = true;
+ currentCtx->d_func()->extension_flags = extensionFlags;
+ } else {
+ defaultExtensions = extensionFlags;
+ }
+
+ if (tmpContext)
+ delete tmpContext;
+
+ return extensionFlags;
}
/*
@@ -5043,7 +5083,6 @@ void QGLWidgetPrivate::initContext(QGLContext *context, const QGLWidget* shareWi
glDevice.setWidget(q);
- QGLExtensions::init();
glcx = 0;
autoSwap = true;
@@ -5292,7 +5331,7 @@ QSize QGLTexture::bindCompressedTexture
}
#if !defined(QT_OPENGL_ES)
if (!glCompressedTexImage2D) {
- if (!(QGLExtensions::glExtensions & QGLExtensions::TextureCompression)) {
+ if (!(QGLExtensions::glExtensions() & QGLExtensions::TextureCompression)) {
qWarning("QGLContext::bindTexture(): The GL implementation does "
"not support texture compression extensions.");
return QSize();
@@ -5331,7 +5370,7 @@ QSize QGLTexture::bindCompressedTextureDDS(const char *buf, int len)
return QSize();
// Bail out if the necessary extension is not present.
- if (!(QGLExtensions::glExtensions & QGLExtensions::DDSTextureCompression)) {
+ if (!(QGLExtensions::glExtensions() & QGLExtensions::DDSTextureCompression)) {
qWarning("QGLContext::bindTexture(): DDS texture compression is not supported.");
return QSize();
}
@@ -5441,13 +5480,13 @@ QSize QGLTexture::bindCompressedTexturePVR(const char *buf, int len)
// Bail out if the necessary extension is not present.
if (textureFormat == GL_ETC1_RGB8_OES) {
- if (!(QGLExtensions::glExtensions &
+ if (!(QGLExtensions::glExtensions() &
QGLExtensions::ETC1TextureCompression)) {
qWarning("QGLContext::bindTexture(): ETC1 texture compression is not supported.");
return QSize();
}
} else {
- if (!(QGLExtensions::glExtensions &
+ if (!(QGLExtensions::glExtensions() &
QGLExtensions::PVRTCTextureCompression)) {
qWarning("QGLContext::bindTexture(): PVRTC texture compression is not supported.");
return QSize();
diff --git a/src/opengl/qgl.h b/src/opengl/qgl.h
index e7142fd..8ada8ce 100644
--- a/src/opengl/qgl.h
+++ b/src/opengl/qgl.h
@@ -418,6 +418,7 @@ private:
friend class QGLContextGroup;
friend class QGLSharedResourceGuard;
friend class QGLPixmapBlurFilter;
+ friend class QGLExtensions;
friend QGLFormat::OpenGLVersionFlags QGLFormat::openGLVersionFlags();
#ifdef Q_WS_MAC
public:
diff --git a/src/opengl/qgl_mac.mm b/src/opengl/qgl_mac.mm
index 6ed07e5..c01575b 100644
--- a/src/opengl/qgl_mac.mm
+++ b/src/opengl/qgl_mac.mm
@@ -116,6 +116,68 @@ extern void qt_mac_dispose_rgn(RgnHandle); //qregion_mac.cpp
extern QRegion qt_mac_convert_mac_region(RgnHandle); //qregion_mac.cpp
extern void qt_mac_to_pascal_string(QString s, Str255 str, TextEncoding encoding=0, int len=-1); //qglobal.cpp
+/*
+ QGLTemporaryContext implementation
+*/
+
+class QGLTemporaryContextPrivate
+{
+public:
+#ifndef QT_MAC_USE_COCOA
+ AGLContext ctx;
+#else
+ NSOpenGLContext *ctx;
+#endif
+};
+
+QGLTemporaryContext::QGLTemporaryContext(bool, QWidget *)
+ : d(new QGLTemporaryContextPrivate)
+{
+ d->ctx = 0;
+#ifndef QT_MAC_USE_COCOA
+ GLint attribs[] = {AGL_RGBA, AGL_NONE};
+ AGLPixelFormat fmt = aglChoosePixelFormat(0, 0, attribs);
+ if (!fmt) {
+ qDebug("QGLTemporaryContext: Couldn't find any RGB visuals");
+ return;
+ }
+ d->ctx = aglCreateContext(fmt, 0);
+ if (!d->ctx)
+ qDebug("QGLTemporaryContext: Unable to create context");
+ else
+ aglSetCurrentContext(d->ctx);
+ aglDestroyPixelFormat(fmt);
+#else
+ QMacCocoaAutoReleasePool pool;
+ NSOpenGLPixelFormatAttribute attribs[] = { 0 };
+ NSOpenGLPixelFormat *fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs];
+ if (!fmt) {
+ qWarning("QGLTemporaryContext: Cannot find any visuals");
+ return;
+ }
+
+ d->ctx = [[NSOpenGLContext alloc] initWithFormat:fmt shareContext:0];
+ if (!d->ctx)
+ qWarning("QGLTemporaryContext: Cannot create context");
+ else
+ [d->ctx makeCurrentContext];
+ [fmt release];
+#endif
+}
+
+QGLTemporaryContext::~QGLTemporaryContext()
+{
+ if (d->ctx) {
+#ifndef QT_MAC_USE_COCOA
+ aglSetCurrentContext(0);
+ aglDestroyContext(d->ctx);
+#else
+ [NSOpenGLContext clearCurrentContext];
+ [d->ctx release];
+#endif
+ }
+}
+
bool QGLFormat::hasOpenGL()
{
return true;
@@ -918,54 +980,6 @@ void QGLWidgetPrivate::updatePaintDevice()
q->update();
}
-
-void QGLExtensions::init()
-{
- static bool init_done = false;
-
- if (init_done)
- return;
- init_done = true;
-
-#ifndef QT_MAC_USE_COCOA
- GLint attribs[] = { AGL_RGBA, AGL_NONE };
- AGLPixelFormat fmt = aglChoosePixelFormat(0, 0, attribs);
- if (!fmt) {
- qDebug("QGLExtensions: Couldn't find any RGB visuals");
- return;
- }
- AGLContext ctx = aglCreateContext(fmt, 0);
- if (!ctx) {
- qDebug("QGLExtensions: Unable to create context");
- } else {
- aglSetCurrentContext(ctx);
- init_extensions();
- aglSetCurrentContext(0);
- aglDestroyContext(ctx);
- }
- aglDestroyPixelFormat(fmt);
-#else
- QMacCocoaAutoReleasePool pool;
- NSOpenGLPixelFormatAttribute attribs[] = { 0 };
- NSOpenGLPixelFormat *fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs];
- if (!fmt) {
- qWarning("QGLExtensions: Cannot find any visuals");
- return;
- }
-
- NSOpenGLContext *ctx = [[NSOpenGLContext alloc] initWithFormat:fmt shareContext:0];
- if (!ctx) {
- qWarning("QGLExtensions: Cannot create context");
- } else {
- [ctx makeCurrentContext];
- init_extensions();
- [NSOpenGLContext clearCurrentContext];
- [ctx release];
- }
- [fmt release];
-#endif
-}
-
#endif
QT_END_NAMESPACE
diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h
index f07a1f1..9e8e335 100644
--- a/src/opengl/qgl_p.h
+++ b/src/opengl/qgl_p.h
@@ -271,6 +271,60 @@ private:
// "ctx" is destroyed. Returns null if nothing is sharing with ctx.
Q_OPENGL_EXPORT const QGLContext *qt_gl_transfer_context(const QGLContext *);
+// GL extension definitions
+class QGLExtensions {
+public:
+ enum Extension {
+ TextureRectangle = 0x00000001,
+ SampleBuffers = 0x00000002,
+ GenerateMipmap = 0x00000004,
+ TextureCompression = 0x00000008,
+ FragmentProgram = 0x00000010,
+ MirroredRepeat = 0x00000020,
+ FramebufferObject = 0x00000040,
+ StencilTwoSide = 0x00000080,
+ StencilWrap = 0x00000100,
+ PackedDepthStencil = 0x00000200,
+ NVFloatBuffer = 0x00000400,
+ PixelBufferObject = 0x00000800,
+ FramebufferBlit = 0x00001000,
+ NPOTTextures = 0x00002000,
+ BGRATextureFormat = 0x00004000,
+ DDSTextureCompression = 0x00008000,
+ ETC1TextureCompression = 0x00010000,
+ PVRTCTextureCompression = 0x00020000,
+ FragmentShader = 0x00040000
+ };
+ Q_DECLARE_FLAGS(Extensions, Extension)
+
+ static Extensions glExtensions();
+
+private:
+ static Extensions currentContextExtensions();
+};
+
+/*
+ QGLTemporaryContext - the main objective of this class is to have a way of
+ creating a GL context and making it current, without going via QGLWidget
+ and friends. At certain points during GL initialization we need a current
+ context in order decide what GL features are available, and to resolve GL
+ extensions. Having a light-weight way of creating such a context saves
+ initial application startup time, and it doesn't wind up creating recursive
+ conflicts.
+ The class currently uses a private d pointer to hide the platform specific
+ types. This could possibly been done inline with #ifdef'ery, but it causes
+ major headaches on e.g. X11 due to namespace pollution.
+*/
+class QGLTemporaryContextPrivate;
+class QGLTemporaryContext {
+public:
+ QGLTemporaryContext(bool directRendering = true, QWidget *parent = 0);
+ ~QGLTemporaryContext();
+
+private:
+ QScopedPointer<QGLTemporaryContextPrivate> d;
+};
+
class QGLTexture;
// This probably needs to grow to GL_MAX_VERTEX_ATTRIBS, but 3 is ok for now as that's
@@ -347,10 +401,12 @@ public:
uint crWin : 1;
uint internal_context : 1;
uint version_flags_cached : 1;
+ uint extension_flags_cached : 1;
QPaintDevice *paintDevice;
QColor transpColor;
QGLContext *q_ptr;
QGLFormat::OpenGLVersionFlags version_flags;
+ QGLExtensions::Extensions extension_flags;
QGLContextGroup *group;
GLint max_texture_size;
@@ -389,41 +445,8 @@ Q_SIGNALS:
void aboutToDestroyContext(const QGLContext *context);
};
-// GL extension definitions
-class QGLExtensions {
-public:
- enum Extension {
- TextureRectangle = 0x00000001,
- SampleBuffers = 0x00000002,
- GenerateMipmap = 0x00000004,
- TextureCompression = 0x00000008,
- FragmentProgram = 0x00000010,
- MirroredRepeat = 0x00000020,
- FramebufferObject = 0x00000040,
- StencilTwoSide = 0x00000080,
- StencilWrap = 0x00000100,
- PackedDepthStencil = 0x00000200,
- NVFloatBuffer = 0x00000400,
- PixelBufferObject = 0x00000800,
- FramebufferBlit = 0x00001000,
- NPOTTextures = 0x00002000,
- BGRATextureFormat = 0x00004000,
- DDSTextureCompression = 0x00008000,
- ETC1TextureCompression = 0x00010000,
- PVRTCTextureCompression = 0x00020000,
- FragmentShader = 0x00040000
- };
- Q_DECLARE_FLAGS(Extensions, Extension)
-
- static Extensions glExtensions;
- static bool nvidiaFboNeedsFinish;
- static void init(); // sys dependent
- static void init_extensions(); // general: called by init()
-};
-
Q_DECLARE_OPERATORS_FOR_FLAGS(QGLExtensions::Extensions)
-
// Temporarily make a context current if not already current or
// shared with the current contex. The previous context is made
// current when the object goes out of scope.
@@ -547,7 +570,7 @@ bool qt_gl_preferGL2Engine();
inline GLenum qt_gl_preferredTextureFormat()
{
- return (QGLExtensions::glExtensions & QGLExtensions::BGRATextureFormat) && QSysInfo::ByteOrder == QSysInfo::LittleEndian
+ return (QGLExtensions::glExtensions() & QGLExtensions::BGRATextureFormat) && QSysInfo::ByteOrder == QSysInfo::LittleEndian
? GL_BGRA : GL_RGBA;
}
@@ -556,7 +579,7 @@ inline GLenum qt_gl_preferredTextureTarget()
#if defined(QT_OPENGL_ES_2)
return GL_TEXTURE_2D;
#else
- return (QGLExtensions::glExtensions & QGLExtensions::TextureRectangle)
+ return (QGLExtensions::glExtensions() & QGLExtensions::TextureRectangle)
&& !qt_gl_preferGL2Engine()
? GL_TEXTURE_RECTANGLE_NV
: GL_TEXTURE_2D;
@@ -628,7 +651,7 @@ private:
};
-// This class can be used to match GL extensions with doing any mallocs. The
+// This class can be used to match GL extensions without doing any mallocs. The
// class assumes that the GL extension string ends with a space character,
// which it should do on all conformant platforms. Create the object and pass
// in a pointer to the extension string, then call match() on each extension
diff --git a/src/opengl/qgl_qws.cpp b/src/opengl/qgl_qws.cpp
index f69ad7b..d4adc8b 100644
--- a/src/opengl/qgl_qws.cpp
+++ b/src/opengl/qgl_qws.cpp
@@ -83,6 +83,28 @@ static QGLScreen *glScreenForDevice(QPaintDevice *device)
return 0;
}
+/*
+ QGLTemporaryContext implementation
+*/
+
+class QGLTemporaryContextPrivate
+{
+public:
+ QGLWidget *widget;
+};
+
+QGLTemporaryContext::QGLTemporaryContext(bool, QWidget *)
+ : d(new QGLTemporaryContextPrivate)
+{
+ d->widget = new QGLWidget;
+ d->widget->makeCurrent();
+}
+
+QGLTemporaryContext::~QGLTemporaryContext()
+{
+ delete d->widget;
+}
+
/*****************************************************************************
QOpenGL debug facilities
*****************************************************************************/
@@ -311,36 +333,4 @@ void QGLWidget::setColormap(const QGLColormap &)
{
}
-void QGLExtensions::init()
-{
- static bool init_done = false;
-
- if (init_done)
- return;
- init_done = true;
-
- // We need a context current to initialize the extensions,
- // but getting a valid EGLNativeWindowType this early can be
- // problematic under QWS. So use a pbuffer instead.
- //
- // Unfortunately OpenGL/ES 2.0 systems don't normally
- // support pbuffers, so we have no choice but to try
- // our luck with a window on those systems.
-#if defined(QT_OPENGL_ES_2)
- QGLWidget tmpWidget;
- tmpWidget.makeCurrent();
-
- init_extensions();
-
- tmpWidget.doneCurrent();
-#else
- QGLPixelBuffer pbuffer(16, 16);
- pbuffer.makeCurrent();
-
- init_extensions();
-
- pbuffer.doneCurrent();
-#endif
-}
-
QT_END_NAMESPACE
diff --git a/src/opengl/qgl_win.cpp b/src/opengl/qgl_win.cpp
index c1132b5..b5f952e 100644
--- a/src/opengl/qgl_win.cpp
+++ b/src/opengl/qgl_win.cpp
@@ -575,7 +575,7 @@ QGLFormat pfiToQGLFormat(HDC hdc, int pfi)
QVarLengthArray<int> iAttributes(40);
QVarLengthArray<int> iValues(40);
int i = 0;
- bool has_sample_buffers = QGLExtensions::glExtensions & QGLExtensions::SampleBuffers;
+ bool has_sample_buffers = QGLExtensions::glExtensions() & QGLExtensions::SampleBuffers;
iAttributes[i++] = WGL_DOUBLE_BUFFER_ARB; // 0
iAttributes[i++] = WGL_DEPTH_BITS_ARB; // 1
@@ -652,52 +652,14 @@ QGLFormat pfiToQGLFormat(HDC hdc, int pfi)
/*
- Creates a temporary GL context and makes it current
- - cleans up when the object is destructed.
+ QGLTemporaryContext implementation
*/
Q_GUI_EXPORT const QString qt_getRegisteredWndClass();
-class QGLTempContext
+class QGLTemporaryContextPrivate
{
public:
- QGLTempContext(bool directRendering, QWidget *parent = 0)
- {
- QString windowClassName = qt_getRegisteredWndClass();
- if (parent && !parent->internalWinId())
- parent = parent->nativeParentWidget();
-
- dmy_id = CreateWindow((const wchar_t *)windowClassName.utf16(),
- 0, 0, 0, 0, 1, 1,
- parent ? parent->winId() : 0, 0, qWinAppInst(), 0);
-
- dmy_pdc = GetDC(dmy_id);
- PIXELFORMATDESCRIPTOR dmy_pfd;
- memset(&dmy_pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
- dmy_pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
- dmy_pfd.nVersion = 1;
- dmy_pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW;
- dmy_pfd.iPixelType = PFD_TYPE_RGBA;
- if (!directRendering)
- dmy_pfd.dwFlags |= PFD_GENERIC_FORMAT;
-
- int dmy_pf = ChoosePixelFormat(dmy_pdc, &dmy_pfd);
- SetPixelFormat(dmy_pdc, dmy_pf, &dmy_pfd);
- dmy_rc = wglCreateContext(dmy_pdc);
- old_dc = wglGetCurrentDC();
- old_context = wglGetCurrentContext();
- wglMakeCurrent(dmy_pdc, dmy_rc);
- }
-
- ~QGLTempContext() {
- wglMakeCurrent(dmy_pdc, 0);
- wglDeleteContext(dmy_rc);
- ReleaseDC(dmy_id, dmy_pdc);
- DestroyWindow(dmy_id);
- if (old_dc && old_context)
- wglMakeCurrent(old_dc, old_context);
- }
-
HDC dmy_pdc;
HGLRC dmy_rc;
HDC old_dc;
@@ -705,6 +667,45 @@ public:
WId dmy_id;
};
+QGLTemporaryContext::QGLTemporaryContext(bool directRendering, QWidget *parent)
+ : d(new QGLTemporaryContextPrivate)
+{
+ QString windowClassName = qt_getRegisteredWndClass();
+ if (parent && !parent->internalWinId())
+ parent = parent->nativeParentWidget();
+
+ d->dmy_id = CreateWindow((const wchar_t *)windowClassName.utf16(),
+ 0, 0, 0, 0, 1, 1,
+ parent ? parent->winId() : 0, 0, qWinAppInst(), 0);
+
+ d->dmy_pdc = GetDC(d->dmy_id);
+ PIXELFORMATDESCRIPTOR dmy_pfd;
+ memset(&dmy_pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
+ dmy_pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
+ dmy_pfd.nVersion = 1;
+ dmy_pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW;
+ dmy_pfd.iPixelType = PFD_TYPE_RGBA;
+ if (!directRendering)
+ dmy_pfd.dwFlags |= PFD_GENERIC_FORMAT;
+
+ int dmy_pf = ChoosePixelFormat(d->dmy_pdc, &dmy_pfd);
+ SetPixelFormat(d->dmy_pdc, dmy_pf, &dmy_pfd);
+ d->dmy_rc = wglCreateContext(d->dmy_pdc);
+ d->old_dc = wglGetCurrentDC();
+ d->old_context = wglGetCurrentContext();
+ wglMakeCurrent(d->dmy_pdc, d->dmy_rc);
+}
+
+QGLTemporaryContext::~QGLTemporaryContext()
+{
+ wglMakeCurrent(d->dmy_pdc, 0);
+ wglDeleteContext(d->dmy_rc);
+ ReleaseDC(d->dmy_id, d->dmy_pdc);
+ DestroyWindow(d->dmy_id);
+ if (d->old_dc && d->old_context)
+ wglMakeCurrent(d->old_dc, d->old_context);
+}
+
static bool qgl_create_context(HDC hdc, QGLContextPrivate *d, QGLContextPrivate *shareContext)
{
d->rc = 0;
@@ -855,10 +856,10 @@ bool QGLContext::chooseContext(const QGLContext* shareContext)
myDc = GetDC(d->win);
}
- // NB! the QGLTempContext object is needed for the
+ // NB! the QGLTemporaryContext object is needed for the
// wglGetProcAddress() calls to succeed and are absolutely
// necessary - don't remove!
- QGLTempContext tmp_ctx(d->glFormat.directRendering(), widget);
+ QGLTemporaryContext tmp_ctx(d->glFormat.directRendering(), widget);
if (!myDc) {
qWarning("QGLContext::chooseContext(): Paint device cannot be null");
@@ -1087,7 +1088,7 @@ int QGLContext::choosePixelFormat(void* dummyPfd, HDC pdc)
iAttributes[i++] = 1;
}
int si = 0;
- bool trySampleBuffers = QGLExtensions::glExtensions & QGLExtensions::SampleBuffers;
+ bool trySampleBuffers = QGLExtensions::glExtensions() & QGLExtensions::SampleBuffers;
if (trySampleBuffers && d->glFormat.sampleBuffers()) {
iAttributes[i++] = WGL_SAMPLE_BUFFERS_ARB;
iAttributes[i++] = TRUE;
@@ -1593,15 +1594,4 @@ void QGLWidget::setColormap(const QGLColormap & c)
}
}
-void QGLExtensions::init()
-{
- static bool init_done = false;
-
- if (init_done)
- return;
- init_done = true;
- QGLTempContext temp_ctx(QGLFormat::defaultFormat().directRendering());
- init_extensions();
-}
-
QT_END_NAMESPACE
diff --git a/src/opengl/qgl_wince.cpp b/src/opengl/qgl_wince.cpp
index 460f10d..00a125a 100644
--- a/src/opengl/qgl_wince.cpp
+++ b/src/opengl/qgl_wince.cpp
@@ -95,8 +95,27 @@ public:
#include <qcolor.h>
+/*
+ QGLTemporaryContext implementation
+*/
+class QGLTemporaryContextPrivate
+{
+public:
+ QGLWidget *widget;
+};
+QGLTemporaryContext::QGLTemporaryContext(bool, QWidget *)
+ : d(new QGLTemporaryContextPrivate)
+{
+ d->widget = new QGLWidget;
+ d->widget->makeCurrent();
+}
+
+QGLTemporaryContext::~QGLTemporaryContext()
+{
+ delete d->widget;
+}
/*****************************************************************************
QGLFormat Win32/WGL-specific code
@@ -627,21 +646,4 @@ void QGLWidget::setColormap(const QGLColormap & c)
}
}
-void QGLExtensions::init()
-{
- static bool init_done = false;
-
- if (init_done)
- return;
- init_done = true;
-
- // We need a context current to initialize the extensions.
- QGLWidget tmpWidget;
- tmpWidget.makeCurrent();
-
- init_extensions();
-
- tmpWidget.doneCurrent();
-}
-
QT_END_NAMESPACE
diff --git a/src/opengl/qgl_x11.cpp b/src/opengl/qgl_x11.cpp
index e883ddc..f4cc7c7 100644
--- a/src/opengl/qgl_x11.cpp
+++ b/src/opengl/qgl_x11.cpp
@@ -549,7 +549,7 @@ void *QGLContext::chooseVisual()
bool triedDouble = false;
bool triedSample = false;
if (fmt.sampleBuffers())
- fmt.setSampleBuffers(QGLExtensions::glExtensions & QGLExtensions::SampleBuffers);
+ fmt.setSampleBuffers(QGLExtensions::glExtensions() & QGLExtensions::SampleBuffers);
while(!fail && !(vis = tryVisual(fmt, bufDepths[i]))) {
if (!fmt.rgba() && bufDepths[i] > 1) {
i++;
@@ -1132,71 +1132,70 @@ void *QGLContext::getProcAddress(const QString &proc) const
return glXGetProcAddressARB(reinterpret_cast<const GLubyte *>(proc.toLatin1().data()));
}
-//
-// This class is used to create a temporary, minimal GL context, which is used
-// to retrive GL version and extension info. It's significantly faster to
-// construct than a QGLWidget, and it doesn't have the recursive creation
-// problem that QGLWidget would have. E.g. creating a temporary QGLWidget to
-// retrieve GL info as part of the QGLWidget initialization.
-//
-class QGLTempContext
-{
+/*
+ QGLTemporaryContext implementation
+*/
+
+class QGLTemporaryContextPrivate {
public:
- QGLTempContext(int screen = 0) :
- initialized(false),
- old_drawable(0),
- old_context(0)
- {
- int attribs[] = {GLX_RGBA, XNone};
- XVisualInfo *vi = glXChooseVisual(X11->display, screen, attribs);
- if (!vi) {
- qWarning("QGLTempContext: No GL capable X visuals available.");
- return;
- }
+ bool initialized;
+ Window drawable;
+ GLXContext context;
+ GLXDrawable oldDrawable;
+ GLXContext oldContext;
+};
- int useGL;
- glXGetConfig(X11->display, vi, GLX_USE_GL, &useGL);
- if (!useGL) {
- XFree(vi);
- return;
- }
+QGLTemporaryContext::QGLTemporaryContext(bool, QWidget *)
+ : d(new QGLTemporaryContextPrivate)
+{
+ d->initialized = false;
+ d->oldDrawable = 0;
+ d->oldContext = 0;
+ int screen = 0;
+
+ int attribs[] = {GLX_RGBA, XNone};
+ XVisualInfo *vi = glXChooseVisual(X11->display, screen, attribs);
+ if (!vi) {
+ qWarning("QGLTempContext: No GL capable X visuals available.");
+ return;
+ }
- old_drawable = glXGetCurrentDrawable();
- old_context = glXGetCurrentContext();
-
- XSetWindowAttributes a;
- a.colormap = qt_gl_choose_cmap(X11->display, vi);
- drawable = XCreateWindow(X11->display, RootWindow(X11->display, screen),
- 0, 0, 1, 1, 0,
- vi->depth, InputOutput, vi->visual,
- CWColormap, &a);
- context = glXCreateContext(X11->display, vi, 0, True);
- if (context && glXMakeCurrent(X11->display, drawable, context)) {
- initialized = true;
- } else {
- qWarning("QGLTempContext: Unable to create GL context.");
- XDestroyWindow(X11->display, drawable);
- }
+ int useGL;
+ glXGetConfig(X11->display, vi, GLX_USE_GL, &useGL);
+ if (!useGL) {
XFree(vi);
+ return;
}
- ~QGLTempContext() {
- if (initialized) {
- glXMakeCurrent(X11->display, 0, 0);
- glXDestroyContext(X11->display, context);
- XDestroyWindow(X11->display, drawable);
- }
- if (old_drawable && old_context)
- glXMakeCurrent(X11->display, old_drawable, old_context);
+ d->oldDrawable = glXGetCurrentDrawable();
+ d->oldContext = glXGetCurrentContext();
+
+ XSetWindowAttributes a;
+ a.colormap = qt_gl_choose_cmap(X11->display, vi);
+ d->drawable = XCreateWindow(X11->display, RootWindow(X11->display, screen),
+ 0, 0, 1, 1, 0,
+ vi->depth, InputOutput, vi->visual,
+ CWColormap, &a);
+ d->context = glXCreateContext(X11->display, vi, 0, True);
+ if (d->context && glXMakeCurrent(X11->display, d->drawable, d->context)) {
+ d->initialized = true;
+ } else {
+ qWarning("QGLTempContext: Unable to create GL context.");
+ XDestroyWindow(X11->display, d->drawable);
}
+ XFree(vi);
+}
-private:
- bool initialized;
- Window drawable;
- GLXContext context;
- GLXDrawable old_drawable;
- GLXContext old_context;
-};
+QGLTemporaryContext::~QGLTemporaryContext()
+{
+ if (d->initialized) {
+ glXMakeCurrent(X11->display, 0, 0);
+ glXDestroyContext(X11->display, d->context);
+ XDestroyWindow(X11->display, d->drawable);
+ }
+ if (d->oldDrawable && d->oldContext)
+ glXMakeCurrent(X11->display, d->oldDrawable, d->oldContext);
+}
/*****************************************************************************
QGLOverlayWidget (Internal overlay class for X11)
@@ -1632,27 +1631,6 @@ void QGLWidget::setColormap(const QGLColormap & c)
delete [] cmw;
}
-void QGLExtensions::init()
-{
- static bool init_done = false;
-
- if (init_done)
- return;
- init_done = true;
-
- QGLTempContext context;
- init_extensions();
-
- // nvidia 9x.xx unix drivers contain a bug which requires us to call glFinish before releasing an fbo
- // to avoid painting artifacts
- const QByteArray versionString(reinterpret_cast<const char*>(glGetString(GL_VERSION)));
- const int pos = versionString.indexOf("NVIDIA");
- if (pos >= 0) {
- const float nvidiaDriverVersion = versionString.mid(pos + strlen("NVIDIA")).toFloat();
- nvidiaFboNeedsFinish = nvidiaDriverVersion >= 90.0 && nvidiaDriverVersion < 100.0;
- }
-}
-
// Solaris defines glXBindTexImageEXT as part of the GL library
#if defined(GLX_VERSION_1_3) && !defined(Q_OS_HPUX)
typedef void (*qt_glXBindTexImageEXT)(Display*, GLXDrawable, int, const int*);
@@ -1668,7 +1646,7 @@ static bool qt_resolveTextureFromPixmap(QPaintDevice *paintDevice)
resolvedTextureFromPixmap = true;
// Check to see if we have NPOT texture support
- if ( !(QGLExtensions::glExtensions & QGLExtensions::NPOTTextures) &&
+ if ( !(QGLExtensions::glExtensions() & QGLExtensions::NPOTTextures) &&
!(QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_2_0))
{
return false; // Can't use TFP without NPOT
diff --git a/src/opengl/qgl_x11egl.cpp b/src/opengl/qgl_x11egl.cpp
index 85daf95..572834b 100644
--- a/src/opengl/qgl_x11egl.cpp
+++ b/src/opengl/qgl_x11egl.cpp
@@ -55,112 +55,115 @@ QT_BEGIN_NAMESPACE
bool qt_egl_setup_x11_visual(XVisualInfo &vi, EGLDisplay display, EGLConfig config,
const QX11Info &x11Info, bool useArgbVisual);
-//
-// QGLTempContext is a class for creating a temporary GL context
-// (which is needed during QGLWidget initialization to retrieve GL
-// extension info). Faster to construct than a full QGLWidget.
-//
-class QGLTempContext
+
+/*
+ QGLTemporaryContext implementation
+*/
+
+class QGLTemporaryContextPrivate
{
public:
- QGLTempContext(int screen = 0) :
- initialized(false),
- window(0),
- context(0),
- surface(0)
- {
- display = eglGetDisplay(EGLNativeDisplayType(X11->display));
+ bool initialized;
+ Window window;
+ EGLContext context;
+ EGLSurface surface;
+ EGLDisplay display;
+};
- if (!eglInitialize(display, NULL, NULL)) {
- qWarning("QGLTempContext: Unable to initialize EGL display.");
- return;
- }
+QGLTemporaryContext::QGLTemporaryContext(bool, QWidget *)
+ : d(new QGLTemporaryContextPrivate)
+{
+ d->initialized = false;
+ d->window = 0;
+ d->context = 0;
+ d->surface = 0;
+ int screen = 0;
+
+ d->display = eglGetDisplay(EGLNativeDisplayType(X11->display));
- EGLConfig config;
- int numConfigs = 0;
- EGLint attribs[] = {
- EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+ if (!eglInitialize(d->display, NULL, NULL)) {
+ qWarning("QGLTemporaryContext: Unable to initialize EGL display.");
+ return;
+ }
+
+ EGLConfig config;
+ int numConfigs = 0;
+ EGLint attribs[] = {
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
#ifdef QT_OPENGL_ES_2
- EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
#endif
- EGL_NONE
- };
+ EGL_NONE
+ };
- eglChooseConfig(display, attribs, &config, 1, &numConfigs);
- if (!numConfigs) {
- qWarning("QGLTempContext: No EGL configurations available.");
- return;
- }
+ eglChooseConfig(d->display, attribs, &config, 1, &numConfigs);
+ if (!numConfigs) {
+ qWarning("QGLTemporaryContext: No EGL configurations available.");
+ return;
+ }
- XVisualInfo visualInfo;
- XVisualInfo *vi;
- int numVisuals;
- EGLint id = 0;
-
- eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &id);
- if (id == 0) {
- // EGL_NATIVE_VISUAL_ID is optional and might not be supported
- // on some implementations - we'll have to do it the hard way
- QX11Info xinfo;
- qt_egl_setup_x11_visual(visualInfo, display, config, xinfo, false);
- } else {
- visualInfo.visualid = id;
- }
- vi = XGetVisualInfo(X11->display, VisualIDMask, &visualInfo, &numVisuals);
- if (!vi || numVisuals < 1) {
- qWarning("QGLTempContext: Unable to get X11 visual info id.");
- return;
- }
+ XVisualInfo visualInfo;
+ XVisualInfo *vi;
+ int numVisuals;
+ EGLint id = 0;
+
+ eglGetConfigAttrib(d->display, config, EGL_NATIVE_VISUAL_ID, &id);
+ if (id == 0) {
+ // EGL_NATIVE_VISUAL_ID is optional and might not be supported
+ // on some implementations - we'll have to do it the hard way
+ QX11Info xinfo;
+ qt_egl_setup_x11_visual(visualInfo, d->display, config, xinfo, false);
+ } else {
+ visualInfo.visualid = id;
+ }
+ vi = XGetVisualInfo(X11->display, VisualIDMask, &visualInfo, &numVisuals);
+ if (!vi || numVisuals < 1) {
+ qWarning("QGLTemporaryContext: Unable to get X11 visual info id.");
+ return;
+ }
- window = XCreateWindow(X11->display, RootWindow(X11->display, screen),
- 0, 0, 1, 1, 0,
- vi->depth, InputOutput, vi->visual,
- 0, 0);
+ d->window = XCreateWindow(X11->display, RootWindow(X11->display, screen),
+ 0, 0, 1, 1, 0,
+ vi->depth, InputOutput, vi->visual,
+ 0, 0);
- surface = eglCreateWindowSurface(display, config, (EGLNativeWindowType) window, NULL);
+ d->surface = eglCreateWindowSurface(d->display, config, (EGLNativeWindowType) d->window, NULL);
- if (surface == EGL_NO_SURFACE) {
- qWarning("QGLTempContext: Error creating EGL surface.");
- XFree(vi);
- XDestroyWindow(X11->display, window);
- return;
- }
+ if (d->surface == EGL_NO_SURFACE) {
+ qWarning("QGLTemporaryContext: Error creating EGL surface.");
+ XFree(vi);
+ XDestroyWindow(X11->display, d->window);
+ return;
+ }
- EGLint contextAttribs[] = {
+ EGLint contextAttribs[] = {
#ifdef QT_OPENGL_ES_2
- EGL_CONTEXT_CLIENT_VERSION, 2,
+ EGL_CONTEXT_CLIENT_VERSION, 2,
#endif
- EGL_NONE
- };
- context = eglCreateContext(display, config, 0, contextAttribs);
- if (context != EGL_NO_CONTEXT
- && eglMakeCurrent(display, surface, surface, context))
- {
- initialized = true;
- } else {
- qWarning("QGLTempContext: Error creating EGL context.");
- eglDestroySurface(display, surface);
- XDestroyWindow(X11->display, window);
- }
- XFree(vi);
+ EGL_NONE
+ };
+ d->context = eglCreateContext(d->display, config, 0, contextAttribs);
+ if (d->context != EGL_NO_CONTEXT
+ && eglMakeCurrent(d->display, d->surface, d->surface, d->context))
+ {
+ d->initialized = true;
+ } else {
+ qWarning("QGLTemporaryContext: Error creating EGL context.");
+ eglDestroySurface(d->display, d->surface);
+ XDestroyWindow(X11->display, d->window);
}
+ XFree(vi);
+}
- ~QGLTempContext() {
- if (initialized) {
- eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
- eglDestroyContext(display, context);
- eglDestroySurface(display, surface);
- XDestroyWindow(X11->display, window);
- }
+QGLTemporaryContext::~QGLTemporaryContext()
+{
+ if (d->initialized) {
+ eglMakeCurrent(d->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ eglDestroyContext(d->display, d->context);
+ eglDestroySurface(d->display, d->surface);
+ XDestroyWindow(X11->display, d->window);
}
-
-private:
- bool initialized;
- Window window;
- EGLContext context;
- EGLSurface surface;
- EGLDisplay display;
-};
+}
bool QGLFormat::hasOpenGLOverlays()
{
@@ -547,19 +550,6 @@ void QGLWidget::setColormap(const QGLColormap &)
{
}
-void QGLExtensions::init()
-{
- static bool init_done = false;
-
- if (init_done)
- return;
- init_done = true;
-
- // We need a context current to initialize the extensions.
- QGLTempContext context;
- init_extensions();
-}
-
// Re-creates the EGL surface if the window ID has changed or if force is true
void QGLWidgetPrivate::recreateEglSurface(bool force)
{
diff --git a/src/opengl/qglframebufferobject.cpp b/src/opengl/qglframebufferobject.cpp
index ed21923..ce80796 100644
--- a/src/opengl/qglframebufferobject.cpp
+++ b/src/opengl/qglframebufferobject.cpp
@@ -396,7 +396,7 @@ void QGLFramebufferObjectPrivate::init(QGLFramebufferObject *q, const QSize &sz,
QGLContext *ctx = const_cast<QGLContext *>(QGLContext::currentContext());
fbo_guard.setContext(ctx);
- bool ext_detected = (QGLExtensions::glExtensions & QGLExtensions::FramebufferObject);
+ bool ext_detected = (QGLExtensions::glExtensions() & QGLExtensions::FramebufferObject);
if (!ext_detected || (ext_detected && !qt_resolve_framebufferobject_extensions(ctx)))
return;
@@ -466,7 +466,7 @@ void QGLFramebufferObjectPrivate::init(QGLFramebufferObject *q, const QSize &sz,
}
if (attachment == QGLFramebufferObject::CombinedDepthStencil
- && (QGLExtensions::glExtensions & QGLExtensions::PackedDepthStencil)) {
+ && (QGLExtensions::glExtensions() & QGLExtensions::PackedDepthStencil)) {
// depth and stencil buffer needs another extension
glGenRenderbuffers(1, &depth_stencil_buffer);
Q_ASSERT(!glIsRenderbuffer(depth_stencil_buffer));
@@ -1028,8 +1028,7 @@ QPaintEngine *QGLFramebufferObject::paintEngine() const
*/
bool QGLFramebufferObject::hasOpenGLFramebufferObjects()
{
- QGLExtensions::init();
- return (QGLExtensions::glExtensions & QGLExtensions::FramebufferObject);
+ return (QGLExtensions::glExtensions() & QGLExtensions::FramebufferObject);
}
/*!
@@ -1188,8 +1187,7 @@ bool QGLFramebufferObject::isBound() const
*/
bool QGLFramebufferObject::hasOpenGLFramebufferBlit()
{
- QGLExtensions::init();
- return (QGLExtensions::glExtensions & QGLExtensions::FramebufferBlit);
+ return (QGLExtensions::glExtensions() & QGLExtensions::FramebufferBlit);
}
/*!
@@ -1229,7 +1227,7 @@ void QGLFramebufferObject::blitFramebuffer(QGLFramebufferObject *target, const Q
GLbitfield buffers,
GLenum filter)
{
- if (!(QGLExtensions::glExtensions & QGLExtensions::FramebufferBlit))
+ if (!(QGLExtensions::glExtensions() & QGLExtensions::FramebufferBlit))
return;
const QGLContext *ctx = QGLContext::currentContext();
diff --git a/src/opengl/qglpixelbuffer_mac.mm b/src/opengl/qglpixelbuffer_mac.mm
index 49c1845..6731dd8 100644
--- a/src/opengl/qglpixelbuffer_mac.mm
+++ b/src/opengl/qglpixelbuffer_mac.mm
@@ -92,7 +92,7 @@ bool QGLPixelBufferPrivate::init(const QSize &size, const QGLFormat &f, QGLWidge
GLenum target = GL_TEXTURE_2D;
- if ((QGLExtensions::glExtensions & QGLExtensions::TextureRectangle)
+ if ((QGLExtensions::glExtensions() & QGLExtensions::TextureRectangle)
&& (size.width() != nearest_gl_texture_size(size.width())
|| size.height() != nearest_gl_texture_size(size.height())))
{
@@ -223,7 +223,7 @@ bool QGLPixelBufferPrivate::init(const QSize &size, const QGLFormat &f, QGLWidge
GLenum target = GL_TEXTURE_2D;
- if ((QGLExtensions::glExtensions & QGLExtensions::TextureRectangle)
+ if ((QGLExtensions::glExtensions() & QGLExtensions::TextureRectangle)
&& (size.width() != nearest_gl_texture_size(size.width())
|| size.height() != nearest_gl_texture_size(size.height())))
{
diff --git a/src/opengl/qglpixelbuffer_p.h b/src/opengl/qglpixelbuffer_p.h
index f40b7c5..c85dc5a 100644
--- a/src/opengl/qglpixelbuffer_p.h
+++ b/src/opengl/qglpixelbuffer_p.h
@@ -154,7 +154,6 @@ class QGLPixelBufferPrivate {
public:
QGLPixelBufferPrivate(QGLPixelBuffer *q) : q_ptr(q), invalid(true), qctx(0), pbuf(0), ctx(0)
{
- QGLExtensions::init();
#ifdef Q_WS_WIN
dc = 0;
#elif defined(Q_WS_MACX)
diff --git a/src/opengl/qglpixelbuffer_win.cpp b/src/opengl/qglpixelbuffer_win.cpp
index a986ccf..8d0d105 100644
--- a/src/opengl/qglpixelbuffer_win.cpp
+++ b/src/opengl/qglpixelbuffer_win.cpp
@@ -221,7 +221,7 @@ static void qt_format_to_attrib_list(bool has_render_texture, const QGLFormat &f
}
if ((f.redBufferSize() > 8 || f.greenBufferSize() > 8
|| f.blueBufferSize() > 8 || f.alphaBufferSize() > 8)
- && (QGLExtensions::glExtensions & QGLExtensions::NVFloatBuffer))
+ && (QGLExtensions::glExtensions() & QGLExtensions::NVFloatBuffer))
{
attribs[i++] = WGL_FLOAT_COMPONENTS_NV;
attribs[i++] = TRUE;
@@ -368,11 +368,9 @@ void QGLPixelBuffer::releaseFromDynamicTexture()
bool QGLPixelBuffer::hasOpenGLPbuffers()
{
bool ret = false;
- QGLWidget *dmy = 0;
- if (!QGLContext::currentContext()) {
- dmy = new QGLWidget;
- dmy->makeCurrent();
- }
+ QGLTemporaryContext *tmpContext = 0;
+ if (!QGLContext::currentContext())
+ tmpContext = new QGLTemporaryContext;
PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB =
(PFNWGLGETEXTENSIONSSTRINGARBPROC) wglGetProcAddress("wglGetExtensionsStringARB");
if (wglGetExtensionsStringARB) {
@@ -382,8 +380,8 @@ bool QGLPixelBuffer::hasOpenGLPbuffers()
ret = true;
}
}
- if (dmy)
- delete dmy;
+ if (tmpContext)
+ delete tmpContext;
return ret;
}
diff --git a/src/opengl/qpaintengine_opengl.cpp b/src/opengl/qpaintengine_opengl.cpp
index c823187..57918d0 100644
--- a/src/opengl/qpaintengine_opengl.cpp
+++ b/src/opengl/qpaintengine_opengl.cpp
@@ -108,6 +108,10 @@ static bool DEBUG_TEMP_FLAG;
#define DEBUG_ONCE_STR(str) DEBUG_ONCE qDebug() << (str);
#endif
+#ifdef Q_WS_X11
+static bool qt_nvidiaFboNeedsFinish = false;
+#endif
+
static inline void qt_glColor4ubv(unsigned char *col)
{
glColor4f(col[0]/255.0f, col[1]/255.0f, col[2]/255.0f, col[3]/255.0f);
@@ -423,7 +427,7 @@ inline void QGLOffscreen::release()
#ifdef Q_WS_X11
// workaround for bug in nvidia driver versions 9x.xx
- if (QGLExtensions::nvidiaFboNeedsFinish)
+ if (qt_nvidiaFboNeedsFinish)
glFinish();
#endif
@@ -477,7 +481,7 @@ inline QGLContext *QGLOffscreen::context() const
bool QGLOffscreen::isSupported()
{
- return (QGLExtensions::glExtensions & QGLExtensions::FramebufferObject); // for fbo
+ return (QGLExtensions::glExtensions() & QGLExtensions::FramebufferObject); // for fbo
}
struct QDrawQueueItem
@@ -1266,7 +1270,7 @@ bool QOpenGLPaintEngine::begin(QPaintDevice *pdev)
for (int j = 0; j < 4; ++j)
d->mv_matrix[i][j] = (i == j ? qreal(1) : qreal(0));
- bool has_frag_program = (QGLExtensions::glExtensions & QGLExtensions::FragmentProgram)
+ bool has_frag_program = (QGLExtensions::glExtensions() & QGLExtensions::FragmentProgram)
&& (pdev->devType() != QInternal::Pixmap);
QGLContext *ctx = const_cast<QGLContext *>(d->device->context());
@@ -1279,11 +1283,27 @@ bool QOpenGLPaintEngine::begin(QPaintDevice *pdev)
has_frag_program = qt_resolve_frag_program_extensions(ctx) && qt_resolve_version_1_3_functions(ctx);
d->use_stencil_method = d->device->format().stencil()
- && (QGLExtensions::glExtensions & QGLExtensions::StencilWrap);
+ && (QGLExtensions::glExtensions() & QGLExtensions::StencilWrap);
if (d->device->format().directRendering()
- && (d->use_stencil_method && QGLExtensions::glExtensions & QGLExtensions::StencilTwoSide))
+ && (d->use_stencil_method && QGLExtensions::glExtensions() & QGLExtensions::StencilTwoSide))
d->has_stencil_face_ext = qt_resolve_stencil_face_extension(ctx);
+#ifdef Q_WS_X11
+ static bool nvidia_workaround_needs_init = true;
+ if (nvidia_workaround_needs_init) {
+ // nvidia 9x.xx unix drivers contain a bug which requires us to
+ // call glFinish before releasing an fbo to avoid painting
+ // artifacts
+ const QByteArray versionString(reinterpret_cast<const char*>(glGetString(GL_VERSION)));
+ const int pos = versionString.indexOf("NVIDIA");
+ if (pos >= 0) {
+ const float nvidiaDriverVersion = versionString.mid(pos + strlen("NVIDIA")).toFloat();
+ qt_nvidiaFboNeedsFinish = nvidiaDriverVersion >= 90.0 && nvidiaDriverVersion < 100.0;
+ }
+ nvidia_workaround_needs_init = false;
+ }
+#endif
+
#ifndef QT_OPENGL_ES
if (!ctx->d_ptr->internal_context) {
glGetDoublev(GL_PROJECTION_MATRIX, &d->projection_matrix[0][0]);
@@ -1333,10 +1353,10 @@ bool QOpenGLPaintEngine::begin(QPaintDevice *pdev)
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
- if (QGLExtensions::glExtensions & QGLExtensions::SampleBuffers)
+ if (QGLExtensions::glExtensions() & QGLExtensions::SampleBuffers)
glDisable(GL_MULTISAMPLE);
glDisable(GL_TEXTURE_2D);
- if (QGLExtensions::glExtensions & QGLExtensions::TextureRectangle)
+ if (QGLExtensions::glExtensions() & QGLExtensions::TextureRectangle)
glDisable(GL_TEXTURE_RECTANGLE_NV);
glDisable(GL_STENCIL_TEST);
glDisable(GL_CULL_FACE);
@@ -1534,7 +1554,7 @@ void QOpenGLPaintEnginePrivate::updateGradient(const QBrush &brush, const QRectF
#ifdef QT_OPENGL_ES
Q_UNUSED(brush);
#else
- bool has_mirrored_repeat = QGLExtensions::glExtensions & QGLExtensions::MirroredRepeat;
+ bool has_mirrored_repeat = QGLExtensions::glExtensions() & QGLExtensions::MirroredRepeat;
Qt::BrushStyle style = brush.style();
QTransform m = brush.transform();
@@ -2098,7 +2118,7 @@ static inline bool needsEmulation(Qt::BrushStyle style)
{
return !(style == Qt::SolidPattern
|| (style == Qt::LinearGradientPattern
- && (QGLExtensions::glExtensions & QGLExtensions::MirroredRepeat)));
+ && (QGLExtensions::glExtensions() & QGLExtensions::MirroredRepeat)));
}
void QOpenGLPaintEnginePrivate::updateUseEmulation()
@@ -2420,12 +2440,12 @@ void QOpenGLPaintEngine::updateRenderHints(QPainter::RenderHints hints)
d->high_quality_antialiasing = true;
} else {
d->high_quality_antialiasing = false;
- if (QGLExtensions::glExtensions & QGLExtensions::SampleBuffers)
+ if (QGLExtensions::glExtensions() & QGLExtensions::SampleBuffers)
glEnable(GL_MULTISAMPLE);
}
} else {
d->high_quality_antialiasing = false;
- if (QGLExtensions::glExtensions & QGLExtensions::SampleBuffers)
+ if (QGLExtensions::glExtensions() & QGLExtensions::SampleBuffers)
glDisable(GL_MULTISAMPLE);
}
@@ -2435,14 +2455,14 @@ void QOpenGLPaintEngine::updateRenderHints(QPainter::RenderHints hints)
if (!d->offscreen.isValid()) {
DEBUG_ONCE_STR("Unable to initialize offscreen, disabling high quality antialiasing");
d->high_quality_antialiasing = false;
- if (QGLExtensions::glExtensions & QGLExtensions::SampleBuffers)
+ if (QGLExtensions::glExtensions() & QGLExtensions::SampleBuffers)
glEnable(GL_MULTISAMPLE);
}
}
d->has_antialiasing = d->high_quality_antialiasing
|| ((hints & QPainter::Antialiasing)
- && (QGLExtensions::glExtensions & QGLExtensions::SampleBuffers));
+ && (QGLExtensions::glExtensions() & QGLExtensions::SampleBuffers));
}
diff --git a/src/opengl/qwindowsurface_gl.cpp b/src/opengl/qwindowsurface_gl.cpp
index 8ee4361..7a565e6 100644
--- a/src/opengl/qwindowsurface_gl.cpp
+++ b/src/opengl/qwindowsurface_gl.cpp
@@ -295,7 +295,6 @@ QGLWindowSurface::QGLWindowSurface(QWidget *window)
: QWindowSurface(window), d_ptr(new QGLWindowSurfacePrivate)
{
Q_ASSERT(window->isTopLevel());
- QGLExtensions::init();
d_ptr->pb = 0;
d_ptr->fbo = 0;
d_ptr->ctx = 0;
@@ -520,7 +519,7 @@ void QGLWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoint &
glDisable(GL_SCISSOR_TEST);
- if (d_ptr->fbo && (QGLExtensions::glExtensions & QGLExtensions::FramebufferBlit)) {
+ if (d_ptr->fbo && (QGLExtensions::glExtensions() & QGLExtensions::FramebufferBlit)) {
const int h = d_ptr->fbo->height();
const int sx0 = br.left();
@@ -698,7 +697,7 @@ void QGLWindowSurface::updateGeometry() {
}
if (d_ptr->destructive_swap_buffers
- && (QGLExtensions::glExtensions & QGLExtensions::FramebufferObject)
+ && (QGLExtensions::glExtensions() & QGLExtensions::FramebufferObject)
&& (d_ptr->fbo || !d_ptr->tried_fbo)
&& qt_gl_preferGL2Engine())
{
@@ -712,7 +711,7 @@ void QGLWindowSurface::updateGeometry() {
format.setInternalTextureFormat(GLenum(GL_RGBA));
format.setTextureTarget(target);
- if (QGLExtensions::glExtensions & QGLExtensions::FramebufferBlit)
+ if (QGLExtensions::glExtensions() & QGLExtensions::FramebufferBlit)
format.setSamples(8);
d_ptr->fbo = new QGLFramebufferObject(rect.size(), format);