55 changes: 47 additions & 8 deletions data/languages/slovak.txt
Expand Up @@ -347,9 +347,6 @@ Red team wins!
Refresh
== Obnoviť

Refreshing master servers
== Obnovujem master servery

Remote console
== Vzdialená konzola

Expand Down Expand Up @@ -413,9 +410,6 @@ Show ingame HUD
Show name plates
== Zobrazovať menovky

Show only supported
== Zobraziť len podporované

Skins
== Skiny

Expand Down Expand Up @@ -739,6 +733,30 @@ transmits your player name to info2.ddnet.tw
Theme
==

AFR
==

ASI
==

AUS
==

EUR
==

NA
==

SA
==

CHN
==

Getting server list from master server
==

Search
==

Expand Down Expand Up @@ -772,6 +790,9 @@ Countries
Types
==

Leak IP
==

Select a name
==

Expand Down Expand Up @@ -952,7 +973,13 @@ UI mouse s.
Dummy
==

Borderless window
Windowed
==

Windowed borderless
==

Desktop fullscreen
==

may cause delay
Expand All @@ -961,7 +988,7 @@ may cause delay
Screen
==

Use OpenGL 3.3 (experimental)
Use modern OpenGL
==

Preinit VBO (iGPUs only)
Expand Down Expand Up @@ -1048,6 +1075,18 @@ Laser Outline Color
Laser Inner Color
==

Hookline
==

No hit
==

Hookable
==

Tee
==

Use old chat style
==

Expand Down
90 changes: 65 additions & 25 deletions data/languages/spanish.txt
Expand Up @@ -10,6 +10,7 @@
# FeaRZ 2020-07-07 12:09:00
# Ryozuki 2020-07-09 12:06:00
# Headshot 2020-11-07 12:40:00
# Headshot 2021-05-30 17:00:00
##### /authors #####

##### translated strings #####
Expand Down Expand Up @@ -357,9 +358,6 @@ Red team wins!
Refresh
== Actualizar

Refreshing master servers
== Actualizando servidores maestros

Remote console
== Consola remota

Expand Down Expand Up @@ -426,9 +424,6 @@ Show name plates
Show only chat messages from friends
== Recibir mensages solo de amigos

Show only supported
== Mostrar únicamente modos soportados

Skins
== Skins

Expand Down Expand Up @@ -615,7 +610,7 @@ Round
== Ronda

Lht.
== Luminosidad
== Lum.

UI Color
== Color de menú
Expand Down Expand Up @@ -905,18 +900,12 @@ Show HUD
UI mouse s.
== UI mouse s.

Borderless window
== Ventana sin bordes

may cause delay
== puede causar retraso

Screen
== Pantalla

Use OpenGL 3.3 (experimental)
== Usar OpenGL 3.3 (experimental)

Preinit VBO (iGPUs only)
== Preinit VBO (solo iGPU)

Expand Down Expand Up @@ -1252,37 +1241,88 @@ Replay
== Repetición

The width of texture %s is not divisible by %d, or the height is not divisible by %d, which might cause visual bugs.
==
== El ancho de la textura %s no es divisible por %d, o el alto no es divisible por %d, lo que puede causar errores visuales.

AFR
== AFR

ASI
== ASI

AUS
== AUS

EUR
== EUR

NA
== NA

SA
== SA

CHN
== CHN

Getting server list from master server
== Obteniendo lista de servidores del servidor maestro

Leak IP
== Filtrar tu IP

Chat command
==
== Comando de chat

Dummy
==
== Dummy

Windowed
== En ventana

Windowed borderless
== Ventana sin bordes

Desktop fullscreen
== Pantalla completa

Use modern OpenGL
== Usar OpenGL moderno

Show client IDs
==
== Mostrar IDs de clientes

Laser Outline Color
==
== Color de contorno del laser

Laser Inner Color
==
== Color interior del laser

Hookline
== Linea del gancho

No hit
== Sin golpes

Hookable
== Enganchable

Tee
== Tee

Preview
==
== Vista previa

Background
==
== Fondo

Entities Background color
==
== Color de fondo de entidades

Regular Background Color
==
== Color de fondo regular

Discord
==
== Discord

https://ddnet.tw/discord
==
== https://ddnet.tw/discord
63 changes: 51 additions & 12 deletions data/languages/swedish.txt
Expand Up @@ -350,9 +350,6 @@ Red team wins!
Refresh
== Uppdatera

Refreshing master servers
== Uppdaterar huvudservrar

Remote console
== Serverkonsol

Expand Down Expand Up @@ -416,9 +413,6 @@ Show ingame HUD
Show name plates
== Visa namnskyltar

Show only supported
== Visa endast upplösningar som stöds

Skins
== Utseende

Expand Down Expand Up @@ -838,9 +832,6 @@ Reset wanted weapon on death
Search
== Sök

Borderless window
== Gränslös fönster

FPM
== FPM

Expand Down Expand Up @@ -1087,9 +1078,6 @@ Show quads
Show names in chat in team colors
== Visa namn in chatten med lag färger

Use OpenGL 3.3 (experimental)
== Använd OpenGL 3.3 (experimentell)

Update now
== Updatera nu

Expand Down Expand Up @@ -1205,6 +1193,33 @@ Checking for existing player with your name
Theme
==

AFR
==

ASI
==

AUS
==

EUR
==

NA
==

SA
==

CHN
==

Getting server list from master server
==

Leak IP
==

Demos directory
==

Expand All @@ -1226,6 +1241,18 @@ Chat command
Dummy
==

Windowed
==

Windowed borderless
==

Desktop fullscreen
==

Use modern OpenGL
==

Game sound volume
==

Expand All @@ -1247,6 +1274,18 @@ Laser Outline Color
Laser Inner Color
==

Hookline
==

No hit
==

Hookable
==

Tee
==

Use old chat style
==

Expand Down
104 changes: 72 additions & 32 deletions data/languages/traditional_chinese.txt
Expand Up @@ -5,6 +5,7 @@
# 2020.8.19 TsFreddie
# 2020.8.20 Dan_cao
# 2020.11.12 TsFreddie
# 2021.6.1 TsFreddie
##### /authors #####

##### translated strings #####
Expand Down Expand Up @@ -184,7 +185,7 @@ Friends
== 好友

Fullscreen
== 全螢幕
== 獨占全螢幕

Game
== 遊戲
Expand Down Expand Up @@ -356,7 +357,7 @@ Player options
== 玩家選項

Players
== 玩家數
== 玩家

Please balance teams!
== 隊伍人數不平衡!
Expand All @@ -379,9 +380,6 @@ Red team wins!
Refresh
== 重新整理

Refreshing master servers
== 正在重新整理主伺服器

Remote console
== 遠端控制檯

Expand Down Expand Up @@ -448,9 +446,6 @@ Show name plates
Show only chat messages from friends
== 只顯示好友訊息

Show only supported
== 只顯示支援的解析度

Skins
== 外觀

Expand Down Expand Up @@ -571,9 +566,6 @@ Yes
You must restart the game for all settings to take effect.
== 你需要重啟遊戲來使某些設定生效。

Borderless window
== 無邊框視窗

Demo
== 回放

Expand Down Expand Up @@ -868,7 +860,7 @@ Frags
== 擊殺數

Enable long pain sound (used when shooting in freeze)
== 啟用長時間痛苦的聲音(在凍結時使用)
== 啟用在凍結時的呼救聲

%.2f MiB
== %.2f MiB
Expand All @@ -877,7 +869,7 @@ Refresh Rate
== 重新整理率

New random timeout code
== 新隨機超時程式碼
== 隨機生成新的超時還原碼

Suicides
== 自殺數
Expand Down Expand Up @@ -928,9 +920,6 @@ Activate
Multiple texture units (disable for MacOS)
== 多重紋理單元 (MacOS不可用)

Use OpenGL 3.3 (experimental)
== 使用 OpenGL 3.3 (實驗性)

File already exists, do you want to overwrite it?
== 檔案已存在,是否覆蓋?

Expand Down Expand Up @@ -968,7 +957,7 @@ Downloading %s:
== 正在下載 %s:

%d new mentions
== %d 條新提示
== %d 條新提及

Toggle dummy
== 切換分身
Expand Down Expand Up @@ -998,7 +987,7 @@ Zoom in
== 視距放大

1 new mention
== 1 條新提示
== 1 條新提及

Update failed! Check log...
== 更新失敗!請檢查日誌...
Expand Down Expand Up @@ -1028,7 +1017,7 @@ Dummy copy
== 分身同步動作

9+ new mentions
== 9+ 條新提示
== 9+ 條新提及

Statboard
== 統計板
Expand Down Expand Up @@ -1233,7 +1222,7 @@ Assets
== 材質

Use old chat style
== 舊版聊天框
== 原始聊天框

Use current map as background
== 使用當前地圖作爲實體層背景地圖
Expand All @@ -1251,37 +1240,88 @@ Assets directory
== 材質目錄

The width of texture %s is not divisible by %d, or the height is not divisible by %d, which might cause visual bugs.
==
== 紋理 %s 的寬度無法被 %d 整除,或者高度無法被 %d 整除,這可能會導致視覺錯誤。

AFR
== 非洲

ASI
== 亞洲

AUS
== 澳洲

EUR
== 歐洲

NA
== 北美

SA
== 南美

CHN
== 中國

Getting server list from master server
== 正在從主伺服器獲取伺服器列表

Leak IP
== 洩露IP

Chat command
==
== 聊天框指令

Dummy
==
== 分身

Windowed
== 視窗化

Windowed borderless
== 無邊框視窗

Desktop fullscreen
== 無邊框全螢幕

Use modern OpenGL
== 使用現代OpenGL

Show client IDs
==
== 顯示客戶端ID

Laser Outline Color
==
== 鐳射線邊框顏色

Laser Inner Color
==
== 鐳射線顏色

Hookline
== 鉤索輔助線

No hit
== 沒有擊中

Hookable
== 可鉤牆壁

Tee
== 其他玩家

Preview
==
== 預覽

Background
==
== 背景

Entities Background color
==
== 實體層背景顏色

Regular Background Color
==
== 背景層背景顏色

Discord
==
== Discord

https://ddnet.tw/discord
==
== https://ddnet.tw/discord
63 changes: 51 additions & 12 deletions data/languages/turkish.txt
Expand Up @@ -349,9 +349,6 @@ Red team wins!
Refresh
== Yenile

Refreshing master servers
== Ana sunucu yenileniyor

Remote console
== Uzak Konsol

Expand Down Expand Up @@ -415,9 +412,6 @@ Show ingame HUD
Show name plates
== Oyuncu isimlerini göster

Show only supported
== Desteklenmeyen çözünürlükleri gizle

Skins
== Skinler

Expand Down Expand Up @@ -906,18 +900,12 @@ Show HUD
UI mouse s.
== Arayüzde mouse duy.

Borderless window
== Kenarsız pencere

may cause delay
== gecikmelere sebep olabilir

Screen
== Ekran

Use OpenGL 3.3 (experimental)
== OpenGL 3.3 Kullan (deneysel)

Preinit VBO (iGPUs only)
== Preinit VBO (sadece iGPUs)

Expand Down Expand Up @@ -1164,6 +1152,30 @@ Speed
Theme
==

AFR
==

ASI
==

AUS
==

EUR
==

NA
==

SA
==

CHN
==

Getting server list from master server
==

%d of %d servers
==

Expand All @@ -1176,6 +1188,9 @@ Theme
%d player
==

Leak IP
==

Demos directory
==

Expand Down Expand Up @@ -1203,6 +1218,18 @@ Chat command
Dummy
==

Windowed
==

Windowed borderless
==

Desktop fullscreen
==

Use modern OpenGL
==

Game sound volume
==

Expand All @@ -1224,6 +1251,18 @@ Laser Outline Color
Laser Inner Color
==

