- made camera textures operational again.

Now with proper separation of software rendering logic from the main part of the class.
This commit is contained in:
Christoph Oelckers 2018-12-11 00:01:45 +01:00
parent 91a8f5cd04
commit 5666e4c805
27 changed files with 517 additions and 458 deletions

View file

@ -1144,6 +1144,7 @@ set (PCH_SOURCES
r_data/voxels.cpp
r_data/renderinfo.cpp
r_data/renderstyle.cpp
r_data/r_canvastexture.cpp
r_data/r_interpolate.cpp
r_data/r_vanillatrans.cpp
r_data/r_sections.cpp
@ -1249,6 +1250,7 @@ set (PCH_SOURCES
sound/wildmidi/wm_error.cpp
swrenderer/textures/r_swtexture.cpp
swrenderer/textures/warptexture.cpp
swrenderer/textures/swcanvastexture.cpp
events.cpp
)

View file

@ -322,7 +322,6 @@ static void MarkRoot()
M_MarkMenus();
Mark(DIntermissionController::CurrentIntermission);
DThinker::MarkRoots();
FCanvasTextureInfo::Mark();
Mark(E_FirstEventHandler);
Mark(E_LastEventHandler);
level.Mark();

View file

@ -1959,6 +1959,7 @@ void FLevelLocals::Tick ()
void FLevelLocals::Mark()
{
canvasTextureInfo.Mark();
for (auto &s : sectorPortals)
{
GC::Mark(s.mSkybox);

View file

@ -44,6 +44,7 @@
#include "p_local.h"
#include "p_destructible.h"
#include "r_data/r_sections.h"
#include "r_data/r_canvastexture.h"
struct FLevelLocals
{
@ -103,6 +104,7 @@ struct FLevelLocals
TArray<FSectorPortalGroup *> portalGroups;
TArray<FLinePortalSpan> linePortalSpans;
FSectionContainer sections;
FCanvasTextureInfo canvasTextureInfo;
int NumMapSections;

View file

@ -254,7 +254,10 @@ sector_t *FGLRenderer::RenderView(player_t* player)
bool saved_niv = NoInterpolateView;
NoInterpolateView = false;
// prepare all camera textures that have been used in the last frame
FCanvasTextureInfo::UpdateAll();
level.canvasTextureInfo.UpdateAll([&](AActor *camera, FCanvasTexture *camtex, double fov)
{
RenderTextureView(camtex, camera, fov);
});
NoInterpolateView = saved_niv;
@ -324,7 +327,8 @@ void FGLRenderer::RenderTextureView(FCanvasTexture *tex, AActor *Viewpoint, doub
EndOffscreen();
tex->SetUpdated();
tex->SetUpdated(true);
static_cast<OpenGLFrameBuffer*>(screen)->camtexcount++;
}
//===========================================================================

View file

@ -186,25 +186,6 @@ void OpenGLFrameBuffer::Update()
Super::Update();
}
//===========================================================================
//
//
//
//===========================================================================
void OpenGLFrameBuffer::RenderTextureView(FCanvasTexture *tex, AActor *Viewpoint, double FOV)
{
if (!V_IsHardwareRenderer())
{
Super::RenderTextureView(tex, Viewpoint, FOV);
}
else if (GLRenderer != nullptr)
{
GLRenderer->RenderTextureView(tex, Viewpoint, FOV);
camtexcount++;
}
}
//===========================================================================
//
// Render the view to a savegame picture

View file

@ -30,7 +30,6 @@ public:
void CleanForRestart() override;
void UpdatePalette() override;
uint32_t GetCaps() override;
void RenderTextureView(FCanvasTexture *tex, AActor *Viewpoint, double FOV) override;
void WriteSavePic(player_t *player, FileWriter *file, int width, int height) override;
sector_t *RenderView(player_t *player) override;
void SetTextureFilterMode() override;
@ -65,7 +64,7 @@ public:
FTexture *WipeStartScreen() override;
FTexture *WipeEndScreen() override;
private:
int camtexcount = 0;
};

View file

@ -9900,7 +9900,7 @@ scriptwait:
}
else
{
FCanvasTextureInfo::Add (camera, picnum, STACK(1));
level.canvasTextureInfo.Add(camera, picnum, STACK(1));
}
}
sp -= 3;

View file

@ -1012,7 +1012,7 @@ void G_SerializeLevel(FSerializer &arc, bool hubload)
StatusBar->SerializeMessages(arc);
AM_SerializeMarkers(arc);
FRemapTable::StaticSerializeTranslations(arc);
FCanvasTextureInfo::Serialize(arc);
level.canvasTextureInfo.Serialize(arc);
P_SerializePlayers(arc, hubload);
P_SerializeSounds(arc);

View file

