OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2014 Google Inc. | 2 * Copyright 2014 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "gm.h" | 8 #include "gm.h" |
9 #include "SkCanvas.h" | 9 #include "SkCanvas.h" |
10 #include "SkData.h" | 10 #include "SkData.h" |
11 #include "SkDecodingImageGenerator.h" | 11 #include "SkDecodingImageGenerator.h" |
12 #include "SkImageDecoder.h" | 12 #include "SkImageDecoder.h" |
13 #include "SkOSFile.h" | 13 #include "SkOSFile.h" |
14 | 14 |
| 15 #ifndef SK_IGNORE_ETC1_SUPPORT |
| 16 |
| 17 #include "etc1.h" |
| 18 |
| 19 /** |
| 20 * Remove the last row and column of ETC1 blocks, effectively |
| 21 * making a texture that started as power of two into a texture |
| 22 * that is no longer power of two... |
| 23 */ |
| 24 bool slice_etc1_data(void *data, int* width, int* height) { |
| 25 |
| 26 // First, parse the data and get to it... |
| 27 etc1_byte *origData = reinterpret_cast<etc1_byte *>(data); |
| 28 if (!etc1_pkm_is_valid(origData)) { |
| 29 return false; |
| 30 } |
| 31 |
| 32 int origW = etc1_pkm_get_width(origData); |
| 33 int origH = etc1_pkm_get_height(origData); |
| 34 |
| 35 int blockWidth = (origW + 3) >> 2; |
| 36 int blockHeight = (origH + 3) >> 2; |
| 37 |
| 38 // Make sure that we have blocks to trim off.. |
| 39 if (blockWidth < 2 || blockHeight < 2) { |
| 40 return false; |
| 41 } |
| 42 |
| 43 int newWidth = (blockWidth - 1) << 2; |
| 44 int newHeight = (blockHeight - 1) << 2; |
| 45 |
| 46 size_t newDataSz = etc1_get_encoded_data_size(newWidth, newHeight) + ETC_PKM
_HEADER_SIZE; |
| 47 SkAutoMalloc am(newDataSz); |
| 48 |
| 49 etc1_byte *newData = reinterpret_cast<etc1_byte *>(am.get()); |
| 50 |
| 51 etc1_pkm_format_header(newData, newWidth, newHeight); |
| 52 newData += ETC_PKM_HEADER_SIZE; |
| 53 origData += ETC_PKM_HEADER_SIZE; |
| 54 |
| 55 for (int j = 0; j < blockHeight - 1; ++j) { |
| 56 memcpy(newData, origData, (blockWidth - 1)*ETC1_ENCODED_BLOCK_SIZE); |
| 57 origData += blockWidth*ETC1_ENCODED_BLOCK_SIZE; |
| 58 newData += (blockWidth - 1)*ETC1_ENCODED_BLOCK_SIZE; |
| 59 } |
| 60 |
| 61 // Stick the data back whence it came |
| 62 memcpy(data, am.get(), newDataSz); |
| 63 *width = newWidth; |
| 64 *height = newHeight; |
| 65 |
| 66 return true; |
| 67 } |
| 68 #endif // SK_IGNORE_ETC1_SUPPORT |
| 69 |
15 namespace skiagm { | 70 namespace skiagm { |
16 | 71 |
17 /** | 72 /** |
18 * Test decoding an image from a PKM or KTX file and then | 73 * Test decoding an image from a PKM or KTX file and then |
19 * from compressed ETC1 data. | 74 * from compressed ETC1 data. |
20 */ | 75 */ |
21 class ETC1BitmapGM : public GM { | 76 class ETC1BitmapGM : public GM { |
22 public: | 77 public: |
23 ETC1BitmapGM() { } | 78 ETC1BitmapGM() { } |
24 virtual ~ETC1BitmapGM() { } | 79 virtual ~ETC1BitmapGM() { } |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
83 virtual ~ETC1Bitmap_KTX_GM() { } | 138 virtual ~ETC1Bitmap_KTX_GM() { } |
84 | 139 |
85 protected: | 140 protected: |
86 | 141 |
87 virtual SkString fileExtension() const SK_OVERRIDE { return SkString("ktx");
} | 142 virtual SkString fileExtension() const SK_OVERRIDE { return SkString("ktx");
} |
88 | 143 |
89 private: | 144 private: |
90 typedef ETC1BitmapGM INHERITED; | 145 typedef ETC1BitmapGM INHERITED; |
91 }; | 146 }; |
92 | 147 |
| 148 #ifndef SK_IGNORE_ETC1_SUPPORT |
| 149 /** |
| 150 * Test decoding an image from a PKM file and then |
| 151 * from non-power-of-two compressed ETC1 data. First slice |
| 152 * off a row and column of blocks in order to make it non-power |
| 153 * of two. |
| 154 */ |
| 155 class ETC1Bitmap_NPOT_GM : public GM { |
| 156 public: |
| 157 ETC1Bitmap_NPOT_GM() { } |
| 158 virtual ~ETC1Bitmap_NPOT_GM() { } |
| 159 |
| 160 protected: |
| 161 virtual SkString onShortName() SK_OVERRIDE { |
| 162 return SkString("etc1bitmap_npot"); |
| 163 } |
| 164 |
| 165 virtual SkISize onISize() SK_OVERRIDE { |
| 166 return make_isize(124, 124); |
| 167 } |
| 168 |
| 169 virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE { |
| 170 |
| 171 SkBitmap bm; |
| 172 SkString filename = SkOSPath::SkPathJoin( |
| 173 INHERITED::gResourcePath.c_str(), "mandrill_128.pkm"); |
| 174 |
| 175 SkAutoDataUnref fileData(SkData::NewFromFileName(filename.c_str())); |
| 176 if (NULL == fileData) { |
| 177 SkDebugf("Could not open the file. Did you forget to set the resourc
ePath?\n"); |
| 178 return; |
| 179 } |
| 180 |
| 181 SkAutoMalloc am(fileData->size()); |
| 182 memcpy(am.get(), fileData->data(), fileData->size()); |
| 183 |
| 184 int width, height; |
| 185 if (!slice_etc1_data(am.get(), &width, &height)) { |
| 186 SkDebugf("ETC1 Data is poorly formatted.\n"); |
| 187 return; |
| 188 } |
| 189 |
| 190 SkASSERT(124 == width); |
| 191 SkASSERT(124 == height); |
| 192 |
| 193 size_t dataSz = etc1_get_encoded_data_size(width, height) + ETC_PKM_HEAD
ER_SIZE; |
| 194 SkAutoDataUnref nonPOTData(SkData::NewWithCopy(am.get(), dataSz)); |
| 195 |
| 196 if (!SkInstallDiscardablePixelRef( |
| 197 SkDecodingImageGenerator::Create( |
| 198 nonPOTData, SkDecodingImageGenerator::Options()), &bm)) { |
| 199 SkDebugf("Could not install discardable pixel ref.\n"); |
| 200 return; |
| 201 } |
| 202 |
| 203 canvas->drawBitmap(bm, 0, 0); |
| 204 } |
| 205 |
| 206 private: |
| 207 typedef GM INHERITED; |
| 208 }; |
| 209 #endif // SK_IGNORE_ETC1_SUPPORT |
| 210 |
93 } // namespace skiagm | 211 } // namespace skiagm |
94 | 212 |
95 ////////////////////////////////////////////////////////////////////////////// | 213 ////////////////////////////////////////////////////////////////////////////// |
96 | 214 |
97 DEF_GM( return SkNEW(skiagm::ETC1Bitmap_PKM_GM); ) | 215 DEF_GM( return SkNEW(skiagm::ETC1Bitmap_PKM_GM); ) |
98 DEF_GM( return SkNEW(skiagm::ETC1Bitmap_KTX_GM); ) | 216 DEF_GM( return SkNEW(skiagm::ETC1Bitmap_KTX_GM); ) |
| 217 |
| 218 #ifndef SK_IGNORE_ETC1_SUPPORT |
| 219 DEF_GM( return SkNEW(skiagm::ETC1Bitmap_NPOT_GM); ) |
| 220 #endif // SK_IGNORE_ETC1_SUPPORT |
OLD | NEW |