Hookline
==

No hit
==

Hookable
==

Tee
==

Use old chat style
==

Expand Down
63 changes: 51 additions & 12 deletions data/languages/ukrainian.txt
Expand Up @@ -269,9 +269,6 @@ Red team wins!
Refresh
== Оновити

Refreshing master servers
== Оновлення списку майстер-сервера

Remote console
== Консоль сервера

Expand Down Expand Up @@ -311,9 +308,6 @@ Show chat
Show name plates
== Показувати ніки гравців

Show only supported
== Тільки підтримувані режими

Skins
== Скіни

Expand Down Expand Up @@ -889,18 +883,12 @@ Show HUD
UI mouse s.
== Чутлив. миші в меню

Borderless window
== Безмежне вікно

may cause delay
== може спричинити затримку

Screen
== Екран

Use OpenGL 3.3 (experimental)
== OpenGL 3.3 (експериментально)

Preinit VBO (iGPUs only)
== Preinit VBO (iGPUs only)

Expand Down Expand Up @@ -1156,6 +1144,30 @@ Speed
Theme
==

AFR
==

ASI
==

AUS
==

EUR
==

NA
==

SA
==

CHN
==

Getting server list from master server
==

%d of %d servers
==

Expand All @@ -1168,6 +1180,9 @@ Theme
%d player
==

Leak IP
==

Markers
==

Expand Down Expand Up @@ -1198,6 +1213,18 @@ Chat command
Dummy
==

Windowed
==

Windowed borderless
==

Desktop fullscreen
==

Use modern OpenGL
==

Game sound volume
==

Expand All @@ -1219,6 +1246,18 @@ Laser Outline Color
Laser Inner Color
==

Hookline
==

No hit
==

Hookable
==

Tee
==

Use old chat style
==

Expand Down
8 changes: 4 additions & 4 deletions data/shader/text.frag
Expand Up @@ -10,12 +10,12 @@ noperspective in vec4 outVertColor;
out vec4 FragClr;
void main()
{
vec4 textColor = gVertColor * outVertColor * texture(gTextSampler, texCoord);
vec4 textOutlineTex = gVertOutlineColor * texture(gTextOutlineSampler, texCoord);
vec4 textColor = gVertColor * outVertColor * vec4(1.0, 1.0, 1.0, texture(gTextSampler, texCoord).r);
vec4 textOutlineTex = gVertOutlineColor * vec4(1.0, 1.0, 1.0, texture(gTextOutlineSampler, texCoord).r);

// ratio between the two textures
float OutlineBlend = (1.0 - textColor.a);

// since the outline is always black, or even if it has decent colors, it can be just added to the actual color
// without loosing any or too much color

Expand Down
8 changes: 4 additions & 4 deletions data/shader/tile.vert
Expand Up @@ -24,14 +24,14 @@ void main()
vec4 VertPos = vec4(inVertex, 0.0, 1.0);
int XCount = gl_InstanceID - (int(gl_InstanceID/gJumpIndex) * gJumpIndex);
int YCount = (int(gl_InstanceID/gJumpIndex));
VertPos.x += gOffset.x + gDir.x * XCount;
VertPos.y += gOffset.y + gDir.y * YCount;
VertPos.x += gOffset.x + gDir.x * float(XCount);
VertPos.y += gOffset.y + gDir.y * float(YCount);

gl_Position = vec4(gPos * VertPos, 0.0, 1.0);
#elif defined(TW_TILE_BORDER_LINE)
vec4 VertPos = vec4(inVertex.x + gOffset.x, inVertex.y + gOffset.y, 0.0, 1.0);
VertPos.x += gDir.x * gl_InstanceID;
VertPos.y += gDir.y * gl_InstanceID;
VertPos.x += gDir.x * float(gl_InstanceID);
VertPos.y += gDir.y * float(gl_InstanceID);

gl_Position = vec4(gPos * VertPos, 0.0, 1.0);
#else
Expand Down
1 change: 1 addition & 0 deletions other/ddnet.appdata.xml
Expand Up @@ -37,6 +37,7 @@
<content_attribute id="social-chat">intense</content_attribute>
</content_rating>
<releases>
<release date="2021-03-25" version="15.4"/>
<release date="2021-02-20" version="15.3.2"/>
<release date="2021-02-12" version="15.3.1"/>
<release date="2021-02-11" version="15.3"/>
Expand Down
20 changes: 18 additions & 2 deletions scripts/fix_style.py
Expand Up @@ -26,11 +26,27 @@ def filter_cpp(filenames):
return [filename for filename in filenames
if any(filename.endswith(ext) for ext in ".c .cpp .h".split())]

def find_clang_format(version):
for binary in (
"clang-format",
"clang-format-{}".format(version),
"/opt/clang-format-static/clang-format-{}".format(version)):
try:
out = subprocess.check_output([binary, "--version"])
except FileNotFoundError:
continue
if "clang-format version {}.".format(version) in out.decode("utf-8"):
return binary
print("Found no clang-format {}".format(version))
sys.exit(-1)

clang_format_bin = find_clang_format(10)

def reformat(filenames):
subprocess.check_call(["clang-format", "-i"] + filenames)
subprocess.check_call([clang_format_bin, "-i"] + filenames)

def warn(filenames):
return subprocess.call(["clang-format", "-Werror", "--dry-run"] + filenames)
return subprocess.call([clang_format_bin, "-Werror", "--dry-run"] + filenames)

def main():
p = argparse.ArgumentParser(description="Check and fix style of changed files")
Expand Down
8 changes: 8 additions & 0 deletions src/base/detect.h
Expand Up @@ -51,6 +51,7 @@
#define CONF_FAMILY_STRING "unix"
#define CONF_PLATFORM_LINUX 1
#define PLATFORM_STRING "linux"
#define CONF_BACKEND_OPENGL_ES3 1
#endif

#if defined(__GNU__) || defined(__gnu__)
Expand Down Expand Up @@ -82,6 +83,13 @@
#define PLATFORM_STRING "beos"
#endif

#if defined(__HAIKU__)
#define CONF_FAMILY_UNIX 1
#define CONF_FAMILY_STRING "unix"
#define CONF_PLATFORM_HAIKU 1
#define CONF_PLATFORM_STRING "haiku"
#endif

/* use gcc endianness definitions when available */
#if defined(__GNUC__) && !defined(__APPLE__) && !defined(__MINGW32__) && !defined(__sun)
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
Expand Down
155 changes: 141 additions & 14 deletions src/base/system.c
Expand Up @@ -1089,6 +1089,73 @@ int net_addr_comp_noport(const NETADDR *a, const NETADDR *b)
return net_addr_comp(&ta, &tb);
}

void net_addr_str_v6(const unsigned short ip[8], int port, char *buffer, int buffer_size)
{
int longest_seq_len = 0;
int longest_seq_start = -1;
int w = 0;
int i;
{
int seq_len = 0;
int seq_start = -1;
// Determine longest sequence of zeros.
for(i = 0; i < 8 + 1; i++)
{
if(seq_start != -1)
{
if(i == 8 || ip[i] != 0)
{
if(longest_seq_len < seq_len)
{
longest_seq_len = seq_len;
longest_seq_start = seq_start;
}
seq_len = 0;
seq_start = -1;
}
else
{
seq_len += 1;
}
}
else
{
if(i != 8 && ip[i] == 0)
{
seq_start = i;
seq_len = 1;
}
}
}
}
if(longest_seq_len <= 1)
{
longest_seq_len = 0;
longest_seq_start = -1;
}
w += str_format(buffer + w, buffer_size - w, "[");
for(i = 0; i < 8; i++)
{
if(longest_seq_start <= i && i < longest_seq_start + longest_seq_len)
{
if(i == longest_seq_start)
{
w += str_format(buffer + w, buffer_size - w, "::");
}
}
else
{
char *colon = i == 0 || i == longest_seq_start + longest_seq_len ? "" : ":";
w += str_format(buffer + w, buffer_size - w, "%s%x", colon, ip[i]);
}
}
w += str_format(buffer + w, buffer_size - w, "]");
if(port >= 0)
{
str_format(buffer + w, buffer_size - w, ":%d", port);
}
}

void net_addr_str(const NETADDR *addr, char *string, int max_length, int add_port)
{
if(addr->type == NETTYPE_IPV4 || addr->type == NETTYPE_WEBSOCKET_IPV4)
Expand All @@ -1100,15 +1167,18 @@ void net_addr_str(const NETADDR *addr, char *string, int max_length, int add_por
}
else if(addr->type == NETTYPE_IPV6)
{
if(add_port != 0)
str_format(string, max_length, "[%x:%x:%x:%x:%x:%x:%x:%x]:%d",
(addr->ip[0] << 8) | addr->ip[1], (addr->ip[2] << 8) | addr->ip[3], (addr->ip[4] << 8) | addr->ip[5], (addr->ip[6] << 8) | addr->ip[7],
(addr->ip[8] << 8) | addr->ip[9], (addr->ip[10] << 8) | addr->ip[11], (addr->ip[12] << 8) | addr->ip[13], (addr->ip[14] << 8) | addr->ip[15],
addr->port);
else
str_format(string, max_length, "[%x:%x:%x:%x:%x:%x:%x:%x]",
(addr->ip[0] << 8) | addr->ip[1], (addr->ip[2] << 8) | addr->ip[3], (addr->ip[4] << 8) | addr->ip[5], (addr->ip[6] << 8) | addr->ip[7],
(addr->ip[8] << 8) | addr->ip[9], (addr->ip[10] << 8) | addr->ip[11], (addr->ip[12] << 8) | addr->ip[13], (addr->ip[14] << 8) | addr->ip[15]);
int port = -1;
unsigned short ip[8];
int i;
if(add_port)
{
port = addr->port;
}
for(i = 0; i < 8; i++)
{
ip[i] = (addr->ip[i * 2] << 8) | (addr->ip[i * 2 + 1]);
}
net_addr_str_v6(ip, port, string, max_length);
}
else
str_format(string, max_length, "unknown type %d", addr->type);
Expand Down Expand Up @@ -1287,6 +1357,10 @@ int net_addr_from_str(NETADDR *addr, const char *string)
if(parse_uint16(&addr->port, &str))
return -1;
}
else
{
addr->port = 0;
}
}
else
return -1;
Expand Down Expand Up @@ -2074,6 +2148,11 @@ int fs_storage_path(const char *appname, char *path, int max)
if(!home)
return -1;

#if defined(CONF_PLATFORM_HAIKU)
str_format(path, max, "%s/config/settings/%s", home, appname);
return 0;
#endif

#if defined(CONF_PLATFORM_MACOS)
snprintf(path, max, "%s/Library/Application Support/%s", home, appname);
#else
Expand Down Expand Up @@ -2113,6 +2192,11 @@ int fs_makedir(const char *path)
return 0;
return -1;
#else
#ifdef CONF_PLATFORM_HAIKU
struct stat st;
if(stat(path, &st) == 0)
return 0;
#endif
if(mkdir(path, 0755) == 0)
return 0;
if(errno == EEXIST)
Expand All @@ -2121,6 +2205,19 @@ int fs_makedir(const char *path)
#endif
}

int fs_removedir(const char *path)
{
#if defined(CONF_FAMILY_WINDOWS)
if(_rmdir(path) == 0)
return 0;
return -1;
#else
if(rmdir(path) == 0)
return 0;
return -1;
#endif
}

