From: Jørgen Lind Date: Wed, 23 Mar 2011 15:57:11 +0000 (+0100) Subject: Lighthouse: Wayland: Added a xpixmap readback glcontext X-Git-Tag: qt-v5.0.0-alpha1~222^2^2~88 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=0b1786e7314c733cce8fc558df646ea9470ed2cf;p=profile%2Fivi%2Fqtwayland.git Lighthouse: Wayland: Added a xpixmap readback glcontext It uses a x11 pixmap to render all gl content into, then reads it back using glReadPixels. Then it sends it over the wire like any other shm surface. --- diff --git a/src/plugins/platforms/wayland/gl_integration/gl_integration.pri b/src/plugins/platforms/wayland/gl_integration/gl_integration.pri index 8a792a5..ed2b021 100644 --- a/src/plugins/platforms/wayland/gl_integration/gl_integration.pri +++ b/src/plugins/platforms/wayland/gl_integration/gl_integration.pri @@ -10,4 +10,8 @@ wayland_egl { include ($$PWD/wayland_egl/wayland_egl.pri) } +xpixmap_egl { + include ($$PWD/xpixmap_egl/xpixmap_egl.pri) +} + diff --git a/src/plugins/platforms/wayland/gl_integration/qwaylandglintegration.h b/src/plugins/platforms/wayland/gl_integration/qwaylandglintegration.h index a1f6b2c..52a663f 100644 --- a/src/plugins/platforms/wayland/gl_integration/qwaylandglintegration.h +++ b/src/plugins/platforms/wayland/gl_integration/qwaylandglintegration.h @@ -2,6 +2,7 @@ #define QWAYLANDGLINTEGRATION_H class QWaylandWindow; +class QWaylandDisplay; class QWidget; class QWaylandGLIntegration @@ -14,7 +15,7 @@ public: virtual QWaylandWindow *createEglWindow(QWidget *widget) = 0; - static QWaylandGLIntegration *createEglIntegration(struct wl_display *waylandDisplay); + static QWaylandGLIntegration *createEglIntegration(QWaylandDisplay *waylandDisplay); }; #endif // QWAYLANDGLINTEGRATION_H diff --git a/src/plugins/platforms/wayland/gl_integration/qwaylandglwindowsurface.cpp b/src/plugins/platforms/wayland/gl_integration/qwaylandglwindowsurface.cpp index ca9fb97..8c83128 100644 --- a/src/plugins/platforms/wayland/gl_integration/qwaylandglwindowsurface.cpp +++ b/src/plugins/platforms/wayland/gl_integration/qwaylandglwindowsurface.cpp @@ -175,7 +175,7 @@ void QWaylandGLWindowSurface::resize(const QSize &size) QWindowSurface::resize(size); window()->platformWindow()->glContext()->makeCurrent(); delete mPaintDevice; - mPaintDevice = new QGLFramebufferObject(size,QGLFramebufferObject::CombinedDepthStencil,GL_TEXTURE_2D,GL_RGBA); + mPaintDevice = new QGLFramebufferObject(size); } QT_END_NAMESPACE diff --git a/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandeglintegration.cpp b/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandeglintegration.cpp index eb46bc7..255fbfe 100644 --- a/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandeglintegration.cpp +++ b/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandeglintegration.cpp @@ -1,5 +1,7 @@ #include "qwaylandeglintegration.h" +#include "gl_integration/qwaylandglintegration.h" + #include "qwaylandeglwindow.h" QWaylandEglIntegration::QWaylandEglIntegration(struct wl_display *waylandDisplay) @@ -42,7 +44,7 @@ wl_egl_display * QWaylandEglIntegration::nativeDisplay() const return mNativeEglDisplay; } -QWaylandGLIntegration *QWaylandGLIntegration::createEglIntegration(wl_display *waylandDisplay) +QWaylandGLIntegration *QWaylandGLIntegration::createEglIntegration(QWaylandDisplay *waylandDisplay) { - return new QWaylandEglIntegration(waylandDisplay); + return new QWaylandEglIntegration(waylandDisplay->wl_display()); } diff --git a/src/plugins/platforms/wayland/gl_integration/xpixmap_egl/qwaylandxpixmapeglcontext.cpp b/src/plugins/platforms/wayland/gl_integration/xpixmap_egl/qwaylandxpixmapeglcontext.cpp new file mode 100644 index 0000000..e29ad97 --- /dev/null +++ b/src/plugins/platforms/wayland/gl_integration/xpixmap_egl/qwaylandxpixmapeglcontext.cpp @@ -0,0 +1,109 @@ +#include "qwaylandxpixmapeglcontext.h" + +#include "../../../eglconvenience/qeglconvenience.h" + +#include + +#include "qwaylandshmsurface.h" + +#include + +QXPixmapReadbackGLContext::QXPixmapReadbackGLContext(QWaylandXPixmapEglIntegration *eglIntegration, QWaylandXPixmapWindow *window) + : mEglIntegration(eglIntegration) + , mWindow(window) + , mBuffer(0) + , mPixmap(0) + , mConfig(q_configFromQPlatformWindowFormat(eglIntegration->eglDisplay(),window->widget()->platformWindowFormat(),true,EGL_PIXMAP_BIT)) + , mPixmapSurface(EGL_NO_SURFACE) +{ + QVector eglContextAttrs; + eglContextAttrs.append(EGL_CONTEXT_CLIENT_VERSION); + eglContextAttrs.append(2); + eglContextAttrs.append(EGL_NONE); + + mContext = eglCreateContext(eglIntegration->eglDisplay(),mConfig,0,eglContextAttrs.constData()); + + geometryChanged(); +} + +QXPixmapReadbackGLContext::~QXPixmapReadbackGLContext() +{ + eglDestroyContext(mEglIntegration->eglDisplay(),mContext); +} + +void QXPixmapReadbackGLContext::makeCurrent() +{ + QPlatformGLContext::makeCurrent(); + + while(mWindow->waitingForFrameSync()) { + mEglIntegration->waylandDisplay()->iterate(); + } + + eglMakeCurrent(mEglIntegration->eglDisplay(),mPixmapSurface,mPixmapSurface,mContext); +} + +void QXPixmapReadbackGLContext::doneCurrent() +{ + QPlatformGLContext::doneCurrent(); + eglMakeCurrent(mEglIntegration->eglDisplay(),EGL_NO_SURFACE,EGL_NO_SURFACE,EGL_NO_CONTEXT); +} + +void QXPixmapReadbackGLContext::swapBuffers() +{ + eglSwapBuffers(mEglIntegration->eglDisplay(),mPixmapSurface); + + if (QPlatformGLContext::currentContext() != this) { + makeCurrent(); + } + + QSize size = mWindow->geometry().size(); + + QImage img(size,QImage::Format_ARGB32); + const uchar *constBits = img.bits(); + void *pixels = const_cast(constBits); + + glReadPixels(0,0, size.width(), size.height(), GL_RGBA,GL_UNSIGNED_BYTE, pixels); + + img = img.mirrored(); + constBits = img.bits(); + + const uchar *constDstBits = mBuffer->image()->bits(); + uchar *dstBits = const_cast(constDstBits); + memcpy(dstBits,constBits,(img.width()*4) * img.height()); + + + mWindow->damage(QRegion(QRect(QPoint(0,0),size))); +} + +void * QXPixmapReadbackGLContext::getProcAddress(const QString &procName) +{ + return (void *) eglGetProcAddress(procName.toLatin1().data()); +} + +QPlatformWindowFormat QXPixmapReadbackGLContext::platformWindowFormat() const +{ + return qt_qPlatformWindowFormatFromConfig(mEglIntegration->eglDisplay(),mConfig); +} + +void QXPixmapReadbackGLContext::geometryChanged() +{ + while (mWindow->waitingForFrameSync()) + mEglIntegration->waylandDisplay()->iterate(); + + QSize size(mWindow->geometry().size()); + delete mBuffer; + if (mPixmap) + XFreePixmap(mEglIntegration->xDisplay(),mPixmap); + if (mPixmapSurface != EGL_NO_SURFACE) + eglDestroySurface(mEglIntegration->eglDisplay(),mPixmapSurface); + + mBuffer = new QWaylandShmBuffer(mEglIntegration->waylandDisplay(),size,QImage::Format_ARGB32); + mWindow->attach(mBuffer); + mPixmap = XCreatePixmap(mEglIntegration->xDisplay(),mEglIntegration->rootWindow(),size.width(),size.height(),mEglIntegration->depth()); + XSync(mEglIntegration->xDisplay(),False); + + mPixmapSurface = eglCreatePixmapSurface(mEglIntegration->eglDisplay(),mConfig,mPixmap,0); + if (mPixmapSurface == EGL_NO_SURFACE) { + qDebug() << "Could not make egl surface out of pixmap :("; + } +} diff --git a/src/plugins/platforms/wayland/gl_integration/xpixmap_egl/qwaylandxpixmapeglcontext.h b/src/plugins/platforms/wayland/gl_integration/xpixmap_egl/qwaylandxpixmapeglcontext.h new file mode 100644 index 0000000..e6c6e8d --- /dev/null +++ b/src/plugins/platforms/wayland/gl_integration/xpixmap_egl/qwaylandxpixmapeglcontext.h @@ -0,0 +1,39 @@ +#ifndef QXPIXMAPREADBACKGLCONTEXT_H +#define QXPIXMAPREADBACKGLCONTEXT_H + +#include +#include + +#include "qwaylandxpixmapeglintegration.h" +#include "qwaylandxpixmapwindow.h" + +class QWaylandShmBuffer; + +class QXPixmapReadbackGLContext : public QPlatformGLContext +{ +public: + QXPixmapReadbackGLContext(QWaylandXPixmapEglIntegration *eglIntegration, QWaylandXPixmapWindow *window); + ~QXPixmapReadbackGLContext(); + + void makeCurrent(); + void doneCurrent(); + void swapBuffers(); + void* getProcAddress(const QString& procName); + + virtual QPlatformWindowFormat platformWindowFormat() const; + + void geometryChanged(); + +private: + QWaylandXPixmapEglIntegration *mEglIntegration; + QWaylandXPixmapWindow *mWindow; + QWaylandShmBuffer *mBuffer; + + Pixmap mPixmap; + + EGLConfig mConfig; + EGLContext mContext; + EGLSurface mPixmapSurface; +}; + +#endif // QXPIXMAPREADBACKGLCONTEXT_H diff --git a/src/plugins/platforms/wayland/gl_integration/xpixmap_egl/qwaylandxpixmapeglintegration.cpp b/src/plugins/platforms/wayland/gl_integration/xpixmap_egl/qwaylandxpixmapeglintegration.cpp new file mode 100644 index 0000000..c9f244c --- /dev/null +++ b/src/plugins/platforms/wayland/gl_integration/xpixmap_egl/qwaylandxpixmapeglintegration.cpp @@ -0,0 +1,70 @@ +#include "qwaylandxpixmapeglintegration.h" + +#include + +#include "qwaylandxpixmapwindow.h" + +QWaylandXPixmapEglIntegration::QWaylandXPixmapEglIntegration(QWaylandDisplay *display) + : QWaylandGLIntegration() + , mWaylandDisplay(display) +{ + char *display_name = getenv("DISPLAY"); + mDisplay = XOpenDisplay(display_name); + mScreen = XDefaultScreen(mDisplay); + mRootWindow = XDefaultRootWindow(mDisplay); + XSync(mDisplay, False); +} + +QWaylandXPixmapEglIntegration::~QWaylandXPixmapEglIntegration() +{ + XCloseDisplay(mDisplay); +} + + +QWaylandGLIntegration *QWaylandGLIntegration::createEglIntegration(QWaylandDisplay *waylandDisplay) +{ + return new QWaylandXPixmapEglIntegration(waylandDisplay); +} + +void QWaylandXPixmapEglIntegration::initialize() +{ + eglBindAPI(EGL_OPENGL_ES_API); + mEglDisplay = eglGetDisplay(mDisplay); + EGLint major, minor; + EGLBoolean initialized = eglInitialize(mEglDisplay,&major,&minor); + if (initialized) { + qDebug() << "EGL initialized successfully" << major << "," << minor; + } else { + qDebug() << "EGL could not initialized. All EGL and GL operations will fail"; + } +} + +QWaylandWindow * QWaylandXPixmapEglIntegration::createEglWindow(QWidget *widget) +{ + return new QWaylandXPixmapWindow(widget,this); +} + +EGLDisplay QWaylandXPixmapEglIntegration::eglDisplay() +{ + return mEglDisplay; +} + +Window QWaylandXPixmapEglIntegration::rootWindow() const +{ + return mRootWindow; +} + +int QWaylandXPixmapEglIntegration::depth() const +{ + return XDefaultDepth(mDisplay,mScreen); +} + +Display * QWaylandXPixmapEglIntegration::xDisplay() const +{ + return mDisplay; +} + +QWaylandDisplay * QWaylandXPixmapEglIntegration::waylandDisplay() const +{ + return mWaylandDisplay; +} diff --git a/src/plugins/platforms/wayland/gl_integration/xpixmap_egl/qwaylandxpixmapeglintegration.h b/src/plugins/platforms/wayland/gl_integration/xpixmap_egl/qwaylandxpixmapeglintegration.h new file mode 100644 index 0000000..534494b --- /dev/null +++ b/src/plugins/platforms/wayland/gl_integration/xpixmap_egl/qwaylandxpixmapeglintegration.h @@ -0,0 +1,42 @@ +#ifndef QWAYLANDXPIXMAPEGLINTEGRATION_H +#define QWAYLANDXPIXMAPEGLINTEGRATION_H + +#include "gl_integration/qwaylandglintegration.h" + +#include +#include +#include +#include +#include + +#include + +#include +//#include (this); + that->mContext = new QXPixmapReadbackGLContext(mEglIntegration,that); + } + return mContext; +} + +void QWaylandXPixmapWindow::newSurfaceCreated() +{ +} + +void QWaylandXPixmapWindow::setGeometry(const QRect &rect) +{ + QPlatformWindow::setGeometry(rect); + + if (mContext) + mContext->geometryChanged(); +} + diff --git a/src/plugins/platforms/wayland/gl_integration/xpixmap_egl/qwaylandxpixmapwindow.h b/src/plugins/platforms/wayland/gl_integration/xpixmap_egl/qwaylandxpixmapwindow.h new file mode 100644 index 0000000..919e29d --- /dev/null +++ b/src/plugins/platforms/wayland/gl_integration/xpixmap_egl/qwaylandxpixmapwindow.h @@ -0,0 +1,27 @@ +#ifndef QWAYLANDXPIXMAPWINDOW_H +#define QWAYLANDXPIXMAPWINDOW_H + +#include "qwaylandshmwindow.h" +#include "qwaylandxpixmapeglintegration.h" + +class QXPixmapReadbackGLContext; + +class QWaylandXPixmapWindow : public QWaylandShmWindow +{ +public: + QWaylandXPixmapWindow(QWidget *window, QWaylandXPixmapEglIntegration *eglIntegration); + + WindowType windowType() const; + + QPlatformGLContext *glContext() const; + + void setGeometry(const QRect &rect); +protected: + void newSurfaceCreated(); + +private: + QWaylandXPixmapEglIntegration *mEglIntegration; + QXPixmapReadbackGLContext *mContext; +}; + +#endif // QWAYLANDXPIXMAPWINDOW_H diff --git a/src/plugins/platforms/wayland/gl_integration/xpixmap_egl/xpixmap_egl.pri b/src/plugins/platforms/wayland/gl_integration/xpixmap_egl/xpixmap_egl.pri new file mode 100644 index 0000000..87e2d28 --- /dev/null +++ b/src/plugins/platforms/wayland/gl_integration/xpixmap_egl/xpixmap_egl.pri @@ -0,0 +1,14 @@ + +LIBS += -lX11 -lXext -lEGL + +HEADERS += \ + gl_integration/xpixmap_egl/qwaylandxpixmapeglintegration.h \ + gl_integration/xpixmap_egl/qwaylandxpixmapwindow.h \ + gl_integration/xpixmap_egl/qwaylandxpixmapeglcontext.h \ + $$PWD/../../../eglconvenience/qeglconvenience.h + +SOURCES += \ + gl_integration/xpixmap_egl/qwaylandxpixmapeglintegration.cpp \ + gl_integration/xpixmap_egl/qwaylandxpixmapwindow.cpp \ + gl_integration/xpixmap_egl/qwaylandxpixmapeglcontext.cpp \ + $$PWD/../../../eglconvenience/qeglconvenience.cpp diff --git a/src/plugins/platforms/wayland/qwaylanddisplay.cpp b/src/plugins/platforms/wayland/qwaylanddisplay.cpp index eebc9de..22e38eb 100644 --- a/src/plugins/platforms/wayland/qwaylanddisplay.cpp +++ b/src/plugins/platforms/wayland/qwaylanddisplay.cpp @@ -190,7 +190,7 @@ QWaylandDisplay::QWaylandDisplay(void) QWaylandDisplay::displayHandleGlobal, this); #ifdef QT_WAYLAND_GL_SUPPORT - mEglIntegration = QWaylandGLIntegration::createEglIntegration(mDisplay); + mEglIntegration = QWaylandGLIntegration::createEglIntegration(this); #endif readEvents(); diff --git a/src/plugins/platforms/wayland/qwaylanddisplay.h b/src/plugins/platforms/wayland/qwaylanddisplay.h index 535dcd6..fc26ad2 100644 --- a/src/plugins/platforms/wayland/qwaylanddisplay.h +++ b/src/plugins/platforms/wayland/qwaylanddisplay.h @@ -81,6 +81,7 @@ public: void iterate(); + struct wl_display *wl_display() const { return mDisplay; } public slots: void readEvents(void); void flushRequests(void); diff --git a/src/plugins/platforms/wayland/qwaylandshmsurface.h b/src/plugins/platforms/wayland/qwaylandshmsurface.h index 02b324a..b29ceaf 100644 --- a/src/plugins/platforms/wayland/qwaylandshmsurface.h +++ b/src/plugins/platforms/wayland/qwaylandshmsurface.h @@ -74,11 +74,8 @@ public: void beginPaint(const QRegion &); private: - static void frameCallback(void *data, uint32_t time);\ - QWaylandShmBuffer *mBuffer; QWaylandDisplay *mDisplay; - bool mWaitingForFrameSync; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/wayland/qwaylandshmwindow.cpp b/src/plugins/platforms/wayland/qwaylandshmwindow.cpp index d7c44a4..2808ed6 100644 --- a/src/plugins/platforms/wayland/qwaylandshmwindow.cpp +++ b/src/plugins/platforms/wayland/qwaylandshmwindow.cpp @@ -43,6 +43,8 @@ #include "qwaylandbuffer.h" +#include + QWaylandShmWindow::QWaylandShmWindow(QWidget *widget) : QWaylandWindow(widget) , mBuffer(0) diff --git a/src/plugins/platforms/wayland/qwaylandshmwindow.h b/src/plugins/platforms/wayland/qwaylandshmwindow.h index 669533c..3876c52 100644 --- a/src/plugins/platforms/wayland/qwaylandshmwindow.h +++ b/src/plugins/platforms/wayland/qwaylandshmwindow.h @@ -43,6 +43,7 @@ #define QWAYLANDSHMWINDOW_H #include "qwaylandwindow.h" +#include class QWaylandShmWindow : public QWaylandWindow { diff --git a/src/plugins/platforms/wayland/wayland.pro b/src/plugins/platforms/wayland/wayland.pro index b44857b..f2d9d6b 100644 --- a/src/plugins/platforms/wayland/wayland.pro +++ b/src/plugins/platforms/wayland/wayland.pro @@ -36,6 +36,7 @@ contains(QT_CONFIG, opengles2) { QT += opengl CONFIG += wayland_egl +# CONFIG += xpixmap_egl include ($$PWD/gl_integration/gl_integration.pri) }