diff --git a/src/BufferCopy/ColorBufferToRDRAM.cpp b/src/BufferCopy/ColorBufferToRDRAM.cpp index 2bb0c469..c051e457 100644 --- a/src/BufferCopy/ColorBufferToRDRAM.cpp +++ b/src/BufferCopy/ColorBufferToRDRAM.cpp @@ -21,16 +21,10 @@ using namespace graphics; ColorBufferToRDRAM::ColorBufferToRDRAM() - : m_FBO(0) - , m_pTexture(nullptr) - , m_pCurFrameBuffer(nullptr) + : m_pCurFrameBuffer(nullptr) , m_frameCount(-1) , m_startAddress(-1) - , m_lastBufferWidth(-1) { - m_allowedRealWidths[0] = 320; - m_allowedRealWidths[1] = 480; - m_allowedRealWidths[2] = 640; } u32 ColorBufferToRDRAM::m_blueNoiseIdx = 0; @@ -41,88 +35,10 @@ ColorBufferToRDRAM::~ColorBufferToRDRAM() void ColorBufferToRDRAM::init() { - m_FBO = gfxContext.createFramebuffer(); } void ColorBufferToRDRAM::destroy() { - _destroyFBTexure(); - if (m_FBO.isNotNull()) { - gfxContext.deleteFramebuffer(m_FBO); - m_FBO.reset(); - } -} - -void ColorBufferToRDRAM::_initFBTexture(void) -{ - const FramebufferTextureFormats & fbTexFormat = gfxContext.getFramebufferTextureFormats(); - - m_pTexture = textureCache().addFrameBufferTexture(Context::EglImage ? textureTarget::TEXTURE_EXTERNAL : textureTarget::TEXTURE_2D); - m_pTexture->format = G_IM_FMT_RGBA; - m_pTexture->size = 2; - m_pTexture->clampS = 1; - m_pTexture->clampT = 1; - m_pTexture->frameBufferTexture = CachedTexture::fbOneSample; - m_pTexture->maskS = 0; - m_pTexture->maskT = 0; - m_pTexture->mirrorS = 0; - m_pTexture->mirrorT = 0; - //The actual VI width is not used for texture width because most texture widths - //cause slowdowns in the glReadPixels call, at least on Android - m_pTexture->width = m_lastBufferWidth; - m_pTexture->height = VI_GetMaxBufferHeight(m_lastBufferWidth); - m_pTexture->textureBytes = m_pTexture->width * m_pTexture->height * fbTexFormat.colorFormatBytes; - - - m_bufferReader.reset(gfxContext.createColorBufferReader(m_pTexture)); - - // Skip this since texture is initialized in the EGL color buffer reader - if (!Context::EglImage) - { - Context::InitTextureParams params; - params.handle = m_pTexture->name; - params.target = textureTarget::TEXTURE_2D; - params.width = m_pTexture->width; - params.height = m_pTexture->height; - params.internalFormat = fbTexFormat.colorInternalFormat; - params.format = fbTexFormat.colorFormat; - params.dataType = fbTexFormat.colorType; - gfxContext.init2DTexture(params); - } - - { - Context::TexParameters params; - params.handle = m_pTexture->name; - params.target = Context::EglImage ? textureTarget::TEXTURE_EXTERNAL : textureTarget::TEXTURE_2D; - params.textureUnitIndex = textureIndices::Tex[0]; - params.minFilter = textureParameters::FILTER_LINEAR; - params.magFilter = textureParameters::FILTER_LINEAR; - gfxContext.setTextureParameters(params); - } - { - Context::FrameBufferRenderTarget bufTarget; - bufTarget.bufferHandle = ObjectHandle(m_FBO); - bufTarget.bufferTarget = bufferTarget::DRAW_FRAMEBUFFER; - bufTarget.attachment = bufferAttachment::COLOR_ATTACHMENT0; - bufTarget.textureTarget = Context::EglImageFramebuffer ? textureTarget::TEXTURE_EXTERNAL : textureTarget::TEXTURE_2D; - bufTarget.textureHandle = m_pTexture->name; - gfxContext.addFrameBufferRenderTarget(bufTarget); - } - - // check if everything is OK - assert(!gfxContext.isFramebufferError()); - - gfxContext.bindFramebuffer(graphics::bufferTarget::DRAW_FRAMEBUFFER, graphics::ObjectHandle::defaultFramebuffer); -} - -void ColorBufferToRDRAM::_destroyFBTexure(void) -{ - m_bufferReader.reset(); - - if (m_pTexture != nullptr) { - textureCache().removeFrameBufferTexture(m_pTexture); - m_pTexture = nullptr; - } } bool ColorBufferToRDRAM::_prepareCopy(u32& _startAddress) @@ -153,15 +69,7 @@ bool ColorBufferToRDRAM::_prepareCopy(u32& _startAddress) if (bufferHeight == 0) return false; - if(m_pTexture == nullptr || - m_pTexture->width != pBuffer->m_width || - m_pTexture->height != VI_GetMaxBufferHeight(pBuffer->m_width)) - { - _destroyFBTexure(); - - m_lastBufferWidth = pBuffer->m_width; - _initFBTexture(); - } + CachedTexture* colorBufferTexture = pBuffer->getColorFbTexture(); m_pCurFrameBuffer = pBuffer; @@ -206,17 +114,17 @@ bool ColorBufferToRDRAM::_prepareCopy(u32& _startAddress) blitParams.dstY0 = 0; blitParams.dstX1 = m_pCurFrameBuffer->m_width; blitParams.dstY1 = bufferHeight; - blitParams.dstWidth = m_pTexture->width; - blitParams.dstHeight = m_pTexture->height; + blitParams.dstWidth = colorBufferTexture->width; + blitParams.dstHeight = colorBufferTexture->height; blitParams.filter = textureParameters::FILTER_LINEAR; blitParams.tex[0] = pInputTexture; blitParams.combiner = CombinerInfo::get().getTexrectDownscaleCopyProgram(); blitParams.readBuffer = readBuffer; - blitParams.drawBuffer = m_FBO; + blitParams.drawBuffer = pBuffer->getColorFbFbo(); blitParams.mask = blitMask::COLOR_BUFFER; wnd.getDrawer().blitOrCopyTexturedRect(blitParams); - gfxContext.bindFramebuffer(bufferTarget::READ_FRAMEBUFFER, m_FBO); + gfxContext.bindFramebuffer(bufferTarget::READ_FRAMEBUFFER, pBuffer->getColorFbFbo()); } else { gfxContext.bindFramebuffer(bufferTarget::READ_FRAMEBUFFER, readBuffer); } @@ -301,7 +209,7 @@ void ColorBufferToRDRAM::_copy(u32 _startAddress, u32 _endAddress, bool _sync) const u32 y1 = (_endAddress - m_pCurFrameBuffer->m_startAddress) / stride; const u32 height = std::min(max_height, 1u + y1 - y0); - const u8* pPixels = m_bufferReader->readPixels(x0, y0, width, height, m_pCurFrameBuffer->m_size, _sync); + const u8* pPixels = m_pCurFrameBuffer->readPixels(x0, y0, width, height, m_pCurFrameBuffer->m_size, _sync); frameBufferList().setCurrentDrawBuffer(); if (pPixels == nullptr) return; @@ -325,7 +233,7 @@ void ColorBufferToRDRAM::_copy(u32 _startAddress, u32 _endAddress, bool _sync) m_pCurFrameBuffer->copyRdram(); m_pCurFrameBuffer->m_cleared = false; - m_bufferReader->cleanUp(); + m_pCurFrameBuffer->cleanUp(); gDP.changed |= CHANGED_SCISSOR; } diff --git a/src/BufferCopy/ColorBufferToRDRAM.h b/src/BufferCopy/ColorBufferToRDRAM.h index ba48f4c7..7248c6a1 100644 --- a/src/BufferCopy/ColorBufferToRDRAM.h +++ b/src/BufferCopy/ColorBufferToRDRAM.h @@ -29,8 +29,6 @@ private: ColorBufferToRDRAM(const ColorBufferToRDRAM &) = delete; virtual ~ColorBufferToRDRAM(); - CachedTexture * m_pTexture; - union RGBA { struct { u8 r, g, b, a; @@ -38,10 +36,6 @@ private: u32 raw; }; - void _initFBTexture(void); - - void _destroyFBTexure(void); - bool _prepareCopy(u32& _startAddress); void _copy(u32 _startAddress, u32 _endAddress, bool _sync); @@ -51,17 +45,11 @@ private: static u16 _RGBAtoRGBA16(u32 _c, u32 x, u32 y); static u32 _RGBAtoRGBA32(u32 _c, u32 x, u32 y); - graphics::ObjectHandle m_FBO; FrameBuffer * m_pCurFrameBuffer; u32 m_frameCount; u32 m_startAddress; - u32 m_lastBufferWidth; - static u32 m_blueNoiseIdx; - - std::array m_allowedRealWidths; - std::unique_ptr m_bufferReader; }; void copyWhiteToRDRAM(FrameBuffer * _pBuffer); diff --git a/src/FrameBuffer.cpp b/src/FrameBuffer.cpp index 48543dcb..3e39fc29 100644 --- a/src/FrameBuffer.cpp +++ b/src/FrameBuffer.cpp @@ -25,6 +25,7 @@ #include #include +#include #include "DisplayWindow.h" using namespace std; @@ -32,6 +33,8 @@ using namespace graphics; FrameBuffer::FrameBuffer() : m_copyFBO(ObjectHandle::defaultFramebuffer) + , m_ColorBufferFBO(0) + , m_pColorBufferTexture(nullptr) { m_pTexture = textureCache().addFrameBufferTexture(config.video.multisampling != 0 ? textureTarget::TEXTURE_2D_MULTISAMPLE : textureTarget::TEXTURE_2D); @@ -54,6 +57,8 @@ FrameBuffer::~FrameBuffer() textureCache().removeFrameBufferTexture(m_pResolveTexture); textureCache().removeFrameBufferTexture(m_pSubTexture); textureCache().removeFrameBufferTexture(m_pFrameBufferCopyTexture); + + _destroyColorFBTexure(); } static @@ -529,6 +534,110 @@ CachedTexture * FrameBuffer::getTextureBG() return pTexture; } +CachedTexture * FrameBuffer::getColorFbTexture() +{ + if(m_pColorBufferTexture == nullptr || + m_pColorBufferTexture->width != m_width || + m_pColorBufferTexture->height != VI_GetMaxBufferHeight(m_width)) + { + _destroyColorFBTexure(); + _initColorFBTexture(m_width); + } + + return m_pColorBufferTexture; +} + +graphics::ObjectHandle FrameBuffer::getColorFbFbo() +{ + return m_ColorBufferFBO; +} + +const u8 * FrameBuffer::readPixels(s32 _x0, s32 _y0, u32 _width, u32 _height, u32 _size, bool _sync) +{ + return m_bufferReader->readPixels(_x0, _y0, _width, _height, _size, _sync); +} + +void FrameBuffer::cleanUp() +{ + m_bufferReader->cleanUp(); +} + +void FrameBuffer::_initColorFBTexture(int _width) +{ + m_ColorBufferFBO = gfxContext.createFramebuffer(); + + const FramebufferTextureFormats & fbTexFormat = gfxContext.getFramebufferTextureFormats(); + + m_pColorBufferTexture = textureCache().addFrameBufferTexture(Context::EglImage ? textureTarget::TEXTURE_EXTERNAL : textureTarget::TEXTURE_2D); + m_pColorBufferTexture->format = G_IM_FMT_RGBA; + m_pColorBufferTexture->size = 2; + m_pColorBufferTexture->clampS = 1; + m_pColorBufferTexture->clampT = 1; + m_pColorBufferTexture->frameBufferTexture = CachedTexture::fbOneSample; + m_pColorBufferTexture->maskS = 0; + m_pColorBufferTexture->maskT = 0; + m_pColorBufferTexture->mirrorS = 0; + m_pColorBufferTexture->mirrorT = 0; + m_pColorBufferTexture->width = _width; + m_pColorBufferTexture->height = VI_GetMaxBufferHeight(_width); + m_pColorBufferTexture->textureBytes = m_pColorBufferTexture->width * m_pColorBufferTexture->height * fbTexFormat.colorFormatBytes; + + m_bufferReader.reset(gfxContext.createColorBufferReader(m_pColorBufferTexture)); + + // Skip this since texture is initialized in the EGL color buffer reader + if (!Context::EglImage) + { + Context::InitTextureParams params; + params.handle = m_pColorBufferTexture->name; + params.target = textureTarget::TEXTURE_2D; + params.width = m_pColorBufferTexture->width; + params.height = m_pColorBufferTexture->height; + params.internalFormat = fbTexFormat.colorInternalFormat; + params.format = fbTexFormat.colorFormat; + params.dataType = fbTexFormat.colorType; + gfxContext.init2DTexture(params); + } + + { + Context::TexParameters params; + params.handle = m_pColorBufferTexture->name; + params.target = Context::EglImage ? textureTarget::TEXTURE_EXTERNAL : textureTarget::TEXTURE_2D; + params.textureUnitIndex = textureIndices::Tex[0]; + params.minFilter = textureParameters::FILTER_LINEAR; + params.magFilter = textureParameters::FILTER_LINEAR; + gfxContext.setTextureParameters(params); + } + { + Context::FrameBufferRenderTarget bufTarget; + bufTarget.bufferHandle = ObjectHandle(m_ColorBufferFBO); + bufTarget.bufferTarget = bufferTarget::DRAW_FRAMEBUFFER; + bufTarget.attachment = bufferAttachment::COLOR_ATTACHMENT0; + bufTarget.textureTarget = Context::EglImageFramebuffer ? textureTarget::TEXTURE_EXTERNAL : textureTarget::TEXTURE_2D; + bufTarget.textureHandle = m_pColorBufferTexture->name; + gfxContext.addFrameBufferRenderTarget(bufTarget); + } + + // check if everything is OK + assert(!gfxContext.isFramebufferError()); + + gfxContext.bindFramebuffer(graphics::bufferTarget::DRAW_FRAMEBUFFER, graphics::ObjectHandle::defaultFramebuffer); +} + +void FrameBuffer::_destroyColorFBTexure() +{ + m_bufferReader.reset(); + + if (m_pColorBufferTexture != nullptr) { + textureCache().removeFrameBufferTexture(m_pColorBufferTexture); + m_pColorBufferTexture = nullptr; + } + + if (m_ColorBufferFBO.isNotNull()) { + gfxContext.deleteFramebuffer(m_ColorBufferFBO); + m_ColorBufferFBO.reset(); + } +} + FrameBufferList & FrameBufferList::get() { static FrameBufferList frameBufferList; diff --git a/src/FrameBuffer.h b/src/FrameBuffer.h index 46ac3638..6e06dae4 100644 --- a/src/FrameBuffer.h +++ b/src/FrameBuffer.h @@ -3,6 +3,7 @@ #include #include +#include #include "gDP.h" #include "Textures.h" @@ -13,6 +14,10 @@ struct DepthBuffer; const u32 fingerprint[4] = { 2, 6, 4, 3 }; +namespace graphics { + class ColorBufferReader; +} + struct FrameBuffer { FrameBuffer(); @@ -28,6 +33,10 @@ struct FrameBuffer void setDirty(); bool isValid(bool _forceCheck) const; bool isAuxiliary() const; + CachedTexture * getColorFbTexture(); + graphics::ObjectHandle getColorFbFbo(); + const u8 * readPixels(s32 _x0, s32 _y0, u32 _width, u32 _height, u32 _size, bool _sync); + void cleanUp(); u32 m_startAddress = 0; u32 m_endAddress = 0; @@ -62,6 +71,10 @@ struct FrameBuffer graphics::ObjectHandle m_depthFBO; CachedTexture *m_pDepthTexture = nullptr; + std::unique_ptr m_bufferReader; + graphics::ObjectHandle m_ColorBufferFBO; + CachedTexture *m_pColorBufferTexture = nullptr; + DepthBuffer *m_pDepthBuffer = nullptr; // multisampling @@ -94,6 +107,8 @@ private: void _initCopyTexture(); CachedTexture * _copyFrameBufferTexture(); CachedTexture * _getSubTexture(u32 _t); + void _initColorFBTexture(int _width); + void _destroyColorFBTexure(); mutable u32 m_validityChecked = false; };