diff options
Diffstat (limited to 'src/opengl')
-rw-r--r-- | src/opengl/gl2paintengineex/qglgradientcache.cpp | 14 | ||||
-rw-r--r-- | src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp | 97 | ||||
-rw-r--r-- | src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h | 8 | ||||
-rw-r--r-- | src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp | 81 | ||||
-rw-r--r-- | src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h | 2 | ||||
-rw-r--r-- | src/opengl/opengl.pro | 3 | ||||
-rw-r--r-- | src/opengl/qgl.cpp | 724 | ||||
-rw-r--r-- | src/opengl/qgl_p.h | 2 | ||||
-rw-r--r-- | src/opengl/qgl_qpa.cpp | 466 | ||||
-rw-r--r-- | src/opengl/qglbuffer.cpp | 4 | ||||
-rw-r--r-- | src/opengl/qglframebufferobject.cpp | 38 | ||||
-rw-r--r-- | src/opengl/qglpaintdevice.cpp | 9 | ||||
-rw-r--r-- | src/opengl/qglpixelbuffer.cpp | 35 | ||||
-rw-r--r-- | src/opengl/qglshaderprogram.cpp | 5 |
14 files changed, 713 insertions, 775 deletions
diff --git a/src/opengl/gl2paintengineex/qglgradientcache.cpp b/src/opengl/gl2paintengineex/qglgradientcache.cpp index 6160554472..d2b6842a8a 100644 --- a/src/opengl/gl2paintengineex/qglgradientcache.cpp +++ b/src/opengl/gl2paintengineex/qglgradientcache.cpp @@ -89,11 +89,12 @@ void QGL2GradientCache::freeResource(QOpenGLContext *) void QGL2GradientCache::cleanCache() { + QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions(); QMutexLocker lock(&m_mutex); QGLGradientColorTableHash::const_iterator it = cache.constBegin(); for (; it != cache.constEnd(); ++it) { const CacheInfo &cache_info = it.value(); - glDeleteTextures(1, &cache_info.texId); + funcs->glDeleteTextures(1, &cache_info.texId); } cache.clear(); } @@ -129,6 +130,7 @@ GLuint QGL2GradientCache::getBuffer(const QGradient &gradient, qreal opacity) GLuint QGL2GradientCache::addCacheElement(quint64 hash_val, const QGradient &gradient, qreal opacity) { + QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions(); if (cache.size() == maxCacheSize()) { int elem_to_remove = qrand() % maxCacheSize(); quint64 key = cache.keys()[elem_to_remove]; @@ -136,7 +138,7 @@ GLuint QGL2GradientCache::addCacheElement(quint64 hash_val, const QGradient &gra // need to call glDeleteTextures on each removed cache entry: QGLGradientColorTableHash::const_iterator it = cache.constFind(key); do { - glDeleteTextures(1, &it.value().texId); + funcs->glDeleteTextures(1, &it.value().texId); } while (++it != cache.constEnd() && it.key() == key); cache.remove(key); // may remove more than 1, but OK } @@ -144,10 +146,10 @@ GLuint QGL2GradientCache::addCacheElement(quint64 hash_val, const QGradient &gra CacheInfo cache_entry(gradient.stops(), opacity, gradient.interpolationMode()); uint buffer[1024]; generateGradientColorTable(gradient, buffer, paletteSize(), opacity); - glGenTextures(1, &cache_entry.texId); - glBindTexture(GL_TEXTURE_2D, cache_entry.texId); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, paletteSize(), 1, - 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer); + funcs->glGenTextures(1, &cache_entry.texId); + funcs->glBindTexture(GL_TEXTURE_2D, cache_entry.texId); + funcs->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, paletteSize(), 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer); return cache.insert(hash_val, cache_entry).value().texId; } diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index 5d4ca42dc2..06857a9bb1 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -86,6 +86,10 @@ #include <QDebug> +#ifndef QT_OPENGL_ES_2 +# include <qopenglfunctions_1_1.h> +#endif + QT_BEGIN_NAMESPACE @@ -106,7 +110,7 @@ QGL2PaintEngineExPrivate::~QGL2PaintEngineExPrivate() } if (elementIndicesVBOId != 0) { - funcs.glDeleteBuffers(1, &elementIndicesVBOId); + glDeleteBuffers(1, &elementIndicesVBOId); elementIndicesVBOId = 0; } } @@ -193,7 +197,7 @@ void QGL2PaintEngineExPrivate::updateBrushTexture() // Get the image data for the pattern QImage texImage = qt_imageForBrush(style, false); - funcs.glActiveTexture(GL_TEXTURE0 + QT_BRUSH_TEXTURE_UNIT); + glActiveTexture(GL_TEXTURE0 + QT_BRUSH_TEXTURE_UNIT); ctx->d_func()->bindTexture(texImage, GL_TEXTURE_2D, GL_RGBA, QGLContext::InternalBindOption); updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, q->state()->renderHints & QPainter::SmoothPixmapTransform); } @@ -206,7 +210,7 @@ void QGL2PaintEngineExPrivate::updateBrushTexture() // for opacity to the cache. GLuint texId = QGL2GradientCache::cacheForContext(ctx)->getBuffer(*g, 1.0); - funcs.glActiveTexture(GL_TEXTURE0 + QT_BRUSH_TEXTURE_UNIT); + glActiveTexture(GL_TEXTURE0 + QT_BRUSH_TEXTURE_UNIT); glBindTexture(GL_TEXTURE_2D, texId); if (g->spread() == QGradient::RepeatSpread || g->type() == QGradient::ConicalGradient) @@ -231,7 +235,7 @@ void QGL2PaintEngineExPrivate::updateBrushTexture() wrapMode = GL_CLAMP_TO_EDGE; } - funcs.glActiveTexture(GL_TEXTURE0 + QT_BRUSH_TEXTURE_UNIT); + glActiveTexture(GL_TEXTURE0 + QT_BRUSH_TEXTURE_UNIT); QGLTexture *tex = ctx->d_func()->bindTexture(currentBrushPixmap, GL_TEXTURE_2D, GL_RGBA, QGLContext::InternalBindOption | QGLContext::CanFlipNativePixmapBindOption); @@ -428,9 +432,9 @@ void QGL2PaintEngineExPrivate::updateMatrix() // Set the PMV matrix attribute. As we use an attributes rather than uniforms, we only // need to do this once for every matrix change and persists across all shader programs. - funcs.glVertexAttrib3fv(QT_PMV_MATRIX_1_ATTR, pmvMatrix[0]); - funcs.glVertexAttrib3fv(QT_PMV_MATRIX_2_ATTR, pmvMatrix[1]); - funcs.glVertexAttrib3fv(QT_PMV_MATRIX_3_ATTR, pmvMatrix[2]); + glVertexAttrib3fv(QT_PMV_MATRIX_1_ATTR, pmvMatrix[0]); + glVertexAttrib3fv(QT_PMV_MATRIX_2_ATTR, pmvMatrix[1]); + glVertexAttrib3fv(QT_PMV_MATRIX_3_ATTR, pmvMatrix[2]); dasher.setInvScale(inverseScale); stroker.setInvScale(inverseScale); @@ -540,11 +544,11 @@ void QGL2PaintEngineEx::beginNativePainting() d->nativePaintingActive = true; - d->funcs.glUseProgram(0); + d->glUseProgram(0); // Disable all the vertex attribute arrays: for (int i = 0; i < QT_GL_VERTEX_ARRAY_TRACKED_COUNT; ++i) - d->funcs.glDisableVertexAttribArray(i); + d->glDisableVertexAttribArray(i); #ifndef QT_OPENGL_ES_2 if (!d->ctx->contextHandle()->isOpenGLES()) { @@ -569,12 +573,15 @@ void QGL2PaintEngineEx::beginNativePainting() const QSize sz = d->device->size(); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0, sz.width(), sz.height(), 0, -999999, 999999); + QOpenGLFunctions_1_1 *gl1funcs = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_1_1>(); + gl1funcs->initializeOpenGLFunctions(); - glMatrixMode(GL_MODELVIEW); - glLoadMatrixf(&mv_matrix[0][0]); + gl1funcs->glMatrixMode(GL_PROJECTION); + gl1funcs->glLoadIdentity(); + gl1funcs->glOrtho(0, sz.width(), sz.height(), 0, -999999, 999999); + + gl1funcs->glMatrixMode(GL_MODELVIEW); + gl1funcs->glLoadMatrixf(&mv_matrix[0][0]); } } #endif @@ -591,13 +598,13 @@ void QGL2PaintEngineEx::beginNativePainting() void QGL2PaintEngineExPrivate::resetGLState() { glDisable(GL_BLEND); - funcs.glActiveTexture(GL_TEXTURE0); + glActiveTexture(GL_TEXTURE0); glDisable(GL_STENCIL_TEST); glDisable(GL_DEPTH_TEST); glDisable(GL_SCISSOR_TEST); glDepthMask(true); glDepthFunc(GL_LESS); - funcs.glClearDepthf(1); + glClearDepthf(1); glStencilMask(0xff); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); glStencilFunc(GL_ALWAYS, 0, 0xff); @@ -608,7 +615,7 @@ void QGL2PaintEngineExPrivate::resetGLState() if (!ctx->contextHandle()->isOpenGLES()) { // gl_Color, corresponding to vertex attribute 3, may have been changed float color[] = { 1.0f, 1.0f, 1.0f, 1.0f }; - funcs.glVertexAttrib4fv(3, color); + glVertexAttrib4fv(3, color); } #endif } @@ -758,7 +765,7 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path) qreal scaleFactor = cache->iscale / inverseScale; if (scaleFactor < 0.5 || scaleFactor > 2.0) { #ifdef QT_OPENGL_CACHE_AS_VBOS - funcs.glDeleteBuffers(1, &cache->vbo); + glDeleteBuffers(1, &cache->vbo); cache->vbo = 0; Q_ASSERT(cache->ibo == 0); #else @@ -785,9 +792,9 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path) cache->primitiveType = GL_TRIANGLE_FAN; cache->iscale = inverseScale; #ifdef QT_OPENGL_CACHE_AS_VBOS - funcs.glGenBuffers(1, &cache->vbo); - funcs.glBindBuffer(GL_ARRAY_BUFFER, cache->vbo); - funcs.glBufferData(GL_ARRAY_BUFFER, floatSizeInBytes, vertexCoordinateArray.data(), GL_STATIC_DRAW); + glGenBuffers(1, &cache->vbo); + glBindBuffer(GL_ARRAY_BUFFER, cache->vbo); + glBufferData(GL_ARRAY_BUFFER, floatSizeInBytes, vertexCoordinateArray.data(), GL_STATIC_DRAW); cache->ibo = 0; #else cache->vertices = (float *) malloc(floatSizeInBytes); @@ -798,7 +805,7 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path) prepareForDraw(currentBrush.isOpaque()); #ifdef QT_OPENGL_CACHE_AS_VBOS - funcs.glBindBuffer(GL_ARRAY_BUFFER, cache->vbo); + glBindBuffer(GL_ARRAY_BUFFER, cache->vbo); setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, 0); #else setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, cache->vertices); @@ -1024,9 +1031,9 @@ void QGL2PaintEngineExPrivate::fillStencilWithVertexArray(const float *data, } // Inc. for front-facing triangle - funcs.glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_INCR_WRAP, GL_INCR_WRAP); + glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_INCR_WRAP, GL_INCR_WRAP); // Dec. for back-facing "holes" - funcs.glStencilOpSeparate(GL_BACK, GL_KEEP, GL_DECR_WRAP, GL_DECR_WRAP); + glStencilOpSeparate(GL_BACK, GL_KEEP, GL_DECR_WRAP, GL_DECR_WRAP); glStencilMask(~GL_STENCIL_HIGH_BIT); drawVertexArrays(data, stops, stopCount, GL_TRIANGLE_FAN); @@ -1375,9 +1382,9 @@ void QGL2PaintEngineEx::renderHintsChanged() if (!d->ctx->contextHandle()->isOpenGLES()) { if ((state()->renderHints & QPainter::Antialiasing) || (state()->renderHints & QPainter::HighQualityAntialiasing)) - glEnable(GL_MULTISAMPLE); + d->glEnable(GL_MULTISAMPLE); else - glDisable(GL_MULTISAMPLE); + d->glDisable(GL_MULTISAMPLE); } #endif @@ -1423,7 +1430,7 @@ void QGL2PaintEngineEx::drawPixmap(const QRectF& dest, const QPixmap & pixmap, c bindOptions |= QGLContext::TemporarilyCachedBindOption; #endif - d->funcs.glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT); + d->glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT); QGLTexture *texture = ctx->d_func()->bindTexture(pixmap, GL_TEXTURE_2D, GL_RGBA, bindOptions); @@ -1465,7 +1472,7 @@ void QGL2PaintEngineEx::drawImage(const QRectF& dest, const QImage& image, const ensureActive(); d->transferMode(ImageDrawingMode); - d->funcs.glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT); + d->glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT); QGLContext::BindOptions bindOptions = QGLContext::InternalBindOption; #ifdef QGL_USE_TEXTURE_POOL @@ -1526,8 +1533,8 @@ bool QGL2PaintEngineEx::drawTexture(const QRectF &dest, GLuint textureId, const ensureActive(); d->transferMode(ImageDrawingMode); - d->funcs.glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT); - glBindTexture(GL_TEXTURE_2D, textureId); + d->glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT); + d->glBindTexture(GL_TEXTURE_2D, textureId); QGLRect srcRect(src.left(), src.bottom(), src.right(), src.top()); @@ -1812,7 +1819,7 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngine::GlyphFormat glyphFo glEnable(GL_BLEND); glBlendFunc(GL_CONSTANT_COLOR, GL_ONE_MINUS_SRC_COLOR); - funcs.glBlendColor(c.redF(), c.greenF(), c.blueF(), c.alphaF()); + glBlendColor(c.redF(), c.greenF(), c.blueF(), c.alphaF()); } else { // Other brush styles need two passes. @@ -1829,7 +1836,7 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngine::GlyphFormat glyphFo glEnable(GL_BLEND); glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR); - funcs.glActiveTexture(GL_TEXTURE0 + QT_MASK_TEXTURE_UNIT); + glActiveTexture(GL_TEXTURE0 + QT_MASK_TEXTURE_UNIT); glBindTexture(GL_TEXTURE_2D, cache->texture()); updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, false); @@ -1855,7 +1862,7 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngine::GlyphFormat glyphFo } compositionModeDirty = true; } else { - // Greyscale/mono glyphs + // Grayscale/mono glyphs shaderManager->setMaskType(QGLEngineShaderManager::PixelMask); prepareForCachedGlyphDraw(*cache); @@ -1864,7 +1871,7 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngine::GlyphFormat glyphFo QGLTextureGlyphCache::FilterMode filterMode = (s->matrix.type() > QTransform::TxTranslate)?QGLTextureGlyphCache::Linear:QGLTextureGlyphCache::Nearest; if (lastMaskTextureUsed != cache->texture() || cache->filterMode() != filterMode) { - funcs.glActiveTexture(GL_TEXTURE0 + QT_MASK_TEXTURE_UNIT); + glActiveTexture(GL_TEXTURE0 + QT_MASK_TEXTURE_UNIT); if (lastMaskTextureUsed != cache->texture()) { glBindTexture(GL_TEXTURE_2D, cache->texture()); lastMaskTextureUsed = cache->texture(); @@ -1965,7 +1972,7 @@ void QGL2PaintEngineExPrivate::drawPixmapFragments(const QPainter::PixmapFragmen allOpaque &= (opacity >= 0.99f); } - funcs.glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT); + glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT); QGLTexture *texture = ctx->d_func()->bindTexture(pixmap, GL_TEXTURE_2D, GL_RGBA, QGLContext::InternalBindOption | QGLContext::CanFlipNativePixmapBindOption); @@ -2039,17 +2046,17 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev) // go after beginPaint: d->device->beginPaint(); - d->funcs.initializeOpenGLFunctions(); + d->initializeOpenGLFunctions(); d->shaderManager = new QGLEngineShaderManager(d->ctx); - glDisable(GL_STENCIL_TEST); - glDisable(GL_DEPTH_TEST); - glDisable(GL_SCISSOR_TEST); + d->glDisable(GL_STENCIL_TEST); + d->glDisable(GL_DEPTH_TEST); + d->glDisable(GL_SCISSOR_TEST); #if !defined(QT_OPENGL_ES_2) if (!d->ctx->contextHandle()->isOpenGLES()) - glDisable(GL_MULTISAMPLE); + d->glDisable(GL_MULTISAMPLE); #endif d->glyphCacheFormat = QFontEngine::Format_A8; @@ -2075,7 +2082,7 @@ bool QGL2PaintEngineEx::end() Q_D(QGL2PaintEngineEx); QGLContext *ctx = d->ctx; - d->funcs.glUseProgram(0); + d->glUseProgram(0); d->transferMode(BrushDrawingMode); d->device->endPaint(); @@ -2089,11 +2096,11 @@ bool QGL2PaintEngineEx::end() #ifdef QT_OPENGL_CACHE_AS_VBOS if (!d->unusedVBOSToClean.isEmpty()) { - glDeleteBuffers(d->unusedVBOSToClean.size(), d->unusedVBOSToClean.constData()); + d->glDeleteBuffers(d->unusedVBOSToClean.size(), d->unusedVBOSToClean.constData()); d->unusedVBOSToClean.clear(); } if (!d->unusedIBOSToClean.isEmpty()) { - glDeleteBuffers(d->unusedIBOSToClean.size(), d->unusedIBOSToClean.constData()); + d->glDeleteBuffers(d->unusedIBOSToClean.size(), d->unusedIBOSToClean.constData()); d->unusedIBOSToClean.clear(); } #endif @@ -2115,7 +2122,7 @@ void QGL2PaintEngineEx::ensureActive() if (d->needsSync) { d->transferMode(BrushDrawingMode); - glViewport(0, 0, d->width, d->height); + d->glViewport(0, 0, d->width, d->height); d->needsSync = false; d->lastMaskTextureUsed = 0; d->shaderManager->setDirty(); @@ -2436,7 +2443,7 @@ void QGL2PaintEngineEx::setState(QPainterState *new_state) if (old_state == s || old_state->clipChanged) { if (old_state && old_state != s && old_state->canRestoreClip) { d->updateClipScissorTest(); - glDepthFunc(GL_LEQUAL); + d->glDepthFunc(GL_LEQUAL); } else { d->regenerateClip(); } diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h index 15ed5bc57d..e851ccac18 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h @@ -165,7 +165,7 @@ private: Q_DISABLE_COPY(QGL2PaintEngineEx) }; -class QGL2PaintEngineExPrivate : public QPaintEngineExPrivate +class QGL2PaintEngineExPrivate : public QPaintEngineExPrivate, protected QOpenGLExtensions { Q_DECLARE_PUBLIC(QGL2PaintEngineEx) public: @@ -261,8 +261,6 @@ public: EngineMode mode; QFontEngine::GlyphFormat glyphCacheFormat; - QOpenGLExtensions funcs; - // Dirty flags bool matrixDirty; // Implies matrix uniforms are also dirty bool compositionModeDirty; @@ -327,9 +325,9 @@ void QGL2PaintEngineExPrivate::setVertexAttributePointer(unsigned int arrayIndex vertexAttribPointers[arrayIndex] = pointer; if (arrayIndex == QT_OPACITY_ATTR) - funcs.glVertexAttribPointer(arrayIndex, 1, GL_FLOAT, GL_FALSE, 0, pointer); + glVertexAttribPointer(arrayIndex, 1, GL_FLOAT, GL_FALSE, 0, pointer); else - funcs.glVertexAttribPointer(arrayIndex, 2, GL_FLOAT, GL_FALSE, 0, pointer); + glVertexAttribPointer(arrayIndex, 2, GL_FLOAT, GL_FALSE, 0, pointer); } QT_END_NAMESPACE diff --git a/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp b/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp index f1da50a6b9..aa1d7decdb 100644 --- a/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp +++ b/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp @@ -96,6 +96,7 @@ void QGLTextureGlyphCache::createTextureData(int width, int height) qWarning("QGLTextureGlyphCache::createTextureData: Called with no context"); return; } + QOpenGLFunctions *funcs = ctx->contextHandle()->functions(); // create in QImageTextureGlyphCache baseclass is meant to be called // only to create the initial image and does not preserve the content, @@ -117,8 +118,8 @@ void QGLTextureGlyphCache::createTextureData(int width, int height) if (!m_textureResource) m_textureResource = new QGLGlyphTexture(ctx); - glGenTextures(1, &m_textureResource->m_texture); - glBindTexture(GL_TEXTURE_2D, m_textureResource->m_texture); + funcs->glGenTextures(1, &m_textureResource->m_texture); + funcs->glBindTexture(GL_TEXTURE_2D, m_textureResource->m_texture); m_textureResource->m_width = width; m_textureResource->m_height = height; @@ -127,18 +128,18 @@ void QGLTextureGlyphCache::createTextureData(int width, int height) QVarLengthArray<uchar> data(width * height * 4); for (int i = 0; i < data.size(); ++i) data[i] = 0; - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]); + funcs->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]); } else { QVarLengthArray<uchar> data(width * height); for (int i = 0; i < data.size(); ++i) data[i] = 0; - glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, &data[0]); + funcs->glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, &data[0]); } - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); m_filterMode = Nearest; } @@ -149,6 +150,7 @@ void QGLTextureGlyphCache::resizeTextureData(int width, int height) qWarning("QGLTextureGlyphCache::resizeTextureData: Called with no context"); return; } + QOpenGLFunctions *funcs = ctx->contextHandle()->functions(); int oldWidth = m_textureResource->m_width; int oldHeight = m_textureResource->m_height; @@ -165,44 +167,42 @@ void QGLTextureGlyphCache::resizeTextureData(int width, int height) if (!QGLFramebufferObject::hasOpenGLFramebufferObjects() || ctx->d_ptr->workaround_brokenFBOReadBack) { QImageTextureGlyphCache::resizeTextureData(width, height); Q_ASSERT(image().depth() == 8); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, oldHeight, GL_ALPHA, GL_UNSIGNED_BYTE, image().constBits()); - glDeleteTextures(1, &oldTexture); + funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, oldHeight, GL_ALPHA, GL_UNSIGNED_BYTE, image().constBits()); + funcs->glDeleteTextures(1, &oldTexture); return; } - QOpenGLFunctions *funcs = ctx->contextHandle()->functions(); - // ### the QTextureGlyphCache API needs to be reworked to allow // ### resizeTextureData to fail funcs->glBindFramebuffer(GL_FRAMEBUFFER, m_textureResource->m_fbo); GLuint tmp_texture; - glGenTextures(1, &tmp_texture); - glBindTexture(GL_TEXTURE_2D, tmp_texture); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, oldWidth, oldHeight, 0, - GL_RGBA, GL_UNSIGNED_BYTE, NULL); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + funcs->glGenTextures(1, &tmp_texture); + funcs->glBindTexture(GL_TEXTURE_2D, tmp_texture); + funcs->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, oldWidth, oldHeight, 0, + GL_RGBA, GL_UNSIGNED_BYTE, NULL); + funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); m_filterMode = Nearest; - glBindTexture(GL_TEXTURE_2D, 0); + funcs->glBindTexture(GL_TEXTURE_2D, 0); funcs->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tmp_texture, 0); funcs->glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT); - glBindTexture(GL_TEXTURE_2D, oldTexture); + funcs->glBindTexture(GL_TEXTURE_2D, oldTexture); if (pex != 0) pex->transferMode(BrushDrawingMode); - glDisable(GL_STENCIL_TEST); - glDisable(GL_DEPTH_TEST); - glDisable(GL_SCISSOR_TEST); - glDisable(GL_BLEND); + funcs->glDisable(GL_STENCIL_TEST); + funcs->glDisable(GL_DEPTH_TEST); + funcs->glDisable(GL_SCISSOR_TEST); + funcs->glDisable(GL_BLEND); - glViewport(0, 0, oldWidth, oldHeight); + funcs->glViewport(0, 0, oldWidth, oldHeight); QGLShaderProgram *blitProgram = 0; if (pex == 0) { @@ -257,21 +257,21 @@ void QGLTextureGlyphCache::resizeTextureData(int width, int height) blitProgram->setUniformValue("imageTexture", QT_IMAGE_TEXTURE_UNIT); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + funcs->glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - glBindTexture(GL_TEXTURE_2D, m_textureResource->m_texture); + funcs->glBindTexture(GL_TEXTURE_2D, m_textureResource->m_texture); - glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, oldWidth, oldHeight); + funcs->glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, oldWidth, oldHeight); funcs->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, 0); - glDeleteTextures(1, &tmp_texture); - glDeleteTextures(1, &oldTexture); + funcs->glDeleteTextures(1, &tmp_texture); + funcs->glDeleteTextures(1, &oldTexture); funcs->glBindFramebuffer(GL_FRAMEBUFFER, ctx->d_ptr->current_fbo); if (pex != 0) { - glViewport(0, 0, pex->width, pex->height); + funcs->glViewport(0, 0, pex->width, pex->height); pex->updateClipScissorTest(); } } @@ -283,16 +283,17 @@ void QGLTextureGlyphCache::fillTexture(const Coord &c, glyph_t glyph, QFixed sub qWarning("QGLTextureGlyphCache::fillTexture: Called with no context"); return; } + QOpenGLFunctions *funcs = ctx->contextHandle()->functions(); if (!QGLFramebufferObject::hasOpenGLFramebufferObjects() || ctx->d_ptr->workaround_brokenFBOReadBack) { QImageTextureGlyphCache::fillTexture(c, glyph, subPixelPosition); - glBindTexture(GL_TEXTURE_2D, m_textureResource->m_texture); + funcs->glBindTexture(GL_TEXTURE_2D, m_textureResource->m_texture); const QImage &texture = image(); const uchar *bits = texture.constBits(); bits += c.y * texture.bytesPerLine() + c.x; for (int i=0; i<c.h; ++i) { - glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y + i, c.w, 1, GL_ALPHA, GL_UNSIGNED_BYTE, bits); + funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y + i, c.w, 1, GL_ALPHA, GL_UNSIGNED_BYTE, bits); bits += texture.bytesPerLine(); } return; @@ -329,14 +330,14 @@ void QGLTextureGlyphCache::fillTexture(const Coord &c, glyph_t glyph, QFixed sub } } - glBindTexture(GL_TEXTURE_2D, m_textureResource->m_texture); + funcs->glBindTexture(GL_TEXTURE_2D, m_textureResource->m_texture); if (mask.format() == QImage::Format_RGB32) { GLenum format = GL_RGBA; #if !defined(QT_OPENGL_ES_2) if (!ctx->contextHandle()->isOpenGLES()) format = GL_BGRA; #endif - glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y, maskWidth, maskHeight, format, GL_UNSIGNED_BYTE, mask.bits()); + funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y, maskWidth, maskHeight, format, GL_UNSIGNED_BYTE, mask.bits()); } else { // glTexSubImage2D() might cause some garbage to appear in the texture if the mask width is // not a multiple of four bytes. The bug appeared on a computer with 32-bit Windows Vista @@ -349,16 +350,16 @@ void QGLTextureGlyphCache::fillTexture(const Coord &c, glyph_t glyph, QFixed sub if (!ctx->d_ptr->workaround_brokenAlphaTexSubImage_init) { // don't know which driver versions exhibit this bug, so be conservative for now - const QByteArray vendorString(reinterpret_cast<const char*>(glGetString(GL_VENDOR))); + const QByteArray vendorString(reinterpret_cast<const char*>(funcs->glGetString(GL_VENDOR))); ctx->d_ptr->workaround_brokenAlphaTexSubImage = vendorString.indexOf("NVIDIA") >= 0; ctx->d_ptr->workaround_brokenAlphaTexSubImage_init = true; } if (ctx->d_ptr->workaround_brokenAlphaTexSubImage) { for (int i = 0; i < maskHeight; ++i) - glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y + i, maskWidth, 1, GL_ALPHA, GL_UNSIGNED_BYTE, mask.scanLine(i)); + funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y + i, maskWidth, 1, GL_ALPHA, GL_UNSIGNED_BYTE, mask.scanLine(i)); } else { - glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y, maskWidth, maskHeight, GL_ALPHA, GL_UNSIGNED_BYTE, mask.bits()); + funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y, maskWidth, maskHeight, GL_ALPHA, GL_UNSIGNED_BYTE, mask.bits()); } } } diff --git a/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h b/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h index 5ffbea8708..5c160ffd59 100644 --- a/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h +++ b/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h @@ -92,7 +92,7 @@ struct QGLGlyphTexture : public QOpenGLSharedResource if (ctx && m_fbo) ctx->contextHandle()->functions()->glDeleteFramebuffers(1, &m_fbo); if (m_width || m_height) - glDeleteTextures(1, &m_texture); + ctx->contextHandle()->functions()->glDeleteTextures(1, &m_texture); } void invalidateResource() diff --git a/src/opengl/opengl.pro b/src/opengl/opengl.pro index 5cd553a5e8..9c62d41d3e 100644 --- a/src/opengl/opengl.pro +++ b/src/opengl/opengl.pro @@ -12,7 +12,6 @@ load(qt_module) contains(QT_CONFIG, opengl):CONFIG += opengl contains(QT_CONFIG, opengles2):CONFIG += opengles2 -contains(QT_CONFIG, egl):CONFIG += egl HEADERS += qgl.h \ qgl_p.h \ @@ -54,5 +53,3 @@ SOURCES += qglshaderprogram.cpp \ gl2paintengineex/qpaintengineex_opengl2.cpp \ gl2paintengineex/qglcustomshaderstage.cpp \ gl2paintengineex/qtextureglyphcache_gl.cpp - -SOURCES += qgl_qpa.cpp diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp index 02ea6e45e3..d2c017fcac 100644 --- a/src/opengl/qgl.cpp +++ b/src/opengl/qgl.cpp @@ -70,6 +70,15 @@ #include "qlibrary.h" #include <qmutex.h> +#include "qsurfaceformat.h" +#include <private/qapplication_p.h> +#include <qpa/qplatformopenglcontext.h> +#include <qpa/qplatformwindow.h> + +#ifndef QT_OPENGL_ES_2 +#include <qopenglfunctions_1_1.h> +#endif + // #define QT_GL_CONTEXT_RESOURCE_DEBUG QT_BEGIN_NAMESPACE @@ -107,6 +116,7 @@ bool qgl_hasExtension(QOpenGLExtensions::OpenGLExtension extension) } QOpenGLExtensions::OpenGLExtensions extensions; + /* Returns the GL extensions for the current QOpenGLContext. If there is no current QOpenGLContext, a default context will be created and the extensions @@ -121,6 +131,20 @@ QOpenGLExtensions* qgl_extensions() return 0; } +QOpenGLFunctions *qgl_functions() +{ + return qgl_extensions(); // QOpenGLExtensions is just a subclass of QOpenGLFunctions +} + +#ifndef QT_OPENGL_ES_2 +QOpenGLFunctions_1_1 *qgl1_functions() +{ + QOpenGLFunctions_1_1 *f = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_1_1>(); + f->initializeOpenGLFunctions(); + return f; +} +#endif + struct QGLThreadContext { ~QGLThreadContext() { if (context) @@ -195,8 +219,6 @@ QGLSignalProxy *QGLSignalProxy::instance() \value NoDeprecatedFunctions Disables the use of deprecated functionality for OpenGL 3.x contexts. A context with deprecated functionality disabled is called a forward compatible context in the OpenGL specification. - - \sa {Sample Buffers Example} */ /***************************************************************************** @@ -420,6 +442,82 @@ QGLFormat::~QGLFormat() } /*! + Returns an OpenGL format for the window format specified by \a format. +*/ +QGLFormat QGLFormat::fromSurfaceFormat(const QSurfaceFormat &format) +{ + QGLFormat retFormat; + if (format.alphaBufferSize() >= 0) + retFormat.setAlphaBufferSize(format.alphaBufferSize()); + if (format.blueBufferSize() >= 0) + retFormat.setBlueBufferSize(format.blueBufferSize()); + if (format.greenBufferSize() >= 0) + retFormat.setGreenBufferSize(format.greenBufferSize()); + if (format.redBufferSize() >= 0) + retFormat.setRedBufferSize(format.redBufferSize()); + if (format.depthBufferSize() >= 0) + retFormat.setDepthBufferSize(format.depthBufferSize()); + if (format.samples() > 1) { + retFormat.setSampleBuffers(true); + retFormat.setSamples(format.samples()); + } + if (format.stencilBufferSize() > 0) { + retFormat.setStencil(true); + retFormat.setStencilBufferSize(format.stencilBufferSize()); + } + retFormat.setSwapInterval(format.swapInterval()); + retFormat.setDoubleBuffer(format.swapBehavior() != QSurfaceFormat::SingleBuffer); + retFormat.setStereo(format.stereo()); + retFormat.setVersion(format.majorVersion(), format.minorVersion()); + retFormat.setProfile(static_cast<QGLFormat::OpenGLContextProfile>(format.profile())); + return retFormat; +} + +/*! + Returns a window format for the OpenGL format specified by \a format. +*/ +QSurfaceFormat QGLFormat::toSurfaceFormat(const QGLFormat &format) +{ + QSurfaceFormat retFormat; + if (format.alpha()) + retFormat.setAlphaBufferSize(format.alphaBufferSize() == -1 ? 1 : format.alphaBufferSize()); + if (format.blueBufferSize() >= 0) + retFormat.setBlueBufferSize(format.blueBufferSize()); + if (format.greenBufferSize() >= 0) + retFormat.setGreenBufferSize(format.greenBufferSize()); + if (format.redBufferSize() >= 0) + retFormat.setRedBufferSize(format.redBufferSize()); + if (format.depth()) + retFormat.setDepthBufferSize(format.depthBufferSize() == -1 ? 1 : format.depthBufferSize()); + retFormat.setSwapBehavior(format.doubleBuffer() ? QSurfaceFormat::DoubleBuffer : QSurfaceFormat::SingleBuffer); + if (format.sampleBuffers()) + retFormat.setSamples(format.samples() == -1 ? 4 : format.samples()); + if (format.stencil()) + retFormat.setStencilBufferSize(format.stencilBufferSize() == -1 ? 1 : format.stencilBufferSize()); + retFormat.setSwapInterval(format.swapInterval()); + retFormat.setStereo(format.stereo()); + retFormat.setMajorVersion(format.majorVersion()); + retFormat.setMinorVersion(format.minorVersion()); + retFormat.setProfile(static_cast<QSurfaceFormat::OpenGLContextProfile>(format.profile())); + // QGLFormat has no way to set DeprecatedFunctions, that is, to tell that forward + // compatibility should not be requested. Some drivers fail to ignore the fwdcompat + // bit with compatibility profiles so make sure it is not set. + if (format.profile() == QGLFormat::CompatibilityProfile) + retFormat.setOption(QSurfaceFormat::DeprecatedFunctions); + return retFormat; +} + +void QGLContextPrivate::setupSharing() { + Q_Q(QGLContext); + QOpenGLContext *sharedContext = guiGlContext->shareContext(); + if (sharedContext) { + QGLContext *actualSharedContext = QGLContext::fromOpenGLContext(sharedContext); + sharing = true; + QGLContextGroup::addShare(q, actualSharedContext); + } +} + +/*! \fn bool QGLFormat::doubleBuffer() const Returns \c true if double buffering is enabled; otherwise returns @@ -1113,8 +1211,11 @@ QGLFormat::OpenGLContextProfile QGLFormat::profile() const \warning This function must not be called until the QApplication object has been created. */ - - +bool QGLFormat::hasOpenGL() +{ + return QApplicationPrivate::platformIntegration() + ->hasCapability(QPlatformIntegration::OpenGL); +} /*! \fn bool QGLFormat::hasOpenGLOverlays() @@ -1125,6 +1226,10 @@ QGLFormat::OpenGLContextProfile QGLFormat::profile() const \warning This function must not be called until the QApplication object has been created. */ +bool QGLFormat::hasOpenGLOverlays() +{ + return false; +} QGLFormat::OpenGLVersionFlags Q_AUTOTEST_EXPORT qOpenGLVersionFlagsFromString(const QString &versionString) { @@ -1355,7 +1460,7 @@ QGLFormat::OpenGLVersionFlags QGLFormat::openGLVersionFlags() } } - QString versionString(QLatin1String(reinterpret_cast<const char*>(glGetString(GL_VERSION)))); + QString versionString(QLatin1String(reinterpret_cast<const char*>(qgl_functions()->glGetString(GL_VERSION)))); OpenGLVersionFlags versionFlags = qOpenGLVersionFlagsFromString(versionString); if (currentCtx) { currentCtx->d_func()->version_flags_cached = true; @@ -1631,6 +1736,60 @@ void QGLContextPrivate::init(QPaintDevice *dev, const QGLFormat &format) QGLContext* QGLContext::currentCtx = 0; /* + QGLTemporaryContext implementation +*/ +class QGLTemporaryContextPrivate +{ +public: + QWindow *window; + QOpenGLContext *context; + + QGLContext *oldContext; +}; + +QGLTemporaryContext::QGLTemporaryContext(bool, QWidget *) + : d(new QGLTemporaryContextPrivate) +{ + d->oldContext = const_cast<QGLContext *>(QGLContext::currentContext()); + + d->window = new QWindow; + d->window->setSurfaceType(QWindow::OpenGLSurface); + d->window->setGeometry(QRect(0, 0, 3, 3)); + d->window->create(); + + d->context = new QOpenGLContext; +#if !defined(QT_OPENGL_ES) + if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL) { + // On desktop, request latest released version + QSurfaceFormat format; +#if defined(Q_OS_MAC) + // OS X is limited to OpenGL 3.2 Core Profile at present + // so set that here. If we use compatibility profile it + // only reports 2.x contexts. + format.setMajorVersion(3); + format.setMinorVersion(2); + format.setProfile(QSurfaceFormat::CoreProfile); +#else + format.setMajorVersion(4); + format.setMinorVersion(3); +#endif + d->context->setFormat(format); + } +#endif // QT_OPENGL_ES + d->context->create(); + d->context->makeCurrent(d->window); +} + +QGLTemporaryContext::~QGLTemporaryContext() +{ + if (d->oldContext) + d->oldContext->makeCurrent(); + + delete d->context; + delete d->window; +} + +/* Read back the contents of the currently bound framebuffer, used in QGLWidget::grabFrameBuffer(), QGLPixelbuffer::toImage() and QGLFramebufferObject::toImage() @@ -1687,7 +1846,7 @@ QImage qt_gl_read_frame_buffer(const QSize &size, bool alpha_format, bool includ return QImage(); int w = size.width(); int h = size.height(); - glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, img.bits()); + qgl_functions()->glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, img.bits()); convertFromGLImage(img, w, h, alpha_format, include_alpha); return img; } @@ -1701,28 +1860,14 @@ QImage qt_gl_read_texture(const QSize &size, bool alpha_format, bool include_alp int h = size.height(); #ifndef QT_OPENGL_ES if (!QOpenGLContext::currentContext()->isOpenGLES()) { - //### glGetTexImage not in GL ES 2.0, need to do something else here! - glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, img.bits()); + + qgl1_functions()->glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, img.bits()); } #endif // QT_OPENGL_ES convertFromGLImage(img, w, h, alpha_format, include_alpha); return img; } -// returns the highest number closest to v, which is a power of 2 -// NB! assumes 32 bit ints -int qt_next_power_of_two(int v) -{ - v--; - v |= v >> 1; - v |= v >> 2; - v |= v >> 4; - v |= v >> 8; - v |= v >> 16; - ++v; - return v; -} - Q_GLOBAL_STATIC(QGLTextureCache, qt_gl_texture_cache) QGLTextureCache::QGLTextureCache() @@ -1981,6 +2126,47 @@ QGLContext::QGLContext(const QGLFormat &format) d->init(0, format); } +static void qDeleteQGLContext(void *handle) +{ + QGLContext *context = static_cast<QGLContext *>(handle); + delete context; +} + +QGLContext::QGLContext(QOpenGLContext *context) + : d_ptr(new QGLContextPrivate(this)) +{ + Q_D(QGLContext); + d->init(0, QGLFormat::fromSurfaceFormat(context->format())); + d->guiGlContext = context; + d->guiGlContext->setQGLContextHandle(this, qDeleteQGLContext); + d->ownContext = false; + d->valid = context->isValid(); + d->setupSharing(); +} + +QOpenGLContext *QGLContext::contextHandle() const +{ + Q_D(const QGLContext); + return d->guiGlContext; +} + +/*! + Returns a OpenGL context for the window context specified by the \a context + parameter. +*/ +QGLContext *QGLContext::fromOpenGLContext(QOpenGLContext *context) +{ + if (!context) + return 0; + if (context->qGLContextHandle()) { + return reinterpret_cast<QGLContext *>(context->qGLContextHandle()); + } + QGLContext *glContext = new QGLContext(context); + //Don't call create on context. This can cause the platformFormat to be set on the widget, which + //will cause the platformWindow to be recreated. + return glContext; +} + /*! Destroys the OpenGL context and frees its resources. */ @@ -2193,7 +2379,7 @@ QGLTexture *QGLContextPrivate::bindTexture(const QImage &image, GLenum target, G q->deleteTexture(texture->id); texture = 0; } else { - glBindTexture(target, texture->id); + qgl_functions()->glBindTexture(target, texture->id); return texture; } } @@ -2245,6 +2431,7 @@ QGLTexture* QGLContextPrivate::bindTexture(const QImage &image, GLenum target, G const qint64 key, QGLContext::BindOptions options) { Q_Q(QGLContext); + QOpenGLFunctions *funcs = qgl_functions(); #ifdef QGL_BIND_TEXTURE_DEBUG printf("QGLContextPrivate::bindTexture(), imageSize=(%d,%d), internalFormat =0x%x, options=%x, key=%llx\n", @@ -2255,14 +2442,14 @@ QGLTexture* QGLContextPrivate::bindTexture(const QImage &image, GLenum target, G #ifndef QT_NO_DEBUG // Reset the gl error stack...git - while (glGetError() != GL_NO_ERROR) ; + while (funcs->glGetError() != GL_NO_ERROR) ; #endif // Scale the pixmap if needed. GL textures needs to have the // dimensions 2^n+2(border) x 2^m+2(border), unless we're using GL // 2.0 or use the GL_TEXTURE_RECTANGLE texture target - int tx_w = qt_next_power_of_two(image.width()); - int tx_h = qt_next_power_of_two(image.height()); + int tx_w = qNextPowerOfTwo(image.width() - 1); + int tx_h = qNextPowerOfTwo(image.height() - 1); QImage img = image; @@ -2280,9 +2467,9 @@ QGLTexture* QGLContextPrivate::bindTexture(const QImage &image, GLenum target, G GLuint filtering = options & QGLContext::LinearFilteringBindOption ? GL_LINEAR : GL_NEAREST; GLuint tx_id; - glGenTextures(1, &tx_id); - glBindTexture(target, tx_id); - glTexParameteri(target, GL_TEXTURE_MAG_FILTER, filtering); + funcs->glGenTextures(1, &tx_id); + funcs->glBindTexture(target, tx_id); + funcs->glTexParameteri(target, GL_TEXTURE_MAG_FILTER, filtering); QOpenGLContext *ctx = QOpenGLContext::currentContext(); bool genMipmap = !ctx->isOpenGLES(); @@ -2293,23 +2480,23 @@ QGLTexture* QGLContextPrivate::bindTexture(const QImage &image, GLenum target, G { #if !defined(QT_OPENGL_ES_2) if (genMipmap) { - glHint(GL_GENERATE_MIPMAP_HINT_SGIS, GL_NICEST); - glTexParameteri(target, GL_GENERATE_MIPMAP_SGIS, GL_TRUE); + funcs->glHint(GL_GENERATE_MIPMAP_HINT_SGIS, GL_NICEST); + funcs->glTexParameteri(target, GL_GENERATE_MIPMAP_SGIS, GL_TRUE); } else { - glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST); + funcs->glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST); genMipmap = true; } #else - glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST); + funcs->glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST); genMipmap = true; #endif - glTexParameteri(target, GL_TEXTURE_MIN_FILTER, options & QGLContext::LinearFilteringBindOption - ? GL_LINEAR_MIPMAP_LINEAR : GL_NEAREST_MIPMAP_NEAREST); + funcs->glTexParameteri(target, GL_TEXTURE_MIN_FILTER, options & QGLContext::LinearFilteringBindOption + ? GL_LINEAR_MIPMAP_LINEAR : GL_NEAREST_MIPMAP_NEAREST); #ifdef QGL_BIND_TEXTURE_DEBUG printf(" - generating mipmaps (%d ms)\n", time.elapsed()); #endif } else { - glTexParameteri(target, GL_TEXTURE_MIN_FILTER, filtering); + funcs->glTexParameteri(target, GL_TEXTURE_MIN_FILTER, filtering); } QImage::Format target_format = img.format(); @@ -2438,12 +2625,12 @@ QGLTexture* QGLContextPrivate::bindTexture(const QImage &image, GLenum target, G #endif const QImage &constRef = img; // to avoid detach in bits()... - glTexImage2D(target, 0, internalFormat, img.width(), img.height(), 0, externalFormat, - pixel_type, constRef.bits()); + funcs->glTexImage2D(target, 0, internalFormat, img.width(), img.height(), 0, externalFormat, + pixel_type, constRef.bits()); if (genMipmap && ctx->isOpenGLES()) q->functions()->glGenerateMipmap(target); #ifndef QT_NO_DEBUG - GLenum error = glGetError(); + GLenum error = funcs->glGetError(); if (error != GL_NO_ERROR) { qWarning(" - texture upload failed, error code 0x%x, enum: %d (%x)\n", error, target, target); } @@ -2491,7 +2678,7 @@ QGLTexture *QGLContextPrivate::bindTexture(const QPixmap &pixmap, GLenum target, q->deleteTexture(texture->id); texture = 0; } else { - glBindTexture(target, texture->id); + qgl_functions()->glBindTexture(target, texture->id); return texture; } } @@ -2532,7 +2719,8 @@ int QGLContextPrivate::maxTextureSize() if (max_texture_size != -1) return max_texture_size; - glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size); + QOpenGLFunctions *funcs = qgl_functions(); + funcs->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size); #ifndef QT_OPENGL_ES Q_Q(QGLContext); @@ -2541,8 +2729,9 @@ int QGLContextPrivate::maxTextureSize() GLint size; GLint next = 64; - glTexImage2D(proxy, 0, GL_RGBA, next, next, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); - glGetTexLevelParameteriv(proxy, 0, GL_TEXTURE_WIDTH, &size); + funcs->glTexImage2D(proxy, 0, GL_RGBA, next, next, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); + QOpenGLFunctions_1_1 *gl1funcs = qgl1_functions(); + gl1funcs->glGetTexLevelParameteriv(proxy, 0, GL_TEXTURE_WIDTH, &size); if (size == 0) { return max_texture_size; } @@ -2552,8 +2741,8 @@ int QGLContextPrivate::maxTextureSize() if (next > max_texture_size) break; - glTexImage2D(proxy, 0, GL_RGBA, next, next, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); - glGetTexLevelParameteriv(proxy, 0, GL_TEXTURE_WIDTH, &next); + funcs->glTexImage2D(proxy, 0, GL_RGBA, next, next, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); + gl1funcs->glGetTexLevelParameteriv(proxy, 0, GL_TEXTURE_WIDTH, &next); } while (next > size); max_texture_size = size; @@ -2670,7 +2859,7 @@ void QGLContext::deleteTexture(GLuint id) { if (QGLTextureCache::instance()->remove(this, id)) return; - glDeleteTextures(1, &id); + qgl_functions()->glDeleteTextures(1, &id); } void qt_add_rect_to_array(const QRectF &r, GLfloat *array) @@ -2706,6 +2895,7 @@ void qt_add_texcoords_to_array(qreal x1, qreal y1, qreal x2, qreal y2, GLfloat * static void qDrawTextureRect(const QRectF &target, GLint textureWidth, GLint textureHeight, GLenum textureTarget) { + QOpenGLFunctions *funcs = qgl_functions(); GLfloat tx = 1.0f; GLfloat ty = 1.0f; @@ -2716,8 +2906,9 @@ static void qDrawTextureRect(const QRectF &target, GLint textureWidth, GLint tex #else if (textureTarget != GL_TEXTURE_2D && !QOpenGLContext::currentContext()->isOpenGLES()) { if (textureWidth == -1 || textureHeight == -1) { - glGetTexLevelParameteriv(textureTarget, 0, GL_TEXTURE_WIDTH, &textureWidth); - glGetTexLevelParameteriv(textureTarget, 0, GL_TEXTURE_HEIGHT, &textureHeight); + QOpenGLFunctions_1_1 *gl1funcs = qgl1_functions(); + gl1funcs->glGetTexLevelParameteriv(textureTarget, 0, GL_TEXTURE_WIDTH, &textureWidth); + gl1funcs->glGetTexLevelParameteriv(textureTarget, 0, GL_TEXTURE_HEIGHT, &textureHeight); } tx = GLfloat(textureWidth); @@ -2732,15 +2923,16 @@ static void qDrawTextureRect(const QRectF &target, GLint textureWidth, GLint tex GLfloat vertexArray[4*2]; qt_add_rect_to_array(target, vertexArray); - glVertexPointer(2, GL_FLOAT, 0, vertexArray); - glTexCoordPointer(2, GL_FLOAT, 0, texCoordArray); + QOpenGLFunctions_1_1 *gl1funcs = qgl1_functions(); + gl1funcs->glVertexPointer(2, GL_FLOAT, 0, vertexArray); + gl1funcs->glTexCoordPointer(2, GL_FLOAT, 0, texCoordArray); - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + gl1funcs->glEnableClientState(GL_VERTEX_ARRAY); + gl1funcs->glEnableClientState(GL_TEXTURE_COORD_ARRAY); + funcs->glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); + gl1funcs->glDisableClientState(GL_VERTEX_ARRAY); + gl1funcs->glDisableClientState(GL_TEXTURE_COORD_ARRAY); } #endif // !QT_OPENGL_ES_2 @@ -2781,6 +2973,7 @@ void QGLContext::drawTexture(const QRectF &target, GLuint textureId, GLenum text #endif #ifndef QT_OPENGL_ES_2 + QOpenGLFunctions *funcs = qgl_functions(); if (!contextHandle()->isOpenGLES()) { #ifdef QT_OPENGL_ES if (textureTarget != GL_TEXTURE_2D) { @@ -2788,22 +2981,22 @@ void QGLContext::drawTexture(const QRectF &target, GLuint textureId, GLenum text return; } #else - const bool wasEnabled = glIsEnabled(GL_TEXTURE_2D); + const bool wasEnabled = funcs->glIsEnabled(GL_TEXTURE_2D); GLint oldTexture; - glGetIntegerv(GL_TEXTURE_BINDING_2D, &oldTexture); + funcs->glGetIntegerv(GL_TEXTURE_BINDING_2D, &oldTexture); #endif - glEnable(textureTarget); - glBindTexture(textureTarget, textureId); + funcs->glEnable(textureTarget); + funcs->glBindTexture(textureTarget, textureId); qDrawTextureRect(target, -1, -1, textureTarget); #ifdef QT_OPENGL_ES - glDisable(textureTarget); + funcs->glDisable(textureTarget); #else if (!wasEnabled) - glDisable(textureTarget); - glBindTexture(textureTarget, oldTexture); + funcs->glDisable(textureTarget); + funcs->glBindTexture(textureTarget, oldTexture); #endif return; } @@ -2844,18 +3037,20 @@ void QGLContext::drawTexture(const QPointF &point, GLuint textureId, GLenum text Q_UNUSED(textureTarget); #else if (!contextHandle()->isOpenGLES()) { - const bool wasEnabled = glIsEnabled(GL_TEXTURE_2D); + QOpenGLFunctions *funcs = qgl_functions(); + const bool wasEnabled = funcs->glIsEnabled(GL_TEXTURE_2D); GLint oldTexture; - glGetIntegerv(GL_TEXTURE_BINDING_2D, &oldTexture); + funcs->glGetIntegerv(GL_TEXTURE_BINDING_2D, &oldTexture); - glEnable(textureTarget); - glBindTexture(textureTarget, textureId); + funcs->glEnable(textureTarget); + funcs->glBindTexture(textureTarget, textureId); GLint textureWidth; GLint textureHeight; - glGetTexLevelParameteriv(textureTarget, 0, GL_TEXTURE_WIDTH, &textureWidth); - glGetTexLevelParameteriv(textureTarget, 0, GL_TEXTURE_HEIGHT, &textureHeight); + QOpenGLFunctions_1_1 *gl1funcs = qgl1_functions(); + gl1funcs->glGetTexLevelParameteriv(textureTarget, 0, GL_TEXTURE_WIDTH, &textureWidth); + gl1funcs->glGetTexLevelParameteriv(textureTarget, 0, GL_TEXTURE_HEIGHT, &textureHeight); if (d_ptr->active_engine && d_ptr->active_engine->type() == QPaintEngine::OpenGL2) { @@ -2872,8 +3067,8 @@ void QGLContext::drawTexture(const QPointF &point, GLuint textureId, GLenum text qDrawTextureRect(QRectF(point, QSizeF(textureWidth, textureHeight)), textureWidth, textureHeight, textureTarget); if (!wasEnabled) - glDisable(textureTarget); - glBindTexture(textureTarget, oldTexture); + funcs->glDisable(textureTarget); + funcs->glBindTexture(textureTarget, oldTexture); return; } #endif @@ -3031,7 +3226,10 @@ bool QGLContext::areSharing(const QGLContext *context1, const QGLContext *contex Returns a colormap index for the color c, in ColorIndex mode. Used by qglColor() and qglClearColor(). */ - +uint QGLContext::colorIndex(const QColor&) const +{ + return 0; +} /*! \fn bool QGLContext::initialized() const @@ -3076,10 +3274,12 @@ bool QGLContext::areSharing(const QGLContext *context1, const QGLContext *contex The returned QColor object will generally work as expected only when passed as the argument to QGLWidget::qglColor() or QGLWidget::qglClearColor(). Under certain circumstances it can - also be used to draw transparent graphics with a QPainter. See the - examples/opengl/overlay_x11 example for details. + also be used to draw transparent graphics with a QPainter. */ - +QColor QGLContext::overlayTransparentColor() const +{ + return QColor(); // Invalid color +} /*! Creates the GL context. Returns \c true if it was successful in @@ -3239,6 +3439,51 @@ void QGLContext::moveToThread(QThread *thread) the virtual function chooseVisual() which finds an appropriate X visual. On other platforms it may work differently. */ +bool QGLContext::chooseContext(const QGLContext* shareContext) +{ + Q_D(QGLContext); + if(!d->paintDevice || d->paintDevice->devType() != QInternal::Widget) { + // Unlike in Qt 4, the only possible target is a widget backed by an OpenGL-based + // QWindow. Pixmaps in particular are not supported anymore as paint devices since + // starting from Qt 5 QPixmap is raster-backed on almost all platforms. + d->valid = false; + }else { + QWidget *widget = static_cast<QWidget *>(d->paintDevice); + QGLFormat glformat = format(); + QSurfaceFormat winFormat = QGLFormat::toSurfaceFormat(glformat); + if (widget->testAttribute(Qt::WA_TranslucentBackground)) + winFormat.setAlphaBufferSize(qMax(winFormat.alphaBufferSize(), 8)); + + QWindow *window = widget->windowHandle(); + if (!window->handle() + || window->surfaceType() != QWindow::OpenGLSurface + || window->requestedFormat() != winFormat) + { + window->setSurfaceType(QWindow::OpenGLSurface); + window->setFormat(winFormat); + window->destroy(); + window->create(); + } + + if (d->ownContext) + delete d->guiGlContext; + d->ownContext = true; + QOpenGLContext *shareGlContext = shareContext ? shareContext->d_func()->guiGlContext : 0; + d->guiGlContext = new QOpenGLContext; + d->guiGlContext->setFormat(winFormat); + d->guiGlContext->setShareContext(shareGlContext); + d->valid = d->guiGlContext->create(); + + if (d->valid) + d->guiGlContext->setQGLContextHandle(this, 0); + + d->glFormat = QGLFormat::fromSurfaceFormat(d->guiGlContext->format()); + d->setupSharing(); + } + + + return d->valid; +} /*! \fn void QGLContext::reset() @@ -3247,7 +3492,33 @@ void QGLContext::moveToThread(QThread *thread) \sa create(), isValid() */ - +void QGLContext::reset() +{ + Q_D(QGLContext); + if (!d->valid) + return; + d->cleanup(); + + d->crWin = false; + d->sharing = false; + d->valid = false; + d->transpColor = QColor(); + d->initDone = false; + QGLContextGroup::removeShare(this); + if (d->guiGlContext) { + if (QOpenGLContext::currentContext() == d->guiGlContext) + doneCurrent(); + if (d->ownContext) { + if (d->guiGlContext->thread() == QThread::currentThread()) + delete d->guiGlContext; + else + d->guiGlContext->deleteLater(); + } else + d->guiGlContext->setQGLContextHandle(0,0); + d->guiGlContext = 0; + } + d->ownContext = false; +} /*! \fn void QGLContext::makeCurrent() @@ -3263,7 +3534,26 @@ void QGLContext::moveToThread(QThread *thread) make sure you've first pushed the context to the relevant thread from the UI thread using moveToThread(). */ +void QGLContext::makeCurrent() +{ + Q_D(QGLContext); + if (!d->paintDevice || d->paintDevice->devType() != QInternal::Widget) + return; + QWidget *widget = static_cast<QWidget *>(d->paintDevice); + if (!widget->windowHandle()) + return; + + if (d->guiGlContext->makeCurrent(widget->windowHandle())) { + if (!d->workaroundsCached) { + d->workaroundsCached = true; + const char *renderer = reinterpret_cast<const char *>(d->guiGlContext->functions()->glGetString(GL_RENDERER)); + if (renderer && strstr(renderer, "Mali")) { + d->workaround_brokenFBOReadBack = true; + } + } + } +} /*! \fn void QGLContext::swapBuffers() const @@ -3271,7 +3561,18 @@ void QGLContext::moveToThread(QThread *thread) Call this to finish a frame of OpenGL rendering, and make sure to call makeCurrent() again before you begin a new frame. */ +void QGLContext::swapBuffers() const +{ + Q_D(const QGLContext); + if (!d->paintDevice || d->paintDevice->devType() != QInternal::Widget) + return; + + QWidget *widget = static_cast<QWidget *>(d->paintDevice); + if (!widget->windowHandle()) + return; + d->guiGlContext->swapBuffers(widget->windowHandle()); +} /*! \fn void QGLContext::doneCurrent() @@ -3279,7 +3580,11 @@ void QGLContext::moveToThread(QThread *thread) Makes no GL context the current context. Normally, you do not need to call this function; QGLContext calls it as necessary. */ - +void QGLContext::doneCurrent() +{ + Q_D(QGLContext); + d->guiGlContext->doneCurrent(); +} /*! \fn QPaintDevice* QGLContext::device() const @@ -3289,7 +3594,6 @@ void QGLContext::moveToThread(QThread *thread) \sa QGLContext::QGLContext() */ - /***************************************************************************** QGLWidget implementation *****************************************************************************/ @@ -3307,6 +3611,11 @@ void QGLContext::moveToThread(QThread *thread) except that you have the choice between using QPainter and standard OpenGL rendering commands. + \note This class is part of the legacy \l {Qt OpenGL} module and, + like the other \c QGL classes, should be avoided in the new + applications. Instead, starting from Qt 5.4, prefer using + QOpenGLWidget and the \c QOpenGL classes. + QGLWidget provides three convenient virtual functions that you can reimplement in your subclass to perform the typical OpenGL tasks: @@ -3405,10 +3714,6 @@ void QGLContext::moveToThread(QThread *thread) \li Call QPainter::end() to finish painting. \endlist - Overpainting 2D content on top of 3D content takes a little more effort. - One approach to doing this is shown in the - \l{Overpainting Example}{Overpainting} example. - \section1 Threading As of Qt version 4.8, support for doing threaded GL rendering has @@ -3502,8 +3807,7 @@ void QGLContext::moveToThread(QThread *thread) \e{OpenGL is a trademark of Silicon Graphics, Inc. in the United States and other countries.} - \sa QGLPixelBuffer, {Hello GL Example}, {2D Painting Example}, {Overpainting Example}, - {Grabber Example} + \sa QOpenGLWidget, QGLPixelBuffer */ /*! @@ -3688,6 +3992,11 @@ QGLWidget::~QGLWidget() \a proc. 0 is returned if a pointer to the function could not be obtained. */ +QFunctionPointer QGLContext::getProcAddress(const QString &procName) const +{ + Q_D(const QGLContext); + return d->guiGlContext->getProcAddress(procName.toLatin1()); +} /*! \fn bool QGLWidget::isValid() const @@ -3775,8 +4084,10 @@ void QGLWidget::swapBuffers() \sa context() */ - - +const QGLContext* QGLWidget::overlayContext() const +{ + return 0; +} /*! \fn void QGLWidget::makeOverlayCurrent() @@ -3789,7 +4100,9 @@ void QGLWidget::swapBuffers() \sa makeCurrent() */ - +void QGLWidget::makeOverlayCurrent() +{ +} /*! \obsolete @@ -3865,8 +4178,28 @@ void QGLWidget::setFormat(const QGLFormat &format) \sa context(), isSharing() */ +void QGLWidget::setContext(QGLContext *context, + const QGLContext* shareContext, + bool deleteOldContext) +{ + Q_D(QGLWidget); + if (context == 0) { + qWarning("QGLWidget::setContext: Cannot set null context"); + return; + } + + if (context->device() == 0) // a context may refere to more than 1 window. + context->setDevice(this); //but its better to point to 1 of them than none of them. + + QGLContext* oldcx = d->glcx; + d->glcx = context; + if (!d->glcx->isValid()) + d->glcx->create(shareContext ? shareContext : oldcx); + if (deleteOldContext) + delete oldcx; +} /*! \fn void QGLWidget::updateGL() @@ -3892,7 +4225,9 @@ void QGLWidget::updateGL() The widget's rendering context will become the current context and initializeGL() will be called if it hasn't already been called. */ - +void QGLWidget::updateOverlayGL() +{ +} /*! This virtual function is called once before the first call to @@ -3921,7 +4256,7 @@ void QGLWidget::initializeGL() void QGLWidget::paintGL() { - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + qgl_functions()->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } @@ -3994,6 +4329,20 @@ void QGLWidget::resizeOverlayGL(int, int) { } +bool QGLWidget::event(QEvent *e) +{ + Q_D(QGLWidget); + + // A re-parent will destroy the window and re-create it. We should not reset the context while it happens. + if (e->type() == QEvent::ParentAboutToChange) + d->parent_changing = true; + + if (e->type() == QEvent::ParentChange) + d->parent_changing = false; + + return QWidget::event(e); +} + /*! \fn void QGLWidget::paintEvent(QPaintEvent *event) @@ -4019,7 +4368,21 @@ void QGLWidget::paintEvent(QPaintEvent *) Handles resize events that are passed in the \a event parameter. Calls the virtual function resizeGL(). */ +void QGLWidget::resizeEvent(QResizeEvent *e) +{ + Q_D(QGLWidget); + QWidget::resizeEvent(e); + if (!isValid()) + return; + makeCurrent(); + if (!d->glcx->initialized()) + glInit(); + const qreal scaleFactor = (window() && window()->windowHandle()) ? + window()->windowHandle()->devicePixelRatio() : 1.0; + + resizeGL(width() * scaleFactor, height() * scaleFactor); +} /*! Renders the current scene on a pixmap and returns the pixmap. @@ -4148,7 +4511,7 @@ void QGLWidget::glDraw() makeCurrent(); #ifndef QT_OPENGL_ES if (d->glcx->deviceIsPixmap() && !d->glcx->contextHandle()->isOpenGLES()) - glDrawBuffer(GL_FRONT); + qgl1_functions()->glDrawBuffer(GL_FRONT); #endif QSize readback_target_size = d->glcx->d_ptr->readback_target_size; if (!d->glcx->initialized()) { @@ -4170,7 +4533,7 @@ void QGLWidget::glDraw() if (d->autoSwap) swapBuffers(); } else { - glFlush(); + qgl_functions()->glFlush(); } } @@ -4188,20 +4551,20 @@ void QGLWidget::qglColor(const QColor& c) const { #if !defined(QT_OPENGL_ES_2) #ifdef QT_OPENGL_ES - glColor4f(c.redF(), c.greenF(), c.blueF(), c.alphaF()); + qgl_functions()->glColor4f(c.redF(), c.greenF(), c.blueF(), c.alphaF()); #else Q_D(const QGLWidget); const QGLContext *ctx = QGLContext::currentContext(); if (ctx && !ctx->contextHandle()->isOpenGLES()) { if (ctx->format().rgba()) - glColor4f(c.redF(), c.greenF(), c.blueF(), c.alphaF()); + qgl1_functions()->glColor4f(c.redF(), c.greenF(), c.blueF(), c.alphaF()); else if (!d->cmap.isEmpty()) { // QGLColormap in use? int i = d->cmap.find(c.rgb()); if (i < 0) i = d->cmap.findNearest(c.rgb()); - glIndexi(i); + qgl1_functions()->glIndexi(i); } else - glIndexi(ctx->colorIndex(c)); + qgl1_functions()->glIndexi(ctx->colorIndex(c)); } #endif //QT_OPENGL_ES #else @@ -4220,23 +4583,23 @@ void QGLWidget::qglColor(const QColor& c) const void QGLWidget::qglClearColor(const QColor& c) const { #ifdef QT_OPENGL_ES - glClearColor(c.redF(), c.greenF(), c.blueF(), c.alphaF()); + qgl_functions()->glClearColor(c.redF(), c.greenF(), c.blueF(), c.alphaF()); #else Q_D(const QGLWidget); const QGLContext *ctx = QGLContext::currentContext(); if (ctx && !ctx->contextHandle()->isOpenGLES()) { if (ctx->format().rgba()) - glClearColor(c.redF(), c.greenF(), c.blueF(), c.alphaF()); + qgl_functions()->glClearColor(c.redF(), c.greenF(), c.blueF(), c.alphaF()); else if (!d->cmap.isEmpty()) { // QGLColormap in use? int i = d->cmap.find(c.rgb()); if (i < 0) i = d->cmap.findNearest(c.rgb()); - glClearIndex(i); + qgl1_functions()->glClearIndex(i); } else { - glClearIndex(ctx->colorIndex(c)); + qgl1_functions()->glClearIndex(ctx->colorIndex(c)); } } else { - glClearColor(c.redF(), c.greenF(), c.blueF(), c.alphaF()); + qgl_functions()->glClearColor(c.redF(), c.greenF(), c.blueF(), c.alphaF()); } #endif } @@ -4305,6 +4668,11 @@ QImage QGLWidget::convertToGLFormat(const QImage& img) \sa setColormap(), QGLColormap::isEmpty() */ +const QGLColormap & QGLWidget::colormap() const +{ + Q_D(const QGLWidget); + return d->cmap; +} /*! \fn void QGLWidget::setColormap(const QGLColormap & cmap) @@ -4314,47 +4682,56 @@ QImage QGLWidget::convertToGLFormat(const QImage& img) \sa colormap() */ +void QGLWidget::setColormap(const QGLColormap & c) +{ + Q_UNUSED(c); +} #ifndef QT_OPENGL_ES static void qt_save_gl_state() { - glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS); - glPushAttrib(GL_ALL_ATTRIB_BITS); - glMatrixMode(GL_TEXTURE); - glPushMatrix(); - glLoadIdentity(); - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - - glShadeModel(GL_FLAT); - glDisable(GL_CULL_FACE); - glDisable(GL_LIGHTING); - glDisable(GL_STENCIL_TEST); - glDisable(GL_DEPTH_TEST); - glEnable(GL_BLEND); - glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + QOpenGLFunctions *funcs = qgl_functions(); + QOpenGLFunctions_1_1 *gl1funcs = qgl1_functions(); + + gl1funcs->glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS); + gl1funcs->glPushAttrib(GL_ALL_ATTRIB_BITS); + gl1funcs->glMatrixMode(GL_TEXTURE); + gl1funcs->glPushMatrix(); + gl1funcs->glLoadIdentity(); + gl1funcs->glMatrixMode(GL_PROJECTION); + gl1funcs->glPushMatrix(); + gl1funcs->glMatrixMode(GL_MODELVIEW); + gl1funcs->glPushMatrix(); + + gl1funcs->glShadeModel(GL_FLAT); + funcs->glDisable(GL_CULL_FACE); + funcs->glDisable(GL_LIGHTING); + funcs->glDisable(GL_STENCIL_TEST); + funcs->glDisable(GL_DEPTH_TEST); + funcs->glEnable(GL_BLEND); + funcs->glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); } static void qt_restore_gl_state() { - glMatrixMode(GL_TEXTURE); - glPopMatrix(); - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); - glPopAttrib(); - glPopClientAttrib(); + QOpenGLFunctions_1_1 *gl1funcs = qgl1_functions(); + + gl1funcs->glMatrixMode(GL_TEXTURE); + gl1funcs->glPopMatrix(); + gl1funcs->glMatrixMode(GL_PROJECTION); + gl1funcs->glPopMatrix(); + gl1funcs->glMatrixMode(GL_MODELVIEW); + gl1funcs->glPopMatrix(); + gl1funcs->glPopAttrib(); + gl1funcs->glPopClientAttrib(); } static void qt_gl_draw_text(QPainter *p, int x, int y, const QString &str, const QFont &font) { GLfloat color[4]; - glGetFloatv(GL_CURRENT_COLOR, &color[0]); + qgl_functions()->glGetFloatv(GL_CURRENT_COLOR, &color[0]); QColor col; col.setRgbF(color[0], color[1], color[2],color[3]); @@ -4391,8 +4768,6 @@ static void qt_gl_draw_text(QPainter *p, int x, int y, const QString &str, \note This function can only be used inside a QPainter::beginNativePainting()/QPainter::endNativePainting() block if a painter is active on the QGLWidget. - - \l{Overpainting Example}{Overpaint} with QPainter::drawText() instead. */ void QGLWidget::renderText(int x, int y, const QString &str, const QFont &font) @@ -4404,10 +4779,11 @@ void QGLWidget::renderText(int x, int y, const QString &str, const QFont &font) if (str.isEmpty() || !isValid()) return; + QOpenGLFunctions *funcs = qgl_functions(); GLint view[4]; - bool use_scissor_testing = glIsEnabled(GL_SCISSOR_TEST); + bool use_scissor_testing = funcs->glIsEnabled(GL_SCISSOR_TEST); if (!use_scissor_testing) - glGetIntegerv(GL_VIEWPORT, &view[0]); + funcs->glGetIntegerv(GL_VIEWPORT, &view[0]); int width = d->glcx->device()->width(); int height = d->glcx->device()->height(); bool auto_swap = autoBufferSwap(); @@ -4422,8 +4798,8 @@ void QGLWidget::renderText(int x, int y, const QString &str, const QFont &font) reuse_painter = true; p = engine->painter(); - glDisable(GL_DEPTH_TEST); - glViewport(0, 0, width, height); + funcs->glDisable(GL_DEPTH_TEST); + funcs->glViewport(0, 0, width, height); } else { setAutoBufferSwap(false); // disable glClear() as a result of QPainter::begin() @@ -4435,11 +4811,11 @@ void QGLWidget::renderText(int x, int y, const QString &str, const QFont &font) if (!use_scissor_testing && viewport != rect()) { // if the user hasn't set a scissor box, we set one that // covers the current viewport - glScissor(view[0], view[1], view[2], view[3]); - glEnable(GL_SCISSOR_TEST); + funcs->glScissor(view[0], view[1], view[2], view[3]); + funcs->glEnable(GL_SCISSOR_TEST); } else if (use_scissor_testing) { // use the scissor box set by the user - glEnable(GL_SCISSOR_TEST); + funcs->glEnable(GL_SCISSOR_TEST); } qt_gl_draw_text(p, x, y, str, font); @@ -4482,8 +4858,6 @@ void QGLWidget::renderText(int x, int y, const QString &str, const QFont &font) \note This function can only be used inside a QPainter::beginNativePainting()/QPainter::endNativePainting() block if a painter is active on the QGLWidget. - - \l{Overpainting Example}{Overpaint} with QPainter::drawText() instead. */ void QGLWidget::renderText(double x, double y, double z, const QString &str, const QFont &font) { @@ -4494,15 +4868,17 @@ void QGLWidget::renderText(double x, double y, double z, const QString &str, con if (str.isEmpty() || !isValid()) return; + QOpenGLFunctions *funcs = qgl_functions(); bool auto_swap = autoBufferSwap(); int width = d->glcx->device()->width(); int height = d->glcx->device()->height(); GLdouble model[4 * 4], proj[4 * 4]; GLint view[4]; - glGetDoublev(GL_MODELVIEW_MATRIX, &model[0]); - glGetDoublev(GL_PROJECTION_MATRIX, &proj[0]); - glGetIntegerv(GL_VIEWPORT, &view[0]); + QOpenGLFunctions_1_1 *gl1funcs = qgl1_functions(); + gl1funcs->glGetDoublev(GL_MODELVIEW_MATRIX, &model[0]); + gl1funcs->glGetDoublev(GL_PROJECTION_MATRIX, &proj[0]); + funcs->glGetIntegerv(GL_VIEWPORT, &view[0]); GLdouble win_x = 0, win_y = 0, win_z = 0; qgluProject(x, y, z, &model[0], &proj[0], &view[0], &win_x, &win_y, &win_z); @@ -4512,8 +4888,8 @@ void QGLWidget::renderText(double x, double y, double z, const QString &str, con QPainter *p; bool reuse_painter = false; - bool use_depth_testing = glIsEnabled(GL_DEPTH_TEST); - bool use_scissor_testing = glIsEnabled(GL_SCISSOR_TEST); + bool use_depth_testing = funcs->glIsEnabled(GL_DEPTH_TEST); + bool use_scissor_testing = funcs->glIsEnabled(GL_SCISSOR_TEST); qt_save_gl_state(); @@ -4529,16 +4905,16 @@ void QGLWidget::renderText(double x, double y, double z, const QString &str, con QRect viewport(view[0], view[1], view[2], view[3]); if (!use_scissor_testing && viewport != rect()) { - glScissor(view[0], view[1], view[2], view[3]); - glEnable(GL_SCISSOR_TEST); + funcs->glScissor(view[0], view[1], view[2], view[3]); + funcs->glEnable(GL_SCISSOR_TEST); } else if (use_scissor_testing) { - glEnable(GL_SCISSOR_TEST); + funcs->glEnable(GL_SCISSOR_TEST); } - glViewport(0, 0, width, height); - glAlphaFunc(GL_GREATER, 0.0); - glEnable(GL_ALPHA_TEST); + funcs->glViewport(0, 0, width, height); + gl1funcs->glAlphaFunc(GL_GREATER, 0.0); + funcs->glEnable(GL_ALPHA_TEST); if (use_depth_testing) - glEnable(GL_DEPTH_TEST); + funcs->glEnable(GL_DEPTH_TEST); // The only option in Qt 5 is the shader-based OpenGL 2 paint engine. // Setting fixed pipeline transformations is futile. Instead, pass the @@ -4731,6 +5107,11 @@ QPaintEngine *QGLWidget::paintEngine() const return qt_qgl_paint_engine(); } +void QGLWidgetPrivate::init(QGLContext *context, const QGLWidget *shareWidget) +{ + initContext(context, shareWidget); +} + /* This is the shared initialization for all platforms. Called from QGLWidgetPrivate::init() */ @@ -4751,6 +5132,19 @@ void QGLWidgetPrivate::initContext(QGLContext *context, const QGLWidget* shareWi glcx = new QGLContext(QGLFormat::defaultFormat(), q); } +bool QGLWidgetPrivate::renderCxPm(QPixmap*) +{ + return false; +} + +/*! \internal + Free up any allocated colormaps. This fn is only called for + top-level widgets. +*/ +void QGLWidgetPrivate::cleanupColormaps() +{ +} + Q_GLOBAL_STATIC(QString, qt_gl_lib_name) void qt_set_gl_library_name(const QString& name) @@ -4976,10 +5370,11 @@ QSize QGLTexture::bindCompressedTextureDDS(const char *buf, int len) const GLubyte *pixels = reinterpret_cast<const GLubyte *>(buf + ddsHeader->dwSize + 4); - glGenTextures(1, &id); - glBindTexture(GL_TEXTURE_2D, id); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + QOpenGLFunctions *funcs = qgl_functions(); + funcs->glGenTextures(1, &id); + funcs->glBindTexture(GL_TEXTURE_2D, id); + funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); int size; int offset = 0; @@ -5072,23 +5467,24 @@ QSize QGLTexture::bindCompressedTexturePVR(const char *buf, int len) } // Create the texture. - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glGenTextures(1, &id); - glBindTexture(GL_TEXTURE_2D, id); + QOpenGLFunctions *funcs = qgl_functions(); + funcs->glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + funcs->glGenTextures(1, &id); + funcs->glBindTexture(GL_TEXTURE_2D, id); if (pvrHeader->mipMapCount) { if ((options & QGLContext::LinearFilteringBindOption) != 0) { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); } else { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); + funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); } } else if ((options & QGLContext::LinearFilteringBindOption) != 0) { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); } else { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); } // Load the compressed mipmap levels. @@ -5114,7 +5510,7 @@ QSize QGLTexture::bindCompressedTexturePVR(const char *buf, int len) } // Restore the default pixel alignment for later texture uploads. - glPixelStorei(GL_UNPACK_ALIGNMENT, 4); + funcs->glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // Set the invert flag for the texture. The "vertical flip" // flag in PVR is the opposite sense to our sense of inversion. diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h index ac4b6d2acc..fb71e60ba9 100644 --- a/src/opengl/qgl_p.h +++ b/src/opengl/qgl_p.h @@ -347,7 +347,7 @@ public: private: static void freeTextureFunc(QOpenGLFunctions *, GLuint id) { - glDeleteTextures(1, &id); + QOpenGLContext::currentContext()->functions()->glDeleteTextures(1, &id); } }; diff --git a/src/opengl/qgl_qpa.cpp b/src/opengl/qgl_qpa.cpp deleted file mode 100644 index 6194f82922..0000000000 --- a/src/opengl/qgl_qpa.cpp +++ /dev/null @@ -1,466 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtOpenGL module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <QApplication> -#include <private/qapplication_p.h> -#include <QPixmap> -#include <QDebug> - -#include <qpa/qplatformopenglcontext.h> -#include <qpa/qplatformwindow.h> -#include <QtGui/QSurfaceFormat> - -#include "qgl.h" -#include "qgl_p.h" - -QT_BEGIN_NAMESPACE - -/*! - Returns an OpenGL format for the window format specified by \a format. -*/ -QGLFormat QGLFormat::fromSurfaceFormat(const QSurfaceFormat &format) -{ - QGLFormat retFormat; - if (format.alphaBufferSize() >= 0) - retFormat.setAlphaBufferSize(format.alphaBufferSize()); - if (format.blueBufferSize() >= 0) - retFormat.setBlueBufferSize(format.blueBufferSize()); - if (format.greenBufferSize() >= 0) - retFormat.setGreenBufferSize(format.greenBufferSize()); - if (format.redBufferSize() >= 0) - retFormat.setRedBufferSize(format.redBufferSize()); - if (format.depthBufferSize() >= 0) - retFormat.setDepthBufferSize(format.depthBufferSize()); - if (format.samples() > 1) { - retFormat.setSampleBuffers(true); - retFormat.setSamples(format.samples()); - } - if (format.stencilBufferSize() > 0) { - retFormat.setStencil(true); - retFormat.setStencilBufferSize(format.stencilBufferSize()); - } - retFormat.setSwapInterval(format.swapInterval()); - retFormat.setDoubleBuffer(format.swapBehavior() != QSurfaceFormat::SingleBuffer); - retFormat.setStereo(format.stereo()); - retFormat.setVersion(format.majorVersion(), format.minorVersion()); - retFormat.setProfile(static_cast<QGLFormat::OpenGLContextProfile>(format.profile())); - return retFormat; -} - -/*! - Returns a window format for the OpenGL format specified by \a format. -*/ -QSurfaceFormat QGLFormat::toSurfaceFormat(const QGLFormat &format) -{ - QSurfaceFormat retFormat; - if (format.alpha()) - retFormat.setAlphaBufferSize(format.alphaBufferSize() == -1 ? 1 : format.alphaBufferSize()); - if (format.blueBufferSize() >= 0) - retFormat.setBlueBufferSize(format.blueBufferSize()); - if (format.greenBufferSize() >= 0) - retFormat.setGreenBufferSize(format.greenBufferSize()); - if (format.redBufferSize() >= 0) - retFormat.setRedBufferSize(format.redBufferSize()); - if (format.depth()) - retFormat.setDepthBufferSize(format.depthBufferSize() == -1 ? 1 : format.depthBufferSize()); - retFormat.setSwapBehavior(format.doubleBuffer() ? QSurfaceFormat::DoubleBuffer : QSurfaceFormat::SingleBuffer); - if (format.sampleBuffers()) - retFormat.setSamples(format.samples() == -1 ? 4 : format.samples()); - if (format.stencil()) - retFormat.setStencilBufferSize(format.stencilBufferSize() == -1 ? 1 : format.stencilBufferSize()); - retFormat.setSwapInterval(format.swapInterval()); - retFormat.setStereo(format.stereo()); - retFormat.setMajorVersion(format.majorVersion()); - retFormat.setMinorVersion(format.minorVersion()); - retFormat.setProfile(static_cast<QSurfaceFormat::OpenGLContextProfile>(format.profile())); - // QGLFormat has no way to set DeprecatedFunctions, that is, to tell that forward - // compatibility should not be requested. Some drivers fail to ignore the fwdcompat - // bit with compatibility profiles so make sure it is not set. - if (format.profile() == QGLFormat::CompatibilityProfile) - retFormat.setOption(QSurfaceFormat::DeprecatedFunctions); - return retFormat; -} - -void QGLContextPrivate::setupSharing() { - Q_Q(QGLContext); - QOpenGLContext *sharedContext = guiGlContext->shareContext(); - if (sharedContext) { - QGLContext *actualSharedContext = QGLContext::fromOpenGLContext(sharedContext); - sharing = true; - QGLContextGroup::addShare(q, actualSharedContext); - } -} - -bool QGLFormat::hasOpenGL() -{ - return QApplicationPrivate::platformIntegration() - ->hasCapability(QPlatformIntegration::OpenGL); -} - -static void qDeleteQGLContext(void *handle) -{ - QGLContext *context = static_cast<QGLContext *>(handle); - delete context; -} - -bool QGLContext::chooseContext(const QGLContext* shareContext) -{ - Q_D(QGLContext); - if(!d->paintDevice || d->paintDevice->devType() != QInternal::Widget) { - // Unlike in Qt 4, the only possible target is a widget backed by an OpenGL-based - // QWindow. Pixmaps in particular are not supported anymore as paint devices since - // starting from Qt 5 QPixmap is raster-backed on almost all platforms. - d->valid = false; - }else { - QWidget *widget = static_cast<QWidget *>(d->paintDevice); - QGLFormat glformat = format(); - QSurfaceFormat winFormat = QGLFormat::toSurfaceFormat(glformat); - if (widget->testAttribute(Qt::WA_TranslucentBackground)) - winFormat.setAlphaBufferSize(qMax(winFormat.alphaBufferSize(), 8)); - - QWindow *window = widget->windowHandle(); - if (!window->handle() - || window->surfaceType() != QWindow::OpenGLSurface - || window->requestedFormat() != winFormat) - { - window->setSurfaceType(QWindow::OpenGLSurface); - window->setFormat(winFormat); - window->destroy(); - window->create(); - } - - if (d->ownContext) - delete d->guiGlContext; - d->ownContext = true; - QOpenGLContext *shareGlContext = shareContext ? shareContext->d_func()->guiGlContext : 0; - d->guiGlContext = new QOpenGLContext; - d->guiGlContext->setFormat(winFormat); - d->guiGlContext->setShareContext(shareGlContext); - d->valid = d->guiGlContext->create(); - - if (d->valid) - d->guiGlContext->setQGLContextHandle(this, 0); - - d->glFormat = QGLFormat::fromSurfaceFormat(d->guiGlContext->format()); - d->setupSharing(); - } - - - return d->valid; -} - -void QGLContext::reset() -{ - Q_D(QGLContext); - if (!d->valid) - return; - d->cleanup(); - - d->crWin = false; - d->sharing = false; - d->valid = false; - d->transpColor = QColor(); - d->initDone = false; - QGLContextGroup::removeShare(this); - if (d->guiGlContext) { - if (QOpenGLContext::currentContext() == d->guiGlContext) - doneCurrent(); - if (d->ownContext) { - if (d->guiGlContext->thread() == QThread::currentThread()) - delete d->guiGlContext; - else - d->guiGlContext->deleteLater(); - } else - d->guiGlContext->setQGLContextHandle(0,0); - d->guiGlContext = 0; - } - d->ownContext = false; -} - -void QGLContext::makeCurrent() -{ - Q_D(QGLContext); - if (!d->paintDevice || d->paintDevice->devType() != QInternal::Widget) - return; - - QWidget *widget = static_cast<QWidget *>(d->paintDevice); - if (!widget->windowHandle()) - return; - - if (d->guiGlContext->makeCurrent(widget->windowHandle())) { - if (!d->workaroundsCached) { - d->workaroundsCached = true; - const char *renderer = reinterpret_cast<const char *>(glGetString(GL_RENDERER)); - if (renderer && strstr(renderer, "Mali")) { - d->workaround_brokenFBOReadBack = true; - } - } - } -} - -void QGLContext::doneCurrent() -{ - Q_D(QGLContext); - d->guiGlContext->doneCurrent(); -} - -void QGLContext::swapBuffers() const -{ - Q_D(const QGLContext); - if (!d->paintDevice || d->paintDevice->devType() != QInternal::Widget) - return; - - QWidget *widget = static_cast<QWidget *>(d->paintDevice); - if (!widget->windowHandle()) - return; - - d->guiGlContext->swapBuffers(widget->windowHandle()); -} - -QFunctionPointer QGLContext::getProcAddress(const QString &procName) const -{ - Q_D(const QGLContext); - return d->guiGlContext->getProcAddress(procName.toLatin1()); -} - -void QGLWidget::setContext(QGLContext *context, - const QGLContext* shareContext, - bool deleteOldContext) -{ - Q_D(QGLWidget); - if (context == 0) { - qWarning("QGLWidget::setContext: Cannot set null context"); - return; - } - - if (context->device() == 0) // a context may refere to more than 1 window. - context->setDevice(this); //but its better to point to 1 of them than none of them. - - QGLContext* oldcx = d->glcx; - d->glcx = context; - - if (!d->glcx->isValid()) - d->glcx->create(shareContext ? shareContext : oldcx); - - if (deleteOldContext) - delete oldcx; -} - -void QGLWidgetPrivate::init(QGLContext *context, const QGLWidget *shareWidget) -{ - initContext(context, shareWidget); -} - -bool QGLFormat::hasOpenGLOverlays() -{ - return false; -} - -QColor QGLContext::overlayTransparentColor() const -{ - return QColor(); // Invalid color -} - -uint QGLContext::colorIndex(const QColor&) const -{ - return 0; -} - -/* - QGLTemporaryContext implementation -*/ -class QGLTemporaryContextPrivate -{ -public: - QWindow *window; - QOpenGLContext *context; - - QGLContext *oldContext; -}; - -QGLTemporaryContext::QGLTemporaryContext(bool, QWidget *) - : d(new QGLTemporaryContextPrivate) -{ - d->oldContext = const_cast<QGLContext *>(QGLContext::currentContext()); - - d->window = new QWindow; - d->window->setSurfaceType(QWindow::OpenGLSurface); - d->window->setGeometry(QRect(0, 0, 3, 3)); - d->window->create(); - - d->context = new QOpenGLContext; -#if !defined(QT_OPENGL_ES) - if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL) { - // On desktop, request latest released version - QSurfaceFormat format; -#if defined(Q_OS_MAC) - // OS X is limited to OpenGL 3.2 Core Profile at present - // so set that here. If we use compatibility profile it - // only reports 2.x contexts. - format.setMajorVersion(3); - format.setMinorVersion(2); - format.setProfile(QSurfaceFormat::CoreProfile); -#else - format.setMajorVersion(4); - format.setMinorVersion(3); -#endif - d->context->setFormat(format); - } -#endif // QT_OPENGL_ES - d->context->create(); - d->context->makeCurrent(d->window); -} - -QGLTemporaryContext::~QGLTemporaryContext() -{ - if (d->oldContext) - d->oldContext->makeCurrent(); - - delete d->context; - delete d->window; -} - - -bool QGLWidgetPrivate::renderCxPm(QPixmap*) -{ - return false; -} - -/*! \internal - Free up any allocated colormaps. This fn is only called for - top-level widgets. -*/ -void QGLWidgetPrivate::cleanupColormaps() -{ -} - -bool QGLWidget::event(QEvent *e) -{ - Q_D(QGLWidget); - - // A re-parent will destroy the window and re-create it. We should not reset the context while it happens. - if (e->type() == QEvent::ParentAboutToChange) - d->parent_changing = true; - - if (e->type() == QEvent::ParentChange) - d->parent_changing = false; - - return QWidget::event(e); -} - -void QGLWidget::resizeEvent(QResizeEvent *e) -{ - Q_D(QGLWidget); - - QWidget::resizeEvent(e); - if (!isValid()) - return; - makeCurrent(); - if (!d->glcx->initialized()) - glInit(); - const qreal scaleFactor = (window() && window()->windowHandle()) ? - window()->windowHandle()->devicePixelRatio() : 1.0; - - resizeGL(width() * scaleFactor, height() * scaleFactor); -} - - -const QGLContext* QGLWidget::overlayContext() const -{ - return 0; -} - -void QGLWidget::makeOverlayCurrent() -{ -} - - -void QGLWidget::updateOverlayGL() -{ -} - -const QGLColormap & QGLWidget::colormap() const -{ - Q_D(const QGLWidget); - return d->cmap; -} - -void QGLWidget::setColormap(const QGLColormap & c) -{ - Q_UNUSED(c); -} - -QGLContext::QGLContext(QOpenGLContext *context) - : d_ptr(new QGLContextPrivate(this)) -{ - Q_D(QGLContext); - d->init(0, QGLFormat::fromSurfaceFormat(context->format())); - d->guiGlContext = context; - d->guiGlContext->setQGLContextHandle(this,qDeleteQGLContext); - d->ownContext = false; - d->valid = context->isValid(); - d->setupSharing(); -} - -QOpenGLContext *QGLContext::contextHandle() const -{ - Q_D(const QGLContext); - return d->guiGlContext; -} - -/*! - Returns a OpenGL context for the window context specified by the \a context - parameter. -*/ -QGLContext *QGLContext::fromOpenGLContext(QOpenGLContext *context) -{ - if (!context) - return 0; - if (context->qGLContextHandle()) { - return reinterpret_cast<QGLContext *>(context->qGLContextHandle()); - } - QGLContext *glContext = new QGLContext(context); - //Don't call create on context. This can cause the platformFormat to be set on the widget, which - //will cause the platformWindow to be recreated. - return glContext; -} - -QT_END_NAMESPACE diff --git a/src/opengl/qglbuffer.cpp b/src/opengl/qglbuffer.cpp index 1c9545990f..525fc15829 100644 --- a/src/opengl/qglbuffer.cpp +++ b/src/opengl/qglbuffer.cpp @@ -347,9 +347,9 @@ bool QGLBuffer::read(int offset, void *data, int count) Q_D(QGLBuffer); if (!d->funcs->hasOpenGLFeature(QOpenGLFunctions::Buffers) || !d->guard->id()) return false; - while (glGetError() != GL_NO_ERROR) ; // Clear error state. + while (d->funcs->glGetError() != GL_NO_ERROR) ; // Clear error state. d->funcs->glGetBufferSubData(d->type, offset, count, data); - return glGetError() == GL_NO_ERROR; + return d->funcs->glGetError() == GL_NO_ERROR; #else Q_UNUSED(offset); Q_UNUSED(data); diff --git a/src/opengl/qglframebufferobject.cpp b/src/opengl/qglframebufferobject.cpp index 419055f1a3..f6e7a9a308 100644 --- a/src/opengl/qglframebufferobject.cpp +++ b/src/opengl/qglframebufferobject.cpp @@ -61,11 +61,11 @@ extern QImage qt_gl_read_frame_buffer(const QSize&, bool, bool); #ifndef QT_NO_DEBUG #define QT_RESET_GLERROR() \ { \ - while (glGetError() != GL_NO_ERROR) {} \ + while (QOpenGLContext::currentContext()->functions()->glGetError() != GL_NO_ERROR) {} \ } #define QT_CHECK_GLERROR() \ { \ - GLenum err = glGetError(); \ + GLenum err = QOpenGLContext::currentContext()->functions()->glGetError(); \ if (err != GL_NO_ERROR) { \ qDebug("[%s line %d] GL Error: %d", \ __FILE__, __LINE__, (int)err); \ @@ -94,6 +94,10 @@ extern QImage qt_gl_read_frame_buffer(const QSize&, bool, bool); #define GL_DEPTH_COMPONENT24 0x81A6 #endif +#ifndef GL_DEPTH_COMPONENT24_OES +#define GL_DEPTH_COMPONENT24_OES 0x81A6 +#endif + #ifndef GL_READ_FRAMEBUFFER #define GL_READ_FRAMEBUFFER 0x8CA8 #endif @@ -460,7 +464,7 @@ namespace void freeTextureFunc(QGLContext *ctx, GLuint id) { Q_UNUSED(ctx); - glDeleteTextures(1, &id); + ctx->contextHandle()->functions()->glDeleteTextures(1, &id); } } @@ -493,10 +497,10 @@ void QGLFramebufferObjectPrivate::init(QGLFramebufferObject *q, const QSize &sz, QT_CHECK_GLERROR(); // init texture if (samples == 0) { - glGenTextures(1, &texture); - glBindTexture(target, texture); - glTexImage2D(target, 0, internal_format, size.width(), size.height(), 0, - GL_RGBA, GL_UNSIGNED_BYTE, NULL); + funcs.glGenTextures(1, &texture); + funcs.glBindTexture(target, texture); + funcs.glTexImage2D(target, 0, internal_format, size.width(), size.height(), 0, + GL_RGBA, GL_UNSIGNED_BYTE, NULL); if (mipmap) { int width = size.width(); int height = size.height(); @@ -505,26 +509,26 @@ void QGLFramebufferObjectPrivate::init(QGLFramebufferObject *q, const QSize &sz, width = qMax(1, width >> 1); height = qMax(1, height >> 1); ++level; - glTexImage2D(target, level, internal_format, width, height, 0, - GL_RGBA, GL_UNSIGNED_BYTE, NULL); + funcs.glTexImage2D(target, level, internal_format, width, height, 0, + GL_RGBA, GL_UNSIGNED_BYTE, NULL); } } - glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + funcs.glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + funcs.glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + funcs.glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + funcs.glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); funcs.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, texture, 0); QT_CHECK_GLERROR(); valid = checkFramebufferStatus(); - glBindTexture(target, 0); + funcs.glBindTexture(target, 0); color_buffer = 0; } else { mipmap = false; GLint maxSamples; - glGetIntegerv(GL_MAX_SAMPLES, &maxSamples); + funcs.glGetIntegerv(GL_MAX_SAMPLES, &maxSamples); samples = qBound(0, int(samples), int(maxSamples)); @@ -694,7 +698,7 @@ void QGLFramebufferObjectPrivate::init(QGLFramebufferObject *q, const QSize &sz, if (color_buffer) funcs.glDeleteRenderbuffers(1, &color_buffer); else - glDeleteTextures(1, &texture); + funcs.glDeleteTextures(1, &texture); if (depth_buffer) funcs.glDeleteRenderbuffers(1, &depth_buffer); if (stencil_buffer && depth_buffer != stencil_buffer) @@ -792,8 +796,6 @@ void QGLFramebufferObjectPrivate::init(QGLFramebufferObject *q, const QSize &sz, OpenGL ES 2.0 is required for this to work. \note This class has been deprecated in favor of QOpenGLFramebufferObject. - - \sa {Framebuffer Object 2 Example} */ diff --git a/src/opengl/qglpaintdevice.cpp b/src/opengl/qglpaintdevice.cpp index 6a8d5c042e..1af4762e6a 100644 --- a/src/opengl/qglpaintdevice.cpp +++ b/src/opengl/qglpaintdevice.cpp @@ -164,18 +164,19 @@ void QGLWidgetGLPaintDevice::setWidget(QGLWidget* w) void QGLWidgetGLPaintDevice::beginPaint() { QGLPaintDevice::beginPaint(); + QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions(); if (!glWidget->d_func()->disable_clear_on_painter_begin && glWidget->autoFillBackground()) { if (glWidget->testAttribute(Qt::WA_TranslucentBackground)) - glClearColor(0.0, 0.0, 0.0, 0.0); + funcs->glClearColor(0.0, 0.0, 0.0, 0.0); else { const QColor &c = glWidget->palette().brush(glWidget->backgroundRole()).color(); float alpha = c.alphaF(); - glClearColor(c.redF() * alpha, c.greenF() * alpha, c.blueF() * alpha, alpha); + funcs->glClearColor(c.redF() * alpha, c.greenF() * alpha, c.blueF() * alpha, alpha); } if (context()->d_func()->workaround_needsFullClearOnEveryFrame) - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + funcs->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); else - glClear(GL_COLOR_BUFFER_BIT); + funcs->glClear(GL_COLOR_BUFFER_BIT); } } diff --git a/src/opengl/qglpixelbuffer.cpp b/src/opengl/qglpixelbuffer.cpp index 12b26e5381..4a32a99912 100644 --- a/src/opengl/qglpixelbuffer.cpp +++ b/src/opengl/qglpixelbuffer.cpp @@ -89,8 +89,6 @@ Pbuffers are provided by the OpenGL \c pbuffer extension; call hasOpenGLPbuffer() to find out if the system provides pbuffers. - - \sa {Pixel Buffers Example} */ #include <private/qopenglextensions_p.h> @@ -124,7 +122,7 @@ void QGLPBufferGLPaintDevice::beginPaint() void QGLPBufferGLPaintDevice::endPaint() { - glFlush(); + QOpenGLContext::currentContext()->functions()->glFlush(); QGLPaintDevice::endPaint(); } @@ -235,7 +233,7 @@ bool QGLPixelBuffer::makeCurrent() d->fbo = new QOpenGLFramebufferObject(d->req_size, format); d->fbo->bind(); d->glDevice.setFbo(d->fbo->handle()); - glViewport(0, 0, d->req_size.width(), d->req_size.height()); + QOpenGLContext::currentContext()->functions()->glViewport(0, 0, d->req_size.width(), d->req_size.height()); } return true; } @@ -338,7 +336,7 @@ void QGLPixelBuffer::updateDynamicTexture(GLuint texture_id) const if (d->invalid || !d->fbo) return; - QOpenGLContext *ctx = QOpenGLContext::currentContext(); + const QGLContext *ctx = QGLContext::currentContext(); if (!ctx) return; @@ -352,19 +350,19 @@ void QGLPixelBuffer::updateDynamicTexture(GLuint texture_id) const #define GL_DRAW_FRAMEBUFFER 0x8CA9 #endif - QOpenGLExtensions extensions(ctx); + QOpenGLExtensions extensions(ctx->contextHandle()); if (d->blit_fbo) { QOpenGLFramebufferObject::blitFramebuffer(d->blit_fbo, d->fbo); extensions.glBindFramebuffer(GL_READ_FRAMEBUFFER, d->blit_fbo->handle()); } - glBindTexture(GL_TEXTURE_2D, texture_id); + extensions.glBindTexture(GL_TEXTURE_2D, texture_id); #ifndef QT_OPENGL_ES - GLenum format = ctx->isOpenGLES() ? GL_RGBA : GL_RGBA8; - glCopyTexImage2D(GL_TEXTURE_2D, 0, format, 0, 0, d->req_size.width(), d->req_size.height(), 0); + GLenum format = ctx->contextHandle()->isOpenGLES() ? GL_RGBA : GL_RGBA8; + extensions.glCopyTexImage2D(GL_TEXTURE_2D, 0, format, 0, 0, d->req_size.width(), d->req_size.height(), 0); #else - glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, d->req_size.width(), d->req_size.height(), 0); + extensions.glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, d->req_size.width(), d->req_size.height(), 0); #endif if (d->blit_fbo) @@ -629,17 +627,18 @@ GLuint QGLPixelBuffer::generateDynamicTexture() const } GLuint texture; + QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions(); - glGenTextures(1, &texture); - glBindTexture(GL_TEXTURE_2D, texture); + funcs->glGenTextures(1, &texture); + funcs->glBindTexture(GL_TEXTURE_2D, texture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, d->req_size.width(), d->req_size.height(), 0, - GL_RGBA, GL_UNSIGNED_BYTE, 0); + funcs->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, d->req_size.width(), d->req_size.height(), 0, + GL_RGBA, GL_UNSIGNED_BYTE, 0); return texture; } diff --git a/src/opengl/qglshaderprogram.cpp b/src/opengl/qglshaderprogram.cpp index 6173ad1288..9cd6ada058 100644 --- a/src/opengl/qglshaderprogram.cpp +++ b/src/opengl/qglshaderprogram.cpp @@ -3074,8 +3074,9 @@ int QGLShaderProgram::maxGeometryOutputVertices() const { GLint n = 0; #if !defined(QT_OPENGL_ES_2) + Q_D(const QGLShaderProgram); if (!QOpenGLContext::currentContext()->isOpenGLES()) - glGetIntegerv(GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT, &n); + d->glfuncs->glGetIntegerv(GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT, &n); #endif return n; } @@ -3229,7 +3230,7 @@ bool QGLShader::hasOpenGLShaders(ShaderType type, const QGLContext *context) if (!resolved) return false; - if ((type & Geometry) && !QByteArray((const char *) glGetString(GL_EXTENSIONS)).contains("GL_EXT_geometry_shader4")) + if ((type & Geometry) && !QByteArray((const char *) functions.glGetString(GL_EXTENSIONS)).contains("GL_EXT_geometry_shader4")) return false; return true; |