v4-meta-multi-textures support Single Texture2D with multi GPU texture handlers.

This commit is contained in:
halx99 2019-11-20 18:19:24 +08:00
parent 72d605dc15
commit e7906acfa4
45 changed files with 596 additions and 381 deletions

View File

@ -119,6 +119,7 @@ bool AtlasNode::initWithTexture(Texture2D* texture, int tileWidth, int tileHeigh
_textureAtlas->initWithTexture(texture, itemsToRender); _textureAtlas->initWithTexture(texture, itemsToRender);
updateProgramStateTexture(texture);
this->updateBlendFunc(); this->updateBlendFunc();
this->updateOpacityModifyRGB(); this->updateOpacityModifyRGB();
@ -157,7 +158,6 @@ void AtlasNode::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags)
return; return;
auto programState = _quadCommand.getPipelineDescriptor().programState; auto programState = _quadCommand.getPipelineDescriptor().programState;
programState->setTexture(_textureLocation, 0, _textureAtlas->getTexture()->getBackendTexture());
const auto& projectionMat = Director::getInstance()->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION); const auto& projectionMat = Director::getInstance()->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
programState->setUniform(_mvpMatrixLocation, projectionMat.m, sizeof(projectionMat.m)); programState->setUniform(_mvpMatrixLocation, projectionMat.m, sizeof(projectionMat.m));
@ -251,6 +251,8 @@ void AtlasNode::updateBlendFunc()
void AtlasNode::setTexture(Texture2D *texture) void AtlasNode::setTexture(Texture2D *texture)
{ {
_textureAtlas->setTexture(texture); _textureAtlas->setTexture(texture);
updateProgramStateTexture(texture);
this->updateBlendFunc(); this->updateBlendFunc();
this->updateOpacityModifyRGB(); this->updateOpacityModifyRGB();
} }

View File

@ -143,7 +143,6 @@ protected:
QuadCommand _quadCommand; QuadCommand _quadCommand;
backend::UniformLocation _textureLocation; backend::UniformLocation _textureLocation;
backend::UniformLocation _mvpMatrixLocation; backend::UniformLocation _mvpMatrixLocation;
backend::ProgramState* _programState = nullptr;
private: private:
CC_DISALLOW_COPY_AND_ASSIGN(AtlasNode); CC_DISALLOW_COPY_AND_ASSIGN(AtlasNode);

View File

@ -336,7 +336,6 @@ protected:
BlendFunc _blendFunc; BlendFunc _blendFunc;
backend::ProgramState* _programState = nullptr;
backend::ProgramState* _programStatePoint = nullptr; backend::ProgramState* _programStatePoint = nullptr;
backend::ProgramState* _programStateLine = nullptr; backend::ProgramState* _programStateLine = nullptr;

View File

@ -354,7 +354,6 @@ protected:
backend::UniformLocation _mvpMatrixLocaiton; backend::UniformLocation _mvpMatrixLocaiton;
backend::UniformLocation _textureLocation; backend::UniformLocation _textureLocation;
backend::UniformLocation _alphaValueLocation; backend::UniformLocation _alphaValueLocation;
backend::ProgramState* _programState = nullptr;
}; };
// end of tilemap_parallax_nodes group // end of tilemap_parallax_nodes group

View File

@ -485,12 +485,12 @@ void FontAtlas::updateTextureContent(backend::PixelFormat format, int startY)
_currentPageDataRGBA[i*4] = data[i*2]; _currentPageDataRGBA[i*4] = data[i*2];
_currentPageDataRGBA[i*4+3] = data[i*2+1]; _currentPageDataRGBA[i*4+3] = data[i*2+1];
} }
_atlasTextures[_currentPage]->updateWithData(_currentPageDataRGBA, 0, startY, CacheTextureWidth, (int)_currentPageOrigY - startY + _currLineHeight); _atlasTextures[_currentPage]->updateWithSubData(_currentPageDataRGBA, 0, startY, CacheTextureWidth, (int)_currentPageOrigY - startY + _currLineHeight);
} }
else else
{ {
data = _currentPageData + CacheTextureWidth * (int)startY; data = _currentPageData + CacheTextureWidth * (int)startY;
_atlasTextures[_currentPage]->updateWithData(data, 0, startY, CacheTextureWidth, (int)_currentPageOrigY - startY + _currLineHeight); _atlasTextures[_currentPage]->updateWithSubData(data, 0, startY, CacheTextureWidth, (int)_currentPageOrigY - startY + _currLineHeight);
} }
} }

View File

@ -48,6 +48,7 @@
#include "2d/CCFontFNT.h" #include "2d/CCFontFNT.h"
#include "renderer/ccShaders.h" #include "renderer/ccShaders.h"
#include "renderer/backend/ProgramState.h" #include "renderer/backend/ProgramState.h"
#include "renderer/backend/ProgramStateRegistry.h"
NS_CC_BEGIN NS_CC_BEGIN
@ -644,9 +645,9 @@ void Label::updateShaderProgram()
if (_currentLabelType == LabelType::BMFONT || _currentLabelType == LabelType::CHARMAP) if (_currentLabelType == LabelType::BMFONT || _currentLabelType == LabelType::CHARMAP)
{ {
auto texture = _getTexture(this); auto texture = _getTexture(this);
if(texture && texture->getAlphaTextureName()) if(texture)
{ {
programType = backend::ProgramType::ETC1; programType = backend::ProgramStateRegistry::getInstance()->getProgramType(programType, texture->getBackendTexture());
} }
} }
else else
@ -665,9 +666,9 @@ void Label::updateShaderProgram()
else else
{ {
auto texture = _getTexture(this); auto texture = _getTexture(this);
if(texture && texture->getAlphaTextureName()) if(texture)
{ {
programType = backend::ProgramType::ETC1; programType = backend::ProgramStateRegistry::getInstance()->getProgramType(programType, texture->getBackendTexture());
} }
} }
break; break;
@ -728,7 +729,6 @@ void Label::updateUniformLocations()
{ {
_mvpMatrixLocation = _programState->getUniformLocation(backend::Uniform::MVP_MATRIX); _mvpMatrixLocation = _programState->getUniformLocation(backend::Uniform::MVP_MATRIX);
_textureLocation = _programState->getUniformLocation(backend::Uniform::TEXTURE); _textureLocation = _programState->getUniformLocation(backend::Uniform::TEXTURE);
_alphaTextureLocation = _programState->getUniformLocation(backend::Uniform::TEXTURE1);
_textColorLocation = _programState->getUniformLocation(backend::Uniform::TEXT_COLOR); _textColorLocation = _programState->getUniformLocation(backend::Uniform::TEXT_COLOR);
_effectColorLocation = _programState->getUniformLocation(backend::Uniform::EFFECT_COLOR); _effectColorLocation = _programState->getUniformLocation(backend::Uniform::EFFECT_COLOR);
_effectTypeLocation = _programState->getUniformLocation(backend::Uniform::EFFECT_TYPE); _effectTypeLocation = _programState->getUniformLocation(backend::Uniform::EFFECT_TYPE);
@ -1756,12 +1756,7 @@ void Label::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags)
auto texture = textureAtlas->getTexture(); auto texture = textureAtlas->getTexture();
auto& pipelineQuad = _quadCommand.getPipelineDescriptor(); auto& pipelineQuad = _quadCommand.getPipelineDescriptor();
pipelineQuad.programState->setUniform(_mvpMatrixLocation, matrixProjection.m, sizeof(matrixProjection.m)); pipelineQuad.programState->setUniform(_mvpMatrixLocation, matrixProjection.m, sizeof(matrixProjection.m));
pipelineQuad.programState->setTexture(_textureLocation, 0, texture->getBackendTexture()); pipelineQuad.programState->setTexture(texture->getBackendTexture());
auto alphaTexture = textureAtlas->getTexture()->getAlphaTexture();
if(alphaTexture && alphaTexture->getBackendTexture())
{
pipelineQuad.programState->setTexture(_alphaTextureLocation, 1, alphaTexture->getBackendTexture());
}
_quadCommand.init(_globalZOrder, texture, _blendFunc, textureAtlas->getQuads(), textureAtlas->getTotalQuads(), transform, flags); _quadCommand.init(_globalZOrder, texture, _blendFunc, textureAtlas->getQuads(), textureAtlas->getTotalQuads(), transform, flags);
renderer->addCommand(&_quadCommand); renderer->addCommand(&_quadCommand);
} }
@ -1796,12 +1791,7 @@ void Label::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags)
auto *programState = command->getPipelineDescriptor().programState; auto *programState = command->getPipelineDescriptor().programState;
Vec4 textColor(_textColorF.r, _textColorF.g, _textColorF.b, _textColorF.a); Vec4 textColor(_textColorF.r, _textColorF.g, _textColorF.b, _textColorF.a);
programState->setUniform(_textColorLocation, &textColor, sizeof(Vec4)); programState->setUniform(_textColorLocation, &textColor, sizeof(Vec4));
programState->setTexture(_textureLocation, 0, textureAtlas->getTexture()->getBackendTexture()); programState->setTexture(textureAtlas->getTexture()->getBackendTexture());
auto alphaTexture = textureAtlas->getTexture()->getAlphaTexture();
if (alphaTexture && alphaTexture->getBackendTexture())
{
programState->setTexture(_alphaTextureLocation, 1, alphaTexture->getBackendTexture());
}
} }
batch.textCommand.getPipelineDescriptor().programState->setUniform(_mvpMatrixLocation, matrixMVP.m, sizeof(matrixMVP.m)); batch.textCommand.getPipelineDescriptor().programState->setUniform(_mvpMatrixLocation, matrixMVP.m, sizeof(matrixMVP.m));
batch.outLineCommand.getPipelineDescriptor().programState->setUniform(_mvpMatrixLocation, matrixMVP.m, sizeof(matrixMVP.m)); batch.outLineCommand.getPipelineDescriptor().programState->setUniform(_mvpMatrixLocation, matrixMVP.m, sizeof(matrixMVP.m));

View File

@ -811,13 +811,10 @@ protected:
backend::UniformLocation _mvpMatrixLocation; backend::UniformLocation _mvpMatrixLocation;
backend::UniformLocation _textureLocation; backend::UniformLocation _textureLocation;
backend::UniformLocation _alphaTextureLocation;
backend::UniformLocation _textColorLocation; backend::UniformLocation _textColorLocation;
backend::UniformLocation _effectColorLocation; backend::UniformLocation _effectColorLocation;
backend::UniformLocation _effectTypeLocation; backend::UniformLocation _effectTypeLocation;
backend::ProgramState* _programState = nullptr;
private: private:
CC_DISALLOW_COPY_AND_ASSIGN(Label); CC_DISALLOW_COPY_AND_ASSIGN(Label);
}; };

View File

@ -278,7 +278,6 @@ protected:
V3F_C4F _vertexData[4]; V3F_C4F _vertexData[4];
backend::UniformLocation _mvpMatrixLocation; backend::UniformLocation _mvpMatrixLocation;
backend::ProgramState* _programState = nullptr;
private: private:
CC_DISALLOW_COPY_AND_ASSIGN(LayerColor); CC_DISALLOW_COPY_AND_ASSIGN(LayerColor);

View File

