diff options
author | Jesse Barnes <jbarnes@virtuousgeek.org> | 2010-10-22 17:31:03 (GMT) |
---|---|---|
committer | Jørgen Lind <jorgen.lind@nokia.com> | 2011-01-25 17:56:26 (GMT) |
commit | 506e3535c85de2b41e0d31bbcd3b726ce8adbeca (patch) | |
tree | 7845a55d113fdfcc2e8607d070ef92a783ef2721 /src/plugins/platforms | |
parent | 229d9d36c3ba3f4149d050a6942886b181a90db7 (diff) | |
download | Qt-506e3535c85de2b41e0d31bbcd3b726ce8adbeca.zip Qt-506e3535c85de2b41e0d31bbcd3b726ce8adbeca.tar.gz Qt-506e3535c85de2b41e0d31bbcd3b726ce8adbeca.tar.bz2 |
Wayland: add GL drawing support
Works with analogclock, draws upside down, fails to resize, and doesn't
show GL widget with hello_es2.
Diffstat (limited to 'src/plugins/platforms')
4 files changed, 167 insertions, 32 deletions
diff --git a/src/plugins/platforms/wayland/qwaylandintegration.cpp b/src/plugins/platforms/wayland/qwaylandintegration.cpp index 248158d..c433983 100644 --- a/src/plugins/platforms/wayland/qwaylandintegration.cpp +++ b/src/plugins/platforms/wayland/qwaylandintegration.cpp @@ -3,6 +3,7 @@ #include <QImageReader> #include <QWindowSystemInterface> #include <QPlatformCursor> +#include <QPaintEngine> #include <QtGui/QPlatformGLContext> #include <QtGui/QPlatformWindowFormat> @@ -10,6 +11,9 @@ #include <QtGui/private/qpixmap_raster_p.h> #include <QtGui/QPlatformWindow> +#include <private/qwindowsurface_gl_p.h> +#include <private/qpixmapdata_gl_p.h> + #include "qwaylandintegration.h" #include "qwaylandwindowsurface.h" @@ -405,9 +409,10 @@ QWaylandDisplay::~QWaylandDisplay(void) wl_display_destroy(mDisplay); } -QWaylandIntegration::QWaylandIntegration() +QWaylandIntegration::QWaylandIntegration(bool useOpenGL) : mFontDb(new QFontconfigDatabase()) , mDisplay(new QWaylandDisplay()) + , mUseOpenGL(useOpenGL) { } @@ -419,6 +424,8 @@ QWaylandIntegration::screens() const QPixmapData *QWaylandIntegration::createPixmapData(QPixmapData::PixelType type) const { + if (mUseOpenGL) + return new QGLPixmapData(type); return new QRasterPixmapData(type); } @@ -426,6 +433,7 @@ QWaylandWindow::QWaylandWindow(QWidget *window, QWaylandDisplay *display) : QPlatformWindow(window) , mSurface(0) , mDisplay(display) + , mGLContext(0) { static WId id = 1; @@ -434,6 +442,8 @@ QWaylandWindow::QWaylandWindow(QWidget *window, QWaylandDisplay *display) QWaylandWindow::~QWaylandWindow() { + if (mGLContext) + delete mGLContext; } WId QWaylandWindow::winId() const @@ -508,6 +518,7 @@ QWaylandGLContext::QWaylandGLContext(QWaylandDisplay *wd, const QPlatformWindowF eglDisplay = mDisplay->eglDisplay(); mContext = eglCreateContext(eglDisplay, NULL, EGL_NO_CONTEXT, contextAttribs); + eglMakeCurrent(eglDisplay, NULL, NULL, mContext); } QWaylandGLContext::~QWaylandGLContext() @@ -518,10 +529,12 @@ QWaylandGLContext::~QWaylandGLContext() void QWaylandGLContext::makeCurrent() { + eglMakeCurrent(mDisplay->eglDisplay(), 0, 0, mContext); } void QWaylandGLContext::doneCurrent() { + eglMakeCurrent(mDisplay->eglDisplay(), 0, 0, mContext); } void QWaylandGLContext::swapBuffers() @@ -554,6 +567,8 @@ QWindowSurface *QWaylandIntegration::createWindowSurface(QWidget *widget, WId wi Q_UNUSED(winId); Q_UNUSED(winId); + if (mUseOpenGL) + return new QWaylandDrmWindowSurface(widget, mDisplay); return new QWaylandShmWindowSurface(widget, mDisplay); } diff --git a/src/plugins/platforms/wayland/qwaylandintegration.h b/src/plugins/platforms/wayland/qwaylandintegration.h index 6267e9b..70fb538 100644 --- a/src/plugins/platforms/wayland/qwaylandintegration.h +++ b/src/plugins/platforms/wayland/qwaylandintegration.h @@ -46,6 +46,7 @@ #include <QObject> #include <QtGui/QPlatformIntegration> #include <QtGui/QPlatformScreen> +#include "qgl.h" #include <wayland-client.h> #include "qwaylandinputdevice.h" @@ -155,6 +156,7 @@ public: WId winId() const; QPlatformGLContext *glContext() const; void attach(QWaylandBuffer *buffer); + QWaylandBuffer *getBuffer(void) { return mBuffer; } private: struct wl_surface *mSurface; @@ -168,7 +170,7 @@ private: class QWaylandIntegration : public QPlatformIntegration { public: - QWaylandIntegration(); + QWaylandIntegration(bool useOpenGL = false); QPixmapData *createPixmapData(QPixmapData::PixelType type) const; QPlatformWindow *createPlatformWindow(QWidget *widget, WId winId) const; @@ -181,6 +183,7 @@ public: private: QPlatformFontDatabase *mFontDb; QWaylandDisplay *mDisplay; + bool mUseOpenGL; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/wayland/qwaylandwindowsurface.cpp b/src/plugins/platforms/wayland/qwaylandwindowsurface.cpp index 0954bc5..78900ba 100644 --- a/src/plugins/platforms/wayland/qwaylandwindowsurface.cpp +++ b/src/plugins/platforms/wayland/qwaylandwindowsurface.cpp @@ -39,10 +39,18 @@ ** ****************************************************************************/ -#include "qwaylandintegration.h" -#include "qwaylandwindowsurface.h" +#define GL_GLEXT_PROTOTYPES +#include <GLES2/gl2.h> +#include <GLES2/gl2ext.h> + +#include <QGLFramebufferObject> #include <QtCore/qdebug.h> #include <QtGui/private/qapplication_p.h> +#include <QtOpenGL/private/qgl_p.h> +#include <QtOpenGL/private/qglpaintdevice_p.h> + +#include "qwaylandintegration.h" +#include "qwaylandwindowsurface.h" #include <wayland-client.h> #include <unistd.h> @@ -50,15 +58,6 @@ #include <errno.h> #include <sys/mman.h> -#define GL_GLEXT_PROTOTYPES -#define EGL_EGLEXT_PROTOTYPES -#define MESA_EGL_NO_X11_HEADERS - -#include <EGL/egl.h> -#include <EGL/eglext.h> -#include <GLES2/gl2.h> -#include <GLES2/gl2ext.h> - QT_BEGIN_NAMESPACE QWaylandShmBuffer::QWaylandShmBuffer(QWaylandDisplay *display, @@ -147,35 +146,77 @@ void QWaylandShmWindowSurface::resize(const QSize &size) ww->attach(mBuffer); } - -class QWaylandDrmBuffer : public QWaylandBuffer { +class QWaylandPaintDevice : public QGLPaintDevice +{ public: - QWaylandDrmBuffer(QWaylandDisplay *display, - const QSize &size, QImage::Format format); - ~QWaylandDrmBuffer(); - EGLImageKHR mImage; - GLuint mTexture; + QWaylandPaintDevice(QWaylandDisplay *display, QWidget *widget) + : QGLPaintDevice(), mDisplay(display), mWidget(widget) + { + QGLFormat format; + mContext = new QGLContext(format, widget); + mContext->create(); + glGenFramebuffers(1, &mFbo); + glGenRenderbuffers(1, &mRbo); + } + ~QWaylandPaintDevice() + { + glDeleteFramebuffers(1, &mFbo); + glDeleteRenderbuffers(1, &mRbo); + } + + QSize size() const { return mWidget->size(); } + QGLContext *context() const { return mContext; } + QPaintEngine *paintEngine() const { return qt_qgl_paint_engine(); } + + void beginPaint(); + void endPaint(); +private: QWaylandDisplay *mDisplay; + QWidget *mWidget; + QGLContext *mContext; + GLuint mFbo, mRbo; }; -class QWaylandDrmWindowSurface : public QWindowSurface +void QWaylandPaintDevice::beginPaint(void) { -public: - QWaylandDrmWindowSurface(QWidget *window, QWaylandDisplay *display); - ~QWaylandDrmWindowSurface(); + QWaylandWindow *mWindow = (QWaylandWindow *)mWidget->platformWindow(); + QWaylandDrmBuffer *mBuffer = (QWaylandDrmBuffer *)mWindow->getBuffer(); + QPlatformGLContext *ctx = mWindow->glContext(); + QRect geometry = mWidget->geometry(); - QPaintDevice *paintDevice(); - void flush(QWidget *widget, const QRegion ®ion, const QPoint &offset); - void resize(const QSize &size); + QGLPaintDevice::beginPaint(); -private: - QWaylandDrmBuffer *mBuffer; - QWaylandDisplay *mDisplay; -}; + ctx->makeCurrent(); + glBindFramebuffer(GL_FRAMEBUFFER, mFbo); + glBindRenderbuffer(GL_RENDERBUFFER, mRbo); + glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, mBuffer->mImage); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_RENDERBUFFER, mRbo); +} + +void QWaylandPaintDevice::endPaint(void) +{ + QWaylandWindow *mWindow = (QWaylandWindow *)mWidget->platformWindow(); + QPlatformGLContext *ctx = mWindow->glContext(); + QRect geometry = mWidget->geometry(); + + wl_surface_damage(mWindow->surface(), 0, 0, + geometry.width(), geometry.height()); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glBindRenderbuffer(GL_RENDERBUFFER, 0); + ctx->doneCurrent(); + + QGLPaintDevice::endPaint(); +} + +/* + * Shared DRM surface for GL based drawing + */ QWaylandDrmBuffer::QWaylandDrmBuffer(QWaylandDisplay *display, const QSize &size, QImage::Format format) : mDisplay(display) + , mSize(size) { Q_UNUSED(format); @@ -216,23 +257,62 @@ QWaylandDrmWindowSurface::QWaylandDrmWindowSurface(QWidget *window, , mBuffer(0) , mDisplay(display) { + mPaintDevice = new QWaylandPaintDevice(display, window); } QWaylandDrmWindowSurface::~QWaylandDrmWindowSurface() { + delete mPaintDevice; } QPaintDevice *QWaylandDrmWindowSurface::paintDevice() { - return NULL; + return mPaintDevice; } void QWaylandDrmWindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoint &offset) { + Q_UNUSED(region); + Q_UNUSED(offset); + Q_UNUSED(widget); +#if 0 + GLuint surf_rbo, surf_fbo; + QWaylandWindow *mWindow = (QWaylandWindow *)widget->platformWindow(); + QPlatformGLContext *ctx = mWindow->glContext(); + QRect geometry = widget->geometry(); + + ctx->makeCurrent(); + + glGenFramebuffers(1, &surf_fbo); + glBindFramebuffer(GL_FRAMEBUFFER, surf_fbo); + glGenRenderbuffers(1, &surf_rbo); + glBindRenderbuffer(GL_RENDERBUFFER, surf_rbo); + glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, mBuffer->mImage); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_RENDERBUFFER, surf_rbo); + + wl_surface_damage(mWindow->surface(), 0, 0, + geometry.width(), geometry.height()); + + ctx->doneCurrent(); +#endif } void QWaylandDrmWindowSurface::resize(const QSize &size) { + QWaylandWindow *ww = (QWaylandWindow *) window()->platformWindow(); + QWindowSurface::resize(size); + QImage::Format format = QApplicationPrivate::platformIntegration()->screens().first()->format(); + + if (mBuffer != NULL && mBuffer->mSize == size) + return; + + if (mBuffer != NULL) + delete mBuffer; + + mBuffer = new QWaylandDrmBuffer(mDisplay, size, format); + + ww->attach(mBuffer); } QT_END_NAMESPACE diff --git a/src/plugins/platforms/wayland/qwaylandwindowsurface.h b/src/plugins/platforms/wayland/qwaylandwindowsurface.h index 2246db6..a033531 100644 --- a/src/plugins/platforms/wayland/qwaylandwindowsurface.h +++ b/src/plugins/platforms/wayland/qwaylandwindowsurface.h @@ -42,10 +42,18 @@ #ifndef QWINDOWSURFACE_WAYLAND_H #define QWINDOWSURFACE_WAYLAND_H +#include <QGLFramebufferObject> #include <QtGui/private/qwindowsurface_p.h> #include <QtGui/QPlatformWindow> +#define MESA_EGL_NO_X11_HEADERS +#define EGL_EGLEXT_PROTOTYPES +#include <EGL/egl.h> +#include <EGL/eglext.h> + +#include <QtOpenGL/qgl.h> + QT_BEGIN_NAMESPACE class QWaylandDisplay; @@ -80,6 +88,35 @@ private: QWaylandDisplay *mDisplay; }; +class QWaylandDrmBuffer : public QWaylandBuffer { +public: + QWaylandDrmBuffer(QWaylandDisplay *display, + const QSize &size, QImage::Format format); + ~QWaylandDrmBuffer(); + EGLImageKHR mImage; + GLuint mTexture; + QWaylandDisplay *mDisplay; + QGLFramebufferObject *pdev; + QSize mSize; +}; + +class QWaylandDrmWindowSurface : public QWindowSurface +{ +public: + QWaylandDrmWindowSurface(QWidget *window, QWaylandDisplay *display); + ~QWaylandDrmWindowSurface(); + + QPaintDevice *paintDevice(); + void flush(QWidget *widget, const QRegion ®ion, const QPoint &offset); + void resize(const QSize &size); + +private: + QWaylandDrmBuffer *mBuffer; + QWaylandDisplay *mDisplay; + QPaintDevice *mPaintDevice; +}; + + QT_END_NAMESPACE #endif |