Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / third_party / ktx / ktx.cpp
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
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,              // 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
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
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
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
137 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
159 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
170 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
185 bool SkKTXFile::isRGBA8() const {
186     return this->valid() && GR_GL_RGBA8 == fHeader.fGLInternalFormat;
187 }
188
189 bool SkKTXFile::isRGB8() const {
190     return this->valid() && GR_GL_RGB8 == fHeader.fGLInternalFormat;
191 }
192
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
340 bool SkKTXFile::is_ktx(const uint8_t *data) {
341     return 0 == memcmp(KTX_FILE_IDENTIFIER, data, KTX_FILE_IDENTIFIER_SIZE);
342 }
343
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
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
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_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
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 += 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 }