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