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