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