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