int fs_is_dir(const char *path)
{
#if defined(CONF_FAMILY_WINDOWS)
Expand Down Expand Up @@ -2199,9 +2296,11 @@ int fs_parent_dir(char *path)

int fs_remove(const char *filename)
{
if(remove(filename) != 0)
return 1;
return 0;
#if defined(CONF_FAMILY_WINDOWS)
return _unlink(filename) != 0;
#else
return unlink(filename) != 0;
#endif
}

int fs_rename(const char *oldname, const char *newname)
Expand Down Expand Up @@ -3017,8 +3116,8 @@ const char *str_utf8_find_nocase(const char *haystack, const char *needle)

int str_utf8_isspace(int code)
{
return code <= 0x0020 || code == 0x0085 || code == 0x00A0 ||
code == 0x034F || code == 0x1160 || code == 0x1680 || code == 0x180E ||
return code <= 0x0020 || code == 0x0085 || code == 0x00A0 || code == 0x034F ||
code == 0x115F || code == 0x1160 || code == 0x1680 || code == 0x180E ||
(code >= 0x2000 && code <= 0x200F) || (code >= 0x2028 && code <= 0x202F) ||
(code >= 0x205F && code <= 0x2064) || (code >= 0x206A && code <= 0x206F) ||
code == 0x2800 || code == 0x3000 || code == 0x3164 ||
Expand Down Expand Up @@ -3524,6 +3623,34 @@ int secure_rand(void)
return (int)(i % RAND_MAX);
}

// From https://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2.
static unsigned int find_next_power_of_two_minus_one(unsigned int n)
{
n--;
n |= n >> 1;
n |= n >> 2;
n |= n >> 4;
n |= n >> 4;
n |= n >> 16;
return n;
}

int secure_rand_below(int below)
{
unsigned int mask = find_next_power_of_two_minus_one(below);
dbg_assert(below > 0, "below must be positive");
while(1)
{
unsigned int n;
secure_random_fill(&n, sizeof(n));
n &= mask;
if((int)n < below)
{
return n;
}
}
}

#if defined(__cplusplus)
}
#endif
30 changes: 30 additions & 0 deletions src/base/system.h
Expand Up @@ -631,7 +631,11 @@ void sphore_destroy(SEMAPHORE *sem);
/* if compiled with -pedantic-errors it will complain about long
not being a C90 thing.
*/
#ifdef CONF_PLATFORM_HAIKU
#include <SupportDefs.h>
#else
__extension__ typedef long long int64;
#endif
__extension__ typedef unsigned long long uint64;
#else
typedef long long int64;
Expand Down Expand Up @@ -1634,6 +1638,21 @@ int fs_listdir_info(const char *dir, FS_LISTDIR_INFO_CALLBACK cb, int type, void
*/
int fs_makedir(const char *path);

/*
Function: fs_removedir
Removes a directory
Parameters:
path - Directory to remove
Returns:
Returns 0 on success. Negative value on failure.
Remarks:
Cannot remove a non-empty directory.
*/
int fs_removedir(const char *path);

/*
Function: fs_makedir_rec_for
Recursively create directories for a file
Expand Down Expand Up @@ -1720,6 +1739,7 @@ int fs_parent_dir(char *path);
Remarks:
- The strings are treated as zero-terminated strings.
- Returns an error if the path specifies a directory name.
*/
int fs_remove(const char *filename);

Expand Down Expand Up @@ -2189,6 +2209,16 @@ void secure_random_fill(void *bytes, unsigned length);
*/
int secure_rand(void);

/*
Function: secure_rand_below
Returns a random nonnegative integer below the given number,
with a uniform distribution.
Parameters:
below - Upper limit (exclusive) of integers to return.
*/
int secure_rand_below(int below);

#ifdef __cplusplus
}
#endif
Expand Down
3 changes: 2 additions & 1 deletion src/base/tl/sorted_array.h
Expand Up @@ -38,7 +38,8 @@ class sorted_array : public array<T, ALLOCATOR>

void sort_range()
{
sort(all());
if(parent::size() > 0)
sort(all());
}

