summaryrefslogtreecommitdiff
path: root/Source/Plugins/Plugin_VideoSoftware/Src/TextureSampler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/Plugins/Plugin_VideoSoftware/Src/TextureSampler.cpp')
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/Src/TextureSampler.cpp166
1 files changed, 109 insertions, 57 deletions
diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/TextureSampler.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/TextureSampler.cpp
index e7001a537b..44878e262b 100644
--- a/Source/Plugins/Plugin_VideoSoftware/Src/TextureSampler.cpp
+++ b/Source/Plugins/Plugin_VideoSoftware/Src/TextureSampler.cpp
@@ -23,28 +23,10 @@
#include <cmath>
-namespace TextureSampler
-{
+#define ALLOW_MIPMAP 1
-inline int iround(float x)
+namespace TextureSampler
{
- int t;
-
-#if defined(_WIN32) && !defined(_M_X64)
- __asm
- {
- fld x
- fistp t
- }
-#else
- t = (int)x;
- if((x - t) >= 0.5)
- return t + 1;
-#endif
-
- return t;
-}
-
inline void WrapCoord(int &coord, int wrapMode, int imageSize)
{
@@ -85,9 +67,53 @@ inline void AddTexel(u8 *inTexel, u32 *outTexel, u32 fract)
outTexel[3] += inTexel[3] * fract;
}
-void Sample(float s, float t, float lod, u8 texmap, u8 *sample)
+void Sample(s32 s, s32 t, s32 lod, bool linear, u8 texmap, u8 *sample)
+{
+ int baseMip = 0;
+ bool mipLinear = false;
+
+#if (ALLOW_MIPMAP)
+ FourTexUnits& texUnit = bpmem.tex[(texmap >> 2) & 1];
+ TexMode0& tm0 = texUnit.texMode0[texmap & 3];
+
+ s32 lodFract = lod & 0xf;
+
+ if (lod > 0 && tm0.min_filter & 3)
+ {
+ // use mipmap
+ baseMip = lod >> 4;
+ mipLinear = (lodFract && tm0.min_filter & 2);
+
+ // if using nearest mip filter and lodFract >= 0.5 round up to next mip
+ baseMip += (lodFract >> 3) & (tm0.min_filter & 1);
+ }
+
+ if (mipLinear)
+ {
+ u8 sampledTex[4];
+ u32 texel[4];
+
+ SampleMip(s, t, baseMip, linear, texmap, sampledTex);
+ SetTexel(sampledTex, texel, (16 - lodFract));
+
+ SampleMip(s, t, baseMip + 1, linear, texmap, sampledTex);
+ AddTexel(sampledTex, texel, lodFract);
+
+ sample[0] = (u8)(texel[0] >> 4);
+ sample[1] = (u8)(texel[1] >> 4);
+ sample[2] = (u8)(texel[2] >> 4);
+ sample[3] = (u8)(texel[3] >> 4);
+ }
+ else
+#endif
+ {
+ SampleMip(s, t, baseMip, linear, texmap, sample);
+ }
+}
+
+void SampleMip(s32 s, s32 t, s32 mip, bool linear, u8 texmap, u8 *sample)
{
- FourTexUnits& texUnit = bpmem.tex[(texmap >> 2) & 1];
+ FourTexUnits& texUnit = bpmem.tex[(texmap >> 2) & 1];
u8 subTexmap = texmap & 3;
TexMode0& tm0 = texUnit.texMode0[subTexmap];
@@ -97,59 +123,85 @@ void Sample(float s, float t, float lod, u8 texmap, u8 *sample)
u32 imageBase = texUnit.texImage3[subTexmap].image_base << 5;
u8 *imageSrc = g_VideoInitialize.pGetMemoryPointer(imageBase);
- bool linear = false;
- if ((lod > 0 && tm0.min_filter > 4) || (lod <= 0 && tm0.mag_filter))
- linear = true;
+ int imageWidth = ti0.width;
+ int imageHeight = ti0.height;
+
+ int tlutAddress = texTlut.tmem_offset << 9;
+
+ // reduce sample location and texture size to mip level
+ // move texture pointer to mip location
+ if (mip)
+ {
+ int mipWidth = imageWidth + 1;
+ int mipHeight = imageHeight + 1;
+
+ int fmtWidth = TexDecoder_GetBlockWidthInTexels(ti0.format);
+ int fmtHeight = TexDecoder_GetBlockHeightInTexels(ti0.format);
+ int fmtDepth = TexDecoder_GetTexelSizeInNibbles(ti0.format);
+
+ imageWidth >>= mip;
+ imageHeight >>= mip;
+ s >>= mip;
+ t >>= mip;
+
+ while (mip)
+ {
+ mipWidth = max(mipWidth, fmtWidth);
+ mipHeight = max(mipHeight, fmtHeight);
+ u32 size = (mipWidth * mipHeight * fmtDepth) >> 1;
+
+ imageSrc += size;
+ mipWidth >>= 1;
+ mipHeight >>= 1;
+ mip--;
+ }
+ }
+
+ // integer part of sample location
+ int imageS = s >> 7;
+ int imageT = t >> 7;
if (linear)
{
- s32 s256 = s32((s - 0.5f) * 256);
- s32 t256 = s32((t- 0.5f) * 256);
-
- int imageS = s256 >> 8;
- int imageSPlus1 = imageS + 1;
- u32 fractS = s256 & 0xff;
- fractS += fractS >> 7;
-
- int imageT = t256 >> 8;
+ // linear sampling
+ int imageSPlus1 = imageS + 1;
+ int fractS = s & 0x7f;
+
int imageTPlus1 = imageT + 1;
- u32 fractT = t256 & 0xff;
- fractT += fractT >> 7;
+ int fractT = t & 0x7f;
u8 sampledTex[4];
u32 texel[4];
- WrapCoord(imageS, tm0.wrap_s, ti0.width);
- WrapCoord(imageT, tm0.wrap_t, ti0.height);
- WrapCoord(imageSPlus1, tm0.wrap_s, ti0.width);
- WrapCoord(imageTPlus1, tm0.wrap_t, ti0.height);
+ WrapCoord(imageS, tm0.wrap_s, imageWidth);
+ WrapCoord(imageT, tm0.wrap_t, imageHeight);
+ WrapCoord(imageSPlus1, tm0.wrap_s, imageWidth);
+ WrapCoord(imageTPlus1, tm0.wrap_t, imageHeight);
- TexDecoder_DecodeTexel(sampledTex, imageSrc, imageS, imageT, ti0.width, ti0.format, texTlut.tmem_offset << 9, texTlut.tlut_format);
- SetTexel(sampledTex, texel, (256 - fractS) * (256 - fractT));
+ TexDecoder_DecodeTexel(sampledTex, imageSrc, imageS, imageT, imageWidth, ti0.format, tlutAddress, texTlut.tlut_format);
+ SetTexel(sampledTex, texel, (128 - fractS) * (128 - fractT));
- TexDecoder_DecodeTexel(sampledTex, imageSrc, imageSPlus1, imageT, ti0.width, ti0.format, texTlut.tmem_offset << 9, texTlut.tlut_format);
- AddTexel(sampledTex, texel, (fractS) * (256 - fractT));
+ TexDecoder_DecodeTexel(sampledTex, imageSrc, imageSPlus1, imageT, imageWidth, ti0.format, tlutAddress, texTlut.tlut_format);
+ AddTexel(sampledTex, texel, (fractS) * (128 - fractT));
- TexDecoder_DecodeTexel(sampledTex, imageSrc, imageS, imageTPlus1, ti0.width, ti0.format, texTlut.tmem_offset << 9, texTlut.tlut_format);
- AddTexel(sampledTex, texel, (256 - fractS) * (fractT));
+ TexDecoder_DecodeTexel(sampledTex, imageSrc, imageS, imageTPlus1, imageWidth, ti0.format, tlutAddress, texTlut.tlut_format);
+ AddTexel(sampledTex, texel, (128 - fractS) * (fractT));
- TexDecoder_DecodeTexel(sampledTex, imageSrc, imageSPlus1, imageTPlus1, ti0.width, ti0.format, texTlut.tmem_offset << 9, texTlut.tlut_format);
+ TexDecoder_DecodeTexel(sampledTex, imageSrc, imageSPlus1, imageTPlus1, imageWidth, ti0.format, tlutAddress, texTlut.tlut_format);
AddTexel(sampledTex, texel, (fractS) * (fractT));
- sample[0] = (u8)(texel[0] >> 16);
- sample[1] = (u8)(texel[1] >> 16);
- sample[2] = (u8)(texel[2] >> 16);
- sample[3] = (u8)(texel[3] >> 16);
+ sample[0] = (u8)(texel[0] >> 14);
+ sample[1] = (u8)(texel[1] >> 14);
+ sample[2] = (u8)(texel[2] >> 14);
+ sample[3] = (u8)(texel[3] >> 14);
}
else
{
- int imageS = int(s);
- int imageT = int(t);
-
- WrapCoord(imageS, tm0.wrap_s, ti0.width);
- WrapCoord(imageT, tm0.wrap_t, ti0.height);
+ // nearest neighbor sampling
+ WrapCoord(imageS, tm0.wrap_s, imageWidth);
+ WrapCoord(imageT, tm0.wrap_t, imageHeight);
- TexDecoder_DecodeTexel(sample, imageSrc, imageS, imageT, ti0.width, ti0.format, texTlut.tmem_offset << 9, texTlut.tlut_format);
+ TexDecoder_DecodeTexel(sample, imageSrc, imageS, imageT, imageWidth, ti0.format, tlutAddress, texTlut.tlut_format);
}
}