summaryrefslogtreecommitdiffstats
path: root/src/opengl
diff options
context:
space:
mode:
authorTom Cooksey <thomas.cooksey@nokia.com>2009-07-30 08:15:46 (GMT)
committerTom Cooksey <thomas.cooksey@nokia.com>2009-07-30 08:15:46 (GMT)
commitd2820e3a67812d31f45df282b378a75511bb1c4b (patch)
tree8ab0213d5250289b30d7e26e50ab85fe3c5c4068 /src/opengl
parent9523b27be4fe00870d19c4ff4caa2d78dcf520e6 (diff)
parent0ff4c453bf3d549e8344ab18f643f61a8b6174ef (diff)
downloadQt-d2820e3a67812d31f45df282b378a75511bb1c4b.zip
Qt-d2820e3a67812d31f45df282b378a75511bb1c4b.tar.gz
Qt-d2820e3a67812d31f45df282b378a75511bb1c4b.tar.bz2
Merge branch 'texture_from_pixmap'
Diffstat (limited to 'src/opengl')
-rw-r--r--src/opengl/qgl.cpp37
-rw-r--r--src/opengl/qgl_p.h14
-rw-r--r--src/opengl/qgl_x11.cpp199
-rw-r--r--src/opengl/qgl_x11egl.cpp173
4 files changed, 330 insertions, 93 deletions
diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp
index f6bfcbe..48d09ce 100644
--- a/src/opengl/qgl.cpp
+++ b/src/opengl/qgl.cpp
@@ -86,6 +86,7 @@
#include <private/qpixmapdata_gl_p.h>
#include <private/qglpixelbuffer_p.h>
#include <private/qwindowsurface_gl_p.h>
+#include <private/qimagepixmapcleanuphooks_p.h>
#include "qcolormap.h"
#include "qfile.h"
#include "qlibrary.h"
@@ -1407,15 +1408,17 @@ QGLTextureCache::QGLTextureCache()
{
Q_ASSERT(qt_gl_texture_cache == 0);
qt_gl_texture_cache = this;
- qt_pixmap_cleanup_hook_64 = cleanupHook;
- qt_image_cleanup_hook_64 = cleanupHook;
+
+ QImagePixmapCleanupHooks::instance()->addPixmapHook(pixmapCleanupHook);
+ QImagePixmapCleanupHooks::instance()->addImageHook(imageCleanupHook);
}
QGLTextureCache::~QGLTextureCache()
{
qt_gl_texture_cache = 0;
- qt_pixmap_cleanup_hook_64 = 0;
- qt_image_cleanup_hook_64 = 0;
+
+ QImagePixmapCleanupHooks::instance()->removePixmapHook(pixmapCleanupHook);
+ QImagePixmapCleanupHooks::instance()->removeImageHook(imageCleanupHook);
}
void QGLTextureCache::insert(QGLContext* ctx, qint64 key, QGLTexture* texture, int cost)
@@ -1471,7 +1474,7 @@ QGLTextureCache* QGLTextureCache::instance()
a hook that removes textures from the cache when a pixmap/image
is deref'ed
*/
-void QGLTextureCache::cleanupHook(qint64 cacheKey)
+void QGLTextureCache::imageCleanupHook(qint64 cacheKey)
{
// ### remove when the GL texture cache becomes thread-safe
if (qApp->thread() != QThread::currentThread())
@@ -1481,6 +1484,24 @@ void QGLTextureCache::cleanupHook(qint64 cacheKey)
instance()->remove(cacheKey);
}
+
+void QGLTextureCache::pixmapCleanupHook(QPixmap* pixmap)
+{
+ // ### remove when the GL texture cache becomes thread-safe
+ if (qApp->thread() == QThread::currentThread()) {
+ const qint64 cacheKey = pixmap->cacheKey();
+ QGLTexture *texture = instance()->getTexture(cacheKey);
+ if (texture && texture->clean)
+ instance()->remove(cacheKey);
+ }
+#if defined(Q_WS_X11)
+ QPixmapData *pd = pixmap->data_ptr();
+ // Only need to delete the gl surface if the pixmap is about to be deleted
+ if (pd->ref == 0)
+ QGLContextPrivate::destroyGlSurfaceForPixmap(pd);
+#endif
+}
+
void QGLTextureCache::deleteIfEmpty()
{
if (instance()->size() == 0)
@@ -2021,11 +2042,11 @@ QGLTexture *QGLContextPrivate::bindTexture(const QPixmap &pixmap, GLenum target,
#if defined(Q_WS_X11)
// Try to use texture_from_pixmap
if (pd->classId() == QPixmapData::X11Class) {
- QPixmap *thatPixmap = const_cast<QPixmap*>(&pixmap);
- texture = bindTextureFromNativePixmap(thatPixmap, key, canInvert);
+ texture = bindTextureFromNativePixmap(pd, key, canInvert);
if (texture) {
texture->clean = clean;
- boundPixmaps.insert(thatPixmap->data_ptr(), QPixmap(pixmap));
+ texture->boundPixmap = pd;
+ boundPixmaps.insert(pd, QPixmap(pixmap));
}
}
#endif
diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h
index 85dae0d..f21ab93 100644
--- a/src/opengl/qgl_p.h
+++ b/src/opengl/qgl_p.h
@@ -241,7 +241,9 @@ public:
quint32 gpm;
int screen;
QHash<QPixmapData*, QPixmap> boundPixmaps;
- QGLTexture *bindTextureFromNativePixmap(QPixmap *pm, const qint64 key, bool internal);
+ QGLTexture *bindTextureFromNativePixmap(QPixmapData*, const qint64 key, bool canInvert);
+ static void destroyGlSurfaceForPixmap(QPixmapData*);
+ static void unbindPixmapFromTexture(QPixmapData*);
#endif
#if defined(Q_WS_MAC)
bool update;
@@ -423,7 +425,8 @@ public:
// is a current context - the context the pixmap was bound to a texture in.
// Otherwise the release doesn't do anything and you get BadDrawable errors
// when you come to delete the context.
- deleteBoundPixmap();
+ if (boundPixmap)
+ QGLContextPrivate::unbindPixmapFromTexture(boundPixmap);
#endif
glDeleteTextures(1, &id);
if (switch_context && current)
@@ -437,9 +440,9 @@ public:
bool clean;
bool yInverted; // NOTE: Y-Inverted textures are for internal use only!
#if defined(Q_WS_X11)
- Qt::HANDLE boundPixmap;
- void deleteBoundPixmap(); // in qgl_x11.cpp/qgl_x11egl.cpp
+ QPixmapData* boundPixmap;
#endif
+
};
class QGLTextureCache {
@@ -458,7 +461,8 @@ public:
static QGLTextureCache *instance();
static void deleteIfEmpty();
- static void cleanupHook(qint64 cacheKey);
+ static void imageCleanupHook(qint64 cacheKey);
+ static void pixmapCleanupHook(QPixmap* pixmap);
private:
QCache<qint64, QGLTexture> m_cache;
diff --git a/src/opengl/qgl_x11.cpp b/src/opengl/qgl_x11.cpp
index cf70991..4509a64 100644
--- a/src/opengl/qgl_x11.cpp
+++ b/src/opengl/qgl_x11.cpp
@@ -58,11 +58,16 @@
#include <private/qglpixelbuffer_p.h>
#endif
+// We always define GLX_EXT_texture_from_pixmap ourselves because
+// we can't trust system headers to do it properly
+#define GLX_EXT_texture_from_pixmap 1
+
#define INT8 dummy_INT8
#define INT32 dummy_INT32
#include <GL/glx.h>
#undef INT8
#undef INT32
+
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>
@@ -90,7 +95,7 @@ extern const QX11Info *qt_x11Info(const QPaintDevice *pd);
#define GLX_SAMPLES_ARB 100001
#endif
-#ifndef GLX_EXT_texture_from_pixmap
+#ifndef GLX_TEXTURE_2D_BIT_EXT
#define GLX_TEXTURE_2D_BIT_EXT 0x00000002
#define GLX_TEXTURE_RECTANGLE_BIT_EXT 0x00000004
#define GLX_BIND_TO_TEXTURE_RGB_EXT 0x20D0
@@ -1548,38 +1553,26 @@ void QGLExtensions::init()
}
}
-#if !defined(glXBindTexImageEXT)
+// Solaris defines glXBindTexImageEXT as part of the GL library
+#if defined(GLX_VERSION_1_3) && !defined(Q_OS_HPUX)
typedef void (*qt_glXBindTexImageEXT)(Display*, GLXDrawable, int, const int*);
-static qt_glXBindTexImageEXT glXBindTexImageEXT = 0;
-#endif
-#if !defined(glXReleaseTexImageEXT)
typedef void (*qt_glXReleaseTexImageEXT)(Display*, GLXDrawable, int);
+static qt_glXBindTexImageEXT glXBindTexImageEXT = 0;
static qt_glXReleaseTexImageEXT glXReleaseTexImageEXT = 0;
-#endif
-static bool qt_resolved_texture_from_pixmap = false;
-QGLTexture *QGLContextPrivate::bindTextureFromNativePixmap(QPixmap *pm, const qint64 key, bool canInvert)
+bool qt_resolveTextureFromPixmap()
{
-#if !defined(Q_OS_LINUX)
- return 0;
-#else
- Q_Q(QGLContext);
-
- if (pm->data_ptr()->classId() != QPixmapData::X11Class)
- return 0;
- QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pm->data_ptr());
- const QX11Info *x11Info = qt_x11Info(pm);
+ static bool resolvedTextureFromPixmap = false;
+ if (!resolvedTextureFromPixmap) {
+ resolvedTextureFromPixmap = true;
- // Check to see if we have NPOT texture support
- // TODO: Use GLX_TEXTURE_RECTANGLE_EXT texture target on systems without npot textures
- if ( !(QGLExtensions::glExtensions & QGLExtensions::NPOTTextures) &&
- !(QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_2_0))
- return 0;
-
-
- if (!qt_resolved_texture_from_pixmap) {
- qt_resolved_texture_from_pixmap = true;
+ // Check to see if we have NPOT texture support
+ if ( !(QGLExtensions::glExtensions & QGLExtensions::NPOTTextures) &&
+ !(QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_2_0))
+ {
+ return false; // Can't use TFP without NPOT
+ }
QString glxExt = QLatin1String(glXGetClientString(QX11Info::display(), GLX_EXTENSIONS));
if (glxExt.contains(QLatin1String("GLX_EXT_texture_from_pixmap"))) {
@@ -1601,81 +1594,139 @@ QGLTexture *QGLContextPrivate::bindTextureFromNativePixmap(QPixmap *pm, const qi
}
}
- if (!glXBindTexImageEXT)
- return 0;
+ return glXBindTexImageEXT && glXReleaseTexImageEXT;
+}
+#endif //defined(GLX_VERSION_1_3) && !defined(Q_OS_HPUX)
+
+QGLTexture *QGLContextPrivate::bindTextureFromNativePixmap(QPixmapData *pmd, const qint64 key, bool canInvert)
+{
#if !defined(GLX_VERSION_1_3) || defined(Q_OS_HPUX)
return 0;
#else
- GLXFBConfig *configList = 0;
- GLXFBConfig glxPixmapConfig;
- int configCount = 0;
- bool hasAlpha = pixmapData->hasAlphaChannel();
-
- int configAttribs[] = {
- hasAlpha ? GLX_BIND_TO_TEXTURE_RGBA_EXT : GLX_BIND_TO_TEXTURE_RGB_EXT, True,
- GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT,
- GLX_BIND_TO_TEXTURE_TARGETS_EXT, GLX_TEXTURE_2D_BIT_EXT,
- // QGLContext::bindTexture() can't return an inverted texture, but QPainter::drawPixmap() can:
- GLX_Y_INVERTED_EXT, canInvert ? GLX_DONT_CARE : False,
- XNone
-// GLX_BIND_TO_MIPMAP_TEXTURE_EXT, False,
-// GLX_BIND_TO_TEXTURE_TARGETS_EXT, GLX_TEXTURE_1D_BIT_EXT or GLX_TEXTURE_2D_BIT_EXT or GLX_TEXTURE_RECTANGLE_BIT_EXT
- };
- configList = glXChooseFBConfig(x11Info->display(), x11Info->screen(), configAttribs, &configCount);
- if (!configList)
- return 0;
- glxPixmapConfig = configList[0];
- XFree(configList);
-
- GLXPixmap glxPixmap;
- int pixmapAttribs[] = {
- GLX_TEXTURE_FORMAT_EXT, hasAlpha ? GLX_TEXTURE_FORMAT_RGBA_EXT : GLX_TEXTURE_FORMAT_RGB_EXT,
- GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
- GLX_MIPMAP_TEXTURE_EXT, False,
- XNone
-// GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGBA_EXT or GLX_TEXTURE_FORMAT_RGB_EXT or GLX_TEXTURE_FORMAT_NONE_EXT,
-// GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT or GLX_TEXTURE_RECTANGLE_EXT,
-// GLX_MIPMAP_TEXTURE_EXT, True or False,
- };
+ Q_Q(QGLContext);
- // Wrap the X Pixmap into a GLXPixmap:
- glxPixmap = glXCreatePixmap(x11Info->display(), glxPixmapConfig, pixmapData->handle(), pixmapAttribs);
+ Q_ASSERT(pmd->classId() == QPixmapData::X11Class);
- if (!glxPixmap)
+ if (!qt_resolveTextureFromPixmap())
return 0;
- int yInverted;
- glXGetFBConfigAttrib(x11Info->display(), glxPixmapConfig, GLX_Y_INVERTED_EXT, &yInverted);
+ QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pmd);
+ const QX11Info &x11Info = pixmapData->xinfo;
+
+ // Store the configs (Can be static because configs aren't dependent on current context)
+ static GLXFBConfig glxRGBPixmapConfig = 0;
+ static bool RGBConfigInverted = false;
+ static GLXFBConfig glxRGBAPixmapConfig = 0;
+ static bool RGBAConfigInverted = false;
+
+ bool hasAlpha = pixmapData->hasAlphaChannel();
+
+ // Check to see if we need a config
+ if ( (hasAlpha && !glxRGBAPixmapConfig) || (!hasAlpha && !glxRGBPixmapConfig) ) {
+ GLXFBConfig *configList = 0;
+ int configCount = 0;
+
+ int configAttribs[] = {
+ hasAlpha ? GLX_BIND_TO_TEXTURE_RGBA_EXT : GLX_BIND_TO_TEXTURE_RGB_EXT, True,
+ GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT,
+ GLX_BIND_TO_TEXTURE_TARGETS_EXT, GLX_TEXTURE_2D_BIT_EXT,
+ // QGLContext::bindTexture() can't return an inverted texture, but QPainter::drawPixmap() can:
+ GLX_Y_INVERTED_EXT, canInvert ? GLX_DONT_CARE : False,
+ XNone
+ };
+ configList = glXChooseFBConfig(x11Info.display(), x11Info.screen(), configAttribs, &configCount);
+ if (!configList)
+ return 0;
+
+ int yInv;
+ glXGetFBConfigAttrib(x11Info.display(), configList[0], GLX_Y_INVERTED_EXT, &yInv);
+
+ if (hasAlpha) {
+ glxRGBAPixmapConfig = configList[0];
+ RGBAConfigInverted = yInv;
+ }
+ else {
+ glxRGBPixmapConfig = configList[0];
+ RGBConfigInverted = yInv;
+ }
+
+ XFree(configList);
+ }
+
+ // Check to see if the surface is still valid
+ if (pixmapData->gl_surface &&
+ hasAlpha != (pixmapData->flags & QX11PixmapData::GlSurfaceCreatedWithAlpha))
+ {
+ // Surface is invalid!
+ destroyGlSurfaceForPixmap(pixmapData);
+ }
+
+ // Check to see if we need a surface
+ if (!pixmapData->gl_surface) {
+ GLXPixmap glxPixmap;
+ int pixmapAttribs[] = {
+ GLX_TEXTURE_FORMAT_EXT, hasAlpha ? GLX_TEXTURE_FORMAT_RGBA_EXT : GLX_TEXTURE_FORMAT_RGB_EXT,
+ GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
+ GLX_MIPMAP_TEXTURE_EXT, False, // Maybe needs to be don't care
+ XNone
+ };
+
+ // Wrap the X Pixmap into a GLXPixmap:
+ glxPixmap = glXCreatePixmap(x11Info.display(),
+ hasAlpha ? glxRGBAPixmapConfig : glxRGBPixmapConfig,
+ pixmapData->handle(), pixmapAttribs);
+
+ if (!glxPixmap)
+ return 0;
+
+ pixmapData->gl_surface = (Qt::HANDLE)glxPixmap;
+
+ // Make sure the cleanup hook gets called so we can delete the glx pixmap
+ pixmapData->is_cached = true;
+ }
GLuint textureId;
glGenTextures(1, &textureId);
glBindTexture(GL_TEXTURE_2D, textureId);
- glXBindTexImageEXT(x11Info->display(), glxPixmap, GLX_FRONT_LEFT_EXT, 0);
+ glXBindTexImageEXT(x11Info.display(), (GLXPixmap)pixmapData->gl_surface, GLX_FRONT_LEFT_EXT, 0);
glBindTexture(GL_TEXTURE_2D, textureId);
- QGLTexture *texture = new QGLTexture(q, textureId, GL_TEXTURE_2D, canInvert, yInverted);
- texture->boundPixmap = glxPixmap;
+ QGLTexture *texture = new QGLTexture(q, textureId, GL_TEXTURE_2D, canInvert, false);
+ texture->yInverted = (hasAlpha && RGBAConfigInverted) || (!hasAlpha && RGBConfigInverted);
+ if (texture->yInverted)
+ pixmapData->flags |= QX11PixmapData::InvertedWhenBoundToTexture;
// We assume the cost of bound pixmaps is zero
QGLTextureCache::instance()->insert(q, key, texture, 0);
return texture;
#endif //!defined(GLX_VERSION_1_3) || defined(Q_OS_HPUX)
-#endif //!defined(Q_OS_LINUX
}
-void QGLTexture::deleteBoundPixmap()
+
+void QGLContextPrivate::destroyGlSurfaceForPixmap(QPixmapData* pmd)
{
-#if defined(GLX_VERSION_1_3) && !defined(Q_OS_HPUX) && defined(Q_OS_LINUX)
- if (boundPixmap) {
- glXReleaseTexImageEXT(QX11Info::display(), boundPixmap, GLX_FRONT_LEFT_EXT);
- glXDestroyPixmap(QX11Info::display(), boundPixmap);
- boundPixmap = 0;
+#if defined(GLX_VERSION_1_3) && !defined(Q_OS_HPUX)
+ Q_ASSERT(pmd->classId() == QPixmapData::X11Class);
+ QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pmd);
+ if (pixmapData->gl_surface) {
+ glXDestroyPixmap(QX11Info::display(), (GLXPixmap)pixmapData->gl_surface);
+ pixmapData->gl_surface = 0;
}
#endif
}
+void QGLContextPrivate::unbindPixmapFromTexture(QPixmapData* pmd)
+{
+#if defined(GLX_VERSION_1_3) && !defined(Q_OS_HPUX)
+ Q_ASSERT(pmd->classId() == QPixmapData::X11Class);
+ Q_ASSERT(QGLContext::currentContext());
+ QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pmd);
+ if (pixmapData->gl_surface)
+ glXReleaseTexImageEXT(QX11Info::display(), (GLXPixmap)pixmapData->gl_surface, GLX_FRONT_LEFT_EXT);
+#endif
+}
QT_END_NAMESPACE
diff --git a/src/opengl/qgl_x11egl.cpp b/src/opengl/qgl_x11egl.cpp
index c6904fe..5ab3647 100644
--- a/src/opengl/qgl_x11egl.cpp
+++ b/src/opengl/qgl_x11egl.cpp
@@ -41,15 +41,16 @@
#include "qgl.h"
#include <private/qt_x11_p.h>
+#include <private/qpixmap_x11_p.h>
#include <private/qgl_p.h>
#include <private/qpaintengine_opengl_p.h>
#include "qgl_egl_p.h"
#include "qcolormap.h"
+#include <QDebug>
QT_BEGIN_NAMESPACE
-
bool QGLFormat::hasOpenGL()
{
return true;
@@ -486,15 +487,175 @@ void QGLWidgetPrivate::recreateEglSurface(bool force)
}
}
-QGLTexture *QGLContextPrivate::bindTextureFromNativePixmap(QPixmap *pm, const qint64 key, bool canInvert)
+
+QGLTexture *QGLContextPrivate::bindTextureFromNativePixmap(QPixmapData* pd, const qint64 key, bool canInvert)
{
- // TODO
- return 0;
+ Q_Q(QGLContext);
+
+ Q_ASSERT(pd->classId() == QPixmapData::X11Class);
+
+ static bool checkedForTFP = false;
+ static bool haveTFP = false;
+
+ if (!checkedForTFP) {
+ // Check for texture_from_pixmap egl extension
+ checkedForTFP = true;
+ if (eglContext->hasExtension("EGL_NOKIA_texture_from_pixmap") ||
+ eglContext->hasExtension("EGL_EXT_texture_from_pixmap"))
+ {
+ qDebug("Found texture_from_pixmap EGL extension!");
+ haveTFP = true;
+ }
+ }
+
+ if (!haveTFP)
+ return 0;
+
+ QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pd);
+
+ bool hasAlpha = pixmapData->hasAlphaChannel();
+
+ // Check to see if the surface is still valid
+ if (pixmapData->gl_surface &&
+ hasAlpha != (pixmapData->flags & QX11PixmapData::GlSurfaceCreatedWithAlpha))
+ {
+ // Surface is invalid!
+ destroyGlSurfaceForPixmap(pixmapData);
+ }
+
+ EGLint pixmapAttribs[] = {
+ EGL_TEXTURE_TARGET, EGL_TEXTURE_2D,
+ EGL_TEXTURE_FORMAT, hasAlpha ? EGL_TEXTURE_RGBA : EGL_TEXTURE_RGB,
+ EGL_NONE
+ };
+ Q_ASSERT(sizeof(Qt::HANDLE) >= sizeof(EGLSurface)); // Just to make totally sure!
+ if (pixmapData->gl_surface == 0)
+ pixmapData->gl_surface = (Qt::HANDLE)EGL_NO_SURFACE;
+ EGLSurface pixmapSurface = (EGLSurface)pixmapData->gl_surface;
+ static EGLConfig pixmapRGBConfig = 0;
+ static EGLConfig pixmapRGBAConfig = 0;
+
+ // Check to see if we need to find a config
+ if ((hasAlpha && !pixmapRGBAConfig) || (!hasAlpha && !pixmapRGBConfig) ) {
+ const EGLint configAttribs[] = {
+ EGL_SURFACE_TYPE, EGL_PIXMAP_BIT,
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+ EGL_DEPTH_SIZE, 0,
+ hasAlpha ? EGL_BIND_TO_TEXTURE_RGBA : EGL_BIND_TO_TEXTURE_RGB, EGL_TRUE,
+ EGL_NONE
+ };
+
+ EGLint configCount = 0;
+ eglChooseConfig(eglContext->display(), configAttribs, 0, 256, &configCount);
+ if (configCount == 0) {
+ haveTFP = false;
+ qWarning("bindTextureFromNativePixmap() - Couldn't find a suitable config");
+ return 0;
+ }
+
+ EGLConfig *configList = new EGLConfig[configCount];
+ eglChooseConfig(eglContext->display(), configAttribs, configList, configCount, &configCount);
+ Q_ASSERT(configCount);
+
+ // Try to create a pixmap surface for each config until one works
+ for (int i = 0; i < configCount; ++i) {
+ pixmapSurface = eglCreatePixmapSurface(eglContext->display(), configList[i],
+ (EGLNativePixmapType) pixmapData->handle(),
+ pixmapAttribs);
+ if (pixmapSurface != EGL_NO_SURFACE) {
+ // Got one!
+ qDebug() << "Found an" << (hasAlpha ? "ARGB" : "RGB")
+ << "config (" << int(configList[i]) << ") to create a pixmap surface";
+ if (hasAlpha)
+ pixmapRGBAConfig = configList[i];
+ else
+ pixmapRGBConfig = configList[i];
+ pixmapData->gl_surface = (Qt::HANDLE)pixmapSurface;
+ break;
+ }
+ }
+ delete configList;
+
+ if ((hasAlpha && !pixmapRGBAConfig) || (!hasAlpha && !pixmapRGBConfig) ) {
+ qDebug("Couldn't create a pixmap surface with any of the provided configs");
+ haveTFP = false;
+ return 0;
+ }
+ }
+
+ if (pixmapSurface == EGL_NO_SURFACE) {
+ pixmapSurface = eglCreatePixmapSurface(eglContext->display(),
+ hasAlpha? pixmapRGBAConfig : pixmapRGBConfig,
+ (EGLNativePixmapType) pixmapData->handle(),
+ pixmapAttribs);
+ if (pixmapSurface == EGL_NO_SURFACE) {
+ qWarning("Failed to create a pixmap surface using config %d",
+ (int)(hasAlpha? pixmapRGBAConfig : pixmapRGBConfig));
+ haveTFP = false;
+ return 0;
+ }
+ pixmapData->gl_surface = (Qt::HANDLE)pixmapSurface;
+ }
+
+ // Make sure the cleanup hook gets called so we can delete the glx pixmap
+ pixmapData->is_cached = true;
+ Q_ASSERT(pixmapData->gl_surface);
+
+ GLuint textureId;
+ glGenTextures(1, &textureId);
+ glEnable(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, textureId);
+
+ // bind the egl pixmap surface to a texture
+ EGLBoolean success;
+ success = eglBindTexImage(eglContext->display(), pixmapSurface, EGL_BACK_BUFFER);
+ if (success == EGL_FALSE) {
+ qWarning() << "eglBindTexImage() failed:" << eglContext->errorString(eglGetError());
+ eglDestroySurface(eglContext->display(), pixmapSurface);
+ pixmapData->gl_surface = (Qt::HANDLE)EGL_NO_SURFACE;
+ haveTFP = false;
+ return 0;
+ }
+
+ QGLTexture *texture = new QGLTexture(q, textureId, GL_TEXTURE_2D, canInvert, true);
+ pixmapData->flags |= QX11PixmapData::InvertedWhenBoundToTexture;
+
+ // We assume the cost of bound pixmaps is zero
+ QGLTextureCache::instance()->insert(q, key, texture, 0);
+
+ glBindTexture(GL_TEXTURE_2D, textureId);
+ return texture;
}
-void QGLTexture::deleteBoundPixmap()
+void QGLContextPrivate::destroyGlSurfaceForPixmap(QPixmapData* pmd)
{
- //TODO
+ Q_ASSERT(pmd->classId() == QPixmapData::X11Class);
+ QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pmd);
+ if (pixmapData->gl_surface) {
+ EGLBoolean success;
+ success = eglDestroySurface(QEglContext::defaultDisplay(0), (EGLSurface)pixmapData->gl_surface);
+ if (success == EGL_FALSE) {
+ qWarning() << "destroyGlSurfaceForPixmap() - Error deleting surface: "
+ << QEglContext::errorString(eglGetError());
+ }
+ pixmapData->gl_surface = 0;
+ }
+}
+
+void QGLContextPrivate::unbindPixmapFromTexture(QPixmapData* pmd)
+{
+ Q_ASSERT(pmd->classId() == QPixmapData::X11Class);
+ QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pmd);
+ if (pixmapData->gl_surface) {
+ EGLBoolean success;
+ success = eglReleaseTexImage(QEglContext::defaultDisplay(0),
+ (EGLSurface)pixmapData->gl_surface,
+ EGL_BACK_BUFFER);
+ if (success == EGL_FALSE) {
+ qWarning() << "unbindPixmapFromTexture() - Unable to release bound texture: "
+ << QEglContext::errorString(eglGetError());
+ }
+ }
}
QT_END_NAMESPACE