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