aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Jim Van Verth <jvanverth@google.com>2017-09-11 11:04:10 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-09-11 15:24:30 +0000
commit6a7a704aa4c4e1862f63f42b3e6df997d472dd2f (patch)
treefb01e0e51729a966efd912be0d87ecc63c421ff6
parentb8163224228b0e702ed02331766d244e579d8b83 (diff)
Add multitexture support to text and path shaders, take 3.
This does not add additional textures to the atlases, just adds the ability to access those textures in the shaders. Bug: skia:3550 Change-Id: I4c1da2bc374a76131f5f4ad946543e03e0ab3126 Reviewed-on: https://skia-review.googlesource.com/44841 Reviewed-by: Robert Phillips <robertphillips@google.com> Commit-Queue: Jim Van Verth <jvanverth@google.com>
-rw-r--r--src/gpu/effects/GrAtlasedShaderHelpers.h63
-rw-r--r--src/gpu/effects/GrBitmapTextGeoProc.cpp30
-rw-r--r--src/gpu/effects/GrDistanceFieldGeoProc.cpp97
-rw-r--r--src/gpu/ops/GrSmallPathRenderer.cpp15
-rw-r--r--src/gpu/text/GrAtlasTextBlob_regenInOp.cpp5
5 files changed, 131 insertions, 79 deletions
diff --git a/src/gpu/effects/GrAtlasedShaderHelpers.h b/src/gpu/effects/GrAtlasedShaderHelpers.h
new file mode 100644
index 0000000000..67f2c242c2
--- /dev/null
+++ b/src/gpu/effects/GrAtlasedShaderHelpers.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrAtlasedShaderHelpers_DEFINED
+#define GrAtlasedShaderHelpers_DEFINED
+
+#include "glsl/GrGLSLPrimitiveProcessor.h"
+#include "glsl/GrGLSLFragmentShaderBuilder.h"
+#include "glsl/GrGLSLVarying.h"
+#include "glsl/GrGLSLVertexShaderBuilder.h"
+
+static void append_index_uv_varyings(GrGLSLPrimitiveProcessor::EmitArgs& args,
+ const char* inTexCoordsName,
+ const char* atlasSizeInvName,
+ GrGLSLVertToFrag *uv,
+ GrGLSLVertToFrag *texIdx,
+ GrGLSLVertToFrag *st) {
+ // 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);",
+ 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;");
+
+ // Multiply by 1/atlasSize to get normalized texture coordinates
+ args.fVaryingHandler->addVarying("TextureCoords", uv, kHigh_GrSLPrecision);
+ args.fVertBuilder->codeAppendf("%s = intCoords * %s;", uv->vsOut(), atlasSizeInvName);
+
+ args.fVaryingHandler->addVarying("TexIndex", texIdx);
+ args.fVertBuilder->codeAppendf("%s = texIdx;", texIdx->vsOut());
+
+ if (st) {
+ args.fVaryingHandler->addVarying("IntTextureCoords", st, kHigh_GrSLPrecision);
+ args.fVertBuilder->codeAppendf("%s = intCoords;", st->vsOut());
+ }
+}
+
+static void append_multitexture_lookup(GrGLSLPrimitiveProcessor::EmitArgs& args,
+ int numTextureSamplers,
+ const GrGLSLVertToFrag &texIdx,
+ const char* coordName,
+ const char* colorName) {
+ // conditionally load from the indexed texture sampler
+ if (numTextureSamplers > 1) {
+ args.fFragBuilder->codeAppendf("if (%s == 0) ", texIdx.fsIn());
+ }
+ args.fFragBuilder->codeAppendf("{ %s = ", colorName);
+ args.fFragBuilder->appendTextureLookup(args.fTexSamplers[0], coordName, kVec2f_GrSLType);
+ args.fFragBuilder->codeAppend("; }");
+ for (int i = 1; i < numTextureSamplers; ++i) {
+ args.fFragBuilder->codeAppendf("else if (%s == %d) { %s =", texIdx.fsIn(), i, colorName);
+ args.fFragBuilder->appendTextureLookup(args.fTexSamplers[i], coordName, kVec2f_GrSLType);
+ args.fFragBuilder->codeAppend("; }");
+ }
+}
+
+#endif
diff --git a/src/gpu/effects/GrBitmapTextGeoProc.cpp b/src/gpu/effects/GrBitmapTextGeoProc.cpp
index c2cf8ebc22..8013d2e4b8 100644
--- a/src/gpu/effects/GrBitmapTextGeoProc.cpp
+++ b/src/gpu/effects/GrBitmapTextGeoProc.cpp
@@ -7,6 +7,7 @@
#include "GrBitmapTextGeoProc.h"
+#include "GrAtlasedShaderHelpers.h"
#include "GrTexture.h"
#include "glsl/GrGLSLFragmentShaderBuilder.h"
#include "glsl/GrGLSLGeometryProcessor.h"
@@ -36,12 +37,10 @@ public:
"AtlasSizeInv",
&atlasSizeInvName);
- GrGLSLVertToFrag v(kVec2f_GrSLType);
- varyingHandler->addVarying("TextureCoords", &v, kHigh_GrSLPrecision);
- vertBuilder->codeAppendf("%s = float2(%s.x, %s.y) * %s;", v.vsOut(),
- btgp.inTextureCoords()->fName,
- btgp.inTextureCoords()->fName,
- atlasSizeInvName);
+ GrGLSLVertToFrag uv(kVec2f_GrSLType);
+ GrGLSLVertToFrag texIdx(kFloat_GrSLType);
+ append_index_uv_varyings(args, btgp.inTextureCoords()->fName, atlasSizeInvName,
+ &uv, &texIdx, nullptr);
GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder;
// Setup pass through color
@@ -64,18 +63,16 @@ public:
btgp.localMatrix(),
args.fFPCoordTransformHandler);
+ fragBuilder->codeAppend("float4 texColor;");
+ append_multitexture_lookup(args, btgp.numTextureSamplers(),
+ texIdx, uv.fsIn(), "texColor");
+
if (btgp.maskFormat() == kARGB_GrMaskFormat) {
- fragBuilder->codeAppendf("%s = ", args.fOutputColor);
- fragBuilder->appendTextureLookupAndModulate(args.fOutputColor,
- args.fTexSamplers[0],
- v.fsIn(),
- kVec2f_GrSLType);
- fragBuilder->codeAppend(";");
+ // modulate by color
+ fragBuilder->codeAppendf("%s = %s * texColor;", args.fOutputColor, args.fOutputColor);
fragBuilder->codeAppendf("%s = float4(1);", args.fOutputCoverage);
} else {
- fragBuilder->codeAppendf("%s = ", args.fOutputCoverage);
- fragBuilder->appendTextureLookup(args.fTexSamplers[0], v.fsIn(), kVec2f_GrSLType);
- fragBuilder->codeAppend(";");
+ fragBuilder->codeAppendf("%s = texColor;", args.fOutputCoverage);
}
}
@@ -89,7 +86,7 @@ public:
fColor = btgp.color();
}
- SkASSERT(btgp.numTextureSamplers() == 1);
+ SkASSERT(btgp.numTextureSamplers() >= 1);
GrTexture* atlas = btgp.textureSampler(0).peekTexture();
SkASSERT(atlas && SkIsPow2(atlas->width()) && SkIsPow2(atlas->height()));
@@ -108,6 +105,7 @@ public:
key |= (btgp.usesLocalCoords() && btgp.localMatrix().hasPerspective()) ? 0x1 : 0x0;
key |= btgp.maskFormat() << 1;
b->add32(key);
+ b->add32(btgp.numTextureSamplers());
}
private:
diff --git a/src/gpu/effects/GrDistanceFieldGeoProc.cpp b/src/gpu/effects/GrDistanceFieldGeoProc.cpp
index 81b33262da..953d4cc2bc 100644
--- a/src/gpu/effects/GrDistanceFieldGeoProc.cpp
+++ b/src/gpu/effects/GrDistanceFieldGeoProc.cpp
@@ -7,6 +7,7 @@
#include "GrDistanceFieldGeoProc.h"
+#include "GrAtlasedShaderHelpers.h"
#include "GrTexture.h"
#include "SkDistanceFieldGen.h"
#include "glsl/GrGLSLFragmentShaderBuilder.h"
@@ -78,17 +79,10 @@ public:
// add varyings
GrGLSLVertToFrag uv(kVec2f_GrSLType);
- varyingHandler->addVarying("TextureCoords", &uv, kHigh_GrSLPrecision);
- vertBuilder->codeAppendf("%s = float2(%s.x, %s.y) * %s;", uv.vsOut(),
- dfTexEffect.inTextureCoords()->fName,
- dfTexEffect.inTextureCoords()->fName,
- atlasSizeInvName);
-
+ GrGLSLVertToFrag texIdx(kFloat_GrSLType);
GrGLSLVertToFrag st(kVec2f_GrSLType);
- varyingHandler->addVarying("IntTextureCoords", &st, kHigh_GrSLPrecision);
- vertBuilder->codeAppendf("%s = float2(%s.x, %s.y);", st.vsOut(),
- dfTexEffect.inTextureCoords()->fName,
- dfTexEffect.inTextureCoords()->fName);
+ append_index_uv_varyings(args, dfTexEffect.inTextureCoords()->fName, atlasSizeInvName,
+ &uv, &texIdx, &st);
bool isUniformScale = (dfTexEffect.getFlags() & kUniformScale_DistanceFieldEffectMask) ==
kUniformScale_DistanceFieldEffectMask;
@@ -100,12 +94,12 @@ public:
// Use highp to work around aliasing issues
fragBuilder->codeAppendf("highp float2 uv = %s;\n", uv.fsIn());
+ fragBuilder->codeAppend("float4 texColor;");
+ append_multitexture_lookup(args, dfTexEffect.numTextureSamplers(),
+ texIdx, "uv", "texColor");
- fragBuilder->codeAppend("float texColor = ");
- fragBuilder->appendTextureLookup(args.fTexSamplers[0], "uv", kVec2f_GrSLType);
- fragBuilder->codeAppend(".r;");
fragBuilder->codeAppend("float distance = "
- SK_DistanceFieldMultiplier "*(texColor - " SK_DistanceFieldThreshold ");");
+ SK_DistanceFieldMultiplier "*(texColor.r - " SK_DistanceFieldThreshold ");");
#ifdef SK_GAMMA_APPLY_TO_A8
// adjust width based on gamma
fragBuilder->codeAppendf("distance -= %s;", distanceAdjustUniName);
@@ -197,7 +191,7 @@ public:
pdman.setMatrix3f(fViewMatrixUniform, viewMatrix);
}
- SkASSERT(dfa8gp.numTextureSamplers() == 1);
+ SkASSERT(dfa8gp.numTextureSamplers() >= 1);
GrTexture* atlas = dfa8gp.textureSampler(0).peekTexture();
SkASSERT(atlas && SkIsPow2(atlas->width()) && SkIsPow2(atlas->height()));
@@ -216,6 +210,7 @@ public:
uint32_t key = dfTexEffect.getFlags();
key |= ComputePosKey(dfTexEffect.viewMatrix()) << 16;
b->add32(key);
+ b->add32(dfTexEffect.numTextureSamplers());
}
private:
@@ -332,17 +327,10 @@ public:
&atlasSizeInvName);
GrGLSLVertToFrag uv(kVec2f_GrSLType);
- varyingHandler->addVarying("TextureCoords", &uv, kHigh_GrSLPrecision);
- vertBuilder->codeAppendf("%s = float2(%s.x, %s.y) * %s;", uv.vsOut(),
- dfTexEffect.inTextureCoords()->fName,
- dfTexEffect.inTextureCoords()->fName,
- atlasSizeInvName);
-
+ GrGLSLVertToFrag texIdx(kFloat_GrSLType);
GrGLSLVertToFrag st(kVec2f_GrSLType);
- varyingHandler->addVarying("IntTextureCoords", &st, kHigh_GrSLPrecision);
- vertBuilder->codeAppendf("%s = float2(%s.x, %s.y);", st.vsOut(),
- dfTexEffect.inTextureCoords()->fName,
- dfTexEffect.inTextureCoords()->fName);
+ append_index_uv_varyings(args, dfTexEffect.inTextureCoords()->fName, atlasSizeInvName,
+ &uv, &texIdx, &st);
// setup pass through color
varyingHandler->addPassThroughAttribute(dfTexEffect.inColor(), args.fOutputColor);
@@ -365,12 +353,12 @@ public:
// Use highp to work around aliasing issues
fragBuilder->codeAppendf("highp float2 uv = %s;", uv.fsIn());
+ fragBuilder->codeAppend("float4 texColor;");
+ append_multitexture_lookup(args, dfTexEffect.numTextureSamplers(),
+ texIdx, "uv", "texColor");
- fragBuilder->codeAppend("float texColor = ");
- fragBuilder->appendTextureLookup(args.fTexSamplers[0], "uv", kVec2f_GrSLType);
- fragBuilder->codeAppend(".r;");
fragBuilder->codeAppend("float distance = "
- SK_DistanceFieldMultiplier "*(texColor - " SK_DistanceFieldThreshold ");");
+ SK_DistanceFieldMultiplier "*(texColor.r - " SK_DistanceFieldThreshold ");");
fragBuilder->codeAppend("float afwidth;");
bool isUniformScale = (dfTexEffect.getFlags() & kUniformScale_DistanceFieldEffectMask) ==
@@ -452,7 +440,7 @@ public:
pdman.setMatrix3f(fViewMatrixUniform, viewMatrix);
}
- SkASSERT(dfpgp.numTextureSamplers() == 1);
+ SkASSERT(dfpgp.numTextureSamplers() >= 1);
GrTexture* atlas = dfpgp.textureSampler(0).peekTexture();
SkASSERT(atlas && SkIsPow2(atlas->width()) && SkIsPow2(atlas->height()));
@@ -472,6 +460,7 @@ public:
uint32_t key = dfTexEffect.getFlags();
key |= ComputePosKey(dfTexEffect.viewMatrix()) << 16;
b->add32(key);
+ b->add32(dfTexEffect.numTextureSamplers());
}
private:
@@ -599,17 +588,10 @@ public:
// set up varyings
GrGLSLVertToFrag uv(kVec2f_GrSLType);
- varyingHandler->addVarying("TextureCoords", &uv, kHigh_GrSLPrecision);
- vertBuilder->codeAppendf("%s = float2(%s.x, %s.y) * %s;", uv.vsOut(),
- dfTexEffect.inTextureCoords()->fName,
- dfTexEffect.inTextureCoords()->fName,
- atlasSizeInvName);
-
+ GrGLSLVertToFrag texIdx(kFloat_GrSLType);
GrGLSLVertToFrag st(kVec2f_GrSLType);
- varyingHandler->addVarying("IntTextureCoords", &st, kHigh_GrSLPrecision);
- vertBuilder->codeAppendf("%s = float2(%s.x, %s.y);", st.vsOut(),
- dfTexEffect.inTextureCoords()->fName,
- dfTexEffect.inTextureCoords()->fName);
+ append_index_uv_varyings(args, dfTexEffect.inTextureCoords()->fName, atlasSizeInvName,
+ &uv, &texIdx, &st);
GrGLSLVertToFrag delta(kFloat_GrSLType);
varyingHandler->addVarying("Delta", &delta, kHigh_GrSLPrecision);
@@ -660,26 +642,26 @@ public:
fragBuilder->codeAppendf("float2 offset = %s*Jdx;", delta.fsIn());
}
+ // sample the texture by index
+ fragBuilder->codeAppend("float4 texColor;");
+ append_multitexture_lookup(args, dfTexEffect.numTextureSamplers(),
+ texIdx, "uv", "texColor");
+
// green is distance to uv center
- fragBuilder->codeAppend("\tfloat4 texColor = ");
- fragBuilder->appendTextureLookup(args.fTexSamplers[0], "uv", kVec2f_GrSLType);
- fragBuilder->codeAppend(";\n");
- fragBuilder->codeAppend("\tfloat3 distance;\n");
- fragBuilder->codeAppend("\tdistance.y = texColor.r;\n");
+ fragBuilder->codeAppend("float3 distance;");
+ fragBuilder->codeAppend("distance.y = texColor.r;");
// red is distance to left offset
- fragBuilder->codeAppend("\tfloat2 uv_adjusted = uv - offset;\n");
- fragBuilder->codeAppend("\ttexColor = ");
- fragBuilder->appendTextureLookup(args.fTexSamplers[0], "uv_adjusted", kVec2f_GrSLType);
- fragBuilder->codeAppend(";\n");
- fragBuilder->codeAppend("\tdistance.x = texColor.r;\n");
+ fragBuilder->codeAppend("float2 uv_adjusted = uv - offset;");
+ append_multitexture_lookup(args, dfTexEffect.numTextureSamplers(),
+ texIdx, "uv_adjusted", "texColor");
+ fragBuilder->codeAppend("distance.x = texColor.r;");
// blue is distance to right offset
- fragBuilder->codeAppend("\tuv_adjusted = uv + offset;\n");
- fragBuilder->codeAppend("\ttexColor = ");
- fragBuilder->appendTextureLookup(args.fTexSamplers[0], "uv_adjusted", kVec2f_GrSLType);
- fragBuilder->codeAppend(";\n");
- fragBuilder->codeAppend("\tdistance.z = texColor.r;\n");
+ fragBuilder->codeAppend("uv_adjusted = uv + offset;");
+ append_multitexture_lookup(args, dfTexEffect.numTextureSamplers(),
+ texIdx, "uv_adjusted", "texColor");
+ fragBuilder->codeAppend("distance.z = texColor.r;");
- fragBuilder->codeAppend("\tdistance = "
+ fragBuilder->codeAppend("distance = "
"float3(" SK_DistanceFieldMultiplier ")*(distance - float3(" SK_DistanceFieldThreshold"));");
// adjust width based on gamma
@@ -757,7 +739,7 @@ public:
pdman.setMatrix3f(fViewMatrixUniform, viewMatrix);
}
- SkASSERT(dflcd.numTextureSamplers() == 1);
+ SkASSERT(dflcd.numTextureSamplers() >= 1);
GrTexture* atlas = dflcd.textureSampler(0).peekTexture();
SkASSERT(atlas && SkIsPow2(atlas->width()) && SkIsPow2(atlas->height()));
@@ -777,6 +759,7 @@ public:
uint32_t key = dfTexEffect.getFlags();
key |= ComputePosKey(dfTexEffect.viewMatrix()) << 16;
b->add32(key);
+ b->add32(dfTexEffect.numTextureSamplers());
}
private:
diff --git a/src/gpu/ops/GrSmallPathRenderer.cpp b/src/gpu/ops/GrSmallPathRenderer.cpp
index 1b0648615d..ec63e9ec7d 100644
--- a/src/gpu/ops/GrSmallPathRenderer.cpp
+++ b/src/gpu/ops/GrSmallPathRenderer.cpp
@@ -485,10 +485,12 @@ private:
shapeData->fBounds.fRight /= scale;
shapeData->fBounds.fBottom /= scale;
- shapeData->fTextureCoords.set(atlasLocation.fX+SK_DistanceFieldPad,
- atlasLocation.fY+SK_DistanceFieldPad,
- atlasLocation.fX+SK_DistanceFieldPad+devPathBounds.width(),
- atlasLocation.fY+SK_DistanceFieldPad+devPathBounds.height());
+ shapeData->fTextureCoords.set((atlasLocation.fX+SK_DistanceFieldPad) << 1,
+ (atlasLocation.fY+SK_DistanceFieldPad) << 1,
+ (atlasLocation.fX+SK_DistanceFieldPad+
+ devPathBounds.width()) << 1,
+ (atlasLocation.fY+SK_DistanceFieldPad+
+ devPathBounds.height()) << 1);
fShapeCache->add(shapeData);
fShapeList->addToTail(shapeData);
@@ -576,8 +578,9 @@ private:
shapeData->fBounds = SkRect::Make(devPathBounds);
shapeData->fBounds.offset(-translateX, -translateY);
- shapeData->fTextureCoords.set(atlasLocation.fX, atlasLocation.fY,
- atlasLocation.fX+width, atlasLocation.fY+height);
+ shapeData->fTextureCoords.set(atlasLocation.fX << 1, atlasLocation.fY << 1,
+ (atlasLocation.fX+width) << 1,
+ (atlasLocation.fY+height) << 1);
fShapeCache->add(shapeData);
fShapeList->addToTail(shapeData);
diff --git a/src/gpu/text/GrAtlasTextBlob_regenInOp.cpp b/src/gpu/text/GrAtlasTextBlob_regenInOp.cpp
index 96f0080ec2..b7911c3eae 100644
--- a/src/gpu/text/GrAtlasTextBlob_regenInOp.cpp
+++ b/src/gpu/text/GrAtlasTextBlob_regenInOp.cpp
@@ -39,6 +39,11 @@ inline void regen_vertices(intptr_t vertex, const GrGlyph* glyph, size_t vertexS
u1 = u0 + width;
v1 = v0 + height;
}
+ // shift to make space for index bits
+ u0 <<= 1;
+ v0 <<= 1;
+ u1 <<= 1;
+ v1 <<= 1;
}
// This is a bit wonky, but sometimes we have LCD text, in which case we won't have color