- merged DCanvas and DSimpleCanvas and use a TArray to hold its memory.

This commit is contained in:
Christoph Oelckers 2018-11-30 17:02:39 +01:00
parent 927d333063
commit 024870ba11
8 changed files with 68 additions and 121 deletions

View file

@ -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) 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]; PalEntry palette[256];
// Take a snapshot of the player's view // Take a snapshot of the player's view
@ -241,7 +241,7 @@ void FSoftwareRenderer::RenderTextureView (FCanvasTexture *tex, AActor *viewpoin
cameraViewwindow = r_viewwindow; cameraViewwindow = r_viewwindow;
uint8_t *Pixels = renderTarget->IsBgra() ? (uint8_t*)tex->GetPixelsBgra() : (uint8_t*)tex->GetPixels(DefaultRenderStyle()); 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. // 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. // 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.

View file

@ -96,7 +96,7 @@ sector_t *SWSceneDrawer::RenderView(player_t *player)
mat->AddTextureLayer(PaletteTexture.get()); mat->AddTextureLayer(PaletteTexture.get());
Canvas.reset(); 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(); auto buf = fbtex->SystemTexture[0]->MapBuffer();

View file

@ -16,7 +16,7 @@ class SWSceneDrawer
std::unique_ptr<FWrapperTexture> FBTexture[2]; std::unique_ptr<FWrapperTexture> FBTexture[2];
int FBTextureIndex = 0; int FBTextureIndex = 0;
bool FBIsTruecolor = false; bool FBIsTruecolor = false;
std::unique_ptr<DSimpleCanvas> Canvas; std::unique_ptr<DCanvas> Canvas;
public: public:
SWSceneDrawer(); SWSceneDrawer();

View file

@ -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. 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()) if (Width != Height || Width != Canvas->GetPitch())
{ {
@ -128,7 +128,7 @@ void FCanvasTexture::MakeTexture (FRenderStyle) // This ignores the render style
void FCanvasTexture::MakeTextureBgra() void FCanvasTexture::MakeTextureBgra()
{ {
CanvasBgra = new DSimpleCanvas(Width, Height, true); CanvasBgra = new DCanvas(Width, Height, true);
if (Width != Height || Width != CanvasBgra->GetPitch()) if (Width != Height || Width != CanvasBgra->GetPitch())
{ {

View file

@ -754,7 +754,7 @@ protected:
}; };
// A texture that can be drawn to. // A texture that can be drawn to.
class DSimpleCanvas; class DCanvas;
class AActor; class AActor;
class FCanvasTexture : public FTexture class FCanvasTexture : public FTexture
@ -770,16 +770,16 @@ public:
bool CheckModified (FRenderStyle) override; bool CheckModified (FRenderStyle) override;
void NeedUpdate() { bNeedsUpdate=true; } void NeedUpdate() { bNeedsUpdate=true; }
void SetUpdated() { bNeedsUpdate = false; bDidUpdate = true; bFirstUpdate = false; } void SetUpdated() { bNeedsUpdate = false; bDidUpdate = true; bFirstUpdate = false; }
DSimpleCanvas *GetCanvas() { return Canvas; } DCanvas *GetCanvas() { return Canvas; }
DSimpleCanvas *GetCanvasBgra() { return CanvasBgra; } DCanvas *GetCanvasBgra() { return CanvasBgra; }
bool Mipmapped() override { return false; } bool Mipmapped() override { return false; }
void MakeTexture (FRenderStyle style); void MakeTexture (FRenderStyle style);
void MakeTextureBgra (); void MakeTextureBgra ();
protected: protected:
DSimpleCanvas *Canvas = nullptr; DCanvas *Canvas = nullptr;
DSimpleCanvas *CanvasBgra = nullptr; DCanvas *CanvasBgra = nullptr;
uint8_t *Pixels = nullptr; uint8_t *Pixels = nullptr;
uint32_t *PixelsBgra = nullptr; uint32_t *PixelsBgra = nullptr;
Span DummySpans[2]; Span DummySpans[2];

View file

@ -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 // DFrameBuffer Constructor

View file

@ -177,6 +177,7 @@ DCanvas::DCanvas (int _width, int _height, bool _bgra)
Width = _width; Width = _width;
Height = _height; Height = _height;
Bgra = _bgra; 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 // V_GetColorFromString

View file

@ -291,53 +291,29 @@ struct VMVa_List
// //
// VIDEO // VIDEO
// //
// [RH] Made screens more implementation-independant:
// //
class DCanvas class DCanvas
{ {
public: public:
DCanvas (int width, int height, bool bgra); DCanvas (int width, int height, bool bgra);
virtual ~DCanvas (); ~DCanvas ();
void Resize(int width, int height);
// Member variable access // 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 GetWidth () const { return Width; }
inline int GetHeight () const { return Height; } inline int GetHeight () const { return Height; }
inline int GetPitch () const { return Pitch; } inline int GetPitch () const { return Pitch; }
inline bool IsBgra() const { return Bgra; } 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: protected:
uint8_t *PixelBuffer; TArray<uint8_t> Pixels;
int Width; int Width;
int Height; int Height;
int Pitch; int Pitch;
bool Bgra; 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 FUniquePalette;
class IHardwareTexture; class IHardwareTexture;
class FTexture; class FTexture;
@ -348,7 +324,6 @@ class FTexture;
class DFrameBuffer class DFrameBuffer
{ {
typedef DSimpleCanvas Super;
protected: protected:
void DrawTextureV(FTexture *img, double x, double y, uint32_t tag, va_list tags) = delete; void DrawTextureV(FTexture *img, double x, double y, uint32_t tag, va_list tags) = delete;