mirror of
https://github.com/blawar/GLideN64.git
synced 2024-07-04 10:03:36 +00:00
Add support for frame buffers, which are inside of some other frame buffer.
Fixed Superbowling: black screen in menu and game #116
This commit is contained in:
parent
c8b6d35597
commit
5538c7b4bb
|
@ -442,7 +442,11 @@ void DepthBufferList::saveBuffer(u32 _address)
|
||||||
if (pFrameBuffer != nullptr)
|
if (pFrameBuffer != nullptr)
|
||||||
pFrameBuffer->m_isDepthBuffer = true;
|
pFrameBuffer->m_isDepthBuffer = true;
|
||||||
|
|
||||||
DepthBuffer * pDepthBuffer = findBuffer(_address);
|
DepthBuffer * pDepthBuffer = nullptr;
|
||||||
|
if (pFrameBuffer != nullptr && pFrameBuffer->m_startAddress != _address)
|
||||||
|
pDepthBuffer = findBuffer(pFrameBuffer->m_startAddress);
|
||||||
|
else
|
||||||
|
pDepthBuffer = findBuffer(_address);
|
||||||
|
|
||||||
if (pDepthBuffer != nullptr && pFrameBuffer != nullptr && pDepthBuffer->m_width != pFrameBuffer->m_width) {
|
if (pDepthBuffer != nullptr && pFrameBuffer != nullptr && pDepthBuffer->m_width != pFrameBuffer->m_width) {
|
||||||
removeBuffer(_address);
|
removeBuffer(_address);
|
||||||
|
|
|
@ -36,7 +36,9 @@ FrameBuffer::FrameBuffer()
|
||||||
, m_size(0)
|
, m_size(0)
|
||||||
, m_width(0)
|
, m_width(0)
|
||||||
, m_height(0)
|
, m_height(0)
|
||||||
, m_validityChecked(0)
|
, m_originX(0)
|
||||||
|
, m_originY(0)
|
||||||
|
, m_swapCount(0)
|
||||||
, m_scale(0)
|
, m_scale(0)
|
||||||
, m_copiedToRdram(false)
|
, m_copiedToRdram(false)
|
||||||
, m_fingerprint(false)
|
, m_fingerprint(false)
|
||||||
|
@ -56,6 +58,7 @@ FrameBuffer::FrameBuffer()
|
||||||
, m_copied(false)
|
, m_copied(false)
|
||||||
, m_pFrameBufferCopyTexture(nullptr)
|
, m_pFrameBufferCopyTexture(nullptr)
|
||||||
, m_copyFBO(ObjectHandle::defaultFramebuffer)
|
, m_copyFBO(ObjectHandle::defaultFramebuffer)
|
||||||
|
, m_validityChecked(0)
|
||||||
{
|
{
|
||||||
m_loadTileOrigin.uls = m_loadTileOrigin.ult = 0;
|
m_loadTileOrigin.uls = m_loadTileOrigin.ult = 0;
|
||||||
m_pTexture = textureCache().addFrameBufferTexture(config.video.multisampling != 0);
|
m_pTexture = textureCache().addFrameBufferTexture(config.video.multisampling != 0);
|
||||||
|
@ -189,6 +192,7 @@ void FrameBuffer::init(u32 _address, u16 _format, u16 _size, u16 _width, bool _c
|
||||||
m_cfb = _cfb;
|
m_cfb = _cfb;
|
||||||
m_cleared = false;
|
m_cleared = false;
|
||||||
m_fingerprint = false;
|
m_fingerprint = false;
|
||||||
|
m_swapCount = dwnd().getBuffersSwapCount();
|
||||||
|
|
||||||
const u16 maxHeight = VI_GetMaxBufferHeight(_width);
|
const u16 maxHeight = VI_GetMaxBufferHeight(_width);
|
||||||
_initTexture(_width, maxHeight, _format, _size, m_pTexture);
|
_initTexture(_width, maxHeight, _format, _size, m_pTexture);
|
||||||
|
@ -716,17 +720,63 @@ void FrameBufferList::saveBuffer(u32 _address, u16 _format, u16 _size, u16 _widt
|
||||||
removeIntersections();
|
removeIntersections();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const float scaleX = config.frameBufferEmulation.nativeResFactor == 0 ?
|
||||||
|
wnd.getScaleX() :
|
||||||
|
static_cast<float>(config.frameBufferEmulation.nativeResFactor);
|
||||||
|
|
||||||
if (m_pCurrent == nullptr || m_pCurrent->m_startAddress != _address || m_pCurrent->m_width != _width)
|
if (m_pCurrent == nullptr || m_pCurrent->m_startAddress != _address || m_pCurrent->m_width != _width)
|
||||||
m_pCurrent = findBuffer(_address);
|
m_pCurrent = findBuffer(_address);
|
||||||
const float scaleX = config.frameBufferEmulation.nativeResFactor == 0 ?
|
|
||||||
wnd.getScaleX() :
|
auto isSubBuffer = [_address, _width, _size, &wnd](const FrameBuffer * _pBuffer) -> bool
|
||||||
static_cast<float>(config.frameBufferEmulation.nativeResFactor);
|
{
|
||||||
if (m_pCurrent != nullptr) {
|
if (_pBuffer->m_swapCount == wnd.getBuffersSwapCount() &&
|
||||||
if ((m_pCurrent->m_startAddress != _address) ||
|
!_pBuffer->m_cfb &&
|
||||||
(m_pCurrent->m_width != _width) ||
|
_pBuffer->m_width == _width &&
|
||||||
(m_pCurrent->m_size < _size) ||
|
_pBuffer->m_size == _size)
|
||||||
(m_pCurrent->m_scale != scaleX))
|
|
||||||
{
|
{
|
||||||
|
const u32 stride = _width << _size >> 1;
|
||||||
|
const u32 diffFromStart = _address - _pBuffer->m_startAddress;
|
||||||
|
if (diffFromStart % stride != 0)
|
||||||
|
return true;
|
||||||
|
const u32 diffFromEnd = _pBuffer->m_endAddress - _address + 1;
|
||||||
|
if ((diffFromEnd / stride > 5))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto isOverlappingBuffer = [_address, _width, _size](const FrameBuffer * _pBuffer) -> bool
|
||||||
|
{
|
||||||
|
if (_pBuffer->m_width == _width && _pBuffer->m_size == _size) {
|
||||||
|
const u32 stride = _width << _size >> 1;
|
||||||
|
const u32 diffEnd = _pBuffer->m_endAddress - _address + 1;
|
||||||
|
if ((diffEnd / stride < 5))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (m_pCurrent != nullptr) {
|
||||||
|
m_pCurrent->m_originX = m_pCurrent->m_originY = 0;
|
||||||
|
if ((m_pCurrent->m_startAddress != _address)) {
|
||||||
|
if (isSubBuffer(m_pCurrent)) {
|
||||||
|
const u32 stride = _width << _size >> 1;
|
||||||
|
const u32 addrOffset = _address - m_pCurrent->m_startAddress;
|
||||||
|
m_pCurrent->m_originX = (addrOffset % stride) >> (_size - 1);
|
||||||
|
m_pCurrent->m_originY = addrOffset / stride;
|
||||||
|
gSP.changed |= CHANGED_VIEWPORT;
|
||||||
|
gDP.changed |= CHANGED_SCISSOR;
|
||||||
|
return;
|
||||||
|
} else if (isOverlappingBuffer(m_pCurrent)) {
|
||||||
|
m_pCurrent->m_endAddress = _address - 1;
|
||||||
|
m_pCurrent = nullptr;
|
||||||
|
} else {
|
||||||
|
removeBuffer(m_pCurrent->m_startAddress);
|
||||||
|
m_pCurrent = nullptr;
|
||||||
|
}
|
||||||
|
} else if ((m_pCurrent->m_width != _width) ||
|
||||||
|
(m_pCurrent->m_size < _size) ||
|
||||||
|
(m_pCurrent->m_scale != scaleX)) {
|
||||||
removeBuffer(m_pCurrent->m_startAddress);
|
removeBuffer(m_pCurrent->m_startAddress);
|
||||||
m_pCurrent = nullptr;
|
m_pCurrent = nullptr;
|
||||||
} else {
|
} else {
|
||||||
|
@ -780,6 +830,7 @@ void FrameBufferList::saveBuffer(u32 _address, u16 _format, u16 _size, u16 _widt
|
||||||
m_pCurrent->m_isDepthBuffer = _address == gDP.depthImageAddress;
|
m_pCurrent->m_isDepthBuffer = _address == gDP.depthImageAddress;
|
||||||
m_pCurrent->m_isPauseScreen = m_pCurrent->m_isOBScreen = false;
|
m_pCurrent->m_isPauseScreen = m_pCurrent->m_isOBScreen = false;
|
||||||
m_pCurrent->m_copied = false;
|
m_pCurrent->m_copied = false;
|
||||||
|
m_pCurrent->m_swapCount = wnd.getBuffersSwapCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FrameBufferList::copyAux()
|
void FrameBufferList::copyAux()
|
||||||
|
|
|
@ -29,8 +29,14 @@ struct FrameBuffer
|
||||||
bool _isMarioTennisScoreboard() const;
|
bool _isMarioTennisScoreboard() const;
|
||||||
bool isAuxiliary() const;
|
bool isAuxiliary() const;
|
||||||
|
|
||||||
u32 m_startAddress, m_endAddress;
|
u32 m_startAddress;
|
||||||
u32 m_size, m_width, m_height;
|
u32 m_endAddress;
|
||||||
|
u32 m_size;
|
||||||
|
u32 m_width;
|
||||||
|
u32 m_height;
|
||||||
|
u32 m_originX;
|
||||||
|
u32 m_originY;
|
||||||
|
u32 m_swapCount;
|
||||||
float m_scale;
|
float m_scale;
|
||||||
bool m_copiedToRdram;
|
bool m_copiedToRdram;
|
||||||
bool m_fingerprint;
|
bool m_fingerprint;
|
||||||
|
@ -83,6 +89,7 @@ private:
|
||||||
void _initCopyTexture();
|
void _initCopyTexture();
|
||||||
CachedTexture * _copyFrameBufferTexture();
|
CachedTexture * _copyFrameBufferTexture();
|
||||||
CachedTexture * _getSubTexture(u32 _t);
|
CachedTexture * _getSubTexture(u32 _t);
|
||||||
|
|
||||||
mutable u32 m_validityChecked;
|
mutable u32 m_validityChecked;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -192,18 +192,21 @@ void GraphicsDrawer::updateScissor(FrameBuffer * _pBuffer) const
|
||||||
{
|
{
|
||||||
DisplayWindow & wnd = DisplayWindow::get();
|
DisplayWindow & wnd = DisplayWindow::get();
|
||||||
f32 scaleX, scaleY;
|
f32 scaleX, scaleY;
|
||||||
|
f32 offsetX = 0.0f, offsetY = 0.0f;
|
||||||
if (_pBuffer == nullptr) {
|
if (_pBuffer == nullptr) {
|
||||||
scaleX = wnd.getScaleX();
|
scaleX = wnd.getScaleX();
|
||||||
scaleY = wnd.getScaleY();
|
scaleY = wnd.getScaleY();
|
||||||
} else {
|
} else {
|
||||||
scaleX = _pBuffer->m_scale;
|
scaleX = _pBuffer->m_scale;
|
||||||
scaleY = _pBuffer->m_scale;
|
scaleY = _pBuffer->m_scale;
|
||||||
|
offsetX = f32(_pBuffer->m_originX);
|
||||||
|
offsetY = f32(_pBuffer->m_originY);
|
||||||
}
|
}
|
||||||
|
|
||||||
f32 SX0 = gDP.scissor.ulx;
|
f32 SX0 = gDP.scissor.ulx + offsetX;
|
||||||
f32 SX1 = gDP.scissor.lrx;
|
f32 SX1 = gDP.scissor.lrx + offsetX;
|
||||||
f32 SY0 = gDP.scissor.uly;
|
f32 SY0 = gDP.scissor.uly + offsetY;
|
||||||
f32 SY1 = gDP.scissor.lry;
|
f32 SY1 = gDP.scissor.lry + offsetY;
|
||||||
|
|
||||||
if (u32(SX1) == 512 && (config.generalEmulation.hacks & hack_RE2) != 0) {
|
if (u32(SX1) == 512 && (config.generalEmulation.hacks & hack_RE2) != 0) {
|
||||||
SX1 = f32(*REG.VI_WIDTH);
|
SX1 = f32(*REG.VI_WIDTH);
|
||||||
|
@ -245,10 +248,13 @@ void GraphicsDrawer::_updateViewport() const
|
||||||
const f32 scaleX = pCurrentBuffer->m_scale;
|
const f32 scaleX = pCurrentBuffer->m_scale;
|
||||||
const f32 scaleY = pCurrentBuffer->m_scale;
|
const f32 scaleY = pCurrentBuffer->m_scale;
|
||||||
float Xf = gSP.viewport.vscale[0] < 0 ? (gSP.viewport.x + gSP.viewport.vscale[0] * 2.0f) : gSP.viewport.x;
|
float Xf = gSP.viewport.vscale[0] < 0 ? (gSP.viewport.x + gSP.viewport.vscale[0] * 2.0f) : gSP.viewport.x;
|
||||||
|
Xf += f32(pCurrentBuffer->m_originX);
|
||||||
if (_needAdjustCoordinate(wnd))
|
if (_needAdjustCoordinate(wnd))
|
||||||
Xf = _adjustViewportX(Xf);
|
Xf = _adjustViewportX(Xf);
|
||||||
const s32 X = (s32)(Xf * scaleX);
|
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)(gSP.viewport.y * scaleY);
|
float Yf = gSP.viewport.vscale[1] < 0 ? (gSP.viewport.y + gSP.viewport.vscale[1] * 2.0f) : gSP.viewport.y;
|
||||||
|
Yf += f32(pCurrentBuffer->m_originY);
|
||||||
|
const s32 Y = (s32)(Yf * scaleY);
|
||||||
gfxContext.setViewport(X, Y,
|
gfxContext.setViewport(X, Y,
|
||||||
std::max((s32)(gSP.viewport.width * scaleX), 0), std::max((s32)(gSP.viewport.height * scaleY), 0));
|
std::max((s32)(gSP.viewport.width * scaleX), 0), std::max((s32)(gSP.viewport.height * scaleY), 0));
|
||||||
}
|
}
|
||||||
|
@ -262,6 +268,7 @@ void GraphicsDrawer::_updateScreenCoordsViewport(const FrameBuffer * _pBuffer) c
|
||||||
|
|
||||||
u32 bufferWidth, bufferHeight;
|
u32 bufferWidth, bufferHeight;
|
||||||
f32 viewportScaleX, viewportScaleY;
|
f32 viewportScaleX, viewportScaleY;
|
||||||
|
s32 X = 0, Y = 0;
|
||||||
if (pCurrentBuffer == nullptr) {
|
if (pCurrentBuffer == nullptr) {
|
||||||
bufferWidth = VI.width;
|
bufferWidth = VI.width;
|
||||||
bufferHeight = VI.height;
|
bufferHeight = VI.height;
|
||||||
|
@ -271,9 +278,11 @@ void GraphicsDrawer::_updateScreenCoordsViewport(const FrameBuffer * _pBuffer) c
|
||||||
bufferWidth = pCurrentBuffer->m_width;
|
bufferWidth = pCurrentBuffer->m_width;
|
||||||
bufferHeight = VI_GetMaxBufferHeight(bufferWidth);
|
bufferHeight = VI_GetMaxBufferHeight(bufferWidth);
|
||||||
viewportScaleX = viewportScaleY = pCurrentBuffer->m_scale;
|
viewportScaleX = viewportScaleY = pCurrentBuffer->m_scale;
|
||||||
|
X = static_cast<s32>(pCurrentBuffer->m_originX * viewportScaleX);
|
||||||
|
Y = static_cast<s32>(pCurrentBuffer->m_originY * viewportScaleY);
|
||||||
}
|
}
|
||||||
|
|
||||||
gfxContext.setViewport(0, 0, (s32)(bufferWidth * viewportScaleX), (s32)(bufferHeight * viewportScaleY));
|
gfxContext.setViewport(X, Y, (s32)(bufferWidth * viewportScaleX), (s32)(bufferHeight * viewportScaleY));
|
||||||
gSP.changed |= CHANGED_VIEWPORT;
|
gSP.changed |= CHANGED_VIEWPORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user