1
0
mirror of https://github.com/blawar/GLideN64.git synced 2024-07-02 09:03:37 +00:00

Keep a color copy FBO and texture per N64 frame buffer

This commit is contained in:
fzurita 2021-04-17 20:45:47 -04:00 committed by Sergey Lipskiy
parent 5f7a7cadc2
commit 43a5d16905
4 changed files with 132 additions and 112 deletions

View File

@ -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;
}

View File

@ -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<u32, 3> m_allowedRealWidths;
std::unique_ptr<graphics::ColorBufferReader> m_bufferReader;
};
void copyWhiteToRDRAM(FrameBuffer * _pBuffer);

View File

@ -25,6 +25,7 @@
#include <Graphics/Context.h>
#include <Graphics/Parameters.h>
#include <Graphics/ColorBufferReader.h>
#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;

View File

@ -3,6 +3,7 @@
#include <list>
#include <vector>
#include <memory>
#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<graphics::ColorBufferReader> 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;
};