1 /****************************************************************************
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
6 ** This file is part of the plugins of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
40 ****************************************************************************/
42 #include "qwaylandreadbackeglcontext.h"
44 #include <qpa/qplatformsupport/eglconvenience/qeglconvenience_p.h.h>
46 #include <QtCore/QDebug>
47 #include <QtGui/QWindowContext>
49 #include "qwaylandshmsurface.h"
52 static inline void qgl_byteSwapImage(QImage &img, GLenum pixel_type)
54 const int width = img.width();
55 const int height = img.height();
57 if (pixel_type == GL_UNSIGNED_INT_8_8_8_8_REV
58 || (pixel_type == GL_UNSIGNED_BYTE && QSysInfo::ByteOrder == QSysInfo::LittleEndian))
60 for (int i = 0; i < height; ++i) {
61 uint *p = (uint *) img.scanLine(i);
62 for (int x = 0; x < width; ++x)
63 p[x] = ((p[x] << 16) & 0xff0000) | ((p[x] >> 16) & 0xff) | (p[x] & 0xff00ff00);
66 for (int i = 0; i < height; ++i) {
67 uint *p = (uint *) img.scanLine(i);
68 for (int x = 0; x < width; ++x)
69 p[x] = (p[x] << 8) | ((p[x] >> 24) & 0xff);
74 QWaylandReadbackEglContext::QWaylandReadbackEglContext(QWaylandReadbackEglIntegration *eglIntegration, QWaylandReadbackEglWindow *window)
75 : mEglIntegration(eglIntegration)
79 , mConfig(q_configFromQWindowFormat(eglIntegration->eglDisplay(),window->window()->requestedWindowFormat(),true,EGL_PIXMAP_BIT))
80 , mPixmapSurface(EGL_NO_SURFACE)
82 QVector<EGLint> eglContextAttrs;
83 eglContextAttrs.append(EGL_CONTEXT_CLIENT_VERSION);
84 eglContextAttrs.append(2);
85 eglContextAttrs.append(EGL_NONE);
87 mContext = eglCreateContext(eglIntegration->eglDisplay(),mConfig,0,eglContextAttrs.constData());
92 QWaylandReadbackEglContext::~QWaylandReadbackEglContext()
94 eglDestroyContext(mEglIntegration->eglDisplay(),mContext);
97 void QWaylandReadbackEglContext::makeCurrent()
99 mWindow->waitForFrameSync();
101 eglMakeCurrent(mEglIntegration->eglDisplay(),mPixmapSurface,mPixmapSurface,mContext);
104 void QWaylandReadbackEglContext::doneCurrent()
106 QPlatformOpenGLContext::doneCurrent();
107 eglMakeCurrent(mEglIntegration->eglDisplay(),EGL_NO_SURFACE,EGL_NO_SURFACE,EGL_NO_CONTEXT);
110 void QWaylandReadbackEglContext::swapBuffers()
112 eglSwapBuffers(mEglIntegration->eglDisplay(),mPixmapSurface);
114 if (QWindowContext::currentContext()->handle() != this) {
118 QSize size = mWindow->geometry().size();
120 QImage img(size,QImage::Format_ARGB32);
121 const uchar *constBits = img.bits();
122 void *pixels = const_cast<uchar *>(constBits);
124 glReadPixels(0,0, size.width(), size.height(), GL_RGBA,GL_UNSIGNED_BYTE, pixels);
126 img = img.mirrored();
127 qgl_byteSwapImage(img,GL_UNSIGNED_INT_8_8_8_8_REV);
128 constBits = img.bits();
130 const uchar *constDstBits = mBuffer->image()->bits();
131 uchar *dstBits = const_cast<uchar *>(constDstBits);
132 memcpy(dstBits,constBits,(img.width()*4) * img.height());
135 mWindow->damage(QRegion(QRect(QPoint(0,0),size)));
138 void * QWaylandReadbackEglContext::getProcAddress(const QString &procName)
140 return (void *) eglGetProcAddress(procName.toLatin1().data());
143 QWindowFormat QWaylandReadbackEglContext::windowFormat() const
145 return q_windowFormatFromConfig(mEglIntegration->eglDisplay(),mConfig);
148 void QWaylandReadbackEglContext::geometryChanged()
150 QSize size(mWindow->geometry().size());
151 if (size.isEmpty()) {
152 //QGLWidget wants a context for a window without geometry
156 mWindow->waitForFrameSync();
160 XFreePixmap(mEglIntegration->xDisplay(),mPixmap);
162 mBuffer = new QWaylandShmBuffer(mEglIntegration->waylandDisplay(),size,QImage::Format_ARGB32);
163 mWindow->attach(mBuffer);
164 mPixmap = XCreatePixmap(mEglIntegration->xDisplay(),mEglIntegration->rootWindow(),size.width(),size.height(),mEglIntegration->depth());
165 XSync(mEglIntegration->xDisplay(),False);
167 mPixmapSurface = eglCreatePixmapSurface(mEglIntegration->eglDisplay(),mConfig,mPixmap,0);
168 if (mPixmapSurface == EGL_NO_SURFACE) {
169 qDebug() << "Could not make egl surface out of pixmap :(";