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