OpenGL Renderer:
- Textures can now be automatically upscaled using the xBRZ filter. Textures can be upscaled to 2x or 4x. - Textures can now be smoothed using a deposterization filter. This can be helpful in smoothing some of the hard color banding that sometimes occurs with xBRZ.
This commit is contained in:
parent
e0a139aeda
commit
485e2cc254
|
@ -483,6 +483,8 @@ extern struct TCommonSettings {
|
|||
, GFX3D_LineHack(true)
|
||||
, GFX3D_Zelda_Shadow_Depth_Hack(0)
|
||||
, GFX3D_Renderer_Multisample(false)
|
||||
, GFX3D_Renderer_TextureDeposterize(false)
|
||||
, GFX3D_Renderer_TextureScalingFactor(1) // Possible values: 1, 2, 4
|
||||
, GFX3D_TXTHack(false)
|
||||
, GFX3D_PrescaleHD(1)
|
||||
, jit_max_block_size(100)
|
||||
|
@ -543,6 +545,8 @@ extern struct TCommonSettings {
|
|||
bool GFX3D_LineHack;
|
||||
int GFX3D_Zelda_Shadow_Depth_Hack;
|
||||
bool GFX3D_Renderer_Multisample;
|
||||
bool GFX3D_Renderer_TextureDeposterize;
|
||||
int GFX3D_Renderer_TextureScalingFactor;
|
||||
bool GFX3D_TXTHack;
|
||||
|
||||
//may not want this on OSX port
|
||||
|
|
|
@ -2880,7 +2880,6 @@ Render3DError OpenGLRenderer_1_2::SetupTexture(const POLY &thePoly, bool enableT
|
|||
glEnable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
// texCacheUnit.TexCache_SetTexture<TexFormat_32bpp>(format, texpal);
|
||||
TexCacheItem *newTexture = TexCache_SetTexture(TexFormat_32bpp, thePoly.texParam, thePoly.texPalette);
|
||||
if(newTexture != this->currTexture)
|
||||
{
|
||||
|
@ -2899,15 +2898,42 @@ Render3DError OpenGLRenderer_1_2::SetupTexture(const POLY &thePoly, bool enableT
|
|||
OGLRef.freeTextureIDs.pop();
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, (GLuint)this->currTexture->texid);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (params.enableRepeatS ? (params.enableMirroredRepeatS ? OGLRef.stateTexMirroredRepeat : GL_REPEAT) : GL_CLAMP_TO_EDGE));
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (params.enableRepeatT ? (params.enableMirroredRepeatT ? OGLRef.stateTexMirroredRepeat : GL_REPEAT) : GL_CLAMP_TO_EDGE));
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
|
||||
this->currTexture->sizeX, this->currTexture->sizeY, 0,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, this->currTexture->decoded);
|
||||
u32 *textureSrc = (u32 *)currTexture->decoded;
|
||||
size_t texWidth = currTexture->sizeX;
|
||||
size_t texHeight = currTexture->sizeY;
|
||||
|
||||
if (this->_textureDeposterizeBuffer != NULL)
|
||||
{
|
||||
this->TextureDeposterize(textureSrc, texWidth, texHeight);
|
||||
textureSrc = this->_textureDeposterizeBuffer;
|
||||
}
|
||||
|
||||
switch (this->_textureScalingFactor)
|
||||
{
|
||||
case 2:
|
||||
{
|
||||
this->TextureUpscale<2>(textureSrc, texWidth, texHeight);
|
||||
textureSrc = this->_textureUpscaleBuffer;
|
||||
break;
|
||||
}
|
||||
|
||||
case 4:
|
||||
{
|
||||
this->TextureUpscale<4>(textureSrc, texWidth, texHeight);
|
||||
textureSrc = this->_textureUpscaleBuffer;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureSrc);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -4393,7 +4419,6 @@ Render3DError OpenGLRenderer_2_0::SetupTexture(const POLY &thePoly, bool enableT
|
|||
|
||||
glUniform1i(OGLRef.uniformPolyEnableTexture, GL_TRUE);
|
||||
|
||||
// texCacheUnit.TexCache_SetTexture<TexFormat_32bpp>(format, texpal);
|
||||
TexCacheItem *newTexture = TexCache_SetTexture(TexFormat_32bpp, thePoly.texParam, thePoly.texPalette);
|
||||
if(newTexture != this->currTexture)
|
||||
{
|
||||
|
@ -4412,15 +4437,42 @@ Render3DError OpenGLRenderer_2_0::SetupTexture(const POLY &thePoly, bool enableT
|
|||
OGLRef.freeTextureIDs.pop();
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, (GLuint)this->currTexture->texid);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (params.enableRepeatS ? (params.enableMirroredRepeatS ? GL_MIRRORED_REPEAT : GL_REPEAT) : GL_CLAMP_TO_EDGE));
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (params.enableRepeatT ? (params.enableMirroredRepeatT ? GL_MIRRORED_REPEAT : GL_REPEAT) : GL_CLAMP_TO_EDGE));
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
|
||||
this->currTexture->sizeX, this->currTexture->sizeY, 0,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, this->currTexture->decoded);
|
||||
u32 *textureSrc = (u32 *)currTexture->decoded;
|
||||
size_t texWidth = currTexture->sizeX;
|
||||
size_t texHeight = currTexture->sizeY;
|
||||
|
||||
if (this->_textureDeposterizeBuffer != NULL)
|
||||
{
|
||||
this->TextureDeposterize(textureSrc, texWidth, texHeight);
|
||||
textureSrc = this->_textureDeposterizeBuffer;
|
||||
}
|
||||
|
||||
switch (this->_textureScalingFactor)
|
||||
{
|
||||
case 2:
|
||||
{
|
||||
this->TextureUpscale<2>(textureSrc, texWidth, texHeight);
|
||||
textureSrc = this->_textureUpscaleBuffer;
|
||||
break;
|
||||
}
|
||||
|
||||
case 4:
|
||||
{
|
||||
this->TextureUpscale<4>(textureSrc, texWidth, texHeight);
|
||||
textureSrc = this->_textureUpscaleBuffer;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureSrc);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -1671,15 +1671,42 @@ Render3DError OpenGLRenderer_3_2::SetupTexture(const POLY &thePoly, bool enableT
|
|||
OGLRef.freeTextureIDs.pop();
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, (GLuint)this->currTexture->texid);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (params.enableRepeatS ? (params.enableMirroredRepeatS ? GL_MIRRORED_REPEAT : GL_REPEAT) : GL_CLAMP_TO_EDGE));
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (params.enableRepeatT ? (params.enableMirroredRepeatT ? GL_MIRRORED_REPEAT : GL_REPEAT) : GL_CLAMP_TO_EDGE));
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
|
||||
this->currTexture->sizeX, this->currTexture->sizeY, 0,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, this->currTexture->decoded);
|
||||
u32 *textureSrc = (u32 *)currTexture->decoded;
|
||||
size_t texWidth = currTexture->sizeX;
|
||||
size_t texHeight = currTexture->sizeY;
|
||||
|
||||
if (this->_textureDeposterizeBuffer != NULL)
|
||||
{
|
||||
this->TextureDeposterize(textureSrc, texWidth, texHeight);
|
||||
textureSrc = this->_textureDeposterizeBuffer;
|
||||
}
|
||||
|
||||
switch (this->_textureScalingFactor)
|
||||
{
|
||||
case 2:
|
||||
{
|
||||
this->TextureUpscale<2>(textureSrc, texWidth, texHeight);
|
||||
textureSrc = this->_textureUpscaleBuffer;
|
||||
break;
|
||||
}
|
||||
|
||||
case 4:
|
||||
{
|
||||
this->TextureUpscale<4>(textureSrc, texWidth, texHeight);
|
||||
textureSrc = this->_textureUpscaleBuffer;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureSrc);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -43,6 +43,8 @@
|
|||
#define COLOR_MASK_G 0x0000FF00
|
||||
#define COLOR_MASK_B 0x000000FF
|
||||
|
||||
#define USE_DESMUME_TEXTURE_UPSCALE_ALPHA_BLEND
|
||||
|
||||
namespace
|
||||
{
|
||||
template <uint32_t N> inline
|
||||
|
@ -87,8 +89,27 @@ uint32_t gradientARGB(uint32_t pixFront, uint32_t pixBack) //find intermediate c
|
|||
const unsigned int weightFront = getAlpha(pixFront) * M;
|
||||
const unsigned int weightBack = getAlpha(pixBack) * (N - M);
|
||||
const unsigned int weightSum = weightFront + weightBack;
|
||||
|
||||
#ifdef USE_DESMUME_TEXTURE_UPSCALE_ALPHA_BLEND
|
||||
if (weightSum == 0)
|
||||
{
|
||||
return (pixFront & 0x00FFFFFF);
|
||||
}
|
||||
else if (weightFront == 0)
|
||||
{
|
||||
return pixBack;
|
||||
}
|
||||
else if (weightBack == 0)
|
||||
{
|
||||
return pixFront;
|
||||
}
|
||||
#else
|
||||
if (weightSum == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
auto calcColor = [=](unsigned char colFront, unsigned char colBack)
|
||||
{
|
||||
|
@ -1165,13 +1186,13 @@ struct ColorGradientARGB
|
|||
};
|
||||
}
|
||||
|
||||
|
||||
void xbrz::scale(size_t factor, const uint32_t* src, uint32_t* trg, int srcWidth, int srcHeight, ColorFormat colFmt, const xbrz::ScalerCfg& cfg, int yFirst, int yLast)
|
||||
template <size_t SCALEFACTOR, xbrz::ColorFormat FORMAT>
|
||||
void xbrz::scale(const uint32_t* src, uint32_t* trg, int srcWidth, int srcHeight, const xbrz::ScalerCfg& cfg, int yFirst, int yLast)
|
||||
{
|
||||
switch (colFmt)
|
||||
switch (FORMAT)
|
||||
{
|
||||
case ColorFormatARGB:
|
||||
switch (factor)
|
||||
switch (SCALEFACTOR)
|
||||
{
|
||||
case 2:
|
||||
return scaleImage<Scaler2x<ColorGradientARGB>, ColorDistanceARGB>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast);
|
||||
|
@ -1187,7 +1208,7 @@ void xbrz::scale(size_t factor, const uint32_t* src, uint32_t* trg, int srcWidth
|
|||
break;
|
||||
|
||||
case ColorFormatRGB:
|
||||
switch (factor)
|
||||
switch (SCALEFACTOR)
|
||||
{
|
||||
case 2:
|
||||
return scaleImage<Scaler2x<ColorGradientRGB>, ColorDistanceRGB>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast);
|
||||
|
@ -1294,25 +1315,28 @@ void xbrz::nearestNeighborScale(const uint32_t* src, int srcWidth, int srcHeight
|
|||
|
||||
void Render2xBRZ(SSurface Src, SSurface Dst)
|
||||
{
|
||||
xbrz::scale(2, (const uint32_t *)Src.Surface, (uint32_t *)Dst.Surface, Src.Width, Src.Height, xbrz::ColorFormatRGB);
|
||||
xbrz::scale<2, xbrz::ColorFormatRGB>((const uint32_t *)Src.Surface, (uint32_t *)Dst.Surface, Src.Width, Src.Height);
|
||||
}
|
||||
|
||||
void Render3xBRZ(SSurface Src, SSurface Dst)
|
||||
{
|
||||
xbrz::scale(3, (const uint32_t *)Src.Surface, (uint32_t *)Dst.Surface, Src.Width, Src.Height, xbrz::ColorFormatRGB);
|
||||
xbrz::scale<3, xbrz::ColorFormatRGB>((const uint32_t *)Src.Surface, (uint32_t *)Dst.Surface, Src.Width, Src.Height);
|
||||
}
|
||||
|
||||
void Render4xBRZ(SSurface Src, SSurface Dst)
|
||||
{
|
||||
xbrz::scale(4, (const uint32_t *)Src.Surface, (uint32_t *)Dst.Surface, Src.Width, Src.Height, xbrz::ColorFormatRGB);
|
||||
xbrz::scale<4, xbrz::ColorFormatRGB>((const uint32_t *)Src.Surface, (uint32_t *)Dst.Surface, Src.Width, Src.Height);
|
||||
}
|
||||
|
||||
void Render5xBRZ(SSurface Src, SSurface Dst)
|
||||
{
|
||||
xbrz::scale(5, (const uint32_t *)Src.Surface, (uint32_t *)Dst.Surface, Src.Width, Src.Height, xbrz::ColorFormatRGB);
|
||||
xbrz::scale<5, xbrz::ColorFormatRGB>((const uint32_t *)Src.Surface, (uint32_t *)Dst.Surface, Src.Width, Src.Height);
|
||||
}
|
||||
|
||||
void Render6xBRZ(SSurface Src, SSurface Dst)
|
||||
{
|
||||
xbrz::scale(6, (const uint32_t *)Src.Surface, (uint32_t *)Dst.Surface, Src.Width, Src.Height, xbrz::ColorFormatRGB);
|
||||
xbrz::scale<6, xbrz::ColorFormatRGB>((const uint32_t *)Src.Surface, (uint32_t *)Dst.Surface, Src.Width, Src.Height);
|
||||
}
|
||||
|
||||
template void xbrz::scale<2, xbrz::ColorFormatARGB>(const uint32_t* src, uint32_t* trg, int srcWidth, int srcHeight, const xbrz::ScalerCfg& cfg, int yFirst, int yLast);
|
||||
template void xbrz::scale<4, xbrz::ColorFormatARGB>(const uint32_t* src, uint32_t* trg, int srcWidth, int srcHeight, const xbrz::ScalerCfg& cfg, int yFirst, int yLast);
|
||||
|
|
|
@ -83,9 +83,8 @@ struct ScalerCfg
|
|||
double newTestAttribute_; //unused; test new parameters
|
||||
};
|
||||
|
||||
void scale(size_t factor, //valid range: 2 - 6
|
||||
const uint32_t* src, uint32_t* trg, int srcWidth, int srcHeight,
|
||||
ColorFormat colFmt,
|
||||
template<size_t SCALEFACTOR, xbrz::ColorFormat FORMAT> //valid range: 2 - 6
|
||||
void scale(const uint32_t* src, uint32_t* trg, int srcWidth, int srcHeight,
|
||||
const ScalerCfg& cfg = ScalerCfg(),
|
||||
int yFirst = 0, int yLast = std::numeric_limits<int>::max()); //slice of source image
|
||||
|
||||
|
|
|
@ -2329,6 +2329,7 @@ void gfx3d_VBlankEndSignal(bool skipFrame)
|
|||
|
||||
GPU->GetEventHandler()->DidRender3DBegin();
|
||||
CurrentRenderer->SetRenderNeedsFinish(true);
|
||||
CurrentRenderer->SetTextureProcessingProperties(CommonSettings.GFX3D_Renderer_TextureDeposterize, CommonSettings.GFX3D_Renderer_TextureScalingFactor);
|
||||
CurrentRenderer->Render(gfx3d);
|
||||
}
|
||||
|
||||
|
|
|
@ -33,7 +33,9 @@
|
|||
#include "gfx3d.h"
|
||||
#include "MMU.h"
|
||||
#include "texcache.h"
|
||||
#include "./filter/xbrz.h"
|
||||
|
||||
#define TEXTURE_DEPOSTERIZE_THRESHOLD 21 // Possible values are [0-255], where lower a value prevents blending and a higher value allows for more blending
|
||||
|
||||
static CACHE_ALIGN u32 dsDepthToD24_LUT[32768] = {0};
|
||||
int cur3DCore = GPU3D_NULL;
|
||||
|
@ -128,6 +130,55 @@ void Render3DBaseDestroy()
|
|||
}
|
||||
}
|
||||
|
||||
static u32 TextureDeposterize_InterpLTE(const u32 pixA, const u32 pixB, const u32 threshold)
|
||||
{
|
||||
const u32 aB = (pixB & 0xFF000000) >> 24;
|
||||
if (aB == 0)
|
||||
{
|
||||
return pixA;
|
||||
}
|
||||
|
||||
const u32 rA = (pixA & 0x000000FF);
|
||||
const u32 gA = (pixA & 0x0000FF00) >> 8;
|
||||
const u32 bA = (pixA & 0x00FF0000) >> 16;
|
||||
const u32 aA = (pixA & 0xFF000000) >> 24;
|
||||
|
||||
const u32 rB = (pixB & 0x000000FF);
|
||||
const u32 gB = (pixB & 0x0000FF00) >> 8;
|
||||
const u32 bB = (pixB & 0x00FF0000) >> 16;
|
||||
|
||||
const u32 rC = ( (rB - rA <= threshold) || (rA - rB <= threshold) ) ? ( ((rA+rB)>>1) ) : rA;
|
||||
const u32 gC = ( (gB - gA <= threshold) || (gA - gB <= threshold) ) ? ( ((gA+gB)>>1) ) : gA;
|
||||
const u32 bC = ( (bB - bA <= threshold) || (bA - bB <= threshold) ) ? ( ((bA+bB)>>1) ) : bA;
|
||||
const u32 aC = ( (bB - aA <= threshold) || (aA - aB <= threshold) ) ? ( ((aA+aB)>>1) ) : aA;
|
||||
|
||||
return (rC | (gC << 8) | (bC << 16) | (aC << 24));
|
||||
}
|
||||
|
||||
static u32 TextureDeposterize_Blend(const u32 pixA, const u32 pixB, const u32 weightA, const u32 weightB)
|
||||
{
|
||||
const u32 aB = (pixB & 0xFF000000) >> 24;
|
||||
if (aB == 0)
|
||||
{
|
||||
return pixA;
|
||||
}
|
||||
|
||||
const u32 weightSum = weightA + weightB;
|
||||
|
||||
const u32 rbA = pixA & 0x00FF00FF;
|
||||
const u32 gA = pixA & 0x0000FF00;
|
||||
const u32 aA = (pixA & 0xFF000000) >> 24;
|
||||
|
||||
const u32 rbB = pixB & 0x00FF00FF;
|
||||
const u32 gB = pixB & 0x0000FF00;
|
||||
|
||||
const u32 rbC = ( ((rbA * weightA) + (rbB * weightB)) / weightSum ) & 0x00FF00FF;
|
||||
const u32 gC = ( (( gA * weightA) + ( gB * weightB)) / weightSum ) & 0x0000FF00;
|
||||
const u32 aC = ( (( aA * weightA) + ( aB * weightB)) / weightSum ) << 24;
|
||||
|
||||
return (rbC | gC | aC);
|
||||
}
|
||||
|
||||
FragmentAttributesBuffer::FragmentAttributesBuffer(size_t newCount)
|
||||
{
|
||||
count = newCount;
|
||||
|
@ -236,6 +287,10 @@ Render3D::Render3D()
|
|||
_willFlushFramebufferRGBA6665 = true;
|
||||
_willFlushFramebufferRGBA5551 = true;
|
||||
|
||||
_textureScalingFactor = 1;
|
||||
_textureDeposterizeBuffer = NULL;
|
||||
_textureUpscaleBuffer = NULL;
|
||||
|
||||
Reset();
|
||||
}
|
||||
|
||||
|
@ -311,6 +366,180 @@ void Render3D::SetRenderNeedsFinish(const bool renderNeedsFinish)
|
|||
this->_renderNeedsFinish = renderNeedsFinish;
|
||||
}
|
||||
|
||||
void Render3D::SetTextureProcessingProperties(bool willDeposterize, size_t scalingFactor)
|
||||
{
|
||||
const bool isScaleValid = ( (scalingFactor == 2) || (scalingFactor == 4) );
|
||||
const size_t newScalingFactor = (isScaleValid) ? scalingFactor : 1;
|
||||
bool needTexCacheReset = false;
|
||||
|
||||
if ( willDeposterize && (this->_textureDeposterizeBuffer == NULL) )
|
||||
{
|
||||
// 1024x1024 texels is the largest possible texture size.
|
||||
// We need two buffers, one for each deposterize stage.
|
||||
const size_t bufferSize = 1024 * 1024 * 2 * sizeof(u32);
|
||||
this->_textureDeposterizeBuffer = (u32 *)malloc_alignedCacheLine(bufferSize);
|
||||
memset(this->_textureDeposterizeBuffer, 0, bufferSize);
|
||||
|
||||
needTexCacheReset = true;
|
||||
}
|
||||
else if ( !willDeposterize && (this->_textureDeposterizeBuffer != NULL) )
|
||||
{
|
||||
free_aligned(this->_textureDeposterizeBuffer);
|
||||
this->_textureDeposterizeBuffer = NULL;
|
||||
|
||||
needTexCacheReset = true;
|
||||
}
|
||||
|
||||
if (newScalingFactor != this->_textureScalingFactor)
|
||||
{
|
||||
u32 *oldTextureBuffer = this->_textureUpscaleBuffer;
|
||||
u32 *newTextureBuffer = (u32 *)malloc_alignedCacheLine( (1024 * newScalingFactor) * (1024 * newScalingFactor) * sizeof(u32) );
|
||||
this->_textureScalingFactor = newScalingFactor;
|
||||
this->_textureUpscaleBuffer = newTextureBuffer;
|
||||
free_aligned(oldTextureBuffer);
|
||||
|
||||
needTexCacheReset = true;
|
||||
}
|
||||
|
||||
if (needTexCacheReset)
|
||||
{
|
||||
TexCache_Reset();
|
||||
}
|
||||
}
|
||||
|
||||
Render3DError Render3D::TextureDeposterize(const u32 *src, const size_t srcTexWidth, const size_t srcTexHeight)
|
||||
{
|
||||
//---------------------------------------\n\
|
||||
// Input Pixel Mapping: 06|07|08
|
||||
// 05|00|01
|
||||
// 04|03|02
|
||||
//
|
||||
// Output Pixel Mapping: 00
|
||||
|
||||
const int w = srcTexWidth;
|
||||
const int h = srcTexHeight;
|
||||
|
||||
u32 color[9];
|
||||
u32 blend[9];
|
||||
u32 *dst = this->_textureDeposterizeBuffer + (1024 * 1024);
|
||||
u32 *finalDst = this->_textureDeposterizeBuffer;
|
||||
|
||||
size_t i = 0;
|
||||
for (int y = 0; y < h; y++)
|
||||
{
|
||||
for (int x = 0; x < w; x++, i++)
|
||||
{
|
||||
if ((src[i] & 0xFF000000) == 0)
|
||||
{
|
||||
dst[i] = src[i];
|
||||
continue;
|
||||
}
|
||||
|
||||
color[0] = src[i];
|
||||
color[1] = (x < w-1) ? src[i+1] : src[i];
|
||||
color[2] = ((x < w-1) && (y < h-1)) ? src[i+w+1] : src[i];
|
||||
color[3] = (y < h-1) ? src[i+w] : src[i];
|
||||
color[4] = ((x > 0) && (y < h-1)) ? src[i+w-1] : src[i];
|
||||
color[5] = (x > 0) ? src[i-1] : src[i];
|
||||
color[6] = ((x > 0) && (y > 0)) ? src[i-w-1] : src[i];
|
||||
color[7] = (y > 0) ? src[i-w] : src[i];
|
||||
color[8] = ((x < w-1) && (y > 0)) ? src[i-w+1] : src[i];
|
||||
|
||||
blend[0] = color[0];
|
||||
blend[1] = TextureDeposterize_InterpLTE(color[0], color[1], TEXTURE_DEPOSTERIZE_THRESHOLD);
|
||||
blend[2] = TextureDeposterize_InterpLTE(color[0], color[2], TEXTURE_DEPOSTERIZE_THRESHOLD);
|
||||
blend[3] = TextureDeposterize_InterpLTE(color[0], color[3], TEXTURE_DEPOSTERIZE_THRESHOLD);
|
||||
blend[4] = TextureDeposterize_InterpLTE(color[0], color[4], TEXTURE_DEPOSTERIZE_THRESHOLD);
|
||||
blend[5] = TextureDeposterize_InterpLTE(color[0], color[5], TEXTURE_DEPOSTERIZE_THRESHOLD);
|
||||
blend[6] = TextureDeposterize_InterpLTE(color[0], color[6], TEXTURE_DEPOSTERIZE_THRESHOLD);
|
||||
blend[7] = TextureDeposterize_InterpLTE(color[0], color[7], TEXTURE_DEPOSTERIZE_THRESHOLD);
|
||||
blend[8] = TextureDeposterize_InterpLTE(color[0], color[8], TEXTURE_DEPOSTERIZE_THRESHOLD);
|
||||
|
||||
dst[i] = TextureDeposterize_Blend(TextureDeposterize_Blend(TextureDeposterize_Blend(TextureDeposterize_Blend(blend[0], blend[5], 1, 7),
|
||||
TextureDeposterize_Blend(blend[0], blend[1], 1, 7),
|
||||
1, 1),
|
||||
TextureDeposterize_Blend(TextureDeposterize_Blend(blend[0], blend[7], 1, 7),
|
||||
TextureDeposterize_Blend(blend[0], blend[3], 1, 7),
|
||||
1, 1),
|
||||
1, 1),
|
||||
TextureDeposterize_Blend(TextureDeposterize_Blend(TextureDeposterize_Blend(blend[0], blend[6], 7, 9),
|
||||
TextureDeposterize_Blend(blend[0], blend[2], 7, 9),
|
||||
1, 1),
|
||||
TextureDeposterize_Blend(TextureDeposterize_Blend(blend[0], blend[8], 7, 9),
|
||||
TextureDeposterize_Blend(blend[0], blend[4], 7, 9),
|
||||
1, 1),
|
||||
1, 1),
|
||||
3, 1);
|
||||
}
|
||||
}
|
||||
|
||||
i = 0;
|
||||
for (int y = 0; y < h; y++)
|
||||
{
|
||||
for (int x = 0; x < w; x++, i++)
|
||||
{
|
||||
if ((src[i] & 0xFF000000) == 0)
|
||||
{
|
||||
finalDst[i] = src[i];
|
||||
continue;
|
||||
}
|
||||
|
||||
color[0] = dst[i];
|
||||
color[1] = (x < w-1) ? dst[i+1] : dst[i];
|
||||
color[2] = ((x < w-1) && (y < h-1)) ? dst[i+w+1] : dst[i];
|
||||
color[3] = (y < h-1) ? dst[i+w] : dst[i];
|
||||
color[4] = ((x > 0) && (y < h-1)) ? dst[i+w-1] : dst[i];
|
||||
color[5] = (x > 0) ? dst[i-1] : dst[i];
|
||||
color[6] = ((x > 0) && (y > 0)) ? dst[i-w-1] : dst[i];
|
||||
color[7] = (y > 0) ? dst[i-w] : dst[i];
|
||||
color[8] = ((x < w-1) && (y > 0)) ? dst[i-w+1] : dst[i];
|
||||
|
||||
blend[0] = color[0];
|
||||
blend[1] = TextureDeposterize_InterpLTE(color[0], color[1], TEXTURE_DEPOSTERIZE_THRESHOLD);
|
||||
blend[2] = TextureDeposterize_InterpLTE(color[0], color[2], TEXTURE_DEPOSTERIZE_THRESHOLD);
|
||||
blend[3] = TextureDeposterize_InterpLTE(color[0], color[3], TEXTURE_DEPOSTERIZE_THRESHOLD);
|
||||
blend[4] = TextureDeposterize_InterpLTE(color[0], color[4], TEXTURE_DEPOSTERIZE_THRESHOLD);
|
||||
blend[5] = TextureDeposterize_InterpLTE(color[0], color[5], TEXTURE_DEPOSTERIZE_THRESHOLD);
|
||||
blend[6] = TextureDeposterize_InterpLTE(color[0], color[6], TEXTURE_DEPOSTERIZE_THRESHOLD);
|
||||
blend[7] = TextureDeposterize_InterpLTE(color[0], color[7], TEXTURE_DEPOSTERIZE_THRESHOLD);
|
||||
blend[8] = TextureDeposterize_InterpLTE(color[0], color[8], TEXTURE_DEPOSTERIZE_THRESHOLD);
|
||||
|
||||
finalDst[i] = TextureDeposterize_Blend(TextureDeposterize_Blend(TextureDeposterize_Blend(TextureDeposterize_Blend(blend[0], blend[5], 1, 7),
|
||||
TextureDeposterize_Blend(blend[0], blend[1], 1, 7),
|
||||
1, 1),
|
||||
TextureDeposterize_Blend(TextureDeposterize_Blend(blend[0], blend[7], 1, 7),
|
||||
TextureDeposterize_Blend(blend[0], blend[3], 1, 7),
|
||||
1, 1),
|
||||
1, 1),
|
||||
TextureDeposterize_Blend(TextureDeposterize_Blend(TextureDeposterize_Blend(blend[0], blend[6], 7, 9),
|
||||
TextureDeposterize_Blend(blend[0], blend[2], 7, 9),
|
||||
1, 1),
|
||||
TextureDeposterize_Blend(TextureDeposterize_Blend(blend[0], blend[8], 7, 9),
|
||||
TextureDeposterize_Blend(blend[0], blend[4], 7, 9),
|
||||
1, 1),
|
||||
1, 1),
|
||||
3, 1);
|
||||
}
|
||||
}
|
||||
|
||||
return RENDER3DERROR_NOERR;
|
||||
}
|
||||
|
||||
template <size_t SCALEFACTOR>
|
||||
Render3DError Render3D::TextureUpscale(const u32 *src, size_t &outTexWidth, size_t &outTexHeight)
|
||||
{
|
||||
if ( (SCALEFACTOR != 2) && (SCALEFACTOR != 4) )
|
||||
{
|
||||
return RENDER3DERROR_NOERR;
|
||||
}
|
||||
|
||||
xbrz::scale<SCALEFACTOR, xbrz::ColorFormatARGB>(src, this->_textureUpscaleBuffer, outTexWidth, outTexHeight);
|
||||
|
||||
outTexWidth *= SCALEFACTOR;
|
||||
outTexHeight *= SCALEFACTOR;
|
||||
return RENDER3DERROR_NOERR;
|
||||
}
|
||||
|
||||
Render3DError Render3D::BeginRender(const GFX3D &engine)
|
||||
{
|
||||
return RENDER3DERROR_NOERR;
|
||||
|
@ -745,3 +974,6 @@ Render3DError Render3D_SSE2::ClearFramebuffer(const GFX3D_State &renderState)
|
|||
}
|
||||
|
||||
#endif // ENABLE_SSE2
|
||||
|
||||
template Render3DError Render3D::TextureUpscale<2>(const u32 *src, size_t &outTexWidth, size_t &outTexHeight);
|
||||
template Render3DError Render3D::TextureUpscale<4>(const u32 *src, size_t &outTexWidth, size_t &outTexHeight);
|
||||
|
|
|
@ -113,11 +113,18 @@ protected:
|
|||
bool _willFlushFramebufferRGBA6665;
|
||||
bool _willFlushFramebufferRGBA5551;
|
||||
|
||||
size_t _textureScalingFactor;
|
||||
u32 *_textureDeposterizeBuffer;
|
||||
u32 *_textureUpscaleBuffer;
|
||||
|
||||
CACHE_ALIGN u16 clearImageColor16Buffer[GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT];
|
||||
CACHE_ALIGN u32 clearImageDepthBuffer[GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT];
|
||||
CACHE_ALIGN u8 clearImageFogBuffer[GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT];
|
||||
CACHE_ALIGN u8 clearImagePolyIDBuffer[GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT];
|
||||
|
||||
Render3DError TextureDeposterize(const u32 *src, const size_t srcTexWidth, const size_t srcTexHeight);
|
||||
template<size_t SCALEFACTOR> Render3DError TextureUpscale(const u32 *src, size_t &outTexWidth, size_t &outTexHeight);
|
||||
|
||||
virtual Render3DError BeginRender(const GFX3D &engine);
|
||||
virtual Render3DError RenderGeometry(const GFX3D_State &renderState, const POLYLIST *polyList, const INDEXLIST *indexList);
|
||||
virtual Render3DError RenderEdgeMarking(const u16 *colorTable, const bool useAntialias);
|
||||
|
@ -166,6 +173,8 @@ public:
|
|||
|
||||
bool GetRenderNeedsFinish() const;
|
||||
void SetRenderNeedsFinish(const bool renderNeedsFinish);
|
||||
|
||||
void SetTextureProcessingProperties(bool willDeposterize, size_t scalingFactor);
|
||||
};
|
||||
|
||||
#ifdef ENABLE_SSE2
|
||||
|
|
Loading…
Reference in New Issue