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

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