diff --git a/cocos/platform/CCImage.cpp b/cocos/platform/CCImage.cpp index 3b6b82f2a9..9a7dde6ae8 100644 --- a/cocos/platform/CCImage.cpp +++ b/cocos/platform/CCImage.cpp @@ -1634,7 +1634,7 @@ bool Image::initWithETCData(const unsigned char * data, ssize_t dataLen) if (Configuration::getInstance()->supportsETC()) { //old opengl version has no define for GL_ETC1_RGB8_OES, add macro to make compiler happy. -#ifdef GL_ETC1_RGB8_OES +#if defined(GL_ETC1_RGB8_OES) || defined(CC_USE_METAL) _pixelFormat = backend::PixelFormat::ETC; _dataLen = dataLen - ETC_PKM_HEADER_SIZE; _data = static_cast(malloc(_dataLen * sizeof(unsigned char))); diff --git a/cocos/renderer/CCTexture2D.cpp b/cocos/renderer/CCTexture2D.cpp index c1b0074239..d7f2ad6e11 100644 --- a/cocos/renderer/CCTexture2D.cpp +++ b/cocos/renderer/CCTexture2D.cpp @@ -61,70 +61,55 @@ namespace { typedef Texture2D::PixelFormatInfoMap::value_type PixelFormatInfoMapValue; static const PixelFormatInfoMapValue TexturePixelFormatInfoTablesValue[] = { - PixelFormatInfoMapValue(backend::PixelFormat::BGRA8888, Texture2D::PixelFormatInfo(GL_BGRA, GL_BGRA, GL_UNSIGNED_BYTE, 32, false, true)), - PixelFormatInfoMapValue(backend::PixelFormat::RGBA8888, Texture2D::PixelFormatInfo(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, 32, false, true)), - PixelFormatInfoMapValue(backend::PixelFormat::RGBA4444, Texture2D::PixelFormatInfo(GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, 16, false, true)), - PixelFormatInfoMapValue(backend::PixelFormat::RGB5A1, Texture2D::PixelFormatInfo(GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, 16, false, true)), - PixelFormatInfoMapValue(backend::PixelFormat::RGB565, Texture2D::PixelFormatInfo(GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 16, false, false)), - PixelFormatInfoMapValue(backend::PixelFormat::RGB888, Texture2D::PixelFormatInfo(GL_RGB, GL_RGB, GL_UNSIGNED_BYTE, 24, false, false)), - PixelFormatInfoMapValue(backend::PixelFormat::A8, Texture2D::PixelFormatInfo(GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE, 8, false, false)), - PixelFormatInfoMapValue(backend::PixelFormat::I8, Texture2D::PixelFormatInfo(GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE, 8, false, false)), - PixelFormatInfoMapValue(backend::PixelFormat::AI88, Texture2D::PixelFormatInfo(GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, 16, false, true)), -#ifndef CC_USE_METAL - //OpenGL only -#ifdef GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG - PixelFormatInfoMapValue(backend::PixelFormat::PVRTC2, Texture2D::PixelFormatInfo(GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG, 0xFFFFFFFF, 0xFFFFFFFF, 2, true, false)), - PixelFormatInfoMapValue(backend::PixelFormat::PVRTC2A, Texture2D::PixelFormatInfo(GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG, 0xFFFFFFFF, 0xFFFFFFFF, 2, true, true)), - PixelFormatInfoMapValue(backend::PixelFormat::PVRTC4, Texture2D::PixelFormatInfo(GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG, 0xFFFFFFFF, 0xFFFFFFFF, 4, true, false)), - PixelFormatInfoMapValue(backend::PixelFormat::PVRTC4A, Texture2D::PixelFormatInfo(GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, 0xFFFFFFFF, 0xFFFFFFFF, 4, true, true)), -#endif -#else - //Metal && iOS -#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) - PixelFormatInfoMapValue(backend::PixelFormat::PVRTC2, Texture2D::PixelFormatInfo(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 2, true, false)), - PixelFormatInfoMapValue(backend::PixelFormat::PVRTC2A, Texture2D::PixelFormatInfo(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 2, true, true)), - PixelFormatInfoMapValue(backend::PixelFormat::PVRTC4, Texture2D::PixelFormatInfo(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 4, true, false)), - PixelFormatInfoMapValue(backend::PixelFormat::PVRTC4A, Texture2D::PixelFormatInfo(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 4, true, true)), -#endif + PixelFormatInfoMapValue(backend::PixelFormat::BGRA8888, Texture2D::PixelFormatInfo(32, false, true)), + PixelFormatInfoMapValue(backend::PixelFormat::RGBA8888, Texture2D::PixelFormatInfo(32, false, true)), + PixelFormatInfoMapValue(backend::PixelFormat::RGBA4444, Texture2D::PixelFormatInfo(16, false, true)), + PixelFormatInfoMapValue(backend::PixelFormat::RGB5A1, Texture2D::PixelFormatInfo(16, false, true)), + PixelFormatInfoMapValue(backend::PixelFormat::RGB565, Texture2D::PixelFormatInfo(16, false, false)), + PixelFormatInfoMapValue(backend::PixelFormat::RGB888, Texture2D::PixelFormatInfo(24, false, false)), + PixelFormatInfoMapValue(backend::PixelFormat::A8, Texture2D::PixelFormatInfo(8, false, false)), + PixelFormatInfoMapValue(backend::PixelFormat::I8, Texture2D::PixelFormatInfo(8, false, false)), + PixelFormatInfoMapValue(backend::PixelFormat::AI88, Texture2D::PixelFormatInfo(16, false, true)), + +#if defined( GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG) || (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) + PixelFormatInfoMapValue(backend::PixelFormat::PVRTC2, Texture2D::PixelFormatInfo(2, true, false)), + PixelFormatInfoMapValue(backend::PixelFormat::PVRTC2A, Texture2D::PixelFormatInfo(2, true, true)), + PixelFormatInfoMapValue(backend::PixelFormat::PVRTC4, Texture2D::PixelFormatInfo(4, true, false)), + PixelFormatInfoMapValue(backend::PixelFormat::PVRTC4A, Texture2D::PixelFormatInfo(4, true, true)), #endif -#ifdef GL_ETC1_RGB8_OES - PixelFormatInfoMapValue(backend::PixelFormat::ETC, Texture2D::PixelFormatInfo(GL_ETC1_RGB8_OES, 0xFFFFFFFF, 0xFFFFFFFF, 4, true, false)), +#if defined(GL_ETC1_RGB8_OES) || (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) + PixelFormatInfoMapValue(backend::PixelFormat::ETC, Texture2D::PixelFormatInfo(4, true, false)), #endif -#ifdef GL_COMPRESSED_RGBA_S3TC_DXT1_EXT - PixelFormatInfoMapValue(backend::PixelFormat::S3TC_DXT1, Texture2D::PixelFormatInfo(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 0xFFFFFFFF, 0xFFFFFFFF, 4, true, false)), +#if defined(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) || (CC_TARGET_PLATFORM == CC_PLATFORM_MAC) + PixelFormatInfoMapValue(backend::PixelFormat::S3TC_DXT1, Texture2D::PixelFormatInfo(4, true, false)), #endif -#ifdef GL_COMPRESSED_RGBA_S3TC_DXT3_EXT - PixelFormatInfoMapValue(backend::PixelFormat::S3TC_DXT3, Texture2D::PixelFormatInfo(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 0xFFFFFFFF, 0xFFFFFFFF, 8, true, false)), +#if defined(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT) || (CC_TARGET_PLATFORM == CC_PLATFORM_MAC) + PixelFormatInfoMapValue(backend::PixelFormat::S3TC_DXT3, Texture2D::PixelFormatInfo(8, true, false)), #endif -#ifdef GL_COMPRESSED_RGBA_S3TC_DXT5_EXT - PixelFormatInfoMapValue(backend::PixelFormat::S3TC_DXT5, Texture2D::PixelFormatInfo(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, 0xFFFFFFFF, 0xFFFFFFFF, 8, true, false)), +#if defined(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT) || (CC_TARGET_PLATFORM == CC_PLATFORM_MAC) + PixelFormatInfoMapValue(backend::PixelFormat::S3TC_DXT5, Texture2D::PixelFormatInfo(8, true, false)), #endif #ifdef GL_ATC_RGB_AMD - PixelFormatInfoMapValue(backend::PixelFormat::ATC_RGB, Texture2D::PixelFormatInfo(GL_ATC_RGB_AMD, - 0xFFFFFFFF, 0xFFFFFFFF, 4, true, false)), + PixelFormatInfoMapValue(backend::PixelFormat::ATC_RGB, Texture2D::PixelFormatInfo(4, true, false)), #endif #ifdef GL_ATC_RGBA_EXPLICIT_ALPHA_AMD - PixelFormatInfoMapValue(backend::PixelFormat::ATC_EXPLICIT_ALPHA, Texture2D::PixelFormatInfo(GL_ATC_RGBA_EXPLICIT_ALPHA_AMD, - 0xFFFFFFFF, 0xFFFFFFFF, 8, true, false)), + PixelFormatInfoMapValue(backend::PixelFormat::ATC_EXPLICIT_ALPHA, Texture2D::PixelFormatInfo(8, true, false)), #endif #ifdef GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD - PixelFormatInfoMapValue(backend::PixelFormat::ATC_INTERPOLATED_ALPHA, Texture2D::PixelFormatInfo(GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD, - 0xFFFFFFFF, 0xFFFFFFFF, 8, true, false)), + PixelFormatInfoMapValue(backend::PixelFormat::ATC_INTERPOLATED_ALPHA, Texture2D::PixelFormatInfo(8, true, false)), #endif //metal formats -#ifdef CC_USE_METAL #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) - PixelFormatInfoMapValue(backend::PixelFormat::MTL_ABGR4, Texture2D::PixelFormatInfo(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 16, false, true)), - PixelFormatInfoMapValue(backend::PixelFormat::MTL_B5G6R5, Texture2D::PixelFormatInfo(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 16, false, false)), - PixelFormatInfoMapValue(backend::PixelFormat::MTL_BGR5A1, Texture2D::PixelFormatInfo(0xFFFFFFFF,0xFFFFFFFF, 0xFFFFFFFF, 16, false, true)), -#endif + PixelFormatInfoMapValue(backend::PixelFormat::MTL_ABGR4, Texture2D::PixelFormatInfo(16, false, true)), + PixelFormatInfoMapValue(backend::PixelFormat::MTL_B5G6R5, Texture2D::PixelFormatInfo(16, false, false)), + PixelFormatInfoMapValue(backend::PixelFormat::MTL_BGR5A1, Texture2D::PixelFormatInfo(16, false, true)), #endif }; } diff --git a/cocos/renderer/CCTexture2D.h b/cocos/renderer/CCTexture2D.h index 5673c47c4d..a6945b29a2 100644 --- a/cocos/renderer/CCTexture2D.h +++ b/cocos/renderer/CCTexture2D.h @@ -74,18 +74,12 @@ class CC_DLL Texture2D : public Ref public: struct PixelFormatInfo { - PixelFormatInfo(GLenum anInternalFormat, GLenum aFormat, GLenum aType, int aBpp, bool aCompressed, bool anAlpha) - : internalFormat(anInternalFormat) - , format(aFormat) - , type(aType) - , bpp(aBpp) + PixelFormatInfo(int aBpp, bool aCompressed, bool anAlpha) + : bpp(aBpp) , compressed(aCompressed) , alpha(anAlpha) {} - - GLenum internalFormat; - GLenum format; - GLenum type; + int bpp; bool compressed; bool alpha; diff --git a/cocos/renderer/backend/metal/TextureMTL.mm b/cocos/renderer/backend/metal/TextureMTL.mm index a3c7e704bc..959ae815d1 100644 --- a/cocos/renderer/backend/metal/TextureMTL.mm +++ b/cocos/renderer/backend/metal/TextureMTL.mm @@ -105,17 +105,77 @@ namespace } } - bool isCompressedFormat(PixelFormat textureFormat) + uint32_t getBytesPerRowETC(MTLPixelFormat pixleFormat, uint32_t width) + { + uint32_t bytesPerRow = 0; +#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) + uint32_t bytesPerBlock = 0, blockWidth = 4; + switch (pixleFormat) { + case MTLPixelFormatETC2_RGB8: + case MTLPixelFormatETC2_RGB8A1: + case MTLPixelFormatEAC_R11Unorm: + bytesPerBlock = 8; + break; + case MTLPixelFormatEAC_RGBA8: + case MTLPixelFormatEAC_RG11Unorm: + bytesPerBlock = 16; + break; + default: + assert(false); //TODO coulsonwang + break; + } + auto blocksPerRow = (width + (blockWidth - 1)) / blockWidth; + bytesPerRow = blocksPerRow * bytesPerBlock; +#endif + return bytesPerRow; + } + + uint32_t getBytesPerRowS3TC(MTLPixelFormat pixleFormat, uint32_t width) + { + uint32_t bytesPerRow = 0; +#if (CC_TARGET_PLATFORM == CC_PLATFORM_MAC) + uint32_t bytesPerBlock = 0, blockWidth = 4; + switch (pixleFormat) { + case MTLPixelFormatBC1_RGBA: + bytesPerBlock = 8; + break; + case MTLPixelFormatBC2_RGBA: + case MTLPixelFormatBC3_RGBA: + bytesPerBlock = 16; + break; + default: + break; + } + auto blocksPerRow = (width + (blockWidth - 1)) / blockWidth; + bytesPerRow = blocksPerRow * bytesPerBlock; +#endif + return bytesPerRow; + } + + uint32_t getBytesPerRow(PixelFormat textureFormat, uint32_t width, uint32_t bitsPerElement) { MTLPixelFormat pixelFormat = Utils::toMTLPixelFormat(textureFormat); -#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) - bool isCompressed = (pixelFormat >= MTLPixelFormatPVRTC_RGB_2BPP && - pixelFormat <= MTLPixelFormatASTC_12x12_LDR); -#else - bool isCompressed = (pixelFormat >= MTLPixelFormatBC1_RGBA && - pixelFormat <= MTLPixelFormatBC7_RGBAUnorm_sRGB); -#endif - return isCompressed; + uint32_t bytesPerRow = 0; + + if(textureFormat >= PixelFormat::PVRTC2 && + textureFormat <= PixelFormat::PVRTC4A) + { + bytesPerRow = 0; + } + else if (textureFormat == PixelFormat::ETC) + { + bytesPerRow = getBytesPerRowETC(pixelFormat, width); + } + else if(textureFormat >= PixelFormat::S3TC_DXT1 && + textureFormat <= PixelFormat::S3TC_DXT5) + { + bytesPerRow = getBytesPerRowS3TC(pixelFormat, width); + } + else + { + bytesPerRow = width * bitsPerElement / 8; + } + return bytesPerRow; } } @@ -124,7 +184,6 @@ TextureMTL::TextureMTL(id mtlDevice, const TextureDescriptor& descrip { _mtlDevice = mtlDevice; updateTextureDescriptor(descriptor); - _isCompressed = isCompressedFormat(descriptor.textureFormat); } TextureMTL::~TextureMTL() @@ -169,9 +228,7 @@ void TextureMTL::updateSubData(uint32_t xoffset, uint32_t yoffset, uint32_t widt (uint32_t)(width * height), _textureFormat, &convertedData); - //TODO coulsonwang, it seems that only PVRTC has such limitation. - //when pixel format is a compressed one, bytePerRow should be set to ZERO - int bytesPerRow = _isCompressed ? 0 : (width * _bitsPerElement / 8); + int bytesPerRow = getBytesPerRow(_textureFormat, width, _bitsPerElement); [_mtlTexture replaceRegion:region mipmapLevel:level diff --git a/cocos/renderer/backend/metal/Utils.mm b/cocos/renderer/backend/metal/Utils.mm index 83e0a8e4e9..dafb18afea 100644 --- a/cocos/renderer/backend/metal/Utils.mm +++ b/cocos/renderer/backend/metal/Utils.mm @@ -97,6 +97,15 @@ MTLPixelFormat Utils::toMTLPixelFormat(PixelFormat textureFormat) return MTLPixelFormatPVRTC_RGBA_2BPP; case PixelFormat::PVRTC2: return MTLPixelFormatPVRTC_RGB_2BPP; + case TextureFormat::ETC1: + return MTLPixelFormatETC2_RGB8; +#else + case PixelFormat::S3TC_DXT1: + return MTLPixelFormatBC1_RGBA; + case PixelFormat::S3TC_DXT3: + return MTLPixelFormatBC2_RGBA; + case PixelFormat::S3TC_DXT5: + return MTLPixelFormatBC3_RGBA; #endif case PixelFormat::RGBA8888: return MTLPixelFormatRGBA8Unorm;