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