mirror of https://github.com/axmolengine/axmol.git
parent
f6d51583a8
commit
5a32bcfdaf
|
@ -34,6 +34,7 @@ THE SOFTWARE.
|
|||
#include "renderer/ccShaders.h"
|
||||
#include "renderer/backend/ProgramState.h"
|
||||
#include "renderer/backend/Device.h"
|
||||
#include "renderer/backend/RenderTarget.h"
|
||||
#include "2d/CCCamera.h"
|
||||
|
||||
|
||||
|
@ -154,6 +155,8 @@ GridBase::~GridBase()
|
|||
{
|
||||
CCLOGINFO("deallocing GridBase: %p", this);
|
||||
|
||||
CC_SAFE_RELEASE(_renderTarget);
|
||||
|
||||
//TODO: ? why 2.0 comments this line: setActive(false);
|
||||
CC_SAFE_RELEASE(_texture);
|
||||
|
||||
|
@ -216,16 +219,13 @@ void GridBase::beforeDraw()
|
|||
Size size = director->getWinSizeInPixels();
|
||||
renderer->setViewPort(0, 0, (unsigned int)size.width, (unsigned int)size.height);
|
||||
|
||||
RenderTargetFlag flags = RenderTargetFlag::COLOR;
|
||||
_oldColorAttachment = renderer->getColorAttachment();
|
||||
_oldDepthAttachment = renderer->getDepthAttachment();
|
||||
_oldStencilAttachment = renderer->getStencilAttachment();
|
||||
_oldRenderTargetFlag = renderer->getRenderTargetFlag();
|
||||
|
||||
renderer->setRenderTarget(flags, _texture, nullptr, nullptr);
|
||||
_oldRenderTarget = renderer->getRenderTarget();
|
||||
CC_SAFE_RELEASE(_renderTarget);
|
||||
_renderTarget = backend::Device::getInstance()->newRenderTarget(TargetBufferFlags::COLOR, _texture->getBackendTexture());
|
||||
renderer->setRenderTarget(_renderTarget);
|
||||
renderer->clear(TargetBufferFlags::COLOR, _clearColor, 1, 0, 0.0);
|
||||
};
|
||||
renderer->addCommand(&_beforeDrawCommand);
|
||||
renderer->clear(ClearFlag::COLOR, _clearColor, 1, 0, 0.0);
|
||||
}
|
||||
|
||||
void GridBase::afterDraw(cocos2d::Node * /*target*/)
|
||||
|
@ -238,7 +238,7 @@ void GridBase::afterDraw(cocos2d::Node * /*target*/)
|
|||
director->setProjection(_directorProjection);
|
||||
const auto& vp = Camera::getDefaultViewport();
|
||||
renderer->setViewPort(vp.x, vp.y, vp.w, vp.h);
|
||||
renderer->setRenderTarget(_oldRenderTargetFlag, _oldColorAttachment, _oldDepthAttachment, _oldStencilAttachment);
|
||||
renderer->setRenderTarget(_oldRenderTarget);
|
||||
};
|
||||
renderer->addCommand(&_afterDrawCommand);
|
||||
|
||||
|
|
|
@ -40,6 +40,11 @@ class Texture2D;
|
|||
// class GLProgram;
|
||||
class Node;
|
||||
|
||||
namespace backend
|
||||
{
|
||||
class RenderTarget;
|
||||
}
|
||||
|
||||
/**
|
||||
* @addtogroup _2d
|
||||
* @{
|
||||
|
@ -153,10 +158,10 @@ protected:
|
|||
CallbackCommand _afterDrawCommand;
|
||||
CallbackCommand _beforeBlitCommand;
|
||||
CallbackCommand _afterBlitCommand;
|
||||
RenderTargetFlag _oldRenderTargetFlag;
|
||||
Texture2D* _oldColorAttachment = nullptr;
|
||||
Texture2D* _oldDepthAttachment = nullptr;
|
||||
Texture2D* _oldStencilAttachment = nullptr;
|
||||
|
||||
// New
|
||||
backend::RenderTarget* _oldRenderTarget = nullptr;
|
||||
backend::RenderTarget* _renderTarget = nullptr;
|
||||
|
||||
backend::UniformLocation _mvpMatrixLocation;
|
||||
backend::UniformLocation _textureLocation;
|
||||
|
|
|
@ -38,6 +38,7 @@ THE SOFTWARE.
|
|||
#include "renderer/CCTextureCache.h"
|
||||
#include "renderer/backend/Device.h"
|
||||
#include "renderer/backend/Texture.h"
|
||||
#include "renderer/backend/RenderTarget.h"
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
|
@ -57,6 +58,7 @@ RenderTexture::RenderTexture()
|
|||
|
||||
RenderTexture::~RenderTexture()
|
||||
{
|
||||
CC_SAFE_RELEASE(_renderTarget);
|
||||
CC_SAFE_RELEASE(_sprite);
|
||||
CC_SAFE_RELEASE(_texture2DCopy);
|
||||
CC_SAFE_RELEASE(_depthStencilTexture);
|
||||
|
@ -207,8 +209,6 @@ bool RenderTexture::initWithWidthAndHeight(int w, int h, backend::PixelFormat fo
|
|||
|
||||
_renderTargetFlags = RenderTargetFlag::COLOR;
|
||||
|
||||
clearColorAttachment();
|
||||
|
||||
if (PixelFormat::D24S8 == depthStencilFormat)
|
||||
{
|
||||
_renderTargetFlags = RenderTargetFlag::ALL;
|
||||
|
@ -228,6 +228,14 @@ bool RenderTexture::initWithWidthAndHeight(int w, int h, backend::PixelFormat fo
|
|||
texture->release();
|
||||
}
|
||||
|
||||
_renderTarget = backend::Device::getInstance()->newRenderTarget(_renderTargetFlags,
|
||||
_texture2D ? _texture2D->getBackendTexture() : nullptr,
|
||||
_depthStencilTexture ? _depthStencilTexture->getBackendTexture() : nullptr,
|
||||
_depthStencilTexture ? _depthStencilTexture->getBackendTexture() : nullptr
|
||||
);
|
||||
|
||||
clearColorAttachment();
|
||||
|
||||
_texture2D->setAntiAliasTexParameters();
|
||||
if (_texture2DCopy)
|
||||
{
|
||||
|
@ -477,7 +485,7 @@ void RenderTexture::newImage(std::function<void(RefPtr<Image>)> imageCallback, b
|
|||
int savedBufferHeight = (int)s.height;
|
||||
bool hasPremultipliedAlpha = _texture2D->hasPremultipliedAlpha();
|
||||
|
||||
_director->getRenderer()->readPixels(_texture2D->getBackendTexture(), [=](const backend::PixelBufferDescriptor& pbd) {
|
||||
_director->getRenderer()->readPixels(_renderTarget, [=](const backend::PixelBufferDescriptor& pbd) {
|
||||
if(pbd) {
|
||||
auto image = utils::makeInstance<Image>(&Image::initWithRawData, pbd._data.getBytes(), pbd._data.getSize(), pbd._width, pbd._height, 8, hasPremultipliedAlpha);
|
||||
imageCallback(image);
|
||||
|
@ -548,12 +556,8 @@ void RenderTexture::onBegin()
|
|||
_oldViewport = renderer->getViewport();
|
||||
renderer->setViewPort(viewport.origin.x, viewport.origin.y, viewport.size.width, viewport.size.height);
|
||||
|
||||
_oldColorAttachment = renderer->getColorAttachment();
|
||||
_oldDepthAttachment = renderer->getDepthAttachment();
|
||||
_oldStencilAttachment = renderer->getStencilAttachment();
|
||||
_oldRenderTargetFlag = renderer->getRenderTargetFlag();
|
||||
|
||||
renderer->setRenderTarget(_renderTargetFlags, _texture2D, _depthStencilTexture, _depthStencilTexture);
|
||||
_oldRenderTarget = renderer->getRenderTarget();
|
||||
renderer->setRenderTarget(_renderTarget);
|
||||
}
|
||||
|
||||
void RenderTexture::onEnd()
|
||||
|
@ -564,7 +568,8 @@ void RenderTexture::onEnd()
|
|||
|
||||
Renderer *renderer = Director::getInstance()->getRenderer();
|
||||
renderer->setViewPort(_oldViewport.x, _oldViewport.y, _oldViewport.w, _oldViewport.h);
|
||||
renderer->setRenderTarget(_oldRenderTargetFlag, _oldColorAttachment, _oldDepthAttachment, _oldStencilAttachment);
|
||||
|
||||
renderer->setRenderTarget(_oldRenderTarget);
|
||||
}
|
||||
|
||||
void RenderTexture::begin()
|
||||
|
@ -629,19 +634,10 @@ void RenderTexture::setClearFlags(ClearFlag clearFlags)
|
|||
void RenderTexture::clearColorAttachment()
|
||||
{
|
||||
auto renderer = _director->getRenderer();
|
||||
_beforeClearAttachmentCommand.func = [=]() -> void {
|
||||
_oldColorAttachment = renderer->getColorAttachment();
|
||||
renderer->setRenderTarget(RenderTargetFlag::COLOR, _texture2D, nullptr, nullptr);
|
||||
};
|
||||
renderer->addCommand(&_beforeClearAttachmentCommand);
|
||||
|
||||
Color4F color(0.f, 0.f, 0.f, 0.f);
|
||||
renderer->clear(ClearFlag::COLOR, color, 1, 0, _globalZOrder);
|
||||
|
||||
_afterClearAttachmentCommand.func = [=]() -> void {
|
||||
renderer->setRenderTarget(RenderTargetFlag::COLOR, _oldColorAttachment, nullptr, nullptr);
|
||||
};
|
||||
renderer->addCommand(&_afterClearAttachmentCommand);
|
||||
_oldRenderTarget = renderer->getRenderTarget();
|
||||
renderer->setRenderTarget(_renderTarget);
|
||||
renderer->clear(TargetBufferFlags::COLOR, Color4F{0.f, 0.f, 0.f, 0.f}, 1, 0, _globalZOrder);
|
||||
renderer->setRenderTarget(_oldRenderTarget);
|
||||
}
|
||||
|
||||
NS_CC_END
|
||||
|
|
|
@ -39,6 +39,7 @@ NS_CC_BEGIN
|
|||
namespace backend
|
||||
{
|
||||
class TextureBackend;
|
||||
class RenderTarget;
|
||||
}
|
||||
|
||||
class EventCustom;
|
||||
|
@ -358,11 +359,11 @@ protected:
|
|||
Texture2D* _texture2D = nullptr;
|
||||
Texture2D* _depthStencilTexture = nullptr;
|
||||
Texture2D* _texture2DCopy = nullptr; // a copy of _texture
|
||||
Texture2D* _oldColorAttachment = nullptr;
|
||||
Texture2D* _oldDepthAttachment = nullptr;
|
||||
Texture2D* _oldStencilAttachment = nullptr;
|
||||
RenderTargetFlag _renderTargetFlags;
|
||||
RenderTargetFlag _oldRenderTargetFlag;
|
||||
|
||||
backend::RenderTarget* _renderTarget = nullptr;
|
||||
backend::RenderTarget* _oldRenderTarget = nullptr;
|
||||
RenderTargetFlag _renderTargetFlags{};
|
||||
|
||||
Image* _UITextureImage = nullptr;
|
||||
backend::PixelFormat _pixelFormat = backend::PixelFormat::RGBA8888;
|
||||
|
||||
|
|
|
@ -388,13 +388,13 @@ void Director::setOpenGLView(GLView *openGLView)
|
|||
|
||||
_isStatusLabelUpdated = true;
|
||||
|
||||
_renderer->init();
|
||||
|
||||
if (_openGLView)
|
||||
{
|
||||
setGLDefaultValues();
|
||||
}
|
||||
|
||||
_renderer->init();
|
||||
|
||||
if (_eventDispatcher)
|
||||
{
|
||||
_eventDispatcher->setEnabled(true);
|
||||
|
|
|
@ -66,16 +66,11 @@ Copyright (c) 2020 c4games.com.
|
|||
return static_cast<_BITMASK>(~static_cast<_IntTy>(_Left)); \
|
||||
} \
|
||||
\
|
||||
constexpr bool _Bitmask_includes( \
|
||||
_BITMASK _Left, _BITMASK _Elements) noexcept { /* return (_Left & _Elements) != _BITMASK{} */ \
|
||||
return (_Left & _Elements) != _BITMASK{}; \
|
||||
} \
|
||||
\
|
||||
constexpr bool _Bitmask_includes_all( \
|
||||
_BITMASK _Left, _BITMASK _Elements) noexcept { /* return (_Left & _Elements) == _Elements */ \
|
||||
return (_Left & _Elements) == _Elements; \
|
||||
constexpr bool operator!(_BITMASK _Left) noexcept { /* return ~_Left */ \
|
||||
using _IntTy = _STD underlying_type<_BITMASK>::type; \
|
||||
return !static_cast<_IntTy>(_Left); \
|
||||
}
|
||||
|
||||
|
||||
// BITSHIFT OPERATIONS, inspired from msvc++ <type_traits>.
|
||||
#define CC_ENABLE_BITSHIFT_OPS(_BITMASK) \
|
||||
constexpr _BITMASK operator>>(_BITMASK _Left, _BITMASK _Right) noexcept { /* return _Left & _Right */ \
|
||||
|
@ -87,3 +82,20 @@ Copyright (c) 2020 c4games.com.
|
|||
using _IntTy = _STD underlying_type<_BITMASK>::type; \
|
||||
return static_cast<_BITMASK>(static_cast<_IntTy>(_Left) << static_cast<_IntTy>(_Right)); \
|
||||
}
|
||||
|
||||
namespace bitmask {
|
||||
template<typename _BITMASK>
|
||||
constexpr bool none(_BITMASK _Left, _BITMASK _Elements) noexcept {
|
||||
return !(_Left & _Elements);
|
||||
}
|
||||
|
||||
template<typename _BITMASK>
|
||||
constexpr bool any(_BITMASK _Left, _BITMASK _Elements) noexcept {
|
||||
return !!(_Left & _Elements);
|
||||
}
|
||||
|
||||
template<typename _BITMASK>
|
||||
constexpr bool only(_BITMASK _Left, _BITMASK _Elements) noexcept {
|
||||
return (_Left & _Elements) == _Elements;
|
||||
}
|
||||
} // namespace bitmask
|
||||
|
|
|
@ -634,6 +634,7 @@ struct CC_DLL ScissorRect
|
|||
float height = 0;
|
||||
};
|
||||
|
||||
// TODO: Move to renderer/backend/Types.h
|
||||
struct TextureFormatEXT
|
||||
{
|
||||
enum {
|
||||
|
@ -652,27 +653,13 @@ struct TextureFlag
|
|||
};
|
||||
};
|
||||
|
||||
enum class ClearFlag : uint8_t
|
||||
{
|
||||
NONE = 0,
|
||||
COLOR = 1,
|
||||
DEPTH = 1 << 1,
|
||||
STENCIL = 1 << 2,
|
||||
ALL = COLOR | DEPTH | STENCIL
|
||||
};
|
||||
CC_ENABLE_BITMASK_OPS(ClearFlag)
|
||||
|
||||
enum class RenderTargetFlag : uint8_t
|
||||
{
|
||||
COLOR = 1,
|
||||
DEPTH = 1 << 1,
|
||||
STENCIL = 1 << 2,
|
||||
ALL = COLOR | DEPTH | STENCIL
|
||||
};
|
||||
CC_ENABLE_BITMASK_OPS(RenderTargetFlag)
|
||||
using TextureUsage = backend::TextureUsage;
|
||||
using PixelFormat = backend::PixelFormat;
|
||||
|
||||
using TargetBufferFlags = backend::TargetBufferFlags;
|
||||
using RenderTargetFlag = backend::RenderTargetFlag;
|
||||
using ClearFlag = backend::ClearFlag;
|
||||
|
||||
NS_CC_END
|
||||
// end group
|
||||
/// @}
|
||||
|
|
|
@ -75,7 +75,6 @@ namespace utils
|
|||
* Capture screen interface
|
||||
*/
|
||||
static EventListenerCustom* s_captureScreenListener;
|
||||
static CallbackCommand s_captureScreenCommand;
|
||||
void captureScreen(std::function<void(RefPtr<Image>)> imageCallback)
|
||||
{
|
||||
if (s_captureScreenListener)
|
||||
|
@ -91,9 +90,8 @@ void captureScreen(std::function<void(RefPtr<Image>)> imageCallback)
|
|||
s_captureScreenListener = eventDispatcher->addCustomEventListener(Director::EVENT_AFTER_DRAW, [=](EventCustom* /*event*/) {
|
||||
eventDispatcher->removeEventListener(s_captureScreenListener);
|
||||
s_captureScreenListener = nullptr;
|
||||
|
||||
// !!!GL: AFTER_DRAW and BEFORE_END_FRAME
|
||||
renderer->readPixels(nullptr, [=](const backend::PixelBufferDescriptor& pbd) {
|
||||
renderer->readPixels(renderer->getDefaultRenderTarget(), [=](const backend::PixelBufferDescriptor& pbd) {
|
||||
if (pbd) {
|
||||
auto image = utils::makeInstance<Image>(&Image::initWithRawData, pbd._data.getBytes(), pbd._data.getSize(), pbd._width, pbd._height, 8, false);
|
||||
imageCallback(image);
|
||||
|
|
|
@ -33,6 +33,8 @@ THE SOFTWARE.
|
|||
#define glUnmapBuffer glUnmapBufferOES
|
||||
|
||||
#define GL_DEPTH24_STENCIL8 GL_DEPTH24_STENCIL8_OES
|
||||
#define GL_DEPTH_STENCIL GL_DEPTH_STENCIL_OES
|
||||
#define GL_UNSIGNED_INT_24_8 GL_UNSIGNED_INT_24_8_OES
|
||||
#define GL_WRITE_ONLY GL_WRITE_ONLY_OES
|
||||
|
||||
// GL_GLEXT_PROTOTYPES isn't defined in glplatform.h on android ndk r7
|
||||
|
|
|
@ -38,6 +38,8 @@ THE SOFTWARE.
|
|||
#define glUnmapBuffer glUnmapBufferOES
|
||||
|
||||
#define GL_DEPTH24_STENCIL8 GL_DEPTH24_STENCIL8_OES
|
||||
#define GL_DEPTH_STENCIL GL_DEPTH_STENCIL_OES
|
||||
#define GL_UNSIGNED_INT_24_8 GL_UNSIGNED_INT_24_8_OES
|
||||
#define GL_WRITE_ONLY GL_WRITE_ONLY_OES
|
||||
|
||||
#include <OpenGLES/ES2/gl.h>
|
||||
|
|
|
@ -32,6 +32,9 @@ THE SOFTWARE.
|
|||
#include "glad/glad.h"
|
||||
|
||||
#if defined(CC_USE_GLES)
|
||||
#undef GL_DEPTH_STENCIL
|
||||
#undef GL_DEPTH24_STENCIL8
|
||||
#undef GL_UNSIGNED_INT_24_8
|
||||
#undef glClearDepth
|
||||
#undef glMapBuffer
|
||||
#undef glUnmapBuffer
|
||||
|
@ -57,6 +60,9 @@ THE SOFTWARE.
|
|||
#undef glGenerateMipmap
|
||||
#endif
|
||||
|
||||
#define GL_DEPTH_STENCIL GL_DEPTH_STENCIL_OES
|
||||
#define GL_DEPTH24_STENCIL8 GL_DEPTH24_STENCIL8_OES
|
||||
#define GL_UNSIGNED_INT_24_8 GL_UNSIGNED_INT_24_8_OES
|
||||
#define glClearDepth glClearDepthf
|
||||
#define glMapBuffer glMapBufferOES
|
||||
#define glUnmapBuffer glUnmapBufferOES
|
||||
|
@ -84,6 +90,4 @@ THE SOFTWARE.
|
|||
|
||||
#endif
|
||||
|
||||
#define CC_GL_DEPTH24_STENCIL8 GL_DEPTH24_STENCIL8
|
||||
|
||||
#endif // CC_TARGET_PLATFORM == CC_PLATFORM_WIN32
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#include "renderer/backend/DepthStencilState.h"
|
||||
#include "renderer/backend/Texture.h"
|
||||
#include "renderer/backend/VertexLayout.h"
|
||||
#include "renderer/backend/RenderPassDescriptor.h"
|
||||
#include "renderer/backend/RenderPassParams.h"
|
||||
#include "renderer/backend/ProgramState.h"
|
||||
|
||||
#include <string>
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#include "xxhash.h"
|
||||
|
||||
#include "renderer/backend/Backend.h"
|
||||
#include "renderer/backend/RenderTarget.h"
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
|
@ -180,6 +181,7 @@ Renderer::~Renderer()
|
|||
|
||||
CC_SAFE_RELEASE(_commandBuffer);
|
||||
CC_SAFE_RELEASE(_renderPipeline);
|
||||
CC_SAFE_RELEASE(_defaultRT);
|
||||
}
|
||||
|
||||
void Renderer::init()
|
||||
|
@ -191,6 +193,9 @@ void Renderer::init()
|
|||
|
||||
auto device = backend::Device::getInstance();
|
||||
_commandBuffer = device->newCommandBuffer();
|
||||
// MTL: default render target flags should have DEPTH_AND_STENCIL make sure further clear could set pipeline state properly
|
||||
_defaultRT = device->newDefaultRenderTarget(TargetBufferFlags::COLOR | TargetBufferFlags::DEPTH_AND_STENCIL);
|
||||
_currentRT = _defaultRT;
|
||||
_renderPipeline = device->newRenderPipeline();
|
||||
_commandBuffer->setRenderPipeline(_renderPipeline);
|
||||
}
|
||||
|
@ -404,7 +409,8 @@ void Renderer::clean()
|
|||
void Renderer::setDepthTest(bool value)
|
||||
{
|
||||
_depthStencilDescriptor.depthTestEnabled = value;
|
||||
_renderPassDescriptor.depthTestEnabled = value;
|
||||
_currentRT->modifyTargetFlags(value ? TargetBufferFlags::DEPTH : TargetBufferFlags::NONE,
|
||||
value ? TargetBufferFlags::NONE : TargetBufferFlags::DEPTH);
|
||||
}
|
||||
|
||||
void Renderer::setDepthWrite(bool value)
|
||||
|
@ -435,7 +441,9 @@ bool Renderer::getDepthWrite() const
|
|||
void Renderer::setStencilTest(bool value)
|
||||
{
|
||||
_depthStencilDescriptor.stencilTestEnabled = value;
|
||||
_renderPassDescriptor.stencilTestEnabled = value;
|
||||
|
||||
_currentRT->modifyTargetFlags(value ? TargetBufferFlags::STENCIL : TargetBufferFlags::NONE,
|
||||
value ? TargetBufferFlags::NONE : TargetBufferFlags::STENCIL);
|
||||
}
|
||||
|
||||
void Renderer::setStencilCompareFunction(backend::CompareFunction func, unsigned int ref, unsigned int readMask)
|
||||
|
@ -615,24 +623,30 @@ void Renderer::drawBatchedTriangles()
|
|||
_vertexBuffer->updateData(_verts, _filledVertex * sizeof(_verts[0]));
|
||||
_indexBuffer->updateData(_indices, _filledIndex * sizeof(_indices[0]));
|
||||
#endif
|
||||
|
||||
|
||||
/************** 2: Draw *************/
|
||||
beginRenderPass();
|
||||
for (int i = 0; i < batchesTotal; ++i)
|
||||
{
|
||||
beginRenderPass(_triBatchesToDraw[i].cmd);
|
||||
|
||||
auto& drawInfo = _triBatchesToDraw[i];
|
||||
setRenderPipeline(drawInfo.cmd->getPipelineDescriptor(), _renderPassParams);
|
||||
_commandBuffer->setVertexBuffer(_vertexBuffer);
|
||||
_commandBuffer->setIndexBuffer(_indexBuffer);
|
||||
auto& pipelineDescriptor = _triBatchesToDraw[i].cmd->getPipelineDescriptor();
|
||||
auto& pipelineDescriptor = drawInfo.cmd->getPipelineDescriptor();
|
||||
_commandBuffer->setProgramState(pipelineDescriptor.programState);
|
||||
_commandBuffer->drawElements(backend::PrimitiveType::TRIANGLE,
|
||||
backend::IndexFormat::U_SHORT,
|
||||
_triBatchesToDraw[i].indicesToDraw,
|
||||
_triBatchesToDraw[i].offset * sizeof(_indices[0]));
|
||||
_commandBuffer->endRenderPass();
|
||||
drawInfo.indicesToDraw,
|
||||
drawInfo.offset * sizeof(_indices[0]));
|
||||
|
||||
|
||||
_drawnBatches++;
|
||||
_drawnVertices += _triBatchesToDraw[i].indicesToDraw;
|
||||
|
||||
}
|
||||
_commandBuffer->endRenderPass();
|
||||
|
||||
|
||||
/************** 3: Cleanup *************/
|
||||
_queuedTriangleCommands.clear();
|
||||
|
@ -649,7 +663,8 @@ void Renderer::drawCustomCommand(RenderCommand *command)
|
|||
|
||||
if (cmd->getBeforeCallback()) cmd->getBeforeCallback()();
|
||||
|
||||
beginRenderPass(command);
|
||||
beginRenderPass();
|
||||
setRenderPipeline(cmd->getPipelineDescriptor(), _renderPassParams);
|
||||
_commandBuffer->setVertexBuffer(cmd->getVertexBuffer());
|
||||
_commandBuffer->setProgramState(cmd->getPipelineDescriptor().programState);
|
||||
|
||||
|
@ -738,21 +753,24 @@ bool Renderer::checkVisibility(const Mat4 &transform, const Size &size)
|
|||
return ret;
|
||||
}
|
||||
|
||||
void Renderer::readPixels(backend::TextureBackend* texture, std::function<void(const backend::PixelBufferDescriptor&)> callback)
|
||||
void Renderer::readPixels(backend::RenderTarget* rt, std::function<void(const backend::PixelBufferDescriptor&)> callback)
|
||||
{
|
||||
if(!texture) // read pixels from screen, metal renderer backend: screen texture must not be a framebufferOnly
|
||||
assert(!!rt);
|
||||
if(rt == _defaultRT) // read pixels from screen, metal renderer backend: screen texture must not be a framebufferOnly
|
||||
backend::Device::getInstance()->setFrameBufferOnly(false);
|
||||
_commandBuffer->capture(texture, std::move(callback));
|
||||
|
||||
_commandBuffer->readPixels(rt, std::move(callback));
|
||||
}
|
||||
|
||||
void Renderer::setRenderPipeline(const PipelineDescriptor& pipelineDescriptor, const backend::RenderPassDescriptor& renderPassDescriptor)
|
||||
void Renderer::setRenderPipeline(const PipelineDescriptor& pipelineDescriptor, const backend::RenderPassParams& renderPassParams)
|
||||
{
|
||||
auto device = backend::Device::getInstance();
|
||||
_renderPipeline->update(pipelineDescriptor, renderPassDescriptor);
|
||||
_renderPipeline->update(pipelineDescriptor, _currentRT, renderPassParams);
|
||||
backend::DepthStencilState* depthStencilState = nullptr;
|
||||
auto needDepthStencilAttachment = renderPassDescriptor.depthTestEnabled || renderPassDescriptor.stencilTestEnabled;
|
||||
if (needDepthStencilAttachment)
|
||||
if (bitmask::any(_currentRT->getTargetFlags(), RenderTargetFlag::DEPTH_AND_STENCIL))
|
||||
{
|
||||
// FIXME: don't use autorelease at draw frame
|
||||
// Now the depthStencilState is in autoreleasepool
|
||||
depthStencilState = device->createDepthStencilState(_depthStencilDescriptor);
|
||||
}
|
||||
_commandBuffer->setDepthStencilState(depthStencilState);
|
||||
|
@ -761,125 +779,36 @@ void Renderer::setRenderPipeline(const PipelineDescriptor& pipelineDescriptor, c
|
|||
#endif
|
||||
}
|
||||
|
||||
void Renderer::beginRenderPass(RenderCommand* cmd)
|
||||
void Renderer::beginRenderPass()
|
||||
{
|
||||
_commandBuffer->beginRenderPass(_renderPassDescriptor);
|
||||
_commandBuffer->setViewport(_viewport.x, _viewport.y, _viewport.w, _viewport.h);
|
||||
_commandBuffer->setCullMode(_cullMode);
|
||||
_commandBuffer->setWinding(_winding);
|
||||
_commandBuffer->setScissorRect(_scissorState.isEnabled, _scissorState.rect.x, _scissorState.rect.y, _scissorState.rect.width, _scissorState.rect.height);
|
||||
setRenderPipeline(cmd->getPipelineDescriptor(), _renderPassDescriptor);
|
||||
|
||||
_commandBuffer->beginRenderPass(_currentRT, _renderPassParams);
|
||||
_commandBuffer->setViewport(_viewport.x, _viewport.y, _viewport.w, _viewport.h);
|
||||
_commandBuffer->setCullMode(_cullMode);
|
||||
_commandBuffer->setWinding(_winding);
|
||||
_commandBuffer->setScissorRect(_scissorState.isEnabled, _scissorState.rect.x, _scissorState.rect.y, _scissorState.rect.width, _scissorState.rect.height);
|
||||
_commandBuffer->setStencilReferenceValue(_stencilRef);
|
||||
}
|
||||
|
||||
void Renderer::setRenderTarget(RenderTargetFlag flags, Texture2D* colorAttachment, Texture2D* depthAttachment, Texture2D* stencilAttachment)
|
||||
{
|
||||
_renderTargetFlag = flags;
|
||||
if (_Bitmask_includes(RenderTargetFlag::COLOR, flags))
|
||||
{
|
||||
_renderPassDescriptor.needColorAttachment = true;
|
||||
if (colorAttachment)
|
||||
_renderPassDescriptor.colorAttachmentsTexture[0] = colorAttachment->getBackendTexture();
|
||||
else
|
||||
_renderPassDescriptor.colorAttachmentsTexture[0] = nullptr;
|
||||
|
||||
_colorAttachment = colorAttachment;
|
||||
}
|
||||
else
|
||||
{
|
||||
_colorAttachment = nullptr;
|
||||
_renderPassDescriptor.needColorAttachment = false;
|
||||
_renderPassDescriptor.colorAttachmentsTexture[0] = nullptr;
|
||||
}
|
||||
|
||||
if (_Bitmask_includes(RenderTargetFlag::DEPTH, flags))
|
||||
{
|
||||
_renderPassDescriptor.depthTestEnabled = true;
|
||||
if (depthAttachment)
|
||||
_renderPassDescriptor.depthAttachmentTexture = depthAttachment->getBackendTexture();
|
||||
else
|
||||
_renderPassDescriptor.depthAttachmentTexture = nullptr;
|
||||
|
||||
_depthAttachment = depthAttachment;
|
||||
}
|
||||
else
|
||||
{
|
||||
_renderPassDescriptor.depthTestEnabled = false;
|
||||
_renderPassDescriptor.depthAttachmentTexture = nullptr;
|
||||
_depthAttachment = nullptr;
|
||||
}
|
||||
|
||||
if (_Bitmask_includes(RenderTargetFlag::STENCIL, flags))
|
||||
{
|
||||
_stencilAttachment = stencilAttachment;
|
||||
_renderPassDescriptor.stencilTestEnabled = true;
|
||||
if (_stencilAttachment)
|
||||
_renderPassDescriptor.stencilAttachmentTexture = stencilAttachment->getBackendTexture();
|
||||
else
|
||||
_renderPassDescriptor.stencilAttachmentTexture = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
_stencilAttachment = nullptr;
|
||||
_renderPassDescriptor.stencilTestEnabled = false;
|
||||
_renderPassDescriptor.stencilAttachmentTexture = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::clear(ClearFlag flags, const Color4F& color, float depth, unsigned int stencil, float globalOrder)
|
||||
{
|
||||
_clearFlag = flags;
|
||||
|
||||
CallbackCommand* command = new CallbackCommand();
|
||||
command->init(globalOrder);
|
||||
command->func = [=]() -> void {
|
||||
backend::RenderPassDescriptor descriptor;
|
||||
backend::RenderPassParams descriptor;
|
||||
|
||||
if (_Bitmask_includes(ClearFlag::COLOR, flags))
|
||||
{
|
||||
_clearColor = color;
|
||||
descriptor.clearColorValue = {color.r, color.g, color.b, color.a};
|
||||
descriptor.needClearColor = true;
|
||||
descriptor.needColorAttachment = true;
|
||||
descriptor.colorAttachmentsTexture[0] = _renderPassDescriptor.colorAttachmentsTexture[0];
|
||||
}
|
||||
if (_Bitmask_includes(ClearFlag::DEPTH, flags))
|
||||
{
|
||||
descriptor.clearDepthValue = depth;
|
||||
descriptor.needClearDepth = true;
|
||||
descriptor.depthTestEnabled = true;
|
||||
descriptor.depthAttachmentTexture = _renderPassDescriptor.depthAttachmentTexture;
|
||||
}
|
||||
if (_Bitmask_includes(ClearFlag::STENCIL, flags))
|
||||
{
|
||||
descriptor.clearStencilValue = stencil;
|
||||
descriptor.needClearStencil = true;
|
||||
descriptor.stencilTestEnabled = true;
|
||||
descriptor.stencilAttachmentTexture = _renderPassDescriptor.stencilAttachmentTexture;
|
||||
}
|
||||
descriptor.flags.clear = flags;
|
||||
if (bitmask::any(flags, ClearFlag::COLOR)) {
|
||||
_clearColor = color;
|
||||
descriptor.clearColorValue = { color.r, color.g, color.b, color.a };
|
||||
}
|
||||
|
||||
_commandBuffer->beginRenderPass(descriptor);
|
||||
_commandBuffer->endRenderPass();
|
||||
if(bitmask::any(flags, ClearFlag::DEPTH))
|
||||
descriptor.clearDepthValue = depth;
|
||||
|
||||
delete command;
|
||||
};
|
||||
addCommand(command);
|
||||
}
|
||||
if(bitmask::any(flags, ClearFlag::STENCIL))
|
||||
descriptor.clearStencilValue = stencil;
|
||||
|
||||
Texture2D* Renderer::getColorAttachment() const
|
||||
{
|
||||
return _colorAttachment;
|
||||
}
|
||||
|
||||
Texture2D* Renderer::getDepthAttachment() const
|
||||
{
|
||||
return _depthAttachment;
|
||||
}
|
||||
|
||||
Texture2D* Renderer::getStencilAttachment() const
|
||||
{
|
||||
return _stencilAttachment;
|
||||
_commandBuffer->beginRenderPass(_currentRT, descriptor);
|
||||
_commandBuffer->endRenderPass();
|
||||
}
|
||||
|
||||
const Color4F& Renderer::getClearColor() const
|
||||
|
@ -889,12 +818,12 @@ const Color4F& Renderer::getClearColor() const
|
|||
|
||||
float Renderer::getClearDepth() const
|
||||
{
|
||||
return _renderPassDescriptor.clearDepthValue;
|
||||
return _renderPassParams.clearDepthValue;
|
||||
}
|
||||
|
||||
unsigned int Renderer::getClearStencil() const
|
||||
{
|
||||
return _renderPassDescriptor.clearStencilValue;
|
||||
return _renderPassParams.clearStencilValue;
|
||||
}
|
||||
|
||||
ClearFlag Renderer::getClearFlag() const
|
||||
|
@ -904,7 +833,7 @@ ClearFlag Renderer::getClearFlag() const
|
|||
|
||||
RenderTargetFlag Renderer::getRenderTargetFlag() const
|
||||
{
|
||||
return _renderTargetFlag;
|
||||
return _currentRT->getTargetFlags();
|
||||
}
|
||||
|
||||
void Renderer::setScissorTest(bool enabled)
|
||||
|
|
|
@ -50,6 +50,7 @@ class CommandBuffer;
|
|||
class RenderPipeline;
|
||||
class RenderPass;
|
||||
class TextureBackend;
|
||||
class RenderTarget;
|
||||
struct RenderPipelineDescriptor;
|
||||
struct PixelBufferDescriptor;
|
||||
}
|
||||
|
@ -187,7 +188,11 @@ public:
|
|||
@stencilAttachment The value to replace stencil attachment. Depth attachment and stencil attachment
|
||||
can be the same value.
|
||||
*/
|
||||
void setRenderTarget(RenderTargetFlag flags, Texture2D* colorAttachment, Texture2D* depthAttachment, Texture2D* stencilAttachment);
|
||||
backend::RenderTarget* getRenderTarget() const { return _currentRT; }
|
||||
void setRenderTarget(backend::RenderTarget* rt) { _currentRT = rt; };
|
||||
|
||||
backend::RenderTarget* getDefaultRenderTarget() const { return _defaultRT; }
|
||||
|
||||
/**
|
||||
Set clear values for each attachment.
|
||||
@flags Flags to indicate which attachment clear value to be modified.
|
||||
|
@ -197,24 +202,6 @@ public:
|
|||
*/
|
||||
void clear(ClearFlag flags, const Color4F& color, float depth, unsigned int stencil, float globalOrder);
|
||||
|
||||
/**
|
||||
* Get color attachment.
|
||||
* @return Color attachment.
|
||||
*/
|
||||
Texture2D* getColorAttachment() const;
|
||||
|
||||
/**
|
||||
* Get depth attachment.
|
||||
* @return Depth attachment.
|
||||
*/
|
||||
Texture2D* getDepthAttachment() const;
|
||||
|
||||
/**
|
||||
* Get stencil attachment.
|
||||
* @return Stencil attachment.
|
||||
*/
|
||||
Texture2D* getStencilAttachment() const;
|
||||
|
||||
/**
|
||||
* Get color clear value.
|
||||
* @return Color clear value.
|
||||
|
@ -407,8 +394,8 @@ public:
|
|||
/** returns whether or not a rectangle is visible or not */
|
||||
bool checkVisibility(const Mat4& transform, const Size& size);
|
||||
|
||||
/** read pixels from texture or screen framebuffer */
|
||||
void readPixels(backend::TextureBackend* texture, std::function<void(const backend::PixelBufferDescriptor&)> callback);
|
||||
/** read pixels from RenderTarget or screen framebuffer */
|
||||
void readPixels(backend::RenderTarget* rt, std::function<void(const backend::PixelBufferDescriptor&)> callback);
|
||||
|
||||
protected:
|
||||
friend class Director;
|
||||
|
@ -474,15 +461,15 @@ protected:
|
|||
void doVisitRenderQueue(const std::vector<RenderCommand*>&);
|
||||
|
||||
void fillVerticesAndIndices(const TrianglesCommand* cmd, unsigned int vertexBufferOffset);
|
||||
void beginRenderPass(RenderCommand*); /// Begin a render pass.
|
||||
void beginRenderPass(); /// Begin a render pass.
|
||||
|
||||
/**
|
||||
* Building a programmable pipeline involves an expensive evaluation of GPU state.
|
||||
* So a new render pipeline object will be created only if it hasn't been created before.
|
||||
* @param pipelineDescriptor Specifies the pipeline descriptor.
|
||||
* @param renderPassDescriptor Specifies the render pass descriptor.
|
||||
* @param renderPassParams Specifies the render pass descriptor.
|
||||
*/
|
||||
void setRenderPipeline(const PipelineDescriptor&, const backend::RenderPassDescriptor&);
|
||||
void setRenderPipeline(const PipelineDescriptor&, const backend::RenderPassParams&);
|
||||
|
||||
void pushStateBlock();
|
||||
|
||||
|
@ -508,7 +495,7 @@ protected:
|
|||
TriangleCommandBufferManager _triangleCommandBufferManager;
|
||||
|
||||
backend::CommandBuffer* _commandBuffer = nullptr;
|
||||
backend::RenderPassDescriptor _renderPassDescriptor;
|
||||
backend::RenderPassParams _renderPassParams;
|
||||
backend::DepthStencilDescriptor _depthStencilDescriptor;
|
||||
|
||||
// Internal structure that has the information for the batches
|
||||
|
@ -541,13 +528,11 @@ protected:
|
|||
|
||||
unsigned int _stencilRef = 0;
|
||||
|
||||
// weak reference
|
||||
Texture2D* _colorAttachment = nullptr;
|
||||
Texture2D* _depthAttachment = nullptr;
|
||||
Texture2D* _stencilAttachment = nullptr;
|
||||
backend::RenderTarget* _defaultRT = nullptr;
|
||||
backend::RenderTarget* _currentRT = nullptr; // weak ref
|
||||
|
||||
Color4F _clearColor = Color4F::BLACK;
|
||||
ClearFlag _clearFlag;
|
||||
RenderTargetFlag _renderTargetFlag = RenderTargetFlag::COLOR;
|
||||
|
||||
struct ScissorState
|
||||
{
|
||||
|
|
|
@ -28,7 +28,7 @@ set(COCOS_RENDERER_HEADER
|
|||
renderer/backend/Program.h
|
||||
renderer/backend/ProgramCache.h
|
||||
renderer/backend/Macros.h
|
||||
renderer/backend/RenderPassDescriptor.h
|
||||
renderer/backend/RenderPassParams.h
|
||||
renderer/backend/RenderPipeline.h
|
||||
renderer/backend/RenderPipelineDescriptor.h
|
||||
renderer/backend/ShaderModule.h
|
||||
|
@ -74,7 +74,7 @@ set(COCOS_RENDERER_SRC
|
|||
renderer/backend/ProgramState.cpp
|
||||
renderer/backend/ProgramStateRegistry.cpp
|
||||
renderer/backend/ShaderCache.cpp
|
||||
renderer/backend/RenderPassDescriptor.cpp
|
||||
renderer/backend/RenderPassParams.cpp
|
||||
)
|
||||
|
||||
if(ANDROID OR WINDOWS OR LINUX OR (IOS AND CC_FORCE_USE_GLES))
|
||||
|
@ -90,6 +90,7 @@ list(APPEND COCOS_RENDERER_HEADER
|
|||
renderer/backend/opengl/TextureGL.h
|
||||
renderer/backend/opengl/UtilsGL.h
|
||||
renderer/backend/opengl/DeviceInfoGL.h
|
||||
renderer/backend/opengl/RenderTargetGL.h
|
||||
)
|
||||
|
||||
list(APPEND COCOS_RENDERER_SRC
|
||||
|
@ -103,6 +104,7 @@ list(APPEND COCOS_RENDERER_SRC
|
|||
renderer/backend/opengl/TextureGL.cpp
|
||||
renderer/backend/opengl/UtilsGL.cpp
|
||||
renderer/backend/opengl/DeviceInfoGL.cpp
|
||||
renderer/backend/opengl/RenderTargetGL.cpp
|
||||
)
|
||||
|
||||
else()
|
||||
|
@ -111,6 +113,7 @@ list(APPEND COCOS_RENDERER_HEADER
|
|||
renderer/backend/metal/BufferMTL.h
|
||||
renderer/backend/metal/BufferManager.h
|
||||
renderer/backend/metal/CommandBufferMTL.h
|
||||
renderer/backend/metal/RenderTargetMTL.h
|
||||
renderer/backend/metal/DepthStencilStateMTL.h
|
||||
renderer/backend/metal/DeviceMTL.h
|
||||
renderer/backend/metal/RenderPipelineMTL.h
|
||||
|
@ -125,6 +128,7 @@ list(APPEND COCOS_RENDERER_SRC
|
|||
renderer/backend/metal/BufferMTL.mm
|
||||
renderer/backend/metal/BufferManager.mm
|
||||
renderer/backend/metal/CommandBufferMTL.mm
|
||||
renderer/backend/metal/RenderTargetMTL.mm
|
||||
renderer/backend/metal/DepthStencilStateMTL.mm
|
||||
renderer/backend/metal/DeviceMTL.mm
|
||||
renderer/backend/metal/RenderPipelineMTL.mm
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "renderer/backend/RenderPassDescriptor.h"
|
||||
#include "renderer/backend/RenderPassParams.h"
|
||||
#include "renderer/backend/RenderPipeline.h"
|
||||
#include "renderer/backend/RenderPipelineDescriptor.h"
|
||||
#include "renderer/backend/Device.h"
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
|
||||
#include "Macros.h"
|
||||
#include "Types.h"
|
||||
#include "RenderPassDescriptor.h"
|
||||
#include "RenderPassParams.h"
|
||||
#include "PixelBufferDescriptor.h"
|
||||
#include "CCStdC.h"
|
||||
#include "ProgramState.h"
|
||||
|
@ -47,6 +47,7 @@ class RenderPipeline;
|
|||
class Buffer;
|
||||
class DepthStencilState;
|
||||
class TextureBackend;
|
||||
class RenderTarget;
|
||||
|
||||
/**
|
||||
* @addtogroup _backend
|
||||
|
@ -70,7 +71,7 @@ public:
|
|||
* Begin a render pass, initial color, depth and stencil attachment.
|
||||
* @param descriptor Specifies a group of render targets that hold the results of a render pass.
|
||||
*/
|
||||
virtual void beginRenderPass(const RenderPassDescriptor& descriptor) = 0;
|
||||
virtual void beginRenderPass(const RenderTarget* renderTarget, const RenderPassParams& descriptor) = 0;
|
||||
|
||||
/**
|
||||
* Sets the current render pipeline state object.
|
||||
|
@ -172,7 +173,7 @@ public:
|
|||
* Get a screen snapshot
|
||||
* @param callback A callback to deal with screen snapshot image.
|
||||
*/
|
||||
virtual void capture(TextureBackend* texture, std::function<void(const PixelBufferDescriptor&)> callback) = 0;
|
||||
virtual void readPixels(RenderTarget* rt, std::function<void(const PixelBufferDescriptor&)> callback) = 0;
|
||||
|
||||
/**
|
||||
* Update both front and back stencil reference value.
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#include "Macros.h"
|
||||
#include "Types.h"
|
||||
#include "RenderPipelineDescriptor.h"
|
||||
#include "RenderPassDescriptor.h"
|
||||
#include "RenderPassParams.h"
|
||||
#include "Texture.h"
|
||||
#include "DepthStencilState.h"
|
||||
#include "ProgramCache.h"
|
||||
|
@ -45,6 +45,7 @@ class Buffer;
|
|||
class ShaderModule;
|
||||
class RenderPipeline;
|
||||
class RenderPass;
|
||||
class RenderTarget;
|
||||
|
||||
/**
|
||||
* @addtogroup _backend
|
||||
|
@ -89,6 +90,13 @@ public:
|
|||
*/
|
||||
virtual TextureBackend* newTexture(const TextureDescriptor& descriptor) = 0;
|
||||
|
||||
virtual RenderTarget* newDefaultRenderTarget(TargetBufferFlags rtf) = 0;
|
||||
|
||||
virtual RenderTarget* newRenderTarget(TargetBufferFlags rtf,
|
||||
TextureBackend* colorAttachment = nullptr,
|
||||
TextureBackend* depthAttachment = nullptr,
|
||||
TextureBackend* stencilAttachhment = nullptr) = 0;
|
||||
|
||||
/**
|
||||
* Create an auto released DepthStencilState object.
|
||||
* @param descriptor Specifies depth and stencil description.
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#define CC_BACKEND_BEGIN namespace cocos2d{ namespace backend{
|
||||
#define CC_BACKEND_END }}
|
||||
|
||||
#define MAX_COLOR_ATTCHMENT 1
|
||||
#define MAX_COLOR_ATTCHMENT 4
|
||||
|
||||
#define MAX_INFLIGHT_BUFFER 3
|
||||
|
||||
|
|
|
@ -1,70 +0,0 @@
|
|||
/****************************************************************************
|
||||
Copyright (c) 2018-2019 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "RenderPassDescriptor.h"
|
||||
|
||||
CC_BACKEND_BEGIN
|
||||
|
||||
RenderPassDescriptor& RenderPassDescriptor::operator=(const RenderPassDescriptor& descriptor)
|
||||
{
|
||||
clearDepthValue = descriptor.clearDepthValue;
|
||||
clearStencilValue = descriptor.clearStencilValue;
|
||||
clearColorValue = descriptor.clearColorValue;
|
||||
needColorAttachment = descriptor.needColorAttachment;
|
||||
depthTestEnabled = descriptor.depthTestEnabled;
|
||||
stencilTestEnabled = descriptor.stencilTestEnabled;
|
||||
needClearColor = descriptor.needClearColor;
|
||||
needClearDepth = descriptor.needClearDepth;
|
||||
needClearStencil = descriptor.needClearStencil;
|
||||
depthAttachmentTexture = descriptor.depthAttachmentTexture;
|
||||
stencilAttachmentTexture = descriptor.stencilAttachmentTexture;
|
||||
colorAttachmentsTexture[0] = descriptor.colorAttachmentsTexture[0];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool RenderPassDescriptor::operator==(const RenderPassDescriptor& descriptor) const
|
||||
{
|
||||
if( clearDepthValue == descriptor.clearDepthValue &&
|
||||
clearStencilValue == descriptor.clearStencilValue &&
|
||||
clearColorValue == descriptor.clearColorValue &&
|
||||
needColorAttachment == descriptor.needColorAttachment &&
|
||||
depthTestEnabled == descriptor.depthTestEnabled &&
|
||||
stencilTestEnabled == descriptor.stencilTestEnabled &&
|
||||
needClearColor == descriptor.needClearColor &&
|
||||
needClearDepth == descriptor.needClearDepth &&
|
||||
needClearStencil == descriptor.needClearStencil &&
|
||||
depthAttachmentTexture == descriptor.depthAttachmentTexture &&
|
||||
stencilAttachmentTexture == descriptor.stencilAttachmentTexture &&
|
||||
colorAttachmentsTexture[0] == descriptor.colorAttachmentsTexture[0])
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
CC_BACKEND_END
|
|
@ -0,0 +1,42 @@
|
|||
/****************************************************************************
|
||||
Copyright (c) 2018-2019 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "RenderPassParams.h"
|
||||
|
||||
CC_BACKEND_BEGIN
|
||||
|
||||
bool RenderPassParams::operator==(const RenderPassParams& descriptor) const
|
||||
{
|
||||
return (clearDepthValue == descriptor.clearDepthValue &&
|
||||
clearStencilValue == descriptor.clearStencilValue &&
|
||||
clearColorValue == descriptor.clearColorValue &&
|
||||
// needColorAttachment == descriptor.needColorAttachment &&
|
||||
// depthTestEnabled == descriptor.depthTestEnabled &&
|
||||
// stencilTestEnabled == descriptor.stencilTestEnabled &&
|
||||
flags.clear == descriptor.flags.clear &&
|
||||
flags.discardStart == descriptor.flags.discardStart &&
|
||||
flags.discardEnd == descriptor.flags.discardEnd);
|
||||
}
|
||||
|
||||
CC_BACKEND_END
|
|
@ -38,28 +38,43 @@ class TextureBackend;
|
|||
* @{
|
||||
*/
|
||||
|
||||
struct RenderPassFlags {
|
||||
/**
|
||||
* bitmask indicating which buffers to clear at the beginning of a render pass.
|
||||
* This implies discard.
|
||||
*/
|
||||
TargetBufferFlags clear;
|
||||
|
||||
/**
|
||||
* bitmask indicating which buffers to discard at the beginning of a render pass.
|
||||
* Discarded buffers have uninitialized content, they must be entirely drawn over or cleared.
|
||||
*/
|
||||
TargetBufferFlags discardStart;
|
||||
|
||||
/**
|
||||
* bitmask indicating which buffers to discard at the end of a render pass.
|
||||
* Discarded buffers' content becomes invalid, they must not be read from again.
|
||||
*/
|
||||
TargetBufferFlags discardEnd;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Store values about color, depth and stencil attachment.
|
||||
*/
|
||||
struct RenderPassDescriptor
|
||||
struct RenderPassParams
|
||||
{
|
||||
RenderPassDescriptor& operator=(const RenderPassDescriptor& descriptor);
|
||||
bool operator==(const RenderPassDescriptor& descriptor) const;
|
||||
bool needDepthStencilAttachment() const { return depthTestEnabled || stencilTestEnabled; }
|
||||
RenderPassParams& operator=(const RenderPassParams& descriptor) = default;
|
||||
bool operator==(const RenderPassParams& descriptor) const;
|
||||
|
||||
float clearDepthValue = 0.f;
|
||||
float clearStencilValue = 0.f;
|
||||
std::array<float, 4> clearColorValue {{0.f, 0.f, 0.f, 0.f}}; // double-braces required in C++11
|
||||
bool needColorAttachment = true;
|
||||
bool depthTestEnabled = false;
|
||||
bool stencilTestEnabled = false;
|
||||
bool needClearColor = false;
|
||||
bool needClearDepth = false;
|
||||
bool needClearStencil = false;
|
||||
TextureBackend* depthAttachmentTexture = nullptr;
|
||||
TextureBackend* stencilAttachmentTexture = nullptr;
|
||||
TextureBackend* colorAttachmentsTexture[MAX_COLOR_ATTCHMENT] = { nullptr };
|
||||
|
||||
// Now, only clear flag used
|
||||
RenderPassFlags flags{};
|
||||
};
|
||||
typedef RenderPassParams RenderPassParams;
|
||||
|
||||
//end of _backend group
|
||||
/// @}
|
|
@ -28,13 +28,14 @@
|
|||
#include "Types.h"
|
||||
#include "base/CCRef.h"
|
||||
#include "renderer/CCPipelineDescriptor.h"
|
||||
#include "renderer/backend/RenderPassDescriptor.h"
|
||||
#include "renderer/backend/RenderPassParams.h"
|
||||
|
||||
CC_BACKEND_BEGIN
|
||||
/**
|
||||
* @addtogroup _backend
|
||||
* @{
|
||||
*/
|
||||
class RenderTarget;
|
||||
|
||||
/**
|
||||
* Render pipeline
|
||||
|
@ -42,7 +43,7 @@ CC_BACKEND_BEGIN
|
|||
class RenderPipeline : public cocos2d::Ref
|
||||
{
|
||||
public:
|
||||
virtual void update(const PipelineDescriptor & pipelineDescirptor, const RenderPassDescriptor& renderpassDescriptor) = 0;
|
||||
virtual void update(const PipelineDescriptor & pipelineDescirptor, const RenderTarget* renderTarget, const RenderPassParams& renderPassParams) = 0;
|
||||
|
||||
protected:
|
||||
virtual ~RenderPipeline() = default;
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
#pragma once
|
||||
|
||||
#include "base/CCRef.h"
|
||||
#include "Texture.h"
|
||||
#include <assert.h>
|
||||
|
||||
CC_BACKEND_BEGIN
|
||||
|
||||
class RenderTarget : public cocos2d::Ref {
|
||||
public:
|
||||
struct RenderBuffer {
|
||||
TextureBackend* texture = nullptr;
|
||||
uint8_t level = 0; // level when attached to a texture
|
||||
explicit operator bool() const {
|
||||
return texture != nullptr;
|
||||
}
|
||||
};
|
||||
typedef RenderBuffer ColorAttachment[MAX_COLOR_ATTCHMENT];
|
||||
|
||||
RenderTarget(bool defaultRenderTarget) : _defaultRenderTarget(defaultRenderTarget) {}
|
||||
virtual ~RenderTarget()
|
||||
{
|
||||
for (auto colorItem : _color)
|
||||
CC_SAFE_RELEASE(colorItem.texture);
|
||||
CC_SAFE_RELEASE(_depth.texture);
|
||||
CC_SAFE_RELEASE(_stencil.texture);
|
||||
}
|
||||
void setTargetFlags(TargetBufferFlags flags) { _flags = flags; }
|
||||
TargetBufferFlags getTargetFlags() const { return _flags; }
|
||||
void modifyTargetFlags(TargetBufferFlags flagsToAdd, TargetBufferFlags flagsToRemove)
|
||||
{
|
||||
_flags |= flagsToAdd;
|
||||
_flags &= ~flagsToRemove;
|
||||
}
|
||||
|
||||
virtual void bindFrameBuffer() const {};
|
||||
virtual void unbindFrameBuffer() const {};
|
||||
|
||||
virtual void setColorAttachment(ColorAttachment attachment) {
|
||||
for (auto colorItem : _color)
|
||||
CC_SAFE_RELEASE(colorItem.texture);
|
||||
memcpy(_color, attachment, sizeof(ColorAttachment));
|
||||
for (auto colorItem : _color)
|
||||
CC_SAFE_RETAIN(colorItem.texture);
|
||||
};
|
||||
virtual void setDepthAttachment(TextureBackend* attachment, int level = 0)
|
||||
{
|
||||
CC_SAFE_RELEASE(_depth.texture);
|
||||
_depth.texture = attachment;
|
||||
_depth.level = level;
|
||||
CC_SAFE_RETAIN(_depth.texture);
|
||||
};
|
||||
virtual void setStencilAttachment(TextureBackend* attachment, int level = 0) {
|
||||
CC_SAFE_RELEASE(_stencil.texture);
|
||||
_stencil.texture = attachment;
|
||||
_stencil.level = level;
|
||||
CC_SAFE_RETAIN(_stencil.texture);
|
||||
};
|
||||
|
||||
bool isDefaultRenderTarget() const { return _defaultRenderTarget; }
|
||||
|
||||
bool _defaultRenderTarget = false;
|
||||
ColorAttachment _color{};
|
||||
RenderBuffer _depth{};
|
||||
RenderBuffer _stencil{};
|
||||
TargetBufferFlags _flags{};
|
||||
|
||||
// uint8_t samples = 1;
|
||||
|
||||
};
|
||||
|
||||
CC_BACKEND_END
|
|
@ -51,14 +51,11 @@ struct TextureDescriptor
|
|||
SamplerDescriptor samplerDescriptor;
|
||||
};
|
||||
|
||||
struct UtilsGL;
|
||||
|
||||
/**
|
||||
* A base texture
|
||||
*/
|
||||
class TextureBackend : public Ref
|
||||
{
|
||||
friend struct UtilsGL;
|
||||
public:
|
||||
/**
|
||||
* Update sampler
|
||||
|
@ -106,6 +103,8 @@ public:
|
|||
int getWidth() const { return _width; }
|
||||
int getHeight() const { return _height; }
|
||||
|
||||
int getBytesPerRow() const { return _width * _bitsPerElement / 8; }
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @param descriptor Specifies the texture descirptor.
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include "Macros.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include "base/bitmask.h"
|
||||
|
@ -258,6 +259,33 @@ enum class ColorWriteMask : uint32_t
|
|||
CC_ENABLE_BITMASK_OPS(ColorWriteMask)
|
||||
CC_ENABLE_BITSHIFT_OPS(ColorWriteMask)
|
||||
|
||||
|
||||
/**
|
||||
* Bitmask for selecting render buffers
|
||||
*/
|
||||
enum class TargetBufferFlags : uint8_t {
|
||||
NONE = 0x0u, //!< No buffer selected.
|
||||
COLOR0 = 0x1u, //!< Color buffer selected.
|
||||
COLOR1 = 0x2u, //!< Color buffer selected.
|
||||
COLOR2 = 0x4u, //!< Color buffer selected.
|
||||
COLOR3 = 0x8u, //!< Color buffer selected.
|
||||
COLOR = COLOR0, //!< \deprecated
|
||||
COLOR_ALL = COLOR0 | COLOR1 | COLOR2 | COLOR3,
|
||||
DEPTH = 0x10u, //!< Depth buffer selected.
|
||||
STENCIL = 0x20u, //!< Stencil buffer selected.
|
||||
DEPTH_AND_STENCIL = DEPTH | STENCIL, //!< depth and stencil buffer selected.
|
||||
ALL = COLOR_ALL | DEPTH | STENCIL //!< Color, depth and stencil buffer selected.
|
||||
};
|
||||
CC_ENABLE_BITMASK_OPS(TargetBufferFlags)
|
||||
|
||||
inline TargetBufferFlags getMRTColorFlag(size_t index) noexcept {
|
||||
assert(index < 4);
|
||||
return TargetBufferFlags(1u << index);
|
||||
}
|
||||
|
||||
typedef TargetBufferFlags ClearFlag;
|
||||
typedef TargetBufferFlags RenderTargetFlag;
|
||||
|
||||
struct SamplerDescriptor
|
||||
{
|
||||
SamplerFilter magFilter = SamplerFilter::LINEAR;
|
||||
|
@ -418,4 +446,6 @@ struct BlendDescriptor
|
|||
BlendFactor sourceAlphaBlendFactor = BlendFactor::ONE;
|
||||
BlendFactor destinationAlphaBlendFactor = BlendFactor::ZERO;
|
||||
};
|
||||
|
||||
|
||||
CC_BACKEND_END
|
||||
|
|
|
@ -61,11 +61,11 @@ public:
|
|||
virtual void beginFrame() override;
|
||||
|
||||
/**
|
||||
* Create a MTLRenderCommandEncoder object for graphics rendering to an attachment in a RenderPassDescriptor.
|
||||
* MTLRenderCommandEncoder is cached if current RenderPassDescriptor is identical to previous one.
|
||||
* Create a MTLRenderCommandEncoder object for graphics rendering to an attachment in a RenderPassParams.
|
||||
* MTLRenderCommandEncoder is cached if current RenderPassParams is identical to previous one.
|
||||
* @param descriptor Specifies a group of render targets that hold the results of a render pass.
|
||||
*/
|
||||
virtual void beginRenderPass(const RenderPassDescriptor& descriptor) override;
|
||||
virtual void beginRenderPass(const RenderTarget* renderTarget, const RenderPassParams& descriptor) override;
|
||||
|
||||
/**
|
||||
* Sets the current render pipeline state object.
|
||||
|
@ -166,10 +166,22 @@ public:
|
|||
virtual void setDepthStencilState(DepthStencilState* depthStencilState) override;
|
||||
|
||||
/**
|
||||
* Get a screen snapshot
|
||||
* @param callback A callback to deal with screen snapshot image.
|
||||
* Read pixels from RenderTarget
|
||||
* @param callback A callback to deal with pixel data read.
|
||||
*/
|
||||
virtual void capture(TextureBackend* texture, std::function<void(const PixelBufferDescriptor&)> callback) override;
|
||||
virtual void readPixels(RenderTarget* rt, std::function<void(const PixelBufferDescriptor&)> callback) override;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Read a block of pixels from the given texture
|
||||
* @param texture Specifies the texture to get the image.
|
||||
* @param origX,origY Specify the window coordinates of the first pixel that is read from the given texture. This location is the lower left corner of a rectangular block of pixels.
|
||||
* @param rectWidth,rectHeight Specify the dimensions of the pixel rectangle. rectWidth and rectHeight of one correspond to a single pixel.
|
||||
* @param pbd, the output buffer for fill texels data
|
||||
* @remark: !!!this function only can call after endFrame, then it's could be works well.
|
||||
*/
|
||||
static void readPixels(TextureBackend* texture, std::size_t origX, std::size_t origY, std::size_t rectWidth, std::size_t rectHeight, PixelBufferDescriptor& pbd);
|
||||
static void readPixels(id<MTLTexture> texture, std::size_t origX, std::size_t origY, std::size_t rectWidth, std::size_t rectHeight, PixelBufferDescriptor& pbd);
|
||||
|
||||
private:
|
||||
void prepareDrawing() const;
|
||||
|
@ -179,7 +191,7 @@ private:
|
|||
void afterDraw();
|
||||
void flush();
|
||||
void flushCaptureCommands();
|
||||
id<MTLRenderCommandEncoder> getRenderCommandEncoder(const RenderPassDescriptor& renderPassDescriptor);
|
||||
id<MTLRenderCommandEncoder> getRenderCommandEncoder(const RenderTarget* renderTarget, const RenderPassParams& renderPassParams);
|
||||
|
||||
id<MTLCommandBuffer> _mtlCommandBuffer = nil;
|
||||
id<MTLCommandQueue> _mtlCommandQueue = nil;
|
||||
|
@ -195,7 +207,8 @@ private:
|
|||
unsigned int _renderTargetHeight = 0;
|
||||
|
||||
dispatch_semaphore_t _frameBoundarySemaphore;
|
||||
RenderPassDescriptor _prevRenderPassDescriptor;
|
||||
const RenderTarget* _currentRenderTarget = nil; // weak ref
|
||||
RenderPassParams _currentRenderPassParams;
|
||||
NSAutoreleasePool* _autoReleasePool = nil;
|
||||
|
||||
std::vector<std::pair<TextureBackend*,std::function<void(const PixelBufferDescriptor&)>>> _captureCallbacks;
|
||||
|
|
|
@ -32,12 +32,46 @@
|
|||
#include "../Macros.h"
|
||||
#include "BufferManager.h"
|
||||
#include "DepthStencilStateMTL.h"
|
||||
#include "RenderTargetMTL.h"
|
||||
|
||||
CC_BACKEND_BEGIN
|
||||
|
||||
namespace
|
||||
{
|
||||
MTLWinding toMTLWinding(Winding winding)
|
||||
|
||||
#define byte(n) ((n) * 8)
|
||||
#define bit(n) (n)
|
||||
static uint8_t getBitsPerElementMTL(MTLPixelFormat pixleFormat)
|
||||
{
|
||||
switch (pixleFormat)
|
||||
{
|
||||
case MTLPixelFormatDepth32Float_Stencil8:
|
||||
return byte(8);
|
||||
case MTLPixelFormatBGRA8Unorm:
|
||||
case MTLPixelFormatRGBA8Unorm:
|
||||
case MTLPixelFormatDepth32Float:
|
||||
return byte(4);
|
||||
#if (CC_TARGET_PLATFORM == CC_PLATFORM_MAC)
|
||||
case MTLPixelFormatDepth24Unorm_Stencil8:
|
||||
return byte(4);
|
||||
#else
|
||||
case MTLPixelFormatABGR4Unorm:
|
||||
case MTLPixelFormatBGR5A1Unorm:
|
||||
case MTLPixelFormatB5G6R5Unorm:
|
||||
case MTLPixelFormatA1BGR5Unorm:
|
||||
return byte(2);
|
||||
#endif
|
||||
case MTLPixelFormatA8Unorm:
|
||||
case MTLPixelFormatR8Unorm:
|
||||
return byte(1);
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static MTLWinding toMTLWinding(Winding winding)
|
||||
{
|
||||
if (Winding::CLOCK_WISE == winding)
|
||||
return MTLWindingClockwise;
|
||||
|
@ -45,7 +79,7 @@ namespace
|
|||
return MTLWindingCounterClockwise;
|
||||
}
|
||||
|
||||
MTLPrimitiveType toMTLPrimitive(PrimitiveType primitiveType)
|
||||
static MTLPrimitiveType toMTLPrimitive(PrimitiveType primitiveType)
|
||||
{
|
||||
MTLPrimitiveType ret = MTLPrimitiveTypeTriangle;
|
||||
switch (primitiveType)
|
||||
|
@ -71,7 +105,7 @@ namespace
|
|||
return ret;
|
||||
}
|
||||
|
||||
MTLIndexType toMTLIndexType(IndexFormat indexFormat)
|
||||
static MTLIndexType toMTLIndexType(IndexFormat indexFormat)
|
||||
{
|
||||
if (IndexFormat::U_SHORT == indexFormat)
|
||||
return MTLIndexTypeUInt16;
|
||||
|
@ -79,7 +113,7 @@ namespace
|
|||
return MTLIndexTypeUInt32;
|
||||
}
|
||||
|
||||
MTLCullMode toMTLCullMode(CullMode mode)
|
||||
static MTLCullMode toMTLCullMode(CullMode mode)
|
||||
{
|
||||
switch (mode) {
|
||||
case CullMode::NONE:
|
||||
|
@ -91,109 +125,21 @@ namespace
|
|||
}
|
||||
}
|
||||
|
||||
MTLRenderPassDescriptor* toMTLRenderPassDescriptor(const RenderPassDescriptor& descriptor)
|
||||
static MTLRenderPassDescriptor* toMTLRenderPassDescriptor(const RenderTarget* rt, const RenderPassParams& params)
|
||||
{
|
||||
MTLRenderPassDescriptor* mtlDescritpor = [MTLRenderPassDescriptor renderPassDescriptor];
|
||||
|
||||
// Set color attachments.
|
||||
if (descriptor.needColorAttachment)
|
||||
{
|
||||
bool hasCustomColorAttachment = false;
|
||||
for (int i = 0; i < MAX_COLOR_ATTCHMENT; ++i)
|
||||
{
|
||||
if (! descriptor.colorAttachmentsTexture[i])
|
||||
continue;
|
||||
|
||||
mtlDescritpor.colorAttachments[i].texture = static_cast<TextureMTL*>(descriptor.colorAttachmentsTexture[i])->getMTLTexture();
|
||||
if (descriptor.needClearColor)
|
||||
{
|
||||
mtlDescritpor.colorAttachments[i].loadAction = MTLLoadActionClear;
|
||||
mtlDescritpor.colorAttachments[i].clearColor = MTLClearColorMake(descriptor.clearColorValue[0],
|
||||
descriptor.clearColorValue[1],
|
||||
descriptor.clearColorValue[2],
|
||||
descriptor.clearColorValue[3]);
|
||||
}
|
||||
else
|
||||
mtlDescritpor.colorAttachments[i].loadAction = MTLLoadActionLoad;
|
||||
|
||||
hasCustomColorAttachment = true;
|
||||
}
|
||||
|
||||
if (!hasCustomColorAttachment)
|
||||
{
|
||||
mtlDescritpor.colorAttachments[0].texture = DeviceMTL::getCurrentDrawable().texture;
|
||||
if (descriptor.needClearColor)
|
||||
{
|
||||
mtlDescritpor.colorAttachments[0].loadAction = MTLLoadActionClear;
|
||||
mtlDescritpor.colorAttachments[0].clearColor = MTLClearColorMake(descriptor.clearColorValue[0],
|
||||
descriptor.clearColorValue[1],
|
||||
descriptor.clearColorValue[2],
|
||||
descriptor.clearColorValue[3]);
|
||||
}
|
||||
else
|
||||
mtlDescritpor.colorAttachments[0].loadAction = MTLLoadActionLoad;
|
||||
}
|
||||
|
||||
mtlDescritpor.colorAttachments[0].storeAction = MTLStoreActionStore;
|
||||
}
|
||||
|
||||
if(descriptor.needDepthStencilAttachment())
|
||||
{
|
||||
// Set depth attachment
|
||||
{
|
||||
if (descriptor.depthAttachmentTexture)
|
||||
mtlDescritpor.depthAttachment.texture = static_cast<TextureMTL*>(descriptor.depthAttachmentTexture)->getMTLTexture();
|
||||
else
|
||||
mtlDescritpor.depthAttachment.texture = UtilsMTL::getDefaultDepthStencilTexture();
|
||||
|
||||
if (descriptor.needClearDepth)
|
||||
{
|
||||
mtlDescritpor.depthAttachment.loadAction = MTLLoadActionClear;
|
||||
mtlDescritpor.depthAttachment.clearDepth = descriptor.clearDepthValue;
|
||||
}
|
||||
else
|
||||
mtlDescritpor.depthAttachment.loadAction = MTLLoadActionLoad;
|
||||
|
||||
mtlDescritpor.depthAttachment.storeAction = MTLStoreActionStore;
|
||||
}
|
||||
|
||||
// Set stencil attachment
|
||||
{
|
||||
if (descriptor.stencilAttachmentTexture)
|
||||
mtlDescritpor.stencilAttachment.texture = static_cast<TextureMTL*>(descriptor.stencilAttachmentTexture)->getMTLTexture();
|
||||
else
|
||||
mtlDescritpor.stencilAttachment.texture = UtilsMTL::getDefaultDepthStencilTexture();
|
||||
|
||||
if (descriptor.needClearStencil)
|
||||
{
|
||||
mtlDescritpor.stencilAttachment.loadAction = MTLLoadActionClear;
|
||||
mtlDescritpor.stencilAttachment.clearStencil = descriptor.clearStencilValue;
|
||||
}
|
||||
else
|
||||
mtlDescritpor.stencilAttachment.loadAction = MTLLoadActionLoad;
|
||||
|
||||
mtlDescritpor.stencilAttachment.storeAction = MTLStoreActionStore;
|
||||
}
|
||||
}
|
||||
|
||||
auto rtMTL = static_cast<const RenderTargetMTL*>(rt);
|
||||
rtMTL->applyRenderPassAttachments(params, mtlDescritpor);
|
||||
return mtlDescritpor;
|
||||
}
|
||||
|
||||
id<MTLTexture> getMTLTexture(TextureBackend* texture, int index = 0)
|
||||
static id<MTLTexture> getMTLTexture(TextureBackend* texture, int index)
|
||||
{
|
||||
switch (texture->getTextureType())
|
||||
{
|
||||
case TextureType::TEXTURE_2D:
|
||||
return static_cast<TextureMTL*>(texture)->getMTLTexture(index);
|
||||
case TextureType::TEXTURE_CUBE:
|
||||
return static_cast<TextureCubeMTL*>(texture)->getMTLTexture(index);
|
||||
default:
|
||||
assert(false);
|
||||
return nil;
|
||||
}
|
||||
return reinterpret_cast<id<MTLTexture>>(texture->getHandler(index));
|
||||
}
|
||||
|
||||
id<MTLSamplerState> getMTLSamplerState(TextureBackend* texture)
|
||||
static id<MTLSamplerState> getMTLSamplerState(TextureBackend* texture)
|
||||
{
|
||||
switch (texture->getTextureType())
|
||||
{
|
||||
|
@ -242,15 +188,16 @@ void CommandBufferMTL::beginFrame()
|
|||
BufferManager::beginFrame();
|
||||
}
|
||||
|
||||
id<MTLRenderCommandEncoder> CommandBufferMTL::getRenderCommandEncoder(const RenderPassDescriptor& renderPassDescriptor)
|
||||
id<MTLRenderCommandEncoder> CommandBufferMTL::getRenderCommandEncoder(const RenderTarget* renderTarget, const RenderPassParams& renderPassParams)
|
||||
{
|
||||
if(_mtlRenderEncoder != nil && _prevRenderPassDescriptor == renderPassDescriptor)
|
||||
if(_mtlRenderEncoder != nil && _currentRenderPassParams == renderPassParams && _currentRenderTarget == renderTarget)
|
||||
{
|
||||
return _mtlRenderEncoder;
|
||||
}
|
||||
else
|
||||
{
|
||||
_prevRenderPassDescriptor = renderPassDescriptor;
|
||||
_currentRenderTarget = renderTarget;
|
||||
_currentRenderPassParams = renderPassParams;
|
||||
}
|
||||
|
||||
if(_mtlRenderEncoder != nil)
|
||||
|
@ -260,7 +207,7 @@ id<MTLRenderCommandEncoder> CommandBufferMTL::getRenderCommandEncoder(const Rend
|
|||
_mtlRenderEncoder = nil;
|
||||
}
|
||||
|
||||
auto mtlDescriptor = toMTLRenderPassDescriptor(renderPassDescriptor);
|
||||
auto mtlDescriptor = toMTLRenderPassDescriptor(renderTarget, renderPassParams);
|
||||
_renderTargetWidth = (unsigned int)mtlDescriptor.colorAttachments[0].texture.width;
|
||||
_renderTargetHeight = (unsigned int)mtlDescriptor.colorAttachments[0].texture.height;
|
||||
id<MTLRenderCommandEncoder> mtlRenderEncoder = [_mtlCommandBuffer renderCommandEncoderWithDescriptor:mtlDescriptor];
|
||||
|
@ -269,9 +216,9 @@ id<MTLRenderCommandEncoder> CommandBufferMTL::getRenderCommandEncoder(const Rend
|
|||
return mtlRenderEncoder;
|
||||
}
|
||||
|
||||
void CommandBufferMTL::beginRenderPass(const RenderPassDescriptor& descriptor)
|
||||
void CommandBufferMTL::beginRenderPass(const RenderTarget* renderTarget, const RenderPassParams& descriptor)
|
||||
{
|
||||
_mtlRenderEncoder = getRenderCommandEncoder(descriptor);
|
||||
_mtlRenderEncoder = getRenderCommandEncoder(renderTarget, descriptor);
|
||||
// [_mtlRenderEncoder setFrontFacingWinding:MTLWindingCounterClockwise];
|
||||
}
|
||||
|
||||
|
@ -355,8 +302,13 @@ void CommandBufferMTL::endRenderPass()
|
|||
|
||||
}
|
||||
|
||||
void CommandBufferMTL::capture(TextureBackend* texture, std::function<void(const PixelBufferDescriptor&)> callback)
|
||||
void CommandBufferMTL::readPixels(RenderTarget* rt, std::function<void(const PixelBufferDescriptor&)> callback)
|
||||
{
|
||||
auto rtMTL = static_cast<RenderTargetMTL*>(rt);
|
||||
|
||||
// we only read form color attachment 0
|
||||
// if it's nullptr, will regard as screen to perform capture
|
||||
auto texture = rtMTL->_color[0].texture;
|
||||
CC_SAFE_RETAIN(texture);
|
||||
_captureCallbacks.emplace_back(texture, std::move(callback));
|
||||
}
|
||||
|
@ -407,7 +359,7 @@ void CommandBufferMTL::flushCaptureCommands()
|
|||
for(auto& cb : _captureCallbacks) {
|
||||
if(cb.first == nil) { // screen capture
|
||||
if(!screenPixelData) {
|
||||
UtilsMTL::readPixels(_drawableTexture, 0, 0, [_drawableTexture width], [_drawableTexture height], screenPixelData);
|
||||
CommandBufferMTL::readPixels(_drawableTexture, 0, 0, [_drawableTexture width], [_drawableTexture height], screenPixelData);
|
||||
// screen framebuffer copied, restore screen framebuffer only to true
|
||||
backend::Device::getInstance()->setFrameBufferOnly(true);
|
||||
}
|
||||
|
@ -417,7 +369,7 @@ void CommandBufferMTL::flushCaptureCommands()
|
|||
PixelBufferDescriptor pixelData;
|
||||
auto texture = cb.first;
|
||||
assert(texture != nullptr);
|
||||
UtilsMTL::readPixels(texture, 0, 0, texture->getWidth(), texture->getHeight(), pixelData);
|
||||
CommandBufferMTL::readPixels(texture, 0, 0, texture->getWidth(), texture->getHeight(), pixelData);
|
||||
CC_SAFE_RELEASE(texture);
|
||||
cb.second(pixelData);
|
||||
}
|
||||
|
@ -570,5 +522,52 @@ void CommandBufferMTL::setScissorRect(bool isEnabled, float x, float y, float wi
|
|||
[_mtlRenderEncoder setScissorRect:scissorRect];
|
||||
}
|
||||
|
||||
void CommandBufferMTL::readPixels(TextureBackend* texture, std::size_t origX, std::size_t origY, std::size_t rectWidth, std::size_t rectHeight, PixelBufferDescriptor& pbd)
|
||||
{
|
||||
CommandBufferMTL::readPixels(reinterpret_cast<id<MTLTexture>>(texture->getHandler()), origX, origY, rectWidth, rectHeight, pbd);
|
||||
}
|
||||
|
||||
void CommandBufferMTL::readPixels(id<MTLTexture> texture, std::size_t origX, std::size_t origY, std::size_t rectWidth, std::size_t rectHeight, PixelBufferDescriptor& pbd)
|
||||
{
|
||||
NSUInteger texWidth = texture.width;
|
||||
NSUInteger texHeight = texture.height;
|
||||
MTLRegion region = MTLRegionMake2D(0, 0, texWidth, texHeight);
|
||||
MTLRegion imageRegion = MTLRegionMake2D(origX, origY, rectWidth, rectHeight);
|
||||
|
||||
MTLTextureDescriptor* textureDescriptor =
|
||||
[MTLTextureDescriptor texture2DDescriptorWithPixelFormat:[texture pixelFormat]
|
||||
width:texWidth
|
||||
height:texHeight
|
||||
mipmapped:NO];
|
||||
id<MTLDevice> device = static_cast<DeviceMTL*>(DeviceMTL::getInstance())->getMTLDevice();
|
||||
id<MTLTexture> readPixelsTexture = [device newTextureWithDescriptor:textureDescriptor];
|
||||
|
||||
id<MTLCommandQueue> commandQueue = static_cast<DeviceMTL*>(DeviceMTL::getInstance())->getMTLCommandQueue();
|
||||
auto commandBuffer = [commandQueue commandBuffer];
|
||||
// [commandBuffer enqueue];
|
||||
|
||||
id<MTLBlitCommandEncoder> blitCommandEncoder = [commandBuffer blitCommandEncoder];
|
||||
[blitCommandEncoder copyFromTexture:texture sourceSlice:0 sourceLevel:0 sourceOrigin:region.origin sourceSize:region.size toTexture:readPixelsTexture destinationSlice:0 destinationLevel:0 destinationOrigin:region.origin];
|
||||
|
||||
#if (CC_TARGET_PLATFORM == CC_PLATFORM_MAC)
|
||||
[blitCommandEncoder synchronizeResource:readPixelsTexture];
|
||||
#endif
|
||||
[blitCommandEncoder endEncoding];
|
||||
|
||||
[commandBuffer addCompletedHandler:^(id<MTLCommandBuffer> commandBufferMTL) {
|
||||
auto bytePerRow = rectWidth * getBitsPerElementMTL(texture.pixelFormat) / 8;
|
||||
auto texelData = pbd._data.resize(bytePerRow * rectHeight);
|
||||
if(texelData != nullptr)
|
||||
{
|
||||
[readPixelsTexture getBytes:texelData bytesPerRow:bytePerRow fromRegion:imageRegion mipmapLevel:0];
|
||||
UtilsMTL::swizzleImage(texelData, rectWidth, rectHeight, readPixelsTexture.pixelFormat);
|
||||
pbd._width = rectWidth;
|
||||
pbd._height = rectHeight;
|
||||
}
|
||||
[readPixelsTexture release];
|
||||
}];
|
||||
[commandBuffer commit];
|
||||
[commandBuffer waitUntilCompleted];
|
||||
}
|
||||
|
||||
CC_BACKEND_END
|
||||
|
|
|
@ -95,6 +95,12 @@ public:
|
|||
* @return A TextureBackend object.
|
||||
*/
|
||||
virtual TextureBackend* newTexture(const TextureDescriptor& descriptor) override;
|
||||
|
||||
RenderTarget* newDefaultRenderTarget(TargetBufferFlags rtf) override;
|
||||
RenderTarget* newRenderTarget(TargetBufferFlags rtf,
|
||||
TextureBackend* colorAttachment,
|
||||
TextureBackend* depthAttachment,
|
||||
TextureBackend* stencilAttachhment) override;
|
||||
|
||||
/**
|
||||
* Create a DepthStencilState object.
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "TextureMTL.h"
|
||||
#include "ProgramMTL.h"
|
||||
#include "DeviceInfoMTL.h"
|
||||
#include "RenderTargetMTL.h"
|
||||
|
||||
#include "base/ccMacros.h"
|
||||
|
||||
|
@ -108,6 +109,27 @@ TextureBackend* DeviceMTL::newTexture(const TextureDescriptor& descriptor)
|
|||
}
|
||||
}
|
||||
|
||||
RenderTarget* DeviceMTL::newDefaultRenderTarget(TargetBufferFlags rtf)
|
||||
{
|
||||
auto rtGL = new RenderTargetMTL(true);
|
||||
rtGL->setTargetFlags(rtf);
|
||||
return rtGL;
|
||||
}
|
||||
|
||||
RenderTarget* DeviceMTL::newRenderTarget(TargetBufferFlags rtf,
|
||||
TextureBackend* colorAttachment,
|
||||
TextureBackend* depthAttachment,
|
||||
TextureBackend* stencilAttachhment)
|
||||
{
|
||||
auto rtGL = new RenderTargetMTL(false);
|
||||
rtGL->setTargetFlags(rtf);
|
||||
rtGL->bindFrameBuffer();
|
||||
rtGL->setColorAttachment(RenderTarget::ColorAttachment{ { colorAttachment, 0 } });
|
||||
rtGL->setDepthAttachment(depthAttachment);
|
||||
rtGL->setStencilAttachment(stencilAttachhment);
|
||||
return rtGL;
|
||||
}
|
||||
|
||||
ShaderModule* DeviceMTL::newShaderModule(ShaderStage stage, const std::string& source)
|
||||
{
|
||||
return new (std::nothrow) ShaderModuleMTL(_mtlDevice, stage, source);
|
||||
|
|
|
@ -49,7 +49,7 @@ public:
|
|||
*/
|
||||
RenderPipelineMTL(id<MTLDevice> mtlDevice);
|
||||
~RenderPipelineMTL();
|
||||
virtual void update(const PipelineDescriptor&, const RenderPassDescriptor&) override;
|
||||
virtual void update(const PipelineDescriptor&, const RenderTarget* renderTarget, const RenderPassParams& renderPassParams) override;
|
||||
|
||||
/**
|
||||
* Get a MTLRenderPipelineState object.
|
||||
|
@ -61,14 +61,14 @@ private:
|
|||
void setVertexLayout(MTLRenderPipelineDescriptor*, const PipelineDescriptor&);
|
||||
void setBlendState(MTLRenderPipelineColorAttachmentDescriptor*, const BlendDescriptor&);
|
||||
void setShaderModules(const PipelineDescriptor&);
|
||||
void setBlendStateAndFormat(const BlendDescriptor&, const RenderPassDescriptor&);
|
||||
void getAttachmentFormat(const RenderPassDescriptor&, PixelFormat&, PixelFormat&, PixelFormat&);
|
||||
void setBlendStateAndFormat(const BlendDescriptor&);
|
||||
void getAttachmentFormat(const RenderTarget* renderTarget, const RenderPassParams& renderPassParams, PixelFormat colorAttachmentsFormat[MAX_COLOR_ATTCHMENT], PixelFormat&, PixelFormat&);
|
||||
|
||||
id<MTLRenderPipelineState> _mtlRenderPipelineState = nil;
|
||||
id<MTLDevice> _mtlDevice = nil;
|
||||
|
||||
MTLRenderPipelineDescriptor* _mtlRenderPipelineDescriptor = nil;
|
||||
PixelFormat _colorAttachmentsFormat[MAX_COLOR_ATTCHMENT] = { PixelFormat::DEFAULT };
|
||||
PixelFormat _colorAttachmentsFormat[MAX_COLOR_ATTCHMENT] = { PixelFormat::NONE };
|
||||
PixelFormat _depthAttachmentFormat = PixelFormat::NONE;
|
||||
PixelFormat _stencilAttachmentFormat = PixelFormat::NONE;
|
||||
NSMutableDictionary* _mtlRenderPipelineStateCache = nil;
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include "RenderPipelineMTL.h"
|
||||
#include "DeviceMTL.h"
|
||||
#include "RenderTargetMTL.h"
|
||||
#include "ShaderModuleMTL.h"
|
||||
#include "DepthStencilStateMTL.h"
|
||||
#include "UtilsMTL.h"
|
||||
|
@ -163,14 +164,15 @@ RenderPipelineMTL::RenderPipelineMTL(id<MTLDevice> mtlDevice)
|
|||
}
|
||||
|
||||
void RenderPipelineMTL::update(const PipelineDescriptor & pipelineDescirptor,
|
||||
const RenderPassDescriptor& renderPassDescriptor)
|
||||
const RenderTarget* renderTarget,
|
||||
const RenderPassParams& renderPassParams)
|
||||
{
|
||||
struct
|
||||
{
|
||||
size_t vertexShaderHash;
|
||||
size_t fragmentShaderHash;
|
||||
unsigned int vertexLayoutInfo[32];
|
||||
backend::PixelFormat colorAttachment;
|
||||
backend::PixelFormat colorAttachment[MAX_COLOR_ATTCHMENT];
|
||||
backend::PixelFormat depthAttachment;
|
||||
backend::PixelFormat stencilAttachment;
|
||||
bool blendEnabled;
|
||||
|
@ -185,11 +187,11 @@ void RenderPipelineMTL::update(const PipelineDescriptor & pipelineDescirptor,
|
|||
|
||||
memset(&hashMe, 0, sizeof(hashMe));
|
||||
const auto& blendDescriptor = pipelineDescirptor.blendDescriptor;
|
||||
getAttachmentFormat(renderPassDescriptor, _colorAttachmentsFormat[0], _depthAttachmentFormat, _stencilAttachmentFormat);
|
||||
getAttachmentFormat(renderTarget, renderPassParams, _colorAttachmentsFormat, _depthAttachmentFormat, _stencilAttachmentFormat);
|
||||
auto program = static_cast<ProgramMTL*>(pipelineDescirptor.programState->getProgram());
|
||||
hashMe.vertexShaderHash = program->getVertexShader()->getHashValue();
|
||||
hashMe.fragmentShaderHash = program->getFragmentShader()->getHashValue();
|
||||
hashMe.colorAttachment = _colorAttachmentsFormat[0];
|
||||
memcpy(&hashMe.colorAttachment, &_colorAttachmentsFormat, sizeof(_colorAttachmentsFormat));
|
||||
hashMe.depthAttachment = _depthAttachmentFormat;
|
||||
hashMe.stencilAttachment =_stencilAttachmentFormat;
|
||||
hashMe.blendEnabled = blendDescriptor.blendEnabled;
|
||||
|
@ -232,7 +234,7 @@ void RenderPipelineMTL::update(const PipelineDescriptor & pipelineDescirptor,
|
|||
setShaderModules(pipelineDescirptor);
|
||||
setVertexLayout(_mtlRenderPipelineDescriptor, pipelineDescirptor);
|
||||
|
||||
setBlendStateAndFormat(pipelineDescirptor.blendDescriptor, renderPassDescriptor);
|
||||
setBlendStateAndFormat(pipelineDescirptor.blendDescriptor);
|
||||
|
||||
NSError *error = nil;
|
||||
_mtlRenderPipelineState = [_mtlDevice newRenderPipelineStateWithDescriptor:_mtlRenderPipelineDescriptor error:&error];
|
||||
|
@ -299,43 +301,29 @@ void RenderPipelineMTL::setShaderModules(const PipelineDescriptor& descriptor)
|
|||
_mtlRenderPipelineDescriptor.fragmentFunction = fragShaderModule->getMTLFunction();
|
||||
}
|
||||
|
||||
void RenderPipelineMTL::getAttachmentFormat(const RenderPassDescriptor& descriptor,
|
||||
PixelFormat& colorFormat,
|
||||
void RenderPipelineMTL::getAttachmentFormat(const RenderTarget* renderTarget,
|
||||
const RenderPassParams& params,
|
||||
PixelFormat colorAttachmentsFormat[MAX_COLOR_ATTCHMENT],
|
||||
PixelFormat& depthFormat,
|
||||
PixelFormat& stencilFormat)
|
||||
{
|
||||
if (descriptor.needColorAttachment)
|
||||
{
|
||||
// FIXME: now just handle color attachment 0.
|
||||
if (descriptor.colorAttachmentsTexture[0])
|
||||
colorFormat = descriptor.colorAttachmentsTexture[0]->getTextureFormat();
|
||||
auto rtMTL = static_cast<const RenderTargetMTL*>(renderTarget);
|
||||
auto rtflags = rtMTL->getTargetFlags();
|
||||
for(auto i = 0; i < MAX_COLOR_ATTCHMENT; ++i) {
|
||||
if (bitmask::any(rtflags, getMRTColorFlag(i)))
|
||||
{
|
||||
colorAttachmentsFormat[i] = rtMTL->getColorAttachmentPixelFormat(i);
|
||||
}
|
||||
else
|
||||
colorFormat = PixelFormat::DEFAULT;
|
||||
}
|
||||
else
|
||||
{
|
||||
colorFormat = PixelFormat::DEFAULT;
|
||||
{
|
||||
colorAttachmentsFormat[i] = PixelFormat::NONE;
|
||||
}
|
||||
}
|
||||
|
||||
if (descriptor.needDepthStencilAttachment())
|
||||
if (bitmask::any(rtflags, RenderTargetFlag::DEPTH_AND_STENCIL))
|
||||
{
|
||||
if(descriptor.depthAttachmentTexture)
|
||||
{
|
||||
depthFormat = descriptor.depthAttachmentTexture->getTextureFormat();
|
||||
}
|
||||
else
|
||||
{
|
||||
depthFormat = PixelFormat::D24S8;
|
||||
}
|
||||
|
||||
if (descriptor.stencilAttachmentTexture)
|
||||
{
|
||||
stencilFormat = descriptor.stencilAttachmentTexture->getTextureFormat();
|
||||
}
|
||||
else
|
||||
{
|
||||
stencilFormat = PixelFormat::D24S8;
|
||||
}
|
||||
depthFormat = rtMTL->getDepthAttachmentPixelFormat();
|
||||
stencilFormat =rtMTL->getStencilAttachmentPixelFormat();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -343,13 +331,14 @@ void RenderPipelineMTL::getAttachmentFormat(const RenderPassDescriptor& descript
|
|||
}
|
||||
}
|
||||
|
||||
void RenderPipelineMTL::setBlendStateAndFormat(const BlendDescriptor& blendDescriptor,
|
||||
const RenderPassDescriptor& renderPassDescriptor)
|
||||
void RenderPipelineMTL::setBlendStateAndFormat(const BlendDescriptor& blendDescriptor)
|
||||
{
|
||||
for (int i = 0; i < MAX_COLOR_ATTCHMENT; ++i)
|
||||
{
|
||||
if (PixelFormat::NONE == _colorAttachmentsFormat[i])
|
||||
if (PixelFormat::NONE == _colorAttachmentsFormat[i]) {
|
||||
_mtlRenderPipelineDescriptor.colorAttachments[i].pixelFormat = MTLPixelFormat::MTLPixelFormatInvalid;
|
||||
continue;
|
||||
}
|
||||
|
||||
_mtlRenderPipelineDescriptor.colorAttachments[i].pixelFormat = UtilsMTL::toMTLPixelFormat(_colorAttachmentsFormat[i]);
|
||||
setBlendState(_mtlRenderPipelineDescriptor.colorAttachments[i], blendDescriptor);
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
#pragma once
|
||||
#include "../RenderTarget.h"
|
||||
#include "CommandBufferMTL.h"
|
||||
|
||||
CC_BACKEND_BEGIN
|
||||
|
||||
class RenderTargetMTL : public RenderTarget
|
||||
{
|
||||
public:
|
||||
struct Attachment {
|
||||
id<MTLTexture> texture = nil;
|
||||
int level = 0;
|
||||
explicit operator bool() const {
|
||||
return texture != nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* generateFBO, false, use for screen framebuffer
|
||||
*/
|
||||
RenderTargetMTL(bool defaultRenderTarget);
|
||||
~RenderTargetMTL();
|
||||
|
||||
void bindFrameBuffer() const override;
|
||||
void unbindFrameBuffer() const override;
|
||||
|
||||
void setColorAttachment(ColorAttachment attachment) override;
|
||||
void setDepthAttachment(TextureBackend* attachment, int level = 0) override;
|
||||
void setStencilAttachment(TextureBackend* attachment, int level = 0) override;
|
||||
|
||||
void applyRenderPassAttachments(const RenderPassParams& parmas, MTLRenderPassDescriptor* descriptor) const;
|
||||
|
||||
Attachment getColorAttachment(int index) const;
|
||||
Attachment getDepthAttachment() const;
|
||||
Attachment getStencilAttachment() const;
|
||||
|
||||
PixelFormat getColorAttachmentPixelFormat(int index) const;
|
||||
PixelFormat getDepthAttachmentPixelFormat() const;
|
||||
PixelFormat getStencilAttachmentPixelFormat() const;
|
||||
public:
|
||||
|
||||
// "Sidecar" textures used to implement automatic MSAA resolve.
|
||||
// id<MTLTexture> multisampledColor[MRT::TARGET_COUNT] = { 0 };
|
||||
// id<MTLTexture> multisampledDepth = nil;
|
||||
// MetalContext*, DeviceMTL*
|
||||
};
|
||||
|
||||
CC_BACKEND_END
|
|
@ -0,0 +1,184 @@
|
|||
#include "RenderTargetMTL.h"
|
||||
#include "UtilsMTL.h"
|
||||
|
||||
CC_BACKEND_BEGIN
|
||||
|
||||
static MTLLoadAction getLoadAction(const RenderPassParams& params,
|
||||
TargetBufferFlags buffer) {
|
||||
const auto clearFlags = (TargetBufferFlags) params.flags.clear;
|
||||
const auto discardStartFlags = params.flags.discardStart;
|
||||
if (bitmask::any(clearFlags, buffer)) {
|
||||
return MTLLoadActionClear;
|
||||
} else if (bitmask::any(discardStartFlags, buffer)) {
|
||||
return MTLLoadActionDontCare;
|
||||
}
|
||||
return MTLLoadActionLoad;
|
||||
}
|
||||
|
||||
static MTLStoreAction getStoreAction(const RenderPassParams& params,
|
||||
TargetBufferFlags buffer) {
|
||||
const auto discardEndFlags = params.flags.discardEnd;
|
||||
if (bitmask::any(discardEndFlags, buffer)) {
|
||||
return MTLStoreActionDontCare;
|
||||
}
|
||||
return MTLStoreActionStore;
|
||||
}
|
||||
|
||||
RenderTargetMTL::RenderTargetMTL(bool defaultRenderTarget) : RenderTarget(defaultRenderTarget)
|
||||
{
|
||||
|
||||
}
|
||||
RenderTargetMTL::~RenderTargetMTL()
|
||||
{
|
||||
}
|
||||
|
||||
void RenderTargetMTL::bindFrameBuffer() const
|
||||
{
|
||||
}
|
||||
|
||||
void RenderTargetMTL::unbindFrameBuffer() const
|
||||
{
|
||||
}
|
||||
void RenderTargetMTL::setColorAttachment(ColorAttachment attachment)
|
||||
{
|
||||
RenderTarget::setColorAttachment(attachment);
|
||||
|
||||
|
||||
}
|
||||
|
||||
void RenderTargetMTL::setDepthAttachment(TextureBackend* attachment, int level)
|
||||
{
|
||||
RenderTarget::setDepthAttachment(attachment, level);
|
||||
|
||||
|
||||
}
|
||||
|
||||
void RenderTargetMTL::setStencilAttachment(TextureBackend* attachment, int level)
|
||||
{
|
||||
RenderTarget::setStencilAttachment(attachment, level);
|
||||
|
||||
}
|
||||
|
||||
void RenderTargetMTL::applyRenderPassAttachments(const RenderPassParams& params, MTLRenderPassDescriptor* descriptor) const
|
||||
{
|
||||
const auto discardFlags = params.flags.discardEnd;
|
||||
|
||||
for (size_t i = 0; i < MAX_COLOR_ATTCHMENT; i++) {
|
||||
auto attachment = getColorAttachment(i);
|
||||
if (!attachment) {
|
||||
continue;
|
||||
}
|
||||
|
||||
descriptor.colorAttachments[i].texture = attachment.texture;
|
||||
descriptor.colorAttachments[i].level = attachment.level;
|
||||
// descriptor.colorAttachments[i].slice = attachment.layer;
|
||||
descriptor.colorAttachments[i].loadAction = getLoadAction(params, getMRTColorFlag(i));
|
||||
descriptor.colorAttachments[i].storeAction = getStoreAction(params, getMRTColorFlag(i));
|
||||
descriptor.colorAttachments[i].clearColor = MTLClearColorMake(
|
||||
params.clearColorValue[0], params.clearColorValue[1], params.clearColorValue[2], params.clearColorValue[3]);
|
||||
#if 0
|
||||
if (multisampledColor[i]) {
|
||||
// We're rendering into our temporary MSAA texture and doing an automatic resolve.
|
||||
// We should not be attempting to load anything into the MSAA texture.
|
||||
assert(descriptor.colorAttachments[i].loadAction != MTLLoadActionLoad);
|
||||
|
||||
descriptor.colorAttachments[i].texture = multisampledColor[i];
|
||||
descriptor.colorAttachments[i].level = 0;
|
||||
descriptor.colorAttachments[i].slice = 0;
|
||||
const bool discard = any(discardFlags & getMRTColorFlag(i));
|
||||
if (!discard) {
|
||||
descriptor.colorAttachments[i].resolveTexture = attachment.texture;
|
||||
descriptor.colorAttachments[i].resolveLevel = attachment.level;
|
||||
descriptor.colorAttachments[i].resolveSlice = attachment.layer;
|
||||
descriptor.colorAttachments[i].storeAction = MTLStoreActionMultisampleResolve;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
auto depthAttachment = getDepthAttachment();
|
||||
if(depthAttachment){
|
||||
descriptor.depthAttachment.texture = depthAttachment.texture;
|
||||
descriptor.depthAttachment.level = depthAttachment.level;
|
||||
// descriptor.depthAttachment.slice = depthAttachment.layer;
|
||||
descriptor.depthAttachment.loadAction = getLoadAction(params, TargetBufferFlags::DEPTH);
|
||||
descriptor.depthAttachment.storeAction = getStoreAction(params, TargetBufferFlags::DEPTH);
|
||||
descriptor.depthAttachment.clearDepth = params.clearDepthValue;
|
||||
}
|
||||
|
||||
auto stencilAttachment = getStencilAttachment();
|
||||
if(stencilAttachment) {
|
||||
descriptor.stencilAttachment.texture = stencilAttachment.texture;
|
||||
descriptor.stencilAttachment.level = depthAttachment.level;
|
||||
// descriptor.stencilAttachment.slice = depthAttachment.layer;
|
||||
descriptor.stencilAttachment.loadAction = getLoadAction(params, TargetBufferFlags::STENCIL);
|
||||
descriptor.stencilAttachment.storeAction = getStoreAction(params, TargetBufferFlags::STENCIL);
|
||||
descriptor.stencilAttachment.clearStencil= params.clearStencilValue;
|
||||
}
|
||||
#if 0
|
||||
if (multisampledDepth) {
|
||||
// We're rendering into our temporary MSAA texture and doing an automatic resolve.
|
||||
// We should not be attempting to load anything into the MSAA texture.
|
||||
assert(descriptor.depthAttachment.loadAction != MTLLoadActionLoad);
|
||||
|
||||
descriptor.depthAttachment.texture = multisampledDepth;
|
||||
descriptor.depthAttachment.level = 0;
|
||||
descriptor.depthAttachment.slice = 0;
|
||||
const bool discard = any(discardFlags & TargetBufferFlags::DEPTH);
|
||||
if (!discard) {
|
||||
descriptor.depthAttachment.resolveTexture = depthAttachment.texture;
|
||||
descriptor.depthAttachment.resolveLevel = depthAttachment.level;
|
||||
descriptor.depthAttachment.resolveSlice = depthAttachment.layer;
|
||||
descriptor.depthAttachment.storeAction = MTLStoreActionMultisampleResolve;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
RenderTargetMTL::Attachment RenderTargetMTL::getColorAttachment(int index) const
|
||||
{
|
||||
if(isDefaultRenderTarget() && index == 0)
|
||||
return {DeviceMTL::getCurrentDrawable().texture, 0};
|
||||
auto& rb = this->_color[index];
|
||||
return RenderTargetMTL::Attachment{static_cast<bool>(rb) ? (id<MTLTexture>)(rb.texture->getHandler()) : nil, rb.level};
|
||||
}
|
||||
|
||||
RenderTargetMTL::Attachment RenderTargetMTL::getDepthAttachment() const
|
||||
{
|
||||
if(isDefaultRenderTarget())
|
||||
return {UtilsMTL::getDefaultDepthStencilTexture(), 0};
|
||||
auto& rb = this->_depth;
|
||||
return RenderTargetMTL::Attachment{!!rb ? (id<MTLTexture>)(rb.texture->getHandler()) : nil, rb.level};
|
||||
}
|
||||
|
||||
RenderTargetMTL::Attachment RenderTargetMTL::getStencilAttachment() const
|
||||
{
|
||||
if(isDefaultRenderTarget())
|
||||
return {UtilsMTL::getDefaultDepthStencilTexture(), 0};
|
||||
auto& rb = this->_stencil;
|
||||
return RenderTargetMTL::Attachment{!!rb ? (id<MTLTexture>)(rb.texture->getHandler()) : nil, rb.level};
|
||||
}
|
||||
|
||||
PixelFormat RenderTargetMTL::getColorAttachmentPixelFormat(int index) const
|
||||
{
|
||||
if(isDefaultRenderTarget() && index == 0)
|
||||
return PixelFormat::DEFAULT;
|
||||
auto& rb = this->_color[index];
|
||||
return rb ? rb.texture->getTextureFormat() : PixelFormat::NONE;
|
||||
}
|
||||
|
||||
PixelFormat RenderTargetMTL::getDepthAttachmentPixelFormat() const
|
||||
{ // FIXME: egnx only support D24S8
|
||||
if(isDefaultRenderTarget() || !_depth)
|
||||
return PixelFormat::D24S8;
|
||||
return _depth.texture->getTextureFormat();
|
||||
}
|
||||
|
||||
PixelFormat RenderTargetMTL::getStencilAttachmentPixelFormat() const
|
||||
{ // FIXME: egnx only support D24S8
|
||||
if(isDefaultRenderTarget() || !_stencil)
|
||||
return PixelFormat::D24S8;
|
||||
return _stencil.texture->getTextureFormat();
|
||||
}
|
||||
|
||||
CC_BACKEND_END
|
|
@ -147,10 +147,12 @@ public:
|
|||
int getCount() const override { return _textureInfo._maxIdx + 1; }
|
||||
|
||||
/**
|
||||
* Get MTLTexture object.
|
||||
* Get MTLTexture object. reinterpret_cast<id<MTLTexture>>(handler);
|
||||
* @return A MTLTexture object.
|
||||
*/
|
||||
inline id<MTLTexture> getMTLTexture(int index = 0) const { return _textureInfo._mtlTextures[index]; }
|
||||
uintptr_t getHandler(int index = 0) const override {
|
||||
return reinterpret_cast<uintptr_t>((void*)_textureInfo._mtlTextures[index]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get MTLSamplerState object
|
||||
|
@ -201,13 +203,11 @@ public:
|
|||
virtual void updateTextureDescriptor(const cocos2d::backend::TextureDescriptor &descriptor, int index = 0) override;
|
||||
|
||||
int getCount() const override { return _textureInfo._maxIdx + 1; }
|
||||
|
||||
/**
|
||||
* Get MTLTexture object.
|
||||
* @return A MTLTexture object.
|
||||
*/
|
||||
inline id<MTLTexture> getMTLTexture(int index = 0) const { return _textureInfo._mtlTextures[index]; }
|
||||
|
||||
uintptr_t getHandler(int index = 0) const override {
|
||||
return reinterpret_cast<uintptr_t>((void*)_textureInfo._mtlTextures[index]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get MTLSamplerState object
|
||||
* @return A MTLSamplerState object.
|
||||
|
|
|
@ -194,7 +194,8 @@ namespace
|
|||
return bytesPerRow;
|
||||
}
|
||||
|
||||
std::size_t getBytesPerRow(PixelFormat textureFormat, std::size_t width, std::size_t bitsPerElement)
|
||||
// TODO: tidy APIs, compression pixelFormat and non-compression pixelFormat
|
||||
std::size_t getBytesPerRowMTL(PixelFormat textureFormat, std::size_t width, std::size_t bitsPerElement)
|
||||
{
|
||||
MTLPixelFormat pixelFormat = UtilsMTL::toMTLPixelFormat(textureFormat);
|
||||
std::size_t bytesPerRow = 0;
|
||||
|
@ -361,7 +362,7 @@ void TextureMTL::updateSubData(std::size_t xoffset, std::size_t yoffset, std::si
|
|||
width * height,
|
||||
_textureFormat, &convertedData);
|
||||
|
||||
std::size_t bytesPerRow = getBytesPerRow(_textureFormat, width, _bitsPerElement);
|
||||
std::size_t bytesPerRow = getBytesPerRowMTL(_textureFormat, width, _bitsPerElement);
|
||||
|
||||
[mtlTexture replaceRegion:region
|
||||
mipmapLevel:level
|
||||
|
@ -393,7 +394,7 @@ void TextureMTL::generateMipmaps()
|
|||
if(!_hasMipmaps)
|
||||
{
|
||||
_hasMipmaps = true;
|
||||
UtilsMTL::generateMipmaps(this->getMTLTexture());
|
||||
UtilsMTL::generateMipmaps(reinterpret_cast<id<MTLTexture>>(this->getHandler()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -454,7 +455,7 @@ void TextureCubeMTL::generateMipmaps()
|
|||
if(!_hasMipmaps)
|
||||
{
|
||||
_hasMipmaps = true;
|
||||
UtilsMTL::generateMipmaps(this->getMTLTexture());
|
||||
UtilsMTL::generateMipmaps(reinterpret_cast<id<MTLTexture>>(this->getHandler()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -83,18 +83,7 @@ struct UtilsMTL
|
|||
* @param texture Specifies a texture to generate mipmap.
|
||||
*/
|
||||
static void generateMipmaps(id<MTLTexture> texture);
|
||||
|
||||
/**
|
||||
* Read a block of pixels from the given texture
|
||||
* @param texture Specifies the texture to get the image.
|
||||
* @param origX,origY Specify the window coordinates of the first pixel that is read from the given texture. This location is the lower left corner of a rectangular block of pixels.
|
||||
* @param rectWidth,rectHeight Specify the dimensions of the pixel rectangle. rectWidth and rectHeight of one correspond to a single pixel.
|
||||
* @param pbd, the output buffer for fill texels data
|
||||
* @remark: !!!this function only can call after endFrame, then it's could be works well.
|
||||
*/
|
||||
static void readPixels(TextureBackend* texture, std::size_t origX, std::size_t origY, std::size_t rectWidth, std::size_t rectHeight, PixelBufferDescriptor& pbd);
|
||||
static void readPixels(id<MTLTexture> texture, std::size_t origX, std::size_t origY, std::size_t rectWidth, std::size_t rectHeight, PixelBufferDescriptor& pbd);
|
||||
|
||||
|
||||
/**
|
||||
* Swizzle the iamge form the given format to MTLPixelFormatRGBA8Unorm.
|
||||
* @param image Specifies the image to be swizzled.
|
||||
|
|
|
@ -36,39 +36,6 @@ id<MTLTexture> UtilsMTL::_defaultColorAttachmentTexture = nil;
|
|||
id<MTLTexture> UtilsMTL::_defaultDepthStencilAttachmentTexture = nil;
|
||||
|
||||
namespace {
|
||||
#define byte(n) ((n) * 8)
|
||||
#define bit(n) (n)
|
||||
|
||||
uint8_t getBitsPerElement(MTLPixelFormat pixleFormat)
|
||||
{
|
||||
switch (pixleFormat)
|
||||
{
|
||||
case MTLPixelFormatDepth32Float_Stencil8:
|
||||
return byte(8);
|
||||
case MTLPixelFormatBGRA8Unorm:
|
||||
case MTLPixelFormatRGBA8Unorm:
|
||||
case MTLPixelFormatDepth32Float:
|
||||
return byte(4);
|
||||
#if (CC_TARGET_PLATFORM == CC_PLATFORM_MAC)
|
||||
case MTLPixelFormatDepth24Unorm_Stencil8:
|
||||
return byte(4);
|
||||
#else
|
||||
case MTLPixelFormatABGR4Unorm:
|
||||
case MTLPixelFormatBGR5A1Unorm:
|
||||
case MTLPixelFormatB5G6R5Unorm:
|
||||
case MTLPixelFormatA1BGR5Unorm:
|
||||
return byte(2);
|
||||
#endif
|
||||
case MTLPixelFormatA8Unorm:
|
||||
case MTLPixelFormatR8Unorm:
|
||||
return byte(1);
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
MTLPixelFormat getSupportedDepthStencilFormat()
|
||||
{
|
||||
MTLPixelFormat pixelFormat = MTLPixelFormatDepth32Float_Stencil8;
|
||||
|
@ -217,59 +184,4 @@ void UtilsMTL::swizzleImage(unsigned char *image, std::size_t width, std::size_t
|
|||
}
|
||||
}
|
||||
|
||||
void UtilsMTL::readPixels(TextureBackend* texture, std::size_t origX, std::size_t origY, std::size_t rectWidth, std::size_t rectHeight, PixelBufferDescriptor& pbd)
|
||||
{
|
||||
switch(texture->getTextureType()){
|
||||
case TextureType::TEXTURE_2D:
|
||||
UtilsMTL::readPixels(static_cast<TextureMTL*>(texture)->getMTLTexture(), origX, origY, rectWidth, rectHeight, pbd);
|
||||
break;
|
||||
case TextureType::TEXTURE_CUBE:
|
||||
UtilsMTL::readPixels(static_cast<TextureCubeMTL*>(texture)->getMTLTexture(), origX, origY, rectWidth, rectHeight, pbd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void UtilsMTL::readPixels(id<MTLTexture> texture, std::size_t origX, std::size_t origY, std::size_t rectWidth, std::size_t rectHeight, PixelBufferDescriptor& pbd)
|
||||
{
|
||||
NSUInteger texWidth = texture.width;
|
||||
NSUInteger texHeight = texture.height;
|
||||
MTLRegion region = MTLRegionMake2D(0, 0, texWidth, texHeight);
|
||||
MTLRegion imageRegion = MTLRegionMake2D(origX, origY, rectWidth, rectHeight);
|
||||
|
||||
MTLTextureDescriptor* textureDescriptor =
|
||||
[MTLTextureDescriptor texture2DDescriptorWithPixelFormat:[texture pixelFormat]
|
||||
width:texWidth
|
||||
height:texHeight
|
||||
mipmapped:NO];
|
||||
id<MTLDevice> device = static_cast<DeviceMTL*>(DeviceMTL::getInstance())->getMTLDevice();
|
||||
id<MTLTexture> readPixelsTexture = [device newTextureWithDescriptor:textureDescriptor];
|
||||
|
||||
id<MTLCommandQueue> commandQueue = static_cast<DeviceMTL*>(DeviceMTL::getInstance())->getMTLCommandQueue();
|
||||
auto commandBuffer = [commandQueue commandBuffer];
|
||||
// [commandBuffer enqueue];
|
||||
|
||||
id<MTLBlitCommandEncoder> blitCommandEncoder = [commandBuffer blitCommandEncoder];
|
||||
[blitCommandEncoder copyFromTexture:texture sourceSlice:0 sourceLevel:0 sourceOrigin:region.origin sourceSize:region.size toTexture:readPixelsTexture destinationSlice:0 destinationLevel:0 destinationOrigin:region.origin];
|
||||
|
||||
#if (CC_TARGET_PLATFORM == CC_PLATFORM_MAC)
|
||||
[blitCommandEncoder synchronizeResource:readPixelsTexture];
|
||||
#endif
|
||||
[blitCommandEncoder endEncoding];
|
||||
|
||||
[commandBuffer addCompletedHandler:^(id<MTLCommandBuffer> commandBufferMTL) {
|
||||
auto bytePerRow = rectWidth * getBitsPerElement(texture.pixelFormat) / 8;
|
||||
auto texelData = pbd._data.resize(bytePerRow * rectHeight);
|
||||
if(texelData != nullptr)
|
||||
{
|
||||
[readPixelsTexture getBytes:texelData bytesPerRow:bytePerRow fromRegion:imageRegion mipmapLevel:0];
|
||||
swizzleImage(texelData, rectWidth, rectHeight, readPixelsTexture.pixelFormat);
|
||||
pbd._width = rectWidth;
|
||||
pbd._height = rectHeight;
|
||||
}
|
||||
[readPixelsTexture release];
|
||||
}];
|
||||
[commandBuffer commit];
|
||||
[commandBuffer waitUntilCompleted];
|
||||
}
|
||||
|
||||
CC_BACKEND_END
|
||||
|
|
|
@ -33,27 +33,13 @@
|
|||
#include "base/CCEventType.h"
|
||||
#include "base/CCDirector.h"
|
||||
#include "renderer/backend/opengl/UtilsGL.h"
|
||||
#include "RenderTargetGL.h"
|
||||
#include <algorithm>
|
||||
|
||||
CC_BACKEND_BEGIN
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
GLuint getHandler(TextureBackend *texture)
|
||||
{
|
||||
switch (texture->getTextureType())
|
||||
{
|
||||
case TextureType::TEXTURE_2D:
|
||||
return static_cast<Texture2DGL*>(texture)->getHandler();
|
||||
case TextureType::TEXTURE_CUBE:
|
||||
return static_cast<TextureCubeGL*>(texture)->getHandler();
|
||||
default:
|
||||
assert(false);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void applyTexture(TextureBackend* texture, int slot, int index)
|
||||
{
|
||||
switch (texture->getTextureType())
|
||||
|
@ -101,199 +87,66 @@ void CommandBufferGL::beginFrame()
|
|||
{
|
||||
}
|
||||
|
||||
void CommandBufferGL::beginRenderPass(const RenderPassDescriptor& descirptor)
|
||||
void CommandBufferGL::beginRenderPass(const RenderTarget* rt, const RenderPassParams& descirptor)
|
||||
{
|
||||
applyRenderPassDescriptor(descirptor);
|
||||
}
|
||||
|
||||
void CommandBufferGL::applyRenderPassDescriptor(const RenderPassDescriptor& descirptor)
|
||||
{
|
||||
bool useColorAttachmentExternal = descirptor.needColorAttachment && descirptor.colorAttachmentsTexture[0];
|
||||
bool useDepthAttachmentExternal = descirptor.depthTestEnabled && descirptor.depthAttachmentTexture;
|
||||
bool useStencilAttachmentExternal = descirptor.stencilTestEnabled && descirptor.stencilAttachmentTexture;
|
||||
bool useGeneratedFBO = false;
|
||||
if (useColorAttachmentExternal || useDepthAttachmentExternal || useStencilAttachmentExternal)
|
||||
{
|
||||
if(_generatedFBO == 0)
|
||||
{
|
||||
glGenFramebuffers(1, &_generatedFBO);
|
||||
}
|
||||
_currentFBO = _generatedFBO;
|
||||
useGeneratedFBO = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
_currentFBO = _defaultFBO;
|
||||
}
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, _currentFBO);
|
||||
auto rtGL = static_cast<const RenderTargetGL*>(rt);
|
||||
|
||||
if (useDepthAttachmentExternal)
|
||||
{
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER,
|
||||
GL_DEPTH_ATTACHMENT,
|
||||
GL_TEXTURE_2D,
|
||||
getHandler(descirptor.depthAttachmentTexture),
|
||||
0);
|
||||
CHECK_GL_ERROR_DEBUG();
|
||||
rtGL->bindFrameBuffer();
|
||||
|
||||
auto clearFlags = descirptor.flags.clear;
|
||||
|
||||
_generatedFBOBindDepth = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_generatedFBOBindDepth && useGeneratedFBO)
|
||||
{
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER,
|
||||
GL_DEPTH_ATTACHMENT,
|
||||
GL_TEXTURE_2D,
|
||||
0,
|
||||
0);
|
||||
CHECK_GL_ERROR_DEBUG();
|
||||
|
||||
_generatedFBOBindDepth = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (useStencilAttachmentExternal)
|
||||
{
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER,
|
||||
GL_STENCIL_ATTACHMENT,
|
||||
GL_TEXTURE_2D,
|
||||
getHandler(descirptor.stencilAttachmentTexture),
|
||||
0);
|
||||
CHECK_GL_ERROR_DEBUG();
|
||||
|
||||
_generatedFBOBindStencil = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_generatedFBOBindStencil && useGeneratedFBO)
|
||||
{
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER,
|
||||
GL_STENCIL_ATTACHMENT,
|
||||
GL_TEXTURE_2D,
|
||||
0,
|
||||
0);
|
||||
CHECK_GL_ERROR_DEBUG();
|
||||
|
||||
_generatedFBOBindStencil = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (descirptor.needColorAttachment)
|
||||
{
|
||||
int i = 0;
|
||||
for (const auto& texture : descirptor.colorAttachmentsTexture)
|
||||
{
|
||||
if (texture)
|
||||
{
|
||||
// TODO: support texture cube
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER,
|
||||
GL_COLOR_ATTACHMENT0 + i,
|
||||
GL_TEXTURE_2D,
|
||||
getHandler(texture),
|
||||
0);
|
||||
}
|
||||
CHECK_GL_ERROR_DEBUG();
|
||||
++i;
|
||||
}
|
||||
|
||||
if (useGeneratedFBO)
|
||||
_generatedFBOBindColor = true;
|
||||
|
||||
#if CC_TARGET_PLATFORM == CC_PLATFORM_WIN32 || CC_TARGET_PLATFORM == CC_PLATFORM_LINUX
|
||||
if (_framebufferReadWriteDisabled)
|
||||
{
|
||||
if (useGeneratedFBO) //user-defined framebuffer
|
||||
{
|
||||
glDrawBuffer(GL_COLOR_ATTACHMENT0);
|
||||
glReadBuffer(GL_COLOR_ATTACHMENT0);
|
||||
}
|
||||
else //default framebuffer
|
||||
{
|
||||
glDrawBuffer(GL_BACK);
|
||||
glReadBuffer(GL_BACK);
|
||||
}
|
||||
_framebufferReadWriteDisabled = false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_generatedFBOBindColor && useGeneratedFBO)
|
||||
{
|
||||
// FIXME: Now only support attaching to attachment 0.
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER,
|
||||
GL_COLOR_ATTACHMENT0,
|
||||
GL_TEXTURE_2D,
|
||||
0,
|
||||
0);
|
||||
|
||||
_generatedFBOBindColor = false;
|
||||
}
|
||||
|
||||
// If not draw buffer is needed, should invoke this line explicitly, or it will cause
|
||||
// GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER and GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER error.
|
||||
// https://stackoverflow.com/questions/28313782/porting-opengl-es-framebuffer-to-opengl
|
||||
#if CC_TARGET_PLATFORM == CC_PLATFORM_WIN32 || CC_TARGET_PLATFORM == CC_PLATFORM_LINUX
|
||||
glDrawBuffer(GL_NONE);
|
||||
glReadBuffer(GL_NONE);
|
||||
_framebufferReadWriteDisabled = true;
|
||||
#endif
|
||||
}
|
||||
CHECK_GL_ERROR_DEBUG();
|
||||
|
||||
// set clear color, depth and stencil
|
||||
GLbitfield mask = 0;
|
||||
if (descirptor.needClearColor)
|
||||
if (bitmask::any(clearFlags, TargetBufferFlags::COLOR))
|
||||
{
|
||||
mask |= GL_COLOR_BUFFER_BIT;
|
||||
const auto& clearColor = descirptor.clearColorValue;
|
||||
glClearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
|
||||
}
|
||||
|
||||
|
||||
CHECK_GL_ERROR_DEBUG();
|
||||
|
||||
|
||||
GLboolean oldDepthWrite = GL_FALSE;
|
||||
GLboolean oldDepthTest = GL_FALSE;
|
||||
GLfloat oldDepthClearValue = 0.f;
|
||||
GLint oldDepthFunc = GL_LESS;
|
||||
if (descirptor.needClearDepth)
|
||||
if (bitmask::any(clearFlags, TargetBufferFlags::DEPTH))
|
||||
{
|
||||
glGetBooleanv(GL_DEPTH_WRITEMASK, &oldDepthWrite);
|
||||
glGetBooleanv(GL_DEPTH_TEST, &oldDepthTest);
|
||||
glGetFloatv(GL_DEPTH_CLEAR_VALUE, &oldDepthClearValue);
|
||||
glGetIntegerv(GL_DEPTH_FUNC, &oldDepthFunc);
|
||||
|
||||
|
||||
mask |= GL_DEPTH_BUFFER_BIT;
|
||||
glClearDepth(descirptor.clearDepthValue);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthMask(GL_TRUE);
|
||||
glDepthFunc(GL_ALWAYS);
|
||||
}
|
||||
|
||||
|
||||
CHECK_GL_ERROR_DEBUG();
|
||||
|
||||
if (descirptor.needClearStencil)
|
||||
|
||||
if (bitmask::any(clearFlags, TargetBufferFlags::STENCIL))
|
||||
{
|
||||
mask |= GL_STENCIL_BUFFER_BIT;
|
||||
glClearStencil(descirptor.clearStencilValue);
|
||||
}
|
||||
|
||||
if(mask) glClear(mask);
|
||||
|
||||
if (mask) glClear(mask);
|
||||
|
||||
CHECK_GL_ERROR_DEBUG();
|
||||
|
||||
|
||||
// restore depth test
|
||||
if (descirptor.needClearDepth)
|
||||
if (bitmask::any(clearFlags, TargetBufferFlags::DEPTH))
|
||||
{
|
||||
if (!oldDepthTest)
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
|
||||
|
||||
glDepthMask(oldDepthWrite);
|
||||
glDepthFunc(oldDepthFunc);
|
||||
glClearDepth(oldDepthClearValue);
|
||||
}
|
||||
|
||||
|
||||
CHECK_GL_ERROR_DEBUG();
|
||||
}
|
||||
|
||||
|
@ -379,7 +232,6 @@ void CommandBufferGL::endRenderPass()
|
|||
|
||||
void CommandBufferGL::endFrame()
|
||||
{
|
||||
// executeGpuCommandsCompleteOps();
|
||||
}
|
||||
|
||||
void CommandBufferGL::setDepthStencilState(DepthStencilState* depthStencilState)
|
||||
|
@ -630,14 +482,64 @@ void CommandBufferGL::setScissorRect(bool isEnabled, float x, float y, float wid
|
|||
}
|
||||
}
|
||||
|
||||
void CommandBufferGL::capture(TextureBackend* texture, std::function<void(const PixelBufferDescriptor&)> callback)
|
||||
void CommandBufferGL::readPixels(RenderTarget* rt, std::function<void(const PixelBufferDescriptor&)> callback)
|
||||
{
|
||||
PixelBufferDescriptor pbd;
|
||||
if (!texture)
|
||||
UtilsGL::readPixels(nullptr, _viewPort.x, _viewPort.y, _viewPort.w, _viewPort.h, pbd);
|
||||
else
|
||||
UtilsGL::readPixels(texture, 0, 0, texture->getWidth(), texture->getHeight(), pbd);
|
||||
if(rt->isDefaultRenderTarget())
|
||||
{ // read pixels from screen
|
||||
readPixels(rt, _viewPort.x, _viewPort.y, _viewPort.w, _viewPort.h, _viewPort.w * 4, pbd);
|
||||
}
|
||||
else {
|
||||
// we only readPixels from the COLOR0 attachment.
|
||||
auto colorAttachment = rt->_color[0].texture;
|
||||
if(colorAttachment) {
|
||||
readPixels(rt, 0, 0, colorAttachment->getWidth(),colorAttachment->getHeight(), colorAttachment->getBytesPerRow(), pbd);
|
||||
}
|
||||
}
|
||||
callback(pbd);
|
||||
}
|
||||
|
||||
void CommandBufferGL::readPixels(RenderTarget* rt, int x, int y, uint32_t width, uint32_t height, uint32_t bytesPerRow, PixelBufferDescriptor& pbd)
|
||||
{
|
||||
rt->bindFrameBuffer();
|
||||
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
||||
|
||||
auto bufferSize = bytesPerRow * height;
|
||||
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32 && defined(GL_ES_VERSION_3_0)) || \
|
||||
(CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID && defined(GL_PIXEL_PACK_BUFFER))
|
||||
GLuint pbo;
|
||||
glGenBuffers(1, &pbo);
|
||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo);
|
||||
glBufferData(GL_PIXEL_PACK_BUFFER, bufferSize, nullptr, GL_STATIC_DRAW);
|
||||
glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
||||
auto buffer = (uint8_t*)glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, bufferSize, GL_MAP_READ_BIT);
|
||||
#else
|
||||
std::unique_ptr<uint8_t[]> bufferStorage(new uint8_t[bufferSize]);
|
||||
auto buffer = bufferStorage.get();
|
||||
memset(buffer, 0, bufferSize);
|
||||
glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
|
||||
#endif
|
||||
uint8_t* wptr = nullptr;
|
||||
if (buffer && (wptr = pbd._data.resize(bufferSize))) {
|
||||
auto rptr = buffer + (height - 1) * bytesPerRow;
|
||||
for (int row = 0; row < height; ++row) {
|
||||
memcpy(wptr, rptr, bytesPerRow);
|
||||
wptr += bytesPerRow;
|
||||
rptr -= bytesPerRow;
|
||||
}
|
||||
pbd._width = width;
|
||||
pbd._height = height;
|
||||
}
|
||||
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32 && defined(GL_ES_VERSION_3_0)) || \
|
||||
(CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID && defined(GL_PIXEL_PACK_BUFFER))
|
||||
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
|
||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
||||
glDeleteBuffers(1, &pbo);
|
||||
#endif
|
||||
|
||||
if (!rt->isDefaultRenderTarget())
|
||||
rt->unbindFrameBuffer();
|
||||
}
|
||||
|
||||
CC_BACKEND_END
|
||||
|
|
|
@ -65,7 +65,7 @@ public:
|
|||
* Begin a render pass, initial color, depth and stencil attachment.
|
||||
* @param descriptor Specifies a group of render targets that hold the results of a render pass.
|
||||
*/
|
||||
virtual void beginRenderPass(const RenderPassDescriptor& descriptor) override;
|
||||
virtual void beginRenderPass(const RenderTarget* rt, const RenderPassParams& descriptor) override;
|
||||
|
||||
/**
|
||||
* Sets the current render pipeline state object.
|
||||
|
@ -167,7 +167,10 @@ public:
|
|||
* Get a screen snapshot
|
||||
* @param callback A callback to deal with screen snapshot image.
|
||||
*/
|
||||
virtual void capture(TextureBackend* texture, std::function<void(const PixelBufferDescriptor&)> callback) override;
|
||||
virtual void readPixels(RenderTarget* rt, std::function<void(const PixelBufferDescriptor&)> callback) override;
|
||||
|
||||
protected:
|
||||
void readPixels(RenderTarget* rt, int x, int y, uint32_t width, uint32_t height, uint32_t bytesPerRow, PixelBufferDescriptor& pbd);
|
||||
|
||||
private:
|
||||
struct Viewport
|
||||
|
@ -183,7 +186,6 @@ private:
|
|||
void setUniforms(ProgramGL* program) const;
|
||||
void setUniform(bool isArray, GLuint location, unsigned int size, GLenum uniformType, void* data) const;
|
||||
void cleanResources();
|
||||
void applyRenderPassDescriptor(const RenderPassDescriptor& descirptor);
|
||||
|
||||
// The frame buffer generated by engine. All frame buffer other than default frame buffer share it.
|
||||
GLuint _generatedFBO = 0;
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "DepthStencilStateGL.h"
|
||||
#include "ProgramGL.h"
|
||||
#include "DeviceInfoGL.h"
|
||||
#include "RenderTargetGL.h"
|
||||
|
||||
CC_BACKEND_BEGIN
|
||||
|
||||
|
@ -82,6 +83,27 @@ TextureBackend* DeviceGL::newTexture(const TextureDescriptor& descriptor)
|
|||
}
|
||||
}
|
||||
|
||||
RenderTarget* DeviceGL::newDefaultRenderTarget(TargetBufferFlags rtf)
|
||||
{
|
||||
auto rtGL = new RenderTargetGL(true);
|
||||
rtGL->setTargetFlags(rtf);
|
||||
return rtGL;
|
||||
}
|
||||
|
||||
RenderTarget* DeviceGL::newRenderTarget(TargetBufferFlags rtf,
|
||||
TextureBackend* colorAttachment,
|
||||
TextureBackend* depthAttachment,
|
||||
TextureBackend* stencilAttachhment)
|
||||
{
|
||||
auto rtGL = new RenderTargetGL(false);
|
||||
rtGL->setTargetFlags(rtf);
|
||||
rtGL->bindFrameBuffer();
|
||||
rtGL->setColorAttachment({ RenderTarget::ColorAttachment{ {colorAttachment, 0} } });
|
||||
rtGL->setDepthAttachment(depthAttachment);
|
||||
rtGL->setStencilAttachment(stencilAttachhment);
|
||||
return rtGL;
|
||||
}
|
||||
|
||||
ShaderModule* DeviceGL::newShaderModule(ShaderStage stage, const std::string& source)
|
||||
{
|
||||
return new (std::nothrow) ShaderModuleGL(stage, source);
|
||||
|
|
|
@ -61,6 +61,12 @@ public:
|
|||
*/
|
||||
virtual TextureBackend* newTexture(const TextureDescriptor& descriptor) override;
|
||||
|
||||
RenderTarget* newDefaultRenderTarget(TargetBufferFlags rtf) override;
|
||||
RenderTarget* newRenderTarget(TargetBufferFlags rtf,
|
||||
TextureBackend* colorAttachment,
|
||||
TextureBackend* depthAttachment,
|
||||
TextureBackend* stencilAttachhment) override;
|
||||
|
||||
/**
|
||||
* Create an auto released DepthStencilState object.
|
||||
* @param descriptor Specifies depth and stencil description.
|
||||
|
|
|
@ -33,7 +33,7 @@ Copyright (c) 2020 c4games.com.
|
|||
|
||||
CC_BACKEND_BEGIN
|
||||
|
||||
void RenderPipelineGL::update(const PipelineDescriptor& pipelineDescirptor, const RenderPassDescriptor& renderpassDescriptor)
|
||||
void RenderPipelineGL::update(const PipelineDescriptor& pipelineDescirptor, const RenderTarget*, const RenderPassParams&)
|
||||
{
|
||||
if(_programGL != pipelineDescirptor.programState->getProgram())
|
||||
{
|
||||
|
@ -54,10 +54,10 @@ void RenderPipelineGL::updateBlendState(const BlendDescriptor& descriptor)
|
|||
auto destinationRGBBlendFactor = UtilsGL::toGLBlendFactor(descriptor.destinationRGBBlendFactor);
|
||||
auto sourceAlphaBlendFactor = UtilsGL::toGLBlendFactor(descriptor.sourceAlphaBlendFactor);
|
||||
auto destinationAlphaBlendFactor = UtilsGL::toGLBlendFactor(descriptor.destinationAlphaBlendFactor);
|
||||
GLboolean writeMaskRed = _Bitmask_includes(descriptor.writeMask, ColorWriteMask::RED);
|
||||
GLboolean writeMaskGreen = _Bitmask_includes(descriptor.writeMask, ColorWriteMask::GREEN);
|
||||
GLboolean writeMaskBlue = _Bitmask_includes(descriptor.writeMask, ColorWriteMask::BLUE);
|
||||
GLboolean writeMaskAlpha = _Bitmask_includes(descriptor.writeMask, ColorWriteMask::ALPHA);
|
||||
GLboolean writeMaskRed = bitmask::any(descriptor.writeMask, ColorWriteMask::RED);
|
||||
GLboolean writeMaskGreen = bitmask::any(descriptor.writeMask, ColorWriteMask::GREEN);
|
||||
GLboolean writeMaskBlue = bitmask::any(descriptor.writeMask, ColorWriteMask::BLUE);
|
||||
GLboolean writeMaskAlpha = bitmask::any(descriptor.writeMask, ColorWriteMask::ALPHA);
|
||||
|
||||
if (blendEnabled)
|
||||
{
|
||||
|
|
|
@ -51,7 +51,7 @@ public:
|
|||
RenderPipelineGL() = default;
|
||||
~RenderPipelineGL();
|
||||
|
||||
virtual void update(const PipelineDescriptor & pipelineDescirptor, const RenderPassDescriptor& renderpassDescriptor) override;
|
||||
virtual void update(const PipelineDescriptor & pipelineDescirptor, const RenderTarget* renderTarget, const RenderPassParams& renderParams) override;
|
||||
/**
|
||||
* Get program instance.
|
||||
* @return Program instance.
|
||||
|
|
|
@ -0,0 +1,109 @@
|
|||
#include "RenderTargetGL.h"
|
||||
#include "base/ccMacros.h"
|
||||
|
||||
CC_BACKEND_BEGIN
|
||||
|
||||
RenderTargetGL::RenderTargetGL(bool defaultRenderTarget) : RenderTarget(defaultRenderTarget)
|
||||
{
|
||||
if (!defaultRenderTarget) {
|
||||
glGenFramebuffers(1, &_FBO);
|
||||
}
|
||||
else {
|
||||
_FBO = 0;
|
||||
}
|
||||
}
|
||||
RenderTargetGL::~RenderTargetGL()
|
||||
{
|
||||
if (!_defaultRenderTarget) {
|
||||
bindFrameBuffer();
|
||||
|
||||
for (auto slot = 0; slot < MAX_COLOR_ATTCHMENT; ++slot)
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER,
|
||||
GL_COLOR_ATTACHMENT0 + slot,
|
||||
GL_TEXTURE_2D,
|
||||
0,
|
||||
0);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER,
|
||||
GL_DEPTH_ATTACHMENT,
|
||||
GL_TEXTURE_2D,
|
||||
0,
|
||||
0);
|
||||
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER,
|
||||
GL_STENCIL_ATTACHMENT,
|
||||
GL_TEXTURE_2D,
|
||||
0,
|
||||
0);
|
||||
|
||||
unbindFrameBuffer();
|
||||
glDeleteFramebuffers(1, &_FBO);
|
||||
CHECK_GL_ERROR_DEBUG();
|
||||
}
|
||||
}
|
||||
|
||||
void RenderTargetGL::bindFrameBuffer() const
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, _FBO);
|
||||
}
|
||||
|
||||
void RenderTargetGL::unbindFrameBuffer() const
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
void RenderTargetGL::setColorAttachment(ColorAttachment attachment)
|
||||
{
|
||||
RenderTarget::setColorAttachment(attachment);
|
||||
|
||||
if (!_defaultRenderTarget && bitmask::any(_flags, TargetBufferFlags::COLOR_ALL)) {
|
||||
GLenum bufs[MAX_COLOR_ATTCHMENT] = { GL_NONE };
|
||||
for (size_t i = 0; i < MAX_COLOR_ATTCHMENT; ++i) {
|
||||
if (bitmask::any(_flags, getMRTColorFlag(i))) {
|
||||
auto textureInfo = attachment[i];
|
||||
auto textureHandler = textureInfo.texture != nullptr ? textureInfo.texture->getHandler() : 0;
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER,
|
||||
GL_COLOR_ATTACHMENT0 + i,
|
||||
GL_TEXTURE_2D,
|
||||
textureHandler,
|
||||
textureInfo.level);
|
||||
bufs[i] = GL_COLOR_ATTACHMENT0 + i;
|
||||
}
|
||||
}
|
||||
#if CC_TARGET_PLATFORM == CC_PLATFORM_WIN32 || CC_TARGET_PLATFORM == CC_PLATFORM_LINUX
|
||||
glDrawBuffers(MAX_COLOR_ATTCHMENT, bufs);
|
||||
#endif
|
||||
CHECK_GL_ERROR_DEBUG();
|
||||
}
|
||||
}
|
||||
|
||||
void RenderTargetGL::setDepthAttachment(TextureBackend* attachment, int level)
|
||||
{
|
||||
RenderTarget::setDepthAttachment(attachment, level);
|
||||
|
||||
if (!_defaultRenderTarget) {
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER,
|
||||
GL_DEPTH_ATTACHMENT,
|
||||
GL_TEXTURE_2D,
|
||||
attachment != nullptr ? attachment->getHandler() : 0,
|
||||
level);
|
||||
|
||||
CHECK_GL_ERROR_DEBUG();
|
||||
}
|
||||
}
|
||||
|
||||
void RenderTargetGL::setStencilAttachment(TextureBackend* attachment, int level)
|
||||
{
|
||||
RenderTarget::setStencilAttachment(attachment, level);
|
||||
|
||||
if (!_defaultRenderTarget) {
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER,
|
||||
GL_STENCIL_ATTACHMENT,
|
||||
GL_TEXTURE_2D,
|
||||
attachment != nullptr ? attachment->getHandler() : 0,
|
||||
level);
|
||||
|
||||
CHECK_GL_ERROR_DEBUG();
|
||||
}
|
||||
}
|
||||
|
||||
CC_BACKEND_END
|
|
@ -0,0 +1,26 @@
|
|||
#pragma once
|
||||
#include "../RenderTarget.h"
|
||||
#include "platform/CCGL.h"
|
||||
|
||||
CC_BACKEND_BEGIN
|
||||
|
||||
class RenderTargetGL : public RenderTarget
|
||||
{
|
||||
public:
|
||||
/*
|
||||
* generateFBO, false, use for screen framebuffer
|
||||
*/
|
||||
RenderTargetGL(bool defaultRenderTarget);
|
||||
~RenderTargetGL();
|
||||
|
||||
void bindFrameBuffer() const override;
|
||||
void unbindFrameBuffer() const override;
|
||||
|
||||
void setColorAttachment(ColorAttachment attachment) override;
|
||||
void setDepthAttachment(TextureBackend* attachment, int level = 0) override;
|
||||
void setStencilAttachment(TextureBackend* attachment, int level = 0) override;
|
||||
public:
|
||||
GLuint _FBO = 0;
|
||||
};
|
||||
|
||||
CC_BACKEND_END
|
|
@ -151,10 +151,10 @@ Texture2DGL::Texture2DGL(const TextureDescriptor& descriptor)
|
|||
|
||||
void Texture2DGL::initWithZeros()
|
||||
{
|
||||
// Ensure the final data size at least 1 byte
|
||||
// Ensure the final data size at least 4 byte
|
||||
_width = (std::max)(_width, (uint32_t)1);
|
||||
_height = (std::max)(_height, (uint32_t)1);
|
||||
_bitsPerElement = (std::max)(_bitsPerElement, (uint8_t)8);
|
||||
_bitsPerElement = (std::max)(_bitsPerElement, (uint8_t)(8 * 4));
|
||||
|
||||
auto size = _width * _height * _bitsPerElement / 8;
|
||||
uint8_t* data = (uint8_t*)malloc(size);
|
||||
|
|
|
@ -385,15 +385,9 @@ void UtilsGL::toGLTypes(PixelFormat textureFormat, GLint &internalFormat, GLuint
|
|||
// internalFormat = GL_DEPTH_COMPONENT;
|
||||
// type = GL_UNSIGNED_INT;
|
||||
case PixelFormat::D24S8:
|
||||
#ifdef CC_USE_GLES
|
||||
format = GL_DEPTH_STENCIL_OES;
|
||||
internalFormat = GL_DEPTH_STENCIL_OES;
|
||||
type = GL_UNSIGNED_INT_24_8_OES;
|
||||
#else
|
||||
format = GL_DEPTH_STENCIL;
|
||||
internalFormat = GL_DEPTH24_STENCIL8;
|
||||
type = GL_UNSIGNED_INT_24_8;
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -592,79 +586,4 @@ GLenum UtilsGL::toGLCullMode(CullMode mode)
|
|||
return GL_FRONT;
|
||||
}
|
||||
|
||||
void UtilsGL::readPixels(TextureBackend* texture, GLint x, GLint y, std::size_t width, std::size_t height, PixelBufferDescriptor& pbd)
|
||||
{
|
||||
GLint defaultFBO = 0;
|
||||
GLuint frameBuffer = 0;
|
||||
|
||||
std::size_t bytesPerRow = 0;
|
||||
if (UTILS_LIKELY(!texture)) // read pixels from screen
|
||||
bytesPerRow = width * 4;
|
||||
else { // read pixels from GPU texture
|
||||
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFBO);
|
||||
|
||||
glGenFramebuffers(1, &frameBuffer);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
|
||||
|
||||
/** Notes from cocos2d-x v3
|
||||
// TODO: move this to configuration, so we don't check it every time
|
||||
// Certain Qualcomm Adreno GPU's will retain data in memory after a frame buffer switch which corrupts the render to the texture. The solution is to clear the frame buffer before rendering to the texture. However, calling glClear has the unintended result of clearing the current texture. Create a temporary texture to overcome this. At the end of RenderTexture::begin(), switch the attached texture to the second one, call glClear, and then switch back to the original texture. This solution is unnecessary for other devices as they don't have the same issue with switching frame buffers.
|
||||
|
||||
if (Configuration::getInstance()->checkForGLExtension("GL_QCOM"))
|
||||
{
|
||||
// -- bind a temporary texture so we can clear the render buffer without losing our texture
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _textureCopy->getName(), 0);
|
||||
CHECK_GL_ERROR_DEBUG();
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _texture->getName(), 0);
|
||||
}
|
||||
*/
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
|
||||
texture->getTextureType() == TextureType::TEXTURE_2D ? GL_TEXTURE_2D : GL_TEXTURE_CUBE_MAP,
|
||||
static_cast<GLuint>(texture->getHandler()),
|
||||
0);
|
||||
|
||||
bytesPerRow = width * texture->_bitsPerElement / 8;
|
||||
}
|
||||
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
||||
|
||||
auto bufferSize = bytesPerRow * height;
|
||||
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32 && defined(GL_ES_VERSION_3_0)) || \
|
||||
(CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID && defined(GL_PIXEL_PACK_BUFFER))
|
||||
GLuint pbo;
|
||||
glGenBuffers(1, &pbo);
|
||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo);
|
||||
glBufferData(GL_PIXEL_PACK_BUFFER, bufferSize, nullptr, GL_STATIC_DRAW);
|
||||
glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
||||
auto buffer = (uint8_t*)glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, bufferSize, GL_MAP_READ_BIT);
|
||||
#else
|
||||
std::unique_ptr<uint8_t[]> bufferStorage(new uint8_t[bufferSize]);
|
||||
auto buffer = bufferStorage.get();
|
||||
glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
|
||||
#endif
|
||||
uint8_t* wptr = pbd._data.resize(bufferSize);
|
||||
if (buffer && wptr) {
|
||||
auto rptr = buffer + (height - 1) * bytesPerRow;
|
||||
for (int row = 0; row < height; ++row) {
|
||||
memcpy(wptr, rptr, bytesPerRow);
|
||||
wptr += bytesPerRow;
|
||||
rptr -= bytesPerRow;
|
||||
}
|
||||
pbd._width = width;
|
||||
pbd._height = height;
|
||||
}
|
||||
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32 && defined(GL_ES_VERSION_3_0)) || \
|
||||
(CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID && defined(GL_PIXEL_PACK_BUFFER))
|
||||
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
|
||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
||||
glDeleteBuffers(1, &pbo);
|
||||
#endif
|
||||
|
||||
if (UTILS_UNLIKELY(frameBuffer)) {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO);
|
||||
glDeleteFramebuffers(1, &frameBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
CC_BACKEND_END
|
||||
|
|
|
@ -34,9 +34,6 @@ CC_BACKEND_BEGIN
|
|||
* @addtogroup _opengl
|
||||
* @{
|
||||
*/
|
||||
|
||||
class TextureBackend;
|
||||
|
||||
/**
|
||||
* Convert backend enum class to corresponding opengl defined value.
|
||||
*/
|
||||
|
@ -154,16 +151,6 @@ struct UtilsGL
|
|||
* @return Cull mode.
|
||||
*/
|
||||
static GLenum toGLCullMode(CullMode mode);
|
||||
|
||||
/**
|
||||
* Read a block of pixels from the given texture
|
||||
* @param texture Specifies the texture to get the image, nullptr: read pixels from screen framebuffer
|
||||
* @param origX,origY Specify the window coordinates of the first pixel that is read from the given texture. This location is the lower left corner of a rectangular block of pixels.
|
||||
* @param rectWidth,rectHeight Specify the dimensions of the pixel rectangle. rectWidth and rectHeight of one correspond to a single pixel.
|
||||
* @param pbd, the output pixel buffer for fill texels data
|
||||
* @remark: !!!this function only can call after endFrame, then it's could be works well.
|
||||
*/
|
||||
static void readPixels(TextureBackend* texture, GLint x, GLint y, std::size_t width, std::size_t height, PixelBufferDescriptor& pbd);
|
||||
};
|
||||
//end of _opengl group
|
||||
/// @}
|
||||
|
|
|
@ -91251,9 +91251,9 @@ int lua_cocos2dx_Renderer_getStencilAttachment(lua_State* tolua_S)
|
|||
tolua_error(tolua_S,"invalid arguments in function 'lua_cocos2dx_Renderer_getStencilAttachment'", nullptr);
|
||||
return 0;
|
||||
}
|
||||
cocos2d::Texture2D* ret = cobj->getStencilAttachment();
|
||||
object_to_luaval<cocos2d::Texture2D>(tolua_S, "cc.Texture2D",(cocos2d::Texture2D*)ret);
|
||||
return 1;
|
||||
// cocos2d::Texture2D* ret = cobj->getStencilAttachment();
|
||||
// object_to_luaval<cocos2d::Texture2D>(tolua_S, "cc.Texture2D",(cocos2d::Texture2D*)ret);
|
||||
return 0;
|
||||
}
|
||||
luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "cc.Renderer:getStencilAttachment",argc, 0);
|
||||
return 0;
|
||||
|
@ -91698,9 +91698,9 @@ int lua_cocos2dx_Renderer_getColorAttachment(lua_State* tolua_S)
|
|||
tolua_error(tolua_S,"invalid arguments in function 'lua_cocos2dx_Renderer_getColorAttachment'", nullptr);
|
||||
return 0;
|
||||
}
|
||||
cocos2d::Texture2D* ret = cobj->getColorAttachment();
|
||||
object_to_luaval<cocos2d::Texture2D>(tolua_S, "cc.Texture2D",(cocos2d::Texture2D*)ret);
|
||||
return 1;
|
||||
// cocos2d::Texture2D* ret = cobj->getColorAttachment();
|
||||
// object_to_luaval<cocos2d::Texture2D>(tolua_S, "cc.Texture2D",(cocos2d::Texture2D*)ret);
|
||||
return 0;
|
||||
}
|
||||
luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "cc.Renderer:getColorAttachment",argc, 0);
|
||||
return 0;
|
||||
|
@ -93060,7 +93060,8 @@ int lua_cocos2dx_Renderer_setRenderTarget(lua_State* tolua_S)
|
|||
tolua_error(tolua_S,"invalid arguments in function 'lua_cocos2dx_Renderer_setRenderTarget'", nullptr);
|
||||
return 0;
|
||||
}
|
||||
cobj->setRenderTarget(arg0, arg1, arg2, arg3);
|
||||
// TODO:
|
||||
// cobj->setRenderTarget(arg0, arg1, arg2, arg3);
|
||||
lua_settop(tolua_S, 1);
|
||||
return 1;
|
||||
}
|
||||
|
@ -93107,9 +93108,9 @@ int lua_cocos2dx_Renderer_getDepthAttachment(lua_State* tolua_S)
|
|||
tolua_error(tolua_S,"invalid arguments in function 'lua_cocos2dx_Renderer_getDepthAttachment'", nullptr);
|
||||
return 0;
|
||||
}
|
||||
cocos2d::Texture2D* ret = cobj->getDepthAttachment();
|
||||
object_to_luaval<cocos2d::Texture2D>(tolua_S, "cc.Texture2D",(cocos2d::Texture2D*)ret);
|
||||
return 1;
|
||||
// cocos2d::Texture2D* ret = cobj->getDepthAttachment();
|
||||
// object_to_luaval<cocos2d::Texture2D>(tolua_S, "cc.Texture2D",(cocos2d::Texture2D*)ret);
|
||||
return 0;
|
||||
}
|
||||
luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "cc.Renderer:getDepthAttachment",argc, 0);
|
||||
return 0;
|
||||
|
|
|
@ -116,12 +116,12 @@ namespace ui {
|
|||
/**
|
||||
@brief Open keyboard and receive input text.
|
||||
*/
|
||||
virtual bool attachWithIME();
|
||||
virtual bool attachWithIME() override;
|
||||
|
||||
/**
|
||||
@brief End text input and close keyboard.
|
||||
*/
|
||||
virtual bool detachWithIME();
|
||||
virtual bool detachWithIME() override;
|
||||
|
||||
void keyboardDidShow(IMEKeyboardNotificationInfo& /*info*/) override;
|
||||
void keyboardDidHide(IMEKeyboardNotificationInfo& /*info*/) override;
|
||||
|
|
|
@ -195,6 +195,7 @@ void ImGuiEXT::loadCustomFonts(void* ud)
|
|||
case CHS_GLYPH_RANGE::FULL:
|
||||
imChars = imFonts->GetGlyphRangesChineseFull();
|
||||
break;
|
||||
default:;
|
||||
}
|
||||
|
||||
imFonts->AddFontFromFileTTF(fontInfo.first.c_str(), fontInfo.second.fontSize * contentZoomFactor, nullptr, imChars);
|
||||
|
|
|
@ -366,10 +366,6 @@ void DataReaderHelper::addDataFromFileAsync(const std::string& imagePath, const
|
|||
{
|
||||
basefilePath = basefilePath.substr(0, pos + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
basefilePath;
|
||||
}
|
||||
|
||||
|
||||
// lazy init
|
||||
|
|
|
@ -1037,8 +1037,8 @@
|
|||
"cocos/renderer/backend/ProgramCache.h",
|
||||
"cocos/renderer/backend/ProgramState.cpp",
|
||||
"cocos/renderer/backend/ProgramState.h",
|
||||
"cocos/renderer/backend/RenderPassDescriptor.cpp",
|
||||
"cocos/renderer/backend/RenderPassDescriptor.h",
|
||||
"cocos/renderer/backend/RenderPassParams.cpp",
|
||||
"cocos/renderer/backend/RenderPassParams.h",
|
||||
"cocos/renderer/backend/RenderPipeline.h",
|
||||
"cocos/renderer/backend/RenderPipelineDescriptor.h",
|
||||
"cocos/renderer/backend/ShaderCache.cpp",
|
||||
|
|
|
@ -50,7 +50,7 @@ function build_mac_cmake()
|
|||
cd $COCOS2DX_ROOT
|
||||
mkdir -p build
|
||||
cmake -S . -B build -GXcode -DBUILD_EXTENSION_IMGUI=ON
|
||||
cmake --build build --config Release -- -quiet
|
||||
cmake --build build --config Release --target cpp-tests -- -quiet
|
||||
#xcodebuild -project Cocos2d-x.xcodeproj -alltargets -jobs $NUM_OF_CORES build | xcpretty
|
||||
##the following commands must not be removed
|
||||
#xcodebuild -project Cocos2d-x.xcodeproj -alltargets -jobs $NUM_OF_CORES build
|
||||
|
|
Loading…
Reference in New Issue