/*
Expand Down
3 changes: 1 addition & 2 deletions src/engine/client.h
Expand Up @@ -125,8 +125,7 @@ class IClient : public IInterface

// gfx
virtual void SwitchWindowScreen(int Index) = 0;
virtual void ToggleFullscreen() = 0;
virtual void ToggleWindowBordered() = 0;
virtual void SetWindowParams(int FullscreenMode, bool IsBorderless) = 0;
virtual void ToggleWindowVSync() = 0;
virtual void LoadFont() = 0;
virtual void Notify(const char *pTitle, const char *pMessage) = 0;
Expand Down
244 changes: 244 additions & 0 deletions src/engine/client/backend/glsl_shader_compiler.cpp
@@ -0,0 +1,244 @@
#include "glsl_shader_compiler.h"

#include <base/system.h>
#include <engine/client/backend_sdl.h>

CGLSLCompiler::CGLSLCompiler(int OpenGLVersionMajor, int OpenGLVersionMinor, int OpenGLVersionPatch, bool IsOpenGLES, float TextureLODBias)
{
m_OpenGLVersionMajor = OpenGLVersionMajor;
m_OpenGLVersionMinor = OpenGLVersionMinor;
m_OpenGLVersionPatch = OpenGLVersionPatch;

m_IsOpenGLES = IsOpenGLES;

m_TextureLODBias = TextureLODBias;

m_HasTextureArray = false;
m_TextureReplaceType = 0;
}

void CGLSLCompiler::AddDefine(const std::string &DefineName, const std::string &DefineValue)
{
m_Defines.emplace_back(SGLSLCompilerDefine(DefineName, DefineValue));
}

void CGLSLCompiler::AddDefine(const char *pDefineName, const char *pDefineValue)
{
AddDefine(std::string(pDefineName), std::string(pDefineValue));
}

void CGLSLCompiler::ClearDefines()
{
m_Defines.clear();
}

void CGLSLCompiler::ParseLine(std::string &Line, const char *pReadLine, EGLSLShaderCompilerType Type)
{
EBackendType BackendType = m_IsOpenGLES ? BACKEND_TYPE_OPENGL_ES : BACKEND_TYPE_OPENGL;
bool IsNewOpenGL = (BackendType == BACKEND_TYPE_OPENGL ? (m_OpenGLVersionMajor >= 4 || (m_OpenGLVersionMajor == 3 && m_OpenGLVersionMinor == 3)) : m_OpenGLVersionMajor >= 3);
if(!IsNewOpenGL)
{
const char *pBuff = pReadLine;
char aTmpStr[1024];
size_t TmpStrSize = 0;
while(*pBuff)
{
while(*pBuff && str_isspace(*pBuff))
{
Line.append(1, *pBuff);
++pBuff;
}

while(*pBuff && !str_isspace(*pBuff) && *pBuff != '(' && *pBuff != '.')
{
aTmpStr[TmpStrSize++] = *pBuff;
++pBuff;
}

if(TmpStrSize > 0)
{
aTmpStr[TmpStrSize] = 0;
TmpStrSize = 0;
if(str_comp(aTmpStr, "layout") == 0)
{
//search for ' in'
while(*pBuff && (*pBuff != ' ' || (*(pBuff + 1) && *(pBuff + 1) != 'i') || *(pBuff + 2) != 'n'))
{
++pBuff;
}

if(*pBuff == ' ' && *(pBuff + 1) && *(pBuff + 1) == 'i' && *(pBuff + 2) == 'n')
{
pBuff += 3;
Line.append("attribute");
Line.append(pBuff);
return;
}
else
{
dbg_msg("shadercompiler", "Fix shader for older OpenGL versions.");
}
}
else if(str_comp(aTmpStr, "noperspective") == 0 || str_comp(aTmpStr, "smooth") == 0 || str_comp(aTmpStr, "flat") == 0)
{
//search for 'in' or 'out'
while(*pBuff && ((*pBuff != 'i' || *(pBuff + 1) != 'n') && (*pBuff != 'o' || (*(pBuff + 1) && *(pBuff + 1) != 'u') || *(pBuff + 2) != 't')))
{
++pBuff;
}

bool Found = false;
if(*pBuff)
{
if(*pBuff == 'i' && *(pBuff + 1) == 'n')
{
pBuff += 2;
Found = true;
}
else if(*pBuff == 'o' && *(pBuff + 1) && *(pBuff + 1) == 'u' && *(pBuff + 2) == 't')
{
pBuff += 3;
Found = true;
}
}

if(!Found)
{
dbg_msg("shadercompiler", "Fix shader for older OpenGL versions.");
}

Line.append("varying");
Line.append(pBuff);
return;
}
else if(str_comp(aTmpStr, "out") == 0 || str_comp(aTmpStr, "in") == 0)
{
if(Type == GLSL_SHADER_COMPILER_TYPE_FRAGMENT && str_comp(aTmpStr, "out") == 0)
return;
Line.append("varying");
Line.append(pBuff);
return;
}
else if(str_comp(aTmpStr, "FragClr") == 0)
{
Line.append("gl_FragColor");
Line.append(pBuff);
return;
}
else if(str_comp(aTmpStr, "texture") == 0)
{
if(m_TextureReplaceType == GLSL_COMPILER_TEXTURE_REPLACE_TYPE_2D)
Line.append("texture2D");
else if(m_TextureReplaceType == GLSL_COMPILER_TEXTURE_REPLACE_TYPE_3D)
Line.append("texture3D");
else if(m_TextureReplaceType == GLSL_COMPILER_TEXTURE_REPLACE_TYPE_2D_ARRAY)
Line.append("texture2DArray");
std::string RestLine;
ParseLine(RestLine, pBuff, Type);
Line.append(RestLine);
return;
}
else
{
Line.append(aTmpStr);
}
}

if(*pBuff)
{
Line.append(1, *pBuff);
++pBuff;
}
}
}
else
{
if(BackendType == BACKEND_TYPE_OPENGL_ES)
{
const char *pBuff = pReadLine;
char aTmpStr[1024];
size_t TmpStrSize = 0;
while(*pBuff)
{
while(*pBuff && str_isspace(*pBuff))
{
Line.append(1, *pBuff);
++pBuff;
}

while(*pBuff && !str_isspace(*pBuff) && *pBuff != '(' && *pBuff != '.')
{
aTmpStr[TmpStrSize++] = *pBuff;
++pBuff;
}

if(TmpStrSize > 0)
{
aTmpStr[TmpStrSize] = 0;
TmpStrSize = 0;

if(str_comp(aTmpStr, "noperspective") == 0)
{
Line.append("smooth");
Line.append(pBuff);
return;
}
// since GLES doesnt support texture LOD bias as global state, use the shader function instead(since GLES 3.0 uses shaders only anyway)
else if(str_comp(aTmpStr, "texture") == 0)
{
Line.append("texture");
// check opening and closing brackets to find the end
int CurBrackets = 1;
while(*pBuff && *pBuff != '(')
{
Line.append(1, *pBuff);

++pBuff;
}

if(*pBuff)
{
Line.append(1, *pBuff);
++pBuff;
}

while(*pBuff)
{
if(*pBuff == '(')
++CurBrackets;
if(*pBuff == ')')
--CurBrackets;

if(CurBrackets == 0)
{
// found end
Line.append(std::string(", ") + std::to_string(m_TextureLODBias) + ")");
++pBuff;
break;
}
else
Line.append(1, *pBuff);
++pBuff;
}

Line.append(pBuff);

return;
}
else
{
Line.append(aTmpStr);
}
}

if(*pBuff)
{
Line.append(1, *pBuff);
++pBuff;
}
}
}
else
Line = pReadLine;
}
}
@@ -1,28 +1,13 @@
#ifndef ENGINE_CLIENT_OPENGL_SL_H
#define ENGINE_CLIENT_OPENGL_SL_H
#ifndef ENGINE_CLIENT_BACKEND_GLSL_SHADER_COMPILER_H
#define ENGINE_CLIENT_BACKEND_GLSL_SHADER_COMPILER_H

#include <GL/glew.h>
#include <string>
#include <vector>

class CGLSLCompiler;

class CGLSL
enum EGLSLShaderCompilerType
{
public:
bool LoadShader(CGLSLCompiler *pCompiler, class IStorage *pStorage, const char *pFile, int Type);
void DeleteShader();

bool IsLoaded();
GLuint GetShaderID();

CGLSL();
virtual ~CGLSL();

private:
GLuint m_ShaderID;
int m_Type;
bool m_IsLoaded;
GLSL_SHADER_COMPILER_TYPE_VERTEX = 0,
GLSL_SHADER_COMPILER_TYPE_FRAGMENT,
};

class CGLSLCompiler
Expand All @@ -47,18 +32,22 @@ class CGLSLCompiler
int m_OpenGLVersionMinor;
int m_OpenGLVersionPatch;

bool m_IsOpenGLES;

float m_TextureLODBias;

bool m_HasTextureArray;
int m_TextureReplaceType; // @see EGLSLCompilerTextureReplaceType
public:
CGLSLCompiler(int OpenGLVersionMajor, int OpenGLVersionMinor, int OpenGLVersionPatch);
CGLSLCompiler(int OpenGLVersionMajor, int OpenGLVersionMinor, int OpenGLVersionPatch, bool IsOpenGLES, float TextureLODBias);
void SetHasTextureArray(bool TextureArray) { m_HasTextureArray = TextureArray; }
void SetTextureReplaceType(int TextureReplaceType) { m_TextureReplaceType = TextureReplaceType; }

void AddDefine(const std::string &DefineName, const std::string &DefineValue);
void AddDefine(const char *pDefineName, const char *pDefineValue);
void ClearDefines();

void ParseLine(std::string &Line, const char *pReadLine, int Type);
void ParseLine(std::string &Line, const char *pReadLine, EGLSLShaderCompilerType Type);

enum EGLSLCompilerTextureReplaceType
{
Expand All @@ -68,4 +57,4 @@ class CGLSLCompiler
};
};

#endif // ENGINE_CLIENT_OPENGL_SL_H
#endif
2,332 changes: 2,332 additions & 0 deletions src/engine/client/backend/opengl/backend_opengl.cpp

Large diffs are not rendered by default.

219 changes: 219 additions & 0 deletions src/engine/client/backend/opengl/backend_opengl.h
@@ -0,0 +1,219 @@
// This file can be included several times.
#if(!defined(BACKEND_AS_OPENGL_ES) && !defined(ENGINE_CLIENT_BACKEND_OPENGL_BACKEND_OPENGL_H)) || \
(defined(BACKEND_AS_OPENGL_ES) && !defined(ENGINE_CLIENT_BACKEND_OPENGL_BACKEND_OPENGL_H_AS_ES))

#if !defined(BACKEND_AS_OPENGL_ES) && !defined(ENGINE_CLIENT_BACKEND_OPENGL_BACKEND_OPENGL_H)
#define ENGINE_CLIENT_BACKEND_OPENGL_BACKEND_OPENGL_H
#endif

#if defined(BACKEND_AS_OPENGL_ES) && !defined(ENGINE_CLIENT_BACKEND_OPENGL_BACKEND_OPENGL_H_AS_ES)
#define ENGINE_CLIENT_BACKEND_OPENGL_BACKEND_OPENGL_H_AS_ES
#endif

#include <engine/client/backend_sdl.h>

class CGLSLProgram;
class CGLSLTWProgram;
class CGLSLPrimitiveProgram;
class CGLSLQuadProgram;
class CGLSLTileProgram;
class CGLSLTextProgram;
class CGLSLPrimitiveExProgram;
class CGLSLSpriteMultipleProgram;

#if defined(BACKEND_AS_OPENGL_ES) && defined(CONF_BACKEND_OPENGL_ES3)
#define BACKEND_GL_MODERN_API 1
#endif

// takes care of opengl related rendering
class CCommandProcessorFragment_OpenGL : public CCommandProcessorFragment_OpenGLBase
{
protected:
struct CTexture
{
CTexture() :
m_Tex(0), m_Tex2DArray(0), m_Sampler(0), m_Sampler2DArray(0), m_LastWrapMode(CCommandBuffer::WRAP_REPEAT), m_MemSize(0), m_Width(0), m_Height(0), m_RescaleCount(0), m_ResizeWidth(0), m_ResizeHeight(0)
{
}

TWGLuint m_Tex;
TWGLuint m_Tex2DArray; //or 3D texture as fallback
TWGLuint m_Sampler;
TWGLuint m_Sampler2DArray; //or 3D texture as fallback
int m_LastWrapMode;

int m_MemSize;

int m_Width;
int m_Height;
int m_RescaleCount;
float m_ResizeWidth;
float m_ResizeHeight;
};
std::vector<CTexture> m_Textures;
std::atomic<int> *m_pTextureMemoryUsage;

TWGLint m_MaxTexSize;

bool m_Has2DArrayTextures;
bool m_Has2DArrayTexturesAsExtension;
TWGLenum m_2DArrayTarget;
bool m_Has3DTextures;
bool m_HasMipMaps;
bool m_HasNPOTTextures;

bool m_HasShaders;
int m_LastBlendMode; //avoid all possible opengl state changes
bool m_LastClipEnable;

int m_OpenGLTextureLodBIAS;

bool m_IsOpenGLES;

protected:
bool IsTexturedState(const CCommandBuffer::SState &State);
static bool Texture2DTo3D(void *pImageBuffer, int ImageWidth, int ImageHeight, int ImageColorChannelCount, int SplitCountWidth, int SplitCountHeight, void *pTarget3DImageData, int &Target3DImageWidth, int &Target3DImageHeight);

bool InitOpenGL(const SCommand_Init *pCommand);

void SetState(const CCommandBuffer::SState &State, bool Use2DArrayTexture = false);
virtual bool IsNewApi() { return false; }
void DestroyTexture(int Slot);

static int TexFormatToOpenGLFormat(int TexFormat);
static int TexFormatToImageColorChannelCount(int TexFormat);
static void *Resize(int Width, int Height, int NewWidth, int NewHeight, int Format, const unsigned char *pData);

virtual bool Cmd_Init(const SCommand_Init *pCommand);
virtual void Cmd_Shutdown(const SCommand_Shutdown *pCommand) {}
virtual void Cmd_Texture_Update(const CCommandBuffer::SCommand_Texture_Update *pCommand);
virtual void Cmd_Texture_Destroy(const CCommandBuffer::SCommand_Texture_Destroy *pCommand);
virtual void Cmd_Texture_Create(const CCommandBuffer::SCommand_Texture_Create *pCommand);
virtual void Cmd_Clear(const CCommandBuffer::SCommand_Clear *pCommand);
virtual void Cmd_Render(const CCommandBuffer::SCommand_Render *pCommand);
virtual void Cmd_RenderTex3D(const CCommandBuffer::SCommand_RenderTex3D *pCommand) {}
virtual void Cmd_Screenshot(const CCommandBuffer::SCommand_Screenshot *pCommand);

virtual void Cmd_Update_Viewport(const CCommandBuffer::SCommand_Update_Viewport *pCommand);
virtual void Cmd_Finish(const CCommandBuffer::SCommand_Finish *pCommand);

virtual void Cmd_CreateBufferObject(const CCommandBuffer::SCommand_CreateBufferObject *pCommand) {}
virtual void Cmd_RecreateBufferObject(const CCommandBuffer::SCommand_RecreateBufferObject *pCommand) {}
virtual void Cmd_UpdateBufferObject(const CCommandBuffer::SCommand_UpdateBufferObject *pCommand) {}
virtual void Cmd_CopyBufferObject(const CCommandBuffer::SCommand_CopyBufferObject *pCommand) {}
virtual void Cmd_DeleteBufferObject(const CCommandBuffer::SCommand_DeleteBufferObject *pCommand) {}

virtual void Cmd_CreateBufferContainer(const CCommandBuffer::SCommand_CreateBufferContainer *pCommand) {}
virtual void Cmd_UpdateBufferContainer(const CCommandBuffer::SCommand_UpdateBufferContainer *pCommand) {}
virtual void Cmd_DeleteBufferContainer(const CCommandBuffer::SCommand_DeleteBufferContainer *pCommand) {}
virtual void Cmd_IndicesRequiredNumNotify(const CCommandBuffer::SCommand_IndicesRequiredNumNotify *pCommand) {}

virtual void Cmd_RenderTileLayer(const CCommandBuffer::SCommand_RenderTileLayer *pCommand) {}
virtual void Cmd_RenderBorderTile(const CCommandBuffer::SCommand_RenderBorderTile *pCommand) {}
virtual void Cmd_RenderBorderTileLine(const CCommandBuffer::SCommand_RenderBorderTileLine *pCommand) {}
virtual void Cmd_RenderQuadLayer(const CCommandBuffer::SCommand_RenderQuadLayer *pCommand) {}
virtual void Cmd_RenderText(const CCommandBuffer::SCommand_RenderText *pCommand) {}
virtual void Cmd_RenderTextStream(const CCommandBuffer::SCommand_RenderTextStream *pCommand) {}
virtual void Cmd_RenderQuadContainer(const CCommandBuffer::SCommand_RenderQuadContainer *pCommand) {}
virtual void Cmd_RenderQuadContainerEx(const CCommandBuffer::SCommand_RenderQuadContainerEx *pCommand) {}
virtual void Cmd_RenderQuadContainerAsSpriteMultiple(const CCommandBuffer::SCommand_RenderQuadContainerAsSpriteMultiple *pCommand) {}

public:
CCommandProcessorFragment_OpenGL();
virtual ~CCommandProcessorFragment_OpenGL() = default;

virtual bool RunCommand(const CCommandBuffer::SCommand *pBaseCommand);
};

class CCommandProcessorFragment_OpenGL2 : public CCommandProcessorFragment_OpenGL
{
struct SBufferContainer
{
SBufferContainer() {}
SBufferContainerInfo m_ContainerInfo;
};
std::vector<SBufferContainer> m_BufferContainers;

GL_SVertexTex3D m_aStreamVertices[1024 * 4];

struct SBufferObject
{
SBufferObject(TWGLuint BufferObjectID) :
m_BufferObjectID(BufferObjectID)
{
m_pData = NULL;
m_DataSize = 0;
}
TWGLuint m_BufferObjectID;
void *m_pData;
size_t m_DataSize;
};

std::vector<SBufferObject> m_BufferObjectIndices;

#ifndef BACKEND_GL_MODERN_API
bool DoAnalyzeStep(size_t StepN, size_t CheckCount, size_t VerticesCount, uint8_t aFakeTexture[], size_t SingleImageSize);
bool IsTileMapAnalysisSucceeded();

void RenderBorderTileEmulation(SBufferContainer &BufferContainer, const CCommandBuffer::SState &State, const float *pColor, const char *pBuffOffset, unsigned int DrawNum, const float *pOffset, const float *pDir, int JumpIndex);
void RenderBorderTileLineEmulation(SBufferContainer &BufferContainer, const CCommandBuffer::SState &State, const float *pColor, const char *pBuffOffset, unsigned int IndexDrawNum, unsigned int DrawNum, const float *pOffset, const float *pDir);
#endif

void UseProgram(CGLSLTWProgram *pProgram);

protected:
void SetState(const CCommandBuffer::SState &State, CGLSLTWProgram *pProgram, bool Use2DArrayTextures = false);

#ifndef BACKEND_GL_MODERN_API
bool Cmd_Init(const SCommand_Init *pCommand) override;

void Cmd_RenderTex3D(const CCommandBuffer::SCommand_RenderTex3D *pCommand) override;

void Cmd_CreateBufferObject(const CCommandBuffer::SCommand_CreateBufferObject *pCommand) override;
void Cmd_RecreateBufferObject(const CCommandBuffer::SCommand_RecreateBufferObject *pCommand) override;
void Cmd_UpdateBufferObject(const CCommandBuffer::SCommand_UpdateBufferObject *pCommand) override;
void Cmd_CopyBufferObject(const CCommandBuffer::SCommand_CopyBufferObject *pCommand) override;
void Cmd_DeleteBufferObject(const CCommandBuffer::SCommand_DeleteBufferObject *pCommand) override;

void Cmd_CreateBufferContainer(const CCommandBuffer::SCommand_CreateBufferContainer *pCommand) override;
void Cmd_UpdateBufferContainer(const CCommandBuffer::SCommand_UpdateBufferContainer *pCommand) override;
void Cmd_DeleteBufferContainer(const CCommandBuffer::SCommand_DeleteBufferContainer *pCommand) override;
void Cmd_IndicesRequiredNumNotify(const CCommandBuffer::SCommand_IndicesRequiredNumNotify *pCommand) override;

void Cmd_RenderTileLayer(const CCommandBuffer::SCommand_RenderTileLayer *pCommand) override;
void Cmd_RenderBorderTile(const CCommandBuffer::SCommand_RenderBorderTile *pCommand) override;
void Cmd_RenderBorderTileLine(const CCommandBuffer::SCommand_RenderBorderTileLine *pCommand) override;
#endif

CGLSLTileProgram *m_pTileProgram;
CGLSLTileProgram *m_pTileProgramTextured;
CGLSLPrimitiveProgram *m_pPrimitive3DProgram;
CGLSLPrimitiveProgram *m_pPrimitive3DProgramTextured;

bool m_UseMultipleTextureUnits;

TWGLint m_MaxTextureUnits;

struct STextureBound
{
int m_TextureSlot;
bool m_Is2DArray;
};
std::vector<STextureBound> m_TextureSlotBoundToUnit; //the texture index generated by loadtextureraw is stored in an index calculated by max texture units

bool IsAndUpdateTextureSlotBound(int IDX, int Slot, bool Is2DArray = false);

public:
CCommandProcessorFragment_OpenGL2() :
CCommandProcessorFragment_OpenGL(), m_UseMultipleTextureUnits(false) {}
};

class CCommandProcessorFragment_OpenGL3 : public CCommandProcessorFragment_OpenGL2
{
};

#if defined(BACKEND_AS_OPENGL_ES) && defined(CONF_BACKEND_OPENGL_ES3)
#undef BACKEND_GL_MODERN_API
#endif

#endif
1,571 changes: 1,571 additions & 0 deletions src/engine/client/backend/opengl/backend_opengl3.cpp

Large diffs are not rendered by default.

118 changes: 118 additions & 0 deletions src/engine/client/backend/opengl/backend_opengl3.h
@@ -0,0 +1,118 @@
// This file can be included several times.
#if(!defined(BACKEND_AS_OPENGL_ES) && !defined(ENGINE_CLIENT_BACKEND_OPENGL_BACKEND_OPENGL3_H)) || \
(defined(BACKEND_AS_OPENGL_ES) && !defined(ENGINE_CLIENT_BACKEND_OPENGL_BACKEND_OPENGL3_H_AS_ES))

#if !defined(BACKEND_AS_OPENGL_ES) && !defined(ENGINE_CLIENT_BACKEND_OPENGL_BACKEND_OPENGL3_H)
#define ENGINE_CLIENT_BACKEND_OPENGL_BACKEND_OPENGL3_H
#endif

#if defined(BACKEND_AS_OPENGL_ES) && !defined(ENGINE_CLIENT_BACKEND_OPENGL_BACKEND_OPENGL3_H_AS_ES)
#define ENGINE_CLIENT_BACKEND_OPENGL_BACKEND_OPENGL3_H_AS_ES
#endif

#include <engine/client/backend_sdl.h>

#include "backend_opengl.h"

#define MAX_STREAM_BUFFER_COUNT 30

// takes care of opengl 3.3+ related rendering
class CCommandProcessorFragment_OpenGL3_3 : public CCommandProcessorFragment_OpenGL3
{
protected:
bool m_UsePreinitializedVertexBuffer;

int m_MaxQuadsAtOnce;
static const int m_MaxQuadsPossible = 256;

CGLSLPrimitiveProgram *m_pPrimitiveProgram;
CGLSLPrimitiveProgram *m_pPrimitiveProgramTextured;
CGLSLTileProgram *m_pBorderTileProgram;
CGLSLTileProgram *m_pBorderTileProgramTextured;
CGLSLTileProgram *m_pBorderTileLineProgram;
CGLSLTileProgram *m_pBorderTileLineProgramTextured;
CGLSLQuadProgram *m_pQuadProgram;
CGLSLQuadProgram *m_pQuadProgramTextured;
CGLSLTextProgram *m_pTextProgram;
CGLSLPrimitiveExProgram *m_pPrimitiveExProgram;
CGLSLPrimitiveExProgram *m_pPrimitiveExProgramTextured;
CGLSLPrimitiveExProgram *m_pPrimitiveExProgramRotationless;
CGLSLPrimitiveExProgram *m_pPrimitiveExProgramTexturedRotationless;
CGLSLSpriteMultipleProgram *m_pSpriteProgramMultiple;

TWGLuint m_LastProgramID;

TWGLuint m_PrimitiveDrawVertexID[MAX_STREAM_BUFFER_COUNT];
TWGLuint m_PrimitiveDrawVertexIDTex3D;
TWGLuint m_PrimitiveDrawBufferID[MAX_STREAM_BUFFER_COUNT];
TWGLuint m_PrimitiveDrawBufferIDTex3D;

TWGLuint m_LastIndexBufferBound[MAX_STREAM_BUFFER_COUNT];

int m_LastStreamBuffer;

TWGLuint m_QuadDrawIndexBufferID;
unsigned int m_CurrentIndicesInBuffer;

void DestroyBufferContainer(int Index, bool DeleteBOs = true);

void AppendIndices(unsigned int NewIndicesCount);

struct SBufferContainer
{
SBufferContainer() :
m_VertArrayID(0), m_LastIndexBufferBound(0) {}
TWGLuint m_VertArrayID;
TWGLuint m_LastIndexBufferBound;
SBufferContainerInfo m_ContainerInfo;
};
std::vector<SBufferContainer> m_BufferContainers;

std::vector<TWGLuint> m_BufferObjectIndices;

CCommandBuffer::SColorf m_ClearColor;

void InitPrimExProgram(CGLSLPrimitiveExProgram *pProgram, class CGLSLCompiler *pCompiler, class IStorage *pStorage, bool Textured, bool Rotationless);

static int TexFormatToNewOpenGLFormat(int TexFormat);
bool IsNewApi() override { return true; }

void UseProgram(CGLSLTWProgram *pProgram);
void UploadStreamBufferData(unsigned int PrimitiveType, const void *pVertices, size_t VertSize, unsigned int PrimitiveCount, bool AsTex3D = false);
void RenderText(const CCommandBuffer::SState &State, int DrawNum, int TextTextureIndex, int TextOutlineTextureIndex, int TextureSize, const float *pTextColor, const float *pTextOutlineColor);

bool Cmd_Init(const SCommand_Init *pCommand) override;
void Cmd_Shutdown(const SCommand_Shutdown *pCommand) override;
void Cmd_Texture_Update(const CCommandBuffer::SCommand_Texture_Update *pCommand) override;
void Cmd_Texture_Destroy(const CCommandBuffer::SCommand_Texture_Destroy *pCommand) override;
void Cmd_Texture_Create(const CCommandBuffer::SCommand_Texture_Create *pCommand) override;
void Cmd_Clear(const CCommandBuffer::SCommand_Clear *pCommand) override;
void Cmd_Render(const CCommandBuffer::SCommand_Render *pCommand) override;
void Cmd_RenderTex3D(const CCommandBuffer::SCommand_RenderTex3D *pCommand) override;

void Cmd_CreateBufferObject(const CCommandBuffer::SCommand_CreateBufferObject *pCommand) override;
void Cmd_RecreateBufferObject(const CCommandBuffer::SCommand_RecreateBufferObject *pCommand) override;
void Cmd_UpdateBufferObject(const CCommandBuffer::SCommand_UpdateBufferObject *pCommand) override;
void Cmd_CopyBufferObject(const CCommandBuffer::SCommand_CopyBufferObject *pCommand) override;
void Cmd_DeleteBufferObject(const CCommandBuffer::SCommand_DeleteBufferObject *pCommand) override;

void Cmd_CreateBufferContainer(const CCommandBuffer::SCommand_CreateBufferContainer *pCommand) override;
void Cmd_UpdateBufferContainer(const CCommandBuffer::SCommand_UpdateBufferContainer *pCommand) override;
void Cmd_DeleteBufferContainer(const CCommandBuffer::SCommand_DeleteBufferContainer *pCommand) override;
void Cmd_IndicesRequiredNumNotify(const CCommandBuffer::SCommand_IndicesRequiredNumNotify *pCommand) override;

void Cmd_RenderTileLayer(const CCommandBuffer::SCommand_RenderTileLayer *pCommand) override;
void Cmd_RenderBorderTile(const CCommandBuffer::SCommand_RenderBorderTile *pCommand) override;
void Cmd_RenderBorderTileLine(const CCommandBuffer::SCommand_RenderBorderTileLine *pCommand) override;
void Cmd_RenderQuadLayer(const CCommandBuffer::SCommand_RenderQuadLayer *pCommand) override;
void Cmd_RenderText(const CCommandBuffer::SCommand_RenderText *pCommand) override;
void Cmd_RenderTextStream(const CCommandBuffer::SCommand_RenderTextStream *pCommand) override;
void Cmd_RenderQuadContainer(const CCommandBuffer::SCommand_RenderQuadContainer *pCommand) override;
void Cmd_RenderQuadContainerEx(const CCommandBuffer::SCommand_RenderQuadContainerEx *pCommand) override;
void Cmd_RenderQuadContainerAsSpriteMultiple(const CCommandBuffer::SCommand_RenderQuadContainerAsSpriteMultiple *pCommand) override;

public:
CCommandProcessorFragment_OpenGL3_3() = default;
};

#endif
159 changes: 159 additions & 0 deletions src/engine/client/backend/opengl/opengl_sl.cpp
@@ -0,0 +1,159 @@
#include "opengl_sl.h"
#include <engine/shared/linereader.h>
#include <engine/storage.h>
#include <stdio.h>
#include <string>
#include <vector>

#include <engine/client/backend_sdl.h>

#include <engine/client/backend/glsl_shader_compiler.h>

#ifndef BACKEND_AS_OPENGL_ES
#include <GL/glew.h>
#else
#include <GLES3/gl3.h>
#endif

bool CGLSL::LoadShader(CGLSLCompiler *pCompiler, IStorage *pStorage, const char *pFile, int Type)
{
if(m_IsLoaded)
return true;
IOHANDLE f = pStorage->OpenFile(pFile, IOFLAG_READ, IStorage::TYPE_ALL);

std::vector<std::string> Lines;
if(f)
{
EBackendType BackendType = pCompiler->m_IsOpenGLES ? BACKEND_TYPE_OPENGL_ES : BACKEND_TYPE_OPENGL;
bool IsNewOpenGL = (BackendType == BACKEND_TYPE_OPENGL ? (pCompiler->m_OpenGLVersionMajor >= 4 || (pCompiler->m_OpenGLVersionMajor == 3 && pCompiler->m_OpenGLVersionMinor == 3)) : pCompiler->m_OpenGLVersionMajor >= 3);
std::string GLShaderStringPostfix = std::string(" core\r\n");
if(BackendType == BACKEND_TYPE_OPENGL_ES)
GLShaderStringPostfix = std::string(" es\r\n");
//add compiler specific values
if(IsNewOpenGL)
Lines.push_back(std::string("#version ") + std::string(std::to_string(pCompiler->m_OpenGLVersionMajor)) + std::string(std::to_string(pCompiler->m_OpenGLVersionMinor)) + std::string(std::to_string(pCompiler->m_OpenGLVersionPatch)) + GLShaderStringPostfix);
else
{
if(pCompiler->m_OpenGLVersionMajor == 3)
{
if(pCompiler->m_OpenGLVersionMinor == 0)
Lines.push_back(std::string("#version 130 \r\n"));
if(pCompiler->m_OpenGLVersionMinor == 1)
Lines.push_back(std::string("#version 140 \r\n"));
if(pCompiler->m_OpenGLVersionMinor == 2)
Lines.push_back(std::string("#version 150 \r\n"));
}
else if(pCompiler->m_OpenGLVersionMajor == 2)
{
if(pCompiler->m_OpenGLVersionMinor == 0)
Lines.push_back(std::string("#version 110 \r\n"));
if(pCompiler->m_OpenGLVersionMinor == 1)
Lines.push_back(std::string("#version 120 \r\n"));
}
}

if(BackendType == BACKEND_TYPE_OPENGL_ES)
{
if(Type == GL_FRAGMENT_SHADER)
{
Lines.push_back("precision highp float; \r\n");
Lines.push_back("precision highp sampler2D; \r\n");
Lines.push_back("precision highp sampler3D; \r\n");
Lines.push_back("precision highp samplerCube; \r\n");
Lines.push_back("precision highp samplerCubeShadow; \r\n");
Lines.push_back("precision highp sampler2DShadow; \r\n");
Lines.push_back("precision highp sampler2DArray; \r\n");
Lines.push_back("precision highp sampler2DArrayShadow; \r\n");
}
}

for(CGLSLCompiler::SGLSLCompilerDefine &Define : pCompiler->m_Defines)
{
Lines.push_back(std::string("#define ") + Define.m_DefineName + std::string(" ") + Define.m_DefineValue + std::string("\r\n"));
}

if(Type == GL_FRAGMENT_SHADER && !IsNewOpenGL && pCompiler->m_OpenGLVersionMajor <= 3 && pCompiler->m_HasTextureArray)
{
Lines.push_back(std::string("#extension GL_EXT_texture_array : enable\r\n"));
}

CLineReader LineReader;
LineReader.Init(f);
char *ReadLine = NULL;
while((ReadLine = LineReader.Get()))
{
std::string Line;
pCompiler->ParseLine(Line, ReadLine, Type == GL_FRAGMENT_SHADER ? GLSL_SHADER_COMPILER_TYPE_FRAGMENT : GLSL_SHADER_COMPILER_TYPE_VERTEX);
Line.append("\r\n");
Lines.push_back(Line);
}
io_close(f);

const char **ShaderCode = new const char *[Lines.size()];

for(size_t i = 0; i < Lines.size(); ++i)
{
ShaderCode[i] = Lines[i].c_str();
}

TWGLuint shader = glCreateShader(Type);

glShaderSource(shader, Lines.size(), ShaderCode, NULL);
glCompileShader(shader);

delete[] ShaderCode;

int CompilationStatus;
glGetShaderiv(shader, GL_COMPILE_STATUS, &CompilationStatus);

if(CompilationStatus == GL_FALSE)
{
char buff[3000];

TWGLint maxLength = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &maxLength);

glGetShaderInfoLog(shader, maxLength, &maxLength, buff);

dbg_msg("glsl", "%s: %s", pFile, buff);
glDeleteShader(shader);
return false;
}
m_Type = Type;
m_IsLoaded = true;

m_ShaderID = shader;

return true;
}
else
return false;
}

void CGLSL::DeleteShader()
{
if(!IsLoaded())
return;
m_IsLoaded = false;
glDeleteShader(m_ShaderID);
}

bool CGLSL::IsLoaded()
{
return m_IsLoaded;
}

TWGLuint CGLSL::GetShaderID()
{
return m_ShaderID;
}

CGLSL::CGLSL()
{
m_IsLoaded = false;
}

CGLSL::~CGLSL()
{
DeleteShader();
}
40 changes: 40 additions & 0 deletions src/engine/client/backend/opengl/opengl_sl.h
@@ -0,0 +1,40 @@
// This file can be included several times.
#if(!defined(BACKEND_AS_OPENGL_ES) && !defined(ENGINE_CLIENT_BACKEND_OPENGL_OPENGL_SL_H)) || \
(defined(BACKEND_AS_OPENGL_ES) && !defined(ENGINE_CLIENT_BACKEND_OPENGL_OPENGL_SL_H_AS_ES))

#if !defined(BACKEND_AS_OPENGL_ES) && !defined(ENGINE_CLIENT_BACKEND_OPENGL_OPENGL_SL_H)
#define ENGINE_CLIENT_BACKEND_OPENGL_OPENGL_SL_H
#endif

#if defined(BACKEND_AS_OPENGL_ES) && !defined(ENGINE_CLIENT_BACKEND_OPENGL_OPENGL_SL_H_AS_ES)
#define ENGINE_CLIENT_BACKEND_OPENGL_OPENGL_SL_H_AS_ES
#endif

#include <base/detect.h>

#include <engine/client/graphics_defines.h>

#include <string>
#include <vector>

class CGLSLCompiler;

class CGLSL
{
public:
bool LoadShader(CGLSLCompiler *pCompiler, class IStorage *pStorage, const char *pFile, int Type);
void DeleteShader();

bool IsLoaded();
TWGLuint GetShaderID();

CGLSL();
virtual ~CGLSL();

private:
TWGLuint m_ShaderID;
int m_Type;
bool m_IsLoaded;
};

#endif
Expand Up @@ -2,6 +2,12 @@
#include "opengl_sl.h"
#include <base/system.h>

#ifndef BACKEND_AS_OPENGL_ES
#include <GL/glew.h>
#else
#include <GLES3/gl3.h>
#endif

void CGLSLProgram::CreateProgram()
{
m_ProgramID = glCreateProgram();
Expand Down Expand Up @@ -33,7 +39,7 @@ void CGLSLProgram::DetachShader(CGLSL *pShader)
}
}

void CGLSLProgram::DetachShaderByID(GLuint ShaderID)
void CGLSLProgram::DetachShaderByID(TWGLuint ShaderID)
{
glDetachShader(m_ProgramID, ShaderID);
}
Expand All @@ -60,7 +66,7 @@ void CGLSLProgram::LinkProgram()

void CGLSLProgram::DetachAllShaders()
{
GLuint aShaders[100];
TWGLuint aShaders[100];
GLsizei ReturnedCount = 0;
while(1)
{
Expand Down Expand Up @@ -99,11 +105,6 @@ void CGLSLProgram::SetUniform(int Loc, const int Value)
glUniform1i(Loc, Value);
}

void CGLSLProgram::SetUniform(int Loc, const unsigned int Value)
{
glUniform1ui(Loc, Value);
}

void CGLSLProgram::SetUniform(int Loc, const float Value)
{
glUniform1f(Loc, Value);
Expand All @@ -125,7 +126,7 @@ void CGLSLProgram::UseProgram()
glUseProgram(m_ProgramID);
}

GLuint CGLSLProgram::GetProgramID()
TWGLuint CGLSLProgram::GetProgramID()
{
return m_ProgramID;
}
Expand Down
@@ -1,7 +1,18 @@
#ifndef ENGINE_CLIENT_OPENGL_SL_PROGRAM_H
#define ENGINE_CLIENT_OPENGL_SL_PROGRAM_H
// This file can be included several times.
#if(!defined(BACKEND_AS_OPENGL_ES) && !defined(ENGINE_CLIENT_BACKEND_OPENGL_OPENGL_SL_PROGRAM_H)) || \
(defined(BACKEND_AS_OPENGL_ES) && !defined(ENGINE_CLIENT_BACKEND_OPENGL_OPENGL_SL_PROGRAM_H_AS_ES))

#include <GL/glew.h>
#if !defined(BACKEND_AS_OPENGL_ES) && !defined(ENGINE_CLIENT_BACKEND_OPENGL_OPENGL_SL_PROGRAM_H)
#define ENGINE_CLIENT_BACKEND_OPENGL_OPENGL_SL_PROGRAM_H
#endif

#if defined(BACKEND_AS_OPENGL_ES) && !defined(ENGINE_CLIENT_BACKEND_OPENGL_OPENGL_SL_PROGRAM_H_AS_ES)
#define ENGINE_CLIENT_BACKEND_OPENGL_OPENGL_SL_PROGRAM_H_AS_ES
#endif

#include <base/detect.h>

#include <engine/client/graphics_defines.h>

class CGLSL;

Expand All @@ -15,17 +26,16 @@ class CGLSLProgram

void LinkProgram();
void UseProgram();
GLuint GetProgramID();
TWGLuint GetProgramID();

void DetachShader(CGLSL *pShader);
void DetachShaderByID(GLuint ShaderID);
void DetachShaderByID(TWGLuint ShaderID);
void DetachAllShaders();

//Support various types
void SetUniformVec2(int Loc, int Count, const float *pValue);
void SetUniformVec4(int Loc, int Count, const float *pValue);
void SetUniform(int Loc, const int Value);
void SetUniform(int Loc, const unsigned int Value);
void SetUniform(int Loc, const bool Value);
void SetUniform(int Loc, const float Value);
void SetUniform(int Loc, int Count, const float *pValues);
Expand All @@ -37,7 +47,7 @@ class CGLSLProgram
virtual ~CGLSLProgram();

protected:
GLuint m_ProgramID;
TWGLuint m_ProgramID;
bool m_IsLinked;
};

Expand Down Expand Up @@ -148,4 +158,4 @@ class CGLSLTileProgram : public CGLSLTWProgram
int m_LocJumpIndex;
};

#endif // ENGINE_CLIENT_OPENGL_SL_PROGRAM_H
#endif
17 changes: 17 additions & 0 deletions src/engine/client/backend/opengles/backend_opengles.cpp
@@ -0,0 +1,17 @@
#include <base/detect.h>

#if defined(CONF_BACKEND_OPENGL_ES) || defined(CONF_BACKEND_OPENGL_ES3)

#define GLES_CLASS_DEFINES_DO_DEFINE
#include "gles_class_defines.h"
#undef GLES_CLASS_DEFINES_DO_DEFINE

#define BACKEND_AS_OPENGL_ES 1

#include <engine/client/backend/opengl/backend_opengl.cpp>

#undef BACKEND_AS_OPENGL_ES

#include "gles_class_defines.h"

#endif
23 changes: 23 additions & 0 deletions src/engine/client/backend/opengles/backend_opengles.h
@@ -0,0 +1,23 @@
#ifndef ENGINE_CLIENT_BACKEND_OPENGLES_BACKEND_OPENGLES_H
#define ENGINE_CLIENT_BACKEND_OPENGLES_BACKEND_OPENGLES_H

#include <base/detect.h>

#if defined(CONF_BACKEND_OPENGL_ES) || defined(CONF_BACKEND_OPENGL_ES3)
#include <engine/client/backend_sdl.h>

#define GLES_CLASS_DEFINES_DO_DEFINE
#include "gles_class_defines.h"
#undef GLES_CLASS_DEFINES_DO_DEFINE

#define BACKEND_AS_OPENGL_ES 1

#include <engine/client/backend/opengl/backend_opengl.h>

#undef BACKEND_AS_OPENGL_ES

#include "gles_class_defines.h"

#endif

#endif
17 changes: 17 additions & 0 deletions src/engine/client/backend/opengles/backend_opengles3.cpp
@@ -0,0 +1,17 @@
#include <base/detect.h>

#if defined(CONF_BACKEND_OPENGL_ES) || defined(CONF_BACKEND_OPENGL_ES3)

#define GLES_CLASS_DEFINES_DO_DEFINE
#include "gles_class_defines.h"
#undef GLES_CLASS_DEFINES_DO_DEFINE

#define BACKEND_AS_OPENGL_ES 1

#include <engine/client/backend/opengl/backend_opengl3.cpp>

#undef BACKEND_AS_OPENGL_ES

#include "gles_class_defines.h"

#endif
23 changes: 23 additions & 0 deletions src/engine/client/backend/opengles/backend_opengles3.h
@@ -0,0 +1,23 @@
#ifndef ENGINE_CLIENT_BACKEND_OPENGLES_BACKEND_OPENGLES3_H
#define ENGINE_CLIENT_BACKEND_OPENGLES_BACKEND_OPENGLES3_H

#include <base/detect.h>

#if defined(CONF_BACKEND_OPENGL_ES) || defined(CONF_BACKEND_OPENGL_ES3)
#include <engine/client/backend_sdl.h>

#define GLES_CLASS_DEFINES_DO_DEFINE
#include "gles_class_defines.h"
#undef GLES_CLASS_DEFINES_DO_DEFINE

#define BACKEND_AS_OPENGL_ES 1

#include <engine/client/backend/opengl/backend_opengl3.h>

#undef BACKEND_AS_OPENGL_ES

#include "gles_class_defines.h"

#endif

#endif
36 changes: 36 additions & 0 deletions src/engine/client/backend/opengles/gles_class_defines.h
@@ -0,0 +1,36 @@
#ifndef ENGINE_CLIENT_BACKEND_OPENGLES_GLES_CLASS_DEFINES_H
#define ENGINE_CLIENT_BACKEND_OPENGLES_GLES_CLASS_DEFINES_H
#undef ENGINE_CLIENT_BACKEND_OPENGLES_GLES_CLASS_DEFINES_H
#endif

#ifdef GLES_CLASS_DEFINES_DO_DEFINE
#define CCommandProcessorFragment_OpenGL3_3 CCommandProcessorFragment_OpenGLES3
#define CCommandProcessorFragment_OpenGL3 CCommandProcessorFragment_OpenGLES3Wrapper
#define CCommandProcessorFragment_OpenGL2 CCommandProcessorFragment_OpenGLES2
#define CCommandProcessorFragment_OpenGL CCommandProcessorFragment_OpenGLES

#define CGLSL CGLSL_ES
#define CGLSLProgram CGLSL_ESProgram
#define CGLSLTWProgram CGLSL_ESTWProgram
#define CGLSLTextProgram CGLSL_ESTextProgram
#define CGLSLPrimitiveProgram CGLSL_ESPrimitiveProgram
#define CGLSLPrimitiveExProgram CGLSL_ESPrimitiveExProgram
#define CGLSLSpriteMultipleProgram CGLSL_ESSpriteMultipleProgram
#define CGLSLQuadProgram CGLSL_ESQuadProgram
#define CGLSLTileProgram CGLSL_ESTileProgram
#else
#undef CCommandProcessorFragment_OpenGL3_3
#undef CCommandProcessorFragment_OpenGL3
#undef CCommandProcessorFragment_OpenGL2
#undef CCommandProcessorFragment_OpenGL

#undef CGLSL
#undef CGLSLProgram
#undef CGLSLTWProgram
#undef CGLSLTextProgram
#undef CGLSLPrimitiveProgram
#undef CGLSLPrimitiveExProgram
#undef CGLSLSpriteMultipleProgram
#undef CGLSLQuadProgram
#undef CGLSLTileProgram
#endif
16 changes: 16 additions & 0 deletions src/engine/client/backend/opengles/opengles_sl.cpp
@@ -0,0 +1,16 @@
#include <base/detect.h>

#if defined(CONF_BACKEND_OPENGL_ES) || defined(CONF_BACKEND_OPENGL_ES3)
#define GLES_CLASS_DEFINES_DO_DEFINE
#include "gles_class_defines.h"
#undef GLES_CLASS_DEFINES_DO_DEFINE

#define BACKEND_AS_OPENGL_ES 1

#include <engine/client/backend/opengl/opengl_sl.cpp>

#undef BACKEND_AS_OPENGL_ES

#include "gles_class_defines.h"

#endif
16 changes: 16 additions & 0 deletions src/engine/client/backend/opengles/opengles_sl_program.cpp
@@ -0,0 +1,16 @@
#include <base/detect.h>

#if defined(CONF_BACKEND_OPENGL_ES) || defined(CONF_BACKEND_OPENGL_ES3)
#define GLES_CLASS_DEFINES_DO_DEFINE
#include "gles_class_defines.h"
#undef GLES_CLASS_DEFINES_DO_DEFINE

#define BACKEND_AS_OPENGL_ES 1

#include <engine/client/backend/opengl/opengl_sl_program.cpp>

#undef BACKEND_AS_OPENGL_ES

#include "gles_class_defines.h"

#endif
4,756 changes: 530 additions & 4,226 deletions src/engine/client/backend_sdl.cpp

Large diffs are not rendered by default.

396 changes: 73 additions & 323 deletions src/engine/client/backend_sdl.h

Large diffs are not rendered by default.

47 changes: 40 additions & 7 deletions src/engine/client/blocklist_driver.cpp
Expand Up @@ -21,24 +21,37 @@ struct SVersion
}
};

enum EBackendDriverBlockListType
{
BACKEND_DRIVER_BLOCKLIST_TYPE_VERSION = 0,
BACKEND_DRIVER_BLOCKLIST_TYPE_VENDOR,
};

/* TODO: generalize it more for other drivers / vendors */
struct SBackEndDriverBlockList
{
EBackendDriverBlockListType m_BlockListType;

SVersion m_VersionMin;
SVersion m_VersionMax;

const char *m_pVendorName;

// the OpenGL version, that is supported
int m_AllowedMajor;
int m_AllowedMinor;
int m_AllowedPatch;

const char *m_pReason;

bool m_DisplayReason;
const char *m_pOSName;
};

