qopengltextureblitter.cpp

Absolute File Name:/home/qt/qt5_coco/qt5/qtbase/src/gui/opengl/qopengltextureblitter.cpp
Source codeSwitch to Preprocessed file
LineSourceCount
1/****************************************************************************-
2**-
3** Copyright (C) 2016 The Qt Company Ltd.-
4** Contact: https://www.qt.io/licensing/-
5**-
6** This file is part of the QtGui module 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 The Qt Company. For licensing terms-
14** and conditions see https://www.qt.io/terms-conditions. For further-
15** information use the contact form at https://www.qt.io/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 3 as published by the Free Software-
20** Foundation and appearing in the file LICENSE.LGPL3 included in the-
21** packaging of this file. Please review the following information to-
22** ensure the GNU Lesser General Public License version 3 requirements-
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.-
24**-
25** GNU General Public License Usage-
26** Alternatively, this file may be used under the terms of the GNU-
27** General Public License version 2.0 or (at your option) the GNU General-
28** Public license version 3 or any later version approved by the KDE Free-
29** Qt Foundation. The licenses are as published by the Free Software-
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3-
31** included in the packaging of this file. Please review the following-
32** information to ensure the GNU General Public License requirements will-
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and-
34** https://www.gnu.org/licenses/gpl-3.0.html.-
35**-
36** $QT_END_LICENSE$-
37**-
38****************************************************************************/-
39-
40#include "qopengltextureblitter_p.h"-
41-
42#include <QtGui/QOpenGLBuffer>-
43#include <QtGui/QOpenGLShaderProgram>-
44#include <QtGui/QOpenGLVertexArrayObject>-
45#include <QtGui/QOpenGLContext>-
46#include <QtGui/QOpenGLFunctions>-
47-
48#ifndef GL_TEXTURE_EXTERNAL_OES-
49#define GL_TEXTURE_EXTERNAL_OES 0x8D65-
50#endif-
51-
52QT_BEGIN_NAMESPACE-
53-
54static const char vertex_shader150[] =-
55 "#version 150 core\n"-
56 "in vec3 vertexCoord;"-
57 "in vec2 textureCoord;"-
58 "out vec2 uv;"-
59 "uniform mat4 vertexTransform;"-
60 "uniform mat3 textureTransform;"-
61 "void main() {"-
62 " uv = (textureTransform * vec3(textureCoord,1.0)).xy;"-
63 " gl_Position = vertexTransform * vec4(vertexCoord,1.0);"-
64 "}";-
65-
66static const char fragment_shader150[] =-
67 "#version 150 core\n"-
68 "in vec2 uv;"-
69 "out vec4 fragcolor;"-
70 "uniform sampler2D textureSampler;"-
71 "uniform bool swizzle;"-
72 "uniform float opacity;"-
73 "void main() {"-
74 " vec4 tmpFragColor = texture(textureSampler, uv);"-
75 " tmpFragColor.a *= opacity;"-
76 " fragcolor = swizzle ? tmpFragColor.bgra : tmpFragColor;"-
77 "}";-
78-
79static const char vertex_shader[] =-
80 "attribute highp vec3 vertexCoord;"-
81 "attribute highp vec2 textureCoord;"-
82 "varying highp vec2 uv;"-
83 "uniform highp mat4 vertexTransform;"-
84 "uniform highp mat3 textureTransform;"-
85 "void main() {"-
86 " uv = (textureTransform * vec3(textureCoord,1.0)).xy;"-
87 " gl_Position = vertexTransform * vec4(vertexCoord,1.0);"-
88 "}";-
89-
90static const char fragment_shader[] =-
91 "varying highp vec2 uv;"-
92 "uniform sampler2D textureSampler;"-
93 "uniform bool swizzle;"-
94 "uniform highp float opacity;"-
95 "void main() {"-
96 " highp vec4 tmpFragColor = texture2D(textureSampler,uv);"-
97 " tmpFragColor.a *= opacity;"-
98 " gl_FragColor = swizzle ? tmpFragColor.bgra : tmpFragColor;"-
99 "}";-
100-
101static const char fragment_shader_external_oes[] =-
102 "#extension GL_OES_EGL_image_external : require\n"-
103 "varying highp vec2 uv;"-
104 "uniform samplerExternalOES textureSampler;\n"-
105 "uniform bool swizzle;"-
106 "uniform highp float opacity;"-
107 "void main() {"-
108 " highp vec4 tmpFragColor = texture2D(textureSampler, uv);"-
109 " tmpFragColor.a *= opacity;"-
110 " gl_FragColor = swizzle ? tmpFragColor.bgra : tmpFragColor;"-
111 "}";-
112-
113static const GLfloat vertex_buffer_data[] = {-
114 -1,-1, 0,-
115 -1, 1, 0,-
116 1,-1, 0,-
117 -1, 1, 0,-
118 1,-1, 0,-
119 1, 1, 0-
120};-
121-
122static const GLfloat texture_buffer_data[] = {-
123 0, 0,-
124 0, 1,-
125 1, 0,-
126 0, 1,-
127 1, 0,-
128 1, 1-
129};-
130-
131class TextureBinder-
132{-
133public:-
134 TextureBinder(GLenum target, GLuint textureId) : m_target(target)-
135 {-
136 QOpenGLContext::currentContext()->functions()->glBindTexture(m_target, textureId);-
137 }
never executed: end of block
0
138 ~TextureBinder()-
139 {-
140 QOpenGLContext::currentContext()->functions()->glBindTexture(m_target, 0);-
141 }
never executed: end of block
0
142-
143private:-
144 GLenum m_target;-
145};-
146-
147class QOpenGLTextureBlitterPrivate-
148{-
149public:-
150 enum TextureMatrixUniform {-
151 User,-
152 Identity,-
153 IdentityFlipped-
154 };-
155-
156 enum ProgramIndex {-
157 TEXTURE_2D,-
158 TEXTURE_EXTERNAL_OES-
159 };-
160-
161 QOpenGLTextureBlitterPrivate() :-
162 swizzle(false),-
163 opacity(1.0f),-
164 vao(new QOpenGLVertexArrayObject),-
165 currentTarget(TEXTURE_2D)-
166 { }
never executed: end of block
0
167-
168 bool buildProgram(ProgramIndex idx, const char *vs, const char *fs);-
169-
170 void blit(GLuint texture, const QMatrix4x4 &vertexTransform, const QMatrix3x3 &textureTransform);-
171 void blit(GLuint texture, const QMatrix4x4 &vertexTransform, QOpenGLTextureBlitter::Origin origin);-
172-
173 void prepareProgram(const QMatrix4x4 &vertexTransform);-
174-
175 QOpenGLBuffer vertexBuffer;-
176 QOpenGLBuffer textureBuffer;-
177 struct Program {-
178 Program() :-
179 vertexCoordAttribPos(0),-
180 vertexTransformUniformPos(0),-
181 textureCoordAttribPos(0),-
182 textureTransformUniformPos(0),-
183 swizzleUniformPos(0),-
184 opacityUniformPos(0),-
185 swizzle(false),-
186 opacity(0.0f),-
187 textureMatrixUniformState(User)-
188 { }
never executed: end of block
0
189 QScopedPointer<QOpenGLShaderProgram> glProgram;-
190 GLuint vertexCoordAttribPos;-
191 GLuint vertexTransformUniformPos;-
192 GLuint textureCoordAttribPos;-
193 GLuint textureTransformUniformPos;-
194 GLuint swizzleUniformPos;-
195 GLuint opacityUniformPos;-
196 bool swizzle;-
197 float opacity;-
198 TextureMatrixUniform textureMatrixUniformState;-
199 } programs[2];-
200 bool swizzle;-
201 float opacity;-
202 QScopedPointer<QOpenGLVertexArrayObject> vao;-
203 GLenum currentTarget;-
204};-
205-
206static inline QOpenGLTextureBlitterPrivate::ProgramIndex targetToProgramIndex(GLenum target)-
207{-
208 switch (target) {-
209 case GL_TEXTURE_2D:
never executed: case 0x0DE1:
0
210 return QOpenGLTextureBlitterPrivate::TEXTURE_2D;
never executed: return QOpenGLTextureBlitterPrivate::TEXTURE_2D;
0
211 case GL_TEXTURE_EXTERNAL_OES:
never executed: case 0x8D65:
0
212 return QOpenGLTextureBlitterPrivate::TEXTURE_EXTERNAL_OES;
never executed: return QOpenGLTextureBlitterPrivate::TEXTURE_EXTERNAL_OES;
0
213 default:
never executed: default:
0
214 qWarning("Unsupported texture target 0x%x", target);-
215 return QOpenGLTextureBlitterPrivate::TEXTURE_2D;
never executed: return QOpenGLTextureBlitterPrivate::TEXTURE_2D;
0
216 }-
217}-
218-
219void QOpenGLTextureBlitterPrivate::prepareProgram(const QMatrix4x4 &vertexTransform)-
220{-
221 Program *program = &programs[targetToProgramIndex(currentTarget)];-
222-
223 vertexBuffer.bind();-
224 program->glProgram->setAttributeBuffer(program->vertexCoordAttribPos, GL_FLOAT, 0, 3, 0);-
225 program->glProgram->enableAttributeArray(program->vertexCoordAttribPos);-
226 vertexBuffer.release();-
227-
228 program->glProgram->setUniformValue(program->vertexTransformUniformPos, vertexTransform);-
229-
230 textureBuffer.bind();-
231 program->glProgram->setAttributeBuffer(program->textureCoordAttribPos, GL_FLOAT, 0, 2, 0);-
232 program->glProgram->enableAttributeArray(program->textureCoordAttribPos);-
233 textureBuffer.release();-
234-
235 if (swizzle != program->swizzle) {
swizzle != program->swizzleDescription
TRUEnever evaluated
FALSEnever evaluated
0
236 program->glProgram->setUniformValue(program->swizzleUniformPos, swizzle);-
237 program->swizzle = swizzle;-
238 }
never executed: end of block
0
239-
240 if (opacity != program->opacity) {
opacity != program->opacityDescription
TRUEnever evaluated
FALSEnever evaluated
0
241 program->glProgram->setUniformValue(program->opacityUniformPos, opacity);-
242 program->opacity = opacity;-
243 }
never executed: end of block
0
244}
never executed: end of block
0
245-
246void QOpenGLTextureBlitterPrivate::blit(GLuint texture,-
247 const QMatrix4x4 &vertexTransform,-
248 const QMatrix3x3 &textureTransform)-
249{-
250 TextureBinder binder(currentTarget, texture);-
251 prepareProgram(vertexTransform);-
252-
253 Program *program = &programs[targetToProgramIndex(currentTarget)];-
254 program->glProgram->setUniformValue(program->textureTransformUniformPos, textureTransform);-
255 program->textureMatrixUniformState = User;-
256-
257 QOpenGLContext::currentContext()->functions()->glDrawArrays(GL_TRIANGLES, 0, 6);-
258}
never executed: end of block
0
259-
260void QOpenGLTextureBlitterPrivate::blit(GLuint texture,-
261 const QMatrix4x4 &vertexTransform,-
262 QOpenGLTextureBlitter::Origin origin)-
263{-
264 TextureBinder binder(currentTarget, texture);-
265 prepareProgram(vertexTransform);-
266-
267 Program *program = &programs[targetToProgramIndex(currentTarget)];-
268 if (origin == QOpenGLTextureBlitter::OriginTopLeft) {
origin == QOpe...:OriginTopLeftDescription
TRUEnever evaluated
FALSEnever evaluated
0
269 if (program->textureMatrixUniformState != IdentityFlipped) {
program->textu...dentityFlippedDescription
TRUEnever evaluated
FALSEnever evaluated
0
270 QMatrix3x3 flipped;-
271 flipped(1,1) = -1;-
272 flipped(1,2) = 1;-
273 program->glProgram->setUniformValue(program->textureTransformUniformPos, flipped);-
274 program->textureMatrixUniformState = IdentityFlipped;-
275 }
never executed: end of block
0
276 } else if (program->textureMatrixUniformState != Identity) {
never executed: end of block
program->textu...te != IdentityDescription
TRUEnever evaluated
FALSEnever evaluated
0
277 program->glProgram->setUniformValue(program->textureTransformUniformPos, QMatrix3x3());-
278 program->textureMatrixUniformState = Identity;-
279 }
never executed: end of block
0
280-
281 QOpenGLContext::currentContext()->functions()->glDrawArrays(GL_TRIANGLES, 0, 6);-
282}
never executed: end of block
0
283-
284bool QOpenGLTextureBlitterPrivate::buildProgram(ProgramIndex idx, const char *vs, const char *fs)-
285{-
286 Program *p = &programs[idx];-
287-
288 p->glProgram.reset(new QOpenGLShaderProgram);-
289-
290 p->glProgram->addShaderFromSourceCode(QOpenGLShader::Vertex, vs);-
291 p->glProgram->addShaderFromSourceCode(QOpenGLShader::Fragment, fs);-
292 p->glProgram->link();-
293 if (!p->glProgram->isLinked()) {
!p->glProgram->isLinked()Description
TRUEnever evaluated
FALSEnever evaluated
0
294 qWarning() << "Could not link shader program:\n" << p->glProgram->log();-
295 return false;
never executed: return false;
0
296 }-
297-
298 p->glProgram->bind();-
299-
300 p->vertexCoordAttribPos = p->glProgram->attributeLocation("vertexCoord");-
301 p->vertexTransformUniformPos = p->glProgram->uniformLocation("vertexTransform");-
302 p->textureCoordAttribPos = p->glProgram->attributeLocation("textureCoord");-
303 p->textureTransformUniformPos = p->glProgram->uniformLocation("textureTransform");-
304 p->swizzleUniformPos = p->glProgram->uniformLocation("swizzle");-
305 p->opacityUniformPos = p->glProgram->uniformLocation("opacity");-
306-
307 p->glProgram->setUniformValue(p->swizzleUniformPos, false);-
308-
309 return true;
never executed: return true;
0
310}-
311-
312QOpenGLTextureBlitter::QOpenGLTextureBlitter()-
313 : d_ptr(new QOpenGLTextureBlitterPrivate)-
314{-
315}
never executed: end of block
0
316-
317QOpenGLTextureBlitter::~QOpenGLTextureBlitter()-
318{-
319 destroy();-
320}
never executed: end of block
0
321-
322bool QOpenGLTextureBlitter::create()-
323{-
324 QOpenGLContext *currentContext = QOpenGLContext::currentContext();-
325 if (!currentContext)
!currentContextDescription
TRUEnever evaluated
FALSEnever evaluated
0
326 return false;
never executed: return false;
0
327-
328 Q_D(QOpenGLTextureBlitter);-
329-
330 if (d->programs[QOpenGLTextureBlitterPrivate::TEXTURE_2D].glProgram)
d->programs[QO..._2D].glProgramDescription
TRUEnever evaluated
FALSEnever evaluated
0
331 return true;
never executed: return true;
0
332-
333 QSurfaceFormat format = currentContext->format();-
334 if (format.profile() == QSurfaceFormat::CoreProfile && format.version() >= qMakePair(3,2)) {
format.profile...t::CoreProfileDescription
TRUEnever evaluated
FALSEnever evaluated
format.version...qMakePair(3,2)Description
TRUEnever evaluated
FALSEnever evaluated
0
335 if (!d->buildProgram(QOpenGLTextureBlitterPrivate::TEXTURE_2D, vertex_shader150, fragment_shader150))
!d->buildProgr...ent_shader150)Description
TRUEnever evaluated
FALSEnever evaluated
0
336 return false;
never executed: return false;
0
337 } else {
never executed: end of block
0
338 if (!d->buildProgram(QOpenGLTextureBlitterPrivate::TEXTURE_2D, vertex_shader, fragment_shader))
!d->buildProgr...agment_shader)Description
TRUEnever evaluated
FALSEnever evaluated
0
339 return false;
never executed: return false;
0
340 if (supportsExternalOESTarget())
supportsExternalOESTarget()Description
TRUEnever evaluated
FALSEnever evaluated
0
341 if (!d->buildProgram(QOpenGLTextureBlitterPrivate::TEXTURE_EXTERNAL_OES, vertex_shader, fragment_shader_external_oes))
!d->buildProgr..._external_oes)Description
TRUEnever evaluated
FALSEnever evaluated
0
342 return false;
never executed: return false;
0
343 }
never executed: end of block
0
344-
345 // Create and bind the VAO, if supported.-
346 QOpenGLVertexArrayObject::Binder vaoBinder(d->vao.data());-
347-
348 d->vertexBuffer.create();-
349 d->vertexBuffer.bind();-
350 d->vertexBuffer.allocate(vertex_buffer_data, sizeof(vertex_buffer_data));-
351 d->vertexBuffer.release();-
352-
353 d->textureBuffer.create();-
354 d->textureBuffer.bind();-
355 d->textureBuffer.allocate(texture_buffer_data, sizeof(texture_buffer_data));-
356 d->textureBuffer.release();-
357-
358 return true;
never executed: return true;
0
359}-
360-
361bool QOpenGLTextureBlitter::isCreated() const-
362{-
363 Q_D(const QOpenGLTextureBlitter);-
364 return d->programs[QOpenGLTextureBlitterPrivate::TEXTURE_2D].glProgram;
never executed: return d->programs[QOpenGLTextureBlitterPrivate::TEXTURE_2D].glProgram;
0
365}-
366-
367void QOpenGLTextureBlitter::destroy()-
368{-
369 if (!isCreated())
!isCreated()Description
TRUEnever evaluated
FALSEnever evaluated
0
370 return;
never executed: return;
0
371 Q_D(QOpenGLTextureBlitter);-
372 d->programs[QOpenGLTextureBlitterPrivate::TEXTURE_2D].glProgram.reset();-
373 d->programs[QOpenGLTextureBlitterPrivate::TEXTURE_EXTERNAL_OES].glProgram.reset();-
374 d->vertexBuffer.destroy();-
375 d->textureBuffer.destroy();-
376 d->vao.reset();-
377}
never executed: end of block
0
378-
379bool QOpenGLTextureBlitter::supportsExternalOESTarget() const-
380{-
381 QOpenGLContext *ctx = QOpenGLContext::currentContext();-
382 return ctx && ctx->isOpenGLES() && ctx->hasExtension("GL_OES_EGL_image_external");
never executed: return ctx && ctx->isOpenGLES() && ctx->hasExtension("GL_OES_EGL_image_external");
0
383}-
384-
385void QOpenGLTextureBlitter::bind(GLenum target)-
386{-
387 Q_D(QOpenGLTextureBlitter);-
388-
389 if (d->vao->isCreated())
d->vao->isCreated()Description
TRUEnever evaluated
FALSEnever evaluated
0
390 d->vao->bind();
never executed: d->vao->bind();
0
391-
392 d->currentTarget = target;-
393 QOpenGLTextureBlitterPrivate::Program *p = &d->programs[targetToProgramIndex(target)];-
394 p->glProgram->bind();-
395-
396 d->vertexBuffer.bind();-
397 p->glProgram->setAttributeBuffer(p->vertexCoordAttribPos, GL_FLOAT, 0, 3, 0);-
398 p->glProgram->enableAttributeArray(p->vertexCoordAttribPos);-
399 d->vertexBuffer.release();-
400-
401 d->textureBuffer.bind();-
402 p->glProgram->setAttributeBuffer(p->textureCoordAttribPos, GL_FLOAT, 0, 2, 0);-
403 p->glProgram->enableAttributeArray(p->textureCoordAttribPos);-
404 d->textureBuffer.release();-
405}
never executed: end of block
0
406-
407void QOpenGLTextureBlitter::release()-
408{-
409 Q_D(QOpenGLTextureBlitter);-
410 d->programs[targetToProgramIndex(d->currentTarget)].glProgram->release();-
411 if (d->vao->isCreated())
d->vao->isCreated()Description
TRUEnever evaluated
FALSEnever evaluated
0
412 d->vao->release();
never executed: d->vao->release();
0
413}
never executed: end of block
0
414-
415void QOpenGLTextureBlitter::setSwizzleRB(bool swizzle)-
416{-
417 Q_D(QOpenGLTextureBlitter);-
418 d->swizzle = swizzle;-
419}
never executed: end of block
0
420-
421void QOpenGLTextureBlitter::setOpacity(float opacity)-
422{-
423 Q_D(QOpenGLTextureBlitter);-
424 d->opacity = opacity;-
425}
never executed: end of block
0
426-
427void QOpenGLTextureBlitter::blit(GLuint texture,-
428 const QMatrix4x4 &targetTransform,-
429 Origin sourceOrigin)-
430{-
431 Q_D(QOpenGLTextureBlitter);-
432 d->blit(texture,targetTransform, sourceOrigin);-
433}
never executed: end of block
0
434-
435void QOpenGLTextureBlitter::blit(GLuint texture,-
436 const QMatrix4x4 &targetTransform,-
437 const QMatrix3x3 &sourceTransform)-
438{-
439 Q_D(QOpenGLTextureBlitter);-
440 d->blit(texture, targetTransform, sourceTransform);-
441}
never executed: end of block
0
442-
443QMatrix4x4 QOpenGLTextureBlitter::targetTransform(const QRectF &target,-
444 const QRect &viewport)-
445{-
446 qreal x_scale = target.width() / viewport.width();-
447 qreal y_scale = target.height() / viewport.height();-
448-
449 const QPointF relative_to_viewport = target.topLeft() - viewport.topLeft();-
450 qreal x_translate = x_scale - 1 + ((relative_to_viewport.x() / viewport.width()) * 2);-
451 qreal y_translate = -y_scale + 1 - ((relative_to_viewport.y() / viewport.height()) * 2);-
452-
453 QMatrix4x4 matrix;-
454 matrix(0,3) = x_translate;-
455 matrix(1,3) = y_translate;-
456-
457 matrix(0,0) = x_scale;-
458 matrix(1,1) = y_scale;-
459-
460 return matrix;
never executed: return matrix;
0
461}-
462-
463QMatrix3x3 QOpenGLTextureBlitter::sourceTransform(const QRectF &subTexture,-
464 const QSize &textureSize,-
465 Origin origin)-
466{-
467 qreal x_scale = subTexture.width() / textureSize.width();-
468 qreal y_scale = subTexture.height() / textureSize.height();-
469-
470 const QPointF topLeft = subTexture.topLeft();-
471 qreal x_translate = topLeft.x() / textureSize.width();-
472 qreal y_translate = topLeft.y() / textureSize.height();-
473-
474 if (origin == OriginTopLeft) {
origin == OriginTopLeftDescription
TRUEnever evaluated
FALSEnever evaluated
0
475 y_scale = -y_scale;-
476 y_translate = 1 - y_translate;-
477 }
never executed: end of block
0
478-
479 QMatrix3x3 matrix;-
480 matrix(0,2) = x_translate;-
481 matrix(1,2) = y_translate;-
482-
483 matrix(0,0) = x_scale;-
484 matrix(1,1) = y_scale;-
485-
486 return matrix;
never executed: return matrix;
0
487}-
488-
489QT_END_NAMESPACE-
Source codeSwitch to Preprocessed file

Generated by Squish Coco Non-Commercial 4.3.0-BETA-master-30-08-2018-4cb69e9