diff options
-rw-r--r-- | gm/fontcache.cpp | 41 | ||||
-rw-r--r-- | gn/samples.gni | 1 | ||||
-rw-r--r-- | samplecode/SampleFlutterAnimate.cpp | 115 | ||||
-rw-r--r-- | src/gpu/GrContext.cpp | 20 | ||||
-rw-r--r-- | src/gpu/effects/GrAtlasedShaderHelpers.h | 28 | ||||
-rw-r--r-- | src/gpu/effects/GrBitmapTextGeoProc.cpp | 3 | ||||
-rw-r--r-- | src/gpu/effects/GrDistanceFieldGeoProc.cpp | 9 | ||||
-rw-r--r-- | src/gpu/text/GrAtlasTextBlobVertexRegenerator.cpp | 40 |
8 files changed, 223 insertions, 34 deletions
diff --git a/gm/fontcache.cpp b/gm/fontcache.cpp index ce919e9df5..f7a1313fb9 100644 --- a/gm/fontcache.cpp +++ b/gm/fontcache.cpp @@ -5,6 +5,13 @@ * found in the LICENSE file. */ +// GM to stress the GPU font cache +// It's not necessary to run this with CPU configs + +#include "gm.h" + +#if SK_SUPPORT_GPU + #include "GrContext.h" #include "GrContextOptions.h" #include "SkCanvas.h" @@ -14,8 +21,6 @@ #include "gm.h" #include "sk_tool_utils.h" -// GM to stress the GPU font cache - static SkScalar draw_string(SkCanvas* canvas, const SkString& text, SkScalar x, SkScalar y, const SkPaint& paint) { canvas->drawString(text, x, y, paint); @@ -24,16 +29,23 @@ static SkScalar draw_string(SkCanvas* canvas, const SkString& text, SkScalar x, class FontCacheGM : public skiagm::GM { public: - FontCacheGM() { this->setBGColor(SK_ColorLTGRAY); } + FontCacheGM(GrContextOptions::Enable allowMultipleTextures) + : fAllowMultipleTextures(allowMultipleTextures) { + this->setBGColor(SK_ColorLTGRAY); + } void modifyGrContextOptions(GrContextOptions* options) override { options->fGlyphCacheTextureMaximumBytes = 0; - options->fAllowMultipleGlyphCacheTextures = GrContextOptions::Enable::kNo; + options->fAllowMultipleGlyphCacheTextures = fAllowMultipleTextures; } protected: SkString onShortName() override { - return SkString("fontcache"); + SkString name("fontcache"); + if (GrContextOptions::Enable::kYes == fAllowMultipleTextures) { + name.append("-mt"); + } + return name; } SkISize onISize() override { return SkISize::Make(kSize, kSize); } @@ -49,9 +61,15 @@ protected: } void onDraw(SkCanvas* canvas) override { + GrRenderTargetContext* renderTargetContext = + canvas->internal_private_accessTopLayerRenderTargetContext(); + if (!renderTargetContext) { + skiagm::GM::DrawGpuOnlyMessage(canvas); + return; + } + canvas->clear(SK_ColorLTGRAY); this->drawText(canvas); -#if SK_SUPPORT_GPU // Debugging tool for GPU. static const bool kShowAtlas = false; if (kShowAtlas) { @@ -60,7 +78,6 @@ protected: canvas->drawImage(img, 0, 0); } } -#endif } private: @@ -83,6 +100,10 @@ private: SkScalar subpixelY = 0; bool offsetX = true; + if (GrContextOptions::Enable::kYes == fAllowMultipleTextures) { + canvas->scale(10, 10); + } + do { for (auto s : kSizes) { auto size = 2 * s; @@ -109,6 +130,7 @@ private: static constexpr SkScalar kSize = 1280; + GrContextOptions::Enable fAllowMultipleTextures; sk_sp<SkTypeface> fTypefaces[6]; typedef GM INHERITED; }; @@ -117,4 +139,7 @@ constexpr SkScalar FontCacheGM::kSize; ////////////////////////////////////////////////////////////////////////////// -DEF_GM(return new FontCacheGM;) +DEF_GM(return new FontCacheGM(GrContextOptions::Enable::kNo)) +DEF_GM(return new FontCacheGM(GrContextOptions::Enable::kYes)) + +#endif diff --git a/gn/samples.gni b/gn/samples.gni index 3ee15aed85..48c580c2a3 100644 --- a/gn/samples.gni +++ b/gn/samples.gni @@ -47,6 +47,7 @@ samples_sources = [ "$_samplecode/SampleFilter2.cpp", "$_samplecode/SampleFilterFuzz.cpp", "$_samplecode/SampleFilterQuality.cpp", + "$_samplecode/SampleFlutterAnimate.cpp", "$_samplecode/SampleFontScalerTest.cpp", "$_samplecode/SampleFuzz.cpp", "$_samplecode/SampleGradients.cpp", diff --git a/samplecode/SampleFlutterAnimate.cpp b/samplecode/SampleFlutterAnimate.cpp new file mode 100644 index 0000000000..813572934e --- /dev/null +++ b/samplecode/SampleFlutterAnimate.cpp @@ -0,0 +1,115 @@ +/* + * Copyright 2018 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SampleCode.h" +#include "SkAnimTimer.h" +#include "SkView.h" +#include "SkCanvas.h" +#include "SkUtils.h" +#include "SkColorPriv.h" +#include "SkColorFilter.h" +#include "SkImage.h" +#include "SkRandom.h" +#include "SkTime.h" +#include "SkTypeface.h" +#include "Timer.h" + +#if SK_SUPPORT_GPU +#include "GrContext.h" +#endif + +// Create an animation of a bunch of letters that rotate in place. This is intended to stress +// the glyph atlas and test that we don't see corruption or bad slowdowns. +class FlutterAnimateView : public SampleView { +public: + FlutterAnimateView() : fCurrTime(0), fResetTime(0) {} + +protected: + void onOnceBeforeDraw() override { + fTypeface = SkTypeface::MakeFromFile("/skimages/samplefont.ttf"); + initChars(); + } + + // overrides from SkEventSink + bool onQuery(SkEvent* evt) override { + if (SampleCode::TitleQ(*evt)) { + SampleCode::TitleR(evt, "FlutterAnimate"); + return true; + } + + return this->INHERITED::onQuery(evt); + } + + void onDrawContent(SkCanvas* canvas) override { + SkPaint paint; + paint.setTypeface(fTypeface); + paint.setAntiAlias(true); + paint.setFilterQuality(kMedium_SkFilterQuality); + paint.setTextSize(50); + + // rough center of each glyph + static constexpr auto kMidX = 35; + static constexpr auto kMidY = 50; + + canvas->clear(SK_ColorWHITE); + for (int i = 0; i < kNumChars; ++i) { + canvas->save(); + double rot = SkScalarInterp(fChars[i].fStartRotation, fChars[i].fEndRotation, + fCurrTime/kDuration); + canvas->translate(fChars[i].fPosition.fX + kMidX, fChars[i].fPosition.fY - kMidY); + canvas->rotate(SkRadiansToDegrees(rot)); + canvas->translate(-35,+50); + canvas->drawString(fChars[i].fChar, 0, 0, paint); + canvas->restore(); + } + } + + bool onAnimate(const SkAnimTimer& timer) override { + fCurrTime = timer.secs() - fResetTime; + if (fCurrTime > kDuration) { + this->initChars(); + fResetTime = timer.secs(); + fCurrTime = 0; + } + + return true; + } + +private: + void initChars() { + for (int i = 0; i < kNumChars; ++i) { + char c = fRand.nextULessThan(26) + 65; + fChars[i].fChar[0] = c; + fChars[i].fChar[1] = '\0'; + fChars[i].fPosition = SkPoint::Make(fRand.nextF()*748 + 10, fRand.nextF()*1004 + 10); + fChars[i].fStartRotation = fRand.nextF(); + fChars[i].fEndRotation = fRand.nextF() * 20 - 10; + } + } + + static constexpr double kDuration = 5.0; + double fCurrTime; + double fResetTime; + SkRandom fRand; + + struct AnimatedChar { + char fChar[2]; + SkPoint fPosition; + SkScalar fStartRotation; + SkScalar fEndRotation; + }; + sk_sp<SkTypeface> fTypeface; + static constexpr int kNumChars = 40; + AnimatedChar fChars[kNumChars]; + + typedef SampleView INHERITED; +}; + +////////////////////////////////////////////////////////////////////////////// + +static SkView* MyFactory() { return new FlutterAnimateView; } +static SkViewRegister reg(MyFactory); diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp index f6c66db223..d1060235f9 100644 --- a/src/gpu/GrContext.cpp +++ b/src/gpu/GrContext.cpp @@ -277,20 +277,12 @@ bool GrContext::init(const GrContextOptions& options) { new GrDrawingManager(this, prcOptions, atlasTextContextOptions, &fSingleOwner)); GrDrawOpAtlas::AllowMultitexturing allowMultitexturing; - switch (options.fAllowMultipleGlyphCacheTextures) { - case GrContextOptions::Enable::kDefault: -#ifdef SK_BUILD_FOR_IOS - allowMultitexturing = GrDrawOpAtlas::AllowMultitexturing::kNo; -#else - allowMultitexturing = GrDrawOpAtlas::AllowMultitexturing::kYes; -#endif - break; - case GrContextOptions::Enable::kNo: - allowMultitexturing = GrDrawOpAtlas::AllowMultitexturing::kNo; - break; - case GrContextOptions::Enable::kYes: - allowMultitexturing = GrDrawOpAtlas::AllowMultitexturing::kYes; - break; + if (GrContextOptions::Enable::kNo == options.fAllowMultipleGlyphCacheTextures || + // multitexturing supported only if range can represent the index + texcoords fully + !(fCaps->shaderCaps()->floatIs32Bits() || fCaps->shaderCaps()->integerSupport())) { + allowMultitexturing = GrDrawOpAtlas::AllowMultitexturing::kNo; + } else { + allowMultitexturing = GrDrawOpAtlas::AllowMultitexturing::kYes; } fAtlasGlyphCache = new GrAtlasGlyphCache(this, options.fGlyphCacheTextureMaximumBytes, allowMultitexturing); diff --git a/src/gpu/effects/GrAtlasedShaderHelpers.h b/src/gpu/effects/GrAtlasedShaderHelpers.h index 99bbcc0606..8c09291d6a 100644 --- a/src/gpu/effects/GrAtlasedShaderHelpers.h +++ b/src/gpu/effects/GrAtlasedShaderHelpers.h @@ -8,6 +8,7 @@ #ifndef GrAtlasedShaderHelpers_DEFINED #define GrAtlasedShaderHelpers_DEFINED +#include "GrShaderCaps.h" #include "glsl/GrGLSLPrimitiveProcessor.h" #include "glsl/GrGLSLFragmentShaderBuilder.h" #include "glsl/GrGLSLVarying.h" @@ -22,22 +23,33 @@ static void append_index_uv_varyings(GrGLSLPrimitiveProcessor::EmitArgs& args, // This extracts the texture index and texel coordinates from the same variable // Packing structure: texel coordinates are multiplied by 2 (or shifted left 1) // texture index is stored as lower bits of both x and y - args.fVertBuilder->codeAppendf("half2 indexTexCoords = half2(%s.x, %s.y);", - inTexCoordsName, inTexCoordsName); - args.fVertBuilder->codeAppend("half2 intCoords = floor(0.5*indexTexCoords);"); - args.fVertBuilder->codeAppend("half2 diff = indexTexCoords - 2.0*intCoords;"); - args.fVertBuilder->codeAppend("half texIdx = 2.0*diff.x + diff.y;"); + if (args.fShaderCaps->integerSupport()) { + args.fVertBuilder->codeAppendf("int2 signedCoords = int2(%s.x, %s.y);", + inTexCoordsName, inTexCoordsName); + args.fVertBuilder->codeAppend("int texIdx = 2*(signedCoords.x & 0x1) + (signedCoords.y & 0x1);"); + args.fVertBuilder->codeAppend("float2 unormTexCoords = float2(signedCoords.x/2, signedCoords.y/2);"); + } else { + args.fVertBuilder->codeAppendf("float2 indexTexCoords = float2(%s.x, %s.y);", + inTexCoordsName, inTexCoordsName); + args.fVertBuilder->codeAppend("float2 unormTexCoords = floor(0.5*indexTexCoords);"); + args.fVertBuilder->codeAppend("float2 diff = indexTexCoords - 2.0*unormTexCoords;"); + args.fVertBuilder->codeAppend("float texIdx = 2.0*diff.x + diff.y;"); + } // Multiply by 1/atlasSize to get normalized texture coordinates args.fVaryingHandler->addVarying("TextureCoords", uv); - args.fVertBuilder->codeAppendf("%s = intCoords * %s;", uv->vsOut(), atlasSizeInvName); + args.fVertBuilder->codeAppendf("%s = unormTexCoords * %s;", uv->vsOut(), atlasSizeInvName); - args.fVaryingHandler->addVarying("TexIndex", texIdx); + if (args.fShaderCaps->integerSupport()) { + args.fVaryingHandler->addFlatVarying("TexIndex", texIdx); + } else { + args.fVaryingHandler->addVarying("TexIndex", texIdx); + } args.fVertBuilder->codeAppendf("%s = texIdx;", texIdx->vsOut()); if (st) { args.fVaryingHandler->addVarying("IntTextureCoords", st); - args.fVertBuilder->codeAppendf("%s = intCoords;", st->vsOut()); + args.fVertBuilder->codeAppendf("%s = unormTexCoords;", st->vsOut()); } } diff --git a/src/gpu/effects/GrBitmapTextGeoProc.cpp b/src/gpu/effects/GrBitmapTextGeoProc.cpp index ae1340badc..a9ebdca89f 100644 --- a/src/gpu/effects/GrBitmapTextGeoProc.cpp +++ b/src/gpu/effects/GrBitmapTextGeoProc.cpp @@ -38,7 +38,8 @@ public: &atlasSizeInvName); GrGLSLVarying uv(kFloat2_GrSLType); - GrGLSLVarying texIdx(kHalf_GrSLType); + GrSLType texIdxType = args.fShaderCaps->integerSupport() ? kInt_GrSLType : kFloat_GrSLType; + GrGLSLVarying texIdx(texIdxType); append_index_uv_varyings(args, btgp.inTextureCoords()->fName, atlasSizeInvName, &uv, &texIdx, nullptr); diff --git a/src/gpu/effects/GrDistanceFieldGeoProc.cpp b/src/gpu/effects/GrDistanceFieldGeoProc.cpp index d8944fa9d0..8a1a4de2d1 100644 --- a/src/gpu/effects/GrDistanceFieldGeoProc.cpp +++ b/src/gpu/effects/GrDistanceFieldGeoProc.cpp @@ -66,7 +66,8 @@ public: // add varyings GrGLSLVarying uv(kFloat2_GrSLType); - GrGLSLVarying texIdx(kHalf_GrSLType); + GrSLType texIdxType = args.fShaderCaps->integerSupport() ? kInt_GrSLType : kFloat_GrSLType; + GrGLSLVarying texIdx(texIdxType); GrGLSLVarying st(kFloat2_GrSLType); append_index_uv_varyings(args, dfTexEffect.inTextureCoords()->fName, atlasSizeInvName, &uv, &texIdx, &st); @@ -325,7 +326,8 @@ public: &atlasSizeInvName); GrGLSLVarying uv(kFloat2_GrSLType); - GrGLSLVarying texIdx(kHalf_GrSLType); + GrSLType texIdxType = args.fShaderCaps->integerSupport() ? kInt_GrSLType : kFloat_GrSLType; + GrGLSLVarying texIdx(texIdxType); GrGLSLVarying st(kFloat2_GrSLType); append_index_uv_varyings(args, dfPathEffect.inTextureCoords()->fName, atlasSizeInvName, &uv, &texIdx, &st); @@ -608,7 +610,8 @@ public: // set up varyings GrGLSLVarying uv(kFloat2_GrSLType); - GrGLSLVarying texIdx(kHalf_GrSLType); + GrSLType texIdxType = args.fShaderCaps->integerSupport() ? kInt_GrSLType : kFloat_GrSLType; + GrGLSLVarying texIdx(texIdxType); GrGLSLVarying st(kFloat2_GrSLType); append_index_uv_varyings(args, dfTexEffect.inTextureCoords()->fName, atlasSizeInvName, &uv, &texIdx, &st); diff --git a/src/gpu/text/GrAtlasTextBlobVertexRegenerator.cpp b/src/gpu/text/GrAtlasTextBlobVertexRegenerator.cpp index 1ae2c79fd4..384596ddb6 100644 --- a/src/gpu/text/GrAtlasTextBlobVertexRegenerator.cpp +++ b/src/gpu/text/GrAtlasTextBlobVertexRegenerator.cpp @@ -38,6 +38,11 @@ inline void regen_vertices(char* vertex, const GrGlyph* glyph, size_t vertexStri bool useDistanceFields, SkScalar transX, SkScalar transY, GrColor color) { uint16_t u0, v0, u1, v1; +#ifdef DISPLAY_PAGE_INDEX + // Enable this to visualize the page from which each glyph is being drawn. + // Green Red Magenta Cyan -> 0 1 2 3; Black -> error + SkColor hackColor; +#endif if (regenTexCoords) { SkASSERT(glyph); int width = glyph->fBounds.width(); @@ -67,6 +72,25 @@ inline void regen_vertices(char* vertex, const GrGlyph* glyph, size_t vertexStri u1 |= uBit; v1 <<= 1; v1 |= vBit; +#ifdef DISPLAY_PAGE_INDEX + switch (pageIndex) { + case 0: + hackColor = SK_ColorGREEN; + break; + case 1: + hackColor = SK_ColorRED; + break; + case 2: + hackColor = SK_ColorMAGENTA; + break; + case 3: + hackColor = SK_ColorCYAN; + break; + default: + hackColor = SK_ColorBLACK; + break; + } +#endif } // This is a bit wonky, but sometimes we have LCD text, in which case we won't have color @@ -90,6 +114,10 @@ inline void regen_vertices(char* vertex, const GrGlyph* glyph, size_t vertexStri uint16_t* textureCoords = reinterpret_cast<uint16_t*>(vertex + texCoordOffset); textureCoords[0] = u0; textureCoords[1] = v0; +#ifdef DISPLAY_PAGE_INDEX + SkColor* vcolor = reinterpret_cast<SkColor*>(vertex + colorOffset); + *vcolor = hackColor; +#endif } vertex += vertexStride; @@ -109,6 +137,10 @@ inline void regen_vertices(char* vertex, const GrGlyph* glyph, size_t vertexStri uint16_t* textureCoords = reinterpret_cast<uint16_t*>(vertex + texCoordOffset); textureCoords[0] = u0; textureCoords[1] = v1; +#ifdef DISPLAY_PAGE_INDEX + SkColor* vcolor = reinterpret_cast<SkColor*>(vertex + colorOffset); + *vcolor = hackColor; +#endif } vertex += vertexStride; @@ -128,6 +160,10 @@ inline void regen_vertices(char* vertex, const GrGlyph* glyph, size_t vertexStri uint16_t* textureCoords = reinterpret_cast<uint16_t*>(vertex + texCoordOffset); textureCoords[0] = u1; textureCoords[1] = v0; +#ifdef DISPLAY_PAGE_INDEX + SkColor* vcolor = reinterpret_cast<SkColor*>(vertex + colorOffset); + *vcolor = hackColor; +#endif } vertex += vertexStride; @@ -147,6 +183,10 @@ inline void regen_vertices(char* vertex, const GrGlyph* glyph, size_t vertexStri uint16_t* textureCoords = reinterpret_cast<uint16_t*>(vertex + texCoordOffset); textureCoords[0] = u1; textureCoords[1] = v1; +#ifdef DISPLAY_PAGE_INDEX + SkColor* vcolor = reinterpret_cast<SkColor*>(vertex + colorOffset); + *vcolor = hackColor; +#endif } } |