1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2014 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker *
4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker */
7*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/glsl/GrGLSLShaderBuilder.h"
8*c8dee2aaSAndroid Build Coastguard Worker
9*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/gpu/ganesh/GrTypesPriv.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skcms/skcms.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkSLTypeShared.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/Blend.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/Swizzle.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrShaderCaps.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrShaderVar.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/glsl/GrGLSLColorSpaceXformHelper.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/glsl/GrGLSLProgramBuilder.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/glsl/GrGLSLProgramDataManager.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/SkSLGLSL.h"
20*c8dee2aaSAndroid Build Coastguard Worker
21*c8dee2aaSAndroid Build Coastguard Worker using namespace skia_private;
22*c8dee2aaSAndroid Build Coastguard Worker
GrGLSLShaderBuilder(GrGLSLProgramBuilder * program)23*c8dee2aaSAndroid Build Coastguard Worker GrGLSLShaderBuilder::GrGLSLShaderBuilder(GrGLSLProgramBuilder* program)
24*c8dee2aaSAndroid Build Coastguard Worker : fProgramBuilder(program)
25*c8dee2aaSAndroid Build Coastguard Worker , fInputs(GrGLSLProgramBuilder::kVarsPerBlock)
26*c8dee2aaSAndroid Build Coastguard Worker , fOutputs(GrGLSLProgramBuilder::kVarsPerBlock)
27*c8dee2aaSAndroid Build Coastguard Worker , fFeaturesAddedMask(0)
28*c8dee2aaSAndroid Build Coastguard Worker , fCodeIndex(kCode)
29*c8dee2aaSAndroid Build Coastguard Worker , fFinalized(false)
30*c8dee2aaSAndroid Build Coastguard Worker , fTmpVariableCounter(0) {
31*c8dee2aaSAndroid Build Coastguard Worker // We push back some placeholder pointers which will later become our header
32*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i <= kCode; i++) {
33*c8dee2aaSAndroid Build Coastguard Worker fShaderStrings.push_back();
34*c8dee2aaSAndroid Build Coastguard Worker }
35*c8dee2aaSAndroid Build Coastguard Worker
36*c8dee2aaSAndroid Build Coastguard Worker this->main() = "void main() {";
37*c8dee2aaSAndroid Build Coastguard Worker }
38*c8dee2aaSAndroid Build Coastguard Worker
declAppend(const GrShaderVar & var)39*c8dee2aaSAndroid Build Coastguard Worker void GrGLSLShaderBuilder::declAppend(const GrShaderVar& var) {
40*c8dee2aaSAndroid Build Coastguard Worker SkString tempDecl;
41*c8dee2aaSAndroid Build Coastguard Worker var.appendDecl(fProgramBuilder->shaderCaps(), &tempDecl);
42*c8dee2aaSAndroid Build Coastguard Worker this->codeAppendf("%s;", tempDecl.c_str());
43*c8dee2aaSAndroid Build Coastguard Worker }
44*c8dee2aaSAndroid Build Coastguard Worker
declareGlobal(const GrShaderVar & v)45*c8dee2aaSAndroid Build Coastguard Worker void GrGLSLShaderBuilder::declareGlobal(const GrShaderVar& v) {
46*c8dee2aaSAndroid Build Coastguard Worker v.appendDecl(this->getProgramBuilder()->shaderCaps(), &this->definitions());
47*c8dee2aaSAndroid Build Coastguard Worker this->definitions().append(";");
48*c8dee2aaSAndroid Build Coastguard Worker }
49*c8dee2aaSAndroid Build Coastguard Worker
getMangledFunctionName(const char * baseName)50*c8dee2aaSAndroid Build Coastguard Worker SkString GrGLSLShaderBuilder::getMangledFunctionName(const char* baseName) {
51*c8dee2aaSAndroid Build Coastguard Worker return fProgramBuilder->nameVariable(/*prefix=*/'\0', baseName);
52*c8dee2aaSAndroid Build Coastguard Worker }
53*c8dee2aaSAndroid Build Coastguard Worker
appendFunctionDecl(SkSLType returnType,const char * mangledName,SkSpan<const GrShaderVar> args)54*c8dee2aaSAndroid Build Coastguard Worker void GrGLSLShaderBuilder::appendFunctionDecl(SkSLType returnType,
55*c8dee2aaSAndroid Build Coastguard Worker const char* mangledName,
56*c8dee2aaSAndroid Build Coastguard Worker SkSpan<const GrShaderVar> args) {
57*c8dee2aaSAndroid Build Coastguard Worker this->functions().appendf("%s %s(", SkSLTypeString(returnType), mangledName);
58*c8dee2aaSAndroid Build Coastguard Worker for (size_t i = 0; i < args.size(); ++i) {
59*c8dee2aaSAndroid Build Coastguard Worker if (i > 0) {
60*c8dee2aaSAndroid Build Coastguard Worker this->functions().append(", ");
61*c8dee2aaSAndroid Build Coastguard Worker }
62*c8dee2aaSAndroid Build Coastguard Worker args[i].appendDecl(fProgramBuilder->shaderCaps(), &this->functions());
63*c8dee2aaSAndroid Build Coastguard Worker }
64*c8dee2aaSAndroid Build Coastguard Worker
65*c8dee2aaSAndroid Build Coastguard Worker this->functions().append(")");
66*c8dee2aaSAndroid Build Coastguard Worker }
67*c8dee2aaSAndroid Build Coastguard Worker
emitFunction(SkSLType returnType,const char * mangledName,SkSpan<const GrShaderVar> args,const char * body)68*c8dee2aaSAndroid Build Coastguard Worker void GrGLSLShaderBuilder::emitFunction(SkSLType returnType,
69*c8dee2aaSAndroid Build Coastguard Worker const char* mangledName,
70*c8dee2aaSAndroid Build Coastguard Worker SkSpan<const GrShaderVar> args,
71*c8dee2aaSAndroid Build Coastguard Worker const char* body) {
72*c8dee2aaSAndroid Build Coastguard Worker this->appendFunctionDecl(returnType, mangledName, args);
73*c8dee2aaSAndroid Build Coastguard Worker this->functions().appendf(" {\n"
74*c8dee2aaSAndroid Build Coastguard Worker "%s"
75*c8dee2aaSAndroid Build Coastguard Worker "}\n\n", body);
76*c8dee2aaSAndroid Build Coastguard Worker }
77*c8dee2aaSAndroid Build Coastguard Worker
emitFunction(const char * declaration,const char * body)78*c8dee2aaSAndroid Build Coastguard Worker void GrGLSLShaderBuilder::emitFunction(const char* declaration, const char* body) {
79*c8dee2aaSAndroid Build Coastguard Worker this->functions().appendf("%s {\n"
80*c8dee2aaSAndroid Build Coastguard Worker "%s"
81*c8dee2aaSAndroid Build Coastguard Worker "}\n\n", declaration, body);
82*c8dee2aaSAndroid Build Coastguard Worker }
83*c8dee2aaSAndroid Build Coastguard Worker
emitFunctionPrototype(SkSLType returnType,const char * mangledName,SkSpan<const GrShaderVar> args)84*c8dee2aaSAndroid Build Coastguard Worker void GrGLSLShaderBuilder::emitFunctionPrototype(SkSLType returnType,
85*c8dee2aaSAndroid Build Coastguard Worker const char* mangledName,
86*c8dee2aaSAndroid Build Coastguard Worker SkSpan<const GrShaderVar> args) {
87*c8dee2aaSAndroid Build Coastguard Worker this->appendFunctionDecl(returnType, mangledName, args);
88*c8dee2aaSAndroid Build Coastguard Worker this->functions().append(";\n");
89*c8dee2aaSAndroid Build Coastguard Worker }
90*c8dee2aaSAndroid Build Coastguard Worker
emitFunctionPrototype(const char * declaration)91*c8dee2aaSAndroid Build Coastguard Worker void GrGLSLShaderBuilder::emitFunctionPrototype(const char* declaration) {
92*c8dee2aaSAndroid Build Coastguard Worker this->functions().appendf("%s\n", declaration);
93*c8dee2aaSAndroid Build Coastguard Worker }
94*c8dee2aaSAndroid Build Coastguard Worker
append_texture_swizzle(SkString * out,skgpu::Swizzle swizzle)95*c8dee2aaSAndroid Build Coastguard Worker static inline void append_texture_swizzle(SkString* out, skgpu::Swizzle swizzle) {
96*c8dee2aaSAndroid Build Coastguard Worker if (swizzle != skgpu::Swizzle::RGBA()) {
97*c8dee2aaSAndroid Build Coastguard Worker out->appendf(".%s", swizzle.asString().c_str());
98*c8dee2aaSAndroid Build Coastguard Worker }
99*c8dee2aaSAndroid Build Coastguard Worker }
100*c8dee2aaSAndroid Build Coastguard Worker
appendTextureLookup(SkString * out,SamplerHandle samplerHandle,const char * coordName) const101*c8dee2aaSAndroid Build Coastguard Worker void GrGLSLShaderBuilder::appendTextureLookup(SkString* out,
102*c8dee2aaSAndroid Build Coastguard Worker SamplerHandle samplerHandle,
103*c8dee2aaSAndroid Build Coastguard Worker const char* coordName) const {
104*c8dee2aaSAndroid Build Coastguard Worker const char* sampler = fProgramBuilder->samplerVariable(samplerHandle);
105*c8dee2aaSAndroid Build Coastguard Worker out->appendf("sample(%s, %s)", sampler, coordName);
106*c8dee2aaSAndroid Build Coastguard Worker append_texture_swizzle(out, fProgramBuilder->samplerSwizzle(samplerHandle));
107*c8dee2aaSAndroid Build Coastguard Worker }
108*c8dee2aaSAndroid Build Coastguard Worker
appendTextureLookup(SamplerHandle samplerHandle,const char * coordName,GrGLSLColorSpaceXformHelper * colorXformHelper)109*c8dee2aaSAndroid Build Coastguard Worker void GrGLSLShaderBuilder::appendTextureLookup(SamplerHandle samplerHandle,
110*c8dee2aaSAndroid Build Coastguard Worker const char* coordName,
111*c8dee2aaSAndroid Build Coastguard Worker GrGLSLColorSpaceXformHelper* colorXformHelper) {
112*c8dee2aaSAndroid Build Coastguard Worker SkString lookup;
113*c8dee2aaSAndroid Build Coastguard Worker this->appendTextureLookup(&lookup, samplerHandle, coordName);
114*c8dee2aaSAndroid Build Coastguard Worker this->appendColorGamutXform(lookup.c_str(), colorXformHelper);
115*c8dee2aaSAndroid Build Coastguard Worker }
116*c8dee2aaSAndroid Build Coastguard Worker
appendTextureLookupAndBlend(const char * dst,SkBlendMode mode,SamplerHandle samplerHandle,const char * coordName,GrGLSLColorSpaceXformHelper * colorXformHelper)117*c8dee2aaSAndroid Build Coastguard Worker void GrGLSLShaderBuilder::appendTextureLookupAndBlend(
118*c8dee2aaSAndroid Build Coastguard Worker const char* dst,
119*c8dee2aaSAndroid Build Coastguard Worker SkBlendMode mode,
120*c8dee2aaSAndroid Build Coastguard Worker SamplerHandle samplerHandle,
121*c8dee2aaSAndroid Build Coastguard Worker const char* coordName,
122*c8dee2aaSAndroid Build Coastguard Worker GrGLSLColorSpaceXformHelper* colorXformHelper) {
123*c8dee2aaSAndroid Build Coastguard Worker if (!dst) {
124*c8dee2aaSAndroid Build Coastguard Worker dst = "half4(1)";
125*c8dee2aaSAndroid Build Coastguard Worker }
126*c8dee2aaSAndroid Build Coastguard Worker SkString lookup;
127*c8dee2aaSAndroid Build Coastguard Worker this->codeAppendf("%s(", skgpu::BlendFuncName(mode));
128*c8dee2aaSAndroid Build Coastguard Worker this->appendTextureLookup(&lookup, samplerHandle, coordName);
129*c8dee2aaSAndroid Build Coastguard Worker this->appendColorGamutXform(lookup.c_str(), colorXformHelper);
130*c8dee2aaSAndroid Build Coastguard Worker this->codeAppendf(", %s)", dst);
131*c8dee2aaSAndroid Build Coastguard Worker }
132*c8dee2aaSAndroid Build Coastguard Worker
appendInputLoad(SamplerHandle samplerHandle)133*c8dee2aaSAndroid Build Coastguard Worker void GrGLSLShaderBuilder::appendInputLoad(SamplerHandle samplerHandle) {
134*c8dee2aaSAndroid Build Coastguard Worker const char* input = fProgramBuilder->inputSamplerVariable(samplerHandle);
135*c8dee2aaSAndroid Build Coastguard Worker SkString load;
136*c8dee2aaSAndroid Build Coastguard Worker load.appendf("subpassLoad(%s)", input);
137*c8dee2aaSAndroid Build Coastguard Worker append_texture_swizzle(&load, fProgramBuilder->inputSamplerSwizzle(samplerHandle));
138*c8dee2aaSAndroid Build Coastguard Worker this->codeAppend(load.c_str());
139*c8dee2aaSAndroid Build Coastguard Worker }
140*c8dee2aaSAndroid Build Coastguard Worker
appendColorGamutXform(SkString * out,const char * srcColor,GrGLSLColorSpaceXformHelper * colorXformHelper)141*c8dee2aaSAndroid Build Coastguard Worker void GrGLSLShaderBuilder::appendColorGamutXform(SkString* out,
142*c8dee2aaSAndroid Build Coastguard Worker const char* srcColor,
143*c8dee2aaSAndroid Build Coastguard Worker GrGLSLColorSpaceXformHelper* colorXformHelper) {
144*c8dee2aaSAndroid Build Coastguard Worker if (!colorXformHelper || colorXformHelper->isNoop()) {
145*c8dee2aaSAndroid Build Coastguard Worker *out = srcColor;
146*c8dee2aaSAndroid Build Coastguard Worker return;
147*c8dee2aaSAndroid Build Coastguard Worker }
148*c8dee2aaSAndroid Build Coastguard Worker
149*c8dee2aaSAndroid Build Coastguard Worker GrGLSLUniformHandler* uniformHandler = fProgramBuilder->uniformHandler();
150*c8dee2aaSAndroid Build Coastguard Worker
151*c8dee2aaSAndroid Build Coastguard Worker // We define up to three helper functions, to keep things clearer. One for the source transfer
152*c8dee2aaSAndroid Build Coastguard Worker // function, one for the (inverse) destination transfer function, and one for the gamut xform.
153*c8dee2aaSAndroid Build Coastguard Worker // Any combination of these may be present, although some configurations are much more likely.
154*c8dee2aaSAndroid Build Coastguard Worker
155*c8dee2aaSAndroid Build Coastguard Worker auto emitTFFunc = [this, &uniformHandler](const char* name,
156*c8dee2aaSAndroid Build Coastguard Worker GrGLSLProgramDataManager::UniformHandle uniform,
157*c8dee2aaSAndroid Build Coastguard Worker skcms_TFType tfType) {
158*c8dee2aaSAndroid Build Coastguard Worker const GrShaderVar gTFArgs[] = { GrShaderVar("x", SkSLType::kFloat) };
159*c8dee2aaSAndroid Build Coastguard Worker const char* coeffs = uniformHandler->getUniformCStr(uniform);
160*c8dee2aaSAndroid Build Coastguard Worker SkString body;
161*c8dee2aaSAndroid Build Coastguard Worker // Temporaries to make evaluation line readable. We always use the sRGBish names, so the
162*c8dee2aaSAndroid Build Coastguard Worker // PQ and HLG math is confusing.
163*c8dee2aaSAndroid Build Coastguard Worker body.appendf("float G = %s[0];", coeffs);
164*c8dee2aaSAndroid Build Coastguard Worker body.appendf("float A = %s[1];", coeffs);
165*c8dee2aaSAndroid Build Coastguard Worker body.appendf("float B = %s[2];", coeffs);
166*c8dee2aaSAndroid Build Coastguard Worker body.appendf("float C = %s[3];", coeffs);
167*c8dee2aaSAndroid Build Coastguard Worker body.appendf("float D = %s[4];", coeffs);
168*c8dee2aaSAndroid Build Coastguard Worker body.appendf("float E = %s[5];", coeffs);
169*c8dee2aaSAndroid Build Coastguard Worker body.appendf("float F = %s[6];", coeffs);
170*c8dee2aaSAndroid Build Coastguard Worker body.append("float s = sign(x);");
171*c8dee2aaSAndroid Build Coastguard Worker body.append("x = abs(x);");
172*c8dee2aaSAndroid Build Coastguard Worker switch (tfType) {
173*c8dee2aaSAndroid Build Coastguard Worker case skcms_TFType_sRGBish:
174*c8dee2aaSAndroid Build Coastguard Worker body.append("x = (x < D) ? (C * x) + F : pow(A * x + B, G) + E;");
175*c8dee2aaSAndroid Build Coastguard Worker break;
176*c8dee2aaSAndroid Build Coastguard Worker case skcms_TFType_PQish:
177*c8dee2aaSAndroid Build Coastguard Worker body.append("x = pow(max(A + B * pow(x, C), 0) / (D + E * pow(x, C)), F);");
178*c8dee2aaSAndroid Build Coastguard Worker break;
179*c8dee2aaSAndroid Build Coastguard Worker case skcms_TFType_HLGish:
180*c8dee2aaSAndroid Build Coastguard Worker body.append("x = (x*A <= 1) ? pow(x*A, B) : exp((x-E)*C) + D; x *= (F+1);");
181*c8dee2aaSAndroid Build Coastguard Worker break;
182*c8dee2aaSAndroid Build Coastguard Worker case skcms_TFType_HLGinvish:
183*c8dee2aaSAndroid Build Coastguard Worker body.append("x /= (F+1); x = (x <= 1) ? A * pow(x, B) : C * log(x - D) + E;");
184*c8dee2aaSAndroid Build Coastguard Worker break;
185*c8dee2aaSAndroid Build Coastguard Worker default:
186*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(false);
187*c8dee2aaSAndroid Build Coastguard Worker break;
188*c8dee2aaSAndroid Build Coastguard Worker }
189*c8dee2aaSAndroid Build Coastguard Worker body.append("return s * x;");
190*c8dee2aaSAndroid Build Coastguard Worker SkString funcName = this->getMangledFunctionName(name);
191*c8dee2aaSAndroid Build Coastguard Worker this->emitFunction(SkSLType::kFloat, funcName.c_str(), {gTFArgs, std::size(gTFArgs)},
192*c8dee2aaSAndroid Build Coastguard Worker body.c_str());
193*c8dee2aaSAndroid Build Coastguard Worker return funcName;
194*c8dee2aaSAndroid Build Coastguard Worker };
195*c8dee2aaSAndroid Build Coastguard Worker
196*c8dee2aaSAndroid Build Coastguard Worker SkString srcTFFuncName;
197*c8dee2aaSAndroid Build Coastguard Worker if (colorXformHelper->applySrcTF()) {
198*c8dee2aaSAndroid Build Coastguard Worker srcTFFuncName = emitTFFunc("src_tf", colorXformHelper->srcTFUniform(),
199*c8dee2aaSAndroid Build Coastguard Worker colorXformHelper->srcTFType());
200*c8dee2aaSAndroid Build Coastguard Worker }
201*c8dee2aaSAndroid Build Coastguard Worker
202*c8dee2aaSAndroid Build Coastguard Worker SkString dstTFFuncName;
203*c8dee2aaSAndroid Build Coastguard Worker if (colorXformHelper->applyDstTF()) {
204*c8dee2aaSAndroid Build Coastguard Worker dstTFFuncName = emitTFFunc("dst_tf", colorXformHelper->dstTFUniform(),
205*c8dee2aaSAndroid Build Coastguard Worker colorXformHelper->dstTFType());
206*c8dee2aaSAndroid Build Coastguard Worker }
207*c8dee2aaSAndroid Build Coastguard Worker
208*c8dee2aaSAndroid Build Coastguard Worker SkString gamutXformFuncName;
209*c8dee2aaSAndroid Build Coastguard Worker if (colorXformHelper->applyGamutXform()) {
210*c8dee2aaSAndroid Build Coastguard Worker const GrShaderVar gGamutXformArgs[] = { GrShaderVar("color", SkSLType::kFloat4) };
211*c8dee2aaSAndroid Build Coastguard Worker const char* xform = uniformHandler->getUniformCStr(colorXformHelper->gamutXformUniform());
212*c8dee2aaSAndroid Build Coastguard Worker SkString body;
213*c8dee2aaSAndroid Build Coastguard Worker body.appendf("color.rgb = (%s * color.rgb);", xform);
214*c8dee2aaSAndroid Build Coastguard Worker body.append("return color;");
215*c8dee2aaSAndroid Build Coastguard Worker gamutXformFuncName = this->getMangledFunctionName("gamut_xform");
216*c8dee2aaSAndroid Build Coastguard Worker this->emitFunction(SkSLType::kFloat4, gamutXformFuncName.c_str(),
217*c8dee2aaSAndroid Build Coastguard Worker {gGamutXformArgs, std::size(gGamutXformArgs)}, body.c_str());
218*c8dee2aaSAndroid Build Coastguard Worker }
219*c8dee2aaSAndroid Build Coastguard Worker
220*c8dee2aaSAndroid Build Coastguard Worker // Now define a wrapper function that applies all the intermediate steps
221*c8dee2aaSAndroid Build Coastguard Worker {
222*c8dee2aaSAndroid Build Coastguard Worker const GrShaderVar gColorXformArgs[] = { GrShaderVar("color", SkSLType::kFloat4) };
223*c8dee2aaSAndroid Build Coastguard Worker SkString body;
224*c8dee2aaSAndroid Build Coastguard Worker if (colorXformHelper->applyUnpremul()) {
225*c8dee2aaSAndroid Build Coastguard Worker body.append("color = unpremul(color);");
226*c8dee2aaSAndroid Build Coastguard Worker }
227*c8dee2aaSAndroid Build Coastguard Worker if (colorXformHelper->applySrcTF()) {
228*c8dee2aaSAndroid Build Coastguard Worker body.appendf("color.r = %s(color.r);", srcTFFuncName.c_str());
229*c8dee2aaSAndroid Build Coastguard Worker body.appendf("color.g = %s(color.g);", srcTFFuncName.c_str());
230*c8dee2aaSAndroid Build Coastguard Worker body.appendf("color.b = %s(color.b);", srcTFFuncName.c_str());
231*c8dee2aaSAndroid Build Coastguard Worker }
232*c8dee2aaSAndroid Build Coastguard Worker if (colorXformHelper->applyGamutXform()) {
233*c8dee2aaSAndroid Build Coastguard Worker body.appendf("color = %s(color);", gamutXformFuncName.c_str());
234*c8dee2aaSAndroid Build Coastguard Worker }
235*c8dee2aaSAndroid Build Coastguard Worker if (colorXformHelper->applyDstTF()) {
236*c8dee2aaSAndroid Build Coastguard Worker body.appendf("color.r = %s(color.r);", dstTFFuncName.c_str());
237*c8dee2aaSAndroid Build Coastguard Worker body.appendf("color.g = %s(color.g);", dstTFFuncName.c_str());
238*c8dee2aaSAndroid Build Coastguard Worker body.appendf("color.b = %s(color.b);", dstTFFuncName.c_str());
239*c8dee2aaSAndroid Build Coastguard Worker }
240*c8dee2aaSAndroid Build Coastguard Worker if (colorXformHelper->applyPremul()) {
241*c8dee2aaSAndroid Build Coastguard Worker body.append("color.rgb *= color.a;");
242*c8dee2aaSAndroid Build Coastguard Worker }
243*c8dee2aaSAndroid Build Coastguard Worker body.append("return half4(color);");
244*c8dee2aaSAndroid Build Coastguard Worker SkString colorXformFuncName = this->getMangledFunctionName("color_xform");
245*c8dee2aaSAndroid Build Coastguard Worker this->emitFunction(SkSLType::kHalf4, colorXformFuncName.c_str(),
246*c8dee2aaSAndroid Build Coastguard Worker {gColorXformArgs, std::size(gColorXformArgs)}, body.c_str());
247*c8dee2aaSAndroid Build Coastguard Worker out->appendf("%s(%s)", colorXformFuncName.c_str(), srcColor);
248*c8dee2aaSAndroid Build Coastguard Worker }
249*c8dee2aaSAndroid Build Coastguard Worker }
250*c8dee2aaSAndroid Build Coastguard Worker
appendColorGamutXform(const char * srcColor,GrGLSLColorSpaceXformHelper * colorXformHelper)251*c8dee2aaSAndroid Build Coastguard Worker void GrGLSLShaderBuilder::appendColorGamutXform(const char* srcColor,
252*c8dee2aaSAndroid Build Coastguard Worker GrGLSLColorSpaceXformHelper* colorXformHelper) {
253*c8dee2aaSAndroid Build Coastguard Worker SkString xform;
254*c8dee2aaSAndroid Build Coastguard Worker this->appendColorGamutXform(&xform, srcColor, colorXformHelper);
255*c8dee2aaSAndroid Build Coastguard Worker this->codeAppend(xform.c_str());
256*c8dee2aaSAndroid Build Coastguard Worker }
257*c8dee2aaSAndroid Build Coastguard Worker
addFeature(uint32_t featureBit,const char * extensionName)258*c8dee2aaSAndroid Build Coastguard Worker bool GrGLSLShaderBuilder::addFeature(uint32_t featureBit, const char* extensionName) {
259*c8dee2aaSAndroid Build Coastguard Worker if (featureBit & fFeaturesAddedMask) {
260*c8dee2aaSAndroid Build Coastguard Worker return false;
261*c8dee2aaSAndroid Build Coastguard Worker }
262*c8dee2aaSAndroid Build Coastguard Worker this->extensions().appendf("#extension %s: require\n", extensionName);
263*c8dee2aaSAndroid Build Coastguard Worker fFeaturesAddedMask |= featureBit;
264*c8dee2aaSAndroid Build Coastguard Worker return true;
265*c8dee2aaSAndroid Build Coastguard Worker }
266*c8dee2aaSAndroid Build Coastguard Worker
appendDecls(const VarArray & vars,SkString * out) const267*c8dee2aaSAndroid Build Coastguard Worker void GrGLSLShaderBuilder::appendDecls(const VarArray& vars, SkString* out) const {
268*c8dee2aaSAndroid Build Coastguard Worker for (const auto& v : vars.items()) {
269*c8dee2aaSAndroid Build Coastguard Worker v.appendDecl(fProgramBuilder->shaderCaps(), out);
270*c8dee2aaSAndroid Build Coastguard Worker out->append(";\n");
271*c8dee2aaSAndroid Build Coastguard Worker }
272*c8dee2aaSAndroid Build Coastguard Worker }
273*c8dee2aaSAndroid Build Coastguard Worker
addLayoutQualifier(const char * param,InterfaceQualifier interface)274*c8dee2aaSAndroid Build Coastguard Worker void GrGLSLShaderBuilder::addLayoutQualifier(const char* param, InterfaceQualifier interface) {
275*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(fProgramBuilder->shaderCaps()->fGLSLGeneration >= SkSL::GLSLGeneration::k330 ||
276*c8dee2aaSAndroid Build Coastguard Worker fProgramBuilder->shaderCaps()->mustEnableAdvBlendEqs());
277*c8dee2aaSAndroid Build Coastguard Worker fLayoutParams[interface].push_back() = param;
278*c8dee2aaSAndroid Build Coastguard Worker }
279*c8dee2aaSAndroid Build Coastguard Worker
compileAndAppendLayoutQualifiers()280*c8dee2aaSAndroid Build Coastguard Worker void GrGLSLShaderBuilder::compileAndAppendLayoutQualifiers() {
281*c8dee2aaSAndroid Build Coastguard Worker static const char* interfaceQualifierNames[] = {
282*c8dee2aaSAndroid Build Coastguard Worker "in",
283*c8dee2aaSAndroid Build Coastguard Worker "out"
284*c8dee2aaSAndroid Build Coastguard Worker };
285*c8dee2aaSAndroid Build Coastguard Worker
286*c8dee2aaSAndroid Build Coastguard Worker for (int interface = 0; interface <= kLastInterfaceQualifier; ++interface) {
287*c8dee2aaSAndroid Build Coastguard Worker const TArray<SkString>& params = fLayoutParams[interface];
288*c8dee2aaSAndroid Build Coastguard Worker if (params.empty()) {
289*c8dee2aaSAndroid Build Coastguard Worker continue;
290*c8dee2aaSAndroid Build Coastguard Worker }
291*c8dee2aaSAndroid Build Coastguard Worker this->layoutQualifiers().appendf("layout(%s", params[0].c_str());
292*c8dee2aaSAndroid Build Coastguard Worker for (int i = 1; i < params.size(); ++i) {
293*c8dee2aaSAndroid Build Coastguard Worker this->layoutQualifiers().appendf(", %s", params[i].c_str());
294*c8dee2aaSAndroid Build Coastguard Worker }
295*c8dee2aaSAndroid Build Coastguard Worker this->layoutQualifiers().appendf(") %s;\n", interfaceQualifierNames[interface]);
296*c8dee2aaSAndroid Build Coastguard Worker }
297*c8dee2aaSAndroid Build Coastguard Worker
298*c8dee2aaSAndroid Build Coastguard Worker static_assert(0 == GrGLSLShaderBuilder::kIn_InterfaceQualifier);
299*c8dee2aaSAndroid Build Coastguard Worker static_assert(1 == GrGLSLShaderBuilder::kOut_InterfaceQualifier);
300*c8dee2aaSAndroid Build Coastguard Worker static_assert(std::size(interfaceQualifierNames) == kLastInterfaceQualifier + 1);
301*c8dee2aaSAndroid Build Coastguard Worker }
302*c8dee2aaSAndroid Build Coastguard Worker
finalize(uint32_t visibility)303*c8dee2aaSAndroid Build Coastguard Worker void GrGLSLShaderBuilder::finalize(uint32_t visibility) {
304*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(!fFinalized);
305*c8dee2aaSAndroid Build Coastguard Worker this->compileAndAppendLayoutQualifiers();
306*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(visibility);
307*c8dee2aaSAndroid Build Coastguard Worker fProgramBuilder->appendUniformDecls((GrShaderFlags) visibility, &this->uniforms());
308*c8dee2aaSAndroid Build Coastguard Worker this->appendDecls(fInputs, &this->inputs());
309*c8dee2aaSAndroid Build Coastguard Worker this->appendDecls(fOutputs, &this->outputs());
310*c8dee2aaSAndroid Build Coastguard Worker this->onFinalize();
311*c8dee2aaSAndroid Build Coastguard Worker // append the 'footer' to code
312*c8dee2aaSAndroid Build Coastguard Worker this->code().append("}");
313*c8dee2aaSAndroid Build Coastguard Worker
314*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i <= fCodeIndex; i++) {
315*c8dee2aaSAndroid Build Coastguard Worker fCompilerString.append(fShaderStrings[i].c_str(), fShaderStrings[i].size());
316*c8dee2aaSAndroid Build Coastguard Worker }
317*c8dee2aaSAndroid Build Coastguard Worker
318*c8dee2aaSAndroid Build Coastguard Worker fFinalized = true;
319*c8dee2aaSAndroid Build Coastguard Worker }
320