diff options
Diffstat (limited to 'src/gui/opengl')
-rw-r--r-- | src/gui/opengl/qopenglframebufferobject.cpp | 36 | ||||
-rw-r--r-- | src/gui/opengl/qopenglpaintengine.cpp | 28 | ||||
-rw-r--r-- | src/gui/opengl/qopenglpaintengine_p.h | 2 | ||||
-rw-r--r-- | src/gui/opengl/qopengltexture.cpp | 4 | ||||
-rw-r--r-- | src/gui/opengl/qopengltexture.h | 4 |
5 files changed, 56 insertions, 18 deletions
diff --git a/src/gui/opengl/qopenglframebufferobject.cpp b/src/gui/opengl/qopenglframebufferobject.cpp index cbc992b7e8..6351b8a1e3 100644 --- a/src/gui/opengl/qopenglframebufferobject.cpp +++ b/src/gui/opengl/qopenglframebufferobject.cpp @@ -469,6 +469,8 @@ void QOpenGLFramebufferObjectPrivate::init(QOpenGLFramebufferObject *, const QSi funcs.glGenFramebuffers(1, &fbo); funcs.glBindFramebuffer(GL_FRAMEBUFFER, fbo); + QOpenGLContextPrivate::get(ctx)->qgl_current_fbo_invalid = true; + GLuint color_buffer = 0; QT_CHECK_GLERROR(); @@ -995,7 +997,11 @@ bool QOpenGLFramebufferObject::bind() if (current->shareGroup() != d->fbo_guard->group()) qWarning("QOpenGLFramebufferObject::bind() called from incompatible context"); #endif + d->funcs.glBindFramebuffer(GL_FRAMEBUFFER, d->fbo()); + + QOpenGLContextPrivate::get(current)->qgl_current_fbo_invalid = true; + if (d->texture_guard || d->format.samples() != 0) d->valid = d->checkFramebufferStatus(current); else @@ -1027,9 +1033,12 @@ bool QOpenGLFramebufferObject::release() qWarning("QOpenGLFramebufferObject::release() called from incompatible context"); #endif - if (current) + if (current) { d->funcs.glBindFramebuffer(GL_FRAMEBUFFER, current->defaultFramebufferObject()); + QOpenGLContextPrivate::get(current)->qgl_current_fbo_invalid = true; + } + return true; } @@ -1192,9 +1201,23 @@ Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, If used together with QOpenGLPaintDevice, \a flipped should be the opposite of the value of QOpenGLPaintDevice::paintFlipped(). - Will try to return a premultiplied ARBG32 or RGB32 image. Since 5.2 it will fall back to - a premultiplied RGBA8888 or RGBx8888 image when reading to ARGB32 is not supported. Since 5.4 an - A2BGR30 image is returned if the internal format is RGB10_A2. + The returned image has a format of premultiplied ARGB32 or RGB32. The latter is used + only when internalTextureFormat() is set to \c GL_RGB. + + If the rendering in the framebuffer was not done with premultiplied alpha in mind, + create a wrapper QImage with a non-premultiplied format. This is necessary before + performing operations like QImage::save() because otherwise the image data would get + unpremultiplied, even though it was not premultiplied in the first place. To create + such a wrapper without performing a copy of the pixel data, do the following: + + \code + QImage fboImage(fbo.toImage()); + QImage image(fboImage.constBits(), fboImage.width(), fboImage.height(), QImage::Format_ARGB32); + \endcode + + Since Qt 5.2 the function will fall back to premultiplied RGBA8888 or RGBx8888 when + reading to (A)RGB32 is not supported. Since 5.4 an A2BGR30 image is returned if the + internal format is RGB10_A2. For multisampled framebuffer objects the samples are resolved using the \c{GL_EXT_framebuffer_blit} extension. If the extension is not available, the contents @@ -1270,8 +1293,10 @@ bool QOpenGLFramebufferObject::bindDefault() { QOpenGLContext *ctx = const_cast<QOpenGLContext *>(QOpenGLContext::currentContext()); - if (ctx) + if (ctx) { ctx->functions()->glBindFramebuffer(GL_FRAMEBUFFER, ctx->defaultFramebufferObject()); + QOpenGLContextPrivate::get(ctx)->qgl_current_fbo_invalid = true; + } #ifdef QT_DEBUG else qWarning("QOpenGLFramebufferObject::bindDefault() called without current context."); @@ -1340,6 +1365,7 @@ void QOpenGLFramebufferObject::setAttachment(QOpenGLFramebufferObject::Attachmen qWarning("QOpenGLFramebufferObject::setAttachment() called from incompatible context"); #endif d->funcs.glBindFramebuffer(GL_FRAMEBUFFER, d->fbo()); + QOpenGLContextPrivate::get(current)->qgl_current_fbo_invalid = true; d->initAttachments(current, attachment); } diff --git a/src/gui/opengl/qopenglpaintengine.cpp b/src/gui/opengl/qopenglpaintengine.cpp index c490726359..b18d2cc42a 100644 --- a/src/gui/opengl/qopenglpaintengine.cpp +++ b/src/gui/opengl/qopenglpaintengine.cpp @@ -107,7 +107,7 @@ QOpenGL2PaintEngineExPrivate::~QOpenGL2PaintEngineExPrivate() } } -void QOpenGL2PaintEngineExPrivate::updateTextureFilter(GLenum target, GLenum wrapMode, bool smoothPixmapTransform, GLuint id) +void QOpenGL2PaintEngineExPrivate::updateTextureFilter(GLenum wrapMode, bool smoothPixmapTransform, GLuint id) { // funcs.glActiveTexture(GL_TEXTURE0 + QT_BRUSH_TEXTURE_UNIT); //### Is it always this texture unit? if (id != GLuint(-1) && id == lastTextureUsed) @@ -115,6 +115,8 @@ void QOpenGL2PaintEngineExPrivate::updateTextureFilter(GLenum target, GLenum wra lastTextureUsed = id; + static const GLenum target = GL_TEXTURE_2D; + if (smoothPixmapTransform) { funcs.glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); funcs.glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); @@ -122,6 +124,7 @@ void QOpenGL2PaintEngineExPrivate::updateTextureFilter(GLenum target, GLenum wra funcs.glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); funcs.glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); } + funcs.glTexParameteri(target, GL_TEXTURE_WRAP_S, wrapMode); funcs.glTexParameteri(target, GL_TEXTURE_WRAP_T, wrapMode); } @@ -185,7 +188,7 @@ void QOpenGL2PaintEngineExPrivate::updateBrushTexture() funcs.glActiveTexture(GL_TEXTURE0 + QT_BRUSH_TEXTURE_UNIT); QOpenGLTextureCache::cacheForContext(ctx)->bindTexture(ctx, texImage); - updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, q->state()->renderHints & QPainter::SmoothPixmapTransform); + updateTextureFilter(GL_REPEAT, q->state()->renderHints & QPainter::SmoothPixmapTransform); } else if (style >= Qt::LinearGradientPattern && style <= Qt::ConicalGradientPattern) { // Gradiant brush: All the gradiants use the same texture @@ -199,12 +202,13 @@ void QOpenGL2PaintEngineExPrivate::updateBrushTexture() funcs.glActiveTexture(GL_TEXTURE0 + QT_BRUSH_TEXTURE_UNIT); funcs.glBindTexture(GL_TEXTURE_2D, texId); + GLenum wrapMode = GL_CLAMP_TO_EDGE; if (g->spread() == QGradient::RepeatSpread || g->type() == QGradient::ConicalGradient) - updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, q->state()->renderHints & QPainter::SmoothPixmapTransform); + wrapMode = GL_REPEAT; else if (g->spread() == QGradient::ReflectSpread) - updateTextureFilter(GL_TEXTURE_2D, GL_MIRRORED_REPEAT, q->state()->renderHints & QPainter::SmoothPixmapTransform); - else - updateTextureFilter(GL_TEXTURE_2D, GL_CLAMP_TO_EDGE, q->state()->renderHints & QPainter::SmoothPixmapTransform); + wrapMode = GL_MIRRORED_REPEAT; + + updateTextureFilter(wrapMode, q->state()->renderHints & QPainter::SmoothPixmapTransform); } else if (style == Qt::TexturePattern) { currentBrushImage = currentBrush.textureImage(); @@ -223,7 +227,7 @@ void QOpenGL2PaintEngineExPrivate::updateBrushTexture() funcs.glActiveTexture(GL_TEXTURE0 + QT_BRUSH_TEXTURE_UNIT); QOpenGLTextureCache::cacheForContext(ctx)->bindTexture(ctx, currentBrushImage); - updateTextureFilter(GL_TEXTURE_2D, wrapMode, q->state()->renderHints & QPainter::SmoothPixmapTransform); + updateTextureFilter(wrapMode, q->state()->renderHints & QPainter::SmoothPixmapTransform); textureInvertedY = false; } brushTextureDirty = false; @@ -1386,7 +1390,7 @@ void QOpenGL2PaintEngineEx::drawPixmap(const QRectF& dest, const QPixmap & pixma bool isBitmap = pixmap.isQBitmap(); bool isOpaque = !isBitmap && !pixmap.hasAlpha(); - d->updateTextureFilter(GL_TEXTURE_2D, GL_CLAMP_TO_EDGE, + d->updateTextureFilter(GL_CLAMP_TO_EDGE, state()->renderHints & QPainter::SmoothPixmapTransform, id); d->shaderManager->setSrcPixelType(isBitmap ? QOpenGLEngineShaderManager::PatternSrc : QOpenGLEngineShaderManager::ImageSrc); @@ -1429,7 +1433,7 @@ void QOpenGL2PaintEngineEx::drawImage(const QRectF& dest, const QImage& image, c d->funcs.glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT); GLuint id = QOpenGLTextureCache::cacheForContext(ctx)->bindTexture(ctx, image, bindOption); - d->updateTextureFilter(GL_TEXTURE_2D, GL_CLAMP_TO_EDGE, + d->updateTextureFilter(GL_CLAMP_TO_EDGE, state()->renderHints & QPainter::SmoothPixmapTransform, id); d->drawTexture(dest, src, image.size(), !image.hasAlphaChannel()); @@ -1476,7 +1480,7 @@ bool QOpenGL2PaintEngineEx::drawTexture(const QRectF &dest, GLuint textureId, co QOpenGLRect srcRect(src.left(), src.bottom(), src.right(), src.top()); - d->updateTextureFilter(GL_TEXTURE_2D, GL_CLAMP_TO_EDGE, + d->updateTextureFilter(GL_CLAMP_TO_EDGE, state()->renderHints & QPainter::SmoothPixmapTransform, textureId); d->shaderManager->setSrcPixelType(QOpenGLEngineShaderManager::ImageSrc); d->drawTexture(dest, srcRect, size, false); @@ -1807,7 +1811,7 @@ void QOpenGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngine::GlyphFormat gly funcs.glActiveTexture(GL_TEXTURE0 + QT_MASK_TEXTURE_UNIT); funcs.glBindTexture(GL_TEXTURE_2D, cache->texture()); - updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, false); + updateTextureFilter(GL_REPEAT, false); #if defined(QT_OPENGL_DRAWCACHEDGLYPHS_INDEX_ARRAY_VBO) funcs.glDrawElements(GL_TRIANGLE_STRIP, 6 * numGlyphs, GL_UNSIGNED_SHORT, 0); @@ -1957,7 +1961,7 @@ void QOpenGL2PaintEngineExPrivate::drawPixmapFragments(const QPainter::PixmapFra bool isBitmap = pixmap.isQBitmap(); bool isOpaque = !isBitmap && (!pixmap.hasAlpha() || (hints & QPainter::OpaqueHint)) && allOpaque; - updateTextureFilter(GL_TEXTURE_2D, GL_CLAMP_TO_EDGE, + updateTextureFilter(GL_CLAMP_TO_EDGE, q->state()->renderHints & QPainter::SmoothPixmapTransform, id); // Setup for texture drawing diff --git a/src/gui/opengl/qopenglpaintengine_p.h b/src/gui/opengl/qopenglpaintengine_p.h index 5ef0366284..a5f3cc2894 100644 --- a/src/gui/opengl/qopenglpaintengine_p.h +++ b/src/gui/opengl/qopenglpaintengine_p.h @@ -193,7 +193,7 @@ public: void updateBrushUniforms(); void updateMatrix(); void updateCompositionMode(); - void updateTextureFilter(GLenum target, GLenum wrapMode, bool smoothPixmapTransform, GLuint id = GLuint(-1)); + void updateTextureFilter(GLenum wrapMode, bool smoothPixmapTransform, GLuint id = GLuint(-1)); void resetGLState(); diff --git a/src/gui/opengl/qopengltexture.cpp b/src/gui/opengl/qopengltexture.cpp index f6083b8cf9..b96bc6f346 100644 --- a/src/gui/opengl/qopengltexture.cpp +++ b/src/gui/opengl/qopengltexture.cpp @@ -2591,6 +2591,7 @@ void QOpenGLTexture::setData(PixelFormat sourceFormat, PixelType sourceType, d->setData(0, 0, QOpenGLTexture::CubeMapPositiveX, sourceFormat, sourceType, data, options); } +#if QT_DEPRECATED_SINCE(5, 3) /*! \obsolete \overload @@ -2648,6 +2649,7 @@ void QOpenGLTexture::setData(PixelFormat sourceFormat, PixelType sourceType, Q_ASSERT(d->textureId); d->setData(0, 0, QOpenGLTexture::CubeMapPositiveX, sourceFormat, sourceType, data, options); } +#endif /*! This overload of setData() will allocate storage for you. @@ -2736,6 +2738,7 @@ void QOpenGLTexture::setCompressedData(int dataSize, const void *data, d->setCompressedData(0, 0, QOpenGLTexture::CubeMapPositiveX, dataSize, data, options); } +#if QT_DEPRECATED_SINCE(5, 3) /*! \obsolete \overload @@ -2789,6 +2792,7 @@ void QOpenGLTexture::setCompressedData(int dataSize, void *data, Q_ASSERT(d->textureId); d->setCompressedData(0, 0, QOpenGLTexture::CubeMapPositiveX, dataSize, data, options); } +#endif /*! Returns \c true if your OpenGL implementation and version supports the texture diff --git a/src/gui/opengl/qopengltexture.h b/src/gui/opengl/qopengltexture.h index a53b1730b7..a0b23c211c 100644 --- a/src/gui/opengl/qopengltexture.h +++ b/src/gui/opengl/qopengltexture.h @@ -342,6 +342,7 @@ public: // Pixel transfer // ### Qt 6: remove the non-const void * overloads +#if QT_DEPRECATED_SINCE(5, 3) QT_DEPRECATED void setData(int mipLevel, int layer, CubeMapFace cubeFace, PixelFormat sourceFormat, PixelType sourceType, void *data, const QOpenGLPixelTransferOptions * const options = 0); @@ -353,6 +354,7 @@ public: void *data, const QOpenGLPixelTransferOptions * const options = 0); QT_DEPRECATED void setData(PixelFormat sourceFormat, PixelType sourceType, void *data, const QOpenGLPixelTransferOptions * const options = 0); +#endif // QT_DEPRECATED_SINCE(5, 3) void setData(int mipLevel, int layer, CubeMapFace cubeFace, PixelFormat sourceFormat, PixelType sourceType, @@ -368,6 +370,7 @@ public: // Compressed data upload // ### Qt 6: remove the non-const void * overloads +#if QT_DEPRECATED_SINCE(5, 3) QT_DEPRECATED void setCompressedData(int mipLevel, int layer, CubeMapFace cubeFace, int dataSize, void *data, const QOpenGLPixelTransferOptions * const options = 0); @@ -378,6 +381,7 @@ public: const QOpenGLPixelTransferOptions * const options = 0); QT_DEPRECATED void setCompressedData(int dataSize, void *data, const QOpenGLPixelTransferOptions * const options = 0); +#endif // QT_DEPRECATED_SINCE(5, 3) void setCompressedData(int mipLevel, int layer, CubeMapFace cubeFace, int dataSize, const void *data, |