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
|
|
|
|
|
|
|
#include "SDL.h"
|
2021-04-30 22:42:37 +00:00
|
|
|
|
|
|
|
#include <base/detect.h>
|
|
|
|
|
2021-05-01 21:33:42 +00:00
|
|
|
#include "graphics_defines.h"
|
2012-01-03 20:39:10 +00:00
|
|
|
|
2020-11-06 17:18:55 +00:00
|
|
|
#include "blocklist_driver.h"
|
2012-01-03 20:39:10 +00:00
|
|
|
#include "graphics_threaded.h"
|
|
|
|
|
Make sure headers compile standalone
Not planning to do this automatically, but at least cleaning it up once
provides some benefit. Every header should include what it uses.
$ for i in src/**/*.h; do j=${i#"src/"}; echo $j; echo "#include <$j>\nint main() { return 0; }" | /usr/bin/c++ -DCONF_OPENSSL -DCONF_SQL -DCONF_VIDEORECORDER -DCONF_WAVPACK_CLOSE_FILE -DCONF_WAVPACK_OPEN_FILE_INPUT_EX -DGAME_RELEASE_VERSION=\"15.0.5\" -DGLEW_STATIC -D_FORTIFY_SOURCE=2 -I/usr/include/freetype2 -I/usr/include/opus -I/usr/include/SDL2 -I/usr/include/wavpack -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -I/usr/include/libmount -I/usr/include/blkid -Isrc -I/usr/include/mysql -I/home/deen/sys/include/ -O2 -g -DNDEBUG -fdiagnostics-color=always -fstack-protector-all -Wall -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -Wformat=2 -Wno-nullability-completeness -Wduplicated-cond -Wduplicated-branches -Wlogical-op -Wrestrict -std=gnu++11 -o /dev/null -x c++ -; done
Ignored: tuning.h, variables.h, config_common.h, mapitems_ex_types.h, mapbugs_list.h, protocol7.h, teehistorian_ex_chunks.h, protocol_ex_msgs.h, config.h, config_variables.h, external, keynames.h
2020-09-26 08:23:33 +00:00
|
|
|
#include <base/tl/threading.h>
|
|
|
|
|
2020-08-29 10:10:38 +00:00
|
|
|
#include <atomic>
|
2021-10-27 22:52:06 +00:00
|
|
|
#include <condition_variable>
|
|
|
|
#include <mutex>
|
|
|
|
#include <thread>
|
2021-08-21 19:41:51 +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
|
|
|
|
{
|
|
|
|
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:
|
|
|
|
virtual ~ICommandProcessor() {}
|
|
|
|
virtual void RunBuffer(CCommandBuffer *pBuffer) = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
CGraphicsBackend_Threaded();
|
|
|
|
|
|
|
|
virtual void RunBuffer(CCommandBuffer *pBuffer);
|
|
|
|
virtual bool IsIdle() const;
|
|
|
|
virtual void WaitForIdle();
|
2015-07-09 00:08:14 +00:00
|
|
|
|
2012-01-03 20:39:10 +00:00
|
|
|
protected:
|
|
|
|
void StartProcessor(ICommandProcessor *pProcessor);
|
|
|
|
void StopProcessor();
|
|
|
|
|
|
|
|
private:
|
|
|
|
ICommandProcessor *m_pProcessor;
|
2021-10-27 22:52:06 +00:00
|
|
|
std::mutex m_BufferSwapMutex;
|
|
|
|
std::condition_variable m_BufferSwapCond;
|
|
|
|
std::condition_variable m_BufferDoneCond;
|
|
|
|
CCommandBuffer *m_pBuffer;
|
2021-10-15 10:15:39 +00:00
|
|
|
std::atomic_bool m_Shutdown;
|
2021-10-27 22:52:06 +00:00
|
|
|
std::atomic_bool m_BufferInProcess;
|
|
|
|
std::thread m_Thread;
|
2012-01-03 20:39:10 +00:00
|
|
|
|
2021-10-27 22:52:06 +00:00
|
|
|
void ThreadFunc();
|
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
|
|
|
};
|
|
|
|
|
2021-04-30 22:42:37 +00:00
|
|
|
enum EBackendType
|
|
|
|
{
|
|
|
|
BACKEND_TYPE_OPENGL = 0,
|
|
|
|
BACKEND_TYPE_OPENGL_ES,
|
|
|
|
};
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
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
|
|
|
|
SDL_Window *m_pWindow;
|
|
|
|
SDL_GLContext m_GLContext;
|
|
|
|
|
|
|
|
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
|
|
|
|
2021-05-02 00:52:13 +00:00
|
|
|
class CCommandProcessorFragment_OpenGLBase
|
|
|
|
{
|
2012-10-06 21:31:02 +00:00
|
|
|
public:
|
2021-05-02 00:52:13 +00:00
|
|
|
virtual ~CCommandProcessorFragment_OpenGLBase() = default;
|
|
|
|
virtual bool RunCommand(const CCommandBuffer::SCommand *pBaseCommand) = 0;
|
|
|
|
|
2012-10-06 21:31:02 +00:00
|
|
|
enum
|
|
|
|
{
|
|
|
|
CMD_INIT = CCommandBuffer::CMDGROUP_PLATFORM_OPENGL,
|
2020-08-29 10:10:38 +00:00
|
|
|
CMD_SHUTDOWN = CMD_INIT + 1,
|
2012-10-06 21:31:02 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct SCommand_Init : public CCommandBuffer::SCommand
|
|
|
|
{
|
2020-09-26 19:41:58 +00:00
|
|
|
SCommand_Init() :
|
|
|
|
SCommand(CMD_INIT) {}
|
2020-08-29 10:10:38 +00:00
|
|
|
class IStorage *m_pStorage;
|
|
|
|
std::atomic<int> *m_pTextureMemoryUsage;
|
2020-08-29 15:44:23 +00:00
|
|
|
SBackendCapabilites *m_pCapabilities;
|
|
|
|
int *m_pInitError;
|
2021-04-30 22:42:37 +00:00
|
|
|
|
|
|
|
const char **m_pErrStringPtr;
|
|
|
|
|
|
|
|
char *m_pVendorString;
|
|
|
|
char *m_pVersionString;
|
|
|
|
char *m_pRendererString;
|
|
|
|
|
|
|
|
int m_RequestedMajor;
|
|
|
|
int m_RequestedMinor;
|
|
|
|
int m_RequestedPatch;
|
|
|
|
|
|
|
|
EBackendType m_RequestedBackend;
|
|
|
|
|
|
|
|
int m_GlewMajor;
|
|
|
|
int m_GlewMinor;
|
|
|
|
int m_GlewPatch;
|
2020-08-22 06:09:10 +00:00
|
|
|
};
|
|
|
|
|
2020-08-29 10:10:38 +00:00
|
|
|
struct SCommand_Shutdown : public CCommandBuffer::SCommand
|
|
|
|
{
|
2020-09-26 19:41:58 +00:00
|
|
|
SCommand_Shutdown() :
|
|
|
|
SCommand(CMD_SHUTDOWN) {}
|
2020-08-29 10:10:38 +00:00
|
|
|
};
|
2012-01-03 20:39:10 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
// command processor impelementation, uses the fragments to combine into one processor
|
|
|
|
class CCommandProcessor_SDL_OpenGL : public CGraphicsBackend_Threaded::ICommandProcessor
|
|
|
|
{
|
2021-05-02 00:52:13 +00:00
|
|
|
CCommandProcessorFragment_OpenGLBase *m_pOpenGL;
|
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;
|
|
|
|
|
2015-07-09 00:08:14 +00:00
|
|
|
public:
|
2021-04-30 22:42:37 +00:00
|
|
|
CCommandProcessor_SDL_OpenGL(EBackendType BackendType, int OpenGLMajor, int OpenGLMinor, int OpenGLPatch);
|
2020-09-30 21:51:33 +00:00
|
|
|
virtual ~CCommandProcessor_SDL_OpenGL();
|
2012-01-03 20:39:10 +00:00
|
|
|
virtual void RunBuffer(CCommandBuffer *pBuffer);
|
|
|
|
};
|
|
|
|
|
2021-03-26 10:30:24 +00:00
|
|
|
static constexpr size_t gs_GPUInfoStringSize = 256;
|
|
|
|
|
2012-01-03 20:39:10 +00:00
|
|
|
// graphics backend implemented with SDL and OpenGL
|
|
|
|
class CGraphicsBackend_SDL_OpenGL : public CGraphicsBackend_Threaded
|
|
|
|
{
|
2021-08-21 19:41:51 +00:00
|
|
|
SDL_Window *m_pWindow = NULL;
|
2015-08-24 20:46:28 +00:00
|
|
|
SDL_GLContext m_GLContext;
|
2012-01-03 20:39:10 +00:00
|
|
|
ICommandProcessor *m_pProcessor;
|
2020-08-29 10:10:38 +00:00
|
|
|
std::atomic<int> m_TextureMemoryUsage;
|
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] = {};
|
|
|
|
|
2020-08-29 10:10:38 +00:00
|
|
|
bool m_UseNewOpenGL;
|
2021-05-02 21:20:21 +00:00
|
|
|
EBackendType m_BackendType;
|
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);
|
|
|
|
|
2012-01-03 20:39:10 +00:00
|
|
|
public:
|
2021-08-21 19:41:51 +00:00
|
|
|
virtual int Init(const char *pName, int *Screen, int *pWidth, int *pHeight, int *pRefreshRate, int FsaaSamples, int Flags, int *pDesktopWidth, int *pDesktopHeight, int *pCurrentWidth, int *pCurrentHeight, class IStorage *pStorage);
|
2012-01-03 20:39:10 +00:00
|
|
|
virtual int Shutdown();
|
|
|
|
|
2012-10-06 21:31:02 +00:00
|
|
|
virtual int MemoryUsage() const;
|
|
|
|
|
2016-04-29 22:34:12 +00:00
|
|
|
virtual int GetNumScreens() const { return m_NumScreens; }
|
|
|
|
|
2021-08-21 19:41:51 +00:00
|
|
|
virtual void GetVideoModes(CVideoMode *pModes, int MaxModes, int *pNumModes, int HiDPIScale, int MaxWindowWidth, int MaxWindowHeight, int Screen);
|
|
|
|
virtual void GetCurrentVideoMode(CVideoMode &CurMode, int HiDPIScale, int MaxWindowWidth, int MaxWindowHeight, int Screen);
|
|
|
|
|
2012-01-03 20:39:10 +00:00
|
|
|
virtual void Minimize();
|
|
|
|
virtual void Maximize();
|
2021-01-31 20:54:04 +00:00
|
|
|
virtual void SetWindowParams(int FullscreenMode, bool IsBorderless);
|
2016-04-29 22:34:12 +00:00
|
|
|
virtual bool SetWindowScreen(int Index);
|
2021-12-13 17:42:21 +00:00
|
|
|
virtual bool UpdateDisplayMode(int Index);
|
2016-04-29 22:34:12 +00:00
|
|
|
virtual int GetWindowScreen();
|
2012-01-03 20:39:10 +00:00
|
|
|
virtual int WindowActive();
|
|
|
|
virtual int WindowOpen();
|
2015-08-24 23:01:38 +00:00
|
|
|
virtual void SetWindowGrab(bool Grab);
|
2021-08-21 19:41:51 +00:00
|
|
|
virtual void ResizeWindow(int w, int h, int RefreshRate);
|
2020-12-12 11:58:59 +00:00
|
|
|
virtual void GetViewportSize(int &w, int &h);
|
2014-10-18 14:17:36 +00:00
|
|
|
virtual void NotifyWindow();
|
2020-09-26 19:41:58 +00:00
|
|
|
|
2021-05-02 21:20:21 +00:00
|
|
|
virtual void GetDriverVersion(EGraphicsDriverAgeType DriverAgeType, int &Major, int &Minor, int &Patch);
|
|
|
|
virtual bool IsConfigModernAPI() { return IsModernAPI(m_BackendType); }
|
2020-08-29 10:10:38 +00:00
|
|
|
virtual bool IsNewOpenGL() { return m_UseNewOpenGL; }
|
|
|
|
virtual bool HasTileBuffering() { return m_Capabilites.m_TileBuffering; }
|
|
|
|
virtual bool HasQuadBuffering() { return m_Capabilites.m_QuadBuffering; }
|
|
|
|
virtual bool HasTextBuffering() { return m_Capabilites.m_TextBuffering; }
|
|
|
|
virtual bool HasQuadContainerBuffering() { return m_Capabilites.m_QuadContainerBuffering; }
|
|
|
|
virtual bool Has2DTextureArrays() { return m_Capabilites.m_2DArrayTextures; }
|
2020-11-05 19:38:37 +00:00
|
|
|
|
|
|
|
virtual const char *GetErrorString()
|
|
|
|
{
|
|
|
|
if(m_aErrorString[0] != '\0')
|
|
|
|
return m_aErrorString;
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
2021-03-26 10:30:24 +00:00
|
|
|
|
|
|
|
virtual const char *GetVendorString()
|
|
|
|
{
|
|
|
|
return m_aVendorString;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual const char *GetVersionString()
|
|
|
|
{
|
|
|
|
return m_aVersionString;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual const char *GetRendererString()
|
|
|
|
{
|
|
|
|
return m_aRendererString;
|
|
|
|
}
|
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
|