LCOV - code coverage report
Current view: top level - gfx/gl - GLReadTexImageHelper.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 315 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 13 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 "GLReadTexImageHelper.h"
       8             : 
       9             : #include "gfx2DGlue.h"
      10             : #include "gfxColor.h"
      11             : #include "gfxTypes.h"
      12             : #include "GLContext.h"
      13             : #include "OGLShaderProgram.h"
      14             : #include "ScopedGLHelpers.h"
      15             : 
      16             : #include "mozilla/gfx/2D.h"
      17             : #include "mozilla/Move.h"
      18             : 
      19             : namespace mozilla {
      20             : namespace gl {
      21             : 
      22             : using namespace mozilla::gfx;
      23             : 
      24           0 : GLReadTexImageHelper::GLReadTexImageHelper(GLContext* gl)
      25           0 :     : mGL(gl)
      26             : {
      27           0 :     mPrograms[0] = 0;
      28           0 :     mPrograms[1] = 0;
      29           0 :     mPrograms[2] = 0;
      30           0 :     mPrograms[3] = 0;
      31           0 : }
      32             : 
      33           0 : GLReadTexImageHelper::~GLReadTexImageHelper()
      34             : {
      35           0 :     if (!mGL->MakeCurrent())
      36           0 :         return;
      37             : 
      38           0 :     mGL->fDeleteProgram(mPrograms[0]);
      39           0 :     mGL->fDeleteProgram(mPrograms[1]);
      40           0 :     mGL->fDeleteProgram(mPrograms[2]);
      41           0 :     mGL->fDeleteProgram(mPrograms[3]);
      42           0 : }
      43             : 
      44             : static const GLchar
      45             : readTextureImageVS[] =
      46             :     "attribute vec2 aVertex;\n"
      47             :     "attribute vec2 aTexCoord;\n"
      48             :     "varying vec2 vTexCoord;\n"
      49             :     "void main() { gl_Position = vec4(aVertex, 0, 1); vTexCoord = aTexCoord; }";
      50             : 
      51             : static const GLchar
      52             : readTextureImageFS_TEXTURE_2D[] =
      53             :     "#ifdef GL_ES\n"
      54             :     "precision mediump float;\n"
      55             :     "#endif\n"
      56             :     "varying vec2 vTexCoord;\n"
      57             :     "uniform sampler2D uTexture;\n"
      58             :     "void main() { gl_FragColor = texture2D(uTexture, vTexCoord); }";
      59             : 
      60             : 
      61             : static const GLchar
      62             : readTextureImageFS_TEXTURE_2D_BGRA[] =
      63             :     "#ifdef GL_ES\n"
      64             :     "precision mediump float;\n"
      65             :     "#endif\n"
      66             :     "varying vec2 vTexCoord;\n"
      67             :     "uniform sampler2D uTexture;\n"
      68             :     "void main() { gl_FragColor = texture2D(uTexture, vTexCoord).bgra; }";
      69             : 
      70             : static const GLchar
      71             : readTextureImageFS_TEXTURE_EXTERNAL[] =
      72             :     "#extension GL_OES_EGL_image_external : require\n"
      73             :     "#ifdef GL_ES\n"
      74             :     "precision mediump float;\n"
      75             :     "#endif\n"
      76             :     "varying vec2 vTexCoord;\n"
      77             :     "uniform samplerExternalOES uTexture;\n"
      78             :     "void main() { gl_FragColor = texture2D(uTexture, vTexCoord); }";
      79             : 
      80             : static const GLchar
      81             : readTextureImageFS_TEXTURE_RECTANGLE[] =
      82             :     "#extension GL_ARB_texture_rectangle\n"
      83             :     "#ifdef GL_ES\n"
      84             :     "precision mediump float;\n"
      85             :     "#endif\n"
      86             :     "varying vec2 vTexCoord;\n"
      87             :     "uniform sampler2DRect uTexture;\n"
      88             :     "void main() { gl_FragColor = texture2DRect(uTexture, vTexCoord).bgra; }";
      89             : 
      90             : GLuint
      91           0 : GLReadTexImageHelper::TextureImageProgramFor(GLenum aTextureTarget,
      92             :                                              int aConfig)
      93             : {
      94           0 :     int variant = 0;
      95           0 :     const GLchar* readTextureImageFS = nullptr;
      96           0 :     if (aTextureTarget == LOCAL_GL_TEXTURE_2D) {
      97           0 :         if (aConfig & mozilla::layers::ENABLE_TEXTURE_RB_SWAP) {
      98             :             // Need to swizzle R/B.
      99           0 :             readTextureImageFS = readTextureImageFS_TEXTURE_2D_BGRA;
     100           0 :             variant = 1;
     101             :         } else {
     102           0 :             readTextureImageFS = readTextureImageFS_TEXTURE_2D;
     103           0 :             variant = 0;
     104             :         }
     105           0 :     } else if (aTextureTarget == LOCAL_GL_TEXTURE_EXTERNAL) {
     106           0 :         readTextureImageFS = readTextureImageFS_TEXTURE_EXTERNAL;
     107           0 :         variant = 2;
     108           0 :     } else if (aTextureTarget == LOCAL_GL_TEXTURE_RECTANGLE) {
     109           0 :         readTextureImageFS = readTextureImageFS_TEXTURE_RECTANGLE;
     110           0 :         variant = 3;
     111             :     }
     112             : 
     113             :     /* This might be overkill, but assure that we don't access out-of-bounds */
     114           0 :     MOZ_ASSERT((size_t) variant < ArrayLength(mPrograms));
     115           0 :     if (!mPrograms[variant]) {
     116           0 :         GLuint vs = mGL->fCreateShader(LOCAL_GL_VERTEX_SHADER);
     117           0 :         const GLchar* vsSourcePtr = &readTextureImageVS[0];
     118           0 :         mGL->fShaderSource(vs, 1, &vsSourcePtr, nullptr);
     119           0 :         mGL->fCompileShader(vs);
     120             : 
     121           0 :         GLuint fs = mGL->fCreateShader(LOCAL_GL_FRAGMENT_SHADER);
     122           0 :         mGL->fShaderSource(fs, 1, &readTextureImageFS, nullptr);
     123           0 :         mGL->fCompileShader(fs);
     124             : 
     125           0 :         GLuint program = mGL->fCreateProgram();
     126           0 :         mGL->fAttachShader(program, vs);
     127           0 :         mGL->fAttachShader(program, fs);
     128           0 :         mGL->fBindAttribLocation(program, 0, "aVertex");
     129           0 :         mGL->fBindAttribLocation(program, 1, "aTexCoord");
     130           0 :         mGL->fLinkProgram(program);
     131             : 
     132             :         GLint success;
     133           0 :         mGL->fGetProgramiv(program, LOCAL_GL_LINK_STATUS, &success);
     134             : 
     135           0 :         if (!success) {
     136           0 :             mGL->fDeleteProgram(program);
     137           0 :             program = 0;
     138             :         }
     139             : 
     140           0 :         mGL->fDeleteShader(vs);
     141           0 :         mGL->fDeleteShader(fs);
     142             : 
     143           0 :         mPrograms[variant] = program;
     144             :     }
     145             : 
     146           0 :     return mPrograms[variant];
     147             : }
     148             : 
     149             : bool
     150           0 : GLReadTexImageHelper::DidGLErrorOccur(const char* str)
     151             : {
     152           0 :     GLenum error = mGL->fGetError();
     153           0 :     if (error != LOCAL_GL_NO_ERROR) {
     154           0 :         printf_stderr("GL ERROR: %s (0x%04x) %s\n",
     155           0 :                       mGL->GLErrorToString(error), error, str);
     156           0 :         return true;
     157             :     }
     158             : 
     159           0 :     return false;
     160             : }
     161             : 
     162             : bool
     163           0 : GetActualReadFormats(GLContext* gl,
     164             :                      GLenum destFormat, GLenum destType,
     165             :                      GLenum* out_readFormat, GLenum* out_readType)
     166             : {
     167           0 :     MOZ_ASSERT(out_readFormat);
     168           0 :     MOZ_ASSERT(out_readType);
     169             : 
     170           0 :     if (destFormat == LOCAL_GL_RGBA &&
     171             :         destType == LOCAL_GL_UNSIGNED_BYTE)
     172             :     {
     173           0 :         *out_readFormat = destFormat;
     174           0 :         *out_readType = destType;
     175           0 :         return true;
     176             :     }
     177             : 
     178           0 :     bool fallback = true;
     179           0 :     if (gl->IsGLES()) {
     180           0 :         GLenum auxFormat = 0;
     181           0 :         GLenum auxType = 0;
     182             : 
     183           0 :         gl->fGetIntegerv(LOCAL_GL_IMPLEMENTATION_COLOR_READ_FORMAT, (GLint*)&auxFormat);
     184           0 :         gl->fGetIntegerv(LOCAL_GL_IMPLEMENTATION_COLOR_READ_TYPE, (GLint*)&auxType);
     185             : 
     186           0 :         if (destFormat == auxFormat &&
     187           0 :             destType == auxType)
     188             :         {
     189           0 :             fallback = false;
     190             :         }
     191             :     } else {
     192           0 :         switch (destFormat) {
     193             :             case LOCAL_GL_RGB: {
     194           0 :                 if (destType == LOCAL_GL_UNSIGNED_SHORT_5_6_5_REV)
     195           0 :                     fallback = false;
     196           0 :                 break;
     197             :             }
     198             :             case LOCAL_GL_BGRA: {
     199           0 :                 if (destType == LOCAL_GL_UNSIGNED_BYTE ||
     200             :                     destType == LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV)
     201             :                 {
     202           0 :                     fallback = false;
     203             :                 }
     204           0 :                 break;
     205             :             }
     206             :         }
     207             :     }
     208             : 
     209           0 :     if (fallback) {
     210           0 :         *out_readFormat = LOCAL_GL_RGBA;
     211           0 :         *out_readType = LOCAL_GL_UNSIGNED_BYTE;
     212           0 :         return false;
     213             :     } else {
     214           0 :         *out_readFormat = destFormat;
     215           0 :         *out_readType = destType;
     216           0 :         return true;
     217             :     }
     218             : }
     219             : 
     220             : void
     221           0 : SwapRAndBComponents(DataSourceSurface* surf)
     222             : {
     223             :     DataSourceSurface::MappedSurface map;
     224           0 :     if (!surf->Map(DataSourceSurface::MapType::READ_WRITE, &map)) {
     225           0 :         MOZ_ASSERT(false, "SwapRAndBComponents: Failed to map surface.");
     226             :         return;
     227             :     }
     228           0 :     MOZ_ASSERT(map.mStride >= 0);
     229             : 
     230           0 :     const size_t rowBytes = surf->GetSize().width*4;
     231           0 :     const size_t rowHole = map.mStride - rowBytes;
     232             : 
     233           0 :     uint8_t* row = map.mData;
     234           0 :     if (!row) {
     235           0 :         MOZ_ASSERT(false, "SwapRAndBComponents: Failed to get data from"
     236             :                           " DataSourceSurface.");
     237             :         surf->Unmap();
     238             :         return;
     239             :     }
     240             : 
     241           0 :     const size_t rows = surf->GetSize().height;
     242           0 :     for (size_t i = 0; i < rows; i++) {
     243           0 :         const uint8_t* rowEnd = row + rowBytes;
     244             : 
     245           0 :         while (row != rowEnd) {
     246           0 :             Swap(row[0], row[2]);
     247           0 :             row += 4;
     248             :         }
     249             : 
     250           0 :         row += rowHole;
     251             :     }
     252             : 
     253           0 :     surf->Unmap();
     254             : }
     255             : 
     256             : static int
     257           0 : CalcRowStride(int width, int pixelSize, int alignment)
     258             : {
     259           0 :     MOZ_ASSERT(alignment);
     260             : 
     261           0 :     int rowStride = width * pixelSize;
     262           0 :     if (rowStride % alignment) { // Extra at the end of the line?
     263           0 :         int alignmentCount = rowStride / alignment;
     264           0 :         rowStride = (alignmentCount+1) * alignment;
     265             :     }
     266           0 :     return rowStride;
     267             : }
     268             : 
     269             : static int
     270           0 : GuessAlignment(int width, int pixelSize, int rowStride)
     271             : {
     272           0 :     int alignment = 8; // Max GLES allows.
     273           0 :     while (CalcRowStride(width, pixelSize, alignment) != rowStride) {
     274           0 :         alignment /= 2;
     275           0 :         if (!alignment) {
     276           0 :             NS_WARNING("Bad alignment for GLES. Will use temp surf for readback.");
     277           0 :             return 0;
     278             :         }
     279             :     }
     280           0 :     return alignment;
     281             : }
     282             : 
     283             : void
     284           0 : ReadPixelsIntoDataSurface(GLContext* gl, DataSourceSurface* dest)
     285             : {
     286           0 :     gl->MakeCurrent();
     287           0 :     MOZ_ASSERT(dest->GetSize().width != 0);
     288           0 :     MOZ_ASSERT(dest->GetSize().height != 0);
     289             : 
     290           0 :     bool hasAlpha = dest->GetFormat() == SurfaceFormat::B8G8R8A8 ||
     291           0 :                     dest->GetFormat() == SurfaceFormat::R8G8B8A8;
     292             : 
     293             :     int destPixelSize;
     294             :     GLenum destFormat;
     295             :     GLenum destType;
     296             : 
     297           0 :     switch (dest->GetFormat()) {
     298             :     case SurfaceFormat::B8G8R8A8:
     299             :     case SurfaceFormat::B8G8R8X8:
     300             :         // Needs host (little) endian ARGB.
     301           0 :         destFormat = LOCAL_GL_BGRA;
     302           0 :         destType = LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV;
     303           0 :         break;
     304             :     case SurfaceFormat::R8G8B8A8:
     305             :     case SurfaceFormat::R8G8B8X8:
     306             :         // Needs host (little) endian ABGR.
     307           0 :         destFormat = LOCAL_GL_RGBA;
     308           0 :         destType = LOCAL_GL_UNSIGNED_BYTE;
     309           0 :         break;
     310             :     case SurfaceFormat::R5G6B5_UINT16:
     311           0 :         destFormat = LOCAL_GL_RGB;
     312           0 :         destType = LOCAL_GL_UNSIGNED_SHORT_5_6_5_REV;
     313           0 :         break;
     314             :     default:
     315           0 :         MOZ_CRASH("GFX: Bad format, read pixels.");
     316             :     }
     317           0 :     destPixelSize = BytesPerPixel(dest->GetFormat());
     318           0 :     MOZ_ASSERT(dest->GetSize().width * destPixelSize <= dest->Stride());
     319             : 
     320           0 :     GLenum readFormat = destFormat;
     321           0 :     GLenum readType = destType;
     322           0 :     bool needsTempSurf = !GetActualReadFormats(gl,
     323             :                                                destFormat, destType,
     324           0 :                                                &readFormat, &readType);
     325             : 
     326           0 :     RefPtr<DataSourceSurface> tempSurf;
     327           0 :     DataSourceSurface* readSurf = dest;
     328           0 :     int readAlignment = GuessAlignment(dest->GetSize().width,
     329             :                                        destPixelSize,
     330           0 :                                        dest->Stride());
     331           0 :     if (!readAlignment) {
     332           0 :         needsTempSurf = true;
     333             :     }
     334           0 :     if (needsTempSurf) {
     335           0 :         if (GLContext::ShouldSpew()) {
     336           0 :             NS_WARNING("Needing intermediary surface for ReadPixels. This will be slow!");
     337             :         }
     338             :         SurfaceFormat readFormatGFX;
     339             : 
     340           0 :         switch (readFormat) {
     341             :             case LOCAL_GL_RGBA: {
     342           0 :                 readFormatGFX = hasAlpha ? SurfaceFormat::R8G8B8A8
     343             :                                          : SurfaceFormat::R8G8B8X8;
     344           0 :                 break;
     345             :             }
     346             :             case LOCAL_GL_BGRA: {
     347           0 :                 readFormatGFX = hasAlpha ? SurfaceFormat::B8G8R8A8
     348             :                                          : SurfaceFormat::B8G8R8X8;
     349           0 :                 break;
     350             :             }
     351             :             case LOCAL_GL_RGB: {
     352           0 :                 MOZ_ASSERT(destPixelSize == 2);
     353           0 :                 MOZ_ASSERT(readType == LOCAL_GL_UNSIGNED_SHORT_5_6_5_REV);
     354           0 :                 readFormatGFX = SurfaceFormat::R5G6B5_UINT16;
     355           0 :                 break;
     356             :             }
     357             :             default: {
     358           0 :                 MOZ_CRASH("GFX: Bad read format, read format.");
     359             :             }
     360             :         }
     361             : 
     362           0 :         switch (readType) {
     363             :             case LOCAL_GL_UNSIGNED_BYTE: {
     364           0 :                 MOZ_ASSERT(readFormat == LOCAL_GL_RGBA);
     365           0 :                 readAlignment = 1;
     366           0 :                 break;
     367             :             }
     368             :             case LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV: {
     369           0 :                 MOZ_ASSERT(readFormat == LOCAL_GL_BGRA);
     370           0 :                 readAlignment = 4;
     371           0 :                 break;
     372             :             }
     373             :             case LOCAL_GL_UNSIGNED_SHORT_5_6_5_REV: {
     374           0 :                 MOZ_ASSERT(readFormat == LOCAL_GL_RGB);
     375           0 :                 readAlignment = 2;
     376           0 :                 break;
     377             :             }
     378             :             default: {
     379           0 :                 MOZ_CRASH("GFX: Bad read type, read type.");
     380             :             }
     381             :         }
     382             : 
     383           0 :         int32_t stride = dest->GetSize().width * BytesPerPixel(readFormatGFX);
     384           0 :         tempSurf = Factory::CreateDataSourceSurfaceWithStride(dest->GetSize(),
     385             :                                                               readFormatGFX,
     386           0 :                                                               stride);
     387           0 :         if (NS_WARN_IF(!tempSurf)) {
     388           0 :             return;
     389             :         }
     390             : 
     391           0 :         readSurf = tempSurf;
     392             :     }
     393           0 :     MOZ_ASSERT(readAlignment);
     394           0 :     MOZ_ASSERT(reinterpret_cast<uintptr_t>(readSurf->GetData()) % readAlignment == 0);
     395             : 
     396           0 :     GLsizei width = dest->GetSize().width;
     397           0 :     GLsizei height = dest->GetSize().height;
     398             : 
     399             :     {
     400           0 :         ScopedPackState safePackState(gl);
     401           0 :         gl->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, readAlignment);
     402             : 
     403             :         gl->fReadPixels(0, 0,
     404             :                         width, height,
     405             :                         readFormat, readType,
     406           0 :                         readSurf->GetData());
     407             :     }
     408             : 
     409           0 :     if (readSurf != dest) {
     410           0 :         MOZ_ASSERT(readFormat == LOCAL_GL_RGBA);
     411           0 :         MOZ_ASSERT(readType == LOCAL_GL_UNSIGNED_BYTE);
     412           0 :         gfx::Factory::CopyDataSourceSurface(readSurf, dest);
     413             :     }
     414             : }
     415             : 
     416             : already_AddRefed<gfx::DataSourceSurface>
     417           0 : YInvertImageSurface(gfx::DataSourceSurface* aSurf)
     418             : {
     419             :     RefPtr<DataSourceSurface> temp =
     420           0 :       Factory::CreateDataSourceSurfaceWithStride(aSurf->GetSize(),
     421           0 :                                                  aSurf->GetFormat(),
     422           0 :                                                  aSurf->Stride());
     423           0 :     if (NS_WARN_IF(!temp)) {
     424           0 :         return nullptr;
     425             :     }
     426             : 
     427             :     DataSourceSurface::MappedSurface map;
     428           0 :     if (!temp->Map(DataSourceSurface::MapType::WRITE, &map)) {
     429           0 :         return nullptr;
     430             :     }
     431             : 
     432             :     RefPtr<DrawTarget> dt =
     433           0 :       Factory::CreateDrawTargetForData(BackendType::CAIRO,
     434             :                                        map.mData,
     435           0 :                                        temp->GetSize(),
     436             :                                        map.mStride,
     437           0 :                                        temp->GetFormat());
     438           0 :     if (!dt) {
     439           0 :         temp->Unmap();
     440           0 :         return nullptr;
     441             :     }
     442             : 
     443           0 :     dt->SetTransform(Matrix::Scaling(1.0, -1.0) *
     444           0 :                      Matrix::Translation(0.0, aSurf->GetSize().height));
     445           0 :     Rect rect(0, 0, aSurf->GetSize().width, aSurf->GetSize().height);
     446           0 :     dt->DrawSurface(aSurf, rect, rect, DrawSurfaceOptions(),
     447           0 :                     DrawOptions(1.0, CompositionOp::OP_SOURCE, AntialiasMode::NONE));
     448           0 :     temp->Unmap();
     449           0 :     return temp.forget();
     450             : }
     451             : 
     452             : already_AddRefed<DataSourceSurface>
     453           0 : ReadBackSurface(GLContext* gl, GLuint aTexture, bool aYInvert, SurfaceFormat aFormat)
     454             : {
     455           0 :     gl->MakeCurrent();
     456           0 :     gl->GuaranteeResolve();
     457           0 :     gl->fActiveTexture(LOCAL_GL_TEXTURE0);
     458           0 :     gl->fBindTexture(LOCAL_GL_TEXTURE_2D, aTexture);
     459             : 
     460           0 :     IntSize size;
     461           0 :     gl->fGetTexLevelParameteriv(LOCAL_GL_TEXTURE_2D, 0, LOCAL_GL_TEXTURE_WIDTH, &size.width);
     462           0 :     gl->fGetTexLevelParameteriv(LOCAL_GL_TEXTURE_2D, 0, LOCAL_GL_TEXTURE_HEIGHT, &size.height);
     463             : 
     464             :     RefPtr<DataSourceSurface> surf =
     465           0 :       Factory::CreateDataSourceSurfaceWithStride(size, SurfaceFormat::B8G8R8A8,
     466           0 :                                                  GetAlignedStride<4>(size.width, BytesPerPixel(SurfaceFormat::B8G8R8A8)));
     467             : 
     468           0 :     if (NS_WARN_IF(!surf)) {
     469           0 :         return nullptr;
     470             :     }
     471             : 
     472           0 :     uint32_t currentPackAlignment = 0;
     473           0 :     gl->fGetIntegerv(LOCAL_GL_PACK_ALIGNMENT, (GLint*)&currentPackAlignment);
     474           0 :     if (currentPackAlignment != 4) {
     475           0 :         gl->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, 4);
     476             :     }
     477             : 
     478           0 :     gl->fGetTexImage(LOCAL_GL_TEXTURE_2D, 0, LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE, surf->GetData());
     479             : 
     480           0 :     if (currentPackAlignment != 4) {
     481           0 :         gl->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, currentPackAlignment);
     482             :     }
     483             : 
     484           0 :     if (aFormat == SurfaceFormat::R8G8B8A8 || aFormat == SurfaceFormat::R8G8B8X8) {
     485           0 :         SwapRAndBComponents(surf);
     486             :     }
     487             : 
     488           0 :     if (aYInvert) {
     489           0 :         surf = YInvertImageSurface(surf);
     490             :     }
     491             : 
     492           0 :     return surf.forget();
     493             : }
     494             : 
     495             : #define CLEANUP_IF_GLERROR_OCCURRED(x)                                      \
     496             :     if (DidGLErrorOccur(x)) {                                               \
     497             :         return false;                                                       \
     498             :     }
     499             : 
     500             : already_AddRefed<DataSourceSurface>
     501           0 : GLReadTexImageHelper::ReadTexImage(GLuint aTextureId,
     502             :                                    GLenum aTextureTarget,
     503             :                                    const gfx::IntSize& aSize,
     504             :     /* ShaderConfigOGL.mFeature */ int aConfig,
     505             :                                    bool aYInvert)
     506             : {
     507             :     /* Allocate resulting image surface */
     508           0 :     int32_t stride = aSize.width * BytesPerPixel(SurfaceFormat::R8G8B8A8);
     509             :     RefPtr<DataSourceSurface> isurf =
     510           0 :         Factory::CreateDataSourceSurfaceWithStride(aSize,
     511             :                                                    SurfaceFormat::R8G8B8A8,
     512           0 :                                                    stride);
     513           0 :     if (NS_WARN_IF(!isurf)) {
     514           0 :         return nullptr;
     515             :     }
     516             : 
     517           0 :     if (!ReadTexImage(isurf, aTextureId, aTextureTarget, aSize, aConfig, aYInvert)) {
     518           0 :         return nullptr;
     519             :     }
     520             : 
     521           0 :     return isurf.forget();
     522             : }
     523             : 
     524             : bool
     525           0 : GLReadTexImageHelper::ReadTexImage(DataSourceSurface* aDest,
     526             :                                    GLuint aTextureId,
     527             :                                    GLenum aTextureTarget,
     528             :                                    const gfx::IntSize& aSize,
     529             :     /* ShaderConfigOGL.mFeature */ int aConfig,
     530             :                                    bool aYInvert)
     531             : {
     532           0 :     MOZ_ASSERT(aTextureTarget == LOCAL_GL_TEXTURE_2D ||
     533             :                aTextureTarget == LOCAL_GL_TEXTURE_EXTERNAL ||
     534             :                aTextureTarget == LOCAL_GL_TEXTURE_RECTANGLE_ARB);
     535             : 
     536           0 :     mGL->MakeCurrent();
     537             : 
     538             :     GLint oldrb, oldfb, oldprog, oldTexUnit, oldTex;
     539             :     GLuint rb, fb;
     540             : 
     541             :     do {
     542           0 :         mGL->fGetIntegerv(LOCAL_GL_RENDERBUFFER_BINDING, &oldrb);
     543           0 :         mGL->fGetIntegerv(LOCAL_GL_FRAMEBUFFER_BINDING, &oldfb);
     544           0 :         mGL->fGetIntegerv(LOCAL_GL_CURRENT_PROGRAM, &oldprog);
     545           0 :         mGL->fGetIntegerv(LOCAL_GL_ACTIVE_TEXTURE, &oldTexUnit);
     546           0 :         mGL->fActiveTexture(LOCAL_GL_TEXTURE0);
     547           0 :         switch (aTextureTarget) {
     548             :         case LOCAL_GL_TEXTURE_2D:
     549           0 :             mGL->fGetIntegerv(LOCAL_GL_TEXTURE_BINDING_2D, &oldTex);
     550           0 :             break;
     551             :         case LOCAL_GL_TEXTURE_EXTERNAL:
     552           0 :             mGL->fGetIntegerv(LOCAL_GL_TEXTURE_BINDING_EXTERNAL, &oldTex);
     553           0 :             break;
     554             :         case LOCAL_GL_TEXTURE_RECTANGLE:
     555           0 :             mGL->fGetIntegerv(LOCAL_GL_TEXTURE_BINDING_RECTANGLE, &oldTex);
     556           0 :             break;
     557             :         default: /* Already checked above */
     558           0 :             break;
     559             :         }
     560             : 
     561           0 :         ScopedGLState scopedScissorTestState(mGL, LOCAL_GL_SCISSOR_TEST, false);
     562           0 :         ScopedGLState scopedBlendState(mGL, LOCAL_GL_BLEND, false);
     563           0 :         ScopedViewportRect scopedViewportRect(mGL, 0, 0, aSize.width, aSize.height);
     564             : 
     565             :         /* Setup renderbuffer */
     566           0 :         mGL->fGenRenderbuffers(1, &rb);
     567           0 :         mGL->fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, rb);
     568             : 
     569             :         GLenum rbInternalFormat =
     570           0 :             mGL->IsGLES()
     571           0 :                 ? (mGL->IsExtensionSupported(GLContext::OES_rgb8_rgba8) ? LOCAL_GL_RGBA8 : LOCAL_GL_RGBA4)
     572           0 :                 : LOCAL_GL_RGBA;
     573           0 :         mGL->fRenderbufferStorage(LOCAL_GL_RENDERBUFFER, rbInternalFormat, aSize.width, aSize.height);
     574           0 :         CLEANUP_IF_GLERROR_OCCURRED("when binding and creating renderbuffer");
     575             : 
     576             :         /* Setup framebuffer */
     577           0 :         mGL->fGenFramebuffers(1, &fb);
     578           0 :         mGL->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, fb);
     579           0 :         mGL->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0,
     580           0 :                                       LOCAL_GL_RENDERBUFFER, rb);
     581           0 :         CLEANUP_IF_GLERROR_OCCURRED("when binding and creating framebuffer");
     582             : 
     583           0 :         MOZ_ASSERT(mGL->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER) == LOCAL_GL_FRAMEBUFFER_COMPLETE);
     584             : 
     585             :         /* Setup vertex and fragment shader */
     586           0 :         GLuint program = TextureImageProgramFor(aTextureTarget, aConfig);
     587           0 :         MOZ_ASSERT(program);
     588             : 
     589           0 :         mGL->fUseProgram(program);
     590           0 :         CLEANUP_IF_GLERROR_OCCURRED("when using program");
     591           0 :         mGL->fUniform1i(mGL->fGetUniformLocation(program, "uTexture"), 0);
     592           0 :         CLEANUP_IF_GLERROR_OCCURRED("when setting uniform location");
     593             : 
     594             :         /* Setup quad geometry */
     595           0 :         mGL->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
     596             : 
     597           0 :         float w = (aTextureTarget == LOCAL_GL_TEXTURE_RECTANGLE) ? (float) aSize.width : 1.0f;
     598           0 :         float h = (aTextureTarget == LOCAL_GL_TEXTURE_RECTANGLE) ? (float) aSize.height : 1.0f;
     599             : 
     600             :         const float
     601             :         vertexArray[4*2] = {
     602             :             -1.0f, -1.0f,
     603             :             1.0f, -1.0f,
     604             :             -1.0f,  1.0f,
     605             :             1.0f,  1.0f
     606           0 :         };
     607           0 :         ScopedVertexAttribPointer autoAttrib0(mGL, 0, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, 0, vertexArray);
     608             : 
     609           0 :         const float u0 = 0.0f;
     610           0 :         const float u1 = w;
     611           0 :         const float v0 = aYInvert ? h : 0.0f;
     612           0 :         const float v1 = aYInvert ? 0.0f : h;
     613             :         const float texCoordArray[8] = { u0, v0,
     614             :                                          u1, v0,
     615             :                                          u0, v1,
     616           0 :                                          u1, v1 };
     617           0 :         ScopedVertexAttribPointer autoAttrib1(mGL, 1, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, 0, texCoordArray);
     618             : 
     619             :         /* Bind the texture */
     620           0 :         if (aTextureId) {
     621           0 :             mGL->fBindTexture(aTextureTarget, aTextureId);
     622           0 :             CLEANUP_IF_GLERROR_OCCURRED("when binding texture");
     623             :         }
     624             : 
     625             :         /* Draw quad */
     626           0 :         mGL->fClearColor(1.0f, 0.0f, 1.0f, 1.0f);
     627           0 :         mGL->fClear(LOCAL_GL_COLOR_BUFFER_BIT);
     628           0 :         CLEANUP_IF_GLERROR_OCCURRED("when clearing color buffer");
     629             : 
     630           0 :         mGL->fDrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4);
     631           0 :         CLEANUP_IF_GLERROR_OCCURRED("when drawing texture");
     632             : 
     633             :         /* Read-back draw results */
     634           0 :         ReadPixelsIntoDataSurface(mGL, aDest);
     635           0 :         CLEANUP_IF_GLERROR_OCCURRED("when reading pixels into surface");
     636             :     } while (false);
     637             : 
     638             :     /* Restore GL state */
     639           0 :     mGL->fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, oldrb);
     640           0 :     mGL->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, oldfb);
     641           0 :     mGL->fUseProgram(oldprog);
     642             : 
     643             :     // note that deleting 0 has no effect in any of these calls
     644           0 :     mGL->fDeleteRenderbuffers(1, &rb);
     645           0 :     mGL->fDeleteFramebuffers(1, &fb);
     646             : 
     647           0 :     if (aTextureId)
     648           0 :         mGL->fBindTexture(aTextureTarget, oldTex);
     649             : 
     650           0 :     if (oldTexUnit != LOCAL_GL_TEXTURE0)
     651           0 :         mGL->fActiveTexture(oldTexUnit);
     652             : 
     653           0 :     return true;
     654             : }
     655             : 
     656             : #undef CLEANUP_IF_GLERROR_OCCURRED
     657             : 
     658             : } // namespace gl
     659             : } // namespace mozilla

Generated by: LCOV version 1.13