1
0
forked from 0ad/0ad

Uses MIPs for terrain textures previews following e4455a8e8f.

Comments By: Stan
Differential Revision: https://code.wildfiregames.com/D4447
This was SVN commit r26239.
This commit is contained in:
Vladislav Belov 2022-01-24 07:00:55 +00:00
parent c114bab396
commit 4ce609bb1f
3 changed files with 50 additions and 19 deletions

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2021 Wildfire Games.
/* Copyright (C) 2022 Wildfire Games.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@ -20,24 +20,19 @@
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* support routines for 2d texture access/writing.
*/
#include "precompiled.h"
#include "tex.h"
#include <math.h>
#include <stdlib.h>
#include <algorithm>
#include "lib/timer.h"
#include "lib/bits.h"
#include "lib/allocators/shared_ptr.h"
#include "lib/bits.h"
#include "lib/sysdep/cpu.h"
#include "lib/tex/tex_codec.h"
#include "lib/timer.h"
#include "tex_codec.h"
#include <algorithm>
#include <cmath>
#include <cstdlib>
static const StatusDefinition texStatusDefinitions[] = {
{ ERR::TEX_FMT_INVALID, L"Invalid/unsupported texture format" },
@ -633,10 +628,35 @@ u8* Tex::get_data()
u8* p = m_Data.get();
if(!p)
return 0;
return nullptr;
return p + m_Ofs;
}
u8* Tex::GetMipLevelData(const u32 level)
{
// (can't use normal CHECK_TEX due to u8* return value)
WARN_IF_ERR(validate());
u8* levelData = m_Data.get();
if (!levelData)
return nullptr;
levelData += m_Ofs;
const size_t dataPadding = (m_Flags & TEX_DXT) != 0 ? 4 : 1;
size_t levelWidth = m_Width, levelHeight = m_Height;
for (u32 currentLevel = 0; levelWidth > 1 || levelHeight > 1; ++currentLevel)
{
if (currentLevel == level)
return levelData;
const size_t levelDataSize = round_up(levelWidth, dataPadding) * round_up(levelHeight, dataPadding) * m_Bpp / 8;
levelData += levelDataSize;
levelWidth = std::max<u32>(levelWidth / 2, 1);
levelHeight = std::max<u32>(levelHeight / 2, 1);
}
return nullptr;
}
// returns color of 1x1 mipmap level
u32 Tex::get_average_color() const
{

View File

@ -332,6 +332,14 @@ struct Tex
**/
u8* get_data();
/**
* return a pointer to the mip level image data (pixels).
*
* @param level which level's data should be returned.
* @return pointer to the data.
**/
u8* GetMipLevelData(const u32 level);
/**
* return the ARGB value of the 1x1 mipmap level of the texture.
*

View File

@ -86,7 +86,7 @@ sTerrainTexturePreview GetPreview(CTerrainTextureEntry* tex, size_t width, size_
// Check that we can fit the texture into the preview size before any transform.
texture.m_Width >= width && texture.m_Height >= height &&
// Transform to a single format that we can process.
texture.transform_to((texture.m_Flags) & ~(TEX_DXT | TEX_MIPMAPS | TEX_GREY | TEX_BGR)) == INFO::OK &&
texture.transform_to((texture.m_Flags | TEX_MIPMAPS) & ~(TEX_DXT | TEX_GREY | TEX_BGR)) == INFO::OK &&
(texture.m_Bpp == 24 || texture.m_Bpp == 32);
if (canUsePreview)
{
@ -95,14 +95,17 @@ sTerrainTexturePreview GetPreview(CTerrainTextureEntry* tex, size_t width, size_
++level;
// Extract the middle section (as a representative preview),
// and copy into buffer.
u8* data = texture.get_data();
const size_t dataShiftX = ((texture.m_Width - width) / 2) >> level;
const size_t dataShiftY = ((texture.m_Height - height) / 2) >> level;
u8* data = texture.GetMipLevelData(level);
ENSURE(data);
const size_t levelWidth = texture.m_Width >> level;
const size_t levelHeight = texture.m_Height >> level;
const size_t dataShiftX = (levelWidth - width) / 2;
const size_t dataShiftY = (levelHeight - height) / 2;
for (size_t y = 0; y < height; ++y)
for (size_t x = 0; x < width; ++x)
{
const size_t bufferOffset = (y * width + x) * previewBPP;
const size_t dataOffset = (((y << level) + dataShiftY) * texture.m_Width + (x << level) + dataShiftX) * texture.m_Bpp / 8;
const size_t dataOffset = ((y + dataShiftY) * levelWidth + x + dataShiftX) * texture.m_Bpp / 8;
buffer[bufferOffset + 0] = data[dataOffset + 0];
buffer[bufferOffset + 1] = data[dataOffset + 1];
buffer[bufferOffset + 2] = data[dataOffset + 2];