File: gropenglstate.h

package info (click to toggle)
freespace2 24.2.0%2Brepack-1
  • links: PTS, VCS
  • area: non-free
  • in suites: forky, sid
  • size: 43,716 kB
  • sloc: cpp: 595,001; ansic: 21,741; python: 1,174; sh: 457; makefile: 248; xml: 181
file content (342 lines) | stat: -rw-r--r-- 8,584 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
/*
 * Copyright (C) Volition, Inc. 1999.  All rights reserved.
 *
 * All source code herein is the property of Volition, Inc. You may not sell 
 * or otherwise commercially exploit the source or things you created based on the 
 * source.
 *
*/


#ifndef _GROPENGLSTATE_H
#define _GROPENGLSTATE_H

#include "globalincs/pstypes.h"
#include "gropengl.h"
#include "gropengltexture.h"
#include "gropenglshader.h"
#include "graphics/material.h"

#include <glad/glad.h>

#define MAX_UNIFORM_BUFFERS 6
#define MAX_UNIFORM_LOCATIONS 256

struct opengl_texture_unit {
	GLboolean enabled;	// has texture target enabled

	GLenum texture_target;
	GLuint texture_id;
};

class opengl_texture_state
{
	private:
		void default_values(GLint unit, GLenum target = GL_INVALID_ENUM);

		GLuint active_texture_unit;
		GLboolean shader_mode;

		opengl_texture_unit *units;
		GLuint num_texture_units;


	public:
		opengl_texture_state(): active_texture_unit(0), shader_mode(GL_FALSE), units(NULL) {}
		~opengl_texture_state();
		
		void init(GLuint n_units);

		void SetTarget(GLenum tex_target);
		void SetActiveUnit(GLuint id = 0);
		void Enable(GLuint tex_id = 0);
		/**
		 * @brief Directly enables a texture on the specified unit
		 *
		 * This is a more efficient version of the standard activeTexture -> Enable since it does not cause an
		 * OpenGL call if the texture is already set correctly
		 *
		 * @warning This may not actually set the active texture unit to the specified value! If you require that then
		 * you need to call SetActiveUnit!
		 *
		 * @param unit The texture unit to use
		 * @param tex_target The texture target of the texture id
		 * @param tex_id The ID of the texture to enable
		 */
		void Enable(GLuint unit, GLenum tex_target, GLuint tex_id);
		void Delete(GLuint tex_id);
		
		inline GLenum GetTarget();
		inline void SetShaderMode(GLboolean mode);
};

inline GLenum opengl_texture_state::GetTarget()
{
	return units[active_texture_unit].texture_target;
}

inline void opengl_texture_state::SetShaderMode(GLboolean mode)
{
	shader_mode = mode;
}

struct opengl_client_texture_unit
{
	GLboolean status;

	GLuint buffer;
	GLint size;
	GLenum type;
	GLsizei stride;
	GLvoid *pointer;

	bool reset_ptr;
	bool used_for_draw;
};

struct opengl_vertex_attrib_unit
{
	GLboolean status;

	GLuint buffer;
	GLint size;
	GLenum type;
	GLboolean normalized;
	GLsizei stride;
	GLvoid *pointer;

	bool status_init;
	bool ptr_init;

	bool reset_ptr;
	bool used_for_draw;
};

class opengl_array_state
{
	private:
		GLuint active_client_texture_unit;
		GLuint num_client_texture_units;

		opengl_client_texture_unit *client_texture_units;

		SCP_map<GLuint, opengl_vertex_attrib_unit> vertex_attrib_units;

		GLuint array_buffer;
		bool array_buffer_valid = false;

		GLuint element_array_buffer;
		bool element_array_buffer_valid = false;

		GLuint texture_array_buffer;
		GLuint uniform_buffer;

		GLuint uniform_buffer_index_bindings[MAX_UNIFORM_BUFFERS];

		struct vertex_buffer_binding {
			GLuint buffer = 0;
			GLintptr offset = 0;
			GLsizei stride = 0;
			bool valid_data = false;
		};
		SCP_vector<vertex_buffer_binding> vertex_buffer_bindings; //!< Use for keeping track of glBindVertexBuffer calls

		/**
		 * @brief Signals that the VAO binding changed which invalidates the state of our array and element buffer state
		 */
		void VertexArrayChanged();
	public:
		opengl_array_state(): active_client_texture_unit(0), client_texture_units(NULL) {
			for ( int i = 0; i < MAX_UNIFORM_BUFFERS; ++i ) {
				uniform_buffer_index_bindings[i] = 0;
			}
		}
		~opengl_array_state();

		void init(GLuint n_units);

		void EnableVertexAttrib(GLuint index);
		void DisableVertexAttrib(GLuint index);
		void VertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLvoid *pointer);
		void ResetVertexAttribs();

		void BindPointersBegin();
		void BindPointersEnd();

		void BindArrayBuffer(GLuint id);
		void BindElementBuffer(GLuint id);
		void BindTextureBuffer(GLuint id);
		void BindUniformBuffer(GLuint id);
		void BindUniformBufferBindingIndex(GLuint id, GLuint index);

		void BindVertexBuffer(GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride);

		friend class opengl_state;
};

