From 30ba436f04e61d4505fb854d5fc56079636e0788 Mon Sep 17 00:00:00 2001 From: joshualitt Date: Thu, 21 Aug 2014 20:18:45 -0700 Subject: Initial refactor of shaderbuilder to prepare for geometry shaders gitignore for eclipse BUG=skia: R=bsalomon@google.com, bsalomon@chromium.org Author: joshualitt@chromium.org Review URL: https://codereview.chromium.org/491673002 --- .gitignore | 3 + gyp/gpu.gypi | 18 +- include/core/SkString.h | 1 + include/gpu/GrEffect.h | 2 +- src/core/SkString.cpp | 8 + src/core/SkXfermode.cpp | 189 ++-- src/effects/SkAlphaThresholdFilter.cpp | 44 +- src/effects/SkArithmeticMode.cpp | 35 +- src/effects/SkBlurMaskFilter.cpp | 113 ++- src/effects/SkColorFilters.cpp | 9 +- src/effects/SkColorMatrixFilter.cpp | 17 +- src/effects/SkDisplacementMapEffect.cpp | 45 +- src/effects/SkLightingImageFilter.cpp | 145 +-- src/effects/SkLumaColorFilter.cpp | 9 +- src/effects/SkMagnifierImageFilter.cpp | 61 +- src/effects/SkMorphologyImageFilter.cpp | 31 +- src/effects/SkPerlinNoiseShader.cpp | 69 +- src/effects/SkTableColorFilter.cpp | 41 +- src/effects/gradients/SkGradientShader.cpp | 51 +- src/effects/gradients/SkGradientShaderPriv.h | 4 +- src/effects/gradients/SkLinearGradient.cpp | 8 +- src/effects/gradients/SkRadialGradient.cpp | 8 +- src/effects/gradients/SkSweepGradient.cpp | 8 +- .../gradients/SkTwoPointConicalGradient_gpu.cpp | 107 +- src/effects/gradients/SkTwoPointRadialGradient.cpp | 17 +- src/gpu/GrAAConvexPathRenderer.cpp | 41 +- src/gpu/GrAARectRenderer.cpp | 72 +- src/gpu/GrOvalRenderer.cpp | 117 ++- src/gpu/effects/GrBezierEffect.cpp | 198 ++-- src/gpu/effects/GrBicubicEffect.cpp | 31 +- src/gpu/effects/GrConfigConversionEffect.cpp | 29 +- src/gpu/effects/GrConvexPolyEffect.cpp | 65 +- src/gpu/effects/GrConvolutionEffect.cpp | 32 +- src/gpu/effects/GrCustomCoordsTextureEffect.cpp | 18 +- src/gpu/effects/GrDashingEffect.cpp | 73 +- src/gpu/effects/GrDistanceFieldTextureEffect.cpp | 206 ++-- src/gpu/effects/GrDistanceFieldTextureEffect.h | 4 +- src/gpu/effects/GrDitherEffect.cpp | 13 +- src/gpu/effects/GrMatrixConvolutionEffect.cpp | 52 +- src/gpu/effects/GrOvalEffect.cpp | 54 +- src/gpu/effects/GrRRectEffect.cpp | 138 +-- src/gpu/effects/GrSimpleTextureEffect.cpp | 11 +- src/gpu/effects/GrTextureDomain.cpp | 71 +- src/gpu/effects/GrTextureDomain.h | 1 + src/gpu/effects/GrYUVtoRGBEffect.cpp | 21 +- src/gpu/gl/GrGLEffect.h | 2 +- src/gpu/gl/GrGLProgram.cpp | 9 +- src/gpu/gl/GrGLProgram.h | 8 +- src/gpu/gl/GrGLProgramDataManager.cpp | 10 +- src/gpu/gl/GrGLProgramDataManager.h | 6 +- src/gpu/gl/GrGLProgramDesc.cpp | 9 +- src/gpu/gl/GrGLProgramDesc.h | 9 +- src/gpu/gl/GrGLProgramEffects.cpp | 66 +- src/gpu/gl/GrGLProgramEffects.h | 54 +- src/gpu/gl/GrGLSLPrettyPrint.cpp | 173 ---- src/gpu/gl/GrGLShaderBuilder.cpp | 1071 -------------------- src/gpu/gl/GrGLShaderBuilder.h | 517 ---------- src/gpu/gl/GrGLVertexEffect.h | 8 +- src/gpu/gl/GrGpuGL.cpp | 1 - src/gpu/gl/builders/GrGLFragmentShaderBuilder.cpp | 351 +++++++ src/gpu/gl/builders/GrGLFragmentShaderBuilder.h | 118 +++ src/gpu/gl/builders/GrGLGeometryShaderBuilder.cpp | 70 ++ src/gpu/gl/builders/GrGLGeometryShaderBuilder.h | 32 + src/gpu/gl/builders/GrGLProgramBuilder.cpp | 409 ++++++++ src/gpu/gl/builders/GrGLProgramBuilder.h | 318 ++++++ src/gpu/gl/builders/GrGLSLPrettyPrint.cpp | 173 ++++ src/gpu/gl/builders/GrGLShaderBuilder.cpp | 155 +++ src/gpu/gl/builders/GrGLShaderBuilder.h | 170 ++++ src/gpu/gl/builders/GrGLShaderStringBuilder.cpp | 85 ++ src/gpu/gl/builders/GrGLShaderStringBuilder.h | 20 + src/gpu/gl/builders/GrGLVertexShaderBuilder.cpp | 200 ++++ src/gpu/gl/builders/GrGLVertexShaderBuilder.h | 81 ++ tests/GLProgramsTest.cpp | 4 +- 73 files changed, 3472 insertions(+), 2947 deletions(-) delete mode 100644 src/gpu/gl/GrGLSLPrettyPrint.cpp delete mode 100644 src/gpu/gl/GrGLShaderBuilder.cpp delete mode 100644 src/gpu/gl/GrGLShaderBuilder.h create mode 100644 src/gpu/gl/builders/GrGLFragmentShaderBuilder.cpp create mode 100644 src/gpu/gl/builders/GrGLFragmentShaderBuilder.h create mode 100644 src/gpu/gl/builders/GrGLGeometryShaderBuilder.cpp create mode 100644 src/gpu/gl/builders/GrGLGeometryShaderBuilder.h create mode 100644 src/gpu/gl/builders/GrGLProgramBuilder.cpp create mode 100644 src/gpu/gl/builders/GrGLProgramBuilder.h create mode 100644 src/gpu/gl/builders/GrGLSLPrettyPrint.cpp create mode 100644 src/gpu/gl/builders/GrGLShaderBuilder.cpp create mode 100644 src/gpu/gl/builders/GrGLShaderBuilder.h create mode 100644 src/gpu/gl/builders/GrGLShaderStringBuilder.cpp create mode 100644 src/gpu/gl/builders/GrGLShaderStringBuilder.h create mode 100644 src/gpu/gl/builders/GrGLVertexShaderBuilder.cpp create mode 100644 src/gpu/gl/builders/GrGLVertexShaderBuilder.h diff --git a/.gitignore b/.gitignore index 27ddb22809..cedd0baa7d 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,9 @@ .android_config .gclient* .gm-actuals +.cproject +.project +.settings/ TAGS common gyp/build diff --git a/gyp/gpu.gypi b/gyp/gpu.gypi index 56ef4b5a63..f00cfac733 100644 --- a/gyp/gpu.gypi +++ b/gyp/gpu.gypi @@ -208,7 +208,6 @@ '<(skia_src_path)/gpu/gl/GrGLPathRange.h', '<(skia_src_path)/gpu/gl/GrGLPathRendering.cpp', '<(skia_src_path)/gpu/gl/GrGLPathRendering.h', - '<(skia_src_path)/gpu/gl/GrGLSLPrettyPrint.cpp', '<(skia_src_path)/gpu/gl/GrGLProgram.cpp', '<(skia_src_path)/gpu/gl/GrGLProgram.h', '<(skia_src_path)/gpu/gl/GrGLProgramDesc.cpp', @@ -219,8 +218,6 @@ '<(skia_src_path)/gpu/gl/GrGLProgramDataManager.h', '<(skia_src_path)/gpu/gl/GrGLRenderTarget.cpp', '<(skia_src_path)/gpu/gl/GrGLRenderTarget.h', - '<(skia_src_path)/gpu/gl/GrGLShaderBuilder.cpp', - '<(skia_src_path)/gpu/gl/GrGLShaderBuilder.h', '<(skia_src_path)/gpu/gl/GrGLShaderVar.h', '<(skia_src_path)/gpu/gl/GrGLSL.cpp', '<(skia_src_path)/gpu/gl/GrGLSL.h', @@ -240,6 +237,21 @@ '<(skia_src_path)/gpu/gl/GrGpuGL.h', '<(skia_src_path)/gpu/gl/GrGpuGL_program.cpp', + # Files for building GLSL shaders + '<(skia_src_path)/gpu/gl/builders/GrGLSLPrettyPrint.cpp', + '<(skia_src_path)/gpu/gl/builders/GrGLShaderBuilder.cpp', + '<(skia_src_path)/gpu/gl/builders/GrGLShaderBuilder.h', + '<(skia_src_path)/gpu/gl/builders/GrGLProgramBuilder.cpp', + '<(skia_src_path)/gpu/gl/builders/GrGLProgramBuilder.h', + '<(skia_src_path)/gpu/gl/builders/GrGLShaderStringBuilder.cpp', + '<(skia_src_path)/gpu/gl/builders/GrGLShaderStringBuilder.h', + '<(skia_src_path)/gpu/gl/builders/GrGLVertexShaderBuilder.cpp', + '<(skia_src_path)/gpu/gl/builders/GrGLVertexShaderBuilder.h', + '<(skia_src_path)/gpu/gl/builders/GrGLFragmentShaderBuilder.cpp', + '<(skia_src_path)/gpu/gl/builders/GrGLFragmentShaderBuilder.h', + '<(skia_src_path)/gpu/gl/builders/GrGLGeometryShaderBuilder.cpp', + '<(skia_src_path)/gpu/gl/builders/GrGLGeometryShaderBuilder.h', + # Sk files '<(skia_include_path)/gpu/SkGpuDevice.h', '<(skia_include_path)/gpu/SkGr.h', diff --git a/include/core/SkString.h b/include/core/SkString.h index bc06cb0aba..8a962ae671 100644 --- a/include/core/SkString.h +++ b/include/core/SkString.h @@ -195,6 +195,7 @@ public: void appendf(const char format[], ...) SK_PRINTF_LIKE(2, 3); void appendVAList(const char format[], va_list); void prependf(const char format[], ...) SK_PRINTF_LIKE(2, 3); + void prependVAList(const char format[], va_list); void remove(size_t offset, size_t length); diff --git a/include/gpu/GrEffect.h b/include/gpu/GrEffect.h index 8cb870ee15..4734c7c377 100644 --- a/include/gpu/GrEffect.h +++ b/include/gpu/GrEffect.h @@ -113,7 +113,7 @@ public: bool willReadFragmentPosition() const { return fWillReadFragmentPosition; } /** Will this effect emit custom vertex shader code? - (To set this value the effect must inherit from GrVertexEffect.) */ + (To set this value the effect must inherit from GrEffect.) */ bool hasVertexCode() const { return fHasVertexCode; } int numVertexAttribs() const { diff --git a/src/core/SkString.cpp b/src/core/SkString.cpp index 1e29dc7172..48459dbbd8 100644 --- a/src/core/SkString.cpp +++ b/src/core/SkString.cpp @@ -583,6 +583,14 @@ void SkString::prependf(const char format[], ...) { this->prepend(buffer, strlen(buffer)); } +void SkString::prependVAList(const char format[], va_list args) { + char buffer[kBufferSize]; + VSNPRINTF(buffer, kBufferSize, format, args); + + this->prepend(buffer, strlen(buffer)); +} + + /////////////////////////////////////////////////////////////////////////////// void SkString::remove(size_t offset, size_t length) { diff --git a/src/core/SkXfermode.cpp b/src/core/SkXfermode.cpp index 7608b79cbc..b10b5e1328 100644 --- a/src/core/SkXfermode.cpp +++ b/src/core/SkXfermode.cpp @@ -783,7 +783,7 @@ void SkXfermode::xferA8(SkAlpha* SK_RESTRICT dst, #include "GrEffectUnitTest.h" #include "GrTBackendEffectFactory.h" #include "gl/GrGLEffect.h" -#include "gl/GrGLShaderBuilder.h" +#include "gl/builders/GrGLProgramBuilder.h" /** * GrEffect that implements the all the separable xfer modes that cannot be expressed as Coeffs. @@ -821,7 +821,7 @@ public: GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&) : GrGLEffect(factory) { } - virtual void emitCode(GrGLShaderBuilder* builder, + virtual void emitCode(GrGLProgramBuilder* builder, const GrDrawEffect& drawEffect, const GrEffectKey& key, const char* outputColor, @@ -830,82 +830,83 @@ public: const TextureSamplerArray& samplers) SK_OVERRIDE { SkXfermode::Mode mode = drawEffect.castEffect().mode(); const GrTexture* backgroundTex = drawEffect.castEffect().backgroundAccess().getTexture(); + GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); const char* dstColor; if (backgroundTex) { dstColor = "bgColor"; - builder->fsCodeAppendf("\t\tvec4 %s = ", dstColor); - builder->fsAppendTextureLookup(samplers[0], coords[0].c_str(), coords[0].type()); - builder->fsCodeAppendf(";\n"); + fsBuilder->codeAppendf("\t\tvec4 %s = ", dstColor); + fsBuilder->appendTextureLookup(samplers[0], coords[0].c_str(), coords[0].type()); + fsBuilder->codeAppendf(";\n"); } else { - dstColor = builder->dstColor(); + dstColor = fsBuilder->dstColor(); } SkASSERT(NULL != dstColor); // We don't try to optimize for this case at all if (NULL == inputColor) { - builder->fsCodeAppendf("\t\tconst vec4 ones = vec4(1);\n"); + fsBuilder->codeAppendf("\t\tconst vec4 ones = vec4(1);\n"); inputColor = "ones"; } - builder->fsCodeAppendf("\t\t// SkXfermode::Mode: %s\n", SkXfermode::ModeName(mode)); + fsBuilder->codeAppendf("\t\t// SkXfermode::Mode: %s\n", SkXfermode::ModeName(mode)); // These all perform src-over on the alpha channel. - builder->fsCodeAppendf("\t\t%s.a = %s.a + (1.0 - %s.a) * %s.a;\n", + fsBuilder->codeAppendf("\t\t%s.a = %s.a + (1.0 - %s.a) * %s.a;\n", outputColor, inputColor, inputColor, dstColor); switch (mode) { case SkXfermode::kOverlay_Mode: // Overlay is Hard-Light with the src and dst reversed - HardLight(builder, outputColor, dstColor, inputColor); + HardLight(fsBuilder, outputColor, dstColor, inputColor); break; case SkXfermode::kDarken_Mode: - builder->fsCodeAppendf("\t\t%s.rgb = min((1.0 - %s.a) * %s.rgb + %s.rgb, " + fsBuilder->codeAppendf("\t\t%s.rgb = min((1.0 - %s.a) * %s.rgb + %s.rgb, " "(1.0 - %s.a) * %s.rgb + %s.rgb);\n", outputColor, inputColor, dstColor, inputColor, dstColor, inputColor, dstColor); break; case SkXfermode::kLighten_Mode: - builder->fsCodeAppendf("\t\t%s.rgb = max((1.0 - %s.a) * %s.rgb + %s.rgb, " + fsBuilder->codeAppendf("\t\t%s.rgb = max((1.0 - %s.a) * %s.rgb + %s.rgb, " "(1.0 - %s.a) * %s.rgb + %s.rgb);\n", outputColor, inputColor, dstColor, inputColor, dstColor, inputColor, dstColor); break; case SkXfermode::kColorDodge_Mode: - ColorDodgeComponent(builder, outputColor, inputColor, dstColor, 'r'); - ColorDodgeComponent(builder, outputColor, inputColor, dstColor, 'g'); - ColorDodgeComponent(builder, outputColor, inputColor, dstColor, 'b'); + ColorDodgeComponent(fsBuilder, outputColor, inputColor, dstColor, 'r'); + ColorDodgeComponent(fsBuilder, outputColor, inputColor, dstColor, 'g'); + ColorDodgeComponent(fsBuilder, outputColor, inputColor, dstColor, 'b'); break; case SkXfermode::kColorBurn_Mode: - ColorBurnComponent(builder, outputColor, inputColor, dstColor, 'r'); - ColorBurnComponent(builder, outputColor, inputColor, dstColor, 'g'); - ColorBurnComponent(builder, outputColor, inputColor, dstColor, 'b'); + ColorBurnComponent(fsBuilder, outputColor, inputColor, dstColor, 'r'); + ColorBurnComponent(fsBuilder, outputColor, inputColor, dstColor, 'g'); + ColorBurnComponent(fsBuilder, outputColor, inputColor, dstColor, 'b'); break; case SkXfermode::kHardLight_Mode: - HardLight(builder, outputColor, inputColor, dstColor); + HardLight(fsBuilder, outputColor, inputColor, dstColor); break; case SkXfermode::kSoftLight_Mode: - builder->fsCodeAppendf("\t\tif (0.0 == %s.a) {\n", dstColor); - builder->fsCodeAppendf("\t\t\t%s.rgba = %s;\n", outputColor, inputColor); - builder->fsCodeAppendf("\t\t} else {\n"); - SoftLightComponentPosDstAlpha(builder, outputColor, inputColor, dstColor, 'r'); - SoftLightComponentPosDstAlpha(builder, outputColor, inputColor, dstColor, 'g'); - SoftLightComponentPosDstAlpha(builder, outputColor, inputColor, dstColor, 'b'); - builder->fsCodeAppendf("\t\t}\n"); + fsBuilder->codeAppendf("\t\tif (0.0 == %s.a) {\n", dstColor); + fsBuilder->codeAppendf("\t\t\t%s.rgba = %s;\n", outputColor, inputColor); + fsBuilder->codeAppendf("\t\t} else {\n"); + SoftLightComponentPosDstAlpha(fsBuilder, outputColor, inputColor, dstColor, 'r'); + SoftLightComponentPosDstAlpha(fsBuilder, outputColor, inputColor, dstColor, 'g'); + SoftLightComponentPosDstAlpha(fsBuilder, outputColor, inputColor, dstColor, 'b'); + fsBuilder->codeAppendf("\t\t}\n"); break; case SkXfermode::kDifference_Mode: - builder->fsCodeAppendf("\t\t%s.rgb = %s.rgb + %s.rgb -" + fsBuilder->codeAppendf("\t\t%s.rgb = %s.rgb + %s.rgb -" "2.0 * min(%s.rgb * %s.a, %s.rgb * %s.a);\n", outputColor, inputColor, dstColor, inputColor, dstColor, dstColor, inputColor); break; case SkXfermode::kExclusion_Mode: - builder->fsCodeAppendf("\t\t%s.rgb = %s.rgb + %s.rgb - " + fsBuilder->codeAppendf("\t\t%s.rgb = %s.rgb + %s.rgb - " "2.0 * %s.rgb * %s.rgb;\n", outputColor, dstColor, inputColor, dstColor, inputColor); break; case SkXfermode::kMultiply_Mode: - builder->fsCodeAppendf("\t\t%s.rgb = (1.0 - %s.a) * %s.rgb + " + fsBuilder->codeAppendf("\t\t%s.rgb = (1.0 - %s.a) * %s.rgb + " "(1.0 - %s.a) * %s.rgb + " "%s.rgb * %s.rgb;\n", outputColor, inputColor, dstColor, dstColor, inputColor, @@ -914,52 +915,52 @@ public: case SkXfermode::kHue_Mode: { // SetLum(SetSat(S * Da, Sat(D * Sa)), Sa*Da, D*Sa) + (1 - Sa) * D + (1 - Da) * S SkString setSat, setLum; - AddSatFunction(builder, &setSat); - AddLumFunction(builder, &setLum); - builder->fsCodeAppendf("\t\tvec4 dstSrcAlpha = %s * %s.a;\n", + AddSatFunction(fsBuilder, &setSat); + AddLumFunction(fsBuilder, &setLum); + fsBuilder->codeAppendf("\t\tvec4 dstSrcAlpha = %s * %s.a;\n", dstColor, inputColor); - builder->fsCodeAppendf("\t\t%s.rgb = %s(%s(%s.rgb * %s.a, dstSrcAlpha.rgb), dstSrcAlpha.a, dstSrcAlpha.rgb);\n", + fsBuilder->codeAppendf("\t\t%s.rgb = %s(%s(%s.rgb * %s.a, dstSrcAlpha.rgb), dstSrcAlpha.a, dstSrcAlpha.rgb);\n", outputColor, setLum.c_str(), setSat.c_str(), inputColor, dstColor); - builder->fsCodeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n", + fsBuilder->codeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n", outputColor, inputColor, dstColor, dstColor, inputColor); break; } case SkXfermode::kSaturation_Mode: { // SetLum(SetSat(D * Sa, Sat(S * Da)), Sa*Da, D*Sa)) + (1 - Sa) * D + (1 - Da) * S SkString setSat, setLum; - AddSatFunction(builder, &setSat); - AddLumFunction(builder, &setLum); - builder->fsCodeAppendf("\t\tvec4 dstSrcAlpha = %s * %s.a;\n", + AddSatFunction(fsBuilder, &setSat); + AddLumFunction(fsBuilder, &setLum); + fsBuilder->codeAppendf("\t\tvec4 dstSrcAlpha = %s * %s.a;\n", dstColor, inputColor); - builder->fsCodeAppendf("\t\t%s.rgb = %s(%s(dstSrcAlpha.rgb, %s.rgb * %s.a), dstSrcAlpha.a, dstSrcAlpha.rgb);\n", + fsBuilder->codeAppendf("\t\t%s.rgb = %s(%s(dstSrcAlpha.rgb, %s.rgb * %s.a), dstSrcAlpha.a, dstSrcAlpha.rgb);\n", outputColor, setLum.c_str(), setSat.c_str(), inputColor, dstColor); - builder->fsCodeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n", + fsBuilder->codeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n", outputColor, inputColor, dstColor, dstColor, inputColor); break; } case SkXfermode::kColor_Mode: { // SetLum(S * Da, Sa* Da, D * Sa) + (1 - Sa) * D + (1 - Da) * S SkString setLum; - AddLumFunction(builder, &setLum); - builder->fsCodeAppendf("\t\tvec4 srcDstAlpha = %s * %s.a;\n", + AddLumFunction(fsBuilder, &setLum); + fsBuilder->codeAppendf("\t\tvec4 srcDstAlpha = %s * %s.a;\n", inputColor, dstColor); - builder->fsCodeAppendf("\t\t%s.rgb = %s(srcDstAlpha.rgb, srcDstAlpha.a, %s.rgb * %s.a);\n", + fsBuilder->codeAppendf("\t\t%s.rgb = %s(srcDstAlpha.rgb, srcDstAlpha.a, %s.rgb * %s.a);\n", outputColor, setLum.c_str(), dstColor, inputColor); - builder->fsCodeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n", + fsBuilder->codeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n", outputColor, inputColor, dstColor, dstColor, inputColor); break; } case SkXfermode::kLuminosity_Mode: { // SetLum(D * Sa, Sa* Da, S * Da) + (1 - Sa) * D + (1 - Da) * S SkString setLum; - AddLumFunction(builder, &setLum); - builder->fsCodeAppendf("\t\tvec4 srcDstAlpha = %s * %s.a;\n", + AddLumFunction(fsBuilder, &setLum); + fsBuilder->codeAppendf("\t\tvec4 srcDstAlpha = %s * %s.a;\n", inputColor, dstColor); - builder->fsCodeAppendf("\t\t%s.rgb = %s(%s.rgb * %s.a, srcDstAlpha.a, srcDstAlpha.rgb);\n", + fsBuilder->codeAppendf("\t\t%s.rgb = %s(%s.rgb * %s.a, srcDstAlpha.a, srcDstAlpha.rgb);\n", outputColor, setLum.c_str(), dstColor, inputColor); - builder->fsCodeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n", + fsBuilder->codeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n", outputColor, inputColor, dstColor, dstColor, inputColor); break; } @@ -979,116 +980,116 @@ public: } private: - static void HardLight(GrGLShaderBuilder* builder, + static void HardLight(GrGLFragmentShaderBuilder* fsBuilder, const char* final, const char* src, const char* dst) { static const char kComponents[] = {'r', 'g', 'b'}; for (size_t i = 0; i < SK_ARRAY_COUNT(kComponents); ++i) { char component = kComponents[i]; - builder->fsCodeAppendf("\t\tif (2.0 * %s.%c <= %s.a) {\n", src, component, src); - builder->fsCodeAppendf("\t\t\t%s.%c = 2.0 * %s.%c * %s.%c;\n", final, component, src, component, dst, component); - builder->fsCodeAppend("\t\t} else {\n"); - builder->fsCodeAppendf("\t\t\t%s.%c = %s.a * %s.a - 2.0 * (%s.a - %s.%c) * (%s.a - %s.%c);\n", + fsBuilder->codeAppendf("\t\tif (2.0 * %s.%c <= %s.a) {\n", src, component, src); + fsBuilder->codeAppendf("\t\t\t%s.%c = 2.0 * %s.%c * %s.%c;\n", final, component, src, component, dst, component); + fsBuilder->codeAppend("\t\t} else {\n"); + fsBuilder->codeAppendf("\t\t\t%s.%c = %s.a * %s.a - 2.0 * (%s.a - %s.%c) * (%s.a - %s.%c);\n", final, component, src, dst, dst, dst, component, src, src, component); - builder->fsCodeAppend("\t\t}\n"); + fsBuilder->codeAppend("\t\t}\n"); } - builder->fsCodeAppendf("\t\t%s.rgb += %s.rgb * (1.0 - %s.a) + %s.rgb * (1.0 - %s.a);\n", + fsBuilder->codeAppendf("\t\t%s.rgb += %s.rgb * (1.0 - %s.a) + %s.rgb * (1.0 - %s.a);\n", final, src, dst, dst, src); } // Does one component of color-dodge - static void ColorDodgeComponent(GrGLShaderBuilder* builder, + static void ColorDodgeComponent(GrGLFragmentShaderBuilder* fsBuilder, const char* final, const char* src, const char* dst, const char component) { - builder->fsCodeAppendf("\t\tif (0.0 == %s.%c) {\n", dst, component); - builder->fsCodeAppendf("\t\t\t%s.%c = %s.%c * (1.0 - %s.a);\n", + fsBuilder->codeAppendf("\t\tif (0.0 == %s.%c) {\n", dst, component); + fsBuilder->codeAppendf("\t\t\t%s.%c = %s.%c * (1.0 - %s.a);\n", final, component, src, component, dst); - builder->fsCodeAppend("\t\t} else {\n"); - builder->fsCodeAppendf("\t\t\tfloat d = %s.a - %s.%c;\n", src, src, component); - builder->fsCodeAppend("\t\t\tif (0.0 == d) {\n"); - builder->fsCodeAppendf("\t\t\t\t%s.%c = %s.a * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n", + fsBuilder->codeAppend("\t\t} else {\n"); + fsBuilder->codeAppendf("\t\t\tfloat d = %s.a - %s.%c;\n", src, src, component); + fsBuilder->codeAppend("\t\t\tif (0.0 == d) {\n"); + fsBuilder->codeAppendf("\t\t\t\t%s.%c = %s.a * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n", final, component, src, dst, src, component, dst, dst, component, src); - builder->fsCodeAppend("\t\t\t} else {\n"); - builder->fsCodeAppendf("\t\t\t\td = min(%s.a, %s.%c * %s.a / d);\n", + fsBuilder->codeAppend("\t\t\t} else {\n"); + fsBuilder->codeAppendf("\t\t\t\td = min(%s.a, %s.%c * %s.a / d);\n", dst, dst, component, src); - builder->fsCodeAppendf("\t\t\t\t%s.%c = d * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n", + fsBuilder->codeAppendf("\t\t\t\t%s.%c = d * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n", final, component, src, src, component, dst, dst, component, src); - builder->fsCodeAppend("\t\t\t}\n"); - builder->fsCodeAppend("\t\t}\n"); + fsBuilder->codeAppend("\t\t\t}\n"); + fsBuilder->codeAppend("\t\t}\n"); } // Does one component of color-burn - static void ColorBurnComponent(GrGLShaderBuilder* builder, + static void ColorBurnComponent(GrGLFragmentShaderBuilder* fsBuilder, const char* final, const char* src, const char* dst, const char component) { - builder->fsCodeAppendf("\t\tif (%s.a == %s.%c) {\n", dst, dst, component); - builder->fsCodeAppendf("\t\t\t%s.%c = %s.a * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n", + fsBuilder->codeAppendf("\t\tif (%s.a == %s.%c) {\n", dst, dst, component); + fsBuilder->codeAppendf("\t\t\t%s.%c = %s.a * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n", final, component, src, dst, src, component, dst, dst, component, src); - builder->fsCodeAppendf("\t\t} else if (0.0 == %s.%c) {\n", src, component); - builder->fsCodeAppendf("\t\t\t%s.%c = %s.%c * (1.0 - %s.a);\n", + fsBuilder->codeAppendf("\t\t} else if (0.0 == %s.%c) {\n", src, component); + fsBuilder->codeAppendf("\t\t\t%s.%c = %s.%c * (1.0 - %s.a);\n", final, component, dst, component, src); - builder->fsCodeAppend("\t\t} else {\n"); - builder->fsCodeAppendf("\t\t\tfloat d = max(0.0, %s.a - (%s.a - %s.%c) * %s.a / %s.%c);\n", + fsBuilder->codeAppend("\t\t} else {\n"); + fsBuilder->codeAppendf("\t\t\tfloat d = max(0.0, %s.a - (%s.a - %s.%c) * %s.a / %s.%c);\n", dst, dst, dst, component, src, src, component); - builder->fsCodeAppendf("\t\t\t%s.%c = %s.a * d + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n", + fsBuilder->codeAppendf("\t\t\t%s.%c = %s.a * d + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n", final, component, src, src, component, dst, dst, component, src); - builder->fsCodeAppend("\t\t}\n"); + fsBuilder->codeAppend("\t\t}\n"); } // Does one component of soft-light. Caller should have already checked that dst alpha > 0. - static void SoftLightComponentPosDstAlpha(GrGLShaderBuilder* builder, + static void SoftLightComponentPosDstAlpha(GrGLFragmentShaderBuilder* fsBuilder, const char* final, const char* src, const char* dst, const char component) { // if (2S < Sa) - builder->fsCodeAppendf("\t\t\tif (2.0 * %s.%c <= %s.a) {\n", src, component, src); + fsBuilder->codeAppendf("\t\t\tif (2.0 * %s.%c <= %s.a) {\n", src, component, src); // (D^2 (Sa-2 S))/Da+(1-Da) S+D (-Sa+2 S+1) - builder->fsCodeAppendf("\t\t\t\t%s.%c = (%s.%c*%s.%c*(%s.a - 2.0*%s.%c)) / %s.a + (1.0 - %s.a) * %s.%c + %s.%c*(-%s.a + 2.0*%s.%c + 1.0);\n", + fsBuilder->codeAppendf("\t\t\t\t%s.%c = (%s.%c*%s.%c*(%s.a - 2.0*%s.%c)) / %s.a + (1.0 - %s.a) * %s.%c + %s.%c*(-%s.a + 2.0*%s.%c + 1.0);\n", final, component, dst, component, dst, component, src, src, component, dst, dst, src, component, dst, component, src, src, component); // else if (4D < Da) - builder->fsCodeAppendf("\t\t\t} else if (4.0 * %s.%c <= %s.a) {\n", + fsBuilder->codeAppendf("\t\t\t} else if (4.0 * %s.%c <= %s.a) {\n", dst, component, dst); - builder->fsCodeAppendf("\t\t\t\tfloat DSqd = %s.%c * %s.%c;\n", + fsBuilder->codeAppendf("\t\t\t\tfloat DSqd = %s.%c * %s.%c;\n", dst, component, dst, component); - builder->fsCodeAppendf("\t\t\t\tfloat DCub = DSqd * %s.%c;\n", dst, component); - builder->fsCodeAppendf("\t\t\t\tfloat DaSqd = %s.a * %s.a;\n", dst, dst); - builder->fsCodeAppendf("\t\t\t\tfloat DaCub = DaSqd * %s.a;\n", dst); + fsBuilder->codeAppendf("\t\t\t\tfloat DCub = DSqd * %s.%c;\n", dst, component); + fsBuilder->codeAppendf("\t\t\t\tfloat DaSqd = %s.a * %s.a;\n", dst, dst); + fsBuilder->codeAppendf("\t\t\t\tfloat DaCub = DaSqd * %s.a;\n", dst); // (Da^3 (-S)+Da^2 (S-D (3 Sa-6 S-1))+12 Da D^2 (Sa-2 S)-16 D^3 (Sa-2 S))/Da^2 - builder->fsCodeAppendf("\t\t\t\t%s.%c = (-DaCub*%s.%c + DaSqd*(%s.%c - %s.%c * (3.0*%s.a - 6.0*%s.%c - 1.0)) + 12.0*%s.a*DSqd*(%s.a - 2.0*%s.%c) - 16.0*DCub * (%s.a - 2.0*%s.%c)) / DaSqd;\n", + fsBuilder->codeAppendf("\t\t\t\t%s.%c = (-DaCub*%s.%c + DaSqd*(%s.%c - %s.%c * (3.0*%s.a - 6.0*%s.%c - 1.0)) + 12.0*%s.a*DSqd*(%s.a - 2.0*%s.%c) - 16.0*DCub * (%s.a - 2.0*%s.%c)) / DaSqd;\n", final, component, src, component, src, component, dst, component, src, src, component, dst, src, src, component, src, src, component); - builder->fsCodeAppendf("\t\t\t} else {\n"); + fsBuilder->codeAppendf("\t\t\t} else {\n"); // -sqrt(Da * D) (Sa-2 S)-Da S+D (Sa-2 S+1)+S - builder->fsCodeAppendf("\t\t\t\t%s.%c = -sqrt(%s.a*%s.%c)*(%s.a - 2.0*%s.%c) - %s.a*%s.%c + %s.%c*(%s.a - 2.0*%s.%c + 1.0) + %s.%c;\n", + fsBuilder->codeAppendf("\t\t\t\t%s.%c = -sqrt(%s.a*%s.%c)*(%s.a - 2.0*%s.%c) - %s.a*%s.%c + %s.%c*(%s.a - 2.0*%s.%c + 1.0) + %s.%c;\n", final, component, dst, dst, component, src, src, component, dst, src, component, dst, component, src, src, component, src, component); - builder->fsCodeAppendf("\t\t\t}\n"); + fsBuilder->codeAppendf("\t\t\t}\n"); } // Adds a function that takes two colors and an alpha as input. It produces a color with the // hue and saturation of the first color, the luminosity of the second color, and the input // alpha. It has this signature: // vec3 set_luminance(vec3 hueSatColor, float alpha, vec3 lumColor). - static void AddLumFunction(GrGLShaderBuilder* builder, SkString* setLumFunction) { + static void AddLumFunction(GrGLFragmentShaderBuilder* fsBuilder, SkString* setLumFunction) { // Emit a helper that gets the luminance of a color. SkString getFunction; GrGLShaderVar getLumArgs[] = { GrGLShaderVar("color", kVec3f_GrSLType), }; SkString getLumBody("\treturn dot(vec3(0.3, 0.59, 0.11), color);\n"); - builder->fsEmitFunction(kFloat_GrSLType, + fsBuilder->emitFunction(kFloat_GrSLType, "luminance", SK_ARRAY_COUNT(getLumArgs), getLumArgs, getLumBody.c_str(), @@ -1113,7 +1114,7 @@ public: "\t\toutColor = outLum + ((outColor - vec3(outLum, outLum, outLum)) * (alpha - outLum)) / (maxComp - outLum);\n" "\t}\n" "\treturn outColor;\n"); - builder->fsEmitFunction(kVec3f_GrSLType, + fsBuilder->emitFunction(kVec3f_GrSLType, "set_luminance", SK_ARRAY_COUNT(setLumArgs), setLumArgs, setLumBody.c_str(), @@ -1123,14 +1124,14 @@ public: // Adds a function that creates a color with the hue and luminosity of one input color and // the saturation of another color. It will have this signature: // float set_saturation(vec3 hueLumColor, vec3 satColor) - static void AddSatFunction(GrGLShaderBuilder* builder, SkString* setSatFunction) { + static void AddSatFunction(GrGLFragmentShaderBuilder* fsBuilder, SkString* setSatFunction) { // Emit a helper that gets the saturation of a color SkString getFunction; GrGLShaderVar getSatArgs[] = { GrGLShaderVar("color", kVec3f_GrSLType) }; SkString getSatBody; getSatBody.printf("\treturn max(max(color.r, color.g), color.b) - " "min(min(color.r, color.g), color.b);\n"); - builder->fsEmitFunction(kFloat_GrSLType, + fsBuilder->emitFunction(kFloat_GrSLType, "saturation", SK_ARRAY_COUNT(getSatArgs), getSatArgs, getSatBody.c_str(), @@ -1156,7 +1157,7 @@ public: "\t} else {\n" "\t\treturn vec3(0, 0, 0);\n" "\t}\n"; - builder->fsEmitFunction(kVec3f_GrSLType, + fsBuilder->emitFunction(kVec3f_GrSLType, "set_saturation_helper", SK_ARRAY_COUNT(helperArgs), helperArgs, kHelperBody, @@ -1187,7 +1188,7 @@ public: "\treturn hueLumColor;\n", getFunction.c_str(), helpFunc, helpFunc, helpFunc, helpFunc, helpFunc, helpFunc); - builder->fsEmitFunction(kVec3f_GrSLType, + fsBuilder->emitFunction(kVec3f_GrSLType, "set_saturation", SK_ARRAY_COUNT(setSatArgs), setSatArgs, setSatBody.c_str(), diff --git a/src/effects/SkAlphaThresholdFilter.cpp b/src/effects/SkAlphaThresholdFilter.cpp index 9c59347f73..8022724ab2 100644 --- a/src/effects/SkAlphaThresholdFilter.cpp +++ b/src/effects/SkAlphaThresholdFilter.cpp @@ -50,7 +50,7 @@ SkImageFilter* SkAlphaThresholdFilter::Create(const SkRegion& region, #include "GrCoordTransform.h" #include "GrEffect.h" #include "gl/GrGLEffect.h" -#include "gl/GrGLShaderBuilder.h" +#include "gl/builders/GrGLProgramBuilder.h" #include "GrTBackendEffectFactory.h" #include "GrTextureAccess.h" @@ -118,7 +118,7 @@ class GrGLAlphaThresholdEffect : public GrGLEffect { public: GrGLAlphaThresholdEffect(const GrBackendEffectFactory&, const GrDrawEffect&); - virtual void emitCode(GrGLShaderBuilder*, + virtual void emitCode(GrGLProgramBuilder*, const GrDrawEffect&, const GrEffectKey&, const char* outputColor, @@ -140,39 +140,41 @@ GrGLAlphaThresholdEffect::GrGLAlphaThresholdEffect(const GrBackendEffectFactory& : INHERITED(factory) { } -void GrGLAlphaThresholdEffect::emitCode(GrGLShaderBuilder* builder, +void GrGLAlphaThresholdEffect::emitCode(GrGLProgramBuilder* builder, const GrDrawEffect&, const GrEffectKey& key, const char* outputColor, const char* inputColor, const TransformedCoordsArray& coords, const TextureSamplerArray& samplers) { - SkString coords2D = builder->ensureFSCoords2D(coords, 0); - SkString maskCoords2D = builder->ensureFSCoords2D(coords, 1); fInnerThresholdVar = builder->addUniform( - GrGLShaderBuilder::kFragment_Visibility, + GrGLProgramBuilder::kFragment_Visibility, kFloat_GrSLType, "inner_threshold"); fOuterThresholdVar = builder->addUniform( - GrGLShaderBuilder::kFragment_Visibility, + GrGLProgramBuilder::kFragment_Visibility, kFloat_GrSLType, "outer_threshold"); - builder->fsCodeAppendf("\t\tvec2 coord = %s;\n", coords2D.c_str()); - builder->fsCodeAppendf("\t\tvec2 mask_coord = %s;\n", maskCoords2D.c_str()); - builder->fsCodeAppend("\t\tvec4 input_color = "); - builder->fsAppendTextureLookup(samplers[0], "coord"); - builder->fsCodeAppend(";\n"); - builder->fsCodeAppend("\t\tvec4 mask_color = "); - builder->fsAppendTextureLookup(samplers[1], "mask_coord"); - builder->fsCodeAppend(";\n"); + GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); + SkString coords2D = fsBuilder->ensureFSCoords2D(coords, 0); + SkString maskCoords2D = fsBuilder->ensureFSCoords2D(coords, 1); - builder->fsCodeAppendf("\t\tfloat inner_thresh = %s;\n", + fsBuilder->codeAppendf("\t\tvec2 coord = %s;\n", coords2D.c_str()); + fsBuilder->codeAppendf("\t\tvec2 mask_coord = %s;\n", maskCoords2D.c_str()); + fsBuilder->codeAppend("\t\tvec4 input_color = "); + fsBuilder->appendTextureLookup(samplers[0], "coord"); + fsBuilder->codeAppend(";\n"); + fsBuilder->codeAppend("\t\tvec4 mask_color = "); + fsBuilder->appendTextureLookup(samplers[1], "mask_coord"); + fsBuilder->codeAppend(";\n"); + + fsBuilder->codeAppendf("\t\tfloat inner_thresh = %s;\n", builder->getUniformCStr(fInnerThresholdVar)); - builder->fsCodeAppendf("\t\tfloat outer_thresh = %s;\n", + fsBuilder->codeAppendf("\t\tfloat outer_thresh = %s;\n", builder->getUniformCStr(fOuterThresholdVar)); - builder->fsCodeAppend("\t\tfloat mask = mask_color.a;\n"); + fsBuilder->codeAppend("\t\tfloat mask = mask_color.a;\n"); - builder->fsCodeAppend("vec4 color = input_color;\n"); - builder->fsCodeAppend("\t\tif (mask < 0.5) {\n" + fsBuilder->codeAppend("vec4 color = input_color;\n"); + fsBuilder->codeAppend("\t\tif (mask < 0.5) {\n" "\t\t\tif (color.a > outer_thresh) {\n" "\t\t\t\tfloat scale = outer_thresh / color.a;\n" "\t\t\t\tcolor.rgb *= scale;\n" @@ -184,7 +186,7 @@ void GrGLAlphaThresholdEffect::emitCode(GrGLShaderBuilder* builder, "\t\t\tcolor.a = inner_thresh;\n" "\t\t}\n"); - builder->fsCodeAppendf("%s = %s;\n", outputColor, + fsBuilder->codeAppendf("%s = %s;\n", outputColor, (GrGLSLExpr4(inputColor) * GrGLSLExpr4("color")).c_str()); } diff --git a/src/effects/SkArithmeticMode.cpp b/src/effects/SkArithmeticMode.cpp index d3be826007..be636c5bbf 100644 --- a/src/effects/SkArithmeticMode.cpp +++ b/src/effects/SkArithmeticMode.cpp @@ -15,7 +15,7 @@ #include "GrContext.h" #include "GrCoordTransform.h" #include "gl/GrGLEffect.h" -#include "gl/GrGLShaderBuilder.h" +#include "gl/builders/GrGLProgramBuilder.h" #include "GrTBackendEffectFactory.h" #endif @@ -252,7 +252,7 @@ public: GrGLArithmeticEffect(const GrBackendEffectFactory&, const GrDrawEffect&); virtual ~GrGLArithmeticEffect(); - virtual void emitCode(GrGLShaderBuilder*, + virtual void emitCode(GrGLProgramBuilder*, const GrDrawEffect&, const GrEffectKey&, const char* outputColor, @@ -359,7 +359,7 @@ GrGLArithmeticEffect::GrGLArithmeticEffect(const GrBackendEffectFactory& factory GrGLArithmeticEffect::~GrGLArithmeticEffect() { } -void GrGLArithmeticEffect::emitCode(GrGLShaderBuilder* builder, +void GrGLArithmeticEffect::emitCode(GrGLProgramBuilder* builder, const GrDrawEffect& drawEffect, const GrEffectKey& key, const char* outputColor, @@ -368,42 +368,43 @@ void GrGLArithmeticEffect::emitCode(GrGLShaderBuilder* builder, const TextureSamplerArray& samplers) { GrTexture* backgroundTex = drawEffect.castEffect().backgroundTexture(); + GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); const char* dstColor; if (backgroundTex) { - builder->fsCodeAppend("\t\tvec4 bgColor = "); - builder->fsAppendTextureLookup(samplers[0], coords[0].c_str(), coords[0].type()); - builder->fsCodeAppendf(";\n"); + fsBuilder->codeAppend("\t\tvec4 bgColor = "); + fsBuilder->appendTextureLookup(samplers[0], coords[0].c_str(), coords[0].type()); + fsBuilder->codeAppendf(";\n"); dstColor = "bgColor"; } else { - dstColor = builder->dstColor(); + dstColor = fsBuilder->dstColor(); } SkASSERT(NULL != dstColor); - fKUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, + fKUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec4f_GrSLType, "k"); const char* kUni = builder->getUniformCStr(fKUni); // We don't try to optimize for this case at all if (NULL == inputColor) { - builder->fsCodeAppendf("\t\tconst vec4 src = vec4(1);\n"); + fsBuilder->codeAppendf("\t\tconst vec4 src = vec4(1);\n"); } else { - builder->fsCodeAppendf("\t\tvec4 src = %s;\n", inputColor); + fsBuilder->codeAppendf("\t\tvec4 src = %s;\n", inputColor); if (gUseUnpremul) { - builder->fsCodeAppendf("\t\tsrc.rgb = clamp(src.rgb / src.a, 0.0, 1.0);\n"); + fsBuilder->codeAppendf("\t\tsrc.rgb = clamp(src.rgb / src.a, 0.0, 1.0);\n"); } } - builder->fsCodeAppendf("\t\tvec4 dst = %s;\n", dstColor); + fsBuilder->codeAppendf("\t\tvec4 dst = %s;\n", dstColor); if (gUseUnpremul) { - builder->fsCodeAppendf("\t\tdst.rgb = clamp(dst.rgb / dst.a, 0.0, 1.0);\n"); + fsBuilder->codeAppendf("\t\tdst.rgb = clamp(dst.rgb / dst.a, 0.0, 1.0);\n"); } - builder->fsCodeAppendf("\t\t%s = %s.x * src * dst + %s.y * src + %s.z * dst + %s.w;\n", outputColor, kUni, kUni, kUni, kUni); - builder->fsCodeAppendf("\t\t%s = clamp(%s, 0.0, 1.0);\n", outputColor, outputColor); + fsBuilder->codeAppendf("\t\t%s = %s.x * src * dst + %s.y * src + %s.z * dst + %s.w;\n", outputColor, kUni, kUni, kUni, kUni); + fsBuilder->codeAppendf("\t\t%s = clamp(%s, 0.0, 1.0);\n", outputColor, outputColor); if (gUseUnpremul) { - builder->fsCodeAppendf("\t\t%s.rgb *= %s.a;\n", outputColor, outputColor); + fsBuilder->codeAppendf("\t\t%s.rgb *= %s.a;\n", outputColor, outputColor); } else if (fEnforcePMColor) { - builder->fsCodeAppendf("\t\t%s.rgb = min(%s.rgb, %s.a);\n", outputColor, outputColor, outputColor); + fsBuilder->codeAppendf("\t\t%s.rgb = min(%s.rgb, %s.a);\n", outputColor, outputColor, outputColor); } } diff --git a/src/effects/SkBlurMaskFilter.cpp b/src/effects/SkBlurMaskFilter.cpp index 4e469bca9b..e4133a8bce 100644 --- a/src/effects/SkBlurMaskFilter.cpp +++ b/src/effects/SkBlurMaskFilter.cpp @@ -22,7 +22,7 @@ #include "GrTexture.h" #include "GrEffect.h" #include "gl/GrGLEffect.h" -#include "gl/GrGLShaderBuilder.h" +#include "gl/builders/GrGLProgramBuilder.h" #include "effects/GrSimpleTextureEffect.h" #include "GrTBackendEffectFactory.h" #include "SkGrPixelRef.h" @@ -610,7 +610,7 @@ class GrGLRectBlurEffect : public GrGLEffect { public: GrGLRectBlurEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&); - virtual void emitCode(GrGLShaderBuilder*, + virtual void emitCode(GrGLProgramBuilder*, const GrDrawEffect&, const GrEffectKey&, const char* outputColor, @@ -635,23 +635,23 @@ GrGLRectBlurEffect::GrGLRectBlurEffect(const GrBackendEffectFactory& factory, co : INHERITED(factory) { } -void OutputRectBlurProfileLookup(GrGLShaderBuilder* builder, +void OutputRectBlurProfileLookup(GrGLFragmentShaderBuilder* fsBuilder, const GrGLShaderBuilder::TextureSampler& sampler, const char *output, const char *profileSize, const char *loc, const char *blurred_width, const char *sharp_width) { - builder->fsCodeAppendf("\tfloat %s;\n", output); - builder->fsCodeAppendf("\t\t{\n"); - builder->fsCodeAppendf("\t\t\tfloat coord = (0.5 * (abs(2.0*%s - %s) - %s))/%s;\n", + fsBuilder->codeAppendf("\tfloat %s;\n", output); + fsBuilder->codeAppendf("\t\t{\n"); + fsBuilder->codeAppendf("\t\t\tfloat coord = (0.5 * (abs(2.0*%s - %s) - %s))/%s;\n", loc, blurred_width, sharp_width, profileSize); - builder->fsCodeAppendf("\t\t\t%s = ", output); - builder->fsAppendTextureLookup(sampler, "vec2(coord,0.5)"); - builder->fsCodeAppend(".a;\n"); - builder->fsCodeAppendf("\t\t}\n"); + fsBuilder->codeAppendf("\t\t\t%s = ", output); + fsBuilder->appendTextureLookup(sampler, "vec2(coord,0.5)"); + fsBuilder->codeAppend(".a;\n"); + fsBuilder->codeAppendf("\t\t}\n"); } -void GrGLRectBlurEffect::emitCode(GrGLShaderBuilder* builder, +void GrGLRectBlurEffect::emitCode(GrGLProgramBuilder* builder, const GrDrawEffect&, const GrEffectKey& key, const char* outputColor, @@ -662,36 +662,37 @@ void GrGLRectBlurEffect::emitCode(GrGLShaderBuilder* builder, const char *rectName; const char *profileSizeName; - fProxyRectUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, + fProxyRectUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec4f_GrSLType, "proxyRect", &rectName); - fProfileSizeUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, + fProfileSizeUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kFloat_GrSLType, "profileSize", &profileSizeName); - const char *fragmentPos = builder->fragmentPosition(); + GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); + const char *fragmentPos = fsBuilder->fragmentPosition(); if (inputColor) { - builder->fsCodeAppendf("\tvec4 src=%s;\n", inputColor); + fsBuilder->codeAppendf("\tvec4 src=%s;\n", inputColor); } else { - builder->fsCodeAppendf("\tvec4 src=vec4(1)\n;"); + fsBuilder->codeAppendf("\tvec4 src=vec4(1)\n;"); } - builder->fsCodeAppendf("\tvec2 translatedPos = %s.xy - %s.xy;\n", fragmentPos, rectName ); - builder->fsCodeAppendf("\tfloat width = %s.z - %s.x;\n", rectName, rectName); - builder->fsCodeAppendf("\tfloat height = %s.w - %s.y;\n", rectName, rectName); + fsBuilder->codeAppendf("\tvec2 translatedPos = %s.xy - %s.xy;\n", fragmentPos, rectName ); + fsBuilder->codeAppendf("\tfloat width = %s.z - %s.x;\n", rectName, rectName); + fsBuilder->codeAppendf("\tfloat height = %s.w - %s.y;\n", rectName, rectName); - builder->fsCodeAppendf("\tvec2 smallDims = vec2(width - %s, height-%s);\n", profileSizeName, profileSizeName); - builder->fsCodeAppendf("\tfloat center = 2.0 * floor(%s/2.0 + .25) - 1.0;\n", profileSizeName); - builder->fsCodeAppendf("\tvec2 wh = smallDims - vec2(center,center);\n"); + fsBuilder->codeAppendf("\tvec2 smallDims = vec2(width - %s, height-%s);\n", profileSizeName, profileSizeName); + fsBuilder->codeAppendf("\tfloat center = 2.0 * floor(%s/2.0 + .25) - 1.0;\n", profileSizeName); + fsBuilder->codeAppendf("\tvec2 wh = smallDims - vec2(center,center);\n"); - OutputRectBlurProfileLookup(builder, samplers[0], "horiz_lookup", profileSizeName, "translatedPos.x", "width", "wh.x"); - OutputRectBlurProfileLookup(builder, samplers[0], "vert_lookup", profileSizeName, "translatedPos.y", "height", "wh.y"); + OutputRectBlurProfileLookup(fsBuilder, samplers[0], "horiz_lookup", profileSizeName, "translatedPos.x", "width", "wh.x"); + OutputRectBlurProfileLookup(fsBuilder, samplers[0], "vert_lookup", profileSizeName, "translatedPos.y", "height", "wh.y"); - builder->fsCodeAppendf("\tfloat final = horiz_lookup * vert_lookup;\n"); - builder->fsCodeAppendf("\t%s = src * vec4(final);\n", outputColor ); + fsBuilder->codeAppendf("\tfloat final = horiz_lookup * vert_lookup;\n"); + fsBuilder->codeAppendf("\t%s = src * vec4(final);\n", outputColor ); } void GrGLRectBlurEffect::setData(const GrGLProgramDataManager& pdman, @@ -971,7 +972,7 @@ class GrGLRRectBlurEffect : public GrGLEffect { public: GrGLRRectBlurEffect(const GrBackendEffectFactory&, const GrDrawEffect&); - virtual void emitCode(GrGLShaderBuilder* builder, + virtual void emitCode(GrGLProgramBuilder* builder, const GrDrawEffect& drawEffect, const GrEffectKey& key, const char* outputColor, @@ -993,7 +994,7 @@ GrGLRRectBlurEffect::GrGLRRectBlurEffect(const GrBackendEffectFactory& factory, : INHERITED (factory) { } -void GrGLRRectBlurEffect::emitCode(GrGLShaderBuilder* builder, +void GrGLRRectBlurEffect::emitCode(GrGLProgramBuilder* builder, const GrDrawEffect& drawEffect, const GrEffectKey& key, const char* outputColor, @@ -1007,45 +1008,47 @@ void GrGLRRectBlurEffect::emitCode(GrGLShaderBuilder* builder, // The proxy rect has left, top, right, and bottom edges correspond to // components x, y, z, and w, respectively. - fProxyRectUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, + fProxyRectUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec4f_GrSLType, "proxyRect", &rectName); - fCornerRadiusUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, + fCornerRadiusUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kFloat_GrSLType, "cornerRadius", &cornerRadiusName); - fBlurRadiusUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, + fBlurRadiusUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kFloat_GrSLType, "blurRadius", &blurRadiusName); - const char* fragmentPos = builder->fragmentPosition(); + + GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); + const char* fragmentPos = fsBuilder->fragmentPosition(); // warp the fragment position to the appropriate part of the 9patch blur texture - builder->fsCodeAppendf("\t\tvec2 rectCenter = (%s.xy + %s.zw)/2.0;\n", rectName, rectName); - builder->fsCodeAppendf("\t\tvec2 translatedFragPos = %s.xy - %s.xy;\n", fragmentPos, rectName); - builder->fsCodeAppendf("\t\tfloat threshold = %s + 2.0*%s;\n", cornerRadiusName, blurRadiusName ); - builder->fsCodeAppendf("\t\tvec2 middle = %s.zw - %s.xy - 2.0*threshold;\n", rectName, rectName ); - - builder->fsCodeAppendf("\t\tif (translatedFragPos.x >= threshold && translatedFragPos.x < (middle.x+threshold)) {\n" ); - builder->fsCodeAppendf("\t\t\ttranslatedFragPos.x = threshold;\n"); - builder->fsCodeAppendf("\t\t} else if (translatedFragPos.x >= (middle.x + threshold)) {\n"); - builder->fsCodeAppendf("\t\t\ttranslatedFragPos.x -= middle.x - 1.0;\n"); - builder->fsCodeAppendf("\t\t}\n"); - - builder->fsCodeAppendf("\t\tif (translatedFragPos.y > threshold && translatedFragPos.y < (middle.y+threshold)) {\n" ); - builder->fsCodeAppendf("\t\t\ttranslatedFragPos.y = threshold;\n"); - builder->fsCodeAppendf("\t\t} else if (translatedFragPos.y >= (middle.y + threshold)) {\n"); - builder->fsCodeAppendf("\t\t\ttranslatedFragPos.y -= middle.y - 1.0;\n"); - builder->fsCodeAppendf("\t\t}\n"); - - builder->fsCodeAppendf("\t\tvec2 proxyDims = vec2(2.0*threshold+1.0);\n"); - builder->fsCodeAppendf("\t\tvec2 texCoord = translatedFragPos / proxyDims;\n"); - - builder->fsCodeAppendf("\t%s = ", outputColor); - builder->fsAppendTextureLookupAndModulate(inputColor, samplers[0], "texCoord"); - builder->fsCodeAppend(";\n"); + fsBuilder->codeAppendf("\t\tvec2 rectCenter = (%s.xy + %s.zw)/2.0;\n", rectName, rectName); + fsBuilder->codeAppendf("\t\tvec2 translatedFragPos = %s.xy - %s.xy;\n", fragmentPos, rectName); + fsBuilder->codeAppendf("\t\tfloat threshold = %s + 2.0*%s;\n", cornerRadiusName, blurRadiusName ); + fsBuilder->codeAppendf("\t\tvec2 middle = %s.zw - %s.xy - 2.0*threshold;\n", rectName, rectName ); + + fsBuilder->codeAppendf("\t\tif (translatedFragPos.x >= threshold && translatedFragPos.x < (middle.x+threshold)) {\n" ); + fsBuilder->codeAppendf("\t\t\ttranslatedFragPos.x = threshold;\n"); + fsBuilder->codeAppendf("\t\t} else if (translatedFragPos.x >= (middle.x + threshold)) {\n"); + fsBuilder->codeAppendf("\t\t\ttranslatedFragPos.x -= middle.x - 1.0;\n"); + fsBuilder->codeAppendf("\t\t}\n"); + + fsBuilder->codeAppendf("\t\tif (translatedFragPos.y > threshold && translatedFragPos.y < (middle.y+threshold)) {\n" ); + fsBuilder->codeAppendf("\t\t\ttranslatedFragPos.y = threshold;\n"); + fsBuilder->codeAppendf("\t\t} else if (translatedFragPos.y >= (middle.y + threshold)) {\n"); + fsBuilder->codeAppendf("\t\t\ttranslatedFragPos.y -= middle.y - 1.0;\n"); + fsBuilder->codeAppendf("\t\t}\n"); + + fsBuilder->codeAppendf("\t\tvec2 proxyDims = vec2(2.0*threshold+1.0);\n"); + fsBuilder->codeAppendf("\t\tvec2 texCoord = translatedFragPos / proxyDims;\n"); + + fsBuilder->codeAppendf("\t%s = ", outputColor); + fsBuilder->appendTextureLookupAndModulate(inputColor, samplers[0], "texCoord"); + fsBuilder->codeAppend(";\n"); } void GrGLRRectBlurEffect::setData(const GrGLProgramDataManager& pdman, diff --git a/src/effects/SkColorFilters.cpp b/src/effects/SkColorFilters.cpp index bcaabf6c9b..e825695d58 100644 --- a/src/effects/SkColorFilters.cpp +++ b/src/effects/SkColorFilters.cpp @@ -127,7 +127,7 @@ SkFlattenable* SkModeColorFilter::CreateProc(SkReadBuffer& buffer) { #include "GrEffectUnitTest.h" #include "GrTBackendEffectFactory.h" #include "gl/GrGLEffect.h" -#include "gl/GrGLShaderBuilder.h" +#include "gl/builders/GrGLProgramBuilder.h" #include "SkGr.h" namespace { @@ -222,7 +222,7 @@ public: : INHERITED(factory) { } - virtual void emitCode(GrGLShaderBuilder* builder, + virtual void emitCode(GrGLProgramBuilder* builder, const GrDrawEffect& drawEffect, const GrEffectKey& key, const char* outputColor, @@ -234,7 +234,7 @@ public: SkASSERT(SkXfermode::kDst_Mode != mode); const char* colorFilterColorUniName = NULL; if (drawEffect.castEffect().willUseFilterColor()) { - fFilterColorUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, + fFilterColorUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec4f_GrSLType, "FilterColor", &colorFilterColorUniName); } @@ -242,7 +242,8 @@ public: GrGLSLExpr4 filter = color_filter_expression(mode, GrGLSLExpr4(colorFilterColorUniName), GrGLSLExpr4(inputColor)); - builder->fsCodeAppendf("\t%s = %s;\n", outputColor, filter.c_str()); + builder->getFragmentShaderBuilder()-> + codeAppendf("\t%s = %s;\n", outputColor, filter.c_str()); } static void GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&, diff --git a/src/effects/SkColorMatrixFilter.cpp b/src/effects/SkColorMatrixFilter.cpp index f62e0f1462..beed67efcf 100644 --- a/src/effects/SkColorMatrixFilter.cpp +++ b/src/effects/SkColorMatrixFilter.cpp @@ -335,7 +335,7 @@ bool SkColorMatrixFilter::asColorMatrix(SkScalar matrix[20]) const { #include "GrEffect.h" #include "GrTBackendEffectFactory.h" #include "gl/GrGLEffect.h" -#include "gl/GrGLShaderBuilder.h" +#include "gl/builders/GrGLProgramBuilder.h" class ColorMatrixEffect : public GrEffect { public: @@ -406,17 +406,17 @@ public: : INHERITED(factory) { } - virtual void emitCode(GrGLShaderBuilder* builder, + virtual void emitCode(GrGLProgramBuilder* builder, const GrDrawEffect&, const GrEffectKey&, const char* outputColor, const char* inputColor, const TransformedCoordsArray&, const TextureSamplerArray&) SK_OVERRIDE { - fMatrixHandle = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, + fMatrixHandle = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kMat44f_GrSLType, "ColorMatrix"); - fVectorHandle = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, + fVectorHandle = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec4f_GrSLType, "ColorMatrixVector"); @@ -424,16 +424,17 @@ public: // could optimize this case, but we aren't for now. inputColor = "vec4(1)"; } + GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); // The max() is to guard against 0 / 0 during unpremul when the incoming color is // transparent black. - builder->fsCodeAppendf("\tfloat nonZeroAlpha = max(%s.a, 0.00001);\n", inputColor); - builder->fsCodeAppendf("\t%s = %s * vec4(%s.rgb / nonZeroAlpha, nonZeroAlpha) + %s;\n", + fsBuilder->codeAppendf("\tfloat nonZeroAlpha = max(%s.a, 0.00001);\n", inputColor); + fsBuilder->codeAppendf("\t%s = %s * vec4(%s.rgb / nonZeroAlpha, nonZeroAlpha) + %s;\n", outputColor, builder->getUniformCStr(fMatrixHandle), inputColor, builder->getUniformCStr(fVectorHandle)); - builder->fsCodeAppendf("\t%s = clamp(%s, 0.0, 1.0);\n", outputColor, outputColor); - builder->fsCodeAppendf("\t%s.rgb *= %s.a;\n", outputColor, outputColor); + fsBuilder->codeAppendf("\t%s = clamp(%s, 0.0, 1.0);\n", outputColor, outputColor); + fsBuilder->codeAppendf("\t%s.rgb *= %s.a;\n", outputColor, outputColor); } virtual void setData(const GrGLProgramDataManager& uniManager, diff --git a/src/effects/SkDisplacementMapEffect.cpp b/src/effects/SkDisplacementMapEffect.cpp index 27fc0d3722..a1d29bf427 100644 --- a/src/effects/SkDisplacementMapEffect.cpp +++ b/src/effects/SkDisplacementMapEffect.cpp @@ -14,7 +14,7 @@ #include "GrContext.h" #include "GrCoordTransform.h" #include "gl/GrGLEffect.h" -#include "gl/GrGLShaderBuilder.h" +#include "gl/builders/GrGLProgramBuilder.h" #include "GrTBackendEffectFactory.h" #endif @@ -302,7 +302,7 @@ public: const GrDrawEffect& drawEffect); virtual ~GrGLDisplacementMapEffect(); - virtual void emitCode(GrGLShaderBuilder*, + virtual void emitCode(GrGLProgramBuilder*, const GrDrawEffect&, const GrEffectKey&, const char* outputColor, @@ -540,7 +540,7 @@ GrGLDisplacementMapEffect::GrGLDisplacementMapEffect(const GrBackendEffectFactor GrGLDisplacementMapEffect::~GrGLDisplacementMapEffect() { } -void GrGLDisplacementMapEffect::emitCode(GrGLShaderBuilder* builder, +void GrGLDisplacementMapEffect::emitCode(GrGLProgramBuilder* builder, const GrDrawEffect&, const GrEffectKey& key, const char* outputColor, @@ -549,7 +549,7 @@ void GrGLDisplacementMapEffect::emitCode(GrGLShaderBuilder* builder, const TextureSamplerArray& samplers) { sk_ignore_unused_variable(inputColor); - fScaleUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, + fScaleUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec2f_GrSLType, "Scale"); const char* scaleUni = builder->getUniformCStr(fScaleUni); const char* dColor = "dColor"; @@ -559,29 +559,30 @@ void GrGLDisplacementMapEffect::emitCode(GrGLShaderBuilder* builder, // a number smaller than that to approximate 0, but // leave room for 32-bit float GPU rounding errors. - builder->fsCodeAppendf("\t\tvec4 %s = ", dColor); - builder->fsAppendTextureLookup(samplers[0], coords[0].c_str(), coords[0].type()); - builder->fsCodeAppend(";\n"); + GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); + fsBuilder->codeAppendf("\t\tvec4 %s = ", dColor); + fsBuilder->appendTextureLookup(samplers[0], coords[0].c_str(), coords[0].type()); + fsBuilder->codeAppend(";\n"); // Unpremultiply the displacement - builder->fsCodeAppendf("\t\t%s.rgb = (%s.a < %s) ? vec3(0.0) : clamp(%s.rgb / %s.a, 0.0, 1.0);", + fsBuilder->codeAppendf("\t\t%s.rgb = (%s.a < %s) ? vec3(0.0) : clamp(%s.rgb / %s.a, 0.0, 1.0);", dColor, dColor, nearZero, dColor, dColor); - builder->fsCodeAppendf("\t\tvec2 %s = %s + %s*(%s.", + fsBuilder->codeAppendf("\t\tvec2 %s = %s + %s*(%s.", cCoords, coords[1].c_str(), scaleUni, dColor); switch (fXChannelSelector) { case SkDisplacementMapEffect::kR_ChannelSelectorType: - builder->fsCodeAppend("r"); + fsBuilder->codeAppend("r"); break; case SkDisplacementMapEffect::kG_ChannelSelectorType: - builder->fsCodeAppend("g"); + fsBuilder->codeAppend("g"); break; case SkDisplacementMapEffect::kB_ChannelSelectorType: - builder->fsCodeAppend("b"); + fsBuilder->codeAppend("b"); break; case SkDisplacementMapEffect::kA_ChannelSelectorType: - builder->fsCodeAppend("a"); + fsBuilder->codeAppend("a"); break; case SkDisplacementMapEffect::kUnknown_ChannelSelectorType: default: @@ -590,31 +591,31 @@ void GrGLDisplacementMapEffect::emitCode(GrGLShaderBuilder* builder, switch (fYChannelSelector) { case SkDisplacementMapEffect::kR_ChannelSelectorType: - builder->fsCodeAppend("r"); + fsBuilder->codeAppend("r"); break; case SkDisplacementMapEffect::kG_ChannelSelectorType: - builder->fsCodeAppend("g"); + fsBuilder->codeAppend("g"); break; case SkDisplacementMapEffect::kB_ChannelSelectorType: - builder->fsCodeAppend("b"); + fsBuilder->codeAppend("b"); break; case SkDisplacementMapEffect::kA_ChannelSelectorType: - builder->fsCodeAppend("a"); + fsBuilder->codeAppend("a"); break; case SkDisplacementMapEffect::kUnknown_ChannelSelectorType: default: SkDEBUGFAIL("Unknown Y channel selector"); } - builder->fsCodeAppend("-vec2(0.5));\t\t"); + fsBuilder->codeAppend("-vec2(0.5));\t\t"); // FIXME : This can be achieved with a "clamp to border" texture repeat mode and // a 0 border color instead of computing if cCoords is out of bounds here. - builder->fsCodeAppendf( + fsBuilder->codeAppendf( "bool %s = (%s.x < 0.0) || (%s.y < 0.0) || (%s.x > 1.0) || (%s.y > 1.0);\t\t", outOfBounds, cCoords, cCoords, cCoords, cCoords); - builder->fsCodeAppendf("%s = %s ? vec4(0.0) : ", outputColor, outOfBounds); - builder->fsAppendTextureLookup(samplers[1], cCoords, coords[1].type()); - builder->fsCodeAppend(";\n"); + fsBuilder->codeAppendf("%s = %s ? vec4(0.0) : ", outputColor, outOfBounds); + fsBuilder->appendTextureLookup(samplers[1], cCoords, coords[1].type()); + fsBuilder->codeAppend(";\n"); } void GrGLDisplacementMapEffect::setData(const GrGLProgramDataManager& pdman, diff --git a/src/effects/SkLightingImageFilter.cpp b/src/effects/SkLightingImageFilter.cpp index d93f4cc9e2..c3834c6977 100644 --- a/src/effects/SkLightingImageFilter.cpp +++ b/src/effects/SkLightingImageFilter.cpp @@ -17,7 +17,7 @@ #if SK_SUPPORT_GPU #include "effects/GrSingleTextureEffect.h" #include "gl/GrGLEffect.h" -#include "gl/GrGLShaderBuilder.h" +#include "gl/builders/GrGLProgramBuilder.h" #include "GrEffect.h" #include "GrTBackendEffectFactory.h" @@ -432,7 +432,7 @@ public: * This is called by GrGLLightingEffect::emitCode() before either of the two virtual functions * below. It adds a vec3f uniform visible in the FS that represents the constant light color. */ - void emitLightColorUniform(GrGLShaderBuilder*); + void emitLightColorUniform(GrGLProgramBuilder*); /** * These two functions are called from GrGLLightingEffect's emitCode() function. @@ -442,8 +442,8 @@ public: * the FS. The default of emitLightColor appends the name of the constant light color uniform * and so this function only needs to be overridden if the light color varies spatially. */ - virtual void emitSurfaceToLight(GrGLShaderBuilder*, const char* z) = 0; - virtual void emitLightColor(GrGLShaderBuilder*, const char *surfaceToLight); + virtual void emitSurfaceToLight(GrGLProgramBuilder*, const char* z) = 0; + virtual void emitLightColor(GrGLProgramBuilder*, const char *surfaceToLight); // This is called from GrGLLightingEffect's setData(). Subclasses of GrGLLight must call // INHERITED::setData(). @@ -470,7 +470,7 @@ public: virtual ~GrGLDistantLight() {} virtual void setData(const GrGLProgramDataManager&, const SkLight* light) const SK_OVERRIDE; - virtual void emitSurfaceToLight(GrGLShaderBuilder*, const char* z) SK_OVERRIDE; + virtual void emitSurfaceToLight(GrGLProgramBuilder*, const char* z) SK_OVERRIDE; private: typedef GrGLLight INHERITED; @@ -484,7 +484,7 @@ public: virtual ~GrGLPointLight() {} virtual void setData(const GrGLProgramDataManager&, const SkLight* light) const SK_OVERRIDE; - virtual void emitSurfaceToLight(GrGLShaderBuilder*, const char* z) SK_OVERRIDE; + virtual void emitSurfaceToLight(GrGLProgramBuilder*, const char* z) SK_OVERRIDE; private: typedef GrGLLight INHERITED; @@ -498,8 +498,8 @@ public: virtual ~GrGLSpotLight() {} virtual void setData(const GrGLProgramDataManager&, const SkLight* light) const SK_OVERRIDE; - virtual void emitSurfaceToLight(GrGLShaderBuilder*, const char* z) SK_OVERRIDE; - virtual void emitLightColor(GrGLShaderBuilder*, const char *surfaceToLight) SK_OVERRIDE; + virtual void emitSurfaceToLight(GrGLProgramBuilder*, const char* z) SK_OVERRIDE; + virtual void emitLightColor(GrGLProgramBuilder*, const char *surfaceToLight) SK_OVERRIDE; private: typedef GrGLLight INHERITED; @@ -1206,7 +1206,7 @@ public: const GrDrawEffect& effect); virtual ~GrGLLightingEffect(); - virtual void emitCode(GrGLShaderBuilder*, + virtual void emitCode(GrGLProgramBuilder*, const GrDrawEffect&, const GrEffectKey&, const char* outputColor, @@ -1222,7 +1222,7 @@ public: virtual void setData(const GrGLProgramDataManager&, const GrDrawEffect&) SK_OVERRIDE; protected: - virtual void emitLightFunc(GrGLShaderBuilder*, SkString* funcName) = 0; + virtual void emitLightFunc(GrGLProgramBuilder*, SkString* funcName) = 0; private: typedef GrGLEffect INHERITED; @@ -1238,7 +1238,7 @@ class GrGLDiffuseLightingEffect : public GrGLLightingEffect { public: GrGLDiffuseLightingEffect(const GrBackendEffectFactory& factory, const GrDrawEffect& drawEffect); - virtual void emitLightFunc(GrGLShaderBuilder*, SkString* funcName) SK_OVERRIDE; + virtual void emitLightFunc(GrGLProgramBuilder*, SkString* funcName) SK_OVERRIDE; virtual void setData(const GrGLProgramDataManager&, const GrDrawEffect&) SK_OVERRIDE; private: @@ -1253,7 +1253,7 @@ class GrGLSpecularLightingEffect : public GrGLLightingEffect { public: GrGLSpecularLightingEffect(const GrBackendEffectFactory& factory, const GrDrawEffect& effect); - virtual void emitLightFunc(GrGLShaderBuilder*, SkString* funcName) SK_OVERRIDE; + virtual void emitLightFunc(GrGLProgramBuilder*, SkString* funcName) SK_OVERRIDE; virtual void setData(const GrGLProgramDataManager&, const GrDrawEffect&) SK_OVERRIDE; private: @@ -1341,19 +1341,17 @@ GrGLLightingEffect::~GrGLLightingEffect() { delete fLight; } -void GrGLLightingEffect::emitCode(GrGLShaderBuilder* builder, +void GrGLLightingEffect::emitCode(GrGLProgramBuilder* builder, const GrDrawEffect&, const GrEffectKey& key, const char* outputColor, const char* inputColor, const TransformedCoordsArray& coords, const TextureSamplerArray& samplers) { - SkString coords2D = builder->ensureFSCoords2D(coords, 0); - - fImageIncrementUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, + fImageIncrementUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec2f_GrSLType, "ImageIncrement"); - fSurfaceScaleUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, + fSurfaceScaleUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kFloat_GrSLType, "SurfaceScale"); fLight->emitLightColorUniform(builder); @@ -1369,7 +1367,10 @@ void GrGLLightingEffect::emitCode(GrGLShaderBuilder* builder, GrGLShaderVar("scale", kFloat_GrSLType), }; SkString sobelFuncName; - builder->fsEmitFunction(kFloat_GrSLType, + GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); + SkString coords2D = fsBuilder->ensureFSCoords2D(coords, 0); + + fsBuilder->emitFunction(kFloat_GrSLType, "sobel", SK_ARRAY_COUNT(gSobelArgs), gSobelArgs, @@ -1381,7 +1382,7 @@ void GrGLLightingEffect::emitCode(GrGLShaderBuilder* builder, GrGLShaderVar("scale", kFloat_GrSLType), }; SkString pointToNormalName; - builder->fsEmitFunction(kVec3f_GrSLType, + fsBuilder->emitFunction(kVec3f_GrSLType, "pointToNormal", SK_ARRAY_COUNT(gPointToNormalArgs), gPointToNormalArgs, @@ -1400,15 +1401,15 @@ void GrGLLightingEffect::emitCode(GrGLShaderBuilder* builder, sobelFuncName.c_str(), sobelFuncName.c_str()); SkString interiorNormalName; - builder->fsEmitFunction(kVec3f_GrSLType, + fsBuilder->emitFunction(kVec3f_GrSLType, "interiorNormal", SK_ARRAY_COUNT(gInteriorNormalArgs), gInteriorNormalArgs, interiorNormalBody.c_str(), &interiorNormalName); - builder->fsCodeAppendf("\t\tvec2 coord = %s;\n", coords2D.c_str()); - builder->fsCodeAppend("\t\tfloat m[9];\n"); + fsBuilder->codeAppendf("\t\tvec2 coord = %s;\n", coords2D.c_str()); + fsBuilder->codeAppend("\t\tfloat m[9];\n"); const char* imgInc = builder->getUniformCStr(fImageIncrementUni); const char* surfScale = builder->getUniformCStr(fSurfaceScaleUni); @@ -1418,23 +1419,23 @@ void GrGLLightingEffect::emitCode(GrGLShaderBuilder* builder, for (int dx = -1; dx <= 1; dx++) { SkString texCoords; texCoords.appendf("coord + vec2(%d, %d) * %s", dx, dy, imgInc); - builder->fsCodeAppendf("\t\tm[%d] = ", index++); - builder->fsAppendTextureLookup(samplers[0], texCoords.c_str()); - builder->fsCodeAppend(".a;\n"); + fsBuilder->codeAppendf("\t\tm[%d] = ", index++); + fsBuilder->appendTextureLookup(samplers[0], texCoords.c_str()); + fsBuilder->codeAppend(".a;\n"); } } - builder->fsCodeAppend("\t\tvec3 surfaceToLight = "); + fsBuilder->codeAppend("\t\tvec3 surfaceToLight = "); SkString arg; arg.appendf("%s * m[4]", surfScale); fLight->emitSurfaceToLight(builder, arg.c_str()); - builder->fsCodeAppend(";\n"); - builder->fsCodeAppendf("\t\t%s = %s(%s(m, %s), surfaceToLight, ", + fsBuilder->codeAppend(";\n"); + fsBuilder->codeAppendf("\t\t%s = %s(%s(m, %s), surfaceToLight, ", outputColor, lightFunc.c_str(), interiorNormalName.c_str(), surfScale); fLight->emitLightColor(builder, "surfaceToLight"); - builder->fsCodeAppend(");\n"); + fsBuilder->codeAppend(");\n"); SkString modulate; GrGLSLMulVarBy4f(&modulate, 2, outputColor, inputColor); - builder->fsCodeAppend(modulate.c_str()); + fsBuilder->codeAppend(modulate.c_str()); } void GrGLLightingEffect::GenKey(const GrDrawEffect& drawEffect, @@ -1462,9 +1463,9 @@ GrGLDiffuseLightingEffect::GrGLDiffuseLightingEffect(const GrBackendEffectFactor : INHERITED(factory, drawEffect) { } -void GrGLDiffuseLightingEffect::emitLightFunc(GrGLShaderBuilder* builder, SkString* funcName) { +void GrGLDiffuseLightingEffect::emitLightFunc(GrGLProgramBuilder* builder, SkString* funcName) { const char* kd; - fKDUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, + fKDUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kFloat_GrSLType, "KD", &kd); @@ -1477,12 +1478,12 @@ void GrGLDiffuseLightingEffect::emitLightFunc(GrGLShaderBuilder* builder, SkStri SkString lightBody; lightBody.appendf("\tfloat colorScale = %s * dot(normal, surfaceToLight);\n", kd); lightBody.appendf("\treturn vec4(lightColor * clamp(colorScale, 0.0, 1.0), 1.0);\n"); - builder->fsEmitFunction(kVec4f_GrSLType, - "light", - SK_ARRAY_COUNT(gLightArgs), - gLightArgs, - lightBody.c_str(), - funcName); + builder->getFragmentShaderBuilder()->emitFunction(kVec4f_GrSLType, + "light", + SK_ARRAY_COUNT(gLightArgs), + gLightArgs, + lightBody.c_str(), + funcName); } void GrGLDiffuseLightingEffect::setData(const GrGLProgramDataManager& pdman, @@ -1541,13 +1542,13 @@ GrGLSpecularLightingEffect::GrGLSpecularLightingEffect(const GrBackendEffectFact : INHERITED(factory, drawEffect) { } -void GrGLSpecularLightingEffect::emitLightFunc(GrGLShaderBuilder* builder, SkString* funcName) { +void GrGLSpecularLightingEffect::emitLightFunc(GrGLProgramBuilder* builder, SkString* funcName) { const char* ks; const char* shininess; - fKSUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, + fKSUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kFloat_GrSLType, "KS", &ks); - fShininessUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, + fShininessUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kFloat_GrSLType, "Shininess", &shininess); static const GrGLShaderVar gLightArgs[] = { @@ -1560,12 +1561,12 @@ void GrGLSpecularLightingEffect::emitLightFunc(GrGLShaderBuilder* builder, SkStr lightBody.appendf("\tfloat colorScale = %s * pow(dot(normal, halfDir), %s);\n", ks, shininess); lightBody.appendf("\tvec3 color = lightColor * clamp(colorScale, 0.0, 1.0);\n"); lightBody.appendf("\treturn vec4(color, max(max(color.r, color.g), color.b));\n"); - builder->fsEmitFunction(kVec4f_GrSLType, - "light", - SK_ARRAY_COUNT(gLightArgs), - gLightArgs, - lightBody.c_str(), - funcName); + builder->getFragmentShaderBuilder()->emitFunction(kVec4f_GrSLType, + "light", + SK_ARRAY_COUNT(gLightArgs), + gLightArgs, + lightBody.c_str(), + funcName); } void GrGLSpecularLightingEffect::setData(const GrGLProgramDataManager& pdman, @@ -1577,14 +1578,15 @@ void GrGLSpecularLightingEffect::setData(const GrGLProgramDataManager& pdman, } /////////////////////////////////////////////////////////////////////////////// -void GrGLLight::emitLightColorUniform(GrGLShaderBuilder* builder) { - fColorUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, +void GrGLLight::emitLightColorUniform(GrGLProgramBuilder* builder) { + fColorUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec3f_GrSLType, "LightColor"); } -void GrGLLight::emitLightColor(GrGLShaderBuilder* builder, +void GrGLLight::emitLightColor(GrGLProgramBuilder* builder, const char *surfaceToLight) { - builder->fsCodeAppend(builder->getUniformCStr(this->lightColorUni())); + builder->getFragmentShaderBuilder()-> + codeAppend(builder->getUniformCStr(this->lightColorUni())); } void GrGLLight::setData(const GrGLProgramDataManager& pdman, @@ -1602,11 +1604,11 @@ void GrGLDistantLight::setData(const GrGLProgramDataManager& pdman, setUniformNormal3(pdman, fDirectionUni, distantLight->direction()); } -void GrGLDistantLight::emitSurfaceToLight(GrGLShaderBuilder* builder, const char* z) { +void GrGLDistantLight::emitSurfaceToLight(GrGLProgramBuilder* builder, const char* z) { const char* dir; - fDirectionUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, kVec3f_GrSLType, + fDirectionUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec3f_GrSLType, "LightDirection", &dir); - builder->fsCodeAppend(dir); + builder->getFragmentShaderBuilder()->codeAppend(dir); } /////////////////////////////////////////////////////////////////////////////// @@ -1619,11 +1621,13 @@ void GrGLPointLight::setData(const GrGLProgramDataManager& pdman, setUniformPoint3(pdman, fLocationUni, pointLight->location()); } -void GrGLPointLight::emitSurfaceToLight(GrGLShaderBuilder* builder, const char* z) { +void GrGLPointLight::emitSurfaceToLight(GrGLProgramBuilder* builder, const char* z) { const char* loc; - fLocationUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, kVec3f_GrSLType, + fLocationUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec3f_GrSLType, "LightLocation", &loc); - builder->fsCodeAppendf("normalize(%s - vec3(%s.xy, %s))", loc, builder->fragmentPosition(), z); + GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); + fsBuilder->codeAppendf("normalize(%s - vec3(%s.xy, %s))", + loc, fsBuilder->fragmentPosition(), z); } /////////////////////////////////////////////////////////////////////////////// @@ -1641,15 +1645,17 @@ void GrGLSpotLight::setData(const GrGLProgramDataManager& pdman, setUniformNormal3(pdman, fSUni, spotLight->s()); } -void GrGLSpotLight::emitSurfaceToLight(GrGLShaderBuilder* builder, const char* z) { +void GrGLSpotLight::emitSurfaceToLight(GrGLProgramBuilder* builder, const char* z) { const char* location; - fLocationUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, + fLocationUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec3f_GrSLType, "LightLocation", &location); - builder->fsCodeAppendf("normalize(%s - vec3(%s.xy, %s))", - location, builder->fragmentPosition(), z); + + GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); + fsBuilder->codeAppendf("normalize(%s - vec3(%s.xy, %s))", + location, fsBuilder->fragmentPosition(), z); } -void GrGLSpotLight::emitLightColor(GrGLShaderBuilder* builder, +void GrGLSpotLight::emitLightColor(GrGLProgramBuilder* builder, const char *surfaceToLight) { const char* color = builder->getUniformCStr(this->lightColorUni()); // created by parent class. @@ -1659,15 +1665,15 @@ void GrGLSpotLight::emitLightColor(GrGLShaderBuilder* builder, const char* cosOuter; const char* coneScale; const char* s; - fExponentUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, + fExponentUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kFloat_GrSLType, "Exponent", &exponent); - fCosInnerConeAngleUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, + fCosInnerConeAngleUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kFloat_GrSLType, "CosInnerConeAngle", &cosInner); - fCosOuterConeAngleUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, + fCosOuterConeAngleUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kFloat_GrSLType, "CosOuterConeAngle", &cosOuter); - fConeScaleUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, + fConeScaleUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kFloat_GrSLType, "ConeScale", &coneScale); - fSUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, + fSUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec3f_GrSLType, "S", &s); static const GrGLShaderVar gLightColorArgs[] = { @@ -1684,14 +1690,15 @@ void GrGLSpotLight::emitLightColor(GrGLShaderBuilder* builder, color, cosOuter, coneScale); lightColorBody.appendf("\t}\n"); lightColorBody.appendf("\treturn %s;\n", color); - builder->fsEmitFunction(kVec3f_GrSLType, + GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); + fsBuilder->emitFunction(kVec3f_GrSLType, "lightColor", SK_ARRAY_COUNT(gLightColorArgs), gLightColorArgs, lightColorBody.c_str(), &fLightColorFunc); - builder->fsCodeAppendf("%s(%s)", fLightColorFunc.c_str(), surfaceToLight); + fsBuilder->codeAppendf("%s(%s)", fLightColorFunc.c_str(), surfaceToLight); } #endif diff --git a/src/effects/SkLumaColorFilter.cpp b/src/effects/SkLumaColorFilter.cpp index 26621bb02e..c1ce05c530 100644 --- a/src/effects/SkLumaColorFilter.cpp +++ b/src/effects/SkLumaColorFilter.cpp @@ -12,7 +12,7 @@ #if SK_SUPPORT_GPU #include "gl/GrGLEffect.h" -#include "gl/GrGLShaderBuilder.h" +#include "gl/builders/GrGLProgramBuilder.h" #include "GrContext.h" #include "GrTBackendEffectFactory.h" #endif @@ -89,7 +89,7 @@ public: static void GenKey(const GrDrawEffect&, const GrGLCaps&, GrEffectKeyBuilder* b) {} - virtual void emitCode(GrGLShaderBuilder* builder, + virtual void emitCode(GrGLProgramBuilder* builder, const GrDrawEffect&, const GrEffectKey&, const char* outputColor, @@ -100,12 +100,13 @@ public: inputColor = "vec4(1)"; } - builder->fsCodeAppendf("\tfloat luma = dot(vec3(%f, %f, %f), %s.rgb);\n", + GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); + fsBuilder->codeAppendf("\tfloat luma = dot(vec3(%f, %f, %f), %s.rgb);\n", SK_ITU_BT709_LUM_COEFF_R, SK_ITU_BT709_LUM_COEFF_G, SK_ITU_BT709_LUM_COEFF_B, inputColor); - builder->fsCodeAppendf("\t%s = vec4(0, 0, 0, luma);\n", + fsBuilder->codeAppendf("\t%s = vec4(0, 0, 0, luma);\n", outputColor); } diff --git a/src/effects/SkMagnifierImageFilter.cpp b/src/effects/SkMagnifierImageFilter.cpp index cb0fc2423f..bf6f4a7725 100644 --- a/src/effects/SkMagnifierImageFilter.cpp +++ b/src/effects/SkMagnifierImageFilter.cpp @@ -16,7 +16,7 @@ #if SK_SUPPORT_GPU #include "effects/GrSingleTextureEffect.h" #include "gl/GrGLEffect.h" -#include "gl/GrGLShaderBuilder.h" +#include "gl/builders/GrGLProgramBuilder.h" #include "gl/GrGLSL.h" #include "gl/GrGLTexture.h" #include "GrTBackendEffectFactory.h" @@ -95,7 +95,7 @@ class GrGLMagnifierEffect : public GrGLEffect { public: GrGLMagnifierEffect(const GrBackendEffectFactory&, const GrDrawEffect&); - virtual void emitCode(GrGLShaderBuilder*, + virtual void emitCode(GrGLProgramBuilder*, const GrDrawEffect&, const GrEffectKey&, const char* outputColor, @@ -117,57 +117,58 @@ GrGLMagnifierEffect::GrGLMagnifierEffect(const GrBackendEffectFactory& factory, : INHERITED(factory) { } -void GrGLMagnifierEffect::emitCode(GrGLShaderBuilder* builder, +void GrGLMagnifierEffect::emitCode(GrGLProgramBuilder* builder, const GrDrawEffect&, const GrEffectKey& key, const char* outputColor, const char* inputColor, const TransformedCoordsArray& coords, const TextureSamplerArray& samplers) { - SkString coords2D = builder->ensureFSCoords2D(coords, 0); fOffsetVar = builder->addUniform( - GrGLShaderBuilder::kFragment_Visibility | - GrGLShaderBuilder::kVertex_Visibility, + GrGLProgramBuilder::kFragment_Visibility | + GrGLProgramBuilder::kVertex_Visibility, kVec2f_GrSLType, "Offset"); fInvZoomVar = builder->addUniform( - GrGLShaderBuilder::kFragment_Visibility | - GrGLShaderBuilder::kVertex_Visibility, + GrGLProgramBuilder::kFragment_Visibility | + GrGLProgramBuilder::kVertex_Visibility, kVec2f_GrSLType, "InvZoom"); fInvInsetVar = builder->addUniform( - GrGLShaderBuilder::kFragment_Visibility | - GrGLShaderBuilder::kVertex_Visibility, + GrGLProgramBuilder::kFragment_Visibility | + GrGLProgramBuilder::kVertex_Visibility, kVec2f_GrSLType, "InvInset"); - builder->fsCodeAppendf("\t\tvec2 coord = %s;\n", coords2D.c_str()); - builder->fsCodeAppendf("\t\tvec2 zoom_coord = %s + %s * %s;\n", + GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); + SkString coords2D = fsBuilder->ensureFSCoords2D(coords, 0); + fsBuilder->codeAppendf("\t\tvec2 coord = %s;\n", coords2D.c_str()); + fsBuilder->codeAppendf("\t\tvec2 zoom_coord = %s + %s * %s;\n", builder->getUniformCStr(fOffsetVar), coords2D.c_str(), builder->getUniformCStr(fInvZoomVar)); - builder->fsCodeAppend("\t\tvec2 delta = min(coord, vec2(1.0, 1.0) - coord);\n"); + fsBuilder->codeAppend("\t\tvec2 delta = min(coord, vec2(1.0, 1.0) - coord);\n"); - builder->fsCodeAppendf("\t\tdelta = delta * %s;\n", builder->getUniformCStr(fInvInsetVar)); + fsBuilder->codeAppendf("\t\tdelta = delta * %s;\n", builder->getUniformCStr(fInvInsetVar)); - builder->fsCodeAppend("\t\tfloat weight = 0.0;\n"); - builder->fsCodeAppend("\t\tif (delta.s < 2.0 && delta.t < 2.0) {\n"); - builder->fsCodeAppend("\t\t\tdelta = vec2(2.0, 2.0) - delta;\n"); - builder->fsCodeAppend("\t\t\tfloat dist = length(delta);\n"); - builder->fsCodeAppend("\t\t\tdist = max(2.0 - dist, 0.0);\n"); - builder->fsCodeAppend("\t\t\tweight = min(dist * dist, 1.0);\n"); - builder->fsCodeAppend("\t\t} else {\n"); - builder->fsCodeAppend("\t\t\tvec2 delta_squared = delta * delta;\n"); - builder->fsCodeAppend("\t\t\tweight = min(min(delta_squared.x, delta_squared.y), 1.0);\n"); - builder->fsCodeAppend("\t\t}\n"); + fsBuilder->codeAppend("\t\tfloat weight = 0.0;\n"); + fsBuilder->codeAppend("\t\tif (delta.s < 2.0 && delta.t < 2.0) {\n"); + fsBuilder->codeAppend("\t\t\tdelta = vec2(2.0, 2.0) - delta;\n"); + fsBuilder->codeAppend("\t\t\tfloat dist = length(delta);\n"); + fsBuilder->codeAppend("\t\t\tdist = max(2.0 - dist, 0.0);\n"); + fsBuilder->codeAppend("\t\t\tweight = min(dist * dist, 1.0);\n"); + fsBuilder->codeAppend("\t\t} else {\n"); + fsBuilder->codeAppend("\t\t\tvec2 delta_squared = delta * delta;\n"); + fsBuilder->codeAppend("\t\t\tweight = min(min(delta_squared.x, delta_squared.y), 1.0);\n"); + fsBuilder->codeAppend("\t\t}\n"); - builder->fsCodeAppend("\t\tvec2 mix_coord = mix(coord, zoom_coord, weight);\n"); - builder->fsCodeAppend("\t\tvec4 output_color = "); - builder->fsAppendTextureLookup(samplers[0], "mix_coord"); - builder->fsCodeAppend(";\n"); + fsBuilder->codeAppend("\t\tvec2 mix_coord = mix(coord, zoom_coord, weight);\n"); + fsBuilder->codeAppend("\t\tvec4 output_color = "); + fsBuilder->appendTextureLookup(samplers[0], "mix_coord"); + fsBuilder->codeAppend(";\n"); - builder->fsCodeAppendf("\t\t%s = output_color;", outputColor); + fsBuilder->codeAppendf("\t\t%s = output_color;", outputColor); SkString modulate; GrGLSLMulVarBy4f(&modulate, 2, outputColor, inputColor); - builder->fsCodeAppend(modulate.c_str()); + fsBuilder->codeAppend(modulate.c_str()); } void GrGLMagnifierEffect::setData(const GrGLProgramDataManager& pdman, diff --git a/src/effects/SkMorphologyImageFilter.cpp b/src/effects/SkMorphologyImageFilter.cpp index bb8478c907..eef2a7d623 100644 --- a/src/effects/SkMorphologyImageFilter.cpp +++ b/src/effects/SkMorphologyImageFilter.cpp @@ -17,7 +17,7 @@ #include "GrTexture.h" #include "GrTBackendEffectFactory.h" #include "gl/GrGLEffect.h" -#include "gl/GrGLShaderBuilder.h" +#include "gl/builders/GrGLProgramBuilder.h" #include "effects/Gr1DKernelEffect.h" #endif @@ -329,7 +329,7 @@ class GrGLMorphologyEffect : public GrGLEffect { public: GrGLMorphologyEffect (const GrBackendEffectFactory&, const GrDrawEffect&); - virtual void emitCode(GrGLShaderBuilder*, + virtual void emitCode(GrGLProgramBuilder*, const GrDrawEffect&, const GrEffectKey&, const char* outputColor, @@ -359,25 +359,26 @@ GrGLMorphologyEffect::GrGLMorphologyEffect(const GrBackendEffectFactory& factory fType = m.type(); } -void GrGLMorphologyEffect::emitCode(GrGLShaderBuilder* builder, +void GrGLMorphologyEffect::emitCode(GrGLProgramBuilder* builder, const GrDrawEffect&, const GrEffectKey& key, const char* outputColor, const char* inputColor, const TransformedCoordsArray& coords, const TextureSamplerArray& samplers) { - SkString coords2D = builder->ensureFSCoords2D(coords, 0); - fImageIncrementUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, + fImageIncrementUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec2f_GrSLType, "ImageIncrement"); + GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); + SkString coords2D = fsBuilder->ensureFSCoords2D(coords, 0); const char* func; switch (fType) { case GrMorphologyEffect::kErode_MorphologyType: - builder->fsCodeAppendf("\t\t%s = vec4(1, 1, 1, 1);\n", outputColor); + fsBuilder->codeAppendf("\t\t%s = vec4(1, 1, 1, 1);\n", outputColor); func = "min"; break; case GrMorphologyEffect::kDilate_MorphologyType: - builder->fsCodeAppendf("\t\t%s = vec4(0, 0, 0, 0);\n", outputColor); + fsBuilder->codeAppendf("\t\t%s = vec4(0, 0, 0, 0);\n", outputColor); func = "max"; break; default: @@ -387,16 +388,16 @@ void GrGLMorphologyEffect::emitCode(GrGLShaderBuilder* builder, } const char* imgInc = builder->getUniformCStr(fImageIncrementUni); - builder->fsCodeAppendf("\t\tvec2 coord = %s - %d.0 * %s;\n", coords2D.c_str(), fRadius, imgInc); - builder->fsCodeAppendf("\t\tfor (int i = 0; i < %d; i++) {\n", this->width()); - builder->fsCodeAppendf("\t\t\t%s = %s(%s, ", outputColor, func, outputColor); - builder->fsAppendTextureLookup(samplers[0], "coord"); - builder->fsCodeAppend(");\n"); - builder->fsCodeAppendf("\t\t\tcoord += %s;\n", imgInc); - builder->fsCodeAppend("\t\t}\n"); + fsBuilder->codeAppendf("\t\tvec2 coord = %s - %d.0 * %s;\n", coords2D.c_str(), fRadius, imgInc); + fsBuilder->codeAppendf("\t\tfor (int i = 0; i < %d; i++) {\n", this->width()); + fsBuilder->codeAppendf("\t\t\t%s = %s(%s, ", outputColor, func, outputColor); + fsBuilder->appendTextureLookup(samplers[0], "coord"); + fsBuilder->codeAppend(");\n"); + fsBuilder->codeAppendf("\t\t\tcoord += %s;\n", imgInc); + fsBuilder->codeAppend("\t\t}\n"); SkString modulate; GrGLSLMulVarBy4f(&modulate, 2, outputColor, inputColor); - builder->fsCodeAppend(modulate.c_str()); + fsBuilder->codeAppend(modulate.c_str()); } void GrGLMorphologyEffect::GenKey(const GrDrawEffect& drawEffect, diff --git a/src/effects/SkPerlinNoiseShader.cpp b/src/effects/SkPerlinNoiseShader.cpp index 427b451dd0..b0ebb39342 100644 --- a/src/effects/SkPerlinNoiseShader.cpp +++ b/src/effects/SkPerlinNoiseShader.cpp @@ -18,7 +18,7 @@ #include "GrContext.h" #include "GrCoordTransform.h" #include "gl/GrGLEffect.h" -#include "gl/GrGLShaderBuilder.h" +#include "gl/builders/GrGLProgramBuilder.h" #include "GrTBackendEffectFactory.h" #include "SkGr.h" #endif @@ -515,7 +515,7 @@ public: const GrDrawEffect& drawEffect); virtual ~GrGLPerlinNoise() {} - virtual void emitCode(GrGLShaderBuilder*, + virtual void emitCode(GrGLProgramBuilder*, const GrDrawEffect&, const GrEffectKey&, const char* outputColor, @@ -663,7 +663,7 @@ GrGLPerlinNoise::GrGLPerlinNoise(const GrBackendEffectFactory& factory, const Gr , fNumOctaves(drawEffect.castEffect().numOctaves()) { } -void GrGLPerlinNoise::emitCode(GrGLShaderBuilder* builder, +void GrGLPerlinNoise::emitCode(GrGLProgramBuilder* builder, const GrDrawEffect&, const GrEffectKey& key, const char* outputColor, @@ -672,18 +672,19 @@ void GrGLPerlinNoise::emitCode(GrGLShaderBuilder* builder, const TextureSamplerArray& samplers) { sk_ignore_unused_variable(inputColor); - SkString vCoords = builder->ensureFSCoords2D(coords, 0); + GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); + SkString vCoords = fsBuilder->ensureFSCoords2D(coords, 0); - fBaseFrequencyUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, + fBaseFrequencyUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec2f_GrSLType, "baseFrequency"); const char* baseFrequencyUni = builder->getUniformCStr(fBaseFrequencyUni); - fAlphaUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, + fAlphaUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kFloat_GrSLType, "alpha"); const char* alphaUni = builder->getUniformCStr(fAlphaUni); const char* stitchDataUni = NULL; if (fStitchTiles) { - fStitchDataUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, + fStitchDataUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec2f_GrSLType, "stitchData"); stitchDataUni = builder->getUniformCStr(fStitchDataUni); } @@ -755,7 +756,7 @@ void GrGLPerlinNoise::emitCode(GrGLShaderBuilder* builder, xCoords.appendf("vec2(%s.x, 0.5)", floorVal); noiseCode.appendf("\n\tvec2 %s;\n\t%s.x = ", latticeIdx, latticeIdx); - builder->appendTextureLookup(&noiseCode, samplers[0], xCoords.c_str(), kVec2f_GrSLType); + fsBuilder->appendTextureLookup(&noiseCode, samplers[0], xCoords.c_str(), kVec2f_GrSLType); noiseCode.append(".r;"); } @@ -765,7 +766,7 @@ void GrGLPerlinNoise::emitCode(GrGLShaderBuilder* builder, xCoords.appendf("vec2(%s.z, 0.5)", floorVal); noiseCode.appendf("\n\t%s.y = ", latticeIdx); - builder->appendTextureLookup(&noiseCode, samplers[0], xCoords.c_str(), kVec2f_GrSLType); + fsBuilder->appendTextureLookup(&noiseCode, samplers[0], xCoords.c_str(), kVec2f_GrSLType); noiseCode.append(".r;"); } @@ -789,7 +790,7 @@ void GrGLPerlinNoise::emitCode(GrGLShaderBuilder* builder, SkString latticeCoords(""); latticeCoords.appendf("vec2(%s.x, %s)", bcoords, chanCoord); noiseCode.appendf("\n\tvec4 %s = ", lattice); - builder->appendTextureLookup(&noiseCode, samplers[1], latticeCoords.c_str(), + fsBuilder->appendTextureLookup(&noiseCode, samplers[1], latticeCoords.c_str(), kVec2f_GrSLType); noiseCode.appendf(".bgra;\n\t%s.x = ", uv); noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal); @@ -801,7 +802,7 @@ void GrGLPerlinNoise::emitCode(GrGLShaderBuilder* builder, SkString latticeCoords(""); latticeCoords.appendf("vec2(%s.y, %s)", bcoords, chanCoord); noiseCode.append("\n\tlattice = "); - builder->appendTextureLookup(&noiseCode, samplers[1], latticeCoords.c_str(), + fsBuilder->appendTextureLookup(&noiseCode, samplers[1], latticeCoords.c_str(), kVec2f_GrSLType); noiseCode.appendf(".bgra;\n\t%s.y = ", uv); noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal); @@ -817,7 +818,7 @@ void GrGLPerlinNoise::emitCode(GrGLShaderBuilder* builder, SkString latticeCoords(""); latticeCoords.appendf("vec2(%s.w, %s)", bcoords, chanCoord); noiseCode.append("\n\tlattice = "); - builder->appendTextureLookup(&noiseCode, samplers[1], latticeCoords.c_str(), + fsBuilder->appendTextureLookup(&noiseCode, samplers[1], latticeCoords.c_str(), kVec2f_GrSLType); noiseCode.appendf(".bgra;\n\t%s.y = ", uv); noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal); @@ -829,7 +830,7 @@ void GrGLPerlinNoise::emitCode(GrGLShaderBuilder* builder, SkString latticeCoords(""); latticeCoords.appendf("vec2(%s.z, %s)", bcoords, chanCoord); noiseCode.append("\n\tlattice = "); - builder->appendTextureLookup(&noiseCode, samplers[1], latticeCoords.c_str(), + fsBuilder->appendTextureLookup(&noiseCode, samplers[1], latticeCoords.c_str(), kVec2f_GrSLType); noiseCode.appendf(".bgra;\n\t%s.x = ", uv); noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal); @@ -842,38 +843,38 @@ void GrGLPerlinNoise::emitCode(GrGLShaderBuilder* builder, SkString noiseFuncName; if (fStitchTiles) { - builder->fsEmitFunction(kFloat_GrSLType, + fsBuilder->emitFunction(kFloat_GrSLType, "perlinnoise", SK_ARRAY_COUNT(gPerlinNoiseStitchArgs), gPerlinNoiseStitchArgs, noiseCode.c_str(), &noiseFuncName); } else { - builder->fsEmitFunction(kFloat_GrSLType, + fsBuilder->emitFunction(kFloat_GrSLType, "perlinnoise", SK_ARRAY_COUNT(gPerlinNoiseArgs), gPerlinNoiseArgs, noiseCode.c_str(), &noiseFuncName); } // There are rounding errors if the floor operation is not performed here - builder->fsCodeAppendf("\n\t\tvec2 %s = floor(%s.xy) * %s;", + fsBuilder->codeAppendf("\n\t\tvec2 %s = floor(%s.xy) * %s;", noiseVec, vCoords.c_str(), baseFrequencyUni); // Clear the color accumulator - builder->fsCodeAppendf("\n\t\t%s = vec4(0.0);", outputColor); + fsBuilder->codeAppendf("\n\t\t%s = vec4(0.0);", outputColor); if (fStitchTiles) { // Set up TurbulenceInitial stitch values. - builder->fsCodeAppendf("\n\t\tvec2 %s = %s;", stitchData, stitchDataUni); + fsBuilder->codeAppendf("\n\t\tvec2 %s = %s;", stitchData, stitchDataUni); } - builder->fsCodeAppendf("\n\t\tfloat %s = 1.0;", ratio); + fsBuilder->codeAppendf("\n\t\tfloat %s = 1.0;", ratio); // Loop over all octaves - builder->fsCodeAppendf("\n\t\tfor (int octave = 0; octave < %d; ++octave) {", fNumOctaves); + fsBuilder->codeAppendf("\n\t\tfor (int octave = 0; octave < %d; ++octave) {", fNumOctaves); - builder->fsCodeAppendf("\n\t\t\t%s += ", outputColor); + fsBuilder->codeAppendf("\n\t\t\t%s += ", outputColor); if (fType != SkPerlinNoiseShader::kFractalNoise_Type) { - builder->fsCodeAppend("abs("); + fsBuilder->codeAppend("abs("); } if (fStitchTiles) { - builder->fsCodeAppendf( + fsBuilder->codeAppendf( "vec4(\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s)," "\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s))", noiseFuncName.c_str(), chanCoordR, noiseVec, stitchData, @@ -881,7 +882,7 @@ void GrGLPerlinNoise::emitCode(GrGLShaderBuilder* builder, noiseFuncName.c_str(), chanCoordB, noiseVec, stitchData, noiseFuncName.c_str(), chanCoordA, noiseVec, stitchData); } else { - builder->fsCodeAppendf( + fsBuilder->codeAppendf( "vec4(\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s)," "\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s))", noiseFuncName.c_str(), chanCoordR, noiseVec, @@ -890,31 +891,31 @@ void GrGLPerlinNoise::emitCode(GrGLShaderBuilder* builder, noiseFuncName.c_str(), chanCoordA, noiseVec); } if (fType != SkPerlinNoiseShader::kFractalNoise_Type) { - builder->fsCodeAppendf(")"); // end of "abs(" + fsBuilder->codeAppendf(")"); // end of "abs(" } - builder->fsCodeAppendf(" * %s;", ratio); + fsBuilder->codeAppendf(" * %s;", ratio); - builder->fsCodeAppendf("\n\t\t\t%s *= vec2(2.0);", noiseVec); - builder->fsCodeAppendf("\n\t\t\t%s *= 0.5;", ratio); + fsBuilder->codeAppendf("\n\t\t\t%s *= vec2(2.0);", noiseVec); + fsBuilder->codeAppendf("\n\t\t\t%s *= 0.5;", ratio); if (fStitchTiles) { - builder->fsCodeAppendf("\n\t\t\t%s *= vec2(2.0);", stitchData); + fsBuilder->codeAppendf("\n\t\t\t%s *= vec2(2.0);", stitchData); } - builder->fsCodeAppend("\n\t\t}"); // end of the for loop on octaves + fsBuilder->codeAppend("\n\t\t}"); // end of the for loop on octaves if (fType == SkPerlinNoiseShader::kFractalNoise_Type) { // The value of turbulenceFunctionResult comes from ((turbulenceFunctionResult) + 1) / 2 // by fractalNoise and (turbulenceFunctionResult) by turbulence. - builder->fsCodeAppendf("\n\t\t%s = %s * vec4(0.5) + vec4(0.5);", outputColor, outputColor); + fsBuilder->codeAppendf("\n\t\t%s = %s * vec4(0.5) + vec4(0.5);", outputColor, outputColor); } - builder->fsCodeAppendf("\n\t\t%s.a *= %s;", outputColor, alphaUni); + fsBuilder->codeAppendf("\n\t\t%s.a *= %s;", outputColor, alphaUni); // Clamp values - builder->fsCodeAppendf("\n\t\t%s = clamp(%s, 0.0, 1.0);", outputColor, outputColor); + fsBuilder->codeAppendf("\n\t\t%s = clamp(%s, 0.0, 1.0);", outputColor, outputColor); // Pre-multiply the result - builder->fsCodeAppendf("\n\t\t%s = vec4(%s.rgb * %s.aaa, %s.a);\n", + fsBuilder->codeAppendf("\n\t\t%s = vec4(%s.rgb * %s.aaa, %s.a);\n", outputColor, outputColor, outputColor, outputColor); } diff --git a/src/effects/SkTableColorFilter.cpp b/src/effects/SkTableColorFilter.cpp index 54e1efe550..8b391eebf4 100644 --- a/src/effects/SkTableColorFilter.cpp +++ b/src/effects/SkTableColorFilter.cpp @@ -278,7 +278,7 @@ bool SkTable_ColorFilter::asComponentTable(SkBitmap* table) const { #include "GrEffect.h" #include "GrTBackendEffectFactory.h" #include "gl/GrGLEffect.h" -#include "gl/GrGLShaderBuilder.h" +#include "gl/builders/GrGLProgramBuilder.h" #include "SkGr.h" class GLColorTableEffect; @@ -316,7 +316,7 @@ class GLColorTableEffect : public GrGLEffect { public: GLColorTableEffect(const GrBackendEffectFactory&, const GrDrawEffect&); - virtual void emitCode(GrGLShaderBuilder*, + virtual void emitCode(GrGLProgramBuilder*, const GrDrawEffect&, const GrEffectKey&, const char* outputColor, @@ -337,7 +337,7 @@ GLColorTableEffect::GLColorTableEffect(const GrBackendEffectFactory& factory, co : INHERITED(factory) { } -void GLColorTableEffect::emitCode(GrGLShaderBuilder* builder, +void GLColorTableEffect::emitCode(GrGLProgramBuilder* builder, const GrDrawEffect&, const GrEffectKey&, const char* outputColor, @@ -347,38 +347,39 @@ void GLColorTableEffect::emitCode(GrGLShaderBuilder* builder, static const float kColorScaleFactor = 255.0f / 256.0f; static const float kColorOffsetFactor = 1.0f / 512.0f; + GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); if (NULL == inputColor) { // the input color is solid white (all ones). static const float kMaxValue = kColorScaleFactor + kColorOffsetFactor; - builder->fsCodeAppendf("\t\tvec4 coord = vec4(%f, %f, %f, %f);\n", + fsBuilder->codeAppendf("\t\tvec4 coord = vec4(%f, %f, %f, %f);\n", kMaxValue, kMaxValue, kMaxValue, kMaxValue); } else { - builder->fsCodeAppendf("\t\tfloat nonZeroAlpha = max(%s.a, .0001);\n", inputColor); - builder->fsCodeAppendf("\t\tvec4 coord = vec4(%s.rgb / nonZeroAlpha, nonZeroAlpha);\n", inputColor); - builder->fsCodeAppendf("\t\tcoord = coord * %f + vec4(%f, %f, %f, %f);\n", + fsBuilder->codeAppendf("\t\tfloat nonZeroAlpha = max(%s.a, .0001);\n", inputColor); + fsBuilder->codeAppendf("\t\tvec4 coord = vec4(%s.rgb / nonZeroAlpha, nonZeroAlpha);\n", inputColor); + fsBuilder->codeAppendf("\t\tcoord = coord * %f + vec4(%f, %f, %f, %f);\n", kColorScaleFactor, kColorOffsetFactor, kColorOffsetFactor, kColorOffsetFactor, kColorOffsetFactor); } - builder->fsCodeAppendf("\t\t%s.a = ", outputColor); - builder->fsAppendTextureLookup(samplers[0], "vec2(coord.a, 0.125)"); - builder->fsCodeAppend(";\n"); + fsBuilder->codeAppendf("\t\t%s.a = ", outputColor); + fsBuilder->appendTextureLookup(samplers[0], "vec2(coord.a, 0.125)"); + fsBuilder->codeAppend(";\n"); - builder->fsCodeAppendf("\t\t%s.r = ", outputColor); - builder->fsAppendTextureLookup(samplers[0], "vec2(coord.r, 0.375)"); - builder->fsCodeAppend(";\n"); + fsBuilder->codeAppendf("\t\t%s.r = ", outputColor); + fsBuilder->appendTextureLookup(samplers[0], "vec2(coord.r, 0.375)"); + fsBuilder->codeAppend(";\n"); - builder->fsCodeAppendf("\t\t%s.g = ", outputColor); - builder->fsAppendTextureLookup(samplers[0], "vec2(coord.g, 0.625)"); - builder->fsCodeAppend(";\n"); + fsBuilder->codeAppendf("\t\t%s.g = ", outputColor); + fsBuilder->appendTextureLookup(samplers[0], "vec2(coord.g, 0.625)"); + fsBuilder->codeAppend(";\n"); - builder->fsCodeAppendf("\t\t%s.b = ", outputColor); - builder->fsAppendTextureLookup(samplers[0], "vec2(coord.b, 0.875)"); - builder->fsCodeAppend(";\n"); + fsBuilder->codeAppendf("\t\t%s.b = ", outputColor); + fsBuilder->appendTextureLookup(samplers[0], "vec2(coord.b, 0.875)"); + fsBuilder->codeAppend(";\n"); - builder->fsCodeAppendf("\t\t%s.rgb *= %s.a;\n", outputColor, outputColor); + fsBuilder->codeAppendf("\t\t%s.rgb *= %s.a;\n", outputColor, outputColor); } /////////////////////////////////////////////////////////////////////////////// diff --git a/src/effects/gradients/SkGradientShader.cpp b/src/effects/gradients/SkGradientShader.cpp index b14a3f7e4f..4f60cfee66 100644 --- a/src/effects/gradients/SkGradientShader.cpp +++ b/src/effects/gradients/SkGradientShader.cpp @@ -927,7 +927,7 @@ SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END #include "effects/GrTextureStripAtlas.h" #include "GrTBackendEffectFactory.h" -#include "gl/GrGLShaderBuilder.h" +#include "gl/builders/GrGLProgramBuilder.h" #include "SkGr.h" GrGLGradientEffect::GrGLGradientEffect(const GrBackendEffectFactory& factory) @@ -937,24 +937,24 @@ GrGLGradientEffect::GrGLGradientEffect(const GrBackendEffectFactory& factory) GrGLGradientEffect::~GrGLGradientEffect() { } -void GrGLGradientEffect::emitUniforms(GrGLShaderBuilder* builder, uint32_t baseKey) { +void GrGLGradientEffect::emitUniforms(GrGLProgramBuilder* builder, uint32_t baseKey) { if (SkGradientShaderBase::kTwo_GpuColorType == ColorTypeFromKey(baseKey)) { // 2 Color case - fColorStartUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, + fColorStartUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec4f_GrSLType, "GradientStartColor"); - fColorEndUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, + fColorEndUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec4f_GrSLType, "GradientEndColor"); } else if (SkGradientShaderBase::kThree_GpuColorType == ColorTypeFromKey(baseKey)){ // 3 Color Case - fColorStartUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, + fColorStartUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec4f_GrSLType, "GradientStartColor"); - fColorMidUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, + fColorMidUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec4f_GrSLType, "GradientMidColor"); - fColorEndUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, + fColorEndUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec4f_GrSLType, "GradientEndColor"); } else { // if not a fast case - fFSYUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, + fFSYUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kFloat_GrSLType, "GradientYCoordFS"); } } @@ -1037,14 +1037,15 @@ uint32_t GrGLGradientEffect::GenBaseGradientKey(const GrDrawEffect& drawEffect) return key; } -void GrGLGradientEffect::emitColor(GrGLShaderBuilder* builder, +void GrGLGradientEffect::emitColor(GrGLProgramBuilder* builder, const char* gradientTValue, uint32_t baseKey, const char* outputColor, const char* inputColor, const TextureSamplerArray& samplers) { + GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); if (SkGradientShaderBase::kTwo_GpuColorType == ColorTypeFromKey(baseKey)){ - builder->fsCodeAppendf("\tvec4 colorTemp = mix(%s, %s, clamp(%s, 0.0, 1.0));\n", + fsBuilder->codeAppendf("\tvec4 colorTemp = mix(%s, %s, clamp(%s, 0.0, 1.0));\n", builder->getUniformVariable(fColorStartUni).c_str(), builder->getUniformVariable(fColorEndUni).c_str(), gradientTValue); @@ -1054,44 +1055,44 @@ void GrGLGradientEffect::emitColor(GrGLShaderBuilder* builder, // case. Make sure the key reflects this optimization (and note that it can use the same // shader as thekBeforeIterp case). This same optimization applies to the 3 color case below. if (GrGradientEffect::kAfterInterp_PremulType == PremulTypeFromKey(baseKey)) { - builder->fsCodeAppend("\tcolorTemp.rgb *= colorTemp.a;\n"); + fsBuilder->codeAppend("\tcolorTemp.rgb *= colorTemp.a;\n"); } - builder->fsCodeAppendf("\t%s = %s;\n", outputColor, + fsBuilder->codeAppendf("\t%s = %s;\n", outputColor, (GrGLSLExpr4(inputColor) * GrGLSLExpr4("colorTemp")).c_str()); } else if (SkGradientShaderBase::kThree_GpuColorType == ColorTypeFromKey(baseKey)){ - builder->fsCodeAppendf("\tfloat oneMinus2t = 1.0 - (2.0 * (%s));\n", + fsBuilder->codeAppendf("\tfloat oneMinus2t = 1.0 - (2.0 * (%s));\n", gradientTValue); - builder->fsCodeAppendf("\tvec4 colorTemp = clamp(oneMinus2t, 0.0, 1.0) * %s;\n", + fsBuilder->codeAppendf("\tvec4 colorTemp = clamp(oneMinus2t, 0.0, 1.0) * %s;\n", builder->getUniformVariable(fColorStartUni).c_str()); if (kTegra3_GrGLRenderer == builder->ctxInfo().renderer()) { // The Tegra3 compiler will sometimes never return if we have // min(abs(oneMinus2t), 1.0), or do the abs first in a separate expression. - builder->fsCodeAppend("\tfloat minAbs = abs(oneMinus2t);\n"); - builder->fsCodeAppend("\tminAbs = minAbs > 1.0 ? 1.0 : minAbs;\n"); - builder->fsCodeAppendf("\tcolorTemp += (1.0 - minAbs) * %s;\n", + fsBuilder->codeAppend("\tfloat minAbs = abs(oneMinus2t);\n"); + fsBuilder->codeAppend("\tminAbs = minAbs > 1.0 ? 1.0 : minAbs;\n"); + fsBuilder->codeAppendf("\tcolorTemp += (1.0 - minAbs) * %s;\n", builder->getUniformVariable(fColorMidUni).c_str()); } else { - builder->fsCodeAppendf("\tcolorTemp += (1.0 - min(abs(oneMinus2t), 1.0)) * %s;\n", + fsBuilder->codeAppendf("\tcolorTemp += (1.0 - min(abs(oneMinus2t), 1.0)) * %s;\n", builder->getUniformVariable(fColorMidUni).c_str()); } - builder->fsCodeAppendf("\tcolorTemp += clamp(-oneMinus2t, 0.0, 1.0) * %s;\n", + fsBuilder->codeAppendf("\tcolorTemp += clamp(-oneMinus2t, 0.0, 1.0) * %s;\n", builder->getUniformVariable(fColorEndUni).c_str()); if (GrGradientEffect::kAfterInterp_PremulType == PremulTypeFromKey(baseKey)) { - builder->fsCodeAppend("\tcolorTemp.rgb *= colorTemp.a;\n"); + fsBuilder->codeAppend("\tcolorTemp.rgb *= colorTemp.a;\n"); } - builder->fsCodeAppendf("\t%s = %s;\n", outputColor, + fsBuilder->codeAppendf("\t%s = %s;\n", outputColor, (GrGLSLExpr4(inputColor) * GrGLSLExpr4("colorTemp")).c_str()); } else { - builder->fsCodeAppendf("\tvec2 coord = vec2(%s, %s);\n", + fsBuilder->codeAppendf("\tvec2 coord = vec2(%s, %s);\n", gradientTValue, builder->getUniformVariable(fFSYUni).c_str()); - builder->fsCodeAppendf("\t%s = ", outputColor); - builder->fsAppendTextureLookupAndModulate(inputColor, + fsBuilder->codeAppendf("\t%s = ", outputColor); + fsBuilder->appendTextureLookupAndModulate(inputColor, samplers[0], "coord"); - builder->fsCodeAppend(";\n"); + fsBuilder->codeAppend(";\n"); } } diff --git a/src/effects/gradients/SkGradientShaderPriv.h b/src/effects/gradients/SkGradientShaderPriv.h index 7c9d9c319b..8f14bbf6e0 100644 --- a/src/effects/gradients/SkGradientShaderPriv.h +++ b/src/effects/gradients/SkGradientShaderPriv.h @@ -413,13 +413,13 @@ protected: // Emits the uniform used as the y-coord to texture samples in derived classes. Subclasses // should call this method from their emitCode(). - void emitUniforms(GrGLShaderBuilder* builder, uint32_t baseKey); + void emitUniforms(GrGLProgramBuilder* builder, uint32_t baseKey); // emit code that gets a fragment's color from an expression for t; Has branches for 3 separate // control flows inside -- 2 color gradients, 3 color symmetric gradients (both using // native GLSL mix), and 4+ color gradients that use the traditional texture lookup. - void emitColor(GrGLShaderBuilder* builder, + void emitColor(GrGLProgramBuilder* builder, const char* gradientTValue, uint32_t baseKey, const char* outputColor, diff --git a/src/effects/gradients/SkLinearGradient.cpp b/src/effects/gradients/SkLinearGradient.cpp index 9d939bf4a2..551afaab02 100644 --- a/src/effects/gradients/SkLinearGradient.cpp +++ b/src/effects/gradients/SkLinearGradient.cpp @@ -460,7 +460,7 @@ void SkLinearGradient::LinearGradientContext::shadeSpan16(int x, int y, #if SK_SUPPORT_GPU #include "GrTBackendEffectFactory.h" -#include "gl/GrGLShaderBuilder.h" +#include "gl/builders/GrGLProgramBuilder.h" #include "SkGr.h" ///////////////////////////////////////////////////////////////////// @@ -473,7 +473,7 @@ public: virtual ~GrGLLinearGradient() { } - virtual void emitCode(GrGLShaderBuilder*, + virtual void emitCode(GrGLProgramBuilder*, const GrDrawEffect&, const GrEffectKey&, const char* outputColor, @@ -550,7 +550,7 @@ GrEffect* GrLinearGradient::TestCreate(SkRandom* random, ///////////////////////////////////////////////////////////////////// -void GrGLLinearGradient::emitCode(GrGLShaderBuilder* builder, +void GrGLLinearGradient::emitCode(GrGLProgramBuilder* builder, const GrDrawEffect&, const GrEffectKey& key, const char* outputColor, @@ -559,7 +559,7 @@ void GrGLLinearGradient::emitCode(GrGLShaderBuilder* builder, const TextureSamplerArray& samplers) { uint32_t baseKey = key.get32(0); this->emitUniforms(builder, baseKey); - SkString t = builder->ensureFSCoords2D(coords, 0); + SkString t = builder->getFragmentShaderBuilder()->ensureFSCoords2D(coords, 0); t.append(".x"); this->emitColor(builder, t.c_str(), baseKey, outputColor, inputColor, samplers); } diff --git a/src/effects/gradients/SkRadialGradient.cpp b/src/effects/gradients/SkRadialGradient.cpp index fb1d40a7ab..aeae24a0af 100644 --- a/src/effects/gradients/SkRadialGradient.cpp +++ b/src/effects/gradients/SkRadialGradient.cpp @@ -470,7 +470,7 @@ void SkRadialGradient::RadialGradientContext::shadeSpan(int x, int y, #if SK_SUPPORT_GPU #include "GrTBackendEffectFactory.h" -#include "gl/GrGLShaderBuilder.h" +#include "gl/builders/GrGLProgramBuilder.h" #include "SkGr.h" class GrGLRadialGradient : public GrGLGradientEffect { @@ -480,7 +480,7 @@ public: const GrDrawEffect&) : INHERITED (factory) { } virtual ~GrGLRadialGradient() { } - virtual void emitCode(GrGLShaderBuilder*, + virtual void emitCode(GrGLProgramBuilder*, const GrDrawEffect&, const GrEffectKey&, const char* outputColor, @@ -559,7 +559,7 @@ GrEffect* GrRadialGradient::TestCreate(SkRandom* random, ///////////////////////////////////////////////////////////////////// -void GrGLRadialGradient::emitCode(GrGLShaderBuilder* builder, +void GrGLRadialGradient::emitCode(GrGLProgramBuilder* builder, const GrDrawEffect&, const GrEffectKey& key, const char* outputColor, @@ -569,7 +569,7 @@ void GrGLRadialGradient::emitCode(GrGLShaderBuilder* builder, uint32_t baseKey = key.get32(0); this->emitUniforms(builder, baseKey); SkString t("length("); - t.append(builder->ensureFSCoords2D(coords, 0)); + t.append(builder->getFragmentShaderBuilder()->ensureFSCoords2D(coords, 0)); t.append(")"); this->emitColor(builder, t.c_str(), baseKey, outputColor, inputColor, samplers); } diff --git a/src/effects/gradients/SkSweepGradient.cpp b/src/effects/gradients/SkSweepGradient.cpp index 1bb595cb3c..c56cf1494c 100644 --- a/src/effects/gradients/SkSweepGradient.cpp +++ b/src/effects/gradients/SkSweepGradient.cpp @@ -185,7 +185,7 @@ void SkSweepGradient::SweepGradientContext::shadeSpan16(int x, int y, uint16_t* #if SK_SUPPORT_GPU #include "GrTBackendEffectFactory.h" -#include "gl/GrGLShaderBuilder.h" +#include "gl/builders/GrGLProgramBuilder.h" #include "SkGr.h" class GrGLSweepGradient : public GrGLGradientEffect { @@ -195,7 +195,7 @@ public: const GrDrawEffect&) : INHERITED (factory) { } virtual ~GrGLSweepGradient() { } - virtual void emitCode(GrGLShaderBuilder*, + virtual void emitCode(GrGLProgramBuilder*, const GrDrawEffect&, const GrEffectKey&, const char* outputColor, @@ -265,7 +265,7 @@ GrEffect* GrSweepGradient::TestCreate(SkRandom* random, ///////////////////////////////////////////////////////////////////// -void GrGLSweepGradient::emitCode(GrGLShaderBuilder* builder, +void GrGLSweepGradient::emitCode(GrGLProgramBuilder* builder, const GrDrawEffect&, const GrEffectKey& key, const char* outputColor, @@ -274,7 +274,7 @@ void GrGLSweepGradient::emitCode(GrGLShaderBuilder* builder, const TextureSamplerArray& samplers) { uint32_t baseKey = key.get32(0); this->emitUniforms(builder, baseKey); - SkString coords2D = builder->ensureFSCoords2D(coords, 0); + SkString coords2D = builder->getFragmentShaderBuilder()->ensureFSCoords2D(coords, 0); const GrGLContextInfo ctxInfo = builder->ctxInfo(); SkString t; // 0.1591549430918 is 1/(2*pi), used since atan returns values [-pi, pi] diff --git a/src/effects/gradients/SkTwoPointConicalGradient_gpu.cpp b/src/effects/gradients/SkTwoPointConicalGradient_gpu.cpp index 4298207ed7..a3ba479cb7 100644 --- a/src/effects/gradients/SkTwoPointConicalGradient_gpu.cpp +++ b/src/effects/gradients/SkTwoPointConicalGradient_gpu.cpp @@ -12,7 +12,7 @@ #if SK_SUPPORT_GPU #include "GrTBackendEffectFactory.h" -#include "gl/GrGLShaderBuilder.h" +#include "gl/builders/GrGLProgramBuilder.h" // For brevity typedef GrGLProgramDataManager::UniformHandle UniformHandle; @@ -137,7 +137,7 @@ public: GLEdge2PtConicalEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&); virtual ~GLEdge2PtConicalEffect() { } - virtual void emitCode(GrGLShaderBuilder*, + virtual void emitCode(GrGLProgramBuilder*, const GrDrawEffect&, const GrEffectKey&, const char* outputColor, @@ -217,7 +217,7 @@ GLEdge2PtConicalEffect::GLEdge2PtConicalEffect(const GrBackendEffectFactory& fac , fCachedRadius(-SK_ScalarMax) , fCachedDiffRadius(-SK_ScalarMax) {} -void GLEdge2PtConicalEffect::emitCode(GrGLShaderBuilder* builder, +void GLEdge2PtConicalEffect::emitCode(GrGLProgramBuilder* builder, const GrDrawEffect&, const GrEffectKey& key, const char* outputColor, @@ -226,7 +226,7 @@ void GLEdge2PtConicalEffect::emitCode(GrGLShaderBuilder* builder, const TextureSamplerArray& samplers) { uint32_t baseKey = key.get32(0); this->emitUniforms(builder, baseKey); - fParamUni = builder->addUniformArray(GrGLShaderBuilder::kFragment_Visibility, + fParamUni = builder->addUniformArray(GrGLProgramBuilder::kFragment_Visibility, kFloat_GrSLType, "Conical2FSParams", 3); SkString cName("c"); @@ -243,8 +243,9 @@ void GLEdge2PtConicalEffect::emitCode(GrGLShaderBuilder* builder, SkASSERT(coords[0].type() == coords[1].type()); const char* coords2D; SkString bVar; + GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); if (kVec3f_GrSLType == coords[0].type()) { - builder->fsCodeAppendf("\tvec3 interpolants = vec3(%s.xy / %s.z, %s.x / %s.z);\n", + fsBuilder->codeAppendf("\tvec3 interpolants = vec3(%s.xy / %s.z, %s.x / %s.z);\n", coords[0].c_str(), coords[0].c_str(), coords[1].c_str(), coords[1].c_str()); coords2D = "interpolants.xy"; bVar = "interpolants.z"; @@ -255,22 +256,22 @@ void GLEdge2PtConicalEffect::emitCode(GrGLShaderBuilder* builder, // output will default to transparent black (we simply won't write anything // else to it if invalid, instead of discarding or returning prematurely) - builder->fsCodeAppendf("\t%s = vec4(0.0,0.0,0.0,0.0);\n", outputColor); + fsBuilder->codeAppendf("\t%s = vec4(0.0,0.0,0.0,0.0);\n", outputColor); // c = (x^2)+(y^2) - params[1] - builder->fsCodeAppendf("\tfloat %s = dot(%s, %s) - %s;\n", + fsBuilder->codeAppendf("\tfloat %s = dot(%s, %s) - %s;\n", cName.c_str(), coords2D, coords2D, p1.c_str()); // linear case: t = -c/b - builder->fsCodeAppendf("\tfloat %s = -(%s / %s);\n", tName.c_str(), + fsBuilder->codeAppendf("\tfloat %s = -(%s / %s);\n", tName.c_str(), cName.c_str(), bVar.c_str()); // if r(t) > 0, then t will be the x coordinate - builder->fsCodeAppendf("\tif (%s * %s + %s > 0.0) {\n", tName.c_str(), + fsBuilder->codeAppendf("\tif (%s * %s + %s > 0.0) {\n", tName.c_str(), p2.c_str(), p0.c_str()); - builder->fsCodeAppend("\t"); + fsBuilder->codeAppend("\t"); this->emitColor(builder, tName.c_str(), baseKey, outputColor, inputColor, samplers); - builder->fsCodeAppend("\t}\n"); + fsBuilder->codeAppend("\t}\n"); } void GLEdge2PtConicalEffect::setData(const GrGLProgramDataManager& pdman, @@ -413,7 +414,7 @@ public: GLFocalOutside2PtConicalEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&); virtual ~GLFocalOutside2PtConicalEffect() { } - virtual void emitCode(GrGLShaderBuilder*, + virtual void emitCode(GrGLProgramBuilder*, const GrDrawEffect&, const GrEffectKey&, const char* outputColor, @@ -493,7 +494,7 @@ GLFocalOutside2PtConicalEffect::GLFocalOutside2PtConicalEffect(const GrBackendEf fIsFlipped = data.isFlipped(); } -void GLFocalOutside2PtConicalEffect::emitCode(GrGLShaderBuilder* builder, +void GLFocalOutside2PtConicalEffect::emitCode(GrGLProgramBuilder* builder, const GrDrawEffect&, const GrEffectKey& key, const char* outputColor, @@ -502,7 +503,7 @@ void GLFocalOutside2PtConicalEffect::emitCode(GrGLShaderBuilder* builder, const TextureSamplerArray& samplers) { uint32_t baseKey = key.get32(0); this->emitUniforms(builder, baseKey); - fParamUni = builder->addUniformArray(GrGLShaderBuilder::kFragment_Visibility, + fParamUni = builder->addUniformArray(GrGLProgramBuilder::kFragment_Visibility, kFloat_GrSLType, "Conical2FSParams", 2); SkString tName("t"); SkString p0; // focalX @@ -512,33 +513,34 @@ void GLFocalOutside2PtConicalEffect::emitCode(GrGLShaderBuilder* builder, builder->getUniformVariable(fParamUni).appendArrayAccess(1, &p1); // if we have a vec3 from being in perspective, convert it to a vec2 first - SkString coords2DString = builder->ensureFSCoords2D(coords, 0); + GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); + SkString coords2DString = fsBuilder->ensureFSCoords2D(coords, 0); const char* coords2D = coords2DString.c_str(); // t = p.x * focal.x +/- sqrt(p.x^2 + (1 - focal.x^2) * p.y^2) // output will default to transparent black (we simply won't write anything // else to it if invalid, instead of discarding or returning prematurely) - builder->fsCodeAppendf("\t%s = vec4(0.0,0.0,0.0,0.0);\n", outputColor); + fsBuilder->codeAppendf("\t%s = vec4(0.0,0.0,0.0,0.0);\n", outputColor); - builder->fsCodeAppendf("\tfloat xs = %s.x * %s.x;\n", coords2D, coords2D); - builder->fsCodeAppendf("\tfloat ys = %s.y * %s.y;\n", coords2D, coords2D); - builder->fsCodeAppendf("\tfloat d = xs + %s * ys;\n", p1.c_str()); + fsBuilder->codeAppendf("\tfloat xs = %s.x * %s.x;\n", coords2D, coords2D); + fsBuilder->codeAppendf("\tfloat ys = %s.y * %s.y;\n", coords2D, coords2D); + fsBuilder->codeAppendf("\tfloat d = xs + %s * ys;\n", p1.c_str()); // Must check to see if we flipped the circle order (to make sure start radius < end radius) // If so we must also flip sign on sqrt if (!fIsFlipped) { - builder->fsCodeAppendf("\tfloat %s = %s.x * %s + sqrt(d);\n", tName.c_str(), + fsBuilder->codeAppendf("\tfloat %s = %s.x * %s + sqrt(d);\n", tName.c_str(), coords2D, p0.c_str()); } else { - builder->fsCodeAppendf("\tfloat %s = %s.x * %s - sqrt(d);\n", tName.c_str(), + fsBuilder->codeAppendf("\tfloat %s = %s.x * %s - sqrt(d);\n", tName.c_str(), coords2D, p0.c_str()); } - builder->fsCodeAppendf("\tif (%s >= 0.0 && d >= 0.0) {\n", tName.c_str()); - builder->fsCodeAppend("\t\t"); + fsBuilder->codeAppendf("\tif (%s >= 0.0 && d >= 0.0) {\n", tName.c_str()); + fsBuilder->codeAppend("\t\t"); this->emitColor(builder, tName.c_str(), baseKey, outputColor, inputColor, samplers); - builder->fsCodeAppend("\t}\n"); + fsBuilder->codeAppend("\t}\n"); } void GLFocalOutside2PtConicalEffect::setData(const GrGLProgramDataManager& pdman, @@ -618,7 +620,7 @@ public: GLFocalInside2PtConicalEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&); virtual ~GLFocalInside2PtConicalEffect() {} - virtual void emitCode(GrGLShaderBuilder*, + virtual void emitCode(GrGLProgramBuilder*, const GrDrawEffect&, const GrEffectKey&, const char* outputColor, @@ -695,7 +697,7 @@ GLFocalInside2PtConicalEffect::GLFocalInside2PtConicalEffect(const GrBackendEffe , fFSVaryingName(NULL) , fCachedFocal(SK_ScalarMax) {} -void GLFocalInside2PtConicalEffect::emitCode(GrGLShaderBuilder* builder, +void GLFocalInside2PtConicalEffect::emitCode(GrGLProgramBuilder* builder, const GrDrawEffect&, const GrEffectKey& key, const char* outputColor, @@ -704,7 +706,7 @@ void GLFocalInside2PtConicalEffect::emitCode(GrGLShaderBuilder* builder, const TextureSamplerArray& samplers) { uint32_t baseKey = key.get32(0); this->emitUniforms(builder, baseKey); - fFocalUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, + fFocalUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kFloat_GrSLType, "Conical2FSParams"); SkString tName("t"); @@ -713,11 +715,12 @@ void GLFocalInside2PtConicalEffect::emitCode(GrGLShaderBuilder* builder, GrGLShaderVar focal = builder->getUniformVariable(fFocalUni); // if we have a vec3 from being in perspective, convert it to a vec2 first - SkString coords2DString = builder->ensureFSCoords2D(coords, 0); + GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); + SkString coords2DString = fsBuilder->ensureFSCoords2D(coords, 0); const char* coords2D = coords2DString.c_str(); // t = p.x * focalX + length(p) - builder->fsCodeAppendf("\tfloat %s = %s.x * %s + length(%s);\n", tName.c_str(), + fsBuilder->codeAppendf("\tfloat %s = %s.x * %s + length(%s);\n", tName.c_str(), coords2D, focal.c_str(), coords2D); this->emitColor(builder, tName.c_str(), baseKey, outputColor, inputColor, samplers); @@ -859,7 +862,7 @@ public: GLCircleInside2PtConicalEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&); virtual ~GLCircleInside2PtConicalEffect() {} - virtual void emitCode(GrGLShaderBuilder*, + virtual void emitCode(GrGLProgramBuilder*, const GrDrawEffect&, const GrEffectKey&, const char* outputColor, @@ -944,7 +947,7 @@ GLCircleInside2PtConicalEffect::GLCircleInside2PtConicalEffect(const GrBackendEf , fCachedB(SK_ScalarMax) , fCachedC(SK_ScalarMax) {} -void GLCircleInside2PtConicalEffect::emitCode(GrGLShaderBuilder* builder, +void GLCircleInside2PtConicalEffect::emitCode(GrGLProgramBuilder* builder, const GrDrawEffect&, const GrEffectKey& key, const char* outputColor, @@ -953,9 +956,9 @@ void GLCircleInside2PtConicalEffect::emitCode(GrGLShaderBuilder* builder, const TextureSamplerArray& samplers) { uint32_t baseKey = key.get32(0); this->emitUniforms(builder, baseKey); - fCenterUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, + fCenterUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec2f_GrSLType, "Conical2FSCenter"); - fParamUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, + fParamUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec3f_GrSLType, "Conical2FSParams"); SkString tName("t"); @@ -966,7 +969,8 @@ void GLCircleInside2PtConicalEffect::emitCode(GrGLShaderBuilder* builder, GrGLShaderVar params = builder->getUniformVariable(fParamUni); // if we have a vec3 from being in perspective, convert it to a vec2 first - SkString coords2DString = builder->ensureFSCoords2D(coords, 0); + GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); + SkString coords2DString = fsBuilder->ensureFSCoords2D(coords, 0); const char* coords2D = coords2DString.c_str(); // p = coords2D @@ -977,9 +981,9 @@ void GLCircleInside2PtConicalEffect::emitCode(GrGLShaderBuilder* builder, // C = 1 / A // d = dot(e, p) + B // t = d +/- sqrt(d^2 - A * dot(p, p) + C) - builder->fsCodeAppendf("\tfloat pDotp = dot(%s, %s);\n", coords2D, coords2D); - builder->fsCodeAppendf("\tfloat d = dot(%s, %s) + %s.y;\n", coords2D, center.c_str(), params.c_str()); - builder->fsCodeAppendf("\tfloat %s = d + sqrt(d * d - %s.x * pDotp + %s.z);\n", + fsBuilder->codeAppendf("\tfloat pDotp = dot(%s, %s);\n", coords2D, coords2D); + fsBuilder->codeAppendf("\tfloat d = dot(%s, %s) + %s.y;\n", coords2D, center.c_str(), params.c_str()); + fsBuilder->codeAppendf("\tfloat %s = d + sqrt(d * d - %s.x * pDotp + %s.z);\n", tName.c_str(), params.c_str(), params.c_str()); this->emitColor(builder, tName.c_str(), baseKey, outputColor, inputColor, samplers); @@ -1085,7 +1089,7 @@ public: GLCircleOutside2PtConicalEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&); virtual ~GLCircleOutside2PtConicalEffect() {} - virtual void emitCode(GrGLShaderBuilder*, + virtual void emitCode(GrGLProgramBuilder*, const GrDrawEffect&, const GrEffectKey&, const char* outputColor, @@ -1178,7 +1182,7 @@ GLCircleOutside2PtConicalEffect::GLCircleOutside2PtConicalEffect(const GrBackend fIsFlipped = data.isFlipped(); } -void GLCircleOutside2PtConicalEffect::emitCode(GrGLShaderBuilder* builder, +void GLCircleOutside2PtConicalEffect::emitCode(GrGLProgramBuilder* builder, const GrDrawEffect&, const GrEffectKey& key, const char* outputColor, @@ -1187,9 +1191,9 @@ void GLCircleOutside2PtConicalEffect::emitCode(GrGLShaderBuilder* builder, const TextureSamplerArray& samplers) { uint32_t baseKey = key.get32(0); this->emitUniforms(builder, baseKey); - fCenterUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, + fCenterUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec2f_GrSLType, "Conical2FSCenter"); - fParamUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, + fParamUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec4f_GrSLType, "Conical2FSParams"); SkString tName("t"); @@ -1200,12 +1204,13 @@ void GLCircleOutside2PtConicalEffect::emitCode(GrGLShaderBuilder* builder, GrGLShaderVar params = builder->getUniformVariable(fParamUni); // if we have a vec3 from being in perspective, convert it to a vec2 first - SkString coords2DString = builder->ensureFSCoords2D(coords, 0); + GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); + SkString coords2DString = fsBuilder->ensureFSCoords2D(coords, 0); const char* coords2D = coords2DString.c_str(); // output will default to transparent black (we simply won't write anything // else to it if invalid, instead of discarding or returning prematurely) - builder->fsCodeAppendf("\t%s = vec4(0.0,0.0,0.0,0.0);\n", outputColor); + fsBuilder->codeAppendf("\t%s = vec4(0.0,0.0,0.0,0.0);\n", outputColor); // p = coords2D // e = center end @@ -1216,22 +1221,22 @@ void GLCircleOutside2PtConicalEffect::emitCode(GrGLShaderBuilder* builder, // d = dot(e, p) + B // t = d +/- sqrt(d^2 - A * dot(p, p) + C) - builder->fsCodeAppendf("\tfloat pDotp = dot(%s, %s);\n", coords2D, coords2D); - builder->fsCodeAppendf("\tfloat d = dot(%s, %s) + %s.y;\n", coords2D, center.c_str(), params.c_str()); - builder->fsCodeAppendf("\tfloat deter = d * d - %s.x * pDotp + %s.z;\n", params.c_str(), params.c_str()); + fsBuilder->codeAppendf("\tfloat pDotp = dot(%s, %s);\n", coords2D, coords2D); + fsBuilder->codeAppendf("\tfloat d = dot(%s, %s) + %s.y;\n", coords2D, center.c_str(), params.c_str()); + fsBuilder->codeAppendf("\tfloat deter = d * d - %s.x * pDotp + %s.z;\n", params.c_str(), params.c_str()); // Must check to see if we flipped the circle order (to make sure start radius < end radius) // If so we must also flip sign on sqrt if (!fIsFlipped) { - builder->fsCodeAppendf("\tfloat %s = d + sqrt(deter);\n", tName.c_str()); + fsBuilder->codeAppendf("\tfloat %s = d + sqrt(deter);\n", tName.c_str()); } else { - builder->fsCodeAppendf("\tfloat %s = d - sqrt(deter);\n", tName.c_str()); + fsBuilder->codeAppendf("\tfloat %s = d - sqrt(deter);\n", tName.c_str()); } - builder->fsCodeAppendf("\tif (%s >= %s.w && deter >= 0.0) {\n", tName.c_str(), params.c_str()); - builder->fsCodeAppend("\t\t"); + fsBuilder->codeAppendf("\tif (%s >= %s.w && deter >= 0.0) {\n", tName.c_str(), params.c_str()); + fsBuilder->codeAppend("\t\t"); this->emitColor(builder, tName.c_str(), baseKey, outputColor, inputColor, samplers); - builder->fsCodeAppend("\t}\n"); + fsBuilder->codeAppend("\t}\n"); } void GLCircleOutside2PtConicalEffect::setData(const GrGLProgramDataManager& pdman, diff --git a/src/effects/gradients/SkTwoPointRadialGradient.cpp b/src/effects/gradients/SkTwoPointRadialGradient.cpp index 754a53261b..bb5ec04bfd 100644 --- a/src/effects/gradients/SkTwoPointRadialGradient.cpp +++ b/src/effects/gradients/SkTwoPointRadialGradient.cpp @@ -398,7 +398,7 @@ void SkTwoPointRadialGradient::init() { #if SK_SUPPORT_GPU #include "GrTBackendEffectFactory.h" -#include "gl/GrGLShaderBuilder.h" +#include "gl/builders/GrGLProgramBuilder.h" #include "SkGr.h" // For brevity @@ -411,7 +411,7 @@ public: GrGLRadial2Gradient(const GrBackendEffectFactory& factory, const GrDrawEffect&); virtual ~GrGLRadial2Gradient() { } - virtual void emitCode(GrGLShaderBuilder*, + virtual void emitCode(GrGLProgramBuilder*, const GrDrawEffect&, const GrEffectKey&, const char* outputColor, @@ -567,7 +567,7 @@ GrGLRadial2Gradient::GrGLRadial2Gradient(const GrBackendEffectFactory& factory, fIsDegenerate = data.isDegenerate(); } -void GrGLRadial2Gradient::emitCode(GrGLShaderBuilder* builder, +void GrGLRadial2Gradient::emitCode(GrGLProgramBuilder* builder, const GrDrawEffect& drawEffect, const GrEffectKey& key, const char* outputColor, @@ -576,7 +576,7 @@ void GrGLRadial2Gradient::emitCode(GrGLShaderBuilder* builder, const TextureSamplerArray& samplers) { uint32_t baseKey = key.get32(0); this->emitUniforms(builder, baseKey); - fParamUni = builder->addUniformArray(GrGLShaderBuilder::kFragment_Visibility, + fParamUni = builder->addUniformArray(GrGLProgramBuilder::kFragment_Visibility, kFloat_GrSLType, "Radial2FSParams", 6); SkString cName("c"); @@ -596,12 +596,13 @@ void GrGLRadial2Gradient::emitCode(GrGLShaderBuilder* builder, builder->getUniformVariable(fParamUni).appendArrayAccess(4, &p4); builder->getUniformVariable(fParamUni).appendArrayAccess(5, &p5); + GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); // We interpolate the linear component in coords[1]. SkASSERT(coords[0].type() == coords[1].type()); const char* coords2D; SkString bVar; if (kVec3f_GrSLType == coords[0].type()) { - builder->fsCodeAppendf("\tvec3 interpolants = vec3(%s.xy, %s.x) / %s.z;\n", + fsBuilder->codeAppendf("\tvec3 interpolants = vec3(%s.xy, %s.x) / %s.z;\n", coords[0].c_str(), coords[1].c_str(), coords[0].c_str()); coords2D = "interpolants.xy"; bVar = "interpolants.z"; @@ -611,7 +612,7 @@ void GrGLRadial2Gradient::emitCode(GrGLShaderBuilder* builder, } // c = (x^2)+(y^2) - params[4] - builder->fsCodeAppendf("\tfloat %s = dot(%s, %s) - %s;\n", + fsBuilder->codeAppendf("\tfloat %s = dot(%s, %s) - %s;\n", cName.c_str(), coords2D, coords2D, p4.c_str()); // If we aren't degenerate, emit some extra code, and accept a slightly @@ -619,13 +620,13 @@ void GrGLRadial2Gradient::emitCode(GrGLShaderBuilder* builder, if (!fIsDegenerate) { // ac4 = 4.0 * params[0] * c - builder->fsCodeAppendf("\tfloat %s = %s * 4.0 * %s;\n", + fsBuilder->codeAppendf("\tfloat %s = %s * 4.0 * %s;\n", ac4Name.c_str(), p0.c_str(), cName.c_str()); // root = sqrt(b^2-4ac) // (abs to avoid exception due to fp precision) - builder->fsCodeAppendf("\tfloat %s = sqrt(abs(%s*%s - %s));\n", + fsBuilder->codeAppendf("\tfloat %s = sqrt(abs(%s*%s - %s));\n", rootName.c_str(), bVar.c_str(), bVar.c_str(), ac4Name.c_str()); diff --git a/src/gpu/GrAAConvexPathRenderer.cpp b/src/gpu/GrAAConvexPathRenderer.cpp index b2c32acd95..b29c7c80a3 100644 --- a/src/gpu/GrAAConvexPathRenderer.cpp +++ b/src/gpu/GrAAConvexPathRenderer.cpp @@ -6,6 +6,7 @@ * found in the LICENSE file. */ +#include "gl/builders/GrGLProgramBuilder.h" #include "GrAAConvexPathRenderer.h" #include "GrContext.h" @@ -19,7 +20,6 @@ #include "SkTraceEvent.h" #include "gl/GrGLEffect.h" -#include "gl/GrGLShaderBuilder.h" #include "gl/GrGLSL.h" #include "gl/GrGLVertexEffect.h" @@ -531,7 +531,7 @@ public: GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&) : INHERITED (factory) {} - virtual void emitCode(GrGLFullShaderBuilder* builder, + virtual void emitCode(GrGLFullProgramBuilder* builder, const GrDrawEffect& drawEffect, const GrEffectKey& key, const char* outputColor, @@ -539,35 +539,38 @@ public: const TransformedCoordsArray&, const TextureSamplerArray& samplers) SK_OVERRIDE { const char *vsName, *fsName; - const SkString* attrName = - builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); - builder->fsCodeAppendf("\t\tfloat edgeAlpha;\n"); - - SkAssertResult(builder->enableFeature( - GrGLShaderBuilder::kStandardDerivatives_GLSLFeature)); builder->addVarying(kVec4f_GrSLType, "QuadEdge", &vsName, &fsName); + GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); + + SkAssertResult(fsBuilder->enableFeature( + GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature)); + fsBuilder->codeAppendf("\t\tfloat edgeAlpha;\n"); + // keep the derivative instructions outside the conditional - builder->fsCodeAppendf("\t\tvec2 duvdx = dFdx(%s.xy);\n", fsName); - builder->fsCodeAppendf("\t\tvec2 duvdy = dFdy(%s.xy);\n", fsName); - builder->fsCodeAppendf("\t\tif (%s.z > 0.0 && %s.w > 0.0) {\n", fsName, fsName); + fsBuilder->codeAppendf("\t\tvec2 duvdx = dFdx(%s.xy);\n", fsName); + fsBuilder->codeAppendf("\t\tvec2 duvdy = dFdy(%s.xy);\n", fsName); + fsBuilder->codeAppendf("\t\tif (%s.z > 0.0 && %s.w > 0.0) {\n", fsName, fsName); // today we know z and w are in device space. We could use derivatives - builder->fsCodeAppendf("\t\t\tedgeAlpha = min(min(%s.z, %s.w) + 0.5, 1.0);\n", fsName, + fsBuilder->codeAppendf("\t\t\tedgeAlpha = min(min(%s.z, %s.w) + 0.5, 1.0);\n", fsName, fsName); - builder->fsCodeAppendf ("\t\t} else {\n"); - builder->fsCodeAppendf("\t\t\tvec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx.y,\n" + fsBuilder->codeAppendf ("\t\t} else {\n"); + fsBuilder->codeAppendf("\t\t\tvec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx.y,\n" "\t\t\t 2.0*%s.x*duvdy.x - duvdy.y);\n", fsName, fsName); - builder->fsCodeAppendf("\t\t\tedgeAlpha = (%s.x*%s.x - %s.y);\n", fsName, fsName, + fsBuilder->codeAppendf("\t\t\tedgeAlpha = (%s.x*%s.x - %s.y);\n", fsName, fsName, fsName); - builder->fsCodeAppendf("\t\t\tedgeAlpha = " + fsBuilder->codeAppendf("\t\t\tedgeAlpha = " "clamp(0.5 - edgeAlpha / length(gF), 0.0, 1.0);\n\t\t}\n"); - builder->fsCodeAppendf("\t%s = %s;\n", outputColor, + fsBuilder->codeAppendf("\t%s = %s;\n", outputColor, (GrGLSLExpr4(inputColor) * GrGLSLExpr1("edgeAlpha")).c_str()); - builder->vsCodeAppendf("\t%s = %s;\n", vsName, attrName->c_str()); + GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder(); + const SkString* attr0Name = + vsBuilder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); + vsBuilder->codeAppendf("\t%s = %s;\n", vsName, attr0Name->c_str()); } static inline void GenKey(const GrDrawEffect&, const GrGLCaps&, GrEffectKeyBuilder*) {} @@ -589,7 +592,7 @@ private: GR_DECLARE_EFFECT_TEST; - typedef GrVertexEffect INHERITED; + typedef GrEffect INHERITED; }; GR_DEFINE_EFFECT_TEST(QuadEdgeEffect); diff --git a/src/gpu/GrAARectRenderer.cpp b/src/gpu/GrAARectRenderer.cpp index 1d350c335b..b4790bb99d 100644 --- a/src/gpu/GrAARectRenderer.cpp +++ b/src/gpu/GrAARectRenderer.cpp @@ -5,10 +5,10 @@ * found in the LICENSE file. */ +#include "gl/builders/GrGLProgramBuilder.h" #include "GrAARectRenderer.h" #include "GrGpu.h" #include "gl/GrGLEffect.h" -#include "gl/GrGLShaderBuilder.h" #include "gl/GrGLVertexEffect.h" #include "GrTBackendEffectFactory.h" #include "SkColorPriv.h" @@ -44,7 +44,7 @@ public: GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&) : INHERITED (factory) {} - virtual void emitCode(GrGLFullShaderBuilder* builder, + virtual void emitCode(GrGLFullProgramBuilder* builder, const GrDrawEffect& drawEffect, const GrEffectKey& key, const char* outputColor, @@ -56,35 +56,38 @@ public: // zw -> w/2+0.5, h/2+0.5 const char *vsRectName, *fsRectName; builder->addVarying(kVec4f_GrSLType, "Rect", &vsRectName, &fsRectName); + + GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder(); const SkString* attr0Name = - builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); - builder->vsCodeAppendf("\t%s = %s;\n", vsRectName, attr0Name->c_str()); + vsBuilder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); + vsBuilder->codeAppendf("\t%s = %s;\n", vsRectName, attr0Name->c_str()); + GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); // TODO: compute all these offsets, spans, and scales in the VS - builder->fsCodeAppendf("\tfloat insetW = min(1.0, %s.z) - 0.5;\n", fsRectName); - builder->fsCodeAppendf("\tfloat insetH = min(1.0, %s.w) - 0.5;\n", fsRectName); - builder->fsCodeAppend("\tfloat outset = 0.5;\n"); + fsBuilder->codeAppendf("\tfloat insetW = min(1.0, %s.z) - 0.5;\n", fsRectName); + fsBuilder->codeAppendf("\tfloat insetH = min(1.0, %s.w) - 0.5;\n", fsRectName); + fsBuilder->codeAppend("\tfloat outset = 0.5;\n"); // For rects > 1 pixel wide and tall the span's are noops (i.e., 1.0). For rects // < 1 pixel wide or tall they serve to normalize the < 1 ramp to a 0 .. 1 range. - builder->fsCodeAppend("\tfloat spanW = insetW + outset;\n"); - builder->fsCodeAppend("\tfloat spanH = insetH + outset;\n"); + fsBuilder->codeAppend("\tfloat spanW = insetW + outset;\n"); + fsBuilder->codeAppend("\tfloat spanH = insetH + outset;\n"); // For rects < 1 pixel wide or tall, these scale factors are used to cap the maximum // value of coverage that is used. In other words it is the coverage that is // used in the interior of the rect after the ramp. - builder->fsCodeAppend("\tfloat scaleW = min(1.0, 2.0*insetW/spanW);\n"); - builder->fsCodeAppend("\tfloat scaleH = min(1.0, 2.0*insetH/spanH);\n"); + fsBuilder->codeAppend("\tfloat scaleW = min(1.0, 2.0*insetW/spanW);\n"); + fsBuilder->codeAppend("\tfloat scaleH = min(1.0, 2.0*insetH/spanH);\n"); // Compute the coverage for the rect's width - builder->fsCodeAppendf( + fsBuilder->codeAppendf( "\tfloat coverage = scaleW*clamp((%s.z-abs(%s.x))/spanW, 0.0, 1.0);\n", fsRectName, fsRectName); // Compute the coverage for the rect's height and merge with the width - builder->fsCodeAppendf( + fsBuilder->codeAppendf( "\tcoverage = coverage*scaleH*clamp((%s.w-abs(%s.y))/spanH, 0.0, 1.0);\n", fsRectName, fsRectName); - builder->fsCodeAppendf("\t%s = %s;\n", outputColor, + fsBuilder->codeAppendf("\t%s = %s;\n", outputColor, (GrGLSLExpr4(inputColor) * GrGLSLExpr1("coverage")).c_str()); } @@ -160,7 +163,7 @@ public: GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&) : INHERITED (factory) {} - virtual void emitCode(GrGLFullShaderBuilder* builder, + virtual void emitCode(GrGLFullProgramBuilder* builder, const GrDrawEffect& drawEffect, const GrEffectKey& key, const char* outputColor, @@ -172,50 +175,53 @@ public: const char *vsRectEdgeName, *fsRectEdgeName; builder->addVarying(kVec4f_GrSLType, "RectEdge", &vsRectEdgeName, &fsRectEdgeName); + + GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder(); const SkString* attr0Name = - builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); - builder->vsCodeAppendf("\t%s = %s;\n", vsRectEdgeName, attr0Name->c_str()); + vsBuilder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); + vsBuilder->codeAppendf("\t%s = %s;\n", vsRectEdgeName, attr0Name->c_str()); // setup the varying for width/2+.5 and height/2+.5 const char *vsWidthHeightName, *fsWidthHeightName; builder->addVarying(kVec2f_GrSLType, "WidthHeight", &vsWidthHeightName, &fsWidthHeightName); const SkString* attr1Name = - builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[1]); - builder->vsCodeAppendf("\t%s = %s;\n", vsWidthHeightName, attr1Name->c_str()); + vsBuilder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[1]); + vsBuilder->codeAppendf("\t%s = %s;\n", vsWidthHeightName, attr1Name->c_str()); + GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); // TODO: compute all these offsets, spans, and scales in the VS - builder->fsCodeAppendf("\tfloat insetW = min(1.0, %s.x) - 0.5;\n", fsWidthHeightName); - builder->fsCodeAppendf("\tfloat insetH = min(1.0, %s.y) - 0.5;\n", fsWidthHeightName); - builder->fsCodeAppend("\tfloat outset = 0.5;\n"); + fsBuilder->codeAppendf("\tfloat insetW = min(1.0, %s.x) - 0.5;\n", fsWidthHeightName); + fsBuilder->codeAppendf("\tfloat insetH = min(1.0, %s.y) - 0.5;\n", fsWidthHeightName); + fsBuilder->codeAppend("\tfloat outset = 0.5;\n"); // For rects > 1 pixel wide and tall the span's are noops (i.e., 1.0). For rects // < 1 pixel wide or tall they serve to normalize the < 1 ramp to a 0 .. 1 range. - builder->fsCodeAppend("\tfloat spanW = insetW + outset;\n"); - builder->fsCodeAppend("\tfloat spanH = insetH + outset;\n"); + fsBuilder->codeAppend("\tfloat spanW = insetW + outset;\n"); + fsBuilder->codeAppend("\tfloat spanH = insetH + outset;\n"); // For rects < 1 pixel wide or tall, these scale factors are used to cap the maximum // value of coverage that is used. In other words it is the coverage that is // used in the interior of the rect after the ramp. - builder->fsCodeAppend("\tfloat scaleW = min(1.0, 2.0*insetW/spanW);\n"); - builder->fsCodeAppend("\tfloat scaleH = min(1.0, 2.0*insetH/spanH);\n"); + fsBuilder->codeAppend("\tfloat scaleW = min(1.0, 2.0*insetW/spanW);\n"); + fsBuilder->codeAppend("\tfloat scaleH = min(1.0, 2.0*insetH/spanH);\n"); // Compute the coverage for the rect's width - builder->fsCodeAppendf("\tvec2 offset = %s.xy - %s.xy;\n", - builder->fragmentPosition(), fsRectEdgeName); - builder->fsCodeAppendf("\tfloat perpDot = abs(offset.x * %s.w - offset.y * %s.z);\n", + fsBuilder->codeAppendf("\tvec2 offset = %s.xy - %s.xy;\n", + fsBuilder->fragmentPosition(), fsRectEdgeName); + fsBuilder->codeAppendf("\tfloat perpDot = abs(offset.x * %s.w - offset.y * %s.z);\n", fsRectEdgeName, fsRectEdgeName); - builder->fsCodeAppendf( + fsBuilder->codeAppendf( "\tfloat coverage = scaleW*clamp((%s.x-perpDot)/spanW, 0.0, 1.0);\n", fsWidthHeightName); // Compute the coverage for the rect's height and merge with the width - builder->fsCodeAppendf("\tperpDot = abs(dot(offset, %s.zw));\n", + fsBuilder->codeAppendf("\tperpDot = abs(dot(offset, %s.zw));\n", fsRectEdgeName); - builder->fsCodeAppendf( + fsBuilder->codeAppendf( "\tcoverage = coverage*scaleH*clamp((%s.y-perpDot)/spanH, 0.0, 1.0);\n", fsWidthHeightName); - builder->fsCodeAppendf("\t%s = %s;\n", outputColor, + fsBuilder->codeAppendf("\t%s = %s;\n", outputColor, (GrGLSLExpr4(inputColor) * GrGLSLExpr1("coverage")).c_str()); } diff --git a/src/gpu/GrOvalRenderer.cpp b/src/gpu/GrOvalRenderer.cpp index 395c90be05..dcce889559 100644 --- a/src/gpu/GrOvalRenderer.cpp +++ b/src/gpu/GrOvalRenderer.cpp @@ -5,12 +5,12 @@ * found in the LICENSE file. */ +#include "gl/builders/GrGLProgramBuilder.h" #include "GrOvalRenderer.h" #include "GrEffect.h" #include "gl/GrGLEffect.h" #include "gl/GrGLSL.h" -#include "gl/GrGLShaderBuilder.h" #include "gl/GrGLVertexEffect.h" #include "GrTBackendEffectFactory.h" @@ -95,7 +95,7 @@ public: GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&) : INHERITED (factory) {} - virtual void emitCode(GrGLFullShaderBuilder* builder, + virtual void emitCode(GrGLFullProgramBuilder* builder, const GrDrawEffect& drawEffect, const GrEffectKey& key, const char* outputColor, @@ -106,18 +106,20 @@ public: const char *vsName, *fsName; builder->addVarying(kVec4f_GrSLType, "CircleEdge", &vsName, &fsName); - const SkString* attrName = - builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); - builder->vsCodeAppendf("\t%s = %s;\n", vsName, attrName->c_str()); + GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder(); + const SkString* attr0Name = + vsBuilder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); + vsBuilder->codeAppendf("\t%s = %s;\n", vsName, attr0Name->c_str()); - builder->fsCodeAppendf("\tfloat d = length(%s.xy);\n", fsName); - builder->fsCodeAppendf("\tfloat edgeAlpha = clamp(%s.z - d, 0.0, 1.0);\n", fsName); + GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); + fsBuilder->codeAppendf("\tfloat d = length(%s.xy);\n", fsName); + fsBuilder->codeAppendf("\tfloat edgeAlpha = clamp(%s.z - d, 0.0, 1.0);\n", fsName); if (circleEffect.isStroked()) { - builder->fsCodeAppendf("\tfloat innerAlpha = clamp(d - %s.w, 0.0, 1.0);\n", fsName); - builder->fsCodeAppend("\tedgeAlpha *= innerAlpha;\n"); + fsBuilder->codeAppendf("\tfloat innerAlpha = clamp(d - %s.w, 0.0, 1.0);\n", fsName); + fsBuilder->codeAppend("\tedgeAlpha *= innerAlpha;\n"); } - builder->fsCodeAppendf("\t%s = %s;\n", outputColor, + fsBuilder->codeAppendf("\t%s = %s;\n", outputColor, (GrGLSLExpr4(inputColor) * GrGLSLExpr1("edgeAlpha")).c_str()); } @@ -206,7 +208,7 @@ public: GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&) : INHERITED (factory) {} - virtual void emitCode(GrGLFullShaderBuilder* builder, + virtual void emitCode(GrGLFullProgramBuilder* builder, const GrDrawEffect& drawEffect, const GrEffectKey& key, const char* outputColor, @@ -219,35 +221,38 @@ public: const char *vsRadiiName, *fsRadiiName; builder->addVarying(kVec2f_GrSLType, "EllipseOffsets", &vsOffsetName, &fsOffsetName); + + GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder(); const SkString* attr0Name = - builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); - builder->vsCodeAppendf("\t%s = %s;\n", vsOffsetName, attr0Name->c_str()); + vsBuilder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); + vsBuilder->codeAppendf("\t%s = %s;\n", vsOffsetName, attr0Name->c_str()); builder->addVarying(kVec4f_GrSLType, "EllipseRadii", &vsRadiiName, &fsRadiiName); const SkString* attr1Name = - builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[1]); - builder->vsCodeAppendf("\t%s = %s;\n", vsRadiiName, attr1Name->c_str()); + vsBuilder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[1]); + vsBuilder->codeAppendf("\t%s = %s;\n", vsRadiiName, attr1Name->c_str()); // for outer curve - builder->fsCodeAppendf("\tvec2 scaledOffset = %s*%s.xy;\n", fsOffsetName, fsRadiiName); - builder->fsCodeAppend("\tfloat test = dot(scaledOffset, scaledOffset) - 1.0;\n"); - builder->fsCodeAppendf("\tvec2 grad = 2.0*scaledOffset*%s.xy;\n", fsRadiiName); - builder->fsCodeAppend("\tfloat grad_dot = dot(grad, grad);\n"); + GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); + fsBuilder->codeAppendf("\tvec2 scaledOffset = %s*%s.xy;\n", fsOffsetName, fsRadiiName); + fsBuilder->codeAppend("\tfloat test = dot(scaledOffset, scaledOffset) - 1.0;\n"); + fsBuilder->codeAppendf("\tvec2 grad = 2.0*scaledOffset*%s.xy;\n", fsRadiiName); + fsBuilder->codeAppend("\tfloat grad_dot = dot(grad, grad);\n"); // avoid calling inversesqrt on zero. - builder->fsCodeAppend("\tgrad_dot = max(grad_dot, 1.0e-4);\n"); - builder->fsCodeAppend("\tfloat invlen = inversesqrt(grad_dot);\n"); - builder->fsCodeAppend("\tfloat edgeAlpha = clamp(0.5-test*invlen, 0.0, 1.0);\n"); + fsBuilder->codeAppend("\tgrad_dot = max(grad_dot, 1.0e-4);\n"); + fsBuilder->codeAppend("\tfloat invlen = inversesqrt(grad_dot);\n"); + fsBuilder->codeAppend("\tfloat edgeAlpha = clamp(0.5-test*invlen, 0.0, 1.0);\n"); // for inner curve if (ellipseEffect.isStroked()) { - builder->fsCodeAppendf("\tscaledOffset = %s*%s.zw;\n", fsOffsetName, fsRadiiName); - builder->fsCodeAppend("\ttest = dot(scaledOffset, scaledOffset) - 1.0;\n"); - builder->fsCodeAppendf("\tgrad = 2.0*scaledOffset*%s.zw;\n", fsRadiiName); - builder->fsCodeAppend("\tinvlen = inversesqrt(dot(grad, grad));\n"); - builder->fsCodeAppend("\tedgeAlpha *= clamp(0.5+test*invlen, 0.0, 1.0);\n"); + fsBuilder->codeAppendf("\tscaledOffset = %s*%s.zw;\n", fsOffsetName, fsRadiiName); + fsBuilder->codeAppend("\ttest = dot(scaledOffset, scaledOffset) - 1.0;\n"); + fsBuilder->codeAppendf("\tgrad = 2.0*scaledOffset*%s.zw;\n", fsRadiiName); + fsBuilder->codeAppend("\tinvlen = inversesqrt(dot(grad, grad));\n"); + fsBuilder->codeAppend("\tedgeAlpha *= clamp(0.5+test*invlen, 0.0, 1.0);\n"); } - builder->fsCodeAppendf("\t%s = %s;\n", outputColor, + fsBuilder->codeAppendf("\t%s = %s;\n", outputColor, (GrGLSLExpr4(inputColor) * GrGLSLExpr1("edgeAlpha")).c_str()); } @@ -344,7 +349,7 @@ public: GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&) : INHERITED (factory) {} - virtual void emitCode(GrGLFullShaderBuilder* builder, + virtual void emitCode(GrGLFullProgramBuilder* builder, const GrDrawEffect& drawEffect, const GrEffectKey& key, const char* outputColor, @@ -353,57 +358,59 @@ public: const TextureSamplerArray& samplers) SK_OVERRIDE { const DIEllipseEdgeEffect& ellipseEffect = drawEffect.castEffect(); - SkAssertResult(builder->enableFeature( - GrGLShaderBuilder::kStandardDerivatives_GLSLFeature)); - const char *vsOffsetName0, *fsOffsetName0; builder->addVarying(kVec2f_GrSLType, "EllipseOffsets0", &vsOffsetName0, &fsOffsetName0); + + GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder(); const SkString* attr0Name = - builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); - builder->vsCodeAppendf("\t%s = %s;\n", vsOffsetName0, attr0Name->c_str()); + vsBuilder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); + vsBuilder->codeAppendf("\t%s = %s;\n", vsOffsetName0, attr0Name->c_str()); const char *vsOffsetName1, *fsOffsetName1; builder->addVarying(kVec2f_GrSLType, "EllipseOffsets1", &vsOffsetName1, &fsOffsetName1); const SkString* attr1Name = - builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[1]); - builder->vsCodeAppendf("\t%s = %s;\n", vsOffsetName1, attr1Name->c_str()); + vsBuilder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[1]); + vsBuilder->codeAppendf("\t%s = %s;\n", vsOffsetName1, attr1Name->c_str()); + GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); + SkAssertResult(fsBuilder->enableFeature( + GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature)); // for outer curve - builder->fsCodeAppendf("\tvec2 scaledOffset = %s.xy;\n", fsOffsetName0); - builder->fsCodeAppend("\tfloat test = dot(scaledOffset, scaledOffset) - 1.0;\n"); - builder->fsCodeAppendf("\tvec2 duvdx = dFdx(%s);\n", fsOffsetName0); - builder->fsCodeAppendf("\tvec2 duvdy = dFdy(%s);\n", fsOffsetName0); - builder->fsCodeAppendf("\tvec2 grad = vec2(2.0*%s.x*duvdx.x + 2.0*%s.y*duvdx.y,\n" + fsBuilder->codeAppendf("\tvec2 scaledOffset = %s.xy;\n", fsOffsetName0); + fsBuilder->codeAppend("\tfloat test = dot(scaledOffset, scaledOffset) - 1.0;\n"); + fsBuilder->codeAppendf("\tvec2 duvdx = dFdx(%s);\n", fsOffsetName0); + fsBuilder->codeAppendf("\tvec2 duvdy = dFdy(%s);\n", fsOffsetName0); + fsBuilder->codeAppendf("\tvec2 grad = vec2(2.0*%s.x*duvdx.x + 2.0*%s.y*duvdx.y,\n" "\t 2.0*%s.x*duvdy.x + 2.0*%s.y*duvdy.y);\n", fsOffsetName0, fsOffsetName0, fsOffsetName0, fsOffsetName0); - builder->fsCodeAppend("\tfloat grad_dot = dot(grad, grad);\n"); + fsBuilder->codeAppend("\tfloat grad_dot = dot(grad, grad);\n"); // avoid calling inversesqrt on zero. - builder->fsCodeAppend("\tgrad_dot = max(grad_dot, 1.0e-4);\n"); - builder->fsCodeAppend("\tfloat invlen = inversesqrt(grad_dot);\n"); + fsBuilder->codeAppend("\tgrad_dot = max(grad_dot, 1.0e-4);\n"); + fsBuilder->codeAppend("\tfloat invlen = inversesqrt(grad_dot);\n"); if (kHairline == ellipseEffect.getMode()) { // can probably do this with one step - builder->fsCodeAppend("\tfloat edgeAlpha = clamp(1.0-test*invlen, 0.0, 1.0);\n"); - builder->fsCodeAppend("\tedgeAlpha *= clamp(1.0+test*invlen, 0.0, 1.0);\n"); + fsBuilder->codeAppend("\tfloat edgeAlpha = clamp(1.0-test*invlen, 0.0, 1.0);\n"); + fsBuilder->codeAppend("\tedgeAlpha *= clamp(1.0+test*invlen, 0.0, 1.0);\n"); } else { - builder->fsCodeAppend("\tfloat edgeAlpha = clamp(0.5-test*invlen, 0.0, 1.0);\n"); + fsBuilder->codeAppend("\tfloat edgeAlpha = clamp(0.5-test*invlen, 0.0, 1.0);\n"); } // for inner curve if (kStroke == ellipseEffect.getMode()) { - builder->fsCodeAppendf("\tscaledOffset = %s.xy;\n", fsOffsetName1); - builder->fsCodeAppend("\ttest = dot(scaledOffset, scaledOffset) - 1.0;\n"); - builder->fsCodeAppendf("\tduvdx = dFdx(%s);\n", fsOffsetName1); - builder->fsCodeAppendf("\tduvdy = dFdy(%s);\n", fsOffsetName1); - builder->fsCodeAppendf("\tgrad = vec2(2.0*%s.x*duvdx.x + 2.0*%s.y*duvdx.y,\n" + fsBuilder->codeAppendf("\tscaledOffset = %s.xy;\n", fsOffsetName1); + fsBuilder->codeAppend("\ttest = dot(scaledOffset, scaledOffset) - 1.0;\n"); + fsBuilder->codeAppendf("\tduvdx = dFdx(%s);\n", fsOffsetName1); + fsBuilder->codeAppendf("\tduvdy = dFdy(%s);\n", fsOffsetName1); + fsBuilder->codeAppendf("\tgrad = vec2(2.0*%s.x*duvdx.x + 2.0*%s.y*duvdx.y,\n" "\t 2.0*%s.x*duvdy.x + 2.0*%s.y*duvdy.y);\n", fsOffsetName1, fsOffsetName1, fsOffsetName1, fsOffsetName1); - builder->fsCodeAppend("\tinvlen = inversesqrt(dot(grad, grad));\n"); - builder->fsCodeAppend("\tedgeAlpha *= clamp(0.5+test*invlen, 0.0, 1.0);\n"); + fsBuilder->codeAppend("\tinvlen = inversesqrt(dot(grad, grad));\n"); + fsBuilder->codeAppend("\tedgeAlpha *= clamp(0.5+test*invlen, 0.0, 1.0);\n"); } - builder->fsCodeAppendf("\t%s = %s;\n", outputColor, + fsBuilder->codeAppendf("\t%s = %s;\n", outputColor, (GrGLSLExpr4(inputColor) * GrGLSLExpr1("edgeAlpha")).c_str()); } diff --git a/src/gpu/effects/GrBezierEffect.cpp b/src/gpu/effects/GrBezierEffect.cpp index 6f3772d798..7384f62856 100644 --- a/src/gpu/effects/GrBezierEffect.cpp +++ b/src/gpu/effects/GrBezierEffect.cpp @@ -5,10 +5,10 @@ * found in the LICENSE file. */ +#include "gl/builders/GrGLProgramBuilder.h" #include "GrBezierEffect.h" #include "gl/GrGLEffect.h" -#include "gl/GrGLShaderBuilder.h" #include "gl/GrGLSL.h" #include "gl/GrGLVertexEffect.h" #include "GrTBackendEffectFactory.h" @@ -17,7 +17,7 @@ class GrGLConicEffect : public GrGLVertexEffect { public: GrGLConicEffect(const GrBackendEffectFactory&, const GrDrawEffect&); - virtual void emitCode(GrGLFullShaderBuilder* builder, + virtual void emitCode(GrGLFullProgramBuilder* builder, const GrDrawEffect& drawEffect, const GrEffectKey& key, const char* outputColor, @@ -42,7 +42,7 @@ GrGLConicEffect::GrGLConicEffect(const GrBackendEffectFactory& factory, fEdgeType = ce.getEdgeType(); } -void GrGLConicEffect::emitCode(GrGLFullShaderBuilder* builder, +void GrGLConicEffect::emitCode(GrGLFullProgramBuilder* builder, const GrDrawEffect& drawEffect, const GrEffectKey& key, const char* outputColor, @@ -53,67 +53,70 @@ void GrGLConicEffect::emitCode(GrGLFullShaderBuilder* builder, builder->addVarying(kVec4f_GrSLType, "ConicCoeffs", &vsName, &fsName); + + GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder(); const SkString* attr0Name = - builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); - builder->vsCodeAppendf("\t%s = %s;\n", vsName, attr0Name->c_str()); + vsBuilder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); + vsBuilder->codeAppendf("\t%s = %s;\n", vsName, attr0Name->c_str()); - builder->fsCodeAppend("\t\tfloat edgeAlpha;\n"); + GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); + fsBuilder->codeAppend("\t\tfloat edgeAlpha;\n"); switch (fEdgeType) { case kHairlineAA_GrEffectEdgeType: { - SkAssertResult(builder->enableFeature( - GrGLShaderBuilder::kStandardDerivatives_GLSLFeature)); - builder->fsCodeAppendf("\t\tvec3 dklmdx = dFdx(%s.xyz);\n", fsName); - builder->fsCodeAppendf("\t\tvec3 dklmdy = dFdy(%s.xyz);\n", fsName); - builder->fsCodeAppendf("\t\tfloat dfdx =\n" + SkAssertResult(fsBuilder->enableFeature( + GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature)); + fsBuilder->codeAppendf("\t\tvec3 dklmdx = dFdx(%s.xyz);\n", fsName); + fsBuilder->codeAppendf("\t\tvec3 dklmdy = dFdy(%s.xyz);\n", fsName); + fsBuilder->codeAppendf("\t\tfloat dfdx =\n" "\t\t\t2.0*%s.x*dklmdx.x - %s.y*dklmdx.z - %s.z*dklmdx.y;\n", fsName, fsName, fsName); - builder->fsCodeAppendf("\t\tfloat dfdy =\n" + fsBuilder->codeAppendf("\t\tfloat dfdy =\n" "\t\t\t2.0*%s.x*dklmdy.x - %s.y*dklmdy.z - %s.z*dklmdy.y;\n", fsName, fsName, fsName); - builder->fsCodeAppend("\t\tvec2 gF = vec2(dfdx, dfdy);\n"); - builder->fsCodeAppend("\t\tfloat gFM = sqrt(dot(gF, gF));\n"); - builder->fsCodeAppendf("\t\tfloat func = %s.x*%s.x - %s.y*%s.z;\n", fsName, fsName, + fsBuilder->codeAppend("\t\tvec2 gF = vec2(dfdx, dfdy);\n"); + fsBuilder->codeAppend("\t\tfloat gFM = sqrt(dot(gF, gF));\n"); + fsBuilder->codeAppendf("\t\tfloat func = %s.x*%s.x - %s.y*%s.z;\n", fsName, fsName, fsName, fsName); - builder->fsCodeAppend("\t\tfunc = abs(func);\n"); - builder->fsCodeAppend("\t\tedgeAlpha = func / gFM;\n"); - builder->fsCodeAppend("\t\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n"); + fsBuilder->codeAppend("\t\tfunc = abs(func);\n"); + fsBuilder->codeAppend("\t\tedgeAlpha = func / gFM;\n"); + fsBuilder->codeAppend("\t\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n"); // Add line below for smooth cubic ramp - // builder->fsCodeAppend("\t\tedgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);\n"); + // fsBuilder->codeAppend("\t\tedgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);\n"); break; } case kFillAA_GrEffectEdgeType: { - SkAssertResult(builder->enableFeature( - GrGLShaderBuilder::kStandardDerivatives_GLSLFeature)); - builder->fsCodeAppendf("\t\tvec3 dklmdx = dFdx(%s.xyz);\n", fsName); - builder->fsCodeAppendf("\t\tvec3 dklmdy = dFdy(%s.xyz);\n", fsName); - builder->fsCodeAppendf("\t\tfloat dfdx =\n" + SkAssertResult(fsBuilder->enableFeature( + GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature)); + fsBuilder->codeAppendf("\t\tvec3 dklmdx = dFdx(%s.xyz);\n", fsName); + fsBuilder->codeAppendf("\t\tvec3 dklmdy = dFdy(%s.xyz);\n", fsName); + fsBuilder->codeAppendf("\t\tfloat dfdx =\n" "\t\t\t2.0*%s.x*dklmdx.x - %s.y*dklmdx.z - %s.z*dklmdx.y;\n", fsName, fsName, fsName); - builder->fsCodeAppendf("\t\tfloat dfdy =\n" + fsBuilder->codeAppendf("\t\tfloat dfdy =\n" "\t\t\t2.0*%s.x*dklmdy.x - %s.y*dklmdy.z - %s.z*dklmdy.y;\n", fsName, fsName, fsName); - builder->fsCodeAppend("\t\tvec2 gF = vec2(dfdx, dfdy);\n"); - builder->fsCodeAppend("\t\tfloat gFM = sqrt(dot(gF, gF));\n"); - builder->fsCodeAppendf("\t\tfloat func = %s.x*%s.x - %s.y*%s.z;\n", fsName, fsName, + fsBuilder->codeAppend("\t\tvec2 gF = vec2(dfdx, dfdy);\n"); + fsBuilder->codeAppend("\t\tfloat gFM = sqrt(dot(gF, gF));\n"); + fsBuilder->codeAppendf("\t\tfloat func = %s.x*%s.x - %s.y*%s.z;\n", fsName, fsName, fsName, fsName); - builder->fsCodeAppend("\t\tedgeAlpha = func / gFM;\n"); - builder->fsCodeAppend("\t\tedgeAlpha = clamp(1.0 - edgeAlpha, 0.0, 1.0);\n"); + fsBuilder->codeAppend("\t\tedgeAlpha = func / gFM;\n"); + fsBuilder->codeAppend("\t\tedgeAlpha = clamp(1.0 - edgeAlpha, 0.0, 1.0);\n"); // Add line below for smooth cubic ramp - // builder->fsCodeAppend("\t\tedgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);\n"); + // fsBuilder->codeAppend("\t\tedgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);\n"); break; } case kFillBW_GrEffectEdgeType: { - builder->fsCodeAppendf("\t\tedgeAlpha = %s.x*%s.x - %s.y*%s.z;\n", fsName, fsName, + fsBuilder->codeAppendf("\t\tedgeAlpha = %s.x*%s.x - %s.y*%s.z;\n", fsName, fsName, fsName, fsName); - builder->fsCodeAppend("\t\tedgeAlpha = float(edgeAlpha < 0.0);\n"); + fsBuilder->codeAppend("\t\tedgeAlpha = float(edgeAlpha < 0.0);\n"); break; } default: SkFAIL("Shouldn't get here"); } - builder->fsCodeAppendf("\t%s = %s;\n", outputColor, + fsBuilder->codeAppendf("\t%s = %s;\n", outputColor, (GrGLSLExpr4(inputColor) * GrGLSLExpr1("edgeAlpha")).c_str()); } @@ -167,7 +170,7 @@ class GrGLQuadEffect : public GrGLVertexEffect { public: GrGLQuadEffect(const GrBackendEffectFactory&, const GrDrawEffect&); - virtual void emitCode(GrGLFullShaderBuilder* builder, + virtual void emitCode(GrGLFullProgramBuilder* builder, const GrDrawEffect& drawEffect, const GrEffectKey& key, const char* outputColor, @@ -192,7 +195,7 @@ GrGLQuadEffect::GrGLQuadEffect(const GrBackendEffectFactory& factory, fEdgeType = ce.getEdgeType(); } -void GrGLQuadEffect::emitCode(GrGLFullShaderBuilder* builder, +void GrGLQuadEffect::emitCode(GrGLFullProgramBuilder* builder, const GrDrawEffect& drawEffect, const GrEffectKey& key, const char* outputColor, @@ -200,61 +203,61 @@ void GrGLQuadEffect::emitCode(GrGLFullShaderBuilder* builder, const TransformedCoordsArray&, const TextureSamplerArray& samplers) { const char *vsName, *fsName; + builder->addVarying(kVec4f_GrSLType, "HairQuadEdge", &vsName, &fsName); + GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder(); const SkString* attrName = - builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); - builder->fsCodeAppendf("\t\tfloat edgeAlpha;\n"); + vsBuilder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); + vsBuilder->codeAppendf("\t%s = %s;\n", vsName, attrName->c_str()); - builder->addVarying(kVec4f_GrSLType, "HairQuadEdge", &vsName, &fsName); + GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); + fsBuilder->codeAppendf("\t\tfloat edgeAlpha;\n"); switch (fEdgeType) { case kHairlineAA_GrEffectEdgeType: { - SkAssertResult(builder->enableFeature( - GrGLShaderBuilder::kStandardDerivatives_GLSLFeature)); - builder->fsCodeAppendf("\t\tvec2 duvdx = dFdx(%s.xy);\n", fsName); - builder->fsCodeAppendf("\t\tvec2 duvdy = dFdy(%s.xy);\n", fsName); - builder->fsCodeAppendf("\t\tvec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx.y,\n" + SkAssertResult(fsBuilder->enableFeature( + GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature)); + fsBuilder->codeAppendf("\t\tvec2 duvdx = dFdx(%s.xy);\n", fsName); + fsBuilder->codeAppendf("\t\tvec2 duvdy = dFdy(%s.xy);\n", fsName); + fsBuilder->codeAppendf("\t\tvec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx.y,\n" "\t\t 2.0*%s.x*duvdy.x - duvdy.y);\n", fsName, fsName); - builder->fsCodeAppendf("\t\tedgeAlpha = (%s.x*%s.x - %s.y);\n", fsName, fsName, + fsBuilder->codeAppendf("\t\tedgeAlpha = (%s.x*%s.x - %s.y);\n", fsName, fsName, fsName); - builder->fsCodeAppend("\t\tedgeAlpha = sqrt(edgeAlpha*edgeAlpha / dot(gF, gF));\n"); - builder->fsCodeAppend("\t\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n"); + fsBuilder->codeAppend("\t\tedgeAlpha = sqrt(edgeAlpha*edgeAlpha / dot(gF, gF));\n"); + fsBuilder->codeAppend("\t\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n"); // Add line below for smooth cubic ramp - // builder->fsCodeAppend("\t\tedgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);\n"); + // fsBuilder->codeAppend("\t\tedgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);\n"); break; } case kFillAA_GrEffectEdgeType: { - SkAssertResult(builder->enableFeature( - GrGLShaderBuilder::kStandardDerivatives_GLSLFeature)); - builder->fsCodeAppendf("\t\tvec2 duvdx = dFdx(%s.xy);\n", fsName); - builder->fsCodeAppendf("\t\tvec2 duvdy = dFdy(%s.xy);\n", fsName); - builder->fsCodeAppendf("\t\tvec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx.y,\n" + SkAssertResult(fsBuilder->enableFeature( + GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature)); + fsBuilder->codeAppendf("\t\tvec2 duvdx = dFdx(%s.xy);\n", fsName); + fsBuilder->codeAppendf("\t\tvec2 duvdy = dFdy(%s.xy);\n", fsName); + fsBuilder->codeAppendf("\t\tvec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx.y,\n" "\t\t 2.0*%s.x*duvdy.x - duvdy.y);\n", fsName, fsName); - builder->fsCodeAppendf("\t\tedgeAlpha = (%s.x*%s.x - %s.y);\n", fsName, fsName, + fsBuilder->codeAppendf("\t\tedgeAlpha = (%s.x*%s.x - %s.y);\n", fsName, fsName, fsName); - builder->fsCodeAppend("\t\tedgeAlpha = edgeAlpha / sqrt(dot(gF, gF));\n"); - builder->fsCodeAppend("\t\tedgeAlpha = clamp(1.0 - edgeAlpha, 0.0, 1.0);\n"); + fsBuilder->codeAppend("\t\tedgeAlpha = edgeAlpha / sqrt(dot(gF, gF));\n"); + fsBuilder->codeAppend("\t\tedgeAlpha = clamp(1.0 - edgeAlpha, 0.0, 1.0);\n"); // Add line below for smooth cubic ramp - // builder->fsCodeAppend("\t\tedgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);\n"); + // fsBuilder->codeAppend("\t\tedgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);\n"); break; } case kFillBW_GrEffectEdgeType: { - builder->fsCodeAppendf("\t\tedgeAlpha = (%s.x*%s.x - %s.y);\n", fsName, fsName, + fsBuilder->codeAppendf("\t\tedgeAlpha = (%s.x*%s.x - %s.y);\n", fsName, fsName, fsName); - builder->fsCodeAppend("\t\tedgeAlpha = float(edgeAlpha < 0.0);\n"); + fsBuilder->codeAppend("\t\tedgeAlpha = float(edgeAlpha < 0.0);\n"); break; } default: SkFAIL("Shouldn't get here"); } - builder->fsCodeAppendf("\t%s = %s;\n", outputColor, + fsBuilder->codeAppendf("\t%s = %s;\n", outputColor, (GrGLSLExpr4(inputColor) * GrGLSLExpr1("edgeAlpha")).c_str()); - - - builder->vsCodeAppendf("\t%s = %s;\n", vsName, attrName->c_str()); } void GrGLQuadEffect::GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&, @@ -307,7 +310,7 @@ class GrGLCubicEffect : public GrGLVertexEffect { public: GrGLCubicEffect(const GrBackendEffectFactory&, const GrDrawEffect&); - virtual void emitCode(GrGLFullShaderBuilder* builder, + virtual void emitCode(GrGLFullProgramBuilder* builder, const GrDrawEffect& drawEffect, const GrEffectKey& key, const char* outputColor, @@ -332,7 +335,7 @@ GrGLCubicEffect::GrGLCubicEffect(const GrBackendEffectFactory& factory, fEdgeType = ce.getEdgeType(); } -void GrGLCubicEffect::emitCode(GrGLFullShaderBuilder* builder, +void GrGLCubicEffect::emitCode(GrGLFullProgramBuilder* builder, const GrDrawEffect& drawEffect, const GrEffectKey& key, const char* outputColor, @@ -343,67 +346,70 @@ void GrGLCubicEffect::emitCode(GrGLFullShaderBuilder* builder, builder->addVarying(kVec4f_GrSLType, "CubicCoeffs", &vsName, &fsName); + + GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder(); const SkString* attr0Name = - builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); - builder->vsCodeAppendf("\t%s = %s;\n", vsName, attr0Name->c_str()); + vsBuilder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); + vsBuilder->codeAppendf("\t%s = %s;\n", vsName, attr0Name->c_str()); - builder->fsCodeAppend("\t\tfloat edgeAlpha;\n"); + GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); + fsBuilder->codeAppend("\t\tfloat edgeAlpha;\n"); switch (fEdgeType) { case kHairlineAA_GrEffectEdgeType: { - SkAssertResult(builder->enableFeature( - GrGLShaderBuilder::kStandardDerivatives_GLSLFeature)); - builder->fsCodeAppendf("\t\tvec3 dklmdx = dFdx(%s.xyz);\n", fsName); - builder->fsCodeAppendf("\t\tvec3 dklmdy = dFdy(%s.xyz);\n", fsName); - builder->fsCodeAppendf("\t\tfloat dfdx =\n" + SkAssertResult(fsBuilder->enableFeature( + GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature)); + fsBuilder->codeAppendf("\t\tvec3 dklmdx = dFdx(%s.xyz);\n", fsName); + fsBuilder->codeAppendf("\t\tvec3 dklmdy = dFdy(%s.xyz);\n", fsName); + fsBuilder->codeAppendf("\t\tfloat dfdx =\n" "\t\t3.0*%s.x*%s.x*dklmdx.x - %s.y*dklmdx.z - %s.z*dklmdx.y;\n", fsName, fsName, fsName, fsName); - builder->fsCodeAppendf("\t\tfloat dfdy =\n" + fsBuilder->codeAppendf("\t\tfloat dfdy =\n" "\t\t3.0*%s.x*%s.x*dklmdy.x - %s.y*dklmdy.z - %s.z*dklmdy.y;\n", fsName, fsName, fsName, fsName); - builder->fsCodeAppend("\t\tvec2 gF = vec2(dfdx, dfdy);\n"); - builder->fsCodeAppend("\t\tfloat gFM = sqrt(dot(gF, gF));\n"); - builder->fsCodeAppendf("\t\tfloat func = %s.x*%s.x*%s.x - %s.y*%s.z;\n", + fsBuilder->codeAppend("\t\tvec2 gF = vec2(dfdx, dfdy);\n"); + fsBuilder->codeAppend("\t\tfloat gFM = sqrt(dot(gF, gF));\n"); + fsBuilder->codeAppendf("\t\tfloat func = %s.x*%s.x*%s.x - %s.y*%s.z;\n", fsName, fsName, fsName, fsName, fsName); - builder->fsCodeAppend("\t\tfunc = abs(func);\n"); - builder->fsCodeAppend("\t\tedgeAlpha = func / gFM;\n"); - builder->fsCodeAppend("\t\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n"); + fsBuilder->codeAppend("\t\tfunc = abs(func);\n"); + fsBuilder->codeAppend("\t\tedgeAlpha = func / gFM;\n"); + fsBuilder->codeAppend("\t\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n"); // Add line below for smooth cubic ramp - // builder->fsCodeAppend("\t\tedgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);\n"); + // fsBuilder->codeAppend("\t\tedgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);\n"); break; } case kFillAA_GrEffectEdgeType: { - SkAssertResult(builder->enableFeature( - GrGLShaderBuilder::kStandardDerivatives_GLSLFeature)); - builder->fsCodeAppendf("\t\tvec3 dklmdx = dFdx(%s.xyz);\n", fsName); - builder->fsCodeAppendf("\t\tvec3 dklmdy = dFdy(%s.xyz);\n", fsName); - builder->fsCodeAppendf("\t\tfloat dfdx =\n" + SkAssertResult(fsBuilder->enableFeature( + GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature)); + fsBuilder->codeAppendf("\t\tvec3 dklmdx = dFdx(%s.xyz);\n", fsName); + fsBuilder->codeAppendf("\t\tvec3 dklmdy = dFdy(%s.xyz);\n", fsName); + fsBuilder->codeAppendf("\t\tfloat dfdx =\n" "\t\t3.0*%s.x*%s.x*dklmdx.x - %s.y*dklmdx.z - %s.z*dklmdx.y;\n", fsName, fsName, fsName, fsName); - builder->fsCodeAppendf("\t\tfloat dfdy =\n" + fsBuilder->codeAppendf("\t\tfloat dfdy =\n" "\t\t3.0*%s.x*%s.x*dklmdy.x - %s.y*dklmdy.z - %s.z*dklmdy.y;\n", fsName, fsName, fsName, fsName); - builder->fsCodeAppend("\t\tvec2 gF = vec2(dfdx, dfdy);\n"); - builder->fsCodeAppend("\t\tfloat gFM = sqrt(dot(gF, gF));\n"); - builder->fsCodeAppendf("\t\tfloat func = %s.x*%s.x*%s.x - %s.y*%s.z;\n", + fsBuilder->codeAppend("\t\tvec2 gF = vec2(dfdx, dfdy);\n"); + fsBuilder->codeAppend("\t\tfloat gFM = sqrt(dot(gF, gF));\n"); + fsBuilder->codeAppendf("\t\tfloat func = %s.x*%s.x*%s.x - %s.y*%s.z;\n", fsName, fsName, fsName, fsName, fsName); - builder->fsCodeAppend("\t\tedgeAlpha = func / gFM;\n"); - builder->fsCodeAppend("\t\tedgeAlpha = clamp(1.0 - edgeAlpha, 0.0, 1.0);\n"); + fsBuilder->codeAppend("\t\tedgeAlpha = func / gFM;\n"); + fsBuilder->codeAppend("\t\tedgeAlpha = clamp(1.0 - edgeAlpha, 0.0, 1.0);\n"); // Add line below for smooth cubic ramp - // builder->fsCodeAppend("\t\tedgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);\n"); + // fsBuilder->codeAppend("\t\tedgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);\n"); break; } case kFillBW_GrEffectEdgeType: { - builder->fsCodeAppendf("\t\tedgeAlpha = %s.x*%s.x*%s.x - %s.y*%s.z;\n", + fsBuilder->codeAppendf("\t\tedgeAlpha = %s.x*%s.x*%s.x - %s.y*%s.z;\n", fsName, fsName, fsName, fsName, fsName); - builder->fsCodeAppend("\t\tedgeAlpha = float(edgeAlpha < 0.0);\n"); + fsBuilder->codeAppend("\t\tedgeAlpha = float(edgeAlpha < 0.0);\n"); break; } default: SkFAIL("Shouldn't get here"); } - builder->fsCodeAppendf("\t%s = %s;\n", outputColor, + fsBuilder->codeAppendf("\t%s = %s;\n", outputColor, (GrGLSLExpr4(inputColor) * GrGLSLExpr1("edgeAlpha")).c_str()); } diff --git a/src/gpu/effects/GrBicubicEffect.cpp b/src/gpu/effects/GrBicubicEffect.cpp index fb98b4ac4c..27d482ae2e 100644 --- a/src/gpu/effects/GrBicubicEffect.cpp +++ b/src/gpu/effects/GrBicubicEffect.cpp @@ -5,9 +5,9 @@ * found in the LICENSE file. */ +#include "gl/builders/GrGLProgramBuilder.h" #include "GrBicubicEffect.h" -#include "gl/GrGLShaderBuilder.h" #define DS(x) SkDoubleToScalar(x) @@ -24,7 +24,7 @@ public: GrGLBicubicEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&); - virtual void emitCode(GrGLShaderBuilder*, + virtual void emitCode(GrGLProgramBuilder*, const GrDrawEffect&, const GrEffectKey&, const char* outputColor, @@ -54,7 +54,7 @@ GrGLBicubicEffect::GrGLBicubicEffect(const GrBackendEffectFactory& factory, cons : INHERITED(factory) { } -void GrGLBicubicEffect::emitCode(GrGLShaderBuilder* builder, +void GrGLBicubicEffect::emitCode(GrGLProgramBuilder* builder, const GrDrawEffect& drawEffect, const GrEffectKey& key, const char* outputColor, @@ -63,10 +63,9 @@ void GrGLBicubicEffect::emitCode(GrGLShaderBuilder* builder, const TextureSamplerArray& samplers) { const GrTextureDomain& domain = drawEffect.castEffect().domain(); - SkString coords2D = builder->ensureFSCoords2D(coords, 0); - fCoefficientsUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, + fCoefficientsUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kMat44f_GrSLType, "Coefficients"); - fImageIncrementUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, + fImageIncrementUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec2f_GrSLType, "ImageIncrement"); const char* imgInc = builder->getUniformCStr(fImageIncrementUni); @@ -82,7 +81,9 @@ void GrGLBicubicEffect::emitCode(GrGLShaderBuilder* builder, GrGLShaderVar("c2", kVec4f_GrSLType), GrGLShaderVar("c3", kVec4f_GrSLType), }; - builder->fsEmitFunction(kVec4f_GrSLType, + GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); + SkString coords2D = fsBuilder->ensureFSCoords2D(coords, 0); + fsBuilder->emitFunction(kVec4f_GrSLType, "cubicBlend", SK_ARRAY_COUNT(gCubicBlendArgs), gCubicBlendArgs, @@ -90,28 +91,28 @@ void GrGLBicubicEffect::emitCode(GrGLShaderBuilder* builder, "\tvec4 c = coefficients * ts;\n" "\treturn c.x * c0 + c.y * c1 + c.z * c2 + c.w * c3;\n", &cubicBlendName); - builder->fsCodeAppendf("\tvec2 coord = %s - %s * vec2(0.5);\n", coords2D.c_str(), imgInc); + fsBuilder->codeAppendf("\tvec2 coord = %s - %s * vec2(0.5);\n", coords2D.c_str(), imgInc); // We unnormalize the coord in order to determine our fractional offset (f) within the texel // We then snap coord to a texel center and renormalize. The snap prevents cases where the // starting coords are near a texel boundary and accumulations of imgInc would cause us to skip/ // double hit a texel. - builder->fsCodeAppendf("\tcoord /= %s;\n", imgInc); - builder->fsCodeAppend("\tvec2 f = fract(coord);\n"); - builder->fsCodeAppendf("\tcoord = (coord - f + vec2(0.5)) * %s;\n", imgInc); - builder->fsCodeAppend("\tvec4 rowColors[4];\n"); + fsBuilder->codeAppendf("\tcoord /= %s;\n", imgInc); + fsBuilder->codeAppend("\tvec2 f = fract(coord);\n"); + fsBuilder->codeAppendf("\tcoord = (coord - f + vec2(0.5)) * %s;\n", imgInc); + fsBuilder->codeAppend("\tvec4 rowColors[4];\n"); for (int y = 0; y < 4; ++y) { for (int x = 0; x < 4; ++x) { SkString coord; coord.printf("coord + %s * vec2(%d, %d)", imgInc, x - 1, y - 1); SkString sampleVar; sampleVar.printf("rowColors[%d]", x); - fDomain.sampleTexture(builder, domain, sampleVar.c_str(), coord, samplers[0]); + fDomain.sampleTexture(fsBuilder, domain, sampleVar.c_str(), coord, samplers[0]); } - builder->fsCodeAppendf("\tvec4 s%d = %s(%s, f.x, rowColors[0], rowColors[1], rowColors[2], rowColors[3]);\n", y, cubicBlendName.c_str(), coeff); + fsBuilder->codeAppendf("\tvec4 s%d = %s(%s, f.x, rowColors[0], rowColors[1], rowColors[2], rowColors[3]);\n", y, cubicBlendName.c_str(), coeff); } SkString bicubicColor; bicubicColor.printf("%s(%s, f.y, s0, s1, s2, s3)", cubicBlendName.c_str(), coeff); - builder->fsCodeAppendf("\t%s = %s;\n", outputColor, (GrGLSLExpr4(bicubicColor.c_str()) * GrGLSLExpr4(inputColor)).c_str()); + fsBuilder->codeAppendf("\t%s = %s;\n", outputColor, (GrGLSLExpr4(bicubicColor.c_str()) * GrGLSLExpr4(inputColor)).c_str()); } void GrGLBicubicEffect::setData(const GrGLProgramDataManager& pdman, diff --git a/src/gpu/effects/GrConfigConversionEffect.cpp b/src/gpu/effects/GrConfigConversionEffect.cpp index d7ba6865c9..84e60cd76c 100644 --- a/src/gpu/effects/GrConfigConversionEffect.cpp +++ b/src/gpu/effects/GrConfigConversionEffect.cpp @@ -10,7 +10,7 @@ #include "GrTBackendEffectFactory.h" #include "GrSimpleTextureEffect.h" #include "gl/GrGLEffect.h" -#include "gl/GrGLShaderBuilder.h" +#include "gl/builders/GrGLProgramBuilder.h" #include "SkMatrix.h" class GrGLConfigConversionEffect : public GrGLEffect { @@ -23,7 +23,7 @@ public: fPMConversion = effect.pmConversion(); } - virtual void emitCode(GrGLShaderBuilder* builder, + virtual void emitCode(GrGLProgramBuilder* builder, const GrDrawEffect&, const GrEffectKey& key, const char* outputColor, @@ -34,20 +34,23 @@ public: GrGLShaderVar tmpVar("tmpColor", kVec4f_GrSLType, 0, GrGLShaderVar::kHigh_Precision); SkString tmpDecl; tmpVar.appendDecl(builder->ctxInfo(), &tmpDecl); - builder->fsCodeAppendf("%s;", tmpDecl.c_str()); - builder->fsCodeAppendf("%s = ", tmpVar.c_str()); - builder->fsAppendTextureLookup(samplers[0], coords[0].c_str(), coords[0].type()); - builder->fsCodeAppend(";"); + GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); + + fsBuilder->codeAppendf("%s;", tmpDecl.c_str()); + + fsBuilder->codeAppendf("%s = ", tmpVar.c_str()); + fsBuilder->appendTextureLookup(samplers[0], coords[0].c_str(), coords[0].type()); + fsBuilder->codeAppend(";"); if (GrConfigConversionEffect::kNone_PMConversion == fPMConversion) { SkASSERT(fSwapRedAndBlue); - builder->fsCodeAppendf("%s = %s.bgra;", outputColor, tmpVar.c_str()); + fsBuilder->codeAppendf("%s = %s.bgra;", outputColor, tmpVar.c_str()); } else { const char* swiz = fSwapRedAndBlue ? "bgr" : "rgb"; switch (fPMConversion) { case GrConfigConversionEffect::kMulByAlpha_RoundUp_PMConversion: - builder->fsCodeAppendf( + fsBuilder->codeAppendf( "%s = vec4(ceil(%s.%s * %s.a * 255.0) / 255.0, %s.a);", tmpVar.c_str(), tmpVar.c_str(), swiz, tmpVar.c_str(), tmpVar.c_str()); break; @@ -56,17 +59,17 @@ public: // In Intel GPUs, the integer value converted from floor(%s.r * 255.0) / 255.0 // is less than the integer value converted from %s.r by 1 when the %s.r is // converted from the integer value 2^n, such as 1, 2, 4, 8, etc. - builder->fsCodeAppendf( + fsBuilder->codeAppendf( "%s = vec4(floor(%s.%s * %s.a * 255.0 + 0.001) / 255.0, %s.a);", tmpVar.c_str(), tmpVar.c_str(), swiz, tmpVar.c_str(), tmpVar.c_str()); break; case GrConfigConversionEffect::kDivByAlpha_RoundUp_PMConversion: - builder->fsCodeAppendf( + fsBuilder->codeAppendf( "%s = %s.a <= 0.0 ? vec4(0,0,0,0) : vec4(ceil(%s.%s / %s.a * 255.0) / 255.0, %s.a);", tmpVar.c_str(), tmpVar.c_str(), tmpVar.c_str(), swiz, tmpVar.c_str(), tmpVar.c_str()); break; case GrConfigConversionEffect::kDivByAlpha_RoundDown_PMConversion: - builder->fsCodeAppendf( + fsBuilder->codeAppendf( "%s = %s.a <= 0.0 ? vec4(0,0,0,0) : vec4(floor(%s.%s / %s.a * 255.0) / 255.0, %s.a);", tmpVar.c_str(), tmpVar.c_str(), tmpVar.c_str(), swiz, tmpVar.c_str(), tmpVar.c_str()); break; @@ -74,11 +77,11 @@ public: SkFAIL("Unknown conversion op."); break; } - builder->fsCodeAppendf("%s = %s;", outputColor, tmpVar.c_str()); + fsBuilder->codeAppendf("%s = %s;", outputColor, tmpVar.c_str()); } SkString modulate; GrGLSLMulVarBy4f(&modulate, 2, outputColor, inputColor); - builder->fsCodeAppend(modulate.c_str()); + fsBuilder->codeAppend(modulate.c_str()); } static inline void GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&, diff --git a/src/gpu/effects/GrConvexPolyEffect.cpp b/src/gpu/effects/GrConvexPolyEffect.cpp index 41911c12b0..71a8befece 100644 --- a/src/gpu/effects/GrConvexPolyEffect.cpp +++ b/src/gpu/effects/GrConvexPolyEffect.cpp @@ -5,10 +5,10 @@ * found in the LICENSE file. */ +#include "gl/builders/GrGLProgramBuilder.h" #include "GrConvexPolyEffect.h" #include "gl/GrGLEffect.h" -#include "gl/GrGLShaderBuilder.h" #include "gl/GrGLSL.h" #include "GrTBackendEffectFactory.h" @@ -89,7 +89,7 @@ class GLAARectEffect : public GrGLEffect { public: GLAARectEffect(const GrBackendEffectFactory&, const GrDrawEffect&); - virtual void emitCode(GrGLShaderBuilder* builder, + virtual void emitCode(GrGLProgramBuilder* builder, const GrDrawEffect& drawEffect, const GrEffectKey& key, const char* outputColor, @@ -113,7 +113,7 @@ GLAARectEffect::GLAARectEffect(const GrBackendEffectFactory& factory, fPrevRect.fLeft = SK_ScalarNaN; } -void GLAARectEffect::emitCode(GrGLShaderBuilder* builder, +void GLAARectEffect::emitCode(GrGLProgramBuilder* builder, const GrDrawEffect& drawEffect, const GrEffectKey& key, const char* outputColor, @@ -124,34 +124,36 @@ void GLAARectEffect::emitCode(GrGLShaderBuilder* builder, const char *rectName; // The rect uniform's xyzw refer to (left + 0.5, top + 0.5, right - 0.5, bottom - 0.5), // respectively. - fRectUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, + fRectUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec4f_GrSLType, "rect", &rectName); - const char* fragmentPos = builder->fragmentPosition(); + + GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); + const char* fragmentPos = fsBuilder->fragmentPosition(); if (GrEffectEdgeTypeIsAA(aare.getEdgeType())) { // The amount of coverage removed in x and y by the edges is computed as a pair of negative // numbers, xSub and ySub. - builder->fsCodeAppend("\t\tfloat xSub, ySub;\n"); - builder->fsCodeAppendf("\t\txSub = min(%s.x - %s.x, 0.0);\n", fragmentPos, rectName); - builder->fsCodeAppendf("\t\txSub += min(%s.z - %s.x, 0.0);\n", rectName, fragmentPos); - builder->fsCodeAppendf("\t\tySub = min(%s.y - %s.y, 0.0);\n", fragmentPos, rectName); - builder->fsCodeAppendf("\t\tySub += min(%s.w - %s.y, 0.0);\n", rectName, fragmentPos); + fsBuilder->codeAppend("\t\tfloat xSub, ySub;\n"); + fsBuilder->codeAppendf("\t\txSub = min(%s.x - %s.x, 0.0);\n", fragmentPos, rectName); + fsBuilder->codeAppendf("\t\txSub += min(%s.z - %s.x, 0.0);\n", rectName, fragmentPos); + fsBuilder->codeAppendf("\t\tySub = min(%s.y - %s.y, 0.0);\n", fragmentPos, rectName); + fsBuilder->codeAppendf("\t\tySub += min(%s.w - %s.y, 0.0);\n", rectName, fragmentPos); // Now compute coverage in x and y and multiply them to get the fraction of the pixel // covered. - builder->fsCodeAppendf("\t\tfloat alpha = (1.0 + max(xSub, -1.0)) * (1.0 + max(ySub, -1.0));\n"); + fsBuilder->codeAppendf("\t\tfloat alpha = (1.0 + max(xSub, -1.0)) * (1.0 + max(ySub, -1.0));\n"); } else { - builder->fsCodeAppendf("\t\tfloat alpha = 1.0;\n"); - builder->fsCodeAppendf("\t\talpha *= (%s.x - %s.x) > -0.5 ? 1.0 : 0.0;\n", fragmentPos, rectName); - builder->fsCodeAppendf("\t\talpha *= (%s.z - %s.x) > -0.5 ? 1.0 : 0.0;\n", rectName, fragmentPos); - builder->fsCodeAppendf("\t\talpha *= (%s.y - %s.y) > -0.5 ? 1.0 : 0.0;\n", fragmentPos, rectName); - builder->fsCodeAppendf("\t\talpha *= (%s.w - %s.y) > -0.5 ? 1.0 : 0.0;\n", rectName, fragmentPos); + fsBuilder->codeAppendf("\t\tfloat alpha = 1.0;\n"); + fsBuilder->codeAppendf("\t\talpha *= (%s.x - %s.x) > -0.5 ? 1.0 : 0.0;\n", fragmentPos, rectName); + fsBuilder->codeAppendf("\t\talpha *= (%s.z - %s.x) > -0.5 ? 1.0 : 0.0;\n", rectName, fragmentPos); + fsBuilder->codeAppendf("\t\talpha *= (%s.y - %s.y) > -0.5 ? 1.0 : 0.0;\n", fragmentPos, rectName); + fsBuilder->codeAppendf("\t\talpha *= (%s.w - %s.y) > -0.5 ? 1.0 : 0.0;\n", rectName, fragmentPos); } if (GrEffectEdgeTypeIsInverseFill(aare.getEdgeType())) { - builder->fsCodeAppend("\t\talpha = 1.0 - alpha;\n"); + fsBuilder->codeAppend("\t\talpha = 1.0 - alpha;\n"); } - builder->fsCodeAppendf("\t\t%s = %s;\n", outputColor, + fsBuilder->codeAppendf("\t\t%s = %s;\n", outputColor, (GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_str()); } @@ -181,7 +183,7 @@ class GrGLConvexPolyEffect : public GrGLEffect { public: GrGLConvexPolyEffect(const GrBackendEffectFactory&, const GrDrawEffect&); - virtual void emitCode(GrGLShaderBuilder* builder, + virtual void emitCode(GrGLProgramBuilder* builder, const GrDrawEffect& drawEffect, const GrEffectKey& key, const char* outputColor, @@ -205,7 +207,7 @@ GrGLConvexPolyEffect::GrGLConvexPolyEffect(const GrBackendEffectFactory& factory fPrevEdges[0] = SK_ScalarNaN; } -void GrGLConvexPolyEffect::emitCode(GrGLShaderBuilder* builder, +void GrGLConvexPolyEffect::emitCode(GrGLProgramBuilder* builder, const GrDrawEffect& drawEffect, const GrEffectKey& key, const char* outputColor, @@ -215,34 +217,35 @@ void GrGLConvexPolyEffect::emitCode(GrGLShaderBuilder* builder, const GrConvexPolyEffect& cpe = drawEffect.castEffect(); const char *edgeArrayName; - fEdgeUniform = builder->addUniformArray(GrGLShaderBuilder::kFragment_Visibility, + fEdgeUniform = builder->addUniformArray(GrGLProgramBuilder::kFragment_Visibility, kVec3f_GrSLType, "edges", cpe.getEdgeCount(), &edgeArrayName); - builder->fsCodeAppend("\t\tfloat alpha = 1.0;\n"); - builder->fsCodeAppend("\t\tfloat edge;\n"); - const char* fragmentPos = builder->fragmentPosition(); + GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); + fsBuilder->codeAppend("\t\tfloat alpha = 1.0;\n"); + fsBuilder->codeAppend("\t\tfloat edge;\n"); + const char* fragmentPos = fsBuilder->fragmentPosition(); for (int i = 0; i < cpe.getEdgeCount(); ++i) { - builder->fsCodeAppendf("\t\tedge = dot(%s[%d], vec3(%s.x, %s.y, 1));\n", + fsBuilder->codeAppendf("\t\tedge = dot(%s[%d], vec3(%s.x, %s.y, 1));\n", edgeArrayName, i, fragmentPos, fragmentPos); if (GrEffectEdgeTypeIsAA(cpe.getEdgeType())) { - builder->fsCodeAppend("\t\tedge = clamp(edge, 0.0, 1.0);\n"); + fsBuilder->codeAppend("\t\tedge = clamp(edge, 0.0, 1.0);\n"); } else { - builder->fsCodeAppend("\t\tedge = edge >= 0.5 ? 1.0 : 0.0;\n"); + fsBuilder->codeAppend("\t\tedge = edge >= 0.5 ? 1.0 : 0.0;\n"); } - builder->fsCodeAppend("\t\talpha *= edge;\n"); + fsBuilder->codeAppend("\t\talpha *= edge;\n"); } // Woe is me. See skbug.com/2149. if (kTegra2_GrGLRenderer == builder->ctxInfo().renderer()) { - builder->fsCodeAppend("\t\tif (-1.0 == alpha) {\n\t\t\tdiscard;\n\t\t}\n"); + fsBuilder->codeAppend("\t\tif (-1.0 == alpha) {\n\t\t\tdiscard;\n\t\t}\n"); } if (GrEffectEdgeTypeIsInverseFill(cpe.getEdgeType())) { - builder->fsCodeAppend("\talpha = 1.0 - alpha;\n"); + fsBuilder->codeAppend("\talpha = 1.0 - alpha;\n"); } - builder->fsCodeAppendf("\t%s = %s;\n", outputColor, + fsBuilder->codeAppendf("\t%s = %s;\n", outputColor, (GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_str()); } diff --git a/src/gpu/effects/GrConvolutionEffect.cpp b/src/gpu/effects/GrConvolutionEffect.cpp index e0cf35b242..ba9f8146c8 100644 --- a/src/gpu/effects/GrConvolutionEffect.cpp +++ b/src/gpu/effects/GrConvolutionEffect.cpp @@ -5,9 +5,9 @@ * found in the LICENSE file. */ +#include "gl/builders/GrGLProgramBuilder.h" #include "GrConvolutionEffect.h" #include "gl/GrGLEffect.h" -#include "gl/GrGLShaderBuilder.h" #include "gl/GrGLSL.h" #include "gl/GrGLTexture.h" #include "GrTBackendEffectFactory.h" @@ -19,7 +19,7 @@ class GrGLConvolutionEffect : public GrGLEffect { public: GrGLConvolutionEffect(const GrBackendEffectFactory&, const GrDrawEffect&); - virtual void emitCode(GrGLShaderBuilder*, + virtual void emitCode(GrGLProgramBuilder*, const GrDrawEffect&, const GrEffectKey&, const char* outputColor, @@ -55,30 +55,32 @@ GrGLConvolutionEffect::GrGLConvolutionEffect(const GrBackendEffectFactory& facto fDirection = c.direction(); } -void GrGLConvolutionEffect::emitCode(GrGLShaderBuilder* builder, +void GrGLConvolutionEffect::emitCode(GrGLProgramBuilder* builder, const GrDrawEffect&, const GrEffectKey& key, const char* outputColor, const char* inputColor, const TransformedCoordsArray& coords, const TextureSamplerArray& samplers) { - SkString coords2D = builder->ensureFSCoords2D(coords, 0); - fImageIncrementUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, + fImageIncrementUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec2f_GrSLType, "ImageIncrement"); if (this->useBounds()) { - fBoundsUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, + fBoundsUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec2f_GrSLType, "Bounds"); } - fKernelUni = builder->addUniformArray(GrGLShaderBuilder::kFragment_Visibility, + fKernelUni = builder->addUniformArray(GrGLProgramBuilder::kFragment_Visibility, kFloat_GrSLType, "Kernel", this->width()); - builder->fsCodeAppendf("\t\t%s = vec4(0, 0, 0, 0);\n", outputColor); + GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); + SkString coords2D = fsBuilder->ensureFSCoords2D(coords, 0); + + fsBuilder->codeAppendf("\t\t%s = vec4(0, 0, 0, 0);\n", outputColor); int width = this->width(); const GrGLShaderVar& kernel = builder->getUniformVariable(fKernelUni); const char* imgInc = builder->getUniformCStr(fImageIncrementUni); - builder->fsCodeAppendf("\t\tvec2 coord = %s - %d.0 * %s;\n", coords2D.c_str(), fRadius, imgInc); + fsBuilder->codeAppendf("\t\tvec2 coord = %s - %d.0 * %s;\n", coords2D.c_str(), fRadius, imgInc); // Manually unroll loop because some drivers don't; yields 20-30% speedup. for (int i = 0; i < width; i++) { @@ -86,21 +88,21 @@ void GrGLConvolutionEffect::emitCode(GrGLShaderBuilder* builder, SkString kernelIndex; index.appendS32(i); kernel.appendArrayAccess(index.c_str(), &kernelIndex); - builder->fsCodeAppendf("\t\t%s += ", outputColor); - builder->fsAppendTextureLookup(samplers[0], "coord"); + fsBuilder->codeAppendf("\t\t%s += ", outputColor); + fsBuilder->appendTextureLookup(samplers[0], "coord"); if (this->useBounds()) { const char* bounds = builder->getUniformCStr(fBoundsUni); const char* component = this->direction() == Gr1DKernelEffect::kY_Direction ? "y" : "x"; - builder->fsCodeAppendf(" * float(coord.%s >= %s.x && coord.%s <= %s.y)", + fsBuilder->codeAppendf(" * float(coord.%s >= %s.x && coord.%s <= %s.y)", component, bounds, component, bounds); } - builder->fsCodeAppendf(" * %s;\n", kernelIndex.c_str()); - builder->fsCodeAppendf("\t\tcoord += %s;\n", imgInc); + fsBuilder->codeAppendf(" * %s;\n", kernelIndex.c_str()); + fsBuilder->codeAppendf("\t\tcoord += %s;\n", imgInc); } SkString modulate; GrGLSLMulVarBy4f(&modulate, 2, outputColor, inputColor); - builder->fsCodeAppend(modulate.c_str()); + fsBuilder->codeAppend(modulate.c_str()); } void GrGLConvolutionEffect::setData(const GrGLProgramDataManager& pdman, diff --git a/src/gpu/effects/GrCustomCoordsTextureEffect.cpp b/src/gpu/effects/GrCustomCoordsTextureEffect.cpp index d235d5fb76..0401c6c7ef 100644 --- a/src/gpu/effects/GrCustomCoordsTextureEffect.cpp +++ b/src/gpu/effects/GrCustomCoordsTextureEffect.cpp @@ -5,9 +5,9 @@ * found in the LICENSE file. */ +#include "gl/builders/GrGLProgramBuilder.h" #include "GrCustomCoordsTextureEffect.h" #include "gl/GrGLEffect.h" -#include "gl/GrGLShaderBuilder.h" #include "gl/GrGLSL.h" #include "gl/GrGLTexture.h" #include "gl/GrGLVertexEffect.h" @@ -19,7 +19,7 @@ public: GrGLCustomCoordsTextureEffect(const GrBackendEffectFactory& factory, const GrDrawEffect& drawEffect) : INHERITED (factory) {} - virtual void emitCode(GrGLFullShaderBuilder* builder, + virtual void emitCode(GrGLFullProgramBuilder* builder, const GrDrawEffect& drawEffect, const GrEffectKey& key, const char* outputColor, @@ -34,16 +34,18 @@ public: builder->addVarying(kVec2f_GrSLType, "textureCoords", &vsVaryingName, &fsVaryingNamePtr); fsCoordName = fsVaryingNamePtr; - const char* attrName = - builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0])->c_str(); - builder->vsCodeAppendf("\t%s = %s;\n", vsVaryingName, attrName); + GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder(); + const SkString* attr0Name = + vsBuilder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); + vsBuilder->codeAppendf("\t%s = %s;\n", vsVaryingName, attr0Name->c_str()); - builder->fsCodeAppendf("\t%s = ", outputColor); - builder->fsAppendTextureLookupAndModulate(inputColor, + GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); + fsBuilder->codeAppendf("\t%s = ", outputColor); + fsBuilder->appendTextureLookupAndModulate(inputColor, samplers[0], fsCoordName.c_str(), kVec2f_GrSLType); - builder->fsCodeAppend(";\n"); + fsBuilder->codeAppend(";\n"); } virtual void setData(const GrGLProgramDataManager& pdman, diff --git a/src/gpu/effects/GrDashingEffect.cpp b/src/gpu/effects/GrDashingEffect.cpp index f3af65e3b6..4b2bafefdb 100644 --- a/src/gpu/effects/GrDashingEffect.cpp +++ b/src/gpu/effects/GrDashingEffect.cpp @@ -5,6 +5,7 @@ * found in the LICENSE file. */ +#include "gl/builders/GrGLProgramBuilder.h" #include "GrDashingEffect.h" #include "../GrAARectRenderer.h" @@ -12,7 +13,6 @@ #include "effects/GrVertexEffect.h" #include "gl/GrGLEffect.h" #include "gl/GrGLVertexEffect.h" -#include "gl/GrGLShaderBuilder.h" #include "gl/GrGLSL.h" #include "GrContext.h" #include "GrCoordTransform.h" @@ -468,7 +468,7 @@ class GLDashingCircleEffect : public GrGLVertexEffect { public: GLDashingCircleEffect(const GrBackendEffectFactory&, const GrDrawEffect&); - virtual void emitCode(GrGLFullShaderBuilder* builder, + virtual void emitCode(GrGLFullProgramBuilder* builder, const GrDrawEffect& drawEffect, const GrEffectKey& key, const char* outputColor, @@ -496,7 +496,7 @@ GLDashingCircleEffect::GLDashingCircleEffect(const GrBackendEffectFactory& facto fPrevIntervalLength = SK_ScalarMax; } -void GLDashingCircleEffect::emitCode(GrGLFullShaderBuilder* builder, +void GLDashingCircleEffect::emitCode(GrGLFullProgramBuilder* builder, const GrDrawEffect& drawEffect, const GrEffectKey& key, const char* outputColor, @@ -507,32 +507,35 @@ void GLDashingCircleEffect::emitCode(GrGLFullShaderBuilder* builder, const char *paramName; // The param uniforms, xyz, refer to circle radius - 0.5, cicles center x coord, and // the total interval length of the dash. - fParamUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, + fParamUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec3f_GrSLType, "params", ¶mName); const char *vsCoordName, *fsCoordName; builder->addVarying(kVec2f_GrSLType, "Coord", &vsCoordName, &fsCoordName); + + GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder(); const SkString* attr0Name = - builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); - builder->vsCodeAppendf("\t%s = %s;\n", vsCoordName, attr0Name->c_str()); + vsBuilder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); + vsBuilder->codeAppendf("\t%s = %s;\n", vsCoordName, attr0Name->c_str()); // transforms all points so that we can compare them to our test circle - builder->fsCodeAppendf("\t\tfloat xShifted = %s.x - floor(%s.x / %s.z) * %s.z;\n", + GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); + fsBuilder->codeAppendf("\t\tfloat xShifted = %s.x - floor(%s.x / %s.z) * %s.z;\n", fsCoordName, fsCoordName, paramName, paramName); - builder->fsCodeAppendf("\t\tvec2 fragPosShifted = vec2(xShifted, %s.y);\n", fsCoordName); - builder->fsCodeAppendf("\t\tvec2 center = vec2(%s.y, 0.0);\n", paramName); - builder->fsCodeAppend("\t\tfloat dist = length(center - fragPosShifted);\n"); + fsBuilder->codeAppendf("\t\tvec2 fragPosShifted = vec2(xShifted, %s.y);\n", fsCoordName); + fsBuilder->codeAppendf("\t\tvec2 center = vec2(%s.y, 0.0);\n", paramName); + fsBuilder->codeAppend("\t\tfloat dist = length(center - fragPosShifted);\n"); if (GrEffectEdgeTypeIsAA(dce.getEdgeType())) { - builder->fsCodeAppendf("\t\tfloat diff = dist - %s.x;\n", paramName); - builder->fsCodeAppend("\t\tdiff = 1.0 - diff;\n"); - builder->fsCodeAppend("\t\tfloat alpha = clamp(diff, 0.0, 1.0);\n"); + fsBuilder->codeAppendf("\t\tfloat diff = dist - %s.x;\n", paramName); + fsBuilder->codeAppend("\t\tdiff = 1.0 - diff;\n"); + fsBuilder->codeAppend("\t\tfloat alpha = clamp(diff, 0.0, 1.0);\n"); } else { - builder->fsCodeAppendf("\t\tfloat alpha = 1.0;\n"); - builder->fsCodeAppendf("\t\talpha *= dist < %s.x + 0.5 ? 1.0 : 0.0;\n", paramName); + fsBuilder->codeAppendf("\t\tfloat alpha = 1.0;\n"); + fsBuilder->codeAppendf("\t\talpha *= dist < %s.x + 0.5 ? 1.0 : 0.0;\n", paramName); } - builder->fsCodeAppendf("\t\t%s = %s;\n", outputColor, + fsBuilder->codeAppendf("\t\t%s = %s;\n", outputColor, (GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_str()); } @@ -673,7 +676,7 @@ class GLDashingLineEffect : public GrGLVertexEffect { public: GLDashingLineEffect(const GrBackendEffectFactory&, const GrDrawEffect&); - virtual void emitCode(GrGLFullShaderBuilder* builder, + virtual void emitCode(GrGLFullProgramBuilder* builder, const GrDrawEffect& drawEffect, const GrEffectKey& key, const char* outputColor, @@ -700,7 +703,7 @@ GLDashingLineEffect::GLDashingLineEffect(const GrBackendEffectFactory& factory, fPrevIntervalLength = SK_ScalarMax; } -void GLDashingLineEffect::emitCode(GrGLFullShaderBuilder* builder, +void GLDashingLineEffect::emitCode(GrGLFullProgramBuilder* builder, const GrDrawEffect& drawEffect, const GrEffectKey& key, const char* outputColor, @@ -711,45 +714,47 @@ void GLDashingLineEffect::emitCode(GrGLFullShaderBuilder* builder, const char *rectName; // The rect uniform's xyzw refer to (left + 0.5, top + 0.5, right - 0.5, bottom - 0.5), // respectively. - fRectUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, + fRectUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec4f_GrSLType, "rect", &rectName); const char *intervalName; // The interval uniform's refers to the total length of the interval (on + off) - fIntervalUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, + fIntervalUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kFloat_GrSLType, "interval", &intervalName); const char *vsCoordName, *fsCoordName; builder->addVarying(kVec2f_GrSLType, "Coord", &vsCoordName, &fsCoordName); + GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder(); const SkString* attr0Name = - builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); - builder->vsCodeAppendf("\t%s = %s;\n", vsCoordName, attr0Name->c_str()); + vsBuilder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); + vsBuilder->codeAppendf("\t%s = %s;\n", vsCoordName, attr0Name->c_str()); // transforms all points so that we can compare them to our test rect - builder->fsCodeAppendf("\t\tfloat xShifted = %s.x - floor(%s.x / %s) * %s;\n", + GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); + fsBuilder->codeAppendf("\t\tfloat xShifted = %s.x - floor(%s.x / %s) * %s;\n", fsCoordName, fsCoordName, intervalName, intervalName); - builder->fsCodeAppendf("\t\tvec2 fragPosShifted = vec2(xShifted, %s.y);\n", fsCoordName); + fsBuilder->codeAppendf("\t\tvec2 fragPosShifted = vec2(xShifted, %s.y);\n", fsCoordName); if (GrEffectEdgeTypeIsAA(de.getEdgeType())) { // The amount of coverage removed in x and y by the edges is computed as a pair of negative // numbers, xSub and ySub. - builder->fsCodeAppend("\t\tfloat xSub, ySub;\n"); - builder->fsCodeAppendf("\t\txSub = min(fragPosShifted.x - %s.x, 0.0);\n", rectName); - builder->fsCodeAppendf("\t\txSub += min(%s.z - fragPosShifted.x, 0.0);\n", rectName); - builder->fsCodeAppendf("\t\tySub = min(fragPosShifted.y - %s.y, 0.0);\n", rectName); - builder->fsCodeAppendf("\t\tySub += min(%s.w - fragPosShifted.y, 0.0);\n", rectName); + fsBuilder->codeAppend("\t\tfloat xSub, ySub;\n"); + fsBuilder->codeAppendf("\t\txSub = min(fragPosShifted.x - %s.x, 0.0);\n", rectName); + fsBuilder->codeAppendf("\t\txSub += min(%s.z - fragPosShifted.x, 0.0);\n", rectName); + fsBuilder->codeAppendf("\t\tySub = min(fragPosShifted.y - %s.y, 0.0);\n", rectName); + fsBuilder->codeAppendf("\t\tySub += min(%s.w - fragPosShifted.y, 0.0);\n", rectName); // Now compute coverage in x and y and multiply them to get the fraction of the pixel // covered. - builder->fsCodeAppendf("\t\tfloat alpha = (1.0 + max(xSub, -1.0)) * (1.0 + max(ySub, -1.0));\n"); + fsBuilder->codeAppendf("\t\tfloat alpha = (1.0 + max(xSub, -1.0)) * (1.0 + max(ySub, -1.0));\n"); } else { // Assuming the bounding geometry is tight so no need to check y values - builder->fsCodeAppendf("\t\tfloat alpha = 1.0;\n"); - builder->fsCodeAppendf("\t\talpha *= (fragPosShifted.x - %s.x) > -0.5 ? 1.0 : 0.0;\n", rectName); - builder->fsCodeAppendf("\t\talpha *= (%s.z - fragPosShifted.x) >= -0.5 ? 1.0 : 0.0;\n", rectName); + fsBuilder->codeAppendf("\t\tfloat alpha = 1.0;\n"); + fsBuilder->codeAppendf("\t\talpha *= (fragPosShifted.x - %s.x) > -0.5 ? 1.0 : 0.0;\n", rectName); + fsBuilder->codeAppendf("\t\talpha *= (%s.z - fragPosShifted.x) >= -0.5 ? 1.0 : 0.0;\n", rectName); } - builder->fsCodeAppendf("\t\t%s = %s;\n", outputColor, + fsBuilder->codeAppendf("\t\t%s = %s;\n", outputColor, (GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_str()); } diff --git a/src/gpu/effects/GrDistanceFieldTextureEffect.cpp b/src/gpu/effects/GrDistanceFieldTextureEffect.cpp index 7ef1cbb2ba..eaaefebc54 100755 --- a/src/gpu/effects/GrDistanceFieldTextureEffect.cpp +++ b/src/gpu/effects/GrDistanceFieldTextureEffect.cpp @@ -5,9 +5,9 @@ * found in the LICENSE file. */ +#include "gl/builders/GrGLProgramBuilder.h" #include "GrDistanceFieldTextureEffect.h" #include "gl/GrGLEffect.h" -#include "gl/GrGLShaderBuilder.h" #include "gl/GrGLSL.h" #include "gl/GrGLTexture.h" #include "gl/GrGLVertexEffect.h" @@ -36,7 +36,7 @@ public: : INHERITED (factory) , fTextureSize(SkISize::Make(-1,-1)) {} - virtual void emitCode(GrGLFullShaderBuilder* builder, + virtual void emitCode(GrGLFullProgramBuilder* builder, const GrDrawEffect& drawEffect, const GrEffectKey& key, const char* outputColor, @@ -45,7 +45,9 @@ public: const TextureSamplerArray& samplers) SK_OVERRIDE { SkASSERT(1 == drawEffect.castEffect().numVertexAttribs()); - SkAssertResult(builder->enableFeature(GrGLShaderBuilder::kStandardDerivatives_GLSLFeature)); + GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); + SkAssertResult(fsBuilder->enableFeature( + GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature)); const GrDistanceFieldTextureEffect& dfTexEffect = drawEffect.castEffect(); @@ -55,73 +57,74 @@ public: builder->addVarying(kVec2f_GrSLType, "textureCoords", &vsCoordName, &fsCoordNamePtr); fsCoordName = fsCoordNamePtr; - const char* attrName0 = - builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0])->c_str(); - builder->vsCodeAppendf("\t%s = %s;\n", vsCoordName, attrName0); + GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder(); + const SkString* attr0Name = + vsBuilder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); + vsBuilder->codeAppendf("\t%s = %s;\n", vsCoordName, attr0Name->c_str()); const char* textureSizeUniName = NULL; - fTextureSizeUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, + fTextureSizeUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec2f_GrSLType, "TextureSize", &textureSizeUniName); - builder->fsCodeAppend("\tvec4 texColor = "); - builder->fsAppendTextureLookup(samplers[0], + fsBuilder->codeAppend("\tvec4 texColor = "); + fsBuilder->appendTextureLookup(samplers[0], fsCoordName.c_str(), kVec2f_GrSLType); - builder->fsCodeAppend(";\n"); - builder->fsCodeAppend("\tfloat distance = " + fsBuilder->codeAppend(";\n"); + fsBuilder->codeAppend("\tfloat distance = " SK_DistanceFieldMultiplier "*(texColor.r - " SK_DistanceFieldThreshold ")" "+ " SK_DistanceFieldNonLCDFactor ";\n"); // we adjust for the effect of the transformation on the distance by using // the length of the gradient of the texture coordinates. We use st coordinates // to ensure we're mapping 1:1 from texel space to pixel space. - builder->fsCodeAppendf("\tvec2 uv = %s;\n", fsCoordName.c_str()); - builder->fsCodeAppendf("\tvec2 st = uv*%s;\n", textureSizeUniName); - builder->fsCodeAppend("\tfloat afwidth;\n"); + fsBuilder->codeAppendf("\tvec2 uv = %s;\n", fsCoordName.c_str()); + fsBuilder->codeAppendf("\tvec2 st = uv*%s;\n", textureSizeUniName); + fsBuilder->codeAppend("\tfloat afwidth;\n"); if (dfTexEffect.getFlags() & kSimilarity_DistanceFieldEffectFlag) { // this gives us a smooth step across approximately one fragment - builder->fsCodeAppend("\tafwidth = " SK_DistanceFieldAAFactor "*dFdx(st.x);\n"); + fsBuilder->codeAppend("\tafwidth = " SK_DistanceFieldAAFactor "*dFdx(st.x);\n"); } else { - builder->fsCodeAppend("\tvec2 Jdx = dFdx(st);\n"); - builder->fsCodeAppend("\tvec2 Jdy = dFdy(st);\n"); + fsBuilder->codeAppend("\tvec2 Jdx = dFdx(st);\n"); + fsBuilder->codeAppend("\tvec2 Jdy = dFdy(st);\n"); - builder->fsCodeAppend("\tvec2 uv_grad;\n"); + fsBuilder->codeAppend("\tvec2 uv_grad;\n"); if (builder->ctxInfo().caps()->dropsTileOnZeroDivide()) { // this is to compensate for the Adreno, which likes to drop tiles on division by 0 - builder->fsCodeAppend("\tfloat uv_len2 = dot(uv, uv);\n"); - builder->fsCodeAppend("\tif (uv_len2 < 0.0001) {\n"); - builder->fsCodeAppend("\t\tuv_grad = vec2(0.7071, 0.7071);\n"); - builder->fsCodeAppend("\t} else {\n"); - builder->fsCodeAppend("\t\tuv_grad = uv*inversesqrt(uv_len2);\n"); - builder->fsCodeAppend("\t}\n"); + fsBuilder->codeAppend("\tfloat uv_len2 = dot(uv, uv);\n"); + fsBuilder->codeAppend("\tif (uv_len2 < 0.0001) {\n"); + fsBuilder->codeAppend("\t\tuv_grad = vec2(0.7071, 0.7071);\n"); + fsBuilder->codeAppend("\t} else {\n"); + fsBuilder->codeAppend("\t\tuv_grad = uv*inversesqrt(uv_len2);\n"); + fsBuilder->codeAppend("\t}\n"); } else { - builder->fsCodeAppend("\tuv_grad = normalize(uv);\n"); + fsBuilder->codeAppend("\tuv_grad = normalize(uv);\n"); } - builder->fsCodeAppend("\tvec2 grad = vec2(uv_grad.x*Jdx.x + uv_grad.y*Jdy.x,\n"); - builder->fsCodeAppend("\t uv_grad.x*Jdx.y + uv_grad.y*Jdy.y);\n"); + fsBuilder->codeAppend("\tvec2 grad = vec2(uv_grad.x*Jdx.x + uv_grad.y*Jdy.x,\n"); + fsBuilder->codeAppend("\t uv_grad.x*Jdx.y + uv_grad.y*Jdy.y);\n"); // this gives us a smooth step across approximately one fragment - builder->fsCodeAppend("\tafwidth = " SK_DistanceFieldAAFactor "*length(grad);\n"); + fsBuilder->codeAppend("\tafwidth = " SK_DistanceFieldAAFactor "*length(grad);\n"); } - builder->fsCodeAppend("\tfloat val = smoothstep(-afwidth, afwidth, distance);\n"); + fsBuilder->codeAppend("\tfloat val = smoothstep(-afwidth, afwidth, distance);\n"); #ifdef SK_GAMMA_APPLY_TO_A8 // adjust based on gamma const char* luminanceUniName = NULL; // width, height, 1/(3*width) - fLuminanceUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, + fLuminanceUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kFloat_GrSLType, "Luminance", &luminanceUniName); - builder->fsCodeAppendf("\tuv = vec2(val, %s);\n", luminanceUniName); - builder->fsCodeAppend("\tvec4 gammaColor = "); - builder->fsAppendTextureLookup(samplers[1], "uv", kVec2f_GrSLType); - builder->fsCodeAppend(";\n"); - builder->fsCodeAppend("\tval = gammaColor.r;\n"); + fsBuilder->codeAppendf("\tuv = vec2(val, %s);\n", luminanceUniName); + fsBuilder->codeAppend("\tvec4 gammaColor = "); + fsBuilder->appendTextureLookup(samplers[1], "uv", kVec2f_GrSLType); + fsBuilder->codeAppend(";\n"); + fsBuilder->codeAppend("\tval = gammaColor.r;\n"); #endif - builder->fsCodeAppendf("\t%s = %s;\n", outputColor, + fsBuilder->codeAppendf("\t%s = %s;\n", outputColor, (GrGLSLExpr4(inputColor) * GrGLSLExpr1("val")).c_str()); } @@ -261,7 +264,7 @@ public: : INHERITED (factory) , fTextureSize(SkISize::Make(-1,-1)) {} - virtual void emitCode(GrGLFullShaderBuilder* builder, + virtual void emitCode(GrGLFullProgramBuilder* builder, const GrDrawEffect& drawEffect, const GrEffectKey& key, const char* outputColor, @@ -270,7 +273,6 @@ public: const TextureSamplerArray& samplers) SK_OVERRIDE { SkASSERT(1 == drawEffect.castEffect().numVertexAttribs()); - SkAssertResult(builder->enableFeature(GrGLShaderBuilder::kStandardDerivatives_GLSLFeature)); const GrDistanceFieldLCDTextureEffect& dfTexEffect = drawEffect.castEffect(); @@ -280,49 +282,55 @@ public: builder->addVarying(kVec2f_GrSLType, "textureCoords", &vsCoordName, &fsCoordNamePtr); fsCoordName = fsCoordNamePtr; - const char* attrName0 = - builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0])->c_str(); - builder->vsCodeAppendf("\t%s = %s;\n", vsCoordName, attrName0); + GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder(); + const SkString* attr0Name = + vsBuilder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); + vsBuilder->codeAppendf("\t%s = %s;\n", vsCoordName, attr0Name->c_str()); const char* textureSizeUniName = NULL; // width, height, 1/(3*width) - fTextureSizeUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, + fTextureSizeUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec3f_GrSLType, "TextureSize", &textureSizeUniName); + GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); + + SkAssertResult(fsBuilder->enableFeature( + GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature)); + // create LCD offset adjusted by inverse of transform - builder->fsCodeAppendf("\tvec2 uv = %s;\n", fsCoordName.c_str()); - builder->fsCodeAppendf("\tvec2 st = uv*%s.xy;\n", textureSizeUniName); + fsBuilder->codeAppendf("\tvec2 uv = %s;\n", fsCoordName.c_str()); + fsBuilder->codeAppendf("\tvec2 st = uv*%s.xy;\n", textureSizeUniName); bool isUniformScale = !!(dfTexEffect.getFlags() & kUniformScale_DistanceFieldEffectMask); if (isUniformScale) { - builder->fsCodeAppend("\tfloat dx = dFdx(st.x);\n"); - builder->fsCodeAppendf("\tvec2 offset = vec2(dx*%s.z, 0.0);\n", textureSizeUniName); + fsBuilder->codeAppend("\tfloat dx = dFdx(st.x);\n"); + fsBuilder->codeAppendf("\tvec2 offset = vec2(dx*%s.z, 0.0);\n", textureSizeUniName); } else { - builder->fsCodeAppend("\tvec2 Jdx = dFdx(st);\n"); - builder->fsCodeAppend("\tvec2 Jdy = dFdy(st);\n"); - builder->fsCodeAppendf("\tvec2 offset = %s.z*Jdx;\n", textureSizeUniName); + fsBuilder->codeAppend("\tvec2 Jdx = dFdx(st);\n"); + fsBuilder->codeAppend("\tvec2 Jdy = dFdy(st);\n"); + fsBuilder->codeAppendf("\tvec2 offset = %s.z*Jdx;\n", textureSizeUniName); } // green is distance to uv center - builder->fsCodeAppend("\tvec4 texColor = "); - builder->fsAppendTextureLookup(samplers[0], "uv", kVec2f_GrSLType); - builder->fsCodeAppend(";\n"); - builder->fsCodeAppend("\tvec3 distance;\n"); - builder->fsCodeAppend("\tdistance.y = texColor.r;\n"); + fsBuilder->codeAppend("\tvec4 texColor = "); + fsBuilder->appendTextureLookup(samplers[0], "uv", kVec2f_GrSLType); + fsBuilder->codeAppend(";\n"); + fsBuilder->codeAppend("\tvec3 distance;\n"); + fsBuilder->codeAppend("\tdistance.y = texColor.r;\n"); // red is distance to left offset - builder->fsCodeAppend("\tvec2 uv_adjusted = uv - offset;\n"); - builder->fsCodeAppend("\ttexColor = "); - builder->fsAppendTextureLookup(samplers[0], "uv_adjusted", kVec2f_GrSLType); - builder->fsCodeAppend(";\n"); - builder->fsCodeAppend("\tdistance.x = texColor.r;\n"); + fsBuilder->codeAppend("\tvec2 uv_adjusted = uv - offset;\n"); + fsBuilder->codeAppend("\ttexColor = "); + fsBuilder->appendTextureLookup(samplers[0], "uv_adjusted", kVec2f_GrSLType); + fsBuilder->codeAppend(";\n"); + fsBuilder->codeAppend("\tdistance.x = texColor.r;\n"); // blue is distance to right offset - builder->fsCodeAppend("\tuv_adjusted = uv + offset;\n"); - builder->fsCodeAppend("\ttexColor = "); - builder->fsAppendTextureLookup(samplers[0], "uv_adjusted", kVec2f_GrSLType); - builder->fsCodeAppend(";\n"); - builder->fsCodeAppend("\tdistance.z = texColor.r;\n"); + fsBuilder->codeAppend("\tuv_adjusted = uv + offset;\n"); + fsBuilder->codeAppend("\ttexColor = "); + fsBuilder->appendTextureLookup(samplers[0], "uv_adjusted", kVec2f_GrSLType); + fsBuilder->codeAppend(";\n"); + fsBuilder->codeAppend("\tdistance.z = texColor.r;\n"); - builder->fsCodeAppend("\tdistance = " + fsBuilder->codeAppend("\tdistance = " "vec3(" SK_DistanceFieldMultiplier ")*(distance - vec3(" SK_DistanceFieldThreshold"))" "+ vec3(" SK_DistanceFieldLCDFactor ");\n"); @@ -334,58 +342,58 @@ public: // for each color component. However, this is only important when using perspective // transformations, and even then using a single factor seems like a reasonable // trade-off between quality and speed. - builder->fsCodeAppend("\tfloat afwidth;\n"); + fsBuilder->codeAppend("\tfloat afwidth;\n"); if (isUniformScale) { // this gives us a smooth step across approximately one fragment - builder->fsCodeAppend("\tafwidth = " SK_DistanceFieldAAFactor "*dx;\n"); + fsBuilder->codeAppend("\tafwidth = " SK_DistanceFieldAAFactor "*dx;\n"); } else { - builder->fsCodeAppend("\tvec2 uv_grad;\n"); + fsBuilder->codeAppend("\tvec2 uv_grad;\n"); if (builder->ctxInfo().caps()->dropsTileOnZeroDivide()) { // this is to compensate for the Adreno, which likes to drop tiles on division by 0 - builder->fsCodeAppend("\tfloat uv_len2 = dot(uv, uv);\n"); - builder->fsCodeAppend("\tif (uv_len2 < 0.0001) {\n"); - builder->fsCodeAppend("\t\tuv_grad = vec2(0.7071, 0.7071);\n"); - builder->fsCodeAppend("\t} else {\n"); - builder->fsCodeAppend("\t\tuv_grad = uv*inversesqrt(uv_len2);\n"); - builder->fsCodeAppend("\t}\n"); + fsBuilder->codeAppend("\tfloat uv_len2 = dot(uv, uv);\n"); + fsBuilder->codeAppend("\tif (uv_len2 < 0.0001) {\n"); + fsBuilder->codeAppend("\t\tuv_grad = vec2(0.7071, 0.7071);\n"); + fsBuilder->codeAppend("\t} else {\n"); + fsBuilder->codeAppend("\t\tuv_grad = uv*inversesqrt(uv_len2);\n"); + fsBuilder->codeAppend("\t}\n"); } else { - builder->fsCodeAppend("\tuv_grad = normalize(uv);\n"); + fsBuilder->codeAppend("\tuv_grad = normalize(uv);\n"); } - builder->fsCodeAppend("\tvec2 grad = vec2(uv_grad.x*Jdx.x + uv_grad.y*Jdy.x,\n"); - builder->fsCodeAppend("\t uv_grad.x*Jdx.y + uv_grad.y*Jdy.y);\n"); + fsBuilder->codeAppend("\tvec2 grad = vec2(uv_grad.x*Jdx.x + uv_grad.y*Jdy.x,\n"); + fsBuilder->codeAppend("\t uv_grad.x*Jdx.y + uv_grad.y*Jdy.y);\n"); // this gives us a smooth step across approximately one fragment - builder->fsCodeAppend("\tafwidth = " SK_DistanceFieldAAFactor "*length(grad);\n"); + fsBuilder->codeAppend("\tafwidth = " SK_DistanceFieldAAFactor "*length(grad);\n"); } - builder->fsCodeAppend("\tvec4 val = vec4(smoothstep(vec3(-afwidth), vec3(afwidth), distance), 1.0);\n"); + fsBuilder->codeAppend("\tvec4 val = vec4(smoothstep(vec3(-afwidth), vec3(afwidth), distance), 1.0);\n"); // adjust based on gamma const char* textColorUniName = NULL; // width, height, 1/(3*width) - fTextColorUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, + fTextColorUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec3f_GrSLType, "TextColor", &textColorUniName); - builder->fsCodeAppendf("\tuv = vec2(val.x, %s.x);\n", textColorUniName); - builder->fsCodeAppend("\tvec4 gammaColor = "); - builder->fsAppendTextureLookup(samplers[1], "uv", kVec2f_GrSLType); - builder->fsCodeAppend(";\n"); - builder->fsCodeAppend("\tval.x = gammaColor.r;\n"); - - builder->fsCodeAppendf("\tuv = vec2(val.y, %s.y);\n", textColorUniName); - builder->fsCodeAppend("\tgammaColor = "); - builder->fsAppendTextureLookup(samplers[1], "uv", kVec2f_GrSLType); - builder->fsCodeAppend(";\n"); - builder->fsCodeAppend("\tval.y = gammaColor.r;\n"); - - builder->fsCodeAppendf("\tuv = vec2(val.z, %s.z);\n", textColorUniName); - builder->fsCodeAppend("\tgammaColor = "); - builder->fsAppendTextureLookup(samplers[1], "uv", kVec2f_GrSLType); - builder->fsCodeAppend(";\n"); - builder->fsCodeAppend("\tval.z = gammaColor.r;\n"); - - builder->fsCodeAppendf("\t%s = %s;\n", outputColor, + fsBuilder->codeAppendf("\tuv = vec2(val.x, %s.x);\n", textColorUniName); + fsBuilder->codeAppend("\tvec4 gammaColor = "); + fsBuilder->appendTextureLookup(samplers[1], "uv", kVec2f_GrSLType); + fsBuilder->codeAppend(";\n"); + fsBuilder->codeAppend("\tval.x = gammaColor.r;\n"); + + fsBuilder->codeAppendf("\tuv = vec2(val.y, %s.y);\n", textColorUniName); + fsBuilder->codeAppend("\tgammaColor = "); + fsBuilder->appendTextureLookup(samplers[1], "uv", kVec2f_GrSLType); + fsBuilder->codeAppend(";\n"); + fsBuilder->codeAppend("\tval.y = gammaColor.r;\n"); + + fsBuilder->codeAppendf("\tuv = vec2(val.z, %s.z);\n", textColorUniName); + fsBuilder->codeAppend("\tgammaColor = "); + fsBuilder->appendTextureLookup(samplers[1], "uv", kVec2f_GrSLType); + fsBuilder->codeAppend(";\n"); + fsBuilder->codeAppend("\tval.z = gammaColor.r;\n"); + + fsBuilder->codeAppendf("\t%s = %s;\n", outputColor, (GrGLSLExpr4(inputColor) * GrGLSLExpr4("val")).c_str()); } diff --git a/src/gpu/effects/GrDistanceFieldTextureEffect.h b/src/gpu/effects/GrDistanceFieldTextureEffect.h index ab84753fff..dca1949c50 100644 --- a/src/gpu/effects/GrDistanceFieldTextureEffect.h +++ b/src/gpu/effects/GrDistanceFieldTextureEffect.h @@ -86,7 +86,7 @@ private: GR_DECLARE_EFFECT_TEST; - typedef GrVertexEffect INHERITED; + typedef GrEffect INHERITED; }; /** @@ -131,7 +131,7 @@ private: GR_DECLARE_EFFECT_TEST; - typedef GrVertexEffect INHERITED; + typedef GrEffect INHERITED; }; #endif diff --git a/src/gpu/effects/GrDitherEffect.cpp b/src/gpu/effects/GrDitherEffect.cpp index a431897a4e..443df9ed36 100644 --- a/src/gpu/effects/GrDitherEffect.cpp +++ b/src/gpu/effects/GrDitherEffect.cpp @@ -5,10 +5,10 @@ * found in the LICENSE file. */ +#include "gl/builders/GrGLProgramBuilder.h" #include "GrDitherEffect.h" #include "gl/GrGLEffect.h" -#include "gl/GrGLShaderBuilder.h" #include "gl/GrGLSL.h" #include "GrTBackendEffectFactory.h" @@ -70,7 +70,7 @@ class GLDitherEffect : public GrGLEffect { public: GLDitherEffect(const GrBackendEffectFactory&, const GrDrawEffect&); - virtual void emitCode(GrGLShaderBuilder* builder, + virtual void emitCode(GrGLProgramBuilder* builder, const GrDrawEffect& drawEffect, const GrEffectKey& key, const char* outputColor, @@ -87,13 +87,14 @@ GLDitherEffect::GLDitherEffect(const GrBackendEffectFactory& factory, : INHERITED (factory) { } -void GLDitherEffect::emitCode(GrGLShaderBuilder* builder, +void GLDitherEffect::emitCode(GrGLProgramBuilder* builder, const GrDrawEffect& drawEffect, const GrEffectKey& key, const char* outputColor, const char* inputColor, const TransformedCoordsArray&, const TextureSamplerArray& samplers) { + GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); // Generate a random number based on the fragment position. For this // random number generator, we use the "GLSL rand" function // that seems to be floating around on the internet. It works under @@ -103,10 +104,10 @@ void GLDitherEffect::emitCode(GrGLShaderBuilder* builder, // For each channel c, add the random offset to the pixel to either bump // it up or let it remain constant during quantization. - builder->fsCodeAppendf("\t\tfloat r = " + fsBuilder->codeAppendf("\t\tfloat r = " "fract(sin(dot(%s.xy ,vec2(12.9898,78.233))) * 43758.5453);\n", - builder->fragmentPosition()); - builder->fsCodeAppendf("\t\t%s = (1.0/255.0) * vec4(r, r, r, r) + %s;\n", + fsBuilder->fragmentPosition()); + fsBuilder->codeAppendf("\t\t%s = (1.0/255.0) * vec4(r, r, r, r) + %s;\n", outputColor, GrGLSLExpr4(inputColor).c_str()); } diff --git a/src/gpu/effects/GrMatrixConvolutionEffect.cpp b/src/gpu/effects/GrMatrixConvolutionEffect.cpp index 01cf944592..e573996e80 100644 --- a/src/gpu/effects/GrMatrixConvolutionEffect.cpp +++ b/src/gpu/effects/GrMatrixConvolutionEffect.cpp @@ -4,8 +4,8 @@ * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ +#include "gl/builders/GrGLProgramBuilder.h" #include "GrMatrixConvolutionEffect.h" -#include "gl/GrGLShaderBuilder.h" #include "gl/GrGLEffect.h" #include "gl/GrGLSL.h" #include "gl/GrGLTexture.h" @@ -15,7 +15,7 @@ class GrGLMatrixConvolutionEffect : public GrGLEffect { public: GrGLMatrixConvolutionEffect(const GrBackendEffectFactory& factory, const GrDrawEffect& effect); - virtual void emitCode(GrGLShaderBuilder*, + virtual void emitCode(GrGLProgramBuilder*, const GrDrawEffect&, const GrEffectKey&, const char* outputColor, @@ -51,7 +51,7 @@ GrGLMatrixConvolutionEffect::GrGLMatrixConvolutionEffect(const GrBackendEffectFa fConvolveAlpha = m.convolveAlpha(); } -void GrGLMatrixConvolutionEffect::emitCode(GrGLShaderBuilder* builder, +void GrGLMatrixConvolutionEffect::emitCode(GrGLProgramBuilder* builder, const GrDrawEffect& drawEffect, const GrEffectKey& key, const char* outputColor, @@ -60,20 +60,20 @@ void GrGLMatrixConvolutionEffect::emitCode(GrGLShaderBuilder* builder, const TextureSamplerArray& samplers) { sk_ignore_unused_variable(inputColor); const GrTextureDomain& domain = drawEffect.castEffect().domain(); - SkString coords2D = builder->ensureFSCoords2D(coords, 0); - fBoundsUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, + + fBoundsUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec4f_GrSLType, "Bounds"); - fImageIncrementUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, + fImageIncrementUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec2f_GrSLType, "ImageIncrement"); - fKernelUni = builder->addUniformArray(GrGLShaderBuilder::kFragment_Visibility, + fKernelUni = builder->addUniformArray(GrGLProgramBuilder::kFragment_Visibility, kFloat_GrSLType, "Kernel", fKernelSize.width() * fKernelSize.height()); - fKernelOffsetUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, + fKernelOffsetUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec2f_GrSLType, "KernelOffset"); - fGainUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, + fGainUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kFloat_GrSLType, "Gain"); - fBiasUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, + fBiasUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kFloat_GrSLType, "Bias"); const char* kernelOffset = builder->getUniformCStr(fKernelOffsetUni); @@ -84,38 +84,40 @@ void GrGLMatrixConvolutionEffect::emitCode(GrGLShaderBuilder* builder, int kWidth = fKernelSize.width(); int kHeight = fKernelSize.height(); - builder->fsCodeAppend("vec4 sum = vec4(0, 0, 0, 0);"); - builder->fsCodeAppendf("vec2 coord = %s - %s * %s;", coords2D.c_str(), kernelOffset, + GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); + SkString coords2D = fsBuilder->ensureFSCoords2D(coords, 0); + fsBuilder->codeAppend("vec4 sum = vec4(0, 0, 0, 0);"); + fsBuilder->codeAppendf("vec2 coord = %s - %s * %s;", coords2D.c_str(), kernelOffset, imgInc); - builder->fsCodeAppend("vec4 c;"); + fsBuilder->codeAppend("vec4 c;"); for (int y = 0; y < kHeight; y++) { for (int x = 0; x < kWidth; x++) { - GrGLShaderBuilder::FSBlock block(builder); - builder->fsCodeAppendf("float k = %s[%d * %d + %d];", kernel, y, kWidth, x); + GrGLShaderBuilder::ShaderBlock block(fsBuilder); + fsBuilder->codeAppendf("float k = %s[%d * %d + %d];", kernel, y, kWidth, x); SkString coord; coord.printf("coord + vec2(%d, %d) * %s", x, y, imgInc); - fDomain.sampleTexture(builder, domain, "c", coord, samplers[0]); + fDomain.sampleTexture(fsBuilder, domain, "c", coord, samplers[0]); if (!fConvolveAlpha) { - builder->fsCodeAppend("c.rgb /= c.a;"); + fsBuilder->codeAppend("c.rgb /= c.a;"); } - builder->fsCodeAppend("sum += c * k;"); + fsBuilder->codeAppend("sum += c * k;"); } } if (fConvolveAlpha) { - builder->fsCodeAppendf("%s = sum * %s + %s;", outputColor, gain, bias); - builder->fsCodeAppendf("%s.rgb = clamp(%s.rgb, 0.0, %s.a);", + fsBuilder->codeAppendf("%s = sum * %s + %s;", outputColor, gain, bias); + fsBuilder->codeAppendf("%s.rgb = clamp(%s.rgb, 0.0, %s.a);", outputColor, outputColor, outputColor); } else { - fDomain.sampleTexture(builder, domain, "c", coords2D, samplers[0]); - builder->fsCodeAppendf("%s.a = c.a;", outputColor); - builder->fsCodeAppendf("%s.rgb = sum.rgb * %s + %s;", outputColor, gain, bias); - builder->fsCodeAppendf("%s.rgb *= %s.a;", outputColor, outputColor); + fDomain.sampleTexture(fsBuilder, domain, "c", coords2D, samplers[0]); + fsBuilder->codeAppendf("%s.a = c.a;", outputColor); + fsBuilder->codeAppendf("%s.rgb = sum.rgb * %s + %s;", outputColor, gain, bias); + fsBuilder->codeAppendf("%s.rgb *= %s.a;", outputColor, outputColor); } SkString modulate; GrGLSLMulVarBy4f(&modulate, 2, outputColor, inputColor); - builder->fsCodeAppend(modulate.c_str()); + fsBuilder->codeAppend(modulate.c_str()); } void GrGLMatrixConvolutionEffect::GenKey(const GrDrawEffect& drawEffect, diff --git a/src/gpu/effects/GrOvalEffect.cpp b/src/gpu/effects/GrOvalEffect.cpp index d915250fe5..369b78042c 100644 --- a/src/gpu/effects/GrOvalEffect.cpp +++ b/src/gpu/effects/GrOvalEffect.cpp @@ -5,10 +5,10 @@ * found in the LICENSE file. */ +#include "gl/builders/GrGLProgramBuilder.h" #include "GrOvalEffect.h" #include "gl/GrGLEffect.h" -#include "gl/GrGLShaderBuilder.h" #include "gl/GrGLSL.h" #include "GrTBackendEffectFactory.h" @@ -100,7 +100,7 @@ class GLCircleEffect : public GrGLEffect { public: GLCircleEffect(const GrBackendEffectFactory&, const GrDrawEffect&); - virtual void emitCode(GrGLShaderBuilder* builder, + virtual void emitCode(GrGLProgramBuilder* builder, const GrDrawEffect& drawEffect, const GrEffectKey& key, const char* outputColor, @@ -126,7 +126,7 @@ GLCircleEffect::GLCircleEffect(const GrBackendEffectFactory& factory, fPrevRadius = -1.f; } -void GLCircleEffect::emitCode(GrGLShaderBuilder* builder, +void GLCircleEffect::emitCode(GrGLProgramBuilder* builder, const GrDrawEffect& drawEffect, const GrEffectKey& key, const char* outputColor, @@ -137,27 +137,29 @@ void GLCircleEffect::emitCode(GrGLShaderBuilder* builder, const char *circleName; // The circle uniform is (center.x, center.y, radius + 0.5) for regular fills and // (... ,radius - 0.5) for inverse fills. - fCircleUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, + fCircleUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec3f_GrSLType, "circle", &circleName); - const char* fragmentPos = builder->fragmentPosition(); + + GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); + const char* fragmentPos = fsBuilder->fragmentPosition(); SkASSERT(kHairlineAA_GrEffectEdgeType != ce.getEdgeType()); if (GrEffectEdgeTypeIsInverseFill(ce.getEdgeType())) { - builder->fsCodeAppendf("\t\tfloat d = length(%s.xy - %s.xy) - %s.z;\n", + fsBuilder->codeAppendf("\t\tfloat d = length(%s.xy - %s.xy) - %s.z;\n", circleName, fragmentPos, circleName); } else { - builder->fsCodeAppendf("\t\tfloat d = %s.z - length(%s.xy - %s.xy);\n", + fsBuilder->codeAppendf("\t\tfloat d = %s.z - length(%s.xy - %s.xy);\n", circleName, fragmentPos, circleName); } if (GrEffectEdgeTypeIsAA(ce.getEdgeType())) { - builder->fsCodeAppend("\t\td = clamp(d, 0.0, 1.0);\n"); + fsBuilder->codeAppend("\t\td = clamp(d, 0.0, 1.0);\n"); } else { - builder->fsCodeAppend("\t\td = d > 0.5 ? 1.0 : 0.0;\n"); + fsBuilder->codeAppend("\t\td = d > 0.5 ? 1.0 : 0.0;\n"); } - builder->fsCodeAppendf("\t\t%s = %s;\n", outputColor, + fsBuilder->codeAppendf("\t\t%s = %s;\n", outputColor, (GrGLSLExpr4(inputColor) * GrGLSLExpr1("d")).c_str()); } @@ -272,7 +274,7 @@ class GLEllipseEffect : public GrGLEffect { public: GLEllipseEffect(const GrBackendEffectFactory&, const GrDrawEffect&); - virtual void emitCode(GrGLShaderBuilder* builder, + virtual void emitCode(GrGLProgramBuilder* builder, const GrDrawEffect& drawEffect, const GrEffectKey& key, const char* outputColor, @@ -298,7 +300,7 @@ GLEllipseEffect::GLEllipseEffect(const GrBackendEffectFactory& factory, fPrevRadii.fX = -1.f; } -void GLEllipseEffect::emitCode(GrGLShaderBuilder* builder, +void GLEllipseEffect::emitCode(GrGLProgramBuilder* builder, const GrDrawEffect& drawEffect, const GrEffectKey& key, const char* outputColor, @@ -308,41 +310,43 @@ void GLEllipseEffect::emitCode(GrGLShaderBuilder* builder, const EllipseEffect& ee = drawEffect.castEffect(); const char *ellipseName; // The ellipse uniform is (center.x, center.y, 1 / rx^2, 1 / ry^2) - fEllipseUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, + fEllipseUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec4f_GrSLType, "ellipse", &ellipseName); - const char* fragmentPos = builder->fragmentPosition(); + + GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); + const char* fragmentPos = fsBuilder->fragmentPosition(); // d is the offset to the ellipse center - builder->fsCodeAppendf("\t\tvec2 d = %s.xy - %s.xy;\n", fragmentPos, ellipseName); - builder->fsCodeAppendf("\t\tvec2 Z = d * %s.zw;\n", ellipseName); + fsBuilder->codeAppendf("\t\tvec2 d = %s.xy - %s.xy;\n", fragmentPos, ellipseName); + fsBuilder->codeAppendf("\t\tvec2 Z = d * %s.zw;\n", ellipseName); // implicit is the evaluation of (x/rx)^2 + (y/ry)^2 - 1. - builder->fsCodeAppend("\t\tfloat implicit = dot(Z, d) - 1.0;\n"); + fsBuilder->codeAppend("\t\tfloat implicit = dot(Z, d) - 1.0;\n"); // grad_dot is the squared length of the gradient of the implicit. - builder->fsCodeAppendf("\t\tfloat grad_dot = 4.0 * dot(Z, Z);\n"); + fsBuilder->codeAppendf("\t\tfloat grad_dot = 4.0 * dot(Z, Z);\n"); // avoid calling inversesqrt on zero. - builder->fsCodeAppend("\t\tgrad_dot = max(grad_dot, 1.0e-4);\n"); - builder->fsCodeAppendf("\t\tfloat approx_dist = implicit * inversesqrt(grad_dot);\n"); + fsBuilder->codeAppend("\t\tgrad_dot = max(grad_dot, 1.0e-4);\n"); + fsBuilder->codeAppendf("\t\tfloat approx_dist = implicit * inversesqrt(grad_dot);\n"); switch (ee.getEdgeType()) { case kFillAA_GrEffectEdgeType: - builder->fsCodeAppend("\t\tfloat alpha = clamp(0.5 - approx_dist, 0.0, 1.0);\n"); + fsBuilder->codeAppend("\t\tfloat alpha = clamp(0.5 - approx_dist, 0.0, 1.0);\n"); break; case kInverseFillAA_GrEffectEdgeType: - builder->fsCodeAppend("\t\tfloat alpha = clamp(0.5 + approx_dist, 0.0, 1.0);\n"); + fsBuilder->codeAppend("\t\tfloat alpha = clamp(0.5 + approx_dist, 0.0, 1.0);\n"); break; case kFillBW_GrEffectEdgeType: - builder->fsCodeAppend("\t\tfloat alpha = approx_dist > 0.0 ? 0.0 : 1.0;\n"); + fsBuilder->codeAppend("\t\tfloat alpha = approx_dist > 0.0 ? 0.0 : 1.0;\n"); break; case kInverseFillBW_GrEffectEdgeType: - builder->fsCodeAppend("\t\tfloat alpha = approx_dist > 0.0 ? 1.0 : 0.0;\n"); + fsBuilder->codeAppend("\t\tfloat alpha = approx_dist > 0.0 ? 1.0 : 0.0;\n"); break; case kHairlineAA_GrEffectEdgeType: SkFAIL("Hairline not expected here."); } - builder->fsCodeAppendf("\t\t%s = %s;\n", outputColor, + fsBuilder->codeAppendf("\t\t%s = %s;\n", outputColor, (GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_str()); } diff --git a/src/gpu/effects/GrRRectEffect.cpp b/src/gpu/effects/GrRRectEffect.cpp index 5a2b0c3d59..8a3fc44704 100644 --- a/src/gpu/effects/GrRRectEffect.cpp +++ b/src/gpu/effects/GrRRectEffect.cpp @@ -5,10 +5,10 @@ * found in the LICENSE file. */ +#include "gl/builders/GrGLProgramBuilder.h" #include "GrRRectEffect.h" #include "gl/GrGLEffect.h" -#include "gl/GrGLShaderBuilder.h" #include "gl/GrGLSL.h" #include "GrConvexPolyEffect.h" #include "GrOvalEffect.h" @@ -134,7 +134,7 @@ class GLCircularRRectEffect : public GrGLEffect { public: GLCircularRRectEffect(const GrBackendEffectFactory&, const GrDrawEffect&); - virtual void emitCode(GrGLShaderBuilder* builder, + virtual void emitCode(GrGLProgramBuilder* builder, const GrDrawEffect& drawEffect, const GrEffectKey& key, const char* outputColor, @@ -159,7 +159,7 @@ GLCircularRRectEffect::GLCircularRRectEffect(const GrBackendEffectFactory& facto fPrevRRect.setEmpty(); } -void GLCircularRRectEffect::emitCode(GrGLShaderBuilder* builder, +void GLCircularRRectEffect::emitCode(GrGLProgramBuilder* builder, const GrDrawEffect& drawEffect, const GrEffectKey& key, const char* outputColor, @@ -173,15 +173,17 @@ void GLCircularRRectEffect::emitCode(GrGLShaderBuilder* builder, // edges correspond to components x, y, z, and w, respectively. When a side of the rrect has // only rectangular corners, that side's value corresponds to the rect edge's value outset by // half a pixel. - fInnerRectUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, + fInnerRectUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec4f_GrSLType, "innerRect", &rectName); - fRadiusPlusHalfUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, + fRadiusPlusHalfUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kFloat_GrSLType, "radiusPlusHalf", &radiusPlusHalfName); - const char* fragmentPos = builder->fragmentPosition(); + + GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); + const char* fragmentPos = fsBuilder->fragmentPosition(); // At each quarter-circle corner we compute a vector that is the offset of the fragment position // from the circle center. The vector is pinned in x and y to be in the quarter-plane relevant // to that corner. This means that points near the interior near the rrect top edge will have @@ -199,95 +201,95 @@ void GLCircularRRectEffect::emitCode(GrGLShaderBuilder* builder, // alphas together. switch (crre.getCircularCornerFlags()) { case CircularRRectEffect::kAll_CornerFlags: - builder->fsCodeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName, fragmentPos); - builder->fsCodeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentPos, rectName); - builder->fsCodeAppend("\t\tvec2 dxy = max(max(dxy0, dxy1), 0.0);\n"); - builder->fsCodeAppendf("\t\tfloat alpha = clamp(%s - length(dxy), 0.0, 1.0);\n", + fsBuilder->codeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName, fragmentPos); + fsBuilder->codeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentPos, rectName); + fsBuilder->codeAppend("\t\tvec2 dxy = max(max(dxy0, dxy1), 0.0);\n"); + fsBuilder->codeAppendf("\t\tfloat alpha = clamp(%s - length(dxy), 0.0, 1.0);\n", radiusPlusHalfName); break; case CircularRRectEffect::kTopLeft_CornerFlag: - builder->fsCodeAppendf("\t\tvec2 dxy = max(%s.xy - %s.xy, 0.0);\n", + fsBuilder->codeAppendf("\t\tvec2 dxy = max(%s.xy - %s.xy, 0.0);\n", rectName, fragmentPos); - builder->fsCodeAppendf("\t\tfloat rightAlpha = clamp(%s.z - %s.x, 0.0, 1.0);\n", + fsBuilder->codeAppendf("\t\tfloat rightAlpha = clamp(%s.z - %s.x, 0.0, 1.0);\n", rectName, fragmentPos); - builder->fsCodeAppendf("\t\tfloat bottomAlpha = clamp(%s.w - %s.y, 0.0, 1.0);\n", + fsBuilder->codeAppendf("\t\tfloat bottomAlpha = clamp(%s.w - %s.y, 0.0, 1.0);\n", rectName, fragmentPos); - builder->fsCodeAppendf("\t\tfloat alpha = bottomAlpha * rightAlpha * clamp(%s - length(dxy), 0.0, 1.0);\n", + fsBuilder->codeAppendf("\t\tfloat alpha = bottomAlpha * rightAlpha * clamp(%s - length(dxy), 0.0, 1.0);\n", radiusPlusHalfName); break; case CircularRRectEffect::kTopRight_CornerFlag: - builder->fsCodeAppendf("\t\tvec2 dxy = max(vec2(%s.x - %s.z, %s.y - %s.y), 0.0);\n", + fsBuilder->codeAppendf("\t\tvec2 dxy = max(vec2(%s.x - %s.z, %s.y - %s.y), 0.0);\n", fragmentPos, rectName, rectName, fragmentPos); - builder->fsCodeAppendf("\t\tfloat leftAlpha = clamp(%s.x - %s.x, 0.0, 1.0);\n", + fsBuilder->codeAppendf("\t\tfloat leftAlpha = clamp(%s.x - %s.x, 0.0, 1.0);\n", fragmentPos, rectName); - builder->fsCodeAppendf("\t\tfloat bottomAlpha = clamp(%s.w - %s.y, 0.0, 1.0);\n", + fsBuilder->codeAppendf("\t\tfloat bottomAlpha = clamp(%s.w - %s.y, 0.0, 1.0);\n", rectName, fragmentPos); - builder->fsCodeAppendf("\t\tfloat alpha = bottomAlpha * leftAlpha * clamp(%s - length(dxy), 0.0, 1.0);\n", + fsBuilder->codeAppendf("\t\tfloat alpha = bottomAlpha * leftAlpha * clamp(%s - length(dxy), 0.0, 1.0);\n", radiusPlusHalfName); break; case CircularRRectEffect::kBottomRight_CornerFlag: - builder->fsCodeAppendf("\t\tvec2 dxy = max(%s.xy - %s.zw, 0.0);\n", + fsBuilder->codeAppendf("\t\tvec2 dxy = max(%s.xy - %s.zw, 0.0);\n", fragmentPos, rectName); - builder->fsCodeAppendf("\t\tfloat leftAlpha = clamp(%s.x - %s.x, 0.0, 1.0);\n", + fsBuilder->codeAppendf("\t\tfloat leftAlpha = clamp(%s.x - %s.x, 0.0, 1.0);\n", fragmentPos, rectName); - builder->fsCodeAppendf("\t\tfloat topAlpha = clamp(%s.y - %s.y, 0.0, 1.0);\n", + fsBuilder->codeAppendf("\t\tfloat topAlpha = clamp(%s.y - %s.y, 0.0, 1.0);\n", fragmentPos, rectName); - builder->fsCodeAppendf("\t\tfloat alpha = topAlpha * leftAlpha * clamp(%s - length(dxy), 0.0, 1.0);\n", + fsBuilder->codeAppendf("\t\tfloat alpha = topAlpha * leftAlpha * clamp(%s - length(dxy), 0.0, 1.0);\n", radiusPlusHalfName); break; case CircularRRectEffect::kBottomLeft_CornerFlag: - builder->fsCodeAppendf("\t\tvec2 dxy = max(vec2(%s.x - %s.x, %s.y - %s.w), 0.0);\n", + fsBuilder->codeAppendf("\t\tvec2 dxy = max(vec2(%s.x - %s.x, %s.y - %s.w), 0.0);\n", rectName, fragmentPos, fragmentPos, rectName); - builder->fsCodeAppendf("\t\tfloat rightAlpha = clamp(%s.z - %s.x, 0.0, 1.0);\n", + fsBuilder->codeAppendf("\t\tfloat rightAlpha = clamp(%s.z - %s.x, 0.0, 1.0);\n", rectName, fragmentPos); - builder->fsCodeAppendf("\t\tfloat topAlpha = clamp(%s.y - %s.y, 0.0, 1.0);\n", + fsBuilder->codeAppendf("\t\tfloat topAlpha = clamp(%s.y - %s.y, 0.0, 1.0);\n", fragmentPos, rectName); - builder->fsCodeAppendf("\t\tfloat alpha = topAlpha * rightAlpha * clamp(%s - length(dxy), 0.0, 1.0);\n", + fsBuilder->codeAppendf("\t\tfloat alpha = topAlpha * rightAlpha * clamp(%s - length(dxy), 0.0, 1.0);\n", radiusPlusHalfName); break; case CircularRRectEffect::kLeft_CornerFlags: - builder->fsCodeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName, fragmentPos); - builder->fsCodeAppendf("\t\tfloat dy1 = %s.y - %s.w;\n", fragmentPos, rectName); - builder->fsCodeAppend("\t\tvec2 dxy = max(vec2(dxy0.x, max(dxy0.y, dy1)), 0.0);\n"); - builder->fsCodeAppendf("\t\tfloat rightAlpha = clamp(%s.z - %s.x, 0.0, 1.0);\n", + fsBuilder->codeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName, fragmentPos); + fsBuilder->codeAppendf("\t\tfloat dy1 = %s.y - %s.w;\n", fragmentPos, rectName); + fsBuilder->codeAppend("\t\tvec2 dxy = max(vec2(dxy0.x, max(dxy0.y, dy1)), 0.0);\n"); + fsBuilder->codeAppendf("\t\tfloat rightAlpha = clamp(%s.z - %s.x, 0.0, 1.0);\n", rectName, fragmentPos); - builder->fsCodeAppendf("\t\tfloat alpha = rightAlpha * clamp(%s - length(dxy), 0.0, 1.0);\n", + fsBuilder->codeAppendf("\t\tfloat alpha = rightAlpha * clamp(%s - length(dxy), 0.0, 1.0);\n", radiusPlusHalfName); break; case CircularRRectEffect::kTop_CornerFlags: - builder->fsCodeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName, fragmentPos); - builder->fsCodeAppendf("\t\tfloat dx1 = %s.x - %s.z;\n", fragmentPos, rectName); - builder->fsCodeAppend("\t\tvec2 dxy = max(vec2(max(dxy0.x, dx1), dxy0.y), 0.0);\n"); - builder->fsCodeAppendf("\t\tfloat bottomAlpha = clamp(%s.w - %s.y, 0.0, 1.0);\n", + fsBuilder->codeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName, fragmentPos); + fsBuilder->codeAppendf("\t\tfloat dx1 = %s.x - %s.z;\n", fragmentPos, rectName); + fsBuilder->codeAppend("\t\tvec2 dxy = max(vec2(max(dxy0.x, dx1), dxy0.y), 0.0);\n"); + fsBuilder->codeAppendf("\t\tfloat bottomAlpha = clamp(%s.w - %s.y, 0.0, 1.0);\n", rectName, fragmentPos); - builder->fsCodeAppendf("\t\tfloat alpha = bottomAlpha * clamp(%s - length(dxy), 0.0, 1.0);\n", + fsBuilder->codeAppendf("\t\tfloat alpha = bottomAlpha * clamp(%s - length(dxy), 0.0, 1.0);\n", radiusPlusHalfName); break; case CircularRRectEffect::kRight_CornerFlags: - builder->fsCodeAppendf("\t\tfloat dy0 = %s.y - %s.y;\n", rectName, fragmentPos); - builder->fsCodeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentPos, rectName); - builder->fsCodeAppend("\t\tvec2 dxy = max(vec2(dxy1.x, max(dy0, dxy1.y)), 0.0);\n"); - builder->fsCodeAppendf("\t\tfloat leftAlpha = clamp(%s.x - %s.x, 0.0, 1.0);\n", + fsBuilder->codeAppendf("\t\tfloat dy0 = %s.y - %s.y;\n", rectName, fragmentPos); + fsBuilder->codeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentPos, rectName); + fsBuilder->codeAppend("\t\tvec2 dxy = max(vec2(dxy1.x, max(dy0, dxy1.y)), 0.0);\n"); + fsBuilder->codeAppendf("\t\tfloat leftAlpha = clamp(%s.x - %s.x, 0.0, 1.0);\n", fragmentPos, rectName); - builder->fsCodeAppendf("\t\tfloat alpha = leftAlpha * clamp(%s - length(dxy), 0.0, 1.0);\n", + fsBuilder->codeAppendf("\t\tfloat alpha = leftAlpha * clamp(%s - length(dxy), 0.0, 1.0);\n", radiusPlusHalfName); break; case CircularRRectEffect::kBottom_CornerFlags: - builder->fsCodeAppendf("\t\tfloat dx0 = %s.x - %s.x;\n", rectName, fragmentPos); - builder->fsCodeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentPos, rectName); - builder->fsCodeAppend("\t\tvec2 dxy = max(vec2(max(dx0, dxy1.x), dxy1.y), 0.0);\n"); - builder->fsCodeAppendf("\t\tfloat topAlpha = clamp(%s.y - %s.y, 0.0, 1.0);\n", + fsBuilder->codeAppendf("\t\tfloat dx0 = %s.x - %s.x;\n", rectName, fragmentPos); + fsBuilder->codeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentPos, rectName); + fsBuilder->codeAppend("\t\tvec2 dxy = max(vec2(max(dx0, dxy1.x), dxy1.y), 0.0);\n"); + fsBuilder->codeAppendf("\t\tfloat topAlpha = clamp(%s.y - %s.y, 0.0, 1.0);\n", fragmentPos, rectName); - builder->fsCodeAppendf("\t\tfloat alpha = topAlpha * clamp(%s - length(dxy), 0.0, 1.0);\n", + fsBuilder->codeAppendf("\t\tfloat alpha = topAlpha * clamp(%s - length(dxy), 0.0, 1.0);\n", radiusPlusHalfName); break; } if (kInverseFillAA_GrEffectEdgeType == crre.getEdgeType()) { - builder->fsCodeAppend("\t\talpha = 1.0 - alpha;\n"); + fsBuilder->codeAppend("\t\talpha = 1.0 - alpha;\n"); } - builder->fsCodeAppendf("\t\t%s = %s;\n", outputColor, + fsBuilder->codeAppendf("\t\t%s = %s;\n", outputColor, (GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_str()); } @@ -486,7 +488,7 @@ class GLEllipticalRRectEffect : public GrGLEffect { public: GLEllipticalRRectEffect(const GrBackendEffectFactory&, const GrDrawEffect&); - virtual void emitCode(GrGLShaderBuilder* builder, + virtual void emitCode(GrGLProgramBuilder* builder, const GrDrawEffect& drawEffect, const GrEffectKey& key, const char* outputColor, @@ -511,7 +513,7 @@ GLEllipticalRRectEffect::GLEllipticalRRectEffect(const GrBackendEffectFactory& f fPrevRRect.setEmpty(); } -void GLEllipticalRRectEffect::emitCode(GrGLShaderBuilder* builder, +void GLEllipticalRRectEffect::emitCode(GrGLProgramBuilder* builder, const GrDrawEffect& drawEffect, const GrEffectKey& key, const char* outputColor, @@ -521,11 +523,13 @@ void GLEllipticalRRectEffect::emitCode(GrGLShaderBuilder* builder, const EllipticalRRectEffect& erre = drawEffect.castEffect(); const char *rectName; // The inner rect is the rrect bounds inset by the x/y radii - fInnerRectUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, + fInnerRectUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec4f_GrSLType, "innerRect", &rectName); - const char* fragmentPos = builder->fragmentPosition(); + + GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); + const char* fragmentPos = fsBuilder->fragmentPosition(); // At each quarter-ellipse corner we compute a vector that is the offset of the fragment pos // to the ellipse center. The vector is pinned in x and y to be in the quarter-plane relevant // to that corner. This means that points near the interior near the rrect top edge will have @@ -537,31 +541,31 @@ void GLEllipticalRRectEffect::emitCode(GrGLShaderBuilder* builder, // The code below is a simplified version of the above that performs maxs on the vector // components before computing distances and alpha values so that only one distance computation // need be computed to determine the min alpha. - builder->fsCodeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName, fragmentPos); - builder->fsCodeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentPos, rectName); + fsBuilder->codeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName, fragmentPos); + fsBuilder->codeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentPos, rectName); switch (erre.getRRect().getType()) { case SkRRect::kSimple_Type: { const char *invRadiiXYSqdName; - fInvRadiiSqdUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, + fInvRadiiSqdUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec2f_GrSLType, "invRadiiXY", &invRadiiXYSqdName); - builder->fsCodeAppend("\t\tvec2 dxy = max(max(dxy0, dxy1), 0.0);\n"); + fsBuilder->codeAppend("\t\tvec2 dxy = max(max(dxy0, dxy1), 0.0);\n"); // Z is the x/y offsets divided by squared radii. - builder->fsCodeAppendf("\t\tvec2 Z = dxy * %s;\n", invRadiiXYSqdName); + fsBuilder->codeAppendf("\t\tvec2 Z = dxy * %s;\n", invRadiiXYSqdName); break; } case SkRRect::kNinePatch_Type: { const char *invRadiiLTRBSqdName; - fInvRadiiSqdUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, + fInvRadiiSqdUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec4f_GrSLType, "invRadiiLTRB", &invRadiiLTRBSqdName); - builder->fsCodeAppend("\t\tvec2 dxy = max(max(dxy0, dxy1), 0.0);\n"); + fsBuilder->codeAppend("\t\tvec2 dxy = max(max(dxy0, dxy1), 0.0);\n"); // Z is the x/y offsets divided by squared radii. We only care about the (at most) one // corner where both the x and y offsets are positive, hence the maxes. (The inverse // squared radii will always be positive.) - builder->fsCodeAppendf("\t\tvec2 Z = max(max(dxy0 * %s.xy, dxy1 * %s.zw), 0.0);\n", + fsBuilder->codeAppendf("\t\tvec2 Z = max(max(dxy0 * %s.xy, dxy1 * %s.zw), 0.0);\n", invRadiiLTRBSqdName, invRadiiLTRBSqdName); break; } @@ -569,20 +573,20 @@ void GLEllipticalRRectEffect::emitCode(GrGLShaderBuilder* builder, SkFAIL("RRect should always be simple or nine-patch."); } // implicit is the evaluation of (x/a)^2 + (y/b)^2 - 1. - builder->fsCodeAppend("\t\tfloat implicit = dot(Z, dxy) - 1.0;\n"); + fsBuilder->codeAppend("\t\tfloat implicit = dot(Z, dxy) - 1.0;\n"); // grad_dot is the squared length of the gradient of the implicit. - builder->fsCodeAppendf("\t\tfloat grad_dot = 4.0 * dot(Z, Z);\n"); + fsBuilder->codeAppendf("\t\tfloat grad_dot = 4.0 * dot(Z, Z);\n"); // avoid calling inversesqrt on zero. - builder->fsCodeAppend("\t\tgrad_dot = max(grad_dot, 1.0e-4);\n"); - builder->fsCodeAppendf("\t\tfloat approx_dist = implicit * inversesqrt(grad_dot);\n"); + fsBuilder->codeAppend("\t\tgrad_dot = max(grad_dot, 1.0e-4);\n"); + fsBuilder->codeAppendf("\t\tfloat approx_dist = implicit * inversesqrt(grad_dot);\n"); if (kFillAA_GrEffectEdgeType == erre.getEdgeType()) { - builder->fsCodeAppend("\t\tfloat alpha = clamp(0.5 - approx_dist, 0.0, 1.0);\n"); + fsBuilder->codeAppend("\t\tfloat alpha = clamp(0.5 - approx_dist, 0.0, 1.0);\n"); } else { - builder->fsCodeAppend("\t\tfloat alpha = clamp(0.5 + approx_dist, 0.0, 1.0);\n"); + fsBuilder->codeAppend("\t\tfloat alpha = clamp(0.5 + approx_dist, 0.0, 1.0);\n"); } - builder->fsCodeAppendf("\t\t%s = %s;\n", outputColor, + fsBuilder->codeAppendf("\t\t%s = %s;\n", outputColor, (GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_str()); } diff --git a/src/gpu/effects/GrSimpleTextureEffect.cpp b/src/gpu/effects/GrSimpleTextureEffect.cpp index 74926bc145..fe55ce9c7c 100644 --- a/src/gpu/effects/GrSimpleTextureEffect.cpp +++ b/src/gpu/effects/GrSimpleTextureEffect.cpp @@ -5,9 +5,9 @@ * found in the LICENSE file. */ +#include "gl/builders/GrGLProgramBuilder.h" #include "GrSimpleTextureEffect.h" #include "gl/GrGLEffect.h" -#include "gl/GrGLShaderBuilder.h" #include "gl/GrGLSL.h" #include "gl/GrGLTexture.h" #include "GrTBackendEffectFactory.h" @@ -19,19 +19,20 @@ public: : INHERITED (factory) { } - virtual void emitCode(GrGLShaderBuilder* builder, + virtual void emitCode(GrGLProgramBuilder* builder, const GrDrawEffect& drawEffect, const GrEffectKey& key, const char* outputColor, const char* inputColor, const TransformedCoordsArray& coords, const TextureSamplerArray& samplers) SK_OVERRIDE { - builder->fsCodeAppendf("\t%s = ", outputColor); - builder->fsAppendTextureLookupAndModulate(inputColor, + GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); + fsBuilder->codeAppendf("\t%s = ", outputColor); + fsBuilder->appendTextureLookupAndModulate(inputColor, samplers[0], coords[0].c_str(), coords[0].type()); - builder->fsCodeAppend(";\n"); + fsBuilder->codeAppend(";\n"); } private: diff --git a/src/gpu/effects/GrTextureDomain.cpp b/src/gpu/effects/GrTextureDomain.cpp index 2bad5e8fc5..40006a3f49 100644 --- a/src/gpu/effects/GrTextureDomain.cpp +++ b/src/gpu/effects/GrTextureDomain.cpp @@ -5,11 +5,11 @@ * found in the LICENSE file. */ +#include "gl/builders/GrGLProgramBuilder.h" #include "GrTextureDomain.h" #include "GrSimpleTextureEffect.h" #include "GrTBackendEffectFactory.h" #include "gl/GrGLEffect.h" -#include "gl/GrGLShaderBuilder.h" #include "SkFloatingPoint.h" @@ -49,23 +49,25 @@ void GrTextureDomain::GLDomain::sampleTexture(GrGLShaderBuilder* builder, SkASSERT((Mode)-1 == fMode || textureDomain.mode() == fMode); SkDEBUGCODE(fMode = textureDomain.mode();) + GrGLProgramBuilder* program = builder->getProgramBuilder(); + if (textureDomain.mode() != kIgnore_Mode && !fDomainUni.isValid()) { const char* name; SkString uniName("TexDom"); if (textureDomain.fIndex >= 0) { uniName.appendS32(textureDomain.fIndex); } - fDomainUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, - kVec4f_GrSLType, uniName.c_str(), &name); + fDomainUni = program->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec4f_GrSLType, + uniName.c_str(), &name); fDomainName = name; } switch (textureDomain.mode()) { case kIgnore_Mode: { - builder->fsCodeAppendf("\t%s = ", outColor); - builder->fsAppendTextureLookupAndModulate(inModulateColor, sampler, + builder->codeAppendf("\t%s = ", outColor); + builder->appendTextureLookupAndModulate(inModulateColor, sampler, inCoords.c_str()); - builder->fsCodeAppend(";\n"); + builder->codeAppend(";\n"); break; } case kClamp_Mode: { @@ -73,49 +75,49 @@ void GrTextureDomain::GLDomain::sampleTexture(GrGLShaderBuilder* builder, clampedCoords.appendf("\tclamp(%s, %s.xy, %s.zw)", inCoords.c_str(), fDomainName.c_str(), fDomainName.c_str()); - builder->fsCodeAppendf("\t%s = ", outColor); - builder->fsAppendTextureLookupAndModulate(inModulateColor, sampler, + builder->codeAppendf("\t%s = ", outColor); + builder->appendTextureLookupAndModulate(inModulateColor, sampler, clampedCoords.c_str()); - builder->fsCodeAppend(";\n"); + builder->codeAppend(";\n"); break; } case kDecal_Mode: { // Add a block since we're going to declare variables. - GrGLShaderBuilder::FSBlock block(builder); + GrGLShaderBuilder::ShaderBlock block(builder); const char* domain = fDomainName.c_str(); - if (kImagination_GrGLVendor == builder->ctxInfo().vendor()) { + if (kImagination_GrGLVendor == program->ctxInfo().vendor()) { // On the NexusS and GalaxyNexus, the other path (with the 'any' // call) causes the compilation error "Calls to any function that // may require a gradient calculation inside a conditional block // may return undefined results". This appears to be an issue with // the 'any' call since even the simple "result=black; if (any()) // result=white;" code fails to compile. - builder->fsCodeAppend("\tvec4 outside = vec4(0.0, 0.0, 0.0, 0.0);\n"); - builder->fsCodeAppend("\tvec4 inside = "); - builder->fsAppendTextureLookupAndModulate(inModulateColor, sampler, + builder->codeAppend("\tvec4 outside = vec4(0.0, 0.0, 0.0, 0.0);\n"); + builder->codeAppend("\tvec4 inside = "); + builder->appendTextureLookupAndModulate(inModulateColor, sampler, inCoords.c_str()); - builder->fsCodeAppend(";\n"); - builder->fsCodeAppendf("\tfloat x = (%s).x;\n", inCoords.c_str()); - builder->fsCodeAppendf("\tfloat y = (%s).y;\n", inCoords.c_str()); + builder->codeAppend(";\n"); + builder->codeAppendf("\tfloat x = (%s).x;\n", inCoords.c_str()); + builder->codeAppendf("\tfloat y = (%s).y;\n", inCoords.c_str()); - builder->fsCodeAppendf("\tx = abs(2.0*(x - %s.x)/(%s.z - %s.x) - 1.0);\n", + builder->codeAppendf("\tx = abs(2.0*(x - %s.x)/(%s.z - %s.x) - 1.0);\n", domain, domain, domain); - builder->fsCodeAppendf("\ty = abs(2.0*(y - %s.y)/(%s.w - %s.y) - 1.0);\n", + builder->codeAppendf("\ty = abs(2.0*(y - %s.y)/(%s.w - %s.y) - 1.0);\n", domain, domain, domain); - builder->fsCodeAppend("\tfloat blend = step(1.0, max(x, y));\n"); - builder->fsCodeAppendf("\t%s = mix(inside, outside, blend);\n", outColor); + builder->codeAppend("\tfloat blend = step(1.0, max(x, y));\n"); + builder->codeAppendf("\t%s = mix(inside, outside, blend);\n", outColor); } else { - builder->fsCodeAppend("\tbvec4 outside;\n"); - builder->fsCodeAppendf("\toutside.xy = lessThan(%s, %s.xy);\n", inCoords.c_str(), + builder->codeAppend("\tbvec4 outside;\n"); + builder->codeAppendf("\toutside.xy = lessThan(%s, %s.xy);\n", inCoords.c_str(), domain); - builder->fsCodeAppendf("\toutside.zw = greaterThan(%s, %s.zw);\n", inCoords.c_str(), + builder->codeAppendf("\toutside.zw = greaterThan(%s, %s.zw);\n", inCoords.c_str(), domain); - builder->fsCodeAppendf("\t%s = any(outside) ? vec4(0.0, 0.0, 0.0, 0.0) : ", + builder->codeAppendf("\t%s = any(outside) ? vec4(0.0, 0.0, 0.0, 0.0) : ", outColor); - builder->fsAppendTextureLookupAndModulate(inModulateColor, sampler, + builder->appendTextureLookupAndModulate(inModulateColor, sampler, inCoords.c_str()); - builder->fsCodeAppend(";\n"); + builder->codeAppend(";\n"); } break; } @@ -125,10 +127,10 @@ void GrTextureDomain::GLDomain::sampleTexture(GrGLShaderBuilder* builder, inCoords.c_str(), fDomainName.c_str(), fDomainName.c_str(), fDomainName.c_str(), fDomainName.c_str()); - builder->fsCodeAppendf("\t%s = ", outColor); - builder->fsAppendTextureLookupAndModulate(inModulateColor, sampler, + builder->codeAppendf("\t%s = ", outColor); + builder->appendTextureLookupAndModulate(inModulateColor, sampler, clampedCoords.c_str()); - builder->fsCodeAppend(";\n"); + builder->codeAppend(";\n"); break; } } @@ -167,7 +169,7 @@ class GrGLTextureDomainEffect : public GrGLEffect { public: GrGLTextureDomainEffect(const GrBackendEffectFactory&, const GrDrawEffect&); - virtual void emitCode(GrGLShaderBuilder*, + virtual void emitCode(GrGLProgramBuilder*, const GrDrawEffect&, const GrEffectKey&, const char* outputColor, @@ -189,7 +191,7 @@ GrGLTextureDomainEffect::GrGLTextureDomainEffect(const GrBackendEffectFactory& f : INHERITED(factory) { } -void GrGLTextureDomainEffect::emitCode(GrGLShaderBuilder* builder, +void GrGLTextureDomainEffect::emitCode(GrGLProgramBuilder* builder, const GrDrawEffect& drawEffect, const GrEffectKey& key, const char* outputColor, @@ -199,8 +201,9 @@ void GrGLTextureDomainEffect::emitCode(GrGLShaderBuilder* builder, const GrTextureDomainEffect& effect = drawEffect.castEffect(); const GrTextureDomain& domain = effect.textureDomain(); - SkString coords2D = builder->ensureFSCoords2D(coords, 0); - fGLDomain.sampleTexture(builder, domain, outputColor, coords2D, samplers[0], inputColor); + GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); + SkString coords2D = fsBuilder->ensureFSCoords2D(coords, 0); + fGLDomain.sampleTexture(fsBuilder, domain, outputColor, coords2D, samplers[0], inputColor); } void GrGLTextureDomainEffect::setData(const GrGLProgramDataManager& pdman, diff --git a/src/gpu/effects/GrTextureDomain.h b/src/gpu/effects/GrTextureDomain.h index 577098a4ad..6cb5ad408e 100644 --- a/src/gpu/effects/GrTextureDomain.h +++ b/src/gpu/effects/GrTextureDomain.h @@ -11,6 +11,7 @@ #include "GrSingleTextureEffect.h" #include "gl/GrGLEffect.h" +class GrGLProgramBuilder; class GrGLShaderBuilder; struct SkRect; diff --git a/src/gpu/effects/GrYUVtoRGBEffect.cpp b/src/gpu/effects/GrYUVtoRGBEffect.cpp index 15e51a2c62..41d75c30ef 100644 --- a/src/gpu/effects/GrYUVtoRGBEffect.cpp +++ b/src/gpu/effects/GrYUVtoRGBEffect.cpp @@ -5,12 +5,12 @@ * found in the LICENSE file. */ +#include "gl/builders/GrGLProgramBuilder.h" #include "GrYUVtoRGBEffect.h" #include "GrCoordTransform.h" #include "GrEffect.h" #include "gl/GrGLEffect.h" -#include "gl/GrGLShaderBuilder.h" #include "GrTBackendEffectFactory.h" namespace { @@ -44,26 +44,27 @@ public: : INHERITED(factory) { } - virtual void emitCode(GrGLShaderBuilder* builder, + virtual void emitCode(GrGLProgramBuilder* builder, const GrDrawEffect&, const GrEffectKey&, const char* outputColor, const char* inputColor, const TransformedCoordsArray& coords, const TextureSamplerArray& samplers) SK_OVERRIDE { + GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); const char* yuvMatrix = "yuvMatrix"; - builder->fsCodeAppendf("\tconst mat4 %s = mat4(1.0, 0.0, 1.402, -0.701,\n\t\t\t" + fsBuilder->codeAppendf("\tconst mat4 %s = mat4(1.0, 0.0, 1.402, -0.701,\n\t\t\t" "1.0, -0.344, -0.714, 0.529,\n\t\t\t" "1.0, 1.772, 0.0, -0.886,\n\t\t\t" "0.0, 0.0, 0.0, 1.0);\n", yuvMatrix); - builder->fsCodeAppendf("\t%s = vec4(\n\t\t", outputColor); - builder->fsAppendTextureLookup(samplers[0], coords[0].c_str(), coords[0].type()); - builder->fsCodeAppend(".r,\n\t\t"); - builder->fsAppendTextureLookup(samplers[1], coords[0].c_str(), coords[0].type()); - builder->fsCodeAppend(".r,\n\t\t"); - builder->fsAppendTextureLookup(samplers[2], coords[0].c_str(), coords[0].type()); - builder->fsCodeAppendf(".r,\n\t\t1.0) * %s;\n", yuvMatrix); + fsBuilder->codeAppendf("\t%s = vec4(\n\t\t", outputColor); + fsBuilder->appendTextureLookup(samplers[0], coords[0].c_str(), coords[0].type()); + fsBuilder->codeAppend(".r,\n\t\t"); + fsBuilder->appendTextureLookup(samplers[1], coords[0].c_str(), coords[0].type()); + fsBuilder->codeAppend(".r,\n\t\t"); + fsBuilder->appendTextureLookup(samplers[2], coords[0].c_str(), coords[0].type()); + fsBuilder->codeAppendf(".r,\n\t\t1.0) * %s;\n", yuvMatrix); } typedef GrGLEffect INHERITED; diff --git a/src/gpu/gl/GrGLEffect.h b/src/gpu/gl/GrGLEffect.h index 18b3002edf..88aa4cdd1c 100644 --- a/src/gpu/gl/GrGLEffect.h +++ b/src/gpu/gl/GrGLEffect.h @@ -68,7 +68,7 @@ public: GrGLEffect. These can be passed to the builder to emit texture reads in the generated code. */ - virtual void emitCode(GrGLShaderBuilder* builder, + virtual void emitCode(GrGLProgramBuilder* builder, const GrDrawEffect& drawEffect, const GrEffectKey& key, const char* outputColor, diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp index d8c751d71d..d49d000fe3 100644 --- a/src/gpu/gl/GrGLProgram.cpp +++ b/src/gpu/gl/GrGLProgram.cpp @@ -24,13 +24,12 @@ GrGLProgram* GrGLProgram::Create(GrGpuGL* gpu, const GrGLProgramDesc& desc, const GrEffectStage* colorStages[], const GrEffectStage* coverageStages[]) { - SkAutoTDelete builder; + SkAutoTDelete builder; if (desc.getHeader().fHasVertexCode ||!gpu->shouldUseFixedFunctionTexturing()) { - builder.reset(SkNEW_ARGS(GrGLFullShaderBuilder, (gpu, desc))); + builder.reset(SkNEW_ARGS(GrGLFullProgramBuilder, (gpu, desc))); } else { - builder.reset(SkNEW_ARGS(GrGLFragmentOnlyShaderBuilder, (gpu, desc))); + builder.reset(SkNEW_ARGS(GrGLFragmentOnlyProgramBuilder, (gpu, desc))); } - if (builder->genProgram(colorStages, coverageStages)) { SkASSERT(0 != builder->getProgramID()); return SkNEW_ARGS(GrGLProgram, (gpu, desc, *builder)); @@ -40,7 +39,7 @@ GrGLProgram* GrGLProgram::Create(GrGpuGL* gpu, GrGLProgram::GrGLProgram(GrGpuGL* gpu, const GrGLProgramDesc& desc, - const GrGLShaderBuilder& builder) + const GrGLProgramBuilder& builder) : fColor(GrColor_ILLEGAL) , fCoverage(GrColor_ILLEGAL) , fDstCopyTexUnit(-1) diff --git a/src/gpu/gl/GrGLProgram.h b/src/gpu/gl/GrGLProgram.h index fb496856b4..7af55f10ee 100644 --- a/src/gpu/gl/GrGLProgram.h +++ b/src/gpu/gl/GrGLProgram.h @@ -9,10 +9,10 @@ #ifndef GrGLProgram_DEFINED #define GrGLProgram_DEFINED +#include "builders/GrGLProgramBuilder.h" #include "GrDrawState.h" #include "GrGLContext.h" #include "GrGLProgramDesc.h" -#include "GrGLShaderBuilder.h" #include "GrGLSL.h" #include "GrGLTexture.h" #include "GrGLProgramDataManager.h" @@ -22,7 +22,7 @@ class GrGLEffect; class GrGLProgramEffects; -class GrGLShaderBuilder; +class GrGLProgramBuilder; /** * This class manages a GPU program and records per-program information. @@ -37,7 +37,7 @@ class GrGLProgram : public SkRefCnt { public: SK_DECLARE_INST_COUNT(GrGLProgram) - typedef GrGLShaderBuilder::BuiltinUniformHandles BuiltinUniformHandles; + typedef GrGLProgramBuilder::BuiltinUniformHandles BuiltinUniformHandles; static GrGLProgram* Create(GrGpuGL* gpu, const GrGLProgramDesc& desc, @@ -167,7 +167,7 @@ private: GrGLProgram(GrGpuGL*, const GrGLProgramDesc&, - const GrGLShaderBuilder&); + const GrGLProgramBuilder&); // Sets the texture units for samplers. void initSamplerUniforms(); diff --git a/src/gpu/gl/GrGLProgramDataManager.cpp b/src/gpu/gl/GrGLProgramDataManager.cpp index c4c51933c7..eed9d1935d 100644 --- a/src/gpu/gl/GrGLProgramDataManager.cpp +++ b/src/gpu/gl/GrGLProgramDataManager.cpp @@ -5,7 +5,7 @@ * found in the LICENSE file. */ -#include "gl/GrGLShaderBuilder.h" +#include "gl/builders/GrGLProgramBuilder.h" #include "gl/GrGLProgram.h" #include "gl/GrGLUniformHandle.h" #include "gl/GrGpuGL.h" @@ -17,13 +17,13 @@ GrGLProgramDataManager::GrGLProgramDataManager(GrGpuGL* gpu, GrGLProgram*, - const GrGLShaderBuilder& builder) + const GrGLProgramBuilder& builder) : fGpu(gpu) { int count = builder.getUniformInfos().count(); fUniforms.push_back_n(count); for (int i = 0; i < count; i++) { Uniform& uniform = fUniforms[i]; - const GrGLShaderBuilder::UniformInfo& builderUniform = builder.getUniformInfos()[i]; + const GrGLProgramBuilder::UniformInfo& builderUniform = builder.getUniformInfos()[i]; SkASSERT(GrGLShaderVar::kNonArray == builderUniform.fVariable.getArrayCount() || builderUniform.fVariable.getArrayCount() > 0); SkDEBUGCODE( @@ -32,12 +32,12 @@ GrGLProgramDataManager::GrGLProgramDataManager(GrGpuGL* gpu, ); // TODO: Move the Xoom uniform array in both FS and VS bug workaround here. - if (GrGLShaderBuilder::kVertex_Visibility & builderUniform.fVisibility) { + if (GrGLProgramBuilder::kVertex_Visibility & builderUniform.fVisibility) { uniform.fVSLocation = builderUniform.fLocation; } else { uniform.fVSLocation = kUnusedUniform; } - if (GrGLShaderBuilder::kFragment_Visibility & builderUniform.fVisibility) { + if (GrGLProgramBuilder::kFragment_Visibility & builderUniform.fVisibility) { uniform.fFSLocation = builderUniform.fLocation; } else { uniform.fFSLocation = kUnusedUniform; diff --git a/src/gpu/gl/GrGLProgramDataManager.h b/src/gpu/gl/GrGLProgramDataManager.h index 8ef4a41fbc..3082f6f02b 100644 --- a/src/gpu/gl/GrGLProgramDataManager.h +++ b/src/gpu/gl/GrGLProgramDataManager.h @@ -17,7 +17,7 @@ class GrGpuGL; class SkMatrix; class GrGLProgram; -class GrGLShaderBuilder; +class GrGLProgramBuilder; /** Manages the resources used by a shader program. * The resources are objects the program uses to communicate with the @@ -51,10 +51,10 @@ public: int fValue; friend class GrGLProgramDataManager; // For accessing toProgramDataIndex(). - friend class GrGLShaderBuilder; // For accessing toShaderBuilderIndex(). + friend class GrGLProgramBuilder; // For accessing toShaderBuilderIndex(). }; - GrGLProgramDataManager(GrGpuGL*, GrGLProgram*, const GrGLShaderBuilder&); + GrGLProgramDataManager(GrGpuGL*, GrGLProgram*, const GrGLProgramBuilder&); /** Functions for uploading uniform values. The varities ending in v can be used to upload to an * array of uniforms. arrayCount must be <= the array count of the uniform. diff --git a/src/gpu/gl/GrGLProgramDesc.cpp b/src/gpu/gl/GrGLProgramDesc.cpp index e1a319104d..7cdbcd0efc 100644 --- a/src/gpu/gl/GrGLProgramDesc.cpp +++ b/src/gpu/gl/GrGLProgramDesc.cpp @@ -5,11 +5,11 @@ * found in the LICENSE file. */ +#include "gl/builders/GrGLProgramBuilder.h" #include "GrGLProgramDesc.h" #include "GrBackendEffectFactory.h" #include "GrDrawEffect.h" #include "GrEffect.h" -#include "GrGLShaderBuilder.h" #include "GrGpuGL.h" #include "SkChecksum.h" @@ -212,15 +212,16 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState, if (NULL != dstCopy) { dstCopyTexture = dstCopy->texture(); } - header->fDstReadKey = GrGLShaderBuilder::KeyForDstRead(dstCopyTexture, gpu->glCaps()); + header->fDstReadKey = GrGLFragmentShaderBuilder::KeyForDstRead(dstCopyTexture, + gpu->glCaps()); SkASSERT(0 != header->fDstReadKey); } else { header->fDstReadKey = 0; } if (readFragPosition) { - header->fFragPosKey = GrGLShaderBuilder::KeyForFragmentPosition(drawState.getRenderTarget(), - gpu->glCaps()); + header->fFragPosKey = GrGLFragmentShaderBuilder::KeyForFragmentPosition( + drawState.getRenderTarget(), gpu->glCaps()); } else { header->fFragPosKey = 0; } diff --git a/src/gpu/gl/GrGLProgramDesc.h b/src/gpu/gl/GrGLProgramDesc.h index cccdee9ce2..e8925d0c5c 100644 --- a/src/gpu/gl/GrGLProgramDesc.h +++ b/src/gpu/gl/GrGLProgramDesc.h @@ -252,9 +252,12 @@ private: // part of GrGLShaderBuilder that is used by effects so that this header doesn't need to be // visible to GrGLEffects. Then make public accessors as necessary and remove friends. friend class GrGLProgram; - friend class GrGLShaderBuilder; - friend class GrGLFullShaderBuilder; - friend class GrGLFragmentOnlyShaderBuilder; + friend class GrGLProgramBuilder; + friend class GrGLFullProgramBuilder; + friend class GrGLFragmentOnlyProgramBuilder; + friend class GrGLVertexShaderBuilder; + friend class GrGLFragmentShaderBuilder; + friend class GrGLGeometryShaderBuilder; }; #endif diff --git a/src/gpu/gl/GrGLProgramEffects.cpp b/src/gpu/gl/GrGLProgramEffects.cpp index 8ea77d05eb..efb64fe640 100644 --- a/src/gpu/gl/GrGLProgramEffects.cpp +++ b/src/gpu/gl/GrGLProgramEffects.cpp @@ -5,10 +5,10 @@ * found in the LICENSE file. */ +#include "gl/builders/GrGLProgramBuilder.h" #include "GrGLProgramEffects.h" #include "GrDrawEffect.h" #include "gl/GrGLEffect.h" -#include "gl/GrGLShaderBuilder.h" #include "gl/GrGLVertexEffect.h" #include "gl/GrGpuGL.h" @@ -204,7 +204,7 @@ GrGLProgramEffects::~GrGLProgramEffects() { } } -void GrGLProgramEffects::emitSamplers(GrGLShaderBuilder* builder, +void GrGLProgramEffects::emitSamplers(GrGLProgramBuilder* builder, const GrEffect* effect, TextureSamplerArray* outSamplers) { SkTArray& samplers = fSamplers.push_back(); @@ -213,7 +213,7 @@ void GrGLProgramEffects::emitSamplers(GrGLShaderBuilder* builder, SkString name; for (int t = 0; t < numTextures; ++t) { name.printf("Sampler%d", t); - samplers[t].fUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, + samplers[t].fUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kSampler2D_GrSLType, name.c_str()); SkNEW_APPEND_TO_TARRAY(outSamplers, TextureSampler, @@ -250,7 +250,7 @@ void GrGLProgramEffects::bindTextures(GrGpuGL* gpu, const GrEffect* effect, int //////////////////////////////////////////////////////////////////////////////// -void GrGLVertexProgramEffects::emitEffect(GrGLFullShaderBuilder* builder, +void GrGLVertexProgramEffects::emitEffect(GrGLFullProgramBuilder* builder, const GrEffectStage& stage, const GrEffectKey& key, const char* outColor, @@ -261,7 +261,9 @@ void GrGLVertexProgramEffects::emitEffect(GrGLFullShaderBuilder* builder, SkSTArray<2, TransformedCoords> coords(effect->numTransforms()); SkSTArray<4, TextureSampler> samplers(effect->numTextures()); - this->emitAttributes(builder, stage); + GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder(); + GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); + vsBuilder->emitAttributes(stage); this->emitTransforms(builder, drawEffect, &coords); this->emitSamplers(builder, effect, &samplers); @@ -271,8 +273,8 @@ void GrGLVertexProgramEffects::emitEffect(GrGLFullShaderBuilder* builder, // Enclose custom code in a block to avoid namespace conflicts SkString openBrace; openBrace.printf("\t{ // Stage %d: %s\n", stageIndex, glEffect->name()); - builder->vsCodeAppend(openBrace.c_str()); - builder->fsCodeAppend(openBrace.c_str()); + fsBuilder->codeAppend(openBrace.c_str()); + vsBuilder->codeAppend(openBrace.c_str()); if (glEffect->isVertexEffect()) { GrGLVertexEffect* vertexEffect = static_cast(glEffect); @@ -281,25 +283,11 @@ void GrGLVertexProgramEffects::emitEffect(GrGLFullShaderBuilder* builder, glEffect->emitCode(builder, drawEffect, key, outColor, inColor, coords, samplers); } - builder->vsCodeAppend("\t}\n"); - builder->fsCodeAppend("\t}\n"); + vsBuilder->codeAppend("\t}\n"); + fsBuilder->codeAppend("\t}\n"); } -void GrGLVertexProgramEffects::emitAttributes(GrGLFullShaderBuilder* builder, - const GrEffectStage& stage) { - int numAttributes = stage.getVertexAttribIndexCount(); - const int* attributeIndices = stage.getVertexAttribIndices(); - for (int a = 0; a < numAttributes; ++a) { - // TODO: Make addAttribute mangle the name. - SkString attributeName("aAttr"); - attributeName.appendS32(attributeIndices[a]); - builder->addEffectAttribute(attributeIndices[a], - stage.getEffect()->vertexAttribType(a), - attributeName); - } -} - -void GrGLVertexProgramEffects::emitTransforms(GrGLFullShaderBuilder* builder, +void GrGLVertexProgramEffects::emitTransforms(GrGLFullProgramBuilder* builder, const GrDrawEffect& drawEffect, TransformedCoordsArray* outCoords) { SkTArray& transforms = fTransforms.push_back(); @@ -327,7 +315,7 @@ void GrGLVertexProgramEffects::emitTransforms(GrGLFullShaderBuilder* builder, suffixedUniName.appendf("_%i", t); uniName = suffixedUniName.c_str(); } - transforms[t].fHandle = builder->addUniform(GrGLShaderBuilder::kVertex_Visibility, + transforms[t].fHandle = builder->addUniform(GrGLProgramBuilder::kVertex_Visibility, kMat33f_GrSLType, uniName, &uniName); @@ -341,18 +329,19 @@ void GrGLVertexProgramEffects::emitTransforms(GrGLFullShaderBuilder* builder, } const char* vsVaryingName; const char* fsVaryingName; + GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder(); builder->addVarying(varyingType, varyingName, &vsVaryingName, &fsVaryingName); const GrGLShaderVar& coords = kPosition_GrCoordSet == get_source_coords(totalKey, t) ? - builder->positionAttribute() : - builder->localCoordsAttribute(); + vsBuilder->positionAttribute() : + vsBuilder->localCoordsAttribute(); // varying = matrix * coords (logically) SkASSERT(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyingType); if (kVec2f_GrSLType == varyingType) { - builder->vsCodeAppendf("\t%s = (%s * vec3(%s, 1)).xy;\n", + vsBuilder->codeAppendf("\t%s = (%s * vec3(%s, 1)).xy;\n", vsVaryingName, uniName, coords.c_str()); } else { - builder->vsCodeAppendf("\t%s = %s * vec3(%s, 1);\n", + vsBuilder->codeAppendf("\t%s = %s * vec3(%s, 1);\n", vsVaryingName, uniName, coords.c_str()); } SkNEW_APPEND_TO_TARRAY(outCoords, TransformedCoords, @@ -390,13 +379,13 @@ void GrGLVertexProgramEffects::setTransformData(const GrGLProgramDataManager& pr } } -GrGLVertexProgramEffectsBuilder::GrGLVertexProgramEffectsBuilder(GrGLFullShaderBuilder* builder, +GrGLVertexProgramEffectsBuilder::GrGLVertexProgramEffectsBuilder(GrGLFullProgramBuilder* builder, int reserveCount) : fBuilder(builder) , fProgramEffects(SkNEW_ARGS(GrGLVertexProgramEffects, - (reserveCount, fBuilder->hasExplicitLocalCoords()))) { + (reserveCount, + fBuilder->getVertexShaderBuilder()->hasExplicitLocalCoords()))) { } - void GrGLVertexProgramEffectsBuilder::emitEffect(const GrEffectStage& stage, const GrEffectKey& key, const char* outColor, @@ -408,7 +397,7 @@ void GrGLVertexProgramEffectsBuilder::emitEffect(const GrEffectStage& stage, //////////////////////////////////////////////////////////////////////////////// -void GrGLPathTexGenProgramEffects::emitEffect(GrGLFragmentOnlyShaderBuilder* builder, +void GrGLPathTexGenProgramEffects::emitEffect(GrGLFragmentOnlyProgramBuilder* builder, const GrEffectStage& stage, const GrEffectKey& key, const char* outColor, @@ -426,18 +415,19 @@ void GrGLPathTexGenProgramEffects::emitEffect(GrGLFragmentOnlyShaderBuilder* bui GrGLEffect* glEffect = effect->getFactory().createGLInstance(drawEffect); fGLEffects.push_back(glEffect); + GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); // Enclose custom code in a block to avoid namespace conflicts SkString openBrace; openBrace.printf("\t{ // Stage %d: %s\n", stageIndex, glEffect->name()); - builder->fsCodeAppend(openBrace.c_str()); + fsBuilder->codeAppend(openBrace.c_str()); SkASSERT(!glEffect->isVertexEffect()); glEffect->emitCode(builder, drawEffect, key, outColor, inColor, coords, samplers); - builder->fsCodeAppend("\t}\n"); + fsBuilder->codeAppend("\t}\n"); } -void GrGLPathTexGenProgramEffects::setupPathTexGen(GrGLFragmentOnlyShaderBuilder* builder, +void GrGLPathTexGenProgramEffects::setupPathTexGen(GrGLFragmentOnlyProgramBuilder* builder, const GrDrawEffect& drawEffect, TransformedCoordsArray* outCoords) { int numTransforms = drawEffect.effect()->numTransforms(); @@ -499,12 +489,11 @@ void GrGLPathTexGenProgramEffects::setPathTexGenState(GrGpuGL* gpu, } GrGLPathTexGenProgramEffectsBuilder::GrGLPathTexGenProgramEffectsBuilder( - GrGLFragmentOnlyShaderBuilder* builder, + GrGLFragmentOnlyProgramBuilder* builder, int reserveCount) : fBuilder(builder) , fProgramEffects(SkNEW_ARGS(GrGLPathTexGenProgramEffects, (reserveCount))) { } - void GrGLPathTexGenProgramEffectsBuilder::emitEffect(const GrEffectStage& stage, const GrEffectKey& key, const char* outColor, @@ -513,3 +502,4 @@ void GrGLPathTexGenProgramEffectsBuilder::emitEffect(const GrEffectStage& stage, SkASSERT(NULL != fProgramEffects.get()); fProgramEffects->emitEffect(fBuilder, stage, key, outColor, inColor, stageIndex); } + diff --git a/src/gpu/gl/GrGLProgramEffects.h b/src/gpu/gl/GrGLProgramEffects.h index 7ae925b69b..e4d84a013b 100644 --- a/src/gpu/gl/GrGLProgramEffects.h +++ b/src/gpu/gl/GrGLProgramEffects.h @@ -16,9 +16,9 @@ class GrEffect; class GrEffectStage; class GrGLVertexProgramEffectsBuilder; -class GrGLShaderBuilder; -class GrGLFullShaderBuilder; -class GrGLFragmentOnlyShaderBuilder; +class GrGLProgramBuilder; +class GrGLFullProgramBuilder; +class GrGLFragmentOnlyProgramBuilder; /** * This class encapsulates an array of GrGLEffects and their supporting data (coord transforms @@ -54,6 +54,8 @@ public: const GrGLProgramDataManager&, const GrEffectStage* effectStages[]) = 0; + void addEffect(GrGLEffect* effect) { fGLEffects.push_back(effect); } + /** * Passed to GrGLEffects so they can add transformed coordinates to their shader code. */ @@ -100,6 +102,7 @@ public: typedef SkTArray TextureSamplerArray; protected: + /** * Helpers for GenEffectMetaKey. */ @@ -117,7 +120,7 @@ protected: * appends the necessary data to the TextureSamplerArray* object so effects can add texture * lookups to their code. This method is only meant to be called during the construction phase. */ - void emitSamplers(GrGLShaderBuilder*, const GrEffect*, TextureSamplerArray*); + void emitSamplers(GrGLProgramBuilder*, const GrEffect*, TextureSamplerArray*); /** * Helper for setData(). Binds all the textures for an effect. @@ -134,6 +137,7 @@ protected: SkTArray > fSamplers; private: + friend class GrGLFragmentO; typedef SkRefCnt INHERITED; }; @@ -143,7 +147,6 @@ private: class GrGLProgramEffectsBuilder { public: virtual ~GrGLProgramEffectsBuilder() { } - /** * Emits the effect's shader code, and stores the necessary uniforms internally. */ @@ -166,19 +169,17 @@ public: const GrEffectStage* effectStages[]) SK_OVERRIDE; private: - friend class GrGLVertexProgramEffectsBuilder; + friend class GrGLFullProgramBuilder; GrGLVertexProgramEffects(int reserveCount, bool explicitLocalCoords) : INHERITED(reserveCount) , fTransforms(reserveCount) , fHasExplicitLocalCoords(explicitLocalCoords) { } - /** - * Helper for GrGLProgramEffectsBuilder::emitEfffect(). This method is meant to only be called - * during the construction phase. + * This method is meant to only be called during the construction phase. */ - void emitEffect(GrGLFullShaderBuilder*, + void emitEffect(GrGLFullProgramBuilder*, const GrEffectStage&, const GrEffectKey&, const char* outColor, @@ -188,7 +189,7 @@ private: /** * Helper for emitEffect(). Emits any attributes an effect may have. */ - void emitAttributes(GrGLFullShaderBuilder*, const GrEffectStage&); + void emitAttributes(GrGLFullProgramBuilder*, const GrEffectStage&); /** * Helper for emitEffect(). Emits code to implement an effect's coord transforms in the VS. @@ -197,7 +198,7 @@ private: * of the varyings in the VS and FS as well their types are appended to the * TransformedCoordsArray* object, which is in turn passed to the effect's emitCode() function. */ - void emitTransforms(GrGLFullShaderBuilder*, + void emitTransforms(GrGLFullProgramBuilder*, const GrDrawEffect&, TransformedCoordsArray*); @@ -215,6 +216,8 @@ private: SkTArray > fTransforms; bool fHasExplicitLocalCoords; + friend class GrGLVertexProgramEffectsBuilder; + typedef GrGLProgramEffects INHERITED; }; @@ -223,25 +226,21 @@ private: */ class GrGLVertexProgramEffectsBuilder : public GrGLProgramEffectsBuilder { public: - GrGLVertexProgramEffectsBuilder(GrGLFullShaderBuilder*, int reserveCount); + GrGLVertexProgramEffectsBuilder(GrGLFullProgramBuilder*, int reserveCount); virtual ~GrGLVertexProgramEffectsBuilder() { } - virtual void emitEffect(const GrEffectStage&, const GrEffectKey&, const char* outColor, const char* inColor, int stageIndex) SK_OVERRIDE; - /** * Finalizes the building process and returns the effect array. After this call, the builder * becomes invalid. */ GrGLProgramEffects* finish() { return fProgramEffects.detach(); } - private: - GrGLFullShaderBuilder* fBuilder; + GrGLFullProgramBuilder* fBuilder; SkAutoTDelete fProgramEffects; - typedef GrGLProgramEffectsBuilder INHERITED; }; @@ -258,7 +257,7 @@ public: const GrEffectStage* effectStages[]) SK_OVERRIDE; private: - friend class GrGLPathTexGenProgramEffectsBuilder; + friend class GrGLFragmentOnlyProgramBuilder; GrGLPathTexGenProgramEffects(int reserveCount) : INHERITED(reserveCount) @@ -266,10 +265,9 @@ private: } /** - * Helper for GrGLProgramEffectsBuilder::emitEfffect(). This method is meant to only be called - * during the construction phase. + * This method is meant to only be called during the construction phase. */ - void emitEffect(GrGLFragmentOnlyShaderBuilder*, + void emitEffect(GrGLFragmentOnlyProgramBuilder*, const GrEffectStage&, const GrEffectKey&, const char* outColor, @@ -284,7 +282,7 @@ private: * types are appended to the TransformedCoordsArray* object, which is in turn passed to the * effect's emitCode() function. */ - void setupPathTexGen(GrGLFragmentOnlyShaderBuilder*, + void setupPathTexGen(GrGLFragmentOnlyProgramBuilder*, const GrDrawEffect&, TransformedCoordsArray*); @@ -302,6 +300,7 @@ private: SkTArray fTransforms; + friend class GrGLPathTexGenProgramEffectsBuilder; typedef GrGLProgramEffects INHERITED; }; @@ -310,26 +309,23 @@ private: */ class GrGLPathTexGenProgramEffectsBuilder : public GrGLProgramEffectsBuilder { public: - GrGLPathTexGenProgramEffectsBuilder(GrGLFragmentOnlyShaderBuilder*, int reserveCount); + GrGLPathTexGenProgramEffectsBuilder(GrGLFragmentOnlyProgramBuilder*, int reserveCount); virtual ~GrGLPathTexGenProgramEffectsBuilder() { } - virtual void emitEffect(const GrEffectStage&, const GrEffectKey&, const char* outColor, const char* inColor, int stageIndex) SK_OVERRIDE; - /** * Finalizes the building process and returns the effect array. After this call, the builder * becomes invalid. */ GrGLProgramEffects* finish() { return fProgramEffects.detach(); } - private: - GrGLFragmentOnlyShaderBuilder* fBuilder; + GrGLFragmentOnlyProgramBuilder* fBuilder; SkAutoTDelete fProgramEffects; - typedef GrGLProgramEffectsBuilder INHERITED; }; + #endif diff --git a/src/gpu/gl/GrGLSLPrettyPrint.cpp b/src/gpu/gl/GrGLSLPrettyPrint.cpp deleted file mode 100644 index 27f4b44e66..0000000000 --- a/src/gpu/gl/GrGLSLPrettyPrint.cpp +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright 2014 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ -#include "gl/GrGLSLPrettyPrint.h" - -namespace GrGLSLPrettyPrint { - -class GLSLPrettyPrint { -public: - GLSLPrettyPrint() {} - - SkString prettify(const SkString& input, bool countlines) { - // setup pretty state - fIndex = 0; - fLength = input.size(); - fInput = input; - fCountlines = countlines; - fTabs = 0; - fLinecount = 1; - fFreshline = true; - - int parensDepth = 0; - // number 1st line - this->lineNumbering(); - while (fLength > fIndex) { - /* the heart and soul of our prettification algorithm. The rules should hopefully be - * self explanatory. For '#' and '//' tokens we parse until we reach a newline. - * - * For long style comments like this one, we search for the ending token. We also - * preserve whitespace in these comments WITH THE CAVEAT that we do the newlines - * ourselves. This allows us to remain in control of line numbers, and matching tabs - * Existing tabs in the input string are copied over too, but this will look funny - * - * '{' and '}' are handled in basically the same way. We add a newline if we aren't - * on a fresh line, dirty the line, then add a second newline, ie braces are always - * on their own lines indented properly. The one funkiness here is structs print with - * the semicolon on its own line. Its not a problem for a glsl compiler though - * - * '(' and ')' are basically ignored, except as a sign we need to ignore ';' ala - * in for loops. - * - * ';' means add a new line - * - * '\t' and '\n' are ignored in general parsing for backwards compatability with - * existing shader code and we also have a special case for handling whitespace - * at the beginning of fresh lines. - * - * Otherwise just add the new character to the pretty string, indenting if necessary. - */ - if (this->hasToken("#") || this->hasToken("//")) { - this->parseUntilNewline(); - } else if (this->hasToken("/*")) { - this->parseUntil("*/"); - } else if ('{' == fInput[fIndex]) { - this->newline(); - this->appendChar('{'); - fTabs++; - this->newline(); - } else if ('}' == fInput[fIndex]) { - fTabs--; - this->newline(); - this->appendChar('}'); - this->newline(); - } else if (this->hasToken(")")) { - parensDepth--; - } else if (this->hasToken("(")) { - parensDepth++; - } else if (!parensDepth && this->hasToken(";")) { - this->newline(); - } else if ('\t' == fInput[fIndex] || '\n' == fInput[fIndex] || - (fFreshline && ' ' == fInput[fIndex])) { - fIndex++; - } else { - this->appendChar(input[fIndex]); - } - } - return fPretty; - } -private: - void appendChar(char c) { - this->tabString(); - fPretty.appendf("%c", fInput[fIndex++]); - fFreshline = false; - } - - // hasToken automatically consumes the next token, if it is a match, and then tabs - // if necessary, before inserting the token into the pretty string - bool hasToken(const char* token) { - size_t i = fIndex; - for (size_t j = 0; token[j] && fLength > i; i++, j++) { - if (token[j] != fInput[i]) { - return false; - } - } - this->tabString(); - fIndex = i; - fPretty.append(token); - fFreshline = false; - return true; - } - - void parseUntilNewline() { - while (fLength > fIndex) { - if ('\n' == fInput[fIndex]) { - fIndex++; - this->newline(); - break; - } - fPretty.appendf("%c", fInput[fIndex++]); - } - } - - // this code assumes it is not actually searching for a newline. If you need to search for a - // newline, then use the function above. If you do search for a newline with this function - // it will consume the entire string and the output will certainly not be prettified - void parseUntil(const char* token) { - while (fLength > fIndex) { - // For embedded newlines, this code will make sure to embed the newline in the - // pretty string, increase the linecount, and tab out the next line to the appropriate - // place - if ('\n' == fInput[fIndex]) { - this->newline(); - this->tabString(); - fIndex++; - } - if (this->hasToken(token)) { - break; - } - fFreshline = false; - fPretty.appendf("%c", fInput[fIndex++]); - } - } - - // We only tab if on a newline, otherwise consider the line tabbed - void tabString() { - if (fFreshline) { - for (int t = 0; t < fTabs; t++) { - fPretty.append("\t"); - } - } - } - - // newline is really a request to add a newline, if we are on a fresh line there is no reason - // to add another newline - void newline() { - if (!fFreshline) { - fFreshline = true; - fPretty.append("\n"); - this->lineNumbering(); - } - } - - void lineNumbering() { - if (fCountlines) { - fPretty.appendf("%4d\t", fLinecount++); - } - } - - bool fCountlines, fFreshline; - int fTabs, fLinecount; - size_t fIndex, fLength; - SkString fInput, fPretty; -}; - -SkString PrettyPrintGLSL(const SkString& input, bool countlines) { - GLSLPrettyPrint pp; - return pp.prettify(input, countlines); -} - -} // end namespace diff --git a/src/gpu/gl/GrGLShaderBuilder.cpp b/src/gpu/gl/GrGLShaderBuilder.cpp deleted file mode 100644 index 9fffd26145..0000000000 --- a/src/gpu/gl/GrGLShaderBuilder.cpp +++ /dev/null @@ -1,1071 +0,0 @@ -/* - * Copyright 2012 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "gl/GrGLShaderBuilder.h" -#include "gl/GrGLProgram.h" -#include "gl/GrGLSLPrettyPrint.h" -#include "gl/GrGLUniformHandle.h" -#include "GrCoordTransform.h" -#include "GrDrawEffect.h" -#include "GrGpuGL.h" -#include "GrTexture.h" -#include "SkRTConf.h" -#include "SkTraceEvent.h" - -#define GL_CALL(X) GR_GL_CALL(this->gpu()->glInterface(), X) -#define GL_CALL_RET(R, X) GR_GL_CALL_RET(this->gpu()->glInterface(), R, X) - -// number of each input/output type in a single allocation block -static const int kVarsPerBlock = 8; - -// except FS outputs where we expect 2 at most. -static const int kMaxFSOutputs = 2; - -// ES2 FS only guarantees mediump and lowp support -static const GrGLShaderVar::Precision kDefaultFragmentPrecision = GrGLShaderVar::kMedium_Precision; - -typedef GrGLProgramDataManager::UniformHandle UniformHandle; - -SK_CONF_DECLARE(bool, c_PrintShaders, "gpu.printShaders", false, - "Print the source code for all shaders generated."); - -/////////////////////////////////////////////////////////////////////////////// - -namespace { - -inline const char* color_attribute_name() { return "aColor"; } -inline const char* coverage_attribute_name() { return "aCoverage"; } -inline const char* declared_color_output_name() { return "fsColorOut"; } -inline const char* dual_source_output_name() { return "dualSourceOut"; } -inline const char* sample_function_name(GrSLType type, GrGLSLGeneration glslGen) { - if (kVec2f_GrSLType == type) { - return glslGen >= k130_GrGLSLGeneration ? "texture" : "texture2D"; - } else { - SkASSERT(kVec3f_GrSLType == type); - return glslGen >= k130_GrGLSLGeneration ? "textureProj" : "texture2DProj"; - } -} - -void append_texture_lookup(SkString* out, - GrGpuGL* gpu, - const char* samplerName, - const char* coordName, - uint32_t configComponentMask, - const char* swizzle, - GrSLType varyingType = kVec2f_GrSLType) { - SkASSERT(NULL != coordName); - - out->appendf("%s(%s, %s)", - sample_function_name(varyingType, gpu->glslGeneration()), - samplerName, - coordName); - - char mangledSwizzle[5]; - - // The swizzling occurs using texture params instead of shader-mangling if ARB_texture_swizzle - // is available. - if (!gpu->glCaps().textureSwizzleSupport() && - (kA_GrColorComponentFlag == configComponentMask)) { - char alphaChar = gpu->glCaps().textureRedSupport() ? 'r' : 'a'; - int i; - for (i = 0; '\0' != swizzle[i]; ++i) { - mangledSwizzle[i] = alphaChar; - } - mangledSwizzle[i] ='\0'; - swizzle = mangledSwizzle; - } - // For shader prettiness we omit the swizzle rather than appending ".rgba". - if (memcmp(swizzle, "rgba", 4)) { - out->appendf(".%s", swizzle); - } -} - -} - -static const char kDstCopyColorName[] = "_dstColor"; - -/////////////////////////////////////////////////////////////////////////////// - -bool GrGLShaderBuilder::genProgram(const GrEffectStage* colorStages[], - const GrEffectStage* coverageStages[]) { - const GrGLProgramDesc::KeyHeader& header = this->desc().getHeader(); - - /////////////////////////////////////////////////////////////////////////// - // emit code to read the dst copy texture, if necessary - if (kNoDstRead_DstReadKey != header.fDstReadKey && !fGpu->glCaps().fbFetchSupport()) { - bool topDown = SkToBool(kTopLeftOrigin_DstReadKeyBit & header.fDstReadKey); - const char* dstCopyTopLeftName; - const char* dstCopyCoordScaleName; - const char* dstCopySamplerName; - uint32_t configMask; - if (SkToBool(kUseAlphaConfig_DstReadKeyBit & header.fDstReadKey)) { - configMask = kA_GrColorComponentFlag; - } else { - configMask = kRGBA_GrColorComponentFlags; - } - fUniformHandles.fDstCopySamplerUni = - this->addUniform(kFragment_Visibility, kSampler2D_GrSLType, "DstCopySampler", - &dstCopySamplerName); - fUniformHandles.fDstCopyTopLeftUni = - this->addUniform(kFragment_Visibility, kVec2f_GrSLType, "DstCopyUpperLeft", - &dstCopyTopLeftName); - fUniformHandles.fDstCopyScaleUni = - this->addUniform(kFragment_Visibility, kVec2f_GrSLType, "DstCopyCoordScale", - &dstCopyCoordScaleName); - const char* fragPos = this->fragmentPosition(); - this->fsCodeAppend("\t// Read color from copy of the destination.\n"); - this->fsCodeAppendf("\tvec2 _dstTexCoord = (%s.xy - %s) * %s;\n", - fragPos, dstCopyTopLeftName, dstCopyCoordScaleName); - if (!topDown) { - this->fsCodeAppend("\t_dstTexCoord.y = 1.0 - _dstTexCoord.y;\n"); - } - this->fsCodeAppendf("\tvec4 %s = ", kDstCopyColorName); - append_texture_lookup(&fFSCode, - fGpu, - dstCopySamplerName, - "_dstTexCoord", - configMask, - "rgba"); - this->fsCodeAppend(";\n\n"); - } - - /////////////////////////////////////////////////////////////////////////// - // get the initial color and coverage to feed into the first effect in each effect chain - - GrGLSLExpr4 inputColor; - GrGLSLExpr4 inputCoverage; - - if (GrGLProgramDesc::kUniform_ColorInput == header.fColorInput) { - const char* name; - fUniformHandles.fColorUni = - this->addUniform(GrGLShaderBuilder::kFragment_Visibility, kVec4f_GrSLType, "Color", - &name); - inputColor = GrGLSLExpr4(name); - } - - if (GrGLProgramDesc::kUniform_ColorInput == header.fCoverageInput) { - const char* name; - fUniformHandles.fCoverageUni = - this->addUniform(GrGLShaderBuilder::kFragment_Visibility, kVec4f_GrSLType, "Coverage", - &name); - inputCoverage = GrGLSLExpr4(name); - } else if (GrGLProgramDesc::kSolidWhite_ColorInput == header.fCoverageInput) { - inputCoverage = GrGLSLExpr4(1); - } - - if (k110_GrGLSLGeneration != fGpu->glslGeneration()) { - fFSOutputs.push_back().set(kVec4f_GrSLType, - GrGLShaderVar::kOut_TypeModifier, - declared_color_output_name()); - fHasCustomColorOutput = true; - } - - this->emitCodeBeforeEffects(&inputColor, &inputCoverage); - - /////////////////////////////////////////////////////////////////////////// - // emit the per-effect code for both color and coverage effects - - GrGLProgramDesc::EffectKeyProvider colorKeyProvider( - &this->desc(), GrGLProgramDesc::EffectKeyProvider::kColor_EffectType); - fColorEffects.reset(this->createAndEmitEffects(colorStages, - this->desc().numColorEffects(), - colorKeyProvider, - &inputColor)); - - GrGLProgramDesc::EffectKeyProvider coverageKeyProvider( - &this->desc(), GrGLProgramDesc::EffectKeyProvider::kCoverage_EffectType); - fCoverageEffects.reset(this->createAndEmitEffects(coverageStages, - this->desc().numCoverageEffects(), - coverageKeyProvider, - &inputCoverage)); - - this->emitCodeAfterEffects(); - - /////////////////////////////////////////////////////////////////////////// - // write the secondary color output if necessary - if (GrGLProgramDesc::CoverageOutputUsesSecondaryOutput(header.fCoverageOutput)) { - const char* secondaryOutputName = this->enableSecondaryOutput(); - - // default coeff to ones for kCoverage_DualSrcOutput - GrGLSLExpr4 coeff(1); - if (GrGLProgramDesc::kSecondaryCoverageISA_CoverageOutput == header.fCoverageOutput) { - // Get (1-A) into coeff - coeff = GrGLSLExpr4::VectorCast(GrGLSLExpr1(1) - inputColor.a()); - } else if (GrGLProgramDesc::kSecondaryCoverageISC_CoverageOutput == - header.fCoverageOutput){ - // Get (1-RGBA) into coeff - coeff = GrGLSLExpr4(1) - inputColor; - } - // Get coeff * coverage into modulate and then write that to the dual source output. - this->fsCodeAppendf("\t%s = %s;\n", secondaryOutputName, (coeff * inputCoverage).c_str()); - } - - /////////////////////////////////////////////////////////////////////////// - // combine color and coverage as frag color - - // Get "color * coverage" into fragColor - GrGLSLExpr4 fragColor = inputColor * inputCoverage; - // Now tack on "+(1-coverage)dst onto the frag color if we were asked to do so. - if (GrGLProgramDesc::kCombineWithDst_CoverageOutput == header.fCoverageOutput) { - GrGLSLExpr4 dstCoeff = GrGLSLExpr4(1) - inputCoverage; - - GrGLSLExpr4 dstContribution = dstCoeff * GrGLSLExpr4(this->dstColor()); - - fragColor = fragColor + dstContribution; - } - this->fsCodeAppendf("\t%s = %s;\n", this->getColorOutputName(), fragColor.c_str()); - - if (!this->finish()) { - return false; - } - - return true; -} - -////////////////////////////////////////////////////////////////////////////// - -GrGLShaderBuilder::GrGLShaderBuilder(GrGpuGL* gpu, - const GrGLProgramDesc& desc) - : fHasVertexShader(false) - , fTexCoordSetCnt(0) - , fProgramID(0) - , fDesc(desc) - , fGpu(gpu) - , fFSFeaturesAddedMask(0) - , fFSInputs(kVarsPerBlock) - , fFSOutputs(kMaxFSOutputs) - , fUniforms(kVarsPerBlock) - , fSetupFragPosition(false) - , fTopLeftFragPosRead(kTopLeftFragPosRead_FragPosKey == desc.getHeader().fFragPosKey) - , fHasCustomColorOutput(false) - , fHasSecondaryOutput(false) { -} - -bool GrGLShaderBuilder::enableFeature(GLSLFeature feature) { - switch (feature) { - case kStandardDerivatives_GLSLFeature: - if (!fGpu->glCaps().shaderDerivativeSupport()) { - return false; - } - if (kGLES_GrGLStandard == fGpu->glStandard()) { - this->addFSFeature(1 << kStandardDerivatives_GLSLFeature, - "GL_OES_standard_derivatives"); - } - return true; - default: - SkFAIL("Unexpected GLSLFeature requested."); - return false; - } -} - -void GrGLShaderBuilder::addFSFeature(uint32_t featureBit, const char* extensionName) { - if (!(featureBit & fFSFeaturesAddedMask)) { - fFSExtensions.appendf("#extension %s: require\n", extensionName); - fFSFeaturesAddedMask |= featureBit; - } -} - -void GrGLShaderBuilder::nameVariable(SkString* out, char prefix, const char* name) { - if ('\0' == prefix) { - *out = name; - } else { - out->printf("%c%s", prefix, name); - } - if (fCodeStage.inStageCode()) { - if (out->endsWith('_')) { - // Names containing "__" are reserved. - out->append("x"); - } - out->appendf("_Stage%d", fCodeStage.stageIndex()); - } -} - -const char* GrGLShaderBuilder::dstColor() { - if (fCodeStage.inStageCode()) { - const GrEffect* effect = fCodeStage.effectStage()->getEffect(); - if (!effect->willReadDstColor()) { - SkDEBUGFAIL("GrGLEffect asked for dst color but its generating GrEffect " - "did not request access."); - return ""; - } - } - - if (fGpu->glCaps().fbFetchSupport()) { - this->addFSFeature(1 << (kLastGLSLPrivateFeature + 1), - fGpu->glCaps().fbFetchExtensionString()); - return fGpu->glCaps().fbFetchColorName(); - } else if (fUniformHandles.fDstCopySamplerUni.isValid()) { - return kDstCopyColorName; - } else { - return ""; - } -} - -void GrGLShaderBuilder::appendTextureLookup(SkString* out, - const GrGLShaderBuilder::TextureSampler& sampler, - const char* coordName, - GrSLType varyingType) const { - append_texture_lookup(out, - fGpu, - this->getUniformCStr(sampler.samplerUniform()), - coordName, - sampler.configComponentMask(), - sampler.swizzle(), - varyingType); -} - -void GrGLShaderBuilder::fsAppendTextureLookup(const GrGLShaderBuilder::TextureSampler& sampler, - const char* coordName, - GrSLType varyingType) { - this->appendTextureLookup(&fFSCode, sampler, coordName, varyingType); -} - -void GrGLShaderBuilder::fsAppendTextureLookupAndModulate( - const char* modulation, - const GrGLShaderBuilder::TextureSampler& sampler, - const char* coordName, - GrSLType varyingType) { - SkString lookup; - this->appendTextureLookup(&lookup, sampler, coordName, varyingType); - fFSCode.append((GrGLSLExpr4(modulation) * GrGLSLExpr4(lookup)).c_str()); -} - -GrGLShaderBuilder::DstReadKey GrGLShaderBuilder::KeyForDstRead(const GrTexture* dstCopy, - const GrGLCaps& caps) { - uint32_t key = kYesDstRead_DstReadKeyBit; - if (caps.fbFetchSupport()) { - return key; - } - SkASSERT(NULL != dstCopy); - if (!caps.textureSwizzleSupport() && GrPixelConfigIsAlphaOnly(dstCopy->config())) { - // The fact that the config is alpha-only must be considered when generating code. - key |= kUseAlphaConfig_DstReadKeyBit; - } - if (kTopLeft_GrSurfaceOrigin == dstCopy->origin()) { - key |= kTopLeftOrigin_DstReadKeyBit; - } - SkASSERT(static_cast(key) == key); - return static_cast(key); -} - -GrGLShaderBuilder::FragPosKey GrGLShaderBuilder::KeyForFragmentPosition(const GrRenderTarget* dst, - const GrGLCaps&) { - if (kTopLeft_GrSurfaceOrigin == dst->origin()) { - return kTopLeftFragPosRead_FragPosKey; - } else { - return kBottomLeftFragPosRead_FragPosKey; - } -} - - -const GrGLenum* GrGLShaderBuilder::GetTexParamSwizzle(GrPixelConfig config, const GrGLCaps& caps) { - if (caps.textureSwizzleSupport() && GrPixelConfigIsAlphaOnly(config)) { - if (caps.textureRedSupport()) { - static const GrGLenum gRedSmear[] = { GR_GL_RED, GR_GL_RED, GR_GL_RED, GR_GL_RED }; - return gRedSmear; - } else { - static const GrGLenum gAlphaSmear[] = { GR_GL_ALPHA, GR_GL_ALPHA, - GR_GL_ALPHA, GR_GL_ALPHA }; - return gAlphaSmear; - } - } else { - static const GrGLenum gStraight[] = { GR_GL_RED, GR_GL_GREEN, GR_GL_BLUE, GR_GL_ALPHA }; - return gStraight; - } -} - -GrGLProgramDataManager::UniformHandle GrGLShaderBuilder::addUniformArray(uint32_t visibility, - GrSLType type, - const char* name, - int count, - const char** outName) { - SkASSERT(name && strlen(name)); - SkDEBUGCODE(static const uint32_t kVisibilityMask = kVertex_Visibility | kFragment_Visibility); - SkASSERT(0 == (~kVisibilityMask & visibility)); - SkASSERT(0 != visibility); - - UniformInfo& uni = fUniforms.push_back(); - uni.fVariable.setType(type); - uni.fVariable.setTypeModifier(GrGLShaderVar::kUniform_TypeModifier); - this->nameVariable(uni.fVariable.accessName(), 'u', name); - uni.fVariable.setArrayCount(count); - uni.fVisibility = visibility; - - // If it is visible in both the VS and FS, the precision must match. - // We declare a default FS precision, but not a default VS. So set the var - // to use the default FS precision. - if ((kVertex_Visibility | kFragment_Visibility) == visibility) { - // the fragment and vertex precisions must match - uni.fVariable.setPrecision(kDefaultFragmentPrecision); - } - - if (NULL != outName) { - *outName = uni.fVariable.c_str(); - } - return GrGLProgramDataManager::UniformHandle::CreateFromUniformIndex(fUniforms.count() - 1); -} - -SkString GrGLShaderBuilder::ensureFSCoords2D(const TransformedCoordsArray& coords, int index) { - if (kVec3f_GrSLType != coords[index].type()) { - SkASSERT(kVec2f_GrSLType == coords[index].type()); - return coords[index].getName(); - } - - SkString coords2D("coords2D"); - if (0 != index) { - coords2D.appendf("_%i", index); - } - this->fsCodeAppendf("\tvec2 %s = %s.xy / %s.z;", - coords2D.c_str(), coords[index].c_str(), coords[index].c_str()); - return coords2D; -} - -const char* GrGLShaderBuilder::fragmentPosition() { - if (fCodeStage.inStageCode()) { - const GrEffect* effect = fCodeStage.effectStage()->getEffect(); - if (!effect->willReadFragmentPosition()) { - SkDEBUGFAIL("GrGLEffect asked for frag position but its generating GrEffect " - "did not request access."); - return ""; - } - } - // We only declare "gl_FragCoord" when we're in the case where we want to use layout qualifiers - // to reverse y. Otherwise it isn't necessary and whether the "in" qualifier appears in the - // declaration varies in earlier GLSL specs. So it is simpler to omit it. - if (fTopLeftFragPosRead) { - fSetupFragPosition = true; - return "gl_FragCoord"; - } else if (fGpu->glCaps().fragCoordConventionsSupport()) { - if (!fSetupFragPosition) { - if (fGpu->glslGeneration() < k150_GrGLSLGeneration) { - this->addFSFeature(1 << kFragCoordConventions_GLSLPrivateFeature, - "GL_ARB_fragment_coord_conventions"); - } - fFSInputs.push_back().set(kVec4f_GrSLType, - GrGLShaderVar::kIn_TypeModifier, - "gl_FragCoord", - GrGLShaderVar::kDefault_Precision, - GrGLShaderVar::kUpperLeft_Origin); - fSetupFragPosition = true; - } - return "gl_FragCoord"; - } else { - static const char* kCoordName = "fragCoordYDown"; - if (!fSetupFragPosition) { - // temporarily change the stage index because we're inserting non-stage code. - CodeStage::AutoStageRestore csar(&fCodeStage, NULL); - - SkASSERT(!fUniformHandles.fRTHeightUni.isValid()); - const char* rtHeightName; - - fUniformHandles.fRTHeightUni = - this->addUniform(kFragment_Visibility, kFloat_GrSLType, "RTHeight", &rtHeightName); - - // Using glFragCoord.zw for the last two components tickles an Adreno driver bug that - // causes programs to fail to link. Making this function return a vec2() didn't fix the - // problem but using 1.0 for the last two components does. - this->fFSCode.prependf("\tvec4 %s = vec4(gl_FragCoord.x, %s - gl_FragCoord.y, 1.0, " - "1.0);\n", kCoordName, rtHeightName); - fSetupFragPosition = true; - } - SkASSERT(fUniformHandles.fRTHeightUni.isValid()); - return kCoordName; - } -} - -void GrGLShaderBuilder::fsEmitFunction(GrSLType returnType, - const char* name, - int argCnt, - const GrGLShaderVar* args, - const char* body, - SkString* outName) { - fFSFunctions.append(GrGLSLTypeString(returnType)); - this->nameVariable(outName, '\0', name); - fFSFunctions.appendf(" %s", outName->c_str()); - fFSFunctions.append("("); - for (int i = 0; i < argCnt; ++i) { - args[i].appendDecl(this->ctxInfo(), &fFSFunctions); - if (i < argCnt - 1) { - fFSFunctions.append(", "); - } - } - fFSFunctions.append(") {\n"); - fFSFunctions.append(body); - fFSFunctions.append("}\n\n"); -} - -namespace { - -inline void append_default_precision_qualifier(GrGLShaderVar::Precision p, - GrGLStandard standard, - SkString* str) { - // Desktop GLSL has added precision qualifiers but they don't do anything. - if (kGLES_GrGLStandard == standard) { - switch (p) { - case GrGLShaderVar::kHigh_Precision: - str->append("precision highp float;\n"); - break; - case GrGLShaderVar::kMedium_Precision: - str->append("precision mediump float;\n"); - break; - case GrGLShaderVar::kLow_Precision: - str->append("precision lowp float;\n"); - break; - case GrGLShaderVar::kDefault_Precision: - SkFAIL("Default precision now allowed."); - default: - SkFAIL("Unknown precision value."); - } - } -} -} - -void GrGLShaderBuilder::appendDecls(const VarArray& vars, SkString* out) const { - for (int i = 0; i < vars.count(); ++i) { - vars[i].appendDecl(this->ctxInfo(), out); - out->append(";\n"); - } -} - -void GrGLShaderBuilder::appendUniformDecls(ShaderVisibility visibility, - SkString* out) const { - for (int i = 0; i < fUniforms.count(); ++i) { - if (fUniforms[i].fVisibility & visibility) { - fUniforms[i].fVariable.appendDecl(this->ctxInfo(), out); - out->append(";\n"); - } - } -} - -void GrGLShaderBuilder::createAndEmitEffects(GrGLProgramEffectsBuilder* programEffectsBuilder, - const GrEffectStage* effectStages[], - int effectCnt, - const GrGLProgramDesc::EffectKeyProvider& keyProvider, - GrGLSLExpr4* fsInOutColor) { - bool effectEmitted = false; - - GrGLSLExpr4 inColor = *fsInOutColor; - GrGLSLExpr4 outColor; - - for (int e = 0; e < effectCnt; ++e) { - SkASSERT(NULL != effectStages[e] && NULL != effectStages[e]->getEffect()); - const GrEffectStage& stage = *effectStages[e]; - - CodeStage::AutoStageRestore csar(&fCodeStage, &stage); - - if (inColor.isZeros()) { - SkString inColorName; - - // Effects have no way to communicate zeros, they treat an empty string as ones. - this->nameVariable(&inColorName, '\0', "input"); - this->fsCodeAppendf("\tvec4 %s = %s;\n", inColorName.c_str(), inColor.c_str()); - inColor = inColorName; - } - - // create var to hold stage result - SkString outColorName; - this->nameVariable(&outColorName, '\0', "output"); - this->fsCodeAppendf("\tvec4 %s;\n", outColorName.c_str()); - outColor = outColorName; - - - programEffectsBuilder->emitEffect(stage, - keyProvider.get(e), - outColor.c_str(), - inColor.isOnes() ? NULL : inColor.c_str(), - fCodeStage.stageIndex()); - - inColor = outColor; - effectEmitted = true; - } - - if (effectEmitted) { - *fsInOutColor = outColor; - } -} - -const char* GrGLShaderBuilder::getColorOutputName() const { - return fHasCustomColorOutput ? declared_color_output_name() : "gl_FragColor"; -} - -const char* GrGLShaderBuilder::enableSecondaryOutput() { - if (!fHasSecondaryOutput) { - fFSOutputs.push_back().set(kVec4f_GrSLType, - GrGLShaderVar::kOut_TypeModifier, - dual_source_output_name()); - fHasSecondaryOutput = true; - } - return dual_source_output_name(); -} - -bool GrGLShaderBuilder::finish() { - SkASSERT(0 == fProgramID); - GL_CALL_RET(fProgramID, CreateProgram()); - if (!fProgramID) { - return false; - } - - SkTDArray shadersToDelete; - - if (!this->compileAndAttachShaders(fProgramID, &shadersToDelete)) { - GL_CALL(DeleteProgram(fProgramID)); - return false; - } - - this->bindProgramLocations(fProgramID); - - GL_CALL(LinkProgram(fProgramID)); - - // Calling GetProgramiv is expensive in Chromium. Assume success in release builds. - bool checkLinked = !fGpu->ctxInfo().isChromium(); -#ifdef SK_DEBUG - checkLinked = true; -#endif - if (checkLinked) { - GrGLint linked = GR_GL_INIT_ZERO; - GL_CALL(GetProgramiv(fProgramID, GR_GL_LINK_STATUS, &linked)); - if (!linked) { - GrGLint infoLen = GR_GL_INIT_ZERO; - GL_CALL(GetProgramiv(fProgramID, GR_GL_INFO_LOG_LENGTH, &infoLen)); - SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger - if (infoLen > 0) { - // retrieve length even though we don't need it to workaround - // bug in chrome cmd buffer param validation. - GrGLsizei length = GR_GL_INIT_ZERO; - GL_CALL(GetProgramInfoLog(fProgramID, - infoLen+1, - &length, - (char*)log.get())); - GrPrintf((char*)log.get()); - } - SkDEBUGFAIL("Error linking program"); - GL_CALL(DeleteProgram(fProgramID)); - fProgramID = 0; - return false; - } - } - - this->resolveProgramLocations(fProgramID); - - for (int i = 0; i < shadersToDelete.count(); ++i) { - GL_CALL(DeleteShader(shadersToDelete[i])); - } - - return true; -} - -// Compiles a GL shader and attaches it to a program. Returns the shader ID if -// successful, or 0 if not. -static GrGLuint attach_shader(const GrGLContext& glCtx, - GrGLuint programId, - GrGLenum type, - const SkString& shaderSrc) { - const GrGLInterface* gli = glCtx.interface(); - - GrGLuint shaderId; - GR_GL_CALL_RET(gli, shaderId, CreateShader(type)); - if (0 == shaderId) { - return 0; - } - -#ifdef SK_DEBUG - SkString prettySource = GrGLSLPrettyPrint::PrettyPrintGLSL(shaderSrc, false); - const GrGLchar* sourceStr = prettySource.c_str(); - GrGLint sourceLength = static_cast(prettySource.size()); -#else - GrGLint sourceLength = static_cast(shaderSrc.size()); - const GrGLchar* sourceStr = shaderSrc.c_str(); -#endif - GR_GL_CALL(gli, ShaderSource(shaderId, 1, &sourceStr, &sourceLength)); - GR_GL_CALL(gli, CompileShader(shaderId)); - - // Calling GetShaderiv in Chromium is quite expensive. Assume success in release builds. - bool checkCompiled = !glCtx.isChromium(); -#ifdef SK_DEBUG - checkCompiled = true; -#endif - if (checkCompiled) { - GrGLint compiled = GR_GL_INIT_ZERO; - GR_GL_CALL(gli, GetShaderiv(shaderId, GR_GL_COMPILE_STATUS, &compiled)); - - if (!compiled) { - GrGLint infoLen = GR_GL_INIT_ZERO; - GR_GL_CALL(gli, GetShaderiv(shaderId, GR_GL_INFO_LOG_LENGTH, &infoLen)); - SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger - if (infoLen > 0) { - // retrieve length even though we don't need it to workaround bug in Chromium cmd - // buffer param validation. - GrGLsizei length = GR_GL_INIT_ZERO; - GR_GL_CALL(gli, GetShaderInfoLog(shaderId, infoLen+1, - &length, (char*)log.get())); - GrPrintf(GrGLSLPrettyPrint::PrettyPrintGLSL(shaderSrc, true).c_str()); - GrPrintf("\n%s", log.get()); - } - SkDEBUGFAIL("Shader compilation failed!"); - GR_GL_CALL(gli, DeleteShader(shaderId)); - return 0; - } - } - - TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("skia.gpu"), "skia_gpu::GLShader", - TRACE_EVENT_SCOPE_THREAD, "shader", TRACE_STR_COPY(shaderSrc.c_str())); - if (c_PrintShaders) { - GrPrintf(GrGLSLPrettyPrint::PrettyPrintGLSL(shaderSrc, true).c_str()); - GrPrintf("\n"); - } - - // Attach the shader, but defer deletion until after we have linked the program. - // This works around a bug in the Android emulator's GLES2 wrapper which - // will immediately delete the shader object and free its memory even though it's - // attached to a program, which then causes glLinkProgram to fail. - GR_GL_CALL(gli, AttachShader(programId, shaderId)); - - return shaderId; -} - -bool GrGLShaderBuilder::compileAndAttachShaders(GrGLuint programId, SkTDArray* shaderIds) const { - SkString fragShaderSrc(GrGetGLSLVersionDecl(this->ctxInfo())); - fragShaderSrc.append(fFSExtensions); - append_default_precision_qualifier(kDefaultFragmentPrecision, - fGpu->glStandard(), - &fragShaderSrc); - this->appendUniformDecls(kFragment_Visibility, &fragShaderSrc); - this->appendDecls(fFSInputs, &fragShaderSrc); - // We shouldn't have declared outputs on 1.10 - SkASSERT(k110_GrGLSLGeneration != fGpu->glslGeneration() || fFSOutputs.empty()); - this->appendDecls(fFSOutputs, &fragShaderSrc); - fragShaderSrc.append(fFSFunctions); - fragShaderSrc.append("void main() {\n"); - fragShaderSrc.append(fFSCode); - fragShaderSrc.append("}\n"); - - GrGLuint fragShaderId = attach_shader(fGpu->glContext(), programId, GR_GL_FRAGMENT_SHADER, fragShaderSrc); - if (!fragShaderId) { - return false; - } - - *shaderIds->append() = fragShaderId; - - return true; -} - -void GrGLShaderBuilder::bindProgramLocations(GrGLuint programId) { - if (fHasCustomColorOutput) { - GL_CALL(BindFragDataLocation(programId, 0, declared_color_output_name())); - } - if (fHasSecondaryOutput) { - GL_CALL(BindFragDataLocationIndexed(programId, 0, 1, dual_source_output_name())); - } - // skbug.com/2056 - bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation != NULL; - if (usingBindUniform) { - int count = fUniforms.count(); - for (int i = 0; i < count; ++i) { - GL_CALL(BindUniformLocation(programId, i, fUniforms[i].fVariable.c_str())); - fUniforms[i].fLocation = i; - } - } -} - -void GrGLShaderBuilder::resolveProgramLocations(GrGLuint programId) { - bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation != NULL; - if (!usingBindUniform) { - int count = fUniforms.count(); - for (int i = 0; i < count; ++i) { - GrGLint location; - GL_CALL_RET(location, - GetUniformLocation(programId, fUniforms[i].fVariable.c_str())); - fUniforms[i].fLocation = location; - } - } -} - -const GrGLContextInfo& GrGLShaderBuilder::ctxInfo() const { - return fGpu->ctxInfo(); -} - -//////////////////////////////////////////////////////////////////////////////// - -GrGLFullShaderBuilder::GrGLFullShaderBuilder(GrGpuGL* gpu, - const GrGLProgramDesc& desc) - : INHERITED(gpu, desc) - , fVSAttrs(kVarsPerBlock) - , fVSOutputs(kVarsPerBlock) - , fGSInputs(kVarsPerBlock) - , fGSOutputs(kVarsPerBlock) { -} - -void GrGLFullShaderBuilder::emitCodeBeforeEffects(GrGLSLExpr4* color, GrGLSLExpr4* coverage) { - const GrGLProgramDesc::KeyHeader& header = this->desc().getHeader(); - - fHasVertexShader = true; - - fPositionVar = &fVSAttrs.push_back(); - fPositionVar->set(kVec2f_GrSLType, GrGLShaderVar::kAttribute_TypeModifier, "aPosition"); - if (-1 != header.fLocalCoordAttributeIndex) { - fLocalCoordsVar = &fVSAttrs.push_back(); - fLocalCoordsVar->set(kVec2f_GrSLType, - GrGLShaderVar::kAttribute_TypeModifier, - "aLocalCoords"); - } else { - fLocalCoordsVar = fPositionVar; - } - - const char* viewMName; - fUniformHandles.fViewMatrixUni = - this->addUniform(GrGLShaderBuilder::kVertex_Visibility, kMat33f_GrSLType, "ViewM", - &viewMName); - - // Transform the position into Skia's device coords. - this->vsCodeAppendf("\tvec3 pos3 = %s * vec3(%s, 1);\n", - viewMName, fPositionVar->c_str()); - - // we output point size in the GS if present - if (header.fEmitsPointSize -#if GR_GL_EXPERIMENTAL_GS - && !header.fExperimentalGS -#endif - ) { - this->vsCodeAppend("\tgl_PointSize = 1.0;\n"); - } - - if (GrGLProgramDesc::kAttribute_ColorInput == header.fColorInput) { - this->addAttribute(kVec4f_GrSLType, color_attribute_name()); - const char *vsName, *fsName; - this->addVarying(kVec4f_GrSLType, "Color", &vsName, &fsName); - this->vsCodeAppendf("\t%s = %s;\n", vsName, color_attribute_name()); - *color = fsName; - } - - if (GrGLProgramDesc::kAttribute_ColorInput == header.fCoverageInput) { - this->addAttribute(kVec4f_GrSLType, coverage_attribute_name()); - const char *vsName, *fsName; - this->addVarying(kVec4f_GrSLType, "Coverage", &vsName, &fsName); - this->vsCodeAppendf("\t%s = %s;\n", vsName, coverage_attribute_name()); - *coverage = fsName; - } -} - -void GrGLFullShaderBuilder::emitCodeAfterEffects() { - const char* rtAdjustName; - fUniformHandles.fRTAdjustmentUni = - this->addUniform(GrGLShaderBuilder::kVertex_Visibility, kVec4f_GrSLType, "rtAdjustment", - &rtAdjustName); - - // Transform from Skia's device coords to GL's normalized device coords. - this->vsCodeAppendf( - "\tgl_Position = vec4(dot(pos3.xz, %s.xy), dot(pos3.yz, %s.zw), 0, pos3.z);\n", - rtAdjustName, rtAdjustName); -} - -bool GrGLFullShaderBuilder::addAttribute(GrSLType type, const char* name) { - for (int i = 0; i < fVSAttrs.count(); ++i) { - const GrGLShaderVar& attr = fVSAttrs[i]; - // if attribute already added, don't add it again - if (attr.getName().equals(name)) { - SkASSERT(attr.getType() == type); - return false; - } - } - fVSAttrs.push_back().set(type, - GrGLShaderVar::kAttribute_TypeModifier, - name); - return true; -} - -bool GrGLFullShaderBuilder::addEffectAttribute(int attributeIndex, - GrSLType type, - const SkString& name) { - if (!this->addAttribute(type, name.c_str())) { - return false; - } - - fEffectAttributes.push_back().set(attributeIndex, name); - return true; -} - -void GrGLFullShaderBuilder::addVarying(GrSLType type, - const char* name, - const char** vsOutName, - const char** fsInName) { - fVSOutputs.push_back(); - fVSOutputs.back().setType(type); - fVSOutputs.back().setTypeModifier(GrGLShaderVar::kVaryingOut_TypeModifier); - this->nameVariable(fVSOutputs.back().accessName(), 'v', name); - - if (vsOutName) { - *vsOutName = fVSOutputs.back().getName().c_str(); - } - // input to FS comes either from VS or GS - const SkString* fsName; -#if GR_GL_EXPERIMENTAL_GS - if (this->desc().getHeader().fExperimentalGS) { - // if we have a GS take each varying in as an array - // and output as non-array. - fGSInputs.push_back(); - fGSInputs.back().setType(type); - fGSInputs.back().setTypeModifier(GrGLShaderVar::kVaryingIn_TypeModifier); - fGSInputs.back().setUnsizedArray(); - *fGSInputs.back().accessName() = fVSOutputs.back().getName(); - fGSOutputs.push_back(); - fGSOutputs.back().setType(type); - fGSOutputs.back().setTypeModifier(GrGLShaderVar::kVaryingOut_TypeModifier); - this->nameVariable(fGSOutputs.back().accessName(), 'g', name); - fsName = fGSOutputs.back().accessName(); - } else -#endif - { - fsName = fVSOutputs.back().accessName(); - } - this->fsInputAppend().set(type, GrGLShaderVar::kVaryingIn_TypeModifier, *fsName); - if (fsInName) { - *fsInName = fsName->c_str(); - } -} - -const SkString* GrGLFullShaderBuilder::getEffectAttributeName(int attributeIndex) const { - const AttributePair* attribEnd = fEffectAttributes.end(); - for (const AttributePair* attrib = fEffectAttributes.begin(); attrib != attribEnd; ++attrib) { - if (attrib->fIndex == attributeIndex) { - return &attrib->fName; - } - } - - return NULL; -} - -GrGLProgramEffects* GrGLFullShaderBuilder::createAndEmitEffects( - const GrEffectStage* effectStages[], - int effectCnt, - const GrGLProgramDesc::EffectKeyProvider& keyProvider, - GrGLSLExpr4* inOutFSColor) { - - GrGLVertexProgramEffectsBuilder programEffectsBuilder(this, effectCnt); - this->INHERITED::createAndEmitEffects(&programEffectsBuilder, - effectStages, - effectCnt, - keyProvider, - inOutFSColor); - return programEffectsBuilder.finish(); -} - -bool GrGLFullShaderBuilder::compileAndAttachShaders(GrGLuint programId, - SkTDArray* shaderIds) const { - const GrGLContext& glCtx = this->gpu()->glContext(); - SkString vertShaderSrc(GrGetGLSLVersionDecl(this->ctxInfo())); - this->appendUniformDecls(kVertex_Visibility, &vertShaderSrc); - this->appendDecls(fVSAttrs, &vertShaderSrc); - this->appendDecls(fVSOutputs, &vertShaderSrc); - vertShaderSrc.append("void main() {\n"); - vertShaderSrc.append(fVSCode); - vertShaderSrc.append("}\n"); - GrGLuint vertShaderId = attach_shader(glCtx, programId, GR_GL_VERTEX_SHADER, vertShaderSrc); - if (!vertShaderId) { - return false; - } - *shaderIds->append() = vertShaderId; - -#if GR_GL_EXPERIMENTAL_GS - if (this->desc().getHeader().fExperimentalGS) { - SkASSERT(this->ctxInfo().glslGeneration() >= k150_GrGLSLGeneration); - SkString geomShaderSrc(GrGetGLSLVersionDecl(this->ctxInfo())); - geomShaderSrc.append("layout(triangles) in;\n" - "layout(triangle_strip, max_vertices = 6) out;\n"); - this->appendDecls(fGSInputs, &geomShaderSrc); - this->appendDecls(fGSOutputs, &geomShaderSrc); - geomShaderSrc.append("void main() {\n"); - geomShaderSrc.append("\tfor (int i = 0; i < 3; ++i) {\n" - "\t\tgl_Position = gl_in[i].gl_Position;\n"); - if (this->desc().getHeader().fEmitsPointSize) { - geomShaderSrc.append("\t\tgl_PointSize = 1.0;\n"); - } - SkASSERT(fGSInputs.count() == fGSOutputs.count()); - for (int i = 0; i < fGSInputs.count(); ++i) { - geomShaderSrc.appendf("\t\t%s = %s[i];\n", - fGSOutputs[i].getName().c_str(), - fGSInputs[i].getName().c_str()); - } - geomShaderSrc.append("\t\tEmitVertex();\n" - "\t}\n" - "\tEndPrimitive();\n"); - geomShaderSrc.append("}\n"); - GrGLuint geomShaderId = attach_shader(glCtx, programId, GR_GL_GEOMETRY_SHADER, geomShaderSrc); - if (!geomShaderId) { - return false; - } - *shaderIds->append() = geomShaderId; - } -#endif - - return this->INHERITED::compileAndAttachShaders(programId, shaderIds); -} - -void GrGLFullShaderBuilder::bindProgramLocations(GrGLuint programId) { - this->INHERITED::bindProgramLocations(programId); - - const GrGLProgramDesc::KeyHeader& header = this->desc().getHeader(); - - // Bind the attrib locations to same values for all shaders - SkASSERT(-1 != header.fPositionAttributeIndex); - GL_CALL(BindAttribLocation(programId, - header.fPositionAttributeIndex, - fPositionVar->c_str())); - if (-1 != header.fLocalCoordAttributeIndex) { - GL_CALL(BindAttribLocation(programId, - header.fLocalCoordAttributeIndex, - fLocalCoordsVar->c_str())); - } - if (-1 != header.fColorAttributeIndex) { - GL_CALL(BindAttribLocation(programId, - header.fColorAttributeIndex, - color_attribute_name())); - } - if (-1 != header.fCoverageAttributeIndex) { - GL_CALL(BindAttribLocation(programId, - header.fCoverageAttributeIndex, - coverage_attribute_name())); - } - - const AttributePair* attribEnd = fEffectAttributes.end(); - for (const AttributePair* attrib = fEffectAttributes.begin(); attrib != attribEnd; ++attrib) { - GL_CALL(BindAttribLocation(programId, attrib->fIndex, attrib->fName.c_str())); - } -} - -//////////////////////////////////////////////////////////////////////////////// - -GrGLFragmentOnlyShaderBuilder::GrGLFragmentOnlyShaderBuilder(GrGpuGL* gpu, - const GrGLProgramDesc& desc) - : INHERITED(gpu, desc) { - SkASSERT(!desc.getHeader().fHasVertexCode); - SkASSERT(gpu->glCaps().pathRenderingSupport()); - SkASSERT(GrGLProgramDesc::kAttribute_ColorInput != desc.getHeader().fColorInput); - SkASSERT(GrGLProgramDesc::kAttribute_ColorInput != desc.getHeader().fCoverageInput); -} - -int GrGLFragmentOnlyShaderBuilder::addTexCoordSets(int count) { - int firstFreeCoordSet = fTexCoordSetCnt; - fTexCoordSetCnt += count; - SkASSERT(gpu()->glCaps().maxFixedFunctionTextureCoords() >= fTexCoordSetCnt); - return firstFreeCoordSet; -} - -GrGLProgramEffects* GrGLFragmentOnlyShaderBuilder::createAndEmitEffects( - const GrEffectStage* effectStages[], - int effectCnt, - const GrGLProgramDesc::EffectKeyProvider& keyProvider, - GrGLSLExpr4* inOutFSColor) { - - GrGLPathTexGenProgramEffectsBuilder pathTexGenEffectsBuilder(this, - effectCnt); - this->INHERITED::createAndEmitEffects(&pathTexGenEffectsBuilder, - effectStages, - effectCnt, - keyProvider, - inOutFSColor); - return pathTexGenEffectsBuilder.finish(); -} diff --git a/src/gpu/gl/GrGLShaderBuilder.h b/src/gpu/gl/GrGLShaderBuilder.h deleted file mode 100644 index 2a14a1f625..0000000000 --- a/src/gpu/gl/GrGLShaderBuilder.h +++ /dev/null @@ -1,517 +0,0 @@ -/* - * Copyright 2012 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef GrGLShaderBuilder_DEFINED -#define GrGLShaderBuilder_DEFINED - -#include "GrAllocator.h" -#include "GrBackendEffectFactory.h" -#include "GrColor.h" -#include "GrEffect.h" -#include "SkTypes.h" -#include "gl/GrGLProgramDesc.h" -#include "gl/GrGLProgramEffects.h" -#include "gl/GrGLSL.h" -#include "gl/GrGLProgramDataManager.h" - -#include - -class GrGLContextInfo; -class GrEffectStage; -class GrGLProgramDesc; - -/** - Contains all the incremental state of a shader as it is being built,as well as helpers to - manipulate that state. -*/ -class GrGLShaderBuilder { -public: - typedef GrTAllocator VarArray; - typedef GrGLProgramEffects::TextureSampler TextureSampler; - typedef GrGLProgramEffects::TransformedCoordsArray TransformedCoordsArray; - - enum ShaderVisibility { - kVertex_Visibility = 0x1, - kGeometry_Visibility = 0x2, - kFragment_Visibility = 0x4, - }; - - typedef GrGLProgramDataManager::UniformHandle UniformHandle; - - // Handles for program uniforms (other than per-effect uniforms) - struct BuiltinUniformHandles { - UniformHandle fViewMatrixUni; - UniformHandle fRTAdjustmentUni; - UniformHandle fColorUni; - UniformHandle fCoverageUni; - - // We use the render target height to provide a y-down frag coord when specifying - // origin_upper_left is not supported. - UniformHandle fRTHeightUni; - - // Uniforms for computing texture coords to do the dst-copy lookup - UniformHandle fDstCopyTopLeftUni; - UniformHandle fDstCopyScaleUni; - UniformHandle fDstCopySamplerUni; - }; - - struct UniformInfo { - GrGLShaderVar fVariable; - uint32_t fVisibility; - GrGLint fLocation; - }; - - // This uses an allocator rather than array so that the GrGLShaderVars don't move in memory - // after they are inserted. Users of GrGLShaderBuilder get refs to the vars and ptrs to their - // name strings. Otherwise, we'd have to hand out copies. - typedef GrTAllocator UniformInfoArray; - - /** Generates a shader program. - * - * The program implements what is specified in the stages given as input. - * After successful generation, the builder result objects are available - * to be used. - * @return true if generation was successful. - */ - bool genProgram(const GrEffectStage* inColorStages[], - const GrEffectStage* inCoverageStages[]); - - // Below are the results of the shader generation. - - GrGLProgramEffects* getColorEffects() const { SkASSERT(fProgramID); return fColorEffects.get(); } - GrGLProgramEffects* getCoverageEffects() const { SkASSERT(fProgramID); return fCoverageEffects.get(); } - const BuiltinUniformHandles& getBuiltinUniformHandles() const { - SkASSERT(fProgramID); - return fUniformHandles; - } - GrGLuint getProgramID() const { SkASSERT(fProgramID); return fProgramID; } - bool hasVertexShader() const { SkASSERT(fProgramID); return fHasVertexShader; } - int getTexCoordSetCount() const { SkASSERT(fProgramID); return fTexCoordSetCnt; } - const UniformInfoArray& getUniformInfos() const { return fUniforms; } - - virtual ~GrGLShaderBuilder() {} - - /** - * Use of these features may require a GLSL extension to be enabled. Shaders may not compile - * if code is added that uses one of these features without calling enableFeature() - */ - enum GLSLFeature { - kStandardDerivatives_GLSLFeature = 0, - - kLastGLSLFeature = kStandardDerivatives_GLSLFeature - }; - - /** - * If the feature is supported then true is returned and any necessary #extension declarations - * are added to the shaders. If the feature is not supported then false will be returned. - */ - bool enableFeature(GLSLFeature); - - /** - * Called by GrGLEffects to add code the fragment shader. - */ - void fsCodeAppendf(const char format[], ...) SK_PRINTF_LIKE(2, 3) { - va_list args; - va_start(args, format); - fFSCode.appendVAList(format, args); - va_end(args); - } - - void fsCodeAppend(const char* str) { fFSCode.append(str); } - - /** Appends a 2D texture sample with projection if necessary. coordType must either be Vec2f or - Vec3f. The latter is interpreted as projective texture coords. The vec length and swizzle - order of the result depends on the GrTextureAccess associated with the TextureSampler. */ - void appendTextureLookup(SkString* out, - const TextureSampler&, - const char* coordName, - GrSLType coordType = kVec2f_GrSLType) const; - - /** Version of above that appends the result to the fragment shader code instead.*/ - void fsAppendTextureLookup(const TextureSampler&, - const char* coordName, - GrSLType coordType = kVec2f_GrSLType); - - - /** Does the work of appendTextureLookup and modulates the result by modulation. The result is - always a vec4. modulation and the swizzle specified by TextureSampler must both be vec4 or - float. If modulation is "" or NULL it this function acts as though appendTextureLookup were - called. */ - void fsAppendTextureLookupAndModulate(const char* modulation, - const TextureSampler&, - const char* coordName, - GrSLType coordType = kVec2f_GrSLType); - - /** Emits a helper function outside of main() in the fragment shader. */ - void fsEmitFunction(GrSLType returnType, - const char* name, - int argCnt, - const GrGLShaderVar* args, - const char* body, - SkString* outName); - - typedef uint8_t DstReadKey; - typedef uint8_t FragPosKey; - - /** Returns a key for adding code to read the copy-of-dst color in service of effects that - require reading the dst. It must not return 0 because 0 indicates that there is no dst - copy read at all (in which case this function should not be called). */ - static DstReadKey KeyForDstRead(const GrTexture* dstCopy, const GrGLCaps&); - - /** Returns a key for reading the fragment location. This should only be called if there is an - effect that will requires the fragment position. If the fragment position is not required, - the key is 0. */ - static FragPosKey KeyForFragmentPosition(const GrRenderTarget* dst, const GrGLCaps&); - - /** If texture swizzling is available using tex parameters then it is preferred over mangling - the generated shader code. This potentially allows greater reuse of cached shaders. */ - static const GrGLenum* GetTexParamSwizzle(GrPixelConfig config, const GrGLCaps& caps); - - /** Add a uniform variable to the current program, that has visibility in one or more shaders. - visibility is a bitfield of ShaderVisibility values indicating from which shaders the - uniform should be accessible. At least one bit must be set. Geometry shader uniforms are not - supported at this time. The actual uniform name will be mangled. If outName is not NULL then - it will refer to the final uniform name after return. Use the addUniformArray variant to add - an array of uniforms. */ - GrGLProgramDataManager::UniformHandle addUniform(uint32_t visibility, - GrSLType type, - const char* name, - const char** outName = NULL) { - return this->addUniformArray(visibility, type, name, GrGLShaderVar::kNonArray, outName); - } - GrGLProgramDataManager::UniformHandle addUniformArray(uint32_t visibility, - GrSLType type, - const char* name, - int arrayCount, - const char** outName = NULL); - - const GrGLShaderVar& getUniformVariable(GrGLProgramDataManager::UniformHandle u) const { - return fUniforms[u.toShaderBuilderIndex()].fVariable; - } - - /** - * Shortcut for getUniformVariable(u).c_str() - */ - const char* getUniformCStr(GrGLProgramDataManager::UniformHandle u) const { - return this->getUniformVariable(u).c_str(); - } - - /** - * This returns a variable name to access the 2D, perspective correct version of the coords in - * the fragment shader. If the coordinates at index are 3-dimensional, it immediately emits a - * perspective divide into the fragment shader (xy / z) to convert them to 2D. - */ - SkString ensureFSCoords2D(const TransformedCoordsArray&, int index); - - /** Returns a variable name that represents the position of the fragment in the FS. The position - is in device space (e.g. 0,0 is the top left and pixel centers are at half-integers). */ - const char* fragmentPosition(); - - /** Returns the variable name that holds the color of the destination pixel. This may be NULL if - no effect advertised that it will read the destination. */ - const char* dstColor(); - - const GrGLContextInfo& ctxInfo() const; - - /** - * Helper for begining and ending a block in the fragment code. TODO: Make GrGLShaderBuilder - * aware of all blocks and turn single \t's into the correct number of tabs (or spaces) so that - * our shaders print pretty without effect writers tracking indentation. - */ - class FSBlock { - public: - FSBlock(GrGLShaderBuilder* builder) : fBuilder(builder) { - SkASSERT(NULL != builder); - fBuilder->fsCodeAppend("\t{\n"); - } - - ~FSBlock() { - fBuilder->fsCodeAppend("\t}\n"); - } - private: - GrGLShaderBuilder* fBuilder; - }; - -protected: - GrGLShaderBuilder(GrGpuGL*, const GrGLProgramDesc&); - - GrGpuGL* gpu() const { return fGpu; } - - const GrGLProgramDesc& desc() const { return fDesc; } - - /** Add input/output variable declarations (i.e. 'varying') to the fragment shader. */ - GrGLShaderVar& fsInputAppend() { return fFSInputs.push_back(); } - - // Helper for emitEffects(). - void createAndEmitEffects(GrGLProgramEffectsBuilder*, - const GrEffectStage* effectStages[], - int effectCnt, - const GrGLProgramDesc::EffectKeyProvider&, - GrGLSLExpr4* inOutFSColor); - - // Generates a name for a variable. The generated string will be name prefixed by the prefix - // char (unless the prefix is '\0'). It also mangles the name to be stage-specific if we're - // generating stage code. - void nameVariable(SkString* out, char prefix, const char* name); - - virtual bool compileAndAttachShaders(GrGLuint programId, SkTDArray* shaderIds) const; - - virtual void bindProgramLocations(GrGLuint programId); - void resolveProgramLocations(GrGLuint programId); - - void appendDecls(const VarArray&, SkString*) const; - void appendUniformDecls(ShaderVisibility, SkString*) const; - - SkAutoTUnref fColorEffects; - SkAutoTUnref fCoverageEffects; - BuiltinUniformHandles fUniformHandles; - bool fHasVertexShader; - int fTexCoordSetCnt; - GrGLuint fProgramID; -private: - class CodeStage : SkNoncopyable { - public: - CodeStage() : fNextIndex(0), fCurrentIndex(-1), fEffectStage(NULL) {} - - bool inStageCode() const { - this->validate(); - return NULL != fEffectStage; - } - - const GrEffectStage* effectStage() const { - this->validate(); - return fEffectStage; - } - - int stageIndex() const { - this->validate(); - return fCurrentIndex; - } - - class AutoStageRestore : SkNoncopyable { - public: - AutoStageRestore(CodeStage* codeStage, const GrEffectStage* newStage) { - SkASSERT(NULL != codeStage); - fSavedIndex = codeStage->fCurrentIndex; - fSavedEffectStage = codeStage->fEffectStage; - - if (NULL == newStage) { - codeStage->fCurrentIndex = -1; - } else { - codeStage->fCurrentIndex = codeStage->fNextIndex++; - } - codeStage->fEffectStage = newStage; - - fCodeStage = codeStage; - } - ~AutoStageRestore() { - fCodeStage->fCurrentIndex = fSavedIndex; - fCodeStage->fEffectStage = fSavedEffectStage; - } - private: - CodeStage* fCodeStage; - int fSavedIndex; - const GrEffectStage* fSavedEffectStage; - }; - private: - void validate() const { SkASSERT((NULL == fEffectStage) == (-1 == fCurrentIndex)); } - int fNextIndex; - int fCurrentIndex; - const GrEffectStage* fEffectStage; - } fCodeStage; - - /** - * The base class will emit the fragment code that precedes the per-effect code and then call - * this function. The subclass can use it to insert additional fragment code that should - * execute before the effects' code and/or emit other shaders (e.g. geometry, vertex). - * - * The subclass can modify the initial color or coverage - */ - virtual void emitCodeBeforeEffects(GrGLSLExpr4* color, GrGLSLExpr4* coverage) = 0; - - /** - * Adds code for effects and returns a GrGLProgramEffects* object. The caller is responsible for - * deleting it when finished. effectStages contains the effects to add. The effect key provider - * is used to communicate the key each effect created in its GenKey function. inOutFSColor - * specifies the input color to the first stage and is updated to be the output color of the - * last stage. The handles to texture samplers for effectStage[i] are added to - * effectSamplerHandles[i]. - */ - virtual GrGLProgramEffects* createAndEmitEffects(const GrEffectStage* effectStages[], - int effectCnt, - const GrGLProgramDesc::EffectKeyProvider&, - GrGLSLExpr4* inOutFSColor) = 0; - - /** - * Similar to emitCodeBeforeEffects() but called after per-effect code is emitted. - */ - virtual void emitCodeAfterEffects() = 0; - - /** Enables using the secondary color output and returns the name of the var in which it is - to be stored */ - const char* enableSecondaryOutput(); - /** Gets the name of the primary color output. */ - const char* getColorOutputName() const; - - /** - * Compiles all the shaders, links them into a program, and writes the program id to the output - * struct. - **/ - bool finish(); - - /** - * Features that should only be enabled by GrGLShaderBuilder itself. - */ - enum GLSLPrivateFeature { - kFragCoordConventions_GLSLPrivateFeature = kLastGLSLFeature + 1, - kLastGLSLPrivateFeature = kFragCoordConventions_GLSLPrivateFeature - }; - bool enablePrivateFeature(GLSLPrivateFeature); - - // If we ever have VS/GS features we can expand this to take a bitmask of ShaderVisibility and - // track the enables separately for each shader. - void addFSFeature(uint32_t featureBit, const char* extensionName); - - // Interpretation of DstReadKey when generating code - enum { - kNoDstRead_DstReadKey = 0, - kYesDstRead_DstReadKeyBit = 0x1, // Set if we do a dst-copy-read. - kUseAlphaConfig_DstReadKeyBit = 0x2, // Set if dst-copy config is alpha only. - kTopLeftOrigin_DstReadKeyBit = 0x4, // Set if dst-copy origin is top-left. - }; - - enum { - kNoFragPosRead_FragPosKey = 0, // The fragment positition will not be needed. - kTopLeftFragPosRead_FragPosKey = 0x1,// Read frag pos relative to top-left. - kBottomLeftFragPosRead_FragPosKey = 0x2,// Read frag pos relative to bottom-left. - }; - - const GrGLProgramDesc& fDesc; - GrGpuGL* fGpu; - uint32_t fFSFeaturesAddedMask; - SkString fFSFunctions; - SkString fFSExtensions; - VarArray fFSInputs; - VarArray fFSOutputs; - UniformInfoArray fUniforms; - - SkString fFSCode; - - bool fSetupFragPosition; - bool fTopLeftFragPosRead; - - bool fHasCustomColorOutput; - bool fHasSecondaryOutput; -}; - -//////////////////////////////////////////////////////////////////////////////// - -class GrGLFullShaderBuilder : public GrGLShaderBuilder { -public: - GrGLFullShaderBuilder(GrGpuGL*, const GrGLProgramDesc&); - - /** - * Called by GrGLEffects to add code to one of the shaders. - */ - void vsCodeAppendf(const char format[], ...) SK_PRINTF_LIKE(2, 3) { - va_list args; - va_start(args, format); - fVSCode.appendVAList(format, args); - va_end(args); - } - - void vsCodeAppend(const char* str) { fVSCode.append(str); } - - /** Add a vertex attribute to the current program that is passed in from the vertex data. - Returns false if the attribute was already there, true otherwise. */ - bool addAttribute(GrSLType type, const char* name); - - /** Add a varying variable to the current program to pass values between vertex and fragment - shaders. If the last two parameters are non-NULL, they are filled in with the name - generated. */ - void addVarying(GrSLType type, - const char* name, - const char** vsOutName = NULL, - const char** fsInName = NULL); - - /** Returns a vertex attribute that represents the vertex position in the VS. This is the - pre-matrix position and is commonly used by effects to compute texture coords via a matrix. - */ - const GrGLShaderVar& positionAttribute() const { return *fPositionVar; } - - /** Returns a vertex attribute that represents the local coords in the VS. This may be the same - as positionAttribute() or it may not be. It depends upon whether the rendering code - specified explicit local coords or not in the GrDrawState. */ - const GrGLShaderVar& localCoordsAttribute() const { return *fLocalCoordsVar; } - - /** - * Are explicit local coordinates provided as input to the vertex shader. - */ - bool hasExplicitLocalCoords() const { return (fLocalCoordsVar != fPositionVar); } - - bool addEffectAttribute(int attributeIndex, GrSLType type, const SkString& name); - const SkString* getEffectAttributeName(int attributeIndex) const; - -private: - virtual void emitCodeBeforeEffects(GrGLSLExpr4* color, GrGLSLExpr4* coverage) SK_OVERRIDE; - - virtual GrGLProgramEffects* createAndEmitEffects(const GrEffectStage* effectStages[], - int effectCnt, - const GrGLProgramDesc::EffectKeyProvider&, - GrGLSLExpr4* inOutFSColor) SK_OVERRIDE; - - virtual void emitCodeAfterEffects() SK_OVERRIDE; - - virtual bool compileAndAttachShaders(GrGLuint programId, - SkTDArray* shaderIds) const SK_OVERRIDE; - - virtual void bindProgramLocations(GrGLuint programId) SK_OVERRIDE; - - VarArray fVSAttrs; - VarArray fVSOutputs; - VarArray fGSInputs; - VarArray fGSOutputs; - - SkString fVSCode; - - struct AttributePair { - void set(int index, const SkString& name) { - fIndex = index; fName = name; - } - int fIndex; - SkString fName; - }; - SkSTArray<10, AttributePair, true> fEffectAttributes; - - GrGLShaderVar* fPositionVar; - GrGLShaderVar* fLocalCoordsVar; - - typedef GrGLShaderBuilder INHERITED; -}; - -//////////////////////////////////////////////////////////////////////////////// - -class GrGLFragmentOnlyShaderBuilder : public GrGLShaderBuilder { -public: - GrGLFragmentOnlyShaderBuilder(GrGpuGL*, const GrGLProgramDesc&); - - int addTexCoordSets(int count); - -private: - virtual void emitCodeBeforeEffects(GrGLSLExpr4* color, GrGLSLExpr4* coverage) SK_OVERRIDE {} - - virtual GrGLProgramEffects* createAndEmitEffects(const GrEffectStage* effectStages[], - int effectCnt, - const GrGLProgramDesc::EffectKeyProvider&, - GrGLSLExpr4* inOutFSColor) SK_OVERRIDE; - - virtual void emitCodeAfterEffects() SK_OVERRIDE {} - - typedef GrGLShaderBuilder INHERITED; -}; - -#endif diff --git a/src/gpu/gl/GrGLVertexEffect.h b/src/gpu/gl/GrGLVertexEffect.h index eba1fbe795..2e82fbc4d7 100644 --- a/src/gpu/gl/GrGLVertexEffect.h +++ b/src/gpu/gl/GrGLVertexEffect.h @@ -24,27 +24,27 @@ public: * This is similar to emitCode() in the base class, except it takes a full shader builder. * This allows the effect subclass to emit vertex code. */ - virtual void emitCode(GrGLFullShaderBuilder* builder, + virtual void emitCode(GrGLFullProgramBuilder* builder, const GrDrawEffect& drawEffect, const GrEffectKey& key, const char* outputColor, const char* inputColor, const TransformedCoordsArray& coords, const TextureSamplerArray& samplers) = 0; - /** * Provide a default override for base class's emitCode() function. */ - virtual void emitCode(GrGLShaderBuilder* builder, + virtual void emitCode(GrGLProgramBuilder* builder, const GrDrawEffect& drawEffect, const GrEffectKey& key, const char* outputColor, const char* inputColor, const TransformedCoordsArray& coords, const TextureSamplerArray& samplers) SK_OVERRIDE { - SkFAIL("GrGLVertexEffect requires GrGLFullShaderBuilder* overload for emitCode()."); + SkFAIL("GrGLVertexEffect requires GrGLFullProgramBuilder* overload for emitCode()."); } + private: typedef GrGLEffect INHERITED; }; diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp index 418f591301..3c22d17b64 100644 --- a/src/gpu/gl/GrGpuGL.cpp +++ b/src/gpu/gl/GrGpuGL.cpp @@ -8,7 +8,6 @@ #include "GrGpuGL.h" #include "GrGLStencilBuffer.h" -#include "GrGLShaderBuilder.h" #include "GrTemplates.h" #include "GrTypes.h" #include "SkStrokeRec.h" diff --git a/src/gpu/gl/builders/GrGLFragmentShaderBuilder.cpp b/src/gpu/gl/builders/GrGLFragmentShaderBuilder.cpp new file mode 100644 index 0000000000..d216a18c25 --- /dev/null +++ b/src/gpu/gl/builders/GrGLFragmentShaderBuilder.cpp @@ -0,0 +1,351 @@ +/* + * Copyright 2014 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "GrGLFragmentShaderBuilder.h" +#include "GrGLShaderStringBuilder.h" +#include "GrGLProgramBuilder.h" +#include "../GrGpuGL.h" + +namespace { +#define GL_CALL(X) GR_GL_CALL(gpu->glInterface(), X) +#define GL_CALL_RET(R, X) GR_GL_CALL_RET(gpu->glInterface(), R, X) +// ES2 FS only guarantees mediump and lowp support +static const GrGLShaderVar::Precision kDefaultFragmentPrecision = GrGLShaderVar::kMedium_Precision; +static const char kDstCopyColorName[] = "_dstColor"; +inline const char* declared_color_output_name() { return "fsColorOut"; } +inline const char* dual_source_output_name() { return "dualSourceOut"; } +inline void append_default_precision_qualifier(GrGLShaderVar::Precision p, + GrGLStandard standard, + SkString* str) { + // Desktop GLSL has added precision qualifiers but they don't do anything. + if (kGLES_GrGLStandard == standard) { + switch (p) { + case GrGLShaderVar::kHigh_Precision: + str->append("precision highp float;\n"); + break; + case GrGLShaderVar::kMedium_Precision: + str->append("precision mediump float;\n"); + break; + case GrGLShaderVar::kLow_Precision: + str->append("precision lowp float;\n"); + break; + case GrGLShaderVar::kDefault_Precision: + SkFAIL("Default precision now allowed."); + default: + SkFAIL("Unknown precision value."); + } + } +} +} + +GrGLFragmentShaderBuilder::DstReadKey GrGLFragmentShaderBuilder::KeyForDstRead( + const GrTexture* dstCopy, const GrGLCaps& caps) { + uint32_t key = kYesDstRead_DstReadKeyBit; + if (caps.fbFetchSupport()) { + return key; + } + SkASSERT(NULL != dstCopy); + if (!caps.textureSwizzleSupport() && GrPixelConfigIsAlphaOnly(dstCopy->config())) { + // The fact that the config is alpha-only must be considered when generating code. + key |= kUseAlphaConfig_DstReadKeyBit; + } + if (kTopLeft_GrSurfaceOrigin == dstCopy->origin()) { + key |= kTopLeftOrigin_DstReadKeyBit; + } + SkASSERT(static_cast(key) == key); + return static_cast(key); +} + +GrGLFragmentShaderBuilder::FragPosKey GrGLFragmentShaderBuilder::KeyForFragmentPosition( + const GrRenderTarget* dst, const GrGLCaps&) { + if (kTopLeft_GrSurfaceOrigin == dst->origin()) { + return kTopLeftFragPosRead_FragPosKey; + } else { + return kBottomLeftFragPosRead_FragPosKey; + } +} + +GrGLFragmentShaderBuilder::GrGLFragmentShaderBuilder(GrGLProgramBuilder* program, + const GrGLProgramDesc& desc) + : INHERITED(program) + , fHasCustomColorOutput(false) + , fHasSecondaryOutput(false) + , fSetupFragPosition(false) + , fTopLeftFragPosRead(kTopLeftFragPosRead_FragPosKey == desc.getHeader().fFragPosKey){ +} + +const char* GrGLFragmentShaderBuilder::dstColor() { + if (fProgramBuilder->fCodeStage.inStageCode()) { + const GrEffect* effect = fProgramBuilder->fCodeStage.effectStage()->getEffect(); + if (!effect->willReadDstColor()) { + SkDEBUGFAIL("GrGLEffect asked for dst color but its generating GrEffect " + "did not request access."); + return ""; + } + } + + GrGpuGL* gpu = fProgramBuilder->gpu(); + if (gpu->glCaps().fbFetchSupport()) { + this->addFeature(1 << (GrGLFragmentShaderBuilder::kLastGLSLPrivateFeature + 1), + gpu->glCaps().fbFetchExtensionString()); + return gpu->glCaps().fbFetchColorName(); + } else if (fProgramBuilder->fUniformHandles.fDstCopySamplerUni.isValid()) { + return kDstCopyColorName; + } else { + return ""; + } +} + +bool GrGLFragmentShaderBuilder::enableFeature(GLSLFeature feature) { + switch (feature) { + case kStandardDerivatives_GLSLFeature: { + GrGpuGL* gpu = fProgramBuilder->gpu(); + if (!gpu->glCaps().shaderDerivativeSupport()) { + return false; + } + if (kGLES_GrGLStandard == gpu->glStandard()) { + this->addFeature(1 << kStandardDerivatives_GLSLFeature, + "GL_OES_standard_derivatives"); + } + return true; + } + default: + SkFAIL("Unexpected GLSLFeature requested."); + return false; + } +} + +SkString GrGLFragmentShaderBuilder::ensureFSCoords2D(const TransformedCoordsArray& coords, int index) { + if (kVec3f_GrSLType != coords[index].type()) { + SkASSERT(kVec2f_GrSLType == coords[index].type()); + return coords[index].getName(); + } + + SkString coords2D("coords2D"); + if (0 != index) { + coords2D.appendf("_%i", index); + } + this->codeAppendf("\tvec2 %s = %s.xy / %s.z;", + coords2D.c_str(), coords[index].c_str(), coords[index].c_str()); + return coords2D; +} + +const char* GrGLFragmentShaderBuilder::fragmentPosition() { + GrGLProgramBuilder::CodeStage* cs = &fProgramBuilder->fCodeStage; + if (cs->inStageCode()) { + const GrEffect* effect = cs->effectStage()->getEffect(); + if (!effect->willReadFragmentPosition()) { + SkDEBUGFAIL("GrGLEffect asked for frag position but its generating GrEffect " + "did not request access."); + return ""; + } + } + + GrGpuGL* gpu = fProgramBuilder->gpu(); + // We only declare "gl_FragCoord" when we're in the case where we want to use layout qualifiers + // to reverse y. Otherwise it isn't necessary and whether the "in" qualifier appears in the + // declaration varies in earlier GLSL specs. So it is simpler to omit it. + if (fTopLeftFragPosRead) { + fSetupFragPosition = true; + return "gl_FragCoord"; + } else if (gpu->glCaps().fragCoordConventionsSupport()) { + if (!fSetupFragPosition) { + if (gpu->glslGeneration() < k150_GrGLSLGeneration) { + this->addFeature(1 << kFragCoordConventions_GLSLPrivateFeature, + "GL_ARB_fragment_coord_conventions"); + } + fInputs.push_back().set(kVec4f_GrSLType, + GrGLShaderVar::kIn_TypeModifier, + "gl_FragCoord", + GrGLShaderVar::kDefault_Precision, + GrGLShaderVar::kUpperLeft_Origin); + fSetupFragPosition = true; + } + return "gl_FragCoord"; + } else { + static const char* kCoordName = "fragCoordYDown"; + if (!fSetupFragPosition) { + // temporarily change the stage index because we're inserting non-stage code. + GrGLProgramBuilder::CodeStage::AutoStageRestore csar(cs, NULL); + + SkASSERT(!fProgramBuilder->fUniformHandles.fRTHeightUni.isValid()); + const char* rtHeightName; + + fProgramBuilder->fUniformHandles.fRTHeightUni = + fProgramBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility, + kFloat_GrSLType, + "RTHeight", + &rtHeightName); + + // Using glFragCoord.zw for the last two components tickles an Adreno driver bug that + // causes programs to fail to link. Making this function return a vec2() didn't fix the + // problem but using 1.0 for the last two components does. + this->codePrependf("\tvec4 %s = vec4(gl_FragCoord.x, %s - gl_FragCoord.y, 1.0, " + "1.0);\n", kCoordName, rtHeightName); + fSetupFragPosition = true; + } + SkASSERT(fProgramBuilder->fUniformHandles.fRTHeightUni.isValid()); + return kCoordName; + } +} + +void GrGLFragmentShaderBuilder::addVarying(GrSLType type, + const char* name, + const char** fsInName) { + fInputs.push_back().set(type, GrGLShaderVar::kVaryingIn_TypeModifier, name); + if (fsInName) { + *fsInName = name; + } +} + +void GrGLFragmentShaderBuilder::bindProgramLocations(GrGLuint programId) { + GrGpuGL* gpu = fProgramBuilder->gpu(); + if (fHasCustomColorOutput) { + GL_CALL(BindFragDataLocation(programId, 0, declared_color_output_name())); + } + if (fHasSecondaryOutput) { + GL_CALL(BindFragDataLocationIndexed(programId, 0, 1, dual_source_output_name())); + } +} + +bool GrGLFragmentShaderBuilder::compileAndAttachShaders(GrGLuint programId, + SkTDArray* shaderIds) const { + GrGpuGL* gpu = fProgramBuilder->gpu(); + SkString fragShaderSrc(GrGetGLSLVersionDecl(gpu->ctxInfo())); + fragShaderSrc.append(fExtensions); + append_default_precision_qualifier(kDefaultFragmentPrecision, + gpu->glStandard(), + &fragShaderSrc); + fProgramBuilder->appendUniformDecls(GrGLProgramBuilder::kFragment_Visibility, &fragShaderSrc); + fProgramBuilder->appendDecls(fInputs, &fragShaderSrc); + // We shouldn't have declared outputs on 1.10 + SkASSERT(k110_GrGLSLGeneration != gpu->glslGeneration() || fOutputs.empty()); + fProgramBuilder->appendDecls(fOutputs, &fragShaderSrc); + fragShaderSrc.append(fFunctions); + fragShaderSrc.append("void main() {\n"); + fragShaderSrc.append(fCode); + fragShaderSrc.append("}\n"); + + GrGLuint fragShaderId = GrGLCompileAndAttachShader(gpu->glContext(), + programId, GR_GL_FRAGMENT_SHADER, fragShaderSrc); + if (!fragShaderId) { + return false; + } + + *shaderIds->append() = fragShaderId; + + return true; +} + +void GrGLFragmentShaderBuilder::emitCodeBeforeEffects() { + const GrGLProgramDesc::KeyHeader& header = fProgramBuilder->desc().getHeader(); + GrGpuGL* gpu = fProgramBuilder->gpu(); + + /////////////////////////////////////////////////////////////////////////// + // emit code to read the dst copy texture, if necessary + if (kNoDstRead_DstReadKey != header.fDstReadKey && !gpu->glCaps().fbFetchSupport()) { + bool topDown = SkToBool(kTopLeftOrigin_DstReadKeyBit & header.fDstReadKey); + const char* dstCopyTopLeftName; + const char* dstCopyCoordScaleName; + const char* dstCopySamplerName; + uint32_t configMask; + if (SkToBool(kUseAlphaConfig_DstReadKeyBit & header.fDstReadKey)) { + configMask = kA_GrColorComponentFlag; + } else { + configMask = kRGBA_GrColorComponentFlags; + } + fProgramBuilder->fUniformHandles.fDstCopySamplerUni = + fProgramBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility, + kSampler2D_GrSLType, + "DstCopySampler", + &dstCopySamplerName); + fProgramBuilder->fUniformHandles.fDstCopyTopLeftUni = + fProgramBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility, + kVec2f_GrSLType, + "DstCopyUpperLeft", + &dstCopyTopLeftName); + fProgramBuilder->fUniformHandles.fDstCopyScaleUni = + fProgramBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility, + kVec2f_GrSLType, + "DstCopyCoordScale", + &dstCopyCoordScaleName); + const char* fragPos = fragmentPosition(); + + this->codeAppend("// Read color from copy of the destination.\n"); + this->codeAppendf("vec2 _dstTexCoord = (%s.xy - %s) * %s;", + fragPos, dstCopyTopLeftName, dstCopyCoordScaleName); + if (!topDown) { + this->codeAppend("_dstTexCoord.y = 1.0 - _dstTexCoord.y;"); + } + this->codeAppendf("vec4 %s = ", kDstCopyColorName); + this->appendTextureLookup(dstCopySamplerName, + "_dstTexCoord", + configMask, + "rgba"); + this->codeAppend(";"); + } + + if (k110_GrGLSLGeneration != gpu->glslGeneration()) { + fOutputs.push_back().set(kVec4f_GrSLType, + GrGLShaderVar::kOut_TypeModifier, + declared_color_output_name()); + fHasCustomColorOutput = true; + } +} + +void GrGLFragmentShaderBuilder::emitCodeAfterEffects(const GrGLSLExpr4& inputColor, const GrGLSLExpr4& inputCoverage) { + const GrGLProgramDesc::KeyHeader& header = fProgramBuilder->desc().getHeader(); + + /////////////////////////////////////////////////////////////////////////// + // write the secondary color output if necessary + if (GrGLProgramDesc::CoverageOutputUsesSecondaryOutput(header.fCoverageOutput)) { + const char* secondaryOutputName = this->enableSecondaryOutput(); + + // default coeff to ones for kCoverage_DualSrcOutput + GrGLSLExpr4 coeff(1); + if (GrGLProgramDesc::kSecondaryCoverageISA_CoverageOutput == header.fCoverageOutput) { + // Get (1-A) into coeff + coeff = GrGLSLExpr4::VectorCast(GrGLSLExpr1(1) - inputColor.a()); + } else if (GrGLProgramDesc::kSecondaryCoverageISC_CoverageOutput == + header.fCoverageOutput){ + // Get (1-RGBA) into coeff + coeff = GrGLSLExpr4(1) - inputColor; + } + // Get coeff * coverage into modulate and then write that to the dual source output. + codeAppendf("\t%s = %s;\n", secondaryOutputName, (coeff * inputCoverage).c_str()); + } + + /////////////////////////////////////////////////////////////////////////// + // combine color and coverage as frag color + + // Get "color * coverage" into fragColor + GrGLSLExpr4 fragColor = inputColor * inputCoverage; + // Now tack on "+(1-coverage)dst onto the frag color if we were asked to do so. + if (GrGLProgramDesc::kCombineWithDst_CoverageOutput == header.fCoverageOutput) { + GrGLSLExpr4 dstCoeff = GrGLSLExpr4(1) - inputCoverage; + + GrGLSLExpr4 dstContribution = dstCoeff * GrGLSLExpr4(dstColor()); + + fragColor = fragColor + dstContribution; + } + codeAppendf("\t%s = %s;\n", this->getColorOutputName(), fragColor.c_str()); +} + +const char* GrGLFragmentShaderBuilder::enableSecondaryOutput() { + if (!fHasSecondaryOutput) { + fOutputs.push_back().set(kVec4f_GrSLType, + GrGLShaderVar::kOut_TypeModifier, + dual_source_output_name()); + fHasSecondaryOutput = true; + } + return dual_source_output_name(); +} + +const char* GrGLFragmentShaderBuilder::getColorOutputName() const { + return fHasCustomColorOutput ? declared_color_output_name() : "gl_FragColor"; +} + diff --git a/src/gpu/gl/builders/GrGLFragmentShaderBuilder.h b/src/gpu/gl/builders/GrGLFragmentShaderBuilder.h new file mode 100644 index 0000000000..0f700bd94d --- /dev/null +++ b/src/gpu/gl/builders/GrGLFragmentShaderBuilder.h @@ -0,0 +1,118 @@ +/* + * Copyright 2014 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrGLFragmentShaderBuilder_DEFINED +#define GrGLFragmentShaderBuilder_DEFINED +#include "GrGLShaderBuilder.h" + +class GrGLProgramBuilder; + +class GrGLFragmentShaderBuilder : public GrGLShaderBuilder { +public: + typedef uint8_t DstReadKey; + typedef uint8_t FragPosKey; + + /** Returns a key for adding code to read the copy-of-dst color in service of effects that + require reading the dst. It must not return 0 because 0 indicates that there is no dst + copy read at all (in which case this function should not be called). */ + static DstReadKey KeyForDstRead(const GrTexture* dstCopy, const GrGLCaps&); + + /** Returns a key for reading the fragment location. This should only be called if there is an + effect that will requires the fragment position. If the fragment position is not required, + the key is 0. */ + static FragPosKey KeyForFragmentPosition(const GrRenderTarget* dst, const GrGLCaps&); + + GrGLFragmentShaderBuilder(GrGLProgramBuilder* program, const GrGLProgramDesc& desc); + + /** Returns the variable name that holds the color of the destination pixel. This may be NULL if + no effect advertised that it will read the destination. */ + const char* dstColor(); + + /** + * Use of these features may require a GLSL extension to be enabled. Shaders may not compile + * if code is added that uses one of these features without calling enableFeature() + */ + enum GLSLFeature { + kStandardDerivatives_GLSLFeature = 0, + kLastGLSLFeature = kStandardDerivatives_GLSLFeature + }; + + /** + * If the feature is supported then true is returned and any necessary #extension declarations + * are added to the shaders. If the feature is not supported then false will be returned. + */ + bool enableFeature(GLSLFeature); + + /** + * This returns a variable name to access the 2D, perspective correct version of the coords in + * the fragment shader. If the coordinates at index are 3-dimensional, it immediately emits a + * perspective divide into the fragment shader (xy / z) to convert them to 2D. + */ + SkString ensureFSCoords2D(const TransformedCoordsArray& coords, int index); + + + /** Returns a variable name that represents the position of the fragment in the FS. The position + is in device space (e.g. 0,0 is the top left and pixel centers are at half-integers). */ + const char* fragmentPosition(); + +private: + /* + * An internal call for GrGLFullProgramBuilder to use to add varyings to the vertex shader + */ + void addVarying(GrSLType type, + const char* name, + const char** fsInName); + + /* + * Private functions used by GrGLProgramBuilder for compilation + */ + void bindProgramLocations(GrGLuint programId); + bool compileAndAttachShaders(GrGLuint programId, SkTDArray* shaderIds) const; + void emitCodeBeforeEffects(); + void emitCodeAfterEffects(const GrGLSLExpr4& inputColor, const GrGLSLExpr4& inputCoverage); + + /** Enables using the secondary color output and returns the name of the var in which it is + to be stored */ + const char* enableSecondaryOutput(); + + /** Gets the name of the primary color output. */ + const char* getColorOutputName() const; + + /** + * Features that should only be enabled by GrGLFragmentShaderBuilder itself. + */ + enum GLSLPrivateFeature { + kFragCoordConventions_GLSLPrivateFeature = kLastGLSLFeature + 1, + kLastGLSLPrivateFeature = kFragCoordConventions_GLSLPrivateFeature + }; + + // Interpretation of DstReadKey when generating code + enum { + kNoDstRead_DstReadKey = 0, + kYesDstRead_DstReadKeyBit = 0x1, // Set if we do a dst-copy-read. + kUseAlphaConfig_DstReadKeyBit = 0x2, // Set if dst-copy config is alpha only. + kTopLeftOrigin_DstReadKeyBit = 0x4, // Set if dst-copy origin is top-left. + }; + + enum { + kNoFragPosRead_FragPosKey = 0, // The fragment positition will not be needed. + kTopLeftFragPosRead_FragPosKey = 0x1,// Read frag pos relative to top-left. + kBottomLeftFragPosRead_FragPosKey = 0x2,// Read frag pos relative to bottom-left. + }; + + bool fHasCustomColorOutput; + bool fHasSecondaryOutput; + bool fSetupFragPosition; + bool fTopLeftFragPosRead; + + friend class GrGLProgramBuilder; + friend class GrGLFullProgramBuilder; + + typedef GrGLShaderBuilder INHERITED; +}; + +#endif diff --git a/src/gpu/gl/builders/GrGLGeometryShaderBuilder.cpp b/src/gpu/gl/builders/GrGLGeometryShaderBuilder.cpp new file mode 100644 index 0000000000..6cdf2f93e0 --- /dev/null +++ b/src/gpu/gl/builders/GrGLGeometryShaderBuilder.cpp @@ -0,0 +1,70 @@ +/* + * Copyright 2014 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "GrGLGeometryShaderBuilder.h" +#include "GrGLShaderStringBuilder.h" +#include "GrGLProgramBuilder.h" +#include "../GrGpuGL.h" + +GrGLGeometryShaderBuilder::GrGLGeometryShaderBuilder(GrGLFullProgramBuilder* program) + : INHERITED(program) { + +} + +void GrGLGeometryShaderBuilder::addVarying(GrSLType type, + const char* name, + const char** gsOutName) { + // if we have a GS take each varying in as an array + // and output as non-array. + fInputs.push_back(); + fInputs.back().setType(type); + fInputs.back().setTypeModifier(GrGLShaderVar::kVaryingIn_TypeModifier); + fInputs.back().setUnsizedArray(); + *fInputs.back().accessName() = name; + fOutputs.push_back(); + fOutputs.back().setType(type); + fOutputs.back().setTypeModifier(GrGLShaderVar::kVaryingOut_TypeModifier); + fProgramBuilder->nameVariable(fOutputs.back().accessName(), 'g', name); + if (gsOutName) { + *gsOutName = fOutputs.back().getName().c_str(); + } +} + + +bool GrGLGeometryShaderBuilder::compileAndAttachShaders(GrGLuint programId, + SkTDArray* shaderIds) const { + const GrGLContext& glCtx = fProgramBuilder->gpu()->glContext(); + SkASSERT(fProgramBuilder->ctxInfo().glslGeneration() >= k150_GrGLSLGeneration); + SkString geomShaderSrc(GrGetGLSLVersionDecl(fProgramBuilder->ctxInfo())); + geomShaderSrc.append("layout(triangles) in;\n" + "layout(triangle_strip, max_vertices = 6) out;\n"); + fProgramBuilder->appendDecls(fInputs, &geomShaderSrc); + fProgramBuilder->appendDecls(fOutputs, &geomShaderSrc); + geomShaderSrc.append("void main() {\n"); + geomShaderSrc.append("\tfor (int i = 0; i < 3; ++i) {\n" + "\t\tgl_Position = gl_in[i].gl_Position;\n"); + if (fProgramBuilder->desc().getHeader().fEmitsPointSize) { + geomShaderSrc.append("\t\tgl_PointSize = 1.0;\n"); + } + SkASSERT(fInputs.count() == fOutputs.count()); + for (int i = 0; i < fInputs.count(); ++i) { + geomShaderSrc.appendf("\t\t%s = %s[i];\n", + fOutputs[i].getName().c_str(), + fInputs[i].getName().c_str()); + } + geomShaderSrc.append("\t\tEmitVertex();\n" + "\t}\n" + "\tEndPrimitive();\n"); + geomShaderSrc.append("}\n"); + GrGLuint geomShaderId = + GrGLCompileAndAttachShader(glCtx, programId, GR_GL_GEOMETRY_SHADER, geomShaderSrc); + if (!geomShaderId) { + return false; + } + *shaderIds->append() = geomShaderId; + return true; +} diff --git a/src/gpu/gl/builders/GrGLGeometryShaderBuilder.h b/src/gpu/gl/builders/GrGLGeometryShaderBuilder.h new file mode 100644 index 0000000000..833d31774f --- /dev/null +++ b/src/gpu/gl/builders/GrGLGeometryShaderBuilder.h @@ -0,0 +1,32 @@ +/* + * Copyright 2014 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrGLGeometryShaderBuilder_DEFINED +#define GrGLGeometryShaderBuilder_DEFINED + +#include "GrGLShaderBuilder.h" + +class GrGLProgramBuilder; + +class GrGLGeometryShaderBuilder : public GrGLFullShaderBuilder { +public: + GrGLGeometryShaderBuilder(GrGLFullProgramBuilder* program); +private: + /* + * an internal call for GrGLFullProgramBuilder to add varyings + */ + void addVarying(GrSLType type, + const char* name, + const char** gsOutName); + + bool compileAndAttachShaders(GrGLuint programId, SkTDArray* shaderIds) const; + + friend class GrGLFullProgramBuilder; + typedef GrGLFullShaderBuilder INHERITED; +}; + +#endif diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.cpp b/src/gpu/gl/builders/GrGLProgramBuilder.cpp new file mode 100644 index 0000000000..f4ee32b48d --- /dev/null +++ b/src/gpu/gl/builders/GrGLProgramBuilder.cpp @@ -0,0 +1,409 @@ +/* + * Copyright 2014 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "gl/GrGLProgram.h" +#include "gl/GrGLSLPrettyPrint.h" +#include "gl/GrGLUniformHandle.h" +#include "GrCoordTransform.h" +#include "GrDrawEffect.h" +#include "../GrGpuGL.h" +#include "GrGLFragmentShaderBuilder.h" +#include "GrGLProgramBuilder.h" +#include "GrTexture.h" +#include "GrGLVertexShaderBuilder.h" +#include "SkRTConf.h" +#include "SkTraceEvent.h" + +namespace { +#define GL_CALL(X) GR_GL_CALL(this->gpu()->glInterface(), X) +#define GL_CALL_RET(R, X) GR_GL_CALL_RET(this->gpu()->glInterface(), R, X) + +// number of each input/output type in a single allocation block +static const int kVarsPerBlock = 8; + +// ES2 FS only guarantees mediump and lowp support +static const GrGLShaderVar::Precision kDefaultFragmentPrecision = GrGLShaderVar::kMedium_Precision; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +bool GrGLProgramBuilder::genProgram(const GrEffectStage* colorStages[], + const GrEffectStage* coverageStages[]) { + const GrGLProgramDesc::KeyHeader& header = this->desc().getHeader(); + + fFS.emitCodeBeforeEffects(); + + /////////////////////////////////////////////////////////////////////////// + // get the initial color and coverage to feed into the first effect in each effect chain + + GrGLSLExpr4 inputColor; + GrGLSLExpr4 inputCoverage; + + if (GrGLProgramDesc::kUniform_ColorInput == header.fColorInput) { + const char* name; + fUniformHandles.fColorUni = + this->addUniform(GrGLProgramBuilder::kFragment_Visibility, + kVec4f_GrSLType, + "Color", + &name); + inputColor = GrGLSLExpr4(name); + } + + if (GrGLProgramDesc::kUniform_ColorInput == header.fCoverageInput) { + const char* name; + fUniformHandles.fCoverageUni = + this->addUniform(GrGLProgramBuilder::kFragment_Visibility, + kVec4f_GrSLType, + "Coverage", + &name); + inputCoverage = GrGLSLExpr4(name); + } else if (GrGLProgramDesc::kSolidWhite_ColorInput == header.fCoverageInput) { + inputCoverage = GrGLSLExpr4(1); + } + + this->emitCodeBeforeEffects(&inputColor, &inputCoverage); + + /////////////////////////////////////////////////////////////////////////// + // emit the per-effect code for both color and coverage effects + + GrGLProgramDesc::EffectKeyProvider colorKeyProvider( + &this->desc(), GrGLProgramDesc::EffectKeyProvider::kColor_EffectType); + fColorEffects.reset(this->createAndEmitEffects(colorStages, + this->desc().numColorEffects(), + colorKeyProvider, + &inputColor)); + + GrGLProgramDesc::EffectKeyProvider coverageKeyProvider( + &this->desc(), GrGLProgramDesc::EffectKeyProvider::kCoverage_EffectType); + fCoverageEffects.reset(this->createAndEmitEffects(coverageStages, + this->desc().numCoverageEffects(), + coverageKeyProvider, + &inputCoverage)); + + this->emitCodeAfterEffects(); + + fFS.emitCodeAfterEffects(inputColor, inputCoverage); + + if (!this->finish()) { + return false; + } + + return true; +} + +////////////////////////////////////////////////////////////////////////////// + +GrGLProgramBuilder::GrGLProgramBuilder(GrGpuGL* gpu, + const GrGLProgramDesc& desc) + : fFragOnly(!desc.getHeader().fHasVertexCode && gpu->shouldUseFixedFunctionTexturing()) + , fTexCoordSetCnt(0) + , fProgramID(0) + , fFS(this, desc) + , fDesc(desc) + , fGpu(gpu) + , fUniforms(kVarsPerBlock) { +} + +void GrGLProgramBuilder::nameVariable(SkString* out, char prefix, const char* name) { + if ('\0' == prefix) { + *out = name; + } else { + out->printf("%c%s", prefix, name); + } + if (fCodeStage.inStageCode()) { + if (out->endsWith('_')) { + // Names containing "__" are reserved. + out->append("x"); + } + out->appendf("_Stage%d", fCodeStage.stageIndex()); + } +} + +GrGLProgramDataManager::UniformHandle GrGLProgramBuilder::addUniformArray(uint32_t visibility, + GrSLType type, + const char* name, + int count, + const char** outName) { + SkASSERT(name && strlen(name)); + SkDEBUGCODE(static const uint32_t kVisibilityMask = kVertex_Visibility | kFragment_Visibility); + SkASSERT(0 == (~kVisibilityMask & visibility)); + SkASSERT(0 != visibility); + + UniformInfo& uni = fUniforms.push_back(); + uni.fVariable.setType(type); + uni.fVariable.setTypeModifier(GrGLShaderVar::kUniform_TypeModifier); + this->nameVariable(uni.fVariable.accessName(), 'u', name); + uni.fVariable.setArrayCount(count); + uni.fVisibility = visibility; + + // If it is visible in both the VS and FS, the precision must match. + // We declare a default FS precision, but not a default VS. So set the var + // to use the default FS precision. + if ((kVertex_Visibility | kFragment_Visibility) == visibility) { + // the fragment and vertex precisions must match + uni.fVariable.setPrecision(kDefaultFragmentPrecision); + } + + if (NULL != outName) { + *outName = uni.fVariable.c_str(); + } + return GrGLProgramDataManager::UniformHandle::CreateFromUniformIndex(fUniforms.count() - 1); +} + +void GrGLProgramBuilder::appendDecls(const VarArray& vars, SkString* out) const { + for (int i = 0; i < vars.count(); ++i) { + vars[i].appendDecl(this->ctxInfo(), out); + out->append(";\n"); + } +} + +void GrGLProgramBuilder::appendUniformDecls(ShaderVisibility visibility, + SkString* out) const { + for (int i = 0; i < fUniforms.count(); ++i) { + if (fUniforms[i].fVisibility & visibility) { + fUniforms[i].fVariable.appendDecl(this->ctxInfo(), out); + out->append(";\n"); + } + } +} + +void GrGLProgramBuilder::createAndEmitEffects(GrGLProgramEffectsBuilder* programEffectsBuilder, + const GrEffectStage* effectStages[], + int effectCnt, + const GrGLProgramDesc::EffectKeyProvider& keyProvider, + GrGLSLExpr4* fsInOutColor) { + bool effectEmitted = false; + + GrGLSLExpr4 inColor = *fsInOutColor; + GrGLSLExpr4 outColor; + + for (int e = 0; e < effectCnt; ++e) { + SkASSERT(NULL != effectStages[e] && NULL != effectStages[e]->getEffect()); + const GrEffectStage& stage = *effectStages[e]; + + CodeStage::AutoStageRestore csar(&fCodeStage, &stage); + + if (inColor.isZeros()) { + SkString inColorName; + + // Effects have no way to communicate zeros, they treat an empty string as ones. + this->nameVariable(&inColorName, '\0', "input"); + fFS.codeAppendf("\tvec4 %s = %s;\n", inColorName.c_str(), inColor.c_str()); + inColor = inColorName; + } + + // create var to hold stage result + SkString outColorName; + this->nameVariable(&outColorName, '\0', "output"); + fFS.codeAppendf("\tvec4 %s;\n", outColorName.c_str()); + outColor = outColorName; + + + programEffectsBuilder->emitEffect(stage, + keyProvider.get(e), + outColor.c_str(), + inColor.isOnes() ? NULL : inColor.c_str(), + fCodeStage.stageIndex()); + + inColor = outColor; + effectEmitted = true; + } + + if (effectEmitted) { + *fsInOutColor = outColor; + } +} + +bool GrGLProgramBuilder::finish() { + SkASSERT(0 == fProgramID); + GL_CALL_RET(fProgramID, CreateProgram()); + if (!fProgramID) { + return false; + } + + SkTDArray shadersToDelete; + + if (!this->compileAndAttachShaders(fProgramID, &shadersToDelete)) { + GL_CALL(DeleteProgram(fProgramID)); + return false; + } + + this->bindProgramLocations(fProgramID); + + GL_CALL(LinkProgram(fProgramID)); + + // Calling GetProgramiv is expensive in Chromium. Assume success in release builds. + bool checkLinked = !fGpu->ctxInfo().isChromium(); +#ifdef SK_DEBUG + checkLinked = true; +#endif + if (checkLinked) { + GrGLint linked = GR_GL_INIT_ZERO; + GL_CALL(GetProgramiv(fProgramID, GR_GL_LINK_STATUS, &linked)); + if (!linked) { + GrGLint infoLen = GR_GL_INIT_ZERO; + GL_CALL(GetProgramiv(fProgramID, GR_GL_INFO_LOG_LENGTH, &infoLen)); + SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger + if (infoLen > 0) { + // retrieve length even though we don't need it to workaround + // bug in chrome cmd buffer param validation. + GrGLsizei length = GR_GL_INIT_ZERO; + GL_CALL(GetProgramInfoLog(fProgramID, + infoLen+1, + &length, + (char*)log.get())); + GrPrintf((char*)log.get()); + } + SkDEBUGFAIL("Error linking program"); + GL_CALL(DeleteProgram(fProgramID)); + fProgramID = 0; + return false; + } + } + + this->resolveProgramLocations(fProgramID); + + for (int i = 0; i < shadersToDelete.count(); ++i) { + GL_CALL(DeleteShader(shadersToDelete[i])); + } + + return true; +} + +bool GrGLProgramBuilder::compileAndAttachShaders(GrGLuint programId, + SkTDArray* shaderIds) const { + return fFS.compileAndAttachShaders(programId, shaderIds); +} + +void GrGLProgramBuilder::bindProgramLocations(GrGLuint programId) { + fFS.bindProgramLocations(programId); + + // skbug.com/2056 + bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation != NULL; + if (usingBindUniform) { + int count = fUniforms.count(); + for (int i = 0; i < count; ++i) { + GL_CALL(BindUniformLocation(programId, i, fUniforms[i].fVariable.c_str())); + fUniforms[i].fLocation = i; + } + } +} + +void GrGLProgramBuilder::resolveProgramLocations(GrGLuint programId) { + bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation != NULL; + if (!usingBindUniform) { + int count = fUniforms.count(); + for (int i = 0; i < count; ++i) { + GrGLint location; + GL_CALL_RET(location, + GetUniformLocation(programId, fUniforms[i].fVariable.c_str())); + fUniforms[i].fLocation = location; + } + } +} + +const GrGLContextInfo& GrGLProgramBuilder::ctxInfo() const { + return fGpu->ctxInfo(); +} + +//////////////////////////////////////////////////////////////////////////////// + +GrGLFullProgramBuilder::GrGLFullProgramBuilder(GrGpuGL* gpu, + const GrGLProgramDesc& desc) + : INHERITED(gpu, desc) + , fGS(this) + , fVS(this) { +} + +void GrGLFullProgramBuilder::emitCodeBeforeEffects(GrGLSLExpr4* color, GrGLSLExpr4* coverage) { + fVS.emitCodeBeforeEffects(color, coverage); +} + +void GrGLFullProgramBuilder::emitCodeAfterEffects() { + fVS.emitCodeAfterEffects(); +} + +void GrGLFullProgramBuilder::addVarying(GrSLType type, + const char* name, + const char** vsOutName, + const char** fsInName) { + fVS.addVarying(type, name, vsOutName); + + SkString* fsInputName = fVS.fOutputs.back().accessName(); + +#if GR_GL_EXPERIMENTAL_GS + if (desc().getHeader().fExperimentalGS) { + // TODO let the caller use these names + fGS.addVarying(type, fsInputName->c_str(), NULL); + fsInputName = fGS.fOutputs.back().accessName(); + } +#endif + fFS.addVarying(type, fsInputName->c_str(), fsInName); +} + +GrGLProgramEffects* GrGLFullProgramBuilder::createAndEmitEffects( + const GrEffectStage* effectStages[], + int effectCnt, + const GrGLProgramDesc::EffectKeyProvider& keyProvider, + GrGLSLExpr4* inOutFSColor) { + + GrGLVertexProgramEffectsBuilder programEffectsBuilder(this, effectCnt); + this->INHERITED::createAndEmitEffects(&programEffectsBuilder, + effectStages, + effectCnt, + keyProvider, + inOutFSColor); + return programEffectsBuilder.finish(); +} + +bool GrGLFullProgramBuilder::compileAndAttachShaders(GrGLuint programId, + SkTDArray* shaderIds) const { + return INHERITED::compileAndAttachShaders(programId, shaderIds) + && fVS.compileAndAttachShaders(programId, shaderIds) +#if GR_GL_EXPERIMENTAL_GS + && (!desc().getHeader().fExperimentalGS + || fGS.compileAndAttachShaders(programId, shaderIds)) +#endif + ; +} + +void GrGLFullProgramBuilder::bindProgramLocations(GrGLuint programId) { + fVS.bindProgramLocations(programId); + INHERITED::bindProgramLocations(programId); +} + +//////////////////////////////////////////////////////////////////////////////// + +GrGLFragmentOnlyProgramBuilder::GrGLFragmentOnlyProgramBuilder(GrGpuGL* gpu, + const GrGLProgramDesc& desc) + : INHERITED(gpu, desc) { + SkASSERT(!desc.getHeader().fHasVertexCode); + SkASSERT(gpu->glCaps().pathRenderingSupport()); + SkASSERT(GrGLProgramDesc::kAttribute_ColorInput != desc.getHeader().fColorInput); + SkASSERT(GrGLProgramDesc::kAttribute_ColorInput != desc.getHeader().fCoverageInput); +} + +int GrGLFragmentOnlyProgramBuilder::addTexCoordSets(int count) { + int firstFreeCoordSet = fTexCoordSetCnt; + fTexCoordSetCnt += count; + SkASSERT(gpu()->glCaps().maxFixedFunctionTextureCoords() >= fTexCoordSetCnt); + return firstFreeCoordSet; +} + +GrGLProgramEffects* GrGLFragmentOnlyProgramBuilder::createAndEmitEffects( + const GrEffectStage* effectStages[], int effectCnt, + const GrGLProgramDesc::EffectKeyProvider& keyProvider, GrGLSLExpr4* inOutFSColor) { + + GrGLPathTexGenProgramEffectsBuilder pathTexGenEffectsBuilder(this, + effectCnt); + this->INHERITED::createAndEmitEffects(&pathTexGenEffectsBuilder, + effectStages, + effectCnt, + keyProvider, + inOutFSColor); + return pathTexGenEffectsBuilder.finish(); +} diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.h b/src/gpu/gl/builders/GrGLProgramBuilder.h new file mode 100644 index 0000000000..09f7eba511 --- /dev/null +++ b/src/gpu/gl/builders/GrGLProgramBuilder.h @@ -0,0 +1,318 @@ +/* + * Copyright 2014 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrGLProgramBuilder_DEFINED +#define GrGLProgramBuilder_DEFINED + +#include "GrAllocator.h" +#include "GrBackendEffectFactory.h" +#include "GrColor.h" +#include "GrEffect.h" +#include "GrGLFragmentShaderBuilder.h" +#include "GrGLGeometryShaderBuilder.h" +#include "GrGLVertexShaderBuilder.h" +#include "SkTypes.h" +#include "gl/GrGLProgramDesc.h" +#include "gl/GrGLProgramEffects.h" +#include "gl/GrGLSL.h" +#include "gl/GrGLProgramDataManager.h" + +#include + +class GrGLContextInfo; +class GrEffectStage; +class GrGLProgramDesc; + +/** + Contains all the incremental state of a shader as it is being built,as well as helpers to + manipulate that state. +*/ +class GrGLProgramBuilder { +public: + enum ShaderVisibility { + kVertex_Visibility = 0x1, + kGeometry_Visibility = 0x2, + kFragment_Visibility = 0x4, + }; + + typedef GrGLProgramDataManager::UniformHandle UniformHandle; + + // Handles for program uniforms (other than per-effect uniforms) + struct BuiltinUniformHandles { + UniformHandle fViewMatrixUni; + UniformHandle fRTAdjustmentUni; + UniformHandle fColorUni; + UniformHandle fCoverageUni; + + // We use the render target height to provide a y-down frag coord when specifying + // origin_upper_left is not supported. + UniformHandle fRTHeightUni; + + // Uniforms for computing texture coords to do the dst-copy lookup + UniformHandle fDstCopyTopLeftUni; + UniformHandle fDstCopyScaleUni; + UniformHandle fDstCopySamplerUni; + }; + + struct UniformInfo { + GrGLShaderVar fVariable; + uint32_t fVisibility; + GrGLint fLocation; + }; + + // This uses an allocator rather than array so that the GrGLShaderVars don't move in memory + // after they are inserted. Users of GrGLShaderBuilder get refs to the vars and ptrs to their + // name strings. Otherwise, we'd have to hand out copies. + typedef GrTAllocator UniformInfoArray; + + /** Generates a shader program. + * + * The program implements what is specified in the stages given as input. + * After successful generation, the builder result objects are available + * to be used. + * @return true if generation was successful. + */ + bool genProgram(const GrEffectStage* inColorStages[], + const GrEffectStage* inCoverageStages[]); + + // Below are the results of the shader generation. + + GrGLProgramEffects* getColorEffects() const { SkASSERT(fProgramID); return fColorEffects.get(); } + GrGLProgramEffects* getCoverageEffects() const { SkASSERT(fProgramID); return fCoverageEffects.get(); } + const BuiltinUniformHandles& getBuiltinUniformHandles() const { + SkASSERT(fProgramID); + return fUniformHandles; + } + GrGLuint getProgramID() const { SkASSERT(fProgramID); return fProgramID; } + bool hasVertexShader() const { SkASSERT(fProgramID); return !fFragOnly; } + int getTexCoordSetCount() const { SkASSERT(fProgramID); return fTexCoordSetCnt; } + const UniformInfoArray& getUniformInfos() const { return fUniforms; } + + virtual ~GrGLProgramBuilder() {} + + /** Add a uniform variable to the current program, that has visibility in one or more shaders. + visibility is a bitfield of ShaderVisibility values indicating from which shaders the + uniform should be accessible. At least one bit must be set. Geometry shader uniforms are not + supported at this time. The actual uniform name will be mangled. If outName is not NULL then + it will refer to the final uniform name after return. Use the addUniformArray variant to add + an array of uniforms. */ + GrGLProgramDataManager::UniformHandle addUniform(uint32_t visibility, + GrSLType type, + const char* name, + const char** outName = NULL) { + return this->addUniformArray(visibility, type, name, GrGLShaderVar::kNonArray, outName); + } + GrGLProgramDataManager::UniformHandle addUniformArray(uint32_t visibility, + GrSLType type, + const char* name, + int arrayCount, + const char** outName = NULL); + + const GrGLShaderVar& getUniformVariable(GrGLProgramDataManager::UniformHandle u) const { + return fUniforms[u.toShaderBuilderIndex()].fVariable; + } + + /** + * Shortcut for getUniformVariable(u).c_str() + */ + const char* getUniformCStr(GrGLProgramDataManager::UniformHandle u) const { + return this->getUniformVariable(u).c_str(); + } + + const GrGLContextInfo& ctxInfo() const; + + GrGLFragmentShaderBuilder* getFragmentShaderBuilder() { return &fFS; } + +protected: + typedef GrTAllocator VarArray; + GrGLProgramBuilder(GrGpuGL*, const GrGLProgramDesc&); + + GrGpuGL* gpu() const { return fGpu; } + + const GrGLProgramDesc& desc() const { return fDesc; } + + // Helper for emitEffects(). + void createAndEmitEffects(GrGLProgramEffectsBuilder*, + const GrEffectStage* effectStages[], + int effectCnt, + const GrGLProgramDesc::EffectKeyProvider&, + GrGLSLExpr4* inOutFSColor); + + // Generates a name for a variable. The generated string will be name prefixed by the prefix + // char (unless the prefix is '\0'). It also mangles the name to be stage-specific if we're + // generating stage code. + void nameVariable(SkString* out, char prefix, const char* name); + + virtual bool compileAndAttachShaders(GrGLuint programId, SkTDArray* shaderIds) const; + + virtual void bindProgramLocations(GrGLuint programId); + void resolveProgramLocations(GrGLuint programId); + + void appendDecls(const VarArray&, SkString*) const; + void appendUniformDecls(ShaderVisibility, SkString*) const; + + SkAutoTUnref fColorEffects; + SkAutoTUnref fCoverageEffects; + BuiltinUniformHandles fUniformHandles; + bool fFragOnly; + int fTexCoordSetCnt; + GrGLuint fProgramID; + GrGLFragmentShaderBuilder fFS; +private: + class CodeStage : SkNoncopyable { + public: + CodeStage() : fNextIndex(0), fCurrentIndex(-1), fEffectStage(NULL) {} + + bool inStageCode() const { + this->validate(); + return NULL != fEffectStage; + } + + const GrEffectStage* effectStage() const { + this->validate(); + return fEffectStage; + } + + int stageIndex() const { + this->validate(); + return fCurrentIndex; + } + + class AutoStageRestore : SkNoncopyable { + public: + AutoStageRestore(CodeStage* codeStage, const GrEffectStage* newStage) { + SkASSERT(NULL != codeStage); + fSavedIndex = codeStage->fCurrentIndex; + fSavedEffectStage = codeStage->fEffectStage; + + if (NULL == newStage) { + codeStage->fCurrentIndex = -1; + } else { + codeStage->fCurrentIndex = codeStage->fNextIndex++; + } + codeStage->fEffectStage = newStage; + + fCodeStage = codeStage; + } + ~AutoStageRestore() { + fCodeStage->fCurrentIndex = fSavedIndex; + fCodeStage->fEffectStage = fSavedEffectStage; + } + private: + CodeStage* fCodeStage; + int fSavedIndex; + const GrEffectStage* fSavedEffectStage; + }; + private: + void validate() const { SkASSERT((NULL == fEffectStage) == (-1 == fCurrentIndex)); } + int fNextIndex; + int fCurrentIndex; + const GrEffectStage* fEffectStage; + } fCodeStage; + + /** + * The base class will emit the fragment code that precedes the per-effect code and then call + * this function. The subclass can use it to insert additional fragment code that should + * execute before the effects' code and/or emit other shaders (e.g. geometry, vertex). + * + * The subclass can modify the initial color or coverage + */ + virtual void emitCodeBeforeEffects(GrGLSLExpr4* color, GrGLSLExpr4* coverage) = 0; + + /** + * Adds code for effects and returns a GrGLProgramEffects* object. The caller is responsible for + * deleting it when finished. effectStages contains the effects to add. The effect key provider + * is used to communicate the key each effect created in its GenKey function. inOutFSColor + * specifies the input color to the first stage and is updated to be the output color of the + * last stage. The handles to texture samplers for effectStage[i] are added to + * effectSamplerHandles[i]. + */ + virtual GrGLProgramEffects* createAndEmitEffects(const GrEffectStage* effectStages[], + int effectCnt, + const GrGLProgramDesc::EffectKeyProvider&, + GrGLSLExpr4* inOutFSColor) = 0; + + /** + * Similar to emitCodeBeforeEffects() but called after per-effect code is emitted. + */ + virtual void emitCodeAfterEffects() = 0; + + /** + * Compiles all the shaders, links them into a program, and writes the program id to the output + * struct. + **/ + bool finish(); + + const GrGLProgramDesc& fDesc; + GrGpuGL* fGpu; + UniformInfoArray fUniforms; + + friend class GrGLShaderBuilder; + friend class GrGLVertexShaderBuilder; + friend class GrGLFragmentShaderBuilder; + friend class GrGLGeometryShaderBuilder; +}; + +//////////////////////////////////////////////////////////////////////////////// + +class GrGLFullProgramBuilder : public GrGLProgramBuilder { +public: + GrGLFullProgramBuilder(GrGpuGL*, const GrGLProgramDesc&); + + /** Add a varying variable to the current program to pass values between vertex and fragment + shaders. If the last two parameters are non-NULL, they are filled in with the name + generated. */ + void addVarying(GrSLType type, + const char* name, + const char** vsOutName = NULL, + const char** fsInName = NULL); + + GrGLVertexShaderBuilder* getVertexShaderBuilder() { return &fVS; } + +private: + virtual void emitCodeBeforeEffects(GrGLSLExpr4* color, GrGLSLExpr4* coverage) SK_OVERRIDE; + + virtual GrGLProgramEffects* createAndEmitEffects(const GrEffectStage* effectStages[], + int effectCnt, + const GrGLProgramDesc::EffectKeyProvider&, + GrGLSLExpr4* inOutFSColor) SK_OVERRIDE; + + virtual void emitCodeAfterEffects() SK_OVERRIDE; + + virtual bool compileAndAttachShaders(GrGLuint programId, + SkTDArray* shaderIds) const SK_OVERRIDE; + + virtual void bindProgramLocations(GrGLuint programId) SK_OVERRIDE; + + GrGLGeometryShaderBuilder fGS; + GrGLVertexShaderBuilder fVS; + + typedef GrGLProgramBuilder INHERITED; +}; + +//////////////////////////////////////////////////////////////////////////////// + +class GrGLFragmentOnlyProgramBuilder : public GrGLProgramBuilder { +public: + GrGLFragmentOnlyProgramBuilder(GrGpuGL*, const GrGLProgramDesc&); + + int addTexCoordSets(int count); + +private: + virtual void emitCodeBeforeEffects(GrGLSLExpr4* color, GrGLSLExpr4* coverage) SK_OVERRIDE {} + + virtual GrGLProgramEffects* createAndEmitEffects(const GrEffectStage* effectStages[], + int effectCnt, + const GrGLProgramDesc::EffectKeyProvider&, + GrGLSLExpr4* inOutFSColor) SK_OVERRIDE; + + virtual void emitCodeAfterEffects() SK_OVERRIDE {} + + typedef GrGLProgramBuilder INHERITED; +}; + +#endif diff --git a/src/gpu/gl/builders/GrGLSLPrettyPrint.cpp b/src/gpu/gl/builders/GrGLSLPrettyPrint.cpp new file mode 100644 index 0000000000..27f4b44e66 --- /dev/null +++ b/src/gpu/gl/builders/GrGLSLPrettyPrint.cpp @@ -0,0 +1,173 @@ +/* + * Copyright 2014 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +#include "gl/GrGLSLPrettyPrint.h" + +namespace GrGLSLPrettyPrint { + +class GLSLPrettyPrint { +public: + GLSLPrettyPrint() {} + + SkString prettify(const SkString& input, bool countlines) { + // setup pretty state + fIndex = 0; + fLength = input.size(); + fInput = input; + fCountlines = countlines; + fTabs = 0; + fLinecount = 1; + fFreshline = true; + + int parensDepth = 0; + // number 1st line + this->lineNumbering(); + while (fLength > fIndex) { + /* the heart and soul of our prettification algorithm. The rules should hopefully be + * self explanatory. For '#' and '//' tokens we parse until we reach a newline. + * + * For long style comments like this one, we search for the ending token. We also + * preserve whitespace in these comments WITH THE CAVEAT that we do the newlines + * ourselves. This allows us to remain in control of line numbers, and matching tabs + * Existing tabs in the input string are copied over too, but this will look funny + * + * '{' and '}' are handled in basically the same way. We add a newline if we aren't + * on a fresh line, dirty the line, then add a second newline, ie braces are always + * on their own lines indented properly. The one funkiness here is structs print with + * the semicolon on its own line. Its not a problem for a glsl compiler though + * + * '(' and ')' are basically ignored, except as a sign we need to ignore ';' ala + * in for loops. + * + * ';' means add a new line + * + * '\t' and '\n' are ignored in general parsing for backwards compatability with + * existing shader code and we also have a special case for handling whitespace + * at the beginning of fresh lines. + * + * Otherwise just add the new character to the pretty string, indenting if necessary. + */ + if (this->hasToken("#") || this->hasToken("//")) { + this->parseUntilNewline(); + } else if (this->hasToken("/*")) { + this->parseUntil("*/"); + } else if ('{' == fInput[fIndex]) { + this->newline(); + this->appendChar('{'); + fTabs++; + this->newline(); + } else if ('}' == fInput[fIndex]) { + fTabs--; + this->newline(); + this->appendChar('}'); + this->newline(); + } else if (this->hasToken(")")) { + parensDepth--; + } else if (this->hasToken("(")) { + parensDepth++; + } else if (!parensDepth && this->hasToken(";")) { + this->newline(); + } else if ('\t' == fInput[fIndex] || '\n' == fInput[fIndex] || + (fFreshline && ' ' == fInput[fIndex])) { + fIndex++; + } else { + this->appendChar(input[fIndex]); + } + } + return fPretty; + } +private: + void appendChar(char c) { + this->tabString(); + fPretty.appendf("%c", fInput[fIndex++]); + fFreshline = false; + } + + // hasToken automatically consumes the next token, if it is a match, and then tabs + // if necessary, before inserting the token into the pretty string + bool hasToken(const char* token) { + size_t i = fIndex; + for (size_t j = 0; token[j] && fLength > i; i++, j++) { + if (token[j] != fInput[i]) { + return false; + } + } + this->tabString(); + fIndex = i; + fPretty.append(token); + fFreshline = false; + return true; + } + + void parseUntilNewline() { + while (fLength > fIndex) { + if ('\n' == fInput[fIndex]) { + fIndex++; + this->newline(); + break; + } + fPretty.appendf("%c", fInput[fIndex++]); + } + } + + // this code assumes it is not actually searching for a newline. If you need to search for a + // newline, then use the function above. If you do search for a newline with this function + // it will consume the entire string and the output will certainly not be prettified + void parseUntil(const char* token) { + while (fLength > fIndex) { + // For embedded newlines, this code will make sure to embed the newline in the + // pretty string, increase the linecount, and tab out the next line to the appropriate + // place + if ('\n' == fInput[fIndex]) { + this->newline(); + this->tabString(); + fIndex++; + } + if (this->hasToken(token)) { + break; + } + fFreshline = false; + fPretty.appendf("%c", fInput[fIndex++]); + } + } + + // We only tab if on a newline, otherwise consider the line tabbed + void tabString() { + if (fFreshline) { + for (int t = 0; t < fTabs; t++) { + fPretty.append("\t"); + } + } + } + + // newline is really a request to add a newline, if we are on a fresh line there is no reason + // to add another newline + void newline() { + if (!fFreshline) { + fFreshline = true; + fPretty.append("\n"); + this->lineNumbering(); + } + } + + void lineNumbering() { + if (fCountlines) { + fPretty.appendf("%4d\t", fLinecount++); + } + } + + bool fCountlines, fFreshline; + int fTabs, fLinecount; + size_t fIndex, fLength; + SkString fInput, fPretty; +}; + +SkString PrettyPrintGLSL(const SkString& input, bool countlines) { + GLSLPrettyPrint pp; + return pp.prettify(input, countlines); +} + +} // end namespace diff --git a/src/gpu/gl/builders/GrGLShaderBuilder.cpp b/src/gpu/gl/builders/GrGLShaderBuilder.cpp new file mode 100644 index 0000000000..4dea142632 --- /dev/null +++ b/src/gpu/gl/builders/GrGLShaderBuilder.cpp @@ -0,0 +1,155 @@ +/* + * Copyright 2014 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "GrGLShaderBuilder.h" +#include "GrGLProgramBuilder.h" +#include "../GrGpuGL.h" +#include "../GrGLShaderVar.h" + +namespace { +inline const char* sample_function_name(GrSLType type, GrGLSLGeneration glslGen) { + if (kVec2f_GrSLType == type) { + return glslGen >= k130_GrGLSLGeneration ? "texture" : "texture2D"; + } else { + SkASSERT(kVec3f_GrSLType == type); + return glslGen >= k130_GrGLSLGeneration ? "textureProj" : "texture2DProj"; + } +} +void append_texture_lookup(SkString* out, + GrGpuGL* gpu, + const char* samplerName, + const char* coordName, + uint32_t configComponentMask, + const char* swizzle, + GrSLType varyingType = kVec2f_GrSLType) { + SkASSERT(NULL != coordName); + + out->appendf("%s(%s, %s)", + sample_function_name(varyingType, gpu->glslGeneration()), + samplerName, + coordName); + + char mangledSwizzle[5]; + + // The swizzling occurs using texture params instead of shader-mangling if ARB_texture_swizzle + // is available. + if (!gpu->glCaps().textureSwizzleSupport() && + (kA_GrColorComponentFlag == configComponentMask)) { + char alphaChar = gpu->glCaps().textureRedSupport() ? 'r' : 'a'; + int i; + for (i = 0; '\0' != swizzle[i]; ++i) { + mangledSwizzle[i] = alphaChar; + } + mangledSwizzle[i] ='\0'; + swizzle = mangledSwizzle; + } + // For shader prettiness we omit the swizzle rather than appending ".rgba". + if (memcmp(swizzle, "rgba", 4)) { + out->appendf(".%s", swizzle); + } +} +static const int kVarsPerBlock = 8; +} + +GrGLShaderBuilder::GrGLShaderBuilder(GrGLProgramBuilder* program) + : fProgramBuilder(program) + , fInputs(kVarsPerBlock) + , fOutputs(kVarsPerBlock) + , fFeaturesAddedMask(0) { +} + +void GrGLShaderBuilder::emitFunction(GrSLType returnType, + const char* name, + int argCnt, + const GrGLShaderVar* args, + const char* body, + SkString* outName) { + fFunctions.append(GrGLSLTypeString(returnType)); + fProgramBuilder->nameVariable(outName, '\0', name); + fFunctions.appendf(" %s", outName->c_str()); + fFunctions.append("("); + const GrGLContextInfo& ctxInfo = fProgramBuilder->gpu()->ctxInfo(); + for (int i = 0; i < argCnt; ++i) { + args[i].appendDecl(ctxInfo, &fFunctions); + if (i < argCnt - 1) { + fFunctions.append(", "); + } + } + fFunctions.append(") {\n"); + fFunctions.append(body); + fFunctions.append("}\n\n"); +} + +void GrGLShaderBuilder::appendTextureLookup(SkString* out, + const TextureSampler& sampler, + const char* coordName, + GrSLType varyingType) const { + append_texture_lookup(out, + fProgramBuilder->gpu(), + fProgramBuilder->getUniformCStr(sampler.samplerUniform()), + coordName, + sampler.configComponentMask(), + sampler.swizzle(), + varyingType); +} + +void GrGLShaderBuilder::appendTextureLookup(const TextureSampler& sampler, + const char* coordName, + GrSLType varyingType) { + this->appendTextureLookup(&fCode, sampler, coordName, varyingType); +} + +void GrGLShaderBuilder::appendTextureLookupAndModulate(const char* modulation, + const TextureSampler& sampler, + const char* coordName, + GrSLType varyingType) { + SkString lookup; + this->appendTextureLookup(&lookup, sampler, coordName, varyingType); + this->codeAppend((GrGLSLExpr4(modulation) * GrGLSLExpr4(lookup)).c_str()); +} + + +const GrGLenum* GrGLShaderBuilder::GetTexParamSwizzle(GrPixelConfig config, const GrGLCaps& caps) { + if (caps.textureSwizzleSupport() && GrPixelConfigIsAlphaOnly(config)) { + if (caps.textureRedSupport()) { + static const GrGLenum gRedSmear[] = { GR_GL_RED, GR_GL_RED, GR_GL_RED, GR_GL_RED }; + return gRedSmear; + } else { + static const GrGLenum gAlphaSmear[] = { GR_GL_ALPHA, GR_GL_ALPHA, + GR_GL_ALPHA, GR_GL_ALPHA }; + return gAlphaSmear; + } + } else { + static const GrGLenum gStraight[] = { GR_GL_RED, GR_GL_GREEN, GR_GL_BLUE, GR_GL_ALPHA }; + return gStraight; + } +} + +void GrGLShaderBuilder::addFeature(uint32_t featureBit, const char* extensionName) { + if (!(featureBit & fFeaturesAddedMask)) { + fExtensions.appendf("#extension %s: require\n", extensionName); + fFeaturesAddedMask |= featureBit; + } +} + +void GrGLShaderBuilder::appendTextureLookup(const char* samplerName, + const char* coordName, + uint32_t configComponentMask, + const char* swizzle) { + append_texture_lookup(&fCode, + fProgramBuilder->gpu(), + samplerName, + coordName, + configComponentMask, + swizzle, + kVec2f_GrSLType); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +GrGLFullShaderBuilder::GrGLFullShaderBuilder(GrGLFullProgramBuilder* program) + : INHERITED(program) + , fFullProgramBuilder(program) {} diff --git a/src/gpu/gl/builders/GrGLShaderBuilder.h b/src/gpu/gl/builders/GrGLShaderBuilder.h new file mode 100644 index 0000000000..1d0fa6a790 --- /dev/null +++ b/src/gpu/gl/builders/GrGLShaderBuilder.h @@ -0,0 +1,170 @@ +/* + * Copyright 2014 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrGLShaderBuilder_DEFINED +#define GrGLShaderBuilder_DEFINED + +#include "gl/GrGLProgramDesc.h" +#include "gl/GrGLProgramEffects.h" +#include "gl/GrGLSL.h" +#include "gl/GrGLProgramDataManager.h" +#include "GrAllocator.h" +#include "GrBackendEffectFactory.h" +#include "GrColor.h" +#include "GrEffect.h" +#include "SkTypes.h" + +#include + +class GrGLContextInfo; +class GrEffectStage; +class GrGLProgramDesc; +class GrGLProgramBuilder; +class GrGLFullProgramBuilder; + +/** + base class for all shaders builders +*/ +class GrGLShaderBuilder { +public: + typedef GrGLProgramEffects::TransformedCoordsArray TransformedCoordsArray; + typedef GrGLProgramEffects::TextureSampler TextureSampler; + GrGLShaderBuilder(GrGLProgramBuilder* program); + + void addInput(GrGLShaderVar i) { fInputs.push_back(i); } + void addOutput(GrGLShaderVar i) { fOutputs.push_back(i); } + + /* + * We put texture lookups in the base class because it is TECHNICALLY possible to do texture + * lookups in any kind of shader. However, for the time being using these calls on non-fragment + * shaders will result in a shader compilation error as texture sampler uniforms are only + * visible to the fragment shader. It would not be hard to change this behavior, if someone + * actually wants to do texture lookups in a non-fragment shader + * + * TODO if append texture lookup is used on a non-fragment shader, sampler uniforms should be + * made visible to that shaders + */ + /** Appends a 2D texture sample with projection if necessary. coordType must either be Vec2f or + Vec3f. The latter is interpreted as projective texture coords. The vec length and swizzle + order of the result depends on the GrTextureAccess associated with the TextureSampler. */ + void appendTextureLookup(SkString* out, + const TextureSampler&, + const char* coordName, + GrSLType coordType = kVec2f_GrSLType) const; + + /** Version of above that appends the result to the fragment shader code instead.*/ + void appendTextureLookup(const TextureSampler&, + const char* coordName, + GrSLType coordType = kVec2f_GrSLType); + + + /** Does the work of appendTextureLookup and modulates the result by modulation. The result is + always a vec4. modulation and the swizzle specified by TextureSampler must both be vec4 or + float. If modulation is "" or NULL it this function acts as though appendTextureLookup were + called. */ + void appendTextureLookupAndModulate(const char* modulation, + const TextureSampler&, + const char* coordName, + GrSLType coordType = kVec2f_GrSLType); + + /** If texture swizzling is available using tex parameters then it is preferred over mangling + the generated shader code. This potentially allows greater reuse of cached shaders. */ + static const GrGLenum* GetTexParamSwizzle(GrPixelConfig config, const GrGLCaps& caps); + + /** + * Called by GrGLEffects to add code to one of the shaders. + */ + void codeAppendf(const char format[], ...) SK_PRINTF_LIKE(2, 3) { + va_list args; + va_start(args, format); + fCode.appendVAList(format, args); + va_end(args); + } + + void codeAppend(const char* str) { fCode.append(str); } + + void codePrependf(const char format[], ...) SK_PRINTF_LIKE(2, 3) { + va_list args; + va_start(args, format); + fCode.prependVAList(format, args); + va_end(args); + } + + /** Emits a helper function outside of main() in the fragment shader. */ + void emitFunction(GrSLType returnType, + const char* name, + int argCnt, + const GrGLShaderVar* args, + const char* body, + SkString* outName); + + /* + * Get parent builder for adding uniforms + */ + GrGLProgramBuilder* getProgramBuilder() { return fProgramBuilder; } + + /** + * Helper for begining and ending a block in the fragment code. + */ + class ShaderBlock { + public: + ShaderBlock(GrGLShaderBuilder* builder) : fBuilder(builder) { + SkASSERT(NULL != builder); + fBuilder->codeAppend("{"); + } + + ~ShaderBlock() { + fBuilder->codeAppend("}"); + } + private: + GrGLShaderBuilder* fBuilder; + }; +protected: + + /* + * this super low level function is just for use internally to builders + */ + void appendTextureLookup(const char* samplerName, + const char* coordName, + uint32_t configComponentMask, + const char* swizzle); + + /* + * A general function which enables an extension in a shader if the feature bit is not present + */ + void addFeature(uint32_t featureBit, const char* extensionName); + + typedef GrTAllocator VarArray; + + GrGLProgramBuilder* fProgramBuilder; + + SkString fCode; + SkString fFunctions; + SkString fExtensions; + + VarArray fInputs; + VarArray fOutputs; + uint32_t fFeaturesAddedMask; +}; + + +/* + * Full Shader builder is the base class for shaders which are only accessible through full program + * builder, ie vertex, geometry, and later TCU / TES. Using this base class, they can access the + * full program builder functionality through the full program pointer + */ +class GrGLFullShaderBuilder : public GrGLShaderBuilder { +public: + GrGLFullShaderBuilder(GrGLFullProgramBuilder* program); + + GrGLFullProgramBuilder* fullProgramBuilder() { return fFullProgramBuilder; } +protected: + GrGLFullProgramBuilder* fFullProgramBuilder; +private: + typedef GrGLShaderBuilder INHERITED; +}; +#endif diff --git a/src/gpu/gl/builders/GrGLShaderStringBuilder.cpp b/src/gpu/gl/builders/GrGLShaderStringBuilder.cpp new file mode 100644 index 0000000000..dff8c7e684 --- /dev/null +++ b/src/gpu/gl/builders/GrGLShaderStringBuilder.cpp @@ -0,0 +1,85 @@ +/* + * Copyright 2014 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "GrGLShaderStringBuilder.h" +#include "../GrGpuGL.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) + +SK_CONF_DECLARE(bool, c_PrintShaders, "gpu.printShaders", false, + "Print the source code for all shaders generated."); + +GrGLuint GrGLCompileAndAttachShader(const GrGLContext& glCtx, + GrGLuint programId, + GrGLenum type, + const SkString& shaderSrc) { + const GrGLInterface* gli = glCtx.interface(); + + GrGLuint shaderId; + GR_GL_CALL_RET(gli, shaderId, CreateShader(type)); + if (0 == shaderId) { + return 0; + } + + #ifdef SK_DEBUG + SkString prettySource = GrGLSLPrettyPrint::PrettyPrintGLSL(shaderSrc, false); + const GrGLchar* sourceStr = prettySource.c_str(); + GrGLint sourceLength = static_cast(prettySource.size()); + #else + GrGLint sourceLength = static_cast(shaderSrc.size()); + const GrGLchar* sourceStr = shaderSrc.c_str(); + #endif + GR_GL_CALL(gli, ShaderSource(shaderId, 1, &sourceStr, &sourceLength)); + GR_GL_CALL(gli, CompileShader(shaderId)); + + // Calling GetShaderiv in Chromium is quite expensive. Assume success in release builds. + bool checkCompiled = !glCtx.isChromium(); + #ifdef SK_DEBUG + checkCompiled = true; + #endif + if (checkCompiled) { + GrGLint compiled = GR_GL_INIT_ZERO; + GR_GL_CALL(gli, GetShaderiv(shaderId, GR_GL_COMPILE_STATUS, &compiled)); + + if (!compiled) { + GrGLint infoLen = GR_GL_INIT_ZERO; + GR_GL_CALL(gli, GetShaderiv(shaderId, GR_GL_INFO_LOG_LENGTH, &infoLen)); + SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger + if (infoLen > 0) { + // retrieve length even though we don't need it to workaround bug in Chromium cmd + // buffer param validation. + GrGLsizei length = GR_GL_INIT_ZERO; + GR_GL_CALL(gli, GetShaderInfoLog(shaderId, infoLen+1, + &length, (char*)log.get())); + GrPrintf(GrGLSLPrettyPrint::PrettyPrintGLSL(shaderSrc, true).c_str()); + GrPrintf("\n%s", log.get()); + } + SkDEBUGFAIL("Shader compilation failed!"); + GR_GL_CALL(gli, DeleteShader(shaderId)); + return 0; + } + } + + TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("skia.gpu"), "skia_gpu::GLShader", + TRACE_EVENT_SCOPE_THREAD, "shader", TRACE_STR_COPY(shaderSrc.c_str())); + if (c_PrintShaders) { + GrPrintf(GrGLSLPrettyPrint::PrettyPrintGLSL(shaderSrc, true).c_str()); + GrPrintf("\n"); + } + + // Attach the shader, but defer deletion until after we have linked the program. + // This works around a bug in the Android emulator's GLES2 wrapper which + // will immediately delete the shader object and free its memory even though it's + // attached to a program, which then causes glLinkProgram to fail. + GR_GL_CALL(gli, AttachShader(programId, shaderId)); + + return shaderId; +} diff --git a/src/gpu/gl/builders/GrGLShaderStringBuilder.h b/src/gpu/gl/builders/GrGLShaderStringBuilder.h new file mode 100644 index 0000000000..8c18fa570a --- /dev/null +++ b/src/gpu/gl/builders/GrGLShaderStringBuilder.h @@ -0,0 +1,20 @@ +/* + * Copyright 2014 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrGLShaderStringBuilder_DEFINED +#define GrGLShaderStringBuilder_DEFINED + +#include "GrAllocator.h" +#include "gl/GrGLContext.h" +#include "SkTypes.h" + +GrGLuint GrGLCompileAndAttachShader(const GrGLContext& glCtx, + GrGLuint programId, + GrGLenum type, + const SkString& shaderSrc); + +#endif diff --git a/src/gpu/gl/builders/GrGLVertexShaderBuilder.cpp b/src/gpu/gl/builders/GrGLVertexShaderBuilder.cpp new file mode 100644 index 0000000000..6abc085706 --- /dev/null +++ b/src/gpu/gl/builders/GrGLVertexShaderBuilder.cpp @@ -0,0 +1,200 @@ +/* + * Copyright 2014 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "GrGLVertexShaderBuilder.h" +#include "GrGLProgramBuilder.h" +#include "GrGLShaderStringBuilder.h" +#include "../GrGpuGL.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) + +namespace { +inline const char* color_attribute_name() { return "aColor"; } +inline const char* coverage_attribute_name() { return "aCoverage"; } +} + +GrGLVertexShaderBuilder::GrGLVertexShaderBuilder(GrGLFullProgramBuilder* program) + : INHERITED(program) + , fPositionVar(NULL) + , fLocalCoordsVar(NULL) { +} +bool GrGLVertexShaderBuilder::addAttribute(GrSLType type, const char* name) { + for (int i = 0; i < fInputs.count(); ++i) { + const GrGLShaderVar& attr = fInputs[i]; + // if attribute already added, don't add it again + if (attr.getName().equals(name)) { + return false; + } + } + fInputs.push_back().set(type, GrGLShaderVar::kAttribute_TypeModifier, name); + return true; +} + +bool GrGLVertexShaderBuilder::addEffectAttribute(int attributeIndex, + GrSLType type, + const SkString& name) { + if (!this->addAttribute(type, name.c_str())) { + return false; + } + + fEffectAttributes.push_back().set(attributeIndex, name); + return true; +} + +void GrGLVertexShaderBuilder::emitAttributes(const GrEffectStage& stage) { + int numAttributes = stage.getVertexAttribIndexCount(); + const int* attributeIndices = stage.getVertexAttribIndices(); + for (int a = 0; a < numAttributes; ++a) { + // TODO: Make addAttribute mangle the name. + SkString attributeName("aAttr"); + attributeName.appendS32(attributeIndices[a]); + this->addEffectAttribute(attributeIndices[a], + stage.getEffect()->vertexAttribType(a), + attributeName); + } +} + +const SkString* GrGLVertexShaderBuilder::getEffectAttributeName(int attributeIndex) const { + const AttributePair* attribEnd = fEffectAttributes.end(); + for (const AttributePair* attrib = fEffectAttributes.begin(); attrib != attribEnd; ++attrib) { + if (attrib->fIndex == attributeIndex) { + return &attrib->fName; + } + } + + return NULL; +} + +void GrGLVertexShaderBuilder::addVarying(GrSLType type, const char* name, const char** vsOutName) { + fOutputs.push_back(); + fOutputs.back().setType(type); + fOutputs.back().setTypeModifier(GrGLShaderVar::kVaryingOut_TypeModifier); + fProgramBuilder->nameVariable(fOutputs.back().accessName(), 'v', name); + + if (vsOutName) { + *vsOutName = fOutputs.back().getName().c_str(); + } +} + + +void GrGLVertexShaderBuilder::bindProgramLocations(GrGLuint programId) { + const GrGLProgramDesc::KeyHeader& header = fProgramBuilder->desc().getHeader(); + GrGpuGL* gpu = fProgramBuilder->gpu(); + + // Bind the attrib locations to same values for all shaders + SkASSERT(-1 != header.fPositionAttributeIndex); + GL_CALL(BindAttribLocation(programId, + header.fPositionAttributeIndex, + fPositionVar->c_str())); + if (-1 != header.fLocalCoordAttributeIndex) { + GL_CALL(BindAttribLocation(programId, + header.fLocalCoordAttributeIndex, + fLocalCoordsVar->c_str())); + } + if (-1 != header.fColorAttributeIndex) { + GL_CALL(BindAttribLocation(programId, + header.fColorAttributeIndex, + color_attribute_name())); + } + if (-1 != header.fCoverageAttributeIndex) { + GL_CALL(BindAttribLocation(programId, + header.fCoverageAttributeIndex, + coverage_attribute_name())); + } + + const AttributePair* attribEnd = fEffectAttributes.end(); + for (const AttributePair* attrib = fEffectAttributes.begin(); attrib != attribEnd; ++attrib) { + GL_CALL(BindAttribLocation(programId, attrib->fIndex, attrib->fName.c_str())); + } +} + +bool GrGLVertexShaderBuilder::compileAndAttachShaders(GrGLuint programId, + SkTDArray* shaderIds) const { + GrGpuGL* gpu = fProgramBuilder->gpu(); + const GrGLContext& glCtx = gpu->glContext(); + const GrGLContextInfo& ctxInfo = gpu->ctxInfo(); + SkString vertShaderSrc(GrGetGLSLVersionDecl(ctxInfo)); + fProgramBuilder->appendUniformDecls(GrGLProgramBuilder::kVertex_Visibility, &vertShaderSrc); + fProgramBuilder->appendDecls(fInputs, &vertShaderSrc); + fProgramBuilder->appendDecls(fOutputs, &vertShaderSrc); + vertShaderSrc.append("void main() {\n"); + vertShaderSrc.append(fCode); + vertShaderSrc.append("}\n"); + GrGLuint vertShaderId = GrGLCompileAndAttachShader(glCtx, programId, + GR_GL_VERTEX_SHADER, vertShaderSrc); + if (!vertShaderId) { + return false; + } + *shaderIds->append() = vertShaderId; + return true; +} + +void GrGLVertexShaderBuilder::emitCodeAfterEffects() { + const char* rtAdjustName; + fProgramBuilder->fUniformHandles.fRTAdjustmentUni = + fProgramBuilder->addUniform(GrGLProgramBuilder::kVertex_Visibility, + kVec4f_GrSLType, + "rtAdjustment", + &rtAdjustName); + + // Transform from Skia's device coords to GL's normalized device coords. + this->codeAppendf( + "\tgl_Position = vec4(dot(pos3.xz, %s.xy), dot(pos3.yz, %s.zw), 0, pos3.z);\n", + rtAdjustName, rtAdjustName); +} + +void GrGLVertexShaderBuilder::emitCodeBeforeEffects(GrGLSLExpr4* color, GrGLSLExpr4* coverage) { + const GrGLProgramDesc::KeyHeader& header = fProgramBuilder->desc().getHeader(); + + fPositionVar = &fInputs.push_back(); + fPositionVar->set(kVec2f_GrSLType, GrGLShaderVar::kAttribute_TypeModifier, "aPosition"); + if (-1 != header.fLocalCoordAttributeIndex) { + fLocalCoordsVar = &fInputs.push_back(); + fLocalCoordsVar->set(kVec2f_GrSLType, + GrGLShaderVar::kAttribute_TypeModifier, + "aLocalCoords"); + } else { + fLocalCoordsVar = fPositionVar; + } + + const char* viewMName; + fProgramBuilder->fUniformHandles.fViewMatrixUni = + fProgramBuilder->addUniform(GrGLProgramBuilder::kVertex_Visibility, + kMat33f_GrSLType, + "ViewM", + &viewMName); + + // Transform the position into Skia's device coords. + this->codeAppendf("\tvec3 pos3 = %s * vec3(%s, 1);\n", + viewMName, fPositionVar->c_str()); + + // we output point size in the GS if present + if (header.fEmitsPointSize +#if GR_GL_EXPERIMENTAL_GS + && !header.fExperimentalGS +#endif + ) { + this->codeAppend("\tgl_PointSize = 1.0;\n"); + } + + if (GrGLProgramDesc::kAttribute_ColorInput == header.fColorInput) { + this->addAttribute(kVec4f_GrSLType, color_attribute_name()); + const char *vsName, *fsName; + fFullProgramBuilder->addVarying(kVec4f_GrSLType, "Color", &vsName, &fsName); + this->codeAppendf("\t%s = %s;\n", vsName, color_attribute_name()); + *color = fsName; + } + + if (GrGLProgramDesc::kAttribute_ColorInput == header.fCoverageInput) { + this->addAttribute(kVec4f_GrSLType, coverage_attribute_name()); + const char *vsName, *fsName; + fFullProgramBuilder->addVarying(kVec4f_GrSLType, "Coverage", &vsName, &fsName); + this->codeAppendf("\t%s = %s;\n", vsName, coverage_attribute_name()); + *coverage = fsName; + } +} diff --git a/src/gpu/gl/builders/GrGLVertexShaderBuilder.h b/src/gpu/gl/builders/GrGLVertexShaderBuilder.h new file mode 100644 index 0000000000..c576f57882 --- /dev/null +++ b/src/gpu/gl/builders/GrGLVertexShaderBuilder.h @@ -0,0 +1,81 @@ +/* + * Copyright 2014 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrGLVertexShader_DEFINED +#define GrGLVertexShader_DEFINED +#include "GrGLShaderBuilder.h" + +class GrGLProgramBuilder; + +class GrGLVertexShaderBuilder : public GrGLFullShaderBuilder { +public: + GrGLVertexShaderBuilder(GrGLFullProgramBuilder* program); + + /* + * Add attribute will push a new attribute onto the end. It will also assert if there is + * a duplicate attribute + */ + bool addAttribute(GrSLType type, const char* name); + + bool addEffectAttribute(int attributeIndex, GrSLType type, const SkString& name); + + /* + * this call is only for GrGLProgramEffects' internal use + */ + void emitAttributes(const GrEffectStage& stage); + + /** + * Are explicit local coordinates provided as input to the vertex shader. + */ + bool hasExplicitLocalCoords() const { return (fLocalCoordsVar != fPositionVar); } + + const SkString* getEffectAttributeName(int attributeIndex) const; + + /** Returns a vertex attribute that represents the local coords in the VS. This may be the same + as positionAttribute() or it may not be. It depends upon whether the rendering code + specified explicit local coords or not in the GrDrawState. */ + const GrGLShaderVar& localCoordsAttribute() const { return *fLocalCoordsVar; } + + /** Returns a vertex attribute that represents the vertex position in the VS. This is the + pre-matrix position and is commonly used by effects to compute texture coords via a matrix. + */ + const GrGLShaderVar& positionAttribute() const { return *fPositionVar; } + +private: + /* + * Internal call for GrGLFullProgramBuilder.addVarying + */ + void addVarying(GrSLType type, + const char* name, + const char** vsOutName); + + /* + * private helpers for compilation by GrGLProgramBuilder + */ + void bindProgramLocations(GrGLuint programId); + bool compileAndAttachShaders(GrGLuint programId, SkTDArray* shaderIds) const; + void emitCodeBeforeEffects(GrGLSLExpr4* color, GrGLSLExpr4* coverage); + void emitCodeAfterEffects(); + + struct AttributePair { + void set(int index, const SkString& name) { + fIndex = index; fName = name; + } + int fIndex; + SkString fName; + }; + + SkSTArray<10, AttributePair, true> fEffectAttributes; + GrGLShaderVar* fPositionVar; + GrGLShaderVar* fLocalCoordsVar; + + friend class GrGLFullProgramBuilder; + + typedef GrGLFullShaderBuilder INHERITED; +}; + +#endif diff --git a/tests/GLProgramsTest.cpp b/tests/GLProgramsTest.cpp index 5763211029..3ab17d4f8d 100644 --- a/tests/GLProgramsTest.cpp +++ b/tests/GLProgramsTest.cpp @@ -102,13 +102,13 @@ bool GrGLProgramDesc::setRandom(SkRandom* random, header->fCoverageEffectCnt = numCoverageStages; if (dstRead) { - header->fDstReadKey = SkToU8(GrGLShaderBuilder::KeyForDstRead(dstCopyTexture, + header->fDstReadKey = SkToU8(GrGLFragmentShaderBuilder::KeyForDstRead(dstCopyTexture, gpu->glCaps())); } else { header->fDstReadKey = 0; } if (fragPos) { - header->fFragPosKey = SkToU8(GrGLShaderBuilder::KeyForFragmentPosition(dstRenderTarget, + header->fFragPosKey = SkToU8(GrGLFragmentShaderBuilder::KeyForFragmentPosition(dstRenderTarget, gpu->glCaps())); } else { header->fFragPosKey = 0; -- cgit v1.2.3