• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     fSRGBSupport = false;
21     fSRGBWriteControl = false;
22     fReuseScratchTextures = true;
23     fReuseScratchBuffers = true;
24     fGpuTracingSupport = false;
25     fOversizedStencilSupport = false;
26     fTextureBarrierSupport = false;
27     fSampleLocationsSupport = false;
28     fMultisampleDisableSupport = false;
29     fInstanceAttribSupport = false;
30     fMixedSamplesSupport = 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     fPerformStencilClearsAsDraws = false;
46     fAllowCoverageCounting = false;
47     fTransferBufferSupport = false;
48     fWritePixelsRowBytesSupport = false;
49     fReadPixelsRowBytesSupport = false;
50     fDriverBlacklistCCPR = false;
51     fDriverBlacklistMSAACCPR = false;
52 
53     fBlendEquationSupport = kBasic_BlendEquationSupport;
54     fAdvBlendEqBlacklist = 0;
55 
56     fMapBufferFlags = kNone_MapFlags;
57 
58     fMaxVertexAttributes = 0;
59     fMaxRenderTargetSize = 1;
60     fMaxPreferredRenderTargetSize = 1;
61     fMaxTextureSize = 1;
62     fMaxWindowRectangles = 0;
63     fInternalMultisampleCount = 0;
64 
65     fSuppressPrints = options.fSuppressPrints;
66 #if GR_TEST_UTILS
67     fWireframeMode = options.fWireframeMode;
68 #else
69     fWireframeMode = false;
70 #endif
71     fBufferMapThreshold = options.fBufferMapThreshold;
72     fAvoidStencilBuffers = false;
73     fAvoidWritePixelsFastPath = false;
74 
75     fPreferVRAMUseOverFlushes = true;
76 
77     fPreferTrianglesOverSampleMask = false;
78 
79     // Default to true, allow older versions of OpenGL to disable explicitly
80     fClampToBorderSupport = true;
81 
82     fDriverBugWorkarounds = options.fDriverBugWorkarounds;
83 }
84 
applyOptionsOverrides(const GrContextOptions & options)85 void GrCaps::applyOptionsOverrides(const GrContextOptions& options) {
86     this->onApplyOptionsOverrides(options);
87     if (options.fDisableDriverCorrectnessWorkarounds) {
88         SkASSERT(!fDriverBlacklistCCPR);
89         SkASSERT(!fDriverBlacklistMSAACCPR);
90         SkASSERT(!fAvoidStencilBuffers);
91         SkASSERT(!fAdvBlendEqBlacklist);
92         SkASSERT(!fPerformColorClearsAsDraws);
93         SkASSERT(!fPerformStencilClearsAsDraws);
94         // Don't check the partial-clear workaround, since that is a backend limitation, not a
95         // driver workaround (it just so happens the fallbacks are the same).
96     }
97     if (GrContextOptions::Enable::kNo == options.fUseDrawInsteadOfClear) {
98         fPerformColorClearsAsDraws = false;
99         fPerformStencilClearsAsDraws = false;
100     } else if (GrContextOptions::Enable::kYes == options.fUseDrawInsteadOfClear) {
101         fPerformColorClearsAsDraws = true;
102         fPerformStencilClearsAsDraws = true;
103     }
104 
105     fAllowCoverageCounting = !options.fDisableCoverageCountingPaths;
106 
107     fMaxTextureSize = SkTMin(fMaxTextureSize, options.fMaxTextureSizeOverride);
108     fMaxTileSize = fMaxTextureSize;
109 #if GR_TEST_UTILS
110     // If the max tile override is zero, it means we should use the max texture size.
111     if (options.fMaxTileSizeOverride && options.fMaxTileSizeOverride < fMaxTextureSize) {
112         fMaxTileSize = options.fMaxTileSizeOverride;
113     }
114     if (options.fSuppressGeometryShaders) {
115         fShaderCaps->fGeometryShaderSupport = false;
116     }
117     if (options.fClearAllTextures) {
118         fShouldInitializeTextures = true;
119     }
120 #endif
121 
122     if (fMaxWindowRectangles > GrWindowRectangles::kMaxWindows) {
123         SkDebugf("WARNING: capping window rectangles at %i. HW advertises support for %i.\n",
124                  GrWindowRectangles::kMaxWindows, fMaxWindowRectangles);
125         fMaxWindowRectangles = GrWindowRectangles::kMaxWindows;
126     }
127 
128     fInternalMultisampleCount = options.fInternalMultisampleCount;
129 
130     fAvoidStencilBuffers = options.fAvoidStencilBuffers;
131 
132     fDriverBugWorkarounds.applyOverrides(options.fDriverBugWorkarounds);
133 }
134 
135 
136 #ifdef SK_ENABLE_DUMP_GPU
137 #include "src/gpu/GrTestUtils.h"
138 
map_flags_to_string(uint32_t flags)139 static SkString map_flags_to_string(uint32_t flags) {
140     SkString str;
141     if (GrCaps::kNone_MapFlags == flags) {
142         str = "none";
143     } else {
144         SkASSERT(GrCaps::kCanMap_MapFlag & flags);
145         SkDEBUGCODE(flags &= ~GrCaps::kCanMap_MapFlag);
146         str = "can_map";
147 
148         if (GrCaps::kSubset_MapFlag & flags) {
149             str.append(" partial");
150         } else {
151             str.append(" full");
152         }
153         SkDEBUGCODE(flags &= ~GrCaps::kSubset_MapFlag);
154         if (GrCaps::kAsyncRead_MapFlag & flags) {
155             str.append(" async_read");
156         } else {
157             str.append(" sync_read");
158         }
159         SkDEBUGCODE(flags &= ~GrCaps::kAsyncRead_MapFlag);
160     }
161     SkASSERT(0 == flags); // Make sure we handled all the flags.
162     return str;
163 }
164 
dumpJSON(SkJSONWriter * writer) const165 void GrCaps::dumpJSON(SkJSONWriter* writer) const {
166     writer->beginObject();
167 
168     writer->appendBool("MIP Map Support", fMipMapSupport);
169     writer->appendBool("NPOT Texture Tile Support", fNPOTTextureTileSupport);
170     writer->appendBool("sRGB Support", fSRGBSupport);
171     writer->appendBool("sRGB Write Control", fSRGBWriteControl);
172     writer->appendBool("Reuse Scratch Textures", fReuseScratchTextures);
173     writer->appendBool("Reuse Scratch Buffers", fReuseScratchBuffers);
174     writer->appendBool("Gpu Tracing Support", fGpuTracingSupport);
175     writer->appendBool("Oversized Stencil Support", fOversizedStencilSupport);
176     writer->appendBool("Texture Barrier Support", fTextureBarrierSupport);
177     writer->appendBool("Sample Locations Support", fSampleLocationsSupport);
178     writer->appendBool("Multisample disable support", fMultisampleDisableSupport);
179     writer->appendBool("Instance Attrib Support", fInstanceAttribSupport);
180     writer->appendBool("Mixed Samples Support", fMixedSamplesSupport);
181     writer->appendBool("MSAA Resolves Automatically", fMSAAResolvesAutomatically);
182     writer->appendBool("Use primitive restart", fUsePrimitiveRestart);
183     writer->appendBool("Prefer client-side dynamic buffers", fPreferClientSideDynamicBuffers);
184     writer->appendBool("Prefer fullscreen clears", fPreferFullscreenClears);
185     writer->appendBool("Must clear buffer memory", fMustClearUploadedBufferData);
186     writer->appendBool("Should initialize textures", fShouldInitializeTextures);
187     writer->appendBool("Supports importing AHardwareBuffers", fSupportsAHardwareBufferImages);
188     writer->appendBool("Fence sync support", fFenceSyncSupport);
189     writer->appendBool("Semaphore support", fSemaphoreSupport);
190     writer->appendBool("Cross context texture support", fCrossContextTextureSupport);
191     writer->appendBool("Half float vertex attribute support", fHalfFloatVertexAttributeSupport);
192     writer->appendBool("Specify GeometryProcessor textures as a dynamic state array",
193                        fDynamicStateArrayGeometryProcessorTextureSupport);
194     writer->appendBool("Use draws for partial clears", fPerformPartialClearsAsDraws);
195     writer->appendBool("Use draws for color clears", fPerformColorClearsAsDraws);
196     writer->appendBool("Use draws for stencil clip clears", fPerformStencilClearsAsDraws);
197     writer->appendBool("Allow coverage counting shortcuts", fAllowCoverageCounting);
198     writer->appendBool("Supports transfer buffers", fTransferBufferSupport);
199     writer->appendBool("Write pixels row bytes support", fWritePixelsRowBytesSupport);
200     writer->appendBool("Read pixels row bytes support", fReadPixelsRowBytesSupport);
201     writer->appendBool("Blacklist CCPR on current driver [workaround]", fDriverBlacklistCCPR);
202     writer->appendBool("Blacklist MSAA version of CCPR on current driver [workaround]",
203                        fDriverBlacklistMSAACCPR);
204     writer->appendBool("Clamp-to-border", fClampToBorderSupport);
205 
206     writer->appendBool("Prefer VRAM Use over flushes [workaround]", fPreferVRAMUseOverFlushes);
207     writer->appendBool("Prefer more triangles over sample mask [MSAA only]",
208                        fPreferTrianglesOverSampleMask);
209     writer->appendBool("Avoid stencil buffers [workaround]", fAvoidStencilBuffers);
210 
211     if (this->advancedBlendEquationSupport()) {
212         writer->appendHexU32("Advanced Blend Equation Blacklist", fAdvBlendEqBlacklist);
213     }
214 
215     writer->appendS32("Max Vertex Attributes", fMaxVertexAttributes);
216     writer->appendS32("Max Texture Size", fMaxTextureSize);
217     writer->appendS32("Max Render Target Size", fMaxRenderTargetSize);
218     writer->appendS32("Max Preferred Render Target Size", fMaxPreferredRenderTargetSize);
219     writer->appendS32("Max Window Rectangles", fMaxWindowRectangles);
220     writer->appendS32("Preferred Sample Count for Internal MSAA and Mixed Samples",
221                       fInternalMultisampleCount);
222 
223     static const char* kBlendEquationSupportNames[] = {
224         "Basic",
225         "Advanced",
226         "Advanced Coherent",
227     };
228     GR_STATIC_ASSERT(0 == kBasic_BlendEquationSupport);
229     GR_STATIC_ASSERT(1 == kAdvanced_BlendEquationSupport);
230     GR_STATIC_ASSERT(2 == kAdvancedCoherent_BlendEquationSupport);
231     GR_STATIC_ASSERT(SK_ARRAY_COUNT(kBlendEquationSupportNames) == kLast_BlendEquationSupport + 1);
232 
233     writer->appendString("Blend Equation Support",
234                          kBlendEquationSupportNames[fBlendEquationSupport]);
235     writer->appendString("Map Buffer Support", map_flags_to_string(fMapBufferFlags).c_str());
236 
237     writer->beginArray("configs");
238 
239     // TODO: Either move this logic into individual backends dump and do it based on format and
240     // colorType, or have a loop printing out the defaults for given GrColorTypes. Or both.
241     for (size_t i = 1; i < kGrPixelConfigCnt; ++i) {
242         GrPixelConfig config = static_cast<GrPixelConfig>(i);
243         writer->beginObject(nullptr, false);
244         writer->appendString("name", GrPixelConfigToStr(config));
245         //writer->appendS32("max sample count", this->maxRenderTargetSampleCount(config));
246 //        writer->appendBool("texturable", this->isConfigTexturable(config));
247         writer->endObject();
248     }
249 
250     writer->endArray();
251 
252     this->onDumpJSON(writer);
253 
254     writer->appendName("shaderCaps");
255     this->shaderCaps()->dumpJSON(writer);
256 
257     writer->endObject();
258 }
259 #else
dumpJSON(SkJSONWriter * writer) const260 void GrCaps::dumpJSON(SkJSONWriter* writer) const { }
261 #endif
262 
surfaceSupportsWritePixels(const GrSurface * surface) const263 bool GrCaps::surfaceSupportsWritePixels(const GrSurface* surface) const {
264     return surface->readOnly() ? false : this->onSurfaceSupportsWritePixels(surface);
265 }
266 
canCopySurface(const GrSurfaceProxy * dst,const GrSurfaceProxy * src,const SkIRect & srcRect,const SkIPoint & dstPoint) const267 bool GrCaps::canCopySurface(const GrSurfaceProxy* dst, const GrSurfaceProxy* src,
268                             const SkIRect& srcRect, const SkIPoint& dstPoint) const {
269     if (dst->readOnly()) {
270         return false;
271     }
272     // Currently we only ever do copies where the configs are the same. This check really should be
273     // checking if the backend formats, color types, and swizzle are compatible. Our copy always
274     // copies exact byte to byte from src to dst so when need to check the if we do this, the dst
275     // has the expected values stored in the right places taking the swizzle into account. For now
276     // we can be more restrictive and just make sure the configs are the same and if we generalize
277     // copies and swizzles more in the future this can be updated.
278     if (this->makeConfigSpecific(dst->config(), dst->backendFormat()) !=
279         this->makeConfigSpecific(src->config(), src->backendFormat())) {
280         return false;
281     }
282     return this->onCanCopySurface(dst, src, srcRect, dstPoint);
283 }
284 
validateSurfaceParams(const SkISize & size,const GrBackendFormat & format,GrPixelConfig config,GrRenderable renderable,int renderTargetSampleCnt,GrMipMapped mipped) const285 bool GrCaps::validateSurfaceParams(const SkISize& size, const GrBackendFormat& format,
286                                    GrPixelConfig config, GrRenderable renderable,
287                                    int renderTargetSampleCnt, GrMipMapped mipped) const {
288     if (!this->isFormatTexturable(format)) {
289         return false;
290     }
291 
292     if (GrMipMapped::kYes == mipped && !this->mipMapSupport()) {
293         return false;
294     }
295 
296     if (size.width() < 1 || size.height() < 1) {
297         return false;
298     }
299 
300     if (renderable == GrRenderable::kYes) {
301         if (!this->isFormatRenderable(format, renderTargetSampleCnt)) {
302             return false;
303         }
304         int maxRTSize = this->maxRenderTargetSize();
305         if (size.width() > maxRTSize || size.height() > maxRTSize) {
306             return false;
307         }
308     } else {
309         // We currently do not support multisampled textures
310         if (renderTargetSampleCnt != 1) {
311             return false;
312         }
313         int maxSize = this->maxTextureSize();
314         if (size.width() > maxSize || size.height() > maxSize) {
315             return false;
316         }
317     }
318 
319     return true;
320 }
321 
supportedReadPixelsColorType(GrColorType srcColorType,const GrBackendFormat & srcFormat,GrColorType dstColorType) const322 GrCaps::SupportedRead GrCaps::supportedReadPixelsColorType(GrColorType srcColorType,
323                                                            const GrBackendFormat& srcFormat,
324                                                            GrColorType dstColorType) const {
325     SupportedRead read = this->onSupportedReadPixelsColorType(srcColorType, srcFormat,
326                                                               dstColorType);
327 
328     // There are known problems with 24 vs 32 bit BPP with this color type. Just fail for now if
329     // using a transfer buffer.
330     if (GrColorType::kRGB_888x == read.fColorType) {
331         read.fOffsetAlignmentForTransferBuffer = 0;
332     }
333     // It's very convenient to access 1 byte-per-channel 32 bit color types as uint32_t on the CPU.
334     // Make those aligned reads out of the buffer even if the underlying API doesn't require it.
335     auto componentFlags = GrColorTypeComponentFlags(read.fColorType);
336     if ((componentFlags == kRGBA_SkColorTypeComponentFlags ||
337          componentFlags == kRGB_SkColorTypeComponentFlags  ||
338          componentFlags == kAlpha_SkColorTypeComponentFlag ||
339          componentFlags == kGray_SkColorTypeComponentFlag) &&
340         GrColorTypeBytesPerPixel(read.fColorType) == 4) {
341         switch (read.fOffsetAlignmentForTransferBuffer & 0b11) {
342             // offset alignment already a multiple of 4
343             case 0:
344                 break;
345             // offset alignment is a multiple of 2 but not 4.
346             case 2:
347                 read.fOffsetAlignmentForTransferBuffer *= 2;
348             // offset alignment is not a multiple of 2.
349             default:
350                 read.fOffsetAlignmentForTransferBuffer *= 4;
351         }
352     }
353     return read;
354 }
355 
356 #ifdef SK_DEBUG
AreConfigsCompatible(GrPixelConfig genericConfig,GrPixelConfig specificConfig)357 bool GrCaps::AreConfigsCompatible(GrPixelConfig genericConfig, GrPixelConfig specificConfig) {
358     bool compatible = false;
359 
360     switch (genericConfig) {
361         case kAlpha_8_GrPixelConfig:
362             compatible = kAlpha_8_GrPixelConfig == specificConfig || // here bc of the mock context
363                          kAlpha_8_as_Alpha_GrPixelConfig == specificConfig ||
364                          kAlpha_8_as_Red_GrPixelConfig == specificConfig;
365             break;
366         case kGray_8_GrPixelConfig:
367             compatible = kGray_8_GrPixelConfig == specificConfig ||  // here bc of the mock context
368                          kGray_8_as_Lum_GrPixelConfig == specificConfig ||
369                          kGray_8_as_Red_GrPixelConfig == specificConfig;
370             break;
371         case kAlpha_half_GrPixelConfig:
372             compatible = kAlpha_half_GrPixelConfig == specificConfig || // bc of the mock context
373                          kAlpha_half_as_Red_GrPixelConfig == specificConfig ||
374                          kAlpha_half_as_Lum_GrPixelConfig == specificConfig;
375             break;
376         case kRGB_888_GrPixelConfig:
377             compatible = kRGB_888_GrPixelConfig == specificConfig ||
378                          kRGB_888X_GrPixelConfig == specificConfig;
379             break;
380         case kRGBA_8888_GrPixelConfig:
381             compatible = kRGBA_8888_GrPixelConfig == specificConfig ||
382                          kBGRA_8888_GrPixelConfig == specificConfig;
383             break;
384         default:
385             compatible = genericConfig == specificConfig;
386             break;
387     }
388 
389     if (!compatible) {
390         SkDebugf("Configs are not compatible: %d %d\n", genericConfig, specificConfig);
391     }
392 
393     return compatible;
394 }
395 #endif
396 
getDefaultBackendFormat(GrColorType grColorType,GrRenderable renderable) const397 GrBackendFormat GrCaps::getDefaultBackendFormat(GrColorType grColorType,
398                                                 GrRenderable renderable) const {
399     GrBackendFormat format = this->onGetDefaultBackendFormat(grColorType, renderable);
400     if (!this->isFormatTexturableAndUploadable(grColorType, format)) {
401         return {};
402     }
403 
404     if (renderable == GrRenderable::kYes) {
405         if (!this->isFormatAsColorTypeRenderable(grColorType, format)) {
406             return {};
407         }
408     }
409 
410     return format;
411 }
412 
413