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