Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(31)

Side by Side Diff: bench/ETCBitmapBench.cpp

Issue 317023002: Two new benches for ETC1 bitmaps. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Code review changes Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | gyp/bench.gypi » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright 2014 Google 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 "SkBenchmark.h"
9 #include "SkCanvas.h"
10 #include "SkData.h"
11 #include "SkDecodingImageGenerator.h"
12 #include "SkImageDecoder.h"
13 #include "SkOSFile.h"
14
15 #ifndef SK_IGNORE_ETC1_SUPPORT
16
17 #include "etc1.h"
18
19 // This takes the etc1 data pointed to by orig, and copies it `factor` times in each
20 // dimension. The return value is the new data or NULL on error.
21 static etc1_byte* create_expanded_etc1_bitmap(const uint8_t* orig, int factor) {
22 SkASSERT(NULL != orig);
23 SkASSERT(factor > 1);
24
25 const etc1_byte* origData = reinterpret_cast<const etc1_byte*>(orig);
26 if (!etc1_pkm_is_valid(orig)) {
27 return NULL;
28 }
29
30 etc1_uint32 origWidth = etc1_pkm_get_width(origData);
31 etc1_uint32 origHeight = etc1_pkm_get_height(origData);
32
33 // The width and height must be aligned along block boundaries
34 if ((origWidth & 3) != 0 || (origHeight & 3) != 0) {
35 return NULL;
36 }
37
38 // The picture must be at least as large as a block.
39 if (origWidth <= 4 || origHeight <= 4) {
40 return NULL;
41 }
42
43 etc1_uint32 newWidth = origWidth * factor;
44 etc1_uint32 newHeight = origHeight * factor;
45
46 etc1_uint32 newDataSz = etc1_get_encoded_data_size(newWidth, newHeight);
47 etc1_byte* newData = reinterpret_cast<etc1_byte *>(
48 sk_malloc_throw(newDataSz + ETC_PKM_HEADER_SIZE));
49 etc1_pkm_format_header(newData, newWidth, newHeight);
50
51 etc1_byte* copyInto = newData;
52
53 copyInto += ETC_PKM_HEADER_SIZE;
54 origData += ETC_PKM_HEADER_SIZE;
55
56 etc1_uint32 origBlocksX = (origWidth >> 2);
57 etc1_uint32 origBlocksY = (origHeight >> 2);
58 etc1_uint32 newBlocksY = (newHeight >> 2);
59 etc1_uint32 origRowSzInBytes = origBlocksX * ETC1_ENCODED_BLOCK_SIZE;
60
61 for (etc1_uint32 j = 0; j < newBlocksY; ++j) {
62 const etc1_byte* rowStart = origData + ((j % origBlocksY) * origRowSzInB ytes);
63 for(etc1_uint32 i = 0; i < newWidth; i += origWidth) {
64 memcpy(copyInto, rowStart, origRowSzInBytes);
65 copyInto += origRowSzInBytes;
66 }
67 }
68 return newData;
69 }
70
71 // This is the base class for all of the benches in this file. In general
72 // the ETC1 benches should all be working on the same data. Due to the
73 // simplicity of the PKM file, that data is the 128x128 mandrill etc1
74 // compressed texture repeated by some factor (currently 8 -> 1024x1024)
75 class ETCBitmapBenchBase : public SkBenchmark {
76 public:
77 ETCBitmapBenchBase() : fPKMData(this->loadPKM()) {
78 if (NULL == fPKMData) {
79 SkDebugf("Could not load PKM data!");
80 }
81 }
82
83 protected:
84 SkAutoDataUnref fPKMData;
85
86 private:
87 SkData *loadPKM() {
88 SkString filename = SkOSPath::SkPathJoin(
89 INHERITED::GetResourcePath().c_str(), "mandrill_128.pkm");
90
91 // Expand the data
92 SkAutoDataUnref fileData(SkData::NewFromFileName(filename.c_str()));
93 if (NULL == fileData) {
94 SkDebugf("Could not open the file. Did you forget to set the resourc ePath?\n");
95 return NULL;
96 }
97
98 const etc1_uint32 kExpansionFactor = 8;
99 etc1_byte* expandedETC1 =
100 create_expanded_etc1_bitmap(fileData->bytes(), kExpansionFactor);
101 if (NULL == expandedETC1) {
102 SkDebugf("Error expanding ETC1 data by factor of %d\n", kExpansionFa ctor);
103 return NULL;
104 }
105
106 etc1_uint32 width = etc1_pkm_get_width(expandedETC1);
107 etc1_uint32 height = etc1_pkm_get_width(expandedETC1);
108 etc1_uint32 dataSz = ETC_PKM_HEADER_SIZE + etc1_get_encoded_data_size(wi dth, height);
109 return SkData::NewFromMalloc(expandedETC1, dataSz);
110 }
111
112 typedef SkBenchmark INHERITED;
113 };
114
115 // This is the rendering benchmark. Prior to rendering the data, create a
116 // bitmap using the etc1 data.
117 class ETCBitmapBench : public ETCBitmapBenchBase {
118 public:
119 ETCBitmapBench(bool decompress, Backend backend)
120 : fDecompress(decompress), fBackend(backend) { }
121
122 virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
123 return backend == this->fBackend;
124 }
125
126 protected:
127 virtual const char* onGetName() SK_OVERRIDE {
128 if (kGPU_Backend == this->fBackend) {
129 if (this->fDecompress) {
130 return "etc1bitmap_render_gpu_decompressed";
131 } else {
132 return "etc1bitmap_render_gpu_compressed";
133 }
134 } else {
135 SkASSERT(kRaster_Backend == this->fBackend);
136 if (this->fDecompress) {
137 return "etc1bitmap_render_raster_decompressed";
138 } else {
139 return "etc1bitmap_render_raster_compressed";
140 }
141 }
142 }
143
144 virtual void onPreDraw() SK_OVERRIDE {
145 if (NULL == fPKMData) {
146 SkDebugf("Failed to load PKM data!\n");
147 return;
148 }
149
150 // Install pixel ref
151 if (!SkInstallDiscardablePixelRef(
152 SkDecodingImageGenerator::Create(
153 fPKMData, SkDecodingImageGenerator::Options()), &(this->fBit map))) {
154 SkDebugf("Could not install discardable pixel ref.\n");
155 return;
156 }
157
158 // Decompress it if necessary
159 if (this->fDecompress) {
160 this->fBitmap.lockPixels();
161 }
162 }
163
164 virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
robertphillips 2014/06/04 19:46:37 ++i ?
krajcevski 2014/06/04 19:57:17 Done.
165 for (int i = 0; i < loops; i++) {
166 canvas->drawBitmap(this->fBitmap, 0, 0, NULL);
167 }
168 }
169
170 protected:
171 SkBitmap fBitmap;
172 bool decompress() const { return fDecompress; }
173 Backend backend() const { return fBackend; }
174 private:
175 const bool fDecompress;
176 const Backend fBackend;
177 typedef ETCBitmapBenchBase INHERITED;
178 };
179
180 // This benchmark is identical to the previous benchmark, but it explicitly forc es
181 // an upload to the GPU before each draw call. We do this by notifying the bitma p
182 // that the pixels have changed (even though they haven't).
183 class ETCBitmapUploadBench : public ETCBitmapBench {
184 public:
185 ETCBitmapUploadBench(bool decompress, Backend backend)
186 : ETCBitmapBench(decompress, backend) { }
187
188 protected:
189 virtual const char* onGetName() SK_OVERRIDE {
190 if (kGPU_Backend == this->backend()) {
191 if (this->decompress()) {
192 return "etc1bitmap_upload_gpu_decompressed";
193 } else {
194 return "etc1bitmap_upload_gpu_compressed";
195 }
196 } else {
197 SkASSERT(kRaster_Backend == this->backend());
198 if (this->decompress()) {
199 return "etc1bitmap_upload_raster_decompressed";
200 } else {
201 return "etc1bitmap_upload_raster_compressed";
202 }
203 }
204 }
205
206 virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
robertphillips 2014/06/04 19:46:37 ++i ?
krajcevski 2014/06/04 19:57:17 Done.
207 for (int i = 0; i < loops; i++) {
208 this->fBitmap.notifyPixelsChanged();
209 canvas->drawBitmap(this->fBitmap, 0, 0, NULL);
210 }
211 }
212
213 private:
214 typedef ETCBitmapBench INHERITED;
215 };
216
217 DEF_BENCH(return new ETCBitmapBench(false, SkBenchmark::kRaster_Backend);)
218 DEF_BENCH(return new ETCBitmapBench(true, SkBenchmark::kRaster_Backend);)
219
220 DEF_BENCH(return new ETCBitmapBench(false, SkBenchmark::kGPU_Backend);)
221 DEF_BENCH(return new ETCBitmapBench(true, SkBenchmark::kGPU_Backend);)
222
223 DEF_BENCH(return new ETCBitmapUploadBench(false, SkBenchmark::kRaster_Backend);)
224 DEF_BENCH(return new ETCBitmapUploadBench(true, SkBenchmark::kRaster_Backend);)
225
226 DEF_BENCH(return new ETCBitmapUploadBench(false, SkBenchmark::kGPU_Backend);)
227 DEF_BENCH(return new ETCBitmapUploadBench(true, SkBenchmark::kGPU_Backend);)
228
229 #endif // SK_IGNORE_ETC1_SUPPORT
OLDNEW
« no previous file with comments | « no previous file | gyp/bench.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698