diff --git a/src/gl/system/gl_framebuffer.cpp b/src/gl/system/gl_framebuffer.cpp index 58cc8be22..ca2616cfd 100644 --- a/src/gl/system/gl_framebuffer.cpp +++ b/src/gl/system/gl_framebuffer.cpp @@ -326,7 +326,7 @@ void OpenGLFrameBuffer::SetTextureFilterMode() if (GLRenderer != nullptr && GLRenderer->mSamplerManager != nullptr) GLRenderer->mSamplerManager->SetTextureFilterMode(); } -IHardwareTexture *OpenGLFrameBuffer::CreateHardwareTexture(FTexture *tex) +IHardwareTexture *OpenGLFrameBuffer::CreateHardwareTexture() { return new FHardwareTexture(true/*tex->bNoCompress*/); } diff --git a/src/gl/system/gl_framebuffer.h b/src/gl/system/gl_framebuffer.h index 60929d947..5ebc586b0 100644 --- a/src/gl/system/gl_framebuffer.h +++ b/src/gl/system/gl_framebuffer.h @@ -33,7 +33,7 @@ public: void WriteSavePic(player_t *player, FileWriter *file, int width, int height) override; sector_t *RenderView(player_t *player) override; void SetTextureFilterMode() override; - IHardwareTexture *CreateHardwareTexture(FTexture *tex) override; + IHardwareTexture *CreateHardwareTexture() override; void PrecacheMaterial(FMaterial *mat, int translation) override; bool CheckPrecacheMaterial(FMaterial *mat) override; FModelRenderer *CreateModelRenderer(int mli) override; diff --git a/src/textures/hires/hirestex.cpp b/src/textures/hires/hirestex.cpp index b2edce48c..824e61d5e 100644 --- a/src/textures/hires/hirestex.cpp +++ b/src/textures/hires/hirestex.cpp @@ -36,6 +36,7 @@ #include "gi.h" #include "cmdlib.h" #include "bitmap.h" +#include "image.h" #ifndef _WIN32 #define _access(a,b) access(a,b) @@ -357,7 +358,7 @@ int FTexture::CheckExternalFile(bool & hascolorkey) // //========================================================================== -unsigned char *FTexture::LoadHiresTexture(int *width, int *height) +bool FTexture::LoadHiresTexture(FTextureBuffer &texbuffer) { if (HiresLump == -1) { @@ -396,10 +397,15 @@ unsigned char *FTexture::LoadHiresTexture(int *width, int *height) if (dwdata[i] == 0xffffff00 || dwdata[i] == 0xffff00ff) dwdata[i] = 0; } } - *width = w; - *height = h; - return buffer; + FContentId contentId; + contentId.id = 0; + contentId.imageID = HiresTexture->GetImage()->GetId(); + texbuffer.mBuffer = buffer; + texbuffer.mWidth = w; + texbuffer.mHeight = h; + texbuffer.mContentId = contentId.id; + return true; } - return nullptr; + return false; } diff --git a/src/textures/hires/hqresize.cpp b/src/textures/hires/hqresize.cpp index 01f310ed2..0ba4b247b 100644 --- a/src/textures/hires/hqresize.cpp +++ b/src/textures/hires/hqresize.cpp @@ -348,46 +348,44 @@ static void xbrzOldScale(size_t factor, const uint32_t* src, uint32_t* trg, int // the upsampled buffer. // //=========================================================================== -unsigned char *FTexture::CreateUpsampledTextureBuffer (unsigned char *inputBuffer, const int inWidth, const int inHeight, int &outWidth, int &outHeight, bool hasAlpha ) +void FTexture::CreateUpsampledTextureBuffer(FTextureBuffer &texbuffer, bool hasAlpha) { // [BB] Make sure that outWidth and outHeight denote the size of // the returned buffer even if we don't upsample the input buffer. - outWidth = inWidth; - outHeight = inHeight; + int outWidth = texbuffer.mWidth; + int outHeight = texbuffer.mHeight; // [BB] Don't resample if the width or height of the input texture is bigger than gl_texture_hqresize_maxinputsize. - if ( ( inWidth > gl_texture_hqresize_maxinputsize ) || ( inHeight > gl_texture_hqresize_maxinputsize ) ) - return inputBuffer; + if ( ( outWidth > gl_texture_hqresize_maxinputsize ) || ( outHeight > gl_texture_hqresize_maxinputsize ) ) + return; - // [BB] Don't try to upsample textures based off FCanvasTexture. + // [BB] Don't try to upsample textures based off FCanvasTexture. (This should never get here in the first place!) if ( bHasCanvas ) - return inputBuffer; + return; // already scaled? if (Scale.X >= 2 && Scale.Y >= 2) - return inputBuffer; + return; switch (UseType) { case ETextureType::Sprite: case ETextureType::SkinSprite: - if (!(gl_texture_hqresize_targets & 2)) return inputBuffer; + if (!(gl_texture_hqresize_targets & 2)) return; break; case ETextureType::FontChar: - if (!(gl_texture_hqresize_targets & 4)) return inputBuffer; + if (!(gl_texture_hqresize_targets & 4)) return; break; default: - if (!(gl_texture_hqresize_targets & 1)) return inputBuffer; + if (!(gl_texture_hqresize_targets & 1)) return; break; } - if (inputBuffer) + if (texbuffer.mBuffer) { int type = gl_texture_hqresize; - outWidth = inWidth; - outHeight = inHeight; #ifdef HAVE_MMX // hqNx MMX does not preserve the alpha channel so fall back to C-version for such textures if (hasAlpha && type > 6 && type <= 9) diff --git a/src/textures/image.h b/src/textures/image.h index e53fc2035..7e0db353f 100644 --- a/src/textures/image.h +++ b/src/textures/image.h @@ -64,6 +64,7 @@ public: bool bMasked = true; // Image (might) have holes (Assume true unless proven otherwise!) int8_t bTranslucent = -1; // Image has pixels with a non-0/1 value. (-1 means the user needs to do a real check) + int GetId() const { return ImageID; } // 'noremap0' will only be looked at by FPatchTexture and forwarded by FMultipatchTexture. diff --git a/src/textures/texture.cpp b/src/textures/texture.cpp index f91f7acc9..538ece45c 100644 --- a/src/textures/texture.cpp +++ b/src/textures/texture.cpp @@ -661,23 +661,22 @@ bool FTexture::ProcessData(unsigned char * buffer, int w, int h, bool ispatch) // //=========================================================================== -unsigned char * FTexture::CreateTexBuffer(int translation, int & w, int & h, int flags) +FTextureBuffer FTexture::CreateTexBuffer(int translation, int flags) { + FTextureBuffer result; + unsigned char * buffer = nullptr; int W, H; int isTransparent = -1; if (flags & CTF_CheckHires) { - buffer = LoadHiresTexture(&w, &h); - if (buffer != nullptr) - return buffer; + if (LoadHiresTexture(result)) return result; } - int exx = !!(flags & CTF_Expand); - W = w = GetWidth() + 2 * exx; - H = h = GetHeight() + 2 * exx; + W = GetWidth() + 2 * exx; + H = GetHeight() + 2 * exx; buffer = new unsigned char[W*(H + 1) * 4]; memset(buffer, 0, W * (H + 1) * 4); @@ -700,13 +699,24 @@ unsigned char * FTexture::CreateTexBuffer(int translation, int & w, int & h, int // A translated image is not conclusive for setting the texture's transparency info. } + FContentId builder; + builder.id = 0; + builder.imageID = GetImage()->GetId(); + builder.translation = MAX(0, translation); + builder.expand = exx; + + result.mBuffer = buffer; + result.mWidth = W; + result.mHeight = H; + result.mContentId = builder.id; + if (flags & CTF_ProcessData) { - buffer = CreateUpsampledTextureBuffer(buffer, W, H, w, h, !!isTransparent); - ProcessData(buffer, w, h, false); + CreateUpsampledTextureBuffer(result, !!isTransparent); + ProcessData(result.mBuffer, result.mWidth, result.mHeight, false); } - return buffer; + return result; } //=========================================================================== diff --git a/src/textures/textures.h b/src/textures/textures.h index 52cf9b97a..47e4da28f 100644 --- a/src/textures/textures.h +++ b/src/textures/textures.h @@ -226,6 +226,31 @@ namespace OpenGLRenderer class FHardwareTexture; } +union FContentId +{ + uint64_t id; + struct + { + unsigned imageID : 24; + unsigned translation : 16; + unsigned expand : 1; + unsigned scaler : 4; + unsigned scalefactor : 4; + }; +}; + +struct FTextureBuffer +{ + uint8_t *mBuffer = nullptr; + int mWidth = 0; + int mHeight = 0; + uint64_t mContentId = 0; // unique content identifier. (Two images created from the same image source with the same settings will return the same value.) + + FTextureBuffer() + { + if (mBuffer) delete[] mBuffer; + } +}; // Base texture class class FTexture @@ -258,12 +283,7 @@ public: virtual ~FTexture (); virtual FImageSource *GetImage() const { return nullptr; } void AddAutoMaterials(); - unsigned char *CreateUpsampledTextureBuffer(unsigned char *inputBuffer, const int inWidth, const int inHeight, int &outWidth, int &outHeight, bool hasAlpha); - - // These should only be used in places where the texture scaling must be ignored and absolutely nowhere else! - // Preferably all code depending on the physical texture size should be rewritten, unless it is part of the software rasterizer. - //int GetPixelWidth() { return GetWidth(); } - //int GetPixelHeight() { return GetHeight(); } + void CreateUpsampledTextureBuffer(FTextureBuffer &texbuffer, bool hasAlpha); // These are mainly meant for 2D code which only needs logical information about the texture to position it properly. int GetDisplayWidth() { return GetScaledWidth(); } @@ -466,13 +486,13 @@ protected: public: - unsigned char * CreateTexBuffer(int translation, int & w, int & h, int flags = 0); + FTextureBuffer CreateTexBuffer(int translation, int flags = 0); bool GetTranslucency(); private: int CheckDDPK3(); int CheckExternalFile(bool & hascolorkey); - unsigned char *LoadHiresTexture(int *width, int *height); + bool LoadHiresTexture(FTextureBuffer &texbuffer); bool bSWSkyColorDone = false; PalEntry FloorSkyColor; diff --git a/src/v_video.h b/src/v_video.h index bdf556edd..bbbcb71f9 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -424,7 +424,7 @@ public: // Delete any resources that need to be deleted after restarting with a different IWAD virtual void CleanForRestart() {} virtual void SetTextureFilterMode() {} - virtual IHardwareTexture *CreateHardwareTexture(FTexture *tex) { return nullptr; } + virtual IHardwareTexture *CreateHardwareTexture() { return nullptr; } virtual bool CheckPrecacheMaterial(FMaterial *mat) { return true; } virtual void PrecacheMaterial(FMaterial *mat, int translation) {} virtual FModelRenderer *CreateModelRenderer(int mli) { return nullptr; }