diff options
author | mtklein <mtklein@google.com> | 2016-08-03 19:19:48 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-08-03 19:19:48 -0700 |
commit | b97963401220da82455e0dfe1f7206e7e8b249e1 (patch) | |
tree | f3415f1aa9e9b89ca3992506de4435b287cf05bb | |
parent | 52d1be5ca7b1ba8cc450be7dd6377ea5bb73386a (diff) |
Revert of SkRTConf: reduce functionality to what we use, increase simplicity (patchset #8 id:150001 of https://codereview.chromium.org/2212473002/ )
Reason for revert:
missed GrVkPipelineStateCache
Original issue's description:
> SkRTConf: reduce functionality to what we use, increase simplicity
>
> GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2212473002
> DOCS_PREVIEW= https://skia.org/?cl=2212473002
> CQ_INCLUDE_TRYBOTS=master.client.skia:Test-Ubuntu-GCC-GCE-CPU-AVX2-x86_64-Release-SKNX_NO_SIMD-Trybot
>
> [mtklein]
> TBR=reed@google.com
> Only removing unused public API.
>
> Committed: https://skia.googlesource.com/skia/+/ef59974708dade6fa72fb0218d4f8a9590175c47
TBR=halcanary@google.com
# Skipping CQ checks because original CL landed less than 1 days ago.
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
Review-Url: https://codereview.chromium.org/2215433003
-rw-r--r-- | BUILD.gn | 1 | ||||
-rw-r--r-- | gyp/utils.gypi | 2 | ||||
-rw-r--r-- | include/utils/SkRTConf.h | 193 | ||||
-rw-r--r-- | site/dev/runtime/config.md | 89 | ||||
-rw-r--r-- | site/dev/runtime/index.md | 181 | ||||
-rw-r--r-- | src/core/SkGraphics.cpp | 10 | ||||
-rw-r--r-- | src/effects/SkBlurMaskFilter.cpp | 9 | ||||
-rw-r--r-- | src/gpu/batches/GrAADistanceFieldPathRenderer.cpp | 1 | ||||
-rw-r--r-- | src/gpu/gl/GrGLGpuProgramCache.cpp | 5 | ||||
-rw-r--r-- | src/gpu/gl/builders/GrGLProgramBuilder.cpp | 1 | ||||
-rw-r--r-- | src/gpu/gl/builders/GrGLShaderStringBuilder.cpp | 5 | ||||
-rw-r--r-- | src/gpu/vk/GrVkPipelineStateCache.cpp | 1 | ||||
-rw-r--r-- | src/images/SkJPEGImageEncoder.cpp | 1 | ||||
-rw-r--r-- | src/images/SkPNGImageEncoder.cpp | 9 | ||||
-rw-r--r-- | src/opts/opts_check_x86.cpp | 1 | ||||
-rw-r--r-- | src/utils/SkRTConf.cpp | 325 | ||||
-rw-r--r-- | tests/PathOpsExtendedTest.cpp | 5 | ||||
-rw-r--r-- | tests/PathOpsSkpClipTest.cpp | 14 | ||||
-rw-r--r-- | tests/RTConfRegistryTest.cpp | 25 | ||||
-rw-r--r-- | tests/RuntimeConfigTest.cpp | 28 | ||||
-rw-r--r-- | tests/SkpSkGrTest.cpp | 1 |
21 files changed, 894 insertions, 13 deletions
@@ -461,6 +461,7 @@ test_lib("tests") { sources = tests_sources - [ rebase_path("tests/FontMgrAndroidParserTest.cpp"), # Android only rebase_path("tests/PathOpsSkpClipTest.cpp"), # alternate main + rebase_path("tests/RTConfRegistryTest.cpp"), # TODO: delete rebase_path("tests/SkSLErrorTest.cpp"), # TODO: make work rebase_path("tests/SkSLGLSLTest.cpp"), # TODO: make work rebase_path("tests/SkpSkGrTest.cpp"), # doesn't compile diff --git a/gyp/utils.gypi b/gyp/utils.gypi index 4903f3d0fa..ac14a74ecd 100644 --- a/gyp/utils.gypi +++ b/gyp/utils.gypi @@ -28,6 +28,7 @@ '<(skia_include_path)/utils/SkParsePath.h', '<(skia_include_path)/utils/SkPictureUtils.h', '<(skia_include_path)/utils/SkRandom.h', + '<(skia_include_path)/utils/SkRTConf.h', '<(skia_include_path)/utils/SkTextBox.h', '<(skia_src_path)/utils/SkBase64.cpp', @@ -67,6 +68,7 @@ '<(skia_src_path)/utils/SkPatchUtils.h', '<(skia_src_path)/utils/SkRGBAToYUV.cpp', '<(skia_src_path)/utils/SkRGBAToYUV.h', + '<(skia_src_path)/utils/SkRTConf.cpp', '<(skia_src_path)/utils/SkTextBox.cpp', '<(skia_src_path)/utils/SkTextureCompressor.cpp', '<(skia_src_path)/utils/SkTextureCompressor.h', diff --git a/include/utils/SkRTConf.h b/include/utils/SkRTConf.h new file mode 100644 index 0000000000..d80e418419 --- /dev/null +++ b/include/utils/SkRTConf.h @@ -0,0 +1,193 @@ +/* + * Copyright 2013 Google, Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + + +#ifndef SkRTConf_DEFINED +#define SkRTConf_DEFINED + +#include "../private/SkTDArray.h" +#include "../private/SkTDict.h" +#include "SkString.h" +#include "SkStream.h" + +/** \class SkRTConfBase + Non-templated base class for the runtime configs +*/ + +class SkRTConfBase { +public: + SkRTConfBase(const char *name) : fName(name) {} + virtual ~SkRTConfBase() {} + virtual const char *getName() const { return fName.c_str(); } + virtual bool isDefault() const = 0; + virtual void print(SkWStream *o) const = 0; + virtual bool equals(const SkRTConfBase *conf) const = 0; +protected: + SkString fName; +}; + +/** \class SkRTConf + A class to provide runtime configurability. +*/ +template<typename T> class SkRTConf: public SkRTConfBase { +public: + SkRTConf(const char *name, const T &defaultValue, const char *description); + operator const T&() const { return fValue; } + void print(SkWStream *o) const; + bool equals(const SkRTConfBase *conf) const; + bool isDefault() const { return fDefault == fValue; } + void set(const T& value) { fValue = value; } +protected: + void doPrint(char *s) const; + + T fValue; + T fDefault; + SkString fDescription; +}; + +#ifdef SK_DEBUG +#define SK_CONF_DECLARE(confType, varName, confName, defaultValue, description) static SkRTConf<confType> varName(confName, defaultValue, description) +#define SK_CONF_SET(confname, value) \ + skRTConfRegistry().set(confname, value, true) +/* SK_CONF_TRY_SET() is like SK_CONF_SET(), but doesn't complain if + confname can't be found. This is useful if the SK_CONF_DECLARE is + inside a source file whose linkage is dependent on the system. */ +#define SK_CONF_TRY_SET(confname, value) \ + skRTConfRegistry().set(confname, value, false) +#else +#define SK_CONF_DECLARE(confType, varName, confName, defaultValue, description) static confType varName = defaultValue +#define SK_CONF_SET(confname, value) (void) confname, (void) value +#define SK_CONF_TRY_SET(confname, value) (void) confname, (void) value +#endif + +/** \class SkRTConfRegistry + A class that maintains a systemwide registry of all runtime configuration + parameters. Mainly used for printing them out and handling multiply-defined + knobs. +*/ + +class SkRTConfRegistry { +public: + SkRTConfRegistry(); + ~SkRTConfRegistry(); + void printAll(const char *fname = NULL) const; + bool hasNonDefault() const; + void printNonDefault(const char *fname = NULL) const; + const char *configFileLocation() const; + void possiblyDumpFile() const; + void validate() const; + template <typename T> void set(const char *confname, + T value, + bool warnIfNotFound = true); + +private: + template<typename T> friend class SkRTConf; + + void registerConf(SkRTConfBase *conf); + + template <typename T> bool parse(const char *name, T* value); + + SkTDArray<SkString *> fConfigFileKeys, fConfigFileValues; + typedef SkTDict< SkTDArray<SkRTConfBase *> * > ConfMap; + ConfMap fConfs; + + template <typename T> + friend bool test_rt_conf_parse(SkRTConfRegistry*, const char* name, T* value); +}; + +// our singleton registry + +SkRTConfRegistry &skRTConfRegistry(); + +template<typename T> +SkRTConf<T>::SkRTConf(const char *name, const T &defaultValue, const char *description) + : SkRTConfBase(name) + , fValue(defaultValue) + , fDefault(defaultValue) + , fDescription(description) { + + T value; + if (skRTConfRegistry().parse(fName.c_str(), &value)) { + fValue = value; + } + skRTConfRegistry().registerConf(this); +} + +template<typename T> +void SkRTConf<T>::print(SkWStream *o) const { + char outline[200]; // should be ok because we specify a max. width for everything here. + char *outptr; + if (strlen(getName()) >= 30) { + o->writeText(getName()); + o->writeText(" "); + outptr = &(outline[0]); + } else { + sprintf(outline, "%-30.30s", getName()); + outptr = &(outline[30]); + } + + doPrint(outptr); + sprintf(outptr+30, " %.128s", fDescription.c_str()); + for (size_t i = strlen(outline); i --> 0 && ' ' == outline[i];) { + outline[i] = '\0'; + } + o->writeText(outline); +} + +template<typename T> +void SkRTConf<T>::doPrint(char *s) const { + sprintf(s, "%-30.30s", "How do I print myself??"); +} + +template<> inline void SkRTConf<bool>::doPrint(char *s) const { + char tmp[30]; + sprintf(tmp, "%s # [%s]", fValue ? "true" : "false", fDefault ? "true" : "false"); + sprintf(s, "%-30.30s", tmp); +} + +template<> inline void SkRTConf<int>::doPrint(char *s) const { + char tmp[30]; + sprintf(tmp, "%d # [%d]", fValue, fDefault); + sprintf(s, "%-30.30s", tmp); +} + +template<> inline void SkRTConf<unsigned int>::doPrint(char *s) const { + char tmp[30]; + sprintf(tmp, "%u # [%u]", fValue, fDefault); + sprintf(s, "%-30.30s", tmp); +} + +template<> inline void SkRTConf<float>::doPrint(char *s) const { + char tmp[30]; + sprintf(tmp, "%6.6f # [%6.6f]", fValue, fDefault); + sprintf(s, "%-30.30s", tmp); +} + +template<> inline void SkRTConf<double>::doPrint(char *s) const { + char tmp[30]; + sprintf(tmp, "%6.6f # [%6.6f]", fValue, fDefault); + sprintf(s, "%-30.30s", tmp); +} + +template<> inline void SkRTConf<const char *>::doPrint(char *s) const { + char tmp[30]; + sprintf(tmp, "%s # [%s]", fValue, fDefault); + sprintf(s, "%-30.30s", tmp); +} + +template<typename T> +bool SkRTConf<T>::equals(const SkRTConfBase *conf) const { + // static_cast here is okay because there's only one kind of child class. + const SkRTConf<T> *child_pointer = static_cast<const SkRTConf<T> *>(conf); + return child_pointer && + fName == child_pointer->fName && + fDescription == child_pointer->fDescription && + fValue == child_pointer->fValue && + fDefault == child_pointer->fDefault; +} + +#endif diff --git a/site/dev/runtime/config.md b/site/dev/runtime/config.md new file mode 100644 index 0000000000..fd31af75c5 --- /dev/null +++ b/site/dev/runtime/config.md @@ -0,0 +1,89 @@ +Runtime Configuration Settings +============================== + +Here is a (partial) list of Skia's runtime configuration settings: + +## Warning suppression: + +* configuration name: images.gif.suppressDecoderWarnings + environment variable: skia_images_gif_suppressDecoderWarnings + type: boolean + description: Suppress GIF warnings and errors when calling image decode + functions. + default: true. + +* configuration name: images.jpeg.suppressDecoderWarnings + environment variable: skia_images_jpeg_suppressDecoderWarnings + type: boolean + description: Suppress most JPG warnings when calling decode functions. + default: false in debug, true otherwise. + +* configuration name: images.jpeg.suppressDecoderErrors + environment variable: skia_images_jpeg_suppressDecoderErrors + type: boolean + description: Suppress most JPG error messages when decode function fails. + default: false in debug, true otherwise. + +* configuration name: images.png.suppressDecoderWarnings + environment variable: skia_images_png_suppressDecoderWarnings + type: boolean + description: Suppress most PNG warnings when calling image decode functions. + default: false in debug, true otherwise. + +## Other: + +* configuration name: bitmap.filter + environment variable: skia_bitmap_filter + type: string + description: Which scanline bitmap filter to use \[mitchell, lanczos, hamming, + gaussian, triangle, box\] + default: mitchell + +* configuration name: mask.filter.analyticNinePatch + environment variable: skia_mask_filter_analyticNinePatch + type: boolean + description: Use the faster analytic blur approach for ninepatch rects + default: \? + +* configuration name: gpu.deferContext + environment variable: skia_gpu_deferContext + type: boolean + description: Defers rendering in GrContext via GrInOrderDrawBuffer + default: true + +* configuration name: gpu.dumpFontCache + environment variable: skia_gpu_dumpFontCache + type: boolean + description: Dump the contents of the font cache before every purge + default: false + +* configuration name: bitmap.filter.highQualitySSE + environment variable: skia_bitmap_filter_highQualitySSE + type: boolean + description: Use SSE optimized version of high quality image filters + default: false + +## Use: + +These configuration values can be changed at runtime by including this in your +program: + +<!--?prettify?--> +~~~~ +#include "SkRTConf.h" +/*...*/ +int main() { + SK_CONF_SET( configuration_name, new_value ); + /*...*/ +~~~~ + +Or by setting the corresponding environment variable before starting the +program. For example, in Bourne shell: + +<!--?prettify?--> +~~~~ +#!/bin/sh +export skia_environment_variable="new_value" +your_program +~~~~ + diff --git a/site/dev/runtime/index.md b/site/dev/runtime/index.md new file mode 100644 index 0000000000..7c8246d23f --- /dev/null +++ b/site/dev/runtime/index.md @@ -0,0 +1,181 @@ +Runtime Configuration +===================== + +Skia supports the configuration of various aspects of its behavior at runtime, +allowing developers to enable\/disable features, or to experiment with numerical +quantities without recompiling. + +## Enabling runtime configuration + +In order to use a runtime-configurable variable in your source, simply: + +<!--?prettify?--> +~~~~ +#include "SkRTConf.h" +~~~~ + +## Declaring a runtime-configurable variable + +At file scope, declare your variable like so: + +<!--?prettify?--> +~~~~ +SK_CONF_DECLARE( confType, varName, confName, defaultValue, description ); +~~~~ + +For example, to declare a boolean variable called ` c_printShaders ` that can be +changed at runtime, you would do something like + +<!--?prettify?--> +~~~~ +SK_CONF_DECLARE( bool, c_printShaders, "gpu.printShaders", false, "print the + source code of any internally generated GPU shaders" ); +~~~~ + +It is safe to declare variables this way in header files; the variables will be +declared as static, but since they are read\-only\-ish \(they can be changed +through a special mechanism; see below\), this is safe. + +## Using a runtime-configurable variable + +The variables created by `SK_CONF_DECLARE` can be used in normal C\+\+ code as +if they were regular contant variables. For example: + +<!--?prettify?--> +~~~~ +if (c_printShaders) { + // actually print out the shaders +} +~~~~ + +## Changing a runtime-configurable variable after launch + +If, for some reason, you want to change the value of a runtime-configurable +variable after your program has started, you can do this with the `SK_CONF_SET` +macro: + +<!--?prettify?--> +~~~~ +SK_CONF_SET( "gpu.printShaders", false ) +~~~~ + +Note that we're using the `confName` parameter to the declaration, not +`varName`. This is because this configuration option may appear in multiple +files \(especially if you declared it in a header!\), and we need to make sure +to update all variables' values, not just the one that's locally visible to the +file you are currently in. + +## Changing a runtime-configurable variable before launch + +This is the primary intended use of these variables. There are two ways that you +can control the values of runtime-configurable variables at launch time: a +skia.conf configuration file, or through the use of environment variables. + +### Using skia.conf + +The skia.conf file is a simple line-based configuration file containing +key-value pairs. It supports python-style \# comments. For our example, we might +see a configuration file that looks like: + +<!--?prettify?--> +~~~~ +gpu.printShaders true +gpu.somethingElse 3.14159 +matrix.invertProperly false # math is hard +... +~~~~ + +*Note: boolean values may be set as 1, 0, true, or false. Other values will +result in runtime errors.* + +If the skia library detects a skia.conf file at initialization time, it will +parse it and override the default values of any declared configuration variables +with the values found in the file. + +*Note: although it might appear that the configuration variables have a +hierarchical naming scheme involving periods, that's just a convention I have +adopted so that when all declared configuration variables are sorted +alphabetically, they are roughly grouped by component.* + +## Using environment variables + +You can quickly override the value of one runtime-configurable variable using an +environment variable equal to the variable's key with "skia." prepended. So, for +example, one might run: + +<!--?prettify?--> +~~~~ +prompt% skia.gpu.printShaders=true out/Debug/dm +~~~~ + +or + +<!--?prettify?--> +~~~~ +prompt% export skia.gpu.printShaders=true +prompt% out/Debug/dm +~~~~ + +On many shells, it is illegal to have a period in an environment variable name, +so skia also supports underscores in place of the periods: + +<!--?prettify?--> +~~~~ +prompt% skia_gpu_printShaders=true out/Debug/dm +~~~~ + +or + +<!--?prettify?--> +~~~~ +prompt% export skia_gpu_printShaders=true` +prompt% out/Debug/dm +~~~~ + +## Discovering all possible configuration variables + +As this system becomes more widely used in skia, there may be hundreds of +configuration variables. What are they all? What are their defaults? What do +they do? + +In order to find out, simply create a zero-length skia.conf file \(on unix, +`touch skia.conf` will do the trick\). If skia detects a zero-length +configuration file, it will overwrite it with a sorted list of all known +configuration variables, their defaults, and their description strings. Each +line will be commented out and have its value already equal to its default, so +you can then edit this file to your liking. + +To trigger this behavior, call the function +`skRTConfRegistry().possiblyDumpFile(); ` or simply use `SkAutoGraphics +ag;`, which also validates your configuration and print out active non-default +options. + +## Are these things enabled all the time? + +No, they are only enabled in builds where SK_DEBUG is defined. This includes both +`Debug` and `Release_Developer` gyp BUILDTYPES. The `Release_Developer` build type +has exactly the same build flags as `Release`, except it re-enables SK_DEBUG, which +in turn enables runtime configuration behavior. +Specifically: + +<!--?prettify?--> +~~~~ +prompt% ninja -C BUILDTYPE=Release_Developer +~~~~ + +... wait a long time ... + +<!--?prettify?--> +~~~~ +prompt % skia_gpu_printShaders=true out/Release_Developer/dm +~~~~ + +... enjoy ... + +## Known issues / limitations + +Lines in 'skia.conf', including comments, are limited to 1024 characters. +Runtime configuration variables of type `char \* ` cannot currently have spaces +in them. +Runtime variables are only fully supported for `int`, `unsigned int`, `float`, +`double`, `bool`, and `char \*`. diff --git a/src/core/SkGraphics.cpp b/src/core/SkGraphics.cpp index 01b1432ef0..d7022b770b 100644 --- a/src/core/SkGraphics.cpp +++ b/src/core/SkGraphics.cpp @@ -22,6 +22,7 @@ #include "SkPixelRef.h" #include "SkRefCnt.h" #include "SkResourceCache.h" +#include "SkRTConf.h" #include "SkScalerContext.h" #include "SkShader.h" #include "SkStream.h" @@ -48,6 +49,15 @@ void SkGraphics::Init() { // SkGraphics::Init() must be thread-safe and idempotent. SkCpu::CacheRuntimeFeatures(); SkOpts::Init(); + +#ifdef SK_DEBUG + skRTConfRegistry().possiblyDumpFile(); + skRTConfRegistry().validate(); + if (skRTConfRegistry().hasNonDefault()) { + SkDebugf("Non-default runtime configuration options:\n"); + skRTConfRegistry().printNonDefault(); + } +#endif } /////////////////////////////////////////////////////////////////////////////// diff --git a/src/effects/SkBlurMaskFilter.cpp b/src/effects/SkBlurMaskFilter.cpp index 38b5313be3..9e0315f2b7 100644 --- a/src/effects/SkBlurMaskFilter.cpp +++ b/src/effects/SkBlurMaskFilter.cpp @@ -12,6 +12,7 @@ #include "SkWriteBuffer.h" #include "SkMaskFilter.h" #include "SkRRect.h" +#include "SkRTConf.h" #include "SkStringUtils.h" #include "SkStrokeRec.h" @@ -303,10 +304,9 @@ static SkCachedData* add_cached_rects(SkMask* mask, SkScalar sigma, SkBlurStyle } #ifdef SK_IGNORE_FAST_RRECT_BLUR - // Use the faster analytic blur approach for ninepatch round rects - static const bool c_analyticBlurRRect{false}; +SK_CONF_DECLARE(bool, c_analyticBlurRRect, "mask.filter.blur.analyticblurrrect", false, "Use the faster analytic blur approach for ninepatch rects"); #else - static const bool c_analyticBlurRRect{true}; +SK_CONF_DECLARE(bool, c_analyticBlurRRect, "mask.filter.blur.analyticblurrrect", true, "Use the faster analytic blur approach for ninepatch round rects"); #endif SkMaskFilter::FilterReturn @@ -443,8 +443,7 @@ SkBlurMaskFilterImpl::filterRRectToNine(const SkRRect& rrect, const SkMatrix& ma return kTrue_FilterReturn; } -// Use the faster analytic blur approach for ninepatch rects -static const bool c_analyticBlurNinepatch{true}; +SK_CONF_DECLARE(bool, c_analyticBlurNinepatch, "mask.filter.analyticNinePatch", true, "Use the faster analytic blur approach for ninepatch rects"); SkMaskFilter::FilterReturn SkBlurMaskFilterImpl::filterRectsToNine(const SkRect rects[], int count, diff --git a/src/gpu/batches/GrAADistanceFieldPathRenderer.cpp b/src/gpu/batches/GrAADistanceFieldPathRenderer.cpp index 36a9ff01e7..a9ba94da40 100644 --- a/src/gpu/batches/GrAADistanceFieldPathRenderer.cpp +++ b/src/gpu/batches/GrAADistanceFieldPathRenderer.cpp @@ -20,6 +20,7 @@ #include "effects/GrDistanceFieldGeoProc.h" #include "SkDistanceFieldGen.h" +#include "SkRTConf.h" #define ATLAS_TEXTURE_WIDTH 2048 #define ATLAS_TEXTURE_HEIGHT 2048 diff --git a/src/gpu/gl/GrGLGpuProgramCache.cpp b/src/gpu/gl/GrGLGpuProgramCache.cpp index ae93926c79..4ba0d23ae5 100644 --- a/src/gpu/gl/GrGLGpuProgramCache.cpp +++ b/src/gpu/gl/GrGLGpuProgramCache.cpp @@ -13,11 +13,12 @@ #include "glsl/GrGLSLFragmentProcessor.h" #include "glsl/GrGLSLProgramDataManager.h" #include "glsl/GrGLSLProgramDesc.h" +#include "SkRTConf.h" #include "SkTSearch.h" #ifdef PROGRAM_CACHE_STATS -// Display program cache usage -static const bool c_DisplayCache{false}; +SK_CONF_DECLARE(bool, c_DisplayCache, "gpu.displayCache", false, + "Display program cache usage."); #endif typedef GrGLSLProgramDataManager::UniformHandle UniformHandle; diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.cpp b/src/gpu/gl/builders/GrGLProgramBuilder.cpp index 2bbeb42af6..2d06e434f2 100644 --- a/src/gpu/gl/builders/GrGLProgramBuilder.cpp +++ b/src/gpu/gl/builders/GrGLProgramBuilder.cpp @@ -12,6 +12,7 @@ #include "GrGLProgramBuilder.h" #include "GrSwizzle.h" #include "GrTexture.h" +#include "SkRTConf.h" #include "SkTraceEvent.h" #include "gl/GrGLGpu.h" #include "gl/GrGLProgram.h" diff --git a/src/gpu/gl/builders/GrGLShaderStringBuilder.cpp b/src/gpu/gl/builders/GrGLShaderStringBuilder.cpp index 296c2beb44..b4ce2824e2 100644 --- a/src/gpu/gl/builders/GrGLShaderStringBuilder.cpp +++ b/src/gpu/gl/builders/GrGLShaderStringBuilder.cpp @@ -8,13 +8,14 @@ #include "GrGLShaderStringBuilder.h" #include "gl/GrGLGpu.h" #include "gl/GrGLSLPrettyPrint.h" +#include "SkRTConf.h" #include "SkTraceEvent.h" #define GL_CALL(X) GR_GL_CALL(gpu->glInterface(), X) #define GL_CALL_RET(R, X) GR_GL_CALL_RET(gpu->glInterface(), R, X) -// Print the source code for all shaders generated. -static const bool c_PrintShaders{false}; +SK_CONF_DECLARE(bool, c_PrintShaders, "gpu.printShaders", false, + "Print the source code for all shaders generated."); static void print_shader_source(const char** strings, int* lengths, int count); diff --git a/src/gpu/vk/GrVkPipelineStateCache.cpp b/src/gpu/vk/GrVkPipelineStateCache.cpp index 494f659e9f..b8335e8e44 100644 --- a/src/gpu/vk/GrVkPipelineStateCache.cpp +++ b/src/gpu/vk/GrVkPipelineStateCache.cpp @@ -11,6 +11,7 @@ #include "GrProcessor.h" #include "GrVkPipelineState.h" #include "GrVkPipelineStateBuilder.h" +#include "SkRTConf.h" #include "glsl/GrGLSLFragmentProcessor.h" #include "glsl/GrGLSLProgramDataManager.h" diff --git a/src/images/SkJPEGImageEncoder.cpp b/src/images/SkJPEGImageEncoder.cpp index 66b2440c20..1051aec205 100644 --- a/src/images/SkJPEGImageEncoder.cpp +++ b/src/images/SkJPEGImageEncoder.cpp @@ -13,6 +13,7 @@ #include "SkTemplates.h" #include "SkTime.h" #include "SkUtils.h" +#include "SkRTConf.h" #include "SkRect.h" #include "SkCanvas.h" diff --git a/src/images/SkPNGImageEncoder.cpp b/src/images/SkPNGImageEncoder.cpp index 1932e66dc6..c3df5d10a8 100644 --- a/src/images/SkPNGImageEncoder.cpp +++ b/src/images/SkPNGImageEncoder.cpp @@ -10,6 +10,7 @@ #include "SkColorPriv.h" #include "SkDither.h" #include "SkMath.h" +#include "SkRTConf.h" #include "SkStream.h" #include "SkTemplates.h" #include "SkUtils.h" @@ -35,9 +36,11 @@ #endif #define DEFAULT_FOR_SUPPRESS_PNG_IMAGE_DECODER_WARNINGS true -// Suppress most PNG warnings when calling image decode functions. -static const bool c_suppressPNGImageDecoderWarnings{ - DEFAULT_FOR_SUPPRESS_PNG_IMAGE_DECODER_WARNINGS}; +SK_CONF_DECLARE(bool, c_suppressPNGImageDecoderWarnings, + "images.png.suppressDecoderWarnings", + DEFAULT_FOR_SUPPRESS_PNG_IMAGE_DECODER_WARNINGS, + "Suppress most PNG warnings when calling image decode " + "functions."); /////////////////////////////////////////////////////////////////////////////// diff --git a/src/opts/opts_check_x86.cpp b/src/opts/opts_check_x86.cpp index a8003a3b0e..dacb49bc91 100644 --- a/src/opts/opts_check_x86.cpp +++ b/src/opts/opts_check_x86.cpp @@ -13,6 +13,7 @@ #include "SkBlitRow.h" #include "SkBlitRow_opts_SSE2.h" #include "SkCpu.h" +#include "SkRTConf.h" /* diff --git a/src/utils/SkRTConf.cpp b/src/utils/SkRTConf.cpp new file mode 100644 index 0000000000..2dfa47efc7 --- /dev/null +++ b/src/utils/SkRTConf.cpp @@ -0,0 +1,325 @@ +/* + * 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 "SkRTConf.h" +#include "SkOSFile.h" + +#include <stdlib.h> + +SkRTConfRegistry::SkRTConfRegistry(): fConfs(100) { + + FILE *fp = sk_fopen(configFileLocation(), kRead_SkFILE_Flag); + + if (!fp) { + return; + } + + char line[1024]; + + while (!sk_feof(fp)) { + + if (!sk_fgets(line, sizeof(line), fp)) { + break; + } + + char *commentptr = strchr(line, '#'); + if (commentptr == line) { + continue; + } + if (commentptr) { + *commentptr = '\0'; + } + + char sep[] = " \t\r\n"; + + char *keyptr = strtok(line, sep); + if (!keyptr) { + continue; + } + + char *valptr = strtok(nullptr, sep); + if (!valptr) { + continue; + } + + SkString *key = new SkString(keyptr); + SkString *val = new SkString(valptr); + + fConfigFileKeys.append(1, &key); + fConfigFileValues.append(1, &val); + } + sk_fclose(fp); +} + +SkRTConfRegistry::~SkRTConfRegistry() { + ConfMap::Iter iter(fConfs); + SkTDArray<SkRTConfBase *> *confArray; + + while (iter.next(&confArray)) { + delete confArray; + } + + for (int i = 0 ; i < fConfigFileKeys.count() ; i++) { + delete fConfigFileKeys[i]; + delete fConfigFileValues[i]; + } +} + +const char *SkRTConfRegistry::configFileLocation() const { + return "skia.conf"; // for now -- should probably do something fancier like home directories or whatever. +} + +// dump all known runtime config options to the file with their default values. +// to trigger this, make a config file of zero size. +void SkRTConfRegistry::possiblyDumpFile() const { + const char *path = configFileLocation(); + FILE *fp = sk_fopen(path, kRead_SkFILE_Flag); + if (!fp) { + return; + } + size_t configFileSize = sk_fgetsize(fp); + if (configFileSize == 0) { + printAll(path); + } + sk_fclose(fp); +} + +// Run through every provided configuration option and print a warning if the user hasn't +// declared a correponding configuration object somewhere. +void SkRTConfRegistry::validate() const { + for (int i = 0 ; i < fConfigFileKeys.count() ; i++) { + if (!fConfs.find(fConfigFileKeys[i]->c_str())) { + SkDebugf("WARNING: You have config value %s in your configuration file, but I've never heard of that.\n", fConfigFileKeys[i]->c_str()); + } + } +} + +void SkRTConfRegistry::printAll(const char *fname) const { + SkWStream *o; + + if (fname) { + o = new SkFILEWStream(fname); + } else { + o = new SkDebugWStream(); + } + + ConfMap::Iter iter(fConfs); + SkTDArray<SkRTConfBase *> *confArray; + + while (iter.next(&confArray)) { + if (confArray->getAt(0)->isDefault()) { + o->writeText("# "); + } + confArray->getAt(0)->print(o); + o->newline(); + } + + delete o; +} + +bool SkRTConfRegistry::hasNonDefault() const { + ConfMap::Iter iter(fConfs); + SkTDArray<SkRTConfBase *> *confArray; + while (iter.next(&confArray)) { + if (!confArray->getAt(0)->isDefault()) { + return true; + } + } + return false; +} + +void SkRTConfRegistry::printNonDefault(const char *fname) const { + SkWStream *o; + + if (fname) { + o = new SkFILEWStream(fname); + } else { + o = new SkDebugWStream(); + } + ConfMap::Iter iter(fConfs); + SkTDArray<SkRTConfBase *> *confArray; + + while (iter.next(&confArray)) { + if (!confArray->getAt(0)->isDefault()) { + confArray->getAt(0)->print(o); + o->newline(); + } + } + + delete o; +} + +// register a configuration variable after its value has been set by the parser. +// we maintain a vector of these things instead of just a single one because the +// user might set the value after initialization time and we need to have +// all the pointers lying around, not just one. +void SkRTConfRegistry::registerConf(SkRTConfBase *conf) { + SkTDArray<SkRTConfBase *> *confArray; + if (fConfs.find(conf->getName(), &confArray)) { + if (!conf->equals(confArray->getAt(0))) { + SkDebugf("WARNING: Skia config \"%s\" was registered more than once in incompatible ways.\n", conf->getName()); + } else { + confArray->append(1, &conf); + } + } else { + confArray = new SkTDArray<SkRTConfBase *>; + confArray->append(1, &conf); + fConfs.set(conf->getName(),confArray); + } +} + +template <typename T> T doParse(const char *, bool *success ) { + SkDebugf("WARNING: Invoked non-specialized doParse function...\n"); + if (success) { + *success = false; + } + return (T) 0; +} + +template<> bool doParse<bool>(const char *s, bool *success) { + if (success) { + *success = true; + } + if (!strcmp(s,"1") || !strcmp(s,"true")) { + return true; + } + if (!strcmp(s,"0") || !strcmp(s,"false")) { + return false; + } + if (success) { + *success = false; + } + return false; +} + +template<> const char * doParse<const char *>(const char * s, bool *success) { + if (success) { + *success = true; + } + return s; +} + +template<> int doParse<int>(const char * s, bool *success) { + if (success) { + *success = true; + } + return atoi(s); +} + +template<> unsigned int doParse<unsigned int>(const char * s, bool *success) { + if (success) { + *success = true; + } + return (unsigned int) atoi(s); +} + +template<> float doParse<float>(const char * s, bool *success) { + if (success) { + *success = true; + } + return (float) atof(s); +} + +template<> double doParse<double>(const char * s, bool *success) { + if (success) { + *success = true; + } + return atof(s); +} + +static inline void str_replace(char *s, char search, char replace) { + for (char *ptr = s ; *ptr ; ptr++) { + if (*ptr == search) { + *ptr = replace; + } + } +} + +template<typename T> bool SkRTConfRegistry::parse(const char *name, T* value) { + const char *str = nullptr; + + for (int i = fConfigFileKeys.count() - 1 ; i >= 0; i--) { + if (fConfigFileKeys[i]->equals(name)) { + str = fConfigFileValues[i]->c_str(); + break; + } + } + + SkString environment_variable("skia."); + environment_variable.append(name); + + const char *environment_value = getenv(environment_variable.c_str()); + if (environment_value) { + str = environment_value; + } else { + // apparently my shell doesn't let me have environment variables that + // have periods in them, so also let the user substitute underscores. + SkAutoTMalloc<char> underscore_name(SkStrDup(environment_variable.c_str())); + str_replace(underscore_name.get(), '.', '_'); + environment_value = getenv(underscore_name.get()); + if (environment_value) { + str = environment_value; + } + } + + if (!str) { + return false; + } + + bool success; + T new_value = doParse<T>(str, &success); + if (success) { + *value = new_value; + } else { + SkDebugf("WARNING: Couldn't parse value \'%s\' for variable \'%s\'\n", + str, name); + } + return success; +} + +// need to explicitly instantiate the parsing function for every config type we might have... + +template bool SkRTConfRegistry::parse(const char *name, bool *value); +template bool SkRTConfRegistry::parse(const char *name, int *value); +template bool SkRTConfRegistry::parse(const char *name, unsigned int *value); +template bool SkRTConfRegistry::parse(const char *name, float *value); +template bool SkRTConfRegistry::parse(const char *name, double *value); +template bool SkRTConfRegistry::parse(const char *name, const char **value); + +template <typename T> void SkRTConfRegistry::set(const char *name, + T value, + bool warnIfNotFound) { + SkTDArray<SkRTConfBase *> *confArray; + if (!fConfs.find(name, &confArray)) { + if (warnIfNotFound) { + SkDebugf("WARNING: Attempting to set configuration value \"%s\"," + " but I've never heard of that.\n", name); + } + return; + } + SkASSERT(confArray != nullptr); + for (SkRTConfBase **confBase = confArray->begin(); confBase != confArray->end(); confBase++) { + // static_cast here is okay because there's only one kind of child class. + SkRTConf<T> *concrete = static_cast<SkRTConf<T> *>(*confBase); + + if (concrete) { + concrete->set(value); + } + } +} + +template void SkRTConfRegistry::set(const char *name, bool value, bool); +template void SkRTConfRegistry::set(const char *name, int value, bool); +template void SkRTConfRegistry::set(const char *name, unsigned int value, bool); +template void SkRTConfRegistry::set(const char *name, float value, bool); +template void SkRTConfRegistry::set(const char *name, double value, bool); +template void SkRTConfRegistry::set(const char *name, char * value, bool); + +SkRTConfRegistry &skRTConfRegistry() { + static SkRTConfRegistry r; + return r; +} diff --git a/tests/PathOpsExtendedTest.cpp b/tests/PathOpsExtendedTest.cpp index 6ea67fe89f..2f6d99d652 100644 --- a/tests/PathOpsExtendedTest.cpp +++ b/tests/PathOpsExtendedTest.cpp @@ -13,6 +13,7 @@ #include "SkMatrix.h" #include "SkMutex.h" #include "SkPaint.h" +#include "SkRTConf.h" #include "SkStream.h" #include <stdlib.h> @@ -629,6 +630,10 @@ bool testPathOpFail(skiatest::Reporter* reporter, const SkPath& a, const SkPath& SK_DECLARE_STATIC_MUTEX(gMutex); void initializeTests(skiatest::Reporter* reporter, const char* test) { +#if 0 // doesn't work yet + SK_CONF_SET("images.jpeg.suppressDecoderWarnings", true); + SK_CONF_SET("images.png.suppressDecoderWarnings", true); +#endif if (reporter->verbose()) { SkAutoMutexAcquire lock(gMutex); testName = test; diff --git a/tests/PathOpsSkpClipTest.cpp b/tests/PathOpsSkpClipTest.cpp index 3c958f1bec..c96e5bf66c 100644 --- a/tests/PathOpsSkpClipTest.cpp +++ b/tests/PathOpsSkpClipTest.cpp @@ -19,6 +19,7 @@ #include "SkOSFile.h" #include "SkPathOpsDebug.h" #include "SkPicture.h" +#include "SkRTConf.h" #include "SkTSort.h" #include "SkStream.h" #include "SkString.h" @@ -26,7 +27,6 @@ #include "SkTDArray.h" #include "SkTaskGroup.h" #include "SkTemplates.h" -#include "SkTSearch.h" #include "SkTime.h" #include <stdlib.h> @@ -740,6 +740,13 @@ checkEarlyExit: return true; } +static void initTest() { +#if !defined SK_BUILD_FOR_WIN && !defined SK_BUILD_FOR_MAC + SK_CONF_SET("images.jpeg.suppressDecoderWarnings", true); + SK_CONF_SET("images.png.suppressDecoderWarnings", true); +#endif +} + static void testSkpClipEncode(TestState* data) { data->fResult.testOne(); if (verbose()) { @@ -820,6 +827,7 @@ typedef SkTRegistry<Test*(*)(void*)> TestRegistry; DEF_TEST(PathOpsSkpClip) { gDirs.setDefault(); + initTest(); SkTArray<TestResult, true> errors; TestState state; state.init(0); @@ -843,6 +851,7 @@ static void testSkpClipMain(TestState* data) { DEF_TEST(PathOpsSkpClipThreaded) { gDirs.setDefault(); + initTest(); TestRunner testRunner; int dirNo; gDirs.reset(); @@ -881,6 +890,7 @@ DEF_TEST(PathOpsSkpClipUberThreaded) { gDirs.setDefault(); const int firstDirNo = gDirs.next(); const int lastDirNo = gDirs.last(); + initTest(); int dirCount = lastDirNo - firstDirNo + 1; SkAutoTDeleteArray<SkTDArray<TestResult> > tests(new SkTDArray<TestResult>[dirCount]); SkAutoTDeleteArray<SkTDArray<SortByName*> > sorted(new SkTDArray<SortByName*>[dirCount]); @@ -963,6 +973,7 @@ DEF_TEST(PathOpsSkpClipOneOff) { if (!skp) { skp = skipOver[testIndex].filename; } + initTest(); SkAssertResult(get_in_path(dirNo, skp).size()); SkString filename(skp); TestResult state; @@ -982,6 +993,7 @@ DEF_TEST(PathOpsTestSkipped) { } int dirNo = skip.directory; const char* skp = skip.filename; + initTest(); SkAssertResult(get_in_path(dirNo, skp).size()); SkString filename(skp); TestResult state; diff --git a/tests/RTConfRegistryTest.cpp b/tests/RTConfRegistryTest.cpp new file mode 100644 index 0000000000..be019f70b4 --- /dev/null +++ b/tests/RTConfRegistryTest.cpp @@ -0,0 +1,25 @@ +/* + * 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 "SkRTConf.h" +#include "SkOSEnvironment.h" +#include "Test.h" + +// Friended proxy for SkRTConfRegistry::parse() +template <typename T> +bool test_rt_conf_parse(SkRTConfRegistry* reg, const char* key, T* value) { + return reg->parse(key, value); +} + +DEF_TEST(SkRTConfRegistry, reporter) { + SkRTConfRegistry reg; + + sk_setenv("skia_nonexistent_item", "132"); + int result = 0; + test_rt_conf_parse(®, "nonexistent.item", &result); + REPORTER_ASSERT(reporter, result == 132); +} diff --git a/tests/RuntimeConfigTest.cpp b/tests/RuntimeConfigTest.cpp new file mode 100644 index 0000000000..b863ee1fd8 --- /dev/null +++ b/tests/RuntimeConfigTest.cpp @@ -0,0 +1,28 @@ +/* + * 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 "SkRTConf.h" +#include "Test.h" + +SK_CONF_DECLARE(int, c_RTConfTestVariable, + "test.utils.rtconf.testVariable", 1, + "This is only a test. Do not be alarmed."); +// TODO(skia-team): more comprehensive unit tests of the SkRTConf +// system. +DEF_TEST(RuntimeConfig, reporter) { + REPORTER_ASSERT(reporter, 1 == c_RTConfTestVariable); + + SK_CONF_SET("test.utils.rtconf.testVariable", 2); +#ifdef SK_DEBUG + REPORTER_ASSERT(reporter, 2 == c_RTConfTestVariable); +#else // not SK_DEBUG + // Can not change RTConf variables in SK_RELEASE. + REPORTER_ASSERT(reporter, 1 == c_RTConfTestVariable); +#endif // SK_DEBUG + + // This should not give a warning. + SK_CONF_TRY_SET("test.utils.rtconf.nonexistentVariable", 7); +} diff --git a/tests/SkpSkGrTest.cpp b/tests/SkpSkGrTest.cpp index ccec37bf21..bf534f4820 100644 --- a/tests/SkpSkGrTest.cpp +++ b/tests/SkpSkGrTest.cpp @@ -18,6 +18,7 @@ #include "SkImageEncoder.h" #include "SkOSFile.h" #include "SkPicture.h" +#include "SkRTConf.h" #include "SkStream.h" #include "SkString.h" #include "SkTArray.h" |