2011-12-31 00:06:04 +00:00
/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
/* If you are missing that file, acquire a complete release at teeworlds.com. */
# include <base/detect.h>
# include <base/math.h>
2012-02-05 12:22:39 +00:00
# include <base/tl/threading.h>
2011-12-31 00:06:04 +00:00
2014-01-19 03:02:01 +00:00
# if defined(CONF_FAMILY_UNIX)
# include <pthread.h>
# endif
2011-12-31 00:06:04 +00:00
# include <base/system.h>
2018-02-12 22:14:14 +00:00
# include <pnglite.h>
2011-12-31 00:06:04 +00:00
2020-09-26 19:41:58 +00:00
# include <engine/console.h>
2011-12-31 00:06:04 +00:00
# include <engine/graphics.h>
# include <engine/keys.h>
2020-09-26 19:41:58 +00:00
# include <engine/shared/config.h>
# include <engine/storage.h>
2020-10-09 07:07:05 +00:00
# include <game/generated/client_data.h>
# include <game/generated/client_data7.h>
2020-08-31 11:07:42 +00:00
# include <game/localization.h>
2011-12-31 00:06:04 +00:00
2020-11-18 06:36:19 +00:00
# include <engine/shared/image_manipulation.h>
2017-10-09 16:58:44 +00:00
# include <math.h> // cosf, sinf, log2f
2011-12-31 00:06:04 +00:00
2020-06-19 06:19:40 +00:00
# if defined(CONF_VIDEORECORDER)
2020-09-26 19:41:58 +00:00
# include "video.h"
2020-06-19 06:19:40 +00:00
# endif
2011-12-31 00:11:24 +00:00
# include "graphics_threaded.h"
2021-09-09 11:23:02 +00:00
# include "graphics_threaded_null.h"
2011-12-31 00:06:04 +00:00
static CVideoMode g_aFakeModes [ ] = {
2021-08-21 19:41:51 +00:00
{ 8192 , 4320 , 8192 , 4320 , 0 , 8 , 8 , 8 , 0 } , { 7680 , 4320 , 7680 , 4320 , 0 , 8 , 8 , 8 , 0 } , { 5120 , 2880 , 5120 , 2880 , 0 , 8 , 8 , 8 , 0 } ,
{ 4096 , 2160 , 4096 , 2160 , 0 , 8 , 8 , 8 , 0 } , { 3840 , 2160 , 3840 , 2160 , 0 , 8 , 8 , 8 , 0 } , { 2560 , 1440 , 2560 , 1440 , 0 , 8 , 8 , 8 , 0 } ,
{ 2048 , 1536 , 2048 , 1536 , 0 , 8 , 8 , 8 , 0 } , { 1920 , 2400 , 1920 , 2400 , 0 , 8 , 8 , 8 , 0 } , { 1920 , 1440 , 1920 , 1440 , 0 , 8 , 8 , 8 , 0 } ,
{ 1920 , 1200 , 1920 , 1200 , 0 , 8 , 8 , 8 , 0 } , { 1920 , 1080 , 1920 , 1080 , 0 , 8 , 8 , 8 , 0 } , { 1856 , 1392 , 1856 , 1392 , 0 , 8 , 8 , 8 , 0 } ,
{ 1800 , 1440 , 1800 , 1440 , 0 , 8 , 8 , 8 , 0 } , { 1792 , 1344 , 1792 , 1344 , 0 , 8 , 8 , 8 , 0 } , { 1680 , 1050 , 1680 , 1050 , 0 , 8 , 8 , 8 , 0 } ,
{ 1600 , 1200 , 1600 , 1200 , 0 , 8 , 8 , 8 , 0 } , { 1600 , 1000 , 1600 , 1000 , 0 , 8 , 8 , 8 , 0 } , { 1440 , 1050 , 1440 , 1050 , 0 , 8 , 8 , 8 , 0 } ,
{ 1440 , 900 , 1440 , 900 , 0 , 8 , 8 , 8 , 0 } , { 1400 , 1050 , 1400 , 1050 , 0 , 8 , 8 , 8 , 0 } , { 1368 , 768 , 1368 , 768 , 0 , 8 , 8 , 8 , 0 } ,
{ 1280 , 1024 , 1280 , 1024 , 0 , 8 , 8 , 8 , 0 } , { 1280 , 960 , 1280 , 960 , 0 , 8 , 8 , 8 , 0 } , { 1280 , 800 , 1280 , 800 , 0 , 8 , 8 , 8 , 0 } ,
{ 1280 , 768 , 1280 , 768 , 0 , 8 , 8 , 8 , 0 } , { 1152 , 864 , 1152 , 864 , 0 , 8 , 8 , 8 , 0 } , { 1024 , 768 , 1024 , 768 , 0 , 8 , 8 , 8 , 0 } ,
{ 1024 , 600 , 1024 , 600 , 0 , 8 , 8 , 8 , 0 } , { 800 , 600 , 800 , 600 , 0 , 8 , 8 , 8 , 0 } , { 768 , 576 , 768 , 576 , 0 , 8 , 8 , 8 , 0 } ,
{ 720 , 400 , 720 , 400 , 0 , 8 , 8 , 8 , 0 } , { 640 , 480 , 640 , 480 , 0 , 8 , 8 , 8 , 0 } , { 400 , 300 , 400 , 300 , 0 , 8 , 8 , 8 , 0 } ,
{ 320 , 240 , 320 , 240 , 0 , 8 , 8 , 8 , 0 } ,
{ 8192 , 4320 , 8192 , 4320 , 0 , 5 , 6 , 5 , 0 } , { 7680 , 4320 , 7680 , 4320 , 0 , 5 , 6 , 5 , 0 } , { 5120 , 2880 , 5120 , 2880 , 0 , 5 , 6 , 5 , 0 } ,
{ 4096 , 2160 , 4096 , 2160 , 0 , 5 , 6 , 5 , 0 } , { 3840 , 2160 , 3840 , 2160 , 0 , 5 , 6 , 5 , 0 } , { 2560 , 1440 , 2560 , 1440 , 0 , 5 , 6 , 5 , 0 } ,
{ 2048 , 1536 , 2048 , 1536 , 0 , 5 , 6 , 5 , 0 } , { 1920 , 2400 , 1920 , 2400 , 0 , 5 , 6 , 5 , 0 } , { 1920 , 1440 , 1920 , 1440 , 0 , 5 , 6 , 5 , 0 } ,
{ 1920 , 1200 , 1920 , 1200 , 0 , 5 , 6 , 5 , 0 } , { 1920 , 1080 , 1920 , 1080 , 0 , 5 , 6 , 5 , 0 } , { 1856 , 1392 , 1856 , 1392 , 0 , 5 , 6 , 5 , 0 } ,
{ 1800 , 1440 , 1800 , 1440 , 0 , 5 , 6 , 5 , 0 } , { 1792 , 1344 , 1792 , 1344 , 0 , 5 , 6 , 5 , 0 } , { 1680 , 1050 , 1680 , 1050 , 0 , 5 , 6 , 5 , 0 } ,
{ 1600 , 1200 , 1600 , 1200 , 0 , 5 , 6 , 5 , 0 } , { 1600 , 1000 , 1600 , 1000 , 0 , 5 , 6 , 5 , 0 } , { 1440 , 1050 , 1440 , 1050 , 0 , 5 , 6 , 5 , 0 } ,
{ 1440 , 900 , 1440 , 900 , 0 , 5 , 6 , 5 , 0 } , { 1400 , 1050 , 1400 , 1050 , 0 , 5 , 6 , 5 , 0 } , { 1368 , 768 , 1368 , 768 , 0 , 5 , 6 , 5 , 0 } ,
{ 1280 , 1024 , 1280 , 1024 , 0 , 5 , 6 , 5 , 0 } , { 1280 , 960 , 1280 , 960 , 0 , 5 , 6 , 5 , 0 } , { 1280 , 800 , 1280 , 800 , 0 , 5 , 6 , 5 , 0 } ,
{ 1280 , 768 , 1280 , 768 , 0 , 5 , 6 , 5 , 0 } , { 1152 , 864 , 1152 , 864 , 0 , 5 , 6 , 5 , 0 } , { 1024 , 768 , 1024 , 768 , 0 , 5 , 6 , 5 , 0 } ,
{ 1024 , 600 , 1024 , 600 , 0 , 5 , 6 , 5 , 0 } , { 800 , 600 , 800 , 600 , 0 , 5 , 6 , 5 , 0 } , { 768 , 576 , 768 , 576 , 0 , 5 , 6 , 5 , 0 } ,
{ 720 , 400 , 720 , 400 , 0 , 5 , 6 , 5 , 0 } , { 640 , 480 , 640 , 480 , 0 , 5 , 6 , 5 , 0 } , { 400 , 300 , 400 , 300 , 0 , 5 , 6 , 5 , 0 } ,
{ 320 , 240 , 320 , 240 , 0 , 5 , 6 , 5 , 0 } } ;
2011-12-31 00:06:04 +00:00
2018-03-13 20:47:07 +00:00
void CGraphics_Threaded : : FlushVertices ( bool KeepVertices )
2011-12-31 00:06:04 +00:00
{
CCommandBuffer : : SCommand_Render Cmd ;
2020-09-21 03:57:54 +00:00
int PrimType , PrimCount , NumVerts ;
size_t VertSize = sizeof ( CCommandBuffer : : SVertex ) ;
FlushVerticesImpl ( KeepVertices , PrimType , PrimCount , NumVerts , Cmd , VertSize ) ;
2011-12-31 00:06:04 +00:00
2020-09-21 03:57:54 +00:00
if ( Cmd . m_pVertices ! = NULL )
2012-01-03 21:01:37 +00:00
{
2020-09-21 03:57:54 +00:00
mem_copy ( Cmd . m_pVertices , m_aVertices , VertSize * NumVerts ) ;
2012-01-03 21:01:37 +00:00
}
2018-03-13 20:47:07 +00:00
}
2020-09-26 19:41:58 +00:00
void CGraphics_Threaded : : FlushTextVertices ( int TextureSize , int TextTextureIndex , int TextOutlineTextureIndex , float * pOutlineTextColor )
2018-03-13 20:47:07 +00:00
{
CCommandBuffer : : SCommand_RenderTextStream Cmd ;
2020-09-21 03:57:54 +00:00
int PrimType , PrimCount , NumVerts ;
size_t VertSize = sizeof ( CCommandBuffer : : SVertex ) ;
2018-03-13 20:47:07 +00:00
Cmd . m_TextureSize = TextureSize ;
Cmd . m_TextTextureIndex = TextTextureIndex ;
Cmd . m_TextOutlineTextureIndex = TextOutlineTextureIndex ;
mem_copy ( Cmd . m_aTextOutlineColor , pOutlineTextColor , sizeof ( Cmd . m_aTextOutlineColor ) ) ;
2020-09-21 03:57:54 +00:00
FlushVerticesImpl ( false , PrimType , PrimCount , NumVerts , Cmd , VertSize ) ;
if ( Cmd . m_pVertices ! = NULL )
2018-03-13 20:47:07 +00:00
{
2020-09-21 03:57:54 +00:00
mem_copy ( Cmd . m_pVertices , m_aVertices , VertSize * NumVerts ) ;
2018-03-13 20:47:07 +00:00
}
2020-09-21 03:57:54 +00:00
}
2018-03-13 20:47:07 +00:00
2020-09-21 03:57:54 +00:00
void CGraphics_Threaded : : FlushVerticesTex3D ( )
{
CCommandBuffer : : SCommand_RenderTex3D Cmd ;
int PrimType , PrimCount , NumVerts ;
size_t VertSize = sizeof ( CCommandBuffer : : SVertexTex3DStream ) ;
FlushVerticesImpl ( false , PrimType , PrimCount , NumVerts , Cmd , VertSize ) ;
2018-03-13 20:47:07 +00:00
2020-09-21 03:57:54 +00:00
if ( Cmd . m_pVertices ! = NULL )
{
mem_copy ( Cmd . m_pVertices , m_aVerticesTex3D , VertSize * NumVerts ) ;
2018-03-13 20:47:07 +00:00
}
2011-12-31 00:06:04 +00:00
}
void CGraphics_Threaded : : AddVertices ( int Count )
{
m_NumVertices + = Count ;
2020-10-09 07:07:05 +00:00
if ( ( m_NumVertices + Count ) > = CCommandBuffer : : MAX_VERTICES )
2012-01-01 13:15:35 +00:00
FlushVertices ( ) ;
2011-12-31 00:06:04 +00:00
}
2020-09-21 03:57:54 +00:00
void CGraphics_Threaded : : AddVertices ( int Count , CCommandBuffer : : SVertex * pVertices )
2011-12-31 00:06:04 +00:00
{
2020-09-21 03:57:54 +00:00
AddVertices ( Count ) ;
}
2019-04-26 22:11:15 +00:00
2020-09-21 03:57:54 +00:00
void CGraphics_Threaded : : AddVertices ( int Count , CCommandBuffer : : SVertexTex3DStream * pVertices )
{
m_NumVertices + = Count ;
2020-10-09 07:07:05 +00:00
if ( ( m_NumVertices + Count ) > = CCommandBuffer : : MAX_VERTICES )
2020-09-21 03:57:54 +00:00
FlushVerticesTex3D ( ) ;
2011-12-31 00:06:04 +00:00
}
CGraphics_Threaded : : CGraphics_Threaded ( )
{
m_State . m_ScreenTL . x = 0 ;
m_State . m_ScreenTL . y = 0 ;
m_State . m_ScreenBR . x = 0 ;
m_State . m_ScreenBR . y = 0 ;
m_State . m_ClipEnable = false ;
m_State . m_ClipX = 0 ;
m_State . m_ClipY = 0 ;
m_State . m_ClipW = 0 ;
m_State . m_ClipH = 0 ;
m_State . m_Texture = - 1 ;
m_State . m_BlendMode = CCommandBuffer : : BLEND_NONE ;
2012-01-08 00:47:53 +00:00
m_State . m_WrapMode = CCommandBuffer : : WRAP_REPEAT ;
2011-12-31 00:06:04 +00:00
2011-12-31 09:04:46 +00:00
m_CurrentCommandBuffer = 0 ;
m_pCommandBuffer = 0x0 ;
m_apCommandBuffers [ 0 ] = 0x0 ;
m_apCommandBuffers [ 1 ] = 0x0 ;
2011-12-31 00:06:04 +00:00
m_NumVertices = 0 ;
m_ScreenWidth = - 1 ;
m_ScreenHeight = - 1 ;
2021-08-21 19:41:51 +00:00
m_ScreenRefreshRate = - 1 ;
2011-12-31 00:06:04 +00:00
m_Rotation = 0 ;
m_Drawing = 0 ;
m_TextureMemoryUsage = 0 ;
m_RenderEnable = true ;
m_DoScreenshot = false ;
2020-12-12 16:51:09 +00:00
png_init ( 0 , 0 ) ; // ignore_convention
2011-12-31 00:06:04 +00:00
}
void CGraphics_Threaded : : ClipEnable ( int x , int y , int w , int h )
{
if ( x < 0 )
w + = x ;
if ( y < 0 )
h + = y ;
x = clamp ( x , 0 , ScreenWidth ( ) ) ;
y = clamp ( y , 0 , ScreenHeight ( ) ) ;
2020-09-26 19:41:58 +00:00
w = clamp ( w , 0 , ScreenWidth ( ) - x ) ;
h = clamp ( h , 0 , ScreenHeight ( ) - y ) ;
2011-12-31 00:06:04 +00:00
m_State . m_ClipEnable = true ;
m_State . m_ClipX = x ;
2020-09-26 19:41:58 +00:00
m_State . m_ClipY = ScreenHeight ( ) - ( y + h ) ;
2011-12-31 00:06:04 +00:00
m_State . m_ClipW = w ;
m_State . m_ClipH = h ;
}
void CGraphics_Threaded : : ClipDisable ( )
{
m_State . m_ClipEnable = false ;
}
void CGraphics_Threaded : : BlendNone ( )
{
m_State . m_BlendMode = CCommandBuffer : : BLEND_NONE ;
}
void CGraphics_Threaded : : BlendNormal ( )
{
m_State . m_BlendMode = CCommandBuffer : : BLEND_ALPHA ;
}
void CGraphics_Threaded : : BlendAdditive ( )
{
m_State . m_BlendMode = CCommandBuffer : : BLEND_ADDITIVE ;
}
2012-01-08 00:47:53 +00:00
void CGraphics_Threaded : : WrapNormal ( )
{
m_State . m_WrapMode = CCommandBuffer : : WRAP_REPEAT ;
}
void CGraphics_Threaded : : WrapClamp ( )
{
m_State . m_WrapMode = CCommandBuffer : : WRAP_CLAMP ;
}
2011-12-31 00:06:04 +00:00
int CGraphics_Threaded : : MemoryUsage ( ) const
{
2012-10-06 21:31:02 +00:00
return m_pBackend - > MemoryUsage ( ) ;
2011-12-31 00:06:04 +00:00
}
void CGraphics_Threaded : : MapScreen ( float TopLeftX , float TopLeftY , float BottomRightX , float BottomRightY )
{
m_State . m_ScreenTL . x = TopLeftX ;
m_State . m_ScreenTL . y = TopLeftY ;
m_State . m_ScreenBR . x = BottomRightX ;
m_State . m_ScreenBR . y = BottomRightY ;
}
void CGraphics_Threaded : : GetScreen ( float * pTopLeftX , float * pTopLeftY , float * pBottomRightX , float * pBottomRightY )
{
* pTopLeftX = m_State . m_ScreenTL . x ;
* pTopLeftY = m_State . m_ScreenTL . y ;
* pBottomRightX = m_State . m_ScreenBR . x ;
* pBottomRightY = m_State . m_ScreenBR . y ;
}
void CGraphics_Threaded : : LinesBegin ( )
{
dbg_assert ( m_Drawing = = 0 , " called Graphics()->LinesBegin twice " ) ;
m_Drawing = DRAWING_LINES ;
2020-09-26 19:41:58 +00:00
SetColor ( 1 , 1 , 1 , 1 ) ;
2011-12-31 00:06:04 +00:00
}
void CGraphics_Threaded : : LinesEnd ( )
{
dbg_assert ( m_Drawing = = DRAWING_LINES , " called Graphics()->LinesEnd without begin " ) ;
2012-01-01 13:15:35 +00:00
FlushVertices ( ) ;
2011-12-31 00:06:04 +00:00
m_Drawing = 0 ;
}
void CGraphics_Threaded : : LinesDraw ( const CLineItem * pArray , int Num )
{
dbg_assert ( m_Drawing = = DRAWING_LINES , " called Graphics()->LinesDraw without begin " ) ;
for ( int i = 0 ; i < Num ; + + i )
{
2020-09-26 19:41:58 +00:00
m_aVertices [ m_NumVertices + 2 * i ] . m_Pos . x = pArray [ i ] . m_X0 ;
m_aVertices [ m_NumVertices + 2 * i ] . m_Pos . y = pArray [ i ] . m_Y0 ;
m_aVertices [ m_NumVertices + 2 * i ] . m_Tex = m_aTexture [ 0 ] ;
SetColor ( & m_aVertices [ m_NumVertices + 2 * i ] , 0 ) ;
2018-03-13 20:47:07 +00:00
2020-09-26 19:41:58 +00:00
m_aVertices [ m_NumVertices + 2 * i + 1 ] . m_Pos . x = pArray [ i ] . m_X1 ;
m_aVertices [ m_NumVertices + 2 * i + 1 ] . m_Pos . y = pArray [ i ] . m_Y1 ;
m_aVertices [ m_NumVertices + 2 * i + 1 ] . m_Tex = m_aTexture [ 1 ] ;
SetColor ( & m_aVertices [ m_NumVertices + 2 * i + 1 ] , 1 ) ;
2011-12-31 00:06:04 +00:00
}
2020-09-26 19:41:58 +00:00
AddVertices ( 2 * Num ) ;
2011-12-31 00:06:04 +00:00
}
2016-07-02 08:33:37 +00:00
int CGraphics_Threaded : : UnloadTexture ( CTextureHandle * Index )
2011-12-31 00:06:04 +00:00
{
2016-07-02 08:33:37 +00:00
if ( Index - > Id ( ) = = m_InvalidTexture . Id ( ) )
2011-12-31 00:06:04 +00:00
return 0 ;
2016-07-02 08:33:37 +00:00
if ( ! Index - > IsValid ( ) )
2011-12-31 00:06:04 +00:00
return 0 ;
2011-12-31 08:40:11 +00:00
CCommandBuffer : : SCommand_Texture_Destroy Cmd ;
2016-07-02 08:33:37 +00:00
Cmd . m_Slot = Index - > Id ( ) ;
2021-04-07 17:03:07 +00:00
AddCmd (
Cmd , [ ] { return true ; } , " failed to unload texture. " ) ;
2011-12-31 08:40:11 +00:00
2016-07-02 08:33:37 +00:00
m_TextureIndices [ Index - > Id ( ) ] = m_FirstFreeTexture ;
m_FirstFreeTexture = Index - > Id ( ) ;
Index - > Invalidate ( ) ;
2011-12-31 00:06:04 +00:00
return 0 ;
}
2020-10-09 07:07:05 +00:00
int CGraphics_Threaded : : UnloadTextureNew ( CTextureHandle & TextureHandle )
{
2016-07-02 08:33:37 +00:00
int Ret = UnloadTexture ( & TextureHandle ) ;
2020-10-09 07:07:05 +00:00
TextureHandle = IGraphics : : CTextureHandle ( ) ;
return Ret ;
}
2011-12-31 08:40:11 +00:00
static int ImageFormatToTexFormat ( int Format )
{
2020-09-26 19:41:58 +00:00
if ( Format = = CImageInfo : : FORMAT_RGB )
return CCommandBuffer : : TEXFORMAT_RGB ;
if ( Format = = CImageInfo : : FORMAT_RGBA )
return CCommandBuffer : : TEXFORMAT_RGBA ;
if ( Format = = CImageInfo : : FORMAT_ALPHA )
return CCommandBuffer : : TEXFORMAT_ALPHA ;
2011-12-31 08:40:11 +00:00
return CCommandBuffer : : TEXFORMAT_RGBA ;
}
2011-12-31 00:06:04 +00:00
2012-10-06 21:31:02 +00:00
static int ImageFormatToPixelSize ( int Format )
{
switch ( Format )
{
case CImageInfo : : FORMAT_RGB : return 3 ;
case CImageInfo : : FORMAT_ALPHA : return 1 ;
default : return 4 ;
}
}
2012-08-12 10:41:50 +00:00
int CGraphics_Threaded : : LoadTextureRawSub ( CTextureHandle TextureID , int x , int y , int Width , int Height , int Format , const void * pData )
2011-12-31 00:06:04 +00:00
{
2011-12-31 08:40:11 +00:00
CCommandBuffer : : SCommand_Texture_Update Cmd ;
2012-08-12 12:02:50 +00:00
Cmd . m_Slot = TextureID . Id ( ) ;
2011-12-31 08:40:11 +00:00
Cmd . m_X = x ;
Cmd . m_Y = y ;
Cmd . m_Width = Width ;
Cmd . m_Height = Height ;
Cmd . m_Format = ImageFormatToTexFormat ( Format ) ;
// calculate memory usage
2020-09-26 19:41:58 +00:00
int MemSize = Width * Height * ImageFormatToPixelSize ( Format ) ;
2011-12-31 08:40:11 +00:00
// copy texture data
2018-04-09 09:56:39 +00:00
void * pTmpData = malloc ( MemSize ) ;
2011-12-31 08:40:11 +00:00
mem_copy ( pTmpData , pData , MemSize ) ;
Cmd . m_pData = pTmpData ;
2019-04-26 22:11:15 +00:00
2021-04-07 17:03:07 +00:00
AddCmd (
Cmd , [ ] { return true ; } , " failed to load raw sub texture. " ) ;
2011-12-31 08:40:11 +00:00
return 0 ;
}
2011-12-31 00:06:04 +00:00
2020-10-09 07:07:05 +00:00
IGraphics : : CTextureHandle CGraphics_Threaded : : LoadSpriteTextureImpl ( CImageInfo & FromImageInfo , int x , int y , int w , int h )
{
int bpp = ImageFormatToPixelSize ( FromImageInfo . m_Format ) ;
m_SpriteHelper . resize ( w * h * bpp ) ;
CopyTextureFromTextureBufferSub ( & m_SpriteHelper [ 0 ] , w , h , ( uint8_t * ) FromImageInfo . m_pData , FromImageInfo . m_Width , FromImageInfo . m_Height , bpp , x , y , w , h ) ;
IGraphics : : CTextureHandle RetHandle = LoadTextureRaw ( w , h , FromImageInfo . m_Format , & m_SpriteHelper [ 0 ] , FromImageInfo . m_Format , 0 ) ;
return RetHandle ;
}
IGraphics : : CTextureHandle CGraphics_Threaded : : LoadSpriteTexture ( CImageInfo & FromImageInfo , CDataSprite * pSprite )
{
int imggx = FromImageInfo . m_Width / pSprite - > m_pSet - > m_Gridx ;
int imggy = FromImageInfo . m_Height / pSprite - > m_pSet - > m_Gridy ;
int x = pSprite - > m_X * imggx ;
int y = pSprite - > m_Y * imggy ;
int w = pSprite - > m_W * imggx ;
int h = pSprite - > m_H * imggy ;
return LoadSpriteTextureImpl ( FromImageInfo , x , y , w , h ) ;
}
IGraphics : : CTextureHandle CGraphics_Threaded : : LoadSpriteTexture ( CImageInfo & FromImageInfo , client_data7 : : CDataSprite * pSprite )
{
int imggx = FromImageInfo . m_Width / pSprite - > m_pSet - > m_Gridx ;
int imggy = FromImageInfo . m_Height / pSprite - > m_pSet - > m_Gridy ;
int x = pSprite - > m_X * imggx ;
int y = pSprite - > m_Y * imggy ;
int w = pSprite - > m_W * imggx ;
int h = pSprite - > m_H * imggy ;
return LoadSpriteTextureImpl ( FromImageInfo , x , y , w , h ) ;
}
bool CGraphics_Threaded : : IsImageSubFullyTransparent ( CImageInfo & FromImageInfo , int x , int y , int w , int h )
{
if ( FromImageInfo . m_Format = = CImageInfo : : FORMAT_ALPHA | | FromImageInfo . m_Format = = CImageInfo : : FORMAT_RGBA )
{
uint8_t * pImgData = ( uint8_t * ) FromImageInfo . m_pData ;
int bpp = ImageFormatToPixelSize ( FromImageInfo . m_Format ) ;
for ( int iy = 0 ; iy < h ; + + iy )
{
for ( int ix = 0 ; ix < w ; + + ix )
{
int RealOffset = ( x + ix ) * bpp + ( y + iy ) * bpp * FromImageInfo . m_Width ;
if ( pImgData [ RealOffset + ( bpp - 1 ) ] > 0 )
return false ;
}
}
return true ;
}
return false ;
}
bool CGraphics_Threaded : : IsSpriteTextureFullyTransparent ( CImageInfo & FromImageInfo , client_data7 : : CDataSprite * pSprite )
{
int imggx = FromImageInfo . m_Width / pSprite - > m_pSet - > m_Gridx ;
int imggy = FromImageInfo . m_Height / pSprite - > m_pSet - > m_Gridy ;
int x = pSprite - > m_X * imggx ;
int y = pSprite - > m_Y * imggy ;
int w = pSprite - > m_W * imggx ;
int h = pSprite - > m_H * imggy ;
return IsImageSubFullyTransparent ( FromImageInfo , x , y , w , h ) ;
}
2020-08-29 10:49:45 +00:00
IGraphics : : CTextureHandle CGraphics_Threaded : : LoadTextureRaw ( int Width , int Height , int Format , const void * pData , int StoreFormat , int Flags , const char * pTexName )
2011-12-31 08:40:11 +00:00
{
2011-12-31 00:06:04 +00:00
// don't waste memory on texture if we are stress testing
2017-06-02 18:45:09 +00:00
# ifdef CONF_DEBUG
2011-12-31 00:06:04 +00:00
if ( g_Config . m_DbgStress )
2011-12-31 08:40:11 +00:00
return m_InvalidTexture ;
2017-06-02 18:45:09 +00:00
# endif
2011-12-31 00:06:04 +00:00
2020-09-15 20:19:50 +00:00
if ( ( Flags & IGraphics : : TEXLOAD_TO_2D_ARRAY_TEXTURE ) ! = 0 | | ( Flags & IGraphics : : TEXLOAD_TO_3D_TEXTURE ) ! = 0 )
{
if ( Width = = 0 | | ( Width % 16 ) ! = 0 | | Height = = 0 | | ( Height % 16 ) ! = 0 )
{
2020-10-02 13:43:52 +00:00
SWarning NewWarning ;
2020-09-15 20:19:50 +00:00
char aText [ 128 ] ;
aText [ 0 ] = ' \0 ' ;
if ( pTexName )
{
str_format ( aText , sizeof ( aText ) , " \" %s \" " , pTexName ) ;
}
2021-02-13 10:30:19 +00:00
str_format ( NewWarning . m_aWarningMsg , sizeof ( NewWarning . m_aWarningMsg ) , Localize ( " The width of texture %s is not divisible by %d, or the height is not divisible by %d, which might cause visual bugs. " ) , aText , 16 , 16 ) ;
2020-09-15 20:19:50 +00:00
m_Warnings . emplace_back ( NewWarning ) ;
}
}
if ( Width = = 0 | | Height = = 0 )
return IGraphics : : CTextureHandle ( ) ;
2011-12-31 00:06:04 +00:00
// grab texture
2011-12-31 08:40:11 +00:00
int Tex = m_FirstFreeTexture ;
2020-11-18 11:41:20 +00:00
if ( Tex = = - 1 )
{
size_t CurSize = m_TextureIndices . size ( ) ;
m_TextureIndices . resize ( CurSize * 2 ) ;
for ( size_t i = 0 ; i < CurSize - 1 ; + + i )
{
m_TextureIndices [ CurSize + i ] = CurSize + i + 1 ;
}
m_TextureIndices . back ( ) = - 1 ;
Tex = CurSize ;
}
m_FirstFreeTexture = m_TextureIndices [ Tex ] ;
m_TextureIndices [ Tex ] = - 1 ;
2011-12-31 00:06:04 +00:00
2011-12-31 08:40:11 +00:00
CCommandBuffer : : SCommand_Texture_Create Cmd ;
Cmd . m_Slot = Tex ;
Cmd . m_Width = Width ;
Cmd . m_Height = Height ;
2012-10-06 21:31:02 +00:00
Cmd . m_PixelSize = ImageFormatToPixelSize ( Format ) ;
2011-12-31 08:40:11 +00:00
Cmd . m_Format = ImageFormatToTexFormat ( Format ) ;
Cmd . m_StoreFormat = ImageFormatToTexFormat ( StoreFormat ) ;
2011-12-31 00:06:04 +00:00
2011-12-31 10:18:55 +00:00
// flags
Cmd . m_Flags = 0 ;
2020-09-26 19:41:58 +00:00
if ( Flags & IGraphics : : TEXLOAD_NOMIPMAPS )
2011-12-31 10:18:55 +00:00
Cmd . m_Flags | = CCommandBuffer : : TEXFLAG_NOMIPMAPS ;
2020-09-26 19:41:58 +00:00
if ( ( Flags & IGraphics : : TEXLOAD_TO_2D_ARRAY_TEXTURE ) ! = 0 )
2020-08-19 05:05:51 +00:00
Cmd . m_Flags | = CCommandBuffer : : TEXFLAG_TO_2D_ARRAY_TEXTURE ;
2020-09-26 19:41:58 +00:00
if ( ( Flags & IGraphics : : TEXLOAD_TO_3D_TEXTURE ) ! = 0 )
2020-08-19 05:05:51 +00:00
Cmd . m_Flags | = CCommandBuffer : : TEXFLAG_TO_3D_TEXTURE ;
2020-09-26 19:41:58 +00:00
if ( ( Flags & IGraphics : : TEXLOAD_TO_2D_ARRAY_TEXTURE_SINGLE_LAYER ) ! = 0 )
2020-08-19 05:05:51 +00:00
Cmd . m_Flags | = CCommandBuffer : : TEXFLAG_TO_2D_ARRAY_TEXTURE_SINGLE_LAYER ;
2020-09-26 19:41:58 +00:00
if ( ( Flags & IGraphics : : TEXLOAD_TO_3D_TEXTURE_SINGLE_LAYER ) ! = 0 )
2020-08-19 05:05:51 +00:00
Cmd . m_Flags | = CCommandBuffer : : TEXFLAG_TO_3D_TEXTURE_SINGLE_LAYER ;
2020-09-26 19:41:58 +00:00
if ( ( Flags & IGraphics : : TEXLOAD_NO_2D_TEXTURE ) ! = 0 )
2020-08-23 06:25:21 +00:00
Cmd . m_Flags | = CCommandBuffer : : TEXFLAG_NO_2D_TEXTURE ;
2011-12-31 10:18:55 +00:00
2011-12-31 08:40:11 +00:00
// copy texture data
2020-09-26 19:41:58 +00:00
int MemSize = Width * Height * Cmd . m_PixelSize ;
2018-04-09 09:56:39 +00:00
void * pTmpData = malloc ( MemSize ) ;
2011-12-31 08:40:11 +00:00
mem_copy ( pTmpData , pData , MemSize ) ;
Cmd . m_pData = pTmpData ;
2011-12-31 00:06:04 +00:00
2021-04-07 17:03:07 +00:00
AddCmd (
Cmd , [ ] { return true ; } , " failed to load raw texture. " ) ;
2011-12-31 09:04:46 +00:00
2012-08-12 10:41:50 +00:00
return CreateTextureHandle ( Tex ) ;
2011-12-31 00:06:04 +00:00
}
// simple uncompressed RGBA loaders
2012-08-12 10:41:50 +00:00
IGraphics : : CTextureHandle CGraphics_Threaded : : LoadTexture ( const char * pFilename , int StorageType , int StoreFormat , int Flags )
2011-12-31 00:06:04 +00:00
{
int l = str_length ( pFilename ) ;
2012-08-12 12:02:50 +00:00
IGraphics : : CTextureHandle ID ;
2011-12-31 00:06:04 +00:00
CImageInfo Img ;
if ( l < 3 )
2012-08-12 10:41:50 +00:00
return CTextureHandle ( ) ;
2011-12-31 00:06:04 +00:00
if ( LoadPNG ( & Img , pFilename , StorageType ) )
{
2018-03-13 20:47:07 +00:00
if ( StoreFormat = = CImageInfo : : FORMAT_AUTO )
2011-12-31 00:06:04 +00:00
StoreFormat = Img . m_Format ;
2020-08-29 10:49:45 +00:00
ID = LoadTextureRaw ( Img . m_Width , Img . m_Height , Img . m_Format , Img . m_pData , StoreFormat , Flags , pFilename ) ;
2018-04-09 09:56:39 +00:00
free ( Img . m_pData ) ;
2012-08-12 12:02:50 +00:00
if ( ID . Id ( ) ! = m_InvalidTexture . Id ( ) & & g_Config . m_Debug )
2011-12-31 00:06:04 +00:00
dbg_msg ( " graphics/texture " , " loaded %s " , pFilename ) ;
2012-08-12 12:02:50 +00:00
return ID ;
2011-12-31 00:06:04 +00:00
}
return m_InvalidTexture ;
}
int CGraphics_Threaded : : LoadPNG ( CImageInfo * pImg , const char * pFilename , int StorageType )
{
2021-09-13 08:06:34 +00:00
char aCompleteFilename [ IO_MAX_PATH_LENGTH ] ;
2011-12-31 00:06:04 +00:00
unsigned char * pBuffer ;
png_t Png ; // ignore_convention
// open file for reading
IOHANDLE File = m_pStorage - > OpenFile ( pFilename , IOFLAG_READ , StorageType , aCompleteFilename , sizeof ( aCompleteFilename ) ) ;
if ( File )
io_close ( File ) ;
else
{
dbg_msg ( " game/png " , " failed to open file. filename='%s' " , pFilename ) ;
return 0 ;
}
int Error = png_open_file ( & Png , aCompleteFilename ) ; // ignore_convention
if ( Error ! = PNG_NO_ERROR )
{
2020-09-30 16:03:06 +00:00
dbg_msg ( " game/png " , " failed to open file. filename='%s', pnglite: %s " , aCompleteFilename , png_error_string ( Error ) ) ;
2011-12-31 00:06:04 +00:00
if ( Error ! = PNG_FILE_ERROR )
png_close_file ( & Png ) ; // ignore_convention
return 0 ;
}
if ( Png . depth ! = 8 | | ( Png . color_type ! = PNG_TRUECOLOR & & Png . color_type ! = PNG_TRUECOLOR_ALPHA ) ) // ignore_convention
{
dbg_msg ( " game/png " , " invalid format. filename='%s' " , aCompleteFilename ) ;
png_close_file ( & Png ) ; // ignore_convention
return 0 ;
}
2020-10-05 17:03:14 +00:00
pBuffer = ( unsigned char * ) malloc ( ( size_t ) Png . width * Png . height * Png . bpp ) ; // ignore_convention
2020-09-30 16:03:06 +00:00
Error = png_get_data ( & Png , pBuffer ) ; // ignore_convention
if ( Error ! = PNG_NO_ERROR )
{
dbg_msg ( " game/png " , " failed to read image. filename='%s', pnglite: %s " , aCompleteFilename , png_error_string ( Error ) ) ;
free ( pBuffer ) ;
png_close_file ( & Png ) ; // ignore_convention
return 0 ;
}
2011-12-31 00:06:04 +00:00
png_close_file ( & Png ) ; // ignore_convention
pImg - > m_Width = Png . width ; // ignore_convention
pImg - > m_Height = Png . height ; // ignore_convention
if ( Png . color_type = = PNG_TRUECOLOR ) // ignore_convention
pImg - > m_Format = CImageInfo : : FORMAT_RGB ;
else if ( Png . color_type = = PNG_TRUECOLOR_ALPHA ) // ignore_convention
pImg - > m_Format = CImageInfo : : FORMAT_RGBA ;
2020-10-12 16:50:23 +00:00
else
{
free ( pBuffer ) ;
return 0 ;
}
2011-12-31 00:06:04 +00:00
pImg - > m_pData = pBuffer ;
return 1 ;
}
2020-11-25 12:05:53 +00:00
void CGraphics_Threaded : : FreePNG ( CImageInfo * pImg )
{
free ( pImg - > m_pData ) ;
pImg - > m_pData = NULL ;
}
2020-11-18 06:36:19 +00:00
bool CGraphics_Threaded : : CheckImageDivisibility ( const char * pFileName , CImageInfo & Img , int DivX , int DivY , bool AllowResize )
{
dbg_assert ( DivX ! = 0 & & DivY ! = 0 , " Passing 0 to this function is not allowed. " ) ;
bool ImageIsValid = true ;
bool WidthBroken = Img . m_Width = = 0 | | ( Img . m_Width % DivX ) ! = 0 ;
bool HeightBroken = Img . m_Height = = 0 | | ( Img . m_Height % DivY ) ! = 0 ;
if ( WidthBroken | | HeightBroken )
{
SWarning NewWarning ;
str_format ( NewWarning . m_aWarningMsg , sizeof ( NewWarning . m_aWarningMsg ) , Localize ( " The width of texture %s is not divisible by %d, or the height is not divisible by %d, which might cause visual bugs. " ) , pFileName , DivX , DivY ) ;
m_Warnings . emplace_back ( NewWarning ) ;
ImageIsValid = false ;
}
if ( AllowResize & & ! ImageIsValid & & Img . m_Width > 0 & & Img . m_Height > 0 )
{
int NewWidth = DivX ;
int NewHeight = DivY ;
if ( WidthBroken )
{
NewWidth = maximum < int > ( HighestBit ( Img . m_Width ) , DivX ) ;
NewHeight = ( NewWidth / DivX ) * DivY ;
}
else
{
NewHeight = maximum < int > ( HighestBit ( Img . m_Height ) , DivY ) ;
NewWidth = ( NewHeight / DivY ) * DivX ;
}
int ColorChannelCount = 4 ;
if ( Img . m_Format = = CImageInfo : : FORMAT_ALPHA )
ColorChannelCount = 1 ;
else if ( Img . m_Format = = CImageInfo : : FORMAT_RGB )
ColorChannelCount = 3 ;
else if ( Img . m_Format = = CImageInfo : : FORMAT_RGBA )
ColorChannelCount = 4 ;
uint8_t * pNewImg = ResizeImage ( ( uint8_t * ) Img . m_pData , Img . m_Width , Img . m_Height , NewWidth , NewHeight , ColorChannelCount ) ;
free ( Img . m_pData ) ;
Img . m_pData = pNewImg ;
Img . m_Width = NewWidth ;
Img . m_Height = NewHeight ;
ImageIsValid = true ;
}
return ImageIsValid ;
}
2020-09-10 22:42:42 +00:00
void CGraphics_Threaded : : CopyTextureBufferSub ( uint8_t * pDestBuffer , uint8_t * pSourceBuffer , int FullWidth , int FullHeight , int ColorChannelCount , int SubOffsetX , int SubOffsetY , int SubCopyWidth , int SubCopyHeight )
2020-09-08 13:11:32 +00:00
{
2020-09-10 22:42:42 +00:00
for ( int Y = 0 ; Y < SubCopyHeight ; + + Y )
2020-09-08 13:11:32 +00:00
{
2020-09-10 22:42:42 +00:00
int ImgOffset = ( ( SubOffsetY + Y ) * FullWidth * ColorChannelCount ) + ( SubOffsetX * ColorChannelCount ) ;
int CopySize = SubCopyWidth * ColorChannelCount ;
2020-09-08 13:11:32 +00:00
mem_copy ( & pDestBuffer [ ImgOffset ] , & pSourceBuffer [ ImgOffset ] , CopySize ) ;
}
}
2020-10-09 07:07:05 +00:00
void CGraphics_Threaded : : CopyTextureFromTextureBufferSub ( uint8_t * pDestBuffer , int DestWidth , int DestHeight , uint8_t * pSourceBuffer , int SrcWidth , int SrcHeight , int ColorChannelCount , int SrcSubOffsetX , int SrcSubOffsetY , int SrcSubCopyWidth , int SrcSubCopyHeight )
{
for ( int Y = 0 ; Y < SrcSubCopyHeight ; + + Y )
{
int SrcImgOffset = ( ( SrcSubOffsetY + Y ) * SrcWidth * ColorChannelCount ) + ( SrcSubOffsetX * ColorChannelCount ) ;
int DstImgOffset = ( Y * DestWidth * ColorChannelCount ) ;
int CopySize = SrcSubCopyWidth * ColorChannelCount ;
mem_copy ( & pDestBuffer [ DstImgOffset ] , & pSourceBuffer [ SrcImgOffset ] , CopySize ) ;
}
}
2012-01-01 13:15:35 +00:00
void CGraphics_Threaded : : KickCommandBuffer ( )
{
2012-01-03 20:39:10 +00:00
m_pBackend - > RunBuffer ( m_pCommandBuffer ) ;
2012-01-01 13:15:35 +00:00
// swap buffer
m_CurrentCommandBuffer ^ = 1 ;
m_pCommandBuffer = m_apCommandBuffers [ m_CurrentCommandBuffer ] ;
m_pCommandBuffer - > Reset ( ) ;
}
2014-01-19 03:02:01 +00:00
void CGraphics_Threaded : : ScreenshotDirect ( )
{
2012-01-01 13:15:35 +00:00
// add swap command
CImageInfo Image ;
mem_zero ( & Image , sizeof ( Image ) ) ;
CCommandBuffer : : SCommand_Screenshot Cmd ;
Cmd . m_pImage = & Image ;
2021-04-07 17:03:07 +00:00
AddCmd (
Cmd , [ ] { return true ; } , " failed to take screenshot. " ) ;
2011-12-31 00:06:04 +00:00
2012-01-01 13:15:35 +00:00
// kick the buffer and wait for the result
2014-03-29 16:04:06 +00:00
KickCommandBuffer ( ) ;
WaitForIdle ( ) ;
2012-01-01 13:15:35 +00:00
if ( Image . m_pData )
2011-12-31 00:06:04 +00:00
{
2012-01-01 13:15:35 +00:00
// find filename
2011-12-31 00:06:04 +00:00
char aWholePath [ 1024 ] ;
png_t Png ; // ignore_convention
2014-03-29 16:04:06 +00:00
IOHANDLE File = m_pStorage - > OpenFile ( m_aScreenshotName , IOFLAG_WRITE , IStorage : : TYPE_SAVE , aWholePath , sizeof ( aWholePath ) ) ;
2011-12-31 00:06:04 +00:00
if ( File )
io_close ( File ) ;
// save png
char aBuf [ 256 ] ;
str_format ( aBuf , sizeof ( aBuf ) , " saved screenshot to '%s' " , aWholePath ) ;
2021-03-30 09:39:38 +00:00
m_pConsole - > Print ( IConsole : : OUTPUT_LEVEL_STANDARD , " client " , aBuf , ColorRGBA { 1.0f , 0.6f , 0.3f , 1.0f } ) ;
2011-12-31 00:06:04 +00:00
png_open_file_write ( & Png , aWholePath ) ; // ignore_convention
2021-04-30 23:16:03 +00:00
png_set_data ( & Png , Image . m_Width , Image . m_Height , 8 , PNG_TRUECOLOR_ALPHA , ( unsigned char * ) Image . m_pData ) ; // ignore_convention
2011-12-31 00:06:04 +00:00
png_close_file ( & Png ) ; // ignore_convention
2018-04-09 09:56:39 +00:00
free ( Image . m_pData ) ;
2012-01-01 13:15:35 +00:00
}
2011-12-31 00:06:04 +00:00
}
2012-08-12 10:41:50 +00:00
void CGraphics_Threaded : : TextureSet ( CTextureHandle TextureID )
2011-12-31 00:06:04 +00:00
{
dbg_assert ( m_Drawing = = 0 , " called Graphics()->TextureSet within begin " ) ;
2012-08-12 12:02:50 +00:00
m_State . m_Texture = TextureID . Id ( ) ;
2011-12-31 00:06:04 +00:00
}
void CGraphics_Threaded : : Clear ( float r , float g , float b )
{
CCommandBuffer : : SCommand_Clear Cmd ;
Cmd . m_Color . r = r ;
Cmd . m_Color . g = g ;
Cmd . m_Color . b = b ;
Cmd . m_Color . a = 0 ;
2021-04-07 17:03:07 +00:00
AddCmd (
Cmd , [ ] { return true ; } , " failed to clear graphics. " ) ;
2011-12-31 00:06:04 +00:00
}
void CGraphics_Threaded : : QuadsBegin ( )
{
dbg_assert ( m_Drawing = = 0 , " called Graphics()->QuadsBegin twice " ) ;
m_Drawing = DRAWING_QUADS ;
2018-03-13 20:47:07 +00:00
QuadsSetSubset ( 0 , 0 , 1 , 1 ) ;
2011-12-31 00:06:04 +00:00
QuadsSetRotation ( 0 ) ;
2018-03-13 20:47:07 +00:00
SetColor ( 1 , 1 , 1 , 1 ) ;
2011-12-31 00:06:04 +00:00
}
void CGraphics_Threaded : : QuadsEnd ( )
{
dbg_assert ( m_Drawing = = DRAWING_QUADS , " called Graphics()->QuadsEnd without begin " ) ;
2012-01-01 13:15:35 +00:00
FlushVertices ( ) ;
2011-12-31 00:06:04 +00:00
m_Drawing = 0 ;
}
2018-03-13 20:47:07 +00:00
void CGraphics_Threaded : : TextQuadsBegin ( )
{
QuadsBegin ( ) ;
}
2020-09-26 19:41:58 +00:00
void CGraphics_Threaded : : TextQuadsEnd ( int TextureSize , int TextTextureIndex , int TextOutlineTextureIndex , float * pOutlineTextColor )
2018-03-13 20:47:07 +00:00
{
dbg_assert ( m_Drawing = = DRAWING_QUADS , " called Graphics()->TextQuadsEnd without begin " ) ;
FlushTextVertices ( TextureSize , TextTextureIndex , TextOutlineTextureIndex , pOutlineTextColor ) ;
m_Drawing = 0 ;
}
2020-09-21 03:57:54 +00:00
void CGraphics_Threaded : : QuadsTex3DBegin ( )
{
QuadsBegin ( ) ;
}
void CGraphics_Threaded : : QuadsTex3DEnd ( )
{
dbg_assert ( m_Drawing = = DRAWING_QUADS , " called Graphics()->QuadsEnd without begin " ) ;
FlushVerticesTex3D ( ) ;
m_Drawing = 0 ;
}
2020-10-20 17:11:19 +00:00
void CGraphics_Threaded : : TrianglesBegin ( )
{
dbg_assert ( m_Drawing = = 0 , " called Graphics()->TrianglesBegin twice " ) ;
m_Drawing = DRAWING_TRIANGLES ;
QuadsSetSubset ( 0 , 0 , 1 , 1 ) ;
QuadsSetRotation ( 0 ) ;
SetColor ( 1 , 1 , 1 , 1 ) ;
}
void CGraphics_Threaded : : TrianglesEnd ( )
{
dbg_assert ( m_Drawing = = DRAWING_TRIANGLES , " called Graphics()->TrianglesEnd without begin " ) ;
FlushVertices ( ) ;
m_Drawing = 0 ;
}
2018-03-13 20:47:07 +00:00
void CGraphics_Threaded : : QuadsEndKeepVertices ( )
{
dbg_assert ( m_Drawing = = DRAWING_QUADS , " called Graphics()->QuadsEndKeepVertices without begin " ) ;
FlushVertices ( true ) ;
m_Drawing = 0 ;
}
void CGraphics_Threaded : : QuadsDrawCurrentVertices ( bool KeepVertices )
{
m_Drawing = DRAWING_QUADS ;
FlushVertices ( KeepVertices ) ;
m_Drawing = 0 ;
}
2011-12-31 00:06:04 +00:00
void CGraphics_Threaded : : QuadsSetRotation ( float Angle )
{
m_Rotation = Angle ;
}
2020-09-26 19:41:58 +00:00
inline void clampf ( float & Value , float Min , float Max )
2017-09-27 12:52:06 +00:00
{
2020-09-26 19:41:58 +00:00
if ( Value > Max )
Value = Max ;
else if ( Value < Min )
Value = Min ;
2017-09-27 10:16:34 +00:00
}
2011-12-31 00:06:04 +00:00
void CGraphics_Threaded : : SetColorVertex ( const CColorVertex * pArray , int Num )
{
dbg_assert ( m_Drawing ! = 0 , " called Graphics()->SetColorVertex without begin " ) ;
for ( int i = 0 ; i < Num ; + + i )
{
2018-03-13 20:47:07 +00:00
float r = pArray [ i ] . m_R , g = pArray [ i ] . m_G , b = pArray [ i ] . m_B , a = pArray [ i ] . m_A ;
clampf ( r , 0.f , 1.f ) ;
clampf ( g , 0.f , 1.f ) ;
clampf ( b , 0.f , 1.f ) ;
clampf ( a , 0.f , 1.f ) ;
2020-09-26 19:41:58 +00:00
m_aColor [ pArray [ i ] . m_Index ] . r = ( unsigned char ) ( r * 255.f ) ;
m_aColor [ pArray [ i ] . m_Index ] . g = ( unsigned char ) ( g * 255.f ) ;
m_aColor [ pArray [ i ] . m_Index ] . b = ( unsigned char ) ( b * 255.f ) ;
m_aColor [ pArray [ i ] . m_Index ] . a = ( unsigned char ) ( a * 255.f ) ;
2011-12-31 00:06:04 +00:00
}
}
void CGraphics_Threaded : : SetColor ( float r , float g , float b , float a )
{
2018-03-13 20:47:07 +00:00
clampf ( r , 0.f , 1.f ) ;
clampf ( g , 0.f , 1.f ) ;
clampf ( b , 0.f , 1.f ) ;
clampf ( a , 0.f , 1.f ) ;
r * = 255.f ;
g * = 255.f ;
b * = 255.f ;
a * = 255.f ;
2019-04-26 22:11:15 +00:00
2020-10-26 14:14:07 +00:00
for ( auto & Color : m_aColor )
2018-03-13 20:47:07 +00:00
{
2020-10-26 14:14:07 +00:00
Color . r = ( unsigned char ) ( r ) ;
Color . g = ( unsigned char ) ( g ) ;
Color . b = ( unsigned char ) ( b ) ;
Color . a = ( unsigned char ) ( a ) ;
2018-03-13 20:47:07 +00:00
}
2011-12-31 00:06:04 +00:00
}
2019-04-26 22:11:15 +00:00
void CGraphics_Threaded : : SetColor ( ColorRGBA rgb )
{
SetColor ( rgb . r , rgb . g , rgb . b , rgb . a ) ;
}
2020-09-03 12:08:26 +00:00
void CGraphics_Threaded : : SetColor4 ( vec4 TopLeft , vec4 TopRight , vec4 BottomLeft , vec4 BottomRight )
{
dbg_assert ( m_Drawing ! = 0 , " called Graphics()->SetColor without begin " ) ;
CColorVertex Array [ 4 ] = {
CColorVertex ( 0 , TopLeft . r , TopLeft . g , TopLeft . b , TopLeft . a ) ,
CColorVertex ( 1 , TopRight . r , TopRight . g , TopRight . b , TopRight . a ) ,
CColorVertex ( 2 , BottomRight . r , BottomRight . g , BottomRight . b , BottomRight . a ) ,
CColorVertex ( 3 , BottomLeft . r , BottomLeft . g , BottomLeft . b , BottomLeft . a ) } ;
SetColorVertex ( Array , 4 ) ;
}
2018-03-13 20:47:07 +00:00
void CGraphics_Threaded : : ChangeColorOfCurrentQuadVertices ( float r , float g , float b , float a )
2017-09-27 10:16:34 +00:00
{
2018-03-13 20:47:07 +00:00
clampf ( r , 0.f , 1.f ) ;
clampf ( g , 0.f , 1.f ) ;
clampf ( b , 0.f , 1.f ) ;
clampf ( a , 0.f , 1.f ) ;
2020-09-26 19:41:58 +00:00
m_aColor [ 0 ] . r = ( unsigned char ) ( r * 255.f ) ;
m_aColor [ 0 ] . g = ( unsigned char ) ( g * 255.f ) ;
m_aColor [ 0 ] . b = ( unsigned char ) ( b * 255.f ) ;
m_aColor [ 0 ] . a = ( unsigned char ) ( a * 255.f ) ;
2018-03-13 20:47:07 +00:00
for ( int i = 0 ; i < m_NumVertices ; + + i )
2017-09-27 10:16:34 +00:00
{
2018-03-13 20:47:07 +00:00
SetColor ( & m_aVertices [ i ] , 0 ) ;
2017-09-27 10:16:34 +00:00
}
}
2019-04-06 15:06:12 +00:00
void CGraphics_Threaded : : ChangeColorOfQuadVertices ( int QuadOffset , unsigned char r , unsigned char g , unsigned char b , unsigned char a )
{
2020-08-18 18:26:35 +00:00
if ( g_Config . m_GfxQuadAsTriangle & & ! m_IsNewOpenGL )
2018-04-03 15:40:21 +00:00
{
m_aVertices [ QuadOffset * 6 ] . m_Color . r = r ;
m_aVertices [ QuadOffset * 6 ] . m_Color . g = g ;
m_aVertices [ QuadOffset * 6 ] . m_Color . b = b ;
m_aVertices [ QuadOffset * 6 ] . m_Color . a = a ;
m_aVertices [ QuadOffset * 6 + 1 ] . m_Color . r = r ;
m_aVertices [ QuadOffset * 6 + 1 ] . m_Color . g = g ;
m_aVertices [ QuadOffset * 6 + 1 ] . m_Color . b = b ;
m_aVertices [ QuadOffset * 6 + 1 ] . m_Color . a = a ;
m_aVertices [ QuadOffset * 6 + 2 ] . m_Color . r = r ;
m_aVertices [ QuadOffset * 6 + 2 ] . m_Color . g = g ;
m_aVertices [ QuadOffset * 6 + 2 ] . m_Color . b = b ;
m_aVertices [ QuadOffset * 6 + 2 ] . m_Color . a = a ;
m_aVertices [ QuadOffset * 6 + 3 ] . m_Color . r = r ;
m_aVertices [ QuadOffset * 6 + 3 ] . m_Color . g = g ;
m_aVertices [ QuadOffset * 6 + 3 ] . m_Color . b = b ;
m_aVertices [ QuadOffset * 6 + 3 ] . m_Color . a = a ;
m_aVertices [ QuadOffset * 6 + 4 ] . m_Color . r = r ;
m_aVertices [ QuadOffset * 6 + 4 ] . m_Color . g = g ;
m_aVertices [ QuadOffset * 6 + 4 ] . m_Color . b = b ;
m_aVertices [ QuadOffset * 6 + 4 ] . m_Color . a = a ;
m_aVertices [ QuadOffset * 6 + 5 ] . m_Color . r = r ;
m_aVertices [ QuadOffset * 6 + 5 ] . m_Color . g = g ;
m_aVertices [ QuadOffset * 6 + 5 ] . m_Color . b = b ;
m_aVertices [ QuadOffset * 6 + 5 ] . m_Color . a = a ;
}
else
{
m_aVertices [ QuadOffset * 4 ] . m_Color . r = r ;
m_aVertices [ QuadOffset * 4 ] . m_Color . g = g ;
m_aVertices [ QuadOffset * 4 ] . m_Color . b = b ;
m_aVertices [ QuadOffset * 4 ] . m_Color . a = a ;
m_aVertices [ QuadOffset * 4 + 1 ] . m_Color . r = r ;
m_aVertices [ QuadOffset * 4 + 1 ] . m_Color . g = g ;
m_aVertices [ QuadOffset * 4 + 1 ] . m_Color . b = b ;
m_aVertices [ QuadOffset * 4 + 1 ] . m_Color . a = a ;
m_aVertices [ QuadOffset * 4 + 2 ] . m_Color . r = r ;
m_aVertices [ QuadOffset * 4 + 2 ] . m_Color . g = g ;
m_aVertices [ QuadOffset * 4 + 2 ] . m_Color . b = b ;
m_aVertices [ QuadOffset * 4 + 2 ] . m_Color . a = a ;
m_aVertices [ QuadOffset * 4 + 3 ] . m_Color . r = r ;
m_aVertices [ QuadOffset * 4 + 3 ] . m_Color . g = g ;
m_aVertices [ QuadOffset * 4 + 3 ] . m_Color . b = b ;
m_aVertices [ QuadOffset * 4 + 3 ] . m_Color . a = a ;
}
}
2011-12-31 00:06:04 +00:00
void CGraphics_Threaded : : QuadsSetSubset ( float TlU , float TlV , float BrU , float BrV )
{
2020-09-26 19:41:58 +00:00
m_aTexture [ 0 ] . u = TlU ;
m_aTexture [ 1 ] . u = BrU ;
m_aTexture [ 0 ] . v = TlV ;
m_aTexture [ 1 ] . v = TlV ;
2011-12-31 00:06:04 +00:00
2020-09-26 19:41:58 +00:00
m_aTexture [ 3 ] . u = TlU ;
m_aTexture [ 2 ] . u = BrU ;
m_aTexture [ 3 ] . v = BrV ;
m_aTexture [ 2 ] . v = BrV ;
2011-12-31 00:06:04 +00:00
}
void CGraphics_Threaded : : QuadsSetSubsetFree (
float x0 , float y0 , float x1 , float y1 ,
2020-09-21 03:57:54 +00:00
float x2 , float y2 , float x3 , float y3 , int Index )
2011-12-31 00:06:04 +00:00
{
2020-09-21 03:57:54 +00:00
m_aTexture [ 0 ] . u = x0 ;
m_aTexture [ 0 ] . v = y0 ;
m_aTexture [ 1 ] . u = x1 ;
m_aTexture [ 1 ] . v = y1 ;
m_aTexture [ 2 ] . u = x2 ;
m_aTexture [ 2 ] . v = y2 ;
m_aTexture [ 3 ] . u = x3 ;
m_aTexture [ 3 ] . v = y3 ;
m_CurIndex = Index ;
2011-12-31 00:06:04 +00:00
}
void CGraphics_Threaded : : QuadsDraw ( CQuadItem * pArray , int Num )
{
for ( int i = 0 ; i < Num ; + + i )
{
2020-09-26 19:41:58 +00:00
pArray [ i ] . m_X - = pArray [ i ] . m_Width / 2 ;
pArray [ i ] . m_Y - = pArray [ i ] . m_Height / 2 ;
2011-12-31 00:06:04 +00:00
}
QuadsDrawTL ( pArray , Num ) ;
}
void CGraphics_Threaded : : QuadsDrawTL ( const CQuadItem * pArray , int Num )
{
2020-09-21 03:57:54 +00:00
QuadsDrawTLImpl ( m_aVertices , pArray , Num ) ;
}
2011-12-31 00:06:04 +00:00
2020-09-21 03:57:54 +00:00
void CGraphics_Threaded : : QuadsTex3DDrawTL ( const CQuadItem * pArray , int Num )
{
int CurNumVert = m_NumVertices ;
2011-12-31 00:06:04 +00:00
2020-09-21 03:57:54 +00:00
int VertNum = 0 ;
2020-08-18 18:26:35 +00:00
if ( g_Config . m_GfxQuadAsTriangle & & ! m_IsNewOpenGL )
2011-12-31 00:06:04 +00:00
{
2020-09-21 03:57:54 +00:00
VertNum = 6 ;
2011-12-31 00:06:04 +00:00
}
2015-03-31 11:35:18 +00:00
else
{
2020-09-21 03:57:54 +00:00
VertNum = 4 ;
}
2015-03-31 11:35:18 +00:00
2020-09-21 03:57:54 +00:00
for ( int i = 0 ; i < Num ; + + i )
{
for ( int n = 0 ; n < VertNum ; + + n )
{
if ( HasTextureArrays ( ) )
m_aVerticesTex3D [ CurNumVert + VertNum * i + n ] . m_Tex . w = ( float ) m_CurIndex ;
else
m_aVerticesTex3D [ CurNumVert + VertNum * i + n ] . m_Tex . w = ( ( float ) m_CurIndex + 0.5f ) / 256.f ;
2015-03-31 11:35:18 +00:00
}
}
2020-09-21 03:57:54 +00:00
QuadsDrawTLImpl ( m_aVerticesTex3D , pArray , Num ) ;
2011-12-31 00:06:04 +00:00
}
void CGraphics_Threaded : : QuadsDrawFreeform ( const CFreeformItem * pArray , int Num )
{
2020-10-20 17:11:19 +00:00
dbg_assert ( m_Drawing = = DRAWING_QUADS | | m_Drawing = = DRAWING_TRIANGLES , " called Graphics()->QuadsDrawFreeform without begin " ) ;
2011-12-31 00:06:04 +00:00
2020-10-20 17:11:19 +00:00
if ( ( g_Config . m_GfxQuadAsTriangle & & ! m_IsNewOpenGL ) | | m_Drawing = = DRAWING_TRIANGLES )
2011-12-31 00:06:04 +00:00
{
2015-03-31 11:35:18 +00:00
for ( int i = 0 ; i < Num ; + + i )
{
2020-09-26 19:41:58 +00:00
m_aVertices [ m_NumVertices + 6 * i ] . m_Pos . x = pArray [ i ] . m_X0 ;
m_aVertices [ m_NumVertices + 6 * i ] . m_Pos . y = pArray [ i ] . m_Y0 ;
m_aVertices [ m_NumVertices + 6 * i ] . m_Tex = m_aTexture [ 0 ] ;
SetColor ( & m_aVertices [ m_NumVertices + 6 * i ] , 0 ) ;
m_aVertices [ m_NumVertices + 6 * i + 1 ] . m_Pos . x = pArray [ i ] . m_X1 ;
m_aVertices [ m_NumVertices + 6 * i + 1 ] . m_Pos . y = pArray [ i ] . m_Y1 ;
m_aVertices [ m_NumVertices + 6 * i + 1 ] . m_Tex = m_aTexture [ 1 ] ;
SetColor ( & m_aVertices [ m_NumVertices + 6 * i + 1 ] , 1 ) ;
m_aVertices [ m_NumVertices + 6 * i + 2 ] . m_Pos . x = pArray [ i ] . m_X3 ;
m_aVertices [ m_NumVertices + 6 * i + 2 ] . m_Pos . y = pArray [ i ] . m_Y3 ;
m_aVertices [ m_NumVertices + 6 * i + 2 ] . m_Tex = m_aTexture [ 3 ] ;
SetColor ( & m_aVertices [ m_NumVertices + 6 * i + 2 ] , 3 ) ;
m_aVertices [ m_NumVertices + 6 * i + 3 ] . m_Pos . x = pArray [ i ] . m_X0 ;
m_aVertices [ m_NumVertices + 6 * i + 3 ] . m_Pos . y = pArray [ i ] . m_Y0 ;
m_aVertices [ m_NumVertices + 6 * i + 3 ] . m_Tex = m_aTexture [ 0 ] ;
SetColor ( & m_aVertices [ m_NumVertices + 6 * i + 3 ] , 0 ) ;
m_aVertices [ m_NumVertices + 6 * i + 4 ] . m_Pos . x = pArray [ i ] . m_X3 ;
m_aVertices [ m_NumVertices + 6 * i + 4 ] . m_Pos . y = pArray [ i ] . m_Y3 ;
m_aVertices [ m_NumVertices + 6 * i + 4 ] . m_Tex = m_aTexture [ 3 ] ;
SetColor ( & m_aVertices [ m_NumVertices + 6 * i + 4 ] , 3 ) ;
m_aVertices [ m_NumVertices + 6 * i + 5 ] . m_Pos . x = pArray [ i ] . m_X2 ;
m_aVertices [ m_NumVertices + 6 * i + 5 ] . m_Pos . y = pArray [ i ] . m_Y2 ;
m_aVertices [ m_NumVertices + 6 * i + 5 ] . m_Tex = m_aTexture [ 2 ] ;
SetColor ( & m_aVertices [ m_NumVertices + 6 * i + 5 ] , 2 ) ;
2015-03-31 11:35:18 +00:00
}
2020-09-26 19:41:58 +00:00
AddVertices ( 3 * 2 * Num ) ;
2011-12-31 00:06:04 +00:00
}
2015-03-31 11:35:18 +00:00
else
{
for ( int i = 0 ; i < Num ; + + i )
{
2020-09-26 19:41:58 +00:00
m_aVertices [ m_NumVertices + 4 * i ] . m_Pos . x = pArray [ i ] . m_X0 ;
m_aVertices [ m_NumVertices + 4 * i ] . m_Pos . y = pArray [ i ] . m_Y0 ;
m_aVertices [ m_NumVertices + 4 * i ] . m_Tex = m_aTexture [ 0 ] ;
SetColor ( & m_aVertices [ m_NumVertices + 4 * i ] , 0 ) ;
m_aVertices [ m_NumVertices + 4 * i + 1 ] . m_Pos . x = pArray [ i ] . m_X1 ;
m_aVertices [ m_NumVertices + 4 * i + 1 ] . m_Pos . y = pArray [ i ] . m_Y1 ;
m_aVertices [ m_NumVertices + 4 * i + 1 ] . m_Tex = m_aTexture [ 1 ] ;
SetColor ( & m_aVertices [ m_NumVertices + 4 * i + 1 ] , 1 ) ;
m_aVertices [ m_NumVertices + 4 * i + 2 ] . m_Pos . x = pArray [ i ] . m_X3 ;
m_aVertices [ m_NumVertices + 4 * i + 2 ] . m_Pos . y = pArray [ i ] . m_Y3 ;
m_aVertices [ m_NumVertices + 4 * i + 2 ] . m_Tex = m_aTexture [ 3 ] ;
SetColor ( & m_aVertices [ m_NumVertices + 4 * i + 2 ] , 3 ) ;
m_aVertices [ m_NumVertices + 4 * i + 3 ] . m_Pos . x = pArray [ i ] . m_X2 ;
m_aVertices [ m_NumVertices + 4 * i + 3 ] . m_Pos . y = pArray [ i ] . m_Y2 ;
m_aVertices [ m_NumVertices + 4 * i + 3 ] . m_Tex = m_aTexture [ 2 ] ;
SetColor ( & m_aVertices [ m_NumVertices + 4 * i + 3 ] , 2 ) ;
2015-03-31 11:35:18 +00:00
}
2011-12-31 00:06:04 +00:00
2020-09-26 19:41:58 +00:00
AddVertices ( 4 * Num ) ;
2015-03-31 11:35:18 +00:00
}
2011-12-31 00:06:04 +00:00
}
2012-10-14 12:04:48 +00:00
void CGraphics_Threaded : : QuadsText ( float x , float y , float Size , const char * pText )
2011-12-31 00:06:04 +00:00
{
float StartX = x ;
while ( * pText )
{
char c = * pText ;
pText + + ;
if ( c = = ' \n ' )
{
x = StartX ;
y + = Size ;
}
else
{
QuadsSetSubset (
2020-09-26 19:41:58 +00:00
( c % 16 ) / 16.0f ,
( c / 16 ) / 16.0f ,
( c % 16 ) / 16.0f + 1.0f / 16.0f ,
( c / 16 ) / 16.0f + 1.0f / 16.0f ) ;
2011-12-31 00:06:04 +00:00
CQuadItem QuadItem ( x , y , Size , Size ) ;
QuadsDrawTL ( & QuadItem , 1 ) ;
2020-09-26 19:41:58 +00:00
x + = Size / 2 ;
2011-12-31 00:06:04 +00:00
}
}
}
2020-09-26 19:41:58 +00:00
void CGraphics_Threaded : : RenderTileLayer ( int BufferContainerIndex , float * pColor , char * * pOffsets , unsigned int * IndicedVertexDrawNum , size_t NumIndicesOffet )
2017-09-13 18:33:58 +00:00
{
2018-03-13 20:47:07 +00:00
if ( NumIndicesOffet = = 0 )
return ;
2019-04-26 22:11:15 +00:00
2017-09-12 18:08:45 +00:00
//add the VertexArrays and draw
2018-03-13 20:47:07 +00:00
CCommandBuffer : : SCommand_RenderTileLayer Cmd ;
2017-09-12 18:08:45 +00:00
Cmd . m_State = m_State ;
Cmd . m_IndicesDrawNum = NumIndicesOffet ;
2018-03-13 20:47:07 +00:00
Cmd . m_BufferContainerIndex = BufferContainerIndex ;
2017-09-12 18:08:45 +00:00
mem_copy ( & Cmd . m_Color , pColor , sizeof ( Cmd . m_Color ) ) ;
2020-09-26 19:41:58 +00:00
void * Data = m_pCommandBuffer - > AllocData ( ( sizeof ( char * ) + sizeof ( unsigned int ) ) * NumIndicesOffet ) ;
2017-09-27 10:16:34 +00:00
if ( Data = = 0x0 )
2017-09-12 18:08:45 +00:00
{
// kick command buffer and try again
KickCommandBuffer ( ) ;
2019-04-26 22:11:15 +00:00
2020-09-26 19:41:58 +00:00
void * Data = m_pCommandBuffer - > AllocData ( ( sizeof ( char * ) + sizeof ( unsigned int ) ) * NumIndicesOffet ) ;
2017-09-27 10:16:34 +00:00
if ( Data = = 0x0 )
2017-09-12 18:08:45 +00:00
{
dbg_msg ( " graphics " , " failed to allocate data for vertices " ) ;
return ;
}
}
2020-09-26 19:41:58 +00:00
Cmd . m_pIndicesOffsets = ( char * * ) Data ;
Cmd . m_pDrawCount = ( unsigned int * ) ( ( ( char * ) Data ) + ( sizeof ( char * ) * NumIndicesOffet ) ) ;
2019-04-26 22:11:15 +00:00
2021-04-07 17:03:07 +00:00
if ( ! AddCmd (
Cmd , [ & ] {
Data = m_pCommandBuffer - > AllocData ( ( sizeof ( char * ) + sizeof ( unsigned int ) ) * NumIndicesOffet ) ;
if ( Data = = 0x0 )
{
dbg_msg ( " graphics " , " failed to allocate data for vertices " ) ;
return false ;
}
Cmd . m_pIndicesOffsets = ( char * * ) Data ;
Cmd . m_pDrawCount = ( unsigned int * ) ( ( ( char * ) Data ) + ( sizeof ( char * ) * NumIndicesOffet ) ) ;
return true ;
} ,
" failed to allocate memory for render command " ) )
2017-09-12 18:08:45 +00:00
{
2021-04-07 17:03:07 +00:00
return ;
2017-09-12 18:08:45 +00:00
}
2020-09-26 19:41:58 +00:00
mem_copy ( Cmd . m_pIndicesOffsets , pOffsets , sizeof ( char * ) * NumIndicesOffet ) ;
mem_copy ( Cmd . m_pDrawCount , IndicedVertexDrawNum , sizeof ( unsigned int ) * NumIndicesOffet ) ;
2019-04-26 22:11:15 +00:00
2017-09-12 18:08:45 +00:00
//todo max indices group check!!
}
2018-08-02 16:26:12 +00:00
void CGraphics_Threaded : : RenderBorderTiles ( int BufferContainerIndex , float * pColor , char * pIndexBufferOffset , float * pOffset , float * pDir , int JumpIndex , unsigned int DrawNum )
2017-09-13 18:33:58 +00:00
{
2018-08-02 16:26:12 +00:00
if ( DrawNum = = 0 )
return ;
2018-02-04 15:00:47 +00:00
// Draw a border tile a lot of times
2017-09-12 18:08:45 +00:00
CCommandBuffer : : SCommand_RenderBorderTile Cmd ;
Cmd . m_State = m_State ;
Cmd . m_DrawNum = DrawNum ;
2018-03-13 20:47:07 +00:00
Cmd . m_BufferContainerIndex = BufferContainerIndex ;
2017-09-12 18:08:45 +00:00
mem_copy ( & Cmd . m_Color , pColor , sizeof ( Cmd . m_Color ) ) ;
2018-08-02 16:26:12 +00:00
Cmd . m_pIndicesOffset = pIndexBufferOffset ;
2017-09-12 18:08:45 +00:00
Cmd . m_JumpIndex = JumpIndex ;
2019-04-26 22:11:15 +00:00
2018-08-02 16:26:12 +00:00
Cmd . m_Offset [ 0 ] = pOffset [ 0 ] ;
Cmd . m_Offset [ 1 ] = pOffset [ 1 ] ;
Cmd . m_Dir [ 0 ] = pDir [ 0 ] ;
Cmd . m_Dir [ 1 ] = pDir [ 1 ] ;
2017-09-12 18:08:45 +00:00
// check if we have enough free memory in the commandbuffer
2021-04-07 17:03:07 +00:00
if ( ! AddCmd (
Cmd , [ ] { return true ; } , " failed to allocate memory for render command " ) )
2017-09-12 18:08:45 +00:00
{
2021-04-07 17:03:07 +00:00
return ;
2017-09-12 18:08:45 +00:00
}
}
2018-08-02 16:26:12 +00:00
void CGraphics_Threaded : : RenderBorderTileLines ( int BufferContainerIndex , float * pColor , char * pIndexBufferOffset , float * pOffset , float * pDir , unsigned int IndexDrawNum , unsigned int RedrawNum )
2017-09-13 18:33:58 +00:00
{
2018-08-02 16:26:12 +00:00
if ( IndexDrawNum = = 0 | | RedrawNum = = 0 )
return ;
2018-02-04 15:00:47 +00:00
// Draw a border tile a lot of times
2017-09-12 18:08:45 +00:00
CCommandBuffer : : SCommand_RenderBorderTileLine Cmd ;
Cmd . m_State = m_State ;
Cmd . m_IndexDrawNum = IndexDrawNum ;
Cmd . m_DrawNum = RedrawNum ;
2018-03-13 20:47:07 +00:00
Cmd . m_BufferContainerIndex = BufferContainerIndex ;
2017-09-12 18:08:45 +00:00
mem_copy ( & Cmd . m_Color , pColor , sizeof ( Cmd . m_Color ) ) ;
2018-08-02 16:26:12 +00:00
Cmd . m_pIndicesOffset = pIndexBufferOffset ;
Cmd . m_Offset [ 0 ] = pOffset [ 0 ] ;
Cmd . m_Offset [ 1 ] = pOffset [ 1 ] ;
Cmd . m_Dir [ 0 ] = pDir [ 0 ] ;
Cmd . m_Dir [ 1 ] = pDir [ 1 ] ;
2017-09-12 18:08:45 +00:00
// check if we have enough free memory in the commandbuffer
2021-04-07 17:03:07 +00:00
if ( ! AddCmd (
Cmd , [ ] { return true ; } , " failed to allocate memory for render command " ) )
2017-09-12 18:08:45 +00:00
{
2021-04-07 17:03:07 +00:00
return ;
2017-09-12 18:08:45 +00:00
}
}
2020-12-29 13:31:42 +00:00
void CGraphics_Threaded : : RenderQuadLayer ( int BufferContainerIndex , SQuadRenderInfo * pQuadInfo , int QuadNum , int QuadOffset )
2017-09-13 18:33:58 +00:00
{
2018-03-13 20:47:07 +00:00
if ( QuadNum = = 0 )
return ;
//add the VertexArrays and draw
CCommandBuffer : : SCommand_RenderQuadLayer Cmd ;
Cmd . m_State = m_State ;
Cmd . m_QuadNum = QuadNum ;
2020-12-29 13:31:42 +00:00
Cmd . m_QuadOffset = QuadOffset ;
2018-03-13 20:47:07 +00:00
Cmd . m_BufferContainerIndex = BufferContainerIndex ;
2020-09-26 19:41:58 +00:00
Cmd . m_pQuadInfo = ( SQuadRenderInfo * ) AllocCommandBufferData ( QuadNum * sizeof ( SQuadRenderInfo ) ) ;
2018-03-13 20:47:07 +00:00
if ( Cmd . m_pQuadInfo = = 0x0 )
return ;
// check if we have enough free memory in the commandbuffer
2021-04-07 17:03:07 +00:00
if ( ! AddCmd (
Cmd , [ & ] {
Cmd . m_pQuadInfo = ( SQuadRenderInfo * ) m_pCommandBuffer - > AllocData ( QuadNum * sizeof ( SQuadRenderInfo ) ) ;
if ( Cmd . m_pQuadInfo = = 0x0 )
{
dbg_msg ( " graphics " , " failed to allocate data for the quad info " ) ;
return false ;
}
return true ;
} ,
" failed to allocate memory for render quad command " ) )
2018-03-13 20:47:07 +00:00
{
2021-04-07 17:03:07 +00:00
return ;
2018-03-13 20:47:07 +00:00
}
mem_copy ( Cmd . m_pQuadInfo , pQuadInfo , sizeof ( SQuadRenderInfo ) * QuadNum ) ;
}
2020-09-26 19:41:58 +00:00
void CGraphics_Threaded : : RenderText ( int BufferContainerIndex , int TextQuadNum , int TextureSize , int TextureTextIndex , int TextureTextOutlineIndex , float * pTextColor , float * pTextoutlineColor )
2018-03-13 20:47:07 +00:00
{
if ( BufferContainerIndex = = - 1 )
return ;
CCommandBuffer : : SCommand_RenderText Cmd ;
Cmd . m_State = m_State ;
Cmd . m_BufferContainerIndex = BufferContainerIndex ;
Cmd . m_DrawNum = TextQuadNum * 6 ;
Cmd . m_TextureSize = TextureSize ;
Cmd . m_TextTextureIndex = TextureTextIndex ;
Cmd . m_TextOutlineTextureIndex = TextureTextOutlineIndex ;
mem_copy ( Cmd . m_aTextColor , pTextColor , sizeof ( Cmd . m_aTextColor ) ) ;
mem_copy ( Cmd . m_aTextOutlineColor , pTextoutlineColor , sizeof ( Cmd . m_aTextOutlineColor ) ) ;
2021-04-07 17:03:07 +00:00
if ( ! AddCmd (
Cmd , [ ] { return true ; } , " failed to allocate memory for render text command " ) )
2017-09-12 18:08:45 +00:00
{
2021-04-07 17:03:07 +00:00
return ;
2017-09-12 18:08:45 +00:00
}
}
2018-03-13 20:47:07 +00:00
int CGraphics_Threaded : : CreateQuadContainer ( )
2017-09-13 18:33:58 +00:00
{
2018-03-13 20:47:07 +00:00
int Index = - 1 ;
if ( m_FirstFreeQuadContainer = = - 1 )
2017-09-13 18:33:58 +00:00
{
2018-03-13 20:47:07 +00:00
Index = m_QuadContainers . size ( ) ;
m_QuadContainers . push_back ( SQuadContainer ( ) ) ;
2017-09-27 12:52:06 +00:00
}
else
{
2018-03-13 20:47:07 +00:00
Index = m_FirstFreeQuadContainer ;
m_FirstFreeQuadContainer = m_QuadContainers [ Index ] . m_FreeIndex ;
m_QuadContainers [ Index ] . m_FreeIndex = Index ;
2017-09-12 18:08:45 +00:00
}
2018-03-13 20:47:07 +00:00
return Index ;
}
2018-04-15 17:34:56 +00:00
void CGraphics_Threaded : : QuadContainerUpload ( int ContainerIndex )
{
2020-08-22 06:09:10 +00:00
if ( IsQuadContainerBufferingEnabled ( ) )
2018-04-15 17:34:56 +00:00
{
2020-09-26 19:41:58 +00:00
SQuadContainer & Container = m_QuadContainers [ ContainerIndex ] ;
2018-04-15 17:34:56 +00:00
if ( Container . m_Quads . size ( ) > 0 )
{
if ( Container . m_QuadBufferObjectIndex = = - 1 )
{
size_t UploadDataSize = Container . m_Quads . size ( ) * sizeof ( SQuadContainer : : SQuad ) ;
Container . m_QuadBufferObjectIndex = CreateBufferObject ( UploadDataSize , & Container . m_Quads [ 0 ] ) ;
}
else
{
size_t UploadDataSize = Container . m_Quads . size ( ) * sizeof ( SQuadContainer : : SQuad ) ;
RecreateBufferObject ( Container . m_QuadBufferObjectIndex , UploadDataSize , & Container . m_Quads [ 0 ] ) ;
}
if ( Container . m_QuadBufferContainerIndex = = - 1 )
{
SBufferContainerInfo Info ;
Info . m_Stride = sizeof ( CCommandBuffer : : SVertex ) ;
Info . m_Attributes . push_back ( SBufferContainerInfo : : SAttribute ( ) ) ;
2020-09-26 19:41:58 +00:00
SBufferContainerInfo : : SAttribute * pAttr = & Info . m_Attributes . back ( ) ;
2018-04-15 17:34:56 +00:00
pAttr - > m_DataTypeCount = 2 ;
pAttr - > m_FuncType = 0 ;
pAttr - > m_Normalized = false ;
pAttr - > m_pOffset = 0 ;
pAttr - > m_Type = GRAPHICS_TYPE_FLOAT ;
pAttr - > m_VertBufferBindingIndex = Container . m_QuadBufferObjectIndex ;
Info . m_Attributes . push_back ( SBufferContainerInfo : : SAttribute ( ) ) ;
pAttr = & Info . m_Attributes . back ( ) ;
pAttr - > m_DataTypeCount = 2 ;
pAttr - > m_FuncType = 0 ;
pAttr - > m_Normalized = false ;
2020-09-26 19:41:58 +00:00
pAttr - > m_pOffset = ( void * ) ( sizeof ( float ) * 2 ) ;
2018-04-15 17:34:56 +00:00
pAttr - > m_Type = GRAPHICS_TYPE_FLOAT ;
pAttr - > m_VertBufferBindingIndex = Container . m_QuadBufferObjectIndex ;
Info . m_Attributes . push_back ( SBufferContainerInfo : : SAttribute ( ) ) ;
pAttr = & Info . m_Attributes . back ( ) ;
pAttr - > m_DataTypeCount = 4 ;
pAttr - > m_FuncType = 0 ;
pAttr - > m_Normalized = true ;
2020-09-26 19:41:58 +00:00
pAttr - > m_pOffset = ( void * ) ( sizeof ( float ) * 2 + sizeof ( float ) * 2 ) ;
2018-04-15 17:34:56 +00:00
pAttr - > m_Type = GRAPHICS_TYPE_UNSIGNED_BYTE ;
pAttr - > m_VertBufferBindingIndex = Container . m_QuadBufferObjectIndex ;
Container . m_QuadBufferContainerIndex = CreateBufferContainer ( & Info ) ;
}
}
}
}
2018-03-13 20:47:07 +00:00
void CGraphics_Threaded : : QuadContainerAddQuads ( int ContainerIndex , CQuadItem * pArray , int Num )
{
2020-09-26 19:41:58 +00:00
SQuadContainer & Container = m_QuadContainers [ ContainerIndex ] ;
2018-03-13 20:47:07 +00:00
2020-10-09 07:07:05 +00:00
if ( ( int ) Container . m_Quads . size ( ) > Num + CCommandBuffer : : CCommandBuffer : : MAX_VERTICES )
2018-03-13 20:47:07 +00:00
return ;
for ( int i = 0 ; i < Num ; + + i )
{
Container . m_Quads . push_back ( SQuadContainer : : SQuad ( ) ) ;
2020-09-26 19:41:58 +00:00
SQuadContainer : : SQuad & Quad = Container . m_Quads . back ( ) ;
2018-03-13 20:47:07 +00:00
Quad . m_aVertices [ 0 ] . m_Pos . x = pArray [ i ] . m_X ;
Quad . m_aVertices [ 0 ] . m_Pos . y = pArray [ i ] . m_Y ;
Quad . m_aVertices [ 0 ] . m_Tex = m_aTexture [ 0 ] ;
SetColor ( & Quad . m_aVertices [ 0 ] , 0 ) ;
Quad . m_aVertices [ 1 ] . m_Pos . x = pArray [ i ] . m_X + pArray [ i ] . m_Width ;
Quad . m_aVertices [ 1 ] . m_Pos . y = pArray [ i ] . m_Y ;
Quad . m_aVertices [ 1 ] . m_Tex = m_aTexture [ 1 ] ;
SetColor ( & Quad . m_aVertices [ 1 ] , 1 ) ;
Quad . m_aVertices [ 2 ] . m_Pos . x = pArray [ i ] . m_X + pArray [ i ] . m_Width ;
Quad . m_aVertices [ 2 ] . m_Pos . y = pArray [ i ] . m_Y + pArray [ i ] . m_Height ;
Quad . m_aVertices [ 2 ] . m_Tex = m_aTexture [ 2 ] ;
SetColor ( & Quad . m_aVertices [ 2 ] , 2 ) ;
Quad . m_aVertices [ 3 ] . m_Pos . x = pArray [ i ] . m_X ;
Quad . m_aVertices [ 3 ] . m_Pos . y = pArray [ i ] . m_Y + pArray [ i ] . m_Height ;
Quad . m_aVertices [ 3 ] . m_Tex = m_aTexture [ 3 ] ;
SetColor ( & Quad . m_aVertices [ 3 ] , 3 ) ;
if ( m_Rotation ! = 0 )
{
CCommandBuffer : : SPoint Center ;
Center . x = pArray [ i ] . m_X + pArray [ i ] . m_Width / 2 ;
Center . y = pArray [ i ] . m_Y + pArray [ i ] . m_Height / 2 ;
Rotate ( Center , Quad . m_aVertices , 4 ) ;
}
}
2018-04-15 17:34:56 +00:00
QuadContainerUpload ( ContainerIndex ) ;
2018-03-13 20:47:07 +00:00
}
void CGraphics_Threaded : : QuadContainerAddQuads ( int ContainerIndex , CFreeformItem * pArray , int Num )
{
2020-09-26 19:41:58 +00:00
SQuadContainer & Container = m_QuadContainers [ ContainerIndex ] ;
2018-03-13 20:47:07 +00:00
2020-10-09 07:07:05 +00:00
if ( ( int ) Container . m_Quads . size ( ) > Num + CCommandBuffer : : CCommandBuffer : : MAX_VERTICES )
2018-03-13 20:47:07 +00:00
return ;
for ( int i = 0 ; i < Num ; + + i )
{
Container . m_Quads . push_back ( SQuadContainer : : SQuad ( ) ) ;
2020-09-26 19:41:58 +00:00
SQuadContainer : : SQuad & Quad = Container . m_Quads . back ( ) ;
2018-03-13 20:47:07 +00:00
Quad . m_aVertices [ 0 ] . m_Pos . x = pArray [ i ] . m_X0 ;
Quad . m_aVertices [ 0 ] . m_Pos . y = pArray [ i ] . m_Y0 ;
Quad . m_aVertices [ 0 ] . m_Tex = m_aTexture [ 0 ] ;
SetColor ( & Quad . m_aVertices [ 0 ] , 0 ) ;
Quad . m_aVertices [ 1 ] . m_Pos . x = pArray [ i ] . m_X1 ;
Quad . m_aVertices [ 1 ] . m_Pos . y = pArray [ i ] . m_Y1 ;
Quad . m_aVertices [ 1 ] . m_Tex = m_aTexture [ 1 ] ;
SetColor ( & Quad . m_aVertices [ 1 ] , 1 ) ;
Quad . m_aVertices [ 2 ] . m_Pos . x = pArray [ i ] . m_X3 ;
Quad . m_aVertices [ 2 ] . m_Pos . y = pArray [ i ] . m_Y3 ;
Quad . m_aVertices [ 2 ] . m_Tex = m_aTexture [ 3 ] ;
SetColor ( & Quad . m_aVertices [ 2 ] , 3 ) ;
Quad . m_aVertices [ 3 ] . m_Pos . x = pArray [ i ] . m_X2 ;
Quad . m_aVertices [ 3 ] . m_Pos . y = pArray [ i ] . m_Y2 ;
Quad . m_aVertices [ 3 ] . m_Tex = m_aTexture [ 2 ] ;
SetColor ( & Quad . m_aVertices [ 3 ] , 2 ) ;
}
2018-04-15 17:34:56 +00:00
QuadContainerUpload ( ContainerIndex ) ;
2018-03-13 20:47:07 +00:00
}
void CGraphics_Threaded : : QuadContainerReset ( int ContainerIndex )
{
2020-09-26 19:41:58 +00:00
SQuadContainer & Container = m_QuadContainers [ ContainerIndex ] ;
2020-08-22 06:09:10 +00:00
if ( IsQuadContainerBufferingEnabled ( ) )
2018-04-15 17:34:56 +00:00
{
if ( Container . m_QuadBufferContainerIndex ! = - 1 )
DeleteBufferContainer ( Container . m_QuadBufferContainerIndex , true ) ;
}
2018-03-13 20:47:07 +00:00
Container . m_Quads . clear ( ) ;
Container . m_QuadBufferContainerIndex = Container . m_QuadBufferObjectIndex = - 1 ;
}
void CGraphics_Threaded : : DeleteQuadContainer ( int ContainerIndex )
{
QuadContainerReset ( ContainerIndex ) ;
// also clear the container index
m_QuadContainers [ ContainerIndex ] . m_FreeIndex = m_FirstFreeQuadContainer ;
m_FirstFreeQuadContainer = ContainerIndex ;
}
void CGraphics_Threaded : : RenderQuadContainer ( int ContainerIndex , int QuadDrawNum )
{
RenderQuadContainer ( ContainerIndex , 0 , QuadDrawNum ) ;
}
void CGraphics_Threaded : : RenderQuadContainer ( int ContainerIndex , int QuadOffset , int QuadDrawNum )
{
2020-09-26 19:41:58 +00:00
SQuadContainer & Container = m_QuadContainers [ ContainerIndex ] ;
2018-03-13 20:47:07 +00:00
if ( QuadDrawNum = = - 1 )
QuadDrawNum = ( int ) Container . m_Quads . size ( ) - QuadOffset ;
if ( ( int ) Container . m_Quads . size ( ) < QuadOffset + QuadDrawNum | | QuadDrawNum = = 0 )
return ;
2019-04-26 22:11:15 +00:00
2020-08-22 06:09:10 +00:00
if ( IsQuadContainerBufferingEnabled ( ) )
2018-03-13 20:47:07 +00:00
{
2018-04-15 17:34:56 +00:00
if ( Container . m_QuadBufferContainerIndex = = - 1 )
return ;
2020-10-09 07:07:05 +00:00
WrapClamp ( ) ;
2018-03-13 20:47:07 +00:00
CCommandBuffer : : SCommand_RenderQuadContainer Cmd ;
Cmd . m_State = m_State ;
Cmd . m_DrawNum = ( unsigned int ) QuadDrawNum * 6 ;
2020-09-26 19:41:58 +00:00
Cmd . m_pOffset = ( void * ) ( QuadOffset * 6 * sizeof ( unsigned int ) ) ;
2018-03-13 20:47:07 +00:00
Cmd . m_BufferContainerIndex = Container . m_QuadBufferContainerIndex ;
2021-04-07 17:03:07 +00:00
if ( ! AddCmd (
Cmd , [ ] { return true ; } , " failed to allocate memory for render quad container " ) )
2018-03-13 20:47:07 +00:00
{
2021-04-07 17:03:07 +00:00
return ;
2018-03-13 20:47:07 +00:00
}
}
else
{
if ( g_Config . m_GfxQuadAsTriangle )
{
for ( int i = 0 ; i < QuadDrawNum ; + + i )
{
2020-09-26 19:41:58 +00:00
SQuadContainer : : SQuad & Quad = Container . m_Quads [ QuadOffset + i ] ;
2018-03-13 20:47:07 +00:00
m_aVertices [ i * 6 ] = Quad . m_aVertices [ 0 ] ;
m_aVertices [ i * 6 + 1 ] = Quad . m_aVertices [ 1 ] ;
m_aVertices [ i * 6 + 2 ] = Quad . m_aVertices [ 2 ] ;
m_aVertices [ i * 6 + 3 ] = Quad . m_aVertices [ 0 ] ;
m_aVertices [ i * 6 + 4 ] = Quad . m_aVertices [ 2 ] ;
m_aVertices [ i * 6 + 5 ] = Quad . m_aVertices [ 3 ] ;
m_NumVertices + = 6 ;
}
}
else
{
mem_copy ( m_aVertices , & Container . m_Quads [ QuadOffset ] , sizeof ( CCommandBuffer : : SVertex ) * 4 * QuadDrawNum ) ;
m_NumVertices + = 4 * QuadDrawNum ;
}
m_Drawing = DRAWING_QUADS ;
2020-10-09 07:07:05 +00:00
WrapClamp ( ) ;
2018-03-13 20:47:07 +00:00
FlushVertices ( false ) ;
m_Drawing = 0 ;
}
2020-10-09 07:07:05 +00:00
WrapNormal ( ) ;
2018-03-13 20:47:07 +00:00
}
2020-10-13 20:08:52 +00:00
void CGraphics_Threaded : : RenderQuadContainerEx ( int ContainerIndex , int QuadOffset , int QuadDrawNum , float X , float Y , float ScaleX , float ScaleY )
2018-03-13 20:47:07 +00:00
{
2020-09-26 19:41:58 +00:00
SQuadContainer & Container = m_QuadContainers [ ContainerIndex ] ;
2018-03-13 20:47:07 +00:00
if ( ( int ) Container . m_Quads . size ( ) < QuadOffset + 1 )
return ;
2020-10-13 20:08:52 +00:00
if ( QuadDrawNum = = - 1 )
QuadDrawNum = ( int ) Container . m_Quads . size ( ) - QuadOffset ;
2020-08-22 06:09:10 +00:00
if ( IsQuadContainerBufferingEnabled ( ) )
2018-03-13 20:47:07 +00:00
{
2018-04-15 17:34:56 +00:00
if ( Container . m_QuadBufferContainerIndex = = - 1 )
return ;
2020-09-26 19:41:58 +00:00
SQuadContainer : : SQuad & Quad = Container . m_Quads [ QuadOffset ] ;
2020-10-20 16:45:03 +00:00
CCommandBuffer : : SCommand_RenderQuadContainerEx Cmd ;
2018-03-13 20:47:07 +00:00
2020-10-09 07:07:05 +00:00
WrapClamp ( ) ;
2018-03-13 20:47:07 +00:00
float ScreenX0 , ScreenY0 , ScreenX1 , ScreenY1 ;
GetScreen ( & ScreenX0 , & ScreenY0 , & ScreenX1 , & ScreenY1 ) ;
MapScreen ( ( ScreenX0 - X ) / ScaleX , ( ScreenY0 - Y ) / ScaleY , ( ScreenX1 - X ) / ScaleX , ( ScreenY1 - Y ) / ScaleY ) ;
Cmd . m_State = m_State ;
MapScreen ( ScreenX0 , ScreenY0 , ScreenX1 , ScreenY1 ) ;
2020-10-13 20:08:52 +00:00
Cmd . m_DrawNum = QuadDrawNum * 6 ;
2020-09-26 19:41:58 +00:00
Cmd . m_pOffset = ( void * ) ( QuadOffset * 6 * sizeof ( unsigned int ) ) ;
2018-03-13 20:47:07 +00:00
Cmd . m_BufferContainerIndex = Container . m_QuadBufferContainerIndex ;
Cmd . m_VertexColor . r = ( float ) m_aColor [ 0 ] . r / 255.f ;
Cmd . m_VertexColor . g = ( float ) m_aColor [ 0 ] . g / 255.f ;
Cmd . m_VertexColor . b = ( float ) m_aColor [ 0 ] . b / 255.f ;
Cmd . m_VertexColor . a = ( float ) m_aColor [ 0 ] . a / 255.f ;
Cmd . m_Rotation = m_Rotation ;
// rotate before positioning
Cmd . m_Center . x = Quad . m_aVertices [ 0 ] . m_Pos . x + ( Quad . m_aVertices [ 1 ] . m_Pos . x - Quad . m_aVertices [ 0 ] . m_Pos . x ) / 2.f ;
Cmd . m_Center . y = Quad . m_aVertices [ 0 ] . m_Pos . y + ( Quad . m_aVertices [ 2 ] . m_Pos . y - Quad . m_aVertices [ 0 ] . m_Pos . y ) / 2.f ;
2021-04-07 17:03:07 +00:00
if ( ! AddCmd (
Cmd , [ ] { return true ; } , " failed to allocate memory for render quad container extended " ) )
2018-03-13 20:47:07 +00:00
{
2021-04-07 17:03:07 +00:00
return ;
2018-03-13 20:47:07 +00:00
}
}
else
{
if ( g_Config . m_GfxQuadAsTriangle )
{
2020-10-13 20:08:52 +00:00
for ( int i = 0 ; i < QuadDrawNum ; + + i )
2018-03-13 20:47:07 +00:00
{
2020-10-13 20:08:52 +00:00
SQuadContainer : : SQuad & Quad = Container . m_Quads [ QuadOffset + i ] ;
m_aVertices [ i * 6 + 0 ] = Quad . m_aVertices [ 0 ] ;
m_aVertices [ i * 6 + 1 ] = Quad . m_aVertices [ 1 ] ;
m_aVertices [ i * 6 + 2 ] = Quad . m_aVertices [ 2 ] ;
m_aVertices [ i * 6 + 3 ] = Quad . m_aVertices [ 0 ] ;
m_aVertices [ i * 6 + 4 ] = Quad . m_aVertices [ 2 ] ;
m_aVertices [ i * 6 + 5 ] = Quad . m_aVertices [ 3 ] ;
2018-03-13 20:47:07 +00:00
2020-10-13 20:08:52 +00:00
for ( int n = 0 ; n < 6 ; + + n )
{
m_aVertices [ i * 6 + n ] . m_Pos . x * = ScaleX ;
m_aVertices [ i * 6 + n ] . m_Pos . y * = ScaleY ;
2018-03-13 20:47:07 +00:00
2020-10-13 20:08:52 +00:00
SetColor ( & m_aVertices [ i * 6 + n ] , 0 ) ;
}
2018-03-13 20:47:07 +00:00
2020-10-13 20:08:52 +00:00
if ( m_Rotation ! = 0 )
{
CCommandBuffer : : SPoint Center ;
Center . x = m_aVertices [ i * 6 + 0 ] . m_Pos . x + ( m_aVertices [ i * 6 + 1 ] . m_Pos . x - m_aVertices [ i * 6 + 0 ] . m_Pos . x ) / 2.f ;
Center . y = m_aVertices [ i * 6 + 0 ] . m_Pos . y + ( m_aVertices [ i * 6 + 2 ] . m_Pos . y - m_aVertices [ i * 6 + 0 ] . m_Pos . y ) / 2.f ;
2018-03-13 20:47:07 +00:00
2020-10-13 20:08:52 +00:00
Rotate ( Center , & m_aVertices [ i * 6 + 0 ] , 6 ) ;
}
for ( int n = 0 ; n < 6 ; + + n )
{
m_aVertices [ i * 6 + n ] . m_Pos . x + = X ;
m_aVertices [ i * 6 + n ] . m_Pos . y + = Y ;
}
m_NumVertices + = 6 ;
2018-03-13 20:47:07 +00:00
}
}
else
{
2020-10-20 17:11:19 +00:00
mem_copy ( m_aVertices , & Container . m_Quads [ QuadOffset ] , sizeof ( CCommandBuffer : : SVertex ) * 4 * QuadDrawNum ) ;
2020-10-13 20:08:52 +00:00
for ( int i = 0 ; i < QuadDrawNum ; + + i )
2018-03-13 20:47:07 +00:00
{
2020-10-13 20:08:52 +00:00
for ( int n = 0 ; n < 4 ; + + n )
{
m_aVertices [ i * 4 + n ] . m_Pos . x * = ScaleX ;
m_aVertices [ i * 4 + n ] . m_Pos . y * = ScaleY ;
SetColor ( & m_aVertices [ i * 4 + n ] , 0 ) ;
}
if ( m_Rotation ! = 0 )
{
CCommandBuffer : : SPoint Center ;
Center . x = m_aVertices [ i * 4 + 0 ] . m_Pos . x + ( m_aVertices [ i * 4 + 1 ] . m_Pos . x - m_aVertices [ i * 4 + 0 ] . m_Pos . x ) / 2.f ;
Center . y = m_aVertices [ i * 4 + 0 ] . m_Pos . y + ( m_aVertices [ i * 4 + 2 ] . m_Pos . y - m_aVertices [ i * 4 + 0 ] . m_Pos . y ) / 2.f ;
Rotate ( Center , & m_aVertices [ i * 4 + 0 ] , 4 ) ;
}
for ( int n = 0 ; n < 4 ; + + n )
{
m_aVertices [ i * 4 + n ] . m_Pos . x + = X ;
m_aVertices [ i * 4 + n ] . m_Pos . y + = Y ;
}
m_NumVertices + = 4 ;
2018-03-13 20:47:07 +00:00
}
}
m_Drawing = DRAWING_QUADS ;
2020-10-09 07:07:05 +00:00
WrapClamp ( ) ;
2018-03-13 20:47:07 +00:00
FlushVertices ( false ) ;
m_Drawing = 0 ;
}
2020-10-09 07:07:05 +00:00
WrapNormal ( ) ;
2018-03-13 20:47:07 +00:00
}
2020-10-13 20:08:52 +00:00
void CGraphics_Threaded : : RenderQuadContainerAsSprite ( int ContainerIndex , int QuadOffset , float X , float Y , float ScaleX , float ScaleY )
{
RenderQuadContainerEx ( ContainerIndex , QuadOffset , 1 , X , Y , ScaleX , ScaleY ) ;
}
2018-03-13 20:47:07 +00:00
void CGraphics_Threaded : : RenderQuadContainerAsSpriteMultiple ( int ContainerIndex , int QuadOffset , int DrawCount , SRenderSpriteInfo * pRenderInfo )
{
2020-09-26 19:41:58 +00:00
SQuadContainer & Container = m_QuadContainers [ ContainerIndex ] ;
2018-03-13 20:47:07 +00:00
if ( DrawCount = = 0 )
return ;
2020-08-22 06:09:10 +00:00
if ( IsQuadContainerBufferingEnabled ( ) )
2018-03-13 20:47:07 +00:00
{
2018-04-15 17:34:56 +00:00
if ( Container . m_QuadBufferContainerIndex = = - 1 )
return ;
2020-10-09 07:07:05 +00:00
WrapClamp ( ) ;
2020-09-26 19:41:58 +00:00
SQuadContainer : : SQuad & Quad = Container . m_Quads [ 0 ] ;
2018-03-13 20:47:07 +00:00
CCommandBuffer : : SCommand_RenderQuadContainerAsSpriteMultiple Cmd ;
Cmd . m_State = m_State ;
Cmd . m_DrawNum = 1 * 6 ;
Cmd . m_DrawCount = DrawCount ;
2020-09-26 19:41:58 +00:00
Cmd . m_pOffset = ( void * ) ( QuadOffset * 6 * sizeof ( unsigned int ) ) ;
2018-03-13 20:47:07 +00:00
Cmd . m_BufferContainerIndex = Container . m_QuadBufferContainerIndex ;
Cmd . m_VertexColor . r = ( float ) m_aColor [ 0 ] . r / 255.f ;
Cmd . m_VertexColor . g = ( float ) m_aColor [ 0 ] . g / 255.f ;
Cmd . m_VertexColor . b = ( float ) m_aColor [ 0 ] . b / 255.f ;
Cmd . m_VertexColor . a = ( float ) m_aColor [ 0 ] . a / 255.f ;
// rotate before positioning
Cmd . m_Center . x = Quad . m_aVertices [ 0 ] . m_Pos . x + ( Quad . m_aVertices [ 1 ] . m_Pos . x - Quad . m_aVertices [ 0 ] . m_Pos . x ) / 2.f ;
Cmd . m_Center . y = Quad . m_aVertices [ 0 ] . m_Pos . y + ( Quad . m_aVertices [ 2 ] . m_Pos . y - Quad . m_aVertices [ 0 ] . m_Pos . y ) / 2.f ;
Cmd . m_pRenderInfo = ( IGraphics : : SRenderSpriteInfo * ) m_pCommandBuffer - > AllocData ( sizeof ( IGraphics : : SRenderSpriteInfo ) * DrawCount ) ;
if ( Cmd . m_pRenderInfo = = 0x0 )
{
// kick command buffer and try again
KickCommandBuffer ( ) ;
Cmd . m_pRenderInfo = ( IGraphics : : SRenderSpriteInfo * ) m_pCommandBuffer - > AllocData ( sizeof ( IGraphics : : SRenderSpriteInfo ) * DrawCount ) ;
if ( Cmd . m_pRenderInfo = = 0x0 )
{
dbg_msg ( " graphics " , " failed to allocate data for render info " ) ;
return ;
}
}
2021-04-07 17:03:07 +00:00
if ( ! AddCmd (
Cmd , [ & ] {
Cmd . m_pRenderInfo = ( IGraphics : : SRenderSpriteInfo * ) m_pCommandBuffer - > AllocData ( sizeof ( IGraphics : : SRenderSpriteInfo ) * DrawCount ) ;
if ( Cmd . m_pRenderInfo = = 0x0 )
{
dbg_msg ( " graphics " , " failed to allocate data for render info " ) ;
return false ;
}
return true ;
} ,
" failed to allocate memory for render quad container sprite " ) )
2018-03-13 20:47:07 +00:00
{
2021-04-07 17:03:07 +00:00
return ;
2018-03-13 20:47:07 +00:00
}
mem_copy ( Cmd . m_pRenderInfo , pRenderInfo , sizeof ( IGraphics : : SRenderSpriteInfo ) * DrawCount ) ;
2020-10-09 07:07:05 +00:00
WrapNormal ( ) ;
2018-03-13 20:47:07 +00:00
}
else
{
for ( int i = 0 ; i < DrawCount ; + + i )
{
QuadsSetRotation ( pRenderInfo [ i ] . m_Rotation ) ;
RenderQuadContainerAsSprite ( ContainerIndex , QuadOffset , pRenderInfo [ i ] . m_Pos [ 0 ] , pRenderInfo [ i ] . m_Pos [ 1 ] , pRenderInfo [ i ] . m_Scale , pRenderInfo [ i ] . m_Scale ) ;
}
}
}
2020-09-26 19:41:58 +00:00
void * CGraphics_Threaded : : AllocCommandBufferData ( unsigned AllocSize )
2019-12-21 13:35:09 +00:00
{
2020-09-26 19:41:58 +00:00
void * pData = m_pCommandBuffer - > AllocData ( AllocSize ) ;
2018-03-13 20:47:07 +00:00
if ( pData = = 0x0 )
2017-09-12 18:08:45 +00:00
{
// kick command buffer and try again
KickCommandBuffer ( ) ;
2018-03-13 20:47:07 +00:00
pData = m_pCommandBuffer - > AllocData ( AllocSize ) ;
if ( pData = = 0x0 )
2017-09-12 18:08:45 +00:00
{
2018-03-13 20:47:07 +00:00
dbg_msg ( " graphics " , " failed to allocate data for command buffer " ) ;
return NULL ;
}
}
return pData ;
}
2020-10-13 17:33:02 +00:00
int CGraphics_Threaded : : CreateBufferObject ( size_t UploadDataSize , void * pUploadData , bool IsMovedPointer )
2018-03-13 20:47:07 +00:00
{
int Index = - 1 ;
if ( m_FirstFreeBufferObjectIndex = = - 1 )
{
Index = m_BufferObjectIndices . size ( ) ;
m_BufferObjectIndices . push_back ( Index ) ;
}
else
{
Index = m_FirstFreeBufferObjectIndex ;
m_FirstFreeBufferObjectIndex = m_BufferObjectIndices [ Index ] ;
m_BufferObjectIndices [ Index ] = Index ;
}
CCommandBuffer : : SCommand_CreateBufferObject Cmd ;
Cmd . m_BufferIndex = Index ;
Cmd . m_DataSize = UploadDataSize ;
2020-10-13 17:33:02 +00:00
Cmd . m_DeletePointer = IsMovedPointer ;
2018-03-13 20:47:07 +00:00
2020-10-13 17:33:02 +00:00
if ( IsMovedPointer )
2018-03-13 20:47:07 +00:00
{
2020-10-13 17:33:02 +00:00
Cmd . m_pUploadData = pUploadData ;
2018-03-13 20:47:07 +00:00
2021-04-07 17:03:07 +00:00
if ( ! AddCmd (
Cmd , [ ] { return true ; } , " failed to allocate memory for update buffer object command " ) )
2018-03-13 20:47:07 +00:00
{
2021-04-07 17:03:07 +00:00
return - 1 ;
2018-03-13 20:47:07 +00:00
}
}
2020-09-26 19:41:58 +00:00
else
{
2020-10-13 17:33:02 +00:00
if ( UploadDataSize < = CMD_BUFFER_DATA_BUFFER_SIZE )
2018-03-13 20:47:07 +00:00
{
2020-10-13 17:33:02 +00:00
Cmd . m_pUploadData = AllocCommandBufferData ( UploadDataSize ) ;
if ( Cmd . m_pUploadData = = NULL )
return - 1 ;
2021-04-07 17:03:07 +00:00
if ( ! AddCmd (
Cmd , [ & ] {
Cmd . m_pUploadData = m_pCommandBuffer - > AllocData ( UploadDataSize ) ;
if ( Cmd . m_pUploadData = = 0x0 )
{
dbg_msg ( " graphics " , " failed to allocate data for upload data " ) ;
return false ;
}
return true ;
} ,
" failed to allocate memory for create buffer object command " ) )
2018-03-13 20:47:07 +00:00
{
2021-04-07 17:03:07 +00:00
return - 1 ;
2018-03-13 20:47:07 +00:00
}
2021-04-07 17:03:07 +00:00
2020-10-13 17:33:02 +00:00
mem_copy ( Cmd . m_pUploadData , pUploadData , UploadDataSize ) ;
2018-03-13 20:47:07 +00:00
}
2020-10-13 17:33:02 +00:00
else
2020-09-26 19:41:58 +00:00
{
2020-10-13 17:33:02 +00:00
Cmd . m_pUploadData = NULL ;
2021-04-07 17:03:07 +00:00
if ( ! AddCmd (
Cmd , [ ] { return true ; } , " failed to allocate memory for create buffer object command " ) )
2020-10-13 17:33:02 +00:00
{
2021-04-07 17:03:07 +00:00
return - 1 ;
2020-10-13 17:33:02 +00:00
}
// update the buffer instead
size_t UploadDataOffset = 0 ;
while ( UploadDataSize > 0 )
{
size_t UpdateSize = ( UploadDataSize > CMD_BUFFER_DATA_BUFFER_SIZE ? CMD_BUFFER_DATA_BUFFER_SIZE : UploadDataSize ) ;
2018-03-13 20:47:07 +00:00
2020-10-13 17:33:02 +00:00
UpdateBufferObject ( Index , UpdateSize , ( ( ( char * ) pUploadData ) + UploadDataOffset ) , ( void * ) UploadDataOffset ) ;
2018-03-13 20:47:07 +00:00
2020-10-13 17:33:02 +00:00
UploadDataOffset + = UpdateSize ;
UploadDataSize - = UpdateSize ;
}
2018-03-13 20:47:07 +00:00
}
}
return Index ;
}
2020-10-13 17:33:02 +00:00
void CGraphics_Threaded : : RecreateBufferObject ( int BufferIndex , size_t UploadDataSize , void * pUploadData , bool IsMovedPointer )
2018-03-13 20:47:07 +00:00
{
CCommandBuffer : : SCommand_RecreateBufferObject Cmd ;
Cmd . m_BufferIndex = BufferIndex ;
Cmd . m_DataSize = UploadDataSize ;
2020-10-13 17:33:02 +00:00
Cmd . m_DeletePointer = IsMovedPointer ;
2018-03-13 20:47:07 +00:00
2020-10-13 17:33:02 +00:00
if ( IsMovedPointer )
2018-03-13 20:47:07 +00:00
{
2020-10-13 17:33:02 +00:00
Cmd . m_pUploadData = pUploadData ;
2018-03-13 20:47:07 +00:00
2021-04-07 17:03:07 +00:00
if ( ! AddCmd (
Cmd , [ ] { return true ; } , " failed to allocate memory for recreate buffer object command " ) )
2018-03-13 20:47:07 +00:00
{
2021-04-07 17:03:07 +00:00
return ;
2017-09-12 18:08:45 +00:00
}
}
2020-09-26 19:41:58 +00:00
else
{
2020-10-13 17:33:02 +00:00
if ( UploadDataSize < = CMD_BUFFER_DATA_BUFFER_SIZE )
2018-03-13 20:47:07 +00:00
{
2020-10-13 17:33:02 +00:00
Cmd . m_pUploadData = AllocCommandBufferData ( UploadDataSize ) ;
if ( Cmd . m_pUploadData = = NULL )
return ;
2021-04-07 17:03:07 +00:00
if ( ! AddCmd (
Cmd , [ & ] {
Cmd . m_pUploadData = m_pCommandBuffer - > AllocData ( UploadDataSize ) ;
if ( Cmd . m_pUploadData = = 0x0 )
{
dbg_msg ( " graphics " , " failed to allocate data for upload data " ) ;
return false ;
}
return true ;
} ,
" failed to allocate memory for recreate buffer object command " ) )
2018-03-13 20:47:07 +00:00
{
2021-04-07 17:03:07 +00:00
return ;
2018-03-13 20:47:07 +00:00
}
2020-10-13 17:33:02 +00:00
mem_copy ( Cmd . m_pUploadData , pUploadData , UploadDataSize ) ;
}
else
2020-09-26 19:41:58 +00:00
{
2020-10-13 17:33:02 +00:00
Cmd . m_pUploadData = NULL ;
2021-04-07 17:03:07 +00:00
if ( ! AddCmd (
Cmd , [ ] { return true ; } , " failed to allocate memory for update buffer object command " ) )
2020-10-13 17:33:02 +00:00
{
2021-04-07 17:03:07 +00:00
return ;
2020-10-13 17:33:02 +00:00
}
2018-03-13 20:47:07 +00:00
2020-10-13 17:33:02 +00:00
// update the buffer instead
size_t UploadDataOffset = 0 ;
while ( UploadDataSize > 0 )
{
size_t UpdateSize = ( UploadDataSize > CMD_BUFFER_DATA_BUFFER_SIZE ? CMD_BUFFER_DATA_BUFFER_SIZE : UploadDataSize ) ;
UpdateBufferObject ( BufferIndex , UpdateSize , ( ( ( char * ) pUploadData ) + UploadDataOffset ) , ( void * ) UploadDataOffset ) ;
2018-03-13 20:47:07 +00:00
2020-10-13 17:33:02 +00:00
UploadDataOffset + = UpdateSize ;
UploadDataSize - = UpdateSize ;
}
2018-03-13 20:47:07 +00:00
}
}
}
2020-10-13 17:33:02 +00:00
void CGraphics_Threaded : : UpdateBufferObject ( int BufferIndex , size_t UploadDataSize , void * pUploadData , void * pOffset , bool IsMovedPointer )
2018-03-13 20:47:07 +00:00
{
CCommandBuffer : : SCommand_UpdateBufferObject Cmd ;
Cmd . m_BufferIndex = BufferIndex ;
Cmd . m_DataSize = UploadDataSize ;
Cmd . m_pOffset = pOffset ;
2020-10-13 17:33:02 +00:00
Cmd . m_DeletePointer = IsMovedPointer ;
2018-03-13 20:47:07 +00:00
2020-10-13 17:33:02 +00:00
if ( IsMovedPointer )
2017-09-12 18:08:45 +00:00
{
2020-10-13 17:33:02 +00:00
Cmd . m_pUploadData = pUploadData ;
2018-03-13 20:47:07 +00:00
2021-04-07 17:03:07 +00:00
if ( ! AddCmd (
Cmd , [ ] { return true ; } , " failed to allocate memory for update buffer object command " ) )
2017-09-12 18:08:45 +00:00
{
2021-04-07 17:03:07 +00:00
return ;
2017-09-12 18:08:45 +00:00
}
2020-10-13 17:33:02 +00:00
}
else
{
Cmd . m_pUploadData = AllocCommandBufferData ( UploadDataSize ) ;
if ( Cmd . m_pUploadData = = NULL )
return ;
2017-09-12 18:08:45 +00:00
2021-04-07 17:03:07 +00:00
if ( ! AddCmd (
Cmd , [ & ] {
Cmd . m_pUploadData = m_pCommandBuffer - > AllocData ( UploadDataSize ) ;
if ( Cmd . m_pUploadData = = 0x0 )
{
dbg_msg ( " graphics " , " failed to allocate data for upload data " ) ;
return false ;
}
return true ;
} ,
" failed to allocate memory for update buffer object command " ) )
2017-09-12 18:08:45 +00:00
{
2021-04-07 17:03:07 +00:00
return ;
2017-09-12 18:08:45 +00:00
}
2018-03-13 20:47:07 +00:00
2020-10-13 17:33:02 +00:00
mem_copy ( Cmd . m_pUploadData , pUploadData , UploadDataSize ) ;
}
2018-03-13 20:47:07 +00:00
}
void CGraphics_Threaded : : CopyBufferObject ( int WriteBufferIndex , int ReadBufferIndex , size_t WriteOffset , size_t ReadOffset , size_t CopyDataSize )
{
CCommandBuffer : : SCommand_CopyBufferObject Cmd ;
Cmd . m_WriteBufferIndex = WriteBufferIndex ;
Cmd . m_ReadBufferIndex = ReadBufferIndex ;
Cmd . m_pWriteOffset = WriteOffset ;
Cmd . m_pReadOffset = ReadOffset ;
Cmd . m_CopySize = CopyDataSize ;
2019-04-26 22:11:15 +00:00
2021-04-07 17:03:07 +00:00
if ( ! AddCmd (
Cmd , [ ] { return true ; } , " failed to allocate memory for copy buffer object command " ) )
2017-09-13 18:33:58 +00:00
{
2021-04-07 17:03:07 +00:00
return ;
2017-09-12 18:08:45 +00:00
}
2018-03-13 20:47:07 +00:00
}
void CGraphics_Threaded : : DeleteBufferObject ( int BufferIndex )
{
if ( BufferIndex = = - 1 )
return ;
CCommandBuffer : : SCommand_DeleteBufferObject Cmd ;
Cmd . m_BufferIndex = BufferIndex ;
2021-04-07 17:03:07 +00:00
if ( ! AddCmd (
Cmd , [ ] { return true ; } , " failed to allocate memory for delete buffer object command " ) )
2017-09-13 18:33:58 +00:00
{
2021-04-07 17:03:07 +00:00
return ;
2017-09-12 18:08:45 +00:00
}
2018-03-13 20:47:07 +00:00
// also clear the buffer object index
m_BufferObjectIndices [ BufferIndex ] = m_FirstFreeBufferObjectIndex ;
m_FirstFreeBufferObjectIndex = BufferIndex ;
}
int CGraphics_Threaded : : CreateBufferContainer ( SBufferContainerInfo * pContainerInfo )
{
int Index = - 1 ;
if ( m_FirstFreeVertexArrayInfo = = - 1 )
{
Index = m_VertexArrayInfo . size ( ) ;
m_VertexArrayInfo . push_back ( SVertexArrayInfo ( ) ) ;
}
else
{
Index = m_FirstFreeVertexArrayInfo ;
m_FirstFreeVertexArrayInfo = m_VertexArrayInfo [ Index ] . m_FreeIndex ;
m_VertexArrayInfo [ Index ] . m_FreeIndex = Index ;
}
CCommandBuffer : : SCommand_CreateBufferContainer Cmd ;
Cmd . m_BufferContainerIndex = Index ;
Cmd . m_AttrCount = ( int ) pContainerInfo - > m_Attributes . size ( ) ;
Cmd . m_Stride = pContainerInfo - > m_Stride ;
2020-09-26 19:41:58 +00:00
Cmd . m_Attributes = ( SBufferContainerInfo : : SAttribute * ) AllocCommandBufferData ( Cmd . m_AttrCount * sizeof ( SBufferContainerInfo : : SAttribute ) ) ;
2018-03-13 20:47:07 +00:00
if ( Cmd . m_Attributes = = NULL )
return - 1 ;
2021-04-07 17:03:07 +00:00
if ( ! AddCmd (
Cmd , [ & ] {
Cmd . m_Attributes = ( SBufferContainerInfo : : SAttribute * ) m_pCommandBuffer - > AllocData ( Cmd . m_AttrCount * sizeof ( SBufferContainerInfo : : SAttribute ) ) ;
if ( Cmd . m_Attributes = = 0x0 )
{
dbg_msg ( " graphics " , " failed to allocate data for upload data " ) ;
return false ;
}
return true ;
} ,
" failed to allocate memory for create buffer container command " ) )
2017-09-12 18:08:45 +00:00
{
2021-04-07 17:03:07 +00:00
return - 1 ;
2017-09-12 18:08:45 +00:00
}
2018-03-13 20:47:07 +00:00
mem_copy ( Cmd . m_Attributes , & pContainerInfo - > m_Attributes [ 0 ] , Cmd . m_AttrCount * sizeof ( SBufferContainerInfo : : SAttribute ) ) ;
2020-10-26 14:14:07 +00:00
for ( auto & Attribute : pContainerInfo - > m_Attributes )
m_VertexArrayInfo [ Index ] . m_AssociatedBufferObjectIndices . push_back ( Attribute . m_VertBufferBindingIndex ) ;
2018-03-13 20:47:07 +00:00
return Index ;
2017-09-12 18:08:45 +00:00
}
2018-03-13 20:47:07 +00:00
void CGraphics_Threaded : : DeleteBufferContainer ( int ContainerIndex , bool DestroyAllBO )
2017-09-13 18:33:58 +00:00
{
2018-03-13 20:47:07 +00:00
if ( ContainerIndex = = - 1 )
return ;
CCommandBuffer : : SCommand_DeleteBufferContainer Cmd ;
Cmd . m_BufferContainerIndex = ContainerIndex ;
Cmd . m_DestroyAllBO = DestroyAllBO ;
2019-04-26 22:11:15 +00:00
2021-04-07 17:03:07 +00:00
if ( ! AddCmd (
Cmd , [ ] { return true ; } , " failed to allocate memory for delete buffer container command " ) )
2017-09-12 18:08:45 +00:00
{
2021-04-07 17:03:07 +00:00
return ;
2017-09-12 18:08:45 +00:00
}
2018-03-13 20:47:07 +00:00
if ( DestroyAllBO )
{
// delete all associated references
for ( size_t i = 0 ; i < m_VertexArrayInfo [ ContainerIndex ] . m_AssociatedBufferObjectIndices . size ( ) ; + + i )
{
int BufferObjectIndex = m_VertexArrayInfo [ ContainerIndex ] . m_AssociatedBufferObjectIndices [ i ] ;
if ( BufferObjectIndex ! = - 1 )
{
// don't delete double entries
2020-10-26 13:11:11 +00:00
for ( int & m_AssociatedBufferObjectIndice : m_VertexArrayInfo [ ContainerIndex ] . m_AssociatedBufferObjectIndices )
2018-03-13 20:47:07 +00:00
{
2020-10-26 13:11:11 +00:00
if ( BufferObjectIndex = = m_AssociatedBufferObjectIndice )
m_AssociatedBufferObjectIndice = - 1 ;
2018-03-13 20:47:07 +00:00
}
// clear the buffer object index
m_BufferObjectIndices [ BufferObjectIndex ] = m_FirstFreeBufferObjectIndex ;
m_FirstFreeBufferObjectIndex = BufferObjectIndex ;
}
}
}
m_VertexArrayInfo [ ContainerIndex ] . m_AssociatedBufferObjectIndices . clear ( ) ;
// also clear the buffer object index
m_VertexArrayInfo [ ContainerIndex ] . m_FreeIndex = m_FirstFreeVertexArrayInfo ;
m_FirstFreeVertexArrayInfo = ContainerIndex ;
}
void CGraphics_Threaded : : UpdateBufferContainer ( int ContainerIndex , SBufferContainerInfo * pContainerInfo )
{
CCommandBuffer : : SCommand_UpdateBufferContainer Cmd ;
Cmd . m_BufferContainerIndex = ContainerIndex ;
Cmd . m_AttrCount = ( int ) pContainerInfo - > m_Attributes . size ( ) ;
Cmd . m_Stride = pContainerInfo - > m_Stride ;
2020-09-26 19:41:58 +00:00
Cmd . m_Attributes = ( SBufferContainerInfo : : SAttribute * ) AllocCommandBufferData ( Cmd . m_AttrCount * sizeof ( SBufferContainerInfo : : SAttribute ) ) ;
2018-03-13 20:47:07 +00:00
if ( Cmd . m_Attributes = = NULL )
return ;
2021-04-07 17:03:07 +00:00
if ( ! AddCmd (
Cmd , [ & ] {
Cmd . m_Attributes = ( SBufferContainerInfo : : SAttribute * ) m_pCommandBuffer - > AllocData ( Cmd . m_AttrCount * sizeof ( SBufferContainerInfo : : SAttribute ) ) ;
if ( Cmd . m_Attributes = = 0x0 )
{
dbg_msg ( " graphics " , " failed to allocate data for upload data " ) ;
return false ;
}
return true ;
} ,
" failed to allocate memory for update buffer container command " ) )
2017-09-12 18:08:45 +00:00
{
2021-04-07 17:03:07 +00:00
return ;
2017-09-12 18:08:45 +00:00
}
2018-03-13 20:47:07 +00:00
mem_copy ( Cmd . m_Attributes , & pContainerInfo - > m_Attributes [ 0 ] , Cmd . m_AttrCount * sizeof ( SBufferContainerInfo : : SAttribute ) ) ;
m_VertexArrayInfo [ ContainerIndex ] . m_AssociatedBufferObjectIndices . clear ( ) ;
2020-10-26 14:14:07 +00:00
for ( auto & Attribute : pContainerInfo - > m_Attributes )
m_VertexArrayInfo [ ContainerIndex ] . m_AssociatedBufferObjectIndices . push_back ( Attribute . m_VertBufferBindingIndex ) ;
2018-03-13 20:47:07 +00:00
}
void CGraphics_Threaded : : IndicesNumRequiredNotify ( unsigned int RequiredIndicesCount )
{
CCommandBuffer : : SCommand_IndicesRequiredNumNotify Cmd ;
Cmd . m_RequiredIndicesNum = RequiredIndicesCount ;
2021-04-07 17:03:07 +00:00
if ( ! AddCmd (
Cmd , [ ] { return true ; } , " failed to allocate memory for indcies required count notify command " ) )
2017-09-13 18:33:58 +00:00
{
2021-04-07 17:03:07 +00:00
return ;
2017-09-12 18:08:45 +00:00
}
}
2011-12-31 13:00:49 +00:00
int CGraphics_Threaded : : IssueInit ( )
{
2012-01-03 20:39:10 +00:00
int Flags = 0 ;
2012-06-27 09:46:11 +00:00
2020-09-26 19:41:58 +00:00
if ( g_Config . m_GfxBorderless )
Flags | = IGraphicsBackend : : INITFLAG_BORDERLESS ;
2021-01-31 20:54:04 +00:00
if ( g_Config . m_GfxFullscreen = = 1 )
2020-09-26 19:41:58 +00:00
Flags | = IGraphicsBackend : : INITFLAG_FULLSCREEN ;
2021-01-31 20:54:04 +00:00
else if ( g_Config . m_GfxFullscreen = = 2 )
Flags | = IGraphicsBackend : : INITFLAG_DESKTOP_FULLSCREEN ;
2020-09-26 19:41:58 +00:00
if ( g_Config . m_GfxVsync )
Flags | = IGraphicsBackend : : INITFLAG_VSYNC ;
if ( g_Config . m_GfxHighdpi )
Flags | = IGraphicsBackend : : INITFLAG_HIGHDPI ;
if ( g_Config . m_GfxResizable )
Flags | = IGraphicsBackend : : INITFLAG_RESIZABLE ;
2011-12-31 13:00:49 +00:00
2021-08-21 19:41:51 +00:00
int r = m_pBackend - > Init ( " DDNet Client " , & g_Config . m_GfxScreen , & g_Config . m_GfxScreenWidth , & g_Config . m_GfxScreenHeight , & g_Config . m_GfxScreenRefreshRate , g_Config . m_GfxFsaaSamples , Flags , & g_Config . m_GfxDesktopWidth , & g_Config . m_GfxDesktopHeight , & m_ScreenWidth , & m_ScreenHeight , m_pStorage ) ;
2020-11-05 19:38:37 +00:00
AddBackEndWarningIfExists ( ) ;
2020-08-18 18:26:35 +00:00
m_IsNewOpenGL = m_pBackend - > IsNewOpenGL ( ) ;
2020-08-22 06:09:10 +00:00
m_OpenGLTileBufferingEnabled = m_IsNewOpenGL | | m_pBackend - > HasTileBuffering ( ) ;
m_OpenGLQuadBufferingEnabled = m_IsNewOpenGL | | m_pBackend - > HasQuadBuffering ( ) ;
m_OpenGLQuadContainerBufferingEnabled = m_IsNewOpenGL | | m_pBackend - > HasQuadContainerBuffering ( ) ;
m_OpenGLTextBufferingEnabled = m_IsNewOpenGL | | ( m_OpenGLQuadContainerBufferingEnabled & & m_pBackend - > HasTextBuffering ( ) ) ;
m_OpenGLHasTextureArrays = m_IsNewOpenGL | | m_pBackend - > Has2DTextureArrays ( ) ;
2021-05-06 10:59:30 +00:00
m_ScreenHiDPIScale = m_ScreenWidth / ( float ) g_Config . m_GfxScreenWidth ;
2021-08-21 19:41:51 +00:00
m_ScreenRefreshRate = g_Config . m_GfxScreenRefreshRate ;
2017-09-12 18:08:45 +00:00
return r ;
2011-12-31 13:00:49 +00:00
}
2020-11-05 19:38:37 +00:00
void CGraphics_Threaded : : AddBackEndWarningIfExists ( )
{
const char * pErrStr = m_pBackend - > GetErrorString ( ) ;
if ( pErrStr ! = NULL )
{
SWarning NewWarning ;
str_format ( NewWarning . m_aWarningMsg , sizeof ( NewWarning . m_aWarningMsg ) , " %s " , Localize ( pErrStr ) ) ;
m_Warnings . emplace_back ( NewWarning ) ;
}
}
2011-12-31 13:00:49 +00:00
int CGraphics_Threaded : : InitWindow ( )
{
2020-08-22 06:09:10 +00:00
int ErrorCode = IssueInit ( ) ;
if ( ErrorCode = = 0 )
2011-12-31 13:00:49 +00:00
return 0 ;
// try disabling fsaa
while ( g_Config . m_GfxFsaaSamples )
{
g_Config . m_GfxFsaaSamples - - ;
if ( g_Config . m_GfxFsaaSamples )
dbg_msg ( " gfx " , " lowering FSAA to %d and trying again " , g_Config . m_GfxFsaaSamples ) ;
else
dbg_msg ( " gfx " , " disabling FSAA and trying again " ) ;
2020-08-22 06:09:10 +00:00
ErrorCode = IssueInit ( ) ;
if ( ErrorCode = = 0 )
2011-12-31 13:00:49 +00:00
return 0 ;
}
2019-04-26 22:11:15 +00:00
2020-08-22 06:09:10 +00:00
size_t OpenGLInitTryCount = 0 ;
while ( ErrorCode = = EGraphicsBackendErrorCodes : : GRAPHICS_BACKEND_ERROR_CODE_OPENGL_CONTEXT_FAILED | | ErrorCode = = EGraphicsBackendErrorCodes : : GRAPHICS_BACKEND_ERROR_CODE_OPENGL_VERSION_FAILED )
2017-09-27 10:16:34 +00:00
{
2020-08-22 06:09:10 +00:00
if ( ErrorCode = = EGraphicsBackendErrorCodes : : GRAPHICS_BACKEND_ERROR_CODE_OPENGL_CONTEXT_FAILED )
{
// try next smaller major/minor or patch version
if ( g_Config . m_GfxOpenGLMajor > = 4 )
{
g_Config . m_GfxOpenGLMajor = 3 ;
g_Config . m_GfxOpenGLMinor = 3 ;
g_Config . m_GfxOpenGLPatch = 0 ;
}
else if ( g_Config . m_GfxOpenGLMajor = = 3 & & g_Config . m_GfxOpenGLMinor > = 1 )
{
g_Config . m_GfxOpenGLMajor = 3 ;
g_Config . m_GfxOpenGLMinor = 0 ;
g_Config . m_GfxOpenGLPatch = 0 ;
}
else if ( g_Config . m_GfxOpenGLMajor = = 3 & & g_Config . m_GfxOpenGLMinor = = 0 )
{
g_Config . m_GfxOpenGLMajor = 2 ;
g_Config . m_GfxOpenGLMinor = 1 ;
g_Config . m_GfxOpenGLPatch = 0 ;
}
else if ( g_Config . m_GfxOpenGLMajor = = 2 & & g_Config . m_GfxOpenGLMinor > = 1 )
{
g_Config . m_GfxOpenGLMajor = 2 ;
g_Config . m_GfxOpenGLMinor = 0 ;
g_Config . m_GfxOpenGLPatch = 0 ;
}
else if ( g_Config . m_GfxOpenGLMajor = = 2 & & g_Config . m_GfxOpenGLMinor = = 0 )
{
g_Config . m_GfxOpenGLMajor = 1 ;
g_Config . m_GfxOpenGLMinor = 5 ;
g_Config . m_GfxOpenGLPatch = 0 ;
}
else if ( g_Config . m_GfxOpenGLMajor = = 1 & & g_Config . m_GfxOpenGLMinor = = 5 )
{
g_Config . m_GfxOpenGLMajor = 1 ;
g_Config . m_GfxOpenGLMinor = 4 ;
g_Config . m_GfxOpenGLPatch = 0 ;
}
else if ( g_Config . m_GfxOpenGLMajor = = 1 & & g_Config . m_GfxOpenGLMinor = = 4 )
{
g_Config . m_GfxOpenGLMajor = 1 ;
g_Config . m_GfxOpenGLMinor = 3 ;
g_Config . m_GfxOpenGLPatch = 0 ;
}
else if ( g_Config . m_GfxOpenGLMajor = = 1 & & g_Config . m_GfxOpenGLMinor = = 3 )
{
g_Config . m_GfxOpenGLMajor = 1 ;
g_Config . m_GfxOpenGLMinor = 2 ;
g_Config . m_GfxOpenGLPatch = 1 ;
}
else if ( g_Config . m_GfxOpenGLMajor = = 1 & & g_Config . m_GfxOpenGLMinor = = 2 )
{
g_Config . m_GfxOpenGLMajor = 1 ;
g_Config . m_GfxOpenGLMinor = 1 ;
g_Config . m_GfxOpenGLPatch = 0 ;
}
}
// new opengl version was set by backend, try again
ErrorCode = IssueInit ( ) ;
if ( ErrorCode = = 0 )
2017-10-20 20:52:38 +00:00
{
2017-09-27 10:16:34 +00:00
return 0 ;
2017-10-20 20:52:38 +00:00
}
2020-08-22 06:09:10 +00:00
if ( + + OpenGLInitTryCount > = 9 )
{
// try something else
break ;
}
2017-09-27 10:16:34 +00:00
}
2011-12-31 13:00:49 +00:00
// try lowering the resolution
if ( g_Config . m_GfxScreenWidth ! = 640 | | g_Config . m_GfxScreenHeight ! = 480 )
{
dbg_msg ( " gfx " , " setting resolution to 640x480 and trying again " ) ;
g_Config . m_GfxScreenWidth = 640 ;
g_Config . m_GfxScreenHeight = 480 ;
if ( IssueInit ( ) = = 0 )
return 0 ;
}
dbg_msg ( " gfx " , " out of ideas. failed to init graphics " ) ;
return - 1 ;
}
2012-01-03 20:39:10 +00:00
int CGraphics_Threaded : : Init ( )
2011-12-31 00:06:04 +00:00
{
// fetch pointers
m_pStorage = Kernel ( ) - > RequestInterface < IStorage > ( ) ;
m_pConsole = Kernel ( ) - > RequestInterface < IConsole > ( ) ;
// init textures
m_FirstFreeTexture = 0 ;
2020-11-18 11:41:20 +00:00
m_TextureIndices . resize ( CCommandBuffer : : MAX_TEXTURES ) ;
for ( int i = 0 ; i < ( int ) m_TextureIndices . size ( ) - 1 ; i + + )
m_TextureIndices [ i ] = i + 1 ;
m_TextureIndices . back ( ) = - 1 ;
2018-03-13 20:47:07 +00:00
m_FirstFreeVertexArrayInfo = - 1 ;
m_FirstFreeBufferObjectIndex = - 1 ;
m_FirstFreeQuadContainer = - 1 ;
2011-12-31 00:06:04 +00:00
2012-01-03 20:39:10 +00:00
m_pBackend = CreateGraphicsBackend ( ) ;
if ( InitWindow ( ) ! = 0 )
return - 1 ;
2021-05-06 10:59:30 +00:00
for ( auto & FakeMode : g_aFakeModes )
{
FakeMode . m_WindowWidth = FakeMode . m_CanvasWidth / m_ScreenHiDPIScale ;
FakeMode . m_WindowHeight = FakeMode . m_CanvasHeight / m_ScreenHiDPIScale ;
2021-08-21 19:41:51 +00:00
FakeMode . m_RefreshRate = g_Config . m_GfxScreenRefreshRate ;
2021-05-06 10:59:30 +00:00
}
2011-12-31 00:06:04 +00:00
// create command buffers
2020-10-26 14:14:07 +00:00
for ( auto & pCommandBuffer : m_apCommandBuffers )
pCommandBuffer = new CCommandBuffer ( CMD_BUFFER_CMD_BUFFER_SIZE , CMD_BUFFER_DATA_BUFFER_SIZE ) ;
2011-12-31 00:06:04 +00:00
m_pCommandBuffer = m_apCommandBuffers [ 0 ] ;
2011-12-31 13:00:49 +00:00
// create null texture, will get id=0
2017-03-21 10:24:44 +00:00
static const unsigned char s_aNullTextureData [ ] = {
2020-09-26 19:41:58 +00:00
0xff , 0x00 , 0x00 , 0xff , 0xff , 0x00 , 0x00 , 0xff , 0x00 , 0xff , 0x00 , 0xff , 0x00 , 0xff , 0x00 , 0xff ,
0xff , 0x00 , 0x00 , 0xff , 0xff , 0x00 , 0x00 , 0xff , 0x00 , 0xff , 0x00 , 0xff , 0x00 , 0xff , 0x00 , 0xff ,
0x00 , 0x00 , 0xff , 0xff , 0x00 , 0x00 , 0xff , 0xff , 0xff , 0xff , 0x00 , 0xff , 0xff , 0xff , 0x00 , 0xff ,
0x00 , 0x00 , 0xff , 0xff , 0x00 , 0x00 , 0xff , 0xff , 0xff , 0xff , 0x00 , 0xff , 0xff , 0xff , 0x00 , 0xff } ;
2011-12-31 13:00:49 +00:00
2021-05-21 12:57:55 +00:00
m_InvalidTexture = LoadTextureRaw ( 4 , 4 , CImageInfo : : FORMAT_RGBA , s_aNullTextureData , CImageInfo : : FORMAT_RGBA , 0 ) ;
2021-03-26 10:30:24 +00:00
ColorRGBA GPUInfoPrintColor { 0.6f , 0.5f , 1.0f , 1.0f } ;
char aBuf [ 256 ] ;
str_format ( aBuf , sizeof ( aBuf ) , " GPU vendor: %s " , GetVendorString ( ) ) ;
m_pConsole - > Print ( IConsole : : OUTPUT_LEVEL_STANDARD , " gfx " , aBuf , GPUInfoPrintColor ) ;
str_format ( aBuf , sizeof ( aBuf ) , " GPU renderer: %s " , GetRendererString ( ) ) ;
m_pConsole - > Print ( IConsole : : OUTPUT_LEVEL_STANDARD , " gfx " , aBuf , GPUInfoPrintColor ) ;
str_format ( aBuf , sizeof ( aBuf ) , " GPU version: %s " , GetVersionString ( ) ) ;
m_pConsole - > Print ( IConsole : : OUTPUT_LEVEL_STANDARD , " gfx " , aBuf , GPUInfoPrintColor ) ;
2011-12-31 13:00:49 +00:00
return 0 ;
2011-12-31 00:06:04 +00:00
}
void CGraphics_Threaded : : Shutdown ( )
{
2012-01-03 20:39:10 +00:00
// shutdown the backend
m_pBackend - > Shutdown ( ) ;
delete m_pBackend ;
m_pBackend = 0x0 ;
2012-01-03 21:01:37 +00:00
// delete the command buffers
2020-10-26 14:14:07 +00:00
for ( auto & pCommandBuffer : m_apCommandBuffers )
delete pCommandBuffer ;
2011-12-31 00:06:04 +00:00
}
2016-04-29 22:34:12 +00:00
int CGraphics_Threaded : : GetNumScreens ( ) const
{
return m_pBackend - > GetNumScreens ( ) ;
}
2011-12-31 00:06:04 +00:00
void CGraphics_Threaded : : Minimize ( )
{
2012-01-03 20:39:10 +00:00
m_pBackend - > Minimize ( ) ;
2011-12-31 00:06:04 +00:00
}
void CGraphics_Threaded : : Maximize ( )
{
// TODO: SDL
2012-01-03 20:39:10 +00:00
m_pBackend - > Maximize ( ) ;
2011-12-31 00:06:04 +00:00
}
2021-01-31 20:54:04 +00:00
void CGraphics_Threaded : : SetWindowParams ( int FullscreenMode , bool IsBorderless )
2016-04-29 19:07:10 +00:00
{
2021-01-31 20:54:04 +00:00
m_pBackend - > SetWindowParams ( FullscreenMode , IsBorderless ) ;
2021-08-21 19:41:51 +00:00
CVideoMode CurMode ;
m_pBackend - > GetCurrentVideoMode ( CurMode , m_ScreenHiDPIScale , g_Config . m_GfxDesktopWidth , g_Config . m_GfxDesktopHeight , g_Config . m_GfxScreen ) ;
Resize ( CurMode . m_WindowWidth , CurMode . m_WindowHeight , CurMode . m_RefreshRate , false , true ) ;
2016-04-29 22:34:12 +00:00
}
bool CGraphics_Threaded : : SetWindowScreen ( int Index )
{
return m_pBackend - > SetWindowScreen ( Index ) ;
}
2021-08-21 19:41:51 +00:00
void CGraphics_Threaded : : Resize ( int w , int h , int RefreshRate , bool SetWindowSize , bool ForceResizeEvent )
2016-04-30 15:59:58 +00:00
{
2020-06-19 06:19:40 +00:00
# if defined(CONF_VIDEORECORDER)
2020-09-26 19:41:58 +00:00
if ( IVideo : : Current ( ) & & IVideo : : Current ( ) - > IsRecording ( ) )
2020-06-19 06:19:40 +00:00
return ;
# endif
2021-08-21 19:41:51 +00:00
if ( ! ForceResizeEvent & & WindowWidth ( ) = = w & & WindowHeight ( ) = = h & & ( RefreshRate ! = - 1 & & RefreshRate = = m_ScreenRefreshRate ) )
2016-04-30 15:59:58 +00:00
return ;
2021-08-24 16:22:31 +00:00
// if the size is changed manually, only set the window resize, a window size changed event is triggered anyway
2020-12-12 11:58:59 +00:00
if ( SetWindowSize )
2021-08-24 16:22:31 +00:00
{
2021-08-21 19:41:51 +00:00
m_pBackend - > ResizeWindow ( w , h , RefreshRate ) ;
2021-08-24 16:22:31 +00:00
}
else
{
// if the size change event is triggered, set all parameters and change the viewport
m_pBackend - > GetViewportSize ( m_ScreenWidth , m_ScreenHeight ) ;
2016-04-30 15:59:58 +00:00
2021-08-24 16:22:31 +00:00
// adjust the viewport to only allow certain aspect ratios
if ( m_ScreenHeight > 4 * m_ScreenWidth / 5 )
m_ScreenHeight = 4 * m_ScreenWidth / 5 ;
if ( m_ScreenWidth > 21 * m_ScreenHeight / 9 )
m_ScreenWidth = 21 * m_ScreenHeight / 9 ;
2016-04-30 15:59:58 +00:00
2021-08-24 16:22:31 +00:00
m_ScreenRefreshRate = RefreshRate = = - 1 ? m_ScreenRefreshRate : RefreshRate ;
2021-08-21 19:41:51 +00:00
2021-08-24 16:22:31 +00:00
g_Config . m_GfxScreenWidth = w ;
g_Config . m_GfxScreenHeight = h ;
g_Config . m_GfxScreenRefreshRate = m_ScreenRefreshRate ;
2021-08-21 19:41:51 +00:00
2021-08-24 16:22:31 +00:00
CCommandBuffer : : SCommand_Update_Viewport Cmd ;
Cmd . m_X = 0 ;
Cmd . m_Y = 0 ;
Cmd . m_Width = m_ScreenWidth ;
Cmd . m_Height = m_ScreenHeight ;
2021-04-07 17:03:07 +00:00
2021-08-24 16:22:31 +00:00
if ( ! AddCmd (
Cmd , [ ] { return true ; } , " failed to add resize command " ) )
{
return ;
}
2016-04-30 15:59:58 +00:00
2021-08-24 16:22:31 +00:00
// kick the command buffer
KickCommandBuffer ( ) ;
WaitForIdle ( ) ;
2018-03-21 14:48:48 +00:00
2021-08-24 16:22:31 +00:00
for ( auto & ResizeListener : m_ResizeListeners )
ResizeListener . m_pFunc ( ResizeListener . m_pUser ) ;
}
2018-03-21 14:48:48 +00:00
}
void CGraphics_Threaded : : AddWindowResizeListener ( WINDOW_RESIZE_FUNC pFunc , void * pUser )
{
m_ResizeListeners . push_back ( SWindowResizeListener ( pFunc , pUser ) ) ;
2016-04-30 15:59:58 +00:00
}
2016-04-29 22:34:12 +00:00
int CGraphics_Threaded : : GetWindowScreen ( )
{
return m_pBackend - > GetWindowScreen ( ) ;
}
2021-08-24 10:18:20 +00:00
void CGraphics_Threaded : : WindowDestroyNtf ( uint32_t WindowID )
{
CCommandBuffer : : SCommand_WindowDestroyNtf Cmd ;
Cmd . m_WindowID = WindowID ;
if ( ! AddCmd (
Cmd , [ ] { return true ; } , " failed to add window destroy notify command " ) )
{
return ;
}
}
void CGraphics_Threaded : : WindowCreateNtf ( uint32_t WindowID )
{
CCommandBuffer : : SCommand_WindowCreateNtf Cmd ;
Cmd . m_WindowID = WindowID ;
if ( ! AddCmd (
Cmd , [ ] { return true ; } , " failed to add window create notify command " ) )
{
return ;
}
}
2011-12-31 00:06:04 +00:00
int CGraphics_Threaded : : WindowActive ( )
{
2012-01-03 20:39:10 +00:00
return m_pBackend - > WindowActive ( ) ;
2011-12-31 00:06:04 +00:00
}
int CGraphics_Threaded : : WindowOpen ( )
{
2012-01-03 20:39:10 +00:00
return m_pBackend - > WindowOpen ( ) ;
2014-10-18 14:17:36 +00:00
}
2011-12-31 00:06:04 +00:00
2015-08-24 23:01:38 +00:00
void CGraphics_Threaded : : SetWindowGrab ( bool Grab )
{
return m_pBackend - > SetWindowGrab ( Grab ) ;
}
2014-10-18 14:17:36 +00:00
void CGraphics_Threaded : : NotifyWindow ( )
{
return m_pBackend - > NotifyWindow ( ) ;
2011-12-31 00:06:04 +00:00
}
void CGraphics_Threaded : : TakeScreenshot ( const char * pFilename )
{
// TODO: screenshot support
char aDate [ 20 ] ;
str_timestamp ( aDate , sizeof ( aDate ) ) ;
2020-09-26 19:41:58 +00:00
str_format ( m_aScreenshotName , sizeof ( m_aScreenshotName ) , " screenshots/%s_%s.png " , pFilename ? pFilename : " screenshot " , aDate ) ;
2011-12-31 00:06:04 +00:00
m_DoScreenshot = true ;
}
2014-01-19 03:02:01 +00:00
void CGraphics_Threaded : : TakeCustomScreenshot ( const char * pFilename )
{
str_copy ( m_aScreenshotName , pFilename , sizeof ( m_aScreenshotName ) ) ;
m_DoScreenshot = true ;
}
2011-12-31 00:06:04 +00:00
void CGraphics_Threaded : : Swap ( )
{
2020-08-29 10:49:45 +00:00
if ( ! m_Warnings . empty ( ) )
{
2020-10-02 13:43:52 +00:00
SWarning * pCurWarning = GetCurWarning ( ) ;
2020-08-29 10:49:45 +00:00
if ( pCurWarning - > m_WasShown )
{
m_Warnings . erase ( m_Warnings . begin ( ) ) ;
}
}
2011-12-31 00:06:04 +00:00
// TODO: screenshot support
if ( m_DoScreenshot )
{
2012-03-04 11:46:46 +00:00
if ( WindowActive ( ) )
2014-01-19 03:02:01 +00:00
ScreenshotDirect ( ) ;
2011-12-31 00:06:04 +00:00
m_DoScreenshot = false ;
2012-01-01 13:15:35 +00:00
}
2011-12-31 00:06:04 +00:00
2021-04-07 17:03:07 +00:00
{
2021-05-01 21:33:42 +00:00
// add swap command
CCommandBuffer : : SCommand_Swap Cmd ;
if ( ! AddCmd (
Cmd , [ ] { return true ; } , " failed to add swap command " ) )
{
return ;
}
}
if ( g_Config . m_GfxFinish )
{
CCommandBuffer : : SCommand_Finish Cmd ;
if ( ! AddCmd (
Cmd , [ ] { return true ; } , " failed to add finish command " ) )
{
return ;
}
2021-04-07 17:03:07 +00:00
}
2011-12-31 09:04:46 +00:00
2012-01-01 13:15:35 +00:00
// kick the command buffer
KickCommandBuffer ( ) ;
2011-12-31 00:06:04 +00:00
}
2016-04-29 22:34:12 +00:00
bool CGraphics_Threaded : : SetVSync ( bool State )
{
2017-08-31 21:42:21 +00:00
if ( ! m_pCommandBuffer )
return true ;
2016-04-29 22:34:12 +00:00
// add vsnc command
2017-08-31 21:42:21 +00:00
bool RetOk = false ;
2016-04-29 22:34:12 +00:00
CCommandBuffer : : SCommand_VSync Cmd ;
Cmd . m_VSync = State ? 1 : 0 ;
Cmd . m_pRetOk = & RetOk ;
2021-04-07 17:03:07 +00:00
if ( ! AddCmd (
Cmd , [ ] { return true ; } , " failed to add vsync command " ) )
{
return false ;
}
2016-04-29 22:34:12 +00:00
// kick the command buffer
KickCommandBuffer ( ) ;
WaitForIdle ( ) ;
return RetOk ;
}
2018-02-04 15:00:47 +00:00
// synchronization
2020-11-29 16:53:54 +00:00
void CGraphics_Threaded : : InsertSignal ( CSemaphore * pSemaphore )
2011-12-31 09:04:46 +00:00
{
CCommandBuffer : : SCommand_Signal Cmd ;
Cmd . m_pSemaphore = pSemaphore ;
2021-04-07 17:03:07 +00:00
if ( ! AddCmd (
Cmd , [ ] { return true ; } , " failed to add signal command " ) )
{
return ;
}
2011-12-31 09:04:46 +00:00
}
2021-02-08 21:26:26 +00:00
bool CGraphics_Threaded : : IsIdle ( ) const
2011-12-31 09:04:46 +00:00
{
2012-01-03 20:39:10 +00:00
return m_pBackend - > IsIdle ( ) ;
2011-12-31 09:04:46 +00:00
}
void CGraphics_Threaded : : WaitForIdle ( )
{
2012-01-03 20:39:10 +00:00
m_pBackend - > WaitForIdle ( ) ;
2011-12-31 09:04:46 +00:00
}
2011-12-31 00:06:04 +00:00
2020-10-02 13:43:52 +00:00
SWarning * CGraphics_Threaded : : GetCurWarning ( )
2020-08-29 10:49:45 +00:00
{
if ( m_Warnings . empty ( ) )
return NULL ;
else
{
2020-10-02 13:43:52 +00:00
SWarning * pCurWarning = & m_Warnings [ 0 ] ;
2020-08-29 10:49:45 +00:00
return pCurWarning ;
}
}
2021-03-26 10:30:24 +00:00
const char * CGraphics_Threaded : : GetVendorString ( )
{
return m_pBackend - > GetVendorString ( ) ;
}
const char * CGraphics_Threaded : : GetVersionString ( )
{
return m_pBackend - > GetVersionString ( ) ;
}
const char * CGraphics_Threaded : : GetRendererString ( )
{
return m_pBackend - > GetRendererString ( ) ;
}
2015-08-24 20:46:28 +00:00
int CGraphics_Threaded : : GetVideoModes ( CVideoMode * pModes , int MaxModes , int Screen )
2011-12-31 00:06:04 +00:00
{
2021-05-07 09:53:52 +00:00
if ( g_Config . m_GfxDisplayAllVideoModes )
2011-12-31 00:06:04 +00:00
{
2020-09-26 19:41:58 +00:00
int Count = sizeof ( g_aFakeModes ) / sizeof ( CVideoMode ) ;
2011-12-31 00:06:04 +00:00
mem_copy ( pModes , g_aFakeModes , sizeof ( g_aFakeModes ) ) ;
if ( MaxModes < Count )
Count = MaxModes ;
return Count ;
}
2012-01-01 13:30:45 +00:00
// add videomodes command
CImageInfo Image ;
mem_zero ( & Image , sizeof ( Image ) ) ;
2011-12-31 00:06:04 +00:00
2012-01-01 13:30:45 +00:00
int NumModes = 0 ;
2021-08-21 19:41:51 +00:00
m_pBackend - > GetVideoModes ( pModes , MaxModes , & NumModes , m_ScreenHiDPIScale , g_Config . m_GfxDesktopWidth , g_Config . m_GfxDesktopHeight , Screen ) ;
2021-04-07 17:03:07 +00:00
2012-01-01 13:30:45 +00:00
return NumModes ;
2011-12-31 00:06:04 +00:00
}
2021-09-09 11:23:02 +00:00
extern IEngineGraphics * CreateEngineGraphicsThreaded ( )
{
# ifdef CONF_HEADLESS_CLIENT
return new CGraphics_ThreadedNull ( ) ;
# else
return new CGraphics_Threaded ( ) ;
# endif
}