From 9075d224afb736e14014d5fa8001be03f79df267 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=B8rgen=20Lind?= Date: Fri, 21 Jan 2011 15:52:02 +0100 Subject: [PATCH] Making clearer separation between responsibility of different classes Ie. Moving code into different files and refactoring some of the classes. The Drmbuffer was most affected. It has a depth and stencil buffer. QWaylandGLContext contain the context. The drm buffer class has to be bound to the context before used. --- src/plugins/platforms/wayland/qwaylandbuffer.h | 60 +++++ src/plugins/platforms/wayland/qwaylandcursor.cpp | 8 +- src/plugins/platforms/wayland/qwaylanddisplay.cpp | 10 + src/plugins/platforms/wayland/qwaylanddisplay.h | 3 + .../platforms/wayland/qwaylanddrmsurface.cpp | 188 ++++++++------- src/plugins/platforms/wayland/qwaylanddrmsurface.h | 106 +++++++++ .../platforms/wayland/qwaylandglcontext.cpp | 262 ++++++++------------- src/plugins/platforms/wayland/qwaylandglcontext.h | 20 +- .../platforms/wayland/qwaylandinputdevice.cpp | 55 ++++- .../platforms/wayland/qwaylandinputdevice.h | 44 +++- .../platforms/wayland/qwaylandintegration.cpp | 46 +++- .../platforms/wayland/qwaylandshmsurface.cpp | 6 +- ...waylandwindowsurface.h => qwaylandshmsurface.h} | 47 +--- src/plugins/platforms/wayland/qwaylandwindow.cpp | 27 ++- src/plugins/platforms/wayland/wayland.pro | 8 +- 15 files changed, 563 insertions(+), 327 deletions(-) create mode 100644 src/plugins/platforms/wayland/qwaylandbuffer.h create mode 100644 src/plugins/platforms/wayland/qwaylanddrmsurface.h rename src/plugins/platforms/wayland/{qwaylandwindowsurface.h => qwaylandshmsurface.h} (69%) diff --git a/src/plugins/platforms/wayland/qwaylandbuffer.h b/src/plugins/platforms/wayland/qwaylandbuffer.h new file mode 100644 index 0000000..643e89c --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandbuffer.h @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the config.tests of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWAYLANDBUFFER_H +#define QWAYLANDBUFFER_H + +#include + +#include + +class QWaylandBuffer { +public: + QWaylandBuffer() { } + virtual ~QWaylandBuffer() { } + wl_buffer *buffer() {return mBuffer;} + virtual QSize size() const = 0; + +protected: + struct wl_buffer *mBuffer; +}; + +#endif // QWAYLANDBUFFER_H diff --git a/src/plugins/platforms/wayland/qwaylandcursor.cpp b/src/plugins/platforms/wayland/qwaylandcursor.cpp index 2a1e9a9..f4bae88 100644 --- a/src/plugins/platforms/wayland/qwaylandcursor.cpp +++ b/src/plugins/platforms/wayland/qwaylandcursor.cpp @@ -42,12 +42,12 @@ #include "qwaylandcursor.h" #include "qwaylanddisplay.h" -#include "qwaylandwindowsurface.h" #include "qwaylandinputdevice.h" +#include "qwaylandshmsurface.h" #include -#define DATADIR "/usr/share" +#define DATADIR "/home/jlind/install/share" static const struct pointer_image { const char *filename; @@ -156,7 +156,7 @@ void QWaylandCursor::changeCursor(QCursor *cursor, QWidget *widget) QImageReader reader(p->filename); - if (mBuffer == NULL || mBuffer->mImage.size() != reader.size()) { + if (mBuffer == NULL || mBuffer->size() != reader.size()) { if (mBuffer) delete mBuffer; @@ -164,7 +164,7 @@ void QWaylandCursor::changeCursor(QCursor *cursor, QWidget *widget) QImage::Format_ARGB32); } - reader.read(&mBuffer->mImage); + reader.read(mBuffer->image()); mDisplay->setCursor(mBuffer, p->hotspot_x, p->hotspot_y); } diff --git a/src/plugins/platforms/wayland/qwaylanddisplay.cpp b/src/plugins/platforms/wayland/qwaylanddisplay.cpp index 8446777..e5adb49 100644 --- a/src/plugins/platforms/wayland/qwaylanddisplay.cpp +++ b/src/plugins/platforms/wayland/qwaylanddisplay.cpp @@ -304,3 +304,13 @@ QWaylandDisplay::~QWaylandDisplay(void) close(mFd); wl_display_destroy(mDisplay); } + +void QWaylandDisplay::syncCallback(wl_display_sync_func_t func, void *data) +{ + wl_display_sync_callback(mDisplay, func, data); +} + +void QWaylandDisplay::frameCallback(wl_display_frame_func_t func, void *data) +{ + wl_display_frame_callback(mDisplay, func, data); +} diff --git a/src/plugins/platforms/wayland/qwaylanddisplay.h b/src/plugins/platforms/wayland/qwaylanddisplay.h index 7d989a9..a95e9c0 100644 --- a/src/plugins/platforms/wayland/qwaylanddisplay.h +++ b/src/plugins/platforms/wayland/qwaylanddisplay.h @@ -78,6 +78,9 @@ public: void setCursor(QWaylandBuffer *buffer, int32_t x, int32_t y); + void syncCallback(wl_display_sync_func_t func, void *data); + void frameCallback(wl_display_frame_func_t func, void *data); + public slots: void eventDispatcher(void); void flushRequests(void); diff --git a/src/plugins/platforms/wayland/qwaylanddrmsurface.cpp b/src/plugins/platforms/wayland/qwaylanddrmsurface.cpp index 1a7683e..5803abf 100644 --- a/src/plugins/platforms/wayland/qwaylanddrmsurface.cpp +++ b/src/plugins/platforms/wayland/qwaylanddrmsurface.cpp @@ -38,21 +38,17 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ +#include "qwaylanddrmsurface.h" -#define GL_GLEXT_PROTOTYPES -#include -#include +#include "qwaylanddisplay.h" +#include "qwaylandwindow.h" +#include "qwaylandscreen.h" -#include #include #include #include #include - -#include "qwaylanddisplay.h" -#include "qwaylandwindowsurface.h" -#include "qwaylandwindow.h" -#include "qwaylandscreen.h" +#include #include #include @@ -65,46 +61,29 @@ QT_BEGIN_NAMESPACE class QWaylandPaintDevice : public QGLPaintDevice { public: - QWaylandPaintDevice(QWaylandDisplay *display, QWidget *widget) - : QGLPaintDevice(), mDisplay(display), mWidget(widget) - { - QGLFormat format; - mContext = new QGLContext(format, widget); - mContext->create(); - } - - QSize size() const { return mWidget->size(); } - QGLContext *context() const { return mContext; } + QWaylandPaintDevice(QWaylandDisplay *display, QWaylandDrmWindowSurface *windowSurface, QPlatformGLContext *context) + : QGLPaintDevice() + , mDisplay(display) + , mPlatformGLContext(context) + , mWindowSurface(windowSurface) + { + } + + QSize size() const { return mWindowSurface->size(); } + QGLContext *context() const { return QGLContext::fromPlatformGLContext(mPlatformGLContext); } + void beginPaint() { mWindowSurface->currentPaintBuffer()->bindToCurrentContext(); } + void ensureActiveTarget() { } + void endPaint() { } QPaintEngine *paintEngine() const { return qt_qgl_paint_engine(); } + bool isFlipped()const {return true;} + - void beginPaint(); - void endPaint(); private: QWaylandDisplay *mDisplay; - QWidget *mWidget; - QGLContext *mContext; -}; - -void QWaylandPaintDevice::beginPaint(void) -{ - QWaylandWindow *mWindow = (QWaylandWindow *)mWidget->platformWindow(); - QPlatformGLContext *ctx = mWindow->glContext(); + QPlatformGLContext *mPlatformGLContext; + QWaylandDrmWindowSurface *mWindowSurface; - QGLPaintDevice::beginPaint(); - - ctx->makeCurrent(); -} - -void QWaylandPaintDevice::endPaint(void) -{ - QWaylandWindow *mWindow = (QWaylandWindow *)mWidget->platformWindow(); - QPlatformGLContext *ctx = mWindow->glContext(); - QRect geometry = mWidget->geometry(); - - ctx->doneCurrent(); - - QGLPaintDevice::endPaint(); -} +}; /* * Shared DRM surface for GL based drawing @@ -117,33 +96,36 @@ QWaylandDrmBuffer::QWaylandDrmBuffer(QWaylandDisplay *display, struct wl_visual *visual; EGLint name, stride; - static const EGLint contextAttribs[] = { - EGL_CONTEXT_CLIENT_VERSION, 2, - EGL_NONE - }; + EGLint imageAttribs[] = { - EGL_WIDTH, 0, - EGL_HEIGHT, 0, + EGL_WIDTH, size.width(), + EGL_HEIGHT, size.height(), EGL_DRM_BUFFER_FORMAT_MESA, EGL_DRM_BUFFER_FORMAT_ARGB32_MESA, - EGL_DRM_BUFFER_USE_MESA, EGL_DRM_BUFFER_USE_SCANOUT_MESA, + EGL_DRM_BUFFER_USE_MESA, EGL_DRM_BUFFER_USE_SCANOUT_MESA, EGL_NONE }; - eglBindAPI(EGL_OPENGL_ES_API); - mContext = eglCreateContext(mDisplay->eglDisplay(), NULL, - EGL_NO_CONTEXT, contextAttribs); - eglMakeCurrent(mDisplay->eglDisplay(), 0, 0, mContext); - - imageAttribs[1] = size.width(); - imageAttribs[3] = size.height(); mImage = eglCreateDRMImageMESA(mDisplay->eglDisplay(), imageAttribs); + glGenFramebuffers(1, &mFbo); + glBindFramebuffer(GL_FRAMEBUFFER_EXT, mFbo); + + glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, mImage); glGenTextures(1, &mTexture); glBindTexture(GL_TEXTURE_2D, mTexture); glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, mImage); + glGenRenderbuffers(1,&mDepthStencil); + glBindRenderbuffer(GL_RENDERBUFFER_EXT,mDepthStencil); + glRenderbufferStorage(GL_RENDERBUFFER_EXT, + GL_DEPTH24_STENCIL8_EXT, size.width(), size.height()); + glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, + GL_RENDERBUFFER_EXT, mDepthStencil); + glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, + GL_RENDERBUFFER_EXT, mDepthStencil); + eglExportDRMImageMESA(mDisplay->eglDisplay(), - mImage, &name, NULL, &stride); + mImage, &name, NULL, &stride); switch (format) { case QImage::Format_ARGB32: @@ -160,6 +142,20 @@ QWaylandDrmBuffer::QWaylandDrmBuffer(QWaylandDisplay *display, mBuffer = display->createDrmBuffer(name, size.width(), size.height(), stride, visual); + + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT); + + switch(status) { + case GL_NO_ERROR: + case GL_FRAMEBUFFER_COMPLETE_EXT: + qDebug() << "fbo ok"; + break; + default: + qDebug() <<"QWaylandDrmBuffer error: "<< status; + break; + } + QT_CHECK_GLERROR(); + } QWaylandDrmBuffer::~QWaylandDrmBuffer(void) @@ -168,22 +164,31 @@ QWaylandDrmBuffer::~QWaylandDrmBuffer(void) glDeleteTextures(1, &mTexture); eglDestroyImageKHR(mDisplay->eglDisplay(), mImage); wl_buffer_destroy(mBuffer); - eglDestroyContext(mDisplay->eglDisplay(), mContext); } +void QWaylandDrmBuffer::bindToCurrentContext() +{ + Q_ASSERT(QPlatformGLContext::currentContext()); + glViewport(0, 0, size().width(), size().height()); + glBindFramebuffer(GL_FRAMEBUFFER_EXT, mFbo); + glBindTexture(GL_TEXTURE_2D, mTexture); + glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, mTexture, 0); + QT_CHECK_GLERROR(); + +} QWaylandDrmWindowSurface::QWaylandDrmWindowSurface(QWidget *window, QWaylandDisplay *display) : QWindowSurface(window) - , mBuffer(0) + , mBufferList(1) // there is something wrong with the buffer flush. keeping it single buffered for now. + , mCurrentPaintBuffer(0) , mDisplay(display) + , mPaintDevice(new QWaylandPaintDevice(mDisplay, this,window->platformWindow()->glContext())) { - QWaylandWindow *ww = (QWaylandWindow *) window->platformWindow(); - QImage::Format format = QApplicationPrivate::platformIntegration()->screens().first()->format(); - - mPaintDevice = new QWaylandPaintDevice(display, window); - mBuffer = new QWaylandDrmBuffer(mDisplay, window->size(), format); - ww->attach(mBuffer); + for (int i = 0; i < mBufferList.size(); i++) { + mBufferList[i] = 0; + } } QWaylandDrmWindowSurface::~QWaylandDrmWindowSurface() @@ -191,6 +196,11 @@ QWaylandDrmWindowSurface::~QWaylandDrmWindowSurface() delete mPaintDevice; } +void QWaylandDrmWindowSurface::beginPaint(const QRegion &) +{ + window()->platformWindow()->glContext()->makeCurrent(); +} + QPaintDevice *QWaylandDrmWindowSurface::paintDevice() { return mPaintDevice; @@ -200,42 +210,40 @@ void QWaylandDrmWindowSurface::flush(QWidget *widget, const QRegion ®ion, con { Q_UNUSED(offset); QWaylandWindow *ww = (QWaylandWindow *) widget->platformWindow(); - QVector rects = region.rects(); - const QRect *r; - int i; - for (i = 0; i < rects.size(); i++) { - r = &rects.at(i); - wl_surface_damage(ww->surface(), - r->x(), r->y(), r->width(), r->height()); + QVector rects = region.rects(); + for (int i = 0; i < rects.size(); i++) { + QRect r = rects.at(i); + wl_surface_damage(ww->surface(), + r.x(), r.y(), r.width(), r.height()); } + + mCurrentPaintBuffer = ++mCurrentPaintBuffer % mBufferList.size(); + ww->attach(currentPaintBuffer()); } void QWaylandDrmWindowSurface::resize(const QSize &requestedSize) { + QWindowSurface::resize(requestedSize); QWaylandWindow *ww = (QWaylandWindow *) window()->platformWindow(); QWaylandScreen *screen = (QWaylandScreen *)QApplicationPrivate::platformIntegration()->screens().first(); QImage::Format format = screen->format(); - QSize screenSize = screen->geometry().size(); - QSize size = requestedSize; - - if (mBuffer != NULL && mBuffer->mSize == size) - return; - - if (mBuffer != NULL) - delete mBuffer; - /* Clamp to screen size */ - if (size.width() > screenSize.width()) - size.setWidth(screenSize.width()); - if (size.height() > screenSize.height()) - size.setHeight(screenSize.height()); + ww->glContext()->makeCurrent(); - QWindowSurface::resize(size); + for (int i = 0; i < mBufferList.size(); i++) { + if (!mBufferList.at(i) || mBufferList.at(i)->size() != requestedSize) { + delete mBufferList[i]; + mBufferList[i] = new QWaylandDrmBuffer(mDisplay, requestedSize, format); + } + } - mBuffer = new QWaylandDrmBuffer(mDisplay, size, format); + ww->attach(currentPaintBuffer()); +} - ww->attach(mBuffer); +QWaylandDrmBuffer * QWaylandDrmWindowSurface::currentPaintBuffer() const +{ + return mBufferList[mCurrentPaintBuffer]; } QT_END_NAMESPACE diff --git a/src/plugins/platforms/wayland/qwaylanddrmsurface.h b/src/plugins/platforms/wayland/qwaylanddrmsurface.h new file mode 100644 index 0000000..c67f16f --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylanddrmsurface.h @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the config.tests of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWAYLANDDRMSURFACE_H +#define QWAYLANDDRMSURFACE_H + +#include "qwaylanddisplay.h" +#include "qwaylandbuffer.h" + +#include +#include + +#define GL_GLEXT_PROTOTYPES +#include +#include + +#define QT_RESET_GLERROR() \ +{ \ + while (glGetError() != GL_NO_ERROR) {} \ +} +#define QT_CHECK_GLERROR() \ +{ \ + GLenum err = glGetError(); \ + if (err != GL_NO_ERROR) { \ + qDebug("[%s line %d] GL Error: 0x%x", \ + __FILE__, __LINE__, (int)err); \ + } \ +} + +class QWaylandDrmBuffer : public QWaylandBuffer { +public: + QWaylandDrmBuffer(QWaylandDisplay *display, + const QSize &size, QImage::Format format); + ~QWaylandDrmBuffer(); + + void bindToCurrentContext(); + QSize size() const { return mSize; } + +private: + EGLImageKHR mImage; + QWaylandDisplay *mDisplay; + QSize mSize; + GLuint mFbo; + GLuint mTexture; + GLuint mDepthStencil; +}; + +class QWaylandDrmWindowSurface : public QWindowSurface +{ +public: + QWaylandDrmWindowSurface(QWidget *window, QWaylandDisplay *display); + ~QWaylandDrmWindowSurface(); + + void beginPaint(const QRegion &); + + QPaintDevice *paintDevice(); + void flush(QWidget *widget, const QRegion ®ion, const QPoint &offset); + void resize(const QSize &size); + + QWaylandDrmBuffer *currentPaintBuffer() const; +private: + QVarLengthArray mBufferList; + int mCurrentPaintBuffer; + QWaylandDisplay *mDisplay; + QPaintDevice *mPaintDevice; +}; + +#endif // QWAYLANDDRMSURFACE_H diff --git a/src/plugins/platforms/wayland/qwaylandglcontext.cpp b/src/plugins/platforms/wayland/qwaylandglcontext.cpp index 24abcf8..4bf68c4 100644 --- a/src/plugins/platforms/wayland/qwaylandglcontext.cpp +++ b/src/plugins/platforms/wayland/qwaylandglcontext.cpp @@ -1,25 +1,53 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + #include "qwaylandglcontext.h" #include "qwaylanddisplay.h" #include "qwaylandwindow.h" -#include "qwaylandwindowsurface.h" -#include "qfontconfigdatabase.h" - -#include -#include -#include -#include +#include "qwaylanddrmsurface.h" #include #include -#include -#include - -#include -#include -#include - #include #include @@ -27,165 +55,80 @@ extern "C" { #include } -QWaylandGLContext::QWaylandGLContext(QWaylandDisplay *wd, QWaylandWindow *window, const QPlatformWindowFormat &format) +Q_GLOBAL_STATIC(QMutex,qt_defaultSharedContextMutex); + +EGLint QWaylandGLContext::contextAttibutes[] = { + EGL_CONTEXT_CLIENT_VERSION, 2, + EGL_NONE +}; + +QWaylandGLContext::QWaylandGLContext(QWaylandDisplay *wd, const QPlatformWindowFormat &format) : QPlatformGLContext() , mFormat(format) , mDisplay(wd) - , mWindow(window) - , parentFbo(0) - , parentRbo(0) { + QPlatformGLContext *sharePlatformContext; + if (format.useDefaultSharedContext()) { + if (!QPlatformGLContext::defaultSharedContext()) { + if (qt_defaultSharedContextMutex()->tryLock()){ + createDefaultSharedContex(wd); + qt_defaultSharedContextMutex()->unlock(); + } else { + qt_defaultSharedContextMutex()->lock(); //wait to the the shared context is created + qt_defaultSharedContextMutex()->unlock(); + } + } + sharePlatformContext = QPlatformGLContext::defaultSharedContext(); + } else { + sharePlatformContext = format.sharedGLContext(); + } + mFormat.setSharedContext(sharePlatformContext); + EGLContext shareEGLContext = EGL_NO_CONTEXT; + if (sharePlatformContext) + shareEGLContext = static_cast(sharePlatformContext)->mContext; + + eglBindAPI(EGL_OPENGL_ES_API); + mContext = eglCreateContext(mDisplay->eglDisplay(), NULL, + shareEGLContext, contextAttibutes); + + mFormat.setAccum(false); + mFormat.setAlphaBufferSize(8); + mFormat.setRedBufferSize(8); + mFormat.setGreenBufferSize(8); + mFormat.setBlueBufferSize(8); + mFormat.setDepth(false); +// mFormat.setDepthBufferSize(8); + mFormat.setStencil(false); +// mFormat.setStencilBufferSize(24); +// mFormat.setSampleBuffers(false); + } +QWaylandGLContext::QWaylandGLContext() + : QPlatformGLContext() + , mDisplay(0) + , mContext(EGL_NO_CONTEXT) +{ } + QWaylandGLContext::~QWaylandGLContext() { - glDeleteRenderbuffers(1, &parentRbo); - glDeleteFramebuffers(1, &parentFbo); + eglDestroyContext(mDisplay->eglDisplay(),mContext); } void QWaylandGLContext::makeCurrent() { - QWaylandDrmBuffer *mBuffer = (QWaylandDrmBuffer *)mWindow->getBuffer(); - QRect geometry = mWindow->geometry(); - - if (!mBuffer) - return; - - eglMakeCurrent(mDisplay->eglDisplay(), 0, 0, mBuffer->mContext); - - glViewport(0, 0, geometry.width(), geometry.height()); - glBindFramebuffer(GL_FRAMEBUFFER, mBuffer->mFbo); - glBindTexture(GL_TEXTURE_2D, mBuffer->mTexture); - glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, mBuffer->mImage); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, mBuffer->mTexture, 0); + QPlatformGLContext::makeCurrent(); + eglMakeCurrent(mDisplay->eglDisplay(), EGL_NO_SURFACE, EGL_NO_SURFACE, mContext); } void QWaylandGLContext::doneCurrent() { -} - -/* drawTexture - Draw from a texture into a the current framebuffer - * @rect: GL normalized coords for drawing (between -1.0f and 1.0f) - * @tex_id: texture source - * @texSize: size of source rectangle in Qt coords - * @br: bounding rect for drawing - */ -static void drawTexture(const QRectF &rect, GLuint tex_id, - const QSize &texSize, const QRectF &br) -{ - QRectF src = br.isEmpty() - ? QRectF(QPointF(), texSize) - : QRectF(QPointF(br.x(), texSize.height() - br.bottom()), br.size()); - qreal width = texSize.width(); - qreal height = texSize.height(); - - src.setLeft(src.left() / width); - src.setRight(src.right() / width); - src.setTop(src.top() / height); - src.setBottom(src.bottom() / height); - - const GLfloat tx1 = src.left(); - const GLfloat tx2 = src.right(); - const GLfloat ty1 = src.top(); - const GLfloat ty2 = src.bottom(); - - GLfloat texCoordArray[4*2] = { - tx1, ty2, tx2, ty2, tx2, ty1, tx1, ty1 - }; - - GLfloat vertexArray[4*2]; - extern void qt_add_rect_to_array(const QRectF &r, GLfloat *array); - qt_add_rect_to_array(rect, vertexArray); - - glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, vertexArray); - glVertexAttribPointer(QT_TEXTURE_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, texCoordArray); - - glBindTexture(GL_TEXTURE_2D, tex_id); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - - glEnableVertexAttribArray(QT_VERTEX_COORDS_ATTR); - glEnableVertexAttribArray(QT_TEXTURE_COORDS_ATTR); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - glDisableVertexAttribArray(QT_VERTEX_COORDS_ATTR); - glDisableVertexAttribArray(QT_TEXTURE_COORDS_ATTR); - - glBindTexture(GL_TEXTURE_2D, 0); + QPlatformGLContext::doneCurrent(); + eglMakeCurrent(mDisplay->eglDisplay(), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); } void QWaylandGLContext::swapBuffers() { - QWaylandWindow *mParentWindow = mWindow->getParentWindow(); - QWaylandDrmBuffer *mBuffer, *mParentBuffer; - QRect geometry = mWindow->geometry(), parentGeometry; - QGLShaderProgram *blitProgram; - QRectF r; - qreal w; - qreal h; - - if (!mParentWindow) { - qDebug("swap without parent widget?\n"); - return; - } - - if (!mParentWindow->surface()) { - qDebug("parent has no surface??\n"); - return; - } - - parentGeometry = mParentWindow->geometry(); - mBuffer = (QWaylandDrmBuffer *)mWindow->getBuffer(); - mParentBuffer = (QWaylandDrmBuffer *)mParentWindow->getBuffer(); - - glDisable(GL_DEPTH_TEST); - - /* These need to be generated against the src context */ - if (!parentFbo) - glGenFramebuffers(1, &parentFbo); - if (!parentRbo) - glGenRenderbuffers(1, &parentRbo); - - glBindFramebuffer(GL_FRAMEBUFFER, parentFbo); - glBindRenderbuffer(GL_RENDERBUFFER, parentRbo); - glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, - mParentBuffer->mImage); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_RENDERBUFFER, parentRbo); - glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, mBuffer->mImage); - glViewport(0, 0, parentGeometry.width(), parentGeometry.height()); - - blitProgram = QGLEngineSharedShaders::shadersForContext(QGLContext::currentContext())->blitProgram(); - blitProgram->bind(); - blitProgram->setUniformValue("imageTexture", 0); - - /* Transform the target rect to the appropriate coords on the parent */ - w = parentGeometry.width(); - h = parentGeometry.height(); - - r.setLeft((geometry.left() / w) * 2.0f - 1.0f); - if (geometry.right() == (parentGeometry.width() - 1)) - r.setRight(1.0f); - else - r.setRight((geometry.right() / w) * 2.0f - 1.0f); - - r.setTop((geometry.top() / h) * 2.0f - 1.0f); - if (geometry.bottom() == (parentGeometry.height() - 1)) - r.setBottom(-1.0f); - else - r.setBottom((geometry.bottom() / h) * 2.0f - 1.0f); - - drawTexture(r, mBuffer->mTexture, mParentWindow->widget()->size(), parentGeometry); - - wl_surface_damage(mParentWindow->surface(), geometry.left(), geometry.top(), - geometry.right(), geometry.bottom()); - /* restore things to the last valid GL state */ - makeCurrent(); - /* hack: avoid tight swapBuffers loops */ - usleep(20000); } void *QWaylandGLContext::getProcAddress(const QString &string) @@ -193,13 +136,12 @@ void *QWaylandGLContext::getProcAddress(const QString &string) return (void *) eglGetProcAddress(string.toLatin1().data()); } -QPlatformGLContext *QWaylandWindow::glContext() const +void QWaylandGLContext::createDefaultSharedContex(QWaylandDisplay *display) { - if (!mGLContext) { - QWaylandWindow *that = const_cast(this); - that->mGLContext = new QWaylandGLContext(mDisplay, that, widget()->platformWindowFormat()); - } - - return mGLContext; + QWaylandGLContext *defaultSharedContext = new QWaylandGLContext; + defaultSharedContext->mDisplay = display; + defaultSharedContext->mContext = eglCreateContext(mDisplay->eglDisplay(), NULL, + EGL_NO_CONTEXT, contextAttibutes); + QPlatformGLContext::setDefaultSharedContext(defaultSharedContext); } diff --git a/src/plugins/platforms/wayland/qwaylandglcontext.h b/src/plugins/platforms/wayland/qwaylandglcontext.h index 6e3c108..d9ba323 100644 --- a/src/plugins/platforms/wayland/qwaylandglcontext.h +++ b/src/plugins/platforms/wayland/qwaylandglcontext.h @@ -44,16 +44,19 @@ #include +#include class QWaylandDisplay; class QWaylandWindow; +class QWaylandDrmWindowSurface; -#define GL_GLEXT_PROTOTYPES -#include -#include +#define MESA_EGL_NO_X11_HEADERS +#define EGL_EGLEXT_PROTOTYPES +#include +#include class QWaylandGLContext : public QPlatformGLContext { public: - QWaylandGLContext(QWaylandDisplay *wd, QWaylandWindow *window, const QPlatformWindowFormat &format); + QWaylandGLContext(QWaylandDisplay *wd, const QPlatformWindowFormat &format); ~QWaylandGLContext(); void makeCurrent(); void doneCurrent(); @@ -64,8 +67,13 @@ public: private: QPlatformWindowFormat mFormat; QWaylandDisplay *mDisplay; - QWaylandWindow *mWindow; - GLuint parentFbo, parentRbo; + + static EGLint contextAttibutes[]; + EGLContext mContext; + + void createDefaultSharedContex(QWaylandDisplay *display); + QWaylandGLContext(); + }; diff --git a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp index 77c5815..03edc07 100644 --- a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp +++ b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp @@ -1,8 +1,49 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + #include "qwaylandinputdevice.h" #include "qwaylandintegration.h" -#include "qwaylandwindowsurface.h" #include "qwaylandwindow.h" +#include "qwaylandbuffer.h" #include @@ -197,10 +238,12 @@ void QWaylandInputDevice::inputHandleKey(void *data, qWarning("keycode %d, sym %d, string %d, modifiers 0x%x", code, sym, s[0], (int) inputDevice->mModifiers); - QWindowSystemInterface::handleKeyEvent(window->widget(), - time, type, sym, - inputDevice->mModifiers, - QString::fromLatin1(s)); + if (window) { + QWindowSystemInterface::handleKeyEvent(window->widget(), + time, type, sym, + inputDevice->mModifiers, + QString::fromLatin1(s)); + } } void QWaylandInputDevice::inputHandlePointerFocus(void *data, @@ -264,5 +307,5 @@ const struct wl_input_device_listener QWaylandInputDevice::inputDeviceListener = void QWaylandInputDevice::attach(QWaylandBuffer *buffer, int x, int y) { - wl_input_device_attach(mInputDevice, mTime, buffer->mBuffer, x, y); + wl_input_device_attach(mInputDevice, mTime, buffer->buffer(), x, y); } diff --git a/src/plugins/platforms/wayland/qwaylandinputdevice.h b/src/plugins/platforms/wayland/qwaylandinputdevice.h index 749ef70..2328db8 100644 --- a/src/plugins/platforms/wayland/qwaylandinputdevice.h +++ b/src/plugins/platforms/wayland/qwaylandinputdevice.h @@ -1,13 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + #ifndef QWAYLANDINPUTDEVICE_H #define QWAYLANDINPUTDEVICE_H +#include "qwaylandwindow.h" + #include #include #include #include #include -#include "qwaylandwindowsurface.h" QT_BEGIN_NAMESPACE diff --git a/src/plugins/platforms/wayland/qwaylandintegration.cpp b/src/plugins/platforms/wayland/qwaylandintegration.cpp index a6fdc2e..e647880 100644 --- a/src/plugins/platforms/wayland/qwaylandintegration.cpp +++ b/src/plugins/platforms/wayland/qwaylandintegration.cpp @@ -1,7 +1,49 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the config.tests of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + #include "qwaylandintegration.h" #include "qwaylanddisplay.h" -#include "qwaylandwindowsurface.h" +#include "qwaylandshmsurface.h" +#include "qwaylanddrmsurface.h" #include "qwaylandwindow.h" #include "qfontconfigdatabase.h" @@ -29,7 +71,7 @@ QWaylandIntegration::screens() const QPixmapData *QWaylandIntegration::createPixmapData(QPixmapData::PixelType type) const { if (mUseOpenGL) - return new QGLPixmapData(type); + return new QGLPixmapData(type); return new QRasterPixmapData(type); } diff --git a/src/plugins/platforms/wayland/qwaylandshmsurface.cpp b/src/plugins/platforms/wayland/qwaylandshmsurface.cpp index 1c3a26c..7112424 100644 --- a/src/plugins/platforms/wayland/qwaylandshmsurface.cpp +++ b/src/plugins/platforms/wayland/qwaylandshmsurface.cpp @@ -38,12 +38,12 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ +#include "qwaylandshmsurface.h" #include #include #include "qwaylanddisplay.h" -#include "qwaylandwindowsurface.h" #include "qwaylandwindow.h" #include @@ -104,7 +104,7 @@ QWaylandShmWindowSurface::~QWaylandShmWindowSurface() QPaintDevice *QWaylandShmWindowSurface::paintDevice() { - return &mBuffer->mImage; + return mBuffer->image(); } void QWaylandShmWindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoint &offset) @@ -129,7 +129,7 @@ void QWaylandShmWindowSurface::resize(const QSize &size) QWindowSurface::resize(size); QImage::Format format = QApplicationPrivate::platformIntegration()->screens().first()->format(); - if (mBuffer != NULL && mBuffer->mImage.size() == size) + if (mBuffer != NULL && mBuffer->size() == size) return; if (mBuffer != NULL) diff --git a/src/plugins/platforms/wayland/qwaylandwindowsurface.h b/src/plugins/platforms/wayland/qwaylandshmsurface.h similarity index 69% rename from src/plugins/platforms/wayland/qwaylandwindowsurface.h rename to src/plugins/platforms/wayland/qwaylandshmsurface.h index db57619..8c24e9f 100644 --- a/src/plugins/platforms/wayland/qwaylandwindowsurface.h +++ b/src/plugins/platforms/wayland/qwaylandshmsurface.h @@ -42,32 +42,23 @@ #ifndef QWINDOWSURFACE_WAYLAND_H #define QWINDOWSURFACE_WAYLAND_H -#include +#include "qwaylandbuffer.h" #include #include -#define MESA_EGL_NO_X11_HEADERS -#define EGL_EGLEXT_PROTOTYPES -#include -#include - QT_BEGIN_NAMESPACE class QWaylandDisplay; -class QWaylandBuffer { -public: - QWaylandBuffer() { } - virtual ~QWaylandBuffer() { } - struct wl_buffer *mBuffer; -}; - class QWaylandShmBuffer : public QWaylandBuffer { public: QWaylandShmBuffer(QWaylandDisplay *display, const QSize &size, QImage::Format format); ~QWaylandShmBuffer(); + QSize size() const { return mImage.size(); } + QImage *image() { return &mImage; } +private: QImage mImage; }; @@ -86,36 +77,6 @@ private: QWaylandDisplay *mDisplay; }; -class QWaylandDrmBuffer : public QWaylandBuffer { -public: - QWaylandDrmBuffer(QWaylandDisplay *display, - const QSize &size, QImage::Format format); - ~QWaylandDrmBuffer(); - EGLContext mContext; - EGLImageKHR mImage; - GLuint mTexture; - QWaylandDisplay *mDisplay; - QSize mSize; - GLuint mFbo; -}; - -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 diff --git a/src/plugins/platforms/wayland/qwaylandwindow.cpp b/src/plugins/platforms/wayland/qwaylandwindow.cpp index 4f696b0..fa62330 100644 --- a/src/plugins/platforms/wayland/qwaylandwindow.cpp +++ b/src/plugins/platforms/wayland/qwaylandwindow.cpp @@ -42,15 +42,19 @@ #include "qwaylandwindow.h" #include "qwaylanddisplay.h" -#include "qwaylandwindowsurface.h" #include "qwaylandglcontext.h" +#include "qwaylandbuffer.h" + +#include "qwaylanddrmsurface.h" #include #include +#include + QWaylandWindow::QWaylandWindow(QWidget *window, QWaylandDisplay *display) : QPlatformWindow(window) - , mSurface(0) + , mSurface(display->createSurface()) , mDisplay(display) , mGLContext(0) , mBuffer(0) @@ -81,9 +85,8 @@ void QWaylandWindow::setParent(const QPlatformWindow *parent) void QWaylandWindow::setVisible(bool visible) { if (visible) { - mSurface = mDisplay->createSurface(); wl_surface_set_user_data(mSurface, this); - attach(mBuffer); + wl_surface_map_toplevel(mSurface); } else { wl_surface_destroy(mSurface); mSurface = NULL; @@ -92,12 +95,8 @@ void QWaylandWindow::setVisible(bool visible) void QWaylandWindow::attach(QWaylandBuffer *buffer) { - QRect geometry = widget()->geometry(); - - mBuffer = buffer; if (mSurface) { - wl_surface_attach(mSurface, mBuffer->mBuffer,geometry.x(),geometry.y()); - wl_surface_map_toplevel(mSurface); + wl_surface_attach(mSurface, buffer->buffer(),0,0); } } @@ -111,3 +110,13 @@ void QWaylandWindow::configure(uint32_t time, uint32_t edges, QWindowSystemInterface::handleGeometryChange(widget(), geometry); } + +QPlatformGLContext *QWaylandWindow::glContext() const +{ + if (!mGLContext) { + QWaylandWindow *that = const_cast(this); + that->mGLContext = new QWaylandGLContext(mDisplay, widget()->platformWindowFormat()); + } + + return mGLContext; +} diff --git a/src/plugins/platforms/wayland/wayland.pro b/src/plugins/platforms/wayland/wayland.pro index 784a248..8ba1408 100644 --- a/src/plugins/platforms/wayland/wayland.pro +++ b/src/plugins/platforms/wayland/wayland.pro @@ -15,17 +15,19 @@ SOURCES = main.cpp \ qwaylandscreen.cpp HEADERS = qwaylandintegration.h \ - qwaylandwindowsurface.h \ qwaylandcursor.h \ qwaylanddisplay.h \ qwaylandwindow.h \ qwaylandscreen.h \ - qwaylandglcontext.h + qwaylandglcontext.h \ + qwaylandshmsurface.h \ + qwaylanddrmsurface.h \ + qwaylandbuffer.h contains(QT_CONFIG, opengl) { QT += opengl } -LIBS += -lwayland-client -lxkbcommon -lEGL -lGLESv2 +LIBS += -lwayland-client -lxkbcommon -lEGL unix { CONFIG += link_pkgconfig PKGCONFIG += libdrm -- 2.7.4