summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/wayland/gl_integration
diff options
context:
space:
mode:
authorGiulio Camuffo <giuliocamuffo@gmail.com>2012-11-04 14:42:09 +0100
committerAndy Nichols <andy.nichols@digia.com>2012-11-17 15:37:21 +0100
commit2246c0150c0f28a6ca9803ca2c454b2492030b8b (patch)
treebd59941716229312c224450c12db1f40dfd21248 /src/plugins/platforms/wayland/gl_integration
parent41c62a3b93869e2ea267e016aa4c293d15482c0b (diff)
Initial implementation of decorations for EGL windows.
Change-Id: I7521e583bf18f3690ecc6baacd05a5e92e9fd890 Reviewed-by: Samuel Rødal <samuel.rodal@digia.com> Reviewed-by: Andy Nichols <andy.nichols@digia.com>
Diffstat (limited to 'src/plugins/platforms/wayland/gl_integration')
-rw-r--r--src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandegldecoration.cpp65
-rw-r--r--src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandegldecoration.h59
-rw-r--r--src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandeglwindow.cpp72
-rw-r--r--src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandeglwindow.h12
-rw-r--r--src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandglcontext.cpp96
-rw-r--r--src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandglcontext.h4
-rw-r--r--src/plugins/platforms/wayland/gl_integration/wayland_egl/wayland_egl.pri6
7 files changed, 303 insertions, 11 deletions
diff --git a/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandegldecoration.cpp b/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandegldecoration.cpp
new file mode 100644
index 000000000..5cf5239a8
--- /dev/null
+++ b/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandegldecoration.cpp
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwaylandegldecoration.h"
+
+#include "qwaylandeglwindow.h"
+
+#include <QtGui/QPainter>
+#include <QtGui/QOpenGLPaintDevice>
+
+QWaylandEglDecoration::QWaylandEglDecoration(QWaylandEglWindow *window)
+ : QWaylandDecoration(window)
+{
+}
+
+QWaylandEglDecoration::~QWaylandEglDecoration()
+{
+}
+
+void QWaylandEglDecoration::paintDecoration()
+{
+ glClearColor(backgroundColor().redF(), backgroundColor().greenF(), backgroundColor().blueF(), backgroundColor().alphaF());
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ QOpenGLPaintDevice device(window()->frameGeometry().size());
+ paint(&device);
+}
diff --git a/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandegldecoration.h b/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandegldecoration.h
new file mode 100644
index 000000000..c1ef6d54a
--- /dev/null
+++ b/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandegldecoration.h
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDEGLDECORATION_H
+#define QWAYLANDEGLDECORATION_H
+
+#include "qwaylanddecoration.h"
+
+class QWaylandEglWindow;
+
+class QWaylandEglDecoration : public QWaylandDecoration
+{
+public:
+ QWaylandEglDecoration(QWaylandEglWindow *window);
+ ~QWaylandEglDecoration();
+
+ void paintDecoration();
+
+};
+
+#endif // QWAYLANDEGLDECORATION_H
diff --git a/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandeglwindow.cpp b/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandeglwindow.cpp
index e8599e41e..73768ddd6 100644
--- a/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandeglwindow.cpp
+++ b/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandeglwindow.cpp
@@ -43,11 +43,15 @@
#include "qwaylandscreen.h"
#include "qwaylandglcontext.h"
+#include "qwaylandegldecoration.h"
#include <QtPlatformSupport/private/qeglconvenience_p.h>
+#include <QDebug>
#include <QtGui/QWindow>
#include <qpa/qwindowsysteminterface.h>
+#include <QOpenGLFramebufferObject>
+#include <QOpenGLContext>
#ifdef QT_WAYLAND_WINDOWMANAGER_SUPPORT
#include "windowmanager_integration/qwaylandwindowmanagerintegration.h"
@@ -56,11 +60,14 @@
QWaylandEglWindow::QWaylandEglWindow(QWindow *window)
: QWaylandWindow(window)
, m_eglIntegration(static_cast<QWaylandEglIntegration *>(mDisplay->eglIntegration()))
- , m_waylandEglWindow(wl_egl_window_create(mSurface,window->width(),window->height()))
+ , m_waylandEglWindow(0)
, m_eglSurface(0)
, m_eglConfig(0)
+ , m_contentFBO(0)
+ , m_resize(false)
, m_format(window->format())
{
+ setGeometry(window->geometry());
}
QWaylandEglWindow::~QWaylandEglWindow()
@@ -71,6 +78,8 @@ QWaylandEglWindow::~QWaylandEglWindow()
}
wl_egl_window_destroy(m_waylandEglWindow);
+
+ delete m_contentFBO;
}
QWaylandWindow::WindowType QWaylandEglWindow::windowType() const
@@ -80,14 +89,32 @@ QWaylandWindow::WindowType QWaylandEglWindow::windowType() const
void QWaylandEglWindow::setGeometry(const QRect &rect)
{
- int current_width, current_height;
- wl_egl_window_get_attached_size(m_waylandEglWindow,&current_width,&current_height);
- if (current_width != rect.width() || current_height != rect.height()) {
- waitForFrameSync();
- wl_egl_window_resize(m_waylandEglWindow, rect.width(), rect.height(), 0, 0);
+ createDecoration();
+ QMargins margins = frameMargins();
+ QSize sizeWithMargins = rect.size() + QSize(margins.left() + margins.right(), margins.top() + margins.bottom());
+
+ if (m_waylandEglWindow) {
+ int current_width, current_height;
+ wl_egl_window_get_attached_size(m_waylandEglWindow,&current_width,&current_height);
+ if (current_width != sizeWithMargins.width() || current_height != sizeWithMargins.height()) {
+ waitForFrameSync();
+ wl_egl_window_resize(m_waylandEglWindow, sizeWithMargins.width(), sizeWithMargins.height(), 0, 0);
+
+ m_resize = true;
+ }
+ } else {
+ m_waylandEglWindow = wl_egl_window_create(mSurface, sizeWithMargins.width(), sizeWithMargins.height());
}
QWaylandWindow::setGeometry(rect);
}
+
+QRect QWaylandEglWindow::contentsRect() const
+{
+ QRect r = geometry();
+ QMargins m = frameMargins();
+ return QRect(m.left(), m.bottom(), r.width(), r.height());
+}
+
QSurfaceFormat QWaylandEglWindow::format() const
{
return m_format;
@@ -106,3 +133,36 @@ EGLSurface QWaylandEglWindow::eglSurface() const
return m_eglSurface;
}
+GLuint QWaylandEglWindow::contentFBO() const
+{
+ if (!decoration())
+ return 0;
+
+ if (m_resize || !m_contentFBO) {
+ QOpenGLFramebufferObject *old = m_contentFBO;
+ m_contentFBO = new QOpenGLFramebufferObject(geometry().width(), geometry().height(), QOpenGLFramebufferObject::CombinedDepthStencil);
+
+ delete old;
+ m_resize = false;
+ }
+
+ return m_contentFBO->handle();
+}
+
+GLuint QWaylandEglWindow::contentTexture() const
+{
+ return m_contentFBO->texture();
+}
+
+void QWaylandEglWindow::bindContentFBO()
+{
+ if (decoration()) {
+ contentFBO();
+ m_contentFBO->bind();
+ }
+}
+
+void QWaylandEglWindow::createDecorationInstance()
+{
+ new QWaylandEglDecoration(this);
+}
diff --git a/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandeglwindow.h b/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandeglwindow.h
index 66b3d619c..1e1b99925 100644
--- a/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandeglwindow.h
+++ b/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandeglwindow.h
@@ -47,6 +47,7 @@
#include "qwaylandeglintegration.h"
class QWaylandGLContext;
+class QOpenGLFramebufferObject;
class QWaylandEglWindow : public QWaylandWindow
{
@@ -56,10 +57,19 @@ public:
WindowType windowType() const;
void setGeometry(const QRect &rect);
+ QRect contentsRect() const;
+
EGLSurface eglSurface() const;
+ GLuint contentFBO() const;
+ GLuint contentTexture() const;
QSurfaceFormat format() const;
+ void bindContentFBO();
+
+protected:
+ void createDecorationInstance();
+
private:
QWaylandEglIntegration *m_eglIntegration;
struct wl_egl_window *m_waylandEglWindow;
@@ -68,6 +78,8 @@ private:
mutable EGLSurface m_eglSurface;
mutable EGLConfig m_eglConfig;
+ mutable QOpenGLFramebufferObject *m_contentFBO;
+ mutable bool m_resize;
QSurfaceFormat m_format;
};
diff --git a/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandglcontext.cpp b/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandglcontext.cpp
index c869aaee7..f9ad280f7 100644
--- a/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandglcontext.cpp
+++ b/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandglcontext.cpp
@@ -44,17 +44,22 @@
#include "qwaylanddisplay.h"
#include "qwaylandwindow.h"
#include "qwaylandeglwindow.h"
+#include "qwaylanddecoration.h"
+#include <QDebug>
#include <QtPlatformSupport/private/qeglconvenience_p.h>
+#include <QtGui/private/qopenglcontext_p.h>
#include <qpa/qplatformopenglcontext.h>
#include <QtGui/QSurfaceFormat>
+#include <QtGui/QOpenGLShaderProgram>
QWaylandGLContext::QWaylandGLContext(EGLDisplay eglDisplay, const QSurfaceFormat &format, QPlatformOpenGLContext *share)
: QPlatformOpenGLContext()
, m_eglDisplay(eglDisplay)
, m_config(q_configFromGLFormat(m_eglDisplay, format, true))
, m_format(q_glFormatFromConfig(m_eglDisplay, m_config))
+ , m_blitProgram(0)
{
m_shareEGLContext = share ? static_cast<QWaylandGLContext *>(share)->eglContext() : EGL_NO_CONTEXT;
@@ -75,13 +80,23 @@ QWaylandGLContext::QWaylandGLContext(EGLDisplay eglDisplay, const QSurfaceFormat
QWaylandGLContext::~QWaylandGLContext()
{
+ delete m_blitProgram;
eglDestroyContext(m_eglDisplay, m_context);
}
bool QWaylandGLContext::makeCurrent(QPlatformSurface *surface)
{
- EGLSurface eglSurface = static_cast<QWaylandEglWindow *>(surface)->eglSurface();
- return eglMakeCurrent(m_eglDisplay, eglSurface, eglSurface, m_context);
+ QWaylandEglWindow *window = static_cast<QWaylandEglWindow *>(surface);
+ EGLSurface eglSurface = window->eglSurface();
+ if (!eglMakeCurrent(m_eglDisplay, eglSurface, eglSurface, m_context))
+ return false;
+
+ // FIXME: remove this as soon as https://codereview.qt-project.org/#change,38879 is merged
+ QOpenGLContextPrivate::setCurrentContext(context());
+
+ window->bindContentFBO();
+
+ return true;
}
void QWaylandGLContext::doneCurrent()
@@ -91,10 +106,85 @@ void QWaylandGLContext::doneCurrent()
void QWaylandGLContext::swapBuffers(QPlatformSurface *surface)
{
- EGLSurface eglSurface = static_cast<QWaylandEglWindow *>(surface)->eglSurface();
+ QWaylandEglWindow *window = static_cast<QWaylandEglWindow *>(surface);
+ EGLSurface eglSurface = window->eglSurface();
+
+ if (window->decoration()) {
+ makeCurrent(surface);
+
+ if (!m_blitProgram) {
+ m_blitProgram = new QOpenGLShaderProgram();
+ m_blitProgram->addShaderFromSourceCode(QOpenGLShader::Vertex, "attribute vec4 position;\n\
+ attribute vec4 texCoords;\n\
+ varying vec2 outTexCoords;\n\
+ void main()\n\
+ {\n\
+ gl_Position = position;\n\
+ outTexCoords = texCoords.xy;\n\
+ }");
+ m_blitProgram->addShaderFromSourceCode(QOpenGLShader::Fragment, "varying vec2 outTexCoords;\n\
+ uniform sampler2D texture;\n\
+ void main()\n\
+ {\n\
+ gl_FragColor = texture2D(texture, outTexCoords);\n\
+ }");
+
+ if (!m_blitProgram->link()) {
+ qDebug() << "Shader Program link failed.";
+ qDebug() << m_blitProgram->log();
+ }
+ }
+
+ glDisable(GL_DEPTH_TEST);
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+ if (window->decoration())
+ window->decoration()->paintDecoration();
+
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, window->contentTexture());
+ QRect r = window->contentsRect();
+ glViewport(r.x(), r.y(), r.width(), r.height());
+
+ static const GLfloat squareVertices[] = {
+ -1.f, -1.f,
+ 1.0f, -1.f,
+ -1.f, 1.0f,
+ 1.0f, 1.0f,
+ };
+ static const GLfloat textureVertices[] = {
+ 0.0f, 0.0f,
+ 1.0f, 0.0f,
+ 0.0f, 1.0f,
+ 1.0f, 1.0f,
+ };
+
+ m_blitProgram->bind();
+
+ m_blitProgram->setUniformValue("texture", 0);
+
+ m_blitProgram->enableAttributeArray("position");
+ m_blitProgram->enableAttributeArray("texCoords");
+ m_blitProgram->setAttributeArray("position", squareVertices, 2);
+ m_blitProgram->setAttributeArray("texCoords", textureVertices, 2);
+
+ m_blitProgram->bind();
+
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+ m_blitProgram->disableAttributeArray("position");
+ m_blitProgram->disableAttributeArray("texCoords");
+ m_blitProgram->release();
+ }
+
eglSwapBuffers(m_eglDisplay, eglSurface);
}
+GLuint QWaylandGLContext::defaultFramebufferObject(QPlatformSurface *surface) const
+{
+ return static_cast<QWaylandEglWindow *>(surface)->contentFBO();
+}
+
bool QWaylandGLContext::isSharing() const
{
return m_shareEGLContext != EGL_NO_CONTEXT;
diff --git a/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandglcontext.h b/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandglcontext.h
index f30b6108f..767f188fb 100644
--- a/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandglcontext.h
+++ b/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandglcontext.h
@@ -50,6 +50,7 @@
class QWaylandWindow;
class QWaylandGLWindowSurface;
+class QOpenGLShaderProgram;
class QWaylandGLContext : public QPlatformOpenGLContext {
public:
@@ -61,6 +62,8 @@ public:
bool makeCurrent(QPlatformSurface *surface);
void doneCurrent();
+ GLuint defaultFramebufferObject(QPlatformSurface *surface) const;
+
bool isSharing() const;
bool isValid() const;
@@ -78,6 +81,7 @@ private:
EGLContext m_shareEGLContext;
EGLConfig m_config;
QSurfaceFormat m_format;
+ QOpenGLShaderProgram *m_blitProgram;
};
diff --git a/src/plugins/platforms/wayland/gl_integration/wayland_egl/wayland_egl.pri b/src/plugins/platforms/wayland/gl_integration/wayland_egl/wayland_egl.pri
index 5bda0074e..08f42b43d 100644
--- a/src/plugins/platforms/wayland/gl_integration/wayland_egl/wayland_egl.pri
+++ b/src/plugins/platforms/wayland/gl_integration/wayland_egl/wayland_egl.pri
@@ -8,8 +8,10 @@
INCLUDEPATH += $$PWD
SOURCES += $$PWD/qwaylandeglintegration.cpp \
$$PWD/qwaylandglcontext.cpp \
- $$PWD/qwaylandeglwindow.cpp
+ $$PWD/qwaylandeglwindow.cpp \
+ $$PWD/qwaylandegldecoration.cpp
HEADERS += $$PWD/qwaylandeglintegration.h \
$$PWD/qwaylandglcontext.h \
- $$PWD/qwaylandeglwindow.h
+ $$PWD/qwaylandeglwindow.h \
+ $$PWD/qwaylandegldecoration.h