- 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
parent 102d2647d3
commit 7e169eb76f
21 changed files with 497 additions and 1429 deletions

View file

@ -1110,6 +1110,7 @@ set (PCH_SOURCES
textures/tgatexture.cpp textures/tgatexture.cpp
textures/warptexture.cpp textures/warptexture.cpp
textures/skyboxtexture.cpp textures/skyboxtexture.cpp
textures/worldtexture.cpp
xlat/parse_xlat.cpp xlat/parse_xlat.cpp
fragglescript/t_func.cpp fragglescript/t_func.cpp
fragglescript/t_load.cpp fragglescript/t_load.cpp

View file

@ -523,24 +523,11 @@ FBrightmapTexture::FBrightmapTexture (FTexture *source)
SourceLump = -1; SourceLump = -1;
} }
FBrightmapTexture::~FBrightmapTexture () uint8_t *FBrightmapTexture::MakeTexture(FRenderStyle style)
{
}
const uint8_t *FBrightmapTexture::GetColumn (unsigned int column, const Span **spans_out)
{
// not needed
return NULL;
}
const uint8_t *FBrightmapTexture::GetPixels ()
{
// not needed
return NULL;
}
void FBrightmapTexture::Unload ()
{ {
// This function is only necessary to satisfy the parent class's interface.
// This will never be called.
return nullptr;
} }
int FBrightmapTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf) int FBrightmapTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf)

View file

@ -4,23 +4,17 @@
#include "r_defs.h" #include "r_defs.h"
#include "textures/textures.h" #include "textures/textures.h"
class FBrightmapTexture : public FTexture class FBrightmapTexture : public FWorldTexture
{ {
public: public:
FBrightmapTexture (FTexture *source); FBrightmapTexture (FTexture *source);
~FBrightmapTexture ();
const uint8_t *GetColumn (unsigned int column, const Span **spans_out); uint8_t *MakeTexture(FRenderStyle style) override;
const uint8_t *GetPixels (); int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf) override;
void Unload (); bool UseBasePalette() override { return false; }
int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf);
bool UseBasePalette() { return false; }
protected: protected:
FTexture *SourcePic; FTexture *SourcePic;
//uint8_t *Pixels;
//Span **Spans;
}; };

View file

@ -53,23 +53,17 @@
// //
//=========================================================================== //===========================================================================
class FVoxelTexture : public FTexture class FVoxelTexture : public FWorldTexture
{ {
public: public:
FVoxelTexture(FVoxel *voxel); FVoxelTexture(FVoxel *voxel);
~FVoxelTexture();
const uint8_t *GetColumn (unsigned int column, const Span **spans_out);
const uint8_t *GetPixels ();
void Unload ();
int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf); int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf) override;
bool UseBasePalette() { return false; } bool UseBasePalette() override { return false; }
uint8_t *MakeTexture(FRenderStyle style) override;
protected: protected:
FVoxel *SourceVox; FVoxel *SourceVox;
uint8_t *Pixels;
}; };
//=========================================================================== //===========================================================================
@ -86,7 +80,6 @@ FVoxelTexture::FVoxelTexture(FVoxel *vox)
WidthBits = 4; WidthBits = 4;
HeightBits = 4; HeightBits = 4;
WidthMask = 15; WidthMask = 15;
Pixels = NULL;
gl_info.bNoFilter = true; gl_info.bNoFilter = true;
gl_info.bNoCompress = true; gl_info.bNoCompress = true;
} }
@ -97,54 +90,32 @@ FVoxelTexture::FVoxelTexture(FVoxel *vox)
// //
//=========================================================================== //===========================================================================
FVoxelTexture::~FVoxelTexture() uint8_t *FVoxelTexture::MakeTexture (FRenderStyle style)
{
}
const uint8_t *FVoxelTexture::GetColumn (unsigned int column, const Span **spans_out)
{
// not needed
return NULL;
}
const uint8_t *FVoxelTexture::GetPixels ()
{ {
// GetPixels gets called when a translated palette is used so we still need to implement it here. // GetPixels gets called when a translated palette is used so we still need to implement it here.
if (Pixels == NULL) auto Pixels = new uint8_t[256];
uint8_t *pp = SourceVox->Palette;
if(pp != NULL)
{ {
Pixels = new uint8_t[256]; for(int i=0;i<256;i++, pp+=3)
uint8_t *pp = SourceVox->Palette;
if(pp != NULL)
{ {
for(int i=0;i<256;i++, pp+=3) PalEntry pe;
{ pe.r = (pp[0] << 2) | (pp[0] >> 4);
PalEntry pe; pe.g = (pp[1] << 2) | (pp[1] >> 4);
pe.r = (pp[0] << 2) | (pp[0] >> 4); pe.b = (pp[2] << 2) | (pp[2] >> 4);
pe.g = (pp[1] << 2) | (pp[1] >> 4); // Alphatexture handling is just for completeness, but rather unlikely to be used ever.
pe.b = (pp[2] << 2) | (pp[2] >> 4); Pixels[i] = (style.Flags & STYLEF_RedIsAlpha)? pe.r : ColorMatcher.Pick(pe);
Pixels[i] = ColorMatcher.Pick(pe);
}
} }
else
{
for(int i=0;i<256;i++, pp+=3)
{
Pixels[i] = (uint8_t)i;
}
}
} }
return Pixels; else
}
void FVoxelTexture::Unload ()
{
if (Pixels != NULL)
{ {
delete[] Pixels; for(int i=0;i<256;i++, pp+=3)
Pixels = NULL; {
} Pixels[i] = (uint8_t)i;
}
}
return Pixels;
} }
//=========================================================================== //===========================================================================

View file

