Chromium Code Reviews| OLD | NEW |
|---|---|
| (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 | |
| OLD | NEW |