mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-10 10:08:18 +00:00
initial commit of the threaded graphics. can start game and render the gui. no textures at the moment. still waits for the swap for now
This commit is contained in:
parent
8ffe582615
commit
8e56885795
|
@ -1689,28 +1689,21 @@ void CClient::InitInterfaces()
|
|||
m_Friends.Init();
|
||||
}
|
||||
|
||||
|
||||
enum
|
||||
void CClient::Run()
|
||||
{
|
||||
GFXSTATE_ERROR = -1,
|
||||
GFXSTATE_INIT = 0,
|
||||
GFXSTATE_IDLE,
|
||||
GFXSTATE_RENDERING,
|
||||
GFXSTATE_SWAPPING,
|
||||
};
|
||||
int64 ReportTime = time_get();
|
||||
int64 ReportInterval = time_freq()*1;
|
||||
|
||||
m_LocalStartTime = time_get();
|
||||
m_SnapshotParts = 0;
|
||||
|
||||
void CClient::GraphicsThread()
|
||||
{
|
||||
// init graphics
|
||||
if(m_pGraphics->Init() != 0)
|
||||
{
|
||||
m_GfxState = GFXSTATE_ERROR;
|
||||
m_GfxStateSemaphore.signal();
|
||||
m_GfxState = GFXSTATE_ERROR;
|
||||
dbg_msg("client", "couldn't init graphics");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// open socket
|
||||
{
|
||||
NETADDR BindAddr;
|
||||
|
@ -1719,7 +1712,6 @@ void CClient::GraphicsThread()
|
|||
if(!m_NetClient.Open(BindAddr, 0))
|
||||
{
|
||||
dbg_msg("client", "couldn't start network");
|
||||
m_GfxState = GFXSTATE_ERROR;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1741,59 +1733,10 @@ void CClient::GraphicsThread()
|
|||
|
||||
// load data
|
||||
if(!LoadData())
|
||||
{
|
||||
m_GfxState = GFXSTATE_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
GameClient()->OnInit();
|
||||
|
||||
|
||||
while(1)
|
||||
{
|
||||
// do idle
|
||||
sync_barrier();
|
||||
m_GfxState = GFXSTATE_IDLE;
|
||||
m_GfxStateSemaphore.signal();
|
||||
m_GfxRenderSemaphore.wait();
|
||||
|
||||
// do render
|
||||
m_GfxState = GFXSTATE_RENDERING;
|
||||
m_GfxStateSemaphore.signal();
|
||||
Render();
|
||||
sync_barrier();
|
||||
|
||||
// do swap
|
||||
m_GfxState = GFXSTATE_SWAPPING;
|
||||
m_GfxStateSemaphore.signal();
|
||||
m_pGraphics->Swap();
|
||||
}
|
||||
|
||||
// do shutdown
|
||||
}
|
||||
|
||||
void CClient::Run()
|
||||
{
|
||||
int64 ReportTime = time_get();
|
||||
int64 ReportInterval = time_freq()*1;
|
||||
|
||||
m_LocalStartTime = time_get();
|
||||
m_SnapshotParts = 0;
|
||||
|
||||
m_GfxState = GFXSTATE_INIT;
|
||||
thread_create(GraphicsThreadProxy, this);
|
||||
|
||||
// wait for gfx to init
|
||||
while(1)
|
||||
{
|
||||
m_GfxStateSemaphore.wait();
|
||||
if(m_GfxState == GFXSTATE_ERROR)
|
||||
return;
|
||||
if(m_GfxState != GFXSTATE_INIT)
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
char aBuf[256];
|
||||
str_format(aBuf, sizeof(aBuf), "version %s", GameClient()->NetVersion());
|
||||
m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "client", aBuf);
|
||||
|
@ -1910,26 +1853,6 @@ void CClient::Run()
|
|||
|
||||
Update();
|
||||
|
||||
|
||||
if(m_GfxState == GFXSTATE_IDLE)
|
||||
{
|
||||
// issue new rendering
|
||||
m_GfxRenderSemaphore.signal();
|
||||
|
||||
// wait for gfx to finish rendering
|
||||
while(m_GfxState != GFXSTATE_SWAPPING)
|
||||
m_GfxStateSemaphore.wait();
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
if(m_pGraphics->AsyncSwapIsDone())
|
||||
{
|
||||
m_pGraphics->BeginScene();
|
||||
Render();
|
||||
m_pGraphics->EndScene();
|
||||
}*/
|
||||
/*
|
||||
if(g_Config.m_DbgStress)
|
||||
{
|
||||
if((m_Frames%10) == 0)
|
||||
|
@ -1942,7 +1865,7 @@ void CClient::Run()
|
|||
{
|
||||
Render();
|
||||
m_pGraphics->Swap();
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
AutoScreenshot_Cleanup();
|
||||
|
|
|
@ -950,4 +950,4 @@ int CGraphics_SDL::GetVideoModes(CVideoMode *pModes, int MaxModes)
|
|||
return NumModes;
|
||||
}
|
||||
|
||||
extern IEngineGraphics *CreateEngineGraphics() { return new CGraphics_SDL(); }
|
||||
//extern IEngineGraphics *CreateEngineGraphics() { return new CGraphics_SDL(); }
|
||||
|
|
|
@ -3,6 +3,348 @@
|
|||
#ifndef ENGINE_CLIENT_GRAPHICS_H
|
||||
#define ENGINE_CLIENT_GRAPHICS_H
|
||||
|
||||
#include <base/tl/threading.h>
|
||||
|
||||
class CCommandBuffer
|
||||
{
|
||||
class CBuffer
|
||||
{
|
||||
unsigned char *m_pData;
|
||||
unsigned m_Size;
|
||||
unsigned m_Used;
|
||||
public:
|
||||
CBuffer(unsigned BufferSize)
|
||||
{
|
||||
m_Size = BufferSize;
|
||||
m_pData = new unsigned char[m_Size];
|
||||
m_Used = 0;
|
||||
}
|
||||
|
||||
~CBuffer()
|
||||
{
|
||||
delete [] m_pData;
|
||||
m_pData = 0x0;
|
||||
m_Used = 0;
|
||||
m_Size = 0;
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
m_Used = 0;
|
||||
}
|
||||
|
||||
void *Alloc(unsigned Requested)
|
||||
{
|
||||
if(Requested + m_Used > m_Size)
|
||||
return 0;
|
||||
void *pPtr = &m_pData[m_Used];
|
||||
m_Used += Requested;
|
||||
return pPtr;
|
||||
}
|
||||
|
||||
unsigned char *DataPtr() { return m_pData; }
|
||||
unsigned DataSize() { return m_Size; }
|
||||
unsigned DataUsed() { return m_Used; }
|
||||
};
|
||||
|
||||
CBuffer m_CmdBuffer;
|
||||
CBuffer m_DataBuffer;
|
||||
public:
|
||||
enum
|
||||
{
|
||||
//
|
||||
CMD_NOP = 0,
|
||||
|
||||
//
|
||||
CMD_INIT,
|
||||
CMD_SHUTDOWN,
|
||||
|
||||
//
|
||||
CMD_RUNBUFFER,
|
||||
|
||||
// syncronization
|
||||
CMD_SIGNAL,
|
||||
|
||||
// texture commands
|
||||
CMD_TEXTURE_CREATE,
|
||||
CMD_TEXTURE_DESTROY,
|
||||
|
||||
// rendering
|
||||
CMD_CLEAR,
|
||||
CMD_RENDER,
|
||||
|
||||
// swap
|
||||
CMD_SWAP,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
//
|
||||
PRIMTYPE_INVALID = 0,
|
||||
PRIMTYPE_LINES,
|
||||
PRIMTYPE_QUADS,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
BLEND_NONE = 0,
|
||||
BLEND_ALPHA,
|
||||
BLEND_ADDITIVE,
|
||||
};
|
||||
|
||||
struct SPoint { float x, y, z; };
|
||||
struct STexCoord { float u, v; };
|
||||
struct SColor { float r, g, b, a; };
|
||||
|
||||
struct SVertex
|
||||
{
|
||||
SPoint m_Pos;
|
||||
STexCoord m_Tex;
|
||||
SColor m_Color;
|
||||
} ;
|
||||
|
||||
struct SCommand
|
||||
{
|
||||
public:
|
||||
SCommand(unsigned Cmd) : m_Cmd(Cmd), m_Size(0) {}
|
||||
unsigned m_Cmd;
|
||||
unsigned m_Size;
|
||||
};
|
||||
|
||||
struct SState
|
||||
{
|
||||
int m_BlendMode;
|
||||
int m_Texture;
|
||||
SPoint m_ScreenTL;
|
||||
SPoint m_ScreenBR;
|
||||
|
||||
// clip
|
||||
bool m_ClipEnable;
|
||||
int m_ClipX;
|
||||
int m_ClipY;
|
||||
int m_ClipW;
|
||||
int m_ClipH;
|
||||
};
|
||||
|
||||
struct SCommand_Clear : public SCommand
|
||||
{
|
||||
SCommand_Clear() : SCommand(CMD_CLEAR) {}
|
||||
SColor m_Color;
|
||||
};
|
||||
|
||||
|
||||
struct SCommand_Init : public SCommand
|
||||
{
|
||||
SCommand_Init() : SCommand(CMD_INIT) {}
|
||||
volatile int *m_pResult;
|
||||
};
|
||||
|
||||
struct SCommand_RunBuffer : public SCommand
|
||||
{
|
||||
SCommand_RunBuffer() : SCommand(CMD_RUNBUFFER) {}
|
||||
CCommandBuffer *m_pOtherBuffer;
|
||||
};
|
||||
|
||||
struct SCommand_Render : public SCommand
|
||||
{
|
||||
SCommand_Render() : SCommand(CMD_RENDER) {}
|
||||
SState m_State;
|
||||
unsigned m_PrimType;
|
||||
unsigned m_PrimCount;
|
||||
SVertex *m_pVertices;
|
||||
};
|
||||
|
||||
struct SCommand_Swap : public SCommand
|
||||
{
|
||||
SCommand_Swap() : SCommand(CMD_SWAP) {}
|
||||
};
|
||||
|
||||
//
|
||||
CCommandBuffer(unsigned CmdBufferSize, unsigned DataBufferSize)
|
||||
: m_CmdBuffer(CmdBufferSize), m_DataBuffer(DataBufferSize)
|
||||
{
|
||||
}
|
||||
|
||||
void *AllocData(unsigned WantedSize)
|
||||
{
|
||||
return m_DataBuffer.Alloc(WantedSize);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void AddCommand(const T &Command)
|
||||
{
|
||||
SCommand *pCmd = (SCommand *)m_CmdBuffer.Alloc(sizeof(Command));
|
||||
if(!pCmd)
|
||||
return;
|
||||
|
||||
mem_copy(pCmd, &Command, sizeof(Command));
|
||||
pCmd->m_Size = sizeof(Command);
|
||||
}
|
||||
|
||||
SCommand *GetCommand(unsigned *pIndex)
|
||||
{
|
||||
if(*pIndex >= m_CmdBuffer.DataUsed())
|
||||
return NULL;
|
||||
|
||||
SCommand *pCommand = (SCommand *)&m_CmdBuffer.DataPtr()[*pIndex];
|
||||
*pIndex += pCommand->m_Size;
|
||||
return pCommand;
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
m_CmdBuffer.Reset();
|
||||
m_DataBuffer.Reset();
|
||||
}
|
||||
};
|
||||
|
||||
class ICommandProcessor
|
||||
{
|
||||
public:
|
||||
virtual ~ICommandProcessor() {}
|
||||
virtual void RunBuffer(CCommandBuffer *pBuffer) = 0;
|
||||
};
|
||||
|
||||
|
||||
class CCommandProcessorHandler
|
||||
{
|
||||
ICommandProcessor *m_pProcessor;
|
||||
CCommandBuffer * volatile m_pBuffer;
|
||||
volatile bool m_Shutdown;
|
||||
semaphore m_Activity;
|
||||
semaphore m_BufferDone;
|
||||
void *m_pThread;
|
||||
|
||||
static void ThreadFunc(void *pUser);
|
||||
|
||||
public:
|
||||
CCommandProcessorHandler();
|
||||
void Start(ICommandProcessor *pProcessor);
|
||||
void RunBuffer(CCommandBuffer *pBuffer);
|
||||
bool IsIdle() const { return m_pBuffer == 0; }
|
||||
void WaitForIdle();
|
||||
};
|
||||
|
||||
class CGraphics_Threaded : public IEngineGraphics
|
||||
{
|
||||
CCommandBuffer::SState m_State;
|
||||
CCommandProcessorHandler m_Handler;
|
||||
|
||||
CCommandBuffer *m_apCommandBuffers[2];
|
||||
CCommandBuffer *m_pCommandBuffer;
|
||||
unsigned m_CurrentCommandBuffer;
|
||||
|
||||
//
|
||||
class IStorage *m_pStorage;
|
||||
class IConsole *m_pConsole;
|
||||
|
||||
enum
|
||||
{
|
||||
MAX_VERTICES = 32*1024,
|
||||
MAX_TEXTURES = 1024*4,
|
||||
|
||||
DRAWING_QUADS=1,
|
||||
DRAWING_LINES=2
|
||||
};
|
||||
|
||||
CCommandBuffer::SVertex m_aVertices[MAX_VERTICES];
|
||||
int m_NumVertices;
|
||||
|
||||
CCommandBuffer::SColor m_aColor[4];
|
||||
CCommandBuffer::STexCoord m_aTexture[4];
|
||||
|
||||
bool m_RenderEnable;
|
||||
|
||||
float m_Rotation;
|
||||
int m_Drawing;
|
||||
bool m_DoScreenshot;
|
||||
char m_aScreenshotName[128];
|
||||
|
||||
int m_InvalidTexture;
|
||||
|
||||
struct CTexture
|
||||
{
|
||||
GLuint m_Tex;
|
||||
int m_MemSize;
|
||||
int m_Flags;
|
||||
int m_Next;
|
||||
};
|
||||
|
||||
CTexture m_aTextures[MAX_TEXTURES];
|
||||
int m_FirstFreeTexture;
|
||||
int m_TextureMemoryUsage;
|
||||
|
||||
void Flush();
|
||||
void AddVertices(int Count);
|
||||
void Rotate4(const CCommandBuffer::SPoint &rCenter, CCommandBuffer::SVertex *pPoints);
|
||||
|
||||
static unsigned char Sample(int w, int h, const unsigned char *pData, int u, int v, int Offset, int ScaleW, int ScaleH, int Bpp);
|
||||
static unsigned char *Rescale(int Width, int Height, int NewWidth, int NewHeight, int Format, const unsigned char *pData);
|
||||
public:
|
||||
CGraphics_Threaded();
|
||||
|
||||
virtual void ClipEnable(int x, int y, int w, int h);
|
||||
virtual void ClipDisable();
|
||||
|
||||
virtual void BlendNone();
|
||||
virtual void BlendNormal();
|
||||
virtual void BlendAdditive();
|
||||
|
||||
virtual int MemoryUsage() const;
|
||||
|
||||
virtual void MapScreen(float TopLeftX, float TopLeftY, float BottomRightX, float BottomRightY);
|
||||
virtual void GetScreen(float *pTopLeftX, float *pTopLeftY, float *pBottomRightX, float *pBottomRightY);
|
||||
|
||||
virtual void LinesBegin();
|
||||
virtual void LinesEnd();
|
||||
virtual void LinesDraw(const CLineItem *pArray, int Num);
|
||||
|
||||
virtual int UnloadTexture(int Index);
|
||||
virtual int LoadTextureRaw(int Width, int Height, int Format, const void *pData, int StoreFormat, int Flags);
|
||||
|
||||
// simple uncompressed RGBA loaders
|
||||
virtual int LoadTexture(const char *pFilename, int StorageType, int StoreFormat, int Flags);
|
||||
virtual int LoadPNG(CImageInfo *pImg, const char *pFilename, int StorageType);
|
||||
|
||||
void ScreenshotDirect(const char *pFilename);
|
||||
|
||||
virtual void TextureSet(int TextureID);
|
||||
|
||||
virtual void Clear(float r, float g, float b);
|
||||
|
||||
virtual void QuadsBegin();
|
||||
virtual void QuadsEnd();
|
||||
virtual void QuadsSetRotation(float Angle);
|
||||
|
||||
virtual void SetColorVertex(const CColorVertex *pArray, int Num);
|
||||
virtual void SetColor(float r, float g, float b, float a);
|
||||
|
||||
virtual void QuadsSetSubset(float TlU, float TlV, float BrU, float BrV);
|
||||
virtual void QuadsSetSubsetFree(
|
||||
float x0, float y0, float x1, float y1,
|
||||
float x2, float y2, float x3, float y3);
|
||||
|
||||
virtual void QuadsDraw(CQuadItem *pArray, int Num);
|
||||
virtual void QuadsDrawTL(const CQuadItem *pArray, int Num);
|
||||
virtual void QuadsDrawFreeform(const CFreeformItem *pArray, int Num);
|
||||
virtual void QuadsText(float x, float y, float Size, float r, float g, float b, float a, const char *pText);
|
||||
|
||||
virtual void Minimize();
|
||||
virtual void Maximize();
|
||||
|
||||
virtual int WindowActive();
|
||||
virtual int WindowOpen();
|
||||
|
||||
virtual bool Init();
|
||||
virtual void Shutdown();
|
||||
|
||||
virtual void TakeScreenshot(const char *pFilename);
|
||||
virtual void Swap();
|
||||
|
||||
virtual int GetVideoModes(CVideoMode *pModes, int MaxModes);
|
||||
|
||||
};
|
||||
|
||||
class CGraphics_OpenGL : public IEngineGraphics
|
||||
{
|
||||
protected:
|
||||
|
|
1225
src/engine/client/graphics_threaded.cpp
Normal file
1225
src/engine/client/graphics_threaded.cpp
Normal file
File diff suppressed because it is too large
Load diff
|
@ -628,7 +628,6 @@ int CMenus::RenderMenubar(CUIRect r)
|
|||
void CMenus::RenderLoading()
|
||||
{
|
||||
// TODO: not supported right now due to separate render thread
|
||||
return;
|
||||
|
||||
static int64 LastLoadRender = 0;
|
||||
float Percent = m_LoadCurrent++/(float)m_LoadTotal;
|
||||
|
|
Loading…
Reference in a new issue