1 /*
2 * Copyright 2015 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 "include/gpu/GrBackendSurface.h"
9 #include "include/gpu/GrContextOptions.h"
10 #include "include/gpu/GrSurface.h"
11 #include "include/private/GrTypesPriv.h"
12 #include "src/gpu/GrCaps.h"
13 #include "src/gpu/GrSurfaceProxy.h"
14 #include "src/gpu/GrWindowRectangles.h"
15 #include "src/utils/SkJSONWriter.h"
16
GrCaps(const GrContextOptions & options)17 GrCaps::GrCaps(const GrContextOptions& options) {
18 fMipMapSupport = false;
19 fNPOTTextureTileSupport = false;
20 fReuseScratchTextures = true;
21 fReuseScratchBuffers = true;
22 fGpuTracingSupport = false;
23 fOversizedStencilSupport = false;
24 fTextureBarrierSupport = false;
25 fSampleLocationsSupport = false;
26 fMultisampleDisableSupport = false;
27 fInstanceAttribSupport = false;
28 fMixedSamplesSupport = false;
29 fConservativeRasterSupport = false;
30 fWireframeSupport = false;
31 fMSAAResolvesAutomatically = false;
32 fUsePrimitiveRestart = false;
33 fPreferClientSideDynamicBuffers = false;
34 fPreferFullscreenClears = false;
35 fMustClearUploadedBufferData = false;
36 fShouldInitializeTextures = false;
37 fSupportsAHardwareBufferImages = false;
38 fFenceSyncSupport = false;
39 fSemaphoreSupport = false;
40 fCrossContextTextureSupport = false;
41 fHalfFloatVertexAttributeSupport = false;
42 fDynamicStateArrayGeometryProcessorTextureSupport = false;
43 fPerformPartialClearsAsDraws = false;
44 fPerformColorClearsAsDraws = false;
45 fAvoidLargeIndexBufferDraws = false;
46 fPerformStencilClearsAsDraws = false;
47 fAllowCoverageCounting = false;
48 fTransferFromBufferToTextureSupport = false;
49 fTransferFromSurfaceToBufferSupport = false;
50 fWritePixelsRowBytesSupport = false;
51 fReadPixelsRowBytesSupport = false;
52 fShouldCollapseSrcOverToSrcWhenAble = false;
53 fDriverBlacklistCCPR = false;
54 fDriverBlacklistMSAACCPR = false;
55
56 fBlendEquationSupport = kBasic_BlendEquationSupport;
57 fAdvBlendEqBlacklist = 0;
58
59 fMapBufferFlags = kNone_MapFlags;
60
61 fMaxVertexAttributes = 0;
62 fMaxRenderTargetSize = 1;
63 fMaxPreferredRenderTargetSize = 1;
64 fMaxTextureSize = 1;
65 fMaxWindowRectangles = 0;
66 fInternalMultisampleCount = 0;
67
68 fSuppressPrints = options.fSuppressPrints;
69 #if GR_TEST_UTILS
70 fWireframeMode = options.fWireframeMode;
71 #else
72 fWireframeMode = false;
73 #endif
74 fBufferMapThreshold = options.fBufferMapThreshold;
75 fAvoidStencilBuffers = false;
76 fAvoidWritePixelsFastPath = false;
77 fRequiresManualFBBarrierAfterTessellatedStencilDraw = false;
78
79 fPreferVRAMUseOverFlushes = true;
80
81 fPreferTrianglesOverSampleMask = false;
82
83 // Default to true, allow older versions of OpenGL to disable explicitly
84 fClampToBorderSupport = true;
85
86 fDriverBugWorkarounds = options.fDriverBugWorkarounds;
87 }
88
finishInitialization(const GrContextOptions & options)89 void GrCaps::finishInitialization(const GrContextOptions& options) {
90 if (fMixedSamplesSupport) {
91 // We need multisample disable and dual source blending in order to support mixed samples.
92 fMixedSamplesSupport = this->multisampleDisableSupport() &&
93 this->shaderCaps()->dualSourceBlendingSupport();
94 }
95
96 // Overrides happen last.
97 this->applyOptionsOverrides(options);
98 }
99
applyOptionsOverrides(const GrContextOptions & options)100 void GrCaps::applyOptionsOverrides(const GrContextOptions& options) {
101 fShaderCaps->applyOptionsOverrides(options);
102 this->onApplyOptionsOverrides(options);
103 if (options.fDisableDriverCorrectnessWorkarounds) {
104 SkASSERT(!fDriverBlacklistCCPR);
105 SkASSERT(!fDriverBlacklistMSAACCPR);
106 SkASSERT(!fAvoidStencilBuffers);
107 SkASSERT(!fAdvBlendEqBlacklist);
108 SkASSERT(!fPerformColorClearsAsDraws);
109 SkASSERT(!fPerformStencilClearsAsDraws);
110 // Don't check the partial-clear workaround, since that is a backend limitation, not a
111 // driver workaround (it just so happens the fallbacks are the same).
112 }
113 if (GrContextOptions::Enable::kNo == options.fUseDrawInsteadOfClear) {
114 fPerformColorClearsAsDraws = false;
115 fPerformStencilClearsAsDraws = false;
116 } else if (GrContextOptions::Enable::kYes == options.fUseDrawInsteadOfClear) {
117 fPerformColorClearsAsDraws = true;
118 fPerformStencilClearsAsDraws = true;
119 }
120
121 fAllowCoverageCounting = !options.fDisableCoverageCountingPaths;
122
123 fMaxTextureSize = std::min(fMaxTextureSize, options.fMaxTextureSizeOverride);
124 fMaxTileSize = fMaxTextureSize;
125 #if GR_TEST_UTILS
126 // If the max tile override is zero, it means we should use the max texture size.
127 if (options.fMaxTileSizeOverride && options.fMaxTileSizeOverride < fMaxTextureSize) {
128 fMaxTileSize = options.fMaxTileSizeOverride;
129 }
130 if (options.fSuppressDualSourceBlending) {
131 // GrShaderCaps::applyOptionsOverrides already handled the rest; here we just need to make
132 // sure mixed samples gets disabled if dual source blending is suppressed.
133 fMixedSamplesSupport = false;
134 }
135 if (options.fClearAllTextures) {
136 fShouldInitializeTextures = true;
137 }
138 #endif
139
140 if (fMaxWindowRectangles > GrWindowRectangles::kMaxWindows) {
141 SkDebugf("WARNING: capping window rectangles at %i. HW advertises support for %i.\n",
142 GrWindowRectangles::kMaxWindows, fMaxWindowRectangles);
143 fMaxWindowRectangles = GrWindowRectangles::kMaxWindows;
144 }
145
146 fInternalMultisampleCount = options.fInternalMultisampleCount;
147
148 fAvoidStencilBuffers = options.fAvoidStencilBuffers;
149
150 fDriverBugWorkarounds.applyOverrides(options.fDriverBugWorkarounds);
151 }
152
153
154 #ifdef SK_ENABLE_DUMP_GPU
155 #include "src/gpu/GrTestUtils.h"
156
map_flags_to_string(uint32_t flags)157 static SkString map_flags_to_string(uint32_t flags) {
158 SkString str;
159 if (GrCaps::kNone_MapFlags == flags) {
160 str = "none";
161 } else {
162 SkASSERT(GrCaps::kCanMap_MapFlag & flags);
163 SkDEBUGCODE(flags &= ~GrCaps::kCanMap_MapFlag);
164 str = "can_map";
165
166 if (GrCaps::kSubset_MapFlag & flags) {
167 str.append(" partial");
168 } else {
169 str.append(" full");
170 }
171 SkDEBUGCODE(flags &= ~GrCaps::kSubset_MapFlag);
172 if (GrCaps::kAsyncRead_MapFlag & flags) {
173 str.append(" async_read");
174 } else {
175 str.append(" sync_read");
176 }
177 SkDEBUGCODE(flags &= ~GrCaps::kAsyncRead_MapFlag);
178 }
179 SkASSERT(0 == flags); // Make sure we handled all the flags.
180 return str;
181 }
182
dumpJSON(SkJSONWriter * writer) const183 void GrCaps::dumpJSON(SkJSONWriter* writer) const {
184 writer->beginObject();
185
186 writer->appendBool("MIP Map Support", fMipMapSupport);
187 writer->appendBool("NPOT Texture Tile Support", fNPOTTextureTileSupport);
188 writer->appendBool("Reuse Scratch Textures", fReuseScratchTextures);
189 writer->appendBool("Reuse Scratch Buffers", fReuseScratchBuffers);
190 writer->appendBool("Gpu Tracing Support", fGpuTracingSupport);
191 writer->appendBool("Oversized Stencil Support", fOversizedStencilSupport);
192 writer->appendBool("Texture Barrier Support", fTextureBarrierSupport);
193 writer->appendBool("Sample Locations Support", fSampleLocationsSupport);
194 writer->appendBool("Multisample disable support", fMultisampleDisableSupport);
195 writer->appendBool("Instance Attrib Support", fInstanceAttribSupport);
196 writer->appendBool("Mixed Samples Support", fMixedSamplesSupport);
197 writer->appendBool("Conservative Raster Support", fConservativeRasterSupport);
198 writer->appendBool("Wireframe Support", fWireframeSupport);
199 writer->appendBool("MSAA Resolves Automatically", fMSAAResolvesAutomatically);
200 writer->appendBool("Use primitive restart", fUsePrimitiveRestart);
201 writer->appendBool("Prefer client-side dynamic buffers", fPreferClientSideDynamicBuffers);
202 writer->appendBool("Prefer fullscreen clears (and stencil discard)", fPreferFullscreenClears);
203 writer->appendBool("Must clear buffer memory", fMustClearUploadedBufferData);
204 writer->appendBool("Should initialize textures", fShouldInitializeTextures);
205 writer->appendBool("Supports importing AHardwareBuffers", fSupportsAHardwareBufferImages);
206 writer->appendBool("Fence sync support", fFenceSyncSupport);
207 writer->appendBool("Semaphore support", fSemaphoreSupport);
208 writer->appendBool("Cross context texture support", fCrossContextTextureSupport);
209 writer->appendBool("Half float vertex attribute support", fHalfFloatVertexAttributeSupport);
210 writer->appendBool("Specify GeometryProcessor textures as a dynamic state array",
211 fDynamicStateArrayGeometryProcessorTextureSupport);
212 writer->appendBool("Use draws for partial clears", fPerformPartialClearsAsDraws);
213 writer->appendBool("Use draws for color clears", fPerformColorClearsAsDraws);
214 writer->appendBool("Avoid Large IndexBuffer Draws", fAvoidLargeIndexBufferDraws);
215 writer->appendBool("Use draws for stencil clip clears", fPerformStencilClearsAsDraws);
216 writer->appendBool("Allow coverage counting shortcuts", fAllowCoverageCounting);
217 writer->appendBool("Supports transfers from buffers to textures",
218 fTransferFromBufferToTextureSupport);
219 writer->appendBool("Supports transfers from textures to buffers",
220 fTransferFromSurfaceToBufferSupport);
221 writer->appendBool("Write pixels row bytes support", fWritePixelsRowBytesSupport);
222 writer->appendBool("Read pixels row bytes support", fReadPixelsRowBytesSupport);
223 writer->appendBool("Blacklist CCPR on current driver [workaround]", fDriverBlacklistCCPR);
224 writer->appendBool("Blacklist MSAA version of CCPR on current driver [workaround]",
225 fDriverBlacklistMSAACCPR);
226 writer->appendBool("Clamp-to-border", fClampToBorderSupport);
227
228 writer->appendBool("Prefer VRAM Use over flushes [workaround]", fPreferVRAMUseOverFlushes);
229 writer->appendBool("Prefer more triangles over sample mask [MSAA only]",
230 fPreferTrianglesOverSampleMask);
231 writer->appendBool("Avoid stencil buffers [workaround]", fAvoidStencilBuffers);
232
233 if (this->advancedBlendEquationSupport()) {
234 writer->appendHexU32("Advanced Blend Equation Blacklist", fAdvBlendEqBlacklist);
235 }
236
237 writer->appendS32("Max Vertex Attributes", fMaxVertexAttributes);
238 writer->appendS32("Max Texture Size", fMaxTextureSize);
239 writer->appendS32("Max Render Target Size", fMaxRenderTargetSize);
240 writer->appendS32("Max Preferred Render Target Size", fMaxPreferredRenderTargetSize);
241 writer->appendS32("Max Window Rectangles", fMaxWindowRectangles);
242 writer->appendS32("Preferred Sample Count for Internal MSAA and Mixed Samples",
243 fInternalMultisampleCount);
244
245 static const char* kBlendEquationSupportNames[] = {
246 "Basic",
247 "Advanced",
248 "Advanced Coherent",
249 };
250 static_assert(0 == kBasic_BlendEquationSupport);
251 static_assert(1 == kAdvanced_BlendEquationSupport);
252 static_assert(2 == kAdvancedCoherent_BlendEquationSupport);
253 static_assert(SK_ARRAY_COUNT(kBlendEquationSupportNames) == kLast_BlendEquationSupport + 1);
254
255 writer->appendString("Blend Equation Support",
256 kBlendEquationSupportNames[fBlendEquationSupport]);
257 writer->appendString("Map Buffer Support", map_flags_to_string(fMapBufferFlags).c_str());
258
259 this->onDumpJSON(writer);
260
261 writer->appendName("shaderCaps");
262 this->shaderCaps()->dumpJSON(writer);
263
264 writer->endObject();
265 }
266 #else
dumpJSON(SkJSONWriter * writer) const267 void GrCaps::dumpJSON(SkJSONWriter* writer) const { }
268 #endif
269
surfaceSupportsWritePixels(const GrSurface * surface) const270 bool GrCaps::surfaceSupportsWritePixels(const GrSurface* surface) const {
271 return surface->readOnly() ? false : this->onSurfaceSupportsWritePixels(surface);
272 }
273
canCopySurface(const GrSurfaceProxy * dst,const GrSurfaceProxy * src,const SkIRect & srcRect,const SkIPoint & dstPoint) const274 bool GrCaps::canCopySurface(const GrSurfaceProxy* dst, const GrSurfaceProxy* src,
275 const SkIRect& srcRect, const SkIPoint& dstPoint) const {
276 if (dst->readOnly()) {
277 return false;
278 }
279
280 if (dst->backendFormat() != src->backendFormat()) {
281 return false;
282 }
283 return this->onCanCopySurface(dst, src, srcRect, dstPoint);
284 }
285
validateSurfaceParams(const SkISize & dimensions,const GrBackendFormat & format,GrRenderable renderable,int renderTargetSampleCnt,GrMipMapped mipped) const286 bool GrCaps::validateSurfaceParams(const SkISize& dimensions, const GrBackendFormat& format,
287 GrRenderable renderable, int renderTargetSampleCnt,
288 GrMipMapped mipped) const {
289 if (!this->isFormatTexturable(format)) {
290 return false;
291 }
292
293 if (GrMipMapped::kYes == mipped && !this->mipMapSupport()) {
294 return false;
295 }
296
297 if (dimensions.width() < 1 || dimensions.height() < 1) {
298 return false;
299 }
300
301 if (renderable == GrRenderable::kYes) {
302 if (!this->isFormatRenderable(format, renderTargetSampleCnt)) {
303 return false;
304 }
305 int maxRTSize = this->maxRenderTargetSize();
306 if (dimensions.width() > maxRTSize || dimensions.height() > maxRTSize) {
307 return false;
308 }
309 } else {
310 // We currently do not support multisampled textures
311 if (renderTargetSampleCnt != 1) {
312 return false;
313 }
314 int maxSize = this->maxTextureSize();
315 if (dimensions.width() > maxSize || dimensions.height() > maxSize) {
316 return false;
317 }
318 }
319
320 return true;
321 }
322
supportedReadPixelsColorType(GrColorType srcColorType,const GrBackendFormat & srcFormat,GrColorType dstColorType) const323 GrCaps::SupportedRead GrCaps::supportedReadPixelsColorType(GrColorType srcColorType,
324 const GrBackendFormat& srcFormat,
325 GrColorType dstColorType) const {
326 SupportedRead read = this->onSupportedReadPixelsColorType(srcColorType, srcFormat,
327 dstColorType);
328
329 // There are known problems with 24 vs 32 bit BPP with this color type. Just fail for now if
330 // using a transfer buffer.
331 if (GrColorType::kRGB_888x == read.fColorType) {
332 read.fOffsetAlignmentForTransferBuffer = 0;
333 }
334 // It's very convenient to access 1 byte-per-channel 32 bit color types as uint32_t on the CPU.
335 // Make those aligned reads out of the buffer even if the underlying API doesn't require it.
336 auto componentFlags = GrColorTypeComponentFlags(read.fColorType);
337 if ((componentFlags == kRGBA_SkColorTypeComponentFlags ||
338 componentFlags == kRGB_SkColorTypeComponentFlags ||
339 componentFlags == kAlpha_SkColorTypeComponentFlag ||
340 componentFlags == kGray_SkColorTypeComponentFlag) &&
341 GrColorTypeBytesPerPixel(read.fColorType) == 4) {
342 switch (read.fOffsetAlignmentForTransferBuffer & 0b11) {
343 // offset alignment already a multiple of 4
344 case 0:
345 break;
346 // offset alignment is a multiple of 2 but not 4.
347 case 2:
348 read.fOffsetAlignmentForTransferBuffer *= 2;
349 // offset alignment is not a multiple of 2.
350 default:
351 read.fOffsetAlignmentForTransferBuffer *= 4;
352 }
353 }
354 return read;
355 }
356
getDefaultBackendFormat(GrColorType grColorType,GrRenderable renderable) const357 GrBackendFormat GrCaps::getDefaultBackendFormat(GrColorType grColorType,
358 GrRenderable renderable) const {
359 GrBackendFormat format = this->onGetDefaultBackendFormat(grColorType, renderable);
360 if (!this->isFormatTexturableAndUploadable(grColorType, format)) {
361 return {};
362 }
363
364 if (renderable == GrRenderable::kYes) {
365 if (!this->isFormatAsColorTypeRenderable(grColorType, format)) {
366 return {};
367 }
368 }
369
370 return format;
371 }
372
373