Change copyrights from Nokia to Digia
[profile/ivi/qtwayland.git] / src / plugins / platforms / wayland / gl_integration / readback_egl / qwaylandreadbackeglcontext.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the plugins of the Qt Toolkit.
7 **
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.
16 **
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.
24 **
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.
28 **
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.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qwaylandreadbackeglcontext.h"
43
44 #include <qpa/qplatformsupport/eglconvenience/qeglconvenience_p.h.h>
45
46 #include <QtCore/QDebug>
47 #include <QtGui/QWindowContext>
48
49 #include "qwaylandshmsurface.h"
50
51
52 static inline void qgl_byteSwapImage(QImage &img, GLenum pixel_type)
53 {
54     const int width = img.width();
55     const int height = img.height();
56
57     if (pixel_type == GL_UNSIGNED_INT_8_8_8_8_REV
58         || (pixel_type == GL_UNSIGNED_BYTE && QSysInfo::ByteOrder == QSysInfo::LittleEndian))
59     {
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);
64         }
65     } else {
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);
70         }
71     }
72 }
73
74 QWaylandReadbackEglContext::QWaylandReadbackEglContext(QWaylandReadbackEglIntegration *eglIntegration, QWaylandReadbackEglWindow *window)
75     : mEglIntegration(eglIntegration)
76     , mWindow(window)
77     , mBuffer(0)
78     , mPixmap(0)
79     , mConfig(q_configFromQWindowFormat(eglIntegration->eglDisplay(),window->window()->requestedWindowFormat(),true,EGL_PIXMAP_BIT))
80     , mPixmapSurface(EGL_NO_SURFACE)
81 {
82     QVector<EGLint> eglContextAttrs;
83     eglContextAttrs.append(EGL_CONTEXT_CLIENT_VERSION);
84     eglContextAttrs.append(2);
85     eglContextAttrs.append(EGL_NONE);
86
87     mContext = eglCreateContext(eglIntegration->eglDisplay(),mConfig,0,eglContextAttrs.constData());
88
89     geometryChanged();
90 }
91
92 QWaylandReadbackEglContext::~QWaylandReadbackEglContext()
93 {
94     eglDestroyContext(mEglIntegration->eglDisplay(),mContext);
95 }
96
97 void QWaylandReadbackEglContext::makeCurrent()
98 {
99     mWindow->waitForFrameSync();
100
101     eglMakeCurrent(mEglIntegration->eglDisplay(),mPixmapSurface,mPixmapSurface,mContext);
102 }
103
104 void QWaylandReadbackEglContext::doneCurrent()
105 {
106     QPlatformOpenGLContext::doneCurrent();
107     eglMakeCurrent(mEglIntegration->eglDisplay(),EGL_NO_SURFACE,EGL_NO_SURFACE,EGL_NO_CONTEXT);
108 }
109
110 void QWaylandReadbackEglContext::swapBuffers()
111 {
112     eglSwapBuffers(mEglIntegration->eglDisplay(),mPixmapSurface);
113
114     if (QWindowContext::currentContext()->handle() != this) {
115         makeCurrent();
116     }
117
118     QSize size = mWindow->geometry().size();
119
120     QImage img(size,QImage::Format_ARGB32);
121     const uchar *constBits = img.bits();
122     void *pixels = const_cast<uchar *>(constBits);
123
124     glReadPixels(0,0, size.width(), size.height(), GL_RGBA,GL_UNSIGNED_BYTE, pixels);
125
126     img = img.mirrored();
127     qgl_byteSwapImage(img,GL_UNSIGNED_INT_8_8_8_8_REV);
128     constBits = img.bits();
129
130     const uchar *constDstBits = mBuffer->image()->bits();
131     uchar *dstBits = const_cast<uchar *>(constDstBits);
132     memcpy(dstBits,constBits,(img.width()*4) * img.height());
133
134
135     mWindow->damage(QRegion(QRect(QPoint(0,0),size)));
136 }
137
138 void * QWaylandReadbackEglContext::getProcAddress(const QString &procName)
139 {
140     return (void *) eglGetProcAddress(procName.toLatin1().data());
141 }
142
143 QWindowFormat QWaylandReadbackEglContext::windowFormat() const
144 {
145     return q_windowFormatFromConfig(mEglIntegration->eglDisplay(),mConfig);
146 }
147
148 void QWaylandReadbackEglContext::geometryChanged()
149 {
150     QSize size(mWindow->geometry().size());
151     if (size.isEmpty()) {
152         //QGLWidget wants a context for a window without geometry
153         size = QSize(1,1);
154     }
155
156     mWindow->waitForFrameSync();
157
158     delete mBuffer;
159     if (mPixmap)
160         XFreePixmap(mEglIntegration->xDisplay(),mPixmap);
161
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);
166
167     mPixmapSurface = eglCreatePixmapSurface(mEglIntegration->eglDisplay(),mConfig,mPixmap,0);
168     if (mPixmapSurface == EGL_NO_SURFACE) {
169         qDebug() << "Could not make egl surface out of pixmap :(";
170     }
171 }