static SBackEndDriverBlockList gs_aBlockList[] = {
{{26, 20, 100, 7800}, {27, 20, 100, 8853}, 2, 0, 0, "This Intel driver version can cause crashes, please update it to a newer version."}};
{BACKEND_DRIVER_BLOCKLIST_TYPE_VENDOR, {26, 20, 100, 7800}, {27, 20, 100, 8853}, "Intel", 2, 0, 0, "This Intel driver version can cause crashes, please update it to a newer version.", false, "windows"}};

const char *ParseBlocklistDriverVersions(const char *pVendorStr, const char *pVersionStr, int &BlocklistMajor, int &BlocklistMinor, int &BlocklistPatch)
const char *ParseBlocklistDriverVersions(const char *pVendorStr, const char *pVersionStr, int &BlocklistMajor, int &BlocklistMinor, int &BlocklistPatch, bool &RequiresWarning)
{
if(str_find_nocase(pVendorStr, "Intel") == NULL)
return NULL;
Expand All @@ -64,12 +77,32 @@ const char *ParseBlocklistDriverVersions(const char *pVendorStr, const char *pVe

for(const auto &BlockListItem : gs_aBlockList)
{
if(BlockListItem.m_VersionMin <= Version && Version <= BlockListItem.m_VersionMax)
if(str_comp(BlockListItem.m_pOSName, CONF_FAMILY_STRING) == 0)
{
BlocklistMajor = BlockListItem.m_AllowedMajor;
BlocklistMinor = BlockListItem.m_AllowedMinor;
BlocklistPatch = BlockListItem.m_AllowedPatch;
return BlockListItem.m_pReason;
bool DriverBlocked = false;
if(BlockListItem.m_BlockListType == BACKEND_DRIVER_BLOCKLIST_TYPE_VENDOR)
{
if(str_find_nocase(pVendorStr, BlockListItem.m_pVendorName) != NULL)
{
DriverBlocked = true;
}
}
else if(BlockListItem.m_BlockListType == BACKEND_DRIVER_BLOCKLIST_TYPE_VERSION)
{
if(BlockListItem.m_VersionMin <= Version && Version <= BlockListItem.m_VersionMax)
{
DriverBlocked = true;
}
}

if(DriverBlocked)
{
RequiresWarning = BlockListItem.m_DisplayReason;
BlocklistMajor = BlockListItem.m_AllowedMajor;
BlocklistMinor = BlockListItem.m_AllowedMinor;
BlocklistPatch = BlockListItem.m_AllowedPatch;
return BlockListItem.m_pReason;
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/engine/client/blocklist_driver.h
@@ -1,6 +1,6 @@
#ifndef ENGINE_CLIENT_BLOCKLIST_DRIVER_H
#define ENGINE_CLIENT_BLOCKLIST_DRIVER_H

const char *ParseBlocklistDriverVersions(const char *pVendorStr, const char *pVersionStr, int &BlocklistMajor, int &BlocklistMinor, int &BlocklistPatch);
const char *ParseBlocklistDriverVersions(const char *pVendorStr, const char *pVersionStr, int &BlocklistMajor, int &BlocklistMinor, int &BlocklistPatch, bool &RequiresWarning);

#endif // ENGINE_CLIENT_BLOCKLIST_DRIVER_H
266 changes: 125 additions & 141 deletions src/engine/client/client.cpp

Large diffs are not rendered by default.

23 changes: 13 additions & 10 deletions src/engine/client/client.h
Expand Up @@ -80,6 +80,7 @@ class CServerCapabilities
public:
bool m_ChatTimeoutCode;
bool m_AnyPlayerFlag;
bool m_PingEx;
};

class CClient : public IClient, public CDemoPlayer::IListener
Expand All @@ -99,7 +100,6 @@ class CClient : public IClient, public CDemoPlayer::IListener
IUpdater *m_pUpdater;
IDiscord *m_pDiscord;
ISteam *m_pSteam;
IEngineMasterServer *m_pMasterServer;

enum
{
Expand Down Expand Up @@ -243,6 +243,13 @@ class CClient : public IClient, public CDemoPlayer::IListener
class CServerInfo m_CurrentServerInfo;
int64 m_CurrentServerInfoRequestTime; // >= 0 should request, == -1 got info

int m_CurrentServerPingInfoType;
int m_CurrentServerPingBasicToken;
int m_CurrentServerPingToken;
CUuid m_CurrentServerPingUuid;
int64 m_CurrentServerCurrentPingTime; // >= 0 request running
int64 m_CurrentServerNextPingTime; // >= 0 should request

// version info
struct CVersionInfo
{
Expand Down Expand Up @@ -276,7 +283,6 @@ class CClient : public IClient, public CDemoPlayer::IListener
IEngineInput *Input() { return m_pInput; }
IEngineSound *Sound() { return m_pSound; }
IGameClient *GameClient() { return m_pGameClient; }
IEngineMasterServer *MasterServer() { return m_pMasterServer; }
IConfigManager *ConfigManager() { return m_pConfigManager; }
CConfig *Config() { return m_pConfig; }
IStorage *Storage() { return m_pStorage; }
Expand Down Expand Up @@ -361,8 +367,6 @@ class CClient : public IClient, public CDemoPlayer::IListener
const char *LoadMap(const char *pName, const char *pFilename, SHA256_DIGEST *pWantedSha256, unsigned WantedCrc);
const char *LoadMapSearch(const char *pMapName, SHA256_DIGEST *pWantedSha256, int WantedCrc);

static bool PlayerScoreNameLess(const CServerInfo::CClient &p0, const CServerInfo::CClient &p1);

void ProcessConnlessPacket(CNetChunk *pPacket);
void ProcessServerInfo(int Type, NETADDR *pFrom, const void *pData, int DataSize);
void ProcessServerPacket(CNetChunk *pPacket);
Expand Down Expand Up @@ -466,12 +470,11 @@ class CClient : public IClient, public CDemoPlayer::IListener
void HandleMapPath(const char *pPath);

// gfx
void SwitchWindowScreen(int Index);
void ToggleFullscreen();
void ToggleWindowBordered();
void ToggleWindowVSync();
void LoadFont();
void Notify(const char *pTitle, const char *pMessage);
virtual void SwitchWindowScreen(int Index);
virtual void SetWindowParams(int FullscreenMode, bool IsBorderless);
virtual void ToggleWindowVSync();
virtual void LoadFont();
virtual void Notify(const char *pTitle, const char *pMessage);
void BenchmarkQuit(int Seconds, const char *pFilename);

// DDRace
Expand Down
12 changes: 12 additions & 0 deletions src/engine/client/graphics_defines.h
@@ -0,0 +1,12 @@
#ifndef ENGINE_CLIENT_GRAPHICS_DEFINES_H
#define ENGINE_CLIENT_GRAPHICS_DEFINES_H

#include <stddef.h>
#include <stdint.h>

typedef uint32_t TWGLuint;
typedef int32_t TWGLint;
typedef uint32_t TWGLenum;
typedef uint8_t TWGLubyte;

#endif
615 changes: 273 additions & 342 deletions src/engine/client/graphics_threaded.cpp

Large diffs are not rendered by default.

98 changes: 67 additions & 31 deletions src/engine/client/graphics_threaded.h
Expand Up @@ -119,12 +119,13 @@ class CCommandBuffer

// swap
CMD_SWAP,
CMD_FINISH,

// misc
CMD_VSYNC,
CMD_SCREENSHOT,
CMD_VIDEOMODES,
CMD_RESIZE,
CMD_UPDATE_VIEWPORT,

};

Expand All @@ -136,8 +137,6 @@ class CCommandBuffer
TEXFORMAT_ALPHA,

TEXFLAG_NOMIPMAPS = 1,
TEXFLAG_COMPRESSED = 2,
TEXFLAG_QUALITY = 4,
TEXFLAG_TO_3D_TEXTURE = (1 << 3),
TEXFLAG_TO_2D_ARRAY_TEXTURE = (1 << 4),
TEXFLAG_TO_3D_TEXTURE_SINGLE_LAYER = (1 << 5),
Expand Down Expand Up @@ -498,15 +497,22 @@ class CCommandBuffer
CVideoMode *m_pModes; // processor will fill this in
int m_MaxModes; // maximum of modes the processor can write to the m_pModes
int *m_pNumModes; // processor will write to this pointer
int m_HiDPIScale;
int m_MaxWindowWidth;
int m_MaxWindowHeight;
int m_Screen;
};

struct SCommand_Swap : public SCommand
{
SCommand_Swap() :
SCommand(CMD_SWAP) {}
};

int m_Finish;
struct SCommand_Finish : public SCommand
{
SCommand_Finish() :
SCommand(CMD_FINISH) {}
};

struct SCommand_VSync : public SCommand
Expand All @@ -518,11 +524,13 @@ class CCommandBuffer
bool *m_pRetOk;
};

struct SCommand_Resize : public SCommand
struct SCommand_Update_Viewport : public SCommand
{
SCommand_Resize() :
SCommand(CMD_RESIZE) {}
SCommand_Update_Viewport() :
SCommand(CMD_UPDATE_VIEWPORT) {}

int m_X;
int m_Y;
int m_Width;
int m_Height;
};
Expand Down Expand Up @@ -581,7 +589,7 @@ class CCommandBuffer
}

template<class T>
bool AddCommand(const T &Command)
bool AddCommandUnsafe(const T &Command)
{
// make sure that we don't do something stupid like ->AddCommand(&Cmd);
(void)static_cast<const SCommand *>(&Command);
Expand Down Expand Up @@ -640,6 +648,7 @@ class IGraphicsBackend
INITFLAG_RESIZABLE = 1 << 2,
INITFLAG_BORDERLESS = 1 << 3,
INITFLAG_HIGHDPI = 1 << 4,
INITFLAG_DESKTOP_FULLSCREEN = 1 << 5,
};

virtual ~IGraphicsBackend() {}
Expand All @@ -653,8 +662,7 @@ class IGraphicsBackend

virtual void Minimize() = 0;
virtual void Maximize() = 0;
virtual bool Fullscreen(bool State) = 0;
virtual void SetWindowBordered(bool State) = 0;
virtual void SetWindowParams(int FullscreenMode, bool IsBorderless) = 0;
virtual bool SetWindowScreen(int Index) = 0;
virtual int GetWindowScreen() = 0;
virtual int WindowActive() = 0;
Expand All @@ -668,13 +676,20 @@ class IGraphicsBackend
virtual bool IsIdle() const = 0;
virtual void WaitForIdle() = 0;

virtual void GetDriverVersion(EGraphicsDriverAgeType DriverAgeType, int &Major, int &Minor, int &Patch) {}
// checks if the current values of the config are a graphics modern API
virtual bool IsConfigModernAPI() { return false; }
virtual bool IsNewOpenGL() { return false; }
virtual bool HasTileBuffering() { return false; }
virtual bool HasQuadBuffering() { return false; }
virtual bool HasTextBuffering() { return false; }
virtual bool HasQuadContainerBuffering() { return false; }
virtual bool Has2DTextureArrays() { return false; }
virtual const char *GetErrorString() { return NULL; }

virtual const char *GetVendorString() = 0;
virtual const char *GetVersionString() = 0;
virtual const char *GetRendererString() = 0;
};

class CGraphics_Threaded : public IEngineGraphics
Expand Down Expand Up @@ -803,6 +818,26 @@ class CGraphics_Threaded : public IEngineGraphics
}
}

