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