2012-01-03 20:39:10 +00:00
# include "SDL.h"
# include "graphics_threaded.h"
2015-08-24 20:46:28 +00:00
# if defined(CONF_PLATFORM_MACOSX)
2012-08-26 18:02:04 +00:00
# include <objc/objc-runtime.h>
2012-01-03 21:49:31 +00:00
2012-08-26 18:02:04 +00:00
class CAutoreleasePool
{
private :
id m_Pool ;
public :
CAutoreleasePool ( )
{
Class NSAutoreleasePoolClass = ( Class ) objc_getClass ( " NSAutoreleasePool " ) ;
m_Pool = class_createInstance ( NSAutoreleasePoolClass , 0 ) ;
SEL selector = sel_registerName ( " init " ) ;
objc_msgSend ( m_Pool , selector ) ;
}
~ CAutoreleasePool ( )
{
SEL selector = sel_registerName ( " drain " ) ;
objc_msgSend ( m_Pool , selector ) ;
}
2015-07-09 00:08:14 +00:00
} ;
2012-01-03 20:39:10 +00:00
# endif
// basic threaded backend, abstract, missing init and shutdown functions
class CGraphicsBackend_Threaded : public IGraphicsBackend
{
public :
// constructed on the main thread, the rest of the functions is runned on the render thread
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 ;
CCommandBuffer * volatile m_pBuffer ;
volatile bool m_Shutdown ;
semaphore m_Activity ;
semaphore m_BufferDone ;
void * m_pThread ;
static void ThreadFunc ( void * pUser ) ;
} ;
// takes care of implementation independent operations
class CCommandProcessorFragment_General
{
void Cmd_Nop ( ) ;
void Cmd_Signal ( const CCommandBuffer : : SCommand_Signal * pCommand ) ;
public :
bool RunCommand ( const CCommandBuffer : : SCommand * pBaseCommand ) ;
} ;
// takes care of opengl related rendering
class CCommandProcessorFragment_OpenGL
{
2012-10-06 21:31:02 +00:00
struct CTexture
{
GLuint m_Tex ;
int m_MemSize ;
} ;
CTexture m_aTextures [ CCommandBuffer : : MAX_TEXTURES ] ;
volatile int * m_pTextureMemoryUsage ;
public :
enum
{
CMD_INIT = CCommandBuffer : : CMDGROUP_PLATFORM_OPENGL ,
} ;
struct SCommand_Init : public CCommandBuffer : : SCommand
{
SCommand_Init ( ) : SCommand ( CMD_INIT ) { }
volatile int * m_pTextureMemoryUsage ;
} ;
private :
2012-01-03 20:39:10 +00:00
static int TexFormatToOpenGLFormat ( int TexFormat ) ;
2012-10-07 09:22:49 +00:00
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 void * Rescale ( int Width , int Height , int NewWidth , int NewHeight , int Format , const unsigned char * pData ) ;
2012-01-03 20:39:10 +00:00
void SetState ( const CCommandBuffer : : SState & State ) ;
2012-10-06 21:31:02 +00:00
void Cmd_Init ( const SCommand_Init * pCommand ) ;
2012-01-03 20:39:10 +00:00
void Cmd_Texture_Update ( const CCommandBuffer : : SCommand_Texture_Update * pCommand ) ;
void Cmd_Texture_Destroy ( const CCommandBuffer : : SCommand_Texture_Destroy * pCommand ) ;
void Cmd_Texture_Create ( const CCommandBuffer : : SCommand_Texture_Create * pCommand ) ;
void Cmd_Clear ( const CCommandBuffer : : SCommand_Clear * pCommand ) ;
void Cmd_Render ( const CCommandBuffer : : SCommand_Render * pCommand ) ;
void Cmd_Screenshot ( const CCommandBuffer : : SCommand_Screenshot * pCommand ) ;
public :
CCommandProcessorFragment_OpenGL ( ) ;
bool RunCommand ( const CCommandBuffer : : SCommand * pBaseCommand ) ;
} ;
2017-09-02 13:24:07 +00:00
class CGLSLProgram ;
2017-09-12 18:07:38 +00:00
class CGLSLTWProgram ;
class CGLSLPrimitiveProgram ;
2017-09-02 13:24:07 +00:00
class CGLSLQuadProgram ;
2017-09-12 18:07:38 +00:00
class CGLSLTileProgram ;
class CGLSLBorderTileProgram ;
class CGLSLBorderTileLineProgram ;
2017-09-02 13:24:07 +00:00
// takes care of opengl 3.2 related rendering
class CCommandProcessorFragment_OpenGL3_3
{
struct CTexture
{
GLuint m_Tex ;
GLuint m_Sampler ;
int m_MemSize ;
} ;
CTexture m_aTextures [ CCommandBuffer : : MAX_TEXTURES ] ;
volatile int * m_pTextureMemoryUsage ;
2017-09-13 18:33:58 +00:00
CGLSLPrimitiveProgram * m_pPrimitiveProgram ;
2017-09-12 18:07:38 +00:00
//CGLSLQuadProgram* m_QuadProgram;
2017-09-13 18:33:58 +00:00
CGLSLTileProgram * m_pTileProgram ;
CGLSLTileProgram * m_pTileProgramTextured ;
CGLSLBorderTileProgram * m_pBorderTileProgram ;
CGLSLBorderTileProgram * m_pBorderTileProgramTextured ;
CGLSLBorderTileLineProgram * m_pBorderTileLineProgram ;
CGLSLBorderTileLineProgram * m_pBorderTileLineProgramTextured ;
2017-09-02 13:24:07 +00:00
2017-09-13 18:33:58 +00:00
GLuint m_PrimitiveDrawVertexID ;
GLuint m_PrimitiveDrawBufferID ;
2017-09-12 18:07:38 +00:00
GLint m_MaxTextureUnits ;
int m_LastBlendMode ; //avoid all possible opengl state changes
bool m_LastClipEnable ;
struct STextureBound {
int m_TextureSlot ;
int m_LastWrapMode ;
} ;
std : : vector < STextureBound > m_TextureSlotBoundToUnit ; //the texture index generated by loadtextureraw is stored in an index calculated by max texture units
bool IsAndUpdateTextureSlotBound ( int IDX , int Slot ) ;
void DestroyTexture ( int Slot ) ;
void DestroyVisualObjects ( int Index ) ;
struct SVisualObject {
SVisualObject ( ) : m_VertArrayID ( 0 ) , m_VertBufferID ( 0 ) , m_NumElements ( 0 ) , m_IsTextured ( false ) , m_IndexBufferID ( 0 ) , m_NumIndices ( 0 ) { }
GLuint m_VertArrayID ;
GLuint m_VertBufferID ;
int m_NumElements ; //vertices and texture coordinates
bool m_IsTextured ;
GLuint m_IndexBufferID ;
int m_NumIndices ;
} ;
std : : vector < SVisualObject > m_VisualObjects ;
2017-09-02 13:24:07 +00:00
public :
enum
{
CMD_INIT = CCommandBuffer : : CMDGROUP_PLATFORM_OPENGL3_3 ,
CMD_SHUTDOWN ,
} ;
struct SCommand_Init : public CCommandBuffer : : SCommand
{
SCommand_Init ( ) : SCommand ( CMD_INIT ) { }
volatile int * m_pTextureMemoryUsage ;
} ;
struct SCommand_Shutdown : public CCommandBuffer : : SCommand
{
SCommand_Shutdown ( ) : SCommand ( CMD_SHUTDOWN ) { }
} ;
private :
static int TexFormatToOpenGLFormat ( int TexFormat ) ;
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 void * Rescale ( int Width , int Height , int NewWidth , int NewHeight , int Format , const unsigned char * pData ) ;
2017-09-12 18:07:38 +00:00
void SetState ( const CCommandBuffer : : SState & State , CGLSLTWProgram * pProgram ) ;
2017-09-02 13:24:07 +00:00
void Cmd_Init ( const SCommand_Init * pCommand ) ;
void Cmd_Shutdown ( const SCommand_Shutdown * pCommand ) ;
void Cmd_Texture_Update ( const CCommandBuffer : : SCommand_Texture_Update * pCommand ) ;
void Cmd_Texture_Destroy ( const CCommandBuffer : : SCommand_Texture_Destroy * pCommand ) ;
void Cmd_Texture_Create ( const CCommandBuffer : : SCommand_Texture_Create * pCommand ) ;
void Cmd_Clear ( const CCommandBuffer : : SCommand_Clear * pCommand ) ;
void Cmd_Render ( const CCommandBuffer : : SCommand_Render * pCommand ) ;
void Cmd_Screenshot ( const CCommandBuffer : : SCommand_Screenshot * pCommand ) ;
2017-09-12 18:07:38 +00:00
void Cmd_CreateVertBuffer ( const CCommandBuffer : : SCommand_CreateVertexBufferObject * pCommand ) ;
void Cmd_AppendVertBuffer ( const CCommandBuffer : : SCommand_AppendVertexBufferObject * pCommand ) ;
void Cmd_CreateVertArray ( const CCommandBuffer : : SCommand_CreateVertexArrayObject * pCommand ) ;
void Cmd_CreateIndexBuffer ( const CCommandBuffer : : SCommand_CreateIndexBufferObject * pCommand ) ;
void Cmd_AppendIndexBuffer ( const CCommandBuffer : : SCommand_AppendIndexBufferObject * pCommand ) ;
void Cmd_RenderVertexArray ( const CCommandBuffer : : SCommand_RenderVertexArray * pCommand ) ;
void Cmd_DestroyVertexArray ( const CCommandBuffer : : SCommand_DestroyVisual * pCommand ) ;
void Cmd_RenderBorderTile ( const CCommandBuffer : : SCommand_RenderBorderTile * pCommand ) ;
void Cmd_RenderBorderTileLine ( const CCommandBuffer : : SCommand_RenderBorderTileLine * pCommand ) ;
2017-09-02 13:24:07 +00:00
public :
CCommandProcessorFragment_OpenGL3_3 ( ) ;
bool RunCommand ( const CCommandBuffer : : SCommand * pBaseCommand ) ;
} ;
2012-01-03 20:39:10 +00:00
// takes care of sdl related commands
class CCommandProcessorFragment_SDL
{
// SDL stuff
2015-08-24 20:46:28 +00:00
SDL_Window * m_pWindow ;
SDL_GLContext m_GLContext ;
2012-01-03 20:39:10 +00:00
public :
enum
{
2012-10-06 21:31:02 +00:00
CMD_INIT = CCommandBuffer : : CMDGROUP_PLATFORM_SDL ,
2012-01-03 20:39:10 +00:00
CMD_SHUTDOWN ,
} ;
struct SCommand_Init : public CCommandBuffer : : SCommand
{
SCommand_Init ( ) : SCommand ( CMD_INIT ) { }
2015-08-24 20:46:28 +00:00
SDL_Window * m_pWindow ;
SDL_GLContext m_GLContext ;
2012-01-03 20:39:10 +00:00
} ;
struct SCommand_Shutdown : public CCommandBuffer : : SCommand
{
SCommand_Shutdown ( ) : SCommand ( CMD_SHUTDOWN ) { }
} ;
private :
void Cmd_Init ( const SCommand_Init * pCommand ) ;
void Cmd_Shutdown ( const SCommand_Shutdown * pCommand ) ;
void Cmd_Swap ( const CCommandBuffer : : SCommand_Swap * pCommand ) ;
2016-04-29 22:34:12 +00:00
void Cmd_VSync ( const CCommandBuffer : : SCommand_VSync * pCommand ) ;
2016-04-30 15:59:58 +00:00
void Cmd_Resize ( const CCommandBuffer : : SCommand_Resize * pCommand ) ;
2012-01-03 20:39:10 +00:00
void Cmd_VideoModes ( const CCommandBuffer : : SCommand_VideoModes * pCommand ) ;
public :
CCommandProcessorFragment_SDL ( ) ;
bool RunCommand ( const CCommandBuffer : : SCommand * pBaseCommand ) ;
} ;
// command processor impelementation, uses the fragments to combine into one processor
class CCommandProcessor_SDL_OpenGL : public CGraphicsBackend_Threaded : : ICommandProcessor
{
2015-07-09 00:08:14 +00:00
CCommandProcessorFragment_OpenGL m_OpenGL ;
2017-09-02 13:24:07 +00:00
CCommandProcessorFragment_OpenGL3_3 m_OpenGL3_3 ;
2015-07-09 00:08:14 +00:00
CCommandProcessorFragment_SDL m_SDL ;
CCommandProcessorFragment_General m_General ;
2017-09-02 13:24:07 +00:00
bool m_UseOpenGL3_3 ;
2015-07-09 00:08:14 +00:00
public :
2017-09-02 13:24:07 +00:00
void UseOpenGL3_3 ( bool Use ) { m_UseOpenGL3_3 = Use ; }
2012-01-03 20:39:10 +00:00
virtual void RunBuffer ( CCommandBuffer * pBuffer ) ;
} ;
// graphics backend implemented with SDL and OpenGL
class CGraphicsBackend_SDL_OpenGL : public CGraphicsBackend_Threaded
{
2015-08-24 20:46:28 +00:00
SDL_Window * m_pWindow ;
SDL_GLContext m_GLContext ;
2012-01-03 20:39:10 +00:00
ICommandProcessor * m_pProcessor ;
2012-10-06 21:31:02 +00:00
volatile int m_TextureMemoryUsage ;
2016-04-29 22:34:12 +00:00
int m_NumScreens ;
2017-09-02 13:24:07 +00:00
bool m_UseOpenGL3_3 ;
2012-01-03 20:39:10 +00:00
public :
2016-04-29 22:34:12 +00:00
virtual int Init ( const char * pName , int * Screen , int * pWidth , int * pHeight , int FsaaSamples , int Flags , int * pDesktopWidth , int * pDesktopHeight ) ;
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 ; }
2012-01-03 20:39:10 +00:00
virtual void Minimize ( ) ;
virtual void Maximize ( ) ;
2016-04-29 19:07:10 +00:00
virtual bool Fullscreen ( bool State ) ;
2016-04-29 22:34:12 +00:00
virtual void SetWindowBordered ( bool State ) ; // on=true/off=false
virtual bool SetWindowScreen ( int Index ) ;
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 ) ;
2014-10-18 14:17:36 +00:00
virtual void NotifyWindow ( ) ;
2017-09-12 18:07:38 +00:00
virtual bool IsOpenGL3_3 ( ) { return m_UseOpenGL3_3 ; }
2012-01-03 20:39:10 +00:00
} ;