3 * Copyright 2014 Google Inc.
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
14 #include "gl/GrGLDefines.h"
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
23 static const uint32_t kKTX_ENDIANNESS_CODE = 0x04030201;
25 bool SkKTXFile::KeyValue::readKeyAndValue(const uint8_t* data) {
26 const char *key = reinterpret_cast<const char *>(data);
27 const char *value = key;
30 while (*value != '\0' && bytesRead < this->fDataSz) {
35 // Error of some sort..
36 if (bytesRead >= this->fDataSz) {
40 // Read the zero terminator
44 size_t bytesLeft = this->fDataSz - bytesRead;
46 // We ignore the null terminator when setting the string value.
47 this->fKey.set(key, bytesRead - 1);
49 this->fValue.set(value, bytesLeft - 1);
57 bool SkKTXFile::KeyValue::writeKeyAndValueForKTX(SkWStream* strm) {
58 size_t bytesWritten = 0;
59 if (!strm->write(&(this->fDataSz), 4)) {
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.
70 size_t keySize = this->fKey.size() + 1;
71 if (!strm->write(this->fKey.c_str(), keySize)) {
75 bytesWritten += keySize;
77 size_t valueSize = this->fValue.size() + 1;
78 if (!strm->write(this->fValue.c_str(), valueSize)) {
82 bytesWritten += valueSize;
84 size_t bytesWrittenPadFour = (bytesWritten + 3) & ~3;
85 uint8_t nullBuf[4] = { 0, 0, 0, 0 };
87 size_t padding = bytesWrittenPadFour - bytesWritten;
88 SkASSERT(padding < 4);
90 return strm->write(nullBuf, padding);
93 uint32_t SkKTXFile::readInt(const uint8_t** buf, size_t* bytesLeft) const {
94 SkASSERT(NULL != buf && NULL != bytesLeft);
103 memcpy(&result, *buf, 4);
107 SkEndianSwap32(result);
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) {
126 bool SkKTXFile::isETC1() const {
127 return this->valid() && GR_GL_COMPRESSED_RGB8_ETC1 == fHeader.fGLInternalFormat;
130 bool SkKTXFile::isRGBA8() const {
131 return this->valid() && GR_GL_RGBA8 == fHeader.fGLInternalFormat;
134 bool SkKTXFile::isRGB8() const {
135 return this->valid() && GR_GL_RGB8 == fHeader.fGLInternalFormat;
138 bool SkKTXFile::readKTXFile(const uint8_t* data, size_t dataLen) {
139 const uint8_t *buf = data;
140 size_t bytesLeft = dataLen;
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;
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)) {
156 uint32_t endianness = this->readInt(&buf, &bytesLeft);
157 fSwapBytes = kKTX_ENDIANNESS_CODE != endianness;
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);
173 // Check for things that we understand...
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) {
184 // This means that for well-formatted KTX files, the glTypeSize
185 // field must be one...
186 if (fHeader.fGLTypeSize != 1) {
190 // We don't support 3D textures.
191 if (fHeader.fPixelDepth > 1) {
195 // We don't support texture arrays
196 if (fHeader.fNumberOfArrayElements > 1) {
200 // We don't support cube maps
201 if (fHeader.fNumberOfFaces > 1) {
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) {
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;
218 if (keyValueBytes > bytesLeft) {
222 KeyValue kv(keyValueBytes);
223 if (!kv.readKeyAndValue(buf)) {
227 fKeyValuePairs.push_back(kv);
229 uint32_t keyValueBytesPadded = (keyValueBytes + 3) & ~3;
230 buf += keyValueBytesPadded;
231 keyValueBytesRead += keyValueBytesPadded;
232 bytesLeft -= keyValueBytesPadded;
235 // Read the pixel data...
236 int mipmaps = SkMax32(fHeader.fNumberOfMipmapLevels, 1);
237 SkASSERT(mipmaps == 1);
239 int arrayElements = SkMax32(fHeader.fNumberOfArrayElements, 1);
240 SkASSERT(arrayElements == 1);
242 int faces = SkMax32(fHeader.fNumberOfFaces, 1);
243 SkASSERT(faces == 1);
245 int depth = SkMax32(fHeader.fPixelDepth, 1);
246 SkASSERT(depth == 1);
248 for (int mipmap = 0; mipmap < mipmaps; ++mipmap) {
249 // Make sure that we have at least 4 more bytes for the first image size
254 uint32_t imgSize = this->readInt(&buf, &bytesLeft);
257 if (bytesLeft < imgSize) {
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);
272 uint32_t imgSizePadded = (imgSize + 3) & ~3;
273 buf += imgSizePadded;
274 bytesLeft -= imgSizePadded;
277 return bytesLeft == 0;
280 bool SkKTXFile::is_ktx(const uint8_t *data) {
281 return 0 == memcmp(KTX_FILE_IDENTIFIER, data, KTX_FILE_IDENTIFIER_SIZE);
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];
288 stream->read((void*)buf, KTX_FILE_IDENTIFIER_SIZE) == KTX_FILE_IDENTIFIER_SIZE;
296 SkKTXFile::KeyValue SkKTXFile::CreateKeyValue(const char *cstrKey, const char *cstrValue) {
297 SkString key(cstrKey);
298 SkString value(cstrValue);
300 // Size of buffer is length of string plus the null terminators...
301 size_t size = key.size() + 1 + value.size() + 1;
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);
309 SkAssertResult(kv.readKeyAndValue(kvBuf));
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)) {
320 if (!stream->write(&kKTX_ENDIANNESS_CODE, 4)) {
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;
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;
342 if (!stream->write(&hdr, sizeof(hdr))) {
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)) {
352 // Write the actual image data
353 if (!stream->write(etc1Data, dataSize)) {
360 bool SkKTXFile::WriteBitmapToKTX(SkWStream* stream, const SkBitmap& bitmap) {
361 const SkColorType ct = bitmap.colorType();
362 SkAutoLockPixels alp(bitmap);
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()) {
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)) {
377 // Collect our key/value pairs...
378 SkTArray<KeyValue> kvPairs;
380 // Next, write the header based on the bitmap's config.
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
388 case kUnknown_SkColorType:
389 // Bitmap hasn't been configured.
392 case kAlpha_8_SkColorType:
393 hdr.fGLType = GR_GL_UNSIGNED_BYTE;
395 hdr.fGLFormat = GR_GL_RED;
396 hdr.fGLInternalFormat = GR_GL_R8;
397 hdr.fGLBaseInternalFormat = GR_GL_RED;
400 case kRGB_565_SkColorType:
401 hdr.fGLType = GR_GL_UNSIGNED_SHORT_5_6_5;
403 hdr.fGLFormat = GR_GL_RGB;
404 hdr.fGLInternalFormat = GR_GL_RGB;
405 hdr.fGLBaseInternalFormat = GR_GL_RGB;
408 case kARGB_4444_SkColorType:
409 hdr.fGLType = GR_GL_UNSIGNED_SHORT_4_4_4_4;
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"));
417 case kN32_SkColorType:
418 hdr.fGLType = GR_GL_UNSIGNED_BYTE;
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"));
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;
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();
442 kvsize = (kvsize + 3) & ~3;
443 hdr.fBytesOfKeyValueData += kvsize;
447 if (!stream->write(&hdr, sizeof(hdr))) {
451 // Write out each key value pair
452 for (KeyValue *kv = kvPairs.begin(); kv != kvPairs.end(); ++kv) {
453 if (!kv->writeKeyAndValueForKTX(stream)) {
458 // Calculate the size of the data
459 int bpp = bitmap.bytesPerPixel();
460 uint32_t dataSz = bpp * width * height;
466 // Write it into the buffer
467 if (!stream->write(&dataSz, 4)) {
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];
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)) {
487 rowPtr += bitmap.rowBytes();
490 for (int i = 0; i < height; ++i) {
491 if (!stream->write(rowPtr, bpp*width)) {
494 rowPtr += bitmap.rowBytes();