Native mipmap support to FTexture

This commit is contained in:
Magnus Norddahl 2016-06-21 21:55:08 +02:00
commit c235de5c22
9 changed files with 171 additions and 196 deletions

View file

@ -3672,106 +3672,6 @@ void ApplySpecialColormapRGBACommand::Execute(DrawerThread *thread)
/////////////////////////////////////////////////////////////////////////////
#include <map>
class MipmappedTexture
{
public:
MipmappedTexture(FTexture *texture)
{
const uint32_t *base_texture = texture->GetPixelsBgra();
Width = texture->GetWidth();
Height = texture->GetHeight();
Levels = MAX(texture->WidthBits, texture->HeightBits);
// I bet there is a better way to calculate this..
int buffersize = 0;
for (int i = 0; i < Levels; i++)
{
int w = MAX(Width >> i, 2); // 2 instead of 1 because we texelGather in 2x2 blocks
int h = MAX(Height >> i, 2);
buffersize += w * h;
}
Pixels.resize(buffersize);
// Base level:
memcpy(Pixels.data(), base_texture, Width * Height * 4);
// Mipmap levels:
uint32_t *src = Pixels.data();
uint32_t *dest = src + Width * Height;
for (int i = 1; i < Levels; i++)
{
int srch = MAX(Height >> (i - 1), 2);
int w = MAX(Width >> i, 2);
int h = MAX(Height >> i, 2);
for (int x = 0; x < w; x++)
{
for (int y = 0; y < h; y++)
{
uint32_t src00 = src[y * 2 + x * 2 * srch];
uint32_t src01 = src[y * 2 + 1 + x * 2 * srch];
uint32_t src10 = src[y * 2 + (x * 2 + 1) * srch];
uint32_t src11 = src[y * 2 + 1 + (x * 2 + 1) * srch];
uint32_t alpha = (APART(src00) + APART(src01) + APART(src10) + APART(src11) + 2) / 4;
uint32_t red = (RPART(src00) + RPART(src01) + RPART(src10) + RPART(src11) + 2) / 4;
uint32_t green = (GPART(src00) + GPART(src01) + GPART(src10) + GPART(src11) + 2) / 4;
uint32_t blue = (BPART(src00) + BPART(src01) + BPART(src10) + BPART(src11) + 2) / 4;
dest[y + x * h] = (alpha << 24) | (red << 16) | (green << 8) | blue;
}
}
src = dest;
dest += w * h;
}
}
int Width = 0;
int Height = 0;
int Levels = 0;
std::vector<uint32_t> Pixels;
};
class TextureMipmapper
{
public:
static std::map<FTexture*, std::shared_ptr<MipmappedTexture>> &Textures()
{
static std::map<FTexture*, std::shared_ptr<MipmappedTexture>> textures;
return textures;
}
};
void R_SetMipmappedSpanSource(FTexture *tex)
{
if (r_swtruecolor)
{
if (r_mipmap)
{
auto &mipmap = TextureMipmapper::Textures()[tex];
if (!mipmap)
mipmap = std::make_shared<MipmappedTexture>(tex);
ds_source = (const BYTE*)mipmap->Pixels.data();
}
else
{
ds_source = (const BYTE*)tex->GetPixelsBgra();
}
}
else
{
ds_source = tex->GetPixels();
}
}
void R_ClearMipmapCache()
{
TextureMipmapper::Textures().clear();
}
void R_BeginDrawerCommands()
{
DrawerCommandQueue::Begin();