diff options
| author | Jasper St. Pierre <jstpierre@mecheye.net> | 2013-12-07 15:14:29 -0500 |
|---|---|---|
| committer | Jasper St. Pierre <jstpierre@mecheye.net> | 2013-12-31 14:03:19 -0500 |
| commit | 34692ab826abc8f8faa61bdb2280b742424528f1 (patch) | |
| tree | b0eedc645badbea316ff59c125eaf808b28777ec /Source/Core/VideoBackends/Software/TextureSampler.cpp | |
| parent | 43e618682e8093602fc83dfa902ee7ae3fd3a4f6 (diff) | |
Remove unnecessary Src/ folders
Diffstat (limited to 'Source/Core/VideoBackends/Software/TextureSampler.cpp')
| -rw-r--r-- | Source/Core/VideoBackends/Software/TextureSampler.cpp | 233 |
1 files changed, 233 insertions, 0 deletions
diff --git a/Source/Core/VideoBackends/Software/TextureSampler.cpp b/Source/Core/VideoBackends/Software/TextureSampler.cpp new file mode 100644 index 0000000000..0657f701f2 --- /dev/null +++ b/Source/Core/VideoBackends/Software/TextureSampler.cpp @@ -0,0 +1,233 @@ +// Copyright 2013 Dolphin Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#include "TextureSampler.h" + +#include "BPMemLoader.h" +#include "TextureDecoder.h" +#include "HW/Memmap.h" + +#include <cmath> + +#define ALLOW_MIPMAP 1 + +namespace TextureSampler +{ + +inline void WrapCoord(int &coord, int wrapMode, int imageSize) +{ + switch (wrapMode) + { + case 0: // clamp + coord = (coord>imageSize)?imageSize:(coord<0)?0:coord; + break; + case 1: // wrap + coord = coord % (imageSize + 1); + coord = (coord<0)?imageSize+coord:coord; + break; + case 2: // mirror + { + int sizePlus1 = imageSize + 1; + int div = coord / sizePlus1; + coord = coord - (div * sizePlus1); + coord = (coord<0)?-coord:coord; + coord = (div&1)?imageSize - coord:coord; + } + break; + } +} + +inline void SetTexel(u8 *inTexel, u32 *outTexel, u32 fract) +{ + outTexel[0] = inTexel[0] * fract; + outTexel[1] = inTexel[1] * fract; + outTexel[2] = inTexel[2] * fract; + outTexel[3] = inTexel[3] * fract; +} + +inline void AddTexel(u8 *inTexel, u32 *outTexel, u32 fract) +{ + outTexel[0] += inTexel[0] * fract; + outTexel[1] += inTexel[1] * fract; + outTexel[2] += inTexel[2] * fract; + outTexel[3] += inTexel[3] * fract; +} + +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]; + u8 subTexmap = texmap & 3; + + TexMode0& tm0 = texUnit.texMode0[subTexmap]; + TexImage0& ti0 = texUnit.texImage0[subTexmap]; + TexTLUT& texTlut = texUnit.texTlut[subTexmap]; + + u8 *imageSrc, *imageSrcOdd = NULL; + if (texUnit.texImage1[subTexmap].image_type) + { + imageSrc = &texMem[texUnit.texImage1[subTexmap].tmem_even * TMEM_LINE_SIZE]; + if (ti0.format == GX_TF_RGBA8) + imageSrcOdd = &texMem[texUnit.texImage2[subTexmap].tmem_odd * TMEM_LINE_SIZE]; + } + else + { + u32 imageBase = texUnit.texImage3[subTexmap].image_base << 5; + imageSrc = Memory::GetPointer(imageBase); + } + + 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--; + } + } + + if (linear) + { + // offset linear sampling + s -= 64; + t -= 64; + + // integer part of sample location + int imageS = s >> 7; + int imageT = t >> 7; + + // linear sampling + int imageSPlus1 = imageS + 1; + int fractS = s & 0x7f; + + int imageTPlus1 = imageT + 1; + int fractT = t & 0x7f; + + u8 sampledTex[4]; + u32 texel[4]; + + WrapCoord(imageS, tm0.wrap_s, imageWidth); + WrapCoord(imageT, tm0.wrap_t, imageHeight); + WrapCoord(imageSPlus1, tm0.wrap_s, imageWidth); + WrapCoord(imageTPlus1, tm0.wrap_t, imageHeight); + + if (!(ti0.format == GX_TF_RGBA8 && texUnit.texImage1[subTexmap].image_type)) + { + 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, imageWidth, ti0.format, tlutAddress, texTlut.tlut_format); + AddTexel(sampledTex, texel, (fractS) * (128 - 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, imageWidth, ti0.format, tlutAddress, texTlut.tlut_format); + AddTexel(sampledTex, texel, (fractS) * (fractT)); + } + else + { + TexDecoder_DecodeTexelRGBA8FromTmem(sampledTex, imageSrc, imageSrcOdd, imageS, imageT, imageWidth); + SetTexel(sampledTex, texel, (128 - fractS) * (128 - fractT)); + + TexDecoder_DecodeTexelRGBA8FromTmem(sampledTex, imageSrc, imageSrcOdd, imageSPlus1, imageT, imageWidth); + AddTexel(sampledTex, texel, (fractS) * (128 - fractT)); + + TexDecoder_DecodeTexelRGBA8FromTmem(sampledTex, imageSrc, imageSrcOdd, imageS, imageTPlus1, imageWidth); + AddTexel(sampledTex, texel, (128 - fractS) * (fractT)); + + TexDecoder_DecodeTexelRGBA8FromTmem(sampledTex, imageSrc, imageSrcOdd, imageSPlus1, imageTPlus1, imageWidth); + AddTexel(sampledTex, texel, (fractS) * (fractT)); + } + + 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 + { + // integer part of sample location + int imageS = s >> 7; + int imageT = t >> 7; + + // nearest neighbor sampling + WrapCoord(imageS, tm0.wrap_s, imageWidth); + WrapCoord(imageT, tm0.wrap_t, imageHeight); + + if (!(ti0.format == GX_TF_RGBA8 && texUnit.texImage1[subTexmap].image_type)) + TexDecoder_DecodeTexel(sample, imageSrc, imageS, imageT, imageWidth, ti0.format, tlutAddress, texTlut.tlut_format); + else + TexDecoder_DecodeTexelRGBA8FromTmem(sample, imageSrc, imageSrcOdd, imageS, imageT, imageWidth); + } +} + +} |