@ -40,32 +40,6 @@ MotionStreak::MotionStreak()
{ {
_customCommand.setDrawType(CustomCommand::DrawType::ARRAY); _customCommand.setDrawType(CustomCommand::DrawType::ARRAY);
_customCommand.setPrimitiveType(CustomCommand::PrimitiveType::TRIANGLE_STRIP); _customCommand.setPrimitiveType(CustomCommand::PrimitiveType::TRIANGLE_STRIP);
auto& pipelineDescriptor = _customCommand.getPipelineDescriptor();
auto* program = backend::Program::getBuiltinProgram(backend::ProgramType::POSITION_TEXTURE_COLOR);
_programState = new (std::nothrow) backend::ProgramState(program);
pipelineDescriptor.programState = _programState;
_mvpMatrixLocaiton = pipelineDescriptor.programState->getUniformLocation("u_MVPMatrix");
_textureLocation = pipelineDescriptor.programState->getUniformLocation("u_texture");
auto vertexLayout = _programState->getVertexLayout();
const auto& attributeInfo = _programState->getProgram()->getActiveAttributes();
auto iter = attributeInfo.find("a_position");
if(iter != attributeInfo.end())
{
vertexLayout->setAttribute("a_position", iter->second.location, backend::VertexFormat::FLOAT2, 0, false);
}
iter = attributeInfo.find("a_texCoord");
if(iter != attributeInfo.end())
{
vertexLayout->setAttribute("a_texCoord", iter->second.location, backend::VertexFormat::FLOAT2, 2 * sizeof(float), false);
}
iter = attributeInfo.find("a_color");
if(iter != attributeInfo.end())
{
vertexLayout->setAttribute("a_color", iter->second.location, backend::VertexFormat::UBYTE4, 4 * sizeof(float), true);
}
vertexLayout->setLayout(4 * sizeof(float) + 4 * sizeof(uint8_t));
} }
MotionStreak::~MotionStreak() MotionStreak::~MotionStreak()
@ -236,9 +210,49 @@ void MotionStreak::setTexture(Texture2D *texture)
CC_SAFE_RETAIN(texture); CC_SAFE_RETAIN(texture);
CC_SAFE_RELEASE(_texture); CC_SAFE_RELEASE(_texture);
_texture = texture; _texture = texture;
setProgramStateWithRegistry(backend::ProgramType::POSITION_TEXTURE_COLOR, _texture);
if (_texture)
_programState->setTexture(_texture->getBackendTexture());
} }
} }
void MotionStreak::setProgramState(backend::ProgramState* programState)
{
CCASSERT(programState, "argument should not be nullptr");
auto& pipelineDescriptor = _customCommand.getPipelineDescriptor();
if (_programState != programState)
{
CC_SAFE_RELEASE(_programState);
_programState = programState;
CC_SAFE_RETAIN(programState);
}
pipelineDescriptor.programState = _programState;
_mvpMatrixLocaiton = _programState->getUniformLocation("u_MVPMatrix");
_textureLocation = _programState->getUniformLocation("u_texture");
auto vertexLayout = _programState->getVertexLayout();
const auto& attributeInfo = _programState->getProgram()->getActiveAttributes();
auto iter = attributeInfo.find("a_position");
if (iter != attributeInfo.end())
{
vertexLayout->setAttribute("a_position", iter->second.location, backend::VertexFormat::FLOAT2, 0, false);
}
iter = attributeInfo.find("a_texCoord");
if (iter != attributeInfo.end())
{
vertexLayout->setAttribute("a_texCoord", iter->second.location, backend::VertexFormat::FLOAT2, 2 * sizeof(float), false);
}
iter = attributeInfo.find("a_color");
if (iter != attributeInfo.end())
{
vertexLayout->setAttribute("a_color", iter->second.location, backend::VertexFormat::UBYTE4, 4 * sizeof(float), true);
}
vertexLayout->setLayout(4 * sizeof(float) + 4 * sizeof(uint8_t));
}
void MotionStreak::setBlendFunc(const BlendFunc &blendFunc) void MotionStreak::setBlendFunc(const BlendFunc &blendFunc)
{ {
_blendFunc = blendFunc; _blendFunc = blendFunc;
@ -398,7 +412,7 @@ void MotionStreak::draw(Renderer *renderer, const Mat4 &transform, uint32_t flag
renderer->addCommand(&_customCommand); renderer->addCommand(&_customCommand);
auto programState = _customCommand.getPipelineDescriptor().programState; auto programState = _customCommand.getPipelineDescriptor().programState;
programState->setTexture(_textureLocation, 0, _texture->getBackendTexture()); // programState->setTexture(_textureLocation, 0, _texture->getBackendTexture());
const auto& projectionMat = Director::getInstance()->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION); const auto& projectionMat = Director::getInstance()->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
Mat4 finalMat = projectionMat * transform; Mat4 finalMat = projectionMat * transform;

View File

@ -147,6 +147,8 @@ public:
_startingPositionInitialized = bStartingPositionInitialized; _startingPositionInitialized = bStartingPositionInitialized;
} }
void setProgramState(backend::ProgramState* programState) override;
CC_CONSTRUCTOR_ACCESS: CC_CONSTRUCTOR_ACCESS:
MotionStreak(); MotionStreak();
virtual ~MotionStreak(); virtual ~MotionStreak();
@ -187,7 +189,6 @@ protected:
backend::UniformLocation _mvpMatrixLocaiton; backend::UniformLocation _mvpMatrixLocaiton;
backend::UniformLocation _textureLocation; backend::UniformLocation _textureLocation;
backend::ProgramState* _programState = nullptr;
private: private:
CC_DISALLOW_COPY_AND_ASSIGN(MotionStreak); CC_DISALLOW_COPY_AND_ASSIGN(MotionStreak);

View File

