diff --git a/src/swrenderer/r_swrenderer.cpp b/src/swrenderer/r_swrenderer.cpp index 9dbba63cb..a20b474cd 100644 --- a/src/swrenderer/r_swrenderer.cpp +++ b/src/swrenderer/r_swrenderer.cpp @@ -181,7 +181,7 @@ void FSoftwareRenderer::RenderView(player_t *player, DCanvas *target, void *vide void FSoftwareRenderer::WriteSavePic (player_t *player, FileWriter *file, int width, int height) { - DSimpleCanvas pic(width, height, false); + DCanvas pic(width, height, false); PalEntry palette[256]; // Take a snapshot of the player's view @@ -241,7 +241,7 @@ void FSoftwareRenderer::RenderTextureView (FCanvasTexture *tex, AActor *viewpoin cameraViewwindow = r_viewwindow; uint8_t *Pixels = renderTarget->IsBgra() ? (uint8_t*)tex->GetPixelsBgra() : (uint8_t*)tex->GetPixels(DefaultRenderStyle()); - DSimpleCanvas *Canvas = renderTarget->IsBgra() ? tex->GetCanvasBgra() : tex->GetCanvas(); + DCanvas *Canvas = renderTarget->IsBgra() ? tex->GetCanvasBgra() : tex->GetCanvas(); // curse Doom's overuse of global variables in the renderer. // These get clobbered by rendering to a camera texture but they need to be preserved so the final rendering can be done with the correct palette. diff --git a/src/swrenderer/r_swscene.cpp b/src/swrenderer/r_swscene.cpp index f68336e85..c29e4fb67 100644 --- a/src/swrenderer/r_swscene.cpp +++ b/src/swrenderer/r_swscene.cpp @@ -96,7 +96,7 @@ sector_t *SWSceneDrawer::RenderView(player_t *player) mat->AddTextureLayer(PaletteTexture.get()); Canvas.reset(); - Canvas.reset(new DSimpleCanvas(screen->GetWidth(), screen->GetHeight(), V_IsTrueColor())); + Canvas.reset(new DCanvas(screen->GetWidth(), screen->GetHeight(), V_IsTrueColor())); } auto buf = fbtex->SystemTexture[0]->MapBuffer(); diff --git a/src/swrenderer/r_swscene.h b/src/swrenderer/r_swscene.h index 9ed0bec03..47757a334 100644 --- a/src/swrenderer/r_swscene.h +++ b/src/swrenderer/r_swscene.h @@ -16,7 +16,7 @@ class SWSceneDrawer std::unique_ptr FBTexture[2]; int FBTextureIndex = 0; bool FBIsTruecolor = false; - std::unique_ptr Canvas; + std::unique_ptr Canvas; public: SWSceneDrawer(); diff --git a/src/textures/formats/canvastexture.cpp b/src/textures/formats/canvastexture.cpp index ae4a4697e..49729818b 100644 --- a/src/textures/formats/canvastexture.cpp +++ b/src/textures/formats/canvastexture.cpp @@ -108,7 +108,7 @@ const uint32_t *FCanvasTexture::GetPixelsBgra() 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 = new DCanvas (Width, Height, false); if (Width != Height || Width != Canvas->GetPitch()) { @@ -128,7 +128,7 @@ void FCanvasTexture::MakeTexture (FRenderStyle) // This ignores the render style void FCanvasTexture::MakeTextureBgra() { - CanvasBgra = new DSimpleCanvas(Width, Height, true); + CanvasBgra = new DCanvas(Width, Height, true); if (Width != Height || Width != CanvasBgra->GetPitch()) { diff --git a/src/textures/textures.h b/src/textures/textures.h index fc70ef122..4c4cd57c6 100644 --- a/src/textures/textures.h +++ b/src/textures/textures.h @@ -754,7 +754,7 @@ protected: }; // A texture that can be drawn to. -class DSimpleCanvas; +class DCanvas; class AActor; class FCanvasTexture : public FTexture @@ -770,16 +770,16 @@ public: bool CheckModified (FRenderStyle) override; void NeedUpdate() { bNeedsUpdate=true; } void SetUpdated() { bNeedsUpdate = false; bDidUpdate = true; bFirstUpdate = false; } - DSimpleCanvas *GetCanvas() { return Canvas; } - DSimpleCanvas *GetCanvasBgra() { return CanvasBgra; } + DCanvas *GetCanvas() { return Canvas; } + DCanvas *GetCanvasBgra() { return CanvasBgra; } bool Mipmapped() override { return false; } void MakeTexture (FRenderStyle style); void MakeTextureBgra (); protected: - DSimpleCanvas *Canvas = nullptr; - DSimpleCanvas *CanvasBgra = nullptr; + DCanvas *Canvas = nullptr; + DCanvas *CanvasBgra = nullptr; uint8_t *Pixels = nullptr; uint32_t *PixelsBgra = nullptr; Span DummySpans[2]; diff --git a/src/v_framebuffer.cpp b/src/v_framebuffer.cpp index c89d3cf8a..dd697d943 100644 --- a/src/v_framebuffer.cpp +++ b/src/v_framebuffer.cpp @@ -82,87 +82,6 @@ void DFrameBuffer::CalcGamma (float gamma, uint8_t gammalookup[256]) } } -//========================================================================== -// -// DSimpleCanvas Constructor -// -// A simple canvas just holds a buffer in main memory. -// -//========================================================================== - -DSimpleCanvas::DSimpleCanvas (int width, int height, bool bgra) - : DCanvas (width, height, bgra) -{ - PixelBuffer = nullptr; - Resize(width, height); -} - -void DSimpleCanvas::Resize(int width, int height) -{ - Width = width; - Height = height; - - if (PixelBuffer != NULL) - { - delete[] PixelBuffer; - PixelBuffer = NULL; - } - - // Making the pitch a power of 2 is very bad for performance - // Try to maximize the number of cache lines that can be filled - // for each column drawing operation by making the pitch slightly - // longer than the width. The values used here are all based on - // empirical evidence. - - if (width <= 640) - { - // For low resolutions, just keep the pitch the same as the width. - // Some speedup can be seen using the technique below, but the speedup - // is so marginal that I don't consider it worthwhile. - Pitch = width; - } - else - { - // If we couldn't figure out the CPU's L1 cache line size, assume - // it's 32 bytes wide. - if (CPU.DataL1LineSize == 0) - { - CPU.DataL1LineSize = 32; - } - // The Athlon and P3 have very different caches, apparently. - // I am going to generalize the Athlon's performance to all AMD - // processors and the P3's to all non-AMD processors. I don't know - // how smart that is, but I don't have a vast plethora of - // processors to test with. - if (CPU.bIsAMD) - { - Pitch = width + CPU.DataL1LineSize; - } - else - { - Pitch = width + MAX(0, CPU.DataL1LineSize - 8); - } - } - int bytes_per_pixel = Bgra ? 4 : 1; - PixelBuffer = new uint8_t[Pitch * height * bytes_per_pixel]; - memset (PixelBuffer, 0, Pitch * height * bytes_per_pixel); -} - -//========================================================================== -// -// DSimpleCanvas Destructor -// -//========================================================================== - -DSimpleCanvas::~DSimpleCanvas () -{ - if (PixelBuffer != NULL) - { - delete[] PixelBuffer; - PixelBuffer = NULL; - } -} - //========================================================================== // // DFrameBuffer Constructor diff --git a/src/v_video.cpp b/src/v_video.cpp index c94f141d2..b9efcf6a1 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -177,6 +177,7 @@ DCanvas::DCanvas (int _width, int _height, bool _bgra) Width = _width; Height = _height; Bgra = _bgra; + Resize(_width, _height); } //========================================================================== @@ -189,6 +190,58 @@ DCanvas::~DCanvas () { } +//========================================================================== +// +// +// +//========================================================================== + +void DCanvas::Resize(int width, int height) +{ + Width = width; + Height = height; + + // Making the pitch a power of 2 is very bad for performance + // Try to maximize the number of cache lines that can be filled + // for each column drawing operation by making the pitch slightly + // longer than the width. The values used here are all based on + // empirical evidence. + + if (width <= 640) + { + // For low resolutions, just keep the pitch the same as the width. + // Some speedup can be seen using the technique below, but the speedup + // is so marginal that I don't consider it worthwhile. + Pitch = width; + } + else + { + // If we couldn't figure out the CPU's L1 cache line size, assume + // it's 32 bytes wide. + if (CPU.DataL1LineSize == 0) + { + CPU.DataL1LineSize = 32; + } + // The Athlon and P3 have very different caches, apparently. + // I am going to generalize the Athlon's performance to all AMD + // processors and the P3's to all non-AMD processors. I don't know + // how smart that is, but I don't have a vast plethora of + // processors to test with. + if (CPU.bIsAMD) + { + Pitch = width + CPU.DataL1LineSize; + } + else + { + Pitch = width + MAX(0, CPU.DataL1LineSize - 8); + } + } + int bytes_per_pixel = Bgra ? 4 : 1; + Pixels.Resize(Pitch * height * bytes_per_pixel); + memset (Pixels.Data(), 0, Pixels.Size()); +} + + //========================================================================== // // V_GetColorFromString diff --git a/src/v_video.h b/src/v_video.h index 61185e1b3..fbecf1f42 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -291,53 +291,29 @@ struct VMVa_List // // VIDEO // -// [RH] Made screens more implementation-independant: // class DCanvas { public: DCanvas (int width, int height, bool bgra); - virtual ~DCanvas (); + ~DCanvas (); + void Resize(int width, int height); // Member variable access - inline uint8_t *GetPixels () const { return PixelBuffer; } + inline uint8_t *GetPixels () const { return Pixels.Data(); } inline int GetWidth () const { return Width; } inline int GetHeight () const { return Height; } inline int GetPitch () const { return Pitch; } inline bool IsBgra() const { return Bgra; } - // Note: pitch here is in pixels, not bytes. - bool SetBuffer(int width, int height, int pitch, uint8_t *buffer) - { - assert(buffer); - Width = width; - Height = height; - Pitch = pitch; - PixelBuffer = buffer; - return true; - } - - protected: - uint8_t *PixelBuffer; + TArray Pixels; int Width; int Height; int Pitch; bool Bgra; }; -// A canvas in system memory. - -class DSimpleCanvas : public DCanvas -{ - typedef DCanvas Super; -public: - DSimpleCanvas (int width, int height, bool bgra); - ~DSimpleCanvas (); - void Resize(int width, int height); -}; - - class FUniquePalette; class IHardwareTexture; class FTexture; @@ -348,7 +324,6 @@ class FTexture; class DFrameBuffer { - typedef DSimpleCanvas Super; protected: void DrawTextureV(FTexture *img, double x, double y, uint32_t tag, va_list tags) = delete;