/* * Copyright 2018 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #ifndef SkSLUniformCTypes_DEFINED #define SkSLUniformCTypes_DEFINED #include "src/sksl/SkSLContext.h" #include "src/sksl/SkSLString.h" #include "src/sksl/ir/SkSLType.h" #include "src/sksl/ir/SkSLVariable.h" namespace SkSL { // This uses templates to define dirtyExpression(), saveState() and setUniform(). Each template can // reference token names formatted ${name} that are replaced with the actual values passed into the // functions. // // dirtyExpression() and saveState() support the following tokens: // - ${newVar} replaced with value of newValueVarName (1st argument) // - ${oldVar} replaced with value of oldValueVarName (2nd argument) // // setUniform() supports these tokens: // - ${pdman} replaced with value of pdmanName (1st argument) // - ${uniform} replaced with value of uniformHandleName (2nd argument) // - ${var} replaced with value of valueVarName (3rd argument) // // All templates and C++ snippets should produce valid expressions, but do not need to include // semicolons or newlines, which will be handled by the code generation itself. class UniformCTypeMapper { public: // Create a templated mapper that does not support state tracking UniformCTypeMapper(Layout::CType ctype, const std::vector& skslTypes, const char* setUniformFormat) : UniformCTypeMapper(ctype, skslTypes, setUniformFormat, false, "", "", "") { } // Create a templated mapper that provides extra patterns for the state // tracking expressions. UniformCTypeMapper(Layout::CType ctype, const std::vector& skslTypes, const String& setUniformFormat, const String& defaultValue, const String& dirtyExpressionFormat, const String& saveStateFormat) : UniformCTypeMapper(ctype, skslTypes, setUniformFormat, true, defaultValue, dirtyExpressionFormat, saveStateFormat) { } // Returns nullptr if the type and layout are not supported; the returned pointer's ownership // is not transfered to the caller. // // The returned mapper can support tracking even if tracking is disabled based on the flags in // the layout. static const UniformCTypeMapper* Get(const Context& context, const Type& type, const Layout& layout); static const UniformCTypeMapper* Get(const Context& context, const Variable& variable) { return Get(context, variable.fType, variable.fModifiers.fLayout); } // The C++ type name that this mapper applies to Layout::CType ctype() const { return fCType; } // The sksl type names that the mapper's ctype can be mapped to const std::vector& supportedTypeNames() const { return fSKSLTypes; } // Whether or not this handler knows how to write state tracking code // for the uniform variables bool supportsTracking() const { return fSupportsTracking; } // What the C++ class fields are initialized to in the GLSLFragmentProcessor The empty string // implies the no-arg constructor is suitable. This is not used if supportsTracking() returns // false. // // The returned snippet will be a valid as the lhs of an assignment. const String& defaultValue() const { return fDefaultValue; } // Return a boolean expression that returns true if the variables specified by newValueVarName // and oldValueVarName have different values. This is ignored if supportsTracking() returns // false. // // The returned snippet will be a valid expression to be inserted into the condition of an 'if' // statement. String dirtyExpression(const String& newValueVarName, const String& oldValueVarName) const; // Return a statement that stores the value of newValueVarName into the variable specified by // oldValueVarName. This is ignored if supportsTracking() returns false. // // The returned snippet will be a valid expression. String saveState(const String& newValueVarName, const String& oldValueVarName) const; // Return a statement that invokes the appropriate setX method on the GrGLSLProgramDataManager // specified by pdmanName, where the uniform is provided by the expression stored in // uniformHandleName, and valueVarName is the variable name pointing to the ctype instance // holding the new value. // // The returned snippet will be a valid expression. String setUniform(const String& pdmanName, const String& uniformHandleName, const String& valueVarName) const; // True if the setUniform() template only uses the value variable once in its expression. The // variable does not necessarily get inlined if this returns true, since a local variable may be // needed if state tracking is employed for a particular uniform. bool canInlineUniformValue() const { return fInlineValue; } private: UniformCTypeMapper(Layout::CType ctype, const std::vector& skslTypes, const String& setUniformFormat, bool enableTracking, const String& defaultValue, const String& dirtyExpressionFormat, const String& saveStateFormat); Layout::CType fCType; std::vector fSKSLTypes; String fUniformTemplate; bool fInlineValue; // Cached value calculated from fUniformTemplate bool fSupportsTracking; String fDefaultValue; String fDirtyExpressionTemplate; String fSaveStateTemplate; }; } // namespace #endif // SkSLUniformCTypes_DEFINED