aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/ops
diff options
context:
space:
mode:
authorGravatar Brian Salomon <bsalomon@google.com>2017-12-15 11:41:09 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-12-15 17:06:08 +0000
commit0215e39d7e415d0530231df6ad20d5f215c72152 (patch)
tree91fec56dae447ceb15e1743117a8ff272c60a7c3 /src/gpu/ops
parent29c14a760682e2c449fa043b5e8b69937cb58f3a (diff)
Transform vertices for distance field glyphs on CPU.
This allows batching of DF draws with different view matrices. For perspective matrices this means the transformed position vertex attribute must have w values. Currently, non-perspective DF draws still use 2 component positions, though this could be changed in the future. Consequently, perspective draws can batch with other perspective draws but not non-perspective draws. Adds a GM to test batching and reusing the same blobs with both perspective and non-perspective matrices. Change-Id: I0e42c5449ebf3a5a54025dbcdec824d904d5bd9e Reviewed-on: https://skia-review.googlesource.com/79900 Commit-Queue: Brian Salomon <bsalomon@google.com> Reviewed-by: Jim Van Verth <jvanverth@google.com>
Diffstat (limited to 'src/gpu/ops')
-rw-r--r--src/gpu/ops/GrAtlasTextOp.cpp106
-rw-r--r--src/gpu/ops/GrAtlasTextOp.h14
2 files changed, 77 insertions, 43 deletions
diff --git a/src/gpu/ops/GrAtlasTextOp.cpp b/src/gpu/ops/GrAtlasTextOp.cpp
index 6743feaae6..d71cd92fde 100644
--- a/src/gpu/ops/GrAtlasTextOp.cpp
+++ b/src/gpu/ops/GrAtlasTextOp.cpp
@@ -6,14 +6,12 @@
*/
#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"
@@ -22,6 +20,35 @@
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;
@@ -183,7 +210,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() && !this->viewMatrix().invert(&localMatrix)) {
+ if (this->usesLocalCoords() && !fGeoData[0].fViewMatrix.invert(&localMatrix)) {
SkDebugf("Cannot invert viewmatrix\n");
return;
}
@@ -200,8 +227,10 @@ 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,
@@ -210,7 +239,7 @@ void GrAtlasTextOp::onPrepareDraws(Target* target) {
flushInfo.fGlyphsToFlush = 0;
size_t vertexStride = flushInfo.fGeometryProcessor->getVertexStride();
- SkASSERT(vertexStride == GrAtlasTextBlob::GetVertexStride(maskFormat));
+ SkASSERT(vertexStride == GrAtlasTextBlob::GetVertexStride(maskFormat, dfPerspective));
int glyphCount = this->numGlyphs();
const GrBuffer* vertexBuffer;
@@ -242,9 +271,24 @@ 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);
@@ -300,19 +344,23 @@ bool GrAtlasTextOp::onCombineIfPossible(GrOp* t, const GrCaps& caps) {
return false;
}
- if (!this->usesDistanceFields()) {
- if (kColorBitmapMask_MaskType == fMaskType && this->color() != that->color()) {
+ 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) {
return false;
}
- if (this->usesLocalCoords() && !this->viewMatrix().cheapEqualTo(that->viewMatrix())) {
+
+ if (fLuminanceColor != that->fLuminanceColor) {
return false;
}
} else {
- if (!this->viewMatrix().cheapEqualTo(that->viewMatrix())) {
- return false;
- }
-
- if (fLuminanceColor != that->fLuminanceColor) {
+ if (kColorBitmapMask_MaskType == fMaskType && this->color() != that->color()) {
return false;
}
}
@@ -358,20 +406,18 @@ 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();
- // 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;
+
+ SkMatrix localMatrix = SkMatrix::I();
+ if (this->usesLocalCoords()) {
+ // If this fails we'll just use I().
+ bool result = fGeoData[0].fViewMatrix.invert(&localMatrix);
+ (void)result;
+ }
// 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);
@@ -384,10 +430,8 @@ sk_sp<GrGeometryProcessor> GrAtlasTextOp::setupDfProcessor() const {
GrDistanceFieldLCDTextGeoProc::DistanceAdjust widthAdjust =
GrDistanceFieldLCDTextGeoProc::DistanceAdjust::Make(
redCorrection, greenCorrection, blueCorrection);
-
- return GrDistanceFieldLCDTextGeoProc::Make(this->color(), viewMatrix, p,
- GrSamplerState::ClampBilerp(), widthAdjust,
- flags, this->usesLocalCoords());
+ return GrDistanceFieldLCDTextGeoProc::Make(this->color(), p, GrSamplerState::ClampBilerp(),
+ widthAdjust, fDFGPFlags, localMatrix);
} else {
#ifdef SK_GAMMA_APPLY_TO_A8
float correction = 0;
@@ -397,13 +441,11 @@ sk_sp<GrGeometryProcessor> GrAtlasTextOp::setupDfProcessor() const {
correction = fDistanceAdjustTable->getAdjustment(lum >> kDistanceAdjustLumShift,
fUseGammaCorrectDistanceTable);
}
- return GrDistanceFieldA8TextGeoProc::Make(this->color(), viewMatrix, p,
- GrSamplerState::ClampBilerp(), correction, flags,
- this->usesLocalCoords());
+ return GrDistanceFieldA8TextGeoProc::Make(this->color(), p, GrSamplerState::ClampBilerp(),
+ correction, fDFGPFlags, localMatrix);
#else
- return GrDistanceFieldA8TextGeoProc::Make(this->color(), viewMatrix, p,
- GrSamplerState::ClampBilerp(), flags,
- this->usesLocalCoords());
+ return GrDistanceFieldA8TextGeoProc::Make(this->color(), p, GrSamplerState::ClampBilerp(),
+ fDFGPFlags, localMatrix);
#endif
}
}
diff --git a/src/gpu/ops/GrAtlasTextOp.h b/src/gpu/ops/GrAtlasTextOp.h
index d31a3297ec..cb15c36fb8 100644
--- a/src/gpu/ops/GrAtlasTextOp.h
+++ b/src/gpu/ops/GrAtlasTextOp.h
@@ -87,16 +87,8 @@ public:
// init() so the op can initialize itself
Geometry& geometry() { return fGeoData[0]; }
- 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);
- }
+ /** Called after this->geometry() has been configured. */
+ void init();
const char* name() const override { return "AtlasTextOp"; }
@@ -187,7 +179,6 @@ 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; }
@@ -212,6 +203,7 @@ private:
sk_sp<const GrDistanceFieldAdjustTable> fDistanceAdjustTable;
SkColor fLuminanceColor;
bool fUseGammaCorrectDistanceTable;
+ uint32_t fDFGPFlags = 0;
typedef GrMeshDrawOp INHERITED;
};