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