1
2 /*
3 * Copyright 2014 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9 #include "ktx.h"
10 #include "SkBitmap.h"
11 #include "SkStream.h"
12 #include "SkEndian.h"
13
14 #include "gl/GrGLDefines.h"
15 #include "GrConfig.h"
16
17 #include "etc1.h"
18
compressed_fmt_to_gl_define(SkTextureCompressor::Format fmt)19 static inline uint32_t compressed_fmt_to_gl_define(SkTextureCompressor::Format fmt) {
20 static const uint32_t kGLDefineMap[SkTextureCompressor::kFormatCnt] = {
21 GR_GL_COMPRESSED_LUMINANCE_LATC1, // kLATC_Format
22 GR_GL_COMPRESSED_R11_EAC, // kR11_EAC_Format
23 GR_GL_COMPRESSED_ETC1_RGB8, // kETC1_Format
24 GR_GL_COMPRESSED_RGBA_ASTC_4x4_KHR, // kASTC_4x4_Format
25 GR_GL_COMPRESSED_RGBA_ASTC_5x4_KHR, // kASTC_5x4_Format
26 GR_GL_COMPRESSED_RGBA_ASTC_5x5_KHR, // kASTC_5x5_Format
27 GR_GL_COMPRESSED_RGBA_ASTC_6x5_KHR, // kASTC_6x5_Format
28 GR_GL_COMPRESSED_RGBA_ASTC_6x6_KHR, // kASTC_6x6_Format
29 GR_GL_COMPRESSED_RGBA_ASTC_8x5_KHR, // kASTC_8x5_Format
30 GR_GL_COMPRESSED_RGBA_ASTC_8x6_KHR, // kASTC_8x6_Format
31 GR_GL_COMPRESSED_RGBA_ASTC_8x8_KHR, // kASTC_8x8_Format
32 GR_GL_COMPRESSED_RGBA_ASTC_10x5_KHR, // kASTC_10x5_Format
33 GR_GL_COMPRESSED_RGBA_ASTC_10x6_KHR, // kASTC_10x6_Format
34 GR_GL_COMPRESSED_RGBA_ASTC_10x8_KHR, // kASTC_10x8_Format
35 GR_GL_COMPRESSED_RGBA_ASTC_10x10_KHR, // kASTC_10x10_Format
36 GR_GL_COMPRESSED_RGBA_ASTC_12x10_KHR, // kASTC_12x10_Format
37 GR_GL_COMPRESSED_RGBA_ASTC_12x12_KHR, // kASTC_12x12_Format
38 };
39
40 GR_STATIC_ASSERT(0 == SkTextureCompressor::kLATC_Format);
41 GR_STATIC_ASSERT(1 == SkTextureCompressor::kR11_EAC_Format);
42 GR_STATIC_ASSERT(2 == SkTextureCompressor::kETC1_Format);
43 GR_STATIC_ASSERT(3 == SkTextureCompressor::kASTC_4x4_Format);
44 GR_STATIC_ASSERT(4 == SkTextureCompressor::kASTC_5x4_Format);
45 GR_STATIC_ASSERT(5 == SkTextureCompressor::kASTC_5x5_Format);
46 GR_STATIC_ASSERT(6 == SkTextureCompressor::kASTC_6x5_Format);
47 GR_STATIC_ASSERT(7 == SkTextureCompressor::kASTC_6x6_Format);
48 GR_STATIC_ASSERT(8 == SkTextureCompressor::kASTC_8x5_Format);
49 GR_STATIC_ASSERT(9 == SkTextureCompressor::kASTC_8x6_Format);
50 GR_STATIC_ASSERT(10 == SkTextureCompressor::kASTC_8x8_Format);
51 GR_STATIC_ASSERT(11 == SkTextureCompressor::kASTC_10x5_Format);
52 GR_STATIC_ASSERT(12 == SkTextureCompressor::kASTC_10x6_Format);
53 GR_STATIC_ASSERT(13 == SkTextureCompressor::kASTC_10x8_Format);
54 GR_STATIC_ASSERT(14 == SkTextureCompressor::kASTC_10x10_Format);
55 GR_STATIC_ASSERT(15 == SkTextureCompressor::kASTC_12x10_Format);
56 GR_STATIC_ASSERT(16 == SkTextureCompressor::kASTC_12x12_Format);
57 GR_STATIC_ASSERT(SK_ARRAY_COUNT(kGLDefineMap) == SkTextureCompressor::kFormatCnt);
58
59 return kGLDefineMap[fmt];
60 }
61
62 #define KTX_FILE_IDENTIFIER_SIZE 12
63 static const uint8_t KTX_FILE_IDENTIFIER[KTX_FILE_IDENTIFIER_SIZE] = {
64 0xAB, 0x4B, 0x54, 0x58, 0x20, 0x31, 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A
65 };
66
67 static const uint32_t kKTX_ENDIANNESS_CODE = 0x04030201;
68
readKeyAndValue(const uint8_t * data)69 bool SkKTXFile::KeyValue::readKeyAndValue(const uint8_t* data) {
70 const char *key = reinterpret_cast<const char *>(data);
71 const char *value = key;
72
73 size_t bytesRead = 0;
74 while (*value != '\0' && bytesRead < this->fDataSz) {
75 ++bytesRead;
76 ++value;
77 }
78
79 // Error of some sort..
80 if (bytesRead >= this->fDataSz) {
81 return false;
82 }
83
84 // Read the zero terminator
85 ++bytesRead;
86 ++value;
87
88 size_t bytesLeft = this->fDataSz - bytesRead;
89
90 // We ignore the null terminator when setting the string value.
91 this->fKey.set(key, bytesRead - 1);
92 if (bytesLeft > 0) {
93 this->fValue.set(value, bytesLeft - 1);
94 } else {
95 return false;
96 }
97
98 return true;
99 }
100
writeKeyAndValueForKTX(SkWStream * strm)101 bool SkKTXFile::KeyValue::writeKeyAndValueForKTX(SkWStream* strm) {
102 size_t bytesWritten = 0;
103 if (!strm->write(&(this->fDataSz), 4)) {
104 return false;
105 }
106
107 bytesWritten += 4;
108
109 // Here we know that C-strings must end with a null terminating
110 // character, so when we get a c_str(), it will have as many
111 // bytes of data as size() returns plus a zero, so we just
112 // write size() + 1 bytes into the stream.
113
114 size_t keySize = this->fKey.size() + 1;
115 if (!strm->write(this->fKey.c_str(), keySize)) {
116 return false;
117 }
118
119 bytesWritten += keySize;
120
121 size_t valueSize = this->fValue.size() + 1;
122 if (!strm->write(this->fValue.c_str(), valueSize)) {
123 return false;
124 }
125
126 bytesWritten += valueSize;
127
128 size_t bytesWrittenPadFour = (bytesWritten + 3) & ~3;
129 uint8_t nullBuf[4] = { 0, 0, 0, 0 };
130
131 size_t padding = bytesWrittenPadFour - bytesWritten;
132 SkASSERT(padding < 4);
133
134 return strm->write(nullBuf, padding);
135 }
136
readInt(const uint8_t ** buf,size_t * bytesLeft) const137 uint32_t SkKTXFile::readInt(const uint8_t** buf, size_t* bytesLeft) const {
138 SkASSERT(buf && bytesLeft);
139
140 uint32_t result;
141
142 if (*bytesLeft < 4) {
143 SkASSERT(false);
144 return 0;
145 }
146
147 memcpy(&result, *buf, 4);
148 *buf += 4;
149
150 if (fSwapBytes) {
151 SkEndianSwap32(result);
152 }
153
154 *bytesLeft -= 4;
155
156 return result;
157 }
158
getValueForKey(const SkString & key) const159 SkString SkKTXFile::getValueForKey(const SkString& key) const {
160 const KeyValue *begin = this->fKeyValuePairs.begin();
161 const KeyValue *end = this->fKeyValuePairs.end();
162 for (const KeyValue *kv = begin; kv != end; ++kv) {
163 if (kv->key() == key) {
164 return kv->value();
165 }
166 }
167 return SkString();
168 }
169
isCompressedFormat(SkTextureCompressor::Format fmt) const170 bool SkKTXFile::isCompressedFormat(SkTextureCompressor::Format fmt) const {
171 if (!this->valid()) {
172 return false;
173 }
174
175 // This has many aliases
176 bool isFmt = false;
177 if (fmt == SkTextureCompressor::kLATC_Format) {
178 isFmt = GR_GL_COMPRESSED_RED_RGTC1 == fHeader.fGLInternalFormat ||
179 GR_GL_COMPRESSED_3DC_X == fHeader.fGLInternalFormat;
180 }
181
182 return isFmt || compressed_fmt_to_gl_define(fmt) == fHeader.fGLInternalFormat;
183 }
184
isRGBA8() const185 bool SkKTXFile::isRGBA8() const {
186 return this->valid() && GR_GL_RGBA8 == fHeader.fGLInternalFormat;
187 }
188
isRGB8() const189 bool SkKTXFile::isRGB8() const {
190 return this->valid() && GR_GL_RGB8 == fHeader.fGLInternalFormat;
191 }
192
readKTXFile(const uint8_t * data,size_t dataLen)193 bool SkKTXFile::readKTXFile(const uint8_t* data, size_t dataLen) {
194 const uint8_t *buf = data;
195 size_t bytesLeft = dataLen;
196
197 // Make sure original KTX header is there... this should have been checked
198 // already by a call to is_ktx()
199 SkASSERT(bytesLeft > KTX_FILE_IDENTIFIER_SIZE);
200 SkASSERT(0 == memcmp(KTX_FILE_IDENTIFIER, buf, KTX_FILE_IDENTIFIER_SIZE));
201 buf += KTX_FILE_IDENTIFIER_SIZE;
202 bytesLeft -= KTX_FILE_IDENTIFIER_SIZE;
203
204 // Read header, but first make sure that we have the proper space: we need
205 // two 32-bit ints: 1 for endianness, and another for the mandatory image
206 // size after the header.
207 if (bytesLeft < 8 + sizeof(Header)) {
208 return false;
209 }
210
211 uint32_t endianness = this->readInt(&buf, &bytesLeft);
212 fSwapBytes = kKTX_ENDIANNESS_CODE != endianness;
213
214 // Read header values
215 fHeader.fGLType = this->readInt(&buf, &bytesLeft);
216 fHeader.fGLTypeSize = this->readInt(&buf, &bytesLeft);
217 fHeader.fGLFormat = this->readInt(&buf, &bytesLeft);
218 fHeader.fGLInternalFormat = this->readInt(&buf, &bytesLeft);
219 fHeader.fGLBaseInternalFormat = this->readInt(&buf, &bytesLeft);
220 fHeader.fPixelWidth = this->readInt(&buf, &bytesLeft);
221 fHeader.fPixelHeight = this->readInt(&buf, &bytesLeft);
222 fHeader.fPixelDepth = this->readInt(&buf, &bytesLeft);
223 fHeader.fNumberOfArrayElements = this->readInt(&buf, &bytesLeft);
224 fHeader.fNumberOfFaces = this->readInt(&buf, &bytesLeft);
225 fHeader.fNumberOfMipmapLevels = this->readInt(&buf, &bytesLeft);
226 fHeader.fBytesOfKeyValueData = this->readInt(&buf, &bytesLeft);
227
228 // Check for things that we understand...
229 {
230 // First, we only support compressed formats and single byte
231 // representations at the moment. If the internal format is
232 // compressed, the the GLType field in the header must be zero.
233 // In the future, we may support additional data types (such
234 // as GL_UNSIGNED_SHORT_5_6_5)
235 if (fHeader.fGLType != 0 && fHeader.fGLType != GR_GL_UNSIGNED_BYTE) {
236 return false;
237 }
238
239 // This means that for well-formatted KTX files, the glTypeSize
240 // field must be one...
241 if (fHeader.fGLTypeSize != 1) {
242 return false;
243 }
244
245 // We don't support 3D textures.
246 if (fHeader.fPixelDepth > 1) {
247 return false;
248 }
249
250 // We don't support texture arrays
251 if (fHeader.fNumberOfArrayElements > 1) {
252 return false;
253 }
254
255 // We don't support cube maps
256 if (fHeader.fNumberOfFaces > 1) {
257 return false;
258 }
259
260 // We don't support width and/or height <= 0
261 if (fHeader.fPixelWidth <= 0 || fHeader.fPixelHeight <= 0) {
262 return false;
263 }
264 }
265
266 // Make sure that we have enough bytes left for the key/value
267 // data according to what was said in the header.
268 if (bytesLeft < fHeader.fBytesOfKeyValueData) {
269 return false;
270 }
271
272 // Next read the key value pairs
273 size_t keyValueBytesRead = 0;
274 while (keyValueBytesRead < fHeader.fBytesOfKeyValueData) {
275 uint32_t keyValueBytes = this->readInt(&buf, &bytesLeft);
276 keyValueBytesRead += 4;
277
278 if (keyValueBytes > bytesLeft) {
279 return false;
280 }
281
282 KeyValue kv(keyValueBytes);
283 if (!kv.readKeyAndValue(buf)) {
284 return false;
285 }
286
287 fKeyValuePairs.push_back(kv);
288
289 uint32_t keyValueBytesPadded = (keyValueBytes + 3) & ~3;
290 buf += keyValueBytesPadded;
291 keyValueBytesRead += keyValueBytesPadded;
292 bytesLeft -= keyValueBytesPadded;
293 }
294
295 // Read the pixel data...
296 int mipmaps = SkMax32(fHeader.fNumberOfMipmapLevels, 1);
297 SkASSERT(mipmaps == 1);
298
299 int arrayElements = SkMax32(fHeader.fNumberOfArrayElements, 1);
300 SkASSERT(arrayElements == 1);
301
302 int faces = SkMax32(fHeader.fNumberOfFaces, 1);
303 SkASSERT(faces == 1);
304
305 int depth = SkMax32(fHeader.fPixelDepth, 1);
306 SkASSERT(depth == 1);
307
308 for (int mipmap = 0; mipmap < mipmaps; ++mipmap) {
309 // Make sure that we have at least 4 more bytes for the first image size
310 if (bytesLeft < 4) {
311 return false;
312 }
313
314 uint32_t imgSize = this->readInt(&buf, &bytesLeft);
315
316 // Truncated file.
317 if (bytesLeft < imgSize) {
318 return false;
319 }
320
321 // !FIXME! If support is ever added for cube maps then the padding
322 // needs to be taken into account here.
323 for (int arrayElement = 0; arrayElement < arrayElements; ++arrayElement) {
324 for (int face = 0; face < faces; ++face) {
325 for (int z = 0; z < depth; ++z) {
326 PixelData pd(buf, imgSize);
327 fPixelData.append(1, &pd);
328 }
329 }
330 }
331
332 uint32_t imgSizePadded = (imgSize + 3) & ~3;
333 buf += imgSizePadded;
334 bytesLeft -= imgSizePadded;
335 }
336
337 return bytesLeft == 0;
338 }
339
is_ktx(const uint8_t * data)340 bool SkKTXFile::is_ktx(const uint8_t *data) {
341 return 0 == memcmp(KTX_FILE_IDENTIFIER, data, KTX_FILE_IDENTIFIER_SIZE);
342 }
343
is_ktx(SkStreamRewindable * stream)344 bool SkKTXFile::is_ktx(SkStreamRewindable* stream) {
345 // Read the KTX header and make sure it's valid.
346 unsigned char buf[KTX_FILE_IDENTIFIER_SIZE];
347 bool largeEnough =
348 stream->read((void*)buf, KTX_FILE_IDENTIFIER_SIZE) == KTX_FILE_IDENTIFIER_SIZE;
349 stream->rewind();
350 if (!largeEnough) {
351 return false;
352 }
353 return is_ktx(buf);
354 }
355
CreateKeyValue(const char * cstrKey,const char * cstrValue)356 SkKTXFile::KeyValue SkKTXFile::CreateKeyValue(const char *cstrKey, const char *cstrValue) {
357 SkString key(cstrKey);
358 SkString value(cstrValue);
359
360 // Size of buffer is length of string plus the null terminators...
361 size_t size = key.size() + 1 + value.size() + 1;
362
363 SkAutoSMalloc<256> buf(size);
364 uint8_t* kvBuf = reinterpret_cast<uint8_t*>(buf.get());
365 memcpy(kvBuf, key.c_str(), key.size() + 1);
366 memcpy(kvBuf + key.size() + 1, value.c_str(), value.size() + 1);
367
368 KeyValue kv(size);
369 SkAssertResult(kv.readKeyAndValue(kvBuf));
370 return kv;
371 }
372
WriteETC1ToKTX(SkWStream * stream,const uint8_t * etc1Data,uint32_t width,uint32_t height)373 bool SkKTXFile::WriteETC1ToKTX(SkWStream* stream, const uint8_t *etc1Data,
374 uint32_t width, uint32_t height) {
375 // First thing's first, write out the magic identifier and endianness...
376 if (!stream->write(KTX_FILE_IDENTIFIER, KTX_FILE_IDENTIFIER_SIZE)) {
377 return false;
378 }
379
380 if (!stream->write(&kKTX_ENDIANNESS_CODE, 4)) {
381 return false;
382 }
383
384 Header hdr;
385 hdr.fGLType = 0;
386 hdr.fGLTypeSize = 1;
387 hdr.fGLFormat = 0;
388 hdr.fGLInternalFormat = GR_GL_COMPRESSED_ETC1_RGB8;
389 hdr.fGLBaseInternalFormat = GR_GL_RGB;
390 hdr.fPixelWidth = width;
391 hdr.fPixelHeight = height;
392 hdr.fNumberOfArrayElements = 0;
393 hdr.fNumberOfFaces = 1;
394 hdr.fNumberOfMipmapLevels = 1;
395
396 // !FIXME! The spec suggests that we put KTXOrientation as a
397 // key value pair in the header, but that means that we'd have to
398 // pipe through the bitmap's orientation to properly do that.
399 hdr.fBytesOfKeyValueData = 0;
400
401 // Write the header
402 if (!stream->write(&hdr, sizeof(hdr))) {
403 return false;
404 }
405
406 // Write the size of the image data
407 etc1_uint32 dataSize = etc1_get_encoded_data_size(width, height);
408 if (!stream->write(&dataSize, 4)) {
409 return false;
410 }
411
412 // Write the actual image data
413 if (!stream->write(etc1Data, dataSize)) {
414 return false;
415 }
416
417 return true;
418 }
419
WriteBitmapToKTX(SkWStream * stream,const SkBitmap & bitmap)420 bool SkKTXFile::WriteBitmapToKTX(SkWStream* stream, const SkBitmap& bitmap) {
421 const SkColorType ct = bitmap.colorType();
422 SkAutoLockPixels alp(bitmap);
423
424 const int width = bitmap.width();
425 const int height = bitmap.width();
426 const uint8_t* src = reinterpret_cast<uint8_t*>(bitmap.getPixels());
427 if (NULL == bitmap.getPixels()) {
428 return false;
429 }
430
431 // First thing's first, write out the magic identifier and endianness...
432 if (!stream->write(KTX_FILE_IDENTIFIER, KTX_FILE_IDENTIFIER_SIZE) ||
433 !stream->write(&kKTX_ENDIANNESS_CODE, 4)) {
434 return false;
435 }
436
437 // Collect our key/value pairs...
438 SkTArray<KeyValue> kvPairs;
439
440 // Next, write the header based on the bitmap's config.
441 Header hdr;
442 switch (ct) {
443 case kIndex_8_SkColorType:
444 // There is a compressed format for this, but we don't support it yet.
445 SkDebugf("Writing indexed bitmap to KTX unsupported.\n");
446 // VVV fall through VVV
447 default:
448 case kUnknown_SkColorType:
449 // Bitmap hasn't been configured.
450 return false;
451
452 case kAlpha_8_SkColorType:
453 hdr.fGLType = GR_GL_UNSIGNED_BYTE;
454 hdr.fGLTypeSize = 1;
455 hdr.fGLFormat = GR_GL_RED;
456 hdr.fGLInternalFormat = GR_GL_R8;
457 hdr.fGLBaseInternalFormat = GR_GL_RED;
458 break;
459
460 case kRGB_565_SkColorType:
461 hdr.fGLType = GR_GL_UNSIGNED_SHORT_5_6_5;
462 hdr.fGLTypeSize = 2;
463 hdr.fGLFormat = GR_GL_RGB;
464 hdr.fGLInternalFormat = GR_GL_RGB;
465 hdr.fGLBaseInternalFormat = GR_GL_RGB;
466 break;
467
468 case kARGB_4444_SkColorType:
469 hdr.fGLType = GR_GL_UNSIGNED_SHORT_4_4_4_4;
470 hdr.fGLTypeSize = 2;
471 hdr.fGLFormat = GR_GL_RGBA;
472 hdr.fGLInternalFormat = GR_GL_RGBA4;
473 hdr.fGLBaseInternalFormat = GR_GL_RGBA;
474 kvPairs.push_back(CreateKeyValue("KTXPremultipliedAlpha", "True"));
475 break;
476
477 case kN32_SkColorType:
478 hdr.fGLType = GR_GL_UNSIGNED_BYTE;
479 hdr.fGLTypeSize = 1;
480 hdr.fGLFormat = GR_GL_RGBA;
481 hdr.fGLInternalFormat = GR_GL_RGBA8;
482 hdr.fGLBaseInternalFormat = GR_GL_RGBA;
483 kvPairs.push_back(CreateKeyValue("KTXPremultipliedAlpha", "True"));
484 break;
485 }
486
487 // Everything else in the header is shared.
488 hdr.fPixelWidth = width;
489 hdr.fPixelHeight = height;
490 hdr.fNumberOfArrayElements = 0;
491 hdr.fNumberOfFaces = 1;
492 hdr.fNumberOfMipmapLevels = 1;
493
494 // Calculate the key value data size
495 hdr.fBytesOfKeyValueData = 0;
496 for (KeyValue *kv = kvPairs.begin(); kv != kvPairs.end(); ++kv) {
497 // Key value size is the size of the key value data,
498 // four bytes for saying how big the key value size is
499 // and then additional bytes for padding to four byte boundary
500 size_t kvsize = kv->size();
501 kvsize += 4;
502 kvsize = (kvsize + 3) & ~3;
503 hdr.fBytesOfKeyValueData = SkToU32(hdr.fBytesOfKeyValueData + kvsize);
504 }
505
506 // Write the header
507 if (!stream->write(&hdr, sizeof(hdr))) {
508 return false;
509 }
510
511 // Write out each key value pair
512 for (KeyValue *kv = kvPairs.begin(); kv != kvPairs.end(); ++kv) {
513 if (!kv->writeKeyAndValueForKTX(stream)) {
514 return false;
515 }
516 }
517
518 // Calculate the size of the data
519 int bpp = bitmap.bytesPerPixel();
520 uint32_t dataSz = bpp * width * height;
521
522 if (0 >= bpp) {
523 return false;
524 }
525
526 // Write it into the buffer
527 if (!stream->write(&dataSz, 4)) {
528 return false;
529 }
530
531 // Write the pixel data...
532 const uint8_t* rowPtr = src;
533 if (kN32_SkColorType == ct) {
534 for (int j = 0; j < height; ++j) {
535 const uint32_t* pixelsPtr = reinterpret_cast<const uint32_t*>(rowPtr);
536 for (int i = 0; i < width; ++i) {
537 uint32_t pixel = pixelsPtr[i];
538 uint8_t dstPixel[4];
539 dstPixel[0] = pixel >> SK_R32_SHIFT;
540 dstPixel[1] = pixel >> SK_G32_SHIFT;
541 dstPixel[2] = pixel >> SK_B32_SHIFT;
542 dstPixel[3] = pixel >> SK_A32_SHIFT;
543 if (!stream->write(dstPixel, 4)) {
544 return false;
545 }
546 }
547 rowPtr += bitmap.rowBytes();
548 }
549 } else {
550 for (int i = 0; i < height; ++i) {
551 if (!stream->write(rowPtr, bpp*width)) {
552 return false;
553 }
554 rowPtr += bitmap.rowBytes();
555 }
556 }
557
558 return true;
559 }
560