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