LCOV - code coverage report
Current view: top level - gfx/gl - GLBlitHelper.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 353 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 16 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /* vim: set ts=8 sts=4 et sw=4 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "gfxUtils.h"
       8             : #include "GLBlitHelper.h"
       9             : #include "GLContext.h"
      10             : #include "GLScreenBuffer.h"
      11             : #include "ScopedGLHelpers.h"
      12             : #include "mozilla/Preferences.h"
      13             : #include "ImageContainer.h"
      14             : #include "HeapCopyOfStackArray.h"
      15             : #include "mozilla/gfx/Matrix.h"
      16             : #include "mozilla/UniquePtr.h"
      17             : 
      18             : #ifdef MOZ_WIDGET_ANDROID
      19             : #include "AndroidSurfaceTexture.h"
      20             : #include "GLImages.h"
      21             : #include "GLLibraryEGL.h"
      22             : #endif
      23             : 
      24             : #ifdef XP_MACOSX
      25             : #include "MacIOSurfaceImage.h"
      26             : #include "GLContextCGL.h"
      27             : #endif
      28             : 
      29             : using mozilla::layers::PlanarYCbCrImage;
      30             : using mozilla::layers::PlanarYCbCrData;
      31             : 
      32             : namespace mozilla {
      33             : namespace gl {
      34             : 
      35           0 : GLBlitHelper::GLBlitHelper(GLContext* gl)
      36             :     : mGL(gl)
      37             :     , mTexBlit_Buffer(0)
      38             :     , mTexBlit_VertShader(0)
      39             :     , mTex2DBlit_FragShader(0)
      40             :     , mTex2DRectBlit_FragShader(0)
      41             :     , mTex2DBlit_Program(0)
      42             :     , mTex2DRectBlit_Program(0)
      43             :     , mYFlipLoc(-1)
      44             :     , mTextureTransformLoc(-1)
      45             :     , mTexExternalBlit_FragShader(0)
      46             :     , mTexYUVPlanarBlit_FragShader(0)
      47             :     , mTexNV12PlanarBlit_FragShader(0)
      48             :     , mTexExternalBlit_Program(0)
      49             :     , mTexYUVPlanarBlit_Program(0)
      50             :     , mTexNV12PlanarBlit_Program(0)
      51             :     , mFBO(0)
      52             :     , mSrcTexY(0)
      53             :     , mSrcTexCb(0)
      54             :     , mSrcTexCr(0)
      55             :     , mSrcTexEGL(0)
      56             :     , mYTexScaleLoc(-1)
      57             :     , mCbCrTexScaleLoc(-1)
      58             :     , mYuvColorMatrixLoc(-1)
      59             :     , mTexWidth(0)
      60             :     , mTexHeight(0)
      61             :     , mCurYScale(1.0f)
      62           0 :     , mCurCbCrScale(1.0f)
      63             : {
      64           0 : }
      65             : 
      66           0 : GLBlitHelper::~GLBlitHelper()
      67             : {
      68           0 :     if (!mGL->MakeCurrent())
      69           0 :         return;
      70             : 
      71           0 :     DeleteTexBlitProgram();
      72             : 
      73             :     GLuint tex[] = {
      74           0 :         mSrcTexY,
      75           0 :         mSrcTexCb,
      76           0 :         mSrcTexCr,
      77           0 :         mSrcTexEGL,
      78           0 :     };
      79             : 
      80           0 :     mSrcTexY = mSrcTexCb = mSrcTexCr = mSrcTexEGL = 0;
      81           0 :     mGL->fDeleteTextures(ArrayLength(tex), tex);
      82             : 
      83           0 :     if (mFBO) {
      84           0 :         mGL->fDeleteFramebuffers(1, &mFBO);
      85             :     }
      86           0 :     mFBO = 0;
      87           0 : }
      88             : 
      89             : // Allowed to be destructive of state we restore in functions below.
      90             : bool
      91           0 : GLBlitHelper::InitTexQuadProgram(BlitType target)
      92             : {
      93           0 :     const char kTexBlit_VertShaderSource[] = "\
      94             :         #version 100                                  \n\
      95             :         #ifdef GL_ES                                  \n\
      96             :         precision mediump float;                      \n\
      97             :         #endif                                        \n\
      98             :         attribute vec2 aPosition;                     \n\
      99             :                                                       \n\
     100             :         uniform float uYflip;                         \n\
     101             :         varying vec2 vTexCoord;                       \n\
     102             :                                                       \n\
     103             :         void main(void)                               \n\
     104             :         {                                             \n\
     105             :             vTexCoord = aPosition;                    \n\
     106             :             vTexCoord.y = abs(vTexCoord.y - uYflip);  \n\
     107             :             vec2 vertPos = aPosition * 2.0 - 1.0;     \n\
     108             :             gl_Position = vec4(vertPos, 0.0, 1.0);    \n\
     109             :         }                                             \n\
     110             :     ";
     111             : 
     112           0 :     const char kTex2DBlit_FragShaderSource[] = "\
     113             :         #version 100                                        \n\
     114             :         #ifdef GL_ES                                        \n\
     115             :         #ifdef GL_FRAGMENT_PRECISION_HIGH                   \n\
     116             :             precision highp float;                          \n\
     117             :         #else                                               \n\
     118             :             precision mediump float;                        \n\
     119             :         #endif                                              \n\
     120             :         #endif                                              \n\
     121             :         uniform sampler2D uTexUnit;                         \n\
     122             :                                                             \n\
     123             :         varying vec2 vTexCoord;                             \n\
     124             :                                                             \n\
     125             :         void main(void)                                     \n\
     126             :         {                                                   \n\
     127             :             gl_FragColor = texture2D(uTexUnit, vTexCoord);  \n\
     128             :         }                                                   \n\
     129             :     ";
     130             : 
     131           0 :     const char kTex2DRectBlit_FragShaderSource[] = "\
     132             :         #version 100                                                  \n\
     133             :         #ifdef GL_FRAGMENT_PRECISION_HIGH                             \n\
     134             :             precision highp float;                                    \n\
     135             :         #else                                                         \n\
     136             :             precision mediump float;                                  \n\
     137             :         #endif                                                        \n\
     138             :                                                                       \n\
     139             :         uniform sampler2D uTexUnit;                                   \n\
     140             :         uniform vec2 uTexCoordMult;                                   \n\
     141             :                                                                       \n\
     142             :         varying vec2 vTexCoord;                                       \n\
     143             :                                                                       \n\
     144             :         void main(void)                                               \n\
     145             :         {                                                             \n\
     146             :             gl_FragColor = texture2DRect(uTexUnit,                    \n\
     147             :                                          vTexCoord * uTexCoordMult);  \n\
     148             :         }                                                             \n\
     149             :     ";
     150             : #ifdef ANDROID /* MOZ_WIDGET_ANDROID */
     151             :     const char kTexExternalBlit_FragShaderSource[] = "\
     152             :         #version 100                                                    \n\
     153             :         #extension GL_OES_EGL_image_external : require                  \n\
     154             :         #ifdef GL_FRAGMENT_PRECISION_HIGH                               \n\
     155             :             precision highp float;                                      \n\
     156             :         #else                                                           \n\
     157             :             precision mediump float;                                    \n\
     158             :         #endif                                                          \n\
     159             :         varying vec2 vTexCoord;                                         \n\
     160             :         uniform mat4 uTextureTransform;                                 \n\
     161             :         uniform samplerExternalOES uTexUnit;                            \n\
     162             :                                                                         \n\
     163             :         void main()                                                     \n\
     164             :         {                                                               \n\
     165             :             gl_FragColor = texture2D(uTexUnit,                          \n\
     166             :                 (uTextureTransform * vec4(vTexCoord, 0.0, 1.0)).xy);    \n\
     167             :         }                                                               \n\
     168             :     ";
     169             : #endif
     170             :     /* From Rec601:
     171             :     [R]   [1.1643835616438356,  0.0,                 1.5960267857142858]      [ Y -  16]
     172             :     [G] = [1.1643835616438358, -0.3917622900949137, -0.8129676472377708]    x [Cb - 128]
     173             :     [B]   [1.1643835616438356,  2.017232142857143,   8.862867620416422e-17]   [Cr - 128]
     174             : 
     175             :     For [0,1] instead of [0,255], and to 5 places:
     176             :     [R]   [1.16438,  0.00000,  1.59603]   [ Y - 0.06275]
     177             :     [G] = [1.16438, -0.39176, -0.81297] x [Cb - 0.50196]
     178             :     [B]   [1.16438,  2.01723,  0.00000]   [Cr - 0.50196]
     179             : 
     180             :     From Rec709:
     181             :     [R]   [1.1643835616438356,  4.2781193979771426e-17, 1.7927410714285714]     [ Y -  16]
     182             :     [G] = [1.1643835616438358, -0.21324861427372963,   -0.532909328559444]    x [Cb - 128]
     183             :     [B]   [1.1643835616438356,  2.1124017857142854,     0.0]                    [Cr - 128]
     184             : 
     185             :     For [0,1] instead of [0,255], and to 5 places:
     186             :     [R]   [1.16438,  0.00000,  1.79274]   [ Y - 0.06275]
     187             :     [G] = [1.16438, -0.21325, -0.53291] x [Cb - 0.50196]
     188             :     [B]   [1.16438,  2.11240,  0.00000]   [Cr - 0.50196]
     189             :     */
     190           0 :     const char kTexYUVPlanarBlit_FragShaderSource[] = "\
     191             :         #version 100                                                        \n\
     192             :         #ifdef GL_ES                                                        \n\
     193             :         precision mediump float;                                            \n\
     194             :         #endif                                                              \n\
     195             :         varying vec2 vTexCoord;                                             \n\
     196             :         uniform sampler2D uYTexture;                                        \n\
     197             :         uniform sampler2D uCbTexture;                                       \n\
     198             :         uniform sampler2D uCrTexture;                                       \n\
     199             :         uniform vec2 uYTexScale;                                            \n\
     200             :         uniform vec2 uCbCrTexScale;                                         \n\
     201             :         uniform mat3 uYuvColorMatrix;                                       \n\
     202             :         void main()                                                         \n\
     203             :         {                                                                   \n\
     204             :             float y = texture2D(uYTexture, vTexCoord * uYTexScale).r;       \n\
     205             :             float cb = texture2D(uCbTexture, vTexCoord * uCbCrTexScale).r;  \n\
     206             :             float cr = texture2D(uCrTexture, vTexCoord * uCbCrTexScale).r;  \n\
     207             :             y = y - 0.06275;                                                \n\
     208             :             cb = cb - 0.50196;                                              \n\
     209             :             cr = cr - 0.50196;                                              \n\
     210             :             vec3 yuv = vec3(y, cb, cr);                                     \n\
     211             :             gl_FragColor.rgb = uYuvColorMatrix * yuv;                       \n\
     212             :             gl_FragColor.a = 1.0;                                           \n\
     213             :         }                                                                   \n\
     214             :     ";
     215             : 
     216             : #ifdef XP_MACOSX
     217             :     const char kTexNV12PlanarBlit_FragShaderSource[] = "\
     218             :         #version 100                                                             \n\
     219             :         #extension GL_ARB_texture_rectangle : require                            \n\
     220             :         #ifdef GL_ES                                                             \n\
     221             :         precision mediump float                                                  \n\
     222             :         #endif                                                                   \n\
     223             :         varying vec2 vTexCoord;                                                  \n\
     224             :         uniform sampler2DRect uYTexture;                                         \n\
     225             :         uniform sampler2DRect uCbCrTexture;                                      \n\
     226             :         uniform vec2 uYTexScale;                                                 \n\
     227             :         uniform vec2 uCbCrTexScale;                                              \n\
     228             :         void main()                                                              \n\
     229             :         {                                                                        \n\
     230             :             float y = texture2DRect(uYTexture, vTexCoord * uYTexScale).r;        \n\
     231             :             float cb = texture2DRect(uCbCrTexture, vTexCoord * uCbCrTexScale).r; \n\
     232             :             float cr = texture2DRect(uCbCrTexture, vTexCoord * uCbCrTexScale).a; \n\
     233             :             y = (y - 0.06275) * 1.16438;                                         \n\
     234             :             cb = cb - 0.50196;                                                   \n\
     235             :             cr = cr - 0.50196;                                                   \n\
     236             :             gl_FragColor.r = y + cr * 1.59603;                                   \n\
     237             :             gl_FragColor.g = y - 0.81297 * cr - 0.39176 * cb;                    \n\
     238             :             gl_FragColor.b = y + cb * 2.01723;                                   \n\
     239             :             gl_FragColor.a = 1.0;                                                \n\
     240             :         }                                                                        \n\
     241             :     ";
     242             : #endif
     243             : 
     244           0 :     bool success = false;
     245             : 
     246             :     GLuint* programPtr;
     247             :     GLuint* fragShaderPtr;
     248             :     const char* fragShaderSource;
     249           0 :     switch (target) {
     250             :     case ConvertEGLImage:
     251             :     case BlitTex2D:
     252           0 :         programPtr = &mTex2DBlit_Program;
     253           0 :         fragShaderPtr = &mTex2DBlit_FragShader;
     254           0 :         fragShaderSource = kTex2DBlit_FragShaderSource;
     255           0 :         break;
     256             :     case BlitTexRect:
     257           0 :         programPtr = &mTex2DRectBlit_Program;
     258           0 :         fragShaderPtr = &mTex2DRectBlit_FragShader;
     259           0 :         fragShaderSource = kTex2DRectBlit_FragShaderSource;
     260           0 :         break;
     261             : #ifdef ANDROID
     262             :     case ConvertSurfaceTexture:
     263             :         programPtr = &mTexExternalBlit_Program;
     264             :         fragShaderPtr = &mTexExternalBlit_FragShader;
     265             :         fragShaderSource = kTexExternalBlit_FragShaderSource;
     266             :         break;
     267             : #endif
     268             :     case ConvertPlanarYCbCr:
     269           0 :         programPtr = &mTexYUVPlanarBlit_Program;
     270           0 :         fragShaderPtr = &mTexYUVPlanarBlit_FragShader;
     271           0 :         fragShaderSource = kTexYUVPlanarBlit_FragShaderSource;
     272           0 :         break;
     273             : #ifdef XP_MACOSX
     274             :     case ConvertMacIOSurfaceImage:
     275             :         programPtr = &mTexNV12PlanarBlit_Program;
     276             :         fragShaderPtr = &mTexNV12PlanarBlit_FragShader;
     277             :         fragShaderSource = kTexNV12PlanarBlit_FragShaderSource;
     278             :         break;
     279             : #endif
     280             :     default:
     281           0 :         return false;
     282             :     }
     283             : 
     284           0 :     GLuint& program = *programPtr;
     285           0 :     GLuint& fragShader = *fragShaderPtr;
     286             : 
     287             :     // Use do-while(false) to let us break on failure
     288             :     do {
     289           0 :         if (program) {
     290             :             // Already have it...
     291           0 :             success = true;
     292           0 :             break;
     293             :         }
     294             : 
     295           0 :         if (!mTexBlit_Buffer) {
     296             : 
     297             :             /* CCW tri-strip:
     298             :              * 2---3
     299             :              * | \ |
     300             :              * 0---1
     301             :              */
     302             :             GLfloat verts[] = {
     303             :                 0.0f, 0.0f,
     304             :                 1.0f, 0.0f,
     305             :                 0.0f, 1.0f,
     306             :                 1.0f, 1.0f
     307           0 :             };
     308           0 :             HeapCopyOfStackArray<GLfloat> vertsOnHeap(verts);
     309             : 
     310           0 :             MOZ_ASSERT(!mTexBlit_Buffer);
     311           0 :             mGL->fGenBuffers(1, &mTexBlit_Buffer);
     312           0 :             mGL->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mTexBlit_Buffer);
     313             : 
     314             :             // Make sure we have a sane size.
     315           0 :             mGL->fBufferData(LOCAL_GL_ARRAY_BUFFER, vertsOnHeap.ByteLength(), vertsOnHeap.Data(), LOCAL_GL_STATIC_DRAW);
     316             :         }
     317             : 
     318           0 :         if (!mTexBlit_VertShader) {
     319             : 
     320           0 :             const char* vertShaderSource = kTexBlit_VertShaderSource;
     321             : 
     322           0 :             mTexBlit_VertShader = mGL->fCreateShader(LOCAL_GL_VERTEX_SHADER);
     323           0 :             mGL->fShaderSource(mTexBlit_VertShader, 1, &vertShaderSource, nullptr);
     324           0 :             mGL->fCompileShader(mTexBlit_VertShader);
     325             :         }
     326             : 
     327           0 :         MOZ_ASSERT(!fragShader);
     328           0 :         fragShader = mGL->fCreateShader(LOCAL_GL_FRAGMENT_SHADER);
     329           0 :         mGL->fShaderSource(fragShader, 1, &fragShaderSource, nullptr);
     330           0 :         mGL->fCompileShader(fragShader);
     331             : 
     332           0 :         program = mGL->fCreateProgram();
     333           0 :         mGL->fAttachShader(program, mTexBlit_VertShader);
     334           0 :         mGL->fAttachShader(program, fragShader);
     335           0 :         mGL->fBindAttribLocation(program, 0, "aPosition");
     336           0 :         mGL->fLinkProgram(program);
     337             : 
     338           0 :         if (GLContext::ShouldSpew()) {
     339           0 :             GLint status = 0;
     340           0 :             mGL->fGetShaderiv(mTexBlit_VertShader, LOCAL_GL_COMPILE_STATUS, &status);
     341           0 :             if (status != LOCAL_GL_TRUE) {
     342           0 :                 NS_ERROR("Vert shader compilation failed.");
     343             : 
     344           0 :                 GLint length = 0;
     345           0 :                 mGL->fGetShaderiv(mTexBlit_VertShader, LOCAL_GL_INFO_LOG_LENGTH, &length);
     346           0 :                 if (!length) {
     347           0 :                     printf_stderr("No shader info log available.\n");
     348           0 :                     break;
     349             :                 }
     350             : 
     351           0 :                 auto buffer = MakeUnique<char[]>(length);
     352           0 :                 mGL->fGetShaderInfoLog(mTexBlit_VertShader, length, nullptr, buffer.get());
     353             : 
     354           0 :                 printf_stderr("Shader info log (%d bytes): %s\n", length, buffer.get());
     355           0 :                 break;
     356             :             }
     357             : 
     358           0 :             status = 0;
     359           0 :             mGL->fGetShaderiv(fragShader, LOCAL_GL_COMPILE_STATUS, &status);
     360           0 :             if (status != LOCAL_GL_TRUE) {
     361           0 :                 NS_ERROR("Frag shader compilation failed.");
     362             : 
     363           0 :                 GLint length = 0;
     364           0 :                 mGL->fGetShaderiv(fragShader, LOCAL_GL_INFO_LOG_LENGTH, &length);
     365           0 :                 if (!length) {
     366           0 :                     printf_stderr("No shader info log available.\n");
     367           0 :                     break;
     368             :                 }
     369             : 
     370           0 :                 auto buffer = MakeUnique<char[]>(length);
     371           0 :                 mGL->fGetShaderInfoLog(fragShader, length, nullptr, buffer.get());
     372             : 
     373           0 :                 printf_stderr("Shader info log (%d bytes): %s\n", length, buffer.get());
     374           0 :                 break;
     375             :             }
     376             :         }
     377             : 
     378           0 :         GLint status = 0;
     379           0 :         mGL->fGetProgramiv(program, LOCAL_GL_LINK_STATUS, &status);
     380           0 :         if (status != LOCAL_GL_TRUE) {
     381           0 :             if (GLContext::ShouldSpew()) {
     382           0 :                 NS_ERROR("Linking blit program failed.");
     383           0 :                 GLint length = 0;
     384           0 :                 mGL->fGetProgramiv(program, LOCAL_GL_INFO_LOG_LENGTH, &length);
     385           0 :                 if (!length) {
     386           0 :                     printf_stderr("No program info log available.\n");
     387           0 :                     break;
     388             :                 }
     389             : 
     390           0 :                 auto buffer = MakeUnique<char[]>(length);
     391           0 :                 mGL->fGetProgramInfoLog(program, length, nullptr, buffer.get());
     392             : 
     393           0 :                 printf_stderr("Program info log (%d bytes): %s\n", length, buffer.get());
     394             :             }
     395           0 :             break;
     396             :         }
     397             : 
     398             :         // Cache and set attribute and uniform
     399           0 :         mGL->fUseProgram(program);
     400           0 :         switch (target) {
     401             : #ifdef ANDROID
     402             :             case ConvertSurfaceTexture:
     403             : #endif
     404             :             case BlitTex2D:
     405             :             case BlitTexRect:
     406             :             case ConvertEGLImage: {
     407           0 :                 GLint texUnitLoc = mGL->fGetUniformLocation(program, "uTexUnit");
     408           0 :                 MOZ_ASSERT(texUnitLoc != -1, "uniform uTexUnit not found");
     409           0 :                 mGL->fUniform1i(texUnitLoc, 0);
     410           0 :                 break;
     411             :             }
     412             :             case ConvertPlanarYCbCr: {
     413           0 :                 GLint texY = mGL->fGetUniformLocation(program, "uYTexture");
     414           0 :                 GLint texCb = mGL->fGetUniformLocation(program, "uCbTexture");
     415           0 :                 GLint texCr = mGL->fGetUniformLocation(program, "uCrTexture");
     416           0 :                 mYTexScaleLoc = mGL->fGetUniformLocation(program, "uYTexScale");
     417           0 :                 mCbCrTexScaleLoc = mGL->fGetUniformLocation(program, "uCbCrTexScale");
     418           0 :                 mYuvColorMatrixLoc = mGL->fGetUniformLocation(program, "uYuvColorMatrix");
     419             : 
     420           0 :                 DebugOnly<bool> hasUniformLocations = texY != -1 &&
     421           0 :                                                       texCb != -1 &&
     422           0 :                                                       texCr != -1 &&
     423           0 :                                                       mYTexScaleLoc != -1 &&
     424           0 :                                                       mCbCrTexScaleLoc != -1 &&
     425           0 :                                                       mYuvColorMatrixLoc != -1;
     426           0 :                 MOZ_ASSERT(hasUniformLocations, "uniforms not found");
     427             : 
     428           0 :                 mGL->fUniform1i(texY, Channel_Y);
     429           0 :                 mGL->fUniform1i(texCb, Channel_Cb);
     430           0 :                 mGL->fUniform1i(texCr, Channel_Cr);
     431           0 :                 break;
     432             :             }
     433             :             case ConvertMacIOSurfaceImage: {
     434             : #ifdef XP_MACOSX
     435             :                 GLint texY = mGL->fGetUniformLocation(program, "uYTexture");
     436             :                 GLint texCbCr = mGL->fGetUniformLocation(program, "uCbCrTexture");
     437             :                 mYTexScaleLoc = mGL->fGetUniformLocation(program, "uYTexScale");
     438             :                 mCbCrTexScaleLoc= mGL->fGetUniformLocation(program, "uCbCrTexScale");
     439             : 
     440             :                 DebugOnly<bool> hasUniformLocations = texY != -1 &&
     441             :                                                       texCbCr != -1 &&
     442             :                                                       mYTexScaleLoc != -1 &&
     443             :                                                       mCbCrTexScaleLoc != -1;
     444             :                 MOZ_ASSERT(hasUniformLocations, "uniforms not found");
     445             : 
     446             :                 mGL->fUniform1i(texY, Channel_Y);
     447             :                 mGL->fUniform1i(texCbCr, Channel_Cb);
     448             : #endif
     449           0 :                 break;
     450             :             }
     451             :             default:
     452           0 :                 return false;
     453             :         }
     454           0 :         MOZ_ASSERT(mGL->fGetAttribLocation(program, "aPosition") == 0);
     455           0 :         mYFlipLoc = mGL->fGetUniformLocation(program, "uYflip");
     456           0 :         MOZ_ASSERT(mYFlipLoc != -1, "uniform: uYflip not found");
     457           0 :         mTextureTransformLoc = mGL->fGetUniformLocation(program, "uTextureTransform");
     458           0 :         if (mTextureTransformLoc >= 0) {
     459             :             // Set identity matrix as default
     460           0 :             gfx::Matrix4x4 identity;
     461           0 :             mGL->fUniformMatrix4fv(mTextureTransformLoc, 1, false, &identity._11);
     462             :         }
     463           0 :         success = true;
     464             :     } while (false);
     465             : 
     466           0 :     if (!success) {
     467             :         // Clean up:
     468           0 :         DeleteTexBlitProgram();
     469           0 :         return false;
     470             :     }
     471             : 
     472           0 :     mGL->fUseProgram(program);
     473           0 :     mGL->fEnableVertexAttribArray(0);
     474           0 :     mGL->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mTexBlit_Buffer);
     475           0 :     mGL->fVertexAttribPointer(0,
     476             :                               2,
     477             :                               LOCAL_GL_FLOAT,
     478             :                               false,
     479             :                               0,
     480           0 :                               nullptr);
     481           0 :     return true;
     482             : }
     483             : 
     484             : bool
     485           0 : GLBlitHelper::UseTexQuadProgram(BlitType target, const gfx::IntSize& srcSize)
     486             : {
     487           0 :     if (!InitTexQuadProgram(target)) {
     488           0 :         return false;
     489             :     }
     490             : 
     491           0 :     if (target == BlitTexRect) {
     492           0 :         GLint texCoordMultLoc = mGL->fGetUniformLocation(mTex2DRectBlit_Program, "uTexCoordMult");
     493           0 :         MOZ_ASSERT(texCoordMultLoc != -1, "uniform not found");
     494           0 :         mGL->fUniform2f(texCoordMultLoc, srcSize.width, srcSize.height);
     495             :     }
     496             : 
     497           0 :     return true;
     498             : }
     499             : 
     500             : void
     501           0 : GLBlitHelper::DeleteTexBlitProgram()
     502             : {
     503           0 :     if (mTexBlit_Buffer) {
     504           0 :         mGL->fDeleteBuffers(1, &mTexBlit_Buffer);
     505           0 :         mTexBlit_Buffer = 0;
     506             :     }
     507           0 :     if (mTexBlit_VertShader) {
     508           0 :         mGL->fDeleteShader(mTexBlit_VertShader);
     509           0 :         mTexBlit_VertShader = 0;
     510             :     }
     511           0 :     if (mTex2DBlit_FragShader) {
     512           0 :         mGL->fDeleteShader(mTex2DBlit_FragShader);
     513           0 :         mTex2DBlit_FragShader = 0;
     514             :     }
     515           0 :     if (mTex2DRectBlit_FragShader) {
     516           0 :         mGL->fDeleteShader(mTex2DRectBlit_FragShader);
     517           0 :         mTex2DRectBlit_FragShader = 0;
     518             :     }
     519           0 :     if (mTex2DBlit_Program) {
     520           0 :         mGL->fDeleteProgram(mTex2DBlit_Program);
     521           0 :         mTex2DBlit_Program = 0;
     522             :     }
     523           0 :     if (mTex2DRectBlit_Program) {
     524           0 :         mGL->fDeleteProgram(mTex2DRectBlit_Program);
     525           0 :         mTex2DRectBlit_Program = 0;
     526             :     }
     527           0 :     if (mTexExternalBlit_FragShader) {
     528           0 :         mGL->fDeleteShader(mTexExternalBlit_FragShader);
     529           0 :         mTexExternalBlit_FragShader = 0;
     530             :     }
     531           0 :     if (mTexYUVPlanarBlit_FragShader) {
     532           0 :         mGL->fDeleteShader(mTexYUVPlanarBlit_FragShader);
     533           0 :         mTexYUVPlanarBlit_FragShader = 0;
     534             :     }
     535           0 :     if (mTexNV12PlanarBlit_FragShader) {
     536           0 :         mGL->fDeleteShader(mTexNV12PlanarBlit_FragShader);
     537           0 :         mTexNV12PlanarBlit_FragShader = 0;
     538             :     }
     539           0 :     if (mTexExternalBlit_Program) {
     540           0 :         mGL->fDeleteProgram(mTexExternalBlit_Program);
     541           0 :         mTexExternalBlit_Program = 0;
     542             :     }
     543           0 :     if (mTexYUVPlanarBlit_Program) {
     544           0 :         mGL->fDeleteProgram(mTexYUVPlanarBlit_Program);
     545           0 :         mTexYUVPlanarBlit_Program = 0;
     546             :     }
     547           0 :     if (mTexNV12PlanarBlit_Program) {
     548           0 :         mGL->fDeleteProgram(mTexNV12PlanarBlit_Program);
     549           0 :         mTexNV12PlanarBlit_Program = 0;
     550             :     }
     551           0 : }
     552             : 
     553             : void
     554           0 : GLBlitHelper::BlitFramebufferToFramebuffer(GLuint srcFB, GLuint destFB,
     555             :                                            const gfx::IntSize& srcSize,
     556             :                                            const gfx::IntSize& destSize,
     557             :                                            bool internalFBs)
     558             : {
     559           0 :     MOZ_ASSERT(!srcFB || mGL->fIsFramebuffer(srcFB));
     560           0 :     MOZ_ASSERT(!destFB || mGL->fIsFramebuffer(destFB));
     561             : 
     562           0 :     MOZ_ASSERT(mGL->IsSupported(GLFeature::framebuffer_blit));
     563             : 
     564           0 :     ScopedBindFramebuffer boundFB(mGL);
     565           0 :     ScopedGLState scissor(mGL, LOCAL_GL_SCISSOR_TEST, false);
     566             : 
     567           0 :     if (internalFBs) {
     568           0 :         mGL->Screen()->BindReadFB_Internal(srcFB);
     569           0 :         mGL->Screen()->BindDrawFB_Internal(destFB);
     570             :     } else {
     571           0 :         mGL->BindReadFB(srcFB);
     572           0 :         mGL->BindDrawFB(destFB);
     573             :     }
     574             : 
     575           0 :     mGL->fBlitFramebuffer(0, 0,  srcSize.width,  srcSize.height,
     576           0 :                           0, 0, destSize.width, destSize.height,
     577             :                           LOCAL_GL_COLOR_BUFFER_BIT,
     578           0 :                           LOCAL_GL_NEAREST);
     579           0 : }
     580             : 
     581             : void
     582           0 : GLBlitHelper::BlitFramebufferToFramebuffer(GLuint srcFB, GLuint destFB,
     583             :                                            const gfx::IntSize& srcSize,
     584             :                                            const gfx::IntSize& destSize,
     585             :                                            const GLFormats& srcFormats,
     586             :                                            bool internalFBs)
     587             : {
     588           0 :     MOZ_ASSERT(!srcFB || mGL->fIsFramebuffer(srcFB));
     589           0 :     MOZ_ASSERT(!destFB || mGL->fIsFramebuffer(destFB));
     590             : 
     591           0 :     if (mGL->IsSupported(GLFeature::framebuffer_blit)) {
     592           0 :         BlitFramebufferToFramebuffer(srcFB, destFB,
     593             :                                      srcSize, destSize,
     594           0 :                                      internalFBs);
     595           0 :         return;
     596             :     }
     597             : 
     598           0 :     GLuint tex = CreateTextureForOffscreen(mGL, srcFormats, srcSize);
     599           0 :     MOZ_ASSERT(tex);
     600             : 
     601           0 :     BlitFramebufferToTexture(srcFB, tex, srcSize, srcSize, internalFBs);
     602           0 :     BlitTextureToFramebuffer(tex, destFB, srcSize, destSize, internalFBs);
     603             : 
     604           0 :     mGL->fDeleteTextures(1, &tex);
     605             : }
     606             : 
     607             : void
     608           0 : GLBlitHelper::BindAndUploadYUVTexture(Channel which,
     609             :                                       uint32_t width,
     610             :                                       uint32_t height,
     611             :                                       void* data,
     612             :                                       bool needsAllocation)
     613             : {
     614           0 :     MOZ_ASSERT(which < Channel_Max, "Invalid channel!");
     615           0 :     GLuint* srcTexArr[3] = {&mSrcTexY, &mSrcTexCb, &mSrcTexCr};
     616           0 :     GLuint& tex = *srcTexArr[which];
     617             : 
     618             :     // RED textures aren't valid in GLES2, and ALPHA textures are not valid in desktop GL Core Profiles.
     619             :     // So use R8 textures on GL3.0+ and GLES3.0+, but LUMINANCE/LUMINANCE/UNSIGNED_BYTE otherwise.
     620             :     GLenum format;
     621             :     GLenum internalFormat;
     622           0 :     if (mGL->IsAtLeast(gl::ContextProfile::OpenGLCore, 300) ||
     623           0 :         mGL->IsAtLeast(gl::ContextProfile::OpenGLES, 300)) {
     624           0 :         format = LOCAL_GL_RED;
     625           0 :         internalFormat = LOCAL_GL_R8;
     626             :     } else {
     627           0 :         format = LOCAL_GL_LUMINANCE;
     628           0 :         internalFormat = LOCAL_GL_LUMINANCE;
     629             :     }
     630             : 
     631           0 :     if (!tex) {
     632           0 :         MOZ_ASSERT(needsAllocation);
     633           0 :         tex = CreateTexture(mGL, internalFormat, format, LOCAL_GL_UNSIGNED_BYTE,
     634           0 :                             gfx::IntSize(width, height), false);
     635             :     }
     636           0 :     mGL->fActiveTexture(LOCAL_GL_TEXTURE0 + which);
     637             : 
     638           0 :     mGL->fBindTexture(LOCAL_GL_TEXTURE_2D, tex);
     639           0 :     if (!needsAllocation) {
     640           0 :         mGL->fTexSubImage2D(LOCAL_GL_TEXTURE_2D,
     641             :                             0,
     642             :                             0,
     643             :                             0,
     644             :                             width,
     645             :                             height,
     646             :                             format,
     647             :                             LOCAL_GL_UNSIGNED_BYTE,
     648           0 :                             data);
     649             :     } else {
     650           0 :         mGL->fTexImage2D(LOCAL_GL_TEXTURE_2D,
     651             :                          0,
     652             :                          internalFormat,
     653             :                          width,
     654             :                          height,
     655             :                          0,
     656             :                          format,
     657             :                          LOCAL_GL_UNSIGNED_BYTE,
     658           0 :                          data);
     659             :     }
     660           0 : }
     661             : 
     662             : void
     663           0 : GLBlitHelper::BindAndUploadEGLImage(EGLImage image, GLuint target)
     664             : {
     665           0 :     MOZ_ASSERT(image != EGL_NO_IMAGE, "Bad EGLImage");
     666             : 
     667           0 :     if (!mSrcTexEGL) {
     668           0 :         mGL->fGenTextures(1, &mSrcTexEGL);
     669           0 :         mGL->fBindTexture(target, mSrcTexEGL);
     670           0 :         mGL->fTexParameteri(target, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);
     671           0 :         mGL->fTexParameteri(target, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE);
     672           0 :         mGL->fTexParameteri(target, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_NEAREST);
     673           0 :         mGL->fTexParameteri(target, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_NEAREST);
     674             :     } else {
     675           0 :         mGL->fBindTexture(target, mSrcTexEGL);
     676             :     }
     677           0 :     mGL->fEGLImageTargetTexture2D(target, image);
     678           0 : }
     679             : 
     680             : #ifdef MOZ_WIDGET_ANDROID
     681             : 
     682             : #define ATTACH_WAIT_MS 50
     683             : 
     684             : bool
     685             : GLBlitHelper::BlitSurfaceTextureImage(layers::SurfaceTextureImage* stImage)
     686             : {
     687             :     // FIXME
     688             :     return false;
     689             : }
     690             : 
     691             : bool
     692             : GLBlitHelper::BlitEGLImageImage(layers::EGLImageImage* image)
     693             : {
     694             :     EGLImage eglImage = image->GetImage();
     695             :     EGLSync eglSync = image->GetSync();
     696             : 
     697             :     if (eglSync) {
     698             :         EGLint status = sEGLLibrary.fClientWaitSync(EGL_DISPLAY(), eglSync, 0, LOCAL_EGL_FOREVER);
     699             :         if (status != LOCAL_EGL_CONDITION_SATISFIED) {
     700             :             return false;
     701             :         }
     702             :     }
     703             : 
     704             :     ScopedBindTextureUnit boundTU(mGL, LOCAL_GL_TEXTURE0);
     705             : 
     706             :     int oldBinding = 0;
     707             :     mGL->fGetIntegerv(LOCAL_GL_TEXTURE_BINDING_2D, &oldBinding);
     708             : 
     709             :     BindAndUploadEGLImage(eglImage, LOCAL_GL_TEXTURE_2D);
     710             : 
     711             :     mGL->fDrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4);
     712             : 
     713             :     mGL->fBindTexture(LOCAL_GL_TEXTURE_2D, oldBinding);
     714             :     return true;
     715             : }
     716             : 
     717             : #endif
     718             : 
     719             : bool
     720           0 : GLBlitHelper::BlitPlanarYCbCrImage(layers::PlanarYCbCrImage* yuvImage)
     721             : {
     722           0 :     ScopedBindTextureUnit boundTU(mGL, LOCAL_GL_TEXTURE0);
     723           0 :     const PlanarYCbCrData* yuvData = yuvImage->GetData();
     724             : 
     725           0 :     bool needsAllocation = false;
     726           0 :     if (mTexWidth != yuvData->mYStride || mTexHeight != yuvData->mYSize.height) {
     727           0 :         mTexWidth = yuvData->mYStride;
     728           0 :         mTexHeight = yuvData->mYSize.height;
     729           0 :         needsAllocation = true;
     730             :     }
     731             : 
     732             :     GLint oldTex[3];
     733           0 :     for (int i = 0; i < 3; i++) {
     734           0 :         mGL->fActiveTexture(LOCAL_GL_TEXTURE0 + i);
     735           0 :         mGL->fGetIntegerv(LOCAL_GL_TEXTURE_BINDING_2D, &oldTex[i]);
     736             :     }
     737             : 
     738             :     {
     739           0 :         const ResetUnpackState reset(mGL);
     740           0 :         BindAndUploadYUVTexture(Channel_Y, yuvData->mYStride, yuvData->mYSize.height, yuvData->mYChannel, needsAllocation);
     741           0 :         BindAndUploadYUVTexture(Channel_Cb, yuvData->mCbCrStride, yuvData->mCbCrSize.height, yuvData->mCbChannel, needsAllocation);
     742           0 :         BindAndUploadYUVTexture(Channel_Cr, yuvData->mCbCrStride, yuvData->mCbCrSize.height, yuvData->mCrChannel, needsAllocation);
     743             :     }
     744             : 
     745           0 :     if (needsAllocation) {
     746           0 :         mGL->fUniform2f(mYTexScaleLoc, (float)yuvData->mYSize.width/yuvData->mYStride, 1.0f);
     747           0 :         mGL->fUniform2f(mCbCrTexScaleLoc, (float)yuvData->mCbCrSize.width/yuvData->mCbCrStride, 1.0f);
     748             :     }
     749             : 
     750           0 :     const auto& yuvToRgb = gfxUtils::YuvToRgbMatrix3x3ColumnMajor(yuvData->mYUVColorSpace);
     751           0 :     mGL->fUniformMatrix3fv(mYuvColorMatrixLoc, 1, 0, yuvToRgb);
     752             : 
     753           0 :     mGL->fDrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4);
     754           0 :     for (int i = 0; i < 3; i++) {
     755           0 :         mGL->fActiveTexture(LOCAL_GL_TEXTURE0 + i);
     756           0 :         mGL->fBindTexture(LOCAL_GL_TEXTURE_2D, oldTex[i]);
     757             :     }
     758           0 :     return true;
     759             : }
     760             : 
     761             : #ifdef XP_MACOSX
     762             : bool
     763             : GLBlitHelper::BlitMacIOSurfaceImage(layers::MacIOSurfaceImage* ioImage)
     764             : {
     765             :     ScopedBindTextureUnit boundTU(mGL, LOCAL_GL_TEXTURE0);
     766             :     MacIOSurface* surf = ioImage->GetSurface();
     767             : 
     768             :     GLint oldTex[2];
     769             :     for (int i = 0; i < 2; i++) {
     770             :         mGL->fActiveTexture(LOCAL_GL_TEXTURE0 + i);
     771             :         mGL->fGetIntegerv(LOCAL_GL_TEXTURE_BINDING_2D, &oldTex[i]);
     772             :     }
     773             : 
     774             :     GLuint textures[2];
     775             :     mGL->fGenTextures(2, textures);
     776             : 
     777             :     mGL->fActiveTexture(LOCAL_GL_TEXTURE0);
     778             :     mGL->fBindTexture(LOCAL_GL_TEXTURE_RECTANGLE_ARB, textures[0]);
     779             :     mGL->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE);
     780             :     mGL->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);
     781             :     surf->CGLTexImageIOSurface2D(mGL,
     782             :                                  gl::GLContextCGL::Cast(mGL)->GetCGLContext(),
     783             :                                  0);
     784             :     mGL->fUniform2f(mYTexScaleLoc, surf->GetWidth(0), surf->GetHeight(0));
     785             : 
     786             :     mGL->fActiveTexture(LOCAL_GL_TEXTURE1);
     787             :     mGL->fBindTexture(LOCAL_GL_TEXTURE_RECTANGLE_ARB, textures[1]);
     788             :     mGL->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE);
     789             :     mGL->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);
     790             :     surf->CGLTexImageIOSurface2D(mGL,
     791             :                                  gl::GLContextCGL::Cast(mGL)->GetCGLContext(),
     792             :                                  1);
     793             :     mGL->fUniform2f(mCbCrTexScaleLoc, surf->GetWidth(1), surf->GetHeight(1));
     794             : 
     795             :     mGL->fDrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4);
     796             :     for (int i = 0; i < 2; i++) {
     797             :         mGL->fActiveTexture(LOCAL_GL_TEXTURE0 + i);
     798             :         mGL->fBindTexture(LOCAL_GL_TEXTURE_2D, oldTex[i]);
     799             :     }
     800             : 
     801             :     mGL->fDeleteTextures(2, textures);
     802             :     return true;
     803             : }
     804             : #endif
     805             : 
     806             : bool
     807           0 : GLBlitHelper::BlitImageToFramebuffer(layers::Image* srcImage,
     808             :                                      const gfx::IntSize& destSize,
     809             :                                      GLuint destFB,
     810             :                                      OriginPos destOrigin)
     811             : {
     812           0 :     ScopedGLDrawState autoStates(mGL);
     813             : 
     814             :     BlitType type;
     815             :     OriginPos srcOrigin;
     816             : 
     817           0 :     switch (srcImage->GetFormat()) {
     818             :     case ImageFormat::PLANAR_YCBCR:
     819           0 :         type = ConvertPlanarYCbCr;
     820           0 :         srcOrigin = OriginPos::BottomLeft;
     821           0 :         break;
     822             : 
     823             : #ifdef MOZ_WIDGET_ANDROID
     824             :     case ImageFormat::SURFACE_TEXTURE:
     825             :         type = ConvertSurfaceTexture;
     826             :         srcOrigin = srcImage->AsSurfaceTextureImage()->GetOriginPos();
     827             :         break;
     828             :     case ImageFormat::EGLIMAGE:
     829             :         type = ConvertEGLImage;
     830             :         srcOrigin = srcImage->AsEGLImageImage()->GetOriginPos();
     831             :         break;
     832             : #endif
     833             : #ifdef XP_MACOSX
     834             :     case ImageFormat::MAC_IOSURFACE:
     835             :         type = ConvertMacIOSurfaceImage;
     836             :         srcOrigin = OriginPos::TopLeft;
     837             :         break;
     838             : #endif
     839             : 
     840             :     default:
     841           0 :         return false;
     842             :     }
     843             : 
     844           0 :     bool init = InitTexQuadProgram(type);
     845           0 :     if (!init) {
     846           0 :         return false;
     847             :     }
     848             : 
     849           0 :     const bool needsYFlip = (srcOrigin != destOrigin);
     850           0 :     mGL->fUniform1f(mYFlipLoc, needsYFlip ? (float)1.0 : (float)0.0);
     851             : 
     852           0 :     ScopedBindFramebuffer boundFB(mGL, destFB);
     853           0 :     mGL->fColorMask(LOCAL_GL_TRUE, LOCAL_GL_TRUE, LOCAL_GL_TRUE, LOCAL_GL_TRUE);
     854           0 :     mGL->fViewport(0, 0, destSize.width, destSize.height);
     855             : 
     856           0 :     switch (type) {
     857             :     case ConvertPlanarYCbCr:
     858           0 :         return BlitPlanarYCbCrImage(static_cast<PlanarYCbCrImage*>(srcImage));
     859             : 
     860             : #ifdef MOZ_WIDGET_ANDROID
     861             :     case ConvertSurfaceTexture:
     862             :         return BlitSurfaceTextureImage(static_cast<layers::SurfaceTextureImage*>(srcImage));
     863             : 
     864             :     case ConvertEGLImage:
     865             :         return BlitEGLImageImage(static_cast<layers::EGLImageImage*>(srcImage));
     866             : #endif
     867             : 
     868             : #ifdef XP_MACOSX
     869             :     case ConvertMacIOSurfaceImage:
     870             :         return BlitMacIOSurfaceImage(srcImage->AsMacIOSurfaceImage());
     871             : #endif
     872             : 
     873             :     default:
     874           0 :         return false;
     875             :     }
     876             : }
     877             : 
     878             : bool
     879           0 : GLBlitHelper::BlitImageToTexture(layers::Image* srcImage,
     880             :                                  const gfx::IntSize& destSize,
     881             :                                  GLuint destTex,
     882             :                                  GLenum destTarget,
     883             :                                  OriginPos destOrigin)
     884             : {
     885           0 :     ScopedFramebufferForTexture autoFBForTex(mGL, destTex, destTarget);
     886           0 :     if (!autoFBForTex.IsComplete())
     887           0 :         return false;
     888             : 
     889           0 :     return BlitImageToFramebuffer(srcImage, destSize, autoFBForTex.FB(), destOrigin);
     890             : }
     891             : 
     892             : void
     893           0 : GLBlitHelper::BlitTextureToFramebuffer(GLuint srcTex, GLuint destFB,
     894             :                                        const gfx::IntSize& srcSize,
     895             :                                        const gfx::IntSize& destSize,
     896             :                                        GLenum srcTarget,
     897             :                                        bool internalFBs)
     898             : {
     899           0 :     MOZ_ASSERT(mGL->fIsTexture(srcTex));
     900           0 :     MOZ_ASSERT(!destFB || mGL->fIsFramebuffer(destFB));
     901             : 
     902           0 :     if (mGL->IsSupported(GLFeature::framebuffer_blit)) {
     903           0 :         ScopedFramebufferForTexture srcWrapper(mGL, srcTex, srcTarget);
     904           0 :         MOZ_DIAGNOSTIC_ASSERT(srcWrapper.IsComplete());
     905             : 
     906           0 :         BlitFramebufferToFramebuffer(srcWrapper.FB(), destFB,
     907             :                                      srcSize, destSize,
     908           0 :                                      internalFBs);
     909           0 :         return;
     910             :     }
     911             : 
     912           0 :     DrawBlitTextureToFramebuffer(srcTex, destFB, srcSize, destSize, srcTarget,
     913           0 :                                  internalFBs);
     914             : }
     915             : 
     916             : 
     917             : void
     918           0 : GLBlitHelper::DrawBlitTextureToFramebuffer(GLuint srcTex, GLuint destFB,
     919             :                                            const gfx::IntSize& srcSize,
     920             :                                            const gfx::IntSize& destSize,
     921             :                                            GLenum srcTarget,
     922             :                                            bool internalFBs)
     923             : {
     924             :     BlitType type;
     925           0 :     switch (srcTarget) {
     926             :     case LOCAL_GL_TEXTURE_2D:
     927           0 :         type = BlitTex2D;
     928           0 :         break;
     929             :     case LOCAL_GL_TEXTURE_RECTANGLE_ARB:
     930           0 :         type = BlitTexRect;
     931           0 :         break;
     932             :     default:
     933           0 :         MOZ_CRASH("GFX: Fatal Error: Bad `srcTarget`.");
     934             :         break;
     935             :     }
     936             : 
     937           0 :     ScopedGLDrawState autoStates(mGL);
     938           0 :     const ScopedBindFramebuffer bindFB(mGL);
     939           0 :     if (internalFBs) {
     940           0 :         mGL->Screen()->BindFB_Internal(destFB);
     941             :     } else {
     942           0 :         mGL->BindFB(destFB);
     943             :     }
     944             : 
     945             :     // Does destructive things to (only!) what we just saved above.
     946           0 :     bool good = UseTexQuadProgram(type, srcSize);
     947           0 :     if (!good) {
     948             :         // We're up against the wall, so bail.
     949           0 :         MOZ_DIAGNOSTIC_ASSERT(false,
     950             :                               "Error: Failed to prepare to blit texture->framebuffer.\n");
     951             :         mGL->fScissor(0, 0, destSize.width, destSize.height);
     952             :         mGL->fColorMask(1, 1, 1, 1);
     953             :         mGL->fClear(LOCAL_GL_COLOR_BUFFER_BIT);
     954             :         return;
     955             :     }
     956             : 
     957           0 :     const ScopedBindTexture bindTex(mGL, srcTex, srcTarget);
     958           0 :     mGL->fDrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4);
     959             : }
     960             : 
     961             : void
     962           0 : GLBlitHelper::BlitFramebufferToTexture(GLuint srcFB, GLuint destTex,
     963             :                                        const gfx::IntSize& srcSize,
     964             :                                        const gfx::IntSize& destSize,
     965             :                                        GLenum destTarget,
     966             :                                        bool internalFBs)
     967             : {
     968             :     // On the Android 4.3 emulator, IsFramebuffer may return false incorrectly.
     969           0 :     MOZ_ASSERT_IF(mGL->Renderer() != GLRenderer::AndroidEmulator, !srcFB || mGL->fIsFramebuffer(srcFB));
     970           0 :     MOZ_ASSERT(mGL->fIsTexture(destTex));
     971             : 
     972           0 :     if (mGL->IsSupported(GLFeature::framebuffer_blit)) {
     973           0 :         ScopedFramebufferForTexture destWrapper(mGL, destTex, destTarget);
     974             : 
     975           0 :         BlitFramebufferToFramebuffer(srcFB, destWrapper.FB(),
     976             :                                      srcSize, destSize,
     977           0 :                                      internalFBs);
     978           0 :         return;
     979             :     }
     980             : 
     981           0 :     ScopedBindTexture autoTex(mGL, destTex, destTarget);
     982             : 
     983           0 :     ScopedBindFramebuffer boundFB(mGL);
     984           0 :     if (internalFBs) {
     985           0 :         mGL->Screen()->BindFB_Internal(srcFB);
     986             :     } else {
     987           0 :         mGL->BindFB(srcFB);
     988             :     }
     989             : 
     990           0 :     ScopedGLState scissor(mGL, LOCAL_GL_SCISSOR_TEST, false);
     991           0 :     mGL->fCopyTexSubImage2D(destTarget, 0,
     992             :                        0, 0,
     993             :                        0, 0,
     994           0 :                        srcSize.width, srcSize.height);
     995             : }
     996             : 
     997             : void
     998           0 : GLBlitHelper::BlitTextureToTexture(GLuint srcTex, GLuint destTex,
     999             :                                    const gfx::IntSize& srcSize,
    1000             :                                    const gfx::IntSize& destSize,
    1001             :                                    GLenum srcTarget, GLenum destTarget)
    1002             : {
    1003           0 :     MOZ_ASSERT(mGL->fIsTexture(srcTex));
    1004           0 :     MOZ_ASSERT(mGL->fIsTexture(destTex));
    1005             : 
    1006             :     // Generally, just use the CopyTexSubImage path
    1007           0 :     ScopedFramebufferForTexture srcWrapper(mGL, srcTex, srcTarget);
    1008             : 
    1009           0 :     BlitFramebufferToTexture(srcWrapper.FB(), destTex,
    1010           0 :                              srcSize, destSize, destTarget);
    1011           0 : }
    1012             : 
    1013             : } // namespace gl
    1014             : } // namespace mozilla

Generated by: LCOV version 1.13