diff options
author | Brian Osman <brianosman@google.com> | 2017-08-10 10:23:25 -0400 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-08-10 15:42:25 +0000 |
commit | 71a1889a1432715e515e000f1f4ef277e90e9ae1 (patch) | |
tree | 5965dc540193f8e9d6add43928a0985eb24bb389 | |
parent | 47238c79c4dd61c8770f45fc36d0cdbaea00b3e2 (diff) |
Revert "Revert "GrContext::dump that produces JSON formatted output""
This reverts commit 0f450acd76fd58a2f7464f99869ed6afbfac303c.
Bug: skia:
Change-Id: I97428fbbc6d82bf8b186ec5fdbf1a939c00e4126
Reviewed-on: https://skia-review.googlesource.com/32726
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
-rw-r--r-- | gn/tests.gni | 1 | ||||
-rw-r--r-- | gn/utils.gni | 1 | ||||
-rw-r--r-- | include/gpu/GrCaps.h | 5 | ||||
-rw-r--r-- | include/gpu/GrContext.h | 3 | ||||
-rw-r--r-- | include/gpu/GrShaderCaps.h | 3 | ||||
-rw-r--r-- | include/gpu/gl/GrGLExtensions.h | 3 | ||||
-rw-r--r-- | src/gpu/GrCaps.cpp | 109 | ||||
-rw-r--r-- | src/gpu/GrContext.cpp | 39 | ||||
-rw-r--r-- | src/gpu/GrGpu.cpp | 11 | ||||
-rw-r--r-- | src/gpu/GrGpu.h | 4 | ||||
-rw-r--r-- | src/gpu/GrShaderCaps.cpp | 116 | ||||
-rw-r--r-- | src/gpu/gl/GrGLCaps.cpp | 120 | ||||
-rw-r--r-- | src/gpu/gl/GrGLCaps.h | 5 | ||||
-rw-r--r-- | src/gpu/gl/GrGLExtensions.cpp | 13 | ||||
-rw-r--r-- | src/gpu/gl/GrGLGpu.cpp | 44 | ||||
-rw-r--r-- | src/gpu/gl/GrGLGpu.h | 2 | ||||
-rw-r--r-- | src/utils/SkJSONWriter.cpp | 43 | ||||
-rw-r--r-- | src/utils/SkJSONWriter.h | 24 | ||||
-rw-r--r-- | tests/GrContextFactoryTest.cpp | 6 | ||||
-rw-r--r-- | tests/GrDrawTargetTest.cpp | 23 |
20 files changed, 329 insertions, 246 deletions
diff --git a/gn/tests.gni b/gn/tests.gni index 3edb3e3f49..26bdc94745 100644 --- a/gn/tests.gni +++ b/gn/tests.gni @@ -89,7 +89,6 @@ tests_sources = [ "$_tests/GrAllocatorTest.cpp", "$_tests/GrContextAbandonTest.cpp", "$_tests/GrContextFactoryTest.cpp", - "$_tests/GrDrawTargetTest.cpp", "$_tests/GrMemoryPoolTest.cpp", "$_tests/GrMeshTest.cpp", "$_tests/GrPipelineDynamicStateTest.cpp", diff --git a/gn/utils.gni b/gn/utils.gni index faab5d9e1b..a8ceba2968 100644 --- a/gn/utils.gni +++ b/gn/utils.gni @@ -45,6 +45,7 @@ skia_utils_sources = [ "$_src/utils/SkInsetConvexPolygon.cpp", "$_src/utils/SkInsetConvexPolygon.h", "$_src/utils/SkInterpolator.cpp", + "$_src/utils/SkJSONWriter.cpp", "$_src/utils/SkJSONWriter.h", "$_src/utils/SkMatrix22.cpp", "$_src/utils/SkMatrix22.h", diff --git a/include/gpu/GrCaps.h b/include/gpu/GrCaps.h index 0990ecb105..65df09251a 100644 --- a/include/gpu/GrCaps.h +++ b/include/gpu/GrCaps.h @@ -16,6 +16,7 @@ struct GrContextOptions; class GrRenderTargetProxy; +class SkJSONWriter; /** * Represents the capabilities of a GrContext. @@ -24,7 +25,8 @@ class GrCaps : public SkRefCnt { public: GrCaps(const GrContextOptions&); - virtual SkString dump() const; + void dumpJSON(SkJSONWriter*) const; + const GrShaderCaps* shaderCaps() const { return fShaderCaps.get(); } bool npotTextureTileSupport() const { return fNPOTTextureTileSupport; } @@ -238,6 +240,7 @@ protected: private: virtual void onApplyOptionsOverrides(const GrContextOptions&) {} + virtual void onDumpJSON(SkJSONWriter*) const {} bool fSuppressPrints : 1; bool fWireframeMode : 1; diff --git a/include/gpu/GrContext.h b/include/gpu/GrContext.h index 7a14a7d990..233a54f0b3 100644 --- a/include/gpu/GrContext.h +++ b/include/gpu/GrContext.h @@ -310,6 +310,9 @@ public: void dumpGpuStatsKeyValuePairs(SkTArray<SkString>* keys, SkTArray<double>* values) const; void printGpuStats() const; + /** Returns a string with detailed information about the context & GPU, in JSON format. */ + SkString dump() const; + /** Specify the TextBlob cache limit. If the current cache exceeds this limit it will purge. this is for testing only */ void setTextBlobCacheLimit_ForTesting(size_t bytes); diff --git a/include/gpu/GrShaderCaps.h b/include/gpu/GrShaderCaps.h index 214d45e4c4..f2c6aaeccb 100644 --- a/include/gpu/GrShaderCaps.h +++ b/include/gpu/GrShaderCaps.h @@ -16,6 +16,7 @@ namespace SkSL { class ShaderCapsFactory; } struct GrContextOptions; +class SkJSONWriter; class GrShaderCaps : public SkRefCnt { public: @@ -68,7 +69,7 @@ public: GrShaderCaps(const GrContextOptions&); - SkString dump() const; + void dumpJSON(SkJSONWriter*) const; bool shaderDerivativeSupport() const { return fShaderDerivativeSupport; } bool geometryShaderSupport() const { return fGeometryShaderSupport; } diff --git a/include/gpu/gl/GrGLExtensions.h b/include/gpu/gl/GrGLExtensions.h index faf73fd36c..0355ad292d 100644 --- a/include/gpu/gl/GrGLExtensions.h +++ b/include/gpu/gl/GrGLExtensions.h @@ -13,6 +13,7 @@ #include "SkString.h" struct GrGLInterface; +class SkJSONWriter; /** * This helper queries the current GL context for its extensions, remembers them, and can be @@ -64,7 +65,7 @@ public: void reset() { fStrings->reset(); } - void print(const char* sep = "\n") const; + void dumpJSON(SkJSONWriter*) const; private: bool fInitialized; diff --git a/src/gpu/GrCaps.cpp b/src/gpu/GrCaps.cpp index 67a8e6859b..00475e63ca 100644 --- a/src/gpu/GrCaps.cpp +++ b/src/gpu/GrCaps.cpp @@ -8,6 +8,7 @@ #include "GrCaps.h" #include "GrContextOptions.h" #include "GrWindowRectangles.h" +#include "SkJSONWriter.h" static const char* pixel_config_name(GrPixelConfig config) { switch (config) { @@ -116,44 +117,45 @@ static SkString map_flags_to_string(uint32_t 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("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("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("Instance Attrib Support : %s\n", gNY[fInstanceAttribSupport]); - 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("Cross context texture support : %s\n", gNY[fCrossContextTextureSupport]); - - r.appendf("Draw Instead of Clear [workaround] : %s\n", gNY[fUseDrawInsteadOfClear]); - r.appendf("Prefer VRAM Use over flushes [workaround] : %s\n", gNY[fPreferVRAMUseOverFlushes]); +void GrCaps::dumpJSON(SkJSONWriter* writer) const { + writer->beginObject(); + + writer->appendBool("MIP Map Support", fMipMapSupport); + writer->appendBool("NPOT Texture Tile Support", fNPOTTextureTileSupport); + writer->appendBool("sRGB Support", fSRGBSupport); + writer->appendBool("sRGB Write Control", fSRGBWriteControl); + writer->appendBool("sRGB Decode Disable", fSRGBDecodeDisableSupport); + writer->appendBool("Discard Render Target Support", fDiscardRenderTargetSupport); + writer->appendBool("Reuse Scratch Textures", fReuseScratchTextures); + writer->appendBool("Reuse Scratch Buffers", fReuseScratchBuffers); + writer->appendBool("Gpu Tracing Support", fGpuTracingSupport); + writer->appendBool("Oversized Stencil Support", fOversizedStencilSupport); + writer->appendBool("Texture Barrier Support", fTextureBarrierSupport); + writer->appendBool("Sample Locations Support", fSampleLocationsSupport); + writer->appendBool("Multisample disable support", fMultisampleDisableSupport); + writer->appendBool("Instance Attrib Support", fInstanceAttribSupport); + writer->appendBool("Uses Mixed Samples", fUsesMixedSamples); + writer->appendBool("Prefer client-side dynamic buffers", fPreferClientSideDynamicBuffers); + writer->appendBool("Full screen clear is free", fFullClearIsFree); + writer->appendBool("Must clear buffer memory", fMustClearUploadedBufferData); + writer->appendBool("Sample shading support", fSampleShadingSupport); + writer->appendBool("Fence sync support", fFenceSyncSupport); + writer->appendBool("Cross context texture support", fCrossContextTextureSupport); + + writer->appendBool("Draw Instead of Clear [workaround]", fUseDrawInsteadOfClear); + writer->appendBool("Prefer VRAM Use over flushes [workaround]", fPreferVRAMUseOverFlushes); if (this->advancedBlendEquationSupport()) { - r.appendf("Advanced Blend Equation Blacklist : 0x%x\n", fAdvBlendEqBlacklist); + writer->appendHexU32("Advanced Blend Equation Blacklist", 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); + writer->appendS32("Max Vertex Attributes", fMaxVertexAttributes); + writer->appendS32("Max Texture Size", fMaxTextureSize); + writer->appendS32("Max Render Target Size", fMaxRenderTargetSize); + writer->appendS32("Max Color Sample Count", fMaxColorSampleCount); + writer->appendS32("Max Stencil Sample Count", fMaxStencilSampleCount); + writer->appendS32("Max Raster Samples", fMaxRasterSamples); + writer->appendS32("Max Window Rectangles", fMaxWindowRectangles); static const char* kInstancedSupportNames[] = { "None", @@ -167,8 +169,7 @@ SkString GrCaps::dump() const { GR_STATIC_ASSERT(3 == (int)InstancedSupport::kMixedSampled); GR_STATIC_ASSERT(4 == SK_ARRAY_COUNT(kInstancedSupportNames)); - r.appendf("Instanced Support : %s\n", - kInstancedSupportNames[(int)fInstancedSupport]); + writer->appendString("Instanced Support", kInstancedSupportNames[(int)fInstancedSupport]); static const char* kBlendEquationSupportNames[] = { "Basic", @@ -180,30 +181,32 @@ SkString GrCaps::dump() const { 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()); + writer->appendString("Blend Equation Support", + kBlendEquationSupportNames[fBlendEquationSupport]); + writer->appendString("Map Buffer Support", map_flags_to_string(fMapBufferFlags).c_str()); SkASSERT(!this->isConfigRenderable(kUnknown_GrPixelConfig, false)); SkASSERT(!this->isConfigRenderable(kUnknown_GrPixelConfig, true)); + SkASSERT(!this->isConfigTexturable(kUnknown_GrPixelConfig)); + + writer->beginArray("configs"); - for (size_t i = 1; i < kGrPixelConfigCnt; ++i) { + for (size_t i = 1; i < kGrPixelConfigCnt; ++i) { GrPixelConfig config = static_cast<GrPixelConfig>(i); - r.appendf("%s is renderable: %s, with MSAA: %s\n", - pixel_config_name(config), - gNY[this->isConfigRenderable(config, false)], - gNY[this->isConfigRenderable(config, true)]); + writer->beginObject(); + writer->appendString("name", pixel_config_name(config)); + writer->appendBool("renderable", this->isConfigRenderable(config, false)); + writer->appendBool("renderableMSAA", this->isConfigRenderable(config, true)); + writer->appendBool("texturable", this->isConfigTexturable(config)); + writer->endObject(); } - SkASSERT(!this->isConfigTexturable(kUnknown_GrPixelConfig)); + writer->endArray(); - for (size_t i = 1; i < kGrPixelConfigCnt; ++i) { - GrPixelConfig config = static_cast<GrPixelConfig>(i); - r.appendf("%s is uploadable to a texture: %s\n", - pixel_config_name(config), - gNY[this->isConfigTexturable(config)]); - } + this->onDumpJSON(writer); + + writer->appendName("shaderCaps"); + this->shaderCaps()->dumpJSON(writer); - return r; + writer->endObject(); } diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp index a0cf5f5da8..efa8e8c610 100644 --- a/src/gpu/GrContext.cpp +++ b/src/gpu/GrContext.cpp @@ -26,6 +26,7 @@ #include "GrTracing.h" #include "SkConvertPixels.h" #include "SkGr.h" +#include "SkJSONWriter.h" #include "SkUnPreMultiplyPriv.h" #include "effects/GrConfigConversionEffect.h" #include "text/GrTextBlobCache.h" @@ -993,3 +994,41 @@ void GrContext::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const { ASSERT_SINGLE_OWNER fResourceCache->dumpMemoryStatistics(traceMemoryDump); } + +////////////////////////////////////////////////////////////////////////////// + +SkString GrContext::dump() const { + SkDynamicMemoryWStream stream; + SkJSONWriter writer(&stream, SkJSONWriter::Mode::kPretty); + writer.beginObject(); + + static const char* kBackendStr[] = { + "Metal", + "OpenGL", + "Vulkan", + "Mock", + }; + GR_STATIC_ASSERT(0 == kMetal_GrBackend); + GR_STATIC_ASSERT(1 == kOpenGL_GrBackend); + GR_STATIC_ASSERT(2 == kVulkan_GrBackend); + GR_STATIC_ASSERT(3 == kMock_GrBackend); + writer.appendString("backend", kBackendStr[fBackend]); + + writer.appendName("caps"); + fCaps->dumpJSON(&writer); + + writer.appendName("gpu"); + fGpu->dumpJSON(&writer); + + // Flush JSON to the memory stream + writer.endObject(); + writer.flush(); + + // Null terminate the JSON data in the memory stream + stream.write8(0); + + // Allocate a string big enough to hold all the data, then copy out of the stream + SkString result(stream.bytesWritten()); + stream.copyToAndReset(result.writable_str()); + return result; +} diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp index f237cce360..50a05c86c9 100644 --- a/src/gpu/GrGpu.cpp +++ b/src/gpu/GrGpu.cpp @@ -26,6 +26,7 @@ #include "GrSurfacePriv.h" #include "GrTexturePriv.h" #include "GrTracing.h" +#include "SkJSONWriter.h" #include "SkMathPriv.h" //////////////////////////////////////////////////////////////////////////////// @@ -538,3 +539,13 @@ GrSemaphoresSubmitted GrGpu::finishFlush(int numSemaphores, return this->caps()->fenceSyncSupport() ? GrSemaphoresSubmitted::kYes : GrSemaphoresSubmitted::kNo; } + +void GrGpu::dumpJSON(SkJSONWriter* writer) const { + writer->beginObject(); + + // TODO: Is there anything useful in the base class to dump here? + + this->onDumpJSON(writer); + + writer->endObject(); +} diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h index fa5f372e14..cc55a05722 100644 --- a/src/gpu/GrGpu.h +++ b/src/gpu/GrGpu.h @@ -40,6 +40,7 @@ class GrStencilAttachment; class GrStencilSettings; class GrSurface; class GrTexture; +class SkJSONWriter; namespace gr_instanced { class InstancedOp; @@ -458,6 +459,7 @@ public: }; Stats* stats() { return &fStats; } + void dumpJSON(SkJSONWriter*) const; /** Creates a texture directly in the backend API without wrapping it in a GrTexture. This is only to be used for testing (particularly for testing the methods that import an externally @@ -619,6 +621,8 @@ private: virtual void onFinishFlush(bool insertedSemaphores) = 0; + virtual void onDumpJSON(SkJSONWriter*) const {} + void resetContext() { this->onResetContext(fResetBits); fResetBits = 0; diff --git a/src/gpu/GrShaderCaps.cpp b/src/gpu/GrShaderCaps.cpp index 5055b24887..03495e98c3 100644 --- a/src/gpu/GrShaderCaps.cpp +++ b/src/gpu/GrShaderCaps.cpp @@ -9,6 +9,7 @@ #include "GrShaderCaps.h" #include "GrContextOptions.h" +#include "SkJSONWriter.h" //////////////////////////////////////////////////////////////////////////////////////////// @@ -95,33 +96,36 @@ GrShaderCaps::GrShaderCaps(const GrContextOptions& options) { fAdvBlendEqInteraction = kNotSupported_AdvBlendEqInteraction; } -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("Image Load Store Support : %s\n", gNY[fImageLoadStoreSupport]); +void GrShaderCaps::dumpJSON(SkJSONWriter* writer) const { + writer->beginObject(); - r.appendf("Shader Float Precisions (varies: %s):\n", gNY[fShaderPrecisionVaries]); + writer->appendBool("Shader Derivative Support", fShaderDerivativeSupport); + writer->appendBool("Geometry Shader Support", fGeometryShaderSupport); + writer->appendBool("Path Rendering Support", fPathRenderingSupport); + writer->appendBool("Dst Read In Shader Support", fDstReadInShaderSupport); + writer->appendBool("Dual Source Blending Support", fDualSourceBlendingSupport); + writer->appendBool("Integer Support", fIntegerSupport); + writer->appendBool("Texel Buffer Support", fTexelBufferSupport); + writer->appendBool("Image Load Store Support", fImageLoadStoreSupport); + + writer->appendBool("Variable Precision", fShaderPrecisionVaries); for (int s = 0; s < kGrShaderTypeCount; ++s) { GrShaderType shaderType = static_cast<GrShaderType>(s); - r.appendf("\t%s:\n", shader_type_to_string(shaderType)); + writer->beginArray(SkStringPrintf("%s precisions", + shader_type_to_string(shaderType)).c_str()); 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); + writer->beginObject(); + writer->appendString("precision", precision_to_string(precision)); + writer->appendS32("log_low", fFloatPrecisions[s][p].fLogRangeLow); + writer->appendS32("log_high", fFloatPrecisions[s][p].fLogRangeHigh); + writer->appendS32("bits", fFloatPrecisions[s][p].fBits); + writer->endObject(); } } + writer->endArray(); } static const char* kAdvBlendEqInteractionStr[] = { @@ -136,47 +140,41 @@ SkString GrShaderCaps::dump() const { GR_STATIC_ASSERT(3 == kSpecificEnables_AdvBlendEqInteraction); GR_STATIC_ASSERT(SK_ARRAY_COUNT(kAdvBlendEqInteractionStr) == kLast_AdvBlendEqInteraction + 1); - r.appendf("--- GLSL-Specific ---\n"); - - r.appendf("FB Fetch Support: %s\n", (fFBFetchSupport ? "YES" : "NO")); - r.appendf("Drops tile on zero divide: %s\n", (fDropsTileOnZeroDivide ? "YES" : "NO")); - r.appendf("Bindless texture support: %s\n", (fBindlessTextureSupport ? "YES" : "NO")); - r.appendf("Uses precision modifiers: %s\n", (fUsesPrecisionModifiers ? "YES" : "NO")); - r.appendf("Can use any() function: %s\n", (fCanUseAnyFunctionInShader ? "YES" : "NO")); - r.appendf("Can use min() and abs() together: %s\n", (fCanUseMinAndAbsTogether ? "YES" : "NO")); - r.appendf("Can use fract() for negative values: %s\n", (fCanUseFractForNegativeValues ? - "YES" : "NO")); - r.appendf("Must force negated atan param to float: %s\n", (fMustForceNegatedAtanParamToFloat ? - "YES" : "NO")); - r.appendf("Must use local out color for FBFetch: %s\n", (fRequiresLocalOutputColorForFBFetch ? - "YES" : "NO")); - r.appendf("Must implement geo shader invocations with loop : %s\n", - (fMustImplementGSInvocationsWithLoop ? "YES" : "NO")); - r.appendf("Must obfuscate uniform color: %s\n", (fMustObfuscateUniformColor ? "YES" : "NO")); - r.appendf("Must guard division even after explicit zero check: %s\n", - (fMustGuardDivisionEvenAfterExplicitZeroCheck ? "YES" : "NO")); - r.appendf("Flat interpolation support: %s\n", (fFlatInterpolationSupport ? "YES" : "NO")); - r.appendf("No perspective interpolation support: %s\n", (fNoPerspectiveInterpolationSupport ? - "YES" : "NO")); - r.appendf("Multisample interpolation support: %s\n", (fMultisampleInterpolationSupport ? - "YES" : "NO")); - r.appendf("Sample variables support: %s\n", (fSampleVariablesSupport ? "YES" : "NO")); - r.appendf("Sample mask override coverage support: %s\n", (fSampleMaskOverrideCoverageSupport ? - "YES" : "NO")); - r.appendf("External texture support: %s\n", (fExternalTextureSupport ? "YES" : "NO")); - r.appendf("texelFetch support: %s\n", (fTexelFetchSupport ? "YES" : "NO")); - r.appendf("sk_VertexID support: %s\n", (fVertexIDSupport ? "YES" : "NO")); - r.appendf("Max VS Samplers: %d\n", fMaxVertexSamplers); - r.appendf("Max GS Samplers: %d\n", fMaxGeometrySamplers); - r.appendf("Max FS Samplers: %d\n", fMaxFragmentSamplers); - r.appendf("Max Combined Samplers: %d\n", fMaxFragmentSamplers); - r.appendf("Max VS Image Storages: %d\n", fMaxVertexImageStorages); - r.appendf("Max GS Image Storages: %d\n", fMaxGeometryImageStorages); - r.appendf("Max FS Image Storages: %d\n", fMaxFragmentImageStorages); - r.appendf("Max Combined Image Storages: %d\n", fMaxFragmentImageStorages); - r.appendf("Advanced blend equation interaction: %s\n", - kAdvBlendEqInteractionStr[fAdvBlendEqInteraction]); - return r; + writer->appendBool("FB Fetch Support", fFBFetchSupport); + writer->appendBool("Drops tile on zero divide", fDropsTileOnZeroDivide); + writer->appendBool("Bindless texture support", fBindlessTextureSupport); + writer->appendBool("Uses precision modifiers", fUsesPrecisionModifiers); + writer->appendBool("Can use any() function", fCanUseAnyFunctionInShader); + writer->appendBool("Can use min() and abs() together", fCanUseMinAndAbsTogether); + writer->appendBool("Can use fract() for negative values", fCanUseFractForNegativeValues); + writer->appendBool("Must force negated atan param to float", fMustForceNegatedAtanParamToFloat); + writer->appendBool("Must use local out color for FBFetch", fRequiresLocalOutputColorForFBFetch); + writer->appendBool("Must implement geo shader invocations with loop", + fMustImplementGSInvocationsWithLoop); + writer->appendBool("Must obfuscate uniform color", fMustObfuscateUniformColor); + writer->appendBool("Must guard division even after explicit zero check", + fMustGuardDivisionEvenAfterExplicitZeroCheck); + writer->appendBool("Flat interpolation support", fFlatInterpolationSupport); + writer->appendBool("No perspective interpolation support", fNoPerspectiveInterpolationSupport); + writer->appendBool("Multisample interpolation support", fMultisampleInterpolationSupport); + writer->appendBool("Sample variables support", fSampleVariablesSupport); + writer->appendBool("Sample mask override coverage support", fSampleMaskOverrideCoverageSupport); + writer->appendBool("External texture support", fExternalTextureSupport); + writer->appendBool("texelFetch support", fTexelFetchSupport); + writer->appendBool("sk_VertexID support", fVertexIDSupport); + + writer->appendS32("Max VS Samplers", fMaxVertexSamplers); + writer->appendS32("Max GS Samplers", fMaxGeometrySamplers); + writer->appendS32("Max FS Samplers", fMaxFragmentSamplers); + writer->appendS32("Max Combined Samplers", fMaxFragmentSamplers); + writer->appendS32("Max VS Image Storages", fMaxVertexImageStorages); + writer->appendS32("Max GS Image Storages", fMaxGeometryImageStorages); + writer->appendS32("Max FS Image Storages", fMaxFragmentImageStorages); + writer->appendS32("Max Combined Image Storages", fMaxFragmentImageStorages); + writer->appendString("Advanced blend equation interaction", + kAdvBlendEqInteractionStr[fAdvBlendEqInteraction]); + + writer->endObject(); } void GrShaderCaps::initSamplerPrecisionTable() { diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp index 04559c3dbd..b90eefb19a 100644 --- a/src/gpu/gl/GrGLCaps.cpp +++ b/src/gpu/gl/GrGLCaps.cpp @@ -12,6 +12,7 @@ #include "GrGLTexture.h" #include "GrShaderCaps.h" #include "GrSurfaceProxyPriv.h" +#include "SkJSONWriter.h" #include "SkTSearch.h" #include "SkTSort.h" #include "instanced/GLInstancedRendering.h" @@ -1248,18 +1249,23 @@ void GrGLCaps::initStencilSupport(const GrGLContextInfo& ctxInfo) { } } -SkString GrGLCaps::dump() const { +void GrGLCaps::onDumpJSON(SkJSONWriter* writer) const { - SkString r = INHERITED::dump(); + // We are called by the base class, which has already called beginObject(). We choose to nest + // all of our caps information in a named sub-object. + writer->beginObject("GL caps"); + + writer->beginArray("Stencil Formats"); - r.appendf("--- GL-Specific ---\n"); for (int i = 0; i < fStencilFormats.count(); ++i) { - r.appendf("Stencil Format %d, stencil bits: %02d, total bits: %02d\n", - i, - fStencilFormats[i].fStencilBits, - fStencilFormats[i].fTotalBits); + writer->beginObject(); + writer->appendS32("stencil bits", fStencilFormats[i].fStencilBits); + writer->appendS32("total bits", fStencilFormats[i].fTotalBits); + writer->endObject(); } + writer->endArray(); + static const char* kMSFBOExtStr[] = { "None", "Standard", @@ -1298,55 +1304,59 @@ SkString GrGLCaps::dump() const { GR_STATIC_ASSERT(3 == kChromium_MapBufferType); GR_STATIC_ASSERT(SK_ARRAY_COUNT(kMapBufferTypeStr) == kLast_MapBufferType + 1); - r.appendf("Core Profile: %s\n", (fIsCoreProfile ? "YES" : "NO")); - r.appendf("MSAA Type: %s\n", kMSFBOExtStr[fMSFBOType]); - r.appendf("Invalidate FB Type: %s\n", kInvalidateFBTypeStr[fInvalidateFBType]); - r.appendf("Map Buffer Type: %s\n", kMapBufferTypeStr[fMapBufferType]); - r.appendf("Max FS Uniform Vectors: %d\n", fMaxFragmentUniformVectors); - r.appendf("Unpack Row length support: %s\n", (fUnpackRowLengthSupport ? "YES": "NO")); - r.appendf("Unpack Flip Y support: %s\n", (fUnpackFlipYSupport ? "YES": "NO")); - r.appendf("Pack Row length support: %s\n", (fPackRowLengthSupport ? "YES": "NO")); - r.appendf("Pack Flip Y support: %s\n", (fPackFlipYSupport ? "YES": "NO")); - - r.appendf("Texture Usage support: %s\n", (fTextureUsageSupport ? "YES": "NO")); - r.appendf("GL_R support: %s\n", (fTextureRedSupport ? "YES": "NO")); - r.appendf("Alpha8 is renderable: %s\n", (fAlpha8IsRenderable ? "YES" : "NO")); - r.appendf("GL_ARB_imaging support: %s\n", (fImagingSupport ? "YES": "NO")); - r.appendf("Vertex array object support: %s\n", (fVertexArrayObjectSupport ? "YES": "NO")); - r.appendf("Direct state access support: %s\n", (fDirectStateAccessSupport ? "YES": "NO")); - r.appendf("Debug support: %s\n", (fDebugSupport ? "YES": "NO")); - r.appendf("Draw indirect support: %s\n", (fDrawIndirectSupport ? "YES" : "NO")); - r.appendf("Multi draw indirect support: %s\n", (fMultiDrawIndirectSupport ? "YES" : "NO")); - r.appendf("Base instance support: %s\n", (fBaseInstanceSupport ? "YES" : "NO")); - r.appendf("RGBA 8888 pixel ops are slow: %s\n", (fRGBA8888PixelsOpsAreSlow ? "YES" : "NO")); - r.appendf("Partial FBO read is slow: %s\n", (fPartialFBOReadIsSlow ? "YES" : "NO")); - r.appendf("Bind uniform location support: %s\n", (fBindUniformLocationSupport ? "YES" : "NO")); - r.appendf("Rectangle texture support: %s\n", (fRectangleTextureSupport? "YES" : "NO")); - r.appendf("Texture swizzle support: %s\n", (fTextureSwizzleSupport ? "YES" : "NO")); - r.appendf("BGRA to RGBA readback conversions are slow: %s\n", - (fRGBAToBGRAReadbackConversionsAreSlow ? "YES" : "NO")); - r.appendf("Intermediate texture for partial updates of unorm textures ever bound to FBOs: %s\n", - fDisallowTexSubImageForUnormConfigTexturesEverBoundToFBO ? "YES" : "NO"); - r.appendf("Intermediate texture for all updates of textures bound to FBOs: %s\n", - fUseDrawInsteadOfAllRenderTargetWrites ? "YES" : "NO"); - - r.append("Configs\n-------\n"); + writer->appendBool("Core Profile", fIsCoreProfile); + writer->appendString("MSAA Type", kMSFBOExtStr[fMSFBOType]); + writer->appendString("Invalidate FB Type", kInvalidateFBTypeStr[fInvalidateFBType]); + writer->appendString("Map Buffer Type", kMapBufferTypeStr[fMapBufferType]); + writer->appendS32("Max FS Uniform Vectors", fMaxFragmentUniformVectors); + writer->appendBool("Unpack Row length support", fUnpackRowLengthSupport); + writer->appendBool("Unpack Flip Y support", fUnpackFlipYSupport); + writer->appendBool("Pack Row length support", fPackRowLengthSupport); + writer->appendBool("Pack Flip Y support", fPackFlipYSupport); + + writer->appendBool("Texture Usage support", fTextureUsageSupport); + writer->appendBool("GL_R support", fTextureRedSupport); + writer->appendBool("Alpha8 is renderable", fAlpha8IsRenderable); + writer->appendBool("GL_ARB_imaging support", fImagingSupport); + writer->appendBool("Vertex array object support", fVertexArrayObjectSupport); + writer->appendBool("Direct state access support", fDirectStateAccessSupport); + writer->appendBool("Debug support", fDebugSupport); + writer->appendBool("Draw indirect support", fDrawIndirectSupport); + writer->appendBool("Multi draw indirect support", fMultiDrawIndirectSupport); + writer->appendBool("Base instance support", fBaseInstanceSupport); + writer->appendBool("RGBA 8888 pixel ops are slow", fRGBA8888PixelsOpsAreSlow); + writer->appendBool("Partial FBO read is slow", fPartialFBOReadIsSlow); + writer->appendBool("Bind uniform location support", fBindUniformLocationSupport); + writer->appendBool("Rectangle texture support", fRectangleTextureSupport); + writer->appendBool("Texture swizzle support", fTextureSwizzleSupport); + writer->appendBool("BGRA to RGBA readback conversions are slow", + fRGBAToBGRAReadbackConversionsAreSlow); + writer->appendBool("Intermediate texture for partial updates of unorm textures ever bound to FBOs", + fDisallowTexSubImageForUnormConfigTexturesEverBoundToFBO); + writer->appendBool("Intermediate texture for all updates of textures bound to FBOs", + fUseDrawInsteadOfAllRenderTargetWrites); + + writer->beginArray("configs"); + for (int i = 0; i < kGrPixelConfigCnt; ++i) { - r.appendf(" cfg: %d flags: 0x%04x, b_internal: 0x%08x s_internal: 0x%08x, e_format: " - "0x%08x, e_format_teximage: 0x%08x, e_type: 0x%08x, i_for_teximage: 0x%08x, " - "i_for_renderbuffer: 0x%08x\n", - i, - fConfigTable[i].fFlags, - fConfigTable[i].fFormats.fBaseInternalFormat, - fConfigTable[i].fFormats.fSizedInternalFormat, - fConfigTable[i].fFormats.fExternalFormat[kOther_ExternalFormatUsage], - fConfigTable[i].fFormats.fExternalFormat[kTexImage_ExternalFormatUsage], - fConfigTable[i].fFormats.fExternalType, - fConfigTable[i].fFormats.fInternalFormatTexImage, - fConfigTable[i].fFormats.fInternalFormatRenderbuffer); - } - - return r; + writer->beginObject(); + writer->appendHexU32("flags", fConfigTable[i].fFlags); + writer->appendHexU32("b_internal", fConfigTable[i].fFormats.fBaseInternalFormat); + writer->appendHexU32("s_internal", fConfigTable[i].fFormats.fSizedInternalFormat); + writer->appendHexU32("e_format", + fConfigTable[i].fFormats.fExternalFormat[kOther_ExternalFormatUsage]); + writer->appendHexU32( + "e_format_teximage", + fConfigTable[i].fFormats.fExternalFormat[kTexImage_ExternalFormatUsage]); + writer->appendHexU32("e_type", fConfigTable[i].fFormats.fExternalType); + writer->appendHexU32("i_for_teximage", fConfigTable[i].fFormats.fInternalFormatTexImage); + writer->appendHexU32("i_for_renderbuffer", + fConfigTable[i].fFormats.fInternalFormatRenderbuffer); + writer->endObject(); + } + + writer->endArray(); + writer->endObject(); } static GrGLenum precision_to_gl_float_type(GrSLPrecision p) { diff --git a/src/gpu/gl/GrGLCaps.h b/src/gpu/gl/GrGLCaps.h index 104308a9ce..1ce6094a6b 100644 --- a/src/gpu/gl/GrGLCaps.h +++ b/src/gpu/gl/GrGLCaps.h @@ -348,10 +348,7 @@ public: bool srgbDecodeDisableAffectsMipmaps() const { return fSRGBDecodeDisableAffectsMipmaps; } - /** - * Returns a string containing the caps info. - */ - SkString dump() const override; + void onDumpJSON(SkJSONWriter*) const override; bool rgba8888PixelsOpsAreSlow() const { return fRGBA8888PixelsOpsAreSlow; } bool partialFBOReadIsSlow() const { return fPartialFBOReadIsSlow; } diff --git a/src/gpu/gl/GrGLExtensions.cpp b/src/gpu/gl/GrGLExtensions.cpp index 29f7799462..c4f6475293 100644 --- a/src/gpu/gl/GrGLExtensions.cpp +++ b/src/gpu/gl/GrGLExtensions.cpp @@ -9,6 +9,7 @@ #include "gl/GrGLDefines.h" #include "gl/GrGLUtil.h" +#include "SkJSONWriter.h" #include "SkMakeUnique.h" #include "SkTSearch.h" #include "SkTSort.h" @@ -146,12 +147,10 @@ void GrGLExtensions::add(const char ext[]) { } } -void GrGLExtensions::print(const char* sep) const { - if (nullptr == sep) { - sep = " "; - } - int cnt = fStrings->count(); - for (int i = 0; i < cnt; ++i) { - SkDebugf("%s%s", (*fStrings)[i].c_str(), (i < cnt - 1) ? sep : ""); +void GrGLExtensions::dumpJSON(SkJSONWriter* writer) const { + writer->beginArray(); + for (int i = 0; i < fStrings->count(); ++i) { + writer->appendString((*fStrings)[i].c_str()); } + writer->endArray(); } diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp index c20cdf048f..2ce2995021 100644 --- a/src/gpu/gl/GrGLGpu.cpp +++ b/src/gpu/gl/GrGLGpu.cpp @@ -27,6 +27,7 @@ #include "GrTexturePriv.h" #include "GrTypes.h" #include "SkAutoMalloc.h" +#include "SkJSONWriter.h" #include "SkMakeUnique.h" #include "SkMipMap.h" #include "SkPixmap.h" @@ -208,8 +209,6 @@ GrGpu* GrGLGpu::Create(const GrGLInterface* interface, const GrContextOptions& o return nullptr; } -static bool gPrintStartupSpew; - GrGLGpu::GrGLGpu(GrGLContext* ctx, GrContext* context) : GrGpu(context) , fGLContext(ctx) @@ -258,26 +257,6 @@ GrGLGpu::GrGLGpu(GrGLContext* ctx, GrContext* context) } GrGLClearErr(this->glInterface()); - if (gPrintStartupSpew) { - const GrGLubyte* vendor; - const GrGLubyte* renderer; - const GrGLubyte* version; - const GrGLubyte* glslVersion; - GL_CALL_RET(vendor, GetString(GR_GL_VENDOR)); - GL_CALL_RET(renderer, GetString(GR_GL_RENDERER)); - GL_CALL_RET(version, GetString(GR_GL_VERSION)); - GL_CALL_RET(glslVersion, GetString(GR_GL_SHADING_LANGUAGE_VERSION)); - SkDebugf("------------------------- create GrGLGpu %p --------------\n", - this); - SkDebugf("------ VENDOR %s\n", vendor); - SkDebugf("------ RENDERER %s\n", renderer); - SkDebugf("------ VERSION %s\n", version); - SkDebugf("------ SHADING LANGUAGE VERSION %s\n", glslVersion); - SkDebugf("------ EXTENSIONS\n"); - this->glContext().extensions().print(); - SkDebugf("\n"); - SkDebugf("%s", this->glCaps().dump().c_str()); - } } GrGLGpu::~GrGLGpu() { @@ -4424,3 +4403,24 @@ int GrGLGpu::TextureToCopyProgramIdx(GrTexture* texture) { return 0; } } + +void GrGLGpu::onDumpJSON(SkJSONWriter* writer) const { + // We are called by the base class, which has already called beginObject(). We choose to nest + // all of our caps information in a named sub-object. + writer->beginObject("GL GPU"); + + const GrGLubyte* str; + GL_CALL_RET(str, GetString(GR_GL_VERSION)); + writer->appendString("GL_VERSION", (const char*)(str)); + GL_CALL_RET(str, GetString(GR_GL_RENDERER)); + writer->appendString("GL_RENDERER", (const char*)(str)); + GL_CALL_RET(str, GetString(GR_GL_VENDOR)); + writer->appendString("GL_VENDOR", (const char*)(str)); + GL_CALL_RET(str, GetString(GR_GL_SHADING_LANGUAGE_VERSION)); + writer->appendString("GL_SHADING_LANGUAGE_VERSION", (const char*)(str)); + + writer->appendName("extensions"); + glInterface()->fExtensions.dumpJSON(writer); + + writer->endObject(); +} diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h index 7ff822fdec..aafcc37a57 100644 --- a/src/gpu/gl/GrGLGpu.h +++ b/src/gpu/gl/GrGLGpu.h @@ -409,6 +409,8 @@ private: // Must be called if bindSurfaceFBOForPixelOps was used to bind a surface for copying. void unbindTextureFBOForPixelOps(GrGLenum fboTarget, GrSurface* surface); + void onDumpJSON(SkJSONWriter*) const override; + sk_sp<GrGLContext> fGLContext; bool createCopyProgram(GrTexture* srcTexture); diff --git a/src/utils/SkJSONWriter.cpp b/src/utils/SkJSONWriter.cpp new file mode 100644 index 0000000000..3b92aa4576 --- /dev/null +++ b/src/utils/SkJSONWriter.cpp @@ -0,0 +1,43 @@ +/* + * Copyright 2017 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +// Make sure that the PRI format string macros are defined +#define __STDC_FORMAT_MACROS +#include <inttypes.h> +#include <stdarg.h> + +#include "SkJSONWriter.h" + +void SkJSONWriter::appendS64(int64_t value) { + this->beginValue(); + this->appendf("%" PRId64, value); +} + +void SkJSONWriter::appendU64(uint64_t value) { + this->beginValue(); + this->appendf("%" PRIu64, value); +} + +void SkJSONWriter::appendHexU64(uint64_t value) { + this->beginValue(); + this->appendf("\"0x%" PRIx64 "\"", value); +} + +void SkJSONWriter::appendf(const char* fmt, ...) { + const int kBufferSize = 1024; + char buffer[kBufferSize]; + va_list argp; + va_start(argp, fmt); +#ifdef SK_BUILD_FOR_WIN + int length = _vsnprintf_s(buffer, kBufferSize, _TRUNCATE, fmt, argp); +#else + int length = vsnprintf(buffer, kBufferSize, fmt, argp); +#endif + SkASSERT(length >= 0 && length < kBufferSize); + va_end(argp); + this->write(buffer, length); +} diff --git a/src/utils/SkJSONWriter.h b/src/utils/SkJSONWriter.h index 9ac28ebc47..65f9990d22 100644 --- a/src/utils/SkJSONWriter.h +++ b/src/utils/SkJSONWriter.h @@ -9,8 +9,7 @@ #define SkJSONWriter_DEFINED #include "SkStream.h" - -#include <inttypes.h> +#include "SkTArray.h" /** * Lightweight class for writing properly structured JSON data. No random-access, everything must @@ -182,13 +181,13 @@ public: } } void appendS32(int32_t value) { this->beginValue(); this->appendf("%d", value); } - void appendS64(int64_t value) { this->beginValue(); this->appendf("%" PRId64, value); } + void appendS64(int64_t value); void appendU32(uint32_t value) { this->beginValue(); this->appendf("%u", value); } - void appendU64(uint64_t value) { this->beginValue(); this->appendf("%" PRIu64, value); } + void appendU64(uint64_t value); void appendFloat(float value) { this->beginValue(); this->appendf("%f", value);; } void appendDouble(double value) { this->beginValue(); this->appendf("%f", value); } void appendHexU32(uint32_t value) { this->beginValue(); this->appendf("\"0x%x\"", value); } - void appendHexU64(uint64_t value) { this->beginValue(); this->appendf("\"0x%" PRIx64 "\"", value); } + void appendHexU64(uint64_t value); #define DEFINE_NAMED_APPEND(function, type) \ void function(const char* name, type value) { this->appendName(name); this->function(value); } @@ -235,20 +234,7 @@ private: kArrayValue, }; - void appendf(const char* fmt, ...) { - const int kBufferSize = 1024; - char buffer[kBufferSize]; - va_list argp; - va_start(argp, fmt); -#ifdef SK_BUILD_FOR_WIN - int length = _vsnprintf_s(buffer, kBufferSize, _TRUNCATE, fmt, argp); -#else - int length = vsnprintf(buffer, kBufferSize, fmt, argp); -#endif - SkASSERT(length >= 0 && length < kBufferSize); - va_end(argp); - this->write(buffer, length); - } + void appendf(const char* fmt, ...); void beginValue(bool structure = false) { SkASSERT(State::kObjectName == fState || diff --git a/tests/GrContextFactoryTest.cpp b/tests/GrContextFactoryTest.cpp index d4d5667152..098b2d61a9 100644 --- a/tests/GrContextFactoryTest.cpp +++ b/tests/GrContextFactoryTest.cpp @@ -139,4 +139,10 @@ DEF_GPUTEST(GrContextFactory_sharedContexts, reporter, /*factory*/) { } } +DEF_GPUTEST_FOR_ALL_CONTEXTS(GrContextDump, reporter, ctxInfo) { + // Ensure that GrContext::dump doesn't assert (which is possible, if the JSON code is wrong) + SkString result = ctxInfo.grContext()->dump(); + REPORTER_ASSERT(reporter, !result.isEmpty()); +} + #endif diff --git a/tests/GrDrawTargetTest.cpp b/tests/GrDrawTargetTest.cpp deleted file mode 100644 index c8492bc3ad..0000000000 --- a/tests/GrDrawTargetTest.cpp +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2013 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "Test.h" -#if SK_SUPPORT_GPU - -#include "GrCaps.h" -#include "GrContext.h" -#include "GrGpu.h" - -DEF_GPUTEST_FOR_ALL_CONTEXTS(GrDrawTargetPrint, reporter, ctxInfo) { - // This used to assert. - SkString result = ctxInfo.grContext()->caps()->dump(); - SkASSERT(!result.isEmpty()); - SkString shaderResult = ctxInfo.grContext()->caps()->shaderCaps()->dump(); - SkASSERT(!shaderResult.isEmpty()); -} - -#endif |