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>
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
2020-09-26 19:41:58 +00:00
# include <engine/console.h>
2022-06-21 13:26:23 +00:00
# include <engine/gfx/image_loader.h>
# include <engine/gfx/image_manipulation.h>
2011-12-31 00:06:04 +00:00
# include <engine/graphics.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-06-19 06:19:40 +00:00
# if defined(CONF_VIDEORECORDER)
2022-06-16 17:50:46 +00:00
# include <engine/shared/video.h>
2020-06-19 06:19:40 +00:00
# endif
2011-12-31 00:11:24 +00:00
# include "graphics_threaded.h"
2011-12-31 00:06:04 +00:00
2022-06-16 17:50:46 +00:00
class CSemaphore ;
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-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 ;
}
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 ;
}
2022-03-20 17:03:25 +00:00
uint64_t CGraphics_Threaded : : TextureMemoryUsage ( ) const
2011-12-31 00:06:04 +00:00
{
2022-03-20 17:03:25 +00:00
return m_pBackend - > TextureMemoryUsage ( ) ;
}
uint64_t CGraphics_Threaded : : BufferMemoryUsage ( ) const
{
return m_pBackend - > BufferMemoryUsage ( ) ;
}
uint64_t CGraphics_Threaded : : StreamedMemoryUsage ( ) const
{
return m_pBackend - > StreamedMemoryUsage ( ) ;
}
uint64_t CGraphics_Threaded : : StagingMemoryUsage ( ) const
{
return m_pBackend - > StagingMemoryUsage ( ) ;
}
const TTWGraphicsGPUList & CGraphics_Threaded : : GetGPUs ( ) const
{
return m_pBackend - > GetGPUs ( ) ;
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
}
2021-09-13 12:55:21 +00:00
int CGraphics_Threaded : : UnloadTexture ( CTextureHandle * pIndex )
2011-12-31 00:06:04 +00:00
{
2021-09-13 12:55:21 +00:00
if ( pIndex - > Id ( ) = = m_InvalidTexture . Id ( ) )
2011-12-31 00:06:04 +00:00
return 0 ;
2021-09-13 12:55:21 +00:00
if ( ! pIndex - > IsValid ( ) )
2011-12-31 00:06:04 +00:00
return 0 ;
2011-12-31 08:40:11 +00:00
CCommandBuffer : : SCommand_Texture_Destroy Cmd ;
2021-09-13 12:55:21 +00:00
Cmd . m_Slot = pIndex - > 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
2022-06-11 19:38:18 +00:00
m_vTextureIndices [ pIndex - > Id ( ) ] = m_FirstFreeTexture ;
2021-09-13 12:55:21 +00:00
m_FirstFreeTexture = pIndex - > Id ( ) ;
2011-12-31 00:06:04 +00:00
2021-09-13 12:55:21 +00:00
pIndex - > Invalidate ( ) ;
2011-12-31 00:06:04 +00:00
return 0 ;
2020-10-09 07:07:05 +00:00
}
2012-10-06 21:31:02 +00:00
static int ImageFormatToPixelSize ( int Format )
{
switch ( Format )
{
case CImageInfo : : FORMAT_RGB : return 3 ;
2022-03-20 17:03:25 +00:00
case CImageInfo : : FORMAT_SINGLE_COMPONENT : return 1 ;
2012-10-06 21:31:02 +00:00
default : return 4 ;
}
}
2022-03-20 17:03:25 +00:00
static bool ConvertToRGBA ( uint8_t * pDest , const uint8_t * pSrc , size_t SrcWidth , size_t SrcHeight , int SrcFormat )
{
if ( SrcFormat = = CImageInfo : : FORMAT_RGBA )
{
mem_copy ( pDest , pSrc , SrcWidth * SrcHeight * 4 ) ;
return true ;
}
else
{
size_t SrcChannelCount = ImageFormatToPixelSize ( SrcFormat ) ;
size_t DstChannelCount = 4 ;
for ( size_t Y = 0 ; Y < SrcHeight ; + + Y )
{
2022-03-22 19:24:27 +00:00
for ( size_t X = 0 ; X < SrcWidth ; + + X )
2022-03-20 17:03:25 +00:00
{
size_t ImgOffsetSrc = ( Y * SrcWidth * SrcChannelCount ) + ( X * SrcChannelCount ) ;
size_t ImgOffsetDest = ( Y * SrcWidth * DstChannelCount ) + ( X * DstChannelCount ) ;
size_t CopySize = SrcChannelCount ;
if ( SrcChannelCount = = 3 )
{
mem_copy ( & pDest [ ImgOffsetDest ] , & pSrc [ ImgOffsetSrc ] , CopySize ) ;
pDest [ ImgOffsetDest + 3 ] = 255 ;
}
else if ( SrcChannelCount = = 1 )
{
pDest [ ImgOffsetDest + 0 ] = 255 ;
pDest [ ImgOffsetDest + 1 ] = 255 ;
pDest [ ImgOffsetDest + 2 ] = 255 ;
pDest [ ImgOffsetDest + 3 ] = pSrc [ ImgOffsetSrc ] ;
}
}
}
return false ;
}
}
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 ;
2022-03-20 17:03:25 +00:00
Cmd . m_Format = CCommandBuffer : : TEXFORMAT_RGBA ;
2011-12-31 08:40:11 +00:00
// calculate memory usage
2022-03-20 17:03:25 +00:00
int MemSize = Width * Height * 4 ;
2011-12-31 08:40:11 +00:00
// copy texture data
2018-04-09 09:56:39 +00:00
void * pTmpData = malloc ( MemSize ) ;
2022-03-20 17:03:25 +00:00
ConvertToRGBA ( ( uint8_t * ) pTmpData , ( const uint8_t * ) pData , Width , Height , Format ) ;
2011-12-31 08:40:11 +00:00
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 ) ;
2022-06-11 20:03:23 +00:00
m_vSpriteHelper . resize ( ( size_t ) w * h * bpp ) ;
2020-10-09 07:07:05 +00:00
2022-07-10 19:22:50 +00:00
CopyTextureFromTextureBufferSub ( m_vSpriteHelper . data ( ) , w , h , ( uint8_t * ) FromImageInfo . m_pData , FromImageInfo . m_Width , FromImageInfo . m_Height , bpp , x , y , w , h ) ;
2020-10-09 07:07:05 +00:00
2022-07-10 19:22:50 +00:00
IGraphics : : CTextureHandle RetHandle = LoadTextureRaw ( w , h , FromImageInfo . m_Format , m_vSpriteHelper . data ( ) , FromImageInfo . m_Format , 0 ) ;
2020-10-09 07:07:05 +00:00
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 )
{
2022-03-20 17:03:25 +00:00
if ( FromImageInfo . m_Format = = CImageInfo : : FORMAT_SINGLE_COMPONENT | | FromImageInfo . m_Format = = CImageInfo : : FORMAT_RGBA )
2020-10-09 07:07:05 +00:00
{
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
2022-06-11 19:38:18 +00:00
m_vWarnings . emplace_back ( NewWarning ) ;
2020-09-15 20:19:50 +00:00
}
}
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 )
{
2022-06-11 19:38:18 +00:00
size_t CurSize = m_vTextureIndices . size ( ) ;
m_vTextureIndices . resize ( CurSize * 2 ) ;
2020-11-18 11:41:20 +00:00
for ( size_t i = 0 ; i < CurSize - 1 ; + + i )
{
2022-06-11 19:38:18 +00:00
m_vTextureIndices [ CurSize + i ] = CurSize + i + 1 ;
2020-11-18 11:41:20 +00:00
}
2022-06-11 19:38:18 +00:00
m_vTextureIndices . back ( ) = - 1 ;
2020-11-18 11:41:20 +00:00
Tex = CurSize ;
}
2022-06-11 19:38:18 +00:00
m_FirstFreeTexture = m_vTextureIndices [ Tex ] ;
m_vTextureIndices [ 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 ;
2022-03-20 17:03:25 +00:00
Cmd . m_PixelSize = 4 ;
Cmd . m_Format = CCommandBuffer : : TEXFORMAT_RGBA ;
Cmd . m_StoreFormat = CCommandBuffer : : TEXFORMAT_RGBA ;
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 ) ;
2022-03-20 17:03:25 +00:00
if ( ! ConvertToRGBA ( ( uint8_t * ) pTmpData , ( const uint8_t * ) pData , Width , Height , Format ) )
{
2022-03-22 19:24:27 +00:00
dbg_msg ( " graphics " , " converted image %s to RGBA, consider making its file format RGBA " , pTexName ? pTexName : " (no name) " ) ;
2022-03-20 17:03:25 +00:00
}
2011-12-31 08:40:11 +00:00
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 ;
}
2022-03-20 17:03:25 +00:00
bool CGraphics_Threaded : : LoadTextTextures ( int Width , int Height , CTextureHandle & TextTexture , CTextureHandle & TextOutlineTexture , void * pTextData , void * pTextOutlineData )
{
if ( Width = = 0 | | Height = = 0 )
return false ;
// grab texture
int Tex = m_FirstFreeTexture ;
if ( Tex = = - 1 )
{
2022-06-11 19:38:18 +00:00
size_t CurSize = m_vTextureIndices . size ( ) ;
m_vTextureIndices . resize ( CurSize * 2 ) ;
2022-03-20 17:03:25 +00:00
for ( size_t i = 0 ; i < CurSize - 1 ; + + i )
{
2022-06-11 19:38:18 +00:00
m_vTextureIndices [ CurSize + i ] = CurSize + i + 1 ;
2022-03-20 17:03:25 +00:00
}
2022-06-11 19:38:18 +00:00
m_vTextureIndices . back ( ) = - 1 ;
2022-03-20 17:03:25 +00:00
Tex = CurSize ;
}
2022-06-11 19:38:18 +00:00
m_FirstFreeTexture = m_vTextureIndices [ Tex ] ;
m_vTextureIndices [ Tex ] = - 1 ;
2022-03-20 17:03:25 +00:00
int Tex2 = m_FirstFreeTexture ;
if ( Tex2 = = - 1 )
{
2022-06-11 19:38:18 +00:00
size_t CurSize = m_vTextureIndices . size ( ) ;
m_vTextureIndices . resize ( CurSize * 2 ) ;
2022-03-20 17:03:25 +00:00
for ( size_t i = 0 ; i < CurSize - 1 ; + + i )
{
2022-06-11 19:38:18 +00:00
m_vTextureIndices [ CurSize + i ] = CurSize + i + 1 ;
2022-03-20 17:03:25 +00:00
}
2022-06-11 19:38:18 +00:00
m_vTextureIndices . back ( ) = - 1 ;
2022-03-20 17:03:25 +00:00
Tex2 = CurSize ;
}
2022-06-11 19:38:18 +00:00
m_FirstFreeTexture = m_vTextureIndices [ Tex2 ] ;
m_vTextureIndices [ Tex2 ] = - 1 ;
2022-03-20 17:03:25 +00:00
CCommandBuffer : : SCommand_TextTextures_Create Cmd ;
Cmd . m_Slot = Tex ;
Cmd . m_SlotOutline = Tex2 ;
Cmd . m_Width = Width ;
Cmd . m_Height = Height ;
Cmd . m_pTextData = pTextData ;
Cmd . m_pTextOutlineData = pTextOutlineData ;
AddCmd (
Cmd , [ ] { return true ; } , " failed to load text textures. " ) ;
TextTexture = CreateTextureHandle ( Tex ) ;
TextOutlineTexture = CreateTextureHandle ( Tex2 ) ;
return true ;
}
bool CGraphics_Threaded : : UnloadTextTextures ( CTextureHandle & TextTexture , CTextureHandle & TextOutlineTexture )
{
CCommandBuffer : : SCommand_TextTextures_Destroy Cmd ;
Cmd . m_Slot = TextTexture . Id ( ) ;
Cmd . m_SlotOutline = TextOutlineTexture . Id ( ) ;
AddCmd (
Cmd , [ ] { return true ; } , " failed to unload text textures. " ) ;
2022-06-11 19:38:18 +00:00
m_vTextureIndices [ TextTexture . Id ( ) ] = m_FirstFreeTexture ;
2022-03-20 17:03:25 +00:00
m_FirstFreeTexture = TextTexture . Id ( ) ;
2022-06-11 19:38:18 +00:00
m_vTextureIndices [ TextOutlineTexture . Id ( ) ] = m_FirstFreeTexture ;
2022-03-20 17:03:25 +00:00
m_FirstFreeTexture = TextOutlineTexture . Id ( ) ;
TextTexture . Invalidate ( ) ;
TextOutlineTexture . Invalidate ( ) ;
return true ;
}
bool CGraphics_Threaded : : UpdateTextTexture ( CTextureHandle TextureID , int x , int y , int Width , int Height , const void * pData )
{
CCommandBuffer : : SCommand_TextTexture_Update Cmd ;
Cmd . m_Slot = TextureID . Id ( ) ;
Cmd . m_X = x ;
Cmd . m_Y = y ;
Cmd . m_Width = Width ;
Cmd . m_Height = Height ;
// calculate memory usage
int MemSize = Width * Height ;
// copy texture data
void * pTmpData = malloc ( MemSize ) ;
mem_copy ( pTmpData , pData , MemSize ) ;
Cmd . m_pData = pTmpData ;
AddCmd (
Cmd , [ ] { return true ; } , " failed to update text texture. " ) ;
2022-03-20 17:04:00 +00:00
return true ;
2022-03-20 17:03:25 +00:00
}
2011-12-31 00:06:04 +00:00
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
IOHANDLE File = m_pStorage - > OpenFile ( pFilename , IOFLAG_READ , StorageType , aCompleteFilename , sizeof ( aCompleteFilename ) ) ;
2022-06-11 07:09:42 +00:00
if ( File )
2011-12-31 00:06:04 +00:00
{
2022-06-11 07:09:42 +00:00
io_seek ( File , 0 , IOSEEK_END ) ;
unsigned int FileSize = io_tell ( File ) ;
io_seek ( File , 0 , IOSEEK_START ) ;
2011-12-31 00:06:04 +00:00
2022-06-11 07:09:42 +00:00
TImageByteBuffer ByteBuffer ;
SImageByteBuffer ImageByteBuffer ( & ByteBuffer ) ;
2011-12-31 00:06:04 +00:00
2022-06-11 07:09:42 +00:00
ByteBuffer . resize ( FileSize ) ;
io_read ( File , & ByteBuffer . front ( ) , FileSize ) ;
2011-12-31 00:06:04 +00:00
2021-11-05 16:21:41 +00:00
io_close ( File ) ;
2022-06-11 07:09:42 +00:00
uint8_t * pImgBuffer = NULL ;
EImageFormat ImageFormat ;
2022-06-27 14:57:23 +00:00
int PngliteIncompatible ;
if ( : : LoadPNG ( ImageByteBuffer , pFilename , PngliteIncompatible , pImg - > m_Width , pImg - > m_Height , pImgBuffer , ImageFormat ) )
2022-06-11 07:09:42 +00:00
{
pImg - > m_pData = pImgBuffer ;
if ( ImageFormat = = IMAGE_FORMAT_RGB ) // ignore_convention
pImg - > m_Format = CImageInfo : : FORMAT_RGB ;
else if ( ImageFormat = = IMAGE_FORMAT_RGBA ) // ignore_convention
pImg - > m_Format = CImageInfo : : FORMAT_RGBA ;
else
{
free ( pImgBuffer ) ;
return 0 ;
}
2022-06-27 14:57:23 +00:00
if ( m_WarnPngliteIncompatibleImages & & PngliteIncompatible ! = 0 )
{
SWarning Warning ;
str_format ( Warning . m_aWarningMsg , sizeof ( Warning . m_aWarningMsg ) , Localize ( " \" %s \" is not compatible with pnglite and cannot be loaded by old DDNet versions: " ) , pFilename ) ;
static const int FLAGS [ ] = { PNGLITE_COLOR_TYPE , PNGLITE_BIT_DEPTH , PNGLITE_INTERLACE_TYPE , PNGLITE_COMPRESSION_TYPE , PNGLITE_FILTER_TYPE } ;
static const char * EXPLANATION [ ] = { " color type " , " bit depth " , " interlace type " , " compression type " , " filter type " } ;
bool First = true ;
for ( int i = 0 ; i < ( int ) std : : size ( FLAGS ) ; i + + )
{
if ( ( PngliteIncompatible & FLAGS [ i ] ) ! = 0 )
{
if ( ! First )
{
str_append ( Warning . m_aWarningMsg , " , " , sizeof ( Warning . m_aWarningMsg ) ) ;
}
str_append ( Warning . m_aWarningMsg , EXPLANATION [ i ] , sizeof ( Warning . m_aWarningMsg ) ) ;
First = false ;
}
}
2022-08-08 14:09:39 +00:00
str_append ( Warning . m_aWarningMsg , " unsupported " , sizeof ( Warning . m_aWarningMsg ) ) ;
2022-06-27 14:57:23 +00:00
m_vWarnings . emplace_back ( Warning ) ;
}
2022-06-11 07:09:42 +00:00
}
else
{
dbg_msg ( " game/png " , " image had unsupported image format. filename='%s' " , pFilename ) ;
return 0 ;
}
2020-09-30 16:03:06 +00:00
}
2020-10-12 16:50:23 +00:00
else
{
2022-06-11 07:09:42 +00:00
dbg_msg ( " game/png " , " failed to open file. filename='%s' " , pFilename ) ;
2020-10-12 16:50:23 +00:00
return 0 ;
}
2022-06-11 07:09:42 +00:00
2011-12-31 00:06:04 +00:00
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 ) ;
2022-06-11 19:38:18 +00:00
m_vWarnings . emplace_back ( NewWarning ) ;
2020-11-18 06:36:19 +00:00
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 ;
2022-03-20 17:03:25 +00:00
if ( Img . m_Format = = CImageInfo : : FORMAT_SINGLE_COMPONENT )
2020-11-18 06:36:19 +00:00
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 ;
}
2022-02-22 23:39:31 +00:00
bool CGraphics_Threaded : : IsImageFormatRGBA ( const char * pFileName , CImageInfo & Img )
2022-02-22 18:43:14 +00:00
{
2022-03-20 17:04:00 +00:00
if ( Img . m_Format ! = CImageInfo : : FORMAT_RGBA )
2022-02-22 18:43:14 +00:00
{
SWarning NewWarning ;
char aText [ 128 ] ;
aText [ 0 ] = ' \0 ' ;
if ( pFileName )
{
str_format ( aText , sizeof ( aText ) , " \" %s \" " , pFileName ) ;
}
str_format ( NewWarning . m_aWarningMsg , sizeof ( NewWarning . m_aWarningMsg ) ,
Localize ( " The format of texture %s is not RGBA which will cause visual bugs. " ) , aText ) ;
2022-06-11 19:38:18 +00:00
m_vWarnings . emplace_back ( NewWarning ) ;
2022-02-22 18:43:14 +00:00
return false ;
}
return true ;
}
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 ( ) ;
}
2022-03-20 17:04:00 +00:00
bool CGraphics_Threaded : : ScreenshotDirect ( )
2014-01-19 03:02:01 +00:00
{
2012-01-01 13:15:35 +00:00
// add swap command
CImageInfo Image ;
mem_zero ( & Image , sizeof ( Image ) ) ;
2022-03-20 17:04:00 +00:00
bool DidSwap = false ;
CCommandBuffer : : SCommand_TrySwapAndScreenshot Cmd ;
2012-01-01 13:15:35 +00:00
Cmd . m_pImage = & Image ;
2022-03-20 17:04:00 +00:00
Cmd . m_pSwapped = & DidSwap ;
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 ] ;
2014-03-29 16:04:06 +00:00
IOHANDLE File = m_pStorage - > OpenFile ( m_aScreenshotName , IOFLAG_WRITE , IStorage : : TYPE_SAVE , aWholePath , sizeof ( aWholePath ) ) ;
2022-06-11 07:09:42 +00:00
if ( File )
2021-11-05 16:21:41 +00:00
{
char aBuf [ 256 ] ;
str_format ( aBuf , sizeof ( aBuf ) , " saved screenshot to '%s' " , aWholePath ) ;
2022-06-11 07:09:42 +00:00
// save png
m_pConsole - > Print ( IConsole : : OUTPUT_LEVEL_STANDARD , " client " , aBuf , ColorRGBA { 1.0f , 0.6f , 0.3f , 1.0f } ) ;
TImageByteBuffer ByteBuffer ;
SImageByteBuffer ImageByteBuffer ( & ByteBuffer ) ;
if ( SavePNG ( IMAGE_FORMAT_RGBA , ( const uint8_t * ) Image . m_pData , ImageByteBuffer , Image . m_Width , Image . m_Height ) )
io_write ( File , & ByteBuffer . front ( ) , ByteBuffer . size ( ) ) ;
2022-02-16 19:54:11 +00:00
io_close ( File ) ;
2021-11-05 16:21:41 +00:00
}
2011-12-31 00:06:04 +00:00
2018-04-09 09:56:39 +00:00
free ( Image . m_pData ) ;
2012-01-01 13:15:35 +00:00
}
2022-03-20 17:04:00 +00:00
return DidSwap ;
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 " ) ;
2022-09-10 10:19:38 +00:00
dbg_assert ( ! TextureID . IsValid ( ) | | m_vTextureIndices [ TextureID . Id ( ) ] = = - 1 , " Texture handle was not invalid, but also did not correlate to an existing texture. " ) ;
2012-08-12 12:02:50 +00:00
m_State . m_Texture = TextureID . Id ( ) ;
2011-12-31 00:06:04 +00:00
}
2022-03-20 17:04:00 +00:00
void CGraphics_Threaded : : Clear ( float r , float g , float b , bool ForceClearNow )
2011-12-31 00:06:04 +00:00
{
CCommandBuffer : : SCommand_Clear Cmd ;
Cmd . m_Color . r = r ;
Cmd . m_Color . g = g ;
Cmd . m_Color . b = b ;
Cmd . m_Color . a = 0 ;
2022-04-03 10:45:23 +00:00
Cmd . m_ForceClear = ForceClearNow ;
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 ;
}
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
}
2022-07-09 20:49:09 +00:00
void CGraphics_Threaded : : SetColor ( ColorRGBA Color )
2019-04-26 22:11:15 +00:00
{
2022-07-09 20:49:09 +00:00
SetColor ( Color . r , Color . g , Color . b , Color . a ) ;
2019-04-26 22:11:15 +00:00
}
2022-07-09 20:49:09 +00:00
void CGraphics_Threaded : : SetColor4 ( ColorRGBA TopLeft , ColorRGBA TopRight , ColorRGBA BottomLeft , ColorRGBA BottomRight )
2020-09-03 12:08:26 +00:00
{
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 )
{
2022-03-20 17:03:25 +00:00
if ( g_Config . m_GfxQuadAsTriangle & & ! m_GLUseTrianglesAsQuad )
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 ;
2022-03-20 17:03:25 +00:00
if ( g_Config . m_GfxQuadAsTriangle & & ! m_GLUseTrianglesAsQuad )
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
2022-03-20 17:03:25 +00:00
if ( ( g_Config . m_GfxQuadAsTriangle & & ! m_GLUseTrianglesAsQuad ) | | 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
}
}
}
2022-07-09 20:27:35 +00:00
void CGraphics_Threaded : : DrawRectExt ( float x , float y , float w , float h , float r , int Corners )
{
2022-07-09 20:49:09 +00:00
const int NumSegments = 8 ;
const float SegmentsAngle = pi / 2 / NumSegments ;
IGraphics : : CFreeformItem aFreeform [ NumSegments * 4 ] ;
size_t NumItems = 0 ;
2022-07-09 20:27:35 +00:00
2022-07-09 20:49:09 +00:00
for ( int i = 0 ; i < NumSegments ; i + = 2 )
2022-07-09 20:27:35 +00:00
{
2022-07-09 20:49:09 +00:00
float a1 = i * SegmentsAngle ;
float a2 = ( i + 1 ) * SegmentsAngle ;
float a3 = ( i + 2 ) * SegmentsAngle ;
2022-07-09 20:27:35 +00:00
float Ca1 = cosf ( a1 ) ;
float Ca2 = cosf ( a2 ) ;
float Ca3 = cosf ( a3 ) ;
float Sa1 = sinf ( a1 ) ;
float Sa2 = sinf ( a2 ) ;
float Sa3 = sinf ( a3 ) ;
2022-07-09 20:49:09 +00:00
if ( Corners & CORNER_TL )
aFreeform [ NumItems + + ] = IGraphics : : CFreeformItem (
2022-07-09 20:27:35 +00:00
x + r , y + r ,
x + ( 1 - Ca1 ) * r , y + ( 1 - Sa1 ) * r ,
x + ( 1 - Ca3 ) * r , y + ( 1 - Sa3 ) * r ,
x + ( 1 - Ca2 ) * r , y + ( 1 - Sa2 ) * r ) ;
2022-07-09 20:49:09 +00:00
if ( Corners & CORNER_TR )
aFreeform [ NumItems + + ] = IGraphics : : CFreeformItem (
2022-07-09 20:27:35 +00:00
x + w - r , y + r ,
x + w - r + Ca1 * r , y + ( 1 - Sa1 ) * r ,
x + w - r + Ca3 * r , y + ( 1 - Sa3 ) * r ,
x + w - r + Ca2 * r , y + ( 1 - Sa2 ) * r ) ;
2022-07-09 20:49:09 +00:00
if ( Corners & CORNER_BL )
aFreeform [ NumItems + + ] = IGraphics : : CFreeformItem (
2022-07-09 20:27:35 +00:00
x + r , y + h - r ,
x + ( 1 - Ca1 ) * r , y + h - r + Sa1 * r ,
x + ( 1 - Ca3 ) * r , y + h - r + Sa3 * r ,
x + ( 1 - Ca2 ) * r , y + h - r + Sa2 * r ) ;
2022-07-09 20:49:09 +00:00
if ( Corners & CORNER_BR )
aFreeform [ NumItems + + ] = IGraphics : : CFreeformItem (
2022-07-09 20:27:35 +00:00
x + w - r , y + h - r ,
x + w - r + Ca1 * r , y + h - r + Sa1 * r ,
x + w - r + Ca3 * r , y + h - r + Sa3 * r ,
x + w - r + Ca2 * r , y + h - r + Sa2 * r ) ;
}
2022-07-09 20:49:09 +00:00
QuadsDrawFreeform ( aFreeform , NumItems ) ;
2022-07-09 20:27:35 +00:00
2022-07-09 20:49:09 +00:00
CQuadItem aQuads [ 9 ] ;
2022-07-09 20:27:35 +00:00
NumItems = 0 ;
2022-07-09 20:49:09 +00:00
aQuads [ NumItems + + ] = CQuadItem ( x + r , y + r , w - r * 2 , h - r * 2 ) ; // center
aQuads [ NumItems + + ] = CQuadItem ( x + r , y , w - r * 2 , r ) ; // top
aQuads [ NumItems + + ] = CQuadItem ( x + r , y + h - r , w - r * 2 , r ) ; // bottom
aQuads [ NumItems + + ] = CQuadItem ( x , y + r , r , h - r * 2 ) ; // left
aQuads [ NumItems + + ] = CQuadItem ( x + w - r , y + r , r , h - r * 2 ) ; // right
2022-07-09 20:27:35 +00:00
2022-07-09 20:49:09 +00:00
if ( ! ( Corners & CORNER_TL ) )
aQuads [ NumItems + + ] = CQuadItem ( x , y , r , r ) ;
if ( ! ( Corners & CORNER_TR ) )
aQuads [ NumItems + + ] = CQuadItem ( x + w , y , - r , r ) ;
if ( ! ( Corners & CORNER_BL ) )
aQuads [ NumItems + + ] = CQuadItem ( x , y + h , r , - r ) ;
if ( ! ( Corners & CORNER_BR ) )
aQuads [ NumItems + + ] = CQuadItem ( x + w , y + h , - r , - r ) ;
2022-07-09 20:27:35 +00:00
2022-07-09 20:49:09 +00:00
QuadsDrawTL ( aQuads , NumItems ) ;
2022-07-09 20:27:35 +00:00
}
2022-07-09 20:49:09 +00:00
void CGraphics_Threaded : : DrawRectExt4 ( float x , float y , float w , float h , ColorRGBA ColorTopLeft , ColorRGBA ColorTopRight , ColorRGBA ColorBottomLeft , ColorRGBA ColorBottomRight , float r , int Corners )
2022-07-09 20:27:35 +00:00
{
if ( Corners = = 0 | | r = = 0.0f )
{
SetColor4 ( ColorTopLeft , ColorTopRight , ColorBottomLeft , ColorBottomRight ) ;
CQuadItem ItemQ = CQuadItem ( x , y , w , h ) ;
QuadsDrawTL ( & ItemQ , 1 ) ;
return ;
}
2022-07-09 20:49:09 +00:00
const int NumSegments = 8 ;
const float SegmentsAngle = pi / 2 / NumSegments ;
for ( int i = 0 ; i < NumSegments ; i + = 2 )
2022-07-09 20:27:35 +00:00
{
2022-07-09 20:49:09 +00:00
float a1 = i * SegmentsAngle ;
float a2 = ( i + 1 ) * SegmentsAngle ;
float a3 = ( i + 2 ) * SegmentsAngle ;
2022-07-09 20:27:35 +00:00
float Ca1 = cosf ( a1 ) ;
float Ca2 = cosf ( a2 ) ;
float Ca3 = cosf ( a3 ) ;
float Sa1 = sinf ( a1 ) ;
float Sa2 = sinf ( a2 ) ;
float Sa3 = sinf ( a3 ) ;
2022-07-09 20:49:09 +00:00
if ( Corners & CORNER_TL )
2022-07-09 20:27:35 +00:00
{
2022-07-09 20:49:09 +00:00
SetColor ( ColorTopLeft ) ;
2022-07-09 20:27:35 +00:00
IGraphics : : CFreeformItem ItemF = IGraphics : : CFreeformItem (
x + r , y + r ,
x + ( 1 - Ca1 ) * r , y + ( 1 - Sa1 ) * r ,
x + ( 1 - Ca3 ) * r , y + ( 1 - Sa3 ) * r ,
x + ( 1 - Ca2 ) * r , y + ( 1 - Sa2 ) * r ) ;
QuadsDrawFreeform ( & ItemF , 1 ) ;
}
2022-07-09 20:49:09 +00:00
if ( Corners & CORNER_TR )
2022-07-09 20:27:35 +00:00
{
2022-07-09 20:49:09 +00:00
SetColor ( ColorTopRight ) ;
2022-07-09 20:27:35 +00:00
IGraphics : : CFreeformItem ItemF = IGraphics : : CFreeformItem (
x + w - r , y + r ,
x + w - r + Ca1 * r , y + ( 1 - Sa1 ) * r ,
x + w - r + Ca3 * r , y + ( 1 - Sa3 ) * r ,
x + w - r + Ca2 * r , y + ( 1 - Sa2 ) * r ) ;
QuadsDrawFreeform ( & ItemF , 1 ) ;
}
2022-07-09 20:49:09 +00:00
if ( Corners & CORNER_BL )
2022-07-09 20:27:35 +00:00
{
2022-07-09 20:49:09 +00:00
SetColor ( ColorBottomLeft ) ;
2022-07-09 20:27:35 +00:00
IGraphics : : CFreeformItem ItemF = IGraphics : : CFreeformItem (
x + r , y + h - r ,
x + ( 1 - Ca1 ) * r , y + h - r + Sa1 * r ,
x + ( 1 - Ca3 ) * r , y + h - r + Sa3 * r ,
x + ( 1 - Ca2 ) * r , y + h - r + Sa2 * r ) ;
QuadsDrawFreeform ( & ItemF , 1 ) ;
}
2022-07-09 20:49:09 +00:00
if ( Corners & CORNER_BR )
2022-07-09 20:27:35 +00:00
{
2022-07-09 20:49:09 +00:00
SetColor ( ColorBottomRight ) ;
2022-07-09 20:27:35 +00:00
IGraphics : : CFreeformItem ItemF = IGraphics : : CFreeformItem (
x + w - r , y + h - r ,
x + w - r + Ca1 * r , y + h - r + Sa1 * r ,
x + w - r + Ca3 * r , y + h - r + Sa3 * r ,
x + w - r + Ca2 * r , y + h - r + Sa2 * r ) ;
QuadsDrawFreeform ( & ItemF , 1 ) ;
}
2022-07-09 20:49:09 +00:00
if ( Corners & CORNER_ITL )
2022-07-09 20:27:35 +00:00
{
2022-07-09 20:49:09 +00:00
SetColor ( ColorTopLeft ) ;
2022-07-09 20:27:35 +00:00
IGraphics : : CFreeformItem ItemF = IGraphics : : CFreeformItem (
x , y ,
x + ( 1 - Ca1 ) * r , y - r + Sa1 * r ,
x + ( 1 - Ca3 ) * r , y - r + Sa3 * r ,
x + ( 1 - Ca2 ) * r , y - r + Sa2 * r ) ;
QuadsDrawFreeform ( & ItemF , 1 ) ;
}
2022-07-09 20:49:09 +00:00
if ( Corners & CORNER_ITR )
2022-07-09 20:27:35 +00:00
{
2022-07-09 20:49:09 +00:00
SetColor ( ColorTopRight ) ;
2022-07-09 20:27:35 +00:00
IGraphics : : CFreeformItem ItemF = IGraphics : : CFreeformItem (
x + w , y ,
x + w - r + Ca1 * r , y - r + Sa1 * r ,
x + w - r + Ca3 * r , y - r + Sa3 * r ,
x + w - r + Ca2 * r , y - r + Sa2 * r ) ;
QuadsDrawFreeform ( & ItemF , 1 ) ;
}
2022-07-09 20:49:09 +00:00
if ( Corners & CORNER_IBL )
2022-07-09 20:27:35 +00:00
{
2022-07-09 20:49:09 +00:00
SetColor ( ColorBottomLeft ) ;
2022-07-09 20:27:35 +00:00
IGraphics : : CFreeformItem ItemF = IGraphics : : CFreeformItem (
x , y + h ,
x + ( 1 - Ca1 ) * r , y + h + ( 1 - Sa1 ) * r ,
x + ( 1 - Ca3 ) * r , y + h + ( 1 - Sa3 ) * r ,
x + ( 1 - Ca2 ) * r , y + h + ( 1 - Sa2 ) * r ) ;
QuadsDrawFreeform ( & ItemF , 1 ) ;
}
2022-07-09 20:49:09 +00:00
if ( Corners & CORNER_IBR )
2022-07-09 20:27:35 +00:00
{
2022-07-09 20:49:09 +00:00
SetColor ( ColorBottomRight ) ;
2022-07-09 20:27:35 +00:00
IGraphics : : CFreeformItem ItemF = IGraphics : : CFreeformItem (
x + w , y + h ,
x + w - r + Ca1 * r , y + h + ( 1 - Sa1 ) * r ,
x + w - r + Ca3 * r , y + h + ( 1 - Sa3 ) * r ,
x + w - r + Ca2 * r , y + h + ( 1 - Sa2 ) * r ) ;
QuadsDrawFreeform ( & ItemF , 1 ) ;
}
}
SetColor4 ( ColorTopLeft , ColorTopRight , ColorBottomLeft , ColorBottomRight ) ;
CQuadItem ItemQ = CQuadItem ( x + r , y + r , w - r * 2 , h - r * 2 ) ; // center
QuadsDrawTL ( & ItemQ , 1 ) ;
2022-07-09 20:49:09 +00:00
2022-07-09 20:27:35 +00:00
SetColor4 ( ColorTopLeft , ColorTopRight , ColorTopLeft , ColorTopRight ) ;
ItemQ = CQuadItem ( x + r , y , w - r * 2 , r ) ; // top
QuadsDrawTL ( & ItemQ , 1 ) ;
2022-07-09 20:49:09 +00:00
2022-07-09 20:27:35 +00:00
SetColor4 ( ColorBottomLeft , ColorBottomRight , ColorBottomLeft , ColorBottomRight ) ;
ItemQ = CQuadItem ( x + r , y + h - r , w - r * 2 , r ) ; // bottom
QuadsDrawTL ( & ItemQ , 1 ) ;
2022-07-09 20:49:09 +00:00
2022-07-09 20:27:35 +00:00
SetColor4 ( ColorTopLeft , ColorTopLeft , ColorBottomLeft , ColorBottomLeft ) ;
ItemQ = CQuadItem ( x , y + r , r , h - r * 2 ) ; // left
QuadsDrawTL ( & ItemQ , 1 ) ;
2022-07-09 20:49:09 +00:00
2022-07-09 20:27:35 +00:00
SetColor4 ( ColorTopRight , ColorTopRight , ColorBottomRight , ColorBottomRight ) ;
ItemQ = CQuadItem ( x + w - r , y + r , r , h - r * 2 ) ; // right
QuadsDrawTL ( & ItemQ , 1 ) ;
2022-07-09 20:49:09 +00:00
if ( ! ( Corners & CORNER_TL ) )
2022-07-09 20:27:35 +00:00
{
2022-07-09 20:49:09 +00:00
SetColor ( ColorTopLeft ) ;
ItemQ = CQuadItem ( x , y , r , r ) ;
2022-07-09 20:27:35 +00:00
QuadsDrawTL ( & ItemQ , 1 ) ;
}
2022-07-09 20:49:09 +00:00
if ( ! ( Corners & CORNER_TR ) )
2022-07-09 20:27:35 +00:00
{
2022-07-09 20:49:09 +00:00
SetColor ( ColorTopRight ) ;
ItemQ = CQuadItem ( x + w , y , - r , r ) ;
2022-07-09 20:27:35 +00:00
QuadsDrawTL ( & ItemQ , 1 ) ;
}
2022-07-09 20:49:09 +00:00
if ( ! ( Corners & CORNER_BL ) )
2022-07-09 20:27:35 +00:00
{
2022-07-09 20:49:09 +00:00
SetColor ( ColorBottomLeft ) ;
ItemQ = CQuadItem ( x , y + h , r , - r ) ;
2022-07-09 20:27:35 +00:00
QuadsDrawTL ( & ItemQ , 1 ) ;
}
2022-07-09 20:49:09 +00:00
if ( ! ( Corners & CORNER_BR ) )
2022-07-09 20:27:35 +00:00
{
2022-07-09 20:49:09 +00:00
SetColor ( ColorBottomRight ) ;
ItemQ = CQuadItem ( x + w , y + h , - r , - r ) ;
2022-07-09 20:27:35 +00:00
QuadsDrawTL ( & ItemQ , 1 ) ;
}
}
int CGraphics_Threaded : : CreateRectQuadContainer ( float x , float y , float w , float h , float r , int Corners )
{
int ContainerIndex = CreateQuadContainer ( false ) ;
if ( Corners = = 0 | | r = = 0.0f )
{
CQuadItem ItemQ = CQuadItem ( x , y , w , h ) ;
QuadContainerAddQuads ( ContainerIndex , & ItemQ , 1 ) ;
QuadContainerUpload ( ContainerIndex ) ;
QuadContainerChangeAutomaticUpload ( ContainerIndex , true ) ;
return ContainerIndex ;
}
2022-07-09 20:49:09 +00:00
const int NumSegments = 8 ;
const float SegmentsAngle = pi / 2 / NumSegments ;
IGraphics : : CFreeformItem aFreeform [ NumSegments * 4 ] ;
size_t NumItems = 0 ;
for ( int i = 0 ; i < NumSegments ; i + = 2 )
2022-07-09 20:27:35 +00:00
{
2022-07-09 20:49:09 +00:00
float a1 = i * SegmentsAngle ;
float a2 = ( i + 1 ) * SegmentsAngle ;
float a3 = ( i + 2 ) * SegmentsAngle ;
2022-07-09 20:27:35 +00:00
float Ca1 = cosf ( a1 ) ;
float Ca2 = cosf ( a2 ) ;
float Ca3 = cosf ( a3 ) ;
float Sa1 = sinf ( a1 ) ;
float Sa2 = sinf ( a2 ) ;
float Sa3 = sinf ( a3 ) ;
2022-07-09 20:49:09 +00:00
if ( Corners & CORNER_TL )
aFreeform [ NumItems + + ] = IGraphics : : CFreeformItem (
2022-07-09 20:27:35 +00:00
x + r , y + r ,
x + ( 1 - Ca1 ) * r , y + ( 1 - Sa1 ) * r ,
x + ( 1 - Ca3 ) * r , y + ( 1 - Sa3 ) * r ,
x + ( 1 - Ca2 ) * r , y + ( 1 - Sa2 ) * r ) ;
2022-07-09 20:49:09 +00:00
if ( Corners & CORNER_TR )
aFreeform [ NumItems + + ] = IGraphics : : CFreeformItem (
2022-07-09 20:27:35 +00:00
x + w - r , y + r ,
x + w - r + Ca1 * r , y + ( 1 - Sa1 ) * r ,
x + w - r + Ca3 * r , y + ( 1 - Sa3 ) * r ,
x + w - r + Ca2 * r , y + ( 1 - Sa2 ) * r ) ;
2022-07-09 20:49:09 +00:00
if ( Corners & CORNER_BL )
aFreeform [ NumItems + + ] = IGraphics : : CFreeformItem (
2022-07-09 20:27:35 +00:00
x + r , y + h - r ,
x + ( 1 - Ca1 ) * r , y + h - r + Sa1 * r ,
x + ( 1 - Ca3 ) * r , y + h - r + Sa3 * r ,
x + ( 1 - Ca2 ) * r , y + h - r + Sa2 * r ) ;
2022-07-09 20:49:09 +00:00
if ( Corners & CORNER_BR )
aFreeform [ NumItems + + ] = IGraphics : : CFreeformItem (
2022-07-09 20:27:35 +00:00
x + w - r , y + h - r ,
x + w - r + Ca1 * r , y + h - r + Sa1 * r ,
x + w - r + Ca3 * r , y + h - r + Sa3 * r ,
x + w - r + Ca2 * r , y + h - r + Sa2 * r ) ;
}
if ( NumItems > 0 )
2022-07-09 20:49:09 +00:00
QuadContainerAddQuads ( ContainerIndex , aFreeform , NumItems ) ;
2022-07-09 20:27:35 +00:00
2022-07-09 20:49:09 +00:00
CQuadItem aQuads [ 9 ] ;
2022-07-09 20:27:35 +00:00
NumItems = 0 ;
2022-07-09 20:49:09 +00:00
aQuads [ NumItems + + ] = CQuadItem ( x + r , y + r , w - r * 2 , h - r * 2 ) ; // center
aQuads [ NumItems + + ] = CQuadItem ( x + r , y , w - r * 2 , r ) ; // top
aQuads [ NumItems + + ] = CQuadItem ( x + r , y + h - r , w - r * 2 , r ) ; // bottom
aQuads [ NumItems + + ] = CQuadItem ( x , y + r , r , h - r * 2 ) ; // left
aQuads [ NumItems + + ] = CQuadItem ( x + w - r , y + r , r , h - r * 2 ) ; // right
if ( ! ( Corners & CORNER_TL ) )
aQuads [ NumItems + + ] = CQuadItem ( x , y , r , r ) ;
if ( ! ( Corners & CORNER_TR ) )
aQuads [ NumItems + + ] = CQuadItem ( x + w , y , - r , r ) ;
if ( ! ( Corners & CORNER_BL ) )
aQuads [ NumItems + + ] = CQuadItem ( x , y + h , r , - r ) ;
if ( ! ( Corners & CORNER_BR ) )
aQuads [ NumItems + + ] = CQuadItem ( x + w , y + h , - r , - r ) ;
2022-07-09 20:27:35 +00:00
if ( NumItems > 0 )
2022-07-09 20:49:09 +00:00
QuadContainerAddQuads ( ContainerIndex , aQuads , NumItems ) ;
2022-07-09 20:27:35 +00:00
QuadContainerUpload ( ContainerIndex ) ;
QuadContainerChangeAutomaticUpload ( ContainerIndex , true ) ;
return ContainerIndex ;
}
void CGraphics_Threaded : : DrawRect ( float x , float y , float w , float h , ColorRGBA Color , int Corners , float Rounding )
{
TextureClear ( ) ;
QuadsBegin ( ) ;
SetColor ( Color ) ;
DrawRectExt ( x , y , w , h , Rounding , Corners ) ;
QuadsEnd ( ) ;
}
2022-07-09 20:49:09 +00:00
void CGraphics_Threaded : : DrawRect4 ( float x , float y , float w , float h , ColorRGBA ColorTopLeft , ColorRGBA ColorTopRight , ColorRGBA ColorBottomLeft , ColorRGBA ColorBottomRight , int Corners , float Rounding )
2022-07-09 20:27:35 +00:00
{
TextureClear ( ) ;
QuadsBegin ( ) ;
DrawRectExt4 ( x , y , w , h , ColorTopLeft , ColorTopRight , ColorBottomLeft , ColorBottomRight , Rounding , Corners ) ;
QuadsEnd ( ) ;
}
2022-07-09 11:26:42 +00:00
void CGraphics_Threaded : : DrawCircle ( float CenterX , float CenterY , float Radius , int Segments )
2022-07-09 11:16:12 +00:00
{
2022-07-09 11:26:42 +00:00
IGraphics : : CFreeformItem aItems [ 32 ] ;
size_t NumItems = 0 ;
const float SegmentsAngle = 2 * pi / Segments ;
2022-07-09 11:16:12 +00:00
for ( int i = 0 ; i < Segments ; i + = 2 )
{
2022-07-09 11:26:42 +00:00
const float a1 = i * SegmentsAngle ;
const float a2 = ( i + 1 ) * SegmentsAngle ;
const float a3 = ( i + 2 ) * SegmentsAngle ;
aItems [ NumItems + + ] = IGraphics : : CFreeformItem (
CenterX , CenterY ,
CenterX + cosf ( a1 ) * Radius , CenterY + sinf ( a1 ) * Radius ,
CenterX + cosf ( a3 ) * Radius , CenterY + sinf ( a3 ) * Radius ,
CenterX + cosf ( a2 ) * Radius , CenterY + sinf ( a2 ) * Radius ) ;
if ( NumItems = = std : : size ( aItems ) )
2022-07-09 11:16:12 +00:00
{
2022-07-09 11:26:42 +00:00
QuadsDrawFreeform ( aItems , std : : size ( aItems ) ) ;
2022-07-09 11:16:12 +00:00
NumItems = 0 ;
}
}
if ( NumItems )
2022-07-09 11:26:42 +00:00
QuadsDrawFreeform ( aItems , NumItems ) ;
2022-07-09 11:16:12 +00:00
}
2022-06-30 22:36:32 +00:00
void CGraphics_Threaded : : RenderTileLayer ( int BufferContainerIndex , const ColorRGBA & Color , char * * pOffsets , unsigned int * pIndicedVertexDrawNum , size_t NumIndicesOffset )
2017-09-13 18:33:58 +00:00
{
2022-03-20 17:04:00 +00:00
if ( NumIndicesOffset = = 0 )
2018-03-13 20:47:07 +00:00
return ;
2019-04-26 22:11:15 +00:00
2022-03-20 17:03:25 +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 ;
2022-03-20 17:04:00 +00:00
Cmd . m_IndicesDrawNum = NumIndicesOffset ;
2018-03-13 20:47:07 +00:00
Cmd . m_BufferContainerIndex = BufferContainerIndex ;
2022-07-01 04:42:36 +00:00
Cmd . m_Color = Color ;
2017-09-12 18:08:45 +00:00
2022-06-30 22:36:32 +00:00
void * pData = m_pCommandBuffer - > AllocData ( ( sizeof ( char * ) + sizeof ( unsigned int ) ) * NumIndicesOffset ) ;
if ( pData = = 0x0 )
2017-09-12 18:08:45 +00:00
{
// kick command buffer and try again
KickCommandBuffer ( ) ;
2019-04-26 22:11:15 +00:00
2022-06-30 22:36:32 +00:00
pData = m_pCommandBuffer - > AllocData ( ( sizeof ( char * ) + sizeof ( unsigned int ) ) * NumIndicesOffset ) ;
if ( pData = = 0x0 )
2017-09-12 18:08:45 +00:00
{
dbg_msg ( " graphics " , " failed to allocate data for vertices " ) ;
return ;
}
}
2022-06-30 22:36:32 +00:00
Cmd . m_pIndicesOffsets = ( char * * ) pData ;
Cmd . m_pDrawCount = ( unsigned int * ) ( ( ( char * ) pData ) + ( sizeof ( char * ) * NumIndicesOffset ) ) ;
2019-04-26 22:11:15 +00:00
2021-04-07 17:03:07 +00:00
if ( ! AddCmd (
Cmd , [ & ] {
2022-06-30 22:36:32 +00:00
pData = m_pCommandBuffer - > AllocData ( ( sizeof ( char * ) + sizeof ( unsigned int ) ) * NumIndicesOffset ) ;
if ( pData = = 0x0 )
2021-04-07 17:03:07 +00:00
{
dbg_msg ( " graphics " , " failed to allocate data for vertices " ) ;
return false ;
}
2022-06-30 22:36:32 +00:00
Cmd . m_pIndicesOffsets = ( char * * ) pData ;
Cmd . m_pDrawCount = ( unsigned int * ) ( ( ( char * ) pData ) + ( sizeof ( char * ) * NumIndicesOffset ) ) ;
2021-04-07 17:03:07 +00:00
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
}
2022-03-20 17:04:00 +00:00
mem_copy ( Cmd . m_pIndicesOffsets , pOffsets , sizeof ( char * ) * NumIndicesOffset ) ;
2022-06-30 22:36:32 +00:00
mem_copy ( Cmd . m_pDrawCount , pIndicedVertexDrawNum , sizeof ( unsigned int ) * NumIndicesOffset ) ;
2019-04-26 22:11:15 +00:00
2022-03-20 17:04:00 +00:00
m_pCommandBuffer - > AddRenderCalls ( NumIndicesOffset ) ;
2022-03-20 17:03:25 +00:00
// todo max indices group check!!
2017-09-12 18:08:45 +00:00
}
2022-07-01 04:42:36 +00:00
void CGraphics_Threaded : : RenderBorderTiles ( int BufferContainerIndex , const ColorRGBA & Color , char * pIndexBufferOffset , const vec2 & Offset , const vec2 & Dir , 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 ;
2022-07-01 04:42:36 +00:00
Cmd . m_Color = Color ;
2017-09-12 18:08:45 +00:00
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
2022-07-01 02:23:22 +00:00
Cmd . m_Offset = Offset ;
Cmd . m_Dir = Dir ;
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
}
2022-03-20 17:04:00 +00:00
m_pCommandBuffer - > AddRenderCalls ( 1 ) ;
2017-09-12 18:08:45 +00:00
}
2022-07-01 04:42:36 +00:00
void CGraphics_Threaded : : RenderBorderTileLines ( int BufferContainerIndex , const ColorRGBA & Color , char * pIndexBufferOffset , const vec2 & Offset , const vec2 & Dir , 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 ;
2022-07-01 04:42:36 +00:00
Cmd . m_Color = Color ;
2017-09-12 18:08:45 +00:00
2018-08-02 16:26:12 +00:00
Cmd . m_pIndicesOffset = pIndexBufferOffset ;
2022-07-01 02:23:22 +00:00
Cmd . m_Offset = Offset ;
Cmd . m_Dir = Dir ;
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
}
2022-03-20 17:04:00 +00:00
m_pCommandBuffer - > AddRenderCalls ( 1 ) ;
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 ;
2022-03-20 17:03:25 +00:00
// add the VertexArrays and draw
2018-03-13 20:47:07 +00:00
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 ) ;
2022-03-20 17:04:00 +00:00
m_pCommandBuffer - > AddRenderCalls ( ( ( QuadNum - 1 ) / gs_GraphicsMaxQuadsRenderCount ) + 1 ) ;
2018-03-13 20:47:07 +00:00
}
2022-07-07 02:51:17 +00:00
void CGraphics_Threaded : : RenderText ( int BufferContainerIndex , int TextQuadNum , int TextureSize , int TextureTextIndex , int TextureTextOutlineIndex , const ColorRGBA & TextColor , const ColorRGBA & TextOutlineColor )
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 ;
2022-07-01 04:42:36 +00:00
Cmd . m_TextColor = TextColor ;
2022-07-07 02:51:17 +00:00
Cmd . m_TextOutlineColor = TextOutlineColor ;
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 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
}
2022-03-20 17:04:00 +00:00
m_pCommandBuffer - > AddRenderCalls ( 1 ) ;
2017-09-12 18:08:45 +00:00
}
2021-09-13 21:14:04 +00:00
int CGraphics_Threaded : : CreateQuadContainer ( bool AutomaticUpload )
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
{
2022-06-11 19:38:18 +00:00
Index = m_vQuadContainers . size ( ) ;
m_vQuadContainers . emplace_back ( AutomaticUpload ) ;
2017-09-27 12:52:06 +00:00
}
else
{
2018-03-13 20:47:07 +00:00
Index = m_FirstFreeQuadContainer ;
2022-06-11 19:38:18 +00:00
m_FirstFreeQuadContainer = m_vQuadContainers [ Index ] . m_FreeIndex ;
m_vQuadContainers [ Index ] . m_FreeIndex = Index ;
2017-09-12 18:08:45 +00:00
}
2018-03-13 20:47:07 +00:00
return Index ;
}
2021-09-13 21:14:04 +00:00
void CGraphics_Threaded : : QuadContainerChangeAutomaticUpload ( int ContainerIndex , bool AutomaticUpload )
{
2022-06-11 19:38:18 +00:00
SQuadContainer & Container = m_vQuadContainers [ ContainerIndex ] ;
2021-09-18 18:41:01 +00:00
Container . m_AutomaticUpload = AutomaticUpload ;
2021-09-13 21:14:04 +00:00
}
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
{
2022-06-11 19:38:18 +00:00
SQuadContainer & Container = m_vQuadContainers [ ContainerIndex ] ;
if ( ! Container . m_vQuads . empty ( ) )
2018-04-15 17:34:56 +00:00
{
if ( Container . m_QuadBufferObjectIndex = = - 1 )
{
2022-06-11 19:38:18 +00:00
size_t UploadDataSize = Container . m_vQuads . size ( ) * sizeof ( SQuadContainer : : SQuad ) ;
2022-07-10 19:22:50 +00:00
Container . m_QuadBufferObjectIndex = CreateBufferObject ( UploadDataSize , Container . m_vQuads . data ( ) , 0 ) ;
2018-04-15 17:34:56 +00:00
}
else
{
2022-06-11 19:38:18 +00:00
size_t UploadDataSize = Container . m_vQuads . size ( ) * sizeof ( SQuadContainer : : SQuad ) ;
2022-07-10 19:22:50 +00:00
RecreateBufferObject ( Container . m_QuadBufferObjectIndex , UploadDataSize , Container . m_vQuads . data ( ) , 0 ) ;
2018-04-15 17:34:56 +00:00
}
if ( Container . m_QuadBufferContainerIndex = = - 1 )
{
SBufferContainerInfo Info ;
Info . m_Stride = sizeof ( CCommandBuffer : : SVertex ) ;
2022-03-20 17:03:25 +00:00
Info . m_VertBufferBindingIndex = Container . m_QuadBufferObjectIndex ;
2018-04-15 17:34:56 +00:00
2022-06-11 19:38:18 +00:00
Info . m_vAttributes . emplace_back ( ) ;
SBufferContainerInfo : : SAttribute * pAttr = & Info . m_vAttributes . 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 ;
2022-06-11 19:38:18 +00:00
Info . m_vAttributes . emplace_back ( ) ;
pAttr = & Info . m_vAttributes . back ( ) ;
2018-04-15 17:34:56 +00:00
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 ;
2022-06-11 19:38:18 +00:00
Info . m_vAttributes . emplace_back ( ) ;
pAttr = & Info . m_vAttributes . back ( ) ;
2018-04-15 17:34:56 +00:00
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 ;
Container . m_QuadBufferContainerIndex = CreateBufferContainer ( & Info ) ;
}
}
}
}
2022-02-18 10:16:55 +00:00
int CGraphics_Threaded : : QuadContainerAddQuads ( int ContainerIndex , CQuadItem * pArray , int Num )
2018-03-13 20:47:07 +00:00
{
2022-06-11 19:38:18 +00:00
SQuadContainer & Container = m_vQuadContainers [ ContainerIndex ] ;
2018-03-13 20:47:07 +00:00
2022-06-11 19:38:18 +00:00
if ( ( int ) Container . m_vQuads . size ( ) > Num + CCommandBuffer : : CCommandBuffer : : MAX_VERTICES )
2022-02-18 10:16:55 +00:00
return - 1 ;
2022-06-11 19:38:18 +00:00
int RetOff = ( int ) Container . m_vQuads . size ( ) ;
2018-03-13 20:47:07 +00:00
for ( int i = 0 ; i < Num ; + + i )
{
2022-06-11 19:38:18 +00:00
Container . m_vQuads . emplace_back ( ) ;
SQuadContainer : : SQuad & Quad = Container . m_vQuads . 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 ) ;
}
}
2021-09-18 18:41:01 +00:00
if ( Container . m_AutomaticUpload )
2021-09-13 21:14:04 +00:00
QuadContainerUpload ( ContainerIndex ) ;
2022-02-18 10:16:55 +00:00
return RetOff ;
2018-03-13 20:47:07 +00:00
}
2022-02-18 10:16:55 +00:00
int CGraphics_Threaded : : QuadContainerAddQuads ( int ContainerIndex , CFreeformItem * pArray , int Num )
2018-03-13 20:47:07 +00:00
{
2022-06-11 19:38:18 +00:00
SQuadContainer & Container = m_vQuadContainers [ ContainerIndex ] ;
2018-03-13 20:47:07 +00:00
2022-06-11 19:38:18 +00:00
if ( ( int ) Container . m_vQuads . size ( ) > Num + CCommandBuffer : : CCommandBuffer : : MAX_VERTICES )
2022-02-18 10:16:55 +00:00
return - 1 ;
2022-06-11 19:38:18 +00:00
int RetOff = ( int ) Container . m_vQuads . size ( ) ;
2018-03-13 20:47:07 +00:00
for ( int i = 0 ; i < Num ; + + i )
{
2022-06-11 19:38:18 +00:00
Container . m_vQuads . emplace_back ( ) ;
SQuadContainer : : SQuad & Quad = Container . m_vQuads . 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 ) ;
}
2021-09-18 18:41:01 +00:00
if ( Container . m_AutomaticUpload )
2021-09-13 21:14:04 +00:00
QuadContainerUpload ( ContainerIndex ) ;
2022-02-18 10:16:55 +00:00
return RetOff ;
2018-03-13 20:47:07 +00:00
}
void CGraphics_Threaded : : QuadContainerReset ( int ContainerIndex )
{
2022-06-11 19:38:18 +00:00
SQuadContainer & Container = m_vQuadContainers [ 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 ) ;
}
2022-06-11 19:38:18 +00:00
Container . m_vQuads . clear ( ) ;
2018-03-13 20:47:07 +00:00
Container . m_QuadBufferContainerIndex = Container . m_QuadBufferObjectIndex = - 1 ;
}
void CGraphics_Threaded : : DeleteQuadContainer ( int ContainerIndex )
{
QuadContainerReset ( ContainerIndex ) ;
// also clear the container index
2022-06-11 19:38:18 +00:00
m_vQuadContainers [ ContainerIndex ] . m_FreeIndex = m_FirstFreeQuadContainer ;
2018-03-13 20:47:07 +00:00
m_FirstFreeQuadContainer = ContainerIndex ;
}
void CGraphics_Threaded : : RenderQuadContainer ( int ContainerIndex , int QuadDrawNum )
{
RenderQuadContainer ( ContainerIndex , 0 , QuadDrawNum ) ;
}
2021-09-13 21:14:04 +00:00
void CGraphics_Threaded : : RenderQuadContainer ( int ContainerIndex , int QuadOffset , int QuadDrawNum , bool ChangeWrapMode )
2018-03-13 20:47:07 +00:00
{
2022-06-11 19:38:18 +00:00
SQuadContainer & Container = m_vQuadContainers [ ContainerIndex ] ;
2018-03-13 20:47:07 +00:00
if ( QuadDrawNum = = - 1 )
2022-06-11 19:38:18 +00:00
QuadDrawNum = ( int ) Container . m_vQuads . size ( ) - QuadOffset ;
2018-03-13 20:47:07 +00:00
2022-06-11 19:38:18 +00:00
if ( ( int ) Container . m_vQuads . size ( ) < QuadOffset + QuadDrawNum | | QuadDrawNum = = 0 )
2018-03-13 20:47:07 +00:00
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 ;
2021-09-13 21:14:04 +00:00
if ( ChangeWrapMode )
WrapClamp ( ) ;
2020-10-09 07:07:05 +00:00
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
}
2022-03-20 17:04:00 +00:00
m_pCommandBuffer - > AddRenderCalls ( 1 ) ;
2018-03-13 20:47:07 +00:00
}
else
{
if ( g_Config . m_GfxQuadAsTriangle )
{
for ( int i = 0 ; i < QuadDrawNum ; + + i )
{
2022-06-11 19:38:18 +00:00
SQuadContainer : : SQuad & Quad = Container . m_vQuads [ 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
{
2022-06-11 19:38:18 +00:00
mem_copy ( m_aVertices , & Container . m_vQuads [ QuadOffset ] , sizeof ( CCommandBuffer : : SVertex ) * 4 * QuadDrawNum ) ;
2018-03-13 20:47:07 +00:00
m_NumVertices + = 4 * QuadDrawNum ;
}
m_Drawing = DRAWING_QUADS ;
2021-09-13 21:14:04 +00:00
if ( ChangeWrapMode )
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
{
2022-06-11 19:38:18 +00:00
SQuadContainer & Container = m_vQuadContainers [ ContainerIndex ] ;
2018-03-13 20:47:07 +00:00
2022-06-11 19:38:18 +00:00
if ( ( int ) Container . m_vQuads . size ( ) < QuadOffset + 1 )
2018-03-13 20:47:07 +00:00
return ;
2020-10-13 20:08:52 +00:00
if ( QuadDrawNum = = - 1 )
2022-06-11 19:38:18 +00:00
QuadDrawNum = ( int ) Container . m_vQuads . size ( ) - QuadOffset ;
2020-10-13 20:08:52 +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 ;
2022-06-11 19:38:18 +00:00
SQuadContainer : : SQuad & Quad = Container . m_vQuads [ 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
}
2022-03-20 17:04:00 +00:00
m_pCommandBuffer - > AddRenderCalls ( 1 ) ;
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
{
2022-06-11 19:38:18 +00:00
SQuadContainer : : SQuad & Quad = Container . m_vQuads [ QuadOffset + i ] ;
2020-10-13 20:08:52 +00:00
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
{
2022-06-11 19:38:18 +00:00
mem_copy ( m_aVertices , & Container . m_vQuads [ 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 )
{
2022-06-11 19:38:18 +00:00
SQuadContainer & Container = m_vQuadContainers [ 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 ( ) ;
2022-06-11 19:38:18 +00:00
SQuadContainer : : SQuad & Quad = Container . m_vQuads [ 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 ) ;
2022-03-20 17:04:00 +00:00
m_pCommandBuffer - > AddRenderCalls ( ( ( DrawCount - 1 ) / gs_GraphicsMaxParticlesRenderCount ) + 1 ) ;
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 ) ;
2022-07-01 02:23:22 +00:00
RenderQuadContainerAsSprite ( ContainerIndex , QuadOffset , pRenderInfo [ i ] . m_Pos . x , pRenderInfo [ i ] . m_Pos . y , pRenderInfo [ i ] . m_Scale , pRenderInfo [ i ] . m_Scale ) ;
2018-03-13 20:47:07 +00:00
}
}
}
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 ;
}
2022-03-20 17:03:25 +00:00
int CGraphics_Threaded : : CreateBufferObject ( size_t UploadDataSize , void * pUploadData , int CreateFlags , bool IsMovedPointer )
2018-03-13 20:47:07 +00:00
{
int Index = - 1 ;
if ( m_FirstFreeBufferObjectIndex = = - 1 )
{
2022-06-11 19:38:18 +00:00
Index = m_vBufferObjectIndices . size ( ) ;
m_vBufferObjectIndices . push_back ( Index ) ;
2018-03-13 20:47:07 +00:00
}
else
{
Index = m_FirstFreeBufferObjectIndex ;
2022-06-11 19:38:18 +00:00
m_FirstFreeBufferObjectIndex = m_vBufferObjectIndices [ Index ] ;
m_vBufferObjectIndices [ Index ] = Index ;
2018-03-13 20:47:07 +00:00
}
CCommandBuffer : : SCommand_CreateBufferObject Cmd ;
Cmd . m_BufferIndex = Index ;
Cmd . m_DataSize = UploadDataSize ;
2020-10-13 17:33:02 +00:00
Cmd . m_DeletePointer = IsMovedPointer ;
2022-03-20 17:03:25 +00:00
Cmd . m_Flags = CreateFlags ;
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
2022-03-20 17:03:25 +00:00
UpdateBufferObjectInternal ( 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 ;
}
2022-03-20 17:03:25 +00:00
void CGraphics_Threaded : : RecreateBufferObject ( int BufferIndex , size_t UploadDataSize , void * pUploadData , int CreateFlags , 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 ;
2022-03-20 17:03:25 +00:00
Cmd . m_Flags = CreateFlags ;
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 ) ;
2022-03-20 17:03:25 +00:00
UpdateBufferObjectInternal ( 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
}
}
}
2022-03-20 17:03:25 +00:00
void CGraphics_Threaded : : UpdateBufferObjectInternal ( 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
}
2022-03-20 17:03:25 +00:00
void CGraphics_Threaded : : CopyBufferObjectInternal ( int WriteBufferIndex , int ReadBufferIndex , size_t WriteOffset , size_t ReadOffset , size_t CopyDataSize )
2018-03-13 20:47:07 +00:00
{
CCommandBuffer : : SCommand_CopyBufferObject Cmd ;
Cmd . m_WriteBufferIndex = WriteBufferIndex ;
Cmd . m_ReadBufferIndex = ReadBufferIndex ;
2022-06-30 22:36:32 +00:00
Cmd . m_WriteOffset = WriteOffset ;
Cmd . m_ReadOffset = ReadOffset ;
2018-03-13 20:47:07 +00:00
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
2022-06-11 19:38:18 +00:00
m_vBufferObjectIndices [ BufferIndex ] = m_FirstFreeBufferObjectIndex ;
2018-03-13 20:47:07 +00:00
m_FirstFreeBufferObjectIndex = BufferIndex ;
}
int CGraphics_Threaded : : CreateBufferContainer ( SBufferContainerInfo * pContainerInfo )
{
int Index = - 1 ;
if ( m_FirstFreeVertexArrayInfo = = - 1 )
{
2022-06-30 22:36:32 +00:00
Index = m_vVertexArrayInfo . size ( ) ;
m_vVertexArrayInfo . emplace_back ( ) ;
2018-03-13 20:47:07 +00:00
}
else
{
Index = m_FirstFreeVertexArrayInfo ;
2022-06-30 22:36:32 +00:00
m_FirstFreeVertexArrayInfo = m_vVertexArrayInfo [ Index ] . m_FreeIndex ;
m_vVertexArrayInfo [ Index ] . m_FreeIndex = Index ;
2018-03-13 20:47:07 +00:00
}
CCommandBuffer : : SCommand_CreateBufferContainer Cmd ;
Cmd . m_BufferContainerIndex = Index ;
2022-06-11 19:38:18 +00:00
Cmd . m_AttrCount = ( int ) pContainerInfo - > m_vAttributes . size ( ) ;
2018-03-13 20:47:07 +00:00
Cmd . m_Stride = pContainerInfo - > m_Stride ;
2022-03-20 17:03:25 +00:00
Cmd . m_VertBufferBindingIndex = pContainerInfo - > m_VertBufferBindingIndex ;
2018-03-13 20:47:07 +00:00
2022-03-24 18:30:26 +00:00
Cmd . m_pAttributes = ( SBufferContainerInfo : : SAttribute * ) AllocCommandBufferData ( Cmd . m_AttrCount * sizeof ( SBufferContainerInfo : : SAttribute ) ) ;
if ( Cmd . m_pAttributes = = nullptr )
2018-03-13 20:47:07 +00:00
return - 1 ;
2021-04-07 17:03:07 +00:00
if ( ! AddCmd (
Cmd , [ & ] {
2022-03-24 18:30:26 +00:00
Cmd . m_pAttributes = ( SBufferContainerInfo : : SAttribute * ) m_pCommandBuffer - > AllocData ( Cmd . m_AttrCount * sizeof ( SBufferContainerInfo : : SAttribute ) ) ;
if ( Cmd . m_pAttributes = = nullptr )
2021-04-07 17:03:07 +00:00
{
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
2022-06-11 19:38:18 +00:00
mem_copy ( Cmd . m_pAttributes , pContainerInfo - > m_vAttributes . data ( ) , Cmd . m_AttrCount * sizeof ( SBufferContainerInfo : : SAttribute ) ) ;
2018-03-13 20:47:07 +00:00
2022-06-30 22:36:32 +00:00
m_vVertexArrayInfo [ Index ] . m_AssociatedBufferObjectIndex = pContainerInfo - > 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
2022-06-30 22:36:32 +00:00
int BufferObjectIndex = m_vVertexArrayInfo [ ContainerIndex ] . m_AssociatedBufferObjectIndex ;
2022-03-20 17:03:25 +00:00
if ( BufferObjectIndex ! = - 1 )
2018-03-13 20:47:07 +00:00
{
2022-03-20 17:03:25 +00:00
// clear the buffer object index
2022-06-11 19:38:18 +00:00
m_vBufferObjectIndices [ BufferObjectIndex ] = m_FirstFreeBufferObjectIndex ;
2022-03-20 17:03:25 +00:00
m_FirstFreeBufferObjectIndex = BufferObjectIndex ;
2018-03-13 20:47:07 +00:00
}
}
2022-06-30 22:36:32 +00:00
m_vVertexArrayInfo [ ContainerIndex ] . m_AssociatedBufferObjectIndex = - 1 ;
2018-03-13 20:47:07 +00:00
// also clear the buffer object index
2022-06-30 22:36:32 +00:00
m_vVertexArrayInfo [ ContainerIndex ] . m_FreeIndex = m_FirstFreeVertexArrayInfo ;
2018-03-13 20:47:07 +00:00
m_FirstFreeVertexArrayInfo = ContainerIndex ;
}
2022-03-20 17:03:25 +00:00
void CGraphics_Threaded : : UpdateBufferContainerInternal ( int ContainerIndex , SBufferContainerInfo * pContainerInfo )
2018-03-13 20:47:07 +00:00
{
CCommandBuffer : : SCommand_UpdateBufferContainer Cmd ;
Cmd . m_BufferContainerIndex = ContainerIndex ;
2022-06-11 19:38:18 +00:00
Cmd . m_AttrCount = ( int ) pContainerInfo - > m_vAttributes . size ( ) ;
2018-03-13 20:47:07 +00:00
Cmd . m_Stride = pContainerInfo - > m_Stride ;
2022-03-20 17:03:25 +00:00
Cmd . m_VertBufferBindingIndex = pContainerInfo - > m_VertBufferBindingIndex ;
2018-03-13 20:47:07 +00:00
2022-03-24 18:30:26 +00:00
Cmd . m_pAttributes = ( SBufferContainerInfo : : SAttribute * ) AllocCommandBufferData ( Cmd . m_AttrCount * sizeof ( SBufferContainerInfo : : SAttribute ) ) ;
if ( Cmd . m_pAttributes = = nullptr )
2018-03-13 20:47:07 +00:00
return ;
2021-04-07 17:03:07 +00:00
if ( ! AddCmd (
Cmd , [ & ] {
2022-03-24 18:30:26 +00:00
Cmd . m_pAttributes = ( SBufferContainerInfo : : SAttribute * ) m_pCommandBuffer - > AllocData ( Cmd . m_AttrCount * sizeof ( SBufferContainerInfo : : SAttribute ) ) ;
if ( Cmd . m_pAttributes = = nullptr )
2021-04-07 17:03:07 +00:00
{
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
2022-06-11 19:38:18 +00:00
mem_copy ( Cmd . m_pAttributes , pContainerInfo - > m_vAttributes . data ( ) , Cmd . m_AttrCount * sizeof ( SBufferContainerInfo : : SAttribute ) ) ;
2018-03-13 20:47:07 +00:00
2022-06-30 22:36:32 +00:00
m_vVertexArrayInfo [ ContainerIndex ] . m_AssociatedBufferObjectIndex = pContainerInfo - > 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 ( )
{
2022-02-04 10:13:38 +00:00
int Flags = 0 ;
bool IsPurlyWindowed = g_Config . m_GfxFullscreen = = 0 ;
bool IsExclusiveFullscreen = g_Config . m_GfxFullscreen = = 1 ;
bool IsDesktopFullscreen = g_Config . m_GfxFullscreen = = 2 ;
# ifndef CONF_FAMILY_WINDOWS
// special mode for windows only
IsDesktopFullscreen | = g_Config . m_GfxFullscreen = = 3 ;
# endif
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 ;
2022-02-04 10:13:38 +00:00
if ( IsExclusiveFullscreen )
2020-09-26 19:41:58 +00:00
Flags | = IGraphicsBackend : : INITFLAG_FULLSCREEN ;
2022-02-04 10:13:38 +00:00
else if ( IsDesktopFullscreen )
2021-01-31 20:54:04 +00:00
Flags | = IGraphicsBackend : : INITFLAG_DESKTOP_FULLSCREEN ;
2022-02-04 10:13:38 +00:00
if ( IsPurlyWindowed | | IsExclusiveFullscreen | | IsDesktopFullscreen )
Flags | = IGraphicsBackend : : INITFLAG_RESIZABLE ;
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 ;
2011-12-31 13:00:49 +00:00
2022-05-22 12:27:55 +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 ( ) ;
2022-04-13 20:02:10 +00:00
if ( r = = 0 )
{
m_GLUseTrianglesAsQuad = m_pBackend - > UseTrianglesAsQuad ( ) ;
m_GLTileBufferingEnabled = m_pBackend - > HasTileBuffering ( ) ;
m_GLQuadBufferingEnabled = m_pBackend - > HasQuadBuffering ( ) ;
m_GLQuadContainerBufferingEnabled = m_pBackend - > HasQuadContainerBuffering ( ) ;
m_GLTextBufferingEnabled = ( m_GLQuadContainerBufferingEnabled & & m_pBackend - > HasTextBuffering ( ) ) ;
m_GLHasTextureArrays = m_pBackend - > Has2DTextureArrays ( ) ;
m_ScreenHiDPIScale = m_ScreenWidth / ( float ) g_Config . m_GfxScreenWidth ;
m_ScreenRefreshRate = g_Config . m_GfxScreenRefreshRate ;
}
2017-09-12 18:08:45 +00:00
return r ;
2011-12-31 13:00:49 +00:00
}
2022-03-20 17:04:00 +00:00
void CGraphics_Threaded : : AdjustViewport ( bool SendViewportChangeToBackend )
{
// adjust the viewport to only allow certain aspect ratios
// keep this in sync with backend_vulkan GetSwapImageSize's check
if ( m_ScreenHeight > 4 * m_ScreenWidth / 5 )
{
m_IsForcedViewport = true ;
m_ScreenHeight = 4 * m_ScreenWidth / 5 ;
if ( SendViewportChangeToBackend )
{
2022-04-19 15:26:05 +00:00
UpdateViewport ( 0 , 0 , m_ScreenWidth , m_ScreenHeight , true ) ;
2022-03-20 17:04:00 +00:00
}
}
else
{
m_IsForcedViewport = false ;
}
}
2022-04-18 07:50:19 +00:00
void CGraphics_Threaded : : UpdateViewport ( int X , int Y , int W , int H , bool ByResize )
{
CCommandBuffer : : SCommand_Update_Viewport Cmd ;
Cmd . m_X = X ;
Cmd . m_Y = Y ;
Cmd . m_Width = W ;
Cmd . m_Height = H ;
Cmd . m_ByResize = ByResize ;
if ( ! AddCmd (
Cmd , [ ] { return true ; } , " failed to add resize command " ) )
{
return ;
}
}
2020-11-05 19:38:37 +00:00
void CGraphics_Threaded : : AddBackEndWarningIfExists ( )
{
const char * pErrStr = m_pBackend - > GetErrorString ( ) ;
if ( pErrStr ! = NULL )
{
SWarning NewWarning ;
2022-10-27 19:28:49 +00:00
str_copy ( NewWarning . m_aWarningMsg , Localize ( pErrStr ) ) ;
2022-06-11 19:38:18 +00:00
m_vWarnings . emplace_back ( NewWarning ) ;
2020-11-05 19:38:37 +00:00
}
}
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 )
{
2022-05-22 12:27:55 +00:00
// 4 is the minimum required by OpenGL ES spec (GL_MAX_SAMPLES - https://www.khronos.org/registry/OpenGL-Refpages/es3.0/html/glGet.xhtml), so can probably also be assumed for OpenGL
if ( g_Config . m_GfxFsaaSamples > 4 )
g_Config . m_GfxFsaaSamples = 4 ;
else
g_Config . m_GfxFsaaSamples = 0 ;
2011-12-31 13:00:49 +00:00
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
2022-03-20 17:03:25 +00:00
size_t GLInitTryCount = 0 ;
while ( ErrorCode = = EGraphicsBackendErrorCodes : : GRAPHICS_BACKEND_ERROR_CODE_GL_CONTEXT_FAILED | | ErrorCode = = EGraphicsBackendErrorCodes : : GRAPHICS_BACKEND_ERROR_CODE_GL_VERSION_FAILED )
2017-09-27 10:16:34 +00:00
{
2022-03-20 17:03:25 +00:00
if ( ErrorCode = = EGraphicsBackendErrorCodes : : GRAPHICS_BACKEND_ERROR_CODE_GL_CONTEXT_FAILED )
2020-08-22 06:09:10 +00:00
{
// try next smaller major/minor or patch version
2022-03-20 17:03:25 +00:00
if ( g_Config . m_GfxGLMajor > = 4 )
2020-08-22 06:09:10 +00:00
{
2022-03-20 17:03:25 +00:00
g_Config . m_GfxGLMajor = 3 ;
g_Config . m_GfxGLMinor = 3 ;
g_Config . m_GfxGLPatch = 0 ;
2020-08-22 06:09:10 +00:00
}
2022-03-20 17:03:25 +00:00
else if ( g_Config . m_GfxGLMajor = = 3 & & g_Config . m_GfxGLMinor > = 1 )
2020-08-22 06:09:10 +00:00
{
2022-03-20 17:03:25 +00:00
g_Config . m_GfxGLMajor = 3 ;
g_Config . m_GfxGLMinor = 0 ;
g_Config . m_GfxGLPatch = 0 ;
2020-08-22 06:09:10 +00:00
}
2022-03-20 17:03:25 +00:00
else if ( g_Config . m_GfxGLMajor = = 3 & & g_Config . m_GfxGLMinor = = 0 )
2020-08-22 06:09:10 +00:00
{
2022-03-20 17:03:25 +00:00
g_Config . m_GfxGLMajor = 2 ;
g_Config . m_GfxGLMinor = 1 ;
g_Config . m_GfxGLPatch = 0 ;
2020-08-22 06:09:10 +00:00
}
2022-03-20 17:03:25 +00:00
else if ( g_Config . m_GfxGLMajor = = 2 & & g_Config . m_GfxGLMinor > = 1 )
2020-08-22 06:09:10 +00:00
{
2022-03-20 17:03:25 +00:00
g_Config . m_GfxGLMajor = 2 ;
g_Config . m_GfxGLMinor = 0 ;
g_Config . m_GfxGLPatch = 0 ;
2020-08-22 06:09:10 +00:00
}
2022-03-20 17:03:25 +00:00
else if ( g_Config . m_GfxGLMajor = = 2 & & g_Config . m_GfxGLMinor = = 0 )
2020-08-22 06:09:10 +00:00
{
2022-03-20 17:03:25 +00:00
g_Config . m_GfxGLMajor = 1 ;
g_Config . m_GfxGLMinor = 5 ;
g_Config . m_GfxGLPatch = 0 ;
2020-08-22 06:09:10 +00:00
}
2022-03-20 17:03:25 +00:00
else if ( g_Config . m_GfxGLMajor = = 1 & & g_Config . m_GfxGLMinor = = 5 )
2020-08-22 06:09:10 +00:00
{
2022-03-20 17:03:25 +00:00
g_Config . m_GfxGLMajor = 1 ;
g_Config . m_GfxGLMinor = 4 ;
g_Config . m_GfxGLPatch = 0 ;
2020-08-22 06:09:10 +00:00
}
2022-03-20 17:03:25 +00:00
else if ( g_Config . m_GfxGLMajor = = 1 & & g_Config . m_GfxGLMinor = = 4 )
2020-08-22 06:09:10 +00:00
{
2022-03-20 17:03:25 +00:00
g_Config . m_GfxGLMajor = 1 ;
g_Config . m_GfxGLMinor = 3 ;
g_Config . m_GfxGLPatch = 0 ;
2020-08-22 06:09:10 +00:00
}
2022-03-20 17:03:25 +00:00
else if ( g_Config . m_GfxGLMajor = = 1 & & g_Config . m_GfxGLMinor = = 3 )
2020-08-22 06:09:10 +00:00
{
2022-03-20 17:03:25 +00:00
g_Config . m_GfxGLMajor = 1 ;
g_Config . m_GfxGLMinor = 2 ;
g_Config . m_GfxGLPatch = 1 ;
2020-08-22 06:09:10 +00:00
}
2022-03-20 17:03:25 +00:00
else if ( g_Config . m_GfxGLMajor = = 1 & & g_Config . m_GfxGLMinor = = 2 )
2020-08-22 06:09:10 +00:00
{
2022-03-20 17:03:25 +00:00
g_Config . m_GfxGLMajor = 1 ;
g_Config . m_GfxGLMinor = 1 ;
g_Config . m_GfxGLPatch = 0 ;
2020-08-22 06:09:10 +00:00
}
}
2022-03-20 17:03:25 +00:00
// new gl version was set by backend, try again
2020-08-22 06:09:10 +00:00
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
2022-03-20 17:03:25 +00:00
if ( + + GLInitTryCount > = 9 )
2020-08-22 06:09:10 +00:00
{
// 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 ;
}
2022-03-20 17:04:00 +00:00
// at the very end, just try to set to gl 1.4
{
g_Config . m_GfxGLMajor = 1 ;
g_Config . m_GfxGLMinor = 4 ;
g_Config . m_GfxGLPatch = 0 ;
if ( IssueInit ( ) = = 0 )
return 0 ;
}
2011-12-31 13:00:49 +00:00
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 ;
2022-06-11 19:38:18 +00:00
m_vTextureIndices . resize ( CCommandBuffer : : MAX_TEXTURES ) ;
for ( int i = 0 ; i < ( int ) m_vTextureIndices . size ( ) - 1 ; i + + )
m_vTextureIndices [ i ] = i + 1 ;
m_vTextureIndices . 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 ) ;
2022-03-20 17:04:00 +00:00
AdjustViewport ( true ) ;
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
}
2022-06-27 14:57:23 +00:00
void CGraphics_Threaded : : WarnPngliteIncompatibleImages ( bool Warn )
{
m_WarnPngliteIncompatibleImages = Warn ;
}
2022-02-04 10:13:38 +00:00
void CGraphics_Threaded : : SetWindowParams ( int FullscreenMode , bool IsBorderless , bool AllowResizing )
2016-04-29 19:07:10 +00:00
{
2022-02-04 10:13:38 +00:00
m_pBackend - > SetWindowParams ( FullscreenMode , IsBorderless , AllowResizing ) ;
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 ) ;
2022-01-15 15:20:01 +00:00
GotResized ( CurMode . m_WindowWidth , CurMode . m_WindowHeight , CurMode . m_RefreshRate ) ;
2016-04-29 22:34:12 +00:00
}
bool CGraphics_Threaded : : SetWindowScreen ( int Index )
{
2021-12-13 17:42:21 +00:00
if ( ! m_pBackend - > SetWindowScreen ( Index ) )
{
return false ;
}
m_pBackend - > GetViewportSize ( m_ScreenWidth , m_ScreenHeight ) ;
2022-03-20 17:04:00 +00:00
AdjustViewport ( true ) ;
2021-12-13 17:42:21 +00:00
m_ScreenHiDPIScale = m_ScreenWidth / ( float ) g_Config . m_GfxScreenWidth ;
return true ;
}
void CGraphics_Threaded : : Move ( int x , int y )
{
# if defined(CONF_VIDEORECORDER)
if ( IVideo : : Current ( ) & & IVideo : : Current ( ) - > IsRecording ( ) )
return ;
# endif
// Only handling CurScreen != m_GfxScreen doesn't work reliably
const int CurScreen = m_pBackend - > GetWindowScreen ( ) ;
m_pBackend - > UpdateDisplayMode ( CurScreen ) ;
m_pBackend - > GetViewportSize ( m_ScreenWidth , m_ScreenHeight ) ;
2022-03-20 17:04:00 +00:00
AdjustViewport ( true ) ;
2021-12-13 17:42:21 +00:00
m_ScreenHiDPIScale = m_ScreenWidth / ( float ) g_Config . m_GfxScreenWidth ;
2016-04-29 22:34:12 +00:00
}
2022-01-15 15:20:01 +00:00
void CGraphics_Threaded : : Resize ( int w , int h , int RefreshRate )
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
2022-01-15 15:20:01 +00:00
if ( WindowWidth ( ) = = w & & WindowHeight ( ) = = h & & 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
2022-01-15 15:20:01 +00:00
if ( m_pBackend - > ResizeWindow ( w , h , RefreshRate ) )
2021-08-24 16:22:31 +00:00
{
2022-01-15 15:20:01 +00:00
CVideoMode CurMode ;
m_pBackend - > GetCurrentVideoMode ( CurMode , m_ScreenHiDPIScale , g_Config . m_GfxDesktopWidth , g_Config . m_GfxDesktopHeight , g_Config . m_GfxScreen ) ;
GotResized ( w , h , RefreshRate ) ;
2021-08-24 16:22:31 +00:00
}
2022-01-15 15:20:01 +00:00
}
2016-04-30 15:59:58 +00:00
2022-01-15 15:20:01 +00:00
void CGraphics_Threaded : : GotResized ( int w , int h , int RefreshRate )
{
# if defined(CONF_VIDEORECORDER)
if ( IVideo : : Current ( ) & & IVideo : : Current ( ) - > IsRecording ( ) )
return ;
# endif
2016-04-30 15:59:58 +00:00
2022-01-15 15:20:01 +00:00
// if RefreshRate is -1 use the current config refresh rate
if ( RefreshRate = = - 1 )
RefreshRate = g_Config . m_GfxScreenRefreshRate ;
2021-08-21 19:41:51 +00:00
2022-01-15 15:20:01 +00:00
// if the size change event is triggered, set all parameters and change the viewport
m_pBackend - > GetViewportSize ( m_ScreenWidth , m_ScreenHeight ) ;
2021-08-21 19:41:51 +00:00
2022-03-20 17:04:00 +00:00
AdjustViewport ( false ) ;
2021-04-07 17:03:07 +00:00
2022-01-15 15:20:01 +00:00
m_ScreenRefreshRate = RefreshRate ;
2016-04-30 15:59:58 +00:00
2022-01-15 15:20:01 +00:00
g_Config . m_GfxScreenWidth = w ;
g_Config . m_GfxScreenHeight = h ;
g_Config . m_GfxScreenRefreshRate = m_ScreenRefreshRate ;
m_ScreenHiDPIScale = m_ScreenWidth / ( float ) g_Config . m_GfxScreenWidth ;
2018-03-21 14:48:48 +00:00
2022-04-19 15:26:05 +00:00
UpdateViewport ( 0 , 0 , m_ScreenWidth , m_ScreenHeight , true ) ;
2022-01-15 15:20:01 +00:00
// kick the command buffer and wait
KickCommandBuffer ( ) ;
WaitForIdle ( ) ;
2022-06-11 19:38:18 +00:00
for ( auto & ResizeListener : m_vResizeListeners )
2022-01-15 15:20:01 +00:00
ResizeListener . m_pFunc ( ResizeListener . m_pUser ) ;
2018-03-21 14:48:48 +00:00
}
void CGraphics_Threaded : : AddWindowResizeListener ( WINDOW_RESIZE_FUNC pFunc , void * pUser )
{
2022-06-11 19:38:18 +00:00
m_vResizeListeners . emplace_back ( 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 )
{
2022-01-20 09:49:31 +00:00
m_pBackend - > WindowDestroyNtf ( WindowID ) ;
2021-08-24 10:18:20 +00:00
CCommandBuffer : : SCommand_WindowDestroyNtf Cmd ;
Cmd . m_WindowID = WindowID ;
if ( ! AddCmd (
Cmd , [ ] { return true ; } , " failed to add window destroy notify command " ) )
{
return ;
}
2022-03-20 17:03:25 +00:00
// wait
KickCommandBuffer ( ) ;
WaitForIdle ( ) ;
2021-08-24 10:18:20 +00:00
}
void CGraphics_Threaded : : WindowCreateNtf ( uint32_t WindowID )
{
2022-01-20 09:49:31 +00:00
m_pBackend - > WindowCreateNtf ( WindowID ) ;
2021-08-24 10:18:20 +00:00
CCommandBuffer : : SCommand_WindowCreateNtf Cmd ;
Cmd . m_WindowID = WindowID ;
if ( ! AddCmd (
Cmd , [ ] { return true ; } , " failed to add window create notify command " ) )
{
return ;
}
2022-03-20 17:03:25 +00:00
// wait
KickCommandBuffer ( ) ;
WaitForIdle ( ) ;
2021-08-24 10:18:20 +00:00
}
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 )
{
2022-07-09 16:14:56 +00:00
str_copy ( m_aScreenshotName , pFilename ) ;
2014-01-19 03:02:01 +00:00
m_DoScreenshot = true ;
}
2011-12-31 00:06:04 +00:00
void CGraphics_Threaded : : Swap ( )
{
2022-06-11 19:38:18 +00:00
if ( ! m_vWarnings . empty ( ) )
2020-08-29 10:49:45 +00:00
{
2020-10-02 13:43:52 +00:00
SWarning * pCurWarning = GetCurWarning ( ) ;
2020-08-29 10:49:45 +00:00
if ( pCurWarning - > m_WasShown )
{
2022-06-11 19:38:18 +00:00
m_vWarnings . erase ( m_vWarnings . begin ( ) ) ;
2020-08-29 10:49:45 +00:00
}
}
2022-03-20 17:04:00 +00:00
bool TookScreenshotAndSwapped = false ;
2011-12-31 00:06:04 +00:00
if ( m_DoScreenshot )
{
2012-03-04 11:46:46 +00:00
if ( WindowActive ( ) )
2022-03-20 17:04:00 +00:00
TookScreenshotAndSwapped = 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
2022-03-20 17:04:00 +00:00
if ( ! TookScreenshotAndSwapped )
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 ( ) ;
2022-01-13 13:22:10 +00:00
// TODO: Remove when https://github.com/libsdl-org/SDL/issues/5203 is fixed
# ifdef CONF_PLATFORM_MACOS
if ( str_find ( GetVersionString ( ) , " Metal " ) )
WaitForIdle ( ) ;
# endif
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 ;
2022-04-26 18:09:47 +00:00
// add vsync 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 ;
}
2022-04-26 18:09:47 +00:00
bool CGraphics_Threaded : : SetMultiSampling ( uint32_t ReqMultiSamplingCount , uint32_t & MultiSamplingCountBackend )
{
if ( ! m_pCommandBuffer )
return true ;
// add multisampling command
bool RetOk = false ;
CCommandBuffer : : SCommand_MultiSampling Cmd ;
Cmd . m_RequestedMultiSamplingCount = ReqMultiSamplingCount ;
Cmd . m_pRetMultiSamplingCount = & MultiSamplingCountBackend ;
Cmd . m_pRetOk = & RetOk ;
if ( ! AddCmd (
Cmd , [ ] { return true ; } , " failed to add multi sampling command " ) )
{
return false ;
}
// 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
{
2022-06-11 19:38:18 +00:00
if ( m_vWarnings . empty ( ) )
2020-08-29 10:49:45 +00:00
return NULL ;
else
{
2022-07-10 19:22:50 +00:00
SWarning * pCurWarning = m_vWarnings . data ( ) ;
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 ( ) ;
}
2022-03-20 17:03:25 +00:00
TGLBackendReadPresentedImageData & CGraphics_Threaded : : GetReadPresentedImageDataFuncUnsafe ( )
{
return m_pBackend - > GetReadPresentedImageDataFuncUnsafe ( ) ;
}
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
{
2022-03-30 13:16:19 +00:00
int Count = std : : size ( g_aFakeModes ) ;
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 ( )
{
return new CGraphics_Threaded ( ) ;
}