@ -43,6 +43,7 @@ THE SOFTWARE.
#include "2d/CCComponent.h" #include "2d/CCComponent.h"
#include "renderer/CCMaterial.h" #include "renderer/CCMaterial.h"
#include "math/TransformUtils.h" #include "math/TransformUtils.h"
#include "renderer/backend/ProgramStateRegistry.h"
#if CC_NODE_RENDER_SUBPIXEL #if CC_NODE_RENDER_SUBPIXEL
@ -2181,6 +2182,20 @@ int Node::getAttachedNodeCount()
return __attachedNodeCount; return __attachedNodeCount;
} }
void Node::setProgramStateWithRegistry(backend::ProgramType programType, Texture2D* texture)
{
auto n = texture ? texture->getBackendTexture()->getCount() : 1;
setProgramState(backend::ProgramStateRegistry::getInstance()->getProgramState(programType, n));
}
void Node::updateProgramStateTexture(Texture2D* texture)
{
if (texture == nullptr || texture->getBackendTexture() == nullptr || _programState == nullptr)
return;
_programState->setTexture(texture->getBackendTexture());
}
void Node::setProgramState(backend::ProgramState* programState) void Node::setProgramState(backend::ProgramState* programState)
{ {
if (_programState != programState) if (_programState != programState)

View File

@ -1768,6 +1768,10 @@ public:
virtual void setCameraMask(unsigned short mask, bool applyChildren = true); virtual void setCameraMask(unsigned short mask, bool applyChildren = true);
virtual void setProgramState(backend::ProgramState* programState); virtual void setProgramState(backend::ProgramState* programState);
void setProgramStateWithRegistry(backend::ProgramType programType, Texture2D* texture);
void updateProgramStateTexture(Texture2D* texture);
virtual backend::ProgramState* getProgramState() const; virtual backend::ProgramState* getProgramState() const;
CC_CONSTRUCTOR_ACCESS: CC_CONSTRUCTOR_ACCESS:

View File

@ -441,7 +441,7 @@ void ParticleBatchNode::draw(Renderer* renderer, const Mat4 & transform, uint32_
Mat4 finalMat = projectionMat * transform; Mat4 finalMat = projectionMat * transform;
auto programState = _customCommand.getPipelineDescriptor().programState; auto programState = _customCommand.getPipelineDescriptor().programState;
programState->setUniform(_mvpMatrixLocaiton, finalMat.m, sizeof(finalMat.m)); programState->setUniform(_mvpMatrixLocaiton, finalMat.m, sizeof(finalMat.m));
programState->setTexture(_textureLocation, 0, _textureAtlas->getTexture()->getBackendTexture()); // programState->setTexture(_textureLocation, 0, _textureAtlas->getTexture()->getBackendTexture());
if (_textureAtlas->isDirty()) if (_textureAtlas->isDirty())
{ {
@ -531,11 +531,14 @@ void ParticleBatchNode::updateBlendFunc()
void ParticleBatchNode::setTexture(Texture2D* texture) void ParticleBatchNode::setTexture(Texture2D* texture)
{ {
_textureAtlas->setTexture(texture); _textureAtlas->setTexture(texture);
if (texture) {
// If the new texture has No premultiplied alpha, AND the blendFunc hasn't been changed, then update it auto programState = _customCommand.getPipelineDescriptor().programState;
if( texture && ! texture->hasPremultipliedAlpha() && ( _blendFunc.src == CC_BLEND_SRC && _blendFunc.dst == CC_BLEND_DST ) ) programState->setTexture(_textureAtlas->getTexture()->getBackendTexture());
{ // If the new texture has No premultiplied alpha, AND the blendFunc hasn't been changed, then update it
_blendFunc = BlendFunc::ALPHA_NON_PREMULTIPLIED; if (!texture->hasPremultipliedAlpha() && (_blendFunc.src == CC_BLEND_SRC && _blendFunc.dst == CC_BLEND_DST))
{
_blendFunc = BlendFunc::ALPHA_NON_PREMULTIPLIED;
}
} }
} }

View File

@ -180,7 +180,6 @@ private:
backend::UniformLocation _mvpMatrixLocaiton; backend::UniformLocation _mvpMatrixLocaiton;
backend::UniformLocation _textureLocation; backend::UniformLocation _textureLocation;
backend::ProgramState* _programState = nullptr;
}; };
// end of _2d group // end of _2d group

View File

@ -230,6 +230,9 @@ void ParticleSystemQuad::setTextureWithRect(Texture2D *texture, const Rect& rect
if( !_texture || texture->getBackendTexture() != _texture->getBackendTexture() ) if( !_texture || texture->getBackendTexture() != _texture->getBackendTexture() )
{ {
ParticleSystem::setTexture(texture); ParticleSystem::setTexture(texture);
auto programState = _quadCommand.getPipelineDescriptor().programState;
programState->setTexture(_texture->getBackendTexture());
} }
this->initTexCoordsWithRect(rect); this->initTexCoordsWithRect(rect);
@ -446,7 +449,7 @@ void ParticleSystemQuad::draw(Renderer *renderer, const Mat4 &transform, uint32_
if(_particleCount > 0) if(_particleCount > 0)
{ {
auto programState = _quadCommand.getPipelineDescriptor().programState; auto programState = _quadCommand.getPipelineDescriptor().programState;
programState->setTexture(_textureLocation, 0, _texture->getBackendTexture()); // programState->setTexture(_textureLocation, 0, _texture->getBackendTexture());
cocos2d::Mat4 projectionMat = Director::getInstance()->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION); cocos2d::Mat4 projectionMat = Director::getInstance()->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
programState->setUniform(_mvpMatrixLocaiton, projectionMat.m, sizeof(projectionMat.m)); programState->setUniform(_mvpMatrixLocaiton, projectionMat.m, sizeof(projectionMat.m));

View File

@ -176,7 +176,6 @@ protected:
backend::UniformLocation _mvpMatrixLocaiton; backend::UniformLocation _mvpMatrixLocaiton;
backend::UniformLocation _textureLocation; backend::UniformLocation _textureLocation;
backend::ProgramState* _programState = nullptr;
private: private:
CC_DISALLOW_COPY_AND_ASSIGN(ParticleSystemQuad); CC_DISALLOW_COPY_AND_ASSIGN(ParticleSystemQuad);

View File

@ -191,7 +191,6 @@ protected:
CustomCommand _customCommand; CustomCommand _customCommand;
CustomCommand _customCommand2; CustomCommand _customCommand2;
backend::ProgramState* _programState = nullptr;
backend::ProgramState* _programState2 = nullptr; backend::ProgramState* _programState2 = nullptr;
backend::UniformLocation _locMVP1; backend::UniformLocation _locMVP1;

View File

@ -384,14 +384,15 @@ void Sprite::updateShaders(const char* vert, const char* frag)
void Sprite::setProgramState(backend::ProgramType type) void Sprite::setProgramState(backend::ProgramType type)
{ {
if(_programState != nullptr && setProgramStateWithRegistry(type, _texture);
/*if(_programState != nullptr &&
_programState->getProgram()->getProgramType() == type) _programState->getProgram()->getProgramType() == type)
return; return;
auto* program = backend::Program::getBuiltinProgram(type); auto* program = backend::Program::getBuiltinProgram(type);
auto programState = new (std::nothrow) backend::ProgramState(program); auto programState = new (std::nothrow) backend::ProgramState(program);
setProgramState(programState); setProgramState(programState);
CC_SAFE_RELEASE_NULL(programState); CC_SAFE_RELEASE_NULL(programState);*/
} }
void Sprite::setProgramState(backend::ProgramState *programState) void Sprite::setProgramState(backend::ProgramState *programState)
@ -408,17 +409,16 @@ void Sprite::setProgramState(backend::ProgramState *programState)
_mvpMatrixLocation = pipelineDescriptor.programState->getUniformLocation(backend::Uniform::MVP_MATRIX); _mvpMatrixLocation = pipelineDescriptor.programState->getUniformLocation(backend::Uniform::MVP_MATRIX);
_textureLocation = pipelineDescriptor.programState->getUniformLocation(backend::Uniform::TEXTURE); _textureLocation = pipelineDescriptor.programState->getUniformLocation(backend::Uniform::TEXTURE);
_alphaTextureLocation = pipelineDescriptor.programState->getUniformLocation(backend::Uniform::TEXTURE1);
setVertexLayout(); setVertexLayout();
updateProgramStateTexture(); updateProgramStateTexture(_texture);
setMVPMatrixUniform(); setMVPMatrixUniform();
} }
void Sprite::setTexture(Texture2D *texture) void Sprite::setTexture(Texture2D *texture)
{ {
auto isETC1 = texture && texture->getAlphaTextureName(); setProgramStateWithRegistry(backend::ProgramType::POSITION_TEXTURE_COLOR, texture);
setProgramState((isETC1) ? backend::ProgramType::ETC1 : backend::ProgramType::POSITION_TEXTURE_COLOR);
CCASSERT(! _batchNode || (texture && texture == _batchNode->getTexture()), "CCSprite: Batched sprites should use the same texture as the batchnode"); CCASSERT(! _batchNode || (texture && texture == _batchNode->getTexture()), "CCSprite: Batched sprites should use the same texture as the batchnode");
// accept texture==nil as argument // accept texture==nil as argument
CCASSERT( !texture || dynamic_cast<Texture2D*>(texture), "setTexture expects a Texture2D. Invalid argument"); CCASSERT( !texture || dynamic_cast<Texture2D*>(texture), "setTexture expects a Texture2D. Invalid argument");
@ -450,21 +450,7 @@ void Sprite::setTexture(Texture2D *texture)
} }
updateBlendFunc(); updateBlendFunc();
} }
updateProgramStateTexture(); updateProgramStateTexture(_texture);
}
void Sprite::updateProgramStateTexture()
{
if (_texture == nullptr || _texture->getBackendTexture() == nullptr)
return;
auto programState = _trianglesCommand.getPipelineDescriptor().programState;
programState->setTexture(_textureLocation, 0, _texture->getBackendTexture());
auto alphaTexture = _texture->getAlphaTexture();
if(alphaTexture && alphaTexture->getBackendTexture())
{
programState->setTexture(_alphaTextureLocation, 1, alphaTexture->getBackendTexture());
}
} }
Texture2D* Sprite::getTexture() const Texture2D* Sprite::getTexture() const

View File

@ -625,6 +625,8 @@ CC_CONSTRUCTOR_ACCESS :
virtual void setVertexLayout(); virtual void setVertexLayout();
virtual void updateShaders(const char* vert, const char* frag); virtual void updateShaders(const char* vert, const char* frag);
void setProgramState(backend::ProgramType type);
protected: protected:
virtual void updateColor() override; virtual void updateColor() override;
virtual void setTextureCoords(const Rect& rect); virtual void setTextureCoords(const Rect& rect);
@ -635,13 +637,11 @@ protected:
virtual void setDirtyRecursively(bool value); virtual void setDirtyRecursively(bool value);
virtual void flipX(); virtual void flipX();
virtual void flipY(); virtual void flipY();
virtual void updateProgramStateTexture();
void updatePoly(); void updatePoly();
void updateStretchFactor(); void updateStretchFactor();
void populateTriangle(int quadIndex, const V3F_C4B_T2F_Quad& quad); void populateTriangle(int quadIndex, const V3F_C4B_T2F_Quad& quad);
void setMVPMatrixUniform(); void setMVPMatrixUniform();
void setProgramState(backend::ProgramType type);
// //
// Data used when the sprite is rendered using a SpriteSheet // Data used when the sprite is rendered using a SpriteSheet
// //
@ -664,8 +664,6 @@ protected:
backend::UniformLocation _mvpMatrixLocation; backend::UniformLocation _mvpMatrixLocation;
backend::UniformLocation _textureLocation; backend::UniformLocation _textureLocation;
backend::UniformLocation _alphaTextureLocation;
#if CC_SPRITE_DEBUG_DRAW #if CC_SPRITE_DEBUG_DRAW
DrawNode *_debugDrawNode = nullptr; DrawNode *_debugDrawNode = nullptr;
#endif //CC_SPRITE_DEBUG_DRAW #endif //CC_SPRITE_DEBUG_DRAW

View File

@ -102,42 +102,45 @@ bool SpriteBatchNode::initWithTexture(Texture2D *tex, ssize_t capacity/* = DEFAU
_textureAtlas->initWithTexture(tex, capacity); _textureAtlas->initWithTexture(tex, capacity);
setProgramStateWithRegistry(backend::ProgramType::POSITION_TEXTURE_COLOR, tex);
updateProgramStateTexture(_textureAtlas->getTexture());
updateBlendFunc(); updateBlendFunc();
_children.reserve(capacity); _children.reserve(capacity);
_descendants.reserve(capacity); _descendants.reserve(capacity);
updateShaders(positionTextureColor_vert, positionTextureColor_frag);
return true; return true;
} }
void SpriteBatchNode::updateShaders(const std::string &vertexShader, const std::string &fragmentShader) void SpriteBatchNode::setProgramState(backend::ProgramState* programState)
{ {
auto& pipelineDescriptor = _quadCommand.getPipelineDescriptor(); auto& pipelineDescriptor = _quadCommand.getPipelineDescriptor();
auto* program = backend::Device::getInstance()->newProgram(vertexShader, fragmentShader); if (_programState != programState)
CC_SAFE_RELEASE(_programState); {
_programState = new (std::nothrow) backend::ProgramState(program); CC_SAFE_RELEASE(_programState);
_programState = programState;
CC_SAFE_RETAIN(programState);
}
pipelineDescriptor.programState = _programState; pipelineDescriptor.programState = _programState;
_mvpMatrixLocaiton = pipelineDescriptor.programState->getUniformLocation("u_MVPMatrix"); _mvpMatrixLocaiton = pipelineDescriptor.programState->getUniformLocation("u_MVPMatrix");
_textureLocation = pipelineDescriptor.programState->getUniformLocation("u_texture"); _textureLocation = pipelineDescriptor.programState->getUniformLocation("u_texture");
CC_SAFE_RELEASE(program);
auto vertexLayout = _programState->getVertexLayout(); auto vertexLayout = _programState->getVertexLayout();
const auto& attributeInfo = _programState->getProgram()->getActiveAttributes(); const auto& attributeInfo = _programState->getProgram()->getActiveAttributes();
auto iter = attributeInfo.find("a_position"); auto iter = attributeInfo.find("a_position");
if(iter != attributeInfo.end()) if (iter != attributeInfo.end())
{ {
vertexLayout->setAttribute("a_position", iter->second.location, backend::VertexFormat::FLOAT3, 0, false); vertexLayout->setAttribute("a_position", iter->second.location, backend::VertexFormat::FLOAT3, 0, false);
} }
iter = attributeInfo.find("a_texCoord"); iter = attributeInfo.find("a_texCoord");
if(iter != attributeInfo.end()) if (iter != attributeInfo.end())
{ {
vertexLayout->setAttribute("a_texCoord", iter->second.location, backend::VertexFormat::FLOAT2, offsetof(V3F_C4B_T2F, texCoords), false); vertexLayout->setAttribute("a_texCoord", iter->second.location, backend::VertexFormat::FLOAT2, offsetof(V3F_C4B_T2F, texCoords), false);
} }
iter = attributeInfo.find("a_color"); iter = attributeInfo.find("a_color");
if(iter != attributeInfo.end()) if (iter != attributeInfo.end())
{ {
vertexLayout->setAttribute("a_color", iter->second.location, backend::VertexFormat::UBYTE4, offsetof(V3F_C4B_T2F, colors), true); vertexLayout->setAttribute("a_color", iter->second.location, backend::VertexFormat::UBYTE4, offsetof(V3F_C4B_T2F, colors), true);
} }
@ -421,7 +424,7 @@ void SpriteBatchNode::draw(Renderer *renderer, const Mat4 &transform, uint32_t f
const auto& matrixProjection = Director::getInstance()->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION); const auto& matrixProjection = Director::getInstance()->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
auto programState = _quadCommand.getPipelineDescriptor().programState; auto programState = _quadCommand.getPipelineDescriptor().programState;
programState->setUniform(_mvpMatrixLocaiton, matrixProjection.m, sizeof(matrixProjection.m)); programState->setUniform(_mvpMatrixLocaiton, matrixProjection.m, sizeof(matrixProjection.m));
programState->setTexture(_textureLocation, 0, _textureAtlas->getTexture()->getBackendTexture()); // programState->setTexture(_textureLocation, 0, _textureAtlas->getTexture()->getBackendTexture());
_quadCommand.init(_globalZOrder, _textureAtlas->getTexture(), _blendFunc, _textureAtlas->getQuads(), _textureAtlas->getTotalQuads(), transform, flags); _quadCommand.init(_globalZOrder, _textureAtlas->getTexture(), _blendFunc, _textureAtlas->getQuads(), _textureAtlas->getTotalQuads(), transform, flags);
renderer->addCommand(&_quadCommand); renderer->addCommand(&_quadCommand);
@ -681,6 +684,8 @@ Texture2D* SpriteBatchNode::getTexture() const
void SpriteBatchNode::setTexture(Texture2D *texture) void SpriteBatchNode::setTexture(Texture2D *texture)
{ {
_textureAtlas->setTexture(texture); _textureAtlas->setTexture(texture);
updateProgramStateTexture(texture);
updateBlendFunc(); updateBlendFunc();
} }

View File

@ -260,7 +260,7 @@ protected:
void swap(ssize_t oldIndex, ssize_t newIndex); void swap(ssize_t oldIndex, ssize_t newIndex);
void updateBlendFunc(); void updateBlendFunc();
virtual void updateShaders(const std::string& vertexShader, const std::string& fragmentShader); void setProgramState(backend::ProgramState* programState) override;
TextureAtlas *_textureAtlas = nullptr; TextureAtlas *_textureAtlas = nullptr;
BlendFunc _blendFunc; BlendFunc _blendFunc;
@ -268,7 +268,6 @@ protected:
backend::UniformLocation _mvpMatrixLocaiton; backend::UniformLocation _mvpMatrixLocaiton;
backend::UniformLocation _textureLocation; backend::UniformLocation _textureLocation;
backend::ProgramState* _programState = nullptr;
// all descendants: children, grand children, etc... // all descendants: children, grand children, etc...
// There is not need to retain/release these objects, since they are already retained by _children // There is not need to retain/release these objects, since they are already retained by _children

View File

@ -249,9 +249,11 @@ void TMXLayer::parseInternalProperties()
auto alphaFuncVal = getProperty("cc_alpha_func"); auto alphaFuncVal = getProperty("cc_alpha_func");
float alphaFuncValue = alphaFuncVal.asFloat(); float alphaFuncValue = alphaFuncVal.asFloat();
setProgramStateWithRegistry(backend::ProgramType::POSITION_TEXTURE_COLOR_ALPHA_TEST, nullptr);
auto& pipelineDescriptor = _quadCommand.getPipelineDescriptor(); auto& pipelineDescriptor = _quadCommand.getPipelineDescriptor();
auto& vertexShader = pipelineDescriptor.programState->getProgram()->getVertexShader(); auto& vertexShader = pipelineDescriptor.programState->getProgram()->getVertexShader();
updateShaders(vertexShader, positionTextureColorAlphaTest_frag);
auto alphaValueLocation = pipelineDescriptor.programState->getUniformLocation("u_alpha_value"); auto alphaValueLocation = pipelineDescriptor.programState->getUniformLocation("u_alpha_value");
pipelineDescriptor.programState->setUniform(alphaValueLocation, &alphaFuncValue, sizeof(alphaFuncValue)); pipelineDescriptor.programState->setUniform(alphaValueLocation, &alphaFuncValue, sizeof(alphaFuncValue));
} }

View File

@ -357,3 +357,7 @@ THE SOFTWARE.
#ifndef CC_STRIP_FPS #ifndef CC_STRIP_FPS
#define CC_STRIP_FPS 0 #define CC_STRIP_FPS 0
#endif #endif
#ifndef CC_META_TEXTURES
#define CC_META_TEXTURES 2
#endif

View File

@ -208,7 +208,6 @@ protected:
void setRootSkeleton(BoneNode* bone, SkeletonNode* skeleton) const; void setRootSkeleton(BoneNode* bone, SkeletonNode* skeleton) const;
protected: protected:
cocos2d::CustomCommand _customCommand; cocos2d::CustomCommand _customCommand;
cocos2d::backend::ProgramState* _programState = nullptr;
cocos2d::backend::UniformLocation _mvpLocation; cocos2d::backend::UniformLocation _mvpLocation;
cocos2d::BlendFunc _blendFunc = cocos2d::BlendFunc::ALPHA_NON_PREMULTIPLIED; cocos2d::BlendFunc _blendFunc = cocos2d::BlendFunc::ALPHA_NON_PREMULTIPLIED;

View File

@ -30,7 +30,6 @@ THE SOFTWARE.
#include <string> #include <string>
#include <ctype.h> #include <ctype.h>
#include "base/CCData.h"
#include "base/ccConfig.h" // CC_USE_JPEG, CC_USE_WEBP #include "base/ccConfig.h" // CC_USE_JPEG, CC_USE_WEBP
#include "platform/CCGL.h" #include "platform/CCGL.h"
@ -481,6 +480,7 @@ bool Image::PNG_PREMULTIPLIED_ALPHA_ENABLED = true;
Image::Image() Image::Image()
: _data(nullptr) : _data(nullptr)
, _dataLen(0) , _dataLen(0)
, _offset(0)
, _width(0) , _width(0)
, _height(0) , _height(0)
, _unpack(false) , _unpack(false)
@ -512,7 +512,9 @@ bool Image::initWithImageFile(const std::string& path)
if (!data.isNull()) if (!data.isNull())
{ {
ret = initWithImageData(data.getBytes(), data.getSize()); ssize_t n = 0;
auto buf = data.takeBuffer(&n);
ret = initWithImageData(buf, n, true);
} }
return ret; return ret;
@ -527,19 +529,21 @@ bool Image::initWithImageFileThreadSafe(const std::string& fullpath)
if (!data.isNull()) if (!data.isNull())
{ {
ret = initWithImageData(data.getBytes(), data.getSize()); ssize_t n = 0;
auto buf = data.takeBuffer(&n);
ret = initWithImageData(buf, n, true);
} }
return ret; return ret;
} }
bool Image::initWithImageData(const unsigned char * data, ssize_t dataLen) bool Image::initWithImageData(const unsigned char* data, ssize_t dataLen, bool ownData)
{ {
bool ret = false; bool ret = false;
do do
{ {
CC_BREAK_IF(! data || dataLen <= 0); CC_BREAK_IF(!data || dataLen == 0);
unsigned char* unpackedData = nullptr; unsigned char* unpackedData = nullptr;
ssize_t unpackedLen = 0; ssize_t unpackedLen = 0;
@ -576,7 +580,7 @@ bool Image::initWithImageData(const unsigned char * data, ssize_t dataLen)
ret = initWithPVRData(unpackedData, unpackedLen); ret = initWithPVRData(unpackedData, unpackedLen);
break; break;
case Format::ETC: case Format::ETC:
ret = initWithETCData(unpackedData, unpackedLen); ret = initWithETCData(unpackedData, unpackedLen, ownData);
break; break;
case Format::S3TC: case Format::S3TC:
ret = initWithS3TCData(unpackedData, unpackedLen); ret = initWithS3TCData(unpackedData, unpackedLen);
@ -1421,7 +1425,7 @@ bool Image::initWithPVRv3Data(const unsigned char * data, ssize_t dataLen)
return true; return true;
} }
bool Image::initWithETCData(const unsigned char * data, ssize_t dataLen) bool Image::initWithETCData(const unsigned char* data, ssize_t dataLen, bool ownData)
{ {
const etc1_byte* header = static_cast<const etc1_byte*>(data); const etc1_byte* header = static_cast<const etc1_byte*>(data);
@ -1439,23 +1443,26 @@ bool Image::initWithETCData(const unsigned char * data, ssize_t dataLen)
return false; return false;
} }
// pitfall: because we do merge etc1 alpha at shader, so must mark as _hasPremultipliedAlpha=true to makesure alpha blend works well.
// the Premultiply operation can only do at shader.
_hasPremultipliedAlpha = true;
if (Configuration::getInstance()->supportsETC()) if (Configuration::getInstance()->supportsETC())
{ {
//old opengl version has no define for GL_ETC1_RGB8_OES, add macro to make compiler happy. //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) #if defined(GL_ETC1_RGB8_OES) || defined(CC_USE_METAL)
_pixelFormat = backend::PixelFormat::ETC; _pixelFormat = backend::PixelFormat::ETC;
_dataLen = dataLen - ETC_PKM_HEADER_SIZE; _data = data;
_data = static_cast<unsigned char*>(malloc(_dataLen * sizeof(unsigned char))); _dataLen = dataLen;
memcpy(_data, static_cast<const unsigned char*>(data) + ETC_PKM_HEADER_SIZE, _dataLen); _offset = ETC_PKM_HEADER_SIZE;
return true; return true;
#else
CC_UNUSED_PARAM(dataLen);
#endif #endif
} }
else else
{ {
CCLOG("cocos2d: Hardware ETC1 decoder not present. Using software decoder"); CCLOG("cocos2d: Hardware ETC1 decoder not present. Using software decoder");
bool ret = true;
//if it is not gles or device do not support ETC, decode texture by software //if it is not gles or device do not support ETC, decode texture by software
int bytePerPixel = 3; int bytePerPixel = 3;
unsigned int stride = _width * bytePerPixel; unsigned int stride = _width * bytePerPixel;
@ -1470,12 +1477,16 @@ bool Image::initWithETCData(const unsigned char * data, ssize_t dataLen)
if (_data != nullptr) if (_data != nullptr)
{ {
free(_data); free(_data);
_data = nullptr;
} }
return false; ret = false;
} }
return true; if (ownData) free((void*)data);
return ret;
} }
if (ownData) free((void*)data);
return false; return false;
} }

View File

@ -30,6 +30,7 @@ THE SOFTWARE.
#include "base/CCRef.h" #include "base/CCRef.h"
#include "renderer/CCTexture2D.h" #include "renderer/CCTexture2D.h"
#include "base/CCData.h"
// premultiply alpha, or the effect will be wrong when using other pixel formats in Texture2D, // premultiply alpha, or the effect will be wrong when using other pixel formats in Texture2D,
// such as RGB888, RGB5A1 // such as RGB888, RGB5A1
@ -125,14 +126,14 @@ public:
* @js NA * @js NA
* @lua NA * @lua NA
*/ */
bool initWithImageData(const unsigned char * data, ssize_t dataLen); bool initWithImageData(const unsigned char * data, ssize_t dataLen, bool ownData = false);
// @warning kFmtRawData only support RGBA8888 // @warning kFmtRawData only support RGBA8888
bool initWithRawData(const unsigned char * data, ssize_t dataLen, int width, int height, int bitsPerComponent, bool preMulti = false); bool initWithRawData(const unsigned char * data, ssize_t dataLen, int width, int height, int bitsPerComponent, bool preMulti = false);
// Getters // Getters
unsigned char * getData() { return _data; } unsigned char * getData() { return _data + _offset; }
ssize_t getDataLen() { return _dataLen; } ssize_t getDataLen() { return _dataLen - _offset; }
Format getFileType() { return _fileType; } Format getFileType() { return _fileType; }
backend::PixelFormat getPixelFormat() { return _pixelFormat; } backend::PixelFormat getPixelFormat() { return _pixelFormat; }
int getWidth() { return _width; } int getWidth() { return _width; }
@ -163,7 +164,7 @@ protected:
bool initWithPVRData(const unsigned char * data, ssize_t dataLen); bool initWithPVRData(const unsigned char * data, ssize_t dataLen);
bool initWithPVRv2Data(const unsigned char * data, ssize_t dataLen); bool initWithPVRv2Data(const unsigned char * data, ssize_t dataLen);
bool initWithPVRv3Data(const unsigned char * data, ssize_t dataLen); bool initWithPVRv3Data(const unsigned char * data, ssize_t dataLen);
bool initWithETCData(const unsigned char * data, ssize_t dataLen); bool initWithETCData(const unsigned char* data, ssize_t dataLen, bool ownData);
bool initWithS3TCData(const unsigned char * data, ssize_t dataLen); bool initWithS3TCData(const unsigned char * data, ssize_t dataLen);
bool initWithATITCData(const unsigned char *data, ssize_t dataLen); bool initWithATITCData(const unsigned char *data, ssize_t dataLen);
typedef struct sImageTGA tImageTGA; typedef struct sImageTGA tImageTGA;
@ -186,6 +187,7 @@ protected:
static bool PNG_PREMULTIPLIED_ALPHA_ENABLED; static bool PNG_PREMULTIPLIED_ALPHA_ENABLED;
unsigned char *_data; unsigned char *_data;
ssize_t _dataLen; ssize_t _dataLen;
ssize_t _offset;
int _width; int _width;
int _height; int _height;
bool _unpack; bool _unpack;

View File

@ -97,8 +97,6 @@ void QuadCommand::init(float globalOrder, Texture2D *texture, const BlendFunc& b
triangles.indices = __indices; triangles.indices = __indices;
triangles.indexCount = (int)quadCount * 6; triangles.indexCount = (int)quadCount * 6;
TrianglesCommand::init(globalOrder, texture, blendType, triangles, mv, flags); TrianglesCommand::init(globalOrder, texture, blendType, triangles, mv, flags);
_alphaTextureID = texture->getAlphaTextureName();
} }
NS_CC_END NS_CC_END

View File

@ -137,7 +137,6 @@ Texture2D::Texture2D()
, _antialiasEnabled(true) , _antialiasEnabled(true)
, _ninePatchInfo(nullptr) , _ninePatchInfo(nullptr)
, _valid(true) , _valid(true)
, _alphaTexture(nullptr)
{ {
backend::TextureDescriptor textureDescriptor; backend::TextureDescriptor textureDescriptor;
textureDescriptor.textureFormat = PixelFormat::NONE; textureDescriptor.textureFormat = PixelFormat::NONE;
@ -149,8 +148,6 @@ Texture2D::~Texture2D()
#if CC_ENABLE_CACHE_TEXTURE_DATA #if CC_ENABLE_CACHE_TEXTURE_DATA
VolatileTextureMgr::removeTexture(this); VolatileTextureMgr::removeTexture(this);
#endif #endif
CC_SAFE_RELEASE_NULL(_alphaTexture); // ETC1 ALPHA support.
CCLOGINFO("deallocing Texture2D: %p - id=%u", this, _name); CCLOGINFO("deallocing Texture2D: %p - id=%u", this, _name);
CC_SAFE_DELETE(_ninePatchInfo); CC_SAFE_DELETE(_ninePatchInfo);
@ -179,11 +176,6 @@ backend::TextureBackend* Texture2D::getBackendTexture() const
return _texture; return _texture;
} }
bool Texture2D::getAlphaTextureName() const
{
return _alphaTexture == nullptr ? 0 : _alphaTexture->getBackendTexture();
}
Size Texture2D::getContentSize() const Size Texture2D::getContentSize() const
{ {
Size ret; Size ret;
@ -235,6 +227,128 @@ bool Texture2D::initWithData(const void *data, ssize_t dataLen, backend::PixelFo
} }
bool Texture2D::initWithMipmaps(MipmapInfo* mipmaps, int mipmapsNum, backend::PixelFormat pixelFormat, backend::PixelFormat renderFormat, int pixelsWide, int pixelsHigh, bool preMultipliedAlpha) bool Texture2D::initWithMipmaps(MipmapInfo* mipmaps, int mipmapsNum, backend::PixelFormat pixelFormat, backend::PixelFormat renderFormat, int pixelsWide, int pixelsHigh, bool preMultipliedAlpha)
{
//the pixelFormat must be a certain value
updateWithMipmaps(mipmaps, mipmapsNum, pixelFormat, renderFormat, pixelsWide, pixelsHigh, preMultipliedAlpha);
return true;
}
bool Texture2D::updateWithImage(Image* image, backend::PixelFormat format, int index)
{
if (image == nullptr)
{
CCLOG("cocos2d: Texture2D. Can't create Texture. UIImage is nil");
return false;
}
if(this->_filePath.empty()) this->_filePath = image->getFilePath();
int imageWidth = image->getWidth();
int imageHeight = image->getHeight();
Configuration* conf = Configuration::getInstance();
int maxTextureSize = conf->getMaxTextureSize();
if (imageWidth > maxTextureSize || imageHeight > maxTextureSize)
{
CCLOG("cocos2d: WARNING: Image (%u x %u) is bigger than the supported %u x %u", imageWidth, imageHeight, maxTextureSize, maxTextureSize);
return false;
}
unsigned char* tempData = image->getData();
Size imageSize = Size((float)imageWidth, (float)imageHeight);
backend::PixelFormat renderFormat = ((PixelFormat::NONE == format) || (PixelFormat::AUTO == format)) ? image->getPixelFormat() : format;
backend::PixelFormat imagePixelFormat = image->getPixelFormat();
size_t tempDataLen = image->getDataLen();
#ifdef CC_USE_METAL
//compressed format does not need conversion
switch (imagePixelFormat) {
case PixelFormat::PVRTC4A:
case PixelFormat::PVRTC4:
case PixelFormat::PVRTC2A:
case PixelFormat::PVRTC2:
case PixelFormat::A8:
renderFormat = imagePixelFormat;
default:
break;
}
//override renderFormat, since some render format is not supported by metal
switch (renderFormat)
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS && !TARGET_OS_SIMULATOR)
//packed 16 bits pixels only available on iOS
case PixelFormat::RGB565:
renderFormat = PixelFormat::MTL_B5G6R5;
break;
case PixelFormat::RGBA4444:
renderFormat = PixelFormat::MTL_ABGR4;
break;
case PixelFormat::RGB5A1:
renderFormat = PixelFormat::MTL_BGR5A1;
break;
#else
case PixelFormat::RGB565:
case PixelFormat::RGB5A1:
case PixelFormat::RGBA4444:
#endif
case PixelFormat::I8:
case PixelFormat::AI88:
//TODO: conversion RGBA8888 -> I8(AI88) -> RGBA8888 may happends
renderFormat = PixelFormat::RGBA8888;
break;
default:
break;
}
#endif
if (image->getNumberOfMipmaps() > 1)
{
if (renderFormat != image->getPixelFormat())
{
CCLOG("cocos2d: WARNING: This image has more than 1 mipmaps and we will not convert the data format");
}
//pixel format of data is not converted, renderFormat can be different from pixelFormat
//it will be done later
updateWithMipmaps(image->getMipmaps(), image->getNumberOfMipmaps(), image->getPixelFormat(), renderFormat, imageWidth, imageHeight, image->hasPremultipliedAlpha(), index);
return true;
}
else if (image->isCompressed())
{
if (renderFormat != image->getPixelFormat())
{
CCLOG("cocos2d: WARNING: This image is compressed and we can't convert it for now");
}
updateWithData(tempData, tempDataLen, image->getPixelFormat(), image->getPixelFormat(), imageWidth, imageHeight, imageSize, image->hasPremultipliedAlpha(), index);
return true;
}
else
{
//after conversion, renderFormat == pixelFormat of data
updateWithData(tempData, tempDataLen, imagePixelFormat, renderFormat, imageWidth, imageHeight, imageSize, image->hasPremultipliedAlpha(), index);
return true;
}
}
bool Texture2D::updateWithData(const void* data, ssize_t dataLen, backend::PixelFormat pixelFormat, backend::PixelFormat renderFormat, int pixelsWide, int pixelsHigh, const Size& /*contentSize*/, bool preMultipliedAlpha, int index)
{
CCASSERT(dataLen > 0 && pixelsWide > 0 && pixelsHigh > 0, "Invalid size");
//if data has no mipmaps, we will consider it has only one mipmap
MipmapInfo mipmap;
mipmap.address = (unsigned char*)data;
mipmap.len = static_cast<int>(dataLen);
return updateWithMipmaps(&mipmap, 1, pixelFormat, renderFormat, pixelsWide, pixelsHigh, preMultipliedAlpha, index);
}
bool Texture2D::updateWithMipmaps(MipmapInfo* mipmaps, int mipmapsNum, backend::PixelFormat pixelFormat, backend::PixelFormat renderFormat, int pixelsWide, int pixelsHigh, bool preMultipliedAlpha, int index)
{ {
//the pixelFormat must be a certain value //the pixelFormat must be a certain value
CCASSERT(pixelFormat != PixelFormat::NONE && pixelFormat != PixelFormat::AUTO, "the \"pixelFormat\" param must be a certain value!"); CCASSERT(pixelFormat != PixelFormat::NONE && pixelFormat != PixelFormat::AUTO, "the \"pixelFormat\" param must be a certain value!");
@ -290,43 +404,43 @@ bool Texture2D::initWithMipmaps(MipmapInfo* mipmaps, int mipmapsNum, backend::Pi
backend::PixelFormat oriPixelFormat = pixelFormat; backend::PixelFormat oriPixelFormat = pixelFormat;
for (int i = 0; i < mipmapsNum; ++i) for (int i = 0; i < mipmapsNum; ++i)
{ {
unsigned char *data = mipmaps[i].address; unsigned char* data = mipmaps[i].address;
size_t dataLen = mipmaps[i].len; size_t dataLen = mipmaps[i].len;
unsigned char *outData = data; unsigned char* outData = data;
size_t outDataLen = dataLen; size_t outDataLen = dataLen;
if(renderFormat != oriPixelFormat && !info.compressed) //need conversion if (renderFormat != oriPixelFormat && !info.compressed) //need conversion
{ {
auto convertedFormat = backend::PixelFormatUtils::convertDataToFormat(data, dataLen, oriPixelFormat, renderFormat, &outData, &outDataLen); auto convertedFormat = backend::PixelFormatUtils::convertDataToFormat(data, dataLen, oriPixelFormat, renderFormat, &outData, &outDataLen);
#ifdef CC_USE_METAL #ifdef CC_USE_METAL
CCASSERT(convertedFormat == renderFormat, "PixelFormat convert failed!"); CCASSERT(convertedFormat == renderFormat, "PixelFormat convert failed!");
#endif #endif
if(convertedFormat == renderFormat) pixelFormat = renderFormat; if (convertedFormat == renderFormat) pixelFormat = renderFormat;
} }
textureDescriptor.textureFormat = pixelFormat; textureDescriptor.textureFormat = pixelFormat;
CCASSERT(textureDescriptor.textureFormat != backend::PixelFormat::NONE, "PixelFormat should not be NONE"); CCASSERT(textureDescriptor.textureFormat != backend::PixelFormat::NONE, "PixelFormat should not be NONE");
if(_texture->getTextureFormat() != textureDescriptor.textureFormat) if (_texture->getTextureFormat() != textureDescriptor.textureFormat)
_texture->updateTextureDescriptor(textureDescriptor); _texture->updateTextureDescriptor(textureDescriptor, index);
if(info.compressed) if (info.compressed)
{ {
_texture->updateCompressedData(data, width, height, dataLen, i); _texture->updateCompressedData(data, width, height, dataLen, i);
} }
else else
{ {
_texture->updateData(outData, width, height, i); _texture->updateData(outData, width, height, i, index);
} }
if(outData && outData != data && outDataLen > 0) if (outData && outData != data && outDataLen > 0)
{ {
free(outData); free(outData);
outData = nullptr; outData = nullptr;
outDataLen = 0; outDataLen = 0;
} }
if (i > 0 && (width != height || ccNextPOT(width) != width )) if (i > 0 && (width != height || ccNextPOT(width) != width))
{ {
CCLOG("cocos2d: Texture2D. WARNING. Mipmap level %u is not squared. Texture won't render correctly. width=%d != height=%d", i, width, height); CCLOG("cocos2d: Texture2D. WARNING. Mipmap level %u is not squared. Texture won't render correctly. width=%d != height=%d", i, width, height);
} }
@ -335,25 +449,25 @@ bool Texture2D::initWithMipmaps(MipmapInfo* mipmaps, int mipmapsNum, backend::Pi
height = MAX(height >> 1, 1); height = MAX(height >> 1, 1);
} }
_contentSize = Size((float)pixelsWide, (float)pixelsHigh); if (index == 0) {
_pixelsWide = pixelsWide; _contentSize = Size((float)pixelsWide, (float)pixelsHigh);
_pixelsHigh = pixelsHigh; _pixelsWide = pixelsWide;
_pixelFormat = pixelFormat; _pixelsHigh = pixelsHigh;
_maxS = 1; _pixelFormat = pixelFormat;
_maxT = 1; _maxS = 1;
_maxT = 1;
_hasPremultipliedAlpha = preMultipliedAlpha; _hasPremultipliedAlpha = preMultipliedAlpha;
_hasMipmaps = mipmapsNum > 1; _hasMipmaps = mipmapsNum > 1;
}
return true;
} }
bool Texture2D::updateWithData(void *data,int offsetX,int offsetY,int width,int height) bool Texture2D::updateWithSubData(void *data,int offsetX,int offsetY,int width,int height, int index)
{ {
if (_texture && width > 0 && height > 0) if (_texture && width > 0 && height > 0)
{ {
uint8_t* textureData = static_cast<uint8_t*>(data); uint8_t* textureData = static_cast<uint8_t*>(data);
_texture->updateSubData(offsetX, offsetY, width, height, 0, textureData); _texture->updateSubData(offsetX, offsetY, width, height, 0, textureData, index);
return true; return true;
} }
return false; return false;
@ -373,97 +487,9 @@ bool Texture2D::initWithImage(Image *image, backend::PixelFormat format)
return false; return false;
} }
int imageWidth = image->getWidth();
int imageHeight = image->getHeight();
this->_filePath = image->getFilePath(); this->_filePath = image->getFilePath();
Configuration *conf = Configuration::getInstance();
int maxTextureSize = conf->getMaxTextureSize(); return updateWithImage(image, format);
if (imageWidth > maxTextureSize || imageHeight > maxTextureSize)
{
CCLOG("cocos2d: WARNING: Image (%u x %u) is bigger than the supported %u x %u", imageWidth, imageHeight, maxTextureSize, maxTextureSize);
return false;
}
unsigned char* tempData = image->getData();
Size imageSize = Size((float)imageWidth, (float)imageHeight);
backend::PixelFormat renderFormat = ((PixelFormat::NONE == format) || (PixelFormat::AUTO == format)) ? image->getPixelFormat() : format;
backend::PixelFormat imagePixelFormat = image->getPixelFormat();
size_t tempDataLen = image->getDataLen();
#ifdef CC_USE_METAL
//compressed format does not need conversion
switch (imagePixelFormat) {
case PixelFormat::PVRTC4A:
case PixelFormat::PVRTC4:
case PixelFormat::PVRTC2A:
case PixelFormat::PVRTC2:
case PixelFormat::A8:
renderFormat = imagePixelFormat;
default:
break;
}
//override renderFormat, since some render format is not supported by metal
switch (renderFormat)
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS && !TARGET_OS_SIMULATOR)
//packed 16 bits pixels only available on iOS
case PixelFormat::RGB565:
renderFormat = PixelFormat::MTL_B5G6R5;
break;
case PixelFormat::RGBA4444:
renderFormat = PixelFormat::MTL_ABGR4;
break;
case PixelFormat::RGB5A1:
renderFormat = PixelFormat::MTL_BGR5A1;
break;
#else
case PixelFormat::RGB565:
case PixelFormat::RGB5A1:
case PixelFormat::RGBA4444:
#endif
case PixelFormat::I8:
case PixelFormat::AI88:
//TODO: conversion RGBA8888 -> I8(AI88) -> RGBA8888 may happends
renderFormat = PixelFormat::RGBA8888;
break;
default:
break;
}
#endif
if (image->getNumberOfMipmaps() > 1)
{
if (renderFormat != image->getPixelFormat())
{
CCLOG("cocos2d: WARNING: This image has more than 1 mipmaps and we will not convert the data format");
}
//pixel format of data is not converted, renderFormat can be different from pixelFormat
//it will be done later
initWithMipmaps(image->getMipmaps(), image->getNumberOfMipmaps(), image->getPixelFormat(), renderFormat, imageWidth, imageHeight, image->hasPremultipliedAlpha());
return true;
}
else if (image->isCompressed())
{
if (renderFormat != image->getPixelFormat())
{
CCLOG("cocos2d: WARNING: This image is compressed and we can't convert it for now");
}
initWithData(tempData, tempDataLen, image->getPixelFormat(), imageWidth, imageHeight, imageSize, image->hasPremultipliedAlpha());
return true;
}
else
{
//after conversion, renderFormat == pixelFormat of data
initWithData(tempData, tempDataLen, imagePixelFormat, renderFormat, imageWidth, imageHeight, imageSize, image->hasPremultipliedAlpha());
return true;
}
} }
// implementation Texture2D (Text) // implementation Texture2D (Text)
@ -792,22 +818,6 @@ void Texture2D::removeSpriteFrameCapInset(SpriteFrame* spriteFrame)
} }
} }
/// halx99 spec, ANDROID ETC1 ALPHA supports.
void Texture2D::setAlphaTexture(Texture2D* alphaTexture)
{
if (alphaTexture != nullptr) {
alphaTexture->retain();
CC_SAFE_RELEASE(_alphaTexture);
_alphaTexture = alphaTexture;
_hasPremultipliedAlpha = true; // PremultipliedAlpha should be true.
}
}
Texture2D* Texture2D::getAlphaTexture() const
{
return _alphaTexture;
}
void Texture2D::setTexParameters(const Texture2D::TexParams &desc) void Texture2D::setTexParameters(const Texture2D::TexParams &desc)
{ {
_texture->updateSamplerDescriptor(desc); _texture->updateSamplerDescriptor(desc);

View File

@ -170,6 +170,18 @@ public:
*/ */
bool initWithMipmaps(MipmapInfo* mipmaps, int mipmapsNum, backend::PixelFormat pixelFormat, backend::PixelFormat renderFormat, int pixelsWide, int pixelsHigh, bool preMultipliedAlpha = false); bool initWithMipmaps(MipmapInfo* mipmaps, int mipmapsNum, backend::PixelFormat pixelFormat, backend::PixelFormat renderFormat, int pixelsWide, int pixelsHigh, bool preMultipliedAlpha = false);
/** Update with image.
@param data Specifies a pointer to the image data in memory.
@param offsetX Specifies a texel offset in the x direction within the texture array.
@param offsetY Specifies a texel offset in the y direction within the texture array.
@param width Specifies the width of the texture subimage.
@param height Specifies the height of the texture subimage.
*/
bool updateWithImage(Image* image, backend::PixelFormat format, int index = 0);
bool updateWithData(const void* data, ssize_t dataLen, backend::PixelFormat pixelFormat, backend::PixelFormat renderFormat, int pixelsWide, int pixelsHigh, const Size& /*contentSize*/, bool preMultipliedAlpha, int index = 0);
bool updateWithMipmaps(MipmapInfo* mipmaps, int mipmapsNum, backend::PixelFormat pixelFormat, backend::PixelFormat renderFormat, int pixelsWide, int pixelsHigh, bool preMultipliedAlpha = false, int index = 0);
/** Update with texture data. /** Update with texture data.
@param data Specifies a pointer to the image data in memory. @param data Specifies a pointer to the image data in memory.
@ -178,7 +190,7 @@ public:
@param width Specifies the width of the texture subimage. @param width Specifies the width of the texture subimage.
@param height Specifies the height of the texture subimage. @param height Specifies the height of the texture subimage.
*/ */
bool updateWithData(void *data,int offsetX,int offsetY,int width,int height); bool updateWithSubData(void *data,int offsetX,int offsetY,int width,int height, int index = 0);
/** /**
Drawing extensions to make it easy to draw basic quads using a Texture2D object. Drawing extensions to make it easy to draw basic quads using a Texture2D object.
These functions require GL_TEXTURE_2D and both GL_VERTEX_ARRAY and GL_TEXTURE_COORD_ARRAY client states to be enabled. These functions require GL_TEXTURE_2D and both GL_VERTEX_ARRAY and GL_TEXTURE_COORD_ARRAY client states to be enabled.
@ -314,11 +326,6 @@ public:
std::string getPath()const { return _filePath; } std::string getPath()const { return _filePath; }
void setAlphaTexture(Texture2D* alphaTexture);
Texture2D* getAlphaTexture() const;
bool getAlphaTextureName() const;
public: public:
/** Get pixel info map, the key-value pairs is PixelFormat and PixelFormatInfo.*/ /** Get pixel info map, the key-value pairs is PixelFormat and PixelFormatInfo.*/
static const PixelFormatInfoMap& getPixelFormatInfoMap(); static const PixelFormatInfoMap& getPixelFormatInfoMap();
@ -409,7 +416,6 @@ protected:
bool _valid; bool _valid;
std::string _filePath; std::string _filePath;
Texture2D* _alphaTexture;
backend::ProgramState* _programState = nullptr; backend::ProgramState* _programState = nullptr;
backend::UniformLocation _mvpMatrixLocation; backend::UniformLocation _mvpMatrixLocation;
backend::UniformLocation _textureLocation; backend::UniformLocation _textureLocation;

View File

@ -348,11 +348,7 @@ void TextureCache::addImageAsyncCallBack(float /*dt*/)
texture->autorelease(); texture->autorelease();
// ETC1 ALPHA supports. // ETC1 ALPHA supports.
if (asyncStruct->imageAlpha.getFileType() == Image::Format::ETC) { if (asyncStruct->imageAlpha.getFileType() == Image::Format::ETC) {
auto alphaTexture = new(std::nothrow) Texture2D(); texture->updateWithImage(&asyncStruct->imageAlpha, Texture2D::getDefaultAlphaPixelFormat(), 1);
if(alphaTexture != nullptr && alphaTexture->initWithImage(&asyncStruct->imageAlpha, asyncStruct->pixelFormat)) {
texture->setAlphaTexture(alphaTexture);
}
CC_SAFE_RELEASE(alphaTexture);
} }
} }
else { else {
@ -421,14 +417,10 @@ Texture2D * TextureCache::addImage(const std::string &path)
std::string alphaFullPath = path + s_etc1AlphaFileSuffix; std::string alphaFullPath = path + s_etc1AlphaFileSuffix;
if (image->getFileType() == Image::Format::ETC && !s_etc1AlphaFileSuffix.empty() && FileUtils::getInstance()->isFileExist(alphaFullPath)) if (image->getFileType() == Image::Format::ETC && !s_etc1AlphaFileSuffix.empty() && FileUtils::getInstance()->isFileExist(alphaFullPath))
{ {
Image alphaImage; Image imageAlpha;
if (alphaImage.initWithImageFile(alphaFullPath)) if (imageAlpha.initWithImageFile(alphaFullPath))
{ {
Texture2D *pAlphaTexture = new(std::nothrow) Texture2D; texture->updateWithImage(&imageAlpha, Texture2D::getDefaultAlphaPixelFormat(), 1);
if(pAlphaTexture != nullptr && pAlphaTexture->initWithImage(&alphaImage)) {
texture->setAlphaTexture(pAlphaTexture);
}
CC_SAFE_RELEASE(pAlphaTexture);
} }
} }

View File

@ -114,8 +114,6 @@ protected:
/**Model view matrix when rendering the triangles.*/ /**Model view matrix when rendering the triangles.*/
Mat4 _mv; Mat4 _mv;
uint8_t _alphaTextureID = 0; // ANDROID ETC1 ALPHA supports.
// Cached value to determine to generate material id or not. // Cached value to determine to generate material id or not.
BlendFunc _blendType = BlendFunc::DISABLE; BlendFunc _blendType = BlendFunc::DISABLE;
backend::Program* _program = nullptr; backend::Program* _program = nullptr;

View File

@ -36,6 +36,7 @@ set(COCOS_RENDERER_HEADER
renderer/backend/Types.h renderer/backend/Types.h
renderer/backend/VertexLayout.h renderer/backend/VertexLayout.h
renderer/backend/ProgramState.h renderer/backend/ProgramState.h
renderer/backend/ProgramStateRegistry.h
renderer/backend/ShaderCache.h renderer/backend/ShaderCache.h
renderer/backend/DeviceInfo.h renderer/backend/DeviceInfo.h
) )
@ -70,6 +71,7 @@ set(COCOS_RENDERER_SRC
renderer/backend/ProgramCache.cpp renderer/backend/ProgramCache.cpp
renderer/backend/Program.cpp renderer/backend/Program.cpp
renderer/backend/ProgramState.cpp renderer/backend/ProgramState.cpp
renderer/backend/ProgramStateRegistry.cpp
renderer/backend/ShaderCache.cpp renderer/backend/ShaderCache.cpp
renderer/backend/RenderPassDescriptor.cpp renderer/backend/RenderPassDescriptor.cpp
) )

