| /* |
| * Copyright 2015 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #include "GrCaps.h" |
| #include "GrContextOptions.h" |
| #include "GrWindowRectangles.h" |
| |
| GrShaderCaps::GrShaderCaps() { |
| fShaderDerivativeSupport = false; |
| fGeometryShaderSupport = false; |
| fPathRenderingSupport = false; |
| fDstReadInShaderSupport = false; |
| fDualSourceBlendingSupport = false; |
| fIntegerSupport = false; |
| fTexelBufferSupport = false; |
| fShaderPrecisionVaries = false; |
| } |
| |
| static const char* shader_type_to_string(GrShaderType type) { |
| switch (type) { |
| case kVertex_GrShaderType: |
| return "vertex"; |
| case kGeometry_GrShaderType: |
| return "geometry"; |
| case kFragment_GrShaderType: |
| return "fragment"; |
| } |
| return ""; |
| } |
| |
| static const char* precision_to_string(GrSLPrecision p) { |
| switch (p) { |
| case kLow_GrSLPrecision: |
| return "low"; |
| case kMedium_GrSLPrecision: |
| return "medium"; |
| case kHigh_GrSLPrecision: |
| return "high"; |
| } |
| return ""; |
| } |
| |
| SkString GrShaderCaps::dump() const { |
| SkString r; |
| static const char* gNY[] = { "NO", "YES" }; |
| r.appendf("Shader Derivative Support : %s\n", gNY[fShaderDerivativeSupport]); |
| r.appendf("Geometry Shader Support : %s\n", gNY[fGeometryShaderSupport]); |
| r.appendf("Path Rendering Support : %s\n", gNY[fPathRenderingSupport]); |
| r.appendf("Dst Read In Shader Support : %s\n", gNY[fDstReadInShaderSupport]); |
| r.appendf("Dual Source Blending Support : %s\n", gNY[fDualSourceBlendingSupport]); |
| r.appendf("Integer Support : %s\n", gNY[fIntegerSupport]); |
| r.appendf("Texel Buffer Support : %s\n", gNY[fTexelBufferSupport]); |
| |
| r.appendf("Shader Float Precisions (varies: %s):\n", gNY[fShaderPrecisionVaries]); |
| |
| for (int s = 0; s < kGrShaderTypeCount; ++s) { |
| GrShaderType shaderType = static_cast<GrShaderType>(s); |
| r.appendf("\t%s:\n", shader_type_to_string(shaderType)); |
| for (int p = 0; p < kGrSLPrecisionCount; ++p) { |
| if (fFloatPrecisions[s][p].supported()) { |
| GrSLPrecision precision = static_cast<GrSLPrecision>(p); |
| r.appendf("\t\t%s: log_low: %d log_high: %d bits: %d\n", |
| precision_to_string(precision), |
| fFloatPrecisions[s][p].fLogRangeLow, |
| fFloatPrecisions[s][p].fLogRangeHigh, |
| fFloatPrecisions[s][p].fBits); |
| } |
| } |
| } |
| |
| return r; |
| } |
| |
| void GrShaderCaps::applyOptionsOverrides(const GrContextOptions& options) { |
| fDualSourceBlendingSupport = fDualSourceBlendingSupport && !options.fSuppressDualSourceBlending; |
| this->onApplyOptionsOverrides(options); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| GrCaps::GrCaps(const GrContextOptions& options) { |
| fMipMapSupport = false; |
| fNPOTTextureTileSupport = false; |
| fSRGBSupport = false; |
| fSRGBWriteControl = false; |
| fTwoSidedStencilSupport = false; |
| fStencilWrapOpsSupport = false; |
| fDiscardRenderTargetSupport = false; |
| fReuseScratchTextures = true; |
| fReuseScratchBuffers = true; |
| fGpuTracingSupport = false; |
| fCompressedTexSubImageSupport = false; |
| fOversizedStencilSupport = false; |
| fTextureBarrierSupport = false; |
| fSampleLocationsSupport = false; |
| fMultisampleDisableSupport = false; |
| fUsesMixedSamples = false; |
| fPreferClientSideDynamicBuffers = false; |
| fFullClearIsFree = false; |
| fMustClearUploadedBufferData = false; |
| fSampleShadingSupport = false; |
| fFenceSyncSupport = false; |
| |
| fUseDrawInsteadOfClear = false; |
| |
| fInstancedSupport = InstancedSupport::kNone; |
| |
| fBlendEquationSupport = kBasic_BlendEquationSupport; |
| fAdvBlendEqBlacklist = 0; |
| |
| fMapBufferFlags = kNone_MapFlags; |
| |
| fMaxVertexAttributes = 0; |
| fMaxRenderTargetSize = 1; |
| fMaxTextureSize = 1; |
| fMaxColorSampleCount = 0; |
| fMaxStencilSampleCount = 0; |
| fMaxRasterSamples = 0; |
| fMaxWindowRectangles = 0; |
| |
| fSuppressPrints = options.fSuppressPrints; |
| fImmediateFlush = options.fImmediateMode; |
| fBufferMapThreshold = options.fBufferMapThreshold; |
| fUseDrawInsteadOfPartialRenderTargetWrite = options.fUseDrawInsteadOfPartialRenderTargetWrite; |
| fUseDrawInsteadOfAllRenderTargetWrites = false; |
| fAvoidInstancedDrawsToFPTargets = false; |
| |
| fPreferVRAMUseOverFlushes = true; |
| } |
| |
| void GrCaps::applyOptionsOverrides(const GrContextOptions& options) { |
| this->onApplyOptionsOverrides(options); |
| fMaxTextureSize = SkTMin(fMaxTextureSize, options.fMaxTextureSizeOverride); |
| // If the max tile override is zero, it means we should use the max texture size. |
| if (!options.fMaxTileSizeOverride || options.fMaxTileSizeOverride > fMaxTextureSize) { |
| fMaxTileSize = fMaxTextureSize; |
| } else { |
| fMaxTileSize = options.fMaxTileSizeOverride; |
| } |
| if (fMaxWindowRectangles > GrWindowRectangles::kMaxWindows) { |
| SkDebugf("WARNING: capping window rectangles at %i. HW advertises support for %i.\n", |
| GrWindowRectangles::kMaxWindows, fMaxWindowRectangles); |
| fMaxWindowRectangles = GrWindowRectangles::kMaxWindows; |
| } |
| } |
| |
| static SkString map_flags_to_string(uint32_t flags) { |
| SkString str; |
| if (GrCaps::kNone_MapFlags == flags) { |
| str = "none"; |
| } else { |
| SkASSERT(GrCaps::kCanMap_MapFlag & flags); |
| SkDEBUGCODE(flags &= ~GrCaps::kCanMap_MapFlag); |
| str = "can_map"; |
| |
| if (GrCaps::kSubset_MapFlag & flags) { |
| str.append(" partial"); |
| } else { |
| str.append(" full"); |
| } |
| SkDEBUGCODE(flags &= ~GrCaps::kSubset_MapFlag); |
| } |
| SkASSERT(0 == flags); // Make sure we handled all the flags. |
| return str; |
| } |
| |
| SkString GrCaps::dump() const { |
| SkString r; |
| static const char* gNY[] = {"NO", "YES"}; |
| r.appendf("MIP Map Support : %s\n", gNY[fMipMapSupport]); |
| r.appendf("NPOT Texture Tile Support : %s\n", gNY[fNPOTTextureTileSupport]); |
| r.appendf("sRGB Support : %s\n", gNY[fSRGBSupport]); |
| r.appendf("sRGB Write Control : %s\n", gNY[fSRGBWriteControl]); |
| r.appendf("Two Sided Stencil Support : %s\n", gNY[fTwoSidedStencilSupport]); |
| r.appendf("Stencil Wrap Ops Support : %s\n", gNY[fStencilWrapOpsSupport]); |
| r.appendf("Discard Render Target Support : %s\n", gNY[fDiscardRenderTargetSupport]); |
| r.appendf("Reuse Scratch Textures : %s\n", gNY[fReuseScratchTextures]); |
| r.appendf("Reuse Scratch Buffers : %s\n", gNY[fReuseScratchBuffers]); |
| r.appendf("Gpu Tracing Support : %s\n", gNY[fGpuTracingSupport]); |
| r.appendf("Compressed Update Support : %s\n", gNY[fCompressedTexSubImageSupport]); |
| r.appendf("Oversized Stencil Support : %s\n", gNY[fOversizedStencilSupport]); |
| r.appendf("Texture Barrier Support : %s\n", gNY[fTextureBarrierSupport]); |
| r.appendf("Sample Locations Support : %s\n", gNY[fSampleLocationsSupport]); |
| r.appendf("Multisample disable support : %s\n", gNY[fMultisampleDisableSupport]); |
| r.appendf("Uses Mixed Samples : %s\n", gNY[fUsesMixedSamples]); |
| r.appendf("Prefer client-side dynamic buffers : %s\n", gNY[fPreferClientSideDynamicBuffers]); |
| r.appendf("Full screen clear is free : %s\n", gNY[fFullClearIsFree]); |
| r.appendf("Must clear buffer memory : %s\n", gNY[fMustClearUploadedBufferData]); |
| r.appendf("Sample shading support : %s\n", gNY[fSampleShadingSupport]); |
| r.appendf("Fence sync support : %s\n", gNY[fFenceSyncSupport]); |
| |
| r.appendf("Draw Instead of Clear [workaround] : %s\n", gNY[fUseDrawInsteadOfClear]); |
| r.appendf("Draw Instead of TexSubImage [workaround] : %s\n", |
| gNY[fUseDrawInsteadOfPartialRenderTargetWrite]); |
| r.appendf("Prefer VRAM Use over flushes [workaround] : %s\n", gNY[fPreferVRAMUseOverFlushes]); |
| |
| if (this->advancedBlendEquationSupport()) { |
| r.appendf("Advanced Blend Equation Blacklist : 0x%x\n", fAdvBlendEqBlacklist); |
| } |
| |
| r.appendf("Max Vertex Attributes : %d\n", fMaxVertexAttributes); |
| r.appendf("Max Texture Size : %d\n", fMaxTextureSize); |
| r.appendf("Max Render Target Size : %d\n", fMaxRenderTargetSize); |
| r.appendf("Max Color Sample Count : %d\n", fMaxColorSampleCount); |
| r.appendf("Max Stencil Sample Count : %d\n", fMaxStencilSampleCount); |
| r.appendf("Max Raster Samples : %d\n", fMaxRasterSamples); |
| r.appendf("Max Window Rectangles : %d\n", fMaxWindowRectangles); |
| |
| static const char* kInstancedSupportNames[] = { |
| "None", |
| "Basic", |
| "Multisampled", |
| "Mixed Sampled", |
| }; |
| GR_STATIC_ASSERT(0 == (int)InstancedSupport::kNone); |
| GR_STATIC_ASSERT(1 == (int)InstancedSupport::kBasic); |
| GR_STATIC_ASSERT(2 == (int)InstancedSupport::kMultisampled); |
| GR_STATIC_ASSERT(3 == (int)InstancedSupport::kMixedSampled); |
| GR_STATIC_ASSERT(4 == SK_ARRAY_COUNT(kInstancedSupportNames)); |
| |
| r.appendf("Instanced Support : %s\n", |
| kInstancedSupportNames[(int)fInstancedSupport]); |
| |
| static const char* kBlendEquationSupportNames[] = { |
| "Basic", |
| "Advanced", |
| "Advanced Coherent", |
| }; |
| GR_STATIC_ASSERT(0 == kBasic_BlendEquationSupport); |
| GR_STATIC_ASSERT(1 == kAdvanced_BlendEquationSupport); |
| GR_STATIC_ASSERT(2 == kAdvancedCoherent_BlendEquationSupport); |
| GR_STATIC_ASSERT(SK_ARRAY_COUNT(kBlendEquationSupportNames) == kLast_BlendEquationSupport + 1); |
| |
| r.appendf("Blend Equation Support : %s\n", |
| kBlendEquationSupportNames[fBlendEquationSupport]); |
| r.appendf("Map Buffer Support : %s\n", |
| map_flags_to_string(fMapBufferFlags).c_str()); |
| |
| static const char* kConfigNames[] = { |
| "Unknown", // kUnknown_GrPixelConfig |
| "Alpha8", // kAlpha_8_GrPixelConfig, |
| "Index8", // kIndex_8_GrPixelConfig, |
| "RGB565", // kRGB_565_GrPixelConfig, |
| "RGBA444", // kRGBA_4444_GrPixelConfig, |
| "RGBA8888", // kRGBA_8888_GrPixelConfig, |
| "BGRA8888", // kBGRA_8888_GrPixelConfig, |
| "SRGBA8888",// kSRGBA_8888_GrPixelConfig, |
| "SBGRA8888",// kSBGRA_8888_GrPixelConfig, |
| "ETC1", // kETC1_GrPixelConfig, |
| "LATC", // kLATC_GrPixelConfig, |
| "R11EAC", // kR11_EAC_GrPixelConfig, |
| "ASTC12x12",// kASTC_12x12_GrPixelConfig, |
| "RGBAFloat",// kRGBA_float_GrPixelConfig |
| "AlphaHalf",// kAlpha_half_GrPixelConfig |
| "RGBAHalf", // kRGBA_half_GrPixelConfig |
| }; |
| GR_STATIC_ASSERT(0 == kUnknown_GrPixelConfig); |
| GR_STATIC_ASSERT(1 == kAlpha_8_GrPixelConfig); |
| GR_STATIC_ASSERT(2 == kIndex_8_GrPixelConfig); |
| GR_STATIC_ASSERT(3 == kRGB_565_GrPixelConfig); |
| GR_STATIC_ASSERT(4 == kRGBA_4444_GrPixelConfig); |
| GR_STATIC_ASSERT(5 == kRGBA_8888_GrPixelConfig); |
| GR_STATIC_ASSERT(6 == kBGRA_8888_GrPixelConfig); |
| GR_STATIC_ASSERT(7 == kSRGBA_8888_GrPixelConfig); |
| GR_STATIC_ASSERT(8 == kSBGRA_8888_GrPixelConfig); |
| GR_STATIC_ASSERT(9 == kETC1_GrPixelConfig); |
| GR_STATIC_ASSERT(10 == kLATC_GrPixelConfig); |
| GR_STATIC_ASSERT(11 == kR11_EAC_GrPixelConfig); |
| GR_STATIC_ASSERT(12 == kASTC_12x12_GrPixelConfig); |
| GR_STATIC_ASSERT(13 == kRGBA_float_GrPixelConfig); |
| GR_STATIC_ASSERT(14 == kAlpha_half_GrPixelConfig); |
| GR_STATIC_ASSERT(15 == kRGBA_half_GrPixelConfig); |
| GR_STATIC_ASSERT(SK_ARRAY_COUNT(kConfigNames) == kGrPixelConfigCnt); |
| |
| SkASSERT(!this->isConfigRenderable(kUnknown_GrPixelConfig, false)); |
| SkASSERT(!this->isConfigRenderable(kUnknown_GrPixelConfig, true)); |
| |
| for (size_t i = 1; i < SK_ARRAY_COUNT(kConfigNames); ++i) { |
| GrPixelConfig config = static_cast<GrPixelConfig>(i); |
| r.appendf("%s is renderable: %s, with MSAA: %s\n", |
| kConfigNames[i], |
| gNY[this->isConfigRenderable(config, false)], |
| gNY[this->isConfigRenderable(config, true)]); |
| } |
| |
| SkASSERT(!this->isConfigTexturable(kUnknown_GrPixelConfig)); |
| |
| for (size_t i = 1; i < SK_ARRAY_COUNT(kConfigNames); ++i) { |
| GrPixelConfig config = static_cast<GrPixelConfig>(i); |
| r.appendf("%s is uploadable to a texture: %s\n", |
| kConfigNames[i], |
| gNY[this->isConfigTexturable(config)]); |
| } |
| |
| return r; |
| } |