From 506e3535c85de2b41e0d31bbcd3b726ce8adbeca Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Fri, 22 Oct 2010 10:31:03 -0700 Subject: Wayland: add GL drawing support Works with analogclock, draws upside down, fails to resize, and doesn't show GL widget with hello_es2. --- .../platforms/wayland/qwaylandintegration.cpp | 17 ++- .../platforms/wayland/qwaylandintegration.h | 5 +- .../platforms/wayland/qwaylandwindowsurface.cpp | 140 ++++++++++++++++----- .../platforms/wayland/qwaylandwindowsurface.h | 37 ++++++ 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 #include #include +#include #include #include @@ -10,6 +11,9 @@ #include #include +#include +#include + #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 #include #include +#include "qgl.h" #include #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 +#include + +#include #include #include +#include +#include + +#include "qwaylandintegration.h" +#include "qwaylandwindowsurface.h" #include #include @@ -50,15 +58,6 @@ #include #include -#define GL_GLEXT_PROTOTYPES -#define EGL_EGLEXT_PROTOTYPES -#define MESA_EGL_NO_X11_HEADERS - -#include -#include -#include -#include - 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 #include #include +#define MESA_EGL_NO_X11_HEADERS +#define EGL_EGLEXT_PROTOTYPES +#include +#include + +#include + 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 -- cgit v0.12