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