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