summaryrefslogtreecommitdiffstats
path: root/src/opengl
diff options
context:
space:
mode:
Diffstat (limited to 'src/opengl')
-rw-r--r--src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp21
-rw-r--r--src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h1
-rw-r--r--src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp2
-rw-r--r--src/opengl/qgl.cpp29
-rw-r--r--src/opengl/qgl_p.h2
-rw-r--r--src/opengl/qglframebufferobject.cpp31
-rw-r--r--src/opengl/qglpaintdevice.cpp13
-rw-r--r--src/opengl/qglpixelbuffer.cpp2
8 files changed, 93 insertions, 8 deletions
diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
index 43df311636..1fa5723d85 100644
--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
+++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
@@ -612,6 +612,21 @@ void QGL2PaintEngineExPrivate::resetGLState()
#endif
}
+bool QGL2PaintEngineExPrivate::resetOpenGLContextActiveEngine()
+{
+ QOpenGLContext *guiGlContext = ctx->contextHandle();
+ QOpenGLContextPrivate *guiGlContextPrivate =
+ guiGlContext ? QOpenGLContextPrivate::get(guiGlContext) : 0;
+
+ if (guiGlContextPrivate && guiGlContextPrivate->active_engine) {
+ ctx->d_func()->refreshCurrentFbo();
+ guiGlContextPrivate->active_engine = 0;
+ return true;
+ }
+
+ return false;
+}
+
void QGL2PaintEngineEx::endNativePainting()
{
Q_D(QGL2PaintEngineEx);
@@ -2015,6 +2030,8 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev)
d->ctx = d->device->context();
d->ctx->d_ptr->active_engine = this;
+ d->resetOpenGLContextActiveEngine();
+
const QSize sz = d->device->size();
d->width = sz.width();
d->height = sz.height();
@@ -2080,6 +2097,8 @@ bool QGL2PaintEngineEx::end()
ctx->d_ptr->active_engine = 0;
+ d->resetOpenGLContextActiveEngine();
+
d->resetGLState();
delete d->shaderManager;
@@ -2105,7 +2124,7 @@ void QGL2PaintEngineEx::ensureActive()
Q_D(QGL2PaintEngineEx);
QGLContext *ctx = d->ctx;
- if (isActive() && ctx->d_ptr->active_engine != this) {
+ if (isActive() && (ctx->d_ptr->active_engine != this || d->resetOpenGLContextActiveEngine())) {
ctx->d_ptr->active_engine = this;
d->needsSync = true;
}
diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h
index 528bfdeeb9..ac1d63df17 100644
--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h
+++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h
@@ -191,6 +191,7 @@ public:
void updateTextureFilter(GLenum target, GLenum wrapMode, bool smoothPixmapTransform, GLuint id = GLuint(-1));
void resetGLState();
+ bool resetOpenGLContextActiveEngine();
// fill, stroke, drawTexture, drawPixmaps & drawCachedGlyphs are the main rendering entry-points,
// however writeClip can also be thought of as en entry point as it does similar things.
diff --git a/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp b/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp
index 211fad267f..8cd26f1ea4 100644
--- a/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp
+++ b/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp
@@ -167,6 +167,8 @@ void QGLTextureGlyphCache::resizeTextureData(int width, int height)
// ### the QTextureGlyphCache API needs to be reworked to allow
// ### resizeTextureData to fail
+ ctx->d_ptr->refreshCurrentFbo();
+
funcs->glBindFramebuffer(GL_FRAMEBUFFER, m_textureResource->m_fbo);
GLuint tmp_texture;
diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp
index 1e49d95087..35f08e0092 100644
--- a/src/opengl/qgl.cpp
+++ b/src/opengl/qgl.cpp
@@ -510,6 +510,35 @@ void QGLContextPrivate::setupSharing() {
}
}
+void QGLContextPrivate::refreshCurrentFbo()
+{
+ QOpenGLContextPrivate *guiGlContextPrivate =
+ guiGlContext ? QOpenGLContextPrivate::get(guiGlContext) : 0;
+
+ // if QOpenGLFramebufferObjects have been used in the mean-time, we've lost our cached value
+ if (guiGlContextPrivate && guiGlContextPrivate->qgl_current_fbo_invalid) {
+ GLint current;
+ QOpenGLFunctions *funcs = qgl_functions();
+ funcs->glGetIntegerv(GL_FRAMEBUFFER_BINDING, &current);
+
+ current_fbo = current;
+
+ guiGlContextPrivate->qgl_current_fbo_invalid = false;
+ }
+}
+
+void QGLContextPrivate::setCurrentFbo(GLuint fbo)
+{
+ current_fbo = fbo;
+
+ QOpenGLContextPrivate *guiGlContextPrivate =
+ guiGlContext ? QOpenGLContextPrivate::get(guiGlContext) : 0;
+
+ if (guiGlContextPrivate)
+ guiGlContextPrivate->qgl_current_fbo_invalid = false;
+}
+
+
/*!
\fn bool QGLFormat::doubleBuffer() const
diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h
index c4151a3d34..4cf656fd86 100644
--- a/src/opengl/qgl_p.h
+++ b/src/opengl/qgl_p.h
@@ -238,6 +238,8 @@ public:
bool ownContext;
void setupSharing();
+ void refreshCurrentFbo();
+ void setCurrentFbo(GLuint fbo);
QGLFormat glFormat;
QGLFormat reqFormat;
diff --git a/src/opengl/qglframebufferobject.cpp b/src/opengl/qglframebufferobject.cpp
index 4ef50e9334..4537f5bfae 100644
--- a/src/opengl/qglframebufferobject.cpp
+++ b/src/opengl/qglframebufferobject.cpp
@@ -472,6 +472,8 @@ void QGLFramebufferObjectPrivate::init(QGLFramebufferObject *q, const QSize &sz,
if (!funcs.hasOpenGLFeature(QOpenGLFunctions::Framebuffers))
return;
+ ctx->d_ptr->refreshCurrentFbo();
+
size = sz;
target = texture_target;
// texture dimensions
@@ -1027,7 +1029,7 @@ bool QGLFramebufferObject::bind()
d->funcs.glBindFramebuffer(GL_FRAMEBUFFER, d->fbo());
d->valid = d->checkFramebufferStatus();
if (d->valid && current)
- current->d_ptr->current_fbo = d->fbo();
+ current->d_ptr->setCurrentFbo(d->fbo());
return d->valid;
}
@@ -1060,7 +1062,7 @@ bool QGLFramebufferObject::release()
#endif
if (current) {
- current->d_ptr->current_fbo = current->d_ptr->default_fbo;
+ current->d_ptr->setCurrentFbo(current->d_ptr->default_fbo);
d->funcs.glBindFramebuffer(GL_FRAMEBUFFER, current->d_ptr->default_fbo);
}
@@ -1109,6 +1111,20 @@ QGLFramebufferObjectFormat QGLFramebufferObject::format() const
Returns the contents of this framebuffer object as a QImage.
+ 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
+
On QNX the back buffer is not preserved when a buffer swap occures. So this function
might return old content.
*/
@@ -1173,7 +1189,7 @@ bool QGLFramebufferObject::bindDefault()
if (!functions.hasOpenGLFeature(QOpenGLFunctions::Framebuffers))
return false;
- ctx->d_ptr->current_fbo = ctx->d_ptr->default_fbo;
+ ctx->d_ptr->setCurrentFbo(ctx->d_ptr->default_fbo);
functions.glBindFramebuffer(GL_FRAMEBUFFER, ctx->d_ptr->default_fbo);
#ifdef QT_DEBUG
} else {
@@ -1320,7 +1336,12 @@ bool QGLFramebufferObject::isBound() const
{
Q_D(const QGLFramebufferObject);
const QGLContext *current = QGLContext::currentContext();
- return current ? current->d_ptr->current_fbo == d->fbo() : false;
+ if (current) {
+ current->d_ptr->refreshCurrentFbo();
+ return current->d_ptr->current_fbo == d->fbo();
+ }
+
+ return false;
}
/*!
@@ -1400,6 +1421,8 @@ void QGLFramebufferObject::blitFramebuffer(QGLFramebufferObject *target, const Q
const int ty0 = th - (targetRect.top() + targetRect.height());
const int ty1 = th - targetRect.top();
+ ctx->d_ptr->refreshCurrentFbo();
+
functions.glBindFramebuffer(GL_READ_FRAMEBUFFER, source ? source->handle() : 0);
functions.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, target ? target->handle() : 0);
diff --git a/src/opengl/qglpaintdevice.cpp b/src/opengl/qglpaintdevice.cpp
index 40cc7bb71d..c07d0a761b 100644
--- a/src/opengl/qglpaintdevice.cpp
+++ b/src/opengl/qglpaintdevice.cpp
@@ -74,6 +74,8 @@ void QGLPaintDevice::beginPaint()
QGLContext *ctx = context();
ctx->makeCurrent();
+ ctx->d_func()->refreshCurrentFbo();
+
// Record the currently bound FBO so we can restore it again
// in endPaint() and bind this device's FBO
//
@@ -85,7 +87,7 @@ void QGLPaintDevice::beginPaint()
m_previousFBO = ctx->d_func()->current_fbo;
if (m_previousFBO != m_thisFBO) {
- ctx->d_ptr->current_fbo = m_thisFBO;
+ ctx->d_func()->setCurrentFbo(m_thisFBO);
ctx->contextHandle()->functions()->glBindFramebuffer(GL_FRAMEBUFFER, m_thisFBO);
}
@@ -102,8 +104,10 @@ void QGLPaintDevice::ensureActiveTarget()
if (ctx != QGLContext::currentContext())
ctx->makeCurrent();
+ ctx->d_func()->refreshCurrentFbo();
+
if (ctx->d_ptr->current_fbo != m_thisFBO) {
- ctx->d_ptr->current_fbo = m_thisFBO;
+ ctx->d_func()->setCurrentFbo(m_thisFBO);
ctx->contextHandle()->functions()->glBindFramebuffer(GL_FRAMEBUFFER, m_thisFBO);
}
@@ -114,8 +118,11 @@ void QGLPaintDevice::endPaint()
{
// Make sure the FBO bound at beginPaint is re-bound again here:
QGLContext *ctx = context();
+
+ ctx->d_func()->refreshCurrentFbo();
+
if (m_previousFBO != ctx->d_func()->current_fbo) {
- ctx->d_ptr->current_fbo = m_previousFBO;
+ ctx->d_func()->setCurrentFbo(m_previousFBO);
ctx->contextHandle()->functions()->glBindFramebuffer(GL_FRAMEBUFFER, m_previousFBO);
}
diff --git a/src/opengl/qglpixelbuffer.cpp b/src/opengl/qglpixelbuffer.cpp
index 56bfaebe4f..63b624aea2 100644
--- a/src/opengl/qglpixelbuffer.cpp
+++ b/src/opengl/qglpixelbuffer.cpp
@@ -344,6 +344,8 @@ void QGLPixelBuffer::updateDynamicTexture(GLuint texture_id) const
QOpenGLExtensions extensions(ctx->contextHandle());
+ ctx->d_ptr->refreshCurrentFbo();
+
if (d->blit_fbo) {
QOpenGLFramebufferObject::blitFramebuffer(d->blit_fbo, d->fbo);
extensions.glBindFramebuffer(GL_READ_FRAMEBUFFER, d->blit_fbo->handle());