1
0
mirror of https://github.com/blawar/GLideN64.git synced 2024-06-25 22:09:35 +00:00

Rewrite buffer height calculation.

This commit is contained in:
Sergey Lipskiy 2017-03-02 22:09:08 +07:00
parent e6811b4d4f
commit dd11326115
6 changed files with 54 additions and 111 deletions

View File

@ -109,16 +109,17 @@ void DepthBuffer::_initDepthBufferTexture(FrameBuffer * _pBuffer, CachedTexture
_pTexture->clampWidth = _pBuffer->m_width;
_pTexture->clampHeight = _pBuffer->m_height;
} else {
const u16 maxHeight = VI_GetMaxBufferHeight(VI.width);
if (config.frameBufferEmulation.nativeResFactor == 0) {
_pTexture->width = dwnd().getWidth();
_pTexture->height = dwnd().getHeight();
_pTexture->height = (u16)(u32)(maxHeight * dwnd().getScaleX());
} else {
_pTexture->width = VI.width * config.frameBufferEmulation.nativeResFactor;
_pTexture->height = VI.height * config.frameBufferEmulation.nativeResFactor;
_pTexture->height = maxHeight * config.frameBufferEmulation.nativeResFactor;
}
_pTexture->address = gDP.depthImageAddress;
_pTexture->clampWidth = VI.width;
_pTexture->clampHeight = VI.height;
_pTexture->clampHeight = maxHeight;
}
_pTexture->format = 0;
_pTexture->size = 2;
@ -169,10 +170,10 @@ void DepthBuffer::_initDepthBufferRenderbuffer(FrameBuffer * _pBuffer)
} else {
if (config.frameBufferEmulation.nativeResFactor == 0) {
m_depthRenderbufferWidth = dwnd().getWidth();
height = dwnd().getHeight();
height = (u32)(VI_GetMaxBufferHeight(VI.width) * dwnd().getScaleX());
} else {
m_depthRenderbufferWidth = VI.width * config.frameBufferEmulation.nativeResFactor;
height = VI.height * config.frameBufferEmulation.nativeResFactor;
height = VI_GetMaxBufferHeight(VI.width) * config.frameBufferEmulation.nativeResFactor;
}
}

View File