class opengl_constant_state {
	GLint _uniform_buffer_offset_alignment;
	GLint _max_uniform_block_size;
	GLint _max_uniform_block_bindings;
	GLfloat _max_anisotropy;

 public:
	opengl_constant_state();

	void init();

	GLint GetUniformBufferOffsetAlignment();

	GLint GetMaxUniformBlockSize();

	GLint GetMaxUniformBlockBindings();

	GLfloat GetMaxAnisotropy();
};

class opengl_state
{
	friend class opengl_texture_state;

	private:
		GLboolean blend_Status;
		GLboolean depthtest_Status;
		GLboolean scissortest_Status;
        GLboolean stenciltest_Status;
		GLboolean cullface_Status;
		GLboolean polygonoffsetfill_Status;
		GLboolean normalize_Status;
		GLboolean clipplane_Status[6];
		bool clipdistance_Status[6];
		GLboolean depthmask_Status;
        bvec4 colormask_Status;

		GLenum frontface_Value;
		GLenum cullface_Value;
		std::pair<GLenum, GLenum> blendfunc_Value;
		std::array<std::pair<GLenum, GLenum>, material::NUM_BUFFER_BLENDS> buffer_blendfunc_Value;
		GLenum depthfunc_Value;

		GLenum polygon_mode_Face;
		GLenum polygon_mode_Mode;

		GLfloat polygon_offset_Factor;
		GLfloat polygon_offset_Unit;

		GLfloat line_width_Value;

		GLenum stencilFunc;
		GLint stencilFuncRef;
		GLuint stencilFuncMask;

		GLuint stencilMask;

		GLenum stencilOpFrontStencilFail;
		GLenum stencilOpFrontDepthFail;
		GLenum stencilOpFrontPass;

		GLenum stencilOpBackStencilFail;
		GLenum stencilOpBackDepthFail;
		GLenum stencilOpBackPass;

		GLuint current_program;

		// The framebuffer state actually consists of draw and read buffers but we only use both at the same time
		GLuint current_framebuffer;
		SCP_vector<GLuint> framebuffer_stack;

		GLuint current_vao = 0;
	public:
		opengl_state() {}
		~opengl_state() {}

		void init();

		opengl_texture_state Texture;
		opengl_array_state Array;
		opengl_constant_state Constants;

		void SetAlphaBlendMode(gr_alpha_blend ab);
		void SetAlphaBlendModei(int buffer, gr_alpha_blend ab);
		void SetZbufferType(gr_zbuffer_type zt);
		void SetPolygonOffset(GLfloat factor, GLfloat units);
		void SetPolygonMode(GLenum face, GLenum mode);
		void SetLineWidth(GLfloat width);

		void StencilFunc(GLenum func, GLint ref, GLuint mask);
		void StencilOpSeparate(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
		void StencilMask(GLuint mask);

		// the GLboolean functions will return the current state if no argument
		// and the previous state if an argument is passed
		GLboolean Blend(GLint state = -1);
		GLboolean AlphaTest(GLint state = -1);
		GLboolean DepthTest(GLint state = -1);
		GLboolean ScissorTest(GLint state = -1);
        GLboolean StencilTest(GLint state = -1);
		GLboolean CullFace(GLint state = -1);
		GLboolean PolygonOffsetFill(GLint state = -1);
		GLboolean ClipDistance(GLint num, bool state = false);
		GLboolean DepthMask(GLint state = -1);
        bvec4 ColorMask(bool red, bool green, bool blue, bool alpha);

		inline GLenum FrontFaceValue(GLenum new_val = GL_INVALID_ENUM);
		inline GLenum CullFaceValue(GLenum new_val = GL_INVALID_ENUM);
		void BlendFunc(GLenum s_val, GLenum d_val);
		void BlendFunci(int buffer, GLenum s_val, GLenum d_val);
		inline GLenum DepthFunc(GLenum new_val = GL_INVALID_ENUM);
		inline void InvalidateColor();

		void UseProgram(GLuint program);
		bool IsCurrentProgram(GLuint program);

		void BindFrameBuffer(GLuint name, GLenum mode = GL_FRAMEBUFFER);

		void PushFramebufferState();
		void PopFramebufferState();

		void BindVertexArray(GLuint vao);
};

inline GLenum opengl_state::FrontFaceValue(GLenum new_val)
{
	if (new_val != frontface_Value) {
		if (new_val != GL_INVALID_ENUM) {
			glFrontFace(new_val);
			frontface_Value = new_val;
		}
	}

	return frontface_Value;
}

inline GLenum opengl_state::CullFaceValue(GLenum new_val)
{
	if (new_val != cullface_Value) {
		if (new_val != GL_INVALID_ENUM) {
			glCullFace(new_val);
			cullface_Value = new_val;
		}
	}

	return cullface_Value;
}

inline GLenum opengl_state::DepthFunc(GLenum new_val)
{
	if (new_val != depthfunc_Value) {
		if (new_val != GL_INVALID_ENUM) {
			glDepthFunc(new_val);
			depthfunc_Value = new_val;
		}
	}

	return depthfunc_Value;
}

extern opengl_state GL_state;

void gr_opengl_clear_states();
void opengl_setup_render_states(int &r,int &g,int &b,int &alpha, int &tmap_type, int flags, int is_scaler = 0);

#endif	// _GROPENGLSTATE_H