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