@ -33,8 +33,7 @@ FrameBuffer::FrameBuffer() :
m_startAddress(0), m_endAddress(0), m_size(0), m_width(0), m_height(0), m_validityChecked(0),
m_scaleX(0), m_scaleY(0),
m_copiedToRdram(false), m_fingerprint(false), m_cleared(false), m_changed(false), m_cfb(false),
m_isDepthBuffer(false), m_isPauseScreen(false), m_isOBScreen(false),
m_needHeightCorrection(false), m_readable(false),
m_isDepthBuffer(false), m_isPauseScreen(false), m_isOBScreen(false), m_readable(false),
m_loadType(LOADTYPE_BLOCK), m_pDepthBuffer(nullptr),
m_pResolveTexture(nullptr), m_resolved(false),
m_pSubTexture(nullptr)
@ -59,8 +58,8 @@ void FrameBuffer::_initTexture(u16 _width, u16 _height, u16 _format, u16 _size,
{
const FramebufferTextureFormats & fbTexFormats = gfxContext.getFramebufferTextureFormats();
_pTexture->width = (u32)(_width * m_scaleX);
_pTexture->height = (u32)(_height * m_scaleY);
_pTexture->width = (u16)(u32)(_width * m_scaleX);
_pTexture->height = (u16)(u32)(_height * m_scaleY);
_pTexture->format = _format;
_pTexture->size = _size;
_pTexture->clampS = 1;
@ -140,13 +139,13 @@ bool FrameBuffer::isAuxiliary() const
return m_width != VI.width;
}
void FrameBuffer::init(u32 _address, u16 _format, u16 _size, u16 _width, u16 _height, bool _cfb)
void FrameBuffer::init(u32 _address, u16 _format, u16 _size, u16 _width, bool _cfb)
{
DisplayWindow & wnd = dwnd();
m_startAddress = _address;
m_endAddress = _address + ((_width * _height) << _size >> 1) - 1;
m_endAddress = _address + (_width << _size >> 1) - 1;
m_width = _width;
m_height = _height;
m_height = 1;
m_size = _size;
if (isAuxiliary() && config.frameBufferEmulation.copyAuxToRDRAM != 0) {
m_scaleX = 1.0f;
@ -154,22 +153,21 @@ void FrameBuffer::init(u32 _address, u16 _format, u16 _size, u16 _width, u16 _he
} else if (config.frameBufferEmulation.nativeResFactor != 0 && config.frameBufferEmulation.enable != 0) {
m_scaleX = m_scaleY = static_cast<float>(config.frameBufferEmulation.nativeResFactor);
} else {
m_scaleX = wnd.getScaleX();
m_scaleY = wnd.getScaleY();
m_scaleY = m_scaleX = wnd.getScaleX();
}
m_cfb = _cfb;
m_needHeightCorrection = _width != VI.width && _width != *REG.VI_WIDTH;
m_cleared = false;
m_fingerprint = false;
_initTexture(_width, _height, _format, _size, m_pTexture);
const u16 maxHeight = VI_GetMaxBufferHeight(_width);
_initTexture(_width, maxHeight, _format, _size, m_pTexture);
if (config.video.multisampling != 0) {
_setAndAttachTexture(m_FBO, m_pTexture, 0, true);
m_pTexture->frameBufferTexture = CachedTexture::fbMultiSample;
m_pResolveTexture = textureCache().addFrameBufferTexture(false);
_initTexture(_width, _height, _format, _size, m_pResolveTexture);
_initTexture(_width, maxHeight, _format, _size, m_pResolveTexture);
m_resolveFBO = gfxContext.createFramebuffer();
_setAndAttachTexture(m_resolveFBO, m_pResolveTexture, 0, false);
assert(!gfxContext.isFramebufferError());
@ -181,16 +179,9 @@ void FrameBuffer::init(u32 _address, u16 _format, u16 _size, u16 _width, u16 _he
wnd.getDrawer().clearColorBuffer(nullptr);
}
void FrameBuffer::reinit(u16 _height)
void FrameBuffer::updateEndAddress()
{
const u16 format = m_pTexture->format;
textureCache().removeFrameBufferTexture(m_pTexture);
gfxContext.deleteFramebuffer(ObjectHandle(m_resolveFBO));
textureCache().removeFrameBufferTexture(m_pResolveTexture);
m_pTexture = textureCache().addFrameBufferTexture(config.video.multisampling != 0);
init(m_startAddress, format, m_size, m_width, _height, m_cfb);
m_endAddress = min(RDRAMSize, m_startAddress + (((m_width * m_height) << m_size >> 1) - 1));
}
inline
@ -498,26 +489,6 @@ void FrameBufferList::setBufferChanged(f32 _maxY)
}
}
void FrameBufferList::correctHeight()
{
if (m_pCurrent == nullptr)
return;
if (m_pCurrent->m_changed) {
m_pCurrent->m_needHeightCorrection = false;
return;
}
if (m_pCurrent->m_needHeightCorrection && m_pCurrent->m_width == gDP.scissor.lrx) {
if (m_pCurrent->m_height != gDP.scissor.lry) {
m_pCurrent->reinit((u32)gDP.scissor.lry);
if (m_pCurrent->_isMarioTennisScoreboard())
RDRAMtoColorBuffer::get().copyFromRDRAM(m_pCurrent->m_startAddress + 4, true);
gSP.changed |= CHANGED_VIEWPORT;
}
m_pCurrent->m_needHeightCorrection = false;
}
}
void FrameBufferList::clearBuffersChanged()
{
gDP.colorImage.changed = FALSE;
@ -578,10 +549,10 @@ void FrameBufferList::_createScreenSizeBuffer()
return;
m_list.emplace_front();
FrameBuffer & buffer = m_list.front();
buffer.init(VI.width * 2, G_IM_FMT_RGBA, G_IM_SIZ_16b, VI.width, VI.height, false);
buffer.init(VI.width * 2, G_IM_FMT_RGBA, G_IM_SIZ_16b, VI.width, false);
}
void FrameBufferList::saveBuffer(u32 _address, u16 _format, u16 _size, u16 _width, u16 _height, bool _cfb)
void FrameBufferList::saveBuffer(u32 _address, u16 _format, u16 _size, u16 _width, bool _cfb)
{
if (config.frameBufferEmulation.enable == 0) {
if (m_list.empty())
@ -598,37 +569,21 @@ void FrameBufferList::saveBuffer(u32 _address, u16 _format, u16 _size, u16 _widt
}
}
if (VI.width == 0 || _height == 0) {
m_pCurrent = nullptr;
gfxContext.bindFramebuffer(bufferTarget::DRAW_FRAMEBUFFER, ObjectHandle::null);
return;
}
DisplayWindow & wnd = dwnd();
bool bPrevIsDepth = false;
if (m_pCurrent != nullptr) {
bPrevIsDepth = m_pCurrent->m_isDepthBuffer;
m_pCurrent->m_readable = true;
m_pCurrent->updateEndAddress();
// Correct buffer's end address
if (!m_pCurrent->isAuxiliary()) {
if (gDP.colorImage.height > 200)
m_prevColorImageHeight = gDP.colorImage.height;
else if (gDP.colorImage.height == 0)
gDP.colorImage.height = m_prevColorImageHeight;
gDP.colorImage.height = min(gDP.colorImage.height, VI.height);
}
//Non-auxiliary buffers are always corrected, auxiliary buffers are correct only if they need correction.
//Also, before making any adjustments, make sure gDP.colorImage.height has a valid value.
if((!m_pCurrent->isAuxiliary() || m_pCurrent->m_needHeightCorrection) && gDP.colorImage.height != 0)
{
m_pCurrent->m_endAddress = min(RDRAMSize, m_pCurrent->m_startAddress + (((m_pCurrent->m_width * gDP.colorImage.height) << m_pCurrent->m_size >> 1) - 1));
}
if (!m_pCurrent->_isMarioTennisScoreboard() && !m_pCurrent->m_isDepthBuffer && !m_pCurrent->m_copiedToRdram && !m_pCurrent->m_cfb && !m_pCurrent->m_cleared && m_pCurrent->m_RdramCopy.empty() && gDP.colorImage.height > 1) {
if (!m_pCurrent->_isMarioTennisScoreboard() &&
!m_pCurrent->m_isDepthBuffer &&
!m_pCurrent->m_copiedToRdram &&
!m_pCurrent->m_cfb &&
!m_pCurrent->m_cleared
&& m_pCurrent->m_RdramCopy.empty()
&& m_pCurrent->m_height > 1) {
m_pCurrent->copyRdram();
}
@ -637,15 +592,14 @@ void FrameBufferList::saveBuffer(u32 _address, u16 _format, u16 _size, u16 _widt
if (m_pCurrent == nullptr || m_pCurrent->m_startAddress != _address || m_pCurrent->m_width != _width)
m_pCurrent = findBuffer(_address);
const float scaleX = config.frameBufferEmulation.nativeResFactor == 0 ? wnd.getScaleX() : static_cast<float>(config.frameBufferEmulation.nativeResFactor);
const float scaleY = config.frameBufferEmulation.nativeResFactor == 0 ? wnd.getScaleY() : scaleX;
const float scaleX = config.frameBufferEmulation.nativeResFactor == 0 ?
wnd.getScaleX() :
static_cast<float>(config.frameBufferEmulation.nativeResFactor);
if (m_pCurrent != nullptr) {
if ((m_pCurrent->m_startAddress != _address) ||
(m_pCurrent->m_width != _width) ||
//(current->height != height) ||
(m_pCurrent->m_size < _size) ||
(m_pCurrent->m_scaleX != scaleX) ||
(m_pCurrent->m_scaleY != scaleY))
(m_pCurrent->m_scaleX != scaleX))
{
removeBuffer(m_pCurrent->m_startAddress);
m_pCurrent = nullptr;
@ -673,7 +627,7 @@ void FrameBufferList::saveBuffer(u32 _address, u16 _format, u16 _size, u16 _widt
// Wasn't found or removed, create a new one
m_list.emplace_front();
FrameBuffer & buffer = m_list.front();
buffer.init(_address, _format, _size, _width, _height, _cfb);
buffer.init(_address, _format, _size, _width, _cfb);
m_pCurrent = &buffer;
if (m_pCurrent->_isMarioTennisScoreboard() || ((config.generalEmulation.hacks & hack_legoRacers) != 0 && _width == VI.width))

View File

@ -17,8 +17,8 @@ struct FrameBuffer
{
FrameBuffer();
~FrameBuffer();
void init(u32 _address, u16 _format, u16 _size, u16 _width, u16 _height, bool _cfb);
void reinit(u16 _height);
void init(u32 _address, u16 _format, u16 _size, u16 _width, bool _cfb);
void updateEndAddress();
void resolveMultisampledTexture(bool _bForce = false);
CachedTexture * getTexture(u32 _t);
CachedTexture * getTextureBG(u32 _t);
@ -39,7 +39,6 @@ struct FrameBuffer
bool m_isDepthBuffer;
bool m_isPauseScreen;
bool m_isOBScreen;
bool m_needHeightCorrection;
bool m_readable;
struct {
@ -80,7 +79,7 @@ class FrameBufferList
public:
void init();
void destroy();
void saveBuffer(u32 _address, u16 _format, u16 _size, u16 _width, u16 _height, bool _cfb);
void saveBuffer(u32 _address, u16 _format, u16 _size, u16 _width, bool _cfb);
void removeAux();
void copyAux();
void removeBuffer(u32 _address);
@ -92,7 +91,6 @@ public:
FrameBuffer * getCurrent() const {return m_pCurrent;}
void renderBuffer(u32 _address);
void setBufferChanged(f32 _maxY);
void correctHeight();
void clearBuffersChanged();
void setCurrentDrawBuffer() const;
void fillRDRAM(s32 ulx, s32 uly, s32 lrx, s32 lry);

View File

@ -19,6 +19,14 @@ using namespace std;
VIInfo VI;
u16 VI_GetMaxBufferHeight(u16 _width)
{
if (_width > 320 || VI.interlaced)
return VI.PAL ? 580 : 480;
return VI.PAL ? 290 : 240;
}
void VI_UpdateSize()
{
const f32 xScale = _FIXED2FLOAT( _SHIFTR( *REG.VI_X_SCALE, 0, 12 ), 10 );
@ -27,8 +35,8 @@ void VI_UpdateSize()
const u32 vScale = _SHIFTR(*REG.VI_Y_SCALE, 0, 12);
// f32 yOffset = _FIXED2FLOAT( _SHIFTR( *REG.VI_Y_SCALE, 16, 12 ), 10 );
const u32 hEnd = _SHIFTR( *REG.VI_H_START, 0, 10 );
const u32 hStart = _SHIFTR( *REG.VI_H_START, 16, 10 );
// const u32 hEnd = _SHIFTR( *REG.VI_H_START, 0, 10 );
// const u32 hStart = _SHIFTR( *REG.VI_H_START, 16, 10 );
// These are in half-lines, so shift an extra bit
const u32 vEnd = _SHIFTR( *REG.VI_V_START, 0, 10 );
@ -77,8 +85,10 @@ void VI_UpdateSize()
if (config.frameBufferEmulation.enable && ((config.generalEmulation.hacks & hack_ZeldaMM) == 0) &&
((interlacedPrev != VI.interlaced) ||
(VI.width > 0 && VI.width != VI.widthPrev) ||
(!VI.interlaced && pDepthBuffer != nullptr && pDepthBuffer->m_width != VI.width) ||
((config.generalEmulation.hacks & hack_ignoreVIHeightChange) == 0 && pBuffer != nullptr && pBuffer->m_height != VI.height))
(!VI.interlaced && pDepthBuffer != nullptr && pDepthBuffer->m_width != VI.width)
)// ||
// ((config.generalEmulation.hacks & hack_ignoreVIHeightChange) == 0 && pBuffer != nullptr && pBuffer->m_height != VI.height))
) {
fbList.removeBuffers(VI.widthPrev);
fbList.removeBuffers(VI.width);
@ -148,7 +158,7 @@ void VI_UpdateScreen()
}
const u32 size = *REG.VI_STATUS & 3;
if (VI.height > 0 && size > G_IM_SIZ_8b && VI.width > 0)
frameBufferList().saveBuffer(*REG.VI_ORIGIN, G_IM_FMT_RGBA, size, VI.width, VI.height, true);
frameBufferList().saveBuffer(*REG.VI_ORIGIN, G_IM_FMT_RGBA, size, VI.width, true);
}
}
// if ((((*REG.VI_STATUS) & 3) > 0) && (gDP.colorImage.changed || bCFB)) { // Does not work in release build!!!

View File

@ -20,6 +20,7 @@ extern VIInfo VI;
void VI_UpdateSize();
void VI_UpdateScreen();
u16 VI_GetMaxBufferHeight(u16 _width);
#endif

View File

@ -132,32 +132,13 @@ void gDPSetColorImage( u32 format, u32 size, u32 width, u32 address )
address = RSP_SegmentToPhysical( address );
if (gDP.colorImage.address != address || gDP.colorImage.width != width || gDP.colorImage.size != size) {
u32 height = 1;
if (width == VI.width)
height = VI.height > 0 ? VI.height : gDP.scissor.lry;
else if (!RSP.bLLE && width == gDP.scissor.lrx && width == gSP.viewport.width) {
height = max(gDP.scissor.lry, gSP.viewport.height);
if (VI.height > 0)
height = min(height, VI.height);
} else if (width == gDP.scissor.lrx)
height = gDP.scissor.lry;
else if (width <= 64)
height = width;
else if (!RSP.bLLE && gSP.viewport.height > 0)
height = gSP.viewport.height;
else
height = VI.height > 0 ? VI.height : gDP.scissor.lry;
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;
frameBufferList().saveBuffer(address, (u16)format, (u16)size, (u16)width, false);
}
gDP.colorImage.format = format;
gDP.colorImage.size = size;
gDP.colorImage.width = width;
gDP.colorImage.height = 0;
gDP.colorImage.address = address;
#ifdef DEBUG
@ -711,8 +692,6 @@ void gDPSetScissor( u32 mode, f32 ulx, f32 uly, f32 lrx, f32 lry )
gDP.changed |= CHANGED_SCISSOR;
frameBufferList().correctHeight();
if (config.video.cropMode == Config::cmAuto && gDP.depthImageAddress != gDP.colorImage.address) {
const u32 maxCropH = VI.width / 16;
const u32 maxCropV = VI.height / 10;