1#include "backend_opengl3.h"
2
3#include <base/detect.h>
4#include <base/log.h>
5
6#if defined(BACKEND_AS_OPENGL_ES) || !defined(CONF_BACKEND_OPENGL_ES)
7
8#ifndef BACKEND_AS_OPENGL_ES
9#include <GL/glew.h>
10#else
11#include <GLES3/gl3.h>
12#endif
13
14#include <engine/client/backend/glsl_shader_compiler.h>
15#include <engine/client/backend/opengl/opengl_sl.h>
16#include <engine/client/backend/opengl/opengl_sl_program.h>
17#include <engine/client/backend_sdl.h>
18#include <engine/gfx/image_manipulation.h>
19
20#if defined(CONF_PLATFORM_EMSCRIPTEN)
21// WebGL2 defines the type of a buffer at the first bind to a buffer target
22// this is different to GLES 3 (https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.1)
23static constexpr GLenum BUFFER_INIT_INDEX_TARGET = GL_ELEMENT_ARRAY_BUFFER;
24static constexpr GLenum BUFFER_INIT_VERTEX_TARGET = GL_ARRAY_BUFFER;
25#else
26static constexpr GLenum BUFFER_INIT_INDEX_TARGET = GL_COPY_WRITE_BUFFER;
27static constexpr GLenum BUFFER_INIT_VERTEX_TARGET = GL_COPY_WRITE_BUFFER;
28#endif
29
30// ------------ CCommandProcessorFragment_OpenGL3_3
31void CCommandProcessorFragment_OpenGL3_3::UseProgram(CGLSLTWProgram *pProgram)
32{
33 if(m_LastProgramId != pProgram->GetProgramId())
34 {
35 pProgram->UseProgram();
36 m_LastProgramId = pProgram->GetProgramId();
37 }
38}
39
40void CCommandProcessorFragment_OpenGL3_3::InitPrimExProgram(CGLSLPrimitiveExProgram *pProgram, CGLSLCompiler *pCompiler, IStorage *pStorage, bool Textured, bool Rotationless)
41{
42 CGLSL PrimitiveVertexShader;
43 CGLSL PrimitiveFragmentShader;
44 if(Textured)
45 pCompiler->AddDefine(pDefineName: "TW_TEXTURED", pDefineValue: "");
46 if(Rotationless)
47 pCompiler->AddDefine(pDefineName: "TW_ROTATIONLESS", pDefineValue: "");
48 PrimitiveVertexShader.LoadShader(pCompiler, pStorage, pFile: "shader/primex.vert", GL_VERTEX_SHADER);
49 PrimitiveFragmentShader.LoadShader(pCompiler, pStorage, pFile: "shader/primex.frag", GL_FRAGMENT_SHADER);
50 if(Textured || Rotationless)
51 pCompiler->ClearDefines();
52
53 pProgram->CreateProgram();
54 pProgram->AddShader(pShader: &PrimitiveVertexShader);
55 pProgram->AddShader(pShader: &PrimitiveFragmentShader);
56 pProgram->LinkProgram();
57
58 UseProgram(pProgram);
59
60 pProgram->m_LocPos = pProgram->GetUniformLoc(pName: "gPos");
61 pProgram->m_LocTextureSampler = pProgram->GetUniformLoc(pName: "gTextureSampler");
62 pProgram->m_LocRotation = pProgram->GetUniformLoc(pName: "gRotation");
63 pProgram->m_LocCenter = pProgram->GetUniformLoc(pName: "gCenter");
64 pProgram->m_LocVertciesColor = pProgram->GetUniformLoc(pName: "gVerticesColor");
65
66 if(!Rotationless)
67 {
68 pProgram->SetUniform(Loc: pProgram->m_LocRotation, Value: 0.0f);
69 float aCenter[2] = {0.f, 0.f};
70 pProgram->SetUniformVec2(Loc: pProgram->m_LocCenter, Count: 1, pValue: aCenter);
71 }
72}
73
74bool CCommandProcessorFragment_OpenGL3_3::Cmd_Init(const SCommand_Init *pCommand)
75{
76 if(!InitOpenGL(pCommand))
77 return false;
78
79 m_OpenGLTextureLodBIAS = g_Config.m_GfxGLTextureLODBIAS;
80
81 glActiveTexture(GL_TEXTURE0);
82
83 m_Has2DArrayTextures = true;
84 m_Has2DArrayTexturesAsExtension = false;
85 m_2DArrayTarget = GL_TEXTURE_2D_ARRAY;
86 m_Has3DTextures = false;
87 m_HasMipMaps = true;
88 m_HasNPOTTextures = true;
89 m_HasShaders = true;
90
91 m_pTextureMemoryUsage = pCommand->m_pTextureMemoryUsage;
92 m_pTextureMemoryUsage->store(i: 0, m: std::memory_order_relaxed);
93 m_LastBlendMode = EBlendMode::ALPHA;
94 m_LastClipEnable = false;
95 m_pPrimitiveProgram = new CGLSLPrimitiveProgram;
96 m_pPrimitiveProgramTextured = new CGLSLPrimitiveProgram;
97 m_pTileProgram = new CGLSLTileProgram;
98 m_pTileProgramTextured = new CGLSLTileProgram;
99 m_pPrimitive3DProgram = new CGLSLPrimitiveProgram;
100 m_pPrimitive3DProgramTextured = new CGLSLPrimitiveProgram;
101 m_pBorderTileProgram = new CGLSLTileProgram;
102 m_pBorderTileProgramTextured = new CGLSLTileProgram;
103 m_pQuadProgram = new CGLSLQuadProgram;
104 m_pQuadProgramTextured = new CGLSLQuadProgram;
105 m_pQuadProgramGrouped = new CGLSLQuadProgram;
106 m_pQuadProgramTexturedGrouped = new CGLSLQuadProgram;
107 m_pTextProgram = new CGLSLTextProgram;
108 m_pPrimitiveExProgram = new CGLSLPrimitiveExProgram;
109 m_pPrimitiveExProgramTextured = new CGLSLPrimitiveExProgram;
110 m_pPrimitiveExProgramRotationless = new CGLSLPrimitiveExProgram;
111 m_pPrimitiveExProgramTexturedRotationless = new CGLSLPrimitiveExProgram;
112 m_pSpriteProgramMultiple = new CGLSLSpriteMultipleProgram;
113 m_LastProgramId = 0;
114
115 CGLSLCompiler ShaderCompiler(g_Config.m_GfxGLMajor, g_Config.m_GfxGLMinor, g_Config.m_GfxGLPatch, m_IsOpenGLES, m_OpenGLTextureLodBIAS / 1000.0f);
116
117 GLint CapVal;
118 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS, params: &CapVal);
119
120 m_MaxQuadsAtOnce = minimum<int>(a: ((CapVal - 20) / (3 * 4)), b: ms_MaxQuadsPossible);
121
122 {
123 CGLSL PrimitiveVertexShader;
124 CGLSL PrimitiveFragmentShader;
125 PrimitiveVertexShader.LoadShader(pCompiler: &ShaderCompiler, pStorage: pCommand->m_pStorage, pFile: "shader/prim.vert", GL_VERTEX_SHADER);
126 PrimitiveFragmentShader.LoadShader(pCompiler: &ShaderCompiler, pStorage: pCommand->m_pStorage, pFile: "shader/prim.frag", GL_FRAGMENT_SHADER);
127
128 m_pPrimitiveProgram->CreateProgram();
129 m_pPrimitiveProgram->AddShader(pShader: &PrimitiveVertexShader);
130 m_pPrimitiveProgram->AddShader(pShader: &PrimitiveFragmentShader);
131 m_pPrimitiveProgram->LinkProgram();
132
133 UseProgram(pProgram: m_pPrimitiveProgram);
134
135 m_pPrimitiveProgram->m_LocPos = m_pPrimitiveProgram->GetUniformLoc(pName: "gPos");
136 m_pPrimitiveProgram->m_LocTextureSampler = m_pPrimitiveProgram->GetUniformLoc(pName: "gTextureSampler");
137 }
138 {
139 CGLSL PrimitiveVertexShader;
140 CGLSL PrimitiveFragmentShader;
141 ShaderCompiler.AddDefine(pDefineName: "TW_TEXTURED", pDefineValue: "");
142 PrimitiveVertexShader.LoadShader(pCompiler: &ShaderCompiler, pStorage: pCommand->m_pStorage, pFile: "shader/prim.vert", GL_VERTEX_SHADER);
143 PrimitiveFragmentShader.LoadShader(pCompiler: &ShaderCompiler, pStorage: pCommand->m_pStorage, pFile: "shader/prim.frag", GL_FRAGMENT_SHADER);
144 ShaderCompiler.ClearDefines();
145
146 m_pPrimitiveProgramTextured->CreateProgram();
147 m_pPrimitiveProgramTextured->AddShader(pShader: &PrimitiveVertexShader);
148 m_pPrimitiveProgramTextured->AddShader(pShader: &PrimitiveFragmentShader);
149 m_pPrimitiveProgramTextured->LinkProgram();
150
151 UseProgram(pProgram: m_pPrimitiveProgramTextured);
152
153 m_pPrimitiveProgramTextured->m_LocPos = m_pPrimitiveProgramTextured->GetUniformLoc(pName: "gPos");
154 m_pPrimitiveProgramTextured->m_LocTextureSampler = m_pPrimitiveProgramTextured->GetUniformLoc(pName: "gTextureSampler");
155 }
156
157 {
158 CGLSL PrimitiveVertexShader;
159 CGLSL PrimitiveFragmentShader;
160 ShaderCompiler.AddDefine(pDefineName: "TW_MODERN_GL", pDefineValue: "");
161 PrimitiveVertexShader.LoadShader(pCompiler: &ShaderCompiler, pStorage: pCommand->m_pStorage, pFile: "shader/pipeline.vert", GL_VERTEX_SHADER);
162 PrimitiveFragmentShader.LoadShader(pCompiler: &ShaderCompiler, pStorage: pCommand->m_pStorage, pFile: "shader/pipeline.frag", GL_FRAGMENT_SHADER);
163 ShaderCompiler.ClearDefines();
164
165 m_pPrimitive3DProgram->CreateProgram();
166 m_pPrimitive3DProgram->AddShader(pShader: &PrimitiveVertexShader);
167 m_pPrimitive3DProgram->AddShader(pShader: &PrimitiveFragmentShader);
168 m_pPrimitive3DProgram->LinkProgram();
169
170 UseProgram(pProgram: m_pPrimitive3DProgram);
171
172 m_pPrimitive3DProgram->m_LocPos = m_pPrimitive3DProgram->GetUniformLoc(pName: "gPos");
173 }
174 {
175 CGLSL PrimitiveVertexShader;
176 CGLSL PrimitiveFragmentShader;
177 ShaderCompiler.AddDefine(pDefineName: "TW_MODERN_GL", pDefineValue: "");
178 ShaderCompiler.AddDefine(pDefineName: "TW_TEXTURED", pDefineValue: "");
179 if(!pCommand->m_pCapabilities->m_2DArrayTextures)
180 ShaderCompiler.AddDefine(pDefineName: "TW_3D_TEXTURED", pDefineValue: "");
181 PrimitiveVertexShader.LoadShader(pCompiler: &ShaderCompiler, pStorage: pCommand->m_pStorage, pFile: "shader/pipeline.vert", GL_VERTEX_SHADER);
182 PrimitiveFragmentShader.LoadShader(pCompiler: &ShaderCompiler, pStorage: pCommand->m_pStorage, pFile: "shader/pipeline.frag", GL_FRAGMENT_SHADER);
183 ShaderCompiler.ClearDefines();
184
185 m_pPrimitive3DProgramTextured->CreateProgram();
186 m_pPrimitive3DProgramTextured->AddShader(pShader: &PrimitiveVertexShader);
187 m_pPrimitive3DProgramTextured->AddShader(pShader: &PrimitiveFragmentShader);
188 m_pPrimitive3DProgramTextured->LinkProgram();
189
190 UseProgram(pProgram: m_pPrimitive3DProgramTextured);
191
192 m_pPrimitive3DProgramTextured->m_LocPos = m_pPrimitive3DProgramTextured->GetUniformLoc(pName: "gPos");
193 m_pPrimitive3DProgramTextured->m_LocTextureSampler = m_pPrimitive3DProgramTextured->GetUniformLoc(pName: "gTextureSampler");
194 }
195
196 {
197 CGLSL VertexShader;
198 CGLSL FragmentShader;
199 VertexShader.LoadShader(pCompiler: &ShaderCompiler, pStorage: pCommand->m_pStorage, pFile: "shader/tile.vert", GL_VERTEX_SHADER);
200 FragmentShader.LoadShader(pCompiler: &ShaderCompiler, pStorage: pCommand->m_pStorage, pFile: "shader/tile.frag", GL_FRAGMENT_SHADER);
201
202 m_pTileProgram->CreateProgram();
203 m_pTileProgram->AddShader(pShader: &VertexShader);
204 m_pTileProgram->AddShader(pShader: &FragmentShader);
205 m_pTileProgram->LinkProgram();
206
207 UseProgram(pProgram: m_pTileProgram);
208
209 m_pTileProgram->m_LocPos = m_pTileProgram->GetUniformLoc(pName: "gPos");
210 m_pTileProgram->m_LocColor = m_pTileProgram->GetUniformLoc(pName: "gVertColor");
211 }
212 {
213 CGLSL VertexShader;
214 CGLSL FragmentShader;
215 ShaderCompiler.AddDefine(pDefineName: "TW_TILE_TEXTURED", pDefineValue: "");
216 VertexShader.LoadShader(pCompiler: &ShaderCompiler, pStorage: pCommand->m_pStorage, pFile: "shader/tile.vert", GL_VERTEX_SHADER);
217 FragmentShader.LoadShader(pCompiler: &ShaderCompiler, pStorage: pCommand->m_pStorage, pFile: "shader/tile.frag", GL_FRAGMENT_SHADER);
218 ShaderCompiler.ClearDefines();
219
220 m_pTileProgramTextured->CreateProgram();
221 m_pTileProgramTextured->AddShader(pShader: &VertexShader);
222 m_pTileProgramTextured->AddShader(pShader: &FragmentShader);
223 m_pTileProgramTextured->LinkProgram();
224
225 UseProgram(pProgram: m_pTileProgramTextured);
226
227 m_pTileProgramTextured->m_LocPos = m_pTileProgramTextured->GetUniformLoc(pName: "gPos");
228 m_pTileProgramTextured->m_LocTextureSampler = m_pTileProgramTextured->GetUniformLoc(pName: "gTextureSampler");
229 m_pTileProgramTextured->m_LocColor = m_pTileProgramTextured->GetUniformLoc(pName: "gVertColor");
230 }
231 {
232 CGLSL VertexShader;
233 CGLSL FragmentShader;
234 VertexShader.LoadShader(pCompiler: &ShaderCompiler, pStorage: pCommand->m_pStorage, pFile: "shader/tile_border.vert", GL_VERTEX_SHADER);
235 FragmentShader.LoadShader(pCompiler: &ShaderCompiler, pStorage: pCommand->m_pStorage, pFile: "shader/tile_border.frag", GL_FRAGMENT_SHADER);
236 ShaderCompiler.ClearDefines();
237
238 m_pBorderTileProgram->CreateProgram();
239 m_pBorderTileProgram->AddShader(pShader: &VertexShader);
240 m_pBorderTileProgram->AddShader(pShader: &FragmentShader);
241 m_pBorderTileProgram->LinkProgram();
242
243 UseProgram(pProgram: m_pBorderTileProgram);
244
245 m_pBorderTileProgram->m_LocPos = m_pBorderTileProgram->GetUniformLoc(pName: "gPos");
246 m_pBorderTileProgram->m_LocColor = m_pBorderTileProgram->GetUniformLoc(pName: "gVertColor");
247 m_pBorderTileProgram->m_LocOffset = m_pBorderTileProgram->GetUniformLoc(pName: "gOffset");
248 m_pBorderTileProgram->m_LocScale = m_pBorderTileProgram->GetUniformLoc(pName: "gScale");
249 }
250 {
251 CGLSL VertexShader;
252 CGLSL FragmentShader;
253 ShaderCompiler.AddDefine(pDefineName: "TW_TILE_TEXTURED", pDefineValue: "");
254 VertexShader.LoadShader(pCompiler: &ShaderCompiler, pStorage: pCommand->m_pStorage, pFile: "shader/tile_border.vert", GL_VERTEX_SHADER);
255 FragmentShader.LoadShader(pCompiler: &ShaderCompiler, pStorage: pCommand->m_pStorage, pFile: "shader/tile_border.frag", GL_FRAGMENT_SHADER);
256 ShaderCompiler.ClearDefines();
257
258 m_pBorderTileProgramTextured->CreateProgram();
259 m_pBorderTileProgramTextured->AddShader(pShader: &VertexShader);
260 m_pBorderTileProgramTextured->AddShader(pShader: &FragmentShader);
261 m_pBorderTileProgramTextured->LinkProgram();
262
263 UseProgram(pProgram: m_pBorderTileProgramTextured);
264
265 m_pBorderTileProgramTextured->m_LocPos = m_pBorderTileProgramTextured->GetUniformLoc(pName: "gPos");
266 m_pBorderTileProgramTextured->m_LocTextureSampler = m_pBorderTileProgramTextured->GetUniformLoc(pName: "gTextureSampler");
267 m_pBorderTileProgramTextured->m_LocColor = m_pBorderTileProgramTextured->GetUniformLoc(pName: "gVertColor");
268 m_pBorderTileProgramTextured->m_LocOffset = m_pBorderTileProgramTextured->GetUniformLoc(pName: "gOffset");
269 m_pBorderTileProgramTextured->m_LocScale = m_pBorderTileProgramTextured->GetUniformLoc(pName: "gScale");
270 }
271 {
272 CGLSL VertexShader;
273 CGLSL FragmentShader;
274 ShaderCompiler.AddDefine(pDefineName: "TW_MAX_QUADS", pDefineValue: std::to_string(val: m_MaxQuadsAtOnce).c_str());
275 VertexShader.LoadShader(pCompiler: &ShaderCompiler, pStorage: pCommand->m_pStorage, pFile: "shader/quad.vert", GL_VERTEX_SHADER);
276 FragmentShader.LoadShader(pCompiler: &ShaderCompiler, pStorage: pCommand->m_pStorage, pFile: "shader/quad.frag", GL_FRAGMENT_SHADER);
277 ShaderCompiler.ClearDefines();
278
279 m_pQuadProgram->CreateProgram();
280 m_pQuadProgram->AddShader(pShader: &VertexShader);
281 m_pQuadProgram->AddShader(pShader: &FragmentShader);
282 m_pQuadProgram->LinkProgram();
283
284 UseProgram(pProgram: m_pQuadProgram);
285
286 m_pQuadProgram->m_LocPos = m_pQuadProgram->GetUniformLoc(pName: "gPos");
287 m_pQuadProgram->m_LocColors = m_pQuadProgram->GetUniformLoc(pName: "gVertColors");
288 m_pQuadProgram->m_LocRotations = m_pQuadProgram->GetUniformLoc(pName: "gRotations");
289 m_pQuadProgram->m_LocOffsets = m_pQuadProgram->GetUniformLoc(pName: "gOffsets");
290 m_pQuadProgram->m_LocQuadOffset = m_pQuadProgram->GetUniformLoc(pName: "gQuadOffset");
291 }
292 {
293 CGLSL VertexShader;
294 CGLSL FragmentShader;
295 ShaderCompiler.AddDefine(pDefineName: "TW_QUAD_TEXTURED", pDefineValue: "");
296 ShaderCompiler.AddDefine(pDefineName: "TW_MAX_QUADS", pDefineValue: std::to_string(val: m_MaxQuadsAtOnce).c_str());
297 VertexShader.LoadShader(pCompiler: &ShaderCompiler, pStorage: pCommand->m_pStorage, pFile: "shader/quad.vert", GL_VERTEX_SHADER);
298 FragmentShader.LoadShader(pCompiler: &ShaderCompiler, pStorage: pCommand->m_pStorage, pFile: "shader/quad.frag", GL_FRAGMENT_SHADER);
299 ShaderCompiler.ClearDefines();
300
301 m_pQuadProgramTextured->CreateProgram();
302 m_pQuadProgramTextured->AddShader(pShader: &VertexShader);
303 m_pQuadProgramTextured->AddShader(pShader: &FragmentShader);
304 m_pQuadProgramTextured->LinkProgram();
305
306 UseProgram(pProgram: m_pQuadProgramTextured);
307
308 m_pQuadProgramTextured->m_LocPos = m_pQuadProgramTextured->GetUniformLoc(pName: "gPos");
309 m_pQuadProgramTextured->m_LocTextureSampler = m_pQuadProgramTextured->GetUniformLoc(pName: "gTextureSampler");
310 m_pQuadProgramTextured->m_LocColors = m_pQuadProgramTextured->GetUniformLoc(pName: "gVertColors");
311 m_pQuadProgramTextured->m_LocRotations = m_pQuadProgramTextured->GetUniformLoc(pName: "gRotations");
312 m_pQuadProgramTextured->m_LocOffsets = m_pQuadProgramTextured->GetUniformLoc(pName: "gOffsets");
313 m_pQuadProgramTextured->m_LocQuadOffset = m_pQuadProgramTextured->GetUniformLoc(pName: "gQuadOffset");
314 }
315 {
316 CGLSL VertexShader;
317 CGLSL FragmentShader;
318 ShaderCompiler.AddDefine(pDefineName: "TW_QUAD_GROUPED", pDefineValue: "");
319 VertexShader.LoadShader(pCompiler: &ShaderCompiler, pStorage: pCommand->m_pStorage, pFile: "shader/quad.vert", GL_VERTEX_SHADER);
320 FragmentShader.LoadShader(pCompiler: &ShaderCompiler, pStorage: pCommand->m_pStorage, pFile: "shader/quad.frag", GL_FRAGMENT_SHADER);
321 ShaderCompiler.ClearDefines();
322
323 m_pQuadProgramGrouped->CreateProgram();
324 m_pQuadProgramGrouped->AddShader(pShader: &VertexShader);
325 m_pQuadProgramGrouped->AddShader(pShader: &FragmentShader);
326 m_pQuadProgramGrouped->LinkProgram();
327
328 UseProgram(pProgram: m_pQuadProgramGrouped);
329
330 m_pQuadProgramGrouped->m_LocPos = m_pQuadProgramGrouped->GetUniformLoc(pName: "gPos");
331 m_pQuadProgramGrouped->m_LocColors = m_pQuadProgramGrouped->GetUniformLoc(pName: "gVertColors");
332 m_pQuadProgramGrouped->m_LocRotations = m_pQuadProgramGrouped->GetUniformLoc(pName: "gRotations");
333 m_pQuadProgramGrouped->m_LocOffsets = m_pQuadProgramGrouped->GetUniformLoc(pName: "gOffsets");
334 }
335 {
336 CGLSL VertexShader;
337 CGLSL FragmentShader;
338 ShaderCompiler.AddDefine(pDefineName: "TW_QUAD_TEXTURED", pDefineValue: "");
339 ShaderCompiler.AddDefine(pDefineName: "TW_QUAD_GROUPED", pDefineValue: "");
340 VertexShader.LoadShader(pCompiler: &ShaderCompiler, pStorage: pCommand->m_pStorage, pFile: "shader/quad.vert", GL_VERTEX_SHADER);
341 FragmentShader.LoadShader(pCompiler: &ShaderCompiler, pStorage: pCommand->m_pStorage, pFile: "shader/quad.frag", GL_FRAGMENT_SHADER);
342 ShaderCompiler.ClearDefines();
343
344 m_pQuadProgramTexturedGrouped->CreateProgram();
345 m_pQuadProgramTexturedGrouped->AddShader(pShader: &VertexShader);
346 m_pQuadProgramTexturedGrouped->AddShader(pShader: &FragmentShader);
347 m_pQuadProgramTexturedGrouped->LinkProgram();
348
349 UseProgram(pProgram: m_pQuadProgramTexturedGrouped);
350
351 m_pQuadProgramTexturedGrouped->m_LocPos = m_pQuadProgramTexturedGrouped->GetUniformLoc(pName: "gPos");
352 m_pQuadProgramTexturedGrouped->m_LocTextureSampler = m_pQuadProgramTexturedGrouped->GetUniformLoc(pName: "gTextureSampler");
353 m_pQuadProgramTexturedGrouped->m_LocColors = m_pQuadProgramTexturedGrouped->GetUniformLoc(pName: "gVertColors");
354 m_pQuadProgramTexturedGrouped->m_LocRotations = m_pQuadProgramTexturedGrouped->GetUniformLoc(pName: "gRotations");
355 m_pQuadProgramTexturedGrouped->m_LocOffsets = m_pQuadProgramTexturedGrouped->GetUniformLoc(pName: "gOffsets");
356 }
357 {
358 CGLSL VertexShader;
359 CGLSL FragmentShader;
360 VertexShader.LoadShader(pCompiler: &ShaderCompiler, pStorage: pCommand->m_pStorage, pFile: "shader/text.vert", GL_VERTEX_SHADER);
361 FragmentShader.LoadShader(pCompiler: &ShaderCompiler, pStorage: pCommand->m_pStorage, pFile: "shader/text.frag", GL_FRAGMENT_SHADER);
362
363 m_pTextProgram->CreateProgram();
364 m_pTextProgram->AddShader(pShader: &VertexShader);
365 m_pTextProgram->AddShader(pShader: &FragmentShader);
366 m_pTextProgram->LinkProgram();
367
368 UseProgram(pProgram: m_pTextProgram);
369
370 m_pTextProgram->m_LocPos = m_pTextProgram->GetUniformLoc(pName: "gPos");
371 m_pTextProgram->m_LocTextureSampler = -1;
372 m_pTextProgram->m_LocTextSampler = m_pTextProgram->GetUniformLoc(pName: "gTextSampler");
373 m_pTextProgram->m_LocTextOutlineSampler = m_pTextProgram->GetUniformLoc(pName: "gTextOutlineSampler");
374 m_pTextProgram->m_LocColor = m_pTextProgram->GetUniformLoc(pName: "gVertColor");
375 m_pTextProgram->m_LocOutlineColor = m_pTextProgram->GetUniformLoc(pName: "gVertOutlineColor");
376 m_pTextProgram->m_LocTextureSize = m_pTextProgram->GetUniformLoc(pName: "gTextureSize");
377 }
378 InitPrimExProgram(pProgram: m_pPrimitiveExProgram, pCompiler: &ShaderCompiler, pStorage: pCommand->m_pStorage, Textured: false, Rotationless: false);
379 InitPrimExProgram(pProgram: m_pPrimitiveExProgramTextured, pCompiler: &ShaderCompiler, pStorage: pCommand->m_pStorage, Textured: true, Rotationless: false);
380 InitPrimExProgram(pProgram: m_pPrimitiveExProgramRotationless, pCompiler: &ShaderCompiler, pStorage: pCommand->m_pStorage, Textured: false, Rotationless: true);
381 InitPrimExProgram(pProgram: m_pPrimitiveExProgramTexturedRotationless, pCompiler: &ShaderCompiler, pStorage: pCommand->m_pStorage, Textured: true, Rotationless: true);
382 {
383 CGLSL PrimitiveVertexShader;
384 CGLSL PrimitiveFragmentShader;
385 PrimitiveVertexShader.LoadShader(pCompiler: &ShaderCompiler, pStorage: pCommand->m_pStorage, pFile: "shader/spritemulti.vert", GL_VERTEX_SHADER);
386 PrimitiveFragmentShader.LoadShader(pCompiler: &ShaderCompiler, pStorage: pCommand->m_pStorage, pFile: "shader/spritemulti.frag", GL_FRAGMENT_SHADER);
387
388 m_pSpriteProgramMultiple->CreateProgram();
389 m_pSpriteProgramMultiple->AddShader(pShader: &PrimitiveVertexShader);
390 m_pSpriteProgramMultiple->AddShader(pShader: &PrimitiveFragmentShader);
391 m_pSpriteProgramMultiple->LinkProgram();
392
393 UseProgram(pProgram: m_pSpriteProgramMultiple);
394
395 m_pSpriteProgramMultiple->m_LocPos = m_pSpriteProgramMultiple->GetUniformLoc(pName: "gPos");
396 m_pSpriteProgramMultiple->m_LocTextureSampler = m_pSpriteProgramMultiple->GetUniformLoc(pName: "gTextureSampler");
397 m_pSpriteProgramMultiple->m_LocRSP = m_pSpriteProgramMultiple->GetUniformLoc(pName: "gRSP[0]");
398 m_pSpriteProgramMultiple->m_LocCenter = m_pSpriteProgramMultiple->GetUniformLoc(pName: "gCenter");
399 m_pSpriteProgramMultiple->m_LocVertciesColor = m_pSpriteProgramMultiple->GetUniformLoc(pName: "gVerticesColor");
400
401 float aCenter[2] = {0.f, 0.f};
402 m_pSpriteProgramMultiple->SetUniformVec2(Loc: m_pSpriteProgramMultiple->m_LocCenter, Count: 1, pValue: aCenter);
403 }
404
405 m_LastStreamBuffer = 0;
406
407 glGenBuffers(MAX_STREAM_BUFFER_COUNT, m_aPrimitiveDrawBufferId);
408 glGenVertexArrays(MAX_STREAM_BUFFER_COUNT, m_aPrimitiveDrawVertexId);
409 glGenBuffers(1, &m_PrimitiveDrawBufferIdTex3D);
410 glGenVertexArrays(1, &m_PrimitiveDrawVertexIdTex3D);
411
412 for(int i = 0; i < MAX_STREAM_BUFFER_COUNT; ++i)
413 {
414 glBindBuffer(GL_ARRAY_BUFFER, m_aPrimitiveDrawBufferId[i]);
415 glBindVertexArray(m_aPrimitiveDrawVertexId[i]);
416 glEnableVertexAttribArray(0);
417 glEnableVertexAttribArray(1);
418 glEnableVertexAttribArray(2);
419
420 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(CCommandBuffer::SVertex), 0);
421 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(CCommandBuffer::SVertex), (void *)(sizeof(float) * 2));
422 glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(CCommandBuffer::SVertex), (void *)(sizeof(float) * 4));
423
424 m_aLastIndexBufferBound[i] = 0;
425 }
426
427 glBindBuffer(GL_ARRAY_BUFFER, m_PrimitiveDrawBufferIdTex3D);
428 glBindVertexArray(m_PrimitiveDrawVertexIdTex3D);
429 glEnableVertexAttribArray(0);
430 glEnableVertexAttribArray(1);
431 glEnableVertexAttribArray(2);
432
433 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(CCommandBuffer::SVertexTex3DStream), 0);
434 glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(CCommandBuffer::SVertexTex3DStream), (void *)(sizeof(float) * 2));
435 glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(CCommandBuffer::SVertexTex3DStream), (void *)(sizeof(float) * 2 + sizeof(unsigned char) * 4));
436
437 // query the image max size only once
438 glGetIntegerv(GL_MAX_TEXTURE_SIZE, params: &m_MaxTexSize);
439
440 glBindVertexArray(0);
441 glGenBuffers(1, &m_QuadDrawIndexBufferId);
442 glBindBuffer(BUFFER_INIT_INDEX_TARGET, m_QuadDrawIndexBufferId);
443
444 unsigned int aIndices[CCommandBuffer::MAX_VERTICES / 4 * 6];
445 int Primq = 0;
446 for(int i = 0; i < CCommandBuffer::MAX_VERTICES / 4 * 6; i += 6)
447 {
448 aIndices[i] = Primq;
449 aIndices[i + 1] = Primq + 1;
450 aIndices[i + 2] = Primq + 2;
451 aIndices[i + 3] = Primq;
452 aIndices[i + 4] = Primq + 2;
453 aIndices[i + 5] = Primq + 3;
454 Primq += 4;
455 }
456 glBufferData(BUFFER_INIT_INDEX_TARGET, sizeof(unsigned int) * CCommandBuffer::MAX_VERTICES / 4 * 6, aIndices, GL_STATIC_DRAW);
457
458 m_CurrentIndicesInBuffer = CCommandBuffer::MAX_VERTICES / 4 * 6;
459
460 m_vTextures.resize(new_size: CCommandBuffer::MAX_TEXTURES);
461
462 m_ClearColor.r = m_ClearColor.g = m_ClearColor.b = -1.f;
463
464 // fix the alignment to allow even 1byte changes, e.g. for alpha components
465 glPixelStorei(GL_UNPACK_ALIGNMENT, param: 1);
466
467 return true;
468}
469
470void CCommandProcessorFragment_OpenGL3_3::Cmd_Shutdown(const SCommand_Shutdown *pCommand)
471{
472 glUseProgram(0);
473
474 m_pPrimitiveProgram->DeleteProgram();
475 m_pPrimitiveProgramTextured->DeleteProgram();
476 m_pBorderTileProgram->DeleteProgram();
477 m_pBorderTileProgramTextured->DeleteProgram();
478 m_pQuadProgram->DeleteProgram();
479 m_pQuadProgramTextured->DeleteProgram();
480 m_pQuadProgramGrouped->DeleteProgram();
481 m_pQuadProgramTexturedGrouped->DeleteProgram();
482 m_pTileProgram->DeleteProgram();
483 m_pTileProgramTextured->DeleteProgram();
484 m_pPrimitive3DProgram->DeleteProgram();
485 m_pPrimitive3DProgramTextured->DeleteProgram();
486 m_pTextProgram->DeleteProgram();
487 m_pPrimitiveExProgram->DeleteProgram();
488 m_pPrimitiveExProgramTextured->DeleteProgram();
489 m_pPrimitiveExProgramRotationless->DeleteProgram();
490 m_pPrimitiveExProgramTexturedRotationless->DeleteProgram();
491 m_pSpriteProgramMultiple->DeleteProgram();
492
493 // clean up everything
494 delete m_pPrimitiveProgram;
495 delete m_pPrimitiveProgramTextured;
496 delete m_pBorderTileProgram;
497 delete m_pBorderTileProgramTextured;
498 delete m_pQuadProgram;
499 delete m_pQuadProgramTextured;
500 delete m_pQuadProgramGrouped;
501 delete m_pQuadProgramTexturedGrouped;
502 delete m_pTileProgram;
503 delete m_pTileProgramTextured;
504 delete m_pPrimitive3DProgram;
505 delete m_pPrimitive3DProgramTextured;
506 delete m_pTextProgram;
507 delete m_pPrimitiveExProgram;
508 delete m_pPrimitiveExProgramTextured;
509 delete m_pPrimitiveExProgramRotationless;
510 delete m_pPrimitiveExProgramTexturedRotationless;
511 delete m_pSpriteProgramMultiple;
512
513 glBindVertexArray(0);
514 glDeleteBuffers(MAX_STREAM_BUFFER_COUNT, m_aPrimitiveDrawBufferId);
515 glDeleteBuffers(1, &m_QuadDrawIndexBufferId);
516 glDeleteVertexArrays(MAX_STREAM_BUFFER_COUNT, m_aPrimitiveDrawVertexId);
517 glDeleteBuffers(1, &m_PrimitiveDrawBufferIdTex3D);
518 glDeleteVertexArrays(1, &m_PrimitiveDrawVertexIdTex3D);
519
520 for(int i = 0; i < (int)m_vTextures.size(); ++i)
521 {
522 DestroyTexture(Slot: i);
523 }
524
525 for(size_t i = 0; i < m_vBufferContainers.size(); ++i)
526 {
527 DestroyBufferContainer(Index: i);
528 }
529
530 m_vBufferContainers.clear();
531}
532
533void CCommandProcessorFragment_OpenGL3_3::TextureUpdate(int Slot, int X, int Y, int Width, int Height, int GLFormat, uint8_t *pTexData)
534{
535 glBindTexture(GL_TEXTURE_2D, texture: m_vTextures[Slot].m_Tex);
536
537 if(m_vTextures[Slot].m_RescaleCount > 0)
538 {
539 for(int i = 0; i < m_vTextures[Slot].m_RescaleCount; ++i)
540 {
541 Width >>= 1;
542 Height >>= 1;
543
544 X /= 2;
545 Y /= 2;
546 }
547
548 uint8_t *pTmpData = ResizeImage(pImageData: pTexData, Width, Height, NewWidth: Width, NewHeight: Height, BPP: GLFormatToPixelSize(GLFormat));
549 free(ptr: pTexData);
550 pTexData = pTmpData;
551 }
552
553 glTexSubImage2D(GL_TEXTURE_2D, level: 0, xoffset: X, yoffset: Y, width: Width, height: Height, format: GLFormat, GL_UNSIGNED_BYTE, pixels: pTexData);
554 free(ptr: pTexData);
555}
556
557void CCommandProcessorFragment_OpenGL3_3::Cmd_Texture_Destroy(const CCommandBuffer::SCommand_Texture_Destroy *pCommand)
558{
559 int Slot = 0;
560 glBindTexture(GL_TEXTURE_2D, texture: 0);
561 glBindSampler(Slot, 0);
562 DestroyTexture(Slot: pCommand->m_Slot);
563}
564
565void CCommandProcessorFragment_OpenGL3_3::TextureCreate(int Slot, int Width, int Height, int GLFormat, int GLStoreFormat, int Flags, uint8_t *pTexData)
566{
567 while(Slot >= (int)m_vTextures.size())
568 m_vTextures.resize(new_size: m_vTextures.size() * 2);
569
570 // resample if needed
571 int RescaleCount = 0;
572 if(GLFormat == GL_RGBA)
573 {
574 if(Width > m_MaxTexSize || Height > m_MaxTexSize)
575 {
576 do
577 {
578 Width >>= 1;
579 Height >>= 1;
580 ++RescaleCount;
581 } while(Width > m_MaxTexSize || Height > m_MaxTexSize);
582
583 uint8_t *pTmpData = ResizeImage(pImageData: pTexData, Width, Height, NewWidth: Width, NewHeight: Height, BPP: GLFormatToPixelSize(GLFormat));
584 free(ptr: pTexData);
585 pTexData = pTmpData;
586 }
587 }
588 m_vTextures[Slot].m_Width = Width;
589 m_vTextures[Slot].m_Height = Height;
590 m_vTextures[Slot].m_RescaleCount = RescaleCount;
591
592 if(GLStoreFormat == GL_RED)
593 GLStoreFormat = GL_R8;
594 const size_t PixelSize = GLFormatToPixelSize(GLFormat);
595
596 int SamplerSlot = 0;
597
598 if((Flags & TextureFlag::NO_2D_TEXTURE) == 0)
599 {
600 glGenTextures(n: 1, textures: &m_vTextures[Slot].m_Tex);
601 glBindTexture(GL_TEXTURE_2D, texture: m_vTextures[Slot].m_Tex);
602
603 glGenSamplers(1, &m_vTextures[Slot].m_Sampler);
604 glBindSampler(SamplerSlot, m_vTextures[Slot].m_Sampler);
605 }
606
607 if(Flags & TextureFlag::NO_MIPMAPS)
608 {
609 if((Flags & TextureFlag::NO_2D_TEXTURE) == 0)
610 {
611 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
612 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
613 glSamplerParameteri(m_vTextures[Slot].m_Sampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
614 glSamplerParameteri(m_vTextures[Slot].m_Sampler, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
615 glTexImage2D(GL_TEXTURE_2D, level: 0, internalformat: GLStoreFormat, width: Width, height: Height, border: 0, format: GLFormat, GL_UNSIGNED_BYTE, pixels: pTexData);
616 }
617 }
618 else
619 {
620 if((Flags & TextureFlag::NO_2D_TEXTURE) == 0)
621 {
622 glSamplerParameteri(m_vTextures[Slot].m_Sampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
623 glSamplerParameteri(m_vTextures[Slot].m_Sampler, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
624
625#ifndef BACKEND_AS_OPENGL_ES
626 if(m_OpenGLTextureLodBIAS != 0 && !m_IsOpenGLES)
627 glSamplerParameterf(m_vTextures[Slot].m_Sampler, GL_TEXTURE_LOD_BIAS, ((GLfloat)m_OpenGLTextureLodBIAS / 1000.0f));
628#endif
629
630 // prevent mipmap display bugs, when zooming out far
631 if(Width >= 1024 && Height >= 1024)
632 {
633 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, param: 5.f);
634 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, param: 5);
635 }
636 glTexImage2D(GL_TEXTURE_2D, level: 0, internalformat: GLStoreFormat, width: Width, height: Height, border: 0, format: GLFormat, GL_UNSIGNED_BYTE, pixels: pTexData);
637 glGenerateMipmap(GL_TEXTURE_2D);
638 }
639
640 if((Flags & TextureFlag::TO_2D_ARRAY_TEXTURE) != 0)
641 {
642 glGenTextures(n: 1, textures: &m_vTextures[Slot].m_Tex2DArray);
643 glBindTexture(GL_TEXTURE_2D_ARRAY, texture: m_vTextures[Slot].m_Tex2DArray);
644
645 glGenSamplers(1, &m_vTextures[Slot].m_Sampler2DArray);
646 glBindSampler(SamplerSlot, m_vTextures[Slot].m_Sampler2DArray);
647 glSamplerParameteri(m_vTextures[Slot].m_Sampler2DArray, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
648 glSamplerParameteri(m_vTextures[Slot].m_Sampler2DArray, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
649 glSamplerParameteri(m_vTextures[Slot].m_Sampler2DArray, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
650 glSamplerParameteri(m_vTextures[Slot].m_Sampler2DArray, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
651 glSamplerParameteri(m_vTextures[Slot].m_Sampler2DArray, GL_TEXTURE_WRAP_R, GL_MIRRORED_REPEAT);
652
653#ifndef BACKEND_AS_OPENGL_ES
654 if(m_OpenGLTextureLodBIAS != 0 && !m_IsOpenGLES)
655 glSamplerParameterf(m_vTextures[Slot].m_Sampler2DArray, GL_TEXTURE_LOD_BIAS, ((GLfloat)m_OpenGLTextureLodBIAS / 1000.0f));
656#endif
657
658 uint8_t *pImageData3D = static_cast<uint8_t *>(malloc(size: (size_t)Width * Height * PixelSize));
659 int Image3DWidth, Image3DHeight;
660
661 int ConvertWidth = Width;
662 int ConvertHeight = Height;
663
664 if(ConvertWidth == 0 || (ConvertWidth % 16) != 0 || ConvertHeight == 0 || (ConvertHeight % 16) != 0)
665 {
666 int NewWidth = maximum<int>(a: HighestBit(OfVar: ConvertWidth), b: 16);
667 int NewHeight = maximum<int>(a: HighestBit(OfVar: ConvertHeight), b: 16);
668 uint8_t *pNewTexData = ResizeImage(pImageData: pTexData, Width: ConvertWidth, Height: ConvertHeight, NewWidth, NewHeight, BPP: GLFormatToPixelSize(GLFormat));
669 log_debug("gfx/opengl", "3D/2D array texture was resized");
670
671 ConvertWidth = NewWidth;
672 ConvertHeight = NewHeight;
673
674 free(ptr: pTexData);
675 pTexData = pNewTexData;
676 }
677
678 if(Texture2DTo3D(pImageBuffer: pTexData, ImageWidth: ConvertWidth, ImageHeight: ConvertHeight, PixelSize, SplitCountWidth: 16, SplitCountHeight: 16, pTarget3DImageData: pImageData3D, Target3DImageWidth&: Image3DWidth, Target3DImageHeight&: Image3DHeight))
679 {
680 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GLStoreFormat, Image3DWidth, Image3DHeight, 256, 0, GLFormat, GL_UNSIGNED_BYTE, pImageData3D);
681 glGenerateMipmap(GL_TEXTURE_2D_ARRAY);
682 }
683
684 free(ptr: pImageData3D);
685 }
686 }
687
688 // This is the initial value for the wrap modes
689 m_vTextures[Slot].m_LastWrapMode = EWrapMode::REPEAT;
690
691 // calculate memory usage
692 m_vTextures[Slot].m_MemSize = (size_t)Width * Height * PixelSize;
693 while(Width > 2 && Height > 2)
694 {
695 Width >>= 1;
696 Height >>= 1;
697 m_vTextures[Slot].m_MemSize += (size_t)Width * Height * PixelSize;
698 }
699 m_pTextureMemoryUsage->store(i: m_pTextureMemoryUsage->load(m: std::memory_order_relaxed) + m_vTextures[Slot].m_MemSize, m: std::memory_order_relaxed);
700
701 free(ptr: pTexData);
702}
703
704void CCommandProcessorFragment_OpenGL3_3::Cmd_Texture_Create(const CCommandBuffer::SCommand_Texture_Create *pCommand)
705{
706 TextureCreate(Slot: pCommand->m_Slot, Width: pCommand->m_Width, Height: pCommand->m_Height, GL_RGBA, GL_RGBA, Flags: pCommand->m_Flags, pTexData: pCommand->m_pData);
707}
708
709void CCommandProcessorFragment_OpenGL3_3::Cmd_TextTexture_Update(const CCommandBuffer::SCommand_TextTexture_Update *pCommand)
710{
711 TextureUpdate(Slot: pCommand->m_Slot, X: pCommand->m_X, Y: pCommand->m_Y, Width: pCommand->m_Width, Height: pCommand->m_Height, GL_RED, pTexData: pCommand->m_pData);
712}
713
714void CCommandProcessorFragment_OpenGL3_3::Cmd_TextTextures_Destroy(const CCommandBuffer::SCommand_TextTextures_Destroy *pCommand)
715{
716 DestroyTexture(Slot: pCommand->m_Slot);
717 DestroyTexture(Slot: pCommand->m_SlotOutline);
718}
719
720void CCommandProcessorFragment_OpenGL3_3::Cmd_TextTextures_Create(const CCommandBuffer::SCommand_TextTextures_Create *pCommand)
721{
722 TextureCreate(Slot: pCommand->m_Slot, Width: pCommand->m_Width, Height: pCommand->m_Height, GL_RED, GL_RED, Flags: TextureFlag::NO_MIPMAPS, pTexData: pCommand->m_pTextData);
723 TextureCreate(Slot: pCommand->m_SlotOutline, Width: pCommand->m_Width, Height: pCommand->m_Height, GL_RED, GL_RED, Flags: TextureFlag::NO_MIPMAPS, pTexData: pCommand->m_pTextOutlineData);
724}
725
726void CCommandProcessorFragment_OpenGL3_3::Cmd_Clear(const CCommandBuffer::SCommand_Clear *pCommand)
727{
728 // if clip is still active, force disable it for clearing, enable it again afterwards
729 bool ClipWasEnabled = m_LastClipEnable;
730 if(ClipWasEnabled)
731 {
732 glDisable(GL_SCISSOR_TEST);
733 }
734 if(pCommand->m_Color.r != m_ClearColor.r || pCommand->m_Color.g != m_ClearColor.g || pCommand->m_Color.b != m_ClearColor.b)
735 {
736 glClearColor(red: pCommand->m_Color.r, green: pCommand->m_Color.g, blue: pCommand->m_Color.b, alpha: 0.0f);
737 m_ClearColor = pCommand->m_Color;
738 }
739 glClear(GL_COLOR_BUFFER_BIT);
740 if(ClipWasEnabled)
741 {
742 glEnable(GL_SCISSOR_TEST);
743 }
744}
745
746void CCommandProcessorFragment_OpenGL3_3::UploadStreamBufferData(EPrimitiveType PrimitiveType, const void *pVertices, size_t VertSize, unsigned int PrimitiveCount, bool AsTex3D)
747{
748 int Count = 0;
749 switch(PrimitiveType)
750 {
751 case EPrimitiveType::LINES:
752 Count = PrimitiveCount * 2;
753 break;
754 case EPrimitiveType::TRIANGLES:
755 Count = PrimitiveCount * 3;
756 break;
757 case EPrimitiveType::QUADS:
758 Count = PrimitiveCount * 4;
759 break;
760 default:
761 return;
762 };
763
764 if(AsTex3D)
765 glBindBuffer(GL_ARRAY_BUFFER, m_PrimitiveDrawBufferIdTex3D);
766 else
767 glBindBuffer(GL_ARRAY_BUFFER, m_aPrimitiveDrawBufferId[m_LastStreamBuffer]);
768
769 glBufferData(GL_ARRAY_BUFFER, VertSize * Count, pVertices, GL_STREAM_DRAW);
770}
771
772void CCommandProcessorFragment_OpenGL3_3::Cmd_Render(const CCommandBuffer::SCommand_Render *pCommand)
773{
774 CGLSLTWProgram *pProgram = m_pPrimitiveProgram;
775 if(IsTexturedState(State: pCommand->m_State))
776 pProgram = m_pPrimitiveProgramTextured;
777 UseProgram(pProgram);
778 SetState(State: pCommand->m_State, pProgram);
779
780 UploadStreamBufferData(PrimitiveType: pCommand->m_PrimType, pVertices: pCommand->m_pVertices, VertSize: sizeof(CCommandBuffer::SVertex), PrimitiveCount: pCommand->m_PrimCount);
781
782 glBindVertexArray(m_aPrimitiveDrawVertexId[m_LastStreamBuffer]);
783
784 switch(pCommand->m_PrimType)
785 {
786 // We don't support GL_QUADS due to core profile
787 case EPrimitiveType::LINES:
788 glDrawArrays(GL_LINES, first: 0, count: pCommand->m_PrimCount * 2);
789 break;
790 case EPrimitiveType::TRIANGLES:
791 glDrawArrays(GL_TRIANGLES, first: 0, count: pCommand->m_PrimCount * 3);
792 break;
793 case EPrimitiveType::QUADS:
794 if(m_aLastIndexBufferBound[m_LastStreamBuffer] != m_QuadDrawIndexBufferId)
795 {
796 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_QuadDrawIndexBufferId);
797 m_aLastIndexBufferBound[m_LastStreamBuffer] = m_QuadDrawIndexBufferId;
798 }
799 glDrawElements(GL_TRIANGLES, count: pCommand->m_PrimCount * 6, GL_UNSIGNED_INT, indices: 0);
800 break;
801 default:
802 dbg_assert_failed("Invalid primitive type: %d", (int)pCommand->m_PrimType);
803 };
804
805 m_LastStreamBuffer = (m_LastStreamBuffer + 1 >= MAX_STREAM_BUFFER_COUNT ? 0 : m_LastStreamBuffer + 1);
806}
807
808void CCommandProcessorFragment_OpenGL3_3::Cmd_RenderTex3D(const CCommandBuffer::SCommand_RenderTex3D *pCommand)
809{
810 CGLSLPrimitiveProgram *pProg = m_pPrimitive3DProgram;
811 if(IsTexturedState(State: pCommand->m_State))
812 pProg = m_pPrimitive3DProgramTextured;
813 UseProgram(pProgram: pProg);
814 SetState(State: pCommand->m_State, pProgram: pProg, Use2DArrayTextures: true);
815
816 UploadStreamBufferData(PrimitiveType: pCommand->m_PrimType, pVertices: pCommand->m_pVertices, VertSize: sizeof(CCommandBuffer::SVertexTex3DStream), PrimitiveCount: pCommand->m_PrimCount, AsTex3D: true);
817
818 glBindVertexArray(m_PrimitiveDrawVertexIdTex3D);
819
820 switch(pCommand->m_PrimType)
821 {
822 // We don't support GL_QUADS due to core profile
823 case EPrimitiveType::LINES:
824 glDrawArrays(GL_LINES, first: 0, count: pCommand->m_PrimCount * 2);
825 break;
826 case EPrimitiveType::QUADS:
827 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_QuadDrawIndexBufferId);
828 glDrawElements(GL_TRIANGLES, count: pCommand->m_PrimCount * 6, GL_UNSIGNED_INT, indices: 0);
829 break;
830 default:
831 dbg_assert_failed("Invalid primitive type: %d", (int)pCommand->m_PrimType);
832 };
833}
834
835void CCommandProcessorFragment_OpenGL3_3::DestroyBufferContainer(int Index, bool DeleteBOs)
836{
837 SBufferContainer &BufferContainer = m_vBufferContainers[Index];
838 if(BufferContainer.m_VertArrayId != 0)
839 glDeleteVertexArrays(1, &BufferContainer.m_VertArrayId);
840
841 // all buffer objects can deleted automatically, so the program doesn't need to deal with them (e.g. causing crashes because of driver bugs)
842 if(DeleteBOs)
843 {
844 int VertBufferId = BufferContainer.m_ContainerInfo.m_VertBufferBindingIndex;
845 if(VertBufferId != -1)
846 {
847 glDeleteBuffers(1, &m_vBufferObjectIndices[VertBufferId]);
848 }
849 }
850
851 BufferContainer.m_LastIndexBufferBound = 0;
852 BufferContainer.m_ContainerInfo.m_vAttributes.clear();
853}
854
855void CCommandProcessorFragment_OpenGL3_3::AppendIndices(unsigned int NewIndicesCount)
856{
857 if(NewIndicesCount <= m_CurrentIndicesInBuffer)
858 return;
859 unsigned int AddCount = NewIndicesCount - m_CurrentIndicesInBuffer;
860 unsigned int *pIndices = new unsigned int[AddCount];
861 int Primq = (m_CurrentIndicesInBuffer / 6) * 4;
862 for(unsigned int i = 0; i < AddCount; i += 6)
863 {
864 pIndices[i] = Primq;
865 pIndices[i + 1] = Primq + 1;
866 pIndices[i + 2] = Primq + 2;
867 pIndices[i + 3] = Primq;
868 pIndices[i + 4] = Primq + 2;
869 pIndices[i + 5] = Primq + 3;
870 Primq += 4;
871 }
872
873 glBindBuffer(GL_COPY_READ_BUFFER, m_QuadDrawIndexBufferId);
874 GLuint NewIndexBufferId;
875 glGenBuffers(1, &NewIndexBufferId);
876 glBindBuffer(BUFFER_INIT_INDEX_TARGET, NewIndexBufferId);
877 constexpr GLsizeiptr Size = sizeof(unsigned int);
878 glBufferData(BUFFER_INIT_INDEX_TARGET, (GLsizeiptr)NewIndicesCount * Size, NULL, GL_STATIC_DRAW);
879 glCopyBufferSubData(GL_COPY_READ_BUFFER, BUFFER_INIT_INDEX_TARGET, 0, 0, (GLsizeiptr)m_CurrentIndicesInBuffer * Size);
880 glBufferSubData(BUFFER_INIT_INDEX_TARGET, (GLsizeiptr)m_CurrentIndicesInBuffer * Size, (GLsizeiptr)AddCount * Size, pIndices);
881 glBindBuffer(BUFFER_INIT_INDEX_TARGET, 0);
882 glBindBuffer(GL_COPY_READ_BUFFER, 0);
883
884 glDeleteBuffers(1, &m_QuadDrawIndexBufferId);
885 m_QuadDrawIndexBufferId = NewIndexBufferId;
886
887 std::fill(first: std::begin(arr&: m_aLastIndexBufferBound), last: std::end(arr&: m_aLastIndexBufferBound), value: 0);
888 for(auto &BufferContainer : m_vBufferContainers)
889 {
890 BufferContainer.m_LastIndexBufferBound = 0;
891 }
892
893 m_CurrentIndicesInBuffer = NewIndicesCount;
894 delete[] pIndices;
895}
896
897void CCommandProcessorFragment_OpenGL3_3::Cmd_CreateBufferObject(const CCommandBuffer::SCommand_CreateBufferObject *pCommand)
898{
899 void *pUploadData = pCommand->m_pUploadData;
900 const int Index = pCommand->m_BufferIndex;
901 // create necessary space
902 if((size_t)Index >= m_vBufferObjectIndices.size())
903 {
904 m_vBufferObjectIndices.resize(new_size: Index + 1, x: 0);
905 }
906
907 GLuint VertBufferId = 0;
908
909 glGenBuffers(1, &VertBufferId);
910 glBindBuffer(BUFFER_INIT_VERTEX_TARGET, VertBufferId);
911 glBufferData(BUFFER_INIT_VERTEX_TARGET, (GLsizeiptr)(pCommand->m_DataSize), pUploadData, GL_STATIC_DRAW);
912
913 m_vBufferObjectIndices[Index] = VertBufferId;
914
915 if(pCommand->m_DeletePointer)
916 free(ptr: pUploadData);
917}
918
919void CCommandProcessorFragment_OpenGL3_3::Cmd_RecreateBufferObject(const CCommandBuffer::SCommand_RecreateBufferObject *pCommand)
920{
921 void *pUploadData = pCommand->m_pUploadData;
922 int Index = pCommand->m_BufferIndex;
923
924 glBindBuffer(BUFFER_INIT_VERTEX_TARGET, m_vBufferObjectIndices[Index]);
925 glBufferData(BUFFER_INIT_VERTEX_TARGET, (GLsizeiptr)(pCommand->m_DataSize), pUploadData, GL_STATIC_DRAW);
926
927 if(pCommand->m_DeletePointer)
928 free(ptr: pUploadData);
929}
930
931void CCommandProcessorFragment_OpenGL3_3::Cmd_UpdateBufferObject(const CCommandBuffer::SCommand_UpdateBufferObject *pCommand)
932{
933 void *pUploadData = pCommand->m_pUploadData;
934 int Index = pCommand->m_BufferIndex;
935
936 glBindBuffer(BUFFER_INIT_VERTEX_TARGET, m_vBufferObjectIndices[Index]);
937 glBufferSubData(BUFFER_INIT_VERTEX_TARGET, (GLintptr)(pCommand->m_pOffset), (GLsizeiptr)(pCommand->m_DataSize), pUploadData);
938
939 if(pCommand->m_DeletePointer)
940 free(ptr: pUploadData);
941}
942
943void CCommandProcessorFragment_OpenGL3_3::Cmd_CopyBufferObject(const CCommandBuffer::SCommand_CopyBufferObject *pCommand)
944{
945 int WriteIndex = pCommand->m_WriteBufferIndex;
946 int ReadIndex = pCommand->m_ReadBufferIndex;
947
948 glBindBuffer(GL_COPY_WRITE_BUFFER, m_vBufferObjectIndices[WriteIndex]);
949 glBindBuffer(GL_COPY_READ_BUFFER, m_vBufferObjectIndices[ReadIndex]);
950 glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, (GLsizeiptr)(pCommand->m_ReadOffset), (GLsizeiptr)(pCommand->m_WriteOffset), (GLsizeiptr)pCommand->m_CopySize);
951}
952
953void CCommandProcessorFragment_OpenGL3_3::Cmd_DeleteBufferObject(const CCommandBuffer::SCommand_DeleteBufferObject *pCommand)
954{
955 int Index = pCommand->m_BufferIndex;
956
957 glDeleteBuffers(1, &m_vBufferObjectIndices[Index]);
958}
959
960void CCommandProcessorFragment_OpenGL3_3::Cmd_CreateBufferContainer(const CCommandBuffer::SCommand_CreateBufferContainer *pCommand)
961{
962 const int Index = pCommand->m_BufferContainerIndex;
963 // create necessary space
964 if((size_t)Index >= m_vBufferContainers.size())
965 {
966 SBufferContainer Container;
967 Container.m_ContainerInfo.m_Stride = 0;
968 Container.m_ContainerInfo.m_VertBufferBindingIndex = -1;
969 m_vBufferContainers.resize(new_size: Index + 1, x: Container);
970 }
971
972 SBufferContainer &BufferContainer = m_vBufferContainers[Index];
973 glGenVertexArrays(1, &BufferContainer.m_VertArrayId);
974 glBindVertexArray(BufferContainer.m_VertArrayId);
975
976 BufferContainer.m_LastIndexBufferBound = 0;
977
978 for(size_t i = 0; i < pCommand->m_AttrCount; ++i)
979 {
980 glEnableVertexAttribArray((GLuint)i);
981
982 glBindBuffer(GL_ARRAY_BUFFER, m_vBufferObjectIndices[pCommand->m_VertBufferBindingIndex]);
983
984 SBufferContainerInfo::SAttribute &Attr = pCommand->m_pAttributes[i];
985
986 if(Attr.m_FuncType == 0)
987 glVertexAttribPointer((GLuint)i, Attr.m_DataTypeCount, Attr.m_Type, (GLboolean)Attr.m_Normalized, pCommand->m_Stride, Attr.m_pOffset);
988 else if(Attr.m_FuncType == 1)
989 glVertexAttribIPointer((GLuint)i, Attr.m_DataTypeCount, Attr.m_Type, pCommand->m_Stride, Attr.m_pOffset);
990
991 BufferContainer.m_ContainerInfo.m_vAttributes.push_back(x: Attr);
992 }
993
994 BufferContainer.m_ContainerInfo.m_VertBufferBindingIndex = pCommand->m_VertBufferBindingIndex;
995 BufferContainer.m_ContainerInfo.m_Stride = pCommand->m_Stride;
996}
997
998void CCommandProcessorFragment_OpenGL3_3::Cmd_UpdateBufferContainer(const CCommandBuffer::SCommand_UpdateBufferContainer *pCommand)
999{
1000 SBufferContainer &BufferContainer = m_vBufferContainers[pCommand->m_BufferContainerIndex];
1001
1002 glBindVertexArray(BufferContainer.m_VertArrayId);
1003
1004 // disable all old attributes
1005 for(size_t i = 0; i < BufferContainer.m_ContainerInfo.m_vAttributes.size(); ++i)
1006 {
1007 glDisableVertexAttribArray((GLuint)i);
1008 }
1009 BufferContainer.m_ContainerInfo.m_vAttributes.clear();
1010
1011 for(size_t i = 0; i < pCommand->m_AttrCount; ++i)
1012 {
1013 glEnableVertexAttribArray((GLuint)i);
1014
1015 glBindBuffer(GL_ARRAY_BUFFER, m_vBufferObjectIndices[pCommand->m_VertBufferBindingIndex]);
1016 SBufferContainerInfo::SAttribute &Attr = pCommand->m_pAttributes[i];
1017 if(Attr.m_FuncType == 0)
1018 glVertexAttribPointer((GLuint)i, Attr.m_DataTypeCount, Attr.m_Type, Attr.m_Normalized, pCommand->m_Stride, Attr.m_pOffset);
1019 else if(Attr.m_FuncType == 1)
1020 glVertexAttribIPointer((GLuint)i, Attr.m_DataTypeCount, Attr.m_Type, pCommand->m_Stride, Attr.m_pOffset);
1021
1022 BufferContainer.m_ContainerInfo.m_vAttributes.push_back(x: Attr);
1023 }
1024
1025 BufferContainer.m_ContainerInfo.m_VertBufferBindingIndex = pCommand->m_VertBufferBindingIndex;
1026 BufferContainer.m_ContainerInfo.m_Stride = pCommand->m_Stride;
1027}
1028
1029void CCommandProcessorFragment_OpenGL3_3::Cmd_DeleteBufferContainer(const CCommandBuffer::SCommand_DeleteBufferContainer *pCommand)
1030{
1031 DestroyBufferContainer(Index: pCommand->m_BufferContainerIndex, DeleteBOs: pCommand->m_DestroyAllBO);
1032}
1033
1034void CCommandProcessorFragment_OpenGL3_3::Cmd_IndicesRequiredNumNotify(const CCommandBuffer::SCommand_IndicesRequiredNumNotify *pCommand)
1035{
1036 if(pCommand->m_RequiredIndicesNum > m_CurrentIndicesInBuffer)
1037 AppendIndices(NewIndicesCount: pCommand->m_RequiredIndicesNum);
1038}
1039
1040void CCommandProcessorFragment_OpenGL3_3::Cmd_RenderBorderTile(const CCommandBuffer::SCommand_RenderBorderTile *pCommand)
1041{
1042 int Index = pCommand->m_BufferContainerIndex;
1043 // if space not there return
1044 if((size_t)Index >= m_vBufferContainers.size())
1045 return;
1046
1047 SBufferContainer &BufferContainer = m_vBufferContainers[Index];
1048 if(BufferContainer.m_VertArrayId == 0)
1049 return;
1050
1051 CGLSLTileProgram *pProgram = NULL;
1052 if(IsTexturedState(State: pCommand->m_State))
1053 pProgram = m_pBorderTileProgramTextured;
1054 else
1055 pProgram = m_pBorderTileProgram;
1056 UseProgram(pProgram);
1057
1058 SetState(State: pCommand->m_State, pProgram, Use2DArrayTextures: true);
1059 pProgram->SetUniformVec4(Loc: pProgram->m_LocColor, Count: 1, pValue: (float *)&pCommand->m_Color);
1060
1061 pProgram->SetUniformVec2(Loc: pProgram->m_LocOffset, Count: 1, pValue: (float *)&pCommand->m_Offset);
1062 pProgram->SetUniformVec2(Loc: pProgram->m_LocScale, Count: 1, pValue: (float *)&pCommand->m_Scale);
1063
1064 glBindVertexArray(BufferContainer.m_VertArrayId);
1065 if(BufferContainer.m_LastIndexBufferBound != m_QuadDrawIndexBufferId)
1066 {
1067 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_QuadDrawIndexBufferId);
1068 BufferContainer.m_LastIndexBufferBound = m_QuadDrawIndexBufferId;
1069 }
1070 glDrawElements(GL_TRIANGLES, count: pCommand->m_DrawNum * 6, GL_UNSIGNED_INT, indices: pCommand->m_pIndicesOffset);
1071}
1072
1073void CCommandProcessorFragment_OpenGL3_3::Cmd_RenderTileLayer(const CCommandBuffer::SCommand_RenderTileLayer *pCommand)
1074{
1075 int Index = pCommand->m_BufferContainerIndex;
1076 // if space not there return
1077 if((size_t)Index >= m_vBufferContainers.size())
1078 return;
1079
1080 SBufferContainer &BufferContainer = m_vBufferContainers[Index];
1081 if(BufferContainer.m_VertArrayId == 0)
1082 return;
1083
1084 if(pCommand->m_IndicesDrawNum == 0)
1085 {
1086 return; // nothing to draw
1087 }
1088
1089 CGLSLTileProgram *pProgram = NULL;
1090 if(IsTexturedState(State: pCommand->m_State))
1091 {
1092 pProgram = m_pTileProgramTextured;
1093 }
1094 else
1095 pProgram = m_pTileProgram;
1096
1097 UseProgram(pProgram);
1098
1099 SetState(State: pCommand->m_State, pProgram, Use2DArrayTextures: true);
1100 pProgram->SetUniformVec4(Loc: pProgram->m_LocColor, Count: 1, pValue: (float *)&pCommand->m_Color);
1101
1102 glBindVertexArray(BufferContainer.m_VertArrayId);
1103 if(BufferContainer.m_LastIndexBufferBound != m_QuadDrawIndexBufferId)
1104 {
1105 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_QuadDrawIndexBufferId);
1106 BufferContainer.m_LastIndexBufferBound = m_QuadDrawIndexBufferId;
1107 }
1108 for(int i = 0; i < pCommand->m_IndicesDrawNum; ++i)
1109 {
1110 glDrawElements(GL_TRIANGLES, count: pCommand->m_pDrawCount[i], GL_UNSIGNED_INT, indices: pCommand->m_pIndicesOffsets[i]);
1111 }
1112}
1113
1114void CCommandProcessorFragment_OpenGL3_3::Cmd_RenderQuadLayer(const CCommandBuffer::SCommand_RenderQuadLayer *pCommand, bool Grouped)
1115{
1116 int Index = pCommand->m_BufferContainerIndex;
1117 // if space not there return
1118 if((size_t)Index >= m_vBufferContainers.size())
1119 return;
1120
1121 SBufferContainer &BufferContainer = m_vBufferContainers[Index];
1122 if(BufferContainer.m_VertArrayId == 0)
1123 return;
1124
1125 if(pCommand->m_QuadNum == 0)
1126 {
1127 return; // nothing to draw
1128 }
1129
1130 CGLSLQuadProgram *pProgram = NULL;
1131 if(Grouped)
1132 {
1133 if(IsTexturedState(State: pCommand->m_State))
1134 {
1135 pProgram = m_pQuadProgramTexturedGrouped;
1136 }
1137 else
1138 pProgram = m_pQuadProgramGrouped;
1139 }
1140 else
1141 {
1142 if(IsTexturedState(State: pCommand->m_State))
1143 {
1144 pProgram = m_pQuadProgramTextured;
1145 }
1146 else
1147 pProgram = m_pQuadProgram;
1148 }
1149
1150 UseProgram(pProgram);
1151 SetState(State: pCommand->m_State, pProgram);
1152
1153 glBindVertexArray(BufferContainer.m_VertArrayId);
1154 if(BufferContainer.m_LastIndexBufferBound != m_QuadDrawIndexBufferId)
1155 {
1156 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_QuadDrawIndexBufferId);
1157 BufferContainer.m_LastIndexBufferBound = m_QuadDrawIndexBufferId;
1158 }
1159
1160 int QuadsLeft = pCommand->m_QuadNum;
1161 size_t QuadOffset = 0;
1162 // the extra offset is not related to the information from the command, but an actual offset in the buffer
1163 size_t QuadOffsetExtra = pCommand->m_QuadOffset;
1164
1165 if(!Grouped)
1166 {
1167 ColorRGBA aColors[ms_MaxQuadsPossible];
1168 vec2 aOffsets[ms_MaxQuadsPossible];
1169 float aRotations[ms_MaxQuadsPossible];
1170
1171 while(QuadsLeft > 0)
1172 {
1173 int ActualQuadCount = minimum<int>(a: QuadsLeft, b: m_MaxQuadsAtOnce);
1174 for(size_t i = 0; i < (size_t)ActualQuadCount; ++i)
1175 {
1176 aColors[i] = pCommand->m_pQuadInfo[i + QuadOffset].m_Color;
1177 aOffsets[i] = pCommand->m_pQuadInfo[i + QuadOffset].m_Offsets;
1178 aRotations[i] = pCommand->m_pQuadInfo[i + QuadOffset].m_Rotation;
1179 }
1180
1181 pProgram->SetUniformVec4(Loc: pProgram->m_LocColors, Count: ActualQuadCount, pValue: (float *)aColors);
1182 pProgram->SetUniformVec2(Loc: pProgram->m_LocOffsets, Count: ActualQuadCount, pValue: (float *)aOffsets);
1183 pProgram->SetUniform(Loc: pProgram->m_LocRotations, Count: ActualQuadCount, pValues: (float *)aRotations);
1184 pProgram->SetUniform(Loc: pProgram->m_LocQuadOffset, Value: (int)(QuadOffset + QuadOffsetExtra));
1185 glDrawElements(GL_TRIANGLES, count: ActualQuadCount * 6, GL_UNSIGNED_INT, indices: (void *)((QuadOffset + QuadOffsetExtra) * 6 * sizeof(unsigned int)));
1186
1187 QuadsLeft -= ActualQuadCount;
1188 QuadOffset += (size_t)ActualQuadCount;
1189 }
1190 }
1191 else
1192 {
1193 ColorRGBA Colors = pCommand->m_pQuadInfo[0].m_Color;
1194 vec2 Offsets = pCommand->m_pQuadInfo[0].m_Offsets;
1195 float Rotations = pCommand->m_pQuadInfo[0].m_Rotation;
1196
1197 pProgram->SetUniformVec4(Loc: pProgram->m_LocColors, Count: 1, pValue: (float *)(&Colors));
1198 pProgram->SetUniformVec2(Loc: pProgram->m_LocOffsets, Count: 1, pValue: (float *)(&Offsets));
1199 pProgram->SetUniform(Loc: pProgram->m_LocRotations, Count: 1, pValues: &Rotations);
1200 glDrawElements(GL_TRIANGLES, count: QuadsLeft * 6, GL_UNSIGNED_INT, indices: (void *)((QuadOffset + QuadOffsetExtra) * 6 * sizeof(unsigned int)));
1201 }
1202}
1203
1204void CCommandProcessorFragment_OpenGL3_3::RenderText(const CCommandBuffer::SState &State, int DrawNum, int TextTextureIndex, int TextOutlineTextureIndex, int TextureSize, const ColorRGBA &TextColor, const ColorRGBA &TextOutlineColor)
1205{
1206 if(DrawNum == 0)
1207 {
1208 return; // nothing to draw
1209 }
1210
1211 UseProgram(pProgram: m_pTextProgram);
1212
1213 int SlotText = 0;
1214 int SlotTextOutline = 1;
1215 glBindTexture(GL_TEXTURE_2D, texture: m_vTextures[TextTextureIndex].m_Tex);
1216 glBindSampler(SlotText, m_vTextures[TextTextureIndex].m_Sampler);
1217 glActiveTexture(GL_TEXTURE1);
1218 glBindTexture(GL_TEXTURE_2D, texture: m_vTextures[TextOutlineTextureIndex].m_Tex);
1219 glBindSampler(SlotTextOutline, m_vTextures[TextOutlineTextureIndex].m_Sampler);
1220 glActiveTexture(GL_TEXTURE0);
1221
1222 if(m_pTextProgram->m_LastTextSampler != SlotText)
1223 {
1224 m_pTextProgram->SetUniform(Loc: m_pTextProgram->m_LocTextSampler, Value: SlotText);
1225 m_pTextProgram->m_LastTextSampler = SlotText;
1226 }
1227
1228 if(m_pTextProgram->m_LastTextOutlineSampler != SlotTextOutline)
1229 {
1230 m_pTextProgram->SetUniform(Loc: m_pTextProgram->m_LocTextOutlineSampler, Value: SlotTextOutline);
1231 m_pTextProgram->m_LastTextOutlineSampler = SlotTextOutline;
1232 }
1233
1234 SetState(State, pProgram: m_pTextProgram);
1235
1236 if(m_pTextProgram->m_LastTextureSize != TextureSize)
1237 {
1238 m_pTextProgram->SetUniform(Loc: m_pTextProgram->m_LocTextureSize, Value: (float)TextureSize);
1239 m_pTextProgram->m_LastTextureSize = TextureSize;
1240 }
1241
1242 if(m_pTextProgram->m_LastOutlineColor != TextOutlineColor)
1243 {
1244 m_pTextProgram->SetUniformVec4(Loc: m_pTextProgram->m_LocOutlineColor, Count: 1, pValue: (float *)&TextOutlineColor);
1245 m_pTextProgram->m_LastOutlineColor = TextOutlineColor;
1246 }
1247
1248 if(m_pTextProgram->m_LastColor != TextColor)
1249 {
1250 m_pTextProgram->SetUniformVec4(Loc: m_pTextProgram->m_LocColor, Count: 1, pValue: (float *)&TextColor);
1251 m_pTextProgram->m_LastColor = TextColor;
1252 }
1253
1254 glDrawElements(GL_TRIANGLES, count: DrawNum, GL_UNSIGNED_INT, indices: (void *)(0));
1255}
1256
1257void CCommandProcessorFragment_OpenGL3_3::Cmd_RenderText(const CCommandBuffer::SCommand_RenderText *pCommand)
1258{
1259 int Index = pCommand->m_BufferContainerIndex;
1260 // if space not there return
1261 if((size_t)Index >= m_vBufferContainers.size())
1262 return;
1263
1264 SBufferContainer &BufferContainer = m_vBufferContainers[Index];
1265 if(BufferContainer.m_VertArrayId == 0)
1266 return;
1267
1268 glBindVertexArray(BufferContainer.m_VertArrayId);
1269 if(BufferContainer.m_LastIndexBufferBound != m_QuadDrawIndexBufferId)
1270 {
1271 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_QuadDrawIndexBufferId);
1272 BufferContainer.m_LastIndexBufferBound = m_QuadDrawIndexBufferId;
1273 }
1274
1275 RenderText(State: pCommand->m_State, DrawNum: pCommand->m_DrawNum, TextTextureIndex: pCommand->m_TextTextureIndex, TextOutlineTextureIndex: pCommand->m_TextOutlineTextureIndex, TextureSize: pCommand->m_TextureSize, TextColor: pCommand->m_TextColor, TextOutlineColor: pCommand->m_TextOutlineColor);
1276}
1277
1278void CCommandProcessorFragment_OpenGL3_3::Cmd_RenderQuadContainer(const CCommandBuffer::SCommand_RenderQuadContainer *pCommand)
1279{
1280 if(pCommand->m_DrawNum == 0)
1281 {
1282 return; // nothing to draw
1283 }
1284
1285 int Index = pCommand->m_BufferContainerIndex;
1286 // if space not there return
1287 if((size_t)Index >= m_vBufferContainers.size())
1288 return;
1289
1290 SBufferContainer &BufferContainer = m_vBufferContainers[Index];
1291 if(BufferContainer.m_VertArrayId == 0)
1292 return;
1293
1294 glBindVertexArray(BufferContainer.m_VertArrayId);
1295 if(BufferContainer.m_LastIndexBufferBound != m_QuadDrawIndexBufferId)
1296 {
1297 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_QuadDrawIndexBufferId);
1298 BufferContainer.m_LastIndexBufferBound = m_QuadDrawIndexBufferId;
1299 }
1300
1301 CGLSLTWProgram *pProgram = m_pPrimitiveProgram;
1302 if(IsTexturedState(State: pCommand->m_State))
1303 pProgram = m_pPrimitiveProgramTextured;
1304 UseProgram(pProgram);
1305 SetState(State: pCommand->m_State, pProgram);
1306
1307 glDrawElements(GL_TRIANGLES, count: pCommand->m_DrawNum, GL_UNSIGNED_INT, indices: pCommand->m_pOffset);
1308}
1309
1310void CCommandProcessorFragment_OpenGL3_3::Cmd_RenderQuadContainerEx(const CCommandBuffer::SCommand_RenderQuadContainerEx *pCommand)
1311{
1312 if(pCommand->m_DrawNum == 0)
1313 {
1314 return; // nothing to draw
1315 }
1316
1317 int Index = pCommand->m_BufferContainerIndex;
1318 // if space not there return
1319 if((size_t)Index >= m_vBufferContainers.size())
1320 return;
1321
1322 SBufferContainer &BufferContainer = m_vBufferContainers[Index];
1323 if(BufferContainer.m_VertArrayId == 0)
1324 return;
1325
1326 glBindVertexArray(BufferContainer.m_VertArrayId);
1327 if(BufferContainer.m_LastIndexBufferBound != m_QuadDrawIndexBufferId)
1328 {
1329 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_QuadDrawIndexBufferId);
1330 BufferContainer.m_LastIndexBufferBound = m_QuadDrawIndexBufferId;
1331 }
1332
1333 CGLSLPrimitiveExProgram *pProgram = m_pPrimitiveExProgramRotationless;
1334 if(IsTexturedState(State: pCommand->m_State))
1335 {
1336 if(pCommand->m_Rotation != 0.0f)
1337 pProgram = m_pPrimitiveExProgramTextured;
1338 else
1339 pProgram = m_pPrimitiveExProgramTexturedRotationless;
1340 }
1341 else
1342 {
1343 if(pCommand->m_Rotation != 0.0f)
1344 pProgram = m_pPrimitiveExProgram;
1345 }
1346
1347 UseProgram(pProgram);
1348 SetState(State: pCommand->m_State, pProgram);
1349
1350 if(pCommand->m_Rotation != 0.0f && pProgram->m_LastCenter != pCommand->m_Center)
1351 {
1352 pProgram->SetUniformVec2(Loc: pProgram->m_LocCenter, Count: 1, pValue: (float *)&pCommand->m_Center);
1353 pProgram->m_LastCenter = pCommand->m_Center;
1354 }
1355
1356 if(pProgram->m_LastRotation != pCommand->m_Rotation)
1357 {
1358 pProgram->SetUniform(Loc: pProgram->m_LocRotation, Value: pCommand->m_Rotation);
1359 pProgram->m_LastRotation = pCommand->m_Rotation;
1360 }
1361
1362 if(pProgram->m_LastVerticesColor != pCommand->m_VertexColor)
1363 {
1364 pProgram->SetUniformVec4(Loc: pProgram->m_LocVertciesColor, Count: 1, pValue: (float *)&pCommand->m_VertexColor);
1365 pProgram->m_LastVerticesColor = pCommand->m_VertexColor;
1366 }
1367
1368 glDrawElements(GL_TRIANGLES, count: pCommand->m_DrawNum, GL_UNSIGNED_INT, indices: pCommand->m_pOffset);
1369}
1370
1371void CCommandProcessorFragment_OpenGL3_3::Cmd_RenderQuadContainerAsSpriteMultiple(const CCommandBuffer::SCommand_RenderQuadContainerAsSpriteMultiple *pCommand)
1372{
1373 if(pCommand->m_DrawNum == 0 || pCommand->m_DrawCount == 0)
1374 {
1375 return; // nothing to draw
1376 }
1377
1378 int Index = pCommand->m_BufferContainerIndex;
1379 // if space not there return
1380 if((size_t)Index >= m_vBufferContainers.size())
1381 return;
1382
1383 SBufferContainer &BufferContainer = m_vBufferContainers[Index];
1384 if(BufferContainer.m_VertArrayId == 0)
1385 return;
1386
1387 glBindVertexArray(BufferContainer.m_VertArrayId);
1388 if(BufferContainer.m_LastIndexBufferBound != m_QuadDrawIndexBufferId)
1389 {
1390 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_QuadDrawIndexBufferId);
1391 BufferContainer.m_LastIndexBufferBound = m_QuadDrawIndexBufferId;
1392 }
1393
1394 UseProgram(pProgram: m_pSpriteProgramMultiple);
1395 SetState(State: pCommand->m_State, pProgram: m_pSpriteProgramMultiple);
1396
1397 if(m_pSpriteProgramMultiple->m_LastCenter != pCommand->m_Center)
1398 {
1399 m_pSpriteProgramMultiple->SetUniformVec2(Loc: m_pSpriteProgramMultiple->m_LocCenter, Count: 1, pValue: (float *)&pCommand->m_Center);
1400 m_pSpriteProgramMultiple->m_LastCenter = pCommand->m_Center;
1401 }
1402
1403 if(m_pSpriteProgramMultiple->m_LastVerticesColor != pCommand->m_VertexColor)
1404 {
1405 m_pSpriteProgramMultiple->SetUniformVec4(Loc: m_pSpriteProgramMultiple->m_LocVertciesColor, Count: 1, pValue: (float *)&pCommand->m_VertexColor);
1406 m_pSpriteProgramMultiple->m_LastVerticesColor = pCommand->m_VertexColor;
1407 }
1408
1409 int DrawCount = pCommand->m_DrawCount;
1410 size_t RenderOffset = 0;
1411
1412 // 4 for the center (always use vec4) and 16 for the matrix(just to be sure), 4 for the sampler and vertex color
1413 const int RSPCount = 256 - 4 - 16 - 8;
1414
1415 while(DrawCount > 0)
1416 {
1417 int UniformCount = (DrawCount > RSPCount ? RSPCount : DrawCount);
1418
1419 m_pSpriteProgramMultiple->SetUniformVec4(Loc: m_pSpriteProgramMultiple->m_LocRSP, Count: UniformCount, pValue: (float *)(pCommand->m_pRenderInfo + RenderOffset));
1420
1421 glDrawElementsInstanced(GL_TRIANGLES, pCommand->m_DrawNum, GL_UNSIGNED_INT, pCommand->m_pOffset, UniformCount);
1422
1423 RenderOffset += RSPCount;
1424 DrawCount -= RSPCount;
1425 }
1426}
1427
1428#endif
1429