| 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 "Benchmark.h" |  | 
| 9 #include "Resources.h" |  | 
| 10 #include "SkCanvas.h" |  | 
| 11 #include "SkData.h" |  | 
| 12 #include "SkImageGenerator.h" |  | 
| 13 #include "SkImageDecoder.h" |  | 
| 14 #include "SkOSFile.h" |  | 
| 15 #include "SkPixelRef.h" |  | 
| 16 |  | 
| 17 #ifndef SK_IGNORE_ETC1_SUPPORT |  | 
| 18 |  | 
| 19 #include "etc1.h" |  | 
| 20 |  | 
| 21 // This takes the etc1 data pointed to by orig, and copies it `factor` times in 
     each |  | 
| 22 // dimension. The return value is the new data or nullptr on error. |  | 
| 23 static etc1_byte* create_expanded_etc1_bitmap(const uint8_t* orig, int factor) { |  | 
| 24     SkASSERT(orig); |  | 
| 25     SkASSERT(factor > 1); |  | 
| 26 |  | 
| 27     const etc1_byte* origData = reinterpret_cast<const etc1_byte*>(orig); |  | 
| 28     if (!etc1_pkm_is_valid(orig)) { |  | 
| 29         return nullptr; |  | 
| 30     } |  | 
| 31 |  | 
| 32     etc1_uint32 origWidth = etc1_pkm_get_width(origData); |  | 
| 33     etc1_uint32 origHeight = etc1_pkm_get_height(origData); |  | 
| 34 |  | 
| 35     // The width and height must be aligned along block boundaries |  | 
| 36     static const etc1_uint32 kETC1BlockWidth = 4; |  | 
| 37     static const etc1_uint32 kETC1BlockHeight = 4; |  | 
| 38     if ((origWidth % kETC1BlockWidth) != 0 || |  | 
| 39         (origHeight % kETC1BlockHeight) != 0) { |  | 
| 40         return nullptr; |  | 
| 41     } |  | 
| 42 |  | 
| 43     // The picture must be at least as large as a block. |  | 
| 44     if (origWidth <= kETC1BlockWidth || origHeight <= kETC1BlockHeight) { |  | 
| 45         return nullptr; |  | 
| 46     } |  | 
| 47 |  | 
| 48     etc1_uint32 newWidth = origWidth * factor; |  | 
| 49     etc1_uint32 newHeight = origHeight * factor; |  | 
| 50 |  | 
| 51     etc1_uint32 newDataSz = etc1_get_encoded_data_size(newWidth, newHeight); |  | 
| 52     etc1_byte* newData = reinterpret_cast<etc1_byte *>( |  | 
| 53         sk_malloc_throw(newDataSz + ETC_PKM_HEADER_SIZE)); |  | 
| 54     etc1_pkm_format_header(newData, newWidth, newHeight); |  | 
| 55 |  | 
| 56     etc1_byte* copyInto = newData; |  | 
| 57 |  | 
| 58     copyInto += ETC_PKM_HEADER_SIZE; |  | 
| 59     origData += ETC_PKM_HEADER_SIZE; |  | 
| 60 |  | 
| 61     etc1_uint32 origBlocksX = (origWidth >> 2); |  | 
| 62     etc1_uint32 origBlocksY = (origHeight >> 2); |  | 
| 63     etc1_uint32 newBlocksY = (newHeight >> 2); |  | 
| 64     etc1_uint32 origRowSzInBytes = origBlocksX * ETC1_ENCODED_BLOCK_SIZE; |  | 
| 65 |  | 
| 66     for (etc1_uint32 j = 0; j < newBlocksY; ++j) { |  | 
| 67         const etc1_byte* rowStart = origData + ((j % origBlocksY) * origRowSzInB
     ytes); |  | 
| 68         for(etc1_uint32 i = 0; i < newWidth; i += origWidth) { |  | 
| 69             memcpy(copyInto, rowStart, origRowSzInBytes); |  | 
| 70             copyInto += origRowSzInBytes; |  | 
| 71         } |  | 
| 72     } |  | 
| 73     return newData; |  | 
| 74 } |  | 
| 75 |  | 
| 76 // Defined in SkImageDecoder_ktx.cpp |  | 
| 77 extern SkImageGenerator* decoder_image_generator(SkData*); |  | 
| 78 |  | 
| 79 // This is the base class for all of the benches in this file. In general |  | 
| 80 // the ETC1 benches should all be working on the same data. Due to the |  | 
| 81 // simplicity of the PKM file, that data is the 128x128 mandrill etc1 |  | 
| 82 // compressed texture repeated by some factor (currently 8 -> 1024x1024) |  | 
| 83 class ETCBitmapBenchBase : public Benchmark { |  | 
| 84 public: |  | 
| 85     ETCBitmapBenchBase() : fPKMData(loadPKM()) { |  | 
| 86         if (nullptr == fPKMData) { |  | 
| 87             SkDebugf("Could not load PKM data!\n"); |  | 
| 88         } |  | 
| 89     } |  | 
| 90 |  | 
| 91 protected: |  | 
| 92     SkAutoDataUnref fPKMData; |  | 
| 93 |  | 
| 94 private: |  | 
| 95     SkData* loadPKM() { |  | 
| 96         SkString pkmFilename = GetResourcePath("mandrill_128.pkm"); |  | 
| 97         // Expand the data |  | 
| 98         SkAutoDataUnref fileData(SkData::NewFromFileName(pkmFilename.c_str())); |  | 
| 99         if (nullptr == fileData) { |  | 
| 100             SkDebugf("Could not open the file. Did you forget to set the resourc
     ePath?\n"); |  | 
| 101             return nullptr; |  | 
| 102         } |  | 
| 103 |  | 
| 104         const etc1_uint32 kExpansionFactor = 8; |  | 
| 105         etc1_byte* expandedETC1 = |  | 
| 106             create_expanded_etc1_bitmap(fileData->bytes(), kExpansionFactor); |  | 
| 107         if (nullptr == expandedETC1) { |  | 
| 108             SkDebugf("Error expanding ETC1 data by factor of %d\n", kExpansionFa
     ctor); |  | 
| 109             return nullptr; |  | 
| 110         } |  | 
| 111 |  | 
| 112         etc1_uint32 width = etc1_pkm_get_width(expandedETC1); |  | 
| 113         etc1_uint32 height = etc1_pkm_get_width(expandedETC1); |  | 
| 114         etc1_uint32 dataSz = ETC_PKM_HEADER_SIZE + etc1_get_encoded_data_size(wi
     dth, height); |  | 
| 115         return SkData::NewFromMalloc(expandedETC1, dataSz); |  | 
| 116     } |  | 
| 117 |  | 
| 118     typedef Benchmark INHERITED; |  | 
| 119 }; |  | 
| 120 |  | 
| 121 // This is the rendering benchmark. Prior to rendering the data, create a |  | 
| 122 // bitmap using the etc1 data. |  | 
| 123 class ETCBitmapBench : public ETCBitmapBenchBase { |  | 
| 124 public: |  | 
| 125     ETCBitmapBench(bool decompress, Backend backend) |  | 
| 126         : fDecompress(decompress), fBackend(backend) { } |  | 
| 127 |  | 
| 128     bool isSuitableFor(Backend backend) override { |  | 
| 129         return SkToBool(fImage) && backend == this->fBackend; |  | 
| 130     } |  | 
| 131 |  | 
| 132 protected: |  | 
| 133     const char* onGetName() override { |  | 
| 134         if (kGPU_Backend == this->fBackend) { |  | 
| 135             if (this->fDecompress) { |  | 
| 136                 return "etc1bitmap_render_gpu_decompressed"; |  | 
| 137             } else { |  | 
| 138                 return "etc1bitmap_render_gpu_compressed"; |  | 
| 139             } |  | 
| 140         } else { |  | 
| 141             SkASSERT(kRaster_Backend == this->fBackend); |  | 
| 142             if (this->fDecompress) { |  | 
| 143                 return "etc1bitmap_render_raster_decompressed"; |  | 
| 144             } else { |  | 
| 145                 return "etc1bitmap_render_raster_compressed"; |  | 
| 146             } |  | 
| 147         } |  | 
| 148     } |  | 
| 149 |  | 
| 150     void onDelayedSetup() override { |  | 
| 151         if (nullptr == fPKMData) { |  | 
| 152             SkDebugf("Failed to load PKM data!\n"); |  | 
| 153             return; |  | 
| 154         } |  | 
| 155 |  | 
| 156         if (fDecompress) { |  | 
| 157             SkAutoTDelete<SkImageGenerator> gen(decoder_image_generator(fPKMData
     )); |  | 
| 158             gen->generateBitmap(&fBitmap); |  | 
| 159         } else { |  | 
| 160             fImage.reset(SkImage::NewFromGenerator(decoder_image_generator(fPKMD
     ata))); |  | 
| 161         } |  | 
| 162     } |  | 
| 163 |  | 
| 164     void onDraw(int loops, SkCanvas* canvas) override { |  | 
| 165         for (int i = 0; i < loops; ++i) { |  | 
| 166             if (fDecompress) { |  | 
| 167                 canvas->drawBitmap(this->fBitmap, 0, 0, nullptr); |  | 
| 168             } else { |  | 
| 169                 canvas->drawImage(fImage, 0, 0, nullptr); |  | 
| 170             } |  | 
| 171         } |  | 
| 172     } |  | 
| 173 |  | 
| 174 protected: |  | 
| 175     SkBitmap fBitmap; |  | 
| 176     SkAutoTUnref<SkImage> fImage; |  | 
| 177 |  | 
| 178     bool decompress() const { return fDecompress; } |  | 
| 179     Backend backend() const { return fBackend; } |  | 
| 180 private: |  | 
| 181     const bool fDecompress; |  | 
| 182     const Backend fBackend; |  | 
| 183     typedef ETCBitmapBenchBase INHERITED; |  | 
| 184 }; |  | 
| 185 |  | 
| 186 // This benchmark is identical to the previous benchmark, but it explicitly forc
     es |  | 
| 187 // an upload to the GPU before each draw call. We do this by notifying the bitma
     p |  | 
| 188 // that the pixels have changed (even though they haven't). |  | 
| 189 class ETCBitmapUploadBench : public ETCBitmapBench { |  | 
| 190 public: |  | 
| 191     ETCBitmapUploadBench(bool decompress, Backend backend) |  | 
| 192         : ETCBitmapBench(decompress, backend) { } |  | 
| 193 |  | 
| 194 protected: |  | 
| 195     const char* onGetName() override { |  | 
| 196         if (kGPU_Backend == this->backend()) { |  | 
| 197             if (this->decompress()) { |  | 
| 198                 return "etc1bitmap_upload_gpu_decompressed"; |  | 
| 199             } else { |  | 
| 200                 return "etc1bitmap_upload_gpu_compressed"; |  | 
| 201             } |  | 
| 202         } else { |  | 
| 203             SkASSERT(kRaster_Backend == this->backend()); |  | 
| 204             if (this->decompress()) { |  | 
| 205                 return "etc1bitmap_upload_raster_decompressed"; |  | 
| 206             } else { |  | 
| 207                 return "etc1bitmap_upload_raster_compressed"; |  | 
| 208             } |  | 
| 209         } |  | 
| 210     } |  | 
| 211 |  | 
| 212     void onDraw(int loops, SkCanvas* canvas) override { |  | 
| 213         SkPixelRef* pr = fBitmap.pixelRef(); |  | 
| 214         for (int i = 0; i < loops; ++i) { |  | 
| 215             if (pr) { |  | 
| 216                 pr->notifyPixelsChanged(); |  | 
| 217             } |  | 
| 218             canvas->drawBitmap(this->fBitmap, 0, 0, nullptr); |  | 
| 219         } |  | 
| 220     } |  | 
| 221 |  | 
| 222 private: |  | 
| 223     typedef ETCBitmapBench INHERITED; |  | 
| 224 }; |  | 
| 225 |  | 
| 226 DEF_BENCH(return new ETCBitmapBench(false, Benchmark::kRaster_Backend);) |  | 
| 227 DEF_BENCH(return new ETCBitmapBench(true, Benchmark::kRaster_Backend);) |  | 
| 228 |  | 
| 229 DEF_BENCH(return new ETCBitmapBench(false, Benchmark::kGPU_Backend);) |  | 
| 230 DEF_BENCH(return new ETCBitmapBench(true, Benchmark::kGPU_Backend);) |  | 
| 231 |  | 
| 232 DEF_BENCH(return new ETCBitmapUploadBench(false, Benchmark::kRaster_Backend);) |  | 
| 233 DEF_BENCH(return new ETCBitmapUploadBench(true, Benchmark::kRaster_Backend);) |  | 
| 234 |  | 
| 235 DEF_BENCH(return new ETCBitmapUploadBench(false, Benchmark::kGPU_Backend);) |  | 
| 236 DEF_BENCH(return new ETCBitmapUploadBench(true, Benchmark::kGPU_Backend);) |  | 
| 237 |  | 
| 238 #endif  // SK_IGNORE_ETC1_SUPPORT |  | 
| OLD | NEW | 
|---|