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 "gm.h" | |
9 | |
10 #include "Resources.h" | |
11 #include "SkCanvas.h" | |
12 #include "SkData.h" | |
13 #include "SkImage.h" | |
14 #include "SkImageGenerator.h" | |
15 #include "SkOSFile.h" | |
16 #include "SkTemplates.h" | |
17 | |
18 #ifndef SK_IGNORE_ETC1_SUPPORT | |
19 | |
20 #include "etc1.h" | |
21 | |
22 /** | |
23 * Remove the last row and column of ETC1 blocks, effectively | |
24 * making a texture that started as power of two into a texture | |
25 * that is no longer power of two... | |
26 */ | |
27 bool slice_etc1_data(void *data, int* width, int* height) { | |
28 | |
29 // First, parse the data and get to it... | |
30 etc1_byte *origData = reinterpret_cast<etc1_byte *>(data); | |
31 if (!etc1_pkm_is_valid(origData)) { | |
32 return false; | |
33 } | |
34 | |
35 int origW = etc1_pkm_get_width(origData); | |
36 int origH = etc1_pkm_get_height(origData); | |
37 | |
38 int blockWidth = (origW + 3) >> 2; | |
39 int blockHeight = (origH + 3) >> 2; | |
40 | |
41 // Make sure that we have blocks to trim off.. | |
42 if (blockWidth < 2 || blockHeight < 2) { | |
43 return false; | |
44 } | |
45 | |
46 int newWidth = (blockWidth - 1) << 2; | |
47 int newHeight = (blockHeight - 1) << 2; | |
48 | |
49 size_t newDataSz = etc1_get_encoded_data_size(newWidth, newHeight) + ETC_PKM
_HEADER_SIZE; | |
50 SkAutoTMalloc<etc1_byte> am(newDataSz); | |
51 | |
52 etc1_byte* newData = am.get(); | |
53 | |
54 etc1_pkm_format_header(newData, newWidth, newHeight); | |
55 newData += ETC_PKM_HEADER_SIZE; | |
56 origData += ETC_PKM_HEADER_SIZE; | |
57 | |
58 for (int j = 0; j < blockHeight - 1; ++j) { | |
59 memcpy(newData, origData, (blockWidth - 1)*ETC1_ENCODED_BLOCK_SIZE); | |
60 origData += blockWidth*ETC1_ENCODED_BLOCK_SIZE; | |
61 newData += (blockWidth - 1)*ETC1_ENCODED_BLOCK_SIZE; | |
62 } | |
63 | |
64 // Stick the data back whence it came | |
65 memcpy(data, am.get(), newDataSz); | |
66 *width = newWidth; | |
67 *height = newHeight; | |
68 | |
69 return true; | |
70 } | |
71 #endif // SK_IGNORE_ETC1_SUPPORT | |
72 | |
73 namespace skiagm { | |
74 | |
75 /** | |
76 * Test decoding an image from a PKM or KTX file and then | |
77 * from compressed ETC1 data. | |
78 */ | |
79 class ETC1BitmapGM : public GM { | |
80 public: | |
81 ETC1BitmapGM() { } | |
82 virtual ~ETC1BitmapGM() { } | |
83 | |
84 protected: | |
85 SkString onShortName() override { | |
86 SkString str = SkString("etc1bitmap_"); | |
87 str.append(this->fileExtension()); | |
88 return str; | |
89 } | |
90 | |
91 SkISize onISize() override { | |
92 return SkISize::Make(128, 128); | |
93 } | |
94 | |
95 virtual SkString fileExtension() const = 0; | |
96 | |
97 void onDraw(SkCanvas* canvas) override { | |
98 SkBitmap bm; | |
99 SkString filename = GetResourcePath("mandrill_128."); | |
100 filename.append(this->fileExtension()); | |
101 sk_sp<SkData> fileData(SkData::MakeFromFileName(filename.c_str())); | |
102 if (nullptr == fileData) { | |
103 SkDebugf("Could not open the file. Did you forget to set the resourc
ePath?\n"); | |
104 return; | |
105 } | |
106 | |
107 sk_sp<SkImage> image(SkImage::MakeFromEncoded(std::move(fileData))); | |
108 if (nullptr == image) { | |
109 SkDebugf("Could not decode the ETC file. ETC may not be included in
this platform.\n"); | |
110 return; | |
111 } | |
112 canvas->drawImage(image, 0, 0); | |
113 } | |
114 | |
115 private: | |
116 typedef GM INHERITED; | |
117 }; | |
118 | |
119 // This class specializes ETC1BitmapGM to load the mandrill_128.pkm file. | |
120 class ETC1Bitmap_PKM_GM : public ETC1BitmapGM { | |
121 public: | |
122 ETC1Bitmap_PKM_GM() : ETC1BitmapGM() { } | |
123 virtual ~ETC1Bitmap_PKM_GM() { } | |
124 | |
125 protected: | |
126 | |
127 SkString fileExtension() const override { return SkString("pkm"); } | |
128 | |
129 private: | |
130 typedef ETC1BitmapGM INHERITED; | |
131 }; | |
132 | |
133 // This class specializes ETC1BitmapGM to load the mandrill_128.ktx file. | |
134 class ETC1Bitmap_KTX_GM : public ETC1BitmapGM { | |
135 public: | |
136 ETC1Bitmap_KTX_GM() : ETC1BitmapGM() { } | |
137 virtual ~ETC1Bitmap_KTX_GM() { } | |
138 | |
139 protected: | |
140 | |
141 SkString fileExtension() const override { return SkString("ktx"); } | |
142 | |
143 private: | |
144 typedef ETC1BitmapGM INHERITED; | |
145 }; | |
146 | |
147 // This class specializes ETC1BitmapGM to load the mandrill_128.r11.ktx file. | |
148 class ETC1Bitmap_R11_KTX_GM : public ETC1BitmapGM { | |
149 public: | |
150 ETC1Bitmap_R11_KTX_GM() : ETC1BitmapGM() { } | |
151 virtual ~ETC1Bitmap_R11_KTX_GM() { } | |
152 | |
153 protected: | |
154 | |
155 SkString fileExtension() const override { return SkString("r11.ktx"); } | |
156 | |
157 private: | |
158 typedef ETC1BitmapGM INHERITED; | |
159 }; | |
160 | |
161 #ifndef SK_IGNORE_ETC1_SUPPORT | |
162 /** | |
163 * Test decoding an image from a PKM file and then | |
164 * from non-power-of-two compressed ETC1 data. First slice | |
165 * off a row and column of blocks in order to make it non-power | |
166 * of two. | |
167 */ | |
168 class ETC1Bitmap_NPOT_GM : public GM { | |
169 public: | |
170 ETC1Bitmap_NPOT_GM() { } | |
171 virtual ~ETC1Bitmap_NPOT_GM() { } | |
172 | |
173 protected: | |
174 SkString onShortName() override { | |
175 return SkString("etc1bitmap_npot"); | |
176 } | |
177 | |
178 SkISize onISize() override { | |
179 return SkISize::Make(124, 124); | |
180 } | |
181 | |
182 void onDraw(SkCanvas* canvas) override { | |
183 SkBitmap bm; | |
184 SkString pkmFilename = GetResourcePath("mandrill_128.pkm"); | |
185 SkAutoDataUnref fileData(SkData::NewFromFileName(pkmFilename.c_str())); | |
186 if (nullptr == fileData) { | |
187 SkDebugf("Could not open the file. Did you forget to set the resourc
ePath?\n"); | |
188 return; | |
189 } | |
190 | |
191 SkAutoMalloc am(fileData->size()); | |
192 memcpy(am.get(), fileData->data(), fileData->size()); | |
193 | |
194 int width, height; | |
195 if (!slice_etc1_data(am.get(), &width, &height)) { | |
196 SkDebugf("ETC1 Data is poorly formatted.\n"); | |
197 return; | |
198 } | |
199 | |
200 SkASSERT(124 == width); | |
201 SkASSERT(124 == height); | |
202 | |
203 size_t dataSz = etc1_get_encoded_data_size(width, height) + ETC_PKM_HEAD
ER_SIZE; | |
204 sk_sp<SkData> nonPOTData(SkData::MakeWithCopy(am.get(), dataSz)); | |
205 canvas->drawImage(SkImage::MakeFromEncoded(std::move(nonPOTData)).get(),
0, 0); | |
206 } | |
207 | |
208 private: | |
209 typedef GM INHERITED; | |
210 }; | |
211 #endif // SK_IGNORE_ETC1_SUPPORT | |
212 | |
213 } // namespace skiagm | |
214 | |
215 ////////////////////////////////////////////////////////////////////////////// | |
216 | |
217 DEF_GM(return new skiagm::ETC1Bitmap_PKM_GM;) | |
218 DEF_GM(return new skiagm::ETC1Bitmap_KTX_GM;) | |
219 DEF_GM(return new skiagm::ETC1Bitmap_R11_KTX_GM;) | |
220 | |
221 #ifndef SK_IGNORE_ETC1_SUPPORT | |
222 DEF_GM(return new skiagm::ETC1Bitmap_NPOT_GM;) | |
223 #endif // SK_IGNORE_ETC1_SUPPORT | |
OLD | NEW |