summaryrefslogtreecommitdiffstats
path: root/src/opengl/gl2paintengineex
diff options
context:
space:
mode:
authorTom Cooksey <thomas.cooksey@nokia.com>2009-07-21 14:15:57 (GMT)
committerTom Cooksey <thomas.cooksey@nokia.com>2009-07-22 14:49:24 (GMT)
commit3597a5b82610752cf95372a5a5f7b33afc8d30b9 (patch)
tree4746be0f1b90894e72ab1e630268c5a048d0410c /src/opengl/gl2paintengineex
parente2aa651aba89bcc409dd090466b04036277a9a7c (diff)
downloadQt-3597a5b82610752cf95372a5a5f7b33afc8d30b9.zip
Qt-3597a5b82610752cf95372a5a5f7b33afc8d30b9.tar.gz
Qt-3597a5b82610752cf95372a5a5f7b33afc8d30b9.tar.bz2
Use texture_from_pixmap on X11 & avoid copies
The patch tries to use texture_from_pixmap extentions on glX to properly bind an X Pixmap to a texture in QGLContextPrivate::bindTexture(QPixmap,). Because GL & X have different coordinate systems, the pixmap will be inverted about the y-axis. The extension does however allow a GLX_Y_INVERTED_EXT attribute to be set which will bind the pixmap the correct way up. If the underlying driver doesn't support this, texture_from_pixmap can't be used for QGLContext::bindTexture, because that function expects the resulting texture to be the right way up. However, it can still be used internally by the paint engine for drawPixmap operations. For these cases, if the pixmap is inverted, the paint engine can simply invert the texture coords to compensate. This is why this patch also moves QGLTexture into qgl_p.h. QGLContextPrivate::bindTexture(QPixmap,) now returns a QGLTexture which the paint engine can inspect to see if it needs to invert the texture coords. Finally, it seems on some (probably all) drivers, deleting an X pixmap which has been bound to a texture before calling glFinish/swapBuffers renders garbage. Presumably this is because X deletes the pixmap behind the driver's back before it's had a chance to use it. To fix this, we reference all QPixmaps which have been bound to stop them being deleted and only deref them after we swap the buffer, when they can be safely deleted. Reviewed-By: Kim
Diffstat (limited to 'src/opengl/gl2paintengineex')
-rw-r--r--src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp22
1 files changed, 18 insertions, 4 deletions
diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
index 7e8a281..167eb64 100644
--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
+++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
@@ -74,6 +74,7 @@
#include <private/qpainter_p.h>
#include <private/qfontengine_p.h>
#include <private/qtextureglyphcache_p.h>
+#include <private/qpixmapdata_gl_p.h>
#include "qglgradientcache_p.h"
#include "qglengineshadermanager_p.h"
@@ -1054,14 +1055,18 @@ void QGL2PaintEngineEx::drawPixmap(const QRectF& dest, const QPixmap & pixmap, c
QGLContext *ctx = d->ctx;
glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT);
- GLuint id = ctx->d_func()->bindTexture(pixmap, GL_TEXTURE_2D, GL_RGBA, true);
+ QGLTexture *texture = ctx->d_func()->bindTexture(pixmap, GL_TEXTURE_2D, GL_RGBA, true, true);
+
+ GLfloat top = texture->yInverted ? (pixmap.height() - src.top()) : src.top();
+ GLfloat bottom = texture->yInverted ? (pixmap.height() - src.bottom()) : src.bottom();
+ QGLRect srcRect(src.left(), top, src.right(), bottom);
bool isBitmap = pixmap.isQBitmap();
bool isOpaque = !isBitmap && !pixmap.hasAlphaChannel();
d->updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT,
- state()->renderHints & QPainter::SmoothPixmapTransform, id);
- d->drawTexture(dest, src, pixmap.size(), isOpaque, isBitmap);
+ state()->renderHints & QPainter::SmoothPixmapTransform, texture->id);
+ d->drawTexture(dest, srcRect, pixmap.size(), isOpaque, isBitmap);
}
void QGL2PaintEngineEx::drawImage(const QRectF& dest, const QImage& image, const QRectF& src,
@@ -1073,7 +1078,8 @@ void QGL2PaintEngineEx::drawImage(const QRectF& dest, const QImage& image, const
QGLContext *ctx = d->ctx;
glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT);
- GLuint id = ctx->d_func()->bindTexture(image, GL_TEXTURE_2D, GL_RGBA, true);
+ QGLTexture *texture = ctx->d_func()->bindTexture(image, GL_TEXTURE_2D, GL_RGBA, true);
+ GLuint id = texture->id;
d->updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT,
state()->renderHints & QPainter::SmoothPixmapTransform, id);
@@ -1287,6 +1293,14 @@ bool QGL2PaintEngineEx::end()
glUseProgram(0);
d->transferMode(BrushDrawingMode);
d->drawable.swapBuffers();
+#if defined(Q_WS_X11)
+ // On some (probably all) drivers, deleting an X pixmap which has been bound to a texture
+ // before calling glFinish/swapBuffers renders garbage. Presumably this is because X deletes
+ // the pixmap behind the driver's back before it's had a chance to use it. To fix this, we
+ // reference all QPixmaps which have been bound to stop them being deleted and only deref
+ // them here, after swapBuffers, where they can be safely deleted.
+ ctx->d_func()->boundPixmaps.clear();
+#endif
d->drawable.doneCurrent();
d->ctx->d_ptr->active_engine = 0;