blob: c66f7b23b96ee03de527e0f7280eb54edf0e8774 [file] [log] [blame]
robertphillips@google.com8cf81e02014-05-22 18:40:29 +00001/*
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"
tfarinabcbc1782014-06-18 14:32:48 -07009
10#include "Resources.h"
robertphillips@google.com8cf81e02014-05-22 18:40:29 +000011#include "SkCanvas.h"
krajcevski9c0e6292014-06-02 07:38:14 -070012#include "SkData.h"
reed5965c8a2015-01-07 18:04:45 -080013#include "SkImageGenerator.h"
robertphillips@google.com8cf81e02014-05-22 18:40:29 +000014#include "SkImageDecoder.h"
15#include "SkOSFile.h"
16
krajcevski2dc337c2014-06-04 09:57:47 -070017#ifndef SK_IGNORE_ETC1_SUPPORT
18
19#include "etc1.h"
20
21/**
22 * Remove the last row and column of ETC1 blocks, effectively
23 * making a texture that started as power of two into a texture
24 * that is no longer power of two...
25 */
26bool slice_etc1_data(void *data, int* width, int* height) {
27
28 // First, parse the data and get to it...
29 etc1_byte *origData = reinterpret_cast<etc1_byte *>(data);
30 if (!etc1_pkm_is_valid(origData)) {
31 return false;
32 }
33
34 int origW = etc1_pkm_get_width(origData);
35 int origH = etc1_pkm_get_height(origData);
36
37 int blockWidth = (origW + 3) >> 2;
38 int blockHeight = (origH + 3) >> 2;
39
40 // Make sure that we have blocks to trim off..
41 if (blockWidth < 2 || blockHeight < 2) {
42 return false;
43 }
44
45 int newWidth = (blockWidth - 1) << 2;
46 int newHeight = (blockHeight - 1) << 2;
47
48 size_t newDataSz = etc1_get_encoded_data_size(newWidth, newHeight) + ETC_PKM_HEADER_SIZE;
49 SkAutoMalloc am(newDataSz);
50
51 etc1_byte *newData = reinterpret_cast<etc1_byte *>(am.get());
52
53 etc1_pkm_format_header(newData, newWidth, newHeight);
54 newData += ETC_PKM_HEADER_SIZE;
55 origData += ETC_PKM_HEADER_SIZE;
56
57 for (int j = 0; j < blockHeight - 1; ++j) {
58 memcpy(newData, origData, (blockWidth - 1)*ETC1_ENCODED_BLOCK_SIZE);
59 origData += blockWidth*ETC1_ENCODED_BLOCK_SIZE;
60 newData += (blockWidth - 1)*ETC1_ENCODED_BLOCK_SIZE;
61 }
62
63 // Stick the data back whence it came
64 memcpy(data, am.get(), newDataSz);
65 *width = newWidth;
66 *height = newHeight;
67
68 return true;
69}
70#endif // SK_IGNORE_ETC1_SUPPORT
71
robertphillips@google.com8cf81e02014-05-22 18:40:29 +000072namespace skiagm {
73
74/**
krajcevski99ffe242014-06-03 13:04:35 -070075 * Test decoding an image from a PKM or KTX file and then
robertphillips@google.com8cf81e02014-05-22 18:40:29 +000076 * from compressed ETC1 data.
77 */
78class ETC1BitmapGM : public GM {
79public:
80 ETC1BitmapGM() { }
81 virtual ~ETC1BitmapGM() { }
82
83protected:
mtklein36352bf2015-03-25 18:17:31 -070084 SkString onShortName() override {
krajcevski99ffe242014-06-03 13:04:35 -070085 SkString str = SkString("etc1bitmap_");
86 str.append(this->fileExtension());
87 return str;
robertphillips@google.com8cf81e02014-05-22 18:40:29 +000088 }
89
mtklein36352bf2015-03-25 18:17:31 -070090 SkISize onISize() override {
tfarinaf5393182014-06-09 23:59:03 -070091 return SkISize::Make(128, 128);
robertphillips@google.com8cf81e02014-05-22 18:40:29 +000092 }
93
krajcevski99ffe242014-06-03 13:04:35 -070094 virtual SkString fileExtension() const = 0;
robertphillips@google.com8cf81e02014-05-22 18:40:29 +000095
mtklein36352bf2015-03-25 18:17:31 -070096 void onDraw(SkCanvas* canvas) override {
robertphillips@google.com8cf81e02014-05-22 18:40:29 +000097 SkBitmap bm;
tfarinac846f4a2014-07-01 12:35:49 -070098 SkString filename = GetResourcePath("mandrill_128.");
krajcevski99ffe242014-06-03 13:04:35 -070099 filename.append(this->fileExtension());
mtklein04cd3682014-06-03 09:04:33 -0700100 SkAutoTUnref<SkData> fileData(SkData::NewFromFileName(filename.c_str()));
krajcevski9c0e6292014-06-02 07:38:14 -0700101 if (NULL == fileData) {
102 SkDebugf("Could not open the file. Did you forget to set the resourcePath?\n");
robertphillips@google.com8cf81e02014-05-22 18:40:29 +0000103 return;
104 }
krajcevski9c0e6292014-06-02 07:38:14 -0700105
reed5965c8a2015-01-07 18:04:45 -0800106 if (!SkInstallDiscardablePixelRef(fileData, &bm)) {
krajcevski9c0e6292014-06-02 07:38:14 -0700107 SkDebugf("Could not install discardable pixel ref.\n");
108 return;
109 }
110
robertphillips@google.com8cf81e02014-05-22 18:40:29 +0000111 canvas->drawBitmap(bm, 0, 0);
112 }
113
114private:
115 typedef GM INHERITED;
116};
117
krajcevski99ffe242014-06-03 13:04:35 -0700118// This class specializes ETC1BitmapGM to load the mandrill_128.pkm file.
119class ETC1Bitmap_PKM_GM : public ETC1BitmapGM {
120public:
121 ETC1Bitmap_PKM_GM() : ETC1BitmapGM() { }
122 virtual ~ETC1Bitmap_PKM_GM() { }
123
124protected:
125
mtklein36352bf2015-03-25 18:17:31 -0700126 SkString fileExtension() const override { return SkString("pkm"); }
krajcevski99ffe242014-06-03 13:04:35 -0700127
128private:
129 typedef ETC1BitmapGM INHERITED;
130};
131
132// This class specializes ETC1BitmapGM to load the mandrill_128.ktx file.
133class ETC1Bitmap_KTX_GM : public ETC1BitmapGM {
134public:
135 ETC1Bitmap_KTX_GM() : ETC1BitmapGM() { }
136 virtual ~ETC1Bitmap_KTX_GM() { }
137
138protected:
139
mtklein36352bf2015-03-25 18:17:31 -0700140 SkString fileExtension() const override { return SkString("ktx"); }
krajcevski99ffe242014-06-03 13:04:35 -0700141
142private:
143 typedef ETC1BitmapGM INHERITED;
144};
145
krajcevskia50b8f02014-08-08 11:38:27 -0700146// This class specializes ETC1BitmapGM to load the mandrill_128.r11.ktx file.
147class ETC1Bitmap_R11_KTX_GM : public ETC1BitmapGM {
148public:
149 ETC1Bitmap_R11_KTX_GM() : ETC1BitmapGM() { }
150 virtual ~ETC1Bitmap_R11_KTX_GM() { }
151
152protected:
153
mtklein36352bf2015-03-25 18:17:31 -0700154 SkString fileExtension() const override { return SkString("r11.ktx"); }
krajcevskia50b8f02014-08-08 11:38:27 -0700155
156private:
157 typedef ETC1BitmapGM INHERITED;
158};
159
krajcevski2dc337c2014-06-04 09:57:47 -0700160#ifndef SK_IGNORE_ETC1_SUPPORT
161/**
162 * Test decoding an image from a PKM file and then
163 * from non-power-of-two compressed ETC1 data. First slice
164 * off a row and column of blocks in order to make it non-power
165 * of two.
166 */
167class ETC1Bitmap_NPOT_GM : public GM {
168public:
169 ETC1Bitmap_NPOT_GM() { }
170 virtual ~ETC1Bitmap_NPOT_GM() { }
171
172protected:
mtklein36352bf2015-03-25 18:17:31 -0700173 SkString onShortName() override {
krajcevski2dc337c2014-06-04 09:57:47 -0700174 return SkString("etc1bitmap_npot");
175 }
176
mtklein36352bf2015-03-25 18:17:31 -0700177 SkISize onISize() override {
tfarinaf5393182014-06-09 23:59:03 -0700178 return SkISize::Make(124, 124);
krajcevski2dc337c2014-06-04 09:57:47 -0700179 }
180
mtklein36352bf2015-03-25 18:17:31 -0700181 void onDraw(SkCanvas* canvas) override {
krajcevski2dc337c2014-06-04 09:57:47 -0700182 SkBitmap bm;
tfarinac846f4a2014-07-01 12:35:49 -0700183 SkString pkmFilename = GetResourcePath("mandrill_128.pkm");
184 SkAutoDataUnref fileData(SkData::NewFromFileName(pkmFilename.c_str()));
krajcevski2dc337c2014-06-04 09:57:47 -0700185 if (NULL == fileData) {
186 SkDebugf("Could not open the file. Did you forget to set the resourcePath?\n");
187 return;
188 }
189
190 SkAutoMalloc am(fileData->size());
191 memcpy(am.get(), fileData->data(), fileData->size());
192
193 int width, height;
194 if (!slice_etc1_data(am.get(), &width, &height)) {
195 SkDebugf("ETC1 Data is poorly formatted.\n");
196 return;
197 }
198
199 SkASSERT(124 == width);
200 SkASSERT(124 == height);
201
202 size_t dataSz = etc1_get_encoded_data_size(width, height) + ETC_PKM_HEADER_SIZE;
203 SkAutoDataUnref nonPOTData(SkData::NewWithCopy(am.get(), dataSz));
204
reed5965c8a2015-01-07 18:04:45 -0800205 if (!SkInstallDiscardablePixelRef(nonPOTData, &bm)) {
krajcevski2dc337c2014-06-04 09:57:47 -0700206 SkDebugf("Could not install discardable pixel ref.\n");
207 return;
208 }
209
210 canvas->drawBitmap(bm, 0, 0);
211 }
212
213private:
214 typedef GM INHERITED;
215};
216#endif // SK_IGNORE_ETC1_SUPPORT
217
robertphillips@google.com8cf81e02014-05-22 18:40:29 +0000218} // namespace skiagm
219
220//////////////////////////////////////////////////////////////////////////////
221
krajcevski99ffe242014-06-03 13:04:35 -0700222DEF_GM( return SkNEW(skiagm::ETC1Bitmap_PKM_GM); )
223DEF_GM( return SkNEW(skiagm::ETC1Bitmap_KTX_GM); )
krajcevskia50b8f02014-08-08 11:38:27 -0700224DEF_GM( return SkNEW(skiagm::ETC1Bitmap_R11_KTX_GM); )
krajcevski2dc337c2014-06-04 09:57:47 -0700225
226#ifndef SK_IGNORE_ETC1_SUPPORT
227DEF_GM( return SkNEW(skiagm::ETC1Bitmap_NPOT_GM); )
228#endif // SK_IGNORE_ETC1_SUPPORT