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