1 /*
2  * Copyright (C) Volition, Inc. 1999.  All rights reserved.
3  *
4  * All source code herein is the property of Volition, Inc. You may not sell
5  * or otherwise commercially exploit the source or things you created based on the
6  * source.
7  *
8 */
9 
10 
11 #include "gropenglshader.h"
12 #include "graphics/material.h"
13 #include "gropenglstate.h"
14 #include "math/vecmat.h"
15 
16 extern GLfloat GL_max_anisotropy;
17 
18 
19 opengl_state GL_state;
20 
21 
~opengl_texture_state()22 opengl_texture_state::~opengl_texture_state()
23 {
24 	if (units != NULL) {
25 		vm_free(units);
26 	}
27 }
28 
init(GLuint n_units)29 void opengl_texture_state::init(GLuint n_units)
30 {
31 	Assert( n_units > 0 );
32 	units = (opengl_texture_unit*) vm_malloc(n_units * sizeof(opengl_texture_unit));
33 	num_texture_units = n_units;
34 
35 	for (unsigned int unit = 0; unit < num_texture_units; unit++) {
36 		units[unit].enabled = GL_FALSE;
37 
38 		default_values(unit);
39 
40 		glActiveTexture(GL_TEXTURE0 + unit);
41 	}
42 
43 	SetActiveUnit();
44 }
45 
default_values(GLint unit,GLenum target)46 void opengl_texture_state::default_values(GLint unit, GLenum target)
47 {
48 	glActiveTexture(GL_TEXTURE0 + unit);
49 
50 	if (target == GL_INVALID_ENUM) {
51 
52 		glBindTexture(GL_TEXTURE_2D, 0);
53 		glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
54 
55 		units[unit].texture_target = GL_TEXTURE_2D;
56 		units[unit].texture_id = 0;
57 	}
58 }
59 
SetTarget(GLenum tex_target)60 void opengl_texture_state::SetTarget(GLenum tex_target)
61 {
62 	if (units[active_texture_unit].texture_target != tex_target) {
63 
64 		if (units[active_texture_unit].texture_id) {
65 			glBindTexture(units[active_texture_unit].texture_target, 0);
66 			units[active_texture_unit].texture_id = 0;
67 		}
68 
69 		// reset modes, since those were only valid for the previous texture target
70 		default_values(active_texture_unit, tex_target);
71 		units[active_texture_unit].texture_target = tex_target;
72 	}
73 }
74 
SetActiveUnit(GLuint id)75 void opengl_texture_state::SetActiveUnit(GLuint id)
76 {
77 	if (id >= num_texture_units) {
78 		Int3();
79 		id = 0;
80 	}
81 
82 	glActiveTexture(GL_TEXTURE0 + id);
83 
84 	active_texture_unit = id;
85 }
86 
Enable(GLuint tex_id)87 void opengl_texture_state::Enable(GLuint tex_id)
88 {
89 	if ( units[active_texture_unit].texture_id == tex_id ) {
90 		return;
91 	}
92 
93 	if (units[active_texture_unit].texture_id != tex_id) {
94 		glBindTexture(units[active_texture_unit].texture_target, tex_id);
95 		units[active_texture_unit].texture_id = tex_id;
96 	}
97 }
98 
Enable(GLuint unit,GLenum tex_target,GLuint tex_id)99 void opengl_texture_state::Enable(GLuint unit, GLenum tex_target, GLuint tex_id) {
100 	Assertion(unit < num_texture_units, "Invalid texture unit value!");
101 
102 	if (units[unit].texture_target == tex_target && units[unit].texture_id == tex_id) {
103 		// The texture unit already uses this texture. There is no need to change it
104 		return;
105 	}
106 
107 	// Go the standard route
108 	SetActiveUnit(unit);
109 	SetTarget(tex_target);
110 	Enable(tex_id);
111 }
112 
Delete(GLuint tex_id)113 void opengl_texture_state::Delete(GLuint tex_id)
114 {
115 	if (tex_id == 0) {
116 		Int3();
117 		return;
118 	}
119 
120 	GLuint atu_save = active_texture_unit;
121 
122 	for (unsigned int i = 0; i < num_texture_units; i++) {
123 		if (units[i].texture_id == tex_id) {
124 			SetActiveUnit(i);
125 
126 			glBindTexture(units[i].texture_target, 0);
127 			units[i].texture_id = 0;
128 
129 			default_values(i, units[i].texture_target);
130 
131 			if (i == atu_save) {
132 				atu_save = 0;
133 			}
134 		}
135 	}
136 
137 	SetActiveUnit(atu_save);
138 }
139 
init()140 void opengl_state::init()
141 {
142 	int i;
143 
144 	glDisable(GL_BLEND);
145 	blend_Status = GL_FALSE;
146 
147 	glDisable(GL_DEPTH_TEST);
148 	depthtest_Status = GL_FALSE;
149 
150 	glDisable(GL_SCISSOR_TEST);
151 	scissortest_Status = GL_FALSE;
152 
153 	glDisable(GL_CULL_FACE);
154 	cullface_Status = GL_FALSE;
155 
156 	glDisable(GL_POLYGON_OFFSET_FILL);
157 	polygonoffsetfill_Status = GL_FALSE;
158 
159 	polygon_offset_Factor = 0.0f;
160 	polygon_offset_Unit = 0.0f;
161 
162 	normalize_Status = GL_FALSE;
163 
164 	for (i = 0; i < (int)(sizeof(clipplane_Status) / sizeof(GLboolean)); i++) {
165 		//glDisable(GL_CLIP_PLANE0+i);
166 		clipplane_Status[i] = GL_FALSE;
167 	}
168 
169 	for (i = 0; i < (int)(sizeof(clipdistance_Status) / sizeof(GLboolean)); i++) {
170 		//glDisable(GL_CLIP_DISTANCE0+i);
171 		clipdistance_Status[i] = GL_FALSE;
172 	}
173 
174 	glDepthMask(GL_FALSE);
175 	depthmask_Status = GL_FALSE;
176 
177 	glFrontFace(GL_CCW);
178 	frontface_Value = GL_CCW;
179 
180 	glCullFace(GL_BACK);
181 	cullface_Value = GL_BACK;
182 
183 	glBlendFunc(GL_ONE, GL_ZERO);
184 	blendfunc_Value.first = GL_ONE;
185 	blendfunc_Value.first = GL_ZERO;
186 	buffer_blendfunc_Value.fill(blendfunc_Value);
187 
188 	glDepthFunc(GL_LESS);
189 	depthfunc_Value = GL_LESS;
190 
191 	glGetFloatv(GL_LINE_WIDTH, &line_width_Value);
192 
193 	current_program = 0;
194 	glUseProgram(0);
195 
196 	current_framebuffer = 0;
197 	glBindFramebuffer(GL_FRAMEBUFFER, 0);
198 
199 	framebuffer_stack.clear();
200 
201 	stencilFunc = GL_ALWAYS;
202 	stencilFuncRef = 0;
203 	stencilFuncMask = 0xFFFFFFFF;
204 	glStencilFunc(stencilFunc, stencilFuncRef, stencilFuncMask);
205 
206 	stencilMask = 0xFFFFFFFF;
207 	glStencilMask(stencilMask);
208 
209 	stencilOpFrontStencilFail = GL_KEEP;
210 	stencilOpFrontDepthFail = GL_KEEP;
211 	stencilOpFrontPass = GL_KEEP;
212 
213 	stencilOpBackStencilFail = GL_KEEP;
214 	stencilOpBackDepthFail = GL_KEEP;
215 	stencilOpBackPass = GL_KEEP;
216 
217 	glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
218 
219 	colormask_Status.x = true;
220 	colormask_Status.y = true;
221 	colormask_Status.z = true;
222 	colormask_Status.w = true;
223 	glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
224 }
225 
Blend(GLint state)226 GLboolean opengl_state::Blend(GLint state)
227 {
228 	GLboolean save_state = blend_Status;
229 
230 	if ( !((state == -1) || (state == blend_Status)) ) {
231 		if (state) {
232 			Assert( state == GL_TRUE );
233 			glEnable(GL_BLEND);
234 			blend_Status = GL_TRUE;
235 		} else {
236 			glDisable(GL_BLEND);
237 			blend_Status = GL_FALSE;
238 		}
239 	}
240 
241 	return save_state;
242 }
243 
DepthTest(GLint state)244 GLboolean opengl_state::DepthTest(GLint state)
245 {
246 	GLboolean save_state = depthtest_Status;
247 
248 	if ( !((state == -1) || (state == depthtest_Status)) ) {
249 		if (state) {
250 			Assert( state == GL_TRUE );
251 			glEnable(GL_DEPTH_TEST);
252 			depthtest_Status = GL_TRUE;
253 		} else {
254 			glDisable(GL_DEPTH_TEST);
255 			depthtest_Status = GL_FALSE;
256 		}
257 	}
258 
259 	return save_state;
260 }
261 
ScissorTest(GLint state)262 GLboolean opengl_state::ScissorTest(GLint state)
263 {
264 	GLboolean save_state = scissortest_Status;
265 
266 	if ( !((state == -1) || (state == scissortest_Status)) ) {
267 		if (state) {
268 			Assert( state == GL_TRUE );
269 			glEnable(GL_SCISSOR_TEST);
270 			scissortest_Status = GL_TRUE;
271 		} else {
272 			glDisable(GL_SCISSOR_TEST);
273 			scissortest_Status = GL_FALSE;
274 		}
275 	}
276 
277 	return save_state;
278 }
279 
StencilTest(GLint state)280 GLboolean opengl_state::StencilTest(GLint state)
281 {
282     GLboolean save_state = stenciltest_Status;
283 
284     if ( !((state == -1) || (state == stenciltest_Status)) ) {
285         if (state) {
286             Assert( state == GL_TRUE );
287             glEnable(GL_STENCIL_TEST);
288             stenciltest_Status = GL_TRUE;
289         } else {
290             glDisable(GL_STENCIL_TEST);
291             stenciltest_Status = GL_FALSE;
292         }
293     }
294 
295     return save_state;
296 }
297 
CullFace(GLint state)298 GLboolean opengl_state::CullFace(GLint state)
299 {
300 	GLboolean save_state = cullface_Status;
301 
302 	if ( !((state == -1) || (state == cullface_Status)) ) {
303 		if (state) {
304 			Assert( state == GL_TRUE );
305 			glEnable(GL_CULL_FACE);
306 			cullface_Status = GL_TRUE;
307 		} else {
308 			glDisable(GL_CULL_FACE);
309 			cullface_Status = GL_FALSE;
310 		}
311 	}
312 
313 	return save_state;
314 }
315 
SetPolygonMode(GLenum face,GLenum mode)316 void opengl_state::SetPolygonMode(GLenum face, GLenum mode)
317 {
318 	if ( polygon_mode_Face != face || polygon_mode_Mode != mode ) {
319 		glPolygonMode(face, mode);
320 
321 		polygon_mode_Face = face;
322 		polygon_mode_Mode = mode;
323 	}
324 }
325 
SetPolygonOffset(GLfloat factor,GLfloat units)326 void opengl_state::SetPolygonOffset(GLfloat factor, GLfloat units)
327 {
328 	if ( polygon_offset_Factor != factor || polygon_offset_Unit != units) {
329 		glPolygonOffset(factor, units);
330 
331 		polygon_offset_Factor = factor;
332 		polygon_offset_Unit = units;
333 	}
334 }
335 
PolygonOffsetFill(GLint state)336 GLboolean opengl_state::PolygonOffsetFill(GLint state)
337 {
338 	GLboolean save_state = polygonoffsetfill_Status;
339 
340 	if ( !((state == -1) || (state == polygonoffsetfill_Status)) ) {
341 		if (state) {
342 			Assert( state == GL_TRUE );
343 			glEnable(GL_POLYGON_OFFSET_FILL);
344 			polygonoffsetfill_Status = GL_TRUE;
345 		} else {
346 			glDisable(GL_POLYGON_OFFSET_FILL);
347 			polygonoffsetfill_Status = GL_FALSE;
348 		}
349 	}
350 
351 	return save_state;
352 }
353 
ClipDistance(GLint num,bool state)354 GLboolean opengl_state::ClipDistance(GLint num, bool state)
355 {
356 	Assert( (num >= 0) && (num < (int)(sizeof(clipdistance_Status) / sizeof(GLboolean))) );
357 
358 	GLboolean save_state = clipdistance_Status[num];
359 
360 	if (state != clipdistance_Status[num]) {
361 		if (state) {
362 			glEnable(GL_CLIP_DISTANCE0+num);
363 		} else {
364 			glDisable(GL_CLIP_DISTANCE0+num);
365 		}
366 		clipdistance_Status[num] = state;
367 	}
368 
369 	return save_state;
370 }
371 
DepthMask(GLint state)372 GLboolean opengl_state::DepthMask(GLint state)
373 {
374 	GLboolean save_state = depthmask_Status;
375 
376 	if ( !((state == -1) || (state == depthmask_Status)) ) {
377 		if (state) {
378 			Assert( state == GL_TRUE );
379 			glDepthMask(GL_TRUE);
380 			depthmask_Status = GL_TRUE;
381 		} else {
382 			glDepthMask(GL_FALSE);
383 			depthmask_Status = GL_FALSE;
384 		}
385 	}
386 
387 	return save_state;
388 }
389 
ColorMask(bool red,bool green,bool blue,bool alpha)390 bvec4 opengl_state::ColorMask(bool red, bool green, bool blue, bool alpha)
391 {
392     auto save_state = colormask_Status;
393 
394 	if (colormask_Status.x != red || colormask_Status.y != green || colormask_Status.z != blue
395 		|| colormask_Status.w != alpha) {
396 		glColorMask(red ? GL_TRUE : GL_FALSE,
397 					green ? GL_TRUE : GL_FALSE,
398 					blue ? GL_TRUE : GL_FALSE,
399 					alpha ? GL_TRUE : GL_FALSE);
400 		colormask_Status = { red, green, blue, alpha };
401     }
402 
403     return save_state;
404 }
405 
BlendFunc(GLenum s_val,GLenum d_val)406 void opengl_state::BlendFunc(GLenum s_val, GLenum d_val)
407 {
408 	if (s_val != blendfunc_Value.first || d_val != blendfunc_Value.second) {
409 		glBlendFunc(s_val, d_val);
410 		blendfunc_Value.first = s_val;
411 		blendfunc_Value.second = d_val;
412 
413 		// This has set all the buffer blend modes as well
414 		buffer_blendfunc_Value.fill(blendfunc_Value);
415 	}
416 }
BlendFunci(int buffer,GLenum s_val,GLenum d_val)417 void opengl_state::BlendFunci(int buffer, GLenum s_val, GLenum d_val) {
418 	Assertion(GLAD_GL_ARB_draw_buffers_blend != 0, "Buffer blend modes are not supported by this OpenGL implementation!");
419 	Assertion(buffer >= 0 && buffer < (int) buffer_blendfunc_Value.size(), "Unsupported index %d specified for buffer blend mode!", buffer);
420 
421 	auto& state = buffer_blendfunc_Value[buffer];
422 	if (state.first == s_val && state.second == d_val) {
423 		// Already uses the correct blend mode
424 		return;
425 	}
426 
427 	glBlendFunciARB(buffer, s_val, d_val);
428 
429 	// Update the saved state
430 	state.first = s_val;
431 	state.second = d_val;
432 	// Set the non-buffer values to an invalid value to make sure that the next call to BlendFunc resets the state.
433 	blendfunc_Value.first = GL_INVALID_ENUM;
434 	blendfunc_Value.second = GL_INVALID_ENUM;
435 }
436 
SetAlphaBlendMode(gr_alpha_blend ab)437 void opengl_state::SetAlphaBlendMode(gr_alpha_blend ab)
438 {
439 	switch (ab) {
440 		case ALPHA_BLEND_ALPHA_BLEND_ALPHA:
441 			GL_state.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
442 			break;
443 
444 		case ALPHA_BLEND_NONE:
445 			GL_state.BlendFunc(GL_ONE, GL_ZERO);
446 			break;
447 
448 		case ALPHA_BLEND_ADDITIVE:
449 			GL_state.BlendFunc(GL_ONE, GL_ONE);
450 			break;
451 
452 		case ALPHA_BLEND_ALPHA_ADDITIVE:
453 			GL_state.BlendFunc(GL_SRC_ALPHA, GL_ONE);
454 			break;
455 
456 		case ALPHA_BLEND_ALPHA_BLEND_SRC_COLOR:
457 			GL_state.BlendFunc(/*GL_SRC_COLOR*/GL_SRC_ALPHA, GL_ONE_MINUS_SRC_COLOR);
458 			break;
459 
460 		case ALPHA_BLEND_PREMULTIPLIED:
461 			GL_state.BlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
462 			break;
463 
464 		default:
465 			break;
466 	}
467 
468 	GL_state.Blend( (ab == ALPHA_BLEND_NONE) ? GL_FALSE : GL_TRUE );
469 }
470 
SetAlphaBlendModei(int buffer,gr_alpha_blend ab)471 void opengl_state::SetAlphaBlendModei(int buffer, gr_alpha_blend ab)
472 {
473 	switch (ab) {
474 	case ALPHA_BLEND_ALPHA_BLEND_ALPHA:
475 		GL_state.BlendFunci(buffer, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
476 		break;
477 
478 	case ALPHA_BLEND_NONE:
479 		GL_state.BlendFunci(buffer, GL_ONE, GL_ZERO);
480 		break;
481 
482 	case ALPHA_BLEND_ADDITIVE:
483 		GL_state.BlendFunci(buffer, GL_ONE, GL_ONE);
484 		break;
485 
486 	case ALPHA_BLEND_ALPHA_ADDITIVE:
487 		GL_state.BlendFunci(buffer, GL_SRC_ALPHA, GL_ONE);
488 		break;
489 
490 	case ALPHA_BLEND_ALPHA_BLEND_SRC_COLOR:
491 		GL_state.BlendFunci(buffer, /*GL_SRC_COLOR*/GL_SRC_ALPHA, GL_ONE_MINUS_SRC_COLOR);
492 		break;
493 
494 	case ALPHA_BLEND_PREMULTIPLIED:
495 		GL_state.BlendFunci(buffer, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
496 		break;
497 
498 	default:
499 		break;
500 	}
501 }
502 
SetZbufferType(gr_zbuffer_type zt)503 void opengl_state::SetZbufferType(gr_zbuffer_type zt)
504 {
505 	switch (zt) {
506 		case ZBUFFER_TYPE_NONE:
507 			GL_state.DepthFunc(GL_ALWAYS);
508 			GL_state.DepthMask(GL_FALSE);
509 			break;
510 
511 		case ZBUFFER_TYPE_READ:
512 			GL_state.DepthFunc(GL_LESS);
513 			GL_state.DepthMask(GL_FALSE);
514 			break;
515 
516 		case ZBUFFER_TYPE_WRITE:
517 			GL_state.DepthFunc(GL_ALWAYS);
518 			GL_state.DepthMask(GL_TRUE);
519 			break;
520 
521 		case ZBUFFER_TYPE_FULL:
522 			GL_state.DepthFunc(GL_LESS);
523 			GL_state.DepthMask(GL_TRUE);
524 			break;
525 
526 		default:
527 			break;
528 	}
529 
530 	GL_state.DepthTest( (zt == ZBUFFER_TYPE_NONE) ? GL_FALSE : GL_TRUE );
531 }
532 
SetLineWidth(GLfloat width)533 void opengl_state::SetLineWidth(GLfloat width)
534 {
535 	if ( width == line_width_Value ) {
536 		return;
537 	}
538 
539 	glLineWidth(width);
540 	line_width_Value = width;
541 }
UseProgram(GLuint program)542 void opengl_state::UseProgram(GLuint program)
543 {
544 	if (current_program == program) {
545 		return;
546 	}
547 
548 	current_program = program;
549 	glUseProgram(program);
550 }
IsCurrentProgram(GLuint program)551 bool opengl_state::IsCurrentProgram(GLuint program) {
552 	return current_program == program;
553 }
BindFrameBuffer(GLuint name)554 void opengl_state::BindFrameBuffer(GLuint name) {
555 	if (current_framebuffer != name) {
556 		glBindFramebuffer(GL_FRAMEBUFFER, name);
557 		current_framebuffer = name;
558 	}
559 }
PushFramebufferState()560 void opengl_state::PushFramebufferState() {
561 	framebuffer_stack.push_back(current_framebuffer);
562 }
PopFramebufferState()563 void opengl_state::PopFramebufferState() {
564 	Assertion(framebuffer_stack.size() > 0, "Tried to pop the framebuffer state stack while it was empty!");
565 
566 	auto restoreBuffer = framebuffer_stack.back();
567 	framebuffer_stack.pop_back();
568 
569 	BindFrameBuffer(restoreBuffer);
570 }
BindVertexArray(GLuint vao)571 void opengl_state::BindVertexArray(GLuint vao) {
572 	if (current_vao == vao) {
573 		return;
574 	}
575 
576 	glBindVertexArray(vao);
577 	current_vao = vao;
578 
579 	Array.VertexArrayChanged();
580 }
StencilFunc(GLenum func,GLint ref,GLuint mask)581 void opengl_state::StencilFunc(GLenum func, GLint ref, GLuint mask) {
582 	if (stencilFunc == func && stencilFuncRef == ref && stencilFuncMask == mask) {
583 		return;
584 	}
585 
586 	glStencilFunc(func, ref, mask);
587 
588 	stencilFunc = func;
589 	stencilFuncRef = ref;
590 	stencilFuncMask = mask;
591 }
StencilOpSeparate(GLenum face,GLenum sfail,GLenum dpfail,GLenum dppass)592 void opengl_state::StencilOpSeparate(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass) {
593 	if (face == GL_FRONT_AND_BACK) {
594 		StencilOpSeparate(GL_FRONT, sfail, dpfail, dppass);
595 		StencilOpSeparate(GL_BACK, sfail, dpfail, dppass);
596 		return;
597 	}
598 
599 	if (face == GL_FRONT) {
600 		if (stencilOpFrontStencilFail == sfail && stencilOpFrontDepthFail == dpfail && stencilOpFrontPass == dppass) {
601 			return;
602 		}
603 
604 		glStencilOpSeparate(GL_FRONT, sfail, dpfail, dppass);
605 
606 		stencilOpFrontStencilFail = sfail;
607 		stencilOpFrontDepthFail = dpfail;
608 		stencilOpFrontPass = dppass;
609 	} else {
610 		if (stencilOpBackStencilFail == sfail && stencilOpBackDepthFail == dpfail && stencilOpBackPass == dppass) {
611 			return;
612 		}
613 
614 		glStencilOpSeparate(GL_BACK, sfail, dpfail, dppass);
615 
616 		stencilOpBackStencilFail = sfail;
617 		stencilOpBackDepthFail = dpfail;
618 		stencilOpBackPass = dppass;
619 	}
620 }
StencilMask(GLuint mask)621 void opengl_state::StencilMask(GLuint mask) {
622 	if (stencilMask == mask) {
623 		return;
624 	}
625 
626 	glStencilMask(mask);
627 	stencilMask = mask;
628 }
629 
~opengl_array_state()630 opengl_array_state::~opengl_array_state()
631 {
632 	if ( client_texture_units != NULL ) {
633 		vm_free(client_texture_units);
634 	}
635 }
636 
init(GLuint n_units)637 void opengl_array_state::init(GLuint n_units)
638 {
639 	Assert( n_units > 0 );
640 	client_texture_units = (opengl_client_texture_unit*) vm_malloc(n_units * sizeof(opengl_client_texture_unit));
641 	num_client_texture_units = n_units;
642 	active_client_texture_unit = 0;
643 
644 	for (unsigned int i = 0; i < num_client_texture_units; i++) {
645 		client_texture_units[i].pointer = 0;
646 		client_texture_units[i].size = 4;
647 		client_texture_units[i].status = GL_FALSE;
648 		client_texture_units[i].stride = 0;
649 		client_texture_units[i].type = GL_FLOAT;
650 		client_texture_units[i].buffer = 0;
651 		client_texture_units[i].reset_ptr = false;
652 		client_texture_units[i].used_for_draw = false;
653 	}
654 
655 	array_buffer = 0;
656 	element_array_buffer = 0;
657 	texture_array_buffer = 0;
658 	uniform_buffer = 0;
659 }
660 
EnableVertexAttrib(GLuint index)661 void opengl_array_state::EnableVertexAttrib(GLuint index)
662 {
663 	opengl_vertex_attrib_unit *va_unit = &vertex_attrib_units[index];
664 
665 	va_unit->used_for_draw = true;
666 
667 	if ( va_unit->status_init && va_unit->status == GL_TRUE ) {
668 		return;
669 	}
670 
671 	glEnableVertexAttribArray(index);
672 	va_unit->status = GL_TRUE;
673 	va_unit->status_init = true;
674 }
675 
DisableVertexAttrib(GLuint index)676 void opengl_array_state::DisableVertexAttrib(GLuint index)
677 {
678 	opengl_vertex_attrib_unit *va_unit = &vertex_attrib_units[index];
679 
680 	if ( va_unit->status_init && va_unit->status == GL_FALSE ) {
681 		return;
682 	}
683 
684 	glDisableVertexAttribArray(index);
685 	va_unit->status = GL_FALSE;
686 	va_unit->status_init = true;
687 }
688 
VertexAttribPointer(GLuint index,GLint size,GLenum type,GLboolean normalized,GLsizei stride,GLvoid * pointer)689 void opengl_array_state::VertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLvoid *pointer)
690 {
691 	opengl_vertex_attrib_unit *va_unit = &vertex_attrib_units[index];
692 
693 	if (
694 		!va_unit->reset_ptr
695 		&& va_unit->ptr_init
696 		&& va_unit->normalized == normalized
697 		&& va_unit->pointer == pointer
698 		&& va_unit->size == size
699 		&& va_unit->stride == stride
700 		&& va_unit->type == type
701 		&& va_unit->buffer == array_buffer
702 	) {
703 		return;
704 	}
705 
706 	glVertexAttribPointer(index, size, type, normalized, stride, pointer);
707 
708 	va_unit->normalized = normalized;
709 	va_unit->pointer = pointer;
710 	va_unit->size = size;
711 	va_unit->stride = stride;
712 	va_unit->type = type;
713 	va_unit->buffer = array_buffer;
714 	va_unit->reset_ptr = false;
715 
716 	va_unit->ptr_init = true;
717 }
718 
ResetVertexAttribs()719 void opengl_array_state::ResetVertexAttribs()
720 {
721 	for (auto &it : vertex_attrib_units) {
722 		DisableVertexAttrib(it.first);
723 	}
724 
725 	vertex_attrib_units.clear();
726 }
727 
BindPointersBegin()728 void opengl_array_state::BindPointersBegin()
729 {
730 	for (unsigned int i = 0; i < num_client_texture_units; i++) {
731 		client_texture_units[i].used_for_draw = false;
732 	}
733 
734 	for (auto &it : vertex_attrib_units) {
735 		it.second.used_for_draw = false;
736 	}
737 }
738 
BindPointersEnd()739 void opengl_array_state::BindPointersEnd()
740 {
741 	for (auto &it : vertex_attrib_units) {
742 		if (!it.second.used_for_draw) {
743 			DisableVertexAttrib(it.first);
744 		}
745 	}
746 }
747 
BindArrayBuffer(GLuint id)748 void opengl_array_state::BindArrayBuffer(GLuint id)
749 {
750 	if ( array_buffer_valid && array_buffer == id ) {
751 		return;
752 	}
753 
754 	glBindBuffer(GL_ARRAY_BUFFER, id);
755 
756 	array_buffer = id;
757 	array_buffer_valid = true;
758 
759 	for (unsigned int i = 0; i < num_client_texture_units; i++) {
760 		client_texture_units[i].reset_ptr = true;
761 	}
762 
763 	for (auto &it : vertex_attrib_units) {
764 		it.second.reset_ptr = true;
765 	}
766 }
767 
BindElementBuffer(GLuint id)768 void opengl_array_state::BindElementBuffer(GLuint id)
769 {
770 	if ( element_array_buffer_valid && element_array_buffer == id ) {
771 		return;
772 	}
773 
774 	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, id);
775 
776 	element_array_buffer = id;
777 	element_array_buffer_valid = true;
778 }
779 
BindTextureBuffer(GLuint id)780 void opengl_array_state::BindTextureBuffer(GLuint id)
781 {
782 	if ( texture_array_buffer == id ) {
783 		return;
784 	}
785 
786 	glBindBuffer(GL_TEXTURE_BUFFER, id);
787 
788 	texture_array_buffer = id;
789 }
790 
BindUniformBufferBindingIndex(GLuint id,GLuint index)791 void opengl_array_state::BindUniformBufferBindingIndex(GLuint id, GLuint index)
792 {
793 	if ( uniform_buffer_index_bindings[index] == id ) {
794 		return;
795 	}
796 
797 	glBindBufferBase(GL_UNIFORM_BUFFER, index, id);
798 
799 	uniform_buffer_index_bindings[index] = id;
800 }
801 
BindUniformBuffer(GLuint id)802 void opengl_array_state::BindUniformBuffer(GLuint id)
803 {
804 	if ( uniform_buffer == id ) {
805 		return;
806 	}
807 
808 	glBindBuffer(GL_UNIFORM_BUFFER, id);
809 
810 	uniform_buffer = id;
811 }
VertexArrayChanged()812 void opengl_array_state::VertexArrayChanged() {
813 	array_buffer_valid = false;
814 	element_array_buffer_valid = false;
815 
816 	for (auto& bindingInfo : vertex_buffer_bindings) {
817 		bindingInfo.valid_data = false;
818 	}
819 }
BindVertexBuffer(GLuint bindingindex,GLuint buffer,GLintptr offset,GLsizei stride)820 void opengl_array_state::BindVertexBuffer(GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride) {
821 	if (bindingindex >= vertex_buffer_bindings.size()) {
822 		// Make sure that we have the place for this information
823 		vertex_buffer_bindings.resize(bindingindex + 1);
824 	}
825 
826 	auto& bindingInfo = vertex_buffer_bindings[bindingindex];
827 
828 	if (bindingInfo.valid_data && bindingInfo.buffer == buffer && bindingInfo.offset == offset
829 		&& bindingInfo.stride == stride) {
830 		return;
831 	}
832 
833 	glBindVertexBuffer(bindingindex, buffer, offset, stride);
834 
835 	bindingInfo.valid_data = true;
836 	bindingInfo.buffer = buffer;
837 	bindingInfo.stride = stride;
838 	bindingInfo.offset = offset;
839 }
opengl_constant_state()840 opengl_constant_state::opengl_constant_state() {
841 }
init()842 void opengl_constant_state::init() {
843 	glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &_uniform_buffer_offset_alignment);
844 	glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &_max_uniform_block_size);
845 	glGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, &_max_uniform_block_bindings);
846 
847 	if (GLAD_GL_EXT_texture_filter_anisotropic) {
848 		glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &_max_anisotropy);
849 	} else {
850 		_max_anisotropy = -1.0f;
851 	}
852 }
GetUniformBufferOffsetAlignment()853 GLint opengl_constant_state::GetUniformBufferOffsetAlignment() {
854 	return _uniform_buffer_offset_alignment;
855 }
GetMaxUniformBlockSize()856 GLint opengl_constant_state::GetMaxUniformBlockSize() {
857 	return _max_uniform_block_size;
858 }
GetMaxUniformBlockBindings()859 GLint opengl_constant_state::GetMaxUniformBlockBindings() {
860 	return _max_uniform_block_bindings;
861 }
GetMaxAnisotropy()862 GLfloat opengl_constant_state::GetMaxAnisotropy() {
863 	return _max_anisotropy;
864 }
865 
gr_opengl_clear_states()866 void gr_opengl_clear_states()
867 {
868 	gr_zbias(0);
869 	gr_zbuffer_set(ZBUFFER_TYPE_READ);
870 	gr_set_cull(0);
871 	gr_set_fill_mode(GR_FILL_MODE_SOLID);
872 
873 	opengl_shader_set_current();
874 }
875