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

          Line data    Source code
       1             : /*
       2             :  * Copyright 2011 Google Inc.
       3             :  *
       4             :  * Use of this source code is governed by a BSD-style license that can be
       5             :  * found in the LICENSE file.
       6             :  */
       7             : 
       8             : #include "GrGLGpu.h"
       9             : 
      10             : #include "../private/GrGLSL.h"
      11             : #include "GrFixedClip.h"
      12             : #include "GrGLBuffer.h"
      13             : #include "GrGLGpuCommandBuffer.h"
      14             : #include "GrGLSemaphore.h"
      15             : #include "GrGLStencilAttachment.h"
      16             : #include "GrGLTextureRenderTarget.h"
      17             : #include "GrGpuResourcePriv.h"
      18             : #include "GrMesh.h"
      19             : #include "GrPipeline.h"
      20             : #include "GrRenderTargetPriv.h"
      21             : #include "GrShaderCaps.h"
      22             : #include "GrSurfacePriv.h"
      23             : #include "GrSurfaceProxyPriv.h"
      24             : #include "GrTexturePriv.h"
      25             : #include "GrTypes.h"
      26             : #include "SkAutoMalloc.h"
      27             : #include "SkMakeUnique.h"
      28             : #include "SkMipMap.h"
      29             : #include "SkPixmap.h"
      30             : #include "SkSLCompiler.h"
      31             : #include "SkStrokeRec.h"
      32             : #include "SkTemplates.h"
      33             : #include "SkTypes.h"
      34             : #include "builders/GrGLShaderStringBuilder.h"
      35             : #include "instanced/GLInstancedRendering.h"
      36             : 
      37             : #define GL_CALL(X) GR_GL_CALL(this->glInterface(), X)
      38             : #define GL_CALL_RET(RET, X) GR_GL_CALL_RET(this->glInterface(), RET, X)
      39             : 
      40             : #define SKIP_CACHE_CHECK    true
      41             : 
      42             : #if GR_GL_CHECK_ALLOC_WITH_GET_ERROR
      43             :     #define CLEAR_ERROR_BEFORE_ALLOC(iface)   GrGLClearErr(iface)
      44             :     #define GL_ALLOC_CALL(iface, call)        GR_GL_CALL_NOERRCHECK(iface, call)
      45             :     #define CHECK_ALLOC_ERROR(iface)          GR_GL_GET_ERROR(iface)
      46             : #else
      47             :     #define CLEAR_ERROR_BEFORE_ALLOC(iface)
      48             :     #define GL_ALLOC_CALL(iface, call)        GR_GL_CALL(iface, call)
      49             :     #define CHECK_ALLOC_ERROR(iface)          GR_GL_NO_ERROR
      50             : #endif
      51             : 
      52             : //#define USE_NSIGHT
      53             : 
      54             : ///////////////////////////////////////////////////////////////////////////////
      55             : 
      56             : using gr_instanced::InstancedRendering;
      57             : using gr_instanced::GLInstancedRendering;
      58             : 
      59             : static const GrGLenum gXfermodeEquation2Blend[] = {
      60             :     // Basic OpenGL blend equations.
      61             :     GR_GL_FUNC_ADD,
      62             :     GR_GL_FUNC_SUBTRACT,
      63             :     GR_GL_FUNC_REVERSE_SUBTRACT,
      64             : 
      65             :     // GL_KHR_blend_equation_advanced.
      66             :     GR_GL_SCREEN,
      67             :     GR_GL_OVERLAY,
      68             :     GR_GL_DARKEN,
      69             :     GR_GL_LIGHTEN,
      70             :     GR_GL_COLORDODGE,
      71             :     GR_GL_COLORBURN,
      72             :     GR_GL_HARDLIGHT,
      73             :     GR_GL_SOFTLIGHT,
      74             :     GR_GL_DIFFERENCE,
      75             :     GR_GL_EXCLUSION,
      76             :     GR_GL_MULTIPLY,
      77             :     GR_GL_HSL_HUE,
      78             :     GR_GL_HSL_SATURATION,
      79             :     GR_GL_HSL_COLOR,
      80             :     GR_GL_HSL_LUMINOSITY
      81             : };
      82             : GR_STATIC_ASSERT(0 == kAdd_GrBlendEquation);
      83             : GR_STATIC_ASSERT(1 == kSubtract_GrBlendEquation);
      84             : GR_STATIC_ASSERT(2 == kReverseSubtract_GrBlendEquation);
      85             : GR_STATIC_ASSERT(3 == kScreen_GrBlendEquation);
      86             : GR_STATIC_ASSERT(4 == kOverlay_GrBlendEquation);
      87             : GR_STATIC_ASSERT(5 == kDarken_GrBlendEquation);
      88             : GR_STATIC_ASSERT(6 == kLighten_GrBlendEquation);
      89             : GR_STATIC_ASSERT(7 == kColorDodge_GrBlendEquation);
      90             : GR_STATIC_ASSERT(8 == kColorBurn_GrBlendEquation);
      91             : GR_STATIC_ASSERT(9 == kHardLight_GrBlendEquation);
      92             : GR_STATIC_ASSERT(10 == kSoftLight_GrBlendEquation);
      93             : GR_STATIC_ASSERT(11 == kDifference_GrBlendEquation);
      94             : GR_STATIC_ASSERT(12 == kExclusion_GrBlendEquation);
      95             : GR_STATIC_ASSERT(13 == kMultiply_GrBlendEquation);
      96             : GR_STATIC_ASSERT(14 == kHSLHue_GrBlendEquation);
      97             : GR_STATIC_ASSERT(15 == kHSLSaturation_GrBlendEquation);
      98             : GR_STATIC_ASSERT(16 == kHSLColor_GrBlendEquation);
      99             : GR_STATIC_ASSERT(17 == kHSLLuminosity_GrBlendEquation);
     100             : GR_STATIC_ASSERT(SK_ARRAY_COUNT(gXfermodeEquation2Blend) == kGrBlendEquationCnt);
     101             : 
     102             : static const GrGLenum gXfermodeCoeff2Blend[] = {
     103             :     GR_GL_ZERO,
     104             :     GR_GL_ONE,
     105             :     GR_GL_SRC_COLOR,
     106             :     GR_GL_ONE_MINUS_SRC_COLOR,
     107             :     GR_GL_DST_COLOR,
     108             :     GR_GL_ONE_MINUS_DST_COLOR,
     109             :     GR_GL_SRC_ALPHA,
     110             :     GR_GL_ONE_MINUS_SRC_ALPHA,
     111             :     GR_GL_DST_ALPHA,
     112             :     GR_GL_ONE_MINUS_DST_ALPHA,
     113             :     GR_GL_CONSTANT_COLOR,
     114             :     GR_GL_ONE_MINUS_CONSTANT_COLOR,
     115             :     GR_GL_CONSTANT_ALPHA,
     116             :     GR_GL_ONE_MINUS_CONSTANT_ALPHA,
     117             : 
     118             :     // extended blend coeffs
     119             :     GR_GL_SRC1_COLOR,
     120             :     GR_GL_ONE_MINUS_SRC1_COLOR,
     121             :     GR_GL_SRC1_ALPHA,
     122             :     GR_GL_ONE_MINUS_SRC1_ALPHA,
     123             : };
     124             : 
     125           0 : bool GrGLGpu::BlendCoeffReferencesConstant(GrBlendCoeff coeff) {
     126             :     static const bool gCoeffReferencesBlendConst[] = {
     127             :         false,
     128             :         false,
     129             :         false,
     130             :         false,
     131             :         false,
     132             :         false,
     133             :         false,
     134             :         false,
     135             :         false,
     136             :         false,
     137             :         true,
     138             :         true,
     139             :         true,
     140             :         true,
     141             : 
     142             :         // extended blend coeffs
     143             :         false,
     144             :         false,
     145             :         false,
     146             :         false,
     147             :     };
     148           0 :     return gCoeffReferencesBlendConst[coeff];
     149             :     GR_STATIC_ASSERT(kGrBlendCoeffCnt == SK_ARRAY_COUNT(gCoeffReferencesBlendConst));
     150             : 
     151             :     GR_STATIC_ASSERT(0 == kZero_GrBlendCoeff);
     152             :     GR_STATIC_ASSERT(1 == kOne_GrBlendCoeff);
     153             :     GR_STATIC_ASSERT(2 == kSC_GrBlendCoeff);
     154             :     GR_STATIC_ASSERT(3 == kISC_GrBlendCoeff);
     155             :     GR_STATIC_ASSERT(4 == kDC_GrBlendCoeff);
     156             :     GR_STATIC_ASSERT(5 == kIDC_GrBlendCoeff);
     157             :     GR_STATIC_ASSERT(6 == kSA_GrBlendCoeff);
     158             :     GR_STATIC_ASSERT(7 == kISA_GrBlendCoeff);
     159             :     GR_STATIC_ASSERT(8 == kDA_GrBlendCoeff);
     160             :     GR_STATIC_ASSERT(9 == kIDA_GrBlendCoeff);
     161             :     GR_STATIC_ASSERT(10 == kConstC_GrBlendCoeff);
     162             :     GR_STATIC_ASSERT(11 == kIConstC_GrBlendCoeff);
     163             :     GR_STATIC_ASSERT(12 == kConstA_GrBlendCoeff);
     164             :     GR_STATIC_ASSERT(13 == kIConstA_GrBlendCoeff);
     165             : 
     166             :     GR_STATIC_ASSERT(14 == kS2C_GrBlendCoeff);
     167             :     GR_STATIC_ASSERT(15 == kIS2C_GrBlendCoeff);
     168             :     GR_STATIC_ASSERT(16 == kS2A_GrBlendCoeff);
     169             :     GR_STATIC_ASSERT(17 == kIS2A_GrBlendCoeff);
     170             : 
     171             :     // assertion for gXfermodeCoeff2Blend have to be in GrGpu scope
     172             :     GR_STATIC_ASSERT(kGrBlendCoeffCnt == SK_ARRAY_COUNT(gXfermodeCoeff2Blend));
     173             : }
     174             : 
     175             : ///////////////////////////////////////////////////////////////////////////////
     176             : 
     177             : 
     178           0 : GrGpu* GrGLGpu::Create(GrBackendContext backendContext, const GrContextOptions& options,
     179             :                        GrContext* context) {
     180             :     sk_sp<const GrGLInterface> glInterface(
     181           0 :         reinterpret_cast<const GrGLInterface*>(backendContext));
     182           0 :     if (!glInterface) {
     183           0 :         glInterface.reset(GrGLDefaultInterface());
     184             :     } else {
     185           0 :         glInterface->ref();
     186             :     }
     187           0 :     if (!glInterface) {
     188           0 :         return nullptr;
     189             :     }
     190           0 :     GrGLContext* glContext = GrGLContext::Create(glInterface.get(), options);
     191           0 :     if (glContext) {
     192           0 :         return new GrGLGpu(glContext, context);
     193             :     }
     194           0 :     return nullptr;
     195             : }
     196             : 
     197             : static bool gPrintStartupSpew;
     198             : 
     199           0 : GrGLGpu::GrGLGpu(GrGLContext* ctx, GrContext* context)
     200             :     : GrGpu(context)
     201             :     , fGLContext(ctx)
     202           0 :     , fProgramCache(new ProgramCache(this))
     203             :     , fHWProgramID(0)
     204             :     , fTempSrcFBOID(0)
     205             :     , fTempDstFBOID(0)
     206             :     , fStencilClearFBOID(0)
     207             :     , fHWMaxUsedBufferTextureUnit(-1)
     208           0 :     , fHWMinSampleShading(0.0) {
     209           0 :     for (size_t i = 0; i < SK_ARRAY_COUNT(fCopyPrograms); ++i) {
     210           0 :         fCopyPrograms[i].fProgram = 0;
     211             :     }
     212           0 :     for (size_t i = 0; i < SK_ARRAY_COUNT(fMipmapPrograms); ++i) {
     213           0 :         fMipmapPrograms[i].fProgram = 0;
     214             :     }
     215           0 :     fWireRectProgram.fProgram = 0;
     216             : 
     217           0 :     SkASSERT(ctx);
     218           0 :     fCaps.reset(SkRef(ctx->caps()));
     219             : 
     220           0 :     fHWBoundTextureUniqueIDs.reset(this->caps()->shaderCaps()->maxCombinedSamplers());
     221           0 :     fHWBoundImageStorages.reset(this->caps()->shaderCaps()->maxCombinedImageStorages());
     222             : 
     223           0 :     fHWBufferState[kVertex_GrBufferType].fGLTarget = GR_GL_ARRAY_BUFFER;
     224           0 :     fHWBufferState[kIndex_GrBufferType].fGLTarget = GR_GL_ELEMENT_ARRAY_BUFFER;
     225           0 :     fHWBufferState[kTexel_GrBufferType].fGLTarget = GR_GL_TEXTURE_BUFFER;
     226           0 :     fHWBufferState[kDrawIndirect_GrBufferType].fGLTarget = GR_GL_DRAW_INDIRECT_BUFFER;
     227           0 :     if (GrGLCaps::kChromium_TransferBufferType == this->glCaps().transferBufferType()) {
     228           0 :         fHWBufferState[kXferCpuToGpu_GrBufferType].fGLTarget =
     229             :             GR_GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM;
     230           0 :         fHWBufferState[kXferGpuToCpu_GrBufferType].fGLTarget =
     231             :             GR_GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM;
     232             :     } else {
     233           0 :         fHWBufferState[kXferCpuToGpu_GrBufferType].fGLTarget = GR_GL_PIXEL_UNPACK_BUFFER;
     234           0 :         fHWBufferState[kXferGpuToCpu_GrBufferType].fGLTarget = GR_GL_PIXEL_PACK_BUFFER;
     235             :     }
     236             :     GR_STATIC_ASSERT(6 == SK_ARRAY_COUNT(fHWBufferState));
     237             : 
     238           0 :     if (this->caps()->shaderCaps()->texelBufferSupport()) {
     239           0 :         fHWBufferTextures.reset(this->caps()->shaderCaps()->maxCombinedSamplers());
     240             :     }
     241             : 
     242           0 :     if (this->glCaps().shaderCaps()->pathRenderingSupport()) {
     243           0 :         fPathRendering.reset(new GrGLPathRendering(this));
     244             :     }
     245             : 
     246           0 :     GrGLClearErr(this->glInterface());
     247           0 :     if (gPrintStartupSpew) {
     248             :         const GrGLubyte* vendor;
     249             :         const GrGLubyte* renderer;
     250             :         const GrGLubyte* version;
     251           0 :         GL_CALL_RET(vendor, GetString(GR_GL_VENDOR));
     252           0 :         GL_CALL_RET(renderer, GetString(GR_GL_RENDERER));
     253           0 :         GL_CALL_RET(version, GetString(GR_GL_VERSION));
     254             :         SkDebugf("------------------------- create GrGLGpu %p --------------\n",
     255           0 :                  this);
     256           0 :         SkDebugf("------ VENDOR %s\n", vendor);
     257           0 :         SkDebugf("------ RENDERER %s\n", renderer);
     258           0 :         SkDebugf("------ VERSION %s\n",  version);
     259           0 :         SkDebugf("------ EXTENSIONS\n");
     260           0 :         this->glContext().extensions().print();
     261           0 :         SkDebugf("\n");
     262           0 :         SkDebugf("%s", this->glCaps().dump().c_str());
     263             :     }
     264           0 : }
     265             : 
     266           0 : GrGLGpu::~GrGLGpu() {
     267             :     // Ensure any GrGpuResource objects get deleted first, since they may require a working GrGLGpu
     268             :     // to release the resources held by the objects themselves.
     269           0 :     fPathRendering.reset();
     270           0 :     fCopyProgramArrayBuffer.reset();
     271           0 :     fMipmapProgramArrayBuffer.reset();
     272           0 :     fWireRectArrayBuffer.reset();
     273             : 
     274           0 :     if (0 != fHWProgramID) {
     275             :         // detach the current program so there is no confusion on OpenGL's part
     276             :         // that we want it to be deleted
     277           0 :         GL_CALL(UseProgram(0));
     278             :     }
     279             : 
     280           0 :     if (0 != fTempSrcFBOID) {
     281           0 :         GL_CALL(DeleteFramebuffers(1, &fTempSrcFBOID));
     282             :     }
     283           0 :     if (0 != fTempDstFBOID) {
     284           0 :         GL_CALL(DeleteFramebuffers(1, &fTempDstFBOID));
     285             :     }
     286           0 :     if (0 != fStencilClearFBOID) {
     287           0 :         GL_CALL(DeleteFramebuffers(1, &fStencilClearFBOID));
     288             :     }
     289             : 
     290           0 :     for (size_t i = 0; i < SK_ARRAY_COUNT(fCopyPrograms); ++i) {
     291           0 :         if (0 != fCopyPrograms[i].fProgram) {
     292           0 :             GL_CALL(DeleteProgram(fCopyPrograms[i].fProgram));
     293             :         }
     294             :     }
     295             : 
     296           0 :     for (size_t i = 0; i < SK_ARRAY_COUNT(fMipmapPrograms); ++i) {
     297           0 :         if (0 != fMipmapPrograms[i].fProgram) {
     298           0 :             GL_CALL(DeleteProgram(fMipmapPrograms[i].fProgram));
     299             :         }
     300             :     }
     301             : 
     302           0 :     if (0 != fWireRectProgram.fProgram) {
     303           0 :         GL_CALL(DeleteProgram(fWireRectProgram.fProgram));
     304             :     }
     305             : 
     306           0 :     delete fProgramCache;
     307           0 : }
     308             : 
     309           0 : void GrGLGpu::disconnect(DisconnectType type) {
     310           0 :     INHERITED::disconnect(type);
     311           0 :     if (DisconnectType::kCleanup == type) {
     312           0 :         if (fHWProgramID) {
     313           0 :             GL_CALL(UseProgram(0));
     314             :         }
     315           0 :         if (fTempSrcFBOID) {
     316           0 :             GL_CALL(DeleteFramebuffers(1, &fTempSrcFBOID));
     317             :         }
     318           0 :         if (fTempDstFBOID) {
     319           0 :             GL_CALL(DeleteFramebuffers(1, &fTempDstFBOID));
     320             :         }
     321           0 :         if (fStencilClearFBOID) {
     322           0 :             GL_CALL(DeleteFramebuffers(1, &fStencilClearFBOID));
     323             :         }
     324           0 :         for (size_t i = 0; i < SK_ARRAY_COUNT(fCopyPrograms); ++i) {
     325           0 :             if (fCopyPrograms[i].fProgram) {
     326           0 :                 GL_CALL(DeleteProgram(fCopyPrograms[i].fProgram));
     327             :             }
     328             :         }
     329           0 :         for (size_t i = 0; i < SK_ARRAY_COUNT(fMipmapPrograms); ++i) {
     330           0 :             if (fMipmapPrograms[i].fProgram) {
     331           0 :                 GL_CALL(DeleteProgram(fMipmapPrograms[i].fProgram));
     332             :             }
     333             :         }
     334           0 :         if (fWireRectProgram.fProgram) {
     335           0 :             GL_CALL(DeleteProgram(fWireRectProgram.fProgram));
     336             :         }
     337             :     } else {
     338           0 :         if (fProgramCache) {
     339           0 :             fProgramCache->abandon();
     340             :         }
     341             :     }
     342             : 
     343           0 :     delete fProgramCache;
     344           0 :     fProgramCache = nullptr;
     345             : 
     346           0 :     fHWProgramID = 0;
     347           0 :     fTempSrcFBOID = 0;
     348           0 :     fTempDstFBOID = 0;
     349           0 :     fStencilClearFBOID = 0;
     350           0 :     fCopyProgramArrayBuffer.reset();
     351           0 :     for (size_t i = 0; i < SK_ARRAY_COUNT(fCopyPrograms); ++i) {
     352           0 :         fCopyPrograms[i].fProgram = 0;
     353             :     }
     354           0 :     fMipmapProgramArrayBuffer.reset();
     355           0 :     for (size_t i = 0; i < SK_ARRAY_COUNT(fMipmapPrograms); ++i) {
     356           0 :         fMipmapPrograms[i].fProgram = 0;
     357             :     }
     358           0 :     fWireRectProgram.fProgram = 0;
     359           0 :     fWireRectArrayBuffer.reset();
     360           0 :     if (this->glCaps().shaderCaps()->pathRenderingSupport()) {
     361           0 :         this->glPathRendering()->disconnect(type);
     362             :     }
     363           0 : }
     364             : 
     365             : ///////////////////////////////////////////////////////////////////////////////
     366             : 
     367           0 : void GrGLGpu::onResetContext(uint32_t resetBits) {
     368             :     // we don't use the zb at all
     369           0 :     if (resetBits & kMisc_GrGLBackendState) {
     370           0 :         GL_CALL(Disable(GR_GL_DEPTH_TEST));
     371           0 :         GL_CALL(DepthMask(GR_GL_FALSE));
     372             : 
     373           0 :         fHWBufferState[kTexel_GrBufferType].invalidate();
     374           0 :         fHWBufferState[kDrawIndirect_GrBufferType].invalidate();
     375           0 :         fHWBufferState[kXferCpuToGpu_GrBufferType].invalidate();
     376           0 :         fHWBufferState[kXferGpuToCpu_GrBufferType].invalidate();
     377             : 
     378           0 :         fHWDrawFace = GrDrawFace::kInvalid;
     379           0 :         if (kGL_GrGLStandard == this->glStandard()) {
     380             : #ifndef USE_NSIGHT
     381             :             // Desktop-only state that we never change
     382           0 :             if (!this->glCaps().isCoreProfile()) {
     383           0 :                 GL_CALL(Disable(GR_GL_POINT_SMOOTH));
     384           0 :                 GL_CALL(Disable(GR_GL_LINE_SMOOTH));
     385           0 :                 GL_CALL(Disable(GR_GL_POLYGON_SMOOTH));
     386           0 :                 GL_CALL(Disable(GR_GL_POLYGON_STIPPLE));
     387           0 :                 GL_CALL(Disable(GR_GL_COLOR_LOGIC_OP));
     388           0 :                 GL_CALL(Disable(GR_GL_INDEX_LOGIC_OP));
     389             :             }
     390             :             // The windows NVIDIA driver has GL_ARB_imaging in the extension string when using a
     391             :             // core profile. This seems like a bug since the core spec removes any mention of
     392             :             // GL_ARB_imaging.
     393           0 :             if (this->glCaps().imagingSupport() && !this->glCaps().isCoreProfile()) {
     394           0 :                 GL_CALL(Disable(GR_GL_COLOR_TABLE));
     395             :             }
     396           0 :             GL_CALL(Disable(GR_GL_POLYGON_OFFSET_FILL));
     397             : 
     398           0 :             GL_CALL(PolygonMode(GR_GL_FRONT_AND_BACK, GR_GL_FILL));
     399             : #endif
     400             :             // Since ES doesn't support glPointSize at all we always use the VS to
     401             :             // set the point size
     402           0 :             GL_CALL(Enable(GR_GL_VERTEX_PROGRAM_POINT_SIZE));
     403             : 
     404             :         }
     405             : 
     406           0 :         if (kGLES_GrGLStandard == this->glStandard() &&
     407           0 :                 this->hasExtension("GL_ARM_shader_framebuffer_fetch")) {
     408             :             // The arm extension requires specifically enabling MSAA fetching per sample.
     409             :             // On some devices this may have a perf hit.  Also multiple render targets are disabled
     410           0 :             GL_CALL(Enable(GR_GL_FETCH_PER_SAMPLE_ARM));
     411             :         }
     412           0 :         fHWWriteToColor = kUnknown_TriState;
     413             :         // we only ever use lines in hairline mode
     414           0 :         GL_CALL(LineWidth(1));
     415           0 :         GL_CALL(Disable(GR_GL_DITHER));
     416             :     }
     417             : 
     418           0 :     if (resetBits & kMSAAEnable_GrGLBackendState) {
     419           0 :         fMSAAEnabled = kUnknown_TriState;
     420             : 
     421           0 :         if (this->caps()->usesMixedSamples()) {
     422           0 :             if (0 != this->caps()->maxRasterSamples()) {
     423           0 :                 fHWRasterMultisampleEnabled = kUnknown_TriState;
     424           0 :                 fHWNumRasterSamples = 0;
     425             :             }
     426             : 
     427             :             // The skia blend modes all use premultiplied alpha and therefore expect RGBA coverage
     428             :             // modulation. This state has no effect when not rendering to a mixed sampled target.
     429           0 :             GL_CALL(CoverageModulation(GR_GL_RGBA));
     430             :         }
     431             :     }
     432             : 
     433           0 :     fHWActiveTextureUnitIdx = -1; // invalid
     434             : 
     435           0 :     if (resetBits & kTextureBinding_GrGLBackendState) {
     436           0 :         for (int s = 0; s < fHWBoundTextureUniqueIDs.count(); ++s) {
     437           0 :             fHWBoundTextureUniqueIDs[s].makeInvalid();
     438             :         }
     439           0 :         for (int b = 0; b < fHWBufferTextures.count(); ++b) {
     440           0 :             SkASSERT(this->caps()->shaderCaps()->texelBufferSupport());
     441           0 :             fHWBufferTextures[b].fKnownBound = false;
     442             :         }
     443           0 :         for (int i = 0; i < fHWBoundImageStorages.count(); ++i) {
     444           0 :             SkASSERT(this->caps()->shaderCaps()->imageLoadStoreSupport());
     445           0 :             fHWBoundImageStorages[i].fTextureUniqueID.makeInvalid();
     446             :         }
     447             :     }
     448             : 
     449           0 :     if (resetBits & kBlend_GrGLBackendState) {
     450           0 :         fHWBlendState.invalidate();
     451             :     }
     452             : 
     453           0 :     if (resetBits & kView_GrGLBackendState) {
     454           0 :         fHWScissorSettings.invalidate();
     455           0 :         fHWWindowRectsState.invalidate();
     456           0 :         fHWViewport.invalidate();
     457             :     }
     458             : 
     459           0 :     if (resetBits & kStencil_GrGLBackendState) {
     460           0 :         fHWStencilSettings.invalidate();
     461           0 :         fHWStencilTestEnabled = kUnknown_TriState;
     462             :     }
     463             : 
     464             :     // Vertex
     465           0 :     if (resetBits & kVertex_GrGLBackendState) {
     466           0 :         fHWVertexArrayState.invalidate();
     467           0 :         fHWBufferState[kVertex_GrBufferType].invalidate();
     468           0 :         fHWBufferState[kIndex_GrBufferType].invalidate();
     469             :     }
     470             : 
     471           0 :     if (resetBits & kRenderTarget_GrGLBackendState) {
     472           0 :         fHWBoundRenderTargetUniqueID.makeInvalid();
     473           0 :         fHWSRGBFramebuffer = kUnknown_TriState;
     474             :     }
     475             : 
     476           0 :     if (resetBits & kPathRendering_GrGLBackendState) {
     477           0 :         if (this->caps()->shaderCaps()->pathRenderingSupport()) {
     478           0 :             this->glPathRendering()->resetContext();
     479             :         }
     480             :     }
     481             : 
     482             :     // we assume these values
     483           0 :     if (resetBits & kPixelStore_GrGLBackendState) {
     484           0 :         if (this->glCaps().unpackRowLengthSupport()) {
     485           0 :             GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, 0));
     486             :         }
     487           0 :         if (this->glCaps().packRowLengthSupport()) {
     488           0 :             GL_CALL(PixelStorei(GR_GL_PACK_ROW_LENGTH, 0));
     489             :         }
     490           0 :         if (this->glCaps().unpackFlipYSupport()) {
     491           0 :             GL_CALL(PixelStorei(GR_GL_UNPACK_FLIP_Y, GR_GL_FALSE));
     492             :         }
     493           0 :         if (this->glCaps().packFlipYSupport()) {
     494           0 :             GL_CALL(PixelStorei(GR_GL_PACK_REVERSE_ROW_ORDER, GR_GL_FALSE));
     495             :         }
     496             :     }
     497             : 
     498           0 :     if (resetBits & kProgram_GrGLBackendState) {
     499           0 :         fHWProgramID = 0;
     500             :     }
     501           0 : }
     502             : 
     503           0 : static GrSurfaceOrigin resolve_origin(GrSurfaceOrigin origin, bool renderTarget) {
     504             :     // By default, GrRenderTargets are GL's normal orientation so that they
     505             :     // can be drawn to by the outside world without the client having
     506             :     // to render upside down.
     507           0 :     if (kDefault_GrSurfaceOrigin == origin) {
     508           0 :         return renderTarget ? kBottomLeft_GrSurfaceOrigin : kTopLeft_GrSurfaceOrigin;
     509             :     } else {
     510           0 :         return origin;
     511             :     }
     512             : }
     513             : 
     514           0 : sk_sp<GrTexture> GrGLGpu::onWrapBackendTexture(const GrBackendTextureDesc& desc,
     515             :                                                GrWrapOwnership ownership) {
     516           0 :     const GrGLTextureInfo* info = reinterpret_cast<const GrGLTextureInfo*>(desc.fTextureHandle);
     517           0 :     if (!info || !info->fID) {
     518           0 :         return nullptr;
     519             :     }
     520             : 
     521             :     // next line relies on GrBackendTextureDesc's flags matching GrTexture's
     522           0 :     bool renderTarget = SkToBool(desc.fFlags & kRenderTarget_GrBackendTextureFlag);
     523           0 :     SkASSERT(!renderTarget || kAdoptAndCache_GrWrapOwnership != ownership);  // Not supported
     524             : 
     525             :     GrGLTexture::IDDesc idDesc;
     526           0 :     idDesc.fInfo = *info;
     527             : 
     528           0 :     if (GR_GL_TEXTURE_EXTERNAL == idDesc.fInfo.fTarget) {
     529           0 :         if (renderTarget) {
     530             :             // This combination is not supported.
     531           0 :             return nullptr;
     532             :         }
     533           0 :         if (!this->caps()->shaderCaps()->externalTextureSupport()) {
     534           0 :             return nullptr;
     535             :         }
     536           0 :     } else  if (GR_GL_TEXTURE_RECTANGLE == idDesc.fInfo.fTarget) {
     537           0 :         if (!this->glCaps().rectangleTextureSupport()) {
     538           0 :             return nullptr;
     539             :         }
     540           0 :     } else if (GR_GL_TEXTURE_2D != idDesc.fInfo.fTarget) {
     541           0 :         return nullptr;
     542             :     }
     543             : 
     544             :     // Sample count is interpreted to mean the number of samples that Gr code should allocate
     545             :     // for a render buffer that resolves to the texture. We don't support MSAA textures.
     546           0 :     if (desc.fSampleCnt && !renderTarget) {
     547           0 :         return nullptr;
     548             :     }
     549             : 
     550           0 :     if (kBorrow_GrWrapOwnership == ownership) {
     551           0 :         idDesc.fOwnership = GrBackendObjectOwnership::kBorrowed;
     552             :     } else {
     553           0 :         idDesc.fOwnership = GrBackendObjectOwnership::kOwned;
     554             :     }
     555             : 
     556           0 :     GrSurfaceDesc surfDesc;
     557           0 :     surfDesc.fFlags = (GrSurfaceFlags) desc.fFlags;
     558           0 :     surfDesc.fWidth = desc.fWidth;
     559           0 :     surfDesc.fHeight = desc.fHeight;
     560           0 :     surfDesc.fConfig = desc.fConfig;
     561           0 :     surfDesc.fSampleCnt = SkTMin(desc.fSampleCnt, this->caps()->maxSampleCount());
     562             :     // FIXME:  this should be calling resolve_origin(), but Chrome code is currently
     563             :     // assuming the old behaviour, which is that backend textures are always
     564             :     // BottomLeft, even for non-RT's.  Once Chrome is fixed, change this to:
     565             :     // glTexDesc.fOrigin = resolve_origin(desc.fOrigin, renderTarget);
     566           0 :     if (kDefault_GrSurfaceOrigin == desc.fOrigin) {
     567           0 :         surfDesc.fOrigin = kBottomLeft_GrSurfaceOrigin;
     568             :     } else {
     569           0 :         surfDesc.fOrigin = desc.fOrigin;
     570             :     }
     571             : 
     572           0 :     if (renderTarget) {
     573             :         GrGLRenderTarget::IDDesc rtIDDesc;
     574           0 :         if (!this->createRenderTargetObjects(surfDesc, idDesc.fInfo, &rtIDDesc)) {
     575           0 :             return nullptr;
     576             :         }
     577           0 :         return GrGLTextureRenderTarget::MakeWrapped(this, surfDesc, idDesc, rtIDDesc);
     578             :     }
     579             : 
     580           0 :     if (kAdoptAndCache_GrWrapOwnership == ownership) {
     581           0 :         return sk_sp<GrTexture>(new GrGLTexture(this, SkBudgeted::kYes, surfDesc, idDesc));
     582             :     } else {
     583           0 :         return GrGLTexture::MakeWrapped(this, surfDesc, idDesc);
     584             :     }
     585             : }
     586             : 
     587           0 : sk_sp<GrRenderTarget> GrGLGpu::onWrapBackendRenderTarget(const GrBackendRenderTargetDesc& wrapDesc){
     588             :     GrGLRenderTarget::IDDesc idDesc;
     589           0 :     idDesc.fRTFBOID = static_cast<GrGLuint>(wrapDesc.fRenderTargetHandle);
     590           0 :     idDesc.fMSColorRenderbufferID = 0;
     591           0 :     idDesc.fTexFBOID = GrGLRenderTarget::kUnresolvableFBOID;
     592           0 :     idDesc.fRTFBOOwnership = GrBackendObjectOwnership::kBorrowed;
     593           0 :     idDesc.fIsMixedSampled = false;
     594             : 
     595           0 :     GrSurfaceDesc desc;
     596           0 :     desc.fConfig = wrapDesc.fConfig;
     597           0 :     desc.fFlags = kCheckAllocation_GrSurfaceFlag | kRenderTarget_GrSurfaceFlag;
     598           0 :     desc.fWidth = wrapDesc.fWidth;
     599           0 :     desc.fHeight = wrapDesc.fHeight;
     600           0 :     desc.fSampleCnt = SkTMin(wrapDesc.fSampleCnt, this->caps()->maxSampleCount());
     601           0 :     desc.fOrigin = resolve_origin(wrapDesc.fOrigin, true);
     602             : 
     603           0 :     return GrGLRenderTarget::MakeWrapped(this, desc, idDesc, wrapDesc.fStencilBits);
     604             : }
     605             : 
     606           0 : sk_sp<GrRenderTarget> GrGLGpu::onWrapBackendTextureAsRenderTarget(const GrBackendTextureDesc& desc){
     607           0 :     const GrGLTextureInfo* info = reinterpret_cast<const GrGLTextureInfo*>(desc.fTextureHandle);
     608           0 :     if (!info || !info->fID) {
     609           0 :         return nullptr;
     610             :     }
     611             : 
     612             :     GrGLTextureInfo texInfo;
     613           0 :     texInfo = *info;
     614             : 
     615           0 :     if (GR_GL_TEXTURE_RECTANGLE != texInfo.fTarget &&
     616           0 :         GR_GL_TEXTURE_2D != texInfo.fTarget) {
     617             :         // Only texture rectangle and texture 2d are supported. We do not check whether texture
     618             :         // rectangle is supported by Skia - if the caller provided us with a texture rectangle,
     619             :         // we assume the necessary support exists.
     620           0 :         return nullptr;
     621             :     }
     622             : 
     623           0 :     GrSurfaceDesc surfDesc;
     624           0 :     surfDesc.fFlags = (GrSurfaceFlags) desc.fFlags;
     625           0 :     surfDesc.fWidth = desc.fWidth;
     626           0 :     surfDesc.fHeight = desc.fHeight;
     627           0 :     surfDesc.fConfig = desc.fConfig;
     628           0 :     surfDesc.fSampleCnt = SkTMin(desc.fSampleCnt, this->caps()->maxSampleCount());
     629             :     // FIXME:  this should be calling resolve_origin(), but Chrome code is currently
     630             :     // assuming the old behaviour, which is that backend textures are always
     631             :     // BottomLeft, even for non-RT's.  Once Chrome is fixed, change this to:
     632             :     // glTexDesc.fOrigin = resolve_origin(desc.fOrigin, renderTarget);
     633           0 :     if (kDefault_GrSurfaceOrigin == desc.fOrigin) {
     634           0 :         surfDesc.fOrigin = kBottomLeft_GrSurfaceOrigin;
     635             :     } else {
     636           0 :         surfDesc.fOrigin = desc.fOrigin;
     637             :     }
     638             : 
     639             :     GrGLRenderTarget::IDDesc rtIDDesc;
     640           0 :     if (!this->createRenderTargetObjects(surfDesc, texInfo, &rtIDDesc)) {
     641           0 :         return nullptr;
     642             :     }
     643           0 :     return GrGLRenderTarget::MakeWrapped(this, surfDesc, rtIDDesc, 0);
     644             : }
     645             : 
     646             : ////////////////////////////////////////////////////////////////////////////////
     647             : 
     648           0 : bool GrGLGpu::onGetWritePixelsInfo(GrSurface* dstSurface, int width, int height,
     649             :                                    GrPixelConfig srcConfig,
     650             :                                    DrawPreference* drawPreference,
     651             :                                    WritePixelTempDrawInfo* tempDrawInfo) {
     652           0 :     if (GrPixelConfigIsCompressed(dstSurface->config())) {
     653           0 :         return false;
     654             :     }
     655             : 
     656             :     // This subclass only allows writes to textures. If the dst is not a texture we have to draw
     657             :     // into it. We could use glDrawPixels on GLs that have it, but we don't today.
     658           0 :     if (!dstSurface->asTexture()) {
     659           0 :         ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
     660             :     } else {
     661           0 :         GrGLTexture* texture = static_cast<GrGLTexture*>(dstSurface->asTexture());
     662           0 :         if (GR_GL_TEXTURE_EXTERNAL == texture->target()) {
     663             :              // We don't currently support writing pixels to EXTERNAL textures.
     664           0 :              return false;
     665             :         }
     666             :     }
     667             : 
     668           0 :     if (GrPixelConfigIsSRGB(dstSurface->config()) != GrPixelConfigIsSRGB(srcConfig)) {
     669           0 :         ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
     670             :     }
     671             : 
     672             :     // Start off assuming no swizzling
     673           0 :     tempDrawInfo->fSwizzle = GrSwizzle::RGBA();
     674           0 :     tempDrawInfo->fWriteConfig = srcConfig;
     675             : 
     676             :     // These settings we will always want if a temp draw is performed. Initially set the config
     677             :     // to srcConfig, though that may be modified if we decide to do a R/G swap.
     678           0 :     tempDrawInfo->fTempSurfaceDesc.fFlags = kNone_GrSurfaceFlags;
     679           0 :     tempDrawInfo->fTempSurfaceDesc.fConfig = srcConfig;
     680           0 :     tempDrawInfo->fTempSurfaceDesc.fWidth = width;
     681           0 :     tempDrawInfo->fTempSurfaceDesc.fHeight = height;
     682           0 :     tempDrawInfo->fTempSurfaceDesc.fSampleCnt = 0;
     683           0 :     tempDrawInfo->fTempSurfaceDesc.fOrigin = kTopLeft_GrSurfaceOrigin; // no CPU y-flip for TL.
     684             : 
     685           0 :     bool configsAreRBSwaps = GrPixelConfigSwapRAndB(srcConfig) == dstSurface->config();
     686             : 
     687           0 :     if (configsAreRBSwaps) {
     688           0 :         if (!this->caps()->isConfigTexturable(srcConfig)) {
     689           0 :             ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
     690           0 :             tempDrawInfo->fTempSurfaceDesc.fConfig = dstSurface->config();
     691           0 :             tempDrawInfo->fSwizzle = GrSwizzle::BGRA();
     692           0 :             tempDrawInfo->fWriteConfig = dstSurface->config();
     693           0 :         } else if (this->glCaps().rgba8888PixelsOpsAreSlow() &&
     694             :                    kRGBA_8888_GrPixelConfig == srcConfig) {
     695           0 :             ElevateDrawPreference(drawPreference, kGpuPrefersDraw_DrawPreference);
     696           0 :             tempDrawInfo->fTempSurfaceDesc.fConfig = dstSurface->config();
     697           0 :             tempDrawInfo->fSwizzle = GrSwizzle::BGRA();
     698           0 :             tempDrawInfo->fWriteConfig = dstSurface->config();
     699           0 :         } else if (kGLES_GrGLStandard == this->glStandard() &&
     700           0 :                    this->glCaps().bgraIsInternalFormat()) {
     701             :             // The internal format and external formats must match texture uploads so we can't
     702             :             // swizzle while uploading when BGRA is a distinct internal format.
     703           0 :             ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
     704           0 :             tempDrawInfo->fTempSurfaceDesc.fConfig = dstSurface->config();
     705           0 :             tempDrawInfo->fSwizzle = GrSwizzle::BGRA();
     706           0 :             tempDrawInfo->fWriteConfig = dstSurface->config();
     707             :         }
     708             :     }
     709             : 
     710           0 :     if (!this->glCaps().unpackFlipYSupport() &&
     711           0 :         kBottomLeft_GrSurfaceOrigin == dstSurface->origin()) {
     712           0 :         ElevateDrawPreference(drawPreference, kGpuPrefersDraw_DrawPreference);
     713             :     }
     714             : 
     715           0 :     return true;
     716             : }
     717             : 
     718           0 : static bool check_write_and_transfer_input(GrGLTexture* glTex, GrSurface* surface,
     719             :                                             GrPixelConfig config) {
     720           0 :     if (!glTex) {
     721           0 :         return false;
     722             :     }
     723             : 
     724             :     // OpenGL doesn't do sRGB <-> linear conversions when reading and writing pixels.
     725           0 :     if (GrPixelConfigIsSRGB(surface->config()) != GrPixelConfigIsSRGB(config)) {
     726           0 :         return false;
     727             :     }
     728             : 
     729             :     // Write or transfer of pixels is not implemented for TEXTURE_EXTERNAL textures
     730           0 :     if (GR_GL_TEXTURE_EXTERNAL == glTex->target()) {
     731           0 :         return false;
     732             :     }
     733             : 
     734           0 :     return true;
     735             : }
     736             : 
     737           0 : bool GrGLGpu::onWritePixels(GrSurface* surface,
     738             :                             int left, int top, int width, int height,
     739             :                             GrPixelConfig config,
     740             :                             const SkTArray<GrMipLevel>& texels) {
     741           0 :     GrGLTexture* glTex = static_cast<GrGLTexture*>(surface->asTexture());
     742             : 
     743           0 :     if (!check_write_and_transfer_input(glTex, surface, config)) {
     744           0 :         return false;
     745             :     }
     746             : 
     747           0 :     this->setScratchTextureUnit();
     748           0 :     GL_CALL(BindTexture(glTex->target(), glTex->textureID()));
     749             : 
     750           0 :     bool success = false;
     751           0 :     if (GrPixelConfigIsCompressed(glTex->desc().fConfig)) {
     752             :         // We check that config == desc.fConfig in GrGLGpu::canWriteTexturePixels()
     753           0 :         SkASSERT(config == glTex->desc().fConfig);
     754           0 :         success = this->uploadCompressedTexData(glTex->desc(), glTex->target(), texels,
     755           0 :                                                 kWrite_UploadType, left, top, width, height);
     756             :     } else {
     757           0 :         success = this->uploadTexData(glTex->desc(), glTex->target(), kWrite_UploadType,
     758           0 :                                       left, top, width, height, config, texels);
     759             :     }
     760             : 
     761           0 :     return success;
     762             : }
     763             : 
     764           0 : bool GrGLGpu::onTransferPixels(GrSurface* surface,
     765             :                                int left, int top, int width, int height,
     766             :                                GrPixelConfig config, GrBuffer* transferBuffer,
     767             :                                size_t offset, size_t rowBytes) {
     768           0 :     GrGLTexture* glTex = static_cast<GrGLTexture*>(surface->asTexture());
     769             : 
     770           0 :     if (!check_write_and_transfer_input(glTex, surface, config)) {
     771           0 :         return false;
     772             :     }
     773             : 
     774             :     // For the moment, can't transfer compressed data
     775           0 :     if (GrPixelConfigIsCompressed(glTex->desc().fConfig)) {
     776           0 :         return false;
     777             :     }
     778             : 
     779           0 :     this->setScratchTextureUnit();
     780           0 :     GL_CALL(BindTexture(glTex->target(), glTex->textureID()));
     781             : 
     782           0 :     SkASSERT(!transferBuffer->isMapped());
     783           0 :     SkASSERT(!transferBuffer->isCPUBacked());
     784           0 :     const GrGLBuffer* glBuffer = static_cast<const GrGLBuffer*>(transferBuffer);
     785           0 :     this->bindBuffer(kXferCpuToGpu_GrBufferType, glBuffer);
     786             : 
     787           0 :     bool success = false;
     788             :     GrMipLevel mipLevel;
     789           0 :     mipLevel.fPixels = transferBuffer;
     790           0 :     mipLevel.fRowBytes = rowBytes;
     791           0 :     SkSTArray<1, GrMipLevel> texels;
     792           0 :     texels.push_back(mipLevel);
     793           0 :     success = this->uploadTexData(glTex->desc(), glTex->target(), kTransfer_UploadType,
     794           0 :                                   left, top, width, height, config, texels);
     795           0 :     return success;
     796             : }
     797             : 
     798             : // For GL_[UN]PACK_ALIGNMENT.
     799           0 : static inline GrGLint config_alignment(GrPixelConfig config) {
     800           0 :     SkASSERT(!GrPixelConfigIsCompressed(config));
     801           0 :     switch (config) {
     802             :         case kAlpha_8_GrPixelConfig:
     803             :         case kGray_8_GrPixelConfig:
     804           0 :             return 1;
     805             :         case kRGB_565_GrPixelConfig:
     806             :         case kRGBA_4444_GrPixelConfig:
     807             :         case kAlpha_half_GrPixelConfig:
     808             :         case kRGBA_half_GrPixelConfig:
     809           0 :             return 2;
     810             :         case kRGBA_8888_GrPixelConfig:
     811             :         case kBGRA_8888_GrPixelConfig:
     812             :         case kSRGBA_8888_GrPixelConfig:
     813             :         case kSBGRA_8888_GrPixelConfig:
     814             :         case kRGBA_8888_sint_GrPixelConfig:
     815             :         case kRGBA_float_GrPixelConfig:
     816             :         case kRG_float_GrPixelConfig:
     817           0 :             return 4;
     818             :         case kUnknown_GrPixelConfig:
     819             :         case kETC1_GrPixelConfig:
     820           0 :             return 0;
     821             :     }
     822           0 :     SkFAIL("Invalid pixel config");
     823           0 :     return 0;
     824             : }
     825             : 
     826           0 : static inline GrGLenum check_alloc_error(const GrSurfaceDesc& desc,
     827             :                                          const GrGLInterface* interface) {
     828           0 :     if (SkToBool(desc.fFlags & kCheckAllocation_GrSurfaceFlag)) {
     829           0 :         return GR_GL_GET_ERROR(interface);
     830             :     } else {
     831           0 :         return CHECK_ALLOC_ERROR(interface);
     832             :     }
     833             : }
     834             : 
     835             : /**
     836             :  * Creates storage space for the texture and fills it with texels.
     837             :  *
     838             :  * @param desc           The surface descriptor for the texture being created.
     839             :  * @param interface      The GL interface in use.
     840             :  * @param caps           The capabilities of the GL device.
     841             :  * @param internalFormat The data format used for the internal storage of the texture. May be sized.
     842             :  * @param internalFormatForTexStorage The data format used for the TexStorage API. Must be sized.
     843             :  * @param externalFormat The data format used for the external storage of the texture.
     844             :  * @param externalType   The type of the data used for the external storage of the texture.
     845             :  * @param texels         The texel data of the texture being created.
     846             :  * @param baseWidth      The width of the texture's base mipmap level
     847             :  * @param baseHeight     The height of the texture's base mipmap level
     848             :  * @param succeeded      Set to true if allocating and populating the texture completed
     849             :  *                       without error.
     850             :  */
     851           0 : static bool allocate_and_populate_uncompressed_texture(const GrSurfaceDesc& desc,
     852             :                                                        const GrGLInterface& interface,
     853             :                                                        const GrGLCaps& caps,
     854             :                                                        GrGLenum target,
     855             :                                                        GrGLenum internalFormat,
     856             :                                                        GrGLenum internalFormatForTexStorage,
     857             :                                                        GrGLenum externalFormat,
     858             :                                                        GrGLenum externalType,
     859             :                                                        const SkTArray<GrMipLevel>& texels,
     860             :                                                        int baseWidth, int baseHeight) {
     861           0 :     CLEAR_ERROR_BEFORE_ALLOC(&interface);
     862             : 
     863           0 :     bool useTexStorage = caps.isConfigTexSupportEnabled(desc.fConfig);
     864             :     // We can only use TexStorage if we know we will not later change the storage requirements.
     865             :     // This means if we may later want to add mipmaps, we cannot use TexStorage.
     866             :     // Right now, we cannot know if we will later add mipmaps or not.
     867             :     // The only time we can use TexStorage is when we already have the
     868             :     // mipmaps or are using a format incompatible with MIP maps.
     869           0 :     useTexStorage &= texels.count() > 1 || GrPixelConfigIsSint(desc.fConfig);
     870             : 
     871           0 :     if (useTexStorage) {
     872             :         // We never resize or change formats of textures.
     873           0 :         GL_ALLOC_CALL(&interface,
     874             :                       TexStorage2D(target,
     875             :                                    SkTMax(texels.count(), 1),
     876             :                                    internalFormatForTexStorage,
     877             :                                    desc.fWidth, desc.fHeight));
     878           0 :         GrGLenum error = check_alloc_error(desc, &interface);
     879           0 :         if (error != GR_GL_NO_ERROR) {
     880           0 :             return  false;
     881             :         } else {
     882           0 :             for (int currentMipLevel = 0; currentMipLevel < texels.count(); currentMipLevel++) {
     883           0 :                 const void* currentMipData = texels[currentMipLevel].fPixels;
     884           0 :                 if (currentMipData == nullptr) {
     885           0 :                     continue;
     886             :                 }
     887           0 :                 int twoToTheMipLevel = 1 << currentMipLevel;
     888           0 :                 int currentWidth = SkTMax(1, desc.fWidth / twoToTheMipLevel);
     889           0 :                 int currentHeight = SkTMax(1, desc.fHeight / twoToTheMipLevel);
     890             : 
     891           0 :                 GR_GL_CALL(&interface,
     892             :                            TexSubImage2D(target,
     893             :                                          currentMipLevel,
     894             :                                          0, // left
     895             :                                          0, // top
     896             :                                          currentWidth,
     897             :                                          currentHeight,
     898             :                                          externalFormat, externalType,
     899             :                                          currentMipData));
     900             :             }
     901           0 :             return true;
     902             :         }
     903             :     } else {
     904           0 :         if (texels.empty()) {
     905           0 :             GL_ALLOC_CALL(&interface,
     906             :                           TexImage2D(target,
     907             :                                      0,
     908             :                                      internalFormat,
     909             :                                      baseWidth,
     910             :                                      baseHeight,
     911             :                                      0, // border
     912             :                                      externalFormat, externalType,
     913             :                                      nullptr));
     914           0 :             GrGLenum error = check_alloc_error(desc, &interface);
     915           0 :             if (error != GR_GL_NO_ERROR) {
     916           0 :                 return false;
     917             :             }
     918             :         } else {
     919           0 :             for (int currentMipLevel = 0; currentMipLevel < texels.count(); currentMipLevel++) {
     920           0 :                 int twoToTheMipLevel = 1 << currentMipLevel;
     921           0 :                 int currentWidth = SkTMax(1, baseWidth / twoToTheMipLevel);
     922           0 :                 int currentHeight = SkTMax(1, baseHeight / twoToTheMipLevel);
     923           0 :                 const void* currentMipData = texels[currentMipLevel].fPixels;
     924             :                 // Even if curremtMipData is nullptr, continue to call TexImage2D.
     925             :                 // This will allocate texture memory which we can later populate.
     926           0 :                 GL_ALLOC_CALL(&interface,
     927             :                               TexImage2D(target,
     928             :                                          currentMipLevel,
     929             :                                          internalFormat,
     930             :                                          currentWidth,
     931             :                                          currentHeight,
     932             :                                          0, // border
     933             :                                          externalFormat, externalType,
     934             :                                          currentMipData));
     935           0 :                 GrGLenum error = check_alloc_error(desc, &interface);
     936           0 :                 if (error != GR_GL_NO_ERROR) {
     937           0 :                     return false;
     938             :                 }
     939             :             }
     940             :         }
     941             :     }
     942           0 :     return true;
     943             : }
     944             : 
     945             : /**
     946             :  * Creates storage space for the texture and fills it with texels.
     947             :  *
     948             :  * @param desc           The surface descriptor for the texture being created.
     949             :  * @param interface      The GL interface in use.
     950             :  * @param caps           The capabilities of the GL device.
     951             :  * @param internalFormat The data format used for the internal storage of the texture.
     952             :  * @param texels         The texel data of the texture being created.
     953             :  */
     954           0 : static bool allocate_and_populate_compressed_texture(const GrSurfaceDesc& desc,
     955             :                                                      const GrGLInterface& interface,
     956             :                                                      const GrGLCaps& caps,
     957             :                                                      GrGLenum target, GrGLenum internalFormat,
     958             :                                                      const SkTArray<GrMipLevel>& texels,
     959             :                                                      int baseWidth, int baseHeight) {
     960           0 :     CLEAR_ERROR_BEFORE_ALLOC(&interface);
     961             : 
     962           0 :     bool useTexStorage = caps.isConfigTexSupportEnabled(desc.fConfig);
     963             :     // We can only use TexStorage if we know we will not later change the storage requirements.
     964             :     // This means if we may later want to add mipmaps, we cannot use TexStorage.
     965             :     // Right now, we cannot know if we will later add mipmaps or not.
     966             :     // The only time we can use TexStorage is when we already have the
     967             :     // mipmaps.
     968           0 :     useTexStorage &= texels.count() > 1;
     969             : 
     970           0 :     if (useTexStorage) {
     971             :         // We never resize or change formats of textures.
     972           0 :         GL_ALLOC_CALL(&interface,
     973             :                       TexStorage2D(target,
     974             :                                    texels.count(),
     975             :                                    internalFormat,
     976             :                                    baseWidth, baseHeight));
     977           0 :         GrGLenum error = check_alloc_error(desc, &interface);
     978           0 :         if (error != GR_GL_NO_ERROR) {
     979           0 :             return false;
     980             :         } else {
     981           0 :             for (int currentMipLevel = 0; currentMipLevel < texels.count(); currentMipLevel++) {
     982           0 :                 const void* currentMipData = texels[currentMipLevel].fPixels;
     983           0 :                 if (currentMipData == nullptr) {
     984           0 :                     continue;
     985             :                 }
     986             : 
     987           0 :                 int twoToTheMipLevel = 1 << currentMipLevel;
     988           0 :                 int currentWidth = SkTMax(1, baseWidth / twoToTheMipLevel);
     989           0 :                 int currentHeight = SkTMax(1, baseHeight / twoToTheMipLevel);
     990             : 
     991             :                 // Make sure that the width and height that we pass to OpenGL
     992             :                 // is a multiple of the block size.
     993           0 :                 size_t dataSize = GrCompressedFormatDataSize(desc.fConfig, currentWidth,
     994           0 :                                                              currentHeight);
     995           0 :                 GR_GL_CALL(&interface, CompressedTexSubImage2D(target,
     996             :                                                                currentMipLevel,
     997             :                                                                0, // left
     998             :                                                                0, // top
     999             :                                                                currentWidth,
    1000             :                                                                currentHeight,
    1001             :                                                                internalFormat,
    1002             :                                                                SkToInt(dataSize),
    1003             :                                                                currentMipData));
    1004             :             }
    1005             :         }
    1006             :     } else {
    1007           0 :         for (int currentMipLevel = 0; currentMipLevel < texels.count(); currentMipLevel++) {
    1008           0 :             int twoToTheMipLevel = 1 << currentMipLevel;
    1009           0 :             int currentWidth = SkTMax(1, baseWidth / twoToTheMipLevel);
    1010           0 :             int currentHeight = SkTMax(1, baseHeight / twoToTheMipLevel);
    1011             : 
    1012             :             // Make sure that the width and height that we pass to OpenGL
    1013             :             // is a multiple of the block size.
    1014           0 :             size_t dataSize = GrCompressedFormatDataSize(desc.fConfig, baseWidth, baseHeight);
    1015             : 
    1016           0 :             GL_ALLOC_CALL(&interface,
    1017             :                           CompressedTexImage2D(target,
    1018             :                                                currentMipLevel,
    1019             :                                                internalFormat,
    1020             :                                                currentWidth,
    1021             :                                                currentHeight,
    1022             :                                                0, // border
    1023             :                                                SkToInt(dataSize),
    1024             :                                                texels[currentMipLevel].fPixels));
    1025             : 
    1026           0 :             GrGLenum error = check_alloc_error(desc, &interface);
    1027           0 :             if (error != GR_GL_NO_ERROR) {
    1028           0 :                 return false;
    1029             :             }
    1030             :         }
    1031             :     }
    1032             : 
    1033           0 :     return true;
    1034             : }
    1035             : 
    1036             : /**
    1037             :  * After a texture is created, any state which was altered during its creation
    1038             :  * needs to be restored.
    1039             :  *
    1040             :  * @param interface          The GL interface to use.
    1041             :  * @param caps               The capabilities of the GL device.
    1042             :  * @param restoreGLRowLength Should the row length unpacking be restored?
    1043             :  * @param glFlipY            Did GL flip the texture vertically?
    1044             :  */
    1045           0 : static void restore_pixelstore_state(const GrGLInterface& interface, const GrGLCaps& caps,
    1046             :                                      bool restoreGLRowLength, bool glFlipY) {
    1047           0 :     if (restoreGLRowLength) {
    1048           0 :         SkASSERT(caps.unpackRowLengthSupport());
    1049           0 :         GR_GL_CALL(&interface, PixelStorei(GR_GL_UNPACK_ROW_LENGTH, 0));
    1050             :     }
    1051           0 :     if (glFlipY) {
    1052           0 :         GR_GL_CALL(&interface, PixelStorei(GR_GL_UNPACK_FLIP_Y, GR_GL_FALSE));
    1053             :     }
    1054           0 : }
    1055             : 
    1056           0 : bool GrGLGpu::uploadTexData(const GrSurfaceDesc& desc,
    1057             :                             GrGLenum target,
    1058             :                             UploadType uploadType,
    1059             :                             int left, int top, int width, int height,
    1060             :                             GrPixelConfig dataConfig,
    1061             :                             const SkTArray<GrMipLevel>& texels) {
    1062             :     // If we're uploading compressed data then we should be using uploadCompressedTexData
    1063           0 :     SkASSERT(!GrPixelConfigIsCompressed(dataConfig));
    1064             : 
    1065           0 :     SkASSERT(this->caps()->isConfigTexturable(desc.fConfig));
    1066             : 
    1067             :     // texels is const.
    1068             :     // But we may need to flip the texture vertically to prepare it.
    1069             :     // Rather than flip in place and alter the incoming data,
    1070             :     // we allocate a new buffer to flip into.
    1071             :     // This means we need to make a non-const shallow copy of texels.
    1072           0 :     SkTArray<GrMipLevel> texelsShallowCopy(texels);
    1073             : 
    1074           0 :     for (int currentMipLevel = texelsShallowCopy.count() - 1; currentMipLevel >= 0;
    1075             :          currentMipLevel--) {
    1076           0 :         SkASSERT(texelsShallowCopy[currentMipLevel].fPixels || kTransfer_UploadType == uploadType);
    1077             :     }
    1078             : 
    1079           0 :     const GrGLInterface* interface = this->glInterface();
    1080           0 :     const GrGLCaps& caps = this->glCaps();
    1081             : 
    1082           0 :     size_t bpp = GrBytesPerPixel(dataConfig);
    1083             : 
    1084           0 :     if (width == 0 || height == 0) {
    1085           0 :         return false;
    1086             :     }
    1087             : 
    1088           0 :     for (int currentMipLevel = 0; currentMipLevel < texelsShallowCopy.count(); currentMipLevel++) {
    1089           0 :         int twoToTheMipLevel = 1 << currentMipLevel;
    1090           0 :         int currentWidth = SkTMax(1, width / twoToTheMipLevel);
    1091           0 :         int currentHeight = SkTMax(1, height / twoToTheMipLevel);
    1092             : 
    1093             :         if (currentHeight > SK_MaxS32 ||
    1094             :             currentWidth > SK_MaxS32) {
    1095           0 :             return false;
    1096             :         }
    1097           0 :         if (!GrSurfacePriv::AdjustWritePixelParams(desc.fWidth, desc.fHeight, bpp, &left, &top,
    1098             :                                                &currentWidth,
    1099             :                                                &currentHeight,
    1100           0 :                                                &texelsShallowCopy[currentMipLevel].fPixels,
    1101           0 :                                                &texelsShallowCopy[currentMipLevel].fRowBytes)) {
    1102           0 :             return false;
    1103             :         }
    1104           0 :         if (currentWidth < 0 || currentHeight < 0) {
    1105           0 :             return false;
    1106             :         }
    1107             :     }
    1108             : 
    1109             :     // Internal format comes from the texture desc.
    1110             :     GrGLenum internalFormat;
    1111             :     // External format and type come from the upload data.
    1112             :     GrGLenum externalFormat;
    1113             :     GrGLenum externalType;
    1114           0 :     if (!this->glCaps().getTexImageFormats(desc.fConfig, dataConfig, &internalFormat,
    1115             :                                            &externalFormat, &externalType)) {
    1116           0 :         return false;
    1117             :     }
    1118             :     // TexStorage requires a sized format, and internalFormat may or may not be
    1119           0 :     GrGLenum internalFormatForTexStorage = this->glCaps().configSizedInternalFormat(desc.fConfig);
    1120             : 
    1121             :     /*
    1122             :      *  Check whether to allocate a temporary buffer for flipping y or
    1123             :      *  because our srcData has extra bytes past each row. If so, we need
    1124             :      *  to trim those off here, since GL ES may not let us specify
    1125             :      *  GL_UNPACK_ROW_LENGTH.
    1126             :      */
    1127           0 :     bool restoreGLRowLength = false;
    1128           0 :     bool swFlipY = false;
    1129           0 :     bool glFlipY = false;
    1130             : 
    1131           0 :     if (kBottomLeft_GrSurfaceOrigin == desc.fOrigin && !texelsShallowCopy.empty()) {
    1132           0 :         if (caps.unpackFlipYSupport()) {
    1133           0 :             glFlipY = true;
    1134             :         } else {
    1135           0 :             swFlipY = true;
    1136             :         }
    1137             :     }
    1138             : 
    1139             :     // in case we need a temporary, trimmed copy of the src pixels
    1140           0 :     SkAutoMalloc tempStorage;
    1141             : 
    1142             :     // find the combined size of all the mip levels and the relative offset of
    1143             :     // each into the collective buffer
    1144           0 :     size_t combined_buffer_size = 0;
    1145           0 :     SkTArray<size_t> individual_mip_offsets(texelsShallowCopy.count());
    1146           0 :     for (int currentMipLevel = 0; currentMipLevel < texelsShallowCopy.count(); currentMipLevel++) {
    1147           0 :         int twoToTheMipLevel = 1 << currentMipLevel;
    1148           0 :         int currentWidth = SkTMax(1, width / twoToTheMipLevel);
    1149           0 :         int currentHeight = SkTMax(1, height / twoToTheMipLevel);
    1150           0 :         const size_t trimmedSize = currentWidth * bpp * currentHeight;
    1151           0 :         individual_mip_offsets.push_back(combined_buffer_size);
    1152           0 :         combined_buffer_size += trimmedSize;
    1153             :     }
    1154           0 :     char* buffer = (char*)tempStorage.reset(combined_buffer_size);
    1155             : 
    1156           0 :     for (int currentMipLevel = 0; currentMipLevel < texelsShallowCopy.count(); currentMipLevel++) {
    1157           0 :         int twoToTheMipLevel = 1 << currentMipLevel;
    1158           0 :         int currentWidth = SkTMax(1, width / twoToTheMipLevel);
    1159           0 :         int currentHeight = SkTMax(1, height / twoToTheMipLevel);
    1160           0 :         const size_t trimRowBytes = currentWidth * bpp;
    1161             : 
    1162             :         /*
    1163             :          *  check whether to allocate a temporary buffer for flipping y or
    1164             :          *  because our srcData has extra bytes past each row. If so, we need
    1165             :          *  to trim those off here, since GL ES may not let us specify
    1166             :          *  GL_UNPACK_ROW_LENGTH.
    1167             :          */
    1168           0 :         restoreGLRowLength = false;
    1169             : 
    1170           0 :         const size_t rowBytes = texelsShallowCopy[currentMipLevel].fRowBytes;
    1171             :       
    1172             :         // TODO: This optimization should be enabled with or without mips.
    1173             :         // For use with mips, we must set GR_GL_UNPACK_ROW_LENGTH once per
    1174             :         // mip level, before calling glTexImage2D.
    1175           0 :         const bool usesMips = texelsShallowCopy.count() > 1;
    1176           0 :         if (caps.unpackRowLengthSupport() && !swFlipY && !usesMips) {
    1177             :             // can't use this for flipping, only non-neg values allowed. :(
    1178           0 :             if (rowBytes != trimRowBytes) {
    1179           0 :                 GrGLint rowLength = static_cast<GrGLint>(rowBytes / bpp);
    1180           0 :                 GR_GL_CALL(interface, PixelStorei(GR_GL_UNPACK_ROW_LENGTH, rowLength));
    1181           0 :                 restoreGLRowLength = true;
    1182             :             }
    1183           0 :         } else if (kTransfer_UploadType != uploadType) {
    1184           0 :             if (trimRowBytes != rowBytes || swFlipY) {
    1185             :                 // copy data into our new storage, skipping the trailing bytes
    1186           0 :                 const char* src = (const char*)texelsShallowCopy[currentMipLevel].fPixels;
    1187           0 :                 if (swFlipY && currentHeight >= 1) {
    1188           0 :                     src += (currentHeight - 1) * rowBytes;
    1189             :                 }
    1190           0 :                 char* dst = buffer + individual_mip_offsets[currentMipLevel];
    1191           0 :                 for (int y = 0; y < currentHeight; y++) {
    1192           0 :                     memcpy(dst, src, trimRowBytes);
    1193           0 :                     if (swFlipY) {
    1194           0 :                         src -= rowBytes;
    1195             :                     } else {
    1196           0 :                         src += rowBytes;
    1197             :                     }
    1198           0 :                     dst += trimRowBytes;
    1199             :                 }
    1200             :                 // now point data to our copied version
    1201           0 :                 texelsShallowCopy[currentMipLevel].fPixels = buffer +
    1202           0 :                     individual_mip_offsets[currentMipLevel];
    1203           0 :                 texelsShallowCopy[currentMipLevel].fRowBytes = trimRowBytes;
    1204             :             }
    1205             :         } else {
    1206           0 :             return false;
    1207             :         }
    1208             :     }
    1209             : 
    1210           0 :     if (!texelsShallowCopy.empty()) {
    1211           0 :         if (glFlipY) {
    1212           0 :             GR_GL_CALL(interface, PixelStorei(GR_GL_UNPACK_FLIP_Y, GR_GL_TRUE));
    1213             :         }
    1214           0 :         GR_GL_CALL(interface, PixelStorei(GR_GL_UNPACK_ALIGNMENT,
    1215             :                                           config_alignment(desc.fConfig)));
    1216             :     }
    1217             : 
    1218           0 :     bool succeeded = true;
    1219           0 :     if (kNewTexture_UploadType == uploadType &&
    1220           0 :         0 == left && 0 == top &&
    1221           0 :         desc.fWidth == width && desc.fHeight == height) {
    1222           0 :         succeeded = allocate_and_populate_uncompressed_texture(desc, *interface, caps, target,
    1223             :                                                                internalFormat,
    1224             :                                                                internalFormatForTexStorage,
    1225             :                                                                externalFormat, externalType,
    1226           0 :                                                                texelsShallowCopy, width, height);
    1227             :     } else {
    1228           0 :         if (swFlipY || glFlipY) {
    1229           0 :             top = desc.fHeight - (top + height);
    1230             :         }
    1231           0 :         for (int currentMipLevel = 0; currentMipLevel < texelsShallowCopy.count();
    1232             :              currentMipLevel++) {
    1233           0 :             int twoToTheMipLevel = 1 << currentMipLevel;
    1234           0 :             int currentWidth = SkTMax(1, width / twoToTheMipLevel);
    1235           0 :             int currentHeight = SkTMax(1, height / twoToTheMipLevel);
    1236             : 
    1237           0 :             GL_CALL(TexSubImage2D(target,
    1238             :                                   currentMipLevel,
    1239             :                                   left, top,
    1240             :                                   currentWidth,
    1241             :                                   currentHeight,
    1242             :                                   externalFormat, externalType,
    1243             :                                   texelsShallowCopy[currentMipLevel].fPixels));
    1244             :         }
    1245             :     }
    1246             : 
    1247           0 :     restore_pixelstore_state(*interface, caps, restoreGLRowLength, glFlipY);
    1248             : 
    1249           0 :     return succeeded;
    1250             : }
    1251             : 
    1252             : // TODO: This function is using a lot of wonky semantics like, if width == -1
    1253             : // then set width = desc.fWdith ... blah. A better way to do it might be to
    1254             : // create a CompressedTexData struct that takes a desc/ptr and figures out
    1255             : // the proper upload semantics. Then users can construct this function how they
    1256             : // see fit if they want to go against the "standard" way to do it.
    1257           0 : bool GrGLGpu::uploadCompressedTexData(const GrSurfaceDesc& desc,
    1258             :                                       GrGLenum target,
    1259             :                                       const SkTArray<GrMipLevel>& texels,
    1260             :                                       UploadType uploadType,
    1261             :                                       int left, int top, int width, int height) {
    1262           0 :     SkASSERT(this->caps()->isConfigTexturable(desc.fConfig));
    1263             : 
    1264             :     // No support for software flip y, yet...
    1265           0 :     SkASSERT(kBottomLeft_GrSurfaceOrigin != desc.fOrigin);
    1266             : 
    1267           0 :     const GrGLInterface* interface = this->glInterface();
    1268           0 :     const GrGLCaps& caps = this->glCaps();
    1269             : 
    1270           0 :     if (-1 == width) {
    1271           0 :         width = desc.fWidth;
    1272             :     }
    1273             : #ifdef SK_DEBUG
    1274             :     else {
    1275           0 :         SkASSERT(width <= desc.fWidth);
    1276             :     }
    1277             : #endif
    1278             : 
    1279           0 :     if (-1 == height) {
    1280           0 :         height = desc.fHeight;
    1281             :     }
    1282             : #ifdef SK_DEBUG
    1283             :     else {
    1284           0 :         SkASSERT(height <= desc.fHeight);
    1285             :     }
    1286             : #endif
    1287             : 
    1288             :     // We only need the internal format for compressed 2D textures.
    1289             :     GrGLenum internalFormat;
    1290           0 :     if (!caps.getCompressedTexImageFormats(desc.fConfig, &internalFormat)) {
    1291           0 :         return false;
    1292             :     }
    1293             : 
    1294           0 :     if (kNewTexture_UploadType == uploadType) {
    1295           0 :         return allocate_and_populate_compressed_texture(desc, *interface, caps, target,
    1296           0 :                                                         internalFormat, texels, width, height);
    1297             :     } else {
    1298           0 :         for (int currentMipLevel = 0; currentMipLevel < texels.count(); currentMipLevel++) {
    1299           0 :             SkASSERT(texels[currentMipLevel].fPixels || kTransfer_UploadType == uploadType);
    1300             : 
    1301           0 :             int twoToTheMipLevel = 1 << currentMipLevel;
    1302           0 :             int currentWidth = SkTMax(1, width / twoToTheMipLevel);
    1303           0 :             int currentHeight = SkTMax(1, height / twoToTheMipLevel);
    1304             : 
    1305             :             // Make sure that the width and height that we pass to OpenGL
    1306             :             // is a multiple of the block size.
    1307           0 :             size_t dataSize = GrCompressedFormatDataSize(desc.fConfig, currentWidth,
    1308           0 :                                                          currentHeight);
    1309           0 :             GL_CALL(CompressedTexSubImage2D(target,
    1310             :                                             currentMipLevel,
    1311             :                                             left, top,
    1312             :                                             currentWidth,
    1313             :                                             currentHeight,
    1314             :                                             internalFormat,
    1315             :                                             SkToInt(dataSize),
    1316             :                                             texels[currentMipLevel].fPixels));
    1317             :         }
    1318             :     }
    1319             : 
    1320           0 :     return true;
    1321             : }
    1322             : 
    1323           0 : static bool renderbuffer_storage_msaa(const GrGLContext& ctx,
    1324             :                                       int sampleCount,
    1325             :                                       GrGLenum format,
    1326             :                                       int width, int height) {
    1327           0 :     CLEAR_ERROR_BEFORE_ALLOC(ctx.interface());
    1328           0 :     SkASSERT(GrGLCaps::kNone_MSFBOType != ctx.caps()->msFBOType());
    1329           0 :     switch (ctx.caps()->msFBOType()) {
    1330             :         case GrGLCaps::kEXT_MSFBOType:
    1331             :         case GrGLCaps::kStandard_MSFBOType:
    1332             :         case GrGLCaps::kMixedSamples_MSFBOType:
    1333           0 :             GL_ALLOC_CALL(ctx.interface(),
    1334             :                             RenderbufferStorageMultisample(GR_GL_RENDERBUFFER,
    1335             :                                                             sampleCount,
    1336             :                                                             format,
    1337             :                                                             width, height));
    1338           0 :             break;
    1339             :         case GrGLCaps::kES_Apple_MSFBOType:
    1340           0 :             GL_ALLOC_CALL(ctx.interface(),
    1341             :                             RenderbufferStorageMultisampleES2APPLE(GR_GL_RENDERBUFFER,
    1342             :                                                                     sampleCount,
    1343             :                                                                     format,
    1344             :                                                                     width, height));
    1345           0 :             break;
    1346             :         case GrGLCaps::kES_EXT_MsToTexture_MSFBOType:
    1347             :         case GrGLCaps::kES_IMG_MsToTexture_MSFBOType:
    1348           0 :             GL_ALLOC_CALL(ctx.interface(),
    1349             :                             RenderbufferStorageMultisampleES2EXT(GR_GL_RENDERBUFFER,
    1350             :                                                                 sampleCount,
    1351             :                                                                 format,
    1352             :                                                                 width, height));
    1353           0 :             break;
    1354             :         case GrGLCaps::kNone_MSFBOType:
    1355           0 :             SkFAIL("Shouldn't be here if we don't support multisampled renderbuffers.");
    1356           0 :             break;
    1357             :     }
    1358           0 :     return (GR_GL_NO_ERROR == CHECK_ALLOC_ERROR(ctx.interface()));
    1359             : }
    1360             : 
    1361           0 : bool GrGLGpu::createRenderTargetObjects(const GrSurfaceDesc& desc,
    1362             :                                         const GrGLTextureInfo& texInfo,
    1363             :                                         GrGLRenderTarget::IDDesc* idDesc) {
    1364           0 :     idDesc->fMSColorRenderbufferID = 0;
    1365           0 :     idDesc->fRTFBOID = 0;
    1366           0 :     idDesc->fRTFBOOwnership = GrBackendObjectOwnership::kOwned;
    1367           0 :     idDesc->fTexFBOID = 0;
    1368           0 :     SkASSERT((GrGLCaps::kMixedSamples_MSFBOType == this->glCaps().msFBOType()) ==
    1369             :              this->caps()->usesMixedSamples());
    1370           0 :     idDesc->fIsMixedSampled = desc.fSampleCnt > 0 && this->caps()->usesMixedSamples();
    1371             : 
    1372             :     GrGLenum status;
    1373             : 
    1374           0 :     GrGLenum colorRenderbufferFormat = 0; // suppress warning
    1375             : 
    1376           0 :     if (desc.fSampleCnt > 0 && GrGLCaps::kNone_MSFBOType == this->glCaps().msFBOType()) {
    1377           0 :         goto FAILED;
    1378             :     }
    1379             : 
    1380           0 :     GL_CALL(GenFramebuffers(1, &idDesc->fTexFBOID));
    1381           0 :     if (!idDesc->fTexFBOID) {
    1382           0 :         goto FAILED;
    1383             :     }
    1384             : 
    1385             :     // If we are using multisampling we will create two FBOS. We render to one and then resolve to
    1386             :     // the texture bound to the other. The exception is the IMG multisample extension. With this
    1387             :     // extension the texture is multisampled when rendered to and then auto-resolves it when it is
    1388             :     // rendered from.
    1389           0 :     if (desc.fSampleCnt > 0 && this->glCaps().usesMSAARenderBuffers()) {
    1390           0 :         GL_CALL(GenFramebuffers(1, &idDesc->fRTFBOID));
    1391           0 :         GL_CALL(GenRenderbuffers(1, &idDesc->fMSColorRenderbufferID));
    1392           0 :         if (!idDesc->fRTFBOID ||
    1393           0 :             !idDesc->fMSColorRenderbufferID) {
    1394             :             goto FAILED;
    1395             :         }
    1396           0 :         if (!this->glCaps().getRenderbufferFormat(desc.fConfig, &colorRenderbufferFormat)) {
    1397           0 :             return false;
    1398             :         }
    1399             :     } else {
    1400           0 :         idDesc->fRTFBOID = idDesc->fTexFBOID;
    1401             :     }
    1402             : 
    1403             :     // below here we may bind the FBO
    1404           0 :     fHWBoundRenderTargetUniqueID.makeInvalid();
    1405           0 :     if (idDesc->fRTFBOID != idDesc->fTexFBOID) {
    1406           0 :         SkASSERT(desc.fSampleCnt > 0);
    1407           0 :         GL_CALL(BindRenderbuffer(GR_GL_RENDERBUFFER, idDesc->fMSColorRenderbufferID));
    1408           0 :         if (!renderbuffer_storage_msaa(*fGLContext,
    1409           0 :                                        desc.fSampleCnt,
    1410             :                                        colorRenderbufferFormat,
    1411           0 :                                        desc.fWidth, desc.fHeight)) {
    1412           0 :             goto FAILED;
    1413             :         }
    1414           0 :         fStats.incRenderTargetBinds();
    1415           0 :         GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, idDesc->fRTFBOID));
    1416           0 :         GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
    1417             :                                         GR_GL_COLOR_ATTACHMENT0,
    1418             :                                         GR_GL_RENDERBUFFER,
    1419             :                                         idDesc->fMSColorRenderbufferID));
    1420           0 :         if ((desc.fFlags & kCheckAllocation_GrSurfaceFlag) ||
    1421           0 :             !this->glCaps().isConfigVerifiedColorAttachment(desc.fConfig)) {
    1422           0 :             GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
    1423           0 :             if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
    1424           0 :                 goto FAILED;
    1425             :             }
    1426           0 :             fGLContext->caps()->markConfigAsValidColorAttachment(desc.fConfig);
    1427             :         }
    1428             :     }
    1429           0 :     fStats.incRenderTargetBinds();
    1430           0 :     GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, idDesc->fTexFBOID));
    1431             : 
    1432           0 :     if (this->glCaps().usesImplicitMSAAResolve() && desc.fSampleCnt > 0) {
    1433           0 :         GL_CALL(FramebufferTexture2DMultisample(GR_GL_FRAMEBUFFER,
    1434             :                                                 GR_GL_COLOR_ATTACHMENT0,
    1435             :                                                 texInfo.fTarget,
    1436             :                                                 texInfo.fID, 0, desc.fSampleCnt));
    1437             :     } else {
    1438           0 :         GL_CALL(FramebufferTexture2D(GR_GL_FRAMEBUFFER,
    1439             :                                      GR_GL_COLOR_ATTACHMENT0,
    1440             :                                      texInfo.fTarget,
    1441             :                                      texInfo.fID, 0));
    1442             :     }
    1443           0 :     if ((desc.fFlags & kCheckAllocation_GrSurfaceFlag) ||
    1444           0 :         !this->glCaps().isConfigVerifiedColorAttachment(desc.fConfig)) {
    1445           0 :         GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
    1446           0 :         if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
    1447           0 :             goto FAILED;
    1448             :         }
    1449           0 :         fGLContext->caps()->markConfigAsValidColorAttachment(desc.fConfig);
    1450             :     }
    1451             : 
    1452           0 :     return true;
    1453             : 
    1454             : FAILED:
    1455           0 :     if (idDesc->fMSColorRenderbufferID) {
    1456           0 :         GL_CALL(DeleteRenderbuffers(1, &idDesc->fMSColorRenderbufferID));
    1457             :     }
    1458           0 :     if (idDesc->fRTFBOID != idDesc->fTexFBOID) {
    1459           0 :         GL_CALL(DeleteFramebuffers(1, &idDesc->fRTFBOID));
    1460             :     }
    1461           0 :     if (idDesc->fTexFBOID) {
    1462           0 :         GL_CALL(DeleteFramebuffers(1, &idDesc->fTexFBOID));
    1463             :     }
    1464           0 :     return false;
    1465             : }
    1466             : 
    1467             : // good to set a break-point here to know when createTexture fails
    1468           0 : static GrTexture* return_null_texture() {
    1469             : //    SkDEBUGFAIL("null texture");
    1470           0 :     return nullptr;
    1471             : }
    1472             : 
    1473             : #if 0 && defined(SK_DEBUG)
    1474             : static size_t as_size_t(int x) {
    1475             :     return x;
    1476             : }
    1477             : #endif
    1478             : 
    1479           0 : static GrGLTexture::IDDesc generate_gl_texture(const GrGLInterface* interface) {
    1480             :     GrGLTexture::IDDesc idDesc;
    1481           0 :     idDesc.fInfo.fID = 0;
    1482           0 :     GR_GL_CALL(interface, GenTextures(1, &idDesc.fInfo.fID));
    1483           0 :     idDesc.fOwnership = GrBackendObjectOwnership::kOwned;
    1484             :     // When we create the texture, we only
    1485             :     // create GL_TEXTURE_2D at the moment.
    1486             :     // External clients can do something different.
    1487           0 :     idDesc.fInfo.fTarget = GR_GL_TEXTURE_2D;
    1488           0 :     return idDesc;
    1489             : }
    1490             : 
    1491           0 : static void set_initial_texture_params(const GrGLInterface* interface,
    1492             :                                        const GrGLTextureInfo& info,
    1493             :                                        GrGLTexture::TexParams* initialTexParams) {
    1494             :     // Some drivers like to know filter/wrap before seeing glTexImage2D. Some
    1495             :     // drivers have a bug where an FBO won't be complete if it includes a
    1496             :     // texture that is not mipmap complete (considering the filter in use).
    1497             :     // we only set a subset here so invalidate first
    1498           0 :     initialTexParams->invalidate();
    1499           0 :     initialTexParams->fMinFilter = GR_GL_NEAREST;
    1500           0 :     initialTexParams->fMagFilter = GR_GL_NEAREST;
    1501           0 :     initialTexParams->fWrapS = GR_GL_CLAMP_TO_EDGE;
    1502           0 :     initialTexParams->fWrapT = GR_GL_CLAMP_TO_EDGE;
    1503           0 :     GR_GL_CALL(interface, TexParameteri(info.fTarget,
    1504             :                                         GR_GL_TEXTURE_MAG_FILTER,
    1505             :                                         initialTexParams->fMagFilter));
    1506           0 :     GR_GL_CALL(interface, TexParameteri(info.fTarget,
    1507             :                                         GR_GL_TEXTURE_MIN_FILTER,
    1508             :                                         initialTexParams->fMinFilter));
    1509           0 :     GR_GL_CALL(interface, TexParameteri(info.fTarget,
    1510             :                                         GR_GL_TEXTURE_WRAP_S,
    1511             :                                         initialTexParams->fWrapS));
    1512           0 :     GR_GL_CALL(interface, TexParameteri(info.fTarget,
    1513             :                                         GR_GL_TEXTURE_WRAP_T,
    1514             :                                         initialTexParams->fWrapT));
    1515           0 : }
    1516             : 
    1517           0 : GrTexture* GrGLGpu::onCreateTexture(const GrSurfaceDesc& desc,
    1518             :                                     SkBudgeted budgeted,
    1519             :                                     const SkTArray<GrMipLevel>& texels) {
    1520             :     // We fail if the MSAA was requested and is not available.
    1521           0 :     if (GrGLCaps::kNone_MSFBOType == this->glCaps().msFBOType() && desc.fSampleCnt) {
    1522             :         //SkDebugf("MSAA RT requested but not supported on this platform.");
    1523           0 :         return return_null_texture();
    1524             :     }
    1525             : 
    1526           0 :     bool renderTarget = SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag);
    1527             : 
    1528             :     GrGLTexture::IDDesc idDesc;
    1529           0 :     idDesc.fOwnership = GrBackendObjectOwnership::kOwned;
    1530             :     GrGLTexture::TexParams initialTexParams;
    1531           0 :     if (!this->createTextureImpl(desc, &idDesc.fInfo, renderTarget, &initialTexParams, texels)) {
    1532           0 :         return return_null_texture();
    1533             :     }
    1534             : 
    1535           0 :     bool wasMipMapDataProvided = false;
    1536           0 :     if (texels.count() > 1) {
    1537           0 :         wasMipMapDataProvided = true;
    1538             :     }
    1539             : 
    1540             :     GrGLTexture* tex;
    1541           0 :     if (renderTarget) {
    1542             :         // unbind the texture from the texture unit before binding it to the frame buffer
    1543           0 :         GL_CALL(BindTexture(idDesc.fInfo.fTarget, 0));
    1544             :         GrGLRenderTarget::IDDesc rtIDDesc;
    1545             : 
    1546           0 :         if (!this->createRenderTargetObjects(desc, idDesc.fInfo, &rtIDDesc)) {
    1547           0 :             GL_CALL(DeleteTextures(1, &idDesc.fInfo.fID));
    1548           0 :             return return_null_texture();
    1549             :         }
    1550           0 :         tex = new GrGLTextureRenderTarget(this, budgeted, desc, idDesc, rtIDDesc,
    1551           0 :                                           wasMipMapDataProvided);
    1552             :     } else {
    1553           0 :         tex = new GrGLTexture(this, budgeted, desc, idDesc, wasMipMapDataProvided);
    1554             :     }
    1555           0 :     tex->setCachedTexParams(initialTexParams, this->getResetTimestamp());
    1556             : #ifdef TRACE_TEXTURE_CREATION
    1557             :     SkDebugf("--- new texture [%d] size=(%d %d) config=%d\n",
    1558             :              idDesc.fInfo.fID, desc.fWidth, desc.fHeight, desc.fConfig);
    1559             : #endif
    1560           0 :     return tex;
    1561             : }
    1562             : 
    1563           0 : GrTexture* GrGLGpu::onCreateCompressedTexture(const GrSurfaceDesc& desc,
    1564             :                                               SkBudgeted budgeted,
    1565             :                                               const SkTArray<GrMipLevel>& texels) {
    1566             :     // Make sure that we're not flipping Y.
    1567           0 :     if (kBottomLeft_GrSurfaceOrigin == desc.fOrigin) {
    1568           0 :         return return_null_texture();
    1569             :     }
    1570             : 
    1571           0 :     GrGLTexture::IDDesc idDesc = generate_gl_texture(this->glInterface());
    1572           0 :     if (!idDesc.fInfo.fID) {
    1573           0 :         return return_null_texture();
    1574             :     }
    1575             : 
    1576           0 :     this->setScratchTextureUnit();
    1577           0 :     GL_CALL(BindTexture(idDesc.fInfo.fTarget, idDesc.fInfo.fID));
    1578             : 
    1579             :     GrGLTexture::TexParams initialTexParams;
    1580           0 :     set_initial_texture_params(this->glInterface(), idDesc.fInfo, &initialTexParams);
    1581             : 
    1582           0 :     if (!this->uploadCompressedTexData(desc, idDesc.fInfo.fTarget, texels)) {
    1583           0 :         GL_CALL(DeleteTextures(1, &idDesc.fInfo.fID));
    1584           0 :         return return_null_texture();
    1585             :     }
    1586             : 
    1587             :     GrGLTexture* tex;
    1588           0 :     tex = new GrGLTexture(this, budgeted, desc, idDesc);
    1589           0 :     tex->setCachedTexParams(initialTexParams, this->getResetTimestamp());
    1590             : #ifdef TRACE_TEXTURE_CREATION
    1591             :     SkDebugf("--- new compressed texture [%d] size=(%d %d) config=%d\n",
    1592             :              idDesc.fInfo.fID, desc.fWidth, desc.fHeight, desc.fConfig);
    1593             : #endif
    1594           0 :     return tex;
    1595             : }
    1596             : 
    1597             : namespace {
    1598             : 
    1599             : const GrGLuint kUnknownBitCount = GrGLStencilAttachment::kUnknownBitCount;
    1600             : 
    1601           0 : void inline get_stencil_rb_sizes(const GrGLInterface* gl,
    1602             :                                  GrGLStencilAttachment::Format* format) {
    1603             : 
    1604             :     // we shouldn't ever know one size and not the other
    1605           0 :     SkASSERT((kUnknownBitCount == format->fStencilBits) ==
    1606             :              (kUnknownBitCount == format->fTotalBits));
    1607           0 :     if (kUnknownBitCount == format->fStencilBits) {
    1608           0 :         GR_GL_GetRenderbufferParameteriv(gl, GR_GL_RENDERBUFFER,
    1609             :                                          GR_GL_RENDERBUFFER_STENCIL_SIZE,
    1610             :                                          (GrGLint*)&format->fStencilBits);
    1611           0 :         if (format->fPacked) {
    1612           0 :             GR_GL_GetRenderbufferParameteriv(gl, GR_GL_RENDERBUFFER,
    1613             :                                              GR_GL_RENDERBUFFER_DEPTH_SIZE,
    1614             :                                              (GrGLint*)&format->fTotalBits);
    1615           0 :             format->fTotalBits += format->fStencilBits;
    1616             :         } else {
    1617           0 :             format->fTotalBits = format->fStencilBits;
    1618             :         }
    1619             :     }
    1620           0 : }
    1621             : }
    1622             : 
    1623           0 : int GrGLGpu::getCompatibleStencilIndex(GrPixelConfig config) {
    1624             :     static const int kSize = 16;
    1625           0 :     SkASSERT(this->caps()->isConfigRenderable(config, false));
    1626           0 :     if (!this->glCaps().hasStencilFormatBeenDeterminedForConfig(config)) {
    1627             :         // Default to unsupported, set this if we find a stencil format that works.
    1628           0 :         int firstWorkingStencilFormatIndex = -1;
    1629             :         // Create color texture
    1630           0 :         GrGLuint colorID = 0;
    1631           0 :         GL_CALL(GenTextures(1, &colorID));
    1632           0 :         this->setScratchTextureUnit();
    1633           0 :         GL_CALL(BindTexture(GR_GL_TEXTURE_2D, colorID));
    1634           0 :         GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
    1635             :                               GR_GL_TEXTURE_MAG_FILTER,
    1636             :                               GR_GL_NEAREST));
    1637           0 :         GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
    1638             :                               GR_GL_TEXTURE_MIN_FILTER,
    1639             :                               GR_GL_NEAREST));
    1640           0 :         GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
    1641             :                               GR_GL_TEXTURE_WRAP_S,
    1642             :                               GR_GL_CLAMP_TO_EDGE));
    1643           0 :         GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
    1644             :                               GR_GL_TEXTURE_WRAP_T,
    1645             :                               GR_GL_CLAMP_TO_EDGE));
    1646             : 
    1647             :         GrGLenum internalFormat;
    1648             :         GrGLenum externalFormat;
    1649             :         GrGLenum externalType;
    1650           0 :         if (!this->glCaps().getTexImageFormats(config, config, &internalFormat, &externalFormat,
    1651             :                                                &externalType)) {
    1652           0 :             return false;
    1653             :         }
    1654           0 :         CLEAR_ERROR_BEFORE_ALLOC(this->glInterface());
    1655           0 :         GL_ALLOC_CALL(this->glInterface(), TexImage2D(GR_GL_TEXTURE_2D,
    1656             :                                                       0,
    1657             :                                                       internalFormat,
    1658             :                                                       kSize,
    1659             :                                                       kSize,
    1660             :                                                       0,
    1661             :                                                       externalFormat,
    1662             :                                                       externalType,
    1663             :                                                       NULL));
    1664           0 :         if (GR_GL_NO_ERROR != CHECK_ALLOC_ERROR(this->glInterface())) {
    1665           0 :             GL_CALL(DeleteTextures(1, &colorID));
    1666           0 :             return -1;
    1667             :         }
    1668             : 
    1669             :         // unbind the texture from the texture unit before binding it to the frame buffer
    1670           0 :         GL_CALL(BindTexture(GR_GL_TEXTURE_2D, 0));
    1671             : 
    1672             :         // Create Framebuffer
    1673           0 :         GrGLuint fb = 0;
    1674           0 :         GL_CALL(GenFramebuffers(1, &fb));
    1675           0 :         GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, fb));
    1676           0 :         fHWBoundRenderTargetUniqueID.makeInvalid();
    1677           0 :         GL_CALL(FramebufferTexture2D(GR_GL_FRAMEBUFFER,
    1678             :                                      GR_GL_COLOR_ATTACHMENT0,
    1679             :                                      GR_GL_TEXTURE_2D,
    1680             :                                      colorID,
    1681             :                                      0));
    1682           0 :         GrGLuint sbRBID = 0;
    1683           0 :         GL_CALL(GenRenderbuffers(1, &sbRBID));
    1684             : 
    1685             :         // look over formats till I find a compatible one
    1686           0 :         int stencilFmtCnt = this->glCaps().stencilFormats().count();
    1687           0 :         if (sbRBID) {
    1688           0 :             GL_CALL(BindRenderbuffer(GR_GL_RENDERBUFFER, sbRBID));
    1689           0 :             for (int i = 0; i < stencilFmtCnt && sbRBID; ++i) {
    1690           0 :                 const GrGLCaps::StencilFormat& sFmt = this->glCaps().stencilFormats()[i];
    1691           0 :                 CLEAR_ERROR_BEFORE_ALLOC(this->glInterface());
    1692           0 :                 GL_ALLOC_CALL(this->glInterface(), RenderbufferStorage(GR_GL_RENDERBUFFER,
    1693             :                                                                        sFmt.fInternalFormat,
    1694             :                                                                        kSize, kSize));
    1695           0 :                 if (GR_GL_NO_ERROR == CHECK_ALLOC_ERROR(this->glInterface())) {
    1696           0 :                     GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
    1697             :                                                     GR_GL_STENCIL_ATTACHMENT,
    1698             :                                                     GR_GL_RENDERBUFFER, sbRBID));
    1699           0 :                     if (sFmt.fPacked) {
    1700           0 :                         GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
    1701             :                                                         GR_GL_DEPTH_ATTACHMENT,
    1702             :                                                         GR_GL_RENDERBUFFER, sbRBID));
    1703             :                     } else {
    1704           0 :                         GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
    1705             :                                                         GR_GL_DEPTH_ATTACHMENT,
    1706             :                                                         GR_GL_RENDERBUFFER, 0));
    1707             :                     }
    1708             :                     GrGLenum status;
    1709           0 :                     GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
    1710           0 :                     if (status == GR_GL_FRAMEBUFFER_COMPLETE) {
    1711           0 :                         firstWorkingStencilFormatIndex = i;
    1712           0 :                         break;
    1713             :                     }
    1714           0 :                     GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
    1715             :                                                     GR_GL_STENCIL_ATTACHMENT,
    1716             :                                                     GR_GL_RENDERBUFFER, 0));
    1717           0 :                     if (sFmt.fPacked) {
    1718           0 :                         GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
    1719             :                                                         GR_GL_DEPTH_ATTACHMENT,
    1720             :                                                         GR_GL_RENDERBUFFER, 0));
    1721             :                     }
    1722             :                 }
    1723             :             }
    1724           0 :             GL_CALL(DeleteRenderbuffers(1, &sbRBID));
    1725             :         }
    1726           0 :         GL_CALL(DeleteTextures(1, &colorID));
    1727           0 :         GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, 0));
    1728           0 :         GL_CALL(DeleteFramebuffers(1, &fb));
    1729           0 :         fGLContext->caps()->setStencilFormatIndexForConfig(config, firstWorkingStencilFormatIndex);
    1730             :     }
    1731           0 :     return this->glCaps().getStencilFormatIndexForConfig(config);
    1732             : }
    1733             : 
    1734           0 : bool GrGLGpu::createTextureImpl(const GrSurfaceDesc& desc, GrGLTextureInfo* info,
    1735             :                                 bool renderTarget, GrGLTexture::TexParams* initialTexParams,
    1736             :                                 const SkTArray<GrMipLevel>& texels) {
    1737           0 :     info->fID = 0;
    1738           0 :     info->fTarget = GR_GL_TEXTURE_2D;
    1739           0 :     GL_CALL(GenTextures(1, &(info->fID)));
    1740             : 
    1741           0 :     if (!info->fID) {
    1742           0 :         return false;
    1743             :     }
    1744             : 
    1745           0 :     this->setScratchTextureUnit();
    1746           0 :     GL_CALL(BindTexture(info->fTarget, info->fID));
    1747             : 
    1748           0 :     if (renderTarget && this->glCaps().textureUsageSupport()) {
    1749             :         // provides a hint about how this texture will be used
    1750           0 :         GL_CALL(TexParameteri(info->fTarget,
    1751             :                               GR_GL_TEXTURE_USAGE,
    1752             :                               GR_GL_FRAMEBUFFER_ATTACHMENT));
    1753             :     }
    1754             : 
    1755           0 :     if (info) {
    1756           0 :         set_initial_texture_params(this->glInterface(), *info, initialTexParams);
    1757             :     }
    1758           0 :     if (!this->uploadTexData(desc, info->fTarget, kNewTexture_UploadType, 0, 0,
    1759           0 :                              desc.fWidth, desc.fHeight,
    1760           0 :                              desc.fConfig, texels)) {
    1761           0 :         GL_CALL(DeleteTextures(1, &(info->fID)));
    1762           0 :         return false;
    1763             :     }
    1764           0 :     return true;
    1765             : }
    1766             : 
    1767           0 : GrStencilAttachment* GrGLGpu::createStencilAttachmentForRenderTarget(const GrRenderTarget* rt,
    1768             :                                                                      int width,
    1769             :                                                                      int height) {
    1770           0 :     SkASSERT(width >= rt->width());
    1771           0 :     SkASSERT(height >= rt->height());
    1772             : 
    1773           0 :     int samples = rt->numStencilSamples();
    1774           0 :     GrGLStencilAttachment::IDDesc sbDesc;
    1775             : 
    1776           0 :     int sIdx = this->getCompatibleStencilIndex(rt->config());
    1777           0 :     if (sIdx < 0) {
    1778           0 :         return nullptr;
    1779             :     }
    1780             : 
    1781           0 :     if (!sbDesc.fRenderbufferID) {
    1782           0 :         GL_CALL(GenRenderbuffers(1, &sbDesc.fRenderbufferID));
    1783             :     }
    1784           0 :     if (!sbDesc.fRenderbufferID) {
    1785           0 :         return nullptr;
    1786             :     }
    1787           0 :     GL_CALL(BindRenderbuffer(GR_GL_RENDERBUFFER, sbDesc.fRenderbufferID));
    1788           0 :     const GrGLCaps::StencilFormat& sFmt = this->glCaps().stencilFormats()[sIdx];
    1789           0 :     CLEAR_ERROR_BEFORE_ALLOC(this->glInterface());
    1790             :     // we do this "if" so that we don't call the multisample
    1791             :     // version on a GL that doesn't have an MSAA extension.
    1792           0 :     if (samples > 0) {
    1793           0 :         SkAssertResult(renderbuffer_storage_msaa(*fGLContext,
    1794             :                                                  samples,
    1795             :                                                  sFmt.fInternalFormat,
    1796             :                                                  width, height));
    1797             :     } else {
    1798           0 :         GL_ALLOC_CALL(this->glInterface(), RenderbufferStorage(GR_GL_RENDERBUFFER,
    1799             :                                                                sFmt.fInternalFormat,
    1800             :                                                                width, height));
    1801           0 :         SkASSERT(GR_GL_NO_ERROR == check_alloc_error(rt->desc(), this->glInterface()));
    1802             :     }
    1803           0 :     fStats.incStencilAttachmentCreates();
    1804             :     // After sized formats we attempt an unsized format and take
    1805             :     // whatever sizes GL gives us. In that case we query for the size.
    1806           0 :     GrGLStencilAttachment::Format format = sFmt;
    1807           0 :     get_stencil_rb_sizes(this->glInterface(), &format);
    1808             :     GrGLStencilAttachment* stencil = new GrGLStencilAttachment(this,
    1809             :                                                                sbDesc,
    1810             :                                                                width,
    1811             :                                                                height,
    1812             :                                                                samples,
    1813           0 :                                                                format);
    1814           0 :     return stencil;
    1815             : }
    1816             : 
    1817             : ////////////////////////////////////////////////////////////////////////////////
    1818             : 
    1819             : // GL_STREAM_DRAW triggers an optimization in Chromium's GPU process where a client's vertex buffer
    1820             : // objects are implemented as client-side-arrays on tile-deferred architectures.
    1821             : #define DYNAMIC_USAGE_PARAM GR_GL_STREAM_DRAW
    1822             : 
    1823           0 : GrBuffer* GrGLGpu::onCreateBuffer(size_t size, GrBufferType intendedType,
    1824             :                                   GrAccessPattern accessPattern, const void* data) {
    1825           0 :     return GrGLBuffer::Create(this, size, intendedType, accessPattern, data);
    1826             : }
    1827             : 
    1828           0 : InstancedRendering* GrGLGpu::onCreateInstancedRendering() {
    1829           0 :     return new GLInstancedRendering(this);
    1830             : }
    1831             : 
    1832           0 : void GrGLGpu::flushScissor(const GrScissorState& scissorState,
    1833             :                            const GrGLIRect& rtViewport,
    1834             :                            GrSurfaceOrigin rtOrigin) {
    1835           0 :     if (scissorState.enabled()) {
    1836             :         GrGLIRect scissor;
    1837           0 :         scissor.setRelativeTo(rtViewport,
    1838           0 :                               scissorState.rect().fLeft,
    1839           0 :                               scissorState.rect().fTop,
    1840           0 :                               scissorState.rect().width(),
    1841           0 :                               scissorState.rect().height(),
    1842           0 :                               rtOrigin);
    1843             :         // if the scissor fully contains the viewport then we fall through and
    1844             :         // disable the scissor test.
    1845           0 :         if (!scissor.contains(rtViewport)) {
    1846           0 :             if (fHWScissorSettings.fRect != scissor) {
    1847           0 :                 scissor.pushToGLScissor(this->glInterface());
    1848           0 :                 fHWScissorSettings.fRect = scissor;
    1849             :             }
    1850           0 :             if (kYes_TriState != fHWScissorSettings.fEnabled) {
    1851           0 :                 GL_CALL(Enable(GR_GL_SCISSOR_TEST));
    1852           0 :                 fHWScissorSettings.fEnabled = kYes_TriState;
    1853             :             }
    1854           0 :             return;
    1855             :         }
    1856             :     }
    1857             : 
    1858             :     // See fall through note above
    1859           0 :     this->disableScissor();
    1860             : }
    1861             : 
    1862           0 : void GrGLGpu::flushWindowRectangles(const GrWindowRectsState& windowState,
    1863             :                                     const GrGLRenderTarget* rt) {
    1864             : #ifndef USE_NSIGHT
    1865             :     typedef GrWindowRectsState::Mode Mode;
    1866           0 :     SkASSERT(!windowState.enabled() || rt->renderFBOID()); // Window rects can't be used on-screen.
    1867           0 :     SkASSERT(windowState.numWindows() <= this->caps()->maxWindowRectangles());
    1868             : 
    1869           0 :     if (!this->caps()->maxWindowRectangles() ||
    1870           0 :         fHWWindowRectsState.knownEqualTo(rt->origin(), rt->getViewport(), windowState)) {
    1871           0 :         return;
    1872             :     }
    1873             : 
    1874             :     // This is purely a workaround for a spurious warning generated by gcc. Otherwise the above
    1875             :     // assert would be sufficient. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=5912
    1876           0 :     int numWindows = SkTMin(windowState.numWindows(), int(GrWindowRectangles::kMaxWindows));
    1877           0 :     SkASSERT(windowState.numWindows() == numWindows);
    1878             : 
    1879             :     GrGLIRect glwindows[GrWindowRectangles::kMaxWindows];
    1880           0 :     const SkIRect* skwindows = windowState.windows().data();
    1881           0 :     for (int i = 0; i < numWindows; ++i) {
    1882           0 :         glwindows[i].setRelativeTo(rt->getViewport(), skwindows[i], rt->origin());
    1883             :     }
    1884             : 
    1885           0 :     GrGLenum glmode = (Mode::kExclusive == windowState.mode()) ? GR_GL_EXCLUSIVE : GR_GL_INCLUSIVE;
    1886           0 :     GL_CALL(WindowRectangles(glmode, numWindows, glwindows->asInts()));
    1887             : 
    1888           0 :     fHWWindowRectsState.set(rt->origin(), rt->getViewport(), windowState);
    1889             : #endif
    1890             : }
    1891             : 
    1892           0 : void GrGLGpu::disableWindowRectangles() {
    1893             : #ifndef USE_NSIGHT
    1894           0 :     if (!this->caps()->maxWindowRectangles() || fHWWindowRectsState.knownDisabled()) {
    1895           0 :         return;
    1896             :     }
    1897           0 :     GL_CALL(WindowRectangles(GR_GL_EXCLUSIVE, 0, nullptr));
    1898           0 :     fHWWindowRectsState.setDisabled();
    1899             : #endif
    1900             : }
    1901             : 
    1902           0 : void GrGLGpu::flushMinSampleShading(float minSampleShading) {
    1903           0 :     if (fHWMinSampleShading != minSampleShading) {
    1904           0 :         if (minSampleShading > 0.0) {
    1905           0 :             GL_CALL(Enable(GR_GL_SAMPLE_SHADING));
    1906           0 :             GL_CALL(MinSampleShading(minSampleShading));
    1907             :         }
    1908             :         else {
    1909           0 :             GL_CALL(Disable(GR_GL_SAMPLE_SHADING));
    1910             :         }
    1911           0 :         fHWMinSampleShading = minSampleShading;
    1912             :     }
    1913           0 : }
    1914             : 
    1915           0 : bool GrGLGpu::flushGLState(const GrPipeline& pipeline, const GrPrimitiveProcessor& primProc,
    1916             :                            bool willDrawPoints) {
    1917           0 :     sk_sp<GrGLProgram> program(fProgramCache->refProgram(this, pipeline, primProc, willDrawPoints));
    1918           0 :     if (!program) {
    1919           0 :         GrCapsDebugf(this->caps(), "Failed to create program!\n");
    1920           0 :         return false;
    1921             :     }
    1922             : 
    1923           0 :     program->generateMipmaps(primProc, pipeline);
    1924             : 
    1925             :     GrXferProcessor::BlendInfo blendInfo;
    1926           0 :     pipeline.getXferProcessor().getBlendInfo(&blendInfo);
    1927             : 
    1928           0 :     this->flushColorWrite(blendInfo.fWriteColor);
    1929           0 :     this->flushDrawFace(pipeline.getDrawFace());
    1930           0 :     this->flushMinSampleShading(primProc.getSampleShading());
    1931             : 
    1932           0 :     GrGLuint programID = program->programID();
    1933           0 :     if (fHWProgramID != programID) {
    1934           0 :         GL_CALL(UseProgram(programID));
    1935           0 :         fHWProgramID = programID;
    1936             :     }
    1937             : 
    1938           0 :     if (blendInfo.fWriteColor) {
    1939             :         // Swizzle the blend to match what the shader will output.
    1940             :         const GrSwizzle& swizzle = this->caps()->shaderCaps()->configOutputSwizzle(
    1941           0 :             pipeline.getRenderTarget()->config());
    1942           0 :         this->flushBlend(blendInfo, swizzle);
    1943             :     }
    1944             : 
    1945           0 :     program->setData(primProc, pipeline);
    1946             : 
    1947           0 :     GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(pipeline.getRenderTarget());
    1948           0 :     GrStencilSettings stencil;
    1949           0 :     if (pipeline.isStencilEnabled()) {
    1950             :         // TODO: attach stencil and create settings during render target flush.
    1951           0 :         SkASSERT(glRT->renderTargetPriv().getStencilAttachment());
    1952           0 :         stencil.reset(*pipeline.getUserStencil(), pipeline.hasStencilClip(),
    1953           0 :                       glRT->renderTargetPriv().numStencilBits());
    1954             :     }
    1955           0 :     this->flushStencil(stencil);
    1956           0 :     this->flushScissor(pipeline.getScissorState(), glRT->getViewport(), glRT->origin());
    1957           0 :     this->flushWindowRectangles(pipeline.getWindowRectsState(), glRT);
    1958           0 :     this->flushHWAAState(glRT, pipeline.isHWAntialiasState(), !stencil.isDisabled());
    1959             : 
    1960             :     // This must come after textures are flushed because a texture may need
    1961             :     // to be msaa-resolved (which will modify bound FBO state).
    1962           0 :     this->flushRenderTarget(glRT, nullptr, pipeline.getDisableOutputConversionToSRGB());
    1963             : 
    1964           0 :     return true;
    1965             : }
    1966             : 
    1967           0 : void GrGLGpu::setupGeometry(const GrPrimitiveProcessor& primProc,
    1968             :                             const GrNonInstancedMesh& mesh,
    1969             :                             size_t* indexOffsetInBytes) {
    1970           0 :     const GrBuffer* vbuf = mesh.vertexBuffer();
    1971           0 :     SkASSERT(vbuf);
    1972           0 :     SkASSERT(!vbuf->isMapped());
    1973             : 
    1974             :     GrGLAttribArrayState* attribState;
    1975           0 :     if (mesh.isIndexed()) {
    1976           0 :         SkASSERT(indexOffsetInBytes);
    1977             : 
    1978           0 :         *indexOffsetInBytes = 0;
    1979           0 :         const GrBuffer* ibuf = mesh.indexBuffer();
    1980           0 :         SkASSERT(ibuf);
    1981           0 :         SkASSERT(!ibuf->isMapped());
    1982           0 :         *indexOffsetInBytes += ibuf->baseOffset();
    1983           0 :         attribState = fHWVertexArrayState.bindInternalVertexArray(this, ibuf);
    1984             :     } else {
    1985           0 :         attribState = fHWVertexArrayState.bindInternalVertexArray(this);
    1986             :     }
    1987             : 
    1988           0 :     int vaCount = primProc.numAttribs();
    1989           0 :     if (vaCount > 0) {
    1990             : 
    1991           0 :         GrGLsizei stride = static_cast<GrGLsizei>(primProc.getVertexStride());
    1992             : 
    1993           0 :         size_t vertexOffsetInBytes = stride * mesh.startVertex();
    1994             : 
    1995           0 :         vertexOffsetInBytes += vbuf->baseOffset();
    1996             : 
    1997           0 :         uint32_t usedAttribArraysMask = 0;
    1998           0 :         size_t offset = 0;
    1999             : 
    2000           0 :         for (int attribIndex = 0; attribIndex < vaCount; attribIndex++) {
    2001           0 :             const GrGeometryProcessor::Attribute& attrib = primProc.getAttrib(attribIndex);
    2002           0 :             usedAttribArraysMask |= (1 << attribIndex);
    2003           0 :             GrVertexAttribType attribType = attrib.fType;
    2004           0 :             attribState->set(this,
    2005             :                              attribIndex,
    2006             :                              vbuf,
    2007             :                              attribType,
    2008             :                              stride,
    2009           0 :                              reinterpret_cast<GrGLvoid*>(vertexOffsetInBytes + offset));
    2010           0 :             offset += attrib.fOffset;
    2011             :         }
    2012           0 :         attribState->disableUnusedArrays(this, usedAttribArraysMask);
    2013             :     }
    2014           0 : }
    2015             : 
    2016           0 : GrGLenum GrGLGpu::bindBuffer(GrBufferType type, const GrBuffer* buffer) {
    2017           0 :     this->handleDirtyContext();
    2018             : 
    2019             :     // Index buffer state is tied to the vertex array.
    2020           0 :     if (kIndex_GrBufferType == type) {
    2021           0 :         this->bindVertexArray(0);
    2022             :     }
    2023             : 
    2024           0 :     SkASSERT(type >= 0 && type <= kLast_GrBufferType);
    2025           0 :     auto& bufferState = fHWBufferState[type];
    2026             : 
    2027           0 :     if (buffer->uniqueID() != bufferState.fBoundBufferUniqueID) {
    2028           0 :         if (buffer->isCPUBacked()) {
    2029           0 :             if (!bufferState.fBufferZeroKnownBound) {
    2030           0 :                 GL_CALL(BindBuffer(bufferState.fGLTarget, 0));
    2031             :             }
    2032             :         } else {
    2033           0 :             const GrGLBuffer* glBuffer = static_cast<const GrGLBuffer*>(buffer);
    2034           0 :             GL_CALL(BindBuffer(bufferState.fGLTarget, glBuffer->bufferID()));
    2035             :         }
    2036           0 :         bufferState.fBufferZeroKnownBound = buffer->isCPUBacked();
    2037           0 :         bufferState.fBoundBufferUniqueID = buffer->uniqueID();
    2038             :     }
    2039             : 
    2040           0 :     return bufferState.fGLTarget;
    2041             : }
    2042             : 
    2043           0 : void GrGLGpu::notifyBufferReleased(const GrGLBuffer* buffer) {
    2044           0 :     if (buffer->hasAttachedToTexture()) {
    2045             :         // Detach this buffer from any textures to ensure the underlying memory is freed.
    2046           0 :         GrGpuResource::UniqueID uniqueID = buffer->uniqueID();
    2047           0 :         for (int i = fHWMaxUsedBufferTextureUnit; i >= 0; --i) {
    2048           0 :             auto& buffTex = fHWBufferTextures[i];
    2049           0 :             if (uniqueID != buffTex.fAttachedBufferUniqueID) {
    2050           0 :                 continue;
    2051             :             }
    2052           0 :             if (i == fHWMaxUsedBufferTextureUnit) {
    2053           0 :                 --fHWMaxUsedBufferTextureUnit;
    2054             :             }
    2055             : 
    2056           0 :             this->setTextureUnit(i);
    2057           0 :             if (!buffTex.fKnownBound) {
    2058           0 :                 SkASSERT(buffTex.fTextureID);
    2059           0 :                 GL_CALL(BindTexture(GR_GL_TEXTURE_BUFFER, buffTex.fTextureID));
    2060           0 :                 buffTex.fKnownBound = true;
    2061             :             }
    2062           0 :             GL_CALL(TexBuffer(GR_GL_TEXTURE_BUFFER,
    2063             :                               this->glCaps().configSizedInternalFormat(buffTex.fTexelConfig), 0));
    2064             :         }
    2065             :     }
    2066           0 : }
    2067             : 
    2068           0 : void GrGLGpu::disableScissor() {
    2069           0 :     if (kNo_TriState != fHWScissorSettings.fEnabled) {
    2070           0 :         GL_CALL(Disable(GR_GL_SCISSOR_TEST));
    2071           0 :         fHWScissorSettings.fEnabled = kNo_TriState;
    2072           0 :         return;
    2073             :     }
    2074             : }
    2075             : 
    2076           0 : void GrGLGpu::clear(const GrFixedClip& clip, GrColor color, GrRenderTarget* target) {
    2077           0 :     this->handleDirtyContext();
    2078             : 
    2079             :     // parent class should never let us get here with no RT
    2080           0 :     SkASSERT(target);
    2081           0 :     GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(target);
    2082             : 
    2083           0 :     this->flushRenderTarget(glRT, clip.scissorEnabled() ? &clip.scissorRect() : nullptr);
    2084           0 :     this->flushScissor(clip.scissorState(), glRT->getViewport(), glRT->origin());
    2085           0 :     this->flushWindowRectangles(clip.windowRectsState(), glRT);
    2086             : 
    2087             :     GrGLfloat r, g, b, a;
    2088             :     static const GrGLfloat scale255 = 1.f / 255.f;
    2089           0 :     a = GrColorUnpackA(color) * scale255;
    2090           0 :     GrGLfloat scaleRGB = scale255;
    2091           0 :     r = GrColorUnpackR(color) * scaleRGB;
    2092           0 :     g = GrColorUnpackG(color) * scaleRGB;
    2093           0 :     b = GrColorUnpackB(color) * scaleRGB;
    2094             : 
    2095           0 :     GL_CALL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
    2096           0 :     fHWWriteToColor = kYes_TriState;
    2097           0 :     GL_CALL(ClearColor(r, g, b, a));
    2098           0 :     GL_CALL(Clear(GR_GL_COLOR_BUFFER_BIT));
    2099           0 : }
    2100             : 
    2101           0 : void GrGLGpu::clearStencil(GrRenderTarget* target) {
    2102           0 :     if (nullptr == target) {
    2103           0 :         return;
    2104             :     }
    2105           0 :     GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(target);
    2106           0 :     this->flushRenderTarget(glRT, &SkIRect::EmptyIRect());
    2107             : 
    2108           0 :     this->disableScissor();
    2109           0 :     this->disableWindowRectangles();
    2110             : 
    2111           0 :     GL_CALL(StencilMask(0xffffffff));
    2112           0 :     GL_CALL(ClearStencil(0));
    2113           0 :     GL_CALL(Clear(GR_GL_STENCIL_BUFFER_BIT));
    2114           0 :     fHWStencilSettings.invalidate();
    2115             : }
    2116             : 
    2117           0 : void GrGLGpu::clearStencilClip(const GrFixedClip& clip,
    2118             :                                bool insideStencilMask,
    2119             :                                GrRenderTarget* target) {
    2120           0 :     SkASSERT(target);
    2121           0 :     this->handleDirtyContext();
    2122             : 
    2123           0 :     GrStencilAttachment* sb = target->renderTargetPriv().getStencilAttachment();
    2124             :     // this should only be called internally when we know we have a
    2125             :     // stencil buffer.
    2126           0 :     SkASSERT(sb);
    2127           0 :     GrGLint stencilBitCount =  sb->bits();
    2128             : #if 0
    2129             :     SkASSERT(stencilBitCount > 0);
    2130             :     GrGLint clipStencilMask  = (1 << (stencilBitCount - 1));
    2131             : #else
    2132             :     // we could just clear the clip bit but when we go through
    2133             :     // ANGLE a partial stencil mask will cause clears to be
    2134             :     // turned into draws. Our contract on GrOpList says that
    2135             :     // changing the clip between stencil passes may or may not
    2136             :     // zero the client's clip bits. So we just clear the whole thing.
    2137             :     static const GrGLint clipStencilMask  = ~0;
    2138             : #endif
    2139             :     GrGLint value;
    2140           0 :     if (insideStencilMask) {
    2141           0 :         value = (1 << (stencilBitCount - 1));
    2142             :     } else {
    2143           0 :         value = 0;
    2144             :     }
    2145           0 :     GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(target);
    2146           0 :     this->flushRenderTarget(glRT, &SkIRect::EmptyIRect());
    2147             : 
    2148           0 :     this->flushScissor(clip.scissorState(), glRT->getViewport(), glRT->origin());
    2149           0 :     this->flushWindowRectangles(clip.windowRectsState(), glRT);
    2150             : 
    2151           0 :     GL_CALL(StencilMask((uint32_t) clipStencilMask));
    2152           0 :     GL_CALL(ClearStencil(value));
    2153           0 :     GL_CALL(Clear(GR_GL_STENCIL_BUFFER_BIT));
    2154           0 :     fHWStencilSettings.invalidate();
    2155           0 : }
    2156             : 
    2157           0 : static bool read_pixels_pays_for_y_flip(GrSurfaceOrigin origin, const GrGLCaps& caps,
    2158             :                                         int width, int height,  GrPixelConfig config,
    2159             :                                         size_t rowBytes) {
    2160             :     // If the surface is already TopLeft, we don't need to flip.
    2161           0 :     if (kTopLeft_GrSurfaceOrigin == origin) {
    2162           0 :         return false;
    2163             :     }
    2164             : 
    2165             :     // If the read is really small or smaller than the min texture size, don't force a draw.
    2166             :     static const int kMinSize = 32;
    2167           0 :     if (width < kMinSize || height < kMinSize) {
    2168           0 :         return false;
    2169             :     }
    2170             : 
    2171             :     // if GL can do the flip then we'll never pay for it.
    2172           0 :     if (caps.packFlipYSupport()) {
    2173           0 :         return false;
    2174             :     }
    2175             : 
    2176             :     // If we have to do memcpy to handle non-trim rowBytes then we
    2177             :     // get the flip for free. Otherwise it costs.
    2178             :     // Note that we're assuming that 0 rowBytes has already been handled and that the width has been
    2179             :     // clipped.
    2180           0 :     return caps.packRowLengthSupport() || GrBytesPerPixel(config) * width == rowBytes;
    2181             : }
    2182             : 
    2183           0 : bool GrGLGpu::readPixelsSupported(GrRenderTarget* target, GrPixelConfig readConfig) {
    2184             : #ifdef SK_BUILD_FOR_MAC
    2185             :     // Chromium may ask us to read back from locked IOSurfaces. Calling the command buffer's
    2186             :     // glGetIntegerv() with GL_IMPLEMENTATION_COLOR_READ_FORMAT/_TYPE causes the command buffer
    2187             :     // to make a call to check the framebuffer status which can hang the driver. So in Mac Chromium
    2188             :     // we always use a temporary surface to test for read pixels support.
    2189             :     // https://www.crbug.com/662802
    2190             :     if (this->glContext().driver() == kChromium_GrGLDriver) {
    2191             :         return this->readPixelsSupported(target->config(), readConfig);
    2192             :     }
    2193             : #endif
    2194           0 :     auto bindRenderTarget = [this, target]() -> bool {
    2195           0 :         this->flushRenderTarget(static_cast<GrGLRenderTarget*>(target), &SkIRect::EmptyIRect());
    2196           0 :         return true;
    2197           0 :     };
    2198           0 :     auto unbindRenderTarget = []{};
    2199           0 :     auto getIntegerv = [this](GrGLenum query, GrGLint* value) {
    2200           0 :         GR_GL_GetIntegerv(this->glInterface(), query, value);
    2201           0 :     };
    2202           0 :     GrPixelConfig rtConfig = target->config();
    2203           0 :     return this->glCaps().readPixelsSupported(rtConfig, readConfig, getIntegerv, bindRenderTarget,
    2204           0 :                                               unbindRenderTarget);
    2205             : }
    2206             : 
    2207           0 : bool GrGLGpu::readPixelsSupported(GrPixelConfig rtConfig, GrPixelConfig readConfig) {
    2208           0 :     sk_sp<GrTexture> temp;
    2209           0 :     auto bindRenderTarget = [this, rtConfig, &temp]() -> bool {
    2210           0 :         GrTextureDesc desc;
    2211           0 :         desc.fConfig = rtConfig;
    2212           0 :         desc.fWidth = desc.fHeight = 16;
    2213           0 :         if (this->glCaps().isConfigRenderable(rtConfig, false)) {
    2214           0 :             desc.fFlags = kRenderTarget_GrSurfaceFlag;
    2215           0 :             temp.reset(this->createTexture(desc, SkBudgeted::kNo));
    2216           0 :             if (!temp) {
    2217           0 :                 return false;
    2218             :             }
    2219           0 :             GrGLRenderTarget* glrt = static_cast<GrGLRenderTarget*>(temp->asRenderTarget());
    2220           0 :             this->flushRenderTarget(glrt, &SkIRect::EmptyIRect());
    2221           0 :             return true;
    2222           0 :         } else if (this->glCaps().canConfigBeFBOColorAttachment(rtConfig)) {
    2223           0 :             temp.reset(this->createTexture(desc, SkBudgeted::kNo));
    2224           0 :             if (!temp) {
    2225           0 :                 return false;
    2226             :             }
    2227             :             GrGLIRect vp;
    2228           0 :             this->bindSurfaceFBOForPixelOps(temp.get(), GR_GL_FRAMEBUFFER, &vp, kDst_TempFBOTarget);
    2229           0 :             fHWBoundRenderTargetUniqueID.makeInvalid();
    2230           0 :             return true;
    2231             :         }
    2232           0 :         return false;
    2233           0 :     };
    2234           0 :     auto unbindRenderTarget = [this, &temp]() {
    2235           0 :         this->unbindTextureFBOForPixelOps(GR_GL_FRAMEBUFFER, temp.get());
    2236           0 :     };
    2237           0 :     auto getIntegerv = [this](GrGLenum query, GrGLint* value) {
    2238           0 :         GR_GL_GetIntegerv(this->glInterface(), query, value);
    2239           0 :     };
    2240           0 :     return this->glCaps().readPixelsSupported(rtConfig, readConfig, getIntegerv, bindRenderTarget,
    2241           0 :                                               unbindRenderTarget);
    2242             : }
    2243             : 
    2244           0 : bool GrGLGpu::readPixelsSupported(GrSurface* surfaceForConfig, GrPixelConfig readConfig) {
    2245           0 :     if (GrRenderTarget* rt = surfaceForConfig->asRenderTarget()) {
    2246           0 :         return this->readPixelsSupported(rt, readConfig);
    2247             :     } else {
    2248           0 :         GrPixelConfig config = surfaceForConfig->config();
    2249           0 :         return this->readPixelsSupported(config, readConfig);
    2250             :     }
    2251             : }
    2252             : 
    2253           0 : static bool requires_srgb_conversion(GrPixelConfig a, GrPixelConfig b) {
    2254           0 :     if (GrPixelConfigIsSRGB(a)) {
    2255           0 :         return !GrPixelConfigIsSRGB(b) && !GrPixelConfigIsAlphaOnly(b);
    2256           0 :     } else if (GrPixelConfigIsSRGB(b)) {
    2257           0 :         return !GrPixelConfigIsSRGB(a) && !GrPixelConfigIsAlphaOnly(a);
    2258             :     }
    2259           0 :     return false;
    2260             : }
    2261             : 
    2262           0 : bool GrGLGpu::onGetReadPixelsInfo(GrSurface* srcSurface, int width, int height, size_t rowBytes,
    2263             :                                   GrPixelConfig readConfig, DrawPreference* drawPreference,
    2264             :                                   ReadPixelTempDrawInfo* tempDrawInfo) {
    2265           0 :     GrPixelConfig srcConfig = srcSurface->config();
    2266             : 
    2267             :     // These settings we will always want if a temp draw is performed.
    2268           0 :     tempDrawInfo->fTempSurfaceDesc.fFlags = kRenderTarget_GrSurfaceFlag;
    2269           0 :     tempDrawInfo->fTempSurfaceDesc.fWidth = width;
    2270           0 :     tempDrawInfo->fTempSurfaceDesc.fHeight = height;
    2271           0 :     tempDrawInfo->fTempSurfaceDesc.fSampleCnt = 0;
    2272           0 :     tempDrawInfo->fTempSurfaceDesc.fOrigin = kTopLeft_GrSurfaceOrigin; // no CPU y-flip for TL.
    2273           0 :     tempDrawInfo->fTempSurfaceFit = this->glCaps().partialFBOReadIsSlow() ? SkBackingFit::kExact
    2274             :                                                                           : SkBackingFit::kApprox;
    2275             :     // For now assume no swizzling, we may change that below.
    2276           0 :     tempDrawInfo->fSwizzle = GrSwizzle::RGBA();
    2277             : 
    2278             :     // Depends on why we need/want a temp draw. Start off assuming no change, the surface we read
    2279             :     // from will be srcConfig and we will read readConfig pixels from it.
    2280             :     // Not that if we require a draw and return a non-renderable format for the temp surface the
    2281             :     // base class will fail for us.
    2282           0 :     tempDrawInfo->fTempSurfaceDesc.fConfig = srcConfig;
    2283           0 :     tempDrawInfo->fReadConfig = readConfig;
    2284             : 
    2285           0 :     if (requires_srgb_conversion(srcConfig, readConfig)) {
    2286           0 :         if (!this->readPixelsSupported(readConfig, readConfig)) {
    2287           0 :             return false;
    2288             :         }
    2289             :         // Draw to do srgb to linear conversion or vice versa.
    2290           0 :         ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
    2291           0 :         tempDrawInfo->fTempSurfaceDesc.fConfig = readConfig;
    2292           0 :         tempDrawInfo->fReadConfig = readConfig;
    2293           0 :         return true;
    2294             :     }
    2295             : 
    2296           0 :     if (this->glCaps().rgba8888PixelsOpsAreSlow() && kRGBA_8888_GrPixelConfig == readConfig &&
    2297           0 :         this->readPixelsSupported(kBGRA_8888_GrPixelConfig, kBGRA_8888_GrPixelConfig)) {
    2298           0 :         tempDrawInfo->fTempSurfaceDesc.fConfig = kBGRA_8888_GrPixelConfig;
    2299           0 :         tempDrawInfo->fSwizzle = GrSwizzle::BGRA();
    2300           0 :         tempDrawInfo->fReadConfig = kBGRA_8888_GrPixelConfig;
    2301           0 :         ElevateDrawPreference(drawPreference, kGpuPrefersDraw_DrawPreference);
    2302           0 :     } else if (this->glCaps().rgbaToBgraReadbackConversionsAreSlow() &&
    2303           0 :                GrBytesPerPixel(readConfig) == 4 &&
    2304           0 :                GrPixelConfigSwapRAndB(readConfig) == srcConfig &&
    2305           0 :                this->readPixelsSupported(srcSurface, srcConfig)) {
    2306             :         // Mesa 3D takes a slow path on when reading back BGRA from an RGBA surface and vice-versa.
    2307             :         // Better to do a draw with a R/B swap and then read as the original config.
    2308           0 :         tempDrawInfo->fTempSurfaceDesc.fConfig = srcConfig;
    2309           0 :         tempDrawInfo->fSwizzle = GrSwizzle::BGRA();
    2310           0 :         tempDrawInfo->fReadConfig = srcConfig;
    2311           0 :         ElevateDrawPreference(drawPreference, kGpuPrefersDraw_DrawPreference);
    2312           0 :     } else if (!this->readPixelsSupported(srcSurface, readConfig)) {
    2313           0 :         if (readConfig == kBGRA_8888_GrPixelConfig &&
    2314           0 :             this->glCaps().canConfigBeFBOColorAttachment(kRGBA_8888_GrPixelConfig) &&
    2315           0 :             this->readPixelsSupported(kRGBA_8888_GrPixelConfig, kRGBA_8888_GrPixelConfig)) {
    2316             :             // We're trying to read BGRA but it's not supported. If RGBA is renderable and
    2317             :             // we can read it back, then do a swizzling draw to a RGBA and read it back (which
    2318             :             // will effectively be BGRA).
    2319           0 :             tempDrawInfo->fTempSurfaceDesc.fConfig = kRGBA_8888_GrPixelConfig;
    2320           0 :             tempDrawInfo->fSwizzle = GrSwizzle::BGRA();
    2321           0 :             tempDrawInfo->fReadConfig = kRGBA_8888_GrPixelConfig;
    2322           0 :             ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
    2323           0 :         } else if (readConfig == kSBGRA_8888_GrPixelConfig &&
    2324           0 :             this->glCaps().canConfigBeFBOColorAttachment(kSRGBA_8888_GrPixelConfig) &&
    2325           0 :             this->readPixelsSupported(kSRGBA_8888_GrPixelConfig, kSRGBA_8888_GrPixelConfig)) {
    2326             :             // We're trying to read sBGRA but it's not supported. If sRGBA is renderable and
    2327             :             // we can read it back, then do a swizzling draw to a sRGBA and read it back (which
    2328             :             // will effectively be sBGRA).
    2329           0 :             tempDrawInfo->fTempSurfaceDesc.fConfig = kSRGBA_8888_GrPixelConfig;
    2330           0 :             tempDrawInfo->fSwizzle = GrSwizzle::BGRA();
    2331           0 :             tempDrawInfo->fReadConfig = kSRGBA_8888_GrPixelConfig;
    2332           0 :             ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
    2333           0 :         } else if (readConfig == kAlpha_8_GrPixelConfig) {
    2334             :             // onReadPixels implements a fallback for cases where we are want to read kAlpha_8,
    2335             :             // it's unsupported, but 32bit RGBA reads are supported.
    2336             :             // Don't attempt to do any srgb conversions since we only care about alpha.
    2337           0 :             GrPixelConfig cpuTempConfig = kRGBA_8888_GrPixelConfig;
    2338           0 :             if (GrPixelConfigIsSRGB(srcSurface->config())) {
    2339           0 :                 cpuTempConfig = kSRGBA_8888_GrPixelConfig;
    2340             :             }
    2341           0 :             if (!this->readPixelsSupported(srcSurface, cpuTempConfig)) {
    2342             :                 // If we can't read RGBA from the src try to draw to a kRGBA_8888 (or kSRGBA_8888)
    2343             :                 // first and then onReadPixels will read that to a 32bit temporary buffer.
    2344           0 :                 if (this->glCaps().canConfigBeFBOColorAttachment(cpuTempConfig)) {
    2345           0 :                     ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
    2346           0 :                     tempDrawInfo->fTempSurfaceDesc.fConfig = cpuTempConfig;
    2347           0 :                     tempDrawInfo->fReadConfig = kAlpha_8_GrPixelConfig;
    2348             :                 } else {
    2349           0 :                     return false;
    2350             :                 }
    2351             :             } else {
    2352           0 :                 SkASSERT(tempDrawInfo->fTempSurfaceDesc.fConfig == srcConfig);
    2353           0 :                 SkASSERT(tempDrawInfo->fReadConfig == kAlpha_8_GrPixelConfig);
    2354             :             }
    2355           0 :         } else if (this->glCaps().canConfigBeFBOColorAttachment(readConfig) &&
    2356           0 :                    this->readPixelsSupported(readConfig, readConfig)) {
    2357             :             // Do a draw to convert from the src config to the read config.
    2358           0 :             ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
    2359           0 :             tempDrawInfo->fTempSurfaceDesc.fConfig = readConfig;
    2360           0 :             tempDrawInfo->fReadConfig = readConfig;
    2361             :         } else {
    2362           0 :             return false;
    2363             :         }
    2364             :     }
    2365             : 
    2366           0 :     if ((srcSurface->asRenderTarget() || this->glCaps().canConfigBeFBOColorAttachment(srcConfig)) &&
    2367           0 :         read_pixels_pays_for_y_flip(srcSurface->origin(), this->glCaps(), width, height, readConfig,
    2368             :                                     rowBytes)) {
    2369           0 :         ElevateDrawPreference(drawPreference, kGpuPrefersDraw_DrawPreference);
    2370             :     }
    2371             : 
    2372           0 :     return true;
    2373             : }
    2374             : 
    2375           0 : bool GrGLGpu::onReadPixels(GrSurface* surface,
    2376             :                            int left, int top,
    2377             :                            int width, int height,
    2378             :                            GrPixelConfig config,
    2379             :                            void* buffer,
    2380             :                            size_t rowBytes) {
    2381           0 :     SkASSERT(surface);
    2382             : 
    2383           0 :     GrGLRenderTarget* renderTarget = static_cast<GrGLRenderTarget*>(surface->asRenderTarget());
    2384           0 :     if (!renderTarget && !this->glCaps().canConfigBeFBOColorAttachment(surface->config())) {
    2385           0 :         return false;
    2386             :     }
    2387             : 
    2388             :     // OpenGL doesn't do sRGB <-> linear conversions when reading and writing pixels.
    2389           0 :     if (requires_srgb_conversion(surface->config(), config)) {
    2390           0 :         return false;
    2391             :     }
    2392             : 
    2393             :     // We have a special case fallback for reading eight bit alpha. We will read back all four 8
    2394             :     // bit channels as RGBA and then extract A.
    2395           0 :     if (!this->readPixelsSupported(surface, config)) {
    2396             :         // Don't attempt to do any srgb conversions since we only care about alpha.
    2397           0 :         GrPixelConfig tempConfig = kRGBA_8888_GrPixelConfig;
    2398           0 :         if (GrPixelConfigIsSRGB(surface->config())) {
    2399           0 :             tempConfig = kSRGBA_8888_GrPixelConfig;
    2400             :         }
    2401           0 :         if (kAlpha_8_GrPixelConfig == config &&
    2402           0 :             this->readPixelsSupported(surface, tempConfig)) {
    2403           0 :             std::unique_ptr<uint32_t[]> temp(new uint32_t[width * height * 4]);
    2404           0 :             if (this->onReadPixels(surface, left, top, width, height, tempConfig, temp.get(),
    2405           0 :                                    width*4)) {
    2406           0 :                 uint8_t* dst = reinterpret_cast<uint8_t*>(buffer);
    2407           0 :                 for (int j = 0; j < height; ++j) {
    2408           0 :                     for (int i = 0; i < width; ++i) {
    2409           0 :                         dst[j*rowBytes + i] = (0xFF000000U & temp[j*width+i]) >> 24;
    2410             :                     }
    2411             :                 }
    2412           0 :                 return true;
    2413             :             }
    2414             :         }
    2415           0 :         return false;
    2416             :     }
    2417             : 
    2418             :     GrGLenum externalFormat;
    2419             :     GrGLenum externalType;
    2420           0 :     if (!this->glCaps().getReadPixelsFormat(surface->config(), config, &externalFormat,
    2421             :                                             &externalType)) {
    2422           0 :         return false;
    2423             :     }
    2424           0 :     bool flipY = kBottomLeft_GrSurfaceOrigin == surface->origin();
    2425             : 
    2426             :     GrGLIRect glvp;
    2427           0 :     if (renderTarget) {
    2428             :         // resolve the render target if necessary
    2429           0 :         switch (renderTarget->getResolveType()) {
    2430             :             case GrGLRenderTarget::kCantResolve_ResolveType:
    2431           0 :                 return false;
    2432             :             case GrGLRenderTarget::kAutoResolves_ResolveType:
    2433           0 :                 this->flushRenderTarget(renderTarget, &SkIRect::EmptyIRect());
    2434           0 :                 break;
    2435             :             case GrGLRenderTarget::kCanResolve_ResolveType:
    2436           0 :                 this->onResolveRenderTarget(renderTarget);
    2437             :                 // we don't track the state of the READ FBO ID.
    2438           0 :                 fStats.incRenderTargetBinds();
    2439           0 :                 GL_CALL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER, renderTarget->textureFBOID()));
    2440           0 :                 break;
    2441             :             default:
    2442           0 :                 SkFAIL("Unknown resolve type");
    2443             :         }
    2444           0 :         glvp = renderTarget->getViewport();
    2445             :     } else {
    2446             :         // Use a temporary FBO.
    2447           0 :         this->bindSurfaceFBOForPixelOps(surface, GR_GL_FRAMEBUFFER, &glvp, kSrc_TempFBOTarget);
    2448           0 :         fHWBoundRenderTargetUniqueID.makeInvalid();
    2449             :     }
    2450             : 
    2451             :     // the read rect is viewport-relative
    2452             :     GrGLIRect readRect;
    2453           0 :     readRect.setRelativeTo(glvp, left, top, width, height, surface->origin());
    2454             : 
    2455           0 :     size_t bytesPerPixel = GrBytesPerPixel(config);
    2456           0 :     size_t tightRowBytes = bytesPerPixel * width;
    2457             : 
    2458           0 :     size_t readDstRowBytes = tightRowBytes;
    2459           0 :     void* readDst = buffer;
    2460             : 
    2461             :     // determine if GL can read using the passed rowBytes or if we need
    2462             :     // a scratch buffer.
    2463           0 :     SkAutoMalloc scratch;
    2464           0 :     if (rowBytes != tightRowBytes) {
    2465           0 :         if (this->glCaps().packRowLengthSupport() && !(rowBytes % bytesPerPixel)) {
    2466           0 :             GL_CALL(PixelStorei(GR_GL_PACK_ROW_LENGTH,
    2467             :                                 static_cast<GrGLint>(rowBytes / bytesPerPixel)));
    2468           0 :             readDstRowBytes = rowBytes;
    2469             :         } else {
    2470           0 :             scratch.reset(tightRowBytes * height);
    2471           0 :             readDst = scratch.get();
    2472             :         }
    2473             :     }
    2474           0 :     if (flipY && this->glCaps().packFlipYSupport()) {
    2475           0 :         GL_CALL(PixelStorei(GR_GL_PACK_REVERSE_ROW_ORDER, 1));
    2476             :     }
    2477           0 :     GL_CALL(PixelStorei(GR_GL_PACK_ALIGNMENT, config_alignment(config)));
    2478             : 
    2479           0 :     GL_CALL(ReadPixels(readRect.fLeft, readRect.fBottom,
    2480             :                        readRect.fWidth, readRect.fHeight,
    2481             :                        externalFormat, externalType, readDst));
    2482           0 :     if (readDstRowBytes != tightRowBytes) {
    2483           0 :         SkASSERT(this->glCaps().packRowLengthSupport());
    2484           0 :         GL_CALL(PixelStorei(GR_GL_PACK_ROW_LENGTH, 0));
    2485             :     }
    2486           0 :     if (flipY && this->glCaps().packFlipYSupport()) {
    2487           0 :         GL_CALL(PixelStorei(GR_GL_PACK_REVERSE_ROW_ORDER, 0));
    2488           0 :         flipY = false;
    2489             :     }
    2490             : 
    2491             :     // now reverse the order of the rows, since GL's are bottom-to-top, but our
    2492             :     // API presents top-to-bottom. We must preserve the padding contents. Note
    2493             :     // that the above readPixels did not overwrite the padding.
    2494           0 :     if (readDst == buffer) {
    2495           0 :         SkASSERT(rowBytes == readDstRowBytes);
    2496           0 :         if (flipY) {
    2497           0 :             scratch.reset(tightRowBytes);
    2498           0 :             void* tmpRow = scratch.get();
    2499             :             // flip y in-place by rows
    2500           0 :             const int halfY = height >> 1;
    2501           0 :             char* top = reinterpret_cast<char*>(buffer);
    2502           0 :             char* bottom = top + (height - 1) * rowBytes;
    2503           0 :             for (int y = 0; y < halfY; y++) {
    2504           0 :                 memcpy(tmpRow, top, tightRowBytes);
    2505           0 :                 memcpy(top, bottom, tightRowBytes);
    2506           0 :                 memcpy(bottom, tmpRow, tightRowBytes);
    2507           0 :                 top += rowBytes;
    2508           0 :                 bottom -= rowBytes;
    2509             :             }
    2510             :         }
    2511             :     } else {
    2512           0 :         SkASSERT(readDst != buffer);
    2513           0 :         SkASSERT(rowBytes != tightRowBytes);
    2514             :         // copy from readDst to buffer while flipping y
    2515             :         // const int halfY = height >> 1;
    2516           0 :         const char* src = reinterpret_cast<const char*>(readDst);
    2517           0 :         char* dst = reinterpret_cast<char*>(buffer);
    2518           0 :         if (flipY) {
    2519           0 :             dst += (height-1) * rowBytes;
    2520             :         }
    2521           0 :         for (int y = 0; y < height; y++) {
    2522           0 :             memcpy(dst, src, tightRowBytes);
    2523           0 :             src += readDstRowBytes;
    2524           0 :             if (!flipY) {
    2525           0 :                 dst += rowBytes;
    2526             :             } else {
    2527           0 :                 dst -= rowBytes;
    2528             :             }
    2529             :         }
    2530             :     }
    2531           0 :     if (!renderTarget) {
    2532           0 :         this->unbindTextureFBOForPixelOps(GR_GL_FRAMEBUFFER, surface);
    2533             :     }
    2534           0 :     return true;
    2535             : }
    2536             : 
    2537           0 : GrGpuCommandBuffer* GrGLGpu::createCommandBuffer(
    2538             :         const GrGpuCommandBuffer::LoadAndStoreInfo& colorInfo,
    2539             :         const GrGpuCommandBuffer::LoadAndStoreInfo& stencilInfo) {
    2540           0 :     return new GrGLGpuCommandBuffer(this);
    2541             : }
    2542             : 
    2543           0 : void GrGLGpu::flushRenderTarget(GrGLRenderTarget* target, const SkIRect* bounds, bool disableSRGB) {
    2544           0 :     SkASSERT(target);
    2545             : 
    2546           0 :     GrGpuResource::UniqueID rtID = target->uniqueID();
    2547           0 :     if (fHWBoundRenderTargetUniqueID != rtID) {
    2548           0 :         fStats.incRenderTargetBinds();
    2549           0 :         GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, target->renderFBOID()));
    2550             : #ifdef SK_DEBUG
    2551             :         // don't do this check in Chromium -- this is causing
    2552             :         // lots of repeated command buffer flushes when the compositor is
    2553             :         // rendering with Ganesh, which is really slow; even too slow for
    2554             :         // Debug mode.
    2555           0 :         if (kChromium_GrGLDriver != this->glContext().driver()) {
    2556             :             GrGLenum status;
    2557           0 :             GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
    2558           0 :             if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
    2559           0 :                 SkDebugf("GrGLGpu::flushRenderTarget glCheckFramebufferStatus %x\n", status);
    2560             :             }
    2561             :         }
    2562             : #endif
    2563           0 :         fHWBoundRenderTargetUniqueID = rtID;
    2564           0 :         this->flushViewport(target->getViewport());
    2565             :     }
    2566             : 
    2567           0 :     if (this->glCaps().srgbWriteControl()) {
    2568           0 :         this->flushFramebufferSRGB(GrPixelConfigIsSRGB(target->config()) && !disableSRGB);
    2569             :     }
    2570             : 
    2571           0 :     this->didWriteToSurface(target, bounds);
    2572           0 : }
    2573             : 
    2574           0 : void GrGLGpu::flushFramebufferSRGB(bool enable) {
    2575           0 :     if (enable && kYes_TriState != fHWSRGBFramebuffer) {
    2576           0 :         GL_CALL(Enable(GR_GL_FRAMEBUFFER_SRGB));
    2577           0 :         fHWSRGBFramebuffer = kYes_TriState;
    2578           0 :     } else if (!enable && kNo_TriState != fHWSRGBFramebuffer) {
    2579           0 :         GL_CALL(Disable(GR_GL_FRAMEBUFFER_SRGB));
    2580           0 :         fHWSRGBFramebuffer = kNo_TriState;
    2581             :     }
    2582           0 : }
    2583             : 
    2584           0 : void GrGLGpu::flushViewport(const GrGLIRect& viewport) {
    2585           0 :     if (fHWViewport != viewport) {
    2586           0 :         viewport.pushToGLViewport(this->glInterface());
    2587           0 :         fHWViewport = viewport;
    2588             :     }
    2589           0 : }
    2590             : 
    2591             : GrGLenum gPrimitiveType2GLMode[] = {
    2592             :     GR_GL_TRIANGLES,
    2593             :     GR_GL_TRIANGLE_STRIP,
    2594             :     GR_GL_TRIANGLE_FAN,
    2595             :     GR_GL_POINTS,
    2596             :     GR_GL_LINES,
    2597             :     GR_GL_LINE_STRIP
    2598             : };
    2599             : 
    2600             : #define SWAP_PER_DRAW 0
    2601             : 
    2602             : #if SWAP_PER_DRAW
    2603             :     #if defined(SK_BUILD_FOR_MAC)
    2604             :         #include <AGL/agl.h>
    2605             :     #elif defined(SK_BUILD_FOR_WIN32)
    2606             :         #include <gl/GL.h>
    2607             :         void SwapBuf() {
    2608             :             DWORD procID = GetCurrentProcessId();
    2609             :             HWND hwnd = GetTopWindow(GetDesktopWindow());
    2610             :             while(hwnd) {
    2611             :                 DWORD wndProcID = 0;
    2612             :                 GetWindowThreadProcessId(hwnd, &wndProcID);
    2613             :                 if(wndProcID == procID) {
    2614             :                     SwapBuffers(GetDC(hwnd));
    2615             :                 }
    2616             :                 hwnd = GetNextWindow(hwnd, GW_HWNDNEXT);
    2617             :             }
    2618             :          }
    2619             :     #endif
    2620             : #endif
    2621             : 
    2622           0 : void GrGLGpu::draw(const GrPipeline& pipeline,
    2623             :                    const GrPrimitiveProcessor& primProc,
    2624             :                    const GrMesh meshes[],
    2625             :                    int meshCount) {
    2626           0 :     this->handleDirtyContext();
    2627             : 
    2628           0 :     bool hasPoints = false;
    2629           0 :     for (int i = 0; i < meshCount; ++i) {
    2630           0 :         if (meshes[i].primitiveType() == kPoints_GrPrimitiveType) {
    2631           0 :             hasPoints = true;
    2632           0 :             break;
    2633             :         }
    2634             :     }
    2635           0 :     if (!this->flushGLState(pipeline, primProc, hasPoints)) {
    2636           0 :         return;
    2637             :     }
    2638             : 
    2639           0 :     for (int i = 0; i < meshCount; ++i) {
    2640           0 :         if (GrXferBarrierType barrierType = pipeline.xferBarrierType(*this->caps())) {
    2641           0 :             this->xferBarrier(pipeline.getRenderTarget(), barrierType);
    2642             :         }
    2643             : 
    2644           0 :         const GrMesh& mesh = meshes[i];
    2645           0 :         GrMesh::Iterator iter;
    2646           0 :         const GrNonInstancedMesh* nonInstMesh = iter.init(mesh);
    2647           0 :         do {
    2648           0 :             size_t indexOffsetInBytes = 0;
    2649           0 :             this->setupGeometry(primProc, *nonInstMesh, &indexOffsetInBytes);
    2650           0 :             if (nonInstMesh->isIndexed()) {
    2651             :                 GrGLvoid* indices =
    2652           0 :                     reinterpret_cast<GrGLvoid*>(indexOffsetInBytes +
    2653           0 :                                                 sizeof(uint16_t) * nonInstMesh->startIndex());
    2654             :                 // info.startVertex() was accounted for by setupGeometry.
    2655           0 :                 if (this->glCaps().drawRangeElementsSupport()) {
    2656             :                     // We assume here that the GrMeshDrawOps that generated the mesh used the full
    2657             :                     // 0..vertexCount()-1 range.
    2658           0 :                     int start = 0;
    2659           0 :                     int end = nonInstMesh->vertexCount() - 1;
    2660           0 :                     GL_CALL(DrawRangeElements(gPrimitiveType2GLMode[nonInstMesh->primitiveType()],
    2661             :                                               start, end,
    2662             :                                               nonInstMesh->indexCount(),
    2663             :                                               GR_GL_UNSIGNED_SHORT,
    2664             :                                               indices));
    2665             :                 } else {
    2666           0 :                     GL_CALL(DrawElements(gPrimitiveType2GLMode[nonInstMesh->primitiveType()],
    2667             :                                          nonInstMesh->indexCount(),
    2668             :                                          GR_GL_UNSIGNED_SHORT,
    2669             :                                          indices));
    2670             :                 }
    2671             :             } else {
    2672             :                 // Pass 0 for parameter first. We have to adjust glVertexAttribPointer() to account
    2673             :                 // for startVertex in the DrawElements case. So we always rely on setupGeometry to
    2674             :                 // have accounted for startVertex.
    2675           0 :                 GL_CALL(DrawArrays(gPrimitiveType2GLMode[nonInstMesh->primitiveType()], 0,
    2676             :                                    nonInstMesh->vertexCount()));
    2677             :             }
    2678           0 :             fStats.incNumDraws();
    2679             :         } while ((nonInstMesh = iter.next()));
    2680             :     }
    2681             : 
    2682             : #if SWAP_PER_DRAW
    2683             :     glFlush();
    2684             :     #if defined(SK_BUILD_FOR_MAC)
    2685             :         aglSwapBuffers(aglGetCurrentContext());
    2686             :         int set_a_break_pt_here = 9;
    2687             :         aglSwapBuffers(aglGetCurrentContext());
    2688             :     #elif defined(SK_BUILD_FOR_WIN32)
    2689             :         SwapBuf();
    2690             :         int set_a_break_pt_here = 9;
    2691             :         SwapBuf();
    2692             :     #endif
    2693             : #endif
    2694             : }
    2695             : 
    2696           0 : void GrGLGpu::onResolveRenderTarget(GrRenderTarget* target) {
    2697           0 :     GrGLRenderTarget* rt = static_cast<GrGLRenderTarget*>(target);
    2698           0 :     if (rt->needsResolve()) {
    2699             :         // Some extensions automatically resolves the texture when it is read.
    2700           0 :         if (this->glCaps().usesMSAARenderBuffers()) {
    2701           0 :             SkASSERT(rt->textureFBOID() != rt->renderFBOID());
    2702           0 :             fStats.incRenderTargetBinds();
    2703           0 :             fStats.incRenderTargetBinds();
    2704           0 :             GL_CALL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER, rt->renderFBOID()));
    2705           0 :             GL_CALL(BindFramebuffer(GR_GL_DRAW_FRAMEBUFFER, rt->textureFBOID()));
    2706             :             // make sure we go through flushRenderTarget() since we've modified
    2707             :             // the bound DRAW FBO ID.
    2708           0 :             fHWBoundRenderTargetUniqueID.makeInvalid();
    2709           0 :             const GrGLIRect& vp = rt->getViewport();
    2710           0 :             const SkIRect dirtyRect = rt->getResolveRect();
    2711             : 
    2712           0 :             if (GrGLCaps::kES_Apple_MSFBOType == this->glCaps().msFBOType()) {
    2713             :                 // Apple's extension uses the scissor as the blit bounds.
    2714           0 :                 GrScissorState scissorState;
    2715           0 :                 scissorState.set(dirtyRect);
    2716           0 :                 this->flushScissor(scissorState, vp, rt->origin());
    2717           0 :                 this->disableWindowRectangles();
    2718           0 :                 GL_CALL(ResolveMultisampleFramebuffer());
    2719             :             } else {
    2720             :                 int l, b, r, t;
    2721           0 :                 if (GrGLCaps::kResolveMustBeFull_BlitFrambufferFlag &
    2722           0 :                     this->glCaps().blitFramebufferSupportFlags()) {
    2723           0 :                     l = 0;
    2724           0 :                     b = 0;
    2725           0 :                     r = target->width();
    2726           0 :                     t = target->height();
    2727             :                 } else {
    2728             :                     GrGLIRect rect;
    2729           0 :                     rect.setRelativeTo(vp, dirtyRect.fLeft, dirtyRect.fTop,
    2730           0 :                                        dirtyRect.width(), dirtyRect.height(), target->origin());
    2731           0 :                     l = rect.fLeft;
    2732           0 :                     b = rect.fBottom;
    2733           0 :                     r = rect.fLeft + rect.fWidth;
    2734           0 :                     t = rect.fBottom + rect.fHeight;
    2735             :                 }
    2736             : 
    2737             :                 // BlitFrameBuffer respects the scissor, so disable it.
    2738           0 :                 this->disableScissor();
    2739           0 :                 this->disableWindowRectangles();
    2740           0 :                 GL_CALL(BlitFramebuffer(l, b, r, t, l, b, r, t,
    2741             :                                         GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST));
    2742             :             }
    2743             :         }
    2744           0 :         rt->flagAsResolved();
    2745             :     }
    2746           0 : }
    2747             : 
    2748             : namespace {
    2749             : 
    2750             : 
    2751           0 : GrGLenum gr_to_gl_stencil_op(GrStencilOp op) {
    2752             :     static const GrGLenum gTable[kGrStencilOpCount] = {
    2753             :         GR_GL_KEEP,        // kKeep
    2754             :         GR_GL_ZERO,        // kZero
    2755             :         GR_GL_REPLACE,     // kReplace
    2756             :         GR_GL_INVERT,      // kInvert
    2757             :         GR_GL_INCR_WRAP,   // kIncWrap
    2758             :         GR_GL_DECR_WRAP,   // kDecWrap
    2759             :         GR_GL_INCR,        // kIncClamp
    2760             :         GR_GL_DECR,        // kDecClamp
    2761             :     };
    2762             :     GR_STATIC_ASSERT(0 == (int)GrStencilOp::kKeep);
    2763             :     GR_STATIC_ASSERT(1 == (int)GrStencilOp::kZero);
    2764             :     GR_STATIC_ASSERT(2 == (int)GrStencilOp::kReplace);
    2765             :     GR_STATIC_ASSERT(3 == (int)GrStencilOp::kInvert);
    2766             :     GR_STATIC_ASSERT(4 == (int)GrStencilOp::kIncWrap);
    2767             :     GR_STATIC_ASSERT(5 == (int)GrStencilOp::kDecWrap);
    2768             :     GR_STATIC_ASSERT(6 == (int)GrStencilOp::kIncClamp);
    2769             :     GR_STATIC_ASSERT(7 == (int)GrStencilOp::kDecClamp);
    2770           0 :     SkASSERT(op < (GrStencilOp)kGrStencilOpCount);
    2771           0 :     return gTable[(int)op];
    2772             : }
    2773             : 
    2774           0 : void set_gl_stencil(const GrGLInterface* gl,
    2775             :                     const GrStencilSettings::Face& face,
    2776             :                     GrGLenum glFace) {
    2777           0 :     GrGLenum glFunc = GrToGLStencilFunc(face.fTest);
    2778           0 :     GrGLenum glFailOp = gr_to_gl_stencil_op(face.fFailOp);
    2779           0 :     GrGLenum glPassOp = gr_to_gl_stencil_op(face.fPassOp);
    2780             : 
    2781           0 :     GrGLint ref = face.fRef;
    2782           0 :     GrGLint mask = face.fTestMask;
    2783           0 :     GrGLint writeMask = face.fWriteMask;
    2784             : 
    2785           0 :     if (GR_GL_FRONT_AND_BACK == glFace) {
    2786             :         // we call the combined func just in case separate stencil is not
    2787             :         // supported.
    2788           0 :         GR_GL_CALL(gl, StencilFunc(glFunc, ref, mask));
    2789           0 :         GR_GL_CALL(gl, StencilMask(writeMask));
    2790           0 :         GR_GL_CALL(gl, StencilOp(glFailOp, GR_GL_KEEP, glPassOp));
    2791             :     } else {
    2792           0 :         GR_GL_CALL(gl, StencilFuncSeparate(glFace, glFunc, ref, mask));
    2793           0 :         GR_GL_CALL(gl, StencilMaskSeparate(glFace, writeMask));
    2794           0 :         GR_GL_CALL(gl, StencilOpSeparate(glFace, glFailOp, GR_GL_KEEP, glPassOp));
    2795             :     }
    2796           0 : }
    2797             : }
    2798             : 
    2799           0 : void GrGLGpu::flushStencil(const GrStencilSettings& stencilSettings) {
    2800           0 :     if (stencilSettings.isDisabled()) {
    2801           0 :         this->disableStencil();
    2802           0 :     } else if (fHWStencilSettings != stencilSettings) {
    2803           0 :         if (kYes_TriState != fHWStencilTestEnabled) {
    2804           0 :             GL_CALL(Enable(GR_GL_STENCIL_TEST));
    2805           0 :             fHWStencilTestEnabled = kYes_TriState;
    2806             :         }
    2807           0 :         if (stencilSettings.isTwoSided()) {
    2808           0 :             SkASSERT(this->caps()->twoSidedStencilSupport());
    2809           0 :             set_gl_stencil(this->glInterface(),
    2810             :                            stencilSettings.front(),
    2811           0 :                            GR_GL_FRONT);
    2812           0 :             set_gl_stencil(this->glInterface(),
    2813             :                            stencilSettings.back(),
    2814           0 :                            GR_GL_BACK);
    2815             :         } else {
    2816           0 :             set_gl_stencil(this->glInterface(),
    2817             :                            stencilSettings.front(),
    2818           0 :                            GR_GL_FRONT_AND_BACK);
    2819             :         }
    2820           0 :         fHWStencilSettings = stencilSettings;
    2821             :     }
    2822           0 : }
    2823             : 
    2824           0 : void GrGLGpu::disableStencil() {
    2825           0 :     if (kNo_TriState != fHWStencilTestEnabled) {
    2826           0 :         GL_CALL(Disable(GR_GL_STENCIL_TEST));
    2827           0 :         fHWStencilTestEnabled = kNo_TriState;
    2828           0 :         fHWStencilSettings.invalidate();
    2829             :     }
    2830           0 : }
    2831             : 
    2832           0 : void GrGLGpu::flushHWAAState(GrRenderTarget* rt, bool useHWAA, bool stencilEnabled) {
    2833             :     // rt is only optional if useHWAA is false.
    2834           0 :     SkASSERT(rt || !useHWAA);
    2835           0 :     SkASSERT(!useHWAA || rt->isStencilBufferMultisampled());
    2836             : 
    2837           0 :     if (this->caps()->multisampleDisableSupport()) {
    2838           0 :         if (useHWAA) {
    2839           0 :             if (kYes_TriState != fMSAAEnabled) {
    2840           0 :                 GL_CALL(Enable(GR_GL_MULTISAMPLE));
    2841           0 :                 fMSAAEnabled = kYes_TriState;
    2842             :             }
    2843             :         } else {
    2844           0 :             if (kNo_TriState != fMSAAEnabled) {
    2845           0 :                 GL_CALL(Disable(GR_GL_MULTISAMPLE));
    2846           0 :                 fMSAAEnabled = kNo_TriState;
    2847             :             }
    2848             :         }
    2849             :     }
    2850             : 
    2851           0 :     if (0 != this->caps()->maxRasterSamples()) {
    2852           0 :         if (useHWAA && rt->isMixedSampled() && !stencilEnabled) {
    2853             :             // Since stencil is disabled and we want more samples than are in the color buffer, we
    2854             :             // need to tell the rasterizer explicitly how many to run.
    2855           0 :             if (kYes_TriState != fHWRasterMultisampleEnabled) {
    2856           0 :                 GL_CALL(Enable(GR_GL_RASTER_MULTISAMPLE));
    2857           0 :                 fHWRasterMultisampleEnabled = kYes_TriState;
    2858             :             }
    2859           0 :             if (rt->numStencilSamples() != fHWNumRasterSamples) {
    2860           0 :                 SkASSERT(rt->numStencilSamples() <= this->caps()->maxRasterSamples());
    2861           0 :                 GL_CALL(RasterSamples(rt->numStencilSamples(), GR_GL_TRUE));
    2862           0 :                 fHWNumRasterSamples = rt->numStencilSamples();
    2863             :             }
    2864             :         } else {
    2865           0 :             if (kNo_TriState != fHWRasterMultisampleEnabled) {
    2866           0 :                 GL_CALL(Disable(GR_GL_RASTER_MULTISAMPLE));
    2867           0 :                 fHWRasterMultisampleEnabled = kNo_TriState;
    2868             :             }
    2869             :         }
    2870             :     } else {
    2871           0 :         SkASSERT(!useHWAA || !rt->isMixedSampled() || stencilEnabled);
    2872             :     }
    2873           0 : }
    2874             : 
    2875           0 : void GrGLGpu::flushBlend(const GrXferProcessor::BlendInfo& blendInfo, const GrSwizzle& swizzle) {
    2876             :     // Any optimization to disable blending should have already been applied and
    2877             :     // tweaked the equation to "add" or "subtract", and the coeffs to (1, 0).
    2878             : 
    2879           0 :     GrBlendEquation equation = blendInfo.fEquation;
    2880           0 :     GrBlendCoeff srcCoeff = blendInfo.fSrcBlend;
    2881           0 :     GrBlendCoeff dstCoeff = blendInfo.fDstBlend;
    2882           0 :     bool blendOff = (kAdd_GrBlendEquation == equation || kSubtract_GrBlendEquation == equation) &&
    2883           0 :                     kOne_GrBlendCoeff == srcCoeff && kZero_GrBlendCoeff == dstCoeff;
    2884           0 :     if (blendOff) {
    2885           0 :         if (kNo_TriState != fHWBlendState.fEnabled) {
    2886           0 :             GL_CALL(Disable(GR_GL_BLEND));
    2887             : 
    2888             :             // Workaround for the ARM KHR_blend_equation_advanced blacklist issue
    2889             :             // https://code.google.com/p/skia/issues/detail?id=3943
    2890           0 :             if (kARM_GrGLVendor == this->ctxInfo().vendor() &&
    2891           0 :                 GrBlendEquationIsAdvanced(fHWBlendState.fEquation)) {
    2892           0 :                 SkASSERT(this->caps()->advancedBlendEquationSupport());
    2893             :                 // Set to any basic blending equation.
    2894           0 :                 GrBlendEquation blend_equation = kAdd_GrBlendEquation;
    2895           0 :                 GL_CALL(BlendEquation(gXfermodeEquation2Blend[blend_equation]));
    2896           0 :                 fHWBlendState.fEquation = blend_equation;
    2897             :             }
    2898             : 
    2899           0 :             fHWBlendState.fEnabled = kNo_TriState;
    2900             :         }
    2901           0 :         return;
    2902             :     }
    2903             : 
    2904           0 :     if (kYes_TriState != fHWBlendState.fEnabled) {
    2905           0 :         GL_CALL(Enable(GR_GL_BLEND));
    2906           0 :         fHWBlendState.fEnabled = kYes_TriState;
    2907             :     }
    2908             : 
    2909           0 :     if (fHWBlendState.fEquation != equation) {
    2910           0 :         GL_CALL(BlendEquation(gXfermodeEquation2Blend[equation]));
    2911           0 :         fHWBlendState.fEquation = equation;
    2912             :     }
    2913             : 
    2914           0 :     if (GrBlendEquationIsAdvanced(equation)) {
    2915           0 :         SkASSERT(this->caps()->advancedBlendEquationSupport());
    2916             :         // Advanced equations have no other blend state.
    2917           0 :         return;
    2918             :     }
    2919             : 
    2920           0 :     if (fHWBlendState.fSrcCoeff != srcCoeff || fHWBlendState.fDstCoeff != dstCoeff) {
    2921           0 :         GL_CALL(BlendFunc(gXfermodeCoeff2Blend[srcCoeff],
    2922             :                           gXfermodeCoeff2Blend[dstCoeff]));
    2923           0 :         fHWBlendState.fSrcCoeff = srcCoeff;
    2924           0 :         fHWBlendState.fDstCoeff = dstCoeff;
    2925             :     }
    2926             : 
    2927           0 :     if ((BlendCoeffReferencesConstant(srcCoeff) || BlendCoeffReferencesConstant(dstCoeff))) {
    2928           0 :         GrColor blendConst = blendInfo.fBlendConstant;
    2929           0 :         blendConst = swizzle.applyTo(blendConst);
    2930           0 :         if (!fHWBlendState.fConstColorValid || fHWBlendState.fConstColor != blendConst) {
    2931             :             GrGLfloat c[4];
    2932           0 :             GrColorToRGBAFloat(blendConst, c);
    2933           0 :             GL_CALL(BlendColor(c[0], c[1], c[2], c[3]));
    2934           0 :             fHWBlendState.fConstColor = blendConst;
    2935           0 :             fHWBlendState.fConstColorValid = true;
    2936             :         }
    2937             :     }
    2938             : }
    2939             : 
    2940           0 : static inline GrGLenum tile_to_gl_wrap(SkShader::TileMode tm) {
    2941             :     static const GrGLenum gWrapModes[] = {
    2942             :         GR_GL_CLAMP_TO_EDGE,
    2943             :         GR_GL_REPEAT,
    2944             :         GR_GL_MIRRORED_REPEAT
    2945             :     };
    2946             :     GR_STATIC_ASSERT(SkShader::kTileModeCount == SK_ARRAY_COUNT(gWrapModes));
    2947             :     GR_STATIC_ASSERT(0 == SkShader::kClamp_TileMode);
    2948             :     GR_STATIC_ASSERT(1 == SkShader::kRepeat_TileMode);
    2949             :     GR_STATIC_ASSERT(2 == SkShader::kMirror_TileMode);
    2950           0 :     return gWrapModes[tm];
    2951             : }
    2952             : 
    2953           0 : static GrGLenum get_component_enum_from_char(char component) {
    2954           0 :     switch (component) {
    2955             :         case 'r':
    2956           0 :            return GR_GL_RED;
    2957             :         case 'g':
    2958           0 :            return GR_GL_GREEN;
    2959             :         case 'b':
    2960           0 :            return GR_GL_BLUE;
    2961             :         case 'a':
    2962           0 :            return GR_GL_ALPHA;
    2963             :         default:
    2964           0 :             SkFAIL("Unsupported component");
    2965           0 :             return 0;
    2966             :     }
    2967             : }
    2968             : 
    2969             : /** If texture swizzling is available using tex parameters then it is preferred over mangling
    2970             :   the generated shader code. This potentially allows greater reuse of cached shaders. */
    2971           0 : static void get_tex_param_swizzle(GrPixelConfig config,
    2972             :                                   const GrGLCaps& caps,
    2973             :                                   GrGLenum* glSwizzle) {
    2974           0 :     const GrSwizzle& swizzle = caps.configSwizzle(config);
    2975           0 :     for (int i = 0; i < 4; ++i) {
    2976           0 :         glSwizzle[i] = get_component_enum_from_char(swizzle.c_str()[i]);
    2977             :     }
    2978           0 : }
    2979             : 
    2980           0 : void GrGLGpu::bindTexture(int unitIdx, const GrSamplerParams& params, bool allowSRGBInputs,
    2981             :                           GrGLTexture* texture) {
    2982           0 :     SkASSERT(texture);
    2983             : 
    2984             : #ifdef SK_DEBUG
    2985           0 :     if (!this->caps()->npotTextureTileSupport()) {
    2986           0 :         const bool tileX = SkShader::kClamp_TileMode != params.getTileModeX();
    2987           0 :         const bool tileY = SkShader::kClamp_TileMode != params.getTileModeY();
    2988           0 :         if (tileX || tileY) {
    2989           0 :             const int w = texture->width();
    2990           0 :             const int h = texture->height();
    2991           0 :             SkASSERT(SkIsPow2(w) && SkIsPow2(h));
    2992             :         }
    2993             :     }
    2994             : #endif
    2995             : 
    2996             :     // If we created a rt/tex and rendered to it without using a texture and now we're texturing
    2997             :     // from the rt it will still be the last bound texture, but it needs resolving. So keep this
    2998             :     // out of the "last != next" check.
    2999           0 :     GrGLRenderTarget* texRT = static_cast<GrGLRenderTarget*>(texture->asRenderTarget());
    3000           0 :     if (texRT) {
    3001           0 :         this->onResolveRenderTarget(texRT);
    3002             :     }
    3003             : 
    3004           0 :     GrGpuResource::UniqueID textureID = texture->uniqueID();
    3005           0 :     GrGLenum target = texture->target();
    3006           0 :     if (fHWBoundTextureUniqueIDs[unitIdx] != textureID) {
    3007           0 :         this->setTextureUnit(unitIdx);
    3008           0 :         GL_CALL(BindTexture(target, texture->textureID()));
    3009           0 :         fHWBoundTextureUniqueIDs[unitIdx] = textureID;
    3010             :     }
    3011             : 
    3012             :     ResetTimestamp timestamp;
    3013           0 :     const GrGLTexture::TexParams& oldTexParams = texture->getCachedTexParams(&timestamp);
    3014           0 :     bool setAll = timestamp < this->getResetTimestamp();
    3015             :     GrGLTexture::TexParams newTexParams;
    3016             : 
    3017             :     static GrGLenum glMinFilterModes[] = {
    3018             :         GR_GL_NEAREST,
    3019             :         GR_GL_LINEAR,
    3020             :         GR_GL_LINEAR_MIPMAP_LINEAR
    3021             :     };
    3022             :     static GrGLenum glMagFilterModes[] = {
    3023             :         GR_GL_NEAREST,
    3024             :         GR_GL_LINEAR,
    3025             :         GR_GL_LINEAR
    3026             :     };
    3027           0 :     GrSamplerParams::FilterMode filterMode = params.filterMode();
    3028             : 
    3029           0 :     if (GrSamplerParams::kMipMap_FilterMode == filterMode) {
    3030           0 :         if (!this->caps()->mipMapSupport() || GrPixelConfigIsCompressed(texture->config())) {
    3031           0 :             filterMode = GrSamplerParams::kBilerp_FilterMode;
    3032             :         }
    3033             :     }
    3034             : 
    3035           0 :     newTexParams.fMinFilter = glMinFilterModes[filterMode];
    3036           0 :     newTexParams.fMagFilter = glMagFilterModes[filterMode];
    3037             : 
    3038           0 :     if (this->glCaps().srgbDecodeDisableSupport() && GrPixelConfigIsSRGB(texture->config())) {
    3039           0 :         newTexParams.fSRGBDecode = allowSRGBInputs ? GR_GL_DECODE_EXT : GR_GL_SKIP_DECODE_EXT;
    3040           0 :         if (setAll || newTexParams.fSRGBDecode != oldTexParams.fSRGBDecode) {
    3041           0 :             this->setTextureUnit(unitIdx);
    3042           0 :             GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SRGB_DECODE_EXT, newTexParams.fSRGBDecode));
    3043             :         }
    3044             :     }
    3045             : 
    3046             : #ifdef SK_DEBUG
    3047             :     // We were supposed to ensure MipMaps were up-to-date and built correctly before getting here.
    3048           0 :     if (GrSamplerParams::kMipMap_FilterMode == filterMode) {
    3049           0 :         SkASSERT(!texture->texturePriv().mipMapsAreDirty());
    3050           0 :         if (GrPixelConfigIsSRGB(texture->config())) {
    3051             :             SkDestinationSurfaceColorMode colorMode = allowSRGBInputs
    3052           0 :                 ? SkDestinationSurfaceColorMode::kGammaAndColorSpaceAware
    3053           0 :                 : SkDestinationSurfaceColorMode::kLegacy;
    3054           0 :             SkASSERT(texture->texturePriv().mipColorMode() == colorMode);
    3055             :         }
    3056             :     }
    3057             : #endif
    3058             : 
    3059           0 :     newTexParams.fMaxMipMapLevel = texture->texturePriv().maxMipMapLevel();
    3060             : 
    3061           0 :     newTexParams.fWrapS = tile_to_gl_wrap(params.getTileModeX());
    3062           0 :     newTexParams.fWrapT = tile_to_gl_wrap(params.getTileModeY());
    3063           0 :     get_tex_param_swizzle(texture->config(), this->glCaps(), newTexParams.fSwizzleRGBA);
    3064           0 :     if (setAll || newTexParams.fMagFilter != oldTexParams.fMagFilter) {
    3065           0 :         this->setTextureUnit(unitIdx);
    3066           0 :         GL_CALL(TexParameteri(target, GR_GL_TEXTURE_MAG_FILTER, newTexParams.fMagFilter));
    3067             :     }
    3068           0 :     if (setAll || newTexParams.fMinFilter != oldTexParams.fMinFilter) {
    3069           0 :         this->setTextureUnit(unitIdx);
    3070           0 :         GL_CALL(TexParameteri(target, GR_GL_TEXTURE_MIN_FILTER, newTexParams.fMinFilter));
    3071             :     }
    3072           0 :     if (setAll || newTexParams.fMaxMipMapLevel != oldTexParams.fMaxMipMapLevel) {
    3073             :         // These are not supported in ES2 contexts
    3074           0 :         if (this->glCaps().mipMapLevelAndLodControlSupport()) {
    3075           0 :             if (newTexParams.fMaxMipMapLevel != 0) {
    3076           0 :                 this->setTextureUnit(unitIdx);
    3077           0 :                 GL_CALL(TexParameteri(target, GR_GL_TEXTURE_MIN_LOD, 0));
    3078           0 :                 GL_CALL(TexParameteri(target, GR_GL_TEXTURE_BASE_LEVEL, 0));
    3079           0 :                 GL_CALL(TexParameteri(target, GR_GL_TEXTURE_MAX_LOD,
    3080             :                                       newTexParams.fMaxMipMapLevel));
    3081           0 :                 GL_CALL(TexParameteri(target, GR_GL_TEXTURE_MAX_LEVEL,
    3082             :                                       newTexParams.fMaxMipMapLevel));
    3083             :             }
    3084             :         }
    3085             :     }
    3086           0 :     if (setAll || newTexParams.fWrapS != oldTexParams.fWrapS) {
    3087           0 :         this->setTextureUnit(unitIdx);
    3088           0 :         GL_CALL(TexParameteri(target, GR_GL_TEXTURE_WRAP_S, newTexParams.fWrapS));
    3089             :     }
    3090           0 :     if (setAll || newTexParams.fWrapT != oldTexParams.fWrapT) {
    3091           0 :         this->setTextureUnit(unitIdx);
    3092           0 :         GL_CALL(TexParameteri(target, GR_GL_TEXTURE_WRAP_T, newTexParams.fWrapT));
    3093             :     }
    3094           0 :     if (this->glCaps().textureSwizzleSupport() &&
    3095           0 :         (setAll || memcmp(newTexParams.fSwizzleRGBA,
    3096             :                           oldTexParams.fSwizzleRGBA,
    3097             :                           sizeof(newTexParams.fSwizzleRGBA)))) {
    3098           0 :         this->setTextureSwizzle(unitIdx, target, newTexParams.fSwizzleRGBA);
    3099             :     }
    3100           0 :     texture->setCachedTexParams(newTexParams, this->getResetTimestamp());
    3101           0 : }
    3102             : 
    3103           0 : void GrGLGpu::bindTexelBuffer(int unitIdx, GrPixelConfig texelConfig, GrGLBuffer* buffer) {
    3104           0 :     SkASSERT(this->glCaps().canUseConfigWithTexelBuffer(texelConfig));
    3105           0 :     SkASSERT(unitIdx >= 0 && unitIdx < fHWBufferTextures.count());
    3106             : 
    3107           0 :     BufferTexture& buffTex = fHWBufferTextures[unitIdx];
    3108             : 
    3109           0 :     if (!buffTex.fKnownBound) {
    3110           0 :         if (!buffTex.fTextureID) {
    3111           0 :             GL_CALL(GenTextures(1, &buffTex.fTextureID));
    3112           0 :             if (!buffTex.fTextureID) {
    3113           0 :                 return;
    3114             :             }
    3115             :         }
    3116             : 
    3117           0 :         this->setTextureUnit(unitIdx);
    3118           0 :         GL_CALL(BindTexture(GR_GL_TEXTURE_BUFFER, buffTex.fTextureID));
    3119             : 
    3120           0 :         buffTex.fKnownBound = true;
    3121             :     }
    3122             : 
    3123           0 :     if (buffer->uniqueID() != buffTex.fAttachedBufferUniqueID ||
    3124           0 :         buffTex.fTexelConfig != texelConfig) {
    3125             : 
    3126           0 :         this->setTextureUnit(unitIdx);
    3127           0 :         GL_CALL(TexBuffer(GR_GL_TEXTURE_BUFFER,
    3128             :                           this->glCaps().configSizedInternalFormat(texelConfig),
    3129             :                           buffer->bufferID()));
    3130             : 
    3131           0 :         buffTex.fTexelConfig = texelConfig;
    3132           0 :         buffTex.fAttachedBufferUniqueID = buffer->uniqueID();
    3133             : 
    3134           0 :         if (this->glCaps().textureSwizzleSupport() &&
    3135           0 :             this->glCaps().configSwizzle(texelConfig) != buffTex.fSwizzle) {
    3136             :             GrGLenum glSwizzle[4];
    3137           0 :             get_tex_param_swizzle(texelConfig, this->glCaps(), glSwizzle);
    3138           0 :             this->setTextureSwizzle(unitIdx, GR_GL_TEXTURE_BUFFER, glSwizzle);
    3139           0 :             buffTex.fSwizzle = this->glCaps().configSwizzle(texelConfig);
    3140             :         }
    3141             : 
    3142           0 :         buffer->setHasAttachedToTexture();
    3143           0 :         fHWMaxUsedBufferTextureUnit = SkTMax(unitIdx, fHWMaxUsedBufferTextureUnit);
    3144             :     }
    3145             : }
    3146             : 
    3147           0 : void GrGLGpu::bindImageStorage(int unitIdx, GrIOType ioType, GrGLTexture *texture) {
    3148           0 :     SkASSERT(texture);
    3149           0 :     if (texture->uniqueID() != fHWBoundImageStorages[unitIdx].fTextureUniqueID ||
    3150           0 :         ioType != fHWBoundImageStorages[unitIdx].fIOType) {
    3151           0 :         GrGLenum access = GR_GL_READ_ONLY;
    3152           0 :         switch (ioType) {
    3153             :             case kRead_GrIOType:
    3154           0 :                 access = GR_GL_READ_ONLY;
    3155           0 :                 break;
    3156             :             case kWrite_GrIOType:
    3157           0 :                 access = GR_GL_WRITE_ONLY;
    3158           0 :                 break;
    3159             :             case kRW_GrIOType:
    3160           0 :                 access = GR_GL_READ_WRITE;
    3161           0 :                 break;
    3162             :         }
    3163           0 :         GrGLenum format = this->glCaps().getImageFormat(texture->config());
    3164           0 :         GL_CALL(BindImageTexture(unitIdx, texture->textureID(), 0, GR_GL_FALSE, 0, access, format));
    3165             :     }
    3166           0 : }
    3167             : 
    3168           0 : void GrGLGpu::generateMipmaps(const GrSamplerParams& params, bool allowSRGBInputs,
    3169             :                               GrGLTexture* texture) {
    3170           0 :     SkASSERT(texture);
    3171             : 
    3172             :     // First, figure out if we need mips for this texture at all:
    3173           0 :     GrSamplerParams::FilterMode filterMode = params.filterMode();
    3174             : 
    3175           0 :     if (GrSamplerParams::kMipMap_FilterMode == filterMode) {
    3176           0 :         if (!this->caps()->mipMapSupport() || GrPixelConfigIsCompressed(texture->config())) {
    3177           0 :             filterMode = GrSamplerParams::kBilerp_FilterMode;
    3178             :         }
    3179             :     }
    3180             : 
    3181           0 :     if (GrSamplerParams::kMipMap_FilterMode != filterMode) {
    3182           0 :         return;
    3183             :     }
    3184             : 
    3185             :     // If this is an sRGB texture and the mips were previously built the "other" way
    3186             :     // (gamma-correct vs. not), then we need to rebuild them. We don't need to check for
    3187             :     // srgbSupport - we'll *never* get an sRGB pixel config if we don't support it.
    3188             :     SkDestinationSurfaceColorMode colorMode = allowSRGBInputs
    3189           0 :         ? SkDestinationSurfaceColorMode::kGammaAndColorSpaceAware
    3190           0 :         : SkDestinationSurfaceColorMode::kLegacy;
    3191           0 :     if (GrPixelConfigIsSRGB(texture->config()) &&
    3192           0 :         colorMode != texture->texturePriv().mipColorMode()) {
    3193           0 :         texture->texturePriv().dirtyMipMaps(true);
    3194             :     }
    3195             : 
    3196             :     // If the mips aren't dirty, we're done:
    3197           0 :     if (!texture->texturePriv().mipMapsAreDirty()) {
    3198           0 :         return;
    3199             :     }
    3200             : 
    3201             :     // If we created a rt/tex and rendered to it without using a texture and now we're texturing
    3202             :     // from the rt it will still be the last bound texture, but it needs resolving.
    3203           0 :     GrGLRenderTarget* texRT = static_cast<GrGLRenderTarget*>(texture->asRenderTarget());
    3204           0 :     if (texRT) {
    3205           0 :         this->onResolveRenderTarget(texRT);
    3206             :     }
    3207             : 
    3208           0 :     GrGLenum target = texture->target();
    3209           0 :     this->setScratchTextureUnit();
    3210           0 :     GL_CALL(BindTexture(target, texture->textureID()));
    3211             : 
    3212             :     // Configure sRGB decode, if necessary. This state is the only thing needed for the driver
    3213             :     // call (glGenerateMipmap) to work correctly. Our manual method dirties other state, too.
    3214           0 :     if (this->glCaps().srgbDecodeDisableSupport() && GrPixelConfigIsSRGB(texture->config())) {
    3215           0 :         GrGLenum srgbDecode = allowSRGBInputs ? GR_GL_DECODE_EXT : GR_GL_SKIP_DECODE_EXT;
    3216             :         // Command buffer's sRGB decode extension doesn't influence mipmap generation correctly.
    3217             :         // If we set this to skip_decode, it appears to suppress sRGB -> Linear for each downsample,
    3218             :         // but not the Linear -> sRGB when writing the next level. The result is that mip-chains
    3219             :         // get progressively brighter as you go down. Forcing this to 'decode' gives predictable
    3220             :         // (and only slightly incorrect) results. See crbug.com/655247 (~comment 28)
    3221           0 :         if (!this->glCaps().srgbDecodeDisableAffectsMipmaps()) {
    3222           0 :             srgbDecode = GR_GL_DECODE_EXT;
    3223             :         }
    3224           0 :         GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SRGB_DECODE_EXT, srgbDecode));
    3225             :     }
    3226             : 
    3227             :     // Either do manual mipmap generation or (if that fails), just rely on the driver:
    3228           0 :     if (!this->generateMipmap(texture, allowSRGBInputs)) {
    3229           0 :         GL_CALL(GenerateMipmap(target));
    3230             :     }
    3231             : 
    3232           0 :     texture->texturePriv().dirtyMipMaps(false);
    3233           0 :     texture->texturePriv().setMaxMipMapLevel(SkMipMap::ComputeLevelCount(
    3234           0 :         texture->width(), texture->height()));
    3235           0 :     texture->texturePriv().setMipColorMode(colorMode);
    3236             : 
    3237             :     // We have potentially set lots of state on the texture. Easiest to dirty it all:
    3238           0 :     texture->textureParamsModified();
    3239             : }
    3240             : 
    3241           0 : void GrGLGpu::setTextureSwizzle(int unitIdx, GrGLenum target, const GrGLenum swizzle[]) {
    3242           0 :     this->setTextureUnit(unitIdx);
    3243           0 :     if (this->glStandard() == kGLES_GrGLStandard) {
    3244             :         // ES3 added swizzle support but not GL_TEXTURE_SWIZZLE_RGBA.
    3245           0 :         GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SWIZZLE_R, swizzle[0]));
    3246           0 :         GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SWIZZLE_G, swizzle[1]));
    3247           0 :         GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SWIZZLE_B, swizzle[2]));
    3248           0 :         GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SWIZZLE_A, swizzle[3]));
    3249             :     } else {
    3250             :         GR_STATIC_ASSERT(sizeof(swizzle[0]) == sizeof(GrGLint));
    3251           0 :         GL_CALL(TexParameteriv(target, GR_GL_TEXTURE_SWIZZLE_RGBA,
    3252             :                                reinterpret_cast<const GrGLint*>(swizzle)));
    3253             :     }
    3254           0 : }
    3255             : 
    3256           0 : void GrGLGpu::flushColorWrite(bool writeColor) {
    3257           0 :     if (!writeColor) {
    3258           0 :         if (kNo_TriState != fHWWriteToColor) {
    3259           0 :             GL_CALL(ColorMask(GR_GL_FALSE, GR_GL_FALSE,
    3260             :                               GR_GL_FALSE, GR_GL_FALSE));
    3261           0 :             fHWWriteToColor = kNo_TriState;
    3262             :         }
    3263             :     } else {
    3264           0 :         if (kYes_TriState != fHWWriteToColor) {
    3265           0 :             GL_CALL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
    3266           0 :             fHWWriteToColor = kYes_TriState;
    3267             :         }
    3268             :     }
    3269           0 : }
    3270             : 
    3271           0 : void GrGLGpu::flushDrawFace(GrDrawFace face) {
    3272           0 :     if (fHWDrawFace != face) {
    3273           0 :         switch (face) {
    3274             :             case GrDrawFace::kCCW:
    3275           0 :                 GL_CALL(Enable(GR_GL_CULL_FACE));
    3276           0 :                 GL_CALL(CullFace(GR_GL_BACK));
    3277           0 :                 break;
    3278             :             case GrDrawFace::kCW:
    3279           0 :                 GL_CALL(Enable(GR_GL_CULL_FACE));
    3280           0 :                 GL_CALL(CullFace(GR_GL_FRONT));
    3281           0 :                 break;
    3282             :             case GrDrawFace::kBoth:
    3283           0 :                 GL_CALL(Disable(GR_GL_CULL_FACE));
    3284           0 :                 break;
    3285             :             default:
    3286           0 :                 SkFAIL("Unknown draw face.");
    3287             :         }
    3288           0 :         fHWDrawFace = face;
    3289             :     }
    3290           0 : }
    3291             : 
    3292           0 : void GrGLGpu::setTextureUnit(int unit) {
    3293           0 :     SkASSERT(unit >= 0 && unit < fHWBoundTextureUniqueIDs.count());
    3294           0 :     if (unit != fHWActiveTextureUnitIdx) {
    3295           0 :         GL_CALL(ActiveTexture(GR_GL_TEXTURE0 + unit));
    3296           0 :         fHWActiveTextureUnitIdx = unit;
    3297             :     }
    3298           0 : }
    3299             : 
    3300           0 : void GrGLGpu::setScratchTextureUnit() {
    3301             :     // Bind the last texture unit since it is the least likely to be used by GrGLProgram.
    3302           0 :     int lastUnitIdx = fHWBoundTextureUniqueIDs.count() - 1;
    3303           0 :     if (lastUnitIdx != fHWActiveTextureUnitIdx) {
    3304           0 :         GL_CALL(ActiveTexture(GR_GL_TEXTURE0 + lastUnitIdx));
    3305           0 :         fHWActiveTextureUnitIdx = lastUnitIdx;
    3306             :     }
    3307             :     // clear out the this field so that if a program does use this unit it will rebind the correct
    3308             :     // texture.
    3309           0 :     fHWBoundTextureUniqueIDs[lastUnitIdx].makeInvalid();
    3310           0 : }
    3311             : 
    3312             : // Determines whether glBlitFramebuffer could be used between src and dst by onCopySurface.
    3313           0 : static inline bool can_blit_framebuffer_for_copy_surface(const GrSurface* dst,
    3314             :                                                          const GrSurface* src,
    3315             :                                                          const SkIRect& srcRect,
    3316             :                                                          const SkIPoint& dstPoint,
    3317             :                                                          const GrGLGpu* gpu) {
    3318           0 :     auto blitFramebufferFlags = gpu->glCaps().blitFramebufferSupportFlags();
    3319           0 :     if (!gpu->glCaps().canConfigBeFBOColorAttachment(dst->config()) ||
    3320           0 :         !gpu->glCaps().canConfigBeFBOColorAttachment(src->config())) {
    3321           0 :         return false;
    3322             :     }
    3323             :     // Blits are not allowed between int color buffers and float/fixed color buffers. GrGpu should
    3324             :     // have filtered such cases out.
    3325           0 :     SkASSERT(GrPixelConfigIsSint(dst->config()) == GrPixelConfigIsSint(src->config()));
    3326           0 :     const GrGLTexture* dstTex = static_cast<const GrGLTexture*>(dst->asTexture());
    3327           0 :     const GrGLTexture* srcTex = static_cast<const GrGLTexture*>(dst->asTexture());
    3328           0 :     const GrRenderTarget* dstRT = dst->asRenderTarget();
    3329           0 :     const GrRenderTarget* srcRT = src->asRenderTarget();
    3330           0 :     if (dstTex && dstTex->target() != GR_GL_TEXTURE_2D) {
    3331           0 :         return false;
    3332             :     }
    3333           0 :     if (srcTex && srcTex->target() != GR_GL_TEXTURE_2D) {
    3334           0 :         return false;
    3335             :     }
    3336           0 :     if (GrGLCaps::kNoSupport_BlitFramebufferFlag & blitFramebufferFlags) {
    3337           0 :         return false;
    3338             :     }
    3339           0 :     if (GrGLCaps::kNoScalingOrMirroring_BlitFramebufferFlag & blitFramebufferFlags) {
    3340             :         // We would mirror to compensate for origin changes. Note that copySurface is
    3341             :         // specified such that the src and dst rects are the same.
    3342           0 :         if (dst->origin() != src->origin()) {
    3343           0 :             return false;
    3344             :         }
    3345             :     }
    3346           0 :     if (GrGLCaps::kResolveMustBeFull_BlitFrambufferFlag & blitFramebufferFlags) {
    3347           0 :         if (srcRT && srcRT->numColorSamples()) {
    3348           0 :             if (dstRT && !dstRT->numColorSamples()) {
    3349           0 :                 return false;
    3350             :             }
    3351           0 :             if (SkRect::Make(srcRect) != srcRT->getBoundsRect()) {
    3352           0 :                 return false;
    3353             :             }
    3354             :         }
    3355             :     }
    3356           0 :     if (GrGLCaps::kNoMSAADst_BlitFramebufferFlag & blitFramebufferFlags) {
    3357           0 :         if (dstRT && dstRT->numColorSamples() > 0) {
    3358           0 :             return false;
    3359             :         }
    3360             :     }    
    3361           0 :     if (GrGLCaps::kNoFormatConversion_BlitFramebufferFlag & blitFramebufferFlags) {
    3362           0 :         if (dst->config() != src->config()) {
    3363           0 :             return false;
    3364             :         }
    3365           0 :     } else if (GrGLCaps::kNoFormatConversionForMSAASrc_BlitFramebufferFlag & blitFramebufferFlags) {
    3366           0 :         const GrRenderTarget* srcRT = src->asRenderTarget();
    3367           0 :         if (srcRT && srcRT->numColorSamples() && dst->config() != src->config()) {
    3368           0 :             return false;
    3369             :         }
    3370             :     }
    3371           0 :     if (GrGLCaps::kRectsMustMatchForMSAASrc_BlitFramebufferFlag & blitFramebufferFlags) {
    3372           0 :         if (srcRT && srcRT->numColorSamples()) {
    3373           0 :             if (dstPoint.fX != srcRect.fLeft || dstPoint.fY != srcRect.fTop) {
    3374           0 :                 return false;
    3375             :             }
    3376           0 :             if (dst->origin() != src->origin()) {
    3377           0 :                 return false;
    3378             :             }
    3379             :         }
    3380             :     }
    3381           0 :     return true;
    3382             : }
    3383             : 
    3384           0 : static inline bool can_copy_texsubimage(const GrSurface* dst,
    3385             :                                         const GrSurface* src,
    3386             :                                         const GrGLGpu* gpu) {
    3387             :     // Table 3.9 of the ES2 spec indicates the supported formats with CopyTexSubImage
    3388             :     // and BGRA isn't in the spec. There doesn't appear to be any extension that adds it. Perhaps
    3389             :     // many drivers would allow it to work, but ANGLE does not.
    3390           0 :     if (kGLES_GrGLStandard == gpu->glStandard() && gpu->glCaps().bgraIsInternalFormat() &&
    3391           0 :         (kBGRA_8888_GrPixelConfig == dst->config() || kBGRA_8888_GrPixelConfig == src->config())) {
    3392           0 :         return false;
    3393             :     }
    3394           0 :     const GrGLRenderTarget* dstRT = static_cast<const GrGLRenderTarget*>(dst->asRenderTarget());
    3395             :     // If dst is multisampled (and uses an extension where there is a separate MSAA renderbuffer)
    3396             :     // then we don't want to copy to the texture but to the MSAA buffer.
    3397           0 :     if (dstRT && dstRT->renderFBOID() != dstRT->textureFBOID()) {
    3398           0 :         return false;
    3399             :     }
    3400           0 :     const GrGLRenderTarget* srcRT = static_cast<const GrGLRenderTarget*>(src->asRenderTarget());
    3401             :     // If the src is multisampled (and uses an extension where there is a separate MSAA
    3402             :     // renderbuffer) then it is an invalid operation to call CopyTexSubImage
    3403           0 :     if (srcRT && srcRT->renderFBOID() != srcRT->textureFBOID()) {
    3404           0 :         return false;
    3405             :     }
    3406             : 
    3407           0 :     const GrGLTexture* dstTex = static_cast<const GrGLTexture*>(dst->asTexture());
    3408             :     // CopyTex(Sub)Image writes to a texture and we have no way of dynamically wrapping a RT in a
    3409             :     // texture.
    3410           0 :     if (!dstTex) {
    3411           0 :         return false;
    3412             :     }
    3413             : 
    3414           0 :     const GrGLTexture* srcTex = static_cast<const GrGLTexture*>(src->asTexture());
    3415             : 
    3416             :     // Check that we could wrap the source in an FBO, that the dst is TEXTURE_2D, that no mirroring
    3417             :     // is required.
    3418           0 :     if (gpu->glCaps().canConfigBeFBOColorAttachment(src->config()) &&
    3419           0 :         !GrPixelConfigIsCompressed(src->config()) &&
    3420           0 :         (!srcTex || srcTex->target() == GR_GL_TEXTURE_2D) && dstTex->target() == GR_GL_TEXTURE_2D &&
    3421           0 :         dst->origin() == src->origin()) {
    3422           0 :         return true;
    3423             :     } else {
    3424           0 :         return false;
    3425             :     }
    3426             : }
    3427             : 
    3428             : // If a temporary FBO was created, its non-zero ID is returned. The viewport that the copy rect is
    3429             : // relative to is output.
    3430           0 : void GrGLGpu::bindSurfaceFBOForPixelOps(GrSurface* surface, GrGLenum fboTarget, GrGLIRect* viewport,
    3431             :                                         TempFBOTarget tempFBOTarget) {
    3432           0 :     GrGLRenderTarget* rt = static_cast<GrGLRenderTarget*>(surface->asRenderTarget());
    3433           0 :     if (!rt) {
    3434           0 :         SkASSERT(surface->asTexture());
    3435           0 :         GrGLuint texID = static_cast<GrGLTexture*>(surface->asTexture())->textureID();
    3436           0 :         GrGLenum target = static_cast<GrGLTexture*>(surface->asTexture())->target();
    3437             :         GrGLuint* tempFBOID;
    3438           0 :         tempFBOID = kSrc_TempFBOTarget == tempFBOTarget ? &fTempSrcFBOID : &fTempDstFBOID;
    3439             : 
    3440           0 :         if (0 == *tempFBOID) {
    3441           0 :             GR_GL_CALL(this->glInterface(), GenFramebuffers(1, tempFBOID));
    3442             :         }
    3443             : 
    3444           0 :         fStats.incRenderTargetBinds();
    3445           0 :         GR_GL_CALL(this->glInterface(), BindFramebuffer(fboTarget, *tempFBOID));
    3446           0 :         GR_GL_CALL(this->glInterface(), FramebufferTexture2D(fboTarget,
    3447             :                                                              GR_GL_COLOR_ATTACHMENT0,
    3448             :                                                              target,
    3449             :                                                              texID,
    3450             :                                                              0));
    3451           0 :         viewport->fLeft = 0;
    3452           0 :         viewport->fBottom = 0;
    3453           0 :         viewport->fWidth = surface->width();
    3454           0 :         viewport->fHeight = surface->height();
    3455             :     } else {
    3456           0 :         fStats.incRenderTargetBinds();
    3457           0 :         GR_GL_CALL(this->glInterface(), BindFramebuffer(fboTarget, rt->renderFBOID()));
    3458           0 :         *viewport = rt->getViewport();
    3459             :     }
    3460           0 : }
    3461             : 
    3462           0 : void GrGLGpu::unbindTextureFBOForPixelOps(GrGLenum fboTarget, GrSurface* surface) {
    3463             :     // bindSurfaceFBOForPixelOps temporarily binds textures that are not render targets to
    3464           0 :     if (!surface->asRenderTarget()) {
    3465           0 :         SkASSERT(surface->asTexture());
    3466           0 :         GrGLenum textureTarget = static_cast<GrGLTexture*>(surface->asTexture())->target();
    3467           0 :         GR_GL_CALL(this->glInterface(), FramebufferTexture2D(fboTarget,
    3468             :                                                              GR_GL_COLOR_ATTACHMENT0,
    3469             :                                                              textureTarget,
    3470             :                                                              0,
    3471             :                                                              0));
    3472             :     }
    3473           0 : }
    3474             : 
    3475           0 : bool GrGLGpu::onCopySurface(GrSurface* dst,
    3476             :                             GrSurface* src,
    3477             :                             const SkIRect& srcRect,
    3478             :                             const SkIPoint& dstPoint) {
    3479             :     // None of our copy methods can handle a swizzle. TODO: Make copySurfaceAsDraw handle the
    3480             :     // swizzle.
    3481           0 :     if (this->caps()->shaderCaps()->configOutputSwizzle(src->config()) !=
    3482             :         this->caps()->shaderCaps()->configOutputSwizzle(dst->config())) {
    3483           0 :         return false;
    3484             :     }
    3485             :     // Don't prefer copying as a draw if the dst doesn't already have a FBO object.
    3486           0 :     bool preferCopy = SkToBool(dst->asRenderTarget());
    3487           0 :     if (preferCopy && src->asTexture()) {
    3488           0 :         if (this->copySurfaceAsDraw(dst, src, srcRect, dstPoint)) {
    3489           0 :             return true;
    3490             :         }
    3491             :     }
    3492             : 
    3493           0 :     if (can_copy_texsubimage(dst, src, this)) {
    3494           0 :         this->copySurfaceAsCopyTexSubImage(dst, src, srcRect, dstPoint);
    3495           0 :         return true;
    3496             :     }
    3497             : 
    3498           0 :     if (can_blit_framebuffer_for_copy_surface(dst, src, srcRect, dstPoint, this)) {
    3499           0 :         return this->copySurfaceAsBlitFramebuffer(dst, src, srcRect, dstPoint);
    3500             :     }
    3501             : 
    3502           0 :     if (!preferCopy && src->asTexture()) {
    3503           0 :         if (this->copySurfaceAsDraw(dst, src, srcRect, dstPoint)) {
    3504           0 :             return true;
    3505             :         }
    3506             :     }
    3507             : 
    3508           0 :     return false;
    3509             : }
    3510             : 
    3511           0 : bool GrGLGpu::createCopyProgram(GrTexture* srcTex) {
    3512           0 :     int progIdx = TextureToCopyProgramIdx(srcTex);
    3513           0 :     const GrShaderCaps* shaderCaps = this->caps()->shaderCaps();
    3514           0 :     GrSLType samplerType = srcTex->texturePriv().samplerType();
    3515             : 
    3516           0 :     if (!fCopyProgramArrayBuffer) {
    3517             :         static const GrGLfloat vdata[] = {
    3518             :             0, 0,
    3519             :             0, 1,
    3520             :             1, 0,
    3521             :             1, 1
    3522             :         };
    3523           0 :         fCopyProgramArrayBuffer.reset(GrGLBuffer::Create(this, sizeof(vdata), kVertex_GrBufferType,
    3524           0 :                                                          kStatic_GrAccessPattern, vdata));
    3525             :     }
    3526           0 :     if (!fCopyProgramArrayBuffer) {
    3527           0 :         return false;
    3528             :     }
    3529             : 
    3530           0 :     SkASSERT(!fCopyPrograms[progIdx].fProgram);
    3531           0 :     GL_CALL_RET(fCopyPrograms[progIdx].fProgram, CreateProgram());
    3532           0 :     if (!fCopyPrograms[progIdx].fProgram) {
    3533           0 :         return false;
    3534             :     }
    3535             : 
    3536           0 :     const char* version = shaderCaps->versionDeclString();
    3537           0 :     GrShaderVar aVertex("a_vertex", kVec2f_GrSLType, GrShaderVar::kIn_TypeModifier);
    3538             :     GrShaderVar uTexCoordXform("u_texCoordXform", kVec4f_GrSLType,
    3539           0 :                                GrShaderVar::kUniform_TypeModifier);
    3540           0 :     GrShaderVar uPosXform("u_posXform", kVec4f_GrSLType, GrShaderVar::kUniform_TypeModifier);
    3541           0 :     GrShaderVar uTexture("u_texture", samplerType, GrShaderVar::kUniform_TypeModifier);
    3542           0 :     GrShaderVar vTexCoord("v_texCoord", kVec2f_GrSLType, GrShaderVar::kOut_TypeModifier);
    3543           0 :     GrShaderVar oFragColor("o_FragColor", kVec4f_GrSLType, GrShaderVar::kOut_TypeModifier);
    3544             : 
    3545           0 :     SkString vshaderTxt(version);
    3546           0 :     if (shaderCaps->noperspectiveInterpolationSupport()) {
    3547           0 :         if (const char* extension = shaderCaps->noperspectiveInterpolationExtensionString()) {
    3548           0 :             vshaderTxt.appendf("#extension %s : require\n", extension);
    3549             :         }
    3550           0 :         vTexCoord.addModifier("noperspective");
    3551             :     }
    3552             : 
    3553           0 :     aVertex.appendDecl(shaderCaps, &vshaderTxt);
    3554           0 :     vshaderTxt.append(";");
    3555           0 :     uTexCoordXform.appendDecl(shaderCaps, &vshaderTxt);
    3556           0 :     vshaderTxt.append(";");
    3557           0 :     uPosXform.appendDecl(shaderCaps, &vshaderTxt);
    3558           0 :     vshaderTxt.append(";");
    3559           0 :     vTexCoord.appendDecl(shaderCaps, &vshaderTxt);
    3560           0 :     vshaderTxt.append(";");
    3561             : 
    3562             :     vshaderTxt.append(
    3563             :         "// Copy Program VS\n"
    3564             :         "void main() {"
    3565             :         "  v_texCoord = a_vertex.xy * u_texCoordXform.xy + u_texCoordXform.zw;"
    3566             :         "  gl_Position.xy = a_vertex * u_posXform.xy + u_posXform.zw;"
    3567             :         "  gl_Position.zw = vec2(0, 1);"
    3568             :         "}"
    3569           0 :     );
    3570             : 
    3571           0 :     SkString fshaderTxt(version);
    3572           0 :     if (shaderCaps->noperspectiveInterpolationSupport()) {
    3573           0 :         if (const char* extension = shaderCaps->noperspectiveInterpolationExtensionString()) {
    3574           0 :             fshaderTxt.appendf("#extension %s : require\n", extension);
    3575             :         }
    3576             :     }
    3577           0 :     if (samplerType == kTextureExternalSampler_GrSLType) {
    3578           0 :         fshaderTxt.appendf("#extension %s : require\n",
    3579           0 :                            shaderCaps->externalTextureExtensionString());
    3580             :     }
    3581             :     GrGLSLAppendDefaultFloatPrecisionDeclaration(kMedium_GrSLPrecision, *shaderCaps,
    3582           0 :                                                  &fshaderTxt);
    3583           0 :     vTexCoord.setTypeModifier(GrShaderVar::kIn_TypeModifier);
    3584           0 :     vTexCoord.appendDecl(shaderCaps, &fshaderTxt);
    3585           0 :     fshaderTxt.append(";");
    3586           0 :     uTexture.appendDecl(shaderCaps, &fshaderTxt);
    3587           0 :     fshaderTxt.append(";");
    3588             :     fshaderTxt.appendf(
    3589             :         "// Copy Program FS\n"
    3590             :         "void main() {"
    3591             :         "  sk_FragColor = texture(u_texture, v_texCoord);"
    3592             :         "}"
    3593           0 :     );
    3594             : 
    3595             :     const char* str;
    3596             :     GrGLint length;
    3597             : 
    3598           0 :     str = vshaderTxt.c_str();
    3599           0 :     length = SkToInt(vshaderTxt.size());
    3600           0 :     SkSL::Program::Settings settings;
    3601           0 :     settings.fCaps = shaderCaps;
    3602             :     SkSL::Program::Inputs inputs;
    3603           0 :     GrGLuint vshader = GrGLCompileAndAttachShader(*fGLContext, fCopyPrograms[progIdx].fProgram,
    3604             :                                                   GR_GL_VERTEX_SHADER, &str, &length, 1,
    3605           0 :                                                   &fStats, settings, &inputs);
    3606           0 :     SkASSERT(inputs.isEmpty());
    3607             : 
    3608           0 :     str = fshaderTxt.c_str();
    3609           0 :     length = SkToInt(fshaderTxt.size());
    3610           0 :     GrGLuint fshader = GrGLCompileAndAttachShader(*fGLContext, fCopyPrograms[progIdx].fProgram,
    3611             :                                                   GR_GL_FRAGMENT_SHADER, &str, &length, 1,
    3612           0 :                                                   &fStats, settings, &inputs);
    3613           0 :     SkASSERT(inputs.isEmpty());
    3614             : 
    3615           0 :     GL_CALL(LinkProgram(fCopyPrograms[progIdx].fProgram));
    3616             : 
    3617           0 :     GL_CALL_RET(fCopyPrograms[progIdx].fTextureUniform,
    3618             :                 GetUniformLocation(fCopyPrograms[progIdx].fProgram, "u_texture"));
    3619           0 :     GL_CALL_RET(fCopyPrograms[progIdx].fPosXformUniform,
    3620             :                 GetUniformLocation(fCopyPrograms[progIdx].fProgram, "u_posXform"));
    3621           0 :     GL_CALL_RET(fCopyPrograms[progIdx].fTexCoordXformUniform,
    3622             :                 GetUniformLocation(fCopyPrograms[progIdx].fProgram, "u_texCoordXform"));
    3623             : 
    3624           0 :     GL_CALL(BindAttribLocation(fCopyPrograms[progIdx].fProgram, 0, "a_vertex"));
    3625             : 
    3626           0 :     GL_CALL(DeleteShader(vshader));
    3627           0 :     GL_CALL(DeleteShader(fshader));
    3628             : 
    3629           0 :     return true;
    3630             : }
    3631             : 
    3632           0 : bool GrGLGpu::createMipmapProgram(int progIdx) {
    3633           0 :     const bool oddWidth = SkToBool(progIdx & 0x2);
    3634           0 :     const bool oddHeight = SkToBool(progIdx & 0x1);
    3635           0 :     const int numTaps = (oddWidth ? 2 : 1) * (oddHeight ? 2 : 1);
    3636             : 
    3637           0 :     const GrShaderCaps* shaderCaps = this->caps()->shaderCaps();
    3638             : 
    3639           0 :     SkASSERT(!fMipmapPrograms[progIdx].fProgram);
    3640           0 :     GL_CALL_RET(fMipmapPrograms[progIdx].fProgram, CreateProgram());
    3641           0 :     if (!fMipmapPrograms[progIdx].fProgram) {
    3642           0 :         return false;
    3643             :     }
    3644             : 
    3645           0 :     const char* version = shaderCaps->versionDeclString();
    3646           0 :     GrShaderVar aVertex("a_vertex", kVec2f_GrSLType, GrShaderVar::kIn_TypeModifier);
    3647             :     GrShaderVar uTexCoordXform("u_texCoordXform", kVec4f_GrSLType,
    3648           0 :                                GrShaderVar::kUniform_TypeModifier);
    3649             :     GrShaderVar uTexture("u_texture", kTexture2DSampler_GrSLType,
    3650           0 :                          GrShaderVar::kUniform_TypeModifier);
    3651             :     // We need 1, 2, or 4 texture coordinates (depending on parity of each dimension):
    3652             :     GrShaderVar vTexCoords[] = {
    3653             :         GrShaderVar("v_texCoord0", kVec2f_GrSLType, GrShaderVar::kOut_TypeModifier),
    3654             :         GrShaderVar("v_texCoord1", kVec2f_GrSLType, GrShaderVar::kOut_TypeModifier),
    3655             :         GrShaderVar("v_texCoord2", kVec2f_GrSLType, GrShaderVar::kOut_TypeModifier),
    3656             :         GrShaderVar("v_texCoord3", kVec2f_GrSLType, GrShaderVar::kOut_TypeModifier),
    3657           0 :     };
    3658           0 :     GrShaderVar oFragColor("o_FragColor", kVec4f_GrSLType,GrShaderVar::kOut_TypeModifier);
    3659             : 
    3660           0 :     SkString vshaderTxt(version);
    3661           0 :     if (shaderCaps->noperspectiveInterpolationSupport()) {
    3662           0 :         if (const char* extension = shaderCaps->noperspectiveInterpolationExtensionString()) {
    3663           0 :             vshaderTxt.appendf("#extension %s : require\n", extension);
    3664             :         }
    3665           0 :         vTexCoords[0].addModifier("noperspective");
    3666           0 :         vTexCoords[1].addModifier("noperspective");
    3667           0 :         vTexCoords[2].addModifier("noperspective");
    3668           0 :         vTexCoords[3].addModifier("noperspective");
    3669             :     }
    3670             : 
    3671           0 :     aVertex.appendDecl(shaderCaps, &vshaderTxt);
    3672           0 :     vshaderTxt.append(";");
    3673           0 :     uTexCoordXform.appendDecl(shaderCaps, &vshaderTxt);
    3674           0 :     vshaderTxt.append(";");
    3675           0 :     for (int i = 0; i < numTaps; ++i) {
    3676           0 :         vTexCoords[i].appendDecl(shaderCaps, &vshaderTxt);
    3677           0 :         vshaderTxt.append(";");
    3678             :     }
    3679             : 
    3680             :     vshaderTxt.append(
    3681             :         "// Mipmap Program VS\n"
    3682             :         "void main() {"
    3683             :         "  gl_Position.xy = a_vertex * vec2(2, 2) - vec2(1, 1);"
    3684             :         "  gl_Position.zw = vec2(0, 1);"
    3685           0 :     );
    3686             : 
    3687             :     // Insert texture coordinate computation:
    3688           0 :     if (oddWidth && oddHeight) {
    3689             :         vshaderTxt.append(
    3690             :             "  v_texCoord0 = a_vertex.xy * u_texCoordXform.yw;"
    3691             :             "  v_texCoord1 = a_vertex.xy * u_texCoordXform.yw + vec2(u_texCoordXform.x, 0);"
    3692             :             "  v_texCoord2 = a_vertex.xy * u_texCoordXform.yw + vec2(0, u_texCoordXform.z);"
    3693             :             "  v_texCoord3 = a_vertex.xy * u_texCoordXform.yw + u_texCoordXform.xz;"
    3694           0 :         );
    3695           0 :     } else if (oddWidth) {
    3696             :         vshaderTxt.append(
    3697             :             "  v_texCoord0 = a_vertex.xy * vec2(u_texCoordXform.y, 1);"
    3698             :             "  v_texCoord1 = a_vertex.xy * vec2(u_texCoordXform.y, 1) + vec2(u_texCoordXform.x, 0);"
    3699           0 :         );
    3700           0 :     } else if (oddHeight) {
    3701             :         vshaderTxt.append(
    3702             :             "  v_texCoord0 = a_vertex.xy * vec2(1, u_texCoordXform.w);"
    3703             :             "  v_texCoord1 = a_vertex.xy * vec2(1, u_texCoordXform.w) + vec2(0, u_texCoordXform.z);"
    3704           0 :         );
    3705             :     } else {
    3706             :         vshaderTxt.append(
    3707             :             "  v_texCoord0 = a_vertex.xy;"
    3708           0 :         );
    3709             :     }
    3710             : 
    3711           0 :     vshaderTxt.append("}");
    3712             : 
    3713           0 :     SkString fshaderTxt(version);
    3714           0 :     if (shaderCaps->noperspectiveInterpolationSupport()) {
    3715           0 :         if (const char* extension = shaderCaps->noperspectiveInterpolationExtensionString()) {
    3716           0 :             fshaderTxt.appendf("#extension %s : require\n", extension);
    3717             :         }
    3718             :     }
    3719             :     GrGLSLAppendDefaultFloatPrecisionDeclaration(kMedium_GrSLPrecision, *shaderCaps,
    3720           0 :                                                  &fshaderTxt);
    3721           0 :     for (int i = 0; i < numTaps; ++i) {
    3722           0 :         vTexCoords[i].setTypeModifier(GrShaderVar::kIn_TypeModifier);
    3723           0 :         vTexCoords[i].appendDecl(shaderCaps, &fshaderTxt);
    3724           0 :         fshaderTxt.append(";");
    3725             :     }
    3726           0 :     uTexture.appendDecl(shaderCaps, &fshaderTxt);
    3727           0 :     fshaderTxt.append(";");
    3728             :     fshaderTxt.append(
    3729             :         "// Mipmap Program FS\n"
    3730             :         "void main() {"
    3731           0 :     );
    3732             : 
    3733           0 :     if (oddWidth && oddHeight) {
    3734             :         fshaderTxt.append(
    3735             :             "  sk_FragColor = (texture(u_texture, v_texCoord0) + "
    3736             :             "                  texture(u_texture, v_texCoord1) + "
    3737             :             "                  texture(u_texture, v_texCoord2) + "
    3738             :             "                  texture(u_texture, v_texCoord3)) * 0.25;"
    3739           0 :         );
    3740           0 :     } else if (oddWidth || oddHeight) {
    3741             :         fshaderTxt.append(
    3742             :             "  sk_FragColor = (texture(u_texture, v_texCoord0) + "
    3743             :             "                  texture(u_texture, v_texCoord1)) * 0.5;"
    3744           0 :         );
    3745             :     } else {
    3746             :         fshaderTxt.append(
    3747             :             "  sk_FragColor = texture(u_texture, v_texCoord0);"
    3748           0 :         );
    3749             :     }
    3750             : 
    3751           0 :     fshaderTxt.append("}");
    3752             : 
    3753             :     const char* str;
    3754             :     GrGLint length;
    3755             : 
    3756           0 :     str = vshaderTxt.c_str();
    3757           0 :     length = SkToInt(vshaderTxt.size());
    3758           0 :     SkSL::Program::Settings settings;
    3759           0 :     settings.fCaps = shaderCaps;
    3760             :     SkSL::Program::Inputs inputs;
    3761           0 :     GrGLuint vshader = GrGLCompileAndAttachShader(*fGLContext, fMipmapPrograms[progIdx].fProgram,
    3762             :                                                   GR_GL_VERTEX_SHADER, &str, &length, 1,
    3763           0 :                                                   &fStats, settings, &inputs);
    3764           0 :     SkASSERT(inputs.isEmpty());
    3765             : 
    3766           0 :     str = fshaderTxt.c_str();
    3767           0 :     length = SkToInt(fshaderTxt.size());
    3768           0 :     GrGLuint fshader = GrGLCompileAndAttachShader(*fGLContext, fMipmapPrograms[progIdx].fProgram,
    3769             :                                                   GR_GL_FRAGMENT_SHADER, &str, &length, 1,
    3770           0 :                                                   &fStats, settings, &inputs);
    3771           0 :     SkASSERT(inputs.isEmpty());
    3772             : 
    3773           0 :     GL_CALL(LinkProgram(fMipmapPrograms[progIdx].fProgram));
    3774             : 
    3775           0 :     GL_CALL_RET(fMipmapPrograms[progIdx].fTextureUniform,
    3776             :                 GetUniformLocation(fMipmapPrograms[progIdx].fProgram, "u_texture"));
    3777           0 :     GL_CALL_RET(fMipmapPrograms[progIdx].fTexCoordXformUniform,
    3778             :                 GetUniformLocation(fMipmapPrograms[progIdx].fProgram, "u_texCoordXform"));
    3779             : 
    3780           0 :     GL_CALL(BindAttribLocation(fMipmapPrograms[progIdx].fProgram, 0, "a_vertex"));
    3781             : 
    3782           0 :     GL_CALL(DeleteShader(vshader));
    3783           0 :     GL_CALL(DeleteShader(fshader));
    3784             : 
    3785           0 :     return true;
    3786             : }
    3787             : 
    3788           0 : bool GrGLGpu::createWireRectProgram() {
    3789           0 :     if (!fWireRectArrayBuffer) {
    3790             :         static const GrGLfloat vdata[] = {
    3791             :             0, 0,
    3792             :             0, 1,
    3793             :             1, 1,
    3794             :             1, 0
    3795             :         };
    3796           0 :         fWireRectArrayBuffer.reset(GrGLBuffer::Create(this, sizeof(vdata), kVertex_GrBufferType,
    3797           0 :                                                       kStatic_GrAccessPattern, vdata));
    3798           0 :         if (!fWireRectArrayBuffer) {
    3799           0 :             return false;
    3800             :         }
    3801             :     }
    3802             : 
    3803           0 :     SkASSERT(!fWireRectProgram.fProgram);
    3804           0 :     GL_CALL_RET(fWireRectProgram.fProgram, CreateProgram());
    3805           0 :     if (!fWireRectProgram.fProgram) {
    3806           0 :         return false;
    3807             :     }
    3808             : 
    3809           0 :     GrShaderVar uColor("u_color", kVec4f_GrSLType, GrShaderVar::kUniform_TypeModifier);
    3810           0 :     GrShaderVar uRect("u_rect", kVec4f_GrSLType, GrShaderVar::kUniform_TypeModifier);
    3811           0 :     GrShaderVar aVertex("a_vertex", kVec2f_GrSLType, GrShaderVar::kIn_TypeModifier);
    3812           0 :     const char* version = this->caps()->shaderCaps()->versionDeclString();
    3813             : 
    3814             :     // The rect uniform specifies the rectangle in NDC space as a vec4 (left,top,right,bottom). The
    3815             :     // program is used with a vbo containing the unit square. Vertices are computed from the rect
    3816             :     // uniform using the 4 vbo vertices.
    3817           0 :     SkString vshaderTxt(version);
    3818           0 :     aVertex.appendDecl(this->caps()->shaderCaps(), &vshaderTxt);
    3819           0 :     vshaderTxt.append(";");
    3820           0 :     uRect.appendDecl(this->caps()->shaderCaps(), &vshaderTxt);
    3821           0 :     vshaderTxt.append(";");
    3822             :     vshaderTxt.append(
    3823             :         "// Wire Rect Program VS\n"
    3824             :         "void main() {"
    3825             :         "  gl_Position.x = u_rect.x + a_vertex.x * (u_rect.z - u_rect.x);"
    3826             :         "  gl_Position.y = u_rect.y + a_vertex.y * (u_rect.w - u_rect.y);"
    3827             :         "  gl_Position.zw = vec2(0, 1);"
    3828             :         "}"
    3829           0 :     );
    3830             : 
    3831           0 :     GrShaderVar oFragColor("o_FragColor", kVec4f_GrSLType, GrShaderVar::kOut_TypeModifier);
    3832             : 
    3833           0 :     SkString fshaderTxt(version);
    3834             :     GrGLSLAppendDefaultFloatPrecisionDeclaration(kMedium_GrSLPrecision,
    3835           0 :                                                  *this->caps()->shaderCaps(),
    3836           0 :                                                  &fshaderTxt);
    3837           0 :     uColor.appendDecl(this->caps()->shaderCaps(), &fshaderTxt);
    3838           0 :     fshaderTxt.append(";");
    3839           0 :     fshaderTxt.appendf(
    3840             :         "// Write Rect Program FS\n"
    3841             :         "void main() {"
    3842             :         "  sk_FragColor = %s;"
    3843             :         "}",
    3844             :         uColor.c_str()
    3845           0 :     );
    3846             : 
    3847             :     const char* str;
    3848             :     GrGLint length;
    3849             : 
    3850           0 :     str = vshaderTxt.c_str();
    3851           0 :     length = SkToInt(vshaderTxt.size());
    3852           0 :     SkSL::Program::Settings settings;
    3853           0 :     settings.fCaps = this->caps()->shaderCaps();
    3854             :     SkSL::Program::Inputs inputs;
    3855           0 :     GrGLuint vshader = GrGLCompileAndAttachShader(*fGLContext, fWireRectProgram.fProgram,
    3856             :                                                   GR_GL_VERTEX_SHADER, &str, &length, 1,
    3857           0 :                                                   &fStats, settings, &inputs);
    3858           0 :     SkASSERT(inputs.isEmpty());
    3859             : 
    3860           0 :     str = fshaderTxt.c_str();
    3861           0 :     length = SkToInt(fshaderTxt.size());
    3862           0 :     GrGLuint fshader = GrGLCompileAndAttachShader(*fGLContext, fWireRectProgram.fProgram,
    3863             :                                                   GR_GL_FRAGMENT_SHADER, &str, &length, 1,
    3864           0 :                                                   &fStats, settings, &inputs);
    3865           0 :     SkASSERT(inputs.isEmpty());
    3866             : 
    3867           0 :     GL_CALL(LinkProgram(fWireRectProgram.fProgram));
    3868             : 
    3869           0 :     GL_CALL_RET(fWireRectProgram.fColorUniform,
    3870             :                 GetUniformLocation(fWireRectProgram.fProgram, "u_color"));
    3871           0 :     GL_CALL_RET(fWireRectProgram.fRectUniform,
    3872             :                 GetUniformLocation(fWireRectProgram.fProgram, "u_rect"));
    3873           0 :     GL_CALL(BindAttribLocation(fWireRectProgram.fProgram, 0, "a_vertex"));
    3874             : 
    3875           0 :     GL_CALL(DeleteShader(vshader));
    3876           0 :     GL_CALL(DeleteShader(fshader));
    3877             : 
    3878           0 :     return true;
    3879             : }
    3880             : 
    3881           0 : void GrGLGpu::drawDebugWireRect(GrRenderTarget* rt, const SkIRect& rect, GrColor color) {
    3882             :     // TODO: This should swizzle the output to match dst's config, though it is a debugging
    3883             :     // visualization.
    3884             : 
    3885           0 :     this->handleDirtyContext();
    3886           0 :     if (!fWireRectProgram.fProgram) {
    3887           0 :         if (!this->createWireRectProgram()) {
    3888           0 :             SkDebugf("Failed to create wire rect program.\n");
    3889           0 :             return;
    3890             :         }
    3891             :     }
    3892             : 
    3893           0 :     int w = rt->width();
    3894           0 :     int h = rt->height();
    3895             : 
    3896             :     // Compute the edges of the rectangle (top,left,right,bottom) in NDC space. Must consider
    3897             :     // whether the render target is flipped or not.
    3898             :     GrGLfloat edges[4];
    3899           0 :     edges[0] = SkIntToScalar(rect.fLeft) + 0.5f;
    3900           0 :     edges[2] = SkIntToScalar(rect.fRight) - 0.5f;
    3901           0 :     if (kBottomLeft_GrSurfaceOrigin == rt->origin()) {
    3902           0 :         edges[1] = h - (SkIntToScalar(rect.fTop) + 0.5f);
    3903           0 :         edges[3] = h - (SkIntToScalar(rect.fBottom) - 0.5f);
    3904             :     } else {
    3905           0 :         edges[1] = SkIntToScalar(rect.fTop) + 0.5f;
    3906           0 :         edges[3] = SkIntToScalar(rect.fBottom) - 0.5f;
    3907             :     }
    3908           0 :     edges[0] = 2 * edges[0] / w - 1.0f;
    3909           0 :     edges[1] = 2 * edges[1] / h - 1.0f;
    3910           0 :     edges[2] = 2 * edges[2] / w - 1.0f;
    3911           0 :     edges[3] = 2 * edges[3] / h - 1.0f;
    3912             : 
    3913             :     GrGLfloat channels[4];
    3914             :     static const GrGLfloat scale255 = 1.f / 255.f;
    3915           0 :     channels[0] = GrColorUnpackR(color) * scale255;
    3916           0 :     channels[1] = GrColorUnpackG(color) * scale255;
    3917           0 :     channels[2] = GrColorUnpackB(color) * scale255;
    3918           0 :     channels[3] = GrColorUnpackA(color) * scale255;
    3919             : 
    3920           0 :     GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(rt->asRenderTarget());
    3921           0 :     this->flushRenderTarget(glRT, &rect);
    3922             : 
    3923           0 :     GL_CALL(UseProgram(fWireRectProgram.fProgram));
    3924           0 :     fHWProgramID = fWireRectProgram.fProgram;
    3925             : 
    3926           0 :     fHWVertexArrayState.setVertexArrayID(this, 0);
    3927             : 
    3928           0 :     GrGLAttribArrayState* attribs = fHWVertexArrayState.bindInternalVertexArray(this);
    3929           0 :     attribs->set(this, 0, fWireRectArrayBuffer.get(), kVec2f_GrVertexAttribType,
    3930           0 :                  2 * sizeof(GrGLfloat), 0);
    3931           0 :     attribs->disableUnusedArrays(this, 0x1);
    3932             : 
    3933           0 :     GL_CALL(Uniform4fv(fWireRectProgram.fRectUniform, 1, edges));
    3934           0 :     GL_CALL(Uniform4fv(fWireRectProgram.fColorUniform, 1, channels));
    3935             : 
    3936             :     GrXferProcessor::BlendInfo blendInfo;
    3937           0 :     blendInfo.reset();
    3938           0 :     this->flushBlend(blendInfo, GrSwizzle::RGBA());
    3939           0 :     this->flushColorWrite(true);
    3940           0 :     this->flushDrawFace(GrDrawFace::kBoth);
    3941           0 :     this->flushHWAAState(glRT, false, false);
    3942           0 :     this->disableScissor();
    3943           0 :     this->disableWindowRectangles();
    3944           0 :     this->disableStencil();
    3945             : 
    3946           0 :     GL_CALL(DrawArrays(GR_GL_LINE_LOOP, 0, 4));
    3947             : }
    3948             : 
    3949             : 
    3950           0 : bool GrGLGpu::copySurfaceAsDraw(GrSurface* dst,
    3951             :                                 GrSurface* src,
    3952             :                                 const SkIRect& srcRect,
    3953             :                                 const SkIPoint& dstPoint) {
    3954           0 :     GrGLTexture* srcTex = static_cast<GrGLTexture*>(src->asTexture());
    3955           0 :     int progIdx = TextureToCopyProgramIdx(srcTex);
    3956             : 
    3957           0 :     if (!fCopyPrograms[progIdx].fProgram) {
    3958           0 :         if (!this->createCopyProgram(srcTex)) {
    3959           0 :             SkDebugf("Failed to create copy program.\n");
    3960           0 :             return false;
    3961             :         }
    3962             :     }
    3963             : 
    3964           0 :     int w = srcRect.width();
    3965           0 :     int h = srcRect.height();
    3966             : 
    3967           0 :     GrSamplerParams params(SkShader::kClamp_TileMode, GrSamplerParams::kNone_FilterMode);
    3968           0 :     this->bindTexture(0, params, true, srcTex);
    3969             : 
    3970             :     GrGLIRect dstVP;
    3971           0 :     this->bindSurfaceFBOForPixelOps(dst, GR_GL_FRAMEBUFFER, &dstVP, kDst_TempFBOTarget);
    3972           0 :     this->flushViewport(dstVP);
    3973           0 :     fHWBoundRenderTargetUniqueID.makeInvalid();
    3974             : 
    3975           0 :     SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY, w, h);
    3976             : 
    3977           0 :     GL_CALL(UseProgram(fCopyPrograms[progIdx].fProgram));
    3978           0 :     fHWProgramID = fCopyPrograms[progIdx].fProgram;
    3979             : 
    3980           0 :     fHWVertexArrayState.setVertexArrayID(this, 0);
    3981             : 
    3982           0 :     GrGLAttribArrayState* attribs = fHWVertexArrayState.bindInternalVertexArray(this);
    3983           0 :     attribs->set(this, 0, fCopyProgramArrayBuffer.get(), kVec2f_GrVertexAttribType,
    3984           0 :                  2 * sizeof(GrGLfloat), 0);
    3985           0 :     attribs->disableUnusedArrays(this, 0x1);
    3986             : 
    3987             :     // dst rect edges in NDC (-1 to 1)
    3988           0 :     int dw = dst->width();
    3989           0 :     int dh = dst->height();
    3990           0 :     GrGLfloat dx0 = 2.f * dstPoint.fX / dw - 1.f;
    3991           0 :     GrGLfloat dx1 = 2.f * (dstPoint.fX + w) / dw - 1.f;
    3992           0 :     GrGLfloat dy0 = 2.f * dstPoint.fY / dh - 1.f;
    3993           0 :     GrGLfloat dy1 = 2.f * (dstPoint.fY + h) / dh - 1.f;
    3994           0 :     if (kBottomLeft_GrSurfaceOrigin == dst->origin()) {
    3995           0 :         dy0 = -dy0;
    3996           0 :         dy1 = -dy1;
    3997             :     }
    3998             : 
    3999           0 :     GrGLfloat sx0 = (GrGLfloat)srcRect.fLeft;
    4000           0 :     GrGLfloat sx1 = (GrGLfloat)(srcRect.fLeft + w);
    4001           0 :     GrGLfloat sy0 = (GrGLfloat)srcRect.fTop;
    4002           0 :     GrGLfloat sy1 = (GrGLfloat)(srcRect.fTop + h);
    4003           0 :     int sh = src->height();
    4004           0 :     if (kBottomLeft_GrSurfaceOrigin == src->origin()) {
    4005           0 :         sy0 = sh - sy0;
    4006           0 :         sy1 = sh - sy1;
    4007             :     }
    4008             :     // src rect edges in normalized texture space (0 to 1) unless we're using a RECTANGLE texture.
    4009           0 :     GrGLenum srcTarget = srcTex->target();
    4010           0 :     if (GR_GL_TEXTURE_RECTANGLE != srcTarget) {
    4011           0 :         int sw = src->width();
    4012           0 :         sx0 /= sw;
    4013           0 :         sx1 /= sw;
    4014           0 :         sy0 /= sh;
    4015           0 :         sy1 /= sh;
    4016             :     }
    4017             : 
    4018           0 :     GL_CALL(Uniform4f(fCopyPrograms[progIdx].fPosXformUniform, dx1 - dx0, dy1 - dy0, dx0, dy0));
    4019           0 :     GL_CALL(Uniform4f(fCopyPrograms[progIdx].fTexCoordXformUniform,
    4020             :                       sx1 - sx0, sy1 - sy0, sx0, sy0));
    4021           0 :     GL_CALL(Uniform1i(fCopyPrograms[progIdx].fTextureUniform, 0));
    4022             : 
    4023             :     GrXferProcessor::BlendInfo blendInfo;
    4024           0 :     blendInfo.reset();
    4025           0 :     this->flushBlend(blendInfo, GrSwizzle::RGBA());
    4026           0 :     this->flushColorWrite(true);
    4027           0 :     this->flushDrawFace(GrDrawFace::kBoth);
    4028           0 :     this->flushHWAAState(nullptr, false, false);
    4029           0 :     this->disableScissor();
    4030           0 :     this->disableWindowRectangles();
    4031           0 :     this->disableStencil();
    4032             : 
    4033           0 :     GL_CALL(DrawArrays(GR_GL_TRIANGLE_STRIP, 0, 4));
    4034           0 :     this->unbindTextureFBOForPixelOps(GR_GL_FRAMEBUFFER, dst);
    4035           0 :     this->didWriteToSurface(dst, &dstRect);
    4036             : 
    4037           0 :     return true;
    4038             : }
    4039             : 
    4040           0 : void GrGLGpu::copySurfaceAsCopyTexSubImage(GrSurface* dst,
    4041             :                                            GrSurface* src,
    4042             :                                            const SkIRect& srcRect,
    4043             :                                            const SkIPoint& dstPoint) {
    4044           0 :     SkASSERT(can_copy_texsubimage(dst, src, this));
    4045             :     GrGLIRect srcVP;
    4046           0 :     this->bindSurfaceFBOForPixelOps(src, GR_GL_FRAMEBUFFER, &srcVP, kSrc_TempFBOTarget);
    4047           0 :     GrGLTexture* dstTex = static_cast<GrGLTexture *>(dst->asTexture());
    4048           0 :     SkASSERT(dstTex);
    4049             :     // We modified the bound FBO
    4050           0 :     fHWBoundRenderTargetUniqueID.makeInvalid();
    4051             :     GrGLIRect srcGLRect;
    4052           0 :     srcGLRect.setRelativeTo(srcVP,
    4053           0 :                             srcRect.fLeft,
    4054           0 :                             srcRect.fTop,
    4055             :                             srcRect.width(),
    4056             :                             srcRect.height(),
    4057           0 :                             src->origin());
    4058             : 
    4059           0 :     this->setScratchTextureUnit();
    4060           0 :     GL_CALL(BindTexture(dstTex->target(), dstTex->textureID()));
    4061             :     GrGLint dstY;
    4062           0 :     if (kBottomLeft_GrSurfaceOrigin == dst->origin()) {
    4063           0 :         dstY = dst->height() - (dstPoint.fY + srcGLRect.fHeight);
    4064             :     } else {
    4065           0 :         dstY = dstPoint.fY;
    4066             :     }
    4067           0 :     GL_CALL(CopyTexSubImage2D(dstTex->target(), 0,
    4068             :                               dstPoint.fX, dstY,
    4069             :                               srcGLRect.fLeft, srcGLRect.fBottom,
    4070             :                               srcGLRect.fWidth, srcGLRect.fHeight));
    4071           0 :     this->unbindTextureFBOForPixelOps(GR_GL_FRAMEBUFFER, src);
    4072           0 :     SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY,
    4073           0 :                                         srcRect.width(), srcRect.height());
    4074           0 :     this->didWriteToSurface(dst, &dstRect);
    4075           0 : }
    4076             : 
    4077           0 : bool GrGLGpu::copySurfaceAsBlitFramebuffer(GrSurface* dst,
    4078             :                                            GrSurface* src,
    4079             :                                            const SkIRect& srcRect,
    4080             :                                            const SkIPoint& dstPoint) {
    4081           0 :     SkASSERT(can_blit_framebuffer_for_copy_surface(dst, src, srcRect, dstPoint, this));
    4082           0 :     SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY,
    4083           0 :                                         srcRect.width(), srcRect.height());
    4084           0 :     if (dst == src) {
    4085           0 :         if (SkIRect::IntersectsNoEmptyCheck(dstRect, srcRect)) {
    4086           0 :             return false;
    4087             :         }
    4088             :     }
    4089             : 
    4090             :     GrGLIRect dstVP;
    4091             :     GrGLIRect srcVP;
    4092           0 :     this->bindSurfaceFBOForPixelOps(dst, GR_GL_DRAW_FRAMEBUFFER, &dstVP, kDst_TempFBOTarget);
    4093           0 :     this->bindSurfaceFBOForPixelOps(src, GR_GL_READ_FRAMEBUFFER, &srcVP, kSrc_TempFBOTarget);
    4094             :     // We modified the bound FBO
    4095           0 :     fHWBoundRenderTargetUniqueID.makeInvalid();
    4096             :     GrGLIRect srcGLRect;
    4097             :     GrGLIRect dstGLRect;
    4098           0 :     srcGLRect.setRelativeTo(srcVP,
    4099           0 :                             srcRect.fLeft,
    4100           0 :                             srcRect.fTop,
    4101             :                             srcRect.width(),
    4102             :                             srcRect.height(),
    4103           0 :                             src->origin());
    4104           0 :     dstGLRect.setRelativeTo(dstVP,
    4105             :                             dstRect.fLeft,
    4106             :                             dstRect.fTop,
    4107             :                             dstRect.width(),
    4108             :                             dstRect.height(),
    4109           0 :                             dst->origin());
    4110             : 
    4111             :     // BlitFrameBuffer respects the scissor, so disable it.
    4112           0 :     this->disableScissor();
    4113           0 :     this->disableWindowRectangles();
    4114             : 
    4115             :     GrGLint srcY0;
    4116             :     GrGLint srcY1;
    4117             :     // Does the blit need to y-mirror or not?
    4118           0 :     if (src->origin() == dst->origin()) {
    4119           0 :         srcY0 = srcGLRect.fBottom;
    4120           0 :         srcY1 = srcGLRect.fBottom + srcGLRect.fHeight;
    4121             :     } else {
    4122           0 :         srcY0 = srcGLRect.fBottom + srcGLRect.fHeight;
    4123           0 :         srcY1 = srcGLRect.fBottom;
    4124             :     }
    4125           0 :     GL_CALL(BlitFramebuffer(srcGLRect.fLeft,
    4126             :                             srcY0,
    4127             :                             srcGLRect.fLeft + srcGLRect.fWidth,
    4128             :                             srcY1,
    4129             :                             dstGLRect.fLeft,
    4130             :                             dstGLRect.fBottom,
    4131             :                             dstGLRect.fLeft + dstGLRect.fWidth,
    4132             :                             dstGLRect.fBottom + dstGLRect.fHeight,
    4133             :                             GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST));
    4134           0 :     this->unbindTextureFBOForPixelOps(GR_GL_DRAW_FRAMEBUFFER, dst);
    4135           0 :     this->unbindTextureFBOForPixelOps(GR_GL_READ_FRAMEBUFFER, src);
    4136           0 :     this->didWriteToSurface(dst, &dstRect);
    4137           0 :     return true;
    4138             : }
    4139             : 
    4140             : // Manual implementation of mipmap generation, to work around driver bugs w/sRGB.
    4141             : // Uses draw calls to do a series of downsample operations to successive mips.
    4142             : // If this returns false, then the calling code falls back to using glGenerateMipmap.
    4143           0 : bool GrGLGpu::generateMipmap(GrGLTexture* texture, bool gammaCorrect) {
    4144           0 :     SkASSERT(!GrPixelConfigIsSint(texture->config()));
    4145             :     // Our iterative downsample requires the ability to limit which level we're sampling:
    4146           0 :     if (!this->glCaps().doManualMipmapping()) {
    4147           0 :         return false;
    4148             :     }
    4149             : 
    4150             :     // Mipmaps are only supported on 2D textures:
    4151           0 :     if (GR_GL_TEXTURE_2D != texture->target()) {
    4152           0 :         return false;
    4153             :     }
    4154             : 
    4155             :     // We need to be able to render to the texture for this to work:
    4156           0 :     if (!this->glCaps().canConfigBeFBOColorAttachment(texture->config())) {
    4157           0 :         return false;
    4158             :     }
    4159             : 
    4160             :     // If we're mipping an sRGB texture, we need to ensure FB sRGB is correct:
    4161           0 :     if (GrPixelConfigIsSRGB(texture->config())) {
    4162             :         // If we have write-control, just set the state that we want:
    4163           0 :         if (this->glCaps().srgbWriteControl()) {
    4164           0 :             this->flushFramebufferSRGB(gammaCorrect);
    4165           0 :         } else if (!gammaCorrect) {
    4166             :             // If we don't have write-control we can't do non-gamma-correct mipmapping:
    4167           0 :             return false;
    4168             :         }
    4169             :     }
    4170             : 
    4171           0 :     int width = texture->width();
    4172           0 :     int height = texture->height();
    4173           0 :     int levelCount = SkMipMap::ComputeLevelCount(width, height) + 1;
    4174             : 
    4175             :     // Define all mips, if we haven't previously done so:
    4176           0 :     if (0 == texture->texturePriv().maxMipMapLevel()) {
    4177             :         GrGLenum internalFormat;
    4178             :         GrGLenum externalFormat;
    4179             :         GrGLenum externalType;
    4180           0 :         if (!this->glCaps().getTexImageFormats(texture->config(), texture->config(),
    4181             :                                                &internalFormat, &externalFormat, &externalType)) {
    4182           0 :             return false;
    4183             :         }
    4184             : 
    4185           0 :         for (GrGLint level = 1; level < levelCount; ++level) {
    4186             :             // Define the next mip:
    4187           0 :             width = SkTMax(1, width / 2);
    4188           0 :             height = SkTMax(1, height / 2);
    4189           0 :             GL_ALLOC_CALL(this->glInterface(), TexImage2D(GR_GL_TEXTURE_2D, level, internalFormat,
    4190             :                                                           width, height, 0,
    4191             :                                                           externalFormat, externalType, nullptr));
    4192             :         }
    4193             :     }
    4194             : 
    4195             :     // Create (if necessary), then bind temporary FBO:
    4196           0 :     if (0 == fTempDstFBOID) {
    4197           0 :         GL_CALL(GenFramebuffers(1, &fTempDstFBOID));
    4198             :     }
    4199           0 :     GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, fTempDstFBOID));
    4200           0 :     fHWBoundRenderTargetUniqueID.makeInvalid();
    4201             : 
    4202             :     // Bind the texture, to get things configured for filtering.
    4203             :     // We'll be changing our base level further below:
    4204           0 :     this->setTextureUnit(0);
    4205           0 :     GrSamplerParams params(SkShader::kClamp_TileMode, GrSamplerParams::kBilerp_FilterMode);
    4206           0 :     this->bindTexture(0, params, gammaCorrect, texture);
    4207             : 
    4208             :     // Vertex data:
    4209           0 :     if (!fMipmapProgramArrayBuffer) {
    4210             :         static const GrGLfloat vdata[] = {
    4211             :             0, 0,
    4212             :             0, 1,
    4213             :             1, 0,
    4214             :             1, 1
    4215             :         };
    4216           0 :         fMipmapProgramArrayBuffer.reset(GrGLBuffer::Create(this, sizeof(vdata),
    4217             :                                                            kVertex_GrBufferType,
    4218           0 :                                                            kStatic_GrAccessPattern, vdata));
    4219             :     }
    4220           0 :     if (!fMipmapProgramArrayBuffer) {
    4221           0 :         return false;
    4222             :     }
    4223             : 
    4224           0 :     fHWVertexArrayState.setVertexArrayID(this, 0);
    4225             : 
    4226           0 :     GrGLAttribArrayState* attribs = fHWVertexArrayState.bindInternalVertexArray(this);
    4227           0 :     attribs->set(this, 0, fMipmapProgramArrayBuffer.get(), kVec2f_GrVertexAttribType,
    4228           0 :                  2 * sizeof(GrGLfloat), 0);
    4229           0 :     attribs->disableUnusedArrays(this, 0x1);
    4230             : 
    4231             :     // Set "simple" state once:
    4232             :     GrXferProcessor::BlendInfo blendInfo;
    4233           0 :     blendInfo.reset();
    4234           0 :     this->flushBlend(blendInfo, GrSwizzle::RGBA());
    4235           0 :     this->flushColorWrite(true);
    4236           0 :     this->flushDrawFace(GrDrawFace::kBoth);
    4237           0 :     this->flushHWAAState(nullptr, false, false);
    4238           0 :     this->disableScissor();
    4239           0 :     this->disableWindowRectangles();
    4240           0 :     this->disableStencil();
    4241             : 
    4242             :     // Do all the blits:
    4243           0 :     width = texture->width();
    4244           0 :     height = texture->height();
    4245             :     GrGLIRect viewport;
    4246           0 :     viewport.fLeft = 0;
    4247           0 :     viewport.fBottom = 0;
    4248           0 :     for (GrGLint level = 1; level < levelCount; ++level) {
    4249             :         // Get and bind the program for this particular downsample (filter shape can vary):
    4250           0 :         int progIdx = TextureSizeToMipmapProgramIdx(width, height);
    4251           0 :         if (!fMipmapPrograms[progIdx].fProgram) {
    4252           0 :             if (!this->createMipmapProgram(progIdx)) {
    4253           0 :                 SkDebugf("Failed to create mipmap program.\n");
    4254           0 :                 return false;
    4255             :             }
    4256             :         }
    4257           0 :         GL_CALL(UseProgram(fMipmapPrograms[progIdx].fProgram));
    4258           0 :         fHWProgramID = fMipmapPrograms[progIdx].fProgram;
    4259             : 
    4260             :         // Texcoord uniform is expected to contain (1/w, (w-1)/w, 1/h, (h-1)/h)
    4261           0 :         const float invWidth = 1.0f / width;
    4262           0 :         const float invHeight = 1.0f / height;
    4263           0 :         GL_CALL(Uniform4f(fMipmapPrograms[progIdx].fTexCoordXformUniform,
    4264             :                           invWidth, (width - 1) * invWidth, invHeight, (height - 1) * invHeight));
    4265           0 :         GL_CALL(Uniform1i(fMipmapPrograms[progIdx].fTextureUniform, 0));
    4266             : 
    4267             :         // Only sample from previous mip
    4268           0 :         GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_BASE_LEVEL, level - 1));
    4269             : 
    4270           0 :         GL_CALL(FramebufferTexture2D(GR_GL_FRAMEBUFFER, GR_GL_COLOR_ATTACHMENT0,
    4271             :                                      GR_GL_TEXTURE_2D, texture->textureID(), level));
    4272             : 
    4273           0 :         width = SkTMax(1, width / 2);
    4274           0 :         height = SkTMax(1, height / 2);
    4275           0 :         viewport.fWidth = width;
    4276           0 :         viewport.fHeight = height;
    4277           0 :         this->flushViewport(viewport);
    4278             : 
    4279           0 :         GL_CALL(DrawArrays(GR_GL_TRIANGLE_STRIP, 0, 4));
    4280             :     }
    4281             : 
    4282             :     // Unbind:
    4283           0 :     GL_CALL(FramebufferTexture2D(GR_GL_FRAMEBUFFER, GR_GL_COLOR_ATTACHMENT0,
    4284             :                                  GR_GL_TEXTURE_2D, 0, 0));
    4285             : 
    4286           0 :     return true;
    4287             : }
    4288             : 
    4289           0 : void GrGLGpu::onQueryMultisampleSpecs(GrRenderTarget* rt, const GrStencilSettings& stencil,
    4290             :                                       int* effectiveSampleCnt, SamplePattern* samplePattern) {
    4291           0 :     SkASSERT(!rt->isMixedSampled() || rt->renderTargetPriv().getStencilAttachment() ||
    4292             :              stencil.isDisabled());
    4293             : 
    4294           0 :     this->flushStencil(stencil);
    4295           0 :     this->flushHWAAState(rt, true, !stencil.isDisabled());
    4296           0 :     this->flushRenderTarget(static_cast<GrGLRenderTarget*>(rt), &SkIRect::EmptyIRect());
    4297             : 
    4298           0 :     if (0 != this->caps()->maxRasterSamples()) {
    4299           0 :         GR_GL_GetIntegerv(this->glInterface(), GR_GL_EFFECTIVE_RASTER_SAMPLES, effectiveSampleCnt);
    4300             :     } else {
    4301           0 :         GR_GL_GetIntegerv(this->glInterface(), GR_GL_SAMPLES, effectiveSampleCnt);
    4302             :     }
    4303             : 
    4304           0 :     SkASSERT(*effectiveSampleCnt >= rt->desc().fSampleCnt);
    4305             : 
    4306           0 :     if (this->caps()->sampleLocationsSupport()) {
    4307           0 :         samplePattern->reset(*effectiveSampleCnt);
    4308           0 :         for (int i = 0; i < *effectiveSampleCnt; ++i) {
    4309             :             GrGLfloat pos[2];
    4310           0 :             GL_CALL(GetMultisamplefv(GR_GL_SAMPLE_POSITION, i, pos));
    4311           0 :             if (kTopLeft_GrSurfaceOrigin == rt->origin()) {
    4312           0 :                 (*samplePattern)[i].set(pos[0], pos[1]);
    4313             :             } else {
    4314           0 :                 (*samplePattern)[i].set(pos[0], 1 - pos[1]);
    4315             :             }
    4316             :         }
    4317             :     }
    4318           0 : }
    4319             : 
    4320           0 : void GrGLGpu::xferBarrier(GrRenderTarget* rt, GrXferBarrierType type) {
    4321           0 :     SkASSERT(type);
    4322           0 :     switch (type) {
    4323             :         case kTexture_GrXferBarrierType: {
    4324           0 :             GrGLRenderTarget* glrt = static_cast<GrGLRenderTarget*>(rt);
    4325           0 :             if (glrt->textureFBOID() != glrt->renderFBOID()) {
    4326             :                 // The render target uses separate storage so no need for glTextureBarrier.
    4327             :                 // FIXME: The render target will resolve automatically when its texture is bound,
    4328             :                 // but we could resolve only the bounds that will be read if we do it here instead.
    4329           0 :                 return;
    4330             :             }
    4331           0 :             SkASSERT(this->caps()->textureBarrierSupport());
    4332           0 :             GL_CALL(TextureBarrier());
    4333           0 :             return;
    4334             :         }
    4335             :         case kBlend_GrXferBarrierType:
    4336           0 :             SkASSERT(GrCaps::kAdvanced_BlendEquationSupport ==
    4337             :                      this->caps()->blendEquationSupport());
    4338           0 :             GL_CALL(BlendBarrier());
    4339           0 :             return;
    4340           0 :         default: break; // placate compiler warnings that kNone not handled
    4341             :     }
    4342             : }
    4343             : 
    4344           0 : GrBackendObject GrGLGpu::createTestingOnlyBackendTexture(void* pixels, int w, int h,
    4345             :                                                          GrPixelConfig config, bool /*isRT*/) {
    4346           0 :     if (!this->caps()->isConfigTexturable(config)) {
    4347           0 :         return false;
    4348             :     }
    4349           0 :     std::unique_ptr<GrGLTextureInfo> info = skstd::make_unique<GrGLTextureInfo>();
    4350           0 :     info->fTarget = GR_GL_TEXTURE_2D;
    4351           0 :     info->fID = 0;
    4352           0 :     GL_CALL(GenTextures(1, &info->fID));
    4353           0 :     GL_CALL(ActiveTexture(GR_GL_TEXTURE0));
    4354           0 :     GL_CALL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, 1));
    4355           0 :     GL_CALL(BindTexture(info->fTarget, info->fID));
    4356           0 :     fHWBoundTextureUniqueIDs[0].makeInvalid();
    4357           0 :     GL_CALL(TexParameteri(info->fTarget, GR_GL_TEXTURE_MAG_FILTER, GR_GL_NEAREST));
    4358           0 :     GL_CALL(TexParameteri(info->fTarget, GR_GL_TEXTURE_MIN_FILTER, GR_GL_NEAREST));
    4359           0 :     GL_CALL(TexParameteri(info->fTarget, GR_GL_TEXTURE_WRAP_S, GR_GL_CLAMP_TO_EDGE));
    4360           0 :     GL_CALL(TexParameteri(info->fTarget, GR_GL_TEXTURE_WRAP_T, GR_GL_CLAMP_TO_EDGE));
    4361             : 
    4362             :     GrGLenum internalFormat;
    4363             :     GrGLenum externalFormat;
    4364             :     GrGLenum externalType;
    4365             : 
    4366           0 :     if (!this->glCaps().getTexImageFormats(config, config, &internalFormat, &externalFormat,
    4367             :                                            &externalType)) {
    4368           0 :         return reinterpret_cast<GrBackendObject>(nullptr);
    4369             :     }
    4370             : 
    4371           0 :     GL_CALL(TexImage2D(info->fTarget, 0, internalFormat, w, h, 0, externalFormat,
    4372             :                        externalType, pixels));
    4373             : 
    4374           0 :     return reinterpret_cast<GrBackendObject>(info.release());
    4375             : }
    4376             : 
    4377           0 : bool GrGLGpu::isTestingOnlyBackendTexture(GrBackendObject id) const {
    4378           0 :     GrGLuint texID = reinterpret_cast<const GrGLTextureInfo*>(id)->fID;
    4379             : 
    4380             :     GrGLboolean result;
    4381           0 :     GL_CALL_RET(result, IsTexture(texID));
    4382             : 
    4383           0 :     return (GR_GL_TRUE == result);
    4384             : }
    4385             : 
    4386           0 : void GrGLGpu::deleteTestingOnlyBackendTexture(GrBackendObject id, bool abandonTexture) {
    4387           0 :     std::unique_ptr<const GrGLTextureInfo> info(reinterpret_cast<const GrGLTextureInfo*>(id));
    4388           0 :     GrGLuint texID = info->fID;
    4389             : 
    4390           0 :     if (!abandonTexture) {
    4391           0 :         GL_CALL(DeleteTextures(1, &texID));
    4392             :     }
    4393           0 : }
    4394             : 
    4395           0 : void GrGLGpu::resetShaderCacheForTesting() const {
    4396           0 :     fProgramCache->abandon();
    4397           0 : }
    4398             : 
    4399             : ///////////////////////////////////////////////////////////////////////////////
    4400             : 
    4401           0 : GrGLAttribArrayState* GrGLGpu::HWVertexArrayState::bindInternalVertexArray(GrGLGpu* gpu,
    4402             :                                                                            const GrBuffer* ibuf) {
    4403             :     GrGLAttribArrayState* attribState;
    4404             : 
    4405           0 :     if (gpu->glCaps().isCoreProfile()) {
    4406           0 :         if (!fCoreProfileVertexArray) {
    4407             :             GrGLuint arrayID;
    4408           0 :             GR_GL_CALL(gpu->glInterface(), GenVertexArrays(1, &arrayID));
    4409           0 :             int attrCount = gpu->glCaps().maxVertexAttributes();
    4410           0 :             fCoreProfileVertexArray = new GrGLVertexArray(arrayID, attrCount);
    4411             :         }
    4412           0 :         if (ibuf) {
    4413           0 :             attribState = fCoreProfileVertexArray->bindWithIndexBuffer(gpu, ibuf);
    4414             :         } else {
    4415           0 :             attribState = fCoreProfileVertexArray->bind(gpu);
    4416             :         }
    4417             :     } else {
    4418           0 :         if (ibuf) {
    4419             :             // bindBuffer implicitly binds VAO 0 when binding an index buffer.
    4420           0 :             gpu->bindBuffer(kIndex_GrBufferType, ibuf);
    4421             :         } else {
    4422           0 :             this->setVertexArrayID(gpu, 0);
    4423             :         }
    4424           0 :         int attrCount = gpu->glCaps().maxVertexAttributes();
    4425           0 :         if (fDefaultVertexArrayAttribState.count() != attrCount) {
    4426           0 :             fDefaultVertexArrayAttribState.resize(attrCount);
    4427             :         }
    4428           0 :         attribState = &fDefaultVertexArrayAttribState;
    4429             :     }
    4430           0 :     return attribState;
    4431             : }
    4432             : 
    4433           0 : bool GrGLGpu::onIsACopyNeededForTextureParams(GrTextureProxy* proxy,
    4434             :                                               const GrSamplerParams& textureParams,
    4435             :                                               GrTextureProducer::CopyParams* copyParams,
    4436             :                                               SkScalar scaleAdjust[2]) const {
    4437           0 :     const GrTexture* texture = proxy->priv().peekTexture();
    4438           0 :     if (!texture) {
    4439             :         // The only way to get and EXTERNAL or RECTANGLE texture in Ganesh is to wrap them.
    4440             :         // In that case the proxy should already be instantiated.
    4441           0 :         return false;
    4442             :     }
    4443             : 
    4444           0 :     if (textureParams.isTiled() ||
    4445           0 :         GrSamplerParams::kMipMap_FilterMode == textureParams.filterMode()) {
    4446           0 :         const GrGLTexture* glTexture = static_cast<const GrGLTexture*>(texture);
    4447           0 :         if (GR_GL_TEXTURE_EXTERNAL == glTexture->target() ||
    4448           0 :             GR_GL_TEXTURE_RECTANGLE == glTexture->target()) {
    4449           0 :             copyParams->fFilter = GrSamplerParams::kNone_FilterMode;
    4450           0 :             copyParams->fWidth = texture->width();
    4451           0 :             copyParams->fHeight = texture->height();
    4452           0 :             return true;
    4453             :         }
    4454             :     }
    4455           0 :     return false;
    4456             : }
    4457             : 
    4458           0 : GrFence SK_WARN_UNUSED_RESULT GrGLGpu::insertFence() {
    4459             :     GrGLsync sync;
    4460           0 :     GL_CALL_RET(sync, FenceSync(GR_GL_SYNC_GPU_COMMANDS_COMPLETE, 0));
    4461             :     GR_STATIC_ASSERT(sizeof(GrFence) >= sizeof(GrGLsync));
    4462           0 :     return (GrFence)sync;
    4463             : }
    4464             : 
    4465           0 : bool GrGLGpu::waitFence(GrFence fence, uint64_t timeout) {
    4466             :     GrGLenum result;
    4467           0 :     GL_CALL_RET(result, ClientWaitSync((GrGLsync)fence, GR_GL_SYNC_FLUSH_COMMANDS_BIT, timeout));
    4468           0 :     return (GR_GL_CONDITION_SATISFIED == result);
    4469             : }
    4470             : 
    4471           0 : void GrGLGpu::deleteFence(GrFence fence) const {
    4472           0 :     this->deleteSync((GrGLsync)fence);
    4473           0 : }
    4474             : 
    4475           0 : sk_sp<GrSemaphore> SK_WARN_UNUSED_RESULT GrGLGpu::makeSemaphore() {
    4476           0 :     return GrGLSemaphore::Make(this);
    4477             : }
    4478             : 
    4479           0 : void GrGLGpu::insertSemaphore(sk_sp<GrSemaphore> semaphore) {
    4480           0 :     GrGLSemaphore* glSem = static_cast<GrGLSemaphore*>(semaphore.get());
    4481             : 
    4482             :     GrGLsync sync;
    4483           0 :     GL_CALL_RET(sync, FenceSync(GR_GL_SYNC_GPU_COMMANDS_COMPLETE, 0));
    4484           0 :     glSem->setSync(sync);
    4485           0 : }
    4486             : 
    4487           0 : void GrGLGpu::waitSemaphore(sk_sp<GrSemaphore> semaphore) {
    4488           0 :     GrGLSemaphore* glSem = static_cast<GrGLSemaphore*>(semaphore.get());
    4489             : 
    4490           0 :     GL_CALL(WaitSync(glSem->sync(), 0, GR_GL_TIMEOUT_IGNORED));
    4491           0 : }
    4492             : 
    4493           0 : void GrGLGpu::deleteSync(GrGLsync sync) const {
    4494           0 :     GL_CALL(DeleteSync(sync));
    4495           0 : }
    4496             : 
    4497           0 : void GrGLGpu::flush() {
    4498           0 :     GL_CALL(Flush());
    4499           0 : }

Generated by: LCOV version 1.13