View File

@ -29,20 +29,6 @@
#include "base/ccMacros.h" #include "base/ccMacros.h"
#include "base/CCConfiguration.h" #include "base/CCConfiguration.h"
namespace std
{
template <>
struct hash<cocos2d::backend::ProgramType>
{
typedef cocos2d::backend::ProgramType argument_type;
typedef std::size_t result_type;
result_type operator()(argument_type const& v) const
{
return hash<int>()(static_cast<int>(v));
}
};
}
CC_BACKEND_BEGIN CC_BACKEND_BEGIN
namespace namespace
@ -126,6 +112,16 @@ bool ProgramCache::init()
addProgram(ProgramType::TERRAIN_3D); addProgram(ProgramType::TERRAIN_3D);
addProgram(ProgramType::PARTICLE_TEXTURE_3D); addProgram(ProgramType::PARTICLE_TEXTURE_3D);
addProgram(ProgramType::PARTICLE_COLOR_3D); addProgram(ProgramType::PARTICLE_COLOR_3D);
/* FIXME: Naming style
** ETC1: POSITION_TEXTURE_COLOR_ETC1
** GRAY_SCALE maybe: POSITION_TEXTURE_COLOR_GRAY
** ETC1_GRAY maybe: POSITION_TEXTURE_COLOR_GRAY_ETC1
*/
ProgramStateRegistry::getInstance()->registerProgram(ProgramType::POSITION_TEXTURE_COLOR, 2,
getBuiltinProgram(ProgramType::ETC1));
ProgramStateRegistry::getInstance()->registerProgram(ProgramType::GRAY_SCALE, 2,
getBuiltinProgram(ProgramType::ETC1_GRAY));
return true; return true;
} }
@ -298,6 +294,7 @@ void ProgramCache::removeUnusedProgram()
void ProgramCache::removeAllPrograms() void ProgramCache::removeAllPrograms()
{ {
ProgramStateRegistry::getInstance()->clearPrograms();
for (auto& program : _cachedPrograms) for (auto& program : _cachedPrograms)
{ {
program.second->release(); program.second->release();

View File

@ -32,6 +32,8 @@
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
#include "ProgramStateRegistry.h"
CC_BACKEND_BEGIN CC_BACKEND_BEGIN
/** /**
* @addtogroup _backend * @addtogroup _backend

View File

@ -381,6 +381,14 @@ void ProgramState::setFragmentUniform(int location, const void* data, std::size_
#endif #endif
} }
void ProgramState::setTexture(backend::TextureBackend* texture)
{
for (int index = 0; index < texture->getCount() && index < CC_META_TEXTURES; ++index) {
auto location = getUniformLocation((backend::Uniform)(backend::Uniform::TEXTURE + index));
setTexture(location, index, texture);
}
}
void ProgramState::setTexture(const backend::UniformLocation& uniformLocation, uint32_t slot, backend::TextureBackend* texture) void ProgramState::setTexture(const backend::UniformLocation& uniformLocation, uint32_t slot, backend::TextureBackend* texture)
{ {
switch (uniformLocation.shaderStage) switch (uniformLocation.shaderStage)

View File

@ -142,6 +142,14 @@ public:
*/ */
void setCallbackUniform(const backend::UniformLocation&, const UniformCallback &); void setCallbackUniform(const backend::UniformLocation&, const UniformCallback &);
/**
* Set texture.
* @param uniformLocation Specifies texture location.
* @param slot Specifies texture slot selector.
* @param texture Specifies a pointer to backend texture.
*/
void setTexture(backend::TextureBackend* texture);
/** /**
* Set texture. * Set texture.
* @param uniformLocation Specifies texture location. * @param uniformLocation Specifies texture location.

View File

@ -0,0 +1,81 @@
#pragma once
#include "ProgramStateRegistry.h"
CC_BACKEND_BEGIN
static ProgramStateRegistry* _sharedStateRegistry = nullptr;
/** returns the shared instance */
ProgramStateRegistry* ProgramStateRegistry::getInstance()
{
if (_sharedStateRegistry)
return _sharedStateRegistry;
_sharedStateRegistry = new (std::nothrow) ProgramStateRegistry();
if (!_sharedStateRegistry->init())
{
CC_SAFE_RELEASE_NULL(_sharedStateRegistry);
}
return _sharedStateRegistry;
}
/** purges the cache. It releases the retained instance. */
void ProgramStateRegistry::destroyInstance()
{
CC_SAFE_RELEASE_NULL(_sharedStateRegistry);
}
bool ProgramStateRegistry::init()
{
return true;
}
void ProgramStateRegistry::registerProgram(ProgramType programType, int maxCount, Program* program)
{
auto maxIndex = maxCount - 1;
auto it = this->_registry.find(programType);
if (it == this->_registry.end()) {
it = this->_registry.emplace(programType, std::vector<Program*>{}).first;
it->second.resize(CC_META_TEXTURES);
}
if (maxIndex < it->second.size())
it->second[maxIndex] = program;
}
void ProgramStateRegistry::clearPrograms() {
this->_registry.clear();
}
ProgramState* ProgramStateRegistry::getProgramState(ProgramType programType, int maxCount)
{
auto maxIndex = maxCount - 1;
auto it = this->_registry.find(programType);
if (it != this->_registry.end() && it->second.size() > maxIndex) {
auto fallback = it->second[maxIndex];
if (fallback)
return new(std::nothrow) ProgramState(fallback);
}
return new(std::nothrow) ProgramState(Program::getBuiltinProgram((ProgramType)programType));
}
ProgramType ProgramStateRegistry::getProgramType(ProgramType programType, TextureBackend* texture2d)
{
return this->getProgramType(programType, texture2d->getCount());
}
ProgramType ProgramStateRegistry::getProgramType(ProgramType programType, int maxCount)
{
auto maxIndex = maxCount - 1;
auto it = this->_registry.find(programType);
if (it != this->_registry.end() && it->second.size() > maxIndex) {
auto fallback = it->second[maxIndex];
if (fallback)
return fallback->getProgramType();
}
return programType;
}
//end of _backend group
/// @}
CC_BACKEND_END

View File

@ -0,0 +1,62 @@
#pragma once
#include "Macros.h"
#include "base/CCRef.h"
#include "platform/CCPlatformMacros.h"
#include "Program.h"
#include "ProgramState.h"
#include <string>
#include <unordered_map>
namespace std
{
template <>
struct hash<cocos2d::backend::ProgramType>
{
typedef cocos2d::backend::ProgramType argument_type;
typedef std::size_t result_type;
result_type operator()(argument_type const& v) const
{
return hash<int>()(static_cast<int>(v));
}
};
};
CC_BACKEND_BEGIN
/**
* @addtogroup _backend
* @{
* #todo: Rename to ProgramStateRegistry
*/
/*
Group by programType and texIndex
default, we register:
programType = positionTextureColor, texIndex = 0 ---> positionTextureColorDefault
programType = positionTextureColor, texIndex = 1 ---> positionTextureColorDualETC1
*/
class ProgramStateRegistry : public Ref {
public:
/** returns the shared instance */
static ProgramStateRegistry* getInstance();
/** purges the cache. It releases the retained instance. */
static void destroyInstance();
bool init();
void registerProgram(ProgramType programType, int maxCount, Program*);
void clearPrograms();
ProgramState* getProgramState(ProgramType programType, int maxCount);
ProgramType getProgramType(ProgramType programType, TextureBackend* texture2d);
ProgramType getProgramType(ProgramType programType, int maxCount);
protected:
std::unordered_map<ProgramType, std::vector<Program*>> _registry;
};
//end of _backend group
/// @}
CC_BACKEND_END

View File

@ -107,7 +107,7 @@ TextureBackend::TextureBackend(const TextureDescriptor& descriptor)
TextureBackend::~TextureBackend() TextureBackend::~TextureBackend()
{} {}
void TextureBackend::updateTextureDescriptor(const cocos2d::backend::TextureDescriptor &descriptor) void TextureBackend::updateTextureDescriptor(const cocos2d::backend::TextureDescriptor &descriptor, int /*index*/)
{ {
_bitsPerElement = computeBitsPerElement(descriptor.textureFormat); _bitsPerElement = computeBitsPerElement(descriptor.textureFormat);
_textureType = descriptor.textureType; _textureType = descriptor.textureType;

View File

@ -60,7 +60,7 @@ public:
* Update sampler * Update sampler
* @param sampler Specifies the sampler descriptor. * @param sampler Specifies the sampler descriptor.
*/ */
virtual void updateSamplerDescriptor(const SamplerDescriptor &sampler) = 0; virtual void updateSamplerDescriptor(const SamplerDescriptor &sampler, int index = 0) = 0;
/** /**
* Read a block of pixels from the drawable texture * Read a block of pixels from the drawable texture
@ -78,7 +78,7 @@ public:
* Update texture description. * Update texture description.
* @param descriptor Specifies texture and sampler descriptor. * @param descriptor Specifies texture and sampler descriptor.
*/ */
virtual void updateTextureDescriptor(const TextureDescriptor& descriptor); virtual void updateTextureDescriptor(const TextureDescriptor& descriptor, int index = 0);
/** /**
* Get texture format. * Get texture format.
@ -104,6 +104,8 @@ public:
*/ */
inline bool hasMipmaps() const { return _hasMipmaps; } inline bool hasMipmaps() const { return _hasMipmaps; }
virtual int getCount() const = 0;
protected: protected:
/** /**
* @param descriptor Specifies the texture descirptor. * @param descriptor Specifies the texture descirptor.
@ -136,7 +138,7 @@ public:
* @param height Specifies the height of the texture image. * @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. * @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) = 0; virtual void updateData(uint8_t* data, std::size_t width , std::size_t height, std::size_t level, int index = 0) = 0;
/** /**
* Update a two-dimensional texture image in a compressed format * Update a two-dimensional texture image in a compressed format
@ -157,7 +159,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 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. * @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) = 0; 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) = 0;
/** /**
* Update a two-dimensional texture subimage in a compressed format * Update a two-dimensional texture subimage in a compressed format

View File

@ -77,14 +77,14 @@ void TextureInfoGL::applySamplerDescriptor(const SamplerDescriptor& descriptor,
Texture2DGL::Texture2DGL(const TextureDescriptor& descriptor) : Texture2DBackend(descriptor) Texture2DGL::Texture2DGL(const TextureDescriptor& descriptor) : Texture2DBackend(descriptor)
{ {
glGenTextures(1, &_textureInfo.texture); glGenTextures(1, &_textureInfo.textures[0]);
updateTextureDescriptor(descriptor); updateTextureDescriptor(descriptor);
#if CC_ENABLE_CACHE_TEXTURE_DATA #if CC_ENABLE_CACHE_TEXTURE_DATA
// Listen this event to restored texture id after coming to foreground on Android. // Listen this event to restored texture id after coming to foreground on Android.
_backToForegroundListener = EventListenerCustom::create(EVENT_RENDERER_RECREATED, [this](EventCustom*){ _backToForegroundListener = EventListenerCustom::create(EVENT_RENDERER_RECREATED, [this](EventCustom*){
glGenTextures(1, &(this->_textureInfo.texture)); glGenTextures(1, &(this->_textureInfo.textures[0]));
this->initWithZeros(); this->initWithZeros();
}); });
Director::getInstance()->getEventDispatcher()->addEventListenerWithFixedPriority(_backToForegroundListener, -1); Director::getInstance()->getEventDispatcher()->addEventListenerWithFixedPriority(_backToForegroundListener, -1);
@ -100,9 +100,9 @@ void Texture2DGL::initWithZeros()
free(data); free(data);
} }
void Texture2DGL::updateTextureDescriptor(const cocos2d::backend::TextureDescriptor &descriptor) void Texture2DGL::updateTextureDescriptor(const cocos2d::backend::TextureDescriptor &descriptor, int index)
{ {
TextureBackend::updateTextureDescriptor(descriptor); TextureBackend::updateTextureDescriptor(descriptor, index);
UtilsGL::toGLTypes(descriptor.textureFormat, _textureInfo.internalFormat, _textureInfo.format, _textureInfo.type, _isCompressed); UtilsGL::toGLTypes(descriptor.textureFormat, _textureInfo.internalFormat, _textureInfo.format, _textureInfo.type, _isCompressed);
bool isPow2 = ISPOW2(_width) && ISPOW2(_height); bool isPow2 = ISPOW2(_width) && ISPOW2(_height);
@ -112,7 +112,7 @@ void Texture2DGL::updateTextureDescriptor(const cocos2d::backend::TextureDescrip
_textureInfo.sAddressModeGL = UtilsGL::toGLAddressMode(descriptor.samplerDescriptor.sAddressMode, isPow2); _textureInfo.sAddressModeGL = UtilsGL::toGLAddressMode(descriptor.samplerDescriptor.sAddressMode, isPow2);
_textureInfo.tAddressModeGL = UtilsGL::toGLAddressMode(descriptor.samplerDescriptor.tAddressMode, isPow2); _textureInfo.tAddressModeGL = UtilsGL::toGLAddressMode(descriptor.samplerDescriptor.tAddressMode, isPow2);
updateSamplerDescriptor(descriptor.samplerDescriptor); updateSamplerDescriptor(descriptor.samplerDescriptor, index);
// Update data here because `updateData()` may not be invoked later. // Update data here because `updateData()` may not be invoked later.
// For example, a texture used as depth buffer will not invoke updateData(). // For example, a texture used as depth buffer will not invoke updateData().
@ -121,20 +121,18 @@ void Texture2DGL::updateTextureDescriptor(const cocos2d::backend::TextureDescrip
Texture2DGL::~Texture2DGL() Texture2DGL::~Texture2DGL()
{ {
if (_textureInfo.texture) _textureInfo.foreach([=](GLuint texID, int) { glDeleteTextures(1, &texID); });
glDeleteTextures(1, &_textureInfo.texture); _textureInfo.textures.fill(0);
_textureInfo.texture = 0;
#if CC_ENABLE_CACHE_TEXTURE_DATA #if CC_ENABLE_CACHE_TEXTURE_DATA
Director::getInstance()->getEventDispatcher()->removeEventListener(_backToForegroundListener); Director::getInstance()->getEventDispatcher()->removeEventListener(_backToForegroundListener);
#endif #endif
} }
void Texture2DGL::updateSamplerDescriptor(const SamplerDescriptor &sampler) { void Texture2DGL::updateSamplerDescriptor(const SamplerDescriptor &sampler, int index) {
bool isPow2 = ISPOW2(_width) && ISPOW2(_height); bool isPow2 = ISPOW2(_width) && ISPOW2(_height);
_textureInfo.applySamplerDescriptor(sampler, isPow2, _hasMipmaps); _textureInfo.applySamplerDescriptor(sampler, isPow2, _hasMipmaps);
glActiveTexture(GL_TEXTURE0); ensure(index);
glBindTexture(GL_TEXTURE_2D, _textureInfo.texture);
if (sampler.magFilter != SamplerFilter::DONT_CARE) if (sampler.magFilter != SamplerFilter::DONT_CARE)
{ {
@ -157,7 +155,7 @@ void Texture2DGL::updateSamplerDescriptor(const SamplerDescriptor &sampler) {
} }
} }
void Texture2DGL::updateData(uint8_t* data, std::size_t width , std::size_t height, std::size_t level) void Texture2DGL::updateData(uint8_t* data, std::size_t width , std::size_t height, std::size_t level, int index)
{ {
//Set the row align only when mipmapsNum == 1 and the data is uncompressed //Set the row align only when mipmapsNum == 1 and the data is uncompressed
auto mipmapEnalbed = isMipmapEnabled(_textureInfo.minFilterGL) || isMipmapEnabled(_textureInfo.magFilterGL); auto mipmapEnalbed = isMipmapEnabled(_textureInfo.minFilterGL) || isMipmapEnabled(_textureInfo.magFilterGL);
@ -187,8 +185,8 @@ void Texture2DGL::updateData(uint8_t* data, std::size_t width , std::size_t heig
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
} }
glActiveTexture(GL_TEXTURE0); auto texID = ensure(index);
glBindTexture(GL_TEXTURE_2D, _textureInfo.texture); if (!texID) return;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, _textureInfo.magFilterGL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, _textureInfo.magFilterGL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, _textureInfo.minFilterGL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, _textureInfo.minFilterGL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, _textureInfo.sAddressModeGL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, _textureInfo.sAddressModeGL);
@ -204,6 +202,9 @@ void Texture2DGL::updateData(uint8_t* data, std::size_t width , std::size_t heig
_textureInfo.format, _textureInfo.format,
_textureInfo.type, _textureInfo.type,
data); data);
cocos2d::log("---> Texture2DGL::updateData:%u", texID);
CHECK_GL_ERROR_DEBUG(); CHECK_GL_ERROR_DEBUG();
if(!_hasMipmaps && level > 0) if(!_hasMipmaps && level > 0)
@ -216,7 +217,7 @@ void Texture2DGL::updateCompressedData(uint8_t *data, std::size_t width, std::si
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, _textureInfo.texture); glBindTexture(GL_TEXTURE_2D, _textureInfo.textures[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, _textureInfo.magFilterGL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, _textureInfo.magFilterGL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, _textureInfo.minFilterGL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, _textureInfo.minFilterGL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, _textureInfo.sAddressModeGL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, _textureInfo.sAddressModeGL);
@ -237,10 +238,9 @@ void Texture2DGL::updateCompressedData(uint8_t *data, std::size_t width, std::si
_hasMipmaps = true; _hasMipmaps = true;
} }
void Texture2DGL::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 Texture2DGL::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)
{ {
glActiveTexture(GL_TEXTURE0); if (!ensure(index)) return;
glBindTexture(GL_TEXTURE_2D, _textureInfo.texture);
glTexSubImage2D(GL_TEXTURE_2D, glTexSubImage2D(GL_TEXTURE_2D,
level, level,
@ -262,7 +262,7 @@ void Texture2DGL::updateCompressedSubData(std::size_t xoffset, std::size_t yoffs
uint8_t *data) uint8_t *data)
{ {
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, _textureInfo.texture); glBindTexture(GL_TEXTURE_2D, _textureInfo.textures[0]);
glCompressedTexSubImage2D(GL_TEXTURE_2D, glCompressedTexSubImage2D(GL_TEXTURE_2D,
level, level,
@ -282,7 +282,21 @@ void Texture2DGL::updateCompressedSubData(std::size_t xoffset, std::size_t yoffs
void Texture2DGL::apply(int index) const void Texture2DGL::apply(int index) const
{ {
glActiveTexture(GL_TEXTURE0 + index); glActiveTexture(GL_TEXTURE0 + index);
glBindTexture(GL_TEXTURE_2D, _textureInfo.texture); glBindTexture(GL_TEXTURE_2D, index < CC_META_TEXTURES ? _textureInfo.textures[index] : 0);
}
GLuint Texture2DGL::ensure(int index)
{
if (index >= CC_META_TEXTURES) return 0;
glActiveTexture(GL_TEXTURE0 + index);
auto& texID = _textureInfo.textures[index];
if (!texID)
glGenTextures(1, &texID);
glBindTexture(GL_TEXTURE_2D, texID);
if (_maxTextureIndex < index) _maxTextureIndex = index;
return texID;
} }
void Texture2DGL::generateMipmaps() void Texture2DGL::generateMipmaps()
@ -293,7 +307,7 @@ void Texture2DGL::generateMipmaps()
if(!_hasMipmaps) if(!_hasMipmaps)
{ {
_hasMipmaps = true; _hasMipmaps = true;
glBindTexture(GL_TEXTURE_2D, _textureInfo.texture); glBindTexture(GL_TEXTURE_2D, _textureInfo.textures[0]);
glGenerateMipmap(GL_TEXTURE_2D); glGenerateMipmap(GL_TEXTURE_2D);
} }
} }
@ -306,7 +320,7 @@ void Texture2DGL::getBytes(std::size_t x, std::size_t y, std::size_t width, std:
GLuint frameBuffer = 0; GLuint frameBuffer = 0;
glGenFramebuffers(1, &frameBuffer); glGenFramebuffers(1, &frameBuffer);
glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer); glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _textureInfo.texture, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _textureInfo.textures[0], 0);
glPixelStorei(GL_PACK_ALIGNMENT, 1); glPixelStorei(GL_PACK_ALIGNMENT, 1);
auto bytePerRow = width * _bitsPerElement / 8; auto bytePerRow = width * _bitsPerElement / 8;
@ -340,7 +354,7 @@ TextureCubeGL::TextureCubeGL(const TextureDescriptor& descriptor)
assert(_width == _height); assert(_width == _height);
_textureType = TextureType::TEXTURE_CUBE; _textureType = TextureType::TEXTURE_CUBE;
UtilsGL::toGLTypes(_textureFormat, _textureInfo.internalFormat, _textureInfo.format, _textureInfo.type, _isCompressed); UtilsGL::toGLTypes(_textureFormat, _textureInfo.internalFormat, _textureInfo.format, _textureInfo.type, _isCompressed);
glGenTextures(1, &_textureInfo.texture); glGenTextures(1, &_textureInfo.textures[0]);
updateSamplerDescriptor(descriptor.samplerDescriptor); updateSamplerDescriptor(descriptor.samplerDescriptor);
#if CC_ENABLE_CACHE_TEXTURE_DATA #if CC_ENABLE_CACHE_TEXTURE_DATA
@ -357,7 +371,7 @@ TextureCubeGL::TextureCubeGL(const TextureDescriptor& descriptor)
void TextureCubeGL::setTexParameters() void TextureCubeGL::setTexParameters()
{ {
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_CUBE_MAP, _textureInfo.texture); glBindTexture(GL_TEXTURE_CUBE_MAP, _textureInfo.textures[0]);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, _textureInfo.minFilterGL); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, _textureInfo.minFilterGL);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, _textureInfo.magFilterGL); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, _textureInfo.magFilterGL);
@ -367,41 +381,40 @@ void TextureCubeGL::setTexParameters()
glBindTexture(GL_TEXTURE_CUBE_MAP, 0); glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
} }
void TextureCubeGL::updateTextureDescriptor(const cocos2d::backend::TextureDescriptor &descriptor) void TextureCubeGL::updateTextureDescriptor(const cocos2d::backend::TextureDescriptor &descriptor, int index)
{ {
UtilsGL::toGLTypes(descriptor.textureFormat, _textureInfo.internalFormat, _textureInfo.format, _textureInfo.type, _isCompressed); UtilsGL::toGLTypes(descriptor.textureFormat, _textureInfo.internalFormat, _textureInfo.format, _textureInfo.type, _isCompressed);
_textureFormat = descriptor.textureFormat; _textureFormat = descriptor.textureFormat;
updateSamplerDescriptor(descriptor.samplerDescriptor); updateSamplerDescriptor(descriptor.samplerDescriptor, index);
} }
TextureCubeGL::~TextureCubeGL() TextureCubeGL::~TextureCubeGL()
{ {
if(_textureInfo.texture) _textureInfo.foreach([=](GLuint texID, int) { glDeleteTextures(1, &texID); });
glDeleteTextures(1, &_textureInfo.texture); _textureInfo.textures.fill(0);
_textureInfo.texture = 0;
#if CC_ENABLE_CACHE_TEXTURE_DATA #if CC_ENABLE_CACHE_TEXTURE_DATA
Director::getInstance()->getEventDispatcher()->removeEventListener(_backToForegroundListener); Director::getInstance()->getEventDispatcher()->removeEventListener(_backToForegroundListener);
#endif #endif
} }
void TextureCubeGL::updateSamplerDescriptor(const SamplerDescriptor &sampler) void TextureCubeGL::updateSamplerDescriptor(const SamplerDescriptor &sampler, int /*index*/)
{ {
_textureInfo.applySamplerDescriptor(sampler, true, _hasMipmaps); _textureInfo.applySamplerDescriptor(sampler, true, _hasMipmaps);
setTexParameters(); setTexParameters();
} }
void TextureCubeGL::apply(int index) const void TextureCubeGL::apply(int location) const
{ {
glActiveTexture(GL_TEXTURE0+ index); glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_CUBE_MAP, _textureInfo.texture); glBindTexture(GL_TEXTURE_CUBE_MAP, _textureInfo.textures[0]);
CHECK_GL_ERROR_DEBUG(); CHECK_GL_ERROR_DEBUG();
} }
void TextureCubeGL::updateFaceData(TextureCubeFace side, void *data) void TextureCubeGL::updateFaceData(TextureCubeFace side, void *data)
{ {
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_CUBE_MAP, _textureInfo.texture); glBindTexture(GL_TEXTURE_CUBE_MAP, _textureInfo.textures[0]);
CHECK_GL_ERROR_DEBUG(); CHECK_GL_ERROR_DEBUG();
int i = static_cast<int>(side); int i = static_cast<int>(side);
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i,
@ -425,7 +438,7 @@ void TextureCubeGL::getBytes(std::size_t x, std::size_t y, std::size_t width, st
GLuint frameBuffer = 0; GLuint frameBuffer = 0;
glGenFramebuffers(1, &frameBuffer); glGenFramebuffers(1, &frameBuffer);
glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer); glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP, _textureInfo.texture, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP, _textureInfo.textures[0], 0);
glPixelStorei(GL_PACK_ALIGNMENT, 1); glPixelStorei(GL_PACK_ALIGNMENT, 1);
auto bytePerRow = width * _bitsPerElement / 8; auto bytePerRow = width * _bitsPerElement / 8;
@ -461,7 +474,7 @@ void TextureCubeGL::generateMipmaps()
if(!_hasMipmaps) if(!_hasMipmaps)
{ {
_hasMipmaps = true; _hasMipmaps = true;
glBindTexture(GL_TEXTURE_CUBE_MAP, _textureInfo.texture); glBindTexture(GL_TEXTURE_CUBE_MAP, _textureInfo.textures[0]);
glGenerateMipmap(GL_TEXTURE_CUBE_MAP); glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
} }
} }

View File

@ -24,6 +24,7 @@
#pragma once #pragma once
#include <array>
#include "../Texture.h" #include "../Texture.h"
#include "platform/CCGL.h" #include "platform/CCGL.h"
#include "base/CCEventListenerCustom.h" #include "base/CCEventListenerCustom.h"
@ -36,6 +37,17 @@ CC_BACKEND_BEGIN
struct TextureInfoGL struct TextureInfoGL
{ {
void applySamplerDescriptor(const SamplerDescriptor &desc, bool isPow2, bool hasMipmaps); void applySamplerDescriptor(const SamplerDescriptor &desc, bool isPow2, bool hasMipmaps);
TextureInfoGL() {
textures.fill(0);
}
template<typename _Fty>
void foreach(const _Fty& cb) const {
GLuint texID;
int idx = 0;
while (texID = textures[idx])
cb(texID, idx++);
}
GLint magFilterGL = GL_LINEAR; GLint magFilterGL = GL_LINEAR;
GLint minFilterGL = GL_LINEAR; GLint minFilterGL = GL_LINEAR;
@ -47,7 +59,7 @@ struct TextureInfoGL
GLenum format = GL_RGBA; GLenum format = GL_RGBA;
GLenum type = GL_UNSIGNED_BYTE; GLenum type = GL_UNSIGNED_BYTE;
GLuint texture = 0; std::array<GLuint, CC_META_TEXTURES + 1> textures;
}; };
/** /**
@ -74,7 +86,7 @@ public:
* @param height Specifies the height of the texture image. * @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. * @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 * Update a two-dimensional texture image in a compressed format
@ -95,7 +107,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 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. * @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 * Update a two-dimensional texture subimage in a compressed format
@ -113,7 +125,7 @@ public:
* Update sampler * Update sampler
* @param sampler Specifies the sampler descriptor. * @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 * Read a block of pixels from the drawable texture
@ -133,13 +145,13 @@ public:
* Update texture description. * Update texture description.
* @param descriptor Specifies texture and sampler descriptor. * @param descriptor Specifies texture and sampler descriptor.
*/ */
virtual void updateTextureDescriptor(const TextureDescriptor& descriptor) override; virtual void updateTextureDescriptor(const TextureDescriptor& descriptor, int index = 0) override;
/** /**
* Get texture object. * Get texture object.
* @return Texture object. * @return Texture object.
*/ */
inline GLuint getHandler() const { return _textureInfo.texture; } inline GLuint getHandler() const { return _textureInfo.textures[0]; }
/** /**
* Set texture to pipeline * Set texture to pipeline
@ -147,10 +159,15 @@ public:
*/ */
void apply(int index) const; void apply(int index) const;
GLuint ensure(int index);
int getCount() const override { return _maxTextureIndex + 1; }
private: private:
void initWithZeros(); void initWithZeros();
TextureInfoGL _textureInfo; TextureInfoGL _textureInfo;
int _maxTextureIndex = 0;
EventListener* _backToForegroundListener = nullptr; EventListener* _backToForegroundListener = nullptr;
}; };
@ -170,7 +187,7 @@ public:
* Update sampler * Update sampler
* @param sampler Specifies the sampler descriptor. * @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. * Update texutre cube data in give slice side.
@ -195,19 +212,21 @@ public:
* Update texture description. * Update texture description.
* @param descriptor Specifies texture and sampler descriptor. * @param descriptor Specifies texture and sampler descriptor.
*/ */
virtual void updateTextureDescriptor(const TextureDescriptor& descriptor) override ; virtual void updateTextureDescriptor(const TextureDescriptor& descriptor, int index = 0) override ;
/** /**
* Get texture object. * Get texture object.
* @return Texture object. * @return Texture object.
*/ */
inline GLuint getHandler() const { return _textureInfo.texture; } inline GLuint getHandler() const { return _textureInfo.textures[0]; }
/** /**
* Set texture to pipeline * Set texture to pipeline
* @param index Specifies the texture image unit selector. * @param index Specifies the texture image unit selector.
*/ */
void apply(int index) const; void apply(int location) const;
int getCount() const { return 1; }
private: private:
void setTexParameters(); void setTexParameters();

