diff --git a/cocos/platform/CCImage.cpp b/cocos/platform/CCImage.cpp index d3d96123e9..b4aebb7c3d 100644 --- a/cocos/platform/CCImage.cpp +++ b/cocos/platform/CCImage.cpp @@ -1448,7 +1448,11 @@ bool Image::initWithETCData(const unsigned char* data, ssize_t dataLen, bool own //old opengl version has no define for GL_ETC1_RGB8_OES, add macro to make compiler happy. #if defined(GL_ETC1_RGB8_OES) || defined(CC_USE_METAL) _pixelFormat = backend::PixelFormat::ETC; - _data = data; + if(ownData) _data = (unsigned char*)data; + else { + _data = (unsigned char*)malloc(dataLen); + if(_data) memcpy(_data, data, dataLen); + } _dataLen = dataLen; _offset = ETC_PKM_HEADER_SIZE; return true; diff --git a/cocos/renderer/backend/Texture.h b/cocos/renderer/backend/Texture.h index b4ec78fc41..7ff74664fb 100644 --- a/cocos/renderer/backend/Texture.h +++ b/cocos/renderer/backend/Texture.h @@ -104,7 +104,7 @@ public: */ inline bool hasMipmaps() const { return _hasMipmaps; } - virtual int getCount() const = 0; + virtual int getCount() const { return 1; }; protected: /** diff --git a/cocos/renderer/backend/metal/TextureMTL.h b/cocos/renderer/backend/metal/TextureMTL.h index efadd6982b..ab0403d226 100644 --- a/cocos/renderer/backend/metal/TextureMTL.h +++ b/cocos/renderer/backend/metal/TextureMTL.h @@ -27,6 +27,7 @@ #include "../Texture.h" #include "DeviceMTL.h" #import +#include CC_BACKEND_BEGIN /** @@ -54,7 +55,7 @@ public: * @param height Specifies the height of the texture image. * @param level Specifies the level-of-detail number. Level 0 is the base image level. Level n is the nth mipmap reduction image. */ - virtual void updateData(uint8_t* data, std::size_t width , std::size_t height, std::size_t level) override; + virtual void updateData(uint8_t* data, std::size_t width , std::size_t height, std::size_t level, int index = 0) override; /** * Update a two-dimensional texture image in a compressed format @@ -75,7 +76,7 @@ public: * @param level Specifies the level-of-detail number. Level 0 is the base image level. Level n is the nth mipmap reduction image. * @param data Specifies a pointer to the image data in memory. */ - virtual void updateSubData(std::size_t xoffset, std::size_t yoffset, std::size_t width, std::size_t height, std::size_t level, uint8_t* data) override; + virtual void updateSubData(std::size_t xoffset, std::size_t yoffset, std::size_t width, std::size_t height, std::size_t level, uint8_t* data, int index = 0) override; /** * Update a two-dimensional texture subimage in a compressed format @@ -93,7 +94,7 @@ public: * Update sampler * @param sampler Specifies the sampler descriptor. */ - virtual void updateSamplerDescriptor(const SamplerDescriptor &sampler) override; + virtual void updateSamplerDescriptor(const SamplerDescriptor &sampler, int index = 0) override; /** * Read a block of pixels from the drawable texture @@ -113,13 +114,17 @@ public: * Update texture description. * @param descriptor Specifies texture and sampler descriptor. */ - virtual void updateTextureDescriptor(const cocos2d::backend::TextureDescriptor &descriptor) override; + virtual void updateTextureDescriptor(const cocos2d::backend::TextureDescriptor &descriptor, int index = 0) override; + + int getCount() const override { return _mtlMaxTexIdx + 1; }; + + id ensure(int index); /** * Get MTLTexture object. * @return A MTLTexture object. */ - inline id getMTLTexture() const { return _mtlTexture; } + inline id getMTLTexture() const { return _mtlTextures[0]; } /** * Get MTLSamplerState object @@ -128,7 +133,7 @@ public: inline id getMTLSamplerState() const { return _mtlSamplerState; } private: - void createTexture(id mtlDevice, const TextureDescriptor& descriptor); + void createTexture(id mtlDevice, const TextureDescriptor& descriptor, int index); void createSampler(id mtlDevice, const SamplerDescriptor& descriptor); MTLSamplerAddressMode _sAddressMode; @@ -137,8 +142,11 @@ private: MTLSamplerMinMagFilter _magFilter; MTLSamplerMipFilter _mipFilter; + TextureDescriptor _textureDescriptor; + id _mtlDevice = nil; - id _mtlTexture = nil; + std::array, CC_META_TEXTURES + 1> _mtlTextures; + int _mtlMaxTexIdx = 0; id _mtlSamplerState = nil; unsigned int _bytesPerRow = 0; }; @@ -160,7 +168,7 @@ public: * Update sampler * @param sampler Specifies the sampler descriptor. */ - virtual void updateSamplerDescriptor(const SamplerDescriptor &sampler) override; + virtual void updateSamplerDescriptor(const SamplerDescriptor &sampler, int index = 0) override; /** * Update texutre cube data in give slice side. @@ -187,7 +195,7 @@ public: * Update texture description. * @param descriptor Specifies texture and sampler descriptor. */ - virtual void updateTextureDescriptor(const cocos2d::backend::TextureDescriptor &descriptor) override; + virtual void updateTextureDescriptor(const cocos2d::backend::TextureDescriptor &descriptor, int index = 0) override; /** * Get MTLTexture object. diff --git a/cocos/renderer/backend/metal/TextureMTL.mm b/cocos/renderer/backend/metal/TextureMTL.mm index e230c05f80..0223b85243 100644 --- a/cocos/renderer/backend/metal/TextureMTL.mm +++ b/cocos/renderer/backend/metal/TextureMTL.mm @@ -193,25 +193,31 @@ TextureMTL::TextureMTL(id mtlDevice, const TextureDescriptor& descrip : backend::Texture2DBackend(descriptor) { _mtlDevice = mtlDevice; + _mtlTextures.fill(nil); updateTextureDescriptor(descriptor); } TextureMTL::~TextureMTL() { - [_mtlTexture release]; + id texture; + int i = 0; + while((texture = _mtlTextures[i++])) + [texture release]; + [_mtlSamplerState release]; } -void TextureMTL::updateSamplerDescriptor(const SamplerDescriptor &sampler) +void TextureMTL::updateSamplerDescriptor(const SamplerDescriptor &sampler, int index) { createSampler(_mtlDevice, sampler); } -void TextureMTL::updateTextureDescriptor(const cocos2d::backend::TextureDescriptor &descriptor) +void TextureMTL::updateTextureDescriptor(const cocos2d::backend::TextureDescriptor &descriptor, int index) { - TextureBackend::updateTextureDescriptor(descriptor); - createTexture(_mtlDevice, descriptor); - updateSamplerDescriptor(descriptor.samplerDescriptor); + _textureDescriptor = descriptor; + TextureBackend::updateTextureDescriptor(descriptor, index); + createTexture(_mtlDevice, descriptor, index); + updateSamplerDescriptor(descriptor.samplerDescriptor, index); if (PixelFormat::RGB888 == _textureFormat) { _bitsPerElement = 4 * 8; @@ -220,13 +226,16 @@ void TextureMTL::updateTextureDescriptor(const cocos2d::backend::TextureDescript _bytesPerRow = descriptor.width * _bitsPerElement / 8 ; } -void TextureMTL::updateData(uint8_t* data, std::size_t width , std::size_t height, std::size_t level) +void TextureMTL::updateData(uint8_t* data, std::size_t width , std::size_t height, std::size_t level, int index) { - updateSubData(0, 0, width, height, level, data); + updateSubData(0, 0, width, height, level, data, index); } -void TextureMTL::updateSubData(std::size_t xoffset, std::size_t yoffset, std::size_t width, std::size_t height, std::size_t level, uint8_t* data) +void TextureMTL::updateSubData(std::size_t xoffset, std::size_t yoffset, std::size_t width, std::size_t height, std::size_t level, uint8_t* data, int index) { + auto mtlTexture = ensure(index); + if(!mtlTexture) return; + MTLRegion region = { {xoffset, yoffset, 0}, // MTLOrigin @@ -240,7 +249,7 @@ void TextureMTL::updateSubData(std::size_t xoffset, std::size_t yoffset, std::si std::size_t bytesPerRow = getBytesPerRow(_textureFormat, width, _bitsPerElement); - [_mtlTexture replaceRegion:region + [mtlTexture replaceRegion:region mipmapLevel:level withBytes:convertedData bytesPerRow:bytesPerRow]; @@ -262,7 +271,7 @@ void TextureMTL::updateCompressedSubData(std::size_t xoffset, std::size_t yoffse updateSubData(xoffset, yoffset, width, height, level, data); } -void TextureMTL::createTexture(id mtlDevice, const TextureDescriptor& descriptor) +void TextureMTL::createTexture(id mtlDevice, const TextureDescriptor& descriptor, int index) { MTLPixelFormat pixelFormat = Utils::toMTLPixelFormat(descriptor.textureFormat); if(pixelFormat == MTLPixelFormatInvalid) @@ -282,9 +291,10 @@ void TextureMTL::createTexture(id mtlDevice, const TextureDescriptor& textureDescriptor.usage = MTLTextureUsageRenderTarget | MTLTextureUsageShaderRead; } - if(_mtlTexture) - [_mtlTexture release]; - _mtlTexture = [mtlDevice newTextureWithDescriptor:textureDescriptor]; + id& mtlTexture = _mtlTextures[index]; + if(mtlTexture) + [mtlTexture release]; + mtlTexture = [mtlDevice newTextureWithDescriptor:textureDescriptor]; } void TextureMTL::createSampler(id mtlDevice, const SamplerDescriptor &descriptor) @@ -339,7 +349,7 @@ void TextureMTL::getBytes(std::size_t x, std::size_t y, std::size_t width, std:: } }; auto flipImageCallback = std::bind(flipImageFunc, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3); - Utils::getTextureBytes(x, y, width, height, _mtlTexture, flipImageCallback); + Utils::getTextureBytes(x, y, width, height, _mtlTextures[0], flipImageCallback); } void TextureMTL::generateMipmaps() @@ -350,11 +360,22 @@ void TextureMTL::generateMipmaps() if(!_hasMipmaps) { _hasMipmaps = true; - Utils::generateMipmaps(_mtlTexture); - + Utils::generateMipmaps(_mtlTextures[0]); } } +id TextureMTL::ensure(int index) +{ + if(index < CC_META_TEXTURES) { + id& mtlTexture = _mtlTextures[index]; + if(mtlTexture) return mtlTexture; + createTexture(_mtlDevice, _textureDescriptor, index); + if(_mtlMaxTexIdx < index) _mtlMaxTexIdx = index; + return mtlTexture; + } + return nil; +} + TextureCubeMTL::TextureCubeMTL(id mtlDevice, const TextureDescriptor& descriptor) : backend::TextureCubemapBackend(descriptor) { @@ -368,7 +389,7 @@ TextureCubeMTL::~TextureCubeMTL() [_mtlSamplerState release]; } -void TextureCubeMTL::updateTextureDescriptor(const cocos2d::backend::TextureDescriptor &descriptor) +void TextureCubeMTL::updateTextureDescriptor(const cocos2d::backend::TextureDescriptor &descriptor, int index) { TextureBackend::updateTextureDescriptor(descriptor); createTexture(_mtlDevice, descriptor); @@ -431,7 +452,7 @@ void TextureCubeMTL::createSampler(id mtlDevice, const SamplerDescrip [mtlDescriptor release]; } -void TextureCubeMTL::updateSamplerDescriptor(const SamplerDescriptor &sampler) +void TextureCubeMTL::updateSamplerDescriptor(const SamplerDescriptor &sampler, int /*index*/) { createSampler(_mtlDevice, sampler); }