@ -3555,7 +3555,6 @@ void P_FreeLevelData ()
MapThingsUserDataIndex.Clear();
MapThingsUserData.Clear();
linemap.Clear();
FCanvasTextureInfo::EmptyList();
R_FreePastViewers();
P_ClearUDMFKeys();
@ -3594,6 +3593,7 @@ void P_FreeLevelData ()
FBehavior::StaticUnloadModules ();
level.canvasTextureInfo.EmptyList();
level.sections.Clear();
level.segs.Clear();
level.sectors.Clear();

View file

@ -0,0 +1,210 @@
/*
** r_canvastexture.cpp
** Maintenance data for camera textures
**
**---------------------------------------------------------------------------
** Copyright 2004-2006 Randy Heit
** Copyright 2006-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 "actor.h"
#include "r_canvastexture.h"
#include "g_levellocals.h"
#include "serializer.h"
//==========================================================================
//
// FCanvasTextureInfo :: Add
//
// Assigns a camera to a canvas texture.
//
//==========================================================================
void FCanvasTextureInfo::Add (AActor *viewpoint, FTextureID picnum, double fov)
{
FCanvasTexture *texture;
if (!picnum.isValid())
{
return;
}
texture = static_cast<FCanvasTexture *>(TexMan.GetTexture(picnum));
if (!texture->bHasCanvas)
{
Printf ("%s is not a valid target for a camera\n", texture->Name.GetChars());
return;
}
// Is this texture already assigned to a camera?
unsigned index = List.FindEx([=](auto &entry) { return entry.Texture == texture; });
if (index < List.Size())
{
auto probe = &List[index];
// Yes, change its assignment to this new camera
if (probe->Viewpoint != viewpoint || probe->FOV != fov)
{
texture->bFirstUpdate = true;
}
probe->Viewpoint = viewpoint;
probe->FOV = fov;
return;
}
// No, create a new assignment
auto probe = &List[List.Reserve(1)];
probe->Viewpoint = viewpoint;
probe->Texture = texture;
probe->PicNum = picnum;
probe->FOV = fov;
texture->bFirstUpdate = true;
}
//==========================================================================
//
// SetCameraToTexture
//
// [ZZ] expose this to ZScript
//
//==========================================================================
void SetCameraToTexture(AActor *viewpoint, const FString &texturename, double fov)
{
FTextureID textureid = TexMan.CheckForTexture(texturename, ETextureType::Wall, FTextureManager::TEXMAN_Overridable);
if (textureid.isValid())
{
// Only proceed if the texture actually has a canvas.
FTexture *tex = TexMan.GetTexture(textureid);
if (tex && tex->isCanvas())
{
level.canvasTextureInfo.Add(viewpoint, textureid, fov);
}
}
}
//==========================================================================
//
// FCanvasTextureInfo :: UpdateAll
//
// Updates all canvas textures that were visible in the last frame.
//
//==========================================================================
void FCanvasTextureInfo::UpdateAll(std::function<void(AActor *, FCanvasTexture *, double fov)> callback)
{
for (auto &probe : List)
{
if (probe.Viewpoint != nullptr && probe.Texture->bNeedsUpdate)
{
callback(probe.Viewpoint, probe.Texture, probe.FOV);
}
}
}
//==========================================================================
//
// FCanvasTextureInfo :: EmptyList
//
// Removes all camera->texture assignments.
//
//==========================================================================
void FCanvasTextureInfo::EmptyList ()
{
List.Clear();
}
//==========================================================================
//
// FCanvasTextureInfo :: Serialize
//
// Reads or writes the current set of mappings in an archive.
//
//==========================================================================
void FCanvasTextureInfo::Serialize(FSerializer &arc)
{
if (arc.isWriting())
{
if (List.Size() > 0)
{
if (arc.BeginArray("canvastextures"))
{
for (auto &probe : List)
{
if (probe.Texture != nullptr && probe.Viewpoint != nullptr)
{
if (arc.BeginObject(nullptr))
{
arc("viewpoint", probe.Viewpoint)
("fov", probe.FOV)
("texture", probe.PicNum)
.EndObject();
}
}
}
arc.EndArray();
}
}
}
else
{
if (arc.BeginArray("canvastextures"))
{
AActor *viewpoint = nullptr;
double fov;
FTextureID picnum;
while (arc.BeginObject(nullptr))
{
arc("viewpoint", viewpoint)
("fov", fov)
("texture", picnum)
.EndObject();
Add(viewpoint, picnum, fov);
}
arc.EndArray();
}
}
}
//==========================================================================
//
// FCanvasTextureInfo :: Mark
//
// Marks all viewpoints in the list for the collector.
//
//==========================================================================
void FCanvasTextureInfo::Mark()
{
for (auto & info : List)
{
GC::Mark(info.Viewpoint);
}
}

View file

@ -0,0 +1,25 @@
#pragma once
class FCanvasTexture;
// This list keeps track of the cameras that draw into canvas textures.
struct FCanvasTextureEntry
{
FCanvasTextureInfo *Next;
TObjPtr<AActor*> Viewpoint;
FCanvasTexture *Texture;
FTextureID PicNum;
double FOV;
};
struct FCanvasTextureInfo
{
TArray<FCanvasTextureEntry> List;
void Add (AActor *viewpoint, FTextureID picnum, double fov);
void UpdateAll (std::function<void(AActor *, FCanvasTexture *, double fov)> callback);
void EmptyList ();
void Serialize(FSerializer &arc);
void Mark();
};

View file

@ -28,9 +28,6 @@ struct FRenderer
// renders view to a savegame picture
virtual void WriteSavePic(player_t *player, FileWriter *file, int width, int height) = 0;
// render to a camera texture
virtual void RenderTextureView(FCanvasTexture *tex, AActor *viewpoint, double fov) = 0;
// draws player sprites with hardware acceleration (only useful for software rendering)
virtual void DrawRemainingPlayerSprites() = 0;

View file

@ -146,8 +146,6 @@ int validcount = 1; // increment every time a check is made
int dl_validcount = 1; // increment every time a check is made
int freelookviewheight;
FCanvasTextureInfo *FCanvasTextureInfo::List;
DVector3a view;
DAngle viewpitch;
@ -433,7 +431,6 @@ static void R_Shutdown ()
SWRenderer = nullptr;
R_DeinitTranslationTables();
R_DeinitColormaps ();
FCanvasTextureInfo::EmptyList();
}
//==========================================================================
@ -1052,195 +1049,6 @@ void R_SetupFrame (FRenderViewpoint &viewpoint, FViewWindow &viewwindow, AActor
}
//==========================================================================
//
// FCanvasTextureInfo :: Add
//
// Assigns a camera to a canvas texture.
//
//==========================================================================
void FCanvasTextureInfo::Add (AActor *viewpoint, FTextureID picnum, double fov)
{
FCanvasTextureInfo *probe;
FCanvasTexture *texture;
if (!picnum.isValid())
{
return;
}
texture = static_cast<FCanvasTexture *>(TexMan.GetTexture(picnum));
if (!texture->bHasCanvas)
{
Printf ("%s is not a valid target for a camera\n", texture->Name.GetChars());
return;
}
// Is this texture already assigned to a camera?
for (probe = List; probe != NULL; probe = probe->Next)
{
if (probe->Texture == texture)
{
// Yes, change its assignment to this new camera
if (probe->Viewpoint != viewpoint || probe->FOV != fov)
{
texture->bFirstUpdate = true;
}
probe->Viewpoint = viewpoint;
probe->FOV = fov;
return;
}
}
// No, create a new assignment
probe = new FCanvasTextureInfo;
probe->Viewpoint = viewpoint;
probe->Texture = texture;
probe->PicNum = picnum;
probe->FOV = fov;
probe->Next = List;
texture->bFirstUpdate = true;
List = probe;
}
// [ZZ] expose this to ZScript
void SetCameraToTexture(AActor *viewpoint, const FString &texturename, double fov)
{
FTextureID textureid = TexMan.CheckForTexture(texturename, ETextureType::Wall, FTextureManager::TEXMAN_Overridable);
if (textureid.isValid())
{
// Only proceed if the texture actually has a canvas.
FTexture *tex = TexMan.GetTexture(textureid);
if (tex && tex->isCanvas())
{
FCanvasTextureInfo::Add(viewpoint, textureid, fov);
}
}
}
DEFINE_ACTION_FUNCTION_NATIVE(_TexMan, SetCameraToTexture, SetCameraToTexture)
{
PARAM_PROLOGUE;
PARAM_OBJECT(viewpoint, AActor);
PARAM_STRING(texturename); // [ZZ] there is no point in having this as FTextureID because it's easier to refer to a cameratexture by name and it isn't executed too often to cache it.
PARAM_FLOAT(fov);
SetCameraToTexture(viewpoint, texturename, fov);
return 0;
}
//==========================================================================
//
// FCanvasTextureInfo :: UpdateAll
//
// Updates all canvas textures that were visible in the last frame.
//
//==========================================================================
void FCanvasTextureInfo::UpdateAll ()
{
FCanvasTextureInfo *probe;
for (probe = List; probe != NULL; probe = probe->Next)
{
if (probe->Viewpoint != NULL && probe->Texture->bNeedsUpdate)
{
screen->RenderTextureView(probe->Texture, probe->Viewpoint, probe->FOV);
}
}
}
//==========================================================================
//
// FCanvasTextureInfo :: EmptyList
//
// Removes all camera->texture assignments.
//
//==========================================================================
void FCanvasTextureInfo::EmptyList ()
{
FCanvasTextureInfo *probe, *next;
for (probe = List; probe != NULL; probe = next)
{
next = probe->Next;
//probe->Texture->Unload();
delete probe;
}
List = NULL;
}
//==========================================================================
//
// FCanvasTextureInfo :: Serialize
//
// Reads or writes the current set of mappings in an archive.
//
//==========================================================================
void FCanvasTextureInfo::Serialize(FSerializer &arc)
{
if (arc.isWriting())
{
if (List != nullptr)
{
if (arc.BeginArray("canvastextures"))
{
FCanvasTextureInfo *probe;
for (probe = List; probe != nullptr; probe = probe->Next)
{
if (probe->Texture != nullptr && probe->Viewpoint != nullptr)
{
if (arc.BeginObject(nullptr))
{
arc("viewpoint", probe->Viewpoint)
("fov", probe->FOV)
("texture", probe->PicNum)
.EndObject();
}
}
}
arc.EndArray();
}
}
}
else
{
if (arc.BeginArray("canvastextures"))
{
AActor *viewpoint = nullptr;
double fov;
FTextureID picnum;
while (arc.BeginObject(nullptr))
{
arc("viewpoint", viewpoint)
("fov", fov)
("texture", picnum)
.EndObject();
Add(viewpoint, picnum, fov);
}
arc.EndArray();
}
}
}
//==========================================================================
//
// FCanvasTextureInfo :: Mark
//
// Marks all viewpoints in the list for the collector.
//
//==========================================================================
void FCanvasTextureInfo::Mark()
{
for (FCanvasTextureInfo *probe = List; probe != NULL; probe = probe->Next)
{
GC::Mark(probe->Viewpoint);
}
}
//==========================================================================
//
// CVAR transsouls

View file

@ -138,25 +138,5 @@ double R_ClampVisibility(double vis);
extern void R_FreePastViewers ();
extern void R_ClearPastViewer (AActor *actor);
class FCanvasTexture;
// This list keeps track of the cameras that draw into canvas textures.
struct FCanvasTextureInfo
{
FCanvasTextureInfo *Next;
TObjPtr<AActor*> Viewpoint;
FCanvasTexture *Texture;
FTextureID PicNum;
double FOV;
static void Add (AActor *viewpoint, FTextureID picnum, double fov);
static void UpdateAll ();
static void EmptyList ();
static void Serialize(FSerializer &arc);
static void Mark();
private:
static FCanvasTextureInfo *List;
};
#endif

View file

@ -1584,6 +1584,19 @@ DEFINE_ACTION_FUNCTION_NATIVE(_TexMan, ReplaceTextures, ReplaceTextures)
return 0;
}
void SetCameraToTexture(AActor *viewpoint, const FString &texturename, double fov);
DEFINE_ACTION_FUNCTION_NATIVE(_TexMan, SetCameraToTexture, SetCameraToTexture)
{
PARAM_PROLOGUE;
PARAM_OBJECT(viewpoint, AActor);
PARAM_STRING(texturename); // [ZZ] there is no point in having this as FTextureID because it's easier to refer to a cameratexture by name and it isn't executed too often to cache it.
PARAM_FLOAT(fov);
SetCameraToTexture(viewpoint, texturename, fov);
return 0;
}
//=====================================================================================
//
// secplane_t exports

View file

@ -52,6 +52,7 @@
#include "p_setup.h"
#include "g_levellocals.h"
#include "image.h"
#include "imagehelpers.h"
// [BB] Use ZDoom's freelook limit for the sotfware renderer.
// Note: ZDoom's limit is chosen such that the sky is rendered properly.
@ -201,7 +202,10 @@ void FSoftwareRenderer::RenderView(player_t *player, DCanvas *target, void *vide
r_viewwindow = mScene.MainThread()->Viewport->viewwindow;
}
FCanvasTextureInfo::UpdateAll();
level.canvasTextureInfo.UpdateAll([&](AActor *camera, FCanvasTexture *camtex, double fov)
{
RenderTextureView(camtex, camera, fov);
});
}
void FSoftwareRenderer::WriteSavePic (player_t *player, FileWriter *file, int width, int height)
@ -255,9 +259,8 @@ void FSoftwareRenderer::SetClearColor(int color)
mScene.SetClearColor(color);
}
void FSoftwareRenderer::RenderTextureView (FCanvasTexture *tex, AActor *viewpoint, double fov)
void FSoftwareRenderer::RenderTextureView (FCanvasTexture *camtex, AActor *viewpoint, double fov)
{
#if 0 // This will require a complete redesign.
auto renderTarget = V_IsPolyRenderer() ? PolyRenderer::Instance()->RenderTarget : mScene.MainThread()->Viewport->RenderTarget;
auto &cameraViewpoint = V_IsPolyRenderer() ? PolyRenderer::Instance()->Viewpoint : mScene.MainThread()->Viewport->viewpoint;
auto &cameraViewwindow = V_IsPolyRenderer() ? PolyRenderer::Instance()->Viewwindow : mScene.MainThread()->Viewport->viewwindow;
@ -265,8 +268,9 @@ void FSoftwareRenderer::RenderTextureView (FCanvasTexture *tex, AActor *viewpoin
// Grab global state shared with rest of zdoom
cameraViewpoint = r_viewpoint;
cameraViewwindow = r_viewwindow;
auto tex = static_cast<FSWCanvasTexture*>(camtex->GetSoftwareTexture());
uint8_t *Pixels = renderTarget->IsBgra() ? (uint8_t*)tex->GetPixelsBgra() : (uint8_t*)tex->GetPixels(DefaultRenderStyle());
DCanvas *Canvas = renderTarget->IsBgra() ? tex->GetCanvasBgra() : tex->GetCanvas();
// curse Doom's overuse of global variables in the renderer.
@ -277,66 +281,19 @@ void FSoftwareRenderer::RenderTextureView (FCanvasTexture *tex, AActor *viewpoin
R_SetFOV (cameraViewpoint, fov);
if (V_IsPolyRenderer())
PolyRenderer::Instance()->RenderViewToCanvas(viewpoint, Canvas, 0, 0, tex->GetWidth(), tex->GetHeight(), tex->bFirstUpdate);
PolyRenderer::Instance()->RenderViewToCanvas(viewpoint, Canvas, 0, 0, tex->GetWidth(), tex->GetHeight(), camtex->bFirstUpdate);
else
mScene.RenderViewToCanvas(viewpoint, Canvas, 0, 0, tex->GetWidth(), tex->GetHeight(), tex->bFirstUpdate);
mScene.RenderViewToCanvas(viewpoint, Canvas, 0, 0, tex->GetWidth(), tex->GetHeight(), camtex->bFirstUpdate);
R_SetFOV (cameraViewpoint, savedfov);
if (Canvas->IsBgra())
{
if (Pixels == Canvas->GetPixels())
{
FTexture::FlipSquareBlockBgra((uint32_t*)Pixels, tex->GetWidth(), tex->GetHeight());
}
else
{
FTexture::FlipNonSquareBlockBgra((uint32_t*)Pixels, (const uint32_t*)Canvas->GetPixels(), tex->GetWidth(), tex->GetHeight(), Canvas->GetPitch());
}
}
else
{
if (Pixels == Canvas->GetPixels())
{
FTexture::FlipSquareBlockRemap(Pixels, tex->GetWidth(), tex->GetHeight(), GPalette.Remap);
}
else
{
FTexture::FlipNonSquareBlockRemap(Pixels, Canvas->GetPixels(), tex->GetWidth(), tex->GetHeight(), Canvas->GetPitch(), GPalette.Remap);
}
}
if (renderTarget->IsBgra())
{
// True color render still sometimes uses palette textures (for sprites, mostly).
// 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(DefaultRenderStyle());
uint32_t *bgrabuffer = (uint32_t*)tex->GetPixelsBgra();
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
uint32_t color = bgrabuffer[y];
int r = RPART(color);
int g = GPART(color);
int b = BPART(color);
palbuffer[y] = RGB32k.RGB[r >> 3][g >> 3][b >> 3];
}
palbuffer += height;
bgrabuffer += height;
}
}
tex->SetUpdated();
tex->UpdatePixels(renderTarget->IsBgra());
*CameraLight::Instance() = savedCameraLight;
// Sync state back to zdoom
r_viewpoint = cameraViewpoint;
r_viewwindow = cameraViewwindow;
#endif
}
void FSoftwareRenderer::SetColormap()

View file

@ -21,7 +21,7 @@ struct FSoftwareRenderer : public FRenderer
void DrawRemainingPlayerSprites() override;
void SetClearColor(int color) override;
void RenderTextureView (FCanvasTexture *tex, AActor *viewpoint, double fov) override;
void RenderTextureView (FCanvasTexture *tex, AActor *viewpoint, double fov);
void SetColormap() override;
void Init() override;

View file

@ -43,7 +43,8 @@ FSoftwareTexture *FTexture::GetSoftwareTexture()
{
if (!SoftwareTexture)
{
if (bWarped) SoftwareTexture = new FWarpTexture(this, bWarped);
if (bHasCanvas) SoftwareTexture = new FSWCanvasTexture(this);
else if (bWarped) SoftwareTexture = new FWarpTexture(this, bWarped);
else SoftwareTexture = new FSoftwareTexture(this);
}
return SoftwareTexture;

View file

@ -2,6 +2,7 @@
#include "textures/textures.h"
#include "v_video.h"
struct FSoftwareTextureSpan
{
uint16_t TopOffset;
@ -62,7 +63,6 @@ public:
int GetHeight () { return mTexture->GetHeight(); }
int GetWidthBits() { return WidthBits; }
int GetHeightBits() { return HeightBits; }
bool Mipmapped() { return mTexture->Mipmapped(); }
int GetScaledWidth () { return mTexture->GetScaledWidth(); }
int GetScaledHeight () { return mTexture->GetScaledHeight(); }
@ -95,7 +95,7 @@ public:
DVector2 GetScale() const { return mTexture->Scale; }
void Unload()
virtual void Unload()
{
Pixels.Reset();
PixelsBgra.Reset();
@ -112,6 +112,9 @@ public:
void GenerateBgraMipmapsFast();
int MipmapLevels();
// Returns true if GetPixelsBgra includes mipmaps
virtual bool Mipmapped() { return true; }
// Returns a single column of the texture
virtual const uint8_t *GetColumn(int style, unsigned int column, const FSoftwareTextureSpan **spans_out);
@ -166,3 +169,29 @@ private:
int NextPo2 (int v); // [mxd]
void SetupMultipliers (int width, int height); // [mxd]
};
class FSWCanvasTexture : public FSoftwareTexture
{
void MakeTexture();
void MakeTextureBgra();
DCanvas *Canvas = nullptr;
DCanvas *CanvasBgra = nullptr;
public:
FSWCanvasTexture(FTexture *source) : FSoftwareTexture(source) {}
~FSWCanvasTexture();
// Returns the whole texture, stored in column-major order
const uint32_t *GetPixelsBgra() override;
const uint8_t *GetPixels(int style) override;
virtual void Unload() override;
void UpdatePixels(bool truecolor);
DCanvas *GetCanvas() { return Canvas; }
DCanvas *GetCanvasBgra() { return CanvasBgra; }
bool Mipmapped() override { return false; }
};

View file

@ -0,0 +1,189 @@
/*
** texture.cpp
** The base texture class
**
**---------------------------------------------------------------------------
** Copyright 2004-2007 Randy Heit
** Copyright 2006-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 "r_swtexture.h"
#include "bitmap.h"
#include "m_alloc.h"
#include "imagehelpers.h"
FSWCanvasTexture::~FSWCanvasTexture()
{
if (Canvas != nullptr)
{
delete Canvas;
Canvas = nullptr;
}
if (CanvasBgra != nullptr)
{
delete CanvasBgra;
CanvasBgra = nullptr;
}
}
//==========================================================================
//
//
//
//==========================================================================
const uint8_t *FSWCanvasTexture::GetPixels(int style)
{
static_cast<FCanvasTexture*>(mTexture)->NeedUpdate();
if (Canvas == nullptr)
{
MakeTexture();
}
return Pixels.Data();
}
//==========================================================================
//
//
//
//==========================================================================
const uint32_t *FSWCanvasTexture::GetPixelsBgra()
{
static_cast<FCanvasTexture*>(mTexture)->NeedUpdate();
if (CanvasBgra == nullptr)
{
MakeTextureBgra();
}
return PixelsBgra.Data();
}
//==========================================================================
//
//
//
//==========================================================================
void FSWCanvasTexture::MakeTexture ()
{
Canvas = new DCanvas (GetWidth(), GetHeight(), false);
Pixels.Resize(GetWidth() * GetHeight());
// Draw a special "unrendered" initial texture into the buffer.
memset (Pixels.Data(), 0, GetWidth() * GetHeight() / 2);
memset (Pixels.Data() + GetWidth() * GetHeight() / 2, 255, GetWidth() * GetHeight() / 2);
}
//==========================================================================
//
//
//
//==========================================================================
void FSWCanvasTexture::MakeTextureBgra()
{
CanvasBgra = new DCanvas(GetWidth(), GetHeight(), true);
PixelsBgra.Resize(GetWidth() * GetHeight());
// Draw a special "unrendered" initial texture into the buffer.
memset(PixelsBgra.Data(), 0, 4* GetWidth() * GetHeight() / 2);
memset(PixelsBgra.Data() + GetWidth() * GetHeight() / 2, 255, 4* GetWidth() * GetHeight() / 2);
}
//==========================================================================
//
//
//
//==========================================================================
void FSWCanvasTexture::Unload ()
{
if (Canvas != nullptr)
{
delete Canvas;
Canvas = nullptr;
}
if (CanvasBgra != nullptr)
{
delete CanvasBgra;
CanvasBgra = nullptr;
}
FSoftwareTexture::Unload();
}
//==========================================================================
//
//
//
//==========================================================================
void FSWCanvasTexture::UpdatePixels(bool truecolor)
{
if (Canvas->IsBgra())
{
ImageHelpers::FlipNonSquareBlock(PixelsBgra.Data(), (const uint32_t*)Canvas->GetPixels(), GetWidth(), GetHeight(), Canvas->GetPitch());
}
else
{
ImageHelpers::FlipNonSquareBlockRemap(Pixels.Data(), Canvas->GetPixels(), GetWidth(), GetHeight(), Canvas->GetPitch(), GPalette.Remap);
}
if (truecolor)
{
// True color render still sometimes uses palette textures (for sprites, mostly).
// We need to make sure that both pixel buffers contain data:
int width = GetWidth();
int height = GetHeight();
uint8_t *palbuffer = const_cast<uint8_t*>(GetPixels(0));
const uint32_t *bgrabuffer = GetPixelsBgra();
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
uint32_t color = bgrabuffer[y];
int r = RPART(color);
int g = GPART(color);
int b = BPART(color);
palbuffer[y] = RGB32k.RGB[r >> 3][g >> 3][b >> 3];
}
palbuffer += height;
bgrabuffer += height;
}
}
static_cast<FCanvasTexture*>(mTexture)->SetUpdated(false);
}

View file

@ -36,123 +36,4 @@
#include "doomtype.h"
#include "v_video.h"
FCanvasTexture::FCanvasTexture (const char *name, int width, int height)
{
Name = name;
Width = width;
Height = height;
bMasked = false;
UseType = ETextureType::Wall;
bNeedsUpdate = true;
bDidUpdate = false;
bHasCanvas = true;
bFirstUpdate = true;
bPixelsAllocated = false;
}
#if 0
const uint8_t *FCanvasTexture::Get8BitPixels(bool alphatex)
{
bNeedsUpdate = true;
if (Canvas == NULL)
{
MakeTexture (style);
}
return Pixels;
}
const uint32_t *FCanvasTexture::GetPixelsBgra()
{
bNeedsUpdate = true;
if (CanvasBgra == NULL)
{
MakeTextureBgra();
}
return PixelsBgra;
}
void FCanvasTexture::MakeTexture (FRenderStyle) // This ignores the render style because making it work as alpha texture is impractical.
{
Canvas = new DCanvas (Width, Height, false);
if (Width != Height || Width != Canvas->GetPitch())
{
Pixels = new uint8_t[Width*Height];
bPixelsAllocated = true;
}
else
{
Pixels = (uint8_t*)Canvas->GetPixels();
bPixelsAllocated = false;
}
// Draw a special "unrendered" initial texture into the buffer.
memset (Pixels, 0, Width*Height/2);
memset (Pixels+Width*Height/2, 255, Width*Height/2);
}
#endif
void FCanvasTexture::MakeTextureBgra()
{
CanvasBgra = new DCanvas(Width, Height, true);
if (Width != Height || Width != CanvasBgra->GetPitch())
{
PixelsBgra = new uint32_t[Width*Height];
bPixelsAllocatedBgra = true;
}
else
{
PixelsBgra = (uint32_t*)CanvasBgra->GetPixels();
bPixelsAllocatedBgra = false;
}
// Draw a special "unrendered" initial texture into the buffer.
memset(PixelsBgra, 0, Width*Height / 2 * 4);
memset(PixelsBgra + Width*Height / 2, 255, Width*Height / 2 * 4);
}
#if 0
void FCanvasTexture::Unload ()
{
if (bPixelsAllocated)
{
if (Pixels != NULL) delete[] Pixels;
bPixelsAllocated = false;
Pixels = NULL;
}
if (bPixelsAllocatedBgra)
{
if (PixelsBgra != NULL) delete[] PixelsBgra;
bPixelsAllocatedBgra = false;
PixelsBgra = NULL;
}
if (Canvas != NULL)
{
delete Canvas;
Canvas = nullptr;
}
if (CanvasBgra != NULL)
{
delete CanvasBgra;
CanvasBgra = nullptr;
}
FTexture::Unload();
}
#endif
bool FCanvasTexture::CheckModified (FRenderStyle)
{
if (bDidUpdate)
{
bDidUpdate = false;
return true;
}
return false;
}

View file

@ -225,20 +225,20 @@ FBitmap FImageSource::GetCachedBitmap(PalEntry *remap, int conversion, int *ptra
trans = cache->TransInfo;
if (cache->RefCount > 1)
{
Printf("returning reference to %s, refcount = %d\n", name.GetChars(), cache->RefCount);
//Printf("returning reference to %s, refcount = %d\n", name.GetChars(), cache->RefCount);
ret.Copy(cache->Pixels, false);
cache->RefCount--;
}
else if (cache->Pixels.GetPixels())
{
Printf("returning contents of %s, refcount = %d\n", name.GetChars(), cache->RefCount);
//Printf("returning contents of %s, refcount = %d\n", name.GetChars(), cache->RefCount);
ret = std::move(cache->Pixels);
precacheDataRgba.Delete(index);
}
else
{
// This should never happen if the function is implemented correctly
Printf("something bad happened for %s, refcount = %d\n", name.GetChars(), cache->RefCount);
//Printf("something bad happened for %s, refcount = %d\n", name.GetChars(), cache->RefCount);
ret.Create(Width, Height);
trans = CopyPixels(&ret, normal);
}
@ -250,13 +250,13 @@ FBitmap FImageSource::GetCachedBitmap(PalEntry *remap, int conversion, int *ptra
if (!info || info->first <= 1 || conversion != normal)
{
// This is either the only copy needed or some access outside the caching block. In these cases create a new one and directly return it.
Printf("returning fresh copy of %s\n", name.GetChars());
//Printf("returning fresh copy of %s\n", name.GetChars());
ret.Create(Width, Height);
trans = CopyPixels(&ret, conversion);
}
else
{
Printf("creating cached entry for %s, refcount = %d\n", name.GetChars(), info->first);
//Printf("creating cached entry for %s, refcount = %d\n", name.GetChars(), info->first);
// This is the first time it gets accessed and needs to be placed in the cache.
PrecacheDataRgba *pdr = &precacheDataRgba[precacheDataRgba.Reserve(1)];

View file

@ -104,7 +104,7 @@ namespace ImageHelpers
{
for (int i = 0; i < x; ++i)
{
uint8_t *corner = block + x*i + i;
T *corner = block + x*i + i;
int count = x - i;
for (int j = 0; j < count; j++)
{

View file

@ -392,9 +392,6 @@ protected:
}
}
// Returns true if GetPixelsBgra includes mipmaps
virtual bool Mipmapped() { return true; }
void SetSpeed(float fac) { shaderspeed = fac; }
int GetWidth () { return Width; }
@ -673,34 +670,27 @@ class AActor;
class FCanvasTexture : public FTexture
{
public:
FCanvasTexture (const char *name, int width, int height);
FCanvasTexture(const char *name, int width, int height)
{
Name = name;
Width = width;
Height = height;
//const uint8_t *GetColumn(FRenderStyle style, unsigned int column, const FSoftwareTextureSpan **spans_out);
//const uint32_t *GetPixelsBgra() override;
bMasked = false;
bHasCanvas = true;
bTranslucent = false;
UseType = ETextureType::Wall;
}
//const uint8_t *Get8BitPixels(bool alphatex);
bool CheckModified (FRenderStyle) /*override*/;
void NeedUpdate() { bNeedsUpdate=true; }
void SetUpdated() { bNeedsUpdate = false; bDidUpdate = true; bFirstUpdate = false; }
DCanvas *GetCanvas() { return Canvas; }
DCanvas *GetCanvasBgra() { return CanvasBgra; }
bool Mipmapped() override { return false; }
void MakeTextureBgra ();
void NeedUpdate() { bNeedsUpdate = true; }
void SetUpdated(bool rendertype) { bNeedsUpdate = false; bFirstUpdate = false; bLastUpdateType = rendertype; }
protected:
DCanvas *Canvas = nullptr;
DCanvas *CanvasBgra = nullptr;
uint8_t *Pixels = nullptr;
uint32_t *PixelsBgra = nullptr;
//FSoftwareTextureSpan DummySpans[2];
bool bLastUpdateType = false;
bool bNeedsUpdate = true;
bool bDidUpdate = false;
bool bPixelsAllocated = false;
bool bPixelsAllocatedBgra = false;
public:
bool bFirstUpdate;
bool bFirstUpdate = true;
friend struct FCanvasTextureInfo;
};

View file

@ -359,11 +359,6 @@ uint32_t DFrameBuffer::GetCaps()
return (uint32_t)FlagSet;
}
void DFrameBuffer::RenderTextureView(FCanvasTexture *tex, AActor *Viewpoint, double FOV)
{
SWRenderer->RenderTextureView(tex, Viewpoint, FOV);
}
void DFrameBuffer::WriteSavePic(player_t *player, FileWriter *file, int width, int height)
{
SWRenderer->WriteSavePic(player, file, width, height);

View file

@ -318,9 +318,6 @@ class FUniquePalette;
class IHardwareTexture;
class FTexture;
// A canvas that represents the actual display. The video code is responsible
// for actually implementing this. Built on top of SimpleCanvas, because it
// needs a system memory buffer when buffered output is enabled.
class DFrameBuffer
{
@ -472,7 +469,6 @@ public:
void InitPalette();
void SetClearColor(int color);
virtual uint32_t GetCaps();
virtual void RenderTextureView(FCanvasTexture *tex, AActor *Viewpoint, double FOV);
virtual void WriteSavePic(player_t *player, FileWriter *file, int width, int height);
virtual sector_t *RenderView(player_t *player) { return nullptr; }