xref: /aosp_15_r20/external/skia/tools/viewer/TextureUploadSlide.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2019 Google Inc. and Adobe 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 #include "include/core/SkCanvas.h"
9 #include "include/core/SkPaint.h"
10 #include "include/core/SkSurface.h"
11 #include "include/core/SkTypes.h"
12 #include "include/gpu/ganesh/GrDirectContext.h"
13 #include "include/gpu/ganesh/SkSurfaceGanesh.h"
14 #include "tools/timer/TimeUtils.h"
15 #include "tools/viewer/Slide.h"
16 
17 using namespace skia_private;
18 
19 /**
20  * This sample exercises heavy texture updates and uploads.
21  */
22 class TextureUploadSlide : public Slide {
23 public:
TextureUploadSlide()24     TextureUploadSlide() { fName = "TextureUpload"; }
25 
onChar(SkUnichar uni)26     bool onChar(SkUnichar uni) override {
27         if ('m' == uni) {
28             fDrawTexturesToScreen = !fDrawTexturesToScreen;
29             return true;
30         } else if ('>' == uni) {
31             fTileSize = std::min(kMaxTileSize, 2*fTileSize);
32             fTileRows = kMaxTileSize/fTileSize;
33             fTileCols = kMaxTileSize/fTileSize;
34             fCachedContext = nullptr;
35         } else if ('<' == uni) {
36             fTileSize = std::max(kMinTileSize, fTileSize/2);
37             fTileRows = kMaxTileSize/fTileSize;
38             fTileCols = kMaxTileSize/fTileSize;
39             fCachedContext = nullptr;
40         }
41         return false;
42     }
43 
getDimensions() const44     SkISize getDimensions() const override { return {1024, 1024}; }
45 
draw(SkCanvas * canvas)46     void draw(SkCanvas* canvas) override {
47         canvas->clear(0xFFFFFFFF);
48 #if defined(SK_GANESH)
49         auto direct = GrAsDirectContext(canvas->recordingContext());
50         if (direct) {
51             // One-time context-specific setup.
52             if (direct != fCachedContext) {
53                 fCachedContext = direct;
54                 this->initializeTextures(direct);
55             }
56 
57             // Upload new texture data for all textures, simulating a full page of tiles
58             // needing refresh.
59             int textureCount = fTileRows * fTileCols;
60             for (int i = 0; i < textureCount; i++) {
61                 fTextures[i]->uploadRasterSurface(i == fActiveTileIndex ? fBlueSurface
62                                                                         : fGraySurface);
63             }
64 
65             // Scale grid.
66             canvas->scale(kGridScale, kGridScale);
67 
68             if (fDrawTexturesToScreen) {
69                 for (int y = 0; y < fTileRows; y++) {
70                     for (int x = 0; x < fTileCols; x++) {
71                         int currentIndex = y * fTileCols + x;
72                         canvas->drawImage(fTextures[currentIndex]->getImage(),
73                                           x * fTileSize, y * fTileSize);
74                     }
75                 }
76             }
77         }
78 #endif
79     }
80 
animate(double nanos)81     bool animate(double nanos) override {
82         constexpr SkScalar kDesiredDurationSecs = 16.0f;
83         float numTiles = fTileRows*fTileCols;
84         fActiveTileIndex = floorf(TimeUtils::Scaled(1e-9 * nanos,
85                                                     numTiles/kDesiredDurationSecs, numTiles));
86         return true;
87     }
88 
89 private:
90     class RenderTargetTexture : public SkRefCnt {
91     public:
RenderTargetTexture(GrDirectContext * direct,int size)92         RenderTargetTexture(GrDirectContext* direct, int size) {
93             SkSurfaceProps surfaceProps(0, kRGB_H_SkPixelGeometry);
94             SkImageInfo imageInfo = SkImageInfo::Make(size, size, kRGBA_8888_SkColorType,
95                                                       kPremul_SkAlphaType);
96             fSurface = SkSurfaces::RenderTarget(
97                     direct, skgpu::Budgeted::kNo, imageInfo, 0, &surfaceProps);
98         }
99 
getImage()100         sk_sp<SkImage> getImage() {
101             return fSurface->makeImageSnapshot();
102         }
103 
uploadRasterSurface(sk_sp<SkSurface> rasterSurface)104         void uploadRasterSurface(sk_sp<SkSurface> rasterSurface) {
105             SkPixmap pixmap;
106             rasterSurface->peekPixels(&pixmap);
107             fSurface->writePixels(pixmap, 0, 0);
108         }
109 
110     private:
111         sk_sp<SkSurface> fSurface;
112         sk_sp<SkImage> fCachedImage;
113     };
114 
115     inline static constexpr int kMinTileSize = 128;
116     inline static constexpr int kMaxTileSize = 2048;
117     inline static constexpr float kGridScale = 0.25f;
118 
119     bool fDrawTexturesToScreen = true;
120     int fTileSize = 256;
121     int fTileRows = 8;
122     int fTileCols = 8;
123 
124     sk_sp<SkSurface> fBlueSurface;
125     sk_sp<SkSurface> fGraySurface;
126 
127     TArray<sk_sp<RenderTargetTexture>> fTextures;
128 
129     GrDirectContext* fCachedContext = nullptr;
130 
131     SkScalar fActiveTileIndex = 0;
132 
getFilledRasterSurface(SkColor color,int size)133     sk_sp<SkSurface> getFilledRasterSurface(SkColor color, int size) {
134         sk_sp<SkSurface> surface(SkSurfaces::Raster(SkImageInfo::MakeN32Premul(size, size)));
135         SkCanvas* canvas = surface->getCanvas();
136         canvas->clear(color);
137         return surface;
138     }
initializeTextures(GrDirectContext * direct)139     void initializeTextures(GrDirectContext* direct) {
140         fTextures.clear();
141         int textureCount = fTileRows * fTileCols;
142         for (int i = 0; i < textureCount; i++) {
143             fTextures.emplace_back(new RenderTargetTexture(direct, fTileSize));
144         }
145 
146         // Construct two simple rasters of differing colors to serve
147         // as cpu rasterized data to refresh textures with.
148         fBlueSurface = this->getFilledRasterSurface(SK_ColorBLUE, fTileSize);
149         fGraySurface = this->getFilledRasterSurface(SK_ColorGRAY, fTileSize);
150     }
151 };
152 
153 
154 DEF_SLIDE( return new TextureUploadSlide(); )
155 
156