template<typename TName, typename TFunc>
bool AddCmd(TName &Cmd, TFunc &&FailFunc, const char *pFailStr)
{
if(!m_pCommandBuffer->AddCommandUnsafe(Cmd))
{
// kick command buffer and try again
KickCommandBuffer();

if(!FailFunc())
return false;

if(!m_pCommandBuffer->AddCommandUnsafe(Cmd))
{
dbg_msg("graphics", "%s", pFailStr);
return false;
}
}
return true;
}

void KickCommandBuffer();

void AddBackEndWarningIfExists();
Expand Down Expand Up @@ -1065,24 +1100,20 @@ class CGraphics_Threaded : public IEngineGraphics
Command.m_PrimType = PrimType;
Command.m_PrimCount = PrimCount;

// check if we have enough free memory in the commandbuffer
if(!m_pCommandBuffer->AddCommand(Command))
if(
!AddCmd(
Command, [&] {
Command.m_pVertices = (decltype(Command.m_pVertices))m_pCommandBuffer->AllocData(VertSize * NumVerts);
if(Command.m_pVertices == NULL)
{
dbg_msg("graphics", "failed to allocate data for vertices");
return false;
}
return true;
},
"failed to allocate memory for render command"))
{
// kick command buffer and try again
KickCommandBuffer();

Command.m_pVertices = (decltype(Command.m_pVertices))m_pCommandBuffer->AllocData(VertSize * NumVerts);
if(Command.m_pVertices == NULL)
{
dbg_msg("graphics", "failed to allocate data for vertices");
return;
}

if(!m_pCommandBuffer->AddCommand(Command))
{
dbg_msg("graphics", "failed to allocate memory for render command");
return;
}
return;
}
}

