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
19static 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,              // kR11_EAC_Format
23        GR_GL_COMPRESSED_RGB8_ETC1,        // kETC1_Format
24        GR_GL_COMPRESSED_RGBA_ASTC_4x4,    // kASTC_4x4_Format
25        GR_GL_COMPRESSED_RGBA_ASTC_5x4,    // kASTC_5x4_Format
26        GR_GL_COMPRESSED_RGBA_ASTC_5x5,    // kASTC_5x5_Format
27        GR_GL_COMPRESSED_RGBA_ASTC_6x5,    // kASTC_6x5_Format
28        GR_GL_COMPRESSED_RGBA_ASTC_6x6,    // kASTC_6x6_Format
29        GR_GL_COMPRESSED_RGBA_ASTC_8x5,    // kASTC_8x5_Format
30        GR_GL_COMPRESSED_RGBA_ASTC_8x6,    // kASTC_8x6_Format
31        GR_GL_COMPRESSED_RGBA_ASTC_8x8,    // kASTC_8x8_Format
32        GR_GL_COMPRESSED_RGBA_ASTC_10x5,   // kASTC_10x5_Format
33        GR_GL_COMPRESSED_RGBA_ASTC_10x6,   // kASTC_10x6_Format
34        GR_GL_COMPRESSED_RGBA_ASTC_10x8,   // kASTC_10x8_Format
35        GR_GL_COMPRESSED_RGBA_ASTC_10x10,  // kASTC_10x10_Format
36        GR_GL_COMPRESSED_RGBA_ASTC_12x10,  // kASTC_12x10_Format
37        GR_GL_COMPRESSED_RGBA_ASTC_12x12,  // 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
63static 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
67static const uint32_t kKTX_ENDIANNESS_CODE = 0x04030201;
68
69bool 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
101bool 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
137uint32_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
159SkString 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
170bool 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
185bool SkKTXFile::isRGBA8() const {
186    return this->valid() && GR_GL_RGBA8 == fHeader.fGLInternalFormat;
187}
188
189bool SkKTXFile::isRGB8() const {
190    return this->valid() && GR_GL_RGB8 == fHeader.fGLInternalFormat;
191}
192
193bool 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
340bool SkKTXFile::is_ktx(const uint8_t *data) {
341    return 0 == memcmp(KTX_FILE_IDENTIFIER, data, KTX_FILE_IDENTIFIER_SIZE);
342}
343
344bool 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
356SkKTXFile::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
373bool 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_RGB8_ETC1;
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
420bool 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 += 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