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