@ -330,7 +330,6 @@ namespace swrenderer
if (rw_pic->UseType == FTexture::TEX_Null) if (rw_pic->UseType == FTexture::TEX_Null)
return; return;
rw_pic->GetHeight(); // To ensure that rw_pic->HeightBits has been set
int fracbits = 32 - rw_pic->HeightBits; int fracbits = 32 - rw_pic->HeightBits;
if (fracbits == 32) if (fracbits == 32)
{ // Hack for one pixel tall textures { // Hack for one pixel tall textures

View file

@ -38,6 +38,7 @@
#include "doomtype.h" #include "doomtype.h"
#include "files.h" #include "files.h"
#include "w_wad.h" #include "w_wad.h"
#include "v_palette.h"
#include "textures/textures.h" #include "textures/textures.h"
//========================================================================== //==========================================================================
@ -46,21 +47,12 @@
// //
//========================================================================== //==========================================================================
class FAutomapTexture : public FTexture class FAutomapTexture : public FWorldTexture
{ {
public: public:
FAutomapTexture(int lumpnum);
~FAutomapTexture (); ~FAutomapTexture ();
uint8_t *MakeTexture (FRenderStyle style);
const uint8_t *GetColumn (unsigned int column, const Span **spans_out);
const uint8_t *GetPixels ();
void Unload ();
void MakeTexture ();
FAutomapTexture (int lumpnum);
private:
uint8_t *Pixels;
Span DummySpan[2];
}; };
@ -86,16 +78,11 @@ FTexture *AutomapTexture_TryCreate(FileReader &data, int lumpnum)
//========================================================================== //==========================================================================
FAutomapTexture::FAutomapTexture (int lumpnum) FAutomapTexture::FAutomapTexture (int lumpnum)
: FTexture(NULL, lumpnum), Pixels(NULL) : FWorldTexture(NULL, lumpnum)
{ {
Width = 320; Width = 320;
Height = uint16_t(Wads.LumpLength(lumpnum) / 320); Height = uint16_t(Wads.LumpLength(lumpnum) / 320);
CalcBitSize (); CalcBitSize ();
DummySpan[0].TopOffset = 0;
DummySpan[0].Length = Height;
DummySpan[1].TopOffset = 0;
DummySpan[1].Length = 0;
} }
//========================================================================== //==========================================================================
@ -104,84 +91,22 @@ FAutomapTexture::FAutomapTexture (int lumpnum)
// //
//========================================================================== //==========================================================================
FAutomapTexture::~FAutomapTexture () uint8_t *FAutomapTexture::MakeTexture (FRenderStyle style)
{
Unload ();
}
//==========================================================================
//
//
//
//==========================================================================
void FAutomapTexture::Unload ()
{
if (Pixels != NULL)
{
delete[] Pixels;
Pixels = NULL;
}
FTexture::Unload();
}
//==========================================================================
//
//
//
//==========================================================================
void FAutomapTexture::MakeTexture ()
{ {
int x, y; int x, y;
FMemLump data = Wads.ReadLump (SourceLump); FMemLump data = Wads.ReadLump (SourceLump);
const uint8_t *indata = (const uint8_t *)data.GetMem(); const uint8_t *indata = (const uint8_t *)data.GetMem();
Pixels = new uint8_t[Width * Height]; auto Pixels = new uint8_t[Width * Height];
for (x = 0; x < Width; ++x) for (x = 0; x < Width; ++x)
{ {
for (y = 0; y < Height; ++y) for (y = 0; y < Height; ++y)
{ {
Pixels[x*Height+y] = indata[x+320*y]; auto p = indata[x + 320 * y];
Pixels[x*Height + y] = (style.Flags & STYLEF_RedIsAlpha) ? p : GPalette.Remap[p];
} }
} }
}
//==========================================================================
//
//
//
//==========================================================================
const uint8_t *FAutomapTexture::GetPixels ()
{
if (Pixels == NULL)
{
MakeTexture ();
}
return Pixels; return Pixels;
} }
//==========================================================================
//
//
//
//==========================================================================
const uint8_t *FAutomapTexture::GetColumn (unsigned int column, const Span **spans_out)
{
if (Pixels == NULL)
{
MakeTexture ();
}
if ((unsigned)column >= (unsigned)Width)
{
column %= Width;
}
if (spans_out != NULL)
{
*spans_out = DummySpan;
}
return Pixels + column*Height;
}

View file

@ -193,13 +193,14 @@ typedef void (*CopyFunc)(uint8_t *pout, const uint8_t *pin, int count, int step,
iCopyColors<cRGBA, cBGRA, op>, \ iCopyColors<cRGBA, cBGRA, op>, \
iCopyColors<cIA, cBGRA, op>, \ iCopyColors<cIA, cBGRA, op>, \
iCopyColors<cCMYK, cBGRA, op>, \ iCopyColors<cCMYK, cBGRA, op>, \
iCopyColors<cYCbCr, cBGRA, op>, \
iCopyColors<cBGR, cBGRA, op>, \ iCopyColors<cBGR, cBGRA, op>, \
iCopyColors<cBGRA, cBGRA, op>, \ iCopyColors<cBGRA, cBGRA, op>, \
iCopyColors<cI16, cBGRA, op>, \ iCopyColors<cI16, cBGRA, op>, \
iCopyColors<cRGB555, cBGRA, op>, \ iCopyColors<cRGB555, cBGRA, op>, \
iCopyColors<cPalEntry, cBGRA, op> \ iCopyColors<cPalEntry, cBGRA, op> \
} }
static const CopyFunc copyfuncs[][10]={ static const CopyFunc copyfuncs[][11]={
COPY_FUNCS(bCopy), COPY_FUNCS(bCopy),
COPY_FUNCS(bBlend), COPY_FUNCS(bBlend),
COPY_FUNCS(bAdd), COPY_FUNCS(bAdd),

View file

@ -235,6 +235,15 @@ struct cCMYK
static __forceinline int Gray(const unsigned char * p) { return (R(p)*77 + G(p)*143 + B(p)*36)>>8; } static __forceinline int Gray(const unsigned char * p) { return (R(p)*77 + G(p)*143 + B(p)*36)>>8; }
}; };
struct cYCbCr
{
static __forceinline unsigned char R(const unsigned char * p) { return clamp((int)(p[0] + 1.40200 * (int(p[2]) - 0x80)), 0, 255); }
static __forceinline unsigned char G(const unsigned char * p) { return clamp((int)(p[0] - 0.34414 * (int(p[1] - 0x80)) - 0.71414 * (int(p[2]) - 0x80)), 0, 255); }
static __forceinline unsigned char B(const unsigned char * p) { return clamp((int)(p[0] + 1.77200 * (int(p[1]) - 0x80)), 0, 255); }
static __forceinline unsigned char A(const unsigned char * p, uint8_t x, uint8_t y, uint8_t z) { return 255; }
static __forceinline int Gray(const unsigned char * p) { return (R(p) * 77 + G(p) * 143 + B(p) * 36) >> 8; }
};
struct cBGR struct cBGR
{ {
static __forceinline unsigned char R(const unsigned char * p) { return p[2]; } static __forceinline unsigned char R(const unsigned char * p) { return p[2]; }
@ -310,6 +319,7 @@ enum ColorType
CF_RGBA, CF_RGBA,
CF_IA, CF_IA,
CF_CMYK, CF_CMYK,
CF_YCbCr,
CF_BGR, CF_BGR,
CF_BGRA, CF_BGRA,
CF_I16, CF_I16,

View file

@ -153,22 +153,21 @@ struct DDSFileHeader
// //
//========================================================================== //==========================================================================
class FDDSTexture : public FTexture class FDDSTexture : public FWorldTexture
{ {
enum
{
PIX_Palette = 0,
PIX_Alphatex = 1,
PIX_ARGB = 2
};
public: public:
FDDSTexture (FileReader &lump, int lumpnum, void *surfdesc); FDDSTexture (FileReader &lump, int lumpnum, void *surfdesc);
~FDDSTexture ();
const uint8_t *GetColumn (unsigned int column, const Span **spans_out); FTextureFormat GetFormat () override;
const uint8_t *GetPixels (); uint8_t *MakeTexture(FRenderStyle style) override;
void Unload ();
FTextureFormat GetFormat ();
protected: protected:
uint8_t *Pixels;
Span **Spans;
uint32_t Format; uint32_t Format;
uint32_t RMask, GMask, BMask, AMask; uint32_t RMask, GMask, BMask, AMask;
@ -180,11 +179,10 @@ protected:
static void CalcBitShift (uint32_t mask, uint8_t *lshift, uint8_t *rshift); static void CalcBitShift (uint32_t mask, uint8_t *lshift, uint8_t *rshift);
void MakeTexture (); void ReadRGB (FileReader &lump, uint8_t *buffer, int pixelmode);
void ReadRGB (FileReader &lump, uint8_t *tcbuf = NULL); void DecompressDXT1 (FileReader &lump, uint8_t *buffer, int pixelmode);
void DecompressDXT1 (FileReader &lump, uint8_t *tcbuf = NULL); void DecompressDXT3 (FileReader &lump, bool premultiplied, uint8_t *buffer, int pixelmode);
void DecompressDXT3 (FileReader &lump, bool premultiplied, uint8_t *tcbuf = NULL); void DecompressDXT5 (FileReader &lump, bool premultiplied, uint8_t *buffer, int pixelmode);
void DecompressDXT5 (FileReader &lump, bool premultiplied, uint8_t *tcbuf = NULL);
int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL); int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL);
bool UseBasePalette(); bool UseBasePalette();
@ -287,7 +285,7 @@ FTexture *DDSTexture_TryCreate (FileReader &data, int lumpnum)
//========================================================================== //==========================================================================
FDDSTexture::FDDSTexture (FileReader &lump, int lumpnum, void *vsurfdesc) FDDSTexture::FDDSTexture (FileReader &lump, int lumpnum, void *vsurfdesc)
: FTexture(NULL, lumpnum), Pixels(0), Spans(0) : FWorldTexture(NULL, lumpnum)
{ {
DDSURFACEDESC2 *surf = (DDSURFACEDESC2 *)vsurfdesc; DDSURFACEDESC2 *surf = (DDSURFACEDESC2 *)vsurfdesc;
@ -381,38 +379,6 @@ void FDDSTexture::CalcBitShift (uint32_t mask, uint8_t *lshiftp, uint8_t *rshift
// //
//========================================================================== //==========================================================================
FDDSTexture::~FDDSTexture ()
{
Unload ();
if (Spans != NULL)
{
FreeSpans (Spans);
Spans = NULL;
}
}
//==========================================================================
//
//
//
//==========================================================================
void FDDSTexture::Unload ()
{
if (Pixels != NULL)
{
delete[] Pixels;
Pixels = NULL;
}
FTexture::Unload();
}
//==========================================================================
//
//
//
//==========================================================================
FTextureFormat FDDSTexture::GetFormat() FTextureFormat FDDSTexture::GetFormat()
{ {
#if 0 #if 0
@ -437,88 +403,41 @@ FTextureFormat FDDSTexture::GetFormat()
// //
//========================================================================== //==========================================================================
const uint8_t *FDDSTexture::GetColumn (unsigned int column, const Span **spans_out) uint8_t *FDDSTexture::MakeTexture (FRenderStyle style)
{ {
if (Pixels == NULL) auto lump = Wads.OpenLumpReader (SourceLump);
{
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;
}
//========================================================================== auto Pixels = new uint8_t[Width*Height];
//
//
//
//==========================================================================
const uint8_t *FDDSTexture::GetPixels () lump.Seek (sizeof(DDSURFACEDESC2) + 4, FileReader::SeekSet);
{
if (Pixels == NULL) int pmode = (style.Flags & STYLEF_RedIsAlpha) ? PIX_Alphatex : PIX_Palette;
if (Format >= 1 && Format <= 4) // RGB: Format is # of bytes per pixel
{ {
MakeTexture (); ReadRGB (lump, Pixels, pmode);
}
else if (Format == ID_DXT1)
{
DecompressDXT1 (lump, Pixels, pmode);
}
else if (Format == ID_DXT3 || Format == ID_DXT2)
{
DecompressDXT3 (lump, Format == ID_DXT2, Pixels, pmode);
}
else if (Format == ID_DXT5 || Format == ID_DXT4)
{
DecompressDXT5 (lump, Format == ID_DXT4, Pixels, pmode);
} }
return Pixels; return Pixels;
} }
//========================================================================== //==========================================================================
// //
// // Note that pixel size == 8 is column-major, but 32 is row-major!
// //
//========================================================================== //==========================================================================
void FDDSTexture::MakeTexture () void FDDSTexture::ReadRGB (FileReader &lump, uint8_t *buffer, int pixelmode)
{
auto lump = Wads.OpenLumpReader (SourceLump);
Pixels = new uint8_t[Width*Height];
lump.Seek (sizeof(DDSURFACEDESC2) + 4, FileReader::SeekSet);
if (Format >= 1 && Format <= 4) // RGB: Format is # of bytes per pixel
{
ReadRGB (lump);
}
else if (Format == ID_DXT1)
{
DecompressDXT1 (lump);
}
else if (Format == ID_DXT3 || Format == ID_DXT2)
{
DecompressDXT3 (lump, Format == ID_DXT2);
}
else if (Format == ID_DXT5 || Format == ID_DXT4)
{
DecompressDXT5 (lump, Format == ID_DXT4);
}
}
//==========================================================================
//
//
//
//==========================================================================
void FDDSTexture::ReadRGB (FileReader &lump, uint8_t *tcbuf)
{ {
uint32_t x, y; uint32_t x, y;
uint32_t amask = AMask == 0 ? 0 : 0x80000000 >> AShiftL; uint32_t amask = AMask == 0 ? 0 : 0x80000000 >> AShiftL;
@ -527,7 +446,7 @@ void FDDSTexture::ReadRGB (FileReader &lump, uint8_t *tcbuf)
for (y = Height; y > 0; --y) for (y = Height; y > 0; --y)
{ {
uint8_t *buffp = linebuff; uint8_t *buffp = linebuff;
uint8_t *pixelp = tcbuf? tcbuf + 4*y*Height : Pixels + y; uint8_t *pixelp = pixelmode == PIX_ARGB? buffer + 4*y*Height : buffer + y;
lump.Read (linebuff, Pitch); lump.Read (linebuff, Pitch);
for (x = Width; x > 0; --x) for (x = Width; x > 0; --x)
{ {
@ -548,14 +467,21 @@ void FDDSTexture::ReadRGB (FileReader &lump, uint8_t *tcbuf)
{ {
c = *buffp++; c = *buffp++;
} }
if (!tcbuf) if (pixelmode != PIX_ARGB)
{ {
if (amask == 0 || (c & amask)) if (amask == 0 || (c & amask))
{ {
uint32_t r = (c & RMask) << RShiftL; r |= r >> RShiftR; uint32_t r = (c & RMask) << RShiftL; r |= r >> RShiftR;
uint32_t g = (c & GMask) << GShiftL; g |= g >> GShiftR; if (pixelmode == PIX_Palette)
uint32_t b = (c & BMask) << BShiftL; b |= b >> BShiftR; {
*pixelp = RGB256k.RGB[r >> 26][g >> 26][b >> 26]; uint32_t g = (c & GMask) << GShiftL; g |= g >> GShiftR;
uint32_t b = (c & BMask) << BShiftL; b |= b >> BShiftR;
*pixelp = RGB256k.RGB[r >> 26][g >> 26][b >> 26];
}
else
{
*pixelp = uint8_t(r >> 24);
}
} }
else else
{ {
@ -587,13 +513,13 @@ void FDDSTexture::ReadRGB (FileReader &lump, uint8_t *tcbuf)
// //
//========================================================================== //==========================================================================
void FDDSTexture::DecompressDXT1 (FileReader &lump, uint8_t *tcbuf) void FDDSTexture::DecompressDXT1 (FileReader &lump, uint8_t *buffer, int pixelmode)
{ {
const long blocklinelen = ((Width + 3) >> 2) << 3; const long blocklinelen = ((Width + 3) >> 2) << 3;
uint8_t *blockbuff = new uint8_t[blocklinelen]; uint8_t *blockbuff = new uint8_t[blocklinelen];
uint8_t *block; uint8_t *block;
PalEntry color[4]; PalEntry color[4];
uint8_t palcol[4]; uint8_t palcol[4] = { 0,0,0,0 }; // shut up compiler warnings.
int ox, oy, x, y, i; int ox, oy, x, y, i;
color[0].a = 255; color[0].a = 255;
@ -639,9 +565,12 @@ void FDDSTexture::DecompressDXT1 (FileReader &lump, uint8_t *tcbuf)
bMasked = true; bMasked = true;
} }
// Pick colors from the palette for each of the four colors. // Pick colors from the palette for each of the four colors.
/*if (!tcbuf)*/ for (i = 3; i >= 0; --i) if (pixelmode != PIX_ARGB) for (i = 3; i >= 0; --i)
{ {
palcol[i] = color[i].a ? RGB256k.RGB[color[i].r >> 2][color[i].g >> 2][color[i].b >> 2] : 0; if (pixelmode == PIX_Palette)
palcol[i] = color[i].a ? RGB256k.RGB[color[i].r >> 2][color[i].g >> 2][color[i].b >> 2] : 0;
else
palcol[i] = (color[i].a * color[i].r) / 255; // use the same logic as the hardware renderer.
} }
// Now decode this 4x4 block to the pixel buffer. // Now decode this 4x4 block to the pixel buffer.
for (y = 0; y < 4; ++y) for (y = 0; y < 4; ++y)
@ -658,13 +587,13 @@ void FDDSTexture::DecompressDXT1 (FileReader &lump, uint8_t *tcbuf)
break; break;
} }
int ci = (yslice >> (x + x)) & 3; int ci = (yslice >> (x + x)) & 3;
if (!tcbuf) if (pixelmode != PIX_ARGB)
{ {
Pixels[oy + y + (ox + x) * Height] = palcol[ci]; buffer[oy + y + (ox + x) * Height] = palcol[ci];
} }
else else
{ {
uint8_t * tcp = &tcbuf[(ox + x)*4 + (oy + y) * Width*4]; uint8_t * tcp = &buffer[(ox + x)*4 + (oy + y) * Width*4];
tcp[0] = color[ci].r; tcp[0] = color[ci].r;
tcp[1] = color[ci].g; tcp[1] = color[ci].g;
tcp[2] = color[ci].b; tcp[2] = color[ci].b;
@ -685,13 +614,13 @@ void FDDSTexture::DecompressDXT1 (FileReader &lump, uint8_t *tcbuf)
// //
//========================================================================== //==========================================================================
void FDDSTexture::DecompressDXT3 (FileReader &lump, bool premultiplied, uint8_t *tcbuf) void FDDSTexture::DecompressDXT3 (FileReader &lump, bool premultiplied, uint8_t *buffer, int pixelmode)
{ {
const long blocklinelen = ((Width + 3) >> 2) << 4; const long blocklinelen = ((Width + 3) >> 2) << 4;
uint8_t *blockbuff = new uint8_t[blocklinelen]; uint8_t *blockbuff = new uint8_t[blocklinelen];
uint8_t *block; uint8_t *block;
PalEntry color[4]; PalEntry color[4];
uint8_t palcol[4]; uint8_t palcol[4] = { 0,0,0,0 };
int ox, oy, x, y, i; int ox, oy, x, y, i;
for (oy = 0; oy < Height; oy += 4) for (oy = 0; oy < Height; oy += 4)
@ -719,10 +648,14 @@ void FDDSTexture::DecompressDXT3 (FileReader &lump, bool premultiplied, uint8_t
color[3].b = (color[0].b + color[1].b + color[1].b + 1) / 3; color[3].b = (color[0].b + color[1].b + color[1].b + 1) / 3;
// Pick colors from the palette for each of the four colors. // Pick colors from the palette for each of the four colors.
if (!tcbuf) for (i = 3; i >= 0; --i) if (pixelmode != PIX_ARGB) for (i = 3; i >= 0; --i)
{ {
palcol[i] = RGB256k.RGB[color[i].r >> 2][color[i].g >> 2][color[i].b >> 2]; if (pixelmode == PIX_Palette)
palcol[i] = color[i].a ? RGB256k.RGB[color[i].r >> 2][color[i].g >> 2][color[i].b >> 2] : 0;
else
palcol[i] = (color[i].a * color[i].r) / 255; // use the same logic as the hardware renderer.
} }
// Now decode this 4x4 block to the pixel buffer. // Now decode this 4x4 block to the pixel buffer.
for (y = 0; y < 4; ++y) for (y = 0; y < 4; ++y)
{ {
@ -738,14 +671,14 @@ void FDDSTexture::DecompressDXT3 (FileReader &lump, bool premultiplied, uint8_t
{ {
break; break;
} }
if (!tcbuf) if (pixelmode != PIX_ARGB)
{ {
Pixels[oy + y + (ox + x) * Height] = ((yalphaslice >> (x*4)) & 15) < 8 ? buffer[oy + y + (ox + x) * Height] = ((yalphaslice >> (x*4)) & 15) < 8 ?
(bMasked = true, 0) : palcol[(yslice >> (x + x)) & 3]; (bMasked = true, 0) : palcol[(yslice >> (x + x)) & 3];
} }
else else
{ {
uint8_t * tcp = &tcbuf[(ox + x)*4 + (oy + y) * Width*4]; uint8_t * tcp = &buffer[(ox + x)*4 + (oy + y) * Width*4];
int c = (yslice >> (x + x)) & 3; int c = (yslice >> (x + x)) & 3;
tcp[0] = color[c].r; tcp[0] = color[c].r;
tcp[1] = color[c].g; tcp[1] = color[c].g;
@ -767,13 +700,13 @@ void FDDSTexture::DecompressDXT3 (FileReader &lump, bool premultiplied, uint8_t
// //
//========================================================================== //==========================================================================
void FDDSTexture::DecompressDXT5 (FileReader &lump, bool premultiplied, uint8_t *tcbuf) void FDDSTexture::DecompressDXT5 (FileReader &lump, bool premultiplied, uint8_t *buffer, int pixelmode)
{ {
const long blocklinelen = ((Width + 3) >> 2) << 4; const long blocklinelen = ((Width + 3) >> 2) << 4;
uint8_t *blockbuff = new uint8_t[blocklinelen]; uint8_t *blockbuff = new uint8_t[blocklinelen];
uint8_t *block; uint8_t *block;
PalEntry color[4]; PalEntry color[4];
uint8_t palcol[4]; uint8_t palcol[4] = { 0,0,0,0 };
uint32_t yalphaslice = 0; uint32_t yalphaslice = 0;
int ox, oy, x, y, i; int ox, oy, x, y, i;
@ -824,9 +757,12 @@ void FDDSTexture::DecompressDXT5 (FileReader &lump, bool premultiplied, uint8_t
color[3].b = (color[0].b + color[1].b + color[1].b + 1) / 3; color[3].b = (color[0].b + color[1].b + color[1].b + 1) / 3;
// Pick colors from the palette for each of the four colors. // Pick colors from the palette for each of the four colors.
if (!tcbuf) for (i = 3; i >= 0; --i) if (pixelmode != PIX_ARGB) for (i = 3; i >= 0; --i)
{ {
palcol[i] = RGB256k.RGB[color[i].r >> 2][color[i].g >> 2][color[i].b >> 2]; if (pixelmode == PIX_Palette)
palcol[i] = color[i].a ? RGB256k.RGB[color[i].r >> 2][color[i].g >> 2][color[i].b >> 2] : 0;
else
palcol[i] = (color[i].a * color[i].r) / 255; // use the same logic as the hardware renderer.
} }
// Now decode this 4x4 block to the pixel buffer. // Now decode this 4x4 block to the pixel buffer.
for (y = 0; y < 4; ++y) for (y = 0; y < 4; ++y)
@ -851,14 +787,14 @@ void FDDSTexture::DecompressDXT5 (FileReader &lump, bool premultiplied, uint8_t
{ {
break; break;
} }
if (!tcbuf) if (pixelmode == 8)
{ {
Pixels[oy + y + (ox + x) * Height] = alpha[((yalphaslice >> (x*3)) & 7)] < 128 ? buffer[oy + y + (ox + x) * Height] = alpha[((yalphaslice >> (x*3)) & 7)] < 128 ?
(bMasked = true, 0) : palcol[(yslice >> (x + x)) & 3]; (bMasked = true, 0) : palcol[(yslice >> (x + x)) & 3];
} }
else else
{ {
uint8_t * tcp = &tcbuf[(ox + x)*4 + (oy + y) * Width*4]; uint8_t * tcp = &buffer[(ox + x)*4 + (oy + y) * Width*4];
int c = (yslice >> (x + x)) & 3; int c = (yslice >> (x + x)) & 3;
tcp[0] = color[c].r; tcp[0] = color[c].r;
tcp[1] = color[c].g; tcp[1] = color[c].g;
@ -889,19 +825,19 @@ int FDDSTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCo
if (Format >= 1 && Format <= 4) // RGB: Format is # of bytes per pixel if (Format >= 1 && Format <= 4) // RGB: Format is # of bytes per pixel
{ {
ReadRGB (lump, TexBuffer); ReadRGB (lump, TexBuffer, PIX_ARGB);
} }
else if (Format == ID_DXT1) else if (Format == ID_DXT1)
{ {
DecompressDXT1 (lump, TexBuffer); DecompressDXT1 (lump, TexBuffer, PIX_ARGB);
} }
else if (Format == ID_DXT3 || Format == ID_DXT2) else if (Format == ID_DXT3 || Format == ID_DXT2)
{ {
DecompressDXT3 (lump, Format == ID_DXT2, TexBuffer); DecompressDXT3 (lump, Format == ID_DXT2, TexBuffer, PIX_ARGB);
} }
else if (Format == ID_DXT5 || Format == ID_DXT4) else if (Format == ID_DXT5 || Format == ID_DXT4)
{ {
DecompressDXT5 (lump, Format == ID_DXT4, TexBuffer); DecompressDXT5 (lump, Format == ID_DXT4, TexBuffer, PIX_ARGB);
} }
// All formats decompress to RGBA. // All formats decompress to RGBA.

View file

@ -1,7 +1,8 @@
/* /*
** flattexture.cpp ** emptytexture.cpp
** Texture class for empty placeholder textures ** Texture class for empty placeholder textures
** (essentially patches with dimensions and offsets of (0,0) ) ** (essentially patches with dimensions and offsets of (0,0) )
** These need special treatment because a texture size of 0 is illegal
** **
**--------------------------------------------------------------------------- **---------------------------------------------------------------------------
** Copyright 2009 Christoph Oelckers ** Copyright 2009 Christoph Oelckers
@ -41,30 +42,21 @@
//========================================================================== //==========================================================================
// //
// A texture defined between F_START and F_END markers //
// //
//========================================================================== //==========================================================================
class FEmptyTexture : public FTexture class FEmptyTexture : public FWorldTexture
{ {
uint8_t Pixel = 0;
public: public:
FEmptyTexture (int lumpnum); FEmptyTexture (int lumpnum);
uint8_t *MakeTexture(FRenderStyle style) override;
const uint8_t *GetColumn (unsigned int column, const Span **spans_out);
const uint8_t *GetPixels ();
void Unload() {}
protected:
uint8_t Pixels[1];
Span DummySpans[1];
}; };
//========================================================================== //==========================================================================
// //
// Since there is no way to detect the validity of a flat //
// they can't be used anywhere else but between F_START and F_END
// //
//========================================================================== //==========================================================================
@ -86,15 +78,13 @@ FTexture *EmptyTexture_TryCreate(FileReader & file, int lumpnum)
//========================================================================== //==========================================================================
FEmptyTexture::FEmptyTexture (int lumpnum) FEmptyTexture::FEmptyTexture (int lumpnum)
: FTexture(NULL, lumpnum) : FWorldTexture(NULL, lumpnum)
{ {
bMasked = true; bMasked = true;
WidthBits = HeightBits = 1; WidthBits = HeightBits = 1;
Width = Height = 1; Width = Height = 1;
WidthMask = 0; WidthMask = 0;
DummySpans[0].TopOffset = 0; PixelsAreStatic = 3;
DummySpans[0].Length = 0;
Pixels[0] = 0;
} }
//========================================================================== //==========================================================================
@ -103,23 +93,8 @@ FEmptyTexture::FEmptyTexture (int lumpnum)
// //
//========================================================================== //==========================================================================
const uint8_t *FEmptyTexture::GetColumn (unsigned int column, const Span **spans_out) uint8_t *FEmptyTexture::MakeTexture(FRenderStyle style)
{ {
if (spans_out != NULL) return &Pixel;
{
*spans_out = DummySpans;
}
return Pixels;
}
//==========================================================================
//
//
//
//==========================================================================
const uint8_t *FEmptyTexture::GetPixels ()
{
return Pixels;
} }

View file

@ -45,24 +45,11 @@
// //
//========================================================================== //==========================================================================
class FFlatTexture : public FTexture class FFlatTexture : public FWorldTexture
{ {
public: public:
FFlatTexture (int lumpnum); FFlatTexture (int lumpnum);
~FFlatTexture (); uint8_t *MakeTexture (FRenderStyle style) override;
const uint8_t *GetColumn (unsigned int column, const Span **spans_out);
const uint8_t *GetPixels ();
void Unload ();
protected:
uint8_t *Pixels;
Span DummySpans[2];
void MakeTexture ();
friend class FTexture;
}; };
@ -86,7 +73,7 @@ FTexture *FlatTexture_TryCreate(FileReader & file, int lumpnum)
//========================================================================== //==========================================================================
FFlatTexture::FFlatTexture (int lumpnum) FFlatTexture::FFlatTexture (int lumpnum)
: FTexture(NULL, lumpnum), Pixels(0) : FWorldTexture(NULL, lumpnum)
{ {
int area; int area;
int bits; int bits;
@ -108,10 +95,6 @@ FFlatTexture::FFlatTexture (int lumpnum)
WidthBits = HeightBits = bits; WidthBits = HeightBits = bits;
Width = Height = 1 << bits; Width = Height = 1 << bits;
WidthMask = (1 << bits) - 1; WidthMask = (1 << bits) - 1;
DummySpans[0].TopOffset = 0;
DummySpans[0].Length = Height;
DummySpans[1].TopOffset = 0;
DummySpans[1].Length = 0;
} }
//========================================================================== //==========================================================================
@ -120,87 +103,17 @@ FFlatTexture::FFlatTexture (int lumpnum)
// //
//========================================================================== //==========================================================================
FFlatTexture::~FFlatTexture () uint8_t *FFlatTexture::MakeTexture (FRenderStyle style)
{
Unload ();
}
//==========================================================================
//
//
//
//==========================================================================
void FFlatTexture::Unload ()
{
if (Pixels != NULL)
{
delete[] Pixels;
Pixels = NULL;
}
FTexture::Unload();
}
//==========================================================================
//
//
//
//==========================================================================
const uint8_t *FFlatTexture::GetColumn (unsigned int column, const Span **spans_out)
{
if (Pixels == NULL)
{
MakeTexture ();
}
if ((unsigned)column >= (unsigned)Width)
{
if (WidthMask + 1 == Width)
{
column &= WidthMask;
}
else
{
column %= Width;
}
}
if (spans_out != NULL)
{
*spans_out = DummySpans;
}
return Pixels + column*Height;
}
//==========================================================================
//
//
//
//==========================================================================
const uint8_t *FFlatTexture::GetPixels ()
{
if (Pixels == NULL)
{
MakeTexture ();
}
return Pixels;
}
//==========================================================================
//
//
//
//==========================================================================
void FFlatTexture::MakeTexture ()
{ {
auto lump = Wads.OpenLumpReader (SourceLump); auto lump = Wads.OpenLumpReader (SourceLump);
Pixels = new uint8_t[Width*Height]; auto Pixels = new uint8_t[Width*Height];
auto numread = lump.Read (Pixels, Width*Height); auto numread = lump.Read (Pixels, Width*Height);
if (numread < Width*Height) if (numread < Width*Height)
{ {
memset (Pixels + numread, 0xBB, Width*Height - numread); memset (Pixels + numread, 0xBB, Width*Height - numread);
} }
FlipSquareBlockRemap (Pixels, Width, Height, GPalette.Remap); if (!(style.Flags & STYLEF_RedIsAlpha)) FTexture::FlipSquareBlockRemap (Pixels, Width, Height, GPalette.Remap);
else FTexture::FlipSquareBlock(Pixels, Width, Height);
return Pixels;
} }

View file

@ -36,6 +36,7 @@
#include "doomtype.h" #include "doomtype.h"
#include "files.h" #include "files.h"
#include "w_wad.h" #include "w_wad.h"
#include "v_palette.h"
#include "textures/textures.h" #include "textures/textures.h"
@ -47,7 +48,7 @@
// //
//========================================================================== //==========================================================================
class FIMGZTexture : public FTexture class FIMGZTexture : public FWorldTexture
{ {
struct ImageHeader struct ImageHeader
{ {
@ -62,18 +63,7 @@ class FIMGZTexture : public FTexture
public: public:
FIMGZTexture (int lumpnum, uint16_t w, uint16_t h, int16_t l, int16_t t); FIMGZTexture (int lumpnum, uint16_t w, uint16_t h, int16_t l, int16_t t);
~FIMGZTexture (); uint8_t *MakeTexture (FRenderStyle style) override;
const uint8_t *GetColumn (unsigned int column, const Span **spans_out);
const uint8_t *GetPixels ();
void Unload ();
protected:
uint8_t *Pixels;
Span **Spans;
void MakeTexture ();
}; };
@ -106,7 +96,7 @@ FTexture *IMGZTexture_TryCreate(FileReader & file, int lumpnum)
//========================================================================== //==========================================================================
FIMGZTexture::FIMGZTexture (int lumpnum, uint16_t w, uint16_t h, int16_t l, int16_t t) FIMGZTexture::FIMGZTexture (int lumpnum, uint16_t w, uint16_t h, int16_t l, int16_t t)
: FTexture(NULL, lumpnum), Pixels(0), Spans(0) : FWorldTexture(NULL, lumpnum)
{ {
Wads.GetLumpName (Name, lumpnum); Wads.GetLumpName (Name, lumpnum);
Width = w; Width = w;
@ -122,88 +112,7 @@ FIMGZTexture::FIMGZTexture (int lumpnum, uint16_t w, uint16_t h, int16_t l, int1
// //
//========================================================================== //==========================================================================
FIMGZTexture::~FIMGZTexture () uint8_t *FIMGZTexture::MakeTexture (FRenderStyle style)
{
Unload ();
if (Spans != NULL)
{
FreeSpans (Spans);
Spans = NULL;
}
}
//==========================================================================
//
//
//
//==========================================================================
void FIMGZTexture::Unload ()
{
if (Pixels != NULL)
{
delete[] Pixels;
Pixels = NULL;
}
FTexture::Unload();
}
//==========================================================================
//
//
//
//==========================================================================
const uint8_t *FIMGZTexture::GetColumn (unsigned int column, const Span **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;
}
//==========================================================================
//
//
//
//==========================================================================
const uint8_t *FIMGZTexture::GetPixels ()
{
if (Pixels == NULL)
{
MakeTexture ();
}
return Pixels;
}
//==========================================================================
//
//
//
//==========================================================================
void FIMGZTexture::MakeTexture ()
{ {
FMemLump lump = Wads.ReadLump (SourceLump); FMemLump lump = Wads.ReadLump (SourceLump);
const ImageHeader *imgz = (const ImageHeader *)lump.GetMem(); const ImageHeader *imgz = (const ImageHeader *)lump.GetMem();
@ -222,7 +131,7 @@ void FIMGZTexture::MakeTexture ()
int dest_rew = Width * Height - 1; int dest_rew = Width * Height - 1;
CalcBitSize (); CalcBitSize ();
Pixels = new uint8_t[Width*Height]; auto Pixels = new uint8_t[Width*Height];
dest_p = Pixels; dest_p = Pixels;
// Convert the source image from row-major to column-major format // Convert the source image from row-major to column-major format
@ -232,7 +141,8 @@ void FIMGZTexture::MakeTexture ()
{ {
for (int x = Width; x != 0; --x) for (int x = Width; x != 0; --x)
{ {
*dest_p = *data; auto p = *data;
*dest_p = (style.Flags & STYLEF_RedIsAlpha) ? p : GPalette.Remap[p];
dest_p += dest_adv; dest_p += dest_adv;
data++; data++;
} }
@ -251,8 +161,8 @@ void FIMGZTexture::MakeTexture ()
{ {
if (runlen != 0) if (runlen != 0)
{ {
uint8_t color = *data; auto p = *data;
*dest_p = color; *dest_p = (style.Flags & STYLEF_RedIsAlpha) ? p : GPalette.Remap[p];
dest_p += dest_adv; dest_p += dest_adv;
data++; data++;
x--; x--;
@ -282,5 +192,6 @@ void FIMGZTexture::MakeTexture ()
dest_p -= dest_rew; dest_p -= dest_rew;
} }
} }
return Pixels;
} }

View file

@ -179,27 +179,16 @@ void JPEG_OutputMessage (j_common_ptr cinfo)
// //
//========================================================================== //==========================================================================
class FJPEGTexture : public FTexture class FJPEGTexture : public FWorldTexture
{ {
public: public:
FJPEGTexture (int lumpnum, int width, int height); FJPEGTexture (int lumpnum, int width, int height);
~FJPEGTexture (); ~FJPEGTexture ();
const uint8_t *GetColumn (unsigned int column, const Span **spans_out); FTextureFormat GetFormat () override;
const uint8_t *GetPixels (); int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL) override;
void Unload (); bool UseBasePalette() override;
FTextureFormat GetFormat (); uint8_t *MakeTexture (FRenderStyle style) override;
int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL);
bool UseBasePalette();
protected:
uint8_t *Pixels;
Span DummySpans[2];
void MakeTexture ();
friend class FTexture;
}; };
//========================================================================== //==========================================================================
@ -259,7 +248,7 @@ FTexture *JPEGTexture_TryCreate(FileReader & data, int lumpnum)
//========================================================================== //==========================================================================
FJPEGTexture::FJPEGTexture (int lumpnum, int width, int height) FJPEGTexture::FJPEGTexture (int lumpnum, int width, int height)
: FTexture(NULL, lumpnum), Pixels(0) : FWorldTexture(NULL, lumpnum)
{ {
UseType = TEX_MiscPatch; UseType = TEX_MiscPatch;
LeftOffset = 0; LeftOffset = 0;
@ -269,35 +258,6 @@ FJPEGTexture::FJPEGTexture (int lumpnum, int width, int height)
Width = width; Width = width;
Height = height; Height = height;
CalcBitSize (); CalcBitSize ();
DummySpans[0].TopOffset = 0;
DummySpans[0].Length = Height;
DummySpans[1].TopOffset = 0;
DummySpans[1].Length = 0;
}
//==========================================================================
//
//
//
//==========================================================================
FJPEGTexture::~FJPEGTexture ()
{
Unload ();
}
//==========================================================================
//
//
//
//==========================================================================
void FJPEGTexture::Unload ()
{
delete[] Pixels;
Pixels = NULL;
FTexture::Unload();
} }
//========================================================================== //==========================================================================
@ -317,142 +277,123 @@ FTextureFormat FJPEGTexture::GetFormat()
// //
//========================================================================== //==========================================================================
const uint8_t *FJPEGTexture::GetColumn (unsigned int column, const Span **spans_out) uint8_t *FJPEGTexture::MakeTexture (FRenderStyle style)
{
if (Pixels == NULL)
{
MakeTexture ();
}
if ((unsigned)column >= (unsigned)Width)
{
if (WidthMask + 1 == Width)
{
column &= WidthMask;
}
else
{
column %= Width;
}
}
if (spans_out != NULL)
{
*spans_out = DummySpans;
}
return Pixels + column*Height;
}
//==========================================================================
//
//
//
//==========================================================================
const uint8_t *FJPEGTexture::GetPixels ()
{
if (Pixels == NULL)
{
MakeTexture ();
}
return Pixels;
}
//==========================================================================
//
//
//
//==========================================================================
void FJPEGTexture::MakeTexture ()
{ {
auto lump = Wads.OpenLumpReader (SourceLump); auto lump = Wads.OpenLumpReader (SourceLump);
JSAMPLE *buff = NULL; JSAMPLE *buff = NULL;
bool doalpha = !!(style.Flags & STYLEF_RedIsAlpha);
jpeg_decompress_struct cinfo; jpeg_decompress_struct cinfo;
jpeg_error_mgr jerr; jpeg_error_mgr jerr;
Pixels = new uint8_t[Width * Height]; auto Pixels = new uint8_t[Width * Height];
memset (Pixels, 0xBA, Width * Height); memset (Pixels, 0xBA, Width * Height);
cinfo.err = jpeg_std_error(&jerr); cinfo.err = jpeg_std_error(&jerr);
cinfo.err->output_message = JPEG_OutputMessage; cinfo.err->output_message = JPEG_OutputMessage;
cinfo.err->error_exit = JPEG_ErrorExit; cinfo.err->error_exit = JPEG_ErrorExit;
jpeg_create_decompress(&cinfo); jpeg_create_decompress(&cinfo);
FLumpSourceMgr sourcemgr(&lump, &cinfo);
try try
{ {
FLumpSourceMgr sourcemgr(&lump, &cinfo);
jpeg_read_header(&cinfo, TRUE); jpeg_read_header(&cinfo, TRUE);
if (!((cinfo.out_color_space == JCS_RGB && cinfo.num_components == 3) || if (!((cinfo.out_color_space == JCS_RGB && cinfo.num_components == 3) ||
(cinfo.out_color_space == JCS_CMYK && cinfo.num_components == 4) || (cinfo.out_color_space == JCS_CMYK && cinfo.num_components == 4) ||
(cinfo.out_color_space == JCS_GRAYSCALE && cinfo.num_components == 1))) (cinfo.out_color_space == JCS_YCbCr && cinfo.num_components == 3) ||
(cinfo.out_color_space == JCS_GRAYSCALE && cinfo.num_components == 1)))
{ {
Printf (TEXTCOLOR_ORANGE "Unsupported color format\n"); Printf(TEXTCOLOR_ORANGE, "Unsupported color format in %s\n", Wads.GetLumpFullPath(SourceLump).GetChars());
throw -1;
} }
else
jpeg_start_decompress(&cinfo);
int y = 0;
buff = new uint8_t[cinfo.output_width * cinfo.output_components];
while (cinfo.output_scanline < cinfo.output_height)
{ {
int num_scanlines = jpeg_read_scanlines(&cinfo, &buff, 1); jpeg_start_decompress(&cinfo);
uint8_t *in = buff;
uint8_t *out = Pixels + y; int y = 0;
switch (cinfo.out_color_space) buff = new uint8_t[cinfo.output_width * cinfo.output_components];
while (cinfo.output_scanline < cinfo.output_height)
{ {
case JCS_RGB: int num_scanlines = jpeg_read_scanlines(&cinfo, &buff, 1);
for (int x = Width; x > 0; --x) uint8_t *in = buff;
uint8_t *out = Pixels + y;
switch (cinfo.out_color_space)
{ {
*out = RGB256k.RGB[in[0]>>2][in[1]>>2][in[2]>>2]; case JCS_RGB:
out += Height; for (int x = Width; x > 0; --x)
in += 3; {
} *out = !doalpha? RGB256k.RGB[in[0] >> 2][in[1] >> 2][in[2] >> 2] : in[0];
break; out += Height;
in += 3;
}
break;
case JCS_GRAYSCALE: case JCS_GRAYSCALE:
for (int x = Width; x > 0; --x) for (int x = Width; x > 0; --x)
{ {
*out = GrayMap[in[0]]; *out = !doalpha ? FTexture::GrayMap[in[0]] : in[0];
out += Height; out += Height;
in += 1; in += 1;
} }
break; break;
case JCS_CMYK: case JCS_CMYK:
// What are you doing using a CMYK image? :) // What are you doing using a CMYK image? :)
for (int x = Width; x > 0; --x) for (int x = Width; x > 0; --x)
{ {
// To be precise, these calculations should use 255, but // To be precise, these calculations should use 255, but
// 256 is much faster and virtually indistinguishable. // 256 is much faster and virtually indistinguishable.
int r = in[3] - (((256-in[0])*in[3]) >> 8); int r = in[3] - (((256 - in[0])*in[3]) >> 8);
int g = in[3] - (((256-in[1])*in[3]) >> 8); if (!doalpha)
int b = in[3] - (((256-in[2])*in[3]) >> 8); {
*out = RGB256k.RGB[r >> 2][g >> 2][b >> 2]; int g = in[3] - (((256 - in[1])*in[3]) >> 8);
out += Height; int b = in[3] - (((256 - in[2])*in[3]) >> 8);
in += 4; *out = RGB256k.RGB[r >> 2][g >> 2][b >> 2];
} }
break; else *out = (uint8_t)r;
out += Height;
in += 4;
}
break;
default: case JCS_YCbCr:
// The other colorspaces were considered above and discarded, // Probably useless but since I had the formula available...
// but GCC will complain without a default for them here. for (int x = Width; x > 0; --x)
break; {
double Y = in[0], Cb = in[1], Cr = in[2];
int r = clamp((int)(Y + 1.40200 * (Cr - 0x80)), 0, 255);
if (!doalpha)
{
int g = clamp((int)(Y - 0.34414 * (Cb - 0x80) - 0.71414 * (Cr - 0x80)), 0, 255);
int b = clamp((int)(Y + 1.77200 * (Cb - 0x80)), 0, 255);
*out = RGB256k.RGB[r >> 2][g >> 2][b >> 2];
}
else *out = (uint8_t)r;
out += Height;
in += 4;
}
break;
default:
// The other colorspaces were considered above and discarded,
// but GCC will complain without a default for them here.
break;
}
y++;
} }
y++; jpeg_finish_decompress(&cinfo);
} }
jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
} }
catch (int) catch (int)
{ {
Printf (TEXTCOLOR_ORANGE " in texture %s\n", Name.GetChars()); Printf(TEXTCOLOR_ORANGE, "JPEG error in %s\n", Wads.GetLumpFullPath(SourceLump).GetChars());
jpeg_destroy_decompress(&cinfo);
} }
jpeg_destroy_decompress(&cinfo);
if (buff != NULL) if (buff != NULL)
{ {
delete[] buff; delete[] buff;
} }
return Pixels;
} }
@ -479,58 +420,66 @@ int FJPEGTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FC
cinfo.err->error_exit = JPEG_ErrorExit; cinfo.err->error_exit = JPEG_ErrorExit;
jpeg_create_decompress(&cinfo); jpeg_create_decompress(&cinfo);
FLumpSourceMgr sourcemgr(&lump, &cinfo);
try try
{ {
FLumpSourceMgr sourcemgr(&lump, &cinfo);
jpeg_read_header(&cinfo, TRUE); jpeg_read_header(&cinfo, TRUE);
if (!((cinfo.out_color_space == JCS_RGB && cinfo.num_components == 3) || if (!((cinfo.out_color_space == JCS_RGB && cinfo.num_components == 3) ||
(cinfo.out_color_space == JCS_CMYK && cinfo.num_components == 4) || (cinfo.out_color_space == JCS_CMYK && cinfo.num_components == 4) ||
(cinfo.out_color_space == JCS_GRAYSCALE && cinfo.num_components == 1))) (cinfo.out_color_space == JCS_YCbCr && cinfo.num_components == 3) ||
(cinfo.out_color_space == JCS_GRAYSCALE && cinfo.num_components == 1)))
{ {
Printf (TEXTCOLOR_ORANGE "Unsupported color format\n"); Printf(TEXTCOLOR_ORANGE, "Unsupported color format in %s\n", Wads.GetLumpFullPath(SourceLump).GetChars());
throw -1;
} }
jpeg_start_decompress(&cinfo); else
int yc = 0;
buff = new uint8_t[cinfo.output_height * cinfo.output_width * cinfo.output_components];
while (cinfo.output_scanline < cinfo.output_height)
{ {
uint8_t * ptr = buff + cinfo.output_width * cinfo.output_components * yc; jpeg_start_decompress(&cinfo);
jpeg_read_scanlines(&cinfo, &ptr, 1);
yc++; int yc = 0;
buff = new uint8_t[cinfo.output_height * cinfo.output_width * cinfo.output_components];
while (cinfo.output_scanline < cinfo.output_height)
{
uint8_t * ptr = buff + cinfo.output_width * cinfo.output_components * yc;
jpeg_read_scanlines(&cinfo, &ptr, 1);
yc++;
}
switch (cinfo.out_color_space)
{
case JCS_RGB:
bmp->CopyPixelDataRGB(x, y, buff, cinfo.output_width, cinfo.output_height,
3, cinfo.output_width * cinfo.output_components, rotate, CF_RGB, inf);
break;
case JCS_GRAYSCALE:
for (int i = 0; i < 256; i++) pe[i] = PalEntry(255, i, i, i); // default to a gray map
bmp->CopyPixelData(x, y, buff, cinfo.output_width, cinfo.output_height,
1, cinfo.output_width, rotate, pe, inf);
break;
case JCS_CMYK:
bmp->CopyPixelDataRGB(x, y, buff, cinfo.output_width, cinfo.output_height,
4, cinfo.output_width * cinfo.output_components, rotate, CF_CMYK, inf);
break;
case JCS_YCbCr:
bmp->CopyPixelDataRGB(x, y, buff, cinfo.output_width, cinfo.output_height,
4, cinfo.output_width * cinfo.output_components, rotate, CF_YCbCr, inf);
break;
default:
assert(0);
break;
}
jpeg_finish_decompress(&cinfo);
} }
switch (cinfo.out_color_space)
{
case JCS_RGB:
bmp->CopyPixelDataRGB(x, y, buff, cinfo.output_width, cinfo.output_height,
3, cinfo.output_width * cinfo.output_components, rotate, CF_RGB, inf);
break;
case JCS_GRAYSCALE:
for(int i=0;i<256;i++) pe[i]=PalEntry(255,i,i,i); // default to a gray map
bmp->CopyPixelData(x, y, buff, cinfo.output_width, cinfo.output_height,
1, cinfo.output_width, rotate, pe, inf);
break;
case JCS_CMYK:
bmp->CopyPixelDataRGB(x, y, buff, cinfo.output_width, cinfo.output_height,
4, cinfo.output_width * cinfo.output_components, rotate, CF_CMYK, inf);
break;
default:
assert(0);
break;
}
jpeg_finish_decompress(&cinfo);
} }
catch(int) catch (int)
{ {
Printf (TEXTCOLOR_ORANGE " in JPEG texture %s\n", Name.GetChars()); Printf(TEXTCOLOR_ORANGE, "JPEG error in %s\n", Wads.GetLumpFullPath(SourceLump).GetChars());
} }
jpeg_destroy_decompress(&cinfo); jpeg_destroy_decompress(&cinfo);
if (buff != NULL) delete [] buff; if (buff != NULL) delete [] buff;

View file

@ -148,24 +148,21 @@ struct FPatchLookup
// //
//========================================================================== //==========================================================================
class FMultiPatchTexture : public FTexture class FMultiPatchTexture : public FWorldTexture
{ {
public: public:
FMultiPatchTexture (const void *texdef, FPatchLookup *patchlookup, int maxpatchnum, bool strife, int deflump); FMultiPatchTexture (const void *texdef, FPatchLookup *patchlookup, int maxpatchnum, bool strife, int deflump);
FMultiPatchTexture (FScanner &sc, int usetype); FMultiPatchTexture (FScanner &sc, int usetype);
~FMultiPatchTexture (); ~FMultiPatchTexture ();
const uint8_t *GetColumn (unsigned int column, const Span **spans_out); FTextureFormat GetFormat() override;
const uint8_t *GetPixels (); bool UseBasePalette() override;
FTextureFormat GetFormat(); virtual void SetFrontSkyLayer () override;
bool UseBasePalette() ;
void Unload ();
virtual void SetFrontSkyLayer ();
int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL); int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL) override;
int GetSourceLump() { return DefinitionLump; } int GetSourceLump() override { return DefinitionLump; }
FTexture *GetRedirect(bool wantwarped); FTexture *GetRedirect(bool wantwarped) override;
FTexture *GetRawTexture(); FTexture *GetRawTexture() override;
void ResolvePatches(); void ResolvePatches();
protected: protected:
@ -201,7 +198,7 @@ protected:
bool bRedirect:1; bool bRedirect:1;
bool bTranslucentPatches:1; bool bTranslucentPatches:1;
void MakeTexture (); uint8_t *MakeTexture (FRenderStyle style);
private: private:
void CheckForHacks (); void CheckForHacks ();
@ -323,11 +320,6 @@ FMultiPatchTexture::~FMultiPatchTexture ()
delete[] Inits; delete[] Inits;
Inits = nullptr; Inits = nullptr;
} }
if (Spans != NULL)
{
FreeSpans (Spans);
Spans = NULL;
}
} }
//========================================================================== //==========================================================================
@ -345,80 +337,6 @@ void FMultiPatchTexture::SetFrontSkyLayer ()
bNoRemap0 = true; 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 // GetBlendMap
@ -427,7 +345,6 @@ const uint8_t *FMultiPatchTexture::GetColumn (unsigned int column, const Span **
uint8_t *GetBlendMap(PalEntry blend, uint8_t *blendwork) uint8_t *GetBlendMap(PalEntry blend, uint8_t *blendwork)
{ {
switch (blend.a==0 ? int(blend) : -1) switch (blend.a==0 ? int(blend) : -1)
{ {
case BLEND_ICEMAP: 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 // 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. // a power of 2, in case somebody accidentally makes it repeat vertically.
int numpix = Width * Height + (1 << HeightBits) - Height; int numpix = Width * Height + (1 << HeightBits) - Height;
uint8_t blendwork[256]; 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); 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) for (int i = 0; i < NumParts; ++i)
{ {
if (Parts[i].Texture->bHasCanvas) continue; // cannot use camera textures as patch. 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) if (Parts[i].Blend != 0)
{ {
trans = GetBlendMap(Parts[i].Blend, blendwork); trans = GetBlendMap(Parts[i].Blend, blendwork);
} }
Parts[i].Texture->CopyToBlock (Pixels, Width, Height, 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) 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; out += Height;
in += 4; in += 4;
@ -539,6 +471,7 @@ void FMultiPatchTexture::MakeTexture ()
} }
delete [] buffer; delete [] buffer;
} }
return Pixels;
} }
//=========================================================================== //===========================================================================
@ -755,14 +688,6 @@ void FMultiPatchTexture::CheckForHacks ()
break; break;
} }
} }
if (i == NumParts)
{
for (i = 0; i < NumParts; ++i)
{
Parts[i].Texture->HackHack(256);
}
}
} }
} }

View file

@ -39,6 +39,7 @@
#include "templates.h" #include "templates.h"
#include "v_palette.h" #include "v_palette.h"
#include "textures/textures.h" #include "textures/textures.h"
#include "r_data/r_translate.h"
// posts are runs of non masked source pixels // posts are runs of non masked source pixels
@ -55,24 +56,13 @@ struct column_t
// //
//========================================================================== //==========================================================================
class FPatchTexture : public FTexture class FPatchTexture : public FWorldTexture
{ {
bool badflag = false;
public: public:
FPatchTexture (int lumpnum, patch_t *header); FPatchTexture (int lumpnum, patch_t *header);
~FPatchTexture (); uint8_t *MakeTexture (FRenderStyle style) override;
void DetectBadPatches();
const uint8_t *GetColumn (unsigned int column, const Span **spans_out);
const uint8_t *GetPixels ();
void Unload ();
protected:
uint8_t *Pixels;
Span **Spans;
bool hackflag;
virtual void MakeTexture ();
void HackHack (int newheight);
}; };
//========================================================================== //==========================================================================
@ -149,12 +139,13 @@ FTexture *PatchTexture_TryCreate(FileReader & file, int lumpnum)
//========================================================================== //==========================================================================
FPatchTexture::FPatchTexture (int lumpnum, patch_t * header) FPatchTexture::FPatchTexture (int lumpnum, patch_t * header)
: FTexture(NULL, lumpnum), Pixels(0), Spans(0), hackflag(false) : FWorldTexture(NULL, lumpnum)
{ {
Width = header->width; Width = header->width;
Height = header->height; Height = header->height;
LeftOffset = header->leftoffset; LeftOffset = header->leftoffset;
TopOffset = header->topoffset; TopOffset = header->topoffset;
DetectBadPatches();
CalcBitSize (); CalcBitSize ();
} }
@ -164,89 +155,7 @@ FPatchTexture::FPatchTexture (int lumpnum, patch_t * header)
// //
//========================================================================== //==========================================================================
FPatchTexture::~FPatchTexture () uint8_t *FPatchTexture::MakeTexture (FRenderStyle style)
{
Unload ();
if (Spans != NULL)
{
FreeSpans (Spans);
Spans = NULL;
}
}
//==========================================================================
//
//
//
//==========================================================================
void FPatchTexture::Unload ()
{
if (Pixels != NULL)
{
delete[] Pixels;
Pixels = NULL;
}
FTexture::Unload();
}
//==========================================================================
//
//
//
//==========================================================================
const uint8_t *FPatchTexture::GetPixels ()
{
if (Pixels == NULL)
{
MakeTexture ();
}
return Pixels;
}
//==========================================================================
//
//
//
//==========================================================================
const uint8_t *FPatchTexture::GetColumn (unsigned int column, const Span **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;
}
//==========================================================================
//
//
//
//==========================================================================
void FPatchTexture::MakeTexture ()
{ {
uint8_t *remap, remaptable[256]; uint8_t *remap, remaptable[256];
int numspans; int numspans;
@ -258,23 +167,11 @@ void FPatchTexture::MakeTexture ()
maxcol = (const column_t *)((const uint8_t *)patch + Wads.LumpLength (SourceLump) - 3); maxcol = (const column_t *)((const uint8_t *)patch + Wads.LumpLength (SourceLump) - 3);
// Check for badly-sized patches if (style.Flags & STYLEF_RedIsAlpha)
#if 0 // Such textures won't be created so there's no need to check here
if (LittleShort(patch->width) <= 0 || LittleShort(patch->height) <= 0)
{ {
lump = Wads.ReadLump ("-BADPATC"); remap = translationtables[TRANSLATION_Standard][8]->Remap;
patch = (const patch_t *)lump.GetMem();
Printf (PRINT_BOLD, "Patch %s has a non-positive size.\n", Name);
} }
else if (LittleShort(patch->width) > 2048 || LittleShort(patch->height) > 2048) else if (bNoRemap0)
{
lump = Wads.ReadLump ("-BADPATC");
patch = (const patch_t *)lump.GetMem();
Printf (PRINT_BOLD, "Patch %s is too big.\n", Name);
}
#endif
if (bNoRemap0)
{ {
memcpy (remaptable, GPalette.Remap, 256); memcpy (remaptable, GPalette.Remap, 256);
remaptable[0] = 0; remaptable[0] = 0;
@ -286,9 +183,9 @@ void FPatchTexture::MakeTexture ()
} }
if (hackflag) if (badflag)
{ {
Pixels = new uint8_t[Width * Height]; auto Pixels = new uint8_t[Width * Height];
uint8_t *out; uint8_t *out;
// Draw the image to the buffer // Draw the image to the buffer
@ -302,7 +199,7 @@ void FPatchTexture::MakeTexture ()
out++, in++; out++, in++;
} }
} }
return; return Pixels;
} }
// Add a little extra space at the end if the texture's height is not // Add a little extra space at the end if the texture's height is not
@ -311,7 +208,7 @@ void FPatchTexture::MakeTexture ()
numspans = Width; numspans = Width;
Pixels = new uint8_t[numpix]; auto Pixels = new uint8_t[numpix];
memset (Pixels, 0, numpix); memset (Pixels, 0, numpix);
// Draw the image to the buffer // Draw the image to the buffer
@ -355,6 +252,7 @@ void FPatchTexture::MakeTexture ()
column = (const column_t *)((const uint8_t *)column + column->length + 4); column = (const column_t *)((const uint8_t *)column + column->length + 4);
} }
} }
return Pixels;
} }
@ -364,8 +262,11 @@ void FPatchTexture::MakeTexture ()
// //
//========================================================================== //==========================================================================
void FPatchTexture::HackHack (int newheight) void FPatchTexture::DetectBadPatches ()
{ {
// The patch must look like it is large enough for the rules to apply to avoid using this on truly empty patches.
if (Wads.LumpLength(SourceLump) < Width * Height / 2) return;
// Check if this patch is likely to be a problem. // Check if this patch is likely to be a problem.
// It must be 256 pixels tall, and all its columns must have exactly // It must be 256 pixels tall, and all its columns must have exactly
// one post, where each post has a supposed length of 0. // one post, where each post has a supposed length of 0.
@ -381,29 +282,17 @@ void FPatchTexture::HackHack (int newheight)
const column_t *col = (column_t*)((uint8_t*)realpatch+LittleLong(cofs[x])); const column_t *col = (column_t*)((uint8_t*)realpatch+LittleLong(cofs[x]));
if (col->topdelta != 0 || col->length != 0) if (col->topdelta != 0 || col->length != 0)
{ {
break; // It's not bad! return; // It's not bad!
} }
col = (column_t *)((uint8_t *)col + 256 + 4); col = (column_t *)((uint8_t *)col + 256 + 4);
if (col->topdelta != 0xFF) if (col->topdelta != 0xFF)
{ {
break; // More than one post in a column! return; // More than one post in a column!
} }
} }
if (x == x2) LeftOffset = 0;
{ TopOffset = 0;
// If all the columns were checked, it needs fixing. badflag = true;
Unload (); bMasked = false; // Hacked textures don't have transparent parts.
if (Spans != NULL)
{
FreeSpans (Spans);
}
Height = newheight;
LeftOffset = 0;
TopOffset = 0;
hackflag = true;
bMasked = false; // Hacked textures don't have transparent parts.
}
} }
} }

View file

@ -81,32 +81,24 @@ struct PCXHeader
// //
//========================================================================== //==========================================================================
class FPCXTexture : public FTexture class FPCXTexture : public FWorldTexture
{ {
public: public:
FPCXTexture (int lumpnum, PCXHeader &); FPCXTexture (int lumpnum, PCXHeader &);
~FPCXTexture (); ~FPCXTexture ();
const uint8_t *GetColumn (unsigned int column, const Span **spans_out); FTextureFormat GetFormat () override;
const uint8_t *GetPixels ();
void Unload ();
FTextureFormat GetFormat ();
int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL); int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL) override;
bool UseBasePalette(); bool UseBasePalette() override;
protected: protected:
uint8_t *Pixels;
Span DummySpans[2];
void ReadPCX1bit (uint8_t *dst, FileReader & lump, PCXHeader *hdr); void ReadPCX1bit (uint8_t *dst, FileReader & lump, PCXHeader *hdr);
void ReadPCX4bits (uint8_t *dst, FileReader & lump, PCXHeader *hdr); void ReadPCX4bits (uint8_t *dst, FileReader & lump, PCXHeader *hdr);
void ReadPCX8bits (uint8_t *dst, FileReader & lump, PCXHeader *hdr); void ReadPCX8bits (uint8_t *dst, FileReader & lump, PCXHeader *hdr);
void ReadPCX24bits (uint8_t *dst, FileReader & lump, PCXHeader *hdr, int planes); void ReadPCX24bits (uint8_t *dst, FileReader & lump, PCXHeader *hdr, int planes);
virtual void MakeTexture (); uint8_t *MakeTexture (FRenderStyle style) override;
friend class FTexture;
}; };
@ -154,44 +146,12 @@ FTexture * PCXTexture_TryCreate(FileReader & file, int lumpnum)
//========================================================================== //==========================================================================
FPCXTexture::FPCXTexture(int lumpnum, PCXHeader & hdr) FPCXTexture::FPCXTexture(int lumpnum, PCXHeader & hdr)
: FTexture(NULL, lumpnum), Pixels(0) : FWorldTexture(NULL, lumpnum)
{ {
bMasked = false; bMasked = false;
Width = LittleShort(hdr.xmax) - LittleShort(hdr.xmin) + 1; Width = LittleShort(hdr.xmax) - LittleShort(hdr.xmin) + 1;
Height = LittleShort(hdr.ymax) - LittleShort(hdr.ymin) + 1; Height = LittleShort(hdr.ymax) - LittleShort(hdr.ymin) + 1;
CalcBitSize(); CalcBitSize();
DummySpans[0].TopOffset = 0;
DummySpans[0].Length = Height;
DummySpans[1].TopOffset = 0;
DummySpans[1].Length = 0;
}
//==========================================================================
//
//
//
//==========================================================================
FPCXTexture::~FPCXTexture ()
{
Unload ();
}
//==========================================================================
//
//
//
//==========================================================================
void FPCXTexture::Unload ()
{
if (Pixels != NULL)
{
delete[] Pixels;
Pixels = NULL;
}
FTexture::Unload();
} }
//========================================================================== //==========================================================================
@ -211,51 +171,6 @@ FTextureFormat FPCXTexture::GetFormat()
// //
//========================================================================== //==========================================================================
const uint8_t *FPCXTexture::GetColumn (unsigned int column, const Span **spans_out)
{
if (Pixels == NULL)
{
MakeTexture ();
}
if ((unsigned)column >= (unsigned)Width)
{
if (WidthMask + 1 == Width)
{
column &= WidthMask;
}
else
{
column %= Width;
}
}
if (spans_out != NULL)
{
*spans_out = DummySpans;
}
return Pixels + column*Height;
}
//==========================================================================
//
//
//
//==========================================================================
const uint8_t *FPCXTexture::GetPixels ()
{
if (Pixels == NULL)
{
MakeTexture ();
}
return Pixels;
}
//==========================================================================
//
//
//
//==========================================================================
void FPCXTexture::ReadPCX1bit (uint8_t *dst, FileReader & lump, PCXHeader *hdr) void FPCXTexture::ReadPCX1bit (uint8_t *dst, FileReader & lump, PCXHeader *hdr)
{ {
int y, i, bytes; int y, i, bytes;
@ -457,18 +372,19 @@ void FPCXTexture::ReadPCX24bits (uint8_t *dst, FileReader & lump, PCXHeader *hdr
// //
//========================================================================== //==========================================================================
void FPCXTexture::MakeTexture() uint8_t *FPCXTexture::MakeTexture(FRenderStyle style)
{ {
uint8_t PaletteMap[256]; uint8_t PaletteMap[256];
PCXHeader header; PCXHeader header;
int bitcount; int bitcount;
bool alphatex = !!(style.Flags & STYLEF_RedIsAlpha);
auto lump = Wads.OpenLumpReader(SourceLump); auto lump = Wads.OpenLumpReader(SourceLump);
lump.Read(&header, sizeof(header)); lump.Read(&header, sizeof(header));
bitcount = header.bitsPerPixel * header.numColorPlanes; bitcount = header.bitsPerPixel * header.numColorPlanes;
Pixels = new uint8_t[Width*Height]; auto Pixels = new uint8_t[Width*Height];
if (bitcount < 24) if (bitcount < 24)
{ {
@ -476,7 +392,8 @@ void FPCXTexture::MakeTexture()
{ {
for (int i=0;i<16;i++) for (int i=0;i<16;i++)
{ {
PaletteMap[i] = ColorMatcher.Pick(header.palette[i*3],header.palette[i*3+1],header.palette[i*3+2]); if (!alphatex) PaletteMap[i] = ColorMatcher.Pick(header.palette[i * 3], header.palette[i * 3 + 1], header.palette[i * 3 + 2]);
else PaletteMap[i] = header.palette[i * 3];
} }
switch (bitcount) switch (bitcount)
@ -502,7 +419,7 @@ void FPCXTexture::MakeTexture()
uint8_t r = lump.ReadUInt8(); uint8_t r = lump.ReadUInt8();
uint8_t g = lump.ReadUInt8(); uint8_t g = lump.ReadUInt8();
uint8_t b = lump.ReadUInt8(); uint8_t b = lump.ReadUInt8();
PaletteMap[i] = ColorMatcher.Pick(r,g,b); PaletteMap[i] = !alphatex? ColorMatcher.Pick(r,g,b) : r;
} }
lump.Seek(sizeof(header), FileReader::SeekSet); lump.Seek(sizeof(header), FileReader::SeekSet);
ReadPCX8bits (Pixels, lump, &header); ReadPCX8bits (Pixels, lump, &header);
@ -529,12 +446,13 @@ void FPCXTexture::MakeTexture()
{ {
for(int x=0; x < Width; x++) for(int x=0; x < Width; x++)
{ {
Pixels[y+Height*x] = RGB256k.RGB[row[0]>>2][row[1]>>2][row[2]>>2]; Pixels[y + Height * x] = !alphatex? RGB256k.RGB[row[0] >> 2][row[1] >> 2][row[2] >> 2] : row[0];
row+=3; row+=3;
} }
} }
delete [] buffer; delete [] buffer;
} }
return Pixels;
} }
//=========================================================================== //===========================================================================

View file

@ -48,24 +48,21 @@
// //
//========================================================================== //==========================================================================
class FPNGTexture : public FTexture class FPNGTexture : public FWorldTexture
{ {
public: public:
FPNGTexture (FileReader &lump, int lumpnum, const FString &filename, int width, int height, uint8_t bitdepth, uint8_t colortype, uint8_t interlace); FPNGTexture (FileReader &lump, int lumpnum, const FString &filename, int width, int height, uint8_t bitdepth, uint8_t colortype, uint8_t interlace);
~FPNGTexture (); ~FPNGTexture();
const uint8_t *GetColumn (unsigned int column, const Span **spans_out); FTextureFormat GetFormat () override;
const uint8_t *GetPixels (); int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL) override;
void Unload (); bool UseBasePalette() override;
FTextureFormat GetFormat (); uint8_t *MakeTexture(FRenderStyle style) override;
int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL);
bool UseBasePalette();
protected: protected:
void ReadAlphaRemap(FileReader *lump, uint8_t *alpharemap);
FString SourceFile; FString SourceFile;
uint8_t *Pixels;
Span **Spans;
FileReader fr; FileReader fr;
uint8_t BitDepth; uint8_t BitDepth;
@ -74,13 +71,10 @@ protected:
bool HaveTrans; bool HaveTrans;
uint16_t NonPaletteTrans[3]; uint16_t NonPaletteTrans[3];
uint8_t *PaletteMap; uint8_t *PaletteMap = nullptr;
int PaletteSize; int PaletteSize = 0;
uint32_t StartOfIDAT; uint32_t StartOfIDAT = 0;
uint32_t StartOfPalette = 0;
void MakeTexture ();
friend class FTexture;
}; };
@ -200,9 +194,8 @@ FTexture *PNGTexture_CreateFromFile(PNGHandle *png, const FString &filename)
FPNGTexture::FPNGTexture (FileReader &lump, int lumpnum, const FString &filename, int width, int height, FPNGTexture::FPNGTexture (FileReader &lump, int lumpnum, const FString &filename, int width, int height,
uint8_t depth, uint8_t colortype, uint8_t interlace) uint8_t depth, uint8_t colortype, uint8_t interlace)
: FTexture(NULL, lumpnum), SourceFile(filename), Pixels(0), Spans(0), : FWorldTexture(NULL, lumpnum), SourceFile(filename),
BitDepth(depth), ColorType(colortype), Interlace(interlace), HaveTrans(false), BitDepth(depth), ColorType(colortype), Interlace(interlace), HaveTrans(false)
PaletteMap(0), PaletteSize(0), StartOfIDAT(0)
{ {
union union
{ {
@ -265,6 +258,7 @@ FPNGTexture::FPNGTexture (FileReader &lump, int lumpnum, const FString &filename
case MAKE_ID('P','L','T','E'): case MAKE_ID('P','L','T','E'):
PaletteSize = MIN<int> (len / 3, 256); PaletteSize = MIN<int> (len / 3, 256);
StartOfPalette = (uint32_t)lump.Tell();
lump.Read (p.pngpal, PaletteSize * 3); lump.Read (p.pngpal, PaletteSize * 3);
if (PaletteSize * 3 != (int)len) if (PaletteSize * 3 != (int)len)
{ {
@ -284,11 +278,6 @@ FPNGTexture::FPNGTexture (FileReader &lump, int lumpnum, const FString &filename
NonPaletteTrans[1] = uint16_t(trans[2] * 256 + trans[3]); NonPaletteTrans[1] = uint16_t(trans[2] * 256 + trans[3]);
NonPaletteTrans[2] = uint16_t(trans[4] * 256 + trans[5]); NonPaletteTrans[2] = uint16_t(trans[4] * 256 + trans[5]);
break; break;
case MAKE_ID('a','l','P','h'):
bAlphaTexture = true;
bMasked = true;
break;
} }
lump.Seek(4, FileReader::SeekCur); // Skip CRC lump.Seek(4, FileReader::SeekCur); // Skip CRC
lump.Read(&len, 4); lump.Read(&len, 4);
@ -304,20 +293,17 @@ FPNGTexture::FPNGTexture (FileReader &lump, int lumpnum, const FString &filename
// intentional fall-through // intentional fall-through
case 0: // Grayscale case 0: // Grayscale
if (!bAlphaTexture) if (colortype == 0 && HaveTrans && NonPaletteTrans[0] < 256)
{ {
if (colortype == 0 && HaveTrans && NonPaletteTrans[0] < 256) bMasked = true;
{ PaletteSize = 256;
bMasked = true; PaletteMap = new uint8_t[256];
PaletteSize = 256; memcpy (PaletteMap, GrayMap, 256);
PaletteMap = new uint8_t[256]; PaletteMap[NonPaletteTrans[0]] = 0;
memcpy (PaletteMap, GrayMap, 256); }
PaletteMap[NonPaletteTrans[0]] = 0; else
} {
else PaletteMap = GrayMap;
{
PaletteMap = GrayMap;
}
} }
break; break;
@ -354,16 +340,10 @@ FPNGTexture::FPNGTexture (FileReader &lump, int lumpnum, const FString &filename
FPNGTexture::~FPNGTexture () FPNGTexture::~FPNGTexture ()
{ {
Unload (); if (PaletteMap != nullptr && PaletteMap != FTexture::GrayMap)
if (Spans != NULL)
{
FreeSpans (Spans);
Spans = NULL;
}
if (PaletteMap != NULL && PaletteMap != GrayMap)
{ {
delete[] PaletteMap; delete[] PaletteMap;
PaletteMap = NULL; PaletteMap = nullptr;
} }
} }
@ -373,19 +353,6 @@ FPNGTexture::~FPNGTexture ()
// //
//========================================================================== //==========================================================================
void FPNGTexture::Unload ()
{
delete[] Pixels;
Pixels = NULL;
FTexture::Unload();
}
//==========================================================================
//
//
//
//==========================================================================
FTextureFormat FPNGTexture::GetFormat() FTextureFormat FPNGTexture::GetFormat()
{ {
#if 0 #if 0
@ -407,32 +374,18 @@ FTextureFormat FPNGTexture::GetFormat()
// //
//========================================================================== //==========================================================================
const uint8_t *FPNGTexture::GetColumn (unsigned int column, const Span **spans_out) void FPNGTexture::ReadAlphaRemap(FileReader *lump, uint8_t *alpharemap)
{ {
if (Pixels == NULL) auto p = lump->Tell();
lump->Seek(StartOfPalette, FileReader::SeekSet);
for (int i = 0; i < PaletteSize; i++)
{ {
MakeTexture (); uint8_t r = lump->ReadUInt8();
lump->ReadUInt8(); // Skip g and b.
lump->ReadUInt8();
alpharemap[i] = PaletteMap[i] == 0? 0 : r;
} }
if ((unsigned)column >= (unsigned)Width) lump->Seek(p, FileReader::SeekSet);
{
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;
} }
//========================================================================== //==========================================================================
@ -441,26 +394,11 @@ const uint8_t *FPNGTexture::GetColumn (unsigned int column, const Span **spans_o
// //
//========================================================================== //==========================================================================
const uint8_t *FPNGTexture::GetPixels () uint8_t *FPNGTexture::MakeTexture (FRenderStyle style)
{
if (Pixels == NULL)
{
MakeTexture ();
}
return Pixels;
}
//==========================================================================
//
//
//
//==========================================================================
void FPNGTexture::MakeTexture ()
{ {
FileReader *lump; FileReader *lump;
FileReader lfr; FileReader lfr;
bool alphatex = !!(style.Flags & STYLEF_RedIsAlpha);
if (SourceLump >= 0) if (SourceLump >= 0)
{ {
@ -472,7 +410,7 @@ void FPNGTexture::MakeTexture ()
lump = &fr; lump = &fr;
} }
Pixels = new uint8_t[Width*Height]; auto Pixels = new uint8_t[Width*Height];
if (StartOfIDAT == 0) if (StartOfIDAT == 0)
{ {
memset (Pixels, 0x99, Width*Height); memset (Pixels, 0x99, Width*Height);
@ -490,25 +428,37 @@ void FPNGTexture::MakeTexture ()
if (Width == Height) if (Width == Height)
{ {
if (PaletteMap != NULL) if (!alphatex)
{ {
FlipSquareBlockRemap (Pixels, Width, Height, PaletteMap); FTexture::FlipSquareBlockRemap (Pixels, Width, Height, PaletteMap);
}
else if (ColorType == 0)
{
FTexture::FlipSquareBlock (Pixels, Width, Height);
} }
else else
{ {
FlipSquareBlock (Pixels, Width, Height); uint8_t alpharemap[256];
ReadAlphaRemap(lump, alpharemap);
FTexture::FlipSquareBlockRemap(Pixels, Width, Height, alpharemap);
} }
} }
else else
{ {
uint8_t *newpix = new uint8_t[Width*Height]; uint8_t *newpix = new uint8_t[Width*Height];
if (PaletteMap != NULL) if (!alphatex)
{ {
FlipNonSquareBlockRemap (newpix, Pixels, Width, Height, Width, PaletteMap); FTexture::FlipNonSquareBlockRemap (newpix, Pixels, Width, Height, Width, PaletteMap);
}
else if (ColorType == 0)
{
FTexture::FlipNonSquareBlock (newpix, Pixels, Width, Height, Width);
} }
else else
{ {
FlipNonSquareBlock (newpix, Pixels, Width, Height, Width); uint8_t alpharemap[256];
ReadAlphaRemap(lump, alpharemap);
FTexture::FlipNonSquareBlockRemap(newpix, Pixels, Width, Height, Width, alpharemap);
} }
uint8_t *oldpix = Pixels; uint8_t *oldpix = Pixels;
Pixels = newpix; Pixels = newpix;
@ -537,22 +487,13 @@ void FPNGTexture::MakeTexture ()
{ {
for (y = Height; y > 0; --y) for (y = Height; y > 0; --y)
{ {
if (!HaveTrans) if (HaveTrans && in[0] == NonPaletteTrans[0] && in[1] == NonPaletteTrans[1] && in[2] == NonPaletteTrans[2])
{ {
*out++ = RGB256k.RGB[in[0]>>2][in[1]>>2][in[2]>>2]; *out++ = 0;
} }
else else
{ {
if (in[0] == NonPaletteTrans[0] && *out++ = alphatex? in[0] : RGB256k.RGB[in[0]>>2][in[1]>>2][in[2]>>2];
in[1] == NonPaletteTrans[1] &&
in[2] == NonPaletteTrans[2])
{
*out++ = 0;
}
else
{
*out++ = RGB256k.RGB[in[0]>>2][in[1]>>2][in[2]>>2];
}
} }
in += pitch; in += pitch;
} }
@ -563,29 +504,14 @@ void FPNGTexture::MakeTexture ()
case 4: // Grayscale + Alpha case 4: // Grayscale + Alpha
pitch = Width * 2; pitch = Width * 2;
backstep = Height * pitch - 2; backstep = Height * pitch - 2;
if (PaletteMap != NULL) for (x = Width; x > 0; --x)
{ {
for (x = Width; x > 0; --x) for (y = Height; y > 0; --y)
{ {
for (y = Height; y > 0; --y) *out++ = alphatex? ((in[0] * in[1]) >> 8) : in[1] < 128 ? 0 : PaletteMap[in[0]];
{ in += pitch;
*out++ = in[1] < 128 ? 0 : PaletteMap[in[0]];
in += pitch;
}
in -= backstep;
}
}
else
{
for (x = Width; x > 0; --x)
{
for (y = Height; y > 0; --y)
{
*out++ = in[1] < 128 ? 0 : in[0];
in += pitch;
}
in -= backstep;
} }
in -= backstep;
} }
break; break;
@ -596,7 +522,7 @@ void FPNGTexture::MakeTexture ()
{ {
for (y = Height; y > 0; --y) for (y = Height; y > 0; --y)
{ {
*out++ = in[3] < 128 ? 0 : RGB256k.RGB[in[0]>>2][in[1]>>2][in[2]>>2]; *out++ = alphatex? ((in[0] * in[3]) >> 8) : in[3] < 128 ? 0 : RGB256k.RGB[in[0]>>2][in[1]>>2][in[2]>>2];
in += pitch; in += pitch;
} }
in -= backstep; in -= backstep;
@ -606,6 +532,7 @@ void FPNGTexture::MakeTexture ()
delete[] tempix; delete[] tempix;
} }
} }
return Pixels;
} }
//=========================================================================== //===========================================================================

View file

@ -46,21 +46,12 @@
// //
//========================================================================== //==========================================================================
class FRawPageTexture : public FTexture class FRawPageTexture : public FWorldTexture
{ {
public: public:
FRawPageTexture (int lumpnum); FRawPageTexture (int lumpnum);
~FRawPageTexture (); ~FRawPageTexture ();
uint8_t *MakeTexture (FRenderStyle style) override;
const uint8_t *GetColumn (unsigned int column, const Span **spans_out);
const uint8_t *GetPixels ();
void Unload ();
protected:
uint8_t *Pixels;
static const Span DummySpans[2];
void MakeTexture ();
}; };
//========================================================================== //==========================================================================
@ -155,17 +146,6 @@ FTexture *RawPageTexture_TryCreate(FileReader & file, int lumpnum)
} }
//==========================================================================
//
//
//
//==========================================================================
const FTexture::Span FRawPageTexture::DummySpans[2] =
{
{ 0, 200 }, { 0, 0 }
};
//========================================================================== //==========================================================================
// //
// //
@ -173,7 +153,7 @@ const FTexture::Span FRawPageTexture::DummySpans[2] =
//========================================================================== //==========================================================================
FRawPageTexture::FRawPageTexture (int lumpnum) FRawPageTexture::FRawPageTexture (int lumpnum)
: FTexture(NULL, lumpnum), Pixels(0) : FWorldTexture(NULL, lumpnum)
{ {
Width = 320; Width = 320;
Height = 200; Height = 200;
@ -188,79 +168,14 @@ FRawPageTexture::FRawPageTexture (int lumpnum)
// //
//========================================================================== //==========================================================================
FRawPageTexture::~FRawPageTexture () uint8_t *FRawPageTexture::MakeTexture (FRenderStyle style)
{
Unload ();
}
//==========================================================================
//
//
//
//==========================================================================
void FRawPageTexture::Unload ()
{
if (Pixels != NULL)
{
delete[] Pixels;
Pixels = NULL;
}
FTexture::Unload();
}
//==========================================================================
//
//
//
//==========================================================================
const uint8_t *FRawPageTexture::GetColumn (unsigned int column, const Span **spans_out)
{
if (Pixels == NULL)
{
MakeTexture ();
}
if ((unsigned)column >= (unsigned)Width)
{
column %= 320;
}
if (spans_out != NULL)
{
*spans_out = DummySpans;
}
return Pixels + column*Height;
}
//==========================================================================
//
//
//
//==========================================================================
const uint8_t *FRawPageTexture::GetPixels ()
{
if (Pixels == NULL)
{
MakeTexture ();
}
return Pixels;
}
//==========================================================================
//
//
//
//==========================================================================
void FRawPageTexture::MakeTexture ()
{ {
FMemLump lump = Wads.ReadLump (SourceLump); FMemLump lump = Wads.ReadLump (SourceLump);
const uint8_t *source = (const uint8_t *)lump.GetMem(); const uint8_t *source = (const uint8_t *)lump.GetMem();
const uint8_t *source_p = source; const uint8_t *source_p = source;
uint8_t *dest_p; uint8_t *dest_p;
Pixels = new uint8_t[Width*Height]; auto Pixels = new uint8_t[Width*Height];
dest_p = Pixels; dest_p = Pixels;
// Convert the source image from row-major to column-major format // Convert the source image from row-major to column-major format
@ -268,11 +183,12 @@ void FRawPageTexture::MakeTexture ()
{ {
for (int x = 320; x != 0; --x) for (int x = 320; x != 0; --x)
{ {
*dest_p = GPalette.Remap[*source_p]; *dest_p = (style.Flags & STYLEF_RedIsAlpha)? *source_p : GPalette.Remap[*source_p];
dest_p += 200; dest_p += 200;
source_p++; source_p++;
} }
dest_p -= 200*320-1; dest_p -= 200*320-1;
} }
return Pixels;
} }

View file

@ -248,10 +248,6 @@ void FTexture::CalcBitSize ()
HeightBits = i; HeightBits = i;
} }
void FTexture::HackHack (int newheight)
{
}
FTexture::Span **FTexture::CreateSpans (const uint8_t *pixels) const FTexture::Span **FTexture::CreateSpans (const uint8_t *pixels) const
{ {
Span **spans, *span; Span **spans, *span;
@ -554,14 +550,15 @@ void FTexture::GenerateBgraMipmapsFast()
} }
} }
void FTexture::CopyToBlock (uint8_t *dest, int dwidth, int dheight, int xpos, int ypos, int rotate, const uint8_t *translation) void FTexture::CopyToBlock (uint8_t *dest, int dwidth, int dheight, int xpos, int ypos, int rotate, const uint8_t *translation, FRenderStyle style)
{ {
const uint8_t *pixels = GetPixels(); const uint8_t *pixels = GetPixels(/*style*/);
int srcwidth = Width; int srcwidth = Width;
int srcheight = Height; int srcheight = Height;
int step_x = Height; int step_x = Height;
int step_y = 1; int step_y = 1;
FClipRect cr = {0, 0, dwidth, dheight}; FClipRect cr = {0, 0, dwidth, dheight};
if (style.Flags & STYLEF_RedIsAlpha) translation = nullptr; // do not apply translations to alpha textures.
if (ClipCopyPixelRect(&cr, xpos, ypos, pixels, srcwidth, srcheight, step_x, step_y, rotate)) if (ClipCopyPixelRect(&cr, xpos, ypos, pixels, srcwidth, srcheight, step_x, step_y, rotate))
{ {

View file

@ -37,6 +37,7 @@
#include "doomtype.h" #include "doomtype.h"
#include "vectors.h" #include "vectors.h"
#include "r_data/renderstyle.h"
#include <vector> #include <vector>
struct FloatRect struct FloatRect
@ -225,13 +226,15 @@ public:
}; };
// Returns a single column of the texture // Returns a single column of the texture
virtual const uint8_t *GetColumn (unsigned int column, const Span **spans_out) = 0; virtual const uint8_t *GetColumn(unsigned int column, const Span **spans_out) = 0;// delete;
//virtual const uint8_t *GetColumn(FRenderStyle style, unsigned int column, const Span **spans_out) = 0;
// Returns a single column of the texture, in BGRA8 format // Returns a single column of the texture, in BGRA8 format
virtual const uint32_t *GetColumnBgra(unsigned int column, const Span **spans_out); virtual const uint32_t *GetColumnBgra(unsigned int column, const Span **spans_out);
// Returns the whole texture, stored in column-major order // Returns the whole texture, stored in column-major order
virtual const uint8_t *GetPixels () = 0; virtual const uint8_t *GetPixels() = 0;// delete;
//virtual const uint8_t *GetPixels(FRenderStyle style) = 0;
// Returns the whole texture, stored in column-major order, in BGRA8 format // Returns the whole texture, stored in column-major order, in BGRA8 format
virtual const uint32_t *GetPixelsBgra(); virtual const uint32_t *GetPixelsBgra();
@ -277,12 +280,7 @@ public:
virtual void SetFrontSkyLayer(); virtual void SetFrontSkyLayer();
void CopyToBlock (uint8_t *dest, int dwidth, int dheight, int x, int y, const uint8_t *translation=NULL) void CopyToBlock (uint8_t *dest, int dwidth, int dheight, int x, int y, int rotate, const uint8_t *translation, FRenderStyle style);
{
CopyToBlock(dest, dwidth, dheight, x, y, 0, translation);
}
void CopyToBlock (uint8_t *dest, int dwidth, int dheight, int x, int y, int rotate, const uint8_t *translation=NULL);
// Returns true if the next call to GetPixels() will return an image different from the // Returns true if the next call to GetPixels() will return an image different from the
// last call to GetPixels(). This should be considered valid only if a call to CheckModified() // last call to GetPixels(). This should be considered valid only if a call to CheckModified()
@ -307,8 +305,6 @@ public:
PalEntry GetSkyCapColor(bool bottom); PalEntry GetSkyCapColor(bool bottom);
static PalEntry averageColor(const uint32_t *data, int size, int maxout); static PalEntry averageColor(const uint32_t *data, int size, int maxout);
virtual void HackHack (int newheight); // called by FMultipatchTexture to discover corrupt patches.
protected: protected:
uint16_t Width, Height, WidthMask; uint16_t Width, Height, WidthMask;
static uint8_t GrayMap[256]; static uint8_t GrayMap[256];
@ -585,6 +581,24 @@ public:
}; };
}; };
// base class for everything that can be used as a world texture.
// This intermediate class encapsulates the buffers for the software renderer.
class FWorldTexture : public FTexture
{
protected:
uint8_t *Pixeldata[2] = { nullptr, nullptr };
Span **Spandata[2] = { nullptr, nullptr };
FWorldTexture(const char *name = nullptr, int lumpnum = -1);
~FWorldTexture();
// These should not be overridden. If that is needed, a class should inherit from something else
const uint8_t *GetColumn(unsigned int column, const Span **spans_out) override final;
const uint8_t *GetPixels() override final;
void Unload() override final; // should be removed after refactoring.
virtual void MakeTexture() = delete;
virtual uint8_t *MakeTexture(FRenderStyle style) = 0;
};
// A texture that doesn't really exist // A texture that doesn't really exist
class FDummyTexture : public FTexture class FDummyTexture : public FTexture
{ {

View file

@ -76,29 +76,18 @@ struct TGAHeader
// //
//========================================================================== //==========================================================================
class FTGATexture : public FTexture class FTGATexture : public FWorldTexture
{ {
public: public:
FTGATexture (int lumpnum, TGAHeader *); FTGATexture (int lumpnum, TGAHeader *);
~FTGATexture ();
const uint8_t *GetColumn (unsigned int column, const Span **spans_out); FTextureFormat GetFormat () override;
const uint8_t *GetPixels (); int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL) override;
void Unload (); bool UseBasePalette() override;
FTextureFormat GetFormat ();
int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL);
bool UseBasePalette();
protected: protected:
uint8_t *Pixels;
Span **Spans;
void ReadCompressed(FileReader &lump, uint8_t * buffer, int bytesperpixel); void ReadCompressed(FileReader &lump, uint8_t * buffer, int bytesperpixel);
uint8_t *MakeTexture (FRenderStyle style) override;
virtual void MakeTexture ();
friend class FTexture;
}; };
//========================================================================== //==========================================================================
@ -142,7 +131,7 @@ FTexture *TGATexture_TryCreate(FileReader & file, int lumpnum)
//========================================================================== //==========================================================================
FTGATexture::FTGATexture (int lumpnum, TGAHeader * hdr) FTGATexture::FTGATexture (int lumpnum, TGAHeader * hdr)
: FTexture(NULL, lumpnum), Pixels(0), Spans(0) : FWorldTexture(NULL, lumpnum)
{ {
Wads.GetLumpName (Name, lumpnum); Wads.GetLumpName (Name, lumpnum);
Width = hdr->width; Width = hdr->width;
@ -158,38 +147,6 @@ FTGATexture::FTGATexture (int lumpnum, TGAHeader * hdr)
// //
//========================================================================== //==========================================================================
FTGATexture::~FTGATexture ()
{
Unload ();
if (Spans != NULL)
{
FreeSpans (Spans);
Spans = NULL;
}
}
//==========================================================================
//
//
//
//==========================================================================
void FTGATexture::Unload ()
{
if (Pixels != NULL)
{
delete[] Pixels;
Pixels = NULL;
}
FTexture::Unload();
}
//==========================================================================
//
//
//
//==========================================================================
FTextureFormat FTGATexture::GetFormat() FTextureFormat FTGATexture::GetFormat()
{ {
return TEX_RGB; return TEX_RGB;
@ -201,55 +158,6 @@ FTextureFormat FTGATexture::GetFormat()
// //
//========================================================================== //==========================================================================
const uint8_t *FTGATexture::GetColumn (unsigned int column, const Span **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;
}
//==========================================================================
//
//
//
//==========================================================================
const uint8_t *FTGATexture::GetPixels ()
{
if (Pixels == NULL)
{
MakeTexture ();
}
return Pixels;
}
//==========================================================================
//
//
//
//==========================================================================
void FTGATexture::ReadCompressed(FileReader &lump, uint8_t * buffer, int bytesperpixel) void FTGATexture::ReadCompressed(FileReader &lump, uint8_t * buffer, int bytesperpixel)
{ {
uint8_t data[4]; uint8_t data[4];
@ -286,7 +194,7 @@ void FTGATexture::ReadCompressed(FileReader &lump, uint8_t * buffer, int bytespe
// //
//========================================================================== //==========================================================================
void FTGATexture::MakeTexture () uint8_t *FTGATexture::MakeTexture (FRenderStyle style)
{ {
uint8_t PaletteMap[256]; uint8_t PaletteMap[256];
auto lump = Wads.OpenLumpReader (SourceLump); auto lump = Wads.OpenLumpReader (SourceLump);
@ -294,8 +202,9 @@ void FTGATexture::MakeTexture ()
uint16_t w; uint16_t w;
uint8_t r,g,b,a; uint8_t r,g,b,a;
uint8_t * buffer; uint8_t * buffer;
bool alphatex = !!(style.Flags & STYLEF_RedIsAlpha);
Pixels = new uint8_t[Width*Height]; auto Pixels = new uint8_t[Width*Height];
lump.Read(&hdr, sizeof(hdr)); lump.Read(&hdr, sizeof(hdr));
lump.Seek(hdr.id_len, FileReader::SeekCur); lump.Seek(hdr.id_len, FileReader::SeekCur);
@ -339,7 +248,7 @@ void FTGATexture::MakeTexture ()
r=g=b=a=0; r=g=b=a=0;
break; break;
} }
PaletteMap[i] = a>=128? ColorMatcher.Pick(r, g, b) : 0; PaletteMap[i] = !alphatex? (a>=128? ColorMatcher.Pick(r, g, b) : 0) : (r * a) >> 8;
} }
} }
@ -397,8 +306,8 @@ void FTGATexture::MakeTexture ()
uint16_t * p = (uint16_t*)(ptr + y * Pitch); uint16_t * p = (uint16_t*)(ptr + y * Pitch);
for(int x=0;x<Width;x++) for(int x=0;x<Width;x++)
{ {
int v = LittleLong(*p); int v = LittleShort(*p);
Pixels[x*Height+y] = RGB256k.RGB[((v>>10) & 0x1f)*2][((v>>5) & 0x1f)*2][(v & 0x1f)*2]; Pixels[x*Height + y] = !alphatex ? RGB256k.RGB[((v >> 10) & 0x1f) * 2][((v >> 5) & 0x1f) * 2][(v & 0x1f) * 2] : ((v >> 10) & 0x1f) * 8;
p+=step_x; p+=step_x;
} }
} }
@ -410,7 +319,7 @@ void FTGATexture::MakeTexture ()
uint8_t * p = ptr + y * Pitch; uint8_t * p = ptr + y * Pitch;
for(int x=0;x<Width;x++) for(int x=0;x<Width;x++)
{ {
Pixels[x*Height+y] = RGB256k.RGB[p[2]>>2][p[1]>>2][p[0]>>2]; Pixels[x*Height + y] = !alphatex ? RGB256k.RGB[p[2] >> 2][p[1] >> 2][p[0] >> 2] : p[2];
p+=step_x; p+=step_x;
} }
} }
@ -424,7 +333,7 @@ void FTGATexture::MakeTexture ()
uint8_t * p = ptr + y * Pitch; uint8_t * p = ptr + y * Pitch;
for(int x=0;x<Width;x++) for(int x=0;x<Width;x++)
{ {
Pixels[x*Height+y] = RGB256k.RGB[p[2]>>2][p[1]>>2][p[0]>>2]; Pixels[x*Height + y] = !alphatex ? RGB256k.RGB[p[2] >> 2][p[1] >> 2][p[0] >> 2] : p[2];
p+=step_x; p+=step_x;
} }
} }
@ -436,7 +345,7 @@ void FTGATexture::MakeTexture ()
uint8_t * p = ptr + y * Pitch; uint8_t * p = ptr + y * Pitch;
for(int x=0;x<Width;x++) for(int x=0;x<Width;x++)
{ {
Pixels[x*Height+y] = p[3] >= 128? RGB256k.RGB[p[2]>>2][p[1]>>2][p[0]>>2] : 0; Pixels[x*Height + y] = !alphatex ? (p[3] >= 128 ? RGB256k.RGB[p[2] >> 2][p[1] >> 2][p[0] >> 2] : 0) : (p[2] * p[3]) >> 8;
p+=step_x; p+=step_x;
} }
} }
@ -457,7 +366,7 @@ void FTGATexture::MakeTexture ()
uint8_t * p = ptr + y * Pitch; uint8_t * p = ptr + y * Pitch;
for(int x=0;x<Width;x++) for(int x=0;x<Width;x++)
{ {
Pixels[x*Height+y] = GrayMap[*p]; Pixels[x*Height+y] = !alphatex? FTexture::GrayMap[*p] : *p;
p+=step_x; p+=step_x;
} }
} }
@ -469,7 +378,7 @@ void FTGATexture::MakeTexture ()
uint8_t * p = ptr + y * Pitch; uint8_t * p = ptr + y * Pitch;
for(int x=0;x<Width;x++) for(int x=0;x<Width;x++)
{ {
Pixels[x*Height+y] = GrayMap[p[1]]; // only use the high byte Pixels[x*Height+y] = !alphatex ? FTexture::GrayMap[p[1]] : p[1]; // only use the high byte
p+=step_x; p+=step_x;
} }
} }
@ -484,6 +393,7 @@ void FTGATexture::MakeTexture ()
break; break;
} }
delete [] buffer; delete [] buffer;
return Pixels;
} }
//=========================================================================== //===========================================================================