re-land of new SkSL precisions
Bug: skia: Change-Id: Ic1deb3db2cbda6ca45f93dee99832971a36a2119 Reviewed-on: https://skia-review.googlesource.com/47841 Commit-Queue: Ethan Nicholas <ethannicholas@google.com> Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
This commit is contained in:
parent
47a540f503
commit
f7b8820dc8
@ -111,9 +111,9 @@ GrGLuint GLCpuPosInstancedArraysBench::setupShader(const GrGLContext* ctx) {
|
||||
const char* version = shaderCaps->versionDeclString();
|
||||
|
||||
// setup vertex shader
|
||||
GrShaderVar aPosition("a_position", kVec2f_GrSLType, GrShaderVar::kIn_TypeModifier);
|
||||
GrShaderVar aColor("a_color", kVec3f_GrSLType, GrShaderVar::kIn_TypeModifier);
|
||||
GrShaderVar oColor("o_color", kVec3f_GrSLType, GrShaderVar::kOut_TypeModifier);
|
||||
GrShaderVar aPosition("a_position", kHalf2_GrSLType, GrShaderVar::kIn_TypeModifier);
|
||||
GrShaderVar aColor("a_color", kHalf3_GrSLType, GrShaderVar::kIn_TypeModifier);
|
||||
GrShaderVar oColor("o_color", kHalf3_GrSLType, GrShaderVar::kOut_TypeModifier);
|
||||
|
||||
SkString vshaderTxt(version);
|
||||
aPosition.appendDecl(shaderCaps, &vshaderTxt);
|
||||
@ -126,14 +126,13 @@ GrGLuint GLCpuPosInstancedArraysBench::setupShader(const GrGLContext* ctx) {
|
||||
vshaderTxt.append(
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
"gl_Position = float4(a_position, 0., 1.);\n"
|
||||
"gl_Position = highfloat4(a_position, 0., 1.);\n"
|
||||
"o_color = a_color;\n"
|
||||
"}\n");
|
||||
|
||||
// setup fragment shader
|
||||
GrShaderVar oFragColor("o_FragColor", kVec4f_GrSLType, GrShaderVar::kOut_TypeModifier);
|
||||
GrShaderVar oFragColor("o_FragColor", kHalf4_GrSLType, GrShaderVar::kOut_TypeModifier);
|
||||
SkString fshaderTxt(version);
|
||||
GrGLSLAppendDefaultFloatPrecisionDeclaration(kMedium_GrSLPrecision, *shaderCaps, &fshaderTxt);
|
||||
oColor.setTypeModifier(GrShaderVar::kIn_TypeModifier);
|
||||
oColor.appendDecl(shaderCaps, &fshaderTxt);
|
||||
fshaderTxt.append(";\n");
|
||||
@ -150,7 +149,7 @@ GrGLuint GLCpuPosInstancedArraysBench::setupShader(const GrGLContext* ctx) {
|
||||
fshaderTxt.appendf(
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
"%s = float4(o_color, 1.0);\n"
|
||||
"%s = highfloat4(o_color, 1.0);\n"
|
||||
"}\n", fsOutName);
|
||||
|
||||
return CreateProgram(ctx, vshaderTxt.c_str(), fshaderTxt.c_str());
|
||||
|
@ -101,10 +101,10 @@ GrGLuint GLVec4ScalarBench::setupShader(const GrGLContext* ctx) {
|
||||
// corner of the screen than the previous circle.
|
||||
|
||||
// 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 oPosition("o_position", kVec2f_GrSLType, GrShaderVar::kOut_TypeModifier);
|
||||
GrShaderVar aColor("a_color", kVec3f_GrSLType, GrShaderVar::kIn_TypeModifier);
|
||||
GrShaderVar oColor("o_color", kVec3f_GrSLType, GrShaderVar::kOut_TypeModifier);
|
||||
GrShaderVar aPosition("a_position", kHalf2_GrSLType, GrShaderVar::kIn_TypeModifier);
|
||||
GrShaderVar oPosition("o_position", kHalf2_GrSLType, GrShaderVar::kOut_TypeModifier);
|
||||
GrShaderVar aColor("a_color", kHalf3_GrSLType, GrShaderVar::kIn_TypeModifier);
|
||||
GrShaderVar oColor("o_color", kHalf3_GrSLType, GrShaderVar::kOut_TypeModifier);
|
||||
|
||||
SkString vshaderTxt(version);
|
||||
aPosition.appendDecl(shaderCaps, &vshaderTxt);
|
||||
@ -119,7 +119,7 @@ GrGLuint GLVec4ScalarBench::setupShader(const GrGLContext* ctx) {
|
||||
vshaderTxt.append(
|
||||
"void main()\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_color = a_color;\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.
|
||||
// Then, this coverage is mixed with the coverage from the previous stage and passed to the
|
||||
// next stage.
|
||||
GrShaderVar oFragColor("o_FragColor", kVec4f_GrSLType, GrShaderVar::kOut_TypeModifier);
|
||||
GrShaderVar oFragColor("o_FragColor", kHalf4_GrSLType, GrShaderVar::kOut_TypeModifier);
|
||||
SkString fshaderTxt(version);
|
||||
GrGLSLAppendDefaultFloatPrecisionDeclaration(kMedium_GrSLPrecision, *shaderCaps, &fshaderTxt);
|
||||
oPosition.setTypeModifier(GrShaderVar::kIn_TypeModifier);
|
||||
oPosition.appendDecl(shaderCaps, &fshaderTxt);
|
||||
fshaderTxt.append(";\n");
|
||||
@ -152,13 +151,13 @@ GrGLuint GLVec4ScalarBench::setupShader(const GrGLContext* ctx) {
|
||||
fshaderTxt.appendf(
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" float4 outputColor;\n"
|
||||
" half4 outputColor;\n"
|
||||
" %s outputCoverage;\n"
|
||||
" outputColor = float4(%s, 1.0);\n"
|
||||
" outputColor = half4(%s, 1.0);\n"
|
||||
" outputCoverage = %s;\n",
|
||||
fCoverageSetup == kUseVec4_CoverageSetup ? "float4" : "float",
|
||||
fCoverageSetup == kUseVec4_CoverageSetup ? "half4" : "half",
|
||||
oColor.getName().c_str(),
|
||||
fCoverageSetup == kUseVec4_CoverageSetup ? "float4(1.0)" : "1.0"
|
||||
fCoverageSetup == kUseVec4_CoverageSetup ? "half4(1.0)" : "1.0"
|
||||
);
|
||||
|
||||
float radius = 1.0f;
|
||||
@ -167,13 +166,13 @@ GrGLuint GLVec4ScalarBench::setupShader(const GrGLContext* ctx) {
|
||||
float centerY = 1.0f - radius;
|
||||
fshaderTxt.appendf(
|
||||
" {\n"
|
||||
" float d = length(%s - float2(%f, %f));\n"
|
||||
" float edgeAlpha = clamp(100.0 * (%f - d), 0.0, 1.0);\n"
|
||||
" half d = length(%s - half2(%f, %f));\n"
|
||||
" half edgeAlpha = clamp(100.0 * (%f - d), 0.0, 1.0);\n"
|
||||
" outputCoverage = 0.5 * outputCoverage + 0.5 * %s;\n"
|
||||
" }\n",
|
||||
oPosition.getName().c_str(), centerX, centerY,
|
||||
radius,
|
||||
fCoverageSetup == kUseVec4_CoverageSetup ? "float4(edgeAlpha)" : "edgeAlpha"
|
||||
fCoverageSetup == kUseVec4_CoverageSetup ? "half4(edgeAlpha)" : "edgeAlpha"
|
||||
);
|
||||
radius *= 0.8f;
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ GrGLuint GLVertexAttributesBench::setupShader(const GrGLContext* ctx, uint32_t a
|
||||
const char* version = shaderCaps->versionDeclString();
|
||||
|
||||
// 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> oVars;
|
||||
|
||||
@ -81,7 +81,7 @@ GrGLuint GLVertexAttributesBench::setupShader(const GrGLContext* ctx, uint32_t a
|
||||
SkString aname;
|
||||
aname.appendf("a_color_%d", i);
|
||||
aVars.push_back(GrShaderVar(aname.c_str(),
|
||||
kVec4f_GrSLType,
|
||||
kHalf4_GrSLType,
|
||||
GrShaderVar::kIn_TypeModifier));
|
||||
aVars.back().appendDecl(shaderCaps, &vshaderTxt);
|
||||
vshaderTxt.append(";\n");
|
||||
@ -92,7 +92,7 @@ GrGLuint GLVertexAttributesBench::setupShader(const GrGLContext* ctx, uint32_t a
|
||||
SkString oname;
|
||||
oname.appendf("o_color_%d", i);
|
||||
oVars.push_back(GrShaderVar(oname.c_str(),
|
||||
kVec4f_GrSLType,
|
||||
kHalf4_GrSLType,
|
||||
GrShaderVar::kOut_TypeModifier));
|
||||
oVars.back().appendDecl(shaderCaps, &vshaderTxt);
|
||||
vshaderTxt.append(";\n");
|
||||
@ -109,15 +109,14 @@ GrGLuint GLVertexAttributesBench::setupShader(const GrGLContext* ctx, uint32_t a
|
||||
|
||||
// Passthrough position as a dummy
|
||||
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");
|
||||
|
||||
// setup fragment shader
|
||||
GrShaderVar oFragColor("o_FragColor", kVec4f_GrSLType, GrShaderVar::kOut_TypeModifier);
|
||||
GrShaderVar oFragColor("o_FragColor", kHalf4_GrSLType, GrShaderVar::kOut_TypeModifier);
|
||||
SkString fshaderTxt(version);
|
||||
GrGLSLAppendDefaultFloatPrecisionDeclaration(kMedium_GrSLPrecision, *shaderCaps, &fshaderTxt);
|
||||
|
||||
const char* fsOutName;
|
||||
if (shaderCaps->mustDeclareFragmentShaderOutput()) {
|
||||
|
@ -95,19 +95,28 @@ GrAAType GrChooseAAType(GrAA, GrFSAAType, GrAllowMixedSamples, const GrCaps&);
|
||||
enum GrSLType {
|
||||
kVoid_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,
|
||||
kInt2_GrSLType,
|
||||
kInt3_GrSLType,
|
||||
kInt4_GrSLType,
|
||||
kUint_GrSLType,
|
||||
kFloat_GrSLType,
|
||||
kVec2f_GrSLType,
|
||||
kVec3f_GrSLType,
|
||||
kVec4f_GrSLType,
|
||||
kVec2us_GrSLType,
|
||||
kVec2i_GrSLType,
|
||||
kVec3i_GrSLType,
|
||||
kVec4i_GrSLType,
|
||||
kMat22f_GrSLType,
|
||||
kMat33f_GrSLType,
|
||||
kMat44f_GrSLType,
|
||||
kUint2_GrSLType,
|
||||
kTexture2DSampler_GrSLType,
|
||||
kITexture2DSampler_GrSLType,
|
||||
kTextureExternalSampler_GrSLType,
|
||||
@ -161,13 +170,20 @@ static const int kGrSLPrecisionCount = kLast_GrSLPrecision + 1;
|
||||
/** Is the shading language type float (including vectors/matrices)? */
|
||||
static inline bool GrSLTypeIsFloatType(GrSLType type) {
|
||||
switch (type) {
|
||||
case kFloat_GrSLType:
|
||||
case kVec2f_GrSLType:
|
||||
case kVec3f_GrSLType:
|
||||
case kVec4f_GrSLType:
|
||||
case kMat22f_GrSLType:
|
||||
case kMat33f_GrSLType:
|
||||
case kMat44f_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:
|
||||
return true;
|
||||
|
||||
case kVoid_GrSLType:
|
||||
@ -177,12 +193,14 @@ static inline bool GrSLTypeIsFloatType(GrSLType type) {
|
||||
case kTexture2DRectSampler_GrSLType:
|
||||
case kBufferSampler_GrSLType:
|
||||
case kBool_GrSLType:
|
||||
case kShort_GrSLType:
|
||||
case kUShort_GrSLType:
|
||||
case kInt_GrSLType:
|
||||
case kInt2_GrSLType:
|
||||
case kInt3_GrSLType:
|
||||
case kInt4_GrSLType:
|
||||
case kUint_GrSLType:
|
||||
case kVec2us_GrSLType:
|
||||
case kVec2i_GrSLType:
|
||||
case kVec3i_GrSLType:
|
||||
case kVec4i_GrSLType:
|
||||
case kUint2_GrSLType:
|
||||
case kTexture2D_GrSLType:
|
||||
case kSampler_GrSLType:
|
||||
case kImageStorage2D_GrSLType:
|
||||
@ -202,21 +220,30 @@ static inline bool GrSLTypeIs2DCombinedSamplerType(GrSLType type) {
|
||||
return true;
|
||||
|
||||
case kVoid_GrSLType:
|
||||
case kFloat_GrSLType:
|
||||
case kVec2f_GrSLType:
|
||||
case kVec3f_GrSLType:
|
||||
case kVec4f_GrSLType:
|
||||
case kVec2us_GrSLType:
|
||||
case kVec2i_GrSLType:
|
||||
case kVec3i_GrSLType:
|
||||
case kVec4i_GrSLType:
|
||||
case kMat22f_GrSLType:
|
||||
case kMat33f_GrSLType:
|
||||
case kMat44f_GrSLType:
|
||||
case kBufferSampler_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 kBufferSampler_GrSLType:
|
||||
case kBool_GrSLType:
|
||||
case kShort_GrSLType:
|
||||
case kUShort_GrSLType:
|
||||
case kTexture2D_GrSLType:
|
||||
case kSampler_GrSLType:
|
||||
case kImageStorage2D_GrSLType:
|
||||
@ -237,20 +264,29 @@ static inline bool GrSLTypeIsCombinedSamplerType(GrSLType type) {
|
||||
return true;
|
||||
|
||||
case kVoid_GrSLType:
|
||||
case kFloat_GrSLType:
|
||||
case kVec2f_GrSLType:
|
||||
case kVec3f_GrSLType:
|
||||
case kVec4f_GrSLType:
|
||||
case kVec2us_GrSLType:
|
||||
case kVec2i_GrSLType:
|
||||
case kVec3i_GrSLType:
|
||||
case kVec4i_GrSLType:
|
||||
case kMat22f_GrSLType:
|
||||
case kMat33f_GrSLType:
|
||||
case kMat44f_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 kBool_GrSLType:
|
||||
case kShort_GrSLType:
|
||||
case kUShort_GrSLType:
|
||||
case kTexture2D_GrSLType:
|
||||
case kSampler_GrSLType:
|
||||
case kImageStorage2D_GrSLType:
|
||||
@ -268,20 +304,29 @@ static inline bool GrSLTypeIsImageStorage(GrSLType type) {
|
||||
return true;
|
||||
|
||||
case kVoid_GrSLType:
|
||||
case kFloat_GrSLType:
|
||||
case kVec2f_GrSLType:
|
||||
case kVec3f_GrSLType:
|
||||
case kVec4f_GrSLType:
|
||||
case kVec2us_GrSLType:
|
||||
case kVec2i_GrSLType:
|
||||
case kVec3i_GrSLType:
|
||||
case kVec4i_GrSLType:
|
||||
case kMat22f_GrSLType:
|
||||
case kMat33f_GrSLType:
|
||||
case kMat44f_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 kBool_GrSLType:
|
||||
case kShort_GrSLType:
|
||||
case kUShort_GrSLType:
|
||||
case kTexture2D_GrSLType:
|
||||
case kSampler_GrSLType:
|
||||
case kTexture2DSampler_GrSLType:
|
||||
@ -297,19 +342,73 @@ static inline bool GrSLTypeIsImageStorage(GrSLType type) {
|
||||
|
||||
static inline bool GrSLTypeAcceptsPrecision(GrSLType 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 kInt2_GrSLType:
|
||||
case kInt3_GrSLType:
|
||||
case kInt4_GrSLType:
|
||||
case kUint_GrSLType:
|
||||
case kFloat_GrSLType:
|
||||
case kVec2f_GrSLType:
|
||||
case kVec3f_GrSLType:
|
||||
case kVec4f_GrSLType:
|
||||
case kVec2us_GrSLType:
|
||||
case kVec2i_GrSLType:
|
||||
case kVec3i_GrSLType:
|
||||
case kVec4i_GrSLType:
|
||||
case kMat22f_GrSLType:
|
||||
case kMat33f_GrSLType:
|
||||
case kMat44f_GrSLType:
|
||||
case kUint2_GrSLType:
|
||||
return false;
|
||||
}
|
||||
SK_ABORT("Unexpected type");
|
||||
return false;
|
||||
}
|
||||
|
||||
// temporarily accepting (but ignoring) precision modifiers on the new types; this will be killed
|
||||
// in a future CL
|
||||
static inline bool GrSLTypeTemporarilyAcceptsPrecision(GrSLType type) {
|
||||
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 kITexture2DSampler_GrSLType:
|
||||
case kTextureExternalSampler_GrSLType:
|
||||
@ -398,25 +497,25 @@ static inline size_t GrVertexAttribTypeSize(GrVertexAttribType type) {
|
||||
static inline GrSLType GrVertexAttribTypeToSLType(GrVertexAttribType type) {
|
||||
switch (type) {
|
||||
case kVec2us_norm_GrVertexAttribType: // fall through
|
||||
return kVec2f_GrSLType;
|
||||
return kHighFloat2_GrSLType;
|
||||
case kVec2us_uint_GrVertexAttribType:
|
||||
return kVec2us_GrSLType;
|
||||
return kUint2_GrSLType;
|
||||
case kUByte_GrVertexAttribType: // fall through
|
||||
case kFloat_GrVertexAttribType:
|
||||
return kFloat_GrSLType;
|
||||
return kHighFloat_GrSLType;
|
||||
case kVec2f_GrVertexAttribType:
|
||||
return kVec2f_GrSLType;
|
||||
return kHighFloat2_GrSLType;
|
||||
case kVec3f_GrVertexAttribType:
|
||||
return kVec3f_GrSLType;
|
||||
return kHighFloat3_GrSLType;
|
||||
case kVec4ub_GrVertexAttribType:
|
||||
case kVec4f_GrVertexAttribType:
|
||||
return kVec4f_GrSLType;
|
||||
return kHighFloat4_GrSLType;
|
||||
case kVec2i_GrVertexAttribType:
|
||||
return kVec2i_GrSLType;
|
||||
return kInt2_GrSLType;
|
||||
case kVec3i_GrVertexAttribType:
|
||||
return kVec3i_GrSLType;
|
||||
return kInt3_GrSLType;
|
||||
case kVec4i_GrVertexAttribType:
|
||||
return kVec4i_GrSLType;
|
||||
return kInt4_GrSLType;
|
||||
case kInt_GrVertexAttribType:
|
||||
return kInt_GrSLType;
|
||||
case kUint_GrVertexAttribType:
|
||||
|
@ -201,23 +201,21 @@ private:
|
||||
|
||||
void emitCode(EmitArgs& args) override {
|
||||
GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
|
||||
fMatrixHandle = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kMat44f_GrSLType, kDefault_GrSLPrecision,
|
||||
fMatrixHandle = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4x4_GrSLType,
|
||||
"ColorMatrix");
|
||||
fVectorHandle = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kVec4f_GrSLType, kDefault_GrSLPrecision,
|
||||
fVectorHandle = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType,
|
||||
"ColorMatrixVector");
|
||||
|
||||
if (nullptr == args.fInputColor) {
|
||||
// could optimize this case, but we aren't for now.
|
||||
args.fInputColor = "float4(1)";
|
||||
args.fInputColor = "half4(1)";
|
||||
}
|
||||
GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder;
|
||||
// The max() is to guard against 0 / 0 during unpremul when the incoming color is
|
||||
// transparent black.
|
||||
fragBuilder->codeAppendf("\tfloat nonZeroAlpha = max(%s.a, 0.00001);\n",
|
||||
fragBuilder->codeAppendf("\thalf nonZeroAlpha = max(%s.a, 0.00001);\n",
|
||||
args.fInputColor);
|
||||
fragBuilder->codeAppendf("\t%s = %s * float4(%s.rgb / nonZeroAlpha, nonZeroAlpha) + "
|
||||
fragBuilder->codeAppendf("\t%s = %s * half4(%s.rgb / nonZeroAlpha, nonZeroAlpha) + "
|
||||
"%s;\n",
|
||||
args.fOutputColor,
|
||||
uniformHandler->getUniformCStr(fMatrixHandle),
|
||||
|
@ -36,24 +36,25 @@ public:
|
||||
(void)_outer;
|
||||
fColorSpaceHelper.emitCode(args.fUniformHandler, _outer.colorXform().get());
|
||||
fInnerThresholdVar = args.fUniformHandler->addUniform(
|
||||
kFragment_GrShaderFlag, kFloat_GrSLType, kDefault_GrSLPrecision, "innerThreshold");
|
||||
kFragment_GrShaderFlag, kHalf_GrSLType, kDefault_GrSLPrecision, "innerThreshold");
|
||||
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_1 = fragBuilder->ensureCoords2D(args.fTransformedCoords[1]);
|
||||
fragBuilder->codeAppendf(
|
||||
"float4 _tmpVar1;float4 color = %stexture(%s, %s).%s%s;\nfloat4 mask_color = "
|
||||
"texture(%s, %s).%s;\nif (mask_color.w < 0.5) {\n if (color.w > %s) {\n "
|
||||
"float scale = %s / color.w;\n color.xyz *= scale;\n color.w = %s;\n "
|
||||
" }\n} else if (color.w < %s) {\n float scale = %s / max(0.001, color.w);\n "
|
||||
" color.xyz *= scale;\n color.w = %s;\n}\n%s = color;\n",
|
||||
"half4 _tmpVar1;half4 color = %stexture(%s, %s).%s%s;\nhalf4 mask_color = "
|
||||
"texture(%s, %s).%s;\nif (highfloat(mask_color.w) < 0.5) {\n if (color.w > %s) "
|
||||
"{\n half scale = %s / color.w;\n color.xyz *= scale;\n "
|
||||
"color.w = %s;\n }\n} else if (color.w < %s) {\n half scale = highfloat(%s) "
|
||||
"/ max(0.001, highfloat(color.w));\n color.xyz *= scale;\n color.w = "
|
||||
"%s;\n}\n%s = color;\n",
|
||||
fColorSpaceHelper.isValid() ? "(_tmpVar1 = " : "",
|
||||
fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]).c_str(),
|
||||
sk_TransformedCoords2D_0.c_str(),
|
||||
fragBuilder->getProgramBuilder()->samplerSwizzle(args.fTexSamplers[0]).c_str(),
|
||||
fColorSpaceHelper.isValid()
|
||||
? SkStringPrintf(", float4(clamp((%s * float4(_tmpVar1.rgb, 1.0)).rgb, "
|
||||
"0.0, _tmpVar1.a), _tmpVar1.a))",
|
||||
? SkStringPrintf(", half4(clamp((%s * half4(_tmpVar1.rgb, 1.0)).rgb, 0.0, "
|
||||
"_tmpVar1.a), _tmpVar1.a))",
|
||||
args.fUniformHandler->getUniformCStr(
|
||||
fColorSpaceHelper.gamutXformUniform()))
|
||||
.c_str()
|
||||
|
@ -1,8 +1,8 @@
|
||||
in uniform sampler2D image;
|
||||
in uniform colorSpaceXform colorXform;
|
||||
in uniform sampler2D mask;
|
||||
in uniform float innerThreshold;
|
||||
in uniform float outerThreshold;
|
||||
in uniform half innerThreshold;
|
||||
in uniform half outerThreshold;
|
||||
|
||||
@class {
|
||||
inline OptimizationFlags optFlags(float outerThreshold);
|
||||
@ -49,16 +49,16 @@ in uniform float outerThreshold;
|
||||
}
|
||||
|
||||
void main() {
|
||||
float4 color = texture(image, sk_TransformedCoords2D[0], colorXform);
|
||||
float4 mask_color = texture(mask, sk_TransformedCoords2D[1]);
|
||||
half4 color = texture(image, sk_TransformedCoords2D[0], colorXform);
|
||||
half4 mask_color = texture(mask, sk_TransformedCoords2D[1]);
|
||||
if (mask_color.a < 0.5) {
|
||||
if (color.a > outerThreshold) {
|
||||
float scale = outerThreshold / color.a;
|
||||
half scale = outerThreshold / color.a;
|
||||
color.rgb *= scale;
|
||||
color.a = outerThreshold;
|
||||
}
|
||||
} 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.a = innerThreshold;
|
||||
}
|
||||
|
@ -263,19 +263,20 @@ public:
|
||||
const GrCircleBlurFragmentProcessor& _outer =
|
||||
args.fFp.cast<GrCircleBlurFragmentProcessor>();
|
||||
(void)_outer;
|
||||
fCircleDataVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kVec4f_GrSLType,
|
||||
fCircleDataVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType,
|
||||
kDefault_GrSLPrecision, "circleData");
|
||||
fragBuilder->codeAppendf(
|
||||
"float2 vec = float2((sk_FragCoord.x - %s.x) * %s.w, (sk_FragCoord.y - %s.y) * "
|
||||
"%s.w);\nfloat dist = length(vec) + (0.5 - %s.z) * %s.w;\n%s = %s * texture(%s, "
|
||||
"float2(dist, 0.5)).%s.w;\n",
|
||||
"half2 vec = half2(half((sk_FragCoord.x - highfloat(%s.x)) * highfloat(%s.w)), "
|
||||
"half((sk_FragCoord.y - highfloat(%s.y)) * highfloat(%s.w)));\nhalf dist = "
|
||||
"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.fOutputColor,
|
||||
args.fInputColor ? args.fInputColor : "float4(1)",
|
||||
args.fInputColor ? args.fInputColor : "half4(1)",
|
||||
fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]).c_str(),
|
||||
fragBuilder->getProgramBuilder()->samplerSwizzle(args.fTexSamplers[0]).c_str());
|
||||
}
|
||||
|
@ -1,13 +1,13 @@
|
||||
in float4 circleRect;
|
||||
in float textureRadius;
|
||||
in float solidRadius;
|
||||
in half4 circleRect;
|
||||
in half textureRadius;
|
||||
in half solidRadius;
|
||||
in uniform sampler2D blurProfileSampler;
|
||||
|
||||
// The data is formatted as:
|
||||
// x, y - the center of the circle
|
||||
// z - inner radius that should map to 0th entry in the texture.
|
||||
// w - the inverse of the distance over which the texture is stretched.
|
||||
uniform float4 circleData;
|
||||
uniform half4 circleData;
|
||||
|
||||
@optimizationFlags {
|
||||
kCompatibleWithCoverageAsAlpha_OptimizationFlag
|
||||
@ -273,10 +273,10 @@ uniform float4 circleData;
|
||||
void main() {
|
||||
// We just want to compute "(length(vec) - circleData.z + 0.5) * circleData.w" but need to
|
||||
// rearrange for precision.
|
||||
float2 vec = float2((sk_FragCoord.x - circleData.x) * circleData.w,
|
||||
(sk_FragCoord.y - circleData.y) * circleData.w);
|
||||
float dist = length(vec) + (0.5 - circleData.z) * circleData.w;
|
||||
sk_OutColor = sk_InColor * texture(blurProfileSampler, float2(dist, 0.5)).a;
|
||||
half2 vec = half2((sk_FragCoord.x - circleData.x) * circleData.w,
|
||||
(sk_FragCoord.y - circleData.y) * circleData.w);
|
||||
half dist = length(vec) + (0.5 - circleData.z) * circleData.w;
|
||||
sk_OutColor = sk_InColor * texture(blurProfileSampler, half2(dist, 0.5)).a;
|
||||
}
|
||||
|
||||
@test(testData) {
|
||||
|
@ -302,18 +302,18 @@ private:
|
||||
SkString dstColor("dstColor");
|
||||
this->emitChild(0, &dstColor, args);
|
||||
|
||||
fKUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kVec4f_GrSLType,
|
||||
kDefault_GrSLPrecision, "k");
|
||||
fKUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType,
|
||||
"k");
|
||||
const char* kUni = args.fUniformHandler->getUniformCStr(fKUni);
|
||||
|
||||
// We don't try to optimize for this case at all
|
||||
if (!args.fInputColor) {
|
||||
fragBuilder->codeAppend("const float4 src = float4(1);");
|
||||
fragBuilder->codeAppend("const half4 src = half4(1);");
|
||||
} 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;",
|
||||
args.fOutputColor, kUni, kUni, kUni, kUni);
|
||||
fragBuilder->codeAppendf("%s = clamp(%s, 0.0, 1.0);\n", args.fOutputColor,
|
||||
|
@ -862,12 +862,12 @@ void OutputRectBlurProfileLookup(GrGLSLFPFragmentBuilder* fragBuilder,
|
||||
const char *profileSize, const char *loc,
|
||||
const char *blurred_width,
|
||||
const char *sharp_width) {
|
||||
fragBuilder->codeAppendf("float %s;", output);
|
||||
fragBuilder->codeAppendf("half %s;", output);
|
||||
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);
|
||||
fragBuilder->codeAppendf("%s = ", output);
|
||||
fragBuilder->appendTextureLookup(sampler, "float2(coord,0.5)");
|
||||
fragBuilder->appendTextureLookup(sampler, "half2(coord,0.5)");
|
||||
fragBuilder->codeAppend(".a;");
|
||||
fragBuilder->codeAppendf("}");
|
||||
}
|
||||
@ -889,49 +889,41 @@ void GrGLRectBlurEffect::emitCode(EmitArgs& args) {
|
||||
const char *rectName;
|
||||
const char *profileSizeName;
|
||||
|
||||
SkString precisionString;
|
||||
if (args.fShaderCaps->usesPrecisionModifiers()) {
|
||||
precisionString.printf("%s ", GrGLSLPrecisionString(rbe.precision()));
|
||||
}
|
||||
const char* floatType = rbe.precision() == kHigh_GrSLPrecision ? "highfloat" : "half";
|
||||
fProxyRectUniform = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kVec4f_GrSLType,
|
||||
rbe.precision(),
|
||||
rbe.precision() == kHigh_GrSLPrecision ?
|
||||
kHighFloat4_GrSLType : kHalf4_GrSLType,
|
||||
"proxyRect",
|
||||
&rectName);
|
||||
fProfileSizeUniform = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kFloat_GrSLType,
|
||||
kDefault_GrSLPrecision,
|
||||
kHalf_GrSLType,
|
||||
"profileSize",
|
||||
&profileSizeName);
|
||||
|
||||
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
|
||||
|
||||
if (args.fInputColor) {
|
||||
fragBuilder->codeAppendf("float4 src=%s;", args.fInputColor);
|
||||
fragBuilder->codeAppendf("half4 src=%s;", args.fInputColor);
|
||||
} else {
|
||||
fragBuilder->codeAppendf("float4 src=float4(1);");
|
||||
fragBuilder->codeAppendf("half4 src=half4(1);");
|
||||
}
|
||||
|
||||
fragBuilder->codeAppendf("%s float2 translatedPos = sk_FragCoord.xy - %s.xy;",
|
||||
precisionString.c_str(), rectName);
|
||||
fragBuilder->codeAppendf("%s float width = %s.z - %s.x;", precisionString.c_str(), rectName,
|
||||
rectName);
|
||||
fragBuilder->codeAppendf("%s float height = %s.w - %s.y;", precisionString.c_str(), rectName,
|
||||
rectName);
|
||||
fragBuilder->codeAppendf("%s2 translatedPos = sk_FragCoord.xy - %s.xy;", floatType, rectName);
|
||||
fragBuilder->codeAppendf("%s width = %s.z - %s.x;", floatType, rectName, rectName);
|
||||
fragBuilder->codeAppendf("%s height = %s.w - %s.y;", floatType, rectName, rectName);
|
||||
|
||||
fragBuilder->codeAppendf("%s float2 smallDims = float2(width - %s, height - %s);",
|
||||
precisionString.c_str(), profileSizeName, profileSizeName);
|
||||
fragBuilder->codeAppendf("%s float center = 2.0 * floor(%s/2.0 + .25) - 1.0;",
|
||||
precisionString.c_str(), profileSizeName);
|
||||
fragBuilder->codeAppendf("%s float2 wh = smallDims - float2(center,center);",
|
||||
precisionString.c_str());
|
||||
fragBuilder->codeAppendf("%s2 smallDims = half2(width - %s, height - %s);", floatType,
|
||||
profileSizeName, profileSizeName);
|
||||
fragBuilder->codeAppendf("%s center = 2.0 * floor(%s/2.0 + .25) - 1.0;", floatType,
|
||||
profileSizeName);
|
||||
fragBuilder->codeAppendf("%s2 wh = smallDims - half2(center,center);", floatType);
|
||||
|
||||
OutputRectBlurProfileLookup(fragBuilder, args.fTexSamplers[0], "horiz_lookup", profileSizeName,
|
||||
"translatedPos.x", "width", "wh.x");
|
||||
OutputRectBlurProfileLookup(fragBuilder, args.fTexSamplers[0], "vert_lookup", profileSizeName,
|
||||
"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);
|
||||
}
|
||||
|
||||
@ -1277,18 +1269,15 @@ void GrGLRRectBlurEffect::emitCode(EmitArgs& args) {
|
||||
// components x, y, z, and w, respectively.
|
||||
|
||||
fProxyRectUniform = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kVec4f_GrSLType,
|
||||
kDefault_GrSLPrecision,
|
||||
kHalf4_GrSLType,
|
||||
"proxyRect",
|
||||
&rectName);
|
||||
fCornerRadiusUniform = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kFloat_GrSLType,
|
||||
kDefault_GrSLPrecision,
|
||||
kHalf_GrSLType,
|
||||
"cornerRadius",
|
||||
&cornerRadiusName);
|
||||
fBlurRadiusUniform = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kFloat_GrSLType,
|
||||
kDefault_GrSLPrecision,
|
||||
kHalf_GrSLType,
|
||||
"blurRadius",
|
||||
&blurRadiusName);
|
||||
|
||||
@ -1296,10 +1285,10 @@ void GrGLRRectBlurEffect::emitCode(EmitArgs& args) {
|
||||
|
||||
// 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("float2 translatedFragPos = sk_FragCoord.xy - %s.xy;", rectName);
|
||||
fragBuilder->codeAppendf("float threshold = %s + 2.0*%s;", cornerRadiusName, blurRadiusName);
|
||||
fragBuilder->codeAppendf("float2 middle = %s.zw - %s.xy - 2.0*threshold;", rectName, rectName);
|
||||
fragBuilder->codeAppendf("half2 rectCenter = (%s.xy + %s.zw)/2.0;", rectName, rectName);
|
||||
fragBuilder->codeAppendf("half2 translatedFragPos = sk_FragCoord.xy - %s.xy;", rectName);
|
||||
fragBuilder->codeAppendf("half threshold = %s + 2.0*%s;", cornerRadiusName, blurRadiusName);
|
||||
fragBuilder->codeAppendf("half2 middle = %s.zw - %s.xy - 2.0*threshold;", rectName, rectName);
|
||||
|
||||
fragBuilder->codeAppendf(
|
||||
"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("}");
|
||||
|
||||
fragBuilder->codeAppendf("float2 proxyDims = float2(2.0*threshold+1.0);");
|
||||
fragBuilder->codeAppendf("float2 texCoord = translatedFragPos / proxyDims;");
|
||||
fragBuilder->codeAppendf("half2 proxyDims = half2(2.0*threshold+1.0);");
|
||||
fragBuilder->codeAppendf("half2 texCoord = translatedFragPos / proxyDims;");
|
||||
|
||||
fragBuilder->codeAppendf("%s = ", args.fOutputColor);
|
||||
fragBuilder->appendTextureLookupAndModulate(args.fInputColor, args.fTexSamplers[0], "texCoord");
|
||||
|
@ -552,8 +552,7 @@ void GrGLDisplacementMapEffect::emitCode(EmitArgs& args) {
|
||||
const GrDisplacementMapEffect& displacementMap = args.fFp.cast<GrDisplacementMapEffect>();
|
||||
const GrTextureDomain& domain = displacementMap.domain();
|
||||
|
||||
fScaleUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kVec2f_GrSLType, kDefault_GrSLPrecision, "Scale");
|
||||
fScaleUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType, "Scale");
|
||||
const char* scaleUni = args.fUniformHandler->getUniformCStr(fScaleUni);
|
||||
const char* dColor = "dColor";
|
||||
const char* cCoords = "cCoords";
|
||||
@ -564,17 +563,17 @@ void GrGLDisplacementMapEffect::emitCode(EmitArgs& args) {
|
||||
fColorSpaceHelper.emitCode(args.fUniformHandler, displacementMap.colorSpaceXform());
|
||||
|
||||
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(),
|
||||
args.fTransformedCoords[0].getType());
|
||||
fragBuilder->codeAppend(";\n");
|
||||
|
||||
// Unpremultiply the displacement
|
||||
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);
|
||||
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);
|
||||
|
||||
switch (displacementMap.xChannelSelector()) {
|
||||
@ -612,7 +611,7 @@ void GrGLDisplacementMapEffect::emitCode(EmitArgs& args) {
|
||||
default:
|
||||
SkDEBUGFAIL("Unknown Y channel selector");
|
||||
}
|
||||
fragBuilder->codeAppend("-float2(0.5));\t\t");
|
||||
fragBuilder->codeAppend("-half2(0.5));\t\t");
|
||||
|
||||
fGLDomain.sampleTexture(fragBuilder,
|
||||
args.fUniformHandler,
|
||||
|
@ -247,47 +247,46 @@ void GLHighContrastFilterEffect::GenKey(
|
||||
|
||||
void GLHighContrastFilterEffect::emitCode(EmitArgs& args) {
|
||||
const char* contrast;
|
||||
fContrastUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kFloat_GrSLType, kDefault_GrSLPrecision,
|
||||
fContrastUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType,
|
||||
"contrast", &contrast);
|
||||
|
||||
if (nullptr == args.fInputColor) {
|
||||
args.fInputColor = "float4(1)";
|
||||
args.fInputColor = "half4(1)";
|
||||
}
|
||||
|
||||
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.
|
||||
fragBuilder->codeAppendf("float nonZeroAlpha = max(color.a, 0.00001);");
|
||||
fragBuilder->codeAppendf("color = float4(color.rgb / nonZeroAlpha, nonZeroAlpha);");
|
||||
fragBuilder->codeAppendf("half nonZeroAlpha = max(color.a, 0.00001);");
|
||||
fragBuilder->codeAppendf("color = half4(color.rgb / nonZeroAlpha, nonZeroAlpha);");
|
||||
|
||||
// Grayscale.
|
||||
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);
|
||||
fragBuilder->codeAppendf("color = float4(luma, luma, luma, 0);");
|
||||
fragBuilder->codeAppendf("color = half4(luma, luma, luma, 0);");
|
||||
}
|
||||
|
||||
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) {
|
||||
// Convert from RGB to HSL.
|
||||
fragBuilder->codeAppendf("float fmax = max(color.r, max(color.g, color.b));");
|
||||
fragBuilder->codeAppendf("float fmin = min(color.r, min(color.g, color.b));");
|
||||
fragBuilder->codeAppendf("float l = (fmax + fmin) / 2;");
|
||||
fragBuilder->codeAppendf("half fmax = max(color.r, max(color.g, color.b));");
|
||||
fragBuilder->codeAppendf("half fmin = min(color.r, min(color.g, color.b));");
|
||||
fragBuilder->codeAppendf("half l = (fmax + fmin) / 2;");
|
||||
|
||||
fragBuilder->codeAppendf("float h;");
|
||||
fragBuilder->codeAppendf("float s;");
|
||||
fragBuilder->codeAppendf("half h;");
|
||||
fragBuilder->codeAppendf("half s;");
|
||||
|
||||
fragBuilder->codeAppendf("if (fmax == fmin) {");
|
||||
fragBuilder->codeAppendf(" h = 0;");
|
||||
fragBuilder->codeAppendf(" s = 0;");
|
||||
fragBuilder->codeAppendf("} else {");
|
||||
fragBuilder->codeAppendf(" float d = fmax - fmin;");
|
||||
fragBuilder->codeAppendf(" half d = fmax - fmin;");
|
||||
fragBuilder->codeAppendf(" s = l > 0.5 ?");
|
||||
fragBuilder->codeAppendf(" d / (2 - fmax - fmin) :");
|
||||
fragBuilder->codeAppendf(" d / (fmax + fmin);");
|
||||
@ -305,11 +304,11 @@ void GLHighContrastFilterEffect::emitCode(EmitArgs& args) {
|
||||
// Convert back from HSL to RGB.
|
||||
SkString hue2rgbFuncName;
|
||||
static const GrShaderVar gHue2rgbArgs[] = {
|
||||
GrShaderVar("p", kFloat_GrSLType),
|
||||
GrShaderVar("q", kFloat_GrSLType),
|
||||
GrShaderVar("t", kFloat_GrSLType),
|
||||
GrShaderVar("p", kHalf_GrSLType),
|
||||
GrShaderVar("q", kHalf_GrSLType),
|
||||
GrShaderVar("t", kHalf_GrSLType),
|
||||
};
|
||||
fragBuilder->emitFunction(kFloat_GrSLType,
|
||||
fragBuilder->emitFunction(kHalf_GrSLType,
|
||||
"hue2rgb",
|
||||
SK_ARRAY_COUNT(gHue2rgbArgs),
|
||||
gHue2rgbArgs,
|
||||
@ -326,10 +325,10 @@ void GLHighContrastFilterEffect::emitCode(EmitArgs& args) {
|
||||
"return p;",
|
||||
&hue2rgbFuncName);
|
||||
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(" float q = l < 0.5 ? l * (1 + s) : l + s - l * s;");
|
||||
fragBuilder->codeAppendf(" float p = 2 * l - q;");
|
||||
fragBuilder->codeAppendf(" half q = l < 0.5 ? l * (1 + s) : l + s - l * s;");
|
||||
fragBuilder->codeAppendf(" half p = 2 * l - q;");
|
||||
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.b = %s(p, q, h - 1/3.);", hue2rgbFuncName.c_str());
|
||||
@ -338,8 +337,8 @@ void GLHighContrastFilterEffect::emitCode(EmitArgs& args) {
|
||||
|
||||
// Contrast.
|
||||
fragBuilder->codeAppendf("if (%s != 0) {", contrast);
|
||||
fragBuilder->codeAppendf(" float m = (1 + %s) / (1 - %s);", contrast, contrast);
|
||||
fragBuilder->codeAppendf(" float off = (-0.5 * m + 0.5);");
|
||||
fragBuilder->codeAppendf(" half m = (1 + %s) / (1 - %s);", contrast, contrast);
|
||||
fragBuilder->codeAppendf(" half off = (-0.5 * m + 0.5);");
|
||||
fragBuilder->codeAppendf(" color = m * color + off;");
|
||||
fragBuilder->codeAppendf("}");
|
||||
|
||||
|
@ -724,7 +724,7 @@ public:
|
||||
|
||||
/**
|
||||
* This is called by GrGLLightingEffect::emitCode() before either of the two virtual functions
|
||||
* below. It adds a vec3f uniform visible in the FS that represents the constant light color.
|
||||
* below. It adds a half3 uniform visible in the FS that represents the constant light color.
|
||||
*/
|
||||
void emitLightColorUniform(GrGLSLUniformHandler*);
|
||||
|
||||
@ -1827,63 +1827,61 @@ void GrGLLightingEffect::emitCode(EmitArgs& args) {
|
||||
|
||||
GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
|
||||
fImageIncrementUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kVec2f_GrSLType, kDefault_GrSLPrecision,
|
||||
"ImageIncrement");
|
||||
kHalf2_GrSLType, "ImageIncrement");
|
||||
fSurfaceScaleUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kFloat_GrSLType, kDefault_GrSLPrecision,
|
||||
"SurfaceScale");
|
||||
kHalf_GrSLType, "SurfaceScale");
|
||||
fLight->emitLightColorUniform(uniformHandler);
|
||||
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
|
||||
SkString lightFunc;
|
||||
this->emitLightFunc(uniformHandler, fragBuilder, &lightFunc);
|
||||
static const GrShaderVar gSobelArgs[] = {
|
||||
GrShaderVar("a", kFloat_GrSLType),
|
||||
GrShaderVar("b", kFloat_GrSLType),
|
||||
GrShaderVar("c", kFloat_GrSLType),
|
||||
GrShaderVar("d", kFloat_GrSLType),
|
||||
GrShaderVar("e", kFloat_GrSLType),
|
||||
GrShaderVar("f", kFloat_GrSLType),
|
||||
GrShaderVar("scale", kFloat_GrSLType),
|
||||
GrShaderVar("a", kHalf_GrSLType),
|
||||
GrShaderVar("b", kHalf_GrSLType),
|
||||
GrShaderVar("c", kHalf_GrSLType),
|
||||
GrShaderVar("d", kHalf_GrSLType),
|
||||
GrShaderVar("e", kHalf_GrSLType),
|
||||
GrShaderVar("f", kHalf_GrSLType),
|
||||
GrShaderVar("scale", kHalf_GrSLType),
|
||||
};
|
||||
SkString sobelFuncName;
|
||||
SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
|
||||
|
||||
fragBuilder->emitFunction(kFloat_GrSLType,
|
||||
fragBuilder->emitFunction(kHalf_GrSLType,
|
||||
"sobel",
|
||||
SK_ARRAY_COUNT(gSobelArgs),
|
||||
gSobelArgs,
|
||||
"\treturn (-a + b - 2.0 * c + 2.0 * d -e + f) * scale;\n",
|
||||
&sobelFuncName);
|
||||
static const GrShaderVar gPointToNormalArgs[] = {
|
||||
GrShaderVar("x", kFloat_GrSLType),
|
||||
GrShaderVar("y", kFloat_GrSLType),
|
||||
GrShaderVar("scale", kFloat_GrSLType),
|
||||
GrShaderVar("x", kHalf_GrSLType),
|
||||
GrShaderVar("y", kHalf_GrSLType),
|
||||
GrShaderVar("scale", kHalf_GrSLType),
|
||||
};
|
||||
SkString pointToNormalName;
|
||||
fragBuilder->emitFunction(kVec3f_GrSLType,
|
||||
fragBuilder->emitFunction(kHalf3_GrSLType,
|
||||
"pointToNormal",
|
||||
SK_ARRAY_COUNT(gPointToNormalArgs),
|
||||
gPointToNormalArgs,
|
||||
"\treturn normalize(float3(-x * scale, -y * scale, 1));\n",
|
||||
"\treturn normalize(half3(-x * scale, -y * scale, 1));\n",
|
||||
&pointToNormalName);
|
||||
|
||||
static const GrShaderVar gInteriorNormalArgs[] = {
|
||||
GrShaderVar("m", kFloat_GrSLType, 9),
|
||||
GrShaderVar("surfaceScale", kFloat_GrSLType),
|
||||
GrShaderVar("m", kHalf_GrSLType, 9),
|
||||
GrShaderVar("surfaceScale", kHalf_GrSLType),
|
||||
};
|
||||
SkString normalBody = emitNormalFunc(le.boundaryMode(),
|
||||
pointToNormalName.c_str(),
|
||||
sobelFuncName.c_str());
|
||||
SkString normalName;
|
||||
fragBuilder->emitFunction(kVec3f_GrSLType,
|
||||
fragBuilder->emitFunction(kHalf3_GrSLType,
|
||||
"normal",
|
||||
SK_ARRAY_COUNT(gInteriorNormalArgs),
|
||||
gInteriorNormalArgs,
|
||||
normalBody.c_str(),
|
||||
&normalName);
|
||||
|
||||
fragBuilder->codeAppendf("\t\tfloat2 coord = %s;\n", coords2D.c_str());
|
||||
fragBuilder->codeAppend("\t\tfloat m[9];\n");
|
||||
fragBuilder->codeAppendf("\t\thighfloat2 coord = %s;\n", coords2D.c_str());
|
||||
fragBuilder->codeAppend("\t\thalf m[9];\n");
|
||||
|
||||
const char* imgInc = uniformHandler->getUniformCStr(fImageIncrementUni);
|
||||
const char* surfScale = uniformHandler->getUniformCStr(fSurfaceScaleUni);
|
||||
@ -1892,10 +1890,10 @@ void GrGLLightingEffect::emitCode(EmitArgs& args) {
|
||||
for (int dy = 1; dy >= -1; dy--) {
|
||||
for (int dx = -1; dx <= 1; dx++) {
|
||||
SkString texCoords;
|
||||
texCoords.appendf("coord + float2(%d, %d) * %s", dx, dy, imgInc);
|
||||
texCoords.appendf("coord + half2(%d, %d) * %s", dx, dy, imgInc);
|
||||
SkString temp;
|
||||
temp.appendf("temp%d", index);
|
||||
fragBuilder->codeAppendf("float4 %s;", temp.c_str());
|
||||
fragBuilder->codeAppendf("half4 %s;", temp.c_str());
|
||||
fDomain.sampleTexture(fragBuilder,
|
||||
args.fUniformHandler,
|
||||
args.fShaderCaps,
|
||||
@ -1907,7 +1905,7 @@ void GrGLLightingEffect::emitCode(EmitArgs& args) {
|
||||
index++;
|
||||
}
|
||||
}
|
||||
fragBuilder->codeAppend("\t\tfloat3 surfaceToLight = ");
|
||||
fragBuilder->codeAppend("\t\thalf3 surfaceToLight = ");
|
||||
SkString arg;
|
||||
arg.appendf("%s * m[4]", surfScale);
|
||||
fLight->emitSurfaceToLight(uniformHandler, fragBuilder, arg.c_str());
|
||||
@ -1953,19 +1951,17 @@ void GrGLDiffuseLightingEffect::emitLightFunc(GrGLSLUniformHandler* uniformHandl
|
||||
GrGLSLFPFragmentBuilder* fragBuilder,
|
||||
SkString* funcName) {
|
||||
const char* kd;
|
||||
fKDUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kFloat_GrSLType, kDefault_GrSLPrecision,
|
||||
"KD", &kd);
|
||||
fKDUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType, "KD", &kd);
|
||||
|
||||
static const GrShaderVar gLightArgs[] = {
|
||||
GrShaderVar("normal", kVec3f_GrSLType),
|
||||
GrShaderVar("surfaceToLight", kVec3f_GrSLType),
|
||||
GrShaderVar("lightColor", kVec3f_GrSLType)
|
||||
GrShaderVar("normal", kHalf3_GrSLType),
|
||||
GrShaderVar("surfaceToLight", kHalf3_GrSLType),
|
||||
GrShaderVar("lightColor", kHalf3_GrSLType)
|
||||
};
|
||||
SkString lightBody;
|
||||
lightBody.appendf("\tfloat colorScale = %s * dot(normal, surfaceToLight);\n", kd);
|
||||
lightBody.appendf("\treturn float4(lightColor * clamp(colorScale, 0.0, 1.0), 1.0);\n");
|
||||
fragBuilder->emitFunction(kVec4f_GrSLType,
|
||||
lightBody.appendf("\thalf colorScale = %s * dot(normal, surfaceToLight);\n", kd);
|
||||
lightBody.appendf("\treturn half4(lightColor * clamp(colorScale, 0.0, 1.0), 1.0);\n");
|
||||
fragBuilder->emitFunction(kHalf4_GrSLType,
|
||||
"light",
|
||||
SK_ARRAY_COUNT(gLightArgs),
|
||||
gLightArgs,
|
||||
@ -2051,26 +2047,24 @@ void GrGLSpecularLightingEffect::emitLightFunc(GrGLSLUniformHandler* uniformHand
|
||||
const char* ks;
|
||||
const char* shininess;
|
||||
|
||||
fKSUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kFloat_GrSLType, kDefault_GrSLPrecision, "KS", &ks);
|
||||
fKSUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType, "KS", &ks);
|
||||
fShininessUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kFloat_GrSLType,
|
||||
kDefault_GrSLPrecision,
|
||||
kHalf_GrSLType,
|
||||
"Shininess",
|
||||
&shininess);
|
||||
|
||||
static const GrShaderVar gLightArgs[] = {
|
||||
GrShaderVar("normal", kVec3f_GrSLType),
|
||||
GrShaderVar("surfaceToLight", kVec3f_GrSLType),
|
||||
GrShaderVar("lightColor", kVec3f_GrSLType)
|
||||
GrShaderVar("normal", kHalf3_GrSLType),
|
||||
GrShaderVar("surfaceToLight", kHalf3_GrSLType),
|
||||
GrShaderVar("lightColor", kHalf3_GrSLType)
|
||||
};
|
||||
SkString lightBody;
|
||||
lightBody.appendf("\tfloat3 halfDir = float3(normalize(surfaceToLight + float3(0, 0, 1)));\n");
|
||||
lightBody.appendf("\thighp float colorScale = %s * pow(dot(normal, halfDir), %s);\n",
|
||||
lightBody.appendf("\thalf3 halfDir = half3(normalize(surfaceToLight + half3(0, 0, 1)));\n");
|
||||
lightBody.appendf("\thighfloat colorScale = %s * pow(dot(normal, halfDir), %s);\n",
|
||||
ks, shininess);
|
||||
lightBody.appendf("\tfloat3 color = lightColor * clamp(colorScale, 0.0, 1.0);\n");
|
||||
lightBody.appendf("\treturn float4(color, max(max(color.r, color.g), color.b));\n");
|
||||
fragBuilder->emitFunction(kVec4f_GrSLType,
|
||||
lightBody.appendf("\thalf3 color = lightColor * clamp(colorScale, 0.0, 1.0);\n");
|
||||
lightBody.appendf("\treturn half4(color, max(max(color.r, color.g), color.b));\n");
|
||||
fragBuilder->emitFunction(kHalf4_GrSLType,
|
||||
"light",
|
||||
SK_ARRAY_COUNT(gLightArgs),
|
||||
gLightArgs,
|
||||
@ -2088,9 +2082,7 @@ void GrGLSpecularLightingEffect::onSetData(const GrGLSLProgramDataManager& pdman
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
void GrGLLight::emitLightColorUniform(GrGLSLUniformHandler* uniformHandler) {
|
||||
fColorUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kVec3f_GrSLType, kDefault_GrSLPrecision,
|
||||
"LightColor");
|
||||
fColorUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf3_GrSLType, "LightColor");
|
||||
}
|
||||
|
||||
void GrGLLight::emitLightColor(GrGLSLUniformHandler* uniformHandler,
|
||||
@ -2119,8 +2111,7 @@ void GrGLDistantLight::emitSurfaceToLight(GrGLSLUniformHandler* uniformHandler,
|
||||
GrGLSLFPFragmentBuilder* fragBuilder,
|
||||
const char* z) {
|
||||
const char* dir;
|
||||
fDirectionUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kVec3f_GrSLType, kDefault_GrSLPrecision,
|
||||
fDirectionUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf3_GrSLType,
|
||||
"LightDirection", &dir);
|
||||
fragBuilder->codeAppend(dir);
|
||||
}
|
||||
@ -2139,10 +2130,9 @@ void GrGLPointLight::emitSurfaceToLight(GrGLSLUniformHandler* uniformHandler,
|
||||
GrGLSLFPFragmentBuilder* fragBuilder,
|
||||
const char* z) {
|
||||
const char* loc;
|
||||
fLocationUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kVec3f_GrSLType, kDefault_GrSLPrecision,
|
||||
fLocationUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf3_GrSLType,
|
||||
"LightLocation", &loc);
|
||||
fragBuilder->codeAppendf("normalize(%s - float3(sk_FragCoord.xy, %s))",
|
||||
fragBuilder->codeAppendf("normalize(%s - half3(sk_FragCoord.xy, %s))",
|
||||
loc, z);
|
||||
}
|
||||
|
||||
@ -2165,11 +2155,10 @@ void GrGLSpotLight::emitSurfaceToLight(GrGLSLUniformHandler* uniformHandler,
|
||||
GrGLSLFPFragmentBuilder* fragBuilder,
|
||||
const char* z) {
|
||||
const char* location;
|
||||
fLocationUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kVec3f_GrSLType, kDefault_GrSLPrecision,
|
||||
fLocationUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf3_GrSLType,
|
||||
"LightLocation", &location);
|
||||
|
||||
fragBuilder->codeAppendf("normalize(%s - float3(sk_FragCoord.xy, %s))",
|
||||
fragBuilder->codeAppendf("normalize(%s - half3(sk_FragCoord.xy, %s))",
|
||||
location, z);
|
||||
}
|
||||
|
||||
@ -2184,36 +2173,31 @@ void GrGLSpotLight::emitLightColor(GrGLSLUniformHandler* uniformHandler,
|
||||
const char* cosOuter;
|
||||
const char* coneScale;
|
||||
const char* s;
|
||||
fExponentUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kFloat_GrSLType, kDefault_GrSLPrecision,
|
||||
fExponentUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType,
|
||||
"Exponent", &exponent);
|
||||
fCosInnerConeAngleUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kFloat_GrSLType, kDefault_GrSLPrecision,
|
||||
fCosInnerConeAngleUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType,
|
||||
"CosInnerConeAngle", &cosInner);
|
||||
fCosOuterConeAngleUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kFloat_GrSLType, kDefault_GrSLPrecision,
|
||||
fCosOuterConeAngleUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType,
|
||||
"CosOuterConeAngle", &cosOuter);
|
||||
fConeScaleUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kFloat_GrSLType, kDefault_GrSLPrecision,
|
||||
fConeScaleUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType,
|
||||
"ConeScale", &coneScale);
|
||||
fSUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kVec3f_GrSLType, kDefault_GrSLPrecision, "S", &s);
|
||||
fSUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf3_GrSLType, "S", &s);
|
||||
|
||||
static const GrShaderVar gLightColorArgs[] = {
|
||||
GrShaderVar("surfaceToLight", kVec3f_GrSLType)
|
||||
GrShaderVar("surfaceToLight", kHalf3_GrSLType)
|
||||
};
|
||||
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("\t\treturn float3(0);\n");
|
||||
lightColorBody.appendf("\t\treturn half3(0);\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("\t\treturn %s * scale * (cosAngle - %s) * %s;\n",
|
||||
color, cosOuter, coneScale);
|
||||
lightColorBody.appendf("\t}\n");
|
||||
lightColorBody.appendf("\treturn %s;\n", color);
|
||||
fragBuilder->emitFunction(kVec3f_GrSLType,
|
||||
fragBuilder->emitFunction(kHalf3_GrSLType,
|
||||
"lightColor",
|
||||
SK_ARRAY_COUNT(gLightColorArgs),
|
||||
gLightColorArgs,
|
||||
|
@ -60,16 +60,16 @@ private:
|
||||
|
||||
void emitCode(EmitArgs& args) override {
|
||||
if (nullptr == args.fInputColor) {
|
||||
args.fInputColor = "float4(1)";
|
||||
args.fInputColor = "half4(1)";
|
||||
}
|
||||
|
||||
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_G,
|
||||
SK_ITU_BT709_LUM_COEFF_B,
|
||||
args.fInputColor);
|
||||
fragBuilder->codeAppendf("\t%s = float4(0, 0, 0, luma);\n",
|
||||
fragBuilder->codeAppendf("\t%s = half4(0, 0, 0, luma);\n",
|
||||
args.fOutputColor);
|
||||
|
||||
}
|
||||
|
@ -180,48 +180,44 @@ private:
|
||||
void GrGLMagnifierEffect::emitCode(EmitArgs& args) {
|
||||
GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
|
||||
fOffsetVar = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kVec2f_GrSLType, kDefault_GrSLPrecision,
|
||||
"Offset");
|
||||
kHalf2_GrSLType, "Offset");
|
||||
fInvZoomVar = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kVec2f_GrSLType, kDefault_GrSLPrecision,
|
||||
"InvZoom");
|
||||
kHalf2_GrSLType, "InvZoom");
|
||||
fInvInsetVar = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kVec2f_GrSLType, kDefault_GrSLPrecision,
|
||||
"InvInset");
|
||||
kHalf2_GrSLType, "InvInset");
|
||||
fBoundsVar = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kVec4f_GrSLType, kDefault_GrSLPrecision,
|
||||
"Bounds");
|
||||
kHalf4_GrSLType, "Bounds");
|
||||
|
||||
const GrMagnifierEffect& zoom = args.fFp.cast<GrMagnifierEffect>();
|
||||
fColorSpaceHelper.emitCode(uniformHandler, zoom.colorSpaceXform());
|
||||
|
||||
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
|
||||
SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
|
||||
fragBuilder->codeAppendf("\t\tfloat2 coord = %s;\n", coords2D.c_str());
|
||||
fragBuilder->codeAppendf("\t\tfloat2 zoom_coord = %s + %s * %s;\n",
|
||||
fragBuilder->codeAppendf("\t\thighfloat2 coord = %s;\n", coords2D.c_str());
|
||||
fragBuilder->codeAppendf("\t\thighfloat2 zoom_coord = %s + %s * %s;\n",
|
||||
uniformHandler->getUniformCStr(fOffsetVar),
|
||||
coords2D.c_str(),
|
||||
uniformHandler->getUniformCStr(fInvZoomVar));
|
||||
const char* bounds = uniformHandler->getUniformCStr(fBoundsVar);
|
||||
fragBuilder->codeAppendf("\t\tfloat2 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\thighfloat2 delta = (coord - %s.xy) * %s.zw;\n", bounds, bounds);
|
||||
fragBuilder->codeAppendf("\t\tdelta = min(delta, half2(1.0, 1.0) - delta);\n");
|
||||
fragBuilder->codeAppendf("\t\tdelta = delta * %s;\n",
|
||||
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\t\tdelta = float2(2.0, 2.0) - delta;\n");
|
||||
fragBuilder->codeAppend("\t\t\tfloat dist = length(delta);\n");
|
||||
fragBuilder->codeAppend("\t\t\tdelta = half2(2.0, 2.0) - 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\tweight = min(dist * dist, 1.0);\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}\n");
|
||||
|
||||
fragBuilder->codeAppend("\t\tfloat2 mix_coord = mix(coord, zoom_coord, weight);\n");
|
||||
fragBuilder->codeAppend("\t\tfloat4 output_color = ");
|
||||
fragBuilder->appendTextureLookup(args.fTexSamplers[0], "mix_coord", kVec2f_GrSLType,
|
||||
fragBuilder->codeAppend("\t\thighfloat2 mix_coord = mix(coord, zoom_coord, weight);\n");
|
||||
fragBuilder->codeAppend("\t\thalf4 output_color = ");
|
||||
fragBuilder->appendTextureLookup(args.fTexSamplers[0], "mix_coord", kHalf2_GrSLType,
|
||||
&fColorSpaceHelper);
|
||||
fragBuilder->codeAppend(";\n");
|
||||
|
||||
|
@ -212,13 +212,9 @@ void GrGLMorphologyEffect::emitCode(EmitArgs& args) {
|
||||
const GrMorphologyEffect& me = args.fFp.cast<GrMorphologyEffect>();
|
||||
|
||||
GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
|
||||
fPixelSizeUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kFloat_GrSLType, kDefault_GrSLPrecision,
|
||||
"PixelSize");
|
||||
fPixelSizeUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType, "PixelSize");
|
||||
const char* pixelSizeInc = uniformHandler->getUniformCStr(fPixelSizeUni);
|
||||
fRangeUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kVec2f_GrSLType, kDefault_GrSLPrecision,
|
||||
"Range");
|
||||
fRangeUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHighFloat2_GrSLType, "Range");
|
||||
const char* range = uniformHandler->getUniformCStr(fRangeUni);
|
||||
|
||||
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
|
||||
@ -226,11 +222,11 @@ void GrGLMorphologyEffect::emitCode(EmitArgs& args) {
|
||||
const char* func;
|
||||
switch (me.type()) {
|
||||
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";
|
||||
break;
|
||||
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";
|
||||
break;
|
||||
default:
|
||||
@ -255,12 +251,12 @@ void GrGLMorphologyEffect::emitCode(EmitArgs& args) {
|
||||
int width = me.width();
|
||||
|
||||
// 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;
|
||||
fragBuilder->codeAppendf("\t\tcoord.%s -= %d.0 * %s; \n", dir, me.radius(), pixelSizeInc);
|
||||
if (me.useRange()) {
|
||||
// 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);
|
||||
// coord.x = max(lowBound, coord.x);
|
||||
fragBuilder->codeAppendf("\t\tcoord.%s = max(%s.x, coord.%s);", dir, range, dir);
|
||||
|
@ -150,49 +150,49 @@ GLOverdrawFragmentProcessor::GLOverdrawFragmentProcessor(const GrColor4f* colors
|
||||
void GLOverdrawFragmentProcessor::emitCode(EmitArgs& args) {
|
||||
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
|
||||
if (nullptr == args.fInputColor) {
|
||||
fragBuilder->codeAppendf("%s.rgba = float4(%f, %f, %f, %f);", args.fOutputColor,
|
||||
fColors[5].fRGBA[0],
|
||||
fColors[5].fRGBA[1],
|
||||
fColors[5].fRGBA[2],
|
||||
fColors[5].fRGBA[3]);
|
||||
fragBuilder->codeAppendf("%s.rgba = half4(%f, %f, %f, %f);", args.fOutputColor,
|
||||
fColors[5].fRGBA[0],
|
||||
fColors[5].fRGBA[1],
|
||||
fColors[5].fRGBA[2],
|
||||
fColors[5].fRGBA[3]);
|
||||
} 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(" %s.rgba = float4(%f, %f, %f, %f);", args.fOutputColor,
|
||||
fColors[0].fRGBA[0],
|
||||
fColors[0].fRGBA[1],
|
||||
fColors[0].fRGBA[2],
|
||||
fColors[0].fRGBA[3]);
|
||||
fragBuilder->codeAppendf(" %s.rgba = half4(%f, %f, %f, %f);", args.fOutputColor,
|
||||
fColors[0].fRGBA[0],
|
||||
fColors[0].fRGBA[1],
|
||||
fColors[0].fRGBA[2],
|
||||
fColors[0].fRGBA[3]);
|
||||
fragBuilder->codeAppendf("} else if (alpha < 1.5) {");
|
||||
fragBuilder->codeAppendf(" %s.rgba = float4(%f, %f, %f, %f);", args.fOutputColor,
|
||||
fColors[1].fRGBA[0],
|
||||
fColors[1].fRGBA[1],
|
||||
fColors[1].fRGBA[2],
|
||||
fColors[1].fRGBA[3]);
|
||||
fragBuilder->codeAppendf(" %s.rgba = half4(%f, %f, %f, %f);", args.fOutputColor,
|
||||
fColors[1].fRGBA[0],
|
||||
fColors[1].fRGBA[1],
|
||||
fColors[1].fRGBA[2],
|
||||
fColors[1].fRGBA[3]);
|
||||
fragBuilder->codeAppendf("} else if (alpha < 2.5) {");
|
||||
fragBuilder->codeAppendf(" %s.rgba = float4(%f, %f, %f, %f);", args.fOutputColor,
|
||||
fColors[2].fRGBA[0],
|
||||
fColors[2].fRGBA[1],
|
||||
fColors[2].fRGBA[2],
|
||||
fColors[2].fRGBA[3]);
|
||||
fragBuilder->codeAppendf(" %s.rgba = half4(%f, %f, %f, %f);", args.fOutputColor,
|
||||
fColors[2].fRGBA[0],
|
||||
fColors[2].fRGBA[1],
|
||||
fColors[2].fRGBA[2],
|
||||
fColors[2].fRGBA[3]);
|
||||
fragBuilder->codeAppendf("} else if (alpha < 3.5) {");
|
||||
fragBuilder->codeAppendf(" %s.rgba = float4(%f, %f, %f, %f);", args.fOutputColor,
|
||||
fColors[3].fRGBA[0],
|
||||
fColors[3].fRGBA[1],
|
||||
fColors[3].fRGBA[2],
|
||||
fColors[3].fRGBA[3]);
|
||||
fragBuilder->codeAppendf(" %s.rgba = half4(%f, %f, %f, %f);", args.fOutputColor,
|
||||
fColors[3].fRGBA[0],
|
||||
fColors[3].fRGBA[1],
|
||||
fColors[3].fRGBA[2],
|
||||
fColors[3].fRGBA[3]);
|
||||
fragBuilder->codeAppendf("} else if (alpha < 4.5) {");
|
||||
fragBuilder->codeAppendf(" %s.rgba = float4(%f, %f, %f, %f);", args.fOutputColor,
|
||||
fColors[4].fRGBA[0],
|
||||
fColors[4].fRGBA[1],
|
||||
fColors[4].fRGBA[2],
|
||||
fColors[4].fRGBA[3]);
|
||||
fragBuilder->codeAppendf(" %s.rgba = half4(%f, %f, %f, %f);", args.fOutputColor,
|
||||
fColors[4].fRGBA[0],
|
||||
fColors[4].fRGBA[1],
|
||||
fColors[4].fRGBA[2],
|
||||
fColors[4].fRGBA[3]);
|
||||
fragBuilder->codeAppendf("} else {");
|
||||
fragBuilder->codeAppendf(" %s.rgba = float4(%f, %f, %f, %f);", args.fOutputColor,
|
||||
fColors[5].fRGBA[0],
|
||||
fColors[5].fRGBA[1],
|
||||
fColors[5].fRGBA[2],
|
||||
fColors[5].fRGBA[3]);
|
||||
fragBuilder->codeAppendf(" %s.rgba = half4(%f, %f, %f, %f);", args.fOutputColor,
|
||||
fColors[5].fRGBA[0],
|
||||
fColors[5].fRGBA[1],
|
||||
fColors[5].fRGBA[2],
|
||||
fColors[5].fRGBA[3]);
|
||||
fragBuilder->codeAppendf("}");
|
||||
}
|
||||
}
|
||||
|
@ -241,7 +241,7 @@ private:
|
||||
|
||||
// Positive distance is towards the center of the circle.
|
||||
// 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);
|
||||
|
||||
switch (mode) {
|
||||
@ -249,14 +249,14 @@ private:
|
||||
// When a shadow circle gets large we can have some precision issues if
|
||||
// we do "length(delta)/radius". The scaleDist temporary cuts the
|
||||
// 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);",
|
||||
outputName, sizesName, indices[0], radName);
|
||||
break;
|
||||
case kRect_Mode:
|
||||
fragBuilder->codeAppendf(
|
||||
"float2 rectDist = float2(1.0 - clamp((%s.%c - delta.x)/%s, 0.0, 1.0),"
|
||||
"1.0 - clamp((%s.%c - delta.y)/%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));",
|
||||
sizesName, indices[0], radName,
|
||||
sizesName, indices[1], radName);
|
||||
fragBuilder->codeAppendf("%s = clamp(1.0 - length(rectDist), 0.0, 1.0);",
|
||||
@ -273,11 +273,11 @@ private:
|
||||
|
||||
//----------------
|
||||
// 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);
|
||||
fragBuilder->codeAppendf("float yDist = (%s.%c - delta.y) / %s;",
|
||||
fragBuilder->codeAppendf("half yDist = (%s.%c - delta.y) / %s;",
|
||||
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
|
||||
@ -286,59 +286,59 @@ private:
|
||||
// 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
|
||||
// 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));",
|
||||
radName, radiiName, indices[0],
|
||||
sizesName, indices[0], sizesName, indices[1]);
|
||||
// "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.
|
||||
fragBuilder->codeAppendf("float maxValue = insetDist/%s;", radName);
|
||||
fragBuilder->codeAppendf("half maxValue = insetDist/%s;", radName);
|
||||
|
||||
fragBuilder->codeAppendf("float2 coneBottom = float2(%s.%c - insetDist,"
|
||||
"%s.%c - insetDist);",
|
||||
fragBuilder->codeAppendf("half2 coneBottom = half2(%s.%c - insetDist,"
|
||||
"%s.%c - insetDist);",
|
||||
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;",
|
||||
sizesName, indices[0], radiiName, indices[0],
|
||||
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;",
|
||||
sizesName, indices[0],
|
||||
sizesName, indices[1], radiiName, indices[1]);
|
||||
|
||||
fragBuilder->codeAppend("float2 ptInConeSpace = delta - coneBottom;");
|
||||
fragBuilder->codeAppend("float distToPtInConeSpace = length(ptInConeSpace);");
|
||||
fragBuilder->codeAppend("half2 ptInConeSpace = delta - coneBottom;");
|
||||
fragBuilder->codeAppend("half distToPtInConeSpace = length(ptInConeSpace);");
|
||||
|
||||
fragBuilder->codeAppend("float cross1 = ptInConeSpace.x * cornerTop.y -"
|
||||
"ptInConeSpace.y * cornerTop.x;");
|
||||
fragBuilder->codeAppend("float cross2 = -ptInConeSpace.x * cornerRight.y + "
|
||||
"ptInConeSpace.y * cornerRight.x;");
|
||||
fragBuilder->codeAppend("half cross1 = ptInConeSpace.x * cornerTop.y -"
|
||||
"ptInConeSpace.y * cornerTop.x;");
|
||||
fragBuilder->codeAppend("half cross2 = -ptInConeSpace.x * cornerRight.y + "
|
||||
"ptInConeSpace.y * cornerRight.x;");
|
||||
|
||||
fragBuilder->codeAppend("float inCone = step(0.0, cross1) *"
|
||||
"step(0.0, cross2);");
|
||||
fragBuilder->codeAppend("half inCone = step(0.0, cross1) *"
|
||||
"step(0.0, cross2);");
|
||||
|
||||
fragBuilder->codeAppendf("float2 cornerCenterInConeSpace = float2(insetDist -"
|
||||
fragBuilder->codeAppendf("half2 cornerCenterInConeSpace = half2(insetDist -"
|
||||
"%s.%c);",
|
||||
radiiName, indices[0]);
|
||||
|
||||
fragBuilder->codeAppend("float2 connectingVec = ptInConeSpace -"
|
||||
fragBuilder->codeAppend("half2 connectingVec = ptInConeSpace -"
|
||||
"cornerCenterInConeSpace;");
|
||||
fragBuilder->codeAppend("ptInConeSpace = normalize(ptInConeSpace);");
|
||||
|
||||
// "a" (i.e., dot(ptInConeSpace, ptInConeSpace) should always be 1.0f since
|
||||
// ptInConeSpace is now normalized
|
||||
fragBuilder->codeAppend("float b = 2.0 * dot(ptInConeSpace, connectingVec);");
|
||||
fragBuilder->codeAppendf("float c = dot(connectingVec, connectingVec) - "
|
||||
fragBuilder->codeAppend("half b = 2.0 * dot(ptInConeSpace, connectingVec);");
|
||||
fragBuilder->codeAppendf("half c = dot(connectingVec, connectingVec) - "
|
||||
"%s.%c * %s.%c;",
|
||||
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
|
||||
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
|
||||
fragBuilder->codeAppend("float coneDist = "
|
||||
fragBuilder->codeAppend("half coneDist = "
|
||||
"max(0.0, 0.5 * (-b + sqrt(bSq - fourAC)));");
|
||||
// make the coneDist a fraction of how far it is from the edge to the
|
||||
// cone's base
|
||||
@ -358,42 +358,38 @@ private:
|
||||
GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
|
||||
|
||||
const char* positionsUniName = nullptr;
|
||||
fPositionsUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kVec4f_GrSLType, kDefault_GrSLPrecision,
|
||||
fPositionsUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType,
|
||||
"Positions", &positionsUniName);
|
||||
const char* sizesUniName = nullptr;
|
||||
fSizesUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kVec4f_GrSLType, kDefault_GrSLPrecision,
|
||||
"Sizes", &sizesUniName);
|
||||
fSizesUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType,
|
||||
kDefault_GrSLPrecision, "Sizes", &sizesUniName);
|
||||
const char* radiiUniName = nullptr;
|
||||
if (fp.fFirstMode == kSimpleCircular_Mode || fp.fSecondMode == kSimpleCircular_Mode) {
|
||||
fRadiiUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kVec4f_GrSLType, kDefault_GrSLPrecision,
|
||||
fRadiiUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType,
|
||||
"Radii", &radiiUniName);
|
||||
}
|
||||
const char* radUniName = nullptr;
|
||||
fRadiusUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kFloat_GrSLType, kDefault_GrSLPrecision,
|
||||
fRadiusUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType,
|
||||
"Radius", &radUniName);
|
||||
|
||||
fragBuilder->codeAppend("float firstDist;");
|
||||
fragBuilder->codeAppend("half firstDist;");
|
||||
fragBuilder->codeAppend("{");
|
||||
this->emitModeCode(fp.firstMode(), fragBuilder,
|
||||
positionsUniName, sizesUniName, radiiUniName,
|
||||
radUniName, "firstDist", "xy");
|
||||
fragBuilder->codeAppend("}");
|
||||
|
||||
fragBuilder->codeAppend("float secondDist;");
|
||||
fragBuilder->codeAppend("half secondDist;");
|
||||
fragBuilder->codeAppend("{");
|
||||
this->emitModeCode(fp.secondMode(), fragBuilder,
|
||||
positionsUniName, sizesUniName, radiiUniName,
|
||||
radUniName, "secondDist", "zw");
|
||||
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
|
||||
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->codeAppendf("%s = factor*%s;",
|
||||
args.fOutputColor, args.fInputColor);
|
||||
|
@ -396,8 +396,7 @@ void GLColorTableEffect::onSetData(const GrGLSLProgramDataManager& pdm,
|
||||
|
||||
void GLColorTableEffect::emitCode(EmitArgs& args) {
|
||||
const char* yoffsets;
|
||||
fRGBAYValuesUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kVec4f_GrSLType, kDefault_GrSLPrecision,
|
||||
fRGBAYValuesUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType,
|
||||
"yoffsets", &yoffsets);
|
||||
static const float kColorScaleFactor = 255.0f / 256.0f;
|
||||
static const float kColorOffsetFactor = 1.0f / 512.0f;
|
||||
@ -405,14 +404,14 @@ void GLColorTableEffect::emitCode(EmitArgs& args) {
|
||||
if (nullptr == args.fInputColor) {
|
||||
// the input color is solid white (all ones).
|
||||
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);
|
||||
|
||||
} else {
|
||||
fragBuilder->codeAppendf("\t\tfloat nonZeroAlpha = max(%s.a, .0001);\n", args.fInputColor);
|
||||
fragBuilder->codeAppendf("\t\tfloat4 coord = float4(%s.rgb / nonZeroAlpha, nonZeroAlpha);\n",
|
||||
fragBuilder->codeAppendf("\t\thalf nonZeroAlpha = max(%s.a, .0001);\n", args.fInputColor);
|
||||
fragBuilder->codeAppendf("\t\thalf4 coord = half4(%s.rgb / nonZeroAlpha, nonZeroAlpha);\n",
|
||||
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,
|
||||
kColorOffsetFactor, kColorOffsetFactor,
|
||||
kColorOffsetFactor, kColorOffsetFactor);
|
||||
@ -421,22 +420,22 @@ void GLColorTableEffect::emitCode(EmitArgs& args) {
|
||||
SkString coord;
|
||||
|
||||
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->codeAppend(".a;\n");
|
||||
|
||||
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->codeAppend(".a;\n");
|
||||
|
||||
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->codeAppend(".a;\n");
|
||||
|
||||
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->codeAppend(".a;\n");
|
||||
|
||||
|
@ -82,26 +82,26 @@ public:
|
||||
|
||||
// Setup pass through color
|
||||
if (gp.hasVertexColor()) {
|
||||
GrGLSLVertToFrag varying(kVec4f_GrSLType);
|
||||
GrGLSLVertToFrag varying(kHalf4_GrSLType);
|
||||
varyingHandler->addVarying("color", &varying);
|
||||
|
||||
// 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
|
||||
if (gp.linearizeColor()) {
|
||||
SkString srgbFuncName;
|
||||
static const GrShaderVar gSrgbArgs[] = {
|
||||
GrShaderVar("x", kFloat_GrSLType),
|
||||
GrShaderVar("x", kHalf_GrSLType),
|
||||
};
|
||||
vertBuilder->emitFunction(kFloat_GrSLType,
|
||||
vertBuilder->emitFunction(kHalf_GrSLType,
|
||||
"srgb_to_linear",
|
||||
SK_ARRAY_COUNT(gSrgbArgs),
|
||||
gSrgbArgs,
|
||||
"return (x <= 0.04045) ? (x / 12.92) "
|
||||
": pow((x + 0.055) / 1.055, 2.4);",
|
||||
&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,
|
||||
@ -110,7 +110,7 @@ public:
|
||||
|
||||
// For SkColor, do a red/blue swap and premul
|
||||
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
|
||||
@ -161,19 +161,18 @@ public:
|
||||
|
||||
// Setup coverage as pass through
|
||||
if (gp.hasVertexCoverage()) {
|
||||
fragBuilder->codeAppendf("float alpha = 1.0;");
|
||||
fragBuilder->codeAppendf("half alpha = 1.0;");
|
||||
varyingHandler->addPassThroughAttribute(gp.inCoverage(), "alpha");
|
||||
fragBuilder->codeAppendf("%s = float4(alpha);", args.fOutputCoverage);
|
||||
fragBuilder->codeAppendf("%s = half4(alpha);", args.fOutputCoverage);
|
||||
} else if (gp.coverage() == 0xff) {
|
||||
fragBuilder->codeAppendf("%s = float4(1);", args.fOutputCoverage);
|
||||
fragBuilder->codeAppendf("%s = half4(1);", args.fOutputCoverage);
|
||||
} else {
|
||||
const char* fragCoverage;
|
||||
fCoverageUniform = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kFloat_GrSLType,
|
||||
kDefault_GrSLPrecision,
|
||||
kHalf_GrSLType,
|
||||
"Coverage",
|
||||
&fragCoverage);
|
||||
fragBuilder->codeAppendf("%s = float4(%s);", args.fOutputCoverage, fragCoverage);
|
||||
fragBuilder->codeAppendf("%s = half4(%s);", args.fOutputCoverage, fragCoverage);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -177,7 +177,7 @@ private:
|
||||
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
|
||||
|
||||
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);
|
||||
fragBuilder->codeAppendf("%s.rgb *= invAlpha;", args.fOutputColor);
|
||||
}
|
||||
@ -387,8 +387,7 @@ std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::OverrideInput(
|
||||
void emitCode(EmitArgs& args) override {
|
||||
const char* colorName;
|
||||
fColorUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kVec4f_GrSLType,
|
||||
kDefault_GrSLPrecision,
|
||||
kHalf4_GrSLType,
|
||||
"Color", &colorName);
|
||||
this->emitChild(0, colorName, args);
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ class GrProcessorKeyBuilder;
|
||||
class GrShaderCaps;
|
||||
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
|
||||
GrCoordTransforms to receive a transformation of the local coordinates that map from local space
|
||||
to the fragment being processed.
|
||||
|
@ -37,14 +37,13 @@ public:
|
||||
// Setup uniform color
|
||||
const char* stagedLocalVarName;
|
||||
fColorUniform = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kVec4f_GrSLType,
|
||||
kDefault_GrSLPrecision,
|
||||
kHalf4_GrSLType,
|
||||
"Color",
|
||||
&stagedLocalVarName);
|
||||
fragBuilder->codeAppendf("%s = %s;", args.fOutputColor, stagedLocalVarName);
|
||||
|
||||
// setup constant solid coverage
|
||||
fragBuilder->codeAppendf("%s = float4(1);", args.fOutputCoverage);
|
||||
fragBuilder->codeAppendf("%s = half4(1);", args.fOutputCoverage);
|
||||
}
|
||||
|
||||
void emitTransforms(GrGLSLVaryingHandler* varyingHandler,
|
||||
@ -52,8 +51,8 @@ public:
|
||||
int i = 0;
|
||||
while (const GrCoordTransform* coordTransform = transformHandler->nextCoordTransform()) {
|
||||
GrSLType varyingType =
|
||||
coordTransform->getMatrix().hasPerspective() ? kVec3f_GrSLType
|
||||
: kVec2f_GrSLType;
|
||||
coordTransform->getMatrix().hasPerspective() ? kHalf3_GrSLType
|
||||
: kHalf2_GrSLType;
|
||||
|
||||
SkString strVaryingName;
|
||||
strVaryingName.printf("TransformedCoord_%d", i);
|
||||
@ -89,9 +88,9 @@ public:
|
||||
}
|
||||
fInstalledTransforms[t].fCurrentValue = m;
|
||||
|
||||
SkASSERT(fInstalledTransforms[t].fType == kVec2f_GrSLType ||
|
||||
fInstalledTransforms[t].fType == kVec3f_GrSLType);
|
||||
unsigned components = fInstalledTransforms[t].fType == kVec2f_GrSLType ? 2 : 3;
|
||||
SkASSERT(fInstalledTransforms[t].fType == kHalf2_GrSLType ||
|
||||
fInstalledTransforms[t].fType == kHalf3_GrSLType);
|
||||
unsigned components = fInstalledTransforms[t].fType == kHalf2_GrSLType ? 2 : 3;
|
||||
pd.setPathFragmentInputTransform(fInstalledTransforms[t].fHandle, components, m);
|
||||
++t;
|
||||
}
|
||||
|
@ -81,7 +81,7 @@ void GrShaderVar::setIOType(GrIOType ioType) {
|
||||
}
|
||||
|
||||
void GrShaderVar::appendDecl(const GrShaderCaps* shaderCaps, SkString* out) const {
|
||||
SkASSERT(kDefault_GrSLPrecision == fPrecision || GrSLTypeAcceptsPrecision(fType));
|
||||
SkASSERT(kDefault_GrSLPrecision == fPrecision || GrSLTypeTemporarilyAcceptsPrecision(fType));
|
||||
SkString layout = fLayoutQualifier;
|
||||
if (!fLayoutQualifier.isEmpty()) {
|
||||
out->appendf("layout(%s) ", fLayoutQualifier.c_str());
|
||||
|
@ -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()
|
||||
: fType(kFloat_GrSLType)
|
||||
: fType(kHalf_GrSLType)
|
||||
, fTypeModifier(kNone_TypeModifier)
|
||||
, fCount(kNonArray)
|
||||
, fPrecision(kDefault_GrSLPrecision)
|
||||
, fUseUniformFloatArrays(USE_UNIFORM_FLOAT_ARRAYS) {
|
||||
}
|
||||
|
||||
@ -116,7 +115,7 @@ public:
|
||||
const char* extraModifiers = nullptr,
|
||||
bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) {
|
||||
SkASSERT(kVoid_GrSLType != type);
|
||||
SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeAcceptsPrecision(type));
|
||||
SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeTemporarilyAcceptsPrecision(type));
|
||||
fType = type;
|
||||
fTypeModifier = typeModifier;
|
||||
fName = name;
|
||||
@ -140,7 +139,7 @@ public:
|
||||
const char* extraModifiers = nullptr,
|
||||
bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) {
|
||||
SkASSERT(kVoid_GrSLType != type);
|
||||
SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeAcceptsPrecision(type));
|
||||
SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeTemporarilyAcceptsPrecision(type));
|
||||
fType = type;
|
||||
fTypeModifier = typeModifier;
|
||||
fName = name;
|
||||
@ -165,7 +164,7 @@ public:
|
||||
const char* extraModifiers = nullptr,
|
||||
bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) {
|
||||
SkASSERT(kVoid_GrSLType != type);
|
||||
SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeAcceptsPrecision(type));
|
||||
SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeTemporarilyAcceptsPrecision(type));
|
||||
fType = type;
|
||||
fTypeModifier = typeModifier;
|
||||
fName = name;
|
||||
@ -190,7 +189,7 @@ public:
|
||||
const char* extraModifiers = nullptr,
|
||||
bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) {
|
||||
SkASSERT(kVoid_GrSLType != type);
|
||||
SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeAcceptsPrecision(type));
|
||||
SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeTemporarilyAcceptsPrecision(type));
|
||||
fType = type;
|
||||
fTypeModifier = typeModifier;
|
||||
fName = name;
|
||||
|
@ -122,8 +122,8 @@ void PrimitiveProcessor::emitVertexShader(const GrCCPRCoverageProcessor& proc,
|
||||
const TexelBufferHandle& pointsBuffer,
|
||||
const char* rtAdjust, GrGPArgs* gpArgs) const {
|
||||
v->codeAppendf("int packedoffset = %s[%i];", proc.instanceAttrib(), proc.atlasOffsetIdx());
|
||||
v->codeAppend ("highp float2 atlasoffset = float2((packedoffset<<16) >> 16, "
|
||||
"packedoffset >> 16);");
|
||||
v->codeAppend ("highfloat2 atlasoffset = highfloat2((packedoffset<<16) >> 16, "
|
||||
"packedoffset >> 16);");
|
||||
|
||||
this->onEmitVertexShader(proc, v, pointsBuffer, "atlasoffset", rtAdjust, gpArgs);
|
||||
}
|
||||
@ -135,12 +135,10 @@ void PrimitiveProcessor::emitGeometryShader(const GrCCPRCoverageProcessor& proc,
|
||||
|
||||
SkString emitVertexFn;
|
||||
SkSTArray<2, GrShaderVar> emitArgs;
|
||||
const char* position = emitArgs.emplace_back("position", kVec2f_GrSLType,
|
||||
GrShaderVar::kNonArray,
|
||||
kHigh_GrSLPrecision).c_str();
|
||||
const char* coverage = emitArgs.emplace_back("coverage", kFloat_GrSLType,
|
||||
GrShaderVar::kNonArray,
|
||||
kHigh_GrSLPrecision).c_str();
|
||||
const char* position = emitArgs.emplace_back("position", kHighFloat2_GrSLType,
|
||||
GrShaderVar::kNonArray).c_str();
|
||||
const char* coverage = emitArgs.emplace_back("coverage", kHighFloat_GrSLType,
|
||||
GrShaderVar::kNonArray).c_str();
|
||||
g->emitFunction(kVoid_GrSLType, "emitVertex", emitArgs.count(), emitArgs.begin(), [&]() {
|
||||
SkString fnBody;
|
||||
this->emitPerVertexGeometryCode(&fnBody, position, coverage, fGeomWind.c_str());
|
||||
@ -151,12 +149,12 @@ void PrimitiveProcessor::emitGeometryShader(const GrCCPRCoverageProcessor& proc,
|
||||
fnBody.appendf("%s = %s * %s;",
|
||||
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();");
|
||||
return fnBody;
|
||||
}().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
|
||||
if (proc.debugVisualizationsEnabled()) {
|
||||
@ -173,7 +171,7 @@ int PrimitiveProcessor::emitHullGeometry(GrGLSLGeometryBuilder* g, const char* e
|
||||
SkASSERT(numSides >= 3);
|
||||
|
||||
if (!midpoint) {
|
||||
g->codeAppendf("highp float2 midpoint = %s * float%i(%f);",
|
||||
g->codeAppendf("highfloat2 midpoint = %s * highfloat%i(%f);",
|
||||
polygonPts, numSides, 1.0 / numSides);
|
||||
midpoint = "midpoint";
|
||||
}
|
||||
@ -182,42 +180,42 @@ int PrimitiveProcessor::emitHullGeometry(GrGLSLGeometryBuilder* g, const char* e
|
||||
"nextidx = (%s + 1) %% %i;",
|
||||
wedgeIdx, numSides - 1, numSides, wedgeIdx, numSides);
|
||||
|
||||
g->codeAppendf("highp float2 self = %s[%s];"
|
||||
"highp int leftidx = %s > 0 ? previdx : nextidx;"
|
||||
"highp int rightidx = %s > 0 ? nextidx : previdx;",
|
||||
g->codeAppendf("highfloat2 self = %s[%s];"
|
||||
"int leftidx = %s > 0 ? previdx : nextidx;"
|
||||
"int rightidx = %s > 0 ? nextidx : previdx;",
|
||||
polygonPts, wedgeIdx, fGeomWind.c_str(), fGeomWind.c_str());
|
||||
|
||||
// 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) {
|
||||
// TODO: evaluate perf gains.
|
||||
g->codeAppend ("highp float2 qsr = sign(right - self);");
|
||||
g->codeAppend ("highfloat2 qsr = sign(right - self);");
|
||||
} else {
|
||||
SkASSERT(4 == numSides);
|
||||
g->codeAppendf("highp float2 diag = %s[(%s + 2) %% 4];", polygonPts, wedgeIdx);
|
||||
g->codeAppend ("highp float2 qsr = sign((right != self ? right : diag) - self);");
|
||||
g->codeAppendf("highfloat2 diag = %s[(%s + 2) %% 4];", polygonPts, wedgeIdx);
|
||||
g->codeAppend ("highfloat2 qsr = sign((right != self ? right : diag) - self);");
|
||||
}
|
||||
|
||||
// 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.
|
||||
// TODO: evaluate perf gains.
|
||||
const char* dr2 = "dr";
|
||||
if (3 == numSides) {
|
||||
// TODO: evaluate perf gains.
|
||||
g->codeAppend ("highp float2 dr = float2(qsr.y != 0 ? +qsr.y : +qsr.x, "
|
||||
"qsr.x != 0 ? -qsr.x : +qsr.y);");
|
||||
g->codeAppend ("highp float2 dr2 = float2(qsr.y != 0 ? +qsr.y : -qsr.x, "
|
||||
"qsr.x != 0 ? -qsr.x : -qsr.y);");
|
||||
g->codeAppend ("highp float2 dl = float2(qls.y != 0 ? +qls.y : +qls.x, "
|
||||
"qls.x != 0 ? -qls.x : +qls.y);");
|
||||
g->codeAppend ("highfloat2 dr = highfloat2(qsr.y != 0 ? +qsr.y : +qsr.x, "
|
||||
"qsr.x != 0 ? -qsr.x : +qsr.y);");
|
||||
g->codeAppend ("highfloat2 dr2 = highfloat2(qsr.y != 0 ? +qsr.y : -qsr.x, "
|
||||
"qsr.x != 0 ? -qsr.x : -qsr.y);");
|
||||
g->codeAppend ("highfloat2 dl = highfloat2(qls.y != 0 ? +qls.y : +qls.x, "
|
||||
"qls.x != 0 ? -qls.x : +qls.y);");
|
||||
dr2 = "dr2";
|
||||
} else {
|
||||
g->codeAppend ("highp float2 dr = float2(qsr.y != 0 ? +qsr.y : 1, "
|
||||
"qsr.x != 0 ? -qsr.x : 1);");
|
||||
g->codeAppend ("highp float2 dl = (qls == float2(0)) ? dr : "
|
||||
"float2(qls.y != 0 ? +qls.y : 1, qls.x != 0 ? -qls.x : 1);");
|
||||
g->codeAppend ("highfloat2 dr = highfloat2(qsr.y != 0 ? +qsr.y : 1, "
|
||||
"qsr.x != 0 ? -qsr.x : 1);");
|
||||
g->codeAppend ("highfloat2 dl = (qls == highfloat2(0)) ? dr : "
|
||||
"highfloat2(qls.y != 0 ? +qls.y : 1, qls.x != 0 ? -qls.x : 1);");
|
||||
}
|
||||
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->codeAppend ("}");
|
||||
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 ("EndPrimitive();");
|
||||
|
||||
@ -241,18 +239,18 @@ int PrimitiveProcessor::emitEdgeGeometry(GrGLSLGeometryBuilder* g, const char* e
|
||||
const char* leftPt, const char* rightPt,
|
||||
const char* distanceEquation) const {
|
||||
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";
|
||||
}
|
||||
|
||||
// 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);
|
||||
g->codeAppendf("mediump float2 endpts_coverage = %s.xy * endpts + %s.z;",
|
||||
g->codeAppendf("half2 endpts_coverage = %s.xy * endpts + %s.z;",
|
||||
distanceEquation, distanceEquation);
|
||||
|
||||
// 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 ("if (aligned) {");
|
||||
g->codeAppend ( "d1 -= qlr;");
|
||||
@ -281,25 +279,25 @@ void PrimitiveProcessor::emitEdgeDistanceEquation(GrGLSLGeometryBuilder* g,
|
||||
const char* leftPt, const char* rightPt,
|
||||
const char* outputDistanceEquation) const {
|
||||
// Which quadrant does the vector from left -> right fall into?
|
||||
g->codeAppendf("highp float2 qlr = sign(%s - %s);", rightPt, leftPt);
|
||||
g->codeAppend ("highp float2 d1 = float2(qlr.y, -qlr.x);");
|
||||
g->codeAppendf("highfloat2 qlr = sign(%s - %s);", rightPt, leftPt);
|
||||
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);
|
||||
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);
|
||||
// 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,
|
||||
const char* pt) const {
|
||||
g->codeAppendf("%s(%s + float2(-bloat.x, -bloat.y), 1);", emitVertexFn, pt);
|
||||
g->codeAppendf("%s(%s + float2(-bloat.x, +bloat.y), 1);", emitVertexFn, pt);
|
||||
g->codeAppendf("%s(%s + float2(+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 + highfloat2(-bloat.x, +bloat.y), 1);", emitVertexFn, pt);
|
||||
g->codeAppendf("%s(%s + highfloat2(+bloat.x, -bloat.y), 1);", emitVertexFn, pt);
|
||||
g->codeAppendf("%s(%s + highfloat2(+bloat.x, +bloat.y), 1);", emitVertexFn, pt);
|
||||
g->codeAppend ("EndPrimitive();");
|
||||
|
||||
return 4;
|
||||
@ -315,17 +313,17 @@ void PrimitiveProcessor::emitCoverage(const GrCCPRCoverageProcessor& proc, GrGLS
|
||||
f->codeAppendf("%s.a = %s;", outputColor, fFragCoverageTimesWind.fsIn());
|
||||
break;
|
||||
case CoverageType::kShader:
|
||||
f->codeAppendf("mediump float coverage = 0;");
|
||||
f->codeAppendf("half coverage = 0;");
|
||||
this->emitShaderCoverage(f, "coverage");
|
||||
f->codeAppendf("%s.a = coverage * %s;", outputColor, fFragWind.fsIn());
|
||||
break;
|
||||
}
|
||||
|
||||
f->codeAppendf("%s = float4(1);", outputCoverage);
|
||||
f->codeAppendf("%s = half4(1);", outputCoverage);
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
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
|
||||
}
|
||||
@ -334,17 +332,17 @@ int PrimitiveProcessor::defineSoftSampleLocations(GrGLSLFragmentBuilder* f,
|
||||
const char* samplesName) const {
|
||||
// Standard DX11 sample locations.
|
||||
#if defined(SK_BUILD_FOR_ANDROID) || defined(SK_BUILD_FOR_IOS)
|
||||
f->defineConstant("highp float2[8]", samplesName, "float2[8]("
|
||||
"float2(+1, -3)/16, float2(-1, +3)/16, float2(+5, +1)/16, float2(-3, -5)/16, "
|
||||
"float2(-5, +5)/16, float2(-7, -1)/16, float2(+3, +7)/16, float2(+7, -7)/16."
|
||||
f->defineConstant("highfloat2[8]", samplesName, "highfloat2[8]("
|
||||
"highfloat2(+1, -3)/16, highfloat2(-1, +3)/16, highfloat2(+5, +1)/16, highfloat2(-3, -5)/16, "
|
||||
"highfloat2(-5, +5)/16, highfloat2(-7, -1)/16, highfloat2(+3, +7)/16, highfloat2(+7, -7)/16."
|
||||
")");
|
||||
return 8;
|
||||
#else
|
||||
f->defineConstant("highp float2[16]", samplesName, "float2[16]("
|
||||
"float2(+1, +1)/16, float2(-1, -3)/16, float2(-3, +2)/16, float2(+4, -1)/16, "
|
||||
"float2(-5, -2)/16, float2(+2, +5)/16, float2(+5, +3)/16, float2(+3, -5)/16, "
|
||||
"float2(-2, +6)/16, float2( 0, -7)/16, float2(-4, -6)/16, float2(-6, +4)/16, "
|
||||
"float2(-8, 0)/16, float2(+7, -4)/16, float2(+6, +7)/16, float2(-7, -8)/16."
|
||||
f->defineConstant("highfloat2[16]", samplesName, "highfloat2[16]("
|
||||
"highfloat2(+1, +1)/16, highfloat2(-1, -3)/16, highfloat2(-3, +2)/16, highfloat2(+4, -1)/16, "
|
||||
"highfloat2(-5, -2)/16, highfloat2(+2, +5)/16, highfloat2(+5, +3)/16, highfloat2(+3, -5)/16, "
|
||||
"highfloat2(-2, +6)/16, highfloat2( 0, -7)/16, highfloat2(-4, -6)/16, highfloat2(-6, +4)/16, "
|
||||
"highfloat2(-8, 0)/16, highfloat2(+7, -4)/16, highfloat2(+6, +7)/16, highfloat2(-7, -8)/16."
|
||||
")");
|
||||
return 16;
|
||||
#endif
|
||||
|
@ -133,9 +133,9 @@ protected:
|
||||
|
||||
PrimitiveProcessor(CoverageType coverageType)
|
||||
: fCoverageType(coverageType)
|
||||
, fGeomWind("wind", kFloat_GrSLType, GrShaderVar::kNonArray, kLow_GrSLPrecision)
|
||||
, fFragWind(kFloat_GrSLType)
|
||||
, fFragCoverageTimesWind(kFloat_GrSLType) {}
|
||||
, fGeomWind("wind", kHalf_GrSLType, GrShaderVar::kNonArray, kLow_GrSLPrecision)
|
||||
, fFragWind(kHalf_GrSLType)
|
||||
, fFragCoverageTimesWind(kHalf_GrSLType) {}
|
||||
|
||||
// Called before generating shader code. Subclass should add its custom varyings to the handler
|
||||
// and update its corresponding internal member variables.
|
||||
|
@ -16,18 +16,18 @@ void GrCCPRCubicProcessor::onEmitVertexShader(const GrCCPRCoverageProcessor& pro
|
||||
const TexelBufferHandle& pointsBuffer,
|
||||
const char* atlasOffset, const char* rtAdjust,
|
||||
GrGPArgs* gpArgs) const {
|
||||
v->codeAppend ("highp float2 self = ");
|
||||
v->codeAppend ("highfloat2 self = ");
|
||||
v->appendTexelFetch(pointsBuffer,
|
||||
SkStringPrintf("%s.x + sk_VertexID", proc.instanceAttrib()).c_str());
|
||||
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,
|
||||
const char* outputWind) const {
|
||||
// We will define bezierpts in onEmitGeometryShader.
|
||||
g->codeAppend ("highp float area_times_2 = "
|
||||
"determinant(float3x3(1, bezierpts[0], "
|
||||
g->codeAppend ("highfloat area_times_2 = "
|
||||
"determinant(highfloat3x3(1, bezierpts[0], "
|
||||
"1, bezierpts[2], "
|
||||
"0, bezierpts[3] - bezierpts[1]));");
|
||||
// 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,
|
||||
const char* wind, const char* rtAdjust) const {
|
||||
// Prepend bezierpts at the start of the shader.
|
||||
g->codePrependf("highp float4x2 bezierpts = float4x2(sk_in[0].gl_Position.xy, "
|
||||
"sk_in[1].gl_Position.xy, "
|
||||
"sk_in[2].gl_Position.xy, "
|
||||
"sk_in[3].gl_Position.xy);");
|
||||
g->codePrependf("highfloat4x2 bezierpts = highfloat4x2(sk_in[0].gl_Position.xy, "
|
||||
"sk_in[1].gl_Position.xy, "
|
||||
"sk_in[2].gl_Position.xy, "
|
||||
"sk_in[3].gl_Position.xy);");
|
||||
|
||||
// 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.
|
||||
g->codeAppend ("highp float2x4 C = float4x4(-1, 3, -3, 1, "
|
||||
" 3, -6, 3, 0, "
|
||||
"-3, 3, 0, 0, "
|
||||
" 1, 0, 0, 0) * transpose(bezierpts);");
|
||||
g->codeAppend ("highfloat2x4 C = highfloat4x4(-1, 3, -3, 1, "
|
||||
" 3, -6, 3, 0, "
|
||||
"-3, 3, 0, 0, "
|
||||
" 1, 0, 0, 0) * transpose(bezierpts);");
|
||||
|
||||
// Find the cubic's inflection function.
|
||||
g->codeAppend ("highp float D3 = +determinant(float2x2(C[0].yz, C[1].yz));");
|
||||
g->codeAppend ("highp float D2 = -determinant(float2x2(C[0].xz, C[1].xz));");
|
||||
g->codeAppend ("highp float D1 = +determinant(float2x2(C));");
|
||||
g->codeAppend ("highfloat D3 = +determinant(highfloat2x2(C[0].yz, C[1].yz));");
|
||||
g->codeAppend ("highfloat D2 = -determinant(highfloat2x2(C[0].xz, C[1].xz));");
|
||||
g->codeAppend ("highfloat D1 = +determinant(highfloat2x2(C));");
|
||||
|
||||
// Calculate the KLM matrix.
|
||||
g->declareGlobal(fKLMMatrix);
|
||||
g->codeAppend ("highp float4 K, L, M;");
|
||||
g->codeAppend ("highp float2 l, m;");
|
||||
g->codeAppend ("highp float discr = 3*D2*D2 - 4*D1*D3;");
|
||||
g->codeAppend ("highfloat4 K, L, M;");
|
||||
g->codeAppend ("highfloat2 l, m;");
|
||||
g->codeAppend ("highfloat discr = 3*D2*D2 - 4*D1*D3;");
|
||||
if (CubicType::kSerpentine == fCubicType) {
|
||||
// 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 ("l.ts = normalize(float2(q, 6*D1));");
|
||||
g->codeAppend ("m.ts = discr <= 0 ? l.ts : normalize(float2(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 ("L = float4(-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 ("highfloat q = 3*D2 + sign(D2) * sqrt(max(3*discr, 0));");
|
||||
g->codeAppend ("l.ts = normalize(highfloat2(q, 6*D1));");
|
||||
g->codeAppend ("m.ts = discr <= 0 ? l.ts : normalize(highfloat2(2*D3, q));");
|
||||
g->codeAppend ("K = highfloat4(0, l.s * m.s, -l.t * m.s - m.t * l.s, l.t * m.t);");
|
||||
g->codeAppend ("L = highfloat4(-1,3,-3,1) * l.ssst * l.sstt * l.sttt;");
|
||||
g->codeAppend ("M = highfloat4(-1,3,-3,1) * m.ssst * m.sstt * m.sttt;");
|
||||
} else {
|
||||
g->codeAppend ("highp float q = D2 + sign(D2) * sqrt(max(-discr, 0));");
|
||||
g->codeAppend ("l.ts = normalize(float2(q, 2*D1));");
|
||||
g->codeAppend ("m.ts = discr >= 0 ? l.ts : normalize(float2(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 ("K = float4(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 ("M = float4(-1,1,-1,1) * m.sstt * (lxm.xzyw + float4(0, 2*lxm.yz, 0));");
|
||||
g->codeAppend ("highfloat q = D2 + sign(D2) * sqrt(max(-discr, 0));");
|
||||
g->codeAppend ("l.ts = normalize(highfloat2(q, 2*D1));");
|
||||
g->codeAppend ("m.ts = discr >= 0 ? l.ts : normalize(highfloat2(2 * (D2*D2 - D3*D1), D1*q));");
|
||||
g->codeAppend ("highfloat4 lxm = highfloat4(l.s * m.s, l.s * m.t, l.t * m.s, l.t * m.t);");
|
||||
g->codeAppend ("K = highfloat4(0, lxm.x, -lxm.y - lxm.z, lxm.w);");
|
||||
g->codeAppend ("L = highfloat4(-1,1,-1,1) * l.sstt * (lxm.xyzw + highfloat4(0, 2*lxm.zy, 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 ("highp float3x3 CI = inverse(float3x3(C[0][0], C[0][middlerow], C[0][3], "
|
||||
"C[1][0], C[1][middlerow], C[1][3], "
|
||||
" 0, 0, 1));");
|
||||
g->codeAppendf("%s = CI * float3x3(K[0], K[middlerow], K[3], "
|
||||
"L[0], L[middlerow], L[3], "
|
||||
"M[0], M[middlerow], M[3]);", fKLMMatrix.c_str());
|
||||
g->codeAppend ("short middlerow = abs(D2) > abs(D1) ? 2 : 1;");
|
||||
g->codeAppend ("highfloat3x3 CI = inverse(highfloat3x3(C[0][0], C[0][middlerow], C[0][3], "
|
||||
"C[1][0], C[1][middlerow], C[1][3], "
|
||||
" 0, 0, 1));");
|
||||
g->codeAppendf("%s = CI * highfloat3x3(K[0], K[middlerow], K[3], "
|
||||
"L[0], L[middlerow], L[3], "
|
||||
"M[0], M[middlerow], M[3]);", fKLMMatrix.c_str());
|
||||
|
||||
// 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());
|
||||
g->codeAppendf("%s *= float3x3(orientation[0] * orientation[1], 0, 0, "
|
||||
"0, orientation[0], 0, "
|
||||
"0, 0, orientation[1]);", fKLMMatrix.c_str());
|
||||
g->codeAppendf("%s *= highfloat3x3(orientation[0] * orientation[1], 0, 0, "
|
||||
"0, orientation[0], 0, "
|
||||
"0, 0, orientation[1]);", fKLMMatrix.c_str());
|
||||
|
||||
g->declareGlobal(fKLMDerivatives);
|
||||
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).
|
||||
g->declareGlobal(fEdgeDistanceEquation);
|
||||
g->codeAppendf("int edgeidx0 = %s > 0 ? 3 : 0;", wind);
|
||||
g->codeAppendf("highp float2 edgept0 = bezierpts[edgeidx0];");
|
||||
g->codeAppendf("highp float2 edgept1 = bezierpts[3 - edgeidx0];");
|
||||
g->codeAppendf("short edgeidx0 = %s > 0 ? 3 : 0;", wind);
|
||||
g->codeAppendf("highfloat2 edgept0 = bezierpts[edgeidx0];");
|
||||
g->codeAppendf("highfloat2 edgept1 = bezierpts[3 - edgeidx0];");
|
||||
this->emitEdgeDistanceEquation(g, "edgept0", "edgept1", fEdgeDistanceEquation.c_str());
|
||||
|
||||
this->emitCubicGeometry(g, emitVertexFn, wind, rtAdjust);
|
||||
@ -123,10 +123,10 @@ void GrCCPRCubicProcessor::onEmitGeometryShader(GrGLSLGeometryBuilder* g, const
|
||||
void GrCCPRCubicProcessor::emitPerVertexGeometryCode(SkString* fnBody, const char* position,
|
||||
const char* /*coverage*/,
|
||||
const char* /*wind*/) const {
|
||||
fnBody->appendf("highp float3 klm = float3(%s, 1) * %s;", position, fKLMMatrix.c_str());
|
||||
fnBody->appendf("highp float d = dot(float3(%s, 1), %s);",
|
||||
fnBody->appendf("highfloat3 klm = highfloat3(%s, 1) * %s;", position, fKLMMatrix.c_str());
|
||||
fnBody->appendf("highfloat d = dot(highfloat3(%s, 1), %s);",
|
||||
position, fEdgeDistanceEquation.c_str());
|
||||
fnBody->appendf("%s = float4(klm, d);", fKLMD.gsOut());
|
||||
fnBody->appendf("%s = highfloat4(klm, d);", fKLMD.gsOut());
|
||||
this->onEmitPerVertexGeometryCode(fnBody);
|
||||
}
|
||||
|
||||
@ -150,10 +150,10 @@ void GrCCPRCubicHullProcessor::onEmitPerVertexGeometryCode(SkString* fnBody) con
|
||||
|
||||
void GrCCPRCubicHullProcessor::emitShaderCoverage(GrGLSLFragmentBuilder* f,
|
||||
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());
|
||||
f->codeAppend ("highp float f = k*k*k - l*m;");
|
||||
f->codeAppendf("highp float2 grad_f = %s * float2(k, 1);", fGradMatrix.fsIn());
|
||||
f->codeAppend ("highfloat f = k*k*k - l*m;");
|
||||
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 += min(d, 0);", outputCoverage); // Flat closing edge.
|
||||
}
|
||||
@ -166,7 +166,7 @@ void GrCCPRCubicCornerProcessor::emitCubicGeometry(GrGLSLGeometryBuilder* g,
|
||||
g->codeAppendf("%s = %s.xy * %s.xz;",
|
||||
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");
|
||||
|
||||
g->configure(GrGLSLGeometryBuilder::InputType::kLinesAdjacency,
|
||||
@ -174,10 +174,10 @@ void GrCCPRCubicCornerProcessor::emitCubicGeometry(GrGLSLGeometryBuilder* g,
|
||||
}
|
||||
|
||||
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(),
|
||||
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(),
|
||||
fKLMDerivatives.c_str(), fEdgeDistanceDerivatives.c_str());
|
||||
|
||||
@ -187,28 +187,28 @@ void GrCCPRCubicCornerProcessor::onEmitPerVertexGeometryCode(SkString* fnBody) c
|
||||
|
||||
void GrCCPRCubicCornerProcessor::emitShaderCoverage(GrGLSLFragmentBuilder* f,
|
||||
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());
|
||||
|
||||
// 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.
|
||||
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());
|
||||
f->codeAppend ("highp float f = k*k*k - l*m;");
|
||||
f->codeAppend ("highp float2 grad_f = float3(3*k*k, -m, -l) * float2x3(grad_klmd);");
|
||||
f->codeAppend ("highfloat f = k*k*k - l*m;");
|
||||
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);",
|
||||
outputCoverage);
|
||||
f->codeAppendf("%s -= d;", outputCoverage);
|
||||
|
||||
// Use software msaa to estimate actual coverage at the corner pixels.
|
||||
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 = highfloat4(%s.xyz, %s.w + 0.5);",
|
||||
fKLMD.fsIn(), fKLMD.fsIn());
|
||||
f->codeAppendf("for (int i = 0; i < %i; ++i) {", sampleCount);
|
||||
f->codeAppend ( "highp float4 klmd = grad_klmd * samples[i] + klmd_center;");
|
||||
f->codeAppend ( "lowp float f = klmd.y * klmd.z - klmd.x * klmd.x * klmd.x;");
|
||||
f->codeAppendf( "%s += all(greaterThan(float4(f, klmd.y, klmd.z, klmd.w), "
|
||||
"float4(0))) ? %f : 0;",
|
||||
f->codeAppend ( "highfloat4 klmd = grad_klmd * samples[i] + klmd_center;");
|
||||
f->codeAppend ( "half f = klmd.y * klmd.z - klmd.x * klmd.x * klmd.x;");
|
||||
f->codeAppendf( "%s += all(greaterThan(half4(f, klmd.y, klmd.z, klmd.w), "
|
||||
"half4(0))) ? %f : 0;",
|
||||
outputCoverage, 1.0 / sampleCount);
|
||||
f->codeAppend ("}");
|
||||
}
|
||||
|
@ -33,12 +33,12 @@ public:
|
||||
GrCCPRCubicProcessor(CubicType cubicType)
|
||||
: INHERITED(CoverageType::kShader)
|
||||
, fCubicType(cubicType)
|
||||
, fKLMMatrix("klm_matrix", kMat33f_GrSLType, GrShaderVar::kNonArray,
|
||||
, fKLMMatrix("klm_matrix", kHighFloat3x3_GrSLType, GrShaderVar::kNonArray,
|
||||
kHigh_GrSLPrecision)
|
||||
, fKLMDerivatives("klm_derivatives", kVec2f_GrSLType, 3, kHigh_GrSLPrecision)
|
||||
, fEdgeDistanceEquation("edge_distance_equation", kVec3f_GrSLType,
|
||||
, fKLMDerivatives("klm_derivatives", kHighFloat2_GrSLType, 3, kHigh_GrSLPrecision)
|
||||
, fEdgeDistanceEquation("edge_distance_equation", kHighFloat3_GrSLType,
|
||||
GrShaderVar::kNonArray, kHigh_GrSLPrecision)
|
||||
, fKLMD(kVec4f_GrSLType) {}
|
||||
, fKLMD(kHighFloat4_GrSLType) {}
|
||||
|
||||
void resetVaryings(GrGLSLVaryingHandler* varyingHandler) override {
|
||||
varyingHandler->addVarying("klmd", &fKLMD, kHigh_GrSLPrecision);
|
||||
@ -71,7 +71,7 @@ class GrCCPRCubicHullProcessor : public GrCCPRCubicProcessor {
|
||||
public:
|
||||
GrCCPRCubicHullProcessor(CubicType cubicType)
|
||||
: INHERITED(cubicType)
|
||||
, fGradMatrix(kMat22f_GrSLType) {}
|
||||
, fGradMatrix(kHighFloat2x2_GrSLType) {}
|
||||
|
||||
void resetVaryings(GrGLSLVaryingHandler* varyingHandler) override {
|
||||
this->INHERITED::resetVaryings(varyingHandler);
|
||||
@ -93,10 +93,10 @@ class GrCCPRCubicCornerProcessor : public GrCCPRCubicProcessor {
|
||||
public:
|
||||
GrCCPRCubicCornerProcessor(CubicType cubicType)
|
||||
: INHERITED(cubicType)
|
||||
, fEdgeDistanceDerivatives("edge_distance_derivatives", kVec2f_GrSLType,
|
||||
, fEdgeDistanceDerivatives("edge_distance_derivatives", kHighFloat2_GrSLType,
|
||||
GrShaderVar::kNonArray, kHigh_GrSLPrecision)
|
||||
, fdKLMDdx(kVec4f_GrSLType)
|
||||
, fdKLMDdy(kVec4f_GrSLType) {}
|
||||
, fdKLMDdx(kHighFloat4_GrSLType)
|
||||
, fdKLMDdy(kHighFloat4_GrSLType) {}
|
||||
|
||||
void resetVaryings(GrGLSLVaryingHandler* varyingHandler) override {
|
||||
this->INHERITED::resetVaryings(varyingHandler);
|
||||
|
@ -121,12 +121,12 @@ void GLSLPathProcessor::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
|
||||
const char* atlasAdjust;
|
||||
fAtlasAdjustUniform = uniHandler->addUniform(
|
||||
kVertex_GrShaderFlag,
|
||||
kVec2f_GrSLType, kHigh_GrSLPrecision, "atlas_adjust", &atlasAdjust);
|
||||
kHighFloat2_GrSLType, "atlas_adjust", &atlasAdjust);
|
||||
|
||||
varyingHandler->emitAttributes(proc);
|
||||
|
||||
GrGLSLVertToFrag texcoord(kVec2f_GrSLType);
|
||||
GrGLSLVertToFrag color(kVec4f_GrSLType);
|
||||
GrGLSLVertToFrag texcoord(kHighFloat2_GrSLType);
|
||||
GrGLSLVertToFrag color(kHalf4_GrSLType);
|
||||
varyingHandler->addVarying("texcoord", &texcoord, kHigh_GrSLPrecision);
|
||||
varyingHandler->addFlatPassThroughAttribute(&proc.getInstanceAttrib(InstanceAttribs::kColor),
|
||||
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
|
||||
// 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.
|
||||
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
|
||||
// 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);
|
||||
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
|
||||
// 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);
|
||||
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->codeAppend ("highp float2 K = float2(dot(N[0], refpt), dot(N[1], refpt45));");
|
||||
v->codeAppendf("highp float2 octocoord = K * inverse(N);");
|
||||
v->codeAppend ("highfloat2 K = highfloat2(dot(N[0], refpt), dot(N[1], refpt45));");
|
||||
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.
|
||||
v->codeAppendf("highp float2 atlascoord = octocoord + float2(%s);",
|
||||
v->codeAppendf("highfloat2 atlascoord = octocoord + highfloat2(%s);",
|
||||
proc.getInstanceAttrib(InstanceAttribs::kAtlasOffset).fName);
|
||||
if (kTopLeft_GrSurfaceOrigin == proc.atlasProxy()->origin()) {
|
||||
v->codeAppendf("%s = atlascoord * %s;", texcoord.vsOut(), atlasAdjust);
|
||||
} else {
|
||||
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);
|
||||
}
|
||||
|
||||
// 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::kViewTranslate).fName);
|
||||
|
||||
@ -181,16 +181,16 @@ void GLSLPathProcessor::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
|
||||
// Fragment shader.
|
||||
GrGLSLPPFragmentBuilder* f = args.fFragBuilder;
|
||||
|
||||
f->codeAppend ("mediump float coverage_count = ");
|
||||
f->appendTextureLookup(args.fTexSamplers[0], texcoord.fsIn(), kVec2f_GrSLType);
|
||||
f->codeAppend ("half coverage_count = ");
|
||||
f->appendTextureLookup(args.fTexSamplers[0], texcoord.fsIn(), kHighFloat2_GrSLType);
|
||||
f->codeAppend (".a;");
|
||||
|
||||
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 {
|
||||
SkASSERT(SkPath::kEvenOdd_FillType == proc.fillType());
|
||||
f->codeAppend ("mediump float t = mod(abs(coverage_count), 2);");
|
||||
f->codeAppendf("%s = float4(1 - abs(t - 1));", args.fOutputCoverage);
|
||||
f->codeAppend ("half t = mod(abs(coverage_count), 2);");
|
||||
f->codeAppendf("%s = half4(1 - abs(t - 1));", args.fOutputCoverage);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,18 +16,18 @@ void GrCCPRQuadraticProcessor::onEmitVertexShader(const GrCCPRCoverageProcessor&
|
||||
const TexelBufferHandle& pointsBuffer,
|
||||
const char* atlasOffset, const char* rtAdjust,
|
||||
GrGPArgs* gpArgs) const {
|
||||
v->codeAppend ("highp float2 self = ");
|
||||
v->codeAppend ("highfloat2 self = ");
|
||||
v->appendTexelFetch(pointsBuffer,
|
||||
SkStringPrintf("%s.x + sk_VertexID", proc.instanceAttrib()).c_str());
|
||||
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,
|
||||
const char* outputWind) const {
|
||||
// We will define bezierpts in onEmitGeometryShader.
|
||||
g->codeAppend ("highp float area_times_2 = "
|
||||
"determinant(float2x2(bezierpts[1] - bezierpts[0], "
|
||||
g->codeAppend ("highfloat area_times_2 = "
|
||||
"determinant(highfloat2x2(bezierpts[1] - bezierpts[0], "
|
||||
"bezierpts[2] - bezierpts[0]));");
|
||||
// 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)) {",
|
||||
@ -46,26 +46,26 @@ void GrCCPRQuadraticProcessor::onEmitGeometryShader(GrGLSLGeometryBuilder* g,
|
||||
const char* emitVertexFn, const char* wind,
|
||||
const char* rtAdjust) const {
|
||||
// Prepend bezierpts at the start of the shader.
|
||||
g->codePrependf("highp float3x2 bezierpts = float3x2(sk_in[0].gl_Position.xy, "
|
||||
"sk_in[1].gl_Position.xy, "
|
||||
"sk_in[2].gl_Position.xy);");
|
||||
g->codePrependf("highfloat3x2 bezierpts = highfloat3x2(sk_in[0].gl_Position.xy, "
|
||||
"sk_in[1].gl_Position.xy, "
|
||||
"sk_in[2].gl_Position.xy);");
|
||||
|
||||
g->declareGlobal(fCanonicalMatrix);
|
||||
g->codeAppendf("%s = float3x3(0.0, 0, 1, "
|
||||
"0.5, 0, 1, "
|
||||
"1.0, 1, 1) * "
|
||||
"inverse(float3x3(bezierpts[0], 1, "
|
||||
"bezierpts[1], 1, "
|
||||
"bezierpts[2], 1));",
|
||||
g->codeAppendf("%s = highfloat3x3(0.0, 0, 1, "
|
||||
"0.5, 0, 1, "
|
||||
"1.0, 1, 1) * "
|
||||
"inverse(highfloat3x3(bezierpts[0], 1, "
|
||||
"bezierpts[1], 1, "
|
||||
"bezierpts[2], 1));",
|
||||
fCanonicalMatrix.c_str());
|
||||
|
||||
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);
|
||||
|
||||
g->declareGlobal(fEdgeDistanceEquation);
|
||||
g->codeAppendf("highp float2 edgept0 = bezierpts[%s > 0 ? 2 : 0];", wind);
|
||||
g->codeAppendf("highp float2 edgept1 = bezierpts[%s > 0 ? 0 : 2];", wind);
|
||||
g->codeAppendf("highfloat2 edgept0 = bezierpts[%s > 0 ? 2 : 0];", wind);
|
||||
g->codeAppendf("highfloat2 edgept1 = bezierpts[%s > 0 ? 0 : 2];", wind);
|
||||
this->emitEdgeDistanceEquation(g, "edgept0", "edgept1", fEdgeDistanceEquation.c_str());
|
||||
|
||||
this->emitQuadraticGeometry(g, emitVertexFn, rtAdjust);
|
||||
@ -74,7 +74,7 @@ void GrCCPRQuadraticProcessor::onEmitGeometryShader(GrGLSLGeometryBuilder* g,
|
||||
void GrCCPRQuadraticProcessor::emitPerVertexGeometryCode(SkString* fnBody, const char* position,
|
||||
const char* /*coverage*/,
|
||||
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);
|
||||
fnBody->appendf("%s.z = dot(%s.xy, %s) + %s.z;",
|
||||
fXYD.gsOut(), fEdgeDistanceEquation.c_str(), position,
|
||||
@ -87,18 +87,18 @@ void GrCCPRQuadraticHullProcessor::emitQuadraticGeometry(GrGLSLGeometryBuilder*
|
||||
const char* /*rtAdjust*/) const {
|
||||
// Find the t value whose tangent is halfway between the tangents at the endpionts.
|
||||
// (We defined bezierpts in onEmitGeometryShader.)
|
||||
g->codeAppend ("highp float2 tan0 = bezierpts[1] - bezierpts[0];");
|
||||
g->codeAppend ("highp float2 tan1 = bezierpts[2] - bezierpts[1];");
|
||||
g->codeAppend ("highp float2 midnorm = normalize(tan0) - normalize(tan1);");
|
||||
g->codeAppend ("highp float2 T = midnorm * float2x2(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 ("highfloat2 tan0 = bezierpts[1] - bezierpts[0];");
|
||||
g->codeAppend ("highfloat2 tan1 = bezierpts[2] - bezierpts[1];");
|
||||
g->codeAppend ("highfloat2 midnorm = normalize(tan0) - normalize(tan1);");
|
||||
g->codeAppend ("highfloat2 T = midnorm * highfloat2x2(tan0 - tan1, tan0);");
|
||||
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
|
||||
// De Casteljau's algorithm.
|
||||
g->codeAppendf("highp float4x2 quadratic_hull = float4x2(bezierpts[0], "
|
||||
"bezierpts[0] + tan0 * t, "
|
||||
"bezierpts[1] + tan1 * t, "
|
||||
"bezierpts[2]);");
|
||||
g->codeAppendf("highfloat4x2 quadratic_hull = highfloat4x2(bezierpts[0], "
|
||||
"bezierpts[0] + tan0 * t, "
|
||||
"bezierpts[1] + tan1 * t, "
|
||||
"bezierpts[2]);");
|
||||
|
||||
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 {
|
||||
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());
|
||||
}
|
||||
|
||||
void GrCCPRQuadraticHullProcessor::emitShaderCoverage(GrGLSLFragmentBuilder* f,
|
||||
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());
|
||||
f->codeAppendf("%s = clamp(0.5 - d, 0, 1);", outputCoverage);
|
||||
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;",
|
||||
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");
|
||||
|
||||
g->configure(GrGLSLGeometryBuilder::InputType::kTriangles,
|
||||
@ -135,35 +135,35 @@ void GrCCPRQuadraticCornerProcessor::emitQuadraticGeometry(GrGLSLGeometryBuilder
|
||||
}
|
||||
|
||||
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(),
|
||||
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(),
|
||||
fEdgeDistanceDerivatives.c_str());
|
||||
}
|
||||
|
||||
void GrCCPRQuadraticCornerProcessor::emitShaderCoverage(GrGLSLFragmentBuilder* f,
|
||||
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());
|
||||
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
|
||||
// the same pixel because those cases should have been weeded out by this point.
|
||||
f->codeAppend ("highp float f = x*x - y;");
|
||||
f->codeAppend ("highp float2 grad_f = float2(2*x, -1) * float2x2(grad_xyd);");
|
||||
f->codeAppend ("highfloat f = x*x - y;");
|
||||
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 -= d;", outputCoverage);
|
||||
|
||||
// Use software msaa to approximate coverage at the corner pixels.
|
||||
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());
|
||||
f->codeAppendf("for (int i = 0; i < %i; ++i) {", sampleCount);
|
||||
f->codeAppend ( "highp float3 xyd = grad_xyd * samples[i] + xyd_center;");
|
||||
f->codeAppend ( "lowp float 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->codeAppend ( "highfloat3 xyd = grad_xyd * samples[i] + xyd_center;");
|
||||
f->codeAppend ( "half f = xyd.y - xyd.x * xyd.x;"); // f > 0 -> inside curve.
|
||||
f->codeAppendf( "%s += all(greaterThan(highfloat2(f,xyd.z), highfloat2(0))) ? %f : 0;",
|
||||
outputCoverage, 1.0 / sampleCount);
|
||||
f->codeAppendf("}");
|
||||
}
|
||||
|
@ -24,13 +24,12 @@ class GrCCPRQuadraticProcessor : public GrCCPRCoverageProcessor::PrimitiveProces
|
||||
public:
|
||||
GrCCPRQuadraticProcessor()
|
||||
: INHERITED(CoverageType::kShader)
|
||||
, fCanonicalMatrix("canonical_matrix", kMat33f_GrSLType, GrShaderVar::kNonArray,
|
||||
kHigh_GrSLPrecision)
|
||||
, fCanonicalDerivatives("canonical_derivatives", kMat22f_GrSLType,
|
||||
GrShaderVar::kNonArray, kHigh_GrSLPrecision)
|
||||
, fEdgeDistanceEquation("edge_distance_equation", kVec3f_GrSLType,
|
||||
GrShaderVar::kNonArray, kHigh_GrSLPrecision)
|
||||
, fXYD(kVec3f_GrSLType) {}
|
||||
, fCanonicalMatrix("canonical_matrix", kHighFloat3x3_GrSLType, GrShaderVar::kNonArray)
|
||||
, fCanonicalDerivatives("canonical_derivatives", kHighFloat2x2_GrSLType,
|
||||
GrShaderVar::kNonArray)
|
||||
, fEdgeDistanceEquation("edge_distance_equation", kHighFloat3_GrSLType,
|
||||
GrShaderVar::kNonArray)
|
||||
, fXYD(kHighFloat3_GrSLType) {}
|
||||
|
||||
void resetVaryings(GrGLSLVaryingHandler* varyingHandler) override {
|
||||
varyingHandler->addVarying("xyd", &fXYD, kHigh_GrSLPrecision);
|
||||
@ -67,7 +66,7 @@ protected:
|
||||
class GrCCPRQuadraticHullProcessor : public GrCCPRQuadraticProcessor {
|
||||
public:
|
||||
GrCCPRQuadraticHullProcessor()
|
||||
: fGradXY(kVec2f_GrSLType) {}
|
||||
: fGradXY(kHighFloat2_GrSLType) {}
|
||||
|
||||
void resetVaryings(GrGLSLVaryingHandler* varyingHandler) override {
|
||||
this->INHERITED::resetVaryings(varyingHandler);
|
||||
@ -91,10 +90,10 @@ private:
|
||||
class GrCCPRQuadraticCornerProcessor : public GrCCPRQuadraticProcessor {
|
||||
public:
|
||||
GrCCPRQuadraticCornerProcessor()
|
||||
: fEdgeDistanceDerivatives("edge_distance_derivatives", kVec2f_GrSLType,
|
||||
GrShaderVar::kNonArray, kHigh_GrSLPrecision)
|
||||
, fdXYDdx(kVec3f_GrSLType)
|
||||
, fdXYDdy(kVec3f_GrSLType) {}
|
||||
: fEdgeDistanceDerivatives("edge_distance_derivatives", kHighFloat2_GrSLType,
|
||||
GrShaderVar::kNonArray)
|
||||
, fdXYDdx(kHighFloat3_GrSLType)
|
||||
, fdXYDdy(kHighFloat3_GrSLType) {}
|
||||
|
||||
void resetVaryings(GrGLSLVaryingHandler* varyingHandler) override {
|
||||
this->INHERITED::resetVaryings(varyingHandler);
|
||||
|
@ -16,16 +16,16 @@ void GrCCPRTriangleProcessor::onEmitVertexShader(const GrCCPRCoverageProcessor&
|
||||
const TexelBufferHandle& pointsBuffer,
|
||||
const char* atlasOffset, const char* rtAdjust,
|
||||
GrGPArgs* gpArgs) const {
|
||||
v->codeAppend ("highp float2 self = ");
|
||||
v->codeAppend ("highfloat2 self = ");
|
||||
v->appendTexelFetch(pointsBuffer,
|
||||
SkStringPrintf("%s[sk_VertexID]", proc.instanceAttrib()).c_str());
|
||||
v->codeAppendf(".xy + %s;", atlasOffset);
|
||||
gpArgs->fPositionVar.set(kVec2f_GrSLType, "self");
|
||||
gpArgs->fPositionVar.set(kHighFloat2_GrSLType, "self");
|
||||
}
|
||||
|
||||
void GrCCPRTriangleProcessor::defineInputVertices(GrGLSLGeometryBuilder* g) const {
|
||||
// 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[2].gl_Position.xy);");
|
||||
}
|
||||
@ -33,8 +33,8 @@ void GrCCPRTriangleProcessor::defineInputVertices(GrGLSLGeometryBuilder* g) cons
|
||||
void GrCCPRTriangleProcessor::emitWind(GrGLSLGeometryBuilder* g, const char* /*rtAdjust*/,
|
||||
const char* outputWind) const {
|
||||
// We will define in_vertices in defineInputVertices.
|
||||
g->codeAppendf("%s = sign(determinant(float2x2(in_vertices[1] - in_vertices[0], "
|
||||
"in_vertices[2] - in_vertices[0])));",
|
||||
g->codeAppendf("%s = sign(determinant(highfloat2x2(in_vertices[1] - in_vertices[0], "
|
||||
"in_vertices[2] - in_vertices[0])));",
|
||||
outputWind);
|
||||
}
|
||||
|
||||
@ -53,8 +53,8 @@ void GrCCPRTriangleHullAndEdgeProcessor::onEmitGeometryShader(GrGLSLGeometryBuil
|
||||
if (GeometryType::kHulls != fGeometryType) {
|
||||
g->codeAppend ("int edgeidx0 = sk_InvocationID, "
|
||||
"edgeidx1 = (edgeidx0 + 1) % 3;");
|
||||
g->codeAppendf("highp float2 edgept0 = in_vertices[%s > 0 ? edgeidx0 : edgeidx1];", wind);
|
||||
g->codeAppendf("highp float2 edgept1 = in_vertices[%s > 0 ? edgeidx1 : edgeidx0];", wind);
|
||||
g->codeAppendf("highfloat2 edgept0 = in_vertices[%s > 0 ? edgeidx0 : edgeidx1];", wind);
|
||||
g->codeAppendf("highfloat2 edgept1 = in_vertices[%s > 0 ? edgeidx1 : edgeidx0];", wind);
|
||||
|
||||
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);
|
||||
|
||||
// Fetch and transform the next point in the triangle.
|
||||
v->codeAppend ("highp float2 next = ");
|
||||
v->codeAppend ("highfloat2 next = ");
|
||||
v->appendTexelFetch(pointsBuffer,
|
||||
SkStringPrintf("%s[(sk_VertexID+1) %% 3]", proc.instanceAttrib()).c_str());
|
||||
v->codeAppendf(".xy + %s;", atlasOffset);
|
||||
|
||||
// Find the plane that gives distance from the [self -> next] edge, normalized to its AA
|
||||
// bloat width.
|
||||
v->codeAppend ("highp float2 n = float2(next.y - self.y, self.x - next.x);");
|
||||
v->codeAppendf("highp float2 d = n * float2x2(self + %f * sign(n), "
|
||||
v->codeAppend ("highfloat2 n = highfloat2(next.y - self.y, self.x - next.x);");
|
||||
v->codeAppendf("highfloat2 d = n * highfloat2x2(self + %f * sign(n), "
|
||||
"self - %f * sign(n));",
|
||||
kAABloatRadius, kAABloatRadius);
|
||||
|
||||
@ -98,7 +98,7 @@ void GrCCPRTriangleCornerProcessor::onEmitGeometryShader(GrGLSLGeometryBuilder*
|
||||
const char* rtAdjust) const {
|
||||
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");
|
||||
|
||||
g->configure(GrGLSLGeometryBuilder::InputType::kTriangles,
|
||||
@ -114,7 +114,7 @@ void GrCCPRTriangleCornerProcessor::emitPerVertexGeometryCode(SkString* fnBody,
|
||||
fNeighbors.gsOut(), fDevCoord.gsIn());
|
||||
fnBody->appendf("%s.zw = %s[(sk_InvocationID + 2) %% 3];",
|
||||
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 + 1) %% 3]) * %s;",
|
||||
fEdgeDistances.gsOut(), fEdgeDistance.gsIn(), fEdgeDistance.gsIn(),
|
||||
@ -129,32 +129,28 @@ void GrCCPRTriangleCornerProcessor::emitPerVertexGeometryCode(SkString* fnBody,
|
||||
void GrCCPRTriangleCornerProcessor::emitShaderCoverage(GrGLSLFragmentBuilder* f,
|
||||
const char* outputCoverage) const {
|
||||
// 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.
|
||||
GrShaderVar samples("samples", kVec4f_GrSLType, GrShaderVar::kNonArray,
|
||||
kHigh_GrSLPrecision);
|
||||
GrShaderVar samples("samples", kHighFloat4_GrSLType, GrShaderVar::kNonArray);
|
||||
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,
|
||||
kHigh_GrSLPrecision);
|
||||
GrShaderVar leftedge("leftedge", kHighFloat4_GrSLType, GrShaderVar::kNonArray);
|
||||
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,
|
||||
kHigh_GrSLPrecision);
|
||||
GrShaderVar rightedge("rightedge", kHighFloat4_GrSLType, GrShaderVar::kNonArray);
|
||||
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;
|
||||
GrShaderVar edgeArg("edge_distance", kVec3f_GrSLType, GrShaderVar::kNonArray,
|
||||
kHigh_GrSLPrecision);
|
||||
GrShaderVar edgeArg("edge_distance", kHighFloat3_GrSLType, GrShaderVar::kNonArray);
|
||||
f->emitFunction(kVoid_GrSLType, "sampleEdge", 1, &edgeArg, [&]() {
|
||||
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());
|
||||
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());
|
||||
b.appendf("if (%s.x <= 1e-3 || (abs(%s.x) < 1e-3 && %s.y > 0)) {",
|
||||
edgeArg.c_str(), edgeArg.c_str(), edgeArg.c_str());
|
||||
@ -166,10 +162,10 @@ void GrCCPRTriangleCornerProcessor::emitShaderCoverage(GrGLSLFragmentBuilder* f,
|
||||
}().c_str(), &sampleEdgeFn);
|
||||
|
||||
// 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);
|
||||
// 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);
|
||||
f->codeAppend ( "discard;");
|
||||
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
|
||||
// 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());
|
||||
|
||||
// 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());
|
||||
|
||||
// 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);
|
||||
// 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());
|
||||
// Sample the opposite edge.
|
||||
f->codeAppendf( "%s(%s[2]);", sampleEdgeFn.c_str(), fEdgeDistances.fsIn());
|
||||
f->codeAppend ("}");
|
||||
|
||||
f->codeAppendf("highp float4 widths = max(%s - %s, 0);", rightedge.c_str(), leftedge.c_str());
|
||||
f->codeAppendf("%s += dot(widths, float4(0.25));", outputCoverage);
|
||||
f->codeAppendf("highfloat4 widths = max(%s - %s, 0);", rightedge.c_str(), leftedge.c_str());
|
||||
f->codeAppendf("%s += dot(widths, highfloat4(0.25));", outputCoverage);
|
||||
}
|
||||
|
@ -72,11 +72,11 @@ class GrCCPRTriangleCornerProcessor : public GrCCPRTriangleProcessor {
|
||||
public:
|
||||
GrCCPRTriangleCornerProcessor()
|
||||
: INHERITED(CoverageType::kShader)
|
||||
, fEdgeDistance(kVec3f_GrSLType)
|
||||
, fDevCoord(kVec2f_GrSLType)
|
||||
, fNeighbors(kVec4f_GrSLType)
|
||||
, fEdgeDistances(kMat33f_GrSLType)
|
||||
, fCornerIdx(kInt_GrSLType) {}
|
||||
, fEdgeDistance(kHighFloat3_GrSLType)
|
||||
, fDevCoord(kHighFloat2_GrSLType)
|
||||
, fNeighbors(kHighFloat4_GrSLType)
|
||||
, fEdgeDistances(kHighFloat3x3_GrSLType)
|
||||
, fCornerIdx(kShort_GrSLType) {}
|
||||
|
||||
void resetVaryings(GrGLSLVaryingHandler* varyingHandler) override {
|
||||
this->INHERITED::resetVaryings(varyingHandler);
|
||||
|
@ -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
|
||||
// Packing structure: texel coordinates are multiplied by 2 (or shifted left 1)
|
||||
// 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);
|
||||
args.fVertBuilder->codeAppend("float2 intCoords = floor(0.5*indexTexCoords);");
|
||||
args.fVertBuilder->codeAppend("float2 diff = indexTexCoords - 2.0*intCoords;");
|
||||
args.fVertBuilder->codeAppend("float texIdx = 2.0*diff.x + diff.y;");
|
||||
args.fVertBuilder->codeAppend("half2 intCoords = floor(0.5*indexTexCoords);");
|
||||
args.fVertBuilder->codeAppend("half2 diff = indexTexCoords - 2.0*intCoords;");
|
||||
args.fVertBuilder->codeAppend("half texIdx = 2.0*diff.x + diff.y;");
|
||||
|
||||
// Multiply by 1/atlasSize to get normalized texture coordinates
|
||||
args.fVaryingHandler->addVarying("TextureCoords", uv, kHigh_GrSLPrecision);
|
||||
@ -49,12 +49,13 @@ static void append_multitexture_lookup(GrGLSLPrimitiveProcessor::EmitArgs& args,
|
||||
// conditionally load from the indexed texture sampler
|
||||
for (int i = 0; i < numTextureSamplers-1; ++i) {
|
||||
args.fFragBuilder->codeAppendf("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("; } else ");
|
||||
}
|
||||
args.fFragBuilder->codeAppendf("{ %s = ", colorName);
|
||||
args.fFragBuilder->appendTextureLookup(args.fTexSamplers[numTextureSamplers-1], coordName,
|
||||
kVec2f_GrSLType);
|
||||
kHighFloat2_GrSLType);
|
||||
args.fFragBuilder->codeAppend("; }");
|
||||
}
|
||||
|
||||
|
@ -77,7 +77,7 @@ void GrGLConicEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
|
||||
// emit attributes
|
||||
varyingHandler->emitAttributes(gp);
|
||||
|
||||
GrGLSLVertToFrag v(kVec4f_GrSLType);
|
||||
GrGLSLVertToFrag v(kHighFloat4_GrSLType);
|
||||
varyingHandler->addVarying("ConicCoeffs", &v, kHigh_GrSLPrecision);
|
||||
vertBuilder->codeAppendf("%s = %s;", v.vsOut(), gp.inConicCoeffs()->fName);
|
||||
|
||||
@ -102,26 +102,18 @@ void GrGLConicEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
|
||||
gp.localMatrix(),
|
||||
args.fFPCoordTransformHandler);
|
||||
|
||||
// TODO: this precision check should actually be a check on the number of bits
|
||||
// high and medium provide and the selection of the lowest level that suffices.
|
||||
// Additionally we should assert that the upstream code only lets us get here if
|
||||
// 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;
|
||||
}
|
||||
// TODO: we should check on the number of bits float and half provide and use the smallest one
|
||||
// that suffices. Additionally we should assert that the upstream code only lets us get here if
|
||||
// either float or half provides the required number of bits.
|
||||
|
||||
GrShaderVar edgeAlpha("edgeAlpha", kFloat_GrSLType, 0, precision);
|
||||
GrShaderVar dklmdx("dklmdx", kVec3f_GrSLType, 0, precision);
|
||||
GrShaderVar dklmdy("dklmdy", kVec3f_GrSLType, 0, precision);
|
||||
GrShaderVar dfdx("dfdx", kFloat_GrSLType, 0, precision);
|
||||
GrShaderVar dfdy("dfdy", kFloat_GrSLType, 0, precision);
|
||||
GrShaderVar gF("gF", kVec2f_GrSLType, 0, precision);
|
||||
GrShaderVar gFM("gFM", kFloat_GrSLType, 0, precision);
|
||||
GrShaderVar func("func", kFloat_GrSLType, 0, precision);
|
||||
GrShaderVar edgeAlpha("edgeAlpha", kHighFloat_GrSLType, 0);
|
||||
GrShaderVar dklmdx("dklmdx", kHighFloat3_GrSLType, 0);
|
||||
GrShaderVar dklmdy("dklmdy", kHighFloat3_GrSLType, 0);
|
||||
GrShaderVar dfdx("dfdx", kHighFloat_GrSLType, 0);
|
||||
GrShaderVar dfdy("dfdy", kHighFloat_GrSLType, 0);
|
||||
GrShaderVar gF("gF", kHighFloat2_GrSLType, 0);
|
||||
GrShaderVar gFM("gFM", kHighFloat_GrSLType, 0);
|
||||
GrShaderVar func("func", kHighFloat_GrSLType, 0);
|
||||
|
||||
fragBuilder->declAppend(edgeAlpha);
|
||||
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());
|
||||
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));",
|
||||
gFM.c_str(), gF.c_str(), gF.c_str());
|
||||
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());
|
||||
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));",
|
||||
gFM.c_str(), gF.c_str(), gF.c_str());
|
||||
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: {
|
||||
fragBuilder->codeAppendf("%s = %s.x * %s.x - %s.y * %s.z;",
|
||||
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());
|
||||
break;
|
||||
}
|
||||
@ -203,14 +197,13 @@ void GrGLConicEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
|
||||
if (gp.coverageScale() != 0xff) {
|
||||
const char* coverageScale;
|
||||
fCoverageScaleUniform = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kFloat_GrSLType,
|
||||
kHigh_GrSLPrecision,
|
||||
kHighFloat_GrSLType,
|
||||
"Coverage",
|
||||
&coverageScale);
|
||||
fragBuilder->codeAppendf("%s = float4(%s * %s);",
|
||||
fragBuilder->codeAppendf("%s = half4(%s * %s);",
|
||||
args.fOutputCoverage, coverageScale, edgeAlpha.c_str());
|
||||
} 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
|
||||
varyingHandler->emitAttributes(gp);
|
||||
|
||||
GrGLSLVertToFrag v(kVec4f_GrSLType);
|
||||
GrGLSLVertToFrag v(kHalf4_GrSLType);
|
||||
varyingHandler->addVarying("HairQuadEdge", &v);
|
||||
vertBuilder->codeAppendf("%s = %s;", v.vsOut(), gp.inHairQuadEdge()->fName);
|
||||
|
||||
@ -363,13 +356,13 @@ void GrGLQuadEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
|
||||
gp.localMatrix(),
|
||||
args.fFPCoordTransformHandler);
|
||||
|
||||
fragBuilder->codeAppendf("float edgeAlpha;");
|
||||
fragBuilder->codeAppendf("half edgeAlpha;");
|
||||
|
||||
switch (fEdgeType) {
|
||||
case kHairlineAA_GrProcessorEdgeType: {
|
||||
fragBuilder->codeAppendf("float2 duvdx = dFdx(%s.xy);", v.fsIn());
|
||||
fragBuilder->codeAppendf("float2 duvdy = dFdy(%s.xy);", v.fsIn());
|
||||
fragBuilder->codeAppendf("float2 gF = float2(2.0 * %s.x * duvdx.x - duvdx.y,"
|
||||
fragBuilder->codeAppendf("half2 duvdx = dFdx(%s.xy);", v.fsIn());
|
||||
fragBuilder->codeAppendf("half2 duvdy = dFdy(%s.xy);", v.fsIn());
|
||||
fragBuilder->codeAppendf("half2 gF = half2(2.0 * %s.x * duvdx.x - duvdx.y,"
|
||||
" 2.0 * %s.x * duvdy.x - duvdy.y);",
|
||||
v.fsIn(), v.fsIn());
|
||||
fragBuilder->codeAppendf("edgeAlpha = (%s.x * %s.x - %s.y);",
|
||||
@ -381,9 +374,9 @@ void GrGLQuadEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
|
||||
break;
|
||||
}
|
||||
case kFillAA_GrProcessorEdgeType: {
|
||||
fragBuilder->codeAppendf("float2 duvdx = dFdx(%s.xy);", v.fsIn());
|
||||
fragBuilder->codeAppendf("float2 duvdy = dFdy(%s.xy);", v.fsIn());
|
||||
fragBuilder->codeAppendf("float2 gF = float2(2.0 * %s.x * duvdx.x - duvdx.y,"
|
||||
fragBuilder->codeAppendf("half2 duvdx = dFdx(%s.xy);", v.fsIn());
|
||||
fragBuilder->codeAppendf("half2 duvdy = dFdy(%s.xy);", v.fsIn());
|
||||
fragBuilder->codeAppendf("half2 gF = half2(2.0 * %s.x * duvdx.x - duvdx.y,"
|
||||
" 2.0 * %s.x * duvdy.x - duvdy.y);",
|
||||
v.fsIn(), v.fsIn());
|
||||
fragBuilder->codeAppendf("edgeAlpha = (%s.x * %s.x - %s.y);",
|
||||
@ -397,7 +390,7 @@ void GrGLQuadEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
|
||||
case kFillBW_GrProcessorEdgeType: {
|
||||
fragBuilder->codeAppendf("edgeAlpha = (%s.x * %s.x - %s.y);",
|
||||
v.fsIn(), v.fsIn(), v.fsIn());
|
||||
fragBuilder->codeAppend("edgeAlpha = float(edgeAlpha < 0.0);");
|
||||
fragBuilder->codeAppend("edgeAlpha = half(edgeAlpha < 0.0);");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -407,13 +400,13 @@ void GrGLQuadEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
|
||||
if (0xff != gp.coverageScale()) {
|
||||
const char* coverageScale;
|
||||
fCoverageScaleUniform = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kFloat_GrSLType,
|
||||
kDefault_GrSLPrecision,
|
||||
kHalf_GrSLType,
|
||||
"Coverage",
|
||||
&coverageScale);
|
||||
fragBuilder->codeAppendf("%s = float4(%s * edgeAlpha);", args.fOutputCoverage, coverageScale);
|
||||
fragBuilder->codeAppendf("%s = half4(%s * edgeAlpha);", args.fOutputCoverage,
|
||||
coverageScale);
|
||||
} 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
|
||||
const char* devkLMMatrixName;
|
||||
fDevKLMUniform = uniformHandler->addUniform(kVertex_GrShaderFlag, kMat33f_GrSLType,
|
||||
kHigh_GrSLPrecision, "KLM", &devkLMMatrixName);
|
||||
GrGLSLVertToFrag v(kVec3f_GrSLType);
|
||||
fDevKLMUniform = uniformHandler->addUniform(kVertex_GrShaderFlag, kHighFloat3x3_GrSLType, "KLM",
|
||||
&devkLMMatrixName);
|
||||
GrGLSLVertToFrag v(kHighFloat3_GrSLType);
|
||||
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());
|
||||
|
||||
|
||||
GrGLSLVertToFrag gradCoeffs(kVec4f_GrSLType);
|
||||
GrGLSLVertToFrag gradCoeffs(kHighFloat4_GrSLType);
|
||||
if (kFillAA_GrProcessorEdgeType == fEdgeType || kHairlineAA_GrProcessorEdgeType == fEdgeType) {
|
||||
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());
|
||||
vertBuilder->codeAppendf("highp float2 gk = float2(%s[0][0], %s[1][0]), "
|
||||
"gl = float2(%s[0][1], %s[1][1]), "
|
||||
"gm = float2(%s[0][2], %s[1][2]);",
|
||||
vertBuilder->codeAppendf("highfloat2 gk = highfloat2(%s[0][0], %s[1][0]), "
|
||||
"gl = highfloat2(%s[0][1], %s[1][1]), "
|
||||
"gm = highfloat2(%s[0][2], %s[1][2]);",
|
||||
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());
|
||||
}
|
||||
|
||||
@ -592,9 +585,9 @@ void GrGLCubicEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
|
||||
args.fFPCoordTransformHandler);
|
||||
|
||||
|
||||
GrShaderVar edgeAlpha("edgeAlpha", kFloat_GrSLType, 0, kHigh_GrSLPrecision);
|
||||
GrShaderVar gF("gF", kVec2f_GrSLType, 0, kHigh_GrSLPrecision);
|
||||
GrShaderVar func("func", kFloat_GrSLType, 0, kHigh_GrSLPrecision);
|
||||
GrShaderVar edgeAlpha("edgeAlpha", kHighFloat_GrSLType, 0);
|
||||
GrShaderVar gF("gF", kHighFloat2_GrSLType, 0);
|
||||
GrShaderVar func("func", kHighFloat_GrSLType, 0);
|
||||
|
||||
fragBuilder->declAppend(edgeAlpha);
|
||||
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;",
|
||||
edgeAlpha.c_str(), 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;
|
||||
}
|
||||
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,
|
||||
|
@ -42,8 +42,7 @@ void GrGLBicubicEffect::emitCode(EmitArgs& args) {
|
||||
const GrBicubicEffect& bicubicEffect = args.fFp.cast<GrBicubicEffect>();
|
||||
|
||||
GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
|
||||
fImageIncrementUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kVec2f_GrSLType, kDefault_GrSLPrecision,
|
||||
fImageIncrementUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType,
|
||||
"ImageIncrement");
|
||||
|
||||
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).
|
||||
*/
|
||||
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,"
|
||||
"-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,"
|
||||
"-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 then snap coord to a texel center and renormalize. The snap prevents cases where the
|
||||
// starting coords are near a texel boundary and accumulations of imgInc would cause us to skip/
|
||||
// double hit a texel.
|
||||
fragBuilder->codeAppendf("coord /= %s;", imgInc);
|
||||
fragBuilder->codeAppend("float2 f = fract(coord);");
|
||||
fragBuilder->codeAppendf("coord = (coord - f + float2(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("float4 wy = kMitchellCoefficients * float4(1.0, f.y, f.y * f.y, f.y * f.y * f.y);");
|
||||
fragBuilder->codeAppend("float4 rowColors[4];");
|
||||
fragBuilder->codeAppend("highfloat2 f = fract(coord);");
|
||||
fragBuilder->codeAppendf("coord = (coord - f + highfloat2(0.5)) * %s;", imgInc);
|
||||
fragBuilder->codeAppend("half4 wx = kMitchellCoefficients * half4(1.0, f.x, f.x * f.x, f.x * f.x * f.x);");
|
||||
fragBuilder->codeAppend("half4 wy = kMitchellCoefficients * half4(1.0, f.y, f.y * f.y, f.y * f.y * f.y);");
|
||||
fragBuilder->codeAppend("half4 rowColors[4];");
|
||||
for (int y = 0; y < 4; ++y) {
|
||||
for (int x = 0; x < 4; ++x) {
|
||||
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;
|
||||
sampleVar.printf("rowColors[%d]", x);
|
||||
fDomain.sampleTexture(fragBuilder,
|
||||
@ -102,7 +101,7 @@ void GrGLBicubicEffect::emitCode(EmitArgs& args) {
|
||||
args.fTexSamplers[0]);
|
||||
}
|
||||
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);
|
||||
}
|
||||
SkString bicubicColor("(wy.x * s0 + wy.y * s1 + wy.z * s2 + wy.w * s3)");
|
||||
|
@ -32,13 +32,13 @@ public:
|
||||
|
||||
const char* atlasSizeInvName;
|
||||
fAtlasSizeInvUniform = uniformHandler->addUniform(kVertex_GrShaderFlag,
|
||||
kVec2f_GrSLType,
|
||||
kHighFloat2_GrSLType,
|
||||
kHigh_GrSLPrecision,
|
||||
"AtlasSizeInv",
|
||||
&atlasSizeInvName);
|
||||
|
||||
GrGLSLVertToFrag uv(kVec2f_GrSLType);
|
||||
GrGLSLVertToFrag texIdx(kFloat_GrSLType);
|
||||
GrGLSLVertToFrag uv(kHighFloat2_GrSLType);
|
||||
GrGLSLVertToFrag texIdx(kHalf_GrSLType);
|
||||
append_index_uv_varyings(args, btgp.inTextureCoords()->fName, atlasSizeInvName,
|
||||
&uv, &texIdx, nullptr);
|
||||
|
||||
@ -63,14 +63,14 @@ public:
|
||||
btgp.localMatrix(),
|
||||
args.fFPCoordTransformHandler);
|
||||
|
||||
fragBuilder->codeAppend("float4 texColor;");
|
||||
fragBuilder->codeAppend("half4 texColor;");
|
||||
append_multitexture_lookup(args, btgp.numTextureSamplers(),
|
||||
texIdx, uv.fsIn(), "texColor");
|
||||
|
||||
if (btgp.maskFormat() == kARGB_GrMaskFormat) {
|
||||
// modulate by color
|
||||
fragBuilder->codeAppendf("%s = %s * texColor;", args.fOutputColor, args.fOutputColor);
|
||||
fragBuilder->codeAppendf("%s = float4(1);", args.fOutputCoverage);
|
||||
fragBuilder->codeAppendf("%s = half4(1);", args.fOutputCoverage);
|
||||
} else {
|
||||
fragBuilder->codeAppendf("%s = texColor;", args.fOutputCoverage);
|
||||
}
|
||||
|
@ -25,12 +25,12 @@ public:
|
||||
args.fFp.cast<GrBlurredEdgeFragmentProcessor>();
|
||||
(void)_outer;
|
||||
fragBuilder->codeAppendf(
|
||||
"float factor = 1.0 - %s.w;\n@switch (%d) {\n case 0:\n factor = "
|
||||
"exp((-factor * factor) * 4.0) - 0.017999999999999999;\n break;\n case "
|
||||
"1:\n factor = smoothstep(1.0, 0.0, factor);\n break;\n}\n%s = "
|
||||
"float4(factor);\n",
|
||||
args.fInputColor ? args.fInputColor : "float4(1)", _outer.mode(),
|
||||
args.fOutputColor);
|
||||
"half factor = half(1.0 - highfloat(%s.w));\n@switch (%d) {\n case 0:\n "
|
||||
"factor = half(exp(highfloat(highfloat(-factor * factor) * 4.0)) - "
|
||||
"0.017999999999999999);\n break;\n case 1:\n factor = "
|
||||
"half(smoothstep(1.0, 0.0, highfloat(factor)));\n break;\n}\n%s = "
|
||||
"half4(factor);\n",
|
||||
args.fInputColor ? args.fInputColor : "half4(1)", _outer.mode(), args.fOutputColor);
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -15,7 +15,7 @@
|
||||
layout(key) in int mode;
|
||||
|
||||
void main() {
|
||||
float factor = 1.0 - sk_InColor.a;
|
||||
half factor = 1.0 - sk_InColor.a;
|
||||
@switch (mode) {
|
||||
case 0: // kGaussian_Mode
|
||||
factor = exp(-factor * factor * 4.0) - 0.018;
|
||||
@ -24,5 +24,5 @@ void main() {
|
||||
factor = smoothstep(1.0, 0.0, factor);
|
||||
break;
|
||||
}
|
||||
sk_OutColor = float4(factor);
|
||||
sk_OutColor = half4(factor);
|
||||
}
|
||||
|
@ -24,14 +24,15 @@ public:
|
||||
const GrCircleEffect& _outer = args.fFp.cast<GrCircleEffect>();
|
||||
(void)_outer;
|
||||
prevRadius = -1.0;
|
||||
fCircleVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kVec4f_GrSLType,
|
||||
fCircleVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType,
|
||||
kDefault_GrSLPrecision, "circle");
|
||||
fragBuilder->codeAppendf(
|
||||
"float2 prevCenter;\nfloat prevRadius = %f;\nfloat d;\n@if (%d == 2 || %d == 3) "
|
||||
"{\n d = (length((%s.xy - sk_FragCoord.xy) * %s.w) - 1.0) * %s.z;\n} else {\n "
|
||||
" d = (1.0 - length((%s.xy - sk_FragCoord.xy) * %s.w)) * %s.z;\n}\n@if ((%d == 1 "
|
||||
"|| %d == 3) || %d == 4) {\n d = clamp(d, 0.0, 1.0);\n} else {\n d = d > 0.5 "
|
||||
"? 1.0 : 0.0;\n}\n%s = %s * d;\n",
|
||||
"half2 prevCenter;\nhalf prevRadius = %f;\nhalf d;\n@if (%d == 2 || %d == 3) {\n "
|
||||
" d = (highfloat(length((%s.xy - half2(sk_FragCoord.xy)) * %s.w)) - 1.0) * "
|
||||
"%s.z;\n} else {\n d = half((1.0 - highfloat(length((%s.xy - "
|
||||
"half2(sk_FragCoord.xy)) * %s.w))) * highfloat(%s.z));\n}\n@if ((%d == 1 || %d == "
|
||||
"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(),
|
||||
args.fUniformHandler->getUniformCStr(fCircleVar),
|
||||
args.fUniformHandler->getUniformCStr(fCircleVar),
|
||||
@ -40,7 +41,7 @@ public:
|
||||
args.fUniformHandler->getUniformCStr(fCircleVar),
|
||||
args.fUniformHandler->getUniformCStr(fCircleVar), _outer.edgeType(),
|
||||
_outer.edgeType(), _outer.edgeType(), args.fOutputColor,
|
||||
args.fInputColor ? args.fInputColor : "float4(1)");
|
||||
args.fInputColor ? args.fInputColor : "half4(1)");
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -6,14 +6,14 @@
|
||||
*/
|
||||
|
||||
layout(key) in int edgeType;
|
||||
in float2 center;
|
||||
in float radius;
|
||||
in half2 center;
|
||||
in half radius;
|
||||
|
||||
float2 prevCenter;
|
||||
float prevRadius = -1;
|
||||
half2 prevCenter;
|
||||
half prevRadius = -1;
|
||||
// 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.
|
||||
uniform float4 circle;
|
||||
uniform half4 circle;
|
||||
|
||||
@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
|
||||
// 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.
|
||||
float d;
|
||||
half d;
|
||||
@if (edgeType == 2 /* kInverseFillBW_GrProcessorEdgeType */ ||
|
||||
edgeType == 3 /* kInverseFillAA_GrProcessorEdgeType */) {
|
||||
d = (length((circle.xy - sk_FragCoord.xy) * circle.w) - 1.0) * circle.z;
|
||||
|
@ -21,16 +21,16 @@ public:
|
||||
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
|
||||
|
||||
// Use highp throughout the shader to avoid some precision issues on specific GPUs.
|
||||
fragBuilder->elevateDefaultPrecision(kHigh_GrSLPrecision);
|
||||
fragBuilder->forceHighPrecision();
|
||||
|
||||
if (nullptr == args.fInputColor) {
|
||||
// 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
|
||||
// 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()) {
|
||||
case GrConfigConversionEffect::kToPremul_PMConversion:
|
||||
@ -40,7 +40,7 @@ public:
|
||||
|
||||
case GrConfigConversionEffect::kToUnpremul_PMConversion:
|
||||
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;
|
||||
|
||||
default:
|
||||
|
@ -19,7 +19,7 @@ public:
|
||||
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
|
||||
const char* colorUni;
|
||||
fColorUniform = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kVec4f_GrSLType, kMedium_GrSLPrecision,
|
||||
kHalf4_GrSLType,
|
||||
"constantColor",
|
||||
&colorUni);
|
||||
GrConstColorProcessor::InputMode mode = args.fFp.cast<GrConstColorProcessor>().inputMode();
|
||||
|
@ -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),
|
||||
// respectively.
|
||||
fRectUniform = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kVec4f_GrSLType,
|
||||
kDefault_GrSLPrecision,
|
||||
kHalf4_GrSLType,
|
||||
"rect",
|
||||
&rectName);
|
||||
|
||||
@ -112,16 +111,16 @@ void GLAARectEffect::emitCode(EmitArgs& args) {
|
||||
if (GrProcessorEdgeTypeIsAA(aare.getEdgeType())) {
|
||||
// The amount of coverage removed in x and y by the edges is computed as a pair of negative
|
||||
// numbers, xSub and ySub.
|
||||
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(%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(%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
|
||||
// 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 {
|
||||
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",
|
||||
rectName);
|
||||
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;
|
||||
fEdgeUniform = args.fUniformHandler->addUniformArray(kFragment_GrShaderFlag,
|
||||
kVec3f_GrSLType,
|
||||
kDefault_GrSLPrecision,
|
||||
kHalf3_GrSLType,
|
||||
"edges",
|
||||
cpe.getEdgeCount(),
|
||||
&edgeArrayName);
|
||||
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
|
||||
fragBuilder->codeAppend("\t\tfloat alpha = 1.0;\n");
|
||||
fragBuilder->codeAppend("\t\tfloat edge;\n");
|
||||
fragBuilder->codeAppend("\t\thalf alpha = 1.0;\n");
|
||||
fragBuilder->codeAppend("\t\thalf edge;\n");
|
||||
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",
|
||||
edgeArrayName, i);
|
||||
if (GrProcessorEdgeTypeIsAA(cpe.getEdgeType())) {
|
||||
|
@ -53,7 +53,7 @@ private:
|
||||
// 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.
|
||||
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 {}
|
||||
|
@ -45,7 +45,7 @@ public:
|
||||
|
||||
const char* atlasSizeInvName;
|
||||
fAtlasSizeInvUniform = uniformHandler->addUniform(kVertex_GrShaderFlag,
|
||||
kVec2f_GrSLType,
|
||||
kHighFloat2_GrSLType,
|
||||
kHigh_GrSLPrecision,
|
||||
"AtlasSizeInv",
|
||||
&atlasSizeInvName);
|
||||
@ -53,8 +53,7 @@ public:
|
||||
// adjust based on gamma
|
||||
const char* distanceAdjustUniName = nullptr;
|
||||
// width, height, 1/(3*width)
|
||||
fDistanceAdjustUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kFloat_GrSLType, kDefault_GrSLPrecision,
|
||||
fDistanceAdjustUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType,
|
||||
"DistanceAdjust", &distanceAdjustUniName);
|
||||
#endif
|
||||
|
||||
@ -78,9 +77,9 @@ public:
|
||||
args.fFPCoordTransformHandler);
|
||||
|
||||
// add varyings
|
||||
GrGLSLVertToFrag uv(kVec2f_GrSLType);
|
||||
GrGLSLVertToFrag texIdx(kFloat_GrSLType);
|
||||
GrGLSLVertToFrag st(kVec2f_GrSLType);
|
||||
GrGLSLVertToFrag uv(kHighFloat2_GrSLType);
|
||||
GrGLSLVertToFrag texIdx(kHalf_GrSLType);
|
||||
GrGLSLVertToFrag st(kHighFloat2_GrSLType);
|
||||
append_index_uv_varyings(args, dfTexEffect.inTextureCoords()->fName, atlasSizeInvName,
|
||||
&uv, &texIdx, &st);
|
||||
|
||||
@ -93,19 +92,19 @@ public:
|
||||
SkToBool(dfTexEffect.getFlags() & kAliased_DistanceFieldEffectFlag);
|
||||
|
||||
// Use highp to work around aliasing issues
|
||||
fragBuilder->codeAppendf("highp float2 uv = %s;\n", uv.fsIn());
|
||||
fragBuilder->codeAppend("float4 texColor;");
|
||||
fragBuilder->codeAppendf("highfloat2 uv = %s;\n", uv.fsIn());
|
||||
fragBuilder->codeAppend("half4 texColor;");
|
||||
append_multitexture_lookup(args, dfTexEffect.numTextureSamplers(),
|
||||
texIdx, "uv", "texColor");
|
||||
|
||||
fragBuilder->codeAppend("float distance = "
|
||||
fragBuilder->codeAppend("half distance = "
|
||||
SK_DistanceFieldMultiplier "*(texColor.r - " SK_DistanceFieldThreshold ");");
|
||||
#ifdef SK_GAMMA_APPLY_TO_A8
|
||||
// adjust width based on gamma
|
||||
fragBuilder->codeAppendf("distance -= %s;", distanceAdjustUniName);
|
||||
#endif
|
||||
|
||||
fragBuilder->codeAppend("float afwidth;");
|
||||
fragBuilder->codeAppend("half afwidth;");
|
||||
if (isUniformScale) {
|
||||
// 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.
|
||||
@ -128,29 +127,29 @@ public:
|
||||
|
||||
// this gives us a smooth step across approximately one fragment
|
||||
#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
|
||||
// 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
|
||||
fragBuilder->codeAppend("afwidth = abs(" SK_DistanceFieldAAFactor "*st_grad_len);");
|
||||
} else {
|
||||
// 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
|
||||
// (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
|
||||
// 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("dist_grad = float2(0.7071, 0.7071);");
|
||||
fragBuilder->codeAppend("dist_grad = half2(0.7071, 0.7071);");
|
||||
fragBuilder->codeAppend("} else {");
|
||||
fragBuilder->codeAppend("dist_grad = dist_grad*inversesqrt(dg_len2);");
|
||||
fragBuilder->codeAppend("}");
|
||||
|
||||
fragBuilder->codeAppendf("float2 Jdx = dFdx(%s);", st.fsIn());
|
||||
fragBuilder->codeAppendf("float2 Jdy = dFdy(%s);", st.fsIn());
|
||||
fragBuilder->codeAppend("float2 grad = float2(dist_grad.x*Jdx.x + dist_grad.y*Jdy.x,");
|
||||
fragBuilder->codeAppendf("half2 Jdx = dFdx(%s);", st.fsIn());
|
||||
fragBuilder->codeAppendf("half2 Jdy = dFdy(%s);", st.fsIn());
|
||||
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);");
|
||||
|
||||
// this gives us a smooth step across approximately one fragment
|
||||
@ -158,18 +157,18 @@ public:
|
||||
}
|
||||
|
||||
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) {
|
||||
// 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
|
||||
// distance mapped linearly to coverage, so use a linear step:
|
||||
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 {
|
||||
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,
|
||||
@ -341,14 +340,14 @@ public:
|
||||
|
||||
const char* atlasSizeInvName;
|
||||
fAtlasSizeInvUniform = uniformHandler->addUniform(kVertex_GrShaderFlag,
|
||||
kVec2f_GrSLType,
|
||||
kHighFloat2_GrSLType,
|
||||
kHigh_GrSLPrecision,
|
||||
"AtlasSizeInv",
|
||||
&atlasSizeInvName);
|
||||
|
||||
GrGLSLVertToFrag uv(kVec2f_GrSLType);
|
||||
GrGLSLVertToFrag texIdx(kFloat_GrSLType);
|
||||
GrGLSLVertToFrag st(kVec2f_GrSLType);
|
||||
GrGLSLVertToFrag uv(kHighFloat2_GrSLType);
|
||||
GrGLSLVertToFrag texIdx(kHalf_GrSLType);
|
||||
GrGLSLVertToFrag st(kHighFloat2_GrSLType);
|
||||
append_index_uv_varyings(args, dfTexEffect.inTextureCoords()->fName, atlasSizeInvName,
|
||||
&uv, &texIdx, &st);
|
||||
|
||||
@ -372,15 +371,15 @@ public:
|
||||
args.fFPCoordTransformHandler);
|
||||
|
||||
// Use highp to work around aliasing issues
|
||||
fragBuilder->codeAppendf("highp float2 uv = %s;", uv.fsIn());
|
||||
fragBuilder->codeAppend("float4 texColor;");
|
||||
fragBuilder->codeAppendf("highfloat2 uv = %s;", uv.fsIn());
|
||||
fragBuilder->codeAppend("half4 texColor;");
|
||||
append_multitexture_lookup(args, dfTexEffect.numTextureSamplers(),
|
||||
texIdx, "uv", "texColor");
|
||||
|
||||
fragBuilder->codeAppend("float distance = "
|
||||
fragBuilder->codeAppend("half distance = "
|
||||
SK_DistanceFieldMultiplier "*(texColor.r - " SK_DistanceFieldThreshold ");");
|
||||
|
||||
fragBuilder->codeAppend("float afwidth;");
|
||||
fragBuilder->codeAppend("half afwidth;");
|
||||
bool isUniformScale = (dfTexEffect.getFlags() & kUniformScale_DistanceFieldEffectMask) ==
|
||||
kUniformScale_DistanceFieldEffectMask;
|
||||
bool isSimilarity = SkToBool(dfTexEffect.getFlags() & kSimilarity_DistanceFieldEffectFlag);
|
||||
@ -407,30 +406,30 @@ public:
|
||||
|
||||
// this gives us a smooth step across approximately one fragment
|
||||
#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
|
||||
// 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
|
||||
fragBuilder->codeAppend("afwidth = abs(" SK_DistanceFieldAAFactor "*st_grad_len);");
|
||||
} else {
|
||||
// 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
|
||||
// (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
|
||||
// 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("dist_grad = float2(0.7071, 0.7071);");
|
||||
fragBuilder->codeAppend("dist_grad = half2(0.7071, 0.7071);");
|
||||
fragBuilder->codeAppend("} else {");
|
||||
fragBuilder->codeAppend("dist_grad = dist_grad*inversesqrt(dg_len2);");
|
||||
fragBuilder->codeAppend("}");
|
||||
|
||||
fragBuilder->codeAppendf("float2 Jdx = dFdx(%s);", st.fsIn());
|
||||
fragBuilder->codeAppendf("float2 Jdy = dFdy(%s);", st.fsIn());
|
||||
fragBuilder->codeAppend("float2 grad = float2(dist_grad.x*Jdx.x + dist_grad.y*Jdy.x,");
|
||||
fragBuilder->codeAppend(" dist_grad.x*Jdx.y + dist_grad.y*Jdy.y);");
|
||||
fragBuilder->codeAppendf("half2 Jdx = dFdx(%s);", st.fsIn());
|
||||
fragBuilder->codeAppendf("half2 Jdy = dFdy(%s);", st.fsIn());
|
||||
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);");
|
||||
|
||||
// this gives us a smooth step across approximately one fragment
|
||||
fragBuilder->codeAppend("afwidth = " SK_DistanceFieldAAFactor "*length(grad);");
|
||||
@ -440,12 +439,12 @@ public:
|
||||
// mapped linearly to coverage, so use a linear step:
|
||||
if (isGammaCorrect) {
|
||||
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 {
|
||||
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,
|
||||
@ -600,7 +599,7 @@ public:
|
||||
|
||||
const char* atlasSizeInvName;
|
||||
fAtlasSizeInvUniform = uniformHandler->addUniform(kVertex_GrShaderFlag,
|
||||
kVec2f_GrSLType,
|
||||
kHighFloat2_GrSLType,
|
||||
kHigh_GrSLPrecision,
|
||||
"AtlasSizeInv",
|
||||
&atlasSizeInvName);
|
||||
@ -627,13 +626,13 @@ public:
|
||||
args.fFPCoordTransformHandler);
|
||||
|
||||
// set up varyings
|
||||
GrGLSLVertToFrag uv(kVec2f_GrSLType);
|
||||
GrGLSLVertToFrag texIdx(kFloat_GrSLType);
|
||||
GrGLSLVertToFrag st(kVec2f_GrSLType);
|
||||
GrGLSLVertToFrag uv(kHighFloat2_GrSLType);
|
||||
GrGLSLVertToFrag texIdx(kHalf_GrSLType);
|
||||
GrGLSLVertToFrag st(kHighFloat2_GrSLType);
|
||||
append_index_uv_varyings(args, dfTexEffect.inTextureCoords()->fName, atlasSizeInvName,
|
||||
&uv, &texIdx, &st);
|
||||
|
||||
GrGLSLVertToFrag delta(kFloat_GrSLType);
|
||||
GrGLSLVertToFrag delta(kHighFloat_GrSLType);
|
||||
varyingHandler->addVarying("Delta", &delta, kHigh_GrSLPrecision);
|
||||
if (dfTexEffect.getFlags() & kBGR_DistanceFieldEffectFlag) {
|
||||
vertBuilder->codeAppendf("%s = -%s.x/3.0;", delta.vsOut(), atlasSizeInvName);
|
||||
@ -650,48 +649,48 @@ public:
|
||||
|
||||
// create LCD offset adjusted by inverse of transform
|
||||
// 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) {
|
||||
#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
|
||||
// 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
|
||||
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) {
|
||||
// For a similarity matrix with rotation, the gradient will not be aligned
|
||||
// with the texel coordinate axes, so we need to calculate it.
|
||||
#ifdef SK_VULKAN
|
||||
fragBuilder->codeAppendf("float2 st_grad = dFdx(%s);", st.fsIn());
|
||||
fragBuilder->codeAppendf("float2 offset = %s*st_grad;", delta.fsIn());
|
||||
fragBuilder->codeAppendf("half2 st_grad = dFdx(%s);", st.fsIn());
|
||||
fragBuilder->codeAppendf("half2 offset = %s*st_grad;", delta.fsIn());
|
||||
#else
|
||||
// We use dFdy because of a Mali 400 bug, and rotate -90 degrees to
|
||||
// get the gradient in the x direction.
|
||||
fragBuilder->codeAppendf("float2 st_grad = dFdy(%s);", st.fsIn());
|
||||
fragBuilder->codeAppendf("float2 offset = %s*float2(st_grad.y, -st_grad.x);",
|
||||
fragBuilder->codeAppendf("half2 st_grad = dFdy(%s);", st.fsIn());
|
||||
fragBuilder->codeAppendf("half2 offset = %s*half2(st_grad.y, -st_grad.x);",
|
||||
delta.fsIn());
|
||||
#endif
|
||||
fragBuilder->codeAppend("float st_grad_len = length(st_grad);");
|
||||
fragBuilder->codeAppend("half st_grad_len = length(st_grad);");
|
||||
} 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("float2 Jdy = dFdy(st);");
|
||||
fragBuilder->codeAppendf("float2 offset = %s*Jdx;", delta.fsIn());
|
||||
fragBuilder->codeAppend("half2 Jdx = dFdx(st);");
|
||||
fragBuilder->codeAppend("half2 Jdy = dFdy(st);");
|
||||
fragBuilder->codeAppendf("half2 offset = %s*Jdx;", delta.fsIn());
|
||||
}
|
||||
|
||||
// sample the texture by index
|
||||
fragBuilder->codeAppend("float4 texColor;");
|
||||
fragBuilder->codeAppend("half4 texColor;");
|
||||
append_multitexture_lookup(args, dfTexEffect.numTextureSamplers(),
|
||||
texIdx, "uv", "texColor");
|
||||
|
||||
// green is distance to uv center
|
||||
fragBuilder->codeAppend("float3 distance;");
|
||||
fragBuilder->codeAppend("half3 distance;");
|
||||
fragBuilder->codeAppend("distance.y = texColor.r;");
|
||||
// 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(),
|
||||
texIdx, "uv_adjusted", "texColor");
|
||||
fragBuilder->codeAppend("distance.x = texColor.r;");
|
||||
@ -702,12 +701,11 @@ public:
|
||||
fragBuilder->codeAppend("distance.z = texColor.r;");
|
||||
|
||||
fragBuilder->codeAppend("distance = "
|
||||
"float3(" SK_DistanceFieldMultiplier ")*(distance - float3(" SK_DistanceFieldThreshold"));");
|
||||
"half3(" SK_DistanceFieldMultiplier ")*(distance - half3(" SK_DistanceFieldThreshold"));");
|
||||
|
||||
// adjust width based on gamma
|
||||
const char* distanceAdjustUniName = nullptr;
|
||||
fDistanceAdjustUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kVec3f_GrSLType, kDefault_GrSLPrecision,
|
||||
fDistanceAdjustUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf3_GrSLType,
|
||||
"DistanceAdjust", &distanceAdjustUniName);
|
||||
fragBuilder->codeAppendf("distance -= %s;", distanceAdjustUniName);
|
||||
|
||||
@ -715,7 +713,7 @@ public:
|
||||
// for each color component. However, this is only important when using perspective
|
||||
// transformations, and even then using a single factor seems like a reasonable
|
||||
// trade-off between quality and speed.
|
||||
fragBuilder->codeAppend("float afwidth;");
|
||||
fragBuilder->codeAppend("half afwidth;");
|
||||
if (isSimilarity) {
|
||||
// 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
|
||||
@ -728,16 +726,16 @@ public:
|
||||
// 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
|
||||
// (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
|
||||
// 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("dist_grad = float2(0.7071, 0.7071);");
|
||||
fragBuilder->codeAppend("dist_grad = half2(0.7071, 0.7071);");
|
||||
fragBuilder->codeAppend("} else {");
|
||||
fragBuilder->codeAppend("dist_grad = dist_grad*inversesqrt(dg_len2);");
|
||||
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);");
|
||||
|
||||
// this gives us a smooth step across approximately one fragment
|
||||
@ -749,11 +747,11 @@ public:
|
||||
// mapped linearly to coverage, so use a linear step:
|
||||
if (isGammaCorrect) {
|
||||
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);
|
||||
} else {
|
||||
fragBuilder->codeAppendf(
|
||||
"%s = float4(smoothstep(float3(-afwidth), float3(afwidth), distance), 1.0);",
|
||||
"%s = half4(smoothstep(half3(-afwidth), half3(afwidth), distance), 1.0);",
|
||||
args.fOutputCoverage);
|
||||
}
|
||||
}
|
||||
|
@ -24,21 +24,22 @@ public:
|
||||
const GrDitherEffect& _outer = args.fFp.cast<GrDitherEffect>();
|
||||
(void)_outer;
|
||||
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.015873015873015872;\n break;\n default:\n range = "
|
||||
"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 = "
|
||||
"(((((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 "
|
||||
"modValues = mod(sk_FragCoord.xyxy, float4(2.0, 2.0, 4.0, 4.0));\n float4 "
|
||||
"stepValues = step(modValues, float4(1.0, 1.0, 2.0, 2.0));\n value = "
|
||||
"dot(stepValues, float4(0.5, 0.25, 0.125, 0.0625)) - 0.46875;\n}\n%s = "
|
||||
"float4(clamp(%s.xyz + value * range, 0.0, %s.w), %s.w);\n",
|
||||
"| (x & 4) >> 2;\n value = highfloat(highfloat(half(m)) / 64.0) - 0.4921875;\n} "
|
||||
"else {\n half4 modValues = half4(mod(sk_FragCoord.xyxy, highfloat4(half4(2.0, "
|
||||
"2.0, 4.0, 4.0))));\n half4 stepValues = half4(step(highfloat4(modValues), "
|
||||
"highfloat4(half4(1.0, 1.0, 2.0, 2.0))));\n value = highfloat(dot(stepValues, "
|
||||
"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,
|
||||
args.fInputColor ? args.fInputColor : "float4(1)",
|
||||
args.fInputColor ? args.fInputColor : "float4(1)",
|
||||
args.fInputColor ? args.fInputColor : "float4(1)");
|
||||
args.fInputColor ? args.fInputColor : "half4(1)",
|
||||
args.fInputColor ? args.fInputColor : "half4(1)",
|
||||
args.fInputColor ? args.fInputColor : "half4(1)");
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -32,8 +32,8 @@ layout(key) in int rangeType;
|
||||
}
|
||||
|
||||
void main() {
|
||||
float value;
|
||||
float range;
|
||||
half value;
|
||||
half range;
|
||||
@switch (rangeType) {
|
||||
case 0:
|
||||
range = 1.0 / 255.0;
|
||||
@ -53,17 +53,17 @@ void main() {
|
||||
uint m = (y & 1) << 5 | (x & 1) << 4 |
|
||||
(y & 2) << 2 | (x & 2) << 1 |
|
||||
(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 {
|
||||
// Simulate the integer effect used above using step/mod. For speed, simulates a 4x4
|
||||
// dither pattern rather than an 8x8 one.
|
||||
float4 modValues = mod(sk_FragCoord.xyxy, float4(2.0, 2.0, 4.0, 4.0));
|
||||
float4 stepValues = step(modValues, float4(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;
|
||||
half4 modValues = mod(sk_FragCoord.xyxy, half4(2.0, 2.0, 4.0, 4.0));
|
||||
half4 stepValues = step(modValues, half4(1.0, 1.0, 2.0, 2.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
|
||||
// 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) {
|
||||
|
@ -23,35 +23,34 @@ public:
|
||||
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
|
||||
const GrEllipseEffect& _outer = args.fFp.cast<GrEllipseEffect>();
|
||||
(void)_outer;
|
||||
prevRadii = float2(-1.0);
|
||||
prevRadii = half2(-1.0);
|
||||
useScale = sk_Caps.floatPrecisionVaries;
|
||||
fEllipseVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kVec4f_GrSLType,
|
||||
kHigh_GrSLPrecision, "ellipse");
|
||||
fEllipseVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHighFloat4_GrSLType,
|
||||
kDefault_GrSLPrecision, "ellipse");
|
||||
if (useScale) {
|
||||
fScaleVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kVec2f_GrSLType,
|
||||
fScaleVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType,
|
||||
kDefault_GrSLPrecision, "scale");
|
||||
}
|
||||
fragBuilder->codeAppendf(
|
||||
"float2 prevCenter;\nfloat2 prevRadii = float2(%f, %f);\nbool useScale = "
|
||||
"%s;\nfloat2 d = sk_FragCoord.xy - %s.xy;\n@if (useScale) {\n d *= "
|
||||
"%s.y;\n}\nfloat2 Z = d * %s.zw;\nfloat implicit = dot(Z, d) - 1.0;\nfloat "
|
||||
"grad_dot = 4.0 * dot(Z, Z);\ngrad_dot = max(grad_dot, 0.0001);\nfloat approx_dist "
|
||||
"= implicit * inversesqrt(grad_dot);\n@if (useScale) {\n approx_dist *= "
|
||||
"%s.x;\n}\nfloat alpha;\n@switch (%d) {\n case 0:\n alpha = approx_dist "
|
||||
"> 0.0 ? 0.0 : 1.0;\n break;\n case 1:\n alpha = clamp(0.5 - "
|
||||
"approx_dist, 0.0, 1.0);\n break;\n case 2:\n alpha = approx_dist "
|
||||
"> 0.0 ? 1.0 : 0.0;\n break;\n case 3:\n alpha = clamp(0.5 + "
|
||||
"approx_dist, 0.0, 1.0);\n break;\n default:\n discard;\n}\n%s = "
|
||||
"%s * alpha;\n",
|
||||
"half2 prevCenter;\nhalf2 prevRadii = half2(%f, %f);\nbool useScale = %s;\nhalf2 d "
|
||||
"= half2(sk_FragCoord.xy - %s.xy);\n@if (useScale) {\n d *= %s.y;\n}\nhalf2 Z = "
|
||||
"d * half2(%s.zw);\nhalf implicit = dot(Z, d) - 1.0;\nhalf grad_dot = 4.0 * dot(Z, "
|
||||
"Z);\ngrad_dot = half(max(highfloat(grad_dot), 0.0001));\nhalf approx_dist = "
|
||||
"highfloat(implicit) * inversesqrt(highfloat(grad_dot));\n@if (useScale) {\n "
|
||||
"approx_dist *= %s.x;\n}\nhalf alpha;\n@switch (%d) {\n case 0:\n alpha "
|
||||
"= half(highfloat(approx_dist) > 0.0 ? 0.0 : 1.0);\n break;\n case 1:\n "
|
||||
" alpha = half(clamp(0.5 - highfloat(approx_dist), 0.0, 1.0));\n "
|
||||
"break;\n case 2:\n alpha = half(highfloat(approx_dist) > 0.0 ? 1.0 : "
|
||||
"0.0);\n break;\n case 3:\n alpha = half(clamp(0.5 + "
|
||||
"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"),
|
||||
args.fUniformHandler->getUniformCStr(fEllipseVar),
|
||||
fScaleVar.isValid() ? args.fUniformHandler->getUniformCStr(fScaleVar)
|
||||
: "float2(0.0)",
|
||||
fScaleVar.isValid() ? args.fUniformHandler->getUniformCStr(fScaleVar) : "half2(0)",
|
||||
args.fUniformHandler->getUniformCStr(fEllipseVar),
|
||||
fScaleVar.isValid() ? args.fUniformHandler->getUniformCStr(fScaleVar)
|
||||
: "float2(0.0)",
|
||||
fScaleVar.isValid() ? args.fUniformHandler->getUniformCStr(fScaleVar) : "half2(0)",
|
||||
_outer.edgeType(), args.fOutputColor,
|
||||
args.fInputColor ? args.fInputColor : "float4(1)");
|
||||
args.fInputColor ? args.fInputColor : "half4(1)");
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -6,17 +6,17 @@
|
||||
*/
|
||||
|
||||
layout(key) in int edgeType;
|
||||
in float2 center;
|
||||
in float2 radii;
|
||||
in half2 center;
|
||||
in half2 radii;
|
||||
|
||||
float2 prevCenter;
|
||||
float2 prevRadii = float2(-1);
|
||||
half2 prevCenter;
|
||||
half2 prevRadii = half2(-1);
|
||||
// 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.
|
||||
uniform highp float4 ellipse;
|
||||
// The last two terms can underflow with halfs, so we use floats.
|
||||
uniform highfloat4 ellipse;
|
||||
|
||||
bool useScale = sk_Caps.floatPrecisionVaries;
|
||||
layout(when=useScale) uniform float2 scale;
|
||||
layout(when=useScale) uniform half2 scale;
|
||||
|
||||
@optimizationFlags { kCompatibleWithCoverageAsAlpha_OptimizationFlag }
|
||||
|
||||
@ -50,7 +50,7 @@ layout(when=useScale) uniform float2 scale;
|
||||
|
||||
void main() {
|
||||
// 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
|
||||
// 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
|
||||
@ -58,19 +58,19 @@ void main() {
|
||||
@if (useScale) {
|
||||
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.
|
||||
float implicit = dot(Z, d) - 1;
|
||||
half implicit = dot(Z, d) - 1;
|
||||
// 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.
|
||||
grad_dot = max(grad_dot, 1e-4);
|
||||
float approx_dist = implicit * inversesqrt(grad_dot);
|
||||
half approx_dist = implicit * inversesqrt(grad_dot);
|
||||
@if (useScale) {
|
||||
approx_dist *= scale.x;
|
||||
}
|
||||
|
||||
float alpha;
|
||||
half alpha;
|
||||
@switch (edgeType) {
|
||||
case 0 /* kFillBW_GrProcessorEdgeType */:
|
||||
alpha = approx_dist > 0.0 ? 0.0 : 1.0;
|
||||
|
@ -41,11 +41,11 @@ void GrGLConvolutionEffect::emitCode(EmitArgs& args) {
|
||||
args.fFp.cast<GrGaussianConvolutionFragmentProcessor>();
|
||||
|
||||
GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
|
||||
fImageIncrementUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kVec2f_GrSLType,
|
||||
kDefault_GrSLPrecision, "ImageIncrement");
|
||||
fImageIncrementUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType,
|
||||
"ImageIncrement");
|
||||
if (ce.useBounds()) {
|
||||
fBoundsUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kVec2f_GrSLType,
|
||||
kDefault_GrSLPrecision, "Bounds");
|
||||
fBoundsUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType,
|
||||
"Bounds");
|
||||
}
|
||||
|
||||
int width = ce.width();
|
||||
@ -53,19 +53,19 @@ void GrGLConvolutionEffect::emitCode(EmitArgs& args) {
|
||||
int arrayCount = (width + 3) / 4;
|
||||
SkASSERT(4 * arrayCount >= width);
|
||||
|
||||
fKernelUni = uniformHandler->addUniformArray(kFragment_GrShaderFlag, kVec4f_GrSLType,
|
||||
kDefault_GrSLPrecision, "Kernel", arrayCount);
|
||||
fKernelUni = uniformHandler->addUniformArray(kFragment_GrShaderFlag, kHalf4_GrSLType,
|
||||
"Kernel", arrayCount);
|
||||
|
||||
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
|
||||
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 char* imgInc = uniformHandler->getUniformCStr(fImageIncrementUni);
|
||||
|
||||
fragBuilder->codeAppendf("float2 coord = %s - %d.0 * %s;", coords2D.c_str(), ce.radius(), imgInc);
|
||||
fragBuilder->codeAppend("float2 coordSampled = float2(0, 0);");
|
||||
fragBuilder->codeAppendf("highfloat2 coord = %s - %d.0 * %s;", coords2D.c_str(), ce.radius(), imgInc);
|
||||
fragBuilder->codeAppend("highfloat2 coordSampled = half2(0, 0);");
|
||||
|
||||
// Manually unroll loop because some drivers don't; yields 20-30% speedup.
|
||||
const char* kVecSuffix[4] = {".x", ".y", ".z", ".w"};
|
||||
|
@ -47,20 +47,15 @@ void GrGLMatrixConvolutionEffect::emitCode(EmitArgs& args) {
|
||||
SkASSERT(4 * arrayCount >= kWidth * kHeight);
|
||||
|
||||
GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
|
||||
fImageIncrementUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kVec2f_GrSLType, kDefault_GrSLPrecision,
|
||||
fImageIncrementUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType,
|
||||
"ImageIncrement");
|
||||
fKernelUni = uniformHandler->addUniformArray(kFragment_GrShaderFlag,
|
||||
kVec4f_GrSLType, kDefault_GrSLPrecision,
|
||||
fKernelUni = uniformHandler->addUniformArray(kFragment_GrShaderFlag, kHalf4_GrSLType,
|
||||
"Kernel",
|
||||
arrayCount);
|
||||
fKernelOffsetUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kVec2f_GrSLType, kDefault_GrSLPrecision,
|
||||
fKernelOffsetUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType,
|
||||
"KernelOffset");
|
||||
fGainUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kFloat_GrSLType, kDefault_GrSLPrecision, "Gain");
|
||||
fBiasUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kFloat_GrSLType, kDefault_GrSLPrecision, "Bias");
|
||||
fGainUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType, "Gain");
|
||||
fBiasUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType, "Bias");
|
||||
|
||||
const char* kernelOffset = uniformHandler->getUniformCStr(fKernelOffsetUni);
|
||||
const char* imgInc = uniformHandler->getUniformCStr(fImageIncrementUni);
|
||||
@ -70,9 +65,9 @@ void GrGLMatrixConvolutionEffect::emitCode(EmitArgs& args) {
|
||||
|
||||
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
|
||||
SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
|
||||
fragBuilder->codeAppend("float4 sum = float4(0, 0, 0, 0);");
|
||||
fragBuilder->codeAppendf("float2 coord = %s - %s * %s;", coords2D.c_str(), kernelOffset, imgInc);
|
||||
fragBuilder->codeAppend("float4 c;");
|
||||
fragBuilder->codeAppend("half4 sum = half4(0, 0, 0, 0);");
|
||||
fragBuilder->codeAppendf("highfloat2 coord = %s - %s * %s;", coords2D.c_str(), kernelOffset, imgInc);
|
||||
fragBuilder->codeAppend("half4 c;");
|
||||
|
||||
const char* kVecSuffix[4] = { ".x", ".y", ".z", ".w" };
|
||||
for (int y = 0; y < kHeight; y++) {
|
||||
@ -80,10 +75,10 @@ void GrGLMatrixConvolutionEffect::emitCode(EmitArgs& args) {
|
||||
GrGLSLShaderBuilder::ShaderBlock block(fragBuilder);
|
||||
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]);
|
||||
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,
|
||||
uniformHandler,
|
||||
args.fShaderCaps,
|
||||
|
@ -23,24 +23,21 @@ public:
|
||||
const char* srcCoeffsName = nullptr;
|
||||
if (SkToBool(csxe.ops() & GrNonlinearColorSpaceXformEffect::kSrcTransfer_Op)) {
|
||||
fSrcTransferFnUni = uniformHandler->addUniformArray(
|
||||
kFragment_GrShaderFlag, kFloat_GrSLType, kDefault_GrSLPrecision,
|
||||
"SrcTransferFn", GrNonlinearColorSpaceXformEffect::kNumTransferFnCoeffs,
|
||||
&srcCoeffsName);
|
||||
kFragment_GrShaderFlag, kHalf_GrSLType, "SrcTransferFn",
|
||||
GrNonlinearColorSpaceXformEffect::kNumTransferFnCoeffs, &srcCoeffsName);
|
||||
}
|
||||
|
||||
const char* dstCoeffsName = nullptr;
|
||||
if (SkToBool(csxe.ops() & GrNonlinearColorSpaceXformEffect::kDstTransfer_Op)) {
|
||||
fDstTransferFnUni = uniformHandler->addUniformArray(
|
||||
kFragment_GrShaderFlag, kFloat_GrSLType, kDefault_GrSLPrecision,
|
||||
"DstTransferFn", GrNonlinearColorSpaceXformEffect::kNumTransferFnCoeffs,
|
||||
&dstCoeffsName);
|
||||
kFragment_GrShaderFlag, kHalf_GrSLType, "DstTransferFn",
|
||||
GrNonlinearColorSpaceXformEffect::kNumTransferFnCoeffs, &dstCoeffsName);
|
||||
}
|
||||
|
||||
const char* gamutXformName = nullptr;
|
||||
if (SkToBool(csxe.ops() & GrNonlinearColorSpaceXformEffect::kGamutXform_Op)) {
|
||||
fGamutXformUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kMat44f_GrSLType,
|
||||
kDefault_GrSLPrecision, "GamutXform",
|
||||
&gamutXformName);
|
||||
fGamutXformUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4x4_GrSLType,
|
||||
"GamutXform", &gamutXformName);
|
||||
}
|
||||
|
||||
// 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";
|
||||
static const GrShaderVar gTransferFnFuncArgs[] = {
|
||||
GrShaderVar("x", kFloat_GrSLType),
|
||||
GrShaderVar("x", kHalf_GrSLType),
|
||||
};
|
||||
SkString transferFnBody;
|
||||
// Temporaries to make evaluation line readable
|
||||
transferFnBody.printf("float A = %s[0];", coeffsName);
|
||||
transferFnBody.appendf("float B = %s[1];", coeffsName);
|
||||
transferFnBody.appendf("float C = %s[2];", coeffsName);
|
||||
transferFnBody.appendf("float D = %s[3];", coeffsName);
|
||||
transferFnBody.appendf("float E = %s[4];", coeffsName);
|
||||
transferFnBody.appendf("float F = %s[5];", coeffsName);
|
||||
transferFnBody.appendf("float G = %s[6];", coeffsName);
|
||||
transferFnBody.append("float s = sign(x);");
|
||||
transferFnBody.printf("half A = %s[0];", coeffsName);
|
||||
transferFnBody.appendf("half B = %s[1];", coeffsName);
|
||||
transferFnBody.appendf("half C = %s[2];", coeffsName);
|
||||
transferFnBody.appendf("half D = %s[3];", coeffsName);
|
||||
transferFnBody.appendf("half E = %s[4];", coeffsName);
|
||||
transferFnBody.appendf("half F = %s[5];", coeffsName);
|
||||
transferFnBody.appendf("half G = %s[6];", coeffsName);
|
||||
transferFnBody.append("half s = sign(x);");
|
||||
transferFnBody.append("x = abs(x);");
|
||||
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]);
|
||||
}
|
||||
|
||||
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)
|
||||
fragBuilder->codeAppendf("float nonZeroAlpha = max(color.a, 0.00001);");
|
||||
fragBuilder->codeAppendf("color = float4(color.rgb / nonZeroAlpha, nonZeroAlpha);");
|
||||
fragBuilder->codeAppendf("half nonZeroAlpha = max(color.a, 0.00001);");
|
||||
fragBuilder->codeAppendf("color = half4(color.rgb / nonZeroAlpha, nonZeroAlpha);");
|
||||
|
||||
// 2: Apply src transfer function (to get to linear RGB)
|
||||
if (srcCoeffsName) {
|
||||
@ -89,7 +86,7 @@ public:
|
||||
// 3: Apply gamut matrix
|
||||
if (gamutXformName) {
|
||||
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
|
||||
@ -100,7 +97,7 @@ public:
|
||||
}
|
||||
|
||||
// 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&,
|
||||
|
@ -440,7 +440,7 @@ static void append_color_output(const PorterDuffXferProcessor& xp,
|
||||
SkASSERT(inColor);
|
||||
switch (outputType) {
|
||||
case BlendFormula::kNone_OutputType:
|
||||
fragBuilder->codeAppendf("%s = float4(0.0);", output);
|
||||
fragBuilder->codeAppendf("%s = half4(0.0);", output);
|
||||
break;
|
||||
case BlendFormula::kCoverage_OutputType:
|
||||
// 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);
|
||||
break;
|
||||
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;
|
||||
default:
|
||||
SK_ABORT("Unsupported output type.");
|
||||
@ -629,8 +629,8 @@ public:
|
||||
private:
|
||||
void emitOutputsForBlendState(const EmitArgs& args) override {
|
||||
const char* alpha;
|
||||
fAlphaUniform = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kFloat_GrSLType,
|
||||
kDefault_GrSLPrecision, "alpha", &alpha);
|
||||
fAlphaUniform = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType,
|
||||
"alpha", &alpha);
|
||||
GrGLSLXPFragmentBuilder* fragBuilder = args.fXPFragBuilder;
|
||||
// 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
|
||||
|
@ -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
|
||||
// only rectangular corners, that side's value corresponds to the rect edge's value outset by
|
||||
// half a pixel.
|
||||
fInnerRectUniform = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kVec4f_GrSLType, kDefault_GrSLPrecision,
|
||||
"innerRect",
|
||||
&rectName);
|
||||
fInnerRectUniform = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType,
|
||||
"innerRect", &rectName);
|
||||
// x is (r + .5) and y is 1/(r + .5)
|
||||
fRadiusPlusHalfUniform = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kVec2f_GrSLType, kDefault_GrSLPrecision,
|
||||
"radiusPlusHalf",
|
||||
&radiusPlusHalfName);
|
||||
fRadiusPlusHalfUniform = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType,
|
||||
"radiusPlusHalf", &radiusPlusHalfName);
|
||||
|
||||
// If we're on a device with a "real" mediump then the length calculation could overflow.
|
||||
SkString clampedCircleDistance;
|
||||
@ -197,87 +193,87 @@ void GLCircularRRectEffect::emitCode(EmitArgs& args) {
|
||||
// alphas together.
|
||||
switch (crre.getCircularCornerFlags()) {
|
||||
case CircularRRectEffect::kAll_CornerFlags:
|
||||
fragBuilder->codeAppendf("float2 dxy0 = %s.xy - sk_FragCoord.xy;", rectName);
|
||||
fragBuilder->codeAppendf("float2 dxy1 = sk_FragCoord.xy - %s.zw;", rectName);
|
||||
fragBuilder->codeAppend("float2 dxy = max(max(dxy0, dxy1), 0.0);");
|
||||
fragBuilder->codeAppendf("float alpha = %s;", clampedCircleDistance.c_str());
|
||||
fragBuilder->codeAppendf("half2 dxy0 = %s.xy - sk_FragCoord.xy;", rectName);
|
||||
fragBuilder->codeAppendf("half2 dxy1 = sk_FragCoord.xy - %s.zw;", rectName);
|
||||
fragBuilder->codeAppend("half2 dxy = max(max(dxy0, dxy1), 0.0);");
|
||||
fragBuilder->codeAppendf("half alpha = %s;", clampedCircleDistance.c_str());
|
||||
break;
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
fragBuilder->codeAppendf("float alpha = bottomAlpha * rightAlpha * %s;",
|
||||
fragBuilder->codeAppendf("half alpha = bottomAlpha * rightAlpha * %s;",
|
||||
clampedCircleDistance.c_str());
|
||||
break;
|
||||
case CircularRRectEffect::kTopRight_CornerFlag:
|
||||
fragBuilder->codeAppendf("float2 dxy = max(float2(sk_FragCoord.x - %s.z, "
|
||||
"%s.y - sk_FragCoord.y), 0.0);",
|
||||
fragBuilder->codeAppendf("half2 dxy = max(half2(sk_FragCoord.x - %s.z, "
|
||||
"%s.y - sk_FragCoord.y), 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);
|
||||
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);
|
||||
fragBuilder->codeAppendf("float alpha = bottomAlpha * leftAlpha * %s;",
|
||||
fragBuilder->codeAppendf("half alpha = bottomAlpha * leftAlpha * %s;",
|
||||
clampedCircleDistance.c_str());
|
||||
break;
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
fragBuilder->codeAppendf("float alpha = topAlpha * leftAlpha * %s;",
|
||||
fragBuilder->codeAppendf("half alpha = topAlpha * leftAlpha * %s;",
|
||||
clampedCircleDistance.c_str());
|
||||
break;
|
||||
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);",
|
||||
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);
|
||||
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);
|
||||
fragBuilder->codeAppendf("float alpha = topAlpha * rightAlpha * %s;",
|
||||
fragBuilder->codeAppendf("half alpha = topAlpha * rightAlpha * %s;",
|
||||
clampedCircleDistance.c_str());
|
||||
break;
|
||||
case CircularRRectEffect::kLeft_CornerFlags:
|
||||
fragBuilder->codeAppendf("float2 dxy0 = %s.xy - sk_FragCoord.xy;", rectName);
|
||||
fragBuilder->codeAppendf("float dy1 = sk_FragCoord.y - %s.w;", rectName);
|
||||
fragBuilder->codeAppend("float2 dxy = max(float2(dxy0.x, max(dxy0.y, dy1)), 0.0);");
|
||||
fragBuilder->codeAppendf("float rightAlpha = clamp(%s.z - sk_FragCoord.x, 0.0, 1.0);",
|
||||
fragBuilder->codeAppendf("half2 dxy0 = %s.xy - sk_FragCoord.xy;", rectName);
|
||||
fragBuilder->codeAppendf("half dy1 = sk_FragCoord.y - %s.w;", rectName);
|
||||
fragBuilder->codeAppend("half2 dxy = max(half2(dxy0.x, max(dxy0.y, dy1)), 0.0);");
|
||||
fragBuilder->codeAppendf("half rightAlpha = clamp(%s.z - sk_FragCoord.x, 0.0, 1.0);",
|
||||
rectName);
|
||||
fragBuilder->codeAppendf("float alpha = rightAlpha * %s;",
|
||||
fragBuilder->codeAppendf("half alpha = rightAlpha * %s;",
|
||||
clampedCircleDistance.c_str());
|
||||
break;
|
||||
case CircularRRectEffect::kTop_CornerFlags:
|
||||
fragBuilder->codeAppendf("float2 dxy0 = %s.xy - sk_FragCoord.xy;", rectName);
|
||||
fragBuilder->codeAppendf("float dx1 = sk_FragCoord.x - %s.z;", rectName);
|
||||
fragBuilder->codeAppend("float2 dxy = max(float2(max(dxy0.x, dx1), dxy0.y), 0.0);");
|
||||
fragBuilder->codeAppendf("float bottomAlpha = clamp(%s.w - sk_FragCoord.y, 0.0, 1.0);",
|
||||
fragBuilder->codeAppendf("half2 dxy0 = %s.xy - sk_FragCoord.xy;", rectName);
|
||||
fragBuilder->codeAppendf("half dx1 = sk_FragCoord.x - %s.z;", rectName);
|
||||
fragBuilder->codeAppend("half2 dxy = max(half2(max(dxy0.x, dx1), dxy0.y), 0.0);");
|
||||
fragBuilder->codeAppendf("half bottomAlpha = clamp(%s.w - sk_FragCoord.y, 0.0, 1.0);",
|
||||
rectName);
|
||||
fragBuilder->codeAppendf("float alpha = bottomAlpha * %s;",
|
||||
fragBuilder->codeAppendf("half alpha = bottomAlpha * %s;",
|
||||
clampedCircleDistance.c_str());
|
||||
break;
|
||||
case CircularRRectEffect::kRight_CornerFlags:
|
||||
fragBuilder->codeAppendf("float dy0 = %s.y - sk_FragCoord.y;", rectName);
|
||||
fragBuilder->codeAppendf("float2 dxy1 = sk_FragCoord.xy - %s.zw;", rectName);
|
||||
fragBuilder->codeAppend("float2 dxy = max(float2(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 dy0 = %s.y - sk_FragCoord.y;", rectName);
|
||||
fragBuilder->codeAppendf("half2 dxy1 = sk_FragCoord.xy - %s.zw;", rectName);
|
||||
fragBuilder->codeAppend("half2 dxy = max(half2(dxy1.x, max(dy0, dxy1.y)), 0.0);");
|
||||
fragBuilder->codeAppendf("half leftAlpha = clamp(sk_FragCoord.x - %s.x, 0.0, 1.0);",
|
||||
rectName);
|
||||
fragBuilder->codeAppendf("float alpha = leftAlpha * %s;",
|
||||
fragBuilder->codeAppendf("half alpha = leftAlpha * %s;",
|
||||
clampedCircleDistance.c_str());
|
||||
break;
|
||||
case CircularRRectEffect::kBottom_CornerFlags:
|
||||
fragBuilder->codeAppendf("float dx0 = %s.x - sk_FragCoord.x;", rectName);
|
||||
fragBuilder->codeAppendf("float2 dxy1 = sk_FragCoord.xy - %s.zw;", rectName);
|
||||
fragBuilder->codeAppend("float2 dxy = max(float2(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 dx0 = %s.x - sk_FragCoord.x;", rectName);
|
||||
fragBuilder->codeAppendf("half2 dxy1 = sk_FragCoord.xy - %s.zw;", rectName);
|
||||
fragBuilder->codeAppend("half2 dxy = max(half2(max(dx0, dxy1.x), dxy1.y), 0.0);");
|
||||
fragBuilder->codeAppendf("half topAlpha = clamp(sk_FragCoord.y - %s.y, 0.0, 1.0);",
|
||||
rectName);
|
||||
fragBuilder->codeAppendf("float alpha = topAlpha * %s;",
|
||||
fragBuilder->codeAppendf("half alpha = topAlpha * %s;",
|
||||
clampedCircleDistance.c_str());
|
||||
break;
|
||||
}
|
||||
@ -514,10 +510,8 @@ void GLEllipticalRRectEffect::emitCode(EmitArgs& args) {
|
||||
GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
|
||||
const char *rectName;
|
||||
// The inner rect is the rrect bounds inset by the x/y radii
|
||||
fInnerRectUniform = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kVec4f_GrSLType, kDefault_GrSLPrecision,
|
||||
"innerRect",
|
||||
&rectName);
|
||||
fInnerRectUniform = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType,
|
||||
"innerRect", &rectName);
|
||||
|
||||
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
|
||||
// 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
|
||||
// components before computing distances and alpha values so that only one distance computation
|
||||
// need be computed to determine the min alpha.
|
||||
fragBuilder->codeAppendf("float2 dxy0 = %s.xy - sk_FragCoord.xy;", rectName);
|
||||
fragBuilder->codeAppendf("float2 dxy1 = sk_FragCoord.xy - %s.zw;", rectName);
|
||||
fragBuilder->codeAppendf("half2 dxy0 = %s.xy - sk_FragCoord.xy;", 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
|
||||
// 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.
|
||||
const char* scaleName = nullptr;
|
||||
if (args.fShaderCaps->floatPrecisionVaries()) {
|
||||
fScaleUniform = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kVec2f_GrSLType, kDefault_GrSLPrecision,
|
||||
"scale", &scaleName);
|
||||
fScaleUniform = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType, "scale",
|
||||
&scaleName);
|
||||
}
|
||||
|
||||
// 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: {
|
||||
const char *invRadiiXYSqdName;
|
||||
fInvRadiiSqdUniform = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kVec2f_GrSLType,
|
||||
kDefault_GrSLPrecision,
|
||||
kHalf2_GrSLType,
|
||||
"invRadiiXY",
|
||||
&invRadiiXYSqdName);
|
||||
fragBuilder->codeAppend("float2 dxy = max(max(dxy0, dxy1), 0.0);");
|
||||
fragBuilder->codeAppend("half2 dxy = max(max(dxy0, dxy1), 0.0);");
|
||||
if (scaleName) {
|
||||
fragBuilder->codeAppendf("dxy *= %s.y;", scaleName);
|
||||
}
|
||||
// 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;
|
||||
}
|
||||
case SkRRect::kNinePatch_Type: {
|
||||
const char *invRadiiLTRBSqdName;
|
||||
fInvRadiiSqdUniform = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kVec4f_GrSLType,
|
||||
kDefault_GrSLPrecision,
|
||||
kHalf4_GrSLType,
|
||||
"invRadiiLTRB",
|
||||
&invRadiiLTRBSqdName);
|
||||
if (scaleName) {
|
||||
fragBuilder->codeAppendf("dxy0 *= %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
|
||||
// corner where both the x and y offsets are positive, hence the maxes. (The inverse
|
||||
// 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);
|
||||
|
||||
break;
|
||||
@ -586,20 +577,20 @@ void GLEllipticalRRectEffect::emitCode(EmitArgs& args) {
|
||||
SK_ABORT("RRect should always be simple or nine-patch.");
|
||||
}
|
||||
// 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.
|
||||
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.
|
||||
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) {
|
||||
fragBuilder->codeAppendf("approx_dist *= %s.x;", scaleName);
|
||||
}
|
||||
|
||||
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 {
|
||||
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);
|
||||
|
@ -20,11 +20,11 @@ public:
|
||||
|
||||
SkString srgbFuncName;
|
||||
static const GrShaderVar gSrgbArgs[] = {
|
||||
GrShaderVar("x", kFloat_GrSLType),
|
||||
GrShaderVar("x", kHalf_GrSLType),
|
||||
};
|
||||
switch (srgbe.mode()) {
|
||||
case GrSRGBEffect::Mode::kLinearToSRGB:
|
||||
fragBuilder->emitFunction(kFloat_GrSLType,
|
||||
fragBuilder->emitFunction(kHalf_GrSLType,
|
||||
"linear_to_srgb",
|
||||
SK_ARRAY_COUNT(gSrgbArgs),
|
||||
gSrgbArgs,
|
||||
@ -33,7 +33,7 @@ public:
|
||||
&srgbFuncName);
|
||||
break;
|
||||
case GrSRGBEffect::Mode::kSRGBToLinear:
|
||||
fragBuilder->emitFunction(kFloat_GrSLType,
|
||||
fragBuilder->emitFunction(kHalf_GrSLType,
|
||||
"srgb_to_linear",
|
||||
SK_ARRAY_COUNT(gSrgbArgs),
|
||||
gSrgbArgs,
|
||||
@ -44,20 +44,20 @@ public:
|
||||
}
|
||||
|
||||
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) {
|
||||
fragBuilder->codeAppendf("float nonZeroAlpha = max(color.a, 0.00001);");
|
||||
fragBuilder->codeAppendf("color = float4(color.rgb / nonZeroAlpha, color.a);");
|
||||
fragBuilder->codeAppendf("half nonZeroAlpha = max(color.a, 0.00001);");
|
||||
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());
|
||||
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);
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ public:
|
||||
|
||||
// emit attributes
|
||||
varyingHandler->emitAttributes(rsgp);
|
||||
fragBuilder->codeAppend("float4 shadowParams;");
|
||||
fragBuilder->codeAppend("half4 shadowParams;");
|
||||
varyingHandler->addPassThroughAttribute(rsgp.inShadowParams(), "shadowParams");
|
||||
|
||||
// setup pass through color
|
||||
@ -43,12 +43,12 @@ public:
|
||||
rsgp.inPosition()->fName,
|
||||
args.fFPCoordTransformHandler);
|
||||
|
||||
fragBuilder->codeAppend("float d = length(shadowParams.xy);");
|
||||
fragBuilder->codeAppend("float distance = shadowParams.z * (1.0 - d);");
|
||||
fragBuilder->codeAppend("half d = length(shadowParams.xy);");
|
||||
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->codeAppendf("%s = float4(factor);",
|
||||
fragBuilder->codeAppendf("%s = half4(factor);",
|
||||
args.fOutputCoverage);
|
||||
}
|
||||
|
||||
|
@ -26,15 +26,15 @@ public:
|
||||
fColorSpaceHelper.emitCode(args.fUniformHandler, _outer.colorXform().get());
|
||||
SkString sk_TransformedCoords2D_0 = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
|
||||
fragBuilder->codeAppendf(
|
||||
"float4 _tmpVar1;%s = %s * %stexture(%s, %s).%s%s;\n", args.fOutputColor,
|
||||
args.fInputColor ? args.fInputColor : "float4(1)",
|
||||
"half4 _tmpVar1;%s = %s * %stexture(%s, %s).%s%s;\n", args.fOutputColor,
|
||||
args.fInputColor ? args.fInputColor : "half4(1)",
|
||||
fColorSpaceHelper.isValid() ? "(_tmpVar1 = " : "",
|
||||
fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]).c_str(),
|
||||
sk_TransformedCoords2D_0.c_str(),
|
||||
fragBuilder->getProgramBuilder()->samplerSwizzle(args.fTexSamplers[0]).c_str(),
|
||||
fColorSpaceHelper.isValid()
|
||||
? SkStringPrintf(", float4(clamp((%s * float4(_tmpVar1.rgb, 1.0)).rgb, "
|
||||
"0.0, _tmpVar1.a), _tmpVar1.a))",
|
||||
? SkStringPrintf(", half4(clamp((%s * half4(_tmpVar1.rgb, 1.0)).rgb, 0.0, "
|
||||
"_tmpVar1.a), _tmpVar1.a))",
|
||||
args.fUniformHandler->getUniformCStr(
|
||||
fColorSpaceHelper.gamutXformUniform()))
|
||||
.c_str()
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
in uniform sampler2D image;
|
||||
in uniform colorSpaceXform colorXform;
|
||||
in float4x4 matrix;
|
||||
in half4x4 matrix;
|
||||
|
||||
@constructorParams {
|
||||
GrSamplerState samplerParams
|
||||
|
@ -78,8 +78,7 @@ void GrTextureDomain::GLDomain::sampleTexture(GrGLSLShaderBuilder* builder,
|
||||
if (textureDomain.fIndex >= 0) {
|
||||
uniName.appendS32(textureDomain.fIndex);
|
||||
}
|
||||
fDomainUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kVec4f_GrSLType, kDefault_GrSLPrecision,
|
||||
fDomainUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType,
|
||||
uniName.c_str(), &name);
|
||||
fDomainName = name;
|
||||
}
|
||||
@ -88,7 +87,7 @@ void GrTextureDomain::GLDomain::sampleTexture(GrGLSLShaderBuilder* builder,
|
||||
case kIgnore_Mode: {
|
||||
builder->codeAppendf("%s = ", outColor);
|
||||
builder->appendTextureLookupAndModulate(inModulateColor, sampler, inCoords.c_str(),
|
||||
kVec2f_GrSLType, colorXformHelper);
|
||||
kHighFloat2_GrSLType, colorXformHelper);
|
||||
builder->codeAppend(";");
|
||||
break;
|
||||
}
|
||||
@ -99,7 +98,7 @@ void GrTextureDomain::GLDomain::sampleTexture(GrGLSLShaderBuilder* builder,
|
||||
|
||||
builder->codeAppendf("%s = ", outColor);
|
||||
builder->appendTextureLookupAndModulate(inModulateColor, sampler, clampedCoords.c_str(),
|
||||
kVec2f_GrSLType, colorXformHelper);
|
||||
kHighFloat2_GrSLType, colorXformHelper);
|
||||
builder->codeAppend(";");
|
||||
break;
|
||||
}
|
||||
@ -115,20 +114,20 @@ void GrTextureDomain::GLDomain::sampleTexture(GrGLSLShaderBuilder* builder,
|
||||
// may return undefined results". This appears to be an issue with
|
||||
// the 'any' call since even the simple "result=black; if (any())
|
||||
// result=white;" code fails to compile.
|
||||
builder->codeAppend("float4 outside = float4(0.0, 0.0, 0.0, 0.0);");
|
||||
builder->codeAppend("float4 inside = ");
|
||||
builder->codeAppend("half4 outside = half4(0.0, 0.0, 0.0, 0.0);");
|
||||
builder->codeAppend("half4 inside = ");
|
||||
builder->appendTextureLookupAndModulate(inModulateColor, sampler, inCoords.c_str(),
|
||||
kVec2f_GrSLType, colorXformHelper);
|
||||
kHighFloat2_GrSLType, colorXformHelper);
|
||||
builder->codeAppend(";");
|
||||
|
||||
builder->codeAppendf("highp float x = (%s).x;", inCoords.c_str());
|
||||
builder->codeAppendf("highp float y = (%s).y;", inCoords.c_str());
|
||||
builder->codeAppendf("highfloat x = (%s).x;", 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);",
|
||||
domain, domain, domain);
|
||||
builder->codeAppendf("y = abs(2.0*(y - %s.y)/(%s.w - %s.y) - 1.0);",
|
||||
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);
|
||||
} else {
|
||||
builder->codeAppend("bool4 outside;\n");
|
||||
@ -136,10 +135,10 @@ void GrTextureDomain::GLDomain::sampleTexture(GrGLSLShaderBuilder* builder,
|
||||
domain);
|
||||
builder->codeAppendf("outside.zw = greaterThan(%s, %s.zw);", inCoords.c_str(),
|
||||
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);
|
||||
builder->appendTextureLookupAndModulate(inModulateColor, sampler, inCoords.c_str(),
|
||||
kVec2f_GrSLType, colorXformHelper);
|
||||
kHighFloat2_GrSLType, colorXformHelper);
|
||||
builder->codeAppend(";");
|
||||
}
|
||||
break;
|
||||
@ -152,7 +151,7 @@ void GrTextureDomain::GLDomain::sampleTexture(GrGLSLShaderBuilder* builder,
|
||||
|
||||
builder->codeAppendf("%s = ", outColor);
|
||||
builder->appendTextureLookupAndModulate(inModulateColor, sampler, clampedCoords.c_str(),
|
||||
kVec2f_GrSLType, colorXformHelper);
|
||||
kHighFloat2_GrSLType, colorXformHelper);
|
||||
builder->codeAppend(";");
|
||||
break;
|
||||
}
|
||||
@ -377,11 +376,10 @@ GrGLSLFragmentProcessor* GrDeviceSpaceTextureDecalFragmentProcessor::onCreateGLS
|
||||
args.fFp.cast<GrDeviceSpaceTextureDecalFragmentProcessor>();
|
||||
const char* scaleAndTranslateName;
|
||||
fScaleAndTranslateUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kVec4f_GrSLType,
|
||||
kDefault_GrSLPrecision,
|
||||
kHalf4_GrSLType,
|
||||
"scaleAndTranslate",
|
||||
&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);
|
||||
fGLDomain.sampleTexture(args.fFragBuilder,
|
||||
args.fUniformHandler,
|
||||
|
@ -23,7 +23,7 @@ struct SkRect;
|
||||
|
||||
/**
|
||||
* 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
|
||||
* 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
|
||||
* 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.
|
||||
* 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
|
||||
|
@ -217,7 +217,7 @@ void GLComposeTwoFragmentProcessor::emitCode(EmitArgs& args) {
|
||||
const char* inputColor = nullptr;
|
||||
if (args.fInputColor) {
|
||||
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
|
||||
@ -452,7 +452,7 @@ public:
|
||||
const char* inputColor = args.fInputColor;
|
||||
// We don't try to optimize for this case at all
|
||||
if (!inputColor) {
|
||||
fragBuilder->codeAppendf("const float4 ones = float4(1);");
|
||||
fragBuilder->codeAppendf("const half4 ones = half4(1);");
|
||||
inputColor = "ones";
|
||||
}
|
||||
|
||||
|
@ -89,10 +89,9 @@ public:
|
||||
const YUVtoRGBEffect& effect = args.fFp.cast<YUVtoRGBEffect>();
|
||||
|
||||
const char* colorSpaceMatrix = nullptr;
|
||||
fMatrixUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kMat44f_GrSLType, kDefault_GrSLPrecision,
|
||||
fMatrixUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4x4_GrSLType,
|
||||
"ColorSpaceMatrix", &colorSpaceMatrix);
|
||||
fragBuilder->codeAppendf("%s = float4(", args.fOutputColor);
|
||||
fragBuilder->codeAppendf("%s = half4(", args.fOutputColor);
|
||||
fragBuilder->appendTextureLookup(args.fTexSamplers[0],
|
||||
args.fTransformedCoords[0].c_str(),
|
||||
args.fTransformedCoords[0].getType());
|
||||
|
@ -3474,13 +3474,13 @@ bool GrGLGpu::createCopyProgram(GrTexture* srcTex) {
|
||||
}
|
||||
|
||||
const char* version = shaderCaps->versionDeclString();
|
||||
GrShaderVar aVertex("a_vertex", kVec2f_GrSLType, GrShaderVar::kIn_TypeModifier);
|
||||
GrShaderVar uTexCoordXform("u_texCoordXform", kVec4f_GrSLType,
|
||||
GrShaderVar aVertex("a_vertex", kHalf2_GrSLType, GrShaderVar::kIn_TypeModifier);
|
||||
GrShaderVar uTexCoordXform("u_texCoordXform", kHalf4_GrSLType,
|
||||
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 vTexCoord("v_texCoord", kVec2f_GrSLType, GrShaderVar::kOut_TypeModifier);
|
||||
GrShaderVar oFragColor("o_FragColor", kVec4f_GrSLType, GrShaderVar::kOut_TypeModifier);
|
||||
GrShaderVar vTexCoord("v_texCoord", kHalf2_GrSLType, GrShaderVar::kOut_TypeModifier);
|
||||
GrShaderVar oFragColor("o_FragColor", kHalf4_GrSLType, GrShaderVar::kOut_TypeModifier);
|
||||
|
||||
SkString vshaderTxt(version);
|
||||
if (shaderCaps->noperspectiveInterpolationSupport()) {
|
||||
@ -3504,7 +3504,7 @@ bool GrGLGpu::createCopyProgram(GrTexture* srcTex) {
|
||||
"void main() {"
|
||||
" v_texCoord = a_vertex.xy * u_texCoordXform.xy + u_texCoordXform.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",
|
||||
shaderCaps->externalTextureExtensionString());
|
||||
}
|
||||
GrGLSLAppendDefaultFloatPrecisionDeclaration(kMedium_GrSLPrecision, *shaderCaps,
|
||||
&fshaderTxt);
|
||||
vTexCoord.setTypeModifier(GrShaderVar::kIn_TypeModifier);
|
||||
vTexCoord.appendDecl(shaderCaps, &fshaderTxt);
|
||||
fshaderTxt.append(";");
|
||||
@ -3583,19 +3581,19 @@ bool GrGLGpu::createMipmapProgram(int progIdx) {
|
||||
}
|
||||
|
||||
const char* version = shaderCaps->versionDeclString();
|
||||
GrShaderVar aVertex("a_vertex", kVec2f_GrSLType, GrShaderVar::kIn_TypeModifier);
|
||||
GrShaderVar uTexCoordXform("u_texCoordXform", kVec4f_GrSLType,
|
||||
GrShaderVar aVertex("a_vertex", kHalf2_GrSLType, GrShaderVar::kIn_TypeModifier);
|
||||
GrShaderVar uTexCoordXform("u_texCoordXform", kHalf4_GrSLType,
|
||||
GrShaderVar::kUniform_TypeModifier);
|
||||
GrShaderVar uTexture("u_texture", kTexture2DSampler_GrSLType,
|
||||
GrShaderVar::kUniform_TypeModifier);
|
||||
// We need 1, 2, or 4 texture coordinates (depending on parity of each dimension):
|
||||
GrShaderVar vTexCoords[] = {
|
||||
GrShaderVar("v_texCoord0", kVec2f_GrSLType, GrShaderVar::kOut_TypeModifier),
|
||||
GrShaderVar("v_texCoord1", kVec2f_GrSLType, GrShaderVar::kOut_TypeModifier),
|
||||
GrShaderVar("v_texCoord2", kVec2f_GrSLType, GrShaderVar::kOut_TypeModifier),
|
||||
GrShaderVar("v_texCoord3", kVec2f_GrSLType, GrShaderVar::kOut_TypeModifier),
|
||||
GrShaderVar("v_texCoord0", kHalf2_GrSLType, GrShaderVar::kOut_TypeModifier),
|
||||
GrShaderVar("v_texCoord1", kHalf2_GrSLType, GrShaderVar::kOut_TypeModifier),
|
||||
GrShaderVar("v_texCoord2", kHalf2_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);
|
||||
if (shaderCaps->noperspectiveInterpolationSupport()) {
|
||||
@ -3620,27 +3618,27 @@ bool GrGLGpu::createMipmapProgram(int progIdx) {
|
||||
vshaderTxt.append(
|
||||
"// Mipmap Program VS\n"
|
||||
"void main() {"
|
||||
" gl_Position.xy = a_vertex * float2(2, 2) - float2(1, 1);"
|
||||
" gl_Position.zw = float2(0, 1);"
|
||||
" gl_Position.xy = a_vertex * half2(2, 2) - half2(1, 1);"
|
||||
" gl_Position.zw = half2(0, 1);"
|
||||
);
|
||||
|
||||
// Insert texture coordinate computation:
|
||||
if (oddWidth && oddHeight) {
|
||||
vshaderTxt.append(
|
||||
" v_texCoord0 = a_vertex.xy * u_texCoordXform.yw;"
|
||||
" v_texCoord1 = a_vertex.xy * u_texCoordXform.yw + float2(u_texCoordXform.x, 0);"
|
||||
" v_texCoord2 = a_vertex.xy * u_texCoordXform.yw + float2(0, u_texCoordXform.z);"
|
||||
" v_texCoord1 = a_vertex.xy * u_texCoordXform.yw + half2(u_texCoordXform.x, 0);"
|
||||
" v_texCoord2 = a_vertex.xy * u_texCoordXform.yw + half2(0, u_texCoordXform.z);"
|
||||
" v_texCoord3 = a_vertex.xy * u_texCoordXform.yw + u_texCoordXform.xz;"
|
||||
);
|
||||
} else if (oddWidth) {
|
||||
vshaderTxt.append(
|
||||
" v_texCoord0 = a_vertex.xy * float2(u_texCoordXform.y, 1);"
|
||||
" v_texCoord1 = a_vertex.xy * float2(u_texCoordXform.y, 1) + float2(u_texCoordXform.x, 0);"
|
||||
" v_texCoord0 = a_vertex.xy * half2(u_texCoordXform.y, 1);"
|
||||
" v_texCoord1 = a_vertex.xy * half2(u_texCoordXform.y, 1) + half2(u_texCoordXform.x, 0);"
|
||||
);
|
||||
} else if (oddHeight) {
|
||||
vshaderTxt.append(
|
||||
" v_texCoord0 = a_vertex.xy * float2(1, u_texCoordXform.w);"
|
||||
" v_texCoord1 = a_vertex.xy * float2(1, u_texCoordXform.w) + float2(0, u_texCoordXform.z);"
|
||||
" v_texCoord0 = a_vertex.xy * half2(1, u_texCoordXform.w);"
|
||||
" v_texCoord1 = a_vertex.xy * half2(1, u_texCoordXform.w) + half2(0, u_texCoordXform.z);"
|
||||
);
|
||||
} else {
|
||||
vshaderTxt.append(
|
||||
@ -3656,8 +3654,6 @@ bool GrGLGpu::createMipmapProgram(int progIdx) {
|
||||
fshaderTxt.appendf("#extension %s : require\n", extension);
|
||||
}
|
||||
}
|
||||
GrGLSLAppendDefaultFloatPrecisionDeclaration(kMedium_GrSLPrecision, *shaderCaps,
|
||||
&fshaderTxt);
|
||||
for (int i = 0; i < numTaps; ++i) {
|
||||
vTexCoords[i].setTypeModifier(GrShaderVar::kIn_TypeModifier);
|
||||
vTexCoords[i].appendDecl(shaderCaps, &fshaderTxt);
|
||||
@ -3743,7 +3739,7 @@ bool GrGLGpu::createStencilClipClearProgram() {
|
||||
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();
|
||||
|
||||
SkString vshaderTxt(version);
|
||||
@ -3752,17 +3748,14 @@ bool GrGLGpu::createStencilClipClearProgram() {
|
||||
vshaderTxt.append(
|
||||
"// Stencil Clip Clear Program VS\n"
|
||||
"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);
|
||||
GrGLSLAppendDefaultFloatPrecisionDeclaration(kMedium_GrSLPrecision,
|
||||
*this->caps()->shaderCaps(),
|
||||
&fshaderTxt);
|
||||
fshaderTxt.appendf(
|
||||
"// Stencil Clip Clear Program FS\n"
|
||||
"void main() {"
|
||||
" sk_FragColor = float4(0);"
|
||||
" sk_FragColor = half4(0);"
|
||||
"}");
|
||||
|
||||
const char* str;
|
||||
|
@ -73,7 +73,7 @@ void GrGLProgramDataManager::setImageStorages(const UniformInfoArray& images) co
|
||||
|
||||
void GrGLProgramDataManager::set1i(UniformHandle u, int32_t i) const {
|
||||
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);
|
||||
if (kUnusedUniform != uni.fLocation) {
|
||||
GR_GL_CALL(fGpu->glInterface(), Uniform1i(uni.fLocation, i));
|
||||
@ -84,7 +84,7 @@ void GrGLProgramDataManager::set1iv(UniformHandle u,
|
||||
int arrayCount,
|
||||
const int v[]) const {
|
||||
const Uniform& uni = fUniforms[u.toIndex()];
|
||||
SkASSERT(uni.fType == kInt_GrSLType);
|
||||
SkASSERT(uni.fType == kInt_GrSLType || uni.fType == kShort_GrSLType);
|
||||
SkASSERT(arrayCount > 0);
|
||||
ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount);
|
||||
if (kUnusedUniform != uni.fLocation) {
|
||||
@ -94,7 +94,7 @@ void GrGLProgramDataManager::set1iv(UniformHandle u,
|
||||
|
||||
void GrGLProgramDataManager::set1f(UniformHandle u, float v0) const {
|
||||
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);
|
||||
if (kUnusedUniform != uni.fLocation) {
|
||||
GR_GL_CALL(fGpu->glInterface(), Uniform1f(uni.fLocation, v0));
|
||||
@ -105,7 +105,7 @@ void GrGLProgramDataManager::set1fv(UniformHandle u,
|
||||
int arrayCount,
|
||||
const float v[]) const {
|
||||
const Uniform& uni = fUniforms[u.toIndex()];
|
||||
SkASSERT(uni.fType == kFloat_GrSLType);
|
||||
SkASSERT(uni.fType == kHighFloat_GrSLType || uni.fType == kHalf_GrSLType);
|
||||
SkASSERT(arrayCount > 0);
|
||||
ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount);
|
||||
// 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 {
|
||||
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);
|
||||
if (kUnusedUniform != uni.fLocation) {
|
||||
GR_GL_CALL(fGpu->glInterface(), Uniform2f(uni.fLocation, v0, v1));
|
||||
@ -130,7 +130,7 @@ void GrGLProgramDataManager::set2fv(UniformHandle u,
|
||||
int arrayCount,
|
||||
const float v[]) const {
|
||||
const Uniform& uni = fUniforms[u.toIndex()];
|
||||
SkASSERT(uni.fType == kVec2f_GrSLType);
|
||||
SkASSERT(uni.fType == kHighFloat2_GrSLType || uni.fType == kHalf2_GrSLType);
|
||||
SkASSERT(arrayCount > 0);
|
||||
ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount);
|
||||
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 {
|
||||
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);
|
||||
if (kUnusedUniform != uni.fLocation) {
|
||||
GR_GL_CALL(fGpu->glInterface(), Uniform3f(uni.fLocation, v0, v1, v2));
|
||||
@ -151,7 +151,7 @@ void GrGLProgramDataManager::set3fv(UniformHandle u,
|
||||
int arrayCount,
|
||||
const float v[]) const {
|
||||
const Uniform& uni = fUniforms[u.toIndex()];
|
||||
SkASSERT(uni.fType == kVec3f_GrSLType);
|
||||
SkASSERT(uni.fType == kHighFloat3_GrSLType || uni.fType == kHalf3_GrSLType);
|
||||
SkASSERT(arrayCount > 0);
|
||||
ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount);
|
||||
if (kUnusedUniform != uni.fLocation) {
|
||||
@ -165,7 +165,7 @@ void GrGLProgramDataManager::set4f(UniformHandle u,
|
||||
float v2,
|
||||
float v3) const {
|
||||
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);
|
||||
if (kUnusedUniform != uni.fLocation) {
|
||||
GR_GL_CALL(fGpu->glInterface(), Uniform4f(uni.fLocation, v0, v1, v2, v3));
|
||||
@ -176,7 +176,7 @@ void GrGLProgramDataManager::set4fv(UniformHandle u,
|
||||
int arrayCount,
|
||||
const float v[]) const {
|
||||
const Uniform& uni = fUniforms[u.toIndex()];
|
||||
SkASSERT(uni.fType == kVec4f_GrSLType);
|
||||
SkASSERT(uni.fType == kHighFloat4_GrSLType || uni.fType == kHalf4_GrSLType);
|
||||
SkASSERT(arrayCount > 0);
|
||||
ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount);
|
||||
if (kUnusedUniform != uni.fLocation) {
|
||||
@ -214,7 +214,8 @@ template<int N> inline void GrGLProgramDataManager::setMatrices(UniformHandle u,
|
||||
int arrayCount,
|
||||
const float matrices[]) const {
|
||||
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);
|
||||
ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount);
|
||||
if (kUnusedUniform != uni.fLocation) {
|
||||
@ -246,8 +247,10 @@ void GrGLProgramDataManager::setPathFragmentInputTransform(VaryingHandle u,
|
||||
SkASSERT(fGpu->glCaps().shaderCaps()->pathRenderingSupport());
|
||||
const PathProcVarying& fragmentInput = fPathProcVaryings[u.toIndex()];
|
||||
|
||||
SkASSERT((components == 2 && fragmentInput.fType == kVec2f_GrSLType) ||
|
||||
(components == 3 && fragmentInput.fType == kVec3f_GrSLType));
|
||||
SkASSERT((components == 2 && (fragmentInput.fType == kHighFloat2_GrSLType ||
|
||||
fragmentInput.fType == kHalf2_GrSLType)) ||
|
||||
(components == 3 && (fragmentInput.fType == kHighFloat3_GrSLType ||
|
||||
fragmentInput.fType == kHalf3_GrSLType)));
|
||||
|
||||
fGpu->glPathRendering()->setProgramPathFragmentInputTransform(fProgramID,
|
||||
fragmentInput.fLocation,
|
||||
|
@ -24,7 +24,7 @@ GrGLSLUniformHandler::UniformHandle GrGLUniformHandler::internalAddUniformArray(
|
||||
const char** outName) {
|
||||
SkASSERT(name && strlen(name));
|
||||
SkASSERT(0 != visibility);
|
||||
SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeAcceptsPrecision(type));
|
||||
SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeTemporarilyAcceptsPrecision(type));
|
||||
|
||||
UniformInfo& uni = fUniforms.push_back();
|
||||
uni.fVariable.setType(type);
|
||||
|
@ -139,6 +139,9 @@ GrGLProgram* GrGLProgramBuilder::finalize() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (fFS.fForceHighPrecision) {
|
||||
settings.fForceHighPrecision = true;
|
||||
}
|
||||
if (!this->compileAndAttachShaders(fFS, programID, GR_GL_FRAGMENT_SHADER, &shadersToDelete,
|
||||
settings, &inputs)) {
|
||||
this->cleanupProgram(programID, shadersToDelete);
|
||||
|
@ -30,33 +30,47 @@ const char* GrGLSLTypeString(const GrShaderCaps* shaderCaps, GrSLType t) {
|
||||
switch (t) {
|
||||
case kVoid_GrSLType:
|
||||
return "void";
|
||||
case kFloat_GrSLType:
|
||||
return "float";
|
||||
case kVec2f_GrSLType:
|
||||
return "float2";
|
||||
case kVec3f_GrSLType:
|
||||
return "float3";
|
||||
case kVec4f_GrSLType:
|
||||
return "float4";
|
||||
case kVec2us_GrSLType:
|
||||
case kHalf_GrSLType:
|
||||
return "half";
|
||||
case kHalf2_GrSLType:
|
||||
return "half2";
|
||||
case kHalf3_GrSLType:
|
||||
return "half3";
|
||||
case kHalf4_GrSLType:
|
||||
return "half4";
|
||||
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()) {
|
||||
return "uint2";
|
||||
} else {
|
||||
// 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";
|
||||
case kVec3i_GrSLType:
|
||||
case kInt3_GrSLType:
|
||||
return "int3";
|
||||
case kVec4i_GrSLType:
|
||||
case kInt4_GrSLType:
|
||||
return "int4";
|
||||
case kMat22f_GrSLType:
|
||||
return "float2x2";
|
||||
case kMat33f_GrSLType:
|
||||
return "float3x3";
|
||||
case kMat44f_GrSLType:
|
||||
return "float4x4";
|
||||
case kHighFloat2x2_GrSLType:
|
||||
return "highfloat2x2";
|
||||
case kHighFloat3x3_GrSLType:
|
||||
return "highfloat3x3";
|
||||
case kHighFloat4x4_GrSLType:
|
||||
return "highfloat4x4";
|
||||
case kHalf2x2_GrSLType:
|
||||
return "half2x2";
|
||||
case kHalf3x3_GrSLType:
|
||||
return "half3x3";
|
||||
case kHalf4x4_GrSLType:
|
||||
return "half4x4";
|
||||
case kTexture2DSampler_GrSLType:
|
||||
return "sampler2D";
|
||||
case kITexture2DSampler_GrSLType:
|
||||
@ -73,6 +87,10 @@ const char* GrGLSLTypeString(const GrShaderCaps* shaderCaps, GrSLType t) {
|
||||
return "int";
|
||||
case kUint_GrSLType:
|
||||
return "uint";
|
||||
case kShort_GrSLType:
|
||||
return "short";
|
||||
case kUShort_GrSLType:
|
||||
return "ushort";
|
||||
case kTexture2D_GrSLType:
|
||||
return "texture2D";
|
||||
case kSampler_GrSLType:
|
||||
|
@ -50,7 +50,7 @@ static void color_dodge_component(GrGLSLFragmentBuilder* fsBuilder,
|
||||
fsBuilder->codeAppendf("%s.%c = %s.%c * (1.0 - %s.a);",
|
||||
final, component, src, component, dst);
|
||||
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->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,
|
||||
@ -84,7 +84,7 @@ static void color_burn_component(GrGLSLFragmentBuilder* fsBuilder,
|
||||
fsBuilder->codeAppendf("%s.%c = %s.%c * (1.0 - %s.a);",
|
||||
final, component, dst, component, src);
|
||||
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);
|
||||
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);
|
||||
@ -114,11 +114,11 @@ static void soft_light_component_pos_dst_alpha(GrGLSLFragmentBuilder* fsBuilder,
|
||||
// else if (4D < Da)
|
||||
fsBuilder->codeAppendf("} else if (4.0 * %s.%c <= %s.a) {",
|
||||
dst, component, dst);
|
||||
fsBuilder->codeAppendf("float DSqd = %s.%c * %s.%c;",
|
||||
fsBuilder->codeAppendf("half DSqd = %s.%c * %s.%c;",
|
||||
dst, component, dst, component);
|
||||
fsBuilder->codeAppendf("float DCub = DSqd * %s.%c;", dst, component);
|
||||
fsBuilder->codeAppendf("float DaSqd = %s.a * %s.a;", dst, dst);
|
||||
fsBuilder->codeAppendf("float DaCub = DaSqd * %s.a;", dst);
|
||||
fsBuilder->codeAppendf("half DCub = DSqd * %s.%c;", dst, component);
|
||||
fsBuilder->codeAppendf("half DaSqd = %s.a * %s.a;", dst, 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
|
||||
fsBuilder->codeAppendf("%s.%c ="
|
||||
"(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.
|
||||
SkString getFunction;
|
||||
GrShaderVar getLumArgs[] = {
|
||||
GrShaderVar("color", kVec3f_GrSLType),
|
||||
GrShaderVar("color", kHalf3_GrSLType),
|
||||
};
|
||||
SkString getLumBody("return dot(float3(0.3, 0.59, 0.11), color);");
|
||||
fsBuilder->emitFunction(kFloat_GrSLType,
|
||||
SkString getLumBody("return dot(highfloat3(0.3, 0.59, 0.11), color);");
|
||||
fsBuilder->emitFunction(kHalf_GrSLType,
|
||||
"luminance",
|
||||
SK_ARRAY_COUNT(getLumArgs), getLumArgs,
|
||||
getLumBody.c_str(),
|
||||
@ -155,27 +155,27 @@ static void add_lum_function(GrGLSLFragmentBuilder* fsBuilder, SkString* setLumF
|
||||
|
||||
// Emit the set luminance function.
|
||||
GrShaderVar setLumArgs[] = {
|
||||
GrShaderVar("hueSat", kVec3f_GrSLType),
|
||||
GrShaderVar("alpha", kFloat_GrSLType),
|
||||
GrShaderVar("lumColor", kVec3f_GrSLType),
|
||||
GrShaderVar("hueSat", kHalf3_GrSLType),
|
||||
GrShaderVar("alpha", kHalf_GrSLType),
|
||||
GrShaderVar("lumColor", kHalf3_GrSLType),
|
||||
};
|
||||
SkString setLumBody;
|
||||
setLumBody.printf("float diff = %s(lumColor - hueSat);", getFunction.c_str());
|
||||
setLumBody.append("float3 outColor = hueSat + diff;");
|
||||
setLumBody.appendf("float outLum = %s(outColor);", getFunction.c_str());
|
||||
setLumBody.append("float minComp = min(min(outColor.r, outColor.g), outColor.b);"
|
||||
"float maxComp = max(max(outColor.r, outColor.g), outColor.b);"
|
||||
setLumBody.printf("half diff = %s(lumColor - hueSat);", getFunction.c_str());
|
||||
setLumBody.append("half3 outColor = hueSat + diff;");
|
||||
setLumBody.appendf("half outLum = %s(outColor);", getFunction.c_str());
|
||||
setLumBody.append("half minComp = min(min(outColor.r, outColor.g), outColor.b);"
|
||||
"half maxComp = max(max(outColor.r, outColor.g), outColor.b);"
|
||||
"if (minComp < 0.0 && outLum != minComp) {"
|
||||
"outColor = outLum + ((outColor - float3(outLum, outLum, outLum)) * outLum) /"
|
||||
"outColor = outLum + ((outColor - half3(outLum, outLum, outLum)) * outLum) /"
|
||||
"(outLum - minComp);"
|
||||
"}"
|
||||
"if (maxComp > alpha && maxComp != outLum) {"
|
||||
"outColor = outLum +"
|
||||
"((outColor - float3(outLum, outLum, outLum)) * (alpha - outLum)) /"
|
||||
"((outColor - half3(outLum, outLum, outLum)) * (alpha - outLum)) /"
|
||||
"(maxComp - outLum);"
|
||||
"}"
|
||||
"return outColor;");
|
||||
fsBuilder->emitFunction(kVec3f_GrSLType,
|
||||
fsBuilder->emitFunction(kHalf3_GrSLType,
|
||||
"set_luminance",
|
||||
SK_ARRAY_COUNT(setLumArgs), setLumArgs,
|
||||
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) {
|
||||
// Emit a helper that gets the saturation of a color
|
||||
SkString getFunction;
|
||||
GrShaderVar getSatArgs[] = { GrShaderVar("color", kVec3f_GrSLType) };
|
||||
GrShaderVar getSatArgs[] = { GrShaderVar("color", kHalf3_GrSLType) };
|
||||
SkString getSatBody;
|
||||
getSatBody.printf("return max(max(color.r, color.g), color.b) - "
|
||||
"min(min(color.r, color.g), color.b);");
|
||||
fsBuilder->emitFunction(kFloat_GrSLType,
|
||||
fsBuilder->emitFunction(kHalf_GrSLType,
|
||||
"saturation",
|
||||
SK_ARRAY_COUNT(getSatArgs), getSatArgs,
|
||||
getSatBody.c_str(),
|
||||
@ -204,33 +204,33 @@ static void add_sat_function(GrGLSLFragmentBuilder* fsBuilder, SkString* setSatF
|
||||
// adjusted min, mid, and max inputs, respectively.
|
||||
SkString helperFunction;
|
||||
GrShaderVar helperArgs[] = {
|
||||
GrShaderVar("minComp", kFloat_GrSLType),
|
||||
GrShaderVar("midComp", kFloat_GrSLType),
|
||||
GrShaderVar("maxComp", kFloat_GrSLType),
|
||||
GrShaderVar("sat", kFloat_GrSLType),
|
||||
GrShaderVar("minComp", kHalf_GrSLType),
|
||||
GrShaderVar("midComp", kHalf_GrSLType),
|
||||
GrShaderVar("maxComp", kHalf_GrSLType),
|
||||
GrShaderVar("sat", kHalf_GrSLType),
|
||||
};
|
||||
static const char kHelperBody[] = "if (minComp < maxComp) {"
|
||||
"float3 result;"
|
||||
"half3 result;"
|
||||
"result.r = 0.0;"
|
||||
"result.g = sat * (midComp - minComp) / (maxComp - minComp);"
|
||||
"result.b = sat;"
|
||||
"return result;"
|
||||
"} else {"
|
||||
"return float3(0, 0, 0);"
|
||||
"return half3(0, 0, 0);"
|
||||
"}";
|
||||
fsBuilder->emitFunction(kVec3f_GrSLType,
|
||||
fsBuilder->emitFunction(kHalf3_GrSLType,
|
||||
"set_saturation_helper",
|
||||
SK_ARRAY_COUNT(helperArgs), helperArgs,
|
||||
kHelperBody,
|
||||
&helperFunction);
|
||||
|
||||
GrShaderVar setSatArgs[] = {
|
||||
GrShaderVar("hueLumColor", kVec3f_GrSLType),
|
||||
GrShaderVar("satColor", kVec3f_GrSLType),
|
||||
GrShaderVar("hueLumColor", kHalf3_GrSLType),
|
||||
GrShaderVar("satColor", kHalf3_GrSLType),
|
||||
};
|
||||
const char* helpFunc = helperFunction.c_str();
|
||||
SkString setSatBody;
|
||||
setSatBody.appendf("float sat = %s(satColor);"
|
||||
setSatBody.appendf("half sat = %s(satColor);"
|
||||
"if (hueLumColor.r <= hueLumColor.g) {"
|
||||
"if (hueLumColor.g <= hueLumColor.b) {"
|
||||
"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;",
|
||||
getFunction.c_str(), helpFunc, helpFunc, helpFunc, helpFunc,
|
||||
helpFunc, helpFunc);
|
||||
fsBuilder->emitFunction(kVec3f_GrSLType,
|
||||
fsBuilder->emitFunction(kHalf3_GrSLType,
|
||||
"set_saturation",
|
||||
SK_ARRAY_COUNT(setSatArgs), setSatArgs,
|
||||
setSatBody.c_str(),
|
||||
@ -330,7 +330,7 @@ static void emit_advanced_xfermode_code(GrGLSLFragmentBuilder* fsBuilder, const
|
||||
SkString setSat, setLum;
|
||||
add_sat_function(fsBuilder, &setSat);
|
||||
add_lum_function(fsBuilder, &setLum);
|
||||
fsBuilder->codeAppendf("float4 dstSrcAlpha = %s * %s.a;",
|
||||
fsBuilder->codeAppendf("half4 dstSrcAlpha = %s * %s.a;",
|
||||
dstColor, srcColor);
|
||||
fsBuilder->codeAppendf("%s.rgb = %s(%s(%s.rgb * %s.a, dstSrcAlpha.rgb),"
|
||||
"dstSrcAlpha.a, dstSrcAlpha.rgb);",
|
||||
@ -345,7 +345,7 @@ static void emit_advanced_xfermode_code(GrGLSLFragmentBuilder* fsBuilder, const
|
||||
SkString setSat, setLum;
|
||||
add_sat_function(fsBuilder, &setSat);
|
||||
add_lum_function(fsBuilder, &setLum);
|
||||
fsBuilder->codeAppendf("float4 dstSrcAlpha = %s * %s.a;",
|
||||
fsBuilder->codeAppendf("half4 dstSrcAlpha = %s * %s.a;",
|
||||
dstColor, srcColor);
|
||||
fsBuilder->codeAppendf("%s.rgb = %s(%s(dstSrcAlpha.rgb, %s.rgb * %s.a),"
|
||||
"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
|
||||
SkString setLum;
|
||||
add_lum_function(fsBuilder, &setLum);
|
||||
fsBuilder->codeAppendf("float4 srcDstAlpha = %s * %s.a;",
|
||||
fsBuilder->codeAppendf("half4 srcDstAlpha = %s * %s.a;",
|
||||
srcColor, dstColor);
|
||||
fsBuilder->codeAppendf("%s.rgb = %s(srcDstAlpha.rgb, srcDstAlpha.a, %s.rgb * %s.a);",
|
||||
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
|
||||
SkString setLum;
|
||||
add_lum_function(fsBuilder, &setLum);
|
||||
fsBuilder->codeAppendf("float4 srcDstAlpha = %s * %s.a;",
|
||||
fsBuilder->codeAppendf("half4 srcDstAlpha = %s * %s.a;",
|
||||
srcColor, dstColor);
|
||||
fsBuilder->codeAppendf("%s.rgb = %s(%s.rgb * %s.a, srcDstAlpha.a, srcDstAlpha.rgb);",
|
||||
outputColor, setLum.c_str(), dstColor, srcColor);
|
||||
@ -406,13 +406,13 @@ static bool append_porterduff_term(GrGLSLFragmentBuilder* fsBuilder, SkBlendMode
|
||||
fsBuilder->codeAppendf(" * %s", srcColorName);
|
||||
break;
|
||||
case SkBlendModeCoeff::kISC:
|
||||
fsBuilder->codeAppendf(" * (float4(1.0) - %s)", srcColorName);
|
||||
fsBuilder->codeAppendf(" * (half4(1.0) - %s)", srcColorName);
|
||||
break;
|
||||
case SkBlendModeCoeff::kDC:
|
||||
fsBuilder->codeAppendf(" * %s", dstColorName);
|
||||
break;
|
||||
case SkBlendModeCoeff::kIDC:
|
||||
fsBuilder->codeAppendf(" * (float4(1.0) - %s)", dstColorName);
|
||||
fsBuilder->codeAppendf(" * (half4(1.0) - %s)", dstColorName);
|
||||
break;
|
||||
case SkBlendModeCoeff::kSA:
|
||||
fsBuilder->codeAppendf(" * %s.a", srcColorName);
|
||||
@ -453,7 +453,7 @@ void GrGLSLBlend::AppendMode(GrGLSLFragmentBuilder* fsBuilder, const char* srcCo
|
||||
false);
|
||||
// append dst blend
|
||||
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) {
|
||||
fsBuilder->codeAppend(", 0, 1);");
|
||||
@ -505,7 +505,7 @@ void GrGLSLBlend::AppendRegionOp(GrGLSLFragmentBuilder* fsBuilder, const char* s
|
||||
false);
|
||||
// append dst blend
|
||||
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(";");
|
||||
}
|
||||
|
@ -24,8 +24,8 @@ public:
|
||||
uint32_t visibility = kFragment_GrShaderFlag) {
|
||||
SkASSERT(uniformHandler);
|
||||
if (colorSpaceXform) {
|
||||
fGamutXformVar = uniformHandler->addUniform(visibility, kMat44f_GrSLType,
|
||||
kDefault_GrSLPrecision, "ColorXform");
|
||||
fGamutXformVar = uniformHandler->addUniform(visibility, kHalf4x4_GrSLType,
|
||||
"ColorXform");
|
||||
fValid = true;
|
||||
}
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ void GrGLSLFragmentProcessor::emitChild(int childIndex, const char* inputColor,
|
||||
SkASSERT(outputColor);
|
||||
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -86,9 +86,9 @@ public:
|
||||
@param fp The processor that generated this program stage.
|
||||
@param key The key that was computed by GenKey() from the generating
|
||||
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).
|
||||
@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
|
||||
ones). TODO: Better system for communicating optimization info
|
||||
(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) {
|
||||
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
|
||||
@ -167,7 +167,7 @@ public:
|
||||
EmitArgs& parentArgs);
|
||||
|
||||
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.*/
|
||||
|
@ -86,7 +86,7 @@ GrGLSLFragmentShaderBuilder::GrGLSLFragmentShaderBuilder(GrGLSLProgramBuilder* p
|
||||
, fHasSecondaryOutput(false)
|
||||
, fUsedSampleOffsetArrays(0)
|
||||
, fHasInitializedSampleMask(false)
|
||||
, fDefaultPrecision(kMedium_GrSLPrecision) {
|
||||
, fForceHighPrecision(false) {
|
||||
fSubstageIndices.push_back(0);
|
||||
#ifdef SK_DEBUG
|
||||
fUsedProcessorFeatures = GrProcessor::kNone_RequiredFeatures;
|
||||
@ -112,14 +112,14 @@ bool GrGLSLFragmentShaderBuilder::enableFeature(GLSLFeature feature) {
|
||||
}
|
||||
|
||||
SkString GrGLSLFragmentShaderBuilder::ensureCoords2D(const GrShaderVar& coords) {
|
||||
if (kVec3f_GrSLType != coords.getType()) {
|
||||
SkASSERT(kVec2f_GrSLType == coords.getType());
|
||||
if (kHighFloat3_GrSLType != coords.getType() && kHalf3_GrSLType != coords.getType()) {
|
||||
SkASSERT(kHighFloat2_GrSLType == coords.getType() || kHalf2_GrSLType == coords.getType());
|
||||
return coords.getName();
|
||||
}
|
||||
|
||||
SkString coords2D;
|
||||
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());
|
||||
return coords2D;
|
||||
}
|
||||
@ -175,10 +175,6 @@ void GrGLSLFragmentShaderBuilder::overrideSampleCoverage(const char* mask) {
|
||||
fHasInitializedSampleMask = true;
|
||||
}
|
||||
|
||||
void GrGLSLFragmentShaderBuilder::elevateDefaultPrecision(GrSLPrecision precision) {
|
||||
fDefaultPrecision = SkTMax(fDefaultPrecision, precision);
|
||||
}
|
||||
|
||||
const char* GrGLSLFragmentShaderBuilder::dstColor() {
|
||||
SkDEBUGCODE(fHasReadDstColor = true;)
|
||||
|
||||
@ -199,7 +195,7 @@ const char* GrGLSLFragmentShaderBuilder::dstColor() {
|
||||
fOutputs[fCustomColorOutputIndex].setTypeModifier(GrShaderVar::kInOut_TypeModifier);
|
||||
fbFetchColorName = DeclaredColorOutputName();
|
||||
// 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 {
|
||||
return fbFetchColorName;
|
||||
}
|
||||
@ -228,7 +224,7 @@ void GrGLSLFragmentShaderBuilder::enableCustomOutput() {
|
||||
if (!fHasCustomColorOutput) {
|
||||
fHasCustomColorOutput = true;
|
||||
fCustomColorOutputIndex = fOutputs.count();
|
||||
fOutputs.push_back().set(kVec4f_GrSLType, DeclaredColorOutputName(),
|
||||
fOutputs.push_back().set(kHalf4_GrSLType, DeclaredColorOutputName(),
|
||||
GrShaderVar::kOut_TypeModifier);
|
||||
fProgramBuilder->finalizeFragmentOutputColor(fOutputs.back());
|
||||
}
|
||||
@ -247,7 +243,7 @@ void GrGLSLFragmentShaderBuilder::enableSecondaryOutput() {
|
||||
// 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.
|
||||
if (caps.mustDeclareFragmentShaderOutput()) {
|
||||
fOutputs.push_back().set(kVec4f_GrSLType, DeclaredSecondaryColorOutputName(),
|
||||
fOutputs.push_back().set(kHalf4_GrSLType, DeclaredSecondaryColorOutputName(),
|
||||
GrShaderVar::kOut_TypeModifier);
|
||||
fProgramBuilder->finalizeFragmentSecondaryColor(fOutputs.back());
|
||||
}
|
||||
@ -280,9 +276,6 @@ GrSurfaceOrigin GrGLSLFragmentShaderBuilder::getSurfaceOrigin() const {
|
||||
|
||||
void GrGLSLFragmentShaderBuilder::onFinalize() {
|
||||
fProgramBuilder->varyingHandler()->getFragDecls(&this->inputs(), &this->outputs());
|
||||
GrGLSLAppendDefaultFloatPrecisionDeclaration(fDefaultPrecision,
|
||||
*fProgramBuilder->shaderCaps(),
|
||||
&this->precisionQualifier());
|
||||
if (fUsedSampleOffsetArrays & (1 << kSkiaDevice_Coordinates)) {
|
||||
this->defineSampleOffsetArray(sample_offset_array_name(kSkiaDevice_Coordinates),
|
||||
SkMatrix::MakeTrans(-0.5f, -0.5f));
|
||||
@ -305,9 +298,9 @@ void GrGLSLFragmentShaderBuilder::defineSampleOffsetArray(const char* name, cons
|
||||
SkSTArray<16, SkPoint, true> offsets;
|
||||
offsets.push_back_n(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) {
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ public:
|
||||
|
||||
/**
|
||||
* 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
|
||||
* fragment shader (xy / z) to convert them to 2D.
|
||||
*/
|
||||
@ -89,13 +89,6 @@ public:
|
||||
*/
|
||||
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
|
||||
* on a child proc.
|
||||
@ -104,6 +97,8 @@ public:
|
||||
virtual void onAfterChildProcEmitCode() = 0;
|
||||
|
||||
virtual const SkString& getMangleString() const = 0;
|
||||
|
||||
virtual void forceHighPrecision() = 0;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -169,10 +164,10 @@ public:
|
||||
void appendOffsetToSample(const char* sampleIdx, Coordinates) override;
|
||||
void maskSampleCoverage(const char* mask, bool invert = false) override;
|
||||
void overrideSampleCoverage(const char* mask) override;
|
||||
void elevateDefaultPrecision(GrSLPrecision) override;
|
||||
const SkString& getMangleString() const override { return fMangleString; }
|
||||
void onBeforeChildProcEmitCode() override;
|
||||
void onAfterChildProcEmitCode() override;
|
||||
void forceHighPrecision() override { fForceHighPrecision = true; }
|
||||
|
||||
// GrGLSLXPFragmentBuilder interface.
|
||||
bool hasCustomColorOutput() const override { return fHasCustomColorOutput; }
|
||||
@ -234,7 +229,7 @@ private:
|
||||
bool fHasSecondaryOutput;
|
||||
uint8_t fUsedSampleOffsetArrays;
|
||||
bool fHasInitializedSampleMask;
|
||||
GrSLPrecision fDefaultPrecision;
|
||||
bool fForceHighPrecision;
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
// some state to verify shaders and effects are consistent, this is reset between effects by
|
||||
|
@ -18,7 +18,8 @@ void GrGLSLGeometryProcessor::emitCode(EmitArgs& args) {
|
||||
GrGPArgs gpArgs;
|
||||
this->onEmitCode(args, &gpArgs);
|
||||
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();
|
||||
}
|
||||
}
|
||||
@ -39,32 +40,28 @@ void GrGLSLGeometryProcessor::emitTransforms(GrGLSLVertexBuilder* vb,
|
||||
uint32_t type = coordTransform->getMatrix().getType();
|
||||
type |= localMatrix.getType();
|
||||
|
||||
varyingType = SkToBool(SkMatrix::kPerspective_Mask & type) ? kVec3f_GrSLType :
|
||||
kVec2f_GrSLType;
|
||||
// Coord transforms are always handled at high precision
|
||||
const GrSLPrecision precision = kHigh_GrSLPrecision;
|
||||
|
||||
varyingType = SkToBool(SkMatrix::kPerspective_Mask & type) ? kHighFloat3_GrSLType :
|
||||
kHighFloat2_GrSLType;
|
||||
const char* uniName;
|
||||
|
||||
|
||||
fInstalledTransforms.push_back().fHandle = uniformHandler->addUniform(kVertex_GrShaderFlag,
|
||||
kMat33f_GrSLType,
|
||||
precision,
|
||||
kHighFloat3x3_GrSLType,
|
||||
strUniName.c_str(),
|
||||
&uniName).toIndex();
|
||||
SkString strVaryingName;
|
||||
strVaryingName.printf("TransformedCoords_%d", i);
|
||||
|
||||
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);
|
||||
|
||||
if (kVec2f_GrSLType == varyingType) {
|
||||
vb->codeAppendf("%s = (%s * float3(%s, 1)).xy;", v.vsOut(), uniName, localCoords);
|
||||
if (kHighFloat2_GrSLType == varyingType) {
|
||||
vb->codeAppendf("%s = (%s * highfloat3(%s, 1)).xy;", v.vsOut(), uniName, localCoords);
|
||||
} else {
|
||||
vb->codeAppendf("%s = %s * float3(%s, 1);", v.vsOut(), uniName, localCoords);
|
||||
vb->codeAppendf("%s = %s * highfloat3(%s, 1);", v.vsOut(), uniName, localCoords);
|
||||
}
|
||||
++i;
|
||||
}
|
||||
@ -88,8 +85,8 @@ void GrGLSLGeometryProcessor::setTransformDataHelper(const SkMatrix& localMatrix
|
||||
void GrGLSLGeometryProcessor::writeOutputPosition(GrGLSLVertexBuilder* vertBuilder,
|
||||
GrGPArgs* gpArgs,
|
||||
const char* posName) {
|
||||
gpArgs->fPositionVar.set(kVec2f_GrSLType, "pos2");
|
||||
vertBuilder->codeAppendf("float2 %s = %s;", gpArgs->fPositionVar.c_str(), posName);
|
||||
gpArgs->fPositionVar.set(kHighFloat2_GrSLType, "pos2");
|
||||
vertBuilder->codeAppendf("highfloat2 %s = %s;", gpArgs->fPositionVar.c_str(), posName);
|
||||
}
|
||||
|
||||
void GrGLSLGeometryProcessor::writeOutputPosition(GrGLSLVertexBuilder* vertBuilder,
|
||||
@ -99,21 +96,21 @@ void GrGLSLGeometryProcessor::writeOutputPosition(GrGLSLVertexBuilder* vertBuild
|
||||
const SkMatrix& mat,
|
||||
UniformHandle* viewMatrixUniform) {
|
||||
if (mat.isIdentity()) {
|
||||
gpArgs->fPositionVar.set(kVec2f_GrSLType, "pos2");
|
||||
vertBuilder->codeAppendf("float2 %s = %s;", gpArgs->fPositionVar.c_str(), posName);
|
||||
gpArgs->fPositionVar.set(kHighFloat2_GrSLType, "pos2");
|
||||
vertBuilder->codeAppendf("highfloat2 %s = %s;", gpArgs->fPositionVar.c_str(), posName);
|
||||
} else {
|
||||
const char* viewMatrixName;
|
||||
*viewMatrixUniform = uniformHandler->addUniform(kVertex_GrShaderFlag,
|
||||
kMat33f_GrSLType, kHigh_GrSLPrecision,
|
||||
kHighFloat3x3_GrSLType,
|
||||
"uViewM",
|
||||
&viewMatrixName);
|
||||
if (!mat.hasPerspective()) {
|
||||
gpArgs->fPositionVar.set(kVec2f_GrSLType, "pos2");
|
||||
vertBuilder->codeAppendf("float2 %s = (%s * float3(%s, 1)).xy;",
|
||||
gpArgs->fPositionVar.set(kHighFloat2_GrSLType, "pos2");
|
||||
vertBuilder->codeAppendf("highfloat2 %s = (%s * highfloat3(%s, 1)).xy;",
|
||||
gpArgs->fPositionVar.c_str(), viewMatrixName, posName);
|
||||
} else {
|
||||
gpArgs->fPositionVar.set(kVec3f_GrSLType, "pos3");
|
||||
vertBuilder->codeAppendf("float3 %s = %s * float3(%s, 1);",
|
||||
gpArgs->fPositionVar.set(kHighFloat3_GrSLType, "pos3");
|
||||
vertBuilder->codeAppendf("highfloat3 %s = %s * highfloat3(%s, 1);",
|
||||
gpArgs->fPositionVar.c_str(), viewMatrixName, posName);
|
||||
}
|
||||
}
|
||||
|
@ -43,13 +43,12 @@ void GrGLSLPrimitiveProcessor::setupUniformColor(GrGLSLPPFragmentBuilder* fragBu
|
||||
SkASSERT(colorUniform);
|
||||
const char* stagedLocalVarName;
|
||||
*colorUniform = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kVec4f_GrSLType,
|
||||
kDefault_GrSLPrecision,
|
||||
kHalf4_GrSLType,
|
||||
"Color",
|
||||
&stagedLocalVarName);
|
||||
fragBuilder->codeAppendf("%s = %s;", outputName, stagedLocalVarName);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -82,8 +82,7 @@ void GrGLSLProgramBuilder::emitAndInstallPrimProc(const GrPrimitiveProcessor& pr
|
||||
rtAdjustVisibility |= kGeometry_GrShaderFlag;
|
||||
}
|
||||
fUniformHandles.fRTAdjustmentUni = this->uniformHandler()->addUniform(rtAdjustVisibility,
|
||||
kVec4f_GrSLType,
|
||||
kHigh_GrSLPrecision,
|
||||
kHighFloat4_GrSLType,
|
||||
"rtAdjustment");
|
||||
const char* rtAdjustName =
|
||||
this->uniformHandler()->getUniformCStr(fUniformHandles.fRTAdjustmentUni);
|
||||
@ -455,7 +454,7 @@ void GrGLSLProgramBuilder::nameExpression(SkString* output, const char* baseName
|
||||
} else {
|
||||
this->nameVariable(&outName, '\0', baseName);
|
||||
}
|
||||
fFS.codeAppendf("float4 %s;", outName.c_str());
|
||||
fFS.codeAppendf("half4 %s;", outName.c_str());
|
||||
*output = outName;
|
||||
}
|
||||
|
||||
@ -468,7 +467,7 @@ void GrGLSLProgramBuilder::addRTHeightUniform(const char* name) {
|
||||
GrGLSLUniformHandler* uniformHandler = this->uniformHandler();
|
||||
fUniformHandles.fRTHeightUni =
|
||||
uniformHandler->internalAddUniformArray(kFragment_GrShaderFlag,
|
||||
kFloat_GrSLType, kDefault_GrSLPrecision,
|
||||
kHalf_GrSLType, kDefault_GrSLPrecision,
|
||||
name, false, 0, nullptr);
|
||||
}
|
||||
|
||||
|
@ -122,16 +122,16 @@ void GrGLSLShaderBuilder::appendColorGamutXform(SkString* out,
|
||||
// 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.
|
||||
static const GrShaderVar gColorGamutXformArgs[] = {
|
||||
GrShaderVar("color", kVec4f_GrSLType),
|
||||
GrShaderVar("xform", kMat44f_GrSLType),
|
||||
GrShaderVar("color", kHalf4_GrSLType),
|
||||
GrShaderVar("xform", kHalf4x4_GrSLType),
|
||||
};
|
||||
SkString functionBody;
|
||||
// Gamut xform, clamp to destination gamut. We only support/have premultiplied textures, so we
|
||||
// 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;");
|
||||
SkString colorGamutXformFuncName;
|
||||
this->emitFunction(kVec4f_GrSLType,
|
||||
this->emitFunction(kHalf4_GrSLType,
|
||||
"colorGamutXform",
|
||||
SK_ARRAY_COUNT(gColorGamutXformArgs),
|
||||
gColorGamutXformArgs,
|
||||
|
@ -37,23 +37,23 @@ public:
|
||||
void appendTextureLookup(SkString* out,
|
||||
SamplerHandle,
|
||||
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.*/
|
||||
void appendTextureLookup(SamplerHandle,
|
||||
const char* coordName,
|
||||
GrSLType coordType = kVec2f_GrSLType,
|
||||
GrSLType coordType = kHalf2_GrSLType,
|
||||
GrGLSLColorSpaceXformHelper* colorXformHelper = nullptr);
|
||||
|
||||
|
||||
/** 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
|
||||
float4 or float. If modulation is "" or nullptr it this function acts as though
|
||||
always a half4. modulation and the swizzle specified by SamplerHandle must both be
|
||||
half4 or half. If modulation is "" or nullptr it this function acts as though
|
||||
appendTextureLookup were called. */
|
||||
void appendTextureLookupAndModulate(const char* modulation,
|
||||
SamplerHandle,
|
||||
const char* coordName,
|
||||
GrSLType coordType = kVec2f_GrSLType,
|
||||
GrSLType coordType = kHalf2_GrSLType,
|
||||
GrGLSLColorSpaceXformHelper* colorXformHelper = nullptr);
|
||||
|
||||
/** Adds a helper function to facilitate color gamut transformation, and produces code that
|
||||
|
@ -38,6 +38,13 @@ public:
|
||||
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,
|
||||
GrSLType type,
|
||||
GrSLPrecision precision,
|
||||
@ -49,6 +56,16 @@ public:
|
||||
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;
|
||||
|
||||
/**
|
||||
|
@ -18,25 +18,25 @@ void GrGLSLVertexBuilder::transformToNormalizedDeviceSpace(const GrShaderVar& po
|
||||
const char* rtAdjustName) {
|
||||
// setup RT Uniform
|
||||
if (this->getProgramBuilder()->desc()->header().fSnapVerticesToPixelCenters) {
|
||||
if (kVec3f_GrSLType == posVar.getType()) {
|
||||
if (kHighFloat3_GrSLType == posVar.getType()) {
|
||||
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 {
|
||||
SkASSERT(kVec2f_GrSLType == posVar.getType());
|
||||
this->codeAppendf("{float2 _posTmp = %s;", posVar.c_str());
|
||||
SkASSERT(kHighFloat2_GrSLType == posVar.getType());
|
||||
this->codeAppendf("{highfloat2 _posTmp = %s;", posVar.c_str());
|
||||
}
|
||||
this->codeAppendf("_posTmp = floor(_posTmp) + float2(0.5, 0.5);"
|
||||
"gl_Position = float4(_posTmp.x * %s.x + %s.y,"
|
||||
this->codeAppendf("_posTmp = floor(_posTmp) + half2(0.5, 0.5);"
|
||||
"gl_Position = highfloat4(_posTmp.x * %s.x + %s.y,"
|
||||
"_posTmp.y * %s.z + %s.w, 0, 1);}",
|
||||
rtAdjustName, rtAdjustName, rtAdjustName, rtAdjustName);
|
||||
} else if (kVec3f_GrSLType == posVar.getType()) {
|
||||
this->codeAppendf("gl_Position = float4(dot(%s.xz, %s.xy), dot(%s.yz, %s.zw), 0, %s.z);",
|
||||
} else if (kHighFloat3_GrSLType == posVar.getType()) {
|
||||
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());
|
||||
} else {
|
||||
SkASSERT(kVec2f_GrSLType == posVar.getType());
|
||||
this->codeAppendf("gl_Position = float4(%s.x * %s.x + %s.y, %s.y * %s.z + %s.w, 0, 1);",
|
||||
SkASSERT(kHighFloat2_GrSLType == posVar.getType());
|
||||
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);
|
||||
}
|
||||
|
@ -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
|
||||
// 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.
|
||||
fragBuilder->codeAppendf("if (all(lessThanEqual(%s.rgb, float3(0)))) {"
|
||||
fragBuilder->codeAppendf("if (all(lessThanEqual(%s.rgb, half3(0)))) {"
|
||||
" discard;"
|
||||
"}", args.fInputCoverage);
|
||||
}
|
||||
@ -61,27 +61,25 @@ void GrGLSLXferProcessor::emitCode(const EmitArgs& args) {
|
||||
const char* dstCoordScaleName;
|
||||
|
||||
fDstTopLeftUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kVec2f_GrSLType,
|
||||
kDefault_GrSLPrecision,
|
||||
kHalf2_GrSLType,
|
||||
"DstTextureUpperLeft",
|
||||
&dstTopLeftName);
|
||||
fDstScaleUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kVec2f_GrSLType,
|
||||
kDefault_GrSLPrecision,
|
||||
kHalf2_GrSLType,
|
||||
"DstTextureCoordScale",
|
||||
&dstCoordScaleName);
|
||||
|
||||
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);
|
||||
|
||||
if (flipY) {
|
||||
fragBuilder->codeAppend("_dstTexCoord.y = 1.0 - _dstTexCoord.y;");
|
||||
}
|
||||
|
||||
fragBuilder->codeAppendf("float4 %s = ", dstColor);
|
||||
fragBuilder->codeAppendf("half4 %s = ", dstColor);
|
||||
fragBuilder->appendTextureLookup(args.fDstTextureSamplerHandle, "_dstTexCoord",
|
||||
kVec2f_GrSLType);
|
||||
kHalf2_GrSLType);
|
||||
fragBuilder->codeAppend(";");
|
||||
} else {
|
||||
needsLocalOutColor = args.fShaderCaps->requiresLocalOutputColorForFBFetch();
|
||||
@ -91,7 +89,7 @@ void GrGLSLXferProcessor::emitCode(const EmitArgs& args) {
|
||||
if (!needsLocalOutColor) {
|
||||
outColor = args.fOutputPrimary;
|
||||
} else {
|
||||
fragBuilder->codeAppendf("float4 %s;", outColor);
|
||||
fragBuilder->codeAppendf("half4 %s;", outColor);
|
||||
}
|
||||
|
||||
this->emitBlendCodeForDstRead(fragBuilder,
|
||||
@ -139,18 +137,18 @@ void GrGLSLXferProcessor::DefaultCoverageModulation(GrGLSLXPFragmentBuilder* fra
|
||||
fragBuilder->codeAppendf("%s *= %s;", outColor, srcCoverage);
|
||||
fragBuilder->codeAppendf("%s = %s;", outColorSecondary, srcCoverage);
|
||||
} else {
|
||||
fragBuilder->codeAppendf("%s = float4(1.0);", outColorSecondary);
|
||||
fragBuilder->codeAppendf("%s = half4(1.0);", outColorSecondary);
|
||||
}
|
||||
} else if (srcCoverage) {
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
}
|
||||
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);
|
||||
if (proc.isLCD()) {
|
||||
fragBuilder->codeAppendf("%s.a = max(max(lerpRed, lerpBlue), lerpGreen);", outColor);
|
||||
|
@ -105,32 +105,38 @@ public:
|
||||
|
||||
void initParams(const TexelBufferHandle paramsBuffer) {
|
||||
fParamsBuffer = paramsBuffer;
|
||||
fVertexBuilder->codeAppendf("highp int paramsIdx = int(%s & 0x%x);",
|
||||
fVertexBuilder->codeAppendf("int paramsIdx = int(%s & 0x%x);",
|
||||
this->attr(Attrib::kInstanceInfo),
|
||||
kParamsIdx_InfoMask);
|
||||
}
|
||||
|
||||
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());
|
||||
switch (type) {
|
||||
case kVec2f_GrSLType: // fall through
|
||||
case kVec3f_GrSLType: // fall through
|
||||
case kVec4f_GrSLType:
|
||||
case kHighFloat2_GrSLType: // fall through
|
||||
case kHighFloat3_GrSLType: // fall through
|
||||
case kHighFloat4_GrSLType: // fall through
|
||||
case kHalf2_GrSLType: // fall through
|
||||
case kHalf3_GrSLType: // fall through
|
||||
case kHalf4_GrSLType:
|
||||
break;
|
||||
default:
|
||||
fVertexBuilder->codeAppendf("%s(", GrGLSLTypeString(shaderCaps, type));
|
||||
}
|
||||
fVertexBuilder->appendTexelFetch(fParamsBuffer, "paramsIdx++");
|
||||
switch (type) {
|
||||
case kVec2f_GrSLType:
|
||||
case kHighFloat2_GrSLType: // fall through
|
||||
case kHalf2_GrSLType:
|
||||
fVertexBuilder->codeAppend(".xy");
|
||||
break;
|
||||
case kVec3f_GrSLType:
|
||||
case kHighFloat3_GrSLType: // fall through
|
||||
case kHalf3_GrSLType:
|
||||
fVertexBuilder->codeAppend(".xyz");
|
||||
break;
|
||||
case kVec4f_GrSLType:
|
||||
case kHighFloat4_GrSLType: // fall through
|
||||
case kHalf4_GrSLType:
|
||||
break;
|
||||
default:
|
||||
fVertexBuilder->codeAppend(")");
|
||||
@ -177,11 +183,11 @@ protected:
|
||||
, fModifiesCoverage(false)
|
||||
, fModifiesColor(false)
|
||||
, fNeedsNeighborRadii(false)
|
||||
, fColor(kVec4f_GrSLType)
|
||||
, fColor(kHalf4_GrSLType)
|
||||
, fTriangleIsArc(kInt_GrSLType)
|
||||
, fArcCoords(kVec2f_GrSLType)
|
||||
, fInnerShapeCoords(kVec2f_GrSLType)
|
||||
, fInnerRRect(kVec4f_GrSLType)
|
||||
, fArcCoords(kHalf2_GrSLType)
|
||||
, fInnerShapeCoords(kHalf2_GrSLType)
|
||||
, fInnerRRect(kHalf4_GrSLType)
|
||||
, fModifiedShapeCoords(nullptr) {
|
||||
if (fOpInfo.fShapeTypes & kRRect_ShapesMask) {
|
||||
fModifiedShapeCoords = "adjustedShapeCoords";
|
||||
@ -232,16 +238,16 @@ void GLSLInstanceProcessor::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
|
||||
}
|
||||
|
||||
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));
|
||||
} else {
|
||||
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));
|
||||
v->codeAppendf("if (0 != (%s & uint(PERSPECTIVE_FLAG))) {",
|
||||
inputs.attr(Attrib::kInstanceInfo));
|
||||
v->codeAppend ( "shapeMatrix[2] = ");
|
||||
inputs.fetchNextParam(args.fShaderCaps, kVec3f_GrSLType);
|
||||
inputs.fetchNextParam(args.fShaderCaps, kHalf3_GrSLType);
|
||||
v->codeAppend ( ";");
|
||||
v->codeAppend ("}");
|
||||
}
|
||||
@ -303,16 +309,16 @@ void GLSLInstanceProcessor::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
|
||||
inputs.attr(Attrib::kInstanceInfo));
|
||||
}
|
||||
// Here we take advantage of the fact that outerRect == localRect in recordDRRect.
|
||||
v->codeAppendf("float4 outer = %s;", inputs.attr(Attrib::kLocalRect));
|
||||
v->codeAppend ("float4 inner = ");
|
||||
v->codeAppendf("half4 outer = %s;", inputs.attr(Attrib::kLocalRect));
|
||||
v->codeAppend ("half4 inner = ");
|
||||
inputs.fetchNextParam(args.fShaderCaps);
|
||||
v->codeAppend (";");
|
||||
// outer2Inner is a transform from shape coords to inner shape coords:
|
||||
// e.g. innerShapeCoords = shapeCoords * outer2Inner.xy + outer2Inner.zw
|
||||
v->codeAppend ("float4 outer2Inner = float4(outer.zw - outer.xy, "
|
||||
"outer.xy + outer.zw - inner.xy - inner.zw) / "
|
||||
"(inner.zw - inner.xy).xyxy;");
|
||||
v->codeAppendf("float2 innerShapeCoords = %s * outer2Inner.xy + outer2Inner.zw;",
|
||||
v->codeAppend ("half4 outer2Inner = half4(outer.zw - outer.xy, "
|
||||
"outer.xy + outer.zw - inner.xy - inner.zw) / "
|
||||
"(inner.zw - inner.xy).xyxy;");
|
||||
v->codeAppendf("half2 innerShapeCoords = %s * outer2Inner.xy + outer2Inner.zw;",
|
||||
backend->outShapeCoords());
|
||||
|
||||
backend->initInnerShape(varyingHandler, v);
|
||||
@ -372,8 +378,8 @@ void GLSLInstanceProcessor::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
|
||||
const char* localCoords = nullptr;
|
||||
if (ip.opInfo().fUsesLocalCoords) {
|
||||
localCoords = "localCoords";
|
||||
v->codeAppendf("float2 t = 0.5 * (%s + float2(1));", backend->outShapeCoords());
|
||||
v->codeAppendf("float2 localCoords = (1.0 - t) * %s.xy + t * %s.zw;",
|
||||
v->codeAppendf("half2 t = 0.5 * (%s + half2(1));", backend->outShapeCoords());
|
||||
v->codeAppendf("half2 localCoords = (1.0 - t) * %s.xy + t * %s.zw;",
|
||||
inputs.attr(Attrib::kLocalRect), inputs.attr(Attrib::kLocalRect));
|
||||
}
|
||||
if (ip.opInfo().fHasLocalMatrix && ip.opInfo().fHasParams) {
|
||||
@ -383,20 +389,20 @@ void GLSLInstanceProcessor::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
|
||||
if (!ip.opInfo().fUsesLocalCoords) {
|
||||
inputs.skipParams(2);
|
||||
} else {
|
||||
v->codeAppendf( "float2x3 localMatrix;");
|
||||
v->codeAppendf( "half2x3 localMatrix;");
|
||||
v->codeAppend ( "localMatrix[0] = ");
|
||||
inputs.fetchNextParam(args.fShaderCaps, kVec3f_GrSLType);
|
||||
inputs.fetchNextParam(args.fShaderCaps, kHalf3_GrSLType);
|
||||
v->codeAppend ( ";");
|
||||
v->codeAppend ( "localMatrix[1] = ");
|
||||
inputs.fetchNextParam(args.fShaderCaps, kVec3f_GrSLType);
|
||||
inputs.fetchNextParam(args.fShaderCaps, kHalf3_GrSLType);
|
||||
v->codeAppend ( ";");
|
||||
v->codeAppend ( "localCoords = (float3(localCoords, 1) * localMatrix).xy;");
|
||||
v->codeAppend ( "localCoords = (half3(localCoords, 1) * localMatrix).xy;");
|
||||
}
|
||||
v->codeAppend("}");
|
||||
}
|
||||
|
||||
GrSLType positionType = ip.opInfo().fHasPerspective ? kVec3f_GrSLType : kVec2f_GrSLType;
|
||||
v->codeAppendf("%s deviceCoords = float3(%s, 1) * shapeMatrix;",
|
||||
GrSLType positionType = ip.opInfo().fHasPerspective ? kHighFloat3_GrSLType : kHighFloat2_GrSLType;
|
||||
v->codeAppendf("%s deviceCoords = highfloat3(%s, 1) * shapeMatrix;",
|
||||
GrGLSLTypeString(args.fShaderCaps, positionType), backend->outShapeCoords());
|
||||
gpArgs->fPositionVar.set(positionType, "deviceCoords");
|
||||
|
||||
@ -409,7 +415,7 @@ void GLSLInstanceProcessor::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
|
||||
void GLSLInstanceProcessor::Backend::init(GrGLSLVaryingHandler* varyingHandler,
|
||||
GrGLSLVertexBuilder* v) {
|
||||
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);
|
||||
@ -425,10 +431,10 @@ void GLSLInstanceProcessor::Backend::setupRRect(const GrShaderCaps* shaderCaps,
|
||||
int* usedShapeDefinitions) {
|
||||
v->codeAppendf("uint2 corner = uint2(uint(%s) & 1, (uint(%s) >> 1) & 1);",
|
||||
fInputs.attr(Attrib::kVertexAttrs), fInputs.attr(Attrib::kVertexAttrs));
|
||||
v->codeAppend ("float2 cornerSign = float2(corner) * 2.0 - 1.0;");
|
||||
v->codeAppendf("float2 radii%s;", fNeedsNeighborRadii ? ", neighborRadii" : "");
|
||||
v->codeAppend ("float2x2 p = ");
|
||||
fInputs.fetchNextParam(shaderCaps, kMat22f_GrSLType);
|
||||
v->codeAppend ("half2 cornerSign = half2(corner) * 2.0 - 1.0;");
|
||||
v->codeAppendf("half2 radii%s;", fNeedsNeighborRadii ? ", neighborRadii" : "");
|
||||
v->codeAppend ("half2x2 p = ");
|
||||
fInputs.fetchNextParam(shaderCaps, kHalf2x2_GrSLType);
|
||||
v->codeAppend (";");
|
||||
uint8_t types = fOpInfo.fShapeTypes & kRRect_ShapesMask;
|
||||
if (0 == (types & (types - 1))) {
|
||||
@ -469,11 +475,11 @@ void GLSLInstanceProcessor::Backend::setupRRect(const GrShaderCaps* shaderCaps,
|
||||
this->adjustRRectVertices(v);
|
||||
|
||||
if (fArcCoords.vsOut()) {
|
||||
v->codeAppendf("%s = (cornerSign * %s + radii - float2(1)) / radii;",
|
||||
v->codeAppendf("%s = (cornerSign * %s + radii - half2(1)) / radii;",
|
||||
fArcCoords.vsOut(), fModifiedShapeCoords);
|
||||
}
|
||||
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));
|
||||
}
|
||||
|
||||
@ -488,9 +494,9 @@ void GLSLInstanceProcessor::Backend::setupSimpleRadii(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) {
|
||||
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
|
||||
*
|
||||
*/
|
||||
v->codeAppend("float2x2 p2 = ");
|
||||
fInputs.fetchNextParam(shaderCaps, kMat22f_GrSLType);
|
||||
v->codeAppend("half2x2 p2 = ");
|
||||
fInputs.fetchNextParam(shaderCaps, kHalf2x2_GrSLType);
|
||||
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) {
|
||||
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]);");
|
||||
}
|
||||
}
|
||||
@ -544,10 +550,10 @@ void GLSLInstanceProcessor::Backend::initInnerShape(GrGLSLVaryingHandler* varyin
|
||||
|
||||
void GLSLInstanceProcessor::Backend::setupInnerSimpleRRect(const GrShaderCaps* shaderCaps,
|
||||
GrGLSLVertexBuilder* v) {
|
||||
v->codeAppend("float2x2 innerP = ");
|
||||
fInputs.fetchNextParam(shaderCaps, kMat22f_GrSLType);
|
||||
v->codeAppend("half2x2 innerP = ");
|
||||
fInputs.fetchNextParam(shaderCaps, kHalf2x2_GrSLType);
|
||||
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);
|
||||
}
|
||||
|
||||
@ -558,7 +564,7 @@ void GLSLInstanceProcessor::Backend::emitCode(GrGLSLVertexBuilder* v, GrGLSLPPFr
|
||||
fModifiesColor ? outColor : nullptr);
|
||||
if (outCoverage && !fModifiesCoverage) {
|
||||
// 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) {
|
||||
// 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) {
|
||||
if (fInnerRRect.vsOut()) {
|
||||
v->codeAppendf("%s = float4(1);", fInnerRRect.vsOut());
|
||||
v->codeAppendf("%s = half4(1);", fInnerRRect.vsOut());
|
||||
}
|
||||
}
|
||||
|
||||
void GLSLInstanceProcessor::BackendNonAA::setupInnerOval(GrGLSLVertexBuilder* v) {
|
||||
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) {
|
||||
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*,
|
||||
@ -647,11 +653,11 @@ void GLSLInstanceProcessor::BackendNonAA::onEmitCode(GrGLSLVertexBuilder*,
|
||||
if (!fOpInfo.fCannotDiscard) {
|
||||
dropFragment = "discard";
|
||||
} else if (fModifiesCoverage) {
|
||||
f->codeAppend ("lowp float covered = 1.0;");
|
||||
f->codeAppend ("half covered = 1.0;");
|
||||
dropFragment = "covered = 0.0";
|
||||
} else if (fModifiesColor) {
|
||||
f->codeAppendf("lowp float4 color = %s;", fColor.fsIn());
|
||||
dropFragment = "color = float4(0)";
|
||||
f->codeAppendf("half4 color = %s;", fColor.fsIn());
|
||||
dropFragment = "color = half4(0)";
|
||||
}
|
||||
if (fTriangleIsArc.fsIn()) {
|
||||
SkASSERT(dropFragment);
|
||||
@ -662,19 +668,19 @@ void GLSLInstanceProcessor::BackendNonAA::onEmitCode(GrGLSLVertexBuilder*,
|
||||
SkASSERT(dropFragment);
|
||||
f->codeAppendf("// Inner shape.\n");
|
||||
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);
|
||||
} else if (kOval_ShapeFlag == fOpInfo.fInnerShapeTypes) {
|
||||
f->codeAppendf("if ((dot(%s, %s) <= 1.0)) %s;",
|
||||
fInnerShapeCoords.fsIn(), fInnerShapeCoords.fsIn(), dropFragment);
|
||||
} else {
|
||||
f->codeAppendf("if (all(lessThan(abs(%s), float2(1)))) {", fInnerShapeCoords.fsIn());
|
||||
f->codeAppendf( "float2 distanceToArcEdge = abs(%s) - %s.xy;",
|
||||
f->codeAppendf("if (all(lessThan(abs(%s), half2(1)))) {", fInnerShapeCoords.fsIn());
|
||||
f->codeAppendf( "half2 distanceToArcEdge = abs(%s) - %s.xy;",
|
||||
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->codeAppend ( "} else {");
|
||||
f->codeAppendf( "float2 rrectCoords = distanceToArcEdge * %s.zw;",
|
||||
f->codeAppendf( "half2 rrectCoords = distanceToArcEdge * %s.zw;",
|
||||
fInnerRRect.fsIn());
|
||||
f->codeAppend ( "if (dot(rrectCoords, rrectCoords) <= 1.0) {");
|
||||
f->codeAppendf( "%s;", dropFragment);
|
||||
@ -684,7 +690,7 @@ void GLSLInstanceProcessor::BackendNonAA::onEmitCode(GrGLSLVertexBuilder*,
|
||||
}
|
||||
}
|
||||
if (fModifiesCoverage) {
|
||||
f->codeAppendf("%s = float4(covered);", outCoverage);
|
||||
f->codeAppendf("%s = half4(covered);", outCoverage);
|
||||
} else if (fModifiesColor) {
|
||||
f->codeAppendf("%s = color;", outColor);
|
||||
}
|
||||
@ -696,15 +702,15 @@ class GLSLInstanceProcessor::BackendCoverage : public Backend {
|
||||
public:
|
||||
BackendCoverage(OpInfo opInfo, const VertexInputs& inputs)
|
||||
: INHERITED(opInfo, inputs)
|
||||
, fColorTimesRectCoverage(kVec4f_GrSLType)
|
||||
, fRectCoverage(kFloat_GrSLType)
|
||||
, fEllipseCoords(kVec2f_GrSLType)
|
||||
, fEllipseName(kVec2f_GrSLType)
|
||||
, fBloatedRadius(kFloat_GrSLType)
|
||||
, fDistanceToInnerEdge(kVec2f_GrSLType)
|
||||
, fInnerShapeBloatedHalfSize(kVec2f_GrSLType)
|
||||
, fInnerEllipseCoords(kVec2f_GrSLType)
|
||||
, fInnerEllipseName(kVec2f_GrSLType) {
|
||||
, fColorTimesRectCoverage(kHalf4_GrSLType)
|
||||
, fRectCoverage(kHalf_GrSLType)
|
||||
, fEllipseCoords(kHalf2_GrSLType)
|
||||
, fEllipseName(kHalf2_GrSLType)
|
||||
, fBloatedRadius(kHalf_GrSLType)
|
||||
, fDistanceToInnerEdge(kHalf2_GrSLType)
|
||||
, fInnerShapeBloatedHalfSize(kHalf2_GrSLType)
|
||||
, fInnerEllipseCoords(kHalf2_GrSLType)
|
||||
, fInnerEllipseName(kHalf2_GrSLType) {
|
||||
fShapeIsCircle = !fOpInfo.fNonSquare && !(fOpInfo.fShapeTypes & kRRect_ShapesMask);
|
||||
fTweakAlphaForCoverage = !fOpInfo.fCannotTweakAlphaForCoverage && !fOpInfo.fInnerShapeTypes;
|
||||
fModifiesCoverage = !fTweakAlphaForCoverage;
|
||||
@ -751,10 +757,10 @@ private:
|
||||
|
||||
void GLSLInstanceProcessor::BackendCoverage::onInit(GrGLSLVaryingHandler* varyingHandler,
|
||||
GrGLSLVertexBuilder* v) {
|
||||
v->codeAppend ("float2x2 shapeTransposeMatrix = transpose(float2x2(shapeMatrix));");
|
||||
v->codeAppend ("float2 shapeHalfSize = float2(length(shapeTransposeMatrix[0]), "
|
||||
v->codeAppend ("half2x2 shapeTransposeMatrix = transpose(half2x2(shapeMatrix));");
|
||||
v->codeAppend ("half2 shapeHalfSize = half2(length(shapeTransposeMatrix[0]), "
|
||||
"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));
|
||||
|
||||
if (kOval_ShapeFlag != fOpInfo.fShapeTypes) {
|
||||
@ -767,7 +773,7 @@ void GLSLInstanceProcessor::BackendCoverage::onInit(GrGLSLVaryingHandler* varyin
|
||||
} else {
|
||||
varyingHandler->addVarying("rectCoverage", &fRectCoverage, kLow_GrSLPrecision);
|
||||
}
|
||||
v->codeAppend("float rectCoverage = 0.0;");
|
||||
v->codeAppend("half rectCoverage = 0.0;");
|
||||
}
|
||||
if (kRect_ShapeFlag != fOpInfo.fShapeTypes) {
|
||||
varyingHandler->addFlatVarying("triangleIsArc", &fTriangleIsArc, kLow_GrSLPrecision);
|
||||
@ -783,18 +789,18 @@ void GLSLInstanceProcessor::BackendCoverage::onInit(GrGLSLVaryingHandler* varyin
|
||||
|
||||
void GLSLInstanceProcessor::BackendCoverage::setupRect(GrGLSLVertexBuilder* v) {
|
||||
// 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));
|
||||
// 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,
|
||||
// combined with the "maxCoverage" logic below gives us mathematically correct coverage even for
|
||||
// subpixel rectangles.
|
||||
v->codeAppendf("bloatedShapeCoords = %s * abs(float2(1.0 + rectBloat));",
|
||||
v->codeAppendf("bloatedShapeCoords = %s * abs(half2(1.0 + rectBloat));",
|
||||
fInputs.attr(Attrib::kShapeCoords));
|
||||
|
||||
// Determine coverage at the vertex. Coverage naturally ramps from 0 to 1 unless the rect is
|
||||
// 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);");
|
||||
v->codeAppendf("rectCoverage = (%s != 0) ? 0.0 : maxCoverage;",
|
||||
fInputs.attr(Attrib::kVertexAttrs));
|
||||
@ -806,9 +812,9 @@ void GLSLInstanceProcessor::BackendCoverage::setupRect(GrGLSLVertexBuilder* v) {
|
||||
|
||||
void GLSLInstanceProcessor::BackendCoverage::setupOval(GrGLSLVertexBuilder* v) {
|
||||
// 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));
|
||||
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));
|
||||
v->codeAppendf("%s = bloatedShapeCoords * shapeHalfSize;", fEllipseCoords.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
|
||||
// can't allow them to get closer than one half pixel to the edge or they might overlap with
|
||||
// their neighboring border.
|
||||
v->codeAppend("float2 innerEdge = max(1.0 - bloat, float2(0));");
|
||||
v->codeAppend ("float2 borderEdge = cornerSign * clamp(1.0 - radii, -innerEdge, innerEdge);");
|
||||
v->codeAppend("half2 innerEdge = max(1.0 - bloat, half2(0));");
|
||||
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.
|
||||
v->codeAppendf("if (abs(%s.x) == 0.5)"
|
||||
"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
|
||||
// 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.)
|
||||
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);");
|
||||
|
||||
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
|
||||
// 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.)
|
||||
v->codeAppendf("float2 clampedRadii = max(radii, bloat);");
|
||||
v->codeAppendf("%s = (cornerSign * bloatedShapeCoords + clampedRadii - float2(1)) * "
|
||||
v->codeAppendf("half2 clampedRadii = max(radii, bloat);");
|
||||
v->codeAppendf("%s = (cornerSign * bloatedShapeCoords + clampedRadii - half2(1)) * "
|
||||
"shapeHalfSize;", fEllipseCoords.vsOut());
|
||||
v->codeAppendf("%s = 1.0 / (clampedRadii * clampedRadii * shapeHalfSize * shapeHalfSize);",
|
||||
fEllipseName.vsOut());
|
||||
@ -872,7 +878,7 @@ void GLSLInstanceProcessor::BackendCoverage::onSetupRRect(GrGLSLVertexBuilder* v
|
||||
|
||||
void GLSLInstanceProcessor::BackendCoverage::onInitInnerShape(GrGLSLVaryingHandler* varyingHandler,
|
||||
GrGLSLVertexBuilder* v) {
|
||||
v->codeAppend("float2 innerShapeHalfSize = shapeHalfSize / outer2Inner.xy;");
|
||||
v->codeAppend("half2 innerShapeHalfSize = shapeHalfSize / outer2Inner.xy;");
|
||||
|
||||
if (kOval_ShapeFlag == fOpInfo.fInnerShapeTypes) {
|
||||
varyingHandler->addVarying("innerEllipseCoords", &fInnerEllipseCoords,
|
||||
@ -910,7 +916,7 @@ void GLSLInstanceProcessor::BackendCoverage::setupInnerOval(GrGLSLVertexBuilder*
|
||||
v->codeAppendf("%s = innerShapeCoords * innerShapeHalfSize;", fInnerEllipseCoords.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 * "
|
||||
"innerShapeHalfSize);",
|
||||
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,
|
||||
@ -937,7 +943,7 @@ void GLSLInstanceProcessor::BackendCoverage::onEmitCode(GrGLSLVertexBuilder* v,
|
||||
v->codeAppendf("%s = rectCoverage;", fRectCoverage.vsOut());
|
||||
}
|
||||
|
||||
SkString coverage("lowp float coverage");
|
||||
SkString coverage("half coverage");
|
||||
if (fOpInfo.fInnerShapeTypes || (!fTweakAlphaForCoverage && fTriangleIsArc.fsIn())) {
|
||||
f->codeAppendf("%s;", coverage.c_str());
|
||||
coverage = "coverage";
|
||||
@ -964,7 +970,7 @@ void GLSLInstanceProcessor::BackendCoverage::onEmitCode(GrGLSLVertexBuilder* v,
|
||||
|
||||
if (fOpInfo.fInnerShapeTypes) {
|
||||
f->codeAppendf("// Inner shape.\n");
|
||||
SkString innerCoverageDecl("lowp float innerCoverage");
|
||||
SkString innerCoverageDecl("half innerCoverage");
|
||||
if (kOval_ShapeFlag == fOpInfo.fInnerShapeTypes) {
|
||||
this->emitArc(f, fInnerEllipseCoords.fsIn(), fInnerEllipseName.fsIn(),
|
||||
true /*ellipseCoordsNeedClamp*/, true /*ellipseCoordsMayBeNegative*/,
|
||||
@ -978,12 +984,12 @@ void GLSLInstanceProcessor::BackendCoverage::onEmitCode(GrGLSLVertexBuilder* v,
|
||||
this->emitInnerRect(f, innerCoverageDecl.c_str());
|
||||
} else {
|
||||
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());
|
||||
f->codeAppend ("if (any(lessThan(distanceToArcEdge, float2(1e-5)))) {");
|
||||
f->codeAppend ("if (any(lessThan(distanceToArcEdge, half2(1e-5)))) {");
|
||||
this->emitInnerRect(f, "innerCoverage");
|
||||
f->codeAppend ("} else {");
|
||||
f->codeAppendf( "mediump float2 ellipseCoords = distanceToArcEdge * %s.zw;",
|
||||
f->codeAppendf( "half2 ellipseCoords = distanceToArcEdge * %s.zw;",
|
||||
fInnerRRect.fsIn());
|
||||
this->emitArc(f, "ellipseCoords", fInnerEllipseName.fsIn(),
|
||||
false /*ellipseCoordsNeedClamp*/,
|
||||
@ -991,9 +997,9 @@ void GLSLInstanceProcessor::BackendCoverage::onEmitCode(GrGLSLVertexBuilder* v,
|
||||
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) {
|
||||
f->codeAppendf("%s = float4(coverage);", outCoverage);
|
||||
f->codeAppendf("%s = half4(coverage);", outCoverage);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1016,7 +1022,7 @@ void GLSLInstanceProcessor::BackendCoverage::emitCircle(GrGLSLPPFragmentBuilder*
|
||||
const char* outCoverage) {
|
||||
// TODO: circleCoords = max(circleCoords, 0) if we decide to do this optimization on rrects.
|
||||
SkASSERT(!(kRRect_ShapesMask & fOpInfo.fShapeTypes));
|
||||
f->codeAppendf("mediump float distanceToEdge = %s - length(%s);",
|
||||
f->codeAppendf("half distanceToEdge = %s - length(%s);",
|
||||
fBloatedRadius.fsIn(), fEllipseCoords.fsIn());
|
||||
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 avoid inversesqrt(0) in the ellipse formula.
|
||||
if (ellipseCoordsMayBeNegative) {
|
||||
f->codeAppendf("mediump float2 ellipseClampedCoords = max(abs(%s), float2(1e-4));",
|
||||
f->codeAppendf("half2 ellipseClampedCoords = max(abs(%s), half2(1e-4));",
|
||||
ellipseCoords);
|
||||
} else {
|
||||
f->codeAppendf("mediump float2 ellipseClampedCoords = max(%s, float2(1e-4));",
|
||||
f->codeAppendf("half2 ellipseClampedCoords = max(%s, half2(1e-4));",
|
||||
ellipseCoords);
|
||||
}
|
||||
ellipseCoords = "ellipseClampedCoords";
|
||||
}
|
||||
// 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.
|
||||
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.
|
||||
f->codeAppendf("highp float gradDot = 4.0 * dot(Z, Z);");
|
||||
f->codeAppend ("mediump float approxDist = implicit * inversesqrt(gradDot);");
|
||||
f->codeAppendf("highfloat gradDot = 4.0 * dot(Z, Z);");
|
||||
f->codeAppend ("half approxDist = implicit * inversesqrt(gradDot);");
|
||||
f->codeAppendf("%s = clamp(0.5 - approxDist, 0.0, 1.0);", outCoverage);
|
||||
}
|
||||
|
||||
void GLSLInstanceProcessor::BackendCoverage::emitInnerRect(GrGLSLPPFragmentBuilder* f,
|
||||
const char* outCoverage) {
|
||||
f->codeAppendf("lowp float2 c = %s - abs(%s);",
|
||||
f->codeAppendf("half2 c = %s - abs(%s);",
|
||||
fInnerShapeBloatedHalfSize.fsIn(), fDistanceToInnerEdge.fsIn());
|
||||
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)
|
||||
: INHERITED(opInfo, inputs)
|
||||
, fEffectiveSampleCnt(effectiveSampleCnt)
|
||||
, fShapeCoords(kVec2f_GrSLType)
|
||||
, fShapeInverseMatrix(kMat22f_GrSLType)
|
||||
, fFragShapeHalfSpan(kVec2f_GrSLType)
|
||||
, fArcTest(kVec2f_GrSLType)
|
||||
, fArcInverseMatrix(kMat22f_GrSLType)
|
||||
, fFragArcHalfSpan(kVec2f_GrSLType)
|
||||
, fShapeCoords(kHalf2_GrSLType)
|
||||
, fShapeInverseMatrix(kHalf2x2_GrSLType)
|
||||
, fFragShapeHalfSpan(kHalf2_GrSLType)
|
||||
, fArcTest(kHalf2_GrSLType)
|
||||
, fArcInverseMatrix(kHalf2x2_GrSLType)
|
||||
, fFragArcHalfSpan(kHalf2_GrSLType)
|
||||
, fEarlyAccept(kInt_GrSLType)
|
||||
, fInnerShapeInverseMatrix(kMat22f_GrSLType)
|
||||
, fFragInnerShapeHalfSpan(kVec2f_GrSLType) {
|
||||
, fInnerShapeInverseMatrix(kHalf2x2_GrSLType)
|
||||
, fFragInnerShapeHalfSpan(kHalf2_GrSLType) {
|
||||
fRectTrianglesMaySplit = fOpInfo.fHasPerspective;
|
||||
fNeedsNeighborRadii = this->isMixedSampled() && !fOpInfo.fHasPerspective;
|
||||
}
|
||||
@ -1181,9 +1187,9 @@ void GLSLInstanceProcessor::BackendMultisample::onInit(GrGLSLVaryingHandler* var
|
||||
}
|
||||
}
|
||||
if (!fOpInfo.fHasPerspective) {
|
||||
v->codeAppend("float2x2 shapeInverseMatrix = inverse(float2x2(shapeMatrix));");
|
||||
v->codeAppend("float2 fragShapeSpan = abs(float4(shapeInverseMatrix).xz) + "
|
||||
"abs(float4(shapeInverseMatrix).yw);");
|
||||
v->codeAppend("half2x2 shapeInverseMatrix = inverse(half2x2(shapeMatrix));");
|
||||
v->codeAppend("half2 fragShapeSpan = abs(half4(shapeInverseMatrix).xz) + "
|
||||
"abs(half4(shapeInverseMatrix).yw);");
|
||||
}
|
||||
}
|
||||
|
||||
@ -1199,7 +1205,7 @@ void GLSLInstanceProcessor::BackendMultisample::setupRect(GrGLSLVertexBuilder* v
|
||||
}
|
||||
if (fArcTest.vsOut()) {
|
||||
// Pick a value that is not > 0.
|
||||
v->codeAppendf("%s = float2(0);", fArcTest.vsOut());
|
||||
v->codeAppendf("%s = highfloat2(0);", fArcTest.vsOut());
|
||||
}
|
||||
if (fTriangleIsArc.vsOut()) {
|
||||
v->codeAppendf("%s = 0;", fTriangleIsArc.vsOut());
|
||||
@ -1212,8 +1218,8 @@ void GLSLInstanceProcessor::BackendMultisample::setupRect(GrGLSLVertexBuilder* v
|
||||
void GLSLInstanceProcessor::BackendMultisample::setupOval(GrGLSLVertexBuilder* v) {
|
||||
v->codeAppendf("%s = abs(%s);", fArcCoords.vsOut(), this->outShapeCoords());
|
||||
if (fArcInverseMatrix.vsOut()) {
|
||||
v->codeAppendf("float2 s = sign(%s);", this->outShapeCoords());
|
||||
v->codeAppendf("%s = shapeInverseMatrix * float2x2(s.x, 0, 0 , s.y);",
|
||||
v->codeAppendf("half2 s = sign(%s);", this->outShapeCoords());
|
||||
v->codeAppendf("%s = shapeInverseMatrix * half2x2(s.x, 0, 0 , s.y);",
|
||||
fArcInverseMatrix.vsOut());
|
||||
}
|
||||
if (fFragArcHalfSpan.vsOut()) {
|
||||
@ -1221,7 +1227,7 @@ void GLSLInstanceProcessor::BackendMultisample::setupOval(GrGLSLVertexBuilder* v
|
||||
}
|
||||
if (fArcTest.vsOut()) {
|
||||
// Pick a value that is > 0.
|
||||
v->codeAppendf("%s = float2(1);", fArcTest.vsOut());
|
||||
v->codeAppendf("%s = half2(1);", fArcTest.vsOut());
|
||||
}
|
||||
if (fTriangleIsArc.vsOut()) {
|
||||
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
|
||||
// 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.
|
||||
v->codeAppend ("float2 midpt = 0.5 * (neighborRadii - radii);");
|
||||
v->codeAppend ("float2 cornerSize = any(lessThan(radii, fragShapeSpan)) ? "
|
||||
"float2(0) : min(radii + 0.5 * fragShapeSpan, 1.0 - midpt);");
|
||||
v->codeAppend ("half2 midpt = 0.5 * (neighborRadii - radii);");
|
||||
v->codeAppend ("half2 cornerSize = any(lessThan(radii, fragShapeSpan)) ? "
|
||||
"half2(0) : min(radii + 0.5 * fragShapeSpan, 1.0 - midpt);");
|
||||
} else {
|
||||
// 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.
|
||||
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)"
|
||||
@ -1275,12 +1281,12 @@ void GLSLInstanceProcessor::BackendMultisample::onSetupRRect(GrGLSLVertexBuilder
|
||||
v->codeAppendf("%s = 0.5 * fragShapeSpan;", fFragShapeHalfSpan.vsOut());
|
||||
}
|
||||
if (fArcInverseMatrix.vsOut()) {
|
||||
v->codeAppend ("float2 s = cornerSign / radii;");
|
||||
v->codeAppendf("%s = shapeInverseMatrix * float2x2(s.x, 0, 0, s.y);",
|
||||
v->codeAppend ("half2 s = cornerSign / radii;");
|
||||
v->codeAppendf("%s = shapeInverseMatrix * half2x2(s.x, 0, 0, s.y);",
|
||||
fArcInverseMatrix.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(),
|
||||
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
|
||||
// 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.
|
||||
v->codeAppendf("%s = (cornerSize == float2(0)) ? float2(0) : "
|
||||
"cornerSign * %s * float2x2(1, cornerSize.x - 1.0, cornerSize.y - 1.0, 1);",
|
||||
v->codeAppendf("%s = (cornerSize == half2(0)) ? half2(0) : "
|
||||
"cornerSign * %s * half2x2(1, cornerSize.x - 1.0, cornerSize.y - 1.0, 1);",
|
||||
fArcTest.vsOut(), fModifiedShapeCoords);
|
||||
if (!fOpInfo.fHasPerspective) {
|
||||
// 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()) {
|
||||
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));
|
||||
}
|
||||
}
|
||||
@ -1319,7 +1325,7 @@ GLSLInstanceProcessor::BackendMultisample::onInitInnerShape(GrGLSLVaryingHandler
|
||||
if (!fOpInfo.fHasPerspective) {
|
||||
varyingHandler->addFlatVarying("innerShapeInverseMatrix", &fInnerShapeInverseMatrix,
|
||||
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());
|
||||
varyingHandler->addFlatVarying("fragInnerShapeHalfSpan", &fFragInnerShapeHalfSpan,
|
||||
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
|
||||
// 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.
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
void GLSLInstanceProcessor::BackendMultisample::setupInnerOval(GrGLSLVertexBuilder* v) {
|
||||
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()) {
|
||||
v->codeAppendf("innerRadii = max(innerRadii, 2e-1 * %s);", fFragInnerShapeHalfSpan.vsOut());
|
||||
} 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*,
|
||||
@ -1364,8 +1370,8 @@ void GLSLInstanceProcessor::BackendMultisample::onEmitCode(GrGLSLVertexBuilder*,
|
||||
}
|
||||
|
||||
if (kRect_ShapeFlag != (fOpInfo.fShapeTypes | fOpInfo.fInnerShapeTypes)) {
|
||||
GrShaderVar x("x", kVec2f_GrSLType, GrShaderVar::kNonArray, kHigh_GrSLPrecision);
|
||||
f->emitFunction(kFloat_GrSLType, "square", 1, &x, "return dot(x, x);", &fSquareFun);
|
||||
GrShaderVar x("x", kHighFloat2_GrSLType, GrShaderVar::kNonArray);
|
||||
f->emitFunction(kHalf_GrSLType, "square", 1, &x, "return dot(x, x);", &fSquareFun);
|
||||
}
|
||||
|
||||
EmitShapeCoords shapeCoords;
|
||||
@ -1387,7 +1393,7 @@ void GLSLInstanceProcessor::BackendMultisample::onEmitCode(GrGLSLVertexBuilder*,
|
||||
if (fOpInfo.fHasPerspective && fOpInfo.fInnerShapeTypes) {
|
||||
// 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.
|
||||
f->codeAppendf("highp float2 fragInnerShapeApproxHalfSpan = 0.5 * fwidth(%s);",
|
||||
f->codeAppendf("highfloat2 fragInnerShapeApproxHalfSpan = 0.5 * fwidth(%s);",
|
||||
fInnerShapeCoords.fsIn());
|
||||
}
|
||||
|
||||
@ -1404,7 +1410,7 @@ void GLSLInstanceProcessor::BackendMultisample::onEmitCode(GrGLSLVertexBuilder*,
|
||||
if (arcTest && fOpInfo.fHasPerspective) {
|
||||
// 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.
|
||||
f->codeAppendf("highp float2 arcTest = %s - 0.5 * fwidth(%s);",
|
||||
f->codeAppendf("highfloat2 arcTest = %s - 0.5 * fwidth(%s);",
|
||||
fArcTest.fsIn(), fArcTest.fsIn());
|
||||
arcTest = "arcTest";
|
||||
}
|
||||
@ -1415,7 +1421,7 @@ void GLSLInstanceProcessor::BackendMultisample::onEmitCode(GrGLSLVertexBuilder*,
|
||||
if (arcTest) {
|
||||
// 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 || "
|
||||
"all(greaterThan(%s, float2(0)))) {", arcTest);
|
||||
"all(greaterThan(%s, highfloat2(0)))) {", arcTest);
|
||||
this->emitArc(f, arcCoords, false, clampArcCoords, opts);
|
||||
f->codeAppend ("} else {");
|
||||
this->emitRect(f, shapeCoords, opts);
|
||||
@ -1488,10 +1494,10 @@ void GLSLInstanceProcessor::BackendMultisample::emitRect(GrGLSLPPFragmentBuilder
|
||||
}
|
||||
f->codeAppend ("int rectMask = 0;");
|
||||
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);
|
||||
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 ("}");
|
||||
this->acceptCoverageMask(f, "rectMask", opts);
|
||||
if (coords.fFragHalfSpan) {
|
||||
@ -1507,7 +1513,7 @@ void GLSLInstanceProcessor::BackendMultisample::emitArc(GrGLSLPPFragmentBuilder*
|
||||
SkString absArcCoords;
|
||||
absArcCoords.printf(coordsMayBeNegative ? "abs(%s)" : "%s", coords.fVarying->fsIn());
|
||||
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);
|
||||
} else {
|
||||
f->codeAppendf("if (%s(%s + %s) < 1.0) {",
|
||||
@ -1515,7 +1521,7 @@ void GLSLInstanceProcessor::BackendMultisample::emitArc(GrGLSLPPFragmentBuilder*
|
||||
}
|
||||
// The entire pixel is inside the arc.
|
||||
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);
|
||||
// The entire pixel is outside the arc.
|
||||
this->acceptOrRejectWholeFragment(f, false, opts);
|
||||
@ -1523,12 +1529,12 @@ void GLSLInstanceProcessor::BackendMultisample::emitArc(GrGLSLPPFragmentBuilder*
|
||||
}
|
||||
f->codeAppend ( "int arcMask = 0;");
|
||||
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);
|
||||
f->codeAppend ( ";");
|
||||
if (clampCoords) {
|
||||
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->codeAppend ( "}");
|
||||
@ -1542,31 +1548,31 @@ void GLSLInstanceProcessor::BackendMultisample::emitSimpleRRect(GrGLSLPPFragment
|
||||
const EmitShapeCoords& coords,
|
||||
const char* rrect,
|
||||
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);
|
||||
f->codeAppend ("if (any(lessThan(distanceToArcEdge, float2(0)))) {");
|
||||
f->codeAppend ("if (any(lessThan(distanceToArcEdge, highfloat2(0)))) {");
|
||||
this->emitRect(f, coords, opts);
|
||||
f->codeAppend ("} else {");
|
||||
if (coords.fInverseMatrix && coords.fFragHalfSpan) {
|
||||
f->codeAppendf("highp float2 rrectCoords = distanceToArcEdge * %s.zw;", rrect);
|
||||
f->codeAppendf("highp float2 fragRRectHalfSpan = %s * %s.zw;", coords.fFragHalfSpan, rrect);
|
||||
f->codeAppendf("highfloat2 rrectCoords = distanceToArcEdge * %s.zw;", rrect);
|
||||
f->codeAppendf("highfloat2 fragRRectHalfSpan = %s * %s.zw;", coords.fFragHalfSpan, rrect);
|
||||
f->codeAppendf("if (%s(rrectCoords + fragRRectHalfSpan) <= 1.0) {", fSquareFun.c_str());
|
||||
// The entire pixel is inside the round rect.
|
||||
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());
|
||||
// The entire pixel is outside the round rect.
|
||||
this->acceptOrRejectWholeFragment(f, false, opts);
|
||||
f->codeAppend ("} else {");
|
||||
f->codeAppendf( "highp float2 s = %s.zw * sign(%s);", rrect, coords.fVarying->fsIn());
|
||||
f->codeAppendf( "highp float2x2 innerRRectInverseMatrix = %s * "
|
||||
"float2x2(s.x, 0, 0, s.y);", coords.fInverseMatrix);
|
||||
f->codeAppendf( "highfloat2 s = %s.zw * sign(%s);", rrect, coords.fVarying->fsIn());
|
||||
f->codeAppendf( "highfloat2x2 innerRRectInverseMatrix = %s * "
|
||||
"highfloat2x2(s.x, 0, 0, s.y);", coords.fInverseMatrix);
|
||||
f->codeAppend ( "highp int rrectMask = 0;");
|
||||
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->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());
|
||||
f->codeAppend ( "}");
|
||||
this->acceptCoverageMask(f, "rrectMask", opts);
|
||||
@ -1574,10 +1580,10 @@ void GLSLInstanceProcessor::BackendMultisample::emitSimpleRRect(GrGLSLPPFragment
|
||||
} else {
|
||||
f->codeAppend ("int rrectMask = 0;");
|
||||
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);
|
||||
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);
|
||||
f->codeAppendf( "if (%s(rrectPt) < 1.0) rrectMask |= (1 << i);", fSquareFun.c_str());
|
||||
f->codeAppend ("}");
|
||||
|
@ -564,7 +564,7 @@ public:
|
||||
// emit attributes
|
||||
varyingHandler->emitAttributes(qe);
|
||||
|
||||
GrGLSLVertToFrag v(kVec4f_GrSLType);
|
||||
GrGLSLVertToFrag v(kHalf4_GrSLType);
|
||||
varyingHandler->addVarying("QuadEdge", &v);
|
||||
vertBuilder->codeAppendf("%s = %s;", v.vsOut(), qe.fInQuadEdge->fName);
|
||||
|
||||
@ -585,17 +585,17 @@ public:
|
||||
qe.fLocalMatrix,
|
||||
args.fFPCoordTransformHandler);
|
||||
|
||||
fragBuilder->codeAppendf("float edgeAlpha;");
|
||||
fragBuilder->codeAppendf("half edgeAlpha;");
|
||||
|
||||
// keep the derivative instructions outside the conditional
|
||||
fragBuilder->codeAppendf("float2 duvdx = dFdx(%s.xy);", v.fsIn());
|
||||
fragBuilder->codeAppendf("float2 duvdy = dFdy(%s.xy);", v.fsIn());
|
||||
fragBuilder->codeAppendf("half2 duvdx = dFdx(%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());
|
||||
// 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(),
|
||||
v.fsIn());
|
||||
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);",
|
||||
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 = "
|
||||
"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,
|
||||
|
@ -887,12 +887,12 @@ void GLDashingCircleEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
|
||||
varyingHandler->emitAttributes(dce);
|
||||
|
||||
// XY are dashPos, Z is dashInterval
|
||||
GrGLSLVertToFrag dashParams(kVec3f_GrSLType);
|
||||
GrGLSLVertToFrag dashParams(kHalf3_GrSLType);
|
||||
varyingHandler->addVarying("DashParam", &dashParams);
|
||||
vertBuilder->codeAppendf("%s = %s;", dashParams.vsOut(), dce.inDashParams()->fName);
|
||||
|
||||
// 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);
|
||||
vertBuilder->codeAppendf("%s = %s;", circleParams.vsOut(), dce.inCircleParams()->fName);
|
||||
|
||||
@ -913,21 +913,21 @@ void GLDashingCircleEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
|
||||
args.fFPCoordTransformHandler);
|
||||
|
||||
// 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());
|
||||
fragBuilder->codeAppendf("float2 fragPosShifted = float2(xShifted, %s.y);", dashParams.fsIn());
|
||||
fragBuilder->codeAppendf("float2 center = float2(%s.y, 0.0);", circleParams.fsIn());
|
||||
fragBuilder->codeAppend("float dist = length(center - fragPosShifted);");
|
||||
fragBuilder->codeAppendf("half2 fragPosShifted = half2(xShifted, %s.y);", dashParams.fsIn());
|
||||
fragBuilder->codeAppendf("half2 center = half2(%s.y, 0.0);", circleParams.fsIn());
|
||||
fragBuilder->codeAppend("half dist = length(center - fragPosShifted);");
|
||||
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("float alpha = clamp(diff, 0.0, 1.0);");
|
||||
fragBuilder->codeAppend("half alpha = clamp(diff, 0.0, 1.0);");
|
||||
} 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("%s = float4(alpha);", args.fOutputCoverage);
|
||||
fragBuilder->codeAppendf("%s = half4(alpha);", args.fOutputCoverage);
|
||||
}
|
||||
|
||||
void GLDashingCircleEffect::setData(const GrGLSLProgramDataManager& pdman,
|
||||
@ -1090,13 +1090,13 @@ void GLDashingLineEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
|
||||
varyingHandler->emitAttributes(de);
|
||||
|
||||
// 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);
|
||||
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),
|
||||
// respectively.
|
||||
GrGLSLVertToFrag inRectParams(kVec4f_GrSLType);
|
||||
GrGLSLVertToFrag inRectParams(kHighFloat4_GrSLType);
|
||||
varyingHandler->addVarying("RectParams", &inRectParams, GrSLPrecision::kHigh_GrSLPrecision);
|
||||
vertBuilder->codeAppendf("%s = %s;", inRectParams.vsOut(), de.inRectParams()->fName);
|
||||
|
||||
@ -1117,14 +1117,14 @@ void GLDashingLineEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
|
||||
args.fFPCoordTransformHandler);
|
||||
|
||||
// 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());
|
||||
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) {
|
||||
// The amount of coverage removed in x and y by the edges is computed as a pair of negative
|
||||
// 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(%s.z - fragPosShifted.x, 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
|
||||
// covered.
|
||||
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) {
|
||||
// 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.
|
||||
fragBuilder->codeAppend("float xSub;");
|
||||
fragBuilder->codeAppend("half xSub;");
|
||||
fragBuilder->codeAppendf("xSub = min(fragPosShifted.x - %s.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.
|
||||
fragBuilder->codeAppendf("float alpha = (1.0 + max(xSub, -1.0));");
|
||||
fragBuilder->codeAppendf("half alpha = (1.0 + max(xSub, -1.0));");
|
||||
} else {
|
||||
// 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;",
|
||||
inRectParams.fsIn());
|
||||
fragBuilder->codeAppendf("alpha *= (%s.z - fragPosShifted.x) >= -0.5 ? 1.0 : 0.0;",
|
||||
inRectParams.fsIn());
|
||||
}
|
||||
fragBuilder->codeAppendf("%s = float4(alpha);", args.fOutputCoverage);
|
||||
fragBuilder->codeAppendf("%s = half4(alpha);", args.fOutputCoverage);
|
||||
}
|
||||
|
||||
void GLDashingLineEffect::setData(const GrGLSLProgramDataManager& pdman,
|
||||
|
@ -140,7 +140,7 @@ public:
|
||||
varyingHandler->emitAttributes(qp);
|
||||
varyingHandler->addPassThroughAttribute(qp.inColor(), args.fOutputColor);
|
||||
|
||||
GrGLSLVertToFrag uv(kVec2f_GrSLType);
|
||||
GrGLSLVertToFrag uv(kHighFloat2_GrSLType);
|
||||
varyingHandler->addVarying("uv", &uv, kHigh_GrSLPrecision);
|
||||
vsBuilder->codeAppendf("%s = %s;", uv.vsOut(), qp.inUV()->fName);
|
||||
|
||||
@ -156,7 +156,7 @@ public:
|
||||
GrGLSLPPFragmentBuilder* fsBuilder = args.fFragBuilder;
|
||||
fsBuilder->codeAppendf("if (%s.x * %s.x >= %s.y) discard;", 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,
|
||||
|
@ -119,21 +119,21 @@ private:
|
||||
|
||||
// emit attributes
|
||||
varyingHandler->emitAttributes(cgp);
|
||||
fragBuilder->codeAppend("highp float4 circleEdge;");
|
||||
fragBuilder->codeAppend("highfloat4 circleEdge;");
|
||||
varyingHandler->addPassThroughAttribute(cgp.fInCircleEdge, "circleEdge",
|
||||
kHigh_GrSLPrecision);
|
||||
if (cgp.fInClipPlane) {
|
||||
fragBuilder->codeAppend("float3 clipPlane;");
|
||||
fragBuilder->codeAppend("half3 clipPlane;");
|
||||
varyingHandler->addPassThroughAttribute(cgp.fInClipPlane, "clipPlane");
|
||||
}
|
||||
if (cgp.fInIsectPlane) {
|
||||
SkASSERT(cgp.fInClipPlane);
|
||||
fragBuilder->codeAppend("float3 isectPlane;");
|
||||
fragBuilder->codeAppend("half3 isectPlane;");
|
||||
varyingHandler->addPassThroughAttribute(cgp.fInIsectPlane, "isectPlane");
|
||||
}
|
||||
if (cgp.fInUnionPlane) {
|
||||
SkASSERT(cgp.fInClipPlane);
|
||||
fragBuilder->codeAppend("float3 unionPlane;");
|
||||
fragBuilder->codeAppend("half3 unionPlane;");
|
||||
varyingHandler->addPassThroughAttribute(cgp.fInUnionPlane, "unionPlane");
|
||||
}
|
||||
|
||||
@ -152,19 +152,19 @@ private:
|
||||
cgp.fLocalMatrix,
|
||||
args.fFPCoordTransformHandler);
|
||||
|
||||
fragBuilder->codeAppend("highp float d = length(circleEdge.xy);");
|
||||
fragBuilder->codeAppend("float distanceToOuterEdge = circleEdge.z * (1.0 - d);");
|
||||
fragBuilder->codeAppend("float edgeAlpha = clamp(distanceToOuterEdge, 0.0, 1.0);");
|
||||
fragBuilder->codeAppend("highfloat d = length(circleEdge.xy);");
|
||||
fragBuilder->codeAppend("half distanceToOuterEdge = circleEdge.z * (1.0 - d);");
|
||||
fragBuilder->codeAppend("half edgeAlpha = clamp(distanceToOuterEdge, 0.0, 1.0);");
|
||||
if (cgp.fStroke) {
|
||||
fragBuilder->codeAppend(
|
||||
"float distanceToInnerEdge = circleEdge.z * (d - circleEdge.w);");
|
||||
fragBuilder->codeAppend("float innerAlpha = clamp(distanceToInnerEdge, 0.0, 1.0);");
|
||||
"half distanceToInnerEdge = circleEdge.z * (d - circleEdge.w);");
|
||||
fragBuilder->codeAppend("half innerAlpha = clamp(distanceToInnerEdge, 0.0, 1.0);");
|
||||
fragBuilder->codeAppend("edgeAlpha *= innerAlpha;");
|
||||
}
|
||||
|
||||
if (cgp.fInClipPlane) {
|
||||
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);");
|
||||
if (cgp.fInIsectPlane) {
|
||||
fragBuilder->codeAppend(
|
||||
@ -178,7 +178,7 @@ private:
|
||||
}
|
||||
fragBuilder->codeAppend("edgeAlpha *= clip;");
|
||||
}
|
||||
fragBuilder->codeAppendf("%s = float4(edgeAlpha);", args.fOutputCoverage);
|
||||
fragBuilder->codeAppendf("%s = half4(edgeAlpha);", args.fOutputCoverage);
|
||||
}
|
||||
|
||||
static void GenKey(const GrGeometryProcessor& gp,
|
||||
@ -275,12 +275,12 @@ private:
|
||||
// emit attributes
|
||||
varyingHandler->emitAttributes(egp);
|
||||
|
||||
GrGLSLVertToFrag ellipseOffsets(kVec2f_GrSLType);
|
||||
GrGLSLVertToFrag ellipseOffsets(kHalf2_GrSLType);
|
||||
varyingHandler->addVarying("EllipseOffsets", &ellipseOffsets);
|
||||
vertBuilder->codeAppendf("%s = %s;", ellipseOffsets.vsOut(),
|
||||
egp.fInEllipseOffset->fName);
|
||||
|
||||
GrGLSLVertToFrag ellipseRadii(kVec4f_GrSLType);
|
||||
GrGLSLVertToFrag ellipseRadii(kHalf4_GrSLType);
|
||||
varyingHandler->addVarying("EllipseRadii", &ellipseRadii);
|
||||
vertBuilder->codeAppendf("%s = %s;", ellipseRadii.vsOut(), egp.fInEllipseRadii->fName);
|
||||
|
||||
@ -301,16 +301,16 @@ private:
|
||||
args.fFPCoordTransformHandler);
|
||||
|
||||
// for outer curve
|
||||
fragBuilder->codeAppendf("float2 scaledOffset = %s*%s.xy;", ellipseOffsets.fsIn(),
|
||||
fragBuilder->codeAppendf("half2 scaledOffset = %s*%s.xy;", ellipseOffsets.fsIn(),
|
||||
ellipseRadii.fsIn());
|
||||
fragBuilder->codeAppend("float test = dot(scaledOffset, scaledOffset) - 1.0;");
|
||||
fragBuilder->codeAppendf("float2 grad = 2.0*scaledOffset*%s.xy;", ellipseRadii.fsIn());
|
||||
fragBuilder->codeAppend("float grad_dot = dot(grad, grad);");
|
||||
fragBuilder->codeAppend("half test = dot(scaledOffset, scaledOffset) - 1.0;");
|
||||
fragBuilder->codeAppendf("half2 grad = 2.0*scaledOffset*%s.xy;", ellipseRadii.fsIn());
|
||||
fragBuilder->codeAppend("half grad_dot = dot(grad, grad);");
|
||||
|
||||
// avoid calling inversesqrt on zero.
|
||||
fragBuilder->codeAppend("grad_dot = max(grad_dot, 1.0e-4);");
|
||||
fragBuilder->codeAppend("float invlen = inversesqrt(grad_dot);");
|
||||
fragBuilder->codeAppend("float edgeAlpha = clamp(0.5-test*invlen, 0.0, 1.0);");
|
||||
fragBuilder->codeAppend("half invlen = inversesqrt(grad_dot);");
|
||||
fragBuilder->codeAppend("half edgeAlpha = clamp(0.5-test*invlen, 0.0, 1.0);");
|
||||
|
||||
// for inner curve
|
||||
if (egp.fStroke) {
|
||||
@ -322,7 +322,7 @@ private:
|
||||
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,
|
||||
@ -417,11 +417,11 @@ private:
|
||||
// emit attributes
|
||||
varyingHandler->emitAttributes(diegp);
|
||||
|
||||
GrGLSLVertToFrag offsets0(kVec2f_GrSLType);
|
||||
GrGLSLVertToFrag offsets0(kHalf2_GrSLType);
|
||||
varyingHandler->addVarying("EllipseOffsets0", &offsets0);
|
||||
vertBuilder->codeAppendf("%s = %s;", offsets0.vsOut(), diegp.fInEllipseOffsets0->fName);
|
||||
|
||||
GrGLSLVertToFrag offsets1(kVec2f_GrSLType);
|
||||
GrGLSLVertToFrag offsets1(kHalf2_GrSLType);
|
||||
varyingHandler->addVarying("EllipseOffsets1", &offsets1);
|
||||
vertBuilder->codeAppendf("%s = %s;", offsets1.vsOut(), diegp.fInEllipseOffsets1->fName);
|
||||
|
||||
@ -445,25 +445,25 @@ private:
|
||||
args.fFPCoordTransformHandler);
|
||||
|
||||
// for outer curve
|
||||
fragBuilder->codeAppendf("float2 scaledOffset = %s.xy;", offsets0.fsIn());
|
||||
fragBuilder->codeAppend("float test = dot(scaledOffset, scaledOffset) - 1.0;");
|
||||
fragBuilder->codeAppendf("float2 duvdx = dFdx(%s);", offsets0.fsIn());
|
||||
fragBuilder->codeAppendf("float2 duvdy = dFdy(%s);", offsets0.fsIn());
|
||||
fragBuilder->codeAppendf("half2 scaledOffset = %s.xy;", offsets0.fsIn());
|
||||
fragBuilder->codeAppend("half test = dot(scaledOffset, scaledOffset) - 1.0;");
|
||||
fragBuilder->codeAppendf("half2 duvdx = dFdx(%s);", offsets0.fsIn());
|
||||
fragBuilder->codeAppendf("half2 duvdy = dFdy(%s);", offsets0.fsIn());
|
||||
fragBuilder->codeAppendf(
|
||||
"float2 grad = float2(2.0*%s.x*duvdx.x + 2.0*%s.y*duvdx.y,"
|
||||
" 2.0*%s.x*duvdy.x + 2.0*%s.y*duvdy.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);",
|
||||
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.
|
||||
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) {
|
||||
// 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);");
|
||||
} 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
|
||||
@ -473,14 +473,14 @@ private:
|
||||
fragBuilder->codeAppendf("duvdx = dFdx(%s);", offsets1.fsIn());
|
||||
fragBuilder->codeAppendf("duvdy = dFdy(%s);", offsets1.fsIn());
|
||||
fragBuilder->codeAppendf(
|
||||
"grad = float2(2.0*%s.x*duvdx.x + 2.0*%s.y*duvdx.y,"
|
||||
" 2.0*%s.x*duvdy.x + 2.0*%s.y*duvdy.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);",
|
||||
offsets1.fsIn(), offsets1.fsIn(), offsets1.fsIn(), offsets1.fsIn());
|
||||
fragBuilder->codeAppend("invlen = inversesqrt(dot(grad, grad));");
|
||||
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,
|
||||
|
@ -115,7 +115,7 @@ public:
|
||||
args.fVaryingHandler->addPassThroughAttribute(&textureGP.fColors,
|
||||
args.fOutputColor);
|
||||
}
|
||||
args.fFragBuilder->codeAppend("highp float2 texCoord;");
|
||||
args.fFragBuilder->codeAppend("highfloat2 texCoord;");
|
||||
args.fVaryingHandler->addPassThroughAttribute(&textureGP.fTextureCoords, "texCoord",
|
||||
kHigh_GrSLPrecision);
|
||||
if (textureGP.numTextureSamplers() > 1) {
|
||||
@ -134,7 +134,7 @@ public:
|
||||
args.fFragBuilder->appendTextureLookupAndModulate(args.fOutputColor,
|
||||
args.fTexSamplers[i],
|
||||
"texCoord",
|
||||
kVec2f_GrSLType,
|
||||
kHighFloat2_GrSLType,
|
||||
&fColorSpaceXformHelper);
|
||||
args.fFragBuilder->codeAppend("; break;");
|
||||
}
|
||||
@ -144,11 +144,11 @@ public:
|
||||
args.fFragBuilder->appendTextureLookupAndModulate(args.fOutputColor,
|
||||
args.fTexSamplers[0],
|
||||
"texCoord",
|
||||
kVec2f_GrSLType,
|
||||
kHighFloat2_GrSLType,
|
||||
&fColorSpaceXformHelper);
|
||||
}
|
||||
args.fFragBuilder->codeAppend(";");
|
||||
args.fFragBuilder->codeAppendf("%s = float4(1);", args.fOutputCoverage);
|
||||
args.fFragBuilder->codeAppendf("%s = highfloat4(1);", args.fOutputCoverage);
|
||||
}
|
||||
GrGLSLColorSpaceXformHelper fColorSpaceXformHelper;
|
||||
};
|
||||
|
@ -44,17 +44,17 @@ bool GrVkCopyManager::createCopyProgram(GrVkGpu* gpu) {
|
||||
"#extension GL_ARB_shading_language_420pack : enable\n"
|
||||
|
||||
"layout(set = 0, binding = 0) uniform vertexUniformBuffer {"
|
||||
"mediump float4 uPosXform;"
|
||||
"mediump float4 uTexCoordXform;"
|
||||
"half4 uPosXform;"
|
||||
"half4 uTexCoordXform;"
|
||||
"};"
|
||||
"layout(location = 0) in highp float2 inPosition;"
|
||||
"layout(location = 1) out mediump float2 vTexCoord;"
|
||||
"layout(location = 0) in highfloat2 inPosition;"
|
||||
"layout(location = 1) out half2 vTexCoord;"
|
||||
|
||||
"// Copy Program VS\n"
|
||||
"void main() {"
|
||||
"vTexCoord = inPosition * uTexCoordXform.xy + uTexCoordXform.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_shading_language_420pack : enable\n"
|
||||
|
||||
"precision mediump float;"
|
||||
|
||||
"layout(set = 1, binding = 0) uniform mediump sampler2D uTextureSampler;"
|
||||
"layout(location = 1) in mediump float2 vTexCoord;"
|
||||
"layout(location = 0, index = 0) out mediump float4 fsColorOut;"
|
||||
"layout(set = 1, binding = 0) uniform sampler2D uTextureSampler;"
|
||||
"layout(location = 1) in half2 vTexCoord;"
|
||||
"layout(location = 0, index = 0) out half4 fsColorOut;"
|
||||
|
||||
"// Copy Program FS\n"
|
||||
"void main() {"
|
||||
|
@ -59,7 +59,7 @@ void* GrVkPipelineStateDataManager::getBufferPtrAndMarkDirty(const Uniform& uni)
|
||||
|
||||
void GrVkPipelineStateDataManager::set1i(UniformHandle u, int32_t i) const {
|
||||
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);
|
||||
void* buffer = this->getBufferPtrAndMarkDirty(uni);
|
||||
memcpy(buffer, &i, sizeof(int32_t));
|
||||
@ -69,7 +69,7 @@ void GrVkPipelineStateDataManager::set1iv(UniformHandle u,
|
||||
int arrayCount,
|
||||
const int32_t v[]) const {
|
||||
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 <= 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 {
|
||||
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);
|
||||
void* buffer = this->getBufferPtrAndMarkDirty(uni);
|
||||
SkASSERT(sizeof(float) == 4);
|
||||
@ -96,7 +96,7 @@ void GrVkPipelineStateDataManager::set1fv(UniformHandle u,
|
||||
int arrayCount,
|
||||
const float v[]) const {
|
||||
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 <= 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 {
|
||||
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);
|
||||
void* buffer = this->getBufferPtrAndMarkDirty(uni);
|
||||
SkASSERT(sizeof(float) == 4);
|
||||
@ -124,7 +124,7 @@ void GrVkPipelineStateDataManager::set2fv(UniformHandle u,
|
||||
int arrayCount,
|
||||
const float v[]) const {
|
||||
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 <= 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 {
|
||||
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);
|
||||
void* buffer = this->getBufferPtrAndMarkDirty(uni);
|
||||
SkASSERT(sizeof(float) == 4);
|
||||
@ -152,7 +152,7 @@ void GrVkPipelineStateDataManager::set3fv(UniformHandle u,
|
||||
int arrayCount,
|
||||
const float v[]) const {
|
||||
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 <= uni.fArrayCount ||
|
||||
(1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount));
|
||||
@ -172,7 +172,7 @@ void GrVkPipelineStateDataManager::set4f(UniformHandle u,
|
||||
float v2,
|
||||
float v3) const {
|
||||
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);
|
||||
void* buffer = this->getBufferPtrAndMarkDirty(uni);
|
||||
SkASSERT(sizeof(float) == 4);
|
||||
@ -184,7 +184,7 @@ void GrVkPipelineStateDataManager::set4fv(UniformHandle u,
|
||||
int arrayCount,
|
||||
const float v[]) const {
|
||||
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 <= uni.fArrayCount ||
|
||||
(1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount));
|
||||
@ -230,7 +230,8 @@ template<int N> inline void GrVkPipelineStateDataManager::setMatrices(UniformHan
|
||||
int arrayCount,
|
||||
const float matrices[]) const {
|
||||
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 <= uni.fArrayCount ||
|
||||
(1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount));
|
||||
|
@ -16,31 +16,40 @@
|
||||
// aligned to 16 bytes (i.e. has mask of 0xF).
|
||||
uint32_t grsltype_to_alignment_mask(GrSLType type) {
|
||||
switch(type) {
|
||||
case kShort_GrSLType: // fall through
|
||||
case kInt_GrSLType:
|
||||
return 0x3;
|
||||
case kUShort_GrSLType: // fall through
|
||||
case kUint_GrSLType:
|
||||
return 0x3;
|
||||
case kFloat_GrSLType:
|
||||
case kHalf_GrSLType: // fall through
|
||||
case kHighFloat_GrSLType:
|
||||
return 0x3;
|
||||
case kVec2f_GrSLType:
|
||||
case kHalf2_GrSLType: // fall through
|
||||
case kHighFloat2_GrSLType:
|
||||
return 0x7;
|
||||
case kVec3f_GrSLType:
|
||||
case kHalf3_GrSLType: // fall through
|
||||
case kHighFloat3_GrSLType:
|
||||
return 0xF;
|
||||
case kVec4f_GrSLType:
|
||||
case kHalf4_GrSLType: // fall through
|
||||
case kHighFloat4_GrSLType:
|
||||
return 0xF;
|
||||
case kVec2us_GrSLType:
|
||||
case kUint2_GrSLType:
|
||||
return 0x3;
|
||||
case kVec2i_GrSLType:
|
||||
case kInt2_GrSLType:
|
||||
return 0x7;
|
||||
case kVec3i_GrSLType:
|
||||
case kInt3_GrSLType:
|
||||
return 0xF;
|
||||
case kVec4i_GrSLType:
|
||||
case kInt4_GrSLType:
|
||||
return 0xF;
|
||||
case kMat22f_GrSLType:
|
||||
case kHalf2x2_GrSLType: // fall through
|
||||
case kHighFloat2x2_GrSLType:
|
||||
return 0x7;
|
||||
case kMat33f_GrSLType:
|
||||
case kHalf3x3_GrSLType: // fall through
|
||||
case kHighFloat3x3_GrSLType:
|
||||
return 0xF;
|
||||
case kMat44f_GrSLType:
|
||||
case kHalf4x4_GrSLType: // fall through
|
||||
case kHighFloat4x4_GrSLType:
|
||||
return 0xF;
|
||||
|
||||
// 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. */
|
||||
static inline uint32_t grsltype_to_vk_size(GrSLType type) {
|
||||
switch(type) {
|
||||
case kShort_GrSLType: // fall through
|
||||
case kInt_GrSLType:
|
||||
return sizeof(int32_t);
|
||||
case kUShort_GrSLType: // fall through
|
||||
case kUint_GrSLType:
|
||||
return sizeof(int32_t);
|
||||
case kFloat_GrSLType:
|
||||
case kHalf_GrSLType: // fall through
|
||||
case kHighFloat_GrSLType:
|
||||
return sizeof(float);
|
||||
case kVec2f_GrSLType:
|
||||
case kHalf2_GrSLType: // fall through
|
||||
case kHighFloat2_GrSLType:
|
||||
return 2 * sizeof(float);
|
||||
case kVec3f_GrSLType:
|
||||
case kHalf3_GrSLType: // fall through
|
||||
case kHighFloat3_GrSLType:
|
||||
return 3 * sizeof(float);
|
||||
case kVec4f_GrSLType:
|
||||
case kHalf4_GrSLType: // fall through
|
||||
case kHighFloat4_GrSLType:
|
||||
return 4 * sizeof(float);
|
||||
case kVec2us_GrSLType:
|
||||
case kUint2_GrSLType:
|
||||
return 2 * sizeof(uint16_t);
|
||||
case kVec2i_GrSLType:
|
||||
case kInt2_GrSLType:
|
||||
return 2 * sizeof(int32_t);
|
||||
case kVec3i_GrSLType:
|
||||
case kInt3_GrSLType:
|
||||
return 3 * sizeof(int32_t);
|
||||
case kVec4i_GrSLType:
|
||||
case kInt4_GrSLType:
|
||||
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.
|
||||
return 8 * sizeof(float);
|
||||
case kMat33f_GrSLType:
|
||||
case kHalf3x3_GrSLType: // fall through
|
||||
case kHighFloat3x3_GrSLType:
|
||||
return 12 * sizeof(float);
|
||||
case kMat44f_GrSLType:
|
||||
case kHalf4x4_GrSLType: // fall through
|
||||
case kHighFloat4x4_GrSLType:
|
||||
return 16 * sizeof(float);
|
||||
|
||||
// This query is only valid for certain types.
|
||||
@ -122,7 +140,7 @@ void get_ubo_aligned_offset(uint32_t* uniformOffset,
|
||||
int arrayCount) {
|
||||
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.
|
||||
if (arrayCount || type == kMat22f_GrSLType) {
|
||||
if (arrayCount || type == kHighFloat2x2_GrSLType) {
|
||||
alignmentMask = 0xF;
|
||||
}
|
||||
uint32_t offsetDiff = *currentOffset & alignmentMask;
|
||||
|
@ -13,27 +13,34 @@ static inline int grsltype_to_location_size(GrSLType type) {
|
||||
switch(type) {
|
||||
case kVoid_GrSLType:
|
||||
return 0;
|
||||
case kFloat_GrSLType:
|
||||
case kHighFloat_GrSLType: // fall through
|
||||
case kHalf_GrSLType:
|
||||
return 1;
|
||||
case kVec2f_GrSLType:
|
||||
case kHighFloat2_GrSLType: // fall through
|
||||
case kHalf2_GrSLType:
|
||||
return 1;
|
||||
case kVec3f_GrSLType:
|
||||
case kHighFloat3_GrSLType:
|
||||
case kHalf3_GrSLType:
|
||||
return 1;
|
||||
case kVec4f_GrSLType:
|
||||
case kHighFloat4_GrSLType:
|
||||
case kHalf4_GrSLType:
|
||||
return 1;
|
||||
case kVec2us_GrSLType:
|
||||
case kUint2_GrSLType:
|
||||
return 1;
|
||||
case kVec2i_GrSLType:
|
||||
case kInt2_GrSLType:
|
||||
return 1;
|
||||
case kVec3i_GrSLType:
|
||||
case kInt3_GrSLType:
|
||||
return 1;
|
||||
case kVec4i_GrSLType:
|
||||
case kInt4_GrSLType:
|
||||
return 1;
|
||||
case kMat22f_GrSLType:
|
||||
case kHighFloat2x2_GrSLType:
|
||||
case kHalf2x2_GrSLType:
|
||||
return 2;
|
||||
case kMat33f_GrSLType:
|
||||
case kHighFloat3x3_GrSLType:
|
||||
case kHalf3x3_GrSLType:
|
||||
return 3;
|
||||
case kMat44f_GrSLType:
|
||||
case kHighFloat4x4_GrSLType:
|
||||
case kHalf4x4_GrSLType:
|
||||
return 4;
|
||||
case kTexture2DSampler_GrSLType:
|
||||
return 0;
|
||||
@ -47,9 +54,11 @@ static inline int grsltype_to_location_size(GrSLType type) {
|
||||
return 0;
|
||||
case kBool_GrSLType:
|
||||
return 1;
|
||||
case kInt_GrSLType:
|
||||
case kInt_GrSLType: // fall through
|
||||
case kShort_GrSLType:
|
||||
return 1;
|
||||
case kUint_GrSLType:
|
||||
case kUShort_GrSLType: // fall through
|
||||
return 1;
|
||||
case kTexture2D_GrSLType:
|
||||
return 0;
|
||||
|
@ -816,15 +816,13 @@ void GrGLPerlinNoise::emitCode(EmitArgs& args) {
|
||||
GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
|
||||
SkString vCoords = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
|
||||
|
||||
fBaseFrequencyUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kVec2f_GrSLType, kDefault_GrSLPrecision,
|
||||
fBaseFrequencyUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType,
|
||||
"baseFrequency");
|
||||
const char* baseFrequencyUni = uniformHandler->getUniformCStr(fBaseFrequencyUni);
|
||||
|
||||
const char* stitchDataUni = nullptr;
|
||||
if (pne.stitchTiles()) {
|
||||
fStitchDataUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kVec2f_GrSLType, kDefault_GrSLPrecision,
|
||||
fStitchDataUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType,
|
||||
"stitchData");
|
||||
stitchDataUni = uniformHandler->getUniformCStr(fStitchDataUni);
|
||||
}
|
||||
@ -849,29 +847,29 @@ void GrGLPerlinNoise::emitCode(EmitArgs& args) {
|
||||
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
|
||||
// [-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
|
||||
static const GrShaderVar gPerlinNoiseArgs[] = {
|
||||
GrShaderVar(chanCoord, kFloat_GrSLType),
|
||||
GrShaderVar(noiseVec, kVec2f_GrSLType)
|
||||
GrShaderVar(chanCoord, kHalf_GrSLType),
|
||||
GrShaderVar(noiseVec, kHalf2_GrSLType)
|
||||
};
|
||||
|
||||
static const GrShaderVar gPerlinNoiseStitchArgs[] = {
|
||||
GrShaderVar(chanCoord, kFloat_GrSLType),
|
||||
GrShaderVar(noiseVec, kVec2f_GrSLType),
|
||||
GrShaderVar(stitchData, kVec2f_GrSLType)
|
||||
GrShaderVar(chanCoord, kHalf_GrSLType),
|
||||
GrShaderVar(noiseVec, kHalf2_GrSLType),
|
||||
GrShaderVar(stitchData, kHalf2_GrSLType)
|
||||
};
|
||||
|
||||
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.zw = %s.xy + float2(1.0);\n", floorVal, floorVal);
|
||||
noiseCode.appendf("\tfloat2 %s = fract(%s);\n", fractVal, noiseVec);
|
||||
noiseCode.appendf("\t%s.zw = %s.xy + half2(1.0);\n", floorVal, floorVal);
|
||||
noiseCode.appendf("\thalf2 %s = fract(%s);\n", fractVal, noiseVec);
|
||||
|
||||
// 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);
|
||||
|
||||
// Adjust frequencies if we're stitching tiles
|
||||
@ -887,28 +885,28 @@ void GrGLPerlinNoise::emitCode(EmitArgs& args) {
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
// Get permutation for x
|
||||
{
|
||||
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(),
|
||||
kVec2f_GrSLType);
|
||||
kHalf2_GrSLType);
|
||||
noiseCode.append(".r;");
|
||||
}
|
||||
|
||||
// Get permutation for x + 1
|
||||
{
|
||||
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);
|
||||
fragBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[0], xCoords.c_str(),
|
||||
kVec2f_GrSLType);
|
||||
kHalf2_GrSLType);
|
||||
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
|
||||
// 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).
|
||||
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);
|
||||
#endif
|
||||
|
||||
// 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)
|
||||
{
|
||||
SkString latticeCoords("");
|
||||
latticeCoords.appendf("float2(%s.x, %s)", bcoords, chanCoord);
|
||||
noiseCode.appendf("\n\tfloat4 %s = ", lattice);
|
||||
latticeCoords.appendf("half2(%s.x, %s)", bcoords, chanCoord);
|
||||
noiseCode.appendf("\n\thalf4 %s = ", lattice);
|
||||
fragBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(),
|
||||
kVec2f_GrSLType);
|
||||
kHalf2_GrSLType);
|
||||
noiseCode.appendf(".bgra;\n\t%s.x = ", uv);
|
||||
noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
|
||||
}
|
||||
@ -942,26 +940,26 @@ void GrGLPerlinNoise::emitCode(EmitArgs& args) {
|
||||
// Compute v, at offset (-1,0)
|
||||
{
|
||||
SkString latticeCoords("");
|
||||
latticeCoords.appendf("float2(%s.y, %s)", bcoords, chanCoord);
|
||||
latticeCoords.appendf("half2(%s.y, %s)", bcoords, chanCoord);
|
||||
noiseCode.append("\n\tlattice = ");
|
||||
fragBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(),
|
||||
kVec2f_GrSLType);
|
||||
kHalf2_GrSLType);
|
||||
noiseCode.appendf(".bgra;\n\t%s.y = ", uv);
|
||||
noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
|
||||
}
|
||||
|
||||
// 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.y -= 1.0;", fractVal);
|
||||
// Compute v, at offset (-1,-1)
|
||||
{
|
||||
SkString latticeCoords("");
|
||||
latticeCoords.appendf("float2(%s.w, %s)", bcoords, chanCoord);
|
||||
latticeCoords.appendf("half2(%s.w, %s)", bcoords, chanCoord);
|
||||
noiseCode.append("\n\tlattice = ");
|
||||
fragBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(),
|
||||
kVec2f_GrSLType);
|
||||
kHalf2_GrSLType);
|
||||
noiseCode.appendf(".bgra;\n\t%s.y = ", uv);
|
||||
noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
|
||||
}
|
||||
@ -970,10 +968,10 @@ void GrGLPerlinNoise::emitCode(EmitArgs& args) {
|
||||
// Compute u, at offset (0,-1)
|
||||
{
|
||||
SkString latticeCoords("");
|
||||
latticeCoords.appendf("float2(%s.z, %s)", bcoords, chanCoord);
|
||||
latticeCoords.appendf("half2(%s.z, %s)", bcoords, chanCoord);
|
||||
noiseCode.append("\n\tlattice = ");
|
||||
fragBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(),
|
||||
kVec2f_GrSLType);
|
||||
kHalf2_GrSLType);
|
||||
noiseCode.appendf(".bgra;\n\t%s.x = ", uv);
|
||||
noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
|
||||
}
|
||||
@ -985,28 +983,28 @@ void GrGLPerlinNoise::emitCode(EmitArgs& args) {
|
||||
|
||||
SkString noiseFuncName;
|
||||
if (pne.stitchTiles()) {
|
||||
fragBuilder->emitFunction(kFloat_GrSLType,
|
||||
fragBuilder->emitFunction(kHalf_GrSLType,
|
||||
"perlinnoise", SK_ARRAY_COUNT(gPerlinNoiseStitchArgs),
|
||||
gPerlinNoiseStitchArgs, noiseCode.c_str(), &noiseFuncName);
|
||||
} else {
|
||||
fragBuilder->emitFunction(kFloat_GrSLType,
|
||||
fragBuilder->emitFunction(kHalf_GrSLType,
|
||||
"perlinnoise", SK_ARRAY_COUNT(gPerlinNoiseArgs),
|
||||
gPerlinNoiseArgs, noiseCode.c_str(), &noiseFuncName);
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
// 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()) {
|
||||
// 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
|
||||
fragBuilder->codeAppendf("for (int octave = 0; octave < %d; ++octave) {", pne.numOctaves());
|
||||
@ -1017,7 +1015,7 @@ void GrGLPerlinNoise::emitCode(EmitArgs& args) {
|
||||
}
|
||||
if (pne.stitchTiles()) {
|
||||
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))",
|
||||
noiseFuncName.c_str(), chanCoordR, noiseVec, stitchData,
|
||||
noiseFuncName.c_str(), chanCoordG, noiseVec, stitchData,
|
||||
@ -1025,7 +1023,7 @@ void GrGLPerlinNoise::emitCode(EmitArgs& args) {
|
||||
noiseFuncName.c_str(), chanCoordA, noiseVec, stitchData);
|
||||
} else {
|
||||
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))",
|
||||
noiseFuncName.c_str(), chanCoordR, noiseVec,
|
||||
noiseFuncName.c_str(), chanCoordG, noiseVec,
|
||||
@ -1037,18 +1035,18 @@ void GrGLPerlinNoise::emitCode(EmitArgs& args) {
|
||||
}
|
||||
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);
|
||||
|
||||
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
|
||||
|
||||
if (pne.type() == SkPerlinNoiseShaderImpl::kFractalNoise_Type) {
|
||||
// The value of turbulenceFunctionResult comes from ((turbulenceFunctionResult) + 1) / 2
|
||||
// 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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
// 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);
|
||||
}
|
||||
@ -1235,133 +1233,130 @@ void GrGLImprovedPerlinNoise::emitCode(EmitArgs& args) {
|
||||
GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
|
||||
SkString vCoords = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
|
||||
|
||||
fBaseFrequencyUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kVec2f_GrSLType, kDefault_GrSLPrecision,
|
||||
fBaseFrequencyUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType,
|
||||
"baseFrequency");
|
||||
const char* baseFrequencyUni = uniformHandler->getUniformCStr(fBaseFrequencyUni);
|
||||
|
||||
fZUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kFloat_GrSLType, kDefault_GrSLPrecision,
|
||||
"z");
|
||||
fZUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType, "z");
|
||||
const char* zUni = uniformHandler->getUniformCStr(fZUni);
|
||||
|
||||
// fade function
|
||||
static const GrShaderVar fadeArgs[] = {
|
||||
GrShaderVar("t", kVec3f_GrSLType)
|
||||
GrShaderVar("t", kHalf3_GrSLType)
|
||||
};
|
||||
SkString fadeFuncName;
|
||||
fragBuilder->emitFunction(kVec3f_GrSLType, "fade", SK_ARRAY_COUNT(fadeArgs),
|
||||
fragBuilder->emitFunction(kHalf3_GrSLType, "fade", SK_ARRAY_COUNT(fadeArgs),
|
||||
fadeArgs,
|
||||
"return t * t * t * (t * (t * 6.0 - 15.0) + 10.0);",
|
||||
&fadeFuncName);
|
||||
|
||||
// perm function
|
||||
static const GrShaderVar permArgs[] = {
|
||||
GrShaderVar("x", kFloat_GrSLType)
|
||||
GrShaderVar("x", kHalf_GrSLType)
|
||||
};
|
||||
SkString permFuncName;
|
||||
SkString permCode("return ");
|
||||
// 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.
|
||||
fragBuilder->appendTextureLookup(&permCode, args.fTexSamplers[0], "float2(fract(x / 256.0), 0.0)",
|
||||
kVec2f_GrSLType);
|
||||
fragBuilder->appendTextureLookup(&permCode, args.fTexSamplers[0], "highfloat2(fract(x / 256.0), 0.0)",
|
||||
kHalf2_GrSLType);
|
||||
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);
|
||||
|
||||
// grad function
|
||||
static const GrShaderVar gradArgs[] = {
|
||||
GrShaderVar("x", kFloat_GrSLType),
|
||||
GrShaderVar("p", kVec3f_GrSLType)
|
||||
GrShaderVar("x", kHalf_GrSLType),
|
||||
GrShaderVar("p", kHalf3_GrSLType)
|
||||
};
|
||||
SkString gradFuncName;
|
||||
SkString gradCode("return dot(");
|
||||
fragBuilder->appendTextureLookup(&gradCode, args.fTexSamplers[1], "float2(fract(x / 16.0), 0.0)",
|
||||
kVec2f_GrSLType);
|
||||
gradCode.append(".rgb * 255.0 - float3(1.0), p);");
|
||||
fragBuilder->emitFunction(kFloat_GrSLType, "grad", SK_ARRAY_COUNT(gradArgs), gradArgs,
|
||||
fragBuilder->appendTextureLookup(&gradCode, args.fTexSamplers[1], "highfloat2(fract(x / 16.0), 0.0)",
|
||||
kHalf2_GrSLType);
|
||||
gradCode.append(".rgb * 255.0 - highfloat3(1.0), p);");
|
||||
fragBuilder->emitFunction(kHalf_GrSLType, "grad", SK_ARRAY_COUNT(gradArgs), gradArgs,
|
||||
gradCode.c_str(), &gradFuncName);
|
||||
|
||||
// lerp function
|
||||
static const GrShaderVar lerpArgs[] = {
|
||||
GrShaderVar("a", kFloat_GrSLType),
|
||||
GrShaderVar("b", kFloat_GrSLType),
|
||||
GrShaderVar("w", kFloat_GrSLType)
|
||||
GrShaderVar("a", kHalf_GrSLType),
|
||||
GrShaderVar("b", kHalf_GrSLType),
|
||||
GrShaderVar("w", kHalf_GrSLType)
|
||||
};
|
||||
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);
|
||||
|
||||
// noise function
|
||||
static const GrShaderVar noiseArgs[] = {
|
||||
GrShaderVar("p", kVec3f_GrSLType),
|
||||
GrShaderVar("p", kHalf3_GrSLType),
|
||||
};
|
||||
SkString noiseFuncName;
|
||||
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.appendf("float3 f = %s(p);", fadeFuncName.c_str());
|
||||
noiseCode.appendf("float A = %s(P.x) + P.y;", permFuncName.c_str());
|
||||
noiseCode.appendf("float AA = %s(A) + P.z;", permFuncName.c_str());
|
||||
noiseCode.appendf("float 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("float BA = %s(B) + P.z;", permFuncName.c_str());
|
||||
noiseCode.appendf("float BB = %s(B + 1.0) + P.z;", permFuncName.c_str());
|
||||
noiseCode.appendf("float result = %s(", lerpFuncName.c_str());
|
||||
noiseCode.appendf("half3 f = %s(p);", fadeFuncName.c_str());
|
||||
noiseCode.appendf("half A = %s(P.x) + P.y;", permFuncName.c_str());
|
||||
noiseCode.appendf("half AA = %s(A) + P.z;", permFuncName.c_str());
|
||||
noiseCode.appendf("half AB = %s(A + 1.0) + P.z;", permFuncName.c_str());
|
||||
noiseCode.appendf("half B = %s(P.x + 1.0) + P.y;", permFuncName.c_str());
|
||||
noiseCode.appendf("half BA = %s(B) + P.z;", permFuncName.c_str());
|
||||
noiseCode.appendf("half BB = %s(B + 1.0) + P.z;", permFuncName.c_str());
|
||||
noiseCode.appendf("half result = %s(", lerpFuncName.c_str());
|
||||
noiseCode.appendf("%s(%s(%s(%s(AA), p),", lerpFuncName.c_str(), lerpFuncName.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());
|
||||
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());
|
||||
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());
|
||||
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(),
|
||||
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());
|
||||
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());
|
||||
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());
|
||||
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);
|
||||
|
||||
// noiseOctaves function
|
||||
static const GrShaderVar noiseOctavesArgs[] = {
|
||||
GrShaderVar("p", kVec3f_GrSLType)
|
||||
GrShaderVar("p", kHalf3_GrSLType)
|
||||
};
|
||||
SkString noiseOctavesFuncName;
|
||||
SkString noiseOctavesCode;
|
||||
noiseOctavesCode.append("float result = 0.0;");
|
||||
noiseOctavesCode.append("float ratio = 1.0;");
|
||||
noiseOctavesCode.appendf("for (float i = 0.0; i < %d; i++) {", pne.octaves());
|
||||
noiseOctavesCode.append("half result = 0.0;");
|
||||
noiseOctavesCode.append("half ratio = 1.0;");
|
||||
noiseOctavesCode.appendf("for (half i = 0.0; i < %d; i++) {", pne.octaves());
|
||||
noiseOctavesCode.appendf("result += %s(p) / ratio;", noiseFuncName.c_str());
|
||||
noiseOctavesCode.append("p *= 2.0;");
|
||||
noiseOctavesCode.append("ratio *= 2.0;");
|
||||
noiseOctavesCode.append("}");
|
||||
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);
|
||||
|
||||
fragBuilder->codeAppendf("float2 coords = %s * %s;", vCoords.c_str(), baseFrequencyUni);
|
||||
fragBuilder->codeAppendf("float r = %s(float3(coords, %s));", noiseOctavesFuncName.c_str(),
|
||||
fragBuilder->codeAppendf("half2 coords = %s * %s;", vCoords.c_str(), baseFrequencyUni);
|
||||
fragBuilder->codeAppendf("half r = %s(half3(coords, %s));", noiseOctavesFuncName.c_str(),
|
||||
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);
|
||||
fragBuilder->codeAppendf("float b = %s(float3(coords, %s + 0000.0));",
|
||||
fragBuilder->codeAppendf("half b = %s(half3(coords, %s + 0000.0));",
|
||||
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);
|
||||
fragBuilder->codeAppendf("%s = float4(r, g, b, a);", args.fOutputColor);
|
||||
fragBuilder->codeAppendf("%s = half4(r, g, b, a);", args.fOutputColor);
|
||||
|
||||
// Clamp values
|
||||
fragBuilder->codeAppendf("%s = clamp(%s, 0.0, 1.0);", args.fOutputColor, args.fOutputColor);
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
@ -1355,17 +1355,15 @@ void GrGradientEffect::GLSLProcessor::emitUniforms(GrGLSLUniformHandler* uniform
|
||||
const GrGradientEffect& ge) {
|
||||
if (int colorCount = color_type_to_color_count(ge.getColorType())) {
|
||||
fColorsUni = uniformHandler->addUniformArray(kFragment_GrShaderFlag,
|
||||
kVec4f_GrSLType,
|
||||
kDefault_GrSLPrecision,
|
||||
kHalf4_GrSLType,
|
||||
"Colors",
|
||||
colorCount);
|
||||
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");
|
||||
}
|
||||
} else {
|
||||
fFSYUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kFloat_GrSLType, kDefault_GrSLPrecision,
|
||||
fFSYUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType,
|
||||
"GradientYCoordFS");
|
||||
}
|
||||
}
|
||||
@ -1557,14 +1555,14 @@ void GrGradientEffect::GLSLProcessor::emitAnalyticalColor(GrGLSLFPFragmentBuilde
|
||||
// First, apply tiling rules.
|
||||
switch (ge.fWrapMode) {
|
||||
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;
|
||||
case GrSamplerState::WrapMode::kRepeat:
|
||||
fragBuilder->codeAppendf("float clamp_t = fract(%s);", t);
|
||||
fragBuilder->codeAppendf("half clamp_t = fract(%s);", t);
|
||||
break;
|
||||
case GrSamplerState::WrapMode::kMirrorRepeat:
|
||||
fragBuilder->codeAppendf("float 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 t_1 = %s - 1.0;", t);
|
||||
fragBuilder->codeAppendf("half clamp_t = abs(t_1 - 2.0 * floor(t_1 * 0.5) - 1.0);");
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1575,8 +1573,8 @@ void GrGradientEffect::GLSLProcessor::emitAnalyticalColor(GrGLSLFPFragmentBuilde
|
||||
// (t, 1/t, 1/(1-t), t/(1-t))
|
||||
const char* stopT = uniformHandler->getUniformCStr(fExtraStopT);
|
||||
|
||||
fragBuilder->codeAppend ("float4 start, end;");
|
||||
fragBuilder->codeAppend ("float relative_t;");
|
||||
fragBuilder->codeAppend ("half4 start, end;");
|
||||
fragBuilder->codeAppend ("half relative_t;");
|
||||
fragBuilder->codeAppendf("if (clamp_t < %s.x) {", stopT);
|
||||
fragBuilder->codeAppendf(" start = %s[0];", 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
|
||||
fragBuilder->codeAppendf(" relative_t = (clamp_t * %s.z) - %s.w;", stopT, stopT);
|
||||
fragBuilder->codeAppend ("}");
|
||||
fragBuilder->codeAppend ("float4 colorTemp = mix(start, end, relative_t);");
|
||||
fragBuilder->codeAppend ("half4 colorTemp = mix(start, end, relative_t);");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
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);
|
||||
if (GrSamplerState::WrapMode::kClamp == ge.fWrapMode) {
|
||||
fragBuilder->codeAppendf("if (%s < 0.0) {", t);
|
||||
@ -1605,7 +1603,7 @@ void GrGradientEffect::GLSLProcessor::emitAnalyticalColor(GrGLSLFPFragmentBuilde
|
||||
}
|
||||
|
||||
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);
|
||||
if (GrSamplerState::WrapMode::kClamp == ge.fWrapMode) {
|
||||
fragBuilder->codeAppendf("if (%s > 1.0) {", t);
|
||||
@ -1617,7 +1615,7 @@ void GrGradientEffect::GLSLProcessor::emitAnalyticalColor(GrGLSLFPFragmentBuilde
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
break;
|
||||
@ -1627,8 +1625,8 @@ void GrGradientEffect::GLSLProcessor::emitAnalyticalColor(GrGLSLFPFragmentBuilde
|
||||
// (t, 1/t, 1/(1-t), t/(1-t))
|
||||
const char* stopT = uniformHandler->getUniformCStr(fExtraStopT);
|
||||
|
||||
fragBuilder->codeAppend("float4 start, end;");
|
||||
fragBuilder->codeAppend("float relative_t;");
|
||||
fragBuilder->codeAppend("half4 start, end;");
|
||||
fragBuilder->codeAppend("half relative_t;");
|
||||
fragBuilder->codeAppendf("if (clamp_t < %s.x) {", stopT);
|
||||
fragBuilder->codeAppendf(" start = %s[0];", 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
|
||||
fragBuilder->codeAppendf(" relative_t = (clamp_t * %s.z) - %s.w;", stopT, stopT);
|
||||
fragBuilder->codeAppend("}");
|
||||
fragBuilder->codeAppend("float4 colorTemp = mix(start, end, relative_t);");
|
||||
fragBuilder->codeAppend("half4 colorTemp = mix(start, end, relative_t);");
|
||||
|
||||
break;
|
||||
}
|
||||
@ -1683,10 +1681,10 @@ void GrGradientEffect::GLSLProcessor::emitColor(GrGLSLFPFragmentBuilder* fragBui
|
||||
|
||||
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->appendTextureLookupAndModulate(inputColor, texSamplers[0], "coord",
|
||||
kVec2f_GrSLType, &fColorSpaceHelper);
|
||||
kHighFloat2_GrSLType, &fColorSpaceHelper);
|
||||
fragBuilder->codeAppend(";");
|
||||
}
|
||||
|
||||
|
@ -198,8 +198,8 @@ void GrSweepGradient::GLSLSweepProcessor::emitCode(EmitArgs& args) {
|
||||
const GrSweepGradient& ge = args.fFp.cast<GrSweepGradient>();
|
||||
GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
|
||||
this->emitUniforms(uniformHandler, ge);
|
||||
fTBiasScaleUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kVec2f_GrSLType,
|
||||
kDefault_GrSLPrecision, "SweepFSParams");
|
||||
fTBiasScaleUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType,
|
||||
"SweepFSParams");
|
||||
const char* tBiasScaleV = uniformHandler->getUniformCStr(fTBiasScaleUni);
|
||||
|
||||
const SkString coords2D = args.fFragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
|
||||
|
@ -235,8 +235,7 @@ void Edge2PtConicalEffect::GLSLEdge2PtConicalProcessor::emitCode(EmitArgs& args)
|
||||
const Edge2PtConicalEffect& ge = args.fFp.cast<Edge2PtConicalEffect>();
|
||||
GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
|
||||
this->emitUniforms(uniformHandler, ge);
|
||||
fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kVec3f_GrSLType, kDefault_GrSLPrecision,
|
||||
fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf3_GrSLType,
|
||||
"Conical2FSParams");
|
||||
|
||||
SkString cName("c");
|
||||
@ -255,8 +254,8 @@ void Edge2PtConicalEffect::GLSLEdge2PtConicalProcessor::emitCode(EmitArgs& args)
|
||||
const char* coords2D;
|
||||
SkString bVar;
|
||||
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
|
||||
if (kVec3f_GrSLType == args.fTransformedCoords[0].getType()) {
|
||||
fragBuilder->codeAppendf("\tfloat3 interpolants = float3(%s.xy / %s.z, %s.x / %s.z);\n",
|
||||
if (kHalf3_GrSLType == args.fTransformedCoords[0].getType()) {
|
||||
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[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
|
||||
// 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]
|
||||
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());
|
||||
|
||||
// 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());
|
||||
|
||||
// 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>();
|
||||
GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
|
||||
this->emitUniforms(uniformHandler, ge);
|
||||
fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kVec2f_GrSLType, kDefault_GrSLPrecision,
|
||||
fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType,
|
||||
"Conical2FSParams");
|
||||
SkString tName("t");
|
||||
SkString p0; // focalX
|
||||
@ -544,19 +542,19 @@ void FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor::emitCode
|
||||
|
||||
// output will default to transparent black (we simply won't write anything
|
||||
// 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("\tfloat ys = %s.y * %s.y;\n", coords2D, coords2D);
|
||||
fragBuilder->codeAppendf("\tfloat d = xs + %s * ys;\n", p1.c_str());
|
||||
fragBuilder->codeAppendf("\thalf xs = %s.x * %s.x;\n", coords2D, coords2D);
|
||||
fragBuilder->codeAppendf("\thalf ys = %s.y * %s.y;\n", coords2D, coords2D);
|
||||
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)
|
||||
// If so we must also flip sign on sqrt
|
||||
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());
|
||||
} 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());
|
||||
}
|
||||
|
||||
@ -734,8 +732,7 @@ void FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor::emitCode(E
|
||||
const FocalInside2PtConicalEffect& ge = args.fFp.cast<FocalInside2PtConicalEffect>();
|
||||
GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
|
||||
this->emitUniforms(uniformHandler, ge);
|
||||
fFocalUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kFloat_GrSLType, kDefault_GrSLPrecision,
|
||||
fFocalUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType,
|
||||
"Conical2FSParams");
|
||||
SkString tName("t");
|
||||
|
||||
@ -749,7 +746,7 @@ void FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor::emitCode(E
|
||||
const char* coords2D = coords2DString.c_str();
|
||||
|
||||
// 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);
|
||||
|
||||
this->emitColor(fragBuilder,
|
||||
@ -993,11 +990,9 @@ void CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor::emitCode
|
||||
const CircleInside2PtConicalEffect& ge = args.fFp.cast<CircleInside2PtConicalEffect>();
|
||||
GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
|
||||
this->emitUniforms(uniformHandler, ge);
|
||||
fCenterUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kVec2f_GrSLType, kDefault_GrSLPrecision,
|
||||
fCenterUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType,
|
||||
"Conical2FSCenter");
|
||||
fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kVec3f_GrSLType, kDefault_GrSLPrecision,
|
||||
fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf3_GrSLType,
|
||||
"Conical2FSParams");
|
||||
SkString tName("t");
|
||||
|
||||
@ -1020,10 +1015,10 @@ void CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor::emitCode
|
||||
// C = 1 / A
|
||||
// d = dot(e, p) + B
|
||||
// t = d +/- sqrt(d^2 - A * dot(p, p) + C)
|
||||
fragBuilder->codeAppendf("\tfloat pDotp = dot(%s, %s);\n", coords2D, coords2D);
|
||||
fragBuilder->codeAppendf("\tfloat d = dot(%s, %s) + %s.y;\n", coords2D, center.c_str(),
|
||||
fragBuilder->codeAppendf("\thalf pDotp = dot(%s, %s);\n", coords2D, coords2D);
|
||||
fragBuilder->codeAppendf("\thalf d = dot(%s, %s) + %s.y;\n", coords2D, center.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());
|
||||
|
||||
this->emitColor(fragBuilder,
|
||||
@ -1241,11 +1236,9 @@ void CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor::emitCo
|
||||
const CircleOutside2PtConicalEffect& ge = args.fFp.cast<CircleOutside2PtConicalEffect>();
|
||||
GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
|
||||
this->emitUniforms(uniformHandler, ge);
|
||||
fCenterUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kVec2f_GrSLType, kDefault_GrSLPrecision,
|
||||
fCenterUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType,
|
||||
"Conical2FSCenter");
|
||||
fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kVec4f_GrSLType, kDefault_GrSLPrecision,
|
||||
fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType,
|
||||
"Conical2FSParams");
|
||||
SkString tName("t");
|
||||
|
||||
@ -1262,7 +1255,7 @@ void CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor::emitCo
|
||||
|
||||
// output will default to transparent black (we simply won't write anything
|
||||
// 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
|
||||
// e = center end
|
||||
@ -1273,18 +1266,18 @@ void CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor::emitCo
|
||||
// d = dot(e, p) + B
|
||||
// t = d +/- sqrt(d^2 - A * dot(p, p) + C)
|
||||
|
||||
fragBuilder->codeAppendf("\tfloat pDotp = dot(%s, %s);\n", coords2D, coords2D);
|
||||
fragBuilder->codeAppendf("\tfloat d = dot(%s, %s) + %s.y;\n", coords2D, center.c_str(),
|
||||
fragBuilder->codeAppendf("\thalf pDotp = dot(%s, %s);\n", coords2D, coords2D);
|
||||
fragBuilder->codeAppendf("\thalf d = dot(%s, %s) + %s.y;\n", coords2D, center.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());
|
||||
|
||||
// Must check to see if we flipped the circle order (to make sure start radius < end radius)
|
||||
// If so we must also flip sign on sqrt
|
||||
if (!fIsFlipped) {
|
||||
fragBuilder->codeAppendf("\tfloat %s = d + sqrt(deter);\n", tName.c_str());
|
||||
fragBuilder->codeAppendf("\thalf %s = d + sqrt(deter);\n", tName.c_str());
|
||||
} 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",
|
||||
|
@ -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); }
|
||||
|
||||
#define half2 float2
|
||||
|
||||
#endif
|
||||
|
@ -51,16 +51,14 @@ void CPPCodeGenerator::writef(const char* s, ...) {
|
||||
void CPPCodeGenerator::writeHeader() {
|
||||
}
|
||||
|
||||
void CPPCodeGenerator::writePrecisionModifier() {
|
||||
bool CPPCodeGenerator::usesPrecisionModifiers() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
void CPPCodeGenerator::writeType(const Type& type) {
|
||||
if (type.kind() == Type::kStruct_Kind) {
|
||||
INHERITED::writeType(type);
|
||||
} else {
|
||||
this->write(type.fName);
|
||||
}
|
||||
String CPPCodeGenerator::getTypeName(const Type& type) {
|
||||
return type.name();
|
||||
}
|
||||
|
||||
void CPPCodeGenerator::writeBinaryExpression(const BinaryExpression& b,
|
||||
Precedence parentPrecedence) {
|
||||
if (b.fOperator == Token::PERCENT) {
|
||||
@ -117,19 +115,16 @@ void CPPCodeGenerator::writeIndexExpression(const IndexExpression& i) {
|
||||
INHERITED::writeIndexExpression(i);
|
||||
}
|
||||
|
||||
static const char* default_value(const Type& type) {
|
||||
if (type.fName == "float") {
|
||||
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") {
|
||||
static String default_value(const Type& type) {
|
||||
if (type.fName == "colorSpaceXform") {
|
||||
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) {
|
||||
@ -140,7 +135,7 @@ static bool is_private(const Variable& var) {
|
||||
}
|
||||
|
||||
void CPPCodeGenerator::writeRuntimeValue(const Type& type, const String& cppCode) {
|
||||
if (type == *fContext.fFloat_Type) {
|
||||
if (type.isFloat()) {
|
||||
this->write("%f");
|
||||
fFormatArgs.push_back(cppCode);
|
||||
} 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) {
|
||||
this->write("%s");
|
||||
fFormatArgs.push_back("(" + cppCode + " ? \"true\" : \"false\")");
|
||||
} else if (type == *fContext.fFloat2_Type) {
|
||||
this->write("float2(%f, %f)");
|
||||
} else if (type == *fContext.fFloat2_Type || type == *fContext.fHalf2_Type) {
|
||||
this->write(type.name() + "(%f, %f)");
|
||||
fFormatArgs.push_back(cppCode + ".fX");
|
||||
fFormatArgs.push_back(cppCode + ".fY");
|
||||
} else {
|
||||
this->write(type.fName);
|
||||
this->write(type.name());
|
||||
this->write("\n");
|
||||
ABORT("unsupported runtime value type\n");
|
||||
}
|
||||
@ -189,7 +184,7 @@ void CPPCodeGenerator::writeVariableReference(const VariableReference& ref) {
|
||||
switch (ref.fVariable.fModifiers.fLayout.fBuiltin) {
|
||||
case SK_INCOLOR_BUILTIN:
|
||||
this->write("%s");
|
||||
fFormatArgs.push_back(String("args.fInputColor ? args.fInputColor : \"float4(1)\""));
|
||||
fFormatArgs.push_back(String("args.fInputColor ? args.fInputColor : \"half4(1)\""));
|
||||
break;
|
||||
case SK_OUTCOLOR_BUILTIN:
|
||||
this->write("%s");
|
||||
@ -211,7 +206,7 @@ void CPPCodeGenerator::writeVariableReference(const VariableReference& ref) {
|
||||
var = String::printf("fColorSpaceHelper.isValid() ? "
|
||||
"args.fUniformHandler->getUniformCStr("
|
||||
"fColorSpaceHelper.gamutXformUniform()) : \"%s\"",
|
||||
default_value(ref.fVariable.fType));
|
||||
default_value(ref.fVariable.fType).c_str());
|
||||
} else {
|
||||
var = String::printf("args.fUniformHandler->getUniformCStr(%sVar)",
|
||||
HCodeGenerator::FieldName(name.c_str()).c_str());
|
||||
@ -221,7 +216,7 @@ void CPPCodeGenerator::writeVariableReference(const VariableReference& ref) {
|
||||
code = String::printf("%sVar.isValid() ? %s : \"%s\"",
|
||||
HCodeGenerator::FieldName(name.c_str()).c_str(),
|
||||
var.c_str(),
|
||||
default_value(ref.fVariable.fType));
|
||||
default_value(ref.fVariable.fType).c_str());
|
||||
} else {
|
||||
code = var;
|
||||
}
|
||||
@ -253,7 +248,7 @@ void CPPCodeGenerator::writeSwitchStatement(const SwitchStatement& s) {
|
||||
void CPPCodeGenerator::writeFunctionCall(const FunctionCall& c) {
|
||||
if (c.fFunction.fBuiltin && c.fFunction.fName == "COLORSPACE") {
|
||||
String tmpVar = "_tmpVar" + to_string(++fVarCount);
|
||||
fFunctionHeader += "float4 " + tmpVar + ";";
|
||||
fFunctionHeader += "half4 " + tmpVar + ";";
|
||||
ASSERT(c.fArguments.size() == 2);
|
||||
this->write("%s");
|
||||
fFormatArgs.push_back("fColorSpaceHelper.isValid() ? \"(" + tmpVar + " = \" : \"\"");
|
||||
@ -262,7 +257,7 @@ void CPPCodeGenerator::writeFunctionCall(const FunctionCall& c) {
|
||||
String xform("args.fUniformHandler->getUniformCStr(fColorSpaceHelper.gamutXformUniform())");
|
||||
this->write("%s");
|
||||
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() : \"\"");
|
||||
return;
|
||||
}
|
||||
@ -349,14 +344,22 @@ void CPPCodeGenerator::addUniform(const Variable& var) {
|
||||
}
|
||||
const char* 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) {
|
||||
type = "kVec2f_GrSLType";
|
||||
type = "kHighFloat2_GrSLType";
|
||||
} else if (var.fType == *fContext.fHalf2_Type) {
|
||||
type = "kHalf2_GrSLType";
|
||||
} 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 ||
|
||||
var.fType == *fContext.fColorSpaceXform_Type) {
|
||||
type = "kMat44f_GrSLType";
|
||||
type = "kHighFloat4x4_GrSLType";
|
||||
} else if (var.fType == *fContext.fHalf4x4_Type) {
|
||||
type = "kHalf4x4_GrSLType";
|
||||
} else {
|
||||
ABORT("unsupported uniform type: %s %s;\n", String(var.fType.fName).c_str(),
|
||||
String(var.fName).c_str());
|
||||
@ -457,11 +460,12 @@ void CPPCodeGenerator::writeSetData(std::vector<const Variable*>& uniforms) {
|
||||
}
|
||||
String nameString(u->fName);
|
||||
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"
|
||||
" %s.set4fv(%sVar, 1, (float*) &%sValue);\n",
|
||||
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"
|
||||
" _outer.%s().asColMajorf(%sValue);\n"
|
||||
" %s.setMatrix4f(%sVar, %sValue);\n",
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user