mirror of
https://github.com/blawar/GLideN64.git
synced 2024-07-04 10:03:36 +00:00
Keep a color copy FBO and texture per N64 frame buffer
This commit is contained in:
parent
5f7a7cadc2
commit
43a5d16905
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue
Block a user