- split out the span generation from most texture classes

Until now each subclass of FTexture had to implement the entire span generation itself, presumably so that a few classes can use simpler structures.
This does not work if a texture can have more than one pixel buffer as is needed for alpha textures.
Even though it means that some classes will allocate more data now, it's the only way to do it properly.
In addition this removes a significant amount of mostly redundant code from the texture classes.

- added alpha texture processing to all converted classes

As of now this is not active and not tested.
Note that as part of the conversion even those textures that were working as alphatextures will not look correct until the higher level code gets adjusted.
This commit is contained in:
Christoph Oelckers 2018-03-18 12:36:14 +01:00
commit 7e169eb76f
21 changed files with 484 additions and 1416 deletions

View file

@ -148,24 +148,21 @@ struct FPatchLookup
//
//==========================================================================
class FMultiPatchTexture : public FTexture
class FMultiPatchTexture : public FWorldTexture
{
public:
FMultiPatchTexture (const void *texdef, FPatchLookup *patchlookup, int maxpatchnum, bool strife, int deflump);
FMultiPatchTexture (FScanner &sc, int usetype);
~FMultiPatchTexture ();
const uint8_t *GetColumn (unsigned int column, const Span **spans_out);
const uint8_t *GetPixels ();
FTextureFormat GetFormat();
bool UseBasePalette() ;
void Unload ();
virtual void SetFrontSkyLayer ();
FTextureFormat GetFormat() override;
bool UseBasePalette() override;
virtual void SetFrontSkyLayer () override;
int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL);
int GetSourceLump() { return DefinitionLump; }
FTexture *GetRedirect(bool wantwarped);
FTexture *GetRawTexture();
int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL) override;
int GetSourceLump() override { return DefinitionLump; }
FTexture *GetRedirect(bool wantwarped) override;
FTexture *GetRawTexture() override;
void ResolvePatches();
protected:
@ -201,7 +198,7 @@ protected:
bool bRedirect:1;
bool bTranslucentPatches:1;
void MakeTexture ();
uint8_t *MakeTexture (FRenderStyle style);
private:
void CheckForHacks ();
@ -323,11 +320,6 @@ FMultiPatchTexture::~FMultiPatchTexture ()
delete[] Inits;
Inits = nullptr;
}
if (Spans != NULL)
{
FreeSpans (Spans);
Spans = NULL;
}
}
//==========================================================================
@ -345,80 +337,6 @@ void FMultiPatchTexture::SetFrontSkyLayer ()
bNoRemap0 = true;
}
//==========================================================================
//
// FMultiPatchTexture :: Unload
//
//==========================================================================
void FMultiPatchTexture::Unload ()
{
if (Pixels != NULL)
{
delete[] Pixels;
Pixels = NULL;
}
FTexture::Unload();
}
//==========================================================================
//
// FMultiPatchTexture :: GetPixels
//
//==========================================================================
const uint8_t *FMultiPatchTexture::GetPixels ()
{
if (bRedirect)
{
return Parts->Texture->GetPixels ();
}
if (Pixels == NULL)
{
MakeTexture ();
}
return Pixels;
}
//==========================================================================
//
// FMultiPatchTexture :: GetColumn
//
//==========================================================================
const uint8_t *FMultiPatchTexture::GetColumn (unsigned int column, const Span **spans_out)
{
if (bRedirect)
{
return Parts->Texture->GetColumn (column, spans_out);
}
if (Pixels == NULL)
{
MakeTexture ();
}
if ((unsigned)column >= (unsigned)Width)
{
if (WidthMask + 1 == Width)
{
column &= WidthMask;
}
else
{
column %= Width;
}
}
if (spans_out != NULL)
{
if (Spans == NULL)
{
Spans = CreateSpans (Pixels);
}
*spans_out = Spans[column];
}
return Pixels + column*Height;
}
//==========================================================================
//
// GetBlendMap
@ -427,7 +345,6 @@ const uint8_t *FMultiPatchTexture::GetColumn (unsigned int column, const Span **
uint8_t *GetBlendMap(PalEntry blend, uint8_t *blendwork)
{
switch (blend.a==0 ? int(blend) : -1)
{
case BLEND_ICEMAP:
@ -480,39 +397,54 @@ uint8_t *GetBlendMap(PalEntry blend, uint8_t *blendwork)
//
//==========================================================================
void FMultiPatchTexture::MakeTexture ()
uint8_t *FMultiPatchTexture::MakeTexture (FRenderStyle style)
{
// Add a little extra space at the end if the texture's height is not
// a power of 2, in case somebody accidentally makes it repeat vertically.
int numpix = Width * Height + (1 << HeightBits) - Height;
uint8_t blendwork[256];
bool hasTranslucent = false;
bool buildrgb = bComplex;
Pixels = new uint8_t[numpix];
auto Pixels = new uint8_t[numpix];
memset (Pixels, 0, numpix);
for (int i = 0; i < NumParts; ++i)
if (style.Flags & STYLEF_RedIsAlpha)
{
if (Parts[i].op != OP_COPY)
// The rules here are as follows:
// A texture uses its palette index as alpha only if it reports to use the base palette.
// In summary this means:
// If a texture is marked 'complex', it will use the red channel.
// If a texture uses non-base-palette patches, it will use the red channel for all pixels, even those coming from a base palette patch.
// If a texture only uses base-palette patches and no compositing effects it will use the palette index.
//
buildrgb = !UseBasePalette();
}
else
{
// For regular textures we can use paletted compositing if all patches are just being copied because they all can create a paletted buffer.
if (!buildrgb) for (int i = 0; i < NumParts; ++i)
{
hasTranslucent = true;
if (Parts[i].op != OP_COPY)
{
buildrgb = true;
}
}
}
if (!hasTranslucent)
{
if (!buildrgb)
{
for (int i = 0; i < NumParts; ++i)
{
if (Parts[i].Texture->bHasCanvas) continue; // cannot use camera textures as patch.
uint8_t *trans = Parts[i].Translation ? Parts[i].Translation->Remap : NULL;
uint8_t *trans = Parts[i].Translation? Parts[i].Translation->Remap : nullptr;
{
if (Parts[i].Blend != 0)
{
trans = GetBlendMap(Parts[i].Blend, blendwork);
}
Parts[i].Texture->CopyToBlock (Pixels, Width, Height,
Parts[i].OriginX, Parts[i].OriginY, Parts[i].Rotate, trans);
Parts[i].OriginX, Parts[i].OriginY, Parts[i].Rotate, trans, style);
}
}
}
@ -531,7 +463,7 @@ void FMultiPatchTexture::MakeTexture ()
{
if (*out == 0 && in[3] != 0)
{
*out = RGB256k.RGB[in[2]>>2][in[1]>>2][in[0]>>2];
*out = (style.Flags & STYLEF_RedIsAlpha)? in[2]*in[3] : RGB256k.RGB[in[2]>>2][in[1]>>2][in[0]>>2];
}
out += Height;
in += 4;
@ -539,6 +471,7 @@ void FMultiPatchTexture::MakeTexture ()
}
delete [] buffer;
}
return Pixels;
}
//===========================================================================
@ -755,14 +688,6 @@ void FMultiPatchTexture::CheckForHacks ()
break;
}
}
if (i == NumParts)
{
for (i = 0; i < NumParts; ++i)
{
Parts[i].Texture->HackHack(256);
}
}
}
}