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