Home | History | Annotate | Download | only in gm
      1 /*
      2  * Copyright 2013 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 // GM to stress the GPU font cache
      9 // It's not necessary to run this with CPU configs
     10 
     11 #include "gm.h"
     12 
     13 #if SK_SUPPORT_GPU
     14 
     15 #include "GrContext.h"
     16 #include "GrContextOptions.h"
     17 #include "SkCanvas.h"
     18 #include "SkGraphics.h"
     19 #include "SkImage.h"
     20 #include "SkTypeface.h"
     21 #include "gm.h"
     22 #include "sk_tool_utils.h"
     23 
     24 static SkScalar draw_string(SkCanvas* canvas, const SkString& text, SkScalar x,
     25                            SkScalar y, const SkPaint& paint) {
     26     canvas->drawString(text, x, y, paint);
     27     return x + paint.measureText(text.c_str(), text.size());
     28 }
     29 
     30 class FontCacheGM : public skiagm::GM {
     31 public:
     32     FontCacheGM(GrContextOptions::Enable allowMultipleTextures)
     33         : fAllowMultipleTextures(allowMultipleTextures) {
     34         this->setBGColor(SK_ColorLTGRAY);
     35     }
     36 
     37     void modifyGrContextOptions(GrContextOptions* options) override {
     38         options->fGlyphCacheTextureMaximumBytes = 0;
     39         options->fAllowMultipleGlyphCacheTextures = fAllowMultipleTextures;
     40     }
     41 
     42 protected:
     43     SkString onShortName() override {
     44         SkString name("fontcache");
     45         if (GrContextOptions::Enable::kYes == fAllowMultipleTextures) {
     46             name.append("-mt");
     47         }
     48         return name;
     49     }
     50 
     51     SkISize onISize() override { return SkISize::Make(kSize, kSize); }
     52 
     53     void onOnceBeforeDraw() override {
     54         fTypefaces[0] = sk_tool_utils::create_portable_typeface("serif", SkFontStyle::Italic());
     55         fTypefaces[1] = sk_tool_utils::create_portable_typeface("sans-serif",SkFontStyle::Italic());
     56         fTypefaces[2] = sk_tool_utils::create_portable_typeface("serif", SkFontStyle::Normal());
     57         fTypefaces[3] =
     58                 sk_tool_utils::create_portable_typeface("sans-serif", SkFontStyle::Normal());
     59         fTypefaces[4] = sk_tool_utils::create_portable_typeface("serif", SkFontStyle::Bold());
     60         fTypefaces[5] = sk_tool_utils::create_portable_typeface("sans-serif", SkFontStyle::Bold());
     61     }
     62 
     63     void onDraw(SkCanvas* canvas) override {
     64         GrRenderTargetContext* renderTargetContext =
     65             canvas->internal_private_accessTopLayerRenderTargetContext();
     66         if (!renderTargetContext) {
     67             skiagm::GM::DrawGpuOnlyMessage(canvas);
     68             return;
     69         }
     70 
     71         canvas->clear(SK_ColorLTGRAY);
     72         this->drawText(canvas);
     73         //  Debugging tool for GPU.
     74         static const bool kShowAtlas = false;
     75         if (kShowAtlas) {
     76             if (auto ctx = canvas->getGrContext()) {
     77                 auto img = ctx->getFontAtlasImage_ForTesting(kA8_GrMaskFormat);
     78                 canvas->drawImage(img, 0, 0);
     79             }
     80         }
     81     }
     82 
     83 private:
     84     void drawText(SkCanvas* canvas) {
     85         static const int kSizes[] = {8, 9, 10, 11, 12, 13, 18, 20, 25};
     86 
     87         static const SkString kTexts[] = {SkString("ABCDEFGHIJKLMNOPQRSTUVWXYZ"),
     88                                           SkString("abcdefghijklmnopqrstuvwxyz"),
     89                                           SkString("0123456789"),
     90                                           SkString("!@#$%^&*()<>[]{}")};
     91         SkPaint paint;
     92         paint.setAntiAlias(true);
     93         paint.setLCDRenderText(false);
     94         paint.setSubpixelText(true);
     95 
     96         static const SkScalar kSubPixelInc = 1 / 2.f;
     97         SkScalar x = 0;
     98         SkScalar y = 10;
     99         SkScalar subpixelX = 0;
    100         SkScalar subpixelY = 0;
    101         bool offsetX = true;
    102 
    103         if (GrContextOptions::Enable::kYes == fAllowMultipleTextures) {
    104             canvas->scale(10, 10);
    105         }
    106 
    107         do {
    108             for (auto s : kSizes) {
    109                 auto size = 2 * s;
    110                 paint.setTextSize(size);
    111                 for (const auto& typeface : fTypefaces) {
    112                     paint.setTypeface(typeface);
    113                     for (const auto& text : kTexts) {
    114                         x = size + draw_string(canvas, text, x + subpixelX, y + subpixelY, paint);
    115                         x = SkScalarCeilToScalar(x);
    116                         if (x + 100 > kSize) {
    117                             x = 0;
    118                             y += SkScalarCeilToScalar(size + 3);
    119                             if (y > kSize) {
    120                                 return;
    121                             }
    122                         }
    123                     }
    124                 }
    125                 (offsetX ? subpixelX : subpixelY) += kSubPixelInc;
    126                 offsetX = !offsetX;
    127             }
    128         } while (true);
    129     }
    130 
    131     static constexpr SkScalar kSize = 1280;
    132 
    133     GrContextOptions::Enable fAllowMultipleTextures;
    134     sk_sp<SkTypeface> fTypefaces[6];
    135     typedef GM INHERITED;
    136 };
    137 
    138 constexpr SkScalar FontCacheGM::kSize;
    139 
    140 //////////////////////////////////////////////////////////////////////////////
    141 
    142 DEF_GM(return new FontCacheGM(GrContextOptions::Enable::kNo))
    143 DEF_GM(return new FontCacheGM(GrContextOptions::Enable::kYes))
    144 
    145 #endif
    146