aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--gm/dftext_blob_persp.cpp143
-rw-r--r--gn/gm.gni1
-rw-r--r--include/core/SkMatrix.h3
-rw-r--r--src/core/SkMatrix.cpp24
-rw-r--r--src/gpu/effects/GrDistanceFieldGeoProc.cpp150
-rw-r--r--src/gpu/effects/GrDistanceFieldGeoProc.h66
-rw-r--r--src/gpu/glsl/GrGLSLGeometryProcessor.cpp33
-rw-r--r--src/gpu/glsl/GrGLSLGeometryProcessor.h3
-rw-r--r--src/gpu/ops/GrAtlasTextOp.cpp106
-rw-r--r--src/gpu/ops/GrAtlasTextOp.h14
-rw-r--r--src/gpu/text/GrAtlasTextBlob.cpp79
-rw-r--r--src/gpu/text/GrAtlasTextBlob.h29
-rw-r--r--src/gpu/text/GrAtlasTextBlobVertexRegenerator.cpp8
-rw-r--r--src/gpu/text/GrAtlasTextContext.cpp3
14 files changed, 247 insertions, 415 deletions
diff --git a/gm/dftext_blob_persp.cpp b/gm/dftext_blob_persp.cpp
deleted file mode 100644
index cfa681d984..0000000000
--- a/gm/dftext_blob_persp.cpp
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright 2017 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "gm.h"
-#include "Resources.h"
-#include "SkCanvas.h"
-#include "SkSurface.h"
-#include "SkTextBlob.h"
-#include "SkTypeface.h"
-#include "sk_tool_utils.h"
-
-/**
- * This GM tests reusing the same text blobs with distance fields rendering using various
- * combinations of perspective and non-perspetive matrices, scissor clips, and different x,y params
- * passed to the draw.
- */
-class DFTextBlobPerspGM : public skiagm::GM {
-public:
- DFTextBlobPerspGM() { this->setBGColor(0xFFFFFFFF); }
-
-protected:
- SkString onShortName() override {
- SkString name("dftext_blob_persp");
- name.append(sk_tool_utils::platform_font_manager());
- return name;
- }
-
- SkISize onISize() override { return SkISize::Make(900, 350); }
-
- void onOnceBeforeDraw() override {
- for (int i = 0; i < 3; ++i) {
- SkPaint paint;
- paint.setTextSize(32);
- paint.setAntiAlias(i > 0);
- paint.setLCDRenderText(i > 1);
- paint.setSubpixelText(true);
- SkTextBlobBuilder builder;
- sk_tool_utils::add_to_text_blob(&builder, "SkiaText", paint, 0, 0);
- fBlobs.emplace_back(builder.make());
- }
- }
-
- virtual void onDraw(SkCanvas* inputCanvas) override {
- // set up offscreen rendering with distance field text
-#if SK_SUPPORT_GPU
- GrContext* ctx = inputCanvas->getGrContext();
- SkISize size = this->onISize();
- if (!inputCanvas->getBaseLayerSize().isEmpty()) {
- size = inputCanvas->getBaseLayerSize();
- }
- SkImageInfo info = SkImageInfo::MakeN32(size.width(), size.height(), kPremul_SkAlphaType,
- inputCanvas->imageInfo().refColorSpace());
- SkSurfaceProps props(SkSurfaceProps::kUseDeviceIndependentFonts_Flag,
- SkSurfaceProps::kLegacyFontHost_InitType);
- auto surface = SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo, info, 0, &props);
- SkCanvas* canvas = surface ? surface->getCanvas() : inputCanvas;
- // init our new canvas with the old canvas's matrix
- canvas->setMatrix(inputCanvas->getTotalMatrix());
-#else
- SkCanvas* canvas = inputCanvas;
-#endif
- SkScalar x = 0, y = 0;
- SkScalar maxH = 0;
- for (auto twm : {TranslateWithMatrix::kNo, TranslateWithMatrix::kYes}) {
- for (auto pm : {PerspMode::kNone, PerspMode::kX, PerspMode::kY, PerspMode::kXY}) {
- for (auto& blob : fBlobs) {
- for (bool clip : {false, true}) {
- canvas->save();
- SkScalar w = blob->bounds().width();
- SkScalar h = blob->bounds().height();
- if (clip) {
- auto rect =
- SkRect::MakeXYWH(x + 5, y + 5, w * 3.f / 4.f, h * 3.f / 4.f);
- canvas->clipRect(rect, false);
- }
- this->drawBlob(canvas, blob.get(), SK_ColorBLACK, x, y + h, pm, twm);
- x += w + 20.f;
- maxH = SkTMax(h, maxH);
- canvas->restore();
- }
- }
- x = 0;
- y += maxH + 20.f;
- maxH = 0;
- }
- }
-#if SK_SUPPORT_GPU
- // render offscreen buffer
- if (surface) {
- SkAutoCanvasRestore acr(inputCanvas, true);
- // since we prepended this matrix already, we blit using identity
- inputCanvas->resetMatrix();
- inputCanvas->drawImage(surface->makeImageSnapshot().get(), 0, 0, nullptr);
- }
-#endif
- }
-
-private:
- enum class PerspMode { kNone, kX, kY, kXY };
-
- enum class TranslateWithMatrix : bool { kNo, kYes };
-
- void drawBlob(SkCanvas* canvas, SkTextBlob* blob, SkColor color, SkScalar x, SkScalar y,
- PerspMode perspMode, TranslateWithMatrix translateWithMatrix) {
- canvas->save();
- SkMatrix persp = SkMatrix::I();
- switch (perspMode) {
- case PerspMode::kNone:
- break;
- case PerspMode::kX:
- persp.setPerspX(0.005f);
- break;
- case PerspMode::kY:
- persp.setPerspY(00.005f);
- break;
- case PerspMode::kXY:
- persp.setPerspX(-0.001f);
- persp.setPerspY(-0.0015f);
- break;
- }
- persp = SkMatrix::Concat(persp, SkMatrix::MakeTrans(-x, -y));
- persp = SkMatrix::Concat(SkMatrix::MakeTrans(x, y), persp);
- canvas->concat(persp);
- if (TranslateWithMatrix::kYes == translateWithMatrix) {
- canvas->translate(x, y);
- x = 0;
- y = 0;
- }
- SkPaint paint;
- paint.setColor(color);
- canvas->drawTextBlob(blob, x, y, paint);
- canvas->restore();
- }
-
- SkTArray<sk_sp<SkTextBlob>, true> fBlobs;
- typedef skiagm::GM INHERITED;
-};
-
-DEF_GM(return new DFTextBlobPerspGM;)
diff --git a/gn/gm.gni b/gn/gm.gni
index c8297cfd24..d24b8bbb27 100644
--- a/gn/gm.gni
+++ b/gn/gm.gni
@@ -102,7 +102,6 @@ gm_sources = [
"$_gm/deferredtextureimage.cpp",
"$_gm/degeneratesegments.cpp",
"$_gm/dftext.cpp",
- "$_gm/dftext_blob_persp.cpp",
"$_gm/discard.cpp",
"$_gm/displacement.cpp",
"$_gm/distantclip.cpp",
diff --git a/include/core/SkMatrix.h b/include/core/SkMatrix.h
index b527ab5ef9..e88232834b 100644
--- a/include/core/SkMatrix.h
+++ b/include/core/SkMatrix.h
@@ -1337,9 +1337,6 @@ public:
@param count items in SkPoint3 array to transform
*/
void mapHomogeneousPoints(SkPoint3 dst[], const SkPoint3 src[], int count) const;
- /** Same as above but with a variable offset between successive points. */
- void mapHomogeneousPointsWithStride(SkPoint3 dst[], const SkPoint3 src[], size_t stride,
- int count) const;
/** Maps SkPoint (x, y) to result. SkPoint is mapped by multiplying by SkMatrix. Given:
diff --git a/src/core/SkMatrix.cpp b/src/core/SkMatrix.cpp
index 4851aeacf6..d02524068e 100644
--- a/src/core/SkMatrix.cpp
+++ b/src/core/SkMatrix.cpp
@@ -1037,48 +1037,32 @@ const SkMatrix::MapPtsProc SkMatrix::gMapPtsProcs[] = {
///////////////////////////////////////////////////////////////////////////////
-void SkMatrix::mapHomogeneousPointsWithStride(SkPoint3 dst[], const SkPoint3 src[], size_t stride,
- int count) const {
+void SkMatrix::mapHomogeneousPoints(SkPoint3 dst[], const SkPoint3 src[], int count) const {
SkASSERT((dst && src && count > 0) || 0 == count);
// no partial overlap
SkASSERT(src == dst || &dst[count] <= &src[0] || &src[count] <= &dst[0]);
if (count > 0) {
if (this->isIdentity()) {
- if (src != dst) {
- if (stride == sizeof(SkPoint3)) {
- memcpy(dst, src, count * sizeof(SkPoint3));
- } else {
- for (int i = 0; i < count; ++i) {
- *dst = *src;
- dst = reinterpret_cast<SkPoint3*>(reinterpret_cast<char*>(dst) + stride);
- src = reinterpret_cast<const SkPoint3*>(reinterpret_cast<const char*>(src) +
- stride);
- }
- }
- }
+ memcpy(dst, src, count * sizeof(SkPoint3));
return;
}
do {
SkScalar sx = src->fX;
SkScalar sy = src->fY;
SkScalar sw = src->fZ;
- src = reinterpret_cast<const SkPoint3*>(reinterpret_cast<const char*>(src) + stride);
+ src++;
SkScalar x = sdot(sx, fMat[kMScaleX], sy, fMat[kMSkewX], sw, fMat[kMTransX]);
SkScalar y = sdot(sx, fMat[kMSkewY], sy, fMat[kMScaleY], sw, fMat[kMTransY]);
SkScalar w = sdot(sx, fMat[kMPersp0], sy, fMat[kMPersp1], sw, fMat[kMPersp2]);
dst->set(x, y, w);
- dst = reinterpret_cast<SkPoint3*>(reinterpret_cast<char*>(dst) + stride);
+ dst++;
} while (--count);
}
}
-void SkMatrix::mapHomogeneousPoints(SkPoint3 dst[], const SkPoint3 src[], int count) const {
- this->mapHomogeneousPointsWithStride(dst, src, sizeof(SkPoint3), count);
-}
-
///////////////////////////////////////////////////////////////////////////////
void SkMatrix::mapVectors(SkPoint dst[], const SkPoint src[], int count) const {
diff --git a/src/gpu/effects/GrDistanceFieldGeoProc.cpp b/src/gpu/effects/GrDistanceFieldGeoProc.cpp
index b8548bb4db..2747f55119 100644
--- a/src/gpu/effects/GrDistanceFieldGeoProc.cpp
+++ b/src/gpu/effects/GrDistanceFieldGeoProc.cpp
@@ -6,6 +6,7 @@
*/
#include "GrDistanceFieldGeoProc.h"
+
#include "GrAtlasedShaderHelpers.h"
#include "GrTexture.h"
#include "SkDistanceFieldGen.h"
@@ -22,7 +23,13 @@
class GrGLDistanceFieldA8TextGeoProc : public GrGLSLGeometryProcessor {
public:
- GrGLDistanceFieldA8TextGeoProc() = default;
+ GrGLDistanceFieldA8TextGeoProc()
+ : fViewMatrix(SkMatrix::InvalidMatrix())
+ #ifdef SK_GAMMA_APPLY_TO_A8
+ , fDistanceAdjust(-1.0f)
+ #endif
+ , fAtlasSize({0,0}) {
+ }
void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override{
const GrDistanceFieldA8TextGeoProc& dfTexEffect =
@@ -54,14 +61,18 @@ public:
varyingHandler->addPassThroughAttribute(dfTexEffect.inColor(), args.fOutputColor);
// Setup position
- gpArgs->fPositionVar = dfTexEffect.inPosition()->asShaderVar();
+ this->writeOutputPosition(vertBuilder,
+ uniformHandler,
+ gpArgs,
+ dfTexEffect.inPosition()->fName,
+ dfTexEffect.viewMatrix(),
+ &fViewMatrixUniform);
// emit transforms
this->emitTransforms(vertBuilder,
varyingHandler,
uniformHandler,
dfTexEffect.inPosition()->asShaderVar(),
- dfTexEffect.localMatrix(),
args.fFPCoordTransformHandler);
// add varyings
@@ -171,6 +182,13 @@ public:
}
#endif
+ if (!dfa8gp.viewMatrix().isIdentity() && !fViewMatrix.cheapEqualTo(dfa8gp.viewMatrix())) {
+ fViewMatrix = dfa8gp.viewMatrix();
+ float viewMatrix[3 * 3];
+ GrGLSLGetMatrix<3>(viewMatrix, fViewMatrix);
+ pdman.setMatrix3f(fViewMatrixUniform, viewMatrix);
+ }
+
SkASSERT(dfa8gp.numTextureSamplers() >= 1);
GrTexture* atlas = dfa8gp.textureSampler(0).peekTexture();
SkASSERT(atlas && SkIsPow2(atlas->width()) && SkIsPow2(atlas->height()));
@@ -180,7 +198,7 @@ public:
pdman.set2f(fAtlasSizeInvUniform, 1.0f / atlas->width(), 1.0f / atlas->height());
}
- this->setTransformDataHelper(dfa8gp.localMatrix(), pdman, &transformIter);
+ this->setTransformDataHelper(SkMatrix::I(), pdman, &transformIter);
}
static inline void GenKey(const GrGeometryProcessor& gp,
@@ -188,16 +206,19 @@ public:
GrProcessorKeyBuilder* b) {
const GrDistanceFieldA8TextGeoProc& dfTexEffect = gp.cast<GrDistanceFieldA8TextGeoProc>();
uint32_t key = dfTexEffect.getFlags();
+ key |= ComputePosKey(dfTexEffect.viewMatrix()) << 16;
b->add32(key);
b->add32(dfTexEffect.numTextureSamplers());
}
private:
+ SkMatrix fViewMatrix;
+ UniformHandle fViewMatrixUniform;
#ifdef SK_GAMMA_APPLY_TO_A8
- float fDistanceAdjust = -1.f;
+ float fDistanceAdjust;
UniformHandle fDistanceAdjustUni;
#endif
- SkISize fAtlasSize = {0, 0};
+ SkISize fAtlasSize;
UniformHandle fAtlasSizeInvUniform;
typedef GrGLSLGeometryProcessor INHERITED;
@@ -206,28 +227,26 @@ private:
///////////////////////////////////////////////////////////////////////////////
GrDistanceFieldA8TextGeoProc::GrDistanceFieldA8TextGeoProc(
- GrColor color,
- const sk_sp<GrTextureProxy> proxies[kMaxTextures],
- const GrSamplerState& params,
+ GrColor color,
+ const SkMatrix& viewMatrix,
+ const sk_sp<GrTextureProxy> proxies[kMaxTextures],
+ const GrSamplerState& params,
#ifdef SK_GAMMA_APPLY_TO_A8
- float distanceAdjust,
+ float distanceAdjust,
#endif
- uint32_t flags,
- const SkMatrix& localMatrix)
+ uint32_t flags,
+ bool usesLocalCoords)
: INHERITED(kGrDistanceFieldA8TextGeoProc_ClassID)
, fColor(color)
+ , fViewMatrix(viewMatrix)
#ifdef SK_GAMMA_APPLY_TO_A8
, fDistanceAdjust(distanceAdjust)
#endif
, fFlags(flags & kNonLCD_DistanceFieldEffectMask)
, fInColor(nullptr)
- , fLocalMatrix(localMatrix) {
+ , fUsesLocalCoords(usesLocalCoords) {
SkASSERT(!(flags & ~kNonLCD_DistanceFieldEffectMask));
- if (flags & kPerspective_DistanceFieldEffectFlag) {
- fInPosition = &this->addVertexAttrib("inPosition", kFloat3_GrVertexAttribType);
- } else {
- fInPosition = &this->addVertexAttrib("inPosition", kFloat2_GrVertexAttribType);
- }
+ fInPosition = &this->addVertexAttrib("inPosition", kFloat2_GrVertexAttribType);
fInColor = &this->addVertexAttrib("inColor", kUByte4_norm_GrVertexAttribType);
fInTextureCoords = &this->addVertexAttrib("inTextureCoords", kUShort2_GrVertexAttribType);
for (int i = 0; i < kMaxTextures; ++i) {
@@ -284,16 +303,14 @@ sk_sp<GrGeometryProcessor> GrDistanceFieldA8TextGeoProc::TestCreate(GrProcessorT
if (flags & kSimilarity_DistanceFieldEffectFlag) {
flags |= d->fRandom->nextBool() ? kScaleOnly_DistanceFieldEffectFlag : 0;
}
- SkMatrix localMatrix = GrTest::TestMatrix(d->fRandom);
- GrColor color = GrRandomColor(d->fRandom);
- float lum = d->fRandom->nextF();
- return GrDistanceFieldA8TextGeoProc::Make(color,
- proxies,
+
+ return GrDistanceFieldA8TextGeoProc::Make(GrRandomColor(d->fRandom),
+ GrTest::TestMatrix(d->fRandom), proxies,
samplerState,
#ifdef SK_GAMMA_APPLY_TO_A8
- lum,
+ d->fRandom->nextF(),
#endif
- flags, localMatrix);
+ flags, d->fRandom->nextBool());
}
#endif
@@ -307,8 +324,7 @@ public:
}
void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override{
- const GrDistanceFieldPathGeoProc& dfPathEffect =
- args.fGP.cast<GrDistanceFieldPathGeoProc>();
+ const GrDistanceFieldPathGeoProc& dfTexEffect = args.fGP.cast<GrDistanceFieldPathGeoProc>();
GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder;
@@ -317,7 +333,7 @@ public:
GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
// emit attributes
- varyingHandler->emitAttributes(dfPathEffect);
+ varyingHandler->emitAttributes(dfTexEffect);
const char* atlasSizeInvName;
fAtlasSizeInvUniform = uniformHandler->addUniform(kVertex_GrShaderFlag,
@@ -329,55 +345,55 @@ public:
GrGLSLVarying uv(kFloat2_GrSLType);
GrGLSLVarying texIdx(kHalf_GrSLType);
GrGLSLVarying st(kFloat2_GrSLType);
- append_index_uv_varyings(args, dfPathEffect.inTextureCoords()->fName, atlasSizeInvName, &uv,
- &texIdx, &st);
+ append_index_uv_varyings(args, dfTexEffect.inTextureCoords()->fName, atlasSizeInvName,
+ &uv, &texIdx, &st);
// setup pass through color
- varyingHandler->addPassThroughAttribute(dfPathEffect.inColor(), args.fOutputColor);
+ varyingHandler->addPassThroughAttribute(dfTexEffect.inColor(), args.fOutputColor);
- if (dfPathEffect.matrix().hasPerspective()) {
+ if (dfTexEffect.matrix().hasPerspective()) {
// Setup position
this->writeOutputPosition(vertBuilder,
uniformHandler,
gpArgs,
- dfPathEffect.inPosition()->fName,
- dfPathEffect.matrix(),
+ dfTexEffect.inPosition()->fName,
+ dfTexEffect.matrix(),
&fMatrixUniform);
// emit transforms
this->emitTransforms(vertBuilder,
varyingHandler,
uniformHandler,
- dfPathEffect.inPosition()->asShaderVar(),
+ dfTexEffect.inPosition()->asShaderVar(),
args.fFPCoordTransformHandler);
} else {
// Setup position
- this->writeOutputPosition(vertBuilder, gpArgs, dfPathEffect.inPosition()->fName);
+ this->writeOutputPosition(vertBuilder, gpArgs, dfTexEffect.inPosition()->fName);
// emit transforms
this->emitTransforms(vertBuilder,
varyingHandler,
uniformHandler,
- dfPathEffect.inPosition()->asShaderVar(),
- dfPathEffect.matrix(),
+ dfTexEffect.inPosition()->asShaderVar(),
+ dfTexEffect.matrix(),
args.fFPCoordTransformHandler);
}
// Use highp to work around aliasing issues
fragBuilder->codeAppendf("float2 uv = %s;", uv.fsIn());
fragBuilder->codeAppend("half4 texColor;");
- append_multitexture_lookup(args, dfPathEffect.numTextureSamplers(), texIdx, "uv",
- "texColor");
+ append_multitexture_lookup(args, dfTexEffect.numTextureSamplers(),
+ texIdx, "uv", "texColor");
fragBuilder->codeAppend("half distance = "
SK_DistanceFieldMultiplier "*(texColor.r - " SK_DistanceFieldThreshold ");");
fragBuilder->codeAppend("half afwidth;");
- bool isUniformScale = (dfPathEffect.getFlags() & kUniformScale_DistanceFieldEffectMask) ==
- kUniformScale_DistanceFieldEffectMask;
- bool isSimilarity = SkToBool(dfPathEffect.getFlags() & kSimilarity_DistanceFieldEffectFlag);
+ bool isUniformScale = (dfTexEffect.getFlags() & kUniformScale_DistanceFieldEffectMask) ==
+ kUniformScale_DistanceFieldEffectMask;
+ bool isSimilarity = SkToBool(dfTexEffect.getFlags() & kSimilarity_DistanceFieldEffectFlag);
bool isGammaCorrect =
- SkToBool(dfPathEffect.getFlags() & kGammaCorrect_DistanceFieldEffectFlag);
+ SkToBool(dfTexEffect.getFlags() & kGammaCorrect_DistanceFieldEffectFlag);
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.
@@ -573,7 +589,9 @@ sk_sp<GrGeometryProcessor> GrDistanceFieldPathGeoProc::TestCreate(GrProcessorTes
class GrGLDistanceFieldLCDTextGeoProc : public GrGLSLGeometryProcessor {
public:
- GrGLDistanceFieldLCDTextGeoProc() : fAtlasSize({0, 0}) {
+ GrGLDistanceFieldLCDTextGeoProc()
+ : fViewMatrix(SkMatrix::InvalidMatrix())
+ , fAtlasSize({0,0}) {
fDistanceAdjust = GrDistanceFieldLCDTextGeoProc::DistanceAdjust::Make(1.0f, 1.0f, 1.0f);
}
@@ -601,14 +619,18 @@ public:
varyingHandler->addPassThroughAttribute(dfTexEffect.inColor(), args.fOutputColor);
// Setup position
- gpArgs->fPositionVar = dfTexEffect.inPosition()->asShaderVar();
+ this->writeOutputPosition(vertBuilder,
+ uniformHandler,
+ gpArgs,
+ dfTexEffect.inPosition()->fName,
+ dfTexEffect.viewMatrix(),
+ &fViewMatrixUniform);
// emit transforms
this->emitTransforms(vertBuilder,
varyingHandler,
uniformHandler,
dfTexEffect.inPosition()->asShaderVar(),
- dfTexEffect.localMatrix(),
args.fFPCoordTransformHandler);
// set up varyings
@@ -756,6 +778,13 @@ public:
fDistanceAdjust = wa;
}
+ if (!dflcd.viewMatrix().isIdentity() && !fViewMatrix.cheapEqualTo(dflcd.viewMatrix())) {
+ fViewMatrix = dflcd.viewMatrix();
+ float viewMatrix[3 * 3];
+ GrGLSLGetMatrix<3>(viewMatrix, fViewMatrix);
+ pdman.setMatrix3f(fViewMatrixUniform, viewMatrix);
+ }
+
SkASSERT(dflcd.numTextureSamplers() >= 1);
GrTexture* atlas = dflcd.textureSampler(0).peekTexture();
SkASSERT(atlas && SkIsPow2(atlas->width()) && SkIsPow2(atlas->height()));
@@ -764,7 +793,8 @@ public:
fAtlasSize.set(atlas->width(), atlas->height());
pdman.set2f(fAtlasSizeInvUniform, 1.0f / atlas->width(), 1.0f / atlas->height());
}
- this->setTransformDataHelper(dflcd.localMatrix(), pdman, &transformIter);
+
+ this->setTransformDataHelper(SkMatrix::I(), pdman, &transformIter);
}
static inline void GenKey(const GrGeometryProcessor& gp,
@@ -773,11 +803,15 @@ public:
const GrDistanceFieldLCDTextGeoProc& dfTexEffect = gp.cast<GrDistanceFieldLCDTextGeoProc>();
uint32_t key = dfTexEffect.getFlags();
+ key |= ComputePosKey(dfTexEffect.viewMatrix()) << 16;
b->add32(key);
b->add32(dfTexEffect.numTextureSamplers());
}
private:
+ SkMatrix fViewMatrix;
+ UniformHandle fViewMatrixUniform;
+
GrDistanceFieldLCDTextGeoProc::DistanceAdjust fDistanceAdjust;
UniformHandle fDistanceAdjustUni;
@@ -790,22 +824,19 @@ private:
///////////////////////////////////////////////////////////////////////////////
GrDistanceFieldLCDTextGeoProc::GrDistanceFieldLCDTextGeoProc(
GrColor color,
+ const SkMatrix& viewMatrix,
const sk_sp<GrTextureProxy> proxies[kMaxTextures],
const GrSamplerState& params,
DistanceAdjust distanceAdjust,
- uint32_t flags,
- const SkMatrix& localMatrix)
+ uint32_t flags, bool usesLocalCoords)
: INHERITED(kGrDistanceFieldLCDTextGeoProc_ClassID)
, fColor(color)
+ , fViewMatrix(viewMatrix)
, fDistanceAdjust(distanceAdjust)
, fFlags(flags & kLCD_DistanceFieldEffectMask)
- , fLocalMatrix(localMatrix) {
+ , fUsesLocalCoords(usesLocalCoords) {
SkASSERT(!(flags & ~kLCD_DistanceFieldEffectMask) && (flags & kUseLCD_DistanceFieldEffectFlag));
- if (fFlags & kPerspective_DistanceFieldEffectFlag) {
- fInPosition = &this->addVertexAttrib("inPosition", kFloat3_GrVertexAttribType);
- } else {
- fInPosition = &this->addVertexAttrib("inPosition", kFloat2_GrVertexAttribType);
- }
+ fInPosition = &this->addVertexAttrib("inPosition", kFloat2_GrVertexAttribType);
fInColor = &this->addVertexAttrib("inColor", kUByte4_norm_GrVertexAttribType);
fInTextureCoords = &this->addVertexAttrib("inTextureCoords", kUShort2_GrVertexAttribType);
for (int i = 0; i < kMaxTextures; ++i) {
@@ -862,9 +893,8 @@ sk_sp<GrGeometryProcessor> GrDistanceFieldLCDTextGeoProc::TestCreate(GrProcessor
flags |= d->fRandom->nextBool() ? kScaleOnly_DistanceFieldEffectFlag : 0;
}
flags |= d->fRandom->nextBool() ? kBGR_DistanceFieldEffectFlag : 0;
- GrColor color = GrRandomColor(d->fRandom);
- SkMatrix localMatrix = GrTest::TestMatrix(d->fRandom);
- return GrDistanceFieldLCDTextGeoProc::Make(color, proxies, samplerState, wa, flags,
- localMatrix);
+ return GrDistanceFieldLCDTextGeoProc::Make(GrRandomColor(d->fRandom),
+ GrTest::TestMatrix(d->fRandom), proxies,
+ samplerState, wa, flags, d->fRandom->nextBool());
}
#endif
diff --git a/src/gpu/effects/GrDistanceFieldGeoProc.h b/src/gpu/effects/GrDistanceFieldGeoProc.h
index f3fd67606b..a09938242f 100644
--- a/src/gpu/effects/GrDistanceFieldGeoProc.h
+++ b/src/gpu/effects/GrDistanceFieldGeoProc.h
@@ -19,27 +19,24 @@ class GrInvariantOutput;
enum GrDistanceFieldEffectFlags {
kSimilarity_DistanceFieldEffectFlag = 0x01, // ctm is similarity matrix
kScaleOnly_DistanceFieldEffectFlag = 0x02, // ctm has only scale and translate
- kPerspective_DistanceFieldEffectFlag = 0x04, // ctm has perspective (and positions are x,y,w)
- kUseLCD_DistanceFieldEffectFlag = 0x08, // use lcd text
- kBGR_DistanceFieldEffectFlag = 0x10, // lcd display has bgr order
- kPortrait_DistanceFieldEffectFlag = 0x20, // lcd display is in portrait mode (not used yet)
- kGammaCorrect_DistanceFieldEffectFlag = 0x40, // assume gamma-correct output (linear blending)
- kAliased_DistanceFieldEffectFlag = 0x80, // monochrome output
+ kUseLCD_DistanceFieldEffectFlag = 0x04, // use lcd text
+ kBGR_DistanceFieldEffectFlag = 0x08, // lcd display has bgr order
+ kPortrait_DistanceFieldEffectFlag = 0x10, // lcd display is in portrait mode (not used yet)
+ kGammaCorrect_DistanceFieldEffectFlag = 0x20, // assume gamma-correct output (linear blending)
+ kAliased_DistanceFieldEffectFlag = 0x40, // monochrome output
- kInvalid_DistanceFieldEffectFlag = 0x100, // invalid state (for initialization)
+ kInvalid_DistanceFieldEffectFlag = 0x80, // invalid state (for initialization)
kUniformScale_DistanceFieldEffectMask = kSimilarity_DistanceFieldEffectFlag |
kScaleOnly_DistanceFieldEffectFlag,
// The subset of the flags relevant to GrDistanceFieldA8TextGeoProc
kNonLCD_DistanceFieldEffectMask = kSimilarity_DistanceFieldEffectFlag |
kScaleOnly_DistanceFieldEffectFlag |
- kPerspective_DistanceFieldEffectFlag |
kGammaCorrect_DistanceFieldEffectFlag |
kAliased_DistanceFieldEffectFlag,
// The subset of the flags relevant to GrDistanceFieldLCDTextGeoProc
kLCD_DistanceFieldEffectMask = kSimilarity_DistanceFieldEffectFlag |
kScaleOnly_DistanceFieldEffectFlag |
- kPerspective_DistanceFieldEffectFlag |
kUseLCD_DistanceFieldEffectFlag |
kBGR_DistanceFieldEffectFlag |
kGammaCorrect_DistanceFieldEffectFlag,
@@ -55,22 +52,23 @@ class GrDistanceFieldA8TextGeoProc : public GrGeometryProcessor {
public:
static constexpr int kMaxTextures = 4;
- /** The local matrix should be identity if local coords are not required by the GrPipeline. */
#ifdef SK_GAMMA_APPLY_TO_A8
- static sk_sp<GrGeometryProcessor> Make(GrColor color,
+ static sk_sp<GrGeometryProcessor> Make(GrColor color, const SkMatrix& viewMatrix,
const sk_sp<GrTextureProxy> proxies[kMaxTextures],
const GrSamplerState& params, float lum, uint32_t flags,
- const SkMatrix& localMatrixIfUsesLocalCoords) {
- return sk_sp<GrGeometryProcessor>(new GrDistanceFieldA8TextGeoProc(
- color, proxies, params, lum, flags, localMatrixIfUsesLocalCoords));
+ bool usesLocalCoords) {
+ return sk_sp<GrGeometryProcessor>(
+ new GrDistanceFieldA8TextGeoProc(color, viewMatrix, proxies,
+ params, lum, flags, usesLocalCoords));
}
#else
- static sk_sp<GrGeometryProcessor> Make(GrColor color,
+ static sk_sp<GrGeometryProcessor> Make(GrColor color, const SkMatrix& viewMatrix,
const sk_sp<GrTextureProxy> proxies[kMaxTextures],
const GrSamplerState& params, uint32_t flags,
- const SkMatrix& localMatrixIfUsesLocalCoords) {
- return sk_sp<GrGeometryProcessor>(new GrDistanceFieldA8TextGeoProc(
- color, proxies, params, flags, localMatrixIfUsesLocalCoords));
+ bool usesLocalCoords) {
+ return sk_sp<GrGeometryProcessor>(
+ new GrDistanceFieldA8TextGeoProc(color, viewMatrix, proxies,
+ params, flags, usesLocalCoords));
}
#endif
@@ -82,7 +80,8 @@ public:
const Attribute* inColor() const { return fInColor; }
const Attribute* inTextureCoords() const { return fInTextureCoords; }
GrColor color() const { return fColor; }
- const SkMatrix& localMatrix() const { return fLocalMatrix; }
+ const SkMatrix& viewMatrix() const { return fViewMatrix; }
+ bool usesLocalCoords() const { return fUsesLocalCoords; }
#ifdef SK_GAMMA_APPLY_TO_A8
float getDistanceAdjust() const { return fDistanceAdjust; }
#endif
@@ -95,14 +94,16 @@ public:
GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override;
private:
- GrDistanceFieldA8TextGeoProc(GrColor, const sk_sp<GrTextureProxy> proxies[kMaxTextures],
+ GrDistanceFieldA8TextGeoProc(GrColor, const SkMatrix& viewMatrix,
+ const sk_sp<GrTextureProxy> proxies[kMaxTextures],
const GrSamplerState& params,
#ifdef SK_GAMMA_APPLY_TO_A8
float distanceAdjust,
#endif
- uint32_t flags, const SkMatrix& localMatrix);
+ uint32_t flags, bool usesLocalCoords);
GrColor fColor;
+ SkMatrix fViewMatrix;
TextureSampler fTextureSamplers[kMaxTextures];
#ifdef SK_GAMMA_APPLY_TO_A8
float fDistanceAdjust;
@@ -111,7 +112,7 @@ private:
const Attribute* fInPosition;
const Attribute* fInColor;
const Attribute* fInTextureCoords;
- SkMatrix fLocalMatrix;
+ bool fUsesLocalCoords;
GR_DECLARE_GEOMETRY_PROCESSOR_TEST
@@ -128,7 +129,6 @@ class GrDistanceFieldPathGeoProc : public GrGeometryProcessor {
public:
static constexpr int kMaxTextures = 4;
- /** The local matrix should be identity if local coords are not required by the GrPipeline. */
static sk_sp<GrGeometryProcessor> Make(GrColor color, const SkMatrix& matrix,
const sk_sp<GrTextureProxy> proxies[kMaxTextures],
const GrSamplerState& params, uint32_t flags) {
@@ -197,13 +197,16 @@ public:
static constexpr int kMaxTextures = 4;
static sk_sp<GrGeometryProcessor> Make(GrColor color,
+ const SkMatrix& viewMatrix,
const sk_sp<GrTextureProxy> proxies[kMaxTextures],
const GrSamplerState& params,
DistanceAdjust distanceAdjust,
uint32_t flags,
- const SkMatrix& localMatrixIfUsesLocalCoords) {
- return sk_sp<GrGeometryProcessor>(new GrDistanceFieldLCDTextGeoProc(
- color, proxies, params, distanceAdjust, flags, localMatrixIfUsesLocalCoords));
+ bool usesLocalCoords) {
+ return sk_sp<GrGeometryProcessor>(
+ new GrDistanceFieldLCDTextGeoProc(color, viewMatrix, proxies,
+ params, distanceAdjust,
+ flags, usesLocalCoords));
}
~GrDistanceFieldLCDTextGeoProc() override {}
@@ -215,8 +218,9 @@ public:
const Attribute* inTextureCoords() const { return fInTextureCoords; }
DistanceAdjust getDistanceAdjust() const { return fDistanceAdjust; }
GrColor color() const { return fColor; }
+ const SkMatrix& viewMatrix() const { return fViewMatrix; }
uint32_t getFlags() const { return fFlags; }
- const SkMatrix& localMatrix() const { return fLocalMatrix; }
+ bool usesLocalCoords() const { return fUsesLocalCoords; }
void addNewProxies(const sk_sp<GrTextureProxy> proxies[kMaxTextures], const GrSamplerState& p);
@@ -225,18 +229,20 @@ public:
GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override;
private:
- GrDistanceFieldLCDTextGeoProc(GrColor, const sk_sp<GrTextureProxy> proxies[kMaxTextures],
+ GrDistanceFieldLCDTextGeoProc(GrColor, const SkMatrix& viewMatrix,
+ const sk_sp<GrTextureProxy> proxies[kMaxTextures],
const GrSamplerState& params, DistanceAdjust wa, uint32_t flags,
- const SkMatrix& localMatrix);
+ bool usesLocalCoords);
GrColor fColor;
+ SkMatrix fViewMatrix;
TextureSampler fTextureSamplers[kMaxTextures];
DistanceAdjust fDistanceAdjust;
uint32_t fFlags;
const Attribute* fInPosition;
const Attribute* fInColor;
const Attribute* fInTextureCoords;
- const SkMatrix fLocalMatrix;
+ bool fUsesLocalCoords;
GR_DECLARE_GEOMETRY_PROCESSOR_TEST
diff --git a/src/gpu/glsl/GrGLSLGeometryProcessor.cpp b/src/gpu/glsl/GrGLSLGeometryProcessor.cpp
index 9a768c21b4..9c71042413 100644
--- a/src/gpu/glsl/GrGLSLGeometryProcessor.cpp
+++ b/src/gpu/glsl/GrGLSLGeometryProcessor.cpp
@@ -57,43 +57,40 @@ void GrGLSLGeometryProcessor::emitTransforms(GrGLSLVertexBuilder* vb,
const SkMatrix& localMatrix,
FPCoordTransformHandler* handler) {
SkASSERT(GrSLTypeIsFloatType(localCoordsVar.getType()));
- SkASSERT(2 == GrSLTypeVecLength(localCoordsVar.getType()) ||
- 3 == GrSLTypeVecLength(localCoordsVar.getType()));
+ SkASSERT(2 == GrSLTypeVecLength(localCoordsVar.getType()));
- bool threeComponentLocalCoords = 3 == GrSLTypeVecLength(localCoordsVar.getType());
- SkString localCoords;
- if (threeComponentLocalCoords) {
- localCoords = localCoordsVar.getName();
- } else {
- localCoords.printf("float3(%s, 1)", localCoordsVar.c_str());
- }
int i = 0;
while (const GrCoordTransform* coordTransform = handler->nextCoordTransform()) {
SkString strUniName;
strUniName.printf("CoordTransformMatrix_%d", i);
+ GrSLType varyingType;
+
+ uint32_t type = coordTransform->getMatrix().getType();
+ type |= localMatrix.getType();
+
+ varyingType = SkToBool(SkMatrix::kPerspective_Mask & type) ? kFloat3_GrSLType :
+ kFloat2_GrSLType;
const char* uniName;
+
+
fInstalledTransforms.push_back().fHandle = uniformHandler->addUniform(kVertex_GrShaderFlag,
kFloat3x3_GrSLType,
strUniName.c_str(),
&uniName).toIndex();
- GrSLType varyingType = kFloat2_GrSLType;
- if (localMatrix.hasPerspective() || coordTransform->getMatrix().hasPerspective()) {
- varyingType = kFloat3_GrSLType;
- }
SkString strVaryingName;
strVaryingName.printf("TransformedCoords_%d", i);
+
GrGLSLVarying v(varyingType);
varyingHandler->addVarying(strVaryingName.c_str(), &v);
+ SkASSERT(kFloat2_GrSLType == varyingType || kFloat3_GrSLType == varyingType);
handler->specifyCoordsForCurrCoordTransform(SkString(v.fsIn()), varyingType);
if (kFloat2_GrSLType == varyingType) {
- vb->codeAppendf("%s = (%s * %s).xy;", v.vsOut(), uniName, localCoords.c_str());
- if (threeComponentLocalCoords) {
- vb->codeAppendf("%s /= %s.z;", v.vsOut(), localCoords.c_str());
- }
+ vb->codeAppendf("%s = (%s * float3(%s, 1)).xy;", v.vsOut(), uniName,
+ localCoordsVar.c_str());
} else {
- vb->codeAppendf("%s = %s * %s;", v.vsOut(), uniName, localCoords.c_str());
+ vb->codeAppendf("%s = %s * float3(%s, 1);", v.vsOut(), uniName, localCoordsVar.c_str());
}
++i;
}
diff --git a/src/gpu/glsl/GrGLSLGeometryProcessor.h b/src/gpu/glsl/GrGLSLGeometryProcessor.h
index 36cc546c4c..de1e4fd02a 100644
--- a/src/gpu/glsl/GrGLSLGeometryProcessor.h
+++ b/src/gpu/glsl/GrGLSLGeometryProcessor.h
@@ -29,8 +29,7 @@ protected:
FPCoordTransformIter*);
// Emit transformed local coords from the vertex shader as a uniform matrix and varying per
- // coord-transform. localCoordsVar must be a 2- or 3-component vector. If it is 3 then it is
- // assumed to be a 2D homogeneous coordinate.
+ // coord-transform.
void emitTransforms(GrGLSLVertexBuilder*,
GrGLSLVaryingHandler*,
GrGLSLUniformHandler*,
diff --git a/src/gpu/ops/GrAtlasTextOp.cpp b/src/gpu/ops/GrAtlasTextOp.cpp
index d71cd92fde..6743feaae6 100644
--- a/src/gpu/ops/GrAtlasTextOp.cpp
+++ b/src/gpu/ops/GrAtlasTextOp.cpp
@@ -6,12 +6,14 @@
*/
#include "GrAtlasTextOp.h"
+
#include "GrContext.h"
#include "GrOpFlushState.h"
#include "GrResourceProvider.h"
+
#include "SkGlyphCache.h"
#include "SkMathPriv.h"
-#include "SkPoint3.h"
+
#include "effects/GrBitmapTextGeoProc.h"
#include "effects/GrDistanceFieldGeoProc.h"
#include "text/GrAtlasGlyphCache.h"
@@ -20,35 +22,6 @@
static const int kDistanceAdjustLumShift = 5;
-void GrAtlasTextOp::init() {
- const Geometry& geo = fGeoData[0];
- fColor = geo.fColor;
- SkRect bounds;
- geo.fBlob->computeSubRunBounds(&bounds, geo.fRun, geo.fSubRun, geo.fViewMatrix, geo.fX, geo.fY);
- // We don't have tight bounds on the glyph paths in device space. For the purposes of bounds
- // we treat this as a set of non-AA rects rendered with a texture.
- this->setBounds(bounds, HasAABloat::kNo, IsZeroArea::kNo);
- if (this->usesDistanceFields()) {
- bool isLCD = this->isLCD();
-
- const SkMatrix& viewMatrix = geo.fViewMatrix;
-
- fDFGPFlags = viewMatrix.isSimilarity() ? kSimilarity_DistanceFieldEffectFlag : 0;
- fDFGPFlags |= viewMatrix.isScaleTranslate() ? kScaleOnly_DistanceFieldEffectFlag : 0;
- fDFGPFlags |= viewMatrix.hasPerspective() ? kPerspective_DistanceFieldEffectFlag : 0;
- fDFGPFlags |= fUseGammaCorrectDistanceTable ? kGammaCorrect_DistanceFieldEffectFlag : 0;
- fDFGPFlags |= (kAliasedDistanceField_MaskType == fMaskType)
- ? kAliased_DistanceFieldEffectFlag
- : 0;
-
- if (isLCD) {
- fDFGPFlags |= kUseLCD_DistanceFieldEffectFlag;
- fDFGPFlags |=
- (kLCDBGRDistanceField_MaskType == fMaskType) ? kBGR_DistanceFieldEffectFlag : 0;
- }
- }
-}
-
SkString GrAtlasTextOp::dumpInfo() const {
SkString str;
@@ -210,7 +183,7 @@ void GrAtlasTextOp::onPrepareDraws(Target* target) {
// if we have RGB, then we won't have any SkShaders so no need to use a localmatrix.
// TODO actually only invert if we don't have RGBA
SkMatrix localMatrix;
- if (this->usesLocalCoords() && !fGeoData[0].fViewMatrix.invert(&localMatrix)) {
+ if (this->usesLocalCoords() && !this->viewMatrix().invert(&localMatrix)) {
SkDebugf("Cannot invert viewmatrix\n");
return;
}
@@ -227,10 +200,8 @@ void GrAtlasTextOp::onPrepareDraws(Target* target) {
FlushInfo flushInfo;
flushInfo.fPipeline =
target->makePipeline(fSRGBFlags, std::move(fProcessors), target->detachAppliedClip());
- SkDEBUGCODE(bool dfPerspective = false);
if (this->usesDistanceFields()) {
flushInfo.fGeometryProcessor = this->setupDfProcessor();
- SkDEBUGCODE(dfPerspective = fGeoData[0].fViewMatrix.hasPerspective());
} else {
flushInfo.fGeometryProcessor = GrBitmapTextGeoProc::Make(
this->color(), proxies, GrSamplerState::ClampNearest(), maskFormat,
@@ -239,7 +210,7 @@ void GrAtlasTextOp::onPrepareDraws(Target* target) {
flushInfo.fGlyphsToFlush = 0;
size_t vertexStride = flushInfo.fGeometryProcessor->getVertexStride();
- SkASSERT(vertexStride == GrAtlasTextBlob::GetVertexStride(maskFormat, dfPerspective));
+ SkASSERT(vertexStride == GrAtlasTextBlob::GetVertexStride(maskFormat));
int glyphCount = this->numGlyphs();
const GrBuffer* vertexBuffer;
@@ -271,24 +242,9 @@ void GrAtlasTextOp::onPrepareDraws(Target* target) {
if (args.fClipRect.isEmpty()) {
memcpy(currVertex, result.fFirstVertex, vertexBytes);
} else {
- SkASSERT(!dfPerspective);
clip_quads(args.fClipRect, currVertex, result.fFirstVertex, vertexStride,
result.fGlyphsRegenerated);
}
- if (this->usesDistanceFields() && !args.fViewMatrix.isIdentity()) {
- // We always do the distance field view matrix transformation after copying rather
- // than during blob vertex generation time in the blob as handling successive
- // arbitrary transformations would be complicated and accumulate error.
- if (args.fViewMatrix.hasPerspective()) {
- auto* pos = reinterpret_cast<SkPoint3*>(currVertex);
- args.fViewMatrix.mapHomogeneousPointsWithStride(
- pos, pos, vertexStride, result.fGlyphsRegenerated * kVerticesPerGlyph);
- } else {
- auto* pos = reinterpret_cast<SkPoint*>(currVertex);
- args.fViewMatrix.mapPointsWithStride(
- pos, vertexStride, result.fGlyphsRegenerated * kVerticesPerGlyph);
- }
- }
flushInfo.fGlyphsToFlush += result.fGlyphsRegenerated;
if (!result.fFinished) {
this->flush(target, &flushInfo);
@@ -344,23 +300,19 @@ bool GrAtlasTextOp::onCombineIfPossible(GrOp* t, const GrCaps& caps) {
return false;
}
- const SkMatrix& thisFirstMatrix = fGeoData[0].fViewMatrix;
- const SkMatrix& thatFirstMatrix = that->fGeoData[0].fViewMatrix;
-
- if (this->usesLocalCoords() && !thisFirstMatrix.cheapEqualTo(thatFirstMatrix)) {
- return false;
- }
-
- if (this->usesDistanceFields()) {
- if (fDFGPFlags != that->fDFGPFlags) {
+ if (!this->usesDistanceFields()) {
+ if (kColorBitmapMask_MaskType == fMaskType && this->color() != that->color()) {
return false;
}
-
- if (fLuminanceColor != that->fLuminanceColor) {
+ if (this->usesLocalCoords() && !this->viewMatrix().cheapEqualTo(that->viewMatrix())) {
return false;
}
} else {
- if (kColorBitmapMask_MaskType == fMaskType && this->color() != that->color()) {
+ if (!this->viewMatrix().cheapEqualTo(that->viewMatrix())) {
+ return false;
+ }
+
+ if (fLuminanceColor != that->fLuminanceColor) {
return false;
}
}
@@ -406,18 +358,20 @@ bool GrAtlasTextOp::onCombineIfPossible(GrOp* t, const GrCaps& caps) {
// TODO trying to figure out why lcd is so whack
// (see comments in GrAtlasTextContext::ComputeCanonicalColor)
sk_sp<GrGeometryProcessor> GrAtlasTextOp::setupDfProcessor() const {
+ const SkMatrix& viewMatrix = this->viewMatrix();
const sk_sp<GrTextureProxy>* p = fFontCache->getProxies(this->maskFormat());
bool isLCD = this->isLCD();
-
- SkMatrix localMatrix = SkMatrix::I();
- if (this->usesLocalCoords()) {
- // If this fails we'll just use I().
- bool result = fGeoData[0].fViewMatrix.invert(&localMatrix);
- (void)result;
- }
+ // set up any flags
+ uint32_t flags = viewMatrix.isSimilarity() ? kSimilarity_DistanceFieldEffectFlag : 0;
+ flags |= viewMatrix.isScaleTranslate() ? kScaleOnly_DistanceFieldEffectFlag : 0;
+ flags |= fUseGammaCorrectDistanceTable ? kGammaCorrect_DistanceFieldEffectFlag : 0;
+ flags |= (kAliasedDistanceField_MaskType == fMaskType) ? kAliased_DistanceFieldEffectFlag : 0;
// see if we need to create a new effect
if (isLCD) {
+ flags |= kUseLCD_DistanceFieldEffectFlag;
+ flags |= (kLCDBGRDistanceField_MaskType == fMaskType) ? kBGR_DistanceFieldEffectFlag : 0;
+
float redCorrection = fDistanceAdjustTable->getAdjustment(
SkColorGetR(fLuminanceColor) >> kDistanceAdjustLumShift,
fUseGammaCorrectDistanceTable);
@@ -430,8 +384,10 @@ sk_sp<GrGeometryProcessor> GrAtlasTextOp::setupDfProcessor() const {
GrDistanceFieldLCDTextGeoProc::DistanceAdjust widthAdjust =
GrDistanceFieldLCDTextGeoProc::DistanceAdjust::Make(
redCorrection, greenCorrection, blueCorrection);
- return GrDistanceFieldLCDTextGeoProc::Make(this->color(), p, GrSamplerState::ClampBilerp(),
- widthAdjust, fDFGPFlags, localMatrix);
+
+ return GrDistanceFieldLCDTextGeoProc::Make(this->color(), viewMatrix, p,
+ GrSamplerState::ClampBilerp(), widthAdjust,
+ flags, this->usesLocalCoords());
} else {
#ifdef SK_GAMMA_APPLY_TO_A8
float correction = 0;
@@ -441,11 +397,13 @@ sk_sp<GrGeometryProcessor> GrAtlasTextOp::setupDfProcessor() const {
correction = fDistanceAdjustTable->getAdjustment(lum >> kDistanceAdjustLumShift,
fUseGammaCorrectDistanceTable);
}
- return GrDistanceFieldA8TextGeoProc::Make(this->color(), p, GrSamplerState::ClampBilerp(),
- correction, fDFGPFlags, localMatrix);
+ return GrDistanceFieldA8TextGeoProc::Make(this->color(), viewMatrix, p,
+ GrSamplerState::ClampBilerp(), correction, flags,
+ this->usesLocalCoords());
#else
- return GrDistanceFieldA8TextGeoProc::Make(this->color(), p, GrSamplerState::ClampBilerp(),
- fDFGPFlags, localMatrix);
+ return GrDistanceFieldA8TextGeoProc::Make(this->color(), viewMatrix, p,
+ GrSamplerState::ClampBilerp(), flags,
+ this->usesLocalCoords());
#endif
}
}
diff --git a/src/gpu/ops/GrAtlasTextOp.h b/src/gpu/ops/GrAtlasTextOp.h
index cb15c36fb8..d31a3297ec 100644
--- a/src/gpu/ops/GrAtlasTextOp.h
+++ b/src/gpu/ops/GrAtlasTextOp.h
@@ -87,8 +87,16 @@ public:
// init() so the op can initialize itself
Geometry& geometry() { return fGeoData[0]; }
- /** Called after this->geometry() has been configured. */
- void init();
+ void init() {
+ const Geometry& geo = fGeoData[0];
+ fColor = geo.fColor;
+ SkRect bounds;
+ geo.fBlob->computeSubRunBounds(&bounds, geo.fRun, geo.fSubRun, geo.fViewMatrix, geo.fX,
+ geo.fY);
+ // We don't have tight bounds on the glyph paths in device space. For the purposes of bounds
+ // we treat this as a set of non-AA rects rendered with a texture.
+ this->setBounds(bounds, HasAABloat::kNo, IsZeroArea::kNo);
+ }
const char* name() const override { return "AtlasTextOp"; }
@@ -179,6 +187,7 @@ private:
inline void flush(GrMeshDrawOp::Target* target, FlushInfo* flushInfo) const;
GrColor color() const { return fColor; }
+ const SkMatrix& viewMatrix() const { return fGeoData[0].fViewMatrix; }
bool usesLocalCoords() const { return fUsesLocalCoords; }
int numGlyphs() const { return fNumGlyphs; }
@@ -203,7 +212,6 @@ private:
sk_sp<const GrDistanceFieldAdjustTable> fDistanceAdjustTable;
SkColor fLuminanceColor;
bool fUseGammaCorrectDistanceTable;
- uint32_t fDFGPFlags = 0;
typedef GrMeshDrawOp INHERITED;
};
diff --git a/src/gpu/text/GrAtlasTextBlob.cpp b/src/gpu/text/GrAtlasTextBlob.cpp
index 02f3ab0a21..0b25a34ed1 100644
--- a/src/gpu/text/GrAtlasTextBlob.cpp
+++ b/src/gpu/text/GrAtlasTextBlob.cpp
@@ -96,13 +96,7 @@ void GrAtlasTextBlob::appendGlyph(int runIndex,
run.fInitialized = true;
- bool hasW = subRun->hasWCoord();
- // DF glyphs drawn in perspective must always have a w coord.
- SkASSERT(hasW || !subRun->drawAsDistanceFields() || !fInitialViewMatrix.hasPerspective());
- // Non-DF glyphs should never have a w coord.
- SkASSERT(!hasW || subRun->drawAsDistanceFields());
-
- size_t vertexStride = GetVertexStride(format, hasW);
+ size_t vertexStride = GetVertexStride(format);
subRun->setMaskFormat(format);
@@ -111,29 +105,53 @@ void GrAtlasTextBlob::appendGlyph(int runIndex,
intptr_t vertex = reinterpret_cast<intptr_t>(this->fVertices + subRun->vertexEndIndex());
- // We always write the third position component used by SDFs. If it is unused it gets
- // overwritten. Similarly, we always write the color and the blob will later overwrite it
- // with texture coords if it is unused.
- size_t colorOffset = hasW ? sizeof(SkPoint3) : sizeof(SkPoint);
- // V0
- *reinterpret_cast<SkPoint3*>(vertex) = {positions.fLeft, positions.fTop, 1.f};
- *reinterpret_cast<GrColor*>(vertex + colorOffset) = color;
- vertex += vertexStride;
-
- // V1
- *reinterpret_cast<SkPoint3*>(vertex) = {positions.fLeft, positions.fBottom, 1.f};
- *reinterpret_cast<GrColor*>(vertex + colorOffset) = color;
- vertex += vertexStride;
-
- // V2
- *reinterpret_cast<SkPoint3*>(vertex) = {positions.fRight, positions.fTop, 1.f};
- *reinterpret_cast<GrColor*>(vertex + colorOffset) = color;
- vertex += vertexStride;
-
- // V3
- *reinterpret_cast<SkPoint3*>(vertex) = {positions.fRight, positions.fBottom, 1.f};
- *reinterpret_cast<GrColor*>(vertex + colorOffset) = color;
-
+ if (kARGB_GrMaskFormat != glyph->fMaskFormat) {
+ // V0
+ SkPoint* position = reinterpret_cast<SkPoint*>(vertex);
+ position->set(positions.fLeft, positions.fTop);
+ SkColor* colorPtr = reinterpret_cast<SkColor*>(vertex + sizeof(SkPoint));
+ *colorPtr = color;
+ vertex += vertexStride;
+
+ // V1
+ position = reinterpret_cast<SkPoint*>(vertex);
+ position->set(positions.fLeft, positions.fBottom);
+ colorPtr = reinterpret_cast<SkColor*>(vertex + sizeof(SkPoint));
+ *colorPtr = color;
+ vertex += vertexStride;
+
+ // V2
+ position = reinterpret_cast<SkPoint*>(vertex);
+ position->set(positions.fRight, positions.fTop);
+ colorPtr = reinterpret_cast<SkColor*>(vertex + sizeof(SkPoint));
+ *colorPtr = color;
+ vertex += vertexStride;
+
+ // V3
+ position = reinterpret_cast<SkPoint*>(vertex);
+ position->set(positions.fRight, positions.fBottom);
+ colorPtr = reinterpret_cast<SkColor*>(vertex + sizeof(SkPoint));
+ *colorPtr = color;
+ } else {
+ // V0
+ SkPoint* position = reinterpret_cast<SkPoint*>(vertex);
+ position->set(positions.fLeft, positions.fTop);
+ vertex += vertexStride;
+
+ // V1
+ position = reinterpret_cast<SkPoint*>(vertex);
+ position->set(positions.fLeft, positions.fBottom);
+ vertex += vertexStride;
+
+ // V2
+ position = reinterpret_cast<SkPoint*>(vertex);
+ position->set(positions.fRight, positions.fTop);
+ vertex += vertexStride;
+
+ // V3
+ position = reinterpret_cast<SkPoint*>(vertex);
+ position->set(positions.fRight, positions.fBottom);
+ }
subRun->appendVertices(vertexStride);
fGlyphs[subRun->glyphEndIndex()] = glyph;
subRun->glyphAppended();
@@ -167,7 +185,6 @@ bool GrAtlasTextBlob::mustRegenerate(const GrTextUtils::Paint& paint,
return true;
}
- /** This could be relaxed for blobs with only distance field glyphs. */
if (fInitialViewMatrix.hasPerspective() && !fInitialViewMatrix.cheapEqualTo(viewMatrix)) {
return true;
}
diff --git a/src/gpu/text/GrAtlasTextBlob.h b/src/gpu/text/GrAtlasTextBlob.h
index 282fa98141..450e256d38 100644
--- a/src/gpu/text/GrAtlasTextBlob.h
+++ b/src/gpu/text/GrAtlasTextBlob.h
@@ -17,7 +17,6 @@
#include "SkMaskFilter.h"
#include "SkOpts.h"
#include "SkPathEffect.h"
-#include "SkPoint3.h"
#include "SkRasterizer.h"
#include "SkSurfaceProps.h"
#include "SkTInternalLList.h"
@@ -54,12 +53,6 @@ public:
static sk_sp<GrAtlasTextBlob> Make(GrMemoryPool* pool, int glyphCount, int runCount);
- /**
- * We currently force regeneration of a blob if old or new matrix differ in having perspective.
- * If we ever change that then the key must contain the perspectiveness when there are distance
- * fields as perspective distance field use 3 component vertex positions and non-perspective
- * uses 2.
- */
struct Key {
Key() {
sk_bzero(this, sizeof(Key));
@@ -133,13 +126,12 @@ public:
}
// sets the last subrun of runIndex to use distance field text
- void setSubRunHasDistanceFields(int runIndex, bool hasLCD, bool isAntiAlias, bool hasWCoord) {
+ void setSubRunHasDistanceFields(int runIndex, bool hasLCD, bool isAntiAlias) {
Run& run = fRuns[runIndex];
Run::SubRunInfo& subRun = run.fSubRunInfo.back();
subRun.setUseLCDText(hasLCD);
subRun.setAntiAliased(isAntiAlias);
subRun.setDrawAsDistanceFields();
- subRun.setHasWCoord(hasWCoord);
}
void setRunDrawAsPaths(int runIndex) {
@@ -177,15 +169,13 @@ public:
SkGlyphCache*, const SkGlyph& skGlyph,
SkScalar x, SkScalar y, SkScalar scale, bool treatAsBMP);
- static size_t GetVertexStride(GrMaskFormat maskFormat, bool isDistanceFieldWithWCoord) {
+ static size_t GetVertexStride(GrMaskFormat maskFormat) {
switch (maskFormat) {
case kA8_GrMaskFormat:
- return isDistanceFieldWithWCoord ? kGrayTextDFPerspectiveVASize : kGrayTextVASize;
+ return kGrayTextVASize;
case kARGB_GrMaskFormat:
- SkASSERT(!isDistanceFieldWithWCoord);
return kColorTextVASize;
default:
- SkASSERT(!isDistanceFieldWithWCoord);
return kLCDTextVASize;
}
}
@@ -242,10 +232,8 @@ public:
// position + local coord
static const size_t kColorTextVASize = sizeof(SkPoint) + sizeof(SkIPoint16);
static const size_t kGrayTextVASize = sizeof(SkPoint) + sizeof(GrColor) + sizeof(SkIPoint16);
- static const size_t kGrayTextDFPerspectiveVASize =
- sizeof(SkPoint3) + sizeof(GrColor) + sizeof(SkIPoint16);
static const size_t kLCDTextVASize = kGrayTextVASize;
- static const size_t kMaxVASize = kGrayTextDFPerspectiveVASize;
+ static const size_t kMaxVASize = kGrayTextVASize;
static const int kVerticesPerGlyph = 4;
static void AssertEqual(const GrAtlasTextBlob&, const GrAtlasTextBlob&);
@@ -431,7 +419,7 @@ private:
// This function assumes the translation will be applied before it is called again
void computeTranslation(const SkMatrix& viewMatrix, SkScalar x, SkScalar y,
- SkScalar* transX, SkScalar* transY);
+ SkScalar*transX, SkScalar* transY);
// df properties
void setDrawAsDistanceFields() { fFlags |= kDrawAsSDF_Flag; }
@@ -444,17 +432,12 @@ private:
fFlags = antiAliased ? fFlags | kAntiAliased_Flag : fFlags & ~kAntiAliased_Flag;
}
bool isAntiAliased() const { return SkToBool(fFlags & kAntiAliased_Flag); }
- void setHasWCoord(bool hasW) {
- fFlags = hasW ? (fFlags | kHasWCoord_Flag) : fFlags & ~kHasWCoord_Flag;
- }
- bool hasWCoord() const { return SkToBool(fFlags & kHasWCoord_Flag); }
private:
enum Flag {
kDrawAsSDF_Flag = 0x1,
kUseLCDText_Flag = 0x2,
- kAntiAliased_Flag = 0x4,
- kHasWCoord_Flag = 0x8
+ kAntiAliased_Flag = 0x4
};
GrDrawOpAtlas::BulkUseTokenUpdater fBulkUseToken;
diff --git a/src/gpu/text/GrAtlasTextBlobVertexRegenerator.cpp b/src/gpu/text/GrAtlasTextBlobVertexRegenerator.cpp
index 1be5ae330c..28b2e0f0c0 100644
--- a/src/gpu/text/GrAtlasTextBlobVertexRegenerator.cpp
+++ b/src/gpu/text/GrAtlasTextBlobVertexRegenerator.cpp
@@ -71,8 +71,8 @@ inline void regen_vertices(char* vertex, const GrGlyph* glyph, size_t vertexStri
// This is a bit wonky, but sometimes we have LCD text, in which case we won't have color
// vertices, hence vertexStride - sizeof(SkIPoint16)
+ intptr_t colorOffset = sizeof(SkPoint);
intptr_t texCoordOffset = vertexStride - sizeof(SkIPoint16);
- intptr_t colorOffset = texCoordOffset - sizeof(GrColor);
// V0
if (regenPos) {
@@ -211,9 +211,8 @@ Regenerator::Result Regenerator::doRegen() {
}
}
- bool hasW = fSubRun->hasWCoord();
Result result;
- auto vertexStride = GetVertexStride(fSubRun->maskFormat(), hasW);
+ auto vertexStride = GetVertexStride(fSubRun->maskFormat());
char* currVertex = fBlob->fVertices + fSubRun->vertexStartIndex() +
fCurrGlyph * kVerticesPerGlyph * vertexStride;
result.fFirstVertex = currVertex;
@@ -301,8 +300,7 @@ Regenerator::Result Regenerator::regenerate() {
return this->doRegen<false, true, true, true>();
case kNoRegen: {
Result result;
- bool hasW = fSubRun->hasWCoord();
- auto vertexStride = GetVertexStride(fSubRun->maskFormat(), hasW);
+ auto vertexStride = GetVertexStride(fSubRun->maskFormat());
result.fGlyphsRegenerated = fSubRun->glyphCount() - fCurrGlyph;
result.fFirstVertex = fBlob->fVertices + fSubRun->vertexStartIndex() +
fCurrGlyph * kVerticesPerGlyph * vertexStride;
diff --git a/src/gpu/text/GrAtlasTextContext.cpp b/src/gpu/text/GrAtlasTextContext.cpp
index 3faa0f7b87..d617786944 100644
--- a/src/gpu/text/GrAtlasTextContext.cpp
+++ b/src/gpu/text/GrAtlasTextContext.cpp
@@ -646,14 +646,13 @@ void GrAtlasTextContext::drawDFPosText(GrAtlasTextBlob* blob, int runIndex,
SkTDArray<char> fallbackTxt;
SkTDArray<SkScalar> fallbackPos;
- bool hasWCoord = viewMatrix.hasPerspective();
// Setup distance field paint and text ratio
SkScalar textRatio;
SkPaint dfPaint(paint);
this->initDistanceFieldPaint(blob, &dfPaint, &textRatio, viewMatrix);
blob->setHasDistanceField();
blob->setSubRunHasDistanceFields(runIndex, paint.skPaint().isLCDRenderText(),
- paint.skPaint().isAntiAlias(), hasWCoord);
+ paint.skPaint().isAntiAlias());
GrAtlasTextStrike* currStrike = nullptr;