2018-07-06 14:11:38 +00:00
|
|
|
#ifndef ENGINE_CLIENT_BACKEND_SDL_H
|
|
|
|
#define ENGINE_CLIENT_BACKEND_SDL_H
|
2012-01-03 20:39:10 +00:00
|
|
|
|
2022-05-29 13:51:38 +00:00
|
|
|
#include <SDL_video.h>
|
2021-04-30 22:42:37 +00:00
|
|
|
|
|
|
|
#include <base/detect.h>
|
|
|
|
|
2022-12-09 15:16:16 +00:00
|
|
|
#include <engine/graphics.h>
|
|
|
|
|
|
|
|
#include <engine/client/graphics_threaded.h>
|
|
|
|
|
|
|
|
#include <engine/client/backend/backend_base.h>
|
2012-01-03 20:39:10 +00:00
|
|
|
|
2020-08-29 10:10:38 +00:00
|
|
|
#include <atomic>
|
2021-10-27 22:52:06 +00:00
|
|
|
#include <condition_variable>
|
2022-12-09 15:16:16 +00:00
|
|
|
#include <cstddef>
|
|
|
|
#include <cstdint>
|
2021-10-27 22:52:06 +00:00
|
|
|
#include <mutex>
|
2022-12-09 15:16:16 +00:00
|
|
|
#include <vector>
|
2020-08-29 10:10:38 +00:00
|
|
|
|
2021-02-12 12:40:29 +00:00
|
|
|
#if defined(CONF_PLATFORM_MACOS)
|
2020-09-26 19:41:58 +00:00
|
|
|
#include <objc/objc-runtime.h>
|
2012-01-03 21:49:31 +00:00
|
|
|
|
2020-09-26 19:41:58 +00:00
|
|
|
class CAutoreleasePool
|
|
|
|
{
|
|
|
|
private:
|
|
|
|
id m_Pool;
|
2012-08-26 18:02:04 +00:00
|
|
|
|
2020-09-26 19:41:58 +00:00
|
|
|
public:
|
|
|
|
CAutoreleasePool()
|
|
|
|
{
|
|
|
|
Class NSAutoreleasePoolClass = (Class)objc_getClass("NSAutoreleasePool");
|
|
|
|
m_Pool = class_createInstance(NSAutoreleasePoolClass, 0);
|
|
|
|
SEL selector = sel_registerName("init");
|
|
|
|
((id(*)(id, SEL))objc_msgSend)(m_Pool, selector);
|
|
|
|
}
|
2012-08-26 18:02:04 +00:00
|
|
|
|
2020-09-26 19:41:58 +00:00
|
|
|
~CAutoreleasePool()
|
|
|
|
{
|
|
|
|
SEL selector = sel_registerName("drain");
|
|
|
|
((id(*)(id, SEL))objc_msgSend)(m_Pool, selector);
|
|
|
|
}
|
|
|
|
};
|
2012-01-03 20:39:10 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
// basic threaded backend, abstract, missing init and shutdown functions
|
|
|
|
class CGraphicsBackend_Threaded : public IGraphicsBackend
|
|
|
|
{
|
2022-12-09 15:16:16 +00:00
|
|
|
private:
|
|
|
|
TTranslateFunc m_TranslateFunc;
|
|
|
|
SGFXWarningContainer m_Warning;
|
|
|
|
|
2012-01-03 20:39:10 +00:00
|
|
|
public:
|
2018-07-10 09:29:02 +00:00
|
|
|
// constructed on the main thread, the rest of the functions is run on the render thread
|
2012-01-03 20:39:10 +00:00
|
|
|
class ICommandProcessor
|
|
|
|
{
|
|
|
|
public:
|
2022-12-09 15:16:16 +00:00
|
|
|
virtual ~ICommandProcessor() = default;
|
2012-01-03 20:39:10 +00:00
|
|
|
virtual void RunBuffer(CCommandBuffer *pBuffer) = 0;
|
2022-12-09 15:16:16 +00:00
|
|
|
|
|
|
|
virtual SGFXErrorContainer &GetError() = 0;
|
|
|
|
virtual void ErroneousCleanup() = 0;
|
|
|
|
|
|
|
|
virtual SGFXWarningContainer &GetWarning() = 0;
|
|
|
|
|
|
|
|
bool HasError()
|
|
|
|
{
|
|
|
|
return GetError().m_ErrorType != GFX_ERROR_TYPE_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool HasWarning()
|
|
|
|
{
|
|
|
|
return GetWarning().m_WarningType != GFX_WARNING_TYPE_NONE;
|
|
|
|
}
|
2012-01-03 20:39:10 +00:00
|
|
|
};
|
|
|
|
|
2022-12-09 15:16:16 +00:00
|
|
|
CGraphicsBackend_Threaded(TTranslateFunc &&TranslateFunc);
|
2012-01-03 20:39:10 +00:00
|
|
|
|
2022-05-17 20:13:44 +00:00
|
|
|
void RunBuffer(CCommandBuffer *pBuffer) override;
|
|
|
|
void RunBufferSingleThreadedUnsafe(CCommandBuffer *pBuffer) override;
|
|
|
|
bool IsIdle() const override;
|
|
|
|
void WaitForIdle() override;
|
2015-07-09 00:08:14 +00:00
|
|
|
|
2022-12-09 15:16:16 +00:00
|
|
|
void ProcessError();
|
|
|
|
|
2012-01-03 20:39:10 +00:00
|
|
|
protected:
|
|
|
|
void StartProcessor(ICommandProcessor *pProcessor);
|
|
|
|
void StopProcessor();
|
|
|
|
|
2022-12-09 15:16:16 +00:00
|
|
|
bool HasWarning()
|
|
|
|
{
|
|
|
|
return m_Warning.m_WarningType != GFX_WARNING_TYPE_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// returns true if the error msg was shown
|
|
|
|
virtual bool TryCreateMsgBox(bool AsError, const char *pTitle, const char *pMsg) = 0;
|
|
|
|
|
2012-01-03 20:39:10 +00:00
|
|
|
private:
|
|
|
|
ICommandProcessor *m_pProcessor;
|
2021-10-27 22:52:06 +00:00
|
|
|
std::mutex m_BufferSwapMutex;
|
|
|
|
std::condition_variable m_BufferSwapCond;
|
|
|
|
CCommandBuffer *m_pBuffer;
|
2022-03-21 15:38:12 +00:00
|
|
|
std::atomic_bool m_Shutdown;
|
2022-02-15 15:27:53 +00:00
|
|
|
bool m_Started = false;
|
2021-10-27 22:52:06 +00:00
|
|
|
std::atomic_bool m_BufferInProcess;
|
2022-03-24 18:30:26 +00:00
|
|
|
void *m_pThread;
|
2012-01-03 20:39:10 +00:00
|
|
|
|
2022-01-21 22:50:17 +00:00
|
|
|
static void ThreadFunc(void *pUser);
|
2022-12-09 15:16:16 +00:00
|
|
|
|
|
|
|
public:
|
|
|
|
bool GetWarning(std::vector<std::string> &WarningStrings) override;
|
2012-01-03 20:39:10 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
// takes care of implementation independent operations
|
|
|
|
class CCommandProcessorFragment_General
|
|
|
|
{
|
|
|
|
void Cmd_Nop();
|
|
|
|
void Cmd_Signal(const CCommandBuffer::SCommand_Signal *pCommand);
|
2020-09-26 19:41:58 +00:00
|
|
|
|
2012-01-03 20:39:10 +00:00
|
|
|
public:
|
2020-09-26 19:41:58 +00:00
|
|
|
bool RunCommand(const CCommandBuffer::SCommand *pBaseCommand);
|
2012-01-03 20:39:10 +00:00
|
|
|
};
|
|
|
|
|
2020-08-29 10:10:38 +00:00
|
|
|
struct SBackendCapabilites
|
|
|
|
{
|
|
|
|
bool m_TileBuffering;
|
|
|
|
bool m_QuadBuffering;
|
|
|
|
bool m_TextBuffering;
|
|
|
|
bool m_QuadContainerBuffering;
|
|
|
|
|
|
|
|
bool m_MipMapping;
|
|
|
|
bool m_NPOTTextures;
|
|
|
|
bool m_3DTextures;
|
|
|
|
bool m_2DArrayTextures;
|
|
|
|
bool m_2DArrayTexturesAsExtension;
|
|
|
|
bool m_ShaderSupport;
|
|
|
|
|
2022-03-20 17:03:25 +00:00
|
|
|
// use quads as much as possible, even if the user config says otherwise
|
|
|
|
bool m_TrianglesAsQuads;
|
|
|
|
|
2020-08-29 10:10:38 +00:00
|
|
|
int m_ContextMajor;
|
|
|
|
int m_ContextMinor;
|
|
|
|
int m_ContextPatch;
|
|
|
|
};
|
|
|
|
|
2021-05-02 00:52:13 +00:00
|
|
|
// takes care of sdl related commands
|
|
|
|
class CCommandProcessorFragment_SDL
|
2012-01-03 20:39:10 +00:00
|
|
|
{
|
2021-05-02 00:52:13 +00:00
|
|
|
// SDL stuff
|
2022-12-04 21:54:18 +00:00
|
|
|
SDL_Window *m_pWindow = nullptr;
|
|
|
|
SDL_GLContext m_GLContext = nullptr;
|
2021-05-02 00:52:13 +00:00
|
|
|
|
|
|
|
public:
|
|
|
|
enum
|
2012-10-06 21:31:02 +00:00
|
|
|
{
|
2021-05-02 00:52:13 +00:00
|
|
|
CMD_INIT = CCommandBuffer::CMDGROUP_PLATFORM_SDL,
|
|
|
|
CMD_SHUTDOWN,
|
2012-10-06 21:31:02 +00:00
|
|
|
};
|
|
|
|
|
2021-05-02 00:52:13 +00:00
|
|
|
struct SCommand_Init : public CCommandBuffer::SCommand
|
|
|
|
{
|
|
|
|
SCommand_Init() :
|
|
|
|
SCommand(CMD_INIT) {}
|
|
|
|
SDL_Window *m_pWindow;
|
|
|
|
SDL_GLContext m_GLContext;
|
|
|
|
};
|
2020-08-29 10:10:38 +00:00
|
|
|
|
2021-05-02 00:52:13 +00:00
|
|
|
struct SCommand_Shutdown : public CCommandBuffer::SCommand
|
|
|
|
{
|
|
|
|
SCommand_Shutdown() :
|
|
|
|
SCommand(CMD_SHUTDOWN) {}
|
|
|
|
};
|
2020-08-29 10:10:38 +00:00
|
|
|
|
2021-05-02 00:52:13 +00:00
|
|
|
private:
|
|
|
|
void Cmd_Init(const SCommand_Init *pCommand);
|
|
|
|
void Cmd_Shutdown(const SCommand_Shutdown *pCommand);
|
|
|
|
void Cmd_Swap(const CCommandBuffer::SCommand_Swap *pCommand);
|
|
|
|
void Cmd_VSync(const CCommandBuffer::SCommand_VSync *pCommand);
|
2021-08-24 10:18:20 +00:00
|
|
|
void Cmd_WindowCreateNtf(const CCommandBuffer::SCommand_WindowCreateNtf *pCommand);
|
|
|
|
void Cmd_WindowDestroyNtf(const CCommandBuffer::SCommand_WindowDestroyNtf *pCommand);
|
2020-09-26 19:41:58 +00:00
|
|
|
|
2021-05-02 00:52:13 +00:00
|
|
|
public:
|
|
|
|
CCommandProcessorFragment_SDL();
|
2020-09-20 17:30:23 +00:00
|
|
|
|
2021-05-02 00:52:13 +00:00
|
|
|
bool RunCommand(const CCommandBuffer::SCommand *pBaseCommand);
|
|
|
|
};
|
2021-04-30 22:42:37 +00:00
|
|
|
|
2022-10-25 16:51:56 +00:00
|
|
|
// command processor implementation, uses the fragments to combine into one processor
|
2022-03-20 17:03:25 +00:00
|
|
|
class CCommandProcessor_SDL_GL : public CGraphicsBackend_Threaded::ICommandProcessor
|
2012-01-03 20:39:10 +00:00
|
|
|
{
|
2022-12-09 15:16:16 +00:00
|
|
|
CCommandProcessorFragment_GLBase *m_pGLBackend;
|
2015-07-09 00:08:14 +00:00
|
|
|
CCommandProcessorFragment_SDL m_SDL;
|
|
|
|
CCommandProcessorFragment_General m_General;
|
2020-09-26 19:41:58 +00:00
|
|
|
|
2021-04-30 22:42:37 +00:00
|
|
|
EBackendType m_BackendType;
|
|
|
|
|
2022-12-09 15:16:16 +00:00
|
|
|
SGFXErrorContainer m_Error;
|
|
|
|
SGFXWarningContainer m_Warning;
|
|
|
|
|
2015-07-09 00:08:14 +00:00
|
|
|
public:
|
2022-03-20 17:03:25 +00:00
|
|
|
CCommandProcessor_SDL_GL(EBackendType BackendType, int GLMajor, int GLMinor, int GLPatch);
|
|
|
|
virtual ~CCommandProcessor_SDL_GL();
|
2022-05-17 20:13:44 +00:00
|
|
|
void RunBuffer(CCommandBuffer *pBuffer) override;
|
2022-12-09 15:16:16 +00:00
|
|
|
|
|
|
|
SGFXErrorContainer &GetError() override;
|
|
|
|
void ErroneousCleanup() override;
|
|
|
|
|
|
|
|
SGFXWarningContainer &GetWarning() override;
|
|
|
|
|
|
|
|
void HandleError();
|
|
|
|
void HandleWarning();
|
2012-01-03 20:39:10 +00:00
|
|
|
};
|
|
|
|
|
2021-03-26 10:30:24 +00:00
|
|
|
static constexpr size_t gs_GPUInfoStringSize = 256;
|
|
|
|
|
2022-03-20 17:03:25 +00:00
|
|
|
// graphics backend implemented with SDL and the graphics library @see EBackendType
|
|
|
|
class CGraphicsBackend_SDL_GL : public CGraphicsBackend_Threaded
|
2012-01-03 20:39:10 +00:00
|
|
|
{
|
2022-12-04 21:54:18 +00:00
|
|
|
SDL_Window *m_pWindow = nullptr;
|
|
|
|
SDL_GLContext m_GLContext = nullptr;
|
2022-03-20 17:04:00 +00:00
|
|
|
ICommandProcessor *m_pProcessor = nullptr;
|
2022-03-20 17:03:25 +00:00
|
|
|
std::atomic<uint64_t> m_TextureMemoryUsage{0};
|
|
|
|
std::atomic<uint64_t> m_BufferMemoryUsage{0};
|
|
|
|
std::atomic<uint64_t> m_StreamMemoryUsage{0};
|
|
|
|
std::atomic<uint64_t> m_StagingMemoryUsage{0};
|
|
|
|
|
|
|
|
TTWGraphicsGPUList m_GPUList;
|
|
|
|
|
|
|
|
TGLBackendReadPresentedImageData m_ReadPresentedImageDataFunc;
|
|
|
|
|
2016-04-29 22:34:12 +00:00
|
|
|
int m_NumScreens;
|
2020-08-29 10:10:38 +00:00
|
|
|
|
|
|
|
SBackendCapabilites m_Capabilites;
|
2020-09-26 19:41:58 +00:00
|
|
|
|
2021-03-26 10:30:24 +00:00
|
|
|
char m_aVendorString[gs_GPUInfoStringSize] = {};
|
|
|
|
char m_aVersionString[gs_GPUInfoStringSize] = {};
|
|
|
|
char m_aRendererString[gs_GPUInfoStringSize] = {};
|
|
|
|
|
2022-03-20 17:04:00 +00:00
|
|
|
EBackendType m_BackendType = BACKEND_TYPE_AUTO;
|
2020-09-26 19:41:58 +00:00
|
|
|
|
2020-11-05 19:38:37 +00:00
|
|
|
char m_aErrorString[256];
|
|
|
|
|
2021-04-30 22:42:37 +00:00
|
|
|
static EBackendType DetectBackend();
|
|
|
|
static void ClampDriverVersion(EBackendType BackendType);
|
|
|
|
|
2022-12-09 15:16:16 +00:00
|
|
|
protected:
|
|
|
|
bool TryCreateMsgBox(bool AsError, const char *pTitle, const char *pMsg) override;
|
|
|
|
|
2012-01-03 20:39:10 +00:00
|
|
|
public:
|
2022-12-09 15:16:16 +00:00
|
|
|
CGraphicsBackend_SDL_GL(TTranslateFunc &&TranslateFunc);
|
2022-05-22 12:27:55 +00:00
|
|
|
int Init(const char *pName, int *pScreen, int *pWidth, int *pHeight, int *pRefreshRate, int *pFsaaSamples, int Flags, int *pDesktopWidth, int *pDesktopHeight, int *pCurrentWidth, int *pCurrentHeight, class IStorage *pStorage) override;
|
2022-05-17 20:13:44 +00:00
|
|
|
int Shutdown() override;
|
|
|
|
|
|
|
|
uint64_t TextureMemoryUsage() const override;
|
|
|
|
uint64_t BufferMemoryUsage() const override;
|
|
|
|
uint64_t StreamedMemoryUsage() const override;
|
|
|
|
uint64_t StagingMemoryUsage() const override;
|
|
|
|
|
|
|
|
const TTWGraphicsGPUList &GetGPUs() const override;
|
|
|
|
|
|
|
|
int GetNumScreens() const override { return m_NumScreens; }
|
|
|
|
|
|
|
|
void GetVideoModes(CVideoMode *pModes, int MaxModes, int *pNumModes, int HiDPIScale, int MaxWindowWidth, int MaxWindowHeight, int ScreenID) override;
|
|
|
|
void GetCurrentVideoMode(CVideoMode &CurMode, int HiDPIScale, int MaxWindowWidth, int MaxWindowHeight, int ScreenID) override;
|
|
|
|
|
|
|
|
void Minimize() override;
|
|
|
|
void Maximize() override;
|
|
|
|
void SetWindowParams(int FullscreenMode, bool IsBorderless, bool AllowResizing) override;
|
|
|
|
bool SetWindowScreen(int Index) override;
|
|
|
|
bool UpdateDisplayMode(int Index) override;
|
|
|
|
int GetWindowScreen() override;
|
|
|
|
int WindowActive() override;
|
|
|
|
int WindowOpen() override;
|
|
|
|
void SetWindowGrab(bool Grab) override;
|
|
|
|
bool ResizeWindow(int w, int h, int RefreshRate) override;
|
|
|
|
void GetViewportSize(int &w, int &h) override;
|
|
|
|
void NotifyWindow() override;
|
|
|
|
|
|
|
|
void WindowDestroyNtf(uint32_t WindowID) override;
|
|
|
|
void WindowCreateNtf(uint32_t WindowID) override;
|
|
|
|
|
|
|
|
bool GetDriverVersion(EGraphicsDriverAgeType DriverAgeType, int &Major, int &Minor, int &Patch, const char *&pName, EBackendType BackendType) override;
|
|
|
|
bool IsConfigModernAPI() override { return IsModernAPI(m_BackendType); }
|
|
|
|
bool UseTrianglesAsQuad() override { return m_Capabilites.m_TrianglesAsQuads; }
|
|
|
|
bool HasTileBuffering() override { return m_Capabilites.m_TileBuffering; }
|
|
|
|
bool HasQuadBuffering() override { return m_Capabilites.m_QuadBuffering; }
|
|
|
|
bool HasTextBuffering() override { return m_Capabilites.m_TextBuffering; }
|
|
|
|
bool HasQuadContainerBuffering() override { return m_Capabilites.m_QuadContainerBuffering; }
|
|
|
|
bool Has2DTextureArrays() override { return m_Capabilites.m_2DArrayTextures; }
|
|
|
|
|
|
|
|
const char *GetErrorString() override
|
2020-11-05 19:38:37 +00:00
|
|
|
{
|
|
|
|
if(m_aErrorString[0] != '\0')
|
|
|
|
return m_aErrorString;
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
2021-03-26 10:30:24 +00:00
|
|
|
|
2022-05-17 20:13:44 +00:00
|
|
|
const char *GetVendorString() override
|
2021-03-26 10:30:24 +00:00
|
|
|
{
|
|
|
|
return m_aVendorString;
|
|
|
|
}
|
|
|
|
|
2022-05-17 20:13:44 +00:00
|
|
|
const char *GetVersionString() override
|
2021-03-26 10:30:24 +00:00
|
|
|
{
|
|
|
|
return m_aVersionString;
|
|
|
|
}
|
|
|
|
|
2022-05-17 20:13:44 +00:00
|
|
|
const char *GetRendererString() override
|
2021-03-26 10:30:24 +00:00
|
|
|
{
|
|
|
|
return m_aRendererString;
|
|
|
|
}
|
2021-04-30 22:42:37 +00:00
|
|
|
|
2022-05-17 20:13:44 +00:00
|
|
|
TGLBackendReadPresentedImageData &GetReadPresentedImageDataFuncUnsafe() override;
|
2022-03-20 17:03:25 +00:00
|
|
|
|
2021-04-30 22:42:37 +00:00
|
|
|
static bool IsModernAPI(EBackendType BackendType);
|
2012-01-03 20:39:10 +00:00
|
|
|
};
|
2018-07-06 14:11:38 +00:00
|
|
|
|
|
|
|
#endif // ENGINE_CLIENT_BACKEND_SDL_H
|