Revert "Revert "Switched highp float to highfloat and mediump float to half.""

This reverts commit 1d816b92bb.

Bug: skia:
Change-Id: I388b5e5e9bf619db48297a80c9a80c039f26c9f1
Reviewed-on: https://skia-review.googlesource.com/46464
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
This commit is contained in:
Ethan Nicholas 2017-09-15 11:42:17 -04:00 committed by Skia Commit-Bot
parent 49f1f34438
commit 05d5a13fea
132 changed files with 2806 additions and 2636 deletions

View File

@ -111,9 +111,9 @@ GrGLuint GLCpuPosInstancedArraysBench::setupShader(const GrGLContext* ctx) {
const char* version = shaderCaps->versionDeclString(); const char* version = shaderCaps->versionDeclString();
// setup vertex shader // setup vertex shader
GrShaderVar aPosition("a_position", kVec2f_GrSLType, GrShaderVar::kIn_TypeModifier); GrShaderVar aPosition("a_position", kHalf2_GrSLType, GrShaderVar::kIn_TypeModifier);
GrShaderVar aColor("a_color", kVec3f_GrSLType, GrShaderVar::kIn_TypeModifier); GrShaderVar aColor("a_color", kHalf3_GrSLType, GrShaderVar::kIn_TypeModifier);
GrShaderVar oColor("o_color", kVec3f_GrSLType, GrShaderVar::kOut_TypeModifier); GrShaderVar oColor("o_color", kHalf3_GrSLType, GrShaderVar::kOut_TypeModifier);
SkString vshaderTxt(version); SkString vshaderTxt(version);
aPosition.appendDecl(shaderCaps, &vshaderTxt); aPosition.appendDecl(shaderCaps, &vshaderTxt);
@ -126,14 +126,13 @@ GrGLuint GLCpuPosInstancedArraysBench::setupShader(const GrGLContext* ctx) {
vshaderTxt.append( vshaderTxt.append(
"void main()\n" "void main()\n"
"{\n" "{\n"
"gl_Position = float4(a_position, 0., 1.);\n" "gl_Position = highfloat4(a_position, 0., 1.);\n"
"o_color = a_color;\n" "o_color = a_color;\n"
"}\n"); "}\n");
// setup fragment shader // setup fragment shader
GrShaderVar oFragColor("o_FragColor", kVec4f_GrSLType, GrShaderVar::kOut_TypeModifier); GrShaderVar oFragColor("o_FragColor", kHalf4_GrSLType, GrShaderVar::kOut_TypeModifier);
SkString fshaderTxt(version); SkString fshaderTxt(version);
GrGLSLAppendDefaultFloatPrecisionDeclaration(kMedium_GrSLPrecision, *shaderCaps, &fshaderTxt);
oColor.setTypeModifier(GrShaderVar::kIn_TypeModifier); oColor.setTypeModifier(GrShaderVar::kIn_TypeModifier);
oColor.appendDecl(shaderCaps, &fshaderTxt); oColor.appendDecl(shaderCaps, &fshaderTxt);
fshaderTxt.append(";\n"); fshaderTxt.append(";\n");
@ -150,7 +149,7 @@ GrGLuint GLCpuPosInstancedArraysBench::setupShader(const GrGLContext* ctx) {
fshaderTxt.appendf( fshaderTxt.appendf(
"void main()\n" "void main()\n"
"{\n" "{\n"
"%s = float4(o_color, 1.0);\n" "%s = highfloat4(o_color, 1.0);\n"
"}\n", fsOutName); "}\n", fsOutName);
return CreateProgram(ctx, vshaderTxt.c_str(), fshaderTxt.c_str()); return CreateProgram(ctx, vshaderTxt.c_str(), fshaderTxt.c_str());

View File

@ -101,10 +101,10 @@ GrGLuint GLVec4ScalarBench::setupShader(const GrGLContext* ctx) {
// corner of the screen than the previous circle. // corner of the screen than the previous circle.
// set up vertex shader; this is a trivial vertex shader that passes through position and color // set up vertex shader; this is a trivial vertex shader that passes through position and color
GrShaderVar aPosition("a_position", kVec2f_GrSLType, GrShaderVar::kIn_TypeModifier); GrShaderVar aPosition("a_position", kHalf2_GrSLType, GrShaderVar::kIn_TypeModifier);
GrShaderVar oPosition("o_position", kVec2f_GrSLType, GrShaderVar::kOut_TypeModifier); GrShaderVar oPosition("o_position", kHalf2_GrSLType, GrShaderVar::kOut_TypeModifier);
GrShaderVar aColor("a_color", kVec3f_GrSLType, GrShaderVar::kIn_TypeModifier); GrShaderVar aColor("a_color", kHalf3_GrSLType, GrShaderVar::kIn_TypeModifier);
GrShaderVar oColor("o_color", kVec3f_GrSLType, GrShaderVar::kOut_TypeModifier); GrShaderVar oColor("o_color", kHalf3_GrSLType, GrShaderVar::kOut_TypeModifier);
SkString vshaderTxt(version); SkString vshaderTxt(version);
aPosition.appendDecl(shaderCaps, &vshaderTxt); aPosition.appendDecl(shaderCaps, &vshaderTxt);
@ -119,7 +119,7 @@ GrGLuint GLVec4ScalarBench::setupShader(const GrGLContext* ctx) {
vshaderTxt.append( vshaderTxt.append(
"void main()\n" "void main()\n"
"{\n" "{\n"
" gl_Position = float4(a_position, 0.0, 1.0);\n" " gl_Position = highfloat4(a_position, 0.0, 1.0);\n"
" o_position = a_position;\n" " o_position = a_position;\n"
" o_color = a_color;\n" " o_color = a_color;\n"
"}\n"); "}\n");
@ -129,9 +129,8 @@ GrGLuint GLVec4ScalarBench::setupShader(const GrGLContext* ctx) {
// coded center and compare that to some hard-coded circle radius to compute a coverage. // coded center and compare that to some hard-coded circle radius to compute a coverage.
// Then, this coverage is mixed with the coverage from the previous stage and passed to the // Then, this coverage is mixed with the coverage from the previous stage and passed to the
// next stage. // next stage.
GrShaderVar oFragColor("o_FragColor", kVec4f_GrSLType, GrShaderVar::kOut_TypeModifier); GrShaderVar oFragColor("o_FragColor", kHalf4_GrSLType, GrShaderVar::kOut_TypeModifier);
SkString fshaderTxt(version); SkString fshaderTxt(version);
GrGLSLAppendDefaultFloatPrecisionDeclaration(kMedium_GrSLPrecision, *shaderCaps, &fshaderTxt);
oPosition.setTypeModifier(GrShaderVar::kIn_TypeModifier); oPosition.setTypeModifier(GrShaderVar::kIn_TypeModifier);
oPosition.appendDecl(shaderCaps, &fshaderTxt); oPosition.appendDecl(shaderCaps, &fshaderTxt);
fshaderTxt.append(";\n"); fshaderTxt.append(";\n");
@ -152,13 +151,13 @@ GrGLuint GLVec4ScalarBench::setupShader(const GrGLContext* ctx) {
fshaderTxt.appendf( fshaderTxt.appendf(
"void main()\n" "void main()\n"
"{\n" "{\n"
" float4 outputColor;\n" " half4 outputColor;\n"
" %s outputCoverage;\n" " %s outputCoverage;\n"
" outputColor = float4(%s, 1.0);\n" " outputColor = half4(%s, 1.0);\n"
" outputCoverage = %s;\n", " outputCoverage = %s;\n",
fCoverageSetup == kUseVec4_CoverageSetup ? "float4" : "float", fCoverageSetup == kUseVec4_CoverageSetup ? "half4" : "half",
oColor.getName().c_str(), oColor.getName().c_str(),
fCoverageSetup == kUseVec4_CoverageSetup ? "float4(1.0)" : "1.0" fCoverageSetup == kUseVec4_CoverageSetup ? "half4(1.0)" : "1.0"
); );
float radius = 1.0f; float radius = 1.0f;
@ -167,13 +166,13 @@ GrGLuint GLVec4ScalarBench::setupShader(const GrGLContext* ctx) {
float centerY = 1.0f - radius; float centerY = 1.0f - radius;
fshaderTxt.appendf( fshaderTxt.appendf(
" {\n" " {\n"
" float d = length(%s - float2(%f, %f));\n" " half d = length(%s - half2(%f, %f));\n"
" float edgeAlpha = clamp(100.0 * (%f - d), 0.0, 1.0);\n" " half edgeAlpha = clamp(100.0 * (%f - d), 0.0, 1.0);\n"
" outputCoverage = 0.5 * outputCoverage + 0.5 * %s;\n" " outputCoverage = 0.5 * outputCoverage + 0.5 * %s;\n"
" }\n", " }\n",
oPosition.getName().c_str(), centerX, centerY, oPosition.getName().c_str(), centerX, centerY,
radius, radius,
fCoverageSetup == kUseVec4_CoverageSetup ? "float4(edgeAlpha)" : "edgeAlpha" fCoverageSetup == kUseVec4_CoverageSetup ? "half4(edgeAlpha)" : "edgeAlpha"
); );
radius *= 0.8f; radius *= 0.8f;
} }

View File

@ -69,7 +69,7 @@ GrGLuint GLVertexAttributesBench::setupShader(const GrGLContext* ctx, uint32_t a
const char* version = shaderCaps->versionDeclString(); const char* version = shaderCaps->versionDeclString();
// setup vertex shader // setup vertex shader
GrShaderVar aPosition("a_position", kVec4f_GrSLType, GrShaderVar::kIn_TypeModifier); GrShaderVar aPosition("a_position", kHighFloat4_GrSLType, GrShaderVar::kIn_TypeModifier);
SkTArray<GrShaderVar> aVars; SkTArray<GrShaderVar> aVars;
SkTArray<GrShaderVar> oVars; SkTArray<GrShaderVar> oVars;
@ -81,7 +81,7 @@ GrGLuint GLVertexAttributesBench::setupShader(const GrGLContext* ctx, uint32_t a
SkString aname; SkString aname;
aname.appendf("a_color_%d", i); aname.appendf("a_color_%d", i);
aVars.push_back(GrShaderVar(aname.c_str(), aVars.push_back(GrShaderVar(aname.c_str(),
kVec4f_GrSLType, kHalf4_GrSLType,
GrShaderVar::kIn_TypeModifier)); GrShaderVar::kIn_TypeModifier));
aVars.back().appendDecl(shaderCaps, &vshaderTxt); aVars.back().appendDecl(shaderCaps, &vshaderTxt);
vshaderTxt.append(";\n"); vshaderTxt.append(";\n");
@ -92,7 +92,7 @@ GrGLuint GLVertexAttributesBench::setupShader(const GrGLContext* ctx, uint32_t a
SkString oname; SkString oname;
oname.appendf("o_color_%d", i); oname.appendf("o_color_%d", i);
oVars.push_back(GrShaderVar(oname.c_str(), oVars.push_back(GrShaderVar(oname.c_str(),
kVec4f_GrSLType, kHalf4_GrSLType,
GrShaderVar::kOut_TypeModifier)); GrShaderVar::kOut_TypeModifier));
oVars.back().appendDecl(shaderCaps, &vshaderTxt); oVars.back().appendDecl(shaderCaps, &vshaderTxt);
vshaderTxt.append(";\n"); vshaderTxt.append(";\n");
@ -109,15 +109,14 @@ GrGLuint GLVertexAttributesBench::setupShader(const GrGLContext* ctx, uint32_t a
// Passthrough position as a dummy // Passthrough position as a dummy
for (uint32_t i = attribs; i < maxAttribs; i++) { for (uint32_t i = attribs; i < maxAttribs; i++) {
vshaderTxt.appendf("%s = float4(0, 0, 0, 1);\n", oVars[i].c_str()); vshaderTxt.appendf("%s = highfloat4(0, 0, 0, 1);\n", oVars[i].c_str());
} }
vshaderTxt.append("}\n"); vshaderTxt.append("}\n");
// setup fragment shader // setup fragment shader
GrShaderVar oFragColor("o_FragColor", kVec4f_GrSLType, GrShaderVar::kOut_TypeModifier); GrShaderVar oFragColor("o_FragColor", kHalf4_GrSLType, GrShaderVar::kOut_TypeModifier);
SkString fshaderTxt(version); SkString fshaderTxt(version);
GrGLSLAppendDefaultFloatPrecisionDeclaration(kMedium_GrSLPrecision, *shaderCaps, &fshaderTxt);
const char* fsOutName; const char* fsOutName;
if (shaderCaps->mustDeclareFragmentShaderOutput()) { if (shaderCaps->mustDeclareFragmentShaderOutput()) {

View File

@ -95,19 +95,28 @@ GrAAType GrChooseAAType(GrAA, GrFSAAType, GrAllowMixedSamples, const GrCaps&);
enum GrSLType { enum GrSLType {
kVoid_GrSLType, kVoid_GrSLType,
kBool_GrSLType, kBool_GrSLType,
kShort_GrSLType,
kUShort_GrSLType,
kHighFloat_GrSLType,
kHighFloat2_GrSLType,
kHighFloat3_GrSLType,
kHighFloat4_GrSLType,
kHighFloat2x2_GrSLType,
kHighFloat3x3_GrSLType,
kHighFloat4x4_GrSLType,
kHalf_GrSLType,
kHalf2_GrSLType,
kHalf3_GrSLType,
kHalf4_GrSLType,
kHalf2x2_GrSLType,
kHalf3x3_GrSLType,
kHalf4x4_GrSLType,
kInt_GrSLType, kInt_GrSLType,
kInt2_GrSLType,
kInt3_GrSLType,
kInt4_GrSLType,
kUint_GrSLType, kUint_GrSLType,
kFloat_GrSLType, kUint2_GrSLType,
kVec2f_GrSLType,
kVec3f_GrSLType,
kVec4f_GrSLType,
kVec2us_GrSLType,
kVec2i_GrSLType,
kVec3i_GrSLType,
kVec4i_GrSLType,
kMat22f_GrSLType,
kMat33f_GrSLType,
kMat44f_GrSLType,
kTexture2DSampler_GrSLType, kTexture2DSampler_GrSLType,
kITexture2DSampler_GrSLType, kITexture2DSampler_GrSLType,
kTextureExternalSampler_GrSLType, kTextureExternalSampler_GrSLType,
@ -161,13 +170,20 @@ static const int kGrSLPrecisionCount = kLast_GrSLPrecision + 1;
/** Is the shading language type float (including vectors/matrices)? */ /** Is the shading language type float (including vectors/matrices)? */
static inline bool GrSLTypeIsFloatType(GrSLType type) { static inline bool GrSLTypeIsFloatType(GrSLType type) {
switch (type) { switch (type) {
case kFloat_GrSLType: case kHighFloat_GrSLType:
case kVec2f_GrSLType: case kHighFloat2_GrSLType:
case kVec3f_GrSLType: case kHighFloat3_GrSLType:
case kVec4f_GrSLType: case kHighFloat4_GrSLType:
case kMat22f_GrSLType: case kHighFloat2x2_GrSLType:
case kMat33f_GrSLType: case kHighFloat3x3_GrSLType:
case kMat44f_GrSLType: case kHighFloat4x4_GrSLType:
case kHalf_GrSLType:
case kHalf2_GrSLType:
case kHalf3_GrSLType:
case kHalf4_GrSLType:
case kHalf2x2_GrSLType:
case kHalf3x3_GrSLType:
case kHalf4x4_GrSLType:
return true; return true;
case kVoid_GrSLType: case kVoid_GrSLType:
@ -177,12 +193,14 @@ static inline bool GrSLTypeIsFloatType(GrSLType type) {
case kTexture2DRectSampler_GrSLType: case kTexture2DRectSampler_GrSLType:
case kBufferSampler_GrSLType: case kBufferSampler_GrSLType:
case kBool_GrSLType: case kBool_GrSLType:
case kShort_GrSLType:
case kUShort_GrSLType:
case kInt_GrSLType: case kInt_GrSLType:
case kInt2_GrSLType:
case kInt3_GrSLType:
case kInt4_GrSLType:
case kUint_GrSLType: case kUint_GrSLType:
case kVec2us_GrSLType: case kUint2_GrSLType:
case kVec2i_GrSLType:
case kVec3i_GrSLType:
case kVec4i_GrSLType:
case kTexture2D_GrSLType: case kTexture2D_GrSLType:
case kSampler_GrSLType: case kSampler_GrSLType:
case kImageStorage2D_GrSLType: case kImageStorage2D_GrSLType:
@ -202,21 +220,30 @@ static inline bool GrSLTypeIs2DCombinedSamplerType(GrSLType type) {
return true; return true;
case kVoid_GrSLType: case kVoid_GrSLType:
case kFloat_GrSLType: case kHighFloat_GrSLType:
case kVec2f_GrSLType: case kHighFloat2_GrSLType:
case kVec3f_GrSLType: case kHighFloat3_GrSLType:
case kVec4f_GrSLType: case kHighFloat4_GrSLType:
case kVec2us_GrSLType: case kHighFloat2x2_GrSLType:
case kVec2i_GrSLType: case kHighFloat3x3_GrSLType:
case kVec3i_GrSLType: case kHighFloat4x4_GrSLType:
case kVec4i_GrSLType: case kHalf_GrSLType:
case kMat22f_GrSLType: case kHalf2_GrSLType:
case kMat33f_GrSLType: case kHalf3_GrSLType:
case kMat44f_GrSLType: case kHalf4_GrSLType:
case kBufferSampler_GrSLType: case kHalf2x2_GrSLType:
case kHalf3x3_GrSLType:
case kHalf4x4_GrSLType:
case kInt_GrSLType: case kInt_GrSLType:
case kInt2_GrSLType:
case kInt3_GrSLType:
case kInt4_GrSLType:
case kUint_GrSLType: case kUint_GrSLType:
case kUint2_GrSLType:
case kBufferSampler_GrSLType:
case kBool_GrSLType: case kBool_GrSLType:
case kShort_GrSLType:
case kUShort_GrSLType:
case kTexture2D_GrSLType: case kTexture2D_GrSLType:
case kSampler_GrSLType: case kSampler_GrSLType:
case kImageStorage2D_GrSLType: case kImageStorage2D_GrSLType:
@ -237,20 +264,29 @@ static inline bool GrSLTypeIsCombinedSamplerType(GrSLType type) {
return true; return true;
case kVoid_GrSLType: case kVoid_GrSLType:
case kFloat_GrSLType: case kHighFloat_GrSLType:
case kVec2f_GrSLType: case kHighFloat2_GrSLType:
case kVec3f_GrSLType: case kHighFloat3_GrSLType:
case kVec4f_GrSLType: case kHighFloat4_GrSLType:
case kVec2us_GrSLType: case kHighFloat2x2_GrSLType:
case kVec2i_GrSLType: case kHighFloat3x3_GrSLType:
case kVec3i_GrSLType: case kHighFloat4x4_GrSLType:
case kVec4i_GrSLType: case kHalf_GrSLType:
case kMat22f_GrSLType: case kHalf2_GrSLType:
case kMat33f_GrSLType: case kHalf3_GrSLType:
case kMat44f_GrSLType: case kHalf4_GrSLType:
case kHalf2x2_GrSLType:
case kHalf3x3_GrSLType:
case kHalf4x4_GrSLType:
case kInt_GrSLType: case kInt_GrSLType:
case kInt2_GrSLType:
case kInt3_GrSLType:
case kInt4_GrSLType:
case kUint_GrSLType: case kUint_GrSLType:
case kUint2_GrSLType:
case kBool_GrSLType: case kBool_GrSLType:
case kShort_GrSLType:
case kUShort_GrSLType:
case kTexture2D_GrSLType: case kTexture2D_GrSLType:
case kSampler_GrSLType: case kSampler_GrSLType:
case kImageStorage2D_GrSLType: case kImageStorage2D_GrSLType:
@ -268,20 +304,29 @@ static inline bool GrSLTypeIsImageStorage(GrSLType type) {
return true; return true;
case kVoid_GrSLType: case kVoid_GrSLType:
case kFloat_GrSLType: case kHighFloat_GrSLType:
case kVec2f_GrSLType: case kHighFloat2_GrSLType:
case kVec3f_GrSLType: case kHighFloat3_GrSLType:
case kVec4f_GrSLType: case kHighFloat4_GrSLType:
case kVec2us_GrSLType: case kHighFloat2x2_GrSLType:
case kVec2i_GrSLType: case kHighFloat3x3_GrSLType:
case kVec3i_GrSLType: case kHighFloat4x4_GrSLType:
case kVec4i_GrSLType: case kHalf_GrSLType:
case kMat22f_GrSLType: case kHalf2_GrSLType:
case kMat33f_GrSLType: case kHalf3_GrSLType:
case kMat44f_GrSLType: case kHalf4_GrSLType:
case kHalf2x2_GrSLType:
case kHalf3x3_GrSLType:
case kHalf4x4_GrSLType:
case kInt_GrSLType: case kInt_GrSLType:
case kInt2_GrSLType:
case kInt3_GrSLType:
case kInt4_GrSLType:
case kUint_GrSLType: case kUint_GrSLType:
case kUint2_GrSLType:
case kBool_GrSLType: case kBool_GrSLType:
case kShort_GrSLType:
case kUShort_GrSLType:
case kTexture2D_GrSLType: case kTexture2D_GrSLType:
case kSampler_GrSLType: case kSampler_GrSLType:
case kTexture2DSampler_GrSLType: case kTexture2DSampler_GrSLType:
@ -297,19 +342,73 @@ static inline bool GrSLTypeIsImageStorage(GrSLType type) {
static inline bool GrSLTypeAcceptsPrecision(GrSLType type) { static inline bool GrSLTypeAcceptsPrecision(GrSLType type) {
switch (type) { switch (type) {
case kTexture2DSampler_GrSLType:
case kITexture2DSampler_GrSLType:
case kTextureExternalSampler_GrSLType:
case kTexture2DRectSampler_GrSLType:
case kBufferSampler_GrSLType:
case kTexture2D_GrSLType:
case kSampler_GrSLType:
case kImageStorage2D_GrSLType:
case kIImageStorage2D_GrSLType:
return true;
case kVoid_GrSLType:
case kBool_GrSLType:
case kShort_GrSLType:
case kUShort_GrSLType:
case kHighFloat_GrSLType:
case kHighFloat2_GrSLType:
case kHighFloat3_GrSLType:
case kHighFloat4_GrSLType:
case kHighFloat2x2_GrSLType:
case kHighFloat3x3_GrSLType:
case kHighFloat4x4_GrSLType:
case kHalf_GrSLType:
case kHalf2_GrSLType:
case kHalf3_GrSLType:
case kHalf4_GrSLType:
case kHalf2x2_GrSLType:
case kHalf3x3_GrSLType:
case kHalf4x4_GrSLType:
case kInt_GrSLType: case kInt_GrSLType:
case kInt2_GrSLType:
case kInt3_GrSLType:
case kInt4_GrSLType:
case kUint_GrSLType: case kUint_GrSLType:
case kFloat_GrSLType: case kUint2_GrSLType:
case kVec2f_GrSLType: return false;
case kVec3f_GrSLType: }
case kVec4f_GrSLType: SK_ABORT("Unexpected type");
case kVec2us_GrSLType: return false;
case kVec2i_GrSLType: }
case kVec3i_GrSLType:
case kVec4i_GrSLType: // temporarily accepting (but ignoring) precision modifiers on the new types; this will be killed
case kMat22f_GrSLType: // in a future CL
case kMat33f_GrSLType: static inline bool GrSLTypeTemporarilyAcceptsPrecision(GrSLType type) {
case kMat44f_GrSLType: switch (type) {
case kShort_GrSLType:
case kUShort_GrSLType:
case kHighFloat_GrSLType:
case kHighFloat2_GrSLType:
case kHighFloat3_GrSLType:
case kHighFloat4_GrSLType:
case kHighFloat2x2_GrSLType:
case kHighFloat3x3_GrSLType:
case kHighFloat4x4_GrSLType:
case kHalf_GrSLType:
case kHalf2_GrSLType:
case kHalf3_GrSLType:
case kHalf4_GrSLType:
case kHalf2x2_GrSLType:
case kHalf3x3_GrSLType:
case kHalf4x4_GrSLType:
case kInt_GrSLType:
case kInt2_GrSLType:
case kInt3_GrSLType:
case kInt4_GrSLType:
case kUint_GrSLType:
case kUint2_GrSLType:
case kTexture2DSampler_GrSLType: case kTexture2DSampler_GrSLType:
case kITexture2DSampler_GrSLType: case kITexture2DSampler_GrSLType:
case kTextureExternalSampler_GrSLType: case kTextureExternalSampler_GrSLType:
@ -398,25 +497,25 @@ static inline size_t GrVertexAttribTypeSize(GrVertexAttribType type) {
static inline GrSLType GrVertexAttribTypeToSLType(GrVertexAttribType type) { static inline GrSLType GrVertexAttribTypeToSLType(GrVertexAttribType type) {
switch (type) { switch (type) {
case kVec2us_norm_GrVertexAttribType: // fall through case kVec2us_norm_GrVertexAttribType: // fall through
return kVec2f_GrSLType; return kHighFloat2_GrSLType;
case kVec2us_uint_GrVertexAttribType: case kVec2us_uint_GrVertexAttribType:
return kVec2us_GrSLType; return kUint2_GrSLType;
case kUByte_GrVertexAttribType: // fall through case kUByte_GrVertexAttribType: // fall through
case kFloat_GrVertexAttribType: case kFloat_GrVertexAttribType:
return kFloat_GrSLType; return kHighFloat_GrSLType;
case kVec2f_GrVertexAttribType: case kVec2f_GrVertexAttribType:
return kVec2f_GrSLType; return kHighFloat2_GrSLType;
case kVec3f_GrVertexAttribType: case kVec3f_GrVertexAttribType:
return kVec3f_GrSLType; return kHighFloat3_GrSLType;
case kVec4ub_GrVertexAttribType: case kVec4ub_GrVertexAttribType:
case kVec4f_GrVertexAttribType: case kVec4f_GrVertexAttribType:
return kVec4f_GrSLType; return kHighFloat4_GrSLType;
case kVec2i_GrVertexAttribType: case kVec2i_GrVertexAttribType:
return kVec2i_GrSLType; return kInt2_GrSLType;
case kVec3i_GrVertexAttribType: case kVec3i_GrVertexAttribType:
return kVec3i_GrSLType; return kInt3_GrSLType;
case kVec4i_GrVertexAttribType: case kVec4i_GrVertexAttribType:
return kVec4i_GrSLType; return kInt4_GrSLType;
case kInt_GrVertexAttribType: case kInt_GrVertexAttribType:
return kInt_GrSLType; return kInt_GrSLType;
case kUint_GrVertexAttribType: case kUint_GrVertexAttribType:

View File

@ -201,23 +201,21 @@ private:
void emitCode(EmitArgs& args) override { void emitCode(EmitArgs& args) override {
GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
fMatrixHandle = uniformHandler->addUniform(kFragment_GrShaderFlag, fMatrixHandle = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4x4_GrSLType,
kMat44f_GrSLType, kDefault_GrSLPrecision,
"ColorMatrix"); "ColorMatrix");
fVectorHandle = uniformHandler->addUniform(kFragment_GrShaderFlag, fVectorHandle = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType,
kVec4f_GrSLType, kDefault_GrSLPrecision,
"ColorMatrixVector"); "ColorMatrixVector");
if (nullptr == args.fInputColor) { if (nullptr == args.fInputColor) {
// could optimize this case, but we aren't for now. // could optimize this case, but we aren't for now.
args.fInputColor = "float4(1)"; args.fInputColor = "half4(1)";
} }
GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder; GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder;
// The max() is to guard against 0 / 0 during unpremul when the incoming color is // The max() is to guard against 0 / 0 during unpremul when the incoming color is
// transparent black. // transparent black.
fragBuilder->codeAppendf("\tfloat nonZeroAlpha = max(%s.a, 0.00001);\n", fragBuilder->codeAppendf("\thalf nonZeroAlpha = max(%s.a, 0.00001);\n",
args.fInputColor); args.fInputColor);
fragBuilder->codeAppendf("\t%s = %s * float4(%s.rgb / nonZeroAlpha, nonZeroAlpha) + " fragBuilder->codeAppendf("\t%s = %s * half4(%s.rgb / nonZeroAlpha, nonZeroAlpha) + "
"%s;\n", "%s;\n",
args.fOutputColor, args.fOutputColor,
uniformHandler->getUniformCStr(fMatrixHandle), uniformHandler->getUniformCStr(fMatrixHandle),

View File

@ -36,24 +36,25 @@ public:
(void)_outer; (void)_outer;
fColorSpaceHelper.emitCode(args.fUniformHandler, _outer.colorXform().get()); fColorSpaceHelper.emitCode(args.fUniformHandler, _outer.colorXform().get());
fInnerThresholdVar = args.fUniformHandler->addUniform( fInnerThresholdVar = args.fUniformHandler->addUniform(
kFragment_GrShaderFlag, kFloat_GrSLType, kDefault_GrSLPrecision, "innerThreshold"); kFragment_GrShaderFlag, kHalf_GrSLType, kDefault_GrSLPrecision, "innerThreshold");
fOuterThresholdVar = args.fUniformHandler->addUniform( fOuterThresholdVar = args.fUniformHandler->addUniform(
kFragment_GrShaderFlag, kFloat_GrSLType, kDefault_GrSLPrecision, "outerThreshold"); kFragment_GrShaderFlag, kHalf_GrSLType, kDefault_GrSLPrecision, "outerThreshold");
SkString sk_TransformedCoords2D_0 = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]); SkString sk_TransformedCoords2D_0 = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
SkString sk_TransformedCoords2D_1 = fragBuilder->ensureCoords2D(args.fTransformedCoords[1]); SkString sk_TransformedCoords2D_1 = fragBuilder->ensureCoords2D(args.fTransformedCoords[1]);
fragBuilder->codeAppendf( fragBuilder->codeAppendf(
"float4 _tmpVar1;float4 color = %stexture(%s, %s).%s%s;\nfloat4 mask_color = " "half4 _tmpVar1;half4 color = %stexture(%s, %s).%s%s;\nhalf4 mask_color = "
"texture(%s, %s).%s;\nif (mask_color.w < 0.5) {\n if (color.w > %s) {\n " "texture(%s, %s).%s;\nif (highfloat(mask_color.w) < 0.5) {\n if (color.w > %s) "
"float scale = %s / color.w;\n color.xyz *= scale;\n color.w = %s;\n " "{\n half scale = %s / color.w;\n color.xyz *= scale;\n "
" }\n} else if (color.w < %s) {\n float scale = %s / max(0.001, color.w);\n " "color.w = %s;\n }\n} else if (color.w < %s) {\n half scale = highfloat(%s) "
" color.xyz *= scale;\n color.w = %s;\n}\n%s = color;\n", "/ max(0.001, highfloat(color.w));\n color.xyz *= scale;\n color.w = "
"%s;\n}\n%s = color;\n",
fColorSpaceHelper.isValid() ? "(_tmpVar1 = " : "", fColorSpaceHelper.isValid() ? "(_tmpVar1 = " : "",
fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]).c_str(), fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]).c_str(),
sk_TransformedCoords2D_0.c_str(), sk_TransformedCoords2D_0.c_str(),
fragBuilder->getProgramBuilder()->samplerSwizzle(args.fTexSamplers[0]).c_str(), fragBuilder->getProgramBuilder()->samplerSwizzle(args.fTexSamplers[0]).c_str(),
fColorSpaceHelper.isValid() fColorSpaceHelper.isValid()
? SkStringPrintf(", float4(clamp((%s * float4(_tmpVar1.rgb, 1.0)).rgb, " ? SkStringPrintf(", half4(clamp((%s * half4(_tmpVar1.rgb, 1.0)).rgb, 0.0, "
"0.0, _tmpVar1.a), _tmpVar1.a))", "_tmpVar1.a), _tmpVar1.a))",
args.fUniformHandler->getUniformCStr( args.fUniformHandler->getUniformCStr(
fColorSpaceHelper.gamutXformUniform())) fColorSpaceHelper.gamutXformUniform()))
.c_str() .c_str()

View File

@ -1,8 +1,8 @@
in uniform sampler2D image; in uniform sampler2D image;
in uniform colorSpaceXform colorXform; in uniform colorSpaceXform colorXform;
in uniform sampler2D mask; in uniform sampler2D mask;
in uniform float innerThreshold; in uniform half innerThreshold;
in uniform float outerThreshold; in uniform half outerThreshold;
@class { @class {
inline OptimizationFlags optFlags(float outerThreshold); inline OptimizationFlags optFlags(float outerThreshold);
@ -49,16 +49,16 @@ in uniform float outerThreshold;
} }
void main() { void main() {
float4 color = texture(image, sk_TransformedCoords2D[0], colorXform); half4 color = texture(image, sk_TransformedCoords2D[0], colorXform);
float4 mask_color = texture(mask, sk_TransformedCoords2D[1]); half4 mask_color = texture(mask, sk_TransformedCoords2D[1]);
if (mask_color.a < 0.5) { if (mask_color.a < 0.5) {
if (color.a > outerThreshold) { if (color.a > outerThreshold) {
float scale = outerThreshold / color.a; half scale = outerThreshold / color.a;
color.rgb *= scale; color.rgb *= scale;
color.a = outerThreshold; color.a = outerThreshold;
} }
} else if (color.a < innerThreshold) { } else if (color.a < innerThreshold) {
float scale = innerThreshold / max(0.001, color.a); half scale = innerThreshold / max(0.001, color.a);
color.rgb *= scale; color.rgb *= scale;
color.a = innerThreshold; color.a = innerThreshold;
} }

View File

@ -263,19 +263,20 @@ public:
const GrCircleBlurFragmentProcessor& _outer = const GrCircleBlurFragmentProcessor& _outer =
args.fFp.cast<GrCircleBlurFragmentProcessor>(); args.fFp.cast<GrCircleBlurFragmentProcessor>();
(void)_outer; (void)_outer;
fCircleDataVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kVec4f_GrSLType, fCircleDataVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType,
kDefault_GrSLPrecision, "circleData"); kDefault_GrSLPrecision, "circleData");
fragBuilder->codeAppendf( fragBuilder->codeAppendf(
"float2 vec = float2((sk_FragCoord.x - %s.x) * %s.w, (sk_FragCoord.y - %s.y) * " "half2 vec = half2(half((sk_FragCoord.x - highfloat(%s.x)) * highfloat(%s.w)), "
"%s.w);\nfloat dist = length(vec) + (0.5 - %s.z) * %s.w;\n%s = %s * texture(%s, " "half((sk_FragCoord.y - highfloat(%s.y)) * highfloat(%s.w)));\nhalf dist = "
"float2(dist, 0.5)).%s.w;\n", "highfloat(length(vec)) + (0.5 - highfloat(%s.z)) * highfloat(%s.w);\n%s = %s * "
"texture(%s, highfloat2(half2(dist, 0.5))).%s.w;\n",
args.fUniformHandler->getUniformCStr(fCircleDataVar), args.fUniformHandler->getUniformCStr(fCircleDataVar),
args.fUniformHandler->getUniformCStr(fCircleDataVar), args.fUniformHandler->getUniformCStr(fCircleDataVar),
args.fUniformHandler->getUniformCStr(fCircleDataVar), args.fUniformHandler->getUniformCStr(fCircleDataVar),
args.fUniformHandler->getUniformCStr(fCircleDataVar), args.fUniformHandler->getUniformCStr(fCircleDataVar),
args.fUniformHandler->getUniformCStr(fCircleDataVar), args.fUniformHandler->getUniformCStr(fCircleDataVar),
args.fUniformHandler->getUniformCStr(fCircleDataVar), args.fOutputColor, args.fUniformHandler->getUniformCStr(fCircleDataVar), args.fOutputColor,
args.fInputColor ? args.fInputColor : "float4(1)", args.fInputColor ? args.fInputColor : "half4(1)",
fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]).c_str(), fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]).c_str(),
fragBuilder->getProgramBuilder()->samplerSwizzle(args.fTexSamplers[0]).c_str()); fragBuilder->getProgramBuilder()->samplerSwizzle(args.fTexSamplers[0]).c_str());
} }

View File

@ -1,13 +1,13 @@
in float4 circleRect; in half4 circleRect;
in float textureRadius; in half textureRadius;
in float solidRadius; in half solidRadius;
in uniform sampler2D blurProfileSampler; in uniform sampler2D blurProfileSampler;
// The data is formatted as: // The data is formatted as:
// x, y - the center of the circle // x, y - the center of the circle
// z - inner radius that should map to 0th entry in the texture. // z - inner radius that should map to 0th entry in the texture.
// w - the inverse of the distance over which the texture is stretched. // w - the inverse of the distance over which the texture is stretched.
uniform float4 circleData; uniform half4 circleData;
@optimizationFlags { @optimizationFlags {
kCompatibleWithCoverageAsAlpha_OptimizationFlag kCompatibleWithCoverageAsAlpha_OptimizationFlag
@ -273,10 +273,10 @@ uniform float4 circleData;
void main() { void main() {
// We just want to compute "(length(vec) - circleData.z + 0.5) * circleData.w" but need to // We just want to compute "(length(vec) - circleData.z + 0.5) * circleData.w" but need to
// rearrange for precision. // rearrange for precision.
float2 vec = float2((sk_FragCoord.x - circleData.x) * circleData.w, half2 vec = half2((sk_FragCoord.x - circleData.x) * circleData.w,
(sk_FragCoord.y - circleData.y) * circleData.w); (sk_FragCoord.y - circleData.y) * circleData.w);
float dist = length(vec) + (0.5 - circleData.z) * circleData.w; half dist = length(vec) + (0.5 - circleData.z) * circleData.w;
sk_OutColor = sk_InColor * texture(blurProfileSampler, float2(dist, 0.5)).a; sk_OutColor = sk_InColor * texture(blurProfileSampler, half2(dist, 0.5)).a;
} }
@test(testData) { @test(testData) {

View File

@ -302,18 +302,18 @@ private:
SkString dstColor("dstColor"); SkString dstColor("dstColor");
this->emitChild(0, &dstColor, args); this->emitChild(0, &dstColor, args);
fKUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kVec4f_GrSLType, fKUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType,
kDefault_GrSLPrecision, "k"); "k");
const char* kUni = args.fUniformHandler->getUniformCStr(fKUni); const char* kUni = args.fUniformHandler->getUniformCStr(fKUni);
// We don't try to optimize for this case at all // We don't try to optimize for this case at all
if (!args.fInputColor) { if (!args.fInputColor) {
fragBuilder->codeAppend("const float4 src = float4(1);"); fragBuilder->codeAppend("const half4 src = half4(1);");
} else { } else {
fragBuilder->codeAppendf("float4 src = %s;", args.fInputColor); fragBuilder->codeAppendf("half4 src = %s;", args.fInputColor);
} }
fragBuilder->codeAppendf("float4 dst = %s;", dstColor.c_str()); fragBuilder->codeAppendf("half4 dst = %s;", dstColor.c_str());
fragBuilder->codeAppendf("%s = %s.x * src * dst + %s.y * src + %s.z * dst + %s.w;", fragBuilder->codeAppendf("%s = %s.x * src * dst + %s.y * src + %s.z * dst + %s.w;",
args.fOutputColor, kUni, kUni, kUni, kUni); args.fOutputColor, kUni, kUni, kUni, kUni);
fragBuilder->codeAppendf("%s = clamp(%s, 0.0, 1.0);\n", args.fOutputColor, fragBuilder->codeAppendf("%s = clamp(%s, 0.0, 1.0);\n", args.fOutputColor,

View File

@ -862,12 +862,12 @@ void OutputRectBlurProfileLookup(GrGLSLFPFragmentBuilder* fragBuilder,
const char *profileSize, const char *loc, const char *profileSize, const char *loc,
const char *blurred_width, const char *blurred_width,
const char *sharp_width) { const char *sharp_width) {
fragBuilder->codeAppendf("float %s;", output); fragBuilder->codeAppendf("half %s;", output);
fragBuilder->codeAppendf("{"); fragBuilder->codeAppendf("{");
fragBuilder->codeAppendf("float coord = ((abs(%s - 0.5 * %s) - 0.5 * %s)) / %s;", fragBuilder->codeAppendf("half coord = ((abs(%s - 0.5 * %s) - 0.5 * %s)) / %s;",
loc, blurred_width, sharp_width, profileSize); loc, blurred_width, sharp_width, profileSize);
fragBuilder->codeAppendf("%s = ", output); fragBuilder->codeAppendf("%s = ", output);
fragBuilder->appendTextureLookup(sampler, "float2(coord,0.5)"); fragBuilder->appendTextureLookup(sampler, "half2(coord,0.5)");
fragBuilder->codeAppend(".a;"); fragBuilder->codeAppend(".a;");
fragBuilder->codeAppendf("}"); fragBuilder->codeAppendf("}");
} }
@ -889,49 +889,41 @@ void GrGLRectBlurEffect::emitCode(EmitArgs& args) {
const char *rectName; const char *rectName;
const char *profileSizeName; const char *profileSizeName;
SkString precisionString; const char* floatType = rbe.precision() == kHigh_GrSLPrecision ? "highfloat" : "half";
if (args.fShaderCaps->usesPrecisionModifiers()) {
precisionString.printf("%s ", GrGLSLPrecisionString(rbe.precision()));
}
fProxyRectUniform = uniformHandler->addUniform(kFragment_GrShaderFlag, fProxyRectUniform = uniformHandler->addUniform(kFragment_GrShaderFlag,
kVec4f_GrSLType, rbe.precision() == kHigh_GrSLPrecision ?
rbe.precision(), kHighFloat4_GrSLType : kHalf4_GrSLType,
"proxyRect", "proxyRect",
&rectName); &rectName);
fProfileSizeUniform = uniformHandler->addUniform(kFragment_GrShaderFlag, fProfileSizeUniform = uniformHandler->addUniform(kFragment_GrShaderFlag,
kFloat_GrSLType, kHalf_GrSLType,
kDefault_GrSLPrecision,
"profileSize", "profileSize",
&profileSizeName); &profileSizeName);
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
if (args.fInputColor) { if (args.fInputColor) {
fragBuilder->codeAppendf("float4 src=%s;", args.fInputColor); fragBuilder->codeAppendf("half4 src=%s;", args.fInputColor);
} else { } else {
fragBuilder->codeAppendf("float4 src=float4(1);"); fragBuilder->codeAppendf("half4 src=half4(1);");
} }
fragBuilder->codeAppendf("%s float2 translatedPos = sk_FragCoord.xy - %s.xy;", fragBuilder->codeAppendf("%s2 translatedPos = sk_FragCoord.xy - %s.xy;", floatType, rectName);
precisionString.c_str(), rectName); fragBuilder->codeAppendf("%s width = %s.z - %s.x;", floatType, rectName, rectName);
fragBuilder->codeAppendf("%s float width = %s.z - %s.x;", precisionString.c_str(), rectName, fragBuilder->codeAppendf("%s height = %s.w - %s.y;", floatType, rectName, rectName);
rectName);
fragBuilder->codeAppendf("%s float height = %s.w - %s.y;", precisionString.c_str(), rectName,
rectName);
fragBuilder->codeAppendf("%s float2 smallDims = float2(width - %s, height - %s);", fragBuilder->codeAppendf("%s2 smallDims = half2(width - %s, height - %s);", floatType,
precisionString.c_str(), profileSizeName, profileSizeName); profileSizeName, profileSizeName);
fragBuilder->codeAppendf("%s float center = 2.0 * floor(%s/2.0 + .25) - 1.0;", fragBuilder->codeAppendf("%s center = 2.0 * floor(%s/2.0 + .25) - 1.0;", floatType,
precisionString.c_str(), profileSizeName); profileSizeName);
fragBuilder->codeAppendf("%s float2 wh = smallDims - float2(center,center);", fragBuilder->codeAppendf("%s2 wh = smallDims - half2(center,center);", floatType);
precisionString.c_str());
OutputRectBlurProfileLookup(fragBuilder, args.fTexSamplers[0], "horiz_lookup", profileSizeName, OutputRectBlurProfileLookup(fragBuilder, args.fTexSamplers[0], "horiz_lookup", profileSizeName,
"translatedPos.x", "width", "wh.x"); "translatedPos.x", "width", "wh.x");
OutputRectBlurProfileLookup(fragBuilder, args.fTexSamplers[0], "vert_lookup", profileSizeName, OutputRectBlurProfileLookup(fragBuilder, args.fTexSamplers[0], "vert_lookup", profileSizeName,
"translatedPos.y", "height", "wh.y"); "translatedPos.y", "height", "wh.y");
fragBuilder->codeAppendf("float final = horiz_lookup * vert_lookup;"); fragBuilder->codeAppendf("half final = horiz_lookup * vert_lookup;");
fragBuilder->codeAppendf("%s = src * final;", args.fOutputColor); fragBuilder->codeAppendf("%s = src * final;", args.fOutputColor);
} }
@ -1277,18 +1269,15 @@ void GrGLRRectBlurEffect::emitCode(EmitArgs& args) {
// components x, y, z, and w, respectively. // components x, y, z, and w, respectively.
fProxyRectUniform = uniformHandler->addUniform(kFragment_GrShaderFlag, fProxyRectUniform = uniformHandler->addUniform(kFragment_GrShaderFlag,
kVec4f_GrSLType, kHalf4_GrSLType,
kDefault_GrSLPrecision,
"proxyRect", "proxyRect",
&rectName); &rectName);
fCornerRadiusUniform = uniformHandler->addUniform(kFragment_GrShaderFlag, fCornerRadiusUniform = uniformHandler->addUniform(kFragment_GrShaderFlag,
kFloat_GrSLType, kHalf_GrSLType,
kDefault_GrSLPrecision,
"cornerRadius", "cornerRadius",
&cornerRadiusName); &cornerRadiusName);
fBlurRadiusUniform = uniformHandler->addUniform(kFragment_GrShaderFlag, fBlurRadiusUniform = uniformHandler->addUniform(kFragment_GrShaderFlag,
kFloat_GrSLType, kHalf_GrSLType,
kDefault_GrSLPrecision,
"blurRadius", "blurRadius",
&blurRadiusName); &blurRadiusName);
@ -1296,10 +1285,10 @@ void GrGLRRectBlurEffect::emitCode(EmitArgs& args) {
// warp the fragment position to the appropriate part of the 9patch blur texture // warp the fragment position to the appropriate part of the 9patch blur texture
fragBuilder->codeAppendf("float2 rectCenter = (%s.xy + %s.zw)/2.0;", rectName, rectName); fragBuilder->codeAppendf("half2 rectCenter = (%s.xy + %s.zw)/2.0;", rectName, rectName);
fragBuilder->codeAppendf("float2 translatedFragPos = sk_FragCoord.xy - %s.xy;", rectName); fragBuilder->codeAppendf("half2 translatedFragPos = sk_FragCoord.xy - %s.xy;", rectName);
fragBuilder->codeAppendf("float threshold = %s + 2.0*%s;", cornerRadiusName, blurRadiusName); fragBuilder->codeAppendf("half threshold = %s + 2.0*%s;", cornerRadiusName, blurRadiusName);
fragBuilder->codeAppendf("float2 middle = %s.zw - %s.xy - 2.0*threshold;", rectName, rectName); fragBuilder->codeAppendf("half2 middle = %s.zw - %s.xy - 2.0*threshold;", rectName, rectName);
fragBuilder->codeAppendf( fragBuilder->codeAppendf(
"if (translatedFragPos.x >= threshold && translatedFragPos.x < (middle.x+threshold)) {"); "if (translatedFragPos.x >= threshold && translatedFragPos.x < (middle.x+threshold)) {");
@ -1315,8 +1304,8 @@ void GrGLRRectBlurEffect::emitCode(EmitArgs& args) {
fragBuilder->codeAppendf("translatedFragPos.y -= middle.y - 1.0;"); fragBuilder->codeAppendf("translatedFragPos.y -= middle.y - 1.0;");
fragBuilder->codeAppendf("}"); fragBuilder->codeAppendf("}");
fragBuilder->codeAppendf("float2 proxyDims = float2(2.0*threshold+1.0);"); fragBuilder->codeAppendf("half2 proxyDims = half2(2.0*threshold+1.0);");
fragBuilder->codeAppendf("float2 texCoord = translatedFragPos / proxyDims;"); fragBuilder->codeAppendf("half2 texCoord = translatedFragPos / proxyDims;");
fragBuilder->codeAppendf("%s = ", args.fOutputColor); fragBuilder->codeAppendf("%s = ", args.fOutputColor);
fragBuilder->appendTextureLookupAndModulate(args.fInputColor, args.fTexSamplers[0], "texCoord"); fragBuilder->appendTextureLookupAndModulate(args.fInputColor, args.fTexSamplers[0], "texCoord");

View File

@ -552,8 +552,7 @@ void GrGLDisplacementMapEffect::emitCode(EmitArgs& args) {
const GrDisplacementMapEffect& displacementMap = args.fFp.cast<GrDisplacementMapEffect>(); const GrDisplacementMapEffect& displacementMap = args.fFp.cast<GrDisplacementMapEffect>();
const GrTextureDomain& domain = displacementMap.domain(); const GrTextureDomain& domain = displacementMap.domain();
fScaleUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, fScaleUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType, "Scale");
kVec2f_GrSLType, kDefault_GrSLPrecision, "Scale");
const char* scaleUni = args.fUniformHandler->getUniformCStr(fScaleUni); const char* scaleUni = args.fUniformHandler->getUniformCStr(fScaleUni);
const char* dColor = "dColor"; const char* dColor = "dColor";
const char* cCoords = "cCoords"; const char* cCoords = "cCoords";
@ -564,17 +563,17 @@ void GrGLDisplacementMapEffect::emitCode(EmitArgs& args) {
fColorSpaceHelper.emitCode(args.fUniformHandler, displacementMap.colorSpaceXform()); fColorSpaceHelper.emitCode(args.fUniformHandler, displacementMap.colorSpaceXform());
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
fragBuilder->codeAppendf("\t\tfloat4 %s = ", dColor); fragBuilder->codeAppendf("\t\thalf4 %s = ", dColor);
fragBuilder->appendTextureLookup(args.fTexSamplers[0], args.fTransformedCoords[0].c_str(), fragBuilder->appendTextureLookup(args.fTexSamplers[0], args.fTransformedCoords[0].c_str(),
args.fTransformedCoords[0].getType()); args.fTransformedCoords[0].getType());
fragBuilder->codeAppend(";\n"); fragBuilder->codeAppend(";\n");
// Unpremultiply the displacement // Unpremultiply the displacement
fragBuilder->codeAppendf( fragBuilder->codeAppendf(
"\t\t%s.rgb = (%s.a < %s) ? float3(0.0) : clamp(%s.rgb / %s.a, 0.0, 1.0);", "\t\t%s.rgb = (%s.a < %s) ? half3(0.0) : clamp(%s.rgb / %s.a, 0.0, 1.0);",
dColor, dColor, nearZero, dColor, dColor); dColor, dColor, nearZero, dColor, dColor);
SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[1]); SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[1]);
fragBuilder->codeAppendf("\t\tfloat2 %s = %s + %s*(%s.", fragBuilder->codeAppendf("\t\thighfloat2 %s = %s + %s*(%s.",
cCoords, coords2D.c_str(), scaleUni, dColor); cCoords, coords2D.c_str(), scaleUni, dColor);
switch (displacementMap.xChannelSelector()) { switch (displacementMap.xChannelSelector()) {
@ -612,7 +611,7 @@ void GrGLDisplacementMapEffect::emitCode(EmitArgs& args) {
default: default:
SkDEBUGFAIL("Unknown Y channel selector"); SkDEBUGFAIL("Unknown Y channel selector");
} }
fragBuilder->codeAppend("-float2(0.5));\t\t"); fragBuilder->codeAppend("-half2(0.5));\t\t");
fGLDomain.sampleTexture(fragBuilder, fGLDomain.sampleTexture(fragBuilder,
args.fUniformHandler, args.fUniformHandler,

View File

@ -247,47 +247,46 @@ void GLHighContrastFilterEffect::GenKey(
void GLHighContrastFilterEffect::emitCode(EmitArgs& args) { void GLHighContrastFilterEffect::emitCode(EmitArgs& args) {
const char* contrast; const char* contrast;
fContrastUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, fContrastUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType,
kFloat_GrSLType, kDefault_GrSLPrecision,
"contrast", &contrast); "contrast", &contrast);
if (nullptr == args.fInputColor) { if (nullptr == args.fInputColor) {
args.fInputColor = "float4(1)"; args.fInputColor = "half4(1)";
} }
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
fragBuilder->codeAppendf("float4 color = %s;", args.fInputColor); fragBuilder->codeAppendf("half4 color = %s;", args.fInputColor);
// Unpremultiply. The max() is to guard against 0 / 0. // Unpremultiply. The max() is to guard against 0 / 0.
fragBuilder->codeAppendf("float nonZeroAlpha = max(color.a, 0.00001);"); fragBuilder->codeAppendf("half nonZeroAlpha = max(color.a, 0.00001);");
fragBuilder->codeAppendf("color = float4(color.rgb / nonZeroAlpha, nonZeroAlpha);"); fragBuilder->codeAppendf("color = half4(color.rgb / nonZeroAlpha, nonZeroAlpha);");
// Grayscale. // Grayscale.
if (fConfig.fGrayscale) { if (fConfig.fGrayscale) {
fragBuilder->codeAppendf("float luma = dot(color, float4(%f, %f, %f, 0));", fragBuilder->codeAppendf("half luma = dot(color, half4(%f, %f, %f, 0));",
SK_LUM_COEFF_R, SK_LUM_COEFF_G, SK_LUM_COEFF_B); SK_LUM_COEFF_R, SK_LUM_COEFF_G, SK_LUM_COEFF_B);
fragBuilder->codeAppendf("color = float4(luma, luma, luma, 0);"); fragBuilder->codeAppendf("color = half4(luma, luma, luma, 0);");
} }
if (fConfig.fInvertStyle == InvertStyle::kInvertBrightness) { if (fConfig.fInvertStyle == InvertStyle::kInvertBrightness) {
fragBuilder->codeAppendf("color = float4(1, 1, 1, 1) - color;"); fragBuilder->codeAppendf("color = half4(1, 1, 1, 1) - color;");
} }
if (fConfig.fInvertStyle == InvertStyle::kInvertLightness) { if (fConfig.fInvertStyle == InvertStyle::kInvertLightness) {
// Convert from RGB to HSL. // Convert from RGB to HSL.
fragBuilder->codeAppendf("float fmax = max(color.r, max(color.g, color.b));"); fragBuilder->codeAppendf("half fmax = max(color.r, max(color.g, color.b));");
fragBuilder->codeAppendf("float fmin = min(color.r, min(color.g, color.b));"); fragBuilder->codeAppendf("half fmin = min(color.r, min(color.g, color.b));");
fragBuilder->codeAppendf("float l = (fmax + fmin) / 2;"); fragBuilder->codeAppendf("half l = (fmax + fmin) / 2;");
fragBuilder->codeAppendf("float h;"); fragBuilder->codeAppendf("half h;");
fragBuilder->codeAppendf("float s;"); fragBuilder->codeAppendf("half s;");
fragBuilder->codeAppendf("if (fmax == fmin) {"); fragBuilder->codeAppendf("if (fmax == fmin) {");
fragBuilder->codeAppendf(" h = 0;"); fragBuilder->codeAppendf(" h = 0;");
fragBuilder->codeAppendf(" s = 0;"); fragBuilder->codeAppendf(" s = 0;");
fragBuilder->codeAppendf("} else {"); fragBuilder->codeAppendf("} else {");
fragBuilder->codeAppendf(" float d = fmax - fmin;"); fragBuilder->codeAppendf(" half d = fmax - fmin;");
fragBuilder->codeAppendf(" s = l > 0.5 ?"); fragBuilder->codeAppendf(" s = l > 0.5 ?");
fragBuilder->codeAppendf(" d / (2 - fmax - fmin) :"); fragBuilder->codeAppendf(" d / (2 - fmax - fmin) :");
fragBuilder->codeAppendf(" d / (fmax + fmin);"); fragBuilder->codeAppendf(" d / (fmax + fmin);");
@ -305,11 +304,11 @@ void GLHighContrastFilterEffect::emitCode(EmitArgs& args) {
// Convert back from HSL to RGB. // Convert back from HSL to RGB.
SkString hue2rgbFuncName; SkString hue2rgbFuncName;
static const GrShaderVar gHue2rgbArgs[] = { static const GrShaderVar gHue2rgbArgs[] = {
GrShaderVar("p", kFloat_GrSLType), GrShaderVar("p", kHalf_GrSLType),
GrShaderVar("q", kFloat_GrSLType), GrShaderVar("q", kHalf_GrSLType),
GrShaderVar("t", kFloat_GrSLType), GrShaderVar("t", kHalf_GrSLType),
}; };
fragBuilder->emitFunction(kFloat_GrSLType, fragBuilder->emitFunction(kHalf_GrSLType,
"hue2rgb", "hue2rgb",
SK_ARRAY_COUNT(gHue2rgbArgs), SK_ARRAY_COUNT(gHue2rgbArgs),
gHue2rgbArgs, gHue2rgbArgs,
@ -326,10 +325,10 @@ void GLHighContrastFilterEffect::emitCode(EmitArgs& args) {
"return p;", "return p;",
&hue2rgbFuncName); &hue2rgbFuncName);
fragBuilder->codeAppendf("if (s == 0) {"); fragBuilder->codeAppendf("if (s == 0) {");
fragBuilder->codeAppendf(" color = float4(l, l, l, 0);"); fragBuilder->codeAppendf(" color = half4(l, l, l, 0);");
fragBuilder->codeAppendf("} else {"); fragBuilder->codeAppendf("} else {");
fragBuilder->codeAppendf(" float q = l < 0.5 ? l * (1 + s) : l + s - l * s;"); fragBuilder->codeAppendf(" half q = l < 0.5 ? l * (1 + s) : l + s - l * s;");
fragBuilder->codeAppendf(" float p = 2 * l - q;"); fragBuilder->codeAppendf(" half p = 2 * l - q;");
fragBuilder->codeAppendf(" color.r = %s(p, q, h + 1/3.);", hue2rgbFuncName.c_str()); fragBuilder->codeAppendf(" color.r = %s(p, q, h + 1/3.);", hue2rgbFuncName.c_str());
fragBuilder->codeAppendf(" color.g = %s(p, q, h);", hue2rgbFuncName.c_str()); fragBuilder->codeAppendf(" color.g = %s(p, q, h);", hue2rgbFuncName.c_str());
fragBuilder->codeAppendf(" color.b = %s(p, q, h - 1/3.);", hue2rgbFuncName.c_str()); fragBuilder->codeAppendf(" color.b = %s(p, q, h - 1/3.);", hue2rgbFuncName.c_str());
@ -338,8 +337,8 @@ void GLHighContrastFilterEffect::emitCode(EmitArgs& args) {
// Contrast. // Contrast.
fragBuilder->codeAppendf("if (%s != 0) {", contrast); fragBuilder->codeAppendf("if (%s != 0) {", contrast);
fragBuilder->codeAppendf(" float m = (1 + %s) / (1 - %s);", contrast, contrast); fragBuilder->codeAppendf(" half m = (1 + %s) / (1 - %s);", contrast, contrast);
fragBuilder->codeAppendf(" float off = (-0.5 * m + 0.5);"); fragBuilder->codeAppendf(" half off = (-0.5 * m + 0.5);");
fragBuilder->codeAppendf(" color = m * color + off;"); fragBuilder->codeAppendf(" color = m * color + off;");
fragBuilder->codeAppendf("}"); fragBuilder->codeAppendf("}");

View File

@ -724,7 +724,7 @@ public:
/** /**
* This is called by GrGLLightingEffect::emitCode() before either of the two virtual functions * 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. * below. It adds a half3 uniform visible in the FS that represents the constant light color.
*/ */
void emitLightColorUniform(GrGLSLUniformHandler*); void emitLightColorUniform(GrGLSLUniformHandler*);
@ -1827,63 +1827,61 @@ void GrGLLightingEffect::emitCode(EmitArgs& args) {
GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
fImageIncrementUni = uniformHandler->addUniform(kFragment_GrShaderFlag, fImageIncrementUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
kVec2f_GrSLType, kDefault_GrSLPrecision, kHalf2_GrSLType, "ImageIncrement");
"ImageIncrement");
fSurfaceScaleUni = uniformHandler->addUniform(kFragment_GrShaderFlag, fSurfaceScaleUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
kFloat_GrSLType, kDefault_GrSLPrecision, kHalf_GrSLType, "SurfaceScale");
"SurfaceScale");
fLight->emitLightColorUniform(uniformHandler); fLight->emitLightColorUniform(uniformHandler);
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
SkString lightFunc; SkString lightFunc;
this->emitLightFunc(uniformHandler, fragBuilder, &lightFunc); this->emitLightFunc(uniformHandler, fragBuilder, &lightFunc);
static const GrShaderVar gSobelArgs[] = { static const GrShaderVar gSobelArgs[] = {
GrShaderVar("a", kFloat_GrSLType), GrShaderVar("a", kHalf_GrSLType),
GrShaderVar("b", kFloat_GrSLType), GrShaderVar("b", kHalf_GrSLType),
GrShaderVar("c", kFloat_GrSLType), GrShaderVar("c", kHalf_GrSLType),
GrShaderVar("d", kFloat_GrSLType), GrShaderVar("d", kHalf_GrSLType),
GrShaderVar("e", kFloat_GrSLType), GrShaderVar("e", kHalf_GrSLType),
GrShaderVar("f", kFloat_GrSLType), GrShaderVar("f", kHalf_GrSLType),
GrShaderVar("scale", kFloat_GrSLType), GrShaderVar("scale", kHalf_GrSLType),
}; };
SkString sobelFuncName; SkString sobelFuncName;
SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]); SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
fragBuilder->emitFunction(kFloat_GrSLType, fragBuilder->emitFunction(kHalf_GrSLType,
"sobel", "sobel",
SK_ARRAY_COUNT(gSobelArgs), SK_ARRAY_COUNT(gSobelArgs),
gSobelArgs, gSobelArgs,
"\treturn (-a + b - 2.0 * c + 2.0 * d -e + f) * scale;\n", "\treturn (-a + b - 2.0 * c + 2.0 * d -e + f) * scale;\n",
&sobelFuncName); &sobelFuncName);
static const GrShaderVar gPointToNormalArgs[] = { static const GrShaderVar gPointToNormalArgs[] = {
GrShaderVar("x", kFloat_GrSLType), GrShaderVar("x", kHalf_GrSLType),
GrShaderVar("y", kFloat_GrSLType), GrShaderVar("y", kHalf_GrSLType),
GrShaderVar("scale", kFloat_GrSLType), GrShaderVar("scale", kHalf_GrSLType),
}; };
SkString pointToNormalName; SkString pointToNormalName;
fragBuilder->emitFunction(kVec3f_GrSLType, fragBuilder->emitFunction(kHalf3_GrSLType,
"pointToNormal", "pointToNormal",
SK_ARRAY_COUNT(gPointToNormalArgs), SK_ARRAY_COUNT(gPointToNormalArgs),
gPointToNormalArgs, gPointToNormalArgs,
"\treturn normalize(float3(-x * scale, -y * scale, 1));\n", "\treturn normalize(half3(-x * scale, -y * scale, 1));\n",
&pointToNormalName); &pointToNormalName);
static const GrShaderVar gInteriorNormalArgs[] = { static const GrShaderVar gInteriorNormalArgs[] = {
GrShaderVar("m", kFloat_GrSLType, 9), GrShaderVar("m", kHalf_GrSLType, 9),
GrShaderVar("surfaceScale", kFloat_GrSLType), GrShaderVar("surfaceScale", kHalf_GrSLType),
}; };
SkString normalBody = emitNormalFunc(le.boundaryMode(), SkString normalBody = emitNormalFunc(le.boundaryMode(),
pointToNormalName.c_str(), pointToNormalName.c_str(),
sobelFuncName.c_str()); sobelFuncName.c_str());
SkString normalName; SkString normalName;
fragBuilder->emitFunction(kVec3f_GrSLType, fragBuilder->emitFunction(kHalf3_GrSLType,
"normal", "normal",
SK_ARRAY_COUNT(gInteriorNormalArgs), SK_ARRAY_COUNT(gInteriorNormalArgs),
gInteriorNormalArgs, gInteriorNormalArgs,
normalBody.c_str(), normalBody.c_str(),
&normalName); &normalName);
fragBuilder->codeAppendf("\t\tfloat2 coord = %s;\n", coords2D.c_str()); fragBuilder->codeAppendf("\t\thighfloat2 coord = %s;\n", coords2D.c_str());
fragBuilder->codeAppend("\t\tfloat m[9];\n"); fragBuilder->codeAppend("\t\thalf m[9];\n");
const char* imgInc = uniformHandler->getUniformCStr(fImageIncrementUni); const char* imgInc = uniformHandler->getUniformCStr(fImageIncrementUni);
const char* surfScale = uniformHandler->getUniformCStr(fSurfaceScaleUni); const char* surfScale = uniformHandler->getUniformCStr(fSurfaceScaleUni);
@ -1892,10 +1890,10 @@ void GrGLLightingEffect::emitCode(EmitArgs& args) {
for (int dy = 1; dy >= -1; dy--) { for (int dy = 1; dy >= -1; dy--) {
for (int dx = -1; dx <= 1; dx++) { for (int dx = -1; dx <= 1; dx++) {
SkString texCoords; SkString texCoords;
texCoords.appendf("coord + float2(%d, %d) * %s", dx, dy, imgInc); texCoords.appendf("coord + half2(%d, %d) * %s", dx, dy, imgInc);
SkString temp; SkString temp;
temp.appendf("temp%d", index); temp.appendf("temp%d", index);
fragBuilder->codeAppendf("float4 %s;", temp.c_str()); fragBuilder->codeAppendf("half4 %s;", temp.c_str());
fDomain.sampleTexture(fragBuilder, fDomain.sampleTexture(fragBuilder,
args.fUniformHandler, args.fUniformHandler,
args.fShaderCaps, args.fShaderCaps,
@ -1907,7 +1905,7 @@ void GrGLLightingEffect::emitCode(EmitArgs& args) {
index++; index++;
} }
} }
fragBuilder->codeAppend("\t\tfloat3 surfaceToLight = "); fragBuilder->codeAppend("\t\thalf3 surfaceToLight = ");
SkString arg; SkString arg;
arg.appendf("%s * m[4]", surfScale); arg.appendf("%s * m[4]", surfScale);
fLight->emitSurfaceToLight(uniformHandler, fragBuilder, arg.c_str()); fLight->emitSurfaceToLight(uniformHandler, fragBuilder, arg.c_str());
@ -1953,19 +1951,17 @@ void GrGLDiffuseLightingEffect::emitLightFunc(GrGLSLUniformHandler* uniformHandl
GrGLSLFPFragmentBuilder* fragBuilder, GrGLSLFPFragmentBuilder* fragBuilder,
SkString* funcName) { SkString* funcName) {
const char* kd; const char* kd;
fKDUni = uniformHandler->addUniform(kFragment_GrShaderFlag, fKDUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType, "KD", &kd);
kFloat_GrSLType, kDefault_GrSLPrecision,
"KD", &kd);
static const GrShaderVar gLightArgs[] = { static const GrShaderVar gLightArgs[] = {
GrShaderVar("normal", kVec3f_GrSLType), GrShaderVar("normal", kHalf3_GrSLType),
GrShaderVar("surfaceToLight", kVec3f_GrSLType), GrShaderVar("surfaceToLight", kHalf3_GrSLType),
GrShaderVar("lightColor", kVec3f_GrSLType) GrShaderVar("lightColor", kHalf3_GrSLType)
}; };
SkString lightBody; SkString lightBody;
lightBody.appendf("\tfloat colorScale = %s * dot(normal, surfaceToLight);\n", kd); lightBody.appendf("\thalf colorScale = %s * dot(normal, surfaceToLight);\n", kd);
lightBody.appendf("\treturn float4(lightColor * clamp(colorScale, 0.0, 1.0), 1.0);\n"); lightBody.appendf("\treturn half4(lightColor * clamp(colorScale, 0.0, 1.0), 1.0);\n");
fragBuilder->emitFunction(kVec4f_GrSLType, fragBuilder->emitFunction(kHalf4_GrSLType,
"light", "light",
SK_ARRAY_COUNT(gLightArgs), SK_ARRAY_COUNT(gLightArgs),
gLightArgs, gLightArgs,
@ -2051,26 +2047,24 @@ void GrGLSpecularLightingEffect::emitLightFunc(GrGLSLUniformHandler* uniformHand
const char* ks; const char* ks;
const char* shininess; const char* shininess;
fKSUni = uniformHandler->addUniform(kFragment_GrShaderFlag, fKSUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType, "KS", &ks);
kFloat_GrSLType, kDefault_GrSLPrecision, "KS", &ks);
fShininessUni = uniformHandler->addUniform(kFragment_GrShaderFlag, fShininessUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
kFloat_GrSLType, kHalf_GrSLType,
kDefault_GrSLPrecision,
"Shininess", "Shininess",
&shininess); &shininess);
static const GrShaderVar gLightArgs[] = { static const GrShaderVar gLightArgs[] = {
GrShaderVar("normal", kVec3f_GrSLType), GrShaderVar("normal", kHalf3_GrSLType),
GrShaderVar("surfaceToLight", kVec3f_GrSLType), GrShaderVar("surfaceToLight", kHalf3_GrSLType),
GrShaderVar("lightColor", kVec3f_GrSLType) GrShaderVar("lightColor", kHalf3_GrSLType)
}; };
SkString lightBody; SkString lightBody;
lightBody.appendf("\tfloat3 halfDir = float3(normalize(surfaceToLight + float3(0, 0, 1)));\n"); lightBody.appendf("\thalf3 halfDir = half3(normalize(surfaceToLight + half3(0, 0, 1)));\n");
lightBody.appendf("\thighp float colorScale = %s * pow(dot(normal, halfDir), %s);\n", lightBody.appendf("\thighfloat colorScale = %s * pow(dot(normal, halfDir), %s);\n",
ks, shininess); ks, shininess);
lightBody.appendf("\tfloat3 color = lightColor * clamp(colorScale, 0.0, 1.0);\n"); lightBody.appendf("\thalf3 color = lightColor * clamp(colorScale, 0.0, 1.0);\n");
lightBody.appendf("\treturn float4(color, max(max(color.r, color.g), color.b));\n"); lightBody.appendf("\treturn half4(color, max(max(color.r, color.g), color.b));\n");
fragBuilder->emitFunction(kVec4f_GrSLType, fragBuilder->emitFunction(kHalf4_GrSLType,
"light", "light",
SK_ARRAY_COUNT(gLightArgs), SK_ARRAY_COUNT(gLightArgs),
gLightArgs, gLightArgs,
@ -2088,9 +2082,7 @@ void GrGLSpecularLightingEffect::onSetData(const GrGLSLProgramDataManager& pdman
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
void GrGLLight::emitLightColorUniform(GrGLSLUniformHandler* uniformHandler) { void GrGLLight::emitLightColorUniform(GrGLSLUniformHandler* uniformHandler) {
fColorUni = uniformHandler->addUniform(kFragment_GrShaderFlag, fColorUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf3_GrSLType, "LightColor");
kVec3f_GrSLType, kDefault_GrSLPrecision,
"LightColor");
} }
void GrGLLight::emitLightColor(GrGLSLUniformHandler* uniformHandler, void GrGLLight::emitLightColor(GrGLSLUniformHandler* uniformHandler,
@ -2119,8 +2111,7 @@ void GrGLDistantLight::emitSurfaceToLight(GrGLSLUniformHandler* uniformHandler,
GrGLSLFPFragmentBuilder* fragBuilder, GrGLSLFPFragmentBuilder* fragBuilder,
const char* z) { const char* z) {
const char* dir; const char* dir;
fDirectionUni = uniformHandler->addUniform(kFragment_GrShaderFlag, fDirectionUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf3_GrSLType,
kVec3f_GrSLType, kDefault_GrSLPrecision,
"LightDirection", &dir); "LightDirection", &dir);
fragBuilder->codeAppend(dir); fragBuilder->codeAppend(dir);
} }
@ -2139,10 +2130,9 @@ void GrGLPointLight::emitSurfaceToLight(GrGLSLUniformHandler* uniformHandler,
GrGLSLFPFragmentBuilder* fragBuilder, GrGLSLFPFragmentBuilder* fragBuilder,
const char* z) { const char* z) {
const char* loc; const char* loc;
fLocationUni = uniformHandler->addUniform(kFragment_GrShaderFlag, fLocationUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf3_GrSLType,
kVec3f_GrSLType, kDefault_GrSLPrecision,
"LightLocation", &loc); "LightLocation", &loc);
fragBuilder->codeAppendf("normalize(%s - float3(sk_FragCoord.xy, %s))", fragBuilder->codeAppendf("normalize(%s - half3(sk_FragCoord.xy, %s))",
loc, z); loc, z);
} }
@ -2165,11 +2155,10 @@ void GrGLSpotLight::emitSurfaceToLight(GrGLSLUniformHandler* uniformHandler,
GrGLSLFPFragmentBuilder* fragBuilder, GrGLSLFPFragmentBuilder* fragBuilder,
const char* z) { const char* z) {
const char* location; const char* location;
fLocationUni = uniformHandler->addUniform(kFragment_GrShaderFlag, fLocationUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf3_GrSLType,
kVec3f_GrSLType, kDefault_GrSLPrecision,
"LightLocation", &location); "LightLocation", &location);
fragBuilder->codeAppendf("normalize(%s - float3(sk_FragCoord.xy, %s))", fragBuilder->codeAppendf("normalize(%s - half3(sk_FragCoord.xy, %s))",
location, z); location, z);
} }
@ -2184,36 +2173,31 @@ void GrGLSpotLight::emitLightColor(GrGLSLUniformHandler* uniformHandler,
const char* cosOuter; const char* cosOuter;
const char* coneScale; const char* coneScale;
const char* s; const char* s;
fExponentUni = uniformHandler->addUniform(kFragment_GrShaderFlag, fExponentUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType,
kFloat_GrSLType, kDefault_GrSLPrecision,
"Exponent", &exponent); "Exponent", &exponent);
fCosInnerConeAngleUni = uniformHandler->addUniform(kFragment_GrShaderFlag, fCosInnerConeAngleUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType,
kFloat_GrSLType, kDefault_GrSLPrecision,
"CosInnerConeAngle", &cosInner); "CosInnerConeAngle", &cosInner);
fCosOuterConeAngleUni = uniformHandler->addUniform(kFragment_GrShaderFlag, fCosOuterConeAngleUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType,
kFloat_GrSLType, kDefault_GrSLPrecision,
"CosOuterConeAngle", &cosOuter); "CosOuterConeAngle", &cosOuter);
fConeScaleUni = uniformHandler->addUniform(kFragment_GrShaderFlag, fConeScaleUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType,
kFloat_GrSLType, kDefault_GrSLPrecision,
"ConeScale", &coneScale); "ConeScale", &coneScale);
fSUni = uniformHandler->addUniform(kFragment_GrShaderFlag, fSUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf3_GrSLType, "S", &s);
kVec3f_GrSLType, kDefault_GrSLPrecision, "S", &s);
static const GrShaderVar gLightColorArgs[] = { static const GrShaderVar gLightColorArgs[] = {
GrShaderVar("surfaceToLight", kVec3f_GrSLType) GrShaderVar("surfaceToLight", kHalf3_GrSLType)
}; };
SkString lightColorBody; SkString lightColorBody;
lightColorBody.appendf("\tfloat cosAngle = -dot(surfaceToLight, %s);\n", s); lightColorBody.appendf("\thalf cosAngle = -dot(surfaceToLight, %s);\n", s);
lightColorBody.appendf("\tif (cosAngle < %s) {\n", cosOuter); lightColorBody.appendf("\tif (cosAngle < %s) {\n", cosOuter);
lightColorBody.appendf("\t\treturn float3(0);\n"); lightColorBody.appendf("\t\treturn half3(0);\n");
lightColorBody.appendf("\t}\n"); lightColorBody.appendf("\t}\n");
lightColorBody.appendf("\tfloat scale = pow(cosAngle, %s);\n", exponent); lightColorBody.appendf("\thalf scale = pow(cosAngle, %s);\n", exponent);
lightColorBody.appendf("\tif (cosAngle < %s) {\n", cosInner); lightColorBody.appendf("\tif (cosAngle < %s) {\n", cosInner);
lightColorBody.appendf("\t\treturn %s * scale * (cosAngle - %s) * %s;\n", lightColorBody.appendf("\t\treturn %s * scale * (cosAngle - %s) * %s;\n",
color, cosOuter, coneScale); color, cosOuter, coneScale);
lightColorBody.appendf("\t}\n"); lightColorBody.appendf("\t}\n");
lightColorBody.appendf("\treturn %s;\n", color); lightColorBody.appendf("\treturn %s;\n", color);
fragBuilder->emitFunction(kVec3f_GrSLType, fragBuilder->emitFunction(kHalf3_GrSLType,
"lightColor", "lightColor",
SK_ARRAY_COUNT(gLightColorArgs), SK_ARRAY_COUNT(gLightColorArgs),
gLightColorArgs, gLightColorArgs,

View File

@ -60,16 +60,16 @@ private:
void emitCode(EmitArgs& args) override { void emitCode(EmitArgs& args) override {
if (nullptr == args.fInputColor) { if (nullptr == args.fInputColor) {
args.fInputColor = "float4(1)"; args.fInputColor = "half4(1)";
} }
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
fragBuilder->codeAppendf("\tfloat luma = dot(float3(%f, %f, %f), %s.rgb);\n", fragBuilder->codeAppendf("\thalf luma = dot(half3(%f, %f, %f), %s.rgb);\n",
SK_ITU_BT709_LUM_COEFF_R, SK_ITU_BT709_LUM_COEFF_R,
SK_ITU_BT709_LUM_COEFF_G, SK_ITU_BT709_LUM_COEFF_G,
SK_ITU_BT709_LUM_COEFF_B, SK_ITU_BT709_LUM_COEFF_B,
args.fInputColor); args.fInputColor);
fragBuilder->codeAppendf("\t%s = float4(0, 0, 0, luma);\n", fragBuilder->codeAppendf("\t%s = half4(0, 0, 0, luma);\n",
args.fOutputColor); args.fOutputColor);
} }

View File

@ -180,48 +180,44 @@ private:
void GrGLMagnifierEffect::emitCode(EmitArgs& args) { void GrGLMagnifierEffect::emitCode(EmitArgs& args) {
GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
fOffsetVar = uniformHandler->addUniform(kFragment_GrShaderFlag, fOffsetVar = uniformHandler->addUniform(kFragment_GrShaderFlag,
kVec2f_GrSLType, kDefault_GrSLPrecision, kHalf2_GrSLType, "Offset");
"Offset");
fInvZoomVar = uniformHandler->addUniform(kFragment_GrShaderFlag, fInvZoomVar = uniformHandler->addUniform(kFragment_GrShaderFlag,
kVec2f_GrSLType, kDefault_GrSLPrecision, kHalf2_GrSLType, "InvZoom");
"InvZoom");
fInvInsetVar = uniformHandler->addUniform(kFragment_GrShaderFlag, fInvInsetVar = uniformHandler->addUniform(kFragment_GrShaderFlag,
kVec2f_GrSLType, kDefault_GrSLPrecision, kHalf2_GrSLType, "InvInset");
"InvInset");
fBoundsVar = uniformHandler->addUniform(kFragment_GrShaderFlag, fBoundsVar = uniformHandler->addUniform(kFragment_GrShaderFlag,
kVec4f_GrSLType, kDefault_GrSLPrecision, kHalf4_GrSLType, "Bounds");
"Bounds");
const GrMagnifierEffect& zoom = args.fFp.cast<GrMagnifierEffect>(); const GrMagnifierEffect& zoom = args.fFp.cast<GrMagnifierEffect>();
fColorSpaceHelper.emitCode(uniformHandler, zoom.colorSpaceXform()); fColorSpaceHelper.emitCode(uniformHandler, zoom.colorSpaceXform());
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]); SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
fragBuilder->codeAppendf("\t\tfloat2 coord = %s;\n", coords2D.c_str()); fragBuilder->codeAppendf("\t\thighfloat2 coord = %s;\n", coords2D.c_str());
fragBuilder->codeAppendf("\t\tfloat2 zoom_coord = %s + %s * %s;\n", fragBuilder->codeAppendf("\t\thighfloat2 zoom_coord = %s + %s * %s;\n",
uniformHandler->getUniformCStr(fOffsetVar), uniformHandler->getUniformCStr(fOffsetVar),
coords2D.c_str(), coords2D.c_str(),
uniformHandler->getUniformCStr(fInvZoomVar)); uniformHandler->getUniformCStr(fInvZoomVar));
const char* bounds = uniformHandler->getUniformCStr(fBoundsVar); const char* bounds = uniformHandler->getUniformCStr(fBoundsVar);
fragBuilder->codeAppendf("\t\tfloat2 delta = (coord - %s.xy) * %s.zw;\n", bounds, bounds); fragBuilder->codeAppendf("\t\thighfloat2 delta = (coord - %s.xy) * %s.zw;\n", bounds, bounds);
fragBuilder->codeAppendf("\t\tdelta = min(delta, float2(1.0, 1.0) - delta);\n"); fragBuilder->codeAppendf("\t\tdelta = min(delta, half2(1.0, 1.0) - delta);\n");
fragBuilder->codeAppendf("\t\tdelta = delta * %s;\n", fragBuilder->codeAppendf("\t\tdelta = delta * %s;\n",
uniformHandler->getUniformCStr(fInvInsetVar)); uniformHandler->getUniformCStr(fInvInsetVar));
fragBuilder->codeAppend("\t\tfloat weight = 0.0;\n"); fragBuilder->codeAppend("\t\thalf weight = 0.0;\n");
fragBuilder->codeAppend("\t\tif (delta.s < 2.0 && delta.t < 2.0) {\n"); fragBuilder->codeAppend("\t\tif (delta.s < 2.0 && delta.t < 2.0) {\n");
fragBuilder->codeAppend("\t\t\tdelta = float2(2.0, 2.0) - delta;\n"); fragBuilder->codeAppend("\t\t\tdelta = half2(2.0, 2.0) - delta;\n");
fragBuilder->codeAppend("\t\t\tfloat dist = length(delta);\n"); fragBuilder->codeAppend("\t\t\thalf dist = length(delta);\n");
fragBuilder->codeAppend("\t\t\tdist = max(2.0 - dist, 0.0);\n"); fragBuilder->codeAppend("\t\t\tdist = max(2.0 - dist, 0.0);\n");
fragBuilder->codeAppend("\t\t\tweight = min(dist * dist, 1.0);\n"); fragBuilder->codeAppend("\t\t\tweight = min(dist * dist, 1.0);\n");
fragBuilder->codeAppend("\t\t} else {\n"); fragBuilder->codeAppend("\t\t} else {\n");
fragBuilder->codeAppend("\t\t\tfloat2 delta_squared = delta * delta;\n"); fragBuilder->codeAppend("\t\t\thighfloat2 delta_squared = delta * delta;\n");
fragBuilder->codeAppend("\t\t\tweight = min(min(delta_squared.x, delta_squared.y), 1.0);\n"); fragBuilder->codeAppend("\t\t\tweight = min(min(delta_squared.x, delta_squared.y), 1.0);\n");
fragBuilder->codeAppend("\t\t}\n"); fragBuilder->codeAppend("\t\t}\n");
fragBuilder->codeAppend("\t\tfloat2 mix_coord = mix(coord, zoom_coord, weight);\n"); fragBuilder->codeAppend("\t\thighfloat2 mix_coord = mix(coord, zoom_coord, weight);\n");
fragBuilder->codeAppend("\t\tfloat4 output_color = "); fragBuilder->codeAppend("\t\thalf4 output_color = ");
fragBuilder->appendTextureLookup(args.fTexSamplers[0], "mix_coord", kVec2f_GrSLType, fragBuilder->appendTextureLookup(args.fTexSamplers[0], "mix_coord", kHalf2_GrSLType,
&fColorSpaceHelper); &fColorSpaceHelper);
fragBuilder->codeAppend(";\n"); fragBuilder->codeAppend(";\n");

View File

@ -212,13 +212,9 @@ void GrGLMorphologyEffect::emitCode(EmitArgs& args) {
const GrMorphologyEffect& me = args.fFp.cast<GrMorphologyEffect>(); const GrMorphologyEffect& me = args.fFp.cast<GrMorphologyEffect>();
GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
fPixelSizeUni = uniformHandler->addUniform(kFragment_GrShaderFlag, fPixelSizeUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType, "PixelSize");
kFloat_GrSLType, kDefault_GrSLPrecision,
"PixelSize");
const char* pixelSizeInc = uniformHandler->getUniformCStr(fPixelSizeUni); const char* pixelSizeInc = uniformHandler->getUniformCStr(fPixelSizeUni);
fRangeUni = uniformHandler->addUniform(kFragment_GrShaderFlag, fRangeUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHighFloat2_GrSLType, "Range");
kVec2f_GrSLType, kDefault_GrSLPrecision,
"Range");
const char* range = uniformHandler->getUniformCStr(fRangeUni); const char* range = uniformHandler->getUniformCStr(fRangeUni);
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
@ -226,11 +222,11 @@ void GrGLMorphologyEffect::emitCode(EmitArgs& args) {
const char* func; const char* func;
switch (me.type()) { switch (me.type()) {
case GrMorphologyEffect::Type::kErode: case GrMorphologyEffect::Type::kErode:
fragBuilder->codeAppendf("\t\t%s = float4(1, 1, 1, 1);\n", args.fOutputColor); fragBuilder->codeAppendf("\t\t%s = half4(1, 1, 1, 1);\n", args.fOutputColor);
func = "min"; func = "min";
break; break;
case GrMorphologyEffect::Type::kDilate: case GrMorphologyEffect::Type::kDilate:
fragBuilder->codeAppendf("\t\t%s = float4(0, 0, 0, 0);\n", args.fOutputColor); fragBuilder->codeAppendf("\t\t%s = half4(0, 0, 0, 0);\n", args.fOutputColor);
func = "max"; func = "max";
break; break;
default: default:
@ -255,12 +251,12 @@ void GrGLMorphologyEffect::emitCode(EmitArgs& args) {
int width = me.width(); int width = me.width();
// float2 coord = coord2D; // float2 coord = coord2D;
fragBuilder->codeAppendf("\t\tfloat2 coord = %s;\n", coords2D.c_str()); fragBuilder->codeAppendf("\t\thighfloat2 coord = %s;\n", coords2D.c_str());
// coord.x -= radius * pixelSize; // coord.x -= radius * pixelSize;
fragBuilder->codeAppendf("\t\tcoord.%s -= %d.0 * %s; \n", dir, me.radius(), pixelSizeInc); fragBuilder->codeAppendf("\t\tcoord.%s -= %d.0 * %s; \n", dir, me.radius(), pixelSizeInc);
if (me.useRange()) { if (me.useRange()) {
// highBound = min(highBound, coord.x + (width-1) * pixelSize); // highBound = min(highBound, coord.x + (width-1) * pixelSize);
fragBuilder->codeAppendf("\t\tfloat highBound = min(%s.y, coord.%s + %f * %s);", fragBuilder->codeAppendf("\t\thighfloat highBound = min(%s.y, coord.%s + %f * %s);",
range, dir, float(width - 1), pixelSizeInc); range, dir, float(width - 1), pixelSizeInc);
// coord.x = max(lowBound, coord.x); // coord.x = max(lowBound, coord.x);
fragBuilder->codeAppendf("\t\tcoord.%s = max(%s.x, coord.%s);", dir, range, dir); fragBuilder->codeAppendf("\t\tcoord.%s = max(%s.x, coord.%s);", dir, range, dir);

View File

@ -150,49 +150,49 @@ GLOverdrawFragmentProcessor::GLOverdrawFragmentProcessor(const GrColor4f* colors
void GLOverdrawFragmentProcessor::emitCode(EmitArgs& args) { void GLOverdrawFragmentProcessor::emitCode(EmitArgs& args) {
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
if (nullptr == args.fInputColor) { if (nullptr == args.fInputColor) {
fragBuilder->codeAppendf("%s.rgba = float4(%f, %f, %f, %f);", args.fOutputColor, fragBuilder->codeAppendf("%s.rgba = half4(%f, %f, %f, %f);", args.fOutputColor,
fColors[5].fRGBA[0], fColors[5].fRGBA[0],
fColors[5].fRGBA[1], fColors[5].fRGBA[1],
fColors[5].fRGBA[2], fColors[5].fRGBA[2],
fColors[5].fRGBA[3]); fColors[5].fRGBA[3]);
} else { } else {
fragBuilder->codeAppendf("float alpha = 255.0 * %s.a;", args.fInputColor); fragBuilder->codeAppendf("half alpha = 255.0 * %s.a;", args.fInputColor);
fragBuilder->codeAppendf("if (alpha < 0.5) {"); fragBuilder->codeAppendf("if (alpha < 0.5) {");
fragBuilder->codeAppendf(" %s.rgba = float4(%f, %f, %f, %f);", args.fOutputColor, fragBuilder->codeAppendf(" %s.rgba = half4(%f, %f, %f, %f);", args.fOutputColor,
fColors[0].fRGBA[0], fColors[0].fRGBA[0],
fColors[0].fRGBA[1], fColors[0].fRGBA[1],
fColors[0].fRGBA[2], fColors[0].fRGBA[2],
fColors[0].fRGBA[3]); fColors[0].fRGBA[3]);
fragBuilder->codeAppendf("} else if (alpha < 1.5) {"); fragBuilder->codeAppendf("} else if (alpha < 1.5) {");
fragBuilder->codeAppendf(" %s.rgba = float4(%f, %f, %f, %f);", args.fOutputColor, fragBuilder->codeAppendf(" %s.rgba = half4(%f, %f, %f, %f);", args.fOutputColor,
fColors[1].fRGBA[0], fColors[1].fRGBA[0],
fColors[1].fRGBA[1], fColors[1].fRGBA[1],
fColors[1].fRGBA[2], fColors[1].fRGBA[2],
fColors[1].fRGBA[3]); fColors[1].fRGBA[3]);
fragBuilder->codeAppendf("} else if (alpha < 2.5) {"); fragBuilder->codeAppendf("} else if (alpha < 2.5) {");
fragBuilder->codeAppendf(" %s.rgba = float4(%f, %f, %f, %f);", args.fOutputColor, fragBuilder->codeAppendf(" %s.rgba = half4(%f, %f, %f, %f);", args.fOutputColor,
fColors[2].fRGBA[0], fColors[2].fRGBA[0],
fColors[2].fRGBA[1], fColors[2].fRGBA[1],
fColors[2].fRGBA[2], fColors[2].fRGBA[2],
fColors[2].fRGBA[3]); fColors[2].fRGBA[3]);
fragBuilder->codeAppendf("} else if (alpha < 3.5) {"); fragBuilder->codeAppendf("} else if (alpha < 3.5) {");
fragBuilder->codeAppendf(" %s.rgba = float4(%f, %f, %f, %f);", args.fOutputColor, fragBuilder->codeAppendf(" %s.rgba = half4(%f, %f, %f, %f);", args.fOutputColor,
fColors[3].fRGBA[0], fColors[3].fRGBA[0],
fColors[3].fRGBA[1], fColors[3].fRGBA[1],
fColors[3].fRGBA[2], fColors[3].fRGBA[2],
fColors[3].fRGBA[3]); fColors[3].fRGBA[3]);
fragBuilder->codeAppendf("} else if (alpha < 4.5) {"); fragBuilder->codeAppendf("} else if (alpha < 4.5) {");
fragBuilder->codeAppendf(" %s.rgba = float4(%f, %f, %f, %f);", args.fOutputColor, fragBuilder->codeAppendf(" %s.rgba = half4(%f, %f, %f, %f);", args.fOutputColor,
fColors[4].fRGBA[0], fColors[4].fRGBA[0],
fColors[4].fRGBA[1], fColors[4].fRGBA[1],
fColors[4].fRGBA[2], fColors[4].fRGBA[2],
fColors[4].fRGBA[3]); fColors[4].fRGBA[3]);
fragBuilder->codeAppendf("} else {"); fragBuilder->codeAppendf("} else {");
fragBuilder->codeAppendf(" %s.rgba = float4(%f, %f, %f, %f);", args.fOutputColor, fragBuilder->codeAppendf(" %s.rgba = half4(%f, %f, %f, %f);", args.fOutputColor,
fColors[5].fRGBA[0], fColors[5].fRGBA[0],
fColors[5].fRGBA[1], fColors[5].fRGBA[1],
fColors[5].fRGBA[2], fColors[5].fRGBA[2],
fColors[5].fRGBA[3]); fColors[5].fRGBA[3]);
fragBuilder->codeAppendf("}"); fragBuilder->codeAppendf("}");
} }
} }

View File

@ -241,7 +241,7 @@ private:
// Positive distance is towards the center of the circle. // Positive distance is towards the center of the circle.
// Map all the cases to the lower right quadrant. // Map all the cases to the lower right quadrant.
fragBuilder->codeAppendf("float2 delta = abs(sk_FragCoord.xy - %s.%s);", fragBuilder->codeAppendf("half2 delta = abs(sk_FragCoord.xy - %s.%s);",
posName, indices); posName, indices);
switch (mode) { switch (mode) {
@ -249,14 +249,14 @@ private:
// When a shadow circle gets large we can have some precision issues if // When a shadow circle gets large we can have some precision issues if
// we do "length(delta)/radius". The scaleDist temporary cuts the // we do "length(delta)/radius". The scaleDist temporary cuts the
// delta vector down a bit before invoking length. // delta vector down a bit before invoking length.
fragBuilder->codeAppendf("float scaledDist = length(delta/%s);", radName); fragBuilder->codeAppendf("half scaledDist = length(delta/%s);", radName);
fragBuilder->codeAppendf("%s = clamp((%s.%c/%s - scaledDist), 0.0, 1.0);", fragBuilder->codeAppendf("%s = clamp((%s.%c/%s - scaledDist), 0.0, 1.0);",
outputName, sizesName, indices[0], radName); outputName, sizesName, indices[0], radName);
break; break;
case kRect_Mode: case kRect_Mode:
fragBuilder->codeAppendf( fragBuilder->codeAppendf(
"float2 rectDist = float2(1.0 - clamp((%s.%c - delta.x)/%s, 0.0, 1.0)," "half2 rectDist = half2(1.0 - clamp((%s.%c - delta.x)/%s, 0.0, 1.0),"
"1.0 - clamp((%s.%c - delta.y)/%s, 0.0, 1.0));", "1.0 - clamp((%s.%c - delta.y)/%s, 0.0, 1.0));",
sizesName, indices[0], radName, sizesName, indices[0], radName,
sizesName, indices[1], radName); sizesName, indices[1], radName);
fragBuilder->codeAppendf("%s = clamp(1.0 - length(rectDist), 0.0, 1.0);", fragBuilder->codeAppendf("%s = clamp(1.0 - length(rectDist), 0.0, 1.0);",
@ -273,11 +273,11 @@ private:
//---------------- //----------------
// rect distance computation // rect distance computation
fragBuilder->codeAppendf("float xDist = (%s.%c - delta.x) / %s;", fragBuilder->codeAppendf("half xDist = (%s.%c - delta.x) / %s;",
sizesName, indices[0], radName); sizesName, indices[0], radName);
fragBuilder->codeAppendf("float yDist = (%s.%c - delta.y) / %s;", fragBuilder->codeAppendf("half yDist = (%s.%c - delta.y) / %s;",
sizesName, indices[1], radName); sizesName, indices[1], radName);
fragBuilder->codeAppend("float rectDist = clamp(min(xDist, yDist), 0.0, 1.0);"); fragBuilder->codeAppend("half rectDist = clamp(min(xDist, yDist), 0.0, 1.0);");
//---------------- //----------------
// ice-cream-cone fractional distance computation // ice-cream-cone fractional distance computation
@ -286,59 +286,59 @@ private:
// compute the pointy end of the ice cream cone. If it smaller we just want to // compute the pointy end of the ice cream cone. If it smaller we just want to
// use the center of the corner's circle. When using the blurRadius the inset // use the center of the corner's circle. When using the blurRadius the inset
// amount can't exceed the halfwidths of the RRect. // amount can't exceed the halfwidths of the RRect.
fragBuilder->codeAppendf("float insetDist = min(max(%s, %s.%c)," fragBuilder->codeAppendf("half insetDist = min(max(%s, %s.%c),"
"min(%s.%c, %s.%c));", "min(%s.%c, %s.%c));",
radName, radiiName, indices[0], radName, radiiName, indices[0],
sizesName, indices[0], sizesName, indices[1]); sizesName, indices[0], sizesName, indices[1]);
// "maxValue" is a correction term for if the blurRadius is larger than the // "maxValue" is a correction term for if the blurRadius is larger than the
// size of the RRect. In that case we don't want to go all the way to black. // size of the RRect. In that case we don't want to go all the way to black.
fragBuilder->codeAppendf("float maxValue = insetDist/%s;", radName); fragBuilder->codeAppendf("half maxValue = insetDist/%s;", radName);
fragBuilder->codeAppendf("float2 coneBottom = float2(%s.%c - insetDist," fragBuilder->codeAppendf("half2 coneBottom = half2(%s.%c - insetDist,"
"%s.%c - insetDist);", "%s.%c - insetDist);",
sizesName, indices[0], sizesName, indices[1]); sizesName, indices[0], sizesName, indices[1]);
fragBuilder->codeAppendf("float2 cornerTop = float2(%s.%c - %s.%c, %s.%c) -" fragBuilder->codeAppendf("half2 cornerTop = half2(%s.%c - %s.%c, %s.%c) -"
"coneBottom;", "coneBottom;",
sizesName, indices[0], radiiName, indices[0], sizesName, indices[0], radiiName, indices[0],
sizesName, indices[1]); sizesName, indices[1]);
fragBuilder->codeAppendf("float2 cornerRight = float2(%s.%c, %s.%c - %s.%c) -" fragBuilder->codeAppendf("half2 cornerRight = half2(%s.%c, %s.%c - %s.%c) -"
"coneBottom;", "coneBottom;",
sizesName, indices[0], sizesName, indices[0],
sizesName, indices[1], radiiName, indices[1]); sizesName, indices[1], radiiName, indices[1]);
fragBuilder->codeAppend("float2 ptInConeSpace = delta - coneBottom;"); fragBuilder->codeAppend("half2 ptInConeSpace = delta - coneBottom;");
fragBuilder->codeAppend("float distToPtInConeSpace = length(ptInConeSpace);"); fragBuilder->codeAppend("half distToPtInConeSpace = length(ptInConeSpace);");
fragBuilder->codeAppend("float cross1 = ptInConeSpace.x * cornerTop.y -" fragBuilder->codeAppend("half cross1 = ptInConeSpace.x * cornerTop.y -"
"ptInConeSpace.y * cornerTop.x;"); "ptInConeSpace.y * cornerTop.x;");
fragBuilder->codeAppend("float cross2 = -ptInConeSpace.x * cornerRight.y + " fragBuilder->codeAppend("half cross2 = -ptInConeSpace.x * cornerRight.y + "
"ptInConeSpace.y * cornerRight.x;"); "ptInConeSpace.y * cornerRight.x;");
fragBuilder->codeAppend("float inCone = step(0.0, cross1) *" fragBuilder->codeAppend("half inCone = step(0.0, cross1) *"
"step(0.0, cross2);"); "step(0.0, cross2);");
fragBuilder->codeAppendf("float2 cornerCenterInConeSpace = float2(insetDist -" fragBuilder->codeAppendf("half2 cornerCenterInConeSpace = half2(insetDist -"
"%s.%c);", "%s.%c);",
radiiName, indices[0]); radiiName, indices[0]);
fragBuilder->codeAppend("float2 connectingVec = ptInConeSpace -" fragBuilder->codeAppend("half2 connectingVec = ptInConeSpace -"
"cornerCenterInConeSpace;"); "cornerCenterInConeSpace;");
fragBuilder->codeAppend("ptInConeSpace = normalize(ptInConeSpace);"); fragBuilder->codeAppend("ptInConeSpace = normalize(ptInConeSpace);");
// "a" (i.e., dot(ptInConeSpace, ptInConeSpace) should always be 1.0f since // "a" (i.e., dot(ptInConeSpace, ptInConeSpace) should always be 1.0f since
// ptInConeSpace is now normalized // ptInConeSpace is now normalized
fragBuilder->codeAppend("float b = 2.0 * dot(ptInConeSpace, connectingVec);"); fragBuilder->codeAppend("half b = 2.0 * dot(ptInConeSpace, connectingVec);");
fragBuilder->codeAppendf("float c = dot(connectingVec, connectingVec) - " fragBuilder->codeAppendf("half c = dot(connectingVec, connectingVec) - "
"%s.%c * %s.%c;", "%s.%c * %s.%c;",
radiiName, indices[0], radiiName, indices[0]); radiiName, indices[0], radiiName, indices[0]);
fragBuilder->codeAppend("float fourAC = 4*c;"); fragBuilder->codeAppend("half fourAC = 4*c;");
// This max prevents sqrt(-1) when outside the cone // This max prevents sqrt(-1) when outside the cone
fragBuilder->codeAppend("float bSq = max(b*b, fourAC);"); fragBuilder->codeAppend("half bSq = max(b*b, fourAC);");
// lop off negative values that are outside the cone // lop off negative values that are outside the cone
fragBuilder->codeAppend("float coneDist = " fragBuilder->codeAppend("half coneDist = "
"max(0.0, 0.5 * (-b + sqrt(bSq - fourAC)));"); "max(0.0, 0.5 * (-b + sqrt(bSq - fourAC)));");
// make the coneDist a fraction of how far it is from the edge to the // make the coneDist a fraction of how far it is from the edge to the
// cone's base // cone's base
@ -358,42 +358,38 @@ private:
GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
const char* positionsUniName = nullptr; const char* positionsUniName = nullptr;
fPositionsUni = uniformHandler->addUniform(kFragment_GrShaderFlag, fPositionsUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType,
kVec4f_GrSLType, kDefault_GrSLPrecision,
"Positions", &positionsUniName); "Positions", &positionsUniName);
const char* sizesUniName = nullptr; const char* sizesUniName = nullptr;
fSizesUni = uniformHandler->addUniform(kFragment_GrShaderFlag, fSizesUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType,
kVec4f_GrSLType, kDefault_GrSLPrecision, kDefault_GrSLPrecision, "Sizes", &sizesUniName);
"Sizes", &sizesUniName);
const char* radiiUniName = nullptr; const char* radiiUniName = nullptr;
if (fp.fFirstMode == kSimpleCircular_Mode || fp.fSecondMode == kSimpleCircular_Mode) { if (fp.fFirstMode == kSimpleCircular_Mode || fp.fSecondMode == kSimpleCircular_Mode) {
fRadiiUni = uniformHandler->addUniform(kFragment_GrShaderFlag, fRadiiUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType,
kVec4f_GrSLType, kDefault_GrSLPrecision,
"Radii", &radiiUniName); "Radii", &radiiUniName);
} }
const char* radUniName = nullptr; const char* radUniName = nullptr;
fRadiusUni = uniformHandler->addUniform(kFragment_GrShaderFlag, fRadiusUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType,
kFloat_GrSLType, kDefault_GrSLPrecision,
"Radius", &radUniName); "Radius", &radUniName);
fragBuilder->codeAppend("float firstDist;"); fragBuilder->codeAppend("half firstDist;");
fragBuilder->codeAppend("{"); fragBuilder->codeAppend("{");
this->emitModeCode(fp.firstMode(), fragBuilder, this->emitModeCode(fp.firstMode(), fragBuilder,
positionsUniName, sizesUniName, radiiUniName, positionsUniName, sizesUniName, radiiUniName,
radUniName, "firstDist", "xy"); radUniName, "firstDist", "xy");
fragBuilder->codeAppend("}"); fragBuilder->codeAppend("}");
fragBuilder->codeAppend("float secondDist;"); fragBuilder->codeAppend("half secondDist;");
fragBuilder->codeAppend("{"); fragBuilder->codeAppend("{");
this->emitModeCode(fp.secondMode(), fragBuilder, this->emitModeCode(fp.secondMode(), fragBuilder,
positionsUniName, sizesUniName, radiiUniName, positionsUniName, sizesUniName, radiiUniName,
radUniName, "secondDist", "zw"); radUniName, "secondDist", "zw");
fragBuilder->codeAppend("}"); fragBuilder->codeAppend("}");
fragBuilder->codeAppend("float2 distVec = float2(1.0 - firstDist, 1.0 - secondDist);"); fragBuilder->codeAppend("half2 distVec = half2(1.0 - firstDist, 1.0 - secondDist);");
// Finally use the distance to apply the Gaussian edge // Finally use the distance to apply the Gaussian edge
fragBuilder->codeAppend("float factor = clamp(length(distVec), 0.0, 1.0);"); fragBuilder->codeAppend("half factor = clamp(length(distVec), 0.0, 1.0);");
fragBuilder->codeAppend("factor = exp(-factor * factor * 4.0) - 0.018;"); fragBuilder->codeAppend("factor = exp(-factor * factor * 4.0) - 0.018;");
fragBuilder->codeAppendf("%s = factor*%s;", fragBuilder->codeAppendf("%s = factor*%s;",
args.fOutputColor, args.fInputColor); args.fOutputColor, args.fInputColor);

View File

@ -396,8 +396,7 @@ void GLColorTableEffect::onSetData(const GrGLSLProgramDataManager& pdm,
void GLColorTableEffect::emitCode(EmitArgs& args) { void GLColorTableEffect::emitCode(EmitArgs& args) {
const char* yoffsets; const char* yoffsets;
fRGBAYValuesUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, fRGBAYValuesUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType,
kVec4f_GrSLType, kDefault_GrSLPrecision,
"yoffsets", &yoffsets); "yoffsets", &yoffsets);
static const float kColorScaleFactor = 255.0f / 256.0f; static const float kColorScaleFactor = 255.0f / 256.0f;
static const float kColorOffsetFactor = 1.0f / 512.0f; static const float kColorOffsetFactor = 1.0f / 512.0f;
@ -405,14 +404,14 @@ void GLColorTableEffect::emitCode(EmitArgs& args) {
if (nullptr == args.fInputColor) { if (nullptr == args.fInputColor) {
// the input color is solid white (all ones). // the input color is solid white (all ones).
static const float kMaxValue = kColorScaleFactor + kColorOffsetFactor; static const float kMaxValue = kColorScaleFactor + kColorOffsetFactor;
fragBuilder->codeAppendf("\t\tfloat4 coord = float4(%f, %f, %f, %f);\n", fragBuilder->codeAppendf("\t\thalf4 coord = half4(%f, %f, %f, %f);\n",
kMaxValue, kMaxValue, kMaxValue, kMaxValue); kMaxValue, kMaxValue, kMaxValue, kMaxValue);
} else { } else {
fragBuilder->codeAppendf("\t\tfloat nonZeroAlpha = max(%s.a, .0001);\n", args.fInputColor); fragBuilder->codeAppendf("\t\thalf nonZeroAlpha = max(%s.a, .0001);\n", args.fInputColor);
fragBuilder->codeAppendf("\t\tfloat4 coord = float4(%s.rgb / nonZeroAlpha, nonZeroAlpha);\n", fragBuilder->codeAppendf("\t\thalf4 coord = half4(%s.rgb / nonZeroAlpha, nonZeroAlpha);\n",
args.fInputColor); args.fInputColor);
fragBuilder->codeAppendf("\t\tcoord = coord * %f + float4(%f, %f, %f, %f);\n", fragBuilder->codeAppendf("\t\tcoord = coord * %f + half4(%f, %f, %f, %f);\n",
kColorScaleFactor, kColorScaleFactor,
kColorOffsetFactor, kColorOffsetFactor, kColorOffsetFactor, kColorOffsetFactor,
kColorOffsetFactor, kColorOffsetFactor); kColorOffsetFactor, kColorOffsetFactor);
@ -421,22 +420,22 @@ void GLColorTableEffect::emitCode(EmitArgs& args) {
SkString coord; SkString coord;
fragBuilder->codeAppendf("\t\t%s.a = ", args.fOutputColor); fragBuilder->codeAppendf("\t\t%s.a = ", args.fOutputColor);
coord.printf("float2(coord.a, %s.a)", yoffsets); coord.printf("half2(coord.a, %s.a)", yoffsets);
fragBuilder->appendTextureLookup(args.fTexSamplers[0], coord.c_str()); fragBuilder->appendTextureLookup(args.fTexSamplers[0], coord.c_str());
fragBuilder->codeAppend(".a;\n"); fragBuilder->codeAppend(".a;\n");
fragBuilder->codeAppendf("\t\t%s.r = ", args.fOutputColor); fragBuilder->codeAppendf("\t\t%s.r = ", args.fOutputColor);
coord.printf("float2(coord.r, %s.r)", yoffsets); coord.printf("half2(coord.r, %s.r)", yoffsets);
fragBuilder->appendTextureLookup(args.fTexSamplers[0], coord.c_str()); fragBuilder->appendTextureLookup(args.fTexSamplers[0], coord.c_str());
fragBuilder->codeAppend(".a;\n"); fragBuilder->codeAppend(".a;\n");
fragBuilder->codeAppendf("\t\t%s.g = ", args.fOutputColor); fragBuilder->codeAppendf("\t\t%s.g = ", args.fOutputColor);
coord.printf("float2(coord.g, %s.g)", yoffsets); coord.printf("half2(coord.g, %s.g)", yoffsets);
fragBuilder->appendTextureLookup(args.fTexSamplers[0], coord.c_str()); fragBuilder->appendTextureLookup(args.fTexSamplers[0], coord.c_str());
fragBuilder->codeAppend(".a;\n"); fragBuilder->codeAppend(".a;\n");
fragBuilder->codeAppendf("\t\t%s.b = ", args.fOutputColor); fragBuilder->codeAppendf("\t\t%s.b = ", args.fOutputColor);
coord.printf("float2(coord.b, %s.b)", yoffsets); coord.printf("half2(coord.b, %s.b)", yoffsets);
fragBuilder->appendTextureLookup(args.fTexSamplers[0], coord.c_str()); fragBuilder->appendTextureLookup(args.fTexSamplers[0], coord.c_str());
fragBuilder->codeAppend(".a;\n"); fragBuilder->codeAppend(".a;\n");

View File

@ -82,26 +82,26 @@ public:
// Setup pass through color // Setup pass through color
if (gp.hasVertexColor()) { if (gp.hasVertexColor()) {
GrGLSLVertToFrag varying(kVec4f_GrSLType); GrGLSLVertToFrag varying(kHalf4_GrSLType);
varyingHandler->addVarying("color", &varying); varyingHandler->addVarying("color", &varying);
// There are several optional steps to process the color. Start with the attribute: // There are several optional steps to process the color. Start with the attribute:
vertBuilder->codeAppendf("float4 color = %s;", gp.inColor()->fName); vertBuilder->codeAppendf("half4 color = %s;", gp.inColor()->fName);
// Linearize // Linearize
if (gp.linearizeColor()) { if (gp.linearizeColor()) {
SkString srgbFuncName; SkString srgbFuncName;
static const GrShaderVar gSrgbArgs[] = { static const GrShaderVar gSrgbArgs[] = {
GrShaderVar("x", kFloat_GrSLType), GrShaderVar("x", kHalf_GrSLType),
}; };
vertBuilder->emitFunction(kFloat_GrSLType, vertBuilder->emitFunction(kHalf_GrSLType,
"srgb_to_linear", "srgb_to_linear",
SK_ARRAY_COUNT(gSrgbArgs), SK_ARRAY_COUNT(gSrgbArgs),
gSrgbArgs, gSrgbArgs,
"return (x <= 0.04045) ? (x / 12.92) " "return (x <= 0.04045) ? (x / 12.92) "
": pow((x + 0.055) / 1.055, 2.4);", ": pow((x + 0.055) / 1.055, 2.4);",
&srgbFuncName); &srgbFuncName);
vertBuilder->codeAppendf("color = float4(%s(%s.r), %s(%s.g), %s(%s.b), %s.a);", vertBuilder->codeAppendf("color = half4(%s(%s.r), %s(%s.g), %s(%s.b), %s.a);",
srgbFuncName.c_str(), gp.inColor()->fName, srgbFuncName.c_str(), gp.inColor()->fName,
srgbFuncName.c_str(), gp.inColor()->fName, srgbFuncName.c_str(), gp.inColor()->fName,
srgbFuncName.c_str(), gp.inColor()->fName, srgbFuncName.c_str(), gp.inColor()->fName,
@ -110,7 +110,7 @@ public:
// For SkColor, do a red/blue swap and premul // For SkColor, do a red/blue swap and premul
if (gp.fFlags & kColorAttributeIsSkColor_GPFlag) { if (gp.fFlags & kColorAttributeIsSkColor_GPFlag) {
vertBuilder->codeAppend("color = float4(color.a * color.bgr, color.a);"); vertBuilder->codeAppend("color = half4(color.a * color.bgr, color.a);");
} }
// Do color-correction to destination gamut // Do color-correction to destination gamut
@ -161,19 +161,18 @@ public:
// Setup coverage as pass through // Setup coverage as pass through
if (gp.hasVertexCoverage()) { if (gp.hasVertexCoverage()) {
fragBuilder->codeAppendf("float alpha = 1.0;"); fragBuilder->codeAppendf("half alpha = 1.0;");
varyingHandler->addPassThroughAttribute(gp.inCoverage(), "alpha"); varyingHandler->addPassThroughAttribute(gp.inCoverage(), "alpha");
fragBuilder->codeAppendf("%s = float4(alpha);", args.fOutputCoverage); fragBuilder->codeAppendf("%s = half4(alpha);", args.fOutputCoverage);
} else if (gp.coverage() == 0xff) { } else if (gp.coverage() == 0xff) {
fragBuilder->codeAppendf("%s = float4(1);", args.fOutputCoverage); fragBuilder->codeAppendf("%s = half4(1);", args.fOutputCoverage);
} else { } else {
const char* fragCoverage; const char* fragCoverage;
fCoverageUniform = uniformHandler->addUniform(kFragment_GrShaderFlag, fCoverageUniform = uniformHandler->addUniform(kFragment_GrShaderFlag,
kFloat_GrSLType, kHalf_GrSLType,
kDefault_GrSLPrecision,
"Coverage", "Coverage",
&fragCoverage); &fragCoverage);
fragBuilder->codeAppendf("%s = float4(%s);", args.fOutputCoverage, fragCoverage); fragBuilder->codeAppendf("%s = half4(%s);", args.fOutputCoverage, fragCoverage);
} }
} }

View File

@ -177,7 +177,7 @@ private:
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
fragBuilder->codeAppendf("%s = %s;", args.fOutputColor, args.fInputColor); fragBuilder->codeAppendf("%s = %s;", args.fOutputColor, args.fInputColor);
fragBuilder->codeAppendf("float invAlpha = %s.a <= 0.0 ? 0.0 : 1.0 / %s.a;", fragBuilder->codeAppendf("half invAlpha = %s.a <= 0.0 ? 0.0 : 1.0 / %s.a;",
args.fInputColor, args.fInputColor); args.fInputColor, args.fInputColor);
fragBuilder->codeAppendf("%s.rgb *= invAlpha;", args.fOutputColor); fragBuilder->codeAppendf("%s.rgb *= invAlpha;", args.fOutputColor);
} }
@ -387,8 +387,7 @@ std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::OverrideInput(
void emitCode(EmitArgs& args) override { void emitCode(EmitArgs& args) override {
const char* colorName; const char* colorName;
fColorUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, fColorUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
kVec4f_GrSLType, kHalf4_GrSLType,
kDefault_GrSLPrecision,
"Color", &colorName); "Color", &colorName);
this->emitChild(0, colorName, args); this->emitChild(0, colorName, args);
} }

View File

@ -18,7 +18,7 @@ class GrProcessorKeyBuilder;
class GrShaderCaps; class GrShaderCaps;
class GrSwizzle; class GrSwizzle;
/** Provides custom fragment shader code. Fragment processors receive an input color (float4) and /** Provides custom fragment shader code. Fragment processors receive an input color (half4) and
produce an output color. They may reference textures and uniforms. They may use produce an output color. They may reference textures and uniforms. They may use
GrCoordTransforms to receive a transformation of the local coordinates that map from local space GrCoordTransforms to receive a transformation of the local coordinates that map from local space
to the fragment being processed. to the fragment being processed.

View File

@ -37,14 +37,13 @@ public:
// Setup uniform color // Setup uniform color
const char* stagedLocalVarName; const char* stagedLocalVarName;
fColorUniform = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, fColorUniform = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
kVec4f_GrSLType, kHalf4_GrSLType,
kDefault_GrSLPrecision,
"Color", "Color",
&stagedLocalVarName); &stagedLocalVarName);
fragBuilder->codeAppendf("%s = %s;", args.fOutputColor, stagedLocalVarName); fragBuilder->codeAppendf("%s = %s;", args.fOutputColor, stagedLocalVarName);
// setup constant solid coverage // setup constant solid coverage
fragBuilder->codeAppendf("%s = float4(1);", args.fOutputCoverage); fragBuilder->codeAppendf("%s = half4(1);", args.fOutputCoverage);
} }
void emitTransforms(GrGLSLVaryingHandler* varyingHandler, void emitTransforms(GrGLSLVaryingHandler* varyingHandler,
@ -52,8 +51,8 @@ public:
int i = 0; int i = 0;
while (const GrCoordTransform* coordTransform = transformHandler->nextCoordTransform()) { while (const GrCoordTransform* coordTransform = transformHandler->nextCoordTransform()) {
GrSLType varyingType = GrSLType varyingType =
coordTransform->getMatrix().hasPerspective() ? kVec3f_GrSLType coordTransform->getMatrix().hasPerspective() ? kHalf3_GrSLType
: kVec2f_GrSLType; : kHalf2_GrSLType;
SkString strVaryingName; SkString strVaryingName;
strVaryingName.printf("TransformedCoord_%d", i); strVaryingName.printf("TransformedCoord_%d", i);
@ -89,9 +88,9 @@ public:
} }
fInstalledTransforms[t].fCurrentValue = m; fInstalledTransforms[t].fCurrentValue = m;
SkASSERT(fInstalledTransforms[t].fType == kVec2f_GrSLType || SkASSERT(fInstalledTransforms[t].fType == kHalf2_GrSLType ||
fInstalledTransforms[t].fType == kVec3f_GrSLType); fInstalledTransforms[t].fType == kHalf3_GrSLType);
unsigned components = fInstalledTransforms[t].fType == kVec2f_GrSLType ? 2 : 3; unsigned components = fInstalledTransforms[t].fType == kHalf2_GrSLType ? 2 : 3;
pd.setPathFragmentInputTransform(fInstalledTransforms[t].fHandle, components, m); pd.setPathFragmentInputTransform(fInstalledTransforms[t].fHandle, components, m);
++t; ++t;
} }

View File

@ -81,7 +81,7 @@ void GrShaderVar::setIOType(GrIOType ioType) {
} }
void GrShaderVar::appendDecl(const GrShaderCaps* shaderCaps, SkString* out) const { void GrShaderVar::appendDecl(const GrShaderCaps* shaderCaps, SkString* out) const {
SkASSERT(kDefault_GrSLPrecision == fPrecision || GrSLTypeAcceptsPrecision(fType)); SkASSERT(kDefault_GrSLPrecision == fPrecision || GrSLTypeTemporarilyAcceptsPrecision(fType));
SkString layout = fLayoutQualifier; SkString layout = fLayoutQualifier;
if (!fLayoutQualifier.isEmpty()) { if (!fLayoutQualifier.isEmpty()) {
out->appendf("layout(%s) ", fLayoutQualifier.c_str()); out->appendf("layout(%s) ", fLayoutQualifier.c_str());

View File

@ -37,13 +37,12 @@ public:
}; };
/** /**
* Defaults to a non-arry float with no precision specifier, type modifier, or layout qualifier. * Defaults to a non-arry half with no type modifier or layout qualifier.
*/ */
GrShaderVar() GrShaderVar()
: fType(kFloat_GrSLType) : fType(kHalf_GrSLType)
, fTypeModifier(kNone_TypeModifier) , fTypeModifier(kNone_TypeModifier)
, fCount(kNonArray) , fCount(kNonArray)
, fPrecision(kDefault_GrSLPrecision)
, fUseUniformFloatArrays(USE_UNIFORM_FLOAT_ARRAYS) { , fUseUniformFloatArrays(USE_UNIFORM_FLOAT_ARRAYS) {
} }
@ -116,7 +115,7 @@ public:
const char* extraModifiers = nullptr, const char* extraModifiers = nullptr,
bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) { bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) {
SkASSERT(kVoid_GrSLType != type); SkASSERT(kVoid_GrSLType != type);
SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeAcceptsPrecision(type)); SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeTemporarilyAcceptsPrecision(type));
fType = type; fType = type;
fTypeModifier = typeModifier; fTypeModifier = typeModifier;
fName = name; fName = name;
@ -140,7 +139,7 @@ public:
const char* extraModifiers = nullptr, const char* extraModifiers = nullptr,
bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) { bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) {
SkASSERT(kVoid_GrSLType != type); SkASSERT(kVoid_GrSLType != type);
SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeAcceptsPrecision(type)); SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeTemporarilyAcceptsPrecision(type));
fType = type; fType = type;
fTypeModifier = typeModifier; fTypeModifier = typeModifier;
fName = name; fName = name;
@ -165,7 +164,7 @@ public:
const char* extraModifiers = nullptr, const char* extraModifiers = nullptr,
bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) { bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) {
SkASSERT(kVoid_GrSLType != type); SkASSERT(kVoid_GrSLType != type);
SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeAcceptsPrecision(type)); SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeTemporarilyAcceptsPrecision(type));
fType = type; fType = type;
fTypeModifier = typeModifier; fTypeModifier = typeModifier;
fName = name; fName = name;
@ -190,7 +189,7 @@ public:
const char* extraModifiers = nullptr, const char* extraModifiers = nullptr,
bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) { bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) {
SkASSERT(kVoid_GrSLType != type); SkASSERT(kVoid_GrSLType != type);
SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeAcceptsPrecision(type)); SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeTemporarilyAcceptsPrecision(type));
fType = type; fType = type;
fTypeModifier = typeModifier; fTypeModifier = typeModifier;
fName = name; fName = name;

View File

@ -122,8 +122,8 @@ void PrimitiveProcessor::emitVertexShader(const GrCCPRCoverageProcessor& proc,
const TexelBufferHandle& pointsBuffer, const TexelBufferHandle& pointsBuffer,
const char* rtAdjust, GrGPArgs* gpArgs) const { const char* rtAdjust, GrGPArgs* gpArgs) const {
v->codeAppendf("int packedoffset = %s[%i];", proc.instanceAttrib(), proc.atlasOffsetIdx()); v->codeAppendf("int packedoffset = %s[%i];", proc.instanceAttrib(), proc.atlasOffsetIdx());
v->codeAppend ("highp float2 atlasoffset = float2((packedoffset<<16) >> 16, " v->codeAppend ("highfloat2 atlasoffset = highfloat2((packedoffset<<16) >> 16, "
"packedoffset >> 16);"); "packedoffset >> 16);");
this->onEmitVertexShader(proc, v, pointsBuffer, "atlasoffset", rtAdjust, gpArgs); this->onEmitVertexShader(proc, v, pointsBuffer, "atlasoffset", rtAdjust, gpArgs);
} }
@ -135,12 +135,10 @@ void PrimitiveProcessor::emitGeometryShader(const GrCCPRCoverageProcessor& proc,
SkString emitVertexFn; SkString emitVertexFn;
SkSTArray<2, GrShaderVar> emitArgs; SkSTArray<2, GrShaderVar> emitArgs;
const char* position = emitArgs.emplace_back("position", kVec2f_GrSLType, const char* position = emitArgs.emplace_back("position", kHighFloat2_GrSLType,
GrShaderVar::kNonArray, GrShaderVar::kNonArray).c_str();
kHigh_GrSLPrecision).c_str(); const char* coverage = emitArgs.emplace_back("coverage", kHighFloat_GrSLType,
const char* coverage = emitArgs.emplace_back("coverage", kFloat_GrSLType, GrShaderVar::kNonArray).c_str();
GrShaderVar::kNonArray,
kHigh_GrSLPrecision).c_str();
g->emitFunction(kVoid_GrSLType, "emitVertex", emitArgs.count(), emitArgs.begin(), [&]() { g->emitFunction(kVoid_GrSLType, "emitVertex", emitArgs.count(), emitArgs.begin(), [&]() {
SkString fnBody; SkString fnBody;
this->emitPerVertexGeometryCode(&fnBody, position, coverage, fGeomWind.c_str()); this->emitPerVertexGeometryCode(&fnBody, position, coverage, fGeomWind.c_str());
@ -151,12 +149,12 @@ void PrimitiveProcessor::emitGeometryShader(const GrCCPRCoverageProcessor& proc,
fnBody.appendf("%s = %s * %s;", fnBody.appendf("%s = %s * %s;",
fFragCoverageTimesWind.gsOut(), coverage, fGeomWind.c_str()); fFragCoverageTimesWind.gsOut(), coverage, fGeomWind.c_str());
} }
fnBody.append ("gl_Position = float4(position, 0, 1);"); fnBody.append ("gl_Position = highfloat4(position, 0, 1);");
fnBody.append ("EmitVertex();"); fnBody.append ("EmitVertex();");
return fnBody; return fnBody;
}().c_str(), &emitVertexFn); }().c_str(), &emitVertexFn);
g->codeAppendf("highp float2 bloat = %f * abs(%s.xz);", kAABloatRadius, rtAdjust); g->codeAppendf("highfloat2 bloat = %f * abs(%s.xz);", kAABloatRadius, rtAdjust);
#ifdef SK_DEBUG #ifdef SK_DEBUG
if (proc.debugVisualizationsEnabled()) { if (proc.debugVisualizationsEnabled()) {
@ -173,7 +171,7 @@ int PrimitiveProcessor::emitHullGeometry(GrGLSLGeometryBuilder* g, const char* e
SkASSERT(numSides >= 3); SkASSERT(numSides >= 3);
if (!midpoint) { if (!midpoint) {
g->codeAppendf("highp float2 midpoint = %s * float%i(%f);", g->codeAppendf("highfloat2 midpoint = %s * highfloat%i(%f);",
polygonPts, numSides, 1.0 / numSides); polygonPts, numSides, 1.0 / numSides);
midpoint = "midpoint"; midpoint = "midpoint";
} }
@ -182,42 +180,42 @@ int PrimitiveProcessor::emitHullGeometry(GrGLSLGeometryBuilder* g, const char* e
"nextidx = (%s + 1) %% %i;", "nextidx = (%s + 1) %% %i;",
wedgeIdx, numSides - 1, numSides, wedgeIdx, numSides); wedgeIdx, numSides - 1, numSides, wedgeIdx, numSides);
g->codeAppendf("highp float2 self = %s[%s];" g->codeAppendf("highfloat2 self = %s[%s];"
"highp int leftidx = %s > 0 ? previdx : nextidx;" "int leftidx = %s > 0 ? previdx : nextidx;"
"highp int rightidx = %s > 0 ? nextidx : previdx;", "int rightidx = %s > 0 ? nextidx : previdx;",
polygonPts, wedgeIdx, fGeomWind.c_str(), fGeomWind.c_str()); polygonPts, wedgeIdx, fGeomWind.c_str(), fGeomWind.c_str());
// Which quadrant does the vector from self -> right fall into? // Which quadrant does the vector from self -> right fall into?
g->codeAppendf("highp float2 right = %s[rightidx];", polygonPts); g->codeAppendf("highfloat2 right = %s[rightidx];", polygonPts);
if (3 == numSides) { if (3 == numSides) {
// TODO: evaluate perf gains. // TODO: evaluate perf gains.
g->codeAppend ("highp float2 qsr = sign(right - self);"); g->codeAppend ("highfloat2 qsr = sign(right - self);");
} else { } else {
SkASSERT(4 == numSides); SkASSERT(4 == numSides);
g->codeAppendf("highp float2 diag = %s[(%s + 2) %% 4];", polygonPts, wedgeIdx); g->codeAppendf("highfloat2 diag = %s[(%s + 2) %% 4];", polygonPts, wedgeIdx);
g->codeAppend ("highp float2 qsr = sign((right != self ? right : diag) - self);"); g->codeAppend ("highfloat2 qsr = sign((right != self ? right : diag) - self);");
} }
// Which quadrant does the vector from left -> self fall into? // Which quadrant does the vector from left -> self fall into?
g->codeAppendf("highp float2 qls = sign(self - %s[leftidx]);", polygonPts); g->codeAppendf("highfloat2 qls = sign(self - %s[leftidx]);", polygonPts);
// d2 just helps us reduce triangle counts with orthogonal, axis-aligned lines. // d2 just helps us reduce triangle counts with orthogonal, axis-aligned lines.
// TODO: evaluate perf gains. // TODO: evaluate perf gains.
const char* dr2 = "dr"; const char* dr2 = "dr";
if (3 == numSides) { if (3 == numSides) {
// TODO: evaluate perf gains. // TODO: evaluate perf gains.
g->codeAppend ("highp float2 dr = float2(qsr.y != 0 ? +qsr.y : +qsr.x, " g->codeAppend ("highfloat2 dr = highfloat2(qsr.y != 0 ? +qsr.y : +qsr.x, "
"qsr.x != 0 ? -qsr.x : +qsr.y);"); "qsr.x != 0 ? -qsr.x : +qsr.y);");
g->codeAppend ("highp float2 dr2 = float2(qsr.y != 0 ? +qsr.y : -qsr.x, " g->codeAppend ("highfloat2 dr2 = highfloat2(qsr.y != 0 ? +qsr.y : -qsr.x, "
"qsr.x != 0 ? -qsr.x : -qsr.y);"); "qsr.x != 0 ? -qsr.x : -qsr.y);");
g->codeAppend ("highp float2 dl = float2(qls.y != 0 ? +qls.y : +qls.x, " g->codeAppend ("highfloat2 dl = highfloat2(qls.y != 0 ? +qls.y : +qls.x, "
"qls.x != 0 ? -qls.x : +qls.y);"); "qls.x != 0 ? -qls.x : +qls.y);");
dr2 = "dr2"; dr2 = "dr2";
} else { } else {
g->codeAppend ("highp float2 dr = float2(qsr.y != 0 ? +qsr.y : 1, " g->codeAppend ("highfloat2 dr = highfloat2(qsr.y != 0 ? +qsr.y : 1, "
"qsr.x != 0 ? -qsr.x : 1);"); "qsr.x != 0 ? -qsr.x : 1);");
g->codeAppend ("highp float2 dl = (qls == float2(0)) ? dr : " g->codeAppend ("highfloat2 dl = (qls == highfloat2(0)) ? dr : "
"float2(qls.y != 0 ? +qls.y : 1, qls.x != 0 ? -qls.x : 1);"); "highfloat2(qls.y != 0 ? +qls.y : 1, qls.x != 0 ? -qls.x : 1);");
} }
g->codeAppendf("bool2 dnotequal = notEqual(%s, dl);", dr2); g->codeAppendf("bool2 dnotequal = notEqual(%s, dl);", dr2);
@ -230,7 +228,7 @@ int PrimitiveProcessor::emitHullGeometry(GrGLSLGeometryBuilder* g, const char* e
g->codeAppendf( "%s(self + bloat * dl, 1);", emitVertexFn); g->codeAppendf( "%s(self + bloat * dl, 1);", emitVertexFn);
g->codeAppend ("}"); g->codeAppend ("}");
g->codeAppend ("if (all(dnotequal)) {"); g->codeAppend ("if (all(dnotequal)) {");
g->codeAppendf( "%s(self + bloat * float2(-dl.y, dl.x), 1);", emitVertexFn); g->codeAppendf( "%s(self + bloat * highfloat2(-dl.y, dl.x), 1);", emitVertexFn);
g->codeAppend ("}"); g->codeAppend ("}");
g->codeAppend ("EndPrimitive();"); g->codeAppend ("EndPrimitive();");
@ -241,18 +239,18 @@ int PrimitiveProcessor::emitEdgeGeometry(GrGLSLGeometryBuilder* g, const char* e
const char* leftPt, const char* rightPt, const char* leftPt, const char* rightPt,
const char* distanceEquation) const { const char* distanceEquation) const {
if (!distanceEquation) { if (!distanceEquation) {
this->emitEdgeDistanceEquation(g, leftPt, rightPt, "highp float3 edge_distance_equation"); this->emitEdgeDistanceEquation(g, leftPt, rightPt, "highfloat3 edge_distance_equation");
distanceEquation = "edge_distance_equation"; distanceEquation = "edge_distance_equation";
} }
// qlr is defined in emitEdgeDistanceEquation. // qlr is defined in emitEdgeDistanceEquation.
g->codeAppendf("highp float2x2 endpts = float2x2(%s - bloat * qlr, %s + bloat * qlr);", g->codeAppendf("highfloat2x2 endpts = highfloat2x2(%s - bloat * qlr, %s + bloat * qlr);",
leftPt, rightPt); leftPt, rightPt);
g->codeAppendf("mediump float2 endpts_coverage = %s.xy * endpts + %s.z;", g->codeAppendf("half2 endpts_coverage = %s.xy * endpts + %s.z;",
distanceEquation, distanceEquation); distanceEquation, distanceEquation);
// d1 is defined in emitEdgeDistanceEquation. // d1 is defined in emitEdgeDistanceEquation.
g->codeAppend ("highp float2 d2 = d1;"); g->codeAppend ("highfloat2 d2 = d1;");
g->codeAppend ("bool aligned = qlr.x == 0 || qlr.y == 0;"); g->codeAppend ("bool aligned = qlr.x == 0 || qlr.y == 0;");
g->codeAppend ("if (aligned) {"); g->codeAppend ("if (aligned) {");
g->codeAppend ( "d1 -= qlr;"); g->codeAppend ( "d1 -= qlr;");
@ -281,25 +279,25 @@ void PrimitiveProcessor::emitEdgeDistanceEquation(GrGLSLGeometryBuilder* g,
const char* leftPt, const char* rightPt, const char* leftPt, const char* rightPt,
const char* outputDistanceEquation) const { const char* outputDistanceEquation) const {
// Which quadrant does the vector from left -> right fall into? // Which quadrant does the vector from left -> right fall into?
g->codeAppendf("highp float2 qlr = sign(%s - %s);", rightPt, leftPt); g->codeAppendf("highfloat2 qlr = sign(%s - %s);", rightPt, leftPt);
g->codeAppend ("highp float2 d1 = float2(qlr.y, -qlr.x);"); g->codeAppend ("highfloat2 d1 = highfloat2(qlr.y, -qlr.x);");
g->codeAppendf("highp float2 n = float2(%s.y - %s.y, %s.x - %s.x);", g->codeAppendf("highfloat2 n = highfloat2(%s.y - %s.y, %s.x - %s.x);",
rightPt, leftPt, leftPt, rightPt); rightPt, leftPt, leftPt, rightPt);
g->codeAppendf("highp float2 kk = n * float2x2(%s + bloat * d1, %s - bloat * d1);", g->codeAppendf("highfloat2 kk = n * highfloat2x2(%s + bloat * d1, %s - bloat * d1);",
leftPt, leftPt); leftPt, leftPt);
// Clamp for when n=0. wind=0 when n=0 so as long as we don't get Inf or NaN we are fine. // Clamp for when n=0. wind=0 when n=0 so as long as we don't get Inf or NaN we are fine.
g->codeAppendf("highp float scale = 1 / max(kk[0] - kk[1], 1e-30);"); g->codeAppendf("highfloat scale = 1 / max(kk[0] - kk[1], 1e-30);");
g->codeAppendf("%s = float3(-n, kk[1]) * scale;", outputDistanceEquation); g->codeAppendf("%s = half3(-n, kk[1]) * scale;", outputDistanceEquation);
} }
int PrimitiveProcessor::emitCornerGeometry(GrGLSLGeometryBuilder* g, const char* emitVertexFn, int PrimitiveProcessor::emitCornerGeometry(GrGLSLGeometryBuilder* g, const char* emitVertexFn,
const char* pt) const { const char* pt) const {
g->codeAppendf("%s(%s + float2(-bloat.x, -bloat.y), 1);", emitVertexFn, pt); g->codeAppendf("%s(%s + highfloat2(-bloat.x, -bloat.y), 1);", emitVertexFn, pt);
g->codeAppendf("%s(%s + float2(-bloat.x, +bloat.y), 1);", emitVertexFn, pt); g->codeAppendf("%s(%s + highfloat2(-bloat.x, +bloat.y), 1);", emitVertexFn, pt);
g->codeAppendf("%s(%s + float2(+bloat.x, -bloat.y), 1);", emitVertexFn, pt); g->codeAppendf("%s(%s + highfloat2(+bloat.x, -bloat.y), 1);", emitVertexFn, pt);
g->codeAppendf("%s(%s + float2(+bloat.x, +bloat.y), 1);", emitVertexFn, pt); g->codeAppendf("%s(%s + highfloat2(+bloat.x, +bloat.y), 1);", emitVertexFn, pt);
g->codeAppend ("EndPrimitive();"); g->codeAppend ("EndPrimitive();");
return 4; return 4;
@ -315,17 +313,17 @@ void PrimitiveProcessor::emitCoverage(const GrCCPRCoverageProcessor& proc, GrGLS
f->codeAppendf("%s.a = %s;", outputColor, fFragCoverageTimesWind.fsIn()); f->codeAppendf("%s.a = %s;", outputColor, fFragCoverageTimesWind.fsIn());
break; break;
case CoverageType::kShader: case CoverageType::kShader:
f->codeAppendf("mediump float coverage = 0;"); f->codeAppendf("half coverage = 0;");
this->emitShaderCoverage(f, "coverage"); this->emitShaderCoverage(f, "coverage");
f->codeAppendf("%s.a = coverage * %s;", outputColor, fFragWind.fsIn()); f->codeAppendf("%s.a = coverage * %s;", outputColor, fFragWind.fsIn());
break; break;
} }
f->codeAppendf("%s = float4(1);", outputCoverage); f->codeAppendf("%s = half4(1);", outputCoverage);
#ifdef SK_DEBUG #ifdef SK_DEBUG
if (proc.debugVisualizationsEnabled()) { if (proc.debugVisualizationsEnabled()) {
f->codeAppendf("%s = float4(-%s.a, %s.a, 0, 1);", outputColor, outputColor, outputColor); f->codeAppendf("%s = half4(-%s.a, %s.a, 0, 1);", outputColor, outputColor, outputColor);
} }
#endif #endif
} }
@ -334,17 +332,17 @@ int PrimitiveProcessor::defineSoftSampleLocations(GrGLSLFragmentBuilder* f,
const char* samplesName) const { const char* samplesName) const {
// Standard DX11 sample locations. // Standard DX11 sample locations.
#if defined(SK_BUILD_FOR_ANDROID) || defined(SK_BUILD_FOR_IOS) #if defined(SK_BUILD_FOR_ANDROID) || defined(SK_BUILD_FOR_IOS)
f->defineConstant("highp float2[8]", samplesName, "float2[8](" f->defineConstant("highfloat2[8]", samplesName, "highfloat2[8]("
"float2(+1, -3)/16, float2(-1, +3)/16, float2(+5, +1)/16, float2(-3, -5)/16, " "highfloat2(+1, -3)/16, highfloat2(-1, +3)/16, highfloat2(+5, +1)/16, highfloat2(-3, -5)/16, "
"float2(-5, +5)/16, float2(-7, -1)/16, float2(+3, +7)/16, float2(+7, -7)/16." "highfloat2(-5, +5)/16, highfloat2(-7, -1)/16, highfloat2(+3, +7)/16, highfloat2(+7, -7)/16."
")"); ")");
return 8; return 8;
#else #else
f->defineConstant("highp float2[16]", samplesName, "float2[16](" f->defineConstant("highfloat2[16]", samplesName, "highfloat2[16]("
"float2(+1, +1)/16, float2(-1, -3)/16, float2(-3, +2)/16, float2(+4, -1)/16, " "highfloat2(+1, +1)/16, highfloat2(-1, -3)/16, highfloat2(-3, +2)/16, highfloat2(+4, -1)/16, "
"float2(-5, -2)/16, float2(+2, +5)/16, float2(+5, +3)/16, float2(+3, -5)/16, " "highfloat2(-5, -2)/16, highfloat2(+2, +5)/16, highfloat2(+5, +3)/16, highfloat2(+3, -5)/16, "
"float2(-2, +6)/16, float2( 0, -7)/16, float2(-4, -6)/16, float2(-6, +4)/16, " "highfloat2(-2, +6)/16, highfloat2( 0, -7)/16, highfloat2(-4, -6)/16, highfloat2(-6, +4)/16, "
"float2(-8, 0)/16, float2(+7, -4)/16, float2(+6, +7)/16, float2(-7, -8)/16." "highfloat2(-8, 0)/16, highfloat2(+7, -4)/16, highfloat2(+6, +7)/16, highfloat2(-7, -8)/16."
")"); ")");
return 16; return 16;
#endif #endif

View File

@ -133,9 +133,9 @@ protected:
PrimitiveProcessor(CoverageType coverageType) PrimitiveProcessor(CoverageType coverageType)
: fCoverageType(coverageType) : fCoverageType(coverageType)
, fGeomWind("wind", kFloat_GrSLType, GrShaderVar::kNonArray, kLow_GrSLPrecision) , fGeomWind("wind", kHalf_GrSLType, GrShaderVar::kNonArray, kLow_GrSLPrecision)
, fFragWind(kFloat_GrSLType) , fFragWind(kHalf_GrSLType)
, fFragCoverageTimesWind(kFloat_GrSLType) {} , fFragCoverageTimesWind(kHalf_GrSLType) {}
// Called before generating shader code. Subclass should add its custom varyings to the handler // Called before generating shader code. Subclass should add its custom varyings to the handler
// and update its corresponding internal member variables. // and update its corresponding internal member variables.

View File

@ -16,18 +16,18 @@ void GrCCPRCubicProcessor::onEmitVertexShader(const GrCCPRCoverageProcessor& pro
const TexelBufferHandle& pointsBuffer, const TexelBufferHandle& pointsBuffer,
const char* atlasOffset, const char* rtAdjust, const char* atlasOffset, const char* rtAdjust,
GrGPArgs* gpArgs) const { GrGPArgs* gpArgs) const {
v->codeAppend ("highp float2 self = "); v->codeAppend ("highfloat2 self = ");
v->appendTexelFetch(pointsBuffer, v->appendTexelFetch(pointsBuffer,
SkStringPrintf("%s.x + sk_VertexID", proc.instanceAttrib()).c_str()); SkStringPrintf("%s.x + sk_VertexID", proc.instanceAttrib()).c_str());
v->codeAppendf(".xy + %s;", atlasOffset); v->codeAppendf(".xy + %s;", atlasOffset);
gpArgs->fPositionVar.set(kVec2f_GrSLType, "self"); gpArgs->fPositionVar.set(kHighFloat2_GrSLType, "self");
} }
void GrCCPRCubicProcessor::emitWind(GrGLSLGeometryBuilder* g, const char* rtAdjust, void GrCCPRCubicProcessor::emitWind(GrGLSLGeometryBuilder* g, const char* rtAdjust,
const char* outputWind) const { const char* outputWind) const {
// We will define bezierpts in onEmitGeometryShader. // We will define bezierpts in onEmitGeometryShader.
g->codeAppend ("highp float area_times_2 = " g->codeAppend ("highfloat area_times_2 = "
"determinant(float3x3(1, bezierpts[0], " "determinant(highfloat3x3(1, bezierpts[0], "
"1, bezierpts[2], " "1, bezierpts[2], "
"0, bezierpts[3] - bezierpts[1]));"); "0, bezierpts[3] - bezierpts[1]));");
// Drop curves that are nearly flat. The KLM math becomes unstable in this case. // Drop curves that are nearly flat. The KLM math becomes unstable in this case.
@ -46,61 +46,61 @@ void GrCCPRCubicProcessor::emitWind(GrGLSLGeometryBuilder* g, const char* rtAdju
void GrCCPRCubicProcessor::onEmitGeometryShader(GrGLSLGeometryBuilder* g, const char* emitVertexFn, void GrCCPRCubicProcessor::onEmitGeometryShader(GrGLSLGeometryBuilder* g, const char* emitVertexFn,
const char* wind, const char* rtAdjust) const { const char* wind, const char* rtAdjust) const {
// Prepend bezierpts at the start of the shader. // Prepend bezierpts at the start of the shader.
g->codePrependf("highp float4x2 bezierpts = float4x2(sk_in[0].gl_Position.xy, " g->codePrependf("highfloat4x2 bezierpts = highfloat4x2(sk_in[0].gl_Position.xy, "
"sk_in[1].gl_Position.xy, " "sk_in[1].gl_Position.xy, "
"sk_in[2].gl_Position.xy, " "sk_in[2].gl_Position.xy, "
"sk_in[3].gl_Position.xy);"); "sk_in[3].gl_Position.xy);");
// Evaluate the cubic at T=.5 for an mid-ish point. // Evaluate the cubic at T=.5 for an mid-ish point.
g->codeAppendf("highp float2 midpoint = bezierpts * float4(.125, .375, .375, .125);"); g->codeAppendf("highfloat2 midpoint = bezierpts * highfloat4(.125, .375, .375, .125);");
// Find the cubic's power basis coefficients. // Find the cubic's power basis coefficients.
g->codeAppend ("highp float2x4 C = float4x4(-1, 3, -3, 1, " g->codeAppend ("highfloat2x4 C = highfloat4x4(-1, 3, -3, 1, "
" 3, -6, 3, 0, " " 3, -6, 3, 0, "
"-3, 3, 0, 0, " "-3, 3, 0, 0, "
" 1, 0, 0, 0) * transpose(bezierpts);"); " 1, 0, 0, 0) * transpose(bezierpts);");
// Find the cubic's inflection function. // Find the cubic's inflection function.
g->codeAppend ("highp float D3 = +determinant(float2x2(C[0].yz, C[1].yz));"); g->codeAppend ("highfloat D3 = +determinant(highfloat2x2(C[0].yz, C[1].yz));");
g->codeAppend ("highp float D2 = -determinant(float2x2(C[0].xz, C[1].xz));"); g->codeAppend ("highfloat D2 = -determinant(highfloat2x2(C[0].xz, C[1].xz));");
g->codeAppend ("highp float D1 = +determinant(float2x2(C));"); g->codeAppend ("highfloat D1 = +determinant(highfloat2x2(C));");
// Calculate the KLM matrix. // Calculate the KLM matrix.
g->declareGlobal(fKLMMatrix); g->declareGlobal(fKLMMatrix);
g->codeAppend ("highp float4 K, L, M;"); g->codeAppend ("highfloat4 K, L, M;");
g->codeAppend ("highp float2 l, m;"); g->codeAppend ("highfloat2 l, m;");
g->codeAppend ("highp float discr = 3*D2*D2 - 4*D1*D3;"); g->codeAppend ("highfloat discr = 3*D2*D2 - 4*D1*D3;");
if (CubicType::kSerpentine == fCubicType) { if (CubicType::kSerpentine == fCubicType) {
// This math also works out for the "cusp" and "cusp at infinity" cases. // This math also works out for the "cusp" and "cusp at infinity" cases.
g->codeAppend ("highp float q = 3*D2 + sign(D2) * sqrt(max(3*discr, 0));"); g->codeAppend ("highfloat q = 3*D2 + sign(D2) * sqrt(max(3*discr, 0));");
g->codeAppend ("l.ts = normalize(float2(q, 6*D1));"); g->codeAppend ("l.ts = normalize(highfloat2(q, 6*D1));");
g->codeAppend ("m.ts = discr <= 0 ? l.ts : normalize(float2(2*D3, q));"); g->codeAppend ("m.ts = discr <= 0 ? l.ts : normalize(highfloat2(2*D3, q));");
g->codeAppend ("K = float4(0, l.s * m.s, -l.t * m.s - m.t * l.s, l.t * m.t);"); g->codeAppend ("K = highfloat4(0, l.s * m.s, -l.t * m.s - m.t * l.s, l.t * m.t);");
g->codeAppend ("L = float4(-1,3,-3,1) * l.ssst * l.sstt * l.sttt;"); g->codeAppend ("L = highfloat4(-1,3,-3,1) * l.ssst * l.sstt * l.sttt;");
g->codeAppend ("M = float4(-1,3,-3,1) * m.ssst * m.sstt * m.sttt;"); g->codeAppend ("M = highfloat4(-1,3,-3,1) * m.ssst * m.sstt * m.sttt;");
} else { } else {
g->codeAppend ("highp float q = D2 + sign(D2) * sqrt(max(-discr, 0));"); g->codeAppend ("highfloat q = D2 + sign(D2) * sqrt(max(-discr, 0));");
g->codeAppend ("l.ts = normalize(float2(q, 2*D1));"); g->codeAppend ("l.ts = normalize(highfloat2(q, 2*D1));");
g->codeAppend ("m.ts = discr >= 0 ? l.ts : normalize(float2(2 * (D2*D2 - D3*D1), D1*q));"); g->codeAppend ("m.ts = discr >= 0 ? l.ts : normalize(highfloat2(2 * (D2*D2 - D3*D1), D1*q));");
g->codeAppend ("highp float4 lxm = float4(l.s * m.s, l.s * m.t, l.t * m.s, l.t * m.t);"); g->codeAppend ("highfloat4 lxm = highfloat4(l.s * m.s, l.s * m.t, l.t * m.s, l.t * m.t);");
g->codeAppend ("K = float4(0, lxm.x, -lxm.y - lxm.z, lxm.w);"); g->codeAppend ("K = highfloat4(0, lxm.x, -lxm.y - lxm.z, lxm.w);");
g->codeAppend ("L = float4(-1,1,-1,1) * l.sstt * (lxm.xyzw + float4(0, 2*lxm.zy, 0));"); g->codeAppend ("L = highfloat4(-1,1,-1,1) * l.sstt * (lxm.xyzw + highfloat4(0, 2*lxm.zy, 0));");
g->codeAppend ("M = float4(-1,1,-1,1) * m.sstt * (lxm.xzyw + float4(0, 2*lxm.yz, 0));"); g->codeAppend ("M = highfloat4(-1,1,-1,1) * m.sstt * (lxm.xzyw + highfloat4(0, 2*lxm.yz, 0));");
} }
g->codeAppend ("lowp int middlerow = abs(D2) > abs(D1) ? 2 : 1;"); g->codeAppend ("short middlerow = abs(D2) > abs(D1) ? 2 : 1;");
g->codeAppend ("highp float3x3 CI = inverse(float3x3(C[0][0], C[0][middlerow], C[0][3], " g->codeAppend ("highfloat3x3 CI = inverse(highfloat3x3(C[0][0], C[0][middlerow], C[0][3], "
"C[1][0], C[1][middlerow], C[1][3], " "C[1][0], C[1][middlerow], C[1][3], "
" 0, 0, 1));"); " 0, 0, 1));");
g->codeAppendf("%s = CI * float3x3(K[0], K[middlerow], K[3], " g->codeAppendf("%s = CI * highfloat3x3(K[0], K[middlerow], K[3], "
"L[0], L[middlerow], L[3], " "L[0], L[middlerow], L[3], "
"M[0], M[middlerow], M[3]);", fKLMMatrix.c_str()); "M[0], M[middlerow], M[3]);", fKLMMatrix.c_str());
// Orient the KLM matrix so we fill the correct side of the curve. // Orient the KLM matrix so we fill the correct side of the curve.
g->codeAppendf("lowp float2 orientation = sign(float3(midpoint, 1) * float2x3(%s[1], %s[2]));", g->codeAppendf("half2 orientation = sign(half3(midpoint, 1) * half2x3(%s[1], %s[2]));",
fKLMMatrix.c_str(), fKLMMatrix.c_str()); fKLMMatrix.c_str(), fKLMMatrix.c_str());
g->codeAppendf("%s *= float3x3(orientation[0] * orientation[1], 0, 0, " g->codeAppendf("%s *= highfloat3x3(orientation[0] * orientation[1], 0, 0, "
"0, orientation[0], 0, " "0, orientation[0], 0, "
"0, 0, orientation[1]);", fKLMMatrix.c_str()); "0, 0, orientation[1]);", fKLMMatrix.c_str());
g->declareGlobal(fKLMDerivatives); g->declareGlobal(fKLMDerivatives);
g->codeAppendf("%s[0] = %s[0].xy * %s.xz;", g->codeAppendf("%s[0] = %s[0].xy * %s.xz;",
@ -112,9 +112,9 @@ void GrCCPRCubicProcessor::onEmitGeometryShader(GrGLSLGeometryBuilder* g, const
// Determine the amount of additional coverage to subtract out for the flat edge (P3 -> P0). // Determine the amount of additional coverage to subtract out for the flat edge (P3 -> P0).
g->declareGlobal(fEdgeDistanceEquation); g->declareGlobal(fEdgeDistanceEquation);
g->codeAppendf("int edgeidx0 = %s > 0 ? 3 : 0;", wind); g->codeAppendf("short edgeidx0 = %s > 0 ? 3 : 0;", wind);
g->codeAppendf("highp float2 edgept0 = bezierpts[edgeidx0];"); g->codeAppendf("highfloat2 edgept0 = bezierpts[edgeidx0];");
g->codeAppendf("highp float2 edgept1 = bezierpts[3 - edgeidx0];"); g->codeAppendf("highfloat2 edgept1 = bezierpts[3 - edgeidx0];");
this->emitEdgeDistanceEquation(g, "edgept0", "edgept1", fEdgeDistanceEquation.c_str()); this->emitEdgeDistanceEquation(g, "edgept0", "edgept1", fEdgeDistanceEquation.c_str());
this->emitCubicGeometry(g, emitVertexFn, wind, rtAdjust); this->emitCubicGeometry(g, emitVertexFn, wind, rtAdjust);
@ -123,10 +123,10 @@ void GrCCPRCubicProcessor::onEmitGeometryShader(GrGLSLGeometryBuilder* g, const
void GrCCPRCubicProcessor::emitPerVertexGeometryCode(SkString* fnBody, const char* position, void GrCCPRCubicProcessor::emitPerVertexGeometryCode(SkString* fnBody, const char* position,
const char* /*coverage*/, const char* /*coverage*/,
const char* /*wind*/) const { const char* /*wind*/) const {
fnBody->appendf("highp float3 klm = float3(%s, 1) * %s;", position, fKLMMatrix.c_str()); fnBody->appendf("highfloat3 klm = highfloat3(%s, 1) * %s;", position, fKLMMatrix.c_str());
fnBody->appendf("highp float d = dot(float3(%s, 1), %s);", fnBody->appendf("highfloat d = dot(float3(%s, 1), %s);",
position, fEdgeDistanceEquation.c_str()); position, fEdgeDistanceEquation.c_str());
fnBody->appendf("%s = float4(klm, d);", fKLMD.gsOut()); fnBody->appendf("%s = highfloat4(klm, d);", fKLMD.gsOut());
this->onEmitPerVertexGeometryCode(fnBody); this->onEmitPerVertexGeometryCode(fnBody);
} }
@ -150,10 +150,10 @@ void GrCCPRCubicHullProcessor::onEmitPerVertexGeometryCode(SkString* fnBody) con
void GrCCPRCubicHullProcessor::emitShaderCoverage(GrGLSLFragmentBuilder* f, void GrCCPRCubicHullProcessor::emitShaderCoverage(GrGLSLFragmentBuilder* f,
const char* outputCoverage) const { const char* outputCoverage) const {
f->codeAppendf("highp float k = %s.x, l = %s.y, m = %s.z, d = %s.w;", f->codeAppendf("highfloat k = %s.x, l = %s.y, m = %s.z, d = %s.w;",
fKLMD.fsIn(), fKLMD.fsIn(), fKLMD.fsIn(), fKLMD.fsIn()); fKLMD.fsIn(), fKLMD.fsIn(), fKLMD.fsIn(), fKLMD.fsIn());
f->codeAppend ("highp float f = k*k*k - l*m;"); f->codeAppend ("highfloat f = k*k*k - l*m;");
f->codeAppendf("highp float2 grad_f = %s * float2(k, 1);", fGradMatrix.fsIn()); f->codeAppendf("highfloat2 grad_f = %s * highfloat2(k, 1);", fGradMatrix.fsIn());
f->codeAppendf("%s = clamp(0.5 - f * inversesqrt(dot(grad_f, grad_f)), 0, 1);", outputCoverage); f->codeAppendf("%s = clamp(0.5 - f * inversesqrt(dot(grad_f, grad_f)), 0, 1);", outputCoverage);
f->codeAppendf("%s += min(d, 0);", outputCoverage); // Flat closing edge. f->codeAppendf("%s += min(d, 0);", outputCoverage); // Flat closing edge.
} }
@ -166,7 +166,7 @@ void GrCCPRCubicCornerProcessor::emitCubicGeometry(GrGLSLGeometryBuilder* g,
g->codeAppendf("%s = %s.xy * %s.xz;", g->codeAppendf("%s = %s.xy * %s.xz;",
fEdgeDistanceDerivatives.c_str(), fEdgeDistanceEquation.c_str(), rtAdjust); fEdgeDistanceDerivatives.c_str(), fEdgeDistanceEquation.c_str(), rtAdjust);
g->codeAppendf("highp float2 corner = bezierpts[sk_InvocationID * 3];"); g->codeAppendf("highfloat2 corner = bezierpts[sk_InvocationID * 3];");
int numVertices = this->emitCornerGeometry(g, emitVertexFn, "corner"); int numVertices = this->emitCornerGeometry(g, emitVertexFn, "corner");
g->configure(GrGLSLGeometryBuilder::InputType::kLinesAdjacency, g->configure(GrGLSLGeometryBuilder::InputType::kLinesAdjacency,
@ -174,10 +174,10 @@ void GrCCPRCubicCornerProcessor::emitCubicGeometry(GrGLSLGeometryBuilder* g,
} }
void GrCCPRCubicCornerProcessor::onEmitPerVertexGeometryCode(SkString* fnBody) const { void GrCCPRCubicCornerProcessor::onEmitPerVertexGeometryCode(SkString* fnBody) const {
fnBody->appendf("%s = float4(%s[0].x, %s[1].x, %s[2].x, %s.x);", fnBody->appendf("%s = highfloat4(%s[0].x, %s[1].x, %s[2].x, %s.x);",
fdKLMDdx.gsOut(), fKLMDerivatives.c_str(), fKLMDerivatives.c_str(), fdKLMDdx.gsOut(), fKLMDerivatives.c_str(), fKLMDerivatives.c_str(),
fKLMDerivatives.c_str(), fEdgeDistanceDerivatives.c_str()); fKLMDerivatives.c_str(), fEdgeDistanceDerivatives.c_str());
fnBody->appendf("%s = float4(%s[0].y, %s[1].y, %s[2].y, %s.y);", fnBody->appendf("%s = highfloat4(%s[0].y, %s[1].y, %s[2].y, %s.y);",
fdKLMDdy.gsOut(), fKLMDerivatives.c_str(), fKLMDerivatives.c_str(), fdKLMDdy.gsOut(), fKLMDerivatives.c_str(), fKLMDerivatives.c_str(),
fKLMDerivatives.c_str(), fEdgeDistanceDerivatives.c_str()); fKLMDerivatives.c_str(), fEdgeDistanceDerivatives.c_str());
@ -187,28 +187,28 @@ void GrCCPRCubicCornerProcessor::onEmitPerVertexGeometryCode(SkString* fnBody) c
void GrCCPRCubicCornerProcessor::emitShaderCoverage(GrGLSLFragmentBuilder* f, void GrCCPRCubicCornerProcessor::emitShaderCoverage(GrGLSLFragmentBuilder* f,
const char* outputCoverage) const { const char* outputCoverage) const {
f->codeAppendf("highp float2x4 grad_klmd = float2x4(%s, %s);", f->codeAppendf("highfloat2x4 grad_klmd = highfloat2x4(%s, %s);",
fdKLMDdx.fsIn(), fdKLMDdy.fsIn()); fdKLMDdx.fsIn(), fdKLMDdy.fsIn());
// Erase what the previous hull shader wrote. We don't worry about the two corners falling on // Erase what the previous hull shader wrote. We don't worry about the two corners falling on
// the same pixel because those cases should have been weeded out by this point. // the same pixel because those cases should have been weeded out by this point.
f->codeAppendf("highp float k = %s.x, l = %s.y, m = %s.z, d = %s.w;", f->codeAppendf("highfloat k = %s.x, l = %s.y, m = %s.z, d = %s.w;",
fKLMD.fsIn(), fKLMD.fsIn(), fKLMD.fsIn(), fKLMD.fsIn()); fKLMD.fsIn(), fKLMD.fsIn(), fKLMD.fsIn(), fKLMD.fsIn());
f->codeAppend ("highp float f = k*k*k - l*m;"); f->codeAppend ("highfloat f = k*k*k - l*m;");
f->codeAppend ("highp float2 grad_f = float3(3*k*k, -m, -l) * float2x3(grad_klmd);"); f->codeAppend ("highfloat2 grad_f = highfloat3(3*k*k, -m, -l) * highfloat2x3(grad_klmd);");
f->codeAppendf("%s = -clamp(0.5 - f * inversesqrt(dot(grad_f, grad_f)), 0, 1);", f->codeAppendf("%s = -clamp(0.5 - f * inversesqrt(dot(grad_f, grad_f)), 0, 1);",
outputCoverage); outputCoverage);
f->codeAppendf("%s -= d;", outputCoverage); f->codeAppendf("%s -= d;", outputCoverage);
// Use software msaa to estimate actual coverage at the corner pixels. // Use software msaa to estimate actual coverage at the corner pixels.
const int sampleCount = this->defineSoftSampleLocations(f, "samples"); const int sampleCount = this->defineSoftSampleLocations(f, "samples");
f->codeAppendf("highp float4 klmd_center = float4(%s.xyz, %s.w + 0.5);", f->codeAppendf("highfloat4 klmd_center = float4(%s.xyz, %s.w + 0.5);",
fKLMD.fsIn(), fKLMD.fsIn()); fKLMD.fsIn(), fKLMD.fsIn());
f->codeAppendf("for (int i = 0; i < %i; ++i) {", sampleCount); f->codeAppendf("for (int i = 0; i < %i; ++i) {", sampleCount);
f->codeAppend ( "highp float4 klmd = grad_klmd * samples[i] + klmd_center;"); f->codeAppend ( "highfloat4 klmd = grad_klmd * samples[i] + klmd_center;");
f->codeAppend ( "lowp float f = klmd.y * klmd.z - klmd.x * klmd.x * klmd.x;"); f->codeAppend ( "half f = klmd.y * klmd.z - klmd.x * klmd.x * klmd.x;");
f->codeAppendf( "%s += all(greaterThan(float4(f, klmd.y, klmd.z, klmd.w), " f->codeAppendf( "%s += all(greaterThan(half4(f, klmd.y, klmd.z, klmd.w), "
"float4(0))) ? %f : 0;", "half4(0))) ? %f : 0;",
outputCoverage, 1.0 / sampleCount); outputCoverage, 1.0 / sampleCount);
f->codeAppend ("}"); f->codeAppend ("}");
} }

View File

@ -33,12 +33,12 @@ public:
GrCCPRCubicProcessor(CubicType cubicType) GrCCPRCubicProcessor(CubicType cubicType)
: INHERITED(CoverageType::kShader) : INHERITED(CoverageType::kShader)
, fCubicType(cubicType) , fCubicType(cubicType)
, fKLMMatrix("klm_matrix", kMat33f_GrSLType, GrShaderVar::kNonArray, , fKLMMatrix("klm_matrix", kHighFloat3x3_GrSLType, GrShaderVar::kNonArray,
kHigh_GrSLPrecision) kHigh_GrSLPrecision)
, fKLMDerivatives("klm_derivatives", kVec2f_GrSLType, 3, kHigh_GrSLPrecision) , fKLMDerivatives("klm_derivatives", kHighFloat2_GrSLType, 3, kHigh_GrSLPrecision)
, fEdgeDistanceEquation("edge_distance_equation", kVec3f_GrSLType, , fEdgeDistanceEquation("edge_distance_equation", kHighFloat3_GrSLType,
GrShaderVar::kNonArray, kHigh_GrSLPrecision) GrShaderVar::kNonArray, kHigh_GrSLPrecision)
, fKLMD(kVec4f_GrSLType) {} , fKLMD(kHighFloat4_GrSLType) {}
void resetVaryings(GrGLSLVaryingHandler* varyingHandler) override { void resetVaryings(GrGLSLVaryingHandler* varyingHandler) override {
varyingHandler->addVarying("klmd", &fKLMD, kHigh_GrSLPrecision); varyingHandler->addVarying("klmd", &fKLMD, kHigh_GrSLPrecision);
@ -71,7 +71,7 @@ class GrCCPRCubicHullProcessor : public GrCCPRCubicProcessor {
public: public:
GrCCPRCubicHullProcessor(CubicType cubicType) GrCCPRCubicHullProcessor(CubicType cubicType)
: INHERITED(cubicType) : INHERITED(cubicType)
, fGradMatrix(kMat22f_GrSLType) {} , fGradMatrix(kHighFloat2x2_GrSLType) {}
void resetVaryings(GrGLSLVaryingHandler* varyingHandler) override { void resetVaryings(GrGLSLVaryingHandler* varyingHandler) override {
this->INHERITED::resetVaryings(varyingHandler); this->INHERITED::resetVaryings(varyingHandler);
@ -93,10 +93,10 @@ class GrCCPRCubicCornerProcessor : public GrCCPRCubicProcessor {
public: public:
GrCCPRCubicCornerProcessor(CubicType cubicType) GrCCPRCubicCornerProcessor(CubicType cubicType)
: INHERITED(cubicType) : INHERITED(cubicType)
, fEdgeDistanceDerivatives("edge_distance_derivatives", kVec2f_GrSLType, , fEdgeDistanceDerivatives("edge_distance_derivatives", kHighFloat2_GrSLType,
GrShaderVar::kNonArray, kHigh_GrSLPrecision) GrShaderVar::kNonArray, kHigh_GrSLPrecision)
, fdKLMDdx(kVec4f_GrSLType) , fdKLMDdx(kHighFloat4_GrSLType)
, fdKLMDdy(kVec4f_GrSLType) {} , fdKLMDdy(kHighFloat4_GrSLType) {}
void resetVaryings(GrGLSLVaryingHandler* varyingHandler) override { void resetVaryings(GrGLSLVaryingHandler* varyingHandler) override {
this->INHERITED::resetVaryings(varyingHandler); this->INHERITED::resetVaryings(varyingHandler);

View File

@ -121,12 +121,12 @@ void GLSLPathProcessor::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
const char* atlasAdjust; const char* atlasAdjust;
fAtlasAdjustUniform = uniHandler->addUniform( fAtlasAdjustUniform = uniHandler->addUniform(
kVertex_GrShaderFlag, kVertex_GrShaderFlag,
kVec2f_GrSLType, kHigh_GrSLPrecision, "atlas_adjust", &atlasAdjust); kHighFloat2_GrSLType, "atlas_adjust", &atlasAdjust);
varyingHandler->emitAttributes(proc); varyingHandler->emitAttributes(proc);
GrGLSLVertToFrag texcoord(kVec2f_GrSLType); GrGLSLVertToFrag texcoord(kHighFloat2_GrSLType);
GrGLSLVertToFrag color(kVec4f_GrSLType); GrGLSLVertToFrag color(kHalf4_GrSLType);
varyingHandler->addVarying("texcoord", &texcoord, kHigh_GrSLPrecision); varyingHandler->addVarying("texcoord", &texcoord, kHigh_GrSLPrecision);
varyingHandler->addFlatPassThroughAttribute(&proc.getInstanceAttrib(InstanceAttribs::kColor), varyingHandler->addFlatPassThroughAttribute(&proc.getInstanceAttrib(InstanceAttribs::kColor),
args.fOutputColor, kLow_GrSLPrecision); args.fOutputColor, kLow_GrSLPrecision);
@ -137,41 +137,41 @@ void GLSLPathProcessor::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
// Find the intersections of (bloated) devBounds and devBounds45 in order to come up with an // Find the intersections of (bloated) devBounds and devBounds45 in order to come up with an
// octagon that circumscribes the (bloated) path. A vertex is the intersection of two lines: // octagon that circumscribes the (bloated) path. A vertex is the intersection of two lines:
// one edge from the path's bounding box and one edge from its 45-degree bounding box. // one edge from the path's bounding box and one edge from its 45-degree bounding box.
v->codeAppendf("highp float2x2 N = float2x2(%s);", proc.getEdgeNormsAttrib().fName); v->codeAppendf("highfloat2x2 N = highfloat2x2(%s);", proc.getEdgeNormsAttrib().fName);
// N[0] is the normal for the edge we are intersecting from the regular bounding box, pointing // N[0] is the normal for the edge we are intersecting from the regular bounding box, pointing
// out of the octagon. // out of the octagon.
v->codeAppendf("highp float2 refpt = (min(N[0].x, N[0].y) < 0) ? %s.xy : %s.zw;", v->codeAppendf("highfloat2 refpt = (min(N[0].x, N[0].y) < 0) ? %s.xy : %s.zw;",
proc.getInstanceAttrib(InstanceAttribs::kDevBounds).fName, proc.getInstanceAttrib(InstanceAttribs::kDevBounds).fName,
proc.getInstanceAttrib(InstanceAttribs::kDevBounds).fName); proc.getInstanceAttrib(InstanceAttribs::kDevBounds).fName);
v->codeAppendf("refpt += N[0] * %f;", kAABloatRadius); // bloat for AA. v->codeAppendf("refpt += N[0] * %f;", kAABloatRadius); // bloat for AA.
// N[1] is the normal for the edge we are intersecting from the 45-degree bounding box, pointing // N[1] is the normal for the edge we are intersecting from the 45-degree bounding box, pointing
// out of the octagon. // out of the octagon.
v->codeAppendf("highp float2 refpt45 = (N[1].x < 0) ? %s.xy : %s.zw;", v->codeAppendf("highfloat2 refpt45 = (N[1].x < 0) ? %s.xy : %s.zw;",
proc.getInstanceAttrib(InstanceAttribs::kDevBounds45).fName, proc.getInstanceAttrib(InstanceAttribs::kDevBounds45).fName,
proc.getInstanceAttrib(InstanceAttribs::kDevBounds45).fName); proc.getInstanceAttrib(InstanceAttribs::kDevBounds45).fName);
v->codeAppendf("refpt45 *= float2x2(.5,.5,-.5,.5);"); // transform back to device space. v->codeAppendf("refpt45 *= highfloat2x2(.5,.5,-.5,.5);"); // transform back to device space.
v->codeAppendf("refpt45 += N[1] * %f;", kAABloatRadius); // bloat for AA. v->codeAppendf("refpt45 += N[1] * %f;", kAABloatRadius); // bloat for AA.
v->codeAppend ("highp float2 K = float2(dot(N[0], refpt), dot(N[1], refpt45));"); v->codeAppend ("highfloat2 K = highfloat2(dot(N[0], refpt), dot(N[1], refpt45));");
v->codeAppendf("highp float2 octocoord = K * inverse(N);"); v->codeAppendf("highfloat2 octocoord = K * inverse(N);");
gpArgs->fPositionVar.set(kVec2f_GrSLType, "octocoord"); gpArgs->fPositionVar.set(kHighFloat2_GrSLType, "octocoord");
// Convert to atlas coordinates in order to do our texture lookup. // Convert to atlas coordinates in order to do our texture lookup.
v->codeAppendf("highp float2 atlascoord = octocoord + float2(%s);", v->codeAppendf("highfloat2 atlascoord = octocoord + highfloat2(%s);",
proc.getInstanceAttrib(InstanceAttribs::kAtlasOffset).fName); proc.getInstanceAttrib(InstanceAttribs::kAtlasOffset).fName);
if (kTopLeft_GrSurfaceOrigin == proc.atlasProxy()->origin()) { if (kTopLeft_GrSurfaceOrigin == proc.atlasProxy()->origin()) {
v->codeAppendf("%s = atlascoord * %s;", texcoord.vsOut(), atlasAdjust); v->codeAppendf("%s = atlascoord * %s;", texcoord.vsOut(), atlasAdjust);
} else { } else {
SkASSERT(kBottomLeft_GrSurfaceOrigin == proc.atlasProxy()->origin()); SkASSERT(kBottomLeft_GrSurfaceOrigin == proc.atlasProxy()->origin());
v->codeAppendf("%s = float2(atlascoord.x * %s.x, 1 - atlascoord.y * %s.y);", v->codeAppendf("%s = highfloat2(atlascoord.x * %s.x, 1 - atlascoord.y * %s.y);",
texcoord.vsOut(), atlasAdjust, atlasAdjust); texcoord.vsOut(), atlasAdjust, atlasAdjust);
} }
// Convert to (local) path cordinates. // Convert to (local) path cordinates.
v->codeAppendf("highp float2 pathcoord = inverse(float2x2(%s)) * (octocoord - %s);", v->codeAppendf("highfloat2 pathcoord = inverse(highfloat2x2(%s)) * (octocoord - %s);",
proc.getInstanceAttrib(InstanceAttribs::kViewMatrix).fName, proc.getInstanceAttrib(InstanceAttribs::kViewMatrix).fName,
proc.getInstanceAttrib(InstanceAttribs::kViewTranslate).fName); proc.getInstanceAttrib(InstanceAttribs::kViewTranslate).fName);
@ -181,16 +181,16 @@ void GLSLPathProcessor::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
// Fragment shader. // Fragment shader.
GrGLSLPPFragmentBuilder* f = args.fFragBuilder; GrGLSLPPFragmentBuilder* f = args.fFragBuilder;
f->codeAppend ("mediump float coverage_count = "); f->codeAppend ("half coverage_count = ");
f->appendTextureLookup(args.fTexSamplers[0], texcoord.fsIn(), kVec2f_GrSLType); f->appendTextureLookup(args.fTexSamplers[0], texcoord.fsIn(), kHighFloat2_GrSLType);
f->codeAppend (".a;"); f->codeAppend (".a;");
if (SkPath::kWinding_FillType == proc.fillType()) { if (SkPath::kWinding_FillType == proc.fillType()) {
f->codeAppendf("%s = float4(min(abs(coverage_count), 1));", args.fOutputCoverage); f->codeAppendf("%s = half4(min(abs(coverage_count), 1));", args.fOutputCoverage);
} else { } else {
SkASSERT(SkPath::kEvenOdd_FillType == proc.fillType()); SkASSERT(SkPath::kEvenOdd_FillType == proc.fillType());
f->codeAppend ("mediump float t = mod(abs(coverage_count), 2);"); f->codeAppend ("half t = mod(abs(coverage_count), 2);");
f->codeAppendf("%s = float4(1 - abs(t - 1));", args.fOutputCoverage); f->codeAppendf("%s = half4(1 - abs(t - 1));", args.fOutputCoverage);
} }
} }

View File

@ -16,18 +16,18 @@ void GrCCPRQuadraticProcessor::onEmitVertexShader(const GrCCPRCoverageProcessor&
const TexelBufferHandle& pointsBuffer, const TexelBufferHandle& pointsBuffer,
const char* atlasOffset, const char* rtAdjust, const char* atlasOffset, const char* rtAdjust,
GrGPArgs* gpArgs) const { GrGPArgs* gpArgs) const {
v->codeAppend ("highp float2 self = "); v->codeAppend ("highfloat2 self = ");
v->appendTexelFetch(pointsBuffer, v->appendTexelFetch(pointsBuffer,
SkStringPrintf("%s.x + sk_VertexID", proc.instanceAttrib()).c_str()); SkStringPrintf("%s.x + sk_VertexID", proc.instanceAttrib()).c_str());
v->codeAppendf(".xy + %s;", atlasOffset); v->codeAppendf(".xy + %s;", atlasOffset);
gpArgs->fPositionVar.set(kVec2f_GrSLType, "self"); gpArgs->fPositionVar.set(kHighFloat2_GrSLType, "self");
} }
void GrCCPRQuadraticProcessor::emitWind(GrGLSLGeometryBuilder* g, const char* rtAdjust, void GrCCPRQuadraticProcessor::emitWind(GrGLSLGeometryBuilder* g, const char* rtAdjust,
const char* outputWind) const { const char* outputWind) const {
// We will define bezierpts in onEmitGeometryShader. // We will define bezierpts in onEmitGeometryShader.
g->codeAppend ("highp float area_times_2 = " g->codeAppend ("highfloat area_times_2 = "
"determinant(float2x2(bezierpts[1] - bezierpts[0], " "determinant(highfloat2x2(bezierpts[1] - bezierpts[0], "
"bezierpts[2] - bezierpts[0]));"); "bezierpts[2] - bezierpts[0]));");
// Drop curves that are nearly flat, in favor of the higher quality triangle antialiasing. // Drop curves that are nearly flat, in favor of the higher quality triangle antialiasing.
g->codeAppendf("if (2 * abs(area_times_2) < length((bezierpts[2] - bezierpts[0]) * %s.zx)) {", g->codeAppendf("if (2 * abs(area_times_2) < length((bezierpts[2] - bezierpts[0]) * %s.zx)) {",
@ -46,26 +46,26 @@ void GrCCPRQuadraticProcessor::onEmitGeometryShader(GrGLSLGeometryBuilder* g,
const char* emitVertexFn, const char* wind, const char* emitVertexFn, const char* wind,
const char* rtAdjust) const { const char* rtAdjust) const {
// Prepend bezierpts at the start of the shader. // Prepend bezierpts at the start of the shader.
g->codePrependf("highp float3x2 bezierpts = float3x2(sk_in[0].gl_Position.xy, " g->codePrependf("highfloat3x2 bezierpts = highfloat3x2(sk_in[0].gl_Position.xy, "
"sk_in[1].gl_Position.xy, " "sk_in[1].gl_Position.xy, "
"sk_in[2].gl_Position.xy);"); "sk_in[2].gl_Position.xy);");
g->declareGlobal(fCanonicalMatrix); g->declareGlobal(fCanonicalMatrix);
g->codeAppendf("%s = float3x3(0.0, 0, 1, " g->codeAppendf("%s = highfloat3x3(0.0, 0, 1, "
"0.5, 0, 1, " "0.5, 0, 1, "
"1.0, 1, 1) * " "1.0, 1, 1) * "
"inverse(float3x3(bezierpts[0], 1, " "inverse(highfloat3x3(bezierpts[0], 1, "
"bezierpts[1], 1, " "bezierpts[1], 1, "
"bezierpts[2], 1));", "bezierpts[2], 1));",
fCanonicalMatrix.c_str()); fCanonicalMatrix.c_str());
g->declareGlobal(fCanonicalDerivatives); g->declareGlobal(fCanonicalDerivatives);
g->codeAppendf("%s = float2x2(%s) * float2x2(%s.x, 0, 0, %s.z);", g->codeAppendf("%s = highfloat2x2(%s) * highfloat2x2(%s.x, 0, 0, %s.z);",
fCanonicalDerivatives.c_str(), fCanonicalMatrix.c_str(), rtAdjust, rtAdjust); fCanonicalDerivatives.c_str(), fCanonicalMatrix.c_str(), rtAdjust, rtAdjust);
g->declareGlobal(fEdgeDistanceEquation); g->declareGlobal(fEdgeDistanceEquation);
g->codeAppendf("highp float2 edgept0 = bezierpts[%s > 0 ? 2 : 0];", wind); g->codeAppendf("highfloat2 edgept0 = bezierpts[%s > 0 ? 2 : 0];", wind);
g->codeAppendf("highp float2 edgept1 = bezierpts[%s > 0 ? 0 : 2];", wind); g->codeAppendf("highfloat2 edgept1 = bezierpts[%s > 0 ? 0 : 2];", wind);
this->emitEdgeDistanceEquation(g, "edgept0", "edgept1", fEdgeDistanceEquation.c_str()); this->emitEdgeDistanceEquation(g, "edgept0", "edgept1", fEdgeDistanceEquation.c_str());
this->emitQuadraticGeometry(g, emitVertexFn, rtAdjust); this->emitQuadraticGeometry(g, emitVertexFn, rtAdjust);
@ -74,7 +74,7 @@ void GrCCPRQuadraticProcessor::onEmitGeometryShader(GrGLSLGeometryBuilder* g,
void GrCCPRQuadraticProcessor::emitPerVertexGeometryCode(SkString* fnBody, const char* position, void GrCCPRQuadraticProcessor::emitPerVertexGeometryCode(SkString* fnBody, const char* position,
const char* /*coverage*/, const char* /*coverage*/,
const char* /*wind*/) const { const char* /*wind*/) const {
fnBody->appendf("%s.xy = (%s * float3(%s, 1)).xy;", fnBody->appendf("%s.xy = (%s * highfloat3(%s, 1)).xy;",
fXYD.gsOut(), fCanonicalMatrix.c_str(), position); fXYD.gsOut(), fCanonicalMatrix.c_str(), position);
fnBody->appendf("%s.z = dot(%s.xy, %s) + %s.z;", fnBody->appendf("%s.z = dot(%s.xy, %s) + %s.z;",
fXYD.gsOut(), fEdgeDistanceEquation.c_str(), position, fXYD.gsOut(), fEdgeDistanceEquation.c_str(), position,
@ -87,18 +87,18 @@ void GrCCPRQuadraticHullProcessor::emitQuadraticGeometry(GrGLSLGeometryBuilder*
const char* /*rtAdjust*/) const { const char* /*rtAdjust*/) const {
// Find the t value whose tangent is halfway between the tangents at the endpionts. // Find the t value whose tangent is halfway between the tangents at the endpionts.
// (We defined bezierpts in onEmitGeometryShader.) // (We defined bezierpts in onEmitGeometryShader.)
g->codeAppend ("highp float2 tan0 = bezierpts[1] - bezierpts[0];"); g->codeAppend ("highfloat2 tan0 = bezierpts[1] - bezierpts[0];");
g->codeAppend ("highp float2 tan1 = bezierpts[2] - bezierpts[1];"); g->codeAppend ("highfloat2 tan1 = bezierpts[2] - bezierpts[1];");
g->codeAppend ("highp float2 midnorm = normalize(tan0) - normalize(tan1);"); g->codeAppend ("highfloat2 midnorm = normalize(tan0) - normalize(tan1);");
g->codeAppend ("highp float2 T = midnorm * float2x2(tan0 - tan1, tan0);"); g->codeAppend ("highfloat2 T = midnorm * highfloat2x2(tan0 - tan1, tan0);");
g->codeAppend ("highp float t = clamp(T.t / T.s, 0, 1);"); // T.s=0 is weeded out by this point. g->codeAppend ("highfloat t = clamp(T.t / T.s, 0, 1);"); // T.s=0 is weeded out by this point.
// Clip the bezier triangle by the tangent at our new t value. This is a simple application for // Clip the bezier triangle by the tangent at our new t value. This is a simple application for
// De Casteljau's algorithm. // De Casteljau's algorithm.
g->codeAppendf("highp float4x2 quadratic_hull = float4x2(bezierpts[0], " g->codeAppendf("highfloat4x2 quadratic_hull = highfloat4x2(bezierpts[0], "
"bezierpts[0] + tan0 * t, " "bezierpts[0] + tan0 * t, "
"bezierpts[1] + tan1 * t, " "bezierpts[1] + tan1 * t, "
"bezierpts[2]);"); "bezierpts[2]);");
int maxVerts = this->emitHullGeometry(g, emitVertexFn, "quadratic_hull", 4, "sk_InvocationID"); int maxVerts = this->emitHullGeometry(g, emitVertexFn, "quadratic_hull", 4, "sk_InvocationID");
@ -108,13 +108,13 @@ void GrCCPRQuadraticHullProcessor::emitQuadraticGeometry(GrGLSLGeometryBuilder*
} }
void GrCCPRQuadraticHullProcessor::onEmitPerVertexGeometryCode(SkString* fnBody) const { void GrCCPRQuadraticHullProcessor::onEmitPerVertexGeometryCode(SkString* fnBody) const {
fnBody->appendf("%s = float2(2 * %s.x, -1) * %s;", fnBody->appendf("%s = highfloat2(2 * %s.x, -1) * %s;",
fGradXY.gsOut(), fXYD.gsOut(), fCanonicalDerivatives.c_str()); fGradXY.gsOut(), fXYD.gsOut(), fCanonicalDerivatives.c_str());
} }
void GrCCPRQuadraticHullProcessor::emitShaderCoverage(GrGLSLFragmentBuilder* f, void GrCCPRQuadraticHullProcessor::emitShaderCoverage(GrGLSLFragmentBuilder* f,
const char* outputCoverage) const { const char* outputCoverage) const {
f->codeAppendf("highp float d = (%s.x * %s.x - %s.y) * inversesqrt(dot(%s, %s));", f->codeAppendf("highfloat d = (%s.x * %s.x - %s.y) * inversesqrt(dot(%s, %s));",
fXYD.fsIn(), fXYD.fsIn(), fXYD.fsIn(), fGradXY.fsIn(), fGradXY.fsIn()); fXYD.fsIn(), fXYD.fsIn(), fXYD.fsIn(), fGradXY.fsIn(), fGradXY.fsIn());
f->codeAppendf("%s = clamp(0.5 - d, 0, 1);", outputCoverage); f->codeAppendf("%s = clamp(0.5 - d, 0, 1);", outputCoverage);
f->codeAppendf("%s += min(%s.z, 0);", outputCoverage, fXYD.fsIn()); // Flat closing edge. f->codeAppendf("%s += min(%s.z, 0);", outputCoverage, fXYD.fsIn()); // Flat closing edge.
@ -127,7 +127,7 @@ void GrCCPRQuadraticCornerProcessor::emitQuadraticGeometry(GrGLSLGeometryBuilder
g->codeAppendf("%s = %s.xy * %s.xz;", g->codeAppendf("%s = %s.xy * %s.xz;",
fEdgeDistanceDerivatives.c_str(), fEdgeDistanceEquation.c_str(), rtAdjust); fEdgeDistanceDerivatives.c_str(), fEdgeDistanceEquation.c_str(), rtAdjust);
g->codeAppendf("highp float2 corner = bezierpts[sk_InvocationID * 2];"); g->codeAppendf("highfloat2 corner = bezierpts[sk_InvocationID * 2];");
int numVertices = this->emitCornerGeometry(g, emitVertexFn, "corner"); int numVertices = this->emitCornerGeometry(g, emitVertexFn, "corner");
g->configure(GrGLSLGeometryBuilder::InputType::kTriangles, g->configure(GrGLSLGeometryBuilder::InputType::kTriangles,
@ -135,35 +135,35 @@ void GrCCPRQuadraticCornerProcessor::emitQuadraticGeometry(GrGLSLGeometryBuilder
} }
void GrCCPRQuadraticCornerProcessor::onEmitPerVertexGeometryCode(SkString* fnBody) const { void GrCCPRQuadraticCornerProcessor::onEmitPerVertexGeometryCode(SkString* fnBody) const {
fnBody->appendf("%s = float3(%s[0].x, %s[0].y, %s.x);", fnBody->appendf("%s = highfloat3(%s[0].x, %s[0].y, %s.x);",
fdXYDdx.gsOut(), fCanonicalDerivatives.c_str(), fCanonicalDerivatives.c_str(), fdXYDdx.gsOut(), fCanonicalDerivatives.c_str(), fCanonicalDerivatives.c_str(),
fEdgeDistanceDerivatives.c_str()); fEdgeDistanceDerivatives.c_str());
fnBody->appendf("%s = float3(%s[1].x, %s[1].y, %s.y);", fnBody->appendf("%s = highfloat3(%s[1].x, %s[1].y, %s.y);",
fdXYDdy.gsOut(), fCanonicalDerivatives.c_str(), fCanonicalDerivatives.c_str(), fdXYDdy.gsOut(), fCanonicalDerivatives.c_str(), fCanonicalDerivatives.c_str(),
fEdgeDistanceDerivatives.c_str()); fEdgeDistanceDerivatives.c_str());
} }
void GrCCPRQuadraticCornerProcessor::emitShaderCoverage(GrGLSLFragmentBuilder* f, void GrCCPRQuadraticCornerProcessor::emitShaderCoverage(GrGLSLFragmentBuilder* f,
const char* outputCoverage) const { const char* outputCoverage) const {
f->codeAppendf("highp float x = %s.x, y = %s.y, d = %s.z;", f->codeAppendf("highfloat x = %s.x, y = %s.y, d = %s.z;",
fXYD.fsIn(), fXYD.fsIn(), fXYD.fsIn()); fXYD.fsIn(), fXYD.fsIn(), fXYD.fsIn());
f->codeAppendf("highp float2x3 grad_xyd = float2x3(%s, %s);", fdXYDdx.fsIn(), fdXYDdy.fsIn()); f->codeAppendf("highfloat2x3 grad_xyd = highfloat2x3(%s, %s);", fdXYDdx.fsIn(), fdXYDdy.fsIn());
// Erase what the previous hull shader wrote. We don't worry about the two corners falling on // Erase what the previous hull shader wrote. We don't worry about the two corners falling on
// the same pixel because those cases should have been weeded out by this point. // the same pixel because those cases should have been weeded out by this point.
f->codeAppend ("highp float f = x*x - y;"); f->codeAppend ("highfloat f = x*x - y;");
f->codeAppend ("highp float2 grad_f = float2(2*x, -1) * float2x2(grad_xyd);"); f->codeAppend ("highfloat2 grad_f = highfloat2(2*x, -1) * highfloat2x2(grad_xyd);");
f->codeAppendf("%s = -(0.5 - f * inversesqrt(dot(grad_f, grad_f)));", outputCoverage); f->codeAppendf("%s = -(0.5 - f * inversesqrt(dot(grad_f, grad_f)));", outputCoverage);
f->codeAppendf("%s -= d;", outputCoverage); f->codeAppendf("%s -= d;", outputCoverage);
// Use software msaa to approximate coverage at the corner pixels. // Use software msaa to approximate coverage at the corner pixels.
int sampleCount = this->defineSoftSampleLocations(f, "samples"); int sampleCount = this->defineSoftSampleLocations(f, "samples");
f->codeAppendf("highp float3 xyd_center = float3(%s.xy, %s.z + 0.5);", f->codeAppendf("highfloat3 xyd_center = highfloat3(%s.xy, %s.z + 0.5);",
fXYD.fsIn(), fXYD.fsIn()); fXYD.fsIn(), fXYD.fsIn());
f->codeAppendf("for (int i = 0; i < %i; ++i) {", sampleCount); f->codeAppendf("for (int i = 0; i < %i; ++i) {", sampleCount);
f->codeAppend ( "highp float3 xyd = grad_xyd * samples[i] + xyd_center;"); f->codeAppend ( "highfloat3 xyd = grad_xyd * samples[i] + xyd_center;");
f->codeAppend ( "lowp float f = xyd.y - xyd.x * xyd.x;"); // f > 0 -> inside curve. f->codeAppend ( "half f = xyd.y - xyd.x * xyd.x;"); // f > 0 -> inside curve.
f->codeAppendf( "%s += all(greaterThan(float2(f,xyd.z), float2(0))) ? %f : 0;", f->codeAppendf( "%s += all(greaterThan(highfloat2(f,xyd.z), highfloat2(0))) ? %f : 0;",
outputCoverage, 1.0 / sampleCount); outputCoverage, 1.0 / sampleCount);
f->codeAppendf("}"); f->codeAppendf("}");
} }

View File

@ -24,13 +24,12 @@ class GrCCPRQuadraticProcessor : public GrCCPRCoverageProcessor::PrimitiveProces
public: public:
GrCCPRQuadraticProcessor() GrCCPRQuadraticProcessor()
: INHERITED(CoverageType::kShader) : INHERITED(CoverageType::kShader)
, fCanonicalMatrix("canonical_matrix", kMat33f_GrSLType, GrShaderVar::kNonArray, , fCanonicalMatrix("canonical_matrix", kHighFloat3x3_GrSLType, GrShaderVar::kNonArray)
kHigh_GrSLPrecision) , fCanonicalDerivatives("canonical_derivatives", kHighFloat2x2_GrSLType,
, fCanonicalDerivatives("canonical_derivatives", kMat22f_GrSLType, GrShaderVar::kNonArray)
GrShaderVar::kNonArray, kHigh_GrSLPrecision) , fEdgeDistanceEquation("edge_distance_equation", kHighFloat3_GrSLType,
, fEdgeDistanceEquation("edge_distance_equation", kVec3f_GrSLType, GrShaderVar::kNonArray)
GrShaderVar::kNonArray, kHigh_GrSLPrecision) , fXYD(kHighFloat3_GrSLType) {}
, fXYD(kVec3f_GrSLType) {}
void resetVaryings(GrGLSLVaryingHandler* varyingHandler) override { void resetVaryings(GrGLSLVaryingHandler* varyingHandler) override {
varyingHandler->addVarying("xyd", &fXYD, kHigh_GrSLPrecision); varyingHandler->addVarying("xyd", &fXYD, kHigh_GrSLPrecision);
@ -67,7 +66,7 @@ protected:
class GrCCPRQuadraticHullProcessor : public GrCCPRQuadraticProcessor { class GrCCPRQuadraticHullProcessor : public GrCCPRQuadraticProcessor {
public: public:
GrCCPRQuadraticHullProcessor() GrCCPRQuadraticHullProcessor()
: fGradXY(kVec2f_GrSLType) {} : fGradXY(kHighFloat2_GrSLType) {}
void resetVaryings(GrGLSLVaryingHandler* varyingHandler) override { void resetVaryings(GrGLSLVaryingHandler* varyingHandler) override {
this->INHERITED::resetVaryings(varyingHandler); this->INHERITED::resetVaryings(varyingHandler);
@ -91,10 +90,10 @@ private:
class GrCCPRQuadraticCornerProcessor : public GrCCPRQuadraticProcessor { class GrCCPRQuadraticCornerProcessor : public GrCCPRQuadraticProcessor {
public: public:
GrCCPRQuadraticCornerProcessor() GrCCPRQuadraticCornerProcessor()
: fEdgeDistanceDerivatives("edge_distance_derivatives", kVec2f_GrSLType, : fEdgeDistanceDerivatives("edge_distance_derivatives", kHighFloat2_GrSLType,
GrShaderVar::kNonArray, kHigh_GrSLPrecision) GrShaderVar::kNonArray)
, fdXYDdx(kVec3f_GrSLType) , fdXYDdx(kHighFloat3_GrSLType)
, fdXYDdy(kVec3f_GrSLType) {} , fdXYDdy(kHighFloat3_GrSLType) {}
void resetVaryings(GrGLSLVaryingHandler* varyingHandler) override { void resetVaryings(GrGLSLVaryingHandler* varyingHandler) override {
this->INHERITED::resetVaryings(varyingHandler); this->INHERITED::resetVaryings(varyingHandler);

View File

@ -16,16 +16,16 @@ void GrCCPRTriangleProcessor::onEmitVertexShader(const GrCCPRCoverageProcessor&
const TexelBufferHandle& pointsBuffer, const TexelBufferHandle& pointsBuffer,
const char* atlasOffset, const char* rtAdjust, const char* atlasOffset, const char* rtAdjust,
GrGPArgs* gpArgs) const { GrGPArgs* gpArgs) const {
v->codeAppend ("highp float2 self = "); v->codeAppend ("highfloat2 self = ");
v->appendTexelFetch(pointsBuffer, v->appendTexelFetch(pointsBuffer,
SkStringPrintf("%s[sk_VertexID]", proc.instanceAttrib()).c_str()); SkStringPrintf("%s[sk_VertexID]", proc.instanceAttrib()).c_str());
v->codeAppendf(".xy + %s;", atlasOffset); v->codeAppendf(".xy + %s;", atlasOffset);
gpArgs->fPositionVar.set(kVec2f_GrSLType, "self"); gpArgs->fPositionVar.set(kHighFloat2_GrSLType, "self");
} }
void GrCCPRTriangleProcessor::defineInputVertices(GrGLSLGeometryBuilder* g) const { void GrCCPRTriangleProcessor::defineInputVertices(GrGLSLGeometryBuilder* g) const {
// Prepend in_vertices at the start of the shader. // Prepend in_vertices at the start of the shader.
g->codePrependf("highp float3x2 in_vertices = float3x2(sk_in[0].gl_Position.xy, " g->codePrependf("highfloat3x2 in_vertices = highfloat3x2(sk_in[0].gl_Position.xy, "
"sk_in[1].gl_Position.xy, " "sk_in[1].gl_Position.xy, "
"sk_in[2].gl_Position.xy);"); "sk_in[2].gl_Position.xy);");
} }
@ -33,8 +33,8 @@ void GrCCPRTriangleProcessor::defineInputVertices(GrGLSLGeometryBuilder* g) cons
void GrCCPRTriangleProcessor::emitWind(GrGLSLGeometryBuilder* g, const char* /*rtAdjust*/, void GrCCPRTriangleProcessor::emitWind(GrGLSLGeometryBuilder* g, const char* /*rtAdjust*/,
const char* outputWind) const { const char* outputWind) const {
// We will define in_vertices in defineInputVertices. // We will define in_vertices in defineInputVertices.
g->codeAppendf("%s = sign(determinant(float2x2(in_vertices[1] - in_vertices[0], " g->codeAppendf("%s = sign(determinant(highfloat2x2(in_vertices[1] - in_vertices[0], "
"in_vertices[2] - in_vertices[0])));", "in_vertices[2] - in_vertices[0])));",
outputWind); outputWind);
} }
@ -53,8 +53,8 @@ void GrCCPRTriangleHullAndEdgeProcessor::onEmitGeometryShader(GrGLSLGeometryBuil
if (GeometryType::kHulls != fGeometryType) { if (GeometryType::kHulls != fGeometryType) {
g->codeAppend ("int edgeidx0 = sk_InvocationID, " g->codeAppend ("int edgeidx0 = sk_InvocationID, "
"edgeidx1 = (edgeidx0 + 1) % 3;"); "edgeidx1 = (edgeidx0 + 1) % 3;");
g->codeAppendf("highp float2 edgept0 = in_vertices[%s > 0 ? edgeidx0 : edgeidx1];", wind); g->codeAppendf("highfloat2 edgept0 = in_vertices[%s > 0 ? edgeidx0 : edgeidx1];", wind);
g->codeAppendf("highp float2 edgept1 = in_vertices[%s > 0 ? edgeidx1 : edgeidx0];", wind); g->codeAppendf("highfloat2 edgept1 = in_vertices[%s > 0 ? edgeidx1 : edgeidx0];", wind);
maxOutputVertices += this->emitEdgeGeometry(g, emitVertexFn, "edgept0", "edgept1"); maxOutputVertices += this->emitEdgeGeometry(g, emitVertexFn, "edgept0", "edgept1");
} }
@ -73,15 +73,15 @@ void GrCCPRTriangleCornerProcessor::onEmitVertexShader(const GrCCPRCoverageProce
this->INHERITED::onEmitVertexShader(proc, v, pointsBuffer, atlasOffset, rtAdjust, gpArgs); this->INHERITED::onEmitVertexShader(proc, v, pointsBuffer, atlasOffset, rtAdjust, gpArgs);
// Fetch and transform the next point in the triangle. // Fetch and transform the next point in the triangle.
v->codeAppend ("highp float2 next = "); v->codeAppend ("highfloat2 next = ");
v->appendTexelFetch(pointsBuffer, v->appendTexelFetch(pointsBuffer,
SkStringPrintf("%s[(sk_VertexID+1) %% 3]", proc.instanceAttrib()).c_str()); SkStringPrintf("%s[(sk_VertexID+1) %% 3]", proc.instanceAttrib()).c_str());
v->codeAppendf(".xy + %s;", atlasOffset); v->codeAppendf(".xy + %s;", atlasOffset);
// Find the plane that gives distance from the [self -> next] edge, normalized to its AA // Find the plane that gives distance from the [self -> next] edge, normalized to its AA
// bloat width. // bloat width.
v->codeAppend ("highp float2 n = float2(next.y - self.y, self.x - next.x);"); v->codeAppend ("highfloat2 n = highfloat2(next.y - self.y, self.x - next.x);");
v->codeAppendf("highp float2 d = n * float2x2(self + %f * sign(n), " v->codeAppendf("highfloat2 d = n * highfloat2x2(self + %f * sign(n), "
"self - %f * sign(n));", "self - %f * sign(n));",
kAABloatRadius, kAABloatRadius); kAABloatRadius, kAABloatRadius);
@ -98,7 +98,7 @@ void GrCCPRTriangleCornerProcessor::onEmitGeometryShader(GrGLSLGeometryBuilder*
const char* rtAdjust) const { const char* rtAdjust) const {
this->defineInputVertices(g); this->defineInputVertices(g);
g->codeAppend ("highp float2 self = in_vertices[sk_InvocationID];"); g->codeAppend ("highfloat2 self = in_vertices[sk_InvocationID];");
int numVertices = this->emitCornerGeometry(g, emitVertexFn, "self"); int numVertices = this->emitCornerGeometry(g, emitVertexFn, "self");
g->configure(GrGLSLGeometryBuilder::InputType::kTriangles, g->configure(GrGLSLGeometryBuilder::InputType::kTriangles,
@ -114,7 +114,7 @@ void GrCCPRTriangleCornerProcessor::emitPerVertexGeometryCode(SkString* fnBody,
fNeighbors.gsOut(), fDevCoord.gsIn()); fNeighbors.gsOut(), fDevCoord.gsIn());
fnBody->appendf("%s.zw = %s[(sk_InvocationID + 2) %% 3];", fnBody->appendf("%s.zw = %s[(sk_InvocationID + 2) %% 3];",
fNeighbors.gsOut(), fDevCoord.gsIn()); fNeighbors.gsOut(), fDevCoord.gsIn());
fnBody->appendf("%s = float3x3(%s[(sk_InvocationID + 2) %% 3], " fnBody->appendf("%s = highfloat3x3(%s[(sk_InvocationID + 2) %% 3], "
"%s[sk_InvocationID], " "%s[sk_InvocationID], "
"%s[(sk_InvocationID + 1) %% 3]) * %s;", "%s[(sk_InvocationID + 1) %% 3]) * %s;",
fEdgeDistances.gsOut(), fEdgeDistance.gsIn(), fEdgeDistance.gsIn(), fEdgeDistances.gsOut(), fEdgeDistance.gsIn(), fEdgeDistance.gsIn(),
@ -129,32 +129,28 @@ void GrCCPRTriangleCornerProcessor::emitPerVertexGeometryCode(SkString* fnBody,
void GrCCPRTriangleCornerProcessor::emitShaderCoverage(GrGLSLFragmentBuilder* f, void GrCCPRTriangleCornerProcessor::emitShaderCoverage(GrGLSLFragmentBuilder* f,
const char* outputCoverage) const { const char* outputCoverage) const {
// FIXME: Adreno breaks if we don't put the frag coord in an intermediate highp variable. // FIXME: Adreno breaks if we don't put the frag coord in an intermediate highp variable.
f->codeAppendf("highp float2 fragcoord = sk_FragCoord.xy;"); f->codeAppendf("highfloat2 fragcoord = sk_FragCoord.xy;");
// Approximate coverage by tracking where 4 horizontal lines enter and leave the triangle. // Approximate coverage by tracking where 4 horizontal lines enter and leave the triangle.
GrShaderVar samples("samples", kVec4f_GrSLType, GrShaderVar::kNonArray, GrShaderVar samples("samples", kHighFloat4_GrSLType, GrShaderVar::kNonArray);
kHigh_GrSLPrecision);
f->declareGlobal(samples); f->declareGlobal(samples);
f->codeAppendf("%s = fragcoord.y + float4(-0.375, -0.125, 0.125, 0.375);", samples.c_str()); f->codeAppendf("%s = fragcoord.y + highfloat4(-0.375, -0.125, 0.125, 0.375);", samples.c_str());
GrShaderVar leftedge("leftedge", kVec4f_GrSLType, GrShaderVar::kNonArray, GrShaderVar leftedge("leftedge", kHighFloat4_GrSLType, GrShaderVar::kNonArray);
kHigh_GrSLPrecision);
f->declareGlobal(leftedge); f->declareGlobal(leftedge);
f->codeAppendf("%s = float4(fragcoord.x - 0.5);", leftedge.c_str()); f->codeAppendf("%s = highfloat4(fragcoord.x - 0.5);", leftedge.c_str());
GrShaderVar rightedge("rightedge", kVec4f_GrSLType, GrShaderVar::kNonArray, GrShaderVar rightedge("rightedge", kHighFloat4_GrSLType, GrShaderVar::kNonArray);
kHigh_GrSLPrecision);
f->declareGlobal(rightedge); f->declareGlobal(rightedge);
f->codeAppendf("%s = float4(fragcoord.x + 0.5);", rightedge.c_str()); f->codeAppendf("%s = highfloat4(fragcoord.x + 0.5);", rightedge.c_str());
SkString sampleEdgeFn; SkString sampleEdgeFn;
GrShaderVar edgeArg("edge_distance", kVec3f_GrSLType, GrShaderVar::kNonArray, GrShaderVar edgeArg("edge_distance", kHighFloat3_GrSLType, GrShaderVar::kNonArray);
kHigh_GrSLPrecision);
f->emitFunction(kVoid_GrSLType, "sampleEdge", 1, &edgeArg, [&]() { f->emitFunction(kVoid_GrSLType, "sampleEdge", 1, &edgeArg, [&]() {
SkString b; SkString b;
b.appendf("highp float m = abs(%s.x) < 1e-3 ? 1e18 : -1 / %s.x;", b.appendf("highfloat m = abs(%s.x) < 1e-3 ? 1e18 : -1 / %s.x;",
edgeArg.c_str(), edgeArg.c_str()); edgeArg.c_str(), edgeArg.c_str());
b.appendf("highp float4 edge = m * (%s.y * samples + %s.z);", b.appendf("highfloat4 edge = m * (%s.y * samples + %s.z);",
edgeArg.c_str(), edgeArg.c_str()); edgeArg.c_str(), edgeArg.c_str());
b.appendf("if (%s.x <= 1e-3 || (abs(%s.x) < 1e-3 && %s.y > 0)) {", b.appendf("if (%s.x <= 1e-3 || (abs(%s.x) < 1e-3 && %s.y > 0)) {",
edgeArg.c_str(), edgeArg.c_str(), edgeArg.c_str()); edgeArg.c_str(), edgeArg.c_str(), edgeArg.c_str());
@ -166,10 +162,10 @@ void GrCCPRTriangleCornerProcessor::emitShaderCoverage(GrGLSLFragmentBuilder* f,
}().c_str(), &sampleEdgeFn); }().c_str(), &sampleEdgeFn);
// See if the previous neighbor already handled this pixel. // See if the previous neighbor already handled this pixel.
f->codeAppendf("if (all(lessThan(abs(fragcoord - %s.zw), float2(%f)))) {", f->codeAppendf("if (all(lessThan(abs(fragcoord - %s.zw), highfloat2(%f)))) {",
fNeighbors.fsIn(), kAABloatRadius); fNeighbors.fsIn(), kAABloatRadius);
// Handle the case where all 3 corners defer to the previous neighbor. // Handle the case where all 3 corners defer to the previous neighbor.
f->codeAppendf( "if (%s != 0 || !all(lessThan(abs(fragcoord - %s.xy), float2(%f)))) {", f->codeAppendf( "if (%s != 0 || !all(lessThan(abs(fragcoord - %s.xy), highfloat2(%f)))) {",
fCornerIdx.fsIn(), fNeighbors.fsIn(), kAABloatRadius); fCornerIdx.fsIn(), fNeighbors.fsIn(), kAABloatRadius);
f->codeAppend ( "discard;"); f->codeAppend ( "discard;");
f->codeAppend ( "}"); f->codeAppend ( "}");
@ -177,7 +173,7 @@ void GrCCPRTriangleCornerProcessor::emitShaderCoverage(GrGLSLFragmentBuilder* f,
// Erase what the hull and two edges wrote at this corner in previous shaders (the two .5's // Erase what the hull and two edges wrote at this corner in previous shaders (the two .5's
// for the edges and the -1 for the hull cancel each other out). // for the edges and the -1 for the hull cancel each other out).
f->codeAppendf("%s = dot(float3(fragcoord, 1) * float2x3(%s), float2(1));", f->codeAppendf("%s = dot(highfloat3(fragcoord, 1) * highfloat2x3(%s), highfloat2(1));",
outputCoverage, fEdgeDistances.fsIn()); outputCoverage, fEdgeDistances.fsIn());
// Sample the two edges at this corner. // Sample the two edges at this corner.
@ -185,15 +181,15 @@ void GrCCPRTriangleCornerProcessor::emitShaderCoverage(GrGLSLFragmentBuilder* f,
f->codeAppendf("%s(%s[1]);", sampleEdgeFn.c_str(), fEdgeDistances.fsIn()); f->codeAppendf("%s(%s[1]);", sampleEdgeFn.c_str(), fEdgeDistances.fsIn());
// Handle the opposite edge if the next neighbor will defer to us. // Handle the opposite edge if the next neighbor will defer to us.
f->codeAppendf("if (all(lessThan(abs(fragcoord - %s.xy), float2(%f)))) {", f->codeAppendf("if (all(lessThan(abs(fragcoord - %s.xy), highfloat2(%f)))) {",
fNeighbors.fsIn(), kAABloatRadius); fNeighbors.fsIn(), kAABloatRadius);
// Erase the coverage the opposite edge wrote to this corner. // Erase the coverage the opposite edge wrote to this corner.
f->codeAppendf( "%s += dot(%s[2], float3(fragcoord, 1)) + 0.5;", f->codeAppendf( "%s += dot(%s[2], highfloat3(fragcoord, 1)) + 0.5;",
outputCoverage, fEdgeDistances.fsIn()); outputCoverage, fEdgeDistances.fsIn());
// Sample the opposite edge. // Sample the opposite edge.
f->codeAppendf( "%s(%s[2]);", sampleEdgeFn.c_str(), fEdgeDistances.fsIn()); f->codeAppendf( "%s(%s[2]);", sampleEdgeFn.c_str(), fEdgeDistances.fsIn());
f->codeAppend ("}"); f->codeAppend ("}");
f->codeAppendf("highp float4 widths = max(%s - %s, 0);", rightedge.c_str(), leftedge.c_str()); f->codeAppendf("highfloat4 widths = max(%s - %s, 0);", rightedge.c_str(), leftedge.c_str());
f->codeAppendf("%s += dot(widths, float4(0.25));", outputCoverage); f->codeAppendf("%s += dot(widths, highfloat4(0.25));", outputCoverage);
} }

View File

@ -72,11 +72,11 @@ class GrCCPRTriangleCornerProcessor : public GrCCPRTriangleProcessor {
public: public:
GrCCPRTriangleCornerProcessor() GrCCPRTriangleCornerProcessor()
: INHERITED(CoverageType::kShader) : INHERITED(CoverageType::kShader)
, fEdgeDistance(kVec3f_GrSLType) , fEdgeDistance(kHighFloat3_GrSLType)
, fDevCoord(kVec2f_GrSLType) , fDevCoord(kHighFloat2_GrSLType)
, fNeighbors(kVec4f_GrSLType) , fNeighbors(kHighFloat4_GrSLType)
, fEdgeDistances(kMat33f_GrSLType) , fEdgeDistances(kHighFloat3x3_GrSLType)
, fCornerIdx(kInt_GrSLType) {} , fCornerIdx(kShort_GrSLType) {}
void resetVaryings(GrGLSLVaryingHandler* varyingHandler) override { void resetVaryings(GrGLSLVaryingHandler* varyingHandler) override {
this->INHERITED::resetVaryings(varyingHandler); this->INHERITED::resetVaryings(varyingHandler);

View File

@ -22,11 +22,11 @@ static void append_index_uv_varyings(GrGLSLPrimitiveProcessor::EmitArgs& args,
// This extracts the texture index and texel coordinates from the same variable // This extracts the texture index and texel coordinates from the same variable
// Packing structure: texel coordinates are multiplied by 2 (or shifted left 1) // Packing structure: texel coordinates are multiplied by 2 (or shifted left 1)
// texture index is stored as lower bits of both x and y // texture index is stored as lower bits of both x and y
args.fVertBuilder->codeAppendf("float2 indexTexCoords = float2(%s.x, %s.y);", args.fVertBuilder->codeAppendf("half2 indexTexCoords = half2(%s.x, %s.y);",
inTexCoordsName, inTexCoordsName); inTexCoordsName, inTexCoordsName);
args.fVertBuilder->codeAppend("float2 intCoords = floor(0.5*indexTexCoords);"); args.fVertBuilder->codeAppend("half2 intCoords = floor(0.5*indexTexCoords);");
args.fVertBuilder->codeAppend("float2 diff = indexTexCoords - 2.0*intCoords;"); args.fVertBuilder->codeAppend("half2 diff = indexTexCoords - 2.0*intCoords;");
args.fVertBuilder->codeAppend("float texIdx = 2.0*diff.x + diff.y;"); args.fVertBuilder->codeAppend("half texIdx = 2.0*diff.x + diff.y;");
// Multiply by 1/atlasSize to get normalized texture coordinates // Multiply by 1/atlasSize to get normalized texture coordinates
args.fVaryingHandler->addVarying("TextureCoords", uv, kHigh_GrSLPrecision); args.fVaryingHandler->addVarying("TextureCoords", uv, kHigh_GrSLPrecision);
@ -51,11 +51,11 @@ static void append_multitexture_lookup(GrGLSLPrimitiveProcessor::EmitArgs& args,
args.fFragBuilder->codeAppendf("if (%s == 0) ", texIdx.fsIn()); args.fFragBuilder->codeAppendf("if (%s == 0) ", texIdx.fsIn());
} }
args.fFragBuilder->codeAppendf("{ %s = ", colorName); args.fFragBuilder->codeAppendf("{ %s = ", colorName);
args.fFragBuilder->appendTextureLookup(args.fTexSamplers[0], coordName, kVec2f_GrSLType); args.fFragBuilder->appendTextureLookup(args.fTexSamplers[0], coordName, kHighFloat2_GrSLType);
args.fFragBuilder->codeAppend("; }"); args.fFragBuilder->codeAppend("; }");
for (int i = 1; i < numTextureSamplers; ++i) { for (int i = 1; i < numTextureSamplers; ++i) {
args.fFragBuilder->codeAppendf("else if (%s == %d) { %s =", texIdx.fsIn(), i, colorName); args.fFragBuilder->codeAppendf("else if (%s == %d) { %s =", texIdx.fsIn(), i, colorName);
args.fFragBuilder->appendTextureLookup(args.fTexSamplers[i], coordName, kVec2f_GrSLType); args.fFragBuilder->appendTextureLookup(args.fTexSamplers[i], coordName, kHighFloat2_GrSLType);
args.fFragBuilder->codeAppend("; }"); args.fFragBuilder->codeAppend("; }");
} }
} }

View File

@ -77,7 +77,7 @@ void GrGLConicEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
// emit attributes // emit attributes
varyingHandler->emitAttributes(gp); varyingHandler->emitAttributes(gp);
GrGLSLVertToFrag v(kVec4f_GrSLType); GrGLSLVertToFrag v(kHighFloat4_GrSLType);
varyingHandler->addVarying("ConicCoeffs", &v, kHigh_GrSLPrecision); varyingHandler->addVarying("ConicCoeffs", &v, kHigh_GrSLPrecision);
vertBuilder->codeAppendf("%s = %s;", v.vsOut(), gp.inConicCoeffs()->fName); vertBuilder->codeAppendf("%s = %s;", v.vsOut(), gp.inConicCoeffs()->fName);
@ -102,26 +102,18 @@ void GrGLConicEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
gp.localMatrix(), gp.localMatrix(),
args.fFPCoordTransformHandler); args.fFPCoordTransformHandler);
// TODO: this precision check should actually be a check on the number of bits // TODO: we should check on the number of bits float and half provide and use the smallest one
// high and medium provide and the selection of the lowest level that suffices. // that suffices. Additionally we should assert that the upstream code only lets us get here if
// Additionally we should assert that the upstream code only lets us get here if // either float or half provides the required number of bits.
// either high or medium provides the required number of bits.
GrSLPrecision precision = kHigh_GrSLPrecision;
const GrShaderCaps::PrecisionInfo& highP = args.fShaderCaps->getFloatShaderPrecisionInfo(
kFragment_GrShaderType,
kHigh_GrSLPrecision);
if (!highP.supported()) {
precision = kMedium_GrSLPrecision;
}
GrShaderVar edgeAlpha("edgeAlpha", kFloat_GrSLType, 0, precision); GrShaderVar edgeAlpha("edgeAlpha", kHighFloat_GrSLType, 0);
GrShaderVar dklmdx("dklmdx", kVec3f_GrSLType, 0, precision); GrShaderVar dklmdx("dklmdx", kHighFloat3_GrSLType, 0);
GrShaderVar dklmdy("dklmdy", kVec3f_GrSLType, 0, precision); GrShaderVar dklmdy("dklmdy", kHighFloat3_GrSLType, 0);
GrShaderVar dfdx("dfdx", kFloat_GrSLType, 0, precision); GrShaderVar dfdx("dfdx", kHighFloat_GrSLType, 0);
GrShaderVar dfdy("dfdy", kFloat_GrSLType, 0, precision); GrShaderVar dfdy("dfdy", kHighFloat_GrSLType, 0);
GrShaderVar gF("gF", kVec2f_GrSLType, 0, precision); GrShaderVar gF("gF", kHighFloat2_GrSLType, 0);
GrShaderVar gFM("gFM", kFloat_GrSLType, 0, precision); GrShaderVar gFM("gFM", kHighFloat_GrSLType, 0);
GrShaderVar func("func", kFloat_GrSLType, 0, precision); GrShaderVar func("func", kHighFloat_GrSLType, 0);
fragBuilder->declAppend(edgeAlpha); fragBuilder->declAppend(edgeAlpha);
fragBuilder->declAppend(dklmdx); fragBuilder->declAppend(dklmdx);
@ -146,7 +138,8 @@ void GrGLConicEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
v.fsIn(), dklmdy.c_str(), v.fsIn(), dklmdy.c_str(),
v.fsIn(), dklmdy.c_str(), v.fsIn(), dklmdy.c_str(),
v.fsIn(), dklmdy.c_str()); v.fsIn(), dklmdy.c_str());
fragBuilder->codeAppendf("%s = float2(%s, %s);", gF.c_str(), dfdx.c_str(), dfdy.c_str()); fragBuilder->codeAppendf("%s = highfloat2(%s, %s);", gF.c_str(), dfdx.c_str(),
dfdy.c_str());
fragBuilder->codeAppendf("%s = sqrt(dot(%s, %s));", fragBuilder->codeAppendf("%s = sqrt(dot(%s, %s));",
gFM.c_str(), gF.c_str(), gF.c_str()); gFM.c_str(), gF.c_str(), gF.c_str());
fragBuilder->codeAppendf("%s = %s.x*%s.x - %s.y*%s.z;", fragBuilder->codeAppendf("%s = %s.x*%s.x - %s.y*%s.z;",
@ -175,7 +168,8 @@ void GrGLConicEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
v.fsIn(), dklmdy.c_str(), v.fsIn(), dklmdy.c_str(),
v.fsIn(), dklmdy.c_str(), v.fsIn(), dklmdy.c_str(),
v.fsIn(), dklmdy.c_str()); v.fsIn(), dklmdy.c_str());
fragBuilder->codeAppendf("%s = float2(%s, %s);", gF.c_str(), dfdx.c_str(), dfdy.c_str()); fragBuilder->codeAppendf("%s = highfloat2(%s, %s);", gF.c_str(), dfdx.c_str(),
dfdy.c_str());
fragBuilder->codeAppendf("%s = sqrt(dot(%s, %s));", fragBuilder->codeAppendf("%s = sqrt(dot(%s, %s));",
gFM.c_str(), gF.c_str(), gF.c_str()); gFM.c_str(), gF.c_str(), gF.c_str());
fragBuilder->codeAppendf("%s = %s.x * %s.x - %s.y * %s.z;", fragBuilder->codeAppendf("%s = %s.x * %s.x - %s.y * %s.z;",
@ -191,7 +185,7 @@ void GrGLConicEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
case kFillBW_GrProcessorEdgeType: { case kFillBW_GrProcessorEdgeType: {
fragBuilder->codeAppendf("%s = %s.x * %s.x - %s.y * %s.z;", fragBuilder->codeAppendf("%s = %s.x * %s.x - %s.y * %s.z;",
edgeAlpha.c_str(), v.fsIn(), v.fsIn(), v.fsIn(), v.fsIn()); edgeAlpha.c_str(), v.fsIn(), v.fsIn(), v.fsIn(), v.fsIn());
fragBuilder->codeAppendf("%s = float(%s < 0.0);", fragBuilder->codeAppendf("%s = highfloat(%s < 0.0);",
edgeAlpha.c_str(), edgeAlpha.c_str()); edgeAlpha.c_str(), edgeAlpha.c_str());
break; break;
} }
@ -203,14 +197,13 @@ void GrGLConicEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
if (gp.coverageScale() != 0xff) { if (gp.coverageScale() != 0xff) {
const char* coverageScale; const char* coverageScale;
fCoverageScaleUniform = uniformHandler->addUniform(kFragment_GrShaderFlag, fCoverageScaleUniform = uniformHandler->addUniform(kFragment_GrShaderFlag,
kFloat_GrSLType, kHighFloat_GrSLType,
kHigh_GrSLPrecision,
"Coverage", "Coverage",
&coverageScale); &coverageScale);
fragBuilder->codeAppendf("%s = float4(%s * %s);", fragBuilder->codeAppendf("%s = half4(%s * %s);",
args.fOutputCoverage, coverageScale, edgeAlpha.c_str()); args.fOutputCoverage, coverageScale, edgeAlpha.c_str());
} else { } else {
fragBuilder->codeAppendf("%s = float4(%s);", args.fOutputCoverage, edgeAlpha.c_str()); fragBuilder->codeAppendf("%s = half4(%s);", args.fOutputCoverage, edgeAlpha.c_str());
} }
} }
@ -338,7 +331,7 @@ void GrGLQuadEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
// emit attributes // emit attributes
varyingHandler->emitAttributes(gp); varyingHandler->emitAttributes(gp);
GrGLSLVertToFrag v(kVec4f_GrSLType); GrGLSLVertToFrag v(kHalf4_GrSLType);
varyingHandler->addVarying("HairQuadEdge", &v); varyingHandler->addVarying("HairQuadEdge", &v);
vertBuilder->codeAppendf("%s = %s;", v.vsOut(), gp.inHairQuadEdge()->fName); vertBuilder->codeAppendf("%s = %s;", v.vsOut(), gp.inHairQuadEdge()->fName);
@ -363,13 +356,13 @@ void GrGLQuadEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
gp.localMatrix(), gp.localMatrix(),
args.fFPCoordTransformHandler); args.fFPCoordTransformHandler);
fragBuilder->codeAppendf("float edgeAlpha;"); fragBuilder->codeAppendf("half edgeAlpha;");
switch (fEdgeType) { switch (fEdgeType) {
case kHairlineAA_GrProcessorEdgeType: { case kHairlineAA_GrProcessorEdgeType: {
fragBuilder->codeAppendf("float2 duvdx = dFdx(%s.xy);", v.fsIn()); fragBuilder->codeAppendf("half2 duvdx = dFdx(%s.xy);", v.fsIn());
fragBuilder->codeAppendf("float2 duvdy = dFdy(%s.xy);", v.fsIn()); fragBuilder->codeAppendf("half2 duvdy = dFdy(%s.xy);", v.fsIn());
fragBuilder->codeAppendf("float2 gF = float2(2.0 * %s.x * duvdx.x - duvdx.y," fragBuilder->codeAppendf("half2 gF = half2(2.0 * %s.x * duvdx.x - duvdx.y,"
" 2.0 * %s.x * duvdy.x - duvdy.y);", " 2.0 * %s.x * duvdy.x - duvdy.y);",
v.fsIn(), v.fsIn()); v.fsIn(), v.fsIn());
fragBuilder->codeAppendf("edgeAlpha = (%s.x * %s.x - %s.y);", fragBuilder->codeAppendf("edgeAlpha = (%s.x * %s.x - %s.y);",
@ -381,9 +374,9 @@ void GrGLQuadEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
break; break;
} }
case kFillAA_GrProcessorEdgeType: { case kFillAA_GrProcessorEdgeType: {
fragBuilder->codeAppendf("float2 duvdx = dFdx(%s.xy);", v.fsIn()); fragBuilder->codeAppendf("half2 duvdx = dFdx(%s.xy);", v.fsIn());
fragBuilder->codeAppendf("float2 duvdy = dFdy(%s.xy);", v.fsIn()); fragBuilder->codeAppendf("half2 duvdy = dFdy(%s.xy);", v.fsIn());
fragBuilder->codeAppendf("float2 gF = float2(2.0 * %s.x * duvdx.x - duvdx.y," fragBuilder->codeAppendf("half2 gF = half2(2.0 * %s.x * duvdx.x - duvdx.y,"
" 2.0 * %s.x * duvdy.x - duvdy.y);", " 2.0 * %s.x * duvdy.x - duvdy.y);",
v.fsIn(), v.fsIn()); v.fsIn(), v.fsIn());
fragBuilder->codeAppendf("edgeAlpha = (%s.x * %s.x - %s.y);", fragBuilder->codeAppendf("edgeAlpha = (%s.x * %s.x - %s.y);",
@ -397,7 +390,7 @@ void GrGLQuadEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
case kFillBW_GrProcessorEdgeType: { case kFillBW_GrProcessorEdgeType: {
fragBuilder->codeAppendf("edgeAlpha = (%s.x * %s.x - %s.y);", fragBuilder->codeAppendf("edgeAlpha = (%s.x * %s.x - %s.y);",
v.fsIn(), v.fsIn(), v.fsIn()); v.fsIn(), v.fsIn(), v.fsIn());
fragBuilder->codeAppend("edgeAlpha = float(edgeAlpha < 0.0);"); fragBuilder->codeAppend("edgeAlpha = half(edgeAlpha < 0.0);");
break; break;
} }
default: default:
@ -407,13 +400,13 @@ void GrGLQuadEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
if (0xff != gp.coverageScale()) { if (0xff != gp.coverageScale()) {
const char* coverageScale; const char* coverageScale;
fCoverageScaleUniform = uniformHandler->addUniform(kFragment_GrShaderFlag, fCoverageScaleUniform = uniformHandler->addUniform(kFragment_GrShaderFlag,
kFloat_GrSLType, kHalf_GrSLType,
kDefault_GrSLPrecision,
"Coverage", "Coverage",
&coverageScale); &coverageScale);
fragBuilder->codeAppendf("%s = float4(%s * edgeAlpha);", args.fOutputCoverage, coverageScale); fragBuilder->codeAppendf("%s = half4(%s * edgeAlpha);", args.fOutputCoverage,
coverageScale);
} else { } else {
fragBuilder->codeAppendf("%s = float4(edgeAlpha);", args.fOutputCoverage); fragBuilder->codeAppendf("%s = half4(edgeAlpha);", args.fOutputCoverage);
} }
} }
@ -561,25 +554,25 @@ void GrGLCubicEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
// Setup KLM // Setup KLM
const char* devkLMMatrixName; const char* devkLMMatrixName;
fDevKLMUniform = uniformHandler->addUniform(kVertex_GrShaderFlag, kMat33f_GrSLType, fDevKLMUniform = uniformHandler->addUniform(kVertex_GrShaderFlag, kHighFloat3x3_GrSLType, "KLM",
kHigh_GrSLPrecision, "KLM", &devkLMMatrixName); &devkLMMatrixName);
GrGLSLVertToFrag v(kVec3f_GrSLType); GrGLSLVertToFrag v(kHighFloat3_GrSLType);
varyingHandler->addVarying("CubicCoeffs", &v, kHigh_GrSLPrecision); varyingHandler->addVarying("CubicCoeffs", &v, kHigh_GrSLPrecision);
vertBuilder->codeAppendf("%s = %s * float3(%s, 1);", vertBuilder->codeAppendf("%s = %s * highfloat3(%s, 1);",
v.vsOut(), devkLMMatrixName, gpArgs->fPositionVar.c_str()); v.vsOut(), devkLMMatrixName, gpArgs->fPositionVar.c_str());
GrGLSLVertToFrag gradCoeffs(kVec4f_GrSLType); GrGLSLVertToFrag gradCoeffs(kHighFloat4_GrSLType);
if (kFillAA_GrProcessorEdgeType == fEdgeType || kHairlineAA_GrProcessorEdgeType == fEdgeType) { if (kFillAA_GrProcessorEdgeType == fEdgeType || kHairlineAA_GrProcessorEdgeType == fEdgeType) {
varyingHandler->addVarying("GradCoeffs", &gradCoeffs, kHigh_GrSLPrecision); varyingHandler->addVarying("GradCoeffs", &gradCoeffs, kHigh_GrSLPrecision);
vertBuilder->codeAppendf("highp float k = %s[0], l = %s[1], m = %s[2];", vertBuilder->codeAppendf("highfloat k = %s[0], l = %s[1], m = %s[2];",
v.vsOut(), v.vsOut(), v.vsOut()); v.vsOut(), v.vsOut(), v.vsOut());
vertBuilder->codeAppendf("highp float2 gk = float2(%s[0][0], %s[1][0]), " vertBuilder->codeAppendf("highfloat2 gk = highfloat2(%s[0][0], %s[1][0]), "
"gl = float2(%s[0][1], %s[1][1]), " "gl = highfloat2(%s[0][1], %s[1][1]), "
"gm = float2(%s[0][2], %s[1][2]);", "gm = highfloat2(%s[0][2], %s[1][2]);",
devkLMMatrixName, devkLMMatrixName, devkLMMatrixName, devkLMMatrixName, devkLMMatrixName, devkLMMatrixName,
devkLMMatrixName, devkLMMatrixName, devkLMMatrixName); devkLMMatrixName, devkLMMatrixName, devkLMMatrixName);
vertBuilder->codeAppendf("%s = float4(3 * k * gk, -m * gl - l * gm);", vertBuilder->codeAppendf("%s = highfloat4(3 * k * gk, -m * gl - l * gm);",
gradCoeffs.vsOut()); gradCoeffs.vsOut());
} }
@ -592,9 +585,9 @@ void GrGLCubicEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
args.fFPCoordTransformHandler); args.fFPCoordTransformHandler);
GrShaderVar edgeAlpha("edgeAlpha", kFloat_GrSLType, 0, kHigh_GrSLPrecision); GrShaderVar edgeAlpha("edgeAlpha", kHighFloat_GrSLType, 0);
GrShaderVar gF("gF", kVec2f_GrSLType, 0, kHigh_GrSLPrecision); GrShaderVar gF("gF", kHighFloat2_GrSLType, 0);
GrShaderVar func("func", kFloat_GrSLType, 0, kHigh_GrSLPrecision); GrShaderVar func("func", kHighFloat_GrSLType, 0);
fragBuilder->declAppend(edgeAlpha); fragBuilder->declAppend(edgeAlpha);
fragBuilder->declAppend(gF); fragBuilder->declAppend(gF);
@ -638,7 +631,7 @@ void GrGLCubicEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
fragBuilder->codeAppendf("%s = %s.x * %s.x * %s.x - %s.y * %s.z;", fragBuilder->codeAppendf("%s = %s.x * %s.x * %s.x - %s.y * %s.z;",
edgeAlpha.c_str(), v.fsIn(), v.fsIn(), edgeAlpha.c_str(), v.fsIn(), v.fsIn(),
v.fsIn(), v.fsIn(), v.fsIn()); v.fsIn(), v.fsIn(), v.fsIn());
fragBuilder->codeAppendf("%s = float(%s < 0.0);", edgeAlpha.c_str(), edgeAlpha.c_str()); fragBuilder->codeAppendf("%s = half(%s < 0.0);", edgeAlpha.c_str(), edgeAlpha.c_str());
break; break;
} }
default: default:
@ -646,7 +639,7 @@ void GrGLCubicEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
} }
fragBuilder->codeAppendf("%s = float4(%s);", args.fOutputCoverage, edgeAlpha.c_str()); fragBuilder->codeAppendf("%s = highfloat4(%s);", args.fOutputCoverage, edgeAlpha.c_str());
} }
void GrGLCubicEffect::GenKey(const GrGeometryProcessor& gp, void GrGLCubicEffect::GenKey(const GrGeometryProcessor& gp,

View File

@ -42,8 +42,7 @@ void GrGLBicubicEffect::emitCode(EmitArgs& args) {
const GrBicubicEffect& bicubicEffect = args.fFp.cast<GrBicubicEffect>(); const GrBicubicEffect& bicubicEffect = args.fFp.cast<GrBicubicEffect>();
GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
fImageIncrementUni = uniformHandler->addUniform(kFragment_GrShaderFlag, fImageIncrementUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType,
kVec2f_GrSLType, kDefault_GrSLPrecision,
"ImageIncrement"); "ImageIncrement");
const char* imgInc = uniformHandler->getUniformCStr(fImageIncrementUni); const char* imgInc = uniformHandler->getUniformCStr(fImageIncrementUni);
@ -71,26 +70,26 @@ void GrGLBicubicEffect::emitCode(EmitArgs& args) {
* *
* This is GLSL, so the matrix is column-major (transposed from standard matrix notation). * This is GLSL, so the matrix is column-major (transposed from standard matrix notation).
*/ */
fragBuilder->codeAppend("float4x4 kMitchellCoefficients = float4x4(" fragBuilder->codeAppend("half4x4 kMitchellCoefficients = half4x4("
" 1.0 / 18.0, 16.0 / 18.0, 1.0 / 18.0, 0.0 / 18.0," " 1.0 / 18.0, 16.0 / 18.0, 1.0 / 18.0, 0.0 / 18.0,"
"-9.0 / 18.0, 0.0 / 18.0, 9.0 / 18.0, 0.0 / 18.0," "-9.0 / 18.0, 0.0 / 18.0, 9.0 / 18.0, 0.0 / 18.0,"
"15.0 / 18.0, -36.0 / 18.0, 27.0 / 18.0, -6.0 / 18.0," "15.0 / 18.0, -36.0 / 18.0, 27.0 / 18.0, -6.0 / 18.0,"
"-7.0 / 18.0, 21.0 / 18.0, -21.0 / 18.0, 7.0 / 18.0);"); "-7.0 / 18.0, 21.0 / 18.0, -21.0 / 18.0, 7.0 / 18.0);");
fragBuilder->codeAppendf("float2 coord = %s - %s * float2(0.5);", coords2D.c_str(), imgInc); fragBuilder->codeAppendf("highfloat2 coord = %s - %s * highfloat2(0.5);", coords2D.c_str(), imgInc);
// We unnormalize the coord in order to determine our fractional offset (f) within the texel // 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 // 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/ // starting coords are near a texel boundary and accumulations of imgInc would cause us to skip/
// double hit a texel. // double hit a texel.
fragBuilder->codeAppendf("coord /= %s;", imgInc); fragBuilder->codeAppendf("coord /= %s;", imgInc);
fragBuilder->codeAppend("float2 f = fract(coord);"); fragBuilder->codeAppend("highfloat2 f = fract(coord);");
fragBuilder->codeAppendf("coord = (coord - f + float2(0.5)) * %s;", imgInc); fragBuilder->codeAppendf("coord = (coord - f + highfloat2(0.5)) * %s;", imgInc);
fragBuilder->codeAppend("float4 wx = kMitchellCoefficients * float4(1.0, f.x, f.x * f.x, f.x * f.x * f.x);"); fragBuilder->codeAppend("half4 wx = kMitchellCoefficients * half4(1.0, f.x, f.x * f.x, f.x * f.x * f.x);");
fragBuilder->codeAppend("float4 wy = kMitchellCoefficients * float4(1.0, f.y, f.y * f.y, f.y * f.y * f.y);"); fragBuilder->codeAppend("half4 wy = kMitchellCoefficients * half4(1.0, f.y, f.y * f.y, f.y * f.y * f.y);");
fragBuilder->codeAppend("float4 rowColors[4];"); fragBuilder->codeAppend("half4 rowColors[4];");
for (int y = 0; y < 4; ++y) { for (int y = 0; y < 4; ++y) {
for (int x = 0; x < 4; ++x) { for (int x = 0; x < 4; ++x) {
SkString coord; SkString coord;
coord.printf("coord + %s * float2(%d, %d)", imgInc, x - 1, y - 1); coord.printf("coord + %s * highfloat2(%d, %d)", imgInc, x - 1, y - 1);
SkString sampleVar; SkString sampleVar;
sampleVar.printf("rowColors[%d]", x); sampleVar.printf("rowColors[%d]", x);
fDomain.sampleTexture(fragBuilder, fDomain.sampleTexture(fragBuilder,
@ -102,7 +101,7 @@ void GrGLBicubicEffect::emitCode(EmitArgs& args) {
args.fTexSamplers[0]); args.fTexSamplers[0]);
} }
fragBuilder->codeAppendf( fragBuilder->codeAppendf(
"float4 s%d = wx.x * rowColors[0] + wx.y * rowColors[1] + wx.z * rowColors[2] + wx.w * rowColors[3];", "half4 s%d = wx.x * rowColors[0] + wx.y * rowColors[1] + wx.z * rowColors[2] + wx.w * rowColors[3];",
y); y);
} }
SkString bicubicColor("(wy.x * s0 + wy.y * s1 + wy.z * s2 + wy.w * s3)"); SkString bicubicColor("(wy.x * s0 + wy.y * s1 + wy.z * s2 + wy.w * s3)");

View File

@ -32,13 +32,13 @@ public:
const char* atlasSizeInvName; const char* atlasSizeInvName;
fAtlasSizeInvUniform = uniformHandler->addUniform(kVertex_GrShaderFlag, fAtlasSizeInvUniform = uniformHandler->addUniform(kVertex_GrShaderFlag,
kVec2f_GrSLType, kHighFloat2_GrSLType,
kHigh_GrSLPrecision, kHigh_GrSLPrecision,
"AtlasSizeInv", "AtlasSizeInv",
&atlasSizeInvName); &atlasSizeInvName);
GrGLSLVertToFrag uv(kVec2f_GrSLType); GrGLSLVertToFrag uv(kHighFloat2_GrSLType);
GrGLSLVertToFrag texIdx(kFloat_GrSLType); GrGLSLVertToFrag texIdx(kHalf_GrSLType);
append_index_uv_varyings(args, btgp.inTextureCoords()->fName, atlasSizeInvName, append_index_uv_varyings(args, btgp.inTextureCoords()->fName, atlasSizeInvName,
&uv, &texIdx, nullptr); &uv, &texIdx, nullptr);
@ -63,14 +63,14 @@ public:
btgp.localMatrix(), btgp.localMatrix(),
args.fFPCoordTransformHandler); args.fFPCoordTransformHandler);
fragBuilder->codeAppend("float4 texColor;"); fragBuilder->codeAppend("half4 texColor;");
append_multitexture_lookup(args, btgp.numTextureSamplers(), append_multitexture_lookup(args, btgp.numTextureSamplers(),
texIdx, uv.fsIn(), "texColor"); texIdx, uv.fsIn(), "texColor");
if (btgp.maskFormat() == kARGB_GrMaskFormat) { if (btgp.maskFormat() == kARGB_GrMaskFormat) {
// modulate by color // modulate by color
fragBuilder->codeAppendf("%s = %s * texColor;", args.fOutputColor, args.fOutputColor); fragBuilder->codeAppendf("%s = %s * texColor;", args.fOutputColor, args.fOutputColor);
fragBuilder->codeAppendf("%s = float4(1);", args.fOutputCoverage); fragBuilder->codeAppendf("%s = half4(1);", args.fOutputCoverage);
} else { } else {
fragBuilder->codeAppendf("%s = texColor;", args.fOutputCoverage); fragBuilder->codeAppendf("%s = texColor;", args.fOutputCoverage);
} }

View File

@ -25,12 +25,12 @@ public:
args.fFp.cast<GrBlurredEdgeFragmentProcessor>(); args.fFp.cast<GrBlurredEdgeFragmentProcessor>();
(void)_outer; (void)_outer;
fragBuilder->codeAppendf( fragBuilder->codeAppendf(
"float factor = 1.0 - %s.w;\n@switch (%d) {\n case 0:\n factor = " "half factor = half(1.0 - highfloat(%s.w));\n@switch (%d) {\n case 0:\n "
"exp((-factor * factor) * 4.0) - 0.017999999999999999;\n break;\n case " "factor = half(exp(highfloat(highfloat(-factor * factor) * 4.0)) - "
"1:\n factor = smoothstep(1.0, 0.0, factor);\n break;\n}\n%s = " "0.017999999999999999);\n break;\n case 1:\n factor = "
"float4(factor);\n", "half(smoothstep(1.0, 0.0, highfloat(factor)));\n break;\n}\n%s = "
args.fInputColor ? args.fInputColor : "float4(1)", _outer.mode(), "half4(factor);\n",
args.fOutputColor); args.fInputColor ? args.fInputColor : "half4(1)", _outer.mode(), args.fOutputColor);
} }
private: private:

View File

@ -15,7 +15,7 @@
layout(key) in int mode; layout(key) in int mode;
void main() { void main() {
float factor = 1.0 - sk_InColor.a; half factor = 1.0 - sk_InColor.a;
@switch (mode) { @switch (mode) {
case 0: // kGaussian_Mode case 0: // kGaussian_Mode
factor = exp(-factor * factor * 4.0) - 0.018; factor = exp(-factor * factor * 4.0) - 0.018;
@ -24,5 +24,5 @@ void main() {
factor = smoothstep(1.0, 0.0, factor); factor = smoothstep(1.0, 0.0, factor);
break; break;
} }
sk_OutColor = float4(factor); sk_OutColor = half4(factor);
} }

View File

@ -24,14 +24,15 @@ public:
const GrCircleEffect& _outer = args.fFp.cast<GrCircleEffect>(); const GrCircleEffect& _outer = args.fFp.cast<GrCircleEffect>();
(void)_outer; (void)_outer;
prevRadius = -1.0; prevRadius = -1.0;
fCircleVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kVec4f_GrSLType, fCircleVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType,
kDefault_GrSLPrecision, "circle"); kDefault_GrSLPrecision, "circle");
fragBuilder->codeAppendf( fragBuilder->codeAppendf(
"float2 prevCenter;\nfloat prevRadius = %f;\nfloat d;\n@if (%d == 2 || %d == 3) " "half2 prevCenter;\nhalf prevRadius = %f;\nhalf d;\n@if (%d == 2 || %d == 3) {\n "
"{\n d = (length((%s.xy - sk_FragCoord.xy) * %s.w) - 1.0) * %s.z;\n} else {\n " " d = (highfloat(length((%s.xy - half2(sk_FragCoord.xy)) * %s.w)) - 1.0) * "
" d = (1.0 - length((%s.xy - sk_FragCoord.xy) * %s.w)) * %s.z;\n}\n@if ((%d == 1 " "%s.z;\n} else {\n d = half((1.0 - highfloat(length((%s.xy - "
"|| %d == 3) || %d == 4) {\n d = clamp(d, 0.0, 1.0);\n} else {\n d = d > 0.5 " "half2(sk_FragCoord.xy)) * %s.w))) * highfloat(%s.z));\n}\n@if ((%d == 1 || %d == "
"? 1.0 : 0.0;\n}\n%s = %s * d;\n", "3) || %d == 4) {\n d = half(clamp(highfloat(d), 0.0, 1.0));\n} else {\n d = "
"half(highfloat(d) > 0.5 ? 1.0 : 0.0);\n}\n%s = %s * d;\n",
prevRadius, _outer.edgeType(), _outer.edgeType(), prevRadius, _outer.edgeType(), _outer.edgeType(),
args.fUniformHandler->getUniformCStr(fCircleVar), args.fUniformHandler->getUniformCStr(fCircleVar),
args.fUniformHandler->getUniformCStr(fCircleVar), args.fUniformHandler->getUniformCStr(fCircleVar),
@ -40,7 +41,7 @@ public:
args.fUniformHandler->getUniformCStr(fCircleVar), args.fUniformHandler->getUniformCStr(fCircleVar),
args.fUniformHandler->getUniformCStr(fCircleVar), _outer.edgeType(), args.fUniformHandler->getUniformCStr(fCircleVar), _outer.edgeType(),
_outer.edgeType(), _outer.edgeType(), args.fOutputColor, _outer.edgeType(), _outer.edgeType(), args.fOutputColor,
args.fInputColor ? args.fInputColor : "float4(1)"); args.fInputColor ? args.fInputColor : "half4(1)");
} }
private: private:

View File

@ -6,14 +6,14 @@
*/ */
layout(key) in int edgeType; layout(key) in int edgeType;
in float2 center; in half2 center;
in float radius; in half radius;
float2 prevCenter; half2 prevCenter;
float prevRadius = -1; half prevRadius = -1;
// The circle uniform is (center.x, center.y, radius + 0.5, 1 / (radius + 0.5)) for regular // The circle uniform is (center.x, center.y, radius + 0.5, 1 / (radius + 0.5)) for regular
// fills and (..., radius - 0.5, 1 / (radius - 0.5)) for inverse fills. // fills and (..., radius - 0.5, 1 / (radius - 0.5)) for inverse fills.
uniform float4 circle; uniform half4 circle;
@optimizationFlags { kCompatibleWithCoverageAsAlpha_OptimizationFlag } @optimizationFlags { kCompatibleWithCoverageAsAlpha_OptimizationFlag }
@ -36,7 +36,7 @@ void main() {
// TODO: Right now the distance to circle caclulation is performed in a space normalized to the // TODO: Right now the distance to circle caclulation is performed in a space normalized to the
// radius and then denormalized. This is to prevent overflow on devices that have a "real" // radius and then denormalized. This is to prevent overflow on devices that have a "real"
// mediump. It'd be nice to only do this on mediump devices. // mediump. It'd be nice to only do this on mediump devices.
float d; half d;
@if (edgeType == 2 /* kInverseFillBW_GrProcessorEdgeType */ || @if (edgeType == 2 /* kInverseFillBW_GrProcessorEdgeType */ ||
edgeType == 3 /* kInverseFillAA_GrProcessorEdgeType */) { edgeType == 3 /* kInverseFillAA_GrProcessorEdgeType */) {
d = (length((circle.xy - sk_FragCoord.xy) * circle.w) - 1.0) * circle.z; d = (length((circle.xy - sk_FragCoord.xy) * circle.w) - 1.0) * circle.z;

View File

@ -21,16 +21,16 @@ public:
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
// Use highp throughout the shader to avoid some precision issues on specific GPUs. // Use highp throughout the shader to avoid some precision issues on specific GPUs.
fragBuilder->elevateDefaultPrecision(kHigh_GrSLPrecision); fragBuilder->forceHighPrecision();
if (nullptr == args.fInputColor) { if (nullptr == args.fInputColor) {
// could optimize this case, but we aren't for now. // could optimize this case, but we aren't for now.
args.fInputColor = "float4(1)"; args.fInputColor = "half4(1)";
} }
// Aggressively round to the nearest exact (N / 255) floating point value. This lets us // Aggressively round to the nearest exact (N / 255) floating point value. This lets us
// find a round-trip preserving pair on some GPUs that do odd byte to float conversion. // find a round-trip preserving pair on some GPUs that do odd byte to float conversion.
fragBuilder->codeAppendf("float4 color = floor(%s * 255.0 + 0.5) / 255.0;", args.fInputColor); fragBuilder->codeAppendf("half4 color = floor(%s * 255.0 + 0.5) / 255.0;", args.fInputColor);
switch (cce.pmConversion()) { switch (cce.pmConversion()) {
case GrConfigConversionEffect::kToPremul_PMConversion: case GrConfigConversionEffect::kToPremul_PMConversion:
@ -40,7 +40,7 @@ public:
case GrConfigConversionEffect::kToUnpremul_PMConversion: case GrConfigConversionEffect::kToUnpremul_PMConversion:
fragBuilder->codeAppend( fragBuilder->codeAppend(
"color.rgb = color.a <= 0.0 ? float3(0,0,0) : floor(color.rgb / color.a * 255.0 + 0.5) / 255.0;"); "color.rgb = color.a <= 0.0 ? half3(0,0,0) : floor(color.rgb / color.a * 255.0 + 0.5) / 255.0;");
break; break;
default: default:

View File

@ -19,7 +19,7 @@ public:
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
const char* colorUni; const char* colorUni;
fColorUniform = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, fColorUniform = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
kVec4f_GrSLType, kMedium_GrSLPrecision, kHalf4_GrSLType,
"constantColor", "constantColor",
&colorUni); &colorUni);
GrConstColorProcessor::InputMode mode = args.fFp.cast<GrConstColorProcessor>().inputMode(); GrConstColorProcessor::InputMode mode = args.fFp.cast<GrConstColorProcessor>().inputMode();

View File

@ -103,8 +103,7 @@ void GLAARectEffect::emitCode(EmitArgs& args) {
// The rect uniform's xyzw refer to (left + 0.5, top + 0.5, right - 0.5, bottom - 0.5), // The rect uniform's xyzw refer to (left + 0.5, top + 0.5, right - 0.5, bottom - 0.5),
// respectively. // respectively.
fRectUniform = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, fRectUniform = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
kVec4f_GrSLType, kHalf4_GrSLType,
kDefault_GrSLPrecision,
"rect", "rect",
&rectName); &rectName);
@ -112,16 +111,16 @@ void GLAARectEffect::emitCode(EmitArgs& args) {
if (GrProcessorEdgeTypeIsAA(aare.getEdgeType())) { if (GrProcessorEdgeTypeIsAA(aare.getEdgeType())) {
// The amount of coverage removed in x and y by the edges is computed as a pair of negative // The amount of coverage removed in x and y by the edges is computed as a pair of negative
// numbers, xSub and ySub. // numbers, xSub and ySub.
fragBuilder->codeAppend("\t\tfloat xSub, ySub;\n"); fragBuilder->codeAppend("\t\thalf xSub, ySub;\n");
fragBuilder->codeAppendf("\t\txSub = min(sk_FragCoord.x - %s.x, 0.0);\n", rectName); fragBuilder->codeAppendf("\t\txSub = min(sk_FragCoord.x - %s.x, 0.0);\n", rectName);
fragBuilder->codeAppendf("\t\txSub += min(%s.z - sk_FragCoord.x, 0.0);\n", rectName); fragBuilder->codeAppendf("\t\txSub += min(%s.z - sk_FragCoord.x, 0.0);\n", rectName);
fragBuilder->codeAppendf("\t\tySub = min(sk_FragCoord.y - %s.y, 0.0);\n", rectName); fragBuilder->codeAppendf("\t\tySub = min(sk_FragCoord.y - %s.y, 0.0);\n", rectName);
fragBuilder->codeAppendf("\t\tySub += min(%s.w - sk_FragCoord.y, 0.0);\n", rectName); fragBuilder->codeAppendf("\t\tySub += min(%s.w - sk_FragCoord.y, 0.0);\n", rectName);
// Now compute coverage in x and y and multiply them to get the fraction of the pixel // Now compute coverage in x and y and multiply them to get the fraction of the pixel
// covered. // covered.
fragBuilder->codeAppendf("\t\tfloat alpha = (1.0 + max(xSub, -1.0)) * (1.0 + max(ySub, -1.0));\n"); fragBuilder->codeAppendf("\t\thalf alpha = (1.0 + max(xSub, -1.0)) * (1.0 + max(ySub, -1.0));\n");
} else { } else {
fragBuilder->codeAppendf("\t\tfloat alpha = 1.0;\n"); fragBuilder->codeAppendf("\t\thalf alpha = 1.0;\n");
fragBuilder->codeAppendf("\t\talpha *= (sk_FragCoord.x - %s.x) > -0.5 ? 1.0 : 0.0;\n", fragBuilder->codeAppendf("\t\talpha *= (sk_FragCoord.x - %s.x) > -0.5 ? 1.0 : 0.0;\n",
rectName); rectName);
fragBuilder->codeAppendf("\t\talpha *= (%s.z - sk_FragCoord.x) > -0.5 ? 1.0 : 0.0;\n", fragBuilder->codeAppendf("\t\talpha *= (%s.z - sk_FragCoord.x) > -0.5 ? 1.0 : 0.0;\n",
@ -191,16 +190,15 @@ void GrGLConvexPolyEffect::emitCode(EmitArgs& args) {
const char *edgeArrayName; const char *edgeArrayName;
fEdgeUniform = args.fUniformHandler->addUniformArray(kFragment_GrShaderFlag, fEdgeUniform = args.fUniformHandler->addUniformArray(kFragment_GrShaderFlag,
kVec3f_GrSLType, kHalf3_GrSLType,
kDefault_GrSLPrecision,
"edges", "edges",
cpe.getEdgeCount(), cpe.getEdgeCount(),
&edgeArrayName); &edgeArrayName);
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
fragBuilder->codeAppend("\t\tfloat alpha = 1.0;\n"); fragBuilder->codeAppend("\t\thalf alpha = 1.0;\n");
fragBuilder->codeAppend("\t\tfloat edge;\n"); fragBuilder->codeAppend("\t\thalf edge;\n");
for (int i = 0; i < cpe.getEdgeCount(); ++i) { for (int i = 0; i < cpe.getEdgeCount(); ++i) {
fragBuilder->codeAppendf("\t\tedge = dot(%s[%d], float3(sk_FragCoord.x, sk_FragCoord.y, " fragBuilder->codeAppendf("\t\tedge = dot(%s[%d], half3(sk_FragCoord.x, sk_FragCoord.y, "
"1));\n", "1));\n",
edgeArrayName, i); edgeArrayName, i);
if (GrProcessorEdgeTypeIsAA(cpe.getEdgeType())) { if (GrProcessorEdgeTypeIsAA(cpe.getEdgeType())) {

View File

@ -53,7 +53,7 @@ private:
// you do not give gl_FragColor a value, the gl context is lost and we end up drawing // you do not give gl_FragColor a value, the gl context is lost and we end up drawing
// nothing. So this fix just sets the gl_FragColor arbitrarily to 0. // nothing. So this fix just sets the gl_FragColor arbitrarily to 0.
GrGLSLXPFragmentBuilder* fragBuilder = args.fXPFragBuilder; GrGLSLXPFragmentBuilder* fragBuilder = args.fXPFragBuilder;
fragBuilder->codeAppendf("%s = float4(0);", args.fOutputPrimary); fragBuilder->codeAppendf("%s = half4(0);", args.fOutputPrimary);
} }
void onSetData(const GrGLSLProgramDataManager&, const GrXferProcessor&) override {} void onSetData(const GrGLSLProgramDataManager&, const GrXferProcessor&) override {}

View File

@ -45,7 +45,7 @@ public:
const char* atlasSizeInvName; const char* atlasSizeInvName;
fAtlasSizeInvUniform = uniformHandler->addUniform(kVertex_GrShaderFlag, fAtlasSizeInvUniform = uniformHandler->addUniform(kVertex_GrShaderFlag,
kVec2f_GrSLType, kHighFloat2_GrSLType,
kHigh_GrSLPrecision, kHigh_GrSLPrecision,
"AtlasSizeInv", "AtlasSizeInv",
&atlasSizeInvName); &atlasSizeInvName);
@ -53,8 +53,7 @@ public:
// adjust based on gamma // adjust based on gamma
const char* distanceAdjustUniName = nullptr; const char* distanceAdjustUniName = nullptr;
// width, height, 1/(3*width) // width, height, 1/(3*width)
fDistanceAdjustUni = uniformHandler->addUniform(kFragment_GrShaderFlag, fDistanceAdjustUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType,
kFloat_GrSLType, kDefault_GrSLPrecision,
"DistanceAdjust", &distanceAdjustUniName); "DistanceAdjust", &distanceAdjustUniName);
#endif #endif
@ -78,9 +77,9 @@ public:
args.fFPCoordTransformHandler); args.fFPCoordTransformHandler);
// add varyings // add varyings
GrGLSLVertToFrag uv(kVec2f_GrSLType); GrGLSLVertToFrag uv(kHighFloat2_GrSLType);
GrGLSLVertToFrag texIdx(kFloat_GrSLType); GrGLSLVertToFrag texIdx(kHalf_GrSLType);
GrGLSLVertToFrag st(kVec2f_GrSLType); GrGLSLVertToFrag st(kHighFloat2_GrSLType);
append_index_uv_varyings(args, dfTexEffect.inTextureCoords()->fName, atlasSizeInvName, append_index_uv_varyings(args, dfTexEffect.inTextureCoords()->fName, atlasSizeInvName,
&uv, &texIdx, &st); &uv, &texIdx, &st);
@ -93,19 +92,19 @@ public:
SkToBool(dfTexEffect.getFlags() & kAliased_DistanceFieldEffectFlag); SkToBool(dfTexEffect.getFlags() & kAliased_DistanceFieldEffectFlag);
// Use highp to work around aliasing issues // Use highp to work around aliasing issues
fragBuilder->codeAppendf("highp float2 uv = %s;\n", uv.fsIn()); fragBuilder->codeAppendf("highfloat2 uv = %s;\n", uv.fsIn());
fragBuilder->codeAppend("float4 texColor;"); fragBuilder->codeAppend("half4 texColor;");
append_multitexture_lookup(args, dfTexEffect.numTextureSamplers(), append_multitexture_lookup(args, dfTexEffect.numTextureSamplers(),
texIdx, "uv", "texColor"); texIdx, "uv", "texColor");
fragBuilder->codeAppend("float distance = " fragBuilder->codeAppend("half distance = "
SK_DistanceFieldMultiplier "*(texColor.r - " SK_DistanceFieldThreshold ");"); SK_DistanceFieldMultiplier "*(texColor.r - " SK_DistanceFieldThreshold ");");
#ifdef SK_GAMMA_APPLY_TO_A8 #ifdef SK_GAMMA_APPLY_TO_A8
// adjust width based on gamma // adjust width based on gamma
fragBuilder->codeAppendf("distance -= %s;", distanceAdjustUniName); fragBuilder->codeAppendf("distance -= %s;", distanceAdjustUniName);
#endif #endif
fragBuilder->codeAppend("float afwidth;"); fragBuilder->codeAppend("half afwidth;");
if (isUniformScale) { if (isUniformScale) {
// For uniform scale, we adjust for the effect of the transformation on the distance // For uniform scale, we adjust for the effect of the transformation on the distance
// by using the length of the gradient of the t coordinate in the y direction. // by using the length of the gradient of the t coordinate in the y direction.
@ -128,29 +127,29 @@ public:
// this gives us a smooth step across approximately one fragment // this gives us a smooth step across approximately one fragment
#ifdef SK_VULKAN #ifdef SK_VULKAN
fragBuilder->codeAppendf("float st_grad_len = length(dFdx(%s));", st.fsIn()); fragBuilder->codeAppendf("half st_grad_len = length(dFdx(%s));", st.fsIn());
#else #else
// We use the y gradient because there is a bug in the Mali 400 in the x direction. // We use the y gradient because there is a bug in the Mali 400 in the x direction.
fragBuilder->codeAppendf("float st_grad_len = length(dFdy(%s));", st.fsIn()); fragBuilder->codeAppendf("half st_grad_len = length(dFdy(%s));", st.fsIn());
#endif #endif
fragBuilder->codeAppend("afwidth = abs(" SK_DistanceFieldAAFactor "*st_grad_len);"); fragBuilder->codeAppend("afwidth = abs(" SK_DistanceFieldAAFactor "*st_grad_len);");
} else { } else {
// For general transforms, to determine the amount of correction we multiply a unit // For general transforms, to determine the amount of correction we multiply a unit
// vector pointing along the SDF gradient direction by the Jacobian of the st coords // vector pointing along the SDF gradient direction by the Jacobian of the st coords
// (which is the inverse transform for this fragment) and take the length of the result. // (which is the inverse transform for this fragment) and take the length of the result.
fragBuilder->codeAppend("float2 dist_grad = float2(dFdx(distance), dFdy(distance));"); fragBuilder->codeAppend("half2 dist_grad = half2(dFdx(distance), dFdy(distance));");
// the length of the gradient may be 0, so we need to check for this // the length of the gradient may be 0, so we need to check for this
// this also compensates for the Adreno, which likes to drop tiles on division by 0 // this also compensates for the Adreno, which likes to drop tiles on division by 0
fragBuilder->codeAppend("float dg_len2 = dot(dist_grad, dist_grad);"); fragBuilder->codeAppend("half dg_len2 = dot(dist_grad, dist_grad);");
fragBuilder->codeAppend("if (dg_len2 < 0.0001) {"); fragBuilder->codeAppend("if (dg_len2 < 0.0001) {");
fragBuilder->codeAppend("dist_grad = float2(0.7071, 0.7071);"); fragBuilder->codeAppend("dist_grad = half2(0.7071, 0.7071);");
fragBuilder->codeAppend("} else {"); fragBuilder->codeAppend("} else {");
fragBuilder->codeAppend("dist_grad = dist_grad*inversesqrt(dg_len2);"); fragBuilder->codeAppend("dist_grad = dist_grad*inversesqrt(dg_len2);");
fragBuilder->codeAppend("}"); fragBuilder->codeAppend("}");
fragBuilder->codeAppendf("float2 Jdx = dFdx(%s);", st.fsIn()); fragBuilder->codeAppendf("half2 Jdx = dFdx(%s);", st.fsIn());
fragBuilder->codeAppendf("float2 Jdy = dFdy(%s);", st.fsIn()); fragBuilder->codeAppendf("half2 Jdy = dFdy(%s);", st.fsIn());
fragBuilder->codeAppend("float2 grad = float2(dist_grad.x*Jdx.x + dist_grad.y*Jdy.x,"); fragBuilder->codeAppend("half2 grad = half2(dist_grad.x*Jdx.x + dist_grad.y*Jdy.x,");
fragBuilder->codeAppend(" dist_grad.x*Jdx.y + dist_grad.y*Jdy.y);"); fragBuilder->codeAppend(" dist_grad.x*Jdx.y + dist_grad.y*Jdy.y);");
// this gives us a smooth step across approximately one fragment // this gives us a smooth step across approximately one fragment
@ -158,18 +157,18 @@ public:
} }
if (isAliased) { if (isAliased) {
fragBuilder->codeAppend("float val = distance > 0 ? 1.0 : 0.0;"); fragBuilder->codeAppend("half val = distance > 0 ? 1.0 : 0.0;");
} else if (isGammaCorrect) { } else if (isGammaCorrect) {
// The smoothstep falloff compensates for the non-linear sRGB response curve. If we are // The smoothstep falloff compensates for the non-linear sRGB response curve. If we are
// doing gamma-correct rendering (to an sRGB or F16 buffer), then we actually want // doing gamma-correct rendering (to an sRGB or F16 buffer), then we actually want
// distance mapped linearly to coverage, so use a linear step: // distance mapped linearly to coverage, so use a linear step:
fragBuilder->codeAppend( fragBuilder->codeAppend(
"float val = clamp((distance + afwidth) / (2.0 * afwidth), 0.0, 1.0);"); "half val = clamp((distance + afwidth) / (2.0 * afwidth), 0.0, 1.0);");
} else { } else {
fragBuilder->codeAppend("float val = smoothstep(-afwidth, afwidth, distance);"); fragBuilder->codeAppend("half val = smoothstep(-afwidth, afwidth, distance);");
} }
fragBuilder->codeAppendf("%s = float4(val);", args.fOutputCoverage); fragBuilder->codeAppendf("%s = half4(val);", args.fOutputCoverage);
} }
void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& proc, void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& proc,
@ -331,14 +330,14 @@ public:
const char* atlasSizeInvName; const char* atlasSizeInvName;
fAtlasSizeInvUniform = uniformHandler->addUniform(kVertex_GrShaderFlag, fAtlasSizeInvUniform = uniformHandler->addUniform(kVertex_GrShaderFlag,
kVec2f_GrSLType, kHighFloat2_GrSLType,
kHigh_GrSLPrecision, kHigh_GrSLPrecision,
"AtlasSizeInv", "AtlasSizeInv",
&atlasSizeInvName); &atlasSizeInvName);
GrGLSLVertToFrag uv(kVec2f_GrSLType); GrGLSLVertToFrag uv(kHighFloat2_GrSLType);
GrGLSLVertToFrag texIdx(kFloat_GrSLType); GrGLSLVertToFrag texIdx(kHalf_GrSLType);
GrGLSLVertToFrag st(kVec2f_GrSLType); GrGLSLVertToFrag st(kHighFloat2_GrSLType);
append_index_uv_varyings(args, dfTexEffect.inTextureCoords()->fName, atlasSizeInvName, append_index_uv_varyings(args, dfTexEffect.inTextureCoords()->fName, atlasSizeInvName,
&uv, &texIdx, &st); &uv, &texIdx, &st);
@ -362,15 +361,15 @@ public:
args.fFPCoordTransformHandler); args.fFPCoordTransformHandler);
// Use highp to work around aliasing issues // Use highp to work around aliasing issues
fragBuilder->codeAppendf("highp float2 uv = %s;", uv.fsIn()); fragBuilder->codeAppendf("highfloat2 uv = %s;", uv.fsIn());
fragBuilder->codeAppend("float4 texColor;"); fragBuilder->codeAppend("half4 texColor;");
append_multitexture_lookup(args, dfTexEffect.numTextureSamplers(), append_multitexture_lookup(args, dfTexEffect.numTextureSamplers(),
texIdx, "uv", "texColor"); texIdx, "uv", "texColor");
fragBuilder->codeAppend("float distance = " fragBuilder->codeAppend("half distance = "
SK_DistanceFieldMultiplier "*(texColor.r - " SK_DistanceFieldThreshold ");"); SK_DistanceFieldMultiplier "*(texColor.r - " SK_DistanceFieldThreshold ");");
fragBuilder->codeAppend("float afwidth;"); fragBuilder->codeAppend("half afwidth;");
bool isUniformScale = (dfTexEffect.getFlags() & kUniformScale_DistanceFieldEffectMask) == bool isUniformScale = (dfTexEffect.getFlags() & kUniformScale_DistanceFieldEffectMask) ==
kUniformScale_DistanceFieldEffectMask; kUniformScale_DistanceFieldEffectMask;
bool isSimilarity = SkToBool(dfTexEffect.getFlags() & kSimilarity_DistanceFieldEffectFlag); bool isSimilarity = SkToBool(dfTexEffect.getFlags() & kSimilarity_DistanceFieldEffectFlag);
@ -397,30 +396,30 @@ public:
// this gives us a smooth step across approximately one fragment // this gives us a smooth step across approximately one fragment
#ifdef SK_VULKAN #ifdef SK_VULKAN
fragBuilder->codeAppendf("float st_grad_len = length(dFdx(%s));", st.fsIn()); fragBuilder->codeAppendf("half st_grad_len = length(dFdx(%s));", st.fsIn());
#else #else
// We use the y gradient because there is a bug in the Mali 400 in the x direction. // We use the y gradient because there is a bug in the Mali 400 in the x direction.
fragBuilder->codeAppendf("float st_grad_len = length(dFdy(%s));", st.fsIn()); fragBuilder->codeAppendf("half st_grad_len = length(dFdy(%s));", st.fsIn());
#endif #endif
fragBuilder->codeAppend("afwidth = abs(" SK_DistanceFieldAAFactor "*st_grad_len);"); fragBuilder->codeAppend("afwidth = abs(" SK_DistanceFieldAAFactor "*st_grad_len);");
} else { } else {
// For general transforms, to determine the amount of correction we multiply a unit // For general transforms, to determine the amount of correction we multiply a unit
// vector pointing along the SDF gradient direction by the Jacobian of the st coords // vector pointing along the SDF gradient direction by the Jacobian of the st coords
// (which is the inverse transform for this fragment) and take the length of the result. // (which is the inverse transform for this fragment) and take the length of the result.
fragBuilder->codeAppend("float2 dist_grad = float2(dFdx(distance), dFdy(distance));"); fragBuilder->codeAppend("half2 dist_grad = half2(dFdx(distance), dFdy(distance));");
// the length of the gradient may be 0, so we need to check for this // the length of the gradient may be 0, so we need to check for this
// this also compensates for the Adreno, which likes to drop tiles on division by 0 // this also compensates for the Adreno, which likes to drop tiles on division by 0
fragBuilder->codeAppend("float dg_len2 = dot(dist_grad, dist_grad);"); fragBuilder->codeAppend("half dg_len2 = dot(dist_grad, dist_grad);");
fragBuilder->codeAppend("if (dg_len2 < 0.0001) {"); fragBuilder->codeAppend("if (dg_len2 < 0.0001) {");
fragBuilder->codeAppend("dist_grad = float2(0.7071, 0.7071);"); fragBuilder->codeAppend("dist_grad = half2(0.7071, 0.7071);");
fragBuilder->codeAppend("} else {"); fragBuilder->codeAppend("} else {");
fragBuilder->codeAppend("dist_grad = dist_grad*inversesqrt(dg_len2);"); fragBuilder->codeAppend("dist_grad = dist_grad*inversesqrt(dg_len2);");
fragBuilder->codeAppend("}"); fragBuilder->codeAppend("}");
fragBuilder->codeAppendf("float2 Jdx = dFdx(%s);", st.fsIn()); fragBuilder->codeAppendf("half2 Jdx = dFdx(%s);", st.fsIn());
fragBuilder->codeAppendf("float2 Jdy = dFdy(%s);", st.fsIn()); fragBuilder->codeAppendf("half2 Jdy = dFdy(%s);", st.fsIn());
fragBuilder->codeAppend("float2 grad = float2(dist_grad.x*Jdx.x + dist_grad.y*Jdy.x,"); fragBuilder->codeAppend("half2 grad = half2(dist_grad.x*Jdx.x + dist_grad.y*Jdy.x,");
fragBuilder->codeAppend(" dist_grad.x*Jdx.y + dist_grad.y*Jdy.y);"); fragBuilder->codeAppend(" dist_grad.x*Jdx.y + dist_grad.y*Jdy.y);");
// this gives us a smooth step across approximately one fragment // this gives us a smooth step across approximately one fragment
fragBuilder->codeAppend("afwidth = " SK_DistanceFieldAAFactor "*length(grad);"); fragBuilder->codeAppend("afwidth = " SK_DistanceFieldAAFactor "*length(grad);");
@ -430,12 +429,12 @@ public:
// mapped linearly to coverage, so use a linear step: // mapped linearly to coverage, so use a linear step:
if (isGammaCorrect) { if (isGammaCorrect) {
fragBuilder->codeAppend( fragBuilder->codeAppend(
"float val = clamp((distance + afwidth) / (2.0 * afwidth), 0.0, 1.0);"); "half val = clamp((distance + afwidth) / (2.0 * afwidth), 0.0, 1.0);");
} else { } else {
fragBuilder->codeAppend("float val = smoothstep(-afwidth, afwidth, distance);"); fragBuilder->codeAppend("half val = smoothstep(-afwidth, afwidth, distance);");
} }
fragBuilder->codeAppendf("%s = float4(val);", args.fOutputCoverage); fragBuilder->codeAppendf("%s = half4(val);", args.fOutputCoverage);
} }
void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& proc, void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& proc,
@ -580,7 +579,7 @@ public:
const char* atlasSizeInvName; const char* atlasSizeInvName;
fAtlasSizeInvUniform = uniformHandler->addUniform(kVertex_GrShaderFlag, fAtlasSizeInvUniform = uniformHandler->addUniform(kVertex_GrShaderFlag,
kVec2f_GrSLType, kHighFloat2_GrSLType,
kHigh_GrSLPrecision, kHigh_GrSLPrecision,
"AtlasSizeInv", "AtlasSizeInv",
&atlasSizeInvName); &atlasSizeInvName);
@ -607,13 +606,13 @@ public:
args.fFPCoordTransformHandler); args.fFPCoordTransformHandler);
// set up varyings // set up varyings
GrGLSLVertToFrag uv(kVec2f_GrSLType); GrGLSLVertToFrag uv(kHighFloat2_GrSLType);
GrGLSLVertToFrag texIdx(kFloat_GrSLType); GrGLSLVertToFrag texIdx(kHalf_GrSLType);
GrGLSLVertToFrag st(kVec2f_GrSLType); GrGLSLVertToFrag st(kHighFloat2_GrSLType);
append_index_uv_varyings(args, dfTexEffect.inTextureCoords()->fName, atlasSizeInvName, append_index_uv_varyings(args, dfTexEffect.inTextureCoords()->fName, atlasSizeInvName,
&uv, &texIdx, &st); &uv, &texIdx, &st);
GrGLSLVertToFrag delta(kFloat_GrSLType); GrGLSLVertToFrag delta(kHighFloat_GrSLType);
varyingHandler->addVarying("Delta", &delta, kHigh_GrSLPrecision); varyingHandler->addVarying("Delta", &delta, kHigh_GrSLPrecision);
if (dfTexEffect.getFlags() & kBGR_DistanceFieldEffectFlag) { if (dfTexEffect.getFlags() & kBGR_DistanceFieldEffectFlag) {
vertBuilder->codeAppendf("%s = -%s.x/3.0;", delta.vsOut(), atlasSizeInvName); vertBuilder->codeAppendf("%s = -%s.x/3.0;", delta.vsOut(), atlasSizeInvName);
@ -630,48 +629,48 @@ public:
// create LCD offset adjusted by inverse of transform // create LCD offset adjusted by inverse of transform
// Use highp to work around aliasing issues // Use highp to work around aliasing issues
fragBuilder->codeAppendf("highp float2 uv = %s;\n", uv.fsIn()); fragBuilder->codeAppendf("highfloat2 uv = %s;\n", uv.fsIn());
if (isUniformScale) { if (isUniformScale) {
#ifdef SK_VULKAN #ifdef SK_VULKAN
fragBuilder->codeAppendf("float st_grad_len = abs(dFdx(%s.x));", st.fsIn()); fragBuilder->codeAppendf("half st_grad_len = abs(dFdx(%s.x));", st.fsIn());
#else #else
// We use the y gradient because there is a bug in the Mali 400 in the x direction. // We use the y gradient because there is a bug in the Mali 400 in the x direction.
fragBuilder->codeAppendf("float st_grad_len = abs(dFdy(%s.y));", st.fsIn()); fragBuilder->codeAppendf("half st_grad_len = abs(dFdy(%s.y));", st.fsIn());
#endif #endif
fragBuilder->codeAppendf("float2 offset = float2(st_grad_len*%s, 0.0);", delta.fsIn()); fragBuilder->codeAppendf("half2 offset = half2(st_grad_len*%s, 0.0);", delta.fsIn());
} else if (isSimilarity) { } else if (isSimilarity) {
// For a similarity matrix with rotation, the gradient will not be aligned // For a similarity matrix with rotation, the gradient will not be aligned
// with the texel coordinate axes, so we need to calculate it. // with the texel coordinate axes, so we need to calculate it.
#ifdef SK_VULKAN #ifdef SK_VULKAN
fragBuilder->codeAppendf("float2 st_grad = dFdx(%s);", st.fsIn()); fragBuilder->codeAppendf("half2 st_grad = dFdx(%s);", st.fsIn());
fragBuilder->codeAppendf("float2 offset = %s*st_grad;", delta.fsIn()); fragBuilder->codeAppendf("half2 offset = %s*st_grad;", delta.fsIn());
#else #else
// We use dFdy because of a Mali 400 bug, and rotate -90 degrees to // We use dFdy because of a Mali 400 bug, and rotate -90 degrees to
// get the gradient in the x direction. // get the gradient in the x direction.
fragBuilder->codeAppendf("float2 st_grad = dFdy(%s);", st.fsIn()); fragBuilder->codeAppendf("half2 st_grad = dFdy(%s);", st.fsIn());
fragBuilder->codeAppendf("float2 offset = %s*float2(st_grad.y, -st_grad.x);", fragBuilder->codeAppendf("half2 offset = %s*half2(st_grad.y, -st_grad.x);",
delta.fsIn()); delta.fsIn());
#endif #endif
fragBuilder->codeAppend("float st_grad_len = length(st_grad);"); fragBuilder->codeAppend("half st_grad_len = length(st_grad);");
} else { } else {
fragBuilder->codeAppendf("float2 st = %s;\n", st.fsIn()); fragBuilder->codeAppendf("half2 st = %s;\n", st.fsIn());
fragBuilder->codeAppend("float2 Jdx = dFdx(st);"); fragBuilder->codeAppend("half2 Jdx = dFdx(st);");
fragBuilder->codeAppend("float2 Jdy = dFdy(st);"); fragBuilder->codeAppend("half2 Jdy = dFdy(st);");
fragBuilder->codeAppendf("float2 offset = %s*Jdx;", delta.fsIn()); fragBuilder->codeAppendf("half2 offset = %s*Jdx;", delta.fsIn());
} }
// sample the texture by index // sample the texture by index
fragBuilder->codeAppend("float4 texColor;"); fragBuilder->codeAppend("half4 texColor;");
append_multitexture_lookup(args, dfTexEffect.numTextureSamplers(), append_multitexture_lookup(args, dfTexEffect.numTextureSamplers(),
texIdx, "uv", "texColor"); texIdx, "uv", "texColor");
// green is distance to uv center // green is distance to uv center
fragBuilder->codeAppend("float3 distance;"); fragBuilder->codeAppend("half3 distance;");
fragBuilder->codeAppend("distance.y = texColor.r;"); fragBuilder->codeAppend("distance.y = texColor.r;");
// red is distance to left offset // red is distance to left offset
fragBuilder->codeAppend("float2 uv_adjusted = uv - offset;"); fragBuilder->codeAppend("half2 uv_adjusted = uv - offset;");
append_multitexture_lookup(args, dfTexEffect.numTextureSamplers(), append_multitexture_lookup(args, dfTexEffect.numTextureSamplers(),
texIdx, "uv_adjusted", "texColor"); texIdx, "uv_adjusted", "texColor");
fragBuilder->codeAppend("distance.x = texColor.r;"); fragBuilder->codeAppend("distance.x = texColor.r;");
@ -682,12 +681,11 @@ public:
fragBuilder->codeAppend("distance.z = texColor.r;"); fragBuilder->codeAppend("distance.z = texColor.r;");
fragBuilder->codeAppend("distance = " fragBuilder->codeAppend("distance = "
"float3(" SK_DistanceFieldMultiplier ")*(distance - float3(" SK_DistanceFieldThreshold"));"); "half3(" SK_DistanceFieldMultiplier ")*(distance - half3(" SK_DistanceFieldThreshold"));");
// adjust width based on gamma // adjust width based on gamma
const char* distanceAdjustUniName = nullptr; const char* distanceAdjustUniName = nullptr;
fDistanceAdjustUni = uniformHandler->addUniform(kFragment_GrShaderFlag, fDistanceAdjustUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf3_GrSLType,
kVec3f_GrSLType, kDefault_GrSLPrecision,
"DistanceAdjust", &distanceAdjustUniName); "DistanceAdjust", &distanceAdjustUniName);
fragBuilder->codeAppendf("distance -= %s;", distanceAdjustUniName); fragBuilder->codeAppendf("distance -= %s;", distanceAdjustUniName);
@ -695,7 +693,7 @@ public:
// for each color component. However, this is only important when using perspective // for each color component. However, this is only important when using perspective
// transformations, and even then using a single factor seems like a reasonable // transformations, and even then using a single factor seems like a reasonable
// trade-off between quality and speed. // trade-off between quality and speed.
fragBuilder->codeAppend("float afwidth;"); fragBuilder->codeAppend("half afwidth;");
if (isSimilarity) { if (isSimilarity) {
// For similarity transform (uniform scale-only is a subset of this), we adjust for the // For similarity transform (uniform scale-only is a subset of this), we adjust for the
// effect of the transformation on the distance by using the length of the gradient of // effect of the transformation on the distance by using the length of the gradient of
@ -708,16 +706,16 @@ public:
// For general transforms, to determine the amount of correction we multiply a unit // For general transforms, to determine the amount of correction we multiply a unit
// vector pointing along the SDF gradient direction by the Jacobian of the st coords // vector pointing along the SDF gradient direction by the Jacobian of the st coords
// (which is the inverse transform for this fragment) and take the length of the result. // (which is the inverse transform for this fragment) and take the length of the result.
fragBuilder->codeAppend("float2 dist_grad = float2(dFdx(distance.r), dFdy(distance.r));"); fragBuilder->codeAppend("half2 dist_grad = half2(dFdx(distance.r), dFdy(distance.r));");
// the length of the gradient may be 0, so we need to check for this // the length of the gradient may be 0, so we need to check for this
// this also compensates for the Adreno, which likes to drop tiles on division by 0 // this also compensates for the Adreno, which likes to drop tiles on division by 0
fragBuilder->codeAppend("float dg_len2 = dot(dist_grad, dist_grad);"); fragBuilder->codeAppend("half dg_len2 = dot(dist_grad, dist_grad);");
fragBuilder->codeAppend("if (dg_len2 < 0.0001) {"); fragBuilder->codeAppend("if (dg_len2 < 0.0001) {");
fragBuilder->codeAppend("dist_grad = float2(0.7071, 0.7071);"); fragBuilder->codeAppend("dist_grad = half2(0.7071, 0.7071);");
fragBuilder->codeAppend("} else {"); fragBuilder->codeAppend("} else {");
fragBuilder->codeAppend("dist_grad = dist_grad*inversesqrt(dg_len2);"); fragBuilder->codeAppend("dist_grad = dist_grad*inversesqrt(dg_len2);");
fragBuilder->codeAppend("}"); fragBuilder->codeAppend("}");
fragBuilder->codeAppend("float2 grad = float2(dist_grad.x*Jdx.x + dist_grad.y*Jdy.x,"); fragBuilder->codeAppend("half2 grad = half2(dist_grad.x*Jdx.x + dist_grad.y*Jdy.x,");
fragBuilder->codeAppend(" dist_grad.x*Jdx.y + dist_grad.y*Jdy.y);"); fragBuilder->codeAppend(" dist_grad.x*Jdx.y + dist_grad.y*Jdy.y);");
// this gives us a smooth step across approximately one fragment // this gives us a smooth step across approximately one fragment
@ -729,11 +727,11 @@ public:
// mapped linearly to coverage, so use a linear step: // mapped linearly to coverage, so use a linear step:
if (isGammaCorrect) { if (isGammaCorrect) {
fragBuilder->codeAppendf("%s = " fragBuilder->codeAppendf("%s = "
"float4(clamp((distance + float3(afwidth)) / float3(2.0 * afwidth), 0.0, 1.0), 1.0);", "half4(clamp((distance + half3(afwidth)) / half3(2.0 * afwidth), 0.0, 1.0), 1.0);",
args.fOutputCoverage); args.fOutputCoverage);
} else { } else {
fragBuilder->codeAppendf( fragBuilder->codeAppendf(
"%s = float4(smoothstep(float3(-afwidth), float3(afwidth), distance), 1.0);", "%s = half4(smoothstep(half3(-afwidth), half3(afwidth), distance), 1.0);",
args.fOutputCoverage); args.fOutputCoverage);
} }
} }

View File

@ -24,21 +24,22 @@ public:
const GrDitherEffect& _outer = args.fFp.cast<GrDitherEffect>(); const GrDitherEffect& _outer = args.fFp.cast<GrDitherEffect>();
(void)_outer; (void)_outer;
fragBuilder->codeAppendf( fragBuilder->codeAppendf(
"float value;\nfloat range;\n@switch (%d) {\n case 0:\n range = " "half value;\nhalf range;\n@switch (%d) {\n case 0:\n range = "
"0.0039215686274509803;\n break;\n case 1:\n range = " "0.0039215686274509803;\n break;\n case 1:\n range = "
"0.015873015873015872;\n break;\n default:\n range = " "0.015873015873015872;\n break;\n default:\n range = "
"0.066666666666666666;\n break;\n}\n@if (sk_Caps.integerSupport) {\n " "0.066666666666666666;\n break;\n}\n@if (sk_Caps.integerSupport) {\n "
"uint x = uint(sk_FragCoord.x);\n uint y = uint(sk_FragCoord.y);\n uint m = " "uint x = uint(sk_FragCoord.x);\n uint y = uint(sk_FragCoord.y);\n uint m = "
"(((((y & 1) << 5 | (x & 1) << 4) | (y & 2) << 2) | (x & 2) << 1) | (y & 4) >> 1) " "(((((y & 1) << 5 | (x & 1) << 4) | (y & 2) << 2) | (x & 2) << 1) | (y & 4) >> 1) "
"| (x & 4) >> 2;\n value = float(m) / 64.0 - 0.4921875;\n} else {\n float4 " "| (x & 4) >> 2;\n value = highfloat(highfloat(half(m)) / 64.0) - 0.4921875;\n} "
"modValues = mod(sk_FragCoord.xyxy, float4(2.0, 2.0, 4.0, 4.0));\n float4 " "else {\n half4 modValues = half4(mod(sk_FragCoord.xyxy, highfloat4(half4(2.0, "
"stepValues = step(modValues, float4(1.0, 1.0, 2.0, 2.0));\n value = " "2.0, 4.0, 4.0))));\n half4 stepValues = half4(step(highfloat4(modValues), "
"dot(stepValues, float4(0.5, 0.25, 0.125, 0.0625)) - 0.46875;\n}\n%s = " "highfloat4(half4(1.0, 1.0, 2.0, 2.0))));\n value = highfloat(dot(stepValues, "
"float4(clamp(%s.xyz + value * range, 0.0, %s.w), %s.w);\n", "half4(0.5, 0.25, 0.125, 0.0625))) - 0.46875;\n}\n%s = "
"half4(clamp(highfloat3(%s.xyz + value * range), 0.0, highfloat(%s.w)), %s.w);\n",
_outer.rangeType(), args.fOutputColor, _outer.rangeType(), args.fOutputColor,
args.fInputColor ? args.fInputColor : "float4(1)", args.fInputColor ? args.fInputColor : "half4(1)",
args.fInputColor ? args.fInputColor : "float4(1)", args.fInputColor ? args.fInputColor : "half4(1)",
args.fInputColor ? args.fInputColor : "float4(1)"); args.fInputColor ? args.fInputColor : "half4(1)");
} }
private: private:

View File

@ -32,8 +32,8 @@ layout(key) in int rangeType;
} }
void main() { void main() {
float value; half value;
float range; half range;
@switch (rangeType) { @switch (rangeType) {
case 0: case 0:
range = 1.0 / 255.0; range = 1.0 / 255.0;
@ -53,17 +53,17 @@ void main() {
uint m = (y & 1) << 5 | (x & 1) << 4 | uint m = (y & 1) << 5 | (x & 1) << 4 |
(y & 2) << 2 | (x & 2) << 1 | (y & 2) << 2 | (x & 2) << 1 |
(y & 4) >> 1 | (x & 4) >> 2; (y & 4) >> 1 | (x & 4) >> 2;
value = float(m) * 1.0 / 64.0 - 63.0 / 128.0; value = half(m) * 1.0 / 64.0 - 63.0 / 128.0;
} else { } else {
// Simulate the integer effect used above using step/mod. For speed, simulates a 4x4 // Simulate the integer effect used above using step/mod. For speed, simulates a 4x4
// dither pattern rather than an 8x8 one. // dither pattern rather than an 8x8 one.
float4 modValues = mod(sk_FragCoord.xyxy, float4(2.0, 2.0, 4.0, 4.0)); half4 modValues = mod(sk_FragCoord.xyxy, half4(2.0, 2.0, 4.0, 4.0));
float4 stepValues = step(modValues, float4(1.0, 1.0, 2.0, 2.0)); half4 stepValues = step(modValues, half4(1.0, 1.0, 2.0, 2.0));
value = dot(stepValues, float4(8.0 / 16.0, 4.0 / 16.0, 2.0 / 16.0, 1.0 / 16.0)) - 15.0 / 32.0; value = dot(stepValues, half4(8.0 / 16.0, 4.0 / 16.0, 2.0 / 16.0, 1.0 / 16.0)) - 15.0 / 32.0;
} }
// For each color channel, add the random offset to the channel value and then clamp // For each color channel, add the random offset to the channel value and then clamp
// between 0 and alpha to keep the color premultiplied. // between 0 and alpha to keep the color premultiplied.
sk_OutColor = float4(clamp(sk_InColor.rgb + value * range, 0, sk_InColor.a), sk_InColor.a); sk_OutColor = half4(clamp(sk_InColor.rgb + value * range, 0, sk_InColor.a), sk_InColor.a);
} }
@test(testData) { @test(testData) {

View File

@ -23,35 +23,34 @@ public:
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
const GrEllipseEffect& _outer = args.fFp.cast<GrEllipseEffect>(); const GrEllipseEffect& _outer = args.fFp.cast<GrEllipseEffect>();
(void)_outer; (void)_outer;
prevRadii = float2(-1.0); prevRadii = half2(-1.0);
useScale = sk_Caps.floatPrecisionVaries; useScale = sk_Caps.floatPrecisionVaries;
fEllipseVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kVec4f_GrSLType, fEllipseVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHighFloat4_GrSLType,
kHigh_GrSLPrecision, "ellipse"); kDefault_GrSLPrecision, "ellipse");
if (useScale) { if (useScale) {
fScaleVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kVec2f_GrSLType, fScaleVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType,
kDefault_GrSLPrecision, "scale"); kDefault_GrSLPrecision, "scale");
} }
fragBuilder->codeAppendf( fragBuilder->codeAppendf(
"float2 prevCenter;\nfloat2 prevRadii = float2(%f, %f);\nbool useScale = " "half2 prevCenter;\nhalf2 prevRadii = half2(%f, %f);\nbool useScale = %s;\nhalf2 d "
"%s;\nfloat2 d = sk_FragCoord.xy - %s.xy;\n@if (useScale) {\n d *= " "= half2(sk_FragCoord.xy - %s.xy);\n@if (useScale) {\n d *= %s.y;\n}\nhalf2 Z = "
"%s.y;\n}\nfloat2 Z = d * %s.zw;\nfloat implicit = dot(Z, d) - 1.0;\nfloat " "d * half2(%s.zw);\nhalf implicit = dot(Z, d) - 1.0;\nhalf grad_dot = 4.0 * dot(Z, "
"grad_dot = 4.0 * dot(Z, Z);\ngrad_dot = max(grad_dot, 0.0001);\nfloat approx_dist " "Z);\ngrad_dot = half(max(highfloat(grad_dot), 0.0001));\nhalf approx_dist = "
"= implicit * inversesqrt(grad_dot);\n@if (useScale) {\n approx_dist *= " "highfloat(implicit) * inversesqrt(highfloat(grad_dot));\n@if (useScale) {\n "
"%s.x;\n}\nfloat alpha;\n@switch (%d) {\n case 0:\n alpha = approx_dist " "approx_dist *= %s.x;\n}\nhalf alpha;\n@switch (%d) {\n case 0:\n alpha "
"> 0.0 ? 0.0 : 1.0;\n break;\n case 1:\n alpha = clamp(0.5 - " "= half(highfloat(approx_dist) > 0.0 ? 0.0 : 1.0);\n break;\n case 1:\n "
"approx_dist, 0.0, 1.0);\n break;\n case 2:\n alpha = approx_dist " " alpha = half(clamp(0.5 - highfloat(approx_dist), 0.0, 1.0));\n "
"> 0.0 ? 1.0 : 0.0;\n break;\n case 3:\n alpha = clamp(0.5 + " "break;\n case 2:\n alpha = half(highfloat(approx_dist) > 0.0 ? 1.0 : "
"approx_dist, 0.0, 1.0);\n break;\n default:\n discard;\n}\n%s = " "0.0);\n break;\n case 3:\n alpha = half(clamp(0.5 + "
"%s * alpha;\n", "highfloat(approx_dist), 0.0, 1.0));\n break;\n default:\n "
"discard;\n}\n%s = %s * alpha;\n",
prevRadii.fX, prevRadii.fY, (useScale ? "true" : "false"), prevRadii.fX, prevRadii.fY, (useScale ? "true" : "false"),
args.fUniformHandler->getUniformCStr(fEllipseVar), args.fUniformHandler->getUniformCStr(fEllipseVar),
fScaleVar.isValid() ? args.fUniformHandler->getUniformCStr(fScaleVar) fScaleVar.isValid() ? args.fUniformHandler->getUniformCStr(fScaleVar) : "half2(0)",
: "float2(0.0)",
args.fUniformHandler->getUniformCStr(fEllipseVar), args.fUniformHandler->getUniformCStr(fEllipseVar),
fScaleVar.isValid() ? args.fUniformHandler->getUniformCStr(fScaleVar) fScaleVar.isValid() ? args.fUniformHandler->getUniformCStr(fScaleVar) : "half2(0)",
: "float2(0.0)",
_outer.edgeType(), args.fOutputColor, _outer.edgeType(), args.fOutputColor,
args.fInputColor ? args.fInputColor : "float4(1)"); args.fInputColor ? args.fInputColor : "half4(1)");
} }
private: private:

View File

@ -6,17 +6,17 @@
*/ */
layout(key) in int edgeType; layout(key) in int edgeType;
in float2 center; in half2 center;
in float2 radii; in half2 radii;
float2 prevCenter; half2 prevCenter;
float2 prevRadii = float2(-1); half2 prevRadii = half2(-1);
// The ellipse uniform is (center.x, center.y, 1 / rx^2, 1 / ry^2) // The ellipse uniform is (center.x, center.y, 1 / rx^2, 1 / ry^2)
// The last two terms can underflow on mediump, so we use highp. // The last two terms can underflow with halfs, so we use floats.
uniform highp float4 ellipse; uniform highfloat4 ellipse;
bool useScale = sk_Caps.floatPrecisionVaries; bool useScale = sk_Caps.floatPrecisionVaries;
layout(when=useScale) uniform float2 scale; layout(when=useScale) uniform half2 scale;
@optimizationFlags { kCompatibleWithCoverageAsAlpha_OptimizationFlag } @optimizationFlags { kCompatibleWithCoverageAsAlpha_OptimizationFlag }
@ -50,7 +50,7 @@ layout(when=useScale) uniform float2 scale;
void main() { void main() {
// d is the offset to the ellipse center // d is the offset to the ellipse center
float2 d = sk_FragCoord.xy - ellipse.xy; half2 d = sk_FragCoord.xy - ellipse.xy;
// If we're on a device with a "real" mediump then we'll do the distance computation in a space // If we're on a device with a "real" mediump then we'll do the distance computation in a space
// that is normalized by the larger radius. The scale uniform will be scale, 1/scale. The // that is normalized by the larger radius. The scale uniform will be scale, 1/scale. The
// inverse squared radii uniform values are already in this normalized space. The center is // inverse squared radii uniform values are already in this normalized space. The center is
@ -58,19 +58,19 @@ void main() {
@if (useScale) { @if (useScale) {
d *= scale.y; d *= scale.y;
} }
float2 Z = d * ellipse.zw; half2 Z = d * ellipse.zw;
// implicit is the evaluation of (x/rx)^2 + (y/ry)^2 - 1. // implicit is the evaluation of (x/rx)^2 + (y/ry)^2 - 1.
float implicit = dot(Z, d) - 1; half implicit = dot(Z, d) - 1;
// grad_dot is the squared length of the gradient of the implicit. // grad_dot is the squared length of the gradient of the implicit.
float grad_dot = 4 * dot(Z, Z); half grad_dot = 4 * dot(Z, Z);
// Avoid calling inversesqrt on zero. // Avoid calling inversesqrt on zero.
grad_dot = max(grad_dot, 1e-4); grad_dot = max(grad_dot, 1e-4);
float approx_dist = implicit * inversesqrt(grad_dot); half approx_dist = implicit * inversesqrt(grad_dot);
@if (useScale) { @if (useScale) {
approx_dist *= scale.x; approx_dist *= scale.x;
} }
float alpha; half alpha;
@switch (edgeType) { @switch (edgeType) {
case 0 /* kFillBW_GrProcessorEdgeType */: case 0 /* kFillBW_GrProcessorEdgeType */:
alpha = approx_dist > 0.0 ? 0.0 : 1.0; alpha = approx_dist > 0.0 ? 0.0 : 1.0;

View File

@ -41,11 +41,11 @@ void GrGLConvolutionEffect::emitCode(EmitArgs& args) {
args.fFp.cast<GrGaussianConvolutionFragmentProcessor>(); args.fFp.cast<GrGaussianConvolutionFragmentProcessor>();
GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
fImageIncrementUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kVec2f_GrSLType, fImageIncrementUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType,
kDefault_GrSLPrecision, "ImageIncrement"); "ImageIncrement");
if (ce.useBounds()) { if (ce.useBounds()) {
fBoundsUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kVec2f_GrSLType, fBoundsUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType,
kDefault_GrSLPrecision, "Bounds"); "Bounds");
} }
int width = ce.width(); int width = ce.width();
@ -53,19 +53,19 @@ void GrGLConvolutionEffect::emitCode(EmitArgs& args) {
int arrayCount = (width + 3) / 4; int arrayCount = (width + 3) / 4;
SkASSERT(4 * arrayCount >= width); SkASSERT(4 * arrayCount >= width);
fKernelUni = uniformHandler->addUniformArray(kFragment_GrShaderFlag, kVec4f_GrSLType, fKernelUni = uniformHandler->addUniformArray(kFragment_GrShaderFlag, kHalf4_GrSLType,
kDefault_GrSLPrecision, "Kernel", arrayCount); "Kernel", arrayCount);
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]); SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
fragBuilder->codeAppendf("%s = float4(0, 0, 0, 0);", args.fOutputColor); fragBuilder->codeAppendf("%s = half4(0, 0, 0, 0);", args.fOutputColor);
const GrShaderVar& kernel = uniformHandler->getUniformVariable(fKernelUni); const GrShaderVar& kernel = uniformHandler->getUniformVariable(fKernelUni);
const char* imgInc = uniformHandler->getUniformCStr(fImageIncrementUni); const char* imgInc = uniformHandler->getUniformCStr(fImageIncrementUni);
fragBuilder->codeAppendf("float2 coord = %s - %d.0 * %s;", coords2D.c_str(), ce.radius(), imgInc); fragBuilder->codeAppendf("highfloat2 coord = %s - %d.0 * %s;", coords2D.c_str(), ce.radius(), imgInc);
fragBuilder->codeAppend("float2 coordSampled = float2(0, 0);"); fragBuilder->codeAppend("highfloat2 coordSampled = half2(0, 0);");
// Manually unroll loop because some drivers don't; yields 20-30% speedup. // Manually unroll loop because some drivers don't; yields 20-30% speedup.
const char* kVecSuffix[4] = {".x", ".y", ".z", ".w"}; const char* kVecSuffix[4] = {".x", ".y", ".z", ".w"};

View File

@ -47,20 +47,15 @@ void GrGLMatrixConvolutionEffect::emitCode(EmitArgs& args) {
SkASSERT(4 * arrayCount >= kWidth * kHeight); SkASSERT(4 * arrayCount >= kWidth * kHeight);
GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
fImageIncrementUni = uniformHandler->addUniform(kFragment_GrShaderFlag, fImageIncrementUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType,
kVec2f_GrSLType, kDefault_GrSLPrecision,
"ImageIncrement"); "ImageIncrement");
fKernelUni = uniformHandler->addUniformArray(kFragment_GrShaderFlag, fKernelUni = uniformHandler->addUniformArray(kFragment_GrShaderFlag, kHalf4_GrSLType,
kVec4f_GrSLType, kDefault_GrSLPrecision,
"Kernel", "Kernel",
arrayCount); arrayCount);
fKernelOffsetUni = uniformHandler->addUniform(kFragment_GrShaderFlag, fKernelOffsetUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType,
kVec2f_GrSLType, kDefault_GrSLPrecision,
"KernelOffset"); "KernelOffset");
fGainUni = uniformHandler->addUniform(kFragment_GrShaderFlag, fGainUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType, "Gain");
kFloat_GrSLType, kDefault_GrSLPrecision, "Gain"); fBiasUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType, "Bias");
fBiasUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
kFloat_GrSLType, kDefault_GrSLPrecision, "Bias");
const char* kernelOffset = uniformHandler->getUniformCStr(fKernelOffsetUni); const char* kernelOffset = uniformHandler->getUniformCStr(fKernelOffsetUni);
const char* imgInc = uniformHandler->getUniformCStr(fImageIncrementUni); const char* imgInc = uniformHandler->getUniformCStr(fImageIncrementUni);
@ -70,9 +65,9 @@ void GrGLMatrixConvolutionEffect::emitCode(EmitArgs& args) {
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]); SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
fragBuilder->codeAppend("float4 sum = float4(0, 0, 0, 0);"); fragBuilder->codeAppend("half4 sum = half4(0, 0, 0, 0);");
fragBuilder->codeAppendf("float2 coord = %s - %s * %s;", coords2D.c_str(), kernelOffset, imgInc); fragBuilder->codeAppendf("highfloat2 coord = %s - %s * %s;", coords2D.c_str(), kernelOffset, imgInc);
fragBuilder->codeAppend("float4 c;"); fragBuilder->codeAppend("half4 c;");
const char* kVecSuffix[4] = { ".x", ".y", ".z", ".w" }; const char* kVecSuffix[4] = { ".x", ".y", ".z", ".w" };
for (int y = 0; y < kHeight; y++) { for (int y = 0; y < kHeight; y++) {
@ -80,10 +75,10 @@ void GrGLMatrixConvolutionEffect::emitCode(EmitArgs& args) {
GrGLSLShaderBuilder::ShaderBlock block(fragBuilder); GrGLSLShaderBuilder::ShaderBlock block(fragBuilder);
int offset = y*kWidth + x; int offset = y*kWidth + x;
fragBuilder->codeAppendf("float k = %s[%d]%s;", kernel, offset / 4, fragBuilder->codeAppendf("half k = %s[%d]%s;", kernel, offset / 4,
kVecSuffix[offset & 0x3]); kVecSuffix[offset & 0x3]);
SkString coord; SkString coord;
coord.printf("coord + float2(%d, %d) * %s", x, y, imgInc); coord.printf("coord + half2(%d, %d) * %s", x, y, imgInc);
fDomain.sampleTexture(fragBuilder, fDomain.sampleTexture(fragBuilder,
uniformHandler, uniformHandler,
args.fShaderCaps, args.fShaderCaps,

View File

@ -23,24 +23,21 @@ public:
const char* srcCoeffsName = nullptr; const char* srcCoeffsName = nullptr;
if (SkToBool(csxe.ops() & GrNonlinearColorSpaceXformEffect::kSrcTransfer_Op)) { if (SkToBool(csxe.ops() & GrNonlinearColorSpaceXformEffect::kSrcTransfer_Op)) {
fSrcTransferFnUni = uniformHandler->addUniformArray( fSrcTransferFnUni = uniformHandler->addUniformArray(
kFragment_GrShaderFlag, kFloat_GrSLType, kDefault_GrSLPrecision, kFragment_GrShaderFlag, kHalf_GrSLType, "SrcTransferFn",
"SrcTransferFn", GrNonlinearColorSpaceXformEffect::kNumTransferFnCoeffs, GrNonlinearColorSpaceXformEffect::kNumTransferFnCoeffs, &srcCoeffsName);
&srcCoeffsName);
} }
const char* dstCoeffsName = nullptr; const char* dstCoeffsName = nullptr;
if (SkToBool(csxe.ops() & GrNonlinearColorSpaceXformEffect::kDstTransfer_Op)) { if (SkToBool(csxe.ops() & GrNonlinearColorSpaceXformEffect::kDstTransfer_Op)) {
fDstTransferFnUni = uniformHandler->addUniformArray( fDstTransferFnUni = uniformHandler->addUniformArray(
kFragment_GrShaderFlag, kFloat_GrSLType, kDefault_GrSLPrecision, kFragment_GrShaderFlag, kHalf_GrSLType, "DstTransferFn",
"DstTransferFn", GrNonlinearColorSpaceXformEffect::kNumTransferFnCoeffs, GrNonlinearColorSpaceXformEffect::kNumTransferFnCoeffs, &dstCoeffsName);
&dstCoeffsName);
} }
const char* gamutXformName = nullptr; const char* gamutXformName = nullptr;
if (SkToBool(csxe.ops() & GrNonlinearColorSpaceXformEffect::kGamutXform_Op)) { if (SkToBool(csxe.ops() & GrNonlinearColorSpaceXformEffect::kGamutXform_Op)) {
fGamutXformUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kMat44f_GrSLType, fGamutXformUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4x4_GrSLType,
kDefault_GrSLPrecision, "GamutXform", "GamutXform", &gamutXformName);
&gamutXformName);
} }
// Helper function to apply the src or dst transfer function to a single value // Helper function to apply the src or dst transfer function to a single value
@ -52,32 +49,32 @@ public:
} }
const char* fnName = i ? "dst_transfer_fn" : "src_transfer_fn"; const char* fnName = i ? "dst_transfer_fn" : "src_transfer_fn";
static const GrShaderVar gTransferFnFuncArgs[] = { static const GrShaderVar gTransferFnFuncArgs[] = {
GrShaderVar("x", kFloat_GrSLType), GrShaderVar("x", kHalf_GrSLType),
}; };
SkString transferFnBody; SkString transferFnBody;
// Temporaries to make evaluation line readable // Temporaries to make evaluation line readable
transferFnBody.printf("float A = %s[0];", coeffsName); transferFnBody.printf("half A = %s[0];", coeffsName);
transferFnBody.appendf("float B = %s[1];", coeffsName); transferFnBody.appendf("half B = %s[1];", coeffsName);
transferFnBody.appendf("float C = %s[2];", coeffsName); transferFnBody.appendf("half C = %s[2];", coeffsName);
transferFnBody.appendf("float D = %s[3];", coeffsName); transferFnBody.appendf("half D = %s[3];", coeffsName);
transferFnBody.appendf("float E = %s[4];", coeffsName); transferFnBody.appendf("half E = %s[4];", coeffsName);
transferFnBody.appendf("float F = %s[5];", coeffsName); transferFnBody.appendf("half F = %s[5];", coeffsName);
transferFnBody.appendf("float G = %s[6];", coeffsName); transferFnBody.appendf("half G = %s[6];", coeffsName);
transferFnBody.append("float s = sign(x);"); transferFnBody.append("half s = sign(x);");
transferFnBody.append("x = abs(x);"); transferFnBody.append("x = abs(x);");
transferFnBody.appendf("return s * ((x < D) ? (C * x) + F : pow(A * x + B, G) + E);"); transferFnBody.appendf("return s * ((x < D) ? (C * x) + F : pow(A * x + B, G) + E);");
fragBuilder->emitFunction(kFloat_GrSLType, fnName, SK_ARRAY_COUNT(gTransferFnFuncArgs), fragBuilder->emitFunction(kHalf_GrSLType, fnName, SK_ARRAY_COUNT(gTransferFnFuncArgs),
gTransferFnFuncArgs, transferFnBody.c_str(), &tfFuncNames[i]); gTransferFnFuncArgs, transferFnBody.c_str(), &tfFuncNames[i]);
} }
if (nullptr == args.fInputColor) { if (nullptr == args.fInputColor) {
args.fInputColor = "float4(1)"; args.fInputColor = "half4(1)";
} }
fragBuilder->codeAppendf("float4 color = %s;", args.fInputColor); fragBuilder->codeAppendf("half4 color = %s;", args.fInputColor);
// 1: Un-premultiply the input color (if necessary) // 1: Un-premultiply the input color (if necessary)
fragBuilder->codeAppendf("float nonZeroAlpha = max(color.a, 0.00001);"); fragBuilder->codeAppendf("half nonZeroAlpha = max(color.a, 0.00001);");
fragBuilder->codeAppendf("color = float4(color.rgb / nonZeroAlpha, nonZeroAlpha);"); fragBuilder->codeAppendf("color = half4(color.rgb / nonZeroAlpha, nonZeroAlpha);");
// 2: Apply src transfer function (to get to linear RGB) // 2: Apply src transfer function (to get to linear RGB)
if (srcCoeffsName) { if (srcCoeffsName) {
@ -89,7 +86,7 @@ public:
// 3: Apply gamut matrix // 3: Apply gamut matrix
if (gamutXformName) { if (gamutXformName) {
fragBuilder->codeAppendf( fragBuilder->codeAppendf(
"color.rgb = (%s * float4(color.rgb, 1.0)).rgb;", gamutXformName); "color.rgb = (%s * half4(color.rgb, 1.0)).rgb;", gamutXformName);
} }
// 4: Apply dst transfer fn // 4: Apply dst transfer fn
@ -100,7 +97,7 @@ public:
} }
// 5: Premultiply again // 5: Premultiply again
fragBuilder->codeAppendf("%s = float4(color.rgb * color.a, color.a);", args.fOutputColor); fragBuilder->codeAppendf("%s = half4(color.rgb * color.a, color.a);", args.fOutputColor);
} }
static inline void GenKey(const GrProcessor& processor, const GrShaderCaps&, static inline void GenKey(const GrProcessor& processor, const GrShaderCaps&,

View File

@ -440,7 +440,7 @@ static void append_color_output(const PorterDuffXferProcessor& xp,
SkASSERT(inColor); SkASSERT(inColor);
switch (outputType) { switch (outputType) {
case BlendFormula::kNone_OutputType: case BlendFormula::kNone_OutputType:
fragBuilder->codeAppendf("%s = float4(0.0);", output); fragBuilder->codeAppendf("%s = half4(0.0);", output);
break; break;
case BlendFormula::kCoverage_OutputType: case BlendFormula::kCoverage_OutputType:
// We can have a coverage formula while not reading coverage if there are mixed samples. // We can have a coverage formula while not reading coverage if there are mixed samples.
@ -456,7 +456,7 @@ static void append_color_output(const PorterDuffXferProcessor& xp,
fragBuilder->codeAppendf("%s = (1.0 - %s.a) * %s;", output, inColor, inCoverage); fragBuilder->codeAppendf("%s = (1.0 - %s.a) * %s;", output, inColor, inCoverage);
break; break;
case BlendFormula::kISCModulate_OutputType: case BlendFormula::kISCModulate_OutputType:
fragBuilder->codeAppendf("%s = (float4(1.0) - %s) * %s;", output, inColor, inCoverage); fragBuilder->codeAppendf("%s = (half4(1.0) - %s) * %s;", output, inColor, inCoverage);
break; break;
default: default:
SK_ABORT("Unsupported output type."); SK_ABORT("Unsupported output type.");
@ -629,8 +629,8 @@ public:
private: private:
void emitOutputsForBlendState(const EmitArgs& args) override { void emitOutputsForBlendState(const EmitArgs& args) override {
const char* alpha; const char* alpha;
fAlphaUniform = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kFloat_GrSLType, fAlphaUniform = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType,
kDefault_GrSLPrecision, "alpha", &alpha); "alpha", &alpha);
GrGLSLXPFragmentBuilder* fragBuilder = args.fXPFragBuilder; GrGLSLXPFragmentBuilder* fragBuilder = args.fXPFragBuilder;
// We want to force our primary output to be alpha * Coverage, where alpha is the alpha // We want to force our primary output to be alpha * Coverage, where alpha is the alpha
// value of the src color. We know that there are no color stages (or we wouldn't have // value of the src color. We know that there are no color stages (or we wouldn't have

View File

@ -160,15 +160,11 @@ void GLCircularRRectEffect::emitCode(EmitArgs& args) {
// edges correspond to components x, y, z, and w, respectively. When a side of the rrect has // 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 // only rectangular corners, that side's value corresponds to the rect edge's value outset by
// half a pixel. // half a pixel.
fInnerRectUniform = uniformHandler->addUniform(kFragment_GrShaderFlag, fInnerRectUniform = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType,
kVec4f_GrSLType, kDefault_GrSLPrecision, "innerRect", &rectName);
"innerRect",
&rectName);
// x is (r + .5) and y is 1/(r + .5) // x is (r + .5) and y is 1/(r + .5)
fRadiusPlusHalfUniform = uniformHandler->addUniform(kFragment_GrShaderFlag, fRadiusPlusHalfUniform = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType,
kVec2f_GrSLType, kDefault_GrSLPrecision, "radiusPlusHalf", &radiusPlusHalfName);
"radiusPlusHalf",
&radiusPlusHalfName);
// If we're on a device with a "real" mediump then the length calculation could overflow. // If we're on a device with a "real" mediump then the length calculation could overflow.
SkString clampedCircleDistance; SkString clampedCircleDistance;
@ -197,87 +193,87 @@ void GLCircularRRectEffect::emitCode(EmitArgs& args) {
// alphas together. // alphas together.
switch (crre.getCircularCornerFlags()) { switch (crre.getCircularCornerFlags()) {
case CircularRRectEffect::kAll_CornerFlags: case CircularRRectEffect::kAll_CornerFlags:
fragBuilder->codeAppendf("float2 dxy0 = %s.xy - sk_FragCoord.xy;", rectName); fragBuilder->codeAppendf("half2 dxy0 = %s.xy - sk_FragCoord.xy;", rectName);
fragBuilder->codeAppendf("float2 dxy1 = sk_FragCoord.xy - %s.zw;", rectName); fragBuilder->codeAppendf("half2 dxy1 = sk_FragCoord.xy - %s.zw;", rectName);
fragBuilder->codeAppend("float2 dxy = max(max(dxy0, dxy1), 0.0);"); fragBuilder->codeAppend("half2 dxy = max(max(dxy0, dxy1), 0.0);");
fragBuilder->codeAppendf("float alpha = %s;", clampedCircleDistance.c_str()); fragBuilder->codeAppendf("half alpha = %s;", clampedCircleDistance.c_str());
break; break;
case CircularRRectEffect::kTopLeft_CornerFlag: case CircularRRectEffect::kTopLeft_CornerFlag:
fragBuilder->codeAppendf("float2 dxy = max(%s.xy - sk_FragCoord.xy, 0.0);", fragBuilder->codeAppendf("half2 dxy = max(%s.xy - sk_FragCoord.xy, 0.0);",
rectName); rectName);
fragBuilder->codeAppendf("float rightAlpha = clamp(%s.z - sk_FragCoord.x, 0.0, 1.0);", fragBuilder->codeAppendf("half rightAlpha = clamp(%s.z - sk_FragCoord.x, 0.0, 1.0);",
rectName); rectName);
fragBuilder->codeAppendf("float bottomAlpha = clamp(%s.w - sk_FragCoord.y, 0.0, 1.0);", fragBuilder->codeAppendf("half bottomAlpha = clamp(%s.w - sk_FragCoord.y, 0.0, 1.0);",
rectName); rectName);
fragBuilder->codeAppendf("float alpha = bottomAlpha * rightAlpha * %s;", fragBuilder->codeAppendf("half alpha = bottomAlpha * rightAlpha * %s;",
clampedCircleDistance.c_str()); clampedCircleDistance.c_str());
break; break;
case CircularRRectEffect::kTopRight_CornerFlag: case CircularRRectEffect::kTopRight_CornerFlag:
fragBuilder->codeAppendf("float2 dxy = max(float2(sk_FragCoord.x - %s.z, " fragBuilder->codeAppendf("half2 dxy = max(half2(sk_FragCoord.x - %s.z, "
"%s.y - sk_FragCoord.y), 0.0);", "%s.y - sk_FragCoord.y), 0.0);",
rectName, rectName); rectName, rectName);
fragBuilder->codeAppendf("float leftAlpha = clamp(sk_FragCoord.x - %s.x, 0.0, 1.0);", fragBuilder->codeAppendf("half leftAlpha = clamp(sk_FragCoord.x - %s.x, 0.0, 1.0);",
rectName); rectName);
fragBuilder->codeAppendf("float bottomAlpha = clamp(%s.w - sk_FragCoord.y, 0.0, 1.0);", fragBuilder->codeAppendf("half bottomAlpha = clamp(%s.w - sk_FragCoord.y, 0.0, 1.0);",
rectName); rectName);
fragBuilder->codeAppendf("float alpha = bottomAlpha * leftAlpha * %s;", fragBuilder->codeAppendf("half alpha = bottomAlpha * leftAlpha * %s;",
clampedCircleDistance.c_str()); clampedCircleDistance.c_str());
break; break;
case CircularRRectEffect::kBottomRight_CornerFlag: case CircularRRectEffect::kBottomRight_CornerFlag:
fragBuilder->codeAppendf("float2 dxy = max(sk_FragCoord.xy - %s.zw, 0.0);", fragBuilder->codeAppendf("half2 dxy = max(sk_FragCoord.xy - %s.zw, 0.0);",
rectName); rectName);
fragBuilder->codeAppendf("float leftAlpha = clamp(sk_FragCoord.x - %s.x, 0.0, 1.0);", fragBuilder->codeAppendf("half leftAlpha = clamp(sk_FragCoord.x - %s.x, 0.0, 1.0);",
rectName); rectName);
fragBuilder->codeAppendf("float topAlpha = clamp(sk_FragCoord.y - %s.y, 0.0, 1.0);", fragBuilder->codeAppendf("half topAlpha = clamp(sk_FragCoord.y - %s.y, 0.0, 1.0);",
rectName); rectName);
fragBuilder->codeAppendf("float alpha = topAlpha * leftAlpha * %s;", fragBuilder->codeAppendf("half alpha = topAlpha * leftAlpha * %s;",
clampedCircleDistance.c_str()); clampedCircleDistance.c_str());
break; break;
case CircularRRectEffect::kBottomLeft_CornerFlag: case CircularRRectEffect::kBottomLeft_CornerFlag:
fragBuilder->codeAppendf("float2 dxy = max(float2(%s.x - sk_FragCoord.x, sk_FragCoord.y - " fragBuilder->codeAppendf("half2 dxy = max(half2(%s.x - sk_FragCoord.x, sk_FragCoord.y - "
"%s.w), 0.0);", "%s.w), 0.0);",
rectName, rectName); rectName, rectName);
fragBuilder->codeAppendf("float rightAlpha = clamp(%s.z - sk_FragCoord.x, 0.0, 1.0);", fragBuilder->codeAppendf("half rightAlpha = clamp(%s.z - sk_FragCoord.x, 0.0, 1.0);",
rectName); rectName);
fragBuilder->codeAppendf("float topAlpha = clamp(sk_FragCoord.y - %s.y, 0.0, 1.0);", fragBuilder->codeAppendf("half topAlpha = clamp(sk_FragCoord.y - %s.y, 0.0, 1.0);",
rectName); rectName);
fragBuilder->codeAppendf("float alpha = topAlpha * rightAlpha * %s;", fragBuilder->codeAppendf("half alpha = topAlpha * rightAlpha * %s;",
clampedCircleDistance.c_str()); clampedCircleDistance.c_str());
break; break;
case CircularRRectEffect::kLeft_CornerFlags: case CircularRRectEffect::kLeft_CornerFlags:
fragBuilder->codeAppendf("float2 dxy0 = %s.xy - sk_FragCoord.xy;", rectName); fragBuilder->codeAppendf("half2 dxy0 = %s.xy - sk_FragCoord.xy;", rectName);
fragBuilder->codeAppendf("float dy1 = sk_FragCoord.y - %s.w;", rectName); fragBuilder->codeAppendf("half dy1 = sk_FragCoord.y - %s.w;", rectName);
fragBuilder->codeAppend("float2 dxy = max(float2(dxy0.x, max(dxy0.y, dy1)), 0.0);"); fragBuilder->codeAppend("half2 dxy = max(half2(dxy0.x, max(dxy0.y, dy1)), 0.0);");
fragBuilder->codeAppendf("float rightAlpha = clamp(%s.z - sk_FragCoord.x, 0.0, 1.0);", fragBuilder->codeAppendf("half rightAlpha = clamp(%s.z - sk_FragCoord.x, 0.0, 1.0);",
rectName); rectName);
fragBuilder->codeAppendf("float alpha = rightAlpha * %s;", fragBuilder->codeAppendf("half alpha = rightAlpha * %s;",
clampedCircleDistance.c_str()); clampedCircleDistance.c_str());
break; break;
case CircularRRectEffect::kTop_CornerFlags: case CircularRRectEffect::kTop_CornerFlags:
fragBuilder->codeAppendf("float2 dxy0 = %s.xy - sk_FragCoord.xy;", rectName); fragBuilder->codeAppendf("half2 dxy0 = %s.xy - sk_FragCoord.xy;", rectName);
fragBuilder->codeAppendf("float dx1 = sk_FragCoord.x - %s.z;", rectName); fragBuilder->codeAppendf("half dx1 = sk_FragCoord.x - %s.z;", rectName);
fragBuilder->codeAppend("float2 dxy = max(float2(max(dxy0.x, dx1), dxy0.y), 0.0);"); fragBuilder->codeAppend("half2 dxy = max(half2(max(dxy0.x, dx1), dxy0.y), 0.0);");
fragBuilder->codeAppendf("float bottomAlpha = clamp(%s.w - sk_FragCoord.y, 0.0, 1.0);", fragBuilder->codeAppendf("half bottomAlpha = clamp(%s.w - sk_FragCoord.y, 0.0, 1.0);",
rectName); rectName);
fragBuilder->codeAppendf("float alpha = bottomAlpha * %s;", fragBuilder->codeAppendf("half alpha = bottomAlpha * %s;",
clampedCircleDistance.c_str()); clampedCircleDistance.c_str());
break; break;
case CircularRRectEffect::kRight_CornerFlags: case CircularRRectEffect::kRight_CornerFlags:
fragBuilder->codeAppendf("float dy0 = %s.y - sk_FragCoord.y;", rectName); fragBuilder->codeAppendf("half dy0 = %s.y - sk_FragCoord.y;", rectName);
fragBuilder->codeAppendf("float2 dxy1 = sk_FragCoord.xy - %s.zw;", rectName); fragBuilder->codeAppendf("half2 dxy1 = sk_FragCoord.xy - %s.zw;", rectName);
fragBuilder->codeAppend("float2 dxy = max(float2(dxy1.x, max(dy0, dxy1.y)), 0.0);"); fragBuilder->codeAppend("half2 dxy = max(half2(dxy1.x, max(dy0, dxy1.y)), 0.0);");
fragBuilder->codeAppendf("float leftAlpha = clamp(sk_FragCoord.x - %s.x, 0.0, 1.0);", fragBuilder->codeAppendf("half leftAlpha = clamp(sk_FragCoord.x - %s.x, 0.0, 1.0);",
rectName); rectName);
fragBuilder->codeAppendf("float alpha = leftAlpha * %s;", fragBuilder->codeAppendf("half alpha = leftAlpha * %s;",
clampedCircleDistance.c_str()); clampedCircleDistance.c_str());
break; break;
case CircularRRectEffect::kBottom_CornerFlags: case CircularRRectEffect::kBottom_CornerFlags:
fragBuilder->codeAppendf("float dx0 = %s.x - sk_FragCoord.x;", rectName); fragBuilder->codeAppendf("half dx0 = %s.x - sk_FragCoord.x;", rectName);
fragBuilder->codeAppendf("float2 dxy1 = sk_FragCoord.xy - %s.zw;", rectName); fragBuilder->codeAppendf("half2 dxy1 = sk_FragCoord.xy - %s.zw;", rectName);
fragBuilder->codeAppend("float2 dxy = max(float2(max(dx0, dxy1.x), dxy1.y), 0.0);"); fragBuilder->codeAppend("half2 dxy = max(half2(max(dx0, dxy1.x), dxy1.y), 0.0);");
fragBuilder->codeAppendf("float topAlpha = clamp(sk_FragCoord.y - %s.y, 0.0, 1.0);", fragBuilder->codeAppendf("half topAlpha = clamp(sk_FragCoord.y - %s.y, 0.0, 1.0);",
rectName); rectName);
fragBuilder->codeAppendf("float alpha = topAlpha * %s;", fragBuilder->codeAppendf("half alpha = topAlpha * %s;",
clampedCircleDistance.c_str()); clampedCircleDistance.c_str());
break; break;
} }
@ -514,10 +510,8 @@ void GLEllipticalRRectEffect::emitCode(EmitArgs& args) {
GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
const char *rectName; const char *rectName;
// The inner rect is the rrect bounds inset by the x/y radii // The inner rect is the rrect bounds inset by the x/y radii
fInnerRectUniform = uniformHandler->addUniform(kFragment_GrShaderFlag, fInnerRectUniform = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType,
kVec4f_GrSLType, kDefault_GrSLPrecision, "innerRect", &rectName);
"innerRect",
&rectName);
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
// At each quarter-ellipse corner we compute a vector that is the offset of the fragment pos // At each quarter-ellipse corner we compute a vector that is the offset of the fragment pos
@ -532,17 +526,16 @@ void GLEllipticalRRectEffect::emitCode(EmitArgs& args) {
// The code below is a simplified version of the above that performs maxs on the vector // 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 // components before computing distances and alpha values so that only one distance computation
// need be computed to determine the min alpha. // need be computed to determine the min alpha.
fragBuilder->codeAppendf("float2 dxy0 = %s.xy - sk_FragCoord.xy;", rectName); fragBuilder->codeAppendf("half2 dxy0 = %s.xy - sk_FragCoord.xy;", rectName);
fragBuilder->codeAppendf("float2 dxy1 = sk_FragCoord.xy - %s.zw;", rectName); fragBuilder->codeAppendf("half2 dxy1 = sk_FragCoord.xy - %s.zw;", rectName);
// If we're on a device with a "real" mediump then we'll do the distance computation in a space // If we're on a device with a "real" mediump then we'll do the distance computation in a space
// that is normalized by the largest radius. The scale uniform will be scale, 1/scale. The // that is normalized by the largest radius. The scale uniform will be scale, 1/scale. The
// radii uniform values are already in this normalized space. // radii uniform values are already in this normalized space.
const char* scaleName = nullptr; const char* scaleName = nullptr;
if (args.fShaderCaps->floatPrecisionVaries()) { if (args.fShaderCaps->floatPrecisionVaries()) {
fScaleUniform = uniformHandler->addUniform(kFragment_GrShaderFlag, fScaleUniform = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType, "scale",
kVec2f_GrSLType, kDefault_GrSLPrecision, &scaleName);
"scale", &scaleName);
} }
// The uniforms with the inv squared radii are highp to prevent underflow. // The uniforms with the inv squared radii are highp to prevent underflow.
@ -550,34 +543,32 @@ void GLEllipticalRRectEffect::emitCode(EmitArgs& args) {
case SkRRect::kSimple_Type: { case SkRRect::kSimple_Type: {
const char *invRadiiXYSqdName; const char *invRadiiXYSqdName;
fInvRadiiSqdUniform = uniformHandler->addUniform(kFragment_GrShaderFlag, fInvRadiiSqdUniform = uniformHandler->addUniform(kFragment_GrShaderFlag,
kVec2f_GrSLType, kHalf2_GrSLType,
kDefault_GrSLPrecision,
"invRadiiXY", "invRadiiXY",
&invRadiiXYSqdName); &invRadiiXYSqdName);
fragBuilder->codeAppend("float2 dxy = max(max(dxy0, dxy1), 0.0);"); fragBuilder->codeAppend("half2 dxy = max(max(dxy0, dxy1), 0.0);");
if (scaleName) { if (scaleName) {
fragBuilder->codeAppendf("dxy *= %s.y;", scaleName); fragBuilder->codeAppendf("dxy *= %s.y;", scaleName);
} }
// Z is the x/y offsets divided by squared radii. // Z is the x/y offsets divided by squared radii.
fragBuilder->codeAppendf("float2 Z = dxy * %s.xy;", invRadiiXYSqdName); fragBuilder->codeAppendf("half2 Z = dxy * %s.xy;", invRadiiXYSqdName);
break; break;
} }
case SkRRect::kNinePatch_Type: { case SkRRect::kNinePatch_Type: {
const char *invRadiiLTRBSqdName; const char *invRadiiLTRBSqdName;
fInvRadiiSqdUniform = uniformHandler->addUniform(kFragment_GrShaderFlag, fInvRadiiSqdUniform = uniformHandler->addUniform(kFragment_GrShaderFlag,
kVec4f_GrSLType, kHalf4_GrSLType,
kDefault_GrSLPrecision,
"invRadiiLTRB", "invRadiiLTRB",
&invRadiiLTRBSqdName); &invRadiiLTRBSqdName);
if (scaleName) { if (scaleName) {
fragBuilder->codeAppendf("dxy0 *= %s.y;", scaleName); fragBuilder->codeAppendf("dxy0 *= %s.y;", scaleName);
fragBuilder->codeAppendf("dxy1 *= %s.y;", scaleName); fragBuilder->codeAppendf("dxy1 *= %s.y;", scaleName);
} }
fragBuilder->codeAppend("float2 dxy = max(max(dxy0, dxy1), 0.0);"); fragBuilder->codeAppend("half2 dxy = max(max(dxy0, dxy1), 0.0);");
// Z is the x/y offsets divided by squared radii. We only care about the (at most) one // 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 // corner where both the x and y offsets are positive, hence the maxes. (The inverse
// squared radii will always be positive.) // squared radii will always be positive.)
fragBuilder->codeAppendf("float2 Z = max(max(dxy0 * %s.xy, dxy1 * %s.zw), 0.0);", fragBuilder->codeAppendf("half2 Z = max(max(dxy0 * %s.xy, dxy1 * %s.zw), 0.0);",
invRadiiLTRBSqdName, invRadiiLTRBSqdName); invRadiiLTRBSqdName, invRadiiLTRBSqdName);
break; break;
@ -586,20 +577,20 @@ void GLEllipticalRRectEffect::emitCode(EmitArgs& args) {
SK_ABORT("RRect should always be simple or nine-patch."); SK_ABORT("RRect should always be simple or nine-patch.");
} }
// implicit is the evaluation of (x/a)^2 + (y/b)^2 - 1. // implicit is the evaluation of (x/a)^2 + (y/b)^2 - 1.
fragBuilder->codeAppend("float implicit = dot(Z, dxy) - 1.0;"); fragBuilder->codeAppend("half implicit = dot(Z, dxy) - 1.0;");
// grad_dot is the squared length of the gradient of the implicit. // grad_dot is the squared length of the gradient of the implicit.
fragBuilder->codeAppend("float grad_dot = 4.0 * dot(Z, Z);"); fragBuilder->codeAppend("half grad_dot = 4.0 * dot(Z, Z);");
// avoid calling inversesqrt on zero. // avoid calling inversesqrt on zero.
fragBuilder->codeAppend("grad_dot = max(grad_dot, 1.0e-4);"); fragBuilder->codeAppend("grad_dot = max(grad_dot, 1.0e-4);");
fragBuilder->codeAppend("float approx_dist = implicit * inversesqrt(grad_dot);"); fragBuilder->codeAppend("half approx_dist = implicit * inversesqrt(grad_dot);");
if (scaleName) { if (scaleName) {
fragBuilder->codeAppendf("approx_dist *= %s.x;", scaleName); fragBuilder->codeAppendf("approx_dist *= %s.x;", scaleName);
} }
if (kFillAA_GrProcessorEdgeType == erre.getEdgeType()) { if (kFillAA_GrProcessorEdgeType == erre.getEdgeType()) {
fragBuilder->codeAppend("float alpha = clamp(0.5 - approx_dist, 0.0, 1.0);"); fragBuilder->codeAppend("half alpha = clamp(0.5 - approx_dist, 0.0, 1.0);");
} else { } else {
fragBuilder->codeAppend("float alpha = clamp(0.5 + approx_dist, 0.0, 1.0);"); fragBuilder->codeAppend("half alpha = clamp(0.5 + approx_dist, 0.0, 1.0);");
} }
fragBuilder->codeAppendf("%s = %s * alpha;", args.fOutputColor, args.fInputColor); fragBuilder->codeAppendf("%s = %s * alpha;", args.fOutputColor, args.fInputColor);

View File

@ -20,11 +20,11 @@ public:
SkString srgbFuncName; SkString srgbFuncName;
static const GrShaderVar gSrgbArgs[] = { static const GrShaderVar gSrgbArgs[] = {
GrShaderVar("x", kFloat_GrSLType), GrShaderVar("x", kHalf_GrSLType),
}; };
switch (srgbe.mode()) { switch (srgbe.mode()) {
case GrSRGBEffect::Mode::kLinearToSRGB: case GrSRGBEffect::Mode::kLinearToSRGB:
fragBuilder->emitFunction(kFloat_GrSLType, fragBuilder->emitFunction(kHalf_GrSLType,
"linear_to_srgb", "linear_to_srgb",
SK_ARRAY_COUNT(gSrgbArgs), SK_ARRAY_COUNT(gSrgbArgs),
gSrgbArgs, gSrgbArgs,
@ -33,7 +33,7 @@ public:
&srgbFuncName); &srgbFuncName);
break; break;
case GrSRGBEffect::Mode::kSRGBToLinear: case GrSRGBEffect::Mode::kSRGBToLinear:
fragBuilder->emitFunction(kFloat_GrSLType, fragBuilder->emitFunction(kHalf_GrSLType,
"srgb_to_linear", "srgb_to_linear",
SK_ARRAY_COUNT(gSrgbArgs), SK_ARRAY_COUNT(gSrgbArgs),
gSrgbArgs, gSrgbArgs,
@ -44,20 +44,20 @@ public:
} }
if (nullptr == args.fInputColor) { if (nullptr == args.fInputColor) {
args.fInputColor = "float4(1)"; args.fInputColor = "half4(1)";
} }
fragBuilder->codeAppendf("float4 color = %s;", args.fInputColor); fragBuilder->codeAppendf("half4 color = %s;", args.fInputColor);
if (srgbe.alpha() == GrSRGBEffect::Alpha::kPremul) { if (srgbe.alpha() == GrSRGBEffect::Alpha::kPremul) {
fragBuilder->codeAppendf("float nonZeroAlpha = max(color.a, 0.00001);"); fragBuilder->codeAppendf("half nonZeroAlpha = max(color.a, 0.00001);");
fragBuilder->codeAppendf("color = float4(color.rgb / nonZeroAlpha, color.a);"); fragBuilder->codeAppendf("color = half4(color.rgb / nonZeroAlpha, color.a);");
} }
fragBuilder->codeAppendf("color = float4(%s(color.r), %s(color.g), %s(color.b), color.a);", fragBuilder->codeAppendf("color = half4(%s(color.r), %s(color.g), %s(color.b), color.a);",
srgbFuncName.c_str(), srgbFuncName.c_str(),
srgbFuncName.c_str(), srgbFuncName.c_str(),
srgbFuncName.c_str()); srgbFuncName.c_str());
if (srgbe.alpha() == GrSRGBEffect::Alpha::kPremul) { if (srgbe.alpha() == GrSRGBEffect::Alpha::kPremul) {
fragBuilder->codeAppendf("color = float4(color.rgb, 1) * color.a;"); fragBuilder->codeAppendf("color = half4(color.rgb, 1) * color.a;");
} }
fragBuilder->codeAppendf("%s = color;", args.fOutputColor); fragBuilder->codeAppendf("%s = color;", args.fOutputColor);
} }

View File

@ -26,7 +26,7 @@ public:
// emit attributes // emit attributes
varyingHandler->emitAttributes(rsgp); varyingHandler->emitAttributes(rsgp);
fragBuilder->codeAppend("float4 shadowParams;"); fragBuilder->codeAppend("half4 shadowParams;");
varyingHandler->addPassThroughAttribute(rsgp.inShadowParams(), "shadowParams"); varyingHandler->addPassThroughAttribute(rsgp.inShadowParams(), "shadowParams");
// setup pass through color // setup pass through color
@ -43,12 +43,12 @@ public:
rsgp.inPosition()->fName, rsgp.inPosition()->fName,
args.fFPCoordTransformHandler); args.fFPCoordTransformHandler);
fragBuilder->codeAppend("float d = length(shadowParams.xy);"); fragBuilder->codeAppend("half d = length(shadowParams.xy);");
fragBuilder->codeAppend("float distance = shadowParams.z * (1.0 - d);"); fragBuilder->codeAppend("half distance = shadowParams.z * (1.0 - d);");
fragBuilder->codeAppend("float factor = 1.0 - clamp(distance, 0.0, shadowParams.w);"); fragBuilder->codeAppend("half factor = 1.0 - clamp(distance, 0.0, shadowParams.w);");
fragBuilder->codeAppend("factor = exp(-factor * factor * 4.0) - 0.018;"); fragBuilder->codeAppend("factor = exp(-factor * factor * 4.0) - 0.018;");
fragBuilder->codeAppendf("%s = float4(factor);", fragBuilder->codeAppendf("%s = half4(factor);",
args.fOutputCoverage); args.fOutputCoverage);
} }

View File

@ -26,15 +26,15 @@ public:
fColorSpaceHelper.emitCode(args.fUniformHandler, _outer.colorXform().get()); fColorSpaceHelper.emitCode(args.fUniformHandler, _outer.colorXform().get());
SkString sk_TransformedCoords2D_0 = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]); SkString sk_TransformedCoords2D_0 = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
fragBuilder->codeAppendf( fragBuilder->codeAppendf(
"float4 _tmpVar1;%s = %s * %stexture(%s, %s).%s%s;\n", args.fOutputColor, "half4 _tmpVar1;%s = %s * %stexture(%s, %s).%s%s;\n", args.fOutputColor,
args.fInputColor ? args.fInputColor : "float4(1)", args.fInputColor ? args.fInputColor : "half4(1)",
fColorSpaceHelper.isValid() ? "(_tmpVar1 = " : "", fColorSpaceHelper.isValid() ? "(_tmpVar1 = " : "",
fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]).c_str(), fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]).c_str(),
sk_TransformedCoords2D_0.c_str(), sk_TransformedCoords2D_0.c_str(),
fragBuilder->getProgramBuilder()->samplerSwizzle(args.fTexSamplers[0]).c_str(), fragBuilder->getProgramBuilder()->samplerSwizzle(args.fTexSamplers[0]).c_str(),
fColorSpaceHelper.isValid() fColorSpaceHelper.isValid()
? SkStringPrintf(", float4(clamp((%s * float4(_tmpVar1.rgb, 1.0)).rgb, " ? SkStringPrintf(", half4(clamp((%s * half4(_tmpVar1.rgb, 1.0)).rgb, 0.0, "
"0.0, _tmpVar1.a), _tmpVar1.a))", "_tmpVar1.a), _tmpVar1.a))",
args.fUniformHandler->getUniformCStr( args.fUniformHandler->getUniformCStr(
fColorSpaceHelper.gamutXformUniform())) fColorSpaceHelper.gamutXformUniform()))
.c_str() .c_str()

View File

@ -7,7 +7,7 @@
in uniform sampler2D image; in uniform sampler2D image;
in uniform colorSpaceXform colorXform; in uniform colorSpaceXform colorXform;
in float4x4 matrix; in half4x4 matrix;
@constructorParams { @constructorParams {
GrSamplerState samplerParams GrSamplerState samplerParams

View File

@ -78,8 +78,7 @@ void GrTextureDomain::GLDomain::sampleTexture(GrGLSLShaderBuilder* builder,
if (textureDomain.fIndex >= 0) { if (textureDomain.fIndex >= 0) {
uniName.appendS32(textureDomain.fIndex); uniName.appendS32(textureDomain.fIndex);
} }
fDomainUni = uniformHandler->addUniform(kFragment_GrShaderFlag, fDomainUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType,
kVec4f_GrSLType, kDefault_GrSLPrecision,
uniName.c_str(), &name); uniName.c_str(), &name);
fDomainName = name; fDomainName = name;
} }
@ -88,7 +87,7 @@ void GrTextureDomain::GLDomain::sampleTexture(GrGLSLShaderBuilder* builder,
case kIgnore_Mode: { case kIgnore_Mode: {
builder->codeAppendf("%s = ", outColor); builder->codeAppendf("%s = ", outColor);
builder->appendTextureLookupAndModulate(inModulateColor, sampler, inCoords.c_str(), builder->appendTextureLookupAndModulate(inModulateColor, sampler, inCoords.c_str(),
kVec2f_GrSLType, colorXformHelper); kHighFloat2_GrSLType, colorXformHelper);
builder->codeAppend(";"); builder->codeAppend(";");
break; break;
} }
@ -99,7 +98,7 @@ void GrTextureDomain::GLDomain::sampleTexture(GrGLSLShaderBuilder* builder,
builder->codeAppendf("%s = ", outColor); builder->codeAppendf("%s = ", outColor);
builder->appendTextureLookupAndModulate(inModulateColor, sampler, clampedCoords.c_str(), builder->appendTextureLookupAndModulate(inModulateColor, sampler, clampedCoords.c_str(),
kVec2f_GrSLType, colorXformHelper); kHighFloat2_GrSLType, colorXformHelper);
builder->codeAppend(";"); builder->codeAppend(";");
break; break;
} }
@ -115,20 +114,20 @@ void GrTextureDomain::GLDomain::sampleTexture(GrGLSLShaderBuilder* builder,
// may return undefined results". This appears to be an issue with // may return undefined results". This appears to be an issue with
// the 'any' call since even the simple "result=black; if (any()) // the 'any' call since even the simple "result=black; if (any())
// result=white;" code fails to compile. // result=white;" code fails to compile.
builder->codeAppend("float4 outside = float4(0.0, 0.0, 0.0, 0.0);"); builder->codeAppend("half4 outside = half4(0.0, 0.0, 0.0, 0.0);");
builder->codeAppend("float4 inside = "); builder->codeAppend("half4 inside = ");
builder->appendTextureLookupAndModulate(inModulateColor, sampler, inCoords.c_str(), builder->appendTextureLookupAndModulate(inModulateColor, sampler, inCoords.c_str(),
kVec2f_GrSLType, colorXformHelper); kHighFloat2_GrSLType, colorXformHelper);
builder->codeAppend(";"); builder->codeAppend(";");
builder->codeAppendf("highp float x = (%s).x;", inCoords.c_str()); builder->codeAppendf("highfloat x = (%s).x;", inCoords.c_str());
builder->codeAppendf("highp float y = (%s).y;", inCoords.c_str()); builder->codeAppendf("highfloat y = (%s).y;", inCoords.c_str());
builder->codeAppendf("x = abs(2.0*(x - %s.x)/(%s.z - %s.x) - 1.0);", builder->codeAppendf("x = abs(2.0*(x - %s.x)/(%s.z - %s.x) - 1.0);",
domain, domain, domain); domain, domain, domain);
builder->codeAppendf("y = abs(2.0*(y - %s.y)/(%s.w - %s.y) - 1.0);", builder->codeAppendf("y = abs(2.0*(y - %s.y)/(%s.w - %s.y) - 1.0);",
domain, domain, domain); domain, domain, domain);
builder->codeAppend("float blend = step(1.0, max(x, y));"); builder->codeAppend("half blend = step(1.0, max(x, y));");
builder->codeAppendf("%s = mix(inside, outside, blend);", outColor); builder->codeAppendf("%s = mix(inside, outside, blend);", outColor);
} else { } else {
builder->codeAppend("bool4 outside;\n"); builder->codeAppend("bool4 outside;\n");
@ -136,10 +135,10 @@ void GrTextureDomain::GLDomain::sampleTexture(GrGLSLShaderBuilder* builder,
domain); domain);
builder->codeAppendf("outside.zw = greaterThan(%s, %s.zw);", inCoords.c_str(), builder->codeAppendf("outside.zw = greaterThan(%s, %s.zw);", inCoords.c_str(),
domain); domain);
builder->codeAppendf("%s = any(outside) ? float4(0.0, 0.0, 0.0, 0.0) : ", builder->codeAppendf("%s = any(outside) ? half4(0.0, 0.0, 0.0, 0.0) : ",
outColor); outColor);
builder->appendTextureLookupAndModulate(inModulateColor, sampler, inCoords.c_str(), builder->appendTextureLookupAndModulate(inModulateColor, sampler, inCoords.c_str(),
kVec2f_GrSLType, colorXformHelper); kHighFloat2_GrSLType, colorXformHelper);
builder->codeAppend(";"); builder->codeAppend(";");
} }
break; break;
@ -152,7 +151,7 @@ void GrTextureDomain::GLDomain::sampleTexture(GrGLSLShaderBuilder* builder,
builder->codeAppendf("%s = ", outColor); builder->codeAppendf("%s = ", outColor);
builder->appendTextureLookupAndModulate(inModulateColor, sampler, clampedCoords.c_str(), builder->appendTextureLookupAndModulate(inModulateColor, sampler, clampedCoords.c_str(),
kVec2f_GrSLType, colorXformHelper); kHighFloat2_GrSLType, colorXformHelper);
builder->codeAppend(";"); builder->codeAppend(";");
break; break;
} }
@ -377,11 +376,10 @@ GrGLSLFragmentProcessor* GrDeviceSpaceTextureDecalFragmentProcessor::onCreateGLS
args.fFp.cast<GrDeviceSpaceTextureDecalFragmentProcessor>(); args.fFp.cast<GrDeviceSpaceTextureDecalFragmentProcessor>();
const char* scaleAndTranslateName; const char* scaleAndTranslateName;
fScaleAndTranslateUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, fScaleAndTranslateUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
kVec4f_GrSLType, kHalf4_GrSLType,
kDefault_GrSLPrecision,
"scaleAndTranslate", "scaleAndTranslate",
&scaleAndTranslateName); &scaleAndTranslateName);
args.fFragBuilder->codeAppendf("float2 coords = sk_FragCoord.xy * %s.xy + %s.zw;", args.fFragBuilder->codeAppendf("half2 coords = sk_FragCoord.xy * %s.xy + %s.zw;",
scaleAndTranslateName, scaleAndTranslateName); scaleAndTranslateName, scaleAndTranslateName);
fGLDomain.sampleTexture(args.fFragBuilder, fGLDomain.sampleTexture(args.fFragBuilder,
args.fUniformHandler, args.fUniformHandler,

View File

@ -23,7 +23,7 @@ struct SkRect;
/** /**
* Limits a texture's lookup coordinates to a domain. Samples outside the domain are either clamped * Limits a texture's lookup coordinates to a domain. Samples outside the domain are either clamped
* the edge of the domain or result in a float4 of zeros (decal mode). The domain is clipped to * the edge of the domain or result in a half4 of zeros (decal mode). The domain is clipped to
* normalized texture coords ([0,1]x[0,1] square). Bilinear filtering can cause texels outside the * normalized texture coords ([0,1]x[0,1] square). Bilinear filtering can cause texels outside the
* domain to affect the read value unless the caller considers this when calculating the domain. * domain to affect the read value unless the caller considers this when calculating the domain.
*/ */
@ -98,7 +98,7 @@ public:
* Call this from GrGLSLFragmentProcessor::emitCode() to sample the texture W.R.T. the * Call this from GrGLSLFragmentProcessor::emitCode() to sample the texture W.R.T. the
* domain and mode. * domain and mode.
* *
* @param outcolor name of float4 variable to hold the sampled color. * @param outcolor name of half4 variable to hold the sampled color.
* @param inCoords name of float2 variable containing the coords to be used with the domain. * @param inCoords name of float2 variable containing the coords to be used with the domain.
* It is assumed that this is a variable and not an expression. * It is assumed that this is a variable and not an expression.
* @param inModulateColor if non-nullptr the sampled color will be modulated with this * @param inModulateColor if non-nullptr the sampled color will be modulated with this

View File

@ -217,7 +217,7 @@ void GLComposeTwoFragmentProcessor::emitCode(EmitArgs& args) {
const char* inputColor = nullptr; const char* inputColor = nullptr;
if (args.fInputColor) { if (args.fInputColor) {
inputColor = "inputColor"; inputColor = "inputColor";
fragBuilder->codeAppendf("float4 inputColor = float4(%s.rgb, 1.0);", args.fInputColor); fragBuilder->codeAppendf("half4 inputColor = half4(%s.rgb, 1.0);", args.fInputColor);
} }
// declare outputColor and emit the code for each of the two children // declare outputColor and emit the code for each of the two children
@ -452,7 +452,7 @@ public:
const char* inputColor = args.fInputColor; const char* inputColor = args.fInputColor;
// We don't try to optimize for this case at all // We don't try to optimize for this case at all
if (!inputColor) { if (!inputColor) {
fragBuilder->codeAppendf("const float4 ones = float4(1);"); fragBuilder->codeAppendf("const half4 ones = half4(1);");
inputColor = "ones"; inputColor = "ones";
} }

View File

@ -89,10 +89,9 @@ public:
const YUVtoRGBEffect& effect = args.fFp.cast<YUVtoRGBEffect>(); const YUVtoRGBEffect& effect = args.fFp.cast<YUVtoRGBEffect>();
const char* colorSpaceMatrix = nullptr; const char* colorSpaceMatrix = nullptr;
fMatrixUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, fMatrixUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4x4_GrSLType,
kMat44f_GrSLType, kDefault_GrSLPrecision,
"ColorSpaceMatrix", &colorSpaceMatrix); "ColorSpaceMatrix", &colorSpaceMatrix);
fragBuilder->codeAppendf("%s = float4(", args.fOutputColor); fragBuilder->codeAppendf("%s = half4(", args.fOutputColor);
fragBuilder->appendTextureLookup(args.fTexSamplers[0], fragBuilder->appendTextureLookup(args.fTexSamplers[0],
args.fTransformedCoords[0].c_str(), args.fTransformedCoords[0].c_str(),
args.fTransformedCoords[0].getType()); args.fTransformedCoords[0].getType());

View File

@ -3474,13 +3474,13 @@ bool GrGLGpu::createCopyProgram(GrTexture* srcTex) {
} }
const char* version = shaderCaps->versionDeclString(); const char* version = shaderCaps->versionDeclString();
GrShaderVar aVertex("a_vertex", kVec2f_GrSLType, GrShaderVar::kIn_TypeModifier); GrShaderVar aVertex("a_vertex", kHalf2_GrSLType, GrShaderVar::kIn_TypeModifier);
GrShaderVar uTexCoordXform("u_texCoordXform", kVec4f_GrSLType, GrShaderVar uTexCoordXform("u_texCoordXform", kHalf4_GrSLType,
GrShaderVar::kUniform_TypeModifier); GrShaderVar::kUniform_TypeModifier);
GrShaderVar uPosXform("u_posXform", kVec4f_GrSLType, GrShaderVar::kUniform_TypeModifier); GrShaderVar uPosXform("u_posXform", kHalf4_GrSLType, GrShaderVar::kUniform_TypeModifier);
GrShaderVar uTexture("u_texture", samplerType, GrShaderVar::kUniform_TypeModifier); GrShaderVar uTexture("u_texture", samplerType, GrShaderVar::kUniform_TypeModifier);
GrShaderVar vTexCoord("v_texCoord", kVec2f_GrSLType, GrShaderVar::kOut_TypeModifier); GrShaderVar vTexCoord("v_texCoord", kHalf2_GrSLType, GrShaderVar::kOut_TypeModifier);
GrShaderVar oFragColor("o_FragColor", kVec4f_GrSLType, GrShaderVar::kOut_TypeModifier); GrShaderVar oFragColor("o_FragColor", kHalf4_GrSLType, GrShaderVar::kOut_TypeModifier);
SkString vshaderTxt(version); SkString vshaderTxt(version);
if (shaderCaps->noperspectiveInterpolationSupport()) { if (shaderCaps->noperspectiveInterpolationSupport()) {
@ -3504,7 +3504,7 @@ bool GrGLGpu::createCopyProgram(GrTexture* srcTex) {
"void main() {" "void main() {"
" v_texCoord = a_vertex.xy * u_texCoordXform.xy + u_texCoordXform.zw;" " v_texCoord = a_vertex.xy * u_texCoordXform.xy + u_texCoordXform.zw;"
" gl_Position.xy = a_vertex * u_posXform.xy + u_posXform.zw;" " gl_Position.xy = a_vertex * u_posXform.xy + u_posXform.zw;"
" gl_Position.zw = float2(0, 1);" " gl_Position.zw = half2(0, 1);"
"}" "}"
); );
@ -3518,8 +3518,6 @@ bool GrGLGpu::createCopyProgram(GrTexture* srcTex) {
fshaderTxt.appendf("#extension %s : require\n", fshaderTxt.appendf("#extension %s : require\n",
shaderCaps->externalTextureExtensionString()); shaderCaps->externalTextureExtensionString());
} }
GrGLSLAppendDefaultFloatPrecisionDeclaration(kMedium_GrSLPrecision, *shaderCaps,
&fshaderTxt);
vTexCoord.setTypeModifier(GrShaderVar::kIn_TypeModifier); vTexCoord.setTypeModifier(GrShaderVar::kIn_TypeModifier);
vTexCoord.appendDecl(shaderCaps, &fshaderTxt); vTexCoord.appendDecl(shaderCaps, &fshaderTxt);
fshaderTxt.append(";"); fshaderTxt.append(";");
@ -3583,19 +3581,19 @@ bool GrGLGpu::createMipmapProgram(int progIdx) {
} }
const char* version = shaderCaps->versionDeclString(); const char* version = shaderCaps->versionDeclString();
GrShaderVar aVertex("a_vertex", kVec2f_GrSLType, GrShaderVar::kIn_TypeModifier); GrShaderVar aVertex("a_vertex", kHalf2_GrSLType, GrShaderVar::kIn_TypeModifier);
GrShaderVar uTexCoordXform("u_texCoordXform", kVec4f_GrSLType, GrShaderVar uTexCoordXform("u_texCoordXform", kHalf4_GrSLType,
GrShaderVar::kUniform_TypeModifier); GrShaderVar::kUniform_TypeModifier);
GrShaderVar uTexture("u_texture", kTexture2DSampler_GrSLType, GrShaderVar uTexture("u_texture", kTexture2DSampler_GrSLType,
GrShaderVar::kUniform_TypeModifier); GrShaderVar::kUniform_TypeModifier);
// We need 1, 2, or 4 texture coordinates (depending on parity of each dimension): // We need 1, 2, or 4 texture coordinates (depending on parity of each dimension):
GrShaderVar vTexCoords[] = { GrShaderVar vTexCoords[] = {
GrShaderVar("v_texCoord0", kVec2f_GrSLType, GrShaderVar::kOut_TypeModifier), GrShaderVar("v_texCoord0", kHalf2_GrSLType, GrShaderVar::kOut_TypeModifier),
GrShaderVar("v_texCoord1", kVec2f_GrSLType, GrShaderVar::kOut_TypeModifier), GrShaderVar("v_texCoord1", kHalf2_GrSLType, GrShaderVar::kOut_TypeModifier),
GrShaderVar("v_texCoord2", kVec2f_GrSLType, GrShaderVar::kOut_TypeModifier), GrShaderVar("v_texCoord2", kHalf2_GrSLType, GrShaderVar::kOut_TypeModifier),
GrShaderVar("v_texCoord3", kVec2f_GrSLType, GrShaderVar::kOut_TypeModifier), GrShaderVar("v_texCoord3", kHalf2_GrSLType, GrShaderVar::kOut_TypeModifier),
}; };
GrShaderVar oFragColor("o_FragColor", kVec4f_GrSLType,GrShaderVar::kOut_TypeModifier); GrShaderVar oFragColor("o_FragColor", kHalf4_GrSLType,GrShaderVar::kOut_TypeModifier);
SkString vshaderTxt(version); SkString vshaderTxt(version);
if (shaderCaps->noperspectiveInterpolationSupport()) { if (shaderCaps->noperspectiveInterpolationSupport()) {
@ -3620,27 +3618,27 @@ bool GrGLGpu::createMipmapProgram(int progIdx) {
vshaderTxt.append( vshaderTxt.append(
"// Mipmap Program VS\n" "// Mipmap Program VS\n"
"void main() {" "void main() {"
" gl_Position.xy = a_vertex * float2(2, 2) - float2(1, 1);" " gl_Position.xy = a_vertex * half2(2, 2) - half2(1, 1);"
" gl_Position.zw = float2(0, 1);" " gl_Position.zw = half2(0, 1);"
); );
// Insert texture coordinate computation: // Insert texture coordinate computation:
if (oddWidth && oddHeight) { if (oddWidth && oddHeight) {
vshaderTxt.append( vshaderTxt.append(
" v_texCoord0 = a_vertex.xy * u_texCoordXform.yw;" " v_texCoord0 = a_vertex.xy * u_texCoordXform.yw;"
" v_texCoord1 = a_vertex.xy * u_texCoordXform.yw + float2(u_texCoordXform.x, 0);" " v_texCoord1 = a_vertex.xy * u_texCoordXform.yw + half2(u_texCoordXform.x, 0);"
" v_texCoord2 = a_vertex.xy * u_texCoordXform.yw + float2(0, u_texCoordXform.z);" " v_texCoord2 = a_vertex.xy * u_texCoordXform.yw + half2(0, u_texCoordXform.z);"
" v_texCoord3 = a_vertex.xy * u_texCoordXform.yw + u_texCoordXform.xz;" " v_texCoord3 = a_vertex.xy * u_texCoordXform.yw + u_texCoordXform.xz;"
); );
} else if (oddWidth) { } else if (oddWidth) {
vshaderTxt.append( vshaderTxt.append(
" v_texCoord0 = a_vertex.xy * float2(u_texCoordXform.y, 1);" " v_texCoord0 = a_vertex.xy * half2(u_texCoordXform.y, 1);"
" v_texCoord1 = a_vertex.xy * float2(u_texCoordXform.y, 1) + float2(u_texCoordXform.x, 0);" " v_texCoord1 = a_vertex.xy * half2(u_texCoordXform.y, 1) + half2(u_texCoordXform.x, 0);"
); );
} else if (oddHeight) { } else if (oddHeight) {
vshaderTxt.append( vshaderTxt.append(
" v_texCoord0 = a_vertex.xy * float2(1, u_texCoordXform.w);" " v_texCoord0 = a_vertex.xy * half2(1, u_texCoordXform.w);"
" v_texCoord1 = a_vertex.xy * float2(1, u_texCoordXform.w) + float2(0, u_texCoordXform.z);" " v_texCoord1 = a_vertex.xy * half2(1, u_texCoordXform.w) + half2(0, u_texCoordXform.z);"
); );
} else { } else {
vshaderTxt.append( vshaderTxt.append(
@ -3656,8 +3654,6 @@ bool GrGLGpu::createMipmapProgram(int progIdx) {
fshaderTxt.appendf("#extension %s : require\n", extension); fshaderTxt.appendf("#extension %s : require\n", extension);
} }
} }
GrGLSLAppendDefaultFloatPrecisionDeclaration(kMedium_GrSLPrecision, *shaderCaps,
&fshaderTxt);
for (int i = 0; i < numTaps; ++i) { for (int i = 0; i < numTaps; ++i) {
vTexCoords[i].setTypeModifier(GrShaderVar::kIn_TypeModifier); vTexCoords[i].setTypeModifier(GrShaderVar::kIn_TypeModifier);
vTexCoords[i].appendDecl(shaderCaps, &fshaderTxt); vTexCoords[i].appendDecl(shaderCaps, &fshaderTxt);
@ -3743,7 +3739,7 @@ bool GrGLGpu::createStencilClipClearProgram() {
return false; return false;
} }
GrShaderVar aVertex("a_vertex", kVec2f_GrSLType, GrShaderVar::kIn_TypeModifier); GrShaderVar aVertex("a_vertex", kHalf2_GrSLType, GrShaderVar::kIn_TypeModifier);
const char* version = this->caps()->shaderCaps()->versionDeclString(); const char* version = this->caps()->shaderCaps()->versionDeclString();
SkString vshaderTxt(version); SkString vshaderTxt(version);
@ -3752,17 +3748,14 @@ bool GrGLGpu::createStencilClipClearProgram() {
vshaderTxt.append( vshaderTxt.append(
"// Stencil Clip Clear Program VS\n" "// Stencil Clip Clear Program VS\n"
"void main() {" "void main() {"
" gl_Position = float4(a_vertex.x, a_vertex.y, 0, 1);" " gl_Position = highfloat4(a_vertex.x, a_vertex.y, 0, 1);"
"}"); "}");
SkString fshaderTxt(version); SkString fshaderTxt(version);
GrGLSLAppendDefaultFloatPrecisionDeclaration(kMedium_GrSLPrecision,
*this->caps()->shaderCaps(),
&fshaderTxt);
fshaderTxt.appendf( fshaderTxt.appendf(
"// Stencil Clip Clear Program FS\n" "// Stencil Clip Clear Program FS\n"
"void main() {" "void main() {"
" sk_FragColor = float4(0);" " sk_FragColor = half4(0);"
"}"); "}");
const char* str; const char* str;

View File

@ -73,7 +73,7 @@ void GrGLProgramDataManager::setImageStorages(const UniformInfoArray& images) co
void GrGLProgramDataManager::set1i(UniformHandle u, int32_t i) const { void GrGLProgramDataManager::set1i(UniformHandle u, int32_t i) const {
const Uniform& uni = fUniforms[u.toIndex()]; const Uniform& uni = fUniforms[u.toIndex()];
SkASSERT(uni.fType == kInt_GrSLType); SkASSERT(uni.fType == kInt_GrSLType || uni.fType == kShort_GrSLType);
SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount); SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
if (kUnusedUniform != uni.fLocation) { if (kUnusedUniform != uni.fLocation) {
GR_GL_CALL(fGpu->glInterface(), Uniform1i(uni.fLocation, i)); GR_GL_CALL(fGpu->glInterface(), Uniform1i(uni.fLocation, i));
@ -84,7 +84,7 @@ void GrGLProgramDataManager::set1iv(UniformHandle u,
int arrayCount, int arrayCount,
const int v[]) const { const int v[]) const {
const Uniform& uni = fUniforms[u.toIndex()]; const Uniform& uni = fUniforms[u.toIndex()];
SkASSERT(uni.fType == kInt_GrSLType); SkASSERT(uni.fType == kInt_GrSLType || uni.fType == kShort_GrSLType);
SkASSERT(arrayCount > 0); SkASSERT(arrayCount > 0);
ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount); ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount);
if (kUnusedUniform != uni.fLocation) { if (kUnusedUniform != uni.fLocation) {
@ -94,7 +94,7 @@ void GrGLProgramDataManager::set1iv(UniformHandle u,
void GrGLProgramDataManager::set1f(UniformHandle u, float v0) const { void GrGLProgramDataManager::set1f(UniformHandle u, float v0) const {
const Uniform& uni = fUniforms[u.toIndex()]; const Uniform& uni = fUniforms[u.toIndex()];
SkASSERT(uni.fType == kFloat_GrSLType); SkASSERT(uni.fType == kHighFloat_GrSLType || uni.fType == kHalf_GrSLType);
SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount); SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
if (kUnusedUniform != uni.fLocation) { if (kUnusedUniform != uni.fLocation) {
GR_GL_CALL(fGpu->glInterface(), Uniform1f(uni.fLocation, v0)); GR_GL_CALL(fGpu->glInterface(), Uniform1f(uni.fLocation, v0));
@ -105,7 +105,7 @@ void GrGLProgramDataManager::set1fv(UniformHandle u,
int arrayCount, int arrayCount,
const float v[]) const { const float v[]) const {
const Uniform& uni = fUniforms[u.toIndex()]; const Uniform& uni = fUniforms[u.toIndex()];
SkASSERT(uni.fType == kFloat_GrSLType); SkASSERT(uni.fType == kHighFloat_GrSLType || uni.fType == kHalf_GrSLType);
SkASSERT(arrayCount > 0); SkASSERT(arrayCount > 0);
ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount); ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount);
// This assert fires in some instances of the two-pt gradient for its VSParams. // This assert fires in some instances of the two-pt gradient for its VSParams.
@ -119,7 +119,7 @@ void GrGLProgramDataManager::set1fv(UniformHandle u,
void GrGLProgramDataManager::set2f(UniformHandle u, float v0, float v1) const { void GrGLProgramDataManager::set2f(UniformHandle u, float v0, float v1) const {
const Uniform& uni = fUniforms[u.toIndex()]; const Uniform& uni = fUniforms[u.toIndex()];
SkASSERT(uni.fType == kVec2f_GrSLType); SkASSERT(uni.fType == kHighFloat2_GrSLType || uni.fType == kHalf2_GrSLType);
SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount); SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
if (kUnusedUniform != uni.fLocation) { if (kUnusedUniform != uni.fLocation) {
GR_GL_CALL(fGpu->glInterface(), Uniform2f(uni.fLocation, v0, v1)); GR_GL_CALL(fGpu->glInterface(), Uniform2f(uni.fLocation, v0, v1));
@ -130,7 +130,7 @@ void GrGLProgramDataManager::set2fv(UniformHandle u,
int arrayCount, int arrayCount,
const float v[]) const { const float v[]) const {
const Uniform& uni = fUniforms[u.toIndex()]; const Uniform& uni = fUniforms[u.toIndex()];
SkASSERT(uni.fType == kVec2f_GrSLType); SkASSERT(uni.fType == kHighFloat2_GrSLType || uni.fType == kHalf2_GrSLType);
SkASSERT(arrayCount > 0); SkASSERT(arrayCount > 0);
ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount); ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount);
if (kUnusedUniform != uni.fLocation) { if (kUnusedUniform != uni.fLocation) {
@ -140,7 +140,7 @@ void GrGLProgramDataManager::set2fv(UniformHandle u,
void GrGLProgramDataManager::set3f(UniformHandle u, float v0, float v1, float v2) const { void GrGLProgramDataManager::set3f(UniformHandle u, float v0, float v1, float v2) const {
const Uniform& uni = fUniforms[u.toIndex()]; const Uniform& uni = fUniforms[u.toIndex()];
SkASSERT(uni.fType == kVec3f_GrSLType); SkASSERT(uni.fType == kHighFloat3_GrSLType || uni.fType == kHalf3_GrSLType);
SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount); SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
if (kUnusedUniform != uni.fLocation) { if (kUnusedUniform != uni.fLocation) {
GR_GL_CALL(fGpu->glInterface(), Uniform3f(uni.fLocation, v0, v1, v2)); GR_GL_CALL(fGpu->glInterface(), Uniform3f(uni.fLocation, v0, v1, v2));
@ -151,7 +151,7 @@ void GrGLProgramDataManager::set3fv(UniformHandle u,
int arrayCount, int arrayCount,
const float v[]) const { const float v[]) const {
const Uniform& uni = fUniforms[u.toIndex()]; const Uniform& uni = fUniforms[u.toIndex()];
SkASSERT(uni.fType == kVec3f_GrSLType); SkASSERT(uni.fType == kHighFloat3_GrSLType || uni.fType == kHalf3_GrSLType);
SkASSERT(arrayCount > 0); SkASSERT(arrayCount > 0);
ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount); ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount);
if (kUnusedUniform != uni.fLocation) { if (kUnusedUniform != uni.fLocation) {
@ -165,7 +165,7 @@ void GrGLProgramDataManager::set4f(UniformHandle u,
float v2, float v2,
float v3) const { float v3) const {
const Uniform& uni = fUniforms[u.toIndex()]; const Uniform& uni = fUniforms[u.toIndex()];
SkASSERT(uni.fType == kVec4f_GrSLType); SkASSERT(uni.fType == kHighFloat4_GrSLType || uni.fType == kHalf4_GrSLType);
SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount); SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
if (kUnusedUniform != uni.fLocation) { if (kUnusedUniform != uni.fLocation) {
GR_GL_CALL(fGpu->glInterface(), Uniform4f(uni.fLocation, v0, v1, v2, v3)); GR_GL_CALL(fGpu->glInterface(), Uniform4f(uni.fLocation, v0, v1, v2, v3));
@ -176,7 +176,7 @@ void GrGLProgramDataManager::set4fv(UniformHandle u,
int arrayCount, int arrayCount,
const float v[]) const { const float v[]) const {
const Uniform& uni = fUniforms[u.toIndex()]; const Uniform& uni = fUniforms[u.toIndex()];
SkASSERT(uni.fType == kVec4f_GrSLType); SkASSERT(uni.fType == kHighFloat4_GrSLType || uni.fType == kHalf4_GrSLType);
SkASSERT(arrayCount > 0); SkASSERT(arrayCount > 0);
ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount); ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount);
if (kUnusedUniform != uni.fLocation) { if (kUnusedUniform != uni.fLocation) {
@ -214,7 +214,8 @@ template<int N> inline void GrGLProgramDataManager::setMatrices(UniformHandle u,
int arrayCount, int arrayCount,
const float matrices[]) const { const float matrices[]) const {
const Uniform& uni = fUniforms[u.toIndex()]; const Uniform& uni = fUniforms[u.toIndex()];
SkASSERT(uni.fType == kMat22f_GrSLType + (N - 2)); SkASSERT(uni.fType == kHighFloat2x2_GrSLType + (N - 2) ||
uni.fType == kHalf2x2_GrSLType + (N - 2));
SkASSERT(arrayCount > 0); SkASSERT(arrayCount > 0);
ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount); ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount);
if (kUnusedUniform != uni.fLocation) { if (kUnusedUniform != uni.fLocation) {
@ -246,8 +247,10 @@ void GrGLProgramDataManager::setPathFragmentInputTransform(VaryingHandle u,
SkASSERT(fGpu->glCaps().shaderCaps()->pathRenderingSupport()); SkASSERT(fGpu->glCaps().shaderCaps()->pathRenderingSupport());
const PathProcVarying& fragmentInput = fPathProcVaryings[u.toIndex()]; const PathProcVarying& fragmentInput = fPathProcVaryings[u.toIndex()];
SkASSERT((components == 2 && fragmentInput.fType == kVec2f_GrSLType) || SkASSERT((components == 2 && (fragmentInput.fType == kHighFloat2_GrSLType ||
(components == 3 && fragmentInput.fType == kVec3f_GrSLType)); fragmentInput.fType == kHalf2_GrSLType)) ||
(components == 3 && (fragmentInput.fType == kHighFloat3_GrSLType ||
fragmentInput.fType == kHalf3_GrSLType)));
fGpu->glPathRendering()->setProgramPathFragmentInputTransform(fProgramID, fGpu->glPathRendering()->setProgramPathFragmentInputTransform(fProgramID,
fragmentInput.fLocation, fragmentInput.fLocation,

View File

@ -24,7 +24,7 @@ GrGLSLUniformHandler::UniformHandle GrGLUniformHandler::internalAddUniformArray(
const char** outName) { const char** outName) {
SkASSERT(name && strlen(name)); SkASSERT(name && strlen(name));
SkASSERT(0 != visibility); SkASSERT(0 != visibility);
SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeAcceptsPrecision(type)); SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeTemporarilyAcceptsPrecision(type));
UniformInfo& uni = fUniforms.push_back(); UniformInfo& uni = fUniforms.push_back();
uni.fVariable.setType(type); uni.fVariable.setType(type);

View File

@ -139,6 +139,9 @@ GrGLProgram* GrGLProgramBuilder::finalize() {
return nullptr; return nullptr;
} }
if (fFS.fForceHighPrecision) {
settings.fForceHighPrecision = true;
}
if (!this->compileAndAttachShaders(fFS, programID, GR_GL_FRAGMENT_SHADER, &shadersToDelete, if (!this->compileAndAttachShaders(fFS, programID, GR_GL_FRAGMENT_SHADER, &shadersToDelete,
settings, &inputs)) { settings, &inputs)) {
this->cleanupProgram(programID, shadersToDelete); this->cleanupProgram(programID, shadersToDelete);

View File

@ -30,33 +30,47 @@ const char* GrGLSLTypeString(const GrShaderCaps* shaderCaps, GrSLType t) {
switch (t) { switch (t) {
case kVoid_GrSLType: case kVoid_GrSLType:
return "void"; return "void";
case kFloat_GrSLType: case kHalf_GrSLType:
return "float"; return "half";
case kVec2f_GrSLType: case kHalf2_GrSLType:
return "float2"; return "half2";
case kVec3f_GrSLType: case kHalf3_GrSLType:
return "float3"; return "half3";
case kVec4f_GrSLType: case kHalf4_GrSLType:
return "float4"; return "half4";
case kVec2us_GrSLType: case kHighFloat_GrSLType:
return "highfloat";
case kHighFloat2_GrSLType:
return "highfloat2";
case kHighFloat3_GrSLType:
return "highfloat3";
case kHighFloat4_GrSLType:
return "highfloat4";
case kUint2_GrSLType:
if (shaderCaps->integerSupport()) { if (shaderCaps->integerSupport()) {
return "uint2"; return "uint2";
} else { } else {
// uint2 (aka uvec2) isn't supported in GLSL ES 1.00/GLSL 1.20 // uint2 (aka uvec2) isn't supported in GLSL ES 1.00/GLSL 1.20
return "float2"; return "highfloat2";
} }
case kVec2i_GrSLType: case kInt2_GrSLType:
return "int2"; return "int2";
case kVec3i_GrSLType: case kInt3_GrSLType:
return "int3"; return "int3";
case kVec4i_GrSLType: case kInt4_GrSLType:
return "int4"; return "int4";
case kMat22f_GrSLType: case kHighFloat2x2_GrSLType:
return "float2x2"; return "highfloat2x2";
case kMat33f_GrSLType: case kHighFloat3x3_GrSLType:
return "float3x3"; return "highfloat3x3";
case kMat44f_GrSLType: case kHighFloat4x4_GrSLType:
return "float4x4"; return "highfloat4x4";
case kHalf2x2_GrSLType:
return "half2x2";
case kHalf3x3_GrSLType:
return "half3x3";
case kHalf4x4_GrSLType:
return "half4x4";
case kTexture2DSampler_GrSLType: case kTexture2DSampler_GrSLType:
return "sampler2D"; return "sampler2D";
case kITexture2DSampler_GrSLType: case kITexture2DSampler_GrSLType:
@ -73,6 +87,10 @@ const char* GrGLSLTypeString(const GrShaderCaps* shaderCaps, GrSLType t) {
return "int"; return "int";
case kUint_GrSLType: case kUint_GrSLType:
return "uint"; return "uint";
case kShort_GrSLType:
return "short";
case kUShort_GrSLType:
return "ushort";
case kTexture2D_GrSLType: case kTexture2D_GrSLType:
return "texture2D"; return "texture2D";
case kSampler_GrSLType: case kSampler_GrSLType:

View File

@ -50,7 +50,7 @@ static void color_dodge_component(GrGLSLFragmentBuilder* fsBuilder,
fsBuilder->codeAppendf("%s.%c = %s.%c * (1.0 - %s.a);", fsBuilder->codeAppendf("%s.%c = %s.%c * (1.0 - %s.a);",
final, component, src, component, dst); final, component, src, component, dst);
fsBuilder->codeAppend("} else {"); fsBuilder->codeAppend("} else {");
fsBuilder->codeAppendf("float d = %s.a - %s.%c;", src, src, component); fsBuilder->codeAppendf("half d = %s.a - %s.%c;", src, src, component);
fsBuilder->codeAppend("if (0.0 == d) {"); fsBuilder->codeAppend("if (0.0 == d) {");
fsBuilder->codeAppendf("%s.%c = %s.a * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);", fsBuilder->codeAppendf("%s.%c = %s.a * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);",
final, component, src, dst, src, component, dst, dst, component, final, component, src, dst, src, component, dst, dst, component,
@ -84,7 +84,7 @@ static void color_burn_component(GrGLSLFragmentBuilder* fsBuilder,
fsBuilder->codeAppendf("%s.%c = %s.%c * (1.0 - %s.a);", fsBuilder->codeAppendf("%s.%c = %s.%c * (1.0 - %s.a);",
final, component, dst, component, src); final, component, dst, component, src);
fsBuilder->codeAppend("} else {"); fsBuilder->codeAppend("} else {");
fsBuilder->codeAppendf("float d = max(0.0, %s.a - (%s.a - %s.%c) * %s.a / (%s.%c %s));", fsBuilder->codeAppendf("half d = max(0.0, %s.a - (%s.a - %s.%c) * %s.a / (%s.%c %s));",
dst, dst, dst, component, src, src, component, divisorGuard); dst, dst, dst, component, src, src, component, divisorGuard);
fsBuilder->codeAppendf("%s.%c = %s.a * d + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);", fsBuilder->codeAppendf("%s.%c = %s.a * d + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);",
final, component, src, src, component, dst, dst, component, src); final, component, src, src, component, dst, dst, component, src);
@ -114,11 +114,11 @@ static void soft_light_component_pos_dst_alpha(GrGLSLFragmentBuilder* fsBuilder,
// else if (4D < Da) // else if (4D < Da)
fsBuilder->codeAppendf("} else if (4.0 * %s.%c <= %s.a) {", fsBuilder->codeAppendf("} else if (4.0 * %s.%c <= %s.a) {",
dst, component, dst); dst, component, dst);
fsBuilder->codeAppendf("float DSqd = %s.%c * %s.%c;", fsBuilder->codeAppendf("half DSqd = %s.%c * %s.%c;",
dst, component, dst, component); dst, component, dst, component);
fsBuilder->codeAppendf("float DCub = DSqd * %s.%c;", dst, component); fsBuilder->codeAppendf("half DCub = DSqd * %s.%c;", dst, component);
fsBuilder->codeAppendf("float DaSqd = %s.a * %s.a;", dst, dst); fsBuilder->codeAppendf("half DaSqd = %s.a * %s.a;", dst, dst);
fsBuilder->codeAppendf("float DaCub = DaSqd * %s.a;", dst); fsBuilder->codeAppendf("half DaCub = DaSqd * %s.a;", 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 // (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
fsBuilder->codeAppendf("%s.%c =" fsBuilder->codeAppendf("%s.%c ="
"(DaSqd*(%s.%c - %s.%c * (3.0*%s.a - 6.0*%s.%c - 1.0)) +" "(DaSqd*(%s.%c - %s.%c * (3.0*%s.a - 6.0*%s.%c - 1.0)) +"
@ -144,10 +144,10 @@ static void add_lum_function(GrGLSLFragmentBuilder* fsBuilder, SkString* setLumF
// Emit a helper that gets the luminance of a color. // Emit a helper that gets the luminance of a color.
SkString getFunction; SkString getFunction;
GrShaderVar getLumArgs[] = { GrShaderVar getLumArgs[] = {
GrShaderVar("color", kVec3f_GrSLType), GrShaderVar("color", kHalf3_GrSLType),
}; };
SkString getLumBody("return dot(float3(0.3, 0.59, 0.11), color);"); SkString getLumBody("return dot(highfloat3(0.3, 0.59, 0.11), color);");
fsBuilder->emitFunction(kFloat_GrSLType, fsBuilder->emitFunction(kHalf_GrSLType,
"luminance", "luminance",
SK_ARRAY_COUNT(getLumArgs), getLumArgs, SK_ARRAY_COUNT(getLumArgs), getLumArgs,
getLumBody.c_str(), getLumBody.c_str(),
@ -155,27 +155,27 @@ static void add_lum_function(GrGLSLFragmentBuilder* fsBuilder, SkString* setLumF
// Emit the set luminance function. // Emit the set luminance function.
GrShaderVar setLumArgs[] = { GrShaderVar setLumArgs[] = {
GrShaderVar("hueSat", kVec3f_GrSLType), GrShaderVar("hueSat", kHalf3_GrSLType),
GrShaderVar("alpha", kFloat_GrSLType), GrShaderVar("alpha", kHalf_GrSLType),
GrShaderVar("lumColor", kVec3f_GrSLType), GrShaderVar("lumColor", kHalf3_GrSLType),
}; };
SkString setLumBody; SkString setLumBody;
setLumBody.printf("float diff = %s(lumColor - hueSat);", getFunction.c_str()); setLumBody.printf("half diff = %s(lumColor - hueSat);", getFunction.c_str());
setLumBody.append("float3 outColor = hueSat + diff;"); setLumBody.append("half3 outColor = hueSat + diff;");
setLumBody.appendf("float outLum = %s(outColor);", getFunction.c_str()); setLumBody.appendf("half outLum = %s(outColor);", getFunction.c_str());
setLumBody.append("float minComp = min(min(outColor.r, outColor.g), outColor.b);" setLumBody.append("half minComp = min(min(outColor.r, outColor.g), outColor.b);"
"float maxComp = max(max(outColor.r, outColor.g), outColor.b);" "half maxComp = max(max(outColor.r, outColor.g), outColor.b);"
"if (minComp < 0.0 && outLum != minComp) {" "if (minComp < 0.0 && outLum != minComp) {"
"outColor = outLum + ((outColor - float3(outLum, outLum, outLum)) * outLum) /" "outColor = outLum + ((outColor - half3(outLum, outLum, outLum)) * outLum) /"
"(outLum - minComp);" "(outLum - minComp);"
"}" "}"
"if (maxComp > alpha && maxComp != outLum) {" "if (maxComp > alpha && maxComp != outLum) {"
"outColor = outLum +" "outColor = outLum +"
"((outColor - float3(outLum, outLum, outLum)) * (alpha - outLum)) /" "((outColor - half3(outLum, outLum, outLum)) * (alpha - outLum)) /"
"(maxComp - outLum);" "(maxComp - outLum);"
"}" "}"
"return outColor;"); "return outColor;");
fsBuilder->emitFunction(kVec3f_GrSLType, fsBuilder->emitFunction(kHalf3_GrSLType,
"set_luminance", "set_luminance",
SK_ARRAY_COUNT(setLumArgs), setLumArgs, SK_ARRAY_COUNT(setLumArgs), setLumArgs,
setLumBody.c_str(), setLumBody.c_str(),
@ -188,11 +188,11 @@ static void add_lum_function(GrGLSLFragmentBuilder* fsBuilder, SkString* setLumF
static void add_sat_function(GrGLSLFragmentBuilder* fsBuilder, SkString* setSatFunction) { static void add_sat_function(GrGLSLFragmentBuilder* fsBuilder, SkString* setSatFunction) {
// Emit a helper that gets the saturation of a color // Emit a helper that gets the saturation of a color
SkString getFunction; SkString getFunction;
GrShaderVar getSatArgs[] = { GrShaderVar("color", kVec3f_GrSLType) }; GrShaderVar getSatArgs[] = { GrShaderVar("color", kHalf3_GrSLType) };
SkString getSatBody; SkString getSatBody;
getSatBody.printf("return max(max(color.r, color.g), color.b) - " getSatBody.printf("return max(max(color.r, color.g), color.b) - "
"min(min(color.r, color.g), color.b);"); "min(min(color.r, color.g), color.b);");
fsBuilder->emitFunction(kFloat_GrSLType, fsBuilder->emitFunction(kHalf_GrSLType,
"saturation", "saturation",
SK_ARRAY_COUNT(getSatArgs), getSatArgs, SK_ARRAY_COUNT(getSatArgs), getSatArgs,
getSatBody.c_str(), getSatBody.c_str(),
@ -204,33 +204,33 @@ static void add_sat_function(GrGLSLFragmentBuilder* fsBuilder, SkString* setSatF
// adjusted min, mid, and max inputs, respectively. // adjusted min, mid, and max inputs, respectively.
SkString helperFunction; SkString helperFunction;
GrShaderVar helperArgs[] = { GrShaderVar helperArgs[] = {
GrShaderVar("minComp", kFloat_GrSLType), GrShaderVar("minComp", kHalf_GrSLType),
GrShaderVar("midComp", kFloat_GrSLType), GrShaderVar("midComp", kHalf_GrSLType),
GrShaderVar("maxComp", kFloat_GrSLType), GrShaderVar("maxComp", kHalf_GrSLType),
GrShaderVar("sat", kFloat_GrSLType), GrShaderVar("sat", kHalf_GrSLType),
}; };
static const char kHelperBody[] = "if (minComp < maxComp) {" static const char kHelperBody[] = "if (minComp < maxComp) {"
"float3 result;" "half3 result;"
"result.r = 0.0;" "result.r = 0.0;"
"result.g = sat * (midComp - minComp) / (maxComp - minComp);" "result.g = sat * (midComp - minComp) / (maxComp - minComp);"
"result.b = sat;" "result.b = sat;"
"return result;" "return result;"
"} else {" "} else {"
"return float3(0, 0, 0);" "return half3(0, 0, 0);"
"}"; "}";
fsBuilder->emitFunction(kVec3f_GrSLType, fsBuilder->emitFunction(kHalf3_GrSLType,
"set_saturation_helper", "set_saturation_helper",
SK_ARRAY_COUNT(helperArgs), helperArgs, SK_ARRAY_COUNT(helperArgs), helperArgs,
kHelperBody, kHelperBody,
&helperFunction); &helperFunction);
GrShaderVar setSatArgs[] = { GrShaderVar setSatArgs[] = {
GrShaderVar("hueLumColor", kVec3f_GrSLType), GrShaderVar("hueLumColor", kHalf3_GrSLType),
GrShaderVar("satColor", kVec3f_GrSLType), GrShaderVar("satColor", kHalf3_GrSLType),
}; };
const char* helpFunc = helperFunction.c_str(); const char* helpFunc = helperFunction.c_str();
SkString setSatBody; SkString setSatBody;
setSatBody.appendf("float sat = %s(satColor);" setSatBody.appendf("half sat = %s(satColor);"
"if (hueLumColor.r <= hueLumColor.g) {" "if (hueLumColor.r <= hueLumColor.g) {"
"if (hueLumColor.g <= hueLumColor.b) {" "if (hueLumColor.g <= hueLumColor.b) {"
"hueLumColor.rgb = %s(hueLumColor.r, hueLumColor.g, hueLumColor.b, sat);" "hueLumColor.rgb = %s(hueLumColor.r, hueLumColor.g, hueLumColor.b, sat);"
@ -249,7 +249,7 @@ static void add_sat_function(GrGLSLFragmentBuilder* fsBuilder, SkString* setSatF
"return hueLumColor;", "return hueLumColor;",
getFunction.c_str(), helpFunc, helpFunc, helpFunc, helpFunc, getFunction.c_str(), helpFunc, helpFunc, helpFunc, helpFunc,
helpFunc, helpFunc); helpFunc, helpFunc);
fsBuilder->emitFunction(kVec3f_GrSLType, fsBuilder->emitFunction(kHalf3_GrSLType,
"set_saturation", "set_saturation",
SK_ARRAY_COUNT(setSatArgs), setSatArgs, SK_ARRAY_COUNT(setSatArgs), setSatArgs,
setSatBody.c_str(), setSatBody.c_str(),
@ -330,7 +330,7 @@ static void emit_advanced_xfermode_code(GrGLSLFragmentBuilder* fsBuilder, const
SkString setSat, setLum; SkString setSat, setLum;
add_sat_function(fsBuilder, &setSat); add_sat_function(fsBuilder, &setSat);
add_lum_function(fsBuilder, &setLum); add_lum_function(fsBuilder, &setLum);
fsBuilder->codeAppendf("float4 dstSrcAlpha = %s * %s.a;", fsBuilder->codeAppendf("half4 dstSrcAlpha = %s * %s.a;",
dstColor, srcColor); dstColor, srcColor);
fsBuilder->codeAppendf("%s.rgb = %s(%s(%s.rgb * %s.a, dstSrcAlpha.rgb)," fsBuilder->codeAppendf("%s.rgb = %s(%s(%s.rgb * %s.a, dstSrcAlpha.rgb),"
"dstSrcAlpha.a, dstSrcAlpha.rgb);", "dstSrcAlpha.a, dstSrcAlpha.rgb);",
@ -345,7 +345,7 @@ static void emit_advanced_xfermode_code(GrGLSLFragmentBuilder* fsBuilder, const
SkString setSat, setLum; SkString setSat, setLum;
add_sat_function(fsBuilder, &setSat); add_sat_function(fsBuilder, &setSat);
add_lum_function(fsBuilder, &setLum); add_lum_function(fsBuilder, &setLum);
fsBuilder->codeAppendf("float4 dstSrcAlpha = %s * %s.a;", fsBuilder->codeAppendf("half4 dstSrcAlpha = %s * %s.a;",
dstColor, srcColor); dstColor, srcColor);
fsBuilder->codeAppendf("%s.rgb = %s(%s(dstSrcAlpha.rgb, %s.rgb * %s.a)," fsBuilder->codeAppendf("%s.rgb = %s(%s(dstSrcAlpha.rgb, %s.rgb * %s.a),"
"dstSrcAlpha.a, dstSrcAlpha.rgb);", "dstSrcAlpha.a, dstSrcAlpha.rgb);",
@ -359,7 +359,7 @@ static void emit_advanced_xfermode_code(GrGLSLFragmentBuilder* fsBuilder, const
// SetLum(S * Da, Sa* Da, D * Sa) + (1 - Sa) * D + (1 - Da) * S // SetLum(S * Da, Sa* Da, D * Sa) + (1 - Sa) * D + (1 - Da) * S
SkString setLum; SkString setLum;
add_lum_function(fsBuilder, &setLum); add_lum_function(fsBuilder, &setLum);
fsBuilder->codeAppendf("float4 srcDstAlpha = %s * %s.a;", fsBuilder->codeAppendf("half4 srcDstAlpha = %s * %s.a;",
srcColor, dstColor); srcColor, dstColor);
fsBuilder->codeAppendf("%s.rgb = %s(srcDstAlpha.rgb, srcDstAlpha.a, %s.rgb * %s.a);", fsBuilder->codeAppendf("%s.rgb = %s(srcDstAlpha.rgb, srcDstAlpha.a, %s.rgb * %s.a);",
outputColor, setLum.c_str(), dstColor, srcColor); outputColor, setLum.c_str(), dstColor, srcColor);
@ -371,7 +371,7 @@ static void emit_advanced_xfermode_code(GrGLSLFragmentBuilder* fsBuilder, const
// SetLum(D * Sa, Sa* Da, S * Da) + (1 - Sa) * D + (1 - Da) * S // SetLum(D * Sa, Sa* Da, S * Da) + (1 - Sa) * D + (1 - Da) * S
SkString setLum; SkString setLum;
add_lum_function(fsBuilder, &setLum); add_lum_function(fsBuilder, &setLum);
fsBuilder->codeAppendf("float4 srcDstAlpha = %s * %s.a;", fsBuilder->codeAppendf("half4 srcDstAlpha = %s * %s.a;",
srcColor, dstColor); srcColor, dstColor);
fsBuilder->codeAppendf("%s.rgb = %s(%s.rgb * %s.a, srcDstAlpha.a, srcDstAlpha.rgb);", fsBuilder->codeAppendf("%s.rgb = %s(%s.rgb * %s.a, srcDstAlpha.a, srcDstAlpha.rgb);",
outputColor, setLum.c_str(), dstColor, srcColor); outputColor, setLum.c_str(), dstColor, srcColor);
@ -406,13 +406,13 @@ static bool append_porterduff_term(GrGLSLFragmentBuilder* fsBuilder, SkBlendMode
fsBuilder->codeAppendf(" * %s", srcColorName); fsBuilder->codeAppendf(" * %s", srcColorName);
break; break;
case SkBlendModeCoeff::kISC: case SkBlendModeCoeff::kISC:
fsBuilder->codeAppendf(" * (float4(1.0) - %s)", srcColorName); fsBuilder->codeAppendf(" * (half4(1.0) - %s)", srcColorName);
break; break;
case SkBlendModeCoeff::kDC: case SkBlendModeCoeff::kDC:
fsBuilder->codeAppendf(" * %s", dstColorName); fsBuilder->codeAppendf(" * %s", dstColorName);
break; break;
case SkBlendModeCoeff::kIDC: case SkBlendModeCoeff::kIDC:
fsBuilder->codeAppendf(" * (float4(1.0) - %s)", dstColorName); fsBuilder->codeAppendf(" * (half4(1.0) - %s)", dstColorName);
break; break;
case SkBlendModeCoeff::kSA: case SkBlendModeCoeff::kSA:
fsBuilder->codeAppendf(" * %s.a", srcColorName); fsBuilder->codeAppendf(" * %s.a", srcColorName);
@ -453,7 +453,7 @@ void GrGLSLBlend::AppendMode(GrGLSLFragmentBuilder* fsBuilder, const char* srcCo
false); false);
// append dst blend // append dst blend
if(!append_porterduff_term(fsBuilder, dstCoeff, dstColor, srcColor, dstColor, didAppend)) { if(!append_porterduff_term(fsBuilder, dstCoeff, dstColor, srcColor, dstColor, didAppend)) {
fsBuilder->codeAppend("float4(0, 0, 0, 0)"); fsBuilder->codeAppend("half4(0, 0, 0, 0)");
} }
if (clamp) { if (clamp) {
fsBuilder->codeAppend(", 0, 1);"); fsBuilder->codeAppend(", 0, 1);");
@ -505,7 +505,7 @@ void GrGLSLBlend::AppendRegionOp(GrGLSLFragmentBuilder* fsBuilder, const char* s
false); false);
// append dst blend // append dst blend
if(!append_porterduff_term(fsBuilder, dstCoeff, dstColor, srcColor, dstColor, didAppend)) { if(!append_porterduff_term(fsBuilder, dstCoeff, dstColor, srcColor, dstColor, didAppend)) {
fsBuilder->codeAppend("float4(0, 0, 0, 0)"); fsBuilder->codeAppend("half4(0, 0, 0, 0)");
} }
fsBuilder->codeAppend(";"); fsBuilder->codeAppend(";");
} }

View File

@ -24,8 +24,8 @@ public:
uint32_t visibility = kFragment_GrShaderFlag) { uint32_t visibility = kFragment_GrShaderFlag) {
SkASSERT(uniformHandler); SkASSERT(uniformHandler);
if (colorSpaceXform) { if (colorSpaceXform) {
fGamutXformVar = uniformHandler->addUniform(visibility, kMat44f_GrSLType, fGamutXformVar = uniformHandler->addUniform(visibility, kHalf4x4_GrSLType,
kDefault_GrSLPrecision, "ColorXform"); "ColorXform");
fValid = true; fValid = true;
} }
} }

View File

@ -29,7 +29,7 @@ void GrGLSLFragmentProcessor::emitChild(int childIndex, const char* inputColor,
SkASSERT(outputColor); SkASSERT(outputColor);
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
outputColor->append(fragBuilder->getMangleString()); outputColor->append(fragBuilder->getMangleString());
fragBuilder->codeAppendf("float4 %s;", outputColor->c_str()); fragBuilder->codeAppendf("half4 %s;", outputColor->c_str());
this->internalEmitChild(childIndex, inputColor, outputColor->c_str(), args); this->internalEmitChild(childIndex, inputColor, outputColor->c_str(), args);
} }

View File

@ -86,9 +86,9 @@ public:
@param fp The processor that generated this program stage. @param fp The processor that generated this program stage.
@param key The key that was computed by GenKey() from the generating @param key The key that was computed by GenKey() from the generating
GrProcessor. GrProcessor.
@param outputColor A predefined float4 in the FS in which the stage should place its @param outputColor A predefined half4 in the FS in which the stage should place its
output color (or coverage). output color (or coverage).
@param inputColor A float4 that holds the input color to the stage in the FS. This may @param inputColor A half4 that holds the input color to the stage in the FS. This may
be nullptr in which case the implied input is solid white (all be nullptr in which case the implied input is solid white (all
ones). TODO: Better system for communicating optimization info ones). TODO: Better system for communicating optimization info
(e.g. input color is solid white, trans black, known to be opaque, (e.g. input color is solid white, trans black, known to be opaque,
@ -152,7 +152,7 @@ public:
} }
inline void emitChild(int childIndex, SkString* outputColor, EmitArgs& parentArgs) { inline void emitChild(int childIndex, SkString* outputColor, EmitArgs& parentArgs) {
this->emitChild(childIndex, "float4(1.0)", outputColor, parentArgs); this->emitChild(childIndex, "half4(1.0)", outputColor, parentArgs);
} }
/** Will emit the code of a child proc in its own scope. Pass in the parent's EmitArgs and /** Will emit the code of a child proc in its own scope. Pass in the parent's EmitArgs and
@ -167,7 +167,7 @@ public:
EmitArgs& parentArgs); EmitArgs& parentArgs);
inline void emitChild(int childIndex, EmitArgs& args) { inline void emitChild(int childIndex, EmitArgs& args) {
this->emitChild(childIndex, "float4(1.0)", args); this->emitChild(childIndex, "half4(1.0)", args);
} }
/** Variation that uses the parent's output color variable to hold the child's output.*/ /** Variation that uses the parent's output color variable to hold the child's output.*/

View File

@ -85,8 +85,7 @@ GrGLSLFragmentShaderBuilder::GrGLSLFragmentShaderBuilder(GrGLSLProgramBuilder* p
, fCustomColorOutputIndex(-1) , fCustomColorOutputIndex(-1)
, fHasSecondaryOutput(false) , fHasSecondaryOutput(false)
, fUsedSampleOffsetArrays(0) , fUsedSampleOffsetArrays(0)
, fHasInitializedSampleMask(false) , fHasInitializedSampleMask(false) {
, fDefaultPrecision(kMedium_GrSLPrecision) {
fSubstageIndices.push_back(0); fSubstageIndices.push_back(0);
#ifdef SK_DEBUG #ifdef SK_DEBUG
fUsedProcessorFeatures = GrProcessor::kNone_RequiredFeatures; fUsedProcessorFeatures = GrProcessor::kNone_RequiredFeatures;
@ -112,14 +111,14 @@ bool GrGLSLFragmentShaderBuilder::enableFeature(GLSLFeature feature) {
} }
SkString GrGLSLFragmentShaderBuilder::ensureCoords2D(const GrShaderVar& coords) { SkString GrGLSLFragmentShaderBuilder::ensureCoords2D(const GrShaderVar& coords) {
if (kVec3f_GrSLType != coords.getType()) { if (kHighFloat3_GrSLType != coords.getType() && kHalf3_GrSLType != coords.getType()) {
SkASSERT(kVec2f_GrSLType == coords.getType()); SkASSERT(kHighFloat2_GrSLType == coords.getType() || kHalf2_GrSLType == coords.getType());
return coords.getName(); return coords.getName();
} }
SkString coords2D; SkString coords2D;
coords2D.printf("%s_ensure2D", coords.c_str()); coords2D.printf("%s_ensure2D", coords.c_str());
this->codeAppendf("\tfloat2 %s = %s.xy / %s.z;", coords2D.c_str(), coords.c_str(), this->codeAppendf("\thighfloat2 %s = %s.xy / %s.z;", coords2D.c_str(), coords.c_str(),
coords.c_str()); coords.c_str());
return coords2D; return coords2D;
} }
@ -175,10 +174,6 @@ void GrGLSLFragmentShaderBuilder::overrideSampleCoverage(const char* mask) {
fHasInitializedSampleMask = true; fHasInitializedSampleMask = true;
} }
void GrGLSLFragmentShaderBuilder::elevateDefaultPrecision(GrSLPrecision precision) {
fDefaultPrecision = SkTMax(fDefaultPrecision, precision);
}
const char* GrGLSLFragmentShaderBuilder::dstColor() { const char* GrGLSLFragmentShaderBuilder::dstColor() {
SkDEBUGCODE(fHasReadDstColor = true;) SkDEBUGCODE(fHasReadDstColor = true;)
@ -199,7 +194,7 @@ const char* GrGLSLFragmentShaderBuilder::dstColor() {
fOutputs[fCustomColorOutputIndex].setTypeModifier(GrShaderVar::kInOut_TypeModifier); fOutputs[fCustomColorOutputIndex].setTypeModifier(GrShaderVar::kInOut_TypeModifier);
fbFetchColorName = DeclaredColorOutputName(); fbFetchColorName = DeclaredColorOutputName();
// Set the dstColor to an intermediate variable so we don't override it with the output // Set the dstColor to an intermediate variable so we don't override it with the output
this->codeAppendf("float4 %s = %s;", kDstColorName, fbFetchColorName); this->codeAppendf("half4 %s = %s;", kDstColorName, fbFetchColorName);
} else { } else {
return fbFetchColorName; return fbFetchColorName;
} }
@ -228,7 +223,7 @@ void GrGLSLFragmentShaderBuilder::enableCustomOutput() {
if (!fHasCustomColorOutput) { if (!fHasCustomColorOutput) {
fHasCustomColorOutput = true; fHasCustomColorOutput = true;
fCustomColorOutputIndex = fOutputs.count(); fCustomColorOutputIndex = fOutputs.count();
fOutputs.push_back().set(kVec4f_GrSLType, DeclaredColorOutputName(), fOutputs.push_back().set(kHalf4_GrSLType, DeclaredColorOutputName(),
GrShaderVar::kOut_TypeModifier); GrShaderVar::kOut_TypeModifier);
fProgramBuilder->finalizeFragmentOutputColor(fOutputs.back()); fProgramBuilder->finalizeFragmentOutputColor(fOutputs.back());
} }
@ -247,7 +242,7 @@ void GrGLSLFragmentShaderBuilder::enableSecondaryOutput() {
// output. The condition also co-incides with the condition in whici GLES SL 2.0 // output. The condition also co-incides with the condition in whici GLES SL 2.0
// requires the built-in gl_SecondaryFragColorEXT, where as 3.0 requires a custom output. // requires the built-in gl_SecondaryFragColorEXT, where as 3.0 requires a custom output.
if (caps.mustDeclareFragmentShaderOutput()) { if (caps.mustDeclareFragmentShaderOutput()) {
fOutputs.push_back().set(kVec4f_GrSLType, DeclaredSecondaryColorOutputName(), fOutputs.push_back().set(kHalf4_GrSLType, DeclaredSecondaryColorOutputName(),
GrShaderVar::kOut_TypeModifier); GrShaderVar::kOut_TypeModifier);
fProgramBuilder->finalizeFragmentSecondaryColor(fOutputs.back()); fProgramBuilder->finalizeFragmentSecondaryColor(fOutputs.back());
} }
@ -280,9 +275,6 @@ GrSurfaceOrigin GrGLSLFragmentShaderBuilder::getSurfaceOrigin() const {
void GrGLSLFragmentShaderBuilder::onFinalize() { void GrGLSLFragmentShaderBuilder::onFinalize() {
fProgramBuilder->varyingHandler()->getFragDecls(&this->inputs(), &this->outputs()); fProgramBuilder->varyingHandler()->getFragDecls(&this->inputs(), &this->outputs());
GrGLSLAppendDefaultFloatPrecisionDeclaration(fDefaultPrecision,
*fProgramBuilder->shaderCaps(),
&this->precisionQualifier());
if (fUsedSampleOffsetArrays & (1 << kSkiaDevice_Coordinates)) { if (fUsedSampleOffsetArrays & (1 << kSkiaDevice_Coordinates)) {
this->defineSampleOffsetArray(sample_offset_array_name(kSkiaDevice_Coordinates), this->defineSampleOffsetArray(sample_offset_array_name(kSkiaDevice_Coordinates),
SkMatrix::MakeTrans(-0.5f, -0.5f)); SkMatrix::MakeTrans(-0.5f, -0.5f));
@ -305,9 +297,9 @@ void GrGLSLFragmentShaderBuilder::defineSampleOffsetArray(const char* name, cons
SkSTArray<16, SkPoint, true> offsets; SkSTArray<16, SkPoint, true> offsets;
offsets.push_back_n(specs.fEffectiveSampleCnt); offsets.push_back_n(specs.fEffectiveSampleCnt);
m.mapPoints(offsets.begin(), specs.fSampleLocations, specs.fEffectiveSampleCnt); m.mapPoints(offsets.begin(), specs.fSampleLocations, specs.fEffectiveSampleCnt);
this->definitions().appendf("const highp float2 %s[] = float2[](", name); this->definitions().appendf("const highfloat2 %s[] = highfloat2[](", name);
for (int i = 0; i < specs.fEffectiveSampleCnt; ++i) { for (int i = 0; i < specs.fEffectiveSampleCnt; ++i) {
this->definitions().appendf("float2(%f, %f)", offsets[i].x(), offsets[i].y()); this->definitions().appendf("highfloat2(%f, %f)", offsets[i].x(), offsets[i].y());
this->definitions().append(i + 1 != specs.fEffectiveSampleCnt ? ", " : ");\n"); this->definitions().append(i + 1 != specs.fEffectiveSampleCnt ? ", " : ");\n");
} }
} }

View File

@ -40,7 +40,7 @@ public:
/** /**
* This returns a variable name to access the 2D, perspective correct version of the coords in * This returns a variable name to access the 2D, perspective correct version of the coords in
* the fragment shader. The passed in coordinates must either be of type kVec2f or kVec3f. If * the fragment shader. The passed in coordinates must either be of type kHalf2 or kHalf3. If
* the coordinates are 3-dimensional, it a perspective divide into is emitted into the * the coordinates are 3-dimensional, it a perspective divide into is emitted into the
* fragment shader (xy / z) to convert them to 2D. * fragment shader (xy / z) to convert them to 2D.
*/ */
@ -89,13 +89,6 @@ public:
*/ */
virtual void maskSampleCoverage(const char* mask, bool invert = false) = 0; virtual void maskSampleCoverage(const char* mask, bool invert = false) = 0;
/**
* Overrides the default precision for the entire fragment program. Processors that require
* high precision input (eg from incoming texture samples) may use this. For calculations that
* are limited to a single processor's code, it is better to annotate individual declarations.
*/
virtual void elevateDefaultPrecision(GrSLPrecision) = 0;
/** /**
* Fragment procs with child procs should call these functions before/after calling emitCode * Fragment procs with child procs should call these functions before/after calling emitCode
* on a child proc. * on a child proc.
@ -104,6 +97,8 @@ public:
virtual void onAfterChildProcEmitCode() = 0; virtual void onAfterChildProcEmitCode() = 0;
virtual const SkString& getMangleString() const = 0; virtual const SkString& getMangleString() const = 0;
virtual void forceHighPrecision() = 0;
}; };
/* /*
@ -169,10 +164,10 @@ public:
void appendOffsetToSample(const char* sampleIdx, Coordinates) override; void appendOffsetToSample(const char* sampleIdx, Coordinates) override;
void maskSampleCoverage(const char* mask, bool invert = false) override; void maskSampleCoverage(const char* mask, bool invert = false) override;
void overrideSampleCoverage(const char* mask) override; void overrideSampleCoverage(const char* mask) override;
void elevateDefaultPrecision(GrSLPrecision) override;
const SkString& getMangleString() const override { return fMangleString; } const SkString& getMangleString() const override { return fMangleString; }
void onBeforeChildProcEmitCode() override; void onBeforeChildProcEmitCode() override;
void onAfterChildProcEmitCode() override; void onAfterChildProcEmitCode() override;
void forceHighPrecision() override { fForceHighPrecision = true; }
// GrGLSLXPFragmentBuilder interface. // GrGLSLXPFragmentBuilder interface.
bool hasCustomColorOutput() const override { return fHasCustomColorOutput; } bool hasCustomColorOutput() const override { return fHasCustomColorOutput; }
@ -234,7 +229,7 @@ private:
bool fHasSecondaryOutput; bool fHasSecondaryOutput;
uint8_t fUsedSampleOffsetArrays; uint8_t fUsedSampleOffsetArrays;
bool fHasInitializedSampleMask; bool fHasInitializedSampleMask;
GrSLPrecision fDefaultPrecision; bool fForceHighPrecision;
#ifdef SK_DEBUG #ifdef SK_DEBUG
// some state to verify shaders and effects are consistent, this is reset between effects by // some state to verify shaders and effects are consistent, this is reset between effects by

View File

@ -18,7 +18,8 @@ void GrGLSLGeometryProcessor::emitCode(EmitArgs& args) {
GrGPArgs gpArgs; GrGPArgs gpArgs;
this->onEmitCode(args, &gpArgs); this->onEmitCode(args, &gpArgs);
vBuilder->transformToNormalizedDeviceSpace(gpArgs.fPositionVar, args.fRTAdjustName); vBuilder->transformToNormalizedDeviceSpace(gpArgs.fPositionVar, args.fRTAdjustName);
if (kVec2f_GrSLType == gpArgs.fPositionVar.getType()) { if (kHighFloat2_GrSLType == gpArgs.fPositionVar.getType() ||
kHalf2_GrSLType == gpArgs.fPositionVar.getType()) {
args.fVaryingHandler->setNoPerspective(); args.fVaryingHandler->setNoPerspective();
} }
} }
@ -39,32 +40,28 @@ void GrGLSLGeometryProcessor::emitTransforms(GrGLSLVertexBuilder* vb,
uint32_t type = coordTransform->getMatrix().getType(); uint32_t type = coordTransform->getMatrix().getType();
type |= localMatrix.getType(); type |= localMatrix.getType();
varyingType = SkToBool(SkMatrix::kPerspective_Mask & type) ? kVec3f_GrSLType : varyingType = SkToBool(SkMatrix::kPerspective_Mask & type) ? kHighFloat3_GrSLType :
kVec2f_GrSLType; kHighFloat2_GrSLType;
// Coord transforms are always handled at high precision
const GrSLPrecision precision = kHigh_GrSLPrecision;
const char* uniName; const char* uniName;
fInstalledTransforms.push_back().fHandle = uniformHandler->addUniform(kVertex_GrShaderFlag, fInstalledTransforms.push_back().fHandle = uniformHandler->addUniform(kVertex_GrShaderFlag,
kMat33f_GrSLType, kHighFloat3x3_GrSLType,
precision,
strUniName.c_str(), strUniName.c_str(),
&uniName).toIndex(); &uniName).toIndex();
SkString strVaryingName; SkString strVaryingName;
strVaryingName.printf("TransformedCoords_%d", i); strVaryingName.printf("TransformedCoords_%d", i);
GrGLSLVertToFrag v(varyingType); GrGLSLVertToFrag v(varyingType);
varyingHandler->addVarying(strVaryingName.c_str(), &v, precision); varyingHandler->addVarying(strVaryingName.c_str(), &v, kHigh_GrSLPrecision);
SkASSERT(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyingType); SkASSERT(kHighFloat2_GrSLType == varyingType || kHighFloat3_GrSLType == varyingType);
handler->specifyCoordsForCurrCoordTransform(SkString(v.fsIn()), varyingType); handler->specifyCoordsForCurrCoordTransform(SkString(v.fsIn()), varyingType);
if (kVec2f_GrSLType == varyingType) { if (kHighFloat2_GrSLType == varyingType) {
vb->codeAppendf("%s = (%s * float3(%s, 1)).xy;", v.vsOut(), uniName, localCoords); vb->codeAppendf("%s = (%s * highfloat3(%s, 1)).xy;", v.vsOut(), uniName, localCoords);
} else { } else {
vb->codeAppendf("%s = %s * float3(%s, 1);", v.vsOut(), uniName, localCoords); vb->codeAppendf("%s = %s * highfloat3(%s, 1);", v.vsOut(), uniName, localCoords);
} }
++i; ++i;
} }
@ -88,8 +85,8 @@ void GrGLSLGeometryProcessor::setTransformDataHelper(const SkMatrix& localMatrix
void GrGLSLGeometryProcessor::writeOutputPosition(GrGLSLVertexBuilder* vertBuilder, void GrGLSLGeometryProcessor::writeOutputPosition(GrGLSLVertexBuilder* vertBuilder,
GrGPArgs* gpArgs, GrGPArgs* gpArgs,
const char* posName) { const char* posName) {
gpArgs->fPositionVar.set(kVec2f_GrSLType, "pos2"); gpArgs->fPositionVar.set(kHighFloat2_GrSLType, "pos2");
vertBuilder->codeAppendf("float2 %s = %s;", gpArgs->fPositionVar.c_str(), posName); vertBuilder->codeAppendf("highfloat2 %s = %s;", gpArgs->fPositionVar.c_str(), posName);
} }
void GrGLSLGeometryProcessor::writeOutputPosition(GrGLSLVertexBuilder* vertBuilder, void GrGLSLGeometryProcessor::writeOutputPosition(GrGLSLVertexBuilder* vertBuilder,
@ -99,21 +96,21 @@ void GrGLSLGeometryProcessor::writeOutputPosition(GrGLSLVertexBuilder* vertBuild
const SkMatrix& mat, const SkMatrix& mat,
UniformHandle* viewMatrixUniform) { UniformHandle* viewMatrixUniform) {
if (mat.isIdentity()) { if (mat.isIdentity()) {
gpArgs->fPositionVar.set(kVec2f_GrSLType, "pos2"); gpArgs->fPositionVar.set(kHighFloat2_GrSLType, "pos2");
vertBuilder->codeAppendf("float2 %s = %s;", gpArgs->fPositionVar.c_str(), posName); vertBuilder->codeAppendf("highfloat2 %s = %s;", gpArgs->fPositionVar.c_str(), posName);
} else { } else {
const char* viewMatrixName; const char* viewMatrixName;
*viewMatrixUniform = uniformHandler->addUniform(kVertex_GrShaderFlag, *viewMatrixUniform = uniformHandler->addUniform(kVertex_GrShaderFlag,
kMat33f_GrSLType, kHigh_GrSLPrecision, kHighFloat3x3_GrSLType,
"uViewM", "uViewM",
&viewMatrixName); &viewMatrixName);
if (!mat.hasPerspective()) { if (!mat.hasPerspective()) {
gpArgs->fPositionVar.set(kVec2f_GrSLType, "pos2"); gpArgs->fPositionVar.set(kHighFloat2_GrSLType, "pos2");
vertBuilder->codeAppendf("float2 %s = (%s * float3(%s, 1)).xy;", vertBuilder->codeAppendf("highfloat2 %s = (%s * highfloat3(%s, 1)).xy;",
gpArgs->fPositionVar.c_str(), viewMatrixName, posName); gpArgs->fPositionVar.c_str(), viewMatrixName, posName);
} else { } else {
gpArgs->fPositionVar.set(kVec3f_GrSLType, "pos3"); gpArgs->fPositionVar.set(kHighFloat3_GrSLType, "pos3");
vertBuilder->codeAppendf("float3 %s = %s * float3(%s, 1);", vertBuilder->codeAppendf("highfloat3 %s = %s * highfloat3(%s, 1);",
gpArgs->fPositionVar.c_str(), viewMatrixName, posName); gpArgs->fPositionVar.c_str(), viewMatrixName, posName);
} }
} }

View File

@ -43,13 +43,12 @@ void GrGLSLPrimitiveProcessor::setupUniformColor(GrGLSLPPFragmentBuilder* fragBu
SkASSERT(colorUniform); SkASSERT(colorUniform);
const char* stagedLocalVarName; const char* stagedLocalVarName;
*colorUniform = uniformHandler->addUniform(kFragment_GrShaderFlag, *colorUniform = uniformHandler->addUniform(kFragment_GrShaderFlag,
kVec4f_GrSLType, kHalf4_GrSLType,
kDefault_GrSLPrecision,
"Color", "Color",
&stagedLocalVarName); &stagedLocalVarName);
fragBuilder->codeAppendf("%s = %s;", outputName, stagedLocalVarName); fragBuilder->codeAppendf("%s = %s;", outputName, stagedLocalVarName);
if (fragBuilder->getProgramBuilder()->shaderCaps()->mustObfuscateUniformColor()) { if (fragBuilder->getProgramBuilder()->shaderCaps()->mustObfuscateUniformColor()) {
fragBuilder->codeAppendf("%s = max(%s, float4(0, 0, 0, 0));", outputName, outputName); fragBuilder->codeAppendf("%s = max(%s, half4(0, 0, 0, 0));", outputName, outputName);
} }
} }

View File

@ -82,8 +82,7 @@ void GrGLSLProgramBuilder::emitAndInstallPrimProc(const GrPrimitiveProcessor& pr
rtAdjustVisibility |= kGeometry_GrShaderFlag; rtAdjustVisibility |= kGeometry_GrShaderFlag;
} }
fUniformHandles.fRTAdjustmentUni = this->uniformHandler()->addUniform(rtAdjustVisibility, fUniformHandles.fRTAdjustmentUni = this->uniformHandler()->addUniform(rtAdjustVisibility,
kVec4f_GrSLType, kHighFloat4_GrSLType,
kHigh_GrSLPrecision,
"rtAdjustment"); "rtAdjustment");
const char* rtAdjustName = const char* rtAdjustName =
this->uniformHandler()->getUniformCStr(fUniformHandles.fRTAdjustmentUni); this->uniformHandler()->getUniformCStr(fUniformHandles.fRTAdjustmentUni);
@ -455,7 +454,7 @@ void GrGLSLProgramBuilder::nameExpression(SkString* output, const char* baseName
} else { } else {
this->nameVariable(&outName, '\0', baseName); this->nameVariable(&outName, '\0', baseName);
} }
fFS.codeAppendf("float4 %s;", outName.c_str()); fFS.codeAppendf("half4 %s;", outName.c_str());
*output = outName; *output = outName;
} }
@ -468,7 +467,7 @@ void GrGLSLProgramBuilder::addRTHeightUniform(const char* name) {
GrGLSLUniformHandler* uniformHandler = this->uniformHandler(); GrGLSLUniformHandler* uniformHandler = this->uniformHandler();
fUniformHandles.fRTHeightUni = fUniformHandles.fRTHeightUni =
uniformHandler->internalAddUniformArray(kFragment_GrShaderFlag, uniformHandler->internalAddUniformArray(kFragment_GrShaderFlag,
kFloat_GrSLType, kDefault_GrSLPrecision, kHalf_GrSLType, kDefault_GrSLPrecision,
name, false, 0, nullptr); name, false, 0, nullptr);
} }

View File

@ -122,16 +122,16 @@ void GrGLSLShaderBuilder::appendColorGamutXform(SkString* out,
// re-insert the original alpha. The supplied srcColor is likely to be of the form // re-insert the original alpha. The supplied srcColor is likely to be of the form
// "texture(...)", and we don't want to evaluate that twice, so wrap everything in a function. // "texture(...)", and we don't want to evaluate that twice, so wrap everything in a function.
static const GrShaderVar gColorGamutXformArgs[] = { static const GrShaderVar gColorGamutXformArgs[] = {
GrShaderVar("color", kVec4f_GrSLType), GrShaderVar("color", kHalf4_GrSLType),
GrShaderVar("xform", kMat44f_GrSLType), GrShaderVar("xform", kHalf4x4_GrSLType),
}; };
SkString functionBody; SkString functionBody;
// Gamut xform, clamp to destination gamut. We only support/have premultiplied textures, so we // Gamut xform, clamp to destination gamut. We only support/have premultiplied textures, so we
// always just clamp to alpha. // always just clamp to alpha.
functionBody.append("\tcolor.rgb = clamp((xform * float4(color.rgb, 1.0)).rgb, 0.0, color.a);\n"); functionBody.append("\tcolor.rgb = clamp((xform * half4(color.rgb, 1.0)).rgb, 0.0, color.a);\n");
functionBody.append("\treturn color;"); functionBody.append("\treturn color;");
SkString colorGamutXformFuncName; SkString colorGamutXformFuncName;
this->emitFunction(kVec4f_GrSLType, this->emitFunction(kHalf4_GrSLType,
"colorGamutXform", "colorGamutXform",
SK_ARRAY_COUNT(gColorGamutXformArgs), SK_ARRAY_COUNT(gColorGamutXformArgs),
gColorGamutXformArgs, gColorGamutXformArgs,

View File

@ -37,23 +37,23 @@ public:
void appendTextureLookup(SkString* out, void appendTextureLookup(SkString* out,
SamplerHandle, SamplerHandle,
const char* coordName, const char* coordName,
GrSLType coordType = kVec2f_GrSLType) const; GrSLType coordType = kHalf2_GrSLType) const;
/** Version of above that appends the result to the shader code instead.*/ /** Version of above that appends the result to the shader code instead.*/
void appendTextureLookup(SamplerHandle, void appendTextureLookup(SamplerHandle,
const char* coordName, const char* coordName,
GrSLType coordType = kVec2f_GrSLType, GrSLType coordType = kHalf2_GrSLType,
GrGLSLColorSpaceXformHelper* colorXformHelper = nullptr); GrGLSLColorSpaceXformHelper* colorXformHelper = nullptr);
/** Does the work of appendTextureLookup and modulates the result by modulation. The result is /** Does the work of appendTextureLookup and modulates the result by modulation. The result is
always a float4. modulation and the swizzle specified by SamplerHandle must both be always a half4. modulation and the swizzle specified by SamplerHandle must both be
float4 or float. If modulation is "" or nullptr it this function acts as though half4 or half. If modulation is "" or nullptr it this function acts as though
appendTextureLookup were called. */ appendTextureLookup were called. */
void appendTextureLookupAndModulate(const char* modulation, void appendTextureLookupAndModulate(const char* modulation,
SamplerHandle, SamplerHandle,
const char* coordName, const char* coordName,
GrSLType coordType = kVec2f_GrSLType, GrSLType coordType = kHalf2_GrSLType,
GrGLSLColorSpaceXformHelper* colorXformHelper = nullptr); GrGLSLColorSpaceXformHelper* colorXformHelper = nullptr);
/** Adds a helper function to facilitate color gamut transformation, and produces code that /** Adds a helper function to facilitate color gamut transformation, and produces code that

View File

@ -38,6 +38,13 @@ public:
return this->addUniformArray(visibility, type, precision, name, 0, outName); return this->addUniformArray(visibility, type, precision, name, 0, outName);
} }
UniformHandle addUniform(uint32_t visibility,
GrSLType type,
const char* name,
const char** outName = nullptr) {
return this->addUniform(visibility, type, kDefault_GrSLPrecision, name, outName);
}
UniformHandle addUniformArray(uint32_t visibility, UniformHandle addUniformArray(uint32_t visibility,
GrSLType type, GrSLType type,
GrSLPrecision precision, GrSLPrecision precision,
@ -49,6 +56,16 @@ public:
outName); outName);
} }
UniformHandle addUniformArray(uint32_t visibility,
GrSLType type,
const char* name,
int arrayCount,
const char** outName = nullptr) {
SkASSERT(!GrSLTypeIsCombinedSamplerType(type));
return this->internalAddUniformArray(visibility, type, kDefault_GrSLPrecision, name, true,
arrayCount, outName);
}
virtual const GrShaderVar& getUniformVariable(UniformHandle u) const = 0; virtual const GrShaderVar& getUniformVariable(UniformHandle u) const = 0;
/** /**

View File

@ -18,25 +18,25 @@ void GrGLSLVertexBuilder::transformToNormalizedDeviceSpace(const GrShaderVar& po
const char* rtAdjustName) { const char* rtAdjustName) {
// setup RT Uniform // setup RT Uniform
if (this->getProgramBuilder()->desc()->header().fSnapVerticesToPixelCenters) { if (this->getProgramBuilder()->desc()->header().fSnapVerticesToPixelCenters) {
if (kVec3f_GrSLType == posVar.getType()) { if (kHighFloat3_GrSLType == posVar.getType()) {
const char* p = posVar.c_str(); const char* p = posVar.c_str();
this->codeAppendf("{float2 _posTmp = float2(%s.x/%s.z, %s.y/%s.z);", p, p, p, p); this->codeAppendf("{highfloat2 _posTmp = highfloat2(%s.x/%s.z, %s.y/%s.z);", p, p, p, p);
} else { } else {
SkASSERT(kVec2f_GrSLType == posVar.getType()); SkASSERT(kHighFloat2_GrSLType == posVar.getType());
this->codeAppendf("{float2 _posTmp = %s;", posVar.c_str()); this->codeAppendf("{highfloat2 _posTmp = %s;", posVar.c_str());
} }
this->codeAppendf("_posTmp = floor(_posTmp) + float2(0.5, 0.5);" this->codeAppendf("_posTmp = floor(_posTmp) + half2(0.5, 0.5);"
"gl_Position = float4(_posTmp.x * %s.x + %s.y," "gl_Position = highfloat4(_posTmp.x * %s.x + %s.y,"
"_posTmp.y * %s.z + %s.w, 0, 1);}", "_posTmp.y * %s.z + %s.w, 0, 1);}",
rtAdjustName, rtAdjustName, rtAdjustName, rtAdjustName); rtAdjustName, rtAdjustName, rtAdjustName, rtAdjustName);
} else if (kVec3f_GrSLType == posVar.getType()) { } else if (kHighFloat3_GrSLType == posVar.getType()) {
this->codeAppendf("gl_Position = float4(dot(%s.xz, %s.xy), dot(%s.yz, %s.zw), 0, %s.z);", this->codeAppendf("gl_Position = highfloat4(dot(%s.xz, %s.xy), dot(%s.yz, %s.zw), 0, %s.z);",
posVar.c_str(), rtAdjustName, posVar.c_str(), rtAdjustName,
posVar.c_str(), rtAdjustName, posVar.c_str(), rtAdjustName,
posVar.c_str()); posVar.c_str());
} else { } else {
SkASSERT(kVec2f_GrSLType == posVar.getType()); SkASSERT(kHighFloat2_GrSLType == posVar.getType());
this->codeAppendf("gl_Position = float4(%s.x * %s.x + %s.y, %s.y * %s.z + %s.w, 0, 1);", this->codeAppendf("gl_Position = highfloat4(%s.x * %s.x + %s.y, %s.y * %s.z + %s.w, 0, 1);",
posVar.c_str(), rtAdjustName, rtAdjustName, posVar.c_str(), rtAdjustName, rtAdjustName,
posVar.c_str(), rtAdjustName, rtAdjustName); posVar.c_str(), rtAdjustName, rtAdjustName);
} }

View File

@ -52,7 +52,7 @@ void GrGLSLXferProcessor::emitCode(const EmitArgs& args) {
// The discard here also helps for batching text draws together which need to read from // The discard here also helps for batching text draws together which need to read from
// a dst copy for blends. Though this only helps the case where the outer bounding boxes // a dst copy for blends. Though this only helps the case where the outer bounding boxes
// of each letter overlap and not two actually parts of the text. // of each letter overlap and not two actually parts of the text.
fragBuilder->codeAppendf("if (all(lessThanEqual(%s.rgb, float3(0)))) {" fragBuilder->codeAppendf("if (all(lessThanEqual(%s.rgb, half3(0)))) {"
" discard;" " discard;"
"}", args.fInputCoverage); "}", args.fInputCoverage);
} }
@ -61,27 +61,25 @@ void GrGLSLXferProcessor::emitCode(const EmitArgs& args) {
const char* dstCoordScaleName; const char* dstCoordScaleName;
fDstTopLeftUni = uniformHandler->addUniform(kFragment_GrShaderFlag, fDstTopLeftUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
kVec2f_GrSLType, kHalf2_GrSLType,
kDefault_GrSLPrecision,
"DstTextureUpperLeft", "DstTextureUpperLeft",
&dstTopLeftName); &dstTopLeftName);
fDstScaleUni = uniformHandler->addUniform(kFragment_GrShaderFlag, fDstScaleUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
kVec2f_GrSLType, kHalf2_GrSLType,
kDefault_GrSLPrecision,
"DstTextureCoordScale", "DstTextureCoordScale",
&dstCoordScaleName); &dstCoordScaleName);
fragBuilder->codeAppend("// Read color from copy of the destination.\n"); fragBuilder->codeAppend("// Read color from copy of the destination.\n");
fragBuilder->codeAppendf("float2 _dstTexCoord = (sk_FragCoord.xy - %s) * %s;", fragBuilder->codeAppendf("half2 _dstTexCoord = (sk_FragCoord.xy - %s) * %s;",
dstTopLeftName, dstCoordScaleName); dstTopLeftName, dstCoordScaleName);
if (flipY) { if (flipY) {
fragBuilder->codeAppend("_dstTexCoord.y = 1.0 - _dstTexCoord.y;"); fragBuilder->codeAppend("_dstTexCoord.y = 1.0 - _dstTexCoord.y;");
} }
fragBuilder->codeAppendf("float4 %s = ", dstColor); fragBuilder->codeAppendf("half4 %s = ", dstColor);
fragBuilder->appendTextureLookup(args.fDstTextureSamplerHandle, "_dstTexCoord", fragBuilder->appendTextureLookup(args.fDstTextureSamplerHandle, "_dstTexCoord",
kVec2f_GrSLType); kHalf2_GrSLType);
fragBuilder->codeAppend(";"); fragBuilder->codeAppend(";");
} else { } else {
needsLocalOutColor = args.fShaderCaps->requiresLocalOutputColorForFBFetch(); needsLocalOutColor = args.fShaderCaps->requiresLocalOutputColorForFBFetch();
@ -91,7 +89,7 @@ void GrGLSLXferProcessor::emitCode(const EmitArgs& args) {
if (!needsLocalOutColor) { if (!needsLocalOutColor) {
outColor = args.fOutputPrimary; outColor = args.fOutputPrimary;
} else { } else {
fragBuilder->codeAppendf("float4 %s;", outColor); fragBuilder->codeAppendf("half4 %s;", outColor);
} }
this->emitBlendCodeForDstRead(fragBuilder, this->emitBlendCodeForDstRead(fragBuilder,
@ -139,18 +137,18 @@ void GrGLSLXferProcessor::DefaultCoverageModulation(GrGLSLXPFragmentBuilder* fra
fragBuilder->codeAppendf("%s *= %s;", outColor, srcCoverage); fragBuilder->codeAppendf("%s *= %s;", outColor, srcCoverage);
fragBuilder->codeAppendf("%s = %s;", outColorSecondary, srcCoverage); fragBuilder->codeAppendf("%s = %s;", outColorSecondary, srcCoverage);
} else { } else {
fragBuilder->codeAppendf("%s = float4(1.0);", outColorSecondary); fragBuilder->codeAppendf("%s = half4(1.0);", outColorSecondary);
} }
} else if (srcCoverage) { } else if (srcCoverage) {
if (proc.isLCD()) { if (proc.isLCD()) {
fragBuilder->codeAppendf("float lerpRed = mix(%s.a, %s.a, %s.r);", fragBuilder->codeAppendf("half lerpRed = mix(%s.a, %s.a, %s.r);",
dstColor, outColor, srcCoverage); dstColor, outColor, srcCoverage);
fragBuilder->codeAppendf("float lerpBlue = mix(%s.a, %s.a, %s.g);", fragBuilder->codeAppendf("half lerpBlue = mix(%s.a, %s.a, %s.g);",
dstColor, outColor, srcCoverage); dstColor, outColor, srcCoverage);
fragBuilder->codeAppendf("float lerpGreen = mix(%s.a, %s.a, %s.b);", fragBuilder->codeAppendf("half lerpGreen = mix(%s.a, %s.a, %s.b);",
dstColor, outColor, srcCoverage); dstColor, outColor, srcCoverage);
} }
fragBuilder->codeAppendf("%s = %s * %s + (float4(1.0) - %s) * %s;", fragBuilder->codeAppendf("%s = %s * %s + (half4(1.0) - %s) * %s;",
outColor, srcCoverage, outColor, srcCoverage, dstColor); outColor, srcCoverage, outColor, srcCoverage, dstColor);
if (proc.isLCD()) { if (proc.isLCD()) {
fragBuilder->codeAppendf("%s.a = max(max(lerpRed, lerpBlue), lerpGreen);", outColor); fragBuilder->codeAppendf("%s.a = max(max(lerpRed, lerpBlue), lerpGreen);", outColor);

View File

@ -105,32 +105,38 @@ public:
void initParams(const TexelBufferHandle paramsBuffer) { void initParams(const TexelBufferHandle paramsBuffer) {
fParamsBuffer = paramsBuffer; fParamsBuffer = paramsBuffer;
fVertexBuilder->codeAppendf("highp int paramsIdx = int(%s & 0x%x);", fVertexBuilder->codeAppendf("int paramsIdx = int(%s & 0x%x);",
this->attr(Attrib::kInstanceInfo), this->attr(Attrib::kInstanceInfo),
kParamsIdx_InfoMask); kParamsIdx_InfoMask);
} }
const char* attr(Attrib attr) const { return fInstProc.getAttrib((int)attr).fName; } const char* attr(Attrib attr) const { return fInstProc.getAttrib((int)attr).fName; }
void fetchNextParam(const GrShaderCaps* shaderCaps, GrSLType type = kVec4f_GrSLType) const { void fetchNextParam(const GrShaderCaps* shaderCaps, GrSLType type = kHalf4_GrSLType) const {
SkASSERT(fParamsBuffer.isValid()); SkASSERT(fParamsBuffer.isValid());
switch (type) { switch (type) {
case kVec2f_GrSLType: // fall through case kHighFloat2_GrSLType: // fall through
case kVec3f_GrSLType: // fall through case kHighFloat3_GrSLType: // fall through
case kVec4f_GrSLType: case kHighFloat4_GrSLType: // fall through
case kHalf2_GrSLType: // fall through
case kHalf3_GrSLType: // fall through
case kHalf4_GrSLType:
break; break;
default: default:
fVertexBuilder->codeAppendf("%s(", GrGLSLTypeString(shaderCaps, type)); fVertexBuilder->codeAppendf("%s(", GrGLSLTypeString(shaderCaps, type));
} }
fVertexBuilder->appendTexelFetch(fParamsBuffer, "paramsIdx++"); fVertexBuilder->appendTexelFetch(fParamsBuffer, "paramsIdx++");
switch (type) { switch (type) {
case kVec2f_GrSLType: case kHighFloat2_GrSLType: // fall through
case kHalf2_GrSLType:
fVertexBuilder->codeAppend(".xy"); fVertexBuilder->codeAppend(".xy");
break; break;
case kVec3f_GrSLType: case kHighFloat3_GrSLType: // fall through
case kHalf3_GrSLType:
fVertexBuilder->codeAppend(".xyz"); fVertexBuilder->codeAppend(".xyz");
break; break;
case kVec4f_GrSLType: case kHighFloat4_GrSLType: // fall through
case kHalf4_GrSLType:
break; break;
default: default:
fVertexBuilder->codeAppend(")"); fVertexBuilder->codeAppend(")");
@ -177,11 +183,11 @@ protected:
, fModifiesCoverage(false) , fModifiesCoverage(false)
, fModifiesColor(false) , fModifiesColor(false)
, fNeedsNeighborRadii(false) , fNeedsNeighborRadii(false)
, fColor(kVec4f_GrSLType) , fColor(kHalf4_GrSLType)
, fTriangleIsArc(kInt_GrSLType) , fTriangleIsArc(kInt_GrSLType)
, fArcCoords(kVec2f_GrSLType) , fArcCoords(kHalf2_GrSLType)
, fInnerShapeCoords(kVec2f_GrSLType) , fInnerShapeCoords(kHalf2_GrSLType)
, fInnerRRect(kVec4f_GrSLType) , fInnerRRect(kHalf4_GrSLType)
, fModifiedShapeCoords(nullptr) { , fModifiedShapeCoords(nullptr) {
if (fOpInfo.fShapeTypes & kRRect_ShapesMask) { if (fOpInfo.fShapeTypes & kRRect_ShapesMask) {
fModifiedShapeCoords = "adjustedShapeCoords"; fModifiedShapeCoords = "adjustedShapeCoords";
@ -232,16 +238,16 @@ void GLSLInstanceProcessor::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
} }
if (!ip.opInfo().fHasPerspective) { if (!ip.opInfo().fHasPerspective) {
v->codeAppendf("float2x3 shapeMatrix = float2x3(%s, %s);", v->codeAppendf("half2x3 shapeMatrix = half2x3(%s, %s);",
inputs.attr(Attrib::kShapeMatrixX), inputs.attr(Attrib::kShapeMatrixY)); inputs.attr(Attrib::kShapeMatrixX), inputs.attr(Attrib::kShapeMatrixY));
} else { } else {
v->defineConstantf("int", "PERSPECTIVE_FLAG", "0x%x", kPerspective_InfoFlag); v->defineConstantf("int", "PERSPECTIVE_FLAG", "0x%x", kPerspective_InfoFlag);
v->codeAppendf("float3x3 shapeMatrix = float3x3(%s, %s, float3(0, 0, 1));", v->codeAppendf("half3x3 shapeMatrix = half3x3(%s, %s, half3(0, 0, 1));",
inputs.attr(Attrib::kShapeMatrixX), inputs.attr(Attrib::kShapeMatrixY)); inputs.attr(Attrib::kShapeMatrixX), inputs.attr(Attrib::kShapeMatrixY));
v->codeAppendf("if (0 != (%s & uint(PERSPECTIVE_FLAG))) {", v->codeAppendf("if (0 != (%s & uint(PERSPECTIVE_FLAG))) {",
inputs.attr(Attrib::kInstanceInfo)); inputs.attr(Attrib::kInstanceInfo));
v->codeAppend ( "shapeMatrix[2] = "); v->codeAppend ( "shapeMatrix[2] = ");
inputs.fetchNextParam(args.fShaderCaps, kVec3f_GrSLType); inputs.fetchNextParam(args.fShaderCaps, kHalf3_GrSLType);
v->codeAppend ( ";"); v->codeAppend ( ";");
v->codeAppend ("}"); v->codeAppend ("}");
} }
@ -303,16 +309,16 @@ void GLSLInstanceProcessor::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
inputs.attr(Attrib::kInstanceInfo)); inputs.attr(Attrib::kInstanceInfo));
} }
// Here we take advantage of the fact that outerRect == localRect in recordDRRect. // Here we take advantage of the fact that outerRect == localRect in recordDRRect.
v->codeAppendf("float4 outer = %s;", inputs.attr(Attrib::kLocalRect)); v->codeAppendf("half4 outer = %s;", inputs.attr(Attrib::kLocalRect));
v->codeAppend ("float4 inner = "); v->codeAppend ("half4 inner = ");
inputs.fetchNextParam(args.fShaderCaps); inputs.fetchNextParam(args.fShaderCaps);
v->codeAppend (";"); v->codeAppend (";");
// outer2Inner is a transform from shape coords to inner shape coords: // outer2Inner is a transform from shape coords to inner shape coords:
// e.g. innerShapeCoords = shapeCoords * outer2Inner.xy + outer2Inner.zw // e.g. innerShapeCoords = shapeCoords * outer2Inner.xy + outer2Inner.zw
v->codeAppend ("float4 outer2Inner = float4(outer.zw - outer.xy, " v->codeAppend ("half4 outer2Inner = half4(outer.zw - outer.xy, "
"outer.xy + outer.zw - inner.xy - inner.zw) / " "outer.xy + outer.zw - inner.xy - inner.zw) / "
"(inner.zw - inner.xy).xyxy;"); "(inner.zw - inner.xy).xyxy;");
v->codeAppendf("float2 innerShapeCoords = %s * outer2Inner.xy + outer2Inner.zw;", v->codeAppendf("half2 innerShapeCoords = %s * outer2Inner.xy + outer2Inner.zw;",
backend->outShapeCoords()); backend->outShapeCoords());
backend->initInnerShape(varyingHandler, v); backend->initInnerShape(varyingHandler, v);
@ -372,8 +378,8 @@ void GLSLInstanceProcessor::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
const char* localCoords = nullptr; const char* localCoords = nullptr;
if (ip.opInfo().fUsesLocalCoords) { if (ip.opInfo().fUsesLocalCoords) {
localCoords = "localCoords"; localCoords = "localCoords";
v->codeAppendf("float2 t = 0.5 * (%s + float2(1));", backend->outShapeCoords()); v->codeAppendf("half2 t = 0.5 * (%s + half2(1));", backend->outShapeCoords());
v->codeAppendf("float2 localCoords = (1.0 - t) * %s.xy + t * %s.zw;", v->codeAppendf("half2 localCoords = (1.0 - t) * %s.xy + t * %s.zw;",
inputs.attr(Attrib::kLocalRect), inputs.attr(Attrib::kLocalRect)); inputs.attr(Attrib::kLocalRect), inputs.attr(Attrib::kLocalRect));
} }
if (ip.opInfo().fHasLocalMatrix && ip.opInfo().fHasParams) { if (ip.opInfo().fHasLocalMatrix && ip.opInfo().fHasParams) {
@ -383,20 +389,20 @@ void GLSLInstanceProcessor::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
if (!ip.opInfo().fUsesLocalCoords) { if (!ip.opInfo().fUsesLocalCoords) {
inputs.skipParams(2); inputs.skipParams(2);
} else { } else {
v->codeAppendf( "float2x3 localMatrix;"); v->codeAppendf( "half2x3 localMatrix;");
v->codeAppend ( "localMatrix[0] = "); v->codeAppend ( "localMatrix[0] = ");
inputs.fetchNextParam(args.fShaderCaps, kVec3f_GrSLType); inputs.fetchNextParam(args.fShaderCaps, kHalf3_GrSLType);
v->codeAppend ( ";"); v->codeAppend ( ";");
v->codeAppend ( "localMatrix[1] = "); v->codeAppend ( "localMatrix[1] = ");
inputs.fetchNextParam(args.fShaderCaps, kVec3f_GrSLType); inputs.fetchNextParam(args.fShaderCaps, kHalf3_GrSLType);
v->codeAppend ( ";"); v->codeAppend ( ";");
v->codeAppend ( "localCoords = (float3(localCoords, 1) * localMatrix).xy;"); v->codeAppend ( "localCoords = (half3(localCoords, 1) * localMatrix).xy;");
} }
v->codeAppend("}"); v->codeAppend("}");
} }
GrSLType positionType = ip.opInfo().fHasPerspective ? kVec3f_GrSLType : kVec2f_GrSLType; GrSLType positionType = ip.opInfo().fHasPerspective ? kHighFloat3_GrSLType : kHighFloat2_GrSLType;
v->codeAppendf("%s deviceCoords = float3(%s, 1) * shapeMatrix;", v->codeAppendf("%s deviceCoords = highfloat3(%s, 1) * shapeMatrix;",
GrGLSLTypeString(args.fShaderCaps, positionType), backend->outShapeCoords()); GrGLSLTypeString(args.fShaderCaps, positionType), backend->outShapeCoords());
gpArgs->fPositionVar.set(positionType, "deviceCoords"); gpArgs->fPositionVar.set(positionType, "deviceCoords");
@ -409,7 +415,7 @@ void GLSLInstanceProcessor::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
void GLSLInstanceProcessor::Backend::init(GrGLSLVaryingHandler* varyingHandler, void GLSLInstanceProcessor::Backend::init(GrGLSLVaryingHandler* varyingHandler,
GrGLSLVertexBuilder* v) { GrGLSLVertexBuilder* v) {
if (fModifiedShapeCoords) { if (fModifiedShapeCoords) {
v->codeAppendf("float2 %s = %s;", fModifiedShapeCoords, fInputs.attr(Attrib::kShapeCoords)); v->codeAppendf("half2 %s = %s;", fModifiedShapeCoords, fInputs.attr(Attrib::kShapeCoords));
} }
this->onInit(varyingHandler, v); this->onInit(varyingHandler, v);
@ -425,10 +431,10 @@ void GLSLInstanceProcessor::Backend::setupRRect(const GrShaderCaps* shaderCaps,
int* usedShapeDefinitions) { int* usedShapeDefinitions) {
v->codeAppendf("uint2 corner = uint2(uint(%s) & 1, (uint(%s) >> 1) & 1);", v->codeAppendf("uint2 corner = uint2(uint(%s) & 1, (uint(%s) >> 1) & 1);",
fInputs.attr(Attrib::kVertexAttrs), fInputs.attr(Attrib::kVertexAttrs)); fInputs.attr(Attrib::kVertexAttrs), fInputs.attr(Attrib::kVertexAttrs));
v->codeAppend ("float2 cornerSign = float2(corner) * 2.0 - 1.0;"); v->codeAppend ("half2 cornerSign = half2(corner) * 2.0 - 1.0;");
v->codeAppendf("float2 radii%s;", fNeedsNeighborRadii ? ", neighborRadii" : ""); v->codeAppendf("half2 radii%s;", fNeedsNeighborRadii ? ", neighborRadii" : "");
v->codeAppend ("float2x2 p = "); v->codeAppend ("half2x2 p = ");
fInputs.fetchNextParam(shaderCaps, kMat22f_GrSLType); fInputs.fetchNextParam(shaderCaps, kHalf2x2_GrSLType);
v->codeAppend (";"); v->codeAppend (";");
uint8_t types = fOpInfo.fShapeTypes & kRRect_ShapesMask; uint8_t types = fOpInfo.fShapeTypes & kRRect_ShapesMask;
if (0 == (types & (types - 1))) { if (0 == (types & (types - 1))) {
@ -469,11 +475,11 @@ void GLSLInstanceProcessor::Backend::setupRRect(const GrShaderCaps* shaderCaps,
this->adjustRRectVertices(v); this->adjustRRectVertices(v);
if (fArcCoords.vsOut()) { if (fArcCoords.vsOut()) {
v->codeAppendf("%s = (cornerSign * %s + radii - float2(1)) / radii;", v->codeAppendf("%s = (cornerSign * %s + radii - half2(1)) / radii;",
fArcCoords.vsOut(), fModifiedShapeCoords); fArcCoords.vsOut(), fModifiedShapeCoords);
} }
if (fTriangleIsArc.vsOut()) { if (fTriangleIsArc.vsOut()) {
v->codeAppendf("%s = int(all(equal(float2(1), abs(%s))));", v->codeAppendf("%s = int(all(equal(half2(1), abs(%s))));",
fTriangleIsArc.vsOut(), fInputs.attr(Attrib::kShapeCoords)); fTriangleIsArc.vsOut(), fInputs.attr(Attrib::kShapeCoords));
} }
@ -488,9 +494,9 @@ void GLSLInstanceProcessor::Backend::setupSimpleRadii(GrGLSLVertexBuilder* v) {
} }
void GLSLInstanceProcessor::Backend::setupNinePatchRadii(GrGLSLVertexBuilder* v) { void GLSLInstanceProcessor::Backend::setupNinePatchRadii(GrGLSLVertexBuilder* v) {
v->codeAppend("radii = float2(p[0][corner.x], p[1][corner.y]);"); v->codeAppend("radii = half2(p[0][corner.x], p[1][corner.y]);");
if (fNeedsNeighborRadii) { if (fNeedsNeighborRadii) {
v->codeAppend("neighborRadii = float2(p[0][1 - corner.x], p[1][1 - corner.y]);"); v->codeAppend("neighborRadii = half2(p[0][1 - corner.x], p[1][1 - corner.y]);");
} }
} }
@ -510,12 +516,12 @@ void GLSLInstanceProcessor::Backend::setupComplexRadii(const GrShaderCaps* shade
* x2 x4 * x2 x4
* *
*/ */
v->codeAppend("float2x2 p2 = "); v->codeAppend("half2x2 p2 = ");
fInputs.fetchNextParam(shaderCaps, kMat22f_GrSLType); fInputs.fetchNextParam(shaderCaps, kHalf2x2_GrSLType);
v->codeAppend(";"); v->codeAppend(";");
v->codeAppend("radii = float2(p[corner.x][corner.y], p2[corner.y][corner.x]);"); v->codeAppend("radii = half2(p[corner.x][corner.y], p2[corner.y][corner.x]);");
if (fNeedsNeighborRadii) { if (fNeedsNeighborRadii) {
v->codeAppend("neighborRadii = float2(p[1 - corner.x][corner.y], " v->codeAppend("neighborRadii = half2(p[1 - corner.x][corner.y], "
"p2[1 - corner.y][corner.x]);"); "p2[1 - corner.y][corner.x]);");
} }
} }
@ -544,10 +550,10 @@ void GLSLInstanceProcessor::Backend::initInnerShape(GrGLSLVaryingHandler* varyin
void GLSLInstanceProcessor::Backend::setupInnerSimpleRRect(const GrShaderCaps* shaderCaps, void GLSLInstanceProcessor::Backend::setupInnerSimpleRRect(const GrShaderCaps* shaderCaps,
GrGLSLVertexBuilder* v) { GrGLSLVertexBuilder* v) {
v->codeAppend("float2x2 innerP = "); v->codeAppend("half2x2 innerP = ");
fInputs.fetchNextParam(shaderCaps, kMat22f_GrSLType); fInputs.fetchNextParam(shaderCaps, kHalf2x2_GrSLType);
v->codeAppend(";"); v->codeAppend(";");
v->codeAppend("float2 innerRadii = innerP[0] * 2.0 / innerP[1];"); v->codeAppend("half2 innerRadii = innerP[0] * 2.0 / innerP[1];");
this->onSetupInnerSimpleRRect(v); this->onSetupInnerSimpleRRect(v);
} }
@ -558,7 +564,7 @@ void GLSLInstanceProcessor::Backend::emitCode(GrGLSLVertexBuilder* v, GrGLSLPPFr
fModifiesColor ? outColor : nullptr); fModifiesColor ? outColor : nullptr);
if (outCoverage && !fModifiesCoverage) { if (outCoverage && !fModifiesCoverage) {
// Even though the subclass doesn't use coverage, we are expected to assign some value. // Even though the subclass doesn't use coverage, we are expected to assign some value.
f->codeAppendf("%s = float4(1);", outCoverage); f->codeAppendf("%s = half4(1);", outCoverage);
} }
if (!fModifiesColor) { if (!fModifiesColor) {
// The subclass didn't assign a value to the output color. // The subclass didn't assign a value to the output color.
@ -625,18 +631,18 @@ void GLSLInstanceProcessor::BackendNonAA::onInitInnerShape(GrGLSLVaryingHandler*
void GLSLInstanceProcessor::BackendNonAA::setupInnerRect(GrGLSLVertexBuilder* v) { void GLSLInstanceProcessor::BackendNonAA::setupInnerRect(GrGLSLVertexBuilder* v) {
if (fInnerRRect.vsOut()) { if (fInnerRRect.vsOut()) {
v->codeAppendf("%s = float4(1);", fInnerRRect.vsOut()); v->codeAppendf("%s = half4(1);", fInnerRRect.vsOut());
} }
} }
void GLSLInstanceProcessor::BackendNonAA::setupInnerOval(GrGLSLVertexBuilder* v) { void GLSLInstanceProcessor::BackendNonAA::setupInnerOval(GrGLSLVertexBuilder* v) {
if (fInnerRRect.vsOut()) { if (fInnerRRect.vsOut()) {
v->codeAppendf("%s = float4(0, 0, 1, 1);", fInnerRRect.vsOut()); v->codeAppendf("%s = half4(0, 0, 1, 1);", fInnerRRect.vsOut());
} }
} }
void GLSLInstanceProcessor::BackendNonAA::onSetupInnerSimpleRRect(GrGLSLVertexBuilder* v) { void GLSLInstanceProcessor::BackendNonAA::onSetupInnerSimpleRRect(GrGLSLVertexBuilder* v) {
v->codeAppendf("%s = float4(1.0 - innerRadii, 1.0 / innerRadii);", fInnerRRect.vsOut()); v->codeAppendf("%s = half4(1.0 - innerRadii, 1.0 / innerRadii);", fInnerRRect.vsOut());
} }
void GLSLInstanceProcessor::BackendNonAA::onEmitCode(GrGLSLVertexBuilder*, void GLSLInstanceProcessor::BackendNonAA::onEmitCode(GrGLSLVertexBuilder*,
@ -647,11 +653,11 @@ void GLSLInstanceProcessor::BackendNonAA::onEmitCode(GrGLSLVertexBuilder*,
if (!fOpInfo.fCannotDiscard) { if (!fOpInfo.fCannotDiscard) {
dropFragment = "discard"; dropFragment = "discard";
} else if (fModifiesCoverage) { } else if (fModifiesCoverage) {
f->codeAppend ("lowp float covered = 1.0;"); f->codeAppend ("half covered = 1.0;");
dropFragment = "covered = 0.0"; dropFragment = "covered = 0.0";
} else if (fModifiesColor) { } else if (fModifiesColor) {
f->codeAppendf("lowp float4 color = %s;", fColor.fsIn()); f->codeAppendf("half4 color = %s;", fColor.fsIn());
dropFragment = "color = float4(0)"; dropFragment = "color = half4(0)";
} }
if (fTriangleIsArc.fsIn()) { if (fTriangleIsArc.fsIn()) {
SkASSERT(dropFragment); SkASSERT(dropFragment);
@ -662,19 +668,19 @@ void GLSLInstanceProcessor::BackendNonAA::onEmitCode(GrGLSLVertexBuilder*,
SkASSERT(dropFragment); SkASSERT(dropFragment);
f->codeAppendf("// Inner shape.\n"); f->codeAppendf("// Inner shape.\n");
if (kRect_ShapeFlag == fOpInfo.fInnerShapeTypes) { if (kRect_ShapeFlag == fOpInfo.fInnerShapeTypes) {
f->codeAppendf("if (all(lessThanEqual(abs(%s), float2(1)))) %s;", f->codeAppendf("if (all(lessThanEqual(abs(%s), half2(1)))) %s;",
fInnerShapeCoords.fsIn(), dropFragment); fInnerShapeCoords.fsIn(), dropFragment);
} else if (kOval_ShapeFlag == fOpInfo.fInnerShapeTypes) { } else if (kOval_ShapeFlag == fOpInfo.fInnerShapeTypes) {
f->codeAppendf("if ((dot(%s, %s) <= 1.0)) %s;", f->codeAppendf("if ((dot(%s, %s) <= 1.0)) %s;",
fInnerShapeCoords.fsIn(), fInnerShapeCoords.fsIn(), dropFragment); fInnerShapeCoords.fsIn(), fInnerShapeCoords.fsIn(), dropFragment);
} else { } else {
f->codeAppendf("if (all(lessThan(abs(%s), float2(1)))) {", fInnerShapeCoords.fsIn()); f->codeAppendf("if (all(lessThan(abs(%s), half2(1)))) {", fInnerShapeCoords.fsIn());
f->codeAppendf( "float2 distanceToArcEdge = abs(%s) - %s.xy;", f->codeAppendf( "half2 distanceToArcEdge = abs(%s) - %s.xy;",
fInnerShapeCoords.fsIn(), fInnerRRect.fsIn()); fInnerShapeCoords.fsIn(), fInnerRRect.fsIn());
f->codeAppend ( "if (any(lessThan(distanceToArcEdge, float2(0)))) {"); f->codeAppend ( "if (any(lessThan(distanceToArcEdge, half2(0)))) {");
f->codeAppendf( "%s;", dropFragment); f->codeAppendf( "%s;", dropFragment);
f->codeAppend ( "} else {"); f->codeAppend ( "} else {");
f->codeAppendf( "float2 rrectCoords = distanceToArcEdge * %s.zw;", f->codeAppendf( "half2 rrectCoords = distanceToArcEdge * %s.zw;",
fInnerRRect.fsIn()); fInnerRRect.fsIn());
f->codeAppend ( "if (dot(rrectCoords, rrectCoords) <= 1.0) {"); f->codeAppend ( "if (dot(rrectCoords, rrectCoords) <= 1.0) {");
f->codeAppendf( "%s;", dropFragment); f->codeAppendf( "%s;", dropFragment);
@ -684,7 +690,7 @@ void GLSLInstanceProcessor::BackendNonAA::onEmitCode(GrGLSLVertexBuilder*,
} }
} }
if (fModifiesCoverage) { if (fModifiesCoverage) {
f->codeAppendf("%s = float4(covered);", outCoverage); f->codeAppendf("%s = half4(covered);", outCoverage);
} else if (fModifiesColor) { } else if (fModifiesColor) {
f->codeAppendf("%s = color;", outColor); f->codeAppendf("%s = color;", outColor);
} }
@ -696,15 +702,15 @@ class GLSLInstanceProcessor::BackendCoverage : public Backend {
public: public:
BackendCoverage(OpInfo opInfo, const VertexInputs& inputs) BackendCoverage(OpInfo opInfo, const VertexInputs& inputs)
: INHERITED(opInfo, inputs) : INHERITED(opInfo, inputs)
, fColorTimesRectCoverage(kVec4f_GrSLType) , fColorTimesRectCoverage(kHalf4_GrSLType)
, fRectCoverage(kFloat_GrSLType) , fRectCoverage(kHalf_GrSLType)
, fEllipseCoords(kVec2f_GrSLType) , fEllipseCoords(kHalf2_GrSLType)
, fEllipseName(kVec2f_GrSLType) , fEllipseName(kHalf2_GrSLType)
, fBloatedRadius(kFloat_GrSLType) , fBloatedRadius(kHalf_GrSLType)
, fDistanceToInnerEdge(kVec2f_GrSLType) , fDistanceToInnerEdge(kHalf2_GrSLType)
, fInnerShapeBloatedHalfSize(kVec2f_GrSLType) , fInnerShapeBloatedHalfSize(kHalf2_GrSLType)
, fInnerEllipseCoords(kVec2f_GrSLType) , fInnerEllipseCoords(kHalf2_GrSLType)
, fInnerEllipseName(kVec2f_GrSLType) { , fInnerEllipseName(kHalf2_GrSLType) {
fShapeIsCircle = !fOpInfo.fNonSquare && !(fOpInfo.fShapeTypes & kRRect_ShapesMask); fShapeIsCircle = !fOpInfo.fNonSquare && !(fOpInfo.fShapeTypes & kRRect_ShapesMask);
fTweakAlphaForCoverage = !fOpInfo.fCannotTweakAlphaForCoverage && !fOpInfo.fInnerShapeTypes; fTweakAlphaForCoverage = !fOpInfo.fCannotTweakAlphaForCoverage && !fOpInfo.fInnerShapeTypes;
fModifiesCoverage = !fTweakAlphaForCoverage; fModifiesCoverage = !fTweakAlphaForCoverage;
@ -751,10 +757,10 @@ private:
void GLSLInstanceProcessor::BackendCoverage::onInit(GrGLSLVaryingHandler* varyingHandler, void GLSLInstanceProcessor::BackendCoverage::onInit(GrGLSLVaryingHandler* varyingHandler,
GrGLSLVertexBuilder* v) { GrGLSLVertexBuilder* v) {
v->codeAppend ("float2x2 shapeTransposeMatrix = transpose(float2x2(shapeMatrix));"); v->codeAppend ("half2x2 shapeTransposeMatrix = transpose(half2x2(shapeMatrix));");
v->codeAppend ("float2 shapeHalfSize = float2(length(shapeTransposeMatrix[0]), " v->codeAppend ("half2 shapeHalfSize = half2(length(shapeTransposeMatrix[0]), "
"length(shapeTransposeMatrix[1]));"); "length(shapeTransposeMatrix[1]));");
v->codeAppend ("float2 bloat = 0.5 / shapeHalfSize;"); v->codeAppend ("half2 bloat = 0.5 / shapeHalfSize;");
v->codeAppendf("bloatedShapeCoords = %s * (1.0 + bloat);", fInputs.attr(Attrib::kShapeCoords)); v->codeAppendf("bloatedShapeCoords = %s * (1.0 + bloat);", fInputs.attr(Attrib::kShapeCoords));
if (kOval_ShapeFlag != fOpInfo.fShapeTypes) { if (kOval_ShapeFlag != fOpInfo.fShapeTypes) {
@ -767,7 +773,7 @@ void GLSLInstanceProcessor::BackendCoverage::onInit(GrGLSLVaryingHandler* varyin
} else { } else {
varyingHandler->addVarying("rectCoverage", &fRectCoverage, kLow_GrSLPrecision); varyingHandler->addVarying("rectCoverage", &fRectCoverage, kLow_GrSLPrecision);
} }
v->codeAppend("float rectCoverage = 0.0;"); v->codeAppend("half rectCoverage = 0.0;");
} }
if (kRect_ShapeFlag != fOpInfo.fShapeTypes) { if (kRect_ShapeFlag != fOpInfo.fShapeTypes) {
varyingHandler->addFlatVarying("triangleIsArc", &fTriangleIsArc, kLow_GrSLPrecision); varyingHandler->addFlatVarying("triangleIsArc", &fTriangleIsArc, kLow_GrSLPrecision);
@ -783,18 +789,18 @@ void GLSLInstanceProcessor::BackendCoverage::onInit(GrGLSLVaryingHandler* varyin
void GLSLInstanceProcessor::BackendCoverage::setupRect(GrGLSLVertexBuilder* v) { void GLSLInstanceProcessor::BackendCoverage::setupRect(GrGLSLVertexBuilder* v) {
// Make the border one pixel wide. Inner vs outer is indicated by coordAttrs. // Make the border one pixel wide. Inner vs outer is indicated by coordAttrs.
v->codeAppendf("float2 rectBloat = (%s != 0) ? bloat : -bloat;", v->codeAppendf("half2 rectBloat = (%s != 0) ? bloat : -bloat;",
fInputs.attr(Attrib::kVertexAttrs)); fInputs.attr(Attrib::kVertexAttrs));
// Here we use the absolute value, because when the rect is thinner than a pixel, this makes it // Here we use the absolute value, because when the rect is thinner than a pixel, this makes it
// mark the spot where pixel center is within half a pixel of the *opposite* edge. This, // mark the spot where pixel center is within half a pixel of the *opposite* edge. This,
// combined with the "maxCoverage" logic below gives us mathematically correct coverage even for // combined with the "maxCoverage" logic below gives us mathematically correct coverage even for
// subpixel rectangles. // subpixel rectangles.
v->codeAppendf("bloatedShapeCoords = %s * abs(float2(1.0 + rectBloat));", v->codeAppendf("bloatedShapeCoords = %s * abs(half2(1.0 + rectBloat));",
fInputs.attr(Attrib::kShapeCoords)); fInputs.attr(Attrib::kShapeCoords));
// Determine coverage at the vertex. Coverage naturally ramps from 0 to 1 unless the rect is // Determine coverage at the vertex. Coverage naturally ramps from 0 to 1 unless the rect is
// narrower than a pixel. // narrower than a pixel.
v->codeAppend ("float maxCoverage = 4.0 * min(0.5, shapeHalfSize.x) *" v->codeAppend ("half maxCoverage = 4.0 * min(0.5, shapeHalfSize.x) *"
"min(0.5, shapeHalfSize.y);"); "min(0.5, shapeHalfSize.y);");
v->codeAppendf("rectCoverage = (%s != 0) ? 0.0 : maxCoverage;", v->codeAppendf("rectCoverage = (%s != 0) ? 0.0 : maxCoverage;",
fInputs.attr(Attrib::kVertexAttrs)); fInputs.attr(Attrib::kVertexAttrs));
@ -806,9 +812,9 @@ void GLSLInstanceProcessor::BackendCoverage::setupRect(GrGLSLVertexBuilder* v) {
void GLSLInstanceProcessor::BackendCoverage::setupOval(GrGLSLVertexBuilder* v) { void GLSLInstanceProcessor::BackendCoverage::setupOval(GrGLSLVertexBuilder* v) {
// Offset the inner and outer octagons by one pixel. Inner vs outer is indicated by coordAttrs. // Offset the inner and outer octagons by one pixel. Inner vs outer is indicated by coordAttrs.
v->codeAppendf("float2 ovalBloat = (%s != 0) ? bloat : -bloat;", v->codeAppendf("half2 ovalBloat = (%s != 0) ? bloat : -bloat;",
fInputs.attr(Attrib::kVertexAttrs)); fInputs.attr(Attrib::kVertexAttrs));
v->codeAppendf("bloatedShapeCoords = %s * max(float2(1.0 + ovalBloat), float2(0));", v->codeAppendf("bloatedShapeCoords = %s * max(half2(1.0 + ovalBloat), half2(0));",
fInputs.attr(Attrib::kShapeCoords)); fInputs.attr(Attrib::kShapeCoords));
v->codeAppendf("%s = bloatedShapeCoords * shapeHalfSize;", fEllipseCoords.vsOut()); v->codeAppendf("%s = bloatedShapeCoords * shapeHalfSize;", fEllipseCoords.vsOut());
if (fEllipseName.vsOut()) { if (fEllipseName.vsOut()) {
@ -831,8 +837,8 @@ void GLSLInstanceProcessor::BackendCoverage::adjustRRectVertices(GrGLSLVertexBui
// We try to let the AA borders line up with the arc edges on their particular side, but we // We try to let the AA borders line up with the arc edges on their particular side, but we
// can't allow them to get closer than one half pixel to the edge or they might overlap with // can't allow them to get closer than one half pixel to the edge or they might overlap with
// their neighboring border. // their neighboring border.
v->codeAppend("float2 innerEdge = max(1.0 - bloat, float2(0));"); v->codeAppend("half2 innerEdge = max(1.0 - bloat, half2(0));");
v->codeAppend ("float2 borderEdge = cornerSign * clamp(1.0 - radii, -innerEdge, innerEdge);"); v->codeAppend ("half2 borderEdge = cornerSign * clamp(1.0 - radii, -innerEdge, innerEdge);");
// 0.5 is a special value that indicates this vertex is an arc edge. // 0.5 is a special value that indicates this vertex is an arc edge.
v->codeAppendf("if (abs(%s.x) == 0.5)" v->codeAppendf("if (abs(%s.x) == 0.5)"
"bloatedShapeCoords.x = borderEdge.x;", fInputs.attr(Attrib::kShapeCoords)); "bloatedShapeCoords.x = borderEdge.x;", fInputs.attr(Attrib::kShapeCoords));
@ -855,7 +861,7 @@ void GLSLInstanceProcessor::BackendCoverage::onSetupRRect(GrGLSLVertexBuilder* v
// interior edge of the border will necessarily clamp, and we need to match the AA behavior of // interior edge of the border will necessarily clamp, and we need to match the AA behavior of
// the arc segments (i.e. distance from bloated edge only; ignoring the fact that the pixel // the arc segments (i.e. distance from bloated edge only; ignoring the fact that the pixel
// actully has less coverage because it's not completely inside the opposite edge.) // actully has less coverage because it's not completely inside the opposite edge.)
v->codeAppend("float2 d = shapeHalfSize + 0.5 - abs(bloatedShapeCoords) * shapeHalfSize;"); v->codeAppend("half2 d = shapeHalfSize + 0.5 - abs(bloatedShapeCoords) * shapeHalfSize;");
v->codeAppend("rectCoverage = min(d.x, d.y);"); v->codeAppend("rectCoverage = min(d.x, d.y);");
SkASSERT(!fShapeIsCircle); SkASSERT(!fShapeIsCircle);
@ -863,8 +869,8 @@ void GLSLInstanceProcessor::BackendCoverage::onSetupRRect(GrGLSLVertexBuilder* v
// smooth transition from flat edge to arc, we don't allow the radii to be smaller than one half // smooth transition from flat edge to arc, we don't allow the radii to be smaller than one half
// pixel. (We don't worry about the transition on the opposite side when a radius is so large // pixel. (We don't worry about the transition on the opposite side when a radius is so large
// that the border clamped on that side.) // that the border clamped on that side.)
v->codeAppendf("float2 clampedRadii = max(radii, bloat);"); v->codeAppendf("half2 clampedRadii = max(radii, bloat);");
v->codeAppendf("%s = (cornerSign * bloatedShapeCoords + clampedRadii - float2(1)) * " v->codeAppendf("%s = (cornerSign * bloatedShapeCoords + clampedRadii - half2(1)) * "
"shapeHalfSize;", fEllipseCoords.vsOut()); "shapeHalfSize;", fEllipseCoords.vsOut());
v->codeAppendf("%s = 1.0 / (clampedRadii * clampedRadii * shapeHalfSize * shapeHalfSize);", v->codeAppendf("%s = 1.0 / (clampedRadii * clampedRadii * shapeHalfSize * shapeHalfSize);",
fEllipseName.vsOut()); fEllipseName.vsOut());
@ -872,7 +878,7 @@ void GLSLInstanceProcessor::BackendCoverage::onSetupRRect(GrGLSLVertexBuilder* v
void GLSLInstanceProcessor::BackendCoverage::onInitInnerShape(GrGLSLVaryingHandler* varyingHandler, void GLSLInstanceProcessor::BackendCoverage::onInitInnerShape(GrGLSLVaryingHandler* varyingHandler,
GrGLSLVertexBuilder* v) { GrGLSLVertexBuilder* v) {
v->codeAppend("float2 innerShapeHalfSize = shapeHalfSize / outer2Inner.xy;"); v->codeAppend("half2 innerShapeHalfSize = shapeHalfSize / outer2Inner.xy;");
if (kOval_ShapeFlag == fOpInfo.fInnerShapeTypes) { if (kOval_ShapeFlag == fOpInfo.fInnerShapeTypes) {
varyingHandler->addVarying("innerEllipseCoords", &fInnerEllipseCoords, varyingHandler->addVarying("innerEllipseCoords", &fInnerEllipseCoords,
@ -910,7 +916,7 @@ void GLSLInstanceProcessor::BackendCoverage::setupInnerOval(GrGLSLVertexBuilder*
v->codeAppendf("%s = innerShapeCoords * innerShapeHalfSize;", fInnerEllipseCoords.vsOut()); v->codeAppendf("%s = innerShapeCoords * innerShapeHalfSize;", fInnerEllipseCoords.vsOut());
} }
if (fInnerRRect.vsOut()) { if (fInnerRRect.vsOut()) {
v->codeAppendf("%s = float4(0, 0, innerShapeHalfSize);", fInnerRRect.vsOut()); v->codeAppendf("%s = half4(0, 0, innerShapeHalfSize);", fInnerRRect.vsOut());
} }
} }
@ -920,7 +926,7 @@ void GLSLInstanceProcessor::BackendCoverage::onSetupInnerSimpleRRect(GrGLSLVerte
v->codeAppendf("%s = 1.0 / (innerRadii * innerRadii * innerShapeHalfSize * " v->codeAppendf("%s = 1.0 / (innerRadii * innerRadii * innerShapeHalfSize * "
"innerShapeHalfSize);", "innerShapeHalfSize);",
fInnerEllipseName.vsOut()); fInnerEllipseName.vsOut());
v->codeAppendf("%s = float4(1.0 - innerRadii, innerShapeHalfSize);", fInnerRRect.vsOut()); v->codeAppendf("%s = half4(1.0 - innerRadii, innerShapeHalfSize);", fInnerRRect.vsOut());
} }
void GLSLInstanceProcessor::BackendCoverage::onEmitCode(GrGLSLVertexBuilder* v, void GLSLInstanceProcessor::BackendCoverage::onEmitCode(GrGLSLVertexBuilder* v,
@ -937,7 +943,7 @@ void GLSLInstanceProcessor::BackendCoverage::onEmitCode(GrGLSLVertexBuilder* v,
v->codeAppendf("%s = rectCoverage;", fRectCoverage.vsOut()); v->codeAppendf("%s = rectCoverage;", fRectCoverage.vsOut());
} }
SkString coverage("lowp float coverage"); SkString coverage("half coverage");
if (fOpInfo.fInnerShapeTypes || (!fTweakAlphaForCoverage && fTriangleIsArc.fsIn())) { if (fOpInfo.fInnerShapeTypes || (!fTweakAlphaForCoverage && fTriangleIsArc.fsIn())) {
f->codeAppendf("%s;", coverage.c_str()); f->codeAppendf("%s;", coverage.c_str());
coverage = "coverage"; coverage = "coverage";
@ -964,7 +970,7 @@ void GLSLInstanceProcessor::BackendCoverage::onEmitCode(GrGLSLVertexBuilder* v,
if (fOpInfo.fInnerShapeTypes) { if (fOpInfo.fInnerShapeTypes) {
f->codeAppendf("// Inner shape.\n"); f->codeAppendf("// Inner shape.\n");
SkString innerCoverageDecl("lowp float innerCoverage"); SkString innerCoverageDecl("half innerCoverage");
if (kOval_ShapeFlag == fOpInfo.fInnerShapeTypes) { if (kOval_ShapeFlag == fOpInfo.fInnerShapeTypes) {
this->emitArc(f, fInnerEllipseCoords.fsIn(), fInnerEllipseName.fsIn(), this->emitArc(f, fInnerEllipseCoords.fsIn(), fInnerEllipseName.fsIn(),
true /*ellipseCoordsNeedClamp*/, true /*ellipseCoordsMayBeNegative*/, true /*ellipseCoordsNeedClamp*/, true /*ellipseCoordsMayBeNegative*/,
@ -978,12 +984,12 @@ void GLSLInstanceProcessor::BackendCoverage::onEmitCode(GrGLSLVertexBuilder* v,
this->emitInnerRect(f, innerCoverageDecl.c_str()); this->emitInnerRect(f, innerCoverageDecl.c_str());
} else { } else {
f->codeAppendf("%s = 0.0;", innerCoverageDecl.c_str()); f->codeAppendf("%s = 0.0;", innerCoverageDecl.c_str());
f->codeAppendf("mediump float2 distanceToArcEdge = abs(%s) - %s.xy;", f->codeAppendf("half2 distanceToArcEdge = abs(%s) - %s.xy;",
fInnerShapeCoords.fsIn(), fInnerRRect.fsIn()); fInnerShapeCoords.fsIn(), fInnerRRect.fsIn());
f->codeAppend ("if (any(lessThan(distanceToArcEdge, float2(1e-5)))) {"); f->codeAppend ("if (any(lessThan(distanceToArcEdge, half2(1e-5)))) {");
this->emitInnerRect(f, "innerCoverage"); this->emitInnerRect(f, "innerCoverage");
f->codeAppend ("} else {"); f->codeAppend ("} else {");
f->codeAppendf( "mediump float2 ellipseCoords = distanceToArcEdge * %s.zw;", f->codeAppendf( "half2 ellipseCoords = distanceToArcEdge * %s.zw;",
fInnerRRect.fsIn()); fInnerRRect.fsIn());
this->emitArc(f, "ellipseCoords", fInnerEllipseName.fsIn(), this->emitArc(f, "ellipseCoords", fInnerEllipseName.fsIn(),
false /*ellipseCoordsNeedClamp*/, false /*ellipseCoordsNeedClamp*/,
@ -991,9 +997,9 @@ void GLSLInstanceProcessor::BackendCoverage::onEmitCode(GrGLSLVertexBuilder* v,
f->codeAppend ("}"); f->codeAppend ("}");
} }
} }
f->codeAppendf("%s = float4(max(coverage - innerCoverage, 0.0));", outCoverage); f->codeAppendf("%s = half4(max(coverage - innerCoverage, 0.0));", outCoverage);
} else if (!fTweakAlphaForCoverage) { } else if (!fTweakAlphaForCoverage) {
f->codeAppendf("%s = float4(coverage);", outCoverage); f->codeAppendf("%s = half4(coverage);", outCoverage);
} }
} }
@ -1016,7 +1022,7 @@ void GLSLInstanceProcessor::BackendCoverage::emitCircle(GrGLSLPPFragmentBuilder*
const char* outCoverage) { const char* outCoverage) {
// TODO: circleCoords = max(circleCoords, 0) if we decide to do this optimization on rrects. // TODO: circleCoords = max(circleCoords, 0) if we decide to do this optimization on rrects.
SkASSERT(!(kRRect_ShapesMask & fOpInfo.fShapeTypes)); SkASSERT(!(kRRect_ShapesMask & fOpInfo.fShapeTypes));
f->codeAppendf("mediump float distanceToEdge = %s - length(%s);", f->codeAppendf("half distanceToEdge = %s - length(%s);",
fBloatedRadius.fsIn(), fEllipseCoords.fsIn()); fBloatedRadius.fsIn(), fEllipseCoords.fsIn());
f->codeAppendf("%s = clamp(distanceToEdge, 0.0, 1.0);", outCoverage); f->codeAppendf("%s = clamp(distanceToEdge, 0.0, 1.0);", outCoverage);
} }
@ -1033,27 +1039,27 @@ void GLSLInstanceProcessor::BackendCoverage::emitArc(GrGLSLPPFragmentBuilder* f,
// - To restrict the arcs of rounded rects to their positive quadrants. // - To restrict the arcs of rounded rects to their positive quadrants.
// - To avoid inversesqrt(0) in the ellipse formula. // - To avoid inversesqrt(0) in the ellipse formula.
if (ellipseCoordsMayBeNegative) { if (ellipseCoordsMayBeNegative) {
f->codeAppendf("mediump float2 ellipseClampedCoords = max(abs(%s), float2(1e-4));", f->codeAppendf("half2 ellipseClampedCoords = max(abs(%s), half2(1e-4));",
ellipseCoords); ellipseCoords);
} else { } else {
f->codeAppendf("mediump float2 ellipseClampedCoords = max(%s, float2(1e-4));", f->codeAppendf("half2 ellipseClampedCoords = max(%s, half2(1e-4));",
ellipseCoords); ellipseCoords);
} }
ellipseCoords = "ellipseClampedCoords"; ellipseCoords = "ellipseClampedCoords";
} }
// ellipseCoords are in pixel space and ellipseName is 1 / rx^2, 1 / ry^2. // ellipseCoords are in pixel space and ellipseName is 1 / rx^2, 1 / ry^2.
f->codeAppendf("highp float2 Z = %s * %s;", ellipseCoords, ellipseName); f->codeAppendf("highfloat2 Z = %s * %s;", ellipseCoords, ellipseName);
// implicit is the evaluation of (x/rx)^2 + (y/ry)^2 - 1. // implicit is the evaluation of (x/rx)^2 + (y/ry)^2 - 1.
f->codeAppendf("highp float implicit = dot(Z, %s) - 1.0;", ellipseCoords); f->codeAppendf("highfloat implicit = dot(Z, %s) - 1.0;", ellipseCoords);
// gradDot is the squared length of the gradient of the implicit. // gradDot is the squared length of the gradient of the implicit.
f->codeAppendf("highp float gradDot = 4.0 * dot(Z, Z);"); f->codeAppendf("highfloat gradDot = 4.0 * dot(Z, Z);");
f->codeAppend ("mediump float approxDist = implicit * inversesqrt(gradDot);"); f->codeAppend ("half approxDist = implicit * inversesqrt(gradDot);");
f->codeAppendf("%s = clamp(0.5 - approxDist, 0.0, 1.0);", outCoverage); f->codeAppendf("%s = clamp(0.5 - approxDist, 0.0, 1.0);", outCoverage);
} }
void GLSLInstanceProcessor::BackendCoverage::emitInnerRect(GrGLSLPPFragmentBuilder* f, void GLSLInstanceProcessor::BackendCoverage::emitInnerRect(GrGLSLPPFragmentBuilder* f,
const char* outCoverage) { const char* outCoverage) {
f->codeAppendf("lowp float2 c = %s - abs(%s);", f->codeAppendf("half2 c = %s - abs(%s);",
fInnerShapeBloatedHalfSize.fsIn(), fDistanceToInnerEdge.fsIn()); fInnerShapeBloatedHalfSize.fsIn(), fDistanceToInnerEdge.fsIn());
f->codeAppendf("%s = clamp(min(c.x, c.y), 0.0, 1.0);", outCoverage); f->codeAppendf("%s = clamp(min(c.x, c.y), 0.0, 1.0);", outCoverage);
} }
@ -1065,15 +1071,15 @@ public:
BackendMultisample(OpInfo opInfo, const VertexInputs& inputs, int effectiveSampleCnt) BackendMultisample(OpInfo opInfo, const VertexInputs& inputs, int effectiveSampleCnt)
: INHERITED(opInfo, inputs) : INHERITED(opInfo, inputs)
, fEffectiveSampleCnt(effectiveSampleCnt) , fEffectiveSampleCnt(effectiveSampleCnt)
, fShapeCoords(kVec2f_GrSLType) , fShapeCoords(kHalf2_GrSLType)
, fShapeInverseMatrix(kMat22f_GrSLType) , fShapeInverseMatrix(kHalf2x2_GrSLType)
, fFragShapeHalfSpan(kVec2f_GrSLType) , fFragShapeHalfSpan(kHalf2_GrSLType)
, fArcTest(kVec2f_GrSLType) , fArcTest(kHalf2_GrSLType)
, fArcInverseMatrix(kMat22f_GrSLType) , fArcInverseMatrix(kHalf2x2_GrSLType)
, fFragArcHalfSpan(kVec2f_GrSLType) , fFragArcHalfSpan(kHalf2_GrSLType)
, fEarlyAccept(kInt_GrSLType) , fEarlyAccept(kInt_GrSLType)
, fInnerShapeInverseMatrix(kMat22f_GrSLType) , fInnerShapeInverseMatrix(kHalf2x2_GrSLType)
, fFragInnerShapeHalfSpan(kVec2f_GrSLType) { , fFragInnerShapeHalfSpan(kHalf2_GrSLType) {
fRectTrianglesMaySplit = fOpInfo.fHasPerspective; fRectTrianglesMaySplit = fOpInfo.fHasPerspective;
fNeedsNeighborRadii = this->isMixedSampled() && !fOpInfo.fHasPerspective; fNeedsNeighborRadii = this->isMixedSampled() && !fOpInfo.fHasPerspective;
} }
@ -1181,9 +1187,9 @@ void GLSLInstanceProcessor::BackendMultisample::onInit(GrGLSLVaryingHandler* var
} }
} }
if (!fOpInfo.fHasPerspective) { if (!fOpInfo.fHasPerspective) {
v->codeAppend("float2x2 shapeInverseMatrix = inverse(float2x2(shapeMatrix));"); v->codeAppend("half2x2 shapeInverseMatrix = inverse(half2x2(shapeMatrix));");
v->codeAppend("float2 fragShapeSpan = abs(float4(shapeInverseMatrix).xz) + " v->codeAppend("half2 fragShapeSpan = abs(half4(shapeInverseMatrix).xz) + "
"abs(float4(shapeInverseMatrix).yw);"); "abs(half4(shapeInverseMatrix).yw);");
} }
} }
@ -1199,7 +1205,7 @@ void GLSLInstanceProcessor::BackendMultisample::setupRect(GrGLSLVertexBuilder* v
} }
if (fArcTest.vsOut()) { if (fArcTest.vsOut()) {
// Pick a value that is not > 0. // Pick a value that is not > 0.
v->codeAppendf("%s = float2(0);", fArcTest.vsOut()); v->codeAppendf("%s = highfloat2(0);", fArcTest.vsOut());
} }
if (fTriangleIsArc.vsOut()) { if (fTriangleIsArc.vsOut()) {
v->codeAppendf("%s = 0;", fTriangleIsArc.vsOut()); v->codeAppendf("%s = 0;", fTriangleIsArc.vsOut());
@ -1212,8 +1218,8 @@ void GLSLInstanceProcessor::BackendMultisample::setupRect(GrGLSLVertexBuilder* v
void GLSLInstanceProcessor::BackendMultisample::setupOval(GrGLSLVertexBuilder* v) { void GLSLInstanceProcessor::BackendMultisample::setupOval(GrGLSLVertexBuilder* v) {
v->codeAppendf("%s = abs(%s);", fArcCoords.vsOut(), this->outShapeCoords()); v->codeAppendf("%s = abs(%s);", fArcCoords.vsOut(), this->outShapeCoords());
if (fArcInverseMatrix.vsOut()) { if (fArcInverseMatrix.vsOut()) {
v->codeAppendf("float2 s = sign(%s);", this->outShapeCoords()); v->codeAppendf("half2 s = sign(%s);", this->outShapeCoords());
v->codeAppendf("%s = shapeInverseMatrix * float2x2(s.x, 0, 0 , s.y);", v->codeAppendf("%s = shapeInverseMatrix * half2x2(s.x, 0, 0 , s.y);",
fArcInverseMatrix.vsOut()); fArcInverseMatrix.vsOut());
} }
if (fFragArcHalfSpan.vsOut()) { if (fFragArcHalfSpan.vsOut()) {
@ -1221,7 +1227,7 @@ void GLSLInstanceProcessor::BackendMultisample::setupOval(GrGLSLVertexBuilder* v
} }
if (fArcTest.vsOut()) { if (fArcTest.vsOut()) {
// Pick a value that is > 0. // Pick a value that is > 0.
v->codeAppendf("%s = float2(1);", fArcTest.vsOut()); v->codeAppendf("%s = half2(1);", fArcTest.vsOut());
} }
if (fTriangleIsArc.vsOut()) { if (fTriangleIsArc.vsOut()) {
if (!this->isMixedSampled()) { if (!this->isMixedSampled()) {
@ -1247,13 +1253,13 @@ void GLSLInstanceProcessor::BackendMultisample::adjustRRectVertices(GrGLSLVertex
// For the mixed samples algorithm it's best to bloat the corner triangles a bit so that // For the mixed samples algorithm it's best to bloat the corner triangles a bit so that
// more of the pixels that cross into the arc region are completely inside the shared edges. // more of the pixels that cross into the arc region are completely inside the shared edges.
// We also snap to a regular rect if the radii shrink smaller than a pixel. // We also snap to a regular rect if the radii shrink smaller than a pixel.
v->codeAppend ("float2 midpt = 0.5 * (neighborRadii - radii);"); v->codeAppend ("half2 midpt = 0.5 * (neighborRadii - radii);");
v->codeAppend ("float2 cornerSize = any(lessThan(radii, fragShapeSpan)) ? " v->codeAppend ("half2 cornerSize = any(lessThan(radii, fragShapeSpan)) ? "
"float2(0) : min(radii + 0.5 * fragShapeSpan, 1.0 - midpt);"); "half2(0) : min(radii + 0.5 * fragShapeSpan, 1.0 - midpt);");
} else { } else {
// TODO: We could still bloat the corner triangle in the perspective case; we would just // TODO: We could still bloat the corner triangle in the perspective case; we would just
// need to find the screen-space derivative of shape coords at this particular point. // need to find the screen-space derivative of shape coords at this particular point.
v->codeAppend ("float2 cornerSize = any(lessThan(radii, float2(1e-3))) ? float2(0) : radii;"); v->codeAppend ("half2 cornerSize = any(lessThan(radii, half2(1e-3))) ? half2(0) : radii;");
} }
v->codeAppendf("if (abs(%s.x) == 0.5)" v->codeAppendf("if (abs(%s.x) == 0.5)"
@ -1275,12 +1281,12 @@ void GLSLInstanceProcessor::BackendMultisample::onSetupRRect(GrGLSLVertexBuilder
v->codeAppendf("%s = 0.5 * fragShapeSpan;", fFragShapeHalfSpan.vsOut()); v->codeAppendf("%s = 0.5 * fragShapeSpan;", fFragShapeHalfSpan.vsOut());
} }
if (fArcInverseMatrix.vsOut()) { if (fArcInverseMatrix.vsOut()) {
v->codeAppend ("float2 s = cornerSign / radii;"); v->codeAppend ("half2 s = cornerSign / radii;");
v->codeAppendf("%s = shapeInverseMatrix * float2x2(s.x, 0, 0, s.y);", v->codeAppendf("%s = shapeInverseMatrix * half2x2(s.x, 0, 0, s.y);",
fArcInverseMatrix.vsOut()); fArcInverseMatrix.vsOut());
} }
if (fFragArcHalfSpan.vsOut()) { if (fFragArcHalfSpan.vsOut()) {
v->codeAppendf("%s = 0.5 * (abs(float4(%s).xz) + abs(float4(%s).yw));", v->codeAppendf("%s = 0.5 * (abs(half4(%s).xz) + abs(half4(%s).yw));",
fFragArcHalfSpan.vsOut(), fArcInverseMatrix.vsOut(), fFragArcHalfSpan.vsOut(), fArcInverseMatrix.vsOut(),
fArcInverseMatrix.vsOut()); fArcInverseMatrix.vsOut());
} }
@ -1289,8 +1295,8 @@ void GLSLInstanceProcessor::BackendMultisample::onSetupRRect(GrGLSLVertexBuilder
// edges of a fan triangle to a point within that triangle. fArcTest is used to check if a // edges of a fan triangle to a point within that triangle. fArcTest is used to check if a
// fragment is too close to either shared edge, in which case we point sample the shape as a // fragment is too close to either shared edge, in which case we point sample the shape as a
// rect at that point in order to guarantee the mixed samples discard logic works correctly. // rect at that point in order to guarantee the mixed samples discard logic works correctly.
v->codeAppendf("%s = (cornerSize == float2(0)) ? float2(0) : " v->codeAppendf("%s = (cornerSize == half2(0)) ? half2(0) : "
"cornerSign * %s * float2x2(1, cornerSize.x - 1.0, cornerSize.y - 1.0, 1);", "cornerSign * %s * half2x2(1, cornerSize.x - 1.0, cornerSize.y - 1.0, 1);",
fArcTest.vsOut(), fModifiedShapeCoords); fArcTest.vsOut(), fModifiedShapeCoords);
if (!fOpInfo.fHasPerspective) { if (!fOpInfo.fHasPerspective) {
// Shift the point at which distances to edges are measured from the center of the pixel // Shift the point at which distances to edges are measured from the center of the pixel
@ -1303,7 +1309,7 @@ void GLSLInstanceProcessor::BackendMultisample::onSetupRRect(GrGLSLVertexBuilder
} }
if (fEarlyAccept.vsOut()) { if (fEarlyAccept.vsOut()) {
SkASSERT(this->isMixedSampled()); SkASSERT(this->isMixedSampled());
v->codeAppendf("%s = all(equal(float2(1), abs(%s))) ? 0 : SAMPLE_MASK_ALL;", v->codeAppendf("%s = all(equal(half2(1), abs(%s))) ? 0 : SAMPLE_MASK_ALL;",
fEarlyAccept.vsOut(), fInputs.attr(Attrib::kShapeCoords)); fEarlyAccept.vsOut(), fInputs.attr(Attrib::kShapeCoords));
} }
} }
@ -1319,7 +1325,7 @@ GLSLInstanceProcessor::BackendMultisample::onInitInnerShape(GrGLSLVaryingHandler
if (!fOpInfo.fHasPerspective) { if (!fOpInfo.fHasPerspective) {
varyingHandler->addFlatVarying("innerShapeInverseMatrix", &fInnerShapeInverseMatrix, varyingHandler->addFlatVarying("innerShapeInverseMatrix", &fInnerShapeInverseMatrix,
kHigh_GrSLPrecision); kHigh_GrSLPrecision);
v->codeAppendf("%s = shapeInverseMatrix * float2x2(outer2Inner.x, 0, 0, outer2Inner.y);", v->codeAppendf("%s = shapeInverseMatrix * highfloat2x2(outer2Inner.x, 0, 0, outer2Inner.y);",
fInnerShapeInverseMatrix.vsOut()); fInnerShapeInverseMatrix.vsOut());
varyingHandler->addFlatVarying("fragInnerShapeHalfSpan", &fFragInnerShapeHalfSpan, varyingHandler->addFlatVarying("fragInnerShapeHalfSpan", &fFragInnerShapeHalfSpan,
kHigh_GrSLPrecision); kHigh_GrSLPrecision);
@ -1333,14 +1339,14 @@ void GLSLInstanceProcessor::BackendMultisample::setupInnerRect(GrGLSLVertexBuild
// The fragment shader will generalize every inner shape as a round rect. Since this one // The fragment shader will generalize every inner shape as a round rect. Since this one
// is a rect, we simply emit bogus parameters for the round rect (negative radii) that // is a rect, we simply emit bogus parameters for the round rect (negative radii) that
// ensure the fragment shader always takes the "sample as rect" codepath. // ensure the fragment shader always takes the "sample as rect" codepath.
v->codeAppendf("%s = float4(2.0 * (inner.zw - inner.xy) / (outer.zw - outer.xy), float2(0));", v->codeAppendf("%s = half4(2.0 * (inner.zw - inner.xy) / (outer.zw - outer.xy), half2(0));",
fInnerRRect.vsOut()); fInnerRRect.vsOut());
} }
} }
void GLSLInstanceProcessor::BackendMultisample::setupInnerOval(GrGLSLVertexBuilder* v) { void GLSLInstanceProcessor::BackendMultisample::setupInnerOval(GrGLSLVertexBuilder* v) {
if (fInnerRRect.vsOut()) { if (fInnerRRect.vsOut()) {
v->codeAppendf("%s = float4(0, 0, 1, 1);", fInnerRRect.vsOut()); v->codeAppendf("%s = half4(0, 0, 1, 1);", fInnerRRect.vsOut());
} }
} }
@ -1349,9 +1355,9 @@ void GLSLInstanceProcessor::BackendMultisample::onSetupInnerSimpleRRect(GrGLSLVe
if (fFragInnerShapeHalfSpan.vsOut()) { if (fFragInnerShapeHalfSpan.vsOut()) {
v->codeAppendf("innerRadii = max(innerRadii, 2e-1 * %s);", fFragInnerShapeHalfSpan.vsOut()); v->codeAppendf("innerRadii = max(innerRadii, 2e-1 * %s);", fFragInnerShapeHalfSpan.vsOut());
} else { } else {
v->codeAppend ("innerRadii = max(innerRadii, float2(1e-4));"); v->codeAppend ("innerRadii = max(innerRadii, half2(1e-4));");
} }
v->codeAppendf("%s = float4(1.0 - innerRadii, 1.0 / innerRadii);", fInnerRRect.vsOut()); v->codeAppendf("%s = half4(1.0 - innerRadii, 1.0 / innerRadii);", fInnerRRect.vsOut());
} }
void GLSLInstanceProcessor::BackendMultisample::onEmitCode(GrGLSLVertexBuilder*, void GLSLInstanceProcessor::BackendMultisample::onEmitCode(GrGLSLVertexBuilder*,
@ -1364,8 +1370,8 @@ void GLSLInstanceProcessor::BackendMultisample::onEmitCode(GrGLSLVertexBuilder*,
} }
if (kRect_ShapeFlag != (fOpInfo.fShapeTypes | fOpInfo.fInnerShapeTypes)) { if (kRect_ShapeFlag != (fOpInfo.fShapeTypes | fOpInfo.fInnerShapeTypes)) {
GrShaderVar x("x", kVec2f_GrSLType, GrShaderVar::kNonArray, kHigh_GrSLPrecision); GrShaderVar x("x", kHighFloat2_GrSLType, GrShaderVar::kNonArray);
f->emitFunction(kFloat_GrSLType, "square", 1, &x, "return dot(x, x);", &fSquareFun); f->emitFunction(kHalf_GrSLType, "square", 1, &x, "return dot(x, x);", &fSquareFun);
} }
EmitShapeCoords shapeCoords; EmitShapeCoords shapeCoords;
@ -1387,7 +1393,7 @@ void GLSLInstanceProcessor::BackendMultisample::onEmitCode(GrGLSLVertexBuilder*,
if (fOpInfo.fHasPerspective && fOpInfo.fInnerShapeTypes) { if (fOpInfo.fHasPerspective && fOpInfo.fInnerShapeTypes) {
// This determines if the fragment should consider the inner shape in its sample mask. // This determines if the fragment should consider the inner shape in its sample mask.
// We take the derivative early in case discards may occur before we get to the inner shape. // We take the derivative early in case discards may occur before we get to the inner shape.
f->codeAppendf("highp float2 fragInnerShapeApproxHalfSpan = 0.5 * fwidth(%s);", f->codeAppendf("highfloat2 fragInnerShapeApproxHalfSpan = 0.5 * fwidth(%s);",
fInnerShapeCoords.fsIn()); fInnerShapeCoords.fsIn());
} }
@ -1404,7 +1410,7 @@ void GLSLInstanceProcessor::BackendMultisample::onEmitCode(GrGLSLVertexBuilder*,
if (arcTest && fOpInfo.fHasPerspective) { if (arcTest && fOpInfo.fHasPerspective) {
// The non-perspective version accounts for fwidth() in the vertex shader. // The non-perspective version accounts for fwidth() in the vertex shader.
// We make sure to take the derivative here, before a neighbor pixel may early accept. // We make sure to take the derivative here, before a neighbor pixel may early accept.
f->codeAppendf("highp float2 arcTest = %s - 0.5 * fwidth(%s);", f->codeAppendf("highfloat2 arcTest = %s - 0.5 * fwidth(%s);",
fArcTest.fsIn(), fArcTest.fsIn()); fArcTest.fsIn(), fArcTest.fsIn());
arcTest = "arcTest"; arcTest = "arcTest";
} }
@ -1415,7 +1421,7 @@ void GLSLInstanceProcessor::BackendMultisample::onEmitCode(GrGLSLVertexBuilder*,
if (arcTest) { if (arcTest) {
// At this point, if the sample mask is all set it means we are inside an arc triangle. // At this point, if the sample mask is all set it means we are inside an arc triangle.
f->codeAppendf("if (gl_SampleMaskIn[0] == SAMPLE_MASK_ALL || " f->codeAppendf("if (gl_SampleMaskIn[0] == SAMPLE_MASK_ALL || "
"all(greaterThan(%s, float2(0)))) {", arcTest); "all(greaterThan(%s, highfloat2(0)))) {", arcTest);
this->emitArc(f, arcCoords, false, clampArcCoords, opts); this->emitArc(f, arcCoords, false, clampArcCoords, opts);
f->codeAppend ("} else {"); f->codeAppend ("} else {");
this->emitRect(f, shapeCoords, opts); this->emitRect(f, shapeCoords, opts);
@ -1488,10 +1494,10 @@ void GLSLInstanceProcessor::BackendMultisample::emitRect(GrGLSLPPFragmentBuilder
} }
f->codeAppend ("int rectMask = 0;"); f->codeAppend ("int rectMask = 0;");
f->codeAppend ("for (int i = 0; i < SAMPLE_COUNT; i++) {"); f->codeAppend ("for (int i = 0; i < SAMPLE_COUNT; i++) {");
f->codeAppend ( "highp float2 pt = "); f->codeAppend ( "highfloat2 pt = ");
this->interpolateAtSample(f, *coords.fVarying, "i", coords.fInverseMatrix); this->interpolateAtSample(f, *coords.fVarying, "i", coords.fInverseMatrix);
f->codeAppend ( ";"); f->codeAppend ( ";");
f->codeAppend ( "if (all(lessThan(abs(pt), float2(1)))) rectMask |= (1 << i);"); f->codeAppend ( "if (all(lessThan(abs(pt), highfloat2(1)))) rectMask |= (1 << i);");
f->codeAppend ("}"); f->codeAppend ("}");
this->acceptCoverageMask(f, "rectMask", opts); this->acceptCoverageMask(f, "rectMask", opts);
if (coords.fFragHalfSpan) { if (coords.fFragHalfSpan) {
@ -1507,7 +1513,7 @@ void GLSLInstanceProcessor::BackendMultisample::emitArc(GrGLSLPPFragmentBuilder*
SkString absArcCoords; SkString absArcCoords;
absArcCoords.printf(coordsMayBeNegative ? "abs(%s)" : "%s", coords.fVarying->fsIn()); absArcCoords.printf(coordsMayBeNegative ? "abs(%s)" : "%s", coords.fVarying->fsIn());
if (clampCoords) { if (clampCoords) {
f->codeAppendf("if (%s(max(%s + %s, float2(0))) < 1.0) {", f->codeAppendf("if (%s(max(%s + %s, half2(0))) < 1.0) {",
fSquareFun.c_str(), absArcCoords.c_str(), coords.fFragHalfSpan); fSquareFun.c_str(), absArcCoords.c_str(), coords.fFragHalfSpan);
} else { } else {
f->codeAppendf("if (%s(%s + %s) < 1.0) {", f->codeAppendf("if (%s(%s + %s) < 1.0) {",
@ -1515,7 +1521,7 @@ void GLSLInstanceProcessor::BackendMultisample::emitArc(GrGLSLPPFragmentBuilder*
} }
// The entire pixel is inside the arc. // The entire pixel is inside the arc.
this->acceptOrRejectWholeFragment(f, true, opts); this->acceptOrRejectWholeFragment(f, true, opts);
f->codeAppendf("} else if (%s(max(%s - %s, float2(0))) >= 1.0) {", f->codeAppendf("} else if (%s(max(%s - %s, half2(0))) >= 1.0) {",
fSquareFun.c_str(), absArcCoords.c_str(), coords.fFragHalfSpan); fSquareFun.c_str(), absArcCoords.c_str(), coords.fFragHalfSpan);
// The entire pixel is outside the arc. // The entire pixel is outside the arc.
this->acceptOrRejectWholeFragment(f, false, opts); this->acceptOrRejectWholeFragment(f, false, opts);
@ -1523,12 +1529,12 @@ void GLSLInstanceProcessor::BackendMultisample::emitArc(GrGLSLPPFragmentBuilder*
} }
f->codeAppend ( "int arcMask = 0;"); f->codeAppend ( "int arcMask = 0;");
f->codeAppend ( "for (int i = 0; i < SAMPLE_COUNT; i++) {"); f->codeAppend ( "for (int i = 0; i < SAMPLE_COUNT; i++) {");
f->codeAppend ( "highp float2 pt = "); f->codeAppend ( "highfloat2 pt = ");
this->interpolateAtSample(f, *coords.fVarying, "i", coords.fInverseMatrix); this->interpolateAtSample(f, *coords.fVarying, "i", coords.fInverseMatrix);
f->codeAppend ( ";"); f->codeAppend ( ";");
if (clampCoords) { if (clampCoords) {
SkASSERT(!coordsMayBeNegative); SkASSERT(!coordsMayBeNegative);
f->codeAppend ( "pt = max(pt, float2(0));"); f->codeAppend ( "pt = max(pt, highfloat2(0));");
} }
f->codeAppendf( "if (%s(pt) < 1.0) arcMask |= (1 << i);", fSquareFun.c_str()); f->codeAppendf( "if (%s(pt) < 1.0) arcMask |= (1 << i);", fSquareFun.c_str());
f->codeAppend ( "}"); f->codeAppend ( "}");
@ -1542,31 +1548,31 @@ void GLSLInstanceProcessor::BackendMultisample::emitSimpleRRect(GrGLSLPPFragment
const EmitShapeCoords& coords, const EmitShapeCoords& coords,
const char* rrect, const char* rrect,
const EmitShapeOpts& opts) { const EmitShapeOpts& opts) {
f->codeAppendf("highp float2 distanceToArcEdge = abs(%s) - %s.xy;", coords.fVarying->fsIn(), f->codeAppendf("highfloat2 distanceToArcEdge = abs(%s) - %s.xy;", coords.fVarying->fsIn(),
rrect); rrect);
f->codeAppend ("if (any(lessThan(distanceToArcEdge, float2(0)))) {"); f->codeAppend ("if (any(lessThan(distanceToArcEdge, highfloat2(0)))) {");
this->emitRect(f, coords, opts); this->emitRect(f, coords, opts);
f->codeAppend ("} else {"); f->codeAppend ("} else {");
if (coords.fInverseMatrix && coords.fFragHalfSpan) { if (coords.fInverseMatrix && coords.fFragHalfSpan) {
f->codeAppendf("highp float2 rrectCoords = distanceToArcEdge * %s.zw;", rrect); f->codeAppendf("highfloat2 rrectCoords = distanceToArcEdge * %s.zw;", rrect);
f->codeAppendf("highp float2 fragRRectHalfSpan = %s * %s.zw;", coords.fFragHalfSpan, rrect); f->codeAppendf("highfloat2 fragRRectHalfSpan = %s * %s.zw;", coords.fFragHalfSpan, rrect);
f->codeAppendf("if (%s(rrectCoords + fragRRectHalfSpan) <= 1.0) {", fSquareFun.c_str()); f->codeAppendf("if (%s(rrectCoords + fragRRectHalfSpan) <= 1.0) {", fSquareFun.c_str());
// The entire pixel is inside the round rect. // The entire pixel is inside the round rect.
this->acceptOrRejectWholeFragment(f, true, opts); this->acceptOrRejectWholeFragment(f, true, opts);
f->codeAppendf("} else if (%s(max(rrectCoords - fragRRectHalfSpan, float2(0))) >= 1.0) {", f->codeAppendf("} else if (%s(max(rrectCoords - fragRRectHalfSpan, highfloat2(0))) >= 1.0) {",
fSquareFun.c_str()); fSquareFun.c_str());
// The entire pixel is outside the round rect. // The entire pixel is outside the round rect.
this->acceptOrRejectWholeFragment(f, false, opts); this->acceptOrRejectWholeFragment(f, false, opts);
f->codeAppend ("} else {"); f->codeAppend ("} else {");
f->codeAppendf( "highp float2 s = %s.zw * sign(%s);", rrect, coords.fVarying->fsIn()); f->codeAppendf( "highfloat2 s = %s.zw * sign(%s);", rrect, coords.fVarying->fsIn());
f->codeAppendf( "highp float2x2 innerRRectInverseMatrix = %s * " f->codeAppendf( "highfloat2x2 innerRRectInverseMatrix = %s * "
"float2x2(s.x, 0, 0, s.y);", coords.fInverseMatrix); "highfloat2x2(s.x, 0, 0, s.y);", coords.fInverseMatrix);
f->codeAppend ( "highp int rrectMask = 0;"); f->codeAppend ( "highp int rrectMask = 0;");
f->codeAppend ( "for (int i = 0; i < SAMPLE_COUNT; i++) {"); f->codeAppend ( "for (int i = 0; i < SAMPLE_COUNT; i++) {");
f->codeAppend ( "highp float2 pt = rrectCoords + "); f->codeAppend ( "highfloat2 pt = rrectCoords + ");
f->appendOffsetToSample("i", GrGLSLFPFragmentBuilder::kSkiaDevice_Coordinates); f->appendOffsetToSample("i", GrGLSLFPFragmentBuilder::kSkiaDevice_Coordinates);
f->codeAppend ( "* innerRRectInverseMatrix;"); f->codeAppend ( "* innerRRectInverseMatrix;");
f->codeAppendf( "if (%s(max(pt, float2(0))) < 1.0) rrectMask |= (1 << i);", f->codeAppendf( "if (%s(max(pt, highfloat2(0))) < 1.0) rrectMask |= (1 << i);",
fSquareFun.c_str()); fSquareFun.c_str());
f->codeAppend ( "}"); f->codeAppend ( "}");
this->acceptCoverageMask(f, "rrectMask", opts); this->acceptCoverageMask(f, "rrectMask", opts);
@ -1574,10 +1580,10 @@ void GLSLInstanceProcessor::BackendMultisample::emitSimpleRRect(GrGLSLPPFragment
} else { } else {
f->codeAppend ("int rrectMask = 0;"); f->codeAppend ("int rrectMask = 0;");
f->codeAppend ("for (int i = 0; i < SAMPLE_COUNT; i++) {"); f->codeAppend ("for (int i = 0; i < SAMPLE_COUNT; i++) {");
f->codeAppend ( "highp float2 shapePt = "); f->codeAppend ( "highfloat2 shapePt = ");
this->interpolateAtSample(f, *coords.fVarying, "i", nullptr); this->interpolateAtSample(f, *coords.fVarying, "i", nullptr);
f->codeAppend ( ";"); f->codeAppend ( ";");
f->codeAppendf( "highp float2 rrectPt = max(abs(shapePt) - %s.xy, float2(0)) * %s.zw;", f->codeAppendf( "highfloat2 rrectPt = max(abs(shapePt) - %s.xy, highfloat2(0)) * %s.zw;",
rrect, rrect); rrect, rrect);
f->codeAppendf( "if (%s(rrectPt) < 1.0) rrectMask |= (1 << i);", fSquareFun.c_str()); f->codeAppendf( "if (%s(rrectPt) < 1.0) rrectMask |= (1 << i);", fSquareFun.c_str());
f->codeAppend ("}"); f->codeAppend ("}");

View File

@ -564,7 +564,7 @@ public:
// emit attributes // emit attributes
varyingHandler->emitAttributes(qe); varyingHandler->emitAttributes(qe);
GrGLSLVertToFrag v(kVec4f_GrSLType); GrGLSLVertToFrag v(kHalf4_GrSLType);
varyingHandler->addVarying("QuadEdge", &v); varyingHandler->addVarying("QuadEdge", &v);
vertBuilder->codeAppendf("%s = %s;", v.vsOut(), qe.fInQuadEdge->fName); vertBuilder->codeAppendf("%s = %s;", v.vsOut(), qe.fInQuadEdge->fName);
@ -585,17 +585,17 @@ public:
qe.fLocalMatrix, qe.fLocalMatrix,
args.fFPCoordTransformHandler); args.fFPCoordTransformHandler);
fragBuilder->codeAppendf("float edgeAlpha;"); fragBuilder->codeAppendf("half edgeAlpha;");
// keep the derivative instructions outside the conditional // keep the derivative instructions outside the conditional
fragBuilder->codeAppendf("float2 duvdx = dFdx(%s.xy);", v.fsIn()); fragBuilder->codeAppendf("half2 duvdx = dFdx(%s.xy);", v.fsIn());
fragBuilder->codeAppendf("float2 duvdy = dFdy(%s.xy);", v.fsIn()); fragBuilder->codeAppendf("half2 duvdy = dFdy(%s.xy);", v.fsIn());
fragBuilder->codeAppendf("if (%s.z > 0.0 && %s.w > 0.0) {", v.fsIn(), v.fsIn()); fragBuilder->codeAppendf("if (%s.z > 0.0 && %s.w > 0.0) {", v.fsIn(), v.fsIn());
// today we know z and w are in device space. We could use derivatives // today we know z and w are in device space. We could use derivatives
fragBuilder->codeAppendf("edgeAlpha = min(min(%s.z, %s.w) + 0.5, 1.0);", v.fsIn(), fragBuilder->codeAppendf("edgeAlpha = min(min(%s.z, %s.w) + 0.5, 1.0);", v.fsIn(),
v.fsIn()); v.fsIn());
fragBuilder->codeAppendf ("} else {"); fragBuilder->codeAppendf ("} else {");
fragBuilder->codeAppendf("float2 gF = float2(2.0*%s.x*duvdx.x - duvdx.y," fragBuilder->codeAppendf("half2 gF = half2(2.0*%s.x*duvdx.x - duvdx.y,"
" 2.0*%s.x*duvdy.x - duvdy.y);", " 2.0*%s.x*duvdy.x - duvdy.y);",
v.fsIn(), v.fsIn()); v.fsIn(), v.fsIn());
fragBuilder->codeAppendf("edgeAlpha = (%s.x*%s.x - %s.y);", v.fsIn(), v.fsIn(), fragBuilder->codeAppendf("edgeAlpha = (%s.x*%s.x - %s.y);", v.fsIn(), v.fsIn(),
@ -603,7 +603,7 @@ public:
fragBuilder->codeAppendf("edgeAlpha = " fragBuilder->codeAppendf("edgeAlpha = "
"clamp(0.5 - edgeAlpha / length(gF), 0.0, 1.0);}"); "clamp(0.5 - edgeAlpha / length(gF), 0.0, 1.0);}");
fragBuilder->codeAppendf("%s = float4(edgeAlpha);", args.fOutputCoverage); fragBuilder->codeAppendf("%s = half4(edgeAlpha);", args.fOutputCoverage);
} }
static inline void GenKey(const GrGeometryProcessor& gp, static inline void GenKey(const GrGeometryProcessor& gp,

View File

@ -887,12 +887,12 @@ void GLDashingCircleEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
varyingHandler->emitAttributes(dce); varyingHandler->emitAttributes(dce);
// XY are dashPos, Z is dashInterval // XY are dashPos, Z is dashInterval
GrGLSLVertToFrag dashParams(kVec3f_GrSLType); GrGLSLVertToFrag dashParams(kHalf3_GrSLType);
varyingHandler->addVarying("DashParam", &dashParams); varyingHandler->addVarying("DashParam", &dashParams);
vertBuilder->codeAppendf("%s = %s;", dashParams.vsOut(), dce.inDashParams()->fName); vertBuilder->codeAppendf("%s = %s;", dashParams.vsOut(), dce.inDashParams()->fName);
// x refers to circle radius - 0.5, y refers to cicle's center x coord // x refers to circle radius - 0.5, y refers to cicle's center x coord
GrGLSLVertToFrag circleParams(kVec2f_GrSLType); GrGLSLVertToFrag circleParams(kHalf2_GrSLType);
varyingHandler->addVarying("CircleParams", &circleParams); varyingHandler->addVarying("CircleParams", &circleParams);
vertBuilder->codeAppendf("%s = %s;", circleParams.vsOut(), dce.inCircleParams()->fName); vertBuilder->codeAppendf("%s = %s;", circleParams.vsOut(), dce.inCircleParams()->fName);
@ -913,21 +913,21 @@ void GLDashingCircleEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
args.fFPCoordTransformHandler); args.fFPCoordTransformHandler);
// transforms all points so that we can compare them to our test circle // transforms all points so that we can compare them to our test circle
fragBuilder->codeAppendf("float xShifted = %s.x - floor(%s.x / %s.z) * %s.z;", fragBuilder->codeAppendf("half xShifted = %s.x - floor(%s.x / %s.z) * %s.z;",
dashParams.fsIn(), dashParams.fsIn(), dashParams.fsIn(), dashParams.fsIn(), dashParams.fsIn(), dashParams.fsIn(),
dashParams.fsIn()); dashParams.fsIn());
fragBuilder->codeAppendf("float2 fragPosShifted = float2(xShifted, %s.y);", dashParams.fsIn()); fragBuilder->codeAppendf("half2 fragPosShifted = half2(xShifted, %s.y);", dashParams.fsIn());
fragBuilder->codeAppendf("float2 center = float2(%s.y, 0.0);", circleParams.fsIn()); fragBuilder->codeAppendf("half2 center = half2(%s.y, 0.0);", circleParams.fsIn());
fragBuilder->codeAppend("float dist = length(center - fragPosShifted);"); fragBuilder->codeAppend("half dist = length(center - fragPosShifted);");
if (dce.aaMode() != AAMode::kNone) { if (dce.aaMode() != AAMode::kNone) {
fragBuilder->codeAppendf("float diff = dist - %s.x;", circleParams.fsIn()); fragBuilder->codeAppendf("half diff = dist - %s.x;", circleParams.fsIn());
fragBuilder->codeAppend("diff = 1.0 - diff;"); fragBuilder->codeAppend("diff = 1.0 - diff;");
fragBuilder->codeAppend("float alpha = clamp(diff, 0.0, 1.0);"); fragBuilder->codeAppend("half alpha = clamp(diff, 0.0, 1.0);");
} else { } else {
fragBuilder->codeAppendf("float alpha = 1.0;"); fragBuilder->codeAppendf("half alpha = 1.0;");
fragBuilder->codeAppendf("alpha *= dist < %s.x + 0.5 ? 1.0 : 0.0;", circleParams.fsIn()); fragBuilder->codeAppendf("alpha *= dist < %s.x + 0.5 ? 1.0 : 0.0;", circleParams.fsIn());
} }
fragBuilder->codeAppendf("%s = float4(alpha);", args.fOutputCoverage); fragBuilder->codeAppendf("%s = half4(alpha);", args.fOutputCoverage);
} }
void GLDashingCircleEffect::setData(const GrGLSLProgramDataManager& pdman, void GLDashingCircleEffect::setData(const GrGLSLProgramDataManager& pdman,
@ -1090,13 +1090,13 @@ void GLDashingLineEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
varyingHandler->emitAttributes(de); varyingHandler->emitAttributes(de);
// XY refers to dashPos, Z is the dash interval length // XY refers to dashPos, Z is the dash interval length
GrGLSLVertToFrag inDashParams(kVec3f_GrSLType); GrGLSLVertToFrag inDashParams(kHighFloat3_GrSLType);
varyingHandler->addVarying("DashParams", &inDashParams, GrSLPrecision::kHigh_GrSLPrecision); varyingHandler->addVarying("DashParams", &inDashParams, GrSLPrecision::kHigh_GrSLPrecision);
vertBuilder->codeAppendf("%s = %s;", inDashParams.vsOut(), de.inDashParams()->fName); vertBuilder->codeAppendf("%s = %s;", inDashParams.vsOut(), de.inDashParams()->fName);
// The rect uniform's xyzw refer to (left + 0.5, top + 0.5, right - 0.5, bottom - 0.5), // The rect uniform's xyzw refer to (left + 0.5, top + 0.5, right - 0.5, bottom - 0.5),
// respectively. // respectively.
GrGLSLVertToFrag inRectParams(kVec4f_GrSLType); GrGLSLVertToFrag inRectParams(kHighFloat4_GrSLType);
varyingHandler->addVarying("RectParams", &inRectParams, GrSLPrecision::kHigh_GrSLPrecision); varyingHandler->addVarying("RectParams", &inRectParams, GrSLPrecision::kHigh_GrSLPrecision);
vertBuilder->codeAppendf("%s = %s;", inRectParams.vsOut(), de.inRectParams()->fName); vertBuilder->codeAppendf("%s = %s;", inRectParams.vsOut(), de.inRectParams()->fName);
@ -1117,14 +1117,14 @@ void GLDashingLineEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
args.fFPCoordTransformHandler); args.fFPCoordTransformHandler);
// transforms all points so that we can compare them to our test rect // transforms all points so that we can compare them to our test rect
fragBuilder->codeAppendf("float xShifted = %s.x - floor(%s.x / %s.z) * %s.z;", fragBuilder->codeAppendf("half xShifted = %s.x - floor(%s.x / %s.z) * %s.z;",
inDashParams.fsIn(), inDashParams.fsIn(), inDashParams.fsIn(), inDashParams.fsIn(), inDashParams.fsIn(), inDashParams.fsIn(),
inDashParams.fsIn()); inDashParams.fsIn());
fragBuilder->codeAppendf("float2 fragPosShifted = float2(xShifted, %s.y);", inDashParams.fsIn()); fragBuilder->codeAppendf("half2 fragPosShifted = half2(xShifted, %s.y);", inDashParams.fsIn());
if (de.aaMode() == AAMode::kCoverage) { if (de.aaMode() == AAMode::kCoverage) {
// The amount of coverage removed in x and y by the edges is computed as a pair of negative // The amount of coverage removed in x and y by the edges is computed as a pair of negative
// numbers, xSub and ySub. // numbers, xSub and ySub.
fragBuilder->codeAppend("float xSub, ySub;"); fragBuilder->codeAppend("half xSub, ySub;");
fragBuilder->codeAppendf("xSub = min(fragPosShifted.x - %s.x, 0.0);", inRectParams.fsIn()); fragBuilder->codeAppendf("xSub = min(fragPosShifted.x - %s.x, 0.0);", inRectParams.fsIn());
fragBuilder->codeAppendf("xSub += min(%s.z - fragPosShifted.x, 0.0);", inRectParams.fsIn()); fragBuilder->codeAppendf("xSub += min(%s.z - fragPosShifted.x, 0.0);", inRectParams.fsIn());
fragBuilder->codeAppendf("ySub = min(fragPosShifted.y - %s.y, 0.0);", inRectParams.fsIn()); fragBuilder->codeAppendf("ySub = min(fragPosShifted.y - %s.y, 0.0);", inRectParams.fsIn());
@ -1132,24 +1132,24 @@ void GLDashingLineEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
// Now compute coverage in x and y and multiply them to get the fraction of the pixel // Now compute coverage in x and y and multiply them to get the fraction of the pixel
// covered. // covered.
fragBuilder->codeAppendf( fragBuilder->codeAppendf(
"float alpha = (1.0 + max(xSub, -1.0)) * (1.0 + max(ySub, -1.0));"); "half alpha = (1.0 + max(xSub, -1.0)) * (1.0 + max(ySub, -1.0));");
} else if (de.aaMode() == AAMode::kCoverageWithMSAA) { } else if (de.aaMode() == AAMode::kCoverageWithMSAA) {
// For MSAA, we don't modulate the alpha by the Y distance, since MSAA coverage will handle // For MSAA, we don't modulate the alpha by the Y distance, since MSAA coverage will handle
// AA on the the top and bottom edges. The shader is only responsible for intra-dash alpha. // AA on the the top and bottom edges. The shader is only responsible for intra-dash alpha.
fragBuilder->codeAppend("float xSub;"); fragBuilder->codeAppend("half xSub;");
fragBuilder->codeAppendf("xSub = min(fragPosShifted.x - %s.x, 0.0);", inRectParams.fsIn()); fragBuilder->codeAppendf("xSub = min(fragPosShifted.x - %s.x, 0.0);", inRectParams.fsIn());
fragBuilder->codeAppendf("xSub += min(%s.z - fragPosShifted.x, 0.0);", inRectParams.fsIn()); fragBuilder->codeAppendf("xSub += min(%s.z - fragPosShifted.x, 0.0);", inRectParams.fsIn());
// Now compute coverage in x to get the fraction of the pixel covered. // Now compute coverage in x to get the fraction of the pixel covered.
fragBuilder->codeAppendf("float alpha = (1.0 + max(xSub, -1.0));"); fragBuilder->codeAppendf("half alpha = (1.0 + max(xSub, -1.0));");
} else { } else {
// Assuming the bounding geometry is tight so no need to check y values // Assuming the bounding geometry is tight so no need to check y values
fragBuilder->codeAppendf("float alpha = 1.0;"); fragBuilder->codeAppendf("half alpha = 1.0;");
fragBuilder->codeAppendf("alpha *= (fragPosShifted.x - %s.x) > -0.5 ? 1.0 : 0.0;", fragBuilder->codeAppendf("alpha *= (fragPosShifted.x - %s.x) > -0.5 ? 1.0 : 0.0;",
inRectParams.fsIn()); inRectParams.fsIn());
fragBuilder->codeAppendf("alpha *= (%s.z - fragPosShifted.x) >= -0.5 ? 1.0 : 0.0;", fragBuilder->codeAppendf("alpha *= (%s.z - fragPosShifted.x) >= -0.5 ? 1.0 : 0.0;",
inRectParams.fsIn()); inRectParams.fsIn());
} }
fragBuilder->codeAppendf("%s = float4(alpha);", args.fOutputCoverage); fragBuilder->codeAppendf("%s = half4(alpha);", args.fOutputCoverage);
} }
void GLDashingLineEffect::setData(const GrGLSLProgramDataManager& pdman, void GLDashingLineEffect::setData(const GrGLSLProgramDataManager& pdman,

View File

@ -140,7 +140,7 @@ public:
varyingHandler->emitAttributes(qp); varyingHandler->emitAttributes(qp);
varyingHandler->addPassThroughAttribute(qp.inColor(), args.fOutputColor); varyingHandler->addPassThroughAttribute(qp.inColor(), args.fOutputColor);
GrGLSLVertToFrag uv(kVec2f_GrSLType); GrGLSLVertToFrag uv(kHighFloat2_GrSLType);
varyingHandler->addVarying("uv", &uv, kHigh_GrSLPrecision); varyingHandler->addVarying("uv", &uv, kHigh_GrSLPrecision);
vsBuilder->codeAppendf("%s = %s;", uv.vsOut(), qp.inUV()->fName); vsBuilder->codeAppendf("%s = %s;", uv.vsOut(), qp.inUV()->fName);
@ -156,7 +156,7 @@ public:
GrGLSLPPFragmentBuilder* fsBuilder = args.fFragBuilder; GrGLSLPPFragmentBuilder* fsBuilder = args.fFragBuilder;
fsBuilder->codeAppendf("if (%s.x * %s.x >= %s.y) discard;", uv.fsIn(), uv.fsIn(), fsBuilder->codeAppendf("if (%s.x * %s.x >= %s.y) discard;", uv.fsIn(), uv.fsIn(),
uv.fsIn()); uv.fsIn());
fsBuilder->codeAppendf("%s = float4(1.0);", args.fOutputCoverage); fsBuilder->codeAppendf("%s = half4(1.0);", args.fOutputCoverage);
} }
static inline void GenKey(const GrGeometryProcessor& gp, static inline void GenKey(const GrGeometryProcessor& gp,

View File

@ -119,21 +119,21 @@ private:
// emit attributes // emit attributes
varyingHandler->emitAttributes(cgp); varyingHandler->emitAttributes(cgp);
fragBuilder->codeAppend("highp float4 circleEdge;"); fragBuilder->codeAppend("highfloat4 circleEdge;");
varyingHandler->addPassThroughAttribute(cgp.fInCircleEdge, "circleEdge", varyingHandler->addPassThroughAttribute(cgp.fInCircleEdge, "circleEdge",
kHigh_GrSLPrecision); kHigh_GrSLPrecision);
if (cgp.fInClipPlane) { if (cgp.fInClipPlane) {
fragBuilder->codeAppend("float3 clipPlane;"); fragBuilder->codeAppend("half3 clipPlane;");
varyingHandler->addPassThroughAttribute(cgp.fInClipPlane, "clipPlane"); varyingHandler->addPassThroughAttribute(cgp.fInClipPlane, "clipPlane");
} }
if (cgp.fInIsectPlane) { if (cgp.fInIsectPlane) {
SkASSERT(cgp.fInClipPlane); SkASSERT(cgp.fInClipPlane);
fragBuilder->codeAppend("float3 isectPlane;"); fragBuilder->codeAppend("half3 isectPlane;");
varyingHandler->addPassThroughAttribute(cgp.fInIsectPlane, "isectPlane"); varyingHandler->addPassThroughAttribute(cgp.fInIsectPlane, "isectPlane");
} }
if (cgp.fInUnionPlane) { if (cgp.fInUnionPlane) {
SkASSERT(cgp.fInClipPlane); SkASSERT(cgp.fInClipPlane);
fragBuilder->codeAppend("float3 unionPlane;"); fragBuilder->codeAppend("half3 unionPlane;");
varyingHandler->addPassThroughAttribute(cgp.fInUnionPlane, "unionPlane"); varyingHandler->addPassThroughAttribute(cgp.fInUnionPlane, "unionPlane");
} }
@ -152,19 +152,19 @@ private:
cgp.fLocalMatrix, cgp.fLocalMatrix,
args.fFPCoordTransformHandler); args.fFPCoordTransformHandler);
fragBuilder->codeAppend("highp float d = length(circleEdge.xy);"); fragBuilder->codeAppend("highfloat d = length(circleEdge.xy);");
fragBuilder->codeAppend("float distanceToOuterEdge = circleEdge.z * (1.0 - d);"); fragBuilder->codeAppend("half distanceToOuterEdge = circleEdge.z * (1.0 - d);");
fragBuilder->codeAppend("float edgeAlpha = clamp(distanceToOuterEdge, 0.0, 1.0);"); fragBuilder->codeAppend("half edgeAlpha = clamp(distanceToOuterEdge, 0.0, 1.0);");
if (cgp.fStroke) { if (cgp.fStroke) {
fragBuilder->codeAppend( fragBuilder->codeAppend(
"float distanceToInnerEdge = circleEdge.z * (d - circleEdge.w);"); "half distanceToInnerEdge = circleEdge.z * (d - circleEdge.w);");
fragBuilder->codeAppend("float innerAlpha = clamp(distanceToInnerEdge, 0.0, 1.0);"); fragBuilder->codeAppend("half innerAlpha = clamp(distanceToInnerEdge, 0.0, 1.0);");
fragBuilder->codeAppend("edgeAlpha *= innerAlpha;"); fragBuilder->codeAppend("edgeAlpha *= innerAlpha;");
} }
if (cgp.fInClipPlane) { if (cgp.fInClipPlane) {
fragBuilder->codeAppend( fragBuilder->codeAppend(
"float clip = clamp(circleEdge.z * dot(circleEdge.xy, clipPlane.xy) + " "half clip = clamp(circleEdge.z * dot(circleEdge.xy, clipPlane.xy) + "
"clipPlane.z, 0.0, 1.0);"); "clipPlane.z, 0.0, 1.0);");
if (cgp.fInIsectPlane) { if (cgp.fInIsectPlane) {
fragBuilder->codeAppend( fragBuilder->codeAppend(
@ -178,7 +178,7 @@ private:
} }
fragBuilder->codeAppend("edgeAlpha *= clip;"); fragBuilder->codeAppend("edgeAlpha *= clip;");
} }
fragBuilder->codeAppendf("%s = float4(edgeAlpha);", args.fOutputCoverage); fragBuilder->codeAppendf("%s = half4(edgeAlpha);", args.fOutputCoverage);
} }
static void GenKey(const GrGeometryProcessor& gp, static void GenKey(const GrGeometryProcessor& gp,
@ -275,12 +275,12 @@ private:
// emit attributes // emit attributes
varyingHandler->emitAttributes(egp); varyingHandler->emitAttributes(egp);
GrGLSLVertToFrag ellipseOffsets(kVec2f_GrSLType); GrGLSLVertToFrag ellipseOffsets(kHalf2_GrSLType);
varyingHandler->addVarying("EllipseOffsets", &ellipseOffsets); varyingHandler->addVarying("EllipseOffsets", &ellipseOffsets);
vertBuilder->codeAppendf("%s = %s;", ellipseOffsets.vsOut(), vertBuilder->codeAppendf("%s = %s;", ellipseOffsets.vsOut(),
egp.fInEllipseOffset->fName); egp.fInEllipseOffset->fName);
GrGLSLVertToFrag ellipseRadii(kVec4f_GrSLType); GrGLSLVertToFrag ellipseRadii(kHalf4_GrSLType);
varyingHandler->addVarying("EllipseRadii", &ellipseRadii); varyingHandler->addVarying("EllipseRadii", &ellipseRadii);
vertBuilder->codeAppendf("%s = %s;", ellipseRadii.vsOut(), egp.fInEllipseRadii->fName); vertBuilder->codeAppendf("%s = %s;", ellipseRadii.vsOut(), egp.fInEllipseRadii->fName);
@ -301,16 +301,16 @@ private:
args.fFPCoordTransformHandler); args.fFPCoordTransformHandler);
// for outer curve // for outer curve
fragBuilder->codeAppendf("float2 scaledOffset = %s*%s.xy;", ellipseOffsets.fsIn(), fragBuilder->codeAppendf("half2 scaledOffset = %s*%s.xy;", ellipseOffsets.fsIn(),
ellipseRadii.fsIn()); ellipseRadii.fsIn());
fragBuilder->codeAppend("float test = dot(scaledOffset, scaledOffset) - 1.0;"); fragBuilder->codeAppend("half test = dot(scaledOffset, scaledOffset) - 1.0;");
fragBuilder->codeAppendf("float2 grad = 2.0*scaledOffset*%s.xy;", ellipseRadii.fsIn()); fragBuilder->codeAppendf("half2 grad = 2.0*scaledOffset*%s.xy;", ellipseRadii.fsIn());
fragBuilder->codeAppend("float grad_dot = dot(grad, grad);"); fragBuilder->codeAppend("half grad_dot = dot(grad, grad);");
// avoid calling inversesqrt on zero. // avoid calling inversesqrt on zero.
fragBuilder->codeAppend("grad_dot = max(grad_dot, 1.0e-4);"); fragBuilder->codeAppend("grad_dot = max(grad_dot, 1.0e-4);");
fragBuilder->codeAppend("float invlen = inversesqrt(grad_dot);"); fragBuilder->codeAppend("half invlen = inversesqrt(grad_dot);");
fragBuilder->codeAppend("float edgeAlpha = clamp(0.5-test*invlen, 0.0, 1.0);"); fragBuilder->codeAppend("half edgeAlpha = clamp(0.5-test*invlen, 0.0, 1.0);");
// for inner curve // for inner curve
if (egp.fStroke) { if (egp.fStroke) {
@ -322,7 +322,7 @@ private:
fragBuilder->codeAppend("edgeAlpha *= clamp(0.5+test*invlen, 0.0, 1.0);"); fragBuilder->codeAppend("edgeAlpha *= clamp(0.5+test*invlen, 0.0, 1.0);");
} }
fragBuilder->codeAppendf("%s = float4(edgeAlpha);", args.fOutputCoverage); fragBuilder->codeAppendf("%s = half4(edgeAlpha);", args.fOutputCoverage);
} }
static void GenKey(const GrGeometryProcessor& gp, static void GenKey(const GrGeometryProcessor& gp,
@ -417,11 +417,11 @@ private:
// emit attributes // emit attributes
varyingHandler->emitAttributes(diegp); varyingHandler->emitAttributes(diegp);
GrGLSLVertToFrag offsets0(kVec2f_GrSLType); GrGLSLVertToFrag offsets0(kHalf2_GrSLType);
varyingHandler->addVarying("EllipseOffsets0", &offsets0); varyingHandler->addVarying("EllipseOffsets0", &offsets0);
vertBuilder->codeAppendf("%s = %s;", offsets0.vsOut(), diegp.fInEllipseOffsets0->fName); vertBuilder->codeAppendf("%s = %s;", offsets0.vsOut(), diegp.fInEllipseOffsets0->fName);
GrGLSLVertToFrag offsets1(kVec2f_GrSLType); GrGLSLVertToFrag offsets1(kHalf2_GrSLType);
varyingHandler->addVarying("EllipseOffsets1", &offsets1); varyingHandler->addVarying("EllipseOffsets1", &offsets1);
vertBuilder->codeAppendf("%s = %s;", offsets1.vsOut(), diegp.fInEllipseOffsets1->fName); vertBuilder->codeAppendf("%s = %s;", offsets1.vsOut(), diegp.fInEllipseOffsets1->fName);
@ -445,25 +445,25 @@ private:
args.fFPCoordTransformHandler); args.fFPCoordTransformHandler);
// for outer curve // for outer curve
fragBuilder->codeAppendf("float2 scaledOffset = %s.xy;", offsets0.fsIn()); fragBuilder->codeAppendf("half2 scaledOffset = %s.xy;", offsets0.fsIn());
fragBuilder->codeAppend("float test = dot(scaledOffset, scaledOffset) - 1.0;"); fragBuilder->codeAppend("half test = dot(scaledOffset, scaledOffset) - 1.0;");
fragBuilder->codeAppendf("float2 duvdx = dFdx(%s);", offsets0.fsIn()); fragBuilder->codeAppendf("half2 duvdx = dFdx(%s);", offsets0.fsIn());
fragBuilder->codeAppendf("float2 duvdy = dFdy(%s);", offsets0.fsIn()); fragBuilder->codeAppendf("half2 duvdy = dFdy(%s);", offsets0.fsIn());
fragBuilder->codeAppendf( fragBuilder->codeAppendf(
"float2 grad = float2(2.0*%s.x*duvdx.x + 2.0*%s.y*duvdx.y," "half2 grad = half2(2.0*%s.x*duvdx.x + 2.0*%s.y*duvdx.y,"
" 2.0*%s.x*duvdy.x + 2.0*%s.y*duvdy.y);", " 2.0*%s.x*duvdy.x + 2.0*%s.y*duvdy.y);",
offsets0.fsIn(), offsets0.fsIn(), offsets0.fsIn(), offsets0.fsIn()); offsets0.fsIn(), offsets0.fsIn(), offsets0.fsIn(), offsets0.fsIn());
fragBuilder->codeAppend("float grad_dot = dot(grad, grad);"); fragBuilder->codeAppend("half grad_dot = dot(grad, grad);");
// avoid calling inversesqrt on zero. // avoid calling inversesqrt on zero.
fragBuilder->codeAppend("grad_dot = max(grad_dot, 1.0e-4);"); fragBuilder->codeAppend("grad_dot = max(grad_dot, 1.0e-4);");
fragBuilder->codeAppend("float invlen = inversesqrt(grad_dot);"); fragBuilder->codeAppend("half invlen = inversesqrt(grad_dot);");
if (DIEllipseStyle::kHairline == diegp.fStyle) { if (DIEllipseStyle::kHairline == diegp.fStyle) {
// can probably do this with one step // can probably do this with one step
fragBuilder->codeAppend("float edgeAlpha = clamp(1.0-test*invlen, 0.0, 1.0);"); fragBuilder->codeAppend("half edgeAlpha = clamp(1.0-test*invlen, 0.0, 1.0);");
fragBuilder->codeAppend("edgeAlpha *= clamp(1.0+test*invlen, 0.0, 1.0);"); fragBuilder->codeAppend("edgeAlpha *= clamp(1.0+test*invlen, 0.0, 1.0);");
} else { } else {
fragBuilder->codeAppend("float edgeAlpha = clamp(0.5-test*invlen, 0.0, 1.0);"); fragBuilder->codeAppend("half edgeAlpha = clamp(0.5-test*invlen, 0.0, 1.0);");
} }
// for inner curve // for inner curve
@ -473,14 +473,14 @@ private:
fragBuilder->codeAppendf("duvdx = dFdx(%s);", offsets1.fsIn()); fragBuilder->codeAppendf("duvdx = dFdx(%s);", offsets1.fsIn());
fragBuilder->codeAppendf("duvdy = dFdy(%s);", offsets1.fsIn()); fragBuilder->codeAppendf("duvdy = dFdy(%s);", offsets1.fsIn());
fragBuilder->codeAppendf( fragBuilder->codeAppendf(
"grad = float2(2.0*%s.x*duvdx.x + 2.0*%s.y*duvdx.y," "grad = half2(2.0*%s.x*duvdx.x + 2.0*%s.y*duvdx.y,"
" 2.0*%s.x*duvdy.x + 2.0*%s.y*duvdy.y);", " 2.0*%s.x*duvdy.x + 2.0*%s.y*duvdy.y);",
offsets1.fsIn(), offsets1.fsIn(), offsets1.fsIn(), offsets1.fsIn()); offsets1.fsIn(), offsets1.fsIn(), offsets1.fsIn(), offsets1.fsIn());
fragBuilder->codeAppend("invlen = inversesqrt(dot(grad, grad));"); fragBuilder->codeAppend("invlen = inversesqrt(dot(grad, grad));");
fragBuilder->codeAppend("edgeAlpha *= clamp(0.5+test*invlen, 0.0, 1.0);"); fragBuilder->codeAppend("edgeAlpha *= clamp(0.5+test*invlen, 0.0, 1.0);");
} }
fragBuilder->codeAppendf("%s = float4(edgeAlpha);", args.fOutputCoverage); fragBuilder->codeAppendf("%s = half4(edgeAlpha);", args.fOutputCoverage);
} }
static void GenKey(const GrGeometryProcessor& gp, static void GenKey(const GrGeometryProcessor& gp,

View File

@ -115,7 +115,7 @@ public:
args.fVaryingHandler->addPassThroughAttribute(&textureGP.fColors, args.fVaryingHandler->addPassThroughAttribute(&textureGP.fColors,
args.fOutputColor); args.fOutputColor);
} }
args.fFragBuilder->codeAppend("highp float2 texCoord;"); args.fFragBuilder->codeAppend("highfloat2 texCoord;");
args.fVaryingHandler->addPassThroughAttribute(&textureGP.fTextureCoords, "texCoord", args.fVaryingHandler->addPassThroughAttribute(&textureGP.fTextureCoords, "texCoord",
kHigh_GrSLPrecision); kHigh_GrSLPrecision);
if (textureGP.numTextureSamplers() > 1) { if (textureGP.numTextureSamplers() > 1) {
@ -134,7 +134,7 @@ public:
args.fFragBuilder->appendTextureLookupAndModulate(args.fOutputColor, args.fFragBuilder->appendTextureLookupAndModulate(args.fOutputColor,
args.fTexSamplers[i], args.fTexSamplers[i],
"texCoord", "texCoord",
kVec2f_GrSLType, kHighFloat2_GrSLType,
&fColorSpaceXformHelper); &fColorSpaceXformHelper);
args.fFragBuilder->codeAppend("; break;"); args.fFragBuilder->codeAppend("; break;");
} }
@ -144,11 +144,11 @@ public:
args.fFragBuilder->appendTextureLookupAndModulate(args.fOutputColor, args.fFragBuilder->appendTextureLookupAndModulate(args.fOutputColor,
args.fTexSamplers[0], args.fTexSamplers[0],
"texCoord", "texCoord",
kVec2f_GrSLType, kHighFloat2_GrSLType,
&fColorSpaceXformHelper); &fColorSpaceXformHelper);
} }
args.fFragBuilder->codeAppend(";"); args.fFragBuilder->codeAppend(";");
args.fFragBuilder->codeAppendf("%s = float4(1);", args.fOutputCoverage); args.fFragBuilder->codeAppendf("%s = highfloat4(1);", args.fOutputCoverage);
} }
GrGLSLColorSpaceXformHelper fColorSpaceXformHelper; GrGLSLColorSpaceXformHelper fColorSpaceXformHelper;
}; };

View File

@ -44,17 +44,17 @@ bool GrVkCopyManager::createCopyProgram(GrVkGpu* gpu) {
"#extension GL_ARB_shading_language_420pack : enable\n" "#extension GL_ARB_shading_language_420pack : enable\n"
"layout(set = 0, binding = 0) uniform vertexUniformBuffer {" "layout(set = 0, binding = 0) uniform vertexUniformBuffer {"
"mediump float4 uPosXform;" "half4 uPosXform;"
"mediump float4 uTexCoordXform;" "half4 uTexCoordXform;"
"};" "};"
"layout(location = 0) in highp float2 inPosition;" "layout(location = 0) in highfloat2 inPosition;"
"layout(location = 1) out mediump float2 vTexCoord;" "layout(location = 1) out half2 vTexCoord;"
"// Copy Program VS\n" "// Copy Program VS\n"
"void main() {" "void main() {"
"vTexCoord = inPosition * uTexCoordXform.xy + uTexCoordXform.zw;" "vTexCoord = inPosition * uTexCoordXform.xy + uTexCoordXform.zw;"
"gl_Position.xy = inPosition * uPosXform.xy + uPosXform.zw;" "gl_Position.xy = inPosition * uPosXform.xy + uPosXform.zw;"
"gl_Position.zw = float2(0, 1);" "gl_Position.zw = half2(0, 1);"
"}" "}"
); );
@ -63,11 +63,9 @@ bool GrVkCopyManager::createCopyProgram(GrVkGpu* gpu) {
"#extension GL_ARB_separate_shader_objects : enable\n" "#extension GL_ARB_separate_shader_objects : enable\n"
"#extension GL_ARB_shading_language_420pack : enable\n" "#extension GL_ARB_shading_language_420pack : enable\n"
"precision mediump float;" "layout(set = 1, binding = 0) uniform sampler2D uTextureSampler;"
"layout(location = 1) in half2 vTexCoord;"
"layout(set = 1, binding = 0) uniform mediump sampler2D uTextureSampler;" "layout(location = 0, index = 0) out half4 fsColorOut;"
"layout(location = 1) in mediump float2 vTexCoord;"
"layout(location = 0, index = 0) out mediump float4 fsColorOut;"
"// Copy Program FS\n" "// Copy Program FS\n"
"void main() {" "void main() {"

View File

@ -59,7 +59,7 @@ void* GrVkPipelineStateDataManager::getBufferPtrAndMarkDirty(const Uniform& uni)
void GrVkPipelineStateDataManager::set1i(UniformHandle u, int32_t i) const { void GrVkPipelineStateDataManager::set1i(UniformHandle u, int32_t i) const {
const Uniform& uni = fUniforms[u.toIndex()]; const Uniform& uni = fUniforms[u.toIndex()];
SkASSERT(uni.fType == kInt_GrSLType); SkASSERT(uni.fType == kInt_GrSLType || uni.fType == kShort_GrSLType);
SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount); SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
void* buffer = this->getBufferPtrAndMarkDirty(uni); void* buffer = this->getBufferPtrAndMarkDirty(uni);
memcpy(buffer, &i, sizeof(int32_t)); memcpy(buffer, &i, sizeof(int32_t));
@ -69,7 +69,7 @@ void GrVkPipelineStateDataManager::set1iv(UniformHandle u,
int arrayCount, int arrayCount,
const int32_t v[]) const { const int32_t v[]) const {
const Uniform& uni = fUniforms[u.toIndex()]; const Uniform& uni = fUniforms[u.toIndex()];
SkASSERT(uni.fType == kInt_GrSLType); SkASSERT(uni.fType == kInt_GrSLType || uni.fType == kShort_GrSLType);
SkASSERT(arrayCount > 0); SkASSERT(arrayCount > 0);
SkASSERT(arrayCount <= uni.fArrayCount || SkASSERT(arrayCount <= uni.fArrayCount ||
(1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount)); (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount));
@ -85,7 +85,7 @@ void GrVkPipelineStateDataManager::set1iv(UniformHandle u,
void GrVkPipelineStateDataManager::set1f(UniformHandle u, float v0) const { void GrVkPipelineStateDataManager::set1f(UniformHandle u, float v0) const {
const Uniform& uni = fUniforms[u.toIndex()]; const Uniform& uni = fUniforms[u.toIndex()];
SkASSERT(uni.fType == kFloat_GrSLType); SkASSERT(uni.fType == kHighFloat_GrSLType || uni.fType == kHalf_GrSLType);
SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount); SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
void* buffer = this->getBufferPtrAndMarkDirty(uni); void* buffer = this->getBufferPtrAndMarkDirty(uni);
SkASSERT(sizeof(float) == 4); SkASSERT(sizeof(float) == 4);
@ -96,7 +96,7 @@ void GrVkPipelineStateDataManager::set1fv(UniformHandle u,
int arrayCount, int arrayCount,
const float v[]) const { const float v[]) const {
const Uniform& uni = fUniforms[u.toIndex()]; const Uniform& uni = fUniforms[u.toIndex()];
SkASSERT(uni.fType == kFloat_GrSLType); SkASSERT(uni.fType == kHighFloat_GrSLType || uni.fType == kHalf_GrSLType);
SkASSERT(arrayCount > 0); SkASSERT(arrayCount > 0);
SkASSERT(arrayCount <= uni.fArrayCount || SkASSERT(arrayCount <= uni.fArrayCount ||
(1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount)); (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount));
@ -112,7 +112,7 @@ void GrVkPipelineStateDataManager::set1fv(UniformHandle u,
void GrVkPipelineStateDataManager::set2f(UniformHandle u, float v0, float v1) const { void GrVkPipelineStateDataManager::set2f(UniformHandle u, float v0, float v1) const {
const Uniform& uni = fUniforms[u.toIndex()]; const Uniform& uni = fUniforms[u.toIndex()];
SkASSERT(uni.fType == kVec2f_GrSLType); SkASSERT(uni.fType == kHighFloat2_GrSLType || uni.fType == kHalf2_GrSLType);
SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount); SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
void* buffer = this->getBufferPtrAndMarkDirty(uni); void* buffer = this->getBufferPtrAndMarkDirty(uni);
SkASSERT(sizeof(float) == 4); SkASSERT(sizeof(float) == 4);
@ -124,7 +124,7 @@ void GrVkPipelineStateDataManager::set2fv(UniformHandle u,
int arrayCount, int arrayCount,
const float v[]) const { const float v[]) const {
const Uniform& uni = fUniforms[u.toIndex()]; const Uniform& uni = fUniforms[u.toIndex()];
SkASSERT(uni.fType == kVec2f_GrSLType); SkASSERT(uni.fType == kHighFloat2_GrSLType || uni.fType == kHalf2_GrSLType);
SkASSERT(arrayCount > 0); SkASSERT(arrayCount > 0);
SkASSERT(arrayCount <= uni.fArrayCount || SkASSERT(arrayCount <= uni.fArrayCount ||
(1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount)); (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount));
@ -140,7 +140,7 @@ void GrVkPipelineStateDataManager::set2fv(UniformHandle u,
void GrVkPipelineStateDataManager::set3f(UniformHandle u, float v0, float v1, float v2) const { void GrVkPipelineStateDataManager::set3f(UniformHandle u, float v0, float v1, float v2) const {
const Uniform& uni = fUniforms[u.toIndex()]; const Uniform& uni = fUniforms[u.toIndex()];
SkASSERT(uni.fType == kVec3f_GrSLType); SkASSERT(uni.fType == kHighFloat3_GrSLType || uni.fType == kHalf3_GrSLType);
SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount); SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
void* buffer = this->getBufferPtrAndMarkDirty(uni); void* buffer = this->getBufferPtrAndMarkDirty(uni);
SkASSERT(sizeof(float) == 4); SkASSERT(sizeof(float) == 4);
@ -152,7 +152,7 @@ void GrVkPipelineStateDataManager::set3fv(UniformHandle u,
int arrayCount, int arrayCount,
const float v[]) const { const float v[]) const {
const Uniform& uni = fUniforms[u.toIndex()]; const Uniform& uni = fUniforms[u.toIndex()];
SkASSERT(uni.fType == kVec3f_GrSLType); SkASSERT(uni.fType == kHighFloat3_GrSLType || uni.fType == kHalf3_GrSLType);
SkASSERT(arrayCount > 0); SkASSERT(arrayCount > 0);
SkASSERT(arrayCount <= uni.fArrayCount || SkASSERT(arrayCount <= uni.fArrayCount ||
(1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount)); (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount));
@ -172,7 +172,7 @@ void GrVkPipelineStateDataManager::set4f(UniformHandle u,
float v2, float v2,
float v3) const { float v3) const {
const Uniform& uni = fUniforms[u.toIndex()]; const Uniform& uni = fUniforms[u.toIndex()];
SkASSERT(uni.fType == kVec4f_GrSLType); SkASSERT(uni.fType == kHighFloat4_GrSLType || uni.fType == kHalf4_GrSLType);
SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount); SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
void* buffer = this->getBufferPtrAndMarkDirty(uni); void* buffer = this->getBufferPtrAndMarkDirty(uni);
SkASSERT(sizeof(float) == 4); SkASSERT(sizeof(float) == 4);
@ -184,7 +184,7 @@ void GrVkPipelineStateDataManager::set4fv(UniformHandle u,
int arrayCount, int arrayCount,
const float v[]) const { const float v[]) const {
const Uniform& uni = fUniforms[u.toIndex()]; const Uniform& uni = fUniforms[u.toIndex()];
SkASSERT(uni.fType == kVec4f_GrSLType); SkASSERT(uni.fType == kHighFloat4_GrSLType || uni.fType == kHalf4_GrSLType);
SkASSERT(arrayCount > 0); SkASSERT(arrayCount > 0);
SkASSERT(arrayCount <= uni.fArrayCount || SkASSERT(arrayCount <= uni.fArrayCount ||
(1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount)); (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount));
@ -230,7 +230,8 @@ template<int N> inline void GrVkPipelineStateDataManager::setMatrices(UniformHan
int arrayCount, int arrayCount,
const float matrices[]) const { const float matrices[]) const {
const Uniform& uni = fUniforms[u.toIndex()]; const Uniform& uni = fUniforms[u.toIndex()];
SkASSERT(uni.fType == kMat22f_GrSLType + (N - 2)); SkASSERT(uni.fType == kHighFloat2x2_GrSLType + (N - 2) ||
uni.fType == kHalf2x2_GrSLType + (N - 2));
SkASSERT(arrayCount > 0); SkASSERT(arrayCount > 0);
SkASSERT(arrayCount <= uni.fArrayCount || SkASSERT(arrayCount <= uni.fArrayCount ||
(1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount)); (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount));

View File

@ -16,31 +16,40 @@
// aligned to 16 bytes (i.e. has mask of 0xF). // aligned to 16 bytes (i.e. has mask of 0xF).
uint32_t grsltype_to_alignment_mask(GrSLType type) { uint32_t grsltype_to_alignment_mask(GrSLType type) {
switch(type) { switch(type) {
case kShort_GrSLType: // fall through
case kInt_GrSLType: case kInt_GrSLType:
return 0x3; return 0x3;
case kUShort_GrSLType: // fall through
case kUint_GrSLType: case kUint_GrSLType:
return 0x3; return 0x3;
case kFloat_GrSLType: case kHalf_GrSLType: // fall through
case kHighFloat_GrSLType:
return 0x3; return 0x3;
case kVec2f_GrSLType: case kHalf2_GrSLType: // fall through
case kHighFloat2_GrSLType:
return 0x7; return 0x7;
case kVec3f_GrSLType: case kHalf3_GrSLType: // fall through
case kHighFloat3_GrSLType:
return 0xF; return 0xF;
case kVec4f_GrSLType: case kHalf4_GrSLType: // fall through
case kHighFloat4_GrSLType:
return 0xF; return 0xF;
case kVec2us_GrSLType: case kUint2_GrSLType:
return 0x3; return 0x3;
case kVec2i_GrSLType: case kInt2_GrSLType:
return 0x7; return 0x7;
case kVec3i_GrSLType: case kInt3_GrSLType:
return 0xF; return 0xF;
case kVec4i_GrSLType: case kInt4_GrSLType:
return 0xF; return 0xF;
case kMat22f_GrSLType: case kHalf2x2_GrSLType: // fall through
case kHighFloat2x2_GrSLType:
return 0x7; return 0x7;
case kMat33f_GrSLType: case kHalf3x3_GrSLType: // fall through
case kHighFloat3x3_GrSLType:
return 0xF; return 0xF;
case kMat44f_GrSLType: case kHalf4x4_GrSLType: // fall through
case kHighFloat4x4_GrSLType:
return 0xF; return 0xF;
// This query is only valid for certain types. // This query is only valid for certain types.
@ -66,32 +75,41 @@ uint32_t grsltype_to_alignment_mask(GrSLType type) {
so a float2x2 takes up 8 floats. */ so a float2x2 takes up 8 floats. */
static inline uint32_t grsltype_to_vk_size(GrSLType type) { static inline uint32_t grsltype_to_vk_size(GrSLType type) {
switch(type) { switch(type) {
case kShort_GrSLType: // fall through
case kInt_GrSLType: case kInt_GrSLType:
return sizeof(int32_t); return sizeof(int32_t);
case kUShort_GrSLType: // fall through
case kUint_GrSLType: case kUint_GrSLType:
return sizeof(int32_t); return sizeof(int32_t);
case kFloat_GrSLType: case kHalf_GrSLType: // fall through
case kHighFloat_GrSLType:
return sizeof(float); return sizeof(float);
case kVec2f_GrSLType: case kHalf2_GrSLType: // fall through
case kHighFloat2_GrSLType:
return 2 * sizeof(float); return 2 * sizeof(float);
case kVec3f_GrSLType: case kHalf3_GrSLType: // fall through
case kHighFloat3_GrSLType:
return 3 * sizeof(float); return 3 * sizeof(float);
case kVec4f_GrSLType: case kHalf4_GrSLType: // fall through
case kHighFloat4_GrSLType:
return 4 * sizeof(float); return 4 * sizeof(float);
case kVec2us_GrSLType: case kUint2_GrSLType:
return 2 * sizeof(uint16_t); return 2 * sizeof(uint16_t);
case kVec2i_GrSLType: case kInt2_GrSLType:
return 2 * sizeof(int32_t); return 2 * sizeof(int32_t);
case kVec3i_GrSLType: case kInt3_GrSLType:
return 3 * sizeof(int32_t); return 3 * sizeof(int32_t);
case kVec4i_GrSLType: case kInt4_GrSLType:
return 4 * sizeof(int32_t); return 4 * sizeof(int32_t);
case kMat22f_GrSLType: case kHalf2x2_GrSLType: // fall through
case kHighFloat2x2_GrSLType:
//TODO: this will be 4 * szof(float) on std430. //TODO: this will be 4 * szof(float) on std430.
return 8 * sizeof(float); return 8 * sizeof(float);
case kMat33f_GrSLType: case kHalf3x3_GrSLType: // fall through
case kHighFloat3x3_GrSLType:
return 12 * sizeof(float); return 12 * sizeof(float);
case kMat44f_GrSLType: case kHalf4x4_GrSLType: // fall through
case kHighFloat4x4_GrSLType:
return 16 * sizeof(float); return 16 * sizeof(float);
// This query is only valid for certain types. // This query is only valid for certain types.
@ -122,7 +140,7 @@ void get_ubo_aligned_offset(uint32_t* uniformOffset,
int arrayCount) { int arrayCount) {
uint32_t alignmentMask = grsltype_to_alignment_mask(type); uint32_t alignmentMask = grsltype_to_alignment_mask(type);
// We want to use the std140 layout here, so we must make arrays align to 16 bytes. // We want to use the std140 layout here, so we must make arrays align to 16 bytes.
if (arrayCount || type == kMat22f_GrSLType) { if (arrayCount || type == kHighFloat2x2_GrSLType) {
alignmentMask = 0xF; alignmentMask = 0xF;
} }
uint32_t offsetDiff = *currentOffset & alignmentMask; uint32_t offsetDiff = *currentOffset & alignmentMask;

View File

@ -13,27 +13,34 @@ static inline int grsltype_to_location_size(GrSLType type) {
switch(type) { switch(type) {
case kVoid_GrSLType: case kVoid_GrSLType:
return 0; return 0;
case kFloat_GrSLType: case kHighFloat_GrSLType: // fall through
case kHalf_GrSLType:
return 1; return 1;
case kVec2f_GrSLType: case kHighFloat2_GrSLType: // fall through
case kHalf2_GrSLType:
return 1; return 1;
case kVec3f_GrSLType: case kHighFloat3_GrSLType:
case kHalf3_GrSLType:
return 1; return 1;
case kVec4f_GrSLType: case kHighFloat4_GrSLType:
case kHalf4_GrSLType:
return 1; return 1;
case kVec2us_GrSLType: case kUint2_GrSLType:
return 1; return 1;
case kVec2i_GrSLType: case kInt2_GrSLType:
return 1; return 1;
case kVec3i_GrSLType: case kInt3_GrSLType:
return 1; return 1;
case kVec4i_GrSLType: case kInt4_GrSLType:
return 1; return 1;
case kMat22f_GrSLType: case kHighFloat2x2_GrSLType:
case kHalf2x2_GrSLType:
return 2; return 2;
case kMat33f_GrSLType: case kHighFloat3x3_GrSLType:
case kHalf3x3_GrSLType:
return 3; return 3;
case kMat44f_GrSLType: case kHighFloat4x4_GrSLType:
case kHalf4x4_GrSLType:
return 4; return 4;
case kTexture2DSampler_GrSLType: case kTexture2DSampler_GrSLType:
return 0; return 0;
@ -47,9 +54,11 @@ static inline int grsltype_to_location_size(GrSLType type) {
return 0; return 0;
case kBool_GrSLType: case kBool_GrSLType:
return 1; return 1;
case kInt_GrSLType: case kInt_GrSLType: // fall through
case kShort_GrSLType:
return 1; return 1;
case kUint_GrSLType: case kUint_GrSLType:
case kUShort_GrSLType: // fall through
return 1; return 1;
case kTexture2D_GrSLType: case kTexture2D_GrSLType:
return 0; return 0;

View File

@ -816,15 +816,13 @@ void GrGLPerlinNoise::emitCode(EmitArgs& args) {
GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
SkString vCoords = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]); SkString vCoords = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
fBaseFrequencyUni = uniformHandler->addUniform(kFragment_GrShaderFlag, fBaseFrequencyUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType,
kVec2f_GrSLType, kDefault_GrSLPrecision,
"baseFrequency"); "baseFrequency");
const char* baseFrequencyUni = uniformHandler->getUniformCStr(fBaseFrequencyUni); const char* baseFrequencyUni = uniformHandler->getUniformCStr(fBaseFrequencyUni);
const char* stitchDataUni = nullptr; const char* stitchDataUni = nullptr;
if (pne.stitchTiles()) { if (pne.stitchTiles()) {
fStitchDataUni = uniformHandler->addUniform(kFragment_GrShaderFlag, fStitchDataUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType,
kVec2f_GrSLType, kDefault_GrSLPrecision,
"stitchData"); "stitchData");
stitchDataUni = uniformHandler->getUniformCStr(fStitchDataUni); stitchDataUni = uniformHandler->getUniformCStr(fStitchDataUni);
} }
@ -849,29 +847,29 @@ void GrGLPerlinNoise::emitCode(EmitArgs& args) {
const char* inc8bit = "0.00390625"; // 1.0 / 256.0 const char* inc8bit = "0.00390625"; // 1.0 / 256.0
// This is the math to convert the two 16bit integer packed into rgba 8 bit input into a // This is the math to convert the two 16bit integer packed into rgba 8 bit input into a
// [-1,1] vector and perform a dot product between that vector and the provided vector. // [-1,1] vector and perform a dot product between that vector and the provided vector.
const char* dotLattice = "dot(((%s.ga + %s.rb * float2(%s)) * float2(2.0) - float2(1.0)), %s);"; const char* dotLattice = "dot(((%s.ga + %s.rb * half2(%s)) * half2(2.0) - half2(1.0)), %s);";
// Add noise function // Add noise function
static const GrShaderVar gPerlinNoiseArgs[] = { static const GrShaderVar gPerlinNoiseArgs[] = {
GrShaderVar(chanCoord, kFloat_GrSLType), GrShaderVar(chanCoord, kHalf_GrSLType),
GrShaderVar(noiseVec, kVec2f_GrSLType) GrShaderVar(noiseVec, kHalf2_GrSLType)
}; };
static const GrShaderVar gPerlinNoiseStitchArgs[] = { static const GrShaderVar gPerlinNoiseStitchArgs[] = {
GrShaderVar(chanCoord, kFloat_GrSLType), GrShaderVar(chanCoord, kHalf_GrSLType),
GrShaderVar(noiseVec, kVec2f_GrSLType), GrShaderVar(noiseVec, kHalf2_GrSLType),
GrShaderVar(stitchData, kVec2f_GrSLType) GrShaderVar(stitchData, kHalf2_GrSLType)
}; };
SkString noiseCode; SkString noiseCode;
noiseCode.appendf("\tfloat4 %s;\n", floorVal); noiseCode.appendf("\thalf4 %s;\n", floorVal);
noiseCode.appendf("\t%s.xy = floor(%s);\n", floorVal, noiseVec); noiseCode.appendf("\t%s.xy = floor(%s);\n", floorVal, noiseVec);
noiseCode.appendf("\t%s.zw = %s.xy + float2(1.0);\n", floorVal, floorVal); noiseCode.appendf("\t%s.zw = %s.xy + half2(1.0);\n", floorVal, floorVal);
noiseCode.appendf("\tfloat2 %s = fract(%s);\n", fractVal, noiseVec); noiseCode.appendf("\thalf2 %s = fract(%s);\n", fractVal, noiseVec);
// smooth curve : t * t * (3 - 2 * t) // smooth curve : t * t * (3 - 2 * t)
noiseCode.appendf("\n\tfloat2 %s = %s * %s * (float2(3.0) - float2(2.0) * %s);", noiseCode.appendf("\n\thalf2 %s = %s * %s * (half2(3.0) - half2(2.0) * %s);",
noiseSmooth, fractVal, fractVal, fractVal); noiseSmooth, fractVal, fractVal, fractVal);
// Adjust frequencies if we're stitching tiles // Adjust frequencies if we're stitching tiles
@ -887,28 +885,28 @@ void GrGLPerlinNoise::emitCode(EmitArgs& args) {
} }
// Get texture coordinates and normalize // Get texture coordinates and normalize
noiseCode.appendf("\n\t%s = fract(floor(mod(%s, 256.0)) / float4(256.0));\n", noiseCode.appendf("\n\t%s = fract(floor(mod(%s, 256.0)) / half4(256.0));\n",
floorVal, floorVal); floorVal, floorVal);
// Get permutation for x // Get permutation for x
{ {
SkString xCoords(""); SkString xCoords("");
xCoords.appendf("float2(%s.x, 0.5)", floorVal); xCoords.appendf("half2(%s.x, 0.5)", floorVal);
noiseCode.appendf("\n\tfloat2 %s;\n\t%s.x = ", latticeIdx, latticeIdx); noiseCode.appendf("\n\thalf2 %s;\n\t%s.x = ", latticeIdx, latticeIdx);
fragBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[0], xCoords.c_str(), fragBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[0], xCoords.c_str(),
kVec2f_GrSLType); kHalf2_GrSLType);
noiseCode.append(".r;"); noiseCode.append(".r;");
} }
// Get permutation for x + 1 // Get permutation for x + 1
{ {
SkString xCoords(""); SkString xCoords("");
xCoords.appendf("float2(%s.z, 0.5)", floorVal); xCoords.appendf("half2(%s.z, 0.5)", floorVal);
noiseCode.appendf("\n\t%s.y = ", latticeIdx); noiseCode.appendf("\n\t%s.y = ", latticeIdx);
fragBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[0], xCoords.c_str(), fragBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[0], xCoords.c_str(),
kVec2f_GrSLType); kHalf2_GrSLType);
noiseCode.append(".r;"); noiseCode.append(".r;");
} }
@ -919,21 +917,21 @@ void GrGLPerlinNoise::emitCode(EmitArgs& args) {
// (or 0.484368 here). The following rounding operation prevents these precision issues from // (or 0.484368 here). The following rounding operation prevents these precision issues from
// affecting the result of the noise by making sure that we only have multiples of 1/255. // affecting the result of the noise by making sure that we only have multiples of 1/255.
// (Note that 1/255 is about 0.003921569, which is the value used here). // (Note that 1/255 is about 0.003921569, which is the value used here).
noiseCode.appendf("\n\t%s = floor(%s * float2(255.0) + float2(0.5)) * float2(0.003921569);", noiseCode.appendf("\n\t%s = floor(%s * half2(255.0) + half2(0.5)) * half2(0.003921569);",
latticeIdx, latticeIdx); latticeIdx, latticeIdx);
#endif #endif
// Get (x,y) coordinates with the permutated x // Get (x,y) coordinates with the permutated x
noiseCode.appendf("\n\tfloat4 %s = fract(%s.xyxy + %s.yyww);", bcoords, latticeIdx, floorVal); noiseCode.appendf("\n\thalf4 %s = fract(%s.xyxy + %s.yyww);", bcoords, latticeIdx, floorVal);
noiseCode.appendf("\n\n\tfloat2 %s;", uv); noiseCode.appendf("\n\n\thalf2 %s;", uv);
// Compute u, at offset (0,0) // Compute u, at offset (0,0)
{ {
SkString latticeCoords(""); SkString latticeCoords("");
latticeCoords.appendf("float2(%s.x, %s)", bcoords, chanCoord); latticeCoords.appendf("half2(%s.x, %s)", bcoords, chanCoord);
noiseCode.appendf("\n\tfloat4 %s = ", lattice); noiseCode.appendf("\n\thalf4 %s = ", lattice);
fragBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(), fragBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(),
kVec2f_GrSLType); kHalf2_GrSLType);
noiseCode.appendf(".bgra;\n\t%s.x = ", uv); noiseCode.appendf(".bgra;\n\t%s.x = ", uv);
noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal); noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
} }
@ -942,26 +940,26 @@ void GrGLPerlinNoise::emitCode(EmitArgs& args) {
// Compute v, at offset (-1,0) // Compute v, at offset (-1,0)
{ {
SkString latticeCoords(""); SkString latticeCoords("");
latticeCoords.appendf("float2(%s.y, %s)", bcoords, chanCoord); latticeCoords.appendf("half2(%s.y, %s)", bcoords, chanCoord);
noiseCode.append("\n\tlattice = "); noiseCode.append("\n\tlattice = ");
fragBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(), fragBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(),
kVec2f_GrSLType); kHalf2_GrSLType);
noiseCode.appendf(".bgra;\n\t%s.y = ", uv); noiseCode.appendf(".bgra;\n\t%s.y = ", uv);
noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal); noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
} }
// Compute 'a' as a linear interpolation of 'u' and 'v' // Compute 'a' as a linear interpolation of 'u' and 'v'
noiseCode.appendf("\n\tfloat2 %s;", ab); noiseCode.appendf("\n\thalf2 %s;", ab);
noiseCode.appendf("\n\t%s.x = mix(%s.x, %s.y, %s.x);", ab, uv, uv, noiseSmooth); noiseCode.appendf("\n\t%s.x = mix(%s.x, %s.y, %s.x);", ab, uv, uv, noiseSmooth);
noiseCode.appendf("\n\t%s.y -= 1.0;", fractVal); noiseCode.appendf("\n\t%s.y -= 1.0;", fractVal);
// Compute v, at offset (-1,-1) // Compute v, at offset (-1,-1)
{ {
SkString latticeCoords(""); SkString latticeCoords("");
latticeCoords.appendf("float2(%s.w, %s)", bcoords, chanCoord); latticeCoords.appendf("half2(%s.w, %s)", bcoords, chanCoord);
noiseCode.append("\n\tlattice = "); noiseCode.append("\n\tlattice = ");
fragBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(), fragBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(),
kVec2f_GrSLType); kHalf2_GrSLType);
noiseCode.appendf(".bgra;\n\t%s.y = ", uv); noiseCode.appendf(".bgra;\n\t%s.y = ", uv);
noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal); noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
} }
@ -970,10 +968,10 @@ void GrGLPerlinNoise::emitCode(EmitArgs& args) {
// Compute u, at offset (0,-1) // Compute u, at offset (0,-1)
{ {
SkString latticeCoords(""); SkString latticeCoords("");
latticeCoords.appendf("float2(%s.z, %s)", bcoords, chanCoord); latticeCoords.appendf("half2(%s.z, %s)", bcoords, chanCoord);
noiseCode.append("\n\tlattice = "); noiseCode.append("\n\tlattice = ");
fragBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(), fragBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(),
kVec2f_GrSLType); kHalf2_GrSLType);
noiseCode.appendf(".bgra;\n\t%s.x = ", uv); noiseCode.appendf(".bgra;\n\t%s.x = ", uv);
noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal); noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
} }
@ -985,28 +983,28 @@ void GrGLPerlinNoise::emitCode(EmitArgs& args) {
SkString noiseFuncName; SkString noiseFuncName;
if (pne.stitchTiles()) { if (pne.stitchTiles()) {
fragBuilder->emitFunction(kFloat_GrSLType, fragBuilder->emitFunction(kHalf_GrSLType,
"perlinnoise", SK_ARRAY_COUNT(gPerlinNoiseStitchArgs), "perlinnoise", SK_ARRAY_COUNT(gPerlinNoiseStitchArgs),
gPerlinNoiseStitchArgs, noiseCode.c_str(), &noiseFuncName); gPerlinNoiseStitchArgs, noiseCode.c_str(), &noiseFuncName);
} else { } else {
fragBuilder->emitFunction(kFloat_GrSLType, fragBuilder->emitFunction(kHalf_GrSLType,
"perlinnoise", SK_ARRAY_COUNT(gPerlinNoiseArgs), "perlinnoise", SK_ARRAY_COUNT(gPerlinNoiseArgs),
gPerlinNoiseArgs, noiseCode.c_str(), &noiseFuncName); gPerlinNoiseArgs, noiseCode.c_str(), &noiseFuncName);
} }
// There are rounding errors if the floor operation is not performed here // There are rounding errors if the floor operation is not performed here
fragBuilder->codeAppendf("\n\t\tfloat2 %s = floor(%s.xy) * %s;", fragBuilder->codeAppendf("\n\t\thalf2 %s = floor(%s.xy) * %s;",
noiseVec, vCoords.c_str(), baseFrequencyUni); noiseVec, vCoords.c_str(), baseFrequencyUni);
// Clear the color accumulator // Clear the color accumulator
fragBuilder->codeAppendf("\n\t\t%s = float4(0.0);", args.fOutputColor); fragBuilder->codeAppendf("\n\t\t%s = half4(0.0);", args.fOutputColor);
if (pne.stitchTiles()) { if (pne.stitchTiles()) {
// Set up TurbulenceInitial stitch values. // Set up TurbulenceInitial stitch values.
fragBuilder->codeAppendf("\n\t\tfloat2 %s = %s;", stitchData, stitchDataUni); fragBuilder->codeAppendf("\n\t\thalf2 %s = %s;", stitchData, stitchDataUni);
} }
fragBuilder->codeAppendf("\n\t\tfloat %s = 1.0;", ratio); fragBuilder->codeAppendf("\n\t\thalf %s = 1.0;", ratio);
// Loop over all octaves // Loop over all octaves
fragBuilder->codeAppendf("for (int octave = 0; octave < %d; ++octave) {", pne.numOctaves()); fragBuilder->codeAppendf("for (int octave = 0; octave < %d; ++octave) {", pne.numOctaves());
@ -1017,7 +1015,7 @@ void GrGLPerlinNoise::emitCode(EmitArgs& args) {
} }
if (pne.stitchTiles()) { if (pne.stitchTiles()) {
fragBuilder->codeAppendf( fragBuilder->codeAppendf(
"float4(\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s)," "half4(\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))", "\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s))",
noiseFuncName.c_str(), chanCoordR, noiseVec, stitchData, noiseFuncName.c_str(), chanCoordR, noiseVec, stitchData,
noiseFuncName.c_str(), chanCoordG, noiseVec, stitchData, noiseFuncName.c_str(), chanCoordG, noiseVec, stitchData,
@ -1025,7 +1023,7 @@ void GrGLPerlinNoise::emitCode(EmitArgs& args) {
noiseFuncName.c_str(), chanCoordA, noiseVec, stitchData); noiseFuncName.c_str(), chanCoordA, noiseVec, stitchData);
} else { } else {
fragBuilder->codeAppendf( fragBuilder->codeAppendf(
"float4(\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s)," "half4(\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))", "\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s))",
noiseFuncName.c_str(), chanCoordR, noiseVec, noiseFuncName.c_str(), chanCoordR, noiseVec,
noiseFuncName.c_str(), chanCoordG, noiseVec, noiseFuncName.c_str(), chanCoordG, noiseVec,
@ -1037,18 +1035,18 @@ void GrGLPerlinNoise::emitCode(EmitArgs& args) {
} }
fragBuilder->codeAppendf(" * %s;", ratio); fragBuilder->codeAppendf(" * %s;", ratio);
fragBuilder->codeAppendf("\n\t\t\t%s *= float2(2.0);", noiseVec); fragBuilder->codeAppendf("\n\t\t\t%s *= half2(2.0);", noiseVec);
fragBuilder->codeAppendf("\n\t\t\t%s *= 0.5;", ratio); fragBuilder->codeAppendf("\n\t\t\t%s *= 0.5;", ratio);
if (pne.stitchTiles()) { if (pne.stitchTiles()) {
fragBuilder->codeAppendf("\n\t\t\t%s *= float2(2.0);", stitchData); fragBuilder->codeAppendf("\n\t\t\t%s *= half2(2.0);", stitchData);
} }
fragBuilder->codeAppend("\n\t\t}"); // end of the for loop on octaves fragBuilder->codeAppend("\n\t\t}"); // end of the for loop on octaves
if (pne.type() == SkPerlinNoiseShaderImpl::kFractalNoise_Type) { if (pne.type() == SkPerlinNoiseShaderImpl::kFractalNoise_Type) {
// The value of turbulenceFunctionResult comes from ((turbulenceFunctionResult) + 1) / 2 // The value of turbulenceFunctionResult comes from ((turbulenceFunctionResult) + 1) / 2
// by fractalNoise and (turbulenceFunctionResult) by turbulence. // by fractalNoise and (turbulenceFunctionResult) by turbulence.
fragBuilder->codeAppendf("\n\t\t%s = %s * float4(0.5) + float4(0.5);", fragBuilder->codeAppendf("\n\t\t%s = %s * half4(0.5) + half4(0.5);",
args.fOutputColor,args.fOutputColor); args.fOutputColor,args.fOutputColor);
} }
@ -1056,7 +1054,7 @@ void GrGLPerlinNoise::emitCode(EmitArgs& args) {
fragBuilder->codeAppendf("\n\t\t%s = clamp(%s, 0.0, 1.0);", args.fOutputColor, args.fOutputColor); fragBuilder->codeAppendf("\n\t\t%s = clamp(%s, 0.0, 1.0);", args.fOutputColor, args.fOutputColor);
// Pre-multiply the result // Pre-multiply the result
fragBuilder->codeAppendf("\n\t\t%s = float4(%s.rgb * %s.aaa, %s.a);\n", fragBuilder->codeAppendf("\n\t\t%s = half4(%s.rgb * %s.aaa, %s.a);\n",
args.fOutputColor, args.fOutputColor, args.fOutputColor, args.fOutputColor,
args.fOutputColor, args.fOutputColor); args.fOutputColor, args.fOutputColor);
} }
@ -1235,133 +1233,130 @@ void GrGLImprovedPerlinNoise::emitCode(EmitArgs& args) {
GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
SkString vCoords = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]); SkString vCoords = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
fBaseFrequencyUni = uniformHandler->addUniform(kFragment_GrShaderFlag, fBaseFrequencyUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType,
kVec2f_GrSLType, kDefault_GrSLPrecision,
"baseFrequency"); "baseFrequency");
const char* baseFrequencyUni = uniformHandler->getUniformCStr(fBaseFrequencyUni); const char* baseFrequencyUni = uniformHandler->getUniformCStr(fBaseFrequencyUni);
fZUni = uniformHandler->addUniform(kFragment_GrShaderFlag, fZUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType, "z");
kFloat_GrSLType, kDefault_GrSLPrecision,
"z");
const char* zUni = uniformHandler->getUniformCStr(fZUni); const char* zUni = uniformHandler->getUniformCStr(fZUni);
// fade function // fade function
static const GrShaderVar fadeArgs[] = { static const GrShaderVar fadeArgs[] = {
GrShaderVar("t", kVec3f_GrSLType) GrShaderVar("t", kHalf3_GrSLType)
}; };
SkString fadeFuncName; SkString fadeFuncName;
fragBuilder->emitFunction(kVec3f_GrSLType, "fade", SK_ARRAY_COUNT(fadeArgs), fragBuilder->emitFunction(kHalf3_GrSLType, "fade", SK_ARRAY_COUNT(fadeArgs),
fadeArgs, fadeArgs,
"return t * t * t * (t * (t * 6.0 - 15.0) + 10.0);", "return t * t * t * (t * (t * 6.0 - 15.0) + 10.0);",
&fadeFuncName); &fadeFuncName);
// perm function // perm function
static const GrShaderVar permArgs[] = { static const GrShaderVar permArgs[] = {
GrShaderVar("x", kFloat_GrSLType) GrShaderVar("x", kHalf_GrSLType)
}; };
SkString permFuncName; SkString permFuncName;
SkString permCode("return "); SkString permCode("return ");
// FIXME even though I'm creating these textures with kRepeat_TileMode, they're clamped. Not // FIXME even though I'm creating these textures with kRepeat_TileMode, they're clamped. Not
// sure why. Using fract() (here and the next texture lookup) as a workaround. // sure why. Using fract() (here and the next texture lookup) as a workaround.
fragBuilder->appendTextureLookup(&permCode, args.fTexSamplers[0], "float2(fract(x / 256.0), 0.0)", fragBuilder->appendTextureLookup(&permCode, args.fTexSamplers[0], "highfloat2(fract(x / 256.0), 0.0)",
kVec2f_GrSLType); kHalf2_GrSLType);
permCode.append(".r * 255.0;"); permCode.append(".r * 255.0;");
fragBuilder->emitFunction(kFloat_GrSLType, "perm", SK_ARRAY_COUNT(permArgs), permArgs, fragBuilder->emitFunction(kHalf_GrSLType, "perm", SK_ARRAY_COUNT(permArgs), permArgs,
permCode.c_str(), &permFuncName); permCode.c_str(), &permFuncName);
// grad function // grad function
static const GrShaderVar gradArgs[] = { static const GrShaderVar gradArgs[] = {
GrShaderVar("x", kFloat_GrSLType), GrShaderVar("x", kHalf_GrSLType),
GrShaderVar("p", kVec3f_GrSLType) GrShaderVar("p", kHalf3_GrSLType)
}; };
SkString gradFuncName; SkString gradFuncName;
SkString gradCode("return dot("); SkString gradCode("return dot(");
fragBuilder->appendTextureLookup(&gradCode, args.fTexSamplers[1], "float2(fract(x / 16.0), 0.0)", fragBuilder->appendTextureLookup(&gradCode, args.fTexSamplers[1], "highfloat2(fract(x / 16.0), 0.0)",
kVec2f_GrSLType); kHalf2_GrSLType);
gradCode.append(".rgb * 255.0 - float3(1.0), p);"); gradCode.append(".rgb * 255.0 - highfloat3(1.0), p);");
fragBuilder->emitFunction(kFloat_GrSLType, "grad", SK_ARRAY_COUNT(gradArgs), gradArgs, fragBuilder->emitFunction(kHalf_GrSLType, "grad", SK_ARRAY_COUNT(gradArgs), gradArgs,
gradCode.c_str(), &gradFuncName); gradCode.c_str(), &gradFuncName);
// lerp function // lerp function
static const GrShaderVar lerpArgs[] = { static const GrShaderVar lerpArgs[] = {
GrShaderVar("a", kFloat_GrSLType), GrShaderVar("a", kHalf_GrSLType),
GrShaderVar("b", kFloat_GrSLType), GrShaderVar("b", kHalf_GrSLType),
GrShaderVar("w", kFloat_GrSLType) GrShaderVar("w", kHalf_GrSLType)
}; };
SkString lerpFuncName; SkString lerpFuncName;
fragBuilder->emitFunction(kFloat_GrSLType, "lerp", SK_ARRAY_COUNT(lerpArgs), lerpArgs, fragBuilder->emitFunction(kHalf_GrSLType, "lerp", SK_ARRAY_COUNT(lerpArgs), lerpArgs,
"return a + w * (b - a);", &lerpFuncName); "return a + w * (b - a);", &lerpFuncName);
// noise function // noise function
static const GrShaderVar noiseArgs[] = { static const GrShaderVar noiseArgs[] = {
GrShaderVar("p", kVec3f_GrSLType), GrShaderVar("p", kHalf3_GrSLType),
}; };
SkString noiseFuncName; SkString noiseFuncName;
SkString noiseCode; SkString noiseCode;
noiseCode.append("float3 P = mod(floor(p), 256.0);"); noiseCode.append("half3 P = mod(floor(p), 256.0);");
noiseCode.append("p -= floor(p);"); noiseCode.append("p -= floor(p);");
noiseCode.appendf("float3 f = %s(p);", fadeFuncName.c_str()); noiseCode.appendf("half3 f = %s(p);", fadeFuncName.c_str());
noiseCode.appendf("float A = %s(P.x) + P.y;", permFuncName.c_str()); noiseCode.appendf("half A = %s(P.x) + P.y;", permFuncName.c_str());
noiseCode.appendf("float AA = %s(A) + P.z;", permFuncName.c_str()); noiseCode.appendf("half AA = %s(A) + P.z;", permFuncName.c_str());
noiseCode.appendf("float AB = %s(A + 1.0) + P.z;", permFuncName.c_str()); noiseCode.appendf("half AB = %s(A + 1.0) + P.z;", permFuncName.c_str());
noiseCode.appendf("float B = %s(P.x + 1.0) + P.y;", permFuncName.c_str()); noiseCode.appendf("half B = %s(P.x + 1.0) + P.y;", permFuncName.c_str());
noiseCode.appendf("float BA = %s(B) + P.z;", permFuncName.c_str()); noiseCode.appendf("half BA = %s(B) + P.z;", permFuncName.c_str());
noiseCode.appendf("float BB = %s(B + 1.0) + P.z;", permFuncName.c_str()); noiseCode.appendf("half BB = %s(B + 1.0) + P.z;", permFuncName.c_str());
noiseCode.appendf("float result = %s(", lerpFuncName.c_str()); noiseCode.appendf("half result = %s(", lerpFuncName.c_str());
noiseCode.appendf("%s(%s(%s(%s(AA), p),", lerpFuncName.c_str(), lerpFuncName.c_str(), noiseCode.appendf("%s(%s(%s(%s(AA), p),", lerpFuncName.c_str(), lerpFuncName.c_str(),
gradFuncName.c_str(), permFuncName.c_str()); gradFuncName.c_str(), permFuncName.c_str());
noiseCode.appendf("%s(%s(BA), p + float3(-1.0, 0.0, 0.0)), f.x),", gradFuncName.c_str(), noiseCode.appendf("%s(%s(BA), p + half3(-1.0, 0.0, 0.0)), f.x),", gradFuncName.c_str(),
permFuncName.c_str()); permFuncName.c_str());
noiseCode.appendf("%s(%s(%s(AB), p + float3(0.0, -1.0, 0.0)),", lerpFuncName.c_str(), noiseCode.appendf("%s(%s(%s(AB), p + half3(0.0, -1.0, 0.0)),", lerpFuncName.c_str(),
gradFuncName.c_str(), permFuncName.c_str()); gradFuncName.c_str(), permFuncName.c_str());
noiseCode.appendf("%s(%s(BB), p + float3(-1.0, -1.0, 0.0)), f.x), f.y),", noiseCode.appendf("%s(%s(BB), p + half3(-1.0, -1.0, 0.0)), f.x), f.y),",
gradFuncName.c_str(), permFuncName.c_str()); gradFuncName.c_str(), permFuncName.c_str());
noiseCode.appendf("%s(%s(%s(%s(AA + 1.0), p + float3(0.0, 0.0, -1.0)),", noiseCode.appendf("%s(%s(%s(%s(AA + 1.0), p + half3(0.0, 0.0, -1.0)),",
lerpFuncName.c_str(), lerpFuncName.c_str(), gradFuncName.c_str(), lerpFuncName.c_str(), lerpFuncName.c_str(), gradFuncName.c_str(),
permFuncName.c_str()); permFuncName.c_str());
noiseCode.appendf("%s(%s(BA + 1.0), p + float3(-1.0, 0.0, -1.0)), f.x),", noiseCode.appendf("%s(%s(BA + 1.0), p + half3(-1.0, 0.0, -1.0)), f.x),",
gradFuncName.c_str(), permFuncName.c_str()); gradFuncName.c_str(), permFuncName.c_str());
noiseCode.appendf("%s(%s(%s(AB + 1.0), p + float3(0.0, -1.0, -1.0)),", noiseCode.appendf("%s(%s(%s(AB + 1.0), p + half3(0.0, -1.0, -1.0)),",
lerpFuncName.c_str(), gradFuncName.c_str(), permFuncName.c_str()); lerpFuncName.c_str(), gradFuncName.c_str(), permFuncName.c_str());
noiseCode.appendf("%s(%s(BB + 1.0), p + float3(-1.0, -1.0, -1.0)), f.x), f.y), f.z);", noiseCode.appendf("%s(%s(BB + 1.0), p + half3(-1.0, -1.0, -1.0)), f.x), f.y), f.z);",
gradFuncName.c_str(), permFuncName.c_str()); gradFuncName.c_str(), permFuncName.c_str());
noiseCode.append("return result;"); noiseCode.append("return result;");
fragBuilder->emitFunction(kFloat_GrSLType, "noise", SK_ARRAY_COUNT(noiseArgs), noiseArgs, fragBuilder->emitFunction(kHalf_GrSLType, "noise", SK_ARRAY_COUNT(noiseArgs), noiseArgs,
noiseCode.c_str(), &noiseFuncName); noiseCode.c_str(), &noiseFuncName);
// noiseOctaves function // noiseOctaves function
static const GrShaderVar noiseOctavesArgs[] = { static const GrShaderVar noiseOctavesArgs[] = {
GrShaderVar("p", kVec3f_GrSLType) GrShaderVar("p", kHalf3_GrSLType)
}; };
SkString noiseOctavesFuncName; SkString noiseOctavesFuncName;
SkString noiseOctavesCode; SkString noiseOctavesCode;
noiseOctavesCode.append("float result = 0.0;"); noiseOctavesCode.append("half result = 0.0;");
noiseOctavesCode.append("float ratio = 1.0;"); noiseOctavesCode.append("half ratio = 1.0;");
noiseOctavesCode.appendf("for (float i = 0.0; i < %d; i++) {", pne.octaves()); noiseOctavesCode.appendf("for (half i = 0.0; i < %d; i++) {", pne.octaves());
noiseOctavesCode.appendf("result += %s(p) / ratio;", noiseFuncName.c_str()); noiseOctavesCode.appendf("result += %s(p) / ratio;", noiseFuncName.c_str());
noiseOctavesCode.append("p *= 2.0;"); noiseOctavesCode.append("p *= 2.0;");
noiseOctavesCode.append("ratio *= 2.0;"); noiseOctavesCode.append("ratio *= 2.0;");
noiseOctavesCode.append("}"); noiseOctavesCode.append("}");
noiseOctavesCode.append("return (result + 1.0) / 2.0;"); noiseOctavesCode.append("return (result + 1.0) / 2.0;");
fragBuilder->emitFunction(kFloat_GrSLType, "noiseOctaves", SK_ARRAY_COUNT(noiseOctavesArgs), fragBuilder->emitFunction(kHalf_GrSLType, "noiseOctaves", SK_ARRAY_COUNT(noiseOctavesArgs),
noiseOctavesArgs, noiseOctavesCode.c_str(), &noiseOctavesFuncName); noiseOctavesArgs, noiseOctavesCode.c_str(), &noiseOctavesFuncName);
fragBuilder->codeAppendf("float2 coords = %s * %s;", vCoords.c_str(), baseFrequencyUni); fragBuilder->codeAppendf("half2 coords = %s * %s;", vCoords.c_str(), baseFrequencyUni);
fragBuilder->codeAppendf("float r = %s(float3(coords, %s));", noiseOctavesFuncName.c_str(), fragBuilder->codeAppendf("half r = %s(half3(coords, %s));", noiseOctavesFuncName.c_str(),
zUni); zUni);
fragBuilder->codeAppendf("float g = %s(float3(coords, %s + 0000.0));", fragBuilder->codeAppendf("half g = %s(half3(coords, %s + 0000.0));",
noiseOctavesFuncName.c_str(), zUni); noiseOctavesFuncName.c_str(), zUni);
fragBuilder->codeAppendf("float b = %s(float3(coords, %s + 0000.0));", fragBuilder->codeAppendf("half b = %s(half3(coords, %s + 0000.0));",
noiseOctavesFuncName.c_str(), zUni); noiseOctavesFuncName.c_str(), zUni);
fragBuilder->codeAppendf("float a = %s(float3(coords, %s + 0000.0));", fragBuilder->codeAppendf("half a = %s(half3(coords, %s + 0000.0));",
noiseOctavesFuncName.c_str(), zUni); noiseOctavesFuncName.c_str(), zUni);
fragBuilder->codeAppendf("%s = float4(r, g, b, a);", args.fOutputColor); fragBuilder->codeAppendf("%s = half4(r, g, b, a);", args.fOutputColor);
// Clamp values // Clamp values
fragBuilder->codeAppendf("%s = clamp(%s, 0.0, 1.0);", args.fOutputColor, args.fOutputColor); fragBuilder->codeAppendf("%s = clamp(%s, 0.0, 1.0);", args.fOutputColor, args.fOutputColor);
// Pre-multiply the result // Pre-multiply the result
fragBuilder->codeAppendf("\n\t\t%s = float4(%s.rgb * %s.aaa, %s.a);\n", fragBuilder->codeAppendf("\n\t\t%s = half4(%s.rgb * %s.aaa, %s.a);\n",
args.fOutputColor, args.fOutputColor, args.fOutputColor, args.fOutputColor,
args.fOutputColor, args.fOutputColor); args.fOutputColor, args.fOutputColor);
} }

View File

@ -1355,17 +1355,15 @@ void GrGradientEffect::GLSLProcessor::emitUniforms(GrGLSLUniformHandler* uniform
const GrGradientEffect& ge) { const GrGradientEffect& ge) {
if (int colorCount = color_type_to_color_count(ge.getColorType())) { if (int colorCount = color_type_to_color_count(ge.getColorType())) {
fColorsUni = uniformHandler->addUniformArray(kFragment_GrShaderFlag, fColorsUni = uniformHandler->addUniformArray(kFragment_GrShaderFlag,
kVec4f_GrSLType, kHalf4_GrSLType,
kDefault_GrSLPrecision,
"Colors", "Colors",
colorCount); colorCount);
if (kSingleHardStop_ColorType == ge.fColorType || kThree_ColorType == ge.fColorType) { if (kSingleHardStop_ColorType == ge.fColorType || kThree_ColorType == ge.fColorType) {
fExtraStopT = uniformHandler->addUniform(kFragment_GrShaderFlag, kVec4f_GrSLType, fExtraStopT = uniformHandler->addUniform(kFragment_GrShaderFlag, kHighFloat4_GrSLType,
kHigh_GrSLPrecision, "ExtraStopT"); kHigh_GrSLPrecision, "ExtraStopT");
} }
} else { } else {
fFSYUni = uniformHandler->addUniform(kFragment_GrShaderFlag, fFSYUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType,
kFloat_GrSLType, kDefault_GrSLPrecision,
"GradientYCoordFS"); "GradientYCoordFS");
} }
} }
@ -1557,14 +1555,14 @@ void GrGradientEffect::GLSLProcessor::emitAnalyticalColor(GrGLSLFPFragmentBuilde
// First, apply tiling rules. // First, apply tiling rules.
switch (ge.fWrapMode) { switch (ge.fWrapMode) {
case GrSamplerState::WrapMode::kClamp: case GrSamplerState::WrapMode::kClamp:
fragBuilder->codeAppendf("float clamp_t = clamp(%s, 0.0, 1.0);", t); fragBuilder->codeAppendf("half clamp_t = clamp(%s, 0.0, 1.0);", t);
break; break;
case GrSamplerState::WrapMode::kRepeat: case GrSamplerState::WrapMode::kRepeat:
fragBuilder->codeAppendf("float clamp_t = fract(%s);", t); fragBuilder->codeAppendf("half clamp_t = fract(%s);", t);
break; break;
case GrSamplerState::WrapMode::kMirrorRepeat: case GrSamplerState::WrapMode::kMirrorRepeat:
fragBuilder->codeAppendf("float t_1 = %s - 1.0;", t); fragBuilder->codeAppendf("half t_1 = %s - 1.0;", t);
fragBuilder->codeAppendf("float clamp_t = abs(t_1 - 2.0 * floor(t_1 * 0.5) - 1.0);"); fragBuilder->codeAppendf("half clamp_t = abs(t_1 - 2.0 * floor(t_1 * 0.5) - 1.0);");
break; break;
} }
@ -1575,8 +1573,8 @@ void GrGradientEffect::GLSLProcessor::emitAnalyticalColor(GrGLSLFPFragmentBuilde
// (t, 1/t, 1/(1-t), t/(1-t)) // (t, 1/t, 1/(1-t), t/(1-t))
const char* stopT = uniformHandler->getUniformCStr(fExtraStopT); const char* stopT = uniformHandler->getUniformCStr(fExtraStopT);
fragBuilder->codeAppend ("float4 start, end;"); fragBuilder->codeAppend ("half4 start, end;");
fragBuilder->codeAppend ("float relative_t;"); fragBuilder->codeAppend ("half relative_t;");
fragBuilder->codeAppendf("if (clamp_t < %s.x) {", stopT); fragBuilder->codeAppendf("if (clamp_t < %s.x) {", stopT);
fragBuilder->codeAppendf(" start = %s[0];", colors); fragBuilder->codeAppendf(" start = %s[0];", colors);
fragBuilder->codeAppendf(" end = %s[1];", colors); fragBuilder->codeAppendf(" end = %s[1];", colors);
@ -1587,13 +1585,13 @@ void GrGradientEffect::GLSLProcessor::emitAnalyticalColor(GrGLSLFPFragmentBuilde
// Want: (t-s)/(1-s), but arrange it as: t/(1-s) - s/(1-s), for FMA form // Want: (t-s)/(1-s), but arrange it as: t/(1-s) - s/(1-s), for FMA form
fragBuilder->codeAppendf(" relative_t = (clamp_t * %s.z) - %s.w;", stopT, stopT); fragBuilder->codeAppendf(" relative_t = (clamp_t * %s.z) - %s.w;", stopT, stopT);
fragBuilder->codeAppend ("}"); fragBuilder->codeAppend ("}");
fragBuilder->codeAppend ("float4 colorTemp = mix(start, end, relative_t);"); fragBuilder->codeAppend ("half4 colorTemp = mix(start, end, relative_t);");
break; break;
} }
case kHardStopLeftEdged_ColorType: { case kHardStopLeftEdged_ColorType: {
fragBuilder->codeAppendf("float4 colorTemp = mix(%s[1], %s[2], clamp_t);", colors, fragBuilder->codeAppendf("half4 colorTemp = mix(%s[1], %s[2], clamp_t);", colors,
colors); colors);
if (GrSamplerState::WrapMode::kClamp == ge.fWrapMode) { if (GrSamplerState::WrapMode::kClamp == ge.fWrapMode) {
fragBuilder->codeAppendf("if (%s < 0.0) {", t); fragBuilder->codeAppendf("if (%s < 0.0) {", t);
@ -1605,7 +1603,7 @@ void GrGradientEffect::GLSLProcessor::emitAnalyticalColor(GrGLSLFPFragmentBuilde
} }
case kHardStopRightEdged_ColorType: { case kHardStopRightEdged_ColorType: {
fragBuilder->codeAppendf("float4 colorTemp = mix(%s[0], %s[1], clamp_t);", colors, fragBuilder->codeAppendf("half4 colorTemp = mix(%s[0], %s[1], clamp_t);", colors,
colors); colors);
if (GrSamplerState::WrapMode::kClamp == ge.fWrapMode) { if (GrSamplerState::WrapMode::kClamp == ge.fWrapMode) {
fragBuilder->codeAppendf("if (%s > 1.0) {", t); fragBuilder->codeAppendf("if (%s > 1.0) {", t);
@ -1617,7 +1615,7 @@ void GrGradientEffect::GLSLProcessor::emitAnalyticalColor(GrGLSLFPFragmentBuilde
} }
case kTwo_ColorType: { case kTwo_ColorType: {
fragBuilder->codeAppendf("float4 colorTemp = mix(%s[0], %s[1], clamp_t);", fragBuilder->codeAppendf("half4 colorTemp = mix(%s[0], %s[1], clamp_t);",
colors, colors); colors, colors);
break; break;
@ -1627,8 +1625,8 @@ void GrGradientEffect::GLSLProcessor::emitAnalyticalColor(GrGLSLFPFragmentBuilde
// (t, 1/t, 1/(1-t), t/(1-t)) // (t, 1/t, 1/(1-t), t/(1-t))
const char* stopT = uniformHandler->getUniformCStr(fExtraStopT); const char* stopT = uniformHandler->getUniformCStr(fExtraStopT);
fragBuilder->codeAppend("float4 start, end;"); fragBuilder->codeAppend("half4 start, end;");
fragBuilder->codeAppend("float relative_t;"); fragBuilder->codeAppend("half relative_t;");
fragBuilder->codeAppendf("if (clamp_t < %s.x) {", stopT); fragBuilder->codeAppendf("if (clamp_t < %s.x) {", stopT);
fragBuilder->codeAppendf(" start = %s[0];", colors); fragBuilder->codeAppendf(" start = %s[0];", colors);
fragBuilder->codeAppendf(" end = %s[1];", colors); fragBuilder->codeAppendf(" end = %s[1];", colors);
@ -1639,7 +1637,7 @@ void GrGradientEffect::GLSLProcessor::emitAnalyticalColor(GrGLSLFPFragmentBuilde
// Want: (t-s)/(1-s), but arrange it as: t/(1-s) - s/(1-s), for FMA form // Want: (t-s)/(1-s), but arrange it as: t/(1-s) - s/(1-s), for FMA form
fragBuilder->codeAppendf(" relative_t = (clamp_t * %s.z) - %s.w;", stopT, stopT); fragBuilder->codeAppendf(" relative_t = (clamp_t * %s.z) - %s.w;", stopT, stopT);
fragBuilder->codeAppend("}"); fragBuilder->codeAppend("}");
fragBuilder->codeAppend("float4 colorTemp = mix(start, end, relative_t);"); fragBuilder->codeAppend("half4 colorTemp = mix(start, end, relative_t);");
break; break;
} }
@ -1683,10 +1681,10 @@ void GrGradientEffect::GLSLProcessor::emitColor(GrGLSLFPFragmentBuilder* fragBui
const char* fsyuni = uniformHandler->getUniformCStr(fFSYUni); const char* fsyuni = uniformHandler->getUniformCStr(fFSYUni);
fragBuilder->codeAppendf("float2 coord = float2(%s, %s);", gradientTValue, fsyuni); fragBuilder->codeAppendf("half2 coord = half2(%s, %s);", gradientTValue, fsyuni);
fragBuilder->codeAppendf("%s = ", outputColor); fragBuilder->codeAppendf("%s = ", outputColor);
fragBuilder->appendTextureLookupAndModulate(inputColor, texSamplers[0], "coord", fragBuilder->appendTextureLookupAndModulate(inputColor, texSamplers[0], "coord",
kVec2f_GrSLType, &fColorSpaceHelper); kHighFloat2_GrSLType, &fColorSpaceHelper);
fragBuilder->codeAppend(";"); fragBuilder->codeAppend(";");
} }

View File

@ -198,8 +198,8 @@ void GrSweepGradient::GLSLSweepProcessor::emitCode(EmitArgs& args) {
const GrSweepGradient& ge = args.fFp.cast<GrSweepGradient>(); const GrSweepGradient& ge = args.fFp.cast<GrSweepGradient>();
GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
this->emitUniforms(uniformHandler, ge); this->emitUniforms(uniformHandler, ge);
fTBiasScaleUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kVec2f_GrSLType, fTBiasScaleUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType,
kDefault_GrSLPrecision, "SweepFSParams"); "SweepFSParams");
const char* tBiasScaleV = uniformHandler->getUniformCStr(fTBiasScaleUni); const char* tBiasScaleV = uniformHandler->getUniformCStr(fTBiasScaleUni);
const SkString coords2D = args.fFragBuilder->ensureCoords2D(args.fTransformedCoords[0]); const SkString coords2D = args.fFragBuilder->ensureCoords2D(args.fTransformedCoords[0]);

View File

@ -235,8 +235,7 @@ void Edge2PtConicalEffect::GLSLEdge2PtConicalProcessor::emitCode(EmitArgs& args)
const Edge2PtConicalEffect& ge = args.fFp.cast<Edge2PtConicalEffect>(); const Edge2PtConicalEffect& ge = args.fFp.cast<Edge2PtConicalEffect>();
GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
this->emitUniforms(uniformHandler, ge); this->emitUniforms(uniformHandler, ge);
fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag, fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf3_GrSLType,
kVec3f_GrSLType, kDefault_GrSLPrecision,
"Conical2FSParams"); "Conical2FSParams");
SkString cName("c"); SkString cName("c");
@ -255,8 +254,8 @@ void Edge2PtConicalEffect::GLSLEdge2PtConicalProcessor::emitCode(EmitArgs& args)
const char* coords2D; const char* coords2D;
SkString bVar; SkString bVar;
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
if (kVec3f_GrSLType == args.fTransformedCoords[0].getType()) { if (kHalf3_GrSLType == args.fTransformedCoords[0].getType()) {
fragBuilder->codeAppendf("\tfloat3 interpolants = float3(%s.xy / %s.z, %s.x / %s.z);\n", fragBuilder->codeAppendf("\thalf3 interpolants = half3(%s.xy / %s.z, %s.x / %s.z);\n",
args.fTransformedCoords[0].c_str(), args.fTransformedCoords[0].c_str(),
args.fTransformedCoords[0].c_str(), args.fTransformedCoords[0].c_str(),
args.fTransformedCoords[1].c_str(), args.fTransformedCoords[1].c_str(),
@ -270,14 +269,14 @@ void Edge2PtConicalEffect::GLSLEdge2PtConicalProcessor::emitCode(EmitArgs& args)
// output will default to transparent black (we simply won't write anything // output will default to transparent black (we simply won't write anything
// else to it if invalid, instead of discarding or returning prematurely) // else to it if invalid, instead of discarding or returning prematurely)
fragBuilder->codeAppendf("\t%s = float4(0.0,0.0,0.0,0.0);\n", args.fOutputColor); fragBuilder->codeAppendf("\t%s = half4(0.0,0.0,0.0,0.0);\n", args.fOutputColor);
// c = (x^2)+(y^2) - params[1] // c = (x^2)+(y^2) - params[1]
fragBuilder->codeAppendf("\tfloat %s = dot(%s, %s) - %s;\n", fragBuilder->codeAppendf("\thalf %s = dot(%s, %s) - %s;\n",
cName.c_str(), coords2D, coords2D, p1.c_str()); cName.c_str(), coords2D, coords2D, p1.c_str());
// linear case: t = -c/b // linear case: t = -c/b
fragBuilder->codeAppendf("\tfloat %s = -(%s / %s);\n", tName.c_str(), fragBuilder->codeAppendf("\thalf %s = -(%s / %s);\n", tName.c_str(),
cName.c_str(), bVar.c_str()); cName.c_str(), bVar.c_str());
// if r(t) > 0, then t will be the x coordinate // if r(t) > 0, then t will be the x coordinate
@ -525,8 +524,7 @@ void FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor::emitCode
const FocalOutside2PtConicalEffect& ge = args.fFp.cast<FocalOutside2PtConicalEffect>(); const FocalOutside2PtConicalEffect& ge = args.fFp.cast<FocalOutside2PtConicalEffect>();
GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
this->emitUniforms(uniformHandler, ge); this->emitUniforms(uniformHandler, ge);
fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag, fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType,
kVec2f_GrSLType, kDefault_GrSLPrecision,
"Conical2FSParams"); "Conical2FSParams");
SkString tName("t"); SkString tName("t");
SkString p0; // focalX SkString p0; // focalX
@ -544,19 +542,19 @@ void FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor::emitCode
// output will default to transparent black (we simply won't write anything // output will default to transparent black (we simply won't write anything
// else to it if invalid, instead of discarding or returning prematurely) // else to it if invalid, instead of discarding or returning prematurely)
fragBuilder->codeAppendf("\t%s = float4(0.0,0.0,0.0,0.0);\n", args.fOutputColor); fragBuilder->codeAppendf("\t%s = half4(0.0,0.0,0.0,0.0);\n", args.fOutputColor);
fragBuilder->codeAppendf("\tfloat xs = %s.x * %s.x;\n", coords2D, coords2D); fragBuilder->codeAppendf("\thalf xs = %s.x * %s.x;\n", coords2D, coords2D);
fragBuilder->codeAppendf("\tfloat ys = %s.y * %s.y;\n", coords2D, coords2D); fragBuilder->codeAppendf("\thalf ys = %s.y * %s.y;\n", coords2D, coords2D);
fragBuilder->codeAppendf("\tfloat d = xs + %s * ys;\n", p1.c_str()); fragBuilder->codeAppendf("\thalf 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) // 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 so we must also flip sign on sqrt
if (!fIsFlipped) { if (!fIsFlipped) {
fragBuilder->codeAppendf("\tfloat %s = %s.x * %s + sqrt(d);\n", tName.c_str(), fragBuilder->codeAppendf("\thalf %s = %s.x * %s + sqrt(d);\n", tName.c_str(),
coords2D, p0.c_str()); coords2D, p0.c_str());
} else { } else {
fragBuilder->codeAppendf("\tfloat %s = %s.x * %s - sqrt(d);\n", tName.c_str(), fragBuilder->codeAppendf("\thalf %s = %s.x * %s - sqrt(d);\n", tName.c_str(),
coords2D, p0.c_str()); coords2D, p0.c_str());
} }
@ -734,8 +732,7 @@ void FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor::emitCode(E
const FocalInside2PtConicalEffect& ge = args.fFp.cast<FocalInside2PtConicalEffect>(); const FocalInside2PtConicalEffect& ge = args.fFp.cast<FocalInside2PtConicalEffect>();
GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
this->emitUniforms(uniformHandler, ge); this->emitUniforms(uniformHandler, ge);
fFocalUni = uniformHandler->addUniform(kFragment_GrShaderFlag, fFocalUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType,
kFloat_GrSLType, kDefault_GrSLPrecision,
"Conical2FSParams"); "Conical2FSParams");
SkString tName("t"); SkString tName("t");
@ -749,7 +746,7 @@ void FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor::emitCode(E
const char* coords2D = coords2DString.c_str(); const char* coords2D = coords2DString.c_str();
// t = p.x * focalX + length(p) // t = p.x * focalX + length(p)
fragBuilder->codeAppendf("\tfloat %s = %s.x * %s + length(%s);\n", tName.c_str(), fragBuilder->codeAppendf("\thalf %s = %s.x * %s + length(%s);\n", tName.c_str(),
coords2D, focal.c_str(), coords2D); coords2D, focal.c_str(), coords2D);
this->emitColor(fragBuilder, this->emitColor(fragBuilder,
@ -993,11 +990,9 @@ void CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor::emitCode
const CircleInside2PtConicalEffect& ge = args.fFp.cast<CircleInside2PtConicalEffect>(); const CircleInside2PtConicalEffect& ge = args.fFp.cast<CircleInside2PtConicalEffect>();
GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
this->emitUniforms(uniformHandler, ge); this->emitUniforms(uniformHandler, ge);
fCenterUni = uniformHandler->addUniform(kFragment_GrShaderFlag, fCenterUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType,
kVec2f_GrSLType, kDefault_GrSLPrecision,
"Conical2FSCenter"); "Conical2FSCenter");
fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag, fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf3_GrSLType,
kVec3f_GrSLType, kDefault_GrSLPrecision,
"Conical2FSParams"); "Conical2FSParams");
SkString tName("t"); SkString tName("t");
@ -1020,10 +1015,10 @@ void CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor::emitCode
// C = 1 / A // C = 1 / A
// d = dot(e, p) + B // d = dot(e, p) + B
// t = d +/- sqrt(d^2 - A * dot(p, p) + C) // t = d +/- sqrt(d^2 - A * dot(p, p) + C)
fragBuilder->codeAppendf("\tfloat pDotp = dot(%s, %s);\n", coords2D, coords2D); fragBuilder->codeAppendf("\thalf pDotp = dot(%s, %s);\n", coords2D, coords2D);
fragBuilder->codeAppendf("\tfloat d = dot(%s, %s) + %s.y;\n", coords2D, center.c_str(), fragBuilder->codeAppendf("\thalf d = dot(%s, %s) + %s.y;\n", coords2D, center.c_str(),
params.c_str()); params.c_str());
fragBuilder->codeAppendf("\tfloat %s = d + sqrt(d * d - %s.x * pDotp + %s.z);\n", fragBuilder->codeAppendf("\thalf %s = d + sqrt(d * d - %s.x * pDotp + %s.z);\n",
tName.c_str(), params.c_str(), params.c_str()); tName.c_str(), params.c_str(), params.c_str());
this->emitColor(fragBuilder, this->emitColor(fragBuilder,
@ -1241,11 +1236,9 @@ void CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor::emitCo
const CircleOutside2PtConicalEffect& ge = args.fFp.cast<CircleOutside2PtConicalEffect>(); const CircleOutside2PtConicalEffect& ge = args.fFp.cast<CircleOutside2PtConicalEffect>();
GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
this->emitUniforms(uniformHandler, ge); this->emitUniforms(uniformHandler, ge);
fCenterUni = uniformHandler->addUniform(kFragment_GrShaderFlag, fCenterUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType,
kVec2f_GrSLType, kDefault_GrSLPrecision,
"Conical2FSCenter"); "Conical2FSCenter");
fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag, fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType,
kVec4f_GrSLType, kDefault_GrSLPrecision,
"Conical2FSParams"); "Conical2FSParams");
SkString tName("t"); SkString tName("t");
@ -1262,7 +1255,7 @@ void CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor::emitCo
// output will default to transparent black (we simply won't write anything // output will default to transparent black (we simply won't write anything
// else to it if invalid, instead of discarding or returning prematurely) // else to it if invalid, instead of discarding or returning prematurely)
fragBuilder->codeAppendf("\t%s = float4(0.0,0.0,0.0,0.0);\n", args.fOutputColor); fragBuilder->codeAppendf("\t%s = half4(0.0,0.0,0.0,0.0);\n", args.fOutputColor);
// p = coords2D // p = coords2D
// e = center end // e = center end
@ -1273,18 +1266,18 @@ void CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor::emitCo
// d = dot(e, p) + B // d = dot(e, p) + B
// t = d +/- sqrt(d^2 - A * dot(p, p) + C) // t = d +/- sqrt(d^2 - A * dot(p, p) + C)
fragBuilder->codeAppendf("\tfloat pDotp = dot(%s, %s);\n", coords2D, coords2D); fragBuilder->codeAppendf("\thalf pDotp = dot(%s, %s);\n", coords2D, coords2D);
fragBuilder->codeAppendf("\tfloat d = dot(%s, %s) + %s.y;\n", coords2D, center.c_str(), fragBuilder->codeAppendf("\thalf d = dot(%s, %s) + %s.y;\n", coords2D, center.c_str(),
params.c_str()); params.c_str());
fragBuilder->codeAppendf("\tfloat deter = d * d - %s.x * pDotp + %s.z;\n", params.c_str(), fragBuilder->codeAppendf("\thalf deter = d * d - %s.x * pDotp + %s.z;\n", params.c_str(),
params.c_str()); params.c_str());
// Must check to see if we flipped the circle order (to make sure start radius < end radius) // 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 so we must also flip sign on sqrt
if (!fIsFlipped) { if (!fIsFlipped) {
fragBuilder->codeAppendf("\tfloat %s = d + sqrt(deter);\n", tName.c_str()); fragBuilder->codeAppendf("\thalf %s = d + sqrt(deter);\n", tName.c_str());
} else { } else {
fragBuilder->codeAppendf("\tfloat %s = d - sqrt(deter);\n", tName.c_str()); fragBuilder->codeAppendf("\thalf %s = d - sqrt(deter);\n", tName.c_str());
} }
fragBuilder->codeAppendf("\tif (%s >= %s.w && deter >= 0.0) {\n", fragBuilder->codeAppendf("\tif (%s >= %s.w && deter >= 0.0) {\n",

View File

@ -22,4 +22,6 @@ inline SkPoint float2(float xy) { return SkPoint::Make(xy, xy); }
inline SkPoint float2(float x, float y) { return SkPoint::Make(x, y); } inline SkPoint float2(float x, float y) { return SkPoint::Make(x, y); }
#define half2 float2
#endif #endif

View File

@ -51,16 +51,14 @@ void CPPCodeGenerator::writef(const char* s, ...) {
void CPPCodeGenerator::writeHeader() { void CPPCodeGenerator::writeHeader() {
} }
void CPPCodeGenerator::writePrecisionModifier() { bool CPPCodeGenerator::usesPrecisionModifiers() const {
return false;
} }
void CPPCodeGenerator::writeType(const Type& type) { String CPPCodeGenerator::getTypeName(const Type& type) {
if (type.kind() == Type::kStruct_Kind) { return type.name();
INHERITED::writeType(type);
} else {
this->write(type.fName);
}
} }
void CPPCodeGenerator::writeBinaryExpression(const BinaryExpression& b, void CPPCodeGenerator::writeBinaryExpression(const BinaryExpression& b,
Precedence parentPrecedence) { Precedence parentPrecedence) {
if (b.fOperator == Token::PERCENT) { if (b.fOperator == Token::PERCENT) {
@ -117,19 +115,16 @@ void CPPCodeGenerator::writeIndexExpression(const IndexExpression& i) {
INHERITED::writeIndexExpression(i); INHERITED::writeIndexExpression(i);
} }
static const char* default_value(const Type& type) { static String default_value(const Type& type) {
if (type.fName == "float") { if (type.fName == "colorSpaceXform") {
return "0.0";
} else if (type.fName == "float2") {
return "float2(0.0)";
} else if (type.fName == "float3") {
return "float30.0)";
} else if (type.fName == "float4") {
return "float4(0.0)";
} else if (type.fName == "floatt4x4" || type.fName == "colorSpaceXform") {
return "float4x4(1.0)"; return "float4x4(1.0)";
} }
ABORT("unsupported default_value type\n"); switch (type.kind()) {
case Type::kScalar_Kind: return "0";
case Type::kVector_Kind: return type.name() + "(0)";
case Type::kMatrix_Kind: return type.name() + "(1)";
default: ABORT("unsupported default_value type\n");
}
} }
static bool is_private(const Variable& var) { static bool is_private(const Variable& var) {
@ -140,7 +135,7 @@ static bool is_private(const Variable& var) {
} }
void CPPCodeGenerator::writeRuntimeValue(const Type& type, const String& cppCode) { void CPPCodeGenerator::writeRuntimeValue(const Type& type, const String& cppCode) {
if (type == *fContext.fFloat_Type) { if (type.isFloat()) {
this->write("%f"); this->write("%f");
fFormatArgs.push_back(cppCode); fFormatArgs.push_back(cppCode);
} else if (type == *fContext.fInt_Type) { } else if (type == *fContext.fInt_Type) {
@ -149,12 +144,12 @@ void CPPCodeGenerator::writeRuntimeValue(const Type& type, const String& cppCode
} else if (type == *fContext.fBool_Type) { } else if (type == *fContext.fBool_Type) {
this->write("%s"); this->write("%s");
fFormatArgs.push_back("(" + cppCode + " ? \"true\" : \"false\")"); fFormatArgs.push_back("(" + cppCode + " ? \"true\" : \"false\")");
} else if (type == *fContext.fFloat2_Type) { } else if (type == *fContext.fFloat2_Type || type == *fContext.fHalf2_Type) {
this->write("float2(%f, %f)"); this->write(type.name() + "(%f, %f)");
fFormatArgs.push_back(cppCode + ".fX"); fFormatArgs.push_back(cppCode + ".fX");
fFormatArgs.push_back(cppCode + ".fY"); fFormatArgs.push_back(cppCode + ".fY");
} else { } else {
this->write(type.fName); this->write(type.name());
this->write("\n"); this->write("\n");
ABORT("unsupported runtime value type\n"); ABORT("unsupported runtime value type\n");
} }
@ -189,7 +184,7 @@ void CPPCodeGenerator::writeVariableReference(const VariableReference& ref) {
switch (ref.fVariable.fModifiers.fLayout.fBuiltin) { switch (ref.fVariable.fModifiers.fLayout.fBuiltin) {
case SK_INCOLOR_BUILTIN: case SK_INCOLOR_BUILTIN:
this->write("%s"); this->write("%s");
fFormatArgs.push_back(String("args.fInputColor ? args.fInputColor : \"float4(1)\"")); fFormatArgs.push_back(String("args.fInputColor ? args.fInputColor : \"half4(1)\""));
break; break;
case SK_OUTCOLOR_BUILTIN: case SK_OUTCOLOR_BUILTIN:
this->write("%s"); this->write("%s");
@ -211,7 +206,7 @@ void CPPCodeGenerator::writeVariableReference(const VariableReference& ref) {
var = String::printf("fColorSpaceHelper.isValid() ? " var = String::printf("fColorSpaceHelper.isValid() ? "
"args.fUniformHandler->getUniformCStr(" "args.fUniformHandler->getUniformCStr("
"fColorSpaceHelper.gamutXformUniform()) : \"%s\"", "fColorSpaceHelper.gamutXformUniform()) : \"%s\"",
default_value(ref.fVariable.fType)); default_value(ref.fVariable.fType).c_str());
} else { } else {
var = String::printf("args.fUniformHandler->getUniformCStr(%sVar)", var = String::printf("args.fUniformHandler->getUniformCStr(%sVar)",
HCodeGenerator::FieldName(name.c_str()).c_str()); HCodeGenerator::FieldName(name.c_str()).c_str());
@ -221,7 +216,7 @@ void CPPCodeGenerator::writeVariableReference(const VariableReference& ref) {
code = String::printf("%sVar.isValid() ? %s : \"%s\"", code = String::printf("%sVar.isValid() ? %s : \"%s\"",
HCodeGenerator::FieldName(name.c_str()).c_str(), HCodeGenerator::FieldName(name.c_str()).c_str(),
var.c_str(), var.c_str(),
default_value(ref.fVariable.fType)); default_value(ref.fVariable.fType).c_str());
} else { } else {
code = var; code = var;
} }
@ -253,7 +248,7 @@ void CPPCodeGenerator::writeSwitchStatement(const SwitchStatement& s) {
void CPPCodeGenerator::writeFunctionCall(const FunctionCall& c) { void CPPCodeGenerator::writeFunctionCall(const FunctionCall& c) {
if (c.fFunction.fBuiltin && c.fFunction.fName == "COLORSPACE") { if (c.fFunction.fBuiltin && c.fFunction.fName == "COLORSPACE") {
String tmpVar = "_tmpVar" + to_string(++fVarCount); String tmpVar = "_tmpVar" + to_string(++fVarCount);
fFunctionHeader += "float4 " + tmpVar + ";"; fFunctionHeader += "half4 " + tmpVar + ";";
ASSERT(c.fArguments.size() == 2); ASSERT(c.fArguments.size() == 2);
this->write("%s"); this->write("%s");
fFormatArgs.push_back("fColorSpaceHelper.isValid() ? \"(" + tmpVar + " = \" : \"\""); fFormatArgs.push_back("fColorSpaceHelper.isValid() ? \"(" + tmpVar + " = \" : \"\"");
@ -262,7 +257,7 @@ void CPPCodeGenerator::writeFunctionCall(const FunctionCall& c) {
String xform("args.fUniformHandler->getUniformCStr(fColorSpaceHelper.gamutXformUniform())"); String xform("args.fUniformHandler->getUniformCStr(fColorSpaceHelper.gamutXformUniform())");
this->write("%s"); this->write("%s");
fFormatArgs.push_back("fColorSpaceHelper.isValid() ? SkStringPrintf(\", " fFormatArgs.push_back("fColorSpaceHelper.isValid() ? SkStringPrintf(\", "
"float4(clamp((%s * float4(" + tmpVar + ".rgb, 1.0)).rgb, 0.0, " + "half4(clamp((%s * half4(" + tmpVar + ".rgb, 1.0)).rgb, 0.0, " +
tmpVar + ".a), " + tmpVar + ".a))\", " + xform + ").c_str() : \"\""); tmpVar + ".a), " + tmpVar + ".a))\", " + xform + ").c_str() : \"\"");
return; return;
} }
@ -349,14 +344,22 @@ void CPPCodeGenerator::addUniform(const Variable& var) {
} }
const char* type; const char* type;
if (var.fType == *fContext.fFloat_Type) { if (var.fType == *fContext.fFloat_Type) {
type = "kFloat_GrSLType"; type = "kHighFloat_GrSLType";
} else if (var.fType == *fContext.fHalf_Type) {
type = "kHalf_GrSLType";
} else if (var.fType == *fContext.fFloat2_Type) { } else if (var.fType == *fContext.fFloat2_Type) {
type = "kVec2f_GrSLType"; type = "kHighFloat2_GrSLType";
} else if (var.fType == *fContext.fHalf2_Type) {
type = "kHalf2_GrSLType";
} else if (var.fType == *fContext.fFloat4_Type) { } else if (var.fType == *fContext.fFloat4_Type) {
type = "kVec4f_GrSLType"; type = "kHighFloat4_GrSLType";
} else if (var.fType == *fContext.fHalf4_Type) {
type = "kHalf4_GrSLType";
} else if (var.fType == *fContext.fFloat4x4_Type || } else if (var.fType == *fContext.fFloat4x4_Type ||
var.fType == *fContext.fColorSpaceXform_Type) { var.fType == *fContext.fColorSpaceXform_Type) {
type = "kMat44f_GrSLType"; type = "kHighFloat4x4_GrSLType";
} else if (var.fType == *fContext.fHalf4x4_Type) {
type = "kHalf4x4_GrSLType";
} else { } else {
ABORT("unsupported uniform type: %s %s;\n", String(var.fType.fName).c_str(), ABORT("unsupported uniform type: %s %s;\n", String(var.fType.fName).c_str(),
String(var.fName).c_str()); String(var.fName).c_str());
@ -457,11 +460,12 @@ void CPPCodeGenerator::writeSetData(std::vector<const Variable*>& uniforms) {
} }
String nameString(u->fName); String nameString(u->fName);
const char* name = nameString.c_str(); const char* name = nameString.c_str();
if (u->fType == *fContext.fFloat4_Type) { if (u->fType == *fContext.fFloat4_Type || u->fType == *fContext.fHalf4_Type) {
this->writef(" const SkRect %sValue = _outer.%s();\n" this->writef(" const SkRect %sValue = _outer.%s();\n"
" %s.set4fv(%sVar, 1, (float*) &%sValue);\n", " %s.set4fv(%sVar, 1, (float*) &%sValue);\n",
name, name, pdman, HCodeGenerator::FieldName(name).c_str(), name); name, name, pdman, HCodeGenerator::FieldName(name).c_str(), name);
} else if (u->fType == *fContext.fFloat4x4_Type) { } else if (u->fType == *fContext.fFloat4x4_Type ||
u->fType == *fContext.fHalf4x4_Type) {
this->writef(" float %sValue[16];\n" this->writef(" float %sValue[16];\n"
" _outer.%s().asColMajorf(%sValue);\n" " _outer.%s().asColMajorf(%sValue);\n"
" %s.setMatrix4f(%sVar, %sValue);\n", " %s.setMatrix4f(%sVar, %sValue);\n",

Some files were not shown because too many files have changed in this diff Show More