summaryrefslogtreecommitdiffstats
path: root/src/opengl
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@nokia.com>2010-04-01 21:07:37 (GMT)
committerThiago Macieira <thiago.macieira@nokia.com>2010-04-01 21:07:37 (GMT)
commit23eb677daea8e084fcaa1256f1a9433e324b1474 (patch)
treea21225293db6881174814290ad7298120c4a078b /src/opengl
parent1f327a1de8db245d0b28e7dfdc5bca1af0b56782 (diff)
parent37e8fd4e09c1221efde3e67e6acd5cfbb35686fd (diff)
downloadQt-23eb677daea8e084fcaa1256f1a9433e324b1474.zip
Qt-23eb677daea8e084fcaa1256f1a9433e324b1474.tar.gz
Qt-23eb677daea8e084fcaa1256f1a9433e324b1474.tar.bz2
Merge remote branch 'origin/4.7' into HEAD
Conflicts: examples/declarative/proxywidgets/proxywidgets.pro examples/declarative/widgets/mywidgets.pro examples/declarative/widgets/widgets.pro
Diffstat (limited to 'src/opengl')
-rw-r--r--src/opengl/opengl.pro1
-rw-r--r--src/opengl/qgl.cpp2
-rw-r--r--src/opengl/qgl_egl_p.h1
-rw-r--r--src/opengl/qgl_p.h2
-rw-r--r--src/opengl/qgl_x11.cpp6
-rw-r--r--src/opengl/qgl_x11egl.cpp147
-rw-r--r--src/opengl/qglextensions.cpp11
-rw-r--r--src/opengl/qglextensions_p.h36
8 files changed, 164 insertions, 42 deletions
diff --git a/src/opengl/opengl.pro b/src/opengl/opengl.pro
index ff42a49..9473343 100644
--- a/src/opengl/opengl.pro
+++ b/src/opengl/opengl.pro
@@ -116,6 +116,7 @@ mac {
LIBS_PRIVATE += -framework AppKit -framework Carbon
}
win32:!wince*: {
+ DEFINES += QT_NO_EGL
SOURCES += qgl_win.cpp \
qglpixelbuffer_win.cpp
}
diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp
index 7aba25a..e56b149 100644
--- a/src/opengl/qgl.cpp
+++ b/src/opengl/qgl.cpp
@@ -2444,7 +2444,7 @@ QGLTexture *QGLContextPrivate::bindTexture(const QPixmap &pixmap, GLenum target,
if (pd->classId() == QPixmapData::X11Class && pd->pixelType() == QPixmapData::PixmapType
&& xinfo && xinfo->screen() == pixmap.x11Info().screen())
{
- texture = bindTextureFromNativePixmap(pd, key, options);
+ texture = bindTextureFromNativePixmap(const_cast<QPixmap*>(&pixmap), key, options);
if (texture) {
texture->options |= QGLContext::MemoryManagedBindOption;
texture->boundPixmap = pd;
diff --git a/src/opengl/qgl_egl_p.h b/src/opengl/qgl_egl_p.h
index 43793cd..85d7f32 100644
--- a/src/opengl/qgl_egl_p.h
+++ b/src/opengl/qgl_egl_p.h
@@ -53,6 +53,7 @@
// We mean it.
//
+#include <QtGui/private/qegl_p.h>
#include <QtGui/private/qeglcontext_p.h>
#include <QtGui/private/qeglproperties_p.h>
diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h
index dc1e26e..1f28b08 100644
--- a/src/opengl/qgl_p.h
+++ b/src/opengl/qgl_p.h
@@ -361,7 +361,7 @@ public:
quint32 gpm;
int screen;
QHash<QPixmapData*, QPixmap> boundPixmaps;
- QGLTexture *bindTextureFromNativePixmap(QPixmapData*, const qint64 key,
+ QGLTexture *bindTextureFromNativePixmap(QPixmap*, const qint64 key,
QGLContext::BindOptions options);
static void destroyGlSurfaceForPixmap(QPixmapData*);
static void unbindPixmapFromTexture(QPixmapData*);
diff --git a/src/opengl/qgl_x11.cpp b/src/opengl/qgl_x11.cpp
index 4fa1467..e1a202f 100644
--- a/src/opengl/qgl_x11.cpp
+++ b/src/opengl/qgl_x11.cpp
@@ -1671,7 +1671,7 @@ static bool qt_resolveTextureFromPixmap(QPaintDevice *paintDevice)
#endif //defined(GLX_VERSION_1_3) && !defined(Q_OS_HPUX)
-QGLTexture *QGLContextPrivate::bindTextureFromNativePixmap(QPixmapData *pmd, const qint64 key,
+QGLTexture *QGLContextPrivate::bindTextureFromNativePixmap(QPixmap *pixmap, const qint64 key,
QGLContext::BindOptions options)
{
#if !defined(GLX_VERSION_1_3) || defined(Q_OS_HPUX)
@@ -1679,12 +1679,12 @@ QGLTexture *QGLContextPrivate::bindTextureFromNativePixmap(QPixmapData *pmd, con
#else
Q_Q(QGLContext);
- Q_ASSERT(pmd->classId() == QPixmapData::X11Class);
+ QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pixmap->data_ptr().data());
+ Q_ASSERT(pixmapData->classId() == QPixmapData::X11Class);
if (!qt_resolveTextureFromPixmap(paintDevice))
return 0;
- 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)
diff --git a/src/opengl/qgl_x11egl.cpp b/src/opengl/qgl_x11egl.cpp
index 0954e69..af0100b 100644
--- a/src/opengl/qgl_x11egl.cpp
+++ b/src/opengl/qgl_x11egl.cpp
@@ -354,7 +354,7 @@ void QGLWidgetPrivate::recreateEglSurface(bool force)
}
-QGLTexture *QGLContextPrivate::bindTextureFromNativePixmap(QPixmapData* pd, const qint64 key,
+QGLTexture *QGLContextPrivate::bindTextureFromNativePixmap(QPixmap *pixmap, const qint64 key,
QGLContext::BindOptions options)
{
Q_Q(QGLContext);
@@ -363,10 +363,33 @@ QGLTexture *QGLContextPrivate::bindTextureFromNativePixmap(QPixmapData* pd, cons
if (!(options & QGLContext::CanFlipNativePixmapBindOption))
return 0;
- Q_ASSERT(pd->classId() == QPixmapData::X11Class);
static bool checkedForTFP = false;
static bool haveTFP = false;
+ static bool checkedForEglImageTFP = false;
+ static bool haveEglImageTFP = false;
+
+
+ if (!checkedForEglImageTFP) {
+ checkedForEglImageTFP = true;
+
+ // We need to be able to create an EGLImage from a native pixmap, which was split
+ // into a seperate EGL extension, EGL_KHR_image_pixmap. It is possible to have
+ // eglCreateImageKHR & eglDestroyImageKHR without support for pixmaps, so we must
+ // check we have the EGLImage from pixmap functionality.
+ if (QEgl::hasExtension("EGL_KHR_image") || QEgl::hasExtension("EGL_KHR_image_pixmap")) {
+ Q_ASSERT(eglCreateImageKHR);
+ Q_ASSERT(eglDestroyImageKHR);
+
+ // Being able to create an EGLImage from a native pixmap is also pretty useless
+ // without the ability to bind that EGLImage as a texture, which is provided by
+ // the GL_OES_EGL_image extension, which we try to resolve here:
+ haveEglImageTFP = qt_resolve_eglimage_gl_extensions(q);
+
+ if (haveEglImageTFP)
+ qDebug("Found EGL_KHR_image_pixmap & GL_OES_EGL_image extensions (preferred method)!");
+ }
+ }
if (!checkedForTFP) {
// Check for texture_from_pixmap egl extension
@@ -379,61 +402,111 @@ QGLTexture *QGLContextPrivate::bindTextureFromNativePixmap(QPixmapData* pd, cons
}
}
- if (!haveTFP)
+ if (!haveTFP && !haveEglImageTFP)
return 0;
- QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pd);
+ QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pixmap->data_ptr().data());
+ Q_ASSERT(pixmapData->classId() == QPixmapData::X11Class);
bool hasAlpha = pixmapData->hasAlphaChannel();
+ bool pixmapHasValidSurface = false;
+ bool textureIsBound = false;
+ GLuint textureId;
+ glGenTextures(1, &textureId);
+ glBindTexture(GL_TEXTURE_2D, textureId);
- // Check to see if the surface is still valid
- if (pixmapData->gl_surface &&
- hasAlpha != (pixmapData->flags & QX11PixmapData::GlSurfaceCreatedWithAlpha))
+ if (haveTFP && pixmapData->gl_surface &&
+ hasAlpha == (pixmapData->flags & QX11PixmapData::GlSurfaceCreatedWithAlpha))
{
- // Surface is invalid!
- destroyGlSurfaceForPixmap(pixmapData);
+ pixmapHasValidSurface = true;
+ }
+
+ // If we already have a valid EGL surface for the pixmap, we should use it
+ if (pixmapHasValidSurface) {
+ EGLBoolean success;
+ success = eglBindTexImage(QEgl::display(), (EGLSurface)pixmapData->gl_surface, EGL_BACK_BUFFER);
+ if (success == EGL_FALSE) {
+ qWarning() << "eglBindTexImage() failed:" << QEgl::errorString();
+ eglDestroySurface(QEgl::display(), (EGLSurface)pixmapData->gl_surface);
+ pixmapData->gl_surface = (void*)EGL_NO_SURFACE;
+ } else
+ textureIsBound = true;
}
- if (pixmapData->gl_surface == 0) {
- EGLConfig config = QEgl::defaultConfig(QInternal::Pixmap,
- QEgl::OpenGL,
- hasAlpha ? QEgl::Translucent : QEgl::NoOptions);
+ // If the pixmap doesn't already have a valid surface, try binding it via EGLImage
+ // first, as going through EGLImage should be faster and better supported:
+ if (!textureIsBound && haveEglImageTFP) {
+ Q_ASSERT(eglCreateImageKHR);
- QPixmap tmpPixmap(pixmapData); //###
- pixmapData->gl_surface = (void*)QEgl::createSurface(&tmpPixmap, config);
- if (pixmapData->gl_surface == (void*)EGL_NO_SURFACE) {
- haveTFP = false;
- return 0;
- }
+ EGLImageKHR eglImage;
+
+ EGLint attribs[] = {
+ EGL_IMAGE_PRESERVED_KHR, EGL_TRUE,
+ EGL_NONE
+ };
+ eglImage = eglCreateImageKHR(QEgl::display(), EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR,
+ (EGLClientBuffer)QEgl::nativePixmap(pixmap), attribs);
+
+ QGLContext* ctx = q;
+ glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, eglImage);
+
+ GLint err = glGetError();
+ if (err == GL_NO_ERROR)
+ textureIsBound = true;
+
+ // Once the egl image is bound, the texture becomes a new sibling image and we can safely
+ // destroy the EGLImage we created for the pixmap:
+ if (eglImage != EGL_NO_IMAGE_KHR)
+ eglDestroyImageKHR(QEgl::display(), eglImage);
}
- Q_ASSERT(pixmapData->gl_surface);
+ if (!textureIsBound && haveTFP) {
+ // Check to see if the surface is still valid
+ if (pixmapData->gl_surface &&
+ hasAlpha != (pixmapData->flags & QX11PixmapData::GlSurfaceCreatedWithAlpha))
+ {
+ // Surface is invalid!
+ destroyGlSurfaceForPixmap(pixmapData);
+ }
- GLuint textureId;
- glGenTextures(1, &textureId);
- glBindTexture(GL_TEXTURE_2D, textureId);
+ if (pixmapData->gl_surface == 0) {
+ EGLConfig config = QEgl::defaultConfig(QInternal::Pixmap,
+ QEgl::OpenGL,
+ hasAlpha ? QEgl::Translucent : QEgl::NoOptions);
- // bind the egl pixmap surface to a texture
- EGLBoolean success;
- success = eglBindTexImage(eglContext->display(), (EGLSurface)pixmapData->gl_surface, EGL_BACK_BUFFER);
- if (success == EGL_FALSE) {
- qWarning() << "eglBindTexImage() failed:" << QEgl::errorString();
- eglDestroySurface(eglContext->display(), (EGLSurface)pixmapData->gl_surface);
- pixmapData->gl_surface = (void*)EGL_NO_SURFACE;
- haveTFP = false;
- return 0;
+ pixmapData->gl_surface = (void*)QEgl::createSurface(pixmap, config);
+ if (pixmapData->gl_surface == (void*)EGL_NO_SURFACE)
+ return false;
+ }
+
+ EGLBoolean success;
+ success = eglBindTexImage(QEgl::display(), (EGLSurface)pixmapData->gl_surface, EGL_BACK_BUFFER);
+ if (success == EGL_FALSE) {
+ qWarning() << "eglBindTexImage() failed:" << QEgl::errorString();
+ eglDestroySurface(QEgl::display(), (EGLSurface)pixmapData->gl_surface);
+ pixmapData->gl_surface = (void*)EGL_NO_SURFACE;
+ haveTFP = false; // If TFP isn't working, disable it's use
+ } else
+ textureIsBound = true;
}
- QGLTexture *texture = new QGLTexture(q, textureId, GL_TEXTURE_2D, options);
- pixmapData->flags |= QX11PixmapData::InvertedWhenBoundToTexture;
+ QGLTexture *texture = 0;
- // We assume the cost of bound pixmaps is zero
- QGLTextureCache::instance()->insert(q, key, texture, 0);
+ if (textureIsBound) {
+ texture = new QGLTexture(q, textureId, GL_TEXTURE_2D, options);
+ 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);
+ } else
+ glDeleteTextures(1, &textureId);
- glBindTexture(GL_TEXTURE_2D, textureId);
return texture;
}
+
void QGLContextPrivate::destroyGlSurfaceForPixmap(QPixmapData* pmd)
{
Q_ASSERT(pmd->classId() == QPixmapData::X11Class);
diff --git a/src/opengl/qglextensions.cpp b/src/opengl/qglextensions.cpp
index 02d5501..ef3c4cd 100644
--- a/src/opengl/qglextensions.cpp
+++ b/src/opengl/qglextensions.cpp
@@ -222,6 +222,17 @@ bool qt_resolve_buffer_extensions(QGLContext *ctx)
#endif
}
+#ifndef QT_NO_EGL
+bool qt_resolve_eglimage_gl_extensions(QGLContext *ctx)
+{
+ if (glEGLImageTargetTexture2DOES || glEGLImageTargetRenderbufferStorageOES)
+ return true;
+ glEGLImageTargetTexture2DOES = (_glEGLImageTargetTexture2DOES) ctx->getProcAddress(QLatin1String("glEGLImageTargetTexture2DOES"));
+ glEGLImageTargetRenderbufferStorageOES = (_glEGLImageTargetRenderbufferStorageOES) ctx->getProcAddress(QLatin1String("glEGLImageTargetRenderbufferStorageOES"));
+ return glEGLImageTargetTexture2DOES && glEGLImageTargetRenderbufferStorageOES;
+}
+#endif
+
bool qt_resolve_glsl_extensions(QGLContext *ctx)
{
// Geometry shaders are optional...
diff --git a/src/opengl/qglextensions_p.h b/src/opengl/qglextensions_p.h
index f6926f3..7597b33 100644
--- a/src/opengl/qglextensions_p.h
+++ b/src/opengl/qglextensions_p.h
@@ -68,6 +68,11 @@
# define APIENTRYP *
#endif
+#ifndef QT_NO_EGL
+// Needed for EGLImageKHR definition:
+#include <QtGui/private/qegl_p.h>
+#endif
+
#include <QtCore/qglobal.h>
#ifndef GL_ARB_vertex_buffer_object
@@ -210,6 +215,14 @@ typedef void (APIENTRY *_glFramebufferTextureFaceEXT)(GLenum target, GLenum atta
typedef void (APIENTRY *_glCompressedTexImage2DARB) (GLenum, GLint, GLenum, GLsizei,
GLsizei, GLint, GLsizei, const GLvoid *);
+#ifndef QT_NO_EGL
+// OES_EGL_image
+// Note: We define these to take EGLImage whereas spec says they take a new GLeglImageOES
+// type, which the EGL image should be cast to.
+typedef void (APIENTRY *_glEGLImageTargetTexture2DOES) (GLenum, EGLImageKHR);
+typedef void (APIENTRY *_glEGLImageTargetRenderbufferStorageOES) (GLenum, EGLImageKHR);
+#endif
+
QT_BEGIN_NAMESPACE
struct QGLExtensionFuncs
@@ -327,6 +340,12 @@ struct QGLExtensionFuncs
// Texture compression
qt_glCompressedTexImage2DARB = 0;
#endif
+
+#ifndef QT_NO_EGL
+ // OES_EGL_image
+ qt_glEGLImageTargetTexture2DOES = 0;
+ qt_glEGLImageTargetRenderbufferStorageOES = 0;
+#endif
}
@@ -447,6 +466,13 @@ struct QGLExtensionFuncs
// Texture compression
_glCompressedTexImage2DARB qt_glCompressedTexImage2DARB;
#endif
+
+#ifndef QT_NO_EGL
+ // OES_EGL_image
+ _glEGLImageTargetTexture2DOES qt_glEGLImageTargetTexture2DOES;
+ _glEGLImageTargetRenderbufferStorageOES qt_glEGLImageTargetRenderbufferStorageOES;
+#endif
+
};
@@ -839,6 +865,12 @@ struct QGLExtensionFuncs
#define glCompressedTexImage2D QGLContextPrivate::extensionFuncs(ctx).qt_glCompressedTexImage2DARB
#endif
+#ifndef QT_NO_EGL
+// OES_EGL_image
+#define glEGLImageTargetTexture2DOES QGLContextPrivate::extensionFuncs(ctx).qt_glEGLImageTargetTexture2DOES
+#define glEGLImageTargetRenderbufferStorageOES QGLContextPrivate::extensionFuncs(ctx).qt_glEGLImageTargetRenderbufferStorageOES
+#endif
+
extern bool qt_resolve_framebufferobject_extensions(QGLContext *ctx);
bool qt_resolve_buffer_extensions(QGLContext *ctx);
@@ -849,6 +881,10 @@ bool qt_resolve_frag_program_extensions(QGLContext *ctx);
bool qt_resolve_glsl_extensions(QGLContext *ctx);
+#ifndef QT_NO_EGL
+bool qt_resolve_eglimage_gl_extensions(QGLContext *ctx);
+#endif
+
QT_END_NAMESPACE
#endif // QGL_EXTENSIONS_P_H