--- a/src/opengl/qgl.cpp Tue Feb 02 00:43:10 2010 +0200
+++ b/src/opengl/qgl.cpp Fri Feb 19 23:40:16 2010 +0200
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
@@ -124,9 +124,6 @@
};
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 @@
// 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 @@
// 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
@@ -1250,7 +1245,7 @@
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;
@@ -1261,8 +1256,7 @@
} else {
if (!hasOpenGL())
return defaultVersionFlags;
- dummy = new QGLWidget;
- dummy->makeCurrent(); // glGetString() needs a current context
+ tmpContext = new QGLTemporaryContext;
cachedDefault = true;
}
}
@@ -1273,9 +1267,9 @@
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;
@@ -1436,6 +1430,18 @@
m_guards = guard->m_next;
}
+const QGLContext *qt_gl_transfer_context(const QGLContext *ctx)
+{
+ if (!ctx)
+ return 0;
+ QList<const QGLContext *> shares
+ (QGLContextPrivate::contextGroup(ctx)->shares());
+ if (shares.size() >= 2)
+ return (ctx == shares.at(0)) ? shares.at(1) : shares.at(0);
+ else
+ return 0;
+}
+
QGLContextPrivate::~QGLContextPrivate()
{
if (!group->m_refs.deref()) {
@@ -1481,9 +1487,13 @@
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;
+ for (int i = 0; i < QT_GL_VERTEX_ARRAY_TRACKED_COUNT; ++i)
+ vertexAttributeArraysEnabledState[i] = false;
}
QGLContext* QGLContext::currentCtx = 0;
@@ -1541,7 +1551,7 @@
QImage qt_gl_read_texture(const QSize &size, bool alpha_format, bool include_alpha)
{
- QImage img(size, alpha_format ? QImage::Format_ARGB32 : QImage::Format_RGB32);
+ QImage img(size, alpha_format ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32);
int w = size.width();
int h = size.height();
#if !defined(QT_OPENGL_ES_2) && !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
@@ -1729,12 +1739,6 @@
#define GL_GENERATE_MIPMAP_HINT_SGIS 0x8192
#endif
-Q_GLOBAL_STATIC(QGLShareRegister, _qgl_share_reg)
-Q_OPENGL_EXPORT QGLShareRegister* qgl_share_reg()
-{
- return _qgl_share_reg();
-}
-
/*!
\class QGLContext
\brief The QGLContext class encapsulates an OpenGL rendering context.
@@ -1874,6 +1878,35 @@
{
}
+#define ctx q_ptr
+void QGLContextPrivate::setVertexAttribArrayEnabled(int arrayIndex, bool enabled)
+{
+ Q_ASSERT(arrayIndex < QT_GL_VERTEX_ARRAY_TRACKED_COUNT);
+ Q_ASSERT(glEnableVertexAttribArray);
+
+ if (vertexAttributeArraysEnabledState[arrayIndex] && !enabled)
+ glDisableVertexAttribArray(arrayIndex);
+
+ if (!vertexAttributeArraysEnabledState[arrayIndex] && enabled)
+ glEnableVertexAttribArray(arrayIndex);
+
+ vertexAttributeArraysEnabledState[arrayIndex] = enabled;
+}
+
+void QGLContextPrivate::syncGlState()
+{
+ Q_ASSERT(glEnableVertexAttribArray);
+ for (int i = 0; i < QT_GL_VERTEX_ARRAY_TRACKED_COUNT; ++i) {
+ if (vertexAttributeArraysEnabledState[i])
+ glEnableVertexAttribArray(i);
+ else
+ glDisableVertexAttribArray(i);
+ }
+
+}
+#undef ctx
+
+
/*!
\overload
@@ -2110,7 +2143,7 @@
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())))
{
@@ -2132,7 +2165,7 @@
bool genMipmap = false;
#endif
if (glFormat.directRendering()
- && (QGLExtensions::glExtensions & QGLExtensions::GenerateMipmap)
+ && (QGLExtensions::glExtensions() & QGLExtensions::GenerateMipmap)
&& target == GL_TEXTURE_2D
&& (options & QGLContext::MipmapBindOption))
{
@@ -2160,9 +2193,12 @@
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;
@@ -2241,12 +2277,9 @@
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",
@@ -2954,7 +2987,7 @@
wd->usesDoubleBufferedGLContext = d->glFormat.doubleBuffer();
}
if (d->sharing) // ok, we managed to share
- qgl_share_reg()->addShare(this, shareContext);
+ QGLContextGroup::addShare(this, shareContext);
return d->valid;
}
@@ -4378,9 +4411,9 @@
int height = d->glcx->device()->height();
bool auto_swap = autoBufferSwap();
+ QPaintEngine::Type oldEngineType = qgl_engine_selector()->preferredPaintEngine();
+ qgl_engine_selector()->setPreferredPaintEngine(QPaintEngine::OpenGL);
QPaintEngine *engine = paintEngine();
- if (engine->type() == QPaintEngine::OpenGL2)
- static_cast<QGL2PaintEngineEx *>(engine)->setRenderTextActive(true);
QPainter *p;
bool reuse_painter = false;
if (engine->isActive()) {
@@ -4400,11 +4433,6 @@
setAutoBufferSwap(false);
// disable glClear() as a result of QPainter::begin()
d->disable_clear_on_painter_begin = true;
- if (engine->type() == QPaintEngine::OpenGL2) {
- qt_save_gl_state();
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- }
p = new QPainter(this);
}
@@ -4428,11 +4456,8 @@
delete p;
setAutoBufferSwap(auto_swap);
d->disable_clear_on_painter_begin = false;
- if (engine->type() == QPaintEngine::OpenGL2)
- qt_restore_gl_state();
}
- if (engine->type() == QPaintEngine::OpenGL2)
- static_cast<QGL2PaintEngineEx *>(engine)->setRenderTextActive(false);
+ qgl_engine_selector()->setPreferredPaintEngine(oldEngineType);
#else // QT_OPENGL_ES
Q_UNUSED(x);
Q_UNUSED(y);
@@ -4480,9 +4505,9 @@
&win_x, &win_y, &win_z);
win_y = height - win_y; // y is inverted
+ QPaintEngine::Type oldEngineType = qgl_engine_selector()->preferredPaintEngine();
+ qgl_engine_selector()->setPreferredPaintEngine(QPaintEngine::OpenGL);
QPaintEngine *engine = paintEngine();
- if (engine->type() == QPaintEngine::OpenGL2)
- static_cast<QGL2PaintEngineEx *>(engine)->setRenderTextActive(true);
QPainter *p;
bool reuse_painter = false;
bool use_depth_testing = glIsEnabled(GL_DEPTH_TEST);
@@ -4496,8 +4521,6 @@
setAutoBufferSwap(false);
// disable glClear() as a result of QPainter::begin()
d->disable_clear_on_painter_begin = true;
- if (engine->type() == QPaintEngine::OpenGL2)
- qt_save_gl_state();
p = new QPainter(this);
}
@@ -4526,13 +4549,10 @@
} else {
p->end();
delete p;
- if (engine->type() == QPaintEngine::OpenGL2)
- qt_restore_gl_state();
setAutoBufferSwap(auto_swap);
d->disable_clear_on_painter_begin = false;
}
- if (engine->type() == QPaintEngine::OpenGL2)
- static_cast<QGL2PaintEngineEx *>(engine)->setRenderTextActive(false);
+ qgl_engine_selector()->setPreferredPaintEngine(oldEngineType);
#else // QT_OPENGL_ES
Q_UNUSED(x);
Q_UNUSED(y);
@@ -4844,9 +4864,13 @@
#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;
@@ -4907,6 +4931,46 @@
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;
}
/*
@@ -4918,7 +4982,6 @@
glDevice.setWidget(q);
- QGLExtensions::init();
glcx = 0;
autoSwap = true;
@@ -4928,8 +4991,6 @@
if (!glcx)
glcx = new QGLContext(QGLFormat::defaultFormat(), q);
-
- q->setAttribute(Qt::WA_NoSystemBackground);
}
#if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS)
@@ -4953,7 +5014,7 @@
}
#endif
-void QGLShareRegister::addShare(const QGLContext *context, const QGLContext *share) {
+void QGLContextGroup::addShare(const QGLContext *context, const QGLContext *share) {
Q_ASSERT(context && share);
if (context->d_ptr->group == share->d_ptr->group)
return;
@@ -4974,11 +5035,7 @@
group->m_shares.append(context);
}
-QList<const QGLContext *> QGLShareRegister::shares(const QGLContext *context) {
- return context->d_ptr->group->m_shares;
-}
-
-void QGLShareRegister::removeShare(const QGLContext *context) {
+void QGLContextGroup::removeShare(const QGLContext *context) {
// Remove the context from the group.
QGLContextGroup *group = context->d_ptr->group;
if (group->m_shares.isEmpty())
@@ -5173,7 +5230,7 @@
}
#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();
@@ -5212,7 +5269,7 @@
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();
}
@@ -5322,13 +5379,13 @@
// 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();