diff options
author | Tom Cooksey <thomas.cooksey@nokia.com> | 2009-07-21 14:15:57 (GMT) |
---|---|---|
committer | Tom Cooksey <thomas.cooksey@nokia.com> | 2009-07-22 14:49:24 (GMT) |
commit | 3597a5b82610752cf95372a5a5f7b33afc8d30b9 (patch) | |
tree | 4746be0f1b90894e72ab1e630268c5a048d0410c /src/opengl/qpixmapdata_gl.cpp | |
parent | e2aa651aba89bcc409dd090466b04036277a9a7c (diff) | |
download | Qt-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/qpixmapdata_gl.cpp')
-rw-r--r-- | src/opengl/qpixmapdata_gl.cpp | 46 |
1 files changed, 26 insertions, 20 deletions
diff --git a/src/opengl/qpixmapdata_gl.cpp b/src/opengl/qpixmapdata_gl.cpp index fe3bb0c..e3ee2b2 100644 --- a/src/opengl/qpixmapdata_gl.cpp +++ b/src/opengl/qpixmapdata_gl.cpp @@ -97,7 +97,6 @@ static int qt_gl_pixmap_serial = 0; QGLPixmapData::QGLPixmapData(PixelType type) : QPixmapData(type, OpenGLClass) , m_renderFbo(0) - , m_textureId(0) , m_engine(0) , m_ctx(0) , m_dirty(false) @@ -113,9 +112,9 @@ QGLPixmapData::~QGLPixmapData() if (!shareWidget) return; - if (m_textureId) { + if (m_texture.id) { QGLShareContextScope ctx(shareWidget->context()); - glDeleteTextures(1, &m_textureId); + glDeleteTextures(1, &m_texture.id); } } @@ -148,10 +147,10 @@ void QGLPixmapData::resize(int width, int height) is_null = (w <= 0 || h <= 0); d = pixelType() == QPixmapData::PixmapType ? 32 : 1; - if (m_textureId) { + if (m_texture.id) { QGLShareContextScope ctx(qt_gl_share_widget()->context()); - glDeleteTextures(1, &m_textureId); - m_textureId = 0; + glDeleteTextures(1, &m_texture.id); + m_texture.id = 0; } m_source = QImage(); @@ -172,9 +171,9 @@ void QGLPixmapData::ensureCreated() const const GLenum format = qt_gl_preferredTextureFormat(); const GLenum target = GL_TEXTURE_2D; - if (!m_textureId) { - glGenTextures(1, &m_textureId); - glBindTexture(target, m_textureId); + if (!m_texture.id) { + glGenTextures(1, &m_texture.id); + glBindTexture(target, m_texture.id); GLenum format = m_hasAlpha ? GL_RGBA : GL_RGB; glTexImage2D(target, 0, format, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); @@ -185,13 +184,15 @@ void QGLPixmapData::ensureCreated() const if (!m_source.isNull()) { const QImage tx = ctx->d_func()->convertToGLFormat(m_source, true, format); - glBindTexture(target, m_textureId); + glBindTexture(target, m_texture.id); glTexSubImage2D(target, 0, 0, 0, w, h, format, GL_UNSIGNED_BYTE, tx.bits()); if (useFramebufferObjects()) m_source = QImage(); } + + m_texture.clean = false; } QGLFramebufferObject *QGLPixmapData::fbo() const @@ -223,10 +224,10 @@ void QGLPixmapData::fromImage(const QImage &image, is_null = (w <= 0 || h <= 0); d = pixelType() == QPixmapData::PixmapType ? 32 : 1; - if (m_textureId) { + if (m_texture.id) { QGLShareContextScope ctx(qt_gl_share_widget()->context()); - glDeleteTextures(1, &m_textureId); - m_textureId = 0; + glDeleteTextures(1, &m_texture.id); + m_texture.id = 0; } } @@ -256,9 +257,9 @@ void QGLPixmapData::fill(const QColor &color) bool hasAlpha = color.alpha() != 255; if (hasAlpha && !m_hasAlpha) { - if (m_textureId) { - glDeleteTextures(1, &m_textureId); - m_textureId = 0; + if (m_texture.id) { + glDeleteTextures(1, &m_texture.id); + m_texture.id = 0; m_dirty = true; } m_hasAlpha = color.alpha() != 255; @@ -321,7 +322,7 @@ QImage QGLPixmapData::toImage() const } QGLShareContextScope ctx(qt_gl_share_widget()->context()); - glBindTexture(GL_TEXTURE_2D, m_textureId); + glBindTexture(GL_TEXTURE_2D, m_texture.id); return qt_gl_read_texture(QSize(w, h), true, true); } @@ -351,7 +352,7 @@ void QGLPixmapData::copyBackFromRenderFbo(bool keepCurrentFboBound) const glBindFramebuffer(GL_FRAMEBUFFER_EXT, ctx->d_ptr->fbo); glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, - GL_TEXTURE_2D, m_textureId, 0); + GL_TEXTURE_2D, m_texture.id, 0); const int x0 = 0; const int x1 = w; @@ -489,7 +490,7 @@ GLuint QGLPixmapData::bind(bool copyBack) const ensureCreated(); } - GLuint id = m_textureId; + GLuint id = m_texture.id; glBindTexture(GL_TEXTURE_2D, id); return id; } @@ -497,7 +498,12 @@ GLuint QGLPixmapData::bind(bool copyBack) const GLuint QGLPixmapData::textureId() const { ensureCreated(); - return m_textureId; + return m_texture.id; +} + +QGLTexture* QGLPixmapData::texture() const +{ + return &m_texture; } extern int qt_defaultDpiX(); |