2015-01-30 13:59:52 +00:00
|
|
|
#include <assert.h>
|
|
|
|
|
|
|
|
#include "N64.h"
|
|
|
|
#include "gSP.h"
|
|
|
|
#include "PostProcessor.h"
|
2015-01-31 07:14:13 +00:00
|
|
|
#include "FrameBuffer.h"
|
2015-01-31 07:50:06 +00:00
|
|
|
#include "Config.h"
|
2020-10-21 17:34:08 +00:00
|
|
|
#include "VI.h"
|
2015-01-30 13:59:52 +00:00
|
|
|
|
2017-01-01 17:30:48 +00:00
|
|
|
#include <Graphics/Context.h>
|
|
|
|
#include <Graphics/Parameters.h>
|
2017-01-15 07:57:25 +00:00
|
|
|
#include "DisplayWindow.h"
|
2017-01-01 17:30:48 +00:00
|
|
|
|
2017-01-21 12:48:02 +00:00
|
|
|
using namespace graphics;
|
|
|
|
|
2017-03-10 06:04:13 +00:00
|
|
|
PostProcessor::PostProcessor()
|
2017-10-24 08:43:41 +00:00
|
|
|
: m_pTextureOriginal(nullptr)
|
2017-03-10 06:04:13 +00:00
|
|
|
{}
|
|
|
|
|
|
|
|
void PostProcessor::_createResultBuffer(const FrameBuffer * _pMainBuffer)
|
2015-01-30 13:59:52 +00:00
|
|
|
{
|
2017-03-10 06:04:13 +00:00
|
|
|
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;
|
2015-01-31 07:14:13 +00:00
|
|
|
pTexture->format = G_IM_FMT_RGBA;
|
|
|
|
pTexture->clampS = 1;
|
|
|
|
pTexture->clampT = 1;
|
2015-05-06 13:47:12 +00:00
|
|
|
pTexture->frameBufferTexture = CachedTexture::fbOneSample;
|
2015-01-31 07:14:13 +00:00
|
|
|
pTexture->maskS = 0;
|
|
|
|
pTexture->maskT = 0;
|
|
|
|
pTexture->mirrorS = 0;
|
|
|
|
pTexture->mirrorT = 0;
|
2019-05-08 14:04:24 +00:00
|
|
|
pTexture->width = pMainTexture->width;
|
|
|
|
pTexture->height = pMainTexture->height;
|
|
|
|
pTexture->textureBytes = pTexture->width * pTexture->height * 4;
|
2015-01-31 07:14:13 +00:00
|
|
|
|
2017-01-21 12:48:02 +00:00
|
|
|
Context::InitTextureParams initParams;
|
|
|
|
initParams.handle = pTexture->name;
|
2019-05-08 14:04:24 +00:00
|
|
|
initParams.width = pTexture->width;
|
|
|
|
initParams.height = pTexture->height;
|
2017-02-14 04:47:10 +00:00
|
|
|
initParams.internalFormat = gfxContext.convertInternalTextureFormat(u32(internalcolorFormat::RGBA8));
|
2017-01-28 09:52:09 +00:00
|
|
|
initParams.format = colorFormat::RGBA;
|
2017-01-21 12:48:02 +00:00
|
|
|
initParams.dataType = datatype::UNSIGNED_BYTE;
|
2017-01-01 17:30:48 +00:00
|
|
|
gfxContext.init2DTexture(initParams);
|
|
|
|
|
2017-01-21 12:48:02 +00:00
|
|
|
Context::TexParameters setParams;
|
|
|
|
setParams.handle = pTexture->name;
|
2017-01-28 09:52:09 +00:00
|
|
|
setParams.target = textureTarget::TEXTURE_2D;
|
2017-01-21 12:48:02 +00:00
|
|
|
setParams.minFilter = textureParameters::FILTER_NEAREST;
|
|
|
|
setParams.magFilter = textureParameters::FILTER_NEAREST;
|
2017-01-01 17:30:48 +00:00
|
|
|
gfxContext.setTextureParameters(setParams);
|
2016-04-02 12:56:07 +00:00
|
|
|
|
2017-01-21 12:48:02 +00:00
|
|
|
Context::FrameBufferRenderTarget bufTarget;
|
2017-03-10 06:04:13 +00:00
|
|
|
bufTarget.bufferHandle = m_pResultBuffer->m_FBO;
|
2017-01-21 12:48:02 +00:00
|
|
|
bufTarget.bufferTarget = bufferTarget::DRAW_FRAMEBUFFER;
|
|
|
|
bufTarget.attachment = bufferAttachment::COLOR_ATTACHMENT0;
|
2017-01-28 09:52:09 +00:00
|
|
|
bufTarget.textureTarget = textureTarget::TEXTURE_2D;
|
2017-03-10 06:04:13 +00:00
|
|
|
bufTarget.textureHandle = pTexture->name;
|
2017-01-02 15:56:47 +00:00
|
|
|
gfxContext.addFrameBufferRenderTarget(bufTarget);
|
2017-01-22 13:43:05 +00:00
|
|
|
assert(!gfxContext.isFramebufferError());
|
2016-04-02 12:56:07 +00:00
|
|
|
}
|
|
|
|
|
2015-12-23 10:21:55 +00:00
|
|
|
void PostProcessor::init()
|
|
|
|
{
|
2018-08-26 10:03:02 +00:00
|
|
|
m_gammaCorrectionProgram.reset(gfxContext.createGammaCorrectionShader());
|
2018-09-09 09:34:00 +00:00
|
|
|
m_postprocessingList.emplace_front(std::mem_fn(&PostProcessor::_doGammaCorrection)); // std::mem_fn to fix compilation with VS 2013
|
|
|
|
if (config.video.fxaa != 0) {
|
2018-08-26 10:03:02 +00:00
|
|
|
m_FXAAProgram.reset(gfxContext.createFXAAShader());
|
2018-09-09 09:34:00 +00:00
|
|
|
m_postprocessingList.emplace_front(std::mem_fn(&PostProcessor::_doFXAA));
|
|
|
|
}
|
2015-12-23 10:21:55 +00:00
|
|
|
}
|
|
|
|
|
2018-08-26 10:03:02 +00:00
|
|
|
void PostProcessor::destroy()
|
2015-12-23 10:22:30 +00:00
|
|
|
{
|
2018-09-09 09:34:00 +00:00
|
|
|
m_postprocessingList.clear();
|
2017-01-18 15:39:10 +00:00
|
|
|
m_gammaCorrectionProgram.reset();
|
2018-08-26 10:03:02 +00:00
|
|
|
m_FXAAProgram.reset();
|
2017-03-10 06:04:13 +00:00
|
|
|
m_pResultBuffer.reset();
|
2015-12-23 10:21:55 +00:00
|
|
|
}
|
|
|
|
|
2018-09-09 09:34:00 +00:00
|
|
|
const PostProcessor::PostprocessingList & PostProcessor::getPostprocessingList() const
|
|
|
|
{
|
|
|
|
return m_postprocessingList;
|
|
|
|
}
|
|
|
|
|
2015-01-30 13:59:52 +00:00
|
|
|
PostProcessor & PostProcessor::get()
|
|
|
|
{
|
|
|
|
static PostProcessor processor;
|
|
|
|
return processor;
|
|
|
|
}
|
|
|
|
|
2015-12-23 10:22:30 +00:00
|
|
|
void PostProcessor::_preDraw(FrameBuffer * _pBuffer)
|
2015-01-30 13:59:52 +00:00
|
|
|
{
|
2021-06-01 12:40:49 +00:00
|
|
|
if (!m_pResultBuffer || m_pResultBuffer->m_width != _pBuffer->m_width || m_pResultBuffer->m_height != _pBuffer->m_height ||
|
2020-12-20 00:18:38 +00:00
|
|
|
m_pResultBuffer->m_scale != _pBuffer->m_scale)
|
2017-03-10 06:04:13 +00:00
|
|
|
_createResultBuffer(_pBuffer);
|
2017-01-18 15:39:10 +00:00
|
|
|
|
2016-05-14 12:11:45 +00:00
|
|
|
if (_pBuffer->m_pTexture->frameBufferTexture == CachedTexture::fbMultiSample) {
|
|
|
|
_pBuffer->resolveMultisampledTexture(true);
|
|
|
|
m_pTextureOriginal = _pBuffer->m_pResolveTexture;
|
2016-04-02 12:21:03 +00:00
|
|
|
} else
|
|
|
|
m_pTextureOriginal = _pBuffer->m_pTexture;
|
2015-01-30 13:59:52 +00:00
|
|
|
|
2017-01-21 12:48:02 +00:00
|
|
|
gfxContext.bindFramebuffer(bufferTarget::READ_FRAMEBUFFER,
|
2018-04-03 15:08:06 +00:00
|
|
|
ObjectHandle::defaultFramebuffer);
|
2015-12-23 10:22:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void PostProcessor::_postDraw()
|
|
|
|
{
|
2017-01-21 12:48:02 +00:00
|
|
|
gfxContext.bindFramebuffer(bufferTarget::DRAW_FRAMEBUFFER,
|
2018-04-03 15:08:06 +00:00
|
|
|
ObjectHandle::defaultFramebuffer);
|
2017-01-18 15:39:10 +00:00
|
|
|
|
|
|
|
gfxContext.resetShaderProgram();
|
2015-12-23 10:22:30 +00:00
|
|
|
}
|
|
|
|
|
2019-11-30 08:31:43 +00:00
|
|
|
FrameBuffer * PostProcessor::_doPostProcessing(FrameBuffer * _pBuffer, graphics::ShaderProgram * _pShader)
|
2016-04-02 12:56:07 +00:00
|
|
|
{
|
2015-12-23 10:22:30 +00:00
|
|
|
_preDraw(_pBuffer);
|
|
|
|
|
2017-01-21 12:48:02 +00:00
|
|
|
gfxContext.bindFramebuffer(bufferTarget::DRAW_FRAMEBUFFER,
|
|
|
|
ObjectHandle(m_pResultBuffer->m_FBO));
|
2017-01-14 07:44:53 +00:00
|
|
|
|
|
|
|
CachedTexture * pDstTex = m_pResultBuffer->m_pTexture;
|
2017-01-18 15:39:10 +00:00
|
|
|
GraphicsDrawer::CopyRectParams copyParams;
|
|
|
|
copyParams.srcX0 = 0;
|
|
|
|
copyParams.srcY0 = 0;
|
2019-05-08 14:04:24 +00:00
|
|
|
copyParams.srcX1 = m_pTextureOriginal->width;
|
|
|
|
copyParams.srcY1 = m_pTextureOriginal->height;
|
|
|
|
copyParams.srcWidth = m_pTextureOriginal->width;
|
|
|
|
copyParams.srcHeight = m_pTextureOriginal->height;
|
2017-01-18 15:39:10 +00:00
|
|
|
copyParams.dstX0 = 0;
|
|
|
|
copyParams.dstY0 = 0;
|
2019-05-08 14:04:24 +00:00
|
|
|
copyParams.dstX1 = pDstTex->width;
|
|
|
|
copyParams.dstY1 = pDstTex->height;
|
|
|
|
copyParams.dstWidth = pDstTex->width;
|
|
|
|
copyParams.dstHeight = pDstTex->height;
|
2017-01-18 15:39:10 +00:00
|
|
|
copyParams.tex[0] = m_pTextureOriginal;
|
2017-01-21 12:48:02 +00:00
|
|
|
copyParams.filter = textureParameters::FILTER_NEAREST;
|
2018-08-26 05:08:02 +00:00
|
|
|
copyParams.combiner = _pShader;
|
2017-01-18 15:39:10 +00:00
|
|
|
|
|
|
|
dwnd().getDrawer().copyTexturedRect(copyParams);
|
2015-12-23 10:22:30 +00:00
|
|
|
|
|
|
|
_postDraw();
|
2017-03-10 06:04:13 +00:00
|
|
|
return m_pResultBuffer.get();
|
2015-01-30 13:59:52 +00:00
|
|
|
}
|
2016-10-29 17:33:05 +00:00
|
|
|
|
2018-09-09 09:34:00 +00:00
|
|
|
FrameBuffer * PostProcessor::_doGammaCorrection(FrameBuffer * _pBuffer)
|
2016-10-29 17:33:05 +00:00
|
|
|
{
|
|
|
|
if (_pBuffer == nullptr)
|
|
|
|
return nullptr;
|
|
|
|
|
2020-10-21 17:34:08 +00:00
|
|
|
if (((*REG.VI_STATUS & VI_STATUS_GAMMA_ENABLED) | config.gammaCorrection.force) == 0)
|
2016-10-29 17:33:05 +00:00
|
|
|
return _pBuffer;
|
|
|
|
|
2018-08-26 05:08:02 +00:00
|
|
|
return _doPostProcessing(_pBuffer, m_gammaCorrectionProgram.get());
|
|
|
|
}
|
2017-01-18 15:39:10 +00:00
|
|
|
|
2018-09-09 09:34:00 +00:00
|
|
|
FrameBuffer * PostProcessor::_doFXAA(FrameBuffer * _pBuffer)
|
2018-08-26 10:03:02 +00:00
|
|
|
{
|
|
|
|
if (_pBuffer == nullptr)
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
if (config.video.fxaa == 0)
|
|
|
|
return _pBuffer;
|
|
|
|
|
|
|
|
return _doPostProcessing(_pBuffer, m_FXAAProgram.get());
|
|
|
|
}
|