Expand Down Expand Up @@ -1112,8 +1143,7 @@ class CGraphics_Threaded : public IEngineGraphics
int GetNumScreens() const override;
void Minimize() override;
void Maximize() override;
bool Fullscreen(bool State) override;
void SetWindowBordered(bool State) override;
void SetWindowParams(int FullscreenMode, bool IsBorderless) override;
bool SetWindowScreen(int Index) override;
void Resize(int w, int h, bool SetWindowSize = false) override;
void AddWindowResizeListener(WINDOW_RESIZE_FUNC pFunc, void *pUser) override;
Expand All @@ -1135,8 +1165,8 @@ class CGraphics_Threaded : public IEngineGraphics

int GetVideoModes(CVideoMode *pModes, int MaxModes, int Screen) override;

virtual int GetDesktopScreenWidth() const { return m_DesktopScreenWidth; }
virtual int GetDesktopScreenHeight() const { return m_DesktopScreenHeight; }
virtual int GetDesktopScreenWidth() const { return g_Config.m_GfxScreenWidth; }
virtual int GetDesktopScreenHeight() const { return g_Config.m_GfxScreenHeight; }

// synchronization
void InsertSignal(CSemaphore *pSemaphore) override;
Expand All @@ -1145,11 +1175,17 @@ class CGraphics_Threaded : public IEngineGraphics

