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

View File

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

View File

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

View File

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

View File

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

View File

@ -40,32 +40,6 @@ MotionStreak::MotionStreak()
{
_customCommand.setDrawType(CustomCommand::DrawType::ARRAY);
_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()
@ -236,9 +210,49 @@ void MotionStreak::setTexture(Texture2D *texture)
CC_SAFE_RETAIN(texture);
CC_SAFE_RELEASE(_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)
{
_blendFunc = blendFunc;
@ -398,7 +412,7 @@ void MotionStreak::draw(Renderer *renderer, const Mat4 &transform, uint32_t flag
renderer->addCommand(&_customCommand);
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);
Mat4 finalMat = projectionMat * transform;

View File

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

View File

@ -43,6 +43,7 @@ THE SOFTWARE.
#include "2d/CCComponent.h"
#include "renderer/CCMaterial.h"
#include "math/TransformUtils.h"
#include "renderer/backend/ProgramStateRegistry.h"
#if CC_NODE_RENDER_SUBPIXEL
@ -2181,6 +2182,20 @@ int Node::getAttachedNodeCount()
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)
{
if (_programState != programState)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -102,42 +102,45 @@ bool SpriteBatchNode::initWithTexture(Texture2D *tex, ssize_t capacity/* = DEFAU
_textureAtlas->initWithTexture(tex, capacity);
setProgramStateWithRegistry(backend::ProgramType::POSITION_TEXTURE_COLOR, tex);
updateProgramStateTexture(_textureAtlas->getTexture());
updateBlendFunc();
_children.reserve(capacity);
_descendants.reserve(capacity);
updateShaders(positionTextureColor_vert, positionTextureColor_frag);
return true;
}
void SpriteBatchNode::updateShaders(const std::string &vertexShader, const std::string &fragmentShader)
void SpriteBatchNode::setProgramState(backend::ProgramState* programState)
{
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);
_programState = programState;
CC_SAFE_RETAIN(programState);
}
pipelineDescriptor.programState = _programState;
_mvpMatrixLocaiton = pipelineDescriptor.programState->getUniformLocation("u_MVPMatrix");
_textureLocation = pipelineDescriptor.programState->getUniformLocation("u_texture");
CC_SAFE_RELEASE(program);
auto vertexLayout = _programState->getVertexLayout();
const auto& attributeInfo = _programState->getProgram()->getActiveAttributes();
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);
}
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);
}
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);
}
@ -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);
auto programState = _quadCommand.getPipelineDescriptor().programState;
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);
renderer->addCommand(&_quadCommand);
@ -681,6 +684,8 @@ Texture2D* SpriteBatchNode::getTexture() const
void SpriteBatchNode::setTexture(Texture2D *texture)
{
_textureAtlas->setTexture(texture);
updateProgramStateTexture(texture);
updateBlendFunc();
}

View File

@ -260,7 +260,7 @@ protected:
void swap(ssize_t oldIndex, ssize_t newIndex);
void updateBlendFunc();
virtual void updateShaders(const std::string& vertexShader, const std::string& fragmentShader);
void setProgramState(backend::ProgramState* programState) override;
TextureAtlas *_textureAtlas = nullptr;
BlendFunc _blendFunc;
@ -268,7 +268,6 @@ protected:
backend::UniformLocation _mvpMatrixLocaiton;
backend::UniformLocation _textureLocation;
backend::ProgramState* _programState = nullptr;
// all descendants: children, grand children, etc...
// 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");
float alphaFuncValue = alphaFuncVal.asFloat();
setProgramStateWithRegistry(backend::ProgramType::POSITION_TEXTURE_COLOR_ALPHA_TEST, nullptr);
auto& pipelineDescriptor = _quadCommand.getPipelineDescriptor();
auto& vertexShader = pipelineDescriptor.programState->getProgram()->getVertexShader();
updateShaders(vertexShader, positionTextureColorAlphaTest_frag);
auto alphaValueLocation = pipelineDescriptor.programState->getUniformLocation("u_alpha_value");
pipelineDescriptor.programState->setUniform(alphaValueLocation, &alphaFuncValue, sizeof(alphaFuncValue));
}

View File

@ -357,3 +357,7 @@ THE SOFTWARE.
#ifndef CC_STRIP_FPS
#define CC_STRIP_FPS 0
#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;
protected:
cocos2d::CustomCommand _customCommand;
cocos2d::backend::ProgramState* _programState = nullptr;
cocos2d::backend::UniformLocation _mvpLocation;
cocos2d::BlendFunc _blendFunc = cocos2d::BlendFunc::ALPHA_NON_PREMULTIPLIED;

View File

@ -30,7 +30,6 @@ THE SOFTWARE.
#include <string>
#include <ctype.h>
#include "base/CCData.h"
#include "base/ccConfig.h" // CC_USE_JPEG, CC_USE_WEBP
#include "platform/CCGL.h"
@ -481,6 +480,7 @@ bool Image::PNG_PREMULTIPLIED_ALPHA_ENABLED = true;
Image::Image()
: _data(nullptr)
, _dataLen(0)
, _offset(0)
, _width(0)
, _height(0)
, _unpack(false)
@ -512,7 +512,9 @@ bool Image::initWithImageFile(const std::string& path)
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;
@ -527,19 +529,21 @@ bool Image::initWithImageFileThreadSafe(const std::string& fullpath)
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;
}
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;
do
{
CC_BREAK_IF(! data || dataLen <= 0);
CC_BREAK_IF(!data || dataLen == 0);
unsigned char* unpackedData = nullptr;
ssize_t unpackedLen = 0;
@ -576,7 +580,7 @@ bool Image::initWithImageData(const unsigned char * data, ssize_t dataLen)
ret = initWithPVRData(unpackedData, unpackedLen);
break;
case Format::ETC:
ret = initWithETCData(unpackedData, unpackedLen);
ret = initWithETCData(unpackedData, unpackedLen, ownData);
break;
case Format::S3TC:
ret = initWithS3TCData(unpackedData, unpackedLen);
@ -1421,7 +1425,7 @@ bool Image::initWithPVRv3Data(const unsigned char * data, ssize_t dataLen)
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);
@ -1439,23 +1443,26 @@ bool Image::initWithETCData(const unsigned char * data, ssize_t dataLen)
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())
{
//old opengl version has no define for GL_ETC1_RGB8_OES, add macro to make compiler happy.
#if defined(GL_ETC1_RGB8_OES) || defined(CC_USE_METAL)
_pixelFormat = backend::PixelFormat::ETC;
_dataLen = dataLen - ETC_PKM_HEADER_SIZE;
_data = static_cast<unsigned char*>(malloc(_dataLen * sizeof(unsigned char)));
memcpy(_data, static_cast<const unsigned char*>(data) + ETC_PKM_HEADER_SIZE, _dataLen);
_data = data;
_dataLen = dataLen;
_offset = ETC_PKM_HEADER_SIZE;
return true;
#else
CC_UNUSED_PARAM(dataLen);
#endif
}
else
{
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
int bytePerPixel = 3;
unsigned int stride = _width * bytePerPixel;
@ -1470,12 +1477,16 @@ bool Image::initWithETCData(const unsigned char * data, ssize_t dataLen)
if (_data != nullptr)
{
free(_data);
_data = nullptr;
}
return false;
ret = false;
}
return true;
if (ownData) free((void*)data);
return ret;
}
if (ownData) free((void*)data);
return false;
}

View File

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

View File

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

View File

@ -137,7 +137,6 @@ Texture2D::Texture2D()
, _antialiasEnabled(true)
, _ninePatchInfo(nullptr)
, _valid(true)
, _alphaTexture(nullptr)
{
backend::TextureDescriptor textureDescriptor;
textureDescriptor.textureFormat = PixelFormat::NONE;
@ -149,8 +148,6 @@ Texture2D::~Texture2D()
#if CC_ENABLE_CACHE_TEXTURE_DATA
VolatileTextureMgr::removeTexture(this);
#endif
CC_SAFE_RELEASE_NULL(_alphaTexture); // ETC1 ALPHA support.
CCLOGINFO("deallocing Texture2D: %p - id=%u", this, _name);
CC_SAFE_DELETE(_ninePatchInfo);
@ -179,11 +176,6 @@ backend::TextureBackend* Texture2D::getBackendTexture() const
return _texture;
}
bool Texture2D::getAlphaTextureName() const
{
return _alphaTexture == nullptr ? 0 : _alphaTexture->getBackendTexture();
}
Size Texture2D::getContentSize() const
{
Size ret;
@ -237,135 +229,12 @@ 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)
{
//the pixelFormat must be a certain value
CCASSERT(pixelFormat != PixelFormat::NONE && pixelFormat != PixelFormat::AUTO, "the \"pixelFormat\" param must be a certain value!");
CCASSERT(pixelsWide > 0 && pixelsHigh > 0, "Invalid size");
if (mipmapsNum <= 0)
{
CCLOG("cocos2d: WARNING: mipmap number is less than 1");
return false;
}
auto formatItr = _pixelFormatInfoTables.find(pixelFormat);
if (formatItr == _pixelFormatInfoTables.end())
{
CCLOG("cocos2d: WARNING: unsupported pixelformat: %lx", (unsigned long)pixelFormat);
#ifdef CC_USE_METAL
CCASSERT(false, "pixeformat not found in _pixelFormatInfoTables, register required!");
#endif
return false;
}
const PixelFormatInfo& info = formatItr->second;
if (info.compressed && !Configuration::getInstance()->supportsPVRTC()
&& !Configuration::getInstance()->supportsETC()
&& !Configuration::getInstance()->supportsS3TC()
&& !Configuration::getInstance()->supportsATITC())
{
CCLOG("cocos2d: WARNING: PVRTC/ETC images are not supported");
return false;
}
#if CC_ENABLE_CACHE_TEXTURE_DATA
VolatileTextureMgr::findVolotileTexture(this);
#endif
backend::TextureDescriptor textureDescriptor;
textureDescriptor.width = pixelsWide;
textureDescriptor.height = pixelsHigh;
textureDescriptor.samplerDescriptor.magFilter = (_antialiasEnabled) ? backend::SamplerFilter::LINEAR : backend::SamplerFilter::NEAREST;
if (mipmapsNum == 1)
{
textureDescriptor.samplerDescriptor.minFilter = (_antialiasEnabled) ? backend::SamplerFilter::LINEAR : backend::SamplerFilter::NEAREST;
}
else
{
textureDescriptor.samplerDescriptor.minFilter = (_antialiasEnabled) ? backend::SamplerFilter::LINEAR_MIPMAP_NEAREST : backend::SamplerFilter::NEAREST_MIPMAP_NEAREST;
}
int width = pixelsWide;
int height = pixelsHigh;
backend::PixelFormat oriPixelFormat = pixelFormat;
for (int i = 0; i < mipmapsNum; ++i)
{
unsigned char *data = mipmaps[i].address;
size_t dataLen = mipmaps[i].len;
unsigned char *outData = data;
size_t outDataLen = dataLen;
if(renderFormat != oriPixelFormat && !info.compressed) //need conversion
{
auto convertedFormat = backend::PixelFormatUtils::convertDataToFormat(data, dataLen, oriPixelFormat, renderFormat, &outData, &outDataLen);
#ifdef CC_USE_METAL
CCASSERT(convertedFormat == renderFormat, "PixelFormat convert failed!");
#endif
if(convertedFormat == renderFormat) pixelFormat = renderFormat;
}
textureDescriptor.textureFormat = pixelFormat;
CCASSERT(textureDescriptor.textureFormat != backend::PixelFormat::NONE, "PixelFormat should not be NONE");
if(_texture->getTextureFormat() != textureDescriptor.textureFormat)
_texture->updateTextureDescriptor(textureDescriptor);
if(info.compressed)
{
_texture->updateCompressedData(data, width, height, dataLen, i);
}
else
{
_texture->updateData(outData, width, height, i);
}
if(outData && outData != data && outDataLen > 0)
{
free(outData);
outData = nullptr;
outDataLen = 0;
}
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);
}
width = MAX(width >> 1, 1);
height = MAX(height >> 1, 1);
}
_contentSize = Size((float)pixelsWide, (float)pixelsHigh);
_pixelsWide = pixelsWide;
_pixelsHigh = pixelsHigh;
_pixelFormat = pixelFormat;
_maxS = 1;
_maxT = 1;
_hasPremultipliedAlpha = preMultipliedAlpha;
_hasMipmaps = mipmapsNum > 1;
updateWithMipmaps(mipmaps, mipmapsNum, pixelFormat, renderFormat, pixelsWide, pixelsHigh, preMultipliedAlpha);
return true;
}
bool Texture2D::updateWithData(void *data,int offsetX,int offsetY,int width,int height)
{
if (_texture && width > 0 && height > 0)
{
uint8_t* textureData = static_cast<uint8_t*>(data);
_texture->updateSubData(offsetX, offsetY, width, height, 0, textureData);
return true;
}
return false;
}
// implementation Texture2D (Image)
bool Texture2D::initWithImage(Image *image)
{
return initWithImage(image, g_defaultAlphaPixelFormat);
}
bool Texture2D::initWithImage(Image *image, backend::PixelFormat format)
bool Texture2D::updateWithImage(Image* image, backend::PixelFormat format, int index)
{
if (image == nullptr)
{
@ -373,10 +242,12 @@ bool Texture2D::initWithImage(Image *image, backend::PixelFormat format)
return false;
}
if(this->_filePath.empty()) this->_filePath = image->getFilePath();
int imageWidth = image->getWidth();
int imageHeight = image->getHeight();
this->_filePath = image->getFilePath();
Configuration *conf = Configuration::getInstance();
Configuration* conf = Configuration::getInstance();
int maxTextureSize = conf->getMaxTextureSize();
if (imageWidth > maxTextureSize || imageHeight > maxTextureSize)
@ -442,7 +313,7 @@ bool Texture2D::initWithImage(Image *image, backend::PixelFormat 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());
updateWithMipmaps(image->getMipmaps(), image->getNumberOfMipmaps(), image->getPixelFormat(), renderFormat, imageWidth, imageHeight, image->hasPremultipliedAlpha(), index);
return true;
}
@ -453,19 +324,174 @@ bool Texture2D::initWithImage(Image *image, backend::PixelFormat format)
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());
updateWithData(tempData, tempDataLen, image->getPixelFormat(), image->getPixelFormat(), imageWidth, imageHeight, imageSize, image->hasPremultipliedAlpha(), index);
return true;
}
else
{
//after conversion, renderFormat == pixelFormat of data
initWithData(tempData, tempDataLen, imagePixelFormat, renderFormat, imageWidth, imageHeight, imageSize, image->hasPremultipliedAlpha());
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
CCASSERT(pixelFormat != PixelFormat::NONE && pixelFormat != PixelFormat::AUTO, "the \"pixelFormat\" param must be a certain value!");
CCASSERT(pixelsWide > 0 && pixelsHigh > 0, "Invalid size");
if (mipmapsNum <= 0)
{
CCLOG("cocos2d: WARNING: mipmap number is less than 1");
return false;
}
auto formatItr = _pixelFormatInfoTables.find(pixelFormat);
if (formatItr == _pixelFormatInfoTables.end())
{
CCLOG("cocos2d: WARNING: unsupported pixelformat: %lx", (unsigned long)pixelFormat);
#ifdef CC_USE_METAL
CCASSERT(false, "pixeformat not found in _pixelFormatInfoTables, register required!");
#endif
return false;
}
const PixelFormatInfo& info = formatItr->second;
if (info.compressed && !Configuration::getInstance()->supportsPVRTC()
&& !Configuration::getInstance()->supportsETC()
&& !Configuration::getInstance()->supportsS3TC()
&& !Configuration::getInstance()->supportsATITC())
{
CCLOG("cocos2d: WARNING: PVRTC/ETC images are not supported");
return false;
}
#if CC_ENABLE_CACHE_TEXTURE_DATA
VolatileTextureMgr::findVolotileTexture(this);
#endif
backend::TextureDescriptor textureDescriptor;
textureDescriptor.width = pixelsWide;
textureDescriptor.height = pixelsHigh;
textureDescriptor.samplerDescriptor.magFilter = (_antialiasEnabled) ? backend::SamplerFilter::LINEAR : backend::SamplerFilter::NEAREST;
if (mipmapsNum == 1)
{
textureDescriptor.samplerDescriptor.minFilter = (_antialiasEnabled) ? backend::SamplerFilter::LINEAR : backend::SamplerFilter::NEAREST;
}
else
{
textureDescriptor.samplerDescriptor.minFilter = (_antialiasEnabled) ? backend::SamplerFilter::LINEAR_MIPMAP_NEAREST : backend::SamplerFilter::NEAREST_MIPMAP_NEAREST;
}
int width = pixelsWide;
int height = pixelsHigh;
backend::PixelFormat oriPixelFormat = pixelFormat;
for (int i = 0; i < mipmapsNum; ++i)
{
unsigned char* data = mipmaps[i].address;
size_t dataLen = mipmaps[i].len;
unsigned char* outData = data;
size_t outDataLen = dataLen;
if (renderFormat != oriPixelFormat && !info.compressed) //need conversion
{
auto convertedFormat = backend::PixelFormatUtils::convertDataToFormat(data, dataLen, oriPixelFormat, renderFormat, &outData, &outDataLen);
#ifdef CC_USE_METAL
CCASSERT(convertedFormat == renderFormat, "PixelFormat convert failed!");
#endif
if (convertedFormat == renderFormat) pixelFormat = renderFormat;
}
textureDescriptor.textureFormat = pixelFormat;
CCASSERT(textureDescriptor.textureFormat != backend::PixelFormat::NONE, "PixelFormat should not be NONE");
if (_texture->getTextureFormat() != textureDescriptor.textureFormat)
_texture->updateTextureDescriptor(textureDescriptor, index);
if (info.compressed)
{
_texture->updateCompressedData(data, width, height, dataLen, i);
}
else
{
_texture->updateData(outData, width, height, i, index);
}
if (outData && outData != data && outDataLen > 0)
{
free(outData);
outData = nullptr;
outDataLen = 0;
}
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);
}
width = MAX(width >> 1, 1);
height = MAX(height >> 1, 1);
}
if (index == 0) {
_contentSize = Size((float)pixelsWide, (float)pixelsHigh);
_pixelsWide = pixelsWide;
_pixelsHigh = pixelsHigh;
_pixelFormat = pixelFormat;
_maxS = 1;
_maxT = 1;
_hasPremultipliedAlpha = preMultipliedAlpha;
_hasMipmaps = mipmapsNum > 1;
}
}
bool Texture2D::updateWithSubData(void *data,int offsetX,int offsetY,int width,int height, int index)
{
if (_texture && width > 0 && height > 0)
{
uint8_t* textureData = static_cast<uint8_t*>(data);
_texture->updateSubData(offsetX, offsetY, width, height, 0, textureData, index);
return true;
}
return false;
}
// implementation Texture2D (Image)
bool Texture2D::initWithImage(Image *image)
{
return initWithImage(image, g_defaultAlphaPixelFormat);
}
bool Texture2D::initWithImage(Image *image, backend::PixelFormat format)
{
if (image == nullptr)
{
CCLOG("cocos2d: Texture2D. Can't create Texture. UIImage is nil");
return false;
}
this->_filePath = image->getFilePath();
return updateWithImage(image, format);
}
// implementation Texture2D (Text)
bool Texture2D::initWithString(const char *text, const std::string& fontName, float fontSize, const Size& dimensions/* = Size(0, 0)*/, TextHAlignment hAlignment/* = TextHAlignment::CENTER */, TextVAlignment vAlignment/* = TextVAlignment::TOP */, bool enableWrap /* = false */, int overflow /* = 0 */)
{
@ -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)
{
_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);
/** 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.
@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 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.
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; }
void setAlphaTexture(Texture2D* alphaTexture);
Texture2D* getAlphaTexture() const;
bool getAlphaTextureName() const;
public:
/** Get pixel info map, the key-value pairs is PixelFormat and PixelFormatInfo.*/
static const PixelFormatInfoMap& getPixelFormatInfoMap();
@ -409,7 +416,6 @@ protected:
bool _valid;
std::string _filePath;
Texture2D* _alphaTexture;
backend::ProgramState* _programState = nullptr;
backend::UniformLocation _mvpMatrixLocation;
backend::UniformLocation _textureLocation;

View File

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

View File

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

View File

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

View File

@ -29,20 +29,6 @@
#include "base/ccMacros.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
namespace
@ -126,6 +112,16 @@ bool ProgramCache::init()
addProgram(ProgramType::TERRAIN_3D);
addProgram(ProgramType::PARTICLE_TEXTURE_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;
}
@ -298,6 +294,7 @@ void ProgramCache::removeUnusedProgram()
void ProgramCache::removeAllPrograms()
{
ProgramStateRegistry::getInstance()->clearPrograms();
for (auto& program : _cachedPrograms)
{
program.second->release();

View File

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

View File

@ -381,6 +381,14 @@ void ProgramState::setFragmentUniform(int location, const void* data, std::size_
#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)
{
switch (uniformLocation.shaderStage)

View File

@ -142,6 +142,14 @@ public:
*/
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.
* @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()
{}
void TextureBackend::updateTextureDescriptor(const cocos2d::backend::TextureDescriptor &descriptor)
void TextureBackend::updateTextureDescriptor(const cocos2d::backend::TextureDescriptor &descriptor, int /*index*/)
{
_bitsPerElement = computeBitsPerElement(descriptor.textureFormat);
_textureType = descriptor.textureType;

View File

@ -60,7 +60,7 @@ public:
* Update sampler
* @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
@ -78,7 +78,7 @@ public:
* Update texture description.
* @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.
@ -104,6 +104,8 @@ public:
*/
inline bool hasMipmaps() const { return _hasMipmaps; }
virtual int getCount() const = 0;
protected:
/**
* @param descriptor Specifies the texture descirptor.
@ -136,7 +138,7 @@ public:
* @param height Specifies the height of the texture image.
* @param level Specifies the level-of-detail number. Level 0 is the base image level. Level n is the nth mipmap reduction image.
*/
virtual void updateData(uint8_t* data, std::size_t width , std::size_t height, std::size_t level) = 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
@ -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 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

View File

@ -77,14 +77,14 @@ void TextureInfoGL::applySamplerDescriptor(const SamplerDescriptor& descriptor,
Texture2DGL::Texture2DGL(const TextureDescriptor& descriptor) : Texture2DBackend(descriptor)
{
glGenTextures(1, &_textureInfo.texture);
glGenTextures(1, &_textureInfo.textures[0]);
updateTextureDescriptor(descriptor);
#if CC_ENABLE_CACHE_TEXTURE_DATA
// Listen this event to restored texture id after coming to foreground on Android.
_backToForegroundListener = EventListenerCustom::create(EVENT_RENDERER_RECREATED, [this](EventCustom*){
glGenTextures(1, &(this->_textureInfo.texture));
glGenTextures(1, &(this->_textureInfo.textures[0]));
this->initWithZeros();
});
Director::getInstance()->getEventDispatcher()->addEventListenerWithFixedPriority(_backToForegroundListener, -1);
@ -100,9 +100,9 @@ void Texture2DGL::initWithZeros()
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);
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.tAddressModeGL = UtilsGL::toGLAddressMode(descriptor.samplerDescriptor.tAddressMode, isPow2);
updateSamplerDescriptor(descriptor.samplerDescriptor);
updateSamplerDescriptor(descriptor.samplerDescriptor, index);
// Update data here because `updateData()` may not be invoked later.
// 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()
{
if (_textureInfo.texture)
glDeleteTextures(1, &_textureInfo.texture);
_textureInfo.texture = 0;
_textureInfo.foreach([=](GLuint texID, int) { glDeleteTextures(1, &texID); });
_textureInfo.textures.fill(0);
#if CC_ENABLE_CACHE_TEXTURE_DATA
Director::getInstance()->getEventDispatcher()->removeEventListener(_backToForegroundListener);
#endif
}
void Texture2DGL::updateSamplerDescriptor(const SamplerDescriptor &sampler) {
void Texture2DGL::updateSamplerDescriptor(const SamplerDescriptor &sampler, int index) {
bool isPow2 = ISPOW2(_width) && ISPOW2(_height);
_textureInfo.applySamplerDescriptor(sampler, isPow2, _hasMipmaps);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, _textureInfo.texture);
ensure(index);
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
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);
}
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, _textureInfo.texture);
auto texID = ensure(index);
if (!texID) return;
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_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.type,
data);
cocos2d::log("---> Texture2DGL::updateData:%u", texID);
CHECK_GL_ERROR_DEBUG();
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);
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_MIN_FILTER, _textureInfo.minFilterGL);
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;
}
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);
glBindTexture(GL_TEXTURE_2D, _textureInfo.texture);
if (!ensure(index)) return;
glTexSubImage2D(GL_TEXTURE_2D,
level,
@ -262,7 +262,7 @@ void Texture2DGL::updateCompressedSubData(std::size_t xoffset, std::size_t yoffs
uint8_t *data)
{
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, _textureInfo.texture);
glBindTexture(GL_TEXTURE_2D, _textureInfo.textures[0]);
glCompressedTexSubImage2D(GL_TEXTURE_2D,
level,
@ -282,7 +282,21 @@ void Texture2DGL::updateCompressedSubData(std::size_t xoffset, std::size_t yoffs
void Texture2DGL::apply(int index) const
{
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()
@ -293,7 +307,7 @@ void Texture2DGL::generateMipmaps()
if(!_hasMipmaps)
{
_hasMipmaps = true;
glBindTexture(GL_TEXTURE_2D, _textureInfo.texture);
glBindTexture(GL_TEXTURE_2D, _textureInfo.textures[0]);
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;
glGenFramebuffers(1, &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);
auto bytePerRow = width * _bitsPerElement / 8;
@ -340,7 +354,7 @@ TextureCubeGL::TextureCubeGL(const TextureDescriptor& descriptor)
assert(_width == _height);
_textureType = TextureType::TEXTURE_CUBE;
UtilsGL::toGLTypes(_textureFormat, _textureInfo.internalFormat, _textureInfo.format, _textureInfo.type, _isCompressed);
glGenTextures(1, &_textureInfo.texture);
glGenTextures(1, &_textureInfo.textures[0]);
updateSamplerDescriptor(descriptor.samplerDescriptor);
#if CC_ENABLE_CACHE_TEXTURE_DATA
@ -357,7 +371,7 @@ TextureCubeGL::TextureCubeGL(const TextureDescriptor& descriptor)
void TextureCubeGL::setTexParameters()
{
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_MAG_FILTER, _textureInfo.magFilterGL);
@ -367,41 +381,40 @@ void TextureCubeGL::setTexParameters()
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);
_textureFormat = descriptor.textureFormat;
updateSamplerDescriptor(descriptor.samplerDescriptor);
updateSamplerDescriptor(descriptor.samplerDescriptor, index);
}
TextureCubeGL::~TextureCubeGL()
{
if(_textureInfo.texture)
glDeleteTextures(1, &_textureInfo.texture);
_textureInfo.texture = 0;
_textureInfo.foreach([=](GLuint texID, int) { glDeleteTextures(1, &texID); });
_textureInfo.textures.fill(0);
#if CC_ENABLE_CACHE_TEXTURE_DATA
Director::getInstance()->getEventDispatcher()->removeEventListener(_backToForegroundListener);
#endif
}
void TextureCubeGL::updateSamplerDescriptor(const SamplerDescriptor &sampler)
void TextureCubeGL::updateSamplerDescriptor(const SamplerDescriptor &sampler, int /*index*/)
{
_textureInfo.applySamplerDescriptor(sampler, true, _hasMipmaps);
setTexParameters();
}
void TextureCubeGL::apply(int index) const
void TextureCubeGL::apply(int location) const
{
glActiveTexture(GL_TEXTURE0+ index);
glBindTexture(GL_TEXTURE_CUBE_MAP, _textureInfo.texture);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_CUBE_MAP, _textureInfo.textures[0]);
CHECK_GL_ERROR_DEBUG();
}
void TextureCubeGL::updateFaceData(TextureCubeFace side, void *data)
{
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_CUBE_MAP, _textureInfo.texture);
glBindTexture(GL_TEXTURE_CUBE_MAP, _textureInfo.textures[0]);
CHECK_GL_ERROR_DEBUG();
int i = static_cast<int>(side);
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;
glGenFramebuffers(1, &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);
auto bytePerRow = width * _bitsPerElement / 8;
@ -461,7 +474,7 @@ void TextureCubeGL::generateMipmaps()
if(!_hasMipmaps)
{
_hasMipmaps = true;
glBindTexture(GL_TEXTURE_CUBE_MAP, _textureInfo.texture);
glBindTexture(GL_TEXTURE_CUBE_MAP, _textureInfo.textures[0]);
glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
}
}

View File

@ -24,6 +24,7 @@
#pragma once
#include <array>
#include "../Texture.h"
#include "platform/CCGL.h"
#include "base/CCEventListenerCustom.h"
@ -36,6 +37,17 @@ CC_BACKEND_BEGIN
struct TextureInfoGL
{
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 minFilterGL = GL_LINEAR;
@ -47,7 +59,7 @@ struct TextureInfoGL
GLenum format = GL_RGBA;
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 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
@ -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 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
@ -113,7 +125,7 @@ public:
* Update sampler
* @param sampler Specifies the sampler descriptor.
*/
virtual void updateSamplerDescriptor(const SamplerDescriptor &sampler) override;
virtual void updateSamplerDescriptor(const SamplerDescriptor &sampler, int index = 0) override;
/**
* Read a block of pixels from the drawable texture
@ -133,13 +145,13 @@ public:
* Update texture description.
* @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.
* @return Texture object.
*/
inline GLuint getHandler() const { return _textureInfo.texture; }
inline GLuint getHandler() const { return _textureInfo.textures[0]; }
/**
* Set texture to pipeline
@ -147,10 +159,15 @@ public:
*/
void apply(int index) const;
GLuint ensure(int index);
int getCount() const override { return _maxTextureIndex + 1; }
private:
void initWithZeros();
TextureInfoGL _textureInfo;
int _maxTextureIndex = 0;
EventListener* _backToForegroundListener = nullptr;
};
@ -170,7 +187,7 @@ public:
* Update sampler
* @param sampler Specifies the sampler descriptor.
*/
virtual void updateSamplerDescriptor(const SamplerDescriptor &sampler) override;
virtual void updateSamplerDescriptor(const SamplerDescriptor &sampler, int index = 0) override;
/**
* Update texutre cube data in give slice side.
@ -195,19 +212,21 @@ public:
* Update texture description.
* @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.
* @return Texture object.
*/
inline GLuint getHandler() const { return _textureInfo.texture; }
inline GLuint getHandler() const { return _textureInfo.textures[0]; }
/**
* Set texture to pipeline
* @param index Specifies the texture image unit selector.
*/
void apply(int index) const;
void apply(int location) const;
int getCount() const { return 1; }
private:
void setTexParameters();

View File

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

View File

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

View File

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