xref: /aosp_15_r20/external/skia/src/gpu/ganesh/gl/GrGLGpu.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2011 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker  *
4*c8dee2aaSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker  * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker  */
7*c8dee2aaSAndroid Build Coastguard Worker 
8*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/gl/GrGLGpu.h"
9*c8dee2aaSAndroid Build Coastguard Worker 
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkAlphaType.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColor.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColorSpace.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkData.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRect.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSize.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkString.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTextureCompressionType.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypes.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/GpuTypes.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrBackendSurface.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrContextOptions.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrDirectContext.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrDriverBugWorkarounds.h"
24*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrTypes.h"
25*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/gl/GrGLConfig.h"
26*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkFloatingPoint.h"
27*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkMath.h"
28*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkPoint_impl.h"
29*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTemplates.h"
30*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTo.h"
31*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkScopeExit.h"
32*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkCompressedDataUtils.h"
33*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkLRUCache.h"
34*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkMipmap.h"
35*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkSLTypeShared.h"
36*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkTraceEvent.h"
37*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/RefCntedCallback.h"
38*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/SkRenderEngineAbortf.h"
39*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/Swizzle.h"
40*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrAttachment.h"
41*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrBackendSurfacePriv.h"
42*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrBackendUtils.h"
43*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrBuffer.h"
44*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrDataUtils.h"
45*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrDirectContextPriv.h"
46*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrGpuBuffer.h"
47*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrImageInfo.h"
48*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrPipeline.h"
49*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrProgramInfo.h"
50*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrRenderTarget.h"
51*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrSemaphore.h"
52*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrShaderCaps.h"
53*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrShaderVar.h"
54*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrStagingBufferManager.h"
55*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrSurface.h"
56*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrTexture.h"
57*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrUtil.h"
58*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrWindowRectangles.h"
59*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/gl/GrGLAttachment.h"
60*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/gl/GrGLBackendSurfacePriv.h"
61*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/gl/GrGLBuffer.h"
62*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/gl/GrGLOpsRenderPass.h"
63*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/gl/GrGLProgram.h"
64*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/gl/GrGLSemaphore.h"
65*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/gl/GrGLTextureRenderTarget.h"
66*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/gl/builders/GrGLShaderStringBuilder.h"
67*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/SkSLProgramKind.h"
68*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/SkSLProgramSettings.h"
69*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/ir/SkSLProgram.h"
70*c8dee2aaSAndroid Build Coastguard Worker 
71*c8dee2aaSAndroid Build Coastguard Worker #include <algorithm>
72*c8dee2aaSAndroid Build Coastguard Worker #include <cmath>
73*c8dee2aaSAndroid Build Coastguard Worker #include <functional>
74*c8dee2aaSAndroid Build Coastguard Worker #include <memory>
75*c8dee2aaSAndroid Build Coastguard Worker #include <string>
76*c8dee2aaSAndroid Build Coastguard Worker #include <utility>
77*c8dee2aaSAndroid Build Coastguard Worker 
78*c8dee2aaSAndroid Build Coastguard Worker using namespace skia_private;
79*c8dee2aaSAndroid Build Coastguard Worker 
80*c8dee2aaSAndroid Build Coastguard Worker #define GL_CALL(X) GR_GL_CALL(this->glInterface(), X)
81*c8dee2aaSAndroid Build Coastguard Worker #define GL_CALL_RET(RET, X) GR_GL_CALL_RET(this->glInterface(), RET, X)
82*c8dee2aaSAndroid Build Coastguard Worker 
83*c8dee2aaSAndroid Build Coastguard Worker #define GL_ALLOC_CALL(call)                                   \
84*c8dee2aaSAndroid Build Coastguard Worker     [&] {                                                     \
85*c8dee2aaSAndroid Build Coastguard Worker         if (this->glCaps().skipErrorChecks()) {               \
86*c8dee2aaSAndroid Build Coastguard Worker             GR_GL_CALL(this->glInterface(), call);            \
87*c8dee2aaSAndroid Build Coastguard Worker             return static_cast<GrGLenum>(GR_GL_NO_ERROR);     \
88*c8dee2aaSAndroid Build Coastguard Worker         } else {                                              \
89*c8dee2aaSAndroid Build Coastguard Worker             this->clearErrorsAndCheckForOOM();                \
90*c8dee2aaSAndroid Build Coastguard Worker             GR_GL_CALL_NOERRCHECK(this->glInterface(), call); \
91*c8dee2aaSAndroid Build Coastguard Worker             return this->getErrorAndCheckForOOM();            \
92*c8dee2aaSAndroid Build Coastguard Worker         }                                                     \
93*c8dee2aaSAndroid Build Coastguard Worker     }()
94*c8dee2aaSAndroid Build Coastguard Worker 
95*c8dee2aaSAndroid Build Coastguard Worker //#define USE_NSIGHT
96*c8dee2aaSAndroid Build Coastguard Worker 
97*c8dee2aaSAndroid Build Coastguard Worker ///////////////////////////////////////////////////////////////////////////////
98*c8dee2aaSAndroid Build Coastguard Worker 
99*c8dee2aaSAndroid Build Coastguard Worker static const GrGLenum gXfermodeEquation2Blend[] = {
100*c8dee2aaSAndroid Build Coastguard Worker     // Basic OpenGL blend equations.
101*c8dee2aaSAndroid Build Coastguard Worker     GR_GL_FUNC_ADD,
102*c8dee2aaSAndroid Build Coastguard Worker     GR_GL_FUNC_SUBTRACT,
103*c8dee2aaSAndroid Build Coastguard Worker     GR_GL_FUNC_REVERSE_SUBTRACT,
104*c8dee2aaSAndroid Build Coastguard Worker 
105*c8dee2aaSAndroid Build Coastguard Worker     // GL_KHR_blend_equation_advanced.
106*c8dee2aaSAndroid Build Coastguard Worker     GR_GL_SCREEN,
107*c8dee2aaSAndroid Build Coastguard Worker     GR_GL_OVERLAY,
108*c8dee2aaSAndroid Build Coastguard Worker     GR_GL_DARKEN,
109*c8dee2aaSAndroid Build Coastguard Worker     GR_GL_LIGHTEN,
110*c8dee2aaSAndroid Build Coastguard Worker     GR_GL_COLORDODGE,
111*c8dee2aaSAndroid Build Coastguard Worker     GR_GL_COLORBURN,
112*c8dee2aaSAndroid Build Coastguard Worker     GR_GL_HARDLIGHT,
113*c8dee2aaSAndroid Build Coastguard Worker     GR_GL_SOFTLIGHT,
114*c8dee2aaSAndroid Build Coastguard Worker     GR_GL_DIFFERENCE,
115*c8dee2aaSAndroid Build Coastguard Worker     GR_GL_EXCLUSION,
116*c8dee2aaSAndroid Build Coastguard Worker     GR_GL_MULTIPLY,
117*c8dee2aaSAndroid Build Coastguard Worker     GR_GL_HSL_HUE,
118*c8dee2aaSAndroid Build Coastguard Worker     GR_GL_HSL_SATURATION,
119*c8dee2aaSAndroid Build Coastguard Worker     GR_GL_HSL_COLOR,
120*c8dee2aaSAndroid Build Coastguard Worker     GR_GL_HSL_LUMINOSITY,
121*c8dee2aaSAndroid Build Coastguard Worker 
122*c8dee2aaSAndroid Build Coastguard Worker     // Illegal... needs to map to something.
123*c8dee2aaSAndroid Build Coastguard Worker     GR_GL_FUNC_ADD,
124*c8dee2aaSAndroid Build Coastguard Worker };
125*c8dee2aaSAndroid Build Coastguard Worker static_assert(0 == (int)skgpu::BlendEquation::kAdd);
126*c8dee2aaSAndroid Build Coastguard Worker static_assert(1 == (int)skgpu::BlendEquation::kSubtract);
127*c8dee2aaSAndroid Build Coastguard Worker static_assert(2 == (int)skgpu::BlendEquation::kReverseSubtract);
128*c8dee2aaSAndroid Build Coastguard Worker static_assert(3 == (int)skgpu::BlendEquation::kScreen);
129*c8dee2aaSAndroid Build Coastguard Worker static_assert(4 == (int)skgpu::BlendEquation::kOverlay);
130*c8dee2aaSAndroid Build Coastguard Worker static_assert(5 == (int)skgpu::BlendEquation::kDarken);
131*c8dee2aaSAndroid Build Coastguard Worker static_assert(6 == (int)skgpu::BlendEquation::kLighten);
132*c8dee2aaSAndroid Build Coastguard Worker static_assert(7 == (int)skgpu::BlendEquation::kColorDodge);
133*c8dee2aaSAndroid Build Coastguard Worker static_assert(8 == (int)skgpu::BlendEquation::kColorBurn);
134*c8dee2aaSAndroid Build Coastguard Worker static_assert(9 == (int)skgpu::BlendEquation::kHardLight);
135*c8dee2aaSAndroid Build Coastguard Worker static_assert(10 == (int)skgpu::BlendEquation::kSoftLight);
136*c8dee2aaSAndroid Build Coastguard Worker static_assert(11 == (int)skgpu::BlendEquation::kDifference);
137*c8dee2aaSAndroid Build Coastguard Worker static_assert(12 == (int)skgpu::BlendEquation::kExclusion);
138*c8dee2aaSAndroid Build Coastguard Worker static_assert(13 == (int)skgpu::BlendEquation::kMultiply);
139*c8dee2aaSAndroid Build Coastguard Worker static_assert(14 == (int)skgpu::BlendEquation::kHSLHue);
140*c8dee2aaSAndroid Build Coastguard Worker static_assert(15 == (int)skgpu::BlendEquation::kHSLSaturation);
141*c8dee2aaSAndroid Build Coastguard Worker static_assert(16 == (int)skgpu::BlendEquation::kHSLColor);
142*c8dee2aaSAndroid Build Coastguard Worker static_assert(17 == (int)skgpu::BlendEquation::kHSLLuminosity);
143*c8dee2aaSAndroid Build Coastguard Worker static_assert(std::size(gXfermodeEquation2Blend) == skgpu::kBlendEquationCnt);
144*c8dee2aaSAndroid Build Coastguard Worker 
145*c8dee2aaSAndroid Build Coastguard Worker static const GrGLenum gXfermodeCoeff2Blend[] = {
146*c8dee2aaSAndroid Build Coastguard Worker     GR_GL_ZERO,
147*c8dee2aaSAndroid Build Coastguard Worker     GR_GL_ONE,
148*c8dee2aaSAndroid Build Coastguard Worker     GR_GL_SRC_COLOR,
149*c8dee2aaSAndroid Build Coastguard Worker     GR_GL_ONE_MINUS_SRC_COLOR,
150*c8dee2aaSAndroid Build Coastguard Worker     GR_GL_DST_COLOR,
151*c8dee2aaSAndroid Build Coastguard Worker     GR_GL_ONE_MINUS_DST_COLOR,
152*c8dee2aaSAndroid Build Coastguard Worker     GR_GL_SRC_ALPHA,
153*c8dee2aaSAndroid Build Coastguard Worker     GR_GL_ONE_MINUS_SRC_ALPHA,
154*c8dee2aaSAndroid Build Coastguard Worker     GR_GL_DST_ALPHA,
155*c8dee2aaSAndroid Build Coastguard Worker     GR_GL_ONE_MINUS_DST_ALPHA,
156*c8dee2aaSAndroid Build Coastguard Worker     GR_GL_CONSTANT_COLOR,
157*c8dee2aaSAndroid Build Coastguard Worker     GR_GL_ONE_MINUS_CONSTANT_COLOR,
158*c8dee2aaSAndroid Build Coastguard Worker 
159*c8dee2aaSAndroid Build Coastguard Worker     // extended blend coeffs
160*c8dee2aaSAndroid Build Coastguard Worker     GR_GL_SRC1_COLOR,
161*c8dee2aaSAndroid Build Coastguard Worker     GR_GL_ONE_MINUS_SRC1_COLOR,
162*c8dee2aaSAndroid Build Coastguard Worker     GR_GL_SRC1_ALPHA,
163*c8dee2aaSAndroid Build Coastguard Worker     GR_GL_ONE_MINUS_SRC1_ALPHA,
164*c8dee2aaSAndroid Build Coastguard Worker 
165*c8dee2aaSAndroid Build Coastguard Worker     // Illegal... needs to map to something.
166*c8dee2aaSAndroid Build Coastguard Worker     GR_GL_ZERO,
167*c8dee2aaSAndroid Build Coastguard Worker };
168*c8dee2aaSAndroid Build Coastguard Worker 
169*c8dee2aaSAndroid Build Coastguard Worker //////////////////////////////////////////////////////////////////////////////
170*c8dee2aaSAndroid Build Coastguard Worker 
gl_target_to_binding_index(GrGLenum target)171*c8dee2aaSAndroid Build Coastguard Worker static int gl_target_to_binding_index(GrGLenum target) {
172*c8dee2aaSAndroid Build Coastguard Worker     switch (target) {
173*c8dee2aaSAndroid Build Coastguard Worker         case GR_GL_TEXTURE_2D:
174*c8dee2aaSAndroid Build Coastguard Worker             return 0;
175*c8dee2aaSAndroid Build Coastguard Worker         case GR_GL_TEXTURE_RECTANGLE:
176*c8dee2aaSAndroid Build Coastguard Worker             return 1;
177*c8dee2aaSAndroid Build Coastguard Worker         case GR_GL_TEXTURE_EXTERNAL:
178*c8dee2aaSAndroid Build Coastguard Worker             return 2;
179*c8dee2aaSAndroid Build Coastguard Worker     }
180*c8dee2aaSAndroid Build Coastguard Worker     SK_ABORT("Unexpected GL texture target.");
181*c8dee2aaSAndroid Build Coastguard Worker }
182*c8dee2aaSAndroid Build Coastguard Worker 
boundID(GrGLenum target) const183*c8dee2aaSAndroid Build Coastguard Worker GrGpuResource::UniqueID GrGLGpu::TextureUnitBindings::boundID(GrGLenum target) const {
184*c8dee2aaSAndroid Build Coastguard Worker     return fTargetBindings[gl_target_to_binding_index(target)].fBoundResourceID;
185*c8dee2aaSAndroid Build Coastguard Worker }
186*c8dee2aaSAndroid Build Coastguard Worker 
hasBeenModified(GrGLenum target) const187*c8dee2aaSAndroid Build Coastguard Worker bool GrGLGpu::TextureUnitBindings::hasBeenModified(GrGLenum target) const {
188*c8dee2aaSAndroid Build Coastguard Worker     return fTargetBindings[gl_target_to_binding_index(target)].fHasBeenModified;
189*c8dee2aaSAndroid Build Coastguard Worker }
190*c8dee2aaSAndroid Build Coastguard Worker 
setBoundID(GrGLenum target,GrGpuResource::UniqueID resourceID)191*c8dee2aaSAndroid Build Coastguard Worker void GrGLGpu::TextureUnitBindings::setBoundID(GrGLenum target, GrGpuResource::UniqueID resourceID) {
192*c8dee2aaSAndroid Build Coastguard Worker     int targetIndex = gl_target_to_binding_index(target);
193*c8dee2aaSAndroid Build Coastguard Worker     fTargetBindings[targetIndex].fBoundResourceID = resourceID;
194*c8dee2aaSAndroid Build Coastguard Worker     fTargetBindings[targetIndex].fHasBeenModified = true;
195*c8dee2aaSAndroid Build Coastguard Worker }
196*c8dee2aaSAndroid Build Coastguard Worker 
invalidateForScratchUse(GrGLenum target)197*c8dee2aaSAndroid Build Coastguard Worker void GrGLGpu::TextureUnitBindings::invalidateForScratchUse(GrGLenum target) {
198*c8dee2aaSAndroid Build Coastguard Worker     this->setBoundID(target, GrGpuResource::UniqueID());
199*c8dee2aaSAndroid Build Coastguard Worker }
200*c8dee2aaSAndroid Build Coastguard Worker 
invalidateAllTargets(bool markUnmodified)201*c8dee2aaSAndroid Build Coastguard Worker void GrGLGpu::TextureUnitBindings::invalidateAllTargets(bool markUnmodified) {
202*c8dee2aaSAndroid Build Coastguard Worker     for (auto& targetBinding : fTargetBindings) {
203*c8dee2aaSAndroid Build Coastguard Worker         targetBinding.fBoundResourceID.makeInvalid();
204*c8dee2aaSAndroid Build Coastguard Worker         if (markUnmodified) {
205*c8dee2aaSAndroid Build Coastguard Worker             targetBinding.fHasBeenModified = false;
206*c8dee2aaSAndroid Build Coastguard Worker         }
207*c8dee2aaSAndroid Build Coastguard Worker     }
208*c8dee2aaSAndroid Build Coastguard Worker }
209*c8dee2aaSAndroid Build Coastguard Worker 
210*c8dee2aaSAndroid Build Coastguard Worker //////////////////////////////////////////////////////////////////////////////
211*c8dee2aaSAndroid Build Coastguard Worker 
filter_to_gl_mag_filter(GrSamplerState::Filter filter)212*c8dee2aaSAndroid Build Coastguard Worker static GrGLenum filter_to_gl_mag_filter(GrSamplerState::Filter filter) {
213*c8dee2aaSAndroid Build Coastguard Worker     switch (filter) {
214*c8dee2aaSAndroid Build Coastguard Worker         case GrSamplerState::Filter::kNearest: return GR_GL_NEAREST;
215*c8dee2aaSAndroid Build Coastguard Worker         case GrSamplerState::Filter::kLinear:  return GR_GL_LINEAR;
216*c8dee2aaSAndroid Build Coastguard Worker     }
217*c8dee2aaSAndroid Build Coastguard Worker     SkUNREACHABLE;
218*c8dee2aaSAndroid Build Coastguard Worker }
219*c8dee2aaSAndroid Build Coastguard Worker 
filter_to_gl_min_filter(GrSamplerState::Filter filter,GrSamplerState::MipmapMode mm)220*c8dee2aaSAndroid Build Coastguard Worker static GrGLenum filter_to_gl_min_filter(GrSamplerState::Filter filter,
221*c8dee2aaSAndroid Build Coastguard Worker                                         GrSamplerState::MipmapMode mm) {
222*c8dee2aaSAndroid Build Coastguard Worker     switch (mm) {
223*c8dee2aaSAndroid Build Coastguard Worker         case GrSamplerState::MipmapMode::kNone:
224*c8dee2aaSAndroid Build Coastguard Worker             return filter_to_gl_mag_filter(filter);
225*c8dee2aaSAndroid Build Coastguard Worker         case GrSamplerState::MipmapMode::kNearest:
226*c8dee2aaSAndroid Build Coastguard Worker             switch (filter) {
227*c8dee2aaSAndroid Build Coastguard Worker                 case GrSamplerState::Filter::kNearest: return GR_GL_NEAREST_MIPMAP_NEAREST;
228*c8dee2aaSAndroid Build Coastguard Worker                 case GrSamplerState::Filter::kLinear:  return GR_GL_LINEAR_MIPMAP_NEAREST;
229*c8dee2aaSAndroid Build Coastguard Worker             }
230*c8dee2aaSAndroid Build Coastguard Worker             SkUNREACHABLE;
231*c8dee2aaSAndroid Build Coastguard Worker         case GrSamplerState::MipmapMode::kLinear:
232*c8dee2aaSAndroid Build Coastguard Worker             switch (filter) {
233*c8dee2aaSAndroid Build Coastguard Worker                 case GrSamplerState::Filter::kNearest: return GR_GL_NEAREST_MIPMAP_LINEAR;
234*c8dee2aaSAndroid Build Coastguard Worker                 case GrSamplerState::Filter::kLinear:  return GR_GL_LINEAR_MIPMAP_LINEAR;
235*c8dee2aaSAndroid Build Coastguard Worker             }
236*c8dee2aaSAndroid Build Coastguard Worker             SkUNREACHABLE;
237*c8dee2aaSAndroid Build Coastguard Worker     }
238*c8dee2aaSAndroid Build Coastguard Worker     SkUNREACHABLE;
239*c8dee2aaSAndroid Build Coastguard Worker }
240*c8dee2aaSAndroid Build Coastguard Worker 
wrap_mode_to_gl_wrap(GrSamplerState::WrapMode wrapMode,const GrCaps & caps)241*c8dee2aaSAndroid Build Coastguard Worker static inline GrGLenum wrap_mode_to_gl_wrap(GrSamplerState::WrapMode wrapMode,
242*c8dee2aaSAndroid Build Coastguard Worker                                             const GrCaps& caps) {
243*c8dee2aaSAndroid Build Coastguard Worker     switch (wrapMode) {
244*c8dee2aaSAndroid Build Coastguard Worker         case GrSamplerState::WrapMode::kClamp:        return GR_GL_CLAMP_TO_EDGE;
245*c8dee2aaSAndroid Build Coastguard Worker         case GrSamplerState::WrapMode::kRepeat:       return GR_GL_REPEAT;
246*c8dee2aaSAndroid Build Coastguard Worker         case GrSamplerState::WrapMode::kMirrorRepeat: return GR_GL_MIRRORED_REPEAT;
247*c8dee2aaSAndroid Build Coastguard Worker         case GrSamplerState::WrapMode::kClampToBorder:
248*c8dee2aaSAndroid Build Coastguard Worker             // May not be supported but should have been caught earlier
249*c8dee2aaSAndroid Build Coastguard Worker             SkASSERT(caps.clampToBorderSupport());
250*c8dee2aaSAndroid Build Coastguard Worker             return GR_GL_CLAMP_TO_BORDER;
251*c8dee2aaSAndroid Build Coastguard Worker     }
252*c8dee2aaSAndroid Build Coastguard Worker     SkUNREACHABLE;
253*c8dee2aaSAndroid Build Coastguard Worker }
254*c8dee2aaSAndroid Build Coastguard Worker 
255*c8dee2aaSAndroid Build Coastguard Worker ///////////////////////////////////////////////////////////////////////////////
256*c8dee2aaSAndroid Build Coastguard Worker 
cleanup_program(GrGLGpu * gpu,GrGLuint * programID,GrGLuint * vshader,GrGLuint * fshader)257*c8dee2aaSAndroid Build Coastguard Worker static void cleanup_program(GrGLGpu* gpu,
258*c8dee2aaSAndroid Build Coastguard Worker                             GrGLuint* programID,
259*c8dee2aaSAndroid Build Coastguard Worker                             GrGLuint* vshader,
260*c8dee2aaSAndroid Build Coastguard Worker                             GrGLuint* fshader) {
261*c8dee2aaSAndroid Build Coastguard Worker     const GrGLInterface* gli = gpu->glInterface();
262*c8dee2aaSAndroid Build Coastguard Worker     if (programID) {
263*c8dee2aaSAndroid Build Coastguard Worker         GR_GL_CALL(gli, DeleteProgram(*programID));
264*c8dee2aaSAndroid Build Coastguard Worker         *programID = 0;
265*c8dee2aaSAndroid Build Coastguard Worker     }
266*c8dee2aaSAndroid Build Coastguard Worker     if (vshader) {
267*c8dee2aaSAndroid Build Coastguard Worker         GR_GL_CALL(gli, DeleteShader(*vshader));
268*c8dee2aaSAndroid Build Coastguard Worker         *vshader = 0;
269*c8dee2aaSAndroid Build Coastguard Worker     }
270*c8dee2aaSAndroid Build Coastguard Worker     if (fshader) {
271*c8dee2aaSAndroid Build Coastguard Worker         GR_GL_CALL(gli, DeleteShader(*fshader));
272*c8dee2aaSAndroid Build Coastguard Worker         *fshader = 0;
273*c8dee2aaSAndroid Build Coastguard Worker     }
274*c8dee2aaSAndroid Build Coastguard Worker }
275*c8dee2aaSAndroid Build Coastguard Worker 
276*c8dee2aaSAndroid Build Coastguard Worker ///////////////////////////////////////////////////////////////////////////////
277*c8dee2aaSAndroid Build Coastguard Worker 
278*c8dee2aaSAndroid Build Coastguard Worker class GrGLGpu::SamplerObjectCache {
279*c8dee2aaSAndroid Build Coastguard Worker public:
SamplerObjectCache(GrGLGpu * gpu)280*c8dee2aaSAndroid Build Coastguard Worker     SamplerObjectCache(GrGLGpu* gpu) : fGpu(gpu) {
281*c8dee2aaSAndroid Build Coastguard Worker         fNumTextureUnits = fGpu->glCaps().shaderCaps()->fMaxFragmentSamplers;
282*c8dee2aaSAndroid Build Coastguard Worker         fTextureUnitStates = std::make_unique<UnitState[]>(fNumTextureUnits);
283*c8dee2aaSAndroid Build Coastguard Worker     }
284*c8dee2aaSAndroid Build Coastguard Worker 
~SamplerObjectCache()285*c8dee2aaSAndroid Build Coastguard Worker     ~SamplerObjectCache() {
286*c8dee2aaSAndroid Build Coastguard Worker         if (!fNumTextureUnits) {
287*c8dee2aaSAndroid Build Coastguard Worker             // We've already been abandoned.
288*c8dee2aaSAndroid Build Coastguard Worker             return;
289*c8dee2aaSAndroid Build Coastguard Worker         }
290*c8dee2aaSAndroid Build Coastguard Worker     }
291*c8dee2aaSAndroid Build Coastguard Worker 
bindSampler(int unitIdx,GrSamplerState state)292*c8dee2aaSAndroid Build Coastguard Worker     void bindSampler(int unitIdx, GrSamplerState state) {
293*c8dee2aaSAndroid Build Coastguard Worker         if (unitIdx >= fNumTextureUnits) {
294*c8dee2aaSAndroid Build Coastguard Worker             return;
295*c8dee2aaSAndroid Build Coastguard Worker         }
296*c8dee2aaSAndroid Build Coastguard Worker         // In GL the max aniso value is specified in addition to min/mag filters and the driver
297*c8dee2aaSAndroid Build Coastguard Worker         // is encouraged to consider the other filter settings when doing aniso.
298*c8dee2aaSAndroid Build Coastguard Worker         uint32_t key = state.asKey(/*anisoIsOrthogonal=*/true);
299*c8dee2aaSAndroid Build Coastguard Worker         const Sampler* sampler = fSamplers.find(key);
300*c8dee2aaSAndroid Build Coastguard Worker         if (!sampler) {
301*c8dee2aaSAndroid Build Coastguard Worker             GrGLuint s;
302*c8dee2aaSAndroid Build Coastguard Worker             GR_GL_CALL(fGpu->glInterface(), GenSamplers(1, &s));
303*c8dee2aaSAndroid Build Coastguard Worker             if (!s) {
304*c8dee2aaSAndroid Build Coastguard Worker                 return;
305*c8dee2aaSAndroid Build Coastguard Worker             }
306*c8dee2aaSAndroid Build Coastguard Worker             sampler = fSamplers.insert(key, Sampler(s, fGpu->glInterface()));
307*c8dee2aaSAndroid Build Coastguard Worker             GrGLenum minFilter = filter_to_gl_min_filter(state.filter(), state.mipmapMode());
308*c8dee2aaSAndroid Build Coastguard Worker             GrGLenum magFilter = filter_to_gl_mag_filter(state.filter());
309*c8dee2aaSAndroid Build Coastguard Worker             GrGLenum wrapX = wrap_mode_to_gl_wrap(state.wrapModeX(), fGpu->glCaps());
310*c8dee2aaSAndroid Build Coastguard Worker             GrGLenum wrapY = wrap_mode_to_gl_wrap(state.wrapModeY(), fGpu->glCaps());
311*c8dee2aaSAndroid Build Coastguard Worker             GR_GL_CALL(fGpu->glInterface(),
312*c8dee2aaSAndroid Build Coastguard Worker                        SamplerParameteri(s, GR_GL_TEXTURE_MIN_FILTER, minFilter));
313*c8dee2aaSAndroid Build Coastguard Worker             GR_GL_CALL(fGpu->glInterface(),
314*c8dee2aaSAndroid Build Coastguard Worker                        SamplerParameteri(s, GR_GL_TEXTURE_MAG_FILTER, magFilter));
315*c8dee2aaSAndroid Build Coastguard Worker             GR_GL_CALL(fGpu->glInterface(), SamplerParameteri(s, GR_GL_TEXTURE_WRAP_S, wrapX));
316*c8dee2aaSAndroid Build Coastguard Worker             GR_GL_CALL(fGpu->glInterface(), SamplerParameteri(s, GR_GL_TEXTURE_WRAP_T, wrapY));
317*c8dee2aaSAndroid Build Coastguard Worker             SkASSERT(fGpu->glCaps().anisoSupport() || !state.isAniso());
318*c8dee2aaSAndroid Build Coastguard Worker             if (fGpu->glCaps().anisoSupport()) {
319*c8dee2aaSAndroid Build Coastguard Worker                 float maxAniso = std::min(static_cast<GrGLfloat>(state.maxAniso()),
320*c8dee2aaSAndroid Build Coastguard Worker                                           fGpu->glCaps().maxTextureMaxAnisotropy());
321*c8dee2aaSAndroid Build Coastguard Worker                 GR_GL_CALL(fGpu->glInterface(), SamplerParameterf(s,
322*c8dee2aaSAndroid Build Coastguard Worker                                                                   GR_GL_TEXTURE_MAX_ANISOTROPY,
323*c8dee2aaSAndroid Build Coastguard Worker                                                                   maxAniso));
324*c8dee2aaSAndroid Build Coastguard Worker             }
325*c8dee2aaSAndroid Build Coastguard Worker         }
326*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(sampler && sampler->id());
327*c8dee2aaSAndroid Build Coastguard Worker         if (!fTextureUnitStates[unitIdx].fKnown ||
328*c8dee2aaSAndroid Build Coastguard Worker             fTextureUnitStates[unitIdx].fSamplerIDIfKnown != sampler->id()) {
329*c8dee2aaSAndroid Build Coastguard Worker             GR_GL_CALL(fGpu->glInterface(), BindSampler(unitIdx, sampler->id()));
330*c8dee2aaSAndroid Build Coastguard Worker             fTextureUnitStates[unitIdx].fSamplerIDIfKnown = sampler->id();
331*c8dee2aaSAndroid Build Coastguard Worker             fTextureUnitStates[unitIdx].fKnown = true;
332*c8dee2aaSAndroid Build Coastguard Worker         }
333*c8dee2aaSAndroid Build Coastguard Worker     }
334*c8dee2aaSAndroid Build Coastguard Worker 
unbindSampler(int unitIdx)335*c8dee2aaSAndroid Build Coastguard Worker     void unbindSampler(int unitIdx) {
336*c8dee2aaSAndroid Build Coastguard Worker         if (!fTextureUnitStates[unitIdx].fKnown ||
337*c8dee2aaSAndroid Build Coastguard Worker             fTextureUnitStates[unitIdx].fSamplerIDIfKnown != 0) {
338*c8dee2aaSAndroid Build Coastguard Worker             GR_GL_CALL(fGpu->glInterface(), BindSampler(unitIdx, 0));
339*c8dee2aaSAndroid Build Coastguard Worker             fTextureUnitStates[unitIdx].fSamplerIDIfKnown = 0;
340*c8dee2aaSAndroid Build Coastguard Worker             fTextureUnitStates[unitIdx].fKnown = true;
341*c8dee2aaSAndroid Build Coastguard Worker         }
342*c8dee2aaSAndroid Build Coastguard Worker     }
343*c8dee2aaSAndroid Build Coastguard Worker 
invalidateBindings()344*c8dee2aaSAndroid Build Coastguard Worker     void invalidateBindings() {
345*c8dee2aaSAndroid Build Coastguard Worker         std::fill_n(fTextureUnitStates.get(), fNumTextureUnits, UnitState{});
346*c8dee2aaSAndroid Build Coastguard Worker     }
347*c8dee2aaSAndroid Build Coastguard Worker 
abandon()348*c8dee2aaSAndroid Build Coastguard Worker     void abandon() {
349*c8dee2aaSAndroid Build Coastguard Worker         fSamplers.foreach([](uint32_t* key, Sampler* sampler) { sampler->abandon(); });
350*c8dee2aaSAndroid Build Coastguard Worker         fTextureUnitStates.reset();
351*c8dee2aaSAndroid Build Coastguard Worker         fNumTextureUnits = 0;
352*c8dee2aaSAndroid Build Coastguard Worker     }
353*c8dee2aaSAndroid Build Coastguard Worker 
release()354*c8dee2aaSAndroid Build Coastguard Worker     void release() {
355*c8dee2aaSAndroid Build Coastguard Worker         if (!fNumTextureUnits) {
356*c8dee2aaSAndroid Build Coastguard Worker             // We've already been abandoned.
357*c8dee2aaSAndroid Build Coastguard Worker             return;
358*c8dee2aaSAndroid Build Coastguard Worker         }
359*c8dee2aaSAndroid Build Coastguard Worker         fSamplers.reset();
360*c8dee2aaSAndroid Build Coastguard Worker         // Deleting a bound sampler implicitly binds sampler 0. We just invalidate all of our
361*c8dee2aaSAndroid Build Coastguard Worker         // knowledge.
362*c8dee2aaSAndroid Build Coastguard Worker         std::fill_n(fTextureUnitStates.get(), fNumTextureUnits, UnitState{});
363*c8dee2aaSAndroid Build Coastguard Worker     }
364*c8dee2aaSAndroid Build Coastguard Worker 
365*c8dee2aaSAndroid Build Coastguard Worker private:
366*c8dee2aaSAndroid Build Coastguard Worker     class Sampler {
367*c8dee2aaSAndroid Build Coastguard Worker     public:
368*c8dee2aaSAndroid Build Coastguard Worker         Sampler() = default;
369*c8dee2aaSAndroid Build Coastguard Worker         Sampler(const Sampler&) = delete;
370*c8dee2aaSAndroid Build Coastguard Worker 
Sampler(Sampler && that)371*c8dee2aaSAndroid Build Coastguard Worker         Sampler(Sampler&& that) {
372*c8dee2aaSAndroid Build Coastguard Worker             fID = that.fID;
373*c8dee2aaSAndroid Build Coastguard Worker             fInterface = that.fInterface;
374*c8dee2aaSAndroid Build Coastguard Worker             that.fID = 0;
375*c8dee2aaSAndroid Build Coastguard Worker         }
376*c8dee2aaSAndroid Build Coastguard Worker 
Sampler(GrGLuint id,const GrGLInterface * interface)377*c8dee2aaSAndroid Build Coastguard Worker         Sampler(GrGLuint id, const GrGLInterface* interface) : fID(id), fInterface(interface) {}
378*c8dee2aaSAndroid Build Coastguard Worker 
~Sampler()379*c8dee2aaSAndroid Build Coastguard Worker         ~Sampler() {
380*c8dee2aaSAndroid Build Coastguard Worker             if (fID) {
381*c8dee2aaSAndroid Build Coastguard Worker                 GR_GL_CALL(fInterface, DeleteSamplers(1, &fID));
382*c8dee2aaSAndroid Build Coastguard Worker             }
383*c8dee2aaSAndroid Build Coastguard Worker         }
384*c8dee2aaSAndroid Build Coastguard Worker 
id() const385*c8dee2aaSAndroid Build Coastguard Worker         GrGLuint id() const { return fID; }
386*c8dee2aaSAndroid Build Coastguard Worker 
abandon()387*c8dee2aaSAndroid Build Coastguard Worker         void abandon() { fID = 0; }
388*c8dee2aaSAndroid Build Coastguard Worker 
389*c8dee2aaSAndroid Build Coastguard Worker     private:
390*c8dee2aaSAndroid Build Coastguard Worker         GrGLuint             fID        = 0;
391*c8dee2aaSAndroid Build Coastguard Worker         const GrGLInterface* fInterface = nullptr;
392*c8dee2aaSAndroid Build Coastguard Worker     };
393*c8dee2aaSAndroid Build Coastguard Worker 
394*c8dee2aaSAndroid Build Coastguard Worker     struct UnitState {
395*c8dee2aaSAndroid Build Coastguard Worker         bool fKnown = false;
396*c8dee2aaSAndroid Build Coastguard Worker         GrGLuint fSamplerIDIfKnown = 0;
397*c8dee2aaSAndroid Build Coastguard Worker     };
398*c8dee2aaSAndroid Build Coastguard Worker 
399*c8dee2aaSAndroid Build Coastguard Worker     static constexpr int kMaxSamplers = 32;
400*c8dee2aaSAndroid Build Coastguard Worker 
401*c8dee2aaSAndroid Build Coastguard Worker     SkLRUCache<uint32_t, Sampler> fSamplers{kMaxSamplers};
402*c8dee2aaSAndroid Build Coastguard Worker     std::unique_ptr<UnitState[]>  fTextureUnitStates;
403*c8dee2aaSAndroid Build Coastguard Worker     GrGLGpu*                      fGpu;
404*c8dee2aaSAndroid Build Coastguard Worker     int                           fNumTextureUnits;
405*c8dee2aaSAndroid Build Coastguard Worker };
406*c8dee2aaSAndroid Build Coastguard Worker 
407*c8dee2aaSAndroid Build Coastguard Worker ///////////////////////////////////////////////////////////////////////////////
408*c8dee2aaSAndroid Build Coastguard Worker 
Make(sk_sp<const GrGLInterface> interface,const GrContextOptions & options,GrDirectContext * direct)409*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<GrGpu> GrGLGpu::Make(sk_sp<const GrGLInterface> interface,
410*c8dee2aaSAndroid Build Coastguard Worker                                      const GrContextOptions& options,
411*c8dee2aaSAndroid Build Coastguard Worker                                      GrDirectContext* direct) {
412*c8dee2aaSAndroid Build Coastguard Worker #if !defined(SK_DISABLE_LEGACY_GL_MAKE_NATIVE_INTERFACE)
413*c8dee2aaSAndroid Build Coastguard Worker     if (!interface) {
414*c8dee2aaSAndroid Build Coastguard Worker         interface = GrGLMakeNativeInterface();
415*c8dee2aaSAndroid Build Coastguard Worker         if (!interface) {
416*c8dee2aaSAndroid Build Coastguard Worker             return nullptr;
417*c8dee2aaSAndroid Build Coastguard Worker         }
418*c8dee2aaSAndroid Build Coastguard Worker     }
419*c8dee2aaSAndroid Build Coastguard Worker #else
420*c8dee2aaSAndroid Build Coastguard Worker     if (!interface) {
421*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
422*c8dee2aaSAndroid Build Coastguard Worker     }
423*c8dee2aaSAndroid Build Coastguard Worker #endif
424*c8dee2aaSAndroid Build Coastguard Worker #ifdef USE_NSIGHT
425*c8dee2aaSAndroid Build Coastguard Worker     const_cast<GrContextOptions&>(options).fSuppressPathRendering = true;
426*c8dee2aaSAndroid Build Coastguard Worker #endif
427*c8dee2aaSAndroid Build Coastguard Worker     auto glContext = GrGLContext::Make(std::move(interface), options);
428*c8dee2aaSAndroid Build Coastguard Worker     if (!glContext) {
429*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
430*c8dee2aaSAndroid Build Coastguard Worker     }
431*c8dee2aaSAndroid Build Coastguard Worker     return std::unique_ptr<GrGpu>(new GrGLGpu(std::move(glContext), direct));
432*c8dee2aaSAndroid Build Coastguard Worker }
433*c8dee2aaSAndroid Build Coastguard Worker 
GrGLGpu(std::unique_ptr<GrGLContext> ctx,GrDirectContext * dContext)434*c8dee2aaSAndroid Build Coastguard Worker GrGLGpu::GrGLGpu(std::unique_ptr<GrGLContext> ctx, GrDirectContext* dContext)
435*c8dee2aaSAndroid Build Coastguard Worker         : GrGpu(dContext)
436*c8dee2aaSAndroid Build Coastguard Worker         , fGLContext(std::move(ctx))
437*c8dee2aaSAndroid Build Coastguard Worker         , fProgramCache(new ProgramCache(dContext->priv().options().fRuntimeProgramCacheSize))
438*c8dee2aaSAndroid Build Coastguard Worker         , fHWProgramID(0)
439*c8dee2aaSAndroid Build Coastguard Worker         , fTempSrcFBOID(0)
440*c8dee2aaSAndroid Build Coastguard Worker         , fTempDstFBOID(0)
441*c8dee2aaSAndroid Build Coastguard Worker         , fStencilClearFBOID(0)
442*c8dee2aaSAndroid Build Coastguard Worker         , fFinishCallbacks(this) {
443*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(fGLContext);
444*c8dee2aaSAndroid Build Coastguard Worker     // Clear errors so we don't get confused whether we caused an error.
445*c8dee2aaSAndroid Build Coastguard Worker     this->clearErrorsAndCheckForOOM();
446*c8dee2aaSAndroid Build Coastguard Worker     // Toss out any pre-existing OOM that was hanging around before we got started.
447*c8dee2aaSAndroid Build Coastguard Worker     this->checkAndResetOOMed();
448*c8dee2aaSAndroid Build Coastguard Worker 
449*c8dee2aaSAndroid Build Coastguard Worker     this->initCaps(sk_ref_sp(fGLContext->caps()));
450*c8dee2aaSAndroid Build Coastguard Worker 
451*c8dee2aaSAndroid Build Coastguard Worker     fHWTextureUnitBindings.reset(this->numTextureUnits());
452*c8dee2aaSAndroid Build Coastguard Worker 
453*c8dee2aaSAndroid Build Coastguard Worker     this->hwBufferState(GrGpuBufferType::kVertex)->fGLTarget = GR_GL_ARRAY_BUFFER;
454*c8dee2aaSAndroid Build Coastguard Worker     this->hwBufferState(GrGpuBufferType::kIndex)->fGLTarget = GR_GL_ELEMENT_ARRAY_BUFFER;
455*c8dee2aaSAndroid Build Coastguard Worker     this->hwBufferState(GrGpuBufferType::kDrawIndirect)->fGLTarget = GR_GL_DRAW_INDIRECT_BUFFER;
456*c8dee2aaSAndroid Build Coastguard Worker     if (GrGLCaps::TransferBufferType::kChromium == this->glCaps().transferBufferType()) {
457*c8dee2aaSAndroid Build Coastguard Worker         this->hwBufferState(GrGpuBufferType::kXferCpuToGpu)->fGLTarget =
458*c8dee2aaSAndroid Build Coastguard Worker                 GR_GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM;
459*c8dee2aaSAndroid Build Coastguard Worker         this->hwBufferState(GrGpuBufferType::kXferGpuToCpu)->fGLTarget =
460*c8dee2aaSAndroid Build Coastguard Worker                 GR_GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM;
461*c8dee2aaSAndroid Build Coastguard Worker     } else {
462*c8dee2aaSAndroid Build Coastguard Worker         this->hwBufferState(GrGpuBufferType::kXferCpuToGpu)->fGLTarget = GR_GL_PIXEL_UNPACK_BUFFER;
463*c8dee2aaSAndroid Build Coastguard Worker         this->hwBufferState(GrGpuBufferType::kXferGpuToCpu)->fGLTarget = GR_GL_PIXEL_PACK_BUFFER;
464*c8dee2aaSAndroid Build Coastguard Worker     }
465*c8dee2aaSAndroid Build Coastguard Worker     for (int i = 0; i < kGrGpuBufferTypeCount; ++i) {
466*c8dee2aaSAndroid Build Coastguard Worker         fHWBufferState[i].invalidate();
467*c8dee2aaSAndroid Build Coastguard Worker     }
468*c8dee2aaSAndroid Build Coastguard Worker 
469*c8dee2aaSAndroid Build Coastguard Worker     if (this->glCaps().useSamplerObjects()) {
470*c8dee2aaSAndroid Build Coastguard Worker         fSamplerObjectCache = std::make_unique<SamplerObjectCache>(this);
471*c8dee2aaSAndroid Build Coastguard Worker     }
472*c8dee2aaSAndroid Build Coastguard Worker }
473*c8dee2aaSAndroid Build Coastguard Worker 
~GrGLGpu()474*c8dee2aaSAndroid Build Coastguard Worker GrGLGpu::~GrGLGpu() {
475*c8dee2aaSAndroid Build Coastguard Worker     // Ensure any GrGpuResource objects get deleted first, since they may require a working GrGLGpu
476*c8dee2aaSAndroid Build Coastguard Worker     // to release the resources held by the objects themselves.
477*c8dee2aaSAndroid Build Coastguard Worker     fCopyProgramArrayBuffer.reset();
478*c8dee2aaSAndroid Build Coastguard Worker     fMipmapProgramArrayBuffer.reset();
479*c8dee2aaSAndroid Build Coastguard Worker     if (fProgramCache) {
480*c8dee2aaSAndroid Build Coastguard Worker         fProgramCache->reset();
481*c8dee2aaSAndroid Build Coastguard Worker     }
482*c8dee2aaSAndroid Build Coastguard Worker 
483*c8dee2aaSAndroid Build Coastguard Worker     fHWProgram.reset();
484*c8dee2aaSAndroid Build Coastguard Worker     if (fHWProgramID) {
485*c8dee2aaSAndroid Build Coastguard Worker         // detach the current program so there is no confusion on OpenGL's part
486*c8dee2aaSAndroid Build Coastguard Worker         // that we want it to be deleted
487*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(UseProgram(0));
488*c8dee2aaSAndroid Build Coastguard Worker     }
489*c8dee2aaSAndroid Build Coastguard Worker 
490*c8dee2aaSAndroid Build Coastguard Worker     if (fTempSrcFBOID) {
491*c8dee2aaSAndroid Build Coastguard Worker         this->deleteFramebuffer(fTempSrcFBOID);
492*c8dee2aaSAndroid Build Coastguard Worker     }
493*c8dee2aaSAndroid Build Coastguard Worker     if (fTempDstFBOID) {
494*c8dee2aaSAndroid Build Coastguard Worker         this->deleteFramebuffer(fTempDstFBOID);
495*c8dee2aaSAndroid Build Coastguard Worker     }
496*c8dee2aaSAndroid Build Coastguard Worker     if (fStencilClearFBOID) {
497*c8dee2aaSAndroid Build Coastguard Worker         this->deleteFramebuffer(fStencilClearFBOID);
498*c8dee2aaSAndroid Build Coastguard Worker     }
499*c8dee2aaSAndroid Build Coastguard Worker 
500*c8dee2aaSAndroid Build Coastguard Worker     for (size_t i = 0; i < std::size(fCopyPrograms); ++i) {
501*c8dee2aaSAndroid Build Coastguard Worker         if (0 != fCopyPrograms[i].fProgram) {
502*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(DeleteProgram(fCopyPrograms[i].fProgram));
503*c8dee2aaSAndroid Build Coastguard Worker         }
504*c8dee2aaSAndroid Build Coastguard Worker     }
505*c8dee2aaSAndroid Build Coastguard Worker 
506*c8dee2aaSAndroid Build Coastguard Worker     for (size_t i = 0; i < std::size(fMipmapPrograms); ++i) {
507*c8dee2aaSAndroid Build Coastguard Worker         if (0 != fMipmapPrograms[i].fProgram) {
508*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(DeleteProgram(fMipmapPrograms[i].fProgram));
509*c8dee2aaSAndroid Build Coastguard Worker         }
510*c8dee2aaSAndroid Build Coastguard Worker     }
511*c8dee2aaSAndroid Build Coastguard Worker 
512*c8dee2aaSAndroid Build Coastguard Worker     fSamplerObjectCache.reset();
513*c8dee2aaSAndroid Build Coastguard Worker 
514*c8dee2aaSAndroid Build Coastguard Worker     fFinishCallbacks.callAll(true);
515*c8dee2aaSAndroid Build Coastguard Worker }
516*c8dee2aaSAndroid Build Coastguard Worker 
disconnect(DisconnectType type)517*c8dee2aaSAndroid Build Coastguard Worker void GrGLGpu::disconnect(DisconnectType type) {
518*c8dee2aaSAndroid Build Coastguard Worker     INHERITED::disconnect(type);
519*c8dee2aaSAndroid Build Coastguard Worker     if (DisconnectType::kCleanup == type) {
520*c8dee2aaSAndroid Build Coastguard Worker         if (fHWProgramID) {
521*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(UseProgram(0));
522*c8dee2aaSAndroid Build Coastguard Worker         }
523*c8dee2aaSAndroid Build Coastguard Worker         if (fTempSrcFBOID) {
524*c8dee2aaSAndroid Build Coastguard Worker             this->deleteFramebuffer(fTempSrcFBOID);
525*c8dee2aaSAndroid Build Coastguard Worker         }
526*c8dee2aaSAndroid Build Coastguard Worker         if (fTempDstFBOID) {
527*c8dee2aaSAndroid Build Coastguard Worker             this->deleteFramebuffer(fTempDstFBOID);
528*c8dee2aaSAndroid Build Coastguard Worker         }
529*c8dee2aaSAndroid Build Coastguard Worker         if (fStencilClearFBOID) {
530*c8dee2aaSAndroid Build Coastguard Worker             this->deleteFramebuffer(fStencilClearFBOID);
531*c8dee2aaSAndroid Build Coastguard Worker         }
532*c8dee2aaSAndroid Build Coastguard Worker         for (size_t i = 0; i < std::size(fCopyPrograms); ++i) {
533*c8dee2aaSAndroid Build Coastguard Worker             if (fCopyPrograms[i].fProgram) {
534*c8dee2aaSAndroid Build Coastguard Worker                 GL_CALL(DeleteProgram(fCopyPrograms[i].fProgram));
535*c8dee2aaSAndroid Build Coastguard Worker             }
536*c8dee2aaSAndroid Build Coastguard Worker         }
537*c8dee2aaSAndroid Build Coastguard Worker         for (size_t i = 0; i < std::size(fMipmapPrograms); ++i) {
538*c8dee2aaSAndroid Build Coastguard Worker             if (fMipmapPrograms[i].fProgram) {
539*c8dee2aaSAndroid Build Coastguard Worker                 GL_CALL(DeleteProgram(fMipmapPrograms[i].fProgram));
540*c8dee2aaSAndroid Build Coastguard Worker             }
541*c8dee2aaSAndroid Build Coastguard Worker         }
542*c8dee2aaSAndroid Build Coastguard Worker 
543*c8dee2aaSAndroid Build Coastguard Worker         if (fSamplerObjectCache) {
544*c8dee2aaSAndroid Build Coastguard Worker             fSamplerObjectCache->release();
545*c8dee2aaSAndroid Build Coastguard Worker         }
546*c8dee2aaSAndroid Build Coastguard Worker     } else {
547*c8dee2aaSAndroid Build Coastguard Worker         if (fProgramCache) {
548*c8dee2aaSAndroid Build Coastguard Worker             fProgramCache->abandon();
549*c8dee2aaSAndroid Build Coastguard Worker         }
550*c8dee2aaSAndroid Build Coastguard Worker         if (fSamplerObjectCache) {
551*c8dee2aaSAndroid Build Coastguard Worker             fSamplerObjectCache->abandon();
552*c8dee2aaSAndroid Build Coastguard Worker         }
553*c8dee2aaSAndroid Build Coastguard Worker     }
554*c8dee2aaSAndroid Build Coastguard Worker 
555*c8dee2aaSAndroid Build Coastguard Worker     fHWProgram.reset();
556*c8dee2aaSAndroid Build Coastguard Worker     fProgramCache->reset();
557*c8dee2aaSAndroid Build Coastguard Worker     fProgramCache.reset();
558*c8dee2aaSAndroid Build Coastguard Worker 
559*c8dee2aaSAndroid Build Coastguard Worker     fHWProgramID = 0;
560*c8dee2aaSAndroid Build Coastguard Worker     fTempSrcFBOID = 0;
561*c8dee2aaSAndroid Build Coastguard Worker     fTempDstFBOID = 0;
562*c8dee2aaSAndroid Build Coastguard Worker     fStencilClearFBOID = 0;
563*c8dee2aaSAndroid Build Coastguard Worker     fCopyProgramArrayBuffer.reset();
564*c8dee2aaSAndroid Build Coastguard Worker     for (size_t i = 0; i < std::size(fCopyPrograms); ++i) {
565*c8dee2aaSAndroid Build Coastguard Worker         fCopyPrograms[i].fProgram = 0;
566*c8dee2aaSAndroid Build Coastguard Worker     }
567*c8dee2aaSAndroid Build Coastguard Worker     fMipmapProgramArrayBuffer.reset();
568*c8dee2aaSAndroid Build Coastguard Worker     for (size_t i = 0; i < std::size(fMipmapPrograms); ++i) {
569*c8dee2aaSAndroid Build Coastguard Worker         fMipmapPrograms[i].fProgram = 0;
570*c8dee2aaSAndroid Build Coastguard Worker     }
571*c8dee2aaSAndroid Build Coastguard Worker 
572*c8dee2aaSAndroid Build Coastguard Worker     fFinishCallbacks.callAll(/* doDelete */ DisconnectType::kCleanup == type);
573*c8dee2aaSAndroid Build Coastguard Worker }
574*c8dee2aaSAndroid Build Coastguard Worker 
pipelineBuilder()575*c8dee2aaSAndroid Build Coastguard Worker GrThreadSafePipelineBuilder* GrGLGpu::pipelineBuilder() {
576*c8dee2aaSAndroid Build Coastguard Worker     return fProgramCache.get();
577*c8dee2aaSAndroid Build Coastguard Worker }
578*c8dee2aaSAndroid Build Coastguard Worker 
refPipelineBuilder()579*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrThreadSafePipelineBuilder> GrGLGpu::refPipelineBuilder() {
580*c8dee2aaSAndroid Build Coastguard Worker     return fProgramCache;
581*c8dee2aaSAndroid Build Coastguard Worker }
582*c8dee2aaSAndroid Build Coastguard Worker 
583*c8dee2aaSAndroid Build Coastguard Worker ///////////////////////////////////////////////////////////////////////////////
584*c8dee2aaSAndroid Build Coastguard Worker 
onResetContext(uint32_t resetBits)585*c8dee2aaSAndroid Build Coastguard Worker void GrGLGpu::onResetContext(uint32_t resetBits) {
586*c8dee2aaSAndroid Build Coastguard Worker     if (resetBits & kMisc_GrGLBackendState) {
587*c8dee2aaSAndroid Build Coastguard Worker         // we don't use the zb at all
588*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(Disable(GR_GL_DEPTH_TEST));
589*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(DepthMask(GR_GL_FALSE));
590*c8dee2aaSAndroid Build Coastguard Worker 
591*c8dee2aaSAndroid Build Coastguard Worker         // We don't use face culling.
592*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(Disable(GR_GL_CULL_FACE));
593*c8dee2aaSAndroid Build Coastguard Worker         // We do use separate stencil. Our algorithms don't care which face is front vs. back so
594*c8dee2aaSAndroid Build Coastguard Worker         // just set this to the default for self-consistency.
595*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(FrontFace(GR_GL_CCW));
596*c8dee2aaSAndroid Build Coastguard Worker 
597*c8dee2aaSAndroid Build Coastguard Worker         this->hwBufferState(GrGpuBufferType::kXferCpuToGpu)->invalidate();
598*c8dee2aaSAndroid Build Coastguard Worker         this->hwBufferState(GrGpuBufferType::kXferGpuToCpu)->invalidate();
599*c8dee2aaSAndroid Build Coastguard Worker 
600*c8dee2aaSAndroid Build Coastguard Worker         if (GR_IS_GR_GL(this->glStandard())) {
601*c8dee2aaSAndroid Build Coastguard Worker #ifndef USE_NSIGHT
602*c8dee2aaSAndroid Build Coastguard Worker             // Desktop-only state that we never change
603*c8dee2aaSAndroid Build Coastguard Worker             if (!this->glCaps().isCoreProfile()) {
604*c8dee2aaSAndroid Build Coastguard Worker                 GL_CALL(Disable(GR_GL_POINT_SMOOTH));
605*c8dee2aaSAndroid Build Coastguard Worker                 GL_CALL(Disable(GR_GL_LINE_SMOOTH));
606*c8dee2aaSAndroid Build Coastguard Worker                 GL_CALL(Disable(GR_GL_POLYGON_SMOOTH));
607*c8dee2aaSAndroid Build Coastguard Worker                 GL_CALL(Disable(GR_GL_POLYGON_STIPPLE));
608*c8dee2aaSAndroid Build Coastguard Worker                 GL_CALL(Disable(GR_GL_COLOR_LOGIC_OP));
609*c8dee2aaSAndroid Build Coastguard Worker                 GL_CALL(Disable(GR_GL_INDEX_LOGIC_OP));
610*c8dee2aaSAndroid Build Coastguard Worker             }
611*c8dee2aaSAndroid Build Coastguard Worker             // The windows NVIDIA driver has GL_ARB_imaging in the extension string when using a
612*c8dee2aaSAndroid Build Coastguard Worker             // core profile. This seems like a bug since the core spec removes any mention of
613*c8dee2aaSAndroid Build Coastguard Worker             // GL_ARB_imaging.
614*c8dee2aaSAndroid Build Coastguard Worker             if (this->glCaps().imagingSupport() && !this->glCaps().isCoreProfile()) {
615*c8dee2aaSAndroid Build Coastguard Worker                 GL_CALL(Disable(GR_GL_COLOR_TABLE));
616*c8dee2aaSAndroid Build Coastguard Worker             }
617*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(Disable(GR_GL_POLYGON_OFFSET_FILL));
618*c8dee2aaSAndroid Build Coastguard Worker 
619*c8dee2aaSAndroid Build Coastguard Worker             fHWWireframeEnabled = kUnknown_TriState;
620*c8dee2aaSAndroid Build Coastguard Worker #endif
621*c8dee2aaSAndroid Build Coastguard Worker             // Since ES doesn't support glPointSize at all we always use the VS to
622*c8dee2aaSAndroid Build Coastguard Worker             // set the point size
623*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(Enable(GR_GL_VERTEX_PROGRAM_POINT_SIZE));
624*c8dee2aaSAndroid Build Coastguard Worker 
625*c8dee2aaSAndroid Build Coastguard Worker         }
626*c8dee2aaSAndroid Build Coastguard Worker 
627*c8dee2aaSAndroid Build Coastguard Worker         if (GR_IS_GR_GL_ES(this->glStandard()) &&
628*c8dee2aaSAndroid Build Coastguard Worker             this->glCaps().fbFetchRequiresEnablePerSample()) {
629*c8dee2aaSAndroid Build Coastguard Worker             // The arm extension requires specifically enabling MSAA fetching per sample.
630*c8dee2aaSAndroid Build Coastguard Worker             // On some devices this may have a perf hit.  Also multiple render targets are disabled
631*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(Enable(GR_GL_FETCH_PER_SAMPLE));
632*c8dee2aaSAndroid Build Coastguard Worker         }
633*c8dee2aaSAndroid Build Coastguard Worker         fHWWriteToColor = kUnknown_TriState;
634*c8dee2aaSAndroid Build Coastguard Worker         // we only ever use lines in hairline mode
635*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(LineWidth(1));
636*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(Disable(GR_GL_DITHER));
637*c8dee2aaSAndroid Build Coastguard Worker 
638*c8dee2aaSAndroid Build Coastguard Worker         fHWClearColor[0] = fHWClearColor[1] = fHWClearColor[2] = fHWClearColor[3] = SK_FloatNaN;
639*c8dee2aaSAndroid Build Coastguard Worker     }
640*c8dee2aaSAndroid Build Coastguard Worker 
641*c8dee2aaSAndroid Build Coastguard Worker     if (resetBits & kMSAAEnable_GrGLBackendState) {
642*c8dee2aaSAndroid Build Coastguard Worker         if (this->glCaps().clientCanDisableMultisample()) {
643*c8dee2aaSAndroid Build Coastguard Worker             // Restore GL_MULTISAMPLE to its initial state. It being enabled has no effect on draws
644*c8dee2aaSAndroid Build Coastguard Worker             // to non-MSAA targets.
645*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(Enable(GR_GL_MULTISAMPLE));
646*c8dee2aaSAndroid Build Coastguard Worker         }
647*c8dee2aaSAndroid Build Coastguard Worker         fHWConservativeRasterEnabled = kUnknown_TriState;
648*c8dee2aaSAndroid Build Coastguard Worker     }
649*c8dee2aaSAndroid Build Coastguard Worker 
650*c8dee2aaSAndroid Build Coastguard Worker     fHWActiveTextureUnitIdx = -1; // invalid
651*c8dee2aaSAndroid Build Coastguard Worker     fLastPrimitiveType = static_cast<GrPrimitiveType>(-1);
652*c8dee2aaSAndroid Build Coastguard Worker 
653*c8dee2aaSAndroid Build Coastguard Worker     if (resetBits & kTextureBinding_GrGLBackendState) {
654*c8dee2aaSAndroid Build Coastguard Worker         for (int s = 0; s < this->numTextureUnits(); ++s) {
655*c8dee2aaSAndroid Build Coastguard Worker             fHWTextureUnitBindings[s].invalidateAllTargets(false);
656*c8dee2aaSAndroid Build Coastguard Worker         }
657*c8dee2aaSAndroid Build Coastguard Worker         if (fSamplerObjectCache) {
658*c8dee2aaSAndroid Build Coastguard Worker             fSamplerObjectCache->invalidateBindings();
659*c8dee2aaSAndroid Build Coastguard Worker         }
660*c8dee2aaSAndroid Build Coastguard Worker     }
661*c8dee2aaSAndroid Build Coastguard Worker 
662*c8dee2aaSAndroid Build Coastguard Worker     if (resetBits & kBlend_GrGLBackendState) {
663*c8dee2aaSAndroid Build Coastguard Worker         fHWBlendState.invalidate();
664*c8dee2aaSAndroid Build Coastguard Worker     }
665*c8dee2aaSAndroid Build Coastguard Worker 
666*c8dee2aaSAndroid Build Coastguard Worker     if (resetBits & kView_GrGLBackendState) {
667*c8dee2aaSAndroid Build Coastguard Worker         fHWScissorSettings.invalidate();
668*c8dee2aaSAndroid Build Coastguard Worker         fHWWindowRectsState.invalidate();
669*c8dee2aaSAndroid Build Coastguard Worker         fHWViewport.invalidate();
670*c8dee2aaSAndroid Build Coastguard Worker     }
671*c8dee2aaSAndroid Build Coastguard Worker 
672*c8dee2aaSAndroid Build Coastguard Worker     if (resetBits & kStencil_GrGLBackendState) {
673*c8dee2aaSAndroid Build Coastguard Worker         fHWStencilSettings.invalidate();
674*c8dee2aaSAndroid Build Coastguard Worker         fHWStencilTestEnabled = kUnknown_TriState;
675*c8dee2aaSAndroid Build Coastguard Worker     }
676*c8dee2aaSAndroid Build Coastguard Worker 
677*c8dee2aaSAndroid Build Coastguard Worker     // Vertex
678*c8dee2aaSAndroid Build Coastguard Worker     if (resetBits & kVertex_GrGLBackendState) {
679*c8dee2aaSAndroid Build Coastguard Worker         fHWVertexArrayState.invalidate();
680*c8dee2aaSAndroid Build Coastguard Worker         this->hwBufferState(GrGpuBufferType::kVertex)->invalidate();
681*c8dee2aaSAndroid Build Coastguard Worker         this->hwBufferState(GrGpuBufferType::kIndex)->invalidate();
682*c8dee2aaSAndroid Build Coastguard Worker         this->hwBufferState(GrGpuBufferType::kDrawIndirect)->invalidate();
683*c8dee2aaSAndroid Build Coastguard Worker     }
684*c8dee2aaSAndroid Build Coastguard Worker 
685*c8dee2aaSAndroid Build Coastguard Worker     if (resetBits & kRenderTarget_GrGLBackendState) {
686*c8dee2aaSAndroid Build Coastguard Worker         fHWBoundRenderTargetUniqueID.makeInvalid();
687*c8dee2aaSAndroid Build Coastguard Worker         fHWSRGBFramebuffer = kUnknown_TriState;
688*c8dee2aaSAndroid Build Coastguard Worker         fBoundDrawFramebuffer = 0;
689*c8dee2aaSAndroid Build Coastguard Worker     }
690*c8dee2aaSAndroid Build Coastguard Worker 
691*c8dee2aaSAndroid Build Coastguard Worker     // we assume these values
692*c8dee2aaSAndroid Build Coastguard Worker     if (resetBits & kPixelStore_GrGLBackendState) {
693*c8dee2aaSAndroid Build Coastguard Worker         if (this->caps()->writePixelsRowBytesSupport() ||
694*c8dee2aaSAndroid Build Coastguard Worker             this->caps()->transferPixelsToRowBytesSupport()) {
695*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, 0));
696*c8dee2aaSAndroid Build Coastguard Worker         }
697*c8dee2aaSAndroid Build Coastguard Worker         if (this->glCaps().readPixelsRowBytesSupport()) {
698*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(PixelStorei(GR_GL_PACK_ROW_LENGTH, 0));
699*c8dee2aaSAndroid Build Coastguard Worker         }
700*c8dee2aaSAndroid Build Coastguard Worker         if (this->glCaps().packFlipYSupport()) {
701*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(PixelStorei(GR_GL_PACK_REVERSE_ROW_ORDER, GR_GL_FALSE));
702*c8dee2aaSAndroid Build Coastguard Worker         }
703*c8dee2aaSAndroid Build Coastguard Worker     }
704*c8dee2aaSAndroid Build Coastguard Worker 
705*c8dee2aaSAndroid Build Coastguard Worker     if (resetBits & kProgram_GrGLBackendState) {
706*c8dee2aaSAndroid Build Coastguard Worker         fHWProgramID = 0;
707*c8dee2aaSAndroid Build Coastguard Worker         fHWProgram.reset();
708*c8dee2aaSAndroid Build Coastguard Worker     }
709*c8dee2aaSAndroid Build Coastguard Worker     ++fResetTimestampForTextureParameters;
710*c8dee2aaSAndroid Build Coastguard Worker }
711*c8dee2aaSAndroid Build Coastguard Worker 
check_backend_texture(const GrBackendTexture & backendTex,const GrGLCaps & caps,GrGLTexture::Desc * desc,bool skipRectTexSupportCheck=false)712*c8dee2aaSAndroid Build Coastguard Worker static bool check_backend_texture(const GrBackendTexture& backendTex,
713*c8dee2aaSAndroid Build Coastguard Worker                                   const GrGLCaps& caps,
714*c8dee2aaSAndroid Build Coastguard Worker                                   GrGLTexture::Desc* desc,
715*c8dee2aaSAndroid Build Coastguard Worker                                   bool skipRectTexSupportCheck = false) {
716*c8dee2aaSAndroid Build Coastguard Worker     GrGLTextureInfo info;
717*c8dee2aaSAndroid Build Coastguard Worker     if (!GrBackendTextures::GetGLTextureInfo(backendTex, &info) || !info.fID || !info.fFormat) {
718*c8dee2aaSAndroid Build Coastguard Worker         return false;
719*c8dee2aaSAndroid Build Coastguard Worker     }
720*c8dee2aaSAndroid Build Coastguard Worker 
721*c8dee2aaSAndroid Build Coastguard Worker     if (info.fProtected == skgpu::Protected::kYes && !caps.supportsProtectedContent()) {
722*c8dee2aaSAndroid Build Coastguard Worker         return false;
723*c8dee2aaSAndroid Build Coastguard Worker     }
724*c8dee2aaSAndroid Build Coastguard Worker 
725*c8dee2aaSAndroid Build Coastguard Worker     desc->fSize = {backendTex.width(), backendTex.height()};
726*c8dee2aaSAndroid Build Coastguard Worker     desc->fTarget = info.fTarget;
727*c8dee2aaSAndroid Build Coastguard Worker     desc->fID = info.fID;
728*c8dee2aaSAndroid Build Coastguard Worker     desc->fFormat = GrGLFormatFromGLEnum(info.fFormat);
729*c8dee2aaSAndroid Build Coastguard Worker     desc->fIsProtected = skgpu::Protected(info.fProtected == skgpu::Protected::kYes ||
730*c8dee2aaSAndroid Build Coastguard Worker                                           caps.strictProtectedness());
731*c8dee2aaSAndroid Build Coastguard Worker 
732*c8dee2aaSAndroid Build Coastguard Worker     if (desc->fFormat == GrGLFormat::kUnknown) {
733*c8dee2aaSAndroid Build Coastguard Worker         return false;
734*c8dee2aaSAndroid Build Coastguard Worker     }
735*c8dee2aaSAndroid Build Coastguard Worker     if (GR_GL_TEXTURE_EXTERNAL == desc->fTarget) {
736*c8dee2aaSAndroid Build Coastguard Worker         if (!caps.shaderCaps()->fExternalTextureSupport) {
737*c8dee2aaSAndroid Build Coastguard Worker             return false;
738*c8dee2aaSAndroid Build Coastguard Worker         }
739*c8dee2aaSAndroid Build Coastguard Worker     } else if (GR_GL_TEXTURE_RECTANGLE == desc->fTarget) {
740*c8dee2aaSAndroid Build Coastguard Worker         if (!caps.rectangleTextureSupport() && !skipRectTexSupportCheck) {
741*c8dee2aaSAndroid Build Coastguard Worker             return false;
742*c8dee2aaSAndroid Build Coastguard Worker         }
743*c8dee2aaSAndroid Build Coastguard Worker     } else if (GR_GL_TEXTURE_2D != desc->fTarget) {
744*c8dee2aaSAndroid Build Coastguard Worker         return false;
745*c8dee2aaSAndroid Build Coastguard Worker     }
746*c8dee2aaSAndroid Build Coastguard Worker 
747*c8dee2aaSAndroid Build Coastguard Worker 
748*c8dee2aaSAndroid Build Coastguard Worker     return true;
749*c8dee2aaSAndroid Build Coastguard Worker }
750*c8dee2aaSAndroid Build Coastguard Worker 
get_gl_texture_params(const GrBackendTexture & backendTex)751*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<GrGLTextureParameters> get_gl_texture_params(const GrBackendTexture& backendTex) {
752*c8dee2aaSAndroid Build Coastguard Worker     const GrBackendTextureData* btd = GrBackendSurfacePriv::GetBackendData(backendTex);
753*c8dee2aaSAndroid Build Coastguard Worker     auto glTextureData = static_cast<const GrGLBackendTextureData*>(btd);
754*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(glTextureData);
755*c8dee2aaSAndroid Build Coastguard Worker     return glTextureData->info().refParameters();
756*c8dee2aaSAndroid Build Coastguard Worker }
757*c8dee2aaSAndroid Build Coastguard Worker 
onWrapBackendTexture(const GrBackendTexture & backendTex,GrWrapOwnership ownership,GrWrapCacheable cacheable,GrIOType ioType)758*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrTexture> GrGLGpu::onWrapBackendTexture(const GrBackendTexture& backendTex,
759*c8dee2aaSAndroid Build Coastguard Worker                                                GrWrapOwnership ownership,
760*c8dee2aaSAndroid Build Coastguard Worker                                                GrWrapCacheable cacheable,
761*c8dee2aaSAndroid Build Coastguard Worker                                                GrIOType ioType) {
762*c8dee2aaSAndroid Build Coastguard Worker     GrGLTexture::Desc desc;
763*c8dee2aaSAndroid Build Coastguard Worker     if (!check_backend_texture(backendTex, this->glCaps(), &desc)) {
764*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
765*c8dee2aaSAndroid Build Coastguard Worker     }
766*c8dee2aaSAndroid Build Coastguard Worker 
767*c8dee2aaSAndroid Build Coastguard Worker     if (kBorrow_GrWrapOwnership == ownership) {
768*c8dee2aaSAndroid Build Coastguard Worker         desc.fOwnership = GrBackendObjectOwnership::kBorrowed;
769*c8dee2aaSAndroid Build Coastguard Worker     } else {
770*c8dee2aaSAndroid Build Coastguard Worker         desc.fOwnership = GrBackendObjectOwnership::kOwned;
771*c8dee2aaSAndroid Build Coastguard Worker     }
772*c8dee2aaSAndroid Build Coastguard Worker 
773*c8dee2aaSAndroid Build Coastguard Worker     GrMipmapStatus mipmapStatus = backendTex.hasMipmaps() ? GrMipmapStatus::kValid
774*c8dee2aaSAndroid Build Coastguard Worker                                                           : GrMipmapStatus::kNotAllocated;
775*c8dee2aaSAndroid Build Coastguard Worker 
776*c8dee2aaSAndroid Build Coastguard Worker     auto texture = GrGLTexture::MakeWrapped(this,
777*c8dee2aaSAndroid Build Coastguard Worker                                             mipmapStatus,
778*c8dee2aaSAndroid Build Coastguard Worker                                             desc,
779*c8dee2aaSAndroid Build Coastguard Worker                                             get_gl_texture_params(backendTex),
780*c8dee2aaSAndroid Build Coastguard Worker                                             cacheable,
781*c8dee2aaSAndroid Build Coastguard Worker                                             ioType,
782*c8dee2aaSAndroid Build Coastguard Worker                                             backendTex.getLabel());
783*c8dee2aaSAndroid Build Coastguard Worker     if (this->glCaps().isFormatRenderable(backendTex.getBackendFormat(), 1)) {
784*c8dee2aaSAndroid Build Coastguard Worker         // Pessimistically assume this external texture may have been bound to a FBO.
785*c8dee2aaSAndroid Build Coastguard Worker         texture->baseLevelWasBoundToFBO();
786*c8dee2aaSAndroid Build Coastguard Worker     }
787*c8dee2aaSAndroid Build Coastguard Worker     return texture;
788*c8dee2aaSAndroid Build Coastguard Worker }
789*c8dee2aaSAndroid Build Coastguard Worker 
check_compressed_backend_texture(const GrBackendTexture & backendTex,const GrGLCaps & caps,GrGLTexture::Desc * desc,bool skipRectTexSupportCheck=false)790*c8dee2aaSAndroid Build Coastguard Worker static bool check_compressed_backend_texture(const GrBackendTexture& backendTex,
791*c8dee2aaSAndroid Build Coastguard Worker                                              const GrGLCaps& caps, GrGLTexture::Desc* desc,
792*c8dee2aaSAndroid Build Coastguard Worker                                              bool skipRectTexSupportCheck = false) {
793*c8dee2aaSAndroid Build Coastguard Worker     GrGLTextureInfo info;
794*c8dee2aaSAndroid Build Coastguard Worker     if (!GrBackendTextures::GetGLTextureInfo(backendTex, &info) || !info.fID || !info.fFormat) {
795*c8dee2aaSAndroid Build Coastguard Worker         return false;
796*c8dee2aaSAndroid Build Coastguard Worker     }
797*c8dee2aaSAndroid Build Coastguard Worker     if (info.fProtected == skgpu::Protected::kYes && !caps.supportsProtectedContent()) {
798*c8dee2aaSAndroid Build Coastguard Worker         return false;
799*c8dee2aaSAndroid Build Coastguard Worker     }
800*c8dee2aaSAndroid Build Coastguard Worker 
801*c8dee2aaSAndroid Build Coastguard Worker     desc->fSize = {backendTex.width(), backendTex.height()};
802*c8dee2aaSAndroid Build Coastguard Worker     desc->fTarget = info.fTarget;
803*c8dee2aaSAndroid Build Coastguard Worker     desc->fID = info.fID;
804*c8dee2aaSAndroid Build Coastguard Worker     desc->fFormat = GrGLFormatFromGLEnum(info.fFormat);
805*c8dee2aaSAndroid Build Coastguard Worker     desc->fIsProtected = skgpu::Protected(info.fProtected == skgpu::Protected::kYes ||
806*c8dee2aaSAndroid Build Coastguard Worker                                           caps.strictProtectedness());
807*c8dee2aaSAndroid Build Coastguard Worker 
808*c8dee2aaSAndroid Build Coastguard Worker     if (desc->fFormat == GrGLFormat::kUnknown) {
809*c8dee2aaSAndroid Build Coastguard Worker         return false;
810*c8dee2aaSAndroid Build Coastguard Worker     }
811*c8dee2aaSAndroid Build Coastguard Worker 
812*c8dee2aaSAndroid Build Coastguard Worker     if (GR_GL_TEXTURE_2D != desc->fTarget) {
813*c8dee2aaSAndroid Build Coastguard Worker         return false;
814*c8dee2aaSAndroid Build Coastguard Worker     }
815*c8dee2aaSAndroid Build Coastguard Worker 
816*c8dee2aaSAndroid Build Coastguard Worker     return true;
817*c8dee2aaSAndroid Build Coastguard Worker }
818*c8dee2aaSAndroid Build Coastguard Worker 
onWrapCompressedBackendTexture(const GrBackendTexture & backendTex,GrWrapOwnership ownership,GrWrapCacheable cacheable)819*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrTexture> GrGLGpu::onWrapCompressedBackendTexture(const GrBackendTexture& backendTex,
820*c8dee2aaSAndroid Build Coastguard Worker                                                          GrWrapOwnership ownership,
821*c8dee2aaSAndroid Build Coastguard Worker                                                          GrWrapCacheable cacheable) {
822*c8dee2aaSAndroid Build Coastguard Worker     GrGLTexture::Desc desc;
823*c8dee2aaSAndroid Build Coastguard Worker     if (!check_compressed_backend_texture(backendTex, this->glCaps(), &desc)) {
824*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
825*c8dee2aaSAndroid Build Coastguard Worker     }
826*c8dee2aaSAndroid Build Coastguard Worker 
827*c8dee2aaSAndroid Build Coastguard Worker     if (kBorrow_GrWrapOwnership == ownership) {
828*c8dee2aaSAndroid Build Coastguard Worker         desc.fOwnership = GrBackendObjectOwnership::kBorrowed;
829*c8dee2aaSAndroid Build Coastguard Worker     } else {
830*c8dee2aaSAndroid Build Coastguard Worker         desc.fOwnership = GrBackendObjectOwnership::kOwned;
831*c8dee2aaSAndroid Build Coastguard Worker     }
832*c8dee2aaSAndroid Build Coastguard Worker 
833*c8dee2aaSAndroid Build Coastguard Worker     GrMipmapStatus mipmapStatus = backendTex.hasMipmaps() ? GrMipmapStatus::kValid
834*c8dee2aaSAndroid Build Coastguard Worker                                                           : GrMipmapStatus::kNotAllocated;
835*c8dee2aaSAndroid Build Coastguard Worker 
836*c8dee2aaSAndroid Build Coastguard Worker     return GrGLTexture::MakeWrapped(this,
837*c8dee2aaSAndroid Build Coastguard Worker                                     mipmapStatus,
838*c8dee2aaSAndroid Build Coastguard Worker                                     desc,
839*c8dee2aaSAndroid Build Coastguard Worker                                     get_gl_texture_params(backendTex),
840*c8dee2aaSAndroid Build Coastguard Worker                                     cacheable,
841*c8dee2aaSAndroid Build Coastguard Worker                                     kRead_GrIOType,
842*c8dee2aaSAndroid Build Coastguard Worker                                     backendTex.getLabel());
843*c8dee2aaSAndroid Build Coastguard Worker }
844*c8dee2aaSAndroid Build Coastguard Worker 
onWrapRenderableBackendTexture(const GrBackendTexture & backendTex,int sampleCnt,GrWrapOwnership ownership,GrWrapCacheable cacheable)845*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrTexture> GrGLGpu::onWrapRenderableBackendTexture(const GrBackendTexture& backendTex,
846*c8dee2aaSAndroid Build Coastguard Worker                                                          int sampleCnt,
847*c8dee2aaSAndroid Build Coastguard Worker                                                          GrWrapOwnership ownership,
848*c8dee2aaSAndroid Build Coastguard Worker                                                          GrWrapCacheable cacheable) {
849*c8dee2aaSAndroid Build Coastguard Worker     const GrGLCaps& caps = this->glCaps();
850*c8dee2aaSAndroid Build Coastguard Worker 
851*c8dee2aaSAndroid Build Coastguard Worker     GrGLTexture::Desc desc;
852*c8dee2aaSAndroid Build Coastguard Worker     if (!check_backend_texture(backendTex, this->glCaps(), &desc)) {
853*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
854*c8dee2aaSAndroid Build Coastguard Worker     }
855*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(caps.isFormatRenderable(desc.fFormat, sampleCnt));
856*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(caps.isFormatTexturable(desc.fFormat));
857*c8dee2aaSAndroid Build Coastguard Worker 
858*c8dee2aaSAndroid Build Coastguard Worker     // We don't support rendering to a EXTERNAL texture.
859*c8dee2aaSAndroid Build Coastguard Worker     if (GR_GL_TEXTURE_EXTERNAL == desc.fTarget) {
860*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
861*c8dee2aaSAndroid Build Coastguard Worker     }
862*c8dee2aaSAndroid Build Coastguard Worker 
863*c8dee2aaSAndroid Build Coastguard Worker     if (kBorrow_GrWrapOwnership == ownership) {
864*c8dee2aaSAndroid Build Coastguard Worker         desc.fOwnership = GrBackendObjectOwnership::kBorrowed;
865*c8dee2aaSAndroid Build Coastguard Worker     } else {
866*c8dee2aaSAndroid Build Coastguard Worker         desc.fOwnership = GrBackendObjectOwnership::kOwned;
867*c8dee2aaSAndroid Build Coastguard Worker     }
868*c8dee2aaSAndroid Build Coastguard Worker 
869*c8dee2aaSAndroid Build Coastguard Worker 
870*c8dee2aaSAndroid Build Coastguard Worker     sampleCnt = caps.getRenderTargetSampleCount(sampleCnt, desc.fFormat);
871*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(sampleCnt);
872*c8dee2aaSAndroid Build Coastguard Worker 
873*c8dee2aaSAndroid Build Coastguard Worker     GrGLRenderTarget::IDs rtIDs;
874*c8dee2aaSAndroid Build Coastguard Worker     if (!this->createRenderTargetObjects(desc, sampleCnt, &rtIDs)) {
875*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
876*c8dee2aaSAndroid Build Coastguard Worker     }
877*c8dee2aaSAndroid Build Coastguard Worker 
878*c8dee2aaSAndroid Build Coastguard Worker     GrMipmapStatus mipmapStatus = backendTex.hasMipmaps() ? GrMipmapStatus::kDirty
879*c8dee2aaSAndroid Build Coastguard Worker                                                           : GrMipmapStatus::kNotAllocated;
880*c8dee2aaSAndroid Build Coastguard Worker 
881*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<GrGLTextureRenderTarget> texRT(
882*c8dee2aaSAndroid Build Coastguard Worker             GrGLTextureRenderTarget::MakeWrapped(this,
883*c8dee2aaSAndroid Build Coastguard Worker                                                  sampleCnt,
884*c8dee2aaSAndroid Build Coastguard Worker                                                  desc,
885*c8dee2aaSAndroid Build Coastguard Worker                                                  get_gl_texture_params(backendTex),
886*c8dee2aaSAndroid Build Coastguard Worker                                                  rtIDs,
887*c8dee2aaSAndroid Build Coastguard Worker                                                  cacheable,
888*c8dee2aaSAndroid Build Coastguard Worker                                                  mipmapStatus,
889*c8dee2aaSAndroid Build Coastguard Worker                                                  backendTex.getLabel()));
890*c8dee2aaSAndroid Build Coastguard Worker     texRT->baseLevelWasBoundToFBO();
891*c8dee2aaSAndroid Build Coastguard Worker     return texRT;
892*c8dee2aaSAndroid Build Coastguard Worker }
893*c8dee2aaSAndroid Build Coastguard Worker 
onWrapBackendRenderTarget(const GrBackendRenderTarget & backendRT)894*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrRenderTarget> GrGLGpu::onWrapBackendRenderTarget(const GrBackendRenderTarget& backendRT) {
895*c8dee2aaSAndroid Build Coastguard Worker     GrGLFramebufferInfo info;
896*c8dee2aaSAndroid Build Coastguard Worker     if (!GrBackendRenderTargets::GetGLFramebufferInfo(backendRT, &info)) {
897*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
898*c8dee2aaSAndroid Build Coastguard Worker     }
899*c8dee2aaSAndroid Build Coastguard Worker 
900*c8dee2aaSAndroid Build Coastguard Worker     if (backendRT.isProtected() && !this->glCaps().supportsProtectedContent()) {
901*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
902*c8dee2aaSAndroid Build Coastguard Worker     }
903*c8dee2aaSAndroid Build Coastguard Worker 
904*c8dee2aaSAndroid Build Coastguard Worker     const auto format = GrBackendFormats::AsGLFormat(backendRT.getBackendFormat());
905*c8dee2aaSAndroid Build Coastguard Worker     if (!this->glCaps().isFormatRenderable(format, backendRT.sampleCnt())) {
906*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
907*c8dee2aaSAndroid Build Coastguard Worker     }
908*c8dee2aaSAndroid Build Coastguard Worker 
909*c8dee2aaSAndroid Build Coastguard Worker     int sampleCount = this->glCaps().getRenderTargetSampleCount(backendRT.sampleCnt(), format);
910*c8dee2aaSAndroid Build Coastguard Worker 
911*c8dee2aaSAndroid Build Coastguard Worker     GrGLRenderTarget::IDs rtIDs;
912*c8dee2aaSAndroid Build Coastguard Worker     if (sampleCount <= 1) {
913*c8dee2aaSAndroid Build Coastguard Worker         rtIDs.fSingleSampleFBOID = info.fFBOID;
914*c8dee2aaSAndroid Build Coastguard Worker         rtIDs.fMultisampleFBOID = GrGLRenderTarget::kUnresolvableFBOID;
915*c8dee2aaSAndroid Build Coastguard Worker     } else {
916*c8dee2aaSAndroid Build Coastguard Worker         rtIDs.fSingleSampleFBOID = GrGLRenderTarget::kUnresolvableFBOID;
917*c8dee2aaSAndroid Build Coastguard Worker         rtIDs.fMultisampleFBOID = info.fFBOID;
918*c8dee2aaSAndroid Build Coastguard Worker     }
919*c8dee2aaSAndroid Build Coastguard Worker     rtIDs.fMSColorRenderbufferID = 0;
920*c8dee2aaSAndroid Build Coastguard Worker     rtIDs.fRTFBOOwnership = GrBackendObjectOwnership::kBorrowed;
921*c8dee2aaSAndroid Build Coastguard Worker     rtIDs.fTotalMemorySamplesPerPixel = sampleCount;
922*c8dee2aaSAndroid Build Coastguard Worker 
923*c8dee2aaSAndroid Build Coastguard Worker     return GrGLRenderTarget::MakeWrapped(this,
924*c8dee2aaSAndroid Build Coastguard Worker                                          backendRT.dimensions(),
925*c8dee2aaSAndroid Build Coastguard Worker                                          format,
926*c8dee2aaSAndroid Build Coastguard Worker                                          sampleCount,
927*c8dee2aaSAndroid Build Coastguard Worker                                          rtIDs,
928*c8dee2aaSAndroid Build Coastguard Worker                                          backendRT.stencilBits(),
929*c8dee2aaSAndroid Build Coastguard Worker                                          skgpu::Protected(backendRT.isProtected()),
930*c8dee2aaSAndroid Build Coastguard Worker                                          /*label=*/"GLGpu_WrapBackendRenderTarget");
931*c8dee2aaSAndroid Build Coastguard Worker }
932*c8dee2aaSAndroid Build Coastguard Worker 
check_write_and_transfer_input(GrGLTexture * glTex)933*c8dee2aaSAndroid Build Coastguard Worker static bool check_write_and_transfer_input(GrGLTexture* glTex) {
934*c8dee2aaSAndroid Build Coastguard Worker     if (!glTex) {
935*c8dee2aaSAndroid Build Coastguard Worker         return false;
936*c8dee2aaSAndroid Build Coastguard Worker     }
937*c8dee2aaSAndroid Build Coastguard Worker 
938*c8dee2aaSAndroid Build Coastguard Worker     // Write or transfer of pixels is not implemented for TEXTURE_EXTERNAL textures
939*c8dee2aaSAndroid Build Coastguard Worker     if (GR_GL_TEXTURE_EXTERNAL == glTex->target()) {
940*c8dee2aaSAndroid Build Coastguard Worker         return false;
941*c8dee2aaSAndroid Build Coastguard Worker     }
942*c8dee2aaSAndroid Build Coastguard Worker 
943*c8dee2aaSAndroid Build Coastguard Worker     return true;
944*c8dee2aaSAndroid Build Coastguard Worker }
945*c8dee2aaSAndroid Build Coastguard Worker 
onWritePixels(GrSurface * surface,SkIRect rect,GrColorType surfaceColorType,GrColorType srcColorType,const GrMipLevel texels[],int mipLevelCount,bool prepForTexSampling)946*c8dee2aaSAndroid Build Coastguard Worker bool GrGLGpu::onWritePixels(GrSurface* surface,
947*c8dee2aaSAndroid Build Coastguard Worker                             SkIRect rect,
948*c8dee2aaSAndroid Build Coastguard Worker                             GrColorType surfaceColorType,
949*c8dee2aaSAndroid Build Coastguard Worker                             GrColorType srcColorType,
950*c8dee2aaSAndroid Build Coastguard Worker                             const GrMipLevel texels[],
951*c8dee2aaSAndroid Build Coastguard Worker                             int mipLevelCount,
952*c8dee2aaSAndroid Build Coastguard Worker                             bool prepForTexSampling) {
953*c8dee2aaSAndroid Build Coastguard Worker     auto glTex = static_cast<GrGLTexture*>(surface->asTexture());
954*c8dee2aaSAndroid Build Coastguard Worker 
955*c8dee2aaSAndroid Build Coastguard Worker     if (!check_write_and_transfer_input(glTex)) {
956*c8dee2aaSAndroid Build Coastguard Worker         return false;
957*c8dee2aaSAndroid Build Coastguard Worker     }
958*c8dee2aaSAndroid Build Coastguard Worker 
959*c8dee2aaSAndroid Build Coastguard Worker     this->bindTextureToScratchUnit(glTex->target(), glTex->textureID());
960*c8dee2aaSAndroid Build Coastguard Worker 
961*c8dee2aaSAndroid Build Coastguard Worker     // If we have mips make sure the base/max levels cover the full range so that the uploads go to
962*c8dee2aaSAndroid Build Coastguard Worker     // the right levels. We've found some Radeons require this.
963*c8dee2aaSAndroid Build Coastguard Worker     if (mipLevelCount && this->glCaps().mipmapLevelControlSupport()) {
964*c8dee2aaSAndroid Build Coastguard Worker         auto params = glTex->parameters();
965*c8dee2aaSAndroid Build Coastguard Worker         GrGLTextureParameters::NonsamplerState nonsamplerState = params->nonsamplerState();
966*c8dee2aaSAndroid Build Coastguard Worker         int maxLevel = glTex->maxMipmapLevel();
967*c8dee2aaSAndroid Build Coastguard Worker         if (params->nonsamplerState().fBaseMipMapLevel != 0) {
968*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(TexParameteri(glTex->target(), GR_GL_TEXTURE_BASE_LEVEL, 0));
969*c8dee2aaSAndroid Build Coastguard Worker             nonsamplerState.fBaseMipMapLevel = 0;
970*c8dee2aaSAndroid Build Coastguard Worker         }
971*c8dee2aaSAndroid Build Coastguard Worker         if (params->nonsamplerState().fMaxMipmapLevel != maxLevel) {
972*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(TexParameteri(glTex->target(), GR_GL_TEXTURE_MAX_LEVEL, maxLevel));
973*c8dee2aaSAndroid Build Coastguard Worker             nonsamplerState.fBaseMipMapLevel = maxLevel;
974*c8dee2aaSAndroid Build Coastguard Worker         }
975*c8dee2aaSAndroid Build Coastguard Worker         params->set(nullptr, nonsamplerState, fResetTimestampForTextureParameters);
976*c8dee2aaSAndroid Build Coastguard Worker     }
977*c8dee2aaSAndroid Build Coastguard Worker 
978*c8dee2aaSAndroid Build Coastguard Worker     if (this->glCaps().flushBeforeWritePixels()) {
979*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(Flush());
980*c8dee2aaSAndroid Build Coastguard Worker     }
981*c8dee2aaSAndroid Build Coastguard Worker 
982*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!GrGLFormatIsCompressed(glTex->format()));
983*c8dee2aaSAndroid Build Coastguard Worker     return this->uploadColorTypeTexData(glTex->format(),
984*c8dee2aaSAndroid Build Coastguard Worker                                         surfaceColorType,
985*c8dee2aaSAndroid Build Coastguard Worker                                         glTex->dimensions(),
986*c8dee2aaSAndroid Build Coastguard Worker                                         glTex->target(),
987*c8dee2aaSAndroid Build Coastguard Worker                                         rect,
988*c8dee2aaSAndroid Build Coastguard Worker                                         srcColorType,
989*c8dee2aaSAndroid Build Coastguard Worker                                         texels,
990*c8dee2aaSAndroid Build Coastguard Worker                                         mipLevelCount);
991*c8dee2aaSAndroid Build Coastguard Worker }
992*c8dee2aaSAndroid Build Coastguard Worker 
onTransferFromBufferToBuffer(sk_sp<GrGpuBuffer> src,size_t srcOffset,sk_sp<GrGpuBuffer> dst,size_t dstOffset,size_t size)993*c8dee2aaSAndroid Build Coastguard Worker bool GrGLGpu::onTransferFromBufferToBuffer(sk_sp<GrGpuBuffer> src,
994*c8dee2aaSAndroid Build Coastguard Worker                                            size_t srcOffset,
995*c8dee2aaSAndroid Build Coastguard Worker                                            sk_sp<GrGpuBuffer> dst,
996*c8dee2aaSAndroid Build Coastguard Worker                                            size_t dstOffset,
997*c8dee2aaSAndroid Build Coastguard Worker                                            size_t size) {
998*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!src->isMapped());
999*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!dst->isMapped());
1000*c8dee2aaSAndroid Build Coastguard Worker 
1001*c8dee2aaSAndroid Build Coastguard Worker     auto glSrc = static_cast<const GrGLBuffer*>(src.get());
1002*c8dee2aaSAndroid Build Coastguard Worker     auto glDst = static_cast<const GrGLBuffer*>(dst.get());
1003*c8dee2aaSAndroid Build Coastguard Worker 
1004*c8dee2aaSAndroid Build Coastguard Worker     // If we refactored bindBuffer() to use something other than GrGpuBufferType to indicate the
1005*c8dee2aaSAndroid Build Coastguard Worker     // binding target then we could use the COPY_READ and COPY_WRITE targets here. But
1006*c8dee2aaSAndroid Build Coastguard Worker     // CopyBufferSubData is documented to work with all the targets so it's not clear it's worth it.
1007*c8dee2aaSAndroid Build Coastguard Worker     this->bindBuffer(GrGpuBufferType::kXferCpuToGpu, glSrc);
1008*c8dee2aaSAndroid Build Coastguard Worker     this->bindBuffer(GrGpuBufferType::kXferGpuToCpu, glDst);
1009*c8dee2aaSAndroid Build Coastguard Worker 
1010*c8dee2aaSAndroid Build Coastguard Worker     GL_CALL(CopyBufferSubData(GR_GL_PIXEL_UNPACK_BUFFER,
1011*c8dee2aaSAndroid Build Coastguard Worker                               GR_GL_PIXEL_PACK_BUFFER,
1012*c8dee2aaSAndroid Build Coastguard Worker                               srcOffset,
1013*c8dee2aaSAndroid Build Coastguard Worker                               dstOffset,
1014*c8dee2aaSAndroid Build Coastguard Worker                               size));
1015*c8dee2aaSAndroid Build Coastguard Worker     return true;
1016*c8dee2aaSAndroid Build Coastguard Worker }
1017*c8dee2aaSAndroid Build Coastguard Worker 
onTransferPixelsTo(GrTexture * texture,SkIRect rect,GrColorType textureColorType,GrColorType bufferColorType,sk_sp<GrGpuBuffer> transferBuffer,size_t offset,size_t rowBytes)1018*c8dee2aaSAndroid Build Coastguard Worker bool GrGLGpu::onTransferPixelsTo(GrTexture* texture,
1019*c8dee2aaSAndroid Build Coastguard Worker                                  SkIRect rect,
1020*c8dee2aaSAndroid Build Coastguard Worker                                  GrColorType textureColorType,
1021*c8dee2aaSAndroid Build Coastguard Worker                                  GrColorType bufferColorType,
1022*c8dee2aaSAndroid Build Coastguard Worker                                  sk_sp<GrGpuBuffer> transferBuffer,
1023*c8dee2aaSAndroid Build Coastguard Worker                                  size_t offset,
1024*c8dee2aaSAndroid Build Coastguard Worker                                  size_t rowBytes) {
1025*c8dee2aaSAndroid Build Coastguard Worker     GrGLTexture* glTex = static_cast<GrGLTexture*>(texture);
1026*c8dee2aaSAndroid Build Coastguard Worker 
1027*c8dee2aaSAndroid Build Coastguard Worker     // Can't transfer compressed data
1028*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!GrGLFormatIsCompressed(glTex->format()));
1029*c8dee2aaSAndroid Build Coastguard Worker 
1030*c8dee2aaSAndroid Build Coastguard Worker     if (!check_write_and_transfer_input(glTex)) {
1031*c8dee2aaSAndroid Build Coastguard Worker         return false;
1032*c8dee2aaSAndroid Build Coastguard Worker     }
1033*c8dee2aaSAndroid Build Coastguard Worker 
1034*c8dee2aaSAndroid Build Coastguard Worker     static_assert(sizeof(int) == sizeof(int32_t), "");
1035*c8dee2aaSAndroid Build Coastguard Worker 
1036*c8dee2aaSAndroid Build Coastguard Worker     this->bindTextureToScratchUnit(glTex->target(), glTex->textureID());
1037*c8dee2aaSAndroid Build Coastguard Worker 
1038*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!transferBuffer->isMapped());
1039*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!transferBuffer->isCpuBuffer());
1040*c8dee2aaSAndroid Build Coastguard Worker     const GrGLBuffer* glBuffer = static_cast<const GrGLBuffer*>(transferBuffer.get());
1041*c8dee2aaSAndroid Build Coastguard Worker     this->bindBuffer(GrGpuBufferType::kXferCpuToGpu, glBuffer);
1042*c8dee2aaSAndroid Build Coastguard Worker 
1043*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(SkIRect::MakeSize(texture->dimensions()).contains(rect));
1044*c8dee2aaSAndroid Build Coastguard Worker 
1045*c8dee2aaSAndroid Build Coastguard Worker     size_t bpp = GrColorTypeBytesPerPixel(bufferColorType);
1046*c8dee2aaSAndroid Build Coastguard Worker     const size_t trimRowBytes = rect.width() * bpp;
1047*c8dee2aaSAndroid Build Coastguard Worker     const void* pixels = (void*)offset;
1048*c8dee2aaSAndroid Build Coastguard Worker 
1049*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(glBuffer->size() >= offset + rowBytes*(rect.height() - 1) + trimRowBytes);
1050*c8dee2aaSAndroid Build Coastguard Worker 
1051*c8dee2aaSAndroid Build Coastguard Worker     bool restoreGLRowLength = false;
1052*c8dee2aaSAndroid Build Coastguard Worker     if (trimRowBytes != rowBytes) {
1053*c8dee2aaSAndroid Build Coastguard Worker         // we should have checked for this support already
1054*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(this->glCaps().transferPixelsToRowBytesSupport());
1055*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, rowBytes / bpp));
1056*c8dee2aaSAndroid Build Coastguard Worker         restoreGLRowLength = true;
1057*c8dee2aaSAndroid Build Coastguard Worker     }
1058*c8dee2aaSAndroid Build Coastguard Worker 
1059*c8dee2aaSAndroid Build Coastguard Worker     GrGLFormat textureFormat = glTex->format();
1060*c8dee2aaSAndroid Build Coastguard Worker     // External format and type come from the upload data.
1061*c8dee2aaSAndroid Build Coastguard Worker     GrGLenum externalFormat = 0;
1062*c8dee2aaSAndroid Build Coastguard Worker     GrGLenum externalType = 0;
1063*c8dee2aaSAndroid Build Coastguard Worker     this->glCaps().getTexSubImageExternalFormatAndType(
1064*c8dee2aaSAndroid Build Coastguard Worker             textureFormat, textureColorType, bufferColorType, &externalFormat, &externalType);
1065*c8dee2aaSAndroid Build Coastguard Worker     if (!externalFormat || !externalType) {
1066*c8dee2aaSAndroid Build Coastguard Worker         return false;
1067*c8dee2aaSAndroid Build Coastguard Worker     }
1068*c8dee2aaSAndroid Build Coastguard Worker 
1069*c8dee2aaSAndroid Build Coastguard Worker     GL_CALL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, 1));
1070*c8dee2aaSAndroid Build Coastguard Worker     GL_CALL(TexSubImage2D(glTex->target(),
1071*c8dee2aaSAndroid Build Coastguard Worker                           0,
1072*c8dee2aaSAndroid Build Coastguard Worker                           rect.left(),
1073*c8dee2aaSAndroid Build Coastguard Worker                           rect.top(),
1074*c8dee2aaSAndroid Build Coastguard Worker                           rect.width(),
1075*c8dee2aaSAndroid Build Coastguard Worker                           rect.height(),
1076*c8dee2aaSAndroid Build Coastguard Worker                           externalFormat,
1077*c8dee2aaSAndroid Build Coastguard Worker                           externalType,
1078*c8dee2aaSAndroid Build Coastguard Worker                           pixels));
1079*c8dee2aaSAndroid Build Coastguard Worker 
1080*c8dee2aaSAndroid Build Coastguard Worker     if (restoreGLRowLength) {
1081*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, 0));
1082*c8dee2aaSAndroid Build Coastguard Worker     }
1083*c8dee2aaSAndroid Build Coastguard Worker 
1084*c8dee2aaSAndroid Build Coastguard Worker     return true;
1085*c8dee2aaSAndroid Build Coastguard Worker }
1086*c8dee2aaSAndroid Build Coastguard Worker 
onTransferPixelsFrom(GrSurface * surface,SkIRect rect,GrColorType surfaceColorType,GrColorType dstColorType,sk_sp<GrGpuBuffer> transferBuffer,size_t offset)1087*c8dee2aaSAndroid Build Coastguard Worker bool GrGLGpu::onTransferPixelsFrom(GrSurface* surface,
1088*c8dee2aaSAndroid Build Coastguard Worker                                    SkIRect rect,
1089*c8dee2aaSAndroid Build Coastguard Worker                                    GrColorType surfaceColorType,
1090*c8dee2aaSAndroid Build Coastguard Worker                                    GrColorType dstColorType,
1091*c8dee2aaSAndroid Build Coastguard Worker                                    sk_sp<GrGpuBuffer> transferBuffer,
1092*c8dee2aaSAndroid Build Coastguard Worker                                    size_t offset) {
1093*c8dee2aaSAndroid Build Coastguard Worker     auto* glBuffer = static_cast<GrGLBuffer*>(transferBuffer.get());
1094*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(glBuffer->size() >= offset + (rect.width() *
1095*c8dee2aaSAndroid Build Coastguard Worker                                            rect.height()*
1096*c8dee2aaSAndroid Build Coastguard Worker                                            GrColorTypeBytesPerPixel(dstColorType)));
1097*c8dee2aaSAndroid Build Coastguard Worker 
1098*c8dee2aaSAndroid Build Coastguard Worker     this->bindBuffer(GrGpuBufferType::kXferGpuToCpu, glBuffer);
1099*c8dee2aaSAndroid Build Coastguard Worker 
1100*c8dee2aaSAndroid Build Coastguard Worker     auto offsetAsPtr = reinterpret_cast<void*>(offset);
1101*c8dee2aaSAndroid Build Coastguard Worker     return this->readOrTransferPixelsFrom(surface,
1102*c8dee2aaSAndroid Build Coastguard Worker                                           rect,
1103*c8dee2aaSAndroid Build Coastguard Worker                                           surfaceColorType,
1104*c8dee2aaSAndroid Build Coastguard Worker                                           dstColorType,
1105*c8dee2aaSAndroid Build Coastguard Worker                                           offsetAsPtr,
1106*c8dee2aaSAndroid Build Coastguard Worker                                           rect.width());
1107*c8dee2aaSAndroid Build Coastguard Worker }
1108*c8dee2aaSAndroid Build Coastguard Worker 
unbindXferBuffer(GrGpuBufferType type)1109*c8dee2aaSAndroid Build Coastguard Worker void GrGLGpu::unbindXferBuffer(GrGpuBufferType type) {
1110*c8dee2aaSAndroid Build Coastguard Worker     if (this->glCaps().transferBufferType() != GrGLCaps::TransferBufferType::kARB_PBO &&
1111*c8dee2aaSAndroid Build Coastguard Worker         this->glCaps().transferBufferType() != GrGLCaps::TransferBufferType::kNV_PBO) {
1112*c8dee2aaSAndroid Build Coastguard Worker         return;
1113*c8dee2aaSAndroid Build Coastguard Worker     }
1114*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(type == GrGpuBufferType::kXferCpuToGpu || type == GrGpuBufferType::kXferGpuToCpu);
1115*c8dee2aaSAndroid Build Coastguard Worker     auto* xferBufferState = this->hwBufferState(type);
1116*c8dee2aaSAndroid Build Coastguard Worker     if (!xferBufferState->fBufferZeroKnownBound) {
1117*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(BindBuffer(xferBufferState->fGLTarget, 0));
1118*c8dee2aaSAndroid Build Coastguard Worker         xferBufferState->fBoundBufferUniqueID.makeInvalid();
1119*c8dee2aaSAndroid Build Coastguard Worker         xferBufferState->fBufferZeroKnownBound = true;
1120*c8dee2aaSAndroid Build Coastguard Worker     }
1121*c8dee2aaSAndroid Build Coastguard Worker }
1122*c8dee2aaSAndroid Build Coastguard Worker 
uploadColorTypeTexData(GrGLFormat textureFormat,GrColorType textureColorType,SkISize texDims,GrGLenum target,SkIRect dstRect,GrColorType srcColorType,const GrMipLevel texels[],int mipLevelCount)1123*c8dee2aaSAndroid Build Coastguard Worker bool GrGLGpu::uploadColorTypeTexData(GrGLFormat textureFormat,
1124*c8dee2aaSAndroid Build Coastguard Worker                                      GrColorType textureColorType,
1125*c8dee2aaSAndroid Build Coastguard Worker                                      SkISize texDims,
1126*c8dee2aaSAndroid Build Coastguard Worker                                      GrGLenum target,
1127*c8dee2aaSAndroid Build Coastguard Worker                                      SkIRect dstRect,
1128*c8dee2aaSAndroid Build Coastguard Worker                                      GrColorType srcColorType,
1129*c8dee2aaSAndroid Build Coastguard Worker                                      const GrMipLevel texels[],
1130*c8dee2aaSAndroid Build Coastguard Worker                                      int mipLevelCount) {
1131*c8dee2aaSAndroid Build Coastguard Worker     // If we're uploading compressed data then we should be using uploadCompressedTexData
1132*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!GrGLFormatIsCompressed(textureFormat));
1133*c8dee2aaSAndroid Build Coastguard Worker 
1134*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(this->glCaps().isFormatTexturable(textureFormat));
1135*c8dee2aaSAndroid Build Coastguard Worker 
1136*c8dee2aaSAndroid Build Coastguard Worker     size_t bpp = GrColorTypeBytesPerPixel(srcColorType);
1137*c8dee2aaSAndroid Build Coastguard Worker 
1138*c8dee2aaSAndroid Build Coastguard Worker     // External format and type come from the upload data.
1139*c8dee2aaSAndroid Build Coastguard Worker     GrGLenum externalFormat;
1140*c8dee2aaSAndroid Build Coastguard Worker     GrGLenum externalType;
1141*c8dee2aaSAndroid Build Coastguard Worker     this->glCaps().getTexSubImageExternalFormatAndType(
1142*c8dee2aaSAndroid Build Coastguard Worker             textureFormat, textureColorType, srcColorType, &externalFormat, &externalType);
1143*c8dee2aaSAndroid Build Coastguard Worker     if (!externalFormat || !externalType) {
1144*c8dee2aaSAndroid Build Coastguard Worker         return false;
1145*c8dee2aaSAndroid Build Coastguard Worker     }
1146*c8dee2aaSAndroid Build Coastguard Worker     this->uploadTexData(texDims, target, dstRect, externalFormat, externalType, bpp, texels,
1147*c8dee2aaSAndroid Build Coastguard Worker                         mipLevelCount);
1148*c8dee2aaSAndroid Build Coastguard Worker     return true;
1149*c8dee2aaSAndroid Build Coastguard Worker }
1150*c8dee2aaSAndroid Build Coastguard Worker 
uploadColorToTex(GrGLFormat textureFormat,SkISize texDims,GrGLenum target,std::array<float,4> color,uint32_t levelMask)1151*c8dee2aaSAndroid Build Coastguard Worker bool GrGLGpu::uploadColorToTex(GrGLFormat textureFormat,
1152*c8dee2aaSAndroid Build Coastguard Worker                                SkISize texDims,
1153*c8dee2aaSAndroid Build Coastguard Worker                                GrGLenum target,
1154*c8dee2aaSAndroid Build Coastguard Worker                                std::array<float, 4> color,
1155*c8dee2aaSAndroid Build Coastguard Worker                                uint32_t levelMask) {
1156*c8dee2aaSAndroid Build Coastguard Worker     GrColorType colorType;
1157*c8dee2aaSAndroid Build Coastguard Worker     GrGLenum externalFormat, externalType;
1158*c8dee2aaSAndroid Build Coastguard Worker     this->glCaps().getTexSubImageDefaultFormatTypeAndColorType(textureFormat, &externalFormat,
1159*c8dee2aaSAndroid Build Coastguard Worker                                                                &externalType, &colorType);
1160*c8dee2aaSAndroid Build Coastguard Worker     if (colorType == GrColorType::kUnknown) {
1161*c8dee2aaSAndroid Build Coastguard Worker         return false;
1162*c8dee2aaSAndroid Build Coastguard Worker     }
1163*c8dee2aaSAndroid Build Coastguard Worker 
1164*c8dee2aaSAndroid Build Coastguard Worker     std::unique_ptr<char[]> pixelStorage;
1165*c8dee2aaSAndroid Build Coastguard Worker     size_t bpp = 0;
1166*c8dee2aaSAndroid Build Coastguard Worker     int numLevels = SkMipmap::ComputeLevelCount(texDims) + 1;
1167*c8dee2aaSAndroid Build Coastguard Worker     STArray<16, GrMipLevel> levels;
1168*c8dee2aaSAndroid Build Coastguard Worker     levels.resize(numLevels);
1169*c8dee2aaSAndroid Build Coastguard Worker     SkISize levelDims = texDims;
1170*c8dee2aaSAndroid Build Coastguard Worker     for (int i = 0; i < numLevels; ++i, levelDims = {std::max(levelDims.width()  >> 1, 1),
1171*c8dee2aaSAndroid Build Coastguard Worker                                                      std::max(levelDims.height() >> 1, 1)}) {
1172*c8dee2aaSAndroid Build Coastguard Worker         if (levelMask & (1 << i)) {
1173*c8dee2aaSAndroid Build Coastguard Worker             if (!pixelStorage) {
1174*c8dee2aaSAndroid Build Coastguard Worker                 // Make one tight image at the first size and reuse it for smaller levels.
1175*c8dee2aaSAndroid Build Coastguard Worker                 GrImageInfo ii(colorType, kUnpremul_SkAlphaType, nullptr, levelDims);
1176*c8dee2aaSAndroid Build Coastguard Worker                 size_t rb = ii.minRowBytes();
1177*c8dee2aaSAndroid Build Coastguard Worker                 pixelStorage.reset(new char[rb * levelDims.height()]);
1178*c8dee2aaSAndroid Build Coastguard Worker                 if (!GrClearImage(ii, pixelStorage.get(), ii.minRowBytes(), color)) {
1179*c8dee2aaSAndroid Build Coastguard Worker                     return false;
1180*c8dee2aaSAndroid Build Coastguard Worker                 }
1181*c8dee2aaSAndroid Build Coastguard Worker                 bpp = ii.bpp();
1182*c8dee2aaSAndroid Build Coastguard Worker             }
1183*c8dee2aaSAndroid Build Coastguard Worker             levels[i] = {pixelStorage.get(), levelDims.width()*bpp, nullptr};
1184*c8dee2aaSAndroid Build Coastguard Worker         }
1185*c8dee2aaSAndroid Build Coastguard Worker     }
1186*c8dee2aaSAndroid Build Coastguard Worker     this->uploadTexData(texDims, target, SkIRect::MakeSize(texDims), externalFormat, externalType,
1187*c8dee2aaSAndroid Build Coastguard Worker                         bpp, levels.begin(), levels.size());
1188*c8dee2aaSAndroid Build Coastguard Worker     return true;
1189*c8dee2aaSAndroid Build Coastguard Worker }
1190*c8dee2aaSAndroid Build Coastguard Worker 
uploadTexData(SkISize texDims,GrGLenum target,SkIRect dstRect,GrGLenum externalFormat,GrGLenum externalType,size_t bpp,const GrMipLevel texels[],int mipLevelCount)1191*c8dee2aaSAndroid Build Coastguard Worker void GrGLGpu::uploadTexData(SkISize texDims,
1192*c8dee2aaSAndroid Build Coastguard Worker                             GrGLenum target,
1193*c8dee2aaSAndroid Build Coastguard Worker                             SkIRect dstRect,
1194*c8dee2aaSAndroid Build Coastguard Worker                             GrGLenum externalFormat,
1195*c8dee2aaSAndroid Build Coastguard Worker                             GrGLenum externalType,
1196*c8dee2aaSAndroid Build Coastguard Worker                             size_t bpp,
1197*c8dee2aaSAndroid Build Coastguard Worker                             const GrMipLevel texels[],
1198*c8dee2aaSAndroid Build Coastguard Worker                             int mipLevelCount) {
1199*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!texDims.isEmpty());
1200*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!dstRect.isEmpty());
1201*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(SkIRect::MakeSize(texDims).contains(dstRect));
1202*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(mipLevelCount > 0 && mipLevelCount <= SkMipmap::ComputeLevelCount(texDims) + 1);
1203*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(mipLevelCount == 1 || dstRect == SkIRect::MakeSize(texDims));
1204*c8dee2aaSAndroid Build Coastguard Worker 
1205*c8dee2aaSAndroid Build Coastguard Worker     const GrGLCaps& caps = this->glCaps();
1206*c8dee2aaSAndroid Build Coastguard Worker 
1207*c8dee2aaSAndroid Build Coastguard Worker     bool restoreGLRowLength = false;
1208*c8dee2aaSAndroid Build Coastguard Worker 
1209*c8dee2aaSAndroid Build Coastguard Worker     this->unbindXferBuffer(GrGpuBufferType::kXferCpuToGpu);
1210*c8dee2aaSAndroid Build Coastguard Worker     GL_CALL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, 1));
1211*c8dee2aaSAndroid Build Coastguard Worker 
1212*c8dee2aaSAndroid Build Coastguard Worker     SkISize dims = dstRect.size();
1213*c8dee2aaSAndroid Build Coastguard Worker     for (int level = 0; level < mipLevelCount; ++level, dims = {std::max(dims.width()  >> 1, 1),
1214*c8dee2aaSAndroid Build Coastguard Worker                                                                 std::max(dims.height() >> 1, 1)}) {
1215*c8dee2aaSAndroid Build Coastguard Worker         if (!texels[level].fPixels) {
1216*c8dee2aaSAndroid Build Coastguard Worker             continue;
1217*c8dee2aaSAndroid Build Coastguard Worker         }
1218*c8dee2aaSAndroid Build Coastguard Worker         const size_t trimRowBytes = dims.width() * bpp;
1219*c8dee2aaSAndroid Build Coastguard Worker         const size_t rowBytes = texels[level].fRowBytes;
1220*c8dee2aaSAndroid Build Coastguard Worker 
1221*c8dee2aaSAndroid Build Coastguard Worker         if (caps.writePixelsRowBytesSupport() && (rowBytes != trimRowBytes || restoreGLRowLength)) {
1222*c8dee2aaSAndroid Build Coastguard Worker             GrGLint rowLength = static_cast<GrGLint>(rowBytes / bpp);
1223*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, rowLength));
1224*c8dee2aaSAndroid Build Coastguard Worker             restoreGLRowLength = true;
1225*c8dee2aaSAndroid Build Coastguard Worker         } else {
1226*c8dee2aaSAndroid Build Coastguard Worker             SkASSERT(rowBytes == trimRowBytes);
1227*c8dee2aaSAndroid Build Coastguard Worker         }
1228*c8dee2aaSAndroid Build Coastguard Worker 
1229*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(TexSubImage2D(target, level, dstRect.x(), dstRect.y(), dims.width(), dims.height(),
1230*c8dee2aaSAndroid Build Coastguard Worker                               externalFormat, externalType, texels[level].fPixels));
1231*c8dee2aaSAndroid Build Coastguard Worker     }
1232*c8dee2aaSAndroid Build Coastguard Worker     if (restoreGLRowLength) {
1233*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(caps.writePixelsRowBytesSupport());
1234*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, 0));
1235*c8dee2aaSAndroid Build Coastguard Worker     }
1236*c8dee2aaSAndroid Build Coastguard Worker }
1237*c8dee2aaSAndroid Build Coastguard Worker 
uploadCompressedTexData(SkTextureCompressionType compressionType,GrGLFormat format,SkISize dimensions,skgpu::Mipmapped mipmapped,GrGLenum target,const void * data,size_t dataSize)1238*c8dee2aaSAndroid Build Coastguard Worker bool GrGLGpu::uploadCompressedTexData(SkTextureCompressionType compressionType,
1239*c8dee2aaSAndroid Build Coastguard Worker                                       GrGLFormat format,
1240*c8dee2aaSAndroid Build Coastguard Worker                                       SkISize dimensions,
1241*c8dee2aaSAndroid Build Coastguard Worker                                       skgpu::Mipmapped mipmapped,
1242*c8dee2aaSAndroid Build Coastguard Worker                                       GrGLenum target,
1243*c8dee2aaSAndroid Build Coastguard Worker                                       const void* data,
1244*c8dee2aaSAndroid Build Coastguard Worker                                       size_t dataSize) {
1245*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(format != GrGLFormat::kUnknown);
1246*c8dee2aaSAndroid Build Coastguard Worker     const GrGLCaps& caps = this->glCaps();
1247*c8dee2aaSAndroid Build Coastguard Worker 
1248*c8dee2aaSAndroid Build Coastguard Worker     // We only need the internal format for compressed 2D textures.
1249*c8dee2aaSAndroid Build Coastguard Worker     GrGLenum internalFormat = caps.getTexImageOrStorageInternalFormat(format);
1250*c8dee2aaSAndroid Build Coastguard Worker     if (!internalFormat) {
1251*c8dee2aaSAndroid Build Coastguard Worker         return false;
1252*c8dee2aaSAndroid Build Coastguard Worker     }
1253*c8dee2aaSAndroid Build Coastguard Worker 
1254*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(compressionType != SkTextureCompressionType::kNone);
1255*c8dee2aaSAndroid Build Coastguard Worker 
1256*c8dee2aaSAndroid Build Coastguard Worker     bool useTexStorage = caps.formatSupportsTexStorage(format);
1257*c8dee2aaSAndroid Build Coastguard Worker 
1258*c8dee2aaSAndroid Build Coastguard Worker     int numMipLevels = 1;
1259*c8dee2aaSAndroid Build Coastguard Worker     if (mipmapped == skgpu::Mipmapped::kYes) {
1260*c8dee2aaSAndroid Build Coastguard Worker         numMipLevels = SkMipmap::ComputeLevelCount(dimensions.width(), dimensions.height())+1;
1261*c8dee2aaSAndroid Build Coastguard Worker     }
1262*c8dee2aaSAndroid Build Coastguard Worker 
1263*c8dee2aaSAndroid Build Coastguard Worker     this->unbindXferBuffer(GrGpuBufferType::kXferCpuToGpu);
1264*c8dee2aaSAndroid Build Coastguard Worker 
1265*c8dee2aaSAndroid Build Coastguard Worker     // TODO: Make sure that the width and height that we pass to OpenGL
1266*c8dee2aaSAndroid Build Coastguard Worker     // is a multiple of the block size.
1267*c8dee2aaSAndroid Build Coastguard Worker 
1268*c8dee2aaSAndroid Build Coastguard Worker     if (useTexStorage) {
1269*c8dee2aaSAndroid Build Coastguard Worker         // We never resize or change formats of textures.
1270*c8dee2aaSAndroid Build Coastguard Worker         GrGLenum error = GL_ALLOC_CALL(TexStorage2D(target, numMipLevels, internalFormat,
1271*c8dee2aaSAndroid Build Coastguard Worker                                                     dimensions.width(), dimensions.height()));
1272*c8dee2aaSAndroid Build Coastguard Worker         if (error != GR_GL_NO_ERROR) {
1273*c8dee2aaSAndroid Build Coastguard Worker             return false;
1274*c8dee2aaSAndroid Build Coastguard Worker         }
1275*c8dee2aaSAndroid Build Coastguard Worker 
1276*c8dee2aaSAndroid Build Coastguard Worker         size_t offset = 0;
1277*c8dee2aaSAndroid Build Coastguard Worker         for (int level = 0; level < numMipLevels; ++level) {
1278*c8dee2aaSAndroid Build Coastguard Worker 
1279*c8dee2aaSAndroid Build Coastguard Worker             size_t levelDataSize = SkCompressedDataSize(compressionType, dimensions,
1280*c8dee2aaSAndroid Build Coastguard Worker                                                         nullptr, false);
1281*c8dee2aaSAndroid Build Coastguard Worker 
1282*c8dee2aaSAndroid Build Coastguard Worker             error = GL_ALLOC_CALL(CompressedTexSubImage2D(target,
1283*c8dee2aaSAndroid Build Coastguard Worker                                                           level,
1284*c8dee2aaSAndroid Build Coastguard Worker                                                           0,  // left
1285*c8dee2aaSAndroid Build Coastguard Worker                                                           0,  // top
1286*c8dee2aaSAndroid Build Coastguard Worker                                                           dimensions.width(),
1287*c8dee2aaSAndroid Build Coastguard Worker                                                           dimensions.height(),
1288*c8dee2aaSAndroid Build Coastguard Worker                                                           internalFormat,
1289*c8dee2aaSAndroid Build Coastguard Worker                                                           SkToInt(levelDataSize),
1290*c8dee2aaSAndroid Build Coastguard Worker                                                           &((const char*)data)[offset]));
1291*c8dee2aaSAndroid Build Coastguard Worker 
1292*c8dee2aaSAndroid Build Coastguard Worker             if (error != GR_GL_NO_ERROR) {
1293*c8dee2aaSAndroid Build Coastguard Worker                 return false;
1294*c8dee2aaSAndroid Build Coastguard Worker             }
1295*c8dee2aaSAndroid Build Coastguard Worker 
1296*c8dee2aaSAndroid Build Coastguard Worker             offset += levelDataSize;
1297*c8dee2aaSAndroid Build Coastguard Worker             dimensions = {std::max(1, dimensions.width()/2), std::max(1, dimensions.height()/2)};
1298*c8dee2aaSAndroid Build Coastguard Worker         }
1299*c8dee2aaSAndroid Build Coastguard Worker     } else {
1300*c8dee2aaSAndroid Build Coastguard Worker         size_t offset = 0;
1301*c8dee2aaSAndroid Build Coastguard Worker 
1302*c8dee2aaSAndroid Build Coastguard Worker         for (int level = 0; level < numMipLevels; ++level) {
1303*c8dee2aaSAndroid Build Coastguard Worker             size_t levelDataSize = SkCompressedDataSize(compressionType, dimensions,
1304*c8dee2aaSAndroid Build Coastguard Worker                                                         nullptr, false);
1305*c8dee2aaSAndroid Build Coastguard Worker 
1306*c8dee2aaSAndroid Build Coastguard Worker             const char* rawLevelData = &((const char*)data)[offset];
1307*c8dee2aaSAndroid Build Coastguard Worker             GrGLenum error = GL_ALLOC_CALL(CompressedTexImage2D(target,
1308*c8dee2aaSAndroid Build Coastguard Worker                                                                 level,
1309*c8dee2aaSAndroid Build Coastguard Worker                                                                 internalFormat,
1310*c8dee2aaSAndroid Build Coastguard Worker                                                                 dimensions.width(),
1311*c8dee2aaSAndroid Build Coastguard Worker                                                                 dimensions.height(),
1312*c8dee2aaSAndroid Build Coastguard Worker                                                                 0,  // border
1313*c8dee2aaSAndroid Build Coastguard Worker                                                                 SkToInt(levelDataSize),
1314*c8dee2aaSAndroid Build Coastguard Worker                                                                 rawLevelData));
1315*c8dee2aaSAndroid Build Coastguard Worker 
1316*c8dee2aaSAndroid Build Coastguard Worker             if (error != GR_GL_NO_ERROR) {
1317*c8dee2aaSAndroid Build Coastguard Worker                 return false;
1318*c8dee2aaSAndroid Build Coastguard Worker             }
1319*c8dee2aaSAndroid Build Coastguard Worker 
1320*c8dee2aaSAndroid Build Coastguard Worker             offset += levelDataSize;
1321*c8dee2aaSAndroid Build Coastguard Worker             dimensions = {std::max(1, dimensions.width()/2), std::max(1, dimensions.height()/2)};
1322*c8dee2aaSAndroid Build Coastguard Worker         }
1323*c8dee2aaSAndroid Build Coastguard Worker     }
1324*c8dee2aaSAndroid Build Coastguard Worker     return true;
1325*c8dee2aaSAndroid Build Coastguard Worker }
1326*c8dee2aaSAndroid Build Coastguard Worker 
renderbufferStorageMSAA(const GrGLContext & ctx,int sampleCount,GrGLenum format,int width,int height)1327*c8dee2aaSAndroid Build Coastguard Worker bool GrGLGpu::renderbufferStorageMSAA(const GrGLContext& ctx, int sampleCount, GrGLenum format,
1328*c8dee2aaSAndroid Build Coastguard Worker                                       int width, int height) {
1329*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(GrGLCaps::kNone_MSFBOType != ctx.caps()->msFBOType());
1330*c8dee2aaSAndroid Build Coastguard Worker     GrGLenum error;
1331*c8dee2aaSAndroid Build Coastguard Worker     switch (ctx.caps()->msFBOType()) {
1332*c8dee2aaSAndroid Build Coastguard Worker         case GrGLCaps::kStandard_MSFBOType:
1333*c8dee2aaSAndroid Build Coastguard Worker             error = GL_ALLOC_CALL(RenderbufferStorageMultisample(GR_GL_RENDERBUFFER, sampleCount,
1334*c8dee2aaSAndroid Build Coastguard Worker                                                                  format, width, height));
1335*c8dee2aaSAndroid Build Coastguard Worker             break;
1336*c8dee2aaSAndroid Build Coastguard Worker         case GrGLCaps::kES_Apple_MSFBOType:
1337*c8dee2aaSAndroid Build Coastguard Worker             error = GL_ALLOC_CALL(RenderbufferStorageMultisampleES2APPLE(
1338*c8dee2aaSAndroid Build Coastguard Worker                     GR_GL_RENDERBUFFER, sampleCount, format, width, height));
1339*c8dee2aaSAndroid Build Coastguard Worker             break;
1340*c8dee2aaSAndroid Build Coastguard Worker         case GrGLCaps::kES_EXT_MsToTexture_MSFBOType:
1341*c8dee2aaSAndroid Build Coastguard Worker         case GrGLCaps::kES_IMG_MsToTexture_MSFBOType:
1342*c8dee2aaSAndroid Build Coastguard Worker             error = GL_ALLOC_CALL(RenderbufferStorageMultisampleES2EXT(
1343*c8dee2aaSAndroid Build Coastguard Worker                     GR_GL_RENDERBUFFER, sampleCount, format, width, height));
1344*c8dee2aaSAndroid Build Coastguard Worker             break;
1345*c8dee2aaSAndroid Build Coastguard Worker         case GrGLCaps::kNone_MSFBOType:
1346*c8dee2aaSAndroid Build Coastguard Worker             SkUNREACHABLE;
1347*c8dee2aaSAndroid Build Coastguard Worker     }
1348*c8dee2aaSAndroid Build Coastguard Worker     return error == GR_GL_NO_ERROR;
1349*c8dee2aaSAndroid Build Coastguard Worker }
1350*c8dee2aaSAndroid Build Coastguard Worker 
createRenderTargetObjects(const GrGLTexture::Desc & desc,int sampleCount,GrGLRenderTarget::IDs * rtIDs)1351*c8dee2aaSAndroid Build Coastguard Worker bool GrGLGpu::createRenderTargetObjects(const GrGLTexture::Desc& desc,
1352*c8dee2aaSAndroid Build Coastguard Worker                                         int sampleCount,
1353*c8dee2aaSAndroid Build Coastguard Worker                                         GrGLRenderTarget::IDs* rtIDs) {
1354*c8dee2aaSAndroid Build Coastguard Worker     rtIDs->fMSColorRenderbufferID = 0;
1355*c8dee2aaSAndroid Build Coastguard Worker     rtIDs->fMultisampleFBOID = 0;
1356*c8dee2aaSAndroid Build Coastguard Worker     rtIDs->fRTFBOOwnership = GrBackendObjectOwnership::kOwned;
1357*c8dee2aaSAndroid Build Coastguard Worker     rtIDs->fSingleSampleFBOID = 0;
1358*c8dee2aaSAndroid Build Coastguard Worker     rtIDs->fTotalMemorySamplesPerPixel = 0;
1359*c8dee2aaSAndroid Build Coastguard Worker 
1360*c8dee2aaSAndroid Build Coastguard Worker     SkScopeExit cleanupOnFail([&] {
1361*c8dee2aaSAndroid Build Coastguard Worker         if (rtIDs->fMSColorRenderbufferID) {
1362*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(DeleteRenderbuffers(1, &rtIDs->fMSColorRenderbufferID));
1363*c8dee2aaSAndroid Build Coastguard Worker         }
1364*c8dee2aaSAndroid Build Coastguard Worker         if (rtIDs->fMultisampleFBOID != rtIDs->fSingleSampleFBOID) {
1365*c8dee2aaSAndroid Build Coastguard Worker             this->deleteFramebuffer(rtIDs->fMultisampleFBOID);
1366*c8dee2aaSAndroid Build Coastguard Worker         }
1367*c8dee2aaSAndroid Build Coastguard Worker         if (rtIDs->fSingleSampleFBOID) {
1368*c8dee2aaSAndroid Build Coastguard Worker             this->deleteFramebuffer(rtIDs->fSingleSampleFBOID);
1369*c8dee2aaSAndroid Build Coastguard Worker         }
1370*c8dee2aaSAndroid Build Coastguard Worker     });
1371*c8dee2aaSAndroid Build Coastguard Worker 
1372*c8dee2aaSAndroid Build Coastguard Worker     GrGLenum colorRenderbufferFormat = 0; // suppress warning
1373*c8dee2aaSAndroid Build Coastguard Worker 
1374*c8dee2aaSAndroid Build Coastguard Worker     if (desc.fFormat == GrGLFormat::kUnknown) {
1375*c8dee2aaSAndroid Build Coastguard Worker         return false;
1376*c8dee2aaSAndroid Build Coastguard Worker     }
1377*c8dee2aaSAndroid Build Coastguard Worker 
1378*c8dee2aaSAndroid Build Coastguard Worker     if (sampleCount > 1 && GrGLCaps::kNone_MSFBOType == this->glCaps().msFBOType()) {
1379*c8dee2aaSAndroid Build Coastguard Worker         return false;
1380*c8dee2aaSAndroid Build Coastguard Worker     }
1381*c8dee2aaSAndroid Build Coastguard Worker 
1382*c8dee2aaSAndroid Build Coastguard Worker     GL_CALL(GenFramebuffers(1, &rtIDs->fSingleSampleFBOID));
1383*c8dee2aaSAndroid Build Coastguard Worker     if (!rtIDs->fSingleSampleFBOID) {
1384*c8dee2aaSAndroid Build Coastguard Worker         RENDERENGINE_ABORTF("%s failed to GenFramebuffers!", __func__);
1385*c8dee2aaSAndroid Build Coastguard Worker         return false;
1386*c8dee2aaSAndroid Build Coastguard Worker     }
1387*c8dee2aaSAndroid Build Coastguard Worker 
1388*c8dee2aaSAndroid Build Coastguard Worker     // If we are using multisampling we will create two FBOS. We render to one and then resolve to
1389*c8dee2aaSAndroid Build Coastguard Worker     // the texture bound to the other. The exception is the IMG multisample extension. With this
1390*c8dee2aaSAndroid Build Coastguard Worker     // extension the texture is multisampled when rendered to and then auto-resolves it when it is
1391*c8dee2aaSAndroid Build Coastguard Worker     // rendered from.
1392*c8dee2aaSAndroid Build Coastguard Worker     if (sampleCount <= 1) {
1393*c8dee2aaSAndroid Build Coastguard Worker         rtIDs->fMultisampleFBOID = GrGLRenderTarget::kUnresolvableFBOID;
1394*c8dee2aaSAndroid Build Coastguard Worker     } else if (this->glCaps().usesImplicitMSAAResolve()) {
1395*c8dee2aaSAndroid Build Coastguard Worker         // GrGLRenderTarget target will configure the FBO as multisample or not base on need.
1396*c8dee2aaSAndroid Build Coastguard Worker         rtIDs->fMultisampleFBOID = rtIDs->fSingleSampleFBOID;
1397*c8dee2aaSAndroid Build Coastguard Worker     } else {
1398*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(GenFramebuffers(1, &rtIDs->fMultisampleFBOID));
1399*c8dee2aaSAndroid Build Coastguard Worker         if (!rtIDs->fMultisampleFBOID) {
1400*c8dee2aaSAndroid Build Coastguard Worker             return false;
1401*c8dee2aaSAndroid Build Coastguard Worker         }
1402*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(GenRenderbuffers(1, &rtIDs->fMSColorRenderbufferID));
1403*c8dee2aaSAndroid Build Coastguard Worker         if (!rtIDs->fMSColorRenderbufferID) {
1404*c8dee2aaSAndroid Build Coastguard Worker             return false;
1405*c8dee2aaSAndroid Build Coastguard Worker         }
1406*c8dee2aaSAndroid Build Coastguard Worker         colorRenderbufferFormat = this->glCaps().getRenderbufferInternalFormat(desc.fFormat);
1407*c8dee2aaSAndroid Build Coastguard Worker     }
1408*c8dee2aaSAndroid Build Coastguard Worker 
1409*c8dee2aaSAndroid Build Coastguard Worker #if defined(__has_feature)
1410*c8dee2aaSAndroid Build Coastguard Worker #define IS_TSAN __has_feature(thread_sanitizer)
1411*c8dee2aaSAndroid Build Coastguard Worker #else
1412*c8dee2aaSAndroid Build Coastguard Worker #define IS_TSAN 0
1413*c8dee2aaSAndroid Build Coastguard Worker #endif
1414*c8dee2aaSAndroid Build Coastguard Worker 
1415*c8dee2aaSAndroid Build Coastguard Worker     // below here we may bind the FBO
1416*c8dee2aaSAndroid Build Coastguard Worker     fHWBoundRenderTargetUniqueID.makeInvalid();
1417*c8dee2aaSAndroid Build Coastguard Worker     if (rtIDs->fMSColorRenderbufferID) {
1418*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(sampleCount > 1);
1419*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(BindRenderbuffer(GR_GL_RENDERBUFFER, rtIDs->fMSColorRenderbufferID));
1420*c8dee2aaSAndroid Build Coastguard Worker         if (!this->renderbufferStorageMSAA(*fGLContext, sampleCount, colorRenderbufferFormat,
1421*c8dee2aaSAndroid Build Coastguard Worker                                            desc.fSize.width(), desc.fSize.height())) {
1422*c8dee2aaSAndroid Build Coastguard Worker             return false;
1423*c8dee2aaSAndroid Build Coastguard Worker         }
1424*c8dee2aaSAndroid Build Coastguard Worker         this->bindFramebuffer(GR_GL_FRAMEBUFFER, rtIDs->fMultisampleFBOID);
1425*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1426*c8dee2aaSAndroid Build Coastguard Worker                                         GR_GL_COLOR_ATTACHMENT0,
1427*c8dee2aaSAndroid Build Coastguard Worker                                         GR_GL_RENDERBUFFER,
1428*c8dee2aaSAndroid Build Coastguard Worker                                         rtIDs->fMSColorRenderbufferID));
1429*c8dee2aaSAndroid Build Coastguard Worker // See skbug.com/12644
1430*c8dee2aaSAndroid Build Coastguard Worker #if !IS_TSAN
1431*c8dee2aaSAndroid Build Coastguard Worker         if (!this->glCaps().skipErrorChecks()) {
1432*c8dee2aaSAndroid Build Coastguard Worker             GrGLenum status;
1433*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
1434*c8dee2aaSAndroid Build Coastguard Worker             if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
1435*c8dee2aaSAndroid Build Coastguard Worker                 return false;
1436*c8dee2aaSAndroid Build Coastguard Worker             }
1437*c8dee2aaSAndroid Build Coastguard Worker             if (this->glCaps().rebindColorAttachmentAfterCheckFramebufferStatus()) {
1438*c8dee2aaSAndroid Build Coastguard Worker                 GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1439*c8dee2aaSAndroid Build Coastguard Worker                                                 GR_GL_COLOR_ATTACHMENT0,
1440*c8dee2aaSAndroid Build Coastguard Worker                                                 GR_GL_RENDERBUFFER,
1441*c8dee2aaSAndroid Build Coastguard Worker                                                 0));
1442*c8dee2aaSAndroid Build Coastguard Worker                 GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1443*c8dee2aaSAndroid Build Coastguard Worker                                                 GR_GL_COLOR_ATTACHMENT0,
1444*c8dee2aaSAndroid Build Coastguard Worker                                                 GR_GL_RENDERBUFFER,
1445*c8dee2aaSAndroid Build Coastguard Worker                                                 rtIDs->fMSColorRenderbufferID));
1446*c8dee2aaSAndroid Build Coastguard Worker             }
1447*c8dee2aaSAndroid Build Coastguard Worker         }
1448*c8dee2aaSAndroid Build Coastguard Worker #endif
1449*c8dee2aaSAndroid Build Coastguard Worker         rtIDs->fTotalMemorySamplesPerPixel += sampleCount;
1450*c8dee2aaSAndroid Build Coastguard Worker     }
1451*c8dee2aaSAndroid Build Coastguard Worker     this->bindFramebuffer(GR_GL_FRAMEBUFFER, rtIDs->fSingleSampleFBOID);
1452*c8dee2aaSAndroid Build Coastguard Worker     GL_CALL(FramebufferTexture2D(GR_GL_FRAMEBUFFER,
1453*c8dee2aaSAndroid Build Coastguard Worker                                  GR_GL_COLOR_ATTACHMENT0,
1454*c8dee2aaSAndroid Build Coastguard Worker                                  desc.fTarget,
1455*c8dee2aaSAndroid Build Coastguard Worker                                  desc.fID,
1456*c8dee2aaSAndroid Build Coastguard Worker                                  0));
1457*c8dee2aaSAndroid Build Coastguard Worker // See skbug.com/12644
1458*c8dee2aaSAndroid Build Coastguard Worker #if !IS_TSAN
1459*c8dee2aaSAndroid Build Coastguard Worker     if (!this->glCaps().skipErrorChecks()) {
1460*c8dee2aaSAndroid Build Coastguard Worker         GrGLenum status;
1461*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
1462*c8dee2aaSAndroid Build Coastguard Worker         if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
1463*c8dee2aaSAndroid Build Coastguard Worker             return false;
1464*c8dee2aaSAndroid Build Coastguard Worker         }
1465*c8dee2aaSAndroid Build Coastguard Worker         if (this->glCaps().rebindColorAttachmentAfterCheckFramebufferStatus()) {
1466*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(FramebufferTexture2D(GR_GL_FRAMEBUFFER,
1467*c8dee2aaSAndroid Build Coastguard Worker                                          GR_GL_COLOR_ATTACHMENT0,
1468*c8dee2aaSAndroid Build Coastguard Worker                                          desc.fTarget,
1469*c8dee2aaSAndroid Build Coastguard Worker                                          0,
1470*c8dee2aaSAndroid Build Coastguard Worker                                          0));
1471*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(FramebufferTexture2D(GR_GL_FRAMEBUFFER,
1472*c8dee2aaSAndroid Build Coastguard Worker                                          GR_GL_COLOR_ATTACHMENT0,
1473*c8dee2aaSAndroid Build Coastguard Worker                                          desc.fTarget,
1474*c8dee2aaSAndroid Build Coastguard Worker                                          desc.fID,
1475*c8dee2aaSAndroid Build Coastguard Worker                                          0));
1476*c8dee2aaSAndroid Build Coastguard Worker         }
1477*c8dee2aaSAndroid Build Coastguard Worker     }
1478*c8dee2aaSAndroid Build Coastguard Worker #endif
1479*c8dee2aaSAndroid Build Coastguard Worker 
1480*c8dee2aaSAndroid Build Coastguard Worker #undef IS_TSAN
1481*c8dee2aaSAndroid Build Coastguard Worker     ++rtIDs->fTotalMemorySamplesPerPixel;
1482*c8dee2aaSAndroid Build Coastguard Worker 
1483*c8dee2aaSAndroid Build Coastguard Worker     // We did it!
1484*c8dee2aaSAndroid Build Coastguard Worker     cleanupOnFail.clear();
1485*c8dee2aaSAndroid Build Coastguard Worker     return true;
1486*c8dee2aaSAndroid Build Coastguard Worker }
1487*c8dee2aaSAndroid Build Coastguard Worker 
1488*c8dee2aaSAndroid Build Coastguard Worker // good to set a break-point here to know when createTexture fails
return_null_texture()1489*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<GrTexture> return_null_texture() {
1490*c8dee2aaSAndroid Build Coastguard Worker //    SkDEBUGFAIL("null texture");
1491*c8dee2aaSAndroid Build Coastguard Worker     return nullptr;
1492*c8dee2aaSAndroid Build Coastguard Worker }
1493*c8dee2aaSAndroid Build Coastguard Worker 
set_initial_texture_params(const GrGLInterface * interface,const GrGLCaps & caps,GrGLenum target)1494*c8dee2aaSAndroid Build Coastguard Worker static GrGLTextureParameters::SamplerOverriddenState set_initial_texture_params(
1495*c8dee2aaSAndroid Build Coastguard Worker         const GrGLInterface* interface,
1496*c8dee2aaSAndroid Build Coastguard Worker         const GrGLCaps& caps,
1497*c8dee2aaSAndroid Build Coastguard Worker         GrGLenum target) {
1498*c8dee2aaSAndroid Build Coastguard Worker     // Some drivers like to know filter/wrap before seeing glTexImage2D. Some
1499*c8dee2aaSAndroid Build Coastguard Worker     // drivers have a bug where an FBO won't be complete if it includes a
1500*c8dee2aaSAndroid Build Coastguard Worker     // texture that is not mipmap complete (considering the filter in use).
1501*c8dee2aaSAndroid Build Coastguard Worker     GrGLTextureParameters::SamplerOverriddenState state;
1502*c8dee2aaSAndroid Build Coastguard Worker     state.fMinFilter = GR_GL_NEAREST;
1503*c8dee2aaSAndroid Build Coastguard Worker     state.fMagFilter = GR_GL_NEAREST;
1504*c8dee2aaSAndroid Build Coastguard Worker     state.fWrapS = GR_GL_CLAMP_TO_EDGE;
1505*c8dee2aaSAndroid Build Coastguard Worker     state.fWrapT = GR_GL_CLAMP_TO_EDGE;
1506*c8dee2aaSAndroid Build Coastguard Worker     GR_GL_CALL(interface, TexParameteri(target, GR_GL_TEXTURE_MAG_FILTER, state.fMagFilter));
1507*c8dee2aaSAndroid Build Coastguard Worker     GR_GL_CALL(interface, TexParameteri(target, GR_GL_TEXTURE_MIN_FILTER, state.fMinFilter));
1508*c8dee2aaSAndroid Build Coastguard Worker     GR_GL_CALL(interface, TexParameteri(target, GR_GL_TEXTURE_WRAP_S, state.fWrapS));
1509*c8dee2aaSAndroid Build Coastguard Worker     GR_GL_CALL(interface, TexParameteri(target, GR_GL_TEXTURE_WRAP_T, state.fWrapT));
1510*c8dee2aaSAndroid Build Coastguard Worker     return state;
1511*c8dee2aaSAndroid Build Coastguard Worker }
1512*c8dee2aaSAndroid Build Coastguard Worker 
onCreateTexture(SkISize dimensions,const GrBackendFormat & format,GrRenderable renderable,int renderTargetSampleCnt,skgpu::Budgeted budgeted,GrProtected isProtected,int mipLevelCount,uint32_t levelClearMask,std::string_view label)1513*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrTexture> GrGLGpu::onCreateTexture(SkISize dimensions,
1514*c8dee2aaSAndroid Build Coastguard Worker                                           const GrBackendFormat& format,
1515*c8dee2aaSAndroid Build Coastguard Worker                                           GrRenderable renderable,
1516*c8dee2aaSAndroid Build Coastguard Worker                                           int renderTargetSampleCnt,
1517*c8dee2aaSAndroid Build Coastguard Worker                                           skgpu::Budgeted budgeted,
1518*c8dee2aaSAndroid Build Coastguard Worker                                           GrProtected isProtected,
1519*c8dee2aaSAndroid Build Coastguard Worker                                           int mipLevelCount,
1520*c8dee2aaSAndroid Build Coastguard Worker                                           uint32_t levelClearMask,
1521*c8dee2aaSAndroid Build Coastguard Worker                                           std::string_view label) {
1522*c8dee2aaSAndroid Build Coastguard Worker     if (isProtected == GrProtected::kYes && !this->glCaps().supportsProtectedContent()) {
1523*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
1524*c8dee2aaSAndroid Build Coastguard Worker     }
1525*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(GrGLCaps::kNone_MSFBOType != this->glCaps().msFBOType() || renderTargetSampleCnt == 1);
1526*c8dee2aaSAndroid Build Coastguard Worker 
1527*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(mipLevelCount > 0);
1528*c8dee2aaSAndroid Build Coastguard Worker     GrMipmapStatus mipmapStatus =
1529*c8dee2aaSAndroid Build Coastguard Worker             mipLevelCount > 1 ? GrMipmapStatus::kDirty : GrMipmapStatus::kNotAllocated;
1530*c8dee2aaSAndroid Build Coastguard Worker     GrGLTextureParameters::SamplerOverriddenState initialState;
1531*c8dee2aaSAndroid Build Coastguard Worker     GrGLTexture::Desc texDesc;
1532*c8dee2aaSAndroid Build Coastguard Worker     texDesc.fSize = dimensions;
1533*c8dee2aaSAndroid Build Coastguard Worker     switch (format.textureType()) {
1534*c8dee2aaSAndroid Build Coastguard Worker         case GrTextureType::kExternal:
1535*c8dee2aaSAndroid Build Coastguard Worker         case GrTextureType::kNone:
1536*c8dee2aaSAndroid Build Coastguard Worker             return nullptr;
1537*c8dee2aaSAndroid Build Coastguard Worker         case GrTextureType::k2D:
1538*c8dee2aaSAndroid Build Coastguard Worker             texDesc.fTarget = GR_GL_TEXTURE_2D;
1539*c8dee2aaSAndroid Build Coastguard Worker             break;
1540*c8dee2aaSAndroid Build Coastguard Worker         case GrTextureType::kRectangle:
1541*c8dee2aaSAndroid Build Coastguard Worker             if (mipLevelCount > 1 || !this->glCaps().rectangleTextureSupport()) {
1542*c8dee2aaSAndroid Build Coastguard Worker                 return nullptr;
1543*c8dee2aaSAndroid Build Coastguard Worker             }
1544*c8dee2aaSAndroid Build Coastguard Worker             texDesc.fTarget = GR_GL_TEXTURE_RECTANGLE;
1545*c8dee2aaSAndroid Build Coastguard Worker             break;
1546*c8dee2aaSAndroid Build Coastguard Worker     }
1547*c8dee2aaSAndroid Build Coastguard Worker     texDesc.fFormat = GrBackendFormats::AsGLFormat(format);
1548*c8dee2aaSAndroid Build Coastguard Worker     texDesc.fOwnership = GrBackendObjectOwnership::kOwned;
1549*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(texDesc.fFormat != GrGLFormat::kUnknown);
1550*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!GrGLFormatIsCompressed(texDesc.fFormat));
1551*c8dee2aaSAndroid Build Coastguard Worker     texDesc.fIsProtected = skgpu::Protected(isProtected == skgpu::Protected::kYes ||
1552*c8dee2aaSAndroid Build Coastguard Worker                                             this->glCaps().strictProtectedness());
1553*c8dee2aaSAndroid Build Coastguard Worker 
1554*c8dee2aaSAndroid Build Coastguard Worker     texDesc.fID = this->createTexture(dimensions, texDesc.fFormat, texDesc.fTarget, renderable,
1555*c8dee2aaSAndroid Build Coastguard Worker                                       &initialState, mipLevelCount, texDesc.fIsProtected, label);
1556*c8dee2aaSAndroid Build Coastguard Worker     if (!texDesc.fID) {
1557*c8dee2aaSAndroid Build Coastguard Worker         return return_null_texture();
1558*c8dee2aaSAndroid Build Coastguard Worker     }
1559*c8dee2aaSAndroid Build Coastguard Worker 
1560*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<GrGLTexture> tex;
1561*c8dee2aaSAndroid Build Coastguard Worker     if (renderable == GrRenderable::kYes) {
1562*c8dee2aaSAndroid Build Coastguard Worker         // unbind the texture from the texture unit before binding it to the frame buffer
1563*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(BindTexture(texDesc.fTarget, 0));
1564*c8dee2aaSAndroid Build Coastguard Worker         GrGLRenderTarget::IDs rtIDDesc;
1565*c8dee2aaSAndroid Build Coastguard Worker 
1566*c8dee2aaSAndroid Build Coastguard Worker         if (!this->createRenderTargetObjects(texDesc, renderTargetSampleCnt, &rtIDDesc)) {
1567*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(DeleteTextures(1, &texDesc.fID));
1568*c8dee2aaSAndroid Build Coastguard Worker             return return_null_texture();
1569*c8dee2aaSAndroid Build Coastguard Worker         }
1570*c8dee2aaSAndroid Build Coastguard Worker         tex = sk_make_sp<GrGLTextureRenderTarget>(this,
1571*c8dee2aaSAndroid Build Coastguard Worker                                                   budgeted,
1572*c8dee2aaSAndroid Build Coastguard Worker                                                   renderTargetSampleCnt,
1573*c8dee2aaSAndroid Build Coastguard Worker                                                   texDesc,
1574*c8dee2aaSAndroid Build Coastguard Worker                                                   rtIDDesc,
1575*c8dee2aaSAndroid Build Coastguard Worker                                                   mipmapStatus,
1576*c8dee2aaSAndroid Build Coastguard Worker                                                   label);
1577*c8dee2aaSAndroid Build Coastguard Worker         tex->baseLevelWasBoundToFBO();
1578*c8dee2aaSAndroid Build Coastguard Worker     } else {
1579*c8dee2aaSAndroid Build Coastguard Worker         tex = sk_make_sp<GrGLTexture>(this, budgeted, texDesc, mipmapStatus, label);
1580*c8dee2aaSAndroid Build Coastguard Worker     }
1581*c8dee2aaSAndroid Build Coastguard Worker     // The non-sampler params are still at their default values.
1582*c8dee2aaSAndroid Build Coastguard Worker     tex->parameters()->set(&initialState, GrGLTextureParameters::NonsamplerState(),
1583*c8dee2aaSAndroid Build Coastguard Worker                            fResetTimestampForTextureParameters);
1584*c8dee2aaSAndroid Build Coastguard Worker     if (levelClearMask) {
1585*c8dee2aaSAndroid Build Coastguard Worker         if (this->glCaps().clearTextureSupport()) {
1586*c8dee2aaSAndroid Build Coastguard Worker             GrGLenum externalFormat, externalType;
1587*c8dee2aaSAndroid Build Coastguard Worker             GrColorType colorType;
1588*c8dee2aaSAndroid Build Coastguard Worker             this->glCaps().getTexSubImageDefaultFormatTypeAndColorType(
1589*c8dee2aaSAndroid Build Coastguard Worker                     texDesc.fFormat, &externalFormat, &externalType, &colorType);
1590*c8dee2aaSAndroid Build Coastguard Worker             for (int i = 0; i < mipLevelCount; ++i) {
1591*c8dee2aaSAndroid Build Coastguard Worker                 if (levelClearMask & (1U << i)) {
1592*c8dee2aaSAndroid Build Coastguard Worker                     GL_CALL(ClearTexImage(tex->textureID(), i, externalFormat, externalType,
1593*c8dee2aaSAndroid Build Coastguard Worker                                           nullptr));
1594*c8dee2aaSAndroid Build Coastguard Worker                 }
1595*c8dee2aaSAndroid Build Coastguard Worker             }
1596*c8dee2aaSAndroid Build Coastguard Worker         } else if (this->glCaps().canFormatBeFBOColorAttachment(
1597*c8dee2aaSAndroid Build Coastguard Worker                            GrBackendFormats::AsGLFormat(format)) &&
1598*c8dee2aaSAndroid Build Coastguard Worker                    !this->glCaps().performColorClearsAsDraws()) {
1599*c8dee2aaSAndroid Build Coastguard Worker             this->flushScissorTest(GrScissorTest::kDisabled);
1600*c8dee2aaSAndroid Build Coastguard Worker             this->disableWindowRectangles();
1601*c8dee2aaSAndroid Build Coastguard Worker             this->flushColorWrite(true);
1602*c8dee2aaSAndroid Build Coastguard Worker             this->flushClearColor({0, 0, 0, 0});
1603*c8dee2aaSAndroid Build Coastguard Worker             for (int i = 0; i < mipLevelCount; ++i) {
1604*c8dee2aaSAndroid Build Coastguard Worker                 if (levelClearMask & (1U << i)) {
1605*c8dee2aaSAndroid Build Coastguard Worker                     this->bindSurfaceFBOForPixelOps(tex.get(), i, GR_GL_FRAMEBUFFER,
1606*c8dee2aaSAndroid Build Coastguard Worker                                                     kDst_TempFBOTarget);
1607*c8dee2aaSAndroid Build Coastguard Worker                     GL_CALL(Clear(GR_GL_COLOR_BUFFER_BIT));
1608*c8dee2aaSAndroid Build Coastguard Worker                     this->unbindSurfaceFBOForPixelOps(tex.get(), i, GR_GL_FRAMEBUFFER);
1609*c8dee2aaSAndroid Build Coastguard Worker                 }
1610*c8dee2aaSAndroid Build Coastguard Worker             }
1611*c8dee2aaSAndroid Build Coastguard Worker             fHWBoundRenderTargetUniqueID.makeInvalid();
1612*c8dee2aaSAndroid Build Coastguard Worker         } else {
1613*c8dee2aaSAndroid Build Coastguard Worker             this->bindTextureToScratchUnit(texDesc.fTarget, tex->textureID());
1614*c8dee2aaSAndroid Build Coastguard Worker             std::array<float, 4> zeros = {};
1615*c8dee2aaSAndroid Build Coastguard Worker             this->uploadColorToTex(texDesc.fFormat,
1616*c8dee2aaSAndroid Build Coastguard Worker                                    texDesc.fSize,
1617*c8dee2aaSAndroid Build Coastguard Worker                                    texDesc.fTarget,
1618*c8dee2aaSAndroid Build Coastguard Worker                                    zeros,
1619*c8dee2aaSAndroid Build Coastguard Worker                                    levelClearMask);
1620*c8dee2aaSAndroid Build Coastguard Worker         }
1621*c8dee2aaSAndroid Build Coastguard Worker     }
1622*c8dee2aaSAndroid Build Coastguard Worker     return tex;
1623*c8dee2aaSAndroid Build Coastguard Worker }
1624*c8dee2aaSAndroid Build Coastguard Worker 
onCreateCompressedTexture(SkISize dimensions,const GrBackendFormat & format,skgpu::Budgeted budgeted,skgpu::Mipmapped mipmapped,GrProtected isProtected,const void * data,size_t dataSize)1625*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrTexture> GrGLGpu::onCreateCompressedTexture(SkISize dimensions,
1626*c8dee2aaSAndroid Build Coastguard Worker                                                     const GrBackendFormat& format,
1627*c8dee2aaSAndroid Build Coastguard Worker                                                     skgpu::Budgeted budgeted,
1628*c8dee2aaSAndroid Build Coastguard Worker                                                     skgpu::Mipmapped mipmapped,
1629*c8dee2aaSAndroid Build Coastguard Worker                                                     GrProtected isProtected,
1630*c8dee2aaSAndroid Build Coastguard Worker                                                     const void* data,
1631*c8dee2aaSAndroid Build Coastguard Worker                                                     size_t dataSize) {
1632*c8dee2aaSAndroid Build Coastguard Worker     if (isProtected == GrProtected::kYes && !this->glCaps().supportsProtectedContent()) {
1633*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
1634*c8dee2aaSAndroid Build Coastguard Worker     }
1635*c8dee2aaSAndroid Build Coastguard Worker     SkTextureCompressionType compression = GrBackendFormatToCompressionType(format);
1636*c8dee2aaSAndroid Build Coastguard Worker 
1637*c8dee2aaSAndroid Build Coastguard Worker     GrGLTextureParameters::SamplerOverriddenState initialState;
1638*c8dee2aaSAndroid Build Coastguard Worker     GrGLTexture::Desc desc;
1639*c8dee2aaSAndroid Build Coastguard Worker     desc.fSize = dimensions;
1640*c8dee2aaSAndroid Build Coastguard Worker     desc.fTarget = GR_GL_TEXTURE_2D;
1641*c8dee2aaSAndroid Build Coastguard Worker     desc.fOwnership = GrBackendObjectOwnership::kOwned;
1642*c8dee2aaSAndroid Build Coastguard Worker     desc.fFormat = GrBackendFormats::AsGLFormat(format);
1643*c8dee2aaSAndroid Build Coastguard Worker     desc.fIsProtected = skgpu::Protected(isProtected == skgpu::Protected::kYes ||
1644*c8dee2aaSAndroid Build Coastguard Worker                                          this->glCaps().strictProtectedness());
1645*c8dee2aaSAndroid Build Coastguard Worker     desc.fID = this->createCompressedTexture2D(desc.fSize, compression, desc.fFormat,
1646*c8dee2aaSAndroid Build Coastguard Worker                                                mipmapped, desc.fIsProtected, &initialState);
1647*c8dee2aaSAndroid Build Coastguard Worker     if (!desc.fID) {
1648*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
1649*c8dee2aaSAndroid Build Coastguard Worker     }
1650*c8dee2aaSAndroid Build Coastguard Worker 
1651*c8dee2aaSAndroid Build Coastguard Worker     if (data) {
1652*c8dee2aaSAndroid Build Coastguard Worker         if (!this->uploadCompressedTexData(compression, desc.fFormat, dimensions, mipmapped,
1653*c8dee2aaSAndroid Build Coastguard Worker                                            GR_GL_TEXTURE_2D, data, dataSize)) {
1654*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(DeleteTextures(1, &desc.fID));
1655*c8dee2aaSAndroid Build Coastguard Worker             return nullptr;
1656*c8dee2aaSAndroid Build Coastguard Worker         }
1657*c8dee2aaSAndroid Build Coastguard Worker     }
1658*c8dee2aaSAndroid Build Coastguard Worker 
1659*c8dee2aaSAndroid Build Coastguard Worker     // Unbind this texture from the scratch texture unit.
1660*c8dee2aaSAndroid Build Coastguard Worker     this->bindTextureToScratchUnit(GR_GL_TEXTURE_2D, 0);
1661*c8dee2aaSAndroid Build Coastguard Worker 
1662*c8dee2aaSAndroid Build Coastguard Worker     GrMipmapStatus mipmapStatus = mipmapped == skgpu::Mipmapped::kYes
1663*c8dee2aaSAndroid Build Coastguard Worker                                           ? GrMipmapStatus::kValid
1664*c8dee2aaSAndroid Build Coastguard Worker                                           : GrMipmapStatus::kNotAllocated;
1665*c8dee2aaSAndroid Build Coastguard Worker 
1666*c8dee2aaSAndroid Build Coastguard Worker     auto tex = sk_make_sp<GrGLTexture>(this, budgeted, desc, mipmapStatus,
1667*c8dee2aaSAndroid Build Coastguard Worker                                        /*label=*/"GLGpuCreateCompressedTexture");
1668*c8dee2aaSAndroid Build Coastguard Worker     // The non-sampler params are still at their default values.
1669*c8dee2aaSAndroid Build Coastguard Worker     tex->parameters()->set(&initialState, GrGLTextureParameters::NonsamplerState(),
1670*c8dee2aaSAndroid Build Coastguard Worker                            fResetTimestampForTextureParameters);
1671*c8dee2aaSAndroid Build Coastguard Worker     return tex;
1672*c8dee2aaSAndroid Build Coastguard Worker }
1673*c8dee2aaSAndroid Build Coastguard Worker 
onCreateCompressedBackendTexture(SkISize dimensions,const GrBackendFormat & format,skgpu::Mipmapped mipmapped,GrProtected isProtected)1674*c8dee2aaSAndroid Build Coastguard Worker GrBackendTexture GrGLGpu::onCreateCompressedBackendTexture(SkISize dimensions,
1675*c8dee2aaSAndroid Build Coastguard Worker                                                            const GrBackendFormat& format,
1676*c8dee2aaSAndroid Build Coastguard Worker                                                            skgpu::Mipmapped mipmapped,
1677*c8dee2aaSAndroid Build Coastguard Worker                                                            GrProtected isProtected) {
1678*c8dee2aaSAndroid Build Coastguard Worker     if (isProtected == GrProtected::kYes && !this->glCaps().supportsProtectedContent()) {
1679*c8dee2aaSAndroid Build Coastguard Worker         return {};
1680*c8dee2aaSAndroid Build Coastguard Worker     }
1681*c8dee2aaSAndroid Build Coastguard Worker 
1682*c8dee2aaSAndroid Build Coastguard Worker     this->handleDirtyContext();
1683*c8dee2aaSAndroid Build Coastguard Worker 
1684*c8dee2aaSAndroid Build Coastguard Worker     GrGLFormat glFormat = GrBackendFormats::AsGLFormat(format);
1685*c8dee2aaSAndroid Build Coastguard Worker     if (glFormat == GrGLFormat::kUnknown) {
1686*c8dee2aaSAndroid Build Coastguard Worker         return {};
1687*c8dee2aaSAndroid Build Coastguard Worker     }
1688*c8dee2aaSAndroid Build Coastguard Worker 
1689*c8dee2aaSAndroid Build Coastguard Worker     SkTextureCompressionType compression = GrBackendFormatToCompressionType(format);
1690*c8dee2aaSAndroid Build Coastguard Worker 
1691*c8dee2aaSAndroid Build Coastguard Worker     GrGLTextureInfo info;
1692*c8dee2aaSAndroid Build Coastguard Worker     GrGLTextureParameters::SamplerOverriddenState initialState;
1693*c8dee2aaSAndroid Build Coastguard Worker 
1694*c8dee2aaSAndroid Build Coastguard Worker     info.fTarget = GR_GL_TEXTURE_2D;
1695*c8dee2aaSAndroid Build Coastguard Worker     info.fFormat = GrGLFormatToEnum(glFormat);
1696*c8dee2aaSAndroid Build Coastguard Worker     info.fProtected = skgpu::Protected(isProtected == skgpu::Protected::kYes ||
1697*c8dee2aaSAndroid Build Coastguard Worker                                        this->glCaps().strictProtectedness());
1698*c8dee2aaSAndroid Build Coastguard Worker     info.fID = this->createCompressedTexture2D(dimensions, compression, glFormat,
1699*c8dee2aaSAndroid Build Coastguard Worker                                                mipmapped, info.fProtected, &initialState);
1700*c8dee2aaSAndroid Build Coastguard Worker     if (!info.fID) {
1701*c8dee2aaSAndroid Build Coastguard Worker         return {};
1702*c8dee2aaSAndroid Build Coastguard Worker     }
1703*c8dee2aaSAndroid Build Coastguard Worker 
1704*c8dee2aaSAndroid Build Coastguard Worker     // Unbind this texture from the scratch texture unit.
1705*c8dee2aaSAndroid Build Coastguard Worker     this->bindTextureToScratchUnit(GR_GL_TEXTURE_2D, 0);
1706*c8dee2aaSAndroid Build Coastguard Worker 
1707*c8dee2aaSAndroid Build Coastguard Worker     auto parameters = sk_make_sp<GrGLTextureParameters>();
1708*c8dee2aaSAndroid Build Coastguard Worker     // The non-sampler params are still at their default values.
1709*c8dee2aaSAndroid Build Coastguard Worker     parameters->set(&initialState, GrGLTextureParameters::NonsamplerState(),
1710*c8dee2aaSAndroid Build Coastguard Worker                     fResetTimestampForTextureParameters);
1711*c8dee2aaSAndroid Build Coastguard Worker 
1712*c8dee2aaSAndroid Build Coastguard Worker     return GrBackendTextures::MakeGL(
1713*c8dee2aaSAndroid Build Coastguard Worker             dimensions.width(), dimensions.height(), mipmapped, info, std::move(parameters));
1714*c8dee2aaSAndroid Build Coastguard Worker }
1715*c8dee2aaSAndroid Build Coastguard Worker 
onUpdateCompressedBackendTexture(const GrBackendTexture & backendTexture,sk_sp<skgpu::RefCntedCallback> finishedCallback,const void * data,size_t length)1716*c8dee2aaSAndroid Build Coastguard Worker bool GrGLGpu::onUpdateCompressedBackendTexture(const GrBackendTexture& backendTexture,
1717*c8dee2aaSAndroid Build Coastguard Worker                                                sk_sp<skgpu::RefCntedCallback> finishedCallback,
1718*c8dee2aaSAndroid Build Coastguard Worker                                                const void* data,
1719*c8dee2aaSAndroid Build Coastguard Worker                                                size_t length) {
1720*c8dee2aaSAndroid Build Coastguard Worker     GrGLTextureInfo info;
1721*c8dee2aaSAndroid Build Coastguard Worker     SkAssertResult(GrBackendTextures::GetGLTextureInfo(backendTexture, &info));
1722*c8dee2aaSAndroid Build Coastguard Worker 
1723*c8dee2aaSAndroid Build Coastguard Worker     GrBackendFormat format = backendTexture.getBackendFormat();
1724*c8dee2aaSAndroid Build Coastguard Worker     GrGLFormat glFormat = GrBackendFormats::AsGLFormat(format);
1725*c8dee2aaSAndroid Build Coastguard Worker     if (glFormat == GrGLFormat::kUnknown) {
1726*c8dee2aaSAndroid Build Coastguard Worker         return false;
1727*c8dee2aaSAndroid Build Coastguard Worker     }
1728*c8dee2aaSAndroid Build Coastguard Worker     SkTextureCompressionType compression = GrBackendFormatToCompressionType(format);
1729*c8dee2aaSAndroid Build Coastguard Worker 
1730*c8dee2aaSAndroid Build Coastguard Worker     skgpu::Mipmapped mipmapped =
1731*c8dee2aaSAndroid Build Coastguard Worker             backendTexture.hasMipmaps() ? skgpu::Mipmapped::kYes : skgpu::Mipmapped::kNo;
1732*c8dee2aaSAndroid Build Coastguard Worker 
1733*c8dee2aaSAndroid Build Coastguard Worker     this->bindTextureToScratchUnit(info.fTarget, info.fID);
1734*c8dee2aaSAndroid Build Coastguard Worker 
1735*c8dee2aaSAndroid Build Coastguard Worker     // If we have mips make sure the base level is set to 0 and the max level set to numMipLevels-1
1736*c8dee2aaSAndroid Build Coastguard Worker     // so that the uploads go to the right levels.
1737*c8dee2aaSAndroid Build Coastguard Worker     if (backendTexture.hasMipmaps() && this->glCaps().mipmapLevelControlSupport()) {
1738*c8dee2aaSAndroid Build Coastguard Worker         auto params = get_gl_texture_params(backendTexture);
1739*c8dee2aaSAndroid Build Coastguard Worker         GrGLTextureParameters::NonsamplerState nonsamplerState = params->nonsamplerState();
1740*c8dee2aaSAndroid Build Coastguard Worker         if (params->nonsamplerState().fBaseMipMapLevel != 0) {
1741*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(TexParameteri(info.fTarget, GR_GL_TEXTURE_BASE_LEVEL, 0));
1742*c8dee2aaSAndroid Build Coastguard Worker             nonsamplerState.fBaseMipMapLevel = 0;
1743*c8dee2aaSAndroid Build Coastguard Worker         }
1744*c8dee2aaSAndroid Build Coastguard Worker         int numMipLevels =
1745*c8dee2aaSAndroid Build Coastguard Worker                 SkMipmap::ComputeLevelCount(backendTexture.width(), backendTexture.height()) + 1;
1746*c8dee2aaSAndroid Build Coastguard Worker         if (params->nonsamplerState().fMaxMipmapLevel != (numMipLevels - 1)) {
1747*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(TexParameteri(info.fTarget, GR_GL_TEXTURE_MAX_LEVEL, numMipLevels - 1));
1748*c8dee2aaSAndroid Build Coastguard Worker             nonsamplerState.fBaseMipMapLevel = numMipLevels - 1;
1749*c8dee2aaSAndroid Build Coastguard Worker         }
1750*c8dee2aaSAndroid Build Coastguard Worker         params->set(nullptr, nonsamplerState, fResetTimestampForTextureParameters);
1751*c8dee2aaSAndroid Build Coastguard Worker     }
1752*c8dee2aaSAndroid Build Coastguard Worker 
1753*c8dee2aaSAndroid Build Coastguard Worker     bool result = this->uploadCompressedTexData(compression,
1754*c8dee2aaSAndroid Build Coastguard Worker                                                 glFormat,
1755*c8dee2aaSAndroid Build Coastguard Worker                                                 backendTexture.dimensions(),
1756*c8dee2aaSAndroid Build Coastguard Worker                                                 mipmapped,
1757*c8dee2aaSAndroid Build Coastguard Worker                                                 GR_GL_TEXTURE_2D,
1758*c8dee2aaSAndroid Build Coastguard Worker                                                 data,
1759*c8dee2aaSAndroid Build Coastguard Worker                                                 length);
1760*c8dee2aaSAndroid Build Coastguard Worker 
1761*c8dee2aaSAndroid Build Coastguard Worker     // Unbind this texture from the scratch texture unit.
1762*c8dee2aaSAndroid Build Coastguard Worker     this->bindTextureToScratchUnit(info.fTarget, 0);
1763*c8dee2aaSAndroid Build Coastguard Worker 
1764*c8dee2aaSAndroid Build Coastguard Worker     return result;
1765*c8dee2aaSAndroid Build Coastguard Worker }
1766*c8dee2aaSAndroid Build Coastguard Worker 
getCompatibleStencilIndex(GrGLFormat format)1767*c8dee2aaSAndroid Build Coastguard Worker int GrGLGpu::getCompatibleStencilIndex(GrGLFormat format) {
1768*c8dee2aaSAndroid Build Coastguard Worker     if (this->glCaps().avoidStencilBuffers()) {
1769*c8dee2aaSAndroid Build Coastguard Worker         return -1;
1770*c8dee2aaSAndroid Build Coastguard Worker     }
1771*c8dee2aaSAndroid Build Coastguard Worker 
1772*c8dee2aaSAndroid Build Coastguard Worker     static const int kSize = 16;
1773*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(this->glCaps().canFormatBeFBOColorAttachment(format));
1774*c8dee2aaSAndroid Build Coastguard Worker 
1775*c8dee2aaSAndroid Build Coastguard Worker     if (!this->glCaps().hasStencilFormatBeenDeterminedForFormat(format)) {
1776*c8dee2aaSAndroid Build Coastguard Worker         // Default to unsupported, set this if we find a stencil format that works.
1777*c8dee2aaSAndroid Build Coastguard Worker         int firstWorkingStencilFormatIndex = -1;
1778*c8dee2aaSAndroid Build Coastguard Worker 
1779*c8dee2aaSAndroid Build Coastguard Worker         // In the following we're not actually creating the StencilBuffer that will be used but,
1780*c8dee2aaSAndroid Build Coastguard Worker         // rather, are just determining the correct format to use. We assume that the
1781*c8dee2aaSAndroid Build Coastguard Worker         // acceptable format will not change between Protected and unProtected stencil buffers and
1782*c8dee2aaSAndroid Build Coastguard Worker         // that using Protected::kNo here will not cause any issues with strictProtectedness mode
1783*c8dee2aaSAndroid Build Coastguard Worker         // (since no work is actually submitted to a queue).
1784*c8dee2aaSAndroid Build Coastguard Worker         const GrProtected kNotProtected = skgpu::Protected::kNo;
1785*c8dee2aaSAndroid Build Coastguard Worker 
1786*c8dee2aaSAndroid Build Coastguard Worker         GrGLuint colorID = this->createTexture({kSize, kSize}, format, GR_GL_TEXTURE_2D,
1787*c8dee2aaSAndroid Build Coastguard Worker                                                GrRenderable::kYes,
1788*c8dee2aaSAndroid Build Coastguard Worker                                                nullptr,
1789*c8dee2aaSAndroid Build Coastguard Worker                                                1,
1790*c8dee2aaSAndroid Build Coastguard Worker                                                kNotProtected,
1791*c8dee2aaSAndroid Build Coastguard Worker                                                /*label=*/"Skia");
1792*c8dee2aaSAndroid Build Coastguard Worker         if (!colorID) {
1793*c8dee2aaSAndroid Build Coastguard Worker             return -1;
1794*c8dee2aaSAndroid Build Coastguard Worker         }
1795*c8dee2aaSAndroid Build Coastguard Worker         // unbind the texture from the texture unit before binding it to the frame buffer
1796*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(BindTexture(GR_GL_TEXTURE_2D, 0));
1797*c8dee2aaSAndroid Build Coastguard Worker 
1798*c8dee2aaSAndroid Build Coastguard Worker         // Create Framebuffer
1799*c8dee2aaSAndroid Build Coastguard Worker         GrGLuint fb = 0;
1800*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(GenFramebuffers(1, &fb));
1801*c8dee2aaSAndroid Build Coastguard Worker         this->bindFramebuffer(GR_GL_FRAMEBUFFER, fb);
1802*c8dee2aaSAndroid Build Coastguard Worker         fHWBoundRenderTargetUniqueID.makeInvalid();
1803*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(FramebufferTexture2D(GR_GL_FRAMEBUFFER,
1804*c8dee2aaSAndroid Build Coastguard Worker                                      GR_GL_COLOR_ATTACHMENT0,
1805*c8dee2aaSAndroid Build Coastguard Worker                                      GR_GL_TEXTURE_2D,
1806*c8dee2aaSAndroid Build Coastguard Worker                                      colorID,
1807*c8dee2aaSAndroid Build Coastguard Worker                                      0));
1808*c8dee2aaSAndroid Build Coastguard Worker         GrGLuint sbRBID = 0;
1809*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(GenRenderbuffers(1, &sbRBID));
1810*c8dee2aaSAndroid Build Coastguard Worker 
1811*c8dee2aaSAndroid Build Coastguard Worker         // look over formats till I find a compatible one
1812*c8dee2aaSAndroid Build Coastguard Worker         int stencilFmtCnt = this->glCaps().stencilFormats().size();
1813*c8dee2aaSAndroid Build Coastguard Worker         if (sbRBID) {
1814*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(BindRenderbuffer(GR_GL_RENDERBUFFER, sbRBID));
1815*c8dee2aaSAndroid Build Coastguard Worker             for (int i = 0; i < stencilFmtCnt && sbRBID; ++i) {
1816*c8dee2aaSAndroid Build Coastguard Worker                 GrGLFormat sFmt = this->glCaps().stencilFormats()[i];
1817*c8dee2aaSAndroid Build Coastguard Worker                 GrGLenum error = GL_ALLOC_CALL(RenderbufferStorage(
1818*c8dee2aaSAndroid Build Coastguard Worker                         GR_GL_RENDERBUFFER, GrGLFormatToEnum(sFmt), kSize, kSize));
1819*c8dee2aaSAndroid Build Coastguard Worker                 if (error == GR_GL_NO_ERROR) {
1820*c8dee2aaSAndroid Build Coastguard Worker                     GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1821*c8dee2aaSAndroid Build Coastguard Worker                                                     GR_GL_STENCIL_ATTACHMENT,
1822*c8dee2aaSAndroid Build Coastguard Worker                                                     GR_GL_RENDERBUFFER, sbRBID));
1823*c8dee2aaSAndroid Build Coastguard Worker                     if (GrGLFormatIsPackedDepthStencil(sFmt)) {
1824*c8dee2aaSAndroid Build Coastguard Worker                         GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1825*c8dee2aaSAndroid Build Coastguard Worker                                                         GR_GL_DEPTH_ATTACHMENT,
1826*c8dee2aaSAndroid Build Coastguard Worker                                                         GR_GL_RENDERBUFFER, sbRBID));
1827*c8dee2aaSAndroid Build Coastguard Worker                     } else {
1828*c8dee2aaSAndroid Build Coastguard Worker                         GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1829*c8dee2aaSAndroid Build Coastguard Worker                                                         GR_GL_DEPTH_ATTACHMENT,
1830*c8dee2aaSAndroid Build Coastguard Worker                                                         GR_GL_RENDERBUFFER, 0));
1831*c8dee2aaSAndroid Build Coastguard Worker                     }
1832*c8dee2aaSAndroid Build Coastguard Worker                     GrGLenum status;
1833*c8dee2aaSAndroid Build Coastguard Worker                     GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
1834*c8dee2aaSAndroid Build Coastguard Worker                     if (status == GR_GL_FRAMEBUFFER_COMPLETE) {
1835*c8dee2aaSAndroid Build Coastguard Worker                         firstWorkingStencilFormatIndex = i;
1836*c8dee2aaSAndroid Build Coastguard Worker                         break;
1837*c8dee2aaSAndroid Build Coastguard Worker                     }
1838*c8dee2aaSAndroid Build Coastguard Worker                     GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1839*c8dee2aaSAndroid Build Coastguard Worker                                                     GR_GL_STENCIL_ATTACHMENT,
1840*c8dee2aaSAndroid Build Coastguard Worker                                                     GR_GL_RENDERBUFFER, 0));
1841*c8dee2aaSAndroid Build Coastguard Worker                     if (GrGLFormatIsPackedDepthStencil(sFmt)) {
1842*c8dee2aaSAndroid Build Coastguard Worker                         GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1843*c8dee2aaSAndroid Build Coastguard Worker                                                         GR_GL_DEPTH_ATTACHMENT,
1844*c8dee2aaSAndroid Build Coastguard Worker                                                         GR_GL_RENDERBUFFER, 0));
1845*c8dee2aaSAndroid Build Coastguard Worker                     }
1846*c8dee2aaSAndroid Build Coastguard Worker                 }
1847*c8dee2aaSAndroid Build Coastguard Worker             }
1848*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(DeleteRenderbuffers(1, &sbRBID));
1849*c8dee2aaSAndroid Build Coastguard Worker         }
1850*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(DeleteTextures(1, &colorID));
1851*c8dee2aaSAndroid Build Coastguard Worker         this->bindFramebuffer(GR_GL_FRAMEBUFFER, 0);
1852*c8dee2aaSAndroid Build Coastguard Worker         this->deleteFramebuffer(fb);
1853*c8dee2aaSAndroid Build Coastguard Worker         fGLContext->caps()->setStencilFormatIndexForFormat(format, firstWorkingStencilFormatIndex);
1854*c8dee2aaSAndroid Build Coastguard Worker     }
1855*c8dee2aaSAndroid Build Coastguard Worker     return this->glCaps().getStencilFormatIndexForFormat(format);
1856*c8dee2aaSAndroid Build Coastguard Worker }
1857*c8dee2aaSAndroid Build Coastguard Worker 
set_khr_debug_label(GrGLGpu * gpu,const GrGLuint id,std::string_view label)1858*c8dee2aaSAndroid Build Coastguard Worker static void set_khr_debug_label(GrGLGpu* gpu, const GrGLuint id, std::string_view label) {
1859*c8dee2aaSAndroid Build Coastguard Worker     const std::string khr_debug_label = label.empty() ? "Skia" : std::string(label);
1860*c8dee2aaSAndroid Build Coastguard Worker     if (gpu->glCaps().debugSupport()) {
1861*c8dee2aaSAndroid Build Coastguard Worker         GR_GL_CALL(gpu->glInterface(), ObjectLabel(GR_GL_TEXTURE, id, -1, khr_debug_label.c_str()));
1862*c8dee2aaSAndroid Build Coastguard Worker     }
1863*c8dee2aaSAndroid Build Coastguard Worker }
1864*c8dee2aaSAndroid Build Coastguard Worker 
createCompressedTexture2D(SkISize dimensions,SkTextureCompressionType compression,GrGLFormat format,skgpu::Mipmapped mipmapped,GrProtected isProtected,GrGLTextureParameters::SamplerOverriddenState * initialState)1865*c8dee2aaSAndroid Build Coastguard Worker GrGLuint GrGLGpu::createCompressedTexture2D(
1866*c8dee2aaSAndroid Build Coastguard Worker         SkISize dimensions,
1867*c8dee2aaSAndroid Build Coastguard Worker         SkTextureCompressionType compression,
1868*c8dee2aaSAndroid Build Coastguard Worker         GrGLFormat format,
1869*c8dee2aaSAndroid Build Coastguard Worker         skgpu::Mipmapped mipmapped,
1870*c8dee2aaSAndroid Build Coastguard Worker         GrProtected isProtected,
1871*c8dee2aaSAndroid Build Coastguard Worker         GrGLTextureParameters::SamplerOverriddenState* initialState) {
1872*c8dee2aaSAndroid Build Coastguard Worker     if (format == GrGLFormat::kUnknown) {
1873*c8dee2aaSAndroid Build Coastguard Worker         return 0;
1874*c8dee2aaSAndroid Build Coastguard Worker     }
1875*c8dee2aaSAndroid Build Coastguard Worker     GrGLuint id = 0;
1876*c8dee2aaSAndroid Build Coastguard Worker     GL_CALL(GenTextures(1, &id));
1877*c8dee2aaSAndroid Build Coastguard Worker     if (!id) {
1878*c8dee2aaSAndroid Build Coastguard Worker         return 0;
1879*c8dee2aaSAndroid Build Coastguard Worker     }
1880*c8dee2aaSAndroid Build Coastguard Worker 
1881*c8dee2aaSAndroid Build Coastguard Worker     this->bindTextureToScratchUnit(GR_GL_TEXTURE_2D, id);
1882*c8dee2aaSAndroid Build Coastguard Worker 
1883*c8dee2aaSAndroid Build Coastguard Worker     set_khr_debug_label(this, id, /*label=*/"Skia");
1884*c8dee2aaSAndroid Build Coastguard Worker 
1885*c8dee2aaSAndroid Build Coastguard Worker     *initialState = set_initial_texture_params(this->glInterface(),
1886*c8dee2aaSAndroid Build Coastguard Worker                                                this->glCaps(),
1887*c8dee2aaSAndroid Build Coastguard Worker                                                GR_GL_TEXTURE_2D);
1888*c8dee2aaSAndroid Build Coastguard Worker 
1889*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(isProtected == skgpu::Protected::kNo || this->glCaps().supportsProtectedContent());
1890*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!this->glCaps().strictProtectedness() || isProtected == skgpu::Protected::kYes);
1891*c8dee2aaSAndroid Build Coastguard Worker 
1892*c8dee2aaSAndroid Build Coastguard Worker     if (GrProtected::kYes == isProtected) {
1893*c8dee2aaSAndroid Build Coastguard Worker         if (this->glCaps().supportsProtectedContent()) {
1894*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_PROTECTED_EXT, GR_GL_TRUE));
1895*c8dee2aaSAndroid Build Coastguard Worker         } else {
1896*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(DeleteTextures(1, &id));
1897*c8dee2aaSAndroid Build Coastguard Worker             return 0;
1898*c8dee2aaSAndroid Build Coastguard Worker         }
1899*c8dee2aaSAndroid Build Coastguard Worker     }
1900*c8dee2aaSAndroid Build Coastguard Worker 
1901*c8dee2aaSAndroid Build Coastguard Worker     return id;
1902*c8dee2aaSAndroid Build Coastguard Worker }
1903*c8dee2aaSAndroid Build Coastguard Worker 
createTexture(SkISize dimensions,GrGLFormat format,GrGLenum target,GrRenderable renderable,GrGLTextureParameters::SamplerOverriddenState * initialState,int mipLevelCount,GrProtected isProtected,std::string_view label)1904*c8dee2aaSAndroid Build Coastguard Worker GrGLuint GrGLGpu::createTexture(SkISize dimensions,
1905*c8dee2aaSAndroid Build Coastguard Worker                                 GrGLFormat format,
1906*c8dee2aaSAndroid Build Coastguard Worker                                 GrGLenum target,
1907*c8dee2aaSAndroid Build Coastguard Worker                                 GrRenderable renderable,
1908*c8dee2aaSAndroid Build Coastguard Worker                                 GrGLTextureParameters::SamplerOverriddenState* initialState,
1909*c8dee2aaSAndroid Build Coastguard Worker                                 int mipLevelCount,
1910*c8dee2aaSAndroid Build Coastguard Worker                                 GrProtected isProtected,
1911*c8dee2aaSAndroid Build Coastguard Worker                                 std::string_view label) {
1912*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(format != GrGLFormat::kUnknown);
1913*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!GrGLFormatIsCompressed(format));
1914*c8dee2aaSAndroid Build Coastguard Worker 
1915*c8dee2aaSAndroid Build Coastguard Worker     GrGLuint id = 0;
1916*c8dee2aaSAndroid Build Coastguard Worker     GL_CALL(GenTextures(1, &id));
1917*c8dee2aaSAndroid Build Coastguard Worker 
1918*c8dee2aaSAndroid Build Coastguard Worker     if (!id) {
1919*c8dee2aaSAndroid Build Coastguard Worker         return 0;
1920*c8dee2aaSAndroid Build Coastguard Worker     }
1921*c8dee2aaSAndroid Build Coastguard Worker 
1922*c8dee2aaSAndroid Build Coastguard Worker     this->bindTextureToScratchUnit(target, id);
1923*c8dee2aaSAndroid Build Coastguard Worker 
1924*c8dee2aaSAndroid Build Coastguard Worker     set_khr_debug_label(this, id, label);
1925*c8dee2aaSAndroid Build Coastguard Worker 
1926*c8dee2aaSAndroid Build Coastguard Worker     if (GrRenderable::kYes == renderable && this->glCaps().textureUsageSupport()) {
1927*c8dee2aaSAndroid Build Coastguard Worker         // provides a hint about how this texture will be used
1928*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(TexParameteri(target, GR_GL_TEXTURE_USAGE, GR_GL_FRAMEBUFFER_ATTACHMENT));
1929*c8dee2aaSAndroid Build Coastguard Worker     }
1930*c8dee2aaSAndroid Build Coastguard Worker 
1931*c8dee2aaSAndroid Build Coastguard Worker     if (initialState) {
1932*c8dee2aaSAndroid Build Coastguard Worker         *initialState = set_initial_texture_params(this->glInterface(), this->glCaps(), target);
1933*c8dee2aaSAndroid Build Coastguard Worker     } else {
1934*c8dee2aaSAndroid Build Coastguard Worker         set_initial_texture_params(this->glInterface(), this->glCaps(), target);
1935*c8dee2aaSAndroid Build Coastguard Worker     }
1936*c8dee2aaSAndroid Build Coastguard Worker 
1937*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(isProtected == skgpu::Protected::kNo || this->glCaps().supportsProtectedContent());
1938*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!this->glCaps().strictProtectedness() || isProtected == skgpu::Protected::kYes);
1939*c8dee2aaSAndroid Build Coastguard Worker 
1940*c8dee2aaSAndroid Build Coastguard Worker     if (GrProtected::kYes == isProtected) {
1941*c8dee2aaSAndroid Build Coastguard Worker         if (this->glCaps().supportsProtectedContent()) {
1942*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(TexParameteri(target, GR_GL_TEXTURE_PROTECTED_EXT, GR_GL_TRUE));
1943*c8dee2aaSAndroid Build Coastguard Worker         } else {
1944*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(DeleteTextures(1, &id));
1945*c8dee2aaSAndroid Build Coastguard Worker             return 0;
1946*c8dee2aaSAndroid Build Coastguard Worker         }
1947*c8dee2aaSAndroid Build Coastguard Worker     }
1948*c8dee2aaSAndroid Build Coastguard Worker 
1949*c8dee2aaSAndroid Build Coastguard Worker     GrGLenum internalFormat = this->glCaps().getTexImageOrStorageInternalFormat(format);
1950*c8dee2aaSAndroid Build Coastguard Worker 
1951*c8dee2aaSAndroid Build Coastguard Worker     bool success = false;
1952*c8dee2aaSAndroid Build Coastguard Worker     if (internalFormat) {
1953*c8dee2aaSAndroid Build Coastguard Worker         if (this->glCaps().formatSupportsTexStorage(format)) {
1954*c8dee2aaSAndroid Build Coastguard Worker             auto levelCount = std::max(mipLevelCount, 1);
1955*c8dee2aaSAndroid Build Coastguard Worker             GrGLenum error = GL_ALLOC_CALL(TexStorage2D(target, levelCount, internalFormat,
1956*c8dee2aaSAndroid Build Coastguard Worker                                                         dimensions.width(), dimensions.height()));
1957*c8dee2aaSAndroid Build Coastguard Worker             success = (error == GR_GL_NO_ERROR);
1958*c8dee2aaSAndroid Build Coastguard Worker         } else {
1959*c8dee2aaSAndroid Build Coastguard Worker             GrGLenum externalFormat, externalType;
1960*c8dee2aaSAndroid Build Coastguard Worker             this->glCaps().getTexImageExternalFormatAndType(format, &externalFormat, &externalType);
1961*c8dee2aaSAndroid Build Coastguard Worker             GrGLenum error = GR_GL_NO_ERROR;
1962*c8dee2aaSAndroid Build Coastguard Worker             if (externalFormat && externalType) {
1963*c8dee2aaSAndroid Build Coastguard Worker                 // If we don't unbind here then nullptr is treated as a zero offset into the bound
1964*c8dee2aaSAndroid Build Coastguard Worker                 // transfer buffer rather than an indication that there is no data to copy.
1965*c8dee2aaSAndroid Build Coastguard Worker                 this->unbindXferBuffer(GrGpuBufferType::kXferCpuToGpu);
1966*c8dee2aaSAndroid Build Coastguard Worker                 for (int level = 0; level < mipLevelCount && error == GR_GL_NO_ERROR; level++) {
1967*c8dee2aaSAndroid Build Coastguard Worker                     const int twoToTheMipLevel = 1 << level;
1968*c8dee2aaSAndroid Build Coastguard Worker                     const int currentWidth = std::max(1, dimensions.width() / twoToTheMipLevel);
1969*c8dee2aaSAndroid Build Coastguard Worker                     const int currentHeight = std::max(1, dimensions.height() / twoToTheMipLevel);
1970*c8dee2aaSAndroid Build Coastguard Worker                     error = GL_ALLOC_CALL(TexImage2D(target, level, internalFormat, currentWidth,
1971*c8dee2aaSAndroid Build Coastguard Worker                                                      currentHeight, 0, externalFormat, externalType,
1972*c8dee2aaSAndroid Build Coastguard Worker                                                      nullptr));
1973*c8dee2aaSAndroid Build Coastguard Worker                 }
1974*c8dee2aaSAndroid Build Coastguard Worker                 success = (error == GR_GL_NO_ERROR);
1975*c8dee2aaSAndroid Build Coastguard Worker             }
1976*c8dee2aaSAndroid Build Coastguard Worker         }
1977*c8dee2aaSAndroid Build Coastguard Worker     }
1978*c8dee2aaSAndroid Build Coastguard Worker     if (success) {
1979*c8dee2aaSAndroid Build Coastguard Worker         return id;
1980*c8dee2aaSAndroid Build Coastguard Worker     }
1981*c8dee2aaSAndroid Build Coastguard Worker     GL_CALL(DeleteTextures(1, &id));
1982*c8dee2aaSAndroid Build Coastguard Worker     return 0;
1983*c8dee2aaSAndroid Build Coastguard Worker }
1984*c8dee2aaSAndroid Build Coastguard Worker 
makeStencilAttachment(const GrBackendFormat & colorFormat,SkISize dimensions,int numStencilSamples)1985*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrAttachment> GrGLGpu::makeStencilAttachment(const GrBackendFormat& colorFormat,
1986*c8dee2aaSAndroid Build Coastguard Worker                                                    SkISize dimensions, int numStencilSamples) {
1987*c8dee2aaSAndroid Build Coastguard Worker     int sIdx = this->getCompatibleStencilIndex(GrBackendFormats::AsGLFormat(colorFormat));
1988*c8dee2aaSAndroid Build Coastguard Worker     if (sIdx < 0) {
1989*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
1990*c8dee2aaSAndroid Build Coastguard Worker     }
1991*c8dee2aaSAndroid Build Coastguard Worker     GrGLFormat sFmt = this->glCaps().stencilFormats()[sIdx];
1992*c8dee2aaSAndroid Build Coastguard Worker 
1993*c8dee2aaSAndroid Build Coastguard Worker     auto stencil = GrGLAttachment::MakeStencil(this, dimensions, numStencilSamples, sFmt);
1994*c8dee2aaSAndroid Build Coastguard Worker     if (stencil) {
1995*c8dee2aaSAndroid Build Coastguard Worker         fStats.incStencilAttachmentCreates();
1996*c8dee2aaSAndroid Build Coastguard Worker     }
1997*c8dee2aaSAndroid Build Coastguard Worker     return stencil;
1998*c8dee2aaSAndroid Build Coastguard Worker }
1999*c8dee2aaSAndroid Build Coastguard Worker 
makeMSAAAttachment(SkISize dimensions,const GrBackendFormat & format,int numSamples,GrProtected isProtected,GrMemoryless isMemoryless)2000*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrAttachment> GrGLGpu::makeMSAAAttachment(SkISize dimensions, const GrBackendFormat& format,
2001*c8dee2aaSAndroid Build Coastguard Worker                                                 int numSamples, GrProtected isProtected,
2002*c8dee2aaSAndroid Build Coastguard Worker                                                 GrMemoryless isMemoryless) {
2003*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(isMemoryless == GrMemoryless::kNo);
2004*c8dee2aaSAndroid Build Coastguard Worker     return GrGLAttachment::MakeMSAA(
2005*c8dee2aaSAndroid Build Coastguard Worker             this, dimensions, numSamples, GrBackendFormats::AsGLFormat(format));
2006*c8dee2aaSAndroid Build Coastguard Worker }
2007*c8dee2aaSAndroid Build Coastguard Worker 
2008*c8dee2aaSAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////////
2009*c8dee2aaSAndroid Build Coastguard Worker 
onCreateBuffer(size_t size,GrGpuBufferType intendedType,GrAccessPattern accessPattern)2010*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrGpuBuffer> GrGLGpu::onCreateBuffer(size_t size,
2011*c8dee2aaSAndroid Build Coastguard Worker                                            GrGpuBufferType intendedType,
2012*c8dee2aaSAndroid Build Coastguard Worker                                            GrAccessPattern accessPattern) {
2013*c8dee2aaSAndroid Build Coastguard Worker     return GrGLBuffer::Make(this, size, intendedType, accessPattern);
2014*c8dee2aaSAndroid Build Coastguard Worker }
2015*c8dee2aaSAndroid Build Coastguard Worker 
flushScissorTest(GrScissorTest scissorTest)2016*c8dee2aaSAndroid Build Coastguard Worker void GrGLGpu::flushScissorTest(GrScissorTest scissorTest) {
2017*c8dee2aaSAndroid Build Coastguard Worker     if (GrScissorTest::kEnabled == scissorTest) {
2018*c8dee2aaSAndroid Build Coastguard Worker         if (kYes_TriState != fHWScissorSettings.fEnabled) {
2019*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(Enable(GR_GL_SCISSOR_TEST));
2020*c8dee2aaSAndroid Build Coastguard Worker             fHWScissorSettings.fEnabled = kYes_TriState;
2021*c8dee2aaSAndroid Build Coastguard Worker         }
2022*c8dee2aaSAndroid Build Coastguard Worker     } else {
2023*c8dee2aaSAndroid Build Coastguard Worker         if (kNo_TriState != fHWScissorSettings.fEnabled) {
2024*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(Disable(GR_GL_SCISSOR_TEST));
2025*c8dee2aaSAndroid Build Coastguard Worker             fHWScissorSettings.fEnabled = kNo_TriState;
2026*c8dee2aaSAndroid Build Coastguard Worker         }
2027*c8dee2aaSAndroid Build Coastguard Worker     }
2028*c8dee2aaSAndroid Build Coastguard Worker }
2029*c8dee2aaSAndroid Build Coastguard Worker 
flushScissorRect(const SkIRect & scissor,int rtHeight,GrSurfaceOrigin rtOrigin)2030*c8dee2aaSAndroid Build Coastguard Worker void GrGLGpu::flushScissorRect(const SkIRect& scissor, int rtHeight, GrSurfaceOrigin rtOrigin) {
2031*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(fHWScissorSettings.fEnabled == TriState::kYes_TriState);
2032*c8dee2aaSAndroid Build Coastguard Worker     auto nativeScissor = GrNativeRect::MakeRelativeTo(rtOrigin, rtHeight, scissor);
2033*c8dee2aaSAndroid Build Coastguard Worker     if (fHWScissorSettings.fRect != nativeScissor) {
2034*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(Scissor(nativeScissor.fX, nativeScissor.fY, nativeScissor.fWidth,
2035*c8dee2aaSAndroid Build Coastguard Worker                         nativeScissor.fHeight));
2036*c8dee2aaSAndroid Build Coastguard Worker         fHWScissorSettings.fRect = nativeScissor;
2037*c8dee2aaSAndroid Build Coastguard Worker     }
2038*c8dee2aaSAndroid Build Coastguard Worker }
2039*c8dee2aaSAndroid Build Coastguard Worker 
flushViewport(const SkIRect & viewport,int rtHeight,GrSurfaceOrigin rtOrigin)2040*c8dee2aaSAndroid Build Coastguard Worker void GrGLGpu::flushViewport(const SkIRect& viewport, int rtHeight, GrSurfaceOrigin rtOrigin) {
2041*c8dee2aaSAndroid Build Coastguard Worker     auto nativeViewport = GrNativeRect::MakeRelativeTo(rtOrigin, rtHeight, viewport);
2042*c8dee2aaSAndroid Build Coastguard Worker     if (fHWViewport != nativeViewport) {
2043*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(Viewport(nativeViewport.fX, nativeViewport.fY,
2044*c8dee2aaSAndroid Build Coastguard Worker                          nativeViewport.fWidth, nativeViewport.fHeight));
2045*c8dee2aaSAndroid Build Coastguard Worker         fHWViewport = nativeViewport;
2046*c8dee2aaSAndroid Build Coastguard Worker     }
2047*c8dee2aaSAndroid Build Coastguard Worker }
2048*c8dee2aaSAndroid Build Coastguard Worker 
flushWindowRectangles(const GrWindowRectsState & windowState,const GrGLRenderTarget * rt,GrSurfaceOrigin origin)2049*c8dee2aaSAndroid Build Coastguard Worker void GrGLGpu::flushWindowRectangles(const GrWindowRectsState& windowState,
2050*c8dee2aaSAndroid Build Coastguard Worker                                     const GrGLRenderTarget* rt, GrSurfaceOrigin origin) {
2051*c8dee2aaSAndroid Build Coastguard Worker #ifndef USE_NSIGHT
2052*c8dee2aaSAndroid Build Coastguard Worker     typedef GrWindowRectsState::Mode Mode;
2053*c8dee2aaSAndroid Build Coastguard Worker     // Window rects can't be used on-screen.
2054*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!windowState.enabled() || !rt->glRTFBOIDis0());
2055*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(windowState.numWindows() <= this->caps()->maxWindowRectangles());
2056*c8dee2aaSAndroid Build Coastguard Worker 
2057*c8dee2aaSAndroid Build Coastguard Worker     if (!this->caps()->maxWindowRectangles() ||
2058*c8dee2aaSAndroid Build Coastguard Worker         fHWWindowRectsState.knownEqualTo(origin, rt->width(), rt->height(), windowState)) {
2059*c8dee2aaSAndroid Build Coastguard Worker         return;
2060*c8dee2aaSAndroid Build Coastguard Worker     }
2061*c8dee2aaSAndroid Build Coastguard Worker 
2062*c8dee2aaSAndroid Build Coastguard Worker     // This is purely a workaround for a spurious warning generated by gcc. Otherwise the above
2063*c8dee2aaSAndroid Build Coastguard Worker     // assert would be sufficient. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=5912
2064*c8dee2aaSAndroid Build Coastguard Worker     int numWindows = std::min(windowState.numWindows(), int(GrWindowRectangles::kMaxWindows));
2065*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(windowState.numWindows() == numWindows);
2066*c8dee2aaSAndroid Build Coastguard Worker 
2067*c8dee2aaSAndroid Build Coastguard Worker     GrNativeRect glwindows[GrWindowRectangles::kMaxWindows];
2068*c8dee2aaSAndroid Build Coastguard Worker     const SkIRect* skwindows = windowState.windows().data();
2069*c8dee2aaSAndroid Build Coastguard Worker     for (int i = 0; i < numWindows; ++i) {
2070*c8dee2aaSAndroid Build Coastguard Worker         glwindows[i].setRelativeTo(origin, rt->height(), skwindows[i]);
2071*c8dee2aaSAndroid Build Coastguard Worker     }
2072*c8dee2aaSAndroid Build Coastguard Worker 
2073*c8dee2aaSAndroid Build Coastguard Worker     GrGLenum glmode = (Mode::kExclusive == windowState.mode()) ? GR_GL_EXCLUSIVE : GR_GL_INCLUSIVE;
2074*c8dee2aaSAndroid Build Coastguard Worker     GL_CALL(WindowRectangles(glmode, numWindows, glwindows->asInts()));
2075*c8dee2aaSAndroid Build Coastguard Worker 
2076*c8dee2aaSAndroid Build Coastguard Worker     fHWWindowRectsState.set(origin, rt->width(), rt->height(), windowState);
2077*c8dee2aaSAndroid Build Coastguard Worker #endif
2078*c8dee2aaSAndroid Build Coastguard Worker }
2079*c8dee2aaSAndroid Build Coastguard Worker 
disableWindowRectangles()2080*c8dee2aaSAndroid Build Coastguard Worker void GrGLGpu::disableWindowRectangles() {
2081*c8dee2aaSAndroid Build Coastguard Worker #ifndef USE_NSIGHT
2082*c8dee2aaSAndroid Build Coastguard Worker     if (!this->caps()->maxWindowRectangles() || fHWWindowRectsState.knownDisabled()) {
2083*c8dee2aaSAndroid Build Coastguard Worker         return;
2084*c8dee2aaSAndroid Build Coastguard Worker     }
2085*c8dee2aaSAndroid Build Coastguard Worker     GL_CALL(WindowRectangles(GR_GL_EXCLUSIVE, 0, nullptr));
2086*c8dee2aaSAndroid Build Coastguard Worker     fHWWindowRectsState.setDisabled();
2087*c8dee2aaSAndroid Build Coastguard Worker #endif
2088*c8dee2aaSAndroid Build Coastguard Worker }
2089*c8dee2aaSAndroid Build Coastguard Worker 
flushGLState(GrRenderTarget * renderTarget,bool useMultisampleFBO,const GrProgramInfo & programInfo)2090*c8dee2aaSAndroid Build Coastguard Worker bool GrGLGpu::flushGLState(GrRenderTarget* renderTarget, bool useMultisampleFBO,
2091*c8dee2aaSAndroid Build Coastguard Worker                            const GrProgramInfo& programInfo) {
2092*c8dee2aaSAndroid Build Coastguard Worker     this->handleDirtyContext();
2093*c8dee2aaSAndroid Build Coastguard Worker 
2094*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<GrGLProgram> program = fProgramCache->findOrCreateProgram(this->getContext(),
2095*c8dee2aaSAndroid Build Coastguard Worker                                                                     programInfo);
2096*c8dee2aaSAndroid Build Coastguard Worker     if (!program) {
2097*c8dee2aaSAndroid Build Coastguard Worker         GrCapsDebugf(this->caps(), "Failed to create program!\n");
2098*c8dee2aaSAndroid Build Coastguard Worker         return false;
2099*c8dee2aaSAndroid Build Coastguard Worker     }
2100*c8dee2aaSAndroid Build Coastguard Worker 
2101*c8dee2aaSAndroid Build Coastguard Worker     this->flushProgram(std::move(program));
2102*c8dee2aaSAndroid Build Coastguard Worker 
2103*c8dee2aaSAndroid Build Coastguard Worker     // Swizzle the blend to match what the shader will output.
2104*c8dee2aaSAndroid Build Coastguard Worker     this->flushBlendAndColorWrite(programInfo.pipeline().getXferProcessor().getBlendInfo(),
2105*c8dee2aaSAndroid Build Coastguard Worker                                   programInfo.pipeline().writeSwizzle());
2106*c8dee2aaSAndroid Build Coastguard Worker 
2107*c8dee2aaSAndroid Build Coastguard Worker     fHWProgram->updateUniforms(renderTarget, programInfo);
2108*c8dee2aaSAndroid Build Coastguard Worker 
2109*c8dee2aaSAndroid Build Coastguard Worker     GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(renderTarget);
2110*c8dee2aaSAndroid Build Coastguard Worker     GrStencilSettings stencil;
2111*c8dee2aaSAndroid Build Coastguard Worker     if (programInfo.isStencilEnabled()) {
2112*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(glRT->getStencilAttachment(useMultisampleFBO));
2113*c8dee2aaSAndroid Build Coastguard Worker         stencil.reset(*programInfo.userStencilSettings(),
2114*c8dee2aaSAndroid Build Coastguard Worker                       programInfo.pipeline().hasStencilClip(),
2115*c8dee2aaSAndroid Build Coastguard Worker                       glRT->numStencilBits(useMultisampleFBO));
2116*c8dee2aaSAndroid Build Coastguard Worker     }
2117*c8dee2aaSAndroid Build Coastguard Worker     this->flushStencil(stencil, programInfo.origin());
2118*c8dee2aaSAndroid Build Coastguard Worker     this->flushScissorTest(GrScissorTest(programInfo.pipeline().isScissorTestEnabled()));
2119*c8dee2aaSAndroid Build Coastguard Worker     this->flushWindowRectangles(programInfo.pipeline().getWindowRectsState(),
2120*c8dee2aaSAndroid Build Coastguard Worker                                 glRT, programInfo.origin());
2121*c8dee2aaSAndroid Build Coastguard Worker     this->flushConservativeRasterState(programInfo.pipeline().usesConservativeRaster());
2122*c8dee2aaSAndroid Build Coastguard Worker     this->flushWireframeState(programInfo.pipeline().isWireframe());
2123*c8dee2aaSAndroid Build Coastguard Worker 
2124*c8dee2aaSAndroid Build Coastguard Worker     // This must come after textures are flushed because a texture may need
2125*c8dee2aaSAndroid Build Coastguard Worker     // to be msaa-resolved (which will modify bound FBO state).
2126*c8dee2aaSAndroid Build Coastguard Worker     this->flushRenderTarget(glRT, useMultisampleFBO);
2127*c8dee2aaSAndroid Build Coastguard Worker 
2128*c8dee2aaSAndroid Build Coastguard Worker     return true;
2129*c8dee2aaSAndroid Build Coastguard Worker }
2130*c8dee2aaSAndroid Build Coastguard Worker 
flushProgram(sk_sp<GrGLProgram> program)2131*c8dee2aaSAndroid Build Coastguard Worker void GrGLGpu::flushProgram(sk_sp<GrGLProgram> program) {
2132*c8dee2aaSAndroid Build Coastguard Worker     if (!program) {
2133*c8dee2aaSAndroid Build Coastguard Worker         fHWProgram.reset();
2134*c8dee2aaSAndroid Build Coastguard Worker         fHWProgramID = 0;
2135*c8dee2aaSAndroid Build Coastguard Worker         return;
2136*c8dee2aaSAndroid Build Coastguard Worker     }
2137*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT((program == fHWProgram) == (fHWProgramID == program->programID()));
2138*c8dee2aaSAndroid Build Coastguard Worker     if (program == fHWProgram) {
2139*c8dee2aaSAndroid Build Coastguard Worker         return;
2140*c8dee2aaSAndroid Build Coastguard Worker     }
2141*c8dee2aaSAndroid Build Coastguard Worker     auto id = program->programID();
2142*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(id);
2143*c8dee2aaSAndroid Build Coastguard Worker     GL_CALL(UseProgram(id));
2144*c8dee2aaSAndroid Build Coastguard Worker     fHWProgram = std::move(program);
2145*c8dee2aaSAndroid Build Coastguard Worker     fHWProgramID = id;
2146*c8dee2aaSAndroid Build Coastguard Worker }
2147*c8dee2aaSAndroid Build Coastguard Worker 
flushProgram(GrGLuint id)2148*c8dee2aaSAndroid Build Coastguard Worker void GrGLGpu::flushProgram(GrGLuint id) {
2149*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(id);
2150*c8dee2aaSAndroid Build Coastguard Worker     if (fHWProgramID == id) {
2151*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(!fHWProgram);
2152*c8dee2aaSAndroid Build Coastguard Worker         return;
2153*c8dee2aaSAndroid Build Coastguard Worker     }
2154*c8dee2aaSAndroid Build Coastguard Worker     fHWProgram.reset();
2155*c8dee2aaSAndroid Build Coastguard Worker     GL_CALL(UseProgram(id));
2156*c8dee2aaSAndroid Build Coastguard Worker     fHWProgramID = id;
2157*c8dee2aaSAndroid Build Coastguard Worker }
2158*c8dee2aaSAndroid Build Coastguard Worker 
didDrawTo(GrRenderTarget * rt)2159*c8dee2aaSAndroid Build Coastguard Worker void GrGLGpu::didDrawTo(GrRenderTarget* rt) {
2160*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(fHWWriteToColor != kUnknown_TriState);
2161*c8dee2aaSAndroid Build Coastguard Worker     if (fHWWriteToColor == kYes_TriState) {
2162*c8dee2aaSAndroid Build Coastguard Worker         // The bounds are only used to check for empty and we don't know the bounds. The origin
2163*c8dee2aaSAndroid Build Coastguard Worker         // is irrelevant if there are no bounds.
2164*c8dee2aaSAndroid Build Coastguard Worker         this->didWriteToSurface(rt, kTopLeft_GrSurfaceOrigin, /*bounds=*/nullptr);
2165*c8dee2aaSAndroid Build Coastguard Worker     }
2166*c8dee2aaSAndroid Build Coastguard Worker }
2167*c8dee2aaSAndroid Build Coastguard Worker 
bindBuffer(GrGpuBufferType type,const GrBuffer * buffer)2168*c8dee2aaSAndroid Build Coastguard Worker GrGLenum GrGLGpu::bindBuffer(GrGpuBufferType type, const GrBuffer* buffer) {
2169*c8dee2aaSAndroid Build Coastguard Worker     this->handleDirtyContext();
2170*c8dee2aaSAndroid Build Coastguard Worker 
2171*c8dee2aaSAndroid Build Coastguard Worker     // Index buffer state is tied to the vertex array.
2172*c8dee2aaSAndroid Build Coastguard Worker     if (GrGpuBufferType::kIndex == type) {
2173*c8dee2aaSAndroid Build Coastguard Worker         this->bindVertexArray(0);
2174*c8dee2aaSAndroid Build Coastguard Worker     }
2175*c8dee2aaSAndroid Build Coastguard Worker 
2176*c8dee2aaSAndroid Build Coastguard Worker     auto* bufferState = this->hwBufferState(type);
2177*c8dee2aaSAndroid Build Coastguard Worker     if (buffer->isCpuBuffer()) {
2178*c8dee2aaSAndroid Build Coastguard Worker         if (!bufferState->fBufferZeroKnownBound) {
2179*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(BindBuffer(bufferState->fGLTarget, 0));
2180*c8dee2aaSAndroid Build Coastguard Worker             bufferState->fBufferZeroKnownBound = true;
2181*c8dee2aaSAndroid Build Coastguard Worker             bufferState->fBoundBufferUniqueID.makeInvalid();
2182*c8dee2aaSAndroid Build Coastguard Worker         }
2183*c8dee2aaSAndroid Build Coastguard Worker     } else if (static_cast<const GrGpuBuffer*>(buffer)->uniqueID() !=
2184*c8dee2aaSAndroid Build Coastguard Worker                bufferState->fBoundBufferUniqueID) {
2185*c8dee2aaSAndroid Build Coastguard Worker         const GrGLBuffer* glBuffer = static_cast<const GrGLBuffer*>(buffer);
2186*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(BindBuffer(bufferState->fGLTarget, glBuffer->bufferID()));
2187*c8dee2aaSAndroid Build Coastguard Worker         bufferState->fBufferZeroKnownBound = false;
2188*c8dee2aaSAndroid Build Coastguard Worker         bufferState->fBoundBufferUniqueID = glBuffer->uniqueID();
2189*c8dee2aaSAndroid Build Coastguard Worker     }
2190*c8dee2aaSAndroid Build Coastguard Worker 
2191*c8dee2aaSAndroid Build Coastguard Worker     return bufferState->fGLTarget;
2192*c8dee2aaSAndroid Build Coastguard Worker }
2193*c8dee2aaSAndroid Build Coastguard Worker 
clear(const GrScissorState & scissor,std::array<float,4> color,GrRenderTarget * target,bool useMultisampleFBO,GrSurfaceOrigin origin)2194*c8dee2aaSAndroid Build Coastguard Worker void GrGLGpu::clear(const GrScissorState& scissor,
2195*c8dee2aaSAndroid Build Coastguard Worker                     std::array<float, 4> color,
2196*c8dee2aaSAndroid Build Coastguard Worker                     GrRenderTarget* target,
2197*c8dee2aaSAndroid Build Coastguard Worker                     bool useMultisampleFBO,
2198*c8dee2aaSAndroid Build Coastguard Worker                     GrSurfaceOrigin origin) {
2199*c8dee2aaSAndroid Build Coastguard Worker     // parent class should never let us get here with no RT
2200*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(target);
2201*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!this->caps()->performColorClearsAsDraws());
2202*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!scissor.enabled() || !this->caps()->performPartialClearsAsDraws());
2203*c8dee2aaSAndroid Build Coastguard Worker 
2204*c8dee2aaSAndroid Build Coastguard Worker     this->handleDirtyContext();
2205*c8dee2aaSAndroid Build Coastguard Worker 
2206*c8dee2aaSAndroid Build Coastguard Worker     GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(target);
2207*c8dee2aaSAndroid Build Coastguard Worker 
2208*c8dee2aaSAndroid Build Coastguard Worker     this->flushRenderTarget(glRT, useMultisampleFBO);
2209*c8dee2aaSAndroid Build Coastguard Worker     this->flushScissor(scissor, glRT->height(), origin);
2210*c8dee2aaSAndroid Build Coastguard Worker     this->disableWindowRectangles();
2211*c8dee2aaSAndroid Build Coastguard Worker     this->flushColorWrite(true);
2212*c8dee2aaSAndroid Build Coastguard Worker     this->flushClearColor(color);
2213*c8dee2aaSAndroid Build Coastguard Worker     GL_CALL(Clear(GR_GL_COLOR_BUFFER_BIT));
2214*c8dee2aaSAndroid Build Coastguard Worker     this->didWriteToSurface(glRT, origin, scissor.enabled() ? &scissor.rect() : nullptr);
2215*c8dee2aaSAndroid Build Coastguard Worker }
2216*c8dee2aaSAndroid Build Coastguard Worker 
use_tiled_rendering(const GrGLCaps & glCaps,const GrOpsRenderPass::StencilLoadAndStoreInfo & stencilLoadStore)2217*c8dee2aaSAndroid Build Coastguard Worker static bool use_tiled_rendering(const GrGLCaps& glCaps,
2218*c8dee2aaSAndroid Build Coastguard Worker                                 const GrOpsRenderPass::StencilLoadAndStoreInfo& stencilLoadStore) {
2219*c8dee2aaSAndroid Build Coastguard Worker     // Only use the tiled rendering extension if we can explicitly clear and discard the stencil.
2220*c8dee2aaSAndroid Build Coastguard Worker     // Otherwise it's faster to just not use it.
2221*c8dee2aaSAndroid Build Coastguard Worker     return glCaps.tiledRenderingSupport() && GrLoadOp::kClear == stencilLoadStore.fLoadOp &&
2222*c8dee2aaSAndroid Build Coastguard Worker            GrStoreOp::kDiscard == stencilLoadStore.fStoreOp;
2223*c8dee2aaSAndroid Build Coastguard Worker }
2224*c8dee2aaSAndroid Build Coastguard Worker 
beginCommandBuffer(GrGLRenderTarget * rt,bool useMultisampleFBO,const SkIRect & bounds,GrSurfaceOrigin origin,const GrOpsRenderPass::LoadAndStoreInfo & colorLoadStore,const GrOpsRenderPass::StencilLoadAndStoreInfo & stencilLoadStore)2225*c8dee2aaSAndroid Build Coastguard Worker void GrGLGpu::beginCommandBuffer(GrGLRenderTarget* rt, bool useMultisampleFBO,
2226*c8dee2aaSAndroid Build Coastguard Worker                                  const SkIRect& bounds, GrSurfaceOrigin origin,
2227*c8dee2aaSAndroid Build Coastguard Worker                                  const GrOpsRenderPass::LoadAndStoreInfo& colorLoadStore,
2228*c8dee2aaSAndroid Build Coastguard Worker                                  const GrOpsRenderPass::StencilLoadAndStoreInfo& stencilLoadStore) {
2229*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!fIsExecutingCommandBuffer_DebugOnly);
2230*c8dee2aaSAndroid Build Coastguard Worker 
2231*c8dee2aaSAndroid Build Coastguard Worker     this->handleDirtyContext();
2232*c8dee2aaSAndroid Build Coastguard Worker 
2233*c8dee2aaSAndroid Build Coastguard Worker     this->flushRenderTarget(rt, useMultisampleFBO);
2234*c8dee2aaSAndroid Build Coastguard Worker     SkDEBUGCODE(fIsExecutingCommandBuffer_DebugOnly = true);
2235*c8dee2aaSAndroid Build Coastguard Worker 
2236*c8dee2aaSAndroid Build Coastguard Worker     if (use_tiled_rendering(this->glCaps(), stencilLoadStore)) {
2237*c8dee2aaSAndroid Build Coastguard Worker         auto nativeBounds = GrNativeRect::MakeRelativeTo(origin, rt->height(), bounds);
2238*c8dee2aaSAndroid Build Coastguard Worker         GrGLbitfield preserveMask = (GrLoadOp::kLoad == colorLoadStore.fLoadOp)
2239*c8dee2aaSAndroid Build Coastguard Worker                 ? GR_GL_COLOR_BUFFER_BIT0 : GR_GL_NONE;
2240*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(GrLoadOp::kLoad != stencilLoadStore.fLoadOp);  // Handled by use_tiled_rendering().
2241*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(StartTiling(nativeBounds.fX, nativeBounds.fY, nativeBounds.fWidth,
2242*c8dee2aaSAndroid Build Coastguard Worker                             nativeBounds.fHeight, preserveMask));
2243*c8dee2aaSAndroid Build Coastguard Worker     }
2244*c8dee2aaSAndroid Build Coastguard Worker 
2245*c8dee2aaSAndroid Build Coastguard Worker     GrGLbitfield clearMask = 0;
2246*c8dee2aaSAndroid Build Coastguard Worker     if (GrLoadOp::kClear == colorLoadStore.fLoadOp) {
2247*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(!this->caps()->performColorClearsAsDraws());
2248*c8dee2aaSAndroid Build Coastguard Worker         this->flushClearColor(colorLoadStore.fClearColor);
2249*c8dee2aaSAndroid Build Coastguard Worker         this->flushColorWrite(true);
2250*c8dee2aaSAndroid Build Coastguard Worker         clearMask |= GR_GL_COLOR_BUFFER_BIT;
2251*c8dee2aaSAndroid Build Coastguard Worker     }
2252*c8dee2aaSAndroid Build Coastguard Worker     if (GrLoadOp::kClear == stencilLoadStore.fLoadOp) {
2253*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(!this->caps()->performStencilClearsAsDraws());
2254*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(StencilMask(0xffffffff));
2255*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(ClearStencil(0));
2256*c8dee2aaSAndroid Build Coastguard Worker         clearMask |= GR_GL_STENCIL_BUFFER_BIT;
2257*c8dee2aaSAndroid Build Coastguard Worker     }
2258*c8dee2aaSAndroid Build Coastguard Worker     if (clearMask) {
2259*c8dee2aaSAndroid Build Coastguard Worker         this->flushScissorTest(GrScissorTest::kDisabled);
2260*c8dee2aaSAndroid Build Coastguard Worker         this->disableWindowRectangles();
2261*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(Clear(clearMask));
2262*c8dee2aaSAndroid Build Coastguard Worker         if (clearMask & GR_GL_COLOR_BUFFER_BIT) {
2263*c8dee2aaSAndroid Build Coastguard Worker             this->didWriteToSurface(rt, origin, nullptr);
2264*c8dee2aaSAndroid Build Coastguard Worker         }
2265*c8dee2aaSAndroid Build Coastguard Worker     }
2266*c8dee2aaSAndroid Build Coastguard Worker }
2267*c8dee2aaSAndroid Build Coastguard Worker 
endCommandBuffer(GrGLRenderTarget * rt,bool useMultisampleFBO,const GrOpsRenderPass::LoadAndStoreInfo & colorLoadStore,const GrOpsRenderPass::StencilLoadAndStoreInfo & stencilLoadStore)2268*c8dee2aaSAndroid Build Coastguard Worker void GrGLGpu::endCommandBuffer(GrGLRenderTarget* rt, bool useMultisampleFBO,
2269*c8dee2aaSAndroid Build Coastguard Worker                                const GrOpsRenderPass::LoadAndStoreInfo& colorLoadStore,
2270*c8dee2aaSAndroid Build Coastguard Worker                                const GrOpsRenderPass::StencilLoadAndStoreInfo& stencilLoadStore) {
2271*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(fIsExecutingCommandBuffer_DebugOnly);
2272*c8dee2aaSAndroid Build Coastguard Worker 
2273*c8dee2aaSAndroid Build Coastguard Worker     this->handleDirtyContext();
2274*c8dee2aaSAndroid Build Coastguard Worker 
2275*c8dee2aaSAndroid Build Coastguard Worker     if (rt->uniqueID() != fHWBoundRenderTargetUniqueID ||
2276*c8dee2aaSAndroid Build Coastguard Worker         useMultisampleFBO != fHWBoundFramebufferIsMSAA) {
2277*c8dee2aaSAndroid Build Coastguard Worker         // The framebuffer binding changed in the middle of a command buffer. We should have already
2278*c8dee2aaSAndroid Build Coastguard Worker         // printed a warning during onFBOChanged.
2279*c8dee2aaSAndroid Build Coastguard Worker         return;
2280*c8dee2aaSAndroid Build Coastguard Worker     }
2281*c8dee2aaSAndroid Build Coastguard Worker 
2282*c8dee2aaSAndroid Build Coastguard Worker     if (GrGLCaps::kNone_InvalidateFBType != this->glCaps().invalidateFBType()) {
2283*c8dee2aaSAndroid Build Coastguard Worker         STArray<2, GrGLenum> discardAttachments;
2284*c8dee2aaSAndroid Build Coastguard Worker         if (GrStoreOp::kDiscard == colorLoadStore.fStoreOp) {
2285*c8dee2aaSAndroid Build Coastguard Worker             discardAttachments.push_back(
2286*c8dee2aaSAndroid Build Coastguard Worker                     rt->isFBO0(useMultisampleFBO) ? GR_GL_COLOR : GR_GL_COLOR_ATTACHMENT0);
2287*c8dee2aaSAndroid Build Coastguard Worker         }
2288*c8dee2aaSAndroid Build Coastguard Worker         if (GrStoreOp::kDiscard == stencilLoadStore.fStoreOp) {
2289*c8dee2aaSAndroid Build Coastguard Worker             discardAttachments.push_back(
2290*c8dee2aaSAndroid Build Coastguard Worker                     rt->isFBO0(useMultisampleFBO) ? GR_GL_STENCIL : GR_GL_STENCIL_ATTACHMENT);
2291*c8dee2aaSAndroid Build Coastguard Worker         }
2292*c8dee2aaSAndroid Build Coastguard Worker 
2293*c8dee2aaSAndroid Build Coastguard Worker         if (!discardAttachments.empty()) {
2294*c8dee2aaSAndroid Build Coastguard Worker             if (GrGLCaps::kInvalidate_InvalidateFBType == this->glCaps().invalidateFBType()) {
2295*c8dee2aaSAndroid Build Coastguard Worker                 GL_CALL(InvalidateFramebuffer(GR_GL_FRAMEBUFFER, discardAttachments.size(),
2296*c8dee2aaSAndroid Build Coastguard Worker                                               discardAttachments.begin()));
2297*c8dee2aaSAndroid Build Coastguard Worker             } else {
2298*c8dee2aaSAndroid Build Coastguard Worker                 SkASSERT(GrGLCaps::kDiscard_InvalidateFBType == this->glCaps().invalidateFBType());
2299*c8dee2aaSAndroid Build Coastguard Worker                 GL_CALL(DiscardFramebuffer(GR_GL_FRAMEBUFFER, discardAttachments.size(),
2300*c8dee2aaSAndroid Build Coastguard Worker                                            discardAttachments.begin()));
2301*c8dee2aaSAndroid Build Coastguard Worker             }
2302*c8dee2aaSAndroid Build Coastguard Worker         }
2303*c8dee2aaSAndroid Build Coastguard Worker     }
2304*c8dee2aaSAndroid Build Coastguard Worker 
2305*c8dee2aaSAndroid Build Coastguard Worker     if (use_tiled_rendering(this->glCaps(), stencilLoadStore)) {
2306*c8dee2aaSAndroid Build Coastguard Worker         GrGLbitfield preserveMask = (GrStoreOp::kStore == colorLoadStore.fStoreOp)
2307*c8dee2aaSAndroid Build Coastguard Worker                 ? GR_GL_COLOR_BUFFER_BIT0 : GR_GL_NONE;
2308*c8dee2aaSAndroid Build Coastguard Worker         // Handled by use_tiled_rendering().
2309*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(GrStoreOp::kStore != stencilLoadStore.fStoreOp);
2310*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(EndTiling(preserveMask));
2311*c8dee2aaSAndroid Build Coastguard Worker     }
2312*c8dee2aaSAndroid Build Coastguard Worker 
2313*c8dee2aaSAndroid Build Coastguard Worker     SkDEBUGCODE(fIsExecutingCommandBuffer_DebugOnly = false);
2314*c8dee2aaSAndroid Build Coastguard Worker }
2315*c8dee2aaSAndroid Build Coastguard Worker 
clearStencilClip(const GrScissorState & scissor,bool insideStencilMask,GrRenderTarget * target,bool useMultisampleFBO,GrSurfaceOrigin origin)2316*c8dee2aaSAndroid Build Coastguard Worker void GrGLGpu::clearStencilClip(const GrScissorState& scissor, bool insideStencilMask,
2317*c8dee2aaSAndroid Build Coastguard Worker                                GrRenderTarget* target, bool useMultisampleFBO,
2318*c8dee2aaSAndroid Build Coastguard Worker                                GrSurfaceOrigin origin) {
2319*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(target);
2320*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!this->caps()->performStencilClearsAsDraws());
2321*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!scissor.enabled() || !this->caps()->performPartialClearsAsDraws());
2322*c8dee2aaSAndroid Build Coastguard Worker     this->handleDirtyContext();
2323*c8dee2aaSAndroid Build Coastguard Worker 
2324*c8dee2aaSAndroid Build Coastguard Worker     GrAttachment* sb = target->getStencilAttachment(useMultisampleFBO);
2325*c8dee2aaSAndroid Build Coastguard Worker     if (!sb) {
2326*c8dee2aaSAndroid Build Coastguard Worker         // We should only get here if we marked a proxy as requiring a SB. However,
2327*c8dee2aaSAndroid Build Coastguard Worker         // the SB creation could later fail. Likely clipping is going to go awry now.
2328*c8dee2aaSAndroid Build Coastguard Worker         return;
2329*c8dee2aaSAndroid Build Coastguard Worker     }
2330*c8dee2aaSAndroid Build Coastguard Worker 
2331*c8dee2aaSAndroid Build Coastguard Worker     GrGLint stencilBitCount =  GrBackendFormatStencilBits(sb->backendFormat());
2332*c8dee2aaSAndroid Build Coastguard Worker #if 0
2333*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(stencilBitCount > 0);
2334*c8dee2aaSAndroid Build Coastguard Worker     GrGLint clipStencilMask  = (1 << (stencilBitCount - 1));
2335*c8dee2aaSAndroid Build Coastguard Worker #else
2336*c8dee2aaSAndroid Build Coastguard Worker     // we could just clear the clip bit but when we go through
2337*c8dee2aaSAndroid Build Coastguard Worker     // ANGLE a partial stencil mask will cause clears to be
2338*c8dee2aaSAndroid Build Coastguard Worker     // turned into draws. Our contract on OpsTask says that
2339*c8dee2aaSAndroid Build Coastguard Worker     // changing the clip between stencil passes may or may not
2340*c8dee2aaSAndroid Build Coastguard Worker     // zero the client's clip bits. So we just clear the whole thing.
2341*c8dee2aaSAndroid Build Coastguard Worker     static const GrGLint clipStencilMask  = ~0;
2342*c8dee2aaSAndroid Build Coastguard Worker #endif
2343*c8dee2aaSAndroid Build Coastguard Worker     GrGLint value;
2344*c8dee2aaSAndroid Build Coastguard Worker     if (insideStencilMask) {
2345*c8dee2aaSAndroid Build Coastguard Worker         value = (1 << (stencilBitCount - 1));
2346*c8dee2aaSAndroid Build Coastguard Worker     } else {
2347*c8dee2aaSAndroid Build Coastguard Worker         value = 0;
2348*c8dee2aaSAndroid Build Coastguard Worker     }
2349*c8dee2aaSAndroid Build Coastguard Worker     GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(target);
2350*c8dee2aaSAndroid Build Coastguard Worker     this->flushRenderTarget(glRT, useMultisampleFBO);
2351*c8dee2aaSAndroid Build Coastguard Worker 
2352*c8dee2aaSAndroid Build Coastguard Worker     this->flushScissor(scissor, glRT->height(), origin);
2353*c8dee2aaSAndroid Build Coastguard Worker     this->disableWindowRectangles();
2354*c8dee2aaSAndroid Build Coastguard Worker 
2355*c8dee2aaSAndroid Build Coastguard Worker     GL_CALL(StencilMask((uint32_t) clipStencilMask));
2356*c8dee2aaSAndroid Build Coastguard Worker     GL_CALL(ClearStencil(value));
2357*c8dee2aaSAndroid Build Coastguard Worker     GL_CALL(Clear(GR_GL_STENCIL_BUFFER_BIT));
2358*c8dee2aaSAndroid Build Coastguard Worker     fHWStencilSettings.invalidate();
2359*c8dee2aaSAndroid Build Coastguard Worker }
2360*c8dee2aaSAndroid Build Coastguard Worker 
readOrTransferPixelsFrom(GrSurface * surface,SkIRect rect,GrColorType surfaceColorType,GrColorType dstColorType,void * offsetOrPtr,int rowWidthInPixels)2361*c8dee2aaSAndroid Build Coastguard Worker bool GrGLGpu::readOrTransferPixelsFrom(GrSurface* surface,
2362*c8dee2aaSAndroid Build Coastguard Worker                                        SkIRect rect,
2363*c8dee2aaSAndroid Build Coastguard Worker                                        GrColorType surfaceColorType,
2364*c8dee2aaSAndroid Build Coastguard Worker                                        GrColorType dstColorType,
2365*c8dee2aaSAndroid Build Coastguard Worker                                        void* offsetOrPtr,
2366*c8dee2aaSAndroid Build Coastguard Worker                                        int rowWidthInPixels) {
2367*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(surface);
2368*c8dee2aaSAndroid Build Coastguard Worker 
2369*c8dee2aaSAndroid Build Coastguard Worker     auto format = GrBackendFormats::AsGLFormat(surface->backendFormat());
2370*c8dee2aaSAndroid Build Coastguard Worker     GrGLRenderTarget* renderTarget = static_cast<GrGLRenderTarget*>(surface->asRenderTarget());
2371*c8dee2aaSAndroid Build Coastguard Worker     if (!renderTarget && !this->glCaps().isFormatRenderable(format, 1)) {
2372*c8dee2aaSAndroid Build Coastguard Worker         return false;
2373*c8dee2aaSAndroid Build Coastguard Worker     }
2374*c8dee2aaSAndroid Build Coastguard Worker     GrGLenum externalFormat = 0;
2375*c8dee2aaSAndroid Build Coastguard Worker     GrGLenum externalType = 0;
2376*c8dee2aaSAndroid Build Coastguard Worker     this->glCaps().getReadPixelsFormat(
2377*c8dee2aaSAndroid Build Coastguard Worker             format, surfaceColorType, dstColorType, &externalFormat, &externalType);
2378*c8dee2aaSAndroid Build Coastguard Worker     if (!externalFormat || !externalType) {
2379*c8dee2aaSAndroid Build Coastguard Worker         return false;
2380*c8dee2aaSAndroid Build Coastguard Worker     }
2381*c8dee2aaSAndroid Build Coastguard Worker 
2382*c8dee2aaSAndroid Build Coastguard Worker     if (renderTarget) {
2383*c8dee2aaSAndroid Build Coastguard Worker         // Always bind the single sample FBO since we can't read pixels from an MSAA framebuffer.
2384*c8dee2aaSAndroid Build Coastguard Worker         constexpr bool useMultisampleFBO = false;
2385*c8dee2aaSAndroid Build Coastguard Worker         if (renderTarget->numSamples() > 1 && renderTarget->isFBO0(useMultisampleFBO)) {
2386*c8dee2aaSAndroid Build Coastguard Worker             return false;
2387*c8dee2aaSAndroid Build Coastguard Worker         }
2388*c8dee2aaSAndroid Build Coastguard Worker         this->flushRenderTarget(renderTarget, useMultisampleFBO);
2389*c8dee2aaSAndroid Build Coastguard Worker     } else {
2390*c8dee2aaSAndroid Build Coastguard Worker         // Use a temporary FBO.
2391*c8dee2aaSAndroid Build Coastguard Worker         this->bindSurfaceFBOForPixelOps(surface, 0, GR_GL_FRAMEBUFFER, kSrc_TempFBOTarget);
2392*c8dee2aaSAndroid Build Coastguard Worker         fHWBoundRenderTargetUniqueID.makeInvalid();
2393*c8dee2aaSAndroid Build Coastguard Worker     }
2394*c8dee2aaSAndroid Build Coastguard Worker 
2395*c8dee2aaSAndroid Build Coastguard Worker     // determine if GL can read using the passed rowBytes or if we need a scratch buffer.
2396*c8dee2aaSAndroid Build Coastguard Worker     if (rowWidthInPixels != rect.width()) {
2397*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(this->glCaps().readPixelsRowBytesSupport());
2398*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(PixelStorei(GR_GL_PACK_ROW_LENGTH, rowWidthInPixels));
2399*c8dee2aaSAndroid Build Coastguard Worker     }
2400*c8dee2aaSAndroid Build Coastguard Worker     GL_CALL(PixelStorei(GR_GL_PACK_ALIGNMENT, 1));
2401*c8dee2aaSAndroid Build Coastguard Worker 
2402*c8dee2aaSAndroid Build Coastguard Worker     GL_CALL(ReadPixels(rect.left(),
2403*c8dee2aaSAndroid Build Coastguard Worker                        rect.top(),
2404*c8dee2aaSAndroid Build Coastguard Worker                        rect.width(),
2405*c8dee2aaSAndroid Build Coastguard Worker                        rect.height(),
2406*c8dee2aaSAndroid Build Coastguard Worker                        externalFormat,
2407*c8dee2aaSAndroid Build Coastguard Worker                        externalType,
2408*c8dee2aaSAndroid Build Coastguard Worker                        offsetOrPtr));
2409*c8dee2aaSAndroid Build Coastguard Worker 
2410*c8dee2aaSAndroid Build Coastguard Worker     if (rowWidthInPixels != rect.width()) {
2411*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(this->glCaps().readPixelsRowBytesSupport());
2412*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(PixelStorei(GR_GL_PACK_ROW_LENGTH, 0));
2413*c8dee2aaSAndroid Build Coastguard Worker     }
2414*c8dee2aaSAndroid Build Coastguard Worker 
2415*c8dee2aaSAndroid Build Coastguard Worker     if (!renderTarget) {
2416*c8dee2aaSAndroid Build Coastguard Worker         this->unbindSurfaceFBOForPixelOps(surface, 0, GR_GL_FRAMEBUFFER);
2417*c8dee2aaSAndroid Build Coastguard Worker     }
2418*c8dee2aaSAndroid Build Coastguard Worker     return true;
2419*c8dee2aaSAndroid Build Coastguard Worker }
2420*c8dee2aaSAndroid Build Coastguard Worker 
onReadPixels(GrSurface * surface,SkIRect rect,GrColorType surfaceColorType,GrColorType dstColorType,void * buffer,size_t rowBytes)2421*c8dee2aaSAndroid Build Coastguard Worker bool GrGLGpu::onReadPixels(GrSurface* surface,
2422*c8dee2aaSAndroid Build Coastguard Worker                            SkIRect rect,
2423*c8dee2aaSAndroid Build Coastguard Worker                            GrColorType surfaceColorType,
2424*c8dee2aaSAndroid Build Coastguard Worker                            GrColorType dstColorType,
2425*c8dee2aaSAndroid Build Coastguard Worker                            void* buffer,
2426*c8dee2aaSAndroid Build Coastguard Worker                            size_t rowBytes) {
2427*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(surface);
2428*c8dee2aaSAndroid Build Coastguard Worker 
2429*c8dee2aaSAndroid Build Coastguard Worker     size_t bytesPerPixel = GrColorTypeBytesPerPixel(dstColorType);
2430*c8dee2aaSAndroid Build Coastguard Worker 
2431*c8dee2aaSAndroid Build Coastguard Worker     // GL_PACK_ROW_LENGTH is in terms of pixels not bytes.
2432*c8dee2aaSAndroid Build Coastguard Worker     int rowPixelWidth;
2433*c8dee2aaSAndroid Build Coastguard Worker 
2434*c8dee2aaSAndroid Build Coastguard Worker     if (rowBytes == SkToSizeT(rect.width()*bytesPerPixel)) {
2435*c8dee2aaSAndroid Build Coastguard Worker         rowPixelWidth = rect.width();
2436*c8dee2aaSAndroid Build Coastguard Worker     } else {
2437*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(!(rowBytes % bytesPerPixel));
2438*c8dee2aaSAndroid Build Coastguard Worker         rowPixelWidth = rowBytes / bytesPerPixel;
2439*c8dee2aaSAndroid Build Coastguard Worker     }
2440*c8dee2aaSAndroid Build Coastguard Worker     this->unbindXferBuffer(GrGpuBufferType::kXferGpuToCpu);
2441*c8dee2aaSAndroid Build Coastguard Worker     return this->readOrTransferPixelsFrom(surface,
2442*c8dee2aaSAndroid Build Coastguard Worker                                           rect,
2443*c8dee2aaSAndroid Build Coastguard Worker                                           surfaceColorType,
2444*c8dee2aaSAndroid Build Coastguard Worker                                           dstColorType,
2445*c8dee2aaSAndroid Build Coastguard Worker                                           buffer,
2446*c8dee2aaSAndroid Build Coastguard Worker                                           rowPixelWidth);
2447*c8dee2aaSAndroid Build Coastguard Worker }
2448*c8dee2aaSAndroid Build Coastguard Worker 
onGetOpsRenderPass(GrRenderTarget * rt,bool useMultisampleFBO,GrAttachment *,GrSurfaceOrigin origin,const SkIRect & bounds,const GrOpsRenderPass::LoadAndStoreInfo & colorInfo,const GrOpsRenderPass::StencilLoadAndStoreInfo & stencilInfo,const TArray<GrSurfaceProxy *,true> & sampledProxies,GrXferBarrierFlags renderPassXferBarriers)2449*c8dee2aaSAndroid Build Coastguard Worker GrOpsRenderPass* GrGLGpu::onGetOpsRenderPass(
2450*c8dee2aaSAndroid Build Coastguard Worker         GrRenderTarget* rt,
2451*c8dee2aaSAndroid Build Coastguard Worker         bool useMultisampleFBO,
2452*c8dee2aaSAndroid Build Coastguard Worker         GrAttachment*,
2453*c8dee2aaSAndroid Build Coastguard Worker         GrSurfaceOrigin origin,
2454*c8dee2aaSAndroid Build Coastguard Worker         const SkIRect& bounds,
2455*c8dee2aaSAndroid Build Coastguard Worker         const GrOpsRenderPass::LoadAndStoreInfo& colorInfo,
2456*c8dee2aaSAndroid Build Coastguard Worker         const GrOpsRenderPass::StencilLoadAndStoreInfo& stencilInfo,
2457*c8dee2aaSAndroid Build Coastguard Worker         const TArray<GrSurfaceProxy*, true>& sampledProxies,
2458*c8dee2aaSAndroid Build Coastguard Worker         GrXferBarrierFlags renderPassXferBarriers) {
2459*c8dee2aaSAndroid Build Coastguard Worker     if (!fCachedOpsRenderPass) {
2460*c8dee2aaSAndroid Build Coastguard Worker         fCachedOpsRenderPass = std::make_unique<GrGLOpsRenderPass>(this);
2461*c8dee2aaSAndroid Build Coastguard Worker     }
2462*c8dee2aaSAndroid Build Coastguard Worker     if (useMultisampleFBO && rt->numSamples() == 1) {
2463*c8dee2aaSAndroid Build Coastguard Worker         // We will be using dynamic msaa. Ensure there is an attachment.
2464*c8dee2aaSAndroid Build Coastguard Worker         auto glRT = static_cast<GrGLRenderTarget*>(rt);
2465*c8dee2aaSAndroid Build Coastguard Worker         if (!glRT->ensureDynamicMSAAAttachment()) {
2466*c8dee2aaSAndroid Build Coastguard Worker             SkDebugf("WARNING: Failed to make dmsaa attachment. Render pass will be dropped.");
2467*c8dee2aaSAndroid Build Coastguard Worker             return nullptr;
2468*c8dee2aaSAndroid Build Coastguard Worker         }
2469*c8dee2aaSAndroid Build Coastguard Worker     }
2470*c8dee2aaSAndroid Build Coastguard Worker     fCachedOpsRenderPass->set(rt, useMultisampleFBO, bounds, origin, colorInfo, stencilInfo);
2471*c8dee2aaSAndroid Build Coastguard Worker     return fCachedOpsRenderPass.get();
2472*c8dee2aaSAndroid Build Coastguard Worker }
2473*c8dee2aaSAndroid Build Coastguard Worker 
flushRenderTarget(GrGLRenderTarget * target,bool useMultisampleFBO)2474*c8dee2aaSAndroid Build Coastguard Worker void GrGLGpu::flushRenderTarget(GrGLRenderTarget* target, bool useMultisampleFBO) {
2475*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(target);
2476*c8dee2aaSAndroid Build Coastguard Worker     GrGpuResource::UniqueID rtID = target->uniqueID();
2477*c8dee2aaSAndroid Build Coastguard Worker     if (fHWBoundRenderTargetUniqueID != rtID           ||
2478*c8dee2aaSAndroid Build Coastguard Worker         fHWBoundFramebufferIsMSAA != useMultisampleFBO ||
2479*c8dee2aaSAndroid Build Coastguard Worker         target->mustRebind(useMultisampleFBO)) {
2480*c8dee2aaSAndroid Build Coastguard Worker         target->bind(useMultisampleFBO);
2481*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_DEBUG
2482*c8dee2aaSAndroid Build Coastguard Worker         // don't do this check in Chromium -- this is causing
2483*c8dee2aaSAndroid Build Coastguard Worker         // lots of repeated command buffer flushes when the compositor is
2484*c8dee2aaSAndroid Build Coastguard Worker         // rendering with Ganesh, which is really slow; even too slow for
2485*c8dee2aaSAndroid Build Coastguard Worker         // Debug mode.
2486*c8dee2aaSAndroid Build Coastguard Worker         // Also don't do this when we know glCheckFramebufferStatus() may have side effects.
2487*c8dee2aaSAndroid Build Coastguard Worker         if (!this->glCaps().skipErrorChecks() &&
2488*c8dee2aaSAndroid Build Coastguard Worker             !this->glCaps().rebindColorAttachmentAfterCheckFramebufferStatus()) {
2489*c8dee2aaSAndroid Build Coastguard Worker             GrGLenum status;
2490*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
2491*c8dee2aaSAndroid Build Coastguard Worker             if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
2492*c8dee2aaSAndroid Build Coastguard Worker                 SkDebugf("GrGLGpu::flushRenderTargetNoColorWrites glCheckFramebufferStatus %x\n",
2493*c8dee2aaSAndroid Build Coastguard Worker                          status);
2494*c8dee2aaSAndroid Build Coastguard Worker             }
2495*c8dee2aaSAndroid Build Coastguard Worker         }
2496*c8dee2aaSAndroid Build Coastguard Worker #endif
2497*c8dee2aaSAndroid Build Coastguard Worker         fHWBoundRenderTargetUniqueID = rtID;
2498*c8dee2aaSAndroid Build Coastguard Worker         fHWBoundFramebufferIsMSAA = useMultisampleFBO;
2499*c8dee2aaSAndroid Build Coastguard Worker         this->flushViewport(SkIRect::MakeSize(target->dimensions()),
2500*c8dee2aaSAndroid Build Coastguard Worker                             target->height(),
2501*c8dee2aaSAndroid Build Coastguard Worker                             kTopLeft_GrSurfaceOrigin); // the origin is irrelevant in this case
2502*c8dee2aaSAndroid Build Coastguard Worker     }
2503*c8dee2aaSAndroid Build Coastguard Worker     if (this->caps()->workarounds().force_update_scissor_state_when_binding_fbo0) {
2504*c8dee2aaSAndroid Build Coastguard Worker         // The driver forgets the correct scissor state when using FBO 0.
2505*c8dee2aaSAndroid Build Coastguard Worker         if (!fHWScissorSettings.fRect.isInvalid()) {
2506*c8dee2aaSAndroid Build Coastguard Worker             const GrNativeRect& r = fHWScissorSettings.fRect;
2507*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(Scissor(r.fX, r.fY, r.fWidth, r.fHeight));
2508*c8dee2aaSAndroid Build Coastguard Worker         }
2509*c8dee2aaSAndroid Build Coastguard Worker         if (fHWScissorSettings.fEnabled == kYes_TriState) {
2510*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(Disable(GR_GL_SCISSOR_TEST));
2511*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(Enable(GR_GL_SCISSOR_TEST));
2512*c8dee2aaSAndroid Build Coastguard Worker         } else if (fHWScissorSettings.fEnabled == kNo_TriState) {
2513*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(Enable(GR_GL_SCISSOR_TEST));
2514*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(Disable(GR_GL_SCISSOR_TEST));
2515*c8dee2aaSAndroid Build Coastguard Worker         }
2516*c8dee2aaSAndroid Build Coastguard Worker     }
2517*c8dee2aaSAndroid Build Coastguard Worker 
2518*c8dee2aaSAndroid Build Coastguard Worker     if (this->glCaps().srgbWriteControl()) {
2519*c8dee2aaSAndroid Build Coastguard Worker         this->flushFramebufferSRGB(this->caps()->isFormatSRGB(target->backendFormat()));
2520*c8dee2aaSAndroid Build Coastguard Worker     }
2521*c8dee2aaSAndroid Build Coastguard Worker 
2522*c8dee2aaSAndroid Build Coastguard Worker     if (this->glCaps().shouldQueryImplementationReadSupport(target->format())) {
2523*c8dee2aaSAndroid Build Coastguard Worker         GrGLint format;
2524*c8dee2aaSAndroid Build Coastguard Worker         GrGLint type;
2525*c8dee2aaSAndroid Build Coastguard Worker         GR_GL_GetIntegerv(this->glInterface(), GR_GL_IMPLEMENTATION_COLOR_READ_FORMAT, &format);
2526*c8dee2aaSAndroid Build Coastguard Worker         GR_GL_GetIntegerv(this->glInterface(), GR_GL_IMPLEMENTATION_COLOR_READ_TYPE, &type);
2527*c8dee2aaSAndroid Build Coastguard Worker         this->glCaps().didQueryImplementationReadSupport(target->format(), format, type);
2528*c8dee2aaSAndroid Build Coastguard Worker     }
2529*c8dee2aaSAndroid Build Coastguard Worker }
2530*c8dee2aaSAndroid Build Coastguard Worker 
flushFramebufferSRGB(bool enable)2531*c8dee2aaSAndroid Build Coastguard Worker void GrGLGpu::flushFramebufferSRGB(bool enable) {
2532*c8dee2aaSAndroid Build Coastguard Worker     if (enable && kYes_TriState != fHWSRGBFramebuffer) {
2533*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(Enable(GR_GL_FRAMEBUFFER_SRGB));
2534*c8dee2aaSAndroid Build Coastguard Worker         fHWSRGBFramebuffer = kYes_TriState;
2535*c8dee2aaSAndroid Build Coastguard Worker     } else if (!enable && kNo_TriState != fHWSRGBFramebuffer) {
2536*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(Disable(GR_GL_FRAMEBUFFER_SRGB));
2537*c8dee2aaSAndroid Build Coastguard Worker         fHWSRGBFramebuffer = kNo_TriState;
2538*c8dee2aaSAndroid Build Coastguard Worker     }
2539*c8dee2aaSAndroid Build Coastguard Worker }
2540*c8dee2aaSAndroid Build Coastguard Worker 
prepareToDraw(GrPrimitiveType primitiveType)2541*c8dee2aaSAndroid Build Coastguard Worker GrGLenum GrGLGpu::prepareToDraw(GrPrimitiveType primitiveType) {
2542*c8dee2aaSAndroid Build Coastguard Worker     fStats.incNumDraws();
2543*c8dee2aaSAndroid Build Coastguard Worker 
2544*c8dee2aaSAndroid Build Coastguard Worker     if (this->glCaps().requiresCullFaceEnableDisableWhenDrawingLinesAfterNonLines() &&
2545*c8dee2aaSAndroid Build Coastguard Worker         GrIsPrimTypeLines(primitiveType) && !GrIsPrimTypeLines(fLastPrimitiveType)) {
2546*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(Enable(GR_GL_CULL_FACE));
2547*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(Disable(GR_GL_CULL_FACE));
2548*c8dee2aaSAndroid Build Coastguard Worker     }
2549*c8dee2aaSAndroid Build Coastguard Worker     fLastPrimitiveType = primitiveType;
2550*c8dee2aaSAndroid Build Coastguard Worker 
2551*c8dee2aaSAndroid Build Coastguard Worker     switch (primitiveType) {
2552*c8dee2aaSAndroid Build Coastguard Worker         case GrPrimitiveType::kTriangles:
2553*c8dee2aaSAndroid Build Coastguard Worker             return GR_GL_TRIANGLES;
2554*c8dee2aaSAndroid Build Coastguard Worker         case GrPrimitiveType::kTriangleStrip:
2555*c8dee2aaSAndroid Build Coastguard Worker             return GR_GL_TRIANGLE_STRIP;
2556*c8dee2aaSAndroid Build Coastguard Worker         case GrPrimitiveType::kPoints:
2557*c8dee2aaSAndroid Build Coastguard Worker             return GR_GL_POINTS;
2558*c8dee2aaSAndroid Build Coastguard Worker         case GrPrimitiveType::kLines:
2559*c8dee2aaSAndroid Build Coastguard Worker             return GR_GL_LINES;
2560*c8dee2aaSAndroid Build Coastguard Worker         case GrPrimitiveType::kLineStrip:
2561*c8dee2aaSAndroid Build Coastguard Worker             return GR_GL_LINE_STRIP;
2562*c8dee2aaSAndroid Build Coastguard Worker     }
2563*c8dee2aaSAndroid Build Coastguard Worker     SK_ABORT("invalid GrPrimitiveType");
2564*c8dee2aaSAndroid Build Coastguard Worker }
2565*c8dee2aaSAndroid Build Coastguard Worker 
onResolveRenderTarget(GrRenderTarget * target,const SkIRect & resolveRect)2566*c8dee2aaSAndroid Build Coastguard Worker void GrGLGpu::onResolveRenderTarget(GrRenderTarget* target, const SkIRect& resolveRect) {
2567*c8dee2aaSAndroid Build Coastguard Worker     auto glRT = static_cast<GrGLRenderTarget*>(target);
2568*c8dee2aaSAndroid Build Coastguard Worker     if (this->glCaps().framebufferResolvesMustBeFullSize()) {
2569*c8dee2aaSAndroid Build Coastguard Worker         this->resolveRenderFBOs(glRT, SkIRect::MakeSize(glRT->dimensions()),
2570*c8dee2aaSAndroid Build Coastguard Worker                                 ResolveDirection::kMSAAToSingle);
2571*c8dee2aaSAndroid Build Coastguard Worker     } else {
2572*c8dee2aaSAndroid Build Coastguard Worker         this->resolveRenderFBOs(glRT, resolveRect, ResolveDirection::kMSAAToSingle);
2573*c8dee2aaSAndroid Build Coastguard Worker     }
2574*c8dee2aaSAndroid Build Coastguard Worker }
2575*c8dee2aaSAndroid Build Coastguard Worker 
resolveRenderFBOs(GrGLRenderTarget * rt,const SkIRect & resolveRect,ResolveDirection resolveDirection,bool invalidateReadBufferAfterBlit)2576*c8dee2aaSAndroid Build Coastguard Worker void GrGLGpu::resolveRenderFBOs(GrGLRenderTarget* rt, const SkIRect& resolveRect,
2577*c8dee2aaSAndroid Build Coastguard Worker                                 ResolveDirection resolveDirection,
2578*c8dee2aaSAndroid Build Coastguard Worker                                 bool invalidateReadBufferAfterBlit) {
2579*c8dee2aaSAndroid Build Coastguard Worker     this->handleDirtyContext();
2580*c8dee2aaSAndroid Build Coastguard Worker     rt->bindForResolve(resolveDirection);
2581*c8dee2aaSAndroid Build Coastguard Worker 
2582*c8dee2aaSAndroid Build Coastguard Worker     const GrGLCaps& caps = this->glCaps();
2583*c8dee2aaSAndroid Build Coastguard Worker 
2584*c8dee2aaSAndroid Build Coastguard Worker     // make sure we go through flushRenderTarget() since we've modified
2585*c8dee2aaSAndroid Build Coastguard Worker     // the bound DRAW FBO ID.
2586*c8dee2aaSAndroid Build Coastguard Worker     fHWBoundRenderTargetUniqueID.makeInvalid();
2587*c8dee2aaSAndroid Build Coastguard Worker     if (GrGLCaps::kES_Apple_MSFBOType == caps.msFBOType()) {
2588*c8dee2aaSAndroid Build Coastguard Worker         // The Apple extension doesn't support blitting from single to multisample.
2589*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(resolveDirection != ResolveDirection::kSingleToMSAA);
2590*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(resolveRect == SkIRect::MakeSize(rt->dimensions()));
2591*c8dee2aaSAndroid Build Coastguard Worker         // Apple's extension uses the scissor as the blit bounds.
2592*c8dee2aaSAndroid Build Coastguard Worker         // Passing in kTopLeft_GrSurfaceOrigin will make sure no transformation of the rect
2593*c8dee2aaSAndroid Build Coastguard Worker         // happens inside flushScissor since resolveRect is already in native device coordinates.
2594*c8dee2aaSAndroid Build Coastguard Worker         GrScissorState scissor(rt->dimensions());
2595*c8dee2aaSAndroid Build Coastguard Worker         SkAssertResult(scissor.set(resolveRect));
2596*c8dee2aaSAndroid Build Coastguard Worker         this->flushScissor(scissor, rt->height(), kTopLeft_GrSurfaceOrigin);
2597*c8dee2aaSAndroid Build Coastguard Worker         this->disableWindowRectangles();
2598*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(ResolveMultisampleFramebuffer());
2599*c8dee2aaSAndroid Build Coastguard Worker     } else {
2600*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(!caps.framebufferResolvesMustBeFullSize() ||
2601*c8dee2aaSAndroid Build Coastguard Worker                  resolveRect == SkIRect::MakeSize(rt->dimensions()));
2602*c8dee2aaSAndroid Build Coastguard Worker         int l = resolveRect.x();
2603*c8dee2aaSAndroid Build Coastguard Worker         int b = resolveRect.y();
2604*c8dee2aaSAndroid Build Coastguard Worker         int r = resolveRect.x() + resolveRect.width();
2605*c8dee2aaSAndroid Build Coastguard Worker         int t = resolveRect.y() + resolveRect.height();
2606*c8dee2aaSAndroid Build Coastguard Worker 
2607*c8dee2aaSAndroid Build Coastguard Worker         // BlitFrameBuffer respects the scissor, so disable it.
2608*c8dee2aaSAndroid Build Coastguard Worker         this->flushScissorTest(GrScissorTest::kDisabled);
2609*c8dee2aaSAndroid Build Coastguard Worker         this->disableWindowRectangles();
2610*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(BlitFramebuffer(l, b, r, t, l, b, r, t, GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST));
2611*c8dee2aaSAndroid Build Coastguard Worker     }
2612*c8dee2aaSAndroid Build Coastguard Worker 
2613*c8dee2aaSAndroid Build Coastguard Worker     if (caps.invalidateFBType() != GrGLCaps::kNone_InvalidateFBType &&
2614*c8dee2aaSAndroid Build Coastguard Worker         invalidateReadBufferAfterBlit) {
2615*c8dee2aaSAndroid Build Coastguard Worker         // Invalidate the read FBO attachment after the blit, in hopes that this allows the driver
2616*c8dee2aaSAndroid Build Coastguard Worker         // to perform tiling optimizations.
2617*c8dee2aaSAndroid Build Coastguard Worker         bool readBufferIsMSAA = resolveDirection == ResolveDirection::kMSAAToSingle;
2618*c8dee2aaSAndroid Build Coastguard Worker         GrGLenum colorDiscardAttachment = rt->isFBO0(readBufferIsMSAA) ? GR_GL_COLOR
2619*c8dee2aaSAndroid Build Coastguard Worker                                                                        : GR_GL_COLOR_ATTACHMENT0;
2620*c8dee2aaSAndroid Build Coastguard Worker         if (caps.invalidateFBType() == GrGLCaps::kInvalidate_InvalidateFBType) {
2621*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(InvalidateFramebuffer(GR_GL_READ_FRAMEBUFFER, 1, &colorDiscardAttachment));
2622*c8dee2aaSAndroid Build Coastguard Worker         } else {
2623*c8dee2aaSAndroid Build Coastguard Worker             SkASSERT(caps.invalidateFBType() == GrGLCaps::kDiscard_InvalidateFBType);
2624*c8dee2aaSAndroid Build Coastguard Worker             // glDiscardFramebuffer only accepts GL_FRAMEBUFFER.
2625*c8dee2aaSAndroid Build Coastguard Worker             rt->bind(readBufferIsMSAA);
2626*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(DiscardFramebuffer(GR_GL_FRAMEBUFFER, 1, &colorDiscardAttachment));
2627*c8dee2aaSAndroid Build Coastguard Worker         }
2628*c8dee2aaSAndroid Build Coastguard Worker     }
2629*c8dee2aaSAndroid Build Coastguard Worker }
2630*c8dee2aaSAndroid Build Coastguard Worker 
2631*c8dee2aaSAndroid Build Coastguard Worker namespace {
2632*c8dee2aaSAndroid Build Coastguard Worker 
2633*c8dee2aaSAndroid Build Coastguard Worker 
gr_to_gl_stencil_op(GrStencilOp op)2634*c8dee2aaSAndroid Build Coastguard Worker GrGLenum gr_to_gl_stencil_op(GrStencilOp op) {
2635*c8dee2aaSAndroid Build Coastguard Worker     static const GrGLenum gTable[kGrStencilOpCount] = {
2636*c8dee2aaSAndroid Build Coastguard Worker         GR_GL_KEEP,        // kKeep
2637*c8dee2aaSAndroid Build Coastguard Worker         GR_GL_ZERO,        // kZero
2638*c8dee2aaSAndroid Build Coastguard Worker         GR_GL_REPLACE,     // kReplace
2639*c8dee2aaSAndroid Build Coastguard Worker         GR_GL_INVERT,      // kInvert
2640*c8dee2aaSAndroid Build Coastguard Worker         GR_GL_INCR_WRAP,   // kIncWrap
2641*c8dee2aaSAndroid Build Coastguard Worker         GR_GL_DECR_WRAP,   // kDecWrap
2642*c8dee2aaSAndroid Build Coastguard Worker         GR_GL_INCR,        // kIncClamp
2643*c8dee2aaSAndroid Build Coastguard Worker         GR_GL_DECR,        // kDecClamp
2644*c8dee2aaSAndroid Build Coastguard Worker     };
2645*c8dee2aaSAndroid Build Coastguard Worker     static_assert(0 == (int)GrStencilOp::kKeep);
2646*c8dee2aaSAndroid Build Coastguard Worker     static_assert(1 == (int)GrStencilOp::kZero);
2647*c8dee2aaSAndroid Build Coastguard Worker     static_assert(2 == (int)GrStencilOp::kReplace);
2648*c8dee2aaSAndroid Build Coastguard Worker     static_assert(3 == (int)GrStencilOp::kInvert);
2649*c8dee2aaSAndroid Build Coastguard Worker     static_assert(4 == (int)GrStencilOp::kIncWrap);
2650*c8dee2aaSAndroid Build Coastguard Worker     static_assert(5 == (int)GrStencilOp::kDecWrap);
2651*c8dee2aaSAndroid Build Coastguard Worker     static_assert(6 == (int)GrStencilOp::kIncClamp);
2652*c8dee2aaSAndroid Build Coastguard Worker     static_assert(7 == (int)GrStencilOp::kDecClamp);
2653*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(op < (GrStencilOp)kGrStencilOpCount);
2654*c8dee2aaSAndroid Build Coastguard Worker     return gTable[(int)op];
2655*c8dee2aaSAndroid Build Coastguard Worker }
2656*c8dee2aaSAndroid Build Coastguard Worker 
set_gl_stencil(const GrGLInterface * gl,const GrStencilSettings::Face & face,GrGLenum glFace)2657*c8dee2aaSAndroid Build Coastguard Worker void set_gl_stencil(const GrGLInterface* gl,
2658*c8dee2aaSAndroid Build Coastguard Worker                     const GrStencilSettings::Face& face,
2659*c8dee2aaSAndroid Build Coastguard Worker                     GrGLenum glFace) {
2660*c8dee2aaSAndroid Build Coastguard Worker     GrGLenum glFunc = GrToGLStencilFunc(face.fTest);
2661*c8dee2aaSAndroid Build Coastguard Worker     GrGLenum glFailOp = gr_to_gl_stencil_op(face.fFailOp);
2662*c8dee2aaSAndroid Build Coastguard Worker     GrGLenum glPassOp = gr_to_gl_stencil_op(face.fPassOp);
2663*c8dee2aaSAndroid Build Coastguard Worker 
2664*c8dee2aaSAndroid Build Coastguard Worker     GrGLint ref = face.fRef;
2665*c8dee2aaSAndroid Build Coastguard Worker     GrGLint mask = face.fTestMask;
2666*c8dee2aaSAndroid Build Coastguard Worker     GrGLint writeMask = face.fWriteMask;
2667*c8dee2aaSAndroid Build Coastguard Worker 
2668*c8dee2aaSAndroid Build Coastguard Worker     if (GR_GL_FRONT_AND_BACK == glFace) {
2669*c8dee2aaSAndroid Build Coastguard Worker         // we call the combined func just in case separate stencil is not
2670*c8dee2aaSAndroid Build Coastguard Worker         // supported.
2671*c8dee2aaSAndroid Build Coastguard Worker         GR_GL_CALL(gl, StencilFunc(glFunc, ref, mask));
2672*c8dee2aaSAndroid Build Coastguard Worker         GR_GL_CALL(gl, StencilMask(writeMask));
2673*c8dee2aaSAndroid Build Coastguard Worker         GR_GL_CALL(gl, StencilOp(glFailOp, GR_GL_KEEP, glPassOp));
2674*c8dee2aaSAndroid Build Coastguard Worker     } else {
2675*c8dee2aaSAndroid Build Coastguard Worker         GR_GL_CALL(gl, StencilFuncSeparate(glFace, glFunc, ref, mask));
2676*c8dee2aaSAndroid Build Coastguard Worker         GR_GL_CALL(gl, StencilMaskSeparate(glFace, writeMask));
2677*c8dee2aaSAndroid Build Coastguard Worker         GR_GL_CALL(gl, StencilOpSeparate(glFace, glFailOp, GR_GL_KEEP, glPassOp));
2678*c8dee2aaSAndroid Build Coastguard Worker     }
2679*c8dee2aaSAndroid Build Coastguard Worker }
2680*c8dee2aaSAndroid Build Coastguard Worker }  // namespace
2681*c8dee2aaSAndroid Build Coastguard Worker 
flushStencil(const GrStencilSettings & stencilSettings,GrSurfaceOrigin origin)2682*c8dee2aaSAndroid Build Coastguard Worker void GrGLGpu::flushStencil(const GrStencilSettings& stencilSettings, GrSurfaceOrigin origin) {
2683*c8dee2aaSAndroid Build Coastguard Worker     if (stencilSettings.isDisabled()) {
2684*c8dee2aaSAndroid Build Coastguard Worker         this->disableStencil();
2685*c8dee2aaSAndroid Build Coastguard Worker     } else if (fHWStencilSettings != stencilSettings ||
2686*c8dee2aaSAndroid Build Coastguard Worker                (stencilSettings.isTwoSided() && fHWStencilOrigin != origin)) {
2687*c8dee2aaSAndroid Build Coastguard Worker         if (kYes_TriState != fHWStencilTestEnabled) {
2688*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(Enable(GR_GL_STENCIL_TEST));
2689*c8dee2aaSAndroid Build Coastguard Worker 
2690*c8dee2aaSAndroid Build Coastguard Worker             fHWStencilTestEnabled = kYes_TriState;
2691*c8dee2aaSAndroid Build Coastguard Worker         }
2692*c8dee2aaSAndroid Build Coastguard Worker         if (!stencilSettings.isTwoSided()) {
2693*c8dee2aaSAndroid Build Coastguard Worker             set_gl_stencil(this->glInterface(), stencilSettings.singleSidedFace(),
2694*c8dee2aaSAndroid Build Coastguard Worker                            GR_GL_FRONT_AND_BACK);
2695*c8dee2aaSAndroid Build Coastguard Worker         } else {
2696*c8dee2aaSAndroid Build Coastguard Worker             set_gl_stencil(this->glInterface(), stencilSettings.postOriginCWFace(origin),
2697*c8dee2aaSAndroid Build Coastguard Worker                            GR_GL_FRONT);
2698*c8dee2aaSAndroid Build Coastguard Worker             set_gl_stencil(this->glInterface(), stencilSettings.postOriginCCWFace(origin),
2699*c8dee2aaSAndroid Build Coastguard Worker                            GR_GL_BACK);
2700*c8dee2aaSAndroid Build Coastguard Worker         }
2701*c8dee2aaSAndroid Build Coastguard Worker         fHWStencilSettings = stencilSettings;
2702*c8dee2aaSAndroid Build Coastguard Worker         fHWStencilOrigin = origin;
2703*c8dee2aaSAndroid Build Coastguard Worker     }
2704*c8dee2aaSAndroid Build Coastguard Worker }
2705*c8dee2aaSAndroid Build Coastguard Worker 
disableStencil()2706*c8dee2aaSAndroid Build Coastguard Worker void GrGLGpu::disableStencil() {
2707*c8dee2aaSAndroid Build Coastguard Worker     if (kNo_TriState != fHWStencilTestEnabled) {
2708*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(Disable(GR_GL_STENCIL_TEST));
2709*c8dee2aaSAndroid Build Coastguard Worker 
2710*c8dee2aaSAndroid Build Coastguard Worker         fHWStencilTestEnabled = kNo_TriState;
2711*c8dee2aaSAndroid Build Coastguard Worker         fHWStencilSettings.invalidate();
2712*c8dee2aaSAndroid Build Coastguard Worker     }
2713*c8dee2aaSAndroid Build Coastguard Worker }
2714*c8dee2aaSAndroid Build Coastguard Worker 
flushConservativeRasterState(bool enabled)2715*c8dee2aaSAndroid Build Coastguard Worker void GrGLGpu::flushConservativeRasterState(bool enabled) {
2716*c8dee2aaSAndroid Build Coastguard Worker     if (this->caps()->conservativeRasterSupport()) {
2717*c8dee2aaSAndroid Build Coastguard Worker         if (enabled) {
2718*c8dee2aaSAndroid Build Coastguard Worker             if (kYes_TriState != fHWConservativeRasterEnabled) {
2719*c8dee2aaSAndroid Build Coastguard Worker                 GL_CALL(Enable(GR_GL_CONSERVATIVE_RASTERIZATION));
2720*c8dee2aaSAndroid Build Coastguard Worker                 fHWConservativeRasterEnabled = kYes_TriState;
2721*c8dee2aaSAndroid Build Coastguard Worker             }
2722*c8dee2aaSAndroid Build Coastguard Worker         } else {
2723*c8dee2aaSAndroid Build Coastguard Worker             if (kNo_TriState != fHWConservativeRasterEnabled) {
2724*c8dee2aaSAndroid Build Coastguard Worker                 GL_CALL(Disable(GR_GL_CONSERVATIVE_RASTERIZATION));
2725*c8dee2aaSAndroid Build Coastguard Worker                 fHWConservativeRasterEnabled = kNo_TriState;
2726*c8dee2aaSAndroid Build Coastguard Worker             }
2727*c8dee2aaSAndroid Build Coastguard Worker         }
2728*c8dee2aaSAndroid Build Coastguard Worker     }
2729*c8dee2aaSAndroid Build Coastguard Worker }
2730*c8dee2aaSAndroid Build Coastguard Worker 
flushWireframeState(bool enabled)2731*c8dee2aaSAndroid Build Coastguard Worker void GrGLGpu::flushWireframeState(bool enabled) {
2732*c8dee2aaSAndroid Build Coastguard Worker     if (this->caps()->wireframeSupport()) {
2733*c8dee2aaSAndroid Build Coastguard Worker         if (this->caps()->wireframeMode() || enabled) {
2734*c8dee2aaSAndroid Build Coastguard Worker             if (kYes_TriState != fHWWireframeEnabled) {
2735*c8dee2aaSAndroid Build Coastguard Worker                 GL_CALL(PolygonMode(GR_GL_FRONT_AND_BACK, GR_GL_LINE));
2736*c8dee2aaSAndroid Build Coastguard Worker                 fHWWireframeEnabled = kYes_TriState;
2737*c8dee2aaSAndroid Build Coastguard Worker             }
2738*c8dee2aaSAndroid Build Coastguard Worker         } else {
2739*c8dee2aaSAndroid Build Coastguard Worker             if (kNo_TriState != fHWWireframeEnabled) {
2740*c8dee2aaSAndroid Build Coastguard Worker                 GL_CALL(PolygonMode(GR_GL_FRONT_AND_BACK, GR_GL_FILL));
2741*c8dee2aaSAndroid Build Coastguard Worker                 fHWWireframeEnabled = kNo_TriState;
2742*c8dee2aaSAndroid Build Coastguard Worker             }
2743*c8dee2aaSAndroid Build Coastguard Worker         }
2744*c8dee2aaSAndroid Build Coastguard Worker     }
2745*c8dee2aaSAndroid Build Coastguard Worker }
2746*c8dee2aaSAndroid Build Coastguard Worker 
flushBlendAndColorWrite(const skgpu::BlendInfo & blendInfo,const skgpu::Swizzle & swizzle)2747*c8dee2aaSAndroid Build Coastguard Worker void GrGLGpu::flushBlendAndColorWrite(const skgpu::BlendInfo& blendInfo,
2748*c8dee2aaSAndroid Build Coastguard Worker                                       const skgpu::Swizzle& swizzle) {
2749*c8dee2aaSAndroid Build Coastguard Worker     if (this->glCaps().neverDisableColorWrites() && !blendInfo.fWritesColor) {
2750*c8dee2aaSAndroid Build Coastguard Worker         // We need to work around a driver bug by using a blend state that preserves the dst color,
2751*c8dee2aaSAndroid Build Coastguard Worker         // rather than disabling color writes.
2752*c8dee2aaSAndroid Build Coastguard Worker         skgpu::BlendInfo preserveDstBlend;
2753*c8dee2aaSAndroid Build Coastguard Worker         preserveDstBlend.fSrcBlend = skgpu::BlendCoeff::kZero;
2754*c8dee2aaSAndroid Build Coastguard Worker         preserveDstBlend.fDstBlend = skgpu::BlendCoeff::kOne;
2755*c8dee2aaSAndroid Build Coastguard Worker         this->flushBlendAndColorWrite(preserveDstBlend, swizzle);
2756*c8dee2aaSAndroid Build Coastguard Worker         return;
2757*c8dee2aaSAndroid Build Coastguard Worker     }
2758*c8dee2aaSAndroid Build Coastguard Worker 
2759*c8dee2aaSAndroid Build Coastguard Worker     skgpu::BlendEquation equation = blendInfo.fEquation;
2760*c8dee2aaSAndroid Build Coastguard Worker     skgpu::BlendCoeff srcCoeff = blendInfo.fSrcBlend;
2761*c8dee2aaSAndroid Build Coastguard Worker     skgpu::BlendCoeff dstCoeff = blendInfo.fDstBlend;
2762*c8dee2aaSAndroid Build Coastguard Worker 
2763*c8dee2aaSAndroid Build Coastguard Worker     // Any optimization to disable blending should have already been applied and
2764*c8dee2aaSAndroid Build Coastguard Worker     // tweaked the equation to "add "or "subtract", and the coeffs to (1, 0).
2765*c8dee2aaSAndroid Build Coastguard Worker     bool blendOff = skgpu::BlendShouldDisable(equation, srcCoeff, dstCoeff) ||
2766*c8dee2aaSAndroid Build Coastguard Worker                     !blendInfo.fWritesColor;
2767*c8dee2aaSAndroid Build Coastguard Worker 
2768*c8dee2aaSAndroid Build Coastguard Worker     if (blendOff) {
2769*c8dee2aaSAndroid Build Coastguard Worker         if (kNo_TriState != fHWBlendState.fEnabled) {
2770*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(Disable(GR_GL_BLEND));
2771*c8dee2aaSAndroid Build Coastguard Worker 
2772*c8dee2aaSAndroid Build Coastguard Worker             // Workaround for the ARM KHR_blend_equation_advanced disable flags issue
2773*c8dee2aaSAndroid Build Coastguard Worker             // https://code.google.com/p/skia/issues/detail?id=3943
2774*c8dee2aaSAndroid Build Coastguard Worker             if (this->ctxInfo().vendor() == GrGLVendor::kARM &&
2775*c8dee2aaSAndroid Build Coastguard Worker                 skgpu::BlendEquationIsAdvanced(fHWBlendState.fEquation)) {
2776*c8dee2aaSAndroid Build Coastguard Worker                 SkASSERT(this->caps()->advancedBlendEquationSupport());
2777*c8dee2aaSAndroid Build Coastguard Worker                 // Set to any basic blending equation.
2778*c8dee2aaSAndroid Build Coastguard Worker                 skgpu::BlendEquation blendEquation = skgpu::BlendEquation::kAdd;
2779*c8dee2aaSAndroid Build Coastguard Worker                 GL_CALL(BlendEquation(gXfermodeEquation2Blend[(int)blendEquation]));
2780*c8dee2aaSAndroid Build Coastguard Worker                 fHWBlendState.fEquation = blendEquation;
2781*c8dee2aaSAndroid Build Coastguard Worker             }
2782*c8dee2aaSAndroid Build Coastguard Worker 
2783*c8dee2aaSAndroid Build Coastguard Worker             // Workaround for Adreno 5xx BlendFunc bug. See crbug.com/1241134.
2784*c8dee2aaSAndroid Build Coastguard Worker             // We must also check to see if the blend coeffs are invalid because the client may have
2785*c8dee2aaSAndroid Build Coastguard Worker             // reset our gl state and thus we will have forgotten if the previous use was a coeff
2786*c8dee2aaSAndroid Build Coastguard Worker             // that referenced src2.
2787*c8dee2aaSAndroid Build Coastguard Worker             if (this->glCaps().mustResetBlendFuncBetweenDualSourceAndDisable() &&
2788*c8dee2aaSAndroid Build Coastguard Worker                 (skgpu::BlendCoeffRefsSrc2(fHWBlendState.fSrcCoeff) ||
2789*c8dee2aaSAndroid Build Coastguard Worker                  skgpu::BlendCoeffRefsSrc2(fHWBlendState.fDstCoeff) ||
2790*c8dee2aaSAndroid Build Coastguard Worker                  fHWBlendState.fSrcCoeff == skgpu::BlendCoeff::kIllegal ||
2791*c8dee2aaSAndroid Build Coastguard Worker                  fHWBlendState.fDstCoeff == skgpu::BlendCoeff::kIllegal)) {
2792*c8dee2aaSAndroid Build Coastguard Worker                 // We just reset the blend func to anything that doesn't reference src2
2793*c8dee2aaSAndroid Build Coastguard Worker                 GL_CALL(BlendFunc(GR_GL_ONE, GR_GL_ZERO));
2794*c8dee2aaSAndroid Build Coastguard Worker                 fHWBlendState.fSrcCoeff = skgpu::BlendCoeff::kOne;
2795*c8dee2aaSAndroid Build Coastguard Worker                 fHWBlendState.fDstCoeff = skgpu::BlendCoeff::kZero;
2796*c8dee2aaSAndroid Build Coastguard Worker             }
2797*c8dee2aaSAndroid Build Coastguard Worker 
2798*c8dee2aaSAndroid Build Coastguard Worker             fHWBlendState.fEnabled = kNo_TriState;
2799*c8dee2aaSAndroid Build Coastguard Worker         }
2800*c8dee2aaSAndroid Build Coastguard Worker     } else {
2801*c8dee2aaSAndroid Build Coastguard Worker         if (kYes_TriState != fHWBlendState.fEnabled) {
2802*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(Enable(GR_GL_BLEND));
2803*c8dee2aaSAndroid Build Coastguard Worker 
2804*c8dee2aaSAndroid Build Coastguard Worker             fHWBlendState.fEnabled = kYes_TriState;
2805*c8dee2aaSAndroid Build Coastguard Worker         }
2806*c8dee2aaSAndroid Build Coastguard Worker 
2807*c8dee2aaSAndroid Build Coastguard Worker         if (fHWBlendState.fEquation != equation) {
2808*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(BlendEquation(gXfermodeEquation2Blend[(int)equation]));
2809*c8dee2aaSAndroid Build Coastguard Worker             fHWBlendState.fEquation = equation;
2810*c8dee2aaSAndroid Build Coastguard Worker         }
2811*c8dee2aaSAndroid Build Coastguard Worker 
2812*c8dee2aaSAndroid Build Coastguard Worker         if (skgpu::BlendEquationIsAdvanced(equation)) {
2813*c8dee2aaSAndroid Build Coastguard Worker             SkASSERT(this->caps()->advancedBlendEquationSupport());
2814*c8dee2aaSAndroid Build Coastguard Worker 
2815*c8dee2aaSAndroid Build Coastguard Worker             this->flushColorWrite(blendInfo.fWritesColor);
2816*c8dee2aaSAndroid Build Coastguard Worker             // Advanced equations have no other blend state.
2817*c8dee2aaSAndroid Build Coastguard Worker             return;
2818*c8dee2aaSAndroid Build Coastguard Worker         }
2819*c8dee2aaSAndroid Build Coastguard Worker 
2820*c8dee2aaSAndroid Build Coastguard Worker         if (fHWBlendState.fSrcCoeff != srcCoeff || fHWBlendState.fDstCoeff != dstCoeff) {
2821*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(BlendFunc(gXfermodeCoeff2Blend[(int)srcCoeff],
2822*c8dee2aaSAndroid Build Coastguard Worker                               gXfermodeCoeff2Blend[(int)dstCoeff]));
2823*c8dee2aaSAndroid Build Coastguard Worker             fHWBlendState.fSrcCoeff = srcCoeff;
2824*c8dee2aaSAndroid Build Coastguard Worker             fHWBlendState.fDstCoeff = dstCoeff;
2825*c8dee2aaSAndroid Build Coastguard Worker         }
2826*c8dee2aaSAndroid Build Coastguard Worker 
2827*c8dee2aaSAndroid Build Coastguard Worker         if (skgpu::BlendCoeffRefsConstant(srcCoeff) || skgpu::BlendCoeffRefsConstant(dstCoeff)) {
2828*c8dee2aaSAndroid Build Coastguard Worker             SkPMColor4f blendConst = swizzle.applyTo(blendInfo.fBlendConstant);
2829*c8dee2aaSAndroid Build Coastguard Worker             if (!fHWBlendState.fConstColorValid || fHWBlendState.fConstColor != blendConst) {
2830*c8dee2aaSAndroid Build Coastguard Worker                 GL_CALL(BlendColor(blendConst.fR, blendConst.fG, blendConst.fB, blendConst.fA));
2831*c8dee2aaSAndroid Build Coastguard Worker                 fHWBlendState.fConstColor = blendConst;
2832*c8dee2aaSAndroid Build Coastguard Worker                 fHWBlendState.fConstColorValid = true;
2833*c8dee2aaSAndroid Build Coastguard Worker             }
2834*c8dee2aaSAndroid Build Coastguard Worker         }
2835*c8dee2aaSAndroid Build Coastguard Worker     }
2836*c8dee2aaSAndroid Build Coastguard Worker 
2837*c8dee2aaSAndroid Build Coastguard Worker     this->flushColorWrite(blendInfo.fWritesColor);
2838*c8dee2aaSAndroid Build Coastguard Worker }
2839*c8dee2aaSAndroid Build Coastguard Worker 
bindTexture(int unitIdx,GrSamplerState samplerState,const skgpu::Swizzle & swizzle,GrGLTexture * texture)2840*c8dee2aaSAndroid Build Coastguard Worker void GrGLGpu::bindTexture(int unitIdx, GrSamplerState samplerState, const skgpu::Swizzle& swizzle,
2841*c8dee2aaSAndroid Build Coastguard Worker                           GrGLTexture* texture) {
2842*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(texture);
2843*c8dee2aaSAndroid Build Coastguard Worker 
2844*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_DEBUG
2845*c8dee2aaSAndroid Build Coastguard Worker     if (!this->caps()->npotTextureTileSupport()) {
2846*c8dee2aaSAndroid Build Coastguard Worker         if (samplerState.isRepeatedX()) {
2847*c8dee2aaSAndroid Build Coastguard Worker             const int w = texture->width();
2848*c8dee2aaSAndroid Build Coastguard Worker             SkASSERT(SkIsPow2(w));
2849*c8dee2aaSAndroid Build Coastguard Worker         }
2850*c8dee2aaSAndroid Build Coastguard Worker         if (samplerState.isRepeatedY()) {
2851*c8dee2aaSAndroid Build Coastguard Worker             const int h = texture->height();
2852*c8dee2aaSAndroid Build Coastguard Worker             SkASSERT(SkIsPow2(h));
2853*c8dee2aaSAndroid Build Coastguard Worker         }
2854*c8dee2aaSAndroid Build Coastguard Worker     }
2855*c8dee2aaSAndroid Build Coastguard Worker #endif
2856*c8dee2aaSAndroid Build Coastguard Worker 
2857*c8dee2aaSAndroid Build Coastguard Worker     GrGpuResource::UniqueID textureID = texture->uniqueID();
2858*c8dee2aaSAndroid Build Coastguard Worker     GrGLenum target = texture->target();
2859*c8dee2aaSAndroid Build Coastguard Worker     if (fHWTextureUnitBindings[unitIdx].boundID(target) != textureID) {
2860*c8dee2aaSAndroid Build Coastguard Worker         this->setTextureUnit(unitIdx);
2861*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(BindTexture(target, texture->textureID()));
2862*c8dee2aaSAndroid Build Coastguard Worker         fHWTextureUnitBindings[unitIdx].setBoundID(target, textureID);
2863*c8dee2aaSAndroid Build Coastguard Worker     }
2864*c8dee2aaSAndroid Build Coastguard Worker 
2865*c8dee2aaSAndroid Build Coastguard Worker     if (samplerState.mipmapped() == skgpu::Mipmapped::kYes) {
2866*c8dee2aaSAndroid Build Coastguard Worker         if (!this->caps()->mipmapSupport() || texture->mipmapped() == skgpu::Mipmapped::kNo) {
2867*c8dee2aaSAndroid Build Coastguard Worker             // We should have caught this already.
2868*c8dee2aaSAndroid Build Coastguard Worker             SkASSERT(!samplerState.isAniso());
2869*c8dee2aaSAndroid Build Coastguard Worker             samplerState = GrSamplerState(samplerState.wrapModeX(),
2870*c8dee2aaSAndroid Build Coastguard Worker                                           samplerState.wrapModeY(),
2871*c8dee2aaSAndroid Build Coastguard Worker                                           samplerState.filter(),
2872*c8dee2aaSAndroid Build Coastguard Worker                                           GrSamplerState::MipmapMode::kNone);
2873*c8dee2aaSAndroid Build Coastguard Worker         } else {
2874*c8dee2aaSAndroid Build Coastguard Worker             SkASSERT(!texture->mipmapsAreDirty());
2875*c8dee2aaSAndroid Build Coastguard Worker         }
2876*c8dee2aaSAndroid Build Coastguard Worker     }
2877*c8dee2aaSAndroid Build Coastguard Worker 
2878*c8dee2aaSAndroid Build Coastguard Worker     auto timestamp = texture->parameters()->resetTimestamp();
2879*c8dee2aaSAndroid Build Coastguard Worker     bool setAll = timestamp < fResetTimestampForTextureParameters;
2880*c8dee2aaSAndroid Build Coastguard Worker     const GrGLTextureParameters::SamplerOverriddenState* samplerStateToRecord = nullptr;
2881*c8dee2aaSAndroid Build Coastguard Worker     GrGLTextureParameters::SamplerOverriddenState newSamplerState;
2882*c8dee2aaSAndroid Build Coastguard Worker     if (this->glCaps().useSamplerObjects()) {
2883*c8dee2aaSAndroid Build Coastguard Worker         fSamplerObjectCache->bindSampler(unitIdx, samplerState);
2884*c8dee2aaSAndroid Build Coastguard Worker         if (this->glCaps().mustSetAnyTexParameterToEnableMipmapping()) {
2885*c8dee2aaSAndroid Build Coastguard Worker             if (samplerState.mipmapped() == skgpu::Mipmapped::kYes) {
2886*c8dee2aaSAndroid Build Coastguard Worker                 GrGLenum minFilter = filter_to_gl_min_filter(samplerState.filter(),
2887*c8dee2aaSAndroid Build Coastguard Worker                                                              samplerState.mipmapMode());
2888*c8dee2aaSAndroid Build Coastguard Worker                 const GrGLTextureParameters::SamplerOverriddenState& oldSamplerState =
2889*c8dee2aaSAndroid Build Coastguard Worker                         texture->parameters()->samplerOverriddenState();
2890*c8dee2aaSAndroid Build Coastguard Worker                 this->setTextureUnit(unitIdx);
2891*c8dee2aaSAndroid Build Coastguard Worker                 GL_CALL(TexParameteri(target, GR_GL_TEXTURE_MIN_FILTER, minFilter));
2892*c8dee2aaSAndroid Build Coastguard Worker                 newSamplerState = oldSamplerState;
2893*c8dee2aaSAndroid Build Coastguard Worker                 newSamplerState.fMinFilter = minFilter;
2894*c8dee2aaSAndroid Build Coastguard Worker                 samplerStateToRecord = &newSamplerState;
2895*c8dee2aaSAndroid Build Coastguard Worker             }
2896*c8dee2aaSAndroid Build Coastguard Worker         }
2897*c8dee2aaSAndroid Build Coastguard Worker     } else {
2898*c8dee2aaSAndroid Build Coastguard Worker         if (fSamplerObjectCache) {
2899*c8dee2aaSAndroid Build Coastguard Worker             fSamplerObjectCache->unbindSampler(unitIdx);
2900*c8dee2aaSAndroid Build Coastguard Worker         }
2901*c8dee2aaSAndroid Build Coastguard Worker         const GrGLTextureParameters::SamplerOverriddenState& oldSamplerState =
2902*c8dee2aaSAndroid Build Coastguard Worker                 texture->parameters()->samplerOverriddenState();
2903*c8dee2aaSAndroid Build Coastguard Worker         samplerStateToRecord = &newSamplerState;
2904*c8dee2aaSAndroid Build Coastguard Worker 
2905*c8dee2aaSAndroid Build Coastguard Worker         newSamplerState.fMinFilter = filter_to_gl_min_filter(samplerState.filter(),
2906*c8dee2aaSAndroid Build Coastguard Worker                                                              samplerState.mipmapMode());
2907*c8dee2aaSAndroid Build Coastguard Worker         newSamplerState.fMagFilter = filter_to_gl_mag_filter(samplerState.filter());
2908*c8dee2aaSAndroid Build Coastguard Worker 
2909*c8dee2aaSAndroid Build Coastguard Worker         newSamplerState.fWrapS = wrap_mode_to_gl_wrap(samplerState.wrapModeX(), this->glCaps());
2910*c8dee2aaSAndroid Build Coastguard Worker         newSamplerState.fWrapT = wrap_mode_to_gl_wrap(samplerState.wrapModeY(), this->glCaps());
2911*c8dee2aaSAndroid Build Coastguard Worker 
2912*c8dee2aaSAndroid Build Coastguard Worker         newSamplerState.fMaxAniso = std::min(static_cast<GrGLfloat>(samplerState.maxAniso()),
2913*c8dee2aaSAndroid Build Coastguard Worker                                              this->glCaps().maxTextureMaxAnisotropy());
2914*c8dee2aaSAndroid Build Coastguard Worker 
2915*c8dee2aaSAndroid Build Coastguard Worker         // These are the OpenGL default values.
2916*c8dee2aaSAndroid Build Coastguard Worker         newSamplerState.fMinLOD = -1000.f;
2917*c8dee2aaSAndroid Build Coastguard Worker         newSamplerState.fMaxLOD = 1000.f;
2918*c8dee2aaSAndroid Build Coastguard Worker 
2919*c8dee2aaSAndroid Build Coastguard Worker         if (setAll || newSamplerState.fMagFilter != oldSamplerState.fMagFilter) {
2920*c8dee2aaSAndroid Build Coastguard Worker             this->setTextureUnit(unitIdx);
2921*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(TexParameteri(target, GR_GL_TEXTURE_MAG_FILTER, newSamplerState.fMagFilter));
2922*c8dee2aaSAndroid Build Coastguard Worker         }
2923*c8dee2aaSAndroid Build Coastguard Worker         if (setAll || newSamplerState.fMinFilter != oldSamplerState.fMinFilter) {
2924*c8dee2aaSAndroid Build Coastguard Worker             this->setTextureUnit(unitIdx);
2925*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(TexParameteri(target, GR_GL_TEXTURE_MIN_FILTER, newSamplerState.fMinFilter));
2926*c8dee2aaSAndroid Build Coastguard Worker         }
2927*c8dee2aaSAndroid Build Coastguard Worker         if (this->glCaps().mipmapLodControlSupport()) {
2928*c8dee2aaSAndroid Build Coastguard Worker             if (setAll || newSamplerState.fMinLOD != oldSamplerState.fMinLOD) {
2929*c8dee2aaSAndroid Build Coastguard Worker                 this->setTextureUnit(unitIdx);
2930*c8dee2aaSAndroid Build Coastguard Worker                 GL_CALL(TexParameterf(target, GR_GL_TEXTURE_MIN_LOD, newSamplerState.fMinLOD));
2931*c8dee2aaSAndroid Build Coastguard Worker             }
2932*c8dee2aaSAndroid Build Coastguard Worker             if (setAll || newSamplerState.fMaxLOD != oldSamplerState.fMaxLOD) {
2933*c8dee2aaSAndroid Build Coastguard Worker                 this->setTextureUnit(unitIdx);
2934*c8dee2aaSAndroid Build Coastguard Worker                 GL_CALL(TexParameterf(target, GR_GL_TEXTURE_MAX_LOD, newSamplerState.fMaxLOD));
2935*c8dee2aaSAndroid Build Coastguard Worker             }
2936*c8dee2aaSAndroid Build Coastguard Worker         }
2937*c8dee2aaSAndroid Build Coastguard Worker         if (setAll || newSamplerState.fWrapS != oldSamplerState.fWrapS) {
2938*c8dee2aaSAndroid Build Coastguard Worker             this->setTextureUnit(unitIdx);
2939*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(TexParameteri(target, GR_GL_TEXTURE_WRAP_S, newSamplerState.fWrapS));
2940*c8dee2aaSAndroid Build Coastguard Worker         }
2941*c8dee2aaSAndroid Build Coastguard Worker         if (setAll || newSamplerState.fWrapT != oldSamplerState.fWrapT) {
2942*c8dee2aaSAndroid Build Coastguard Worker             this->setTextureUnit(unitIdx);
2943*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(TexParameteri(target, GR_GL_TEXTURE_WRAP_T, newSamplerState.fWrapT));
2944*c8dee2aaSAndroid Build Coastguard Worker         }
2945*c8dee2aaSAndroid Build Coastguard Worker         if (this->glCaps().clampToBorderSupport()) {
2946*c8dee2aaSAndroid Build Coastguard Worker             // Make sure the border color is transparent black (the default)
2947*c8dee2aaSAndroid Build Coastguard Worker             if (setAll || oldSamplerState.fBorderColorInvalid) {
2948*c8dee2aaSAndroid Build Coastguard Worker                 this->setTextureUnit(unitIdx);
2949*c8dee2aaSAndroid Build Coastguard Worker                 static const GrGLfloat kTransparentBlack[4] = {0.f, 0.f, 0.f, 0.f};
2950*c8dee2aaSAndroid Build Coastguard Worker                 GL_CALL(TexParameterfv(target, GR_GL_TEXTURE_BORDER_COLOR, kTransparentBlack));
2951*c8dee2aaSAndroid Build Coastguard Worker             }
2952*c8dee2aaSAndroid Build Coastguard Worker         }
2953*c8dee2aaSAndroid Build Coastguard Worker         if (this->caps()->anisoSupport()) {
2954*c8dee2aaSAndroid Build Coastguard Worker             if (setAll || oldSamplerState.fMaxAniso != newSamplerState.fMaxAniso) {
2955*c8dee2aaSAndroid Build Coastguard Worker                 GL_CALL(TexParameterf(target,
2956*c8dee2aaSAndroid Build Coastguard Worker                                       GR_GL_TEXTURE_MAX_ANISOTROPY,
2957*c8dee2aaSAndroid Build Coastguard Worker                                       newSamplerState.fMaxAniso));
2958*c8dee2aaSAndroid Build Coastguard Worker             }
2959*c8dee2aaSAndroid Build Coastguard Worker         }
2960*c8dee2aaSAndroid Build Coastguard Worker     }
2961*c8dee2aaSAndroid Build Coastguard Worker     GrGLTextureParameters::NonsamplerState newNonsamplerState;
2962*c8dee2aaSAndroid Build Coastguard Worker     newNonsamplerState.fBaseMipMapLevel = 0;
2963*c8dee2aaSAndroid Build Coastguard Worker     newNonsamplerState.fMaxMipmapLevel = texture->maxMipmapLevel();
2964*c8dee2aaSAndroid Build Coastguard Worker     newNonsamplerState.fSwizzleIsRGBA = true;
2965*c8dee2aaSAndroid Build Coastguard Worker 
2966*c8dee2aaSAndroid Build Coastguard Worker     const GrGLTextureParameters::NonsamplerState& oldNonsamplerState =
2967*c8dee2aaSAndroid Build Coastguard Worker             texture->parameters()->nonsamplerState();
2968*c8dee2aaSAndroid Build Coastguard Worker     if (this->glCaps().textureSwizzleSupport()) {
2969*c8dee2aaSAndroid Build Coastguard Worker         if (setAll || !oldNonsamplerState.fSwizzleIsRGBA) {
2970*c8dee2aaSAndroid Build Coastguard Worker             static constexpr GrGLenum kRGBA[4] {
2971*c8dee2aaSAndroid Build Coastguard Worker                 GR_GL_RED,
2972*c8dee2aaSAndroid Build Coastguard Worker                 GR_GL_GREEN,
2973*c8dee2aaSAndroid Build Coastguard Worker                 GR_GL_BLUE,
2974*c8dee2aaSAndroid Build Coastguard Worker                 GR_GL_ALPHA
2975*c8dee2aaSAndroid Build Coastguard Worker             };
2976*c8dee2aaSAndroid Build Coastguard Worker             this->setTextureUnit(unitIdx);
2977*c8dee2aaSAndroid Build Coastguard Worker             if (GR_IS_GR_GL(this->glStandard())) {
2978*c8dee2aaSAndroid Build Coastguard Worker                 static_assert(sizeof(kRGBA[0]) == sizeof(GrGLint));
2979*c8dee2aaSAndroid Build Coastguard Worker                 GL_CALL(TexParameteriv(target, GR_GL_TEXTURE_SWIZZLE_RGBA,
2980*c8dee2aaSAndroid Build Coastguard Worker                                        reinterpret_cast<const GrGLint*>(kRGBA)));
2981*c8dee2aaSAndroid Build Coastguard Worker             } else if (GR_IS_GR_GL_ES(this->glStandard())) {
2982*c8dee2aaSAndroid Build Coastguard Worker                 // ES3 added swizzle support but not GL_TEXTURE_SWIZZLE_RGBA.
2983*c8dee2aaSAndroid Build Coastguard Worker                 GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SWIZZLE_R, kRGBA[0]));
2984*c8dee2aaSAndroid Build Coastguard Worker                 GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SWIZZLE_G, kRGBA[1]));
2985*c8dee2aaSAndroid Build Coastguard Worker                 GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SWIZZLE_B, kRGBA[2]));
2986*c8dee2aaSAndroid Build Coastguard Worker                 GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SWIZZLE_A, kRGBA[3]));
2987*c8dee2aaSAndroid Build Coastguard Worker             }
2988*c8dee2aaSAndroid Build Coastguard Worker         }
2989*c8dee2aaSAndroid Build Coastguard Worker     }
2990*c8dee2aaSAndroid Build Coastguard Worker     // These are not supported in ES2 contexts
2991*c8dee2aaSAndroid Build Coastguard Worker     if (this->glCaps().mipmapLevelControlSupport() &&
2992*c8dee2aaSAndroid Build Coastguard Worker         (texture->textureType() != GrTextureType::kExternal ||
2993*c8dee2aaSAndroid Build Coastguard Worker          !this->glCaps().dontSetBaseOrMaxLevelForExternalTextures())) {
2994*c8dee2aaSAndroid Build Coastguard Worker         if (newNonsamplerState.fBaseMipMapLevel != oldNonsamplerState.fBaseMipMapLevel) {
2995*c8dee2aaSAndroid Build Coastguard Worker             this->setTextureUnit(unitIdx);
2996*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(TexParameteri(target, GR_GL_TEXTURE_BASE_LEVEL,
2997*c8dee2aaSAndroid Build Coastguard Worker                                   newNonsamplerState.fBaseMipMapLevel));
2998*c8dee2aaSAndroid Build Coastguard Worker         }
2999*c8dee2aaSAndroid Build Coastguard Worker         if (newNonsamplerState.fMaxMipmapLevel != oldNonsamplerState.fMaxMipmapLevel) {
3000*c8dee2aaSAndroid Build Coastguard Worker             this->setTextureUnit(unitIdx);
3001*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(TexParameteri(target, GR_GL_TEXTURE_MAX_LEVEL,
3002*c8dee2aaSAndroid Build Coastguard Worker                                   newNonsamplerState.fMaxMipmapLevel));
3003*c8dee2aaSAndroid Build Coastguard Worker         }
3004*c8dee2aaSAndroid Build Coastguard Worker     }
3005*c8dee2aaSAndroid Build Coastguard Worker     texture->parameters()->set(samplerStateToRecord, newNonsamplerState,
3006*c8dee2aaSAndroid Build Coastguard Worker                                fResetTimestampForTextureParameters);
3007*c8dee2aaSAndroid Build Coastguard Worker }
3008*c8dee2aaSAndroid Build Coastguard Worker 
onResetTextureBindings()3009*c8dee2aaSAndroid Build Coastguard Worker void GrGLGpu::onResetTextureBindings() {
3010*c8dee2aaSAndroid Build Coastguard Worker     static constexpr GrGLenum kTargets[] = {GR_GL_TEXTURE_2D, GR_GL_TEXTURE_RECTANGLE,
3011*c8dee2aaSAndroid Build Coastguard Worker                                             GR_GL_TEXTURE_EXTERNAL};
3012*c8dee2aaSAndroid Build Coastguard Worker     for (int i = 0; i < this->numTextureUnits(); ++i) {
3013*c8dee2aaSAndroid Build Coastguard Worker         this->setTextureUnit(i);
3014*c8dee2aaSAndroid Build Coastguard Worker         for (auto target : kTargets) {
3015*c8dee2aaSAndroid Build Coastguard Worker             if (fHWTextureUnitBindings[i].hasBeenModified(target)) {
3016*c8dee2aaSAndroid Build Coastguard Worker                 GL_CALL(BindTexture(target, 0));
3017*c8dee2aaSAndroid Build Coastguard Worker             }
3018*c8dee2aaSAndroid Build Coastguard Worker         }
3019*c8dee2aaSAndroid Build Coastguard Worker         fHWTextureUnitBindings[i].invalidateAllTargets(true);
3020*c8dee2aaSAndroid Build Coastguard Worker     }
3021*c8dee2aaSAndroid Build Coastguard Worker }
3022*c8dee2aaSAndroid Build Coastguard Worker 
flushColorWrite(bool writeColor)3023*c8dee2aaSAndroid Build Coastguard Worker void GrGLGpu::flushColorWrite(bool writeColor) {
3024*c8dee2aaSAndroid Build Coastguard Worker     if (!writeColor) {
3025*c8dee2aaSAndroid Build Coastguard Worker         if (kNo_TriState != fHWWriteToColor) {
3026*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(ColorMask(GR_GL_FALSE, GR_GL_FALSE,
3027*c8dee2aaSAndroid Build Coastguard Worker                               GR_GL_FALSE, GR_GL_FALSE));
3028*c8dee2aaSAndroid Build Coastguard Worker             fHWWriteToColor = kNo_TriState;
3029*c8dee2aaSAndroid Build Coastguard Worker         }
3030*c8dee2aaSAndroid Build Coastguard Worker     } else {
3031*c8dee2aaSAndroid Build Coastguard Worker         if (kYes_TriState != fHWWriteToColor) {
3032*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
3033*c8dee2aaSAndroid Build Coastguard Worker             fHWWriteToColor = kYes_TriState;
3034*c8dee2aaSAndroid Build Coastguard Worker         }
3035*c8dee2aaSAndroid Build Coastguard Worker     }
3036*c8dee2aaSAndroid Build Coastguard Worker }
3037*c8dee2aaSAndroid Build Coastguard Worker 
flushClearColor(std::array<float,4> color)3038*c8dee2aaSAndroid Build Coastguard Worker void GrGLGpu::flushClearColor(std::array<float, 4> color) {
3039*c8dee2aaSAndroid Build Coastguard Worker     GrGLfloat r = color[0], g = color[1], b = color[2], a = color[3];
3040*c8dee2aaSAndroid Build Coastguard Worker     if (this->glCaps().clearToBoundaryValuesIsBroken() &&
3041*c8dee2aaSAndroid Build Coastguard Worker         (1 == r || 0 == r) && (1 == g || 0 == g) && (1 == b || 0 == b) && (1 == a || 0 == a)) {
3042*c8dee2aaSAndroid Build Coastguard Worker         static const GrGLfloat safeAlpha1 = nextafter(1.f, 2.f);
3043*c8dee2aaSAndroid Build Coastguard Worker         static const GrGLfloat safeAlpha0 = nextafter(0.f, -1.f);
3044*c8dee2aaSAndroid Build Coastguard Worker         a = (1 == a) ? safeAlpha1 : safeAlpha0;
3045*c8dee2aaSAndroid Build Coastguard Worker     }
3046*c8dee2aaSAndroid Build Coastguard Worker     if (r != fHWClearColor[0] || g != fHWClearColor[1] ||
3047*c8dee2aaSAndroid Build Coastguard Worker         b != fHWClearColor[2] || a != fHWClearColor[3]) {
3048*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(ClearColor(r, g, b, a));
3049*c8dee2aaSAndroid Build Coastguard Worker         fHWClearColor[0] = r;
3050*c8dee2aaSAndroid Build Coastguard Worker         fHWClearColor[1] = g;
3051*c8dee2aaSAndroid Build Coastguard Worker         fHWClearColor[2] = b;
3052*c8dee2aaSAndroid Build Coastguard Worker         fHWClearColor[3] = a;
3053*c8dee2aaSAndroid Build Coastguard Worker     }
3054*c8dee2aaSAndroid Build Coastguard Worker }
3055*c8dee2aaSAndroid Build Coastguard Worker 
setTextureUnit(int unit)3056*c8dee2aaSAndroid Build Coastguard Worker void GrGLGpu::setTextureUnit(int unit) {
3057*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(unit >= 0 && unit < this->numTextureUnits());
3058*c8dee2aaSAndroid Build Coastguard Worker     if (unit != fHWActiveTextureUnitIdx) {
3059*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(ActiveTexture(GR_GL_TEXTURE0 + unit));
3060*c8dee2aaSAndroid Build Coastguard Worker         fHWActiveTextureUnitIdx = unit;
3061*c8dee2aaSAndroid Build Coastguard Worker     }
3062*c8dee2aaSAndroid Build Coastguard Worker }
3063*c8dee2aaSAndroid Build Coastguard Worker 
bindTextureToScratchUnit(GrGLenum target,GrGLint textureID)3064*c8dee2aaSAndroid Build Coastguard Worker void GrGLGpu::bindTextureToScratchUnit(GrGLenum target, GrGLint textureID) {
3065*c8dee2aaSAndroid Build Coastguard Worker     // Bind the last texture unit since it is the least likely to be used by GrGLProgram.
3066*c8dee2aaSAndroid Build Coastguard Worker     int lastUnitIdx = this->numTextureUnits() - 1;
3067*c8dee2aaSAndroid Build Coastguard Worker     if (lastUnitIdx != fHWActiveTextureUnitIdx) {
3068*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(ActiveTexture(GR_GL_TEXTURE0 + lastUnitIdx));
3069*c8dee2aaSAndroid Build Coastguard Worker         fHWActiveTextureUnitIdx = lastUnitIdx;
3070*c8dee2aaSAndroid Build Coastguard Worker     }
3071*c8dee2aaSAndroid Build Coastguard Worker     // Clear out the this field so that if a GrGLProgram does use this unit it will rebind the
3072*c8dee2aaSAndroid Build Coastguard Worker     // correct texture.
3073*c8dee2aaSAndroid Build Coastguard Worker     fHWTextureUnitBindings[lastUnitIdx].invalidateForScratchUse(target);
3074*c8dee2aaSAndroid Build Coastguard Worker     GL_CALL(BindTexture(target, textureID));
3075*c8dee2aaSAndroid Build Coastguard Worker }
3076*c8dee2aaSAndroid Build Coastguard Worker 
3077*c8dee2aaSAndroid Build Coastguard Worker // Determines whether glBlitFramebuffer could be used between src and dst by onCopySurface.
can_blit_framebuffer_for_copy_surface(const GrSurface * dst,const GrSurface * src,const SkIRect & srcRect,const SkIRect & dstRect,const GrGLCaps & caps)3078*c8dee2aaSAndroid Build Coastguard Worker static inline bool can_blit_framebuffer_for_copy_surface(const GrSurface* dst,
3079*c8dee2aaSAndroid Build Coastguard Worker                                                          const GrSurface* src,
3080*c8dee2aaSAndroid Build Coastguard Worker                                                          const SkIRect& srcRect,
3081*c8dee2aaSAndroid Build Coastguard Worker                                                          const SkIRect& dstRect,
3082*c8dee2aaSAndroid Build Coastguard Worker                                                          const GrGLCaps& caps) {
3083*c8dee2aaSAndroid Build Coastguard Worker     int dstSampleCnt = 0;
3084*c8dee2aaSAndroid Build Coastguard Worker     int srcSampleCnt = 0;
3085*c8dee2aaSAndroid Build Coastguard Worker     if (const GrRenderTarget* rt = dst->asRenderTarget()) {
3086*c8dee2aaSAndroid Build Coastguard Worker         dstSampleCnt = rt->numSamples();
3087*c8dee2aaSAndroid Build Coastguard Worker     }
3088*c8dee2aaSAndroid Build Coastguard Worker     if (const GrRenderTarget* rt = src->asRenderTarget()) {
3089*c8dee2aaSAndroid Build Coastguard Worker         srcSampleCnt = rt->numSamples();
3090*c8dee2aaSAndroid Build Coastguard Worker     }
3091*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT((dstSampleCnt > 0) == SkToBool(dst->asRenderTarget()));
3092*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT((srcSampleCnt > 0) == SkToBool(src->asRenderTarget()));
3093*c8dee2aaSAndroid Build Coastguard Worker 
3094*c8dee2aaSAndroid Build Coastguard Worker     GrGLFormat dstFormat = GrBackendFormats::AsGLFormat(dst->backendFormat());
3095*c8dee2aaSAndroid Build Coastguard Worker     GrGLFormat srcFormat = GrBackendFormats::AsGLFormat(src->backendFormat());
3096*c8dee2aaSAndroid Build Coastguard Worker 
3097*c8dee2aaSAndroid Build Coastguard Worker     const GrGLTexture* dstTex = static_cast<const GrGLTexture*>(dst->asTexture());
3098*c8dee2aaSAndroid Build Coastguard Worker     const GrGLTexture* srcTex = static_cast<const GrGLTexture*>(src->asTexture());
3099*c8dee2aaSAndroid Build Coastguard Worker 
3100*c8dee2aaSAndroid Build Coastguard Worker     GrTextureType dstTexType;
3101*c8dee2aaSAndroid Build Coastguard Worker     GrTextureType* dstTexTypePtr = nullptr;
3102*c8dee2aaSAndroid Build Coastguard Worker     GrTextureType srcTexType;
3103*c8dee2aaSAndroid Build Coastguard Worker     GrTextureType* srcTexTypePtr = nullptr;
3104*c8dee2aaSAndroid Build Coastguard Worker     if (dstTex) {
3105*c8dee2aaSAndroid Build Coastguard Worker         dstTexType = dstTex->textureType();
3106*c8dee2aaSAndroid Build Coastguard Worker         dstTexTypePtr = &dstTexType;
3107*c8dee2aaSAndroid Build Coastguard Worker     }
3108*c8dee2aaSAndroid Build Coastguard Worker     if (srcTex) {
3109*c8dee2aaSAndroid Build Coastguard Worker         srcTexType = srcTex->textureType();
3110*c8dee2aaSAndroid Build Coastguard Worker         srcTexTypePtr = &srcTexType;
3111*c8dee2aaSAndroid Build Coastguard Worker     }
3112*c8dee2aaSAndroid Build Coastguard Worker 
3113*c8dee2aaSAndroid Build Coastguard Worker     return caps.canCopyAsBlit(dstFormat, dstSampleCnt, dstTexTypePtr,
3114*c8dee2aaSAndroid Build Coastguard Worker                               srcFormat, srcSampleCnt, srcTexTypePtr,
3115*c8dee2aaSAndroid Build Coastguard Worker                               src->getBoundsRect(), true, srcRect, dstRect);
3116*c8dee2aaSAndroid Build Coastguard Worker }
3117*c8dee2aaSAndroid Build Coastguard Worker 
rt_has_msaa_render_buffer(const GrGLRenderTarget * rt,const GrGLCaps & glCaps)3118*c8dee2aaSAndroid Build Coastguard Worker static bool rt_has_msaa_render_buffer(const GrGLRenderTarget* rt, const GrGLCaps& glCaps) {
3119*c8dee2aaSAndroid Build Coastguard Worker     // A RT has a separate MSAA renderbuffer if:
3120*c8dee2aaSAndroid Build Coastguard Worker     // 1) It's multisampled
3121*c8dee2aaSAndroid Build Coastguard Worker     // 2) We're using an extension with separate MSAA renderbuffers
3122*c8dee2aaSAndroid Build Coastguard Worker     // 3) It's not FBO 0, which is special and always auto-resolves
3123*c8dee2aaSAndroid Build Coastguard Worker     return rt->numSamples() > 1 && glCaps.usesMSAARenderBuffers() && !rt->isFBO0(true/*msaa*/);
3124*c8dee2aaSAndroid Build Coastguard Worker }
3125*c8dee2aaSAndroid Build Coastguard Worker 
can_copy_texsubimage(const GrSurface * dst,const GrSurface * src,const GrGLCaps & caps)3126*c8dee2aaSAndroid Build Coastguard Worker static inline bool can_copy_texsubimage(const GrSurface* dst, const GrSurface* src,
3127*c8dee2aaSAndroid Build Coastguard Worker                                         const GrGLCaps& caps) {
3128*c8dee2aaSAndroid Build Coastguard Worker 
3129*c8dee2aaSAndroid Build Coastguard Worker     const GrGLRenderTarget* dstRT = static_cast<const GrGLRenderTarget*>(dst->asRenderTarget());
3130*c8dee2aaSAndroid Build Coastguard Worker     const GrGLRenderTarget* srcRT = static_cast<const GrGLRenderTarget*>(src->asRenderTarget());
3131*c8dee2aaSAndroid Build Coastguard Worker     const GrGLTexture* dstTex = static_cast<const GrGLTexture*>(dst->asTexture());
3132*c8dee2aaSAndroid Build Coastguard Worker     const GrGLTexture* srcTex = static_cast<const GrGLTexture*>(src->asTexture());
3133*c8dee2aaSAndroid Build Coastguard Worker 
3134*c8dee2aaSAndroid Build Coastguard Worker     bool dstHasMSAARenderBuffer = dstRT ? rt_has_msaa_render_buffer(dstRT, caps) : false;
3135*c8dee2aaSAndroid Build Coastguard Worker     bool srcHasMSAARenderBuffer = srcRT ? rt_has_msaa_render_buffer(srcRT, caps) : false;
3136*c8dee2aaSAndroid Build Coastguard Worker 
3137*c8dee2aaSAndroid Build Coastguard Worker     GrGLFormat dstFormat = GrBackendFormats::AsGLFormat(dst->backendFormat());
3138*c8dee2aaSAndroid Build Coastguard Worker     GrGLFormat srcFormat = GrBackendFormats::AsGLFormat(src->backendFormat());
3139*c8dee2aaSAndroid Build Coastguard Worker 
3140*c8dee2aaSAndroid Build Coastguard Worker     GrTextureType dstTexType;
3141*c8dee2aaSAndroid Build Coastguard Worker     GrTextureType* dstTexTypePtr = nullptr;
3142*c8dee2aaSAndroid Build Coastguard Worker     GrTextureType srcTexType;
3143*c8dee2aaSAndroid Build Coastguard Worker     GrTextureType* srcTexTypePtr = nullptr;
3144*c8dee2aaSAndroid Build Coastguard Worker     if (dstTex) {
3145*c8dee2aaSAndroid Build Coastguard Worker         dstTexType = dstTex->textureType();
3146*c8dee2aaSAndroid Build Coastguard Worker         dstTexTypePtr = &dstTexType;
3147*c8dee2aaSAndroid Build Coastguard Worker     }
3148*c8dee2aaSAndroid Build Coastguard Worker     if (srcTex) {
3149*c8dee2aaSAndroid Build Coastguard Worker         srcTexType = srcTex->textureType();
3150*c8dee2aaSAndroid Build Coastguard Worker         srcTexTypePtr = &srcTexType;
3151*c8dee2aaSAndroid Build Coastguard Worker     }
3152*c8dee2aaSAndroid Build Coastguard Worker 
3153*c8dee2aaSAndroid Build Coastguard Worker     return caps.canCopyTexSubImage(dstFormat, dstHasMSAARenderBuffer, dstTexTypePtr,
3154*c8dee2aaSAndroid Build Coastguard Worker                                    srcFormat, srcHasMSAARenderBuffer, srcTexTypePtr);
3155*c8dee2aaSAndroid Build Coastguard Worker }
3156*c8dee2aaSAndroid Build Coastguard Worker 
bindSurfaceFBOForPixelOps(GrSurface * surface,int mipLevel,GrGLenum fboTarget,TempFBOTarget tempFBOTarget)3157*c8dee2aaSAndroid Build Coastguard Worker void GrGLGpu::bindSurfaceFBOForPixelOps(GrSurface* surface, int mipLevel, GrGLenum fboTarget,
3158*c8dee2aaSAndroid Build Coastguard Worker                                         TempFBOTarget tempFBOTarget) {
3159*c8dee2aaSAndroid Build Coastguard Worker     GrGLRenderTarget* rt = static_cast<GrGLRenderTarget*>(surface->asRenderTarget());
3160*c8dee2aaSAndroid Build Coastguard Worker     if (!rt || mipLevel > 0) {
3161*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(surface->asTexture());
3162*c8dee2aaSAndroid Build Coastguard Worker         GrGLTexture* texture = static_cast<GrGLTexture*>(surface->asTexture());
3163*c8dee2aaSAndroid Build Coastguard Worker         GrGLuint texID = texture->textureID();
3164*c8dee2aaSAndroid Build Coastguard Worker         GrGLenum target = texture->target();
3165*c8dee2aaSAndroid Build Coastguard Worker         GrGLuint* tempFBOID;
3166*c8dee2aaSAndroid Build Coastguard Worker         tempFBOID = kSrc_TempFBOTarget == tempFBOTarget ? &fTempSrcFBOID : &fTempDstFBOID;
3167*c8dee2aaSAndroid Build Coastguard Worker 
3168*c8dee2aaSAndroid Build Coastguard Worker         if (0 == *tempFBOID) {
3169*c8dee2aaSAndroid Build Coastguard Worker             GR_GL_CALL(this->glInterface(), GenFramebuffers(1, tempFBOID));
3170*c8dee2aaSAndroid Build Coastguard Worker         }
3171*c8dee2aaSAndroid Build Coastguard Worker 
3172*c8dee2aaSAndroid Build Coastguard Worker         this->bindFramebuffer(fboTarget, *tempFBOID);
3173*c8dee2aaSAndroid Build Coastguard Worker         GR_GL_CALL(
3174*c8dee2aaSAndroid Build Coastguard Worker                 this->glInterface(),
3175*c8dee2aaSAndroid Build Coastguard Worker                 FramebufferTexture2D(fboTarget, GR_GL_COLOR_ATTACHMENT0, target, texID, mipLevel));
3176*c8dee2aaSAndroid Build Coastguard Worker         if (mipLevel == 0) {
3177*c8dee2aaSAndroid Build Coastguard Worker             texture->baseLevelWasBoundToFBO();
3178*c8dee2aaSAndroid Build Coastguard Worker         }
3179*c8dee2aaSAndroid Build Coastguard Worker     } else {
3180*c8dee2aaSAndroid Build Coastguard Worker         rt->bindForPixelOps(fboTarget);
3181*c8dee2aaSAndroid Build Coastguard Worker     }
3182*c8dee2aaSAndroid Build Coastguard Worker }
3183*c8dee2aaSAndroid Build Coastguard Worker 
unbindSurfaceFBOForPixelOps(GrSurface * surface,int mipLevel,GrGLenum fboTarget)3184*c8dee2aaSAndroid Build Coastguard Worker void GrGLGpu::unbindSurfaceFBOForPixelOps(GrSurface* surface, int mipLevel, GrGLenum fboTarget) {
3185*c8dee2aaSAndroid Build Coastguard Worker     // bindSurfaceFBOForPixelOps temporarily binds textures that are not render targets to
3186*c8dee2aaSAndroid Build Coastguard Worker     if (mipLevel > 0 || !surface->asRenderTarget()) {
3187*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(surface->asTexture());
3188*c8dee2aaSAndroid Build Coastguard Worker         GrGLenum textureTarget = static_cast<GrGLTexture*>(surface->asTexture())->target();
3189*c8dee2aaSAndroid Build Coastguard Worker         GR_GL_CALL(this->glInterface(), FramebufferTexture2D(fboTarget,
3190*c8dee2aaSAndroid Build Coastguard Worker                                                              GR_GL_COLOR_ATTACHMENT0,
3191*c8dee2aaSAndroid Build Coastguard Worker                                                              textureTarget,
3192*c8dee2aaSAndroid Build Coastguard Worker                                                              0,
3193*c8dee2aaSAndroid Build Coastguard Worker                                                              0));
3194*c8dee2aaSAndroid Build Coastguard Worker     }
3195*c8dee2aaSAndroid Build Coastguard Worker }
3196*c8dee2aaSAndroid Build Coastguard Worker 
onFBOChanged()3197*c8dee2aaSAndroid Build Coastguard Worker void GrGLGpu::onFBOChanged() {
3198*c8dee2aaSAndroid Build Coastguard Worker     if (this->caps()->workarounds().flush_on_framebuffer_change) {
3199*c8dee2aaSAndroid Build Coastguard Worker         this->flush(FlushType::kForce);
3200*c8dee2aaSAndroid Build Coastguard Worker     }
3201*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_DEBUG
3202*c8dee2aaSAndroid Build Coastguard Worker     if (fIsExecutingCommandBuffer_DebugOnly) {
3203*c8dee2aaSAndroid Build Coastguard Worker         SkDebugf("WARNING: GL FBO binding changed while executing a command buffer. "
3204*c8dee2aaSAndroid Build Coastguard Worker                  "This will severely hurt performance.\n");
3205*c8dee2aaSAndroid Build Coastguard Worker     }
3206*c8dee2aaSAndroid Build Coastguard Worker #endif
3207*c8dee2aaSAndroid Build Coastguard Worker }
3208*c8dee2aaSAndroid Build Coastguard Worker 
bindFramebuffer(GrGLenum target,GrGLuint fboid)3209*c8dee2aaSAndroid Build Coastguard Worker void GrGLGpu::bindFramebuffer(GrGLenum target, GrGLuint fboid) {
3210*c8dee2aaSAndroid Build Coastguard Worker     GL_CALL(BindFramebuffer(target, fboid));
3211*c8dee2aaSAndroid Build Coastguard Worker     if (target == GR_GL_FRAMEBUFFER || target == GR_GL_DRAW_FRAMEBUFFER) {
3212*c8dee2aaSAndroid Build Coastguard Worker         fBoundDrawFramebuffer = fboid;
3213*c8dee2aaSAndroid Build Coastguard Worker     }
3214*c8dee2aaSAndroid Build Coastguard Worker     this->onFBOChanged();
3215*c8dee2aaSAndroid Build Coastguard Worker }
3216*c8dee2aaSAndroid Build Coastguard Worker 
deleteFramebuffer(GrGLuint fboid)3217*c8dee2aaSAndroid Build Coastguard Worker void GrGLGpu::deleteFramebuffer(GrGLuint fboid) {
3218*c8dee2aaSAndroid Build Coastguard Worker     // We're relying on the GL state shadowing being correct in the workaround code below so we
3219*c8dee2aaSAndroid Build Coastguard Worker     // need to handle a dirty context.
3220*c8dee2aaSAndroid Build Coastguard Worker     this->handleDirtyContext();
3221*c8dee2aaSAndroid Build Coastguard Worker     if (fboid == fBoundDrawFramebuffer &&
3222*c8dee2aaSAndroid Build Coastguard Worker         this->caps()->workarounds().unbind_attachments_on_bound_render_fbo_delete) {
3223*c8dee2aaSAndroid Build Coastguard Worker         // This workaround only applies to deleting currently bound framebuffers
3224*c8dee2aaSAndroid Build Coastguard Worker         // on Adreno 420.  Because this is a somewhat rare case, instead of
3225*c8dee2aaSAndroid Build Coastguard Worker         // tracking all the attachments of every framebuffer instead just always
3226*c8dee2aaSAndroid Build Coastguard Worker         // unbind all attachments.
3227*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, GR_GL_COLOR_ATTACHMENT0,
3228*c8dee2aaSAndroid Build Coastguard Worker                                         GR_GL_RENDERBUFFER, 0));
3229*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, GR_GL_STENCIL_ATTACHMENT,
3230*c8dee2aaSAndroid Build Coastguard Worker                                         GR_GL_RENDERBUFFER, 0));
3231*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, GR_GL_DEPTH_ATTACHMENT,
3232*c8dee2aaSAndroid Build Coastguard Worker                                         GR_GL_RENDERBUFFER, 0));
3233*c8dee2aaSAndroid Build Coastguard Worker     }
3234*c8dee2aaSAndroid Build Coastguard Worker 
3235*c8dee2aaSAndroid Build Coastguard Worker     GL_CALL(DeleteFramebuffers(1, &fboid));
3236*c8dee2aaSAndroid Build Coastguard Worker 
3237*c8dee2aaSAndroid Build Coastguard Worker     // Deleting the currently bound framebuffer rebinds to 0.
3238*c8dee2aaSAndroid Build Coastguard Worker     if (fboid == fBoundDrawFramebuffer) {
3239*c8dee2aaSAndroid Build Coastguard Worker         this->onFBOChanged();
3240*c8dee2aaSAndroid Build Coastguard Worker     }
3241*c8dee2aaSAndroid Build Coastguard Worker }
3242*c8dee2aaSAndroid Build Coastguard Worker 
onCopySurface(GrSurface * dst,const SkIRect & dstRect,GrSurface * src,const SkIRect & srcRect,GrSamplerState::Filter filter)3243*c8dee2aaSAndroid Build Coastguard Worker bool GrGLGpu::onCopySurface(GrSurface* dst, const SkIRect& dstRect,
3244*c8dee2aaSAndroid Build Coastguard Worker                             GrSurface* src, const SkIRect& srcRect,
3245*c8dee2aaSAndroid Build Coastguard Worker                             GrSamplerState::Filter filter) {
3246*c8dee2aaSAndroid Build Coastguard Worker     // Don't prefer copying as a draw if the dst doesn't already have a FBO object.
3247*c8dee2aaSAndroid Build Coastguard Worker     // This implicitly handles this->glCaps().useDrawInsteadOfAllRenderTargetWrites().
3248*c8dee2aaSAndroid Build Coastguard Worker     bool preferCopy = SkToBool(dst->asRenderTarget());
3249*c8dee2aaSAndroid Build Coastguard Worker     bool scalingCopy = dstRect.size() != srcRect.size();
3250*c8dee2aaSAndroid Build Coastguard Worker     auto dstFormat = GrBackendFormats::AsGLFormat(dst->backendFormat());
3251*c8dee2aaSAndroid Build Coastguard Worker     if (preferCopy &&
3252*c8dee2aaSAndroid Build Coastguard Worker         this->glCaps().canCopyAsDraw(dstFormat, SkToBool(src->asTexture()), scalingCopy)) {
3253*c8dee2aaSAndroid Build Coastguard Worker         GrRenderTarget* dstRT = dst->asRenderTarget();
3254*c8dee2aaSAndroid Build Coastguard Worker         bool drawToMultisampleFBO = dstRT && dstRT->numSamples() > 1;
3255*c8dee2aaSAndroid Build Coastguard Worker         if (this->copySurfaceAsDraw(dst, drawToMultisampleFBO, src, srcRect, dstRect, filter)) {
3256*c8dee2aaSAndroid Build Coastguard Worker             return true;
3257*c8dee2aaSAndroid Build Coastguard Worker         }
3258*c8dee2aaSAndroid Build Coastguard Worker     }
3259*c8dee2aaSAndroid Build Coastguard Worker 
3260*c8dee2aaSAndroid Build Coastguard Worker     // Prefer copying as with glCopyTexSubImage when the dimensions are the same.
3261*c8dee2aaSAndroid Build Coastguard Worker     if (!scalingCopy && can_copy_texsubimage(dst, src, this->glCaps())) {
3262*c8dee2aaSAndroid Build Coastguard Worker         this->copySurfaceAsCopyTexSubImage(dst, src, srcRect, dstRect.topLeft());
3263*c8dee2aaSAndroid Build Coastguard Worker         return true;
3264*c8dee2aaSAndroid Build Coastguard Worker     }
3265*c8dee2aaSAndroid Build Coastguard Worker 
3266*c8dee2aaSAndroid Build Coastguard Worker     if (can_blit_framebuffer_for_copy_surface(dst, src, srcRect, dstRect, this->glCaps())) {
3267*c8dee2aaSAndroid Build Coastguard Worker         return this->copySurfaceAsBlitFramebuffer(dst, src, srcRect, dstRect, filter);
3268*c8dee2aaSAndroid Build Coastguard Worker     }
3269*c8dee2aaSAndroid Build Coastguard Worker 
3270*c8dee2aaSAndroid Build Coastguard Worker     if (!preferCopy &&
3271*c8dee2aaSAndroid Build Coastguard Worker         this->glCaps().canCopyAsDraw(dstFormat, SkToBool(src->asTexture()), scalingCopy)) {
3272*c8dee2aaSAndroid Build Coastguard Worker         GrRenderTarget* dstRT = dst->asRenderTarget();
3273*c8dee2aaSAndroid Build Coastguard Worker         bool drawToMultisampleFBO = dstRT && dstRT->numSamples() > 1;
3274*c8dee2aaSAndroid Build Coastguard Worker         if (this->copySurfaceAsDraw(dst, drawToMultisampleFBO, src, srcRect, dstRect, filter)) {
3275*c8dee2aaSAndroid Build Coastguard Worker             return true;
3276*c8dee2aaSAndroid Build Coastguard Worker         }
3277*c8dee2aaSAndroid Build Coastguard Worker     }
3278*c8dee2aaSAndroid Build Coastguard Worker 
3279*c8dee2aaSAndroid Build Coastguard Worker     return false;
3280*c8dee2aaSAndroid Build Coastguard Worker }
3281*c8dee2aaSAndroid Build Coastguard Worker 
createCopyProgram(GrTexture * srcTex)3282*c8dee2aaSAndroid Build Coastguard Worker bool GrGLGpu::createCopyProgram(GrTexture* srcTex) {
3283*c8dee2aaSAndroid Build Coastguard Worker     TRACE_EVENT0("skia.gpu", TRACE_FUNC);
3284*c8dee2aaSAndroid Build Coastguard Worker 
3285*c8dee2aaSAndroid Build Coastguard Worker     int progIdx = TextureToCopyProgramIdx(srcTex);
3286*c8dee2aaSAndroid Build Coastguard Worker     const GrShaderCaps* shaderCaps = this->caps()->shaderCaps();
3287*c8dee2aaSAndroid Build Coastguard Worker     SkSLType samplerType = SkSLCombinedSamplerTypeForTextureType(srcTex->textureType());
3288*c8dee2aaSAndroid Build Coastguard Worker 
3289*c8dee2aaSAndroid Build Coastguard Worker     if (!fCopyProgramArrayBuffer) {
3290*c8dee2aaSAndroid Build Coastguard Worker         static const GrGLfloat vdata[] = {
3291*c8dee2aaSAndroid Build Coastguard Worker             0, 0,
3292*c8dee2aaSAndroid Build Coastguard Worker             0, 1,
3293*c8dee2aaSAndroid Build Coastguard Worker             1, 0,
3294*c8dee2aaSAndroid Build Coastguard Worker             1, 1
3295*c8dee2aaSAndroid Build Coastguard Worker         };
3296*c8dee2aaSAndroid Build Coastguard Worker         fCopyProgramArrayBuffer = GrGLBuffer::Make(this,
3297*c8dee2aaSAndroid Build Coastguard Worker                                                    sizeof(vdata),
3298*c8dee2aaSAndroid Build Coastguard Worker                                                    GrGpuBufferType::kVertex,
3299*c8dee2aaSAndroid Build Coastguard Worker                                                    kStatic_GrAccessPattern);
3300*c8dee2aaSAndroid Build Coastguard Worker         if (fCopyProgramArrayBuffer) {
3301*c8dee2aaSAndroid Build Coastguard Worker             fCopyProgramArrayBuffer->updateData(
3302*c8dee2aaSAndroid Build Coastguard Worker                     vdata, /*offset=*/0, sizeof(vdata), /*preserve=*/false);
3303*c8dee2aaSAndroid Build Coastguard Worker         }
3304*c8dee2aaSAndroid Build Coastguard Worker     }
3305*c8dee2aaSAndroid Build Coastguard Worker     if (!fCopyProgramArrayBuffer) {
3306*c8dee2aaSAndroid Build Coastguard Worker         return false;
3307*c8dee2aaSAndroid Build Coastguard Worker     }
3308*c8dee2aaSAndroid Build Coastguard Worker 
3309*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!fCopyPrograms[progIdx].fProgram);
3310*c8dee2aaSAndroid Build Coastguard Worker     GL_CALL_RET(fCopyPrograms[progIdx].fProgram, CreateProgram());
3311*c8dee2aaSAndroid Build Coastguard Worker     if (!fCopyPrograms[progIdx].fProgram) {
3312*c8dee2aaSAndroid Build Coastguard Worker         return false;
3313*c8dee2aaSAndroid Build Coastguard Worker     }
3314*c8dee2aaSAndroid Build Coastguard Worker 
3315*c8dee2aaSAndroid Build Coastguard Worker     GrShaderVar aVertex("a_vertex", SkSLType::kHalf2, GrShaderVar::TypeModifier::In);
3316*c8dee2aaSAndroid Build Coastguard Worker     GrShaderVar uTexCoordXform("u_texCoordXform", SkSLType::kHalf4,
3317*c8dee2aaSAndroid Build Coastguard Worker                                GrShaderVar::TypeModifier::Uniform);
3318*c8dee2aaSAndroid Build Coastguard Worker     GrShaderVar uPosXform("u_posXform", SkSLType::kHalf4, GrShaderVar::TypeModifier::Uniform);
3319*c8dee2aaSAndroid Build Coastguard Worker     GrShaderVar uTexture("u_texture", samplerType);
3320*c8dee2aaSAndroid Build Coastguard Worker     GrShaderVar vTexCoord("v_texCoord", SkSLType::kHalf2, GrShaderVar::TypeModifier::Out);
3321*c8dee2aaSAndroid Build Coastguard Worker     GrShaderVar oFragColor("o_FragColor", SkSLType::kHalf4, GrShaderVar::TypeModifier::Out);
3322*c8dee2aaSAndroid Build Coastguard Worker 
3323*c8dee2aaSAndroid Build Coastguard Worker     SkString vshaderTxt;
3324*c8dee2aaSAndroid Build Coastguard Worker     if (shaderCaps->fNoPerspectiveInterpolationSupport) {
3325*c8dee2aaSAndroid Build Coastguard Worker         if (const char* extension = shaderCaps->noperspectiveInterpolationExtensionString()) {
3326*c8dee2aaSAndroid Build Coastguard Worker             vshaderTxt.appendf("#extension %s : require\n", extension);
3327*c8dee2aaSAndroid Build Coastguard Worker         }
3328*c8dee2aaSAndroid Build Coastguard Worker         vTexCoord.addModifier("noperspective");
3329*c8dee2aaSAndroid Build Coastguard Worker     }
3330*c8dee2aaSAndroid Build Coastguard Worker 
3331*c8dee2aaSAndroid Build Coastguard Worker     aVertex.appendDecl(shaderCaps, &vshaderTxt);
3332*c8dee2aaSAndroid Build Coastguard Worker     vshaderTxt.append(";");
3333*c8dee2aaSAndroid Build Coastguard Worker     uTexCoordXform.appendDecl(shaderCaps, &vshaderTxt);
3334*c8dee2aaSAndroid Build Coastguard Worker     vshaderTxt.append(";");
3335*c8dee2aaSAndroid Build Coastguard Worker     uPosXform.appendDecl(shaderCaps, &vshaderTxt);
3336*c8dee2aaSAndroid Build Coastguard Worker     vshaderTxt.append(";");
3337*c8dee2aaSAndroid Build Coastguard Worker     vTexCoord.appendDecl(shaderCaps, &vshaderTxt);
3338*c8dee2aaSAndroid Build Coastguard Worker     vshaderTxt.append(";");
3339*c8dee2aaSAndroid Build Coastguard Worker 
3340*c8dee2aaSAndroid Build Coastguard Worker     vshaderTxt.append(
3341*c8dee2aaSAndroid Build Coastguard Worker         // Copy Program VS
3342*c8dee2aaSAndroid Build Coastguard Worker         "void main() {"
3343*c8dee2aaSAndroid Build Coastguard Worker           "v_texCoord = half2(a_vertex.xy * u_texCoordXform.xy + u_texCoordXform.zw);"
3344*c8dee2aaSAndroid Build Coastguard Worker           "sk_Position.xy = a_vertex * u_posXform.xy + u_posXform.zw;"
3345*c8dee2aaSAndroid Build Coastguard Worker           "sk_Position.zw = half2(0, 1);"
3346*c8dee2aaSAndroid Build Coastguard Worker         "}"
3347*c8dee2aaSAndroid Build Coastguard Worker     );
3348*c8dee2aaSAndroid Build Coastguard Worker 
3349*c8dee2aaSAndroid Build Coastguard Worker     SkString fshaderTxt;
3350*c8dee2aaSAndroid Build Coastguard Worker     if (shaderCaps->fNoPerspectiveInterpolationSupport) {
3351*c8dee2aaSAndroid Build Coastguard Worker         if (const char* extension = shaderCaps->noperspectiveInterpolationExtensionString()) {
3352*c8dee2aaSAndroid Build Coastguard Worker             fshaderTxt.appendf("#extension %s : require\n", extension);
3353*c8dee2aaSAndroid Build Coastguard Worker         }
3354*c8dee2aaSAndroid Build Coastguard Worker     }
3355*c8dee2aaSAndroid Build Coastguard Worker     vTexCoord.setTypeModifier(GrShaderVar::TypeModifier::In);
3356*c8dee2aaSAndroid Build Coastguard Worker     vTexCoord.appendDecl(shaderCaps, &fshaderTxt);
3357*c8dee2aaSAndroid Build Coastguard Worker     fshaderTxt.append(";");
3358*c8dee2aaSAndroid Build Coastguard Worker     uTexture.appendDecl(shaderCaps, &fshaderTxt);
3359*c8dee2aaSAndroid Build Coastguard Worker     fshaderTxt.append(";");
3360*c8dee2aaSAndroid Build Coastguard Worker     fshaderTxt.appendf(
3361*c8dee2aaSAndroid Build Coastguard Worker         // Copy Program FS
3362*c8dee2aaSAndroid Build Coastguard Worker         "void main() {"
3363*c8dee2aaSAndroid Build Coastguard Worker           "sk_FragColor = sample(u_texture, v_texCoord);"
3364*c8dee2aaSAndroid Build Coastguard Worker         "}"
3365*c8dee2aaSAndroid Build Coastguard Worker     );
3366*c8dee2aaSAndroid Build Coastguard Worker     std::string vertexSkSL{vshaderTxt.c_str(), vshaderTxt.size()};
3367*c8dee2aaSAndroid Build Coastguard Worker     std::string fragmentSkSL{fshaderTxt.c_str(), fshaderTxt.size()};
3368*c8dee2aaSAndroid Build Coastguard Worker 
3369*c8dee2aaSAndroid Build Coastguard Worker     auto errorHandler = this->getContext()->priv().getShaderErrorHandler();
3370*c8dee2aaSAndroid Build Coastguard Worker     std::string glsl[kGrShaderTypeCount];
3371*c8dee2aaSAndroid Build Coastguard Worker     SkSL::ProgramSettings settings;
3372*c8dee2aaSAndroid Build Coastguard Worker     SkSL::Program::Interface interface;
3373*c8dee2aaSAndroid Build Coastguard Worker     skgpu::SkSLToGLSL(shaderCaps, vertexSkSL, SkSL::ProgramKind::kVertex, settings,
3374*c8dee2aaSAndroid Build Coastguard Worker                       &glsl[kVertex_GrShaderType], &interface, errorHandler);
3375*c8dee2aaSAndroid Build Coastguard Worker     GrGLuint vshader = GrGLCompileAndAttachShader(*fGLContext,
3376*c8dee2aaSAndroid Build Coastguard Worker                                                   fCopyPrograms[progIdx].fProgram,
3377*c8dee2aaSAndroid Build Coastguard Worker                                                   GR_GL_VERTEX_SHADER,
3378*c8dee2aaSAndroid Build Coastguard Worker                                                   glsl[kVertex_GrShaderType],
3379*c8dee2aaSAndroid Build Coastguard Worker                                                   /*shaderWasCached=*/false,
3380*c8dee2aaSAndroid Build Coastguard Worker                                                   fProgramCache->stats(),
3381*c8dee2aaSAndroid Build Coastguard Worker                                                   errorHandler);
3382*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(interface == SkSL::Program::Interface());
3383*c8dee2aaSAndroid Build Coastguard Worker     if (!vshader) {
3384*c8dee2aaSAndroid Build Coastguard Worker         // Just delete the program, no shaders to delete
3385*c8dee2aaSAndroid Build Coastguard Worker         cleanup_program(this, &fCopyPrograms[progIdx].fProgram, nullptr, nullptr);
3386*c8dee2aaSAndroid Build Coastguard Worker         return false;
3387*c8dee2aaSAndroid Build Coastguard Worker     }
3388*c8dee2aaSAndroid Build Coastguard Worker 
3389*c8dee2aaSAndroid Build Coastguard Worker     skgpu::SkSLToGLSL(shaderCaps, fragmentSkSL, SkSL::ProgramKind::kFragment, settings,
3390*c8dee2aaSAndroid Build Coastguard Worker                       &glsl[kFragment_GrShaderType], &interface, errorHandler);
3391*c8dee2aaSAndroid Build Coastguard Worker     GrGLuint fshader = GrGLCompileAndAttachShader(*fGLContext,
3392*c8dee2aaSAndroid Build Coastguard Worker                                                   fCopyPrograms[progIdx].fProgram,
3393*c8dee2aaSAndroid Build Coastguard Worker                                                   GR_GL_FRAGMENT_SHADER,
3394*c8dee2aaSAndroid Build Coastguard Worker                                                   glsl[kFragment_GrShaderType],
3395*c8dee2aaSAndroid Build Coastguard Worker                                                   /*shaderWasCached=*/false,
3396*c8dee2aaSAndroid Build Coastguard Worker                                                   fProgramCache->stats(),
3397*c8dee2aaSAndroid Build Coastguard Worker                                                   errorHandler);
3398*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(interface == SkSL::Program::Interface());
3399*c8dee2aaSAndroid Build Coastguard Worker     if (!fshader) {
3400*c8dee2aaSAndroid Build Coastguard Worker         // Delete the program and previously compiled vertex shader
3401*c8dee2aaSAndroid Build Coastguard Worker         cleanup_program(this, &fCopyPrograms[progIdx].fProgram, &vshader, nullptr);
3402*c8dee2aaSAndroid Build Coastguard Worker         return false;
3403*c8dee2aaSAndroid Build Coastguard Worker     }
3404*c8dee2aaSAndroid Build Coastguard Worker 
3405*c8dee2aaSAndroid Build Coastguard Worker     const std::string* sksl[kGrShaderTypeCount] = {&vertexSkSL, &fragmentSkSL};
3406*c8dee2aaSAndroid Build Coastguard Worker     GL_CALL(LinkProgram(fCopyPrograms[progIdx].fProgram));
3407*c8dee2aaSAndroid Build Coastguard Worker     if (!GrGLCheckLinkStatus(this,
3408*c8dee2aaSAndroid Build Coastguard Worker                              fCopyPrograms[progIdx].fProgram,
3409*c8dee2aaSAndroid Build Coastguard Worker                              /*shaderWasCached=*/false,
3410*c8dee2aaSAndroid Build Coastguard Worker                              errorHandler,
3411*c8dee2aaSAndroid Build Coastguard Worker                              sksl,
3412*c8dee2aaSAndroid Build Coastguard Worker                              glsl)) {
3413*c8dee2aaSAndroid Build Coastguard Worker         // Failed to link, delete everything
3414*c8dee2aaSAndroid Build Coastguard Worker         cleanup_program(this, &fCopyPrograms[progIdx].fProgram, &vshader, &fshader);
3415*c8dee2aaSAndroid Build Coastguard Worker         return false;
3416*c8dee2aaSAndroid Build Coastguard Worker     }
3417*c8dee2aaSAndroid Build Coastguard Worker 
3418*c8dee2aaSAndroid Build Coastguard Worker     GL_CALL_RET(fCopyPrograms[progIdx].fTextureUniform,
3419*c8dee2aaSAndroid Build Coastguard Worker                 GetUniformLocation(fCopyPrograms[progIdx].fProgram, "u_texture"));
3420*c8dee2aaSAndroid Build Coastguard Worker     GL_CALL_RET(fCopyPrograms[progIdx].fPosXformUniform,
3421*c8dee2aaSAndroid Build Coastguard Worker                 GetUniformLocation(fCopyPrograms[progIdx].fProgram, "u_posXform"));
3422*c8dee2aaSAndroid Build Coastguard Worker     GL_CALL_RET(fCopyPrograms[progIdx].fTexCoordXformUniform,
3423*c8dee2aaSAndroid Build Coastguard Worker                 GetUniformLocation(fCopyPrograms[progIdx].fProgram, "u_texCoordXform"));
3424*c8dee2aaSAndroid Build Coastguard Worker 
3425*c8dee2aaSAndroid Build Coastguard Worker     GL_CALL(BindAttribLocation(fCopyPrograms[progIdx].fProgram, 0, "a_vertex"));
3426*c8dee2aaSAndroid Build Coastguard Worker 
3427*c8dee2aaSAndroid Build Coastguard Worker     // Cleanup the shaders, but not the program
3428*c8dee2aaSAndroid Build Coastguard Worker     cleanup_program(this, nullptr, &vshader, &fshader);
3429*c8dee2aaSAndroid Build Coastguard Worker 
3430*c8dee2aaSAndroid Build Coastguard Worker     return true;
3431*c8dee2aaSAndroid Build Coastguard Worker }
3432*c8dee2aaSAndroid Build Coastguard Worker 
createMipmapProgram(int progIdx)3433*c8dee2aaSAndroid Build Coastguard Worker bool GrGLGpu::createMipmapProgram(int progIdx) {
3434*c8dee2aaSAndroid Build Coastguard Worker     const bool oddWidth = SkToBool(progIdx & 0x2);
3435*c8dee2aaSAndroid Build Coastguard Worker     const bool oddHeight = SkToBool(progIdx & 0x1);
3436*c8dee2aaSAndroid Build Coastguard Worker     const int numTaps = (oddWidth ? 2 : 1) * (oddHeight ? 2 : 1);
3437*c8dee2aaSAndroid Build Coastguard Worker 
3438*c8dee2aaSAndroid Build Coastguard Worker     const GrShaderCaps* shaderCaps = this->caps()->shaderCaps();
3439*c8dee2aaSAndroid Build Coastguard Worker 
3440*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!fMipmapPrograms[progIdx].fProgram);
3441*c8dee2aaSAndroid Build Coastguard Worker     GL_CALL_RET(fMipmapPrograms[progIdx].fProgram, CreateProgram());
3442*c8dee2aaSAndroid Build Coastguard Worker     if (!fMipmapPrograms[progIdx].fProgram) {
3443*c8dee2aaSAndroid Build Coastguard Worker         return false;
3444*c8dee2aaSAndroid Build Coastguard Worker     }
3445*c8dee2aaSAndroid Build Coastguard Worker 
3446*c8dee2aaSAndroid Build Coastguard Worker     GrShaderVar aVertex("a_vertex", SkSLType::kHalf2, GrShaderVar::TypeModifier::In);
3447*c8dee2aaSAndroid Build Coastguard Worker     GrShaderVar uTexCoordXform("u_texCoordXform", SkSLType::kHalf4,
3448*c8dee2aaSAndroid Build Coastguard Worker                                GrShaderVar::TypeModifier::Uniform);
3449*c8dee2aaSAndroid Build Coastguard Worker     GrShaderVar uTexture("u_texture", SkSLType::kTexture2DSampler);
3450*c8dee2aaSAndroid Build Coastguard Worker     // We need 1, 2, or 4 texture coordinates (depending on parity of each dimension):
3451*c8dee2aaSAndroid Build Coastguard Worker     GrShaderVar vTexCoords[] = {
3452*c8dee2aaSAndroid Build Coastguard Worker         GrShaderVar("v_texCoord0", SkSLType::kHalf2, GrShaderVar::TypeModifier::Out),
3453*c8dee2aaSAndroid Build Coastguard Worker         GrShaderVar("v_texCoord1", SkSLType::kHalf2, GrShaderVar::TypeModifier::Out),
3454*c8dee2aaSAndroid Build Coastguard Worker         GrShaderVar("v_texCoord2", SkSLType::kHalf2, GrShaderVar::TypeModifier::Out),
3455*c8dee2aaSAndroid Build Coastguard Worker         GrShaderVar("v_texCoord3", SkSLType::kHalf2, GrShaderVar::TypeModifier::Out),
3456*c8dee2aaSAndroid Build Coastguard Worker     };
3457*c8dee2aaSAndroid Build Coastguard Worker     GrShaderVar oFragColor("o_FragColor", SkSLType::kHalf4,GrShaderVar::TypeModifier::Out);
3458*c8dee2aaSAndroid Build Coastguard Worker 
3459*c8dee2aaSAndroid Build Coastguard Worker     SkString vshaderTxt;
3460*c8dee2aaSAndroid Build Coastguard Worker     if (shaderCaps->fNoPerspectiveInterpolationSupport) {
3461*c8dee2aaSAndroid Build Coastguard Worker         if (const char* extension = shaderCaps->noperspectiveInterpolationExtensionString()) {
3462*c8dee2aaSAndroid Build Coastguard Worker             vshaderTxt.appendf("#extension %s : require\n", extension);
3463*c8dee2aaSAndroid Build Coastguard Worker         }
3464*c8dee2aaSAndroid Build Coastguard Worker         vTexCoords[0].addModifier("noperspective");
3465*c8dee2aaSAndroid Build Coastguard Worker         vTexCoords[1].addModifier("noperspective");
3466*c8dee2aaSAndroid Build Coastguard Worker         vTexCoords[2].addModifier("noperspective");
3467*c8dee2aaSAndroid Build Coastguard Worker         vTexCoords[3].addModifier("noperspective");
3468*c8dee2aaSAndroid Build Coastguard Worker     }
3469*c8dee2aaSAndroid Build Coastguard Worker 
3470*c8dee2aaSAndroid Build Coastguard Worker     aVertex.appendDecl(shaderCaps, &vshaderTxt);
3471*c8dee2aaSAndroid Build Coastguard Worker     vshaderTxt.append(";");
3472*c8dee2aaSAndroid Build Coastguard Worker     uTexCoordXform.appendDecl(shaderCaps, &vshaderTxt);
3473*c8dee2aaSAndroid Build Coastguard Worker     vshaderTxt.append(";");
3474*c8dee2aaSAndroid Build Coastguard Worker     for (int i = 0; i < numTaps; ++i) {
3475*c8dee2aaSAndroid Build Coastguard Worker         vTexCoords[i].appendDecl(shaderCaps, &vshaderTxt);
3476*c8dee2aaSAndroid Build Coastguard Worker         vshaderTxt.append(";");
3477*c8dee2aaSAndroid Build Coastguard Worker     }
3478*c8dee2aaSAndroid Build Coastguard Worker 
3479*c8dee2aaSAndroid Build Coastguard Worker     vshaderTxt.append(
3480*c8dee2aaSAndroid Build Coastguard Worker         // Mipmap Program VS
3481*c8dee2aaSAndroid Build Coastguard Worker         "void main() {"
3482*c8dee2aaSAndroid Build Coastguard Worker           "sk_Position.xy = a_vertex * half2(2) - half2(1);"
3483*c8dee2aaSAndroid Build Coastguard Worker           "sk_Position.zw = half2(0, 1);"
3484*c8dee2aaSAndroid Build Coastguard Worker     );
3485*c8dee2aaSAndroid Build Coastguard Worker 
3486*c8dee2aaSAndroid Build Coastguard Worker     // Insert texture coordinate computation:
3487*c8dee2aaSAndroid Build Coastguard Worker     if (oddWidth && oddHeight) {
3488*c8dee2aaSAndroid Build Coastguard Worker         vshaderTxt.append(
3489*c8dee2aaSAndroid Build Coastguard Worker               "v_texCoord0 = a_vertex.xy * u_texCoordXform.yw;"
3490*c8dee2aaSAndroid Build Coastguard Worker               "v_texCoord1 = a_vertex.xy * u_texCoordXform.yw + half2(u_texCoordXform.x, 0);"
3491*c8dee2aaSAndroid Build Coastguard Worker               "v_texCoord2 = a_vertex.xy * u_texCoordXform.yw + half2(0, u_texCoordXform.z);"
3492*c8dee2aaSAndroid Build Coastguard Worker               "v_texCoord3 = a_vertex.xy * u_texCoordXform.yw + u_texCoordXform.xz;"
3493*c8dee2aaSAndroid Build Coastguard Worker         );
3494*c8dee2aaSAndroid Build Coastguard Worker     } else if (oddWidth) {
3495*c8dee2aaSAndroid Build Coastguard Worker         vshaderTxt.append(
3496*c8dee2aaSAndroid Build Coastguard Worker               "v_texCoord0 = a_vertex.xy * half2(u_texCoordXform.y, 1);"
3497*c8dee2aaSAndroid Build Coastguard Worker               "v_texCoord1 = a_vertex.xy * half2(u_texCoordXform.y, 1) + half2(u_texCoordXform.x, 0);"
3498*c8dee2aaSAndroid Build Coastguard Worker         );
3499*c8dee2aaSAndroid Build Coastguard Worker     } else if (oddHeight) {
3500*c8dee2aaSAndroid Build Coastguard Worker         vshaderTxt.append(
3501*c8dee2aaSAndroid Build Coastguard Worker               "v_texCoord0 = a_vertex.xy * half2(1, u_texCoordXform.w);"
3502*c8dee2aaSAndroid Build Coastguard Worker               "v_texCoord1 = a_vertex.xy * half2(1, u_texCoordXform.w) + half2(0, u_texCoordXform.z);"
3503*c8dee2aaSAndroid Build Coastguard Worker         );
3504*c8dee2aaSAndroid Build Coastguard Worker     } else {
3505*c8dee2aaSAndroid Build Coastguard Worker         vshaderTxt.append(
3506*c8dee2aaSAndroid Build Coastguard Worker               "v_texCoord0 = a_vertex.xy;"
3507*c8dee2aaSAndroid Build Coastguard Worker         );
3508*c8dee2aaSAndroid Build Coastguard Worker     }
3509*c8dee2aaSAndroid Build Coastguard Worker 
3510*c8dee2aaSAndroid Build Coastguard Worker     vshaderTxt.append("}");
3511*c8dee2aaSAndroid Build Coastguard Worker 
3512*c8dee2aaSAndroid Build Coastguard Worker     SkString fshaderTxt;
3513*c8dee2aaSAndroid Build Coastguard Worker     if (shaderCaps->fNoPerspectiveInterpolationSupport) {
3514*c8dee2aaSAndroid Build Coastguard Worker         if (const char* extension = shaderCaps->noperspectiveInterpolationExtensionString()) {
3515*c8dee2aaSAndroid Build Coastguard Worker             fshaderTxt.appendf("#extension %s : require\n", extension);
3516*c8dee2aaSAndroid Build Coastguard Worker         }
3517*c8dee2aaSAndroid Build Coastguard Worker     }
3518*c8dee2aaSAndroid Build Coastguard Worker     for (int i = 0; i < numTaps; ++i) {
3519*c8dee2aaSAndroid Build Coastguard Worker         vTexCoords[i].setTypeModifier(GrShaderVar::TypeModifier::In);
3520*c8dee2aaSAndroid Build Coastguard Worker         vTexCoords[i].appendDecl(shaderCaps, &fshaderTxt);
3521*c8dee2aaSAndroid Build Coastguard Worker         fshaderTxt.append(";");
3522*c8dee2aaSAndroid Build Coastguard Worker     }
3523*c8dee2aaSAndroid Build Coastguard Worker     uTexture.appendDecl(shaderCaps, &fshaderTxt);
3524*c8dee2aaSAndroid Build Coastguard Worker     fshaderTxt.append(";");
3525*c8dee2aaSAndroid Build Coastguard Worker     fshaderTxt.append(
3526*c8dee2aaSAndroid Build Coastguard Worker         // Mipmap Program FS
3527*c8dee2aaSAndroid Build Coastguard Worker         "void main() {"
3528*c8dee2aaSAndroid Build Coastguard Worker     );
3529*c8dee2aaSAndroid Build Coastguard Worker 
3530*c8dee2aaSAndroid Build Coastguard Worker     if (oddWidth && oddHeight) {
3531*c8dee2aaSAndroid Build Coastguard Worker         fshaderTxt.append(
3532*c8dee2aaSAndroid Build Coastguard Worker               "sk_FragColor = (sample(u_texture, v_texCoord0) + "
3533*c8dee2aaSAndroid Build Coastguard Worker                               "sample(u_texture, v_texCoord1) + "
3534*c8dee2aaSAndroid Build Coastguard Worker                               "sample(u_texture, v_texCoord2) + "
3535*c8dee2aaSAndroid Build Coastguard Worker                               "sample(u_texture, v_texCoord3)) * 0.25;"
3536*c8dee2aaSAndroid Build Coastguard Worker         );
3537*c8dee2aaSAndroid Build Coastguard Worker     } else if (oddWidth || oddHeight) {
3538*c8dee2aaSAndroid Build Coastguard Worker         fshaderTxt.append(
3539*c8dee2aaSAndroid Build Coastguard Worker               "sk_FragColor = (sample(u_texture, v_texCoord0) + "
3540*c8dee2aaSAndroid Build Coastguard Worker                               "sample(u_texture, v_texCoord1)) * 0.5;"
3541*c8dee2aaSAndroid Build Coastguard Worker         );
3542*c8dee2aaSAndroid Build Coastguard Worker     } else {
3543*c8dee2aaSAndroid Build Coastguard Worker         fshaderTxt.append(
3544*c8dee2aaSAndroid Build Coastguard Worker               "sk_FragColor = sample(u_texture, v_texCoord0);"
3545*c8dee2aaSAndroid Build Coastguard Worker         );
3546*c8dee2aaSAndroid Build Coastguard Worker     }
3547*c8dee2aaSAndroid Build Coastguard Worker 
3548*c8dee2aaSAndroid Build Coastguard Worker     fshaderTxt.append("}");
3549*c8dee2aaSAndroid Build Coastguard Worker 
3550*c8dee2aaSAndroid Build Coastguard Worker     std::string vertexSkSL{vshaderTxt.c_str(), vshaderTxt.size()};
3551*c8dee2aaSAndroid Build Coastguard Worker     std::string fragmentSkSL{fshaderTxt.c_str(), fshaderTxt.size()};
3552*c8dee2aaSAndroid Build Coastguard Worker 
3553*c8dee2aaSAndroid Build Coastguard Worker     auto errorHandler = this->getContext()->priv().getShaderErrorHandler();
3554*c8dee2aaSAndroid Build Coastguard Worker     std::string glsl[kGrShaderTypeCount];
3555*c8dee2aaSAndroid Build Coastguard Worker     SkSL::ProgramSettings settings;
3556*c8dee2aaSAndroid Build Coastguard Worker     SkSL::Program::Interface interface;
3557*c8dee2aaSAndroid Build Coastguard Worker 
3558*c8dee2aaSAndroid Build Coastguard Worker     skgpu::SkSLToGLSL(shaderCaps, vertexSkSL, SkSL::ProgramKind::kVertex, settings,
3559*c8dee2aaSAndroid Build Coastguard Worker                       &glsl[kVertex_GrShaderType], &interface, errorHandler);
3560*c8dee2aaSAndroid Build Coastguard Worker     GrGLuint vshader = GrGLCompileAndAttachShader(*fGLContext,
3561*c8dee2aaSAndroid Build Coastguard Worker                                                   fMipmapPrograms[progIdx].fProgram,
3562*c8dee2aaSAndroid Build Coastguard Worker                                                   GR_GL_VERTEX_SHADER,
3563*c8dee2aaSAndroid Build Coastguard Worker                                                   glsl[kVertex_GrShaderType],
3564*c8dee2aaSAndroid Build Coastguard Worker                                                   /*shaderWasCached=*/false,
3565*c8dee2aaSAndroid Build Coastguard Worker                                                   fProgramCache->stats(),
3566*c8dee2aaSAndroid Build Coastguard Worker                                                   errorHandler);
3567*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(interface == SkSL::Program::Interface());
3568*c8dee2aaSAndroid Build Coastguard Worker     if (!vshader) {
3569*c8dee2aaSAndroid Build Coastguard Worker         cleanup_program(this, &fMipmapPrograms[progIdx].fProgram, nullptr, nullptr);
3570*c8dee2aaSAndroid Build Coastguard Worker         return false;
3571*c8dee2aaSAndroid Build Coastguard Worker     }
3572*c8dee2aaSAndroid Build Coastguard Worker 
3573*c8dee2aaSAndroid Build Coastguard Worker     skgpu::SkSLToGLSL(shaderCaps, fragmentSkSL, SkSL::ProgramKind::kFragment, settings,
3574*c8dee2aaSAndroid Build Coastguard Worker                       &glsl[kFragment_GrShaderType], &interface, errorHandler);
3575*c8dee2aaSAndroid Build Coastguard Worker     GrGLuint fshader = GrGLCompileAndAttachShader(*fGLContext,
3576*c8dee2aaSAndroid Build Coastguard Worker                                                   fMipmapPrograms[progIdx].fProgram,
3577*c8dee2aaSAndroid Build Coastguard Worker                                                   GR_GL_FRAGMENT_SHADER,
3578*c8dee2aaSAndroid Build Coastguard Worker                                                   glsl[kFragment_GrShaderType],
3579*c8dee2aaSAndroid Build Coastguard Worker                                                   /*shaderWasCached=*/false,
3580*c8dee2aaSAndroid Build Coastguard Worker                                                   fProgramCache->stats(),
3581*c8dee2aaSAndroid Build Coastguard Worker                                                   errorHandler);
3582*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(interface == SkSL::Program::Interface());
3583*c8dee2aaSAndroid Build Coastguard Worker     if (!fshader) {
3584*c8dee2aaSAndroid Build Coastguard Worker         cleanup_program(this, &fMipmapPrograms[progIdx].fProgram, &vshader, nullptr);
3585*c8dee2aaSAndroid Build Coastguard Worker         return false;
3586*c8dee2aaSAndroid Build Coastguard Worker     }
3587*c8dee2aaSAndroid Build Coastguard Worker 
3588*c8dee2aaSAndroid Build Coastguard Worker     const std::string* sksl[kGrShaderTypeCount] = {&vertexSkSL, &fragmentSkSL};
3589*c8dee2aaSAndroid Build Coastguard Worker     GL_CALL(LinkProgram(fMipmapPrograms[progIdx].fProgram));
3590*c8dee2aaSAndroid Build Coastguard Worker     if (!GrGLCheckLinkStatus(this,
3591*c8dee2aaSAndroid Build Coastguard Worker                              fMipmapPrograms[progIdx].fProgram,
3592*c8dee2aaSAndroid Build Coastguard Worker                              /*shaderWasCached=*/false,
3593*c8dee2aaSAndroid Build Coastguard Worker                              errorHandler,
3594*c8dee2aaSAndroid Build Coastguard Worker                              sksl,
3595*c8dee2aaSAndroid Build Coastguard Worker                              glsl)) {
3596*c8dee2aaSAndroid Build Coastguard Worker         // Program linking failed, clean up
3597*c8dee2aaSAndroid Build Coastguard Worker         cleanup_program(this, &fMipmapPrograms[progIdx].fProgram, &vshader, &fshader);
3598*c8dee2aaSAndroid Build Coastguard Worker         return false;
3599*c8dee2aaSAndroid Build Coastguard Worker     }
3600*c8dee2aaSAndroid Build Coastguard Worker 
3601*c8dee2aaSAndroid Build Coastguard Worker     GL_CALL_RET(fMipmapPrograms[progIdx].fTextureUniform,
3602*c8dee2aaSAndroid Build Coastguard Worker                 GetUniformLocation(fMipmapPrograms[progIdx].fProgram, "u_texture"));
3603*c8dee2aaSAndroid Build Coastguard Worker     GL_CALL_RET(fMipmapPrograms[progIdx].fTexCoordXformUniform,
3604*c8dee2aaSAndroid Build Coastguard Worker                 GetUniformLocation(fMipmapPrograms[progIdx].fProgram, "u_texCoordXform"));
3605*c8dee2aaSAndroid Build Coastguard Worker 
3606*c8dee2aaSAndroid Build Coastguard Worker     GL_CALL(BindAttribLocation(fMipmapPrograms[progIdx].fProgram, 0, "a_vertex"));
3607*c8dee2aaSAndroid Build Coastguard Worker 
3608*c8dee2aaSAndroid Build Coastguard Worker     // Clean up the shaders
3609*c8dee2aaSAndroid Build Coastguard Worker     cleanup_program(this, nullptr, &vshader, &fshader);
3610*c8dee2aaSAndroid Build Coastguard Worker 
3611*c8dee2aaSAndroid Build Coastguard Worker     return true;
3612*c8dee2aaSAndroid Build Coastguard Worker }
3613*c8dee2aaSAndroid Build Coastguard Worker 
copySurfaceAsDraw(GrSurface * dst,bool drawToMultisampleFBO,GrSurface * src,const SkIRect & srcRect,const SkIRect & dstRect,GrSamplerState::Filter filter)3614*c8dee2aaSAndroid Build Coastguard Worker bool GrGLGpu::copySurfaceAsDraw(GrSurface* dst, bool drawToMultisampleFBO, GrSurface* src,
3615*c8dee2aaSAndroid Build Coastguard Worker                                 const SkIRect& srcRect, const SkIRect& dstRect,
3616*c8dee2aaSAndroid Build Coastguard Worker                                 GrSamplerState::Filter filter) {
3617*c8dee2aaSAndroid Build Coastguard Worker     auto* srcTex = static_cast<GrGLTexture*>(src->asTexture());
3618*c8dee2aaSAndroid Build Coastguard Worker     if (!srcTex) {
3619*c8dee2aaSAndroid Build Coastguard Worker         return false;
3620*c8dee2aaSAndroid Build Coastguard Worker     }
3621*c8dee2aaSAndroid Build Coastguard Worker     // We don't swizzle at all in our copies.
3622*c8dee2aaSAndroid Build Coastguard Worker     this->bindTexture(0, filter, skgpu::Swizzle::RGBA(), srcTex);
3623*c8dee2aaSAndroid Build Coastguard Worker     if (auto* dstRT = static_cast<GrGLRenderTarget*>(dst->asRenderTarget())) {
3624*c8dee2aaSAndroid Build Coastguard Worker         this->flushRenderTarget(dstRT, drawToMultisampleFBO);
3625*c8dee2aaSAndroid Build Coastguard Worker     } else {
3626*c8dee2aaSAndroid Build Coastguard Worker         auto* dstTex = static_cast<GrGLTexture*>(src->asTexture());
3627*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(dstTex);
3628*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(!drawToMultisampleFBO);
3629*c8dee2aaSAndroid Build Coastguard Worker         if (!this->glCaps().isFormatRenderable(dstTex->format(), 1)) {
3630*c8dee2aaSAndroid Build Coastguard Worker             return false;
3631*c8dee2aaSAndroid Build Coastguard Worker         }
3632*c8dee2aaSAndroid Build Coastguard Worker         this->bindSurfaceFBOForPixelOps(dst, 0, GR_GL_FRAMEBUFFER, kDst_TempFBOTarget);
3633*c8dee2aaSAndroid Build Coastguard Worker         fHWBoundRenderTargetUniqueID.makeInvalid();
3634*c8dee2aaSAndroid Build Coastguard Worker     }
3635*c8dee2aaSAndroid Build Coastguard Worker     int progIdx = TextureToCopyProgramIdx(srcTex);
3636*c8dee2aaSAndroid Build Coastguard Worker     if (!fCopyPrograms[progIdx].fProgram) {
3637*c8dee2aaSAndroid Build Coastguard Worker         if (!this->createCopyProgram(srcTex)) {
3638*c8dee2aaSAndroid Build Coastguard Worker             SkDebugf("Failed to create copy program.\n");
3639*c8dee2aaSAndroid Build Coastguard Worker             return false;
3640*c8dee2aaSAndroid Build Coastguard Worker         }
3641*c8dee2aaSAndroid Build Coastguard Worker     }
3642*c8dee2aaSAndroid Build Coastguard Worker     this->flushViewport(SkIRect::MakeSize(dst->dimensions()),
3643*c8dee2aaSAndroid Build Coastguard Worker                         dst->height(),
3644*c8dee2aaSAndroid Build Coastguard Worker                         kTopLeft_GrSurfaceOrigin); // the origin is irrelevant in this case
3645*c8dee2aaSAndroid Build Coastguard Worker     this->flushProgram(fCopyPrograms[progIdx].fProgram);
3646*c8dee2aaSAndroid Build Coastguard Worker     fHWVertexArrayState.setVertexArrayID(this, 0);
3647*c8dee2aaSAndroid Build Coastguard Worker     GrGLAttribArrayState* attribs = fHWVertexArrayState.bindInternalVertexArray(this);
3648*c8dee2aaSAndroid Build Coastguard Worker     attribs->enableVertexArrays(this, 1);
3649*c8dee2aaSAndroid Build Coastguard Worker     attribs->set(this, 0, fCopyProgramArrayBuffer.get(), kFloat2_GrVertexAttribType,
3650*c8dee2aaSAndroid Build Coastguard Worker                  SkSLType::kFloat2, 2 * sizeof(GrGLfloat), 0);
3651*c8dee2aaSAndroid Build Coastguard Worker     // dst rect edges in NDC (-1 to 1)
3652*c8dee2aaSAndroid Build Coastguard Worker     int dw = dst->width();
3653*c8dee2aaSAndroid Build Coastguard Worker     int dh = dst->height();
3654*c8dee2aaSAndroid Build Coastguard Worker     GrGLfloat dx0 = 2.f * dstRect.fLeft / dw - 1.f;
3655*c8dee2aaSAndroid Build Coastguard Worker     GrGLfloat dx1 = 2.f * dstRect.fRight / dw - 1.f;
3656*c8dee2aaSAndroid Build Coastguard Worker     GrGLfloat dy0 = 2.f * dstRect.fTop / dh - 1.f;
3657*c8dee2aaSAndroid Build Coastguard Worker     GrGLfloat dy1 = 2.f * dstRect.fBottom / dh - 1.f;
3658*c8dee2aaSAndroid Build Coastguard Worker     GrGLfloat sx0 = (GrGLfloat)srcRect.fLeft;
3659*c8dee2aaSAndroid Build Coastguard Worker     GrGLfloat sx1 = (GrGLfloat)(srcRect.fRight);
3660*c8dee2aaSAndroid Build Coastguard Worker     GrGLfloat sy0 = (GrGLfloat)srcRect.fTop;
3661*c8dee2aaSAndroid Build Coastguard Worker     GrGLfloat sy1 = (GrGLfloat)(srcRect.fBottom);
3662*c8dee2aaSAndroid Build Coastguard Worker     int sw = src->width();
3663*c8dee2aaSAndroid Build Coastguard Worker     int sh = src->height();
3664*c8dee2aaSAndroid Build Coastguard Worker     if (srcTex->textureType() != GrTextureType::kRectangle) {
3665*c8dee2aaSAndroid Build Coastguard Worker         // src rect edges in normalized texture space (0 to 1)
3666*c8dee2aaSAndroid Build Coastguard Worker         sx0 /= sw;
3667*c8dee2aaSAndroid Build Coastguard Worker         sx1 /= sw;
3668*c8dee2aaSAndroid Build Coastguard Worker         sy0 /= sh;
3669*c8dee2aaSAndroid Build Coastguard Worker         sy1 /= sh;
3670*c8dee2aaSAndroid Build Coastguard Worker     }
3671*c8dee2aaSAndroid Build Coastguard Worker     GL_CALL(Uniform4f(fCopyPrograms[progIdx].fPosXformUniform, dx1 - dx0, dy1 - dy0, dx0, dy0));
3672*c8dee2aaSAndroid Build Coastguard Worker     GL_CALL(Uniform4f(fCopyPrograms[progIdx].fTexCoordXformUniform,
3673*c8dee2aaSAndroid Build Coastguard Worker                       sx1 - sx0, sy1 - sy0, sx0, sy0));
3674*c8dee2aaSAndroid Build Coastguard Worker     GL_CALL(Uniform1i(fCopyPrograms[progIdx].fTextureUniform, 0));
3675*c8dee2aaSAndroid Build Coastguard Worker     this->flushBlendAndColorWrite(skgpu::BlendInfo(), skgpu::Swizzle::RGBA());
3676*c8dee2aaSAndroid Build Coastguard Worker     this->flushConservativeRasterState(false);
3677*c8dee2aaSAndroid Build Coastguard Worker     this->flushWireframeState(false);
3678*c8dee2aaSAndroid Build Coastguard Worker     this->flushScissorTest(GrScissorTest::kDisabled);
3679*c8dee2aaSAndroid Build Coastguard Worker     this->disableWindowRectangles();
3680*c8dee2aaSAndroid Build Coastguard Worker     this->disableStencil();
3681*c8dee2aaSAndroid Build Coastguard Worker     if (this->glCaps().srgbWriteControl()) {
3682*c8dee2aaSAndroid Build Coastguard Worker         this->flushFramebufferSRGB(true);
3683*c8dee2aaSAndroid Build Coastguard Worker     }
3684*c8dee2aaSAndroid Build Coastguard Worker     GL_CALL(DrawArrays(GR_GL_TRIANGLE_STRIP, 0, 4));
3685*c8dee2aaSAndroid Build Coastguard Worker     this->unbindSurfaceFBOForPixelOps(dst, 0, GR_GL_FRAMEBUFFER);
3686*c8dee2aaSAndroid Build Coastguard Worker     // The rect is already in device space so we pass in kTopLeft so no flip is done.
3687*c8dee2aaSAndroid Build Coastguard Worker     this->didWriteToSurface(dst, kTopLeft_GrSurfaceOrigin, &dstRect);
3688*c8dee2aaSAndroid Build Coastguard Worker     return true;
3689*c8dee2aaSAndroid Build Coastguard Worker }
3690*c8dee2aaSAndroid Build Coastguard Worker 
copySurfaceAsCopyTexSubImage(GrSurface * dst,GrSurface * src,const SkIRect & srcRect,const SkIPoint & dstPoint)3691*c8dee2aaSAndroid Build Coastguard Worker void GrGLGpu::copySurfaceAsCopyTexSubImage(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
3692*c8dee2aaSAndroid Build Coastguard Worker                                            const SkIPoint& dstPoint) {
3693*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(can_copy_texsubimage(dst, src, this->glCaps()));
3694*c8dee2aaSAndroid Build Coastguard Worker     this->bindSurfaceFBOForPixelOps(src, 0, GR_GL_FRAMEBUFFER, kSrc_TempFBOTarget);
3695*c8dee2aaSAndroid Build Coastguard Worker     GrGLTexture* dstTex = static_cast<GrGLTexture *>(dst->asTexture());
3696*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(dstTex);
3697*c8dee2aaSAndroid Build Coastguard Worker     // We modified the bound FBO
3698*c8dee2aaSAndroid Build Coastguard Worker     fHWBoundRenderTargetUniqueID.makeInvalid();
3699*c8dee2aaSAndroid Build Coastguard Worker 
3700*c8dee2aaSAndroid Build Coastguard Worker     this->bindTextureToScratchUnit(dstTex->target(), dstTex->textureID());
3701*c8dee2aaSAndroid Build Coastguard Worker     GL_CALL(CopyTexSubImage2D(dstTex->target(), 0,
3702*c8dee2aaSAndroid Build Coastguard Worker                               dstPoint.fX, dstPoint.fY,
3703*c8dee2aaSAndroid Build Coastguard Worker                               srcRect.fLeft, srcRect.fTop,
3704*c8dee2aaSAndroid Build Coastguard Worker                               srcRect.width(), srcRect.height()));
3705*c8dee2aaSAndroid Build Coastguard Worker     this->unbindSurfaceFBOForPixelOps(src, 0, GR_GL_FRAMEBUFFER);
3706*c8dee2aaSAndroid Build Coastguard Worker     SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY,
3707*c8dee2aaSAndroid Build Coastguard Worker                                         srcRect.width(), srcRect.height());
3708*c8dee2aaSAndroid Build Coastguard Worker     // The rect is already in device space so we pass in kTopLeft so no flip is done.
3709*c8dee2aaSAndroid Build Coastguard Worker     this->didWriteToSurface(dst, kTopLeft_GrSurfaceOrigin, &dstRect);
3710*c8dee2aaSAndroid Build Coastguard Worker }
3711*c8dee2aaSAndroid Build Coastguard Worker 
copySurfaceAsBlitFramebuffer(GrSurface * dst,GrSurface * src,const SkIRect & srcRect,const SkIRect & dstRect,GrSamplerState::Filter filter)3712*c8dee2aaSAndroid Build Coastguard Worker bool GrGLGpu::copySurfaceAsBlitFramebuffer(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
3713*c8dee2aaSAndroid Build Coastguard Worker                                            const SkIRect& dstRect, GrSamplerState::Filter filter) {
3714*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(can_blit_framebuffer_for_copy_surface(dst, src, srcRect, dstRect, this->glCaps()));
3715*c8dee2aaSAndroid Build Coastguard Worker     if (dst == src) {
3716*c8dee2aaSAndroid Build Coastguard Worker         if (SkIRect::Intersects(dstRect, srcRect)) {
3717*c8dee2aaSAndroid Build Coastguard Worker             return false;
3718*c8dee2aaSAndroid Build Coastguard Worker         }
3719*c8dee2aaSAndroid Build Coastguard Worker     }
3720*c8dee2aaSAndroid Build Coastguard Worker 
3721*c8dee2aaSAndroid Build Coastguard Worker     this->bindSurfaceFBOForPixelOps(dst, 0, GR_GL_DRAW_FRAMEBUFFER, kDst_TempFBOTarget);
3722*c8dee2aaSAndroid Build Coastguard Worker     this->bindSurfaceFBOForPixelOps(src, 0, GR_GL_READ_FRAMEBUFFER, kSrc_TempFBOTarget);
3723*c8dee2aaSAndroid Build Coastguard Worker     // We modified the bound FBO
3724*c8dee2aaSAndroid Build Coastguard Worker     fHWBoundRenderTargetUniqueID.makeInvalid();
3725*c8dee2aaSAndroid Build Coastguard Worker 
3726*c8dee2aaSAndroid Build Coastguard Worker     // BlitFrameBuffer respects the scissor, so disable it.
3727*c8dee2aaSAndroid Build Coastguard Worker     this->flushScissorTest(GrScissorTest::kDisabled);
3728*c8dee2aaSAndroid Build Coastguard Worker     this->disableWindowRectangles();
3729*c8dee2aaSAndroid Build Coastguard Worker 
3730*c8dee2aaSAndroid Build Coastguard Worker     GL_CALL(BlitFramebuffer(srcRect.fLeft,
3731*c8dee2aaSAndroid Build Coastguard Worker                             srcRect.fTop,
3732*c8dee2aaSAndroid Build Coastguard Worker                             srcRect.fRight,
3733*c8dee2aaSAndroid Build Coastguard Worker                             srcRect.fBottom,
3734*c8dee2aaSAndroid Build Coastguard Worker                             dstRect.fLeft,
3735*c8dee2aaSAndroid Build Coastguard Worker                             dstRect.fTop,
3736*c8dee2aaSAndroid Build Coastguard Worker                             dstRect.fRight,
3737*c8dee2aaSAndroid Build Coastguard Worker                             dstRect.fBottom,
3738*c8dee2aaSAndroid Build Coastguard Worker                             GR_GL_COLOR_BUFFER_BIT,
3739*c8dee2aaSAndroid Build Coastguard Worker                             filter_to_gl_mag_filter(filter)));
3740*c8dee2aaSAndroid Build Coastguard Worker     this->unbindSurfaceFBOForPixelOps(dst, 0, GR_GL_DRAW_FRAMEBUFFER);
3741*c8dee2aaSAndroid Build Coastguard Worker     this->unbindSurfaceFBOForPixelOps(src, 0, GR_GL_READ_FRAMEBUFFER);
3742*c8dee2aaSAndroid Build Coastguard Worker 
3743*c8dee2aaSAndroid Build Coastguard Worker     // The rect is already in device space so we pass in kTopLeft so no flip is done.
3744*c8dee2aaSAndroid Build Coastguard Worker     this->didWriteToSurface(dst, kTopLeft_GrSurfaceOrigin, &dstRect);
3745*c8dee2aaSAndroid Build Coastguard Worker     return true;
3746*c8dee2aaSAndroid Build Coastguard Worker }
3747*c8dee2aaSAndroid Build Coastguard Worker 
onRegenerateMipMapLevels(GrTexture * texture)3748*c8dee2aaSAndroid Build Coastguard Worker bool GrGLGpu::onRegenerateMipMapLevels(GrTexture* texture) {
3749*c8dee2aaSAndroid Build Coastguard Worker     using RegenerateMipmapType = GrGLCaps::RegenerateMipmapType;
3750*c8dee2aaSAndroid Build Coastguard Worker 
3751*c8dee2aaSAndroid Build Coastguard Worker     auto glTex = static_cast<GrGLTexture*>(texture);
3752*c8dee2aaSAndroid Build Coastguard Worker     // Mipmaps are only supported on 2D textures:
3753*c8dee2aaSAndroid Build Coastguard Worker     if (GR_GL_TEXTURE_2D != glTex->target()) {
3754*c8dee2aaSAndroid Build Coastguard Worker         return false;
3755*c8dee2aaSAndroid Build Coastguard Worker     }
3756*c8dee2aaSAndroid Build Coastguard Worker     GrGLFormat format = glTex->format();
3757*c8dee2aaSAndroid Build Coastguard Worker     // Manual implementation of mipmap generation, to work around driver bugs w/sRGB.
3758*c8dee2aaSAndroid Build Coastguard Worker     // Uses draw calls to do a series of downsample operations to successive mips.
3759*c8dee2aaSAndroid Build Coastguard Worker 
3760*c8dee2aaSAndroid Build Coastguard Worker     // The manual approach requires the ability to limit which level we're sampling and that the
3761*c8dee2aaSAndroid Build Coastguard Worker     // destination can be bound to a FBO:
3762*c8dee2aaSAndroid Build Coastguard Worker     if (!this->glCaps().doManualMipmapping() || !this->glCaps().isFormatRenderable(format, 1)) {
3763*c8dee2aaSAndroid Build Coastguard Worker         GrGLenum target = glTex->target();
3764*c8dee2aaSAndroid Build Coastguard Worker         this->bindTextureToScratchUnit(target, glTex->textureID());
3765*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(GenerateMipmap(glTex->target()));
3766*c8dee2aaSAndroid Build Coastguard Worker         return true;
3767*c8dee2aaSAndroid Build Coastguard Worker     }
3768*c8dee2aaSAndroid Build Coastguard Worker 
3769*c8dee2aaSAndroid Build Coastguard Worker     int width = texture->width();
3770*c8dee2aaSAndroid Build Coastguard Worker     int height = texture->height();
3771*c8dee2aaSAndroid Build Coastguard Worker     int levelCount = SkMipmap::ComputeLevelCount(width, height) + 1;
3772*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(levelCount == texture->maxMipmapLevel() + 1);
3773*c8dee2aaSAndroid Build Coastguard Worker 
3774*c8dee2aaSAndroid Build Coastguard Worker     // Create (if necessary), then bind temporary FBO:
3775*c8dee2aaSAndroid Build Coastguard Worker     if (0 == fTempDstFBOID) {
3776*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(GenFramebuffers(1, &fTempDstFBOID));
3777*c8dee2aaSAndroid Build Coastguard Worker     }
3778*c8dee2aaSAndroid Build Coastguard Worker     this->bindFramebuffer(GR_GL_FRAMEBUFFER, fTempDstFBOID);
3779*c8dee2aaSAndroid Build Coastguard Worker     fHWBoundRenderTargetUniqueID.makeInvalid();
3780*c8dee2aaSAndroid Build Coastguard Worker 
3781*c8dee2aaSAndroid Build Coastguard Worker     // Bind the texture, to get things configured for filtering.
3782*c8dee2aaSAndroid Build Coastguard Worker     // We'll be changing our base level and max level further below:
3783*c8dee2aaSAndroid Build Coastguard Worker     this->setTextureUnit(0);
3784*c8dee2aaSAndroid Build Coastguard Worker     // The mipmap program does not do any swizzling.
3785*c8dee2aaSAndroid Build Coastguard Worker     this->bindTexture(0, GrSamplerState::Filter::kLinear, skgpu::Swizzle::RGBA(), glTex);
3786*c8dee2aaSAndroid Build Coastguard Worker 
3787*c8dee2aaSAndroid Build Coastguard Worker     // Vertex data:
3788*c8dee2aaSAndroid Build Coastguard Worker     if (!fMipmapProgramArrayBuffer) {
3789*c8dee2aaSAndroid Build Coastguard Worker         static const GrGLfloat vdata[] = {
3790*c8dee2aaSAndroid Build Coastguard Worker             0, 0,
3791*c8dee2aaSAndroid Build Coastguard Worker             0, 1,
3792*c8dee2aaSAndroid Build Coastguard Worker             1, 0,
3793*c8dee2aaSAndroid Build Coastguard Worker             1, 1
3794*c8dee2aaSAndroid Build Coastguard Worker         };
3795*c8dee2aaSAndroid Build Coastguard Worker         fMipmapProgramArrayBuffer = GrGLBuffer::Make(this,
3796*c8dee2aaSAndroid Build Coastguard Worker                                                      sizeof(vdata),
3797*c8dee2aaSAndroid Build Coastguard Worker                                                      GrGpuBufferType::kVertex,
3798*c8dee2aaSAndroid Build Coastguard Worker                                                      kStatic_GrAccessPattern);
3799*c8dee2aaSAndroid Build Coastguard Worker         fMipmapProgramArrayBuffer->updateData(vdata, /*offset=*/0,
3800*c8dee2aaSAndroid Build Coastguard Worker 
3801*c8dee2aaSAndroid Build Coastguard Worker                                               sizeof(vdata),
3802*c8dee2aaSAndroid Build Coastguard Worker                                               /*preserve=*/false);
3803*c8dee2aaSAndroid Build Coastguard Worker     }
3804*c8dee2aaSAndroid Build Coastguard Worker     if (!fMipmapProgramArrayBuffer) {
3805*c8dee2aaSAndroid Build Coastguard Worker         return false;
3806*c8dee2aaSAndroid Build Coastguard Worker     }
3807*c8dee2aaSAndroid Build Coastguard Worker 
3808*c8dee2aaSAndroid Build Coastguard Worker     fHWVertexArrayState.setVertexArrayID(this, 0);
3809*c8dee2aaSAndroid Build Coastguard Worker 
3810*c8dee2aaSAndroid Build Coastguard Worker     GrGLAttribArrayState* attribs = fHWVertexArrayState.bindInternalVertexArray(this);
3811*c8dee2aaSAndroid Build Coastguard Worker     attribs->enableVertexArrays(this, 1);
3812*c8dee2aaSAndroid Build Coastguard Worker     attribs->set(this, 0, fMipmapProgramArrayBuffer.get(), kFloat2_GrVertexAttribType,
3813*c8dee2aaSAndroid Build Coastguard Worker                  SkSLType::kFloat2, 2 * sizeof(GrGLfloat), 0);
3814*c8dee2aaSAndroid Build Coastguard Worker 
3815*c8dee2aaSAndroid Build Coastguard Worker     // Set "simple" state once:
3816*c8dee2aaSAndroid Build Coastguard Worker     this->flushBlendAndColorWrite(skgpu::BlendInfo(), skgpu::Swizzle::RGBA());
3817*c8dee2aaSAndroid Build Coastguard Worker     this->flushScissorTest(GrScissorTest::kDisabled);
3818*c8dee2aaSAndroid Build Coastguard Worker     this->disableWindowRectangles();
3819*c8dee2aaSAndroid Build Coastguard Worker     this->disableStencil();
3820*c8dee2aaSAndroid Build Coastguard Worker 
3821*c8dee2aaSAndroid Build Coastguard Worker     // Do all the blits:
3822*c8dee2aaSAndroid Build Coastguard Worker     width = texture->width();
3823*c8dee2aaSAndroid Build Coastguard Worker     height = texture->height();
3824*c8dee2aaSAndroid Build Coastguard Worker 
3825*c8dee2aaSAndroid Build Coastguard Worker     std::unique_ptr<GrSemaphore> semaphore;
3826*c8dee2aaSAndroid Build Coastguard Worker     for (GrGLint level = 1; level < levelCount; ++level) {
3827*c8dee2aaSAndroid Build Coastguard Worker         // Get and bind the program for this particular downsample (filter shape can vary):
3828*c8dee2aaSAndroid Build Coastguard Worker         int progIdx = TextureSizeToMipmapProgramIdx(width, height);
3829*c8dee2aaSAndroid Build Coastguard Worker         if (!fMipmapPrograms[progIdx].fProgram) {
3830*c8dee2aaSAndroid Build Coastguard Worker             if (!this->createMipmapProgram(progIdx)) {
3831*c8dee2aaSAndroid Build Coastguard Worker                 SkDebugf("Failed to create mipmap program.\n");
3832*c8dee2aaSAndroid Build Coastguard Worker                 // Invalidate all params to cover base and max level change in a previous iteration.
3833*c8dee2aaSAndroid Build Coastguard Worker                 glTex->textureParamsModified();
3834*c8dee2aaSAndroid Build Coastguard Worker                 return false;
3835*c8dee2aaSAndroid Build Coastguard Worker             }
3836*c8dee2aaSAndroid Build Coastguard Worker         }
3837*c8dee2aaSAndroid Build Coastguard Worker         this->flushProgram(fMipmapPrograms[progIdx].fProgram);
3838*c8dee2aaSAndroid Build Coastguard Worker 
3839*c8dee2aaSAndroid Build Coastguard Worker         if (this->glCaps().regenerateMipmapType() == RegenerateMipmapType::kBasePlusSync &&
3840*c8dee2aaSAndroid Build Coastguard Worker             level > 1) {
3841*c8dee2aaSAndroid Build Coastguard Worker             this->waitSemaphore(semaphore.get());
3842*c8dee2aaSAndroid Build Coastguard Worker             semaphore.reset();
3843*c8dee2aaSAndroid Build Coastguard Worker         }
3844*c8dee2aaSAndroid Build Coastguard Worker 
3845*c8dee2aaSAndroid Build Coastguard Worker         // Texcoord uniform is expected to contain (1/w, (w-1)/w, 1/h, (h-1)/h)
3846*c8dee2aaSAndroid Build Coastguard Worker         const float invWidth = 1.0f / width;
3847*c8dee2aaSAndroid Build Coastguard Worker         const float invHeight = 1.0f / height;
3848*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(Uniform4f(fMipmapPrograms[progIdx].fTexCoordXformUniform,
3849*c8dee2aaSAndroid Build Coastguard Worker                           invWidth, (width - 1) * invWidth, invHeight, (height - 1) * invHeight));
3850*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(Uniform1i(fMipmapPrograms[progIdx].fTextureUniform, 0));
3851*c8dee2aaSAndroid Build Coastguard Worker 
3852*c8dee2aaSAndroid Build Coastguard Worker         // Set the base level so that we only sample from the previous mip.
3853*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(this->glCaps().mipmapLevelControlSupport());
3854*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_BASE_LEVEL, level - 1));
3855*c8dee2aaSAndroid Build Coastguard Worker         // Setting the max level is technically unnecessary and can affect
3856*c8dee2aaSAndroid Build Coastguard Worker         // validation for the framebuffer. However, by making it clear that a
3857*c8dee2aaSAndroid Build Coastguard Worker         // rendering feedback loop is not occurring, we avoid hitting a slow
3858*c8dee2aaSAndroid Build Coastguard Worker         // path on some drivers.
3859*c8dee2aaSAndroid Build Coastguard Worker         if (this->glCaps().regenerateMipmapType() == RegenerateMipmapType::kBasePlusMaxLevel) {
3860*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_MAX_LEVEL, level - 1));
3861*c8dee2aaSAndroid Build Coastguard Worker         }
3862*c8dee2aaSAndroid Build Coastguard Worker 
3863*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(FramebufferTexture2D(GR_GL_FRAMEBUFFER, GR_GL_COLOR_ATTACHMENT0, GR_GL_TEXTURE_2D,
3864*c8dee2aaSAndroid Build Coastguard Worker                                      glTex->textureID(), level));
3865*c8dee2aaSAndroid Build Coastguard Worker 
3866*c8dee2aaSAndroid Build Coastguard Worker         width = std::max(1, width / 2);
3867*c8dee2aaSAndroid Build Coastguard Worker         height = std::max(1, height / 2);
3868*c8dee2aaSAndroid Build Coastguard Worker         this->flushViewport(SkIRect::MakeWH(width, height), height, kTopLeft_GrSurfaceOrigin);
3869*c8dee2aaSAndroid Build Coastguard Worker 
3870*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(DrawArrays(GR_GL_TRIANGLE_STRIP, 0, 4));
3871*c8dee2aaSAndroid Build Coastguard Worker 
3872*c8dee2aaSAndroid Build Coastguard Worker         if (this->glCaps().regenerateMipmapType() == RegenerateMipmapType::kBasePlusSync &&
3873*c8dee2aaSAndroid Build Coastguard Worker             level < levelCount-1) {
3874*c8dee2aaSAndroid Build Coastguard Worker             semaphore = this->makeSemaphore(true);
3875*c8dee2aaSAndroid Build Coastguard Worker             this->insertSemaphore(semaphore.get());
3876*c8dee2aaSAndroid Build Coastguard Worker         }
3877*c8dee2aaSAndroid Build Coastguard Worker     }
3878*c8dee2aaSAndroid Build Coastguard Worker 
3879*c8dee2aaSAndroid Build Coastguard Worker     // Unbind:
3880*c8dee2aaSAndroid Build Coastguard Worker     GL_CALL(FramebufferTexture2D(GR_GL_FRAMEBUFFER, GR_GL_COLOR_ATTACHMENT0,
3881*c8dee2aaSAndroid Build Coastguard Worker                                  GR_GL_TEXTURE_2D, 0, 0));
3882*c8dee2aaSAndroid Build Coastguard Worker 
3883*c8dee2aaSAndroid Build Coastguard Worker     // We modified the base level and max level params.
3884*c8dee2aaSAndroid Build Coastguard Worker     GrGLTextureParameters::NonsamplerState nonsamplerState = glTex->parameters()->nonsamplerState();
3885*c8dee2aaSAndroid Build Coastguard Worker     // We drew the 2nd to last level into the last level.
3886*c8dee2aaSAndroid Build Coastguard Worker     nonsamplerState.fBaseMipMapLevel = levelCount - 2;
3887*c8dee2aaSAndroid Build Coastguard Worker     if (this->glCaps().regenerateMipmapType() == RegenerateMipmapType::kBasePlusMaxLevel) {
3888*c8dee2aaSAndroid Build Coastguard Worker         nonsamplerState.fMaxMipmapLevel = levelCount - 2;
3889*c8dee2aaSAndroid Build Coastguard Worker     }
3890*c8dee2aaSAndroid Build Coastguard Worker     glTex->parameters()->set(nullptr, nonsamplerState, fResetTimestampForTextureParameters);
3891*c8dee2aaSAndroid Build Coastguard Worker 
3892*c8dee2aaSAndroid Build Coastguard Worker     return true;
3893*c8dee2aaSAndroid Build Coastguard Worker }
3894*c8dee2aaSAndroid Build Coastguard Worker 
xferBarrier(GrRenderTarget * rt,GrXferBarrierType type)3895*c8dee2aaSAndroid Build Coastguard Worker void GrGLGpu::xferBarrier(GrRenderTarget* rt, GrXferBarrierType type) {
3896*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(type);
3897*c8dee2aaSAndroid Build Coastguard Worker     switch (type) {
3898*c8dee2aaSAndroid Build Coastguard Worker         case kTexture_GrXferBarrierType: {
3899*c8dee2aaSAndroid Build Coastguard Worker             GrGLRenderTarget* glrt = static_cast<GrGLRenderTarget*>(rt);
3900*c8dee2aaSAndroid Build Coastguard Worker             SkASSERT(glrt->asTexture());
3901*c8dee2aaSAndroid Build Coastguard Worker             SkASSERT(!glrt->isFBO0(false/*multisample*/));
3902*c8dee2aaSAndroid Build Coastguard Worker             if (glrt->requiresManualMSAAResolve()) {
3903*c8dee2aaSAndroid Build Coastguard Worker                 // The render target uses separate storage so no need for glTextureBarrier.
3904*c8dee2aaSAndroid Build Coastguard Worker                 // FIXME: The render target will resolve automatically when its texture is bound,
3905*c8dee2aaSAndroid Build Coastguard Worker                 // but we could resolve only the bounds that will be read if we do it here instead.
3906*c8dee2aaSAndroid Build Coastguard Worker                 return;
3907*c8dee2aaSAndroid Build Coastguard Worker             }
3908*c8dee2aaSAndroid Build Coastguard Worker             SkASSERT(this->caps()->textureBarrierSupport());
3909*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(TextureBarrier());
3910*c8dee2aaSAndroid Build Coastguard Worker             return;
3911*c8dee2aaSAndroid Build Coastguard Worker         }
3912*c8dee2aaSAndroid Build Coastguard Worker         case kBlend_GrXferBarrierType:
3913*c8dee2aaSAndroid Build Coastguard Worker             SkASSERT(GrCaps::kAdvanced_BlendEquationSupport ==
3914*c8dee2aaSAndroid Build Coastguard Worker                      this->caps()->blendEquationSupport());
3915*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(BlendBarrier());
3916*c8dee2aaSAndroid Build Coastguard Worker             return;
3917*c8dee2aaSAndroid Build Coastguard Worker         default: break; // placate compiler warnings that kNone not handled
3918*c8dee2aaSAndroid Build Coastguard Worker     }
3919*c8dee2aaSAndroid Build Coastguard Worker }
3920*c8dee2aaSAndroid Build Coastguard Worker 
onCreateBackendTexture(SkISize dimensions,const GrBackendFormat & format,GrRenderable renderable,skgpu::Mipmapped mipmapped,GrProtected isProtected,std::string_view label)3921*c8dee2aaSAndroid Build Coastguard Worker GrBackendTexture GrGLGpu::onCreateBackendTexture(SkISize dimensions,
3922*c8dee2aaSAndroid Build Coastguard Worker                                                  const GrBackendFormat& format,
3923*c8dee2aaSAndroid Build Coastguard Worker                                                  GrRenderable renderable,
3924*c8dee2aaSAndroid Build Coastguard Worker                                                  skgpu::Mipmapped mipmapped,
3925*c8dee2aaSAndroid Build Coastguard Worker                                                  GrProtected isProtected,
3926*c8dee2aaSAndroid Build Coastguard Worker                                                  std::string_view label) {
3927*c8dee2aaSAndroid Build Coastguard Worker     this->handleDirtyContext();
3928*c8dee2aaSAndroid Build Coastguard Worker 
3929*c8dee2aaSAndroid Build Coastguard Worker     if (isProtected == GrProtected::kYes && !this->glCaps().supportsProtectedContent()) {
3930*c8dee2aaSAndroid Build Coastguard Worker         return {};
3931*c8dee2aaSAndroid Build Coastguard Worker     }
3932*c8dee2aaSAndroid Build Coastguard Worker 
3933*c8dee2aaSAndroid Build Coastguard Worker     GrGLFormat glFormat = GrBackendFormats::AsGLFormat(format);
3934*c8dee2aaSAndroid Build Coastguard Worker     if (glFormat == GrGLFormat::kUnknown) {
3935*c8dee2aaSAndroid Build Coastguard Worker         return {};
3936*c8dee2aaSAndroid Build Coastguard Worker     }
3937*c8dee2aaSAndroid Build Coastguard Worker 
3938*c8dee2aaSAndroid Build Coastguard Worker     int numMipLevels = 1;
3939*c8dee2aaSAndroid Build Coastguard Worker     if (mipmapped == skgpu::Mipmapped::kYes) {
3940*c8dee2aaSAndroid Build Coastguard Worker         numMipLevels = SkMipmap::ComputeLevelCount(dimensions.width(), dimensions.height()) + 1;
3941*c8dee2aaSAndroid Build Coastguard Worker     }
3942*c8dee2aaSAndroid Build Coastguard Worker 
3943*c8dee2aaSAndroid Build Coastguard Worker     // Compressed formats go through onCreateCompressedBackendTexture
3944*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!GrGLFormatIsCompressed(glFormat));
3945*c8dee2aaSAndroid Build Coastguard Worker 
3946*c8dee2aaSAndroid Build Coastguard Worker     GrGLTextureInfo info;
3947*c8dee2aaSAndroid Build Coastguard Worker     GrGLTextureParameters::SamplerOverriddenState initialState;
3948*c8dee2aaSAndroid Build Coastguard Worker 
3949*c8dee2aaSAndroid Build Coastguard Worker     if (glFormat == GrGLFormat::kUnknown) {
3950*c8dee2aaSAndroid Build Coastguard Worker         return {};
3951*c8dee2aaSAndroid Build Coastguard Worker     }
3952*c8dee2aaSAndroid Build Coastguard Worker     switch (format.textureType()) {
3953*c8dee2aaSAndroid Build Coastguard Worker         case GrTextureType::kNone:
3954*c8dee2aaSAndroid Build Coastguard Worker         case GrTextureType::kExternal:
3955*c8dee2aaSAndroid Build Coastguard Worker             return {};
3956*c8dee2aaSAndroid Build Coastguard Worker         case GrTextureType::k2D:
3957*c8dee2aaSAndroid Build Coastguard Worker             info.fTarget = GR_GL_TEXTURE_2D;
3958*c8dee2aaSAndroid Build Coastguard Worker             break;
3959*c8dee2aaSAndroid Build Coastguard Worker         case GrTextureType::kRectangle:
3960*c8dee2aaSAndroid Build Coastguard Worker             if (!this->glCaps().rectangleTextureSupport() || mipmapped == skgpu::Mipmapped::kYes) {
3961*c8dee2aaSAndroid Build Coastguard Worker                 return {};
3962*c8dee2aaSAndroid Build Coastguard Worker             }
3963*c8dee2aaSAndroid Build Coastguard Worker             info.fTarget = GR_GL_TEXTURE_RECTANGLE;
3964*c8dee2aaSAndroid Build Coastguard Worker             break;
3965*c8dee2aaSAndroid Build Coastguard Worker     }
3966*c8dee2aaSAndroid Build Coastguard Worker     info.fProtected = skgpu::Protected(isProtected == skgpu::Protected::kYes ||
3967*c8dee2aaSAndroid Build Coastguard Worker                                        this->glCaps().strictProtectedness());
3968*c8dee2aaSAndroid Build Coastguard Worker     info.fFormat = GrGLFormatToEnum(glFormat);
3969*c8dee2aaSAndroid Build Coastguard Worker     info.fID = this->createTexture(dimensions, glFormat, info.fTarget, renderable, &initialState,
3970*c8dee2aaSAndroid Build Coastguard Worker                                    numMipLevels, info.fProtected, label);
3971*c8dee2aaSAndroid Build Coastguard Worker     if (!info.fID) {
3972*c8dee2aaSAndroid Build Coastguard Worker         return {};
3973*c8dee2aaSAndroid Build Coastguard Worker     }
3974*c8dee2aaSAndroid Build Coastguard Worker 
3975*c8dee2aaSAndroid Build Coastguard Worker     // Unbind this texture from the scratch texture unit.
3976*c8dee2aaSAndroid Build Coastguard Worker     this->bindTextureToScratchUnit(info.fTarget, 0);
3977*c8dee2aaSAndroid Build Coastguard Worker 
3978*c8dee2aaSAndroid Build Coastguard Worker     auto parameters = sk_make_sp<GrGLTextureParameters>();
3979*c8dee2aaSAndroid Build Coastguard Worker     // The non-sampler params are still at their default values.
3980*c8dee2aaSAndroid Build Coastguard Worker     parameters->set(&initialState, GrGLTextureParameters::NonsamplerState(),
3981*c8dee2aaSAndroid Build Coastguard Worker                     fResetTimestampForTextureParameters);
3982*c8dee2aaSAndroid Build Coastguard Worker 
3983*c8dee2aaSAndroid Build Coastguard Worker     return GrBackendTextures::MakeGL(
3984*c8dee2aaSAndroid Build Coastguard Worker             dimensions.width(), dimensions.height(), mipmapped, info, std::move(parameters), label);
3985*c8dee2aaSAndroid Build Coastguard Worker }
3986*c8dee2aaSAndroid Build Coastguard Worker 
onClearBackendTexture(const GrBackendTexture & backendTexture,sk_sp<skgpu::RefCntedCallback> finishedCallback,std::array<float,4> color)3987*c8dee2aaSAndroid Build Coastguard Worker bool GrGLGpu::onClearBackendTexture(const GrBackendTexture& backendTexture,
3988*c8dee2aaSAndroid Build Coastguard Worker                                     sk_sp<skgpu::RefCntedCallback> finishedCallback,
3989*c8dee2aaSAndroid Build Coastguard Worker                                     std::array<float, 4> color) {
3990*c8dee2aaSAndroid Build Coastguard Worker     this->handleDirtyContext();
3991*c8dee2aaSAndroid Build Coastguard Worker 
3992*c8dee2aaSAndroid Build Coastguard Worker     GrGLTextureInfo info;
3993*c8dee2aaSAndroid Build Coastguard Worker     SkAssertResult(GrBackendTextures::GetGLTextureInfo(backendTexture, &info));
3994*c8dee2aaSAndroid Build Coastguard Worker 
3995*c8dee2aaSAndroid Build Coastguard Worker     int numMipLevels = 1;
3996*c8dee2aaSAndroid Build Coastguard Worker     if (backendTexture.hasMipmaps()) {
3997*c8dee2aaSAndroid Build Coastguard Worker         numMipLevels =
3998*c8dee2aaSAndroid Build Coastguard Worker                 SkMipmap::ComputeLevelCount(backendTexture.width(), backendTexture.height()) + 1;
3999*c8dee2aaSAndroid Build Coastguard Worker     }
4000*c8dee2aaSAndroid Build Coastguard Worker 
4001*c8dee2aaSAndroid Build Coastguard Worker     GrGLFormat glFormat = GrGLFormatFromGLEnum(info.fFormat);
4002*c8dee2aaSAndroid Build Coastguard Worker 
4003*c8dee2aaSAndroid Build Coastguard Worker     this->bindTextureToScratchUnit(info.fTarget, info.fID);
4004*c8dee2aaSAndroid Build Coastguard Worker 
4005*c8dee2aaSAndroid Build Coastguard Worker     // If we have mips make sure the base level is set to 0 and the max level set to numMipLevels-1
4006*c8dee2aaSAndroid Build Coastguard Worker     // so that the uploads go to the right levels.
4007*c8dee2aaSAndroid Build Coastguard Worker     if (numMipLevels && this->glCaps().mipmapLevelControlSupport()) {
4008*c8dee2aaSAndroid Build Coastguard Worker         auto params = get_gl_texture_params(backendTexture);
4009*c8dee2aaSAndroid Build Coastguard Worker         GrGLTextureParameters::NonsamplerState nonsamplerState = params->nonsamplerState();
4010*c8dee2aaSAndroid Build Coastguard Worker         if (params->nonsamplerState().fBaseMipMapLevel != 0) {
4011*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(TexParameteri(info.fTarget, GR_GL_TEXTURE_BASE_LEVEL, 0));
4012*c8dee2aaSAndroid Build Coastguard Worker             nonsamplerState.fBaseMipMapLevel = 0;
4013*c8dee2aaSAndroid Build Coastguard Worker         }
4014*c8dee2aaSAndroid Build Coastguard Worker         if (params->nonsamplerState().fMaxMipmapLevel != (numMipLevels - 1)) {
4015*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(TexParameteri(info.fTarget, GR_GL_TEXTURE_MAX_LEVEL, numMipLevels - 1));
4016*c8dee2aaSAndroid Build Coastguard Worker             nonsamplerState.fBaseMipMapLevel = numMipLevels - 1;
4017*c8dee2aaSAndroid Build Coastguard Worker         }
4018*c8dee2aaSAndroid Build Coastguard Worker         params->set(nullptr, nonsamplerState, fResetTimestampForTextureParameters);
4019*c8dee2aaSAndroid Build Coastguard Worker     }
4020*c8dee2aaSAndroid Build Coastguard Worker 
4021*c8dee2aaSAndroid Build Coastguard Worker     uint32_t levelMask = (1 << numMipLevels) - 1;
4022*c8dee2aaSAndroid Build Coastguard Worker     bool result = this->uploadColorToTex(glFormat,
4023*c8dee2aaSAndroid Build Coastguard Worker                                          backendTexture.dimensions(),
4024*c8dee2aaSAndroid Build Coastguard Worker                                          info.fTarget,
4025*c8dee2aaSAndroid Build Coastguard Worker                                          color,
4026*c8dee2aaSAndroid Build Coastguard Worker                                          levelMask);
4027*c8dee2aaSAndroid Build Coastguard Worker 
4028*c8dee2aaSAndroid Build Coastguard Worker     // Unbind this texture from the scratch texture unit.
4029*c8dee2aaSAndroid Build Coastguard Worker     this->bindTextureToScratchUnit(info.fTarget, 0);
4030*c8dee2aaSAndroid Build Coastguard Worker     return result;
4031*c8dee2aaSAndroid Build Coastguard Worker }
4032*c8dee2aaSAndroid Build Coastguard Worker 
deleteBackendTexture(const GrBackendTexture & tex)4033*c8dee2aaSAndroid Build Coastguard Worker void GrGLGpu::deleteBackendTexture(const GrBackendTexture& tex) {
4034*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(GrBackendApi::kOpenGL == tex.backend());
4035*c8dee2aaSAndroid Build Coastguard Worker 
4036*c8dee2aaSAndroid Build Coastguard Worker     GrGLTextureInfo info;
4037*c8dee2aaSAndroid Build Coastguard Worker     if (GrBackendTextures::GetGLTextureInfo(tex, &info)) {
4038*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(DeleteTextures(1, &info.fID));
4039*c8dee2aaSAndroid Build Coastguard Worker     }
4040*c8dee2aaSAndroid Build Coastguard Worker }
4041*c8dee2aaSAndroid Build Coastguard Worker 
compile(const GrProgramDesc & desc,const GrProgramInfo & programInfo)4042*c8dee2aaSAndroid Build Coastguard Worker bool GrGLGpu::compile(const GrProgramDesc& desc, const GrProgramInfo& programInfo) {
4043*c8dee2aaSAndroid Build Coastguard Worker     GrThreadSafePipelineBuilder::Stats::ProgramCacheResult stat;
4044*c8dee2aaSAndroid Build Coastguard Worker 
4045*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<GrGLProgram> tmp = fProgramCache->findOrCreateProgram(this->getContext(),
4046*c8dee2aaSAndroid Build Coastguard Worker                                                                 desc, programInfo, &stat);
4047*c8dee2aaSAndroid Build Coastguard Worker     if (!tmp) {
4048*c8dee2aaSAndroid Build Coastguard Worker         return false;
4049*c8dee2aaSAndroid Build Coastguard Worker     }
4050*c8dee2aaSAndroid Build Coastguard Worker 
4051*c8dee2aaSAndroid Build Coastguard Worker     return stat != GrThreadSafePipelineBuilder::Stats::ProgramCacheResult::kHit;
4052*c8dee2aaSAndroid Build Coastguard Worker }
4053*c8dee2aaSAndroid Build Coastguard Worker 
4054*c8dee2aaSAndroid Build Coastguard Worker #if defined(GPU_TEST_UTILS)
4055*c8dee2aaSAndroid Build Coastguard Worker 
isTestingOnlyBackendTexture(const GrBackendTexture & tex) const4056*c8dee2aaSAndroid Build Coastguard Worker bool GrGLGpu::isTestingOnlyBackendTexture(const GrBackendTexture& tex) const {
4057*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(GrBackendApi::kOpenGL == tex.backend());
4058*c8dee2aaSAndroid Build Coastguard Worker 
4059*c8dee2aaSAndroid Build Coastguard Worker     GrGLTextureInfo info;
4060*c8dee2aaSAndroid Build Coastguard Worker     if (!GrBackendTextures::GetGLTextureInfo(tex, &info)) {
4061*c8dee2aaSAndroid Build Coastguard Worker         return false;
4062*c8dee2aaSAndroid Build Coastguard Worker     }
4063*c8dee2aaSAndroid Build Coastguard Worker 
4064*c8dee2aaSAndroid Build Coastguard Worker     GrGLboolean result;
4065*c8dee2aaSAndroid Build Coastguard Worker     GL_CALL_RET(result, IsTexture(info.fID));
4066*c8dee2aaSAndroid Build Coastguard Worker 
4067*c8dee2aaSAndroid Build Coastguard Worker     return (GR_GL_TRUE == result);
4068*c8dee2aaSAndroid Build Coastguard Worker }
4069*c8dee2aaSAndroid Build Coastguard Worker 
createTestingOnlyBackendRenderTarget(SkISize dimensions,GrColorType colorType,int sampleCnt,GrProtected isProtected)4070*c8dee2aaSAndroid Build Coastguard Worker GrBackendRenderTarget GrGLGpu::createTestingOnlyBackendRenderTarget(SkISize dimensions,
4071*c8dee2aaSAndroid Build Coastguard Worker                                                                     GrColorType colorType,
4072*c8dee2aaSAndroid Build Coastguard Worker                                                                     int sampleCnt,
4073*c8dee2aaSAndroid Build Coastguard Worker                                                                     GrProtected isProtected) {
4074*c8dee2aaSAndroid Build Coastguard Worker     if (dimensions.width()  > this->caps()->maxRenderTargetSize() ||
4075*c8dee2aaSAndroid Build Coastguard Worker         dimensions.height() > this->caps()->maxRenderTargetSize()) {
4076*c8dee2aaSAndroid Build Coastguard Worker         return {};
4077*c8dee2aaSAndroid Build Coastguard Worker     }
4078*c8dee2aaSAndroid Build Coastguard Worker     if (isProtected == GrProtected::kYes && !this->glCaps().supportsProtectedContent()) {
4079*c8dee2aaSAndroid Build Coastguard Worker         return {};
4080*c8dee2aaSAndroid Build Coastguard Worker     }
4081*c8dee2aaSAndroid Build Coastguard Worker 
4082*c8dee2aaSAndroid Build Coastguard Worker     this->handleDirtyContext();
4083*c8dee2aaSAndroid Build Coastguard Worker     auto format = this->glCaps().getFormatFromColorType(colorType);
4084*c8dee2aaSAndroid Build Coastguard Worker     sampleCnt = this->glCaps().getRenderTargetSampleCount(sampleCnt, format);
4085*c8dee2aaSAndroid Build Coastguard Worker     if (!sampleCnt) {
4086*c8dee2aaSAndroid Build Coastguard Worker         return {};
4087*c8dee2aaSAndroid Build Coastguard Worker     }
4088*c8dee2aaSAndroid Build Coastguard Worker     // We make a texture instead of a render target if we're using a
4089*c8dee2aaSAndroid Build Coastguard Worker     // "multisampled_render_to_texture" style extension or have a BGRA format that
4090*c8dee2aaSAndroid Build Coastguard Worker     // is allowed for textures but not render buffer internal formats.
4091*c8dee2aaSAndroid Build Coastguard Worker     bool useTexture = false;
4092*c8dee2aaSAndroid Build Coastguard Worker     if (sampleCnt > 1 && !this->glCaps().usesMSAARenderBuffers()) {
4093*c8dee2aaSAndroid Build Coastguard Worker         useTexture = true;
4094*c8dee2aaSAndroid Build Coastguard Worker     } else if (format == GrGLFormat::kBGRA8 &&
4095*c8dee2aaSAndroid Build Coastguard Worker         this->glCaps().getRenderbufferInternalFormat(GrGLFormat::kBGRA8) != GR_GL_BGRA8) {
4096*c8dee2aaSAndroid Build Coastguard Worker         // We have a BGRA extension that doesn't support BGRA render buffers. We can use a texture
4097*c8dee2aaSAndroid Build Coastguard Worker         // unless we've been asked for MSAA. Note we already checked above for render-to-
4098*c8dee2aaSAndroid Build Coastguard Worker         // multisampled-texture style extensions.
4099*c8dee2aaSAndroid Build Coastguard Worker         if (sampleCnt > 1) {
4100*c8dee2aaSAndroid Build Coastguard Worker             return {};
4101*c8dee2aaSAndroid Build Coastguard Worker         }
4102*c8dee2aaSAndroid Build Coastguard Worker         useTexture = true;
4103*c8dee2aaSAndroid Build Coastguard Worker     }
4104*c8dee2aaSAndroid Build Coastguard Worker 
4105*c8dee2aaSAndroid Build Coastguard Worker     bool avoidStencil = this->glCaps().avoidStencilBuffers();
4106*c8dee2aaSAndroid Build Coastguard Worker     int sFormatIdx = -1;
4107*c8dee2aaSAndroid Build Coastguard Worker     if (!avoidStencil) {
4108*c8dee2aaSAndroid Build Coastguard Worker         sFormatIdx = this->getCompatibleStencilIndex(format);
4109*c8dee2aaSAndroid Build Coastguard Worker         if (sFormatIdx < 0) {
4110*c8dee2aaSAndroid Build Coastguard Worker             return {};
4111*c8dee2aaSAndroid Build Coastguard Worker         }
4112*c8dee2aaSAndroid Build Coastguard Worker     }
4113*c8dee2aaSAndroid Build Coastguard Worker     GrGLuint colorID = 0;
4114*c8dee2aaSAndroid Build Coastguard Worker     GrGLuint stencilID = 0;
4115*c8dee2aaSAndroid Build Coastguard Worker     GrGLFramebufferInfo info;
4116*c8dee2aaSAndroid Build Coastguard Worker     info.fFBOID = 0;
4117*c8dee2aaSAndroid Build Coastguard Worker     info.fFormat = GrGLFormatToEnum(format);
4118*c8dee2aaSAndroid Build Coastguard Worker     info.fProtected = skgpu::Protected(isProtected == skgpu::Protected::kYes ||
4119*c8dee2aaSAndroid Build Coastguard Worker                                        this->glCaps().strictProtectedness());
4120*c8dee2aaSAndroid Build Coastguard Worker 
4121*c8dee2aaSAndroid Build Coastguard Worker     auto deleteIDs = [&](bool saveFBO = false) {
4122*c8dee2aaSAndroid Build Coastguard Worker         if (colorID) {
4123*c8dee2aaSAndroid Build Coastguard Worker             if (useTexture) {
4124*c8dee2aaSAndroid Build Coastguard Worker                 GL_CALL(DeleteTextures(1, &colorID));
4125*c8dee2aaSAndroid Build Coastguard Worker             } else {
4126*c8dee2aaSAndroid Build Coastguard Worker                 GL_CALL(DeleteRenderbuffers(1, &colorID));
4127*c8dee2aaSAndroid Build Coastguard Worker             }
4128*c8dee2aaSAndroid Build Coastguard Worker         }
4129*c8dee2aaSAndroid Build Coastguard Worker         if (stencilID) {
4130*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(DeleteRenderbuffers(1, &stencilID));
4131*c8dee2aaSAndroid Build Coastguard Worker         }
4132*c8dee2aaSAndroid Build Coastguard Worker         if (!saveFBO && info.fFBOID) {
4133*c8dee2aaSAndroid Build Coastguard Worker             this->deleteFramebuffer(info.fFBOID);
4134*c8dee2aaSAndroid Build Coastguard Worker         }
4135*c8dee2aaSAndroid Build Coastguard Worker     };
4136*c8dee2aaSAndroid Build Coastguard Worker 
4137*c8dee2aaSAndroid Build Coastguard Worker     if (useTexture) {
4138*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(GenTextures(1, &colorID));
4139*c8dee2aaSAndroid Build Coastguard Worker     } else {
4140*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(GenRenderbuffers(1, &colorID));
4141*c8dee2aaSAndroid Build Coastguard Worker     }
4142*c8dee2aaSAndroid Build Coastguard Worker     if (!colorID) {
4143*c8dee2aaSAndroid Build Coastguard Worker         deleteIDs();
4144*c8dee2aaSAndroid Build Coastguard Worker         return {};
4145*c8dee2aaSAndroid Build Coastguard Worker     }
4146*c8dee2aaSAndroid Build Coastguard Worker 
4147*c8dee2aaSAndroid Build Coastguard Worker     if (!avoidStencil) {
4148*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(GenRenderbuffers(1, &stencilID));
4149*c8dee2aaSAndroid Build Coastguard Worker         if (!stencilID) {
4150*c8dee2aaSAndroid Build Coastguard Worker             deleteIDs();
4151*c8dee2aaSAndroid Build Coastguard Worker             return {};
4152*c8dee2aaSAndroid Build Coastguard Worker         }
4153*c8dee2aaSAndroid Build Coastguard Worker     }
4154*c8dee2aaSAndroid Build Coastguard Worker 
4155*c8dee2aaSAndroid Build Coastguard Worker     GL_CALL(GenFramebuffers(1, &info.fFBOID));
4156*c8dee2aaSAndroid Build Coastguard Worker     if (!info.fFBOID) {
4157*c8dee2aaSAndroid Build Coastguard Worker         deleteIDs();
4158*c8dee2aaSAndroid Build Coastguard Worker         return {};
4159*c8dee2aaSAndroid Build Coastguard Worker     }
4160*c8dee2aaSAndroid Build Coastguard Worker 
4161*c8dee2aaSAndroid Build Coastguard Worker     this->invalidateBoundRenderTarget();
4162*c8dee2aaSAndroid Build Coastguard Worker 
4163*c8dee2aaSAndroid Build Coastguard Worker     this->bindFramebuffer(GR_GL_FRAMEBUFFER, info.fFBOID);
4164*c8dee2aaSAndroid Build Coastguard Worker     if (useTexture) {
4165*c8dee2aaSAndroid Build Coastguard Worker         GrGLTextureParameters::SamplerOverriddenState initialState;
4166*c8dee2aaSAndroid Build Coastguard Worker         colorID = this->createTexture(dimensions, format, GR_GL_TEXTURE_2D, GrRenderable::kYes,
4167*c8dee2aaSAndroid Build Coastguard Worker                                       &initialState,
4168*c8dee2aaSAndroid Build Coastguard Worker                                       1,
4169*c8dee2aaSAndroid Build Coastguard Worker                                       info.fProtected,
4170*c8dee2aaSAndroid Build Coastguard Worker                                       /*label=*/"Skia");
4171*c8dee2aaSAndroid Build Coastguard Worker         if (!colorID) {
4172*c8dee2aaSAndroid Build Coastguard Worker             deleteIDs();
4173*c8dee2aaSAndroid Build Coastguard Worker             return {};
4174*c8dee2aaSAndroid Build Coastguard Worker         }
4175*c8dee2aaSAndroid Build Coastguard Worker         if (sampleCnt == 1) {
4176*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(FramebufferTexture2D(GR_GL_FRAMEBUFFER, GR_GL_COLOR_ATTACHMENT0,
4177*c8dee2aaSAndroid Build Coastguard Worker                                          GR_GL_TEXTURE_2D, colorID, 0));
4178*c8dee2aaSAndroid Build Coastguard Worker         } else {
4179*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(FramebufferTexture2DMultisample(GR_GL_FRAMEBUFFER, GR_GL_COLOR_ATTACHMENT0,
4180*c8dee2aaSAndroid Build Coastguard Worker                                                     GR_GL_TEXTURE_2D, colorID, 0, sampleCnt));
4181*c8dee2aaSAndroid Build Coastguard Worker         }
4182*c8dee2aaSAndroid Build Coastguard Worker     } else {
4183*c8dee2aaSAndroid Build Coastguard Worker         GrGLenum renderBufferFormat = this->glCaps().getRenderbufferInternalFormat(format);
4184*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(BindRenderbuffer(GR_GL_RENDERBUFFER, colorID));
4185*c8dee2aaSAndroid Build Coastguard Worker         if (sampleCnt == 1) {
4186*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(RenderbufferStorage(GR_GL_RENDERBUFFER, renderBufferFormat, dimensions.width(),
4187*c8dee2aaSAndroid Build Coastguard Worker                                         dimensions.height()));
4188*c8dee2aaSAndroid Build Coastguard Worker         } else {
4189*c8dee2aaSAndroid Build Coastguard Worker             if (!this->renderbufferStorageMSAA(this->glContext(), sampleCnt, renderBufferFormat,
4190*c8dee2aaSAndroid Build Coastguard Worker                                                dimensions.width(), dimensions.height())) {
4191*c8dee2aaSAndroid Build Coastguard Worker                 deleteIDs();
4192*c8dee2aaSAndroid Build Coastguard Worker                 return {};
4193*c8dee2aaSAndroid Build Coastguard Worker             }
4194*c8dee2aaSAndroid Build Coastguard Worker         }
4195*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, GR_GL_COLOR_ATTACHMENT0,
4196*c8dee2aaSAndroid Build Coastguard Worker                                         GR_GL_RENDERBUFFER, colorID));
4197*c8dee2aaSAndroid Build Coastguard Worker     }
4198*c8dee2aaSAndroid Build Coastguard Worker     if (!avoidStencil) {
4199*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(BindRenderbuffer(GR_GL_RENDERBUFFER, stencilID));
4200*c8dee2aaSAndroid Build Coastguard Worker         auto stencilBufferFormat = this->glCaps().stencilFormats()[sFormatIdx];
4201*c8dee2aaSAndroid Build Coastguard Worker         if (sampleCnt == 1) {
4202*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(RenderbufferStorage(GR_GL_RENDERBUFFER, GrGLFormatToEnum(stencilBufferFormat),
4203*c8dee2aaSAndroid Build Coastguard Worker                                         dimensions.width(), dimensions.height()));
4204*c8dee2aaSAndroid Build Coastguard Worker         } else {
4205*c8dee2aaSAndroid Build Coastguard Worker             if (!this->renderbufferStorageMSAA(this->glContext(), sampleCnt,
4206*c8dee2aaSAndroid Build Coastguard Worker                                                GrGLFormatToEnum(stencilBufferFormat),
4207*c8dee2aaSAndroid Build Coastguard Worker                                                dimensions.width(), dimensions.height())) {
4208*c8dee2aaSAndroid Build Coastguard Worker                 deleteIDs();
4209*c8dee2aaSAndroid Build Coastguard Worker                 return {};
4210*c8dee2aaSAndroid Build Coastguard Worker                                                }
4211*c8dee2aaSAndroid Build Coastguard Worker         }
4212*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
4213*c8dee2aaSAndroid Build Coastguard Worker                                         GR_GL_STENCIL_ATTACHMENT,
4214*c8dee2aaSAndroid Build Coastguard Worker                                         GR_GL_RENDERBUFFER,
4215*c8dee2aaSAndroid Build Coastguard Worker                                         stencilID));
4216*c8dee2aaSAndroid Build Coastguard Worker         if (GrGLFormatIsPackedDepthStencil(this->glCaps().stencilFormats()[sFormatIdx])) {
4217*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, GR_GL_DEPTH_ATTACHMENT,
4218*c8dee2aaSAndroid Build Coastguard Worker                                             GR_GL_RENDERBUFFER, stencilID));
4219*c8dee2aaSAndroid Build Coastguard Worker         }
4220*c8dee2aaSAndroid Build Coastguard Worker     }
4221*c8dee2aaSAndroid Build Coastguard Worker 
4222*c8dee2aaSAndroid Build Coastguard Worker     // We don't want to have to recover the renderbuffer/texture IDs later to delete them. OpenGL
4223*c8dee2aaSAndroid Build Coastguard Worker     // has this rule that if a renderbuffer/texture is deleted and a FBO other than the current FBO
4224*c8dee2aaSAndroid Build Coastguard Worker     // has the RB attached then deletion is delayed. So we unbind the FBO here and delete the
4225*c8dee2aaSAndroid Build Coastguard Worker     // renderbuffers/texture.
4226*c8dee2aaSAndroid Build Coastguard Worker     this->bindFramebuffer(GR_GL_FRAMEBUFFER, 0);
4227*c8dee2aaSAndroid Build Coastguard Worker     deleteIDs(/* saveFBO = */ true);
4228*c8dee2aaSAndroid Build Coastguard Worker 
4229*c8dee2aaSAndroid Build Coastguard Worker     this->bindFramebuffer(GR_GL_FRAMEBUFFER, info.fFBOID);
4230*c8dee2aaSAndroid Build Coastguard Worker     GrGLenum status;
4231*c8dee2aaSAndroid Build Coastguard Worker     GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
4232*c8dee2aaSAndroid Build Coastguard Worker     if (GR_GL_FRAMEBUFFER_COMPLETE != status) {
4233*c8dee2aaSAndroid Build Coastguard Worker         this->deleteFramebuffer(info.fFBOID);
4234*c8dee2aaSAndroid Build Coastguard Worker         return {};
4235*c8dee2aaSAndroid Build Coastguard Worker     }
4236*c8dee2aaSAndroid Build Coastguard Worker 
4237*c8dee2aaSAndroid Build Coastguard Worker     int stencilBits = 0;
4238*c8dee2aaSAndroid Build Coastguard Worker     if (!avoidStencil) {
4239*c8dee2aaSAndroid Build Coastguard Worker         stencilBits = SkToInt(GrGLFormatStencilBits(this->glCaps().stencilFormats()[sFormatIdx]));
4240*c8dee2aaSAndroid Build Coastguard Worker     }
4241*c8dee2aaSAndroid Build Coastguard Worker 
4242*c8dee2aaSAndroid Build Coastguard Worker     GrBackendRenderTarget beRT = GrBackendRenderTargets::MakeGL(
4243*c8dee2aaSAndroid Build Coastguard Worker             dimensions.width(), dimensions.height(), sampleCnt, stencilBits, info);
4244*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(this->caps()->areColorTypeAndFormatCompatible(colorType, beRT.getBackendFormat()));
4245*c8dee2aaSAndroid Build Coastguard Worker     return beRT;
4246*c8dee2aaSAndroid Build Coastguard Worker }
4247*c8dee2aaSAndroid Build Coastguard Worker 
deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget & backendRT)4248*c8dee2aaSAndroid Build Coastguard Worker void GrGLGpu::deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget& backendRT) {
4249*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(GrBackendApi::kOpenGL == backendRT.backend());
4250*c8dee2aaSAndroid Build Coastguard Worker     GrGLFramebufferInfo info;
4251*c8dee2aaSAndroid Build Coastguard Worker     if (GrBackendRenderTargets::GetGLFramebufferInfo(backendRT, &info)) {
4252*c8dee2aaSAndroid Build Coastguard Worker         if (info.fFBOID) {
4253*c8dee2aaSAndroid Build Coastguard Worker             this->deleteFramebuffer(info.fFBOID);
4254*c8dee2aaSAndroid Build Coastguard Worker         }
4255*c8dee2aaSAndroid Build Coastguard Worker     }
4256*c8dee2aaSAndroid Build Coastguard Worker }
4257*c8dee2aaSAndroid Build Coastguard Worker #endif
4258*c8dee2aaSAndroid Build Coastguard Worker 
4259*c8dee2aaSAndroid Build Coastguard Worker ///////////////////////////////////////////////////////////////////////////////
4260*c8dee2aaSAndroid Build Coastguard Worker 
bindInternalVertexArray(GrGLGpu * gpu,const GrBuffer * ibuf)4261*c8dee2aaSAndroid Build Coastguard Worker GrGLAttribArrayState* GrGLGpu::HWVertexArrayState::bindInternalVertexArray(GrGLGpu* gpu,
4262*c8dee2aaSAndroid Build Coastguard Worker                                                                            const GrBuffer* ibuf) {
4263*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!ibuf || ibuf->isCpuBuffer() || !static_cast<const GrGpuBuffer*>(ibuf)->isMapped());
4264*c8dee2aaSAndroid Build Coastguard Worker     GrGLAttribArrayState* attribState;
4265*c8dee2aaSAndroid Build Coastguard Worker 
4266*c8dee2aaSAndroid Build Coastguard Worker     if (gpu->glCaps().isCoreProfile()) {
4267*c8dee2aaSAndroid Build Coastguard Worker         if (!fCoreProfileVertexArray) {
4268*c8dee2aaSAndroid Build Coastguard Worker             GrGLuint arrayID;
4269*c8dee2aaSAndroid Build Coastguard Worker             GR_GL_CALL(gpu->glInterface(), GenVertexArrays(1, &arrayID));
4270*c8dee2aaSAndroid Build Coastguard Worker             int attrCount = gpu->glCaps().maxVertexAttributes();
4271*c8dee2aaSAndroid Build Coastguard Worker             fCoreProfileVertexArray = new GrGLVertexArray(arrayID, attrCount);
4272*c8dee2aaSAndroid Build Coastguard Worker         }
4273*c8dee2aaSAndroid Build Coastguard Worker         if (ibuf) {
4274*c8dee2aaSAndroid Build Coastguard Worker             attribState = fCoreProfileVertexArray->bindWithIndexBuffer(gpu, ibuf);
4275*c8dee2aaSAndroid Build Coastguard Worker         } else {
4276*c8dee2aaSAndroid Build Coastguard Worker             attribState = fCoreProfileVertexArray->bind(gpu);
4277*c8dee2aaSAndroid Build Coastguard Worker         }
4278*c8dee2aaSAndroid Build Coastguard Worker     } else {
4279*c8dee2aaSAndroid Build Coastguard Worker         if (ibuf) {
4280*c8dee2aaSAndroid Build Coastguard Worker             // bindBuffer implicitly binds VAO 0 when binding an index buffer.
4281*c8dee2aaSAndroid Build Coastguard Worker             gpu->bindBuffer(GrGpuBufferType::kIndex, ibuf);
4282*c8dee2aaSAndroid Build Coastguard Worker         } else {
4283*c8dee2aaSAndroid Build Coastguard Worker             this->setVertexArrayID(gpu, 0);
4284*c8dee2aaSAndroid Build Coastguard Worker         }
4285*c8dee2aaSAndroid Build Coastguard Worker         int attrCount = gpu->glCaps().maxVertexAttributes();
4286*c8dee2aaSAndroid Build Coastguard Worker         if (fDefaultVertexArrayAttribState.count() != attrCount) {
4287*c8dee2aaSAndroid Build Coastguard Worker             fDefaultVertexArrayAttribState.resize(attrCount);
4288*c8dee2aaSAndroid Build Coastguard Worker         }
4289*c8dee2aaSAndroid Build Coastguard Worker         attribState = &fDefaultVertexArrayAttribState;
4290*c8dee2aaSAndroid Build Coastguard Worker     }
4291*c8dee2aaSAndroid Build Coastguard Worker     return attribState;
4292*c8dee2aaSAndroid Build Coastguard Worker }
4293*c8dee2aaSAndroid Build Coastguard Worker 
addFinishedCallback(skgpu::AutoCallback callback,std::optional<GrTimerQuery> timerQuery)4294*c8dee2aaSAndroid Build Coastguard Worker void GrGLGpu::addFinishedCallback(skgpu::AutoCallback callback,
4295*c8dee2aaSAndroid Build Coastguard Worker                                   std::optional<GrTimerQuery> timerQuery) {
4296*c8dee2aaSAndroid Build Coastguard Worker     GrGLint glQuery = timerQuery ? static_cast<GrGLint>(timerQuery->query) : 0;
4297*c8dee2aaSAndroid Build Coastguard Worker     fFinishCallbacks.add(std::move(callback), glQuery);
4298*c8dee2aaSAndroid Build Coastguard Worker }
4299*c8dee2aaSAndroid Build Coastguard Worker 
flush(FlushType flushType)4300*c8dee2aaSAndroid Build Coastguard Worker void GrGLGpu::flush(FlushType flushType) {
4301*c8dee2aaSAndroid Build Coastguard Worker     if (fNeedsGLFlush || flushType == FlushType::kForce) {
4302*c8dee2aaSAndroid Build Coastguard Worker         GL_CALL(Flush());
4303*c8dee2aaSAndroid Build Coastguard Worker         fNeedsGLFlush = false;
4304*c8dee2aaSAndroid Build Coastguard Worker     }
4305*c8dee2aaSAndroid Build Coastguard Worker }
4306*c8dee2aaSAndroid Build Coastguard Worker 
onSubmitToGpu(const GrSubmitInfo & info)4307*c8dee2aaSAndroid Build Coastguard Worker bool GrGLGpu::onSubmitToGpu(const GrSubmitInfo& info) {
4308*c8dee2aaSAndroid Build Coastguard Worker     if (info.fSync == GrSyncCpu::kYes ||
4309*c8dee2aaSAndroid Build Coastguard Worker         (!fFinishCallbacks.empty() && !this->glCaps().fenceSyncSupport())) {
4310*c8dee2aaSAndroid Build Coastguard Worker         this->finishOutstandingGpuWork();
4311*c8dee2aaSAndroid Build Coastguard Worker         fFinishCallbacks.callAll(true);
4312*c8dee2aaSAndroid Build Coastguard Worker     } else {
4313*c8dee2aaSAndroid Build Coastguard Worker         this->flush();
4314*c8dee2aaSAndroid Build Coastguard Worker         // See if any previously inserted finish procs are good to go.
4315*c8dee2aaSAndroid Build Coastguard Worker         fFinishCallbacks.check();
4316*c8dee2aaSAndroid Build Coastguard Worker     }
4317*c8dee2aaSAndroid Build Coastguard Worker     if (!this->glCaps().skipErrorChecks()) {
4318*c8dee2aaSAndroid Build Coastguard Worker         this->clearErrorsAndCheckForOOM();
4319*c8dee2aaSAndroid Build Coastguard Worker     }
4320*c8dee2aaSAndroid Build Coastguard Worker     return true;
4321*c8dee2aaSAndroid Build Coastguard Worker }
4322*c8dee2aaSAndroid Build Coastguard Worker 
willExecute()4323*c8dee2aaSAndroid Build Coastguard Worker void GrGLGpu::willExecute() {
4324*c8dee2aaSAndroid Build Coastguard Worker     // Because our transfers will be submitted to GL to perfom immediately (no command buffer to
4325*c8dee2aaSAndroid Build Coastguard Worker     // submit), we must unmap any staging buffers.
4326*c8dee2aaSAndroid Build Coastguard Worker     if (fStagingBufferManager) {
4327*c8dee2aaSAndroid Build Coastguard Worker         fStagingBufferManager->detachBuffers();
4328*c8dee2aaSAndroid Build Coastguard Worker     }
4329*c8dee2aaSAndroid Build Coastguard Worker }
4330*c8dee2aaSAndroid Build Coastguard Worker 
submit(GrOpsRenderPass * renderPass)4331*c8dee2aaSAndroid Build Coastguard Worker void GrGLGpu::submit(GrOpsRenderPass* renderPass) {
4332*c8dee2aaSAndroid Build Coastguard Worker     // The GrGLOpsRenderPass doesn't buffer ops so there is nothing to do here
4333*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(fCachedOpsRenderPass.get() == renderPass);
4334*c8dee2aaSAndroid Build Coastguard Worker     fCachedOpsRenderPass->reset();
4335*c8dee2aaSAndroid Build Coastguard Worker }
4336*c8dee2aaSAndroid Build Coastguard Worker 
insertSync()4337*c8dee2aaSAndroid Build Coastguard Worker [[nodiscard]] GrGLsync GrGLGpu::insertSync() {
4338*c8dee2aaSAndroid Build Coastguard Worker     GrGLsync sync = nullptr;
4339*c8dee2aaSAndroid Build Coastguard Worker     switch (this->glCaps().fenceType()) {
4340*c8dee2aaSAndroid Build Coastguard Worker         case GrGLCaps::FenceType::kNone:
4341*c8dee2aaSAndroid Build Coastguard Worker             return nullptr;
4342*c8dee2aaSAndroid Build Coastguard Worker         case GrGLCaps::FenceType::kNVFence: {
4343*c8dee2aaSAndroid Build Coastguard Worker             static_assert(sizeof(GrGLsync) >= sizeof(GrGLuint));
4344*c8dee2aaSAndroid Build Coastguard Worker             GrGLuint fence = 0;
4345*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(GenFences(1, &fence));
4346*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(SetFence(fence, GR_GL_ALL_COMPLETED));
4347*c8dee2aaSAndroid Build Coastguard Worker             sync = reinterpret_cast<GrGLsync>(static_cast<intptr_t>(fence));
4348*c8dee2aaSAndroid Build Coastguard Worker             break;
4349*c8dee2aaSAndroid Build Coastguard Worker         }
4350*c8dee2aaSAndroid Build Coastguard Worker         case GrGLCaps::FenceType::kSyncObject: {
4351*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL_RET(sync, FenceSync(GR_GL_SYNC_GPU_COMMANDS_COMPLETE, 0));
4352*c8dee2aaSAndroid Build Coastguard Worker             break;
4353*c8dee2aaSAndroid Build Coastguard Worker         }
4354*c8dee2aaSAndroid Build Coastguard Worker     }
4355*c8dee2aaSAndroid Build Coastguard Worker     this->setNeedsFlush();
4356*c8dee2aaSAndroid Build Coastguard Worker     return sync;
4357*c8dee2aaSAndroid Build Coastguard Worker }
4358*c8dee2aaSAndroid Build Coastguard Worker 
testSync(GrGLsync sync)4359*c8dee2aaSAndroid Build Coastguard Worker bool GrGLGpu::testSync(GrGLsync sync) {
4360*c8dee2aaSAndroid Build Coastguard Worker     switch (this->glCaps().fenceType()) {
4361*c8dee2aaSAndroid Build Coastguard Worker         case GrGLCaps::FenceType::kNone:
4362*c8dee2aaSAndroid Build Coastguard Worker             SK_ABORT("Testing sync without sync support.");
4363*c8dee2aaSAndroid Build Coastguard Worker             return false;
4364*c8dee2aaSAndroid Build Coastguard Worker         case GrGLCaps::FenceType::kNVFence: {
4365*c8dee2aaSAndroid Build Coastguard Worker             GrGLuint nvFence = static_cast<GrGLuint>(reinterpret_cast<intptr_t>(sync));
4366*c8dee2aaSAndroid Build Coastguard Worker             GrGLboolean result;
4367*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL_RET(result, TestFence(nvFence));
4368*c8dee2aaSAndroid Build Coastguard Worker             return result == GR_GL_TRUE;
4369*c8dee2aaSAndroid Build Coastguard Worker         }
4370*c8dee2aaSAndroid Build Coastguard Worker         case GrGLCaps::FenceType::kSyncObject: {
4371*c8dee2aaSAndroid Build Coastguard Worker             constexpr GrGLbitfield kFlags = 0;
4372*c8dee2aaSAndroid Build Coastguard Worker             GrGLenum result;
4373*c8dee2aaSAndroid Build Coastguard Worker #if defined(__EMSCRIPTEN__)
4374*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL_RET(result, ClientWaitSync(sync, kFlags, 0, 0));
4375*c8dee2aaSAndroid Build Coastguard Worker #else
4376*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL_RET(result, ClientWaitSync(sync, kFlags, 0));
4377*c8dee2aaSAndroid Build Coastguard Worker #endif
4378*c8dee2aaSAndroid Build Coastguard Worker             return (GR_GL_CONDITION_SATISFIED == result || GR_GL_ALREADY_SIGNALED == result);
4379*c8dee2aaSAndroid Build Coastguard Worker         }
4380*c8dee2aaSAndroid Build Coastguard Worker     }
4381*c8dee2aaSAndroid Build Coastguard Worker     SkUNREACHABLE;
4382*c8dee2aaSAndroid Build Coastguard Worker }
4383*c8dee2aaSAndroid Build Coastguard Worker 
deleteSync(GrGLsync sync)4384*c8dee2aaSAndroid Build Coastguard Worker void GrGLGpu::deleteSync(GrGLsync sync) {
4385*c8dee2aaSAndroid Build Coastguard Worker     switch (this->glCaps().fenceType()) {
4386*c8dee2aaSAndroid Build Coastguard Worker         case GrGLCaps::FenceType::kNone:
4387*c8dee2aaSAndroid Build Coastguard Worker             SK_ABORT("Deleting sync without sync support.");
4388*c8dee2aaSAndroid Build Coastguard Worker             break;
4389*c8dee2aaSAndroid Build Coastguard Worker         case GrGLCaps::FenceType::kNVFence: {
4390*c8dee2aaSAndroid Build Coastguard Worker             GrGLuint nvFence = SkToUInt(reinterpret_cast<intptr_t>(sync));
4391*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(DeleteFences(1, &nvFence));
4392*c8dee2aaSAndroid Build Coastguard Worker             break;
4393*c8dee2aaSAndroid Build Coastguard Worker         }
4394*c8dee2aaSAndroid Build Coastguard Worker         case GrGLCaps::FenceType::kSyncObject:
4395*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(DeleteSync(sync));
4396*c8dee2aaSAndroid Build Coastguard Worker             break;
4397*c8dee2aaSAndroid Build Coastguard Worker     }
4398*c8dee2aaSAndroid Build Coastguard Worker }
4399*c8dee2aaSAndroid Build Coastguard Worker 
makeSemaphore(bool isOwned)4400*c8dee2aaSAndroid Build Coastguard Worker [[nodiscard]] std::unique_ptr<GrSemaphore> GrGLGpu::makeSemaphore(bool isOwned) {
4401*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(this->caps()->semaphoreSupport());
4402*c8dee2aaSAndroid Build Coastguard Worker     return GrGLSemaphore::Make(this, isOwned);
4403*c8dee2aaSAndroid Build Coastguard Worker }
4404*c8dee2aaSAndroid Build Coastguard Worker 
wrapBackendSemaphore(const GrBackendSemaphore &,GrSemaphoreWrapType,GrWrapOwnership)4405*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<GrSemaphore> GrGLGpu::wrapBackendSemaphore(const GrBackendSemaphore&,
4406*c8dee2aaSAndroid Build Coastguard Worker                                                            GrSemaphoreWrapType,
4407*c8dee2aaSAndroid Build Coastguard Worker                                                            GrWrapOwnership) {
4408*c8dee2aaSAndroid Build Coastguard Worker     SK_ABORT("Unsupported");
4409*c8dee2aaSAndroid Build Coastguard Worker }
4410*c8dee2aaSAndroid Build Coastguard Worker 
insertSemaphore(GrSemaphore * semaphore)4411*c8dee2aaSAndroid Build Coastguard Worker void GrGLGpu::insertSemaphore(GrSemaphore* semaphore) {
4412*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(semaphore);
4413*c8dee2aaSAndroid Build Coastguard Worker     GrGLSemaphore* glSem = static_cast<GrGLSemaphore*>(semaphore);
4414*c8dee2aaSAndroid Build Coastguard Worker 
4415*c8dee2aaSAndroid Build Coastguard Worker     GrGLsync sync;
4416*c8dee2aaSAndroid Build Coastguard Worker     GL_CALL_RET(sync, FenceSync(GR_GL_SYNC_GPU_COMMANDS_COMPLETE, 0));
4417*c8dee2aaSAndroid Build Coastguard Worker     glSem->setSync(sync);
4418*c8dee2aaSAndroid Build Coastguard Worker     this->setNeedsFlush();
4419*c8dee2aaSAndroid Build Coastguard Worker }
4420*c8dee2aaSAndroid Build Coastguard Worker 
waitSemaphore(GrSemaphore * semaphore)4421*c8dee2aaSAndroid Build Coastguard Worker void GrGLGpu::waitSemaphore(GrSemaphore* semaphore) {
4422*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(semaphore);
4423*c8dee2aaSAndroid Build Coastguard Worker     GrGLSemaphore* glSem = static_cast<GrGLSemaphore*>(semaphore);
4424*c8dee2aaSAndroid Build Coastguard Worker 
4425*c8dee2aaSAndroid Build Coastguard Worker #if defined(__EMSCRIPTEN__)
4426*c8dee2aaSAndroid Build Coastguard Worker     constexpr auto kLo = SkTo<GrGLuint>(GR_GL_TIMEOUT_IGNORED & 0xFFFFFFFFull);
4427*c8dee2aaSAndroid Build Coastguard Worker     constexpr auto kHi = SkTo<GrGLuint>(GR_GL_TIMEOUT_IGNORED >> 32);
4428*c8dee2aaSAndroid Build Coastguard Worker     GL_CALL(WaitSync(glSem->sync(), 0, kLo, kHi));
4429*c8dee2aaSAndroid Build Coastguard Worker #else
4430*c8dee2aaSAndroid Build Coastguard Worker     GL_CALL(WaitSync(glSem->sync(), 0, GR_GL_TIMEOUT_IGNORED));
4431*c8dee2aaSAndroid Build Coastguard Worker #endif
4432*c8dee2aaSAndroid Build Coastguard Worker }
4433*c8dee2aaSAndroid Build Coastguard Worker 
startTimerQuery()4434*c8dee2aaSAndroid Build Coastguard Worker std::optional<GrTimerQuery> GrGLGpu::startTimerQuery() {
4435*c8dee2aaSAndroid Build Coastguard Worker     if (glCaps().timerQueryType() == GrGLCaps::TimerQueryType::kNone) {
4436*c8dee2aaSAndroid Build Coastguard Worker         return {};
4437*c8dee2aaSAndroid Build Coastguard Worker     }
4438*c8dee2aaSAndroid Build Coastguard Worker     GrGLuint glQuery;
4439*c8dee2aaSAndroid Build Coastguard Worker     GL_CALL(GenQueries(1, &glQuery));
4440*c8dee2aaSAndroid Build Coastguard Worker     if (!glQuery) {
4441*c8dee2aaSAndroid Build Coastguard Worker         return {};
4442*c8dee2aaSAndroid Build Coastguard Worker     }
4443*c8dee2aaSAndroid Build Coastguard Worker     if (glCaps().timerQueryType() == GrGLCaps::TimerQueryType::kDisjoint) {
4444*c8dee2aaSAndroid Build Coastguard Worker         // Clear the disjoint state
4445*c8dee2aaSAndroid Build Coastguard Worker         GrGLint _;
4446*c8dee2aaSAndroid Build Coastguard Worker         GR_GL_GetIntegerv(this->glInterface(), GR_GL_GPU_DISJOINT, &_);
4447*c8dee2aaSAndroid Build Coastguard Worker     }
4448*c8dee2aaSAndroid Build Coastguard Worker     GL_CALL(BeginQuery(GR_GL_TIME_ELAPSED, glQuery));
4449*c8dee2aaSAndroid Build Coastguard Worker     return GrTimerQuery{glQuery};
4450*c8dee2aaSAndroid Build Coastguard Worker }
4451*c8dee2aaSAndroid Build Coastguard Worker 
endTimerQuery(const GrTimerQuery & timerQuery)4452*c8dee2aaSAndroid Build Coastguard Worker void GrGLGpu::endTimerQuery(const GrTimerQuery& timerQuery) {
4453*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(glCaps().timerQueryType() != GrGLCaps::TimerQueryType::kNone);
4454*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(SkToUInt(timerQuery.query));
4455*c8dee2aaSAndroid Build Coastguard Worker     // Since only one query of a particular type can be active at once, glEndQuery doesn't take a
4456*c8dee2aaSAndroid Build Coastguard Worker     // query parameter.
4457*c8dee2aaSAndroid Build Coastguard Worker     GL_CALL(EndQuery(GR_GL_TIME_ELAPSED));
4458*c8dee2aaSAndroid Build Coastguard Worker }
4459*c8dee2aaSAndroid Build Coastguard Worker 
getTimerQueryResult(GrGLuint query)4460*c8dee2aaSAndroid Build Coastguard Worker uint64_t GrGLGpu::getTimerQueryResult(GrGLuint query) {
4461*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(glCaps().timerQueryType() != GrGLCaps::TimerQueryType::kNone);
4462*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(query);
4463*c8dee2aaSAndroid Build Coastguard Worker 
4464*c8dee2aaSAndroid Build Coastguard Worker     // Because we only call this after a sync completes the query *should* be available.
4465*c8dee2aaSAndroid Build Coastguard Worker     GrGLuint available;
4466*c8dee2aaSAndroid Build Coastguard Worker     GL_CALL(GetQueryObjectuiv(query, GR_GL_QUERY_RESULT_AVAILABLE, &available));
4467*c8dee2aaSAndroid Build Coastguard Worker     bool getResult = true;
4468*c8dee2aaSAndroid Build Coastguard Worker     if (!available) {
4469*c8dee2aaSAndroid Build Coastguard Worker         SkDebugf("GL timer query is not available.\n");
4470*c8dee2aaSAndroid Build Coastguard Worker         getResult = false;
4471*c8dee2aaSAndroid Build Coastguard Worker     }
4472*c8dee2aaSAndroid Build Coastguard Worker 
4473*c8dee2aaSAndroid Build Coastguard Worker     if (glCaps().timerQueryType() == GrGLCaps::TimerQueryType::kDisjoint) {
4474*c8dee2aaSAndroid Build Coastguard Worker         // Clear the disjoint state
4475*c8dee2aaSAndroid Build Coastguard Worker         GrGLint disjoint;
4476*c8dee2aaSAndroid Build Coastguard Worker         GR_GL_GetIntegerv(this->glInterface(), GR_GL_GPU_DISJOINT, &disjoint);
4477*c8dee2aaSAndroid Build Coastguard Worker         if (disjoint) {
4478*c8dee2aaSAndroid Build Coastguard Worker             SkDebugf("GL timer query ignored because of disjoint event.\n");
4479*c8dee2aaSAndroid Build Coastguard Worker             getResult = false;
4480*c8dee2aaSAndroid Build Coastguard Worker         }
4481*c8dee2aaSAndroid Build Coastguard Worker     }
4482*c8dee2aaSAndroid Build Coastguard Worker 
4483*c8dee2aaSAndroid Build Coastguard Worker     uint64_t result = 0;
4484*c8dee2aaSAndroid Build Coastguard Worker     if (getResult) {
4485*c8dee2aaSAndroid Build Coastguard Worker         GR_GL_GetQueryObjectui64v(this->glInterface(), query, GR_GL_QUERY_RESULT, &result);
4486*c8dee2aaSAndroid Build Coastguard Worker     }
4487*c8dee2aaSAndroid Build Coastguard Worker     GL_CALL(DeleteQueries(1, &query));
4488*c8dee2aaSAndroid Build Coastguard Worker     return result;
4489*c8dee2aaSAndroid Build Coastguard Worker }
4490*c8dee2aaSAndroid Build Coastguard Worker 
checkFinishedCallbacks()4491*c8dee2aaSAndroid Build Coastguard Worker void GrGLGpu::checkFinishedCallbacks() {
4492*c8dee2aaSAndroid Build Coastguard Worker     fFinishCallbacks.check();
4493*c8dee2aaSAndroid Build Coastguard Worker }
4494*c8dee2aaSAndroid Build Coastguard Worker 
finishOutstandingGpuWork()4495*c8dee2aaSAndroid Build Coastguard Worker void GrGLGpu::finishOutstandingGpuWork() {
4496*c8dee2aaSAndroid Build Coastguard Worker     GL_CALL(Finish());
4497*c8dee2aaSAndroid Build Coastguard Worker }
4498*c8dee2aaSAndroid Build Coastguard Worker 
clearErrorsAndCheckForOOM()4499*c8dee2aaSAndroid Build Coastguard Worker void GrGLGpu::clearErrorsAndCheckForOOM() {
4500*c8dee2aaSAndroid Build Coastguard Worker     while (this->getErrorAndCheckForOOM() != GR_GL_NO_ERROR) {}
4501*c8dee2aaSAndroid Build Coastguard Worker }
4502*c8dee2aaSAndroid Build Coastguard Worker 
getErrorAndCheckForOOM()4503*c8dee2aaSAndroid Build Coastguard Worker GrGLenum GrGLGpu::getErrorAndCheckForOOM() {
4504*c8dee2aaSAndroid Build Coastguard Worker #if GR_GL_CHECK_ERROR
4505*c8dee2aaSAndroid Build Coastguard Worker     if (this->glInterface()->checkAndResetOOMed()) {
4506*c8dee2aaSAndroid Build Coastguard Worker         this->setOOMed();
4507*c8dee2aaSAndroid Build Coastguard Worker     }
4508*c8dee2aaSAndroid Build Coastguard Worker #endif
4509*c8dee2aaSAndroid Build Coastguard Worker     GrGLenum error = this->fGLContext->glInterface()->fFunctions.fGetError();
4510*c8dee2aaSAndroid Build Coastguard Worker     if (error == GR_GL_OUT_OF_MEMORY) {
4511*c8dee2aaSAndroid Build Coastguard Worker         this->setOOMed();
4512*c8dee2aaSAndroid Build Coastguard Worker     }
4513*c8dee2aaSAndroid Build Coastguard Worker     return error;
4514*c8dee2aaSAndroid Build Coastguard Worker }
4515*c8dee2aaSAndroid Build Coastguard Worker 
prepareTextureForCrossContextUsage(GrTexture * texture)4516*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<GrSemaphore> GrGLGpu::prepareTextureForCrossContextUsage(GrTexture* texture) {
4517*c8dee2aaSAndroid Build Coastguard Worker     // Set up a semaphore to be signaled once the data is ready, and flush GL
4518*c8dee2aaSAndroid Build Coastguard Worker     std::unique_ptr<GrSemaphore> semaphore = this->makeSemaphore(true);
4519*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(semaphore);
4520*c8dee2aaSAndroid Build Coastguard Worker     this->insertSemaphore(semaphore.get());
4521*c8dee2aaSAndroid Build Coastguard Worker     // We must call flush here to make sure the GrGLsync object gets created and sent to the gpu.
4522*c8dee2aaSAndroid Build Coastguard Worker     this->flush(FlushType::kForce);
4523*c8dee2aaSAndroid Build Coastguard Worker 
4524*c8dee2aaSAndroid Build Coastguard Worker     return semaphore;
4525*c8dee2aaSAndroid Build Coastguard Worker }
4526*c8dee2aaSAndroid Build Coastguard Worker 
TextureToCopyProgramIdx(GrTexture * texture)4527*c8dee2aaSAndroid Build Coastguard Worker int GrGLGpu::TextureToCopyProgramIdx(GrTexture* texture) {
4528*c8dee2aaSAndroid Build Coastguard Worker     switch (SkSLCombinedSamplerTypeForTextureType(texture->textureType())) {
4529*c8dee2aaSAndroid Build Coastguard Worker         case SkSLType::kTexture2DSampler:
4530*c8dee2aaSAndroid Build Coastguard Worker             return 0;
4531*c8dee2aaSAndroid Build Coastguard Worker         case SkSLType::kTexture2DRectSampler:
4532*c8dee2aaSAndroid Build Coastguard Worker             return 1;
4533*c8dee2aaSAndroid Build Coastguard Worker         case SkSLType::kTextureExternalSampler:
4534*c8dee2aaSAndroid Build Coastguard Worker             return 2;
4535*c8dee2aaSAndroid Build Coastguard Worker         default:
4536*c8dee2aaSAndroid Build Coastguard Worker             SK_ABORT("Unexpected samper type");
4537*c8dee2aaSAndroid Build Coastguard Worker     }
4538*c8dee2aaSAndroid Build Coastguard Worker }
4539*c8dee2aaSAndroid Build Coastguard Worker 
4540*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_ENABLE_DUMP_GPU
4541*c8dee2aaSAndroid Build Coastguard Worker #include "src/utils/SkJSONWriter.h"
onDumpJSON(SkJSONWriter * writer) const4542*c8dee2aaSAndroid Build Coastguard Worker void GrGLGpu::onDumpJSON(SkJSONWriter* writer) const {
4543*c8dee2aaSAndroid Build Coastguard Worker     // We are called by the base class, which has already called beginObject(). We choose to nest
4544*c8dee2aaSAndroid Build Coastguard Worker     // all of our caps information in a named sub-object.
4545*c8dee2aaSAndroid Build Coastguard Worker     writer->beginObject("GL GPU");
4546*c8dee2aaSAndroid Build Coastguard Worker 
4547*c8dee2aaSAndroid Build Coastguard Worker     const GrGLubyte* str;
4548*c8dee2aaSAndroid Build Coastguard Worker     GL_CALL_RET(str, GetString(GR_GL_VERSION));
4549*c8dee2aaSAndroid Build Coastguard Worker     writer->appendCString("GL_VERSION", (const char*)(str));
4550*c8dee2aaSAndroid Build Coastguard Worker     GL_CALL_RET(str, GetString(GR_GL_RENDERER));
4551*c8dee2aaSAndroid Build Coastguard Worker     writer->appendCString("GL_RENDERER", (const char*)(str));
4552*c8dee2aaSAndroid Build Coastguard Worker     GL_CALL_RET(str, GetString(GR_GL_VENDOR));
4553*c8dee2aaSAndroid Build Coastguard Worker     writer->appendCString("GL_VENDOR", (const char*)(str));
4554*c8dee2aaSAndroid Build Coastguard Worker     GL_CALL_RET(str, GetString(GR_GL_SHADING_LANGUAGE_VERSION));
4555*c8dee2aaSAndroid Build Coastguard Worker     writer->appendCString("GL_SHADING_LANGUAGE_VERSION", (const char*)(str));
4556*c8dee2aaSAndroid Build Coastguard Worker 
4557*c8dee2aaSAndroid Build Coastguard Worker     writer->appendName("extensions");
4558*c8dee2aaSAndroid Build Coastguard Worker     glInterface()->fExtensions.dumpJSON(writer);
4559*c8dee2aaSAndroid Build Coastguard Worker 
4560*c8dee2aaSAndroid Build Coastguard Worker     writer->endObject();
4561*c8dee2aaSAndroid Build Coastguard Worker }
4562*c8dee2aaSAndroid Build Coastguard Worker #endif
4563