SWarning *GetCurWarning() override;

void GetDriverVersion(EGraphicsDriverAgeType DriverAgeType, int &Major, int &Minor, int &Patch) override { m_pBackend->GetDriverVersion(DriverAgeType, Major, Minor, Patch); }
bool IsConfigModernAPI() override { return m_pBackend->IsConfigModernAPI(); }
bool IsTileBufferingEnabled() override { return m_OpenGLTileBufferingEnabled; }
bool IsQuadBufferingEnabled() override { return m_OpenGLQuadBufferingEnabled; }
bool IsTextBufferingEnabled() override { return m_OpenGLTextBufferingEnabled; }
bool IsQuadContainerBufferingEnabled() override { return m_OpenGLQuadContainerBufferingEnabled; }
bool HasTextureArrays() override { return m_OpenGLHasTextureArrays; }

const char *GetVendorString() override;
const char *GetVersionString() override;
const char *GetRendererString() override;
};

extern IGraphicsBackend *CreateGraphicsBackend();
Expand Down
20 changes: 18 additions & 2 deletions src/engine/client/http.cpp
Expand Up @@ -186,8 +186,24 @@ int CRequest::ProgressCallback(void *pUser, double DlTotal, double DlCurr, doubl
return pTask->m_Abort ? -1 : 0;
}

CGet::CGet(const char *pUrl, CTimeout Timeout) :
CRequest(pUrl, Timeout),
CHead::CHead(const char *pUrl, CTimeout Timeout, bool LogProgress) :
CRequest(pUrl, Timeout, LogProgress)
{
}

CHead::~CHead()
{
}

bool CHead::AfterInit(void *pCurl)
{
CURL *pHandle = pCurl;
curl_easy_setopt(pHandle, CURLOPT_NOBODY, 1L);
return true;
}

CGet::CGet(const char *pUrl, CTimeout Timeout, bool LogProgress) :
CRequest(pUrl, Timeout, LogProgress),
m_BufferSize(0),
m_BufferLength(0),
m_pBuffer(NULL)
Expand Down
12 changes: 11 additions & 1 deletion src/engine/client/http.h
Expand Up @@ -66,6 +66,16 @@ class CRequest : public IJob
void Abort() { m_Abort = true; }
};

class CHead : public CRequest
{
virtual size_t OnData(char *pData, size_t DataSize) { return DataSize; }
virtual bool AfterInit(void *pCurl);

public:
CHead(const char *pUrl, CTimeout Timeout, bool LogProgress = true);
~CHead();
};

class CGet : public CRequest
{
virtual size_t OnData(char *pData, size_t DataSize);
Expand All @@ -75,7 +85,7 @@ class CGet : public CRequest
unsigned char *m_pBuffer;

public:
CGet(const char *pUrl, CTimeout Timeout);
CGet(const char *pUrl, CTimeout Timeout, bool LogProgress = true);
~CGet();

size_t ResultSize() const
Expand Down
4 changes: 2 additions & 2 deletions src/engine/client/input.cpp
Expand Up @@ -89,8 +89,6 @@ void CInput::MouseModeRelative()
m_InputGrabbed = 1;
SDL_SetRelativeMouseMode(SDL_TRUE);
Graphics()->SetWindowGrab(true);
// We should do this call to reset relative mouse position after alt+tab
SDL_GetRelativeMouseState(0x0, 0x0);
}

int CInput::MouseDoubleClick()
Expand Down Expand Up @@ -336,6 +334,8 @@ int CInput::Update()
MouseModeRelative();
m_MouseFocus = true;
IgnoreKeys = true;
// We should do this call to reset relative mouse position after alt+tab
SDL_GetRelativeMouseState(0x0, 0x0);
break;
case SDL_WINDOWEVENT_FOCUS_LOST:
m_MouseFocus = false;
Expand Down