- use image sources, not textures to manage Build tiles.

The font manager and texture compositor need this - they cannot work off non-image-backed textures.
This commit is contained in:
Christoph Oelckers 2020-04-10 18:17:26 +02:00
parent a223535f86
commit 0179029ed1
5 changed files with 92 additions and 54 deletions

View file

@ -721,19 +721,16 @@ FTextureBuffer FTexture::CreateTexBuffer(int translation, int flags)
// //
//=========================================================================== //===========================================================================
bool FTexture::GetTranslucency() bool FTexture::DetermineTranslucency()
{ {
if (bTranslucent == -1) if (!bHasCanvas)
{ {
if (!bHasCanvas) // This will calculate all we need, so just discard the result.
{ CreateTexBuffer(0);
// This will calculate all we need, so just discard the result. }
CreateTexBuffer(0); else
} {
else bTranslucent = 0;
{
bTranslucent = 0;
}
} }
return !!bTranslucent; return !!bTranslucent;
} }

View file

@ -438,7 +438,12 @@ protected:
public: public:
FTextureBuffer CreateTexBuffer(int translation, int flags = 0); FTextureBuffer CreateTexBuffer(int translation, int flags = 0);
FTextureBuffer CreateTexBuffer(const PalEntry* translation, int flags = 0); FTextureBuffer CreateTexBuffer(const PalEntry* translation, int flags = 0);
bool GetTranslucency();
virtual bool DetermineTranslucency();
bool GetTranslucency()
{
return bTranslucent != -1 ? bTranslucent : DetermineTranslucency();
}
FMaterial* GetMaterial(int num) FMaterial* GetMaterial(int num)
{ {
return Material[num]; return Material[num];
@ -535,6 +540,7 @@ public:
FImageSource* GetImage() const override { return mImage; } FImageSource* GetImage() const override { return mImage; }
FBitmap GetBgraBitmap(const PalEntry* p, int* trans) override; FBitmap GetBgraBitmap(const PalEntry* p, int* trans) override;
bool DetermineTranslucency() override;
}; };

View file

@ -81,21 +81,19 @@ picanm_t tileConvertAnimFormat(int32_t const picanimraw, int* lo, int* to)
// //
//========================================================================== //==========================================================================
FBitmap FTileTexture::GetBgraBitmap(const PalEntry* remap, int* ptrans) int FTileTexture::CopyPixels(FBitmap* bmp, int conversion)
{ {
FBitmap bmp;
TArray<uint8_t> buffer; TArray<uint8_t> buffer;
bmp.Create(Width, Height); bmp->Create(Width, Height);
auto ppix = GetRawData(); auto ppix = GetRawData();
if (ppix) if (ppix)
{ {
if (remap == nullptr) remap = GPalette.BaseColors; bmp->CopyPixelData(0, 0, ppix, Width, Height, Height, 1, 0, GPalette.BaseColors);
bmp.CopyPixelData(0, 0, ppix, Width, Height, Height, 1, 0, remap);
} }
return bmp; return 0;
} }
TArray<uint8_t> FTileTexture::Get8BitPixels(bool alphatex) TArray<uint8_t> FTileTexture::CreatePalettedPixels(int conversion)
{ {
TArray<uint8_t> buffer(Width * Height, true); TArray<uint8_t> buffer(Width * Height, true);
auto p = GetRawData(); auto p = GetRawData();
@ -106,19 +104,19 @@ TArray<uint8_t> FTileTexture::Get8BitPixels(bool alphatex)
//========================================================================== //==========================================================================
// //
// Tile textures are owned by their containing file object. //
// //
//========================================================================== //==========================================================================
FArtTile* GetTileTexture(const char* name, const TArray<uint8_t>& backingstore, uint32_t offset, int width, int height) static FTexture* GetTileTexture(const char* name, const TArray<uint8_t>& backingstore, uint32_t offset, int width, int height)
{ {
auto tex = new FArtTile(backingstore, offset, width, height); auto tex = new FArtTile(backingstore, offset, width, height);
if (tex) if (tex)
{ {
tex->SetName(name); return new FImageTexture(tex, name);
} }
return tex; return nullptr;
} }
//========================================================================== //==========================================================================
@ -453,7 +451,7 @@ FTexture* BuildTiles::ValidateCustomTile(int tilenum, ReplacementType type)
// view tilting in the software renderer (this should just use a local buffer instead of relying on the texture manager.) // view tilting in the software renderer (this should just use a local buffer instead of relying on the texture manager.)
// Movie playback (like thumbnails this should bypass the texture manager entirely.) // Movie playback (like thumbnails this should bypass the texture manager entirely.)
// Blood's 'lens' effect (apparently MP only) - combination of a camera texture with a distortion map - should be made a shader effect to be applied to the camera texture. // Blood's 'lens' effect (apparently MP only) - combination of a camera texture with a distortion map - should be made a shader effect to be applied to the camera texture.
replacement = new FWritableTile; replacement = new FImageTexture(new FWritableTile);
} }
else if (type == ReplacementType::Restorable) else if (type == ReplacementType::Restorable)
{ {
@ -465,7 +463,7 @@ FTexture* BuildTiles::ValidateCustomTile(int tilenum, ReplacementType type)
// All of these effects should probably be redone without actual texture hacking... // All of these effects should probably be redone without actual texture hacking...
if (tile->GetTexelWidth() == 0 || tile->GetTexelHeight() == 0) return nullptr; // The base must have a size for this to work. if (tile->GetTexelWidth() == 0 || tile->GetTexelHeight() == 0) return nullptr; // The base must have a size for this to work.
// todo: invalidate hardware textures for tile. // todo: invalidate hardware textures for tile.
replacement = new FRestorableTile(tile); replacement = new FImageTexture(new FRestorableTile(tile->GetImage()));
} }
else if (type == ReplacementType::Canvas) else if (type == ReplacementType::Canvas)
{ {
@ -500,8 +498,9 @@ uint8_t* BuildTiles::tileCreate(int tilenum, int width, int height)
if (width <= 0 || height <= 0) return nullptr; if (width <= 0 || height <= 0) return nullptr;
auto tex = ValidateCustomTile(tilenum, ReplacementType::Writable); auto tex = ValidateCustomTile(tilenum, ReplacementType::Writable);
if (tex == nullptr) return nullptr; if (tex == nullptr) return nullptr;
auto wtex = static_cast<FWritableTile*>(tex); auto wtex = static_cast<FWritableTile*>(tex->GetImage());
if (!wtex->Resize(width, height)) return nullptr; if (!wtex->ResizeImage(width, height)) return nullptr;
tex->SetSize(width, height);
return wtex->GetRawData(); return wtex->GetRawData();
} }
@ -515,7 +514,7 @@ uint8_t* BuildTiles::tileCreate(int tilenum, int width, int height)
uint8_t* BuildTiles::tileMakeWritable(int num) uint8_t* BuildTiles::tileMakeWritable(int num)
{ {
auto tex = ValidateCustomTile(num, ReplacementType::Restorable); auto tex = ValidateCustomTile(num, ReplacementType::Restorable);
auto wtex = static_cast<FWritableTile*>(tex); auto wtex = static_cast<FWritableTile*>(tex->GetImage());
return wtex ? wtex->GetRawData() : nullptr; return wtex ? wtex->GetRawData() : nullptr;
} }
@ -528,13 +527,14 @@ uint8_t* BuildTiles::tileMakeWritable(int num)
int32_t tileGetCRC32(int tileNum) int32_t tileGetCRC32(int tileNum)
{ {
if ((unsigned)tileNum >= (unsigned)MAXTILES) return 0; if ((unsigned)tileNum >= (unsigned)MAXTILES) return 0;
auto tile = tileGetTexture(tileNum); auto tile = dynamic_cast<FArtTile*>(TileFiles.tiledata[tileNum].texture->GetImage()); // only consider original ART tiles.
if (!tile || TileFiles.tiledata[tileNum].replacement != ReplacementType::Art) return 0; // only consider original ART tiles. if (!tile) return 0;
auto pixels = tile->Get8BitPixels(false); auto pixels = tile->GetRawData();
if (!pixels.Size()) return 0; if (!pixels) return 0;
int size = tile->GetTexelWidth() * tile->GetTexelHeight();
auto size = tile->GetWidth() * tile->GetHeight();
if (size == 0) return 0; if (size == 0) return 0;
return crc32(0, (const Bytef*)pixels.Data(), size); return crc32(0, (const Bytef*)pixels, size);
} }
@ -612,7 +612,7 @@ void tileCopy(int tile, int source, int pal, int xoffset, int yoffset, int flags
pixel = remap[pixel]; pixel = remap[pixel];
} }
} }
tex = new FLooseTile(buffer, tex->GetTexelWidth(), tex->GetTexelHeight()); tex = new FImageTexture(new FLooseTile(buffer, tex->GetTexelWidth(), tex->GetTexelHeight()));
picanm = &TileFiles.tiledata[tile].picanm; picanm = &TileFiles.tiledata[tile].picanm;
TileFiles.AddTile(tile, tex); TileFiles.AddTile(tile, tex);
} }
@ -709,7 +709,7 @@ void tileSetDummy(int tile, int width, int height)
} }
else if (width > 0 && height > 0) else if (width > 0 && height > 0)
{ {
auto dtile = new FDummyTile(width, height); auto dtile = new FImageTexture(new FDummyTile(width, height));
TileFiles.AddTile(tile, dtile); TileFiles.AddTile(tile, dtile);
} }
} }
@ -732,6 +732,15 @@ int BuildTiles::findUnusedTile(void)
return -1; return -1;
} }
//==========================================================================
//
// fixme: This *really* needs to be done by rotating the texture coordinates,
// not by creating an entirely new texture.
// Unfortunately it's in all the wrong place in the rendering code so it
// has to wait for later.
//
//==========================================================================
int BuildTiles::tileCreateRotated(int tileNum) int BuildTiles::tileCreateRotated(int tileNum)
{ {
if ((unsigned)tileNum >= MAXTILES) return tileNum; if ((unsigned)tileNum >= MAXTILES) return tileNum;
@ -754,7 +763,7 @@ int BuildTiles::tileCreateRotated(int tileNum)
*(dst + y * width + xofs) = *(src + y + yofs); *(dst + y * width + xofs) = *(src + y + yofs);
} }
auto dtex = new FLooseTile(dbuffer, tex->GetTexelHeight(), tex->GetTexelWidth()); auto dtex = new FImageTexture(new FLooseTile(dbuffer, tex->GetTexelHeight(), tex->GetTexelWidth()));
int index = findUnusedTile(); int index = findUnusedTile();
bool mapart = TileFiles.tiledata[tileNum].texture != TileFiles.tiledata[tileNum].backup; bool mapart = TileFiles.tiledata[tileNum].texture != TileFiles.tiledata[tileNum].backup;
TileFiles.AddTile(index, dtex, mapart); TileFiles.AddTile(index, dtex, mapart);

