diff options
-rw-r--r-- | gm/dftext_blob_persp.cpp | 143 | ||||
-rw-r--r-- | gn/gm.gni | 1 | ||||
-rw-r--r-- | include/core/SkMatrix.h | 3 | ||||
-rw-r--r-- | src/core/SkMatrix.cpp | 24 | ||||
-rw-r--r-- | src/gpu/effects/GrDistanceFieldGeoProc.cpp | 150 | ||||
-rw-r--r-- | src/gpu/effects/GrDistanceFieldGeoProc.h | 66 | ||||
-rw-r--r-- | src/gpu/glsl/GrGLSLGeometryProcessor.cpp | 33 | ||||
-rw-r--r-- | src/gpu/glsl/GrGLSLGeometryProcessor.h | 3 | ||||
-rw-r--r-- | src/gpu/ops/GrAtlasTextOp.cpp | 106 | ||||
-rw-r--r-- | src/gpu/ops/GrAtlasTextOp.h | 14 | ||||
-rw-r--r-- | src/gpu/text/GrAtlasTextBlob.cpp | 79 | ||||
-rw-r--r-- | src/gpu/text/GrAtlasTextBlob.h | 29 | ||||
-rw-r--r-- | src/gpu/text/GrAtlasTextBlobVertexRegenerator.cpp | 8 | ||||
-rw-r--r-- | src/gpu/text/GrAtlasTextContext.cpp | 3 |
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;) @@ -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; |