KDint xmGetInfoETC ( KDFile* file, XMImage* image ) { ETCInfo* info = 0; image->info = kdCalloc ( 1, sizeof ( ETCInfo ) ); info = (ETCInfo*) image->info; if ( !info ) { return -1; } if ( kdFread ( info, sizeof ( ETCInfo ), 1, file ) == 0 ) { kdSetError ( KD_EILSEQ ); return -1; } if ( !etc1_pkm_is_valid ( info->header ) ) { kdSetError ( KD_EILSEQ ); return -1; } image->type = KD_IMAGE_TYPE_ETC; image->width = etc1_pkm_get_width ( info->header ); image->height = etc1_pkm_get_height ( info->header ); image->level = 1; image->alpha = 0; image->bpp = 0; image->format = KD_IMAGE_FORMAT_COMPRESSED_ATX; return 0; }
static inline jint wrapped_Java_com_badlogic_gdx_graphics_glutils_ETC1_getHeightPKM (JNIEnv* env, jclass clazz, jobject obj_header, jint offset, char* header) { //@line:228 return etc1_pkm_get_height((etc1_byte*)header + offset); }
static GrTexture *load_etc1_texture(GrContext* ctx, const GrUniqueKey& optionalKey, const SkBitmap &bm, GrSurfaceDesc desc) { SkAutoTUnref<SkData> data(bm.pixelRef()->refEncodedData()); // Is this even encoded data? if (NULL == data) { return NULL; } // Is this a valid PKM encoded data? const uint8_t *bytes = data->bytes(); if (etc1_pkm_is_valid(bytes)) { uint32_t encodedWidth = etc1_pkm_get_width(bytes); uint32_t encodedHeight = etc1_pkm_get_height(bytes); // Does the data match the dimensions of the bitmap? If not, // then we don't know how to scale the image to match it... if (encodedWidth != static_cast<uint32_t>(bm.width()) || encodedHeight != static_cast<uint32_t>(bm.height())) { return NULL; } // Everything seems good... skip ahead to the data. bytes += ETC_PKM_HEADER_SIZE; desc.fConfig = kETC1_GrPixelConfig; } else if (SkKTXFile::is_ktx(bytes)) { SkKTXFile ktx(data); // Is it actually an ETC1 texture? if (!ktx.isCompressedFormat(SkTextureCompressor::kETC1_Format)) { return NULL; } // Does the data match the dimensions of the bitmap? If not, // then we don't know how to scale the image to match it... if (ktx.width() != bm.width() || ktx.height() != bm.height()) { return NULL; } bytes = ktx.pixelData(); desc.fConfig = kETC1_GrPixelConfig; } else { return NULL; } return create_texture_for_bmp(ctx, optionalKey, desc, bm.pixelRef(), bytes, 0); }
bool SkKTXImageEncoder::encodePKM(SkWStream* stream, const SkData *data) { const uint8_t* bytes = data->bytes(); SkASSERT(etc1_pkm_is_valid(bytes)); etc1_uint32 width = etc1_pkm_get_width(bytes); etc1_uint32 height = etc1_pkm_get_height(bytes); // ETC1 Data is stored as compressed 4x4 pixel blocks, so we must make sure // that our dimensions are valid. if (width == 0 || (width & 3) != 0 || height == 0 || (height & 3) != 0) { return false; } // Advance pointer to etc1 data. bytes += ETC_PKM_HEADER_SIZE; return SkKTXFile::WriteETC1ToKTX(stream, bytes, width, height); }
/** * Remove the last row and column of ETC1 blocks, effectively * making a texture that started as power of two into a texture * that is no longer power of two... */ bool slice_etc1_data(void *data, int* width, int* height) { // First, parse the data and get to it... etc1_byte *origData = reinterpret_cast<etc1_byte *>(data); if (!etc1_pkm_is_valid(origData)) { return false; } int origW = etc1_pkm_get_width(origData); int origH = etc1_pkm_get_height(origData); int blockWidth = (origW + 3) >> 2; int blockHeight = (origH + 3) >> 2; // Make sure that we have blocks to trim off.. if (blockWidth < 2 || blockHeight < 2) { return false; } int newWidth = (blockWidth - 1) << 2; int newHeight = (blockHeight - 1) << 2; size_t newDataSz = etc1_get_encoded_data_size(newWidth, newHeight) + ETC_PKM_HEADER_SIZE; SkAutoMalloc am(newDataSz); etc1_byte *newData = reinterpret_cast<etc1_byte *>(am.get()); etc1_pkm_format_header(newData, newWidth, newHeight); newData += ETC_PKM_HEADER_SIZE; origData += ETC_PKM_HEADER_SIZE; for (int j = 0; j < blockHeight - 1; ++j) { memcpy(newData, origData, (blockWidth - 1)*ETC1_ENCODED_BLOCK_SIZE); origData += blockWidth*ETC1_ENCODED_BLOCK_SIZE; newData += (blockWidth - 1)*ETC1_ENCODED_BLOCK_SIZE; } // Stick the data back whence it came memcpy(data, am.get(), newDataSz); *width = newWidth; *height = newHeight; return true; }
GrPixelConfig GrIsCompressedTextureDataSupported(GrContext* ctx, SkData* data, int expectedW, int expectedH, const void** outStartOfDataToUpload) { *outStartOfDataToUpload = nullptr; #ifndef SK_IGNORE_ETC1_SUPPORT if (!ctx->caps()->isConfigTexturable(kETC1_GrPixelConfig)) { return kUnknown_GrPixelConfig; } const uint8_t* bytes = data->bytes(); if (data->size() > ETC_PKM_HEADER_SIZE && etc1_pkm_is_valid(bytes)) { // Does the data match the dimensions of the bitmap? If not, // then we don't know how to scale the image to match it... if (etc1_pkm_get_width(bytes) != (unsigned)expectedW || etc1_pkm_get_height(bytes) != (unsigned)expectedH) { return kUnknown_GrPixelConfig; } *outStartOfDataToUpload = bytes + ETC_PKM_HEADER_SIZE; return kETC1_GrPixelConfig; } else if (SkKTXFile::is_ktx(bytes)) { SkKTXFile ktx(data); // Is it actually an ETC1 texture? if (!ktx.isCompressedFormat(SkTextureCompressor::kETC1_Format)) { return kUnknown_GrPixelConfig; } // Does the data match the dimensions of the bitmap? If not, // then we don't know how to scale the image to match it... if (ktx.width() != expectedW || ktx.height() != expectedH) { return kUnknown_GrPixelConfig; } *outStartOfDataToUpload = ktx.pixelData(); return kETC1_GrPixelConfig; } #endif return kUnknown_GrPixelConfig; }
GLuint loadTextureFromPKM(const ResourcePtr& pkmData, int &width, int &height) { #ifdef GL_ETC1_RGB8_OES const unsigned ETC_PKM_HEADER_SIZE = 16; if (pkmData->data().size() <= ETC_PKM_HEADER_SIZE) { LOGE("pkmData is not the right size. expected > %u, is: %zu", ETC_PKM_HEADER_SIZE, pkmData->data().size()); return TEXTURE_LOAD_ERROR; } etc1_byte* header = &pkmData->data()[0]; if (!etc1_pkm_is_valid(header)) return TEXTURE_LOAD_ERROR; width = etc1_pkm_get_width(header); height = etc1_pkm_get_height(header); size_t encodedDataSize = etc1_get_encoded_data_size(width, height); if (pkmData->data().size() != ETC_PKM_HEADER_SIZE + encodedDataSize) { LOGE("pkmData is not the right size. expected: %zu, is: %zu", ETC_PKM_HEADER_SIZE + encodedDataSize, pkmData->data().size()); return TEXTURE_LOAD_ERROR; } //Now generate the OpenGL texture object GLuint texture = genTexture(); bindTexture2D(texture); compressedTexImage2D(GL_ETC1_RGB8_OES, width, height, encodedDataSize, static_cast<GLvoid*> (&pkmData->data()[ETC_PKM_HEADER_SIZE])); texParameter(GL_TEXTURE_MIN_FILTER, GL_LINEAR); texParameter(GL_TEXTURE_MAG_FILTER, GL_NEAREST); return texture; #else LOGE("PKM texture format not supported by this platform"); return TEXTURE_LOAD_ERROR; #endif }
JNIEXPORT jint JNICALL Java_com_badlogic_gdx_graphics_glutils_ETC1_getHeightPKM (JNIEnv *env, jclass, jobject header, jint offset) { etc1_byte* headerPtr = (etc1_byte*)env->GetDirectBufferAddress(header) + offset; return etc1_pkm_get_height(headerPtr); }