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
|