diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e75798a54..cfd970d6d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1110,6 +1110,7 @@ set (PCH_SOURCES textures/tgatexture.cpp textures/warptexture.cpp textures/skyboxtexture.cpp + textures/worldtexture.cpp xlat/parse_xlat.cpp fragglescript/t_func.cpp fragglescript/t_load.cpp diff --git a/src/gl/textures/gl_texture.cpp b/src/gl/textures/gl_texture.cpp index 0d3e84e4b..0680ccdd6 100644 --- a/src/gl/textures/gl_texture.cpp +++ b/src/gl/textures/gl_texture.cpp @@ -523,24 +523,11 @@ FBrightmapTexture::FBrightmapTexture (FTexture *source) SourceLump = -1; } -FBrightmapTexture::~FBrightmapTexture () -{ -} - -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 () +uint8_t *FBrightmapTexture::MakeTexture(FRenderStyle style) { + // 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) diff --git a/src/gl/textures/gl_texture.h b/src/gl/textures/gl_texture.h index 80eede02f..44016f181 100644 --- a/src/gl/textures/gl_texture.h +++ b/src/gl/textures/gl_texture.h @@ -4,23 +4,17 @@ #include "r_defs.h" #include "textures/textures.h" -class FBrightmapTexture : public FTexture +class FBrightmapTexture : public FWorldTexture { public: FBrightmapTexture (FTexture *source); - ~FBrightmapTexture (); - 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); - bool UseBasePalette() { return false; } + uint8_t *MakeTexture(FRenderStyle style) override; + int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf) override; + bool UseBasePalette() override { return false; } protected: FTexture *SourcePic; - //uint8_t *Pixels; - //Span **Spans; }; diff --git a/src/r_data/models/models_voxel.cpp b/src/r_data/models/models_voxel.cpp index 848f5a54d..9533aca69 100644 --- a/src/r_data/models/models_voxel.cpp +++ b/src/r_data/models/models_voxel.cpp @@ -53,23 +53,17 @@ // //=========================================================================== -class FVoxelTexture : public FTexture +class FVoxelTexture : public FWorldTexture { public: - 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); - bool UseBasePalette() { return false; } + int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf) override; + bool UseBasePalette() override { return false; } + uint8_t *MakeTexture(FRenderStyle style) override; protected: FVoxel *SourceVox; - uint8_t *Pixels; - }; //=========================================================================== @@ -86,7 +80,6 @@ FVoxelTexture::FVoxelTexture(FVoxel *vox) WidthBits = 4; HeightBits = 4; WidthMask = 15; - Pixels = NULL; gl_info.bNoFilter = true; gl_info.bNoCompress = true; } @@ -97,54 +90,32 @@ FVoxelTexture::FVoxelTexture(FVoxel *vox) // //=========================================================================== -FVoxelTexture::~FVoxelTexture() -{ -} - -const uint8_t *FVoxelTexture::GetColumn (unsigned int column, const Span **spans_out) -{ - // not needed - return NULL; -} - -const uint8_t *FVoxelTexture::GetPixels () +uint8_t *FVoxelTexture::MakeTexture (FRenderStyle style) { // 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]; - - uint8_t *pp = SourceVox->Palette; - - if(pp != NULL) + for(int i=0;i<256;i++, pp+=3) { - for(int i=0;i<256;i++, pp+=3) - { - PalEntry pe; - pe.r = (pp[0] << 2) | (pp[0] >> 4); - pe.g = (pp[1] << 2) | (pp[1] >> 4); - pe.b = (pp[2] << 2) | (pp[2] >> 4); - Pixels[i] = ColorMatcher.Pick(pe); - } + PalEntry pe; + pe.r = (pp[0] << 2) | (pp[0] >> 4); + pe.g = (pp[1] << 2) | (pp[1] >> 4); + pe.b = (pp[2] << 2) | (pp[2] >> 4); + // Alphatexture handling is just for completeness, but rather unlikely to be used ever. + Pixels[i] = (style.Flags & STYLEF_RedIsAlpha)? pe.r : ColorMatcher.Pick(pe); } - else - { - for(int i=0;i<256;i++, pp+=3) - { - Pixels[i] = (uint8_t)i; - } - } } - return Pixels; -} - -void FVoxelTexture::Unload () -{ - if (Pixels != NULL) + else { - delete[] Pixels; - Pixels = NULL; - } + for(int i=0;i<256;i++, pp+=3) + { + Pixels[i] = (uint8_t)i; + } + } + return Pixels; } //=========================================================================== diff --git a/src/swrenderer/line/r_walldraw.cpp b/src/swrenderer/line/r_walldraw.cpp index 5b7518440..ac277a0ae 100644 --- a/src/swrenderer/line/r_walldraw.cpp +++ b/src/swrenderer/line/r_walldraw.cpp @@ -330,7 +330,6 @@ namespace swrenderer if (rw_pic->UseType == FTexture::TEX_Null) return; - rw_pic->GetHeight(); // To ensure that rw_pic->HeightBits has been set int fracbits = 32 - rw_pic->HeightBits; if (fracbits == 32) { // Hack for one pixel tall textures diff --git a/src/textures/automaptexture.cpp b/src/textures/automaptexture.cpp index 3bd16f5bc..27080669e 100644 --- a/src/textures/automaptexture.cpp +++ b/src/textures/automaptexture.cpp @@ -38,6 +38,7 @@ #include "doomtype.h" #include "files.h" #include "w_wad.h" +#include "v_palette.h" #include "textures/textures.h" //========================================================================== @@ -46,21 +47,12 @@ // //========================================================================== -class FAutomapTexture : public FTexture +class FAutomapTexture : public FWorldTexture { public: + FAutomapTexture(int lumpnum); ~FAutomapTexture (); - - 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]; + uint8_t *MakeTexture (FRenderStyle style); }; @@ -86,16 +78,11 @@ FTexture *AutomapTexture_TryCreate(FileReader &data, int lumpnum) //========================================================================== FAutomapTexture::FAutomapTexture (int lumpnum) -: FTexture(NULL, lumpnum), Pixels(NULL) +: FWorldTexture(NULL, lumpnum) { Width = 320; Height = uint16_t(Wads.LumpLength(lumpnum) / 320); 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 () -{ - Unload (); -} - -//========================================================================== -// -// -// -//========================================================================== - -void FAutomapTexture::Unload () -{ - if (Pixels != NULL) - { - delete[] Pixels; - Pixels = NULL; - } - FTexture::Unload(); -} - -//========================================================================== -// -// -// -//========================================================================== - -void FAutomapTexture::MakeTexture () +uint8_t *FAutomapTexture::MakeTexture (FRenderStyle style) { int x, y; FMemLump data = Wads.ReadLump (SourceLump); 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 (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; } -//========================================================================== -// -// -// -//========================================================================== - -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; -} diff --git a/src/textures/bitmap.cpp b/src/textures/bitmap.cpp index cdeb645e3..33cfe2141 100644 --- a/src/textures/bitmap.cpp +++ b/src/textures/bitmap.cpp @@ -193,13 +193,14 @@ typedef void (*CopyFunc)(uint8_t *pout, const uint8_t *pin, int count, int step, iCopyColors, \ iCopyColors, \ iCopyColors, \ + iCopyColors, \ iCopyColors, \ iCopyColors, \ iCopyColors, \ iCopyColors, \ iCopyColors \ } -static const CopyFunc copyfuncs[][10]={ +static const CopyFunc copyfuncs[][11]={ COPY_FUNCS(bCopy), COPY_FUNCS(bBlend), COPY_FUNCS(bAdd), diff --git a/src/textures/bitmap.h b/src/textures/bitmap.h index 0811eaa70..51d857ac4 100644 --- a/src/textures/bitmap.h +++ b/src/textures/bitmap.h @@ -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; } }; +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 { static __forceinline unsigned char R(const unsigned char * p) { return p[2]; } @@ -310,6 +319,7 @@ enum ColorType CF_RGBA, CF_IA, CF_CMYK, + CF_YCbCr, CF_BGR, CF_BGRA, CF_I16, diff --git a/src/textures/ddstexture.cpp b/src/textures/ddstexture.cpp index 9cde88ced..313682f14 100644 --- a/src/textures/ddstexture.cpp +++ b/src/textures/ddstexture.cpp @@ -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: FDDSTexture (FileReader &lump, int lumpnum, void *surfdesc); - ~FDDSTexture (); - const uint8_t *GetColumn (unsigned int column, const Span **spans_out); - const uint8_t *GetPixels (); - void Unload (); - FTextureFormat GetFormat (); + FTextureFormat GetFormat () override; + uint8_t *MakeTexture(FRenderStyle style) override; protected: - - uint8_t *Pixels; - Span **Spans; - uint32_t Format; uint32_t RMask, GMask, BMask, AMask; @@ -180,11 +179,10 @@ protected: static void CalcBitShift (uint32_t mask, uint8_t *lshift, uint8_t *rshift); - void MakeTexture (); - void ReadRGB (FileReader &lump, uint8_t *tcbuf = NULL); - void DecompressDXT1 (FileReader &lump, uint8_t *tcbuf = NULL); - void DecompressDXT3 (FileReader &lump, bool premultiplied, uint8_t *tcbuf = NULL); - void DecompressDXT5 (FileReader &lump, bool premultiplied, uint8_t *tcbuf = NULL); + void ReadRGB (FileReader &lump, uint8_t *buffer, int pixelmode); + void DecompressDXT1 (FileReader &lump, uint8_t *buffer, int pixelmode); + void DecompressDXT3 (FileReader &lump, bool premultiplied, uint8_t *buffer, int pixelmode); + void DecompressDXT5 (FileReader &lump, bool premultiplied, uint8_t *buffer, int pixelmode); int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL); bool UseBasePalette(); @@ -287,7 +285,7 @@ FTexture *DDSTexture_TryCreate (FileReader &data, int lumpnum) //========================================================================== FDDSTexture::FDDSTexture (FileReader &lump, int lumpnum, void *vsurfdesc) -: FTexture(NULL, lumpnum), Pixels(0), Spans(0) +: FWorldTexture(NULL, lumpnum) { 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() { #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) - { - 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 lump = Wads.OpenLumpReader (SourceLump); -//========================================================================== -// -// -// -//========================================================================== + auto Pixels = new uint8_t[Width*Height]; -const uint8_t *FDDSTexture::GetPixels () -{ - if (Pixels == NULL) + lump.Seek (sizeof(DDSURFACEDESC2) + 4, FileReader::SeekSet); + + 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; } //========================================================================== // -// +// Note that pixel size == 8 is column-major, but 32 is row-major! // //========================================================================== -void FDDSTexture::MakeTexture () -{ - 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) +void FDDSTexture::ReadRGB (FileReader &lump, uint8_t *buffer, int pixelmode) { uint32_t x, y; 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) { 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); for (x = Width; x > 0; --x) { @@ -548,14 +467,21 @@ void FDDSTexture::ReadRGB (FileReader &lump, uint8_t *tcbuf) { c = *buffp++; } - if (!tcbuf) + if (pixelmode != PIX_ARGB) { if (amask == 0 || (c & amask)) { uint32_t r = (c & RMask) << RShiftL; r |= r >> RShiftR; - 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]; + if (pixelmode == PIX_Palette) + { + 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 { @@ -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; uint8_t *blockbuff = new uint8_t[blocklinelen]; uint8_t *block; 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; color[0].a = 255; @@ -639,9 +565,12 @@ void FDDSTexture::DecompressDXT1 (FileReader &lump, uint8_t *tcbuf) bMasked = true; } // 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. for (y = 0; y < 4; ++y) @@ -658,13 +587,13 @@ void FDDSTexture::DecompressDXT1 (FileReader &lump, uint8_t *tcbuf) break; } 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 { - 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[1] = color[ci].g; 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; uint8_t *blockbuff = new uint8_t[blocklinelen]; uint8_t *block; PalEntry color[4]; - uint8_t palcol[4]; + uint8_t palcol[4] = { 0,0,0,0 }; int ox, oy, x, y, i; 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; // 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. for (y = 0; y < 4; ++y) { @@ -738,14 +671,14 @@ void FDDSTexture::DecompressDXT3 (FileReader &lump, bool premultiplied, uint8_t { 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]; } 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; tcp[0] = color[c].r; 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; uint8_t *blockbuff = new uint8_t[blocklinelen]; uint8_t *block; PalEntry color[4]; - uint8_t palcol[4]; + uint8_t palcol[4] = { 0,0,0,0 }; uint32_t yalphaslice = 0; 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; // 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. for (y = 0; y < 4; ++y) @@ -851,14 +787,14 @@ void FDDSTexture::DecompressDXT5 (FileReader &lump, bool premultiplied, uint8_t { 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]; } 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; tcp[0] = color[c].r; 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 { - ReadRGB (lump, TexBuffer); + ReadRGB (lump, TexBuffer, PIX_ARGB); } else if (Format == ID_DXT1) { - DecompressDXT1 (lump, TexBuffer); + DecompressDXT1 (lump, TexBuffer, PIX_ARGB); } 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) { - DecompressDXT5 (lump, Format == ID_DXT4, TexBuffer); + DecompressDXT5 (lump, Format == ID_DXT4, TexBuffer, PIX_ARGB); } // All formats decompress to RGBA. diff --git a/src/textures/emptytexture.cpp b/src/textures/emptytexture.cpp index 45039cae2..19698551f 100644 --- a/src/textures/emptytexture.cpp +++ b/src/textures/emptytexture.cpp @@ -1,7 +1,8 @@ /* -** flattexture.cpp +** emptytexture.cpp ** Texture class for empty placeholder textures ** (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 @@ -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: FEmptyTexture (int lumpnum); - - 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]; + uint8_t *MakeTexture(FRenderStyle style) override; }; - - //========================================================================== // -// 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) -: FTexture(NULL, lumpnum) +: FWorldTexture(NULL, lumpnum) { bMasked = true; WidthBits = HeightBits = 1; Width = Height = 1; WidthMask = 0; - DummySpans[0].TopOffset = 0; - DummySpans[0].Length = 0; - Pixels[0] = 0; + PixelsAreStatic = 3; } //========================================================================== @@ -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) - { - *spans_out = DummySpans; - } - return Pixels; -} - -//========================================================================== -// -// -// -//========================================================================== - -const uint8_t *FEmptyTexture::GetPixels () -{ - return Pixels; + return &Pixel; } diff --git a/src/textures/flattexture.cpp b/src/textures/flattexture.cpp index 408acb099..7581b3a6e 100644 --- a/src/textures/flattexture.cpp +++ b/src/textures/flattexture.cpp @@ -45,24 +45,11 @@ // //========================================================================== -class FFlatTexture : public FTexture +class FFlatTexture : public FWorldTexture { public: FFlatTexture (int lumpnum); - ~FFlatTexture (); - - 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; + uint8_t *MakeTexture (FRenderStyle style) override; }; @@ -86,7 +73,7 @@ FTexture *FlatTexture_TryCreate(FileReader & file, int lumpnum) //========================================================================== FFlatTexture::FFlatTexture (int lumpnum) -: FTexture(NULL, lumpnum), Pixels(0) +: FWorldTexture(NULL, lumpnum) { int area; int bits; @@ -108,10 +95,6 @@ FFlatTexture::FFlatTexture (int lumpnum) WidthBits = HeightBits = bits; Width = Height = 1 << bits; 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 () -{ - 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 () +uint8_t *FFlatTexture::MakeTexture (FRenderStyle style) { 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); if (numread < Width*Height) { 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; } diff --git a/src/textures/imgztexture.cpp b/src/textures/imgztexture.cpp index 1f623d084..e21074055 100644 --- a/src/textures/imgztexture.cpp +++ b/src/textures/imgztexture.cpp @@ -36,6 +36,7 @@ #include "doomtype.h" #include "files.h" #include "w_wad.h" +#include "v_palette.h" #include "textures/textures.h" @@ -47,7 +48,7 @@ // //========================================================================== -class FIMGZTexture : public FTexture +class FIMGZTexture : public FWorldTexture { struct ImageHeader { @@ -62,18 +63,7 @@ class FIMGZTexture : public FTexture public: FIMGZTexture (int lumpnum, uint16_t w, uint16_t h, int16_t l, int16_t t); - ~FIMGZTexture (); - - 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 (); + uint8_t *MakeTexture (FRenderStyle style) override; }; @@ -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) - : FTexture(NULL, lumpnum), Pixels(0), Spans(0) + : FWorldTexture(NULL, lumpnum) { Wads.GetLumpName (Name, lumpnum); Width = w; @@ -122,88 +112,7 @@ FIMGZTexture::FIMGZTexture (int lumpnum, uint16_t w, uint16_t h, int16_t l, int1 // //========================================================================== -FIMGZTexture::~FIMGZTexture () -{ - 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 () +uint8_t *FIMGZTexture::MakeTexture (FRenderStyle style) { FMemLump lump = Wads.ReadLump (SourceLump); const ImageHeader *imgz = (const ImageHeader *)lump.GetMem(); @@ -222,7 +131,7 @@ void FIMGZTexture::MakeTexture () int dest_rew = Width * Height - 1; CalcBitSize (); - Pixels = new uint8_t[Width*Height]; + auto Pixels = new uint8_t[Width*Height]; dest_p = Pixels; // 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) { - *dest_p = *data; + auto p = *data; + *dest_p = (style.Flags & STYLEF_RedIsAlpha) ? p : GPalette.Remap[p]; dest_p += dest_adv; data++; } @@ -251,8 +161,8 @@ void FIMGZTexture::MakeTexture () { if (runlen != 0) { - uint8_t color = *data; - *dest_p = color; + auto p = *data; + *dest_p = (style.Flags & STYLEF_RedIsAlpha) ? p : GPalette.Remap[p]; dest_p += dest_adv; data++; x--; @@ -282,5 +192,6 @@ void FIMGZTexture::MakeTexture () dest_p -= dest_rew; } } + return Pixels; } diff --git a/src/textures/jpegtexture.cpp b/src/textures/jpegtexture.cpp index c9f19c1da..abf1e34ec 100644 --- a/src/textures/jpegtexture.cpp +++ b/src/textures/jpegtexture.cpp @@ -179,27 +179,16 @@ void JPEG_OutputMessage (j_common_ptr cinfo) // //========================================================================== -class FJPEGTexture : public FTexture +class FJPEGTexture : public FWorldTexture { public: FJPEGTexture (int lumpnum, int width, int height); ~FJPEGTexture (); - const uint8_t *GetColumn (unsigned int column, const Span **spans_out); - const uint8_t *GetPixels (); - void Unload (); - FTextureFormat GetFormat (); - 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; + FTextureFormat GetFormat () override; + int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL) override; + bool UseBasePalette() override; + uint8_t *MakeTexture (FRenderStyle style) override; }; //========================================================================== @@ -259,7 +248,7 @@ FTexture *JPEGTexture_TryCreate(FileReader & data, int lumpnum) //========================================================================== FJPEGTexture::FJPEGTexture (int lumpnum, int width, int height) -: FTexture(NULL, lumpnum), Pixels(0) +: FWorldTexture(NULL, lumpnum) { UseType = TEX_MiscPatch; LeftOffset = 0; @@ -269,35 +258,6 @@ FJPEGTexture::FJPEGTexture (int lumpnum, int width, int height) Width = width; Height = height; 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) -{ - 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 () +uint8_t *FJPEGTexture::MakeTexture (FRenderStyle style) { auto lump = Wads.OpenLumpReader (SourceLump); JSAMPLE *buff = NULL; + bool doalpha = !!(style.Flags & STYLEF_RedIsAlpha); jpeg_decompress_struct cinfo; jpeg_error_mgr jerr; - Pixels = new uint8_t[Width * Height]; + auto Pixels = new uint8_t[Width * Height]; memset (Pixels, 0xBA, Width * Height); cinfo.err = jpeg_std_error(&jerr); cinfo.err->output_message = JPEG_OutputMessage; cinfo.err->error_exit = JPEG_ErrorExit; jpeg_create_decompress(&cinfo); + + FLumpSourceMgr sourcemgr(&lump, &cinfo); try { - FLumpSourceMgr sourcemgr(&lump, &cinfo); jpeg_read_header(&cinfo, TRUE); 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_GRAYSCALE && cinfo.num_components == 1))) + (cinfo.out_color_space == JCS_CMYK && cinfo.num_components == 4) || + (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"); - throw -1; + Printf(TEXTCOLOR_ORANGE, "Unsupported color format in %s\n", Wads.GetLumpFullPath(SourceLump).GetChars()); } - - jpeg_start_decompress(&cinfo); - - int y = 0; - buff = new uint8_t[cinfo.output_width * cinfo.output_components]; - - while (cinfo.output_scanline < cinfo.output_height) + else { - int num_scanlines = jpeg_read_scanlines(&cinfo, &buff, 1); - uint8_t *in = buff; - uint8_t *out = Pixels + y; - switch (cinfo.out_color_space) + jpeg_start_decompress(&cinfo); + + int y = 0; + buff = new uint8_t[cinfo.output_width * cinfo.output_components]; + + while (cinfo.output_scanline < cinfo.output_height) { - case JCS_RGB: - for (int x = Width; x > 0; --x) + int num_scanlines = jpeg_read_scanlines(&cinfo, &buff, 1); + 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]; - out += Height; - in += 3; - } - break; + case JCS_RGB: + for (int x = Width; x > 0; --x) + { + *out = !doalpha? RGB256k.RGB[in[0] >> 2][in[1] >> 2][in[2] >> 2] : in[0]; + out += Height; + in += 3; + } + break; - case JCS_GRAYSCALE: - for (int x = Width; x > 0; --x) - { - *out = GrayMap[in[0]]; - out += Height; - in += 1; - } - break; + case JCS_GRAYSCALE: + for (int x = Width; x > 0; --x) + { + *out = !doalpha ? FTexture::GrayMap[in[0]] : in[0]; + out += Height; + in += 1; + } + break; - case JCS_CMYK: - // What are you doing using a CMYK image? :) - for (int x = Width; x > 0; --x) - { - // To be precise, these calculations should use 255, but - // 256 is much faster and virtually indistinguishable. - int r = in[3] - (((256-in[0])*in[3]) >> 8); - int g = in[3] - (((256-in[1])*in[3]) >> 8); - int b = in[3] - (((256-in[2])*in[3]) >> 8); - *out = RGB256k.RGB[r >> 2][g >> 2][b >> 2]; - out += Height; - in += 4; - } - break; + case JCS_CMYK: + // What are you doing using a CMYK image? :) + for (int x = Width; x > 0; --x) + { + // To be precise, these calculations should use 255, but + // 256 is much faster and virtually indistinguishable. + int r = in[3] - (((256 - in[0])*in[3]) >> 8); + if (!doalpha) + { + int g = in[3] - (((256 - in[1])*in[3]) >> 8); + int b = in[3] - (((256 - in[2])*in[3]) >> 8); + *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; + case JCS_YCbCr: + // Probably useless but since I had the formula available... + for (int x = Width; x > 0; --x) + { + 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) { - Printf (TEXTCOLOR_ORANGE " in texture %s\n", Name.GetChars()); - jpeg_destroy_decompress(&cinfo); + Printf(TEXTCOLOR_ORANGE, "JPEG error in %s\n", Wads.GetLumpFullPath(SourceLump).GetChars()); } + jpeg_destroy_decompress(&cinfo); if (buff != NULL) { 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; jpeg_create_decompress(&cinfo); + FLumpSourceMgr sourcemgr(&lump, &cinfo); try { - FLumpSourceMgr sourcemgr(&lump, &cinfo); jpeg_read_header(&cinfo, TRUE); 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_GRAYSCALE && cinfo.num_components == 1))) + (cinfo.out_color_space == JCS_CMYK && cinfo.num_components == 4) || + (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"); - throw -1; + Printf(TEXTCOLOR_ORANGE, "Unsupported color format in %s\n", Wads.GetLumpFullPath(SourceLump).GetChars()); } - jpeg_start_decompress(&cinfo); - - int yc = 0; - buff = new uint8_t[cinfo.output_height * cinfo.output_width * cinfo.output_components]; - - - while (cinfo.output_scanline < cinfo.output_height) + else { - uint8_t * ptr = buff + cinfo.output_width * cinfo.output_components * yc; - jpeg_read_scanlines(&cinfo, &ptr, 1); - yc++; + jpeg_start_decompress(&cinfo); + + 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); if (buff != NULL) delete [] buff; diff --git a/src/textures/multipatchtexture.cpp b/src/textures/multipatchtexture.cpp index e5beb246f..e2bf932e9 100644 --- a/src/textures/multipatchtexture.cpp +++ b/src/textures/multipatchtexture.cpp @@ -148,24 +148,21 @@ struct FPatchLookup // //========================================================================== -class FMultiPatchTexture : public FTexture +class FMultiPatchTexture : public FWorldTexture { public: FMultiPatchTexture (const void *texdef, FPatchLookup *patchlookup, int maxpatchnum, bool strife, int deflump); FMultiPatchTexture (FScanner &sc, int usetype); ~FMultiPatchTexture (); - const uint8_t *GetColumn (unsigned int column, const Span **spans_out); - const uint8_t *GetPixels (); - FTextureFormat GetFormat(); - bool UseBasePalette() ; - void Unload (); - virtual void SetFrontSkyLayer (); + FTextureFormat GetFormat() override; + bool UseBasePalette() override; + virtual void SetFrontSkyLayer () override; - int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL); - int GetSourceLump() { return DefinitionLump; } - FTexture *GetRedirect(bool wantwarped); - FTexture *GetRawTexture(); + int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL) override; + int GetSourceLump() override { return DefinitionLump; } + FTexture *GetRedirect(bool wantwarped) override; + FTexture *GetRawTexture() override; void ResolvePatches(); protected: @@ -201,7 +198,7 @@ protected: bool bRedirect:1; bool bTranslucentPatches:1; - void MakeTexture (); + uint8_t *MakeTexture (FRenderStyle style); private: void CheckForHacks (); @@ -323,11 +320,6 @@ FMultiPatchTexture::~FMultiPatchTexture () delete[] Inits; Inits = nullptr; } - if (Spans != NULL) - { - FreeSpans (Spans); - Spans = NULL; - } } //========================================================================== @@ -345,80 +337,6 @@ void FMultiPatchTexture::SetFrontSkyLayer () bNoRemap0 = true; } -//========================================================================== -// -// FMultiPatchTexture :: Unload -// -//========================================================================== - -void FMultiPatchTexture::Unload () -{ - if (Pixels != NULL) - { - delete[] Pixels; - Pixels = NULL; - } - FTexture::Unload(); -} - -//========================================================================== -// -// FMultiPatchTexture :: GetPixels -// -//========================================================================== - -const uint8_t *FMultiPatchTexture::GetPixels () -{ - if (bRedirect) - { - return Parts->Texture->GetPixels (); - } - if (Pixels == NULL) - { - MakeTexture (); - } - return Pixels; -} - -//========================================================================== -// -// FMultiPatchTexture :: GetColumn -// -//========================================================================== - -const uint8_t *FMultiPatchTexture::GetColumn (unsigned int column, const Span **spans_out) -{ - if (bRedirect) - { - return Parts->Texture->GetColumn (column, spans_out); - } - if (Pixels == NULL) - { - MakeTexture (); - } - if ((unsigned)column >= (unsigned)Width) - { - if (WidthMask + 1 == Width) - { - column &= WidthMask; - } - else - { - column %= Width; - } - } - if (spans_out != NULL) - { - if (Spans == NULL) - { - Spans = CreateSpans (Pixels); - } - *spans_out = Spans[column]; - } - return Pixels + column*Height; -} - - //========================================================================== // // GetBlendMap @@ -427,7 +345,6 @@ const uint8_t *FMultiPatchTexture::GetColumn (unsigned int column, const Span ** uint8_t *GetBlendMap(PalEntry blend, uint8_t *blendwork) { - switch (blend.a==0 ? int(blend) : -1) { case BLEND_ICEMAP: @@ -480,39 +397,54 @@ uint8_t *GetBlendMap(PalEntry blend, uint8_t *blendwork) // //========================================================================== -void FMultiPatchTexture::MakeTexture () +uint8_t *FMultiPatchTexture::MakeTexture (FRenderStyle style) { // Add a little extra space at the end if the texture's height is not // a power of 2, in case somebody accidentally makes it repeat vertically. int numpix = Width * Height + (1 << HeightBits) - Height; uint8_t blendwork[256]; - bool hasTranslucent = false; + bool buildrgb = bComplex; - Pixels = new uint8_t[numpix]; + auto Pixels = new uint8_t[numpix]; memset (Pixels, 0, numpix); - for (int i = 0; i < NumParts; ++i) + if (style.Flags & STYLEF_RedIsAlpha) { - if (Parts[i].op != OP_COPY) + // The rules here are as follows: + // A texture uses its palette index as alpha only if it reports to use the base palette. + // In summary this means: + // If a texture is marked 'complex', it will use the red channel. + // If a texture uses non-base-palette patches, it will use the red channel for all pixels, even those coming from a base palette patch. + // If a texture only uses base-palette patches and no compositing effects it will use the palette index. + // + buildrgb = !UseBasePalette(); + } + else + { + // For regular textures we can use paletted compositing if all patches are just being copied because they all can create a paletted buffer. + if (!buildrgb) for (int i = 0; i < NumParts; ++i) { - hasTranslucent = true; + if (Parts[i].op != OP_COPY) + { + buildrgb = true; + } } } - if (!hasTranslucent) - { + if (!buildrgb) + { for (int i = 0; i < NumParts; ++i) { if (Parts[i].Texture->bHasCanvas) continue; // cannot use camera textures as patch. - uint8_t *trans = Parts[i].Translation ? Parts[i].Translation->Remap : NULL; + uint8_t *trans = Parts[i].Translation? Parts[i].Translation->Remap : nullptr; { if (Parts[i].Blend != 0) { trans = GetBlendMap(Parts[i].Blend, blendwork); } Parts[i].Texture->CopyToBlock (Pixels, Width, Height, - Parts[i].OriginX, Parts[i].OriginY, Parts[i].Rotate, trans); + Parts[i].OriginX, Parts[i].OriginY, Parts[i].Rotate, trans, style); } } } @@ -531,7 +463,7 @@ void FMultiPatchTexture::MakeTexture () { if (*out == 0 && in[3] != 0) { - *out = RGB256k.RGB[in[2]>>2][in[1]>>2][in[0]>>2]; + *out = (style.Flags & STYLEF_RedIsAlpha)? in[2]*in[3] : RGB256k.RGB[in[2]>>2][in[1]>>2][in[0]>>2]; } out += Height; in += 4; @@ -539,6 +471,7 @@ void FMultiPatchTexture::MakeTexture () } delete [] buffer; } + return Pixels; } //=========================================================================== @@ -755,14 +688,6 @@ void FMultiPatchTexture::CheckForHacks () break; } } - - if (i == NumParts) - { - for (i = 0; i < NumParts; ++i) - { - Parts[i].Texture->HackHack(256); - } - } } } diff --git a/src/textures/patchtexture.cpp b/src/textures/patchtexture.cpp index c964b9a53..b4a8e3909 100644 --- a/src/textures/patchtexture.cpp +++ b/src/textures/patchtexture.cpp @@ -39,6 +39,7 @@ #include "templates.h" #include "v_palette.h" #include "textures/textures.h" +#include "r_data/r_translate.h" // 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: FPatchTexture (int lumpnum, patch_t *header); - ~FPatchTexture (); - - 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); + uint8_t *MakeTexture (FRenderStyle style) override; + void DetectBadPatches(); }; //========================================================================== @@ -149,12 +139,13 @@ FTexture *PatchTexture_TryCreate(FileReader & file, int lumpnum) //========================================================================== FPatchTexture::FPatchTexture (int lumpnum, patch_t * header) -: FTexture(NULL, lumpnum), Pixels(0), Spans(0), hackflag(false) +: FWorldTexture(NULL, lumpnum) { Width = header->width; Height = header->height; LeftOffset = header->leftoffset; TopOffset = header->topoffset; + DetectBadPatches(); CalcBitSize (); } @@ -164,89 +155,7 @@ FPatchTexture::FPatchTexture (int lumpnum, patch_t * header) // //========================================================================== -FPatchTexture::~FPatchTexture () -{ - 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 *FPatchTexture::MakeTexture (FRenderStyle style) { uint8_t *remap, remaptable[256]; int numspans; @@ -258,23 +167,11 @@ void FPatchTexture::MakeTexture () maxcol = (const column_t *)((const uint8_t *)patch + Wads.LumpLength (SourceLump) - 3); - // Check for badly-sized patches -#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) + if (style.Flags & STYLEF_RedIsAlpha) { - lump = Wads.ReadLump ("-BADPATC"); - patch = (const patch_t *)lump.GetMem(); - Printf (PRINT_BOLD, "Patch %s has a non-positive size.\n", Name); + remap = translationtables[TRANSLATION_Standard][8]->Remap; } - else if (LittleShort(patch->width) > 2048 || LittleShort(patch->height) > 2048) - { - lump = Wads.ReadLump ("-BADPATC"); - patch = (const patch_t *)lump.GetMem(); - Printf (PRINT_BOLD, "Patch %s is too big.\n", Name); - } -#endif - - if (bNoRemap0) + else if (bNoRemap0) { memcpy (remaptable, GPalette.Remap, 256); 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; // Draw the image to the buffer @@ -302,7 +199,7 @@ void FPatchTexture::MakeTexture () out++, in++; } } - return; + return Pixels; } // Add a little extra space at the end if the texture's height is not @@ -311,7 +208,7 @@ void FPatchTexture::MakeTexture () numspans = Width; - Pixels = new uint8_t[numpix]; + auto Pixels = new uint8_t[numpix]; memset (Pixels, 0, numpix); // Draw the image to the buffer @@ -355,6 +252,7 @@ void FPatchTexture::MakeTexture () 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. // It must be 256 pixels tall, and all its columns must have exactly // 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])); 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); if (col->topdelta != 0xFF) { - break; // More than one post in a column! + return; // More than one post in a column! } } - if (x == x2) - { - // If all the columns were checked, it needs fixing. - Unload (); - if (Spans != NULL) - { - FreeSpans (Spans); - } - - Height = newheight; - LeftOffset = 0; - TopOffset = 0; - - hackflag = true; - bMasked = false; // Hacked textures don't have transparent parts. - } + LeftOffset = 0; + TopOffset = 0; + badflag = true; + bMasked = false; // Hacked textures don't have transparent parts. } } diff --git a/src/textures/pcxtexture.cpp b/src/textures/pcxtexture.cpp index 75331caa5..efe12e3c2 100644 --- a/src/textures/pcxtexture.cpp +++ b/src/textures/pcxtexture.cpp @@ -81,32 +81,24 @@ struct PCXHeader // //========================================================================== -class FPCXTexture : public FTexture +class FPCXTexture : public FWorldTexture { public: FPCXTexture (int lumpnum, PCXHeader &); ~FPCXTexture (); - const uint8_t *GetColumn (unsigned int column, const Span **spans_out); - const uint8_t *GetPixels (); - void Unload (); - FTextureFormat GetFormat (); + FTextureFormat GetFormat () override; - int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL); - bool UseBasePalette(); + int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL) override; + bool UseBasePalette() override; protected: - uint8_t *Pixels; - Span DummySpans[2]; - void ReadPCX1bit (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 ReadPCX24bits (uint8_t *dst, FileReader & lump, PCXHeader *hdr, int planes); - virtual void MakeTexture (); - - friend class FTexture; + uint8_t *MakeTexture (FRenderStyle style) override; }; @@ -154,44 +146,12 @@ FTexture * PCXTexture_TryCreate(FileReader & file, int lumpnum) //========================================================================== FPCXTexture::FPCXTexture(int lumpnum, PCXHeader & hdr) -: FTexture(NULL, lumpnum), Pixels(0) +: FWorldTexture(NULL, lumpnum) { bMasked = false; Width = LittleShort(hdr.xmax) - LittleShort(hdr.xmin) + 1; Height = LittleShort(hdr.ymax) - LittleShort(hdr.ymin) + 1; 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) { 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]; PCXHeader header; int bitcount; + bool alphatex = !!(style.Flags & STYLEF_RedIsAlpha); auto lump = Wads.OpenLumpReader(SourceLump); lump.Read(&header, sizeof(header)); bitcount = header.bitsPerPixel * header.numColorPlanes; - Pixels = new uint8_t[Width*Height]; + auto Pixels = new uint8_t[Width*Height]; if (bitcount < 24) { @@ -476,7 +392,8 @@ void FPCXTexture::MakeTexture() { 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) @@ -502,7 +419,7 @@ void FPCXTexture::MakeTexture() uint8_t r = lump.ReadUInt8(); uint8_t g = 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); ReadPCX8bits (Pixels, lump, &header); @@ -529,12 +446,13 @@ void FPCXTexture::MakeTexture() { 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; } } delete [] buffer; } + return Pixels; } //=========================================================================== diff --git a/src/textures/pngtexture.cpp b/src/textures/pngtexture.cpp index 480502c33..00a7ba701 100644 --- a/src/textures/pngtexture.cpp +++ b/src/textures/pngtexture.cpp @@ -48,24 +48,21 @@ // //========================================================================== -class FPNGTexture : public FTexture +class FPNGTexture : public FWorldTexture { public: 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); - const uint8_t *GetPixels (); - void Unload (); - FTextureFormat GetFormat (); - int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL); - bool UseBasePalette(); + FTextureFormat GetFormat () override; + int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL) override; + bool UseBasePalette() override; + uint8_t *MakeTexture(FRenderStyle style) override; protected: + void ReadAlphaRemap(FileReader *lump, uint8_t *alpharemap); FString SourceFile; - uint8_t *Pixels; - Span **Spans; FileReader fr; uint8_t BitDepth; @@ -74,13 +71,10 @@ protected: bool HaveTrans; uint16_t NonPaletteTrans[3]; - uint8_t *PaletteMap; - int PaletteSize; - uint32_t StartOfIDAT; - - void MakeTexture (); - - friend class FTexture; + uint8_t *PaletteMap = nullptr; + int PaletteSize = 0; + uint32_t StartOfIDAT = 0; + uint32_t StartOfPalette = 0; }; @@ -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, uint8_t depth, uint8_t colortype, uint8_t interlace) -: FTexture(NULL, lumpnum), SourceFile(filename), Pixels(0), Spans(0), - BitDepth(depth), ColorType(colortype), Interlace(interlace), HaveTrans(false), - PaletteMap(0), PaletteSize(0), StartOfIDAT(0) +: FWorldTexture(NULL, lumpnum), SourceFile(filename), + BitDepth(depth), ColorType(colortype), Interlace(interlace), HaveTrans(false) { union { @@ -265,6 +258,7 @@ FPNGTexture::FPNGTexture (FileReader &lump, int lumpnum, const FString &filename case MAKE_ID('P','L','T','E'): PaletteSize = MIN (len / 3, 256); + StartOfPalette = (uint32_t)lump.Tell(); lump.Read (p.pngpal, PaletteSize * 3); 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[2] = uint16_t(trans[4] * 256 + trans[5]); break; - - case MAKE_ID('a','l','P','h'): - bAlphaTexture = true; - bMasked = true; - break; } lump.Seek(4, FileReader::SeekCur); // Skip CRC lump.Read(&len, 4); @@ -304,20 +293,17 @@ FPNGTexture::FPNGTexture (FileReader &lump, int lumpnum, const FString &filename // intentional fall-through case 0: // Grayscale - if (!bAlphaTexture) + if (colortype == 0 && HaveTrans && NonPaletteTrans[0] < 256) { - if (colortype == 0 && HaveTrans && NonPaletteTrans[0] < 256) - { - bMasked = true; - PaletteSize = 256; - PaletteMap = new uint8_t[256]; - memcpy (PaletteMap, GrayMap, 256); - PaletteMap[NonPaletteTrans[0]] = 0; - } - else - { - PaletteMap = GrayMap; - } + bMasked = true; + PaletteSize = 256; + PaletteMap = new uint8_t[256]; + memcpy (PaletteMap, GrayMap, 256); + PaletteMap[NonPaletteTrans[0]] = 0; + } + else + { + PaletteMap = GrayMap; } break; @@ -354,16 +340,10 @@ FPNGTexture::FPNGTexture (FileReader &lump, int lumpnum, const FString &filename FPNGTexture::~FPNGTexture () { - Unload (); - if (Spans != NULL) - { - FreeSpans (Spans); - Spans = NULL; - } - if (PaletteMap != NULL && PaletteMap != GrayMap) + if (PaletteMap != nullptr && PaletteMap != FTexture::GrayMap) { delete[] PaletteMap; - PaletteMap = NULL; + PaletteMap = nullptr; } } @@ -373,19 +353,6 @@ FPNGTexture::~FPNGTexture () // //========================================================================== -void FPNGTexture::Unload () -{ - delete[] Pixels; - Pixels = NULL; - FTexture::Unload(); -} - -//========================================================================== -// -// -// -//========================================================================== - FTextureFormat FPNGTexture::GetFormat() { #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) - { - 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; + lump->Seek(p, FileReader::SeekSet); } //========================================================================== @@ -441,26 +394,11 @@ const uint8_t *FPNGTexture::GetColumn (unsigned int column, const Span **spans_o // //========================================================================== -const uint8_t *FPNGTexture::GetPixels () -{ - if (Pixels == NULL) - { - MakeTexture (); - } - return Pixels; -} - - -//========================================================================== -// -// -// -//========================================================================== - -void FPNGTexture::MakeTexture () +uint8_t *FPNGTexture::MakeTexture (FRenderStyle style) { FileReader *lump; FileReader lfr; + bool alphatex = !!(style.Flags & STYLEF_RedIsAlpha); if (SourceLump >= 0) { @@ -472,7 +410,7 @@ void FPNGTexture::MakeTexture () lump = &fr; } - Pixels = new uint8_t[Width*Height]; + auto Pixels = new uint8_t[Width*Height]; if (StartOfIDAT == 0) { memset (Pixels, 0x99, Width*Height); @@ -490,25 +428,37 @@ void FPNGTexture::MakeTexture () 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 { - FlipSquareBlock (Pixels, Width, Height); + uint8_t alpharemap[256]; + ReadAlphaRemap(lump, alpharemap); + FTexture::FlipSquareBlockRemap(Pixels, Width, Height, alpharemap); } } else { 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 { - 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; Pixels = newpix; @@ -537,22 +487,13 @@ void FPNGTexture::MakeTexture () { 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 { - if (in[0] == NonPaletteTrans[0] && - in[1] == NonPaletteTrans[1] && - in[2] == NonPaletteTrans[2]) - { - *out++ = 0; - } - else - { - *out++ = RGB256k.RGB[in[0]>>2][in[1]>>2][in[2]>>2]; - } + *out++ = alphatex? in[0] : RGB256k.RGB[in[0]>>2][in[1]>>2][in[2]>>2]; } in += pitch; } @@ -563,29 +504,14 @@ void FPNGTexture::MakeTexture () case 4: // Grayscale + Alpha pitch = Width * 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++ = 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; + *out++ = alphatex? ((in[0] * in[1]) >> 8) : in[1] < 128 ? 0 : PaletteMap[in[0]]; + in += pitch; } + in -= backstep; } break; @@ -596,7 +522,7 @@ void FPNGTexture::MakeTexture () { 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 -= backstep; @@ -606,6 +532,7 @@ void FPNGTexture::MakeTexture () delete[] tempix; } } + return Pixels; } //=========================================================================== diff --git a/src/textures/rawpagetexture.cpp b/src/textures/rawpagetexture.cpp index 99354bb66..7e9268c6e 100644 --- a/src/textures/rawpagetexture.cpp +++ b/src/textures/rawpagetexture.cpp @@ -46,21 +46,12 @@ // //========================================================================== -class FRawPageTexture : public FTexture +class FRawPageTexture : public FWorldTexture { public: FRawPageTexture (int lumpnum); ~FRawPageTexture (); - - 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 (); + uint8_t *MakeTexture (FRenderStyle style) override; }; //========================================================================== @@ -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) -: FTexture(NULL, lumpnum), Pixels(0) +: FWorldTexture(NULL, lumpnum) { Width = 320; Height = 200; @@ -188,79 +168,14 @@ FRawPageTexture::FRawPageTexture (int lumpnum) // //========================================================================== -FRawPageTexture::~FRawPageTexture () -{ - 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 () +uint8_t *FRawPageTexture::MakeTexture (FRenderStyle style) { FMemLump lump = Wads.ReadLump (SourceLump); const uint8_t *source = (const uint8_t *)lump.GetMem(); const uint8_t *source_p = source; uint8_t *dest_p; - Pixels = new uint8_t[Width*Height]; + auto Pixels = new uint8_t[Width*Height]; dest_p = Pixels; // 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) { - *dest_p = GPalette.Remap[*source_p]; + *dest_p = (style.Flags & STYLEF_RedIsAlpha)? *source_p : GPalette.Remap[*source_p]; dest_p += 200; source_p++; } dest_p -= 200*320-1; } + return Pixels; } diff --git a/src/textures/texture.cpp b/src/textures/texture.cpp index 212f53a03..154efb222 100644 --- a/src/textures/texture.cpp +++ b/src/textures/texture.cpp @@ -248,10 +248,6 @@ void FTexture::CalcBitSize () HeightBits = i; } -void FTexture::HackHack (int newheight) -{ -} - FTexture::Span **FTexture::CreateSpans (const uint8_t *pixels) const { 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 srcheight = Height; int step_x = Height; int step_y = 1; 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)) { diff --git a/src/textures/textures.h b/src/textures/textures.h index 006d24bb7..0aede4562 100644 --- a/src/textures/textures.h +++ b/src/textures/textures.h @@ -37,6 +37,7 @@ #include "doomtype.h" #include "vectors.h" +#include "r_data/renderstyle.h" #include struct FloatRect @@ -225,13 +226,15 @@ public: }; // 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 virtual const uint32_t *GetColumnBgra(unsigned int column, const Span **spans_out); // 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 virtual const uint32_t *GetPixelsBgra(); @@ -277,12 +280,7 @@ public: virtual void SetFrontSkyLayer(); - void CopyToBlock (uint8_t *dest, int dwidth, int dheight, int x, int y, const uint8_t *translation=NULL) - { - 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); + void CopyToBlock (uint8_t *dest, int dwidth, int dheight, int x, int y, int rotate, const uint8_t *translation, FRenderStyle style); // 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() @@ -307,8 +305,6 @@ public: PalEntry GetSkyCapColor(bool bottom); static PalEntry averageColor(const uint32_t *data, int size, int maxout); - virtual void HackHack (int newheight); // called by FMultipatchTexture to discover corrupt patches. - protected: uint16_t Width, Height, WidthMask; 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 class FDummyTexture : public FTexture { diff --git a/src/textures/tgatexture.cpp b/src/textures/tgatexture.cpp index 97e381e6b..4b6430837 100644 --- a/src/textures/tgatexture.cpp +++ b/src/textures/tgatexture.cpp @@ -76,29 +76,18 @@ struct TGAHeader // //========================================================================== -class FTGATexture : public FTexture +class FTGATexture : public FWorldTexture { public: FTGATexture (int lumpnum, TGAHeader *); - ~FTGATexture (); - const uint8_t *GetColumn (unsigned int column, const Span **spans_out); - const uint8_t *GetPixels (); - void Unload (); - FTextureFormat GetFormat (); - - int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL); - bool UseBasePalette(); + FTextureFormat GetFormat () override; + int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL) override; + bool UseBasePalette() override; protected: - uint8_t *Pixels; - Span **Spans; - void ReadCompressed(FileReader &lump, uint8_t * buffer, int bytesperpixel); - - virtual void MakeTexture (); - - friend class FTexture; + uint8_t *MakeTexture (FRenderStyle style) override; }; //========================================================================== @@ -142,7 +131,7 @@ FTexture *TGATexture_TryCreate(FileReader & file, int lumpnum) //========================================================================== FTGATexture::FTGATexture (int lumpnum, TGAHeader * hdr) -: FTexture(NULL, lumpnum), Pixels(0), Spans(0) +: FWorldTexture(NULL, lumpnum) { Wads.GetLumpName (Name, lumpnum); 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() { 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) { 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]; auto lump = Wads.OpenLumpReader (SourceLump); @@ -294,8 +202,9 @@ void FTGATexture::MakeTexture () uint16_t w; uint8_t r,g,b,a; 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.Seek(hdr.id_len, FileReader::SeekCur); @@ -339,7 +248,7 @@ void FTGATexture::MakeTexture () r=g=b=a=0; 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); for(int x=0;x>10) & 0x1f)*2][((v>>5) & 0x1f)*2][(v & 0x1f)*2]; + int v = LittleShort(*p); + 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; } } @@ -410,7 +319,7 @@ void FTGATexture::MakeTexture () uint8_t * p = ptr + y * Pitch; for(int x=0;x>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; } } @@ -424,7 +333,7 @@ void FTGATexture::MakeTexture () uint8_t * p = ptr + y * Pitch; for(int x=0;x>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; } } @@ -436,7 +345,7 @@ void FTGATexture::MakeTexture () uint8_t * p = ptr + y * Pitch; for(int x=0;x= 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; } } @@ -457,7 +366,7 @@ void FTGATexture::MakeTexture () uint8_t * p = ptr + y * Pitch; for(int x=0;x