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 "GrCaps.h"
9 #include "GrContextOptions.h"
10 #include "GrWindowRectangles.h"
11 
GrShaderCaps()12 GrShaderCaps::GrShaderCaps() {
13     fShaderDerivativeSupport = false;
14     fGeometryShaderSupport = false;
15     fPathRenderingSupport = false;
16     fDstReadInShaderSupport = false;
17     fDualSourceBlendingSupport = false;
18     fIntegerSupport = false;
19     fTexelBufferSupport = false;
20     fShaderPrecisionVaries = false;
21 }
22 
shader_type_to_string(GrShaderType type)23 static const char* shader_type_to_string(GrShaderType type) {
24     switch (type) {
25     case kVertex_GrShaderType:
26         return "vertex";
27     case kGeometry_GrShaderType:
28         return "geometry";
29     case kFragment_GrShaderType:
30         return "fragment";
31     }
32     return "";
33 }
34 
precision_to_string(GrSLPrecision p)35 static const char* precision_to_string(GrSLPrecision p) {
36     switch (p) {
37     case kLow_GrSLPrecision:
38         return "low";
39     case kMedium_GrSLPrecision:
40         return "medium";
41     case kHigh_GrSLPrecision:
42         return "high";
43     }
44     return "";
45 }
46 
dump() const47 SkString GrShaderCaps::dump() const {
48     SkString r;
49     static const char* gNY[] = { "NO", "YES" };
50     r.appendf("Shader Derivative Support          : %s\n", gNY[fShaderDerivativeSupport]);
51     r.appendf("Geometry Shader Support            : %s\n", gNY[fGeometryShaderSupport]);
52     r.appendf("Path Rendering Support             : %s\n", gNY[fPathRenderingSupport]);
53     r.appendf("Dst Read In Shader Support         : %s\n", gNY[fDstReadInShaderSupport]);
54     r.appendf("Dual Source Blending Support       : %s\n", gNY[fDualSourceBlendingSupport]);
55     r.appendf("Integer Support                    : %s\n", gNY[fIntegerSupport]);
56     r.appendf("Texel Buffer Support               : %s\n", gNY[fTexelBufferSupport]);
57 
58     r.appendf("Shader Float Precisions (varies: %s):\n", gNY[fShaderPrecisionVaries]);
59 
60     for (int s = 0; s < kGrShaderTypeCount; ++s) {
61         GrShaderType shaderType = static_cast<GrShaderType>(s);
62         r.appendf("\t%s:\n", shader_type_to_string(shaderType));
63         for (int p = 0; p < kGrSLPrecisionCount; ++p) {
64             if (fFloatPrecisions[s][p].supported()) {
65                 GrSLPrecision precision = static_cast<GrSLPrecision>(p);
66                 r.appendf("\t\t%s: log_low: %d log_high: %d bits: %d\n",
67                     precision_to_string(precision),
68                     fFloatPrecisions[s][p].fLogRangeLow,
69                     fFloatPrecisions[s][p].fLogRangeHigh,
70                     fFloatPrecisions[s][p].fBits);
71             }
72         }
73     }
74 
75     return r;
76 }
77 
applyOptionsOverrides(const GrContextOptions & options)78 void GrShaderCaps::applyOptionsOverrides(const GrContextOptions& options) {
79     fDualSourceBlendingSupport = fDualSourceBlendingSupport && !options.fSuppressDualSourceBlending;
80     this->onApplyOptionsOverrides(options);
81 }
82 
83 ///////////////////////////////////////////////////////////////////////////////
84 
GrCaps(const GrContextOptions & options)85 GrCaps::GrCaps(const GrContextOptions& options) {
86     fMipMapSupport = false;
87     fNPOTTextureTileSupport = false;
88     fSRGBSupport = false;
89     fSRGBWriteControl = false;
90     fTwoSidedStencilSupport = false;
91     fStencilWrapOpsSupport = false;
92     fDiscardRenderTargetSupport = false;
93     fReuseScratchTextures = true;
94     fReuseScratchBuffers = true;
95     fGpuTracingSupport = false;
96     fCompressedTexSubImageSupport = false;
97     fOversizedStencilSupport = false;
98     fTextureBarrierSupport = false;
99     fSampleLocationsSupport = false;
100     fMultisampleDisableSupport = false;
101     fUsesMixedSamples = false;
102     fPreferClientSideDynamicBuffers = false;
103     fFullClearIsFree = false;
104     fMustClearUploadedBufferData = false;
105     fSampleShadingSupport = false;
106     fFenceSyncSupport = false;
107 
108     fUseDrawInsteadOfClear = false;
109 
110     fInstancedSupport = InstancedSupport::kNone;
111 
112     fBlendEquationSupport = kBasic_BlendEquationSupport;
113     fAdvBlendEqBlacklist = 0;
114 
115     fMapBufferFlags = kNone_MapFlags;
116 
117     fMaxVertexAttributes = 0;
118     fMaxRenderTargetSize = 1;
119     fMaxTextureSize = 1;
120     fMaxColorSampleCount = 0;
121     fMaxStencilSampleCount = 0;
122     fMaxRasterSamples = 0;
123     fMaxWindowRectangles = 0;
124 
125     fSuppressPrints = options.fSuppressPrints;
126     fImmediateFlush = options.fImmediateMode;
127     fBufferMapThreshold = options.fBufferMapThreshold;
128     fUseDrawInsteadOfPartialRenderTargetWrite = options.fUseDrawInsteadOfPartialRenderTargetWrite;
129     fUseDrawInsteadOfAllRenderTargetWrites = false;
130     fAvoidInstancedDrawsToFPTargets = false;
131 
132     fPreferVRAMUseOverFlushes = true;
133 }
134 
applyOptionsOverrides(const GrContextOptions & options)135 void GrCaps::applyOptionsOverrides(const GrContextOptions& options) {
136     this->onApplyOptionsOverrides(options);
137     fMaxTextureSize = SkTMin(fMaxTextureSize, options.fMaxTextureSizeOverride);
138     // If the max tile override is zero, it means we should use the max texture size.
139     if (!options.fMaxTileSizeOverride || options.fMaxTileSizeOverride > fMaxTextureSize) {
140         fMaxTileSize = fMaxTextureSize;
141     } else {
142         fMaxTileSize = options.fMaxTileSizeOverride;
143     }
144     if (fMaxWindowRectangles > GrWindowRectangles::kMaxWindows) {
145         SkDebugf("WARNING: capping window rectangles at %i. HW advertises support for %i.\n",
146                  GrWindowRectangles::kMaxWindows, fMaxWindowRectangles);
147         fMaxWindowRectangles = GrWindowRectangles::kMaxWindows;
148     }
149 }
150 
map_flags_to_string(uint32_t flags)151 static SkString map_flags_to_string(uint32_t flags) {
152     SkString str;
153     if (GrCaps::kNone_MapFlags == flags) {
154         str = "none";
155     } else {
156         SkASSERT(GrCaps::kCanMap_MapFlag & flags);
157         SkDEBUGCODE(flags &= ~GrCaps::kCanMap_MapFlag);
158         str = "can_map";
159 
160         if (GrCaps::kSubset_MapFlag & flags) {
161             str.append(" partial");
162         } else {
163             str.append(" full");
164         }
165         SkDEBUGCODE(flags &= ~GrCaps::kSubset_MapFlag);
166     }
167     SkASSERT(0 == flags); // Make sure we handled all the flags.
168     return str;
169 }
170 
dump() const171 SkString GrCaps::dump() const {
172     SkString r;
173     static const char* gNY[] = {"NO", "YES"};
174     r.appendf("MIP Map Support                    : %s\n", gNY[fMipMapSupport]);
175     r.appendf("NPOT Texture Tile Support          : %s\n", gNY[fNPOTTextureTileSupport]);
176     r.appendf("sRGB Support                       : %s\n", gNY[fSRGBSupport]);
177     r.appendf("sRGB Write Control                 : %s\n", gNY[fSRGBWriteControl]);
178     r.appendf("Two Sided Stencil Support          : %s\n", gNY[fTwoSidedStencilSupport]);
179     r.appendf("Stencil Wrap Ops  Support          : %s\n", gNY[fStencilWrapOpsSupport]);
180     r.appendf("Discard Render Target Support      : %s\n", gNY[fDiscardRenderTargetSupport]);
181     r.appendf("Reuse Scratch Textures             : %s\n", gNY[fReuseScratchTextures]);
182     r.appendf("Reuse Scratch Buffers              : %s\n", gNY[fReuseScratchBuffers]);
183     r.appendf("Gpu Tracing Support                : %s\n", gNY[fGpuTracingSupport]);
184     r.appendf("Compressed Update Support          : %s\n", gNY[fCompressedTexSubImageSupport]);
185     r.appendf("Oversized Stencil Support          : %s\n", gNY[fOversizedStencilSupport]);
186     r.appendf("Texture Barrier Support            : %s\n", gNY[fTextureBarrierSupport]);
187     r.appendf("Sample Locations Support           : %s\n", gNY[fSampleLocationsSupport]);
188     r.appendf("Multisample disable support        : %s\n", gNY[fMultisampleDisableSupport]);
189     r.appendf("Uses Mixed Samples                 : %s\n", gNY[fUsesMixedSamples]);
190     r.appendf("Prefer client-side dynamic buffers : %s\n", gNY[fPreferClientSideDynamicBuffers]);
191     r.appendf("Full screen clear is free          : %s\n", gNY[fFullClearIsFree]);
192     r.appendf("Must clear buffer memory           : %s\n", gNY[fMustClearUploadedBufferData]);
193     r.appendf("Sample shading support             : %s\n", gNY[fSampleShadingSupport]);
194     r.appendf("Fence sync support                 : %s\n", gNY[fFenceSyncSupport]);
195 
196     r.appendf("Draw Instead of Clear [workaround] : %s\n", gNY[fUseDrawInsteadOfClear]);
197     r.appendf("Draw Instead of TexSubImage [workaround] : %s\n",
198               gNY[fUseDrawInsteadOfPartialRenderTargetWrite]);
199     r.appendf("Prefer VRAM Use over flushes [workaround] : %s\n", gNY[fPreferVRAMUseOverFlushes]);
200 
201     if (this->advancedBlendEquationSupport()) {
202         r.appendf("Advanced Blend Equation Blacklist  : 0x%x\n", fAdvBlendEqBlacklist);
203     }
204 
205     r.appendf("Max Vertex Attributes              : %d\n", fMaxVertexAttributes);
206     r.appendf("Max Texture Size                   : %d\n", fMaxTextureSize);
207     r.appendf("Max Render Target Size             : %d\n", fMaxRenderTargetSize);
208     r.appendf("Max Color Sample Count             : %d\n", fMaxColorSampleCount);
209     r.appendf("Max Stencil Sample Count           : %d\n", fMaxStencilSampleCount);
210     r.appendf("Max Raster Samples                 : %d\n", fMaxRasterSamples);
211     r.appendf("Max Window Rectangles              : %d\n", fMaxWindowRectangles);
212 
213     static const char* kInstancedSupportNames[] = {
214         "None",
215         "Basic",
216         "Multisampled",
217         "Mixed Sampled",
218     };
219     GR_STATIC_ASSERT(0 == (int)InstancedSupport::kNone);
220     GR_STATIC_ASSERT(1 == (int)InstancedSupport::kBasic);
221     GR_STATIC_ASSERT(2 == (int)InstancedSupport::kMultisampled);
222     GR_STATIC_ASSERT(3 == (int)InstancedSupport::kMixedSampled);
223     GR_STATIC_ASSERT(4 == SK_ARRAY_COUNT(kInstancedSupportNames));
224 
225     r.appendf("Instanced Support                  : %s\n",
226               kInstancedSupportNames[(int)fInstancedSupport]);
227 
228     static const char* kBlendEquationSupportNames[] = {
229         "Basic",
230         "Advanced",
231         "Advanced Coherent",
232     };
233     GR_STATIC_ASSERT(0 == kBasic_BlendEquationSupport);
234     GR_STATIC_ASSERT(1 == kAdvanced_BlendEquationSupport);
235     GR_STATIC_ASSERT(2 == kAdvancedCoherent_BlendEquationSupport);
236     GR_STATIC_ASSERT(SK_ARRAY_COUNT(kBlendEquationSupportNames) == kLast_BlendEquationSupport + 1);
237 
238     r.appendf("Blend Equation Support             : %s\n",
239               kBlendEquationSupportNames[fBlendEquationSupport]);
240     r.appendf("Map Buffer Support                 : %s\n",
241               map_flags_to_string(fMapBufferFlags).c_str());
242 
243     static const char* kConfigNames[] = {
244         "Unknown",  // kUnknown_GrPixelConfig
245         "Alpha8",   // kAlpha_8_GrPixelConfig,
246         "Index8",   // kIndex_8_GrPixelConfig,
247         "RGB565",   // kRGB_565_GrPixelConfig,
248         "RGBA444",  // kRGBA_4444_GrPixelConfig,
249         "RGBA8888", // kRGBA_8888_GrPixelConfig,
250         "BGRA8888", // kBGRA_8888_GrPixelConfig,
251         "SRGBA8888",// kSRGBA_8888_GrPixelConfig,
252         "SBGRA8888",// kSBGRA_8888_GrPixelConfig,
253         "ETC1",     // kETC1_GrPixelConfig,
254         "LATC",     // kLATC_GrPixelConfig,
255         "R11EAC",   // kR11_EAC_GrPixelConfig,
256         "ASTC12x12",// kASTC_12x12_GrPixelConfig,
257         "RGBAFloat",// kRGBA_float_GrPixelConfig
258         "AlphaHalf",// kAlpha_half_GrPixelConfig
259         "RGBAHalf", // kRGBA_half_GrPixelConfig
260     };
261     GR_STATIC_ASSERT(0  == kUnknown_GrPixelConfig);
262     GR_STATIC_ASSERT(1  == kAlpha_8_GrPixelConfig);
263     GR_STATIC_ASSERT(2  == kIndex_8_GrPixelConfig);
264     GR_STATIC_ASSERT(3  == kRGB_565_GrPixelConfig);
265     GR_STATIC_ASSERT(4  == kRGBA_4444_GrPixelConfig);
266     GR_STATIC_ASSERT(5  == kRGBA_8888_GrPixelConfig);
267     GR_STATIC_ASSERT(6  == kBGRA_8888_GrPixelConfig);
268     GR_STATIC_ASSERT(7  == kSRGBA_8888_GrPixelConfig);
269     GR_STATIC_ASSERT(8  == kSBGRA_8888_GrPixelConfig);
270     GR_STATIC_ASSERT(9  == kETC1_GrPixelConfig);
271     GR_STATIC_ASSERT(10  == kLATC_GrPixelConfig);
272     GR_STATIC_ASSERT(11  == kR11_EAC_GrPixelConfig);
273     GR_STATIC_ASSERT(12 == kASTC_12x12_GrPixelConfig);
274     GR_STATIC_ASSERT(13 == kRGBA_float_GrPixelConfig);
275     GR_STATIC_ASSERT(14 == kAlpha_half_GrPixelConfig);
276     GR_STATIC_ASSERT(15 == kRGBA_half_GrPixelConfig);
277     GR_STATIC_ASSERT(SK_ARRAY_COUNT(kConfigNames) == kGrPixelConfigCnt);
278 
279     SkASSERT(!this->isConfigRenderable(kUnknown_GrPixelConfig, false));
280     SkASSERT(!this->isConfigRenderable(kUnknown_GrPixelConfig, true));
281 
282     for (size_t i = 1; i < SK_ARRAY_COUNT(kConfigNames); ++i)  {
283         GrPixelConfig config = static_cast<GrPixelConfig>(i);
284         r.appendf("%s is renderable: %s, with MSAA: %s\n",
285                   kConfigNames[i],
286                   gNY[this->isConfigRenderable(config, false)],
287                   gNY[this->isConfigRenderable(config, true)]);
288     }
289 
290     SkASSERT(!this->isConfigTexturable(kUnknown_GrPixelConfig));
291 
292     for (size_t i = 1; i < SK_ARRAY_COUNT(kConfigNames); ++i)  {
293         GrPixelConfig config = static_cast<GrPixelConfig>(i);
294         r.appendf("%s is uploadable to a texture: %s\n",
295                   kConfigNames[i],
296                   gNY[this->isConfigTexturable(config)]);
297     }
298 
299     return r;
300 }
301