diff options
Diffstat (limited to 'src/plugins/graphicssystems/meego/qmeegographicssystem.cpp')
-rw-r--r-- | src/plugins/graphicssystems/meego/qmeegographicssystem.cpp | 203 |
1 files changed, 203 insertions, 0 deletions
diff --git a/src/plugins/graphicssystems/meego/qmeegographicssystem.cpp b/src/plugins/graphicssystems/meego/qmeegographicssystem.cpp index 2a64d49..f8b228c 100644 --- a/src/plugins/graphicssystems/meego/qmeegographicssystem.cpp +++ b/src/plugins/graphicssystems/meego/qmeegographicssystem.cpp @@ -51,6 +51,7 @@ #include <private/qimage_p.h> #include <private/qeglproperties_p.h> #include <private/qeglcontext_p.h> +#include <private/qpixmap_x11_p.h> #include "qmeegopixmapdata.h" #include "qmeegographicssystem.h" @@ -58,6 +59,8 @@ bool QMeeGoGraphicsSystem::surfaceWasCreated = false; +QHash <Qt::HANDLE, QPixmap*> QMeeGoGraphicsSystem::liveTexturePixmaps; + QMeeGoGraphicsSystem::QMeeGoGraphicsSystem() { qDebug("Using the meego graphics system"); @@ -170,6 +173,22 @@ QPixmapData *QMeeGoGraphicsSystem::pixmapDataFromEGLSharedImage(Qt::HANDLE handl } } +QPixmapData *QMeeGoGraphicsSystem::pixmapDataFromEGLImage(Qt::HANDLE handle) +{ + if (QMeeGoGraphicsSystem::meeGoRunning()) { + QMeeGoPixmapData *pmd = new QMeeGoPixmapData; + pmd->fromEGLImage(handle); + + // FIXME Ok. This is a bit BAD BAD BAD. We're abusing here the fact that we KNOW + // that this function is used for the live pixmap... + pmd->texture()->options &= ~QGLContext::InvertedYBindOption; + return QMeeGoGraphicsSystem::wrapPixmapData(pmd); + } else { + qFatal("Can't create from EGL image when not running meego graphics system!"); + return NULL; + } +} + void QMeeGoGraphicsSystem::updateEGLSharedImagePixmap(QPixmap *pixmap) { QMeeGoPixmapData *pmd = (QMeeGoPixmapData *) pixmap->pixmapData(); @@ -188,6 +207,109 @@ QPixmapData *QMeeGoGraphicsSystem::pixmapDataWithGLTexture(int w, int h) return QMeeGoGraphicsSystem::wrapPixmapData(pmd); } +Qt::HANDLE QMeeGoGraphicsSystem::createLiveTexture(int w, int h, QImage::Format format) +{ + // No need to wrap the QPixmapData here. This QPixmap(Data) is a + // internal implementation and we don't migrate it between + // graphics system switching. + + // We use a bit ugly way of enforcing a color format on the X pixmap -- we create + // a local QImage and fromImage from there. This is quite redundant (extra overhead of creating + // the useless image only to delete it) but shouldn't be too bad for now... you're not expected + // to call createLiveTexture too often anyways. Would be great if QX11PixmapData had a way to + // force the X format upon creation or resize. + + QImage image(w, h, format); + QX11PixmapData *pmd = new QX11PixmapData(QPixmapData::PixmapType); + pmd->fromImage(image, Qt::NoOpaqueDetection); + QPixmap *p = new QPixmap(pmd); + + liveTexturePixmaps.insert(p->handle(), p); + return p->handle(); +} + +void QMeeGoGraphicsSystem::destroyLiveTexture(Qt::HANDLE h) +{ + if (liveTexturePixmaps.contains(h)) { + QPixmap *p = liveTexturePixmaps.value(h); + delete p; + liveTexturePixmaps.remove(h); + } else + qWarning("Trying to destroy live texture %ld which was not found!", h); +} + +bool QMeeGoGraphicsSystem::lockLiveTexture(Qt::HANDLE h) +{ + if (! liveTexturePixmaps.contains(h)) { + qWarning("Trying to lock live texture %ld which was not found!", h); + return false; + } + + EGLint attribs[] = { + EGL_MAP_PRESERVE_PIXELS_KHR, EGL_TRUE, + EGL_LOCK_USAGE_HINT_KHR, EGL_READ_SURFACE_BIT_KHR | EGL_WRITE_SURFACE_BIT_KHR, + EGL_NONE + }; + + QGLShareContextScope ctx(qt_gl_share_widget()->context()); + EGLSurface surface = getSurfaceForLiveTexturePixmap(liveTexturePixmaps.value(h)); + return QMeeGoExtensions::eglLockSurfaceKHR(QEgl::display(), surface, attribs); +} + +bool QMeeGoGraphicsSystem::unlockLiveTexture(Qt::HANDLE h) +{ + if (! liveTexturePixmaps.contains(h)) { + qWarning("Trying to lock live texture %ld which was not found!", h); + return false; + } + + QGLShareContextScope ctx(qt_gl_share_widget()->context()); + QMeeGoExtensions::ensureInitialized(); + + EGLSurface surface = getSurfaceForLiveTexturePixmap(liveTexturePixmaps.value(h)); + if (QMeeGoExtensions::eglUnlockSurfaceKHR(QEgl::display(), surface)) { + glFinish(); + return true; + } else { + return false; + } +} + +void QMeeGoGraphicsSystem::queryLiveTexture(Qt::HANDLE h, void **data, int *pitch) +{ + // FIXME Only allow this on locked surfaces + if (! liveTexturePixmaps.contains(h)) { + qWarning("Trying to query live texture %ld which was not found!", h); + return; + } + + QGLShareContextScope ctx(qt_gl_share_widget()->context()); + QMeeGoExtensions::ensureInitialized(); + + EGLSurface surface = getSurfaceForLiveTexturePixmap(liveTexturePixmaps.value(h)); + eglQuerySurface(QEgl::display(), surface, EGL_BITMAP_POINTER_KHR, (EGLint*) data); + eglQuerySurface(QEgl::display(), surface, EGL_BITMAP_PITCH_KHR, (EGLint*) pitch); +} + +Qt::HANDLE QMeeGoGraphicsSystem::liveTextureToEGLImage(Qt::HANDLE h) +{ + QGLShareContextScope ctx(qt_gl_share_widget()->context()); + QMeeGoExtensions::ensureInitialized(); + + EGLint attribs[] = { + EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, + EGL_NONE + }; + + EGLImageKHR eglImage = QEgl::eglCreateImageKHR(QEgl::display(), EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR, + (EGLClientBuffer) h, attribs); + + if (eglImage == EGL_NO_IMAGE_KHR) + qWarning("eglCreateImageKHR failed!"); + + return (Qt::HANDLE) eglImage; +} + bool QMeeGoGraphicsSystem::meeGoRunning() { if (! QApplicationPrivate::instance()) { @@ -204,6 +326,52 @@ bool QMeeGoGraphicsSystem::meeGoRunning() return (name == "meego"); } +void QMeeGoGraphicsSystem::destroySurfaceForLiveTexturePixmap(QPixmapData* pmd) +{ + Q_ASSERT(pmd->classId() == QPixmapData::X11Class); + QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pmd); + if (pixmapData->gl_surface) { + eglDestroySurface(QEgl::display(), (EGLSurface)pixmapData->gl_surface); + pixmapData->gl_surface = 0; + } +} + +EGLSurface QMeeGoGraphicsSystem::getSurfaceForLiveTexturePixmap(QPixmap *pixmap) +{ + // This code is a crative remix of the stuff that can be found in the + // Qt's TFP implementation in /src/opengl/qgl_x11egl.cpp ::bindiTextureFromNativePixmap + QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pixmap->data_ptr().data()); + Q_ASSERT(pixmapData->classId() == QPixmapData::X11Class); + bool hasAlpha = pixmapData->hasAlphaChannel(); + + if (pixmapData->gl_surface && + hasAlpha == (pixmapData->flags & QX11PixmapData::GlSurfaceCreatedWithAlpha)) + return pixmapData->gl_surface; + + // Check to see if the surface is still valid + if (pixmapData->gl_surface && + hasAlpha != ((pixmapData->flags & QX11PixmapData::GlSurfaceCreatedWithAlpha) > 0)) { + // Surface is invalid! + QMeeGoGraphicsSystem::destroySurfaceForLiveTexturePixmap(pixmapData); + } + + if (pixmapData->gl_surface == 0) { + EGLConfig config = QEgl::defaultConfig(QInternal::Pixmap, + QEgl::OpenGL, + hasAlpha ? QEgl::Translucent : QEgl::NoOptions); + + pixmapData->gl_surface = (void*)QEgl::createSurface(pixmap, config); + + if (hasAlpha) + pixmapData->flags = pixmapData->flags | QX11PixmapData::GlSurfaceCreatedWithAlpha; + + if (pixmapData->gl_surface == (void*)EGL_NO_SURFACE) + return NULL; + } + + return pixmapData->gl_surface; +} + /* C API */ int qt_meego_image_to_egl_shared_image(const QImage &image) @@ -216,6 +384,11 @@ QPixmapData* qt_meego_pixmapdata_from_egl_shared_image(Qt::HANDLE handle, const return QMeeGoGraphicsSystem::pixmapDataFromEGLSharedImage(handle, softImage); } +QPixmapData* qt_meego_pixmapdata_from_egl_image(Qt::HANDLE handle) +{ + return QMeeGoGraphicsSystem::pixmapDataFromEGLImage(handle); +} + QPixmapData* qt_meego_pixmapdata_with_gl_texture(int w, int h) { return QMeeGoGraphicsSystem::pixmapDataWithGLTexture(w, h); @@ -245,3 +418,33 @@ void qt_meego_update_egl_shared_image_pixmap(QPixmap *pixmap) { QMeeGoGraphicsSystem::updateEGLSharedImagePixmap(pixmap); } + +Qt::HANDLE qt_meego_live_texture_create(int w, int h, QImage::Format format) +{ + return QMeeGoGraphicsSystem::createLiveTexture(w, h, format); +} + +void qt_meego_live_texture_destroy(Qt::HANDLE h) +{ + QMeeGoGraphicsSystem::destroyLiveTexture(h); +} + +bool qt_meego_live_texture_lock(Qt::HANDLE h) +{ + return QMeeGoGraphicsSystem::lockLiveTexture(h); +} + +bool qt_meego_live_texture_unlock(Qt::HANDLE h) +{ + return QMeeGoGraphicsSystem::unlockLiveTexture(h); +} + +void qt_meego_live_texture_query(Qt::HANDLE h, void **data, int *pitch) +{ + return QMeeGoGraphicsSystem::queryLiveTexture(h, data, pitch); +} + +Qt::HANDLE qt_meego_live_texture_to_egl_image(Qt::HANDLE h) +{ + return QMeeGoGraphicsSystem::liveTextureToEGLImage(h); +} |