• 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 "GrGLGpu.h"
9 
10 #include <cmath>
11 #include "../private/GrGLSL.h"
12 #include "GrBackendSemaphore.h"
13 #include "GrBackendSurface.h"
14 #include "GrFixedClip.h"
15 #include "GrGLBuffer.h"
16 #include "GrGLGpuCommandBuffer.h"
17 #include "GrGLSemaphore.h"
18 #include "GrGLStencilAttachment.h"
19 #include "GrGLTextureRenderTarget.h"
20 #include "GrGpuResourcePriv.h"
21 #include "GrMesh.h"
22 #include "GrPipeline.h"
23 #include "GrRenderTargetPriv.h"
24 #include "GrShaderCaps.h"
25 #include "GrSurfaceProxyPriv.h"
26 #include "GrTexturePriv.h"
27 #include "GrTypes.h"
28 #include "SkAutoMalloc.h"
29 #include "SkHalf.h"
30 #include "SkJSONWriter.h"
31 #include "SkMakeUnique.h"
32 #include "SkMipMap.h"
33 #include "SkPixmap.h"
34 #include "SkSLCompiler.h"
35 #include "SkStrokeRec.h"
36 #include "SkTemplates.h"
37 #include "SkTraceEvent.h"
38 #include "SkTypes.h"
39 #include "builders/GrGLShaderStringBuilder.h"
40 
41 #define GL_CALL(X) GR_GL_CALL(this->glInterface(), X)
42 #define GL_CALL_RET(RET, X) GR_GL_CALL_RET(this->glInterface(), RET, X)
43 
44 #define SKIP_CACHE_CHECK    true
45 
46 #if GR_GL_CHECK_ALLOC_WITH_GET_ERROR
47     #define CLEAR_ERROR_BEFORE_ALLOC(iface)   GrGLClearErr(iface)
48     #define GL_ALLOC_CALL(iface, call)        GR_GL_CALL_NOERRCHECK(iface, call)
49     #define CHECK_ALLOC_ERROR(iface)          GR_GL_GET_ERROR(iface)
50 #else
51     #define CLEAR_ERROR_BEFORE_ALLOC(iface)
52     #define GL_ALLOC_CALL(iface, call)        GR_GL_CALL(iface, call)
53     #define CHECK_ALLOC_ERROR(iface)          GR_GL_NO_ERROR
54 #endif
55 
56 //#define USE_NSIGHT
57 
58 ///////////////////////////////////////////////////////////////////////////////
59 
60 static const GrGLenum gXfermodeEquation2Blend[] = {
61     // Basic OpenGL blend equations.
62     GR_GL_FUNC_ADD,
63     GR_GL_FUNC_SUBTRACT,
64     GR_GL_FUNC_REVERSE_SUBTRACT,
65 
66     // GL_KHR_blend_equation_advanced.
67     GR_GL_SCREEN,
68     GR_GL_OVERLAY,
69     GR_GL_DARKEN,
70     GR_GL_LIGHTEN,
71     GR_GL_COLORDODGE,
72     GR_GL_COLORBURN,
73     GR_GL_HARDLIGHT,
74     GR_GL_SOFTLIGHT,
75     GR_GL_DIFFERENCE,
76     GR_GL_EXCLUSION,
77     GR_GL_MULTIPLY,
78     GR_GL_HSL_HUE,
79     GR_GL_HSL_SATURATION,
80     GR_GL_HSL_COLOR,
81     GR_GL_HSL_LUMINOSITY
82 };
83 GR_STATIC_ASSERT(0 == kAdd_GrBlendEquation);
84 GR_STATIC_ASSERT(1 == kSubtract_GrBlendEquation);
85 GR_STATIC_ASSERT(2 == kReverseSubtract_GrBlendEquation);
86 GR_STATIC_ASSERT(3 == kScreen_GrBlendEquation);
87 GR_STATIC_ASSERT(4 == kOverlay_GrBlendEquation);
88 GR_STATIC_ASSERT(5 == kDarken_GrBlendEquation);
89 GR_STATIC_ASSERT(6 == kLighten_GrBlendEquation);
90 GR_STATIC_ASSERT(7 == kColorDodge_GrBlendEquation);
91 GR_STATIC_ASSERT(8 == kColorBurn_GrBlendEquation);
92 GR_STATIC_ASSERT(9 == kHardLight_GrBlendEquation);
93 GR_STATIC_ASSERT(10 == kSoftLight_GrBlendEquation);
94 GR_STATIC_ASSERT(11 == kDifference_GrBlendEquation);
95 GR_STATIC_ASSERT(12 == kExclusion_GrBlendEquation);
96 GR_STATIC_ASSERT(13 == kMultiply_GrBlendEquation);
97 GR_STATIC_ASSERT(14 == kHSLHue_GrBlendEquation);
98 GR_STATIC_ASSERT(15 == kHSLSaturation_GrBlendEquation);
99 GR_STATIC_ASSERT(16 == kHSLColor_GrBlendEquation);
100 GR_STATIC_ASSERT(17 == kHSLLuminosity_GrBlendEquation);
101 GR_STATIC_ASSERT(SK_ARRAY_COUNT(gXfermodeEquation2Blend) == kGrBlendEquationCnt);
102 
103 static const GrGLenum gXfermodeCoeff2Blend[] = {
104     GR_GL_ZERO,
105     GR_GL_ONE,
106     GR_GL_SRC_COLOR,
107     GR_GL_ONE_MINUS_SRC_COLOR,
108     GR_GL_DST_COLOR,
109     GR_GL_ONE_MINUS_DST_COLOR,
110     GR_GL_SRC_ALPHA,
111     GR_GL_ONE_MINUS_SRC_ALPHA,
112     GR_GL_DST_ALPHA,
113     GR_GL_ONE_MINUS_DST_ALPHA,
114     GR_GL_CONSTANT_COLOR,
115     GR_GL_ONE_MINUS_CONSTANT_COLOR,
116     GR_GL_CONSTANT_ALPHA,
117     GR_GL_ONE_MINUS_CONSTANT_ALPHA,
118 
119     // extended blend coeffs
120     GR_GL_SRC1_COLOR,
121     GR_GL_ONE_MINUS_SRC1_COLOR,
122     GR_GL_SRC1_ALPHA,
123     GR_GL_ONE_MINUS_SRC1_ALPHA,
124 };
125 
BlendCoeffReferencesConstant(GrBlendCoeff coeff)126 bool GrGLGpu::BlendCoeffReferencesConstant(GrBlendCoeff coeff) {
127     static const bool gCoeffReferencesBlendConst[] = {
128         false,
129         false,
130         false,
131         false,
132         false,
133         false,
134         false,
135         false,
136         false,
137         false,
138         true,
139         true,
140         true,
141         true,
142 
143         // extended blend coeffs
144         false,
145         false,
146         false,
147         false,
148     };
149     return gCoeffReferencesBlendConst[coeff];
150     GR_STATIC_ASSERT(kGrBlendCoeffCnt == SK_ARRAY_COUNT(gCoeffReferencesBlendConst));
151 
152     GR_STATIC_ASSERT(0 == kZero_GrBlendCoeff);
153     GR_STATIC_ASSERT(1 == kOne_GrBlendCoeff);
154     GR_STATIC_ASSERT(2 == kSC_GrBlendCoeff);
155     GR_STATIC_ASSERT(3 == kISC_GrBlendCoeff);
156     GR_STATIC_ASSERT(4 == kDC_GrBlendCoeff);
157     GR_STATIC_ASSERT(5 == kIDC_GrBlendCoeff);
158     GR_STATIC_ASSERT(6 == kSA_GrBlendCoeff);
159     GR_STATIC_ASSERT(7 == kISA_GrBlendCoeff);
160     GR_STATIC_ASSERT(8 == kDA_GrBlendCoeff);
161     GR_STATIC_ASSERT(9 == kIDA_GrBlendCoeff);
162     GR_STATIC_ASSERT(10 == kConstC_GrBlendCoeff);
163     GR_STATIC_ASSERT(11 == kIConstC_GrBlendCoeff);
164     GR_STATIC_ASSERT(12 == kConstA_GrBlendCoeff);
165     GR_STATIC_ASSERT(13 == kIConstA_GrBlendCoeff);
166 
167     GR_STATIC_ASSERT(14 == kS2C_GrBlendCoeff);
168     GR_STATIC_ASSERT(15 == kIS2C_GrBlendCoeff);
169     GR_STATIC_ASSERT(16 == kS2A_GrBlendCoeff);
170     GR_STATIC_ASSERT(17 == kIS2A_GrBlendCoeff);
171 
172     // assertion for gXfermodeCoeff2Blend have to be in GrGpu scope
173     GR_STATIC_ASSERT(kGrBlendCoeffCnt == SK_ARRAY_COUNT(gXfermodeCoeff2Blend));
174 }
175 
176 ///////////////////////////////////////////////////////////////////////////////
177 
Make(GrBackendContext backendContext,const GrContextOptions & options,GrContext * context)178 sk_sp<GrGpu> GrGLGpu::Make(GrBackendContext backendContext, const GrContextOptions& options,
179                            GrContext* context) {
180     const auto* interface = reinterpret_cast<const GrGLInterface*>(backendContext);
181     return Make(sk_ref_sp(interface), options, context);
182 }
183 
Make(sk_sp<const GrGLInterface> interface,const GrContextOptions & options,GrContext * context)184 sk_sp<GrGpu> GrGLGpu::Make(sk_sp<const GrGLInterface> interface, const GrContextOptions& options,
185                            GrContext* context) {
186     if (!interface) {
187         interface = GrGLMakeNativeInterface();
188         // For clients that have written their own GrGLCreateNativeInterface and haven't yet updated
189         // to GrGLMakeNativeInterface.
190         if (!interface) {
191             interface = sk_ref_sp(GrGLCreateNativeInterface());
192         }
193         if (!interface) {
194             return nullptr;
195         }
196     }
197 #ifdef USE_NSIGHT
198     const_cast<GrContextOptions&>(options).fSuppressPathRendering = true;
199 #endif
200     auto glContext = GrGLContext::Make(std::move(interface), options);
201     if (!glContext) {
202         return nullptr;
203     }
204     return sk_sp<GrGpu>(new GrGLGpu(std::move(glContext), context));
205 }
206 
GrGLGpu(std::unique_ptr<GrGLContext> ctx,GrContext * context)207 GrGLGpu::GrGLGpu(std::unique_ptr<GrGLContext> ctx, GrContext* context)
208         : GrGpu(context)
209         , fGLContext(std::move(ctx))
210         , fProgramCache(new ProgramCache(this))
211         , fHWProgramID(0)
212         , fTempSrcFBOID(0)
213         , fTempDstFBOID(0)
214         , fStencilClearFBOID(0)
215         , fHWMaxUsedBufferTextureUnit(-1)
216         , fHWMinSampleShading(0.0) {
217     SkASSERT(fGLContext);
218     fCaps = sk_ref_sp(fGLContext->caps());
219 
220     fHWBoundTextureUniqueIDs.reset(this->caps()->shaderCaps()->maxCombinedSamplers());
221 
222     fHWBufferState[kVertex_GrBufferType].fGLTarget = GR_GL_ARRAY_BUFFER;
223     fHWBufferState[kIndex_GrBufferType].fGLTarget = GR_GL_ELEMENT_ARRAY_BUFFER;
224     fHWBufferState[kTexel_GrBufferType].fGLTarget = GR_GL_TEXTURE_BUFFER;
225     fHWBufferState[kDrawIndirect_GrBufferType].fGLTarget = GR_GL_DRAW_INDIRECT_BUFFER;
226     if (GrGLCaps::kChromium_TransferBufferType == this->glCaps().transferBufferType()) {
227         fHWBufferState[kXferCpuToGpu_GrBufferType].fGLTarget =
228             GR_GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM;
229         fHWBufferState[kXferGpuToCpu_GrBufferType].fGLTarget =
230             GR_GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM;
231     } else {
232         fHWBufferState[kXferCpuToGpu_GrBufferType].fGLTarget = GR_GL_PIXEL_UNPACK_BUFFER;
233         fHWBufferState[kXferGpuToCpu_GrBufferType].fGLTarget = GR_GL_PIXEL_PACK_BUFFER;
234     }
235     for (int i = 0; i < kGrBufferTypeCount; ++i) {
236         fHWBufferState[i].invalidate();
237     }
238     GR_STATIC_ASSERT(6 == SK_ARRAY_COUNT(fHWBufferState));
239 
240     if (this->caps()->shaderCaps()->texelBufferSupport()) {
241         fHWBufferTextures.reset(this->caps()->shaderCaps()->maxCombinedSamplers());
242     }
243 
244     if (this->glCaps().shaderCaps()->pathRenderingSupport()) {
245         fPathRendering.reset(new GrGLPathRendering(this));
246     }
247 
248     GrGLClearErr(this->glInterface());
249 }
250 
~GrGLGpu()251 GrGLGpu::~GrGLGpu() {
252     // Ensure any GrGpuResource objects get deleted first, since they may require a working GrGLGpu
253     // to release the resources held by the objects themselves.
254     fPathRendering.reset();
255     fCopyProgramArrayBuffer.reset();
256     fMipmapProgramArrayBuffer.reset();
257     fStencilClipClearArrayBuffer.reset();
258 
259     if (fHWProgramID) {
260         // detach the current program so there is no confusion on OpenGL's part
261         // that we want it to be deleted
262         GL_CALL(UseProgram(0));
263     }
264 
265     if (fTempSrcFBOID) {
266         GL_CALL(DeleteFramebuffers(1, &fTempSrcFBOID));
267     }
268     if (fTempDstFBOID) {
269         GL_CALL(DeleteFramebuffers(1, &fTempDstFBOID));
270     }
271     if (fStencilClearFBOID) {
272         GL_CALL(DeleteFramebuffers(1, &fStencilClearFBOID));
273     }
274 
275     for (size_t i = 0; i < SK_ARRAY_COUNT(fCopyPrograms); ++i) {
276         if (0 != fCopyPrograms[i].fProgram) {
277             GL_CALL(DeleteProgram(fCopyPrograms[i].fProgram));
278         }
279     }
280 
281     for (size_t i = 0; i < SK_ARRAY_COUNT(fMipmapPrograms); ++i) {
282         if (0 != fMipmapPrograms[i].fProgram) {
283             GL_CALL(DeleteProgram(fMipmapPrograms[i].fProgram));
284         }
285     }
286 
287     if (fStencilClipClearProgram) {
288         GL_CALL(DeleteProgram(fStencilClipClearProgram));
289     }
290 
291     if (fClearColorProgram.fProgram) {
292         GL_CALL(DeleteProgram(fClearColorProgram.fProgram));
293     }
294 
295     delete fProgramCache;
296 }
297 
disconnect(DisconnectType type)298 void GrGLGpu::disconnect(DisconnectType type) {
299     INHERITED::disconnect(type);
300     if (DisconnectType::kCleanup == type) {
301         if (fHWProgramID) {
302             GL_CALL(UseProgram(0));
303         }
304         if (fTempSrcFBOID) {
305             GL_CALL(DeleteFramebuffers(1, &fTempSrcFBOID));
306         }
307         if (fTempDstFBOID) {
308             GL_CALL(DeleteFramebuffers(1, &fTempDstFBOID));
309         }
310         if (fStencilClearFBOID) {
311             GL_CALL(DeleteFramebuffers(1, &fStencilClearFBOID));
312         }
313         for (size_t i = 0; i < SK_ARRAY_COUNT(fCopyPrograms); ++i) {
314             if (fCopyPrograms[i].fProgram) {
315                 GL_CALL(DeleteProgram(fCopyPrograms[i].fProgram));
316             }
317         }
318         for (size_t i = 0; i < SK_ARRAY_COUNT(fMipmapPrograms); ++i) {
319             if (fMipmapPrograms[i].fProgram) {
320                 GL_CALL(DeleteProgram(fMipmapPrograms[i].fProgram));
321             }
322         }
323         if (fStencilClipClearProgram) {
324             GL_CALL(DeleteProgram(fStencilClipClearProgram));
325         }
326 
327         if (fClearColorProgram.fProgram) {
328             GL_CALL(DeleteProgram(fClearColorProgram.fProgram));
329         }
330     } else {
331         if (fProgramCache) {
332             fProgramCache->abandon();
333         }
334     }
335 
336     delete fProgramCache;
337     fProgramCache = nullptr;
338 
339     fHWProgramID = 0;
340     fTempSrcFBOID = 0;
341     fTempDstFBOID = 0;
342     fStencilClearFBOID = 0;
343     fCopyProgramArrayBuffer.reset();
344     for (size_t i = 0; i < SK_ARRAY_COUNT(fCopyPrograms); ++i) {
345         fCopyPrograms[i].fProgram = 0;
346     }
347     fMipmapProgramArrayBuffer.reset();
348     for (size_t i = 0; i < SK_ARRAY_COUNT(fMipmapPrograms); ++i) {
349         fMipmapPrograms[i].fProgram = 0;
350     }
351     fStencilClipClearProgram = 0;
352     fStencilClipClearArrayBuffer.reset();
353     fClearColorProgram.fProgram = 0;
354 
355     if (this->glCaps().shaderCaps()->pathRenderingSupport()) {
356         this->glPathRendering()->disconnect(type);
357     }
358 }
359 
360 ///////////////////////////////////////////////////////////////////////////////
361 
onResetContext(uint32_t resetBits)362 void GrGLGpu::onResetContext(uint32_t resetBits) {
363     if (resetBits & kMisc_GrGLBackendState) {
364         // we don't use the zb at all
365         GL_CALL(Disable(GR_GL_DEPTH_TEST));
366         GL_CALL(DepthMask(GR_GL_FALSE));
367 
368         // We don't use face culling.
369         GL_CALL(Disable(GR_GL_CULL_FACE));
370         // We do use separate stencil. Our algorithms don't care which face is front vs. back so
371         // just set this to the default for self-consistency.
372         GL_CALL(FrontFace(GR_GL_CCW));
373 
374         fHWBufferState[kTexel_GrBufferType].invalidate();
375         fHWBufferState[kDrawIndirect_GrBufferType].invalidate();
376         fHWBufferState[kXferCpuToGpu_GrBufferType].invalidate();
377         fHWBufferState[kXferGpuToCpu_GrBufferType].invalidate();
378 
379         if (kGL_GrGLStandard == this->glStandard()) {
380 #ifndef USE_NSIGHT
381             // Desktop-only state that we never change
382             if (!this->glCaps().isCoreProfile()) {
383                 GL_CALL(Disable(GR_GL_POINT_SMOOTH));
384                 GL_CALL(Disable(GR_GL_LINE_SMOOTH));
385                 GL_CALL(Disable(GR_GL_POLYGON_SMOOTH));
386                 GL_CALL(Disable(GR_GL_POLYGON_STIPPLE));
387                 GL_CALL(Disable(GR_GL_COLOR_LOGIC_OP));
388                 GL_CALL(Disable(GR_GL_INDEX_LOGIC_OP));
389             }
390             // The windows NVIDIA driver has GL_ARB_imaging in the extension string when using a
391             // core profile. This seems like a bug since the core spec removes any mention of
392             // GL_ARB_imaging.
393             if (this->glCaps().imagingSupport() && !this->glCaps().isCoreProfile()) {
394                 GL_CALL(Disable(GR_GL_COLOR_TABLE));
395             }
396             GL_CALL(Disable(GR_GL_POLYGON_OFFSET_FILL));
397 
398             if (this->caps()->wireframeMode()) {
399                 GL_CALL(PolygonMode(GR_GL_FRONT_AND_BACK, GR_GL_LINE));
400             } else {
401                 GL_CALL(PolygonMode(GR_GL_FRONT_AND_BACK, GR_GL_FILL));
402             }
403 #endif
404             // Since ES doesn't support glPointSize at all we always use the VS to
405             // set the point size
406             GL_CALL(Enable(GR_GL_VERTEX_PROGRAM_POINT_SIZE));
407 
408         }
409 
410         if (kGLES_GrGLStandard == this->glStandard() &&
411                 this->hasExtension("GL_ARM_shader_framebuffer_fetch")) {
412             // The arm extension requires specifically enabling MSAA fetching per sample.
413             // On some devices this may have a perf hit.  Also multiple render targets are disabled
414             GL_CALL(Enable(GR_GL_FETCH_PER_SAMPLE_ARM));
415         }
416         fHWWriteToColor = kUnknown_TriState;
417         // we only ever use lines in hairline mode
418         GL_CALL(LineWidth(1));
419         GL_CALL(Disable(GR_GL_DITHER));
420     }
421 
422     if (resetBits & kMSAAEnable_GrGLBackendState) {
423         fMSAAEnabled = kUnknown_TriState;
424 
425         if (this->caps()->usesMixedSamples()) {
426             if (0 != this->caps()->maxRasterSamples()) {
427                 fHWRasterMultisampleEnabled = kUnknown_TriState;
428                 fHWNumRasterSamples = 0;
429             }
430 
431             // The skia blend modes all use premultiplied alpha and therefore expect RGBA coverage
432             // modulation. This state has no effect when not rendering to a mixed sampled target.
433             GL_CALL(CoverageModulation(GR_GL_RGBA));
434         }
435     }
436 
437     fHWActiveTextureUnitIdx = -1; // invalid
438     fLastPrimitiveType = static_cast<GrPrimitiveType>(-1);
439 
440     if (resetBits & kTextureBinding_GrGLBackendState) {
441         for (int s = 0; s < fHWBoundTextureUniqueIDs.count(); ++s) {
442             fHWBoundTextureUniqueIDs[s].makeInvalid();
443         }
444         for (int b = 0; b < fHWBufferTextures.count(); ++b) {
445             SkASSERT(this->caps()->shaderCaps()->texelBufferSupport());
446             fHWBufferTextures[b].fKnownBound = false;
447         }
448     }
449 
450     if (resetBits & kBlend_GrGLBackendState) {
451         fHWBlendState.invalidate();
452     }
453 
454     if (resetBits & kView_GrGLBackendState) {
455         fHWScissorSettings.invalidate();
456         fHWWindowRectsState.invalidate();
457         fHWViewport.invalidate();
458     }
459 
460     if (resetBits & kStencil_GrGLBackendState) {
461         fHWStencilSettings.invalidate();
462         fHWStencilTestEnabled = kUnknown_TriState;
463     }
464 
465     // Vertex
466     if (resetBits & kVertex_GrGLBackendState) {
467         fHWVertexArrayState.invalidate();
468         fHWBufferState[kVertex_GrBufferType].invalidate();
469         fHWBufferState[kIndex_GrBufferType].invalidate();
470     }
471 
472     if (resetBits & kRenderTarget_GrGLBackendState) {
473         fHWBoundRenderTargetUniqueID.makeInvalid();
474         fHWSRGBFramebuffer = kUnknown_TriState;
475     }
476 
477     if (resetBits & kPathRendering_GrGLBackendState) {
478         if (this->caps()->shaderCaps()->pathRenderingSupport()) {
479             this->glPathRendering()->resetContext();
480         }
481     }
482 
483     // we assume these values
484     if (resetBits & kPixelStore_GrGLBackendState) {
485         if (this->glCaps().unpackRowLengthSupport()) {
486             GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, 0));
487         }
488         if (this->glCaps().packRowLengthSupport()) {
489             GL_CALL(PixelStorei(GR_GL_PACK_ROW_LENGTH, 0));
490         }
491         if (this->glCaps().unpackFlipYSupport()) {
492             GL_CALL(PixelStorei(GR_GL_UNPACK_FLIP_Y, GR_GL_FALSE));
493         }
494         if (this->glCaps().packFlipYSupport()) {
495             GL_CALL(PixelStorei(GR_GL_PACK_REVERSE_ROW_ORDER, GR_GL_FALSE));
496         }
497     }
498 
499     if (resetBits & kProgram_GrGLBackendState) {
500         fHWProgramID = 0;
501     }
502 }
503 
check_backend_texture(const GrBackendTexture & backendTex,const GrGLCaps & caps,GrGLTexture::IDDesc * idDesc)504 static bool check_backend_texture(const GrBackendTexture& backendTex, const GrGLCaps& caps,
505                                   GrGLTexture::IDDesc* idDesc) {
506     const GrGLTextureInfo* info = backendTex.getGLTextureInfo();
507     if (!info || !info->fID) {
508         return false;
509     }
510 
511     idDesc->fInfo = *info;
512 
513     if (GR_GL_TEXTURE_EXTERNAL == idDesc->fInfo.fTarget) {
514         if (!caps.shaderCaps()->externalTextureSupport()) {
515             return false;
516         }
517     } else if (GR_GL_TEXTURE_RECTANGLE == idDesc->fInfo.fTarget) {
518         if (!caps.rectangleTextureSupport()) {
519             return false;
520         }
521     } else if (GR_GL_TEXTURE_2D != idDesc->fInfo.fTarget) {
522         return false;
523     }
524     return true;
525 }
526 
onWrapBackendTexture(const GrBackendTexture & backendTex,GrWrapOwnership ownership)527 sk_sp<GrTexture> GrGLGpu::onWrapBackendTexture(const GrBackendTexture& backendTex,
528                                                GrWrapOwnership ownership) {
529     GrGLTexture::IDDesc idDesc;
530     if (!check_backend_texture(backendTex, this->glCaps(), &idDesc)) {
531         return nullptr;
532     }
533     if (!idDesc.fInfo.fFormat) {
534         idDesc.fInfo.fFormat = this->glCaps().configSizedInternalFormat(backendTex.config());
535     }
536     if (kBorrow_GrWrapOwnership == ownership) {
537         idDesc.fOwnership = GrBackendObjectOwnership::kBorrowed;
538     } else {
539         idDesc.fOwnership = GrBackendObjectOwnership::kOwned;
540     }
541 
542     GrSurfaceDesc surfDesc;
543     surfDesc.fFlags = kNone_GrSurfaceFlags;
544     surfDesc.fOrigin = kTopLeft_GrSurfaceOrigin; // This isn't used in the following
545     surfDesc.fWidth = backendTex.width();
546     surfDesc.fHeight = backendTex.height();
547     surfDesc.fConfig = backendTex.config();
548     surfDesc.fSampleCnt = 1;
549 
550     GrMipMapsStatus mipMapsStatus = backendTex.hasMipMaps() ? GrMipMapsStatus::kValid
551                                                             : GrMipMapsStatus::kNotAllocated;
552 
553     return GrGLTexture::MakeWrapped(this, surfDesc, mipMapsStatus, idDesc);
554 }
555 
onWrapRenderableBackendTexture(const GrBackendTexture & backendTex,int sampleCnt,GrWrapOwnership ownership)556 sk_sp<GrTexture> GrGLGpu::onWrapRenderableBackendTexture(const GrBackendTexture& backendTex,
557                                                          int sampleCnt,
558                                                          GrWrapOwnership ownership) {
559     GrGLTexture::IDDesc idDesc;
560     if (!check_backend_texture(backendTex, this->glCaps(), &idDesc)) {
561         return nullptr;
562     }
563     if (!idDesc.fInfo.fFormat) {
564         idDesc.fInfo.fFormat = this->glCaps().configSizedInternalFormat(backendTex.config());
565     }
566 
567     // We don't support rendering to a EXTERNAL texture.
568     if (GR_GL_TEXTURE_EXTERNAL == idDesc.fInfo.fTarget) {
569         return nullptr;
570     }
571 
572     if (kBorrow_GrWrapOwnership == ownership) {
573         idDesc.fOwnership = GrBackendObjectOwnership::kBorrowed;
574     } else {
575         idDesc.fOwnership = GrBackendObjectOwnership::kOwned;
576     }
577 
578     GrSurfaceDesc surfDesc;
579     surfDesc.fFlags = kRenderTarget_GrSurfaceFlag;
580     surfDesc.fOrigin = kBottomLeft_GrSurfaceOrigin; // This isn't actually used in the following
581     surfDesc.fWidth = backendTex.width();
582     surfDesc.fHeight = backendTex.height();
583     surfDesc.fConfig = backendTex.config();
584     surfDesc.fSampleCnt = this->caps()->getSampleCount(sampleCnt, backendTex.config());
585     if (surfDesc.fSampleCnt < 1) {
586         return nullptr;
587     }
588 
589     GrGLRenderTarget::IDDesc rtIDDesc;
590     if (!this->createRenderTargetObjects(surfDesc, idDesc.fInfo, &rtIDDesc)) {
591         return nullptr;
592     }
593 
594     GrMipMapsStatus mipMapsStatus = backendTex.hasMipMaps() ? GrMipMapsStatus::kDirty
595                                                             : GrMipMapsStatus::kNotAllocated;
596 
597     sk_sp<GrGLTextureRenderTarget> texRT(
598             GrGLTextureRenderTarget::MakeWrapped(this, surfDesc, idDesc, rtIDDesc, mipMapsStatus));
599     texRT->baseLevelWasBoundToFBO();
600     return std::move(texRT);
601 }
602 
onWrapBackendRenderTarget(const GrBackendRenderTarget & backendRT)603 sk_sp<GrRenderTarget> GrGLGpu::onWrapBackendRenderTarget(const GrBackendRenderTarget& backendRT) {
604     const GrGLFramebufferInfo* info = backendRT.getGLFramebufferInfo();
605     if (!info) {
606         return nullptr;
607     }
608 
609     GrGLRenderTarget::IDDesc idDesc;
610     idDesc.fRTFBOID = info->fFBOID;
611     idDesc.fMSColorRenderbufferID = 0;
612     idDesc.fTexFBOID = GrGLRenderTarget::kUnresolvableFBOID;
613     idDesc.fRTFBOOwnership = GrBackendObjectOwnership::kBorrowed;
614     idDesc.fIsMixedSampled = false;
615 
616     GrSurfaceDesc desc;
617     desc.fFlags = kRenderTarget_GrSurfaceFlag;
618     desc.fOrigin = kBottomLeft_GrSurfaceOrigin; // This isn't actually used in the following
619     desc.fWidth = backendRT.width();
620     desc.fHeight = backendRT.height();
621     desc.fConfig = backendRT.config();
622     desc.fSampleCnt = this->caps()->getSampleCount(backendRT.sampleCnt(), backendRT.config());
623 
624     return GrGLRenderTarget::MakeWrapped(this, desc, idDesc, backendRT.stencilBits());
625 }
626 
onWrapBackendTextureAsRenderTarget(const GrBackendTexture & tex,int sampleCnt)627 sk_sp<GrRenderTarget> GrGLGpu::onWrapBackendTextureAsRenderTarget(const GrBackendTexture& tex,
628                                                                   int sampleCnt) {
629     const GrGLTextureInfo* info = tex.getGLTextureInfo();
630     if (!info || !info->fID) {
631         return nullptr;
632     }
633 
634     GrGLTextureInfo texInfo;
635     texInfo = *info;
636 
637     if (GR_GL_TEXTURE_RECTANGLE != texInfo.fTarget &&
638         GR_GL_TEXTURE_2D != texInfo.fTarget) {
639         // Only texture rectangle and texture 2d are supported. We do not check whether texture
640         // rectangle is supported by Skia - if the caller provided us with a texture rectangle,
641         // we assume the necessary support exists.
642         return nullptr;
643     }
644 
645     GrSurfaceDesc surfDesc;
646     surfDesc.fFlags = kRenderTarget_GrSurfaceFlag;
647     surfDesc.fOrigin = kBottomLeft_GrSurfaceOrigin; // This isn't actually used in the following
648     surfDesc.fWidth = tex.width();
649     surfDesc.fHeight = tex.height();
650     surfDesc.fConfig = tex.config();
651     surfDesc.fSampleCnt = this->caps()->getSampleCount(sampleCnt, tex.config());
652 
653     GrGLRenderTarget::IDDesc rtIDDesc;
654     if (!this->createRenderTargetObjects(surfDesc, texInfo, &rtIDDesc)) {
655         return nullptr;
656     }
657     return GrGLRenderTarget::MakeWrapped(this, surfDesc, rtIDDesc, 0);
658 }
659 
660 ////////////////////////////////////////////////////////////////////////////////
661 
onGetWritePixelsInfo(GrSurface * dstSurface,GrSurfaceOrigin dstOrigin,int width,int height,GrPixelConfig srcConfig,DrawPreference * drawPreference,WritePixelTempDrawInfo * tempDrawInfo)662 bool GrGLGpu::onGetWritePixelsInfo(GrSurface* dstSurface, GrSurfaceOrigin dstOrigin,
663                                    int width, int height,
664                                    GrPixelConfig srcConfig,
665                                    DrawPreference* drawPreference,
666                                    WritePixelTempDrawInfo* tempDrawInfo) {
667     if (SkToBool(dstSurface->asRenderTarget())) {
668         if (this->glCaps().useDrawInsteadOfAllRenderTargetWrites()) {
669             ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
670         }
671     }
672 
673     GrGLTexture* texture = static_cast<GrGLTexture*>(dstSurface->asTexture());
674 
675     if (texture) {
676         if (GR_GL_TEXTURE_EXTERNAL == texture->target()) {
677              // We don't currently support writing pixels to EXTERNAL textures.
678              return false;
679         }
680         if (GrPixelConfigIsUnorm(texture->config()) && texture->hasBaseLevelBeenBoundToFBO() &&
681             this->glCaps().disallowTexSubImageForUnormConfigTexturesEverBoundToFBO() &&
682             (width < dstSurface->width() || height < dstSurface->height())) {
683             ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
684         }
685     } else {
686         // This subclass only allows writes to textures. If the dst is not a texture we have to draw
687         // into it. We could use glDrawPixels on GLs that have it, but we don't today.
688         ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
689     }
690 
691     // If the dst is MSAA, we have to draw, or we'll just be writing to the resolve target.
692     if (dstSurface->asRenderTarget() && dstSurface->asRenderTarget()->numColorSamples() > 1) {
693         ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
694     }
695 
696     if (GrPixelConfigIsSRGB(dstSurface->config()) != GrPixelConfigIsSRGB(srcConfig)) {
697         ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
698     }
699 
700     // Start off assuming no swizzling
701     tempDrawInfo->fSwizzle = GrSwizzle::RGBA();
702     tempDrawInfo->fWriteConfig = srcConfig;
703 
704     // These settings we will always want if a temp draw is performed. Initially set the config
705     // to srcConfig, though that may be modified if we decide to do a R/G swap.
706     tempDrawInfo->fTempSurfaceDesc.fFlags = kNone_GrSurfaceFlags;
707     tempDrawInfo->fTempSurfaceDesc.fConfig = srcConfig;
708     tempDrawInfo->fTempSurfaceDesc.fWidth = width;
709     tempDrawInfo->fTempSurfaceDesc.fHeight = height;
710     tempDrawInfo->fTempSurfaceDesc.fSampleCnt = 1;
711     tempDrawInfo->fTempSurfaceDesc.fOrigin = kTopLeft_GrSurfaceOrigin; // no CPU y-flip for TL.
712 
713     bool configsAreRBSwaps = GrPixelConfigSwapRAndB(srcConfig) == dstSurface->config();
714 
715     if (configsAreRBSwaps) {
716         if (!this->caps()->isConfigTexturable(srcConfig)) {
717             ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
718             tempDrawInfo->fTempSurfaceDesc.fConfig = dstSurface->config();
719             tempDrawInfo->fSwizzle = GrSwizzle::BGRA();
720             tempDrawInfo->fWriteConfig = dstSurface->config();
721         } else if (this->glCaps().rgba8888PixelsOpsAreSlow() &&
722                    kRGBA_8888_GrPixelConfig == srcConfig) {
723             ElevateDrawPreference(drawPreference, kGpuPrefersDraw_DrawPreference);
724             tempDrawInfo->fTempSurfaceDesc.fConfig = dstSurface->config();
725             tempDrawInfo->fSwizzle = GrSwizzle::BGRA();
726             tempDrawInfo->fWriteConfig = dstSurface->config();
727         } else if (kGLES_GrGLStandard == this->glStandard() &&
728                    this->glCaps().bgraIsInternalFormat()) {
729             // The internal format and external formats must match texture uploads so we can't
730             // swizzle while uploading when BGRA is a distinct internal format.
731             ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
732             tempDrawInfo->fTempSurfaceDesc.fConfig = dstSurface->config();
733             tempDrawInfo->fSwizzle = GrSwizzle::BGRA();
734             tempDrawInfo->fWriteConfig = dstSurface->config();
735         }
736     }
737 
738     if (!this->glCaps().unpackFlipYSupport() && kBottomLeft_GrSurfaceOrigin == dstOrigin) {
739         ElevateDrawPreference(drawPreference, kGpuPrefersDraw_DrawPreference);
740     }
741 
742     return true;
743 }
744 
check_write_and_transfer_input(GrGLTexture * glTex,GrSurface * surface,GrPixelConfig config)745 static bool check_write_and_transfer_input(GrGLTexture* glTex, GrSurface* surface,
746                                             GrPixelConfig config) {
747     if (!glTex) {
748         return false;
749     }
750 
751     // OpenGL doesn't do sRGB <-> linear conversions when reading and writing pixels.
752     if (GrPixelConfigIsSRGB(surface->config()) != GrPixelConfigIsSRGB(config)) {
753         return false;
754     }
755 
756     // Write or transfer of pixels is not implemented for TEXTURE_EXTERNAL textures
757     if (GR_GL_TEXTURE_EXTERNAL == glTex->target()) {
758         return false;
759     }
760 
761     return true;
762 }
763 
onWritePixels(GrSurface * surface,GrSurfaceOrigin origin,int left,int top,int width,int height,GrPixelConfig config,const GrMipLevel texels[],int mipLevelCount)764 bool GrGLGpu::onWritePixels(GrSurface* surface, GrSurfaceOrigin origin,
765                             int left, int top, int width, int height,
766                             GrPixelConfig config,
767                             const GrMipLevel texels[],
768                             int mipLevelCount) {
769     GrGLTexture* glTex = static_cast<GrGLTexture*>(surface->asTexture());
770 
771     if (!check_write_and_transfer_input(glTex, surface, config)) {
772         return false;
773     }
774 
775     this->setScratchTextureUnit();
776     GL_CALL(BindTexture(glTex->target(), glTex->textureID()));
777 
778     return this->uploadTexData(glTex->config(), glTex->width(), glTex->height(),
779                                origin, glTex->target(), kWrite_UploadType,
780                                left, top, width, height, config, texels, mipLevelCount);
781 }
782 
783 // For GL_[UN]PACK_ALIGNMENT.
config_alignment(GrPixelConfig config)784 static inline GrGLint config_alignment(GrPixelConfig config) {
785     switch (config) {
786         case kAlpha_8_GrPixelConfig:
787         case kAlpha_8_as_Alpha_GrPixelConfig:
788         case kAlpha_8_as_Red_GrPixelConfig:
789         case kGray_8_GrPixelConfig:
790         case kGray_8_as_Lum_GrPixelConfig:
791         case kGray_8_as_Red_GrPixelConfig:
792             return 1;
793         case kRGB_565_GrPixelConfig:
794         case kRGBA_4444_GrPixelConfig:
795         case kAlpha_half_GrPixelConfig:
796         case kAlpha_half_as_Red_GrPixelConfig:
797         case kRGBA_half_GrPixelConfig:
798             return 2;
799         case kRGBA_8888_GrPixelConfig:
800         case kBGRA_8888_GrPixelConfig:
801         case kSRGBA_8888_GrPixelConfig:
802         case kSBGRA_8888_GrPixelConfig:
803         case kRGBA_8888_sint_GrPixelConfig:
804         case kRGBA_float_GrPixelConfig:
805         case kRG_float_GrPixelConfig:
806             return 4;
807         case kUnknown_GrPixelConfig:
808             return 0;
809     }
810     SK_ABORT("Invalid pixel config");
811     return 0;
812 }
813 
onTransferPixels(GrTexture * texture,int left,int top,int width,int height,GrPixelConfig config,GrBuffer * transferBuffer,size_t offset,size_t rowBytes)814 bool GrGLGpu::onTransferPixels(GrTexture* texture,
815                                int left, int top, int width, int height,
816                                GrPixelConfig config, GrBuffer* transferBuffer,
817                                size_t offset, size_t rowBytes) {
818     GrGLTexture* glTex = static_cast<GrGLTexture*>(texture);
819     GrPixelConfig texConfig = glTex->config();
820     SkASSERT(this->caps()->isConfigTexturable(texConfig));
821 
822     if (!check_write_and_transfer_input(glTex, texture, config)) {
823         return false;
824     }
825 
826     if (width <= 0 || width > SK_MaxS32 || height <= 0 || height > SK_MaxS32) {
827         return false;
828     }
829 
830     this->setScratchTextureUnit();
831     GL_CALL(BindTexture(glTex->target(), glTex->textureID()));
832 
833     SkASSERT(!transferBuffer->isMapped());
834     SkASSERT(!transferBuffer->isCPUBacked());
835     const GrGLBuffer* glBuffer = static_cast<const GrGLBuffer*>(transferBuffer);
836     this->bindBuffer(kXferCpuToGpu_GrBufferType, glBuffer);
837 
838     SkDEBUGCODE(
839         SkIRect subRect = SkIRect::MakeXYWH(left, top, width, height);
840         SkIRect bounds = SkIRect::MakeWH(texture->width(), texture->height());
841         SkASSERT(bounds.contains(subRect));
842     )
843 
844     size_t bpp = GrBytesPerPixel(config);
845     const size_t trimRowBytes = width * bpp;
846     if (!rowBytes) {
847         rowBytes = trimRowBytes;
848     }
849     const void* pixels = (void*)offset;
850     if (width < 0 || height < 0) {
851         return false;
852     }
853 
854     bool restoreGLRowLength = false;
855     if (trimRowBytes != rowBytes) {
856         // we should have checked for this support already
857         SkASSERT(this->glCaps().unpackRowLengthSupport());
858         GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, rowBytes / bpp));
859         restoreGLRowLength = true;
860     }
861 
862     // Internal format comes from the texture desc.
863     GrGLenum internalFormat;
864     // External format and type come from the upload data.
865     GrGLenum externalFormat;
866     GrGLenum externalType;
867     if (!this->glCaps().getTexImageFormats(texConfig, config, &internalFormat,
868                                            &externalFormat, &externalType)) {
869         return false;
870     }
871 
872     GL_CALL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, config_alignment(texConfig)));
873     GL_CALL(TexSubImage2D(glTex->target(),
874                           0,
875                           left, top,
876                           width,
877                           height,
878                           externalFormat, externalType,
879                           pixels));
880 
881     if (restoreGLRowLength) {
882         GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, 0));
883     }
884 
885     return true;
886 }
887 
888 /**
889  * Creates storage space for the texture and fills it with texels.
890  *
891  * @param config         Pixel config of the texture.
892  * @param interface      The GL interface in use.
893  * @param caps           The capabilities of the GL device.
894  * @param internalFormat The data format used for the internal storage of the texture. May be sized.
895  * @param internalFormatForTexStorage The data format used for the TexStorage API. Must be sized.
896  * @param externalFormat The data format used for the external storage of the texture.
897  * @param externalType   The type of the data used for the external storage of the texture.
898  * @param texels         The texel data of the texture being created.
899  * @param baseWidth      The width of the texture's base mipmap level
900  * @param baseHeight     The height of the texture's base mipmap level
901  */
allocate_and_populate_texture(GrPixelConfig config,const GrGLInterface & interface,const GrGLCaps & caps,GrGLenum target,GrGLenum internalFormat,GrGLenum internalFormatForTexStorage,GrGLenum externalFormat,GrGLenum externalType,const GrMipLevel texels[],int mipLevelCount,int baseWidth,int baseHeight)902 static bool allocate_and_populate_texture(GrPixelConfig config,
903                                           const GrGLInterface& interface,
904                                           const GrGLCaps& caps,
905                                           GrGLenum target,
906                                           GrGLenum internalFormat,
907                                           GrGLenum internalFormatForTexStorage,
908                                           GrGLenum externalFormat,
909                                           GrGLenum externalType,
910                                           const GrMipLevel texels[], int mipLevelCount,
911                                           int baseWidth, int baseHeight) {
912     CLEAR_ERROR_BEFORE_ALLOC(&interface);
913 
914     bool useTexStorage = caps.isConfigTexSupportEnabled(config);
915     // We can only use TexStorage if we know we will not later change the storage requirements.
916     // This means if we may later want to add mipmaps, we cannot use TexStorage.
917     // Right now, we cannot know if we will later add mipmaps or not.
918     // The only time we can use TexStorage is when we already have the
919     // mipmaps or are using a format incompatible with MIP maps.
920     useTexStorage &= mipLevelCount > 1 || GrPixelConfigIsSint(config);
921 
922     if (useTexStorage) {
923         // We never resize or change formats of textures.
924         GL_ALLOC_CALL(&interface,
925                       TexStorage2D(target, SkTMax(mipLevelCount, 1), internalFormatForTexStorage,
926                                    baseWidth, baseHeight));
927         GrGLenum error = CHECK_ALLOC_ERROR(&interface);
928         if (error != GR_GL_NO_ERROR) {
929             return  false;
930         } else {
931             for (int currentMipLevel = 0; currentMipLevel < mipLevelCount; currentMipLevel++) {
932                 const void* currentMipData = texels[currentMipLevel].fPixels;
933                 if (currentMipData == nullptr) {
934                     continue;
935                 }
936                 int twoToTheMipLevel = 1 << currentMipLevel;
937                 int currentWidth = SkTMax(1, baseWidth / twoToTheMipLevel);
938                 int currentHeight = SkTMax(1, baseHeight / twoToTheMipLevel);
939 
940                 GR_GL_CALL(&interface,
941                            TexSubImage2D(target,
942                                          currentMipLevel,
943                                          0, // left
944                                          0, // top
945                                          currentWidth,
946                                          currentHeight,
947                                          externalFormat, externalType,
948                                          currentMipData));
949             }
950             return true;
951         }
952     } else {
953         if (!mipLevelCount) {
954             GL_ALLOC_CALL(&interface,
955                           TexImage2D(target,
956                                      0,
957                                      internalFormat,
958                                      baseWidth,
959                                      baseHeight,
960                                      0, // border
961                                      externalFormat, externalType,
962                                      nullptr));
963             GrGLenum error = CHECK_ALLOC_ERROR(&interface);
964             if (error != GR_GL_NO_ERROR) {
965                 return false;
966             }
967         } else {
968             for (int currentMipLevel = 0; currentMipLevel < mipLevelCount; currentMipLevel++) {
969                 int twoToTheMipLevel = 1 << currentMipLevel;
970                 int currentWidth = SkTMax(1, baseWidth / twoToTheMipLevel);
971                 int currentHeight = SkTMax(1, baseHeight / twoToTheMipLevel);
972                 const void* currentMipData = texels[currentMipLevel].fPixels;
973                 // Even if curremtMipData is nullptr, continue to call TexImage2D.
974                 // This will allocate texture memory which we can later populate.
975                 GL_ALLOC_CALL(&interface,
976                               TexImage2D(target,
977                                          currentMipLevel,
978                                          internalFormat,
979                                          currentWidth,
980                                          currentHeight,
981                                          0, // border
982                                          externalFormat, externalType,
983                                          currentMipData));
984                 GrGLenum error = CHECK_ALLOC_ERROR(&interface);
985                 if (error != GR_GL_NO_ERROR) {
986                     return false;
987                 }
988             }
989         }
990     }
991     return true;
992 }
993 
994 /**
995  * After a texture is created, any state which was altered during its creation
996  * needs to be restored.
997  *
998  * @param interface          The GL interface to use.
999  * @param caps               The capabilities of the GL device.
1000  * @param restoreGLRowLength Should the row length unpacking be restored?
1001  * @param glFlipY            Did GL flip the texture vertically?
1002  */
restore_pixelstore_state(const GrGLInterface & interface,const GrGLCaps & caps,bool restoreGLRowLength,bool glFlipY)1003 static void restore_pixelstore_state(const GrGLInterface& interface, const GrGLCaps& caps,
1004                                      bool restoreGLRowLength, bool glFlipY) {
1005     if (restoreGLRowLength) {
1006         SkASSERT(caps.unpackRowLengthSupport());
1007         GR_GL_CALL(&interface, PixelStorei(GR_GL_UNPACK_ROW_LENGTH, 0));
1008     }
1009     if (glFlipY) {
1010         GR_GL_CALL(&interface, PixelStorei(GR_GL_UNPACK_FLIP_Y, GR_GL_FALSE));
1011     }
1012 }
1013 
unbindCpuToGpuXferBuffer()1014 void GrGLGpu::unbindCpuToGpuXferBuffer() {
1015     auto& xferBufferState = fHWBufferState[kXferCpuToGpu_GrBufferType];
1016     if (!xferBufferState.fBoundBufferUniqueID.isInvalid()) {
1017         GL_CALL(BindBuffer(xferBufferState.fGLTarget, 0));
1018         xferBufferState.invalidate();
1019     }
1020 
1021 }
1022 
uploadTexData(GrPixelConfig texConfig,int texWidth,int texHeight,GrSurfaceOrigin texOrigin,GrGLenum target,UploadType uploadType,int left,int top,int width,int height,GrPixelConfig dataConfig,const GrMipLevel texels[],int mipLevelCount,GrMipMapsStatus * mipMapsStatus)1023 bool GrGLGpu::uploadTexData(GrPixelConfig texConfig, int texWidth, int texHeight,
1024                             GrSurfaceOrigin texOrigin, GrGLenum target, UploadType uploadType,
1025                             int left, int top, int width, int height, GrPixelConfig dataConfig,
1026                             const GrMipLevel texels[], int mipLevelCount,
1027                             GrMipMapsStatus* mipMapsStatus) {
1028     SkASSERT(this->caps()->isConfigTexturable(texConfig));
1029     SkDEBUGCODE(
1030         SkIRect subRect = SkIRect::MakeXYWH(left, top, width, height);
1031         SkIRect bounds = SkIRect::MakeWH(texWidth, texHeight);
1032         SkASSERT(bounds.contains(subRect));
1033     )
1034     SkASSERT(1 == mipLevelCount ||
1035              (0 == left && 0 == top && width == texWidth && height == texHeight));
1036 
1037     this->unbindCpuToGpuXferBuffer();
1038 
1039     // texels is const.
1040     // But we may need to flip the texture vertically to prepare it.
1041     // Rather than flip in place and alter the incoming data,
1042     // we allocate a new buffer to flip into.
1043     // This means we need to make a non-const shallow copy of texels.
1044     SkAutoTMalloc<GrMipLevel> texelsShallowCopy;
1045 
1046     if (mipLevelCount) {
1047         texelsShallowCopy.reset(mipLevelCount);
1048         memcpy(texelsShallowCopy.get(), texels, mipLevelCount*sizeof(GrMipLevel));
1049     }
1050 
1051     const GrGLInterface* interface = this->glInterface();
1052     const GrGLCaps& caps = this->glCaps();
1053 
1054     size_t bpp = GrBytesPerPixel(dataConfig);
1055 
1056     if (width == 0 || height == 0) {
1057         return false;
1058     }
1059 
1060     // Internal format comes from the texture desc.
1061     GrGLenum internalFormat;
1062     // External format and type come from the upload data.
1063     GrGLenum externalFormat;
1064     GrGLenum externalType;
1065     if (!this->glCaps().getTexImageFormats(texConfig, dataConfig, &internalFormat, &externalFormat,
1066                                            &externalType)) {
1067         return false;
1068     }
1069     // TexStorage requires a sized format, and internalFormat may or may not be
1070     GrGLenum internalFormatForTexStorage = this->glCaps().configSizedInternalFormat(texConfig);
1071 
1072     /*
1073      *  Check whether to allocate a temporary buffer for flipping y or
1074      *  because our srcData has extra bytes past each row. If so, we need
1075      *  to trim those off here, since GL ES may not let us specify
1076      *  GL_UNPACK_ROW_LENGTH.
1077      */
1078     bool restoreGLRowLength = false;
1079     bool swFlipY = false;
1080     bool glFlipY = false;
1081 
1082     if (kBottomLeft_GrSurfaceOrigin == texOrigin && mipLevelCount) {
1083         if (caps.unpackFlipYSupport()) {
1084             glFlipY = true;
1085         } else {
1086             swFlipY = true;
1087         }
1088     }
1089 
1090     // in case we need a temporary, trimmed copy of the src pixels
1091     SkAutoSMalloc<128 * 128> tempStorage;
1092 
1093     if (mipMapsStatus) {
1094         *mipMapsStatus = GrMipMapsStatus::kValid;
1095     }
1096 
1097     const bool usesMips = mipLevelCount > 1;
1098 
1099     // find the combined size of all the mip levels and the relative offset of
1100     // each into the collective buffer
1101     bool willNeedData = false;
1102     size_t combinedBufferSize = 0;
1103     SkTArray<size_t> individualMipOffsets(mipLevelCount);
1104     for (int currentMipLevel = 0; currentMipLevel < mipLevelCount; currentMipLevel++) {
1105         if (texelsShallowCopy[currentMipLevel].fPixels) {
1106             int twoToTheMipLevel = 1 << currentMipLevel;
1107             int currentWidth = SkTMax(1, width / twoToTheMipLevel);
1108             int currentHeight = SkTMax(1, height / twoToTheMipLevel);
1109             const size_t trimRowBytes = currentWidth * bpp;
1110             const size_t trimmedSize = trimRowBytes * currentHeight;
1111 
1112             const size_t rowBytes = texelsShallowCopy[currentMipLevel].fRowBytes
1113                     ? texelsShallowCopy[currentMipLevel].fRowBytes
1114                     : trimRowBytes;
1115 
1116 
1117             if (((!caps.unpackRowLengthSupport() || usesMips) && trimRowBytes != rowBytes) ||
1118                 swFlipY) {
1119                 willNeedData = true;
1120             }
1121 
1122             individualMipOffsets.push_back(combinedBufferSize);
1123             combinedBufferSize += trimmedSize;
1124         } else {
1125             if (mipMapsStatus) {
1126                 *mipMapsStatus = GrMipMapsStatus::kDirty;
1127             }
1128             individualMipOffsets.push_back(0);
1129         }
1130     }
1131     if (mipMapsStatus && mipLevelCount <= 1) {
1132         *mipMapsStatus = GrMipMapsStatus::kNotAllocated;
1133     }
1134     char* buffer = nullptr;
1135     if (willNeedData) {
1136         buffer = (char*)tempStorage.reset(combinedBufferSize);
1137     }
1138 
1139     for (int currentMipLevel = 0; currentMipLevel < mipLevelCount; currentMipLevel++) {
1140         if (!texelsShallowCopy[currentMipLevel].fPixels) {
1141             continue;
1142         }
1143         int twoToTheMipLevel = 1 << currentMipLevel;
1144         int currentWidth = SkTMax(1, width / twoToTheMipLevel);
1145         int currentHeight = SkTMax(1, height / twoToTheMipLevel);
1146         const size_t trimRowBytes = currentWidth * bpp;
1147 
1148         /*
1149          *  check whether to allocate a temporary buffer for flipping y or
1150          *  because our srcData has extra bytes past each row. If so, we need
1151          *  to trim those off here, since GL ES may not let us specify
1152          *  GL_UNPACK_ROW_LENGTH.
1153          */
1154         restoreGLRowLength = false;
1155 
1156         const size_t rowBytes = texelsShallowCopy[currentMipLevel].fRowBytes
1157                 ? texelsShallowCopy[currentMipLevel].fRowBytes
1158                 : trimRowBytes;
1159 
1160         // TODO: This optimization should be enabled with or without mips.
1161         // For use with mips, we must set GR_GL_UNPACK_ROW_LENGTH once per
1162         // mip level, before calling glTexImage2D.
1163         if (caps.unpackRowLengthSupport() && !swFlipY && !usesMips) {
1164             // can't use this for flipping, only non-neg values allowed. :(
1165             if (rowBytes != trimRowBytes) {
1166                 GrGLint rowLength = static_cast<GrGLint>(rowBytes / bpp);
1167                 GR_GL_CALL(interface, PixelStorei(GR_GL_UNPACK_ROW_LENGTH, rowLength));
1168                 restoreGLRowLength = true;
1169             }
1170         } else if (trimRowBytes != rowBytes || swFlipY) {
1171             // copy data into our new storage, skipping the trailing bytes
1172             const char* src = (const char*)texelsShallowCopy[currentMipLevel].fPixels;
1173             if (swFlipY && currentHeight >= 1) {
1174                 src += (currentHeight - 1) * rowBytes;
1175             }
1176             char* dst = buffer + individualMipOffsets[currentMipLevel];
1177             for (int y = 0; y < currentHeight; y++) {
1178                 memcpy(dst, src, trimRowBytes);
1179                 if (swFlipY) {
1180                     src -= rowBytes;
1181                 } else {
1182                     src += rowBytes;
1183                 }
1184                 dst += trimRowBytes;
1185             }
1186             // now point data to our copied version
1187             texelsShallowCopy[currentMipLevel].fPixels = buffer +
1188                 individualMipOffsets[currentMipLevel];
1189             texelsShallowCopy[currentMipLevel].fRowBytes = trimRowBytes;
1190         }
1191     }
1192 
1193     if (mipLevelCount) {
1194         if (glFlipY) {
1195             GR_GL_CALL(interface, PixelStorei(GR_GL_UNPACK_FLIP_Y, GR_GL_TRUE));
1196         }
1197         GR_GL_CALL(interface, PixelStorei(GR_GL_UNPACK_ALIGNMENT, config_alignment(texConfig)));
1198     }
1199 
1200     bool succeeded = true;
1201     if (kNewTexture_UploadType == uploadType) {
1202         if (0 == left && 0 == top && texWidth == width && texHeight == height) {
1203             succeeded = allocate_and_populate_texture(
1204                     texConfig, *interface, caps, target, internalFormat,
1205                     internalFormatForTexStorage, externalFormat, externalType,
1206                     texelsShallowCopy, mipLevelCount, width, height);
1207         } else {
1208             succeeded = false;
1209         }
1210     } else {
1211         if (swFlipY || glFlipY) {
1212             top = texHeight - (top + height);
1213         }
1214         for (int currentMipLevel = 0; currentMipLevel < mipLevelCount; currentMipLevel++) {
1215             if (!texelsShallowCopy[currentMipLevel].fPixels) {
1216                 continue;
1217             }
1218             int twoToTheMipLevel = 1 << currentMipLevel;
1219             int currentWidth = SkTMax(1, width / twoToTheMipLevel);
1220             int currentHeight = SkTMax(1, height / twoToTheMipLevel);
1221 
1222             GL_CALL(TexSubImage2D(target,
1223                                   currentMipLevel,
1224                                   left, top,
1225                                   currentWidth,
1226                                   currentHeight,
1227                                   externalFormat, externalType,
1228                                   texelsShallowCopy[currentMipLevel].fPixels));
1229         }
1230     }
1231 
1232     restore_pixelstore_state(*interface, caps, restoreGLRowLength, glFlipY);
1233 
1234     return succeeded;
1235 }
1236 
renderbuffer_storage_msaa(const GrGLContext & ctx,int sampleCount,GrGLenum format,int width,int height)1237 static bool renderbuffer_storage_msaa(const GrGLContext& ctx,
1238                                       int sampleCount,
1239                                       GrGLenum format,
1240                                       int width, int height) {
1241     CLEAR_ERROR_BEFORE_ALLOC(ctx.interface());
1242     SkASSERT(GrGLCaps::kNone_MSFBOType != ctx.caps()->msFBOType());
1243     switch (ctx.caps()->msFBOType()) {
1244         case GrGLCaps::kStandard_MSFBOType:
1245         case GrGLCaps::kMixedSamples_MSFBOType:
1246             GL_ALLOC_CALL(ctx.interface(),
1247                             RenderbufferStorageMultisample(GR_GL_RENDERBUFFER,
1248                                                             sampleCount,
1249                                                             format,
1250                                                             width, height));
1251             break;
1252         case GrGLCaps::kES_Apple_MSFBOType:
1253             GL_ALLOC_CALL(ctx.interface(),
1254                             RenderbufferStorageMultisampleES2APPLE(GR_GL_RENDERBUFFER,
1255                                                                     sampleCount,
1256                                                                     format,
1257                                                                     width, height));
1258             break;
1259         case GrGLCaps::kES_EXT_MsToTexture_MSFBOType:
1260         case GrGLCaps::kES_IMG_MsToTexture_MSFBOType:
1261             GL_ALLOC_CALL(ctx.interface(),
1262                             RenderbufferStorageMultisampleES2EXT(GR_GL_RENDERBUFFER,
1263                                                                 sampleCount,
1264                                                                 format,
1265                                                                 width, height));
1266             break;
1267         case GrGLCaps::kNone_MSFBOType:
1268             SK_ABORT("Shouldn't be here if we don't support multisampled renderbuffers.");
1269             break;
1270     }
1271     return (GR_GL_NO_ERROR == CHECK_ALLOC_ERROR(ctx.interface()));
1272 }
1273 
createRenderTargetObjects(const GrSurfaceDesc & desc,const GrGLTextureInfo & texInfo,GrGLRenderTarget::IDDesc * idDesc)1274 bool GrGLGpu::createRenderTargetObjects(const GrSurfaceDesc& desc,
1275                                         const GrGLTextureInfo& texInfo,
1276                                         GrGLRenderTarget::IDDesc* idDesc) {
1277     idDesc->fMSColorRenderbufferID = 0;
1278     idDesc->fRTFBOID = 0;
1279     idDesc->fRTFBOOwnership = GrBackendObjectOwnership::kOwned;
1280     idDesc->fTexFBOID = 0;
1281     SkASSERT((GrGLCaps::kMixedSamples_MSFBOType == this->glCaps().msFBOType()) ==
1282              this->caps()->usesMixedSamples());
1283     idDesc->fIsMixedSampled = desc.fSampleCnt > 1 && this->caps()->usesMixedSamples();
1284 
1285     GrGLenum status;
1286 
1287     GrGLenum colorRenderbufferFormat = 0; // suppress warning
1288 
1289     if (desc.fSampleCnt > 1 && GrGLCaps::kNone_MSFBOType == this->glCaps().msFBOType()) {
1290         goto FAILED;
1291     }
1292 
1293     GL_CALL(GenFramebuffers(1, &idDesc->fTexFBOID));
1294     if (!idDesc->fTexFBOID) {
1295         goto FAILED;
1296     }
1297 
1298     // If we are using multisampling we will create two FBOS. We render to one and then resolve to
1299     // the texture bound to the other. The exception is the IMG multisample extension. With this
1300     // extension the texture is multisampled when rendered to and then auto-resolves it when it is
1301     // rendered from.
1302     if (desc.fSampleCnt > 1 && this->glCaps().usesMSAARenderBuffers()) {
1303         GL_CALL(GenFramebuffers(1, &idDesc->fRTFBOID));
1304         GL_CALL(GenRenderbuffers(1, &idDesc->fMSColorRenderbufferID));
1305         if (!idDesc->fRTFBOID ||
1306             !idDesc->fMSColorRenderbufferID) {
1307             goto FAILED;
1308         }
1309         if (!this->glCaps().getRenderbufferFormat(desc.fConfig, &colorRenderbufferFormat)) {
1310             return false;
1311         }
1312     } else {
1313         idDesc->fRTFBOID = idDesc->fTexFBOID;
1314     }
1315 
1316     // below here we may bind the FBO
1317     fHWBoundRenderTargetUniqueID.makeInvalid();
1318     if (idDesc->fRTFBOID != idDesc->fTexFBOID) {
1319         SkASSERT(desc.fSampleCnt > 1);
1320         GL_CALL(BindRenderbuffer(GR_GL_RENDERBUFFER, idDesc->fMSColorRenderbufferID));
1321         if (!renderbuffer_storage_msaa(*fGLContext,
1322                                        desc.fSampleCnt,
1323                                        colorRenderbufferFormat,
1324                                        desc.fWidth, desc.fHeight)) {
1325             goto FAILED;
1326         }
1327         fStats.incRenderTargetBinds();
1328         GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, idDesc->fRTFBOID));
1329         GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1330                                         GR_GL_COLOR_ATTACHMENT0,
1331                                         GR_GL_RENDERBUFFER,
1332                                         idDesc->fMSColorRenderbufferID));
1333         if (!this->glCaps().isConfigVerifiedColorAttachment(desc.fConfig)) {
1334             GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
1335             if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
1336                 goto FAILED;
1337             }
1338             fGLContext->caps()->markConfigAsValidColorAttachment(desc.fConfig);
1339         }
1340     }
1341     fStats.incRenderTargetBinds();
1342     GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, idDesc->fTexFBOID));
1343 
1344     if (this->glCaps().usesImplicitMSAAResolve() && desc.fSampleCnt > 1) {
1345         GL_CALL(FramebufferTexture2DMultisample(GR_GL_FRAMEBUFFER,
1346                                                 GR_GL_COLOR_ATTACHMENT0,
1347                                                 texInfo.fTarget,
1348                                                 texInfo.fID, 0, desc.fSampleCnt));
1349     } else {
1350         GL_CALL(FramebufferTexture2D(GR_GL_FRAMEBUFFER,
1351                                      GR_GL_COLOR_ATTACHMENT0,
1352                                      texInfo.fTarget,
1353                                      texInfo.fID, 0));
1354     }
1355     if (!this->glCaps().isConfigVerifiedColorAttachment(desc.fConfig)) {
1356         GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
1357         if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
1358             goto FAILED;
1359         }
1360         fGLContext->caps()->markConfigAsValidColorAttachment(desc.fConfig);
1361     }
1362 
1363     return true;
1364 
1365 FAILED:
1366     if (idDesc->fMSColorRenderbufferID) {
1367         GL_CALL(DeleteRenderbuffers(1, &idDesc->fMSColorRenderbufferID));
1368     }
1369     if (idDesc->fRTFBOID != idDesc->fTexFBOID) {
1370         GL_CALL(DeleteFramebuffers(1, &idDesc->fRTFBOID));
1371     }
1372     if (idDesc->fTexFBOID) {
1373         GL_CALL(DeleteFramebuffers(1, &idDesc->fTexFBOID));
1374     }
1375     return false;
1376 }
1377 
1378 // good to set a break-point here to know when createTexture fails
return_null_texture()1379 static sk_sp<GrTexture> return_null_texture() {
1380 //    SkDEBUGFAIL("null texture");
1381     return nullptr;
1382 }
1383 
1384 #if 0 && defined(SK_DEBUG)
1385 static size_t as_size_t(int x) {
1386     return x;
1387 }
1388 #endif
1389 
set_initial_texture_params(const GrGLInterface * interface,const GrGLTextureInfo & info,GrGLTexture::TexParams * initialTexParams)1390 static void set_initial_texture_params(const GrGLInterface* interface,
1391                                        const GrGLTextureInfo& info,
1392                                        GrGLTexture::TexParams* initialTexParams) {
1393     // Some drivers like to know filter/wrap before seeing glTexImage2D. Some
1394     // drivers have a bug where an FBO won't be complete if it includes a
1395     // texture that is not mipmap complete (considering the filter in use).
1396     // we only set a subset here so invalidate first
1397     initialTexParams->invalidate();
1398     initialTexParams->fMinFilter = GR_GL_NEAREST;
1399     initialTexParams->fMagFilter = GR_GL_NEAREST;
1400     initialTexParams->fWrapS = GR_GL_CLAMP_TO_EDGE;
1401     initialTexParams->fWrapT = GR_GL_CLAMP_TO_EDGE;
1402     GR_GL_CALL(interface, TexParameteri(info.fTarget,
1403                                         GR_GL_TEXTURE_MAG_FILTER,
1404                                         initialTexParams->fMagFilter));
1405     GR_GL_CALL(interface, TexParameteri(info.fTarget,
1406                                         GR_GL_TEXTURE_MIN_FILTER,
1407                                         initialTexParams->fMinFilter));
1408     GR_GL_CALL(interface, TexParameteri(info.fTarget,
1409                                         GR_GL_TEXTURE_WRAP_S,
1410                                         initialTexParams->fWrapS));
1411     GR_GL_CALL(interface, TexParameteri(info.fTarget,
1412                                         GR_GL_TEXTURE_WRAP_T,
1413                                         initialTexParams->fWrapT));
1414 }
1415 
onCreateTexture(const GrSurfaceDesc & desc,SkBudgeted budgeted,const GrMipLevel texels[],int mipLevelCount)1416 sk_sp<GrTexture> GrGLGpu::onCreateTexture(const GrSurfaceDesc& desc,
1417                                           SkBudgeted budgeted,
1418                                           const GrMipLevel texels[],
1419                                           int mipLevelCount) {
1420     // We fail if the MSAA was requested and is not available.
1421     if (GrGLCaps::kNone_MSFBOType == this->glCaps().msFBOType() && desc.fSampleCnt > 1) {
1422         //SkDebugf("MSAA RT requested but not supported on this platform.");
1423         return return_null_texture();
1424     }
1425 
1426     bool performClear = (desc.fFlags & kPerformInitialClear_GrSurfaceFlag);
1427 
1428     GrMipLevel zeroLevel;
1429     std::unique_ptr<uint8_t[]> zeros;
1430     // TODO: remove the GrPixelConfigIsSint test. This is here because we have yet to add support
1431     // for glClearBuffer* which must be used instead of glClearColor/glClear for integer FBO
1432     // attachments.
1433     if (performClear && !this->glCaps().clearTextureSupport() &&
1434         (!this->glCaps().canConfigBeFBOColorAttachment(desc.fConfig) ||
1435          GrPixelConfigIsSint(desc.fConfig))) {
1436         size_t rowSize = GrBytesPerPixel(desc.fConfig) * desc.fWidth;
1437         size_t size = rowSize * desc.fHeight;
1438         zeros.reset(new uint8_t[size]);
1439         memset(zeros.get(), 0, size);
1440         zeroLevel.fPixels = zeros.get();
1441         zeroLevel.fRowBytes = 0;
1442         texels = &zeroLevel;
1443         mipLevelCount = 1;
1444         performClear = false;
1445     }
1446 
1447     bool isRenderTarget = SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag);
1448 
1449     GrGLTexture::IDDesc idDesc;
1450     idDesc.fOwnership = GrBackendObjectOwnership::kOwned;
1451     GrMipMapsStatus mipMapsStatus;
1452     GrGLTexture::TexParams initialTexParams;
1453     if (!this->createTextureImpl(desc, &idDesc.fInfo, isRenderTarget, &initialTexParams,
1454                                  texels, mipLevelCount, &mipMapsStatus)) {
1455         return return_null_texture();
1456     }
1457 
1458     sk_sp<GrGLTexture> tex;
1459     if (isRenderTarget) {
1460         // unbind the texture from the texture unit before binding it to the frame buffer
1461         GL_CALL(BindTexture(idDesc.fInfo.fTarget, 0));
1462         GrGLRenderTarget::IDDesc rtIDDesc;
1463 
1464         if (!this->createRenderTargetObjects(desc, idDesc.fInfo, &rtIDDesc)) {
1465             GL_CALL(DeleteTextures(1, &idDesc.fInfo.fID));
1466             return return_null_texture();
1467         }
1468         tex = sk_make_sp<GrGLTextureRenderTarget>(this, budgeted, desc, idDesc, rtIDDesc,
1469                                                   mipMapsStatus);
1470         tex->baseLevelWasBoundToFBO();
1471     } else {
1472         tex = sk_make_sp<GrGLTexture>(this, budgeted, desc, idDesc, mipMapsStatus);
1473     }
1474     tex->setCachedTexParams(initialTexParams, this->getResetTimestamp());
1475 #ifdef TRACE_TEXTURE_CREATION
1476     SkDebugf("--- new texture [%d] size=(%d %d) config=%d\n",
1477              idDesc.fInfo.fID, desc.fWidth, desc.fHeight, desc.fConfig);
1478 #endif
1479     if (tex && performClear) {
1480         if (this->glCaps().clearTextureSupport()) {
1481             GrGLenum format = GrPixelConfigIsSint(tex->config()) ? GR_GL_RGBA_INTEGER : GR_GL_RGBA;
1482             static constexpr uint32_t kZero = 0;
1483             GL_CALL(ClearTexImage(tex->textureID(), 0, format, GR_GL_UNSIGNED_BYTE, &kZero));
1484         } else {
1485             SkASSERT(!GrPixelConfigIsSint(desc.fConfig));
1486             GrGLIRect viewport;
1487             this->bindSurfaceFBOForPixelOps(tex.get(), GR_GL_FRAMEBUFFER, &viewport,
1488                                             kDst_TempFBOTarget);
1489             this->disableScissor();
1490             this->disableWindowRectangles();
1491             GL_CALL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
1492             fHWWriteToColor = kYes_TriState;
1493             GL_CALL(ClearColor(0, 0, 0, 0));
1494             GL_CALL(Clear(GR_GL_COLOR_BUFFER_BIT));
1495             this->unbindTextureFBOForPixelOps(GR_GL_FRAMEBUFFER, tex.get());
1496             fHWBoundRenderTargetUniqueID.makeInvalid();
1497         }
1498     }
1499     return tex;
1500 }
1501 
1502 namespace {
1503 
1504 const GrGLuint kUnknownBitCount = GrGLStencilAttachment::kUnknownBitCount;
1505 
get_stencil_rb_sizes(const GrGLInterface * gl,GrGLStencilAttachment::Format * format)1506 void inline get_stencil_rb_sizes(const GrGLInterface* gl,
1507                                  GrGLStencilAttachment::Format* format) {
1508 
1509     // we shouldn't ever know one size and not the other
1510     SkASSERT((kUnknownBitCount == format->fStencilBits) ==
1511              (kUnknownBitCount == format->fTotalBits));
1512     if (kUnknownBitCount == format->fStencilBits) {
1513         GR_GL_GetRenderbufferParameteriv(gl, GR_GL_RENDERBUFFER,
1514                                          GR_GL_RENDERBUFFER_STENCIL_SIZE,
1515                                          (GrGLint*)&format->fStencilBits);
1516         if (format->fPacked) {
1517             GR_GL_GetRenderbufferParameteriv(gl, GR_GL_RENDERBUFFER,
1518                                              GR_GL_RENDERBUFFER_DEPTH_SIZE,
1519                                              (GrGLint*)&format->fTotalBits);
1520             format->fTotalBits += format->fStencilBits;
1521         } else {
1522             format->fTotalBits = format->fStencilBits;
1523         }
1524     }
1525 }
1526 }
1527 
getCompatibleStencilIndex(GrPixelConfig config)1528 int GrGLGpu::getCompatibleStencilIndex(GrPixelConfig config) {
1529     static const int kSize = 16;
1530     SkASSERT(this->caps()->isConfigRenderable(config, false));
1531     if (!this->glCaps().hasStencilFormatBeenDeterminedForConfig(config)) {
1532         // Default to unsupported, set this if we find a stencil format that works.
1533         int firstWorkingStencilFormatIndex = -1;
1534 
1535         // Create color texture
1536         GrGLuint colorID = 0;
1537         GL_CALL(GenTextures(1, &colorID));
1538         this->setScratchTextureUnit();
1539         GL_CALL(BindTexture(GR_GL_TEXTURE_2D, colorID));
1540         GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
1541                               GR_GL_TEXTURE_MAG_FILTER,
1542                               GR_GL_NEAREST));
1543         GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
1544                               GR_GL_TEXTURE_MIN_FILTER,
1545                               GR_GL_NEAREST));
1546         GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
1547                               GR_GL_TEXTURE_WRAP_S,
1548                               GR_GL_CLAMP_TO_EDGE));
1549         GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
1550                               GR_GL_TEXTURE_WRAP_T,
1551                               GR_GL_CLAMP_TO_EDGE));
1552 
1553         GrGLenum internalFormat;
1554         GrGLenum externalFormat;
1555         GrGLenum externalType;
1556         if (!this->glCaps().getTexImageFormats(config, config, &internalFormat, &externalFormat,
1557                                                &externalType)) {
1558             return false;
1559         }
1560         this->unbindCpuToGpuXferBuffer();
1561         CLEAR_ERROR_BEFORE_ALLOC(this->glInterface());
1562         GL_ALLOC_CALL(this->glInterface(), TexImage2D(GR_GL_TEXTURE_2D,
1563                                                       0,
1564                                                       internalFormat,
1565                                                       kSize,
1566                                                       kSize,
1567                                                       0,
1568                                                       externalFormat,
1569                                                       externalType,
1570                                                       nullptr));
1571         if (GR_GL_NO_ERROR != CHECK_ALLOC_ERROR(this->glInterface())) {
1572             GL_CALL(DeleteTextures(1, &colorID));
1573             return -1;
1574         }
1575 
1576         // unbind the texture from the texture unit before binding it to the frame buffer
1577         GL_CALL(BindTexture(GR_GL_TEXTURE_2D, 0));
1578 
1579         // Create Framebuffer
1580         GrGLuint fb = 0;
1581         GL_CALL(GenFramebuffers(1, &fb));
1582         GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, fb));
1583         fHWBoundRenderTargetUniqueID.makeInvalid();
1584         GL_CALL(FramebufferTexture2D(GR_GL_FRAMEBUFFER,
1585                                      GR_GL_COLOR_ATTACHMENT0,
1586                                      GR_GL_TEXTURE_2D,
1587                                      colorID,
1588                                      0));
1589         GrGLuint sbRBID = 0;
1590         GL_CALL(GenRenderbuffers(1, &sbRBID));
1591 
1592         // look over formats till I find a compatible one
1593         int stencilFmtCnt = this->glCaps().stencilFormats().count();
1594         if (sbRBID) {
1595             GL_CALL(BindRenderbuffer(GR_GL_RENDERBUFFER, sbRBID));
1596             for (int i = 0; i < stencilFmtCnt && sbRBID; ++i) {
1597                 const GrGLCaps::StencilFormat& sFmt = this->glCaps().stencilFormats()[i];
1598                 CLEAR_ERROR_BEFORE_ALLOC(this->glInterface());
1599                 GL_ALLOC_CALL(this->glInterface(), RenderbufferStorage(GR_GL_RENDERBUFFER,
1600                                                                        sFmt.fInternalFormat,
1601                                                                        kSize, kSize));
1602                 if (GR_GL_NO_ERROR == CHECK_ALLOC_ERROR(this->glInterface())) {
1603                     GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1604                                                     GR_GL_STENCIL_ATTACHMENT,
1605                                                     GR_GL_RENDERBUFFER, sbRBID));
1606                     if (sFmt.fPacked) {
1607                         GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1608                                                         GR_GL_DEPTH_ATTACHMENT,
1609                                                         GR_GL_RENDERBUFFER, sbRBID));
1610                     } else {
1611                         GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1612                                                         GR_GL_DEPTH_ATTACHMENT,
1613                                                         GR_GL_RENDERBUFFER, 0));
1614                     }
1615                     GrGLenum status;
1616                     GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
1617                     if (status == GR_GL_FRAMEBUFFER_COMPLETE) {
1618                         firstWorkingStencilFormatIndex = i;
1619                         break;
1620                     }
1621                     GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1622                                                     GR_GL_STENCIL_ATTACHMENT,
1623                                                     GR_GL_RENDERBUFFER, 0));
1624                     if (sFmt.fPacked) {
1625                         GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1626                                                         GR_GL_DEPTH_ATTACHMENT,
1627                                                         GR_GL_RENDERBUFFER, 0));
1628                     }
1629                 }
1630             }
1631             GL_CALL(DeleteRenderbuffers(1, &sbRBID));
1632         }
1633         GL_CALL(DeleteTextures(1, &colorID));
1634         GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, 0));
1635         GL_CALL(DeleteFramebuffers(1, &fb));
1636         fGLContext->caps()->setStencilFormatIndexForConfig(config, firstWorkingStencilFormatIndex);
1637     }
1638     return this->glCaps().getStencilFormatIndexForConfig(config);
1639 }
1640 
createTextureImpl(const GrSurfaceDesc & desc,GrGLTextureInfo * info,bool renderTarget,GrGLTexture::TexParams * initialTexParams,const GrMipLevel texels[],int mipLevelCount,GrMipMapsStatus * mipMapsStatus)1641 bool GrGLGpu::createTextureImpl(const GrSurfaceDesc& desc, GrGLTextureInfo* info,
1642                                 bool renderTarget, GrGLTexture::TexParams* initialTexParams,
1643                                 const GrMipLevel texels[], int mipLevelCount,
1644                                 GrMipMapsStatus* mipMapsStatus) {
1645     info->fID = 0;
1646     info->fTarget = GR_GL_TEXTURE_2D;
1647     GL_CALL(GenTextures(1, &(info->fID)));
1648 
1649     if (!info->fID) {
1650         return false;
1651     }
1652 
1653     this->setScratchTextureUnit();
1654     GL_CALL(BindTexture(info->fTarget, info->fID));
1655 
1656     if (renderTarget && this->glCaps().textureUsageSupport()) {
1657         // provides a hint about how this texture will be used
1658         GL_CALL(TexParameteri(info->fTarget,
1659                               GR_GL_TEXTURE_USAGE,
1660                               GR_GL_FRAMEBUFFER_ATTACHMENT));
1661     }
1662 
1663     if (info) {
1664         set_initial_texture_params(this->glInterface(), *info, initialTexParams);
1665     }
1666     if (!this->uploadTexData(desc.fConfig, desc.fWidth, desc.fHeight, desc.fOrigin, info->fTarget,
1667                              kNewTexture_UploadType, 0, 0, desc.fWidth, desc.fHeight, desc.fConfig,
1668                              texels, mipLevelCount, mipMapsStatus)) {
1669         GL_CALL(DeleteTextures(1, &(info->fID)));
1670         return false;
1671     }
1672     info->fFormat = this->glCaps().configSizedInternalFormat(desc.fConfig);
1673     return true;
1674 }
1675 
createStencilAttachmentForRenderTarget(const GrRenderTarget * rt,int width,int height)1676 GrStencilAttachment* GrGLGpu::createStencilAttachmentForRenderTarget(const GrRenderTarget* rt,
1677                                                                      int width, int height) {
1678     SkASSERT(width >= rt->width());
1679     SkASSERT(height >= rt->height());
1680 
1681     int samples = rt->numStencilSamples();
1682     GrGLStencilAttachment::IDDesc sbDesc;
1683 
1684     int sIdx = this->getCompatibleStencilIndex(rt->config());
1685     if (sIdx < 0) {
1686         return nullptr;
1687     }
1688 
1689     if (!sbDesc.fRenderbufferID) {
1690         GL_CALL(GenRenderbuffers(1, &sbDesc.fRenderbufferID));
1691     }
1692     if (!sbDesc.fRenderbufferID) {
1693         return nullptr;
1694     }
1695     GL_CALL(BindRenderbuffer(GR_GL_RENDERBUFFER, sbDesc.fRenderbufferID));
1696     const GrGLCaps::StencilFormat& sFmt = this->glCaps().stencilFormats()[sIdx];
1697     CLEAR_ERROR_BEFORE_ALLOC(this->glInterface());
1698     // we do this "if" so that we don't call the multisample
1699     // version on a GL that doesn't have an MSAA extension.
1700     if (samples > 1) {
1701         SkAssertResult(renderbuffer_storage_msaa(*fGLContext,
1702                                                  samples,
1703                                                  sFmt.fInternalFormat,
1704                                                  width, height));
1705     } else {
1706         GL_ALLOC_CALL(this->glInterface(), RenderbufferStorage(GR_GL_RENDERBUFFER,
1707                                                                sFmt.fInternalFormat,
1708                                                                width, height));
1709         SkASSERT(GR_GL_NO_ERROR == CHECK_ALLOC_ERROR(this->glInterface()));
1710     }
1711     fStats.incStencilAttachmentCreates();
1712     // After sized formats we attempt an unsized format and take
1713     // whatever sizes GL gives us. In that case we query for the size.
1714     GrGLStencilAttachment::Format format = sFmt;
1715     get_stencil_rb_sizes(this->glInterface(), &format);
1716     GrGLStencilAttachment* stencil = new GrGLStencilAttachment(this,
1717                                                                sbDesc,
1718                                                                width,
1719                                                                height,
1720                                                                samples,
1721                                                                format);
1722     return stencil;
1723 }
1724 
1725 ////////////////////////////////////////////////////////////////////////////////
1726 
1727 // GL_STREAM_DRAW triggers an optimization in Chromium's GPU process where a client's vertex buffer
1728 // objects are implemented as client-side-arrays on tile-deferred architectures.
1729 #define DYNAMIC_USAGE_PARAM GR_GL_STREAM_DRAW
1730 
onCreateBuffer(size_t size,GrBufferType intendedType,GrAccessPattern accessPattern,const void * data)1731 GrBuffer* GrGLGpu::onCreateBuffer(size_t size, GrBufferType intendedType,
1732                                   GrAccessPattern accessPattern, const void* data) {
1733     return GrGLBuffer::Create(this, size, intendedType, accessPattern, data);
1734 }
1735 
flushScissor(const GrScissorState & scissorState,const GrGLIRect & rtViewport,GrSurfaceOrigin rtOrigin)1736 void GrGLGpu::flushScissor(const GrScissorState& scissorState,
1737                            const GrGLIRect& rtViewport,
1738                            GrSurfaceOrigin rtOrigin) {
1739     if (scissorState.enabled()) {
1740         GrGLIRect scissor;
1741         scissor.setRelativeTo(rtViewport, scissorState.rect(), rtOrigin);
1742         // if the scissor fully contains the viewport then we fall through and
1743         // disable the scissor test.
1744         if (!scissor.contains(rtViewport)) {
1745             if (fHWScissorSettings.fRect != scissor) {
1746                 scissor.pushToGLScissor(this->glInterface());
1747                 fHWScissorSettings.fRect = scissor;
1748             }
1749             if (kYes_TriState != fHWScissorSettings.fEnabled) {
1750                 GL_CALL(Enable(GR_GL_SCISSOR_TEST));
1751                 fHWScissorSettings.fEnabled = kYes_TriState;
1752             }
1753             return;
1754         }
1755     }
1756 
1757     // See fall through note above
1758     this->disableScissor();
1759 }
1760 
flushWindowRectangles(const GrWindowRectsState & windowState,const GrGLRenderTarget * rt,GrSurfaceOrigin origin)1761 void GrGLGpu::flushWindowRectangles(const GrWindowRectsState& windowState,
1762                                     const GrGLRenderTarget* rt, GrSurfaceOrigin origin) {
1763 #ifndef USE_NSIGHT
1764     typedef GrWindowRectsState::Mode Mode;
1765     SkASSERT(!windowState.enabled() || rt->renderFBOID()); // Window rects can't be used on-screen.
1766     SkASSERT(windowState.numWindows() <= this->caps()->maxWindowRectangles());
1767 
1768     if (!this->caps()->maxWindowRectangles() ||
1769         fHWWindowRectsState.knownEqualTo(origin, rt->getViewport(), windowState)) {
1770         return;
1771     }
1772 
1773     // This is purely a workaround for a spurious warning generated by gcc. Otherwise the above
1774     // assert would be sufficient. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=5912
1775     int numWindows = SkTMin(windowState.numWindows(), int(GrWindowRectangles::kMaxWindows));
1776     SkASSERT(windowState.numWindows() == numWindows);
1777 
1778     GrGLIRect glwindows[GrWindowRectangles::kMaxWindows];
1779     const SkIRect* skwindows = windowState.windows().data();
1780     for (int i = 0; i < numWindows; ++i) {
1781         glwindows[i].setRelativeTo(rt->getViewport(), skwindows[i], origin);
1782     }
1783 
1784     GrGLenum glmode = (Mode::kExclusive == windowState.mode()) ? GR_GL_EXCLUSIVE : GR_GL_INCLUSIVE;
1785     GL_CALL(WindowRectangles(glmode, numWindows, glwindows->asInts()));
1786 
1787     fHWWindowRectsState.set(origin, rt->getViewport(), windowState);
1788 #endif
1789 }
1790 
disableWindowRectangles()1791 void GrGLGpu::disableWindowRectangles() {
1792 #ifndef USE_NSIGHT
1793     if (!this->caps()->maxWindowRectangles() || fHWWindowRectsState.knownDisabled()) {
1794         return;
1795     }
1796     GL_CALL(WindowRectangles(GR_GL_EXCLUSIVE, 0, nullptr));
1797     fHWWindowRectsState.setDisabled();
1798 #endif
1799 }
1800 
flushMinSampleShading(float minSampleShading)1801 void GrGLGpu::flushMinSampleShading(float minSampleShading) {
1802     if (fHWMinSampleShading != minSampleShading) {
1803         if (minSampleShading > 0.0) {
1804             GL_CALL(Enable(GR_GL_SAMPLE_SHADING));
1805             GL_CALL(MinSampleShading(minSampleShading));
1806         }
1807         else {
1808             GL_CALL(Disable(GR_GL_SAMPLE_SHADING));
1809         }
1810         fHWMinSampleShading = minSampleShading;
1811     }
1812 }
1813 
flushGLState(const GrPipeline & pipeline,const GrPrimitiveProcessor & primProc,bool willDrawPoints)1814 bool GrGLGpu::flushGLState(const GrPipeline& pipeline, const GrPrimitiveProcessor& primProc,
1815                            bool willDrawPoints) {
1816     sk_sp<GrGLProgram> program(fProgramCache->refProgram(this, pipeline, primProc, willDrawPoints));
1817     if (!program) {
1818         GrCapsDebugf(this->caps(), "Failed to create program!\n");
1819         return false;
1820     }
1821 
1822     program->generateMipmaps(primProc, pipeline);
1823 
1824     GrXferProcessor::BlendInfo blendInfo;
1825     pipeline.getXferProcessor().getBlendInfo(&blendInfo);
1826 
1827     this->flushColorWrite(blendInfo.fWriteColor);
1828     this->flushMinSampleShading(primProc.getSampleShading());
1829 
1830     GrGLuint programID = program->programID();
1831     if (fHWProgramID != programID) {
1832         GL_CALL(UseProgram(programID));
1833         fHWProgramID = programID;
1834     }
1835 
1836     if (blendInfo.fWriteColor) {
1837         // Swizzle the blend to match what the shader will output.
1838         const GrSwizzle& swizzle = this->caps()->shaderCaps()->configOutputSwizzle(
1839             pipeline.proxy()->config());
1840         this->flushBlend(blendInfo, swizzle);
1841     }
1842 
1843     program->setData(primProc, pipeline);
1844 
1845     GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(pipeline.renderTarget());
1846     GrStencilSettings stencil;
1847     if (pipeline.isStencilEnabled()) {
1848         // TODO: attach stencil and create settings during render target flush.
1849         SkASSERT(glRT->renderTargetPriv().getStencilAttachment());
1850         stencil.reset(*pipeline.getUserStencil(), pipeline.hasStencilClip(),
1851                       glRT->renderTargetPriv().numStencilBits());
1852     }
1853     this->flushStencil(stencil);
1854     this->flushScissor(pipeline.getScissorState(), glRT->getViewport(), pipeline.proxy()->origin());
1855     this->flushWindowRectangles(pipeline.getWindowRectsState(), glRT, pipeline.proxy()->origin());
1856     this->flushHWAAState(glRT, pipeline.isHWAntialiasState(), !stencil.isDisabled());
1857 
1858     // This must come after textures are flushed because a texture may need
1859     // to be msaa-resolved (which will modify bound FBO state).
1860     this->flushRenderTarget(glRT, nullptr, pipeline.getDisableOutputConversionToSRGB());
1861 
1862     return true;
1863 }
1864 
setupGeometry(const GrPrimitiveProcessor & primProc,const GrBuffer * indexBuffer,const GrBuffer * vertexBuffer,int baseVertex,const GrBuffer * instanceBuffer,int baseInstance)1865 void GrGLGpu::setupGeometry(const GrPrimitiveProcessor& primProc,
1866                             const GrBuffer* indexBuffer,
1867                             const GrBuffer* vertexBuffer,
1868                             int baseVertex,
1869                             const GrBuffer* instanceBuffer,
1870                             int baseInstance) {
1871     using EnablePrimitiveRestart = GrGLAttribArrayState::EnablePrimitiveRestart;
1872 
1873     GrGLAttribArrayState* attribState;
1874     if (indexBuffer) {
1875         SkASSERT(indexBuffer && !indexBuffer->isMapped());
1876         attribState = fHWVertexArrayState.bindInternalVertexArray(this, indexBuffer);
1877     } else {
1878         attribState = fHWVertexArrayState.bindInternalVertexArray(this);
1879     }
1880 
1881     struct {
1882         const GrBuffer*   fBuffer;
1883         int               fStride;
1884         size_t            fBufferOffset;
1885     } bindings[2];
1886 
1887     if (int vertexStride = primProc.getVertexStride()) {
1888         SkASSERT(vertexBuffer && !vertexBuffer->isMapped());
1889         bindings[0].fBuffer = vertexBuffer;
1890         bindings[0].fStride = vertexStride;
1891         bindings[0].fBufferOffset = vertexBuffer->baseOffset() + baseVertex * vertexStride;
1892     }
1893     if (int instanceStride = primProc.getInstanceStride()) {
1894         SkASSERT(instanceBuffer && !instanceBuffer->isMapped());
1895         bindings[1].fBuffer = instanceBuffer;
1896         bindings[1].fStride = instanceStride;
1897         bindings[1].fBufferOffset = instanceBuffer->baseOffset() + baseInstance * instanceStride;
1898     }
1899 
1900     int numAttribs = primProc.numAttribs();
1901     auto enableRestart = EnablePrimitiveRestart(primProc.willUsePrimitiveRestart() && indexBuffer);
1902     attribState->enableVertexArrays(this, numAttribs, enableRestart);
1903 
1904     for (int i = 0; i < numAttribs; ++i) {
1905         using InputRate = GrPrimitiveProcessor::Attribute::InputRate;
1906         const GrGeometryProcessor::Attribute& attrib = primProc.getAttrib(i);
1907         const int divisor = InputRate::kPerInstance == attrib.fInputRate ? 1 : 0;
1908         const auto& binding = bindings[divisor];
1909         attribState->set(this, i, binding.fBuffer, attrib.fType, binding.fStride,
1910                          binding.fBufferOffset + attrib.fOffsetInRecord, divisor);
1911     }
1912 }
1913 
bindBuffer(GrBufferType type,const GrBuffer * buffer)1914 GrGLenum GrGLGpu::bindBuffer(GrBufferType type, const GrBuffer* buffer) {
1915     this->handleDirtyContext();
1916 
1917     // Index buffer state is tied to the vertex array.
1918     if (kIndex_GrBufferType == type) {
1919         this->bindVertexArray(0);
1920     }
1921 
1922     SkASSERT(type >= 0 && type <= kLast_GrBufferType);
1923     auto& bufferState = fHWBufferState[type];
1924 
1925     if (buffer->uniqueID() != bufferState.fBoundBufferUniqueID) {
1926         if (buffer->isCPUBacked()) {
1927             if (!bufferState.fBufferZeroKnownBound) {
1928                 GL_CALL(BindBuffer(bufferState.fGLTarget, 0));
1929             }
1930         } else {
1931             const GrGLBuffer* glBuffer = static_cast<const GrGLBuffer*>(buffer);
1932             GL_CALL(BindBuffer(bufferState.fGLTarget, glBuffer->bufferID()));
1933         }
1934         bufferState.fBufferZeroKnownBound = buffer->isCPUBacked();
1935         bufferState.fBoundBufferUniqueID = buffer->uniqueID();
1936     }
1937 
1938     return bufferState.fGLTarget;
1939 }
1940 
notifyBufferReleased(const GrGLBuffer * buffer)1941 void GrGLGpu::notifyBufferReleased(const GrGLBuffer* buffer) {
1942     if (buffer->hasAttachedToTexture()) {
1943         // Detach this buffer from any textures to ensure the underlying memory is freed.
1944         GrGpuResource::UniqueID uniqueID = buffer->uniqueID();
1945         for (int i = fHWMaxUsedBufferTextureUnit; i >= 0; --i) {
1946             auto& buffTex = fHWBufferTextures[i];
1947             if (uniqueID != buffTex.fAttachedBufferUniqueID) {
1948                 continue;
1949             }
1950             if (i == fHWMaxUsedBufferTextureUnit) {
1951                 --fHWMaxUsedBufferTextureUnit;
1952             }
1953 
1954             this->setTextureUnit(i);
1955             if (!buffTex.fKnownBound) {
1956                 SkASSERT(buffTex.fTextureID);
1957                 GL_CALL(BindTexture(GR_GL_TEXTURE_BUFFER, buffTex.fTextureID));
1958                 buffTex.fKnownBound = true;
1959             }
1960             GL_CALL(TexBuffer(GR_GL_TEXTURE_BUFFER,
1961                               this->glCaps().configSizedInternalFormat(buffTex.fTexelConfig), 0));
1962         }
1963     }
1964 }
1965 
disableScissor()1966 void GrGLGpu::disableScissor() {
1967     if (kNo_TriState != fHWScissorSettings.fEnabled) {
1968         GL_CALL(Disable(GR_GL_SCISSOR_TEST));
1969         fHWScissorSettings.fEnabled = kNo_TriState;
1970         return;
1971     }
1972 }
1973 
clear(const GrFixedClip & clip,GrColor color,GrRenderTarget * target,GrSurfaceOrigin origin)1974 void GrGLGpu::clear(const GrFixedClip& clip, GrColor color,
1975                     GrRenderTarget* target, GrSurfaceOrigin origin) {
1976     // parent class should never let us get here with no RT
1977     SkASSERT(target);
1978 
1979     this->handleDirtyContext();
1980 
1981     GrGLfloat r, g, b, a;
1982     static const GrGLfloat scale255 = 1.f / 255.f;
1983     a = GrColorUnpackA(color) * scale255;
1984     GrGLfloat scaleRGB = scale255;
1985     r = GrColorUnpackR(color) * scaleRGB;
1986     g = GrColorUnpackG(color) * scaleRGB;
1987     b = GrColorUnpackB(color) * scaleRGB;
1988 
1989     if (this->glCaps().useDrawToClearColor()) {
1990         this->clearColorAsDraw(clip, r, g, b, a, target, origin);
1991         return;
1992     }
1993 
1994     GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(target);
1995 
1996     this->flushRenderTarget(glRT, clip.scissorEnabled() ? &clip.scissorRect() : nullptr);
1997     this->flushScissor(clip.scissorState(), glRT->getViewport(), origin);
1998     this->flushWindowRectangles(clip.windowRectsState(), glRT, origin);
1999 
2000     GL_CALL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
2001     fHWWriteToColor = kYes_TriState;
2002 
2003     if (this->glCaps().clearToBoundaryValuesIsBroken() &&
2004         (1 == r || 0 == r) && (1 == g || 0 == g) && (1 == b || 0 == b) && (1 == a || 0 == a)) {
2005         static const GrGLfloat safeAlpha1 = nextafter(1.f, 2.f);
2006         static const GrGLfloat safeAlpha0 = nextafter(0.f, -1.f);
2007         a = (1 == a) ? safeAlpha1 : safeAlpha0;
2008     }
2009     GL_CALL(ClearColor(r, g, b, a));
2010     GL_CALL(Clear(GR_GL_COLOR_BUFFER_BIT));
2011 }
2012 
clearStencil(GrRenderTarget * target,int clearValue)2013 void GrGLGpu::clearStencil(GrRenderTarget* target, int clearValue) {
2014     if (!target) {
2015         return;
2016     }
2017 
2018     GrStencilAttachment* sb = target->renderTargetPriv().getStencilAttachment();
2019     // this should only be called internally when we know we have a
2020     // stencil buffer.
2021     SkASSERT(sb);
2022 
2023     GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(target);
2024     this->flushRenderTarget(glRT, &SkIRect::EmptyIRect());
2025 
2026     this->disableScissor();
2027     this->disableWindowRectangles();
2028 
2029     GL_CALL(StencilMask(0xffffffff));
2030     GL_CALL(ClearStencil(clearValue));
2031     GL_CALL(Clear(GR_GL_STENCIL_BUFFER_BIT));
2032     fHWStencilSettings.invalidate();
2033     if (!clearValue) {
2034         sb->cleared();
2035     }
2036 }
2037 
clearStencilClip(const GrFixedClip & clip,bool insideStencilMask,GrRenderTarget * target,GrSurfaceOrigin origin)2038 void GrGLGpu::clearStencilClip(const GrFixedClip& clip,
2039                                bool insideStencilMask,
2040                                GrRenderTarget* target, GrSurfaceOrigin origin) {
2041     SkASSERT(target);
2042     this->handleDirtyContext();
2043 
2044     if (this->glCaps().useDrawToClearStencilClip()) {
2045         this->clearStencilClipAsDraw(clip, insideStencilMask, target, origin);
2046         return;
2047     }
2048 
2049     GrStencilAttachment* sb = target->renderTargetPriv().getStencilAttachment();
2050     // this should only be called internally when we know we have a
2051     // stencil buffer.
2052     SkASSERT(sb);
2053     GrGLint stencilBitCount =  sb->bits();
2054 #if 0
2055     SkASSERT(stencilBitCount > 0);
2056     GrGLint clipStencilMask  = (1 << (stencilBitCount - 1));
2057 #else
2058     // we could just clear the clip bit but when we go through
2059     // ANGLE a partial stencil mask will cause clears to be
2060     // turned into draws. Our contract on GrOpList says that
2061     // changing the clip between stencil passes may or may not
2062     // zero the client's clip bits. So we just clear the whole thing.
2063     static const GrGLint clipStencilMask  = ~0;
2064 #endif
2065     GrGLint value;
2066     if (insideStencilMask) {
2067         value = (1 << (stencilBitCount - 1));
2068     } else {
2069         value = 0;
2070     }
2071     GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(target);
2072     this->flushRenderTarget(glRT, &SkIRect::EmptyIRect());
2073 
2074     this->flushScissor(clip.scissorState(), glRT->getViewport(), origin);
2075     this->flushWindowRectangles(clip.windowRectsState(), glRT, origin);
2076 
2077     GL_CALL(StencilMask((uint32_t) clipStencilMask));
2078     GL_CALL(ClearStencil(value));
2079     GL_CALL(Clear(GR_GL_STENCIL_BUFFER_BIT));
2080     fHWStencilSettings.invalidate();
2081 }
2082 
read_pixels_pays_for_y_flip(GrSurfaceOrigin origin,const GrGLCaps & caps,int width,int height,GrPixelConfig config,size_t rowBytes)2083 static bool read_pixels_pays_for_y_flip(GrSurfaceOrigin origin, const GrGLCaps& caps,
2084                                         int width, int height,  GrPixelConfig config,
2085                                         size_t rowBytes) {
2086     // If the surface is already TopLeft, we don't need to flip.
2087     if (kTopLeft_GrSurfaceOrigin == origin) {
2088         return false;
2089     }
2090 
2091     // If the read is really small or smaller than the min texture size, don't force a draw.
2092     static const int kMinSize = 32;
2093     if (width < kMinSize || height < kMinSize) {
2094         return false;
2095     }
2096 
2097     // if GL can do the flip then we'll never pay for it.
2098     if (caps.packFlipYSupport()) {
2099         return false;
2100     }
2101 
2102     // If we have to do memcpy to handle non-trim rowBytes then we
2103     // get the flip for free. Otherwise it costs.
2104     // Note that we're assuming that 0 rowBytes has already been handled and that the width has been
2105     // clipped.
2106     return caps.packRowLengthSupport() || GrBytesPerPixel(config) * width == rowBytes;
2107 }
2108 
readPixelsSupported(GrRenderTarget * target,GrPixelConfig readConfig)2109 bool GrGLGpu::readPixelsSupported(GrRenderTarget* target, GrPixelConfig readConfig) {
2110 #ifdef SK_BUILD_FOR_MAC
2111     // Chromium may ask us to read back from locked IOSurfaces. Calling the command buffer's
2112     // glGetIntegerv() with GL_IMPLEMENTATION_COLOR_READ_FORMAT/_TYPE causes the command buffer
2113     // to make a call to check the framebuffer status which can hang the driver. So in Mac Chromium
2114     // we always use a temporary surface to test for read pixels support.
2115     // https://www.crbug.com/662802
2116     if (this->glContext().driver() == kChromium_GrGLDriver) {
2117         return this->readPixelsSupported(target->config(), readConfig);
2118     }
2119 #endif
2120     auto bindRenderTarget = [this, target]() -> bool {
2121         this->flushRenderTarget(static_cast<GrGLRenderTarget*>(target), &SkIRect::EmptyIRect());
2122         return true;
2123     };
2124     auto unbindRenderTarget = []{};
2125     auto getIntegerv = [this](GrGLenum query, GrGLint* value) {
2126         GR_GL_GetIntegerv(this->glInterface(), query, value);
2127     };
2128     GrPixelConfig rtConfig = target->config();
2129     return this->glCaps().readPixelsSupported(rtConfig, readConfig, getIntegerv, bindRenderTarget,
2130                                               unbindRenderTarget);
2131 }
2132 
readPixelsSupported(GrPixelConfig rtConfig,GrPixelConfig readConfig)2133 bool GrGLGpu::readPixelsSupported(GrPixelConfig rtConfig, GrPixelConfig readConfig) {
2134     sk_sp<GrTexture> temp;
2135     auto bindRenderTarget = [this, rtConfig, &temp]() -> bool {
2136         GrSurfaceDesc desc;
2137         desc.fConfig = rtConfig;
2138         desc.fWidth = desc.fHeight = 16;
2139         if (this->glCaps().isConfigRenderable(rtConfig, false)) {
2140             desc.fFlags = kRenderTarget_GrSurfaceFlag;
2141             desc.fOrigin = kBottomLeft_GrSurfaceOrigin;
2142             temp = this->createTexture(desc, SkBudgeted::kNo);
2143             if (!temp) {
2144                 return false;
2145             }
2146             GrGLRenderTarget* glrt = static_cast<GrGLRenderTarget*>(temp->asRenderTarget());
2147             this->flushRenderTarget(glrt, &SkIRect::EmptyIRect());
2148             return true;
2149         } else if (this->glCaps().canConfigBeFBOColorAttachment(rtConfig)) {
2150             desc.fOrigin = kTopLeft_GrSurfaceOrigin;
2151             temp = this->createTexture(desc, SkBudgeted::kNo);
2152             if (!temp) {
2153                 return false;
2154             }
2155             GrGLIRect vp;
2156             this->bindSurfaceFBOForPixelOps(temp.get(), GR_GL_FRAMEBUFFER, &vp, kDst_TempFBOTarget);
2157             fHWBoundRenderTargetUniqueID.makeInvalid();
2158             return true;
2159         }
2160         return false;
2161     };
2162     auto unbindRenderTarget = [this, &temp]() {
2163         this->unbindTextureFBOForPixelOps(GR_GL_FRAMEBUFFER, temp.get());
2164     };
2165     auto getIntegerv = [this](GrGLenum query, GrGLint* value) {
2166         GR_GL_GetIntegerv(this->glInterface(), query, value);
2167     };
2168     return this->glCaps().readPixelsSupported(rtConfig, readConfig, getIntegerv, bindRenderTarget,
2169                                               unbindRenderTarget);
2170 }
2171 
readPixelsSupported(GrSurface * surfaceForConfig,GrPixelConfig readConfig)2172 bool GrGLGpu::readPixelsSupported(GrSurface* surfaceForConfig, GrPixelConfig readConfig) {
2173     if (GrRenderTarget* rt = surfaceForConfig->asRenderTarget()) {
2174         return this->readPixelsSupported(rt, readConfig);
2175     } else {
2176         GrPixelConfig config = surfaceForConfig->config();
2177         return this->readPixelsSupported(config, readConfig);
2178     }
2179 }
2180 
requires_srgb_conversion(GrPixelConfig a,GrPixelConfig b)2181 static bool requires_srgb_conversion(GrPixelConfig a, GrPixelConfig b) {
2182     if (GrPixelConfigIsSRGB(a)) {
2183         return !GrPixelConfigIsSRGB(b) && !GrPixelConfigIsAlphaOnly(b);
2184     } else if (GrPixelConfigIsSRGB(b)) {
2185         return !GrPixelConfigIsSRGB(a) && !GrPixelConfigIsAlphaOnly(a);
2186     }
2187     return false;
2188 }
2189 
onGetReadPixelsInfo(GrSurface * srcSurface,GrSurfaceOrigin srcOrigin,int width,int height,size_t rowBytes,GrPixelConfig readConfig,DrawPreference * drawPreference,ReadPixelTempDrawInfo * tempDrawInfo)2190 bool GrGLGpu::onGetReadPixelsInfo(GrSurface* srcSurface, GrSurfaceOrigin srcOrigin,
2191                                   int width, int height, size_t rowBytes,
2192                                   GrPixelConfig readConfig, DrawPreference* drawPreference,
2193                                   ReadPixelTempDrawInfo* tempDrawInfo) {
2194     GrPixelConfig srcConfig = srcSurface->config();
2195 
2196     // These settings we will always want if a temp draw is performed.
2197     tempDrawInfo->fTempSurfaceDesc.fFlags = kRenderTarget_GrSurfaceFlag;
2198     tempDrawInfo->fTempSurfaceDesc.fWidth = width;
2199     tempDrawInfo->fTempSurfaceDesc.fHeight = height;
2200     tempDrawInfo->fTempSurfaceDesc.fSampleCnt = 1;
2201     tempDrawInfo->fTempSurfaceDesc.fOrigin = kTopLeft_GrSurfaceOrigin; // no CPU y-flip for TL.
2202     tempDrawInfo->fTempSurfaceFit = this->glCaps().partialFBOReadIsSlow() ? SkBackingFit::kExact
2203                                                                           : SkBackingFit::kApprox;
2204     // For now assume no swizzling, we may change that below.
2205     tempDrawInfo->fSwizzle = GrSwizzle::RGBA();
2206 
2207     // Depends on why we need/want a temp draw. Start off assuming no change, the surface we read
2208     // from will be srcConfig and we will read readConfig pixels from it.
2209     // Note that if we require a draw and return a non-renderable format for the temp surface the
2210     // base class will fail for us.
2211     tempDrawInfo->fTempSurfaceDesc.fConfig = srcConfig;
2212     tempDrawInfo->fReadConfig = readConfig;
2213 
2214     if (requires_srgb_conversion(srcConfig, readConfig)) {
2215         if (!this->readPixelsSupported(readConfig, readConfig)) {
2216             return false;
2217         }
2218         // Draw to do srgb to linear conversion or vice versa.
2219         ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
2220         tempDrawInfo->fTempSurfaceDesc.fConfig = readConfig;
2221         tempDrawInfo->fReadConfig = readConfig;
2222         return true;
2223     }
2224 
2225     if (this->glCaps().rgba8888PixelsOpsAreSlow() && kRGBA_8888_GrPixelConfig == readConfig &&
2226         this->readPixelsSupported(kBGRA_8888_GrPixelConfig, kBGRA_8888_GrPixelConfig)) {
2227         tempDrawInfo->fTempSurfaceDesc.fConfig = kBGRA_8888_GrPixelConfig;
2228         tempDrawInfo->fSwizzle = GrSwizzle::BGRA();
2229         tempDrawInfo->fReadConfig = kBGRA_8888_GrPixelConfig;
2230         ElevateDrawPreference(drawPreference, kGpuPrefersDraw_DrawPreference);
2231     } else if (this->glCaps().rgbaToBgraReadbackConversionsAreSlow() &&
2232                GrBytesPerPixel(readConfig) == 4 &&
2233                GrPixelConfigSwapRAndB(readConfig) == srcConfig &&
2234                this->readPixelsSupported(srcSurface, srcConfig)) {
2235         // Mesa 3D takes a slow path on when reading back BGRA from an RGBA surface and vice-versa.
2236         // Better to do a draw with a R/B swap and then read as the original config.
2237         tempDrawInfo->fTempSurfaceDesc.fConfig = srcConfig;
2238         tempDrawInfo->fSwizzle = GrSwizzle::BGRA();
2239         tempDrawInfo->fReadConfig = srcConfig;
2240         ElevateDrawPreference(drawPreference, kGpuPrefersDraw_DrawPreference);
2241     } else if (!this->readPixelsSupported(srcSurface, readConfig)) {
2242         if (readConfig == kBGRA_8888_GrPixelConfig &&
2243             this->glCaps().canConfigBeFBOColorAttachment(kRGBA_8888_GrPixelConfig) &&
2244             this->readPixelsSupported(kRGBA_8888_GrPixelConfig, kRGBA_8888_GrPixelConfig)) {
2245             // We're trying to read BGRA but it's not supported. If RGBA is renderable and
2246             // we can read it back, then do a swizzling draw to a RGBA and read it back (which
2247             // will effectively be BGRA).
2248             tempDrawInfo->fTempSurfaceDesc.fConfig = kRGBA_8888_GrPixelConfig;
2249             tempDrawInfo->fSwizzle = GrSwizzle::BGRA();
2250             tempDrawInfo->fReadConfig = kRGBA_8888_GrPixelConfig;
2251             ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
2252         } else if (readConfig == kSBGRA_8888_GrPixelConfig &&
2253             this->glCaps().canConfigBeFBOColorAttachment(kSRGBA_8888_GrPixelConfig) &&
2254             this->readPixelsSupported(kSRGBA_8888_GrPixelConfig, kSRGBA_8888_GrPixelConfig)) {
2255             // We're trying to read sBGRA but it's not supported. If sRGBA is renderable and
2256             // we can read it back, then do a swizzling draw to a sRGBA and read it back (which
2257             // will effectively be sBGRA).
2258             tempDrawInfo->fTempSurfaceDesc.fConfig = kSRGBA_8888_GrPixelConfig;
2259             tempDrawInfo->fSwizzle = GrSwizzle::BGRA();
2260             tempDrawInfo->fReadConfig = kSRGBA_8888_GrPixelConfig;
2261             ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
2262         } else if (readConfig == kAlpha_8_GrPixelConfig) {
2263             // onReadPixels implements a fallback for cases where we are want to read kAlpha_8,
2264             // it's unsupported, but 32bit RGBA reads are supported.
2265             // Don't attempt to do any srgb conversions since we only care about alpha.
2266             GrPixelConfig cpuTempConfig = kRGBA_8888_GrPixelConfig;
2267             if (GrPixelConfigIsSRGB(srcSurface->config())) {
2268                 cpuTempConfig = kSRGBA_8888_GrPixelConfig;
2269             }
2270             if (!this->readPixelsSupported(srcSurface, cpuTempConfig)) {
2271                 // If we can't read RGBA from the src try to draw to a kRGBA_8888 (or kSRGBA_8888)
2272                 // first and then onReadPixels will read that to a 32bit temporary buffer.
2273                 if (this->glCaps().canConfigBeFBOColorAttachment(cpuTempConfig)) {
2274                     ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
2275                     tempDrawInfo->fTempSurfaceDesc.fConfig = cpuTempConfig;
2276                     tempDrawInfo->fReadConfig = kAlpha_8_GrPixelConfig;
2277                 } else {
2278                     return false;
2279                 }
2280             } else {
2281                 SkASSERT(tempDrawInfo->fTempSurfaceDesc.fConfig == srcConfig);
2282                 SkASSERT(tempDrawInfo->fReadConfig == kAlpha_8_GrPixelConfig);
2283             }
2284         } else if (readConfig == kRGBA_half_GrPixelConfig &&
2285                    this->readPixelsSupported(srcSurface, kRGBA_float_GrPixelConfig)) {
2286             // If reading in half float format is not supported, then read in float format.
2287             return true;
2288         } else if (this->glCaps().canConfigBeFBOColorAttachment(readConfig) &&
2289                    this->readPixelsSupported(readConfig, readConfig)) {
2290             // Do a draw to convert from the src config to the read config.
2291             ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
2292             tempDrawInfo->fTempSurfaceDesc.fConfig = readConfig;
2293             tempDrawInfo->fReadConfig = readConfig;
2294         } else {
2295             return false;
2296         }
2297     }
2298 
2299     if ((srcSurface->asRenderTarget() || this->glCaps().canConfigBeFBOColorAttachment(srcConfig)) &&
2300         read_pixels_pays_for_y_flip(srcOrigin, this->glCaps(), width, height, readConfig,
2301                                     rowBytes)) {
2302         ElevateDrawPreference(drawPreference, kGpuPrefersDraw_DrawPreference);
2303     }
2304 
2305     return true;
2306 }
2307 
onReadPixels(GrSurface * surface,GrSurfaceOrigin origin,int left,int top,int width,int height,GrPixelConfig config,void * buffer,size_t rowBytes)2308 bool GrGLGpu::onReadPixels(GrSurface* surface, GrSurfaceOrigin origin,
2309                            int left, int top,
2310                            int width, int height,
2311                            GrPixelConfig config,
2312                            void* buffer,
2313                            size_t rowBytes) {
2314     SkASSERT(surface);
2315 
2316     GrGLRenderTarget* renderTarget = static_cast<GrGLRenderTarget*>(surface->asRenderTarget());
2317     if (!renderTarget && !this->glCaps().canConfigBeFBOColorAttachment(surface->config())) {
2318         return false;
2319     }
2320 
2321     // OpenGL doesn't do sRGB <-> linear conversions when reading and writing pixels.
2322     if (requires_srgb_conversion(surface->config(), config)) {
2323         return false;
2324     }
2325 
2326     // We have a special case fallback for reading eight bit alpha. We will read back all four 8
2327     // bit channels as RGBA and then extract A.
2328     if (!this->readPixelsSupported(surface, config)) {
2329         // Don't attempt to do any srgb conversions since we only care about alpha.
2330         GrPixelConfig tempConfig = kRGBA_8888_GrPixelConfig;
2331         if (GrPixelConfigIsSRGB(surface->config())) {
2332             tempConfig = kSRGBA_8888_GrPixelConfig;
2333         }
2334         if (kAlpha_8_GrPixelConfig == config &&
2335             this->readPixelsSupported(surface, tempConfig)) {
2336             std::unique_ptr<uint32_t[]> temp(new uint32_t[width * height * 4]);
2337             if (this->onReadPixels(surface, origin, left, top, width, height,
2338                                    tempConfig, temp.get(), width*4)) {
2339                 uint8_t* dst = reinterpret_cast<uint8_t*>(buffer);
2340                 for (int j = 0; j < height; ++j) {
2341                     for (int i = 0; i < width; ++i) {
2342                         dst[j*rowBytes + i] = (0xFF000000U & temp[j*width+i]) >> 24;
2343                     }
2344                 }
2345                 return true;
2346             }
2347         }
2348 
2349         // If reading in half float format is not supported, then read in a temporary float buffer
2350         // and convert to half float.
2351         if (kRGBA_half_GrPixelConfig == config &&
2352             this->readPixelsSupported(surface, kRGBA_float_GrPixelConfig)) {
2353             std::unique_ptr<float[]> temp(new float[width * height * 4]);
2354             if (this->onReadPixels(surface, origin, left, top, width, height,
2355                                    kRGBA_float_GrPixelConfig, temp.get(),
2356                                    width*sizeof(float)*4)) {
2357                 uint8_t* dst = reinterpret_cast<uint8_t*>(buffer);
2358                 float* src = temp.get();
2359                 for (int j = 0; j < height; ++j) {
2360                     SkHalf* dstRow = reinterpret_cast<SkHalf*>(dst);
2361                     for (int i = 0; i < width; ++i) {
2362                         for (int color = 0; color < 4; color++) {
2363                             *dstRow++ = SkFloatToHalf(*src++);
2364                         }
2365                     }
2366                     dst += rowBytes;
2367                 }
2368                 return true;
2369             }
2370         }
2371         return false;
2372     }
2373 
2374     GrGLenum externalFormat;
2375     GrGLenum externalType;
2376     if (!this->glCaps().getReadPixelsFormat(surface->config(), config, &externalFormat,
2377                                             &externalType)) {
2378         return false;
2379     }
2380     bool flipY = kBottomLeft_GrSurfaceOrigin == origin;
2381 
2382     GrGLIRect glvp;
2383     if (renderTarget) {
2384         // resolve the render target if necessary
2385         switch (renderTarget->getResolveType()) {
2386             case GrGLRenderTarget::kCantResolve_ResolveType:
2387                 return false;
2388             case GrGLRenderTarget::kAutoResolves_ResolveType:
2389                 this->flushRenderTarget(renderTarget, &SkIRect::EmptyIRect());
2390                 break;
2391             case GrGLRenderTarget::kCanResolve_ResolveType:
2392                 this->onResolveRenderTarget(renderTarget, origin);
2393                 // we don't track the state of the READ FBO ID.
2394                 fStats.incRenderTargetBinds();
2395                 GL_CALL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER, renderTarget->textureFBOID()));
2396                 break;
2397             default:
2398                 SK_ABORT("Unknown resolve type");
2399         }
2400         glvp = renderTarget->getViewport();
2401     } else {
2402         // Use a temporary FBO.
2403         this->bindSurfaceFBOForPixelOps(surface, GR_GL_FRAMEBUFFER, &glvp, kSrc_TempFBOTarget);
2404         fHWBoundRenderTargetUniqueID.makeInvalid();
2405     }
2406 
2407     // the read rect is viewport-relative
2408     GrGLIRect readRect;
2409     readRect.setRelativeTo(glvp, left, top, width, height, origin);
2410 
2411     size_t bytesPerPixel = GrBytesPerPixel(config);
2412     size_t tightRowBytes = bytesPerPixel * width;
2413 
2414     size_t readDstRowBytes = tightRowBytes;
2415     void* readDst = buffer;
2416 
2417     // determine if GL can read using the passed rowBytes or if we need
2418     // a scratch buffer.
2419     SkAutoSMalloc<32 * sizeof(GrColor)> scratch;
2420     if (rowBytes != tightRowBytes) {
2421         if (this->glCaps().packRowLengthSupport() && !(rowBytes % bytesPerPixel)) {
2422             GL_CALL(PixelStorei(GR_GL_PACK_ROW_LENGTH,
2423                                 static_cast<GrGLint>(rowBytes / bytesPerPixel)));
2424             readDstRowBytes = rowBytes;
2425         } else {
2426             scratch.reset(tightRowBytes * height);
2427             readDst = scratch.get();
2428         }
2429     }
2430     if (flipY && this->glCaps().packFlipYSupport()) {
2431         GL_CALL(PixelStorei(GR_GL_PACK_REVERSE_ROW_ORDER, 1));
2432     }
2433     GL_CALL(PixelStorei(GR_GL_PACK_ALIGNMENT, config_alignment(config)));
2434 
2435     GL_CALL(ReadPixels(readRect.fLeft, readRect.fBottom,
2436                        readRect.fWidth, readRect.fHeight,
2437                        externalFormat, externalType, readDst));
2438     if (readDstRowBytes != tightRowBytes) {
2439         SkASSERT(this->glCaps().packRowLengthSupport());
2440         GL_CALL(PixelStorei(GR_GL_PACK_ROW_LENGTH, 0));
2441     }
2442     if (flipY && this->glCaps().packFlipYSupport()) {
2443         GL_CALL(PixelStorei(GR_GL_PACK_REVERSE_ROW_ORDER, 0));
2444         flipY = false;
2445     }
2446 
2447     // now reverse the order of the rows, since GL's are bottom-to-top, but our
2448     // API presents top-to-bottom. We must preserve the padding contents. Note
2449     // that the above readPixels did not overwrite the padding.
2450     if (readDst == buffer) {
2451         SkASSERT(rowBytes == readDstRowBytes);
2452         if (flipY) {
2453             scratch.reset(tightRowBytes);
2454             void* tmpRow = scratch.get();
2455             // flip y in-place by rows
2456             const int halfY = height >> 1;
2457             char* top = reinterpret_cast<char*>(buffer);
2458             char* bottom = top + (height - 1) * rowBytes;
2459             for (int y = 0; y < halfY; y++) {
2460                 memcpy(tmpRow, top, tightRowBytes);
2461                 memcpy(top, bottom, tightRowBytes);
2462                 memcpy(bottom, tmpRow, tightRowBytes);
2463                 top += rowBytes;
2464                 bottom -= rowBytes;
2465             }
2466         }
2467     } else {
2468         SkASSERT(readDst != buffer);
2469         SkASSERT(rowBytes != tightRowBytes);
2470         // copy from readDst to buffer while flipping y
2471         // const int halfY = height >> 1;
2472         const char* src = reinterpret_cast<const char*>(readDst);
2473         char* dst = reinterpret_cast<char*>(buffer);
2474         if (flipY) {
2475             dst += (height-1) * rowBytes;
2476         }
2477         for (int y = 0; y < height; y++) {
2478             memcpy(dst, src, tightRowBytes);
2479             src += readDstRowBytes;
2480             if (!flipY) {
2481                 dst += rowBytes;
2482             } else {
2483                 dst -= rowBytes;
2484             }
2485         }
2486     }
2487     if (!renderTarget) {
2488         this->unbindTextureFBOForPixelOps(GR_GL_FRAMEBUFFER, surface);
2489     }
2490     return true;
2491 }
2492 
createCommandBuffer(GrRenderTarget * rt,GrSurfaceOrigin origin,const GrGpuRTCommandBuffer::LoadAndStoreInfo & colorInfo,const GrGpuRTCommandBuffer::StencilLoadAndStoreInfo & stencilInfo)2493 GrGpuRTCommandBuffer* GrGLGpu::createCommandBuffer(
2494         GrRenderTarget* rt, GrSurfaceOrigin origin,
2495         const GrGpuRTCommandBuffer::LoadAndStoreInfo& colorInfo,
2496         const GrGpuRTCommandBuffer::StencilLoadAndStoreInfo& stencilInfo) {
2497     return new GrGLGpuRTCommandBuffer(this, rt, origin, colorInfo, stencilInfo);
2498 }
2499 
createCommandBuffer(GrTexture * texture,GrSurfaceOrigin origin)2500 GrGpuTextureCommandBuffer* GrGLGpu::createCommandBuffer(GrTexture* texture,
2501                                                         GrSurfaceOrigin origin) {
2502     return new GrGLGpuTextureCommandBuffer(this, texture, origin);
2503 }
2504 
flushRenderTarget(GrGLRenderTarget * target,const SkIRect * bounds,bool disableSRGB)2505 void GrGLGpu::flushRenderTarget(GrGLRenderTarget* target, const SkIRect* bounds, bool disableSRGB) {
2506     SkASSERT(target);
2507 
2508     GrGpuResource::UniqueID rtID = target->uniqueID();
2509     if (fHWBoundRenderTargetUniqueID != rtID) {
2510         fStats.incRenderTargetBinds();
2511         GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, target->renderFBOID()));
2512 #ifdef SK_DEBUG
2513         // don't do this check in Chromium -- this is causing
2514         // lots of repeated command buffer flushes when the compositor is
2515         // rendering with Ganesh, which is really slow; even too slow for
2516         // Debug mode.
2517         if (kChromium_GrGLDriver != this->glContext().driver()) {
2518             GrGLenum status;
2519             GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
2520             if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
2521                 SkDebugf("GrGLGpu::flushRenderTarget glCheckFramebufferStatus %x\n", status);
2522             }
2523         }
2524 #endif
2525         fHWBoundRenderTargetUniqueID = rtID;
2526         this->flushViewport(target->getViewport());
2527     }
2528 
2529     if (this->glCaps().srgbWriteControl()) {
2530         this->flushFramebufferSRGB(GrPixelConfigIsSRGB(target->config()) && !disableSRGB);
2531     }
2532 
2533     this->didWriteToSurface(target, bounds);
2534 }
2535 
flushFramebufferSRGB(bool enable)2536 void GrGLGpu::flushFramebufferSRGB(bool enable) {
2537     if (enable && kYes_TriState != fHWSRGBFramebuffer) {
2538         GL_CALL(Enable(GR_GL_FRAMEBUFFER_SRGB));
2539         fHWSRGBFramebuffer = kYes_TriState;
2540     } else if (!enable && kNo_TriState != fHWSRGBFramebuffer) {
2541         GL_CALL(Disable(GR_GL_FRAMEBUFFER_SRGB));
2542         fHWSRGBFramebuffer = kNo_TriState;
2543     }
2544 }
2545 
flushViewport(const GrGLIRect & viewport)2546 void GrGLGpu::flushViewport(const GrGLIRect& viewport) {
2547     if (fHWViewport != viewport) {
2548         viewport.pushToGLViewport(this->glInterface());
2549         fHWViewport = viewport;
2550     }
2551 }
2552 
2553 #define SWAP_PER_DRAW 0
2554 
2555 #if SWAP_PER_DRAW
2556     #if defined(SK_BUILD_FOR_MAC)
2557         #include <AGL/agl.h>
2558     #elif defined(SK_BUILD_FOR_WIN)
2559         #include <gl/GL.h>
SwapBuf()2560         void SwapBuf() {
2561             DWORD procID = GetCurrentProcessId();
2562             HWND hwnd = GetTopWindow(GetDesktopWindow());
2563             while(hwnd) {
2564                 DWORD wndProcID = 0;
2565                 GetWindowThreadProcessId(hwnd, &wndProcID);
2566                 if(wndProcID == procID) {
2567                     SwapBuffers(GetDC(hwnd));
2568                 }
2569                 hwnd = GetNextWindow(hwnd, GW_HWNDNEXT);
2570             }
2571          }
2572     #endif
2573 #endif
2574 
draw(const GrPipeline & pipeline,const GrPrimitiveProcessor & primProc,const GrMesh meshes[],const GrPipeline::DynamicState dynamicStates[],int meshCount)2575 void GrGLGpu::draw(const GrPipeline& pipeline,
2576                    const GrPrimitiveProcessor& primProc,
2577                    const GrMesh meshes[],
2578                    const GrPipeline::DynamicState dynamicStates[],
2579                    int meshCount) {
2580     this->handleDirtyContext();
2581 
2582     bool hasPoints = false;
2583     for (int i = 0; i < meshCount; ++i) {
2584         if (meshes[i].primitiveType() == GrPrimitiveType::kPoints) {
2585             hasPoints = true;
2586             break;
2587         }
2588     }
2589     if (!this->flushGLState(pipeline, primProc, hasPoints)) {
2590         return;
2591     }
2592 
2593     for (int i = 0; i < meshCount; ++i) {
2594         if (GrXferBarrierType barrierType = pipeline.xferBarrierType(*this->caps())) {
2595             this->xferBarrier(pipeline.renderTarget(), barrierType);
2596         }
2597 
2598         if (dynamicStates) {
2599             if (pipeline.getScissorState().enabled()) {
2600                 GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(pipeline.renderTarget());
2601                 this->flushScissor(dynamicStates[i].fScissorRect,
2602                                    glRT->getViewport(), pipeline.proxy()->origin());
2603             }
2604         }
2605         if (this->glCaps().requiresCullFaceEnableDisableWhenDrawingLinesAfterNonLines() &&
2606             GrIsPrimTypeLines(meshes[i].primitiveType()) &&
2607             !GrIsPrimTypeLines(fLastPrimitiveType)) {
2608             GL_CALL(Enable(GR_GL_CULL_FACE));
2609             GL_CALL(Disable(GR_GL_CULL_FACE));
2610         }
2611         meshes[i].sendToGpu(primProc, this);
2612         fLastPrimitiveType = meshes[i].primitiveType();
2613     }
2614 
2615 #if SWAP_PER_DRAW
2616     glFlush();
2617     #if defined(SK_BUILD_FOR_MAC)
2618         aglSwapBuffers(aglGetCurrentContext());
2619         int set_a_break_pt_here = 9;
2620         aglSwapBuffers(aglGetCurrentContext());
2621     #elif defined(SK_BUILD_FOR_WIN)
2622         SwapBuf();
2623         int set_a_break_pt_here = 9;
2624         SwapBuf();
2625     #endif
2626 #endif
2627 }
2628 
gr_primitive_type_to_gl_mode(GrPrimitiveType primitiveType)2629 static GrGLenum gr_primitive_type_to_gl_mode(GrPrimitiveType primitiveType) {
2630     switch (primitiveType) {
2631         case GrPrimitiveType::kTriangles:
2632             return GR_GL_TRIANGLES;
2633         case GrPrimitiveType::kTriangleStrip:
2634             return GR_GL_TRIANGLE_STRIP;
2635         case GrPrimitiveType::kTriangleFan:
2636             return GR_GL_TRIANGLE_FAN;
2637         case GrPrimitiveType::kPoints:
2638             return GR_GL_POINTS;
2639         case GrPrimitiveType::kLines:
2640             return GR_GL_LINES;
2641         case GrPrimitiveType::kLineStrip:
2642             return GR_GL_LINE_STRIP;
2643         case GrPrimitiveType::kLinesAdjacency:
2644             return GR_GL_LINES_ADJACENCY;
2645     }
2646     SK_ABORT("invalid GrPrimitiveType");
2647     return GR_GL_TRIANGLES;
2648 }
2649 
sendMeshToGpu(const GrPrimitiveProcessor & primProc,GrPrimitiveType primitiveType,const GrBuffer * vertexBuffer,int vertexCount,int baseVertex)2650 void GrGLGpu::sendMeshToGpu(const GrPrimitiveProcessor& primProc, GrPrimitiveType primitiveType,
2651                             const GrBuffer* vertexBuffer, int vertexCount, int baseVertex) {
2652     const GrGLenum glPrimType = gr_primitive_type_to_gl_mode(primitiveType);
2653     if (this->glCaps().drawArraysBaseVertexIsBroken()) {
2654         this->setupGeometry(primProc, nullptr, vertexBuffer, baseVertex, nullptr, 0);
2655         GL_CALL(DrawArrays(glPrimType, 0, vertexCount));
2656     } else {
2657         this->setupGeometry(primProc, nullptr, vertexBuffer, 0, nullptr, 0);
2658         GL_CALL(DrawArrays(glPrimType, baseVertex, vertexCount));
2659     }
2660     fStats.incNumDraws();
2661 }
2662 
sendIndexedMeshToGpu(const GrPrimitiveProcessor & primProc,GrPrimitiveType primitiveType,const GrBuffer * indexBuffer,int indexCount,int baseIndex,uint16_t minIndexValue,uint16_t maxIndexValue,const GrBuffer * vertexBuffer,int baseVertex)2663 void GrGLGpu::sendIndexedMeshToGpu(const GrPrimitiveProcessor& primProc,
2664                                    GrPrimitiveType primitiveType, const GrBuffer* indexBuffer,
2665                                    int indexCount, int baseIndex, uint16_t minIndexValue,
2666                                    uint16_t maxIndexValue, const GrBuffer* vertexBuffer,
2667                                    int baseVertex) {
2668     const GrGLenum glPrimType = gr_primitive_type_to_gl_mode(primitiveType);
2669     GrGLvoid* const indices = reinterpret_cast<void*>(indexBuffer->baseOffset() +
2670                                                       sizeof(uint16_t) * baseIndex);
2671 
2672     this->setupGeometry(primProc, indexBuffer, vertexBuffer, baseVertex, nullptr, 0);
2673 
2674     if (this->glCaps().drawRangeElementsSupport()) {
2675         GL_CALL(DrawRangeElements(glPrimType, minIndexValue, maxIndexValue, indexCount,
2676                                   GR_GL_UNSIGNED_SHORT, indices));
2677     } else {
2678         GL_CALL(DrawElements(glPrimType, indexCount, GR_GL_UNSIGNED_SHORT, indices));
2679     }
2680     fStats.incNumDraws();
2681 }
2682 
sendInstancedMeshToGpu(const GrPrimitiveProcessor & primProc,GrPrimitiveType primitiveType,const GrBuffer * vertexBuffer,int vertexCount,int baseVertex,const GrBuffer * instanceBuffer,int instanceCount,int baseInstance)2683 void GrGLGpu::sendInstancedMeshToGpu(const GrPrimitiveProcessor& primProc, GrPrimitiveType
2684                                      primitiveType, const GrBuffer* vertexBuffer,
2685                                      int vertexCount, int baseVertex,
2686                                      const GrBuffer* instanceBuffer, int instanceCount,
2687                                      int baseInstance) {
2688     GrGLenum glPrimType = gr_primitive_type_to_gl_mode(primitiveType);
2689     int maxInstances = this->glCaps().maxInstancesPerDrawArraysWithoutCrashing(instanceCount);
2690     for (int i = 0; i < instanceCount; i += maxInstances) {
2691         this->setupGeometry(primProc, nullptr, vertexBuffer, 0, instanceBuffer, baseInstance + i);
2692         GL_CALL(DrawArraysInstanced(glPrimType, baseVertex, vertexCount,
2693                                     SkTMin(instanceCount - i, maxInstances)));
2694         fStats.incNumDraws();
2695     }
2696 }
2697 
sendIndexedInstancedMeshToGpu(const GrPrimitiveProcessor & primProc,GrPrimitiveType primitiveType,const GrBuffer * indexBuffer,int indexCount,int baseIndex,const GrBuffer * vertexBuffer,int baseVertex,const GrBuffer * instanceBuffer,int instanceCount,int baseInstance)2698 void GrGLGpu::sendIndexedInstancedMeshToGpu(const GrPrimitiveProcessor& primProc,
2699                                             GrPrimitiveType primitiveType,
2700                                             const GrBuffer* indexBuffer, int indexCount,
2701                                             int baseIndex, const GrBuffer* vertexBuffer,
2702                                             int baseVertex, const GrBuffer* instanceBuffer,
2703                                             int instanceCount, int baseInstance) {
2704     const GrGLenum glPrimType = gr_primitive_type_to_gl_mode(primitiveType);
2705     GrGLvoid* indices = reinterpret_cast<void*>(indexBuffer->baseOffset() +
2706                                                 sizeof(uint16_t) * baseIndex);
2707     this->setupGeometry(primProc, indexBuffer, vertexBuffer, baseVertex,
2708                         instanceBuffer, baseInstance);
2709     GL_CALL(DrawElementsInstanced(glPrimType, indexCount, GR_GL_UNSIGNED_SHORT, indices,
2710                                   instanceCount));
2711     fStats.incNumDraws();
2712 }
2713 
onResolveRenderTarget(GrRenderTarget * target,GrSurfaceOrigin origin)2714 void GrGLGpu::onResolveRenderTarget(GrRenderTarget* target, GrSurfaceOrigin origin) {
2715     GrGLRenderTarget* rt = static_cast<GrGLRenderTarget*>(target);
2716     if (rt->needsResolve()) {
2717         // Some extensions automatically resolves the texture when it is read.
2718         if (this->glCaps().usesMSAARenderBuffers()) {
2719             SkASSERT(rt->textureFBOID() != rt->renderFBOID());
2720             SkASSERT(rt->textureFBOID() != 0 && rt->renderFBOID() != 0);
2721             fStats.incRenderTargetBinds();
2722             fStats.incRenderTargetBinds();
2723             GL_CALL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER, rt->renderFBOID()));
2724             GL_CALL(BindFramebuffer(GR_GL_DRAW_FRAMEBUFFER, rt->textureFBOID()));
2725             // make sure we go through flushRenderTarget() since we've modified
2726             // the bound DRAW FBO ID.
2727             fHWBoundRenderTargetUniqueID.makeInvalid();
2728             const GrGLIRect& vp = rt->getViewport();
2729             const SkIRect dirtyRect = rt->getResolveRect();
2730 
2731             if (GrGLCaps::kES_Apple_MSFBOType == this->glCaps().msFBOType()) {
2732                 // Apple's extension uses the scissor as the blit bounds.
2733                 GrScissorState scissorState;
2734                 scissorState.set(dirtyRect);
2735                 this->flushScissor(scissorState, vp, origin);
2736                 this->disableWindowRectangles();
2737                 GL_CALL(ResolveMultisampleFramebuffer());
2738             } else {
2739                 int l, b, r, t;
2740                 if (GrGLCaps::kResolveMustBeFull_BlitFrambufferFlag &
2741                     this->glCaps().blitFramebufferSupportFlags()) {
2742                     l = 0;
2743                     b = 0;
2744                     r = target->width();
2745                     t = target->height();
2746                 } else {
2747                     GrGLIRect rect;
2748                     rect.setRelativeTo(vp, dirtyRect, origin);
2749                     l = rect.fLeft;
2750                     b = rect.fBottom;
2751                     r = rect.fLeft + rect.fWidth;
2752                     t = rect.fBottom + rect.fHeight;
2753                 }
2754 
2755                 // BlitFrameBuffer respects the scissor, so disable it.
2756                 this->disableScissor();
2757                 this->disableWindowRectangles();
2758                 GL_CALL(BlitFramebuffer(l, b, r, t, l, b, r, t,
2759                                         GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST));
2760             }
2761         }
2762         rt->flagAsResolved();
2763     }
2764 }
2765 
2766 namespace {
2767 
2768 
gr_to_gl_stencil_op(GrStencilOp op)2769 GrGLenum gr_to_gl_stencil_op(GrStencilOp op) {
2770     static const GrGLenum gTable[kGrStencilOpCount] = {
2771         GR_GL_KEEP,        // kKeep
2772         GR_GL_ZERO,        // kZero
2773         GR_GL_REPLACE,     // kReplace
2774         GR_GL_INVERT,      // kInvert
2775         GR_GL_INCR_WRAP,   // kIncWrap
2776         GR_GL_DECR_WRAP,   // kDecWrap
2777         GR_GL_INCR,        // kIncClamp
2778         GR_GL_DECR,        // kDecClamp
2779     };
2780     GR_STATIC_ASSERT(0 == (int)GrStencilOp::kKeep);
2781     GR_STATIC_ASSERT(1 == (int)GrStencilOp::kZero);
2782     GR_STATIC_ASSERT(2 == (int)GrStencilOp::kReplace);
2783     GR_STATIC_ASSERT(3 == (int)GrStencilOp::kInvert);
2784     GR_STATIC_ASSERT(4 == (int)GrStencilOp::kIncWrap);
2785     GR_STATIC_ASSERT(5 == (int)GrStencilOp::kDecWrap);
2786     GR_STATIC_ASSERT(6 == (int)GrStencilOp::kIncClamp);
2787     GR_STATIC_ASSERT(7 == (int)GrStencilOp::kDecClamp);
2788     SkASSERT(op < (GrStencilOp)kGrStencilOpCount);
2789     return gTable[(int)op];
2790 }
2791 
set_gl_stencil(const GrGLInterface * gl,const GrStencilSettings::Face & face,GrGLenum glFace)2792 void set_gl_stencil(const GrGLInterface* gl,
2793                     const GrStencilSettings::Face& face,
2794                     GrGLenum glFace) {
2795     GrGLenum glFunc = GrToGLStencilFunc(face.fTest);
2796     GrGLenum glFailOp = gr_to_gl_stencil_op(face.fFailOp);
2797     GrGLenum glPassOp = gr_to_gl_stencil_op(face.fPassOp);
2798 
2799     GrGLint ref = face.fRef;
2800     GrGLint mask = face.fTestMask;
2801     GrGLint writeMask = face.fWriteMask;
2802 
2803     if (GR_GL_FRONT_AND_BACK == glFace) {
2804         // we call the combined func just in case separate stencil is not
2805         // supported.
2806         GR_GL_CALL(gl, StencilFunc(glFunc, ref, mask));
2807         GR_GL_CALL(gl, StencilMask(writeMask));
2808         GR_GL_CALL(gl, StencilOp(glFailOp, GR_GL_KEEP, glPassOp));
2809     } else {
2810         GR_GL_CALL(gl, StencilFuncSeparate(glFace, glFunc, ref, mask));
2811         GR_GL_CALL(gl, StencilMaskSeparate(glFace, writeMask));
2812         GR_GL_CALL(gl, StencilOpSeparate(glFace, glFailOp, GR_GL_KEEP, glPassOp));
2813     }
2814 }
2815 }
2816 
flushStencil(const GrStencilSettings & stencilSettings)2817 void GrGLGpu::flushStencil(const GrStencilSettings& stencilSettings) {
2818     if (stencilSettings.isDisabled()) {
2819         this->disableStencil();
2820     } else if (fHWStencilSettings != stencilSettings) {
2821         if (kYes_TriState != fHWStencilTestEnabled) {
2822             GL_CALL(Enable(GR_GL_STENCIL_TEST));
2823 
2824             fHWStencilTestEnabled = kYes_TriState;
2825         }
2826         if (stencilSettings.isTwoSided()) {
2827             set_gl_stencil(this->glInterface(),
2828                            stencilSettings.front(),
2829                            GR_GL_FRONT);
2830             set_gl_stencil(this->glInterface(),
2831                            stencilSettings.back(),
2832                            GR_GL_BACK);
2833         } else {
2834             set_gl_stencil(this->glInterface(),
2835                            stencilSettings.front(),
2836                            GR_GL_FRONT_AND_BACK);
2837         }
2838         fHWStencilSettings = stencilSettings;
2839     }
2840 }
2841 
disableStencil()2842 void GrGLGpu::disableStencil() {
2843     if (kNo_TriState != fHWStencilTestEnabled) {
2844         GL_CALL(Disable(GR_GL_STENCIL_TEST));
2845 
2846         fHWStencilTestEnabled = kNo_TriState;
2847         fHWStencilSettings.invalidate();
2848     }
2849 }
2850 
flushHWAAState(GrRenderTarget * rt,bool useHWAA,bool stencilEnabled)2851 void GrGLGpu::flushHWAAState(GrRenderTarget* rt, bool useHWAA, bool stencilEnabled) {
2852     // rt is only optional if useHWAA is false.
2853     SkASSERT(rt || !useHWAA);
2854     SkASSERT(!useHWAA || rt->isStencilBufferMultisampled());
2855 
2856     if (this->caps()->multisampleDisableSupport()) {
2857         if (useHWAA) {
2858             if (kYes_TriState != fMSAAEnabled) {
2859                 GL_CALL(Enable(GR_GL_MULTISAMPLE));
2860                 fMSAAEnabled = kYes_TriState;
2861             }
2862         } else {
2863             if (kNo_TriState != fMSAAEnabled) {
2864                 GL_CALL(Disable(GR_GL_MULTISAMPLE));
2865                 fMSAAEnabled = kNo_TriState;
2866             }
2867         }
2868     }
2869 
2870     if (0 != this->caps()->maxRasterSamples()) {
2871         if (useHWAA && GrFSAAType::kMixedSamples == rt->fsaaType() && !stencilEnabled) {
2872             // Since stencil is disabled and we want more samples than are in the color buffer, we
2873             // need to tell the rasterizer explicitly how many to run.
2874             if (kYes_TriState != fHWRasterMultisampleEnabled) {
2875                 GL_CALL(Enable(GR_GL_RASTER_MULTISAMPLE));
2876                 fHWRasterMultisampleEnabled = kYes_TriState;
2877             }
2878             if (rt->numStencilSamples() != fHWNumRasterSamples) {
2879                 SkASSERT(rt->numStencilSamples() <= this->caps()->maxRasterSamples());
2880                 GL_CALL(RasterSamples(rt->numStencilSamples(), GR_GL_TRUE));
2881                 fHWNumRasterSamples = rt->numStencilSamples();
2882             }
2883         } else {
2884             if (kNo_TriState != fHWRasterMultisampleEnabled) {
2885                 GL_CALL(Disable(GR_GL_RASTER_MULTISAMPLE));
2886                 fHWRasterMultisampleEnabled = kNo_TriState;
2887             }
2888         }
2889     } else {
2890         SkASSERT(!useHWAA || GrFSAAType::kMixedSamples != rt->fsaaType() || stencilEnabled);
2891     }
2892 }
2893 
flushBlend(const GrXferProcessor::BlendInfo & blendInfo,const GrSwizzle & swizzle)2894 void GrGLGpu::flushBlend(const GrXferProcessor::BlendInfo& blendInfo, const GrSwizzle& swizzle) {
2895     // Any optimization to disable blending should have already been applied and
2896     // tweaked the equation to "add" or "subtract", and the coeffs to (1, 0).
2897 
2898     GrBlendEquation equation = blendInfo.fEquation;
2899     GrBlendCoeff srcCoeff = blendInfo.fSrcBlend;
2900     GrBlendCoeff dstCoeff = blendInfo.fDstBlend;
2901     bool blendOff = (kAdd_GrBlendEquation == equation || kSubtract_GrBlendEquation == equation) &&
2902                     kOne_GrBlendCoeff == srcCoeff && kZero_GrBlendCoeff == dstCoeff;
2903     if (blendOff) {
2904         if (kNo_TriState != fHWBlendState.fEnabled) {
2905             GL_CALL(Disable(GR_GL_BLEND));
2906 
2907             // Workaround for the ARM KHR_blend_equation_advanced blacklist issue
2908             // https://code.google.com/p/skia/issues/detail?id=3943
2909             if (kARM_GrGLVendor == this->ctxInfo().vendor() &&
2910                 GrBlendEquationIsAdvanced(fHWBlendState.fEquation)) {
2911                 SkASSERT(this->caps()->advancedBlendEquationSupport());
2912                 // Set to any basic blending equation.
2913                 GrBlendEquation blend_equation = kAdd_GrBlendEquation;
2914                 GL_CALL(BlendEquation(gXfermodeEquation2Blend[blend_equation]));
2915                 fHWBlendState.fEquation = blend_equation;
2916             }
2917 
2918             fHWBlendState.fEnabled = kNo_TriState;
2919         }
2920         return;
2921     }
2922 
2923     if (kYes_TriState != fHWBlendState.fEnabled) {
2924         GL_CALL(Enable(GR_GL_BLEND));
2925 
2926         fHWBlendState.fEnabled = kYes_TriState;
2927     }
2928 
2929     if (fHWBlendState.fEquation != equation) {
2930         GL_CALL(BlendEquation(gXfermodeEquation2Blend[equation]));
2931         fHWBlendState.fEquation = equation;
2932     }
2933 
2934     if (GrBlendEquationIsAdvanced(equation)) {
2935         SkASSERT(this->caps()->advancedBlendEquationSupport());
2936         // Advanced equations have no other blend state.
2937         return;
2938     }
2939 
2940     if (fHWBlendState.fSrcCoeff != srcCoeff || fHWBlendState.fDstCoeff != dstCoeff) {
2941         GL_CALL(BlendFunc(gXfermodeCoeff2Blend[srcCoeff],
2942                           gXfermodeCoeff2Blend[dstCoeff]));
2943         fHWBlendState.fSrcCoeff = srcCoeff;
2944         fHWBlendState.fDstCoeff = dstCoeff;
2945     }
2946 
2947     if ((BlendCoeffReferencesConstant(srcCoeff) || BlendCoeffReferencesConstant(dstCoeff))) {
2948         GrColor blendConst = blendInfo.fBlendConstant;
2949         blendConst = swizzle.applyTo(blendConst);
2950         if (!fHWBlendState.fConstColorValid || fHWBlendState.fConstColor != blendConst) {
2951             GrGLfloat c[4];
2952             GrColorToRGBAFloat(blendConst, c);
2953             GL_CALL(BlendColor(c[0], c[1], c[2], c[3]));
2954             fHWBlendState.fConstColor = blendConst;
2955             fHWBlendState.fConstColorValid = true;
2956         }
2957     }
2958 }
2959 
wrap_mode_to_gl_wrap(GrSamplerState::WrapMode wrapMode)2960 static inline GrGLenum wrap_mode_to_gl_wrap(GrSamplerState::WrapMode wrapMode) {
2961     switch (wrapMode) {
2962         case GrSamplerState::WrapMode::kClamp:
2963             return GR_GL_CLAMP_TO_EDGE;
2964         case GrSamplerState::WrapMode::kRepeat:
2965             return GR_GL_REPEAT;
2966         case GrSamplerState::WrapMode::kMirrorRepeat:
2967             return GR_GL_MIRRORED_REPEAT;
2968     };
2969     SK_ABORT("Unknown wrap mode");
2970     return 0;
2971 }
2972 
get_component_enum_from_char(char component)2973 static GrGLenum get_component_enum_from_char(char component) {
2974     switch (component) {
2975         case 'r':
2976            return GR_GL_RED;
2977         case 'g':
2978            return GR_GL_GREEN;
2979         case 'b':
2980            return GR_GL_BLUE;
2981         case 'a':
2982            return GR_GL_ALPHA;
2983         default:
2984             SK_ABORT("Unsupported component");
2985             return 0;
2986     }
2987 }
2988 
2989 /** If texture swizzling is available using tex parameters then it is preferred over mangling
2990   the generated shader code. This potentially allows greater reuse of cached shaders. */
get_tex_param_swizzle(GrPixelConfig config,const GrGLCaps & caps,GrGLenum * glSwizzle)2991 static void get_tex_param_swizzle(GrPixelConfig config,
2992                                   const GrGLCaps& caps,
2993                                   GrGLenum* glSwizzle) {
2994     const GrSwizzle& swizzle = caps.configSwizzle(config);
2995     for (int i = 0; i < 4; ++i) {
2996         glSwizzle[i] = get_component_enum_from_char(swizzle.c_str()[i]);
2997     }
2998 }
2999 
filter_to_gl_mag_filter(GrSamplerState::Filter filter)3000 static GrGLenum filter_to_gl_mag_filter(GrSamplerState::Filter filter) {
3001     switch (filter) {
3002         case GrSamplerState::Filter::kNearest:
3003             return GR_GL_NEAREST;
3004         case GrSamplerState::Filter::kBilerp:
3005             return GR_GL_LINEAR;
3006         case GrSamplerState::Filter::kMipMap:
3007             return GR_GL_LINEAR;
3008     }
3009     SK_ABORT("Unknown filter");
3010     return 0;
3011 }
3012 
filter_to_gl_min_filter(GrSamplerState::Filter filter)3013 static GrGLenum filter_to_gl_min_filter(GrSamplerState::Filter filter) {
3014     switch (filter) {
3015         case GrSamplerState::Filter::kNearest:
3016             return GR_GL_NEAREST;
3017         case GrSamplerState::Filter::kBilerp:
3018             return GR_GL_LINEAR;
3019         case GrSamplerState::Filter::kMipMap:
3020             return GR_GL_LINEAR_MIPMAP_LINEAR;
3021     }
3022     SK_ABORT("Unknown filter");
3023     return 0;
3024 }
3025 
bindTexture(int unitIdx,const GrSamplerState & samplerState,bool allowSRGBInputs,GrGLTexture * texture,GrSurfaceOrigin textureOrigin)3026 void GrGLGpu::bindTexture(int unitIdx, const GrSamplerState& samplerState, bool allowSRGBInputs,
3027                           GrGLTexture* texture, GrSurfaceOrigin textureOrigin) {
3028     SkASSERT(texture);
3029 
3030 #ifdef SK_DEBUG
3031     if (!this->caps()->npotTextureTileSupport()) {
3032         if (samplerState.isRepeated()) {
3033             const int w = texture->width();
3034             const int h = texture->height();
3035             SkASSERT(SkIsPow2(w) && SkIsPow2(h));
3036         }
3037     }
3038 #endif
3039 
3040     // If we created a rt/tex and rendered to it without using a texture and now we're texturing
3041     // from the rt it will still be the last bound texture, but it needs resolving. So keep this
3042     // out of the "last != next" check.
3043     GrGLRenderTarget* texRT = static_cast<GrGLRenderTarget*>(texture->asRenderTarget());
3044     if (texRT) {
3045         this->onResolveRenderTarget(texRT, textureOrigin);
3046     }
3047 
3048     GrGpuResource::UniqueID textureID = texture->uniqueID();
3049     GrGLenum target = texture->target();
3050     if (fHWBoundTextureUniqueIDs[unitIdx] != textureID) {
3051         this->setTextureUnit(unitIdx);
3052         GL_CALL(BindTexture(target, texture->textureID()));
3053         fHWBoundTextureUniqueIDs[unitIdx] = textureID;
3054     }
3055 
3056     ResetTimestamp timestamp;
3057     const GrGLTexture::TexParams& oldTexParams = texture->getCachedTexParams(&timestamp);
3058     bool setAll = timestamp < this->getResetTimestamp();
3059     GrGLTexture::TexParams newTexParams;
3060 
3061     GrSamplerState::Filter filterMode = samplerState.filter();
3062 
3063     if (GrSamplerState::Filter::kMipMap == filterMode) {
3064         if (!this->caps()->mipMapSupport()) {
3065             filterMode = GrSamplerState::Filter::kBilerp;
3066         }
3067     }
3068 
3069     newTexParams.fMinFilter = filter_to_gl_min_filter(filterMode);
3070     newTexParams.fMagFilter = filter_to_gl_mag_filter(filterMode);
3071 
3072     if (this->glCaps().srgbDecodeDisableSupport() && GrPixelConfigIsSRGB(texture->config())) {
3073         newTexParams.fSRGBDecode = allowSRGBInputs ? GR_GL_DECODE_EXT : GR_GL_SKIP_DECODE_EXT;
3074         if (setAll || newTexParams.fSRGBDecode != oldTexParams.fSRGBDecode) {
3075             this->setTextureUnit(unitIdx);
3076             GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SRGB_DECODE_EXT, newTexParams.fSRGBDecode));
3077         }
3078     }
3079 
3080 #ifdef SK_DEBUG
3081     // We were supposed to ensure MipMaps were up-to-date and built correctly before getting here.
3082     if (GrSamplerState::Filter::kMipMap == filterMode) {
3083         SkASSERT(!texture->texturePriv().mipMapsAreDirty());
3084         if (GrPixelConfigIsSRGB(texture->config())) {
3085             SkDestinationSurfaceColorMode colorMode = allowSRGBInputs
3086                 ? SkDestinationSurfaceColorMode::kGammaAndColorSpaceAware
3087                 : SkDestinationSurfaceColorMode::kLegacy;
3088             SkASSERT(texture->texturePriv().mipColorMode() == colorMode);
3089         }
3090     }
3091 #endif
3092 
3093     newTexParams.fMaxMipMapLevel = texture->texturePriv().maxMipMapLevel();
3094 
3095     newTexParams.fWrapS = wrap_mode_to_gl_wrap(samplerState.wrapModeX());
3096     newTexParams.fWrapT = wrap_mode_to_gl_wrap(samplerState.wrapModeY());
3097     get_tex_param_swizzle(texture->config(), this->glCaps(), newTexParams.fSwizzleRGBA);
3098     if (setAll || newTexParams.fMagFilter != oldTexParams.fMagFilter) {
3099         this->setTextureUnit(unitIdx);
3100         GL_CALL(TexParameteri(target, GR_GL_TEXTURE_MAG_FILTER, newTexParams.fMagFilter));
3101     }
3102     if (setAll || newTexParams.fMinFilter != oldTexParams.fMinFilter) {
3103         this->setTextureUnit(unitIdx);
3104         GL_CALL(TexParameteri(target, GR_GL_TEXTURE_MIN_FILTER, newTexParams.fMinFilter));
3105     }
3106     if (setAll || newTexParams.fMaxMipMapLevel != oldTexParams.fMaxMipMapLevel) {
3107         // These are not supported in ES2 contexts
3108         if (this->glCaps().mipMapLevelAndLodControlSupport()) {
3109             if (newTexParams.fMaxMipMapLevel != 0) {
3110                 this->setTextureUnit(unitIdx);
3111                 GL_CALL(TexParameteri(target, GR_GL_TEXTURE_MIN_LOD, 0));
3112                 GL_CALL(TexParameteri(target, GR_GL_TEXTURE_BASE_LEVEL, 0));
3113                 GL_CALL(TexParameteri(target, GR_GL_TEXTURE_MAX_LOD,
3114                                       newTexParams.fMaxMipMapLevel));
3115                 GL_CALL(TexParameteri(target, GR_GL_TEXTURE_MAX_LEVEL,
3116                                       newTexParams.fMaxMipMapLevel));
3117             }
3118         }
3119     }
3120     if (setAll || newTexParams.fWrapS != oldTexParams.fWrapS) {
3121         this->setTextureUnit(unitIdx);
3122         GL_CALL(TexParameteri(target, GR_GL_TEXTURE_WRAP_S, newTexParams.fWrapS));
3123     }
3124     if (setAll || newTexParams.fWrapT != oldTexParams.fWrapT) {
3125         this->setTextureUnit(unitIdx);
3126         GL_CALL(TexParameteri(target, GR_GL_TEXTURE_WRAP_T, newTexParams.fWrapT));
3127     }
3128     if (this->glCaps().textureSwizzleSupport() &&
3129         (setAll || memcmp(newTexParams.fSwizzleRGBA,
3130                           oldTexParams.fSwizzleRGBA,
3131                           sizeof(newTexParams.fSwizzleRGBA)))) {
3132         this->setTextureSwizzle(unitIdx, target, newTexParams.fSwizzleRGBA);
3133     }
3134     texture->setCachedTexParams(newTexParams, this->getResetTimestamp());
3135 }
3136 
bindTexelBuffer(int unitIdx,GrPixelConfig texelConfig,GrGLBuffer * buffer)3137 void GrGLGpu::bindTexelBuffer(int unitIdx, GrPixelConfig texelConfig, GrGLBuffer* buffer) {
3138     SkASSERT(this->glCaps().canUseConfigWithTexelBuffer(texelConfig));
3139     SkASSERT(unitIdx >= 0 && unitIdx < fHWBufferTextures.count());
3140 
3141     BufferTexture& buffTex = fHWBufferTextures[unitIdx];
3142 
3143     if (!buffTex.fKnownBound) {
3144         if (!buffTex.fTextureID) {
3145             GL_CALL(GenTextures(1, &buffTex.fTextureID));
3146             if (!buffTex.fTextureID) {
3147                 return;
3148             }
3149         }
3150 
3151         this->setTextureUnit(unitIdx);
3152         GL_CALL(BindTexture(GR_GL_TEXTURE_BUFFER, buffTex.fTextureID));
3153 
3154         buffTex.fKnownBound = true;
3155     }
3156 
3157     if (buffer->uniqueID() != buffTex.fAttachedBufferUniqueID ||
3158         buffTex.fTexelConfig != texelConfig) {
3159 
3160         this->setTextureUnit(unitIdx);
3161         GL_CALL(TexBuffer(GR_GL_TEXTURE_BUFFER,
3162                           this->glCaps().configSizedInternalFormat(texelConfig),
3163                           buffer->bufferID()));
3164 
3165         buffTex.fTexelConfig = texelConfig;
3166         buffTex.fAttachedBufferUniqueID = buffer->uniqueID();
3167 
3168         if (this->glCaps().textureSwizzleSupport() &&
3169             this->glCaps().configSwizzle(texelConfig) != buffTex.fSwizzle) {
3170             GrGLenum glSwizzle[4];
3171             get_tex_param_swizzle(texelConfig, this->glCaps(), glSwizzle);
3172             this->setTextureSwizzle(unitIdx, GR_GL_TEXTURE_BUFFER, glSwizzle);
3173             buffTex.fSwizzle = this->glCaps().configSwizzle(texelConfig);
3174         }
3175 
3176         buffer->setHasAttachedToTexture();
3177         fHWMaxUsedBufferTextureUnit = SkTMax(unitIdx, fHWMaxUsedBufferTextureUnit);
3178     }
3179 }
3180 
generateMipmaps(const GrSamplerState & params,bool allowSRGBInputs,GrGLTexture * texture,GrSurfaceOrigin textureOrigin)3181 void GrGLGpu::generateMipmaps(const GrSamplerState& params, bool allowSRGBInputs,
3182                               GrGLTexture* texture, GrSurfaceOrigin textureOrigin) {
3183     SkASSERT(texture);
3184 
3185     // First, figure out if we need mips for this texture at all:
3186     GrSamplerState::Filter filterMode = params.filter();
3187 
3188     if (GrSamplerState::Filter::kMipMap == filterMode) {
3189         if (!this->caps()->mipMapSupport()) {
3190             filterMode = GrSamplerState::Filter::kBilerp;
3191         }
3192     }
3193 
3194     if (GrSamplerState::Filter::kMipMap != filterMode) {
3195         return;
3196     }
3197 
3198     // If this is an sRGB texture and the mips were previously built the "other" way
3199     // (gamma-correct vs. not), then we need to rebuild them. We don't need to check for
3200     // srgbSupport - we'll *never* get an sRGB pixel config if we don't support it.
3201     SkDestinationSurfaceColorMode colorMode = allowSRGBInputs
3202         ? SkDestinationSurfaceColorMode::kGammaAndColorSpaceAware
3203         : SkDestinationSurfaceColorMode::kLegacy;
3204     if (GrPixelConfigIsSRGB(texture->config()) &&
3205         colorMode != texture->texturePriv().mipColorMode()) {
3206         texture->texturePriv().markMipMapsDirty();
3207     }
3208 
3209     // If the mips aren't dirty, we're done:
3210     if (!texture->texturePriv().mipMapsAreDirty()) {
3211         return;
3212     }
3213 
3214     // If we created a rt/tex and rendered to it without using a texture and now we're texturing
3215     // from the rt it will still be the last bound texture, but it needs resolving.
3216     GrGLRenderTarget* texRT = static_cast<GrGLRenderTarget*>(texture->asRenderTarget());
3217     if (texRT) {
3218         this->onResolveRenderTarget(texRT, textureOrigin);
3219     }
3220 
3221     GrGLenum target = texture->target();
3222     this->setScratchTextureUnit();
3223     GL_CALL(BindTexture(target, texture->textureID()));
3224 
3225     // Configure sRGB decode, if necessary. This state is the only thing needed for the driver
3226     // call (glGenerateMipmap) to work correctly. Our manual method dirties other state, too.
3227     if (this->glCaps().srgbDecodeDisableSupport() && GrPixelConfigIsSRGB(texture->config())) {
3228         GrGLenum srgbDecode = allowSRGBInputs ? GR_GL_DECODE_EXT : GR_GL_SKIP_DECODE_EXT;
3229         // Command buffer's sRGB decode extension doesn't influence mipmap generation correctly.
3230         // If we set this to skip_decode, it appears to suppress sRGB -> Linear for each downsample,
3231         // but not the Linear -> sRGB when writing the next level. The result is that mip-chains
3232         // get progressively brighter as you go down. Forcing this to 'decode' gives predictable
3233         // (and only slightly incorrect) results. See crbug.com/655247 (~comment 28)
3234         if (!this->glCaps().srgbDecodeDisableAffectsMipmaps()) {
3235             srgbDecode = GR_GL_DECODE_EXT;
3236         }
3237         GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SRGB_DECODE_EXT, srgbDecode));
3238     }
3239 
3240     // Either do manual mipmap generation or (if that fails), just rely on the driver:
3241     if (!this->generateMipmap(texture, textureOrigin, allowSRGBInputs)) {
3242         GL_CALL(GenerateMipmap(target));
3243     }
3244 
3245     texture->texturePriv().markMipMapsClean();
3246     texture->texturePriv().setMaxMipMapLevel(SkMipMap::ComputeLevelCount(
3247         texture->width(), texture->height()));
3248     texture->texturePriv().setMipColorMode(colorMode);
3249 
3250     // We have potentially set lots of state on the texture. Easiest to dirty it all:
3251     texture->textureParamsModified();
3252 }
3253 
setTextureSwizzle(int unitIdx,GrGLenum target,const GrGLenum swizzle[])3254 void GrGLGpu::setTextureSwizzle(int unitIdx, GrGLenum target, const GrGLenum swizzle[]) {
3255     this->setTextureUnit(unitIdx);
3256     if (this->glStandard() == kGLES_GrGLStandard) {
3257         // ES3 added swizzle support but not GL_TEXTURE_SWIZZLE_RGBA.
3258         GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SWIZZLE_R, swizzle[0]));
3259         GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SWIZZLE_G, swizzle[1]));
3260         GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SWIZZLE_B, swizzle[2]));
3261         GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SWIZZLE_A, swizzle[3]));
3262     } else {
3263         GR_STATIC_ASSERT(sizeof(swizzle[0]) == sizeof(GrGLint));
3264         GL_CALL(TexParameteriv(target, GR_GL_TEXTURE_SWIZZLE_RGBA,
3265                                reinterpret_cast<const GrGLint*>(swizzle)));
3266     }
3267 }
3268 
flushColorWrite(bool writeColor)3269 void GrGLGpu::flushColorWrite(bool writeColor) {
3270     if (!writeColor) {
3271         if (kNo_TriState != fHWWriteToColor) {
3272             GL_CALL(ColorMask(GR_GL_FALSE, GR_GL_FALSE,
3273                               GR_GL_FALSE, GR_GL_FALSE));
3274             fHWWriteToColor = kNo_TriState;
3275         }
3276     } else {
3277         if (kYes_TriState != fHWWriteToColor) {
3278             GL_CALL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
3279             fHWWriteToColor = kYes_TriState;
3280         }
3281     }
3282 }
3283 
setTextureUnit(int unit)3284 void GrGLGpu::setTextureUnit(int unit) {
3285     SkASSERT(unit >= 0 && unit < fHWBoundTextureUniqueIDs.count());
3286     if (unit != fHWActiveTextureUnitIdx) {
3287         GL_CALL(ActiveTexture(GR_GL_TEXTURE0 + unit));
3288         fHWActiveTextureUnitIdx = unit;
3289     }
3290 }
3291 
setScratchTextureUnit()3292 void GrGLGpu::setScratchTextureUnit() {
3293     // Bind the last texture unit since it is the least likely to be used by GrGLProgram.
3294     int lastUnitIdx = fHWBoundTextureUniqueIDs.count() - 1;
3295     if (lastUnitIdx != fHWActiveTextureUnitIdx) {
3296         GL_CALL(ActiveTexture(GR_GL_TEXTURE0 + lastUnitIdx));
3297         fHWActiveTextureUnitIdx = lastUnitIdx;
3298     }
3299     // clear out the this field so that if a program does use this unit it will rebind the correct
3300     // texture.
3301     fHWBoundTextureUniqueIDs[lastUnitIdx].makeInvalid();
3302 }
3303 
3304 // Determines whether glBlitFramebuffer could be used between src and dst by onCopySurface.
can_blit_framebuffer_for_copy_surface(const GrSurface * dst,GrSurfaceOrigin dstOrigin,const GrSurface * src,GrSurfaceOrigin srcOrigin,const SkIRect & srcRect,const SkIPoint & dstPoint,const GrGLGpu * gpu)3305 static inline bool can_blit_framebuffer_for_copy_surface(
3306                                                 const GrSurface* dst, GrSurfaceOrigin dstOrigin,
3307                                                 const GrSurface* src, GrSurfaceOrigin srcOrigin,
3308                                                 const SkIRect& srcRect,
3309                                                 const SkIPoint& dstPoint,
3310                                                 const GrGLGpu* gpu) {
3311     auto blitFramebufferFlags = gpu->glCaps().blitFramebufferSupportFlags();
3312     if (!gpu->glCaps().canConfigBeFBOColorAttachment(dst->config()) ||
3313         !gpu->glCaps().canConfigBeFBOColorAttachment(src->config())) {
3314         return false;
3315     }
3316     // Blits are not allowed between int color buffers and float/fixed color buffers. GrGpu should
3317     // have filtered such cases out.
3318     SkASSERT(GrPixelConfigIsSint(dst->config()) == GrPixelConfigIsSint(src->config()));
3319     const GrGLTexture* dstTex = static_cast<const GrGLTexture*>(dst->asTexture());
3320     const GrGLTexture* srcTex = static_cast<const GrGLTexture*>(src->asTexture());
3321     const GrRenderTarget* dstRT = dst->asRenderTarget();
3322     const GrRenderTarget* srcRT = src->asRenderTarget();
3323     if (dstTex && dstTex->target() != GR_GL_TEXTURE_2D) {
3324         return false;
3325     }
3326     if (srcTex && srcTex->target() != GR_GL_TEXTURE_2D) {
3327         return false;
3328     }
3329     if (GrGLCaps::kNoSupport_BlitFramebufferFlag & blitFramebufferFlags) {
3330         return false;
3331     }
3332     if (GrGLCaps::kNoScalingOrMirroring_BlitFramebufferFlag & blitFramebufferFlags) {
3333         // We would mirror to compensate for origin changes. Note that copySurface is
3334         // specified such that the src and dst rects are the same.
3335         if (dstOrigin != srcOrigin) {
3336             return false;
3337         }
3338     }
3339     if (GrGLCaps::kResolveMustBeFull_BlitFrambufferFlag & blitFramebufferFlags) {
3340         if (srcRT && srcRT->numColorSamples() > 1) {
3341             if (dstRT && 1 == dstRT->numColorSamples()) {
3342                 return false;
3343             }
3344             if (SkRect::Make(srcRect) != srcRT->getBoundsRect()) {
3345                 return false;
3346             }
3347         }
3348     }
3349     if (GrGLCaps::kNoMSAADst_BlitFramebufferFlag & blitFramebufferFlags) {
3350         if (dstRT && dstRT->numColorSamples() > 1) {
3351             return false;
3352         }
3353     }
3354     if (GrGLCaps::kNoFormatConversion_BlitFramebufferFlag & blitFramebufferFlags) {
3355         if (dst->config() != src->config()) {
3356             return false;
3357         }
3358     } else if (GrGLCaps::kNoFormatConversionForMSAASrc_BlitFramebufferFlag & blitFramebufferFlags) {
3359         const GrRenderTarget* srcRT = src->asRenderTarget();
3360         if (srcRT && srcRT->numColorSamples() > 1 && dst->config() != src->config()) {
3361             return false;
3362         }
3363     }
3364     if (GrGLCaps::kRectsMustMatchForMSAASrc_BlitFramebufferFlag & blitFramebufferFlags) {
3365         if (srcRT && srcRT->numColorSamples() > 1) {
3366             if (dstPoint.fX != srcRect.fLeft || dstPoint.fY != srcRect.fTop) {
3367                 return false;
3368             }
3369             if (dstOrigin != srcOrigin) {
3370                 return false;
3371             }
3372         }
3373     }
3374     return true;
3375 }
3376 
rt_has_msaa_render_buffer(const GrGLRenderTarget * rt,const GrGLCaps & glCaps)3377 static bool rt_has_msaa_render_buffer(const GrGLRenderTarget* rt, const GrGLCaps& glCaps) {
3378     // A RT has a separate MSAA renderbuffer if:
3379     // 1) It's multisampled
3380     // 2) We're using an extension with separate MSAA renderbuffers
3381     // 3) It's not FBO 0, which is special and always auto-resolves
3382     return rt->numColorSamples() > 1 && glCaps.usesMSAARenderBuffers() && rt->renderFBOID() != 0;
3383 }
3384 
can_copy_texsubimage(const GrSurface * dst,GrSurfaceOrigin dstOrigin,const GrSurface * src,GrSurfaceOrigin srcOrigin,const GrGLGpu * gpu)3385 static inline bool can_copy_texsubimage(const GrSurface* dst, GrSurfaceOrigin dstOrigin,
3386                                         const GrSurface* src, GrSurfaceOrigin srcOrigin,
3387                                         const GrGLGpu* gpu) {
3388     // Table 3.9 of the ES2 spec indicates the supported formats with CopyTexSubImage
3389     // and BGRA isn't in the spec. There doesn't appear to be any extension that adds it. Perhaps
3390     // many drivers would allow it to work, but ANGLE does not.
3391     if (kGLES_GrGLStandard == gpu->glStandard() && gpu->glCaps().bgraIsInternalFormat() &&
3392         (kBGRA_8888_GrPixelConfig == dst->config() || kBGRA_8888_GrPixelConfig == src->config())) {
3393         return false;
3394     }
3395     const GrGLRenderTarget* dstRT = static_cast<const GrGLRenderTarget*>(dst->asRenderTarget());
3396     // If dst is multisampled (and uses an extension where there is a separate MSAA renderbuffer)
3397     // then we don't want to copy to the texture but to the MSAA buffer.
3398     if (dstRT && rt_has_msaa_render_buffer(dstRT, gpu->glCaps())) {
3399         return false;
3400     }
3401     const GrGLRenderTarget* srcRT = static_cast<const GrGLRenderTarget*>(src->asRenderTarget());
3402     // If the src is multisampled (and uses an extension where there is a separate MSAA
3403     // renderbuffer) then it is an invalid operation to call CopyTexSubImage
3404     if (srcRT && rt_has_msaa_render_buffer(srcRT, gpu->glCaps())) {
3405         return false;
3406     }
3407 
3408     const GrGLTexture* dstTex = static_cast<const GrGLTexture*>(dst->asTexture());
3409     // CopyTex(Sub)Image writes to a texture and we have no way of dynamically wrapping a RT in a
3410     // texture.
3411     if (!dstTex) {
3412         return false;
3413     }
3414 
3415     const GrGLTexture* srcTex = static_cast<const GrGLTexture*>(src->asTexture());
3416 
3417     // Check that we could wrap the source in an FBO, that the dst is TEXTURE_2D, that no mirroring
3418     // is required.
3419     if (gpu->glCaps().canConfigBeFBOColorAttachment(src->config()) &&
3420         (!srcTex || srcTex->target() == GR_GL_TEXTURE_2D) && dstTex->target() == GR_GL_TEXTURE_2D &&
3421         dstOrigin == srcOrigin) {
3422         return true;
3423     } else {
3424         return false;
3425     }
3426 }
3427 
3428 // If a temporary FBO was created, its non-zero ID is returned. The viewport that the copy rect is
3429 // relative to is output.
bindSurfaceFBOForPixelOps(GrSurface * surface,GrGLenum fboTarget,GrGLIRect * viewport,TempFBOTarget tempFBOTarget)3430 void GrGLGpu::bindSurfaceFBOForPixelOps(GrSurface* surface, GrGLenum fboTarget, GrGLIRect* viewport,
3431                                         TempFBOTarget tempFBOTarget) {
3432     GrGLRenderTarget* rt = static_cast<GrGLRenderTarget*>(surface->asRenderTarget());
3433     if (!rt) {
3434         SkASSERT(surface->asTexture());
3435         GrGLTexture* texture = static_cast<GrGLTexture*>(surface->asTexture());
3436         GrGLuint texID = texture->textureID();
3437         GrGLenum target = texture->target();
3438         GrGLuint* tempFBOID;
3439         tempFBOID = kSrc_TempFBOTarget == tempFBOTarget ? &fTempSrcFBOID : &fTempDstFBOID;
3440 
3441         if (0 == *tempFBOID) {
3442             GR_GL_CALL(this->glInterface(), GenFramebuffers(1, tempFBOID));
3443         }
3444 
3445         fStats.incRenderTargetBinds();
3446         GR_GL_CALL(this->glInterface(), BindFramebuffer(fboTarget, *tempFBOID));
3447         GR_GL_CALL(this->glInterface(), FramebufferTexture2D(fboTarget,
3448                                                              GR_GL_COLOR_ATTACHMENT0,
3449                                                              target,
3450                                                              texID,
3451                                                              0));
3452         texture->baseLevelWasBoundToFBO();
3453         viewport->fLeft = 0;
3454         viewport->fBottom = 0;
3455         viewport->fWidth = surface->width();
3456         viewport->fHeight = surface->height();
3457     } else {
3458         fStats.incRenderTargetBinds();
3459         GR_GL_CALL(this->glInterface(), BindFramebuffer(fboTarget, rt->renderFBOID()));
3460         *viewport = rt->getViewport();
3461     }
3462 }
3463 
unbindTextureFBOForPixelOps(GrGLenum fboTarget,GrSurface * surface)3464 void GrGLGpu::unbindTextureFBOForPixelOps(GrGLenum fboTarget, GrSurface* surface) {
3465     // bindSurfaceFBOForPixelOps temporarily binds textures that are not render targets to
3466     if (!surface->asRenderTarget()) {
3467         SkASSERT(surface->asTexture());
3468         GrGLenum textureTarget = static_cast<GrGLTexture*>(surface->asTexture())->target();
3469         GR_GL_CALL(this->glInterface(), FramebufferTexture2D(fboTarget,
3470                                                              GR_GL_COLOR_ATTACHMENT0,
3471                                                              textureTarget,
3472                                                              0,
3473                                                              0));
3474     }
3475 }
3476 
onCopySurface(GrSurface * dst,GrSurfaceOrigin dstOrigin,GrSurface * src,GrSurfaceOrigin srcOrigin,const SkIRect & srcRect,const SkIPoint & dstPoint,bool canDiscardOutsideDstRect)3477 bool GrGLGpu::onCopySurface(GrSurface* dst, GrSurfaceOrigin dstOrigin,
3478                             GrSurface* src, GrSurfaceOrigin srcOrigin,
3479                             const SkIRect& srcRect, const SkIPoint& dstPoint,
3480                             bool canDiscardOutsideDstRect) {
3481     // None of our copy methods can handle a swizzle. TODO: Make copySurfaceAsDraw handle the
3482     // swizzle.
3483     if (this->caps()->shaderCaps()->configOutputSwizzle(src->config()) !=
3484         this->caps()->shaderCaps()->configOutputSwizzle(dst->config())) {
3485         return false;
3486     }
3487     // Don't prefer copying as a draw if the dst doesn't already have a FBO object.
3488     bool preferCopy = SkToBool(dst->asRenderTarget());
3489     if (preferCopy && src->asTexture()) {
3490         if (this->copySurfaceAsDraw(dst, dstOrigin, src, srcOrigin, srcRect, dstPoint)) {
3491             return true;
3492         }
3493     }
3494 
3495     if (can_copy_texsubimage(dst, dstOrigin, src, srcOrigin, this)) {
3496         this->copySurfaceAsCopyTexSubImage(dst, dstOrigin, src, srcOrigin, srcRect, dstPoint);
3497         return true;
3498     }
3499 
3500     if (can_blit_framebuffer_for_copy_surface(dst, dstOrigin, src, srcOrigin,
3501                                               srcRect, dstPoint, this)) {
3502         return this->copySurfaceAsBlitFramebuffer(dst, dstOrigin, src, srcOrigin,
3503                                                   srcRect, dstPoint);
3504     }
3505 
3506     if (!preferCopy && src->asTexture()) {
3507         if (this->copySurfaceAsDraw(dst, dstOrigin, src, srcOrigin, srcRect, dstPoint)) {
3508             return true;
3509         }
3510     }
3511 
3512     return false;
3513 }
3514 
createCopyProgram(GrTexture * srcTex)3515 bool GrGLGpu::createCopyProgram(GrTexture* srcTex) {
3516     TRACE_EVENT0("skia", TRACE_FUNC);
3517 
3518     int progIdx = TextureToCopyProgramIdx(srcTex);
3519     const GrShaderCaps* shaderCaps = this->caps()->shaderCaps();
3520     GrSLType samplerType = srcTex->texturePriv().samplerType();
3521 
3522     if (!fCopyProgramArrayBuffer) {
3523         static const GrGLfloat vdata[] = {
3524             0, 0,
3525             0, 1,
3526             1, 0,
3527             1, 1
3528         };
3529         fCopyProgramArrayBuffer.reset(GrGLBuffer::Create(this, sizeof(vdata), kVertex_GrBufferType,
3530                                                          kStatic_GrAccessPattern, vdata));
3531     }
3532     if (!fCopyProgramArrayBuffer) {
3533         return false;
3534     }
3535 
3536     SkASSERT(!fCopyPrograms[progIdx].fProgram);
3537     GL_CALL_RET(fCopyPrograms[progIdx].fProgram, CreateProgram());
3538     if (!fCopyPrograms[progIdx].fProgram) {
3539         return false;
3540     }
3541 
3542     const char* version = shaderCaps->versionDeclString();
3543     GrShaderVar aVertex("a_vertex", kHalf2_GrSLType, GrShaderVar::kIn_TypeModifier);
3544     GrShaderVar uTexCoordXform("u_texCoordXform", kHalf4_GrSLType,
3545                                GrShaderVar::kUniform_TypeModifier);
3546     GrShaderVar uPosXform("u_posXform", kHalf4_GrSLType, GrShaderVar::kUniform_TypeModifier);
3547     GrShaderVar uTexture("u_texture", samplerType, GrShaderVar::kUniform_TypeModifier);
3548     GrShaderVar vTexCoord("v_texCoord", kHalf2_GrSLType, GrShaderVar::kOut_TypeModifier);
3549     GrShaderVar oFragColor("o_FragColor", kHalf4_GrSLType, GrShaderVar::kOut_TypeModifier);
3550 
3551     SkString vshaderTxt(version);
3552     if (shaderCaps->noperspectiveInterpolationSupport()) {
3553         if (const char* extension = shaderCaps->noperspectiveInterpolationExtensionString()) {
3554             vshaderTxt.appendf("#extension %s : require\n", extension);
3555         }
3556         vTexCoord.addModifier("noperspective");
3557     }
3558 
3559     aVertex.appendDecl(shaderCaps, &vshaderTxt);
3560     vshaderTxt.append(";");
3561     uTexCoordXform.appendDecl(shaderCaps, &vshaderTxt);
3562     vshaderTxt.append(";");
3563     uPosXform.appendDecl(shaderCaps, &vshaderTxt);
3564     vshaderTxt.append(";");
3565     vTexCoord.appendDecl(shaderCaps, &vshaderTxt);
3566     vshaderTxt.append(";");
3567 
3568     vshaderTxt.append(
3569         "// Copy Program VS\n"
3570         "void main() {"
3571         "  v_texCoord = a_vertex.xy * u_texCoordXform.xy + u_texCoordXform.zw;"
3572         "  sk_Position.xy = a_vertex * u_posXform.xy + u_posXform.zw;"
3573         "  sk_Position.zw = half2(0, 1);"
3574         "}"
3575     );
3576 
3577     SkString fshaderTxt(version);
3578     if (shaderCaps->noperspectiveInterpolationSupport()) {
3579         if (const char* extension = shaderCaps->noperspectiveInterpolationExtensionString()) {
3580             fshaderTxt.appendf("#extension %s : require\n", extension);
3581         }
3582     }
3583     if (samplerType == kTextureExternalSampler_GrSLType) {
3584         fshaderTxt.appendf("#extension %s : require\n",
3585                            shaderCaps->externalTextureExtensionString());
3586     }
3587     vTexCoord.setTypeModifier(GrShaderVar::kIn_TypeModifier);
3588     vTexCoord.appendDecl(shaderCaps, &fshaderTxt);
3589     fshaderTxt.append(";");
3590     uTexture.appendDecl(shaderCaps, &fshaderTxt);
3591     fshaderTxt.append(";");
3592     fshaderTxt.appendf(
3593         "// Copy Program FS\n"
3594         "void main() {"
3595         "  sk_FragColor = texture(u_texture, v_texCoord);"
3596         "}"
3597     );
3598 
3599     const char* str;
3600     GrGLint length;
3601 
3602     str = vshaderTxt.c_str();
3603     length = SkToInt(vshaderTxt.size());
3604     SkSL::Program::Settings settings;
3605     settings.fCaps = shaderCaps;
3606     SkSL::String glsl;
3607     std::unique_ptr<SkSL::Program> program = GrSkSLtoGLSL(*fGLContext, GR_GL_VERTEX_SHADER,
3608                                                           &str, &length, 1, settings, &glsl);
3609     GrGLuint vshader = GrGLCompileAndAttachShader(*fGLContext, fCopyPrograms[progIdx].fProgram,
3610                                                   GR_GL_VERTEX_SHADER, glsl.c_str(), glsl.size(),
3611                                                   &fStats, settings);
3612     SkASSERT(program->fInputs.isEmpty());
3613 
3614     str = fshaderTxt.c_str();
3615     length = SkToInt(fshaderTxt.size());
3616     program = GrSkSLtoGLSL(*fGLContext, GR_GL_FRAGMENT_SHADER, &str, &length, 1, settings, &glsl);
3617     GrGLuint fshader = GrGLCompileAndAttachShader(*fGLContext, fCopyPrograms[progIdx].fProgram,
3618                                                   GR_GL_FRAGMENT_SHADER, glsl.c_str(), glsl.size(),
3619                                                   &fStats, settings);
3620     SkASSERT(program->fInputs.isEmpty());
3621 
3622     GL_CALL(LinkProgram(fCopyPrograms[progIdx].fProgram));
3623 
3624     GL_CALL_RET(fCopyPrograms[progIdx].fTextureUniform,
3625                 GetUniformLocation(fCopyPrograms[progIdx].fProgram, "u_texture"));
3626     GL_CALL_RET(fCopyPrograms[progIdx].fPosXformUniform,
3627                 GetUniformLocation(fCopyPrograms[progIdx].fProgram, "u_posXform"));
3628     GL_CALL_RET(fCopyPrograms[progIdx].fTexCoordXformUniform,
3629                 GetUniformLocation(fCopyPrograms[progIdx].fProgram, "u_texCoordXform"));
3630 
3631     GL_CALL(BindAttribLocation(fCopyPrograms[progIdx].fProgram, 0, "a_vertex"));
3632 
3633     GL_CALL(DeleteShader(vshader));
3634     GL_CALL(DeleteShader(fshader));
3635 
3636     return true;
3637 }
3638 
createMipmapProgram(int progIdx)3639 bool GrGLGpu::createMipmapProgram(int progIdx) {
3640     const bool oddWidth = SkToBool(progIdx & 0x2);
3641     const bool oddHeight = SkToBool(progIdx & 0x1);
3642     const int numTaps = (oddWidth ? 2 : 1) * (oddHeight ? 2 : 1);
3643 
3644     const GrShaderCaps* shaderCaps = this->caps()->shaderCaps();
3645 
3646     SkASSERT(!fMipmapPrograms[progIdx].fProgram);
3647     GL_CALL_RET(fMipmapPrograms[progIdx].fProgram, CreateProgram());
3648     if (!fMipmapPrograms[progIdx].fProgram) {
3649         return false;
3650     }
3651 
3652     const char* version = shaderCaps->versionDeclString();
3653     GrShaderVar aVertex("a_vertex", kHalf2_GrSLType, GrShaderVar::kIn_TypeModifier);
3654     GrShaderVar uTexCoordXform("u_texCoordXform", kHalf4_GrSLType,
3655                                GrShaderVar::kUniform_TypeModifier);
3656     GrShaderVar uTexture("u_texture", kTexture2DSampler_GrSLType,
3657                          GrShaderVar::kUniform_TypeModifier);
3658     // We need 1, 2, or 4 texture coordinates (depending on parity of each dimension):
3659     GrShaderVar vTexCoords[] = {
3660         GrShaderVar("v_texCoord0", kHalf2_GrSLType, GrShaderVar::kOut_TypeModifier),
3661         GrShaderVar("v_texCoord1", kHalf2_GrSLType, GrShaderVar::kOut_TypeModifier),
3662         GrShaderVar("v_texCoord2", kHalf2_GrSLType, GrShaderVar::kOut_TypeModifier),
3663         GrShaderVar("v_texCoord3", kHalf2_GrSLType, GrShaderVar::kOut_TypeModifier),
3664     };
3665     GrShaderVar oFragColor("o_FragColor", kHalf4_GrSLType,GrShaderVar::kOut_TypeModifier);
3666 
3667     SkString vshaderTxt(version);
3668     if (shaderCaps->noperspectiveInterpolationSupport()) {
3669         if (const char* extension = shaderCaps->noperspectiveInterpolationExtensionString()) {
3670             vshaderTxt.appendf("#extension %s : require\n", extension);
3671         }
3672         vTexCoords[0].addModifier("noperspective");
3673         vTexCoords[1].addModifier("noperspective");
3674         vTexCoords[2].addModifier("noperspective");
3675         vTexCoords[3].addModifier("noperspective");
3676     }
3677 
3678     aVertex.appendDecl(shaderCaps, &vshaderTxt);
3679     vshaderTxt.append(";");
3680     uTexCoordXform.appendDecl(shaderCaps, &vshaderTxt);
3681     vshaderTxt.append(";");
3682     for (int i = 0; i < numTaps; ++i) {
3683         vTexCoords[i].appendDecl(shaderCaps, &vshaderTxt);
3684         vshaderTxt.append(";");
3685     }
3686 
3687     vshaderTxt.append(
3688         "// Mipmap Program VS\n"
3689         "void main() {"
3690         "  sk_Position.xy = a_vertex * half2(2, 2) - half2(1, 1);"
3691         "  sk_Position.zw = half2(0, 1);"
3692     );
3693 
3694     // Insert texture coordinate computation:
3695     if (oddWidth && oddHeight) {
3696         vshaderTxt.append(
3697             "  v_texCoord0 = a_vertex.xy * u_texCoordXform.yw;"
3698             "  v_texCoord1 = a_vertex.xy * u_texCoordXform.yw + half2(u_texCoordXform.x, 0);"
3699             "  v_texCoord2 = a_vertex.xy * u_texCoordXform.yw + half2(0, u_texCoordXform.z);"
3700             "  v_texCoord3 = a_vertex.xy * u_texCoordXform.yw + u_texCoordXform.xz;"
3701         );
3702     } else if (oddWidth) {
3703         vshaderTxt.append(
3704             "  v_texCoord0 = a_vertex.xy * half2(u_texCoordXform.y, 1);"
3705             "  v_texCoord1 = a_vertex.xy * half2(u_texCoordXform.y, 1) + half2(u_texCoordXform.x, 0);"
3706         );
3707     } else if (oddHeight) {
3708         vshaderTxt.append(
3709             "  v_texCoord0 = a_vertex.xy * half2(1, u_texCoordXform.w);"
3710             "  v_texCoord1 = a_vertex.xy * half2(1, u_texCoordXform.w) + half2(0, u_texCoordXform.z);"
3711         );
3712     } else {
3713         vshaderTxt.append(
3714             "  v_texCoord0 = a_vertex.xy;"
3715         );
3716     }
3717 
3718     vshaderTxt.append("}");
3719 
3720     SkString fshaderTxt(version);
3721     if (shaderCaps->noperspectiveInterpolationSupport()) {
3722         if (const char* extension = shaderCaps->noperspectiveInterpolationExtensionString()) {
3723             fshaderTxt.appendf("#extension %s : require\n", extension);
3724         }
3725     }
3726     for (int i = 0; i < numTaps; ++i) {
3727         vTexCoords[i].setTypeModifier(GrShaderVar::kIn_TypeModifier);
3728         vTexCoords[i].appendDecl(shaderCaps, &fshaderTxt);
3729         fshaderTxt.append(";");
3730     }
3731     uTexture.appendDecl(shaderCaps, &fshaderTxt);
3732     fshaderTxt.append(";");
3733     fshaderTxt.append(
3734         "// Mipmap Program FS\n"
3735         "void main() {"
3736     );
3737 
3738     if (oddWidth && oddHeight) {
3739         fshaderTxt.append(
3740             "  sk_FragColor = (texture(u_texture, v_texCoord0) + "
3741             "                  texture(u_texture, v_texCoord1) + "
3742             "                  texture(u_texture, v_texCoord2) + "
3743             "                  texture(u_texture, v_texCoord3)) * 0.25;"
3744         );
3745     } else if (oddWidth || oddHeight) {
3746         fshaderTxt.append(
3747             "  sk_FragColor = (texture(u_texture, v_texCoord0) + "
3748             "                  texture(u_texture, v_texCoord1)) * 0.5;"
3749         );
3750     } else {
3751         fshaderTxt.append(
3752             "  sk_FragColor = texture(u_texture, v_texCoord0);"
3753         );
3754     }
3755 
3756     fshaderTxt.append("}");
3757 
3758     const char* str;
3759     GrGLint length;
3760 
3761     str = vshaderTxt.c_str();
3762     length = SkToInt(vshaderTxt.size());
3763     SkSL::Program::Settings settings;
3764     settings.fCaps = shaderCaps;
3765     SkSL::String glsl;
3766     std::unique_ptr<SkSL::Program> program = GrSkSLtoGLSL(*fGLContext, GR_GL_VERTEX_SHADER,
3767                                                           &str, &length, 1, settings, &glsl);
3768     GrGLuint vshader = GrGLCompileAndAttachShader(*fGLContext, fMipmapPrograms[progIdx].fProgram,
3769                                                   GR_GL_VERTEX_SHADER, glsl.c_str(), glsl.size(),
3770                                                   &fStats, settings);
3771     SkASSERT(program->fInputs.isEmpty());
3772 
3773     str = fshaderTxt.c_str();
3774     length = SkToInt(fshaderTxt.size());
3775     program = GrSkSLtoGLSL(*fGLContext, GR_GL_FRAGMENT_SHADER, &str, &length, 1, settings, &glsl);
3776     GrGLuint fshader = GrGLCompileAndAttachShader(*fGLContext, fMipmapPrograms[progIdx].fProgram,
3777                                                   GR_GL_FRAGMENT_SHADER, glsl.c_str(), glsl.size(),
3778                                                   &fStats, settings);
3779     SkASSERT(program->fInputs.isEmpty());
3780 
3781     GL_CALL(LinkProgram(fMipmapPrograms[progIdx].fProgram));
3782 
3783     GL_CALL_RET(fMipmapPrograms[progIdx].fTextureUniform,
3784                 GetUniformLocation(fMipmapPrograms[progIdx].fProgram, "u_texture"));
3785     GL_CALL_RET(fMipmapPrograms[progIdx].fTexCoordXformUniform,
3786                 GetUniformLocation(fMipmapPrograms[progIdx].fProgram, "u_texCoordXform"));
3787 
3788     GL_CALL(BindAttribLocation(fMipmapPrograms[progIdx].fProgram, 0, "a_vertex"));
3789 
3790     GL_CALL(DeleteShader(vshader));
3791     GL_CALL(DeleteShader(fshader));
3792 
3793     return true;
3794 }
3795 
createStencilClipClearProgram()3796 bool GrGLGpu::createStencilClipClearProgram() {
3797     TRACE_EVENT0("skia", TRACE_FUNC);
3798 
3799     if (!fStencilClipClearArrayBuffer) {
3800         static const GrGLfloat vdata[] = {-1, -1, 1, -1, -1, 1, 1, 1};
3801         fStencilClipClearArrayBuffer.reset(GrGLBuffer::Create(
3802                 this, sizeof(vdata), kVertex_GrBufferType, kStatic_GrAccessPattern, vdata));
3803         if (!fStencilClipClearArrayBuffer) {
3804             return false;
3805         }
3806     }
3807 
3808     SkASSERT(!fStencilClipClearProgram);
3809     GL_CALL_RET(fStencilClipClearProgram, CreateProgram());
3810     if (!fStencilClipClearProgram) {
3811         return false;
3812     }
3813 
3814     GrShaderVar aVertex("a_vertex", kHalf2_GrSLType, GrShaderVar::kIn_TypeModifier);
3815     const char* version = this->caps()->shaderCaps()->versionDeclString();
3816 
3817     SkString vshaderTxt(version);
3818     aVertex.appendDecl(this->caps()->shaderCaps(), &vshaderTxt);
3819     vshaderTxt.append(";");
3820     vshaderTxt.append(
3821             "// Stencil Clip Clear Program VS\n"
3822             "void main() {"
3823             "  sk_Position = float4(a_vertex.x, a_vertex.y, 0, 1);"
3824             "}");
3825 
3826     SkString fshaderTxt(version);
3827     fshaderTxt.appendf(
3828             "// Stencil Clip Clear Program FS\n"
3829             "void main() {"
3830             "  sk_FragColor = half4(0);"
3831             "}");
3832 
3833     const char* str;
3834     GrGLint length;
3835 
3836     str = vshaderTxt.c_str();
3837     length = SkToInt(vshaderTxt.size());
3838     SkSL::Program::Settings settings;
3839     settings.fCaps = this->caps()->shaderCaps();
3840     SkSL::String glsl;
3841     std::unique_ptr<SkSL::Program> program = GrSkSLtoGLSL(*fGLContext, GR_GL_VERTEX_SHADER,
3842                                                           &str, &length, 1, settings, &glsl);
3843     GrGLuint vshader = GrGLCompileAndAttachShader(*fGLContext, fStencilClipClearProgram,
3844                                                   GR_GL_VERTEX_SHADER, glsl.c_str(), glsl.size(),
3845                                                   &fStats, settings);
3846     SkASSERT(program->fInputs.isEmpty());
3847 
3848     str = fshaderTxt.c_str();
3849     length = SkToInt(fshaderTxt.size());
3850     program = GrSkSLtoGLSL(*fGLContext, GR_GL_FRAGMENT_SHADER, &str, &length, 1, settings, &glsl);
3851     GrGLuint fshader = GrGLCompileAndAttachShader(*fGLContext, fStencilClipClearProgram,
3852                                                   GR_GL_FRAGMENT_SHADER, glsl.c_str(), glsl.size(),
3853                                                   &fStats, settings);
3854     SkASSERT(program->fInputs.isEmpty());
3855 
3856     GL_CALL(LinkProgram(fStencilClipClearProgram));
3857 
3858     GL_CALL(BindAttribLocation(fStencilClipClearProgram, 0, "a_vertex"));
3859 
3860     GL_CALL(DeleteShader(vshader));
3861     GL_CALL(DeleteShader(fshader));
3862 
3863     return true;
3864 }
3865 
clearStencilClipAsDraw(const GrFixedClip & clip,bool insideStencilMask,GrRenderTarget * rt,GrSurfaceOrigin origin)3866 void GrGLGpu::clearStencilClipAsDraw(const GrFixedClip& clip, bool insideStencilMask,
3867                                      GrRenderTarget* rt, GrSurfaceOrigin origin) {
3868     // TODO: This should swizzle the output to match dst's config, though it is a debugging
3869     // visualization.
3870 
3871     this->handleDirtyContext();
3872     if (!fStencilClipClearProgram) {
3873         if (!this->createStencilClipClearProgram()) {
3874             SkDebugf("Failed to create stencil clip clear program.\n");
3875             return;
3876         }
3877     }
3878 
3879     GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(rt->asRenderTarget());
3880     this->flushRenderTarget(glRT, nullptr);
3881 
3882     GL_CALL(UseProgram(fStencilClipClearProgram));
3883     fHWProgramID = fStencilClipClearProgram;
3884 
3885     fHWVertexArrayState.setVertexArrayID(this, 0);
3886 
3887     GrGLAttribArrayState* attribs = fHWVertexArrayState.bindInternalVertexArray(this);
3888     attribs->enableVertexArrays(this, 1);
3889     attribs->set(this, 0, fStencilClipClearArrayBuffer.get(), kHalf2_GrVertexAttribType,
3890                  2 * sizeof(GrGLfloat), 0);
3891 
3892     GrXferProcessor::BlendInfo blendInfo;
3893     blendInfo.reset();
3894     this->flushBlend(blendInfo, GrSwizzle::RGBA());
3895     this->flushColorWrite(false);
3896     this->flushHWAAState(glRT, false, false);
3897     this->flushScissor(clip.scissorState(), glRT->getViewport(), origin);
3898     this->flushWindowRectangles(clip.windowRectsState(), glRT, origin);
3899     GrStencilAttachment* sb = rt->renderTargetPriv().getStencilAttachment();
3900     // This should only be called internally when we know we have a stencil buffer.
3901     SkASSERT(sb);
3902     GrStencilSettings settings = GrStencilSettings(
3903             *GrStencilSettings::SetClipBitSettings(insideStencilMask), false, sb->bits());
3904     this->flushStencil(settings);
3905     GL_CALL(DrawArrays(GR_GL_TRIANGLE_STRIP, 0, 4));
3906 }
3907 
createClearColorProgram()3908 bool GrGLGpu::createClearColorProgram() {
3909     TRACE_EVENT0("skia", TRACE_FUNC);
3910 
3911     if (!fClearProgramArrayBuffer) {
3912         static const GrGLfloat vdata[] = {-1, -1, 1, -1, -1, 1, 1, 1};
3913         fClearProgramArrayBuffer.reset(GrGLBuffer::Create(this, sizeof(vdata), kVertex_GrBufferType,
3914                                                           kStatic_GrAccessPattern, vdata));
3915         if (!fClearProgramArrayBuffer) {
3916             return false;
3917         }
3918     }
3919 
3920     SkASSERT(!fClearColorProgram.fProgram);
3921     GL_CALL_RET(fClearColorProgram.fProgram, CreateProgram());
3922     if (!fClearColorProgram.fProgram) {
3923         return false;
3924     }
3925 
3926     GrShaderVar aVertex("a_vertex", kHalf2_GrSLType, GrShaderVar::kIn_TypeModifier);
3927     const char* version = this->caps()->shaderCaps()->versionDeclString();
3928 
3929     SkString vshaderTxt(version);
3930     aVertex.appendDecl(this->caps()->shaderCaps(), &vshaderTxt);
3931     vshaderTxt.append(";");
3932     vshaderTxt.append(R"(
3933             // Clear Color Program VS
3934             void main() {
3935                 sk_Position = float4(a_vertex.x, a_vertex.y, 0, 1);
3936             })");
3937 
3938     GrShaderVar uColor("u_color", kHalf4_GrSLType, GrShaderVar::kUniform_TypeModifier);
3939     SkString fshaderTxt(version);
3940     uColor.appendDecl(this->caps()->shaderCaps(), &fshaderTxt);
3941     fshaderTxt.append(";");
3942     fshaderTxt.appendf(R"(
3943             // Clear Color Program FS
3944             void main() {
3945               sk_FragColor = u_color;
3946             })");
3947 
3948     const char* str;
3949     GrGLint length;
3950 
3951     str = vshaderTxt.c_str();
3952     length = SkToInt(vshaderTxt.size());
3953     SkSL::Program::Settings settings;
3954     settings.fCaps = this->caps()->shaderCaps();
3955     SkSL::String glsl;
3956     GrSkSLtoGLSL(*fGLContext, GR_GL_VERTEX_SHADER, &str, &length, 1, settings, &glsl);
3957     GrGLuint vshader = GrGLCompileAndAttachShader(*fGLContext, fClearColorProgram.fProgram,
3958                                                   GR_GL_VERTEX_SHADER, glsl.c_str(), glsl.size(),
3959                                                   &fStats, settings);
3960 
3961     str = fshaderTxt.c_str();
3962     length = SkToInt(fshaderTxt.size());
3963     GrSkSLtoGLSL(*fGLContext, GR_GL_FRAGMENT_SHADER, &str, &length, 1, settings, &glsl);
3964     GrGLuint fshader = GrGLCompileAndAttachShader(*fGLContext, fClearColorProgram.fProgram,
3965                                                   GR_GL_FRAGMENT_SHADER, glsl.c_str(), glsl.size(),
3966                                                   &fStats, settings);
3967 
3968     GL_CALL(LinkProgram(fClearColorProgram.fProgram));
3969 
3970     GL_CALL(BindAttribLocation(fClearColorProgram.fProgram, 0, "a_vertex"));
3971 
3972     GL_CALL_RET(fClearColorProgram.fColorUniform,
3973                 GetUniformLocation(fClearColorProgram.fProgram, "u_color"));
3974 
3975     GL_CALL(DeleteShader(vshader));
3976     GL_CALL(DeleteShader(fshader));
3977 
3978     return true;
3979 }
3980 
clearColorAsDraw(const GrFixedClip & clip,GrGLfloat r,GrGLfloat g,GrGLfloat b,GrGLfloat a,GrRenderTarget * dst,GrSurfaceOrigin origin)3981 void GrGLGpu::clearColorAsDraw(const GrFixedClip& clip, GrGLfloat r, GrGLfloat g, GrGLfloat b,
3982                                GrGLfloat a, GrRenderTarget* dst, GrSurfaceOrigin origin) {
3983     if (!fClearColorProgram.fProgram) {
3984         if (!this->createClearColorProgram()) {
3985             SkDebugf("Failed to create clear color program.\n");
3986             return;
3987         }
3988     }
3989 
3990     GrGLIRect dstVP;
3991     this->bindSurfaceFBOForPixelOps(dst, GR_GL_FRAMEBUFFER, &dstVP, kDst_TempFBOTarget);
3992     this->flushViewport(dstVP);
3993     fHWBoundRenderTargetUniqueID.makeInvalid();
3994 
3995     GL_CALL(UseProgram(fClearColorProgram.fProgram));
3996     fHWProgramID = fClearColorProgram.fProgram;
3997 
3998     fHWVertexArrayState.setVertexArrayID(this, 0);
3999 
4000     GrGLAttribArrayState* attribs = fHWVertexArrayState.bindInternalVertexArray(this);
4001     attribs->enableVertexArrays(this, 1);
4002     attribs->set(this, 0, fClearProgramArrayBuffer.get(), kHalf2_GrVertexAttribType,
4003                  2 * sizeof(GrGLfloat), 0);
4004 
4005     GrGLRenderTarget* glrt = static_cast<GrGLRenderTarget*>(dst);
4006     this->flushScissor(clip.scissorState(), glrt->getViewport(), origin);
4007     this->flushWindowRectangles(clip.windowRectsState(), glrt, origin);
4008 
4009     GL_CALL(Uniform4f(fClearColorProgram.fColorUniform, r, g, b, a));
4010 
4011     GrXferProcessor::BlendInfo blendInfo;
4012     blendInfo.reset();
4013     this->flushBlend(blendInfo, GrSwizzle::RGBA());
4014     this->flushColorWrite(true);
4015     this->flushHWAAState(nullptr, false, false);
4016     this->disableStencil();
4017     if (this->glCaps().srgbWriteControl()) {
4018         this->flushFramebufferSRGB(true);
4019     }
4020 
4021     GL_CALL(DrawArrays(GR_GL_TRIANGLE_STRIP, 0, 4));
4022     this->unbindTextureFBOForPixelOps(GR_GL_FRAMEBUFFER, dst);
4023     this->didWriteToSurface(dst, clip.scissorEnabled() ? &clip.scissorRect() : nullptr);
4024 }
4025 
copySurfaceAsDraw(GrSurface * dst,GrSurfaceOrigin dstOrigin,GrSurface * src,GrSurfaceOrigin srcOrigin,const SkIRect & srcRect,const SkIPoint & dstPoint)4026 bool GrGLGpu::copySurfaceAsDraw(GrSurface* dst, GrSurfaceOrigin dstOrigin,
4027                                 GrSurface* src, GrSurfaceOrigin srcOrigin,
4028                                 const SkIRect& srcRect,
4029                                 const SkIPoint& dstPoint) {
4030     GrGLTexture* srcTex = static_cast<GrGLTexture*>(src->asTexture());
4031     int progIdx = TextureToCopyProgramIdx(srcTex);
4032 
4033     if (!fCopyPrograms[progIdx].fProgram) {
4034         if (!this->createCopyProgram(srcTex)) {
4035             SkDebugf("Failed to create copy program.\n");
4036             return false;
4037         }
4038     }
4039 
4040     int w = srcRect.width();
4041     int h = srcRect.height();
4042 
4043     this->bindTexture(0, GrSamplerState::ClampNearest(), true, srcTex, srcOrigin);
4044 
4045     GrGLIRect dstVP;
4046     this->bindSurfaceFBOForPixelOps(dst, GR_GL_FRAMEBUFFER, &dstVP, kDst_TempFBOTarget);
4047     this->flushViewport(dstVP);
4048     fHWBoundRenderTargetUniqueID.makeInvalid();
4049 
4050     SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY, w, h);
4051 
4052     GL_CALL(UseProgram(fCopyPrograms[progIdx].fProgram));
4053     fHWProgramID = fCopyPrograms[progIdx].fProgram;
4054 
4055     fHWVertexArrayState.setVertexArrayID(this, 0);
4056 
4057     GrGLAttribArrayState* attribs = fHWVertexArrayState.bindInternalVertexArray(this);
4058     attribs->enableVertexArrays(this, 1);
4059     attribs->set(this, 0, fCopyProgramArrayBuffer.get(), kHalf2_GrVertexAttribType,
4060                  2 * sizeof(GrGLfloat), 0);
4061 
4062     // dst rect edges in NDC (-1 to 1)
4063     int dw = dst->width();
4064     int dh = dst->height();
4065     GrGLfloat dx0 = 2.f * dstPoint.fX / dw - 1.f;
4066     GrGLfloat dx1 = 2.f * (dstPoint.fX + w) / dw - 1.f;
4067     GrGLfloat dy0 = 2.f * dstPoint.fY / dh - 1.f;
4068     GrGLfloat dy1 = 2.f * (dstPoint.fY + h) / dh - 1.f;
4069     if (kBottomLeft_GrSurfaceOrigin == dstOrigin) {
4070         dy0 = -dy0;
4071         dy1 = -dy1;
4072     }
4073 
4074     GrGLfloat sx0 = (GrGLfloat)srcRect.fLeft;
4075     GrGLfloat sx1 = (GrGLfloat)(srcRect.fLeft + w);
4076     GrGLfloat sy0 = (GrGLfloat)srcRect.fTop;
4077     GrGLfloat sy1 = (GrGLfloat)(srcRect.fTop + h);
4078     int sw = src->width();
4079     int sh = src->height();
4080     if (kBottomLeft_GrSurfaceOrigin == srcOrigin) {
4081         sy0 = sh - sy0;
4082         sy1 = sh - sy1;
4083     }
4084     // src rect edges in normalized texture space (0 to 1)
4085     sx0 /= sw;
4086     sx1 /= sw;
4087     sy0 /= sh;
4088     sy1 /= sh;
4089 
4090     GL_CALL(Uniform4f(fCopyPrograms[progIdx].fPosXformUniform, dx1 - dx0, dy1 - dy0, dx0, dy0));
4091     GL_CALL(Uniform4f(fCopyPrograms[progIdx].fTexCoordXformUniform,
4092                       sx1 - sx0, sy1 - sy0, sx0, sy0));
4093     GL_CALL(Uniform1i(fCopyPrograms[progIdx].fTextureUniform, 0));
4094 
4095     GrXferProcessor::BlendInfo blendInfo;
4096     blendInfo.reset();
4097     this->flushBlend(blendInfo, GrSwizzle::RGBA());
4098     this->flushColorWrite(true);
4099     this->flushHWAAState(nullptr, false, false);
4100     this->disableScissor();
4101     this->disableWindowRectangles();
4102     this->disableStencil();
4103     if (this->glCaps().srgbWriteControl()) {
4104         this->flushFramebufferSRGB(true);
4105     }
4106 
4107     GL_CALL(DrawArrays(GR_GL_TRIANGLE_STRIP, 0, 4));
4108     this->unbindTextureFBOForPixelOps(GR_GL_FRAMEBUFFER, dst);
4109     this->didWriteToSurface(dst, &dstRect);
4110 
4111     return true;
4112 }
4113 
copySurfaceAsCopyTexSubImage(GrSurface * dst,GrSurfaceOrigin dstOrigin,GrSurface * src,GrSurfaceOrigin srcOrigin,const SkIRect & srcRect,const SkIPoint & dstPoint)4114 void GrGLGpu::copySurfaceAsCopyTexSubImage(GrSurface* dst, GrSurfaceOrigin dstOrigin,
4115                                            GrSurface* src, GrSurfaceOrigin srcOrigin,
4116                                            const SkIRect& srcRect,
4117                                            const SkIPoint& dstPoint) {
4118     SkASSERT(can_copy_texsubimage(dst, dstOrigin, src, srcOrigin, this));
4119     GrGLIRect srcVP;
4120     this->bindSurfaceFBOForPixelOps(src, GR_GL_FRAMEBUFFER, &srcVP, kSrc_TempFBOTarget);
4121     GrGLTexture* dstTex = static_cast<GrGLTexture *>(dst->asTexture());
4122     SkASSERT(dstTex);
4123     // We modified the bound FBO
4124     fHWBoundRenderTargetUniqueID.makeInvalid();
4125     GrGLIRect srcGLRect;
4126     srcGLRect.setRelativeTo(srcVP, srcRect, srcOrigin);
4127 
4128     this->setScratchTextureUnit();
4129     GL_CALL(BindTexture(dstTex->target(), dstTex->textureID()));
4130     GrGLint dstY;
4131     if (kBottomLeft_GrSurfaceOrigin == dstOrigin) {
4132         dstY = dst->height() - (dstPoint.fY + srcGLRect.fHeight);
4133     } else {
4134         dstY = dstPoint.fY;
4135     }
4136     GL_CALL(CopyTexSubImage2D(dstTex->target(), 0,
4137                               dstPoint.fX, dstY,
4138                               srcGLRect.fLeft, srcGLRect.fBottom,
4139                               srcGLRect.fWidth, srcGLRect.fHeight));
4140     this->unbindTextureFBOForPixelOps(GR_GL_FRAMEBUFFER, src);
4141     SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY,
4142                                         srcRect.width(), srcRect.height());
4143     this->didWriteToSurface(dst, &dstRect);
4144 }
4145 
copySurfaceAsBlitFramebuffer(GrSurface * dst,GrSurfaceOrigin dstOrigin,GrSurface * src,GrSurfaceOrigin srcOrigin,const SkIRect & srcRect,const SkIPoint & dstPoint)4146 bool GrGLGpu::copySurfaceAsBlitFramebuffer(GrSurface* dst, GrSurfaceOrigin dstOrigin,
4147                                            GrSurface* src, GrSurfaceOrigin srcOrigin,
4148                                            const SkIRect& srcRect,
4149                                            const SkIPoint& dstPoint) {
4150     SkASSERT(can_blit_framebuffer_for_copy_surface(dst, dstOrigin, src, srcOrigin,
4151                                                    srcRect, dstPoint, this));
4152     SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY,
4153                                         srcRect.width(), srcRect.height());
4154     if (dst == src) {
4155         if (SkIRect::IntersectsNoEmptyCheck(dstRect, srcRect)) {
4156             return false;
4157         }
4158     }
4159 
4160     GrGLIRect dstVP;
4161     GrGLIRect srcVP;
4162     this->bindSurfaceFBOForPixelOps(dst, GR_GL_DRAW_FRAMEBUFFER, &dstVP, kDst_TempFBOTarget);
4163     this->bindSurfaceFBOForPixelOps(src, GR_GL_READ_FRAMEBUFFER, &srcVP, kSrc_TempFBOTarget);
4164     // We modified the bound FBO
4165     fHWBoundRenderTargetUniqueID.makeInvalid();
4166     GrGLIRect srcGLRect;
4167     GrGLIRect dstGLRect;
4168     srcGLRect.setRelativeTo(srcVP, srcRect, srcOrigin);
4169     dstGLRect.setRelativeTo(dstVP, dstRect, dstOrigin);
4170 
4171     // BlitFrameBuffer respects the scissor, so disable it.
4172     this->disableScissor();
4173     this->disableWindowRectangles();
4174 
4175     GrGLint srcY0;
4176     GrGLint srcY1;
4177     // Does the blit need to y-mirror or not?
4178     if (srcOrigin == dstOrigin) {
4179         srcY0 = srcGLRect.fBottom;
4180         srcY1 = srcGLRect.fBottom + srcGLRect.fHeight;
4181     } else {
4182         srcY0 = srcGLRect.fBottom + srcGLRect.fHeight;
4183         srcY1 = srcGLRect.fBottom;
4184     }
4185     GL_CALL(BlitFramebuffer(srcGLRect.fLeft,
4186                             srcY0,
4187                             srcGLRect.fLeft + srcGLRect.fWidth,
4188                             srcY1,
4189                             dstGLRect.fLeft,
4190                             dstGLRect.fBottom,
4191                             dstGLRect.fLeft + dstGLRect.fWidth,
4192                             dstGLRect.fBottom + dstGLRect.fHeight,
4193                             GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST));
4194     this->unbindTextureFBOForPixelOps(GR_GL_DRAW_FRAMEBUFFER, dst);
4195     this->unbindTextureFBOForPixelOps(GR_GL_READ_FRAMEBUFFER, src);
4196     this->didWriteToSurface(dst, &dstRect);
4197     return true;
4198 }
4199 
4200 // Manual implementation of mipmap generation, to work around driver bugs w/sRGB.
4201 // Uses draw calls to do a series of downsample operations to successive mips.
4202 // If this returns false, then the calling code falls back to using glGenerateMipmap.
generateMipmap(GrGLTexture * texture,GrSurfaceOrigin textureOrigin,bool gammaCorrect)4203 bool GrGLGpu::generateMipmap(GrGLTexture* texture, GrSurfaceOrigin textureOrigin,
4204                              bool gammaCorrect) {
4205     SkASSERT(!GrPixelConfigIsSint(texture->config()));
4206     // Our iterative downsample requires the ability to limit which level we're sampling:
4207     if (!this->glCaps().doManualMipmapping()) {
4208         return false;
4209     }
4210 
4211     // Mipmaps are only supported on 2D textures:
4212     if (GR_GL_TEXTURE_2D != texture->target()) {
4213         return false;
4214     }
4215 
4216     // We need to be able to render to the texture for this to work:
4217     if (!this->glCaps().canConfigBeFBOColorAttachment(texture->config())) {
4218         return false;
4219     }
4220 
4221     // If we're mipping an sRGB texture, we need to ensure FB sRGB is correct:
4222     if (GrPixelConfigIsSRGB(texture->config())) {
4223         // If we have write-control, just set the state that we want:
4224         if (this->glCaps().srgbWriteControl()) {
4225             this->flushFramebufferSRGB(gammaCorrect);
4226         } else if (!gammaCorrect) {
4227             // If we don't have write-control we can't do non-gamma-correct mipmapping:
4228             return false;
4229         }
4230     }
4231 
4232     int width = texture->width();
4233     int height = texture->height();
4234     int levelCount = SkMipMap::ComputeLevelCount(width, height) + 1;
4235 
4236     // Define all mips, if we haven't previously done so:
4237     if (0 == texture->texturePriv().maxMipMapLevel()) {
4238         GrGLenum internalFormat;
4239         GrGLenum externalFormat;
4240         GrGLenum externalType;
4241         if (!this->glCaps().getTexImageFormats(texture->config(), texture->config(),
4242                                                &internalFormat, &externalFormat, &externalType)) {
4243             return false;
4244         }
4245 
4246         this->unbindCpuToGpuXferBuffer();
4247 
4248         for (GrGLint level = 1; level < levelCount; ++level) {
4249             // Define the next mip:
4250             width = SkTMax(1, width / 2);
4251             height = SkTMax(1, height / 2);
4252             GL_ALLOC_CALL(this->glInterface(), TexImage2D(GR_GL_TEXTURE_2D, level, internalFormat,
4253                                                           width, height, 0,
4254                                                           externalFormat, externalType, nullptr));
4255         }
4256     }
4257 
4258     // Create (if necessary), then bind temporary FBO:
4259     if (0 == fTempDstFBOID) {
4260         GL_CALL(GenFramebuffers(1, &fTempDstFBOID));
4261     }
4262     GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, fTempDstFBOID));
4263     fHWBoundRenderTargetUniqueID.makeInvalid();
4264 
4265     // Bind the texture, to get things configured for filtering.
4266     // We'll be changing our base level further below:
4267     this->setTextureUnit(0);
4268     this->bindTexture(0, GrSamplerState::ClampBilerp(), gammaCorrect, texture, textureOrigin);
4269 
4270     // Vertex data:
4271     if (!fMipmapProgramArrayBuffer) {
4272         static const GrGLfloat vdata[] = {
4273             0, 0,
4274             0, 1,
4275             1, 0,
4276             1, 1
4277         };
4278         fMipmapProgramArrayBuffer.reset(GrGLBuffer::Create(this, sizeof(vdata),
4279                                                            kVertex_GrBufferType,
4280                                                            kStatic_GrAccessPattern, vdata));
4281     }
4282     if (!fMipmapProgramArrayBuffer) {
4283         return false;
4284     }
4285 
4286     fHWVertexArrayState.setVertexArrayID(this, 0);
4287 
4288     GrGLAttribArrayState* attribs = fHWVertexArrayState.bindInternalVertexArray(this);
4289     attribs->enableVertexArrays(this, 1);
4290     attribs->set(this, 0, fMipmapProgramArrayBuffer.get(), kHalf2_GrVertexAttribType,
4291                  2 * sizeof(GrGLfloat), 0);
4292 
4293     // Set "simple" state once:
4294     GrXferProcessor::BlendInfo blendInfo;
4295     blendInfo.reset();
4296     this->flushBlend(blendInfo, GrSwizzle::RGBA());
4297     this->flushColorWrite(true);
4298     this->flushHWAAState(nullptr, false, false);
4299     this->disableScissor();
4300     this->disableWindowRectangles();
4301     this->disableStencil();
4302 
4303     // Do all the blits:
4304     width = texture->width();
4305     height = texture->height();
4306     GrGLIRect viewport;
4307     viewport.fLeft = 0;
4308     viewport.fBottom = 0;
4309     for (GrGLint level = 1; level < levelCount; ++level) {
4310         // Get and bind the program for this particular downsample (filter shape can vary):
4311         int progIdx = TextureSizeToMipmapProgramIdx(width, height);
4312         if (!fMipmapPrograms[progIdx].fProgram) {
4313             if (!this->createMipmapProgram(progIdx)) {
4314                 SkDebugf("Failed to create mipmap program.\n");
4315                 return false;
4316             }
4317         }
4318         GL_CALL(UseProgram(fMipmapPrograms[progIdx].fProgram));
4319         fHWProgramID = fMipmapPrograms[progIdx].fProgram;
4320 
4321         // Texcoord uniform is expected to contain (1/w, (w-1)/w, 1/h, (h-1)/h)
4322         const float invWidth = 1.0f / width;
4323         const float invHeight = 1.0f / height;
4324         GL_CALL(Uniform4f(fMipmapPrograms[progIdx].fTexCoordXformUniform,
4325                           invWidth, (width - 1) * invWidth, invHeight, (height - 1) * invHeight));
4326         GL_CALL(Uniform1i(fMipmapPrograms[progIdx].fTextureUniform, 0));
4327 
4328         // Only sample from previous mip
4329         GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_BASE_LEVEL, level - 1));
4330 
4331         GL_CALL(FramebufferTexture2D(GR_GL_FRAMEBUFFER, GR_GL_COLOR_ATTACHMENT0,
4332                                      GR_GL_TEXTURE_2D, texture->textureID(), level));
4333 
4334         width = SkTMax(1, width / 2);
4335         height = SkTMax(1, height / 2);
4336         viewport.fWidth = width;
4337         viewport.fHeight = height;
4338         this->flushViewport(viewport);
4339 
4340         GL_CALL(DrawArrays(GR_GL_TRIANGLE_STRIP, 0, 4));
4341     }
4342 
4343     // Unbind:
4344     GL_CALL(FramebufferTexture2D(GR_GL_FRAMEBUFFER, GR_GL_COLOR_ATTACHMENT0,
4345                                  GR_GL_TEXTURE_2D, 0, 0));
4346 
4347     return true;
4348 }
4349 
onQueryMultisampleSpecs(GrRenderTarget * rt,GrSurfaceOrigin rtOrigin,const GrStencilSettings & stencil,int * effectiveSampleCnt,SamplePattern * samplePattern)4350 void GrGLGpu::onQueryMultisampleSpecs(GrRenderTarget* rt, GrSurfaceOrigin rtOrigin,
4351                                       const GrStencilSettings& stencil,
4352                                       int* effectiveSampleCnt, SamplePattern* samplePattern) {
4353     SkASSERT(GrFSAAType::kMixedSamples != rt->fsaaType() ||
4354              rt->renderTargetPriv().getStencilAttachment() || stencil.isDisabled());
4355 
4356     this->flushStencil(stencil);
4357     this->flushHWAAState(rt, true, !stencil.isDisabled());
4358     this->flushRenderTarget(static_cast<GrGLRenderTarget*>(rt), &SkIRect::EmptyIRect());
4359 
4360     if (0 != this->caps()->maxRasterSamples()) {
4361         GR_GL_GetIntegerv(this->glInterface(), GR_GL_EFFECTIVE_RASTER_SAMPLES, effectiveSampleCnt);
4362     } else {
4363         GR_GL_GetIntegerv(this->glInterface(), GR_GL_SAMPLES, effectiveSampleCnt);
4364     }
4365 
4366     SkASSERT(*effectiveSampleCnt >= rt->numStencilSamples());
4367 
4368     if (this->caps()->sampleLocationsSupport()) {
4369         samplePattern->reset(*effectiveSampleCnt);
4370         for (int i = 0; i < *effectiveSampleCnt; ++i) {
4371             GrGLfloat pos[2];
4372             GL_CALL(GetMultisamplefv(GR_GL_SAMPLE_POSITION, i, pos));
4373             if (kTopLeft_GrSurfaceOrigin == rtOrigin) {
4374                 (*samplePattern)[i].set(pos[0], pos[1]);
4375             } else {
4376                 (*samplePattern)[i].set(pos[0], 1 - pos[1]);
4377             }
4378         }
4379     }
4380 }
4381 
xferBarrier(GrRenderTarget * rt,GrXferBarrierType type)4382 void GrGLGpu::xferBarrier(GrRenderTarget* rt, GrXferBarrierType type) {
4383     SkASSERT(type);
4384     switch (type) {
4385         case kTexture_GrXferBarrierType: {
4386             GrGLRenderTarget* glrt = static_cast<GrGLRenderTarget*>(rt);
4387             SkASSERT(glrt->textureFBOID() != 0 && glrt->renderFBOID() != 0);
4388             if (glrt->textureFBOID() != glrt->renderFBOID()) {
4389                 // The render target uses separate storage so no need for glTextureBarrier.
4390                 // FIXME: The render target will resolve automatically when its texture is bound,
4391                 // but we could resolve only the bounds that will be read if we do it here instead.
4392                 return;
4393             }
4394             SkASSERT(this->caps()->textureBarrierSupport());
4395             GL_CALL(TextureBarrier());
4396             return;
4397         }
4398         case kBlend_GrXferBarrierType:
4399             SkASSERT(GrCaps::kAdvanced_BlendEquationSupport ==
4400                      this->caps()->blendEquationSupport());
4401             GL_CALL(BlendBarrier());
4402             return;
4403         default: break; // placate compiler warnings that kNone not handled
4404     }
4405 }
4406 
createTestingOnlyBackendTexture(void * pixels,int w,int h,GrPixelConfig config,bool,GrMipMapped mipMapped)4407 GrBackendTexture GrGLGpu::createTestingOnlyBackendTexture(void* pixels, int w, int h,
4408                                                           GrPixelConfig config, bool /*isRT*/,
4409                                                           GrMipMapped mipMapped) {
4410     if (!this->caps()->isConfigTexturable(config)) {
4411         return GrBackendTexture();  // invalid
4412     }
4413 
4414     // Currently we don't support uploading pixel data when mipped.
4415     if (pixels && GrMipMapped::kYes == mipMapped) {
4416         return GrBackendTexture();  // invalid
4417     }
4418 
4419     GrGLTextureInfo info;
4420     info.fTarget = GR_GL_TEXTURE_2D;
4421     info.fID = 0;
4422     GL_CALL(GenTextures(1, &info.fID));
4423     GL_CALL(ActiveTexture(GR_GL_TEXTURE0));
4424     GL_CALL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, 1));
4425     GL_CALL(BindTexture(info.fTarget, info.fID));
4426     fHWBoundTextureUniqueIDs[0].makeInvalid();
4427     GL_CALL(TexParameteri(info.fTarget, GR_GL_TEXTURE_MAG_FILTER, GR_GL_NEAREST));
4428     GL_CALL(TexParameteri(info.fTarget, GR_GL_TEXTURE_MIN_FILTER, GR_GL_NEAREST));
4429     GL_CALL(TexParameteri(info.fTarget, GR_GL_TEXTURE_WRAP_S, GR_GL_CLAMP_TO_EDGE));
4430     GL_CALL(TexParameteri(info.fTarget, GR_GL_TEXTURE_WRAP_T, GR_GL_CLAMP_TO_EDGE));
4431 
4432     GrGLenum internalFormat;
4433     GrGLenum externalFormat;
4434     GrGLenum externalType;
4435 
4436     if (!this->glCaps().getTexImageFormats(config, config, &internalFormat, &externalFormat,
4437                                            &externalType)) {
4438         return GrBackendTexture();  // invalid
4439     }
4440 
4441     info.fFormat = this->glCaps().configSizedInternalFormat(config);
4442 
4443     this->unbindCpuToGpuXferBuffer();
4444 
4445     // Figure out the number of mip levels.
4446     int mipLevels = 1;
4447     if (GrMipMapped::kYes == mipMapped) {
4448         mipLevels = SkMipMap::ComputeLevelCount(w, h) + 1;
4449     }
4450 
4451     size_t bpp = GrBytesPerPixel(config);
4452     size_t baseLayerSize = bpp * w * h;
4453     SkAutoMalloc defaultStorage(baseLayerSize);
4454     if (!pixels) {
4455         // Fill in the texture with all zeros so we don't have random garbage
4456         pixels = defaultStorage.get();
4457         memset(pixels, 0, baseLayerSize);
4458     }
4459 
4460     int width = w;
4461     int height = h;
4462     for (int i = 0; i < mipLevels; ++i) {
4463         GL_CALL(TexImage2D(info.fTarget, i, internalFormat, width, height, 0, externalFormat,
4464                            externalType, pixels));
4465         width = SkTMax(1, width / 2);
4466         height = SkTMax(1, height / 2);
4467     }
4468 
4469     return GrBackendTexture(w, h, mipMapped, info);
4470 }
4471 
isTestingOnlyBackendTexture(const GrBackendTexture & tex) const4472 bool GrGLGpu::isTestingOnlyBackendTexture(const GrBackendTexture& tex) const {
4473     SkASSERT(kOpenGL_GrBackend == tex.backend());
4474 
4475     const GrGLTextureInfo* info = tex.getGLTextureInfo();
4476     if (!info) {
4477         return false;
4478     }
4479 
4480     GrGLboolean result;
4481     GL_CALL_RET(result, IsTexture(info->fID));
4482 
4483     return (GR_GL_TRUE == result);
4484 }
4485 
deleteTestingOnlyBackendTexture(GrBackendTexture * tex,bool abandonTexture)4486 void GrGLGpu::deleteTestingOnlyBackendTexture(GrBackendTexture* tex, bool abandonTexture) {
4487     SkASSERT(kOpenGL_GrBackend == tex->backend());
4488 
4489     const GrGLTextureInfo* info = tex->getGLTextureInfo();
4490     if (info && !abandonTexture) {
4491         GrGLuint texID = info->fID;
4492 
4493         GL_CALL(DeleteTextures(1, &texID));
4494     }
4495 }
4496 
resetShaderCacheForTesting() const4497 void GrGLGpu::resetShaderCacheForTesting() const {
4498     fProgramCache->abandon();
4499 }
4500 
testingOnly_flushGpuAndSync()4501 void GrGLGpu::testingOnly_flushGpuAndSync() {
4502     GL_CALL(Finish());
4503 }
4504 
4505 ///////////////////////////////////////////////////////////////////////////////
4506 
bindInternalVertexArray(GrGLGpu * gpu,const GrBuffer * ibuf)4507 GrGLAttribArrayState* GrGLGpu::HWVertexArrayState::bindInternalVertexArray(GrGLGpu* gpu,
4508                                                                            const GrBuffer* ibuf) {
4509     GrGLAttribArrayState* attribState;
4510 
4511     if (gpu->glCaps().isCoreProfile()) {
4512         if (!fCoreProfileVertexArray) {
4513             GrGLuint arrayID;
4514             GR_GL_CALL(gpu->glInterface(), GenVertexArrays(1, &arrayID));
4515             int attrCount = gpu->glCaps().maxVertexAttributes();
4516             fCoreProfileVertexArray = new GrGLVertexArray(arrayID, attrCount);
4517         }
4518         if (ibuf) {
4519             attribState = fCoreProfileVertexArray->bindWithIndexBuffer(gpu, ibuf);
4520         } else {
4521             attribState = fCoreProfileVertexArray->bind(gpu);
4522         }
4523     } else {
4524         if (ibuf) {
4525             // bindBuffer implicitly binds VAO 0 when binding an index buffer.
4526             gpu->bindBuffer(kIndex_GrBufferType, ibuf);
4527         } else {
4528             this->setVertexArrayID(gpu, 0);
4529         }
4530         int attrCount = gpu->glCaps().maxVertexAttributes();
4531         if (fDefaultVertexArrayAttribState.count() != attrCount) {
4532             fDefaultVertexArrayAttribState.resize(attrCount);
4533         }
4534         attribState = &fDefaultVertexArrayAttribState;
4535     }
4536     return attribState;
4537 }
4538 
onIsACopyNeededForTextureParams(GrTextureProxy * proxy,const GrSamplerState & textureParams,GrTextureProducer::CopyParams * copyParams,SkScalar scaleAdjust[2]) const4539 bool GrGLGpu::onIsACopyNeededForTextureParams(GrTextureProxy* proxy,
4540                                               const GrSamplerState& textureParams,
4541                                               GrTextureProducer::CopyParams* copyParams,
4542                                               SkScalar scaleAdjust[2]) const {
4543     const GrTexture* texture = proxy->priv().peekTexture();
4544     if (!texture) {
4545         // The only way to get and EXTERNAL or RECTANGLE texture in Ganesh is to wrap them.
4546         // In that case the proxy should already be instantiated.
4547         return false;
4548     }
4549 
4550     if (textureParams.isRepeated() || GrSamplerState::Filter::kMipMap == textureParams.filter()) {
4551         const GrGLTexture* glTexture = static_cast<const GrGLTexture*>(texture);
4552         if (GR_GL_TEXTURE_EXTERNAL == glTexture->target() ||
4553             GR_GL_TEXTURE_RECTANGLE == glTexture->target()) {
4554             copyParams->fFilter = GrSamplerState::Filter::kNearest;
4555             copyParams->fWidth = texture->width();
4556             copyParams->fHeight = texture->height();
4557             return true;
4558         }
4559     }
4560     return false;
4561 }
4562 
onFinishFlush(bool insertedSemaphore)4563 void GrGLGpu::onFinishFlush(bool insertedSemaphore) {
4564     // If we inserted semaphores during the flush, we need to call GLFlush.
4565     if (insertedSemaphore) {
4566         GL_CALL(Flush());
4567     }
4568 }
4569 
insertFence()4570 GrFence SK_WARN_UNUSED_RESULT GrGLGpu::insertFence() {
4571     SkASSERT(this->caps()->fenceSyncSupport());
4572     GrGLsync sync;
4573     GL_CALL_RET(sync, FenceSync(GR_GL_SYNC_GPU_COMMANDS_COMPLETE, 0));
4574     GR_STATIC_ASSERT(sizeof(GrFence) >= sizeof(GrGLsync));
4575     return (GrFence)sync;
4576 }
4577 
waitFence(GrFence fence,uint64_t timeout)4578 bool GrGLGpu::waitFence(GrFence fence, uint64_t timeout) {
4579     GrGLenum result;
4580     GL_CALL_RET(result, ClientWaitSync((GrGLsync)fence, GR_GL_SYNC_FLUSH_COMMANDS_BIT, timeout));
4581     return (GR_GL_CONDITION_SATISFIED == result);
4582 }
4583 
deleteFence(GrFence fence) const4584 void GrGLGpu::deleteFence(GrFence fence) const {
4585     this->deleteSync((GrGLsync)fence);
4586 }
4587 
makeSemaphore(bool isOwned)4588 sk_sp<GrSemaphore> SK_WARN_UNUSED_RESULT GrGLGpu::makeSemaphore(bool isOwned) {
4589     SkASSERT(this->caps()->fenceSyncSupport());
4590     return GrGLSemaphore::Make(this, isOwned);
4591 }
4592 
wrapBackendSemaphore(const GrBackendSemaphore & semaphore,GrResourceProvider::SemaphoreWrapType wrapType,GrWrapOwnership ownership)4593 sk_sp<GrSemaphore> GrGLGpu::wrapBackendSemaphore(const GrBackendSemaphore& semaphore,
4594                                                  GrResourceProvider::SemaphoreWrapType wrapType,
4595                                                  GrWrapOwnership ownership) {
4596     SkASSERT(this->caps()->fenceSyncSupport());
4597     return GrGLSemaphore::MakeWrapped(this, semaphore.glSync(), ownership);
4598 }
4599 
insertSemaphore(sk_sp<GrSemaphore> semaphore,bool flush)4600 void GrGLGpu::insertSemaphore(sk_sp<GrSemaphore> semaphore, bool flush) {
4601     GrGLSemaphore* glSem = static_cast<GrGLSemaphore*>(semaphore.get());
4602 
4603     GrGLsync sync;
4604     GL_CALL_RET(sync, FenceSync(GR_GL_SYNC_GPU_COMMANDS_COMPLETE, 0));
4605     glSem->setSync(sync);
4606 
4607     if (flush) {
4608         GL_CALL(Flush());
4609     }
4610 }
4611 
waitSemaphore(sk_sp<GrSemaphore> semaphore)4612 void GrGLGpu::waitSemaphore(sk_sp<GrSemaphore> semaphore) {
4613     GrGLSemaphore* glSem = static_cast<GrGLSemaphore*>(semaphore.get());
4614 
4615     GL_CALL(WaitSync(glSem->sync(), 0, GR_GL_TIMEOUT_IGNORED));
4616 }
4617 
deleteSync(GrGLsync sync) const4618 void GrGLGpu::deleteSync(GrGLsync sync) const {
4619     GL_CALL(DeleteSync(sync));
4620 }
4621 
insertEventMarker(const char * msg)4622 void GrGLGpu::insertEventMarker(const char* msg) {
4623     GL_CALL(InsertEventMarker(strlen(msg), msg));
4624 }
4625 
prepareTextureForCrossContextUsage(GrTexture * texture)4626 sk_sp<GrSemaphore> GrGLGpu::prepareTextureForCrossContextUsage(GrTexture* texture) {
4627     // Set up a semaphore to be signaled once the data is ready, and flush GL
4628     sk_sp<GrSemaphore> semaphore = this->makeSemaphore(true);
4629     this->insertSemaphore(semaphore, true);
4630 
4631     return semaphore;
4632 }
4633 
TextureToCopyProgramIdx(GrTexture * texture)4634 int GrGLGpu::TextureToCopyProgramIdx(GrTexture* texture) {
4635     switch (texture->texturePriv().samplerType()) {
4636         case kTexture2DSampler_GrSLType:
4637             return 0;
4638         case kITexture2DSampler_GrSLType:
4639             return 1;
4640         case kTexture2DRectSampler_GrSLType:
4641             return 2;
4642         case kTextureExternalSampler_GrSLType:
4643             return 3;
4644         default:
4645             SK_ABORT("Unexpected samper type");
4646             return 0;
4647     }
4648 }
4649 
onDumpJSON(SkJSONWriter * writer) const4650 void GrGLGpu::onDumpJSON(SkJSONWriter* writer) const {
4651     // We are called by the base class, which has already called beginObject(). We choose to nest
4652     // all of our caps information in a named sub-object.
4653     writer->beginObject("GL GPU");
4654 
4655     const GrGLubyte* str;
4656     GL_CALL_RET(str, GetString(GR_GL_VERSION));
4657     writer->appendString("GL_VERSION", (const char*)(str));
4658     GL_CALL_RET(str, GetString(GR_GL_RENDERER));
4659     writer->appendString("GL_RENDERER", (const char*)(str));
4660     GL_CALL_RET(str, GetString(GR_GL_VENDOR));
4661     writer->appendString("GL_VENDOR", (const char*)(str));
4662     GL_CALL_RET(str, GetString(GR_GL_SHADING_LANGUAGE_VERSION));
4663     writer->appendString("GL_SHADING_LANGUAGE_VERSION", (const char*)(str));
4664 
4665     writer->appendName("extensions");
4666     glInterface()->fExtensions.dumpJSON(writer);
4667 
4668     writer->endObject();
4669 }
4670