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

186 lines
5.6 KiB
C++

#include <assert.h>
#include "N64.h"
#include "gSP.h"
#include "PostProcessor.h"
#include "FrameBuffer.h"
#include "Config.h"
#include <Graphics/Context.h>
#include <Graphics/Parameters.h>
#include "DisplayWindow.h"
using namespace graphics;
PostProcessor::PostProcessor()
: m_pTextureOriginal(nullptr)
{}
void PostProcessor::_createResultBuffer(const FrameBuffer * _pMainBuffer)
{
m_pResultBuffer.reset(new FrameBuffer());
m_pResultBuffer->m_width = _pMainBuffer->m_width;
m_pResultBuffer->m_height = _pMainBuffer->m_height;
m_pResultBuffer->m_scale = _pMainBuffer->m_scale;
const CachedTexture * pMainTexture = _pMainBuffer->m_pTexture;
CachedTexture * pTexture = m_pResultBuffer->m_pTexture;
pTexture->format = G_IM_FMT_RGBA;
pTexture->clampS = 1;
pTexture->clampT = 1;
pTexture->frameBufferTexture = CachedTexture::fbOneSample;
pTexture->maskS = 0;
pTexture->maskT = 0;
pTexture->mirrorS = 0;
pTexture->mirrorT = 0;
pTexture->realWidth = pMainTexture->realWidth;
pTexture->realHeight = pMainTexture->realHeight;
pTexture->textureBytes = pTexture->realWidth * pTexture->realHeight * 4;
Context::InitTextureParams initParams;
initParams.handle = pTexture->name;
initParams.width = pTexture->realWidth;
initParams.height = pTexture->realHeight;
initParams.internalFormat = gfxContext.convertInternalTextureFormat(u32(internalcolorFormat::RGBA8));
initParams.format = colorFormat::RGBA;
initParams.dataType = datatype::UNSIGNED_BYTE;
gfxContext.init2DTexture(initParams);
Context::TexParameters setParams;
setParams.handle = pTexture->name;
setParams.target = textureTarget::TEXTURE_2D;
setParams.minFilter = textureParameters::FILTER_NEAREST;
setParams.magFilter = textureParameters::FILTER_NEAREST;
gfxContext.setTextureParameters(setParams);
Context::FrameBufferRenderTarget bufTarget;
bufTarget.bufferHandle = m_pResultBuffer->m_FBO;
bufTarget.bufferTarget = bufferTarget::DRAW_FRAMEBUFFER;
bufTarget.attachment = bufferAttachment::COLOR_ATTACHMENT0;
bufTarget.textureTarget = textureTarget::TEXTURE_2D;
bufTarget.textureHandle = pTexture->name;
gfxContext.addFrameBufferRenderTarget(bufTarget);
assert(!gfxContext.isFramebufferError());
}
void PostProcessor::init()
{
m_gammaCorrectionProgram.reset(gfxContext.createGammaCorrectionShader());
m_postprocessingList.emplace_front(std::mem_fn(&PostProcessor::_doGammaCorrection)); // std::mem_fn to fix compilation with VS 2013
if (config.video.fxaa != 0) {
m_FXAAProgram.reset(gfxContext.createFXAAShader());
m_postprocessingList.emplace_front(std::mem_fn(&PostProcessor::_doFXAA));
}
if (config.generalEmulation.enableBlitScreenWorkaround != 0) {
m_orientationCorrectionProgram.reset(gfxContext.createOrientationCorrectionShader());
m_postprocessingList.emplace_front(std::mem_fn(&PostProcessor::_doOrientationCorrection));
}
}
void PostProcessor::destroy()
{
m_postprocessingList.clear();
m_gammaCorrectionProgram.reset();
m_FXAAProgram.reset();
m_orientationCorrectionProgram.reset();
m_pResultBuffer.reset();
}
const PostProcessor::PostprocessingList & PostProcessor::getPostprocessingList() const
{
return m_postprocessingList;
}
PostProcessor & PostProcessor::get()
{
static PostProcessor processor;
return processor;
}
void PostProcessor::_preDraw(FrameBuffer * _pBuffer)
{
if (!m_pResultBuffer || m_pResultBuffer->m_width != _pBuffer->m_width)
_createResultBuffer(_pBuffer);
if (_pBuffer->m_pTexture->frameBufferTexture == CachedTexture::fbMultiSample) {
_pBuffer->resolveMultisampledTexture(true);
m_pTextureOriginal = _pBuffer->m_pResolveTexture;
} else
m_pTextureOriginal = _pBuffer->m_pTexture;
gfxContext.bindFramebuffer(bufferTarget::READ_FRAMEBUFFER,
ObjectHandle::defaultFramebuffer);
}
void PostProcessor::_postDraw()
{
gfxContext.bindFramebuffer(bufferTarget::DRAW_FRAMEBUFFER,
ObjectHandle::defaultFramebuffer);
gfxContext.resetShaderProgram();
}
FrameBuffer * PostProcessor::_doPostProcessing(FrameBuffer * _pBuffer, graphics::ShaderProgram * _pShader)
{
_preDraw(_pBuffer);
gfxContext.bindFramebuffer(bufferTarget::DRAW_FRAMEBUFFER,
ObjectHandle(m_pResultBuffer->m_FBO));
CachedTexture * pDstTex = m_pResultBuffer->m_pTexture;
GraphicsDrawer::CopyRectParams copyParams;
copyParams.srcX0 = 0;
copyParams.srcY0 = 0;
copyParams.srcX1 = m_pTextureOriginal->realWidth;
copyParams.srcY1 = m_pTextureOriginal->realHeight;
copyParams.srcWidth = m_pTextureOriginal->realWidth;
copyParams.srcHeight = m_pTextureOriginal->realHeight;
copyParams.dstX0 = 0;
copyParams.dstY0 = 0;
copyParams.dstX1 = pDstTex->realWidth;
copyParams.dstY1 = pDstTex->realHeight;
copyParams.dstWidth = pDstTex->realWidth;
copyParams.dstHeight = pDstTex->realHeight;
copyParams.tex[0] = m_pTextureOriginal;
copyParams.filter = textureParameters::FILTER_NEAREST;
copyParams.combiner = _pShader;
dwnd().getDrawer().copyTexturedRect(copyParams);
_postDraw();
return m_pResultBuffer.get();
}
FrameBuffer * PostProcessor::_doGammaCorrection(FrameBuffer * _pBuffer)
{
if (_pBuffer == nullptr)
return nullptr;
if (((*REG.VI_STATUS & 8) | config.gammaCorrection.force) == 0)
return _pBuffer;
return _doPostProcessing(_pBuffer, m_gammaCorrectionProgram.get());
}
FrameBuffer * PostProcessor::_doOrientationCorrection(FrameBuffer * _pBuffer)
{
if (_pBuffer == nullptr)
return nullptr;
if (config.generalEmulation.enableBlitScreenWorkaround == 0)
return _pBuffer;
return _doPostProcessing(_pBuffer, m_orientationCorrectionProgram.get());
}
FrameBuffer * PostProcessor::_doFXAA(FrameBuffer * _pBuffer)
{
if (_pBuffer == nullptr)
return nullptr;
if (config.video.fxaa == 0)
return _pBuffer;
return _doPostProcessing(_pBuffer, m_FXAAProgram.get());
}