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