From 873a830d88205c4444b031b36c99dc3c1aff9d6d Mon Sep 17 00:00:00 2001 From: Sergey Lipskiy Date: Sat, 25 Feb 2017 13:38:33 +0700 Subject: [PATCH] Always render to FBO, even when frame buffer emulation is disabled. --- src/DepthBuffer.cpp | 24 +++++++++- src/DepthBuffer.h | 2 + src/FrameBuffer.cpp | 102 +++++++++++++++++++++++++++++++++++------ src/FrameBuffer.h | 3 ++ src/GraphicsDrawer.cpp | 14 +++--- src/VI.cpp | 5 +- src/gDP.cpp | 8 ++-- 7 files changed, 129 insertions(+), 29 deletions(-) diff --git a/src/DepthBuffer.cpp b/src/DepthBuffer.cpp index 85d40397..3637f264 100644 --- a/src/DepthBuffer.cpp +++ b/src/DepthBuffer.cpp @@ -417,10 +417,32 @@ void DepthBufferList::removeBuffer(u32 _address ) } } +void DepthBufferList::_createScreenSizeBuffer(u32 _address) +{ + FrameBuffer * pFrameBuffer = frameBufferList().findBuffer(VI.width*2); + if (pFrameBuffer == nullptr) + return; + + m_list.emplace_front(); + DepthBuffer & buffer = m_list.front(); + + buffer.m_address = _address; + buffer.m_width = pFrameBuffer->m_width; + + buffer.initDepthBufferTexture(pFrameBuffer); + + m_pCurrent = &buffer; + frameBufferList().attachDepthBuffer(); + m_pCurrent = nullptr; +} + void DepthBufferList::saveBuffer(u32 _address) { - if (!config.frameBufferEmulation.enable) + if (config.frameBufferEmulation.enable == 0) { + if (m_list.empty()) + _createScreenSizeBuffer(_address); return; + } FrameBuffer * pFrameBuffer = frameBufferList().findBuffer(_address); if (pFrameBuffer != nullptr) diff --git a/src/DepthBuffer.h b/src/DepthBuffer.h index 95ccb0ea..e39c2821 100644 --- a/src/DepthBuffer.h +++ b/src/DepthBuffer.h @@ -67,6 +67,8 @@ private: DepthBufferList(const DepthBufferList &); ~DepthBufferList(); + void _createScreenSizeBuffer(u32 _address); + typedef std::list DepthBuffers; DepthBuffers m_list; DepthBuffer *m_pCurrent; diff --git a/src/FrameBuffer.cpp b/src/FrameBuffer.cpp index a487a42f..338760d3 100644 --- a/src/FrameBuffer.cpp +++ b/src/FrameBuffer.cpp @@ -151,7 +151,7 @@ void FrameBuffer::init(u32 _address, u32 _endAddress, u16 _format, u16 _size, u1 if (isAuxiliary() && config.frameBufferEmulation.copyAuxToRDRAM != 0) { m_scaleX = 1.0f; m_scaleY = 1.0f; - } else if (config.frameBufferEmulation.nativeResFactor != 0) { + } else if (config.frameBufferEmulation.nativeResFactor != 0 && config.frameBufferEmulation.enable != 0) { m_scaleX = m_scaleY = static_cast(config.frameBufferEmulation.nativeResFactor); } else { m_scaleX = wnd.getScaleX(); @@ -564,8 +564,24 @@ FrameBuffer * FrameBufferList::findTmpBuffer(u32 _address) return nullptr; } + +void FrameBufferList::_createScreenSizeBuffer() +{ + if (VI.height == 0) + return; + m_list.emplace_front(); + FrameBuffer & buffer = m_list.front(); + buffer.init(VI.width * 2, VI.width * VI.height * 2, G_IM_FMT_RGBA, G_IM_SIZ_16b, VI.width, VI.height, false); +} + void FrameBufferList::saveBuffer(u32 _address, u16 _format, u16 _size, u16 _width, u16 _height, bool _cfb) { + if (config.frameBufferEmulation.enable == 0) { + if (m_list.empty()) + _createScreenSizeBuffer(); + return; + } + if (m_pCurrent != nullptr && config.frameBufferEmulation.copyAuxToRDRAM != 0 && (config.generalEmulation.hacks & hack_Snap) == 0) { @@ -754,35 +770,36 @@ void FrameBufferList::fillBufferInfo(void * _pinfo, u32 _size) void FrameBufferList::attachDepthBuffer() { - if (m_pCurrent == nullptr) + FrameBuffer * pCurrent = config.frameBufferEmulation.enable == 0 ? &m_list.back() : m_pCurrent; + if (pCurrent == nullptr) return; DepthBuffer * pDepthBuffer = depthBufferList().getCurrent(); - if (m_pCurrent->m_pDepthBuffer == pDepthBuffer) + if (pCurrent->m_pDepthBuffer == pDepthBuffer) return; - if (m_pCurrent->m_FBO.isNotNull() && pDepthBuffer != nullptr) { - pDepthBuffer->initDepthImageTexture(m_pCurrent); - pDepthBuffer->initDepthBufferTexture(m_pCurrent); + if (pCurrent->m_FBO.isNotNull() && pDepthBuffer != nullptr) { + pDepthBuffer->initDepthImageTexture(pCurrent); + pDepthBuffer->initDepthBufferTexture(pCurrent); bool goodDepthBufferTexture = false; if (gfxContext.isSupported(SpecialFeatures::DepthFramebufferTextures)) { goodDepthBufferTexture = gfxContext.isSupported(SpecialFeatures::WeakBlitFramebuffer) ? - pDepthBuffer->m_pDepthBufferTexture->realWidth == m_pCurrent->m_pTexture->realWidth : - pDepthBuffer->m_pDepthBufferTexture->realWidth >= m_pCurrent->m_pTexture->realWidth; + pDepthBuffer->m_pDepthBufferTexture->realWidth == pCurrent->m_pTexture->realWidth : + pDepthBuffer->m_pDepthBufferTexture->realWidth >= pCurrent->m_pTexture->realWidth; } else { - goodDepthBufferTexture = pDepthBuffer->m_depthRenderbufferWidth == m_pCurrent->m_pTexture->realWidth; + goodDepthBufferTexture = pDepthBuffer->m_depthRenderbufferWidth == pCurrent->m_pTexture->realWidth; } if (goodDepthBufferTexture) { - m_pCurrent->m_pDepthBuffer = pDepthBuffer; - pDepthBuffer->setDepthAttachment(m_pCurrent->m_FBO, bufferTarget::DRAW_FRAMEBUFFER); + pCurrent->m_pDepthBuffer = pDepthBuffer; + pDepthBuffer->setDepthAttachment(pCurrent->m_FBO, bufferTarget::DRAW_FRAMEBUFFER); if (config.frameBufferEmulation.N64DepthCompare != 0) pDepthBuffer->bindDepthImageTexture(); } else - m_pCurrent->m_pDepthBuffer = nullptr; + pCurrent->m_pDepthBuffer = nullptr; } else - m_pCurrent->m_pDepthBuffer = nullptr; + pCurrent->m_pDepthBuffer = nullptr; assert(!gfxContext.isFramebufferError()); } @@ -814,6 +831,60 @@ void FrameBuffer_Destroy() frameBufferList().destroy(); } +void FrameBufferList::_renderScreenSizeBuffer() +{ + if (m_list.empty()) + return; + + DisplayWindow & wnd = dwnd(); + GraphicsDrawer & drawer = wnd.getDrawer(); + FrameBuffer *pBuffer = &m_list.back(); + PostProcessor & postProcessor = PostProcessor::get(); + FrameBuffer * pFilteredBuffer = postProcessor.doBlur(postProcessor.doGammaCorrection( + postProcessor.doOrientationCorrection(pBuffer))); + CachedTexture * pBufferTexture = pFilteredBuffer->m_pTexture; + + + s32 srcCoord[4] = { 0, 0, pBufferTexture->realWidth, pBufferTexture->realHeight }; + const s32 hOffset = (wnd.getScreenWidth() - wnd.getWidth()) / 2; + const s32 vOffset = (wnd.getScreenHeight() - wnd.getHeight()) / 2 + wnd.getHeightOffset(); + s32 dstCoord[4] = { hOffset, vOffset, hOffset + pBufferTexture->realWidth, vOffset + pBufferTexture->realHeight }; + + gfxContext.bindFramebuffer(bufferTarget::DRAW_FRAMEBUFFER, ObjectHandle::null); + + float clearColor[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + drawer.clearColorBuffer(clearColor); + + TextureParam filter = textureParameters::FILTER_LINEAR; + + GraphicsDrawer::BlitOrCopyRectParams blitParams; + blitParams.srcX0 = srcCoord[0]; + blitParams.srcY0 = srcCoord[1]; + blitParams.srcX1 = srcCoord[2]; + blitParams.srcY1 = srcCoord[3]; + blitParams.srcWidth = pBufferTexture->realWidth; + blitParams.srcHeight = pBufferTexture->realHeight; + blitParams.dstX0 = dstCoord[0]; + blitParams.dstY0 = dstCoord[1]; + blitParams.dstX1 = dstCoord[2]; + blitParams.dstY1 = dstCoord[3]; + blitParams.dstWidth = wnd.getScreenWidth(); + blitParams.dstHeight = wnd.getScreenHeight() + wnd.getHeightOffset(); + blitParams.filter = filter; + blitParams.mask = blitMask::COLOR_BUFFER; + blitParams.tex[0] = pBufferTexture; + blitParams.combiner = CombinerInfo::get().getTexrectCopyProgram(); + blitParams.readBuffer = pFilteredBuffer->m_FBO; + + drawer.blitOrCopyTexturedRect(blitParams); + + gfxContext.bindFramebuffer(bufferTarget::READ_FRAMEBUFFER, ObjectHandle::null); + + wnd.swapBuffers(); + gfxContext.bindFramebuffer(bufferTarget::DRAW_FRAMEBUFFER, pBuffer->m_FBO); + gDP.changed |= CHANGED_SCISSOR; +} + void FrameBufferList::renderBuffer(u32 _address) { static s32 vStartPrev = 0; @@ -821,6 +892,11 @@ void FrameBufferList::renderBuffer(u32 _address) if (VI.width == 0 || *REG.VI_WIDTH == 0 || *REG.VI_H_START == 0) // H width is zero. Don't draw return; + if (config.frameBufferEmulation.enable == 0) { + _renderScreenSizeBuffer(); + return; + } + FrameBuffer *pBuffer = findBuffer(_address); if (pBuffer == nullptr) return; diff --git a/src/FrameBuffer.h b/src/FrameBuffer.h index 4ba41dd3..0b0b4834 100644 --- a/src/FrameBuffer.h +++ b/src/FrameBuffer.h @@ -110,6 +110,9 @@ private: FrameBuffer * _findBuffer(u32 _startAddress, u32 _endAddress, u32 _width); + void _createScreenSizeBuffer(); + void _renderScreenSizeBuffer(); + typedef std::list FrameBuffers; FrameBuffers m_list; FrameBuffer * m_pCurrent; diff --git a/src/GraphicsDrawer.cpp b/src/GraphicsDrawer.cpp index f8892b58..3830f79f 100644 --- a/src/GraphicsDrawer.cpp +++ b/src/GraphicsDrawer.cpp @@ -173,16 +173,14 @@ void GraphicsDrawer::updateScissor(FrameBuffer * _pBuffer) const { DisplayWindow & wnd = DisplayWindow::get(); f32 scaleX, scaleY; - u32 heightOffset, screenHeight; + u32 screenHeight; if (_pBuffer == nullptr) { scaleX = wnd.getScaleX(); scaleY = wnd.getScaleY(); - heightOffset = wnd.getHeightOffset(); screenHeight = VI.height; } else { scaleX = _pBuffer->m_scaleX; scaleY = _pBuffer->m_scaleY; - heightOffset = 0; screenHeight = (_pBuffer->m_height == 0) ? VI.height : _pBuffer->m_height; } @@ -191,7 +189,7 @@ void GraphicsDrawer::updateScissor(FrameBuffer * _pBuffer) const if (_needAdjustCoordinate(wnd)) _adjustScissorX(SX0, SX1, wnd.getAdjustScale()); - gfxContext.setScissor((s32)(SX0 * scaleX), (s32)((screenHeight - gDP.scissor.lry) * scaleY + heightOffset), + gfxContext.setScissor((s32)(SX0 * scaleX), (s32)((screenHeight - gDP.scissor.lry) * scaleY), std::max((s32)((SX1 - SX0) * scaleX), 0), std::max((s32)((gDP.scissor.lry - gDP.scissor.uly) * scaleY), 0)); gDP.changed &= ~CHANGED_SCISSOR; } @@ -216,7 +214,7 @@ void GraphicsDrawer::_updateViewport() const Xf = _adjustViewportX(Xf); const s32 X = (s32)(Xf * scaleX); const s32 Y = gSP.viewport.vscale[1] < 0 ? (s32)((gSP.viewport.y + gSP.viewport.vscale[1] * 2.0f) * scaleY) : (s32)((VI.height - (gSP.viewport.y + gSP.viewport.height)) * scaleY); - gfxContext.setViewport(X, Y + wnd.getHeightOffset(), + gfxContext.setViewport(X, Y, std::max((s32)(gSP.viewport.width * scaleX), 0), std::max((s32)(gSP.viewport.height * scaleY), 0)); } else { const f32 scaleX = pCurrentBuffer->m_scaleX; @@ -237,7 +235,7 @@ void GraphicsDrawer::_updateScreenCoordsViewport() const DisplayWindow & wnd = DisplayWindow::get(); FrameBuffer * pCurrentBuffer = frameBufferList().getCurrent(); if (pCurrentBuffer == nullptr) - gfxContext.setViewport(0, wnd.getHeightOffset(), wnd.getScreenWidth(), wnd.getScreenHeight()); + gfxContext.setViewport(0, 0, wnd.getScreenWidth(), wnd.getScreenHeight()); else gfxContext.setViewport(0, 0, s32(pCurrentBuffer->m_width*pCurrentBuffer->m_scaleX), s32(pCurrentBuffer->m_height*pCurrentBuffer->m_scaleY)); gSP.changed |= CHANGED_VIEWPORT; @@ -846,7 +844,7 @@ void GraphicsDrawer::drawRect(int _ulx, int _uly, int _lrx, int _lry, float *_pC FrameBuffer * pCurrentBuffer = frameBufferList().getCurrent(); DisplayWindow & wnd = dwnd(); if (pCurrentBuffer == nullptr) - gfxContext.setViewport(0, wnd.getHeightOffset(), wnd.getScreenWidth(), wnd.getScreenHeight()); + gfxContext.setViewport(0, 0, wnd.getScreenWidth(), wnd.getScreenHeight()); else gfxContext.setViewport(0, 0, pCurrentBuffer->m_width*pCurrentBuffer->m_scaleX, pCurrentBuffer->m_height*pCurrentBuffer->m_scaleY); @@ -1249,7 +1247,7 @@ void GraphicsDrawer::drawTexturedRect(const TexturedRectParams & _params) m_texrectDrawer.add(); else { if (pCurrentBuffer == nullptr) - gfxContext.setViewport(0, wnd.getHeightOffset(), wnd.getScreenWidth(), wnd.getScreenHeight()); + gfxContext.setViewport(0, 0, wnd.getScreenWidth(), wnd.getScreenHeight()); else gfxContext.setViewport(0, 0, pCurrentBuffer->m_width*pCurrentBuffer->m_scaleX, pCurrentBuffer->m_height*pCurrentBuffer->m_scaleY); diff --git a/src/VI.cpp b/src/VI.cpp index acbd7548..e54ab636 100644 --- a/src/VI.cpp +++ b/src/VI.cpp @@ -163,10 +163,9 @@ void VI_UpdateScreen() frameBufferList().clearBuffersChanged(); VI.lastOrigin = *REG.VI_ORIGIN; } - } - else { + } else { if (gDP.changed & CHANGED_COLORBUFFER) { - wnd.swapBuffers(); + frameBufferList().renderBuffer(*REG.VI_ORIGIN); gDP.changed &= ~CHANGED_COLORBUFFER; VI.lastOrigin = *REG.VI_ORIGIN; } diff --git a/src/gDP.cpp b/src/gDP.cpp index 44ba7ebb..25bc96b1 100644 --- a/src/gDP.cpp +++ b/src/gDP.cpp @@ -148,10 +148,10 @@ void gDPSetColorImage( u32 format, u32 size, u32 width, u32 address ) else height = VI.height > 0 ? VI.height : gDP.scissor.lry; - if (config.frameBufferEmulation.enable) { - frameBufferList().saveBuffer(address, (u16)format, (u16)size, (u16)width, height, false); - gDP.colorImage.height = 0; - } else + frameBufferList().saveBuffer(address, (u16)format, (u16)size, (u16)width, height, false); + if (config.frameBufferEmulation.enable != 0) + gDP.colorImage.height = 0; + else gDP.colorImage.height = height; }