6#include <QtOpenGL/QOpenGLShaderProgram>
7#include <QtOpenGL/QOpenGLVertexArrayObject>
8#include <QtOpenGL/QOpenGLBuffer>
9#include <QtGui/QOpenGLContext>
10#include <QtGui/QOpenGLFunctions>
11#include <QtGui/QOpenGLExtraFunctions>
13#ifndef GL_TEXTURE_EXTERNAL_OES
14#define GL_TEXTURE_EXTERNAL_OES 0x8D65
16#ifndef GL_TEXTURE_RECTANGLE
17#define GL_TEXTURE_RECTANGLE 0x84F5
19#ifndef GL_TEXTURE_WIDTH
20#define GL_TEXTURE_WIDTH 0x1000
22#ifndef GL_TEXTURE_HEIGHT
23#define GL_TEXTURE_HEIGHT 0x1001
29
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
73 "in vec3 vertexCoord;"
74 "in vec2 textureCoord;"
76 "uniform mat4 vertexTransform;"
77 "uniform mat3 textureTransform;"
79 " uv = (textureTransform * vec3(textureCoord,1.0)).xy;"
80 " gl_Position = vertexTransform * vec4(vertexCoord,1.0);"
87 "uniform sampler2D textureSampler;"
88 "uniform bool swizzle;"
89 "uniform float opacity;"
91 " vec4 tmpFragColor = texture(textureSampler, uv);"
92 " tmpFragColor.a *= opacity;"
93 " fragcolor = swizzle ? tmpFragColor.bgra : tmpFragColor;"
97 "attribute highp vec3 vertexCoord;"
98 "attribute highp vec2 textureCoord;"
99 "varying highp vec2 uv;"
100 "uniform highp mat4 vertexTransform;"
101 "uniform highp mat3 textureTransform;"
103 " uv = (textureTransform * vec3(textureCoord,1.0)).xy;"
104 " gl_Position = vertexTransform * vec4(vertexCoord,1.0);"
108 "varying highp vec2 uv;"
109 "uniform sampler2D textureSampler;"
110 "uniform bool swizzle;"
111 "uniform highp float opacity;"
113 " highp vec4 tmpFragColor = texture2D(textureSampler,uv);"
114 " tmpFragColor.a *= opacity;"
115 " gl_FragColor = swizzle ? tmpFragColor.bgra : tmpFragColor;"
119 "#extension GL_OES_EGL_image_external : require\n"
120 "varying highp vec2 uv;"
121 "uniform samplerExternalOES textureSampler;\n"
122 "uniform bool swizzle;"
123 "uniform highp float opacity;"
125 " highp vec4 tmpFragColor = texture2D(textureSampler, uv);"
126 " tmpFragColor.a *= opacity;"
127 " gl_FragColor = swizzle ? tmpFragColor.bgra : tmpFragColor;"
131 "varying highp vec2 uv;"
132 "uniform sampler2DRect textureSampler;"
133 "uniform bool swizzle;"
134 "uniform highp float opacity;"
136 " highp vec4 tmpFragColor = texture2DRect(textureSampler,uv);"
137 " tmpFragColor.a *= opacity;"
138 " gl_FragColor = swizzle ? tmpFragColor.bgra : tmpFragColor;"
142 "#version 150 core\n"
144 "out vec4 fragcolor;"
145 "uniform sampler2DRect textureSampler;"
146 "uniform bool swizzle;"
147 "uniform float opacity;"
149 " vec4 tmpFragColor = texture(textureSampler, uv);"
150 " tmpFragColor.a *= opacity;"
151 " fragcolor = swizzle ? tmpFragColor.bgra : tmpFragColor;"
177 QOpenGLContext::currentContext()->functions()->glBindTexture(m_target, textureId);
181 QOpenGLContext::currentContext()->functions()->glBindTexture(m_target, 0);
214 void blit(GLuint texture,
const QMatrix4x4 &targetTransform,
const QMatrix3x3 &sourceTransform);
215 void blit(GLuint texture,
const QMatrix4x4 &targetTransform, QOpenGLTextureBlitter::Origin origin);
263 qWarning(
"Unsupported texture target 0x%x", target);
270 ProgramIndex programIndex = targetToProgramIndex(currentTarget);
274 Program *program = &programs[programIndex];
277 program->glProgram->setAttributeBuffer(program->vertexCoordAttribPos, GL_FLOAT, 0, 3, 0);
278 program->glProgram->enableAttributeArray(program->vertexCoordAttribPos);
279 vertexBuffer.release();
281 program->glProgram->setUniformValue(program->vertexTransformUniformPos, vertexTransform);
283 textureBuffer.bind();
284 program->glProgram->setAttributeBuffer(program->textureCoordAttribPos, GL_FLOAT, 0, 2, 0);
285 program->glProgram->enableAttributeArray(program->textureCoordAttribPos);
286 textureBuffer.release();
289 program->glProgram->setUniformValue(program->swizzleUniformPos,
swizzle);
294 program->glProgram->setUniformValue(program->opacityUniformPos,
opacity);
305 QMatrix4x4 textureTransform(sourceTransform);
306 if (
auto *glFunctions = QOpenGLContext::currentContext()->extraFunctions()) {
308 glFunctions->glGetTexLevelParameteriv(currentTarget, 0,
GL_TEXTURE_WIDTH, &width);
309 glFunctions->glGetTexLevelParameteriv(currentTarget, 0,
GL_TEXTURE_HEIGHT, &height);
310 textureTransform.scale(width, height);
312 return textureTransform.toGenericMatrix<3, 3>();
315 return sourceTransform;
319 const QMatrix4x4 &targetTransform,
320 const QMatrix3x3 &sourceTransform)
323 if (!prepareProgram(targetTransform))
326 Program *program = &programs[targetToProgramIndex(currentTarget)];
328 const QMatrix3x3 textureTransform = toTextureCoordinates(sourceTransform);
329 program->glProgram->setUniformValue(program->textureTransformUniformPos, textureTransform);
332 QOpenGLContext::currentContext()->functions()->glDrawArrays(GL_TRIANGLES, 0, 6);
336 const QMatrix4x4 &targetTransform,
337 QOpenGLTextureBlitter::Origin origin)
340 if (!prepareProgram(targetTransform))
343 Program *program = &programs[targetToProgramIndex(currentTarget)];
345 if (origin == QOpenGLTextureBlitter::OriginTopLeft) {
347 QMatrix3x3 sourceTransform;
348 sourceTransform(1,1) = -1;
349 sourceTransform(1,2) = 1;
350 const QMatrix3x3 textureTransform = toTextureCoordinates(sourceTransform);
351 program->glProgram->setUniformValue(program->textureTransformUniformPos, textureTransform);
355 const QMatrix3x3 textureTransform = toTextureCoordinates(QMatrix3x3());
356 program->glProgram->setUniformValue(program->textureTransformUniformPos, textureTransform);
360 QOpenGLContext::currentContext()->functions()->glDrawArrays(GL_TRIANGLES, 0, 6);
367 p->glProgram.reset(
new QOpenGLShaderProgram);
369 p->glProgram->addCacheableShaderFromSourceCode(QOpenGLShader::Vertex, vs);
370 p->glProgram->addCacheableShaderFromSourceCode(QOpenGLShader::Fragment, fs);
371 p->glProgram->link();
372 if (!p->glProgram->isLinked()) {
373 qWarning() <<
"Could not link shader program:\n" << p->glProgram->log();
377 p->glProgram->bind();
379 p->vertexCoordAttribPos = p->glProgram->attributeLocation(
"vertexCoord");
380 p->vertexTransformUniformPos = p->glProgram->uniformLocation(
"vertexTransform");
381 p->textureCoordAttribPos = p->glProgram->attributeLocation(
"textureCoord");
382 p->textureTransformUniformPos = p->glProgram->uniformLocation(
"textureTransform");
383 p->swizzleUniformPos = p->glProgram->uniformLocation(
"swizzle");
384 p->opacityUniformPos = p->glProgram->uniformLocation(
"opacity");
386 p->glProgram->setUniformValue(p->swizzleUniformPos,
false);
389 p->glProgram->release();
394bool QOpenGLTextureBlitterPrivate::ensureProgram(ProgramIndex idx)
396 if (programs[idx].glProgram)
399 QOpenGLContext *currentContext = QOpenGLContext::currentContext();
403 QSurfaceFormat format = currentContext->format();
404 if (format.profile() == QSurfaceFormat::CoreProfile && format.version() >= std::pair(3,2)) {
405 if (idx == QOpenGLTextureBlitterPrivate::TEXTURE_RECTANGLE && q->supportsRectangleTarget()) {
406 if (!buildProgram(idx, vertex_shader150, fragment_shader150_rectangle))
410 if (idx == QOpenGLTextureBlitterPrivate::TEXTURE_RECTANGLE && q->supportsRectangleTarget()) {
411 if (!buildProgram(idx, vertex_shader, fragment_shader_rectangle))
414 if (idx == QOpenGLTextureBlitterPrivate::TEXTURE_EXTERNAL_OES && q->supportsExternalOESTarget()) {
415 if (!buildProgram(idx, vertex_shader, fragment_shader_external_oes))
420 return !programs[idx].glProgram.isNull();
424
425
426
427
428
429
430
431
432QOpenGLTextureBlitter::QOpenGLTextureBlitter()
433 : d_ptr(
new QOpenGLTextureBlitterPrivate(
this))
438
439
440
441
442
443
444
445
446QOpenGLTextureBlitter::~QOpenGLTextureBlitter()
452
453
454
455
456
457
458
459
460
461bool QOpenGLTextureBlitter::create()
463 QOpenGLContext *currentContext = QOpenGLContext::currentContext();
467 Q_D(QOpenGLTextureBlitter);
469 if (d->programs[QOpenGLTextureBlitterPrivate::TEXTURE_2D].glProgram)
472 QSurfaceFormat format = currentContext->format();
475 if (format.profile() == QSurfaceFormat::CoreProfile && format.version() >= std::pair(3,2)) {
476 if (!d->buildProgram(QOpenGLTextureBlitterPrivate::TEXTURE_2D, vertex_shader150, fragment_shader150))
479 if (!d->buildProgram(QOpenGLTextureBlitterPrivate::TEXTURE_2D, vertex_shader, fragment_shader))
484 QOpenGLVertexArrayObject::Binder vaoBinder(d->vao.data());
486 d->vertexBuffer.create();
487 d->vertexBuffer.bind();
488 d->vertexBuffer.allocate(vertex_buffer_data,
sizeof(vertex_buffer_data));
489 d->vertexBuffer.release();
491 d->textureBuffer.create();
492 d->textureBuffer.bind();
493 d->textureBuffer.allocate(texture_buffer_data,
sizeof(texture_buffer_data));
494 d->textureBuffer.release();
500
501
502
503
504bool QOpenGLTextureBlitter::isCreated()
const
506 Q_D(
const QOpenGLTextureBlitter);
507 return !d->programs[QOpenGLTextureBlitterPrivate::TEXTURE_2D].glProgram.isNull();
511
512
513
514
515
516
517
518
519void QOpenGLTextureBlitter::destroy()
523 Q_D(QOpenGLTextureBlitter);
524 d->programs[QOpenGLTextureBlitterPrivate::TEXTURE_2D].glProgram.reset();
525 d->programs[QOpenGLTextureBlitterPrivate::TEXTURE_EXTERNAL_OES].glProgram.reset();
526 d->programs[QOpenGLTextureBlitterPrivate::TEXTURE_RECTANGLE].glProgram.reset();
527 d->vertexBuffer.destroy();
528 d->textureBuffer.destroy();
533
534
535
536
537
538bool QOpenGLTextureBlitter::supportsExternalOESTarget()
const
540 QOpenGLContext *ctx = QOpenGLContext::currentContext();
541 return ctx && ctx->isOpenGLES() && ctx->hasExtension(
"GL_OES_EGL_image_external");
545
546
547
548
549
550bool QOpenGLTextureBlitter::supportsRectangleTarget()
const
552 QOpenGLContext *ctx = QOpenGLContext::currentContext();
553 if (!ctx || ctx->isOpenGLES())
556 if (ctx->hasExtension(
"GL_ARB_texture_rectangle"))
559 if (ctx->hasExtension(
"GL_EXT_texture_rectangle"))
562 QSurfaceFormat f = ctx->format();
563 const auto version = std::pair(f.majorVersion(), f.minorVersion());
564 if (version >= std::pair(3, 1))
571
572
573
574
575
576
577
578
579
580
581void QOpenGLTextureBlitter::bind(GLenum target)
583 Q_D(QOpenGLTextureBlitter);
585 if (d->vao->isCreated())
588 d->currentTarget = target;
589 QOpenGLTextureBlitterPrivate::ProgramIndex programIndex = targetToProgramIndex(target);
590 if (!d->ensureProgram(programIndex))
593 QOpenGLTextureBlitterPrivate::Program *p = &d->programs[programIndex];
594 p->glProgram->bind();
596 d->vertexBuffer.bind();
597 p->glProgram->setAttributeBuffer(p->vertexCoordAttribPos, GL_FLOAT, 0, 3, 0);
598 p->glProgram->enableAttributeArray(p->vertexCoordAttribPos);
599 d->vertexBuffer.release();
601 d->textureBuffer.bind();
602 p->glProgram->setAttributeBuffer(p->textureCoordAttribPos, GL_FLOAT, 0, 2, 0);
603 p->glProgram->enableAttributeArray(p->textureCoordAttribPos);
604 d->textureBuffer.release();
608
609
610
611
612void QOpenGLTextureBlitter::release()
614 Q_D(QOpenGLTextureBlitter);
615 QOpenGLTextureBlitterPrivate::Program *p = &d->programs[targetToProgramIndex(d->currentTarget)];
617 p->glProgram->release();
618 if (d->vao->isCreated())
623
624
625
626
627
628
629
630
631
632
633
634void QOpenGLTextureBlitter::setRedBlueSwizzle(
bool swizzle)
636 Q_D(QOpenGLTextureBlitter);
637 d->swizzle = swizzle;
641
642
643
644
645
646
647void QOpenGLTextureBlitter::setOpacity(
float opacity)
649 Q_D(QOpenGLTextureBlitter);
650 d->opacity = opacity;
654
655
656
657
658
659
660
661
662
663
664
665
668
669
670
671
672
673
674
675
676
677
678
679
680
681void QOpenGLTextureBlitter::blit(GLuint texture,
682 const QMatrix4x4 &targetTransform,
685 Q_D(QOpenGLTextureBlitter);
686 d->blit(texture, targetTransform, sourceOrigin);
690
691
692
693
694
695
696
697
698
699
700
701
702void QOpenGLTextureBlitter::blit(GLuint texture,
703 const QMatrix4x4 &targetTransform,
704 const QMatrix3x3 &sourceTransform)
706 Q_D(QOpenGLTextureBlitter);
707 d->blit(texture, targetTransform, sourceTransform);
711
712
713
714
715
716
717
718
719
720
721
722QMatrix4x4 QOpenGLTextureBlitter::targetTransform(
const QRectF &target,
723 const QRect &viewport)
725 qreal x_scale = target.width() / viewport.width();
726 qreal y_scale = target.height() / viewport.height();
728 const QPointF relative_to_viewport = target.topLeft() - viewport.topLeft();
729 qreal x_translate = x_scale - 1 + ((relative_to_viewport.x() / viewport.width()) * 2);
730 qreal y_translate = -y_scale + 1 - ((relative_to_viewport.y() / viewport.height()) * 2);
733 matrix(0,3) = x_translate;
734 matrix(1,3) = y_translate;
736 matrix(0,0) = x_scale;
737 matrix(1,1) = y_scale;
743
744
745
746
747
748
749
750
751
752
753QMatrix3x3 QOpenGLTextureBlitter::sourceTransform(
const QRectF &subTexture,
754 const QSize &textureSize,
757 qreal x_scale = subTexture.width() / textureSize.width();
758 qreal y_scale = subTexture.height() / textureSize.height();
760 const QPointF topLeft = subTexture.topLeft();
761 qreal x_translate = topLeft.x() / textureSize.width();
762 qreal y_translate = topLeft.y() / textureSize.height();
764 if (origin == OriginTopLeft) {
766 y_translate = 1 - y_translate;
770 matrix(0,2) = x_translate;
771 matrix(1,2) = y_translate;
773 matrix(0,0) = x_scale;
774 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