View file

@ -1,6 +1,7 @@
#pragma once #pragma once
#include "textures.h" #include "textures.h"
#include "image.h"
#include "i_time.h" #include "i_time.h"
#include "compat.h" #include "compat.h"
@ -67,16 +68,17 @@ struct HightileReplacement
uint16_t palnum, flags; uint16_t palnum, flags;
}; };
class FTileTexture : public FTexture class FTileTexture : public FImageSource
{ {
public: public:
FTileTexture() FTileTexture()
{} {
bUseGamePalette = true;
bTranslucent = false;
}
virtual uint8_t* GetRawData() = 0; virtual uint8_t* GetRawData() = 0;
void SetName(const char* name) { Name = name; } virtual TArray<uint8_t> CreatePalettedPixels(int conversion);
TArray<uint8_t> Get8BitPixels(bool alphatex) override; virtual int CopyPixels(FBitmap* bmp, int conversion); // This will always ignore 'luminance'.
FBitmap GetBgraBitmap(const PalEntry* remap, int* trans = nullptr) override;
//bool GetTranslucency() override { return false; }
}; };
//========================================================================== //==========================================================================
@ -93,7 +95,8 @@ public:
FArtTile(const TArray<uint8_t>& backingstore, uint32_t offset, int width, int height) FArtTile(const TArray<uint8_t>& backingstore, uint32_t offset, int width, int height)
: RawPixels(backingstore), Offset(offset) : RawPixels(backingstore), Offset(offset)
{ {
SetSize(width, height); Width = width;
Height = height;
} }
uint8_t* GetRawData() override final uint8_t* GetRawData() override final
{ {
@ -114,7 +117,8 @@ public:
FLooseTile(TArray<uint8_t>& store, int width, int height) FLooseTile(TArray<uint8_t>& store, int width, int height)
{ {
RawPixels = std::move(store); RawPixels = std::move(store);
SetSize(width, height); Width = width;
Height = height;
} }
uint8_t* GetRawData() override uint8_t* GetRawData() override
@ -135,7 +139,8 @@ class FDummyTile : public FTileTexture
public: public:
FDummyTile(int width, int height) FDummyTile(int width, int height)
{ {
SetSize(width, height); Width = width;
Height = height;
} }
uint8_t* GetRawData() override uint8_t* GetRawData() override
@ -166,7 +171,7 @@ public:
return buffer.Data(); return buffer.Data();
} }
bool Resize(int w, int h) bool ResizeImage(int w, int h)
{ {
if (w <= 0 || h <= 0) if (w <= 0 || h <= 0)
{ {
@ -175,7 +180,8 @@ public:
} }
else else
{ {
SetSize(w, h); Width = w;
Height = h;
buffer.Resize(w * h); buffer.Resize(w * h);
return true; return true;
} }
@ -191,20 +197,21 @@ public:
class FRestorableTile : public FWritableTile class FRestorableTile : public FWritableTile
{ {
FTexture* Base; FImageSource* Base;
public: public:
FRestorableTile(FTexture* base) FRestorableTile(FImageSource* base)
{ {
Base = base; Base = base;
CopySize(base);
Resize(GetTexelWidth(), GetTexelHeight()); CopySize(*base);
ResizeImage(Width, Height);
Reload(); Reload();
} }
void Reload() void Reload()
{ {
buffer = std::move(Base->Get8BitPixels(false)); buffer = std::move(Base->GetPalettedPixels(0));
} }
}; };
@ -274,7 +281,7 @@ struct BuildTiles
BuildTiles() BuildTiles()
{ {
Placeholder = new FDummyTile(0, 0); Placeholder = new FImageTexture(new FDummyTile(0, 0));
for (auto& tile : tiledata) for (auto& tile : tiledata)
{ {
tile.backup = tile.texture = Placeholder; tile.backup = tile.texture = Placeholder;

View file

@ -88,6 +88,25 @@ TArray<uint8_t> FImageTexture::Get8BitPixels(bool alpha)
return mImage->GetPalettedPixels(alpha ? alpha : bNoRemap0 ? FImageSource::noremap0 : FImageSource::normal); return mImage->GetPalettedPixels(alpha ? alpha : bNoRemap0 ? FImageSource::noremap0 : FImageSource::normal);
} }
//===========================================================================
//
// use the already known state of the underlying image to save time.
//
//===========================================================================
bool FImageTexture::DetermineTranslucency()
{
if (mImage->bTranslucent != -1)
{
bTranslucent = mImage->bTranslucent;
return !!bTranslucent;
}
else
{
return FTexture::DetermineTranslucency();
}
}
FTexture* CreateImageTexture(FImageSource* img, const char* name) noexcept FTexture* CreateImageTexture(FImageSource* img, const char* name) noexcept
{ {