eglfs: remove support for widget rendering using opengl paint engine
[profile/ivi/qtbase.git] / src / plugins / platforms / eglfs / qeglfsbackingstore.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the plugins of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qeglfsbackingstore.h"
43 #include "qeglfscursor.h"
44
45 #include <QtGui/QOpenGLContext>
46 #include <QtGui/QOpenGLPaintDevice>
47 #include <QtGui/QOpenGLShaderProgram>
48
49 #include <QtGui/QScreen>
50
51 QT_BEGIN_NAMESPACE
52
53 QEglFSBackingStore::QEglFSBackingStore(QWindow *window)
54     : QPlatformBackingStore(window)
55     , m_context(new QOpenGLContext)
56     , m_texture(0)
57     , m_program(0)
58 {
59     m_context->setFormat(window->requestedFormat());
60     m_context->setScreen(window->screen());
61     m_context->create();
62 }
63
64 QEglFSBackingStore::~QEglFSBackingStore()
65 {
66     delete m_context;
67 }
68
69 QPaintDevice *QEglFSBackingStore::paintDevice()
70 {
71     return &m_image;
72 }
73
74 void QEglFSBackingStore::flush(QWindow *window, const QRegion &region, const QPoint &offset)
75 {
76     Q_UNUSED(region);
77     Q_UNUSED(offset);
78
79 #ifdef QEGL_EXTRA_DEBUG
80     qWarning("QEglBackingStore::flush %p", window);
81 #endif
82
83     if (!m_program) {
84         static const char *textureVertexProgram =
85             "attribute highp vec2 vertexCoordEntry;\n"
86             "attribute highp vec2 textureCoordEntry;\n"
87             "varying highp vec2 textureCoord;\n"
88             "void main() {\n"
89             "   textureCoord = textureCoordEntry;\n"
90             "   gl_Position = vec4(vertexCoordEntry, 0.0, 1.0);\n"
91             "}\n";
92
93         static const char *textureFragmentProgram =
94             "uniform sampler2D texture;\n"
95             "varying highp vec2 textureCoord;\n"
96             "void main() {\n"
97             "   gl_FragColor = texture2D(texture, textureCoord).bgra;\n"
98             "}\n";
99
100         m_program = new QOpenGLShaderProgram;
101
102         m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, textureVertexProgram);
103         m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, textureFragmentProgram);
104         m_program->link();
105
106         m_vertexCoordEntry = m_program->attributeLocation("vertexCoordEntry");
107         m_textureCoordEntry = m_program->attributeLocation("textureCoordEntry");
108     }
109
110     m_program->bind();
111
112     const GLfloat textureCoordinates[] = {
113         0, 1,
114         1, 1,
115         1, 0,
116         0, 0
117     };
118
119     QRectF r = window->geometry();
120     QRectF sr = window->screen()->geometry();
121
122     GLfloat x1 = (r.left() / sr.width()) * 2 - 1;
123     GLfloat x2 = (r.right() / sr.width()) * 2 - 1;
124     GLfloat y1 = (r.top() / sr.height()) * 2 - 1;
125     GLfloat y2 = (r.bottom() / sr.height()) * 2 - 1;
126
127     const GLfloat vertexCoordinates[] = {
128         x1, y1,
129         x2, y1,
130         x2, y2,
131         x1, y2
132     };
133
134     glEnableVertexAttribArray(m_vertexCoordEntry);
135     glEnableVertexAttribArray(m_textureCoordEntry);
136
137     glVertexAttribPointer(m_vertexCoordEntry, 2, GL_FLOAT, GL_FALSE, 0, vertexCoordinates);
138     glVertexAttribPointer(m_textureCoordEntry, 2, GL_FLOAT, GL_FALSE, 0, textureCoordinates);
139
140     glBindTexture(GL_TEXTURE_2D, m_texture);
141
142     if (!m_dirty.isNull()) {
143         QRect imageRect = m_image.rect();
144
145         QRegion fixed;
146         foreach (const QRect &rect, m_dirty.rects()) {
147             // intersect with image rect to be sure
148             QRect r = imageRect & rect;
149
150             // if the rect is wide enough it's cheaper to just
151             // extend it instead of doing an image copy
152             if (r.width() >= imageRect.width() / 2) {
153                 r.setX(0);
154                 r.setWidth(imageRect.width());
155             }
156
157             fixed |= r;
158         }
159
160         foreach (const QRect &rect, fixed.rects()) {
161             // if the sub-rect is full-width we can pass the image data directly to
162             // OpenGL instead of copying, since there's no gap between scanlines
163             if (rect.width() == imageRect.width()) {
164                 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, rect.y(), rect.width(), rect.height(), GL_RGBA, GL_UNSIGNED_BYTE, m_image.constScanLine(rect.y()));
165             } else {
166                 glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x(), rect.y(), rect.width(), rect.height(), GL_RGBA, GL_UNSIGNED_BYTE,
167                     m_image.copy(rect).constBits());
168             }
169         }
170
171         m_dirty = QRegion();
172     }
173
174     glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
175
176     m_program->release();
177     glBindTexture(GL_TEXTURE_2D, 0);
178     glDisableVertexAttribArray(m_vertexCoordEntry);
179     glDisableVertexAttribArray(m_textureCoordEntry);
180
181     // draw the cursor
182     if (QEglFSCursor *cursor = static_cast<QEglFSCursor *>(window->screen()->handle()->cursor()))
183         cursor->render();
184
185     m_context->swapBuffers(window);
186 }
187
188 void QEglFSBackingStore::makeCurrent()
189 {
190     // needed to prevent QOpenGLContext::makeCurrent() from failing
191     window()->setSurfaceType(QSurface::OpenGLSurface);
192
193     m_context->makeCurrent(window());
194 }
195
196 void QEglFSBackingStore::beginPaint(const QRegion &rgn)
197 {
198     makeCurrent();
199
200     m_dirty = m_dirty | rgn;
201 }
202
203 void QEglFSBackingStore::endPaint()
204 {
205 }
206
207 void QEglFSBackingStore::resize(const QSize &size, const QRegion &staticContents)
208 {
209     Q_UNUSED(staticContents);
210
211     m_image = QImage(size, QImage::Format_RGB32);
212     makeCurrent();
213     if (m_texture)
214         glDeleteTextures(1, &m_texture);
215     glGenTextures(1, &m_texture);
216     glBindTexture(GL_TEXTURE_2D, m_texture);
217     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
218     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
219     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
220     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
221
222     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width(), size.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
223 }
224
225 QT_END_NAMESPACE