diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 58ca6a9ba..cfd970d6d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -639,6 +639,12 @@ elseif( FLUIDSYNTH_FOUND ) add_definitions( -DHAVE_FLUIDSYNTH ) endif() +option( SEND_ANON_STATS "Enable sending of anonymous hardware statistics" ON ) + +if( NOT SEND_ANON_STATS ) + add_definitions( -DNO_SEND_STATS ) +endif() + # Project files should be aware of the header files. We can GLOB these since # there's generally a new cpp for every header so this file will get changed if( WIN32 ) @@ -1104,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/am_map.cpp b/src/am_map.cpp index c6e6ba19b..2f6c04c6d 100644 --- a/src/am_map.cpp +++ b/src/am_map.cpp @@ -3088,7 +3088,7 @@ static void DrawMarker (FTexture *tex, double x, double y, int yadjust, DTA_TranslationIndex, translation, DTA_Alpha, alpha, DTA_FillColor, fillcolor, - DTA_RenderStyle, uint32_t(renderstyle), + DTA_RenderStyle, renderstyle.AsDWORD, TAG_DONE); } diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index 76bcc1931..a3e2773af 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -564,6 +564,8 @@ static void stripwhite (char *str) static char *igets (void) { + assert(PatchPt != nullptr); + char *line; if (*PatchPt == '\0' || PatchPt >= PatchFile + PatchSize ) @@ -2536,7 +2538,7 @@ static bool DoDehPatch() cont = 0; if (0 == strncmp (PatchFile, "Patch File for DeHackEd v", 25)) { - if (PatchFile[25] < '3' && PatchFile[25] != '2' && PatchFile[27] != '3') + if (PatchFile[25] < '3' && (PatchFile[25] < '2' || PatchFile[27] < '3')) { Printf (PRINT_BOLD, "\"%s\" is an old and unsupported DeHackEd patch\n", PatchName); delete[] PatchName; @@ -2550,16 +2552,16 @@ static bool DoDehPatch() } PatchPt = strchr (PatchFile, '\n'); - while ((cont = GetLine()) == 1) + while (PatchPt != nullptr && (cont = GetLine()) == 1) { CHECKKEY ("Doom version", dversion) else CHECKKEY ("Patch format", pversion) } if (!cont || dversion == -1 || pversion == -1) { + Printf (PRINT_BOLD, "\"%s\" is not a DeHackEd patch file\n", PatchName); delete[] PatchName; delete[] PatchFile; - Printf (PRINT_BOLD, "\"%s\" is not a DeHackEd patch file\n", PatchFile); return false; } } diff --git a/src/d_main.cpp b/src/d_main.cpp index 6338f9b04..007af39d5 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -2352,6 +2352,9 @@ void D_DoomMain (void) D_DoomInit(); + extern void D_ConfirmSendStats(); + D_ConfirmSendStats(); + // [RH] Make sure zdoom.pk3 is always loaded, // as it contains magic stuff we need. wad = BaseFileSearch (BASEWAD, NULL, true); diff --git a/src/d_net.cpp b/src/d_net.cpp index 57dbb93b7..7681626d0 100644 --- a/src/d_net.cpp +++ b/src/d_net.cpp @@ -1914,6 +1914,10 @@ void TryRunTics (void) // Check possible stall conditions Net_CheckLastReceived (counts); + // Update time returned by I_GetTime, but only if we are stuck in this loop + if (lowtic < gametic + counts) + I_SetFrameTime(); + // don't stay in here forever -- give the menu a chance to work if (I_GetTime () - entertic >= 1) { diff --git a/src/d_stats.cpp b/src/d_stats.cpp index ebec250bb..e6c0e196b 100644 --- a/src/d_stats.cpp +++ b/src/d_stats.cpp @@ -1,3 +1,16 @@ + +#ifdef NO_SEND_STATS + +void D_DoAnonStats() +{ +} + +void D_ConfirmSendStats() +{ +} + +#else // !NO_SEND_STATS + #if defined(_WIN32) #define _WIN32_WINNT 0x0501 #define WIN32_LEAN_AND_MEAN @@ -5,6 +18,11 @@ #include extern int sys_ostype; #else +#ifdef __APPLE__ +#include +#else // !__APPLE__ +#include +#endif // __APPLE__ #include #include #include @@ -20,12 +38,13 @@ extern int sys_ostype; EXTERN_CVAR(Bool, vid_glswfb) extern int currentrenderer; +CVAR(Int, sys_statsenabled, -1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOSET) CVAR(String, sys_statshost, "gzstats.drdteam.org", CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_NOSET) CVAR(Int, sys_statsport, 80, CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_NOSET) // Each machine will only send two reports, one when started with hardware rendering and one when started with software rendering. -#define CHECKVERSION 330 -#define CHECKVERSIONSTR "330" +#define CHECKVERSION 331 +#define CHECKVERSIONSTR "331" CVAR(Int, sentstats_swr_done, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOSET) CVAR(Int, sentstats_hwr_done, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOSET) @@ -48,6 +67,11 @@ bool I_HTTPRequest(const char* request) SOCKET Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); struct hostent *host; host = gethostbyname(sys_statshost.GetHumanString()); + if (host == nullptr) + { + DPrintf(DMSG_ERROR, "Error looking up hostname.\n"); + return false; + } SOCKADDR_IN SockAddr; SockAddr.sin_port = htons(sys_statsport); SockAddr.sin_family = AF_INET; @@ -113,18 +137,15 @@ bool I_HTTPRequest(const char* request) return false; } - char buffer[1024]; - sprintf(buffer, "%s", request); - Printf("Buffer: %s", buffer); - n = write(sockfd, (char*)buffer, (int)strlen(request)); + n = write(sockfd, request, strlen(request)); if (n<0) { DPrintf(DMSG_ERROR, "Error writing to socket.\n"); close(sockfd); return false; } - bzero(buffer, 1024); + char buffer[1024] = {}; n = read(sockfd, buffer, 1023); close(sockfd); DPrintf(DMSG_NOTIFY, "Stats send successful.\n"); @@ -185,12 +206,49 @@ static int GetOSVersion() #endif } + +#ifdef _WIN32 + +static int GetCoreInfo() +{ + PSYSTEM_LOGICAL_PROCESSOR_INFORMATION buffer = NULL; + PSYSTEM_LOGICAL_PROCESSOR_INFORMATION ptr = NULL; + DWORD returnLength = 0; + int cores = 0; + uint32_t byteOffset = 0; + + auto rc = GetLogicalProcessorInformation(buffer, &returnLength); + + if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) + { + buffer = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)malloc(returnLength); + if (!GetLogicalProcessorInformation(buffer, &returnLength)) return 0; + } + else + { + return 0; + } + + ptr = buffer; + + while (byteOffset + sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION) <= returnLength) + { + if (ptr->Relationship == RelationProcessorCore) cores++; + byteOffset += sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION); + ptr++; + } + free(buffer); + return cores < 2 ? 0 : cores < 4 ? 1 : cores < 6 ? 2 : cores < 8 ? 3 : 4; +} + +#else static int GetCoreInfo() { int cores = std::thread::hardware_concurrency(); if (CPU.HyperThreading) cores /= 2; return cores < 2? 0 : cores < 4? 1 : cores < 6? 2 : cores < 8? 3 : 4; } +#endif static int GetRenderInfo() { @@ -227,6 +285,11 @@ static void D_DoHTTPRequest(const char *request) void D_DoAnonStats() { + if (sys_statsenabled != 1) + { + return; + } + static bool done = false; // do this only once per session. if (done) return; done = true; @@ -236,9 +299,62 @@ void D_DoAnonStats() if (currentrenderer == 1 && sentstats_hwr_done >= CHECKVERSION) return; static char requeststring[1024]; - sprintf(requeststring, "GET /stats.php?render=%i&cores=%i&os=%i HTTP/1.1\nHost: %s\nConnection: close\nUser-Agent: %s %s\n\n", - GetRenderInfo(), GetCoreInfo(), GetOSVersion(), sys_statshost.GetHumanString(), GAMENAME, VERSIONSTR); + mysnprintf(requeststring, sizeof requeststring, "GET /stats.py?render=%i&cores=%i&os=%i&renderconfig=%i HTTP/1.1\nHost: %s\nConnection: close\nUser-Agent: %s %s\n\n", + GetRenderInfo(), GetCoreInfo(), GetOSVersion(), currentrenderer, sys_statshost.GetHumanString(), GAMENAME, VERSIONSTR); DPrintf(DMSG_NOTIFY, "Sending %s", requeststring); std::thread t1(D_DoHTTPRequest, requeststring); t1.detach(); } + +void D_ConfirmSendStats() +{ + if (sys_statsenabled >= 0) + { + return; + } + + // TODO: texts + static const char *const MESSAGE_TEXT = "send stats?"; + static const char *const TITLE_TEXT = GAMENAME; + + UCVarValue enabled = { 0 }; + +#ifdef _WIN32 + extern HWND Window; + enabled.Int = MessageBox(Window, MESSAGE_TEXT, TITLE_TEXT, MB_ICONQUESTION | MB_YESNO) == IDYES; +#elif defined __APPLE__ + const CFStringRef messageString = CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, MESSAGE_TEXT, kCFStringEncodingASCII, kCFAllocatorNull); + const CFStringRef titleString = CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, TITLE_TEXT, kCFStringEncodingASCII, kCFAllocatorNull); + if (messageString != nullptr && titleString != nullptr) + { + CFOptionFlags response; + const SInt32 result = CFUserNotificationDisplayAlert(0, kCFUserNotificationNoteAlertLevel, nullptr, nullptr, nullptr, + titleString, messageString, CFSTR("Yes"), CFSTR("No"), nullptr, &response); + enabled.Int = result == 0 && (response & 3) == kCFUserNotificationDefaultResponse; + CFRelease(titleString); + CFRelease(messageString); + } +#else // !__APPLE__ + const SDL_MessageBoxButtonData buttons[] = + { + { SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT, 0, "Yes" }, + { SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT, 1, "No" }, + }; + const SDL_MessageBoxData messageboxdata = + { + SDL_MESSAGEBOX_INFORMATION, + nullptr, + TITLE_TEXT, + MESSAGE_TEXT, + SDL_arraysize(buttons), + buttons, + nullptr + }; + int buttonid; + enabled.Int = SDL_ShowMessageBox(&messageboxdata, &buttonid) == 0 && buttonid == 0; +#endif // _WIN32 + + sys_statsenabled.ForceSet(enabled, CVAR_Int); +} + +#endif // NO_SEND_STATS diff --git a/src/files.h b/src/files.h index 096452269..89e6a091d 100644 --- a/src/files.h +++ b/src/files.h @@ -201,56 +201,56 @@ public: uint8_t ReadUInt8() { - uint8_t v; + uint8_t v = 0; Read(&v, 1); return v; } int8_t ReadInt8() { - int8_t v; + int8_t v = 0; Read(&v, 1); return v; } uint16_t ReadUInt16() { - uint16_t v; + uint16_t v = 0; Read(&v, 2); return LittleShort(v); } int16_t ReadInt16() { - uint16_t v; + uint16_t v = 0; Read(&v, 2); return LittleShort(v); } uint32_t ReadUInt32() { - uint32_t v; + uint32_t v = 0; Read(&v, 4); return LittleLong(v); } int32_t ReadInt32() { - uint32_t v; + uint32_t v = 0; Read(&v, 4); return LittleLong(v); } uint32_t ReadUInt32BE() { - uint32_t v; + uint32_t v = 0; Read(&v, 4); return BigLong(v); } int32_t ReadInt32BE() { - uint32_t v; + uint32_t v = 0; Read(&v, 4); return BigLong(v); } diff --git a/src/g_inventory/a_pickups.cpp b/src/g_inventory/a_pickups.cpp index ff98ea421..2ed33954b 100644 --- a/src/g_inventory/a_pickups.cpp +++ b/src/g_inventory/a_pickups.cpp @@ -82,6 +82,7 @@ DEFINE_FIELD(AInventory, MaxAmount) DEFINE_FIELD(AInventory, InterHubAmount) DEFINE_FIELD(AInventory, RespawnTics) DEFINE_FIELD(AInventory, Icon) +DEFINE_FIELD(AInventory, AltHUDIcon) DEFINE_FIELD(AInventory, DropTime) DEFINE_FIELD(AInventory, SpawnPointClass) DEFINE_FIELD(AInventory, PickupFlash) @@ -147,6 +148,7 @@ void AInventory::Serialize(FSerializer &arc) ("respawntics", RespawnTics, def->RespawnTics) ("itemflags", ItemFlags, def->ItemFlags) ("icon", Icon, def->Icon) + ("althudicon", AltHUDIcon, def->AltHUDIcon) ("pickupsound", PickupSound, def->PickupSound) ("spawnpointclass", SpawnPointClass, def->SpawnPointClass) ("droptime", DropTime, def->DropTime); diff --git a/src/gl/textures/gl_material.cpp b/src/gl/textures/gl_material.cpp index 859706772..98f0559d9 100644 --- a/src/gl/textures/gl_material.cpp +++ b/src/gl/textures/gl_material.cpp @@ -31,6 +31,7 @@ #include "r_utility.h" #include "templates.h" #include "sc_man.h" +#include "r_data/renderstyle.h" #include "colormatcher.h" #include "textures/warpbuffer.h" #include "textures/bitmap.h" @@ -297,7 +298,7 @@ const FHardwareTexture *FGLTexture::Bind(int texunit, int clampmode, int transla if (hwtex) { // Texture has become invalid - if ((!tex->bHasCanvas && (!tex->bWarped || gl.legacyMode)) && tex->CheckModified()) + if ((!tex->bHasCanvas && (!tex->bWarped || gl.legacyMode)) && tex->CheckModified(DefaultRenderStyle())) { Clean(true); hwtex = CreateHwTexture(); @@ -323,7 +324,7 @@ const FHardwareTexture *FGLTexture::Bind(int texunit, int clampmode, int transla WarpBuffer((uint32_t*)warpbuffer, (const uint32_t*)buffer, w, h, wt->WidthOffsetMultiplier, wt->HeightOffsetMultiplier, screen->FrameTime, wt->Speed, tex->bWarped); delete[] buffer; buffer = warpbuffer; - wt->GenTime = screen->FrameTime; + wt->GenTime[0] = screen->FrameTime; } tex->ProcessData(buffer, w, h, false); } diff --git a/src/gl/textures/gl_texture.cpp b/src/gl/textures/gl_texture.cpp index 0d3e84e4b..f228d2123 100644 --- a/src/gl/textures/gl_texture.cpp +++ b/src/gl/textures/gl_texture.cpp @@ -238,7 +238,7 @@ void FTexture::CreateDefaultBrightmap() ) { // May have one - let's check when we use this texture - const uint8_t *texbuf = GetPixels(); + const uint8_t *texbuf = GetPixels(DefaultRenderStyle()); const int white = ColorMatcher.Pick(255,255,255); int size = GetWidth() * GetHeight(); @@ -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/p_mobj.cpp b/src/p_mobj.cpp index 371e3f977..e27ab198c 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -8516,5 +8516,7 @@ void PrintMiscActorInfo(AActor *query) query->Speed, query->Vel.X, query->Vel.Y, query->Vel.Z, query->Vel.Length()); Printf("Scale: x:%f, y:%f\n", query->Scale.X, query->Scale.Y); Printf("FriendlySeeBlocks: %d\n", query->friendlyseeblocks); + Printf("Target: %s\n", query->target ? query->target->GetClass()->TypeName.GetChars() : "-"); + Printf("Last enemy: %s\n", query->lastenemy ? query->lastenemy->GetClass()->TypeName.GetChars() : "-"); } } diff --git a/src/polyrenderer/drawers/poly_draw_args.cpp b/src/polyrenderer/drawers/poly_draw_args.cpp index 466a39f4a..312cb3e32 100644 --- a/src/polyrenderer/drawers/poly_draw_args.cpp +++ b/src/polyrenderer/drawers/poly_draw_args.cpp @@ -46,20 +46,21 @@ void PolyDrawArgs::SetTexture(const uint8_t *texels, int width, int height) mTranslation = nullptr; } -void PolyDrawArgs::SetTexture(FTexture *texture) +void PolyDrawArgs::SetTexture(FTexture *texture, FRenderStyle style) { mTextureWidth = texture->GetWidth(); mTextureHeight = texture->GetHeight(); if (PolyRenderer::Instance()->RenderTarget->IsBgra()) mTexturePixels = (const uint8_t *)texture->GetPixelsBgra(); else - mTexturePixels = texture->GetPixels(); + mTexturePixels = texture->GetPixels(style); mTranslation = nullptr; } -void PolyDrawArgs::SetTexture(FTexture *texture, uint32_t translationID, bool forcePal) +void PolyDrawArgs::SetTexture(FTexture *texture, uint32_t translationID, FRenderStyle style) { - if (translationID != 0xffffffff && translationID != 0) + // Alphatexture overrides translations. + if (translationID != 0xffffffff && translationID != 0 && !(style.Flags & STYLEF_RedIsAlpha)) { FRemapTable *table = TranslationToTable(translationID); if (table != nullptr && !table->Inactive) @@ -71,20 +72,20 @@ void PolyDrawArgs::SetTexture(FTexture *texture, uint32_t translationID, bool fo mTextureWidth = texture->GetWidth(); mTextureHeight = texture->GetHeight(); - mTexturePixels = texture->GetPixels(); + mTexturePixels = texture->GetPixels(style); return; } } - if (forcePal) + if (style.Flags & STYLEF_RedIsAlpha) { mTextureWidth = texture->GetWidth(); mTextureHeight = texture->GetHeight(); - mTexturePixels = texture->GetPixels(); + mTexturePixels = texture->GetPixels(style); } else { - SetTexture(texture); + SetTexture(texture, style); } } @@ -164,8 +165,7 @@ void PolyDrawArgs::DrawElements(PolyRenderThread *thread, const TriVertex *verti void PolyDrawArgs::SetStyle(const FRenderStyle &renderstyle, double alpha, uint32_t fillcolor, uint32_t translationID, FTexture *tex, bool fullbright) { - bool forcePal = (renderstyle == LegacyRenderStyles[STYLE_Shaded] || renderstyle == LegacyRenderStyles[STYLE_AddShaded]); - SetTexture(tex, translationID, forcePal); + SetTexture(tex, translationID, renderstyle); if (renderstyle == LegacyRenderStyles[STYLE_Normal] || (r_drawfuzz == 0 && renderstyle == LegacyRenderStyles[STYLE_OptFuzzy])) { @@ -232,20 +232,20 @@ void RectDrawArgs::SetTexture(const uint8_t *texels, int width, int height) mTranslation = nullptr; } -void RectDrawArgs::SetTexture(FTexture *texture) +void RectDrawArgs::SetTexture(FTexture *texture, FRenderStyle style) { mTextureWidth = texture->GetWidth(); mTextureHeight = texture->GetHeight(); if (PolyRenderer::Instance()->RenderTarget->IsBgra()) mTexturePixels = (const uint8_t *)texture->GetPixelsBgra(); else - mTexturePixels = texture->GetPixels(); + mTexturePixels = texture->GetPixels(style); mTranslation = nullptr; } -void RectDrawArgs::SetTexture(FTexture *texture, uint32_t translationID, bool forcePal) +void RectDrawArgs::SetTexture(FTexture *texture, uint32_t translationID, FRenderStyle style) { - if (translationID != 0xffffffff && translationID != 0) + if (translationID != 0xffffffff && translationID != 0 && !(style.Flags & STYLEF_RedIsAlpha)) { FRemapTable *table = TranslationToTable(translationID); if (table != nullptr && !table->Inactive) @@ -257,20 +257,20 @@ void RectDrawArgs::SetTexture(FTexture *texture, uint32_t translationID, bool fo mTextureWidth = texture->GetWidth(); mTextureHeight = texture->GetHeight(); - mTexturePixels = texture->GetPixels(); + mTexturePixels = texture->GetPixels(style); return; } } - if (forcePal) + if (style.Flags & STYLEF_RedIsAlpha) { mTextureWidth = texture->GetWidth(); mTextureHeight = texture->GetHeight(); - mTexturePixels = texture->GetPixels(); + mTexturePixels = texture->GetPixels(style); } else { - SetTexture(texture); + SetTexture(texture, style); } } @@ -315,10 +315,9 @@ void RectDrawArgs::Draw(PolyRenderThread *thread, double x0, double x1, double y thread->DrawQueue->Push(*this); } -void RectDrawArgs::SetStyle(const FRenderStyle &renderstyle, double alpha, uint32_t fillcolor, uint32_t translationID, FTexture *tex, bool fullbright) +void RectDrawArgs::SetStyle(FRenderStyle renderstyle, double alpha, uint32_t fillcolor, uint32_t translationID, FTexture *tex, bool fullbright) { - bool forcePal = (renderstyle == LegacyRenderStyles[STYLE_Shaded] || renderstyle == LegacyRenderStyles[STYLE_AddShaded]); - SetTexture(tex, translationID, forcePal); + SetTexture(tex, translationID, renderstyle); if (renderstyle == LegacyRenderStyles[STYLE_Normal] || (r_drawfuzz == 0 && renderstyle == LegacyRenderStyles[STYLE_OptFuzzy])) { diff --git a/src/polyrenderer/drawers/poly_draw_args.h b/src/polyrenderer/drawers/poly_draw_args.h index eb543bbbf..05ad0862d 100644 --- a/src/polyrenderer/drawers/poly_draw_args.h +++ b/src/polyrenderer/drawers/poly_draw_args.h @@ -67,8 +67,8 @@ class PolyDrawArgs public: void SetClipPlane(int index, const PolyClipPlane &plane) { mClipPlane[index] = plane; } void SetTexture(const uint8_t *texels, int width, int height); - void SetTexture(FTexture *texture); - void SetTexture(FTexture *texture, uint32_t translationID, bool forcePal = false); + void SetTexture(FTexture *texture, FRenderStyle style); + void SetTexture(FTexture *texture, uint32_t translationID, FRenderStyle style); void SetLight(FSWColormap *basecolormap, uint32_t lightlevel, double globVis, bool fixed); void SetDepthTest(bool enable) { mDepthTest = enable; } void SetStencilTestValue(uint8_t stencilTestValue) { mStencilTestValue = stencilTestValue; } @@ -186,11 +186,11 @@ class RectDrawArgs { public: void SetTexture(const uint8_t *texels, int width, int height); - void SetTexture(FTexture *texture); - void SetTexture(FTexture *texture, uint32_t translationID, bool forcePal = false); + void SetTexture(FTexture *texture, FRenderStyle style); + void SetTexture(FTexture *texture, uint32_t translationID, FRenderStyle style); void SetLight(FSWColormap *basecolormap, uint32_t lightlevel); void SetStyle(TriBlendMode blendmode, double srcalpha = 1.0, double destalpha = 1.0) { mBlendMode = blendmode; mSrcAlpha = (uint32_t)(srcalpha * 256.0 + 0.5); mDestAlpha = (uint32_t)(destalpha * 256.0 + 0.5); } - void SetStyle(const FRenderStyle &renderstyle, double alpha, uint32_t fillcolor, uint32_t translationID, FTexture *texture, bool fullbright); + void SetStyle(FRenderStyle renderstyle, double alpha, uint32_t fillcolor, uint32_t translationID, FTexture *texture, bool fullbright); void SetColor(uint32_t bgra, uint8_t palindex); void Draw(PolyRenderThread *thread, double x0, double x1, double y0, double y1, double u0, double u1, double v0, double v1); diff --git a/src/polyrenderer/poly_renderthread.cpp b/src/polyrenderer/poly_renderthread.cpp index 9c3b33122..55d1c8469 100644 --- a/src/polyrenderer/poly_renderthread.cpp +++ b/src/polyrenderer/poly_renderthread.cpp @@ -74,7 +74,7 @@ void PolyRenderThread::FlushDrawQueue() } } -void PolyRenderThread::PrepareTexture(FTexture *texture) +void PolyRenderThread::PrepareTexture(FTexture *texture, FRenderStyle style) { if (texture == nullptr) return; @@ -91,9 +91,9 @@ void PolyRenderThread::PrepareTexture(FTexture *texture) std::unique_lock lock(loadmutex); - texture->GetPixels(); + texture->GetPixels(style); const FTexture::Span *spans; - texture->GetColumn(0, &spans); + texture->GetColumn(style, 0, &spans); if (PolyRenderer::Instance()->RenderTarget->IsBgra()) { texture->GetPixelsBgra(); diff --git a/src/polyrenderer/poly_renderthread.h b/src/polyrenderer/poly_renderthread.h index af10fd45c..afed28b19 100644 --- a/src/polyrenderer/poly_renderthread.h +++ b/src/polyrenderer/poly_renderthread.h @@ -47,7 +47,7 @@ public: DrawerCommandQueuePtr DrawQueue; // Make sure texture can accessed safely - void PrepareTexture(FTexture *texture); + void PrepareTexture(FTexture *texture, FRenderStyle style); // Setup poly object in a threadsafe manner void PreparePolyObject(subsector_t *sub); diff --git a/src/polyrenderer/scene/poly_cull.cpp b/src/polyrenderer/scene/poly_cull.cpp index a3361fd62..d53e0e1bf 100644 --- a/src/polyrenderer/scene/poly_cull.cpp +++ b/src/polyrenderer/scene/poly_cull.cpp @@ -33,26 +33,15 @@ void PolyCull::CullScene(const PolyClipPlane &portalClipPlane) ClearSolidSegments(); MarkViewFrustum(); - if (level.LevelName != lastLevelName) // Is this the best way to detect a level change? - { - lastLevelName = level.LevelName; - SubsectorDepths.clear(); - SubsectorDepths.resize(level.subsectors.Size(), 0xffffffff); - SectorSeen.clear(); - SectorSeen.resize(level.sectors.Size()); - } - else - { - for (const auto &sub : PvsSectors) - SubsectorDepths[sub->Index()] = 0xffffffff; - SubsectorDepths.resize(level.subsectors.Size(), 0xffffffff); + for (uint32_t sub : PvsSubsectors) + SubsectorDepths[sub] = 0xffffffff; + SubsectorDepths.resize(level.subsectors.Size(), 0xffffffff); - for (const auto §or : SeenSectors) - SectorSeen[sector->Index()] = false; - SectorSeen.resize(level.sectors.Size()); - } + for (uint32_t sector : SeenSectors) + SectorSeen[sector] = false; + SectorSeen.resize(level.sectors.Size()); - PvsSectors.clear(); + PvsSubsectors.clear(); SeenSectors.clear(); NextPvsLineStart = 0; @@ -125,10 +114,10 @@ void PolyCull::CullSubsector(subsector_t *sub) FirstSkyHeight = false; } - uint32_t subsectorDepth = (uint32_t)PvsSectors.size(); + uint32_t subsectorDepth = (uint32_t)PvsSubsectors.size(); // Mark that we need to render this - PvsSectors.push_back(sub); + PvsSubsectors.push_back(sub->Index()); PvsLineStart.push_back(NextPvsLineStart); DVector3 viewpos = PolyRenderer::Instance()->Viewpoint.Pos; @@ -169,7 +158,7 @@ void PolyCull::CullSubsector(subsector_t *sub) if (!SectorSeen[sub->sector->Index()]) { SectorSeen[sub->sector->Index()] = true; - SeenSectors.push_back(sub->sector); + SeenSectors.push_back(sub->sector->Index()); } SubsectorDepths[sub->Index()] = subsectorDepth; diff --git a/src/polyrenderer/scene/poly_cull.h b/src/polyrenderer/scene/poly_cull.h index 474a33bb6..4b851373e 100644 --- a/src/polyrenderer/scene/poly_cull.h +++ b/src/polyrenderer/scene/poly_cull.h @@ -36,11 +36,11 @@ public: return PvsLineVisible[PvsLineStart[subsectorDepth] + lineIndex]; } - std::vector PvsSectors; + std::vector PvsSubsectors; double MaxCeilingHeight = 0.0; double MinFloorHeight = 0.0; - std::vector SeenSectors; + std::vector SeenSectors; std::vector SectorSeen; std::vector SubsectorDepths; diff --git a/src/polyrenderer/scene/poly_model.cpp b/src/polyrenderer/scene/poly_model.cpp index c952625c3..b2ce178cc 100644 --- a/src/polyrenderer/scene/poly_model.cpp +++ b/src/polyrenderer/scene/poly_model.cpp @@ -147,7 +147,7 @@ void PolyModelRenderer::DrawArrays(int start, int count) args.SetStencilTestValue(StencilValue); args.SetClipPlane(0, PolyClipPlane()); args.SetStyle(TriBlendMode::TextureOpaque); - args.SetTexture(SkinTexture); + args.SetTexture(SkinTexture, DefaultRenderStyle()); args.SetDepthTest(true); args.SetWriteDepth(true); args.SetWriteStencil(false); @@ -181,7 +181,7 @@ void PolyModelRenderer::DrawElements(int numIndices, size_t offset) args.SetStencilTestValue(StencilValue); args.SetClipPlane(0, PolyClipPlane()); args.SetStyle(TriBlendMode::TextureOpaque); - args.SetTexture(SkinTexture); + args.SetTexture(SkinTexture, DefaultRenderStyle()); args.SetDepthTest(true); args.SetWriteDepth(true); args.SetWriteStencil(false); diff --git a/src/polyrenderer/scene/poly_plane.cpp b/src/polyrenderer/scene/poly_plane.cpp index f5485d096..874fe2630 100644 --- a/src/polyrenderer/scene/poly_plane.cpp +++ b/src/polyrenderer/scene/poly_plane.cpp @@ -81,7 +81,7 @@ void RenderPolyPlane::RenderNormal(PolyRenderThread *thread, const TriMatrix &wo args.SetStencilTestValue(stencilValue); args.SetWriteStencil(true, stencilValue + 1); args.SetClipPlane(0, clipPlane); - args.SetTexture(tex); + args.SetTexture(tex, DefaultRenderStyle()); args.SetStyle(TriBlendMode::TextureOpaque); args.DrawArray(thread, vertices, fakeflat.Subsector->numlines, PolyDrawMode::TriangleFan); } @@ -572,7 +572,7 @@ void Render3DFloorPlane::Render(PolyRenderThread *thread, const TriMatrix &world args.SetFaceCullCCW(true); args.SetStencilTestValue(stencilValue); args.SetWriteStencil(true, stencilValue + 1); - args.SetTexture(tex); + args.SetTexture(tex, DefaultRenderStyle()); args.SetClipPlane(0, clipPlane); args.DrawArray(thread, vertices, sub->numlines, PolyDrawMode::TriangleFan); } diff --git a/src/polyrenderer/scene/poly_scene.cpp b/src/polyrenderer/scene/poly_scene.cpp index 02ad1842e..42f6e815b 100644 --- a/src/polyrenderer/scene/poly_scene.cpp +++ b/src/polyrenderer/scene/poly_scene.cpp @@ -69,8 +69,8 @@ void RenderPolyScene::RenderSectors() { PolyRenderThread *mainthread = PolyRenderer::Instance()->Threads.MainThread(); - int totalcount = (int)Cull.PvsSectors.size(); - auto subsectors = Cull.PvsSectors.data(); + int totalcount = (int)Cull.PvsSubsectors.size(); + uint32_t *subsectors = Cull.PvsSubsectors.data(); TranslucentObjects.resize(PolyRenderer::Instance()->Threads.NumThreads()); @@ -82,7 +82,7 @@ void RenderPolyScene::RenderSectors() int end = thread->End; for (int i = start; i < end; i++) { - RenderSubsector(thread, subsectors[i], i); + RenderSubsector(thread, &level.subsectors[subsectors[i]], i); } }, [&](PolyRenderThread *thread) { @@ -372,8 +372,9 @@ void RenderPolyScene::RenderTranslucent(int portalDepth) } const auto &viewpoint = PolyRenderer::Instance()->Viewpoint; - for (sector_t *sector : Cull.SeenSectors) + for (uint32_t sectorIndex : Cull.SeenSectors) { + sector_t *sector = &level.sectors[sectorIndex]; for (AActor *thing = sector->thinglist; thing != nullptr; thing = thing->snext) { DVector2 left, right; diff --git a/src/polyrenderer/scene/poly_sky.cpp b/src/polyrenderer/scene/poly_sky.cpp index 06cb7a8ec..eafa4c94c 100644 --- a/src/polyrenderer/scene/poly_sky.cpp +++ b/src/polyrenderer/scene/poly_sky.cpp @@ -91,7 +91,7 @@ void PolySkyDome::Render(PolyRenderThread *thread, const TriMatrix &worldToClip) RenderCapColorRow(thread, args, mCurrentSetup.frontskytex, 0, false); RenderCapColorRow(thread, args, mCurrentSetup.frontskytex, rc, true); - args.SetTexture(mCurrentSetup.frontskytex); + args.SetTexture(mCurrentSetup.frontskytex, DefaultRenderStyle()); uint32_t topcapcolor = mCurrentSetup.frontskytex->GetSkyCapColor(false); uint32_t bottomcapcolor = mCurrentSetup.frontskytex->GetSkyCapColor(true); diff --git a/src/polyrenderer/scene/poly_wall.cpp b/src/polyrenderer/scene/poly_wall.cpp index 20b9a1ade..fb75f7bf4 100644 --- a/src/polyrenderer/scene/poly_wall.cpp +++ b/src/polyrenderer/scene/poly_wall.cpp @@ -327,7 +327,7 @@ void RenderPolyWall::Render(PolyRenderThread *thread, const TriMatrix &worldToCl args.SetStencilTestValue(StencilValue); args.SetWriteStencil(true, StencilValue + 1); if (Texture && !Polyportal) - args.SetTexture(Texture); + args.SetTexture(Texture, DefaultRenderStyle()); args.SetClipPlane(0, clipPlane); SetDynLights(thread, args); diff --git a/src/polyrenderer/scene/poly_wallsprite.cpp b/src/polyrenderer/scene/poly_wallsprite.cpp index 846524f9d..7da68c5e5 100644 --- a/src/polyrenderer/scene/poly_wallsprite.cpp +++ b/src/polyrenderer/scene/poly_wallsprite.cpp @@ -105,7 +105,7 @@ void RenderPolyWallSprite::Render(PolyRenderThread *thread, const TriMatrix &wor args.SetTransform(&worldToClip); args.SetFaceCullCCW(true); args.SetStencilTestValue(stencilValue); - args.SetTexture(tex); + args.SetTexture(tex, thing->RenderStyle); args.SetClipPlane(0, clipPlane); args.SetDepthTest(true); args.SetWriteDepth(false); 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/r_data/renderstyle.h b/src/r_data/renderstyle.h index b1fd98a5c..afb82d380 100644 --- a/src/r_data/renderstyle.h +++ b/src/r_data/renderstyle.h @@ -133,20 +133,28 @@ union FRenderStyle uint32_t AsDWORD; inline FRenderStyle &operator= (ERenderStyle legacy); - operator uint32_t() const { return AsDWORD; } bool operator==(const FRenderStyle &o) const { return AsDWORD == o.AsDWORD; } void CheckFuzz(); bool IsVisible(double alpha) const throw(); private: // Code that compares an actor's render style with a legacy render - // style value should be updated. Making these conversion operators - // private will catch those cases. - operator ERenderStyle() const { return STYLE_Normal; } - operator int() const { return STYLE_Normal; } + // style value should be updated. + operator ERenderStyle() = delete; + operator int() const = delete; }; extern FRenderStyle LegacyRenderStyles[STYLE_Count]; +inline FRenderStyle DefaultRenderStyle() +{ + return LegacyRenderStyles[STYLE_Normal]; +} + +inline FRenderStyle BadRenderStyle() // This is just a marker to find places where work is still needed. +{ + return LegacyRenderStyles[STYLE_Normal]; +} + inline FRenderStyle &FRenderStyle::operator= (ERenderStyle legacy) { if (legacy < STYLE_None || legacy >= STYLE_Count) diff --git a/src/resourcefiles/file_zip.cpp b/src/resourcefiles/file_zip.cpp index bf51cd2a4..b3bfa7a2d 100644 --- a/src/resourcefiles/file_zip.cpp +++ b/src/resourcefiles/file_zip.cpp @@ -280,6 +280,8 @@ bool FZipFile::Open(bool quiet) } } } + // If it ran through the list without finding anything it should not attempt any path remapping. + if (!foundspeciallump) name0 = ""; dirptr = (char*)directory; lump_p = Lumps; diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 279d9adda..4d530c8a5 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2743,6 +2743,7 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool if (parentfunc->Variants[0].Implementation->DefaultArgs.Size() > 0) { sym->Variants[0].Implementation->DefaultArgs = parentfunc->Variants[0].Implementation->DefaultArgs; + sym->Variants[0].ArgFlags = parentfunc->Variants[0].ArgFlags; } } } diff --git a/src/sound/musicformats/music_libsndfile.cpp b/src/sound/musicformats/music_libsndfile.cpp index b87492a4e..61be6b56c 100644 --- a/src/sound/musicformats/music_libsndfile.cpp +++ b/src/sound/musicformats/music_libsndfile.cpp @@ -298,8 +298,9 @@ SndFileSong::SndFileSong(FileReader &reader, SoundDecoder *decoder, uint32_t loo if (!startass) loop_start = Scale(loop_start, SampleRate, 1000); if (!endass) loop_end = Scale(loop_end, SampleRate, 1000); + const uint32_t sampleLength = (uint32_t)decoder->getSampleLength(); Loop_Start = loop_start; - Loop_End = clamp(loop_end, 0, (uint32_t)decoder->getSampleLength()); + Loop_End = sampleLength == 0 ? loop_end : clamp(loop_end, 0, sampleLength); Reader = std::move(reader); Decoder = decoder; Channels = iChannels == ChannelConfig_Stereo? 2:1; @@ -419,12 +420,17 @@ bool SndFileSong::Read(SoundStream *stream, void *vbuff, int ilen, void *userdat // This looks a bit more complicated than necessary because libmpg123 will not read the full requested length for the last block in the file. if (currentpos + framestoread > song->Loop_End) { - size_t endblock = (song->Loop_End - currentpos) * song->Channels * 2; - size_t endlen = song->Decoder->read(buff, endblock); + // Loop can be very short, make sure the current position doesn't exceed it + if (currentpos < song->Loop_End) + { + size_t endblock = (song->Loop_End - currentpos) * song->Channels * 2; + size_t endlen = song->Decoder->read(buff, endblock); + + // Even if zero bytes was read give it a chance to start from the beginning + buff += endlen; + len -= endlen; + } - // Even if zero bytes was read give it a chance to start from the beginning - buff = buff + endlen; - len -= endlen; song->Decoder->seek(song->Loop_Start, false, true); } while (len > 0) diff --git a/src/swrenderer/line/r_renderdrawsegment.cpp b/src/swrenderer/line/r_renderdrawsegment.cpp index 86f86c2cb..f46fbc133 100644 --- a/src/swrenderer/line/r_renderdrawsegment.cpp +++ b/src/swrenderer/line/r_renderdrawsegment.cpp @@ -155,6 +155,7 @@ namespace swrenderer bool RenderDrawSegment::RenderWall(DrawSegment *ds, int x1, int x2, WallDrawerArgs &walldrawerargs, SpriteDrawerArgs &columndrawerargs, bool visible, FDynamicColormap *basecolormap, int wallshade) { + auto renderstyle = DefaultRenderStyle(); auto viewport = Thread->Viewport.get(); Clip3DFloors *clip3d = Thread->Clip3D.get(); @@ -314,7 +315,7 @@ namespace swrenderer // draw the columns one at a time if (visible) { - Thread->PrepareTexture(tex); + Thread->PrepareTexture(tex, renderstyle); for (int x = x1; x < x2; ++x) { if (cameraLight->FixedColormap() == nullptr && cameraLight->FixedLightLevel() < 0) @@ -329,7 +330,7 @@ namespace swrenderer else sprtopscreen = viewport->CenterY - texturemid * spryscale; - columndrawerargs.DrawMaskedColumn(Thread, x, iscale, tex, maskedtexturecol[x], spryscale, sprtopscreen, sprflipvert, mfloorclip, mceilingclip); + columndrawerargs.DrawMaskedColumn(Thread, x, iscale, tex, maskedtexturecol[x], spryscale, sprtopscreen, sprflipvert, mfloorclip, mceilingclip, renderstyle); rw_light += rw_lightstep; spryscale += rw_scalestep; diff --git a/src/swrenderer/line/r_walldraw.cpp b/src/swrenderer/line/r_walldraw.cpp index 5b7518440..0b9c9131d 100644 --- a/src/swrenderer/line/r_walldraw.cpp +++ b/src/swrenderer/line/r_walldraw.cpp @@ -97,7 +97,7 @@ namespace swrenderer col = width + (col % width); } - source = texture->GetColumn(col, nullptr); + source = texture->GetColumn(DefaultRenderStyle(), col, nullptr); source2 = nullptr; texturefracx = 0; } @@ -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 @@ -531,7 +530,7 @@ namespace swrenderer this->rw_pic = pic; this->mask = mask; - Thread->PrepareTexture(pic); + Thread->PrepareTexture(pic, DefaultRenderStyle()); // Get correct render style? Shaded won't get here. if (rw_pic->GetHeight() != 1 << rw_pic->HeightBits) { diff --git a/src/swrenderer/plane/r_skyplane.cpp b/src/swrenderer/plane/r_skyplane.cpp index ef7a6b898..e95abbd46 100644 --- a/src/swrenderer/plane/r_skyplane.cpp +++ b/src/swrenderer/plane/r_skyplane.cpp @@ -172,8 +172,8 @@ namespace swrenderer drawerargs.SetLight(&NormalLight, 0, 0); } - Thread->PrepareTexture(frontskytex); - Thread->PrepareTexture(backskytex); + Thread->PrepareTexture(frontskytex, DefaultRenderStyle()); + Thread->PrepareTexture(backskytex, DefaultRenderStyle()); DrawSky(pl); } diff --git a/src/swrenderer/r_renderthread.cpp b/src/swrenderer/r_renderthread.cpp index bb2816a94..986879618 100644 --- a/src/swrenderer/r_renderthread.cpp +++ b/src/swrenderer/r_renderthread.cpp @@ -89,7 +89,7 @@ namespace swrenderer return pal_drawers.get(); } - void RenderThread::PrepareTexture(FTexture *texture) + void RenderThread::PrepareTexture(FTexture *texture, FRenderStyle style) { if (texture == nullptr) return; @@ -106,9 +106,9 @@ namespace swrenderer std::unique_lock lock(loadmutex); - texture->GetPixels(); + texture->GetPixels(style); const FTexture::Span *spans; - texture->GetColumn(0, &spans); + texture->GetColumn(style, 0, &spans); if (Viewport->RenderTarget->IsBgra()) { texture->GetPixelsBgra(); diff --git a/src/swrenderer/r_renderthread.h b/src/swrenderer/r_renderthread.h index 3e559155b..34beab6ae 100644 --- a/src/swrenderer/r_renderthread.h +++ b/src/swrenderer/r_renderthread.h @@ -84,7 +84,7 @@ namespace swrenderer SWPixelFormatDrawers *Drawers(RenderViewport *viewport); // Make sure texture can accessed safely - void PrepareTexture(FTexture *texture); + void PrepareTexture(FTexture *texture, FRenderStyle style); // Setup poly object in a threadsafe manner void PreparePolyObject(subsector_t *sub); diff --git a/src/swrenderer/r_swcanvas.cpp b/src/swrenderer/r_swcanvas.cpp index 0330d4d6e..5522d89dc 100644 --- a/src/swrenderer/r_swcanvas.cpp +++ b/src/swrenderer/r_swcanvas.cpp @@ -196,7 +196,7 @@ void SWCanvas::DrawTexture(DCanvas *canvas, FTexture *img, DrawParms &parms) while (x < x2_i) { - drawerargs.DrawMaskedColumn(&thread, x, iscale, img, frac, spryscale, sprtopscreen, sprflipvert, mfloorclip, mceilingclip, !parms.masked); + drawerargs.DrawMaskedColumn(&thread, x, iscale, img, frac, spryscale, sprtopscreen, sprflipvert, mfloorclip, mceilingclip, parms.style, !parms.masked); x++; frac += xiscale_i; } diff --git a/src/swrenderer/r_swrenderer.cpp b/src/swrenderer/r_swrenderer.cpp index 3c18e6218..c31908a17 100644 --- a/src/swrenderer/r_swrenderer.cpp +++ b/src/swrenderer/r_swrenderer.cpp @@ -105,14 +105,14 @@ void FSoftwareRenderer::PrecacheTexture(FTexture *tex, int cache) if (isbgra) tex->GetColumnBgra(0, &spanp); else - tex->GetColumn(0, &spanp); + tex->GetColumn(DefaultRenderStyle(), 0, &spanp); } else if (cache != 0) { if (isbgra) tex->GetPixelsBgra(); else - tex->GetPixels (); + tex->GetPixels (DefaultRenderStyle()); } else { @@ -282,7 +282,7 @@ void FSoftwareRenderer::RenderTextureView (FCanvasTexture *tex, AActor *viewpoin cameraViewpoint = r_viewpoint; cameraViewwindow = r_viewwindow; - uint8_t *Pixels = renderTarget->IsBgra() ? (uint8_t*)tex->GetPixelsBgra() : (uint8_t*)tex->GetPixels(); + uint8_t *Pixels = renderTarget->IsBgra() ? (uint8_t*)tex->GetPixelsBgra() : (uint8_t*)tex->GetPixels(DefaultRenderStyle()); DSimpleCanvas *Canvas = renderTarget->IsBgra() ? tex->GetCanvasBgra() : tex->GetCanvas(); // curse Doom's overuse of global variables in the renderer. @@ -328,7 +328,7 @@ void FSoftwareRenderer::RenderTextureView (FCanvasTexture *tex, AActor *viewpoin // We need to make sure that both pixel buffers contain data: int width = tex->GetWidth(); int height = tex->GetHeight(); - uint8_t *palbuffer = (uint8_t *)tex->GetPixels(); + uint8_t *palbuffer = (uint8_t *)tex->GetPixels(DefaultRenderStyle()); uint32_t *bgrabuffer = (uint32_t*)tex->GetPixelsBgra(); for (int x = 0; x < width; x++) { diff --git a/src/swrenderer/things/r_decal.cpp b/src/swrenderer/things/r_decal.cpp index b1711d9e3..8361a8061 100644 --- a/src/swrenderer/things/r_decal.cpp +++ b/src/swrenderer/things/r_decal.cpp @@ -312,14 +312,14 @@ namespace swrenderer if (visible) { - thread->PrepareTexture(WallSpriteTile); + thread->PrepareTexture(WallSpriteTile, decal->RenderStyle); while (x < x2) { if (calclighting) { // calculate lighting drawerargs.SetLight(usecolormap, light, wallshade); } - DrawColumn(thread, drawerargs, x, WallSpriteTile, walltexcoords, texturemid, maskedScaleY, sprflipvert, mfloorclip, mceilingclip); + DrawColumn(thread, drawerargs, x, WallSpriteTile, walltexcoords, texturemid, maskedScaleY, sprflipvert, mfloorclip, mceilingclip, decal->RenderStyle); light += lightstep; x++; } @@ -333,7 +333,7 @@ namespace swrenderer } while (needrepeat--); } - void RenderDecal::DrawColumn(RenderThread *thread, SpriteDrawerArgs &drawerargs, int x, FTexture *WallSpriteTile, const ProjectedWallTexcoords &walltexcoords, double texturemid, float maskedScaleY, bool sprflipvert, const short *mfloorclip, const short *mceilingclip) + void RenderDecal::DrawColumn(RenderThread *thread, SpriteDrawerArgs &drawerargs, int x, FTexture *WallSpriteTile, const ProjectedWallTexcoords &walltexcoords, double texturemid, float maskedScaleY, bool sprflipvert, const short *mfloorclip, const short *mceilingclip, FRenderStyle style) { auto viewport = thread->Viewport.get(); @@ -345,6 +345,6 @@ namespace swrenderer else sprtopscreen = viewport->CenterY - texturemid * spryscale; - drawerargs.DrawMaskedColumn(thread, x, FLOAT2FIXED(iscale), WallSpriteTile, walltexcoords.UPos[x], spryscale, sprtopscreen, sprflipvert, mfloorclip, mceilingclip); + drawerargs.DrawMaskedColumn(thread, x, FLOAT2FIXED(iscale), WallSpriteTile, walltexcoords.UPos[x], spryscale, sprtopscreen, sprflipvert, mfloorclip, mceilingclip, style); } } diff --git a/src/swrenderer/things/r_decal.h b/src/swrenderer/things/r_decal.h index 712e82900..e617b04a6 100644 --- a/src/swrenderer/things/r_decal.h +++ b/src/swrenderer/things/r_decal.h @@ -16,6 +16,6 @@ namespace swrenderer private: static void Render(RenderThread *thread, side_t *wall, DBaseDecal *first, DrawSegment *clipper, int wallshade, float lightleft, float lightstep, seg_t *curline, const FWallCoords &wallC, bool foggy, FDynamicColormap *basecolormap, const short *walltop, const short *wallbottom, bool drawsegPass); - static void DrawColumn(RenderThread *thread, SpriteDrawerArgs &drawerargs, int x, FTexture *WallSpriteTile, const ProjectedWallTexcoords &walltexcoords, double texturemid, float maskedScaleY, bool sprflipvert, const short *mfloorclip, const short *mceilingclip); + static void DrawColumn(RenderThread *thread, SpriteDrawerArgs &drawerargs, int x, FTexture *WallSpriteTile, const ProjectedWallTexcoords &walltexcoords, double texturemid, float maskedScaleY, bool sprflipvert, const short *mfloorclip, const short *mceilingclip, FRenderStyle style); }; } diff --git a/src/swrenderer/things/r_model.cpp b/src/swrenderer/things/r_model.cpp index 4b68db219..b6f5fe0c7 100644 --- a/src/swrenderer/things/r_model.cpp +++ b/src/swrenderer/things/r_model.cpp @@ -199,7 +199,7 @@ namespace swrenderer if (Thread->Viewport->RenderTarget->IsBgra()) args.SetTexture((const uint8_t *)SkinTexture->GetPixelsBgra(), SkinTexture->GetWidth(), SkinTexture->GetHeight()); else - args.SetTexture(SkinTexture->GetPixels(), SkinTexture->GetWidth(), SkinTexture->GetHeight()); + args.SetTexture(SkinTexture->GetPixels(DefaultRenderStyle()), SkinTexture->GetWidth(), SkinTexture->GetHeight()); args.SetDepthTest(true); args.SetWriteDepth(true); @@ -237,7 +237,7 @@ namespace swrenderer if (Thread->Viewport->RenderTarget->IsBgra()) args.SetTexture((const uint8_t *)SkinTexture->GetPixelsBgra(), SkinTexture->GetWidth(), SkinTexture->GetHeight()); else - args.SetTexture(SkinTexture->GetPixels(), SkinTexture->GetWidth(), SkinTexture->GetHeight()); + args.SetTexture(SkinTexture->GetPixels(DefaultRenderStyle()), SkinTexture->GetWidth(), SkinTexture->GetHeight()); args.SetDepthTest(true); args.SetWriteDepth(true); diff --git a/src/swrenderer/things/r_playersprite.cpp b/src/swrenderer/things/r_playersprite.cpp index 41ec47239..924c7a7d8 100644 --- a/src/swrenderer/things/r_playersprite.cpp +++ b/src/swrenderer/things/r_playersprite.cpp @@ -545,10 +545,10 @@ namespace swrenderer short *mceilingclip = zeroarray; fixed_t frac = startfrac; - thread->PrepareTexture(pic); + thread->PrepareTexture(pic, RenderStyle); for (int x = x1; x < x2; x++) { - drawerargs.DrawMaskedColumn(thread, x, iscale, pic, frac + xiscale / 2, spryscale, sprtopscreen, sprflipvert, mfloorclip, mceilingclip, false); + drawerargs.DrawMaskedColumn(thread, x, iscale, pic, frac + xiscale / 2, spryscale, sprtopscreen, sprflipvert, mfloorclip, mceilingclip, RenderStyle, false); frac += xiscale; } diff --git a/src/swrenderer/things/r_sprite.cpp b/src/swrenderer/things/r_sprite.cpp index 74a76a79f..be26ad7c2 100644 --- a/src/swrenderer/things/r_sprite.cpp +++ b/src/swrenderer/things/r_sprite.cpp @@ -361,11 +361,11 @@ namespace swrenderer { RenderTranslucentPass *translucentPass = thread->TranslucentPass.get(); - thread->PrepareTexture(tex); + thread->PrepareTexture(tex, vis->RenderStyle); while (x < x2) { if (!translucentPass->ClipSpriteColumnWithPortals(x, vis)) - drawerargs.DrawMaskedColumn(thread, x, iscale, tex, frac, spryscale, sprtopscreen, sprflipvert, mfloorclip, mceilingclip, false); + drawerargs.DrawMaskedColumn(thread, x, iscale, tex, frac, spryscale, sprtopscreen, sprflipvert, mfloorclip, mceilingclip, vis->RenderStyle, false); x++; frac += xiscale; } diff --git a/src/swrenderer/things/r_wallsprite.cpp b/src/swrenderer/things/r_wallsprite.cpp index be4c4195e..f44d88e2a 100644 --- a/src/swrenderer/things/r_wallsprite.cpp +++ b/src/swrenderer/things/r_wallsprite.cpp @@ -239,7 +239,7 @@ namespace swrenderer { RenderTranslucentPass *translucentPass = thread->TranslucentPass.get(); - thread->PrepareTexture(WallSpriteTile); + thread->PrepareTexture(WallSpriteTile, spr->RenderStyle); while (x < x2) { if (calclighting) @@ -247,14 +247,14 @@ namespace swrenderer drawerargs.SetLight(usecolormap, light, shade); } if (!translucentPass->ClipSpriteColumnWithPortals(x, spr)) - DrawColumn(thread, drawerargs, x, WallSpriteTile, walltexcoords, texturemid, maskedScaleY, sprflipvert, mfloorclip, mceilingclip); + DrawColumn(thread, drawerargs, x, WallSpriteTile, walltexcoords, texturemid, maskedScaleY, sprflipvert, mfloorclip, mceilingclip, spr->RenderStyle); light += lightstep; x++; } } } - void RenderWallSprite::DrawColumn(RenderThread *thread, SpriteDrawerArgs &drawerargs, int x, FTexture *WallSpriteTile, const ProjectedWallTexcoords &walltexcoords, double texturemid, float maskedScaleY, bool sprflipvert, const short *mfloorclip, const short *mceilingclip) + void RenderWallSprite::DrawColumn(RenderThread *thread, SpriteDrawerArgs &drawerargs, int x, FTexture *WallSpriteTile, const ProjectedWallTexcoords &walltexcoords, double texturemid, float maskedScaleY, bool sprflipvert, const short *mfloorclip, const short *mceilingclip, FRenderStyle style) { auto viewport = thread->Viewport.get(); @@ -266,6 +266,6 @@ namespace swrenderer else sprtopscreen = viewport->CenterY - texturemid * spryscale; - drawerargs.DrawMaskedColumn(thread, x, FLOAT2FIXED(iscale), WallSpriteTile, walltexcoords.UPos[x], spryscale, sprtopscreen, sprflipvert, mfloorclip, mceilingclip); + drawerargs.DrawMaskedColumn(thread, x, FLOAT2FIXED(iscale), WallSpriteTile, walltexcoords.UPos[x], spryscale, sprtopscreen, sprflipvert, mfloorclip, mceilingclip, style); } } diff --git a/src/swrenderer/things/r_wallsprite.h b/src/swrenderer/things/r_wallsprite.h index c248c6c8c..fa127ccf4 100644 --- a/src/swrenderer/things/r_wallsprite.h +++ b/src/swrenderer/things/r_wallsprite.h @@ -17,7 +17,7 @@ namespace swrenderer void Render(RenderThread *thread, short *cliptop, short *clipbottom, int minZ, int maxZ, Fake3DTranslucent clip3DFloor) override; private: - static void DrawColumn(RenderThread *thread, SpriteDrawerArgs &drawerargs, int x, FTexture *WallSpriteTile, const ProjectedWallTexcoords &walltexcoords, double texturemid, float maskedScaleY, bool sprflipvert, const short *mfloorclip, const short *mceilingclip); + static void DrawColumn(RenderThread *thread, SpriteDrawerArgs &drawerargs, int x, FTexture *WallSpriteTile, const ProjectedWallTexcoords &walltexcoords, double texturemid, float maskedScaleY, bool sprflipvert, const short *mfloorclip, const short *mceilingclip, FRenderStyle style); FWallCoords wallc; uint32_t Translation = 0; diff --git a/src/swrenderer/viewport/r_skydrawer.cpp b/src/swrenderer/viewport/r_skydrawer.cpp index 16e2d2ab3..c134a46e2 100644 --- a/src/swrenderer/viewport/r_skydrawer.cpp +++ b/src/swrenderer/viewport/r_skydrawer.cpp @@ -56,7 +56,7 @@ namespace swrenderer } else { - dc_source = texture->GetColumn(column, nullptr); + dc_source = texture->GetColumn(DefaultRenderStyle(), column, nullptr); dc_sourceheight = texture->GetHeight(); } } @@ -75,7 +75,7 @@ namespace swrenderer } else { - dc_source2 = texture->GetColumn(column, nullptr); + dc_source2 = texture->GetColumn(DefaultRenderStyle(), column, nullptr); dc_sourceheight2 = texture->GetHeight(); } } diff --git a/src/swrenderer/viewport/r_spandrawer.cpp b/src/swrenderer/viewport/r_spandrawer.cpp index ffc4dfc5f..e5adf5409 100644 --- a/src/swrenderer/viewport/r_spandrawer.cpp +++ b/src/swrenderer/viewport/r_spandrawer.cpp @@ -32,7 +32,7 @@ namespace swrenderer void SpanDrawerArgs::SetTexture(RenderThread *thread, FTexture *tex) { - thread->PrepareTexture(tex); + thread->PrepareTexture(tex, DefaultRenderStyle()); ds_texwidth = tex->GetWidth(); ds_texheight = tex->GetHeight(); @@ -47,7 +47,7 @@ namespace swrenderer ds_ybits--; } - ds_source = thread->Viewport->RenderTarget->IsBgra() ? (const uint8_t*)tex->GetPixelsBgra() : tex->GetPixels(); + ds_source = thread->Viewport->RenderTarget->IsBgra() ? (const uint8_t*)tex->GetPixelsBgra() : tex->GetPixels(DefaultRenderStyle()); // Get correct render style? Shaded won't get here. ds_source_mipmapped = tex->Mipmapped() && tex->GetWidth() > 1 && tex->GetHeight() > 1; } diff --git a/src/swrenderer/viewport/r_spritedrawer.cpp b/src/swrenderer/viewport/r_spritedrawer.cpp index 0dbb38716..20abfca51 100644 --- a/src/swrenderer/viewport/r_spritedrawer.cpp +++ b/src/swrenderer/viewport/r_spritedrawer.cpp @@ -43,7 +43,7 @@ namespace swrenderer colfunc = &SWPixelFormatDrawers::DrawColumn; } - void SpriteDrawerArgs::DrawMaskedColumn(RenderThread *thread, int x, fixed_t iscale, FTexture *tex, fixed_t col, double spryscale, double sprtopscreen, bool sprflipvert, const short *mfloorclip, const short *mceilingclip, bool unmasked) + void SpriteDrawerArgs::DrawMaskedColumn(RenderThread *thread, int x, fixed_t iscale, FTexture *tex, fixed_t col, double spryscale, double sprtopscreen, bool sprflipvert, const short *mfloorclip, const short *mceilingclip, FRenderStyle style, bool unmasked) { if (x < thread->X1 || x >= thread->X2) return; @@ -67,7 +67,7 @@ namespace swrenderer if (viewport->RenderTarget->IsBgra() && !drawer_needs_pal_input) column = (const uint8_t *)tex->GetColumnBgra(col >> FRACBITS, &span); else - column = tex->GetColumn(col >> FRACBITS, &span); + column = tex->GetColumn(style, col >> FRACBITS, &span); FTexture::Span unmaskedSpan[2]; if (unmasked) diff --git a/src/swrenderer/viewport/r_spritedrawer.h b/src/swrenderer/viewport/r_spritedrawer.h index e1df5e926..f6a3aae79 100644 --- a/src/swrenderer/viewport/r_spritedrawer.h +++ b/src/swrenderer/viewport/r_spritedrawer.h @@ -33,7 +33,7 @@ namespace swrenderer void SetSolidColor(int color) { dc_color = color; dc_color_bgra = GPalette.BaseColors[color]; } void SetDynamicLight(uint32_t color) { dynlightcolor = color; } - void DrawMaskedColumn(RenderThread *thread, int x, fixed_t iscale, FTexture *texture, fixed_t column, double spryscale, double sprtopscreen, bool sprflipvert, const short *mfloorclip, const short *mceilingclip, bool unmasked = false); + void DrawMaskedColumn(RenderThread *thread, int x, fixed_t iscale, FTexture *texture, fixed_t column, double spryscale, double sprtopscreen, bool sprflipvert, const short *mfloorclip, const short *mceilingclip, FRenderStyle style, bool unmasked = false); void FillColumn(RenderThread *thread); void DrawVoxelBlocks(RenderThread *thread, const VoxelBlock *blocks, int blockcount); diff --git a/src/textures/automaptexture.cpp b/src/textures/automaptexture.cpp index 3bd16f5bc..c07eded6e 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,11 @@ // //========================================================================== -class FAutomapTexture : public FTexture +class FAutomapTexture : public FWorldTexture { public: - ~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]; + FAutomapTexture(int lumpnum); + uint8_t *MakeTexture (FRenderStyle style); }; @@ -86,16 +77,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 +90,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/backdroptexture.cpp b/src/textures/backdroptexture.cpp index aec95cc2e..9d9049fae 100644 --- a/src/textures/backdroptexture.cpp +++ b/src/textures/backdroptexture.cpp @@ -56,7 +56,7 @@ // //============================================================================= -struct FBackdropTexture : public FTexture +class FBackdropTexture : public FWorldTexture { enum { @@ -77,15 +77,12 @@ struct FBackdropTexture : public FTexture public: FBackdropTexture(); - const uint8_t *GetColumn(unsigned int column, const Span **spans_out); - const uint8_t *GetPixels(); - void Unload(); - bool CheckModified(); + bool CheckModified(FRenderStyle style) override; + uint8_t *MakeTexture(FRenderStyle style) override; protected: uint32_t costab[COS_SIZE]; - uint8_t *Pixels; - static const Span DummySpan[2]; + uint8_t Pixels[160*144]; int LastRenderTic; uint32_t time1, time2, time3, time4; @@ -170,8 +167,6 @@ static uint8_t pattern2[1024] = 7, 7, 0, 5, 1, 6, 7, 9,12, 9,12,21,22,25,24,22,23,25,24,18,24,22,17,13,10, 9,10, 9, 6,11, 6, 5, }; -const FTexture::Span FBackdropTexture::DummySpan[2] = { { 0, 160 }, { 0, 0 } }; - //============================================================================= // // @@ -180,7 +175,7 @@ const FTexture::Span FBackdropTexture::DummySpan[2] = { { 0, 160 }, { 0, 0 } }; FBackdropTexture::FBackdropTexture() { - Pixels = nullptr; + PixelsAreStatic = 3; Width = 144; Height = 160; WidthBits = 8; @@ -209,44 +204,19 @@ FBackdropTexture::FBackdropTexture() // //============================================================================= -bool FBackdropTexture::CheckModified() +bool FBackdropTexture::CheckModified(FRenderStyle) { return LastRenderTic != gametic; } -void FBackdropTexture::Unload() -{ - if (Pixels != nullptr) delete[] Pixels; - Pixels = nullptr; -} - //============================================================================= // -// +// There's no point making this work as a regular texture as it is made to +// work with special translations. As an alpha texture it should be fine. // //============================================================================= -const uint8_t *FBackdropTexture::GetColumn(unsigned int column, const Span **spans_out) -{ - if (LastRenderTic != gametic) - { - Render(); - } - column = clamp(column, 0u, 143u); - if (spans_out != nullptr) - { - *spans_out = DummySpan; - } - return Pixels + column*160; -} - -//============================================================================= -// -// -// -//============================================================================= - -const uint8_t *FBackdropTexture::GetPixels() +uint8_t *FBackdropTexture::MakeTexture(FRenderStyle style) { if (LastRenderTic != gametic) { @@ -266,7 +236,6 @@ void FBackdropTexture::Render() uint8_t *from; int width, height, pitch; - if (Pixels == nullptr) Pixels = new uint8_t[160 * 144]; width = 160; height = 144; pitch = width; 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/buildtexture.cpp b/src/textures/buildtexture.cpp index dd9545553..96e24af21 100644 --- a/src/textures/buildtexture.cpp +++ b/src/textures/buildtexture.cpp @@ -1,9 +1,10 @@ /* ** buildtexture.cpp -** Handling Build textures +** Handling Build textures (now as a usable editing feature!) ** **--------------------------------------------------------------------------- ** Copyright 2004-2006 Randy Heit +** Copyright 2018 Christoph Oelckers ** All rights reserved. ** ** Redistribution and use in source and binary forms, with or without @@ -39,8 +40,13 @@ #include "templates.h" #include "cmdlib.h" #include "st_start.h" +#include "colormatcher.h" +#include "bitmap.h" #include "textures/textures.h" #include "r_data/sprites.h" +#include "r_data/r_translate.h" +#include "resourcefiles/resourcefile.h" + //========================================================================== // @@ -48,18 +54,18 @@ // //========================================================================== -class FBuildTexture : public FTexture +class FBuildTexture : public FWorldTexture { public: - FBuildTexture (int tilenum, const uint8_t *pixels, int width, int height, int left, int top); - ~FBuildTexture (); - - const uint8_t *GetColumn (unsigned int column, const Span **spans_out); - const uint8_t *GetPixels (); + FBuildTexture (const FString &pathprefix, int tilenum, const uint8_t *pixels, int translation, int width, int height, int left, int top); + uint8_t *MakeTexture(FRenderStyle style) override; + int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL) override; + bool UseBasePalette() override { return false; } + FTextureFormat GetFormat() override { return TEX_RGB; } protected: - const uint8_t *Pixels; - Span **Spans; + const uint8_t *RawPixels; + int Translation; }; @@ -69,72 +75,37 @@ protected: // //========================================================================== -FBuildTexture::FBuildTexture (int tilenum, const uint8_t *pixels, int width, int height, int left, int top) -: Pixels (pixels), Spans (NULL) +FBuildTexture::FBuildTexture(const FString &pathprefix, int tilenum, const uint8_t *pixels, int translation, int width, int height, int left, int top) +: RawPixels (pixels), Translation(translation) { + PixelsAreStatic = 3; Width = width; Height = height; LeftOffset = left; TopOffset = top; CalcBitSize (); - Name.Format("BTIL%04d", tilenum); - UseType = TEX_Build; + Name.Format("%sBTIL%04d", pathprefix.GetChars(), tilenum); + UseType = TEX_Override; } -//========================================================================== -// -// -// -//========================================================================== - -FBuildTexture::~FBuildTexture () +uint8_t *FBuildTexture::MakeTexture(FRenderStyle style) { - if (Spans != NULL) + auto Pixels = new uint8_t[Width * Height]; + FRemapTable *Remap = translationtables[TRANSLATION_Standard][Translation]; + for (int i = 0; i < Width*Height; i++) { - FreeSpans (Spans); - Spans = NULL; + auto c = RawPixels[i]; + Pixels[i] = (style.Flags & STYLEF_RedIsAlpha) ? Remap->Palette[c].r : Remap->Remap[c]; } + return (uint8_t*)RawPixels; } -//========================================================================== -// -// -// -//========================================================================== - -const uint8_t *FBuildTexture::GetPixels () +int FBuildTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf) { - return Pixels; -} + PalEntry *Remap = translationtables[TRANSLATION_Standard][Translation]->Palette; + bmp->CopyPixelData(x, y, RawPixels, Width, Height, Height, 1, rotate, Remap, inf); + return 0; -//========================================================================== -// -// -// -//========================================================================== - -const uint8_t *FBuildTexture::GetColumn (unsigned int column, const Span **spans_out) -{ - if (column >= 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; } //=========================================================================== @@ -145,15 +116,16 @@ const uint8_t *FBuildTexture::GetColumn (unsigned int column, const Span **spans // //=========================================================================== -void FTextureManager::AddTiles (void *tiles) +void FTextureManager::AddTiles (const FString &pathprefix, const void *tiles, int translation) { + // int numtiles = LittleLong(((uint32_t *)tiles)[1]); // This value is not reliable int tilestart = LittleLong(((uint32_t *)tiles)[2]); int tileend = LittleLong(((uint32_t *)tiles)[3]); const uint16_t *tilesizx = &((const uint16_t *)tiles)[8]; const uint16_t *tilesizy = &tilesizx[tileend - tilestart + 1]; const uint32_t *picanm = (const uint32_t *)&tilesizy[tileend - tilestart + 1]; - uint8_t *tiledata = (uint8_t *)&picanm[tileend - tilestart + 1]; + const uint8_t *tiledata = (const uint8_t *)&picanm[tileend - tilestart + 1]; for (int i = tilestart; i <= tileend; ++i) { @@ -169,15 +141,12 @@ void FTextureManager::AddTiles (void *tiles) if (width <= 0 || height <= 0) continue; - tex = new FBuildTexture (i, tiledata, width, height, xoffs, yoffs); + tex = new FBuildTexture (pathprefix, i, tiledata, translation, width, height, xoffs, yoffs); texnum = AddTexture (tex); - while (size > 0) - { - *tiledata = 255 - *tiledata; - tiledata++; - size--; - } - StartScreen->Progress(); + tiledata += size; + + // reactivate only if the texture counter works here. + //StartScreen->Progress(); if ((picanm[pic] & 63) && (picanm[pic] & 192)) { @@ -251,7 +220,7 @@ void FTextureManager::AddTiles (void *tiles) // //=========================================================================== -int FTextureManager::CountTiles (void *tiles) +static int CountTiles (const void *tiles) { int version = LittleLong(*(uint32_t *)tiles); if (version != 1) @@ -265,6 +234,60 @@ int FTextureManager::CountTiles (void *tiles) return tileend >= tilestart ? tileend - tilestart + 1 : 0; } +//=========================================================================== +// +// Create palette data and remap table for the tile set's palette +// +//=========================================================================== + +static int BuildPaletteTranslation(int lump) +{ + if (Wads.LumpLength(lump) < 768) + { + return false; + } + + FMemLump data = Wads.ReadLump(lump); + const uint8_t *ipal = (const uint8_t *)data.GetMem(); + FRemapTable opal; + + bool blood = false; + for (int c = 0; c < 765; c++) // Build used VGA palettes (color values 0..63), Blood used full palettes (0..255) Let's hope this doesn't screw up... + { + if (ipal[c] >= 64) + { + blood = true; + break; + } + } + + for (int c = 0; c < 255; c++) + { + int r, g, b; + if (!blood) + { + r = (ipal[3*c ] << 2) | (ipal[3 * c ] >> 4); + g = (ipal[3*c + 1] << 2) | (ipal[3 * c + 1] >> 4); + b = (ipal[3*c + 2] << 2) | (ipal[3 * c + 2] >> 4); + } + else + { + r = ipal[3 * c] << 2; + g = ipal[3 * c + 1] << 2; + b = ipal[3 * c + 2] << 2; + } + opal.Palette[c] = PalEntry(255, r, g, b); + opal.Remap[c] = ColorMatcher.Pick(r, g, b); + } + // The last entry is transparent. + opal.Palette[255] = 0; + opal.Remap[255] = 0; + // Store the remap table in the translation manager so that we do not need to keep track of it ourselves. + // Slot 0 for internal translations is a convenient location because normally it only contains a small number of translations. + return GetTranslationIndex(opal.StoreTranslation(TRANSLATION_Standard)); +} + + //=========================================================================== // // R_CountBuildTiles @@ -274,98 +297,59 @@ int FTextureManager::CountTiles (void *tiles) // //=========================================================================== -int FTextureManager::CountBuildTiles () +void FTextureManager::InitBuildTiles() { - int numartfiles = 0; - char artfile[] = "tilesXXX.art"; int lumpnum; int numtiles; int totaltiles = 0; - lumpnum = Wads.CheckNumForFullName ("blood.pal"); - if (lumpnum >= 0) + // The search rules are as follows: + // - scan the entire lump directory for palette.dat files. + // - if one is found, process the directory for .ART files and add textures for them. + // - once all have been found, process all directories that may contain Build data. + // - the root is not excluded which allows to read this from .GRP files as well. + // - Blood support has been removed because it is not useful for modding to have loose .ART files. + // + // Unfortunately neither the palettes nor the .ART files contain any usable identifying marker + // so this can only go by the file names. + + int numlumps = Wads.GetNumLumps(); + for (int i = 0; i < numlumps; i++) { - // Blood's tiles are external resources. (Why did they do it like that?) - FString rffpath = Wads.GetWadFullName (Wads.GetLumpFile (lumpnum)); - int slashat = rffpath.LastIndexOf ('/'); - if (slashat >= 0) + const char *name = Wads.GetLumpFullName(i); + if (Wads.CheckNumForFullName(name) != i) continue; // This palette is hidden by a later one. Do not process + FString base = ExtractFileBase(name, true); + base.ToLower(); + if (base.Compare("palette.dat") == 0 && Wads.LumpLength(i) >= 768) // must be a valid palette, i.e. at least 256 colors. { - rffpath.Truncate (slashat + 1); - } - else - { - rffpath += '/'; - } + FString path = ExtractFilePath(name); + if (path.IsNotEmpty() && path.Back() != '/') path += '/'; - for (; numartfiles < 1000; numartfiles++) - { - artfile[5] = numartfiles / 100 + '0'; - artfile[6] = numartfiles / 10 % 10 + '0'; - artfile[7] = numartfiles % 10 + '0'; - - FString artpath = rffpath; - artpath += artfile; - - FileReader fr; - - if (!fr.OpenFile(artpath)) + int translation = BuildPaletteTranslation(i); + for (int numartfiles = 0; numartfiles < 1000; numartfiles++) { - break; - } + FStringf artpath("%stiles%03d.art", path.GetChars(), numartfiles); + // only read from the same source as the palette. + // The entire format here is just too volatile to allow liberal mixing. + // An .ART set must be treated as one unit. + lumpnum = Wads.CheckNumForFullName(artpath, Wads.GetLumpFile(i)); + if (lumpnum < 0) + { + break; + } - auto len = fr.GetLength(); - uint8_t *art = new uint8_t[len]; - if (fr.Read (art, len) != len || (numtiles = CountTiles(art)) == 0) - { - delete[] art; - } - else - { - BuildTileFiles.Push (art); - totaltiles += numtiles; + BuildTileData.Reserve(1); + auto &artdata = BuildTileData.Last(); + artdata.Resize(Wads.LumpLength(lumpnum)); + Wads.ReadLump(lumpnum, &artdata[0]); + + if ((numtiles = CountTiles(&artdata[0])) > 0) + { + AddTiles(path, &artdata[0], translation); + totaltiles += numtiles; + } } } } - - for (; numartfiles < 1000; numartfiles++) - { - artfile[5] = numartfiles / 100 + '0'; - artfile[6] = numartfiles / 10 % 10 + '0'; - artfile[7] = numartfiles % 10 + '0'; - lumpnum = Wads.CheckNumForFullName (artfile); - if (lumpnum < 0) - { - break; - } - - uint8_t *art = new uint8_t[Wads.LumpLength (lumpnum)]; - Wads.ReadLump (lumpnum, art); - - if ((numtiles = CountTiles(art)) == 0) - { - delete[] art; - } - else - { - BuildTileFiles.Push (art); - totaltiles += numtiles; - } - } - return totaltiles; } -//=========================================================================== -// -// R_InitBuildTiles -// -// [RH] Support Build tiles! -// -//=========================================================================== - -void FTextureManager::InitBuildTiles () -{ - for (unsigned int i = 0; i < BuildTileFiles.Size(); ++i) - { - AddTiles (BuildTileFiles[i]); - } -} diff --git a/src/textures/canvastexture.cpp b/src/textures/canvastexture.cpp index d2530017b..e13dd6d3d 100644 --- a/src/textures/canvastexture.cpp +++ b/src/textures/canvastexture.cpp @@ -65,12 +65,12 @@ FCanvasTexture::~FCanvasTexture () Unload (); } -const uint8_t *FCanvasTexture::GetColumn (unsigned int column, const Span **spans_out) +const uint8_t *FCanvasTexture::GetColumn(FRenderStyle style, unsigned int column, const Span **spans_out) { bNeedsUpdate = true; if (Canvas == NULL) { - MakeTexture (); + MakeTexture (style); } if ((unsigned)column >= (unsigned)Width) { @@ -90,12 +90,12 @@ const uint8_t *FCanvasTexture::GetColumn (unsigned int column, const Span **span return Pixels + column*Height; } -const uint8_t *FCanvasTexture::GetPixels () +const uint8_t *FCanvasTexture::GetPixels (FRenderStyle style) { bNeedsUpdate = true; if (Canvas == NULL) { - MakeTexture (); + MakeTexture (style); } return Pixels; } @@ -110,7 +110,7 @@ const uint32_t *FCanvasTexture::GetPixelsBgra() return PixelsBgra; } -void FCanvasTexture::MakeTexture () +void FCanvasTexture::MakeTexture (FRenderStyle) // This ignores the render style because making it work as alpha texture is impractical. { Canvas = new DSimpleCanvas (Width, Height, false); Canvas->Lock (); @@ -183,7 +183,7 @@ void FCanvasTexture::Unload () FTexture::Unload(); } -bool FCanvasTexture::CheckModified () +bool FCanvasTexture::CheckModified (FRenderStyle) { if (bDidUpdate) { 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..33ecaf148 100644 --- a/src/textures/jpegtexture.cpp +++ b/src/textures/jpegtexture.cpp @@ -179,27 +179,15 @@ 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 +247,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 +257,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 +276,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 +419,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..8571f820b 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: @@ -198,10 +195,16 @@ protected: int NumParts; TexPart *Parts; TexInit *Inits; - bool bRedirect:1; - bool bTranslucentPatches:1; + bool bRedirect; + bool bTranslucentPatches; + + uint8_t *MakeTexture (FRenderStyle style); + + // The getters must optionally redirect if it's a simple one-patch texture. + const uint8_t *GetPixels(FRenderStyle style) override { return bRedirect ? Parts->Texture->GetPixels(style) : FWorldTexture::GetPixels(style); } + const uint8_t *GetColumn(FRenderStyle style, unsigned int col, const Span **out) override + { return bRedirect ? Parts->Texture->GetColumn(style, col, out) : FWorldTexture::GetColumn(style, col, out); } - void MakeTexture (); private: void CheckForHacks (); @@ -323,11 +326,6 @@ FMultiPatchTexture::~FMultiPatchTexture () delete[] Inits; Inits = nullptr; } - if (Spans != NULL) - { - FreeSpans (Spans); - Spans = NULL; - } } //========================================================================== @@ -345,80 +343,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 +351,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 +403,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 +469,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 +477,7 @@ void FMultiPatchTexture::MakeTexture () } delete [] buffer; } + return Pixels; } //=========================================================================== @@ -755,14 +694,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..f5635c7a3 100644 --- a/src/textures/pcxtexture.cpp +++ b/src/textures/pcxtexture.cpp @@ -81,32 +81,23 @@ 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 +145,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 +170,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 +371,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 +391,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 +418,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 +445,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..adf8abfff 100644 --- a/src/textures/rawpagetexture.cpp +++ b/src/textures/rawpagetexture.cpp @@ -46,21 +46,11 @@ // //========================================================================== -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 +145,6 @@ FTexture *RawPageTexture_TryCreate(FileReader & file, int lumpnum) } -//========================================================================== -// -// -// -//========================================================================== - -const FTexture::Span FRawPageTexture::DummySpans[2] = -{ - { 0, 200 }, { 0, 0 } -}; - //========================================================================== // // @@ -173,7 +152,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 +167,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 +182,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/shadertexture.cpp b/src/textures/shadertexture.cpp index 93e423470..67d4db683 100644 --- a/src/textures/shadertexture.cpp +++ b/src/textures/shadertexture.cpp @@ -49,9 +49,11 @@ #include "r_defs.h" #include "r_state.h" #include "r_data/r_translate.h" +#include "r_data/renderstyle.h" +#include "bitmap.h" -class FBarShader : public FTexture +class FBarShader : public FWorldTexture { public: FBarShader(bool vertical, bool reverse) @@ -62,6 +64,7 @@ public: Width = vertical ? 2 : 256; Height = vertical ? 256 : 2; CalcBitSize(); + PixelsAreStatic = 2; // The alpha buffer is static, but if this gets used as a regular texture, a separate buffer needs to be made. // Fill the column/row with shading values. // Vertical shaders have have minimum alpha at the top @@ -106,24 +109,42 @@ public: } } } - DummySpan[0].TopOffset = 0; - DummySpan[0].Length = vertical ? 256 : 2; - DummySpan[1].TopOffset = 0; - DummySpan[1].Length = 0; } - const uint8_t *GetColumn(unsigned int column, const Span **spans_out) + + uint8_t *MakeTexture(FRenderStyle style) override { - if (spans_out != NULL) + if (style.Flags & STYLEF_RedIsAlpha) { - *spans_out = DummySpan; + return Pixels; + } + else + { + // Since this presents itself to the game as a regular named texture + // it can easily be used on walls and flats and should work as such, + // even if it makes little sense. + auto Pix = new uint8_t[512]; + for (int i = 0; i < 512; i++) + { + Pix[i] = GrayMap[Pixels[i]]; + } + return Pix; } - return Pixels + ((column & WidthMask) << HeightBits); } - const uint8_t *GetPixels() { return Pixels; } - void Unload() {} + + int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL) override + { + bmp->CopyPixelData(x, y, Pixels, Width, Height, Height, 1, rotate, translationtables[TRANSLATION_Standard][8]->Palette, inf); + return 0; + } + + bool UseBasePalette() override + { + return false; + } + + private: uint8_t Pixels[512]; - Span DummySpan[2]; }; diff --git a/src/textures/skyboxtexture.cpp b/src/textures/skyboxtexture.cpp index 9c3b21b67..5270af937 100644 --- a/src/textures/skyboxtexture.cpp +++ b/src/textures/skyboxtexture.cpp @@ -59,9 +59,9 @@ FSkyBox::~FSkyBox() // //----------------------------------------------------------------------------- -const uint8_t *FSkyBox::GetColumn (unsigned int column, const Span **spans_out) +const uint8_t *FSkyBox::GetColumn(FRenderStyle style, unsigned int column, const Span **spans_out) { - if (faces[0]) return faces[0]->GetColumn(column, spans_out); + if (faces[0]) return faces[0]->GetColumn(style, column, spans_out); return NULL; } @@ -71,9 +71,9 @@ const uint8_t *FSkyBox::GetColumn (unsigned int column, const Span **spans_out) // //----------------------------------------------------------------------------- -const uint8_t *FSkyBox::GetPixels () +const uint8_t *FSkyBox::GetPixels (FRenderStyle style) { - if (faces[0]) return faces[0]->GetPixels(); + if (faces[0]) return faces[0]->GetPixels(style); return NULL; } diff --git a/src/textures/skyboxtexture.h b/src/textures/skyboxtexture.h index 3a4edd042..a6048ce58 100644 --- a/src/textures/skyboxtexture.h +++ b/src/textures/skyboxtexture.h @@ -17,8 +17,8 @@ public: FSkyBox(); ~FSkyBox(); - const uint8_t *GetColumn (unsigned int column, const Span **spans_out); - const uint8_t *GetPixels (); + const uint8_t *GetColumn(FRenderStyle style, unsigned int column, const Span **spans_out); + const uint8_t *GetPixels (FRenderStyle style); int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf); bool UseBasePalette(); void Unload (); diff --git a/src/textures/texture.cpp b/src/textures/texture.cpp index 212f53a03..2b6ec321c 100644 --- a/src/textures/texture.cpp +++ b/src/textures/texture.cpp @@ -183,19 +183,20 @@ void FTexture::Unload() const uint32_t *FTexture::GetColumnBgra(unsigned int column, const Span **spans_out) { const uint32_t *pixels = GetPixelsBgra(); + if (pixels == nullptr) return nullptr; column %= Width; if (spans_out != nullptr) - GetColumn(column, spans_out); + GetColumn(DefaultRenderStyle(), column, spans_out); // This isn't the right way to create the spans. return pixels + column * Height; } const uint32_t *FTexture::GetPixelsBgra() { - if (PixelsBgra.empty() || CheckModified()) + if (PixelsBgra.empty() || CheckModified(DefaultRenderStyle())) { - if (!GetColumn(0, nullptr)) + if (!GetColumn(DefaultRenderStyle(), 0, nullptr)) return nullptr; FBitmap bitmap; @@ -206,7 +207,7 @@ const uint32_t *FTexture::GetPixelsBgra() return PixelsBgra.data(); } -bool FTexture::CheckModified () +bool FTexture::CheckModified (FRenderStyle) { return false; } @@ -248,10 +249,6 @@ void FTexture::CalcBitSize () HeightBits = i; } -void FTexture::HackHack (int newheight) -{ -} - FTexture::Span **FTexture::CreateSpans (const uint8_t *pixels) const { Span **spans, *span; @@ -286,6 +283,7 @@ FTexture::Span **FTexture::CreateSpans (const uint8_t *pixels) const newspan = true; for (y = numrows; y > 0; --y) { + if (*data_p++ == 0) { if (!newspan) @@ -554,14 +552,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)) { @@ -723,7 +722,7 @@ FNativeTexture *FTexture::GetNative(bool wrapping) } else { - if (CheckModified()) + if (CheckModified(DefaultRenderStyle())) { Native->Update(); } @@ -743,12 +742,6 @@ void FTexture::KillNative() } } -// For this generic implementation, we just call GetPixels and copy that data -// to the buffer. Texture formats that can do better than paletted images -// should provide their own implementation that may preserve the original -// color data. Note that the buffer expects row-major data, since that's -// generally more convenient for any non-Doom image formats, and it doesn't -// need to be used by any of Doom's column drawing routines. void FTexture::FillBuffer(uint8_t *buff, int pitch, int height, FTextureFormat fmt) { const uint8_t *pix; @@ -761,7 +754,7 @@ void FTexture::FillBuffer(uint8_t *buff, int pitch, int height, FTextureFormat f { case TEX_Pal: case TEX_Gray: - pix = GetPixels(); + pix = GetPixels(DefaultRenderStyle()); stride = pitch - w; for (y = 0; y < h; ++y) { @@ -805,14 +798,14 @@ int FTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyI { PalEntry *palette = screen->GetPalette(); for(int i=1;i<256;i++) palette[i].a = 255; // set proper alpha values - bmp->CopyPixelData(x, y, GetPixels(), Width, Height, Height, 1, rotate, palette, inf); + bmp->CopyPixelData(x, y, GetPixels(DefaultRenderStyle()), Width, Height, Height, 1, rotate, palette, inf); for(int i=1;i<256;i++) palette[i].a = 0; return 0; } int FTexture::CopyTrueColorTranslated(FBitmap *bmp, int x, int y, int rotate, PalEntry *remap, FCopyInfo *inf) { - bmp->CopyPixelData(x, y, GetPixels(), Width, Height, Height, 1, rotate, remap, inf); + bmp->CopyPixelData(x, y, GetPixels(DefaultRenderStyle()), Width, Height, Height, 1, rotate, remap, inf); return 0; } @@ -923,7 +916,7 @@ int FTexture::CheckRealHeight() for (int i = 0; i < GetWidth(); ++i) { - GetColumn(i, &span); + GetColumn(DefaultRenderStyle(), i, &span); while (span->Length != 0) { if (span->TopOffset < miny) @@ -963,16 +956,15 @@ void FDummyTexture::SetSize (int width, int height) CalcBitSize (); } -// This must never be called -const uint8_t *FDummyTexture::GetColumn (unsigned int column, const Span **spans_out) +// These only get called from the texture precacher which discards the result. +const uint8_t *FDummyTexture::GetColumn(FRenderStyle style, unsigned int column, const Span **spans_out) { - return NULL; + return nullptr; } -// And this also must never be called -const uint8_t *FDummyTexture::GetPixels () +const uint8_t *FDummyTexture::GetPixels(FRenderStyle style) { - return NULL; + return nullptr; } //========================================================================== @@ -999,7 +991,7 @@ CCMD (printspans) { const FTexture::Span *spans; Printf ("%4d:", x); - tex->GetColumn (x, &spans); + tex->GetColumn(DefaultRenderStyle(), x, &spans); while (spans->Length != 0) { Printf (" (%4d,%4d)", spans->TopOffset, spans->TopOffset+spans->Length-1); diff --git a/src/textures/texturemanager.cpp b/src/textures/texturemanager.cpp index cdaf17a49..b16b5bd5e 100644 --- a/src/textures/texturemanager.cpp +++ b/src/textures/texturemanager.cpp @@ -137,12 +137,7 @@ void FTextureManager::DeleteAll() } } mAnimatedDoors.Clear(); - - for (unsigned int i = 0; i < BuildTileFiles.Size(); ++i) - { - delete[] BuildTileFiles[i]; - } - BuildTileFiles.Clear(); + BuildTileData.Clear(); } //========================================================================== @@ -982,8 +977,7 @@ void FTextureManager::Init() { DeleteAll(); SpriteFrames.Clear(); - // Init Build Tile data if it hasn't been done already - if (BuildTileFiles.Size() == 0) CountBuildTiles (); + //if (BuildTileFiles.Size() == 0) CountBuildTiles (); FTexture::InitGrayMap(); // Texture 0 is a dummy texture used to indicate "no texture" @@ -1131,7 +1125,7 @@ int FTextureManager::GuesstimateNumTextures () } } - numtex += CountBuildTiles (); + //numtex += CountBuildTiles (); // this cannot be done with a lot of overhead so just leave it out. numtex += CountTexturesX (); return numtex; } diff --git a/src/textures/textures.h b/src/textures/textures.h index 006d24bb7..52fd089c8 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 @@ -206,7 +207,6 @@ public: TEX_Flat, TEX_Sprite, TEX_WallPatch, - TEX_Build, TEX_SkinSprite, TEX_Decal, TEX_MiscPatch, @@ -225,13 +225,13 @@ 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(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(FRenderStyle style) = 0; // Returns the whole texture, stored in column-major order, in BGRA8 format virtual const uint32_t *GetPixelsBgra(); @@ -277,17 +277,12 @@ 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() // is immediately followed by a call to GetPixels(). - virtual bool CheckModified (); + virtual bool CheckModified (FRenderStyle style); static void InitGrayMap(); @@ -307,8 +302,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]; @@ -528,9 +521,8 @@ private: int CountLumpTextures (int lumpnum); // Build tiles - void AddTiles (void *tiles); - int CountTiles (void *tiles); - int CountBuildTiles (); + void AddTiles (const FString &pathprefix, const void *, int translation); + //int CountBuildTiles (); void InitBuildTiles (); // Animation stuff @@ -572,11 +564,12 @@ private: FTextureID DefaultTexture; TArray FirstTextureForFile; TMap PalettedVersions; // maps from normal -> paletted version + TArray > BuildTileData; TArray mAnimations; TArray mSwitchDefs; TArray mAnimatedDoors; - TArray BuildTileFiles; + public: short sintable[2048]; // for texture warping enum @@ -585,45 +578,60 @@ 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 }; + uint8_t PixelsAreStatic = 0; // can be set by subclasses which provide static pixel buffers. + + FWorldTexture(const char *name = nullptr, int lumpnum = -1); + ~FWorldTexture(); + + const uint8_t *GetColumn(FRenderStyle style, unsigned int column, const Span **spans_out) override; + const uint8_t *GetPixels(FRenderStyle style) override; + void Unload() override; + virtual uint8_t *MakeTexture(FRenderStyle style) = 0; + void FreeAllSpans(); +}; + // A texture that doesn't really exist class FDummyTexture : public FTexture { public: FDummyTexture (); - const uint8_t *GetColumn (unsigned int column, const Span **spans_out); - const uint8_t *GetPixels (); + const uint8_t *GetColumn(FRenderStyle style, unsigned int column, const Span **spans_out) override; + const uint8_t *GetPixels(FRenderStyle style) override; void SetSize (int width, int height); }; // A texture that returns a wiggly version of another texture. -class FWarpTexture : public FTexture +class FWarpTexture : public FWorldTexture { public: FWarpTexture (FTexture *source, int warptype); ~FWarpTexture (); + void Unload() override; - virtual int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate=0, FCopyInfo *inf = NULL); - const uint8_t *GetColumn (unsigned int column, const Span **spans_out); - const uint8_t *GetPixels (); + virtual int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate=0, FCopyInfo *inf = NULL) override; const uint32_t *GetPixelsBgra() override; - void Unload (); - bool CheckModified (); + bool CheckModified (FRenderStyle) override; float GetSpeed() const { return Speed; } int GetSourceLump() { return SourcePic->GetSourceLump(); } void SetSpeed(float fac) { Speed = fac; } FTexture *GetRedirect(bool wantwarped); - uint64_t GenTime; - uint64_t GenTimeBgra; - float Speed; + uint64_t GenTime[2] = { 0, 0 }; + uint64_t GenTimeBgra = 0; + float Speed = 1.f; int WidthOffsetMultiplier, HeightOffsetMultiplier; // [mxd] protected: FTexture *SourcePic; - uint8_t *Pixels; - Span **Spans; - virtual void MakeTexture (uint64_t time); + uint8_t *MakeTexture (FRenderStyle style) override; int NextPo2 (int v); // [mxd] void SetupMultipliers (int width, int height); // [mxd] }; @@ -638,17 +646,17 @@ public: FCanvasTexture (const char *name, int width, int height); ~FCanvasTexture (); - const uint8_t *GetColumn (unsigned int column, const Span **spans_out); - const uint8_t *GetPixels (); + const uint8_t *GetColumn(FRenderStyle style, unsigned int column, const Span **spans_out); + const uint8_t *GetPixels (FRenderStyle style); const uint32_t *GetPixelsBgra() override; void Unload (); - bool CheckModified (); + bool CheckModified (FRenderStyle) override; void NeedUpdate() { bNeedsUpdate=true; } void SetUpdated() { bNeedsUpdate = false; bDidUpdate = true; bFirstUpdate = false; } DSimpleCanvas *GetCanvas() { return Canvas; } DSimpleCanvas *GetCanvasBgra() { return CanvasBgra; } bool Mipmapped() override { return false; } - void MakeTexture (); + void MakeTexture (FRenderStyle style); void MakeTextureBgra (); protected: 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;xUnload (); - FTexture::Unload(); + FWorldTexture::Unload(); + FreeAllSpans(); } -bool FWarpTexture::CheckModified () +bool FWarpTexture::CheckModified (FRenderStyle style) { - return screen->FrameTime != GenTime; -} - -const uint8_t *FWarpTexture::GetPixels () -{ - uint64_t time = screen->FrameTime; - - if (Pixels == NULL || time != GenTime) - { - MakeTexture (time); - } - return Pixels; + return screen->FrameTime != GenTime[!!(style.Flags & STYLEF_RedIsAlpha)]; } const uint32_t *FWarpTexture::GetPixelsBgra() { - uint64_t time = screen->FrameTime; - if (Pixels == NULL || time != GenTime) - MakeTexture(time); - - if (PixelsBgra.empty() || time != GenTimeBgra) + auto Pixels = GetPixels(DefaultRenderStyle()); + if (PixelsBgra.empty() || GenTime[0] != GenTimeBgra) { CreatePixelsBgraWithMipmaps(); for (int i = 0; i < Width * Height; i++) @@ -112,58 +84,21 @@ const uint32_t *FWarpTexture::GetPixelsBgra() PixelsBgra[i] = 0; } GenerateBgraMipmapsFast(); - GenTimeBgra = time; + GenTimeBgra = GenTime[0]; } return PixelsBgra.data(); } -const uint8_t *FWarpTexture::GetColumn (unsigned int column, const Span **spans_out) + +uint8_t *FWarpTexture::MakeTexture(FRenderStyle style) { - uint64_t time =screen->FrameTime; - - if (Pixels == NULL || time != GenTime) - { - MakeTexture (time); - } - 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 FWarpTexture::MakeTexture(uint64_t time) -{ - const uint8_t *otherpix = SourcePic->GetPixels(); - - if (Pixels == NULL) - { - Pixels = new uint8_t[Width * Height]; - } - if (Spans != NULL) - { - FreeSpans(Spans); - Spans = NULL; - } - - GenTime = time; + uint64_t time = screen->FrameTime; + const uint8_t *otherpix = SourcePic->GetPixels(style); + auto Pixels = new uint8_t[Width * Height]; WarpBuffer(Pixels, otherpix, Width, Height, WidthOffsetMultiplier, HeightOffsetMultiplier, time, Speed, bWarped); + FreeAllSpans(); + GenTime[!!(style.Flags & STYLEF_RedIsAlpha)] = time; + return Pixels; } // [mxd] Non power of 2 textures need different offset multipliers, otherwise warp animation won't sync across texture diff --git a/src/textures/worldtexture.cpp b/src/textures/worldtexture.cpp new file mode 100644 index 000000000..db50c7fb4 --- /dev/null +++ b/src/textures/worldtexture.cpp @@ -0,0 +1,150 @@ +/* +** worldtexture.cpp +** Intermediate class for some common code for several classes +** +**--------------------------------------------------------------------------- +** Copyright 2018 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +** +*/ + +#include "textures.h" + + +//========================================================================== +// +// +// +//========================================================================== + +FWorldTexture::FWorldTexture(const char *name, int lumpnum) + : FTexture(name, lumpnum) +{ +} + +//========================================================================== +// +// +// +//========================================================================== + +FWorldTexture::~FWorldTexture() +{ + Unload(); + FreeAllSpans(); +} + +//========================================================================== +// +// +// +//========================================================================== + +void FWorldTexture::FreeAllSpans() +{ + for(int i = 0; i < 2; i++) + { + if (Spandata[i] != nullptr) + { + FreeSpans (Spandata[i]); + Spandata[i] = nullptr; + } + } +} + +//========================================================================== +// +// +// +//========================================================================== + +void FWorldTexture::Unload () +{ + for(int i = 0; i < 2; i++) + { + if (!(PixelsAreStatic & (1 << i))) + { + delete[] Pixeldata[i]; + } + Pixeldata[i] = nullptr; + } + FTexture::Unload(); +} + +//========================================================================== +// +// +// +//========================================================================== + +const uint8_t *FWorldTexture::GetColumn(FRenderStyle style, unsigned int column, const Span **spans_out) +{ + int index = !!(style.Flags & STYLEF_RedIsAlpha); + GetPixels(style); + if ((unsigned)column >= (unsigned)Width) + { + if (WidthMask + 1 == Width) + { + column &= WidthMask; + } + else + { + column %= Width; + } + } + if (spans_out != nullptr) + { + if (Spandata[index] == nullptr) + { + Spandata[index] = CreateSpans (Pixeldata[index]); + } + *spans_out = Spandata[index][column]; + } + return Pixeldata[index] + column*Height; +} + +//========================================================================== +// +// +// +//========================================================================== + +const uint8_t *FWorldTexture::GetPixels (FRenderStyle style) +{ + if (CheckModified(style)) + { + Unload(); + } + int index = !!(style.Flags & STYLEF_RedIsAlpha); + if (Pixeldata[index] == nullptr) + { + Pixeldata[index] = MakeTexture (style); + } + return Pixeldata[index]; +} + diff --git a/src/v_font.cpp b/src/v_font.cpp index a8afa079c..e38ecfbde 100644 --- a/src/v_font.cpp +++ b/src/v_font.cpp @@ -177,8 +177,8 @@ class FFontChar1 : public FTexture { public: FFontChar1 (FTexture *sourcelump); - const uint8_t *GetColumn (unsigned int column, const Span **spans_out); - const uint8_t *GetPixels (); + const uint8_t *GetColumn(FRenderStyle style, unsigned int column, const Span **spans_out); + const uint8_t *GetPixels (FRenderStyle style); void SetSourceRemap(const uint8_t *sourceremap); void Unload (); ~FFontChar1 (); @@ -198,8 +198,8 @@ public: FFontChar2 (int sourcelump, int sourcepos, int width, int height, int leftofs=0, int topofs=0); ~FFontChar2 (); - const uint8_t *GetColumn (unsigned int column, const Span **spans_out); - const uint8_t *GetPixels (); + const uint8_t *GetColumn(FRenderStyle style, unsigned int column, const Span **spans_out); + const uint8_t *GetPixels (FRenderStyle style); void SetSourceRemap(const uint8_t *sourceremap); void Unload (); @@ -559,7 +559,7 @@ void RecordTextureColors (FTexture *pic, uint8_t *usedcolors) for (x = pic->GetWidth() - 1; x >= 0; x--) { const FTexture::Span *spans; - const uint8_t *column = pic->GetColumn (x, &spans); + const uint8_t *column = pic->GetColumn(DefaultRenderStyle(), x, &spans); // This shouldn't use the spans... while (spans->Length != 0) { @@ -1649,9 +1649,11 @@ FFontChar1::FFontChar1 (FTexture *sourcelump) // // FFontChar1 :: GetPixels // +// Render style is not relevant for fonts. This must not use it! +// //========================================================================== -const uint8_t *FFontChar1::GetPixels () +const uint8_t *FFontChar1::GetPixels (FRenderStyle) { if (Pixels == NULL) { @@ -1666,12 +1668,12 @@ const uint8_t *FFontChar1::GetPixels () // //========================================================================== -void FFontChar1::MakeTexture () +void FFontChar1::MakeTexture () { // Make the texture as normal, then remap it so that all the colors // are at the low end of the palette Pixels = new uint8_t[Width*Height]; - const uint8_t *pix = BaseTexture->GetPixels(); + const uint8_t *pix = BaseTexture->GetPixels(DefaultRenderStyle()); if (!SourceRemap) { @@ -1692,14 +1694,14 @@ void FFontChar1::MakeTexture () // //========================================================================== -const uint8_t *FFontChar1::GetColumn (unsigned int column, const Span **spans_out) +const uint8_t *FFontChar1::GetColumn(FRenderStyle, unsigned int column, const Span **spans_out) { if (Pixels == NULL) { MakeTexture (); } - BaseTexture->GetColumn(column, spans_out); + BaseTexture->GetColumn(DefaultRenderStyle(), column, spans_out); return Pixels + column*Height; } @@ -1797,9 +1799,11 @@ void FFontChar2::Unload () // // FFontChar2 :: GetPixels // +// Like for FontChar1, the render style has no relevance here as well. +// //========================================================================== -const uint8_t *FFontChar2::GetPixels () +const uint8_t *FFontChar2::GetPixels (FRenderStyle) { if (Pixels == NULL) { @@ -1814,7 +1818,7 @@ const uint8_t *FFontChar2::GetPixels () // //========================================================================== -const uint8_t *FFontChar2::GetColumn (unsigned int column, const Span **spans_out) +const uint8_t *FFontChar2::GetColumn(FRenderStyle, unsigned int column, const Span **spans_out) { if (Pixels == NULL) { diff --git a/src/v_palette.cpp b/src/v_palette.cpp index 11e3f6945..654526a20 100644 --- a/src/v_palette.cpp +++ b/src/v_palette.cpp @@ -340,69 +340,20 @@ void ReadPalette(int lumpnum, uint8_t *buffer) } } -static bool FixBuildPalette (uint8_t *opal, int lump, bool blood) -{ - if (Wads.LumpLength (lump) < 768) - { - return false; - } - - FMemLump data = Wads.ReadLump (lump); - const uint8_t *ipal = (const uint8_t *)data.GetMem(); - - // Reverse the palette because BUILD used entry 255 as - // transparent, but we use 0 as transparent. - - for (int c = 0; c < 768; c += 3) - { - if (!blood) - { - opal[c] = (ipal[765-c] << 2) | (ipal[765-c] >> 4); - opal[c+1] = (ipal[766-c] << 2) | (ipal[766-c] >> 4); - opal[c+2] = (ipal[767-c] << 2) | (ipal[767-c] >> 4); - } - else - { - opal[c] = ipal[765-c]; - opal[c+1] = ipal[766-c]; - opal[c+2] = ipal[767-c]; - } - } - return true; -} - void InitPalette () { uint8_t pal[768]; - bool usingBuild = false; - int lump; - - if ((lump = Wads.CheckNumForFullName ("palette.dat")) >= 0 && Wads.LumpLength (lump) >= 768) - { - usingBuild = FixBuildPalette (pal, lump, false); - } - else if ((lump = Wads.CheckNumForFullName ("blood.pal")) >= 0 && Wads.LumpLength (lump) >= 768) - { - usingBuild = FixBuildPalette (pal, lump, true); - } - - if (!usingBuild) - { - ReadPalette(Wads.CheckNumForName("PLAYPAL"), pal); - } + + ReadPalette(Wads.CheckNumForName("PLAYPAL"), pal); GPalette.SetPalette (pal); GPalette.MakeGoodRemap (); ColorMatcher.SetPalette ((uint32_t *)GPalette.BaseColors); - // The BUILD engine already has a transparent color, so it doesn't need any remapping. - if (!usingBuild) - { - if (GPalette.Remap[0] == 0) - { // No duplicates, so settle for something close to color 0 - GPalette.Remap[0] = BestColor ((uint32_t *)GPalette.BaseColors, - GPalette.BaseColors[0].r, GPalette.BaseColors[0].g, GPalette.BaseColors[0].b, 1, 255); - } + if (GPalette.Remap[0] == 0) + { // No duplicates, so settle for something close to color 0 + GPalette.Remap[0] = BestColor ((uint32_t *)GPalette.BaseColors, + GPalette.BaseColors[0].r, GPalette.BaseColors[0].g, GPalette.BaseColors[0].b, 1, 255); } // Colormaps have to be initialized before actors are loaded, diff --git a/src/v_video.cpp b/src/v_video.cpp index ca2e8b62a..5e86b915b 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -135,9 +135,9 @@ class FPaletteTester : public FTexture public: FPaletteTester (); - const uint8_t *GetColumn(unsigned int column, const Span **spans_out); - const uint8_t *GetPixels(); - bool CheckModified(); + const uint8_t *GetColumn(FRenderStyle, unsigned int column, const Span **spans_out) override; + const uint8_t *GetPixels(FRenderStyle); + bool CheckModified(FRenderStyle); void SetTranslation(int num); protected: @@ -983,7 +983,7 @@ FPaletteTester::FPaletteTester() // //========================================================================== -bool FPaletteTester::CheckModified() +bool FPaletteTester::CheckModified(FRenderStyle) { return CurTranslation != WantTranslation; } @@ -1008,7 +1008,7 @@ void FPaletteTester::SetTranslation(int num) // //========================================================================== -const uint8_t *FPaletteTester::GetColumn (unsigned int column, const Span **spans_out) +const uint8_t *FPaletteTester::GetColumn(FRenderStyle, unsigned int column, const Span **spans_out) { if (CurTranslation != WantTranslation) { @@ -1028,7 +1028,7 @@ const uint8_t *FPaletteTester::GetColumn (unsigned int column, const Span **span // //========================================================================== -const uint8_t *FPaletteTester::GetPixels () +const uint8_t *FPaletteTester::GetPixels (FRenderStyle) { if (CurTranslation != WantTranslation) { diff --git a/src/w_wad.cpp b/src/w_wad.cpp index e084d4c74..31e65cd9b 100644 --- a/src/w_wad.cpp +++ b/src/w_wad.cpp @@ -1255,6 +1255,19 @@ int FWadCollection::GetLumpFile (int lump) const return LumpInfo[lump].wadnum; } +//========================================================================== +// +// W_GetLumpFile +// +//========================================================================== + +FResourceLump *FWadCollection::GetLumpRecord(int lump) const +{ + if ((size_t)lump >= LumpInfo.Size()) + return nullptr; + return LumpInfo[lump].lump; +} + //========================================================================== // // W_ReadLump diff --git a/src/w_wad.h b/src/w_wad.h index 114a37039..9f33ac2c1 100644 --- a/src/w_wad.h +++ b/src/w_wad.h @@ -170,6 +170,7 @@ public: int GetLumpFile (int lump) const; // [RH] Returns wadnum for a specified lump int GetLumpNamespace (int lump) const; // [RH] Returns the namespace a lump belongs to int GetLumpIndexNum (int lump) const; // Returns the RFF index number for this lump + FResourceLump *GetLumpRecord(int lump) const; // Returns the FResourceLump, in case the caller wants to have direct access to the lump cache. bool CheckLumpName (int lump, const char *name) const; // [RH] Returns true if the names match bool IsEncryptedFile(int lump) const; diff --git a/wadsrc/static/zscript/inventory/inventory.txt b/wadsrc/static/zscript/inventory/inventory.txt index e7786059b..1bc3f42a6 100644 --- a/wadsrc/static/zscript/inventory/inventory.txt +++ b/wadsrc/static/zscript/inventory/inventory.txt @@ -16,6 +16,7 @@ class Inventory : Actor native native int InterHubAmount; // Amount of item that can be kept between hubs or levels native int RespawnTics; // Tics from pickup time to respawn time native TextureID Icon; // Icon to show on status bar or HUD + native TextureID AltHUDIcon; native int DropTime; // Countdown after dropping native Class SpawnPointClass; // For respawning like Heretic's mace native Class PickupFlash; // actor to spawn as pickup flash diff --git a/wadsrc/static/zscript/statusbar/heretic_sbar.txt b/wadsrc/static/zscript/statusbar/heretic_sbar.txt index 691a89e33..8d490444e 100644 --- a/wadsrc/static/zscript/statusbar/heretic_sbar.txt +++ b/wadsrc/static/zscript/statusbar/heretic_sbar.txt @@ -6,6 +6,7 @@ class HereticStatusBar : BaseStatusBar HUDFont mBigFont; InventoryBarState diparms; InventoryBarState diparms_sbar; + private int wiggle; override void Init() @@ -40,6 +41,12 @@ class HereticStatusBar : BaseStatusBar { Super.Tick(); mHealthInterpolator.Update(CPlayer.health); + + // wiggle the chain if it moves + if (level.time & 1) + { + wiggle = (mHealthInterpolator.GetValue() != CPlayer.health) && Random[ChainWiggle](0, 1); + } } override void Draw (int state, double TicFrac) @@ -73,7 +80,6 @@ class HereticStatusBar : BaseStatusBar DrawImage("CHAINCAC", (0, 190), DI_ITEM_OFFSETS); // wiggle the chain if it moves int inthealth = mHealthInterpolator.GetValue(); - int wiggle = (inthealth != CPlayer.health) && Random[ChainWiggle](0, 1); DrawGem("CHAIN", "LIFEGEM2",inthealth, CPlayer.mo.GetMaxHealth(true), (2, 191 + wiggle), 15, 25, 16, (multiplayer? DI_TRANSLATABLE : 0) | DI_ITEM_LEFT_TOP); DrawImage("LTFACE", (0, 190), DI_ITEM_OFFSETS); DrawImage("RTFACE", (276, 190), DI_ITEM_OFFSETS);