update gliden64

This commit is contained in:
Logan McNaughton committed 2021-04-19 16:21:50 -06:00
1 parent 525b136e9c
commit d753e48ca1
28 files changed
+590 -441

No files matched your search

+38 -157
View File
@@ -12,17 +12,6 @@
#include "Log.h"
#include "MemoryStatus.h"
/*
#include "ColorBufferToRDRAM_GL.h"
#include "ColorBufferToRDRAM_BufferStorageExt.h"
#elif defined(OS_ANDROID) && defined (GLES2)
#include "ColorBufferToRDRAM_GL.h"
#include "ColorBufferToRDRAM_GLES.h"
#else
#include "ColorBufferToRDRAMStub.h"
#endif
*/
#include <Graphics/Context.h>
#include <Graphics/Parameters.h>
#include <Graphics/ColorBufferReader.h>
@@ -32,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;
@@ -52,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)
@@ -164,15 +69,7 @@ bool ColorBufferToRDRAM::_prepareCopy(u32& _startAddress)
if (bufferHeight == 0)
return false;
if(m_pTexture == nullptr ||
m_pTexture->width != _getRealWidth(pBuffer->m_width) ||
m_pTexture->height != VI_GetMaxBufferHeight(_getRealWidth(pBuffer->m_width)))
{
_destroyFBTexure();
m_lastBufferWidth = _getRealWidth(pBuffer->m_width);
_initFBTexture();
}
CachedTexture* colorBufferTexture = pBuffer->getColorFbTexture();
m_pCurFrameBuffer = pBuffer;
@@ -190,47 +87,43 @@ bool ColorBufferToRDRAM::_prepareCopy(u32& _startAddress)
readBuffer = m_pCurFrameBuffer->m_FBO;
}
if (m_pCurFrameBuffer->m_scale != 1.0f) {
u32 x0 = 0;
u32 width;
if (config.frameBufferEmulation.nativeResFactor == 0) {
const u32 screenWidth = wnd.getWidth();
width = screenWidth;
if (wnd.isAdjustScreen()) {
width = static_cast<u32>(screenWidth*wnd.getAdjustScale());
x0 = (screenWidth - width) / 2;
}
} else {
width = m_pCurFrameBuffer->m_pTexture->width;
u32 x0 = 0;
u32 width;
if (config.frameBufferEmulation.nativeResFactor == 0) {
const u32 screenWidth = wnd.getWidth();
width = screenWidth;
if (wnd.isAdjustScreen()) {
width = static_cast<u32>(screenWidth*wnd.getAdjustScale());
x0 = (screenWidth - width) / 2;
}
u32 height = (u32)(bufferHeight * m_pCurFrameBuffer->m_scale);
CachedTexture * pInputTexture = m_pCurFrameBuffer->m_pTexture;
GraphicsDrawer::BlitOrCopyRectParams blitParams;
blitParams.srcX0 = x0;
blitParams.srcY0 = 0;
blitParams.srcX1 = x0 + width;
blitParams.srcY1 = height;
blitParams.srcWidth = pInputTexture->width;
blitParams.srcHeight = pInputTexture->height;
blitParams.dstX0 = 0;
blitParams.dstY0 = 0;
blitParams.dstX1 = m_pCurFrameBuffer->m_width;
blitParams.dstY1 = bufferHeight;
blitParams.dstWidth = m_pTexture->width;
blitParams.dstHeight = m_pTexture->height;
blitParams.filter = textureParameters::FILTER_LINEAR;
blitParams.tex[0] = pInputTexture;
blitParams.combiner = CombinerInfo::get().getTexrectDownscaleCopyProgram();
blitParams.readBuffer = readBuffer;
blitParams.drawBuffer = m_FBO;
blitParams.mask = blitMask::COLOR_BUFFER;
wnd.getDrawer().blitOrCopyTexturedRect(blitParams);
gfxContext.bindFramebuffer(bufferTarget::READ_FRAMEBUFFER, m_FBO);
} else {
gfxContext.bindFramebuffer(bufferTarget::READ_FRAMEBUFFER, readBuffer);
width = m_pCurFrameBuffer->m_pTexture->width;
}
u32 height = (u32)(bufferHeight * m_pCurFrameBuffer->m_scale);
CachedTexture * pInputTexture = m_pCurFrameBuffer->m_pTexture;
GraphicsDrawer::BlitOrCopyRectParams blitParams;
blitParams.srcX0 = x0;
blitParams.srcY0 = 0;
blitParams.srcX1 = x0 + width;
blitParams.srcY1 = height;
blitParams.srcWidth = pInputTexture->width;
blitParams.srcHeight = pInputTexture->height;
blitParams.dstX0 = 0;
blitParams.dstY0 = 0;
blitParams.dstX1 = m_pCurFrameBuffer->m_width;
blitParams.dstY1 = bufferHeight;
blitParams.dstWidth = colorBufferTexture->width;
blitParams.dstHeight = colorBufferTexture->height;
blitParams.filter = m_pCurFrameBuffer->m_scale == 1.0f ? textureParameters::FILTER_NEAREST : textureParameters::FILTER_LINEAR;
blitParams.tex[0] = pInputTexture;
blitParams.combiner = CombinerInfo::get().getTexrectDownscaleCopyProgram();
blitParams.readBuffer = readBuffer;
blitParams.drawBuffer = pBuffer->getColorFbFbo();
blitParams.mask = blitMask::COLOR_BUFFER;
wnd.getDrawer().blitOrCopyTexturedRect(blitParams);
gfxContext.bindFramebuffer(bufferTarget::READ_FRAMEBUFFER, pBuffer->getColorFbFbo());
m_frameCount = curFrame;
m_startAddress = _startAddress;
@@ -312,7 +205,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;
@@ -336,23 +229,11 @@ 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;
}
u32 ColorBufferToRDRAM::_getRealWidth(u32 _viWidth)
{
u32 index = 0;
const u32 maxIndex = static_cast<u32>(m_allowedRealWidths.size()) - 1;
while (index < maxIndex && _viWidth > m_allowedRealWidths[index])
{
++index;
}
return m_allowedRealWidths[index];
}
void ColorBufferToRDRAM::copyToRDRAM(u32 _address, bool _sync)
{
if (!isMemoryWritable(RDRAM + _address, gDP.colorImage.width << gDP.colorImage.size >> 1))
@@ -29,8 +29,6 @@ private:
ColorBufferToRDRAM(const ColorBufferToRDRAM &) = delete;
virtual ~ColorBufferToRDRAM();
CachedTexture * m_pTexture;
union RGBA {
struct {
u8 r, g, b, a;
@@ -38,32 +36,20 @@ private:
u32 raw;
};
void _initFBTexture(void);
void _destroyFBTexure(void);
bool _prepareCopy(u32& _startAddress);
void _copy(u32 _startAddress, u32 _endAddress, bool _sync);
u32 _getRealWidth(u32 _viWidth);
// Convert pixel from video memory to N64 buffer format.
static u8 _RGBAtoR8(u8 _c, u32 x, u32 y);
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);
@@ -179,7 +179,6 @@ u32 RGBA32ToABGR32(u32 col, bool _fullAlpha)
void RDRAMtoColorBuffer::_copyFromRDRAM(u32 _height, bool _fullAlpha)
{
Cleaner cleaner(this);
ValueKeeper<u32> otherMode(gSP.clipRatio, 1U);
const u32 address = m_pCurBuffer->m_startAddress;
const u32 width = m_pCurBuffer->m_width;
const u32 height = _height;
+5
View File
@@ -64,6 +64,7 @@ void Config::resetToDefaults()
graphics2D.correctTexrectCoords = tcDisable;
graphics2D.enableNativeResTexrects = NativeResTexrectsMode::ntDisable;
graphics2D.bgMode = BGMode::bgStripped;
graphics2D.enableTexCoordBounds = 0;
frameBufferEmulation.enable = 1;
frameBufferEmulation.copyDepthToRDRAM = cdSoftwareRender;
@@ -173,6 +174,10 @@ const char* Config::hotkeyIniName(u32 _idx)
return "hkHdTexReload";
case Config::HotKey::hkHdTexToggle:
return "hkHdTexToggle";
case Config::HotKey::hkTexCoordBounds:
return "hkTexCoordBounds";
case Config::HotKey::hkNativeResTexrects:
return "hkNativeResTexrects";
case Config::HotKey::hkVsync:
return "hkVsync";
case Config::HotKey::hkFBEmulation:
+3
View File
@@ -92,6 +92,7 @@ struct Config
u32 correctTexrectCoords;
u32 enableNativeResTexrects;
u32 bgMode;
u32 enableTexCoordBounds;
} graphics2D;
enum Aspect {
@@ -221,6 +222,8 @@ struct Config
hkTexDump = 0,
hkHdTexReload,
hkHdTexToggle,
hkTexCoordBounds,
hkNativeResTexrects,
hkVsync,
hkFBEmulation,
hkN64DepthCompare,
+54 -26
View File
@@ -28,6 +28,7 @@
#include "gSP.h"
#include "Combiner.h"
#include "ClipPolygon.h"
#include "DisplayWindow.h"
/*
* vbp is a pointer to a vertex array. The first 3 vertices in that
@@ -289,6 +290,7 @@ void clipInHomogeneousSpace(SPVertex * _pVertices, std::vector<SPVertex> & _vRes
const bool usesColor = pCurrCmb->usesShade();
const bool usesTexture = pCurrCmb->usesTexture();
const float wScale = static_cast<float>(gSP.clipRatio);
const float xScale = dwnd().getAdjustScale();
auto clipVertex = [usesColor, usesTexture](SPVertex const* src, SPVertex * dst, float t)
{
@@ -363,10 +365,10 @@ void clipInHomogeneousSpace(SPVertex * _pVertices, std::vector<SPVertex> & _vRes
switch (_clipPlane) {
case 1:
visible = -pVertex->w * wScale <= pVertex->x;
visible = -pVertex->w * wScale <= pVertex->x * xScale;
break;
case 2:
visible = pVertex->x <= pVertex->w * wScale;
visible = pVertex->x * xScale <= pVertex->w * wScale;
break;
case 3:
visible = -pVertex->w * wScale <= pVertex->y;
@@ -402,36 +404,49 @@ void clipInHomogeneousSpace(SPVertex * _pVertices, std::vector<SPVertex> & _vRes
SPVertex *Vertex3 = _pVertices + fifocp;
float t1, t2;
const float scaledW1 = Vertex1->w * wScale;
const float scaledW2 = Vertex2->w * wScale;
const float scaledW3 = Vertex3->w * wScale;
switch (_clipPlane) {
case 1:
t1 = (Vertex1->x + Vertex1->w * wScale) / (Vertex1->x - Vertex3->x + Vertex1->w * wScale - Vertex3->w * wScale);
t2 = (Vertex2->x + Vertex2->w * wScale) / (Vertex2->x - Vertex3->x + Vertex2->w * wScale - Vertex3->w * wScale);
{
const float scaledX1 = Vertex1->x * xScale;
const float scaledX2 = Vertex2->x * xScale;
const float scaledX3 = Vertex3->x * xScale;
t1 = (scaledX1 + scaledW1) / (scaledX1 - scaledX3 + scaledW1 - scaledW3);
t2 = (scaledX2 + scaledW2) / (scaledX2 - scaledX3 + scaledW2 - scaledW3);
}
break;
case 2:
t1 = (Vertex1->x - Vertex1->w * wScale) / (Vertex1->x - Vertex3->x - Vertex1->w * wScale + Vertex3->w * wScale);
t2 = (Vertex2->x - Vertex2->w * wScale) / (Vertex2->x - Vertex3->x - Vertex2->w * wScale + Vertex3->w * wScale);
{
const float scaledX1 = Vertex1->x * xScale;
const float scaledX2 = Vertex2->x * xScale;
const float scaledX3 = Vertex3->x * xScale;
t1 = (scaledX1 - scaledW1) / (scaledX1 - scaledX3 - scaledW1 + scaledW3);
t2 = (scaledX2 - scaledW2) / (scaledX2 - scaledX3 - scaledW2 + scaledW3);
}
break;
case 3:
t1 = (Vertex1->y + Vertex1->w * wScale) / (Vertex1->y - Vertex3->y + Vertex1->w * wScale - Vertex3->w * wScale);
t2 = (Vertex2->y + Vertex2->w * wScale) / (Vertex2->y - Vertex3->y + Vertex2->w * wScale - Vertex3->w * wScale);
t1 = (Vertex1->y + scaledW1) / (Vertex1->y - Vertex3->y + scaledW1 - scaledW3);
t2 = (Vertex2->y + scaledW2) / (Vertex2->y - Vertex3->y + scaledW2 - scaledW3);
break;
case 4:
t1 = (Vertex1->y - Vertex1->w * wScale) / (Vertex1->y - Vertex3->y - Vertex1->w * wScale + Vertex3->w * wScale);
t2 = (Vertex2->y - Vertex2->w * wScale) / (Vertex2->y - Vertex3->y - Vertex2->w * wScale + Vertex3->w * wScale);
t1 = (Vertex1->y - scaledW1) / (Vertex1->y - Vertex3->y - scaledW1 + scaledW3);
t2 = (Vertex2->y - scaledW2) / (Vertex2->y - Vertex3->y - scaledW2 + scaledW3);
break;
case 5:
t1 = (Vertex1->z + Vertex1->w * wScale) / (Vertex1->z - Vertex3->z + Vertex1->w * wScale - Vertex3->w * wScale);
t2 = (Vertex2->z + Vertex2->w * wScale) / (Vertex2->z - Vertex3->z + Vertex2->w * wScale - Vertex3->w * wScale);
t1 = (Vertex1->z + scaledW1) / (Vertex1->z - Vertex3->z + scaledW1 - scaledW3);
t2 = (Vertex2->z + scaledW2) / (Vertex2->z - Vertex3->z + scaledW2 - scaledW3);
break;
case 6:
t1 = (Vertex1->z - Vertex1->w * wScale) / (Vertex1->z - Vertex3->z - Vertex1->w * wScale + Vertex3->w * wScale);
t2 = (Vertex2->z - Vertex2->w * wScale) / (Vertex2->z - Vertex3->z - Vertex2->w * wScale + Vertex3->w * wScale);
t1 = (Vertex1->z - scaledW1) / (Vertex1->z - Vertex3->z - scaledW1 + scaledW3);
t2 = (Vertex2->z - scaledW2) / (Vertex2->z - Vertex3->z - scaledW2 + scaledW3);
break;
}
@@ -453,36 +468,49 @@ void clipInHomogeneousSpace(SPVertex * _pVertices, std::vector<SPVertex> & _vRes
SPVertex *NewVertex3 = NewVertices + fbcp;
float t1, t2;
const float scaledW1 = Vertex1->w * wScale;
const float scaledW2 = Vertex2->w * wScale;
const float scaledW3 = Vertex3->w * wScale;
switch (_clipPlane) {
case 1:
t1 = (Vertex3->x + Vertex3->w * wScale) / (Vertex3->x - Vertex1->x + Vertex3->w * wScale - Vertex1->w * wScale);
t2 = (Vertex3->x + Vertex3->w * wScale) / (Vertex3->x - Vertex2->x + Vertex3->w * wScale - Vertex2->w * wScale);
{
const float scaledX1 = Vertex1->x * xScale;
const float scaledX2 = Vertex2->x * xScale;
const float scaledX3 = Vertex3->x * xScale;
t1 = (scaledX3 + scaledW3) / (scaledX3 - scaledX1 + scaledW3 - scaledW1);
t2 = (scaledX3 + scaledW3) / (scaledX3 - scaledX2 + scaledW3 - scaledW2);
}
break;
case 2:
t1 = (Vertex3->x - Vertex3->w * wScale) / (Vertex3->x - Vertex1->x - Vertex3->w * wScale + Vertex1->w * wScale);
t2 = (Vertex3->x - Vertex3->w * wScale) / (Vertex3->x - Vertex2->x - Vertex3->w * wScale + Vertex2->w * wScale);
{
const float scaledX1 = Vertex1->x * xScale;
const float scaledX2 = Vertex2->x * xScale;
const float scaledX3 = Vertex3->x * xScale;
t1 = (scaledX3 - scaledW3) / (scaledX3 - scaledX1 - scaledW3 + scaledW1);
t2 = (scaledX3 - scaledW3) / (scaledX3 - scaledX2 - scaledW3 + scaledW2);
}
break;
case 3:
t1 = (Vertex3->y + Vertex3->w * wScale) / (Vertex3->y - Vertex1->y + Vertex3->w * wScale - Vertex1->w * wScale);
t2 = (Vertex3->y + Vertex3->w * wScale) / (Vertex3->y - Vertex2->y + Vertex3->w * wScale - Vertex2->w * wScale);
t1 = (Vertex3->y + scaledW3) / (Vertex3->y - Vertex1->y + scaledW3 - scaledW1);
t2 = (Vertex3->y + scaledW3) / (Vertex3->y - Vertex2->y + scaledW3 - scaledW2);
break;
case 4:
t1 = (Vertex3->y - Vertex3->w * wScale) / (Vertex3->y - Vertex1->y - Vertex3->w * wScale + Vertex1->w * wScale);
t2 = (Vertex3->y - Vertex3->w * wScale) / (Vertex3->y - Vertex2->y - Vertex3->w * wScale + Vertex2->w * wScale);
t1 = (Vertex3->y - scaledW3) / (Vertex3->y - Vertex1->y - scaledW3 + scaledW1);
t2 = (Vertex3->y - scaledW3) / (Vertex3->y - Vertex2->y - scaledW3 + scaledW2);
break;
case 5:
t1 = (Vertex3->z + Vertex3->w * wScale) / (Vertex3->z - Vertex1->z + Vertex3->w * wScale - Vertex1->w * wScale);
t2 = (Vertex3->z + Vertex3->w * wScale) / (Vertex3->z - Vertex2->z + Vertex3->w * wScale - Vertex2->w * wScale);
t1 = (Vertex3->z + scaledW3) / (Vertex3->z - Vertex1->z + scaledW3 - scaledW1);
t2 = (Vertex3->z + scaledW3) / (Vertex3->z - Vertex2->z + scaledW3 - scaledW2);
break;
case 6:
t1 = (Vertex3->z - Vertex3->w * wScale) / (Vertex3->z - Vertex1->z - Vertex3->w * wScale + Vertex1->w * wScale);
t2 = (Vertex3->z - Vertex3->w * wScale) / (Vertex3->z - Vertex2->z - Vertex3->w * wScale + Vertex2->w * wScale);
t1 = (Vertex3->z - scaledW3) / (Vertex3->z - Vertex1->z - scaledW3 + scaledW1);
t2 = (Vertex3->z - scaledW3) / (Vertex3->z - Vertex2->z - scaledW3 + scaledW2);
break;
}
+3 -3
View File
@@ -63,9 +63,9 @@ protected:
u32 m_resizeWidth = 0;
u32 m_resizeHeight = 0;
u32 m_maxMsaa = 0;
f32 m_scaleX = 0;
f32 m_scaleY = 0;
f32 m_adjustScale = 0;
f32 m_scaleX = 0.0f;
f32 m_scaleY = 0.0f;
f32 m_adjustScale = 1.0f;
wchar_t m_strScreenDirectory[PLUGIN_PATH_SIZE];
+109
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;
+15
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;
};
+6
View File
@@ -80,6 +80,10 @@ QString ConfigDialog::_hotkeyDescription(quint32 _idx) const
return tr("Reload HD textures");
case Config::HotKey::hkHdTexToggle:
return tr("Toggle HD textures");
case Config::HotKey::hkTexCoordBounds:
return tr("Toggle texcoords bounds");
case Config::HotKey::hkNativeResTexrects:
return tr("Toggle 2D texrects in native resolution");
case Config::HotKey::hkVsync:
return tr("Toggle VSync");
case Config::HotKey::hkFBEmulation:
@@ -241,6 +245,7 @@ void ConfigDialog::_init(bool reInit, bool blockCustomSettings)
}
ui->halosRemovalCheckBox->setChecked(config.texture.enableHalosRemoval != 0);
ui->texCoordBoundsCheckBox->setChecked(config.graphics2D.enableTexCoordBounds != 0);
ui->nativeRes2DComboBox->setCurrentIndex(config.graphics2D.enableNativeResTexrects);
@@ -574,6 +579,7 @@ void ConfigDialog::accept(bool justSave) {
config.graphics2D.bgMode = Config::BGMode::bgStripped;
config.texture.enableHalosRemoval = ui->halosRemovalCheckBox->isChecked() ? 1 : 0;
config.graphics2D.enableTexCoordBounds = ui->texCoordBoundsCheckBox->isChecked() ? 1 : 0;
config.graphics2D.enableNativeResTexrects = ui->nativeRes2DComboBox->currentIndex();
config.frameBufferEmulation.enable = ui->frameBufferCheckBox->isChecked() ? 1 : 0;
+3
View File
@@ -57,6 +57,7 @@ void _loadSettings(QSettings & settings)
config.graphics2D.correctTexrectCoords = settings.value("correctTexrectCoords", config.graphics2D.correctTexrectCoords).toInt();
config.graphics2D.enableNativeResTexrects = settings.value("enableNativeResTexrects", config.graphics2D.enableNativeResTexrects).toInt();
config.graphics2D.bgMode = settings.value("bgMode", config.graphics2D.bgMode).toInt();
config.graphics2D.enableTexCoordBounds = settings.value("enableTexCoordBounds", config.graphics2D.enableTexCoordBounds).toInt();
settings.endGroup();
settings.beginGroup("frameBufferEmulation");
@@ -240,6 +241,7 @@ void writeSettings(const QString & _strIniFolder)
settings.setValue("correctTexrectCoords", config.graphics2D.correctTexrectCoords);
settings.setValue("enableNativeResTexrects", config.graphics2D.enableNativeResTexrects);
settings.setValue("bgMode", config.graphics2D.bgMode);
settings.setValue("enableTexCoordBounds", config.graphics2D.enableTexCoordBounds);
settings.endGroup();
settings.beginGroup("frameBufferEmulation");
@@ -437,6 +439,7 @@ void saveCustomRomSettings(const QString & _strIniFolder, const char * _strRomNa
WriteCustomSetting(graphics2D, correctTexrectCoords);
WriteCustomSetting(graphics2D, enableNativeResTexrects);
WriteCustomSetting(graphics2D, bgMode);
WriteCustomSetting(graphics2D, enableTexCoordBounds);
settings.endGroup();
settings.beginGroup("frameBufferEmulation");
+19 -5
View File
@@ -1502,11 +1502,25 @@
</layout>
</item>
<item>
<widget class="QCheckBox" name="halosRemovalCheckBox">
<property name="text">
<string>Try to remove colored halos around transparent objects</string>
</property>
</widget>
<layout class="QHBoxLayout" name="horizontalLayout_29">
<item>
<widget class="QCheckBox" name="halosRemovalCheckBox">
<property name="text">
<string>Remove colored halos around transparent objects</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="texCoordBoundsCheckBox">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Bound texture rectangle texture coordinates to the values they take in native resolutions. It prevents garbage due to fetching out of texture bounds, but can result in hard edges.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Enable native-res bounds for texture coordinates</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
@@ -267,7 +267,7 @@ public:
ss << "# define IN in" << std::endl << "# define OUT out" << std::endl;
m_part = ss.str();
}
m_part += "uniform lowp float uClipRatio; \n";
m_part += "uniform lowp vec2 uVertexOffset; \n";
}
};
@@ -296,6 +296,10 @@ public:
"uniform mediump vec2 uCacheScale[2]; \n"
"uniform mediump vec2 uCacheOffset[2]; \n"
"uniform mediump vec2 uCacheShiftScale[2]; \n"
"uniform mediump vec2 uVTrans; \n"
"uniform mediump vec2 uVScale; \n"
"uniform mediump vec2 uAdjustTrans; \n"
"uniform mediump vec2 uAdjustScale; \n"
"uniform lowp ivec2 uCacheFrameBuffer; \n"
"OUT highp vec2 vTexCoord0; \n"
"OUT highp vec2 vTexCoord1; \n"
@@ -314,8 +318,8 @@ public:
" vec2 texCoordOut = texCoord*uCacheShiftScale[idx]; \n"
" texCoordOut -= uTexOffset[idx]; \n"
" texCoordOut += uCacheOffset[idx]; \n"
" if (uTextureFilterMode != 0 && uCacheFrameBuffer[idx] != 0) \n"
" texCoordOut -= vec2(0.5); \n"
" if (uTextureFilterMode != 0 && uCacheFrameBuffer[idx] != 0) \n" /* Workaround for framebuffer textures. */
" texCoordOut -= vec2(0.0,1.0); \n" /* They contain garbage at the bottom. */
" return texCoordOut * uCacheScale[idx]; \n"
"} \n"
" \n"
@@ -330,17 +334,18 @@ public:
" vTexCoord1 = calcTexCoord(texCoord, 1); \n"
" vLodTexCoord = texCoord; \n"
" vNumLights = aNumLights; \n"
" if (aModify != vec4(0.0)) { \n"
" if ((aModify[0]) != 0.0) { \n"
" gl_Position.xy = gl_Position.xy * uScreenCoordsScale + vec2(-1.0, 1.0); \n"
" gl_Position.xy *= gl_Position.w; \n"
" } \n"
" if ((aModify[1]) != 0.0) \n"
" gl_Position.z *= gl_Position.w; \n"
" if ((aModify[3]) != 0.0) \n"
" vNumLights = 0.0; \n"
" if ((aModify[0]) != 0.0) { \n"
" gl_Position.xy *= gl_Position.w; \n"
" } \n"
" gl_Position.y = -gl_Position.y; \n"
" else { \n"
" gl_Position.xy = gl_Position.xy * uVScale.xy + uVTrans.xy * gl_Position.ww; \n"
" gl_Position.xy = floor(gl_Position.xy * vec2(4.0)) * vec2(0.25); \n"
" gl_Position.xy = gl_Position.xy * uAdjustScale + gl_Position.ww * uAdjustTrans; \n"
" } \n"
" if ((aModify[1]) != 0.0) \n"
" gl_Position.z *= gl_Position.w; \n"
" if ((aModify[3]) != 0.0) \n"
" vNumLights = 0.0; \n"
" if (uFogUsage > 0) { \n"
" lowp float fp; \n"
" if (aPosition.z < -aPosition.w && aModify[1] == 0.0) \n"
@@ -374,6 +379,10 @@ public:
"uniform lowp int uFogUsage; \n"
"uniform mediump vec2 uFogScale; \n"
"uniform mediump vec2 uScreenCoordsScale; \n"
"uniform mediump vec2 uVTrans; \n"
"uniform mediump vec2 uVScale; \n"
"uniform mediump vec2 uAdjustTrans; \n"
"uniform mediump vec2 uAdjustScale; \n"
" \n"
"OUT lowp float vNumLights; \n"
"OUT lowp vec4 vShadeColor; \n"
@@ -390,17 +399,18 @@ public:
" gl_Position = aPosition; \n"
" vShadeColor = aColor; \n"
" vNumLights = aNumLights; \n"
" if (aModify != vec4(0.0)) { \n"
" if ((aModify[0]) != 0.0) { \n"
" gl_Position.xy = gl_Position.xy * uScreenCoordsScale + vec2(-1.0, 1.0); \n"
" gl_Position.xy *= gl_Position.w; \n"
" } \n"
" if ((aModify[1]) != 0.0) \n"
" gl_Position.z *= gl_Position.w; \n"
" if ((aModify[3]) != 0.0) \n"
" vNumLights = 0.0; \n"
" if ((aModify[0]) != 0.0) { \n"
" gl_Position.xy *= gl_Position.w; \n"
" } \n"
" gl_Position.y = -gl_Position.y; \n"
" else { \n"
" gl_Position.xy = gl_Position.xy * uVScale.xy + uVTrans.xy * gl_Position.ww; \n"
" gl_Position.xy = floor(gl_Position.xy * vec2(4.0)) * vec2(0.25); \n"
" gl_Position.xy = gl_Position.xy * uAdjustScale + gl_Position.ww * uAdjustTrans; \n"
" } \n"
" if ((aModify[1]) != 0.0) \n"
" gl_Position.z *= gl_Position.w; \n"
" if ((aModify[3]) != 0.0) \n"
" vNumLights = 0.0; \n"
" if (uFogUsage > 0) { \n"
" lowp float fp; \n"
" if (aPosition.z < -aPosition.w && aModify[1] == 0.0) \n"
@@ -503,7 +513,8 @@ public:
m_part = " gl_Position.z /= 8.0; \n";
}
m_part +=
" gl_Position.zw *= vec2(uClipRatio); \n"
" gl_Position.xy += uVertexOffset * vec2(gl_Position.w); \n"
" gl_Position.zw *= vec2(1024.0f); \n"
"} \n"
;
}
@@ -946,6 +957,10 @@ public:
"uniform lowp vec2 uTexMirrorEn1; \n"
"uniform lowp vec2 uTexClampEn0; \n"
"uniform lowp vec2 uTexClampEn1; \n"
"uniform highp vec2 uTexCoordOffset[2]; \n"
"uniform lowp int uUseTexCoordBounds; \n"
"uniform highp vec4 uTexCoordBounds0; \n"
"uniform highp vec4 uTexCoordBounds1; \n"
"uniform lowp int uScreenSpaceTriangle; \n"
"highp vec2 texCoord0; \n"
"highp vec2 texCoord1; \n"
@@ -2575,6 +2590,23 @@ public:
};
class ShaderFragmentCorrectTexCoords : public ShaderPart {
public:
ShaderFragmentCorrectTexCoords() {
m_part +=
" highp vec2 mTexCoord0 = vTexCoord0 + vec2(0.0001); \n"
" highp vec2 mTexCoord1 = vTexCoord1 + vec2(0.0001); \n"
" mTexCoord0 += uTexCoordOffset[0]; \n"
" mTexCoord1 += uTexCoordOffset[1]; \n"
" if (uUseTexCoordBounds != 0) { \n"
" mTexCoord0 = clamp(mTexCoord0, uTexCoordBounds0.xy, uTexCoordBounds0.zw); \n"
" mTexCoord1 = clamp(mTexCoord1, uTexCoordBounds1.xy, uTexCoordBounds1.zw); \n"
" } \n"
;
}
};
class ShaderTextureEngine : public ShaderPart
{
public:
@@ -2637,7 +2669,7 @@ public:
ShaderFragmentTextureEngineTex0(const opengl::GLInfo _glinfo)
{
m_part =
"textureEngine0(vTexCoord0, tcData0); \n"
"textureEngine0(mTexCoord0, tcData0); \n"
;
}
};
@@ -2647,7 +2679,7 @@ public:
ShaderFragmentTextureEngineTex1(const opengl::GLInfo _glinfo)
{
m_part =
"textureEngine1(vTexCoord1, tcData1); \n"
"textureEngine1(mTexCoord1, tcData1); \n"
;
}
};
@@ -2891,6 +2923,7 @@ graphics::CombinerProgram * CombinerProgramBuilder::buildCombinerProgram(Combine
if (bUseTextures) {
m_fragmentCorrectTexCoords->write(ssShader);
if (combinerInputs.usesTile(0))
{
m_fragmentTextureEngineTex0->write(ssShader);
@@ -3060,6 +3093,7 @@ CombinerProgramBuilder::CombinerProgramBuilder(const opengl::GLInfo & _glinfo, o
, m_fragmentBlendMux(new ShaderFragmentBlendMux(_glinfo))
, m_fragmentReadTex0(new ShaderFragmentReadTex0(_glinfo))
, m_fragmentReadTex1(new ShaderFragmentReadTex1(_glinfo))
, m_fragmentCorrectTexCoords(new ShaderFragmentCorrectTexCoords())
, m_fragmentTextureEngineTex0(new ShaderFragmentTextureEngineTex0(_glinfo))
, m_fragmentTextureEngineTex1(new ShaderFragmentTextureEngineTex1(_glinfo))
, m_fragmentReadTexCopyMode(new ShaderFragmentReadTexCopyMode(_glinfo))
@@ -74,6 +74,7 @@ namespace glsl {
ShaderPartPtr m_fragmentBlendMux;
ShaderPartPtr m_fragmentReadTex0;
ShaderPartPtr m_fragmentReadTex1;
ShaderPartPtr m_fragmentCorrectTexCoords;
ShaderPartPtr m_fragmentTextureEngineTex0;
ShaderPartPtr m_fragmentTextureEngineTex1;
ShaderPartPtr m_fragmentReadTexCopyMode;
@@ -1,3 +1,4 @@
#include <cmath>
#include <Config.h>
#include "glsl_CombinerProgramUniformFactory.h"
#include <Graphics/Parameters.h>
@@ -216,6 +217,113 @@ private:
iUniform uScreenSpaceTriangle;
};
class URasterInfo : public UniformGroup {
public:
URasterInfo(GLuint _program) {
LocateUniform(uVertexOffset);
LocateUniform(uTexCoordOffset[0]);
LocateUniform(uTexCoordOffset[1]);
LocateUniform(uUseTexCoordBounds);
LocateUniform(uTexCoordBounds0);
LocateUniform(uTexCoordBounds1);
}
void update(bool _force) override {
const bool isNativeRes = config.frameBufferEmulation.nativeResFactor == 1 && config.video.multisampling == 0;
const bool isTexRect = dwnd().getDrawer().getDrawingState() == DrawingState::TexRect;
const bool useTexCoordBounds = isTexRect && !isNativeRes && config.graphics2D.enableTexCoordBounds;
/* At rasterization stage, the N64 places samples on the top left of the fragment while OpenGL */
/* places them in the fragment center. As a result, a normal approach results in shifted texture */
/* coordinates. In native resolution, this difference can be negated by shifting vertices by 0.5. */
/* In higher resolutions, there are more samples than the game intends, so shifting is not very */
/* effective. Still, an heuristic is applied to render texture rectangles as correctly as possible */
/* in higher resolutions too. See issue #2324 for details. */
const float vertexOffset = isNativeRes ? 0.5f : 0.0f;
float texCoordOffset[2][2] = { 0.0f, 0.0f };
if (isTexRect && !isNativeRes) {
float scale[2] = { 0.0f, 0.0f };
if (config.graphics2D.enableNativeResTexrects != 0) {
scale[0] = scale[1] = 1.0f;
} else if (config.frameBufferEmulation.nativeResFactor != 0) {
scale[0] = scale[1] = static_cast<float>(config.frameBufferEmulation.nativeResFactor);
} else {
scale[0] = dwnd().getScaleX();
scale[1] = dwnd().getScaleY();
}
for (int t = 0; t < 2; t++) {
const CachedTexture* _pTexture = textureCache().current[t];
if (_pTexture != nullptr) {
texCoordOffset[t][0] = (gDP.lastTexRectInfo.dsdx >= 0.0f ? -0.5f / scale[0] : -1.0f + 0.5f / scale[0]) * gDP.lastTexRectInfo.dsdx * _pTexture->hdRatioS;
texCoordOffset[t][1] = (gDP.lastTexRectInfo.dtdy >= 0.0f ? -0.5f / scale[1] : -1.0f + 0.5f / scale[1]) * gDP.lastTexRectInfo.dtdy * _pTexture->hdRatioT;
}
}
}
float tcbounds[2][4] = {};
if (useTexCoordBounds) {
f32 uls, lrs, ult, lrt, S, T, shiftScaleS, shiftScaleT;
s16 shiftedS, shiftedT;
u32 shifts, shiftt;
for (int t = 0; t < 2; t++) {
const CachedTexture * _pTexture = textureCache().current[t];
const gDPTile * _pTile = gSP.textureTile[t];
if (_pTexture != nullptr && _pTile != nullptr){
if (_pTile->shifts > 10) {
shifts = 16 - _pTile->shifts;
shiftedS = static_cast<s16>(gDP.lastTexRectInfo.s << shifts);
shiftScaleS = static_cast<f32>(1 << shifts);
} else {
shifts = _pTile->shifts;
shiftedS = static_cast<s16>(gDP.lastTexRectInfo.s >> shifts);
shiftScaleS = 1.0f / static_cast<f32>(1 << shifts);
}
if (_pTile->shiftt > 10) {
shiftt = 16 - _pTile->shiftt;
shiftedT = static_cast<s16>(gDP.lastTexRectInfo.t << shiftt);
shiftScaleT = static_cast<f32>(1 << shiftt);
} else {
shiftt = _pTile->shiftt;
shiftedT = static_cast<s16>(gDP.lastTexRectInfo.t >> shiftt);
shiftScaleT = 1.0f / static_cast<f32>(1 << shiftt);
}
S = _FIXED2FLOAT(shiftedS, 5);
T = _FIXED2FLOAT(shiftedT, 5);
uls = S + (ceilf(gDP.lastTexRectInfo.ulx) - gDP.lastTexRectInfo.ulx) * gDP.lastTexRectInfo.dsdx * shiftScaleS;
lrs = S + (ceilf(gDP.lastTexRectInfo.lrx) - gDP.lastTexRectInfo.ulx - 1.0f) * gDP.lastTexRectInfo.dsdx * shiftScaleS;
ult = T + (ceilf(gDP.lastTexRectInfo.uly) - gDP.lastTexRectInfo.uly) * gDP.lastTexRectInfo.dtdy * shiftScaleT;
lrt = T + (ceilf(gDP.lastTexRectInfo.lry) - gDP.lastTexRectInfo.uly - 1.0f) * gDP.lastTexRectInfo.dtdy * shiftScaleT;
tcbounds[t][0] = (fmin(uls, lrs) - _pTile->fuls) * _pTexture->hdRatioS;
tcbounds[t][1] = (fmin(ult, lrt) - _pTile->fult) * _pTexture->hdRatioT;
tcbounds[t][2] = (fmax(uls, lrs) - _pTile->fuls) * _pTexture->hdRatioS;
tcbounds[t][3] = (fmax(ult, lrt) - _pTile->fult) * _pTexture->hdRatioT;
if (_pTexture->frameBufferTexture != CachedTexture::fbNone) {
tcbounds[t][0] += _pTexture->offsetS * _pTexture->hdRatioS;
tcbounds[t][1] += _pTexture->offsetT * _pTexture->hdRatioT;
tcbounds[t][2] += _pTexture->offsetS * _pTexture->hdRatioS;
tcbounds[t][3] += _pTexture->offsetT * _pTexture->hdRatioT;
}
}
}
}
uVertexOffset.set(vertexOffset, vertexOffset, _force);
uTexCoordOffset[0].set(texCoordOffset[0][0], texCoordOffset[0][1], _force);
uTexCoordOffset[1].set(texCoordOffset[1][0], texCoordOffset[1][1], _force);
uUseTexCoordBounds.set(useTexCoordBounds ? 1 : 0, _force);
uTexCoordBounds0.set(tcbounds[0], _force);
uTexCoordBounds1.set(tcbounds[1], _force);
}
private:
fv2Uniform uVertexOffset;
fv2Uniform uTexCoordOffset[2];
iUniform uUseTexCoordBounds;
fv4Uniform uTexCoordBounds0;
fv4Uniform uTexCoordBounds1;
};
class UFrameBufferInfo : public UniformGroup
{
public:
@@ -603,6 +711,43 @@ private:
fUniform uAlphaTestValue;
};
class UViewportInfo : public UniformGroup
{
public:
UViewportInfo(GLuint _program) {
LocateUniform(uVTrans);
LocateUniform(uVScale);
LocateUniform(uAdjustTrans);
LocateUniform(uAdjustScale);
}
void update(bool _force) override
{
const bool isOrthographicProjection = gSP.matrix.projection[3][2] == -1.f;
float adjustTrans[2] = { 0.0f, 0.0f };
float adjustScale[2] = { 1.0f, 1.0f };
if (dwnd().isAdjustScreen() && (gDP.colorImage.width > VI.width * 98 / 100)) {
if (isOrthographicProjection) {
adjustScale[1] = 1.0f / dwnd().getAdjustScale();
adjustTrans[1] = static_cast<f32>(gDP.colorImage.width) * 3.0f / 4.0f * (1.0f - adjustScale[1]) / 2.0f;
} else {
adjustScale[0] = dwnd().getAdjustScale();
adjustTrans[0] = static_cast<f32>(gDP.colorImage.width) * (1.0f - adjustScale[0]) / 2.0f;
}
}
uVTrans.set(gSP.viewport.vtrans[0], gSP.viewport.vtrans[1], _force);
uVScale.set(gSP.viewport.vscale[0], -gSP.viewport.vscale[1], _force);
uAdjustTrans.set(adjustTrans[0], adjustTrans[1], _force);
uAdjustScale.set(adjustScale[0], adjustScale[1], _force);
}
private:
fv2Uniform uVTrans;
fv2Uniform uVScale;
fv2Uniform uAdjustTrans;
fv2Uniform uAdjustScale;
};
class UDepthScale : public UniformGroup
{
public:
@@ -738,22 +883,6 @@ private:
iUniform uClampMode;
};
class UClipRatio : public UniformGroup
{
public:
UClipRatio(GLuint _program) {
LocateUniform(uClipRatio);
}
void update(bool _force) override
{
uClipRatio.set(float(gSP.clipRatio), _force);
}
private:
fUniform uClipRatio;
};
class UPolygonOffset : public UniformGroup
{
public:
@@ -1094,6 +1223,8 @@ void CombinerProgramUniformFactory::buildUniforms(GLuint _program,
{
_uniforms.emplace_back(new UNoiseTex(_program));
_uniforms.emplace_back(new UScreenSpaceTriangleInfo(_program));
_uniforms.emplace_back(new URasterInfo(_program));
_uniforms.emplace_back(new UViewportInfo(_program));
if (!m_glInfo.isGLES2) {
_uniforms.emplace_back(new UDepthTex(_program));
@@ -1165,8 +1296,6 @@ void CombinerProgramUniformFactory::buildUniforms(GLuint _program,
_uniforms.emplace_back(new UPolygonOffset(_program));
}
_uniforms.emplace_back(new UClipRatio(_program));
_uniforms.emplace_back(new UScreenCoordsScale(_program));
_uniforms.emplace_back(new UColors(_program));
@@ -20,7 +20,7 @@ namespace glsl {
bool _saveCombinerKeys(const graphics::Combiners & _combiners) const;
bool _loadFromCombinerKeys(graphics::Combiners & _combiners);
const u32 m_formatVersion = 0x33U;
const u32 m_formatVersion = 0x34U;
const u32 m_keysFormatVersion = 0x05;
const opengl::GLInfo & m_glinfo;
opengl::CachedUseProgram * m_useProgram;
@@ -22,6 +22,8 @@ GraphicBufferWrapper::GraphicBufferWrapper() {
m_private = true;
m_privateGraphicBuffer = new GraphicBuffer();
}
m_stride = 0;
}
GraphicBufferWrapper::~GraphicBufferWrapper() {
@@ -51,7 +53,6 @@ bool GraphicBufferWrapper::allocate(const AHardwareBuffer_Desc *desc) {
}
}
int GraphicBufferWrapper::lock(uint64_t usage, void **out_virtual_address) {
int returnValue = 0;
@@ -64,7 +65,6 @@ int GraphicBufferWrapper::lock(uint64_t usage, void **out_virtual_address) {
return returnValue;
}
void GraphicBufferWrapper::release() {
if (!m_private) {
AndroidHardwareBufferCompat::GetInstance().Release(m_publicGraphicBuffer);
@@ -81,7 +81,6 @@ void GraphicBufferWrapper::unlock() {
}
EGLClientBuffer GraphicBufferWrapper::getClientBuffer() {
EGLClientBuffer clientBuffer = nullptr;
if (m_private) {
@@ -93,6 +92,15 @@ EGLClientBuffer GraphicBufferWrapper::getClientBuffer() {
return clientBuffer;
}
unsigned GraphicBufferWrapper::getStride() const {
if (m_private) {
return m_privateGraphicBuffer->getStride();
} else {
AHardwareBuffer_Desc bufferInfo;
AndroidHardwareBufferCompat::GetInstance().Describe(m_publicGraphicBuffer, &bufferInfo);
return bufferInfo.stride;
}
}
int GraphicBufferWrapper::getApiLevel()
{
@@ -28,6 +28,7 @@ public:
void release();
void unlock();
EGLClientBuffer getClientBuffer();
unsigned int getStride() const;
private:
@@ -36,6 +37,7 @@ private:
bool m_private;
GraphicBuffer* m_privateGraphicBuffer;
AHardwareBuffer* m_publicGraphicBuffer;
unsigned int m_stride;
};
@@ -55,7 +55,7 @@ const u8 * ColorBufferReaderWithEGLImage::_readPixels(const ReadColorBufferParam
m_hardwareBuffer.lock(AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN, &gpuData);
m_bufferLocked = true;
_heightOffset = static_cast<u32>(_params.y0);
_stride = m_pTexture->width;
_stride = m_hardwareBuffer.getStride();
} else {
gpuData = m_pixelData.data();
glReadPixels(_params.x0, _params.y0, m_pTexture->width, _params.height, format, type, gpuData);
+37 -123
View File
@@ -238,86 +238,25 @@ void GraphicsDrawer::updateScissor(FrameBuffer * _pBuffer) const
gDP.changed &= ~CHANGED_SCISSOR;
}
inline
float _adjustViewportX(f32 _X0)
void GraphicsDrawer::_updateViewport(const FrameBuffer* _pBuffer, const f32 scale) const
{
const f32 halfX = gDP.colorImage.width / 2.0f;
const f32 halfVP = gSP.viewport.width / 2.0f;
return (_X0 + halfVP - halfX) * dwnd().getAdjustScale() + halfX - halfVP;
}
inline
void _adjustViewportToClipRatio(s32 & x, s32 & y, s32 & width, s32 & height)
{
x -= static_cast<s32>(gSP.clipRatio - 1) * width / 2;
y -= static_cast<s32>(gSP.clipRatio - 1) * height / 2;
width *= gSP.clipRatio;
height *= gSP.clipRatio;
}
void GraphicsDrawer::_updateViewport() const
{
DisplayWindow & wnd = DisplayWindow::get();
FrameBuffer * pCurrentBuffer = frameBufferList().getCurrent();
if (pCurrentBuffer == nullptr) {
const f32 scaleX = wnd.getScaleX();
const f32 scaleY = wnd.getScaleY();
float Xf = gSP.viewport.vscale[0] < 0 ? (gSP.viewport.x + gSP.viewport.vscale[0] * 2.0f) : gSP.viewport.x;
if (_needAdjustCoordinate(wnd))
Xf = _adjustViewportX(Xf);
s32 X = static_cast<s32>(Xf * scaleX);
s32 Y = static_cast<s32>(gSP.viewport.y * scaleY);
s32 WIDTH = std::max(static_cast<s32>(gSP.viewport.width * scaleX), 0);
s32 HEIGHT = std::max(static_cast<s32>(gSP.viewport.height * scaleY), 0);
_adjustViewportToClipRatio(X, Y, WIDTH, HEIGHT);
gfxContext.setViewport(X, Y, WIDTH, HEIGHT);
} else {
const f32 scaleX = 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;
Xf += f32(pCurrentBuffer->m_originX);
if (_needAdjustCoordinate(wnd))
Xf = _adjustViewportX(Xf);
s32 X = roundup(Xf, scaleX);
float Yf = gSP.viewport.vscale[1] < 0 ? (gSP.viewport.y + gSP.viewport.vscale[1] * 2.0f) : gSP.viewport.y;
Yf += f32(pCurrentBuffer->m_originY);
s32 Y = roundup(Yf, scaleY);
s32 WIDTH = std::max(roundup(gSP.viewport.width, scaleX), 0);
s32 HEIGHT = std::max(roundup(gSP.viewport.height, scaleY), 0);
_adjustViewportToClipRatio(X, Y, WIDTH, HEIGHT);
gfxContext.setViewport(X, Y, WIDTH, HEIGHT);
}
gSP.changed &= ~CHANGED_VIEWPORT;
}
void GraphicsDrawer::_updateScreenCoordsViewport(const FrameBuffer * _pBuffer) const
{
DisplayWindow & wnd = DisplayWindow::get();
const FrameBuffer * pCurrentBuffer = _pBuffer != nullptr ? _pBuffer : frameBufferList().getCurrent();
u32 bufferWidth, bufferHeight;
f32 viewportScaleX, viewportScaleY;
s32 X = 0, Y = 0;
if (pCurrentBuffer == nullptr) {
bufferWidth = VI.width;
bufferHeight = VI.height;
viewportScaleX = wnd.getScaleX();
viewportScaleY = wnd.getScaleY();
} else {
bufferWidth = pCurrentBuffer->m_width;
bufferHeight = VI_GetMaxBufferHeight(static_cast<u16>(bufferWidth));
viewportScaleX = viewportScaleY = pCurrentBuffer->m_scale;
X = roundup(f32(pCurrentBuffer->m_originX), viewportScaleX);
Y = roundup(f32(pCurrentBuffer->m_originY), viewportScaleY);
if (RSP.LLE || gSP.viewport.width == 0.0f) {
gSP.viewport.width = f32(bufferWidth);
gSP.viewport.height = f32(bufferHeight);
s32 X, Y, WIDTH, HEIGHT;
f32 scaleX, scaleY;
if (scale == 0.0f) {
const FrameBuffer* pCurrentBuffer = _pBuffer != nullptr ? _pBuffer : frameBufferList().getCurrent();
if (pCurrentBuffer != nullptr) {
scaleX = scaleY = pCurrentBuffer->m_scale;
} else {
scaleX = dwnd().getScaleX();
scaleY = dwnd().getScaleY();
}
} else {
scaleX = scaleY = scale;
}
s32 WIDTH = roundup(f32(bufferWidth), viewportScaleX);
s32 HEIGHT = roundup(f32(bufferHeight), viewportScaleY);
_adjustViewportToClipRatio(X, Y, WIDTH, HEIGHT);
X = roundup(-1024.0f, scaleX);
Y = roundup(-1024.0f, scaleY);
WIDTH = roundup(2048.0f, scaleX);
HEIGHT = roundup(2048.0f, scaleY);
gfxContext.setViewport(X, Y, WIDTH, HEIGHT);
gSP.changed |= CHANGED_VIEWPORT;
}
@@ -796,7 +735,7 @@ void GraphicsDrawer::_prepareDrawTriangle(DrawingState _drawingState)
m_bFlatColors = bFlatColors;
if ((m_modifyVertices & MODIFY_XY) != 0)
_updateScreenCoordsViewport();
_updateViewport();
m_modifyVertices = 0;
}
@@ -853,8 +792,6 @@ void GraphicsDrawer::drawScreenSpaceTriangle(u32 _numVtx, graphics::DrawModePara
if (_numVtx == 0 || !_canDraw())
return;
ValueKeeper<u32> otherMode(gSP.clipRatio, 1U);
f32 maxY = 0;
for (u32 i = 0; i < _numVtx; ++i) {
SPVertex & vtx = m_dmaVertices[i];
@@ -1042,7 +979,7 @@ void GraphicsDrawer::drawLine(u32 _v0, u32 _v1, float _width)
m_drawingState = DrawingState::Line;
if ((triangles.vertices[_v0].modify & MODIFY_XY) != 0)
_updateScreenCoordsViewport();
_updateViewport();
SPVertex vertexBuf[2] = { triangles.vertices[_v0], triangles.vertices[_v1] };
gfxContext.drawLine(lineWidth, vertexBuf);
@@ -1050,7 +987,6 @@ void GraphicsDrawer::drawLine(u32 _v0, u32 _v1, float _width)
void GraphicsDrawer::drawRect(int _ulx, int _uly, int _lrx, int _lry)
{
ValueKeeper<u32> otherMode(gSP.clipRatio, 1U);
m_texrectDrawer.draw();
m_statistics.fillRects++;
@@ -1064,24 +1000,22 @@ void GraphicsDrawer::drawRect(int _ulx, int _uly, int _lrx, int _lry)
m_drawingState = DrawingState::Rect;
_updateScreenCoordsViewport();
_updateViewport();
gfxContext.enable(enable::CULL_FACE, false);
f32 scaleX, scaleY;
calcCoordsScales(frameBufferList().getCurrent(), scaleX, scaleY);
const float Z = (gDP.otherMode.depthSource == G_ZS_PRIM) ? gDP.primDepth.z : 0.0f;
const float W = 1.0f;
m_rect[0].x = static_cast<f32>(_ulx) * (2.0f * scaleX) - 1.0f;
m_rect[0].y = static_cast<f32>(_uly) * (2.0f * scaleY) - 1.0f;
m_rect[0].x = static_cast<f32>(_ulx);
m_rect[0].y = static_cast<f32>(_uly);
m_rect[0].z = Z;
m_rect[0].w = W;
m_rect[1].x = static_cast<f32>(_lrx) * (2.0f * scaleX) - 1.0f;
m_rect[1].x = static_cast<f32>(_lrx);
m_rect[1].y = m_rect[0].y;
m_rect[1].z = Z;
m_rect[1].w = W;
m_rect[2].x = m_rect[0].x;
m_rect[2].y = static_cast<f32>(_lry) * (2.0f * scaleY) - 1.0f;
m_rect[2].y = static_cast<f32>(_lry);
m_rect[2].z = Z;
m_rect[2].w = W;
m_rect[3].x = m_rect[1].x;
@@ -1101,8 +1035,11 @@ void GraphicsDrawer::drawRect(int _ulx, int _uly, int _lrx, int _lry)
DisplayWindow & wnd = dwnd();
if (wnd.isAdjustScreen() && (gDP.colorImage.width > VI.width * 98 / 100) && (static_cast<u32>(_lrx - _ulx) < VI.width * 9 / 10)) {
const float scale = wnd.getAdjustScale();
for (u32 i = 0; i < 4; ++i)
const float offsetx = static_cast<f32>(gDP.colorImage.width) * (1.0f - scale) / 2.0f;
for (u32 i = 0; i < 4; ++i) {
m_rect[i].x *= scale;
m_rect[i].x += offsetx;
}
}
Context::DrawRectParameters rectParams;
@@ -1265,7 +1202,6 @@ void GraphicsDrawer::drawTexturedRect(const TexturedRectParams & _params)
gSP.changed &= ~CHANGED_GEOMETRYMODE; // Don't update cull mode
m_drawingState = DrawingState::TexRect;
m_statistics.texRects++;
ValueKeeper<u32> otherMode(gSP.clipRatio, 1U);
if (m_texrectDrawer.canContinue()) {
CombinerInfo & cmbInfo = CombinerInfo::get();
@@ -1305,14 +1241,13 @@ void GraphicsDrawer::drawTexturedRect(const TexturedRectParams & _params)
&& ((cache.current[0]->frameBufferTexture == CachedTexture::fbNone && !cache.current[0]->bHDTexture))
&& (cache.current[1] == nullptr || (cache.current[1]->frameBufferTexture == CachedTexture::fbNone && !cache.current[1]->bHDTexture)));
f32 scaleX, scaleY;
calcCoordsScales(pCurrentBuffer, scaleX, scaleY);
const float Z = (gDP.otherMode.depthSource == G_ZS_PRIM) ? gDP.primDepth.z : 0.0f;
const float W = 1.0f;
const f32 ulx = _params.ulx * (2.0f * scaleX) - 1.0f;
const f32 uly = _params.uly * (2.0f * scaleY) - 1.0f;
const f32 lrx = _params.lrx * (2.0f * scaleX) - 1.0f;
const f32 lry = _params.lry * (2.0f * scaleY) - 1.0f;
const f32 ulx = _params.ulx;
const f32 uly = _params.uly;
const f32 lrx = _params.lrx;
const f32 lry = _params.lry;
m_rect[0].x = ulx;
m_rect[0].y = uly;
m_rect[0].z = Z;
@@ -1380,15 +1315,6 @@ void GraphicsDrawer::drawTexturedRect(const TexturedRectParams & _params)
texST[t].t0 = ult - gSP.textureTile[t]->fult;
texST[t].t1 = lrt - gSP.textureTile[t]->fult;
if (uls > lrs) {
texST[t].s0 -= _params.dsdx * shiftScaleS;
texST[t].s1 -= _params.dsdx * shiftScaleS;
}
if (ult > lrt) {
texST[t].t0 -= _params.dtdy * shiftScaleT;
texST[t].t1 -= _params.dtdy * shiftScaleT;
}
if (cache.current[t]->frameBufferTexture != CachedTexture::fbNone) {
texST[t].s0 = cache.current[t]->offsetS + texST[t].s0;
texST[t].t0 = cache.current[t]->offsetT + texST[t].t0;
@@ -1425,13 +1351,6 @@ void GraphicsDrawer::drawTexturedRect(const TexturedRectParams & _params)
texST[t].s1 *= cache.current[t]->hdRatioS;
texST[t].t1 *= cache.current[t]->hdRatioT;
if (gDP.otherMode.textureFilter != G_TF_POINT && gDP.otherMode.cycleType != G_CYC_COPY) {
texST[t].s0 -= 0.5f;
texST[t].t0 -= 0.5f;
texST[t].s1 -= 0.5f;
texST[t].t1 -= 0.5f;
}
}
}
@@ -1482,8 +1401,11 @@ void GraphicsDrawer::drawTexturedRect(const TexturedRectParams & _params)
((gDP.colorImage.width > VI.width * 98 / 100) && (static_cast<u32>(_params.lrx - _params.ulx) < VI.width * 9 / 10))))
{
const float scale = wnd.getAdjustScale();
for (u32 i = 0; i < 4; ++i)
const float offsetx = static_cast<f32>(gDP.colorImage.width) * (1.0f-scale) / 2.0f;
for (u32 i = 0; i < 4; ++i) {
m_rect[i].x *= scale;
m_rect[i].x += offsetx;
}
}
m_rect[0].bc0 = 0.0f;
@@ -1505,7 +1427,7 @@ void GraphicsDrawer::drawTexturedRect(const TexturedRectParams & _params)
return;
}
_updateScreenCoordsViewport(_params.pBuffer);
_updateViewport(_params.pBuffer);
Context::DrawRectParameters rectParams;
rectParams.mode = drawmode::TRIANGLE_STRIP;
rectParams.verticesCount = 4;
@@ -1513,14 +1435,6 @@ void GraphicsDrawer::drawTexturedRect(const TexturedRectParams & _params)
rectParams.combiner = currentCombiner();
gfxContext.drawRects(rectParams);
if (g_debugger.isCaptureMode()) {
m_rect[0].x = _params.ulx;
m_rect[0].y = _params.uly;
m_rect[1].x = _params.lrx;
m_rect[1].y = _params.uly;
m_rect[2].x = _params.ulx;
m_rect[2].y = _params.lry;
m_rect[3].x = _params.lrx;
m_rect[3].y = _params.lry;
g_debugger.addRects(rectParams);
}
+1 -2
View File
@@ -190,8 +190,7 @@ private:
void _ordinaryBlending() const;
void _dualSourceBlending() const;
void _updateCullFace() const;
void _updateViewport() const;
void _updateScreenCoordsViewport(const FrameBuffer * _pBuffer = nullptr) const;
void _updateViewport(const FrameBuffer * _pBuffer = nullptr, const f32 scale = 0.0f) const;
void _updateDepthUpdate() const;
void _updateDepthCompare() const;
void _updateTextures() const;
+16 -20
View File
@@ -29,8 +29,6 @@ TexrectDrawer::TexrectDrawer()
, m_Z(0)
, m_max_lrx(0)
, m_max_lry(0)
, m_stepY(0.0f)
, m_stepX(0.0f)
, m_scissor(gDPScissor())
, m_pTexture(nullptr)
, m_pBuffer(nullptr)
@@ -54,8 +52,6 @@ void TexrectDrawer::init()
m_pTexture->width = 640;
m_pTexture->height = 580;
m_pTexture->textureBytes = m_pTexture->width * m_pTexture->height * fbTexFormats.colorFormatBytes;
m_stepX = 2.0f / 640.0f;
m_stepY = 2.0f / 580.0f;
Context::InitTextureParams initParams;
initParams.handle = m_pTexture->name;
@@ -108,8 +104,7 @@ void TexrectDrawer::destroy()
void TexrectDrawer::_setViewport() const
{
const u32 bufferWidth = m_pBuffer == nullptr ? VI.width : m_pBuffer->m_width;
gfxContext.setViewport(0, 0, bufferWidth, VI_GetMaxBufferHeight(bufferWidth));
dwnd().getDrawer()._updateViewport(nullptr, 1.0f);
}
void TexrectDrawer::_setDrawBuffer()
@@ -381,13 +376,14 @@ bool TexrectDrawer::draw()
scaleX *= 2.0f;
scaleY *= 2.0f;
const float s0 = (m_ulx + 1.0f) / scaleX / (float)m_pTexture->width + 0.5f / (float)m_pTexture->width;
const float t0 = (m_lry + 1.0f) / scaleY / (float)m_pTexture->height;// +0.5f / (float)m_pTexture->height;
const float s1 = (m_lrx + 1.0f) / scaleX / (float)m_pTexture->width;
const float t1 = (m_uly + 1.0f) / scaleY / (float)m_pTexture->height;
const float W = 1.0f;
const float s0 = m_ulx / (float)m_pTexture->width; // +0.5f / (float)m_pTexture->width;
const float t0 = m_lry / (float)m_pTexture->height;// +0.5f / (float)m_pTexture->height;
const float s1 = m_lrx / (float)m_pTexture->width;
const float t1 = m_uly / (float)m_pTexture->height;
const float W = 1024.0f;
const float Z = m_Z * 1024.0f;
drawer._updateScreenCoordsViewport(m_pBuffer);
drawer._updateViewport(m_pBuffer);
textureCache().activateTexture(0, m_pTexture);
// Disable filtering to avoid black outlines
@@ -404,25 +400,25 @@ bool TexrectDrawer::draw()
rect[0].x = m_ulx;
rect[0].y = m_lry;
rect[0].z = m_Z;
rect[0].z = Z;
rect[0].w = W;
rect[0].s0 = s0;
rect[0].t0 = t0;
rect[1].x = m_lrx;
rect[1].y = m_lry;
rect[1].z = m_Z;
rect[1].z = Z;
rect[1].w = W;
rect[1].s0 = s1;
rect[1].t0 = t0;
rect[2].x = m_ulx;
rect[2].y = m_uly;
rect[2].z = m_Z;
rect[2].z = Z;
rect[2].w = W;
rect[2].s0 = s0;
rect[2].t0 = t1;
rect[3].x = m_lrx;
rect[3].y = m_uly;
rect[3].z = m_Z;
rect[3].z = Z;
rect[3].w = W;
rect[3].s0 = s1;
rect[3].t0 = t1;
@@ -440,15 +436,15 @@ bool TexrectDrawer::draw()
gfxContext.bindFramebuffer(bufferTarget::DRAW_FRAMEBUFFER, m_FBO);
m_programClear->activate();
const f32 ulx = std::max(-1.0f, m_ulx - m_stepX);
const f32 lrx = std::min( 1.0f, m_lrx + m_stepX);
const f32 ulx = std::max(0.0f, m_ulx - 1.0f);
const f32 lrx = std::min(640.0f, m_lrx + 1.0f);
rect[0].x = ulx;
rect[1].x = lrx;
rect[2].x = ulx;
rect[3].x = lrx;
const f32 uly = std::max(-1.0f, m_uly - m_stepY);
const f32 lry = std::min( 1.0f, m_lry + m_stepY);
const f32 uly = std::max(0.0f, m_uly - 1.0f);
const f32 lry = std::min(580.0f, m_lry + 1.0f);
rect[0].y = uly;
rect[1].y = uly;
rect[2].y = lry;
-2
View File
@@ -34,8 +34,6 @@ private:
f32 m_ulx, m_lrx, m_uly, m_lry, m_Z;
s32 m_ulx_i, m_uly_i, m_lry_i;
f32 m_max_lrx, m_max_lry;
f32 m_stepY;
f32 m_stepX;
graphics::ObjectHandle m_FBO;
gDPScissor m_scissor;
CachedTexture * m_pTexture;
+21
View File
@@ -130,6 +130,27 @@ static void checkHotkeys()
textureCache().toggleDumpTex();
}
if (osal_is_key_pressed(config.hotkeys.keys[Config::hkTexCoordBounds], 0x0001)) {
if (config.graphics2D.enableTexCoordBounds == 0)
dwnd().getDrawer().showMessage("Bound texrect texture coordinates on\n", Milliseconds(1000));
else
dwnd().getDrawer().showMessage("Bound texrect texture coordinates off\n", Milliseconds(1000));
config.graphics2D.enableTexCoordBounds = !config.graphics2D.enableTexCoordBounds;
}
if (osal_is_key_pressed(config.hotkeys.keys[Config::hkNativeResTexrects], 0x0001)) {
static u32 s_nativeResTexrects = Config::NativeResTexrectsMode::ntOptimized;
if (config.graphics2D.enableNativeResTexrects != Config::NativeResTexrectsMode::ntDisable) {
s_nativeResTexrects = config.graphics2D.enableNativeResTexrects;
config.graphics2D.enableNativeResTexrects = Config::NativeResTexrectsMode::ntDisable;
}
else
config.graphics2D.enableNativeResTexrects = s_nativeResTexrects;
if (config.graphics2D.enableNativeResTexrects == Config::NativeResTexrectsMode::ntDisable)
dwnd().getDrawer().showMessage("Disable 2D texrects in native resolution\n", Milliseconds(1000));
else
dwnd().getDrawer().showMessage("Enable 2D texrects in native resolution\n", Milliseconds(1000));
}
if (osal_is_key_pressed(config.hotkeys.keys[Config::hkVsync], 0x0001)) {
config.video.verticalSync = !config.video.verticalSync;
+9
View File
@@ -866,6 +866,15 @@ void gDPTextureRectangle(f32 ulx, f32 uly, f32 lrx, f32 lry, s32 tile, s16 s, s1
gDP.rectColor = gDPInfo::Color();
gDP.lastTexRectInfo.ulx = ulx;
gDP.lastTexRectInfo.lrx = lrx;
gDP.lastTexRectInfo.uly = uly;
gDP.lastTexRectInfo.lry = lry;
gDP.lastTexRectInfo.s = !flip ? s : t;
gDP.lastTexRectInfo.t = !flip ? t : s;
gDP.lastTexRectInfo.dsdx = !flip ? dsdx : dtdy;
gDP.lastTexRectInfo.dtdy = !flip ? dtdy : dsdx;
GraphicsDrawer & drawer = dwnd().getDrawer();
GraphicsDrawer::TexturedRectParams params(ulx, uly, lrx, lry, dsdx, dtdy, s, t,
flip, false, true, frameBufferList().getCurrent());
+9 -1
View File
@@ -122,6 +122,13 @@ struct gDPScissor
s16 xh, yh, xl, yl;
};
struct gDPTexrectInfo
{
f32 ulx, lrx, uly, lry;
s16 s, t;
f32 dsdx, dtdy;
};
struct gDPInfo
{
struct OtherMode
@@ -255,7 +262,8 @@ struct gDPInfo
u64 paletteCRC256;
u32 half_1, half_2;
gDPLoadTileInfo loadInfo[512];
gDPLoadTileInfo loadInfo[512];
gDPTexrectInfo lastTexRectInfo;
};
extern gDPInfo gDP;
+10 -38
View File
@@ -440,7 +440,7 @@ void gSPLookAt( u32 _l, u32 _n )
static
void gSPUpdateLightVectors()
{
InverseTransformVectorNormalizeN(&gSP.lights.xyz[0], &gSP.lights.i_xyz[0],
InverseTransformVectorNormalizeN(&gSP.lights.xyz[0], &gSP.lights.i_xyz[0],
gSP.matrix.modelView[gSP.matrix.modelViewi], gSP.numLights);
gSP.changed ^= CHANGED_LIGHT;
gSP.changed |= CHANGED_HW_LIGHT;
@@ -763,11 +763,13 @@ void gSPBillboardVertex(u32 v, SPVertex * spVtx)
template <u32 VNUM>
void gSPClipVertex(u32 v, SPVertex * spVtx)
{
const f32 scale = dwnd().getAdjustScale();
for (u32 j = 0; j < VNUM; ++j) {
SPVertex & vtx = spVtx[v+j];
vtx.clip = 0;
if (vtx.x > +vtx.w) vtx.clip |= CLIP_POSX;
if (vtx.x < -vtx.w) vtx.clip |= CLIP_NEGX;
const f32 scaledX = vtx.x * scale;
if (scaledX > +vtx.w) vtx.clip |= CLIP_POSX;
if (scaledX < -vtx.w) vtx.clip |= CLIP_NEGX;
if (vtx.y > +vtx.w) vtx.clip |= CLIP_POSY;
if (vtx.y < -vtx.w) vtx.clip |= CLIP_NEGY;
if (vtx.w < 0.01f) vtx.clip |= CLIP_W;
@@ -817,28 +819,6 @@ void gSPProcessVertex(u32 v, SPVertex * spVtx)
gSPTransformVertex<VNUM>(v, spVtx, gSP.matrix.combined );
if (dwnd().isAdjustScreen() && (gDP.colorImage.width > VI.width * 98 / 100)) {
const f32 adjustScale = dwnd().getAdjustScale();
for(int i = 0; i < VNUM; ++i) {
SPVertex & vtx = spVtx[v+i];
vtx.x *= adjustScale;
if (gSP.matrix.projection[3][2] == -1.f)
vtx.w *= adjustScale;
}
}
if (gSP.viewport.vscale[0] < 0) {
for(int i = 0; i < VNUM; ++i) {
SPVertex & vtx = spVtx[v+i];
vtx.x = -vtx.x;
}
}
if (gSP.viewport.vscale[1] < 0) {
for(int i = 0; i < VNUM; ++i) {
SPVertex & vtx = spVtx[v+i];
vtx.y = -vtx.y;
}
}
if (gSP.matrix.billboard)
gSPBillboardVertex<VNUM>(v, spVtx);
@@ -1670,32 +1650,24 @@ void gSPModifyVertex( u32 _vtx, u32 _where, u32 _val )
case G_MWO_POINT_XYSCREEN:
vtx0.x = _FIXED2FLOAT((s16)_SHIFTR(_val, 16, 16), 2);
vtx0.y = _FIXED2FLOAT((s16)_SHIFTR(_val, 0, 16), 2);
DebugMsg(DEBUG_NORMAL, "gSPModifyVertex: XY(%02f, %02f);\n", vtx0.x, vtx0.y);
vtx0.modify |= MODIFY_XY;
vtx0.clip &= ~(CLIP_POSX | CLIP_NEGX | CLIP_POSY | CLIP_NEGY);
if ((config.generalEmulation.hacks & hack_ModifyVertexXyInShader) == 0) {
vtx0.x = (vtx0.x - gSP.viewport.vtrans[0]) / gSP.viewport.vscale[0];
if (gSP.viewport.vscale[0] < 0)
vtx0.x = -vtx0.x;
vtx0.x *= vtx0.w;
if (dwnd().isAdjustScreen()) {
const f32 adjustScale = dwnd().getAdjustScale();
const f32 adjustOffset = static_cast<f32>(VI.width) * (1.0f - adjustScale) / 2.0f;
vtx0.x *= adjustScale;
vtx0.x += adjustOffset;
if (gSP.matrix.projection[3][2] == -1.f)
vtx0.w *= adjustScale;
}
vtx0.y = -(vtx0.y - gSP.viewport.vtrans[1]) / gSP.viewport.vscale[1];
if (gSP.viewport.vscale[1] < 0)
vtx0.y = -vtx0.y;
vtx0.y *= vtx0.w;
} else {
vtx0.modify |= MODIFY_XY;
if (vtx0.w == 0.0f || gDP.otherMode.depthSource == G_ZS_PRIM) {
vtx0.w = 1.0f;
vtx0.clip &= ~(CLIP_W);
}
}
vtx0.clip &= ~(CLIP_POSX | CLIP_NEGX | CLIP_POSY | CLIP_NEGY);
DebugMsg(DEBUG_NORMAL, "gSPModifyVertex: XY(%02f, %02f);\n", vtx0.x, vtx0.y);
break;
case G_MWO_POINT_ZSCREEN:
{
@@ -29,6 +29,10 @@ const char* _hotkeyDescription(u32 _idx)
return "Hotkey: reload HD textures";
case Config::HotKey::hkHdTexToggle:
return "Hotkey: toggle HD textures";
case Config::HotKey::hkTexCoordBounds:
return "Hotkey: toggle texcoords bounds";
case Config::HotKey::hkNativeResTexrects:
return "Hotkey: toggle 2D texrects in native resolution";
case Config::HotKey::hkVsync:
return "Hotkey: toggle VSync";
case Config::HotKey::hkFBEmulation:
@@ -178,6 +182,8 @@ bool Config_SetDefault()
assert(res == M64ERR_SUCCESS);
res = ConfigSetDefaultInt(g_configVideoGliden64, "BackgroundsMode", config.graphics2D.bgMode, "Render backgrounds mode (HLE only). (0=One piece (fast), 1=Stripped (precise))");
assert(res == M64ERR_SUCCESS);
res = ConfigSetDefaultInt(g_configVideoGliden64, "EnableTexCoordBounds", config.graphics2D.enableTexCoordBounds, "Bound texture rectangle texture coordinates to the values they take in native resolutions. It prevents garbage due to fetching out of texture bounds, but can result in hard edges. (0=Off, 1=On)");
assert(res == M64ERR_SUCCESS);
//#Frame Buffer Settings:"
res = ConfigSetDefaultBool(g_configVideoGliden64, "EnableFBEmulation", config.frameBufferEmulation.enable, "Enable frame and|or depth buffer emulation.");
@@ -383,6 +389,8 @@ void Config_LoadCustomConfig()
if (result == M64ERR_SUCCESS) config.graphics2D.enableNativeResTexrects = atoi(value);
result = ConfigExternalGetParameter(fileHandle, sectionName, "graphics2D\\bgMode", value, sizeof(value));
if (result == M64ERR_SUCCESS) config.graphics2D.bgMode = atoi(value);
result = ConfigExternalGetParameter(fileHandle, sectionName, "graphics2D\\enableTexCoordBounds", value, sizeof(value));
if (result == M64ERR_SUCCESS) config.graphics2D.enableTexCoordBounds = atoi(value);
result = ConfigExternalGetParameter(fileHandle, sectionName, "frameBufferEmulation\\enable", value, sizeof(value));
if (result == M64ERR_SUCCESS) config.frameBufferEmulation.enable = atoi(value);
@@ -509,6 +517,7 @@ void Config_LoadConfig()
config.graphics2D.correctTexrectCoords = ConfigGetParamInt(g_configVideoGliden64, "CorrectTexrectCoords");
config.graphics2D.enableNativeResTexrects = ConfigGetParamInt(g_configVideoGliden64, "EnableNativeResTexrects");
config.graphics2D.bgMode = ConfigGetParamInt(g_configVideoGliden64, "BackgroundsMode");
config.graphics2D.enableTexCoordBounds = ConfigGetParamInt(g_configVideoGliden64, "EnableTexCoordBounds");
//#Frame Buffer Settings:"
config.frameBufferEmulation.enable = ConfigGetParamBool(g_configVideoGliden64, "EnableFBEmulation");
config.frameBufferEmulation.copyAuxToRDRAM = ConfigGetParamBool(g_configVideoGliden64, "EnableCopyAuxiliaryToRDRAM");