2
Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). <qt-info@nokia.com>
3
Copyright (C) 2011-2012 Collabora Ltd. <info@collabora.com>
5
This library is free software; you can redistribute it and/or modify
6
it under the terms of the GNU Lesser General Public License version 2.1
7
as published by the Free Software Foundation.
9
This program is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
GNU Lesser General Public License for more details.
14
You should have received a copy of the GNU Lesser General Public License
15
along with this program. If not, see <http://www.gnu.org/licenses/>.
17
#include "openglsurfacepainter.h"
18
#include <QtCore/qmath.h>
21
# define GL_TEXTURE0 0x84C0
22
# define GL_TEXTURE1 0x84C1
23
# define GL_TEXTURE2 0x84C2
26
#ifndef GL_PROGRAM_ERROR_STRING_ARB
27
# define GL_PROGRAM_ERROR_STRING_ARB 0x8874
30
#ifndef GL_UNSIGNED_SHORT_5_6_5
31
# define GL_UNSIGNED_SHORT_5_6_5 33635
34
#define QRECT_TO_GLMATRIX(rect) \
36
GLfloat(rect.left()) , GLfloat(rect.bottom() + 1), \
37
GLfloat(rect.right() + 1), GLfloat(rect.bottom() + 1), \
38
GLfloat(rect.left()) , GLfloat(rect.top()), \
39
GLfloat(rect.right() + 1), GLfloat(rect.top()) \
42
OpenGLSurfacePainter::OpenGLSurfacePainter()
44
, m_textureInternalFormat(0)
47
, m_videoColorMatrix(GST_VIDEO_COLOR_MATRIX_UNKNOWN)
50
glActiveTexture = (_glActiveTexture) QGLContext::currentContext()->getProcAddress(
51
QLatin1String("glActiveTexture"));
56
QSet<GstVideoFormat> OpenGLSurfacePainter::supportedPixelFormats()
58
return QSet<GstVideoFormat>()
59
//also handled by the generic painter on LE
60
<< GST_VIDEO_FORMAT_BGRA
61
<< GST_VIDEO_FORMAT_BGRx
63
//also handled by the generic painter on BE
64
<< GST_VIDEO_FORMAT_ARGB
65
<< GST_VIDEO_FORMAT_xRGB
67
//also handled by the generic painter everywhere
68
<< GST_VIDEO_FORMAT_RGB
69
<< GST_VIDEO_FORMAT_RGB16
71
//not handled by the generic painter
72
<< GST_VIDEO_FORMAT_BGR
73
<< GST_VIDEO_FORMAT_v308
74
<< GST_VIDEO_FORMAT_AYUV
75
<< GST_VIDEO_FORMAT_YV12
76
<< GST_VIDEO_FORMAT_I420
80
void OpenGLSurfacePainter::updateColors(int brightness, int contrast, int hue, int saturation)
82
const qreal b = brightness / 200.0;
83
const qreal c = contrast / 100.0 + 1.0;
84
const qreal h = hue / 100.0;
85
const qreal s = saturation / 100.0 + 1.0;
87
const qreal cosH = qCos(M_PI * h);
88
const qreal sinH = qSin(M_PI * h);
90
const qreal h11 = 0.787 * cosH - 0.213 * sinH + 0.213;
91
const qreal h21 = -0.213 * cosH + 0.143 * sinH + 0.213;
92
const qreal h31 = -0.213 * cosH - 0.787 * sinH + 0.213;
94
const qreal h12 = -0.715 * cosH - 0.715 * sinH + 0.715;
95
const qreal h22 = 0.285 * cosH + 0.140 * sinH + 0.715;
96
const qreal h32 = -0.715 * cosH + 0.715 * sinH + 0.715;
98
const qreal h13 = -0.072 * cosH + 0.928 * sinH + 0.072;
99
const qreal h23 = -0.072 * cosH - 0.283 * sinH + 0.072;
100
const qreal h33 = 0.928 * cosH + 0.072 * sinH + 0.072;
102
const qreal sr = (1.0 - s) * 0.3086;
103
const qreal sg = (1.0 - s) * 0.6094;
104
const qreal sb = (1.0 - s) * 0.0820;
106
const qreal sr_s = sr + s;
107
const qreal sg_s = sg + s;
108
const qreal sb_s = sr + s;
110
const float m4 = (s + sr + sg + sb) * (0.5 - 0.5 * c + b);
112
m_colorMatrix(0, 0) = c * (sr_s * h11 + sg * h21 + sb * h31);
113
m_colorMatrix(0, 1) = c * (sr_s * h12 + sg * h22 + sb * h32);
114
m_colorMatrix(0, 2) = c * (sr_s * h13 + sg * h23 + sb * h33);
115
m_colorMatrix(0, 3) = m4;
117
m_colorMatrix(1, 0) = c * (sr * h11 + sg_s * h21 + sb * h31);
118
m_colorMatrix(1, 1) = c * (sr * h12 + sg_s * h22 + sb * h32);
119
m_colorMatrix(1, 2) = c * (sr * h13 + sg_s * h23 + sb * h33);
120
m_colorMatrix(1, 3) = m4;
122
m_colorMatrix(2, 0) = c * (sr * h11 + sg * h21 + sb_s * h31);
123
m_colorMatrix(2, 1) = c * (sr * h12 + sg * h22 + sb_s * h32);
124
m_colorMatrix(2, 2) = c * (sr * h13 + sg * h23 + sb_s * h33);
125
m_colorMatrix(2, 3) = m4;
127
m_colorMatrix(3, 0) = 0.0;
128
m_colorMatrix(3, 1) = 0.0;
129
m_colorMatrix(3, 2) = 0.0;
130
m_colorMatrix(3, 3) = 1.0;
132
switch (m_videoColorMatrix) {
134
//I have no idea what this is - it's not needed currently in this code
135
case BufferFormat::YCbCr_JPEG:
136
m_colorMatrix *= QMatrix4x4(
137
1.0, 0.000, 1.402, -0.701,
138
1.0, -0.344, -0.714, 0.529,
139
1.0, 1.772, 0.000, -0.886,
140
0.0, 0.000, 0.000, 1.0000);
143
case GST_VIDEO_COLOR_MATRIX_BT709:
144
m_colorMatrix *= QMatrix4x4(
145
1.164, 0.000, 1.793, -0.5727,
146
1.164, -0.534, -0.213, 0.3007,
147
1.164, 2.115, 0.000, -1.1302,
148
0.0, 0.000, 0.000, 1.0000);
150
case GST_VIDEO_COLOR_MATRIX_BT601:
151
m_colorMatrix *= QMatrix4x4(
152
1.164, 0.000, 1.596, -0.8708,
153
1.164, -0.392, -0.813, 0.5296,
154
1.164, 2.017, 0.000, -1.081,
155
0.0, 0.000, 0.000, 1.0000);
162
void OpenGLSurfacePainter::paint(quint8 *data,
163
const BufferFormat & frameFormat,
164
const QRectF & clipRect,
166
const PaintAreas & areas)
168
// if these are enabled, we need to reenable them after beginNativePainting()
169
// has been called, as they may get disabled
170
bool stencilTestEnabled = glIsEnabled(GL_STENCIL_TEST);
171
bool scissorTestEnabled = glIsEnabled(GL_SCISSOR_TEST);
173
painter->beginNativePainting();
175
if (stencilTestEnabled)
176
glEnable(GL_STENCIL_TEST);
177
if (scissorTestEnabled)
178
glEnable(GL_SCISSOR_TEST);
180
const GLfloat vertexCoordArray[] = QRECT_TO_GLMATRIX(areas.videoArea);
182
const GLfloat txLeft = clipRect.left() / frameFormat.frameSize().width();
183
const GLfloat txRight = (clipRect.right() + 1) / frameFormat.frameSize().width();
184
const GLfloat txTop = clipRect.top() / frameFormat.frameSize().height();
185
const GLfloat txBottom = (clipRect.bottom() + 1) / frameFormat.frameSize().height();
187
const GLfloat textureCoordArray[] =
195
for (int i = 0; i < m_textureCount; ++i) {
196
glBindTexture(GL_TEXTURE_2D, m_textureIds[i]);
200
m_textureInternalFormat,
206
data + m_textureOffsets[i]);
207
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
208
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
209
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
210
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
213
paintImpl(painter, vertexCoordArray, textureCoordArray);
215
painter->endNativePainting();
216
painter->fillRect(areas.blackArea1, Qt::black);
217
painter->fillRect(areas.blackArea2, Qt::black);
220
void OpenGLSurfacePainter::initRgbTextureInfo(
221
GLenum internalFormat, GLuint format, GLenum type, const QSize &size)
224
//make sure we get 8 bits per component, at least on the desktop GL where we can
225
switch(internalFormat) {
227
internalFormat = GL_RGBA8;
230
internalFormat = GL_RGB8;
237
m_textureInternalFormat = internalFormat;
238
m_textureFormat = format;
239
m_textureType = type;
241
m_textureWidths[0] = size.width();
242
m_textureHeights[0] = size.height();
243
m_textureOffsets[0] = 0;
246
void OpenGLSurfacePainter::initYuv420PTextureInfo(const QSize &size)
248
int bytesPerLine = (size.width() + 3) & ~3;
249
int bytesPerLine2 = (size.width() / 2 + 3) & ~3;
251
m_textureInternalFormat = GL_LUMINANCE;
252
m_textureFormat = GL_LUMINANCE;
253
m_textureType = GL_UNSIGNED_BYTE;
255
m_textureWidths[0] = bytesPerLine;
256
m_textureHeights[0] = size.height();
257
m_textureOffsets[0] = 0;
258
m_textureWidths[1] = bytesPerLine2;
259
m_textureHeights[1] = size.height() / 2;
260
m_textureOffsets[1] = bytesPerLine * size.height();
261
m_textureWidths[2] = bytesPerLine2;
262
m_textureHeights[2] = size.height() / 2;
263
m_textureOffsets[2] = bytesPerLine * size.height() + bytesPerLine2 * size.height()/2;
266
void OpenGLSurfacePainter::initYv12TextureInfo(const QSize &size)
268
int bytesPerLine = (size.width() + 3) & ~3;
269
int bytesPerLine2 = (size.width() / 2 + 3) & ~3;
271
m_textureInternalFormat = GL_LUMINANCE;
272
m_textureFormat = GL_LUMINANCE;
273
m_textureType = GL_UNSIGNED_BYTE;
275
m_textureWidths[0] = bytesPerLine;
276
m_textureHeights[0] = size.height();
277
m_textureOffsets[0] = 0;
278
m_textureWidths[1] = bytesPerLine2;
279
m_textureHeights[1] = size.height() / 2;
280
m_textureOffsets[1] = bytesPerLine * size.height() + bytesPerLine2 * size.height()/2;
281
m_textureWidths[2] = bytesPerLine2;
282
m_textureHeights[2] = size.height() / 2;
283
m_textureOffsets[2] = bytesPerLine * size.height();
288
# ifndef GL_FRAGMENT_PROGRAM_ARB
289
# define GL_FRAGMENT_PROGRAM_ARB 0x8804
290
# define GL_PROGRAM_FORMAT_ASCII_ARB 0x8875
293
// Interprets the RGBA texture as in fact being BGRx and paints it.
294
static const char *qt_arbfp_bgrxShaderProgram =
296
"PARAM matrix[4] = { program.local[0..2],"
297
"{ 0.0, 0.0, 0.0, 1.0 } };\n"
299
"TEX bgrx.xyz, fragment.texcoord[0], texture[0], 2D;\n"
300
"MOV bgrx.w, matrix[3].w;\n"
301
"DP4 result.color.x, bgrx.zyxw, matrix[0];\n"
302
"DP4 result.color.y, bgrx.zyxw, matrix[1];\n"
303
"DP4 result.color.z, bgrx.zyxw, matrix[2];\n"
306
// Interprets the RGBA texture as in fact being BGRA and paints it.
307
static const char *qt_arbfp_bgraShaderProgram =
309
"PARAM matrix[4] = { program.local[0..2],"
310
"{ 0.0, 0.0, 0.0, 1.0 } };\n"
312
"TEX bgra, fragment.texcoord[0], texture[0], 2D;\n"
313
"MOV bgra.w, matrix[3].w;\n"
314
"DP4 result.color.x, bgra.zyxw, matrix[0];\n"
315
"DP4 result.color.y, bgra.zyxw, matrix[1];\n"
316
"DP4 result.color.z, bgra.zyxw, matrix[2];\n"
317
"TEX result.color.w, fragment.texcoord[0], texture, 2D;\n"
320
// Interprets the RGBA texture as in fact being xRGB and paints it.
321
static const char *qt_arbfp_xrgbShaderProgram =
323
"PARAM matrix[4] = { program.local[0..2],"
324
"{ 0.0, 0.0, 0.0, 1.0 } };\n"
326
"TEX xrgb, fragment.texcoord[0], texture[0], 2D;\n"
327
"MOV xrgb.x, matrix[3].w;\n"
328
"DP4 result.color.x, xrgb.yzwx, matrix[0];\n"
329
"DP4 result.color.y, xrgb.yzwx, matrix[1];\n"
330
"DP4 result.color.z, xrgb.yzwx, matrix[2];\n"
333
// Interprets the RGBA texture as in fact being ARGB and paints it.
334
static const char *qt_arbfp_argbShaderProgram =
336
"PARAM matrix[4] = { program.local[0..2],"
337
"{ 0.0, 0.0, 0.0, 1.0 } };\n"
339
"TEX argb, fragment.texcoord[0], texture[0], 2D;\n"
340
"MOV argb.x, matrix[3].w;\n"
341
"DP4 result.color.x, argb.yzwx, matrix[0];\n"
342
"DP4 result.color.y, argb.yzwx, matrix[1];\n"
343
"DP4 result.color.z, argb.yzwx, matrix[2];\n"
344
"TEX result.color.w, fragment.texcoord[0], texture, 2D;\n"
347
// Paints RGB frames without doing any color channel flipping.
348
static const char *qt_arbfp_rgbxShaderProgram =
350
"PARAM matrix[4] = { program.local[0..2],"
351
"{ 0.0, 0.0, 0.0, 1.0 } };\n"
353
"TEX rgb.xyz, fragment.texcoord[0], texture[0], 2D;\n"
354
"MOV rgb.w, matrix[3].w;\n"
355
"DP4 result.color.x, rgb, matrix[0];\n"
356
"DP4 result.color.y, rgb, matrix[1];\n"
357
"DP4 result.color.z, rgb, matrix[2];\n"
360
// Paints a YUV420P or YV12 frame.
361
static const char *qt_arbfp_yuvPlanarShaderProgram =
363
"PARAM matrix[4] = { program.local[0..2],"
364
"{ 0.0, 0.0, 0.0, 1.0 } };\n"
366
"TEX yuv.x, fragment.texcoord[0], texture[0], 2D;\n"
367
"TEX yuv.y, fragment.texcoord[0], texture[1], 2D;\n"
368
"TEX yuv.z, fragment.texcoord[0], texture[2], 2D;\n"
369
"MOV yuv.w, matrix[3].w;\n"
370
"DP4 result.color.x, yuv, matrix[0];\n"
371
"DP4 result.color.y, yuv, matrix[1];\n"
372
"DP4 result.color.z, yuv, matrix[2];\n"
377
ArbFpSurfacePainter::ArbFpSurfacePainter()
378
: OpenGLSurfacePainter()
381
const QGLContext *context = QGLContext::currentContext();
383
glProgramStringARB = (_glProgramStringARB) context->getProcAddress(
384
QLatin1String("glProgramStringARB"));
385
glBindProgramARB = (_glBindProgramARB) context->getProcAddress(
386
QLatin1String("glBindProgramARB"));
387
glDeleteProgramsARB = (_glDeleteProgramsARB) context->getProcAddress(
388
QLatin1String("glDeleteProgramsARB"));
389
glGenProgramsARB = (_glGenProgramsARB) context->getProcAddress(
390
QLatin1String("glGenProgramsARB"));
391
glProgramLocalParameter4fARB = (_glProgramLocalParameter4fARB) context->getProcAddress(
392
QLatin1String("glProgramLocalParameter4fARB"));
395
void ArbFpSurfacePainter::init(const BufferFormat &format)
397
Q_ASSERT(m_textureCount == 0);
399
const char *program = 0;
401
switch (format.videoFormat()) {
402
case GST_VIDEO_FORMAT_BGRx:
403
initRgbTextureInfo(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize());
404
program = qt_arbfp_bgrxShaderProgram;
406
case GST_VIDEO_FORMAT_xRGB:
407
initRgbTextureInfo(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize());
408
program = qt_arbfp_xrgbShaderProgram;
410
case GST_VIDEO_FORMAT_BGRA:
411
initRgbTextureInfo(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize());
412
program = qt_arbfp_bgraShaderProgram;
414
case GST_VIDEO_FORMAT_ARGB:
415
initRgbTextureInfo(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize());
416
program = qt_arbfp_argbShaderProgram;
418
case GST_VIDEO_FORMAT_RGB:
419
initRgbTextureInfo(GL_RGB, GL_RGB, GL_UNSIGNED_BYTE, format.frameSize());
420
program = qt_arbfp_rgbxShaderProgram;
422
case GST_VIDEO_FORMAT_BGR:
423
initRgbTextureInfo(GL_RGB, GL_RGB, GL_UNSIGNED_BYTE, format.frameSize());
424
program = qt_arbfp_bgrxShaderProgram;
426
//NOTE: unlike the other formats, this is endianness-dependent,
427
//but using GL_UNSIGNED_SHORT_5_6_5 ensures that it's handled correctly
428
case GST_VIDEO_FORMAT_RGB16:
429
initRgbTextureInfo(GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, format.frameSize());
430
program = qt_arbfp_rgbxShaderProgram;
432
case GST_VIDEO_FORMAT_v308:
433
initRgbTextureInfo(GL_RGB, GL_RGB, GL_UNSIGNED_BYTE, format.frameSize());
434
program = qt_arbfp_rgbxShaderProgram;
436
case GST_VIDEO_FORMAT_AYUV:
437
initRgbTextureInfo(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize());
438
program = qt_arbfp_argbShaderProgram;
440
case GST_VIDEO_FORMAT_YV12:
441
initYv12TextureInfo(format.frameSize());
442
program = qt_arbfp_yuvPlanarShaderProgram;
444
case GST_VIDEO_FORMAT_I420:
445
initYuv420PTextureInfo(format.frameSize());
446
program = qt_arbfp_yuvPlanarShaderProgram;
453
m_videoColorMatrix = format.colorMatrix();
455
glGenProgramsARB(1, &m_programId);
457
GLenum glError = glGetError();
458
if (glError != GL_NO_ERROR) {
459
throw QString("ARBfb Shader allocation error ") +
460
QString::number(static_cast<int>(glError), 16);
462
glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, m_programId);
464
GL_FRAGMENT_PROGRAM_ARB,
465
GL_PROGRAM_FORMAT_ASCII_ARB,
467
reinterpret_cast<const GLvoid *>(program));
469
if ((glError = glGetError()) != GL_NO_ERROR) {
470
const GLubyte* errorString = glGetString(GL_PROGRAM_ERROR_STRING_ARB);
472
glDeleteProgramsARB(1, &m_programId);
476
throw QString("ARBfp Shader compile error ") +
477
QString::number(static_cast<int>(glError), 16) +
478
reinterpret_cast<const char *>(errorString);
480
glGenTextures(m_textureCount, m_textureIds);
485
void ArbFpSurfacePainter::cleanup()
487
glDeleteTextures(m_textureCount, m_textureIds);
488
glDeleteProgramsARB(1, &m_programId);
494
void ArbFpSurfacePainter::paintImpl(const QPainter *painter,
495
const GLfloat *vertexCoordArray,
496
const GLfloat *textureCoordArray)
500
glEnable(GL_FRAGMENT_PROGRAM_ARB);
501
glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, m_programId);
503
glProgramLocalParameter4fARB(
504
GL_FRAGMENT_PROGRAM_ARB,
509
m_colorMatrix(0, 3));
510
glProgramLocalParameter4fARB(
511
GL_FRAGMENT_PROGRAM_ARB,
516
m_colorMatrix(1, 3));
517
glProgramLocalParameter4fARB(
518
GL_FRAGMENT_PROGRAM_ARB,
523
m_colorMatrix(2, 3));
525
glActiveTexture(GL_TEXTURE0);
526
glBindTexture(GL_TEXTURE_2D, m_textureIds[0]);
528
if (m_textureCount == 3) {
529
glActiveTexture(GL_TEXTURE1);
530
glBindTexture(GL_TEXTURE_2D, m_textureIds[1]);
531
glActiveTexture(GL_TEXTURE2);
532
glBindTexture(GL_TEXTURE_2D, m_textureIds[2]);
533
glActiveTexture(GL_TEXTURE0);
536
glVertexPointer(2, GL_FLOAT, 0, vertexCoordArray);
537
glTexCoordPointer(2, GL_FLOAT, 0, textureCoordArray);
539
glEnableClientState(GL_VERTEX_ARRAY);
540
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
542
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
544
glDisableClientState(GL_VERTEX_ARRAY);
545
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
546
glDisable(GL_FRAGMENT_PROGRAM_ARB);
551
static const char *qt_glsl_vertexShaderProgram =
552
"attribute highp vec4 vertexCoordArray;\n"
553
"attribute highp vec2 textureCoordArray;\n"
554
"uniform highp mat4 positionMatrix;\n"
555
"varying highp vec2 textureCoord;\n"
558
" gl_Position = positionMatrix * vertexCoordArray;\n"
559
" textureCoord = textureCoordArray;\n"
562
// Interprets the RGBA texture as in fact being BGRx and paints it.
563
static const char *qt_glsl_bgrxShaderProgram =
564
"uniform sampler2D texRgb;\n"
565
"uniform mediump mat4 colorMatrix;\n"
566
"varying highp vec2 textureCoord;\n"
569
" highp vec4 color = vec4(texture2D(texRgb, textureCoord.st).bgr, 1.0);\n"
570
" gl_FragColor = colorMatrix * color;\n"
573
// Interprets the RGBA texture as in fact being BGRA and paints it.
574
static const char *qt_glsl_bgraShaderProgram =
575
"uniform sampler2D texRgb;\n"
576
"uniform mediump mat4 colorMatrix;\n"
577
"varying highp vec2 textureCoord;\n"
580
" highp vec4 color = vec4(texture2D(texRgb, textureCoord.st).bgr, 1.0);\n"
581
" color = colorMatrix * color;\n"
582
" gl_FragColor = vec4(color.rgb, texture2D(texRgb, textureCoord.st).a);\n"
585
// Interprets the RGBA texture as in fact being xRGB and paints it.
586
static const char *qt_glsl_xrgbShaderProgram =
587
"uniform sampler2D texRgb;\n"
588
"uniform mediump mat4 colorMatrix;\n"
589
"varying highp vec2 textureCoord;\n"
592
" highp vec4 color = vec4(texture2D(texRgb, textureCoord.st).gba, 1.0);\n"
593
" gl_FragColor = colorMatrix * color;\n"
596
// Interprets the RGBA texture as in fact being ARGB and paints it.
597
static const char *qt_glsl_argbShaderProgram =
598
"uniform sampler2D texRgb;\n"
599
"uniform mediump mat4 colorMatrix;\n"
600
"varying highp vec2 textureCoord;\n"
603
" highp vec4 color = vec4(texture2D(texRgb, textureCoord.st).gba, 1.0);\n"
604
" color = colorMatrix * color;\n"
605
" gl_FragColor = vec4(color.rgb, texture2D(texRgb, textureCoord.st).r);\n"
608
// Paints RGB frames without doing any color channel flipping.
609
static const char *qt_glsl_rgbxShaderProgram =
610
"uniform sampler2D texRgb;\n"
611
"uniform mediump mat4 colorMatrix;\n"
612
"varying highp vec2 textureCoord;\n"
615
" highp vec4 color = vec4(texture2D(texRgb, textureCoord.st).rgb, 1.0);\n"
616
" gl_FragColor = colorMatrix * color;\n"
619
// Paints planar yuv frames.
620
static const char *qt_glsl_yuvPlanarShaderProgram =
621
"uniform sampler2D texY;\n"
622
"uniform sampler2D texU;\n"
623
"uniform sampler2D texV;\n"
624
"uniform mediump mat4 colorMatrix;\n"
625
"varying highp vec2 textureCoord;\n"
628
" highp vec4 color = vec4(\n"
629
" texture2D(texY, textureCoord.st).r,\n"
630
" texture2D(texU, textureCoord.st).r,\n"
631
" texture2D(texV, textureCoord.st).r,\n"
633
" gl_FragColor = colorMatrix * color;\n"
637
GlslSurfacePainter::GlslSurfacePainter()
638
: OpenGLSurfacePainter()
642
void GlslSurfacePainter::init(const BufferFormat &format)
644
Q_ASSERT(m_textureCount == 0);
646
const char *fragmentProgram = 0;
648
switch (format.videoFormat()) {
649
case GST_VIDEO_FORMAT_BGRx:
650
initRgbTextureInfo(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize());
651
fragmentProgram = qt_glsl_bgrxShaderProgram;
653
case GST_VIDEO_FORMAT_xRGB:
654
initRgbTextureInfo(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize());
655
fragmentProgram = qt_glsl_xrgbShaderProgram;
657
case GST_VIDEO_FORMAT_BGRA:
658
initRgbTextureInfo(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize());
659
fragmentProgram = qt_glsl_bgraShaderProgram;
661
case GST_VIDEO_FORMAT_ARGB:
662
initRgbTextureInfo(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize());
663
fragmentProgram = qt_glsl_argbShaderProgram;
665
case GST_VIDEO_FORMAT_RGB:
666
initRgbTextureInfo(GL_RGB, GL_RGB, GL_UNSIGNED_BYTE, format.frameSize());
667
fragmentProgram = qt_glsl_rgbxShaderProgram;
669
case GST_VIDEO_FORMAT_BGR:
670
initRgbTextureInfo(GL_RGB, GL_RGB, GL_UNSIGNED_BYTE, format.frameSize());
671
fragmentProgram = qt_glsl_bgrxShaderProgram;
673
//NOTE: unlike the other formats, this is endianness-dependent,
674
//but using GL_UNSIGNED_SHORT_5_6_5 ensures that it's handled correctly
675
case GST_VIDEO_FORMAT_RGB16:
676
initRgbTextureInfo(GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, format.frameSize());
677
fragmentProgram = qt_glsl_rgbxShaderProgram;
679
case GST_VIDEO_FORMAT_v308:
680
initRgbTextureInfo(GL_RGB, GL_RGB, GL_UNSIGNED_BYTE, format.frameSize());
681
fragmentProgram = qt_glsl_rgbxShaderProgram;
683
case GST_VIDEO_FORMAT_AYUV:
684
initRgbTextureInfo(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize());
685
fragmentProgram = qt_glsl_argbShaderProgram;
687
case GST_VIDEO_FORMAT_YV12:
688
initYv12TextureInfo(format.frameSize());
689
fragmentProgram = qt_glsl_yuvPlanarShaderProgram;
691
case GST_VIDEO_FORMAT_I420:
692
initYuv420PTextureInfo(format.frameSize());
693
fragmentProgram = qt_glsl_yuvPlanarShaderProgram;
700
m_videoColorMatrix = format.colorMatrix();
702
if (!m_program.addShaderFromSourceCode(QGLShader::Vertex, qt_glsl_vertexShaderProgram)) {
703
throw QString("Vertex shader compile error ") + m_program.log();
706
if (!m_program.addShaderFromSourceCode(QGLShader::Fragment, fragmentProgram)) {
707
throw QString("Shader compile error ") + m_program.log();
710
if(!m_program.link()) {
711
throw QString("Shader link error ") + m_program.log();
714
glGenTextures(m_textureCount, m_textureIds);
717
void GlslSurfacePainter::cleanup()
719
glDeleteTextures(m_textureCount, m_textureIds);
720
m_program.removeAllShaders();
725
void GlslSurfacePainter::paintImpl(const QPainter *painter,
726
const GLfloat *vertexCoordArray,
727
const GLfloat *textureCoordArray)
729
const int deviceWidth = QGLContext::currentContext()->device()->width();
730
const int deviceHeight = QGLContext::currentContext()->device()->height();
732
const QTransform transform = painter->deviceTransform();
734
const GLfloat wfactor = 2.0 / deviceWidth;
735
const GLfloat hfactor = -2.0 / deviceHeight;
737
const GLfloat positionMatrix[4][4] =
740
/*(0,0)*/ GLfloat(wfactor * transform.m11() - transform.m13()),
741
/*(0,1)*/ GLfloat(hfactor * transform.m12() + transform.m13()),
743
/*(0,3)*/ GLfloat(transform.m13())
745
/*(1,0)*/ GLfloat(wfactor * transform.m21() - transform.m23()),
746
/*(1,1)*/ GLfloat(hfactor * transform.m22() + transform.m23()),
748
/*(1,3)*/ GLfloat(transform.m23())
755
/*(3,0)*/ GLfloat(wfactor * transform.dx() - transform.m33()),
756
/*(3,1)*/ GLfloat(hfactor * transform.dy() + transform.m33()),
758
/*(3,3)*/ GLfloat(transform.m33())
764
m_program.enableAttributeArray("vertexCoordArray");
765
m_program.enableAttributeArray("textureCoordArray");
766
m_program.setAttributeArray("vertexCoordArray", vertexCoordArray, 2);
767
m_program.setAttributeArray("textureCoordArray", textureCoordArray, 2);
768
m_program.setUniformValue("positionMatrix", positionMatrix);
770
if (m_textureCount == 3) {
771
glActiveTexture(GL_TEXTURE0);
772
glBindTexture(GL_TEXTURE_2D, m_textureIds[0]);
773
glActiveTexture(GL_TEXTURE1);
774
glBindTexture(GL_TEXTURE_2D, m_textureIds[1]);
775
glActiveTexture(GL_TEXTURE2);
776
glBindTexture(GL_TEXTURE_2D, m_textureIds[2]);
777
glActiveTexture(GL_TEXTURE0);
779
m_program.setUniformValue("texY", 0);
780
m_program.setUniformValue("texU", 1);
781
m_program.setUniformValue("texV", 2);
783
glActiveTexture(GL_TEXTURE0);
784
glBindTexture(GL_TEXTURE_2D, m_textureIds[0]);
786
m_program.setUniformValue("texRgb", 0);
788
m_program.setUniformValue("colorMatrix", m_colorMatrix);
790
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);