7#include <QtOpenGL/QOpenGLShaderProgram>
8#include <QtOpenGL/QOpenGLVertexArrayObject>
9#include <QtOpenGL/QOpenGLBuffer>
10#include <QtGui/QOpenGLContext>
11#include <QtGui/QOpenGLFunctions>
12#include <QtGui/QOpenGLExtraFunctions>
14#ifndef GL_TEXTURE_EXTERNAL_OES
15#define GL_TEXTURE_EXTERNAL_OES 0x8D65
17#ifndef GL_TEXTURE_RECTANGLE
18#define GL_TEXTURE_RECTANGLE 0x84F5
20#ifndef GL_TEXTURE_WIDTH
21#define GL_TEXTURE_WIDTH 0x1000
23#ifndef GL_TEXTURE_HEIGHT
24#define GL_TEXTURE_HEIGHT 0x1001
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
74 "in vec3 vertexCoord;"
75 "in vec2 textureCoord;"
77 "uniform mat4 vertexTransform;"
78 "uniform mat3 textureTransform;"
80 " uv = (textureTransform * vec3(textureCoord,1.0)).xy;"
81 " gl_Position = vertexTransform * vec4(vertexCoord,1.0);"
88 "uniform sampler2D textureSampler;"
89 "uniform bool swizzle;"
90 "uniform float opacity;"
92 " vec4 tmpFragColor = texture(textureSampler, uv);"
93 " tmpFragColor.a *= opacity;"
94 " fragcolor = swizzle ? tmpFragColor.bgra : tmpFragColor;"
98 "attribute highp vec3 vertexCoord;"
99 "attribute highp vec2 textureCoord;"
100 "varying highp vec2 uv;"
101 "uniform highp mat4 vertexTransform;"
102 "uniform highp mat3 textureTransform;"
104 " uv = (textureTransform * vec3(textureCoord,1.0)).xy;"
105 " gl_Position = vertexTransform * vec4(vertexCoord,1.0);"
109 "varying highp vec2 uv;"
110 "uniform sampler2D textureSampler;"
111 "uniform bool swizzle;"
112 "uniform highp float opacity;"
114 " highp vec4 tmpFragColor = texture2D(textureSampler,uv);"
115 " tmpFragColor.a *= opacity;"
116 " gl_FragColor = swizzle ? tmpFragColor.bgra : tmpFragColor;"
120 "#extension GL_OES_EGL_image_external : require\n"
121 "varying highp vec2 uv;"
122 "uniform samplerExternalOES textureSampler;\n"
123 "uniform bool swizzle;"
124 "uniform highp float opacity;"
126 " highp vec4 tmpFragColor = texture2D(textureSampler, uv);"
127 " tmpFragColor.a *= opacity;"
128 " gl_FragColor = swizzle ? tmpFragColor.bgra : tmpFragColor;"
132 "varying highp vec2 uv;"
133 "uniform sampler2DRect textureSampler;"
134 "uniform bool swizzle;"
135 "uniform highp float opacity;"
137 " highp vec4 tmpFragColor = texture2DRect(textureSampler,uv);"
138 " tmpFragColor.a *= opacity;"
139 " gl_FragColor = swizzle ? tmpFragColor.bgra : tmpFragColor;"
143 "#version 150 core\n"
145 "out vec4 fragcolor;"
146 "uniform sampler2DRect textureSampler;"
147 "uniform bool swizzle;"
148 "uniform float opacity;"
150 " vec4 tmpFragColor = texture(textureSampler, uv);"
151 " tmpFragColor.a *= opacity;"
152 " fragcolor = swizzle ? tmpFragColor.bgra : tmpFragColor;"
178 QOpenGLContext::currentContext()->functions()->glBindTexture(m_target, textureId);
182 QOpenGLContext::currentContext()->functions()->glBindTexture(m_target, 0);
215 void blit(GLuint texture,
const QMatrix4x4 &targetTransform,
const QMatrix3x3 &sourceTransform);
216 void blit(GLuint texture,
const QMatrix4x4 &targetTransform, QOpenGLTextureBlitter::Origin origin);
264 qWarning(
"Unsupported texture target 0x%x", target);
271 ProgramIndex programIndex = targetToProgramIndex(currentTarget);
275 Program *program = &programs[programIndex];
278 program->glProgram->setAttributeBuffer(program->vertexCoordAttribPos, GL_FLOAT, 0, 3, 0);
279 program->glProgram->enableAttributeArray(program->vertexCoordAttribPos);
280 vertexBuffer.release();
282 program->glProgram->setUniformValue(program->vertexTransformUniformPos, vertexTransform);
284 textureBuffer.bind();
285 program->glProgram->setAttributeBuffer(program->textureCoordAttribPos, GL_FLOAT, 0, 2, 0);
286 program->glProgram->enableAttributeArray(program->textureCoordAttribPos);
287 textureBuffer.release();
290 program->glProgram->setUniformValue(program->swizzleUniformPos,
swizzle);
295 program->glProgram->setUniformValue(program->opacityUniformPos,
opacity);
306 QMatrix4x4 textureTransform(sourceTransform);
307 if (
auto *glFunctions = QOpenGLContext::currentContext()->extraFunctions()) {
309 glFunctions->glGetTexLevelParameteriv(currentTarget, 0,
GL_TEXTURE_WIDTH, &width);
310 glFunctions->glGetTexLevelParameteriv(currentTarget, 0,
GL_TEXTURE_HEIGHT, &height);
311 textureTransform.scale(width, height);
313 return textureTransform.toGenericMatrix<3, 3>();
316 return sourceTransform;
320 const QMatrix4x4 &targetTransform,
321 const QMatrix3x3 &sourceTransform)
324 if (!prepareProgram(targetTransform))
327 Program *program = &programs[targetToProgramIndex(currentTarget)];
329 const QMatrix3x3 textureTransform = toTextureCoordinates(sourceTransform);
330 program->glProgram->setUniformValue(program->textureTransformUniformPos, textureTransform);
333 QOpenGLContext::currentContext()->functions()->glDrawArrays(GL_TRIANGLES, 0, 6);
337 const QMatrix4x4 &targetTransform,
338 QOpenGLTextureBlitter::Origin origin)
341 if (!prepareProgram(targetTransform))
344 Program *program = &programs[targetToProgramIndex(currentTarget)];
346 if (origin == QOpenGLTextureBlitter::OriginTopLeft) {
348 QMatrix3x3 sourceTransform;
349 sourceTransform(1,1) = -1;
350 sourceTransform(1,2) = 1;
351 const QMatrix3x3 textureTransform = toTextureCoordinates(sourceTransform);
352 program->glProgram->setUniformValue(program->textureTransformUniformPos, textureTransform);
356 const QMatrix3x3 textureTransform = toTextureCoordinates(QMatrix3x3());
357 program->glProgram->setUniformValue(program->textureTransformUniformPos, textureTransform);
361 QOpenGLContext::currentContext()->functions()->glDrawArrays(GL_TRIANGLES, 0, 6);
368 p->glProgram.reset(
new QOpenGLShaderProgram);
370 p->glProgram->addCacheableShaderFromSourceCode(QOpenGLShader::Vertex, vs);
371 p->glProgram->addCacheableShaderFromSourceCode(QOpenGLShader::Fragment, fs);
372 p->glProgram->link();
373 if (!p->glProgram->isLinked()) {
374 qWarning() <<
"Could not link shader program:\n" << p->glProgram->log();
378 p->glProgram->bind();
380 p->vertexCoordAttribPos = p->glProgram->attributeLocation(
"vertexCoord");
381 p->vertexTransformUniformPos = p->glProgram->uniformLocation(
"vertexTransform");
382 p->textureCoordAttribPos = p->glProgram->attributeLocation(
"textureCoord");
383 p->textureTransformUniformPos = p->glProgram->uniformLocation(
"textureTransform");
384 p->swizzleUniformPos = p->glProgram->uniformLocation(
"swizzle");
385 p->opacityUniformPos = p->glProgram->uniformLocation(
"opacity");
387 p->glProgram->setUniformValue(p->swizzleUniformPos,
false);
390 p->glProgram->release();
397 if (programs[idx].glProgram)
400 QOpenGLContext *currentContext = QOpenGLContext::currentContext();
404 QSurfaceFormat format = currentContext->format();
405 if (format.profile() == QSurfaceFormat::CoreProfile && format.version() >= std::pair(3,2)) {
406 if (idx == QOpenGLTextureBlitterPrivate::TEXTURE_RECTANGLE && q->supportsRectangleTarget()) {
411 if (idx == QOpenGLTextureBlitterPrivate::TEXTURE_RECTANGLE && q->supportsRectangleTarget()) {
415 if (idx == QOpenGLTextureBlitterPrivate::TEXTURE_EXTERNAL_OES && q->supportsExternalOESTarget()) {
421 return !programs[idx].glProgram.isNull();
425
426
427
428
429
430
431
432
433QOpenGLTextureBlitter::QOpenGLTextureBlitter()
434 : d_ptr(
new QOpenGLTextureBlitterPrivate(
this))
439
440
441
442
443
444
445
446
447QOpenGLTextureBlitter::~QOpenGLTextureBlitter()
453
454
455
456
457
458
459
460
461
462bool QOpenGLTextureBlitter::create()
464 QOpenGLContext *currentContext = QOpenGLContext::currentContext();
468 Q_D(QOpenGLTextureBlitter);
470 if (d->programs[QOpenGLTextureBlitterPrivate::TEXTURE_2D].glProgram)
473 QSurfaceFormat format = currentContext->format();
476 if (format.profile() == QSurfaceFormat::CoreProfile && format.version() >= std::pair(3,2)) {
477 if (!d->buildProgram(QOpenGLTextureBlitterPrivate::TEXTURE_2D, vertex_shader150, fragment_shader150))
480 if (!d->buildProgram(QOpenGLTextureBlitterPrivate::TEXTURE_2D, vertex_shader, fragment_shader))
485 QOpenGLVertexArrayObject::Binder vaoBinder(d->vao.data());
487 d->vertexBuffer.create();
488 d->vertexBuffer.bind();
489 d->vertexBuffer.allocate(vertex_buffer_data,
sizeof(vertex_buffer_data));
490 d->vertexBuffer.release();
492 d->textureBuffer.create();
493 d->textureBuffer.bind();
494 d->textureBuffer.allocate(texture_buffer_data,
sizeof(texture_buffer_data));
495 d->textureBuffer.release();
501
502
503
504
505bool QOpenGLTextureBlitter::isCreated()
const
507 Q_D(
const QOpenGLTextureBlitter);
508 return !d->programs[QOpenGLTextureBlitterPrivate::TEXTURE_2D].glProgram.isNull();
512
513
514
515
516
517
518
519
520void QOpenGLTextureBlitter::destroy()
524 Q_D(QOpenGLTextureBlitter);
525 d->programs[QOpenGLTextureBlitterPrivate::TEXTURE_2D].glProgram.reset();
526 d->programs[QOpenGLTextureBlitterPrivate::TEXTURE_EXTERNAL_OES].glProgram.reset();
527 d->programs[QOpenGLTextureBlitterPrivate::TEXTURE_RECTANGLE].glProgram.reset();
528 d->vertexBuffer.destroy();
529 d->textureBuffer.destroy();
534
535
536
537
538
539bool QOpenGLTextureBlitter::supportsExternalOESTarget()
const
541 QOpenGLContext *ctx = QOpenGLContext::currentContext();
542 return ctx && ctx->isOpenGLES() && ctx->hasExtension(
"GL_OES_EGL_image_external");
546
547
548
549
550
551bool QOpenGLTextureBlitter::supportsRectangleTarget()
const
553 QOpenGLContext *ctx = QOpenGLContext::currentContext();
554 if (!ctx || ctx->isOpenGLES())
557 if (ctx->hasExtension(
"GL_ARB_texture_rectangle"))
560 if (ctx->hasExtension(
"GL_EXT_texture_rectangle"))
563 QSurfaceFormat f = ctx->format();
564 const auto version = std::pair(f.majorVersion(), f.minorVersion());
565 if (version >= std::pair(3, 1))
572
573
574
575
576
577
578
579
580
581
582void QOpenGLTextureBlitter::bind(GLenum target)
584 Q_D(QOpenGLTextureBlitter);
586 if (d->vao->isCreated())
589 d->currentTarget = target;
590 QOpenGLTextureBlitterPrivate::ProgramIndex programIndex = targetToProgramIndex(target);
591 if (!d->ensureProgram(programIndex))
594 QOpenGLTextureBlitterPrivate::Program *p = &d->programs[programIndex];
595 p->glProgram->bind();
597 d->vertexBuffer.bind();
598 p->glProgram->setAttributeBuffer(p->vertexCoordAttribPos, GL_FLOAT, 0, 3, 0);
599 p->glProgram->enableAttributeArray(p->vertexCoordAttribPos);
600 d->vertexBuffer.release();
602 d->textureBuffer.bind();
603 p->glProgram->setAttributeBuffer(p->textureCoordAttribPos, GL_FLOAT, 0, 2, 0);
604 p->glProgram->enableAttributeArray(p->textureCoordAttribPos);
605 d->textureBuffer.release();
609
610
611
612
613void QOpenGLTextureBlitter::release()
615 Q_D(QOpenGLTextureBlitter);
616 QOpenGLTextureBlitterPrivate::Program *p = &d->programs[targetToProgramIndex(d->currentTarget)];
618 p->glProgram->release();
619 if (d->vao->isCreated())
624
625
626
627
628
629
630
631
632
633
634
635void QOpenGLTextureBlitter::setRedBlueSwizzle(
bool swizzle)
637 Q_D(QOpenGLTextureBlitter);
638 d->swizzle = swizzle;
642
643
644
645
646
647
648void QOpenGLTextureBlitter::setOpacity(
float opacity)
650 Q_D(QOpenGLTextureBlitter);
651 d->opacity = opacity;
655
656
657
658
659
660
661
662
663
664
665
666
669
670
671
672
673
674
675
676
677
678
679
680
681
682void QOpenGLTextureBlitter::blit(GLuint texture,
683 const QMatrix4x4 &targetTransform,
686 Q_D(QOpenGLTextureBlitter);
687 d->blit(texture, targetTransform, sourceOrigin);
691
692
693
694
695
696
697
698
699
700
701
702
703void QOpenGLTextureBlitter::blit(GLuint texture,
704 const QMatrix4x4 &targetTransform,
705 const QMatrix3x3 &sourceTransform)
707 Q_D(QOpenGLTextureBlitter);
708 d->blit(texture, targetTransform, sourceTransform);
712
713
714
715
716
717
718
719
720
721
722
723QMatrix4x4 QOpenGLTextureBlitter::targetTransform(
const QRectF &target,
724 const QRect &viewport)
726 qreal x_scale = target.width() / viewport.width();
727 qreal y_scale = target.height() / viewport.height();
729 const QPointF relative_to_viewport = target.topLeft() - viewport.topLeft();
730 qreal x_translate = x_scale - 1 + ((relative_to_viewport.x() / viewport.width()) * 2);
731 qreal y_translate = -y_scale + 1 - ((relative_to_viewport.y() / viewport.height()) * 2);
734 matrix(0,3) = x_translate;
735 matrix(1,3) = y_translate;
737 matrix(0,0) = x_scale;
738 matrix(1,1) = y_scale;
744
745
746
747
748
749
750
751
752
753
754QMatrix3x3 QOpenGLTextureBlitter::sourceTransform(
const QRectF &subTexture,
755 const QSize &textureSize,
758 qreal x_scale = subTexture.width() / textureSize.width();
759 qreal y_scale = subTexture.height() / textureSize.height();
761 const QPointF topLeft = subTexture.topLeft();
762 qreal x_translate = topLeft.x() / textureSize.width();
763 qreal y_translate = topLeft.y() / textureSize.height();
765 if (origin == OriginTopLeft) {
767 y_translate = 1 - y_translate;
771 matrix(0,2) = x_translate;
772 matrix(1,2) = y_translate;
774 matrix(0,0) = x_scale;
775 matrix(1,1) = y_scale;
QBlitterTextureBinder(GLenum target, GLuint textureId)
QMatrix3x3 toTextureCoordinates(const QMatrix3x3 &sourceTransform) const
bool ensureProgram(ProgramIndex idx)
QOpenGLBuffer vertexBuffer
void blit(GLuint texture, const QMatrix4x4 &targetTransform, QOpenGLTextureBlitter::Origin origin)
QOpenGLTextureBlitter * q
QOpenGLTextureBlitterPrivate(QOpenGLTextureBlitter *q_ptr)
QOpenGLBuffer textureBuffer
QScopedPointer< QOpenGLVertexArrayObject > vao
bool buildProgram(ProgramIndex idx, const char *vs, const char *fs)
void blit(GLuint texture, const QMatrix4x4 &targetTransform, const QMatrix3x3 &sourceTransform)
bool prepareProgram(const QMatrix4x4 &vertexTransform)
Combined button and popup list for selecting options.
#define GL_TEXTURE_EXTERNAL_OES
#define GL_TEXTURE_RECTANGLE
static const char fragment_shader_external_oes[]
static const char fragment_shader150[]
static const char vertex_shader[]
#define GL_TEXTURE_HEIGHT
static const GLfloat texture_buffer_data[]
static const char fragment_shader150_rectangle[]
static const GLfloat vertex_buffer_data[]
static const char fragment_shader_rectangle[]
static QOpenGLTextureBlitterPrivate::ProgramIndex targetToProgramIndex(GLenum target)
static const char fragment_shader[]
static const char vertex_shader150[]
QScopedPointer< QOpenGLShaderProgram > glProgram
GLuint vertexTransformUniformPos
GLuint vertexCoordAttribPos
GLuint textureCoordAttribPos
GLuint textureTransformUniformPos
TextureMatrixUniform textureMatrixUniformState