2014-11-05 00:46:40 +00:00
# include <base/detect.h>
# if defined(CONF_FAMILY_WINDOWS)
// For FlashWindowEx, FLASHWINFO, FLASHW_TRAY
# define _WIN32_WINNT 0x0501
# define WINVER 0x0501
# endif
2012-01-03 20:39:10 +00:00
2017-10-20 09:35:44 +00:00
# include "engine/external/glew/GL/glew.h"
2017-10-20 07:08:49 +00:00
2015-08-24 20:46:28 +00:00
# include <base/detect.h>
2016-04-29 22:34:12 +00:00
# include <base/math.h>
2015-08-26 01:50:01 +00:00
# include <stdlib.h>
2012-01-03 20:39:10 +00:00
# include "SDL.h"
2014-10-18 14:17:36 +00:00
# include "SDL_syswm.h"
2014-06-16 11:29:18 +00:00
# if defined(__ANDROID__)
# define GL_GLEXT_PROTOTYPES
# include <GLES/gl.h>
# include <GLES/glext.h>
# include <GL/glu.h>
# define glOrtho glOrthof
# else
2015-08-24 20:46:28 +00:00
# if defined(CONF_PLATFORM_MACOSX)
# include "OpenGL/glu.h"
# else
2017-10-20 08:20:29 +00:00
# include "SDL_opengl.h"
2015-08-24 20:46:28 +00:00
# include "GL/glu.h"
# endif
2014-06-16 11:29:18 +00:00
# endif
2012-01-03 20:39:10 +00:00
2014-10-26 00:25:36 +00:00
# if defined(SDL_VIDEO_DRIVER_X11)
# include <X11/Xutil.h>
# include <X11/Xlib.h>
# endif
2014-10-28 00:12:11 +00:00
# include <engine/shared/config.h>
2012-02-05 12:22:39 +00:00
# include <base/tl/threading.h>
2012-01-03 20:39:10 +00:00
# include "graphics_threaded.h"
# include "backend_sdl.h"
2017-09-02 13:24:07 +00:00
# include "opengl_sl_program.h"
# include "opengl_sl.h"
2017-10-17 14:38:40 +00:00
# ifdef __MINGW32__
extern " C "
{
int putenv ( const char * ) ;
}
# endif
2012-01-03 20:39:10 +00:00
// ------------ CGraphicsBackend_Threaded
void CGraphicsBackend_Threaded : : ThreadFunc ( void * pUser )
{
CGraphicsBackend_Threaded * pThis = ( CGraphicsBackend_Threaded * ) pUser ;
while ( ! pThis - > m_Shutdown )
{
pThis - > m_Activity . wait ( ) ;
if ( pThis - > m_pBuffer )
{
2015-08-24 20:46:28 +00:00
# ifdef CONF_PLATFORM_MACOSX
CAutoreleasePool AutoreleasePool ;
# endif
2012-01-03 20:39:10 +00:00
pThis - > m_pProcessor - > RunBuffer ( pThis - > m_pBuffer ) ;
sync_barrier ( ) ;
pThis - > m_pBuffer = 0x0 ;
pThis - > m_BufferDone . signal ( ) ;
}
}
}
CGraphicsBackend_Threaded : : CGraphicsBackend_Threaded ( )
{
m_pBuffer = 0x0 ;
m_pProcessor = 0x0 ;
m_pThread = 0x0 ;
}
void CGraphicsBackend_Threaded : : StartProcessor ( ICommandProcessor * pProcessor )
{
m_Shutdown = false ;
m_pProcessor = pProcessor ;
2015-04-07 17:07:38 +00:00
m_pThread = thread_init ( ThreadFunc , this ) ;
2012-01-03 20:39:10 +00:00
m_BufferDone . signal ( ) ;
}
void CGraphicsBackend_Threaded : : StopProcessor ( )
{
m_Shutdown = true ;
m_Activity . signal ( ) ;
thread_wait ( m_pThread ) ;
}
void CGraphicsBackend_Threaded : : RunBuffer ( CCommandBuffer * pBuffer )
{
WaitForIdle ( ) ;
m_pBuffer = pBuffer ;
m_Activity . signal ( ) ;
}
bool CGraphicsBackend_Threaded : : IsIdle ( ) const
{
return m_pBuffer = = 0x0 ;
}
void CGraphicsBackend_Threaded : : WaitForIdle ( )
{
while ( m_pBuffer ! = 0x0 )
m_BufferDone . wait ( ) ;
}
// ------------ CCommandProcessorFragment_General
void CCommandProcessorFragment_General : : Cmd_Signal ( const CCommandBuffer : : SCommand_Signal * pCommand )
{
pCommand - > m_pSemaphore - > signal ( ) ;
}
bool CCommandProcessorFragment_General : : RunCommand ( const CCommandBuffer : : SCommand * pBaseCommand )
{
switch ( pBaseCommand - > m_Cmd )
{
case CCommandBuffer : : CMD_NOP : break ;
case CCommandBuffer : : CMD_SIGNAL : Cmd_Signal ( static_cast < const CCommandBuffer : : SCommand_Signal * > ( pBaseCommand ) ) ; break ;
default : return false ;
}
return true ;
}
// ------------ CCommandProcessorFragment_OpenGL
int CCommandProcessorFragment_OpenGL : : TexFormatToOpenGLFormat ( int TexFormat )
{
if ( TexFormat = = CCommandBuffer : : TEXFORMAT_RGB ) return GL_RGB ;
if ( TexFormat = = CCommandBuffer : : TEXFORMAT_ALPHA ) return GL_ALPHA ;
if ( TexFormat = = CCommandBuffer : : TEXFORMAT_RGBA ) return GL_RGBA ;
return GL_RGBA ;
}
2012-10-07 09:22:49 +00:00
unsigned char CCommandProcessorFragment_OpenGL : : Sample ( int w , int h , const unsigned char * pData , int u , int v , int Offset , int ScaleW , int ScaleH , int Bpp )
{
int Value = 0 ;
for ( int x = 0 ; x < ScaleW ; x + + )
for ( int y = 0 ; y < ScaleH ; y + + )
Value + = pData [ ( ( v + y ) * w + ( u + x ) ) * Bpp + Offset ] ;
return Value / ( ScaleW * ScaleH ) ;
}
void * CCommandProcessorFragment_OpenGL : : Rescale ( int Width , int Height , int NewWidth , int NewHeight , int Format , const unsigned char * pData )
{
unsigned char * pTmpData ;
int ScaleW = Width / NewWidth ;
int ScaleH = Height / NewHeight ;
int Bpp = 3 ;
if ( Format = = CCommandBuffer : : TEXFORMAT_RGBA )
Bpp = 4 ;
pTmpData = ( unsigned char * ) mem_alloc ( NewWidth * NewHeight * Bpp , 1 ) ;
int c = 0 ;
for ( int y = 0 ; y < NewHeight ; y + + )
for ( int x = 0 ; x < NewWidth ; x + + , c + + )
{
pTmpData [ c * Bpp ] = Sample ( Width , Height , pData , x * ScaleW , y * ScaleH , 0 , ScaleW , ScaleH , Bpp ) ;
pTmpData [ c * Bpp + 1 ] = Sample ( Width , Height , pData , x * ScaleW , y * ScaleH , 1 , ScaleW , ScaleH , Bpp ) ;
pTmpData [ c * Bpp + 2 ] = Sample ( Width , Height , pData , x * ScaleW , y * ScaleH , 2 , ScaleW , ScaleH , Bpp ) ;
if ( Bpp = = 4 )
pTmpData [ c * Bpp + 3 ] = Sample ( Width , Height , pData , x * ScaleW , y * ScaleH , 3 , ScaleW , ScaleH , Bpp ) ;
}
return pTmpData ;
}
2012-01-03 20:39:10 +00:00
void CCommandProcessorFragment_OpenGL : : SetState ( const CCommandBuffer : : SState & State )
{
// blend
switch ( State . m_BlendMode )
{
case CCommandBuffer : : BLEND_NONE :
glDisable ( GL_BLEND ) ;
break ;
case CCommandBuffer : : BLEND_ALPHA :
glEnable ( GL_BLEND ) ;
glBlendFunc ( GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA ) ;
break ;
case CCommandBuffer : : BLEND_ADDITIVE :
glEnable ( GL_BLEND ) ;
glBlendFunc ( GL_SRC_ALPHA , GL_ONE ) ;
break ;
default :
dbg_msg ( " render " , " unknown blendmode %d \n " , State . m_BlendMode ) ;
} ;
// clip
if ( State . m_ClipEnable )
{
glScissor ( State . m_ClipX , State . m_ClipY , State . m_ClipW , State . m_ClipH ) ;
glEnable ( GL_SCISSOR_TEST ) ;
}
else
glDisable ( GL_SCISSOR_TEST ) ;
2015-07-09 00:08:14 +00:00
2012-01-03 20:39:10 +00:00
// texture
if ( State . m_Texture > = 0 & & State . m_Texture < CCommandBuffer : : MAX_TEXTURES )
{
glEnable ( GL_TEXTURE_2D ) ;
2012-10-06 21:31:02 +00:00
glBindTexture ( GL_TEXTURE_2D , m_aTextures [ State . m_Texture ] . m_Tex ) ;
2012-01-03 20:39:10 +00:00
}
else
glDisable ( GL_TEXTURE_2D ) ;
2012-01-08 00:47:53 +00:00
switch ( State . m_WrapMode )
{
case CCommandBuffer : : WRAP_REPEAT :
2012-01-08 12:57:40 +00:00
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_S , GL_REPEAT ) ;
2012-01-08 00:47:53 +00:00
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_T , GL_REPEAT ) ;
break ;
case CCommandBuffer : : WRAP_CLAMP :
2012-01-08 12:57:40 +00:00
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_S , GL_CLAMP_TO_EDGE ) ;
2012-01-08 00:47:53 +00:00
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_T , GL_CLAMP_TO_EDGE ) ;
break ;
default :
dbg_msg ( " render " , " unknown wrapmode %d \n " , State . m_WrapMode ) ;
} ;
2012-01-03 20:39:10 +00:00
// screen mapping
glMatrixMode ( GL_PROJECTION ) ;
glLoadIdentity ( ) ;
2017-09-14 06:03:33 +00:00
glOrtho ( State . m_ScreenTL . x , State . m_ScreenBR . x , State . m_ScreenBR . y , State . m_ScreenTL . y , - 10.0f , 10.f ) ;
2012-01-03 20:39:10 +00:00
}
2012-10-06 21:31:02 +00:00
void CCommandProcessorFragment_OpenGL : : Cmd_Init ( const SCommand_Init * pCommand )
{
m_pTextureMemoryUsage = pCommand - > m_pTextureMemoryUsage ;
}
2012-01-03 20:39:10 +00:00
void CCommandProcessorFragment_OpenGL : : Cmd_Texture_Update ( const CCommandBuffer : : SCommand_Texture_Update * pCommand )
{
2012-10-06 21:31:02 +00:00
glBindTexture ( GL_TEXTURE_2D , m_aTextures [ pCommand - > m_Slot ] . m_Tex ) ;
2012-01-03 20:39:10 +00:00
glTexSubImage2D ( GL_TEXTURE_2D , 0 , pCommand - > m_X , pCommand - > m_Y , pCommand - > m_Width , pCommand - > m_Height ,
TexFormatToOpenGLFormat ( pCommand - > m_Format ) , GL_UNSIGNED_BYTE , pCommand - > m_pData ) ;
mem_free ( pCommand - > m_pData ) ;
}
void CCommandProcessorFragment_OpenGL : : Cmd_Texture_Destroy ( const CCommandBuffer : : SCommand_Texture_Destroy * pCommand )
{
2012-10-06 21:31:02 +00:00
glDeleteTextures ( 1 , & m_aTextures [ pCommand - > m_Slot ] . m_Tex ) ;
* m_pTextureMemoryUsage - = m_aTextures [ pCommand - > m_Slot ] . m_MemSize ;
2012-01-03 20:39:10 +00:00
}
void CCommandProcessorFragment_OpenGL : : Cmd_Texture_Create ( const CCommandBuffer : : SCommand_Texture_Create * pCommand )
{
2012-10-07 09:22:49 +00:00
int Width = pCommand - > m_Width ;
int Height = pCommand - > m_Height ;
void * pTexData = pCommand - > m_pData ;
// resample if needed
if ( pCommand - > m_Format = = CCommandBuffer : : TEXFORMAT_RGBA | | pCommand - > m_Format = = CCommandBuffer : : TEXFORMAT_RGB )
{
2014-10-15 13:44:29 +00:00
int MaxTexSize ;
2012-10-07 09:22:49 +00:00
glGetIntegerv ( GL_MAX_TEXTURE_SIZE , & MaxTexSize ) ;
if ( Width > MaxTexSize | | Height > MaxTexSize )
{
do
{
Width > > = 1 ;
Height > > = 1 ;
}
while ( Width > MaxTexSize | | Height > MaxTexSize ) ;
void * pTmpData = Rescale ( pCommand - > m_Width , pCommand - > m_Height , Width , Height , pCommand - > m_Format , static_cast < const unsigned char * > ( pCommand - > m_pData ) ) ;
mem_free ( pTexData ) ;
pTexData = pTmpData ;
}
else if ( Width > 16 & & Height > 16 & & ( pCommand - > m_Flags & CCommandBuffer : : TEXFLAG_QUALITY ) = = 0 )
{
Width > > = 1 ;
Height > > = 1 ;
void * pTmpData = Rescale ( pCommand - > m_Width , pCommand - > m_Height , Width , Height , pCommand - > m_Format , static_cast < const unsigned char * > ( pCommand - > m_pData ) ) ;
mem_free ( pTexData ) ;
pTexData = pTmpData ;
}
}
2012-01-03 20:39:10 +00:00
int Oglformat = TexFormatToOpenGLFormat ( pCommand - > m_Format ) ;
int StoreOglformat = TexFormatToOpenGLFormat ( pCommand - > m_StoreFormat ) ;
2014-06-16 11:29:18 +00:00
# if defined(__ANDROID__)
StoreOglformat = Oglformat ;
# else
2012-08-27 16:58:30 +00:00
if ( pCommand - > m_Flags & CCommandBuffer : : TEXFLAG_COMPRESSED )
{
switch ( StoreOglformat )
{
2012-10-06 11:24:31 +00:00
case GL_RGB : StoreOglformat = GL_COMPRESSED_RGB_ARB ; break ;
case GL_ALPHA : StoreOglformat = GL_COMPRESSED_ALPHA_ARB ; break ;
case GL_RGBA : StoreOglformat = GL_COMPRESSED_RGBA_ARB ; break ;
2012-08-27 16:58:30 +00:00
default : StoreOglformat = GL_COMPRESSED_RGBA_ARB ;
}
}
2014-06-16 11:29:18 +00:00
# endif
2012-10-06 21:31:02 +00:00
glGenTextures ( 1 , & m_aTextures [ pCommand - > m_Slot ] . m_Tex ) ;
glBindTexture ( GL_TEXTURE_2D , m_aTextures [ pCommand - > m_Slot ] . m_Tex ) ;
2012-01-03 20:39:10 +00:00
if ( pCommand - > m_Flags & CCommandBuffer : : TEXFLAG_NOMIPMAPS )
{
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_LINEAR ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_LINEAR ) ;
2012-10-07 09:22:49 +00:00
glTexImage2D ( GL_TEXTURE_2D , 0 , StoreOglformat , Width , Height , 0 , Oglformat , GL_UNSIGNED_BYTE , pTexData ) ;
2012-01-03 20:39:10 +00:00
}
else
{
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_LINEAR ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_LINEAR_MIPMAP_NEAREST ) ;
2012-10-07 09:22:49 +00:00
gluBuild2DMipmaps ( GL_TEXTURE_2D , StoreOglformat , Width , Height , Oglformat , GL_UNSIGNED_BYTE , pTexData ) ;
2012-01-03 20:39:10 +00:00
}
2017-09-02 13:24:07 +00:00
2012-10-06 21:31:02 +00:00
// calculate memory usage
m_aTextures [ pCommand - > m_Slot ] . m_MemSize = Width * Height * pCommand - > m_PixelSize ;
while ( Width > 2 & & Height > 2 )
{
Width > > = 1 ;
Height > > = 1 ;
m_aTextures [ pCommand - > m_Slot ] . m_MemSize + = Width * Height * pCommand - > m_PixelSize ;
}
* m_pTextureMemoryUsage + = m_aTextures [ pCommand - > m_Slot ] . m_MemSize ;
2012-10-07 09:22:49 +00:00
mem_free ( pTexData ) ;
2012-01-03 20:39:10 +00:00
}
void CCommandProcessorFragment_OpenGL : : Cmd_Clear ( const CCommandBuffer : : SCommand_Clear * pCommand )
{
glClearColor ( pCommand - > m_Color . r , pCommand - > m_Color . g , pCommand - > m_Color . b , 0.0f ) ;
glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ;
}
void CCommandProcessorFragment_OpenGL : : Cmd_Render ( const CCommandBuffer : : SCommand_Render * pCommand )
{
SetState ( pCommand - > m_State ) ;
2015-07-09 00:08:14 +00:00
2017-09-27 10:16:34 +00:00
glVertexPointer ( 2 , GL_FLOAT , sizeof ( CCommandBuffer : : SVertexOld ) , ( char * ) pCommand - > m_pVertices ) ;
glTexCoordPointer ( 2 , GL_FLOAT , sizeof ( CCommandBuffer : : SVertexOld ) , ( char * ) pCommand - > m_pVertices + sizeof ( float ) * 2 ) ;
glColorPointer ( 4 , GL_FLOAT , sizeof ( CCommandBuffer : : SVertexOld ) , ( char * ) pCommand - > m_pVertices + sizeof ( float ) * 4 ) ;
2012-01-03 20:39:10 +00:00
glEnableClientState ( GL_VERTEX_ARRAY ) ;
glEnableClientState ( GL_TEXTURE_COORD_ARRAY ) ;
glEnableClientState ( GL_COLOR_ARRAY ) ;
switch ( pCommand - > m_PrimType )
{
case CCommandBuffer : : PRIMTYPE_QUADS :
2015-03-31 11:35:18 +00:00
# if defined(__ANDROID__)
for ( unsigned i = 0 , j = pCommand - > m_PrimCount ; i < j ; i + + )
glDrawArrays ( GL_TRIANGLE_FAN , i * 4 , 4 ) ;
# else
glDrawArrays ( GL_QUADS , 0 , pCommand - > m_PrimCount * 4 ) ;
2014-10-28 01:01:51 +00:00
# endif
2012-01-03 20:39:10 +00:00
break ;
case CCommandBuffer : : PRIMTYPE_LINES :
glDrawArrays ( GL_LINES , 0 , pCommand - > m_PrimCount * 2 ) ;
break ;
2015-03-31 11:35:18 +00:00
case CCommandBuffer : : PRIMTYPE_TRIANGLES :
glDrawArrays ( GL_TRIANGLES , 0 , pCommand - > m_PrimCount * 3 ) ;
break ;
2012-01-03 20:39:10 +00:00
default :
dbg_msg ( " render " , " unknown primtype %d \n " , pCommand - > m_Cmd ) ;
} ;
}
void CCommandProcessorFragment_OpenGL : : Cmd_Screenshot ( const CCommandBuffer : : SCommand_Screenshot * pCommand )
{
// fetch image data
GLint aViewport [ 4 ] = { 0 , 0 , 0 , 0 } ;
glGetIntegerv ( GL_VIEWPORT , aViewport ) ;
int w = aViewport [ 2 ] ;
int h = aViewport [ 3 ] ;
// we allocate one more row to use when we are flipping the texture
unsigned char * pPixelData = ( unsigned char * ) mem_alloc ( w * ( h + 1 ) * 3 , 1 ) ;
unsigned char * pTempRow = pPixelData + w * h * 3 ;
// fetch the pixels
GLint Alignment ;
glGetIntegerv ( GL_PACK_ALIGNMENT , & Alignment ) ;
glPixelStorei ( GL_PACK_ALIGNMENT , 1 ) ;
glReadPixels ( 0 , 0 , w , h , GL_RGB , GL_UNSIGNED_BYTE , pPixelData ) ;
glPixelStorei ( GL_PACK_ALIGNMENT , Alignment ) ;
// flip the pixel because opengl works from bottom left corner
for ( int y = 0 ; y < h / 2 ; y + + )
{
mem_copy ( pTempRow , pPixelData + y * w * 3 , w * 3 ) ;
mem_copy ( pPixelData + y * w * 3 , pPixelData + ( h - y - 1 ) * w * 3 , w * 3 ) ;
mem_copy ( pPixelData + ( h - y - 1 ) * w * 3 , pTempRow , w * 3 ) ;
}
// fill in the information
pCommand - > m_pImage - > m_Width = w ;
pCommand - > m_pImage - > m_Height = h ;
pCommand - > m_pImage - > m_Format = CImageInfo : : FORMAT_RGB ;
pCommand - > m_pImage - > m_pData = pPixelData ;
}
CCommandProcessorFragment_OpenGL : : CCommandProcessorFragment_OpenGL ( )
{
mem_zero ( m_aTextures , sizeof ( m_aTextures ) ) ;
2012-10-06 21:31:02 +00:00
m_pTextureMemoryUsage = 0 ;
2012-01-03 20:39:10 +00:00
}
bool CCommandProcessorFragment_OpenGL : : RunCommand ( const CCommandBuffer : : SCommand * pBaseCommand )
{
switch ( pBaseCommand - > m_Cmd )
{
2012-10-06 21:31:02 +00:00
case CMD_INIT : Cmd_Init ( static_cast < const SCommand_Init * > ( pBaseCommand ) ) ; break ;
2012-01-03 20:39:10 +00:00
case CCommandBuffer : : CMD_TEXTURE_CREATE : Cmd_Texture_Create ( static_cast < const CCommandBuffer : : SCommand_Texture_Create * > ( pBaseCommand ) ) ; break ;
case CCommandBuffer : : CMD_TEXTURE_DESTROY : Cmd_Texture_Destroy ( static_cast < const CCommandBuffer : : SCommand_Texture_Destroy * > ( pBaseCommand ) ) ; break ;
case CCommandBuffer : : CMD_TEXTURE_UPDATE : Cmd_Texture_Update ( static_cast < const CCommandBuffer : : SCommand_Texture_Update * > ( pBaseCommand ) ) ; break ;
case CCommandBuffer : : CMD_CLEAR : Cmd_Clear ( static_cast < const CCommandBuffer : : SCommand_Clear * > ( pBaseCommand ) ) ; break ;
case CCommandBuffer : : CMD_RENDER : Cmd_Render ( static_cast < const CCommandBuffer : : SCommand_Render * > ( pBaseCommand ) ) ; break ;
case CCommandBuffer : : CMD_SCREENSHOT : Cmd_Screenshot ( static_cast < const CCommandBuffer : : SCommand_Screenshot * > ( pBaseCommand ) ) ; break ;
default : return false ;
}
return true ;
}
2017-09-02 13:24:07 +00:00
// ------------ CCommandProcessorFragment_OpenGL3_3
int CCommandProcessorFragment_OpenGL3_3 : : TexFormatToOpenGLFormat ( int TexFormat )
{
if ( TexFormat = = CCommandBuffer : : TEXFORMAT_RGB ) return GL_RGB ;
if ( TexFormat = = CCommandBuffer : : TEXFORMAT_ALPHA ) return GL_RED ;
if ( TexFormat = = CCommandBuffer : : TEXFORMAT_RGBA ) return GL_RGBA ;
return GL_RGBA ;
}
unsigned char CCommandProcessorFragment_OpenGL3_3 : : Sample ( int w , int h , const unsigned char * pData , int u , int v , int Offset , int ScaleW , int ScaleH , int Bpp )
{
int Value = 0 ;
for ( int x = 0 ; x < ScaleW ; x + + )
for ( int y = 0 ; y < ScaleH ; y + + )
Value + = pData [ ( ( v + y ) * w + ( u + x ) ) * Bpp + Offset ] ;
return Value / ( ScaleW * ScaleH ) ;
}
void * CCommandProcessorFragment_OpenGL3_3 : : Rescale ( int Width , int Height , int NewWidth , int NewHeight , int Format , const unsigned char * pData )
{
unsigned char * pTmpData ;
int ScaleW = Width / NewWidth ;
int ScaleH = Height / NewHeight ;
int Bpp = 3 ;
if ( Format = = CCommandBuffer : : TEXFORMAT_RGBA )
Bpp = 4 ;
pTmpData = ( unsigned char * ) mem_alloc ( NewWidth * NewHeight * Bpp , 1 ) ;
int c = 0 ;
for ( int y = 0 ; y < NewHeight ; y + + )
for ( int x = 0 ; x < NewWidth ; x + + , c + + )
{
pTmpData [ c * Bpp ] = Sample ( Width , Height , pData , x * ScaleW , y * ScaleH , 0 , ScaleW , ScaleH , Bpp ) ;
pTmpData [ c * Bpp + 1 ] = Sample ( Width , Height , pData , x * ScaleW , y * ScaleH , 1 , ScaleW , ScaleH , Bpp ) ;
pTmpData [ c * Bpp + 2 ] = Sample ( Width , Height , pData , x * ScaleW , y * ScaleH , 2 , ScaleW , ScaleH , Bpp ) ;
if ( Bpp = = 4 )
pTmpData [ c * Bpp + 3 ] = Sample ( Width , Height , pData , x * ScaleW , y * ScaleH , 3 , ScaleW , ScaleH , Bpp ) ;
}
return pTmpData ;
}
2017-09-12 18:07:38 +00:00
void CCommandProcessorFragment_OpenGL3_3 : : SetState ( const CCommandBuffer : : SState & State , CGLSLTWProgram * pProgram )
2017-09-02 13:24:07 +00:00
{
2017-09-14 00:49:35 +00:00
if ( State . m_BlendMode ! = m_LastBlendMode & & State . m_BlendMode ! = CCommandBuffer : : BLEND_NONE )
2017-09-13 18:33:58 +00:00
{
2017-09-12 18:07:38 +00:00
// blend
switch ( State . m_BlendMode )
{
case CCommandBuffer : : BLEND_NONE :
//we don't really need this anymore
2017-09-14 00:49:35 +00:00
//glDisable(GL_BLEND);
2017-09-12 18:07:38 +00:00
break ;
case CCommandBuffer : : BLEND_ALPHA :
glEnable ( GL_BLEND ) ;
glBlendFunc ( GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA ) ;
break ;
case CCommandBuffer : : BLEND_ADDITIVE :
glEnable ( GL_BLEND ) ;
glBlendFunc ( GL_SRC_ALPHA , GL_ONE ) ;
break ;
default :
dbg_msg ( " render " , " unknown blendmode %d \n " , State . m_BlendMode ) ;
} ;
m_LastBlendMode = State . m_BlendMode ;
}
2017-09-02 13:24:07 +00:00
// clip
if ( State . m_ClipEnable )
{
glScissor ( State . m_ClipX , State . m_ClipY , State . m_ClipW , State . m_ClipH ) ;
glEnable ( GL_SCISSOR_TEST ) ;
2017-09-12 18:07:38 +00:00
m_LastClipEnable = true ;
2017-09-02 13:24:07 +00:00
}
2017-09-13 18:33:58 +00:00
else if ( m_LastClipEnable )
{
2017-09-12 18:07:38 +00:00
//dont disable it always
2017-09-02 13:24:07 +00:00
glDisable ( GL_SCISSOR_TEST ) ;
2017-09-12 18:07:38 +00:00
m_LastClipEnable = false ;
}
2017-09-02 13:24:07 +00:00
// texture
if ( State . m_Texture > = 0 & & State . m_Texture < CCommandBuffer : : MAX_TEXTURES )
{
2017-09-12 18:07:38 +00:00
int Slot = State . m_Texture % m_MaxTextureUnits ;
2017-09-14 00:58:13 +00:00
if ( m_UseMultipleTextureUnits )
2017-09-13 18:33:58 +00:00
{
2017-09-14 00:49:35 +00:00
if ( ! IsAndUpdateTextureSlotBound ( Slot , State . m_Texture ) )
{
glActiveTexture ( GL_TEXTURE0 + Slot ) ;
glBindTexture ( GL_TEXTURE_2D , m_aTextures [ State . m_Texture ] . m_Tex ) ;
glBindSampler ( Slot , m_aTextures [ State . m_Texture ] . m_Sampler ) ;
}
2017-09-27 12:52:06 +00:00
} else
{
2017-09-14 00:49:35 +00:00
Slot = 0 ;
2017-09-12 18:07:38 +00:00
glBindTexture ( GL_TEXTURE_2D , m_aTextures [ State . m_Texture ] . m_Tex ) ;
glBindSampler ( Slot , m_aTextures [ State . m_Texture ] . m_Sampler ) ;
}
if ( pProgram - > m_LocIsTextured ! = - 1 ) pProgram - > SetUniform ( pProgram - > m_LocIsTextured , ( int ) 1 ) ;
pProgram - > SetUniform ( pProgram - > m_LocTextureSampler , ( int ) Slot ) ;
2017-09-02 13:24:07 +00:00
2017-10-09 13:59:16 +00:00
if ( m_aTextures [ State . m_Texture ] . m_LastWrapMode ! = State . m_WrapMode )
2017-09-13 18:33:58 +00:00
{
2017-09-12 18:07:38 +00:00
switch ( State . m_WrapMode )
{
case CCommandBuffer : : WRAP_REPEAT :
glSamplerParameteri ( m_aTextures [ State . m_Texture ] . m_Sampler , GL_TEXTURE_WRAP_S , GL_REPEAT ) ;
glSamplerParameteri ( m_aTextures [ State . m_Texture ] . m_Sampler , GL_TEXTURE_WRAP_T , GL_REPEAT ) ;
break ;
case CCommandBuffer : : WRAP_CLAMP :
glSamplerParameteri ( m_aTextures [ State . m_Texture ] . m_Sampler , GL_TEXTURE_WRAP_S , GL_CLAMP_TO_EDGE ) ;
glSamplerParameteri ( m_aTextures [ State . m_Texture ] . m_Sampler , GL_TEXTURE_WRAP_T , GL_CLAMP_TO_EDGE ) ;
break ;
default :
dbg_msg ( " render " , " unknown wrapmode %d \n " , State . m_WrapMode ) ;
} ;
2017-10-09 13:59:16 +00:00
m_aTextures [ State . m_Texture ] . m_LastWrapMode = State . m_WrapMode ;
2017-09-12 18:07:38 +00:00
}
2017-09-02 13:24:07 +00:00
}
2017-09-27 12:52:06 +00:00
else
{
2017-09-12 18:07:38 +00:00
if ( pProgram - > m_LocIsTextured ! = - 1 ) pProgram - > SetUniform ( pProgram - > m_LocIsTextured , ( int ) 0 ) ;
2017-09-02 13:24:07 +00:00
}
// screen mapping
2017-09-14 17:47:04 +00:00
//orthographic projection matrix
2017-09-27 10:15:30 +00:00
//if we use the same z coordinate for every vertex, we can just ignore the z coordinate and set it in the shaders
2017-09-02 13:24:07 +00:00
2017-09-27 10:15:30 +00:00
float m [ 2 * 4 ] = {
2017-09-14 17:47:04 +00:00
2.f / ( State . m_ScreenBR . x - State . m_ScreenTL . x ) , 0 , 0 , - ( ( State . m_ScreenBR . x + State . m_ScreenTL . x ) / ( State . m_ScreenBR . x - State . m_ScreenTL . x ) ) ,
0 , ( 2.f / ( State . m_ScreenTL . y - State . m_ScreenBR . y ) ) , 0 , - ( ( State . m_ScreenTL . y + State . m_ScreenBR . y ) / ( State . m_ScreenTL . y - State . m_ScreenBR . y ) ) ,
2017-09-27 10:15:30 +00:00
//0, 0, -(2.f/(9.f)), -((11.f)/(9.f)),
//0, 0, 0, 1.0f
2017-09-02 13:24:07 +00:00
} ;
2017-09-12 18:07:38 +00:00
//transpose bcs of column-major order of opengl
2017-09-27 10:15:30 +00:00
glUniformMatrix4x2fv ( pProgram - > m_LocPos , 1 , true , ( float * ) & m ) ;
2017-09-02 13:24:07 +00:00
}
void CCommandProcessorFragment_OpenGL3_3 : : Cmd_Init ( const SCommand_Init * pCommand )
{
2017-09-14 00:58:13 +00:00
m_UseMultipleTextureUnits = g_Config . m_GfxEnableTextureUnitOptimization ;
if ( ! m_UseMultipleTextureUnits )
2017-09-14 00:49:35 +00:00
{
glActiveTexture ( GL_TEXTURE0 ) ;
}
2017-09-02 13:24:07 +00:00
m_pTextureMemoryUsage = pCommand - > m_pTextureMemoryUsage ;
2017-09-12 18:07:38 +00:00
m_LastBlendMode = - 1 ;
m_LastClipEnable = false ;
2017-09-13 18:33:58 +00:00
m_pPrimitiveProgram = new CGLSLPrimitiveProgram ;
m_pTileProgram = new CGLSLTileProgram ;
m_pTileProgramTextured = new CGLSLTileProgram ;
m_pBorderTileProgram = new CGLSLBorderTileProgram ;
m_pBorderTileProgramTextured = new CGLSLBorderTileProgram ;
m_pBorderTileLineProgram = new CGLSLBorderTileLineProgram ;
m_pBorderTileLineProgramTextured = new CGLSLBorderTileLineProgram ;
2017-09-02 13:24:07 +00:00
2017-09-12 18:07:38 +00:00
{
CGLSL PrimitiveVertexShader ;
CGLSL PrimitiveFragmentShader ;
PrimitiveVertexShader . LoadShader ( " ./shader/prim.vert " , GL_VERTEX_SHADER ) ;
PrimitiveFragmentShader . LoadShader ( " ./shader/prim.frag " , GL_FRAGMENT_SHADER ) ;
2017-09-13 18:33:58 +00:00
m_pPrimitiveProgram - > CreateProgram ( ) ;
m_pPrimitiveProgram - > AddShader ( & PrimitiveVertexShader ) ;
m_pPrimitiveProgram - > AddShader ( & PrimitiveFragmentShader ) ;
m_pPrimitiveProgram - > LinkProgram ( ) ;
2017-09-12 18:07:38 +00:00
2017-09-13 18:33:58 +00:00
m_pPrimitiveProgram - > UseProgram ( ) ;
2017-09-12 18:07:38 +00:00
2017-09-13 18:33:58 +00:00
m_pPrimitiveProgram - > m_LocPos = m_pPrimitiveProgram - > GetUniformLoc ( " Pos " ) ;
m_pPrimitiveProgram - > m_LocIsTextured = m_pPrimitiveProgram - > GetUniformLoc ( " isTextured " ) ;
m_pPrimitiveProgram - > m_LocTextureSampler = m_pPrimitiveProgram - > GetUniformLoc ( " textureSampler " ) ;
2017-09-12 18:07:38 +00:00
}
{
CGLSL VertexShader ;
CGLSL FragmentShader ;
VertexShader . LoadShader ( " ./shader/tile.vert " , GL_VERTEX_SHADER ) ;
FragmentShader . LoadShader ( " ./shader/tile.frag " , GL_FRAGMENT_SHADER ) ;
2017-09-13 18:33:58 +00:00
m_pTileProgram - > CreateProgram ( ) ;
m_pTileProgram - > AddShader ( & VertexShader ) ;
m_pTileProgram - > AddShader ( & FragmentShader ) ;
m_pTileProgram - > LinkProgram ( ) ;
2017-09-12 18:07:38 +00:00
2017-09-13 18:33:58 +00:00
m_pTileProgram - > UseProgram ( ) ;
2017-09-12 18:07:38 +00:00
2017-09-13 18:33:58 +00:00
m_pTileProgram - > m_LocPos = m_pTileProgram - > GetUniformLoc ( " Pos " ) ;
m_pTileProgram - > m_LocIsTextured = - 1 ;
m_pTileProgram - > m_LocTextureSampler = - 1 ;
m_pTileProgram - > m_LocColor = m_pTileProgram - > GetUniformLoc ( " vertColor " ) ;
2017-10-09 16:58:44 +00:00
m_pTileProgram - > m_LocLOD = - 1 ;
2017-09-12 18:07:38 +00:00
}
{
CGLSL VertexShader ;
CGLSL FragmentShader ;
VertexShader . LoadShader ( " ./shader/tiletex.vert " , GL_VERTEX_SHADER ) ;
FragmentShader . LoadShader ( " ./shader/tiletex.frag " , GL_FRAGMENT_SHADER ) ;
2017-09-13 18:33:58 +00:00
m_pTileProgramTextured - > CreateProgram ( ) ;
m_pTileProgramTextured - > AddShader ( & VertexShader ) ;
m_pTileProgramTextured - > AddShader ( & FragmentShader ) ;
m_pTileProgramTextured - > LinkProgram ( ) ;
2017-09-12 18:07:38 +00:00
2017-09-13 18:33:58 +00:00
m_pTileProgramTextured - > UseProgram ( ) ;
2017-09-12 18:07:38 +00:00
2017-09-13 18:33:58 +00:00
m_pTileProgramTextured - > m_LocPos = m_pTileProgramTextured - > GetUniformLoc ( " Pos " ) ;
m_pTileProgramTextured - > m_LocIsTextured = - 1 ;
m_pTileProgramTextured - > m_LocTextureSampler = m_pTileProgramTextured - > GetUniformLoc ( " textureSampler " ) ;
m_pTileProgramTextured - > m_LocColor = m_pTileProgramTextured - > GetUniformLoc ( " vertColor " ) ;
2017-10-09 16:58:44 +00:00
m_pTileProgramTextured - > m_LocLOD = m_pTileProgramTextured - > GetUniformLoc ( " LOD " ) ;
2017-09-12 18:07:38 +00:00
}
{
CGLSL VertexShader ;
CGLSL FragmentShader ;
VertexShader . LoadShader ( " ./shader/bordertile.vert " , GL_VERTEX_SHADER ) ;
FragmentShader . LoadShader ( " ./shader/bordertile.frag " , GL_FRAGMENT_SHADER ) ;
2017-09-13 18:33:58 +00:00
m_pBorderTileProgram - > CreateProgram ( ) ;
m_pBorderTileProgram - > AddShader ( & VertexShader ) ;
m_pBorderTileProgram - > AddShader ( & FragmentShader ) ;
m_pBorderTileProgram - > LinkProgram ( ) ;
2017-09-12 18:07:38 +00:00
2017-09-13 18:33:58 +00:00
m_pBorderTileProgram - > UseProgram ( ) ;
2017-09-12 18:07:38 +00:00
2017-09-13 18:33:58 +00:00
m_pBorderTileProgram - > m_LocPos = m_pBorderTileProgram - > GetUniformLoc ( " Pos " ) ;
m_pBorderTileProgram - > m_LocIsTextured = - 1 ;
m_pBorderTileProgram - > m_LocTextureSampler = - 1 ;
m_pBorderTileProgram - > m_LocColor = m_pBorderTileProgram - > GetUniformLoc ( " vertColor " ) ;
2017-10-09 16:58:44 +00:00
m_pBorderTileProgram - > m_LocLOD = - 1 ;
2017-09-13 18:33:58 +00:00
m_pBorderTileProgram - > m_LocOffset = m_pBorderTileProgram - > GetUniformLoc ( " Offset " ) ;
m_pBorderTileProgram - > m_LocDir = m_pBorderTileProgram - > GetUniformLoc ( " Dir " ) ;
m_pBorderTileProgram - > m_LocJumpIndex = m_pBorderTileProgram - > GetUniformLoc ( " JumpIndex " ) ;
2017-09-12 18:07:38 +00:00
}
{
CGLSL VertexShader ;
CGLSL FragmentShader ;
VertexShader . LoadShader ( " ./shader/bordertiletex.vert " , GL_VERTEX_SHADER ) ;
FragmentShader . LoadShader ( " ./shader/bordertiletex.frag " , GL_FRAGMENT_SHADER ) ;
2017-09-13 18:33:58 +00:00
m_pBorderTileProgramTextured - > CreateProgram ( ) ;
m_pBorderTileProgramTextured - > AddShader ( & VertexShader ) ;
m_pBorderTileProgramTextured - > AddShader ( & FragmentShader ) ;
m_pBorderTileProgramTextured - > LinkProgram ( ) ;
2017-09-12 18:07:38 +00:00
2017-09-13 18:33:58 +00:00
m_pBorderTileProgramTextured - > UseProgram ( ) ;
2017-09-12 18:07:38 +00:00
2017-09-13 18:33:58 +00:00
m_pBorderTileProgramTextured - > m_LocPos = m_pBorderTileProgramTextured - > GetUniformLoc ( " Pos " ) ;
m_pBorderTileProgramTextured - > m_LocIsTextured = - 1 ;
m_pBorderTileProgramTextured - > m_LocTextureSampler = m_pBorderTileProgramTextured - > GetUniformLoc ( " textureSampler " ) ;
m_pBorderTileProgramTextured - > m_LocColor = m_pBorderTileProgramTextured - > GetUniformLoc ( " vertColor " ) ;
2017-10-09 16:58:44 +00:00
m_pBorderTileProgramTextured - > m_LocLOD = m_pBorderTileProgramTextured - > GetUniformLoc ( " LOD " ) ;
2017-09-13 18:33:58 +00:00
m_pBorderTileProgramTextured - > m_LocOffset = m_pBorderTileProgramTextured - > GetUniformLoc ( " Offset " ) ;
m_pBorderTileProgramTextured - > m_LocDir = m_pBorderTileProgramTextured - > GetUniformLoc ( " Dir " ) ;
m_pBorderTileProgramTextured - > m_LocJumpIndex = m_pBorderTileProgramTextured - > GetUniformLoc ( " JumpIndex " ) ;
2017-09-12 18:07:38 +00:00
}
{
CGLSL VertexShader ;
CGLSL FragmentShader ;
VertexShader . LoadShader ( " ./shader/bordertileline.vert " , GL_VERTEX_SHADER ) ;
FragmentShader . LoadShader ( " ./shader/bordertileline.frag " , GL_FRAGMENT_SHADER ) ;
2017-09-13 18:33:58 +00:00
m_pBorderTileLineProgram - > CreateProgram ( ) ;
m_pBorderTileLineProgram - > AddShader ( & VertexShader ) ;
m_pBorderTileLineProgram - > AddShader ( & FragmentShader ) ;
m_pBorderTileLineProgram - > LinkProgram ( ) ;
2017-09-12 18:07:38 +00:00
2017-09-13 18:33:58 +00:00
m_pBorderTileLineProgram - > UseProgram ( ) ;
2017-09-12 18:07:38 +00:00
2017-09-13 18:33:58 +00:00
m_pBorderTileLineProgram - > m_LocPos = m_pBorderTileLineProgram - > GetUniformLoc ( " Pos " ) ;
m_pBorderTileLineProgram - > m_LocIsTextured = - 1 ;
m_pBorderTileLineProgram - > m_LocTextureSampler = - 1 ;
m_pBorderTileLineProgram - > m_LocColor = m_pBorderTileLineProgram - > GetUniformLoc ( " vertColor " ) ;
2017-10-09 16:58:44 +00:00
m_pBorderTileLineProgram - > m_LocLOD = - 1 ;
2017-09-13 18:33:58 +00:00
m_pBorderTileLineProgram - > m_LocDir = m_pBorderTileLineProgram - > GetUniformLoc ( " Dir " ) ;
2017-09-12 18:07:38 +00:00
}
{
CGLSL VertexShader ;
CGLSL FragmentShader ;
VertexShader . LoadShader ( " ./shader/bordertilelinetex.vert " , GL_VERTEX_SHADER ) ;
FragmentShader . LoadShader ( " ./shader/bordertilelinetex.frag " , GL_FRAGMENT_SHADER ) ;
2017-09-13 18:33:58 +00:00
m_pBorderTileLineProgramTextured - > CreateProgram ( ) ;
m_pBorderTileLineProgramTextured - > AddShader ( & VertexShader ) ;
m_pBorderTileLineProgramTextured - > AddShader ( & FragmentShader ) ;
m_pBorderTileLineProgramTextured - > LinkProgram ( ) ;
2017-09-12 18:07:38 +00:00
2017-09-13 18:33:58 +00:00
m_pBorderTileLineProgramTextured - > UseProgram ( ) ;
2017-09-12 18:07:38 +00:00
2017-09-13 18:33:58 +00:00
m_pBorderTileLineProgramTextured - > m_LocPos = m_pBorderTileLineProgramTextured - > GetUniformLoc ( " Pos " ) ;
m_pBorderTileLineProgramTextured - > m_LocIsTextured = - 1 ;
m_pBorderTileLineProgramTextured - > m_LocTextureSampler = m_pBorderTileLineProgramTextured - > GetUniformLoc ( " textureSampler " ) ;
m_pBorderTileLineProgramTextured - > m_LocColor = m_pBorderTileLineProgramTextured - > GetUniformLoc ( " vertColor " ) ;
2017-10-09 16:58:44 +00:00
m_pBorderTileLineProgramTextured - > m_LocLOD = m_pBorderTileLineProgramTextured - > GetUniformLoc ( " LOD " ) ;
2017-09-13 18:33:58 +00:00
m_pBorderTileLineProgramTextured - > m_LocDir = m_pBorderTileLineProgramTextured - > GetUniformLoc ( " Dir " ) ;
2017-09-12 18:07:38 +00:00
}
2017-09-02 13:24:07 +00:00
2017-09-13 18:33:58 +00:00
glGenBuffers ( 1 , & m_PrimitiveDrawBufferID ) ;
glGenVertexArrays ( 1 , & m_PrimitiveDrawVertexID ) ;
2017-09-27 10:16:34 +00:00
glBindBuffer ( GL_ARRAY_BUFFER , m_PrimitiveDrawBufferID ) ;
2017-09-13 18:33:58 +00:00
glBindVertexArray ( m_PrimitiveDrawVertexID ) ;
2017-09-02 13:24:07 +00:00
glEnableVertexAttribArray ( 0 ) ;
glEnableVertexAttribArray ( 1 ) ;
glEnableVertexAttribArray ( 2 ) ;
2017-09-12 18:07:38 +00:00
2017-09-27 10:16:34 +00:00
glVertexAttribPointer ( 0 , 2 , GL_FLOAT , GL_FALSE , sizeof ( CCommandBuffer : : SVertex ) , 0 ) ;
glVertexAttribPointer ( 1 , 2 , GL_FLOAT , GL_FALSE , sizeof ( CCommandBuffer : : SVertex ) , ( void * ) ( sizeof ( float ) * 2 ) ) ;
glVertexAttribPointer ( 2 , 4 , GL_UNSIGNED_BYTE , GL_TRUE , sizeof ( CCommandBuffer : : SVertex ) , ( void * ) ( sizeof ( float ) * 4 ) ) ;
m_UsePreinitializedVertexBuffer = g_Config . m_GfxUsePreinitBuffer ;
if ( m_UsePreinitializedVertexBuffer )
glBufferData ( GL_ARRAY_BUFFER , sizeof ( CCommandBuffer : : SVertex ) * CCommandBuffer : : MAX_VERTICES , NULL , GL_STREAM_DRAW ) ;
2017-09-12 18:07:38 +00:00
//query maximum of allowed textures
glGetIntegerv ( GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS , & m_MaxTextureUnits ) ;
m_TextureSlotBoundToUnit . resize ( m_MaxTextureUnits ) ;
2017-09-13 18:33:58 +00:00
for ( int i = 0 ; i < m_MaxTextureUnits ; + + i )
{
2017-09-12 18:07:38 +00:00
m_TextureSlotBoundToUnit [ i ] . m_TextureSlot = - 1 ;
}
2017-11-03 18:48:17 +00:00
glBindVertexArray ( 0 ) ;
2017-09-27 10:16:34 +00:00
glGenBuffers ( 1 , & m_QuadDrawIndexBufferID ) ;
glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER , m_QuadDrawIndexBufferID ) ;
2017-11-03 18:33:23 +00:00
m_LastIndexBufferBound = 0 ;
2017-09-14 00:49:35 +00:00
unsigned int Indices [ CCommandBuffer : : MAX_VERTICES / 4 * 6 ] ;
int Primq = 0 ;
for ( int i = 0 ; i < CCommandBuffer : : MAX_VERTICES / 4 * 6 ; i + = 6 )
{
Indices [ i ] = Primq ;
2017-09-27 10:16:34 +00:00
Indices [ i + 1 ] = Primq + 1 ;
Indices [ i + 2 ] = Primq + 2 ;
Indices [ i + 3 ] = Primq ;
Indices [ i + 4 ] = Primq + 2 ;
Indices [ i + 5 ] = Primq + 3 ;
2017-09-14 00:49:35 +00:00
Primq + = 4 ;
}
glBufferData ( GL_ELEMENT_ARRAY_BUFFER , sizeof ( unsigned int ) * CCommandBuffer : : MAX_VERTICES / 4 * 6 , Indices , GL_STATIC_DRAW ) ;
2017-09-27 10:16:34 +00:00
m_CurrentIndicesInBuffer = CCommandBuffer : : MAX_VERTICES / 4 * 6 ;
2017-09-12 18:07:38 +00:00
mem_zero ( m_aTextures , sizeof ( m_aTextures ) ) ;
2017-09-27 10:16:34 +00:00
m_ClearColor . r = m_ClearColor . g = m_ClearColor . b = - 1.f ;
2017-09-02 13:24:07 +00:00
}
void CCommandProcessorFragment_OpenGL3_3 : : Cmd_Shutdown ( const SCommand_Shutdown * pCommand )
{
2017-09-14 17:34:14 +00:00
//clean up everything
2017-09-13 18:33:58 +00:00
delete m_pPrimitiveProgram ;
2017-09-12 18:07:38 +00:00
//delete m_QuadProgram;
2017-09-13 18:33:58 +00:00
delete m_pTileProgram ;
delete m_pTileProgramTextured ;
delete m_pBorderTileProgram ;
delete m_pBorderTileProgramTextured ;
delete m_pBorderTileLineProgram ;
delete m_pBorderTileLineProgramTextured ;
2017-09-02 13:24:07 +00:00
glBindVertexArray ( 0 ) ;
2017-09-13 18:33:58 +00:00
glDeleteBuffers ( 1 , & m_PrimitiveDrawBufferID ) ;
2017-09-27 10:16:34 +00:00
glDeleteBuffers ( 1 , & m_QuadDrawIndexBufferID ) ;
2017-09-13 18:33:58 +00:00
glDeleteVertexArrays ( 1 , & m_PrimitiveDrawVertexID ) ;
2017-09-12 18:07:38 +00:00
2017-09-13 18:33:58 +00:00
for ( int i = 0 ; i < CCommandBuffer : : MAX_TEXTURES ; + + i )
{
2017-09-12 18:07:38 +00:00
DestroyTexture ( i ) ;
}
2017-09-27 12:52:06 +00:00
for ( size_t i = 0 ; i < m_VisualObjects . size ( ) ; + + i )
2017-09-13 18:33:58 +00:00
{
2017-09-12 18:07:38 +00:00
DestroyVisualObjects ( i ) ;
}
m_VisualObjects . clear ( ) ;
2017-09-02 13:24:07 +00:00
}
void CCommandProcessorFragment_OpenGL3_3 : : Cmd_Texture_Update ( const CCommandBuffer : : SCommand_Texture_Update * pCommand )
{
2017-09-14 00:58:13 +00:00
if ( m_UseMultipleTextureUnits )
2017-09-14 00:49:35 +00:00
{
int Slot = pCommand - > m_Slot % m_MaxTextureUnits ;
//just tell, that we using this texture now
IsAndUpdateTextureSlotBound ( Slot , pCommand - > m_Slot ) ;
glActiveTexture ( GL_TEXTURE0 + Slot ) ;
2017-09-27 10:16:34 +00:00
glBindSampler ( Slot , m_aTextures [ pCommand - > m_Slot ] . m_Sampler ) ;
2017-09-14 00:49:35 +00:00
}
2017-09-15 01:01:26 +00:00
//fix the alignment to allow even 1byte changes, e.g. for alpha components
glPixelStorei ( GL_UNPACK_ALIGNMENT , 1 ) ;
2017-09-02 13:24:07 +00:00
glBindTexture ( GL_TEXTURE_2D , m_aTextures [ pCommand - > m_Slot ] . m_Tex ) ;
glTexSubImage2D ( GL_TEXTURE_2D , 0 , pCommand - > m_X , pCommand - > m_Y , pCommand - > m_Width , pCommand - > m_Height ,
TexFormatToOpenGLFormat ( pCommand - > m_Format ) , GL_UNSIGNED_BYTE , pCommand - > m_pData ) ;
mem_free ( pCommand - > m_pData ) ;
}
void CCommandProcessorFragment_OpenGL3_3 : : Cmd_Texture_Destroy ( const CCommandBuffer : : SCommand_Texture_Destroy * pCommand )
{
2017-09-14 00:49:35 +00:00
int Slot = 0 ;
2017-09-14 00:58:13 +00:00
if ( m_UseMultipleTextureUnits )
2017-09-14 00:49:35 +00:00
{
Slot = pCommand - > m_Slot % m_MaxTextureUnits ;
IsAndUpdateTextureSlotBound ( Slot , pCommand - > m_Slot ) ;
glActiveTexture ( GL_TEXTURE0 + Slot ) ;
}
2017-09-12 18:07:38 +00:00
glBindTexture ( GL_TEXTURE_2D , 0 ) ;
glBindSampler ( Slot , 0 ) ;
m_TextureSlotBoundToUnit [ Slot ] . m_TextureSlot = - 1 ;
DestroyTexture ( pCommand - > m_Slot ) ;
2017-09-02 13:24:07 +00:00
}
void CCommandProcessorFragment_OpenGL3_3 : : Cmd_Texture_Create ( const CCommandBuffer : : SCommand_Texture_Create * pCommand )
{
int Width = pCommand - > m_Width ;
int Height = pCommand - > m_Height ;
void * pTexData = pCommand - > m_pData ;
// resample if needed
if ( pCommand - > m_Format = = CCommandBuffer : : TEXFORMAT_RGBA | | pCommand - > m_Format = = CCommandBuffer : : TEXFORMAT_RGB )
{
int MaxTexSize ;
glGetIntegerv ( GL_MAX_TEXTURE_SIZE , & MaxTexSize ) ;
if ( Width > MaxTexSize | | Height > MaxTexSize )
{
do
{
Width > > = 1 ;
Height > > = 1 ;
}
while ( Width > MaxTexSize | | Height > MaxTexSize ) ;
void * pTmpData = Rescale ( pCommand - > m_Width , pCommand - > m_Height , Width , Height , pCommand - > m_Format , static_cast < const unsigned char * > ( pCommand - > m_pData ) ) ;
mem_free ( pTexData ) ;
pTexData = pTmpData ;
}
else if ( Width > 16 & & Height > 16 & & ( pCommand - > m_Flags & CCommandBuffer : : TEXFLAG_QUALITY ) = = 0 )
{
Width > > = 1 ;
Height > > = 1 ;
void * pTmpData = Rescale ( pCommand - > m_Width , pCommand - > m_Height , Width , Height , pCommand - > m_Format , static_cast < const unsigned char * > ( pCommand - > m_pData ) ) ;
mem_free ( pTexData ) ;
pTexData = pTmpData ;
}
}
int Oglformat = TexFormatToOpenGLFormat ( pCommand - > m_Format ) ;
int StoreOglformat = TexFormatToOpenGLFormat ( pCommand - > m_StoreFormat ) ;
# if defined(__ANDROID__)
StoreOglformat = Oglformat ;
# else
if ( pCommand - > m_Flags & CCommandBuffer : : TEXFLAG_COMPRESSED )
{
switch ( StoreOglformat )
{
case GL_RGB : StoreOglformat = GL_COMPRESSED_RGB ; break ;
2017-09-12 18:07:38 +00:00
//this needs further checks. it seems on some gpus COMPRESSED_ALPHA isnt in the core profile
case GL_RED : StoreOglformat = GL_COMPRESSED_RGBA ; break ;
2017-09-02 13:24:07 +00:00
case GL_RGBA : StoreOglformat = GL_COMPRESSED_RGBA ; break ;
default : StoreOglformat = GL_COMPRESSED_RGBA ;
}
}
# endif
2017-09-14 00:49:35 +00:00
int Slot = 0 ;
2017-09-14 00:58:13 +00:00
if ( m_UseMultipleTextureUnits )
2017-09-14 00:49:35 +00:00
{
Slot = pCommand - > m_Slot % m_MaxTextureUnits ;
//just tell, that we using this texture now
IsAndUpdateTextureSlotBound ( Slot , pCommand - > m_Slot ) ;
glActiveTexture ( GL_TEXTURE0 + Slot ) ;
}
2017-09-02 13:24:07 +00:00
glGenTextures ( 1 , & m_aTextures [ pCommand - > m_Slot ] . m_Tex ) ;
glBindTexture ( GL_TEXTURE_2D , m_aTextures [ pCommand - > m_Slot ] . m_Tex ) ;
glGenSamplers ( 1 , & m_aTextures [ pCommand - > m_Slot ] . m_Sampler ) ;
2017-09-12 18:07:38 +00:00
glBindSampler ( Slot , m_aTextures [ pCommand - > m_Slot ] . m_Sampler ) ;
2017-09-02 13:24:07 +00:00
2017-09-13 18:33:58 +00:00
if ( Oglformat = = GL_RED )
{
2017-09-02 13:24:07 +00:00
//Bind the texture 2D.
GLint swizzleMask [ ] = { GL_ONE , GL_ONE , GL_ONE , GL_RED } ;
glTexParameteriv ( GL_TEXTURE_2D , GL_TEXTURE_SWIZZLE_RGBA , swizzleMask ) ;
2017-09-13 16:32:08 +00:00
StoreOglformat = GL_RGBA ;
2017-09-02 13:24:07 +00:00
}
if ( pCommand - > m_Flags & CCommandBuffer : : TEXFLAG_NOMIPMAPS )
{
2017-11-03 18:33:23 +00:00
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_LINEAR ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_LINEAR ) ;
2017-09-02 13:24:07 +00:00
glSamplerParameteri ( m_aTextures [ pCommand - > m_Slot ] . m_Sampler , GL_TEXTURE_MAG_FILTER , GL_LINEAR ) ;
glSamplerParameteri ( m_aTextures [ pCommand - > m_Slot ] . m_Sampler , GL_TEXTURE_MIN_FILTER , GL_LINEAR ) ;
glTexImage2D ( GL_TEXTURE_2D , 0 , StoreOglformat , Width , Height , 0 , Oglformat , GL_UNSIGNED_BYTE , pTexData ) ;
}
else
{
glSamplerParameteri ( m_aTextures [ pCommand - > m_Slot ] . m_Sampler , GL_TEXTURE_MAG_FILTER , GL_LINEAR ) ;
glSamplerParameteri ( m_aTextures [ pCommand - > m_Slot ] . m_Sampler , GL_TEXTURE_MIN_FILTER , GL_LINEAR_MIPMAP_NEAREST ) ;
2017-10-09 16:58:44 +00:00
//prevent mipmap display bugs, when zooming out far
if ( Width > = 1024 & & Height > = 1024 )
{
2017-10-14 21:27:14 +00:00
glTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_MAX_LEVEL , 5.f ) ;
2017-10-09 16:58:44 +00:00
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAX_LOD , 5 ) ;
}
glTexImage2D ( GL_TEXTURE_2D , 0 , StoreOglformat , Width , Height , 0 , Oglformat , GL_UNSIGNED_BYTE , pTexData ) ;
glGenerateMipmap ( GL_TEXTURE_2D ) ;
2017-09-02 13:24:07 +00:00
}
2017-10-09 13:59:16 +00:00
//this is the initial value for the wrap modes
m_aTextures [ pCommand - > m_Slot ] . m_LastWrapMode = CCommandBuffer : : WRAP_REPEAT ;
2017-09-02 13:24:07 +00:00
// calculate memory usage
m_aTextures [ pCommand - > m_Slot ] . m_MemSize = Width * Height * pCommand - > m_PixelSize ;
while ( Width > 2 & & Height > 2 )
{
Width > > = 1 ;
Height > > = 1 ;
m_aTextures [ pCommand - > m_Slot ] . m_MemSize + = Width * Height * pCommand - > m_PixelSize ;
}
* m_pTextureMemoryUsage + = m_aTextures [ pCommand - > m_Slot ] . m_MemSize ;
mem_free ( pTexData ) ;
}
void CCommandProcessorFragment_OpenGL3_3 : : Cmd_Clear ( const CCommandBuffer : : SCommand_Clear * pCommand )
{
2017-09-27 10:16:34 +00:00
if ( pCommand - > m_Color . r ! = m_ClearColor . r | | pCommand - > m_Color . g ! = m_ClearColor . g | | pCommand - > m_Color . b ! = m_ClearColor . b )
{
glClearColor ( pCommand - > m_Color . r , pCommand - > m_Color . g , pCommand - > m_Color . b , 0.0f ) ;
m_ClearColor = pCommand - > m_Color ;
}
glClear ( GL_COLOR_BUFFER_BIT ) ;
2017-09-02 13:24:07 +00:00
}
void CCommandProcessorFragment_OpenGL3_3 : : Cmd_Render ( const CCommandBuffer : : SCommand_Render * pCommand )
{
2017-09-13 18:33:58 +00:00
m_pPrimitiveProgram - > UseProgram ( ) ;
SetState ( pCommand - > m_State , m_pPrimitiveProgram ) ;
2017-09-02 13:24:07 +00:00
int Count = 0 ;
switch ( pCommand - > m_PrimType )
{
case CCommandBuffer : : PRIMTYPE_LINES :
Count = pCommand - > m_PrimCount * 2 ;
break ;
2017-09-14 00:49:35 +00:00
case CCommandBuffer : : PRIMTYPE_QUADS :
Count = pCommand - > m_PrimCount * 4 ;
2017-09-02 13:24:07 +00:00
break ;
2017-09-12 18:07:38 +00:00
default :
return ;
2017-09-02 13:24:07 +00:00
} ;
2017-09-27 10:16:34 +00:00
2017-09-14 00:49:35 +00:00
glBindBuffer ( GL_ARRAY_BUFFER , m_PrimitiveDrawBufferID ) ;
2017-09-27 10:16:34 +00:00
if ( ! m_UsePreinitializedVertexBuffer )
glBufferData ( GL_ARRAY_BUFFER , sizeof ( CCommandBuffer : : SVertex ) * Count , ( char * ) pCommand - > m_pVertices , GL_STREAM_DRAW ) ;
else
{
//this is better for some iGPUs. Probably due to not initializing a new buffer in the system memory again and again...(driver dependend)
void * pData = glMapBufferRange ( GL_ARRAY_BUFFER , 0 , sizeof ( CCommandBuffer : : SVertex ) * Count , GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT ) ;
2017-09-02 13:24:07 +00:00
2017-09-27 10:16:34 +00:00
mem_copy ( pData , pCommand - > m_pVertices , sizeof ( CCommandBuffer : : SVertex ) * Count ) ;
glUnmapBuffer ( GL_ARRAY_BUFFER ) ;
}
2017-09-14 01:50:42 +00:00
glBindVertexArray ( m_PrimitiveDrawVertexID ) ;
2017-09-02 13:24:07 +00:00
switch ( pCommand - > m_PrimType )
{
2017-09-12 18:07:38 +00:00
//we dont support GL_QUADS due to core profile
2017-09-02 13:24:07 +00:00
case CCommandBuffer : : PRIMTYPE_LINES :
glDrawArrays ( GL_LINES , 0 , pCommand - > m_PrimCount * 2 ) ;
break ;
2017-09-14 00:49:35 +00:00
case CCommandBuffer : : PRIMTYPE_QUADS :
2017-10-23 16:02:18 +00:00
if ( m_LastIndexBufferBound ! = m_QuadDrawIndexBufferID )
{
glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER , m_QuadDrawIndexBufferID ) ;
m_LastIndexBufferBound = m_QuadDrawIndexBufferID ;
}
2017-09-14 00:49:35 +00:00
glDrawElements ( GL_TRIANGLES , pCommand - > m_PrimCount * 6 , GL_UNSIGNED_INT , 0 ) ;
2017-09-02 13:24:07 +00:00
break ;
default :
dbg_msg ( " render " , " unknown primtype %d \n " , pCommand - > m_Cmd ) ;
} ;
}
void CCommandProcessorFragment_OpenGL3_3 : : Cmd_Screenshot ( const CCommandBuffer : : SCommand_Screenshot * pCommand )
{
// fetch image data
GLint aViewport [ 4 ] = { 0 , 0 , 0 , 0 } ;
glGetIntegerv ( GL_VIEWPORT , aViewport ) ;
int w = aViewport [ 2 ] ;
int h = aViewport [ 3 ] ;
// we allocate one more row to use when we are flipping the texture
unsigned char * pPixelData = ( unsigned char * ) mem_alloc ( w * ( h + 1 ) * 3 , 1 ) ;
unsigned char * pTempRow = pPixelData + w * h * 3 ;
// fetch the pixels
GLint Alignment ;
glGetIntegerv ( GL_PACK_ALIGNMENT , & Alignment ) ;
glPixelStorei ( GL_PACK_ALIGNMENT , 1 ) ;
glReadPixels ( 0 , 0 , w , h , GL_RGB , GL_UNSIGNED_BYTE , pPixelData ) ;
glPixelStorei ( GL_PACK_ALIGNMENT , Alignment ) ;
// flip the pixel because opengl works from bottom left corner
for ( int y = 0 ; y < h / 2 ; y + + )
{
mem_copy ( pTempRow , pPixelData + y * w * 3 , w * 3 ) ;
mem_copy ( pPixelData + y * w * 3 , pPixelData + ( h - y - 1 ) * w * 3 , w * 3 ) ;
mem_copy ( pPixelData + ( h - y - 1 ) * w * 3 , pTempRow , w * 3 ) ;
}
// fill in the information
pCommand - > m_pImage - > m_Width = w ;
pCommand - > m_pImage - > m_Height = h ;
pCommand - > m_pImage - > m_Format = CImageInfo : : FORMAT_RGB ;
pCommand - > m_pImage - > m_pData = pPixelData ;
}
CCommandProcessorFragment_OpenGL3_3 : : CCommandProcessorFragment_OpenGL3_3 ( )
{
mem_zero ( m_aTextures , sizeof ( m_aTextures ) ) ;
m_pTextureMemoryUsage = 0 ;
}
bool CCommandProcessorFragment_OpenGL3_3 : : RunCommand ( const CCommandBuffer : : SCommand * pBaseCommand )
{
switch ( pBaseCommand - > m_Cmd )
{
case CMD_INIT : Cmd_Init ( static_cast < const SCommand_Init * > ( pBaseCommand ) ) ; break ;
case CMD_SHUTDOWN : Cmd_Shutdown ( static_cast < const SCommand_Shutdown * > ( pBaseCommand ) ) ; break ;
case CCommandBuffer : : CMD_TEXTURE_CREATE : Cmd_Texture_Create ( static_cast < const CCommandBuffer : : SCommand_Texture_Create * > ( pBaseCommand ) ) ; break ;
case CCommandBuffer : : CMD_TEXTURE_DESTROY : Cmd_Texture_Destroy ( static_cast < const CCommandBuffer : : SCommand_Texture_Destroy * > ( pBaseCommand ) ) ; break ;
case CCommandBuffer : : CMD_TEXTURE_UPDATE : Cmd_Texture_Update ( static_cast < const CCommandBuffer : : SCommand_Texture_Update * > ( pBaseCommand ) ) ; break ;
case CCommandBuffer : : CMD_CLEAR : Cmd_Clear ( static_cast < const CCommandBuffer : : SCommand_Clear * > ( pBaseCommand ) ) ; break ;
case CCommandBuffer : : CMD_RENDER : Cmd_Render ( static_cast < const CCommandBuffer : : SCommand_Render * > ( pBaseCommand ) ) ; break ;
case CCommandBuffer : : CMD_SCREENSHOT : Cmd_Screenshot ( static_cast < const CCommandBuffer : : SCommand_Screenshot * > ( pBaseCommand ) ) ; break ;
2017-09-12 18:07:38 +00:00
case CCommandBuffer : : CMD_CREATE_VERTEX_BUFFER_OBJECT : Cmd_CreateVertBuffer ( static_cast < const CCommandBuffer : : SCommand_CreateVertexBufferObject * > ( pBaseCommand ) ) ; break ;
case CCommandBuffer : : CMD_APPEND_VERTEX_BUFFER_OBJECT : Cmd_AppendVertBuffer ( static_cast < const CCommandBuffer : : SCommand_AppendVertexBufferObject * > ( pBaseCommand ) ) ; break ;
case CCommandBuffer : : CMD_CREATE_VERTEX_ARRAY_OBJECT : Cmd_CreateVertArray ( static_cast < const CCommandBuffer : : SCommand_CreateVertexArrayObject * > ( pBaseCommand ) ) ; break ;
case CCommandBuffer : : CMD_RENDER_IBO_VERTEX_ARRAY : Cmd_RenderVertexArray ( static_cast < const CCommandBuffer : : SCommand_RenderVertexArray * > ( pBaseCommand ) ) ; break ;
case CCommandBuffer : : CMD_DESTROY_VISUAL : Cmd_DestroyVertexArray ( static_cast < const CCommandBuffer : : SCommand_DestroyVisual * > ( pBaseCommand ) ) ; break ;
case CCommandBuffer : : CMD_RENDER_BORDER_TILE : Cmd_RenderBorderTile ( static_cast < const CCommandBuffer : : SCommand_RenderBorderTile * > ( pBaseCommand ) ) ; break ;
case CCommandBuffer : : CMD_RENDER_BORDER_TILE_LINE : Cmd_RenderBorderTileLine ( static_cast < const CCommandBuffer : : SCommand_RenderBorderTileLine * > ( pBaseCommand ) ) ; break ;
2017-09-02 13:24:07 +00:00
default : return false ;
}
return true ;
}
2017-09-13 18:33:58 +00:00
bool CCommandProcessorFragment_OpenGL3_3 : : IsAndUpdateTextureSlotBound ( int IDX , int Slot )
{
2017-09-12 18:07:38 +00:00
if ( m_TextureSlotBoundToUnit [ IDX ] . m_TextureSlot = = Slot ) return true ;
2017-09-27 12:52:06 +00:00
else
{
2017-09-12 18:07:38 +00:00
//the texture slot uses this index now
m_TextureSlotBoundToUnit [ IDX ] . m_TextureSlot = Slot ;
return false ;
}
}
2017-09-13 18:33:58 +00:00
void CCommandProcessorFragment_OpenGL3_3 : : DestroyTexture ( int Slot )
{
2017-09-12 18:07:38 +00:00
glDeleteTextures ( 1 , & m_aTextures [ Slot ] . m_Tex ) ;
glDeleteSamplers ( 1 , & m_aTextures [ Slot ] . m_Sampler ) ;
* m_pTextureMemoryUsage - = m_aTextures [ Slot ] . m_MemSize ;
m_aTextures [ Slot ] . m_Tex = 0 ;
m_aTextures [ Slot ] . m_Sampler = 0 ;
}
2017-09-13 18:33:58 +00:00
void CCommandProcessorFragment_OpenGL3_3 : : DestroyVisualObjects ( int Index )
{
2017-09-12 18:07:38 +00:00
SVisualObject & VisualObject = m_VisualObjects [ Index ] ;
2017-10-23 16:02:18 +00:00
if ( VisualObject . m_VertArrayID ! = 0 ) glDeleteVertexArrays ( 1 , & VisualObject . m_VertArrayID ) ;
// this is required, due to a driver bug for AMD under windows
if ( VisualObject . m_VertBufferID ! = 0 ) glDeleteBuffers ( 1 , & VisualObject . m_VertBufferID ) ;
2017-09-12 18:07:38 +00:00
VisualObject . m_NumElements = 0 ;
VisualObject . m_IsTextured = false ;
2017-09-27 10:16:34 +00:00
VisualObject . m_VertBufferID = VisualObject . m_VertArrayID = 0 ;
2017-10-24 01:12:48 +00:00
VisualObject . m_LastIndexBufferBound = 0 ;
2017-09-12 18:07:38 +00:00
}
2017-09-27 10:16:34 +00:00
void CCommandProcessorFragment_OpenGL3_3 : : AppendIndices ( unsigned int NewIndicesCount )
{
if ( NewIndicesCount < = m_CurrentIndicesInBuffer ) return ;
unsigned int AddCount = NewIndicesCount - m_CurrentIndicesInBuffer ;
unsigned int * Indices = new unsigned int [ AddCount ] ;
int Primq = ( m_CurrentIndicesInBuffer / 6 ) * 4 ;
2017-09-27 12:52:06 +00:00
for ( unsigned int i = 0 ; i < AddCount ; i + = 6 )
2017-09-27 10:16:34 +00:00
{
Indices [ i ] = Primq ;
Indices [ i + 1 ] = Primq + 1 ;
Indices [ i + 2 ] = Primq + 2 ;
Indices [ i + 3 ] = Primq ;
Indices [ i + 4 ] = Primq + 2 ;
Indices [ i + 5 ] = Primq + 3 ;
Primq + = 4 ;
}
glBindBuffer ( GL_COPY_READ_BUFFER , m_QuadDrawIndexBufferID ) ;
GLuint NewIndexBufferID ;
glGenBuffers ( 1 , & NewIndexBufferID ) ;
glBindBuffer ( GL_COPY_WRITE_BUFFER , NewIndexBufferID ) ;
GLsizeiptr size = sizeof ( unsigned int ) ;
glBufferData ( GL_COPY_WRITE_BUFFER , ( GLsizeiptr ) NewIndicesCount * size , NULL , GL_STATIC_DRAW ) ;
glCopyBufferSubData ( GL_COPY_READ_BUFFER , GL_COPY_WRITE_BUFFER , 0 , 0 , ( GLsizeiptr ) m_CurrentIndicesInBuffer * size ) ;
glBufferSubData ( GL_COPY_WRITE_BUFFER , ( GLsizeiptr ) m_CurrentIndicesInBuffer * size , ( GLsizeiptr ) AddCount * size , Indices ) ;
glBindBuffer ( GL_COPY_WRITE_BUFFER , 0 ) ;
glBindBuffer ( GL_COPY_READ_BUFFER , 0 ) ;
2017-09-12 18:07:38 +00:00
2017-09-27 10:16:34 +00:00
glDeleteBuffers ( 1 , & m_QuadDrawIndexBufferID ) ;
m_QuadDrawIndexBufferID = NewIndexBufferID ;
2017-11-03 18:48:17 +00:00
m_LastIndexBufferBound = 0 ;
for ( size_t i = 0 ; i < m_VisualObjects . size ( ) ; + + i ) {
m_VisualObjects [ i ] . m_LastIndexBufferBound = 0 ;
}
2017-09-27 10:16:34 +00:00
m_CurrentIndicesInBuffer = NewIndicesCount ;
delete [ ] Indices ;
}
2017-09-13 18:33:58 +00:00
void CCommandProcessorFragment_OpenGL3_3 : : Cmd_DestroyVertexArray ( const CCommandBuffer : : SCommand_DestroyVisual * pCommand )
{
2017-09-12 18:07:38 +00:00
int Index = pCommand - > m_VisualObjectIDX ;
2017-09-27 12:52:06 +00:00
if ( ( size_t ) Index > = m_VisualObjects . size ( ) )
2017-09-12 18:07:38 +00:00
return ;
DestroyVisualObjects ( Index ) ;
}
2017-09-13 18:33:58 +00:00
void CCommandProcessorFragment_OpenGL3_3 : : Cmd_RenderBorderTile ( const CCommandBuffer : : SCommand_RenderBorderTile * pCommand )
{
2017-09-12 18:07:38 +00:00
int Index = pCommand - > m_VisualObjectIDX ;
//if space not there return
2017-09-27 12:52:06 +00:00
if ( ( size_t ) Index > = m_VisualObjects . size ( ) )
2017-09-12 18:07:38 +00:00
return ;
SVisualObject & VisualObject = m_VisualObjects [ Index ] ;
2017-09-27 10:16:34 +00:00
if ( VisualObject . m_VertArrayID = = 0 ) return ;
2017-09-12 18:07:38 +00:00
CGLSLBorderTileProgram * pProgram = NULL ;
2017-09-13 18:33:58 +00:00
if ( VisualObject . m_IsTextured )
{
pProgram = m_pBorderTileProgramTextured ;
2017-09-12 18:07:38 +00:00
}
2017-09-13 18:33:58 +00:00
else pProgram = m_pBorderTileProgram ;
2017-09-12 18:07:38 +00:00
pProgram - > UseProgram ( ) ;
2017-10-09 16:58:44 +00:00
if ( pProgram - > m_LocLOD ! = - 1 ) pProgram - > SetUniform ( pProgram - > m_LocLOD , ( float ) ( pCommand - > m_LOD ) ) ;
2017-09-12 18:07:38 +00:00
SetState ( pCommand - > m_State , pProgram ) ;
pProgram - > SetUniformVec4 ( pProgram - > m_LocColor , 1 , ( float * ) & pCommand - > m_Color ) ;
pProgram - > SetUniformVec2 ( pProgram - > m_LocOffset , 1 , ( float * ) & pCommand - > m_Offset ) ;
pProgram - > SetUniformVec2 ( pProgram - > m_LocDir , 1 , ( float * ) & pCommand - > m_Dir ) ;
pProgram - > SetUniform ( pProgram - > m_LocJumpIndex , ( int ) pCommand - > m_JumpIndex ) ;
glBindVertexArray ( VisualObject . m_VertArrayID ) ;
2017-10-23 16:02:18 +00:00
if ( VisualObject . m_LastIndexBufferBound ! = m_QuadDrawIndexBufferID )
{
glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER , m_QuadDrawIndexBufferID ) ;
VisualObject . m_LastIndexBufferBound = m_QuadDrawIndexBufferID ;
}
2017-09-12 18:07:38 +00:00
glDrawElementsInstanced ( GL_TRIANGLES , 6 , GL_UNSIGNED_INT , pCommand - > m_pIndicesOffset , pCommand - > m_DrawNum ) ;
}
2017-09-13 18:33:58 +00:00
void CCommandProcessorFragment_OpenGL3_3 : : Cmd_RenderBorderTileLine ( const CCommandBuffer : : SCommand_RenderBorderTileLine * pCommand )
{
2017-09-12 18:07:38 +00:00
int Index = pCommand - > m_VisualObjectIDX ;
//if space not there return
2017-09-27 12:52:06 +00:00
if ( ( size_t ) Index > = m_VisualObjects . size ( ) )
2017-09-12 18:07:38 +00:00
return ;
SVisualObject & VisualObject = m_VisualObjects [ Index ] ;
2017-09-27 10:16:34 +00:00
if ( VisualObject . m_VertArrayID = = 0 ) return ;
2017-09-12 18:07:38 +00:00
CGLSLBorderTileLineProgram * pProgram = NULL ;
2017-09-13 18:33:58 +00:00
if ( VisualObject . m_IsTextured )
{
pProgram = m_pBorderTileLineProgramTextured ;
2017-09-12 18:07:38 +00:00
}
2017-09-13 18:33:58 +00:00
else pProgram = m_pBorderTileLineProgram ;
2017-09-12 18:07:38 +00:00
pProgram - > UseProgram ( ) ;
2017-10-09 16:58:44 +00:00
if ( pProgram - > m_LocLOD ! = - 1 ) pProgram - > SetUniform ( pProgram - > m_LocLOD , ( float ) ( pCommand - > m_LOD ) ) ;
2017-09-12 18:07:38 +00:00
SetState ( pCommand - > m_State , pProgram ) ;
pProgram - > SetUniformVec4 ( pProgram - > m_LocColor , 1 , ( float * ) & pCommand - > m_Color ) ;
pProgram - > SetUniformVec2 ( pProgram - > m_LocDir , 1 , ( float * ) & pCommand - > m_Dir ) ;
glBindVertexArray ( VisualObject . m_VertArrayID ) ;
2017-10-23 16:02:18 +00:00
if ( VisualObject . m_LastIndexBufferBound ! = m_QuadDrawIndexBufferID )
{
glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER , m_QuadDrawIndexBufferID ) ;
VisualObject . m_LastIndexBufferBound = m_QuadDrawIndexBufferID ;
}
2017-09-12 18:07:38 +00:00
glDrawElementsInstanced ( GL_TRIANGLES , pCommand - > m_IndexDrawNum , GL_UNSIGNED_INT , pCommand - > m_pIndicesOffset , pCommand - > m_DrawNum ) ;
}
2017-09-13 18:33:58 +00:00
void CCommandProcessorFragment_OpenGL3_3 : : Cmd_RenderVertexArray ( const CCommandBuffer : : SCommand_RenderVertexArray * pCommand )
{
2017-09-12 18:07:38 +00:00
int Index = pCommand - > m_VisualObjectIDX ;
//if space not there return
2017-09-27 12:52:06 +00:00
if ( ( size_t ) Index > = m_VisualObjects . size ( ) )
2017-09-12 18:07:38 +00:00
return ;
SVisualObject & VisualObject = m_VisualObjects [ Index ] ;
2017-09-27 10:16:34 +00:00
if ( VisualObject . m_VertArrayID = = 0 ) return ;
2017-09-12 18:07:38 +00:00
2017-09-27 10:16:34 +00:00
if ( pCommand - > m_IndicesDrawNum = = 0 )
2017-09-13 18:33:58 +00:00
{
2017-09-12 18:07:38 +00:00
return ; //nothing to draw
}
CGLSLTileProgram * pProgram = NULL ;
2017-09-13 18:33:58 +00:00
if ( VisualObject . m_IsTextured )
{
pProgram = m_pTileProgramTextured ;
2017-09-12 18:07:38 +00:00
}
2017-09-13 18:33:58 +00:00
else pProgram = m_pTileProgram ;
2017-09-12 18:07:38 +00:00
pProgram - > UseProgram ( ) ;
2017-10-09 16:58:44 +00:00
if ( pProgram - > m_LocLOD ! = - 1 ) pProgram - > SetUniform ( pProgram - > m_LocLOD , ( float ) ( pCommand - > m_LOD ) ) ;
2017-09-12 18:07:38 +00:00
SetState ( pCommand - > m_State , pProgram ) ;
pProgram - > SetUniformVec4 ( pProgram - > m_LocColor , 1 , ( float * ) & pCommand - > m_Color ) ;
glBindVertexArray ( VisualObject . m_VertArrayID ) ;
2017-10-23 16:02:18 +00:00
if ( VisualObject . m_LastIndexBufferBound ! = m_QuadDrawIndexBufferID )
{
glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER , m_QuadDrawIndexBufferID ) ;
VisualObject . m_LastIndexBufferBound = m_QuadDrawIndexBufferID ;
}
2017-09-27 10:16:34 +00:00
for ( int i = 0 ; i < pCommand - > m_IndicesDrawNum ; + + i )
2017-09-13 18:33:58 +00:00
{
2017-09-27 10:16:34 +00:00
glDrawElements ( GL_TRIANGLES , pCommand - > m_pDrawCount [ i ] , GL_UNSIGNED_INT , pCommand - > m_pIndicesOffsets [ i ] ) ;
2017-09-12 18:07:38 +00:00
}
}
2017-09-13 18:33:58 +00:00
void CCommandProcessorFragment_OpenGL3_3 : : Cmd_CreateVertBuffer ( const CCommandBuffer : : SCommand_CreateVertexBufferObject * pCommand )
{
2017-09-12 18:07:38 +00:00
int Index = pCommand - > m_VisualObjectIDX ;
//create necessary space
2017-09-27 12:52:06 +00:00
if ( ( size_t ) Index > = m_VisualObjects . size ( ) )
2017-09-13 18:33:58 +00:00
{
for ( int i = m_VisualObjects . size ( ) ; i < Index + 1 ; + + i )
{
2017-09-12 18:07:38 +00:00
m_VisualObjects . push_back ( SVisualObject ( ) ) ;
}
}
SVisualObject & VisualObject = m_VisualObjects [ Index ] ;
VisualObject . m_NumElements = pCommand - > m_NumVertices ;
VisualObject . m_IsTextured = pCommand - > m_IsTextured ;
glGenBuffers ( 1 , & VisualObject . m_VertBufferID ) ;
glBindBuffer ( GL_ARRAY_BUFFER , VisualObject . m_VertBufferID ) ;
GLsizeiptr size = ( VisualObject . m_IsTextured ? ( sizeof ( float ) + sizeof ( unsigned char ) * 2 ) : ( sizeof ( float ) ) ) ;
glBufferData ( GL_ARRAY_BUFFER , ( GLsizeiptr ) ( VisualObject . m_NumElements * size ) , pCommand - > m_Elements , GL_STATIC_DRAW ) ;
glBindBuffer ( GL_ARRAY_BUFFER , 0 ) ;
}
2017-09-13 18:33:58 +00:00
void CCommandProcessorFragment_OpenGL3_3 : : Cmd_AppendVertBuffer ( const CCommandBuffer : : SCommand_AppendVertexBufferObject * pCommand )
{
2017-09-12 18:07:38 +00:00
int Index = pCommand - > m_VisualObjectIDX ;
//if space not there return
2017-09-27 12:52:06 +00:00
if ( ( size_t ) Index > = m_VisualObjects . size ( ) )
2017-09-13 18:33:58 +00:00
{
2017-09-12 18:07:38 +00:00
return ;
}
SVisualObject & VisualObject = m_VisualObjects [ Index ] ;
glBindBuffer ( GL_COPY_READ_BUFFER , VisualObject . m_VertBufferID ) ;
GLuint NewVerBufferID ;
glGenBuffers ( 1 , & NewVerBufferID ) ;
glBindBuffer ( GL_COPY_WRITE_BUFFER , NewVerBufferID ) ;
GLsizeiptr size = ( VisualObject . m_IsTextured ? ( sizeof ( float ) + sizeof ( unsigned char ) * 2 ) : ( sizeof ( float ) ) ) ;
glBufferData ( GL_COPY_WRITE_BUFFER , ( GLsizeiptr ) ( ( VisualObject . m_NumElements + pCommand - > m_NumVertices ) * size ) , NULL , GL_STATIC_DRAW ) ;
glCopyBufferSubData ( GL_COPY_READ_BUFFER , GL_COPY_WRITE_BUFFER , 0 , 0 , ( GLsizeiptr ) ( VisualObject . m_NumElements * size ) ) ;
glBufferSubData ( GL_COPY_WRITE_BUFFER , ( GLsizeiptr ) ( VisualObject . m_NumElements * size ) , ( GLsizeiptr ) ( pCommand - > m_NumVertices * size ) , pCommand - > m_Elements ) ;
glBindBuffer ( GL_COPY_WRITE_BUFFER , 0 ) ;
glBindBuffer ( GL_COPY_READ_BUFFER , 0 ) ;
glDeleteBuffers ( 1 , & VisualObject . m_VertBufferID ) ;
VisualObject . m_VertBufferID = NewVerBufferID ;
VisualObject . m_NumElements + = pCommand - > m_NumVertices ;
}
2017-09-13 18:33:58 +00:00
void CCommandProcessorFragment_OpenGL3_3 : : Cmd_CreateVertArray ( const CCommandBuffer : : SCommand_CreateVertexArrayObject * pCommand )
{
2017-09-12 18:07:38 +00:00
int Index = pCommand - > m_VisualObjectIDX ;
//if space not there return
2017-09-27 12:52:06 +00:00
if ( ( size_t ) Index > = m_VisualObjects . size ( ) )
2017-09-12 18:07:38 +00:00
return ;
2017-09-27 10:16:34 +00:00
if ( pCommand - > m_RequiredIndicesCount > m_CurrentIndicesInBuffer )
AppendIndices ( pCommand - > m_RequiredIndicesCount ) ;
2017-09-12 18:07:38 +00:00
SVisualObject & VisualObject = m_VisualObjects [ Index ] ;
glGenVertexArrays ( 1 , & VisualObject . m_VertArrayID ) ;
glBindVertexArray ( VisualObject . m_VertArrayID ) ;
glEnableVertexAttribArray ( 0 ) ;
2017-09-13 18:33:58 +00:00
if ( VisualObject . m_IsTextured )
{
2017-09-12 18:07:38 +00:00
glEnableVertexAttribArray ( 1 ) ;
glEnableVertexAttribArray ( 2 ) ;
}
glBindBuffer ( GL_ARRAY_BUFFER , VisualObject . m_VertBufferID ) ;
GLsizei stride = sizeof ( float ) * 2 + sizeof ( unsigned char ) * 2 * 2 ;
glVertexAttribPointer ( 0 , 2 , GL_FLOAT , GL_FALSE , ( GLsizei ) ( VisualObject . m_IsTextured ? stride : 0 ) , 0 ) ;
2017-09-13 18:33:58 +00:00
if ( VisualObject . m_IsTextured )
{
2017-09-12 18:07:38 +00:00
glVertexAttribPointer ( 1 , 2 , GL_UNSIGNED_BYTE , GL_FALSE , ( GLsizei ) ( VisualObject . m_IsTextured ? stride : 0 ) , ( void * ) ( sizeof ( float ) * 2 ) ) ;
glVertexAttribIPointer ( 2 , 2 , GL_UNSIGNED_BYTE , ( GLsizei ) ( VisualObject . m_IsTextured ? stride : 0 ) , ( void * ) ( sizeof ( float ) * 2 + sizeof ( unsigned char ) * 2 ) ) ;
}
glBindVertexArray ( 0 ) ;
glBindBuffer ( GL_ARRAY_BUFFER , 0 ) ;
2017-10-23 16:02:18 +00:00
// due to a driver bug for AMD hardware (https://stackoverflow.com/questions/41520764/should-i-delete-vertex-buffer-object-after-binding-it-to-vertex-array-objects)
// we don't delete the VBO bound to the VAO
2017-09-12 18:07:38 +00:00
}
2012-01-03 20:39:10 +00:00
// ------------ CCommandProcessorFragment_SDL
void CCommandProcessorFragment_SDL : : Cmd_Init ( const SCommand_Init * pCommand )
{
2015-08-24 20:46:28 +00:00
m_GLContext = pCommand - > m_GLContext ;
m_pWindow = pCommand - > m_pWindow ;
SDL_GL_MakeCurrent ( m_pWindow , m_GLContext ) ;
2012-01-03 20:39:10 +00:00
// set some default settings
glEnable ( GL_BLEND ) ;
glDisable ( GL_CULL_FACE ) ;
glDisable ( GL_DEPTH_TEST ) ;
glAlphaFunc ( GL_GREATER , 0 ) ;
glEnable ( GL_ALPHA_TEST ) ;
glDepthMask ( 0 ) ;
}
2017-10-23 16:02:18 +00:00
void CCommandProcessorFragment_SDL : : Cmd_Update_Viewport ( const SCommand_Update_Viewport * pCommand )
{
glViewport ( pCommand - > m_X , pCommand - > m_Y , pCommand - > m_Width , pCommand - > m_Height ) ;
}
2012-01-03 20:39:10 +00:00
void CCommandProcessorFragment_SDL : : Cmd_Shutdown ( const SCommand_Shutdown * pCommand )
{
2015-08-24 20:46:28 +00:00
SDL_GL_MakeCurrent ( NULL , NULL ) ;
2012-01-03 20:39:10 +00:00
}
void CCommandProcessorFragment_SDL : : Cmd_Swap ( const CCommandBuffer : : SCommand_Swap * pCommand )
{
2015-08-24 20:46:28 +00:00
SDL_GL_SwapWindow ( m_pWindow ) ;
2012-01-06 13:12:49 +00:00
if ( pCommand - > m_Finish )
glFinish ( ) ;
2012-01-03 20:39:10 +00:00
}
2016-04-29 22:34:12 +00:00
void CCommandProcessorFragment_SDL : : Cmd_VSync ( const CCommandBuffer : : SCommand_VSync * pCommand )
{
* pCommand - > m_pRetOk = SDL_GL_SetSwapInterval ( pCommand - > m_VSync ) = = 0 ;
}
2016-04-30 15:59:58 +00:00
void CCommandProcessorFragment_SDL : : Cmd_Resize ( const CCommandBuffer : : SCommand_Resize * pCommand )
{
SDL_SetWindowSize ( m_pWindow , pCommand - > m_Width , pCommand - > m_Height ) ;
glViewport ( 0 , 0 , pCommand - > m_Width , pCommand - > m_Height ) ;
}
2012-01-03 20:39:10 +00:00
void CCommandProcessorFragment_SDL : : Cmd_VideoModes ( const CCommandBuffer : : SCommand_VideoModes * pCommand )
{
2015-08-24 20:46:28 +00:00
SDL_DisplayMode mode ;
int maxModes = SDL_GetNumDisplayModes ( pCommand - > m_Screen ) ,
numModes = 0 ;
for ( int i = 0 ; i < maxModes ; i + + )
2012-01-03 20:39:10 +00:00
{
2015-08-24 20:46:28 +00:00
if ( SDL_GetDisplayMode ( pCommand - > m_Screen , i , & mode ) < 0 )
{
dbg_msg ( " gfx " , " unable to get display mode: %s " , SDL_GetError ( ) ) ;
continue ;
}
2017-03-21 10:24:44 +00:00
bool AlreadyFound = false ;
2015-08-24 20:46:28 +00:00
for ( int j = 0 ; j < numModes ; j + + )
2012-01-03 20:39:10 +00:00
{
2015-08-24 20:46:28 +00:00
if ( pCommand - > m_pModes [ j ] . m_Width = = mode . w & & pCommand - > m_pModes [ j ] . m_Height = = mode . h )
{
2017-03-21 10:24:44 +00:00
AlreadyFound = true ;
2012-01-03 20:39:10 +00:00
break ;
2015-08-24 20:46:28 +00:00
}
2012-01-03 20:39:10 +00:00
}
2017-03-21 10:24:44 +00:00
if ( AlreadyFound )
2015-08-24 20:46:28 +00:00
continue ;
2012-01-03 20:39:10 +00:00
2015-08-24 20:46:28 +00:00
pCommand - > m_pModes [ numModes ] . m_Width = mode . w ;
pCommand - > m_pModes [ numModes ] . m_Height = mode . h ;
pCommand - > m_pModes [ numModes ] . m_Red = 8 ;
pCommand - > m_pModes [ numModes ] . m_Green = 8 ;
pCommand - > m_pModes [ numModes ] . m_Blue = 8 ;
numModes + + ;
2012-01-03 20:39:10 +00:00
}
2015-08-24 20:46:28 +00:00
* pCommand - > m_pNumModes = numModes ;
2012-01-03 20:39:10 +00:00
}
CCommandProcessorFragment_SDL : : CCommandProcessorFragment_SDL ( )
{
}
bool CCommandProcessorFragment_SDL : : RunCommand ( const CCommandBuffer : : SCommand * pBaseCommand )
{
switch ( pBaseCommand - > m_Cmd )
{
case CCommandBuffer : : CMD_SWAP : Cmd_Swap ( static_cast < const CCommandBuffer : : SCommand_Swap * > ( pBaseCommand ) ) ; break ;
2016-04-29 22:34:12 +00:00
case CCommandBuffer : : CMD_VSYNC : Cmd_VSync ( static_cast < const CCommandBuffer : : SCommand_VSync * > ( pBaseCommand ) ) ; break ;
2016-04-30 15:59:58 +00:00
case CCommandBuffer : : CMD_RESIZE : Cmd_Resize ( static_cast < const CCommandBuffer : : SCommand_Resize * > ( pBaseCommand ) ) ; break ;
2012-01-03 20:39:10 +00:00
case CCommandBuffer : : CMD_VIDEOMODES : Cmd_VideoModes ( static_cast < const CCommandBuffer : : SCommand_VideoModes * > ( pBaseCommand ) ) ; break ;
case CMD_INIT : Cmd_Init ( static_cast < const SCommand_Init * > ( pBaseCommand ) ) ; break ;
case CMD_SHUTDOWN : Cmd_Shutdown ( static_cast < const SCommand_Shutdown * > ( pBaseCommand ) ) ; break ;
2017-10-23 16:02:18 +00:00
case CMD_UPDATE_VIEWPORT : Cmd_Update_Viewport ( static_cast < const SCommand_Update_Viewport * > ( pBaseCommand ) ) ; break ;
2012-01-03 20:39:10 +00:00
default : return false ;
}
return true ;
}
// ------------ CCommandProcessor_SDL_OpenGL
void CCommandProcessor_SDL_OpenGL : : RunBuffer ( CCommandBuffer * pBuffer )
{
unsigned CmdIndex = 0 ;
while ( 1 )
{
const CCommandBuffer : : SCommand * pBaseCommand = pBuffer - > GetCommand ( & CmdIndex ) ;
if ( pBaseCommand = = 0x0 )
break ;
2017-09-02 13:24:07 +00:00
2017-09-13 18:33:58 +00:00
if ( m_UseOpenGL3_3 )
{
2017-09-02 13:24:07 +00:00
if ( m_OpenGL3_3 . RunCommand ( pBaseCommand ) )
continue ;
}
2017-09-13 18:33:58 +00:00
else
{
2017-09-02 13:24:07 +00:00
if ( m_OpenGL . RunCommand ( pBaseCommand ) )
continue ;
}
2012-01-03 20:39:10 +00:00
if ( m_SDL . RunCommand ( pBaseCommand ) )
continue ;
if ( m_General . RunCommand ( pBaseCommand ) )
continue ;
2015-07-09 00:08:14 +00:00
2012-01-03 20:39:10 +00:00
dbg_msg ( " graphics " , " unknown command %d " , pBaseCommand - > m_Cmd ) ;
}
}
// ------------ CGraphicsBackend_SDL_OpenGL
2017-10-23 16:02:18 +00:00
int CGraphicsBackend_SDL_OpenGL : : Init ( const char * pName , int * Screen , int * pWidth , int * pHeight , int FsaaSamples , int Flags , int * pDesktopWidth , int * pDesktopHeight , int * pCurrentWidth , int * pCurrentHeight )
2017-09-02 13:24:07 +00:00
{
2012-01-03 20:39:10 +00:00
if ( ! SDL_WasInit ( SDL_INIT_VIDEO ) )
{
if ( SDL_InitSubSystem ( SDL_INIT_VIDEO ) < 0 )
{
dbg_msg ( " gfx " , " unable to init SDL video: %s " , SDL_GetError ( ) ) ;
return - 1 ;
}
# ifdef CONF_FAMILY_WINDOWS
if ( ! getenv ( " SDL_VIDEO_WINDOW_POS " ) & & ! getenv ( " SDL_VIDEO_CENTERED " ) ) // ignore_convention
2013-02-25 11:48:31 +00:00
putenv ( " SDL_VIDEO_WINDOW_POS=center " ) ; // ignore_convention
2012-01-03 20:39:10 +00:00
# endif
}
2017-09-27 10:16:34 +00:00
SDL_ClearError ( ) ;
const char * pErr = NULL ;
//query default values, since they are platform dependend
static bool s_InitDefaultParams = false ;
static int s_SDLGLContextProfileMask , s_SDLGLContextMajorVersion , s_SDLGLContextMinorVersion ;
if ( ! s_InitDefaultParams )
{
SDL_GL_GetAttribute ( SDL_GL_CONTEXT_PROFILE_MASK , & s_SDLGLContextProfileMask ) ;
SDL_GL_GetAttribute ( SDL_GL_CONTEXT_MAJOR_VERSION , & s_SDLGLContextMajorVersion ) ;
SDL_GL_GetAttribute ( SDL_GL_CONTEXT_MINOR_VERSION , & s_SDLGLContextMinorVersion ) ;
s_InitDefaultParams = true ;
}
2017-09-02 13:24:07 +00:00
m_UseOpenGL3_3 = false ;
2017-10-20 20:52:38 +00:00
if ( g_Config . m_GfxOpenGL3 & & SDL_GL_SetAttribute ( SDL_GL_CONTEXT_PROFILE_MASK , SDL_GL_CONTEXT_PROFILE_CORE ) = = 0 )
2017-09-13 18:33:58 +00:00
{
2017-09-27 10:16:34 +00:00
pErr = SDL_GetError ( ) ;
if ( pErr [ 0 ] ! = ' \0 ' )
2017-09-13 18:33:58 +00:00
{
2017-09-27 10:16:34 +00:00
dbg_msg ( " gfx " , " Using old OpenGL context, because an error occurred while trying to use OpenGL context 3.3: %s. " , pErr ) ;
SDL_GL_SetAttribute ( SDL_GL_CONTEXT_PROFILE_MASK , s_SDLGLContextProfileMask ) ;
2017-09-02 13:24:07 +00:00
}
2017-09-27 10:16:34 +00:00
else
{
if ( SDL_GL_SetAttribute ( SDL_GL_CONTEXT_MAJOR_VERSION , 3 ) = = 0 & & SDL_GL_SetAttribute ( SDL_GL_CONTEXT_MINOR_VERSION , 3 ) = = 0 )
{
pErr = SDL_GetError ( ) ;
if ( pErr [ 0 ] ! = ' \0 ' )
{
dbg_msg ( " gfx " , " Using old OpenGL context, because an error occurred while trying to use OpenGL context 3.3: %s. " , pErr ) ;
SDL_GL_SetAttribute ( SDL_GL_CONTEXT_MAJOR_VERSION , s_SDLGLContextMajorVersion ) ;
SDL_GL_SetAttribute ( SDL_GL_CONTEXT_MINOR_VERSION , s_SDLGLContextMinorVersion ) ;
}
else
{
m_UseOpenGL3_3 = true ;
int vMaj , vMin ;
SDL_GL_GetAttribute ( SDL_GL_CONTEXT_MAJOR_VERSION , & vMaj ) ;
SDL_GL_GetAttribute ( SDL_GL_CONTEXT_MINOR_VERSION , & vMin ) ;
dbg_msg ( " gfx " , " Using OpenGL version %d.%d. " , vMaj , vMin ) ;
}
}
else
{
dbg_msg ( " gfx " , " Couldn't create OpenGL 3.3 context. " ) ;
SDL_GL_SetAttribute ( SDL_GL_CONTEXT_MAJOR_VERSION , s_SDLGLContextMajorVersion ) ;
SDL_GL_SetAttribute ( SDL_GL_CONTEXT_MINOR_VERSION , s_SDLGLContextMinorVersion ) ;
}
2017-09-02 13:24:07 +00:00
}
}
2017-09-27 10:16:34 +00:00
else
{
//set default attributes
SDL_GL_SetAttribute ( SDL_GL_CONTEXT_PROFILE_MASK , s_SDLGLContextProfileMask ) ;
SDL_GL_SetAttribute ( SDL_GL_CONTEXT_MAJOR_VERSION , s_SDLGLContextMajorVersion ) ;
SDL_GL_SetAttribute ( SDL_GL_CONTEXT_MINOR_VERSION , s_SDLGLContextMinorVersion ) ;
}
2017-09-02 13:24:07 +00:00
2016-04-29 22:34:12 +00:00
// set screen
SDL_Rect ScreenPos ;
m_NumScreens = SDL_GetNumVideoDisplays ( ) ;
if ( m_NumScreens > 0 )
{
2016-05-07 21:19:46 +00:00
if ( * Screen < 0 | | * Screen > = m_NumScreens )
* Screen = 0 ;
2016-04-29 22:34:12 +00:00
if ( SDL_GetDisplayBounds ( * Screen , & ScreenPos ) ! = 0 )
{
dbg_msg ( " gfx " , " unable to retrieve screen information: %s " , SDL_GetError ( ) ) ;
return - 1 ;
}
}
else
2015-08-24 20:46:28 +00:00
{
2016-04-29 22:34:12 +00:00
dbg_msg ( " gfx " , " unable to retrieve number of screens: %s " , SDL_GetError ( ) ) ;
2015-08-24 20:46:28 +00:00
return - 1 ;
}
2012-01-03 20:39:10 +00:00
2016-04-29 22:34:12 +00:00
// store desktop resolution for settings reset button
SDL_DisplayMode DisplayMode ;
if ( SDL_GetDesktopDisplayMode ( * Screen , & DisplayMode ) )
{
dbg_msg ( " gfx " , " unable to get desktop resolution: %s " , SDL_GetError ( ) ) ;
return - 1 ;
}
* pDesktopWidth = DisplayMode . w ;
* pDesktopHeight = DisplayMode . h ;
// use desktop resolution as default resolution
2017-07-11 12:08:03 +00:00
# ifdef __ANDROID__
* pWidth = * pDesktopWidth ;
* pHeight = * pDesktopHeight ;
2017-07-15 15:29:57 +00:00
/*
2017-07-15 14:38:40 +00:00
# elif defined(CONF_FAMILY_WINDOWS)
if ( * pWidth = = 0 | | * pHeight = = 0 )
{
* pWidth = * pDesktopWidth ;
* pHeight = * pDesktopHeight ;
}
else
{
float dpi = - 1 ;
SDL_GetDisplayDPI ( 0 , NULL , & dpi , NULL ) ;
if ( dpi > 0 )
{
* pWidth = * pWidth * 96 / dpi ;
* pHeight = * pHeight * 96 / dpi ;
}
}
2017-07-15 15:29:57 +00:00
*/
2017-07-11 12:08:03 +00:00
# else
if ( * pWidth = = 0 | | * pHeight = = 0 )
{
* pWidth = * pDesktopWidth ;
* pHeight = * pDesktopHeight ;
}
# endif
2012-03-04 11:46:55 +00:00
2015-08-24 20:46:28 +00:00
// set flags
2017-07-15 14:18:18 +00:00
int SdlFlags = SDL_WINDOW_OPENGL | SDL_WINDOW_HIDDEN | SDL_WINDOW_ALLOW_HIGHDPI ;
2016-05-01 01:28:41 +00:00
# if defined(SDL_VIDEO_DRIVER_X11)
2015-08-24 20:46:28 +00:00
if ( Flags & IGraphicsBackend : : INITFLAG_RESIZABLE )
SdlFlags | = SDL_WINDOW_RESIZABLE ;
2016-05-01 01:28:41 +00:00
# endif
2012-06-27 09:46:11 +00:00
if ( Flags & IGraphicsBackend : : INITFLAG_BORDERLESS )
2015-08-24 20:46:28 +00:00
SdlFlags | = SDL_WINDOW_BORDERLESS ;
2012-01-03 20:39:10 +00:00
if ( Flags & IGraphicsBackend : : INITFLAG_FULLSCREEN )
2016-04-30 21:10:09 +00:00
{
2016-04-29 22:34:12 +00:00
# if defined(CONF_PLATFORM_MACOSX) // Todo SDL: remove this when fixed (game freezes when losing focus in fullscreen)
SdlFlags | = SDL_WINDOW_FULLSCREEN_DESKTOP ; // always use "fake" fullscreen
2016-04-30 21:10:09 +00:00
* pWidth = * pDesktopWidth ;
* pHeight = * pDesktopHeight ;
2016-04-29 22:34:12 +00:00
# else
2017-10-23 16:02:18 +00:00
//when we are at fullscreen, we really shouldn't allow window sizes, that aren't supported by the driver
bool SupportedResolution = false ;
SDL_DisplayMode mode ;
2017-10-23 16:31:44 +00:00
int maxModes = SDL_GetNumDisplayModes ( g_Config . m_GfxScreen ) ;
2017-10-23 16:02:18 +00:00
for ( int i = 0 ; i < maxModes ; i + + )
{
if ( SDL_GetDisplayMode ( g_Config . m_GfxScreen , i , & mode ) < 0 )
{
dbg_msg ( " gfx " , " unable to get display mode: %s " , SDL_GetError ( ) ) ;
continue ;
}
if ( * pWidth = = mode . w & & * pHeight = = mode . h )
{
SupportedResolution = true ;
break ;
}
}
if ( SupportedResolution )
SdlFlags | = SDL_WINDOW_FULLSCREEN ;
else
SdlFlags | = SDL_WINDOW_FULLSCREEN_DESKTOP ;
2016-04-29 22:34:12 +00:00
# endif
2016-04-30 21:10:09 +00:00
}
2012-01-03 20:39:10 +00:00
// set gl attributes
2015-08-24 20:46:28 +00:00
SDL_GL_SetAttribute ( SDL_GL_DOUBLEBUFFER , 1 ) ;
2012-01-03 20:39:10 +00:00
if ( FsaaSamples )
{
SDL_GL_SetAttribute ( SDL_GL_MULTISAMPLEBUFFERS , 1 ) ;
SDL_GL_SetAttribute ( SDL_GL_MULTISAMPLESAMPLES , FsaaSamples ) ;
}
else
{
SDL_GL_SetAttribute ( SDL_GL_MULTISAMPLEBUFFERS , 0 ) ;
SDL_GL_SetAttribute ( SDL_GL_MULTISAMPLESAMPLES , 0 ) ;
}
2016-05-07 13:59:13 +00:00
if ( g_Config . m_InpMouseOld )
SDL_SetHint ( SDL_HINT_MOUSE_RELATIVE_MODE_WARP , " 1 " ) ;
2015-08-24 20:46:28 +00:00
m_pWindow = SDL_CreateWindow (
pName ,
2016-05-07 21:19:46 +00:00
SDL_WINDOWPOS_UNDEFINED ,
SDL_WINDOWPOS_UNDEFINED ,
2015-08-24 20:46:28 +00:00
* pWidth ,
* pHeight ,
SdlFlags ) ;
2012-01-03 20:39:10 +00:00
// set caption
2015-08-24 20:46:28 +00:00
if ( m_pWindow = = NULL )
{
dbg_msg ( " gfx " , " unable to create window: %s " , SDL_GetError ( ) ) ;
return - 1 ;
}
m_GLContext = SDL_GL_CreateContext ( m_pWindow ) ;
2012-01-03 20:39:10 +00:00
2015-08-24 20:46:28 +00:00
if ( m_GLContext = = NULL )
2012-01-03 20:39:10 +00:00
{
2015-08-24 20:46:28 +00:00
dbg_msg ( " gfx " , " unable to create OpenGL context: %s " , SDL_GetError ( ) ) ;
2012-01-03 20:39:10 +00:00
return - 1 ;
2015-07-09 00:08:14 +00:00
}
2017-10-20 07:08:49 +00:00
2017-09-02 13:24:07 +00:00
//support graphic cards that are pretty old(and linux)
glewExperimental = GL_TRUE ;
if ( GLEW_OK ! = glewInit ( ) )
return - 1 ;
2012-01-03 20:39:10 +00:00
2016-05-07 14:35:31 +00:00
SDL_GL_GetDrawableSize ( m_pWindow , pWidth , pHeight ) ;
2015-08-24 20:46:28 +00:00
SDL_GL_SetSwapInterval ( Flags & IGraphicsBackend : : INITFLAG_VSYNC ? 1 : 0 ) ;
SDL_GL_MakeCurrent ( NULL , NULL ) ;
2012-01-03 20:39:10 +00:00
// start the command processor
m_pProcessor = new CCommandProcessor_SDL_OpenGL ;
2017-09-02 13:24:07 +00:00
( ( CCommandProcessor_SDL_OpenGL * ) m_pProcessor ) - > UseOpenGL3_3 ( m_UseOpenGL3_3 ) ;
2012-01-03 20:39:10 +00:00
StartProcessor ( m_pProcessor ) ;
2012-10-06 21:31:02 +00:00
// issue init commands for OpenGL and SDL
2012-01-03 20:39:10 +00:00
CCommandBuffer CmdBuffer ( 1024 , 512 ) ;
2017-09-13 18:33:58 +00:00
if ( m_UseOpenGL3_3 )
{
2017-09-02 13:24:07 +00:00
//run sdl first to have the context in the thread
CCommandProcessorFragment_SDL : : SCommand_Init CmdSDL ;
CmdSDL . m_pWindow = m_pWindow ;
CmdSDL . m_GLContext = m_GLContext ;
CmdBuffer . AddCommand ( CmdSDL ) ;
RunBuffer ( & CmdBuffer ) ;
WaitForIdle ( ) ;
CCommandProcessorFragment_OpenGL3_3 : : SCommand_Init CmdOpenGL ;
CmdOpenGL . m_pTextureMemoryUsage = & m_TextureMemoryUsage ;
CmdBuffer . AddCommand ( CmdOpenGL ) ;
RunBuffer ( & CmdBuffer ) ;
WaitForIdle ( ) ;
2017-09-27 12:52:06 +00:00
}
else
{
2017-09-02 13:24:07 +00:00
CCommandProcessorFragment_OpenGL : : SCommand_Init CmdOpenGL ;
CmdOpenGL . m_pTextureMemoryUsage = & m_TextureMemoryUsage ;
CmdBuffer . AddCommand ( CmdOpenGL ) ;
CCommandProcessorFragment_SDL : : SCommand_Init CmdSDL ;
CmdSDL . m_pWindow = m_pWindow ;
CmdSDL . m_GLContext = m_GLContext ;
CmdBuffer . AddCommand ( CmdSDL ) ;
RunBuffer ( & CmdBuffer ) ;
WaitForIdle ( ) ;
}
2012-01-03 20:39:10 +00:00
2017-10-23 16:02:18 +00:00
* pCurrentWidth = * pWidth ;
* pCurrentHeight = * pHeight ;
2016-05-07 19:16:31 +00:00
SDL_ShowWindow ( m_pWindow ) ;
2017-10-23 16:02:18 +00:00
if ( SetWindowScreen ( g_Config . m_GfxScreen ) )
{
// query the current displaymode, when running in fullscreen
// this is required if DPI scaling is active
if ( SdlFlags & SDL_WINDOW_FULLSCREEN )
{
SDL_DisplayMode CurrentDisplayMode ;
SDL_GetCurrentDisplayMode ( g_Config . m_GfxScreen , & CurrentDisplayMode ) ;
* pCurrentWidth = CurrentDisplayMode . w ;
* pCurrentHeight = CurrentDisplayMode . h ;
// since the window is centered, calculate how much the viewport has to be fixed
//int XOverflow = (*pWidth > *pCurrentWidth ? (*pWidth - *pCurrentWidth) : 0);
//int YOverflow = (*pHeight > *pCurrentHeight ? (*pHeight - *pCurrentHeight) : 0);
//TODO: current problem is, that the opengl driver knows about the scaled display,
//so the viewport cannot be adjusted for resolutions, that are higher than allowed by the display driver
CCommandProcessorFragment_SDL : : SCommand_Update_Viewport CmdSDL ;
CmdSDL . m_X = 0 ;
CmdSDL . m_Y = 0 ;
CmdSDL . m_Width = CurrentDisplayMode . w ;
CmdSDL . m_Height = CurrentDisplayMode . h ;
CmdBuffer . AddCommand ( CmdSDL ) ;
RunBuffer ( & CmdBuffer ) ;
WaitForIdle ( ) ;
}
}
2016-05-07 19:16:31 +00:00
2012-01-03 20:39:10 +00:00
// return
return 0 ;
}
int CGraphicsBackend_SDL_OpenGL : : Shutdown ( )
{
// issue a shutdown command
CCommandBuffer CmdBuffer ( 1024 , 512 ) ;
2017-09-13 18:33:58 +00:00
if ( m_UseOpenGL3_3 )
{
2017-09-02 13:24:07 +00:00
CCommandProcessorFragment_OpenGL3_3 : : SCommand_Shutdown Cmd ;
CmdBuffer . AddCommand ( Cmd ) ;
}
2012-01-03 20:39:10 +00:00
CCommandProcessorFragment_SDL : : SCommand_Shutdown Cmd ;
CmdBuffer . AddCommand ( Cmd ) ;
RunBuffer ( & CmdBuffer ) ;
WaitForIdle ( ) ;
2015-07-09 00:08:14 +00:00
2012-01-03 20:39:10 +00:00
// stop and delete the processor
StopProcessor ( ) ;
delete m_pProcessor ;
m_pProcessor = 0 ;
2015-08-24 20:46:28 +00:00
SDL_GL_DeleteContext ( m_GLContext ) ;
SDL_DestroyWindow ( m_pWindow ) ;
2012-01-03 20:39:10 +00:00
SDL_QuitSubSystem ( SDL_INIT_VIDEO ) ;
return 0 ;
}
2012-10-06 21:31:02 +00:00
int CGraphicsBackend_SDL_OpenGL : : MemoryUsage ( ) const
{
return m_TextureMemoryUsage ;
}
2012-01-03 20:39:10 +00:00
void CGraphicsBackend_SDL_OpenGL : : Minimize ( )
{
2015-08-24 20:46:28 +00:00
SDL_MinimizeWindow ( m_pWindow ) ;
2012-01-03 20:39:10 +00:00
}
void CGraphicsBackend_SDL_OpenGL : : Maximize ( )
{
// TODO: SDL
}
2016-04-29 19:07:10 +00:00
bool CGraphicsBackend_SDL_OpenGL : : Fullscreen ( bool State )
{
2016-04-29 22:34:12 +00:00
# if defined(CONF_PLATFORM_MACOSX) // Todo SDL: remove this when fixed (game freezes when losing focus in fullscreen)
return SDL_SetWindowFullscreen ( m_pWindow , State ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0 ) = = 0 ;
# else
2016-04-29 19:07:10 +00:00
return SDL_SetWindowFullscreen ( m_pWindow , State ? SDL_WINDOW_FULLSCREEN : 0 ) = = 0 ;
2016-04-29 22:34:12 +00:00
# endif
}
void CGraphicsBackend_SDL_OpenGL : : SetWindowBordered ( bool State )
{
SDL_SetWindowBordered ( m_pWindow , SDL_bool ( State ) ) ;
}
bool CGraphicsBackend_SDL_OpenGL : : SetWindowScreen ( int Index )
{
if ( Index > = 0 & & Index < m_NumScreens )
{
SDL_Rect ScreenPos ;
if ( SDL_GetDisplayBounds ( Index , & ScreenPos ) = = 0 )
{
SDL_SetWindowPosition ( m_pWindow ,
2016-05-07 14:35:31 +00:00
SDL_WINDOWPOS_CENTERED_DISPLAY ( Index ) ,
SDL_WINDOWPOS_CENTERED_DISPLAY ( Index ) ) ;
2016-04-29 22:34:12 +00:00
return true ;
}
}
return false ;
}
int CGraphicsBackend_SDL_OpenGL : : GetWindowScreen ( )
{
return SDL_GetWindowDisplayIndex ( m_pWindow ) ;
2016-04-29 19:07:10 +00:00
}
2012-01-03 20:39:10 +00:00
int CGraphicsBackend_SDL_OpenGL : : WindowActive ( )
{
2015-08-24 20:46:28 +00:00
return SDL_GetWindowFlags ( m_pWindow ) & SDL_WINDOW_INPUT_FOCUS ;
2012-01-03 20:39:10 +00:00
}
int CGraphicsBackend_SDL_OpenGL : : WindowOpen ( )
{
2015-08-24 20:46:28 +00:00
return SDL_GetWindowFlags ( m_pWindow ) & SDL_WINDOW_SHOWN ;
2014-10-18 14:17:36 +00:00
}
2012-01-03 20:39:10 +00:00
2015-08-24 23:01:38 +00:00
void CGraphicsBackend_SDL_OpenGL : : SetWindowGrab ( bool Grab )
{
SDL_SetWindowGrab ( m_pWindow , Grab ? SDL_TRUE : SDL_FALSE ) ;
}
2014-10-18 14:17:36 +00:00
void CGraphicsBackend_SDL_OpenGL : : NotifyWindow ( )
{
2015-08-25 00:39:48 +00:00
// get window handle
SDL_SysWMinfo info ;
SDL_VERSION ( & info . version ) ;
if ( ! SDL_GetWindowWMInfo ( m_pWindow , & info ) )
{
dbg_msg ( " gfx " , " unable to obtain window handle " ) ;
return ;
}
# if defined(CONF_FAMILY_WINDOWS)
FLASHWINFO desc ;
desc . cbSize = sizeof ( desc ) ;
2015-08-26 02:18:31 +00:00
desc . hwnd = info . info . win . window ;
2015-08-25 00:39:48 +00:00
desc . dwFlags = FLASHW_TRAY ;
desc . uCount = 3 ; // flash 3 times
desc . dwTimeout = 0 ;
FlashWindowEx ( & desc ) ;
# elif defined(SDL_VIDEO_DRIVER_X11) && !defined(CONF_PLATFORM_MACOSX)
Display * dpy = info . info . x11 . display ;
Window win = info . info . x11 . window ;
// Old hints
XWMHints * wmhints ;
wmhints = XAllocWMHints ( ) ;
wmhints - > flags = XUrgencyHint ;
XSetWMHints ( dpy , win , wmhints ) ;
XFree ( wmhints ) ;
// More modern way of notifying
static Atom demandsAttention = XInternAtom ( dpy , " _NET_WM_STATE_DEMANDS_ATTENTION " , true ) ;
static Atom wmState = XInternAtom ( dpy , " _NET_WM_STATE " , true ) ;
XChangeProperty ( dpy , win , wmState , XA_ATOM , 32 , PropModeReplace ,
( unsigned char * ) & demandsAttention , 1 ) ;
# endif
2012-01-03 20:39:10 +00:00
}
IGraphicsBackend * CreateGraphicsBackend ( ) { return new CGraphicsBackend_SDL_OpenGL ; }