src/multimedia/qpaintervideosurface.cpp
changeset 0 876b1a06bc25
equal deleted inserted replaced
-1:000000000000 0:876b1a06bc25
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the Qt Mobility Components.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include <qpaintervideosurface_p.h>
       
    43 #include <qpaintervideosurface_mac_p.h>
       
    44 
       
    45 #include <qmath.h>
       
    46 
       
    47 #include <qpainter.h>
       
    48 #include <qvariant.h>
       
    49 #include <qvideosurfaceformat.h>
       
    50 
       
    51 #if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1)
       
    52 #include <qglshaderprogram.h>
       
    53 #endif
       
    54 
       
    55 #include <QtDebug>
       
    56 QT_BEGIN_NAMESPACE
       
    57 
       
    58 QVideoSurfacePainter::~QVideoSurfacePainter()
       
    59 {
       
    60 }
       
    61 
       
    62 class QVideoSurfaceRasterPainter : public QVideoSurfacePainter
       
    63 {
       
    64 public:
       
    65     QVideoSurfaceRasterPainter();
       
    66 
       
    67     QList<QVideoFrame::PixelFormat> supportedPixelFormats(
       
    68             QAbstractVideoBuffer::HandleType handleType) const;
       
    69 
       
    70     bool isFormatSupported(
       
    71             const QVideoSurfaceFormat &format, QVideoSurfaceFormat *similar) const;
       
    72 
       
    73     QAbstractVideoSurface::Error start(const QVideoSurfaceFormat &format);
       
    74     void stop();
       
    75 
       
    76     QAbstractVideoSurface::Error setCurrentFrame(const QVideoFrame &frame);
       
    77 
       
    78     QAbstractVideoSurface::Error paint(
       
    79             const QRectF &target, QPainter *painter, const QRectF &source);
       
    80 
       
    81     void updateColors(int brightness, int contrast, int hue, int saturation);
       
    82 
       
    83 private:
       
    84     QList<QVideoFrame::PixelFormat> m_imagePixelFormats;
       
    85     QVideoFrame m_frame;
       
    86     QSize m_imageSize;
       
    87     QImage::Format m_imageFormat;
       
    88     QVideoSurfaceFormat::Direction m_scanLineDirection;
       
    89 };
       
    90 
       
    91 QVideoSurfaceRasterPainter::QVideoSurfaceRasterPainter()
       
    92     : m_imageFormat(QImage::Format_Invalid)
       
    93     , m_scanLineDirection(QVideoSurfaceFormat::TopToBottom)
       
    94 {
       
    95     m_imagePixelFormats
       
    96         << QVideoFrame::Format_RGB32
       
    97 #ifndef QT_OPENGL_ES // The raster formats should be a subset of the GL formats.
       
    98         << QVideoFrame::Format_RGB24
       
    99 #endif
       
   100         << QVideoFrame::Format_ARGB32
       
   101         << QVideoFrame::Format_RGB565;
       
   102 }
       
   103 
       
   104 QList<QVideoFrame::PixelFormat> QVideoSurfaceRasterPainter::supportedPixelFormats(
       
   105         QAbstractVideoBuffer::HandleType handleType) const
       
   106 {
       
   107     return handleType == QAbstractVideoBuffer::NoHandle
       
   108         ? m_imagePixelFormats
       
   109         : QList<QVideoFrame::PixelFormat>();
       
   110 }
       
   111 
       
   112 bool QVideoSurfaceRasterPainter::isFormatSupported(
       
   113         const QVideoSurfaceFormat &format, QVideoSurfaceFormat *) const
       
   114 {
       
   115     return format.handleType() == QAbstractVideoBuffer::NoHandle
       
   116             && m_imagePixelFormats.contains(format.pixelFormat())
       
   117             && !format.frameSize().isEmpty();
       
   118 }
       
   119 
       
   120 QAbstractVideoSurface::Error QVideoSurfaceRasterPainter::start(const QVideoSurfaceFormat &format)
       
   121 {
       
   122     m_frame = QVideoFrame();
       
   123     m_imageFormat = QVideoFrame::imageFormatFromPixelFormat(format.pixelFormat());
       
   124     m_imageSize = format.frameSize();
       
   125     m_scanLineDirection = format.scanLineDirection();
       
   126 
       
   127     return format.handleType() == QAbstractVideoBuffer::NoHandle
       
   128             && m_imageFormat != QImage::Format_Invalid
       
   129             && !m_imageSize.isEmpty()
       
   130             ? QAbstractVideoSurface::NoError
       
   131             : QAbstractVideoSurface::UnsupportedFormatError;
       
   132 }
       
   133 
       
   134 void QVideoSurfaceRasterPainter::stop()
       
   135 {
       
   136     m_frame = QVideoFrame();
       
   137 }
       
   138 
       
   139 QAbstractVideoSurface::Error QVideoSurfaceRasterPainter::setCurrentFrame(const QVideoFrame &frame)
       
   140 {
       
   141     m_frame = frame;
       
   142 
       
   143     return QAbstractVideoSurface::NoError;
       
   144 }
       
   145 
       
   146 QAbstractVideoSurface::Error QVideoSurfaceRasterPainter::paint(
       
   147             const QRectF &target, QPainter *painter, const QRectF &source)
       
   148 {
       
   149     if (m_frame.map(QAbstractVideoBuffer::ReadOnly)) {
       
   150         QImage image(
       
   151                 m_frame.bits(),
       
   152                 m_imageSize.width(),
       
   153                 m_imageSize.height(),
       
   154                 m_frame.bytesPerLine(),
       
   155                 m_imageFormat);
       
   156 
       
   157         if (m_scanLineDirection == QVideoSurfaceFormat::BottomToTop) {
       
   158             const QTransform oldTransform = painter->transform();
       
   159 
       
   160             painter->scale(1, -1);
       
   161             painter->translate(0, -target.bottom());
       
   162             painter->drawImage(
       
   163                 QRectF(target.x(), 0, target.width(), target.height()), image, source);
       
   164             painter->setTransform(oldTransform);
       
   165         } else {
       
   166             painter->drawImage(target, image, source);
       
   167         }
       
   168 
       
   169         m_frame.unmap();
       
   170     } else if (m_frame.isValid()) {
       
   171         return QAbstractVideoSurface::IncorrectFormatError;
       
   172     } else {
       
   173         painter->fillRect(target, Qt::black);
       
   174     }
       
   175     return QAbstractVideoSurface::NoError;
       
   176 }
       
   177 
       
   178 void QVideoSurfaceRasterPainter::updateColors(int, int, int, int)
       
   179 {
       
   180 }
       
   181 
       
   182 #if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1)
       
   183 
       
   184 #ifndef Q_WS_MAC
       
   185 # ifndef APIENTRYP
       
   186 #   ifdef APIENTRY
       
   187 #     define APIENTRYP APIENTRY *
       
   188 #   else
       
   189 #     define APIENTRY
       
   190 #     define APIENTRYP *
       
   191 #   endif
       
   192 # endif
       
   193 #else
       
   194 # define APIENTRY
       
   195 # define APIENTRYP *
       
   196 #endif
       
   197 
       
   198 #ifndef GL_TEXTURE0
       
   199 #  define GL_TEXTURE0    0x84C0
       
   200 #  define GL_TEXTURE1    0x84C1
       
   201 #  define GL_TEXTURE2    0x84C2
       
   202 #endif
       
   203 #ifndef GL_PROGRAM_ERROR_STRING_ARB
       
   204 #  define GL_PROGRAM_ERROR_STRING_ARB       0x8874
       
   205 #endif
       
   206 
       
   207 #ifndef GL_UNSIGNED_SHORT_5_6_5
       
   208 #  define GL_UNSIGNED_SHORT_5_6_5 33635
       
   209 #endif
       
   210 
       
   211 class QVideoSurfaceGLPainter : public QVideoSurfacePainter
       
   212 {
       
   213 public:
       
   214     QVideoSurfaceGLPainter(QGLContext *context);
       
   215     ~QVideoSurfaceGLPainter();
       
   216     QList<QVideoFrame::PixelFormat> supportedPixelFormats(
       
   217             QAbstractVideoBuffer::HandleType handleType) const;
       
   218 
       
   219     bool isFormatSupported(
       
   220             const QVideoSurfaceFormat &format, QVideoSurfaceFormat *similar) const;
       
   221 
       
   222     QAbstractVideoSurface::Error setCurrentFrame(const QVideoFrame &frame);
       
   223 
       
   224     void updateColors(int brightness, int contrast, int hue, int saturation);
       
   225     void viewportDestroyed();
       
   226 
       
   227 protected:
       
   228     void initRgbTextureInfo(GLenum internalFormat, GLuint format, GLenum type, const QSize &size);
       
   229     void initYuv420PTextureInfo(const QSize &size);
       
   230     void initYv12TextureInfo(const QSize &size);
       
   231 
       
   232 #ifndef QT_OPENGL_ES
       
   233     typedef void (APIENTRY *_glActiveTexture) (GLenum);
       
   234     _glActiveTexture glActiveTexture;
       
   235 #endif
       
   236 
       
   237     QList<QVideoFrame::PixelFormat> m_imagePixelFormats;
       
   238     QList<QVideoFrame::PixelFormat> m_glPixelFormats;
       
   239     QMatrix4x4 m_colorMatrix;
       
   240     QVideoFrame m_frame;
       
   241 
       
   242     QGLContext *m_context;
       
   243     QAbstractVideoBuffer::HandleType m_handleType;
       
   244     QVideoSurfaceFormat::Direction m_scanLineDirection;
       
   245     QVideoSurfaceFormat::YCbCrColorSpace m_colorSpace;
       
   246     GLenum m_textureFormat;
       
   247     GLuint m_textureInternalFormat;
       
   248     GLenum m_textureType;
       
   249     int m_textureCount;
       
   250     GLuint m_textureIds[3];
       
   251     int m_textureWidths[3];
       
   252     int m_textureHeights[3];
       
   253     int m_textureOffsets[3];
       
   254     bool m_yuv;
       
   255 };
       
   256 
       
   257 QVideoSurfaceGLPainter::QVideoSurfaceGLPainter(QGLContext *context)
       
   258     : m_context(context)
       
   259     , m_handleType(QAbstractVideoBuffer::NoHandle)
       
   260     , m_scanLineDirection(QVideoSurfaceFormat::TopToBottom)
       
   261     , m_colorSpace(QVideoSurfaceFormat::YCbCr_BT601)
       
   262     , m_textureFormat(0)
       
   263     , m_textureInternalFormat(0)
       
   264     , m_textureType(0)
       
   265     , m_textureCount(0)
       
   266     , m_yuv(false)
       
   267 {
       
   268 #ifndef QT_OPENGL_ES
       
   269     glActiveTexture = (_glActiveTexture)m_context->getProcAddress(QLatin1String("glActiveTexture"));
       
   270 #endif
       
   271 }
       
   272 
       
   273 QVideoSurfaceGLPainter::~QVideoSurfaceGLPainter()
       
   274 {
       
   275 }
       
   276 
       
   277 void QVideoSurfaceGLPainter::viewportDestroyed()
       
   278 {
       
   279     m_context = 0;
       
   280 }
       
   281 
       
   282 QList<QVideoFrame::PixelFormat> QVideoSurfaceGLPainter::supportedPixelFormats(
       
   283         QAbstractVideoBuffer::HandleType handleType) const
       
   284 {
       
   285     switch (handleType) {
       
   286     case QAbstractVideoBuffer::NoHandle:
       
   287         return m_imagePixelFormats;
       
   288     case QAbstractVideoBuffer::GLTextureHandle:
       
   289         return m_glPixelFormats;
       
   290     default:
       
   291         return QList<QVideoFrame::PixelFormat>();
       
   292     }
       
   293 }
       
   294 
       
   295 bool QVideoSurfaceGLPainter::isFormatSupported(
       
   296         const QVideoSurfaceFormat &format, QVideoSurfaceFormat *) const
       
   297 {
       
   298     if (format.frameSize().isEmpty()) {
       
   299         return false;
       
   300     } else {
       
   301         switch (format.handleType()) {
       
   302         case QAbstractVideoBuffer::NoHandle:
       
   303             return m_imagePixelFormats.contains(format.pixelFormat());
       
   304         case QAbstractVideoBuffer::GLTextureHandle:
       
   305             return m_glPixelFormats.contains(format.pixelFormat());
       
   306         default:
       
   307             return false;
       
   308         }
       
   309     }
       
   310 }
       
   311 
       
   312 QAbstractVideoSurface::Error QVideoSurfaceGLPainter::setCurrentFrame(const QVideoFrame &frame)
       
   313 {
       
   314     m_frame = frame;
       
   315 
       
   316     if (m_handleType == QAbstractVideoBuffer::GLTextureHandle) {
       
   317         m_textureIds[0] = frame.handle().toInt();
       
   318     } else if (m_frame.map(QAbstractVideoBuffer::ReadOnly)) {
       
   319         m_context->makeCurrent();
       
   320 
       
   321         for (int i = 0; i < m_textureCount; ++i) {
       
   322             glBindTexture(GL_TEXTURE_2D, m_textureIds[i]);
       
   323             glTexImage2D(
       
   324                     GL_TEXTURE_2D,
       
   325                     0,
       
   326                     m_textureInternalFormat,
       
   327                     m_textureWidths[i],
       
   328                     m_textureHeights[i],
       
   329                     0,
       
   330                     m_textureFormat,
       
   331                     m_textureType,
       
   332                     m_frame.bits() + m_textureOffsets[i]);
       
   333             glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
       
   334             glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
       
   335             glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
       
   336             glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
       
   337         }
       
   338         m_frame.unmap();
       
   339     } else if (m_frame.isValid()) {
       
   340         return QAbstractVideoSurface::IncorrectFormatError;
       
   341     }
       
   342 
       
   343     return QAbstractVideoSurface::NoError;
       
   344 }
       
   345 
       
   346 void QVideoSurfaceGLPainter::updateColors(int brightness, int contrast, int hue, int saturation)
       
   347 {
       
   348     const qreal b = brightness / 200.0;
       
   349     const qreal c = contrast / 100.0 + 1.0;
       
   350     const qreal h = hue / 100.0;
       
   351     const qreal s = saturation / 100.0 + 1.0;
       
   352 
       
   353     const qreal cosH = qCos(M_PI * h);
       
   354     const qreal sinH = qSin(M_PI * h);
       
   355 
       
   356     const qreal h11 =  0.787 * cosH - 0.213 * sinH + 0.213;
       
   357     const qreal h21 = -0.213 * cosH + 0.143 * sinH + 0.213;
       
   358     const qreal h31 = -0.213 * cosH - 0.787 * sinH + 0.213;
       
   359 
       
   360     const qreal h12 = -0.715 * cosH - 0.715 * sinH + 0.715;
       
   361     const qreal h22 =  0.285 * cosH + 0.140 * sinH + 0.715;
       
   362     const qreal h32 = -0.715 * cosH + 0.715 * sinH + 0.715;
       
   363 
       
   364     const qreal h13 = -0.072 * cosH + 0.928 * sinH + 0.072;
       
   365     const qreal h23 = -0.072 * cosH - 0.283 * sinH + 0.072;
       
   366     const qreal h33 =  0.928 * cosH + 0.072 * sinH + 0.072;
       
   367 
       
   368     const qreal sr = (1.0 - s) * 0.3086;
       
   369     const qreal sg = (1.0 - s) * 0.6094;
       
   370     const qreal sb = (1.0 - s) * 0.0820;
       
   371 
       
   372     const qreal sr_s = sr + s;
       
   373     const qreal sg_s = sg + s;
       
   374     const qreal sb_s = sr + s;
       
   375 
       
   376     const float m4 = (s + sr + sg + sb) * (0.5 - 0.5 * c + b);
       
   377 
       
   378     m_colorMatrix(0, 0) = c * (sr_s * h11 + sg * h21 + sb * h31);
       
   379     m_colorMatrix(0, 1) = c * (sr_s * h12 + sg * h22 + sb * h32);
       
   380     m_colorMatrix(0, 2) = c * (sr_s * h13 + sg * h23 + sb * h33);
       
   381     m_colorMatrix(0, 3) = m4;
       
   382 
       
   383     m_colorMatrix(1, 0) = c * (sr * h11 + sg_s * h21 + sb * h31);
       
   384     m_colorMatrix(1, 1) = c * (sr * h12 + sg_s * h22 + sb * h32);
       
   385     m_colorMatrix(1, 2) = c * (sr * h13 + sg_s * h23 + sb * h33);
       
   386     m_colorMatrix(1, 3) = m4;
       
   387 
       
   388     m_colorMatrix(2, 0) = c * (sr * h11 + sg * h21 + sb_s * h31);
       
   389     m_colorMatrix(2, 1) = c * (sr * h12 + sg * h22 + sb_s * h32);
       
   390     m_colorMatrix(2, 2) = c * (sr * h13 + sg * h23 + sb_s * h33);
       
   391     m_colorMatrix(2, 3) = m4;
       
   392 
       
   393     m_colorMatrix(3, 0) = 0.0;
       
   394     m_colorMatrix(3, 1) = 0.0;
       
   395     m_colorMatrix(3, 2) = 0.0;
       
   396     m_colorMatrix(3, 3) = 1.0;
       
   397 
       
   398     if (m_yuv) {
       
   399         QMatrix4x4 colorSpaceMatrix;
       
   400 
       
   401         switch (m_colorSpace) {
       
   402         case QVideoSurfaceFormat::YCbCr_JPEG:
       
   403             colorSpaceMatrix = QMatrix4x4(
       
   404                         1.0,  0.000,  1.402, -0.701,
       
   405                         1.0, -0.344, -0.714,  0.529,
       
   406                         1.0,  1.772,  0.000, -0.886,
       
   407                         0.0,  0.000,  0.000,  1.0000);
       
   408             break;
       
   409         case QVideoSurfaceFormat::YCbCr_BT709:
       
   410         case QVideoSurfaceFormat::YCbCr_xvYCC709:
       
   411             colorSpaceMatrix = QMatrix4x4(
       
   412                         1.164,  0.000,  1.793, -0.5727,
       
   413                         1.164, -0.534, -0.213,  0.3007,
       
   414                         1.164,  2.115,  0.000, -1.1302,
       
   415                         0.0,    0.000,  0.000,  1.0000);
       
   416             break;
       
   417         default: //BT 601:
       
   418             colorSpaceMatrix = QMatrix4x4(
       
   419                         1.164,  0.000,  1.596, -0.8708,
       
   420                         1.164, -0.392, -0.813,  0.5296,
       
   421                         1.164,  2.017,  0.000, -1.081,
       
   422                         0.0,    0.000,  0.000,  1.0000);
       
   423         }
       
   424 
       
   425         m_colorMatrix = m_colorMatrix * colorSpaceMatrix;
       
   426     }
       
   427 }
       
   428 
       
   429 void QVideoSurfaceGLPainter::initRgbTextureInfo(
       
   430         GLenum internalFormat, GLuint format, GLenum type, const QSize &size)
       
   431 {
       
   432     m_yuv = false;
       
   433     m_textureInternalFormat = internalFormat;
       
   434     m_textureFormat = format;
       
   435     m_textureType = type;
       
   436     m_textureCount = 1;
       
   437     m_textureWidths[0] = size.width();
       
   438     m_textureHeights[0] = size.height();
       
   439     m_textureOffsets[0] = 0;
       
   440 }
       
   441 
       
   442 void QVideoSurfaceGLPainter::initYuv420PTextureInfo(const QSize &size)
       
   443 {
       
   444     int bytesPerLine = (size.width() + 3) & ~3;
       
   445     int bytesPerLine2 = (size.width() / 2 + 3) & ~3;
       
   446 
       
   447     m_yuv = true;
       
   448     m_textureInternalFormat = GL_LUMINANCE;
       
   449     m_textureFormat = GL_LUMINANCE;
       
   450     m_textureType = GL_UNSIGNED_BYTE;
       
   451     m_textureCount = 3;
       
   452     m_textureWidths[0] = bytesPerLine;
       
   453     m_textureHeights[0] = size.height();
       
   454     m_textureOffsets[0] = 0;
       
   455     m_textureWidths[1] = bytesPerLine2;
       
   456     m_textureHeights[1] = size.height() / 2;
       
   457     m_textureOffsets[1] = bytesPerLine * size.height();
       
   458     m_textureWidths[2] = bytesPerLine2;
       
   459     m_textureHeights[2] = size.height() / 2;
       
   460     m_textureOffsets[2] = bytesPerLine * size.height() + bytesPerLine2 * size.height()/2;
       
   461 }
       
   462 
       
   463 void QVideoSurfaceGLPainter::initYv12TextureInfo(const QSize &size)
       
   464 {
       
   465     int bytesPerLine = (size.width() + 3) & ~3;
       
   466     int bytesPerLine2 = (size.width() / 2 + 3) & ~3;
       
   467 
       
   468     m_yuv = true;
       
   469     m_textureInternalFormat = GL_LUMINANCE;
       
   470     m_textureFormat = GL_LUMINANCE;
       
   471     m_textureType = GL_UNSIGNED_BYTE;
       
   472     m_textureCount = 3;
       
   473     m_textureWidths[0] = bytesPerLine;
       
   474     m_textureHeights[0] = size.height();
       
   475     m_textureOffsets[0] = 0;
       
   476     m_textureWidths[1] = bytesPerLine2;
       
   477     m_textureHeights[1] = size.height() / 2;
       
   478     m_textureOffsets[1] = bytesPerLine * size.height() + bytesPerLine2 * size.height()/2;
       
   479     m_textureWidths[2] = bytesPerLine2;
       
   480     m_textureHeights[2] = size.height() / 2;
       
   481     m_textureOffsets[2] = bytesPerLine * size.height();
       
   482 }
       
   483 
       
   484 #ifndef QT_OPENGL_ES
       
   485 
       
   486 # ifndef GL_FRAGMENT_PROGRAM_ARB
       
   487 #  define GL_FRAGMENT_PROGRAM_ARB           0x8804
       
   488 #  define GL_PROGRAM_FORMAT_ASCII_ARB       0x8875
       
   489 # endif
       
   490 
       
   491 // Paints an RGB32 frame
       
   492 static const char *qt_arbfp_xrgbShaderProgram =
       
   493     "!!ARBfp1.0\n"
       
   494     "PARAM matrix[4] = { program.local[0..2],"
       
   495     "{ 0.0, 0.0, 0.0, 1.0 } };\n"
       
   496     "TEMP xrgb;\n"
       
   497     "TEX xrgb.xyz, fragment.texcoord[0], texture[0], 2D;\n"
       
   498     "MOV xrgb.w, matrix[3].w;\n"
       
   499     "DP4 result.color.x, xrgb.zyxw, matrix[0];\n"
       
   500     "DP4 result.color.y, xrgb.zyxw, matrix[1];\n"
       
   501     "DP4 result.color.z, xrgb.zyxw, matrix[2];\n"
       
   502     "END";
       
   503 
       
   504 // Paints an ARGB frame.
       
   505 static const char *qt_arbfp_argbShaderProgram =
       
   506     "!!ARBfp1.0\n"
       
   507     "PARAM matrix[4] = { program.local[0..2],"
       
   508     "{ 0.0, 0.0, 0.0, 1.0 } };\n"
       
   509     "TEMP argb;\n"
       
   510     "TEX argb, fragment.texcoord[0], texture[0], 2D;\n"
       
   511     "MOV argb.w, matrix[3].w;\n"
       
   512     "DP4 result.color.x, argb.zyxw, matrix[0];\n"
       
   513     "DP4 result.color.y, argb.zyxw, matrix[1];\n"
       
   514     "DP4 result.color.z, argb.zyxw, matrix[2];\n"
       
   515     "TEX result.color.w, fragment.texcoord[0], texture, 2D;\n"
       
   516     "END";
       
   517 
       
   518 // Paints an RGB(A) frame.
       
   519 static const char *qt_arbfp_rgbShaderProgram =
       
   520     "!!ARBfp1.0\n"
       
   521     "PARAM matrix[4] = { program.local[0..2],"
       
   522     "{ 0.0, 0.0, 0.0, 1.0 } };\n"
       
   523     "TEMP rgb;\n"
       
   524     "TEX rgb, fragment.texcoord[0], texture[0], 2D;\n"
       
   525     "MOV rgb.w, matrix[3].w;\n"
       
   526     "DP4 result.color.x, rgb, matrix[0];\n"
       
   527     "DP4 result.color.y, rgb, matrix[1];\n"
       
   528     "DP4 result.color.z, rgb, matrix[2];\n"
       
   529     "TEX result.color.w, fragment.texcoord[0], texture, 2D;\n"
       
   530     "END";
       
   531 
       
   532 // Paints a YUV420P or YV12 frame.
       
   533 static const char *qt_arbfp_yuvPlanarShaderProgram =
       
   534     "!!ARBfp1.0\n"
       
   535     "PARAM matrix[4] = { program.local[0..2],"
       
   536     "{ 0.0, 0.0, 0.0, 1.0 } };\n"
       
   537     "TEMP yuv;\n"
       
   538     "TEX yuv.x, fragment.texcoord[0], texture[0], 2D;\n"
       
   539     "TEX yuv.y, fragment.texcoord[0], texture[1], 2D;\n"
       
   540     "TEX yuv.z, fragment.texcoord[0], texture[2], 2D;\n"
       
   541     "MOV yuv.w, matrix[3].w;\n"
       
   542     "DP4 result.color.x, yuv, matrix[0];\n"
       
   543     "DP4 result.color.y, yuv, matrix[1];\n"
       
   544     "DP4 result.color.z, yuv, matrix[2];\n"
       
   545     "END";
       
   546 
       
   547 // Paints a YUV444 frame.
       
   548 static const char *qt_arbfp_xyuvShaderProgram =
       
   549     "!!ARBfp1.0\n"
       
   550     "PARAM matrix[4] = { program.local[0..2],"
       
   551     "{ 0.0, 0.0, 0.0, 1.0 } };\n"
       
   552     "TEMP ayuv;\n"
       
   553     "TEX ayuv, fragment.texcoord[0], texture[0], 2D;\n"
       
   554     "MOV ayuv.x, matrix[3].w;\n"
       
   555     "DP4 result.color.x, ayuv.yzwx, matrix[0];\n"
       
   556     "DP4 result.color.y, ayuv.yzwx, matrix[1];\n"
       
   557     "DP4 result.color.z, ayuv.yzwx, matrix[2];\n"
       
   558     "END";
       
   559 
       
   560 // Paints a AYUV444 frame.
       
   561 static const char *qt_arbfp_ayuvShaderProgram =
       
   562     "!!ARBfp1.0\n"
       
   563     "PARAM matrix[4] = { program.local[0..2],"
       
   564     "{ 0.0, 0.0, 0.0, 1.0 } };\n"
       
   565     "TEMP ayuv;\n"
       
   566     "TEX ayuv, fragment.texcoord[0], texture[0], 2D;\n"
       
   567     "MOV ayuv.x, matrix[3].w;\n"
       
   568     "DP4 result.color.x, ayuv.yzwx, matrix[0];\n"
       
   569     "DP4 result.color.y, ayuv.yzwx, matrix[1];\n"
       
   570     "DP4 result.color.z, ayuv.yzwx, matrix[2];\n"
       
   571     "TEX result.color.w, fragment.texcoord[0], texture, 2D;\n"
       
   572     "END";
       
   573 
       
   574 class QVideoSurfaceArbFpPainter : public QVideoSurfaceGLPainter
       
   575 {
       
   576 public:
       
   577     QVideoSurfaceArbFpPainter(QGLContext *context);
       
   578 
       
   579     QAbstractVideoSurface::Error start(const QVideoSurfaceFormat &format);
       
   580     void stop();
       
   581 
       
   582     QAbstractVideoSurface::Error paint(
       
   583             const QRectF &target, QPainter *painter, const QRectF &source);
       
   584 
       
   585 private:
       
   586     typedef void (APIENTRY *_glProgramStringARB) (GLenum, GLenum, GLsizei, const GLvoid *);
       
   587     typedef void (APIENTRY *_glBindProgramARB) (GLenum, GLuint);
       
   588     typedef void (APIENTRY *_glDeleteProgramsARB) (GLsizei, const GLuint *);
       
   589     typedef void (APIENTRY *_glGenProgramsARB) (GLsizei, GLuint *);
       
   590     typedef void (APIENTRY *_glProgramLocalParameter4fARB) (
       
   591             GLenum, GLuint, GLfloat, GLfloat, GLfloat, GLfloat);
       
   592     typedef void (APIENTRY *_glActiveTexture) (GLenum);
       
   593 
       
   594     _glProgramStringARB glProgramStringARB;
       
   595     _glBindProgramARB glBindProgramARB;
       
   596     _glDeleteProgramsARB glDeleteProgramsARB;
       
   597     _glGenProgramsARB glGenProgramsARB;
       
   598     _glProgramLocalParameter4fARB glProgramLocalParameter4fARB;
       
   599 
       
   600     GLuint m_programId;
       
   601     QSize m_frameSize;
       
   602 };
       
   603 
       
   604 QVideoSurfaceArbFpPainter::QVideoSurfaceArbFpPainter(QGLContext *context)
       
   605     : QVideoSurfaceGLPainter(context)
       
   606     , m_programId(0)
       
   607 {
       
   608     glProgramStringARB = (_glProgramStringARB) m_context->getProcAddress(
       
   609                 QLatin1String("glProgramStringARB"));
       
   610     glBindProgramARB = (_glBindProgramARB) m_context->getProcAddress(
       
   611                 QLatin1String("glBindProgramARB"));
       
   612     glDeleteProgramsARB = (_glDeleteProgramsARB) m_context->getProcAddress(
       
   613                 QLatin1String("glDeleteProgramsARB"));
       
   614     glGenProgramsARB = (_glGenProgramsARB) m_context->getProcAddress(
       
   615                 QLatin1String("glGenProgramsARB"));
       
   616     glProgramLocalParameter4fARB = (_glProgramLocalParameter4fARB) m_context->getProcAddress(
       
   617                 QLatin1String("glProgramLocalParameter4fARB"));
       
   618 
       
   619     m_imagePixelFormats
       
   620             << QVideoFrame::Format_RGB32
       
   621             << QVideoFrame::Format_BGR32
       
   622             << QVideoFrame::Format_ARGB32
       
   623             << QVideoFrame::Format_RGB24
       
   624             << QVideoFrame::Format_BGR24
       
   625             << QVideoFrame::Format_RGB565
       
   626             << QVideoFrame::Format_AYUV444
       
   627             << QVideoFrame::Format_YUV444
       
   628             << QVideoFrame::Format_YV12
       
   629             << QVideoFrame::Format_YUV420P;
       
   630     m_glPixelFormats
       
   631             << QVideoFrame::Format_RGB32
       
   632             << QVideoFrame::Format_ARGB32;
       
   633 }
       
   634 
       
   635 QAbstractVideoSurface::Error QVideoSurfaceArbFpPainter::start(const QVideoSurfaceFormat &format)
       
   636 {
       
   637     Q_ASSERT(m_textureCount == 0);
       
   638 
       
   639     QAbstractVideoSurface::Error error = QAbstractVideoSurface::NoError;
       
   640 
       
   641     m_context->makeCurrent();
       
   642 
       
   643     const char *program = 0;
       
   644 
       
   645     if (format.handleType() == QAbstractVideoBuffer::NoHandle) {
       
   646         switch (format.pixelFormat()) {
       
   647         case QVideoFrame::Format_RGB32:
       
   648             initRgbTextureInfo(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize());
       
   649             program = qt_arbfp_xrgbShaderProgram;
       
   650             break;
       
   651         case QVideoFrame::Format_BGR32:
       
   652             initRgbTextureInfo(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize());
       
   653             program = qt_arbfp_rgbShaderProgram;
       
   654             break;
       
   655         case QVideoFrame::Format_ARGB32:
       
   656             initRgbTextureInfo(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize());
       
   657             program = qt_arbfp_argbShaderProgram;
       
   658             break;
       
   659         case QVideoFrame::Format_RGB24:
       
   660             initRgbTextureInfo(GL_RGB8, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize());
       
   661             program = qt_arbfp_rgbShaderProgram;
       
   662             break;
       
   663         case QVideoFrame::Format_BGR24:
       
   664             initRgbTextureInfo(GL_RGB8, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize());
       
   665             program = qt_arbfp_xrgbShaderProgram;
       
   666             break;
       
   667         case QVideoFrame::Format_RGB565:
       
   668             initRgbTextureInfo(GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, format.frameSize());
       
   669             program = qt_arbfp_rgbShaderProgram;
       
   670             break;
       
   671         case QVideoFrame::Format_YUV444:
       
   672             initRgbTextureInfo(GL_RGB, GL_RGB, GL_UNSIGNED_BYTE, format.frameSize());
       
   673             program = qt_arbfp_xyuvShaderProgram;
       
   674             m_yuv = true;
       
   675             break;
       
   676         case QVideoFrame::Format_AYUV444:
       
   677             initRgbTextureInfo(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize());
       
   678             program = qt_arbfp_ayuvShaderProgram;
       
   679             m_yuv = true;
       
   680             break;
       
   681         case QVideoFrame::Format_YV12:
       
   682             initYv12TextureInfo(format.frameSize());
       
   683             program = qt_arbfp_yuvPlanarShaderProgram;
       
   684             break;
       
   685         case QVideoFrame::Format_YUV420P:
       
   686             initYuv420PTextureInfo(format.frameSize());
       
   687             program = qt_arbfp_yuvPlanarShaderProgram;
       
   688             break;
       
   689         default:
       
   690             break;
       
   691         }
       
   692     } else if (format.handleType() == QAbstractVideoBuffer::GLTextureHandle) {
       
   693         switch (format.pixelFormat()) {
       
   694         case QVideoFrame::Format_RGB32:
       
   695         case QVideoFrame::Format_ARGB32:
       
   696             m_yuv = false;
       
   697             m_textureCount = 1;
       
   698             program = qt_arbfp_rgbShaderProgram;
       
   699             break;
       
   700         default:
       
   701             break;
       
   702         }
       
   703     }
       
   704 
       
   705     if (!program) {
       
   706         error = QAbstractVideoSurface::UnsupportedFormatError;
       
   707     } else {
       
   708         glGenProgramsARB(1, &m_programId);
       
   709 
       
   710         GLenum glError = glGetError();
       
   711         if (glError != GL_NO_ERROR) {
       
   712             qWarning("QPainterVideoSurface: ARBfb Shader allocation error %x", int(glError));
       
   713             m_textureCount = 0;
       
   714             m_programId = 0;
       
   715 
       
   716             error = QAbstractVideoSurface::ResourceError;
       
   717         } else {
       
   718             glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, m_programId);
       
   719             glProgramStringARB(
       
   720                     GL_FRAGMENT_PROGRAM_ARB,
       
   721                     GL_PROGRAM_FORMAT_ASCII_ARB,
       
   722                     qstrlen(program),
       
   723                     reinterpret_cast<const GLvoid *>(program));
       
   724 
       
   725             if ((glError = glGetError()) != GL_NO_ERROR) {
       
   726                 const GLubyte* errorString = glGetString(GL_PROGRAM_ERROR_STRING_ARB);
       
   727 
       
   728                 qWarning("QPainterVideoSurface: ARBfp Shader compile error %x, %s",
       
   729                          int(glError),
       
   730                          reinterpret_cast<const char *>(errorString));
       
   731                 glDeleteProgramsARB(1, &m_programId);
       
   732 
       
   733                 m_textureCount = 0;
       
   734                 m_programId = 0;
       
   735 
       
   736                 error = QAbstractVideoSurface::ResourceError;
       
   737             } else {
       
   738                 m_handleType = format.handleType();
       
   739                 m_scanLineDirection = format.scanLineDirection();
       
   740                 m_frameSize = format.frameSize();
       
   741                 m_colorSpace = format.yCbCrColorSpace();
       
   742 
       
   743                 if (m_handleType == QAbstractVideoBuffer::NoHandle)
       
   744                     glGenTextures(m_textureCount, m_textureIds);
       
   745             }
       
   746         }
       
   747     }
       
   748 
       
   749     return error;
       
   750 }
       
   751 
       
   752 void QVideoSurfaceArbFpPainter::stop()
       
   753 {
       
   754     if (m_context) {
       
   755         m_context->makeCurrent();
       
   756 
       
   757         if (m_handleType != QAbstractVideoBuffer::GLTextureHandle)
       
   758             glDeleteTextures(m_textureCount, m_textureIds);
       
   759         glDeleteProgramsARB(1, &m_programId);
       
   760     }
       
   761 
       
   762     m_textureCount = 0;
       
   763     m_programId = 0;
       
   764     m_handleType = QAbstractVideoBuffer::NoHandle;
       
   765 }
       
   766 
       
   767 QAbstractVideoSurface::Error QVideoSurfaceArbFpPainter::paint(
       
   768         const QRectF &target, QPainter *painter, const QRectF &source)
       
   769 {
       
   770     if (m_frame.isValid()) {
       
   771         bool stencilTestEnabled = glIsEnabled(GL_STENCIL_TEST);
       
   772         bool scissorTestEnabled = glIsEnabled(GL_SCISSOR_TEST);
       
   773 
       
   774         painter->beginNativePainting();
       
   775 
       
   776         if (stencilTestEnabled)
       
   777             glEnable(GL_STENCIL_TEST);
       
   778         if (scissorTestEnabled)
       
   779             glEnable(GL_SCISSOR_TEST);
       
   780 
       
   781         const float txLeft = source.left() / m_frameSize.width();
       
   782         const float txRight = source.right() / m_frameSize.width();
       
   783         const float txTop = m_scanLineDirection == QVideoSurfaceFormat::TopToBottom
       
   784                 ? source.top() / m_frameSize.height()
       
   785                 : source.bottom() / m_frameSize.height();
       
   786         const float txBottom = m_scanLineDirection == QVideoSurfaceFormat::TopToBottom
       
   787                 ? source.bottom() / m_frameSize.height()
       
   788                 : source.top() / m_frameSize.height();
       
   789 
       
   790         const float tx_array[] =
       
   791         {
       
   792             txLeft , txBottom,
       
   793             txRight, txBottom,
       
   794             txLeft , txTop,
       
   795             txRight, txTop
       
   796         };
       
   797 
       
   798         const GLfloat vTop = m_scanLineDirection == QVideoSurfaceFormat::TopToBottom
       
   799                 ? target.top()
       
   800                 : target.bottom() + 1;
       
   801         const GLfloat vBottom = m_scanLineDirection == QVideoSurfaceFormat::TopToBottom
       
   802                 ? target.bottom() + 1
       
   803                 : target.top();
       
   804 
       
   805         const GLfloat v_array[] =
       
   806         {
       
   807             target.left()     , vBottom,
       
   808             target.right() + 1, vBottom,
       
   809             target.left()     , vTop,
       
   810             target.right() + 1, vTop
       
   811         };
       
   812 
       
   813         glEnable(GL_FRAGMENT_PROGRAM_ARB);
       
   814         glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, m_programId);
       
   815 
       
   816         glProgramLocalParameter4fARB(
       
   817                 GL_FRAGMENT_PROGRAM_ARB,
       
   818                 0,
       
   819                 m_colorMatrix(0, 0),
       
   820                 m_colorMatrix(0, 1),
       
   821                 m_colorMatrix(0, 2),
       
   822                 m_colorMatrix(0, 3));
       
   823         glProgramLocalParameter4fARB(
       
   824                 GL_FRAGMENT_PROGRAM_ARB,
       
   825                 1,
       
   826                 m_colorMatrix(1, 0),
       
   827                 m_colorMatrix(1, 1),
       
   828                 m_colorMatrix(1, 2),
       
   829                 m_colorMatrix(1, 3));
       
   830         glProgramLocalParameter4fARB(
       
   831                 GL_FRAGMENT_PROGRAM_ARB,
       
   832                 2,
       
   833                 m_colorMatrix(2, 0),
       
   834                 m_colorMatrix(2, 1),
       
   835                 m_colorMatrix(2, 2),
       
   836                 m_colorMatrix(2, 3));
       
   837 
       
   838         glActiveTexture(GL_TEXTURE0);
       
   839         glBindTexture(GL_TEXTURE_2D, m_textureIds[0]);
       
   840 
       
   841         if (m_textureCount == 3) {
       
   842             glActiveTexture(GL_TEXTURE1);
       
   843             glBindTexture(GL_TEXTURE_2D, m_textureIds[1]);
       
   844             glActiveTexture(GL_TEXTURE2);
       
   845             glBindTexture(GL_TEXTURE_2D, m_textureIds[2]);
       
   846             glActiveTexture(GL_TEXTURE0);
       
   847         }
       
   848 
       
   849         glVertexPointer(2, GL_FLOAT, 0, v_array);
       
   850         glTexCoordPointer(2, GL_FLOAT, 0, tx_array);
       
   851 
       
   852         glEnableClientState(GL_VERTEX_ARRAY);
       
   853         glEnableClientState(GL_TEXTURE_COORD_ARRAY);
       
   854 
       
   855         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
       
   856 
       
   857         glDisableClientState(GL_TEXTURE_COORD_ARRAY);
       
   858         glDisableClientState(GL_VERTEX_ARRAY);
       
   859         glDisable(GL_FRAGMENT_PROGRAM_ARB);
       
   860 
       
   861         painter->endNativePainting();
       
   862     }
       
   863     return QAbstractVideoSurface::NoError;
       
   864 }
       
   865 
       
   866 #endif
       
   867 
       
   868 static const char *qt_glsl_vertexShaderProgram =
       
   869         "attribute highp vec4 vertexCoordArray;\n"
       
   870         "attribute highp vec2 textureCoordArray;\n"
       
   871         "uniform highp mat4 positionMatrix;\n"
       
   872         "varying highp vec2 textureCoord;\n"
       
   873         "void main(void)\n"
       
   874         "{\n"
       
   875         "   gl_Position = positionMatrix * vertexCoordArray;\n"
       
   876         "   textureCoord = textureCoordArray;\n"
       
   877         "}\n";
       
   878 
       
   879 // Paints an RGB32 frame
       
   880 static const char *qt_glsl_xrgbShaderProgram =
       
   881         "uniform sampler2D texRgb;\n"
       
   882         "uniform mediump mat4 colorMatrix;\n"
       
   883         "varying highp vec2 textureCoord;\n"
       
   884         "void main(void)\n"
       
   885         "{\n"
       
   886         "    highp vec4 color = vec4(texture2D(texRgb, textureCoord.st).bgr, 1.0);\n"
       
   887         "    gl_FragColor = colorMatrix * color;\n"
       
   888         "}\n";
       
   889 
       
   890 // Paints an ARGB frame.
       
   891 static const char *qt_glsl_argbShaderProgram =
       
   892         "uniform sampler2D texRgb;\n"
       
   893         "uniform mediump mat4 colorMatrix;\n"
       
   894         "varying highp vec2 textureCoord;\n"
       
   895         "void main(void)\n"
       
   896         "{\n"
       
   897         "    highp vec4 color = vec4(texture2D(texRgb, textureCoord.st).bgr, 1.0);\n"
       
   898         "    color = colorMatrix * color;\n"
       
   899         "    gl_FragColor = vec4(color.rgb, texture2D(texRgb, textureCoord.st).a);\n"
       
   900         "}\n";
       
   901 
       
   902 // Paints an RGB(A) frame.
       
   903 static const char *qt_glsl_rgbShaderProgram =
       
   904         "uniform sampler2D texRgb;\n"
       
   905         "uniform mediump mat4 colorMatrix;\n"
       
   906         "varying highp vec2 textureCoord;\n"
       
   907         "void main(void)\n"
       
   908         "{\n"
       
   909         "    highp vec4 color = vec4(texture2D(texRgb, textureCoord.st).rgb, 1.0);\n"
       
   910         "    color = colorMatrix * color;\n"
       
   911         "    gl_FragColor = vec4(color.rgb, texture2D(texRgb, textureCoord.st).a);\n"
       
   912         "}\n";
       
   913 
       
   914 // Paints a YUV420P or YV12 frame.
       
   915 static const char *qt_glsl_yuvPlanarShaderProgram =
       
   916         "uniform sampler2D texY;\n"
       
   917         "uniform sampler2D texU;\n"
       
   918         "uniform sampler2D texV;\n"
       
   919         "uniform mediump mat4 colorMatrix;\n"
       
   920         "varying highp vec2 textureCoord;\n"
       
   921         "void main(void)\n"
       
   922         "{\n"
       
   923         "    highp vec4 color = vec4(\n"
       
   924         "           texture2D(texY, textureCoord.st).r,\n"
       
   925         "           texture2D(texU, textureCoord.st).r,\n"
       
   926         "           texture2D(texV, textureCoord.st).r,\n"
       
   927         "           1.0);\n"
       
   928         "    gl_FragColor = colorMatrix * color;\n"
       
   929         "}\n";
       
   930 
       
   931 // Paints a YUV444 frame.
       
   932 static const char *qt_glsl_xyuvShaderProgram =
       
   933         "uniform sampler2D texRgb;\n"
       
   934         "uniform mediump mat4 colorMatrix;\n"
       
   935         "varying highp vec2 textureCoord;\n"
       
   936         "void main(void)\n"
       
   937         "{\n"
       
   938         "    highp vec4 color = vec4(texture2D(texRgb, textureCoord.st).gba, 1.0);\n"
       
   939         "    gl_FragColor = colorMatrix * color;\n"
       
   940         "}\n";
       
   941 
       
   942 // Paints a AYUV444 frame.
       
   943 static const char *qt_glsl_ayuvShaderProgram =
       
   944         "uniform sampler2D texRgb;\n"
       
   945         "uniform mediump mat4 colorMatrix;\n"
       
   946         "varying highp vec2 textureCoord;\n"
       
   947         "void main(void)\n"
       
   948         "{\n"
       
   949         "    highp vec4 color = vec4(texture2D(texRgb, textureCoord.st).gba, 1.0);\n"
       
   950         "    color = colorMatrix * color;\n"
       
   951         "    gl_FragColor = vec4(color.rgb, texture2D(texRgb, textureCoord.st).r);\n"
       
   952         "}\n";
       
   953 
       
   954 class QVideoSurfaceGlslPainter : public QVideoSurfaceGLPainter
       
   955 {
       
   956 public:
       
   957     QVideoSurfaceGlslPainter(QGLContext *context);
       
   958 
       
   959     QAbstractVideoSurface::Error start(const QVideoSurfaceFormat &format);
       
   960     void stop();
       
   961 
       
   962     QAbstractVideoSurface::Error paint(
       
   963             const QRectF &target, QPainter *painter, const QRectF &source);
       
   964 
       
   965 private:
       
   966     QGLShaderProgram m_program;
       
   967     QSize m_frameSize;
       
   968 };
       
   969 
       
   970 QVideoSurfaceGlslPainter::QVideoSurfaceGlslPainter(QGLContext *context)
       
   971     : QVideoSurfaceGLPainter(context)
       
   972     , m_program(context)
       
   973 {
       
   974     m_imagePixelFormats
       
   975             << QVideoFrame::Format_RGB32
       
   976             << QVideoFrame::Format_BGR32
       
   977             << QVideoFrame::Format_ARGB32
       
   978 #ifndef QT_OPENGL_ES
       
   979             << QVideoFrame::Format_RGB24
       
   980             << QVideoFrame::Format_BGR24
       
   981 #endif
       
   982             << QVideoFrame::Format_RGB565
       
   983             << QVideoFrame::Format_YUV444
       
   984             << QVideoFrame::Format_AYUV444
       
   985             << QVideoFrame::Format_YV12
       
   986             << QVideoFrame::Format_YUV420P;
       
   987     m_glPixelFormats
       
   988             << QVideoFrame::Format_RGB32
       
   989             << QVideoFrame::Format_ARGB32;
       
   990 }
       
   991 
       
   992 QAbstractVideoSurface::Error QVideoSurfaceGlslPainter::start(const QVideoSurfaceFormat &format)
       
   993 {
       
   994     Q_ASSERT(m_textureCount == 0);
       
   995 
       
   996     QAbstractVideoSurface::Error error = QAbstractVideoSurface::NoError;
       
   997 
       
   998     m_context->makeCurrent();
       
   999 
       
  1000     const char *fragmentProgram = 0;
       
  1001 
       
  1002     if (format.handleType() == QAbstractVideoBuffer::NoHandle) {
       
  1003         switch (format.pixelFormat()) {
       
  1004         case QVideoFrame::Format_RGB32:
       
  1005             initRgbTextureInfo(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize());
       
  1006             fragmentProgram = qt_glsl_xrgbShaderProgram;
       
  1007             break;
       
  1008         case QVideoFrame::Format_BGR32:
       
  1009             initRgbTextureInfo(GL_RGB, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize());
       
  1010             fragmentProgram = qt_glsl_rgbShaderProgram;
       
  1011             break;
       
  1012         case QVideoFrame::Format_ARGB32:
       
  1013             initRgbTextureInfo(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize());
       
  1014             fragmentProgram = qt_glsl_argbShaderProgram;
       
  1015             break;
       
  1016 #ifndef QT_OPENGL_ES
       
  1017         case QVideoFrame::Format_RGB24:
       
  1018             initRgbTextureInfo(GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE, format.frameSize());
       
  1019             fragmentProgram = qt_glsl_rgbShaderProgram;
       
  1020             break;
       
  1021         case QVideoFrame::Format_BGR24:
       
  1022             initRgbTextureInfo(GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE, format.frameSize());
       
  1023             fragmentProgram = qt_glsl_argbShaderProgram;
       
  1024             break;
       
  1025 #endif
       
  1026         case QVideoFrame::Format_RGB565:
       
  1027             initRgbTextureInfo(GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, format.frameSize());
       
  1028             fragmentProgram = qt_glsl_rgbShaderProgram;
       
  1029             break;
       
  1030         case QVideoFrame::Format_YUV444:
       
  1031             initRgbTextureInfo(GL_RGB, GL_RGB, GL_UNSIGNED_BYTE, format.frameSize());
       
  1032             fragmentProgram = qt_glsl_xyuvShaderProgram;
       
  1033             m_yuv = true;
       
  1034             break;
       
  1035         case QVideoFrame::Format_AYUV444:
       
  1036             initRgbTextureInfo(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize());
       
  1037             fragmentProgram = qt_glsl_ayuvShaderProgram;
       
  1038             m_yuv = true;
       
  1039             break;
       
  1040         case QVideoFrame::Format_YV12:
       
  1041             initYv12TextureInfo(format.frameSize());
       
  1042             fragmentProgram = qt_glsl_yuvPlanarShaderProgram;
       
  1043             break;
       
  1044         case QVideoFrame::Format_YUV420P:
       
  1045             initYuv420PTextureInfo(format.frameSize());
       
  1046             fragmentProgram = qt_glsl_yuvPlanarShaderProgram;
       
  1047             break;
       
  1048         default:
       
  1049             break;
       
  1050         }
       
  1051     } else if (format.handleType() == QAbstractVideoBuffer::GLTextureHandle) {
       
  1052         switch (format.pixelFormat()) {
       
  1053         case QVideoFrame::Format_RGB32:
       
  1054         case QVideoFrame::Format_ARGB32:
       
  1055             m_yuv = false;
       
  1056             m_textureCount = 1;
       
  1057             fragmentProgram = qt_glsl_rgbShaderProgram;
       
  1058             break;
       
  1059         default:
       
  1060             break;
       
  1061         }
       
  1062     }
       
  1063 
       
  1064     if (!fragmentProgram) {
       
  1065         error = QAbstractVideoSurface::UnsupportedFormatError;
       
  1066     } else if (!m_program.addShaderFromSourceCode(QGLShader::Vertex, qt_glsl_vertexShaderProgram)) {
       
  1067         qWarning("QPainterVideoSurface: Vertex shader compile error %s",
       
  1068                  qPrintable(m_program.log()));
       
  1069         error = QAbstractVideoSurface::ResourceError;
       
  1070     } else if (!m_program.addShaderFromSourceCode(QGLShader::Fragment, fragmentProgram)) {
       
  1071         qWarning("QPainterVideoSurface: Shader compile error %s", qPrintable(m_program.log()));
       
  1072         error = QAbstractVideoSurface::ResourceError;
       
  1073         m_program.removeAllShaders();
       
  1074     } else if(!m_program.link()) {
       
  1075         qWarning("QPainterVideoSurface: Shader link error %s", qPrintable(m_program.log()));
       
  1076         m_program.removeAllShaders();
       
  1077         error = QAbstractVideoSurface::ResourceError;
       
  1078     } else {
       
  1079         m_handleType = format.handleType();
       
  1080         m_scanLineDirection = format.scanLineDirection();
       
  1081         m_frameSize = format.frameSize();
       
  1082         m_colorSpace = format.yCbCrColorSpace();
       
  1083 
       
  1084         if (m_handleType == QAbstractVideoBuffer::NoHandle)
       
  1085             glGenTextures(m_textureCount, m_textureIds);
       
  1086     }
       
  1087 
       
  1088     return error;
       
  1089 }
       
  1090 
       
  1091 void QVideoSurfaceGlslPainter::stop()
       
  1092 {
       
  1093     if (m_context) {
       
  1094         m_context->makeCurrent();
       
  1095 
       
  1096         if (m_handleType != QAbstractVideoBuffer::GLTextureHandle)
       
  1097             glDeleteTextures(m_textureCount, m_textureIds);
       
  1098     }
       
  1099 
       
  1100     m_program.removeAllShaders();
       
  1101 
       
  1102     m_textureCount = 0;
       
  1103     m_handleType = QAbstractVideoBuffer::NoHandle;
       
  1104 }
       
  1105 
       
  1106 QAbstractVideoSurface::Error QVideoSurfaceGlslPainter::paint(
       
  1107         const QRectF &target, QPainter *painter, const QRectF &source)
       
  1108 {
       
  1109     if (m_frame.isValid()) {
       
  1110         bool stencilTestEnabled = glIsEnabled(GL_STENCIL_TEST);
       
  1111         bool scissorTestEnabled = glIsEnabled(GL_SCISSOR_TEST);
       
  1112 
       
  1113         painter->beginNativePainting();
       
  1114 
       
  1115         if (stencilTestEnabled)
       
  1116             glEnable(GL_STENCIL_TEST);
       
  1117         if (scissorTestEnabled)
       
  1118             glEnable(GL_SCISSOR_TEST);
       
  1119 
       
  1120         const int width = QGLContext::currentContext()->device()->width();
       
  1121         const int height = QGLContext::currentContext()->device()->height();
       
  1122 
       
  1123         const QTransform transform = painter->deviceTransform();
       
  1124 
       
  1125         const GLfloat wfactor = 2.0 / width;
       
  1126         const GLfloat hfactor = -2.0 / height;
       
  1127 
       
  1128         const GLfloat positionMatrix[4][4] =
       
  1129         {
       
  1130             {
       
  1131                 /*(0,0)*/ wfactor * transform.m11() - transform.m13(),
       
  1132                 /*(0,1)*/ hfactor * transform.m12() + transform.m13(),
       
  1133                 /*(0,2)*/ 0.0,
       
  1134                 /*(0,3)*/ transform.m13()
       
  1135             }, {
       
  1136                 /*(1,0)*/ wfactor * transform.m21() - transform.m23(),
       
  1137                 /*(1,1)*/ hfactor * transform.m22() + transform.m23(),
       
  1138                 /*(1,2)*/ 0.0,
       
  1139                 /*(1,3)*/ transform.m23()
       
  1140             }, {
       
  1141                 /*(2,0)*/ 0.0,
       
  1142                 /*(2,1)*/ 0.0,
       
  1143                 /*(2,2)*/ -1.0,
       
  1144                 /*(2,3)*/ 0.0
       
  1145             }, {
       
  1146                 /*(3,0)*/ wfactor * transform.dx() - transform.m33(),
       
  1147                 /*(3,1)*/ hfactor * transform.dy() + transform.m33(),
       
  1148                 /*(3,2)*/ 0.0,
       
  1149                 /*(3,3)*/ transform.m33()
       
  1150             }
       
  1151         };
       
  1152 
       
  1153         const GLfloat vTop = m_scanLineDirection == QVideoSurfaceFormat::TopToBottom
       
  1154                 ? target.top()
       
  1155                 : target.bottom() + 1;
       
  1156         const GLfloat vBottom = m_scanLineDirection == QVideoSurfaceFormat::TopToBottom
       
  1157                 ? target.bottom() + 1
       
  1158                 : target.top();
       
  1159 
       
  1160 
       
  1161         const GLfloat vertexCoordArray[] =
       
  1162         {
       
  1163             target.left()     , vBottom,
       
  1164             target.right() + 1, vBottom,
       
  1165             target.left()     , vTop,
       
  1166             target.right() + 1, vTop
       
  1167         };
       
  1168 
       
  1169         const GLfloat txLeft = source.left() / m_frameSize.width();
       
  1170         const GLfloat txRight = source.right() / m_frameSize.width();
       
  1171         const GLfloat txTop = m_scanLineDirection == QVideoSurfaceFormat::TopToBottom
       
  1172                 ? source.top() / m_frameSize.height()
       
  1173                 : source.bottom() / m_frameSize.height();
       
  1174         const GLfloat txBottom = m_scanLineDirection == QVideoSurfaceFormat::TopToBottom
       
  1175                 ? source.bottom() / m_frameSize.height()
       
  1176                 : source.top() / m_frameSize.height();
       
  1177 
       
  1178         const GLfloat textureCoordArray[] =
       
  1179         {
       
  1180             txLeft , txBottom,
       
  1181             txRight, txBottom,
       
  1182             txLeft , txTop,
       
  1183             txRight, txTop
       
  1184         };
       
  1185 
       
  1186         m_program.bind();
       
  1187 
       
  1188         m_program.enableAttributeArray("vertexCoordArray");
       
  1189         m_program.enableAttributeArray("textureCoordArray");
       
  1190         m_program.setAttributeArray("vertexCoordArray", vertexCoordArray, 2);
       
  1191         m_program.setAttributeArray("textureCoordArray", textureCoordArray, 2);
       
  1192         m_program.setUniformValue("positionMatrix", positionMatrix);
       
  1193 
       
  1194         if (m_textureCount == 3) {
       
  1195             glActiveTexture(GL_TEXTURE0);
       
  1196             glBindTexture(GL_TEXTURE_2D, m_textureIds[0]);
       
  1197             glActiveTexture(GL_TEXTURE1);
       
  1198             glBindTexture(GL_TEXTURE_2D, m_textureIds[1]);
       
  1199             glActiveTexture(GL_TEXTURE2);
       
  1200             glBindTexture(GL_TEXTURE_2D, m_textureIds[2]);
       
  1201             glActiveTexture(GL_TEXTURE0);
       
  1202 
       
  1203             m_program.setUniformValue("texY", 0);
       
  1204             m_program.setUniformValue("texU", 1);
       
  1205             m_program.setUniformValue("texV", 2);
       
  1206         } else {
       
  1207             glActiveTexture(GL_TEXTURE0);
       
  1208             glBindTexture(GL_TEXTURE_2D, m_textureIds[0]);
       
  1209 
       
  1210             m_program.setUniformValue("texRgb", 0);
       
  1211         }
       
  1212         m_program.setUniformValue("colorMatrix", m_colorMatrix);
       
  1213 
       
  1214         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
       
  1215 
       
  1216         m_program.release();
       
  1217 
       
  1218         painter->endNativePainting();
       
  1219     }
       
  1220     return QAbstractVideoSurface::NoError;
       
  1221 }
       
  1222 
       
  1223 #endif
       
  1224 
       
  1225 /*!
       
  1226     \class QPainterVideoSurface
       
  1227     \internal
       
  1228 */
       
  1229 
       
  1230 /*!
       
  1231 */
       
  1232 QPainterVideoSurface::QPainterVideoSurface(QObject *parent)
       
  1233     : QAbstractVideoSurface(parent)
       
  1234     , m_painter(0)
       
  1235 #if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1)
       
  1236     , m_glContext(0)
       
  1237     , m_shaderTypes(NoShaders)
       
  1238     , m_shaderType(NoShaders)
       
  1239 #endif
       
  1240     , m_brightness(0)
       
  1241     , m_contrast(0)
       
  1242     , m_hue(0)
       
  1243     , m_saturation(0)
       
  1244     , m_pixelFormat(QVideoFrame::Format_Invalid)
       
  1245     , m_colorsDirty(true)
       
  1246     , m_ready(false)
       
  1247 {
       
  1248 }
       
  1249 
       
  1250 /*!
       
  1251 */
       
  1252 QPainterVideoSurface::~QPainterVideoSurface()
       
  1253 {
       
  1254     if (isActive())
       
  1255         m_painter->stop();
       
  1256 
       
  1257     delete m_painter;
       
  1258 }
       
  1259 
       
  1260 /*!
       
  1261 */
       
  1262 QList<QVideoFrame::PixelFormat> QPainterVideoSurface::supportedPixelFormats(
       
  1263         QAbstractVideoBuffer::HandleType handleType) const
       
  1264 {
       
  1265     if (!m_painter)
       
  1266         const_cast<QPainterVideoSurface *>(this)->createPainter();
       
  1267 
       
  1268     return m_painter->supportedPixelFormats(handleType);
       
  1269 }
       
  1270 
       
  1271 /*!
       
  1272 */
       
  1273 bool QPainterVideoSurface::isFormatSupported(
       
  1274         const QVideoSurfaceFormat &format, QVideoSurfaceFormat *similar) const
       
  1275 {
       
  1276     if (!m_painter)
       
  1277         const_cast<QPainterVideoSurface *>(this)->createPainter();
       
  1278 
       
  1279     return m_painter->isFormatSupported(format, similar);
       
  1280 }
       
  1281 
       
  1282 /*!
       
  1283 */
       
  1284 bool QPainterVideoSurface::start(const QVideoSurfaceFormat &format)
       
  1285 {
       
  1286     if (isActive())
       
  1287         m_painter->stop();
       
  1288 
       
  1289     if (!m_painter)
       
  1290         createPainter();
       
  1291 
       
  1292     if (format.frameSize().isEmpty()) {
       
  1293         setError(UnsupportedFormatError);
       
  1294     } else {
       
  1295         QAbstractVideoSurface::Error error = m_painter->start(format);
       
  1296 
       
  1297         if (error != QAbstractVideoSurface::NoError) {
       
  1298             setError(error);
       
  1299         } else {
       
  1300             m_pixelFormat = format.pixelFormat();
       
  1301             m_frameSize = format.frameSize();
       
  1302             m_sourceRect = format.viewport();
       
  1303             m_colorsDirty = true;
       
  1304             m_ready = true;
       
  1305 
       
  1306             return QAbstractVideoSurface::start(format);
       
  1307         }
       
  1308     }
       
  1309 
       
  1310     QAbstractVideoSurface::stop();
       
  1311 
       
  1312     return false;
       
  1313 }
       
  1314 
       
  1315 /*!
       
  1316 */
       
  1317 void QPainterVideoSurface::stop()
       
  1318 {
       
  1319     if (isActive()) {
       
  1320         m_painter->stop();
       
  1321         m_ready = false;
       
  1322 
       
  1323         QAbstractVideoSurface::stop();
       
  1324     }
       
  1325 }
       
  1326 
       
  1327 /*!
       
  1328 */
       
  1329 bool QPainterVideoSurface::present(const QVideoFrame &frame)
       
  1330 {
       
  1331     if (!m_ready) {
       
  1332         if (!isActive())
       
  1333             setError(StoppedError);
       
  1334     } else if (frame.isValid() 
       
  1335             && (frame.pixelFormat() != m_pixelFormat || frame.size() != m_frameSize)) {
       
  1336         setError(IncorrectFormatError);
       
  1337 
       
  1338         stop();
       
  1339     } else {
       
  1340         QAbstractVideoSurface::Error error = m_painter->setCurrentFrame(frame);
       
  1341 
       
  1342         if (error != QAbstractVideoSurface::NoError) {
       
  1343             setError(error);
       
  1344 
       
  1345             stop();
       
  1346         } else {
       
  1347             m_ready = false;
       
  1348 
       
  1349             emit frameChanged();
       
  1350 
       
  1351             return true;
       
  1352         }
       
  1353     }
       
  1354     return false;
       
  1355 }
       
  1356 
       
  1357 /*!
       
  1358 */
       
  1359 int QPainterVideoSurface::brightness() const
       
  1360 {
       
  1361     return m_brightness;
       
  1362 }
       
  1363 
       
  1364 /*!
       
  1365 */
       
  1366 void QPainterVideoSurface::setBrightness(int brightness)
       
  1367 {
       
  1368     m_brightness = brightness;
       
  1369 
       
  1370     m_colorsDirty = true;
       
  1371 }
       
  1372 
       
  1373 /*!
       
  1374 */
       
  1375 int QPainterVideoSurface::contrast() const
       
  1376 {
       
  1377     return m_contrast;
       
  1378 }
       
  1379 
       
  1380 /*!
       
  1381 */
       
  1382 void QPainterVideoSurface::setContrast(int contrast)
       
  1383 {
       
  1384     m_contrast = contrast;
       
  1385 
       
  1386     m_colorsDirty = true;
       
  1387 }
       
  1388 
       
  1389 /*!
       
  1390 */
       
  1391 int QPainterVideoSurface::hue() const
       
  1392 {
       
  1393     return m_hue;
       
  1394 }
       
  1395 
       
  1396 /*!
       
  1397 */
       
  1398 void QPainterVideoSurface::setHue(int hue)
       
  1399 {
       
  1400     m_hue = hue;
       
  1401 
       
  1402     m_colorsDirty = true;
       
  1403 }
       
  1404 
       
  1405 /*!
       
  1406 */
       
  1407 int QPainterVideoSurface::saturation() const
       
  1408 {
       
  1409     return m_saturation;
       
  1410 }
       
  1411 
       
  1412 /*!
       
  1413 */
       
  1414 void QPainterVideoSurface::setSaturation(int saturation)
       
  1415 {
       
  1416     m_saturation = saturation;
       
  1417 
       
  1418     m_colorsDirty = true;
       
  1419 }
       
  1420 
       
  1421 /*!
       
  1422 */
       
  1423 bool QPainterVideoSurface::isReady() const
       
  1424 {
       
  1425     return m_ready;
       
  1426 }
       
  1427 
       
  1428 /*!
       
  1429 */
       
  1430 void QPainterVideoSurface::setReady(bool ready)
       
  1431 {
       
  1432     m_ready = ready;
       
  1433 }
       
  1434 
       
  1435 /*!
       
  1436 */
       
  1437 void QPainterVideoSurface::paint(QPainter *painter, const QRectF &target, const QRectF &source)
       
  1438 {
       
  1439     if (!isActive()) {
       
  1440         painter->fillRect(target, QBrush(Qt::black));
       
  1441     } else {
       
  1442         if (m_colorsDirty) {
       
  1443             m_painter->updateColors(m_brightness, m_contrast, m_hue, m_saturation);
       
  1444             m_colorsDirty = false;
       
  1445         }
       
  1446 
       
  1447         const QRectF sourceRect(
       
  1448                 m_sourceRect.x() + m_sourceRect.width() * source.x(),
       
  1449                 m_sourceRect.y() + m_sourceRect.height() * source.y(),
       
  1450                 m_sourceRect.width() * source.width(),
       
  1451                 m_sourceRect.height() * source.height());
       
  1452 
       
  1453         QAbstractVideoSurface::Error error = m_painter->paint(target, painter, sourceRect);
       
  1454 
       
  1455         if (error != QAbstractVideoSurface::NoError) {
       
  1456             setError(error);
       
  1457 
       
  1458             stop();
       
  1459         }
       
  1460     }
       
  1461 }
       
  1462 
       
  1463 /*!
       
  1464     \fn QPainterVideoSurface::frameChanged()
       
  1465 */
       
  1466 
       
  1467 #if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1)
       
  1468 
       
  1469 /*!
       
  1470 */
       
  1471 const QGLContext *QPainterVideoSurface::glContext() const
       
  1472 {
       
  1473     return m_glContext;
       
  1474 }
       
  1475 
       
  1476 /*!
       
  1477 */
       
  1478 void QPainterVideoSurface::setGLContext(QGLContext *context)
       
  1479 {
       
  1480     if (m_glContext == context)
       
  1481         return;
       
  1482 
       
  1483     m_glContext = context;
       
  1484 
       
  1485     m_shaderTypes = NoShaders;
       
  1486 
       
  1487     if (m_glContext) {
       
  1488         m_glContext->makeCurrent();
       
  1489 
       
  1490         const QByteArray extensions(reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS)));
       
  1491 #ifndef QT_OPENGL_ES
       
  1492 
       
  1493         if (extensions.contains("ARB_fragment_program"))
       
  1494             m_shaderTypes |= FragmentProgramShader;
       
  1495 #endif
       
  1496 
       
  1497         if (QGLShaderProgram::hasOpenGLShaderPrograms(m_glContext)
       
  1498                 && extensions.contains("ARB_shader_objects"))
       
  1499             m_shaderTypes |= GlslShader;
       
  1500     }
       
  1501 
       
  1502     ShaderType type = (m_shaderType & m_shaderTypes)
       
  1503             ? m_shaderType
       
  1504             : NoShaders;
       
  1505 
       
  1506     if (type != m_shaderType || type != NoShaders) {
       
  1507         m_shaderType = type;
       
  1508 
       
  1509         if (isActive()) {
       
  1510             m_painter->stop();
       
  1511             delete m_painter;
       
  1512             m_painter = 0;
       
  1513             m_ready = false;
       
  1514 
       
  1515             setError(ResourceError);
       
  1516             QAbstractVideoSurface::stop();
       
  1517         }
       
  1518         emit supportedFormatsChanged();
       
  1519     }
       
  1520 }
       
  1521 
       
  1522 /*!
       
  1523     \enum QPainterVideoSurface::ShaderType
       
  1524 
       
  1525     \value NoShaders
       
  1526     \value FragmentProgramShader
       
  1527     \value HlslShader
       
  1528 */
       
  1529 
       
  1530 /*!
       
  1531     \typedef QPainterVideoSurface::ShaderTypes
       
  1532 */
       
  1533 
       
  1534 /*!
       
  1535 */
       
  1536 QPainterVideoSurface::ShaderTypes QPainterVideoSurface::supportedShaderTypes() const
       
  1537 {
       
  1538     return m_shaderTypes;
       
  1539 }
       
  1540 
       
  1541 /*!
       
  1542 */
       
  1543 QPainterVideoSurface::ShaderType QPainterVideoSurface::shaderType() const
       
  1544 {
       
  1545     return m_shaderType;
       
  1546 }
       
  1547 
       
  1548 /*!
       
  1549 */
       
  1550 void QPainterVideoSurface::setShaderType(ShaderType type)
       
  1551 {
       
  1552     if (!(type & m_shaderTypes))
       
  1553         type = NoShaders;
       
  1554 
       
  1555     if (type != m_shaderType) {
       
  1556         m_shaderType = type;
       
  1557 
       
  1558         if (isActive()) {
       
  1559             m_painter->stop();
       
  1560             delete m_painter;
       
  1561             m_painter = 0;
       
  1562             m_ready = false;
       
  1563 
       
  1564             setError(ResourceError);
       
  1565             QAbstractVideoSurface::stop();
       
  1566         } else {
       
  1567             delete m_painter;
       
  1568             m_painter = 0;
       
  1569         }
       
  1570         emit supportedFormatsChanged();
       
  1571     }
       
  1572 }
       
  1573 
       
  1574 #endif
       
  1575 
       
  1576 void QPainterVideoSurface::viewportDestroyed()
       
  1577 {
       
  1578     if (m_painter) {
       
  1579         m_painter->viewportDestroyed();
       
  1580 
       
  1581         setError(ResourceError);
       
  1582         stop();
       
  1583         delete m_painter;
       
  1584         m_painter = 0;
       
  1585     }
       
  1586 }
       
  1587 
       
  1588 void QPainterVideoSurface::createPainter()
       
  1589 {
       
  1590     Q_ASSERT(!m_painter);
       
  1591 
       
  1592 #ifdef Q_WS_MAC
       
  1593     if (m_glContext)
       
  1594         m_glContext->makeCurrent();
       
  1595 
       
  1596     m_painter = new QVideoSurfaceCoreGraphicsPainter(m_glContext != 0);
       
  1597     return;
       
  1598 #endif
       
  1599 
       
  1600 #if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1)
       
  1601     switch (m_shaderType) {
       
  1602 #ifndef QT_OPENGL_ES
       
  1603     case FragmentProgramShader:
       
  1604         Q_ASSERT(m_glContext);
       
  1605         m_glContext->makeCurrent();
       
  1606         m_painter = new QVideoSurfaceArbFpPainter(m_glContext);
       
  1607         break;
       
  1608 #endif
       
  1609     case GlslShader:
       
  1610         Q_ASSERT(m_glContext);
       
  1611         m_glContext->makeCurrent();
       
  1612         m_painter = new QVideoSurfaceGlslPainter(m_glContext);
       
  1613         break;
       
  1614     default:
       
  1615         m_painter = new QVideoSurfaceRasterPainter;
       
  1616         break;
       
  1617     }
       
  1618 #else
       
  1619     m_painter = new QVideoSurfaceRasterPainter;
       
  1620 #endif
       
  1621 }
       
  1622 
       
  1623 #include "moc_qpaintervideosurface_p.cpp"
       
  1624 QT_END_NAMESPACE
       
  1625 
       
  1626