diff options
author | Paul Olav Tvete <paul.tvete@nokia.com> | 2010-10-05 13:46:47 (GMT) |
---|---|---|
committer | Paul Olav Tvete <paul.tvete@nokia.com> | 2010-10-05 13:46:47 (GMT) |
commit | ad04d96fdac0fea252096d5144abf684516cbb10 (patch) | |
tree | 50e9defb39955db39116677f2eef3d72e8053a26 /src/opengl | |
parent | 1200bf9f82860d2f391a4b68ce25c606eb9a0831 (diff) | |
parent | bbaf34b1f5ac4e6d425eab183112b504b9ed4e83 (diff) | |
download | Qt-ad04d96fdac0fea252096d5144abf684516cbb10.zip Qt-ad04d96fdac0fea252096d5144abf684516cbb10.tar.gz Qt-ad04d96fdac0fea252096d5144abf684516cbb10.tar.bz2 |
Merge remote branch 'qt/master' into lighthouse-master
Conflicts:
src/gui/painting/qpdf.cpp
Diffstat (limited to 'src/opengl')
-rw-r--r-- | src/opengl/gl2paintengineex/qglengineshadermanager.cpp | 17 | ||||
-rw-r--r-- | src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp | 103 | ||||
-rw-r--r-- | src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp | 85 | ||||
-rw-r--r-- | src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h | 9 | ||||
-rw-r--r-- | src/opengl/qgl.cpp | 3 | ||||
-rw-r--r-- | src/opengl/qgl_egl.cpp | 1 | ||||
-rw-r--r-- | src/opengl/qgl_x11.cpp | 4 | ||||
-rw-r--r-- | src/opengl/qglframebufferobject.cpp | 105 | ||||
-rw-r--r-- | src/opengl/qglframebufferobject_p.h | 5 | ||||
-rw-r--r-- | src/opengl/qglpixelbuffer_win.cpp | 21 | ||||
-rw-r--r-- | src/opengl/qpaintengine_opengl.cpp | 4 |
11 files changed, 252 insertions, 105 deletions
diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp index 4b5f53e..93ff3f4 100644 --- a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp +++ b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp @@ -41,6 +41,7 @@ #include "qglengineshadermanager_p.h" #include "qglengineshadersource_p.h" +#include "qpaintengineex_opengl2_p.h" #if defined(QT_DEBUG) #include <QMetaEnum> @@ -265,6 +266,7 @@ QByteArray QGLEngineSharedShaders::snippetNameStr(SnippetName name) #endif // The address returned here will only be valid until next time this function is called. +// The program is return bound. QGLEngineShaderProg *QGLEngineSharedShaders::findProgramInCache(const QGLEngineShaderProg &prog) { for (int i = 0; i < cachedPrograms.size(); ++i) { @@ -272,6 +274,7 @@ QGLEngineShaderProg *QGLEngineSharedShaders::findProgramInCache(const QGLEngineS if (*cachedProg == prog) { // Move the program to the top of the list as a poor-man's cache algo cachedPrograms.move(i, 0); + cachedProg->program->bind(); return cachedProg; } } @@ -374,6 +377,14 @@ QGLEngineShaderProg *QGLEngineSharedShaders::findProgramInCache(const QGLEngineS qWarning() << error; break; } + + newProg->program->bind(); + + if (newProg->maskFragShader != QGLEngineSharedShaders::NoMaskFragmentShader) { + GLuint location = newProg->program->uniformLocation("maskTexture"); + newProg->program->setUniformValue(location, QT_MASK_TEXTURE_UNIT); + } + if (cachedPrograms.count() > 30) { // The cache is full, so delete the last 5 programs in the list. // These programs will be least used, as a program us bumped to @@ -787,10 +798,8 @@ bool QGLEngineShaderManager::useCorrectShaderProg() // At this point, requiredProgram is fully populated so try to find the program in the cache currentShaderProg = sharedShaders->findProgramInCache(requiredProgram); - if (currentShaderProg) { - currentShaderProg->program->bind(); - if (useCustomSrc) - customSrcStage->setUniforms(currentShaderProg->program); + if (currentShaderProg && useCustomSrc) { + customSrcStage->setUniforms(currentShaderProg->program); } // Make sure all the vertex attribute arrays the program uses are enabled (and the ones it diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index d89ef08..0941040 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -98,6 +98,10 @@ QT_BEGIN_NAMESPACE extern Q_GUI_EXPORT bool qt_cleartype_enabled; #endif +#ifdef Q_WS_MAC +extern bool qt_applefontsmoothing_enabled; +#endif + extern QImage qt_imageForBrush(int brushStyle, bool invert); ////////////////////////////////// Private Methods ////////////////////////////////////////// @@ -612,8 +616,6 @@ void QGL2PaintEngineExPrivate::transferMode(EngineMode newMode) } if (newMode == TextDrawingMode) { - setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, (GLfloat*)vertexCoordinateArray.data()); - setVertexAttributePointer(QT_TEXTURE_COORDS_ATTR, (GLfloat*)textureCoordinateArray.data()); shaderManager->setHasComplexGeometry(true); } else { shaderManager->setHasComplexGeometry(false); @@ -866,32 +868,6 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path) if (do_vectorpath_cache) path.makeCacheable(); - if (!device->format().stencil()) { - // If there is no stencil buffer, triangulate the path instead. - - QRectF bbox = path.controlPointRect(); - // If the path doesn't fit within these limits, it is possible that the triangulation will fail. - bool withinLimits = (bbox.left() > -0x8000 * inverseScale) - && (bbox.right() < 0x8000 * inverseScale) - && (bbox.top() > -0x8000 * inverseScale) - && (bbox.bottom() < 0x8000 * inverseScale); - if (withinLimits) { - QTriangleSet polys = qTriangulate(path, QTransform().scale(1 / inverseScale, 1 / inverseScale)); - - QVarLengthArray<float> vertices(polys.vertices.size()); - for (int i = 0; i < polys.vertices.size(); ++i) - vertices[i] = float(inverseScale * polys.vertices.at(i)); - - prepareForDraw(currentBrush.isOpaque()); - setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, vertices.constData()); - glDrawElements(GL_TRIANGLES, polys.indices.size(), GL_UNSIGNED_INT, polys.indices.constData()); - } else { - // We can't handle big, concave painter paths with OpenGL without stencil buffer. - qWarning("Painter path exceeds +/-32767 pixels."); - } - return; - } - // The path is too complicated & needs the stencil technique vertexCoordinateArray.clear(); vertexCoordinateArray.addPath(path, inverseScale, false); @@ -1340,7 +1316,7 @@ void QGL2PaintEngineEx::drawPixmap(const QRectF& dest, const QPixmap & pixmap, c QGLRect srcRect(src.left(), top, src.right(), bottom); bool isBitmap = pixmap.isQBitmap(); - bool isOpaque = !isBitmap && !pixmap.hasAlphaChannel(); + bool isOpaque = !isBitmap && !pixmap.hasAlpha(); d->updateTextureFilter(GL_TEXTURE_2D, GL_CLAMP_TO_EDGE, state()->renderHints & QPainter::SmoothPixmapTransform, texture->id); @@ -1470,7 +1446,7 @@ namespace { { public: QOpenGLStaticTextUserData() - : QStaticTextUserData(OpenGLUserData) + : QStaticTextUserData(OpenGLUserData), cacheSize(0, 0) { } @@ -1478,6 +1454,7 @@ namespace { { } + QSize cacheSize; QGL2PEXVertexArray vertexCoordinateArray; QGL2PEXVertexArray textureCoordinateArray; }; @@ -1501,10 +1478,23 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp staticTextItem->fontEngine->setGlyphCache(cacheKey, cache); } - cache->setPaintEnginePrivate(this); - cache->populate(staticTextItem->fontEngine, staticTextItem->numGlyphs, staticTextItem->glyphs, - staticTextItem->glyphPositions); - cache->fillInPendingGlyphs(); + bool recreateVertexArrays = false; + if (staticTextItem->userDataNeedsUpdate) + recreateVertexArrays = true; + else if (staticTextItem->userData == 0) + recreateVertexArrays = true; + else if (staticTextItem->userData->type != QStaticTextUserData::OpenGLUserData) + recreateVertexArrays = true; + + // We only need to update the cache with new glyphs if we are actually going to recreate the vertex arrays. + // If the cache size has changed, we do need to regenerate the vertices, but we don't need to repopulate the + // cache so this text is performed before we test if the cache size has changed. + if (recreateVertexArrays) { + cache->setPaintEnginePrivate(this); + cache->populate(staticTextItem->fontEngine, staticTextItem->numGlyphs, staticTextItem->glyphs, + staticTextItem->glyphPositions); + cache->fillInPendingGlyphs(); + } if (cache->width() == 0 || cache->height() == 0) return; @@ -1516,14 +1506,6 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp GLfloat dx = 1.0 / cache->width(); GLfloat dy = 1.0 / cache->height(); - bool recreateVertexArrays = false; - if (staticTextItem->userDataNeedsUpdate) - recreateVertexArrays = true; - else if (staticTextItem->userData == 0) - recreateVertexArrays = true; - else if (staticTextItem->userData->type != QStaticTextUserData::OpenGLUserData) - recreateVertexArrays = true; - // Use global arrays by default QGL2PEXVertexArray *vertexCoordinates = &vertexCoordinateArray; QGL2PEXVertexArray *textureCoordinates = &textureCoordinateArray; @@ -1544,6 +1526,12 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp // Use cache if backend optimizations is turned on vertexCoordinates = &userData->vertexCoordinateArray; textureCoordinates = &userData->textureCoordinateArray; + + QSize size(cache->width(), cache->height()); + if (userData->cacheSize != size) { + recreateVertexArrays = true; + userData->cacheSize = size; + } } @@ -1665,7 +1653,6 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp glBindTexture(GL_TEXTURE_2D, cache->texture()); updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, false); - shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::MaskTexture), QT_MASK_TEXTURE_UNIT); #if defined(QT_OPENGL_DRAWCACHEDGLYPHS_INDEX_ARRAY_VBO) glDrawElements(GL_TRIANGLE_STRIP, 6 * staticTextItem->numGlyphs, GL_UNSIGNED_SHORT, 0); #else @@ -1695,13 +1682,26 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp } //### TODO: Gamma correction - glActiveTexture(GL_TEXTURE0 + QT_MASK_TEXTURE_UNIT); - if (lastMaskTextureUsed != cache->texture()) { - glBindTexture(GL_TEXTURE_2D, cache->texture()); - lastMaskTextureUsed = cache->texture(); + QGLTextureGlyphCache::FilterMode filterMode = (s->matrix.type() > QTransform::TxTranslate)?QGLTextureGlyphCache::Linear:QGLTextureGlyphCache::Nearest; + if (lastMaskTextureUsed != cache->texture() || cache->filterMode() != filterMode) { + + glActiveTexture(GL_TEXTURE0 + QT_MASK_TEXTURE_UNIT); + if (lastMaskTextureUsed != cache->texture()) { + glBindTexture(GL_TEXTURE_2D, cache->texture()); + lastMaskTextureUsed = cache->texture(); + } + + if (cache->filterMode() != filterMode) { + if (filterMode == QGLTextureGlyphCache::Linear) { + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + } else { + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + } + cache->setFilterMode(filterMode); + } } - updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, s->matrix.type() > QTransform::TxTranslate); - shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::MaskTexture), QT_MASK_TEXTURE_UNIT); #if defined(QT_OPENGL_DRAWCACHEDGLYPHS_INDEX_ARRAY_VBO) glDrawElements(GL_TRIANGLE_STRIP, 6 * staticTextItem->numGlyphs, GL_UNSIGNED_SHORT, 0); @@ -1800,7 +1800,7 @@ void QGL2PaintEngineExPrivate::drawPixmapFragments(const QPainter::PixmapFragmen transferMode(ImageArrayDrawingMode); bool isBitmap = pixmap.isQBitmap(); - bool isOpaque = !isBitmap && (!pixmap.hasAlphaChannel() || (hints & QPainter::OpaqueHint)) && allOpaque; + bool isOpaque = !isBitmap && (!pixmap.hasAlpha() || (hints & QPainter::OpaqueHint)) && allOpaque; updateTextureFilter(GL_TEXTURE_2D, GL_CLAMP_TO_EDGE, q->state()->renderHints & QPainter::SmoothPixmapTransform, texture->id); @@ -1881,6 +1881,9 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev) #if defined(Q_WS_WIN) if (qt_cleartype_enabled) #endif +#if defined(Q_WS_MAC) + if (qt_applefontsmoothing_enabled) +#endif d->glyphCacheType = QFontEngineGlyphCache::Raster_RGBMask; #endif diff --git a/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp b/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp index f8e34d4..3f10454 100644 --- a/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp +++ b/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp @@ -41,6 +41,7 @@ #include "qtextureglyphcache_gl_p.h" #include "qpaintengineex_opengl2_p.h" +#include "private/qglengineshadersource_p.h" #if defined QT_OPENGL_ES_2 && !defined(QT_NO_EGL) #include "private/qeglcontext_p.h" @@ -54,8 +55,10 @@ extern Q_GUI_EXPORT bool qt_cleartype_enabled; QGLTextureGlyphCache::QGLTextureGlyphCache(const QGLContext *context, QFontEngineGlyphCache::Type type, const QTransform &matrix) : QImageTextureGlyphCache(type, matrix) - , ctx(0) + , ctx(context) , pex(0) + , m_filterMode(Nearest) + , m_blitProgram(0) { #ifdef QT_GL_TEXTURE_GLYPH_CACHE_DEBUG qDebug(" -> QGLTextureGlyphCache() %p for context %p.", this, ctx); @@ -68,6 +71,8 @@ QGLTextureGlyphCache::~QGLTextureGlyphCache() #ifdef QT_GL_TEXTURE_GLYPH_CACHE_DEBUG qDebug(" -> ~QGLTextureGlyphCache() %p.", this); #endif + + delete m_blitProgram; } void QGLTextureGlyphCache::setContext(const QGLContext *context) @@ -86,7 +91,7 @@ void QGLTextureGlyphCache::createTextureData(int width, int height) // create in QImageTextureGlyphCache baseclass is meant to be called // only to create the initial image and does not preserve the content, // so we don't call when this function is called from resize. - if ((pex == 0 || ctx->d_ptr->workaround_brokenFBOReadBack) && image().isNull()) + if (ctx->d_ptr->workaround_brokenFBOReadBack && image().isNull()) QImageTextureGlyphCache::createTextureData(width, height); // Make the lower glyph texture size 16 x 16. @@ -113,6 +118,9 @@ void QGLTextureGlyphCache::createTextureData(int width, int height) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + m_filterMode = Nearest; } void QGLTextureGlyphCache::resizeTextureData(int width, int height) @@ -135,7 +143,7 @@ void QGLTextureGlyphCache::resizeTextureData(int width, int height) GLuint oldTexture = glyphTexture->m_texture; createTextureData(width, height); - if (pex == 0 || ctx->d_ptr->workaround_brokenFBOReadBack) { + if (ctx->d_ptr->workaround_brokenFBOReadBack) { QImageTextureGlyphCache::resizeTextureData(width, height); Q_ASSERT(image().depth() == 8); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, oldWidth, oldHeight, GL_ALPHA, GL_UNSIGNED_BYTE, image().constBits()); @@ -157,6 +165,7 @@ void QGLTextureGlyphCache::resizeTextureData(int width, int height) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + m_filterMode = Nearest; glBindTexture(GL_TEXTURE_2D, 0); glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, tmp_texture, 0); @@ -164,7 +173,8 @@ void QGLTextureGlyphCache::resizeTextureData(int width, int height) glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT); glBindTexture(GL_TEXTURE_2D, oldTexture); - pex->transferMode(BrushDrawingMode); + if (pex != 0) + pex->transferMode(BrushDrawingMode); glDisable(GL_STENCIL_TEST); glDisable(GL_DEPTH_TEST); @@ -173,7 +183,7 @@ void QGLTextureGlyphCache::resizeTextureData(int width, int height) glViewport(0, 0, oldWidth, oldHeight); - GLfloat* vertexCoordinateArray = pex->staticVertexCoordinateArray; + GLfloat vertexCoordinateArray[8]; vertexCoordinateArray[0] = -1.0f; vertexCoordinateArray[1] = -1.0f; vertexCoordinateArray[2] = 1.0f; @@ -183,7 +193,7 @@ void QGLTextureGlyphCache::resizeTextureData(int width, int height) vertexCoordinateArray[6] = -1.0f; vertexCoordinateArray[7] = 1.0f; - GLfloat* textureCoordinateArray = pex->staticTextureCoordinateArray; + GLfloat textureCoordinateArray[8]; textureCoordinateArray[0] = 0.0f; textureCoordinateArray[1] = 0.0f; textureCoordinateArray[2] = 1.0f; @@ -193,11 +203,58 @@ void QGLTextureGlyphCache::resizeTextureData(int width, int height) textureCoordinateArray[6] = 0.0f; textureCoordinateArray[7] = 1.0f; - pex->setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, vertexCoordinateArray); - pex->setVertexAttributePointer(QT_TEXTURE_COORDS_ATTR, textureCoordinateArray); + QGLShaderProgram *blitProgram = 0; + if (pex == 0) { + if (m_blitProgram == 0) { + m_blitProgram = new QGLShaderProgram(ctx); + + { + QString source; + source.append(qglslMainWithTexCoordsVertexShader); + source.append(qglslUntransformedPositionVertexShader); + + QGLShader *vertexShader = new QGLShader(QGLShader::Vertex, m_blitProgram); + vertexShader->compileSourceCode(source); + + m_blitProgram->addShader(vertexShader); + } + + { + QString source; + source.append(qglslMainFragmentShader); + source.append(qglslImageSrcFragmentShader); + + QGLShader *fragmentShader = new QGLShader(QGLShader::Fragment, m_blitProgram); + fragmentShader->compileSourceCode(source); + + m_blitProgram->addShader(fragmentShader); + } - pex->shaderManager->useBlitProgram(); - pex->shaderManager->blitProgram()->setUniformValue("imageTexture", QT_IMAGE_TEXTURE_UNIT); + m_blitProgram->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR); + m_blitProgram->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR); + + m_blitProgram->link(); + } + + glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, vertexCoordinateArray); + glVertexAttribPointer(QT_TEXTURE_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, textureCoordinateArray); + + m_blitProgram->bind(); + QGLContextPrivate* ctx_d = const_cast<QGLContextPrivate *>(ctx->d_func()); + ctx_d->setVertexAttribArrayEnabled(QT_VERTEX_COORDS_ATTR, true); + ctx_d->setVertexAttribArrayEnabled(QT_TEXTURE_COORDS_ATTR, true); + ctx_d->setVertexAttribArrayEnabled(QT_OPACITY_ATTR, false); + blitProgram = m_blitProgram; + + } else { + pex->setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, vertexCoordinateArray); + pex->setVertexAttributePointer(QT_TEXTURE_COORDS_ATTR, textureCoordinateArray); + + pex->shaderManager->useBlitProgram(); + blitProgram = pex->shaderManager->blitProgram(); + } + + blitProgram->setUniformValue("imageTexture", QT_IMAGE_TEXTURE_UNIT); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); @@ -212,8 +269,10 @@ void QGLTextureGlyphCache::resizeTextureData(int width, int height) glBindFramebuffer(GL_FRAMEBUFFER_EXT, ctx->d_ptr->current_fbo); - glViewport(0, 0, pex->width, pex->height); - pex->updateClipScissorTest(); + if (pex != 0) { + glViewport(0, 0, pex->width, pex->height); + pex->updateClipScissorTest(); + } } void QGLTextureGlyphCache::fillTexture(const Coord &c, glyph_t glyph, QFixed subPixelPosition) @@ -224,7 +283,7 @@ void QGLTextureGlyphCache::fillTexture(const Coord &c, glyph_t glyph, QFixed sub } QGLGlyphTexture *glyphTexture = m_textureResource.value(ctx); - if (pex == 0 || ctx->d_ptr->workaround_brokenFBOReadBack) { + if (ctx->d_ptr->workaround_brokenFBOReadBack) { QImageTextureGlyphCache::fillTexture(c, glyph, subPixelPosition); glBindTexture(GL_TEXTURE_2D, glyphTexture->m_texture); diff --git a/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h b/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h index ada47e9..7e2c625 100644 --- a/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h +++ b/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h @@ -133,11 +133,20 @@ public: void setContext(const QGLContext *context); inline const QGLContext *context() const { return ctx; } + enum FilterMode { + Nearest, + Linear + }; + FilterMode filterMode() const { return m_filterMode; } + void setFilterMode(FilterMode m) { m_filterMode = m; } + private: QGLContextGroupResource<QGLGlyphTexture> m_textureResource; const QGLContext *ctx; QGL2PaintEngineExPrivate *pex; + QGLShaderProgram *m_blitProgram; + FilterMode m_filterMode; }; QT_END_NAMESPACE diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp index ec191e1..8cbba2a 100644 --- a/src/opengl/qgl.cpp +++ b/src/opengl/qgl.cpp @@ -518,6 +518,9 @@ QGLFormat::~QGLFormat() exchange the screen contents with the buffer. The result is flicker-free drawing and often better performance. + Note that single buffered contexts are currently not supported + with EGL. + \sa doubleBuffer(), QGLContext::swapBuffers(), QGLWidget::swapBuffers() */ diff --git a/src/opengl/qgl_egl.cpp b/src/opengl/qgl_egl.cpp index ebd1169..c79c4cd 100644 --- a/src/opengl/qgl_egl.cpp +++ b/src/opengl/qgl_egl.cpp @@ -143,6 +143,7 @@ void qt_glformat_from_eglconfig(QGLFormat& format, const EGLConfig config) format.setRgba(true); // EGL doesn't support colour index rendering format.setStereo(false); // EGL doesn't support stereo buffers format.setAccumBufferSize(0); // EGL doesn't support accululation buffers + format.setDoubleBuffer(true); // We don't support single buffered EGL contexts // Clear the EGL error state because some of the above may // have errored out because the attribute is not applicable diff --git a/src/opengl/qgl_x11.cpp b/src/opengl/qgl_x11.cpp index f3a4c95..7f4c670 100644 --- a/src/opengl/qgl_x11.cpp +++ b/src/opengl/qgl_x11.cpp @@ -1776,6 +1776,10 @@ QGLTexture *QGLContextPrivate::bindTextureFromNativePixmap(QPixmap *pixmap, cons QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pixmap->data_ptr().data()); Q_ASSERT(pixmapData->classId() == QPixmapData::X11Class); + // We can't use TFP if the pixmap has a separate X11 mask + if (pixmapData->x11_mask) + return 0; + if (!qt_resolveTextureFromPixmap(paintDevice)) return 0; diff --git a/src/opengl/qglframebufferobject.cpp b/src/opengl/qglframebufferobject.cpp index cee950a..5d78ac0 100644 --- a/src/opengl/qglframebufferobject.cpp +++ b/src/opengl/qglframebufferobject.cpp @@ -324,10 +324,6 @@ void QGLFBOGLPaintDevice::setFBO(QGLFramebufferObject* f, fboFormat.setStencil(true); } else if (attachment == QGLFramebufferObject::Depth) { fboFormat.setDepth(true); - fboFormat.setStencil(false); - } else { - fboFormat.setDepth(false); - fboFormat.setStencil(false); } GLenum format = f->format().internalTextureFormat(); @@ -472,13 +468,17 @@ void QGLFramebufferObjectPrivate::init(QGLFramebufferObject *q, const QSize &sz, glGetRenderbufferParameteriv(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_SAMPLES_EXT, &samples); } + // In practice, a combined depth-stencil buffer is supported by all desktop platforms, while a + // separate stencil buffer is not. On embedded devices however, a combined depth-stencil buffer + // might not be supported while separate buffers are, according to QTBUG-12861. + if (attachment == QGLFramebufferObject::CombinedDepthStencil && (QGLExtensions::glExtensions() & QGLExtensions::PackedDepthStencil)) { // depth and stencil buffer needs another extension - glGenRenderbuffers(1, &depth_stencil_buffer); - Q_ASSERT(!glIsRenderbuffer(depth_stencil_buffer)); - glBindRenderbuffer(GL_RENDERBUFFER_EXT, depth_stencil_buffer); - Q_ASSERT(glIsRenderbuffer(depth_stencil_buffer)); + glGenRenderbuffers(1, &depth_buffer); + Q_ASSERT(!glIsRenderbuffer(depth_buffer)); + glBindRenderbuffer(GL_RENDERBUFFER_EXT, depth_buffer); + Q_ASSERT(glIsRenderbuffer(depth_buffer)); if (samples != 0 && glRenderbufferStorageMultisampleEXT) glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, samples, GL_DEPTH24_STENCIL8_EXT, size.width(), size.height()); @@ -486,24 +486,26 @@ void QGLFramebufferObjectPrivate::init(QGLFramebufferObject *q, const QSize &sz, glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT, size.width(), size.height()); - GLint i = 0; - glGetRenderbufferParameteriv(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_DEPTH_SIZE_EXT, &i); + stencil_buffer = depth_buffer; glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, - GL_RENDERBUFFER_EXT, depth_stencil_buffer); + GL_RENDERBUFFER_EXT, depth_buffer); glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, - GL_RENDERBUFFER_EXT, depth_stencil_buffer); - fbo_attachment = QGLFramebufferObject::CombinedDepthStencil; + GL_RENDERBUFFER_EXT, stencil_buffer); valid = checkFramebufferStatus(); - if (!valid) - glDeleteRenderbuffers(1, &depth_stencil_buffer); - } else if (attachment == QGLFramebufferObject::Depth - || attachment == QGLFramebufferObject::CombinedDepthStencil) + if (!valid) { + glDeleteRenderbuffers(1, &depth_buffer); + stencil_buffer = depth_buffer = 0; + } + } + + if (depth_buffer == 0 && (attachment == QGLFramebufferObject::CombinedDepthStencil + || (attachment == QGLFramebufferObject::Depth))) { - glGenRenderbuffers(1, &depth_stencil_buffer); - Q_ASSERT(!glIsRenderbuffer(depth_stencil_buffer)); - glBindRenderbuffer(GL_RENDERBUFFER_EXT, depth_stencil_buffer); - Q_ASSERT(glIsRenderbuffer(depth_stencil_buffer)); + glGenRenderbuffers(1, &depth_buffer); + Q_ASSERT(!glIsRenderbuffer(depth_buffer)); + glBindRenderbuffer(GL_RENDERBUFFER_EXT, depth_buffer); + Q_ASSERT(glIsRenderbuffer(depth_buffer)); if (samples != 0 && glRenderbufferStorageMultisampleEXT) { #ifdef QT_OPENGL_ES #define GL_DEPTH_COMPONENT16 0x81A5 @@ -521,14 +523,53 @@ void QGLFramebufferObjectPrivate::init(QGLFramebufferObject *q, const QSize &sz, glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, size.width(), size.height()); #endif } - GLint i = 0; - glGetRenderbufferParameteriv(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_DEPTH_SIZE_EXT, &i); glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, - GL_RENDERBUFFER_EXT, depth_stencil_buffer); - fbo_attachment = QGLFramebufferObject::Depth; + GL_RENDERBUFFER_EXT, depth_buffer); valid = checkFramebufferStatus(); - if (!valid) - glDeleteRenderbuffers(1, &depth_stencil_buffer); + if (!valid) { + glDeleteRenderbuffers(1, &depth_buffer); + depth_buffer = 0; + } + } + + if (stencil_buffer == 0 && (attachment == QGLFramebufferObject::CombinedDepthStencil)) { + glGenRenderbuffers(1, &stencil_buffer); + Q_ASSERT(!glIsRenderbuffer(stencil_buffer)); + glBindRenderbuffer(GL_RENDERBUFFER_EXT, stencil_buffer); + Q_ASSERT(glIsRenderbuffer(stencil_buffer)); + if (samples != 0 && glRenderbufferStorageMultisampleEXT) { +#ifdef QT_OPENGL_ES + glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, samples, + GL_STENCIL_INDEX8_EXT, size.width(), size.height()); +#else + glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, samples, + GL_STENCIL_INDEX, size.width(), size.height()); +#endif + } else { +#ifdef QT_OPENGL_ES + glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_STENCIL_INDEX8_EXT, + size.width(), size.height()); +#else + glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_STENCIL_INDEX, + size.width(), size.height()); +#endif + } + glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, + GL_RENDERBUFFER_EXT, stencil_buffer); + valid = checkFramebufferStatus(); + if (!valid) { + glDeleteRenderbuffers(1, &stencil_buffer); + stencil_buffer = 0; + } + } + + // The FBO might have become valid after removing the depth or stencil buffer. + valid = checkFramebufferStatus(); + + if (depth_buffer && stencil_buffer) { + fbo_attachment = QGLFramebufferObject::CombinedDepthStencil; + } else if (depth_buffer) { + fbo_attachment = QGLFramebufferObject::Depth; } else { fbo_attachment = QGLFramebufferObject::NoAttachment; } @@ -539,6 +580,10 @@ void QGLFramebufferObjectPrivate::init(QGLFramebufferObject *q, const QSize &sz, glDeleteRenderbuffers(1, &color_buffer); else glDeleteTextures(1, &texture); + if (depth_buffer) + glDeleteRenderbuffers(1, &depth_buffer); + if (stencil_buffer && depth_buffer != stencil_buffer) + glDeleteRenderbuffers(1, &stencil_buffer); glDeleteFramebuffers(1, &fbo); fbo_guard.setId(0); } @@ -828,8 +873,10 @@ QGLFramebufferObject::~QGLFramebufferObject() glDeleteTextures(1, &d->texture); if (d->color_buffer) glDeleteRenderbuffers(1, &d->color_buffer); - if (d->depth_stencil_buffer) - glDeleteRenderbuffers(1, &d->depth_stencil_buffer); + if (d->depth_buffer) + glDeleteRenderbuffers(1, &d->depth_buffer); + if (d->stencil_buffer && d->stencil_buffer != d->depth_buffer) + glDeleteRenderbuffers(1, &d->stencil_buffer); GLuint fbo = d->fbo(); glDeleteFramebuffers(1, &fbo); } diff --git a/src/opengl/qglframebufferobject_p.h b/src/opengl/qglframebufferobject_p.h index d8ff012..58b4e9e 100644 --- a/src/opengl/qglframebufferobject_p.h +++ b/src/opengl/qglframebufferobject_p.h @@ -126,7 +126,7 @@ private: class QGLFramebufferObjectPrivate { public: - QGLFramebufferObjectPrivate() : fbo_guard(0), texture(0), depth_stencil_buffer(0) + QGLFramebufferObjectPrivate() : fbo_guard(0), texture(0), depth_buffer(0), stencil_buffer(0) , color_buffer(0), valid(false), engine(0) {} ~QGLFramebufferObjectPrivate() {} @@ -136,7 +136,8 @@ public: bool checkFramebufferStatus() const; QGLSharedResourceGuard fbo_guard; GLuint texture; - GLuint depth_stencil_buffer; + GLuint depth_buffer; + GLuint stencil_buffer; GLuint color_buffer; GLenum target; QSize size; diff --git a/src/opengl/qglpixelbuffer_win.cpp b/src/opengl/qglpixelbuffer_win.cpp index 1da0aad..c61d9bf 100644 --- a/src/opengl/qglpixelbuffer_win.cpp +++ b/src/opengl/qglpixelbuffer_win.cpp @@ -172,6 +172,10 @@ typedef BOOL (WINAPI * PFNWGLSETPBUFFERATTRIBARBPROC) (HPBUFFERARB hPbuffer, con #define WGL_SAMPLES_ARB 0x2042 #endif +#ifndef GL_SAMPLES_ARB +#define GL_SAMPLES_ARB 0x80A9 +#endif + QGLFormat pfiToQGLFormat(HDC hdc, int pfi); static void qt_format_to_attrib_list(bool has_render_texture, const QGLFormat &f, int attribs[]) @@ -258,11 +262,10 @@ bool QGLPixelBufferPrivate::init(const QSize &size, const QGLFormat &f, QGLWidge dc = wglGetCurrentDC(); Q_ASSERT(dc); + has_render_texture = false; // sample buffers doesn't work in conjunction with the render_texture extension - if (f.sampleBuffers()) { - has_render_texture = false; - } else { + if (!f.sampleBuffers()) { PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC) wglGetProcAddress("wglGetExtensionsStringARB"); @@ -303,7 +306,7 @@ bool QGLPixelBufferPrivate::init(const QSize &size, const QGLFormat &f, QGLWidge pbuf = wglCreatePbufferARB(dc, pixel_format, size.width(), size.height(), has_render_texture ? pb_attribs : 0); - if(!pbuf) { + if (!pbuf) { // try again without the render_texture extension pbuf = wglCreatePbufferARB(dc, pixel_format, size.width(), size.height(), 0); has_render_texture = false; @@ -315,12 +318,20 @@ bool QGLPixelBufferPrivate::init(const QSize &size, const QGLFormat &f, QGLWidge dc = wglGetPbufferDCARB(pbuf); ctx = wglCreateContext(dc); - if (!dc || !ctx) { qWarning("QGLPixelBuffer: Unable to create pbuffer context - giving up."); return false; } + // Explicitly disable the render_texture extension if we have a + // multi-sampled pbuffer context. This seems to be a problem only with + // ATI cards if multi-sampling is forced globally in the driver. + wglMakeCurrent(dc, ctx); + GLint samples = 0; + glGetIntegerv(GL_SAMPLES_ARB, &samples); + if (has_render_texture && samples != 0) + has_render_texture = false; + HGLRC share_ctx = shareWidget ? shareWidget->d_func()->glcx->d_func()->rc : 0; if (share_ctx && !wglShareLists(share_ctx, ctx)) qWarning("QGLPixelBuffer: Unable to share display lists - with share widget."); diff --git a/src/opengl/qpaintengine_opengl.cpp b/src/opengl/qpaintengine_opengl.cpp index 58778ea..2f17aa6 100644 --- a/src/opengl/qpaintengine_opengl.cpp +++ b/src/opengl/qpaintengine_opengl.cpp @@ -506,12 +506,12 @@ struct QDrawQueueItem ////////// GL program cache: start -typedef struct { +struct GLProgram { int brush; // brush index or mask index int mode; // composition mode index bool mask; GLuint program; -} GLProgram; +}; typedef QMultiHash<const QGLContext *, GLProgram> QGLProgramHash; |