1 /* 2 * Copyright 2016 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #ifndef SKSL_CODEGENERATOR 9 #define SKSL_CODEGENERATOR 10 11 #include "src/sksl/SkSLOutputStream.h" 12 #include "src/sksl/ir/SkSLProgram.h" 13 14 namespace SkSL { 15 16 /** 17 * Abstract superclass of all code generators, which take a Program as input and produce code as 18 * output. 19 */ 20 class CodeGenerator { 21 public: CodeGenerator(const Context * context,const Program * program,OutputStream * out)22 CodeGenerator(const Context* context, const Program* program, OutputStream* out) 23 : fContext(*context) 24 , fProgram(*program) 25 , fOut(out) {} 26 ~CodeGenerator()27 virtual ~CodeGenerator() {} 28 29 virtual bool generateCode() = 0; 30 31 // Intended for use by AutoOutputStream. outputStream()32 OutputStream* outputStream() { return fOut; } setOutputStream(OutputStream * output)33 void setOutputStream(OutputStream* output) { fOut = output; } 34 35 protected: 36 #if defined(SK_USE_LEGACY_MIPMAP_LOD_BIAS) 37 static constexpr float kSharpenTexturesBias = -.5f; 38 #else 39 // For SkMipmapMode::kLinear we want a bias such that when the unbiased LOD value is 40 // midway between levels we select just the larger level, i.e. a bias of -.5. However, using 41 // this bias with kNearest mode with a draw that is a perfect power of two downscale puts us 42 // right on the rounding edge where it could go up or down depending on the particular GPU. 43 // Experimentally we found that at -.49 most iOS devices (iPhone 7, 8, and iPad Pro 44 // [PowerVRGT7800 version]) all round to the level twice as big as the device space footprint 45 // for some such draws in our unit tests on GLES. However, the iPhone 11 still fails and so 46 // we are using -.475. They do not at -.48. All other GPUs passed tests with -.499. Though, at 47 // this time the bias is not implemented in the MSL codegen and so iOS/Metal was not tested. 48 static constexpr float kSharpenTexturesBias = -.475f; 49 #endif 50 51 const Context& fContext; 52 const Program& fProgram; 53 OutputStream* fOut; 54 }; 55 56 class AutoOutputStream { 57 public: 58 // Maintains the current indentation level while writing to the new output stream. AutoOutputStream(CodeGenerator * codeGen,OutputStream * newOutput)59 AutoOutputStream(CodeGenerator* codeGen, OutputStream* newOutput) 60 : fCodeGen(codeGen) 61 , fOldOutput(codeGen->outputStream()) { 62 fCodeGen->setOutputStream(newOutput); 63 } 64 // Resets the indentation when entering the scope, and restores it when leaving. AutoOutputStream(CodeGenerator * codeGen,OutputStream * newOutput,int * indentationPtr)65 AutoOutputStream(CodeGenerator* codeGen, OutputStream* newOutput, int *indentationPtr) 66 : fCodeGen(codeGen) 67 , fOldOutput(codeGen->outputStream()) 68 , fIndentationPtr(indentationPtr) 69 , fOldIndentation(indentationPtr ? *indentationPtr : 0) { 70 fCodeGen->setOutputStream(newOutput); 71 *fIndentationPtr = 0; 72 } ~AutoOutputStream()73 ~AutoOutputStream() { 74 fCodeGen->setOutputStream(fOldOutput); 75 if (fIndentationPtr) { 76 *fIndentationPtr = fOldIndentation; 77 } 78 } 79 80 private: 81 CodeGenerator* fCodeGen = nullptr; 82 OutputStream* fOldOutput = nullptr; 83 int *fIndentationPtr = nullptr; 84 int fOldIndentation = 0; 85 }; 86 87 } // namespace SkSL 88 89 #endif 90