View File

@ -27,6 +27,7 @@ THE SOFTWARE.
#include "2d/CCSprite.h" #include "2d/CCSprite.h"
#include "editor-support/cocostudio/CocosStudioExtension.h" #include "editor-support/cocostudio/CocosStudioExtension.h"
#include "renderer/ccShaders.h" #include "renderer/ccShaders.h"
#include "renderer/backend/ProgramStateRegistry.h"
NS_CC_BEGIN NS_CC_BEGIN
@ -309,12 +310,8 @@ void AbstractCheckButton::onPressStateChangedToNormal()
_backGroundBoxDisabledRenderer->setVisible(false); _backGroundBoxDisabledRenderer->setVisible(false);
_frontCrossDisabledRenderer->setVisible(false); _frontCrossDisabledRenderer->setVisible(false);
auto isETC1 = _backGroundBoxRenderer->getTexture() && _backGroundBoxRenderer->getTexture()->getAlphaTextureName(); _backGroundBoxRenderer->setProgramState(backend::ProgramType::POSITION_TEXTURE_COLOR);
_backGroundBoxRenderer->updateShaders(positionTextureColor_vert, (isETC1)?etc1_frag:positionTextureColor_frag); _frontCrossRenderer->setProgramState(backend::ProgramType::POSITION_TEXTURE_COLOR);
isETC1 = _frontCrossRenderer->getTexture() && _frontCrossRenderer->getTexture()->getAlphaTextureName();
_frontCrossRenderer->updateShaders(positionTextureColor_vert, (isETC1)?etc1_frag:positionTextureColor_frag);
_backGroundBoxRenderer->setScale(_backgroundTextureScaleX, _backgroundTextureScaleY); _backGroundBoxRenderer->setScale(_backgroundTextureScaleX, _backgroundTextureScaleY);
_frontCrossRenderer->setScale(_backgroundTextureScaleX, _backgroundTextureScaleY); _frontCrossRenderer->setScale(_backgroundTextureScaleX, _backgroundTextureScaleY);
@ -329,11 +326,8 @@ void AbstractCheckButton::onPressStateChangedToNormal()
void AbstractCheckButton::onPressStateChangedToPressed() void AbstractCheckButton::onPressStateChangedToPressed()
{ {
auto isETC1 = _backGroundBoxRenderer->getTexture() && _backGroundBoxRenderer->getTexture()->getAlphaTextureName(); _backGroundBoxRenderer->setProgramState(backend::ProgramType::POSITION_TEXTURE_COLOR);
_backGroundBoxRenderer->updateShaders(positionTextureColor_vert, (isETC1)?etc1_frag:positionTextureColor_frag); _frontCrossRenderer->setProgramState(backend::ProgramType::POSITION_TEXTURE_COLOR);
isETC1 = _frontCrossRenderer->getTexture() && _frontCrossRenderer->getTexture()->getAlphaTextureName();
_frontCrossRenderer->updateShaders(positionTextureColor_vert, (isETC1)?etc1_frag:positionTextureColor_frag);
if (!_isBackgroundSelectedTextureLoaded) if (!_isBackgroundSelectedTextureLoaded)
{ {
@ -356,11 +350,9 @@ void AbstractCheckButton::onPressStateChangedToDisabled()
if (!_isBackgroundDisabledTextureLoaded if (!_isBackgroundDisabledTextureLoaded
|| !_isFrontCrossDisabledTextureLoaded) || !_isFrontCrossDisabledTextureLoaded)
{ {
auto isETC1 = _backGroundBoxRenderer->getTexture() && _backGroundBoxRenderer->getTexture()->getAlphaTextureName(); _backGroundBoxRenderer->setProgramState(backend::ProgramType::GRAY_SCALE);
_backGroundBoxRenderer->updateShaders(positionTextureColor_vert, (isETC1)?etc1Gray_frag:grayScale_frag);
isETC1 = _frontCrossRenderer->getTexture() && _frontCrossRenderer->getTexture()->getAlphaTextureName(); _frontCrossRenderer->setProgramState(backend::ProgramType::GRAY_SCALE);
_frontCrossRenderer->updateShaders(positionTextureColor_vert, (isETC1)?etc1Gray_frag:grayScale_frag);
} }
else else
{ {

View File

@ -35,6 +35,7 @@
#include "2d/CCDrawNode.h" #include "2d/CCDrawNode.h"
#include "2d/CCCamera.h" #include "2d/CCCamera.h"
#include "renderer/CCRenderer.h" #include "renderer/CCRenderer.h"
#include "renderer/backend/ProgramStateRegistry.h"
using namespace cocos2d; using namespace cocos2d;
using namespace cocos2d::ui; using namespace cocos2d::ui;
@ -304,14 +305,13 @@ void Scale9Sprite::setState(Scale9Sprite::State state)
{ {
if (_brightState != state) { if (_brightState != state) {
_brightState = state; _brightState = state;
auto isETC1 = getTexture() && getTexture()->getAlphaTextureName();
switch (state) switch (state)
{ {
case State::NORMAL: case State::NORMAL:
Sprite::updateShaders(positionTextureColor_vert, (isETC1)?etc1_frag:positionTextureColor_frag); Sprite::setProgramState(backend::ProgramType::POSITION_TEXTURE_COLOR);
break; break;
case State::GRAY: case State::GRAY:
Sprite::updateShaders(positionTextureColor_vert, (isETC1)?etc1Gray_frag:grayScale_frag); Sprite::setProgramState(backend::ProgramType::GRAY_SCALE);
default: default:
break; break;
} }

View File

@ -680,15 +680,13 @@ void Slider::onPressStateChangedToNormal()
_slidBallPressedRenderer->setVisible(false); _slidBallPressedRenderer->setVisible(false);
_slidBallDisabledRenderer->setVisible(false); _slidBallDisabledRenderer->setVisible(false);
auto isETC1 = _slidBallNormalRenderer->getTexture() && _slidBallNormalRenderer->getTexture()->getAlphaTextureName(); _slidBallNormalRenderer->setProgramState(backend::ProgramType::POSITION_TEXTURE_COLOR);
_slidBallNormalRenderer->updateShaders(positionTextureColor_vert, (isETC1)?etc1_frag:positionTextureColor_frag);
_slidBallNormalRenderer->setScale(_sliderBallNormalTextureScaleX, _sliderBallNormalTextureScaleY); _slidBallNormalRenderer->setScale(_sliderBallNormalTextureScaleX, _sliderBallNormalTextureScaleY);
} }
void Slider::onPressStateChangedToPressed() void Slider::onPressStateChangedToPressed()
{ {
auto isETC1 = _slidBallNormalRenderer->getTexture() && _slidBallNormalRenderer->getTexture()->getAlphaTextureName(); _slidBallNormalRenderer->setProgramState(backend::ProgramType::POSITION_TEXTURE_COLOR);
_slidBallNormalRenderer->updateShaders(positionTextureColor_vert, (isETC1)?etc1_frag:positionTextureColor_frag);
if (!_isSliderBallPressedTextureLoaded) if (!_isSliderBallPressedTextureLoaded)
{ {
@ -707,8 +705,7 @@ void Slider::onPressStateChangedToDisabled()
{ {
if (!_isSliderBallDisabledTexturedLoaded) if (!_isSliderBallDisabledTexturedLoaded)
{ {
auto isETC1 = _slidBallNormalRenderer->getTexture() && _slidBallNormalRenderer->getTexture()->getAlphaTextureName(); _slidBallNormalRenderer->setProgramState(backend::ProgramType::GRAY_SCALE);
_slidBallNormalRenderer->updateShaders(positionTextureColor_vert, (isETC1)?etc1Gray_frag:grayScale_frag);
_slidBallNormalRenderer->setVisible(true); _slidBallNormalRenderer->setVisible(true);
} }
else else