2018-05-15 13:22:26 +00:00
|
|
|
#pragma once
|
2019-10-19 16:34:24 +00:00
|
|
|
#include "wsi/gl_context.h"
|
2020-03-28 16:58:01 +00:00
|
|
|
#include <map>
|
2018-05-15 13:22:26 +00:00
|
|
|
|
|
|
|
#define TEXTURE_ID_CACHE_SIZE 32
|
|
|
|
|
|
|
|
class GLCache {
|
|
|
|
public:
|
|
|
|
GLCache() { Reset(); }
|
|
|
|
|
|
|
|
void BindTexture(GLenum target, GLuint texture) {
|
2020-01-05 19:44:39 +00:00
|
|
|
if (target == GL_TEXTURE_2D && !_disable_cache) {
|
|
|
|
if (texture != _texture) {
|
|
|
|
glBindTexture(target, texture);
|
|
|
|
_texture = texture;
|
2018-10-05 13:07:30 +00:00
|
|
|
}
|
2018-05-15 13:22:26 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
glBindTexture(target, texture);
|
|
|
|
}
|
|
|
|
|
|
|
|
void BlendFunc(GLenum sfactor, GLenum dfactor) {
|
2020-01-05 19:44:39 +00:00
|
|
|
if (sfactor != _src_blend_factor || dfactor != _dst_blend_factor || _disable_cache) {
|
2018-05-15 13:22:26 +00:00
|
|
|
_src_blend_factor = sfactor;
|
|
|
|
_dst_blend_factor = dfactor;
|
|
|
|
glBlendFunc(sfactor, dfactor);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {
|
2020-01-05 19:44:39 +00:00
|
|
|
if (red != _clear_r || green != _clear_g || blue != _clear_b || alpha != _clear_a || _disable_cache) {
|
2018-05-15 13:22:26 +00:00
|
|
|
_clear_r = red;
|
|
|
|
_clear_g = green;
|
|
|
|
_clear_b = blue;
|
|
|
|
_clear_a = alpha;
|
2018-05-15 14:09:50 +00:00
|
|
|
glClearColor(red, green, blue, alpha);
|
2018-05-15 13:22:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CullFace(GLenum mode) {
|
2020-01-05 19:44:39 +00:00
|
|
|
if (mode != _cull_face || _disable_cache) {
|
2018-05-15 13:22:26 +00:00
|
|
|
_cull_face = mode;
|
|
|
|
glCullFace(mode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DeleteTextures(GLsizei n, const GLuint *textures) {
|
2018-10-05 13:07:30 +00:00
|
|
|
for (int i = 0; i < n; i++)
|
2020-01-05 19:44:39 +00:00
|
|
|
{
|
|
|
|
_texture_params.erase(textures[i]);
|
2018-05-16 17:34:45 +00:00
|
|
|
if (textures[i] == _texture)
|
2018-05-15 13:22:26 +00:00
|
|
|
_texture = 0;
|
|
|
|
}
|
|
|
|
glDeleteTextures(n, textures);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DepthFunc(GLenum func) {
|
2018-10-05 13:07:30 +00:00
|
|
|
if (func != _depth_func || _disable_cache) {
|
2018-05-15 13:22:26 +00:00
|
|
|
_depth_func = func;
|
|
|
|
glDepthFunc(func);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DepthMask(GLboolean flag) {
|
2020-01-05 19:44:39 +00:00
|
|
|
if (flag != _depth_mask || _disable_cache) {
|
2018-05-15 13:22:26 +00:00
|
|
|
_depth_mask = flag;
|
|
|
|
glDepthMask(flag);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Enable(GLenum cap) {
|
2018-10-05 13:07:30 +00:00
|
|
|
setCapability(cap, GL_TRUE);
|
2018-05-15 13:22:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Disable(GLenum cap) {
|
2018-10-05 13:07:30 +00:00
|
|
|
setCapability(cap, GL_FALSE);
|
2018-05-15 13:22:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void UseProgram(GLuint program) {
|
2020-01-05 19:44:39 +00:00
|
|
|
if (program != _program || _disable_cache) {
|
2018-05-15 13:22:26 +00:00
|
|
|
_program = program;
|
|
|
|
glUseProgram(program);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void StencilFunc(GLenum func, GLint ref, GLuint mask) {
|
2020-01-05 19:44:39 +00:00
|
|
|
if (_stencil_func != func || _stencil_ref != ref || _stencil_fmask != mask || _disable_cache) {
|
2018-05-15 13:22:26 +00:00
|
|
|
_stencil_func = func;
|
|
|
|
_stencil_ref = ref;
|
|
|
|
_stencil_fmask = mask;
|
2018-10-05 13:07:30 +00:00
|
|
|
|
2018-05-15 13:22:26 +00:00
|
|
|
glStencilFunc(func, ref, mask);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void StencilOp(GLenum sfail, GLenum dpfail, GLenum dppass) {
|
2020-01-05 19:44:39 +00:00
|
|
|
if (_stencil_sfail != sfail ||_stencil_dpfail != dpfail || _stencil_dppass != dppass || _disable_cache) {
|
2018-05-15 13:22:26 +00:00
|
|
|
_stencil_sfail = sfail;
|
|
|
|
_stencil_dpfail = dpfail;
|
|
|
|
_stencil_dppass = dppass;
|
2018-10-05 13:07:30 +00:00
|
|
|
|
2018-05-15 13:22:26 +00:00
|
|
|
glStencilOp(sfail, dpfail, dppass);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void StencilMask(GLuint mask) {
|
2020-01-05 19:44:39 +00:00
|
|
|
if (_stencil_mask != mask || _disable_cache) {
|
2018-05-15 13:22:26 +00:00
|
|
|
_stencil_mask = mask;
|
|
|
|
glStencilMask(mask);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-11 13:50:16 +00:00
|
|
|
void Scissor(GLint x, GLint y, GLsizei width, GLsizei height)
|
|
|
|
{
|
|
|
|
if (x != _scissor.x || y != _scissor.y || width != _scissor.width || height != _scissor.height || _disable_cache)
|
|
|
|
{
|
|
|
|
_scissor.x = x;
|
|
|
|
_scissor.y = y;
|
|
|
|
_scissor.width = width;
|
|
|
|
_scissor.height = height;
|
|
|
|
glScissor(x, y, width, height);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-05 13:07:30 +00:00
|
|
|
void TexParameteri(GLenum target, GLenum pname, GLint param)
|
|
|
|
{
|
|
|
|
if (target == GL_TEXTURE_2D && !_disable_cache)
|
2018-05-16 17:34:45 +00:00
|
|
|
{
|
|
|
|
TextureParameters &cur_params = _texture_params[_texture];
|
|
|
|
switch (pname) {
|
|
|
|
case GL_TEXTURE_MIN_FILTER:
|
2020-05-11 13:50:16 +00:00
|
|
|
if (cur_params._min_filter == (GLenum)param)
|
2018-05-16 17:34:45 +00:00
|
|
|
return;
|
|
|
|
cur_params._min_filter = param;
|
|
|
|
break;
|
|
|
|
case GL_TEXTURE_MAG_FILTER:
|
2020-05-11 13:50:16 +00:00
|
|
|
if (cur_params._mag_filter == (GLenum)param)
|
2018-05-16 17:34:45 +00:00
|
|
|
return;
|
|
|
|
cur_params._mag_filter = param;
|
|
|
|
break;
|
|
|
|
case GL_TEXTURE_WRAP_S:
|
2020-05-11 13:50:16 +00:00
|
|
|
if (cur_params._wrap_s == (GLenum)param)
|
2018-05-16 17:34:45 +00:00
|
|
|
return;
|
|
|
|
cur_params._wrap_s = param;
|
|
|
|
break;
|
|
|
|
case GL_TEXTURE_WRAP_T:
|
2020-05-11 13:50:16 +00:00
|
|
|
if (cur_params._wrap_t == (GLenum)param)
|
2018-05-16 17:34:45 +00:00
|
|
|
return;
|
|
|
|
cur_params._wrap_t = param;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
glTexParameteri(target, pname, param);
|
|
|
|
}
|
|
|
|
|
2018-05-15 13:22:26 +00:00
|
|
|
GLuint GenTexture() {
|
|
|
|
if (_texture_cache_size == 0) {
|
|
|
|
_texture_cache_size = TEXTURE_ID_CACHE_SIZE;
|
|
|
|
glGenTextures(_texture_cache_size, _texture_ids);
|
|
|
|
}
|
|
|
|
return _texture_ids[--_texture_cache_size];
|
|
|
|
}
|
|
|
|
|
2019-04-09 13:18:48 +00:00
|
|
|
void DeleteProgram(GLuint program)
|
|
|
|
{
|
2020-03-28 11:33:48 +00:00
|
|
|
if (program == 0)
|
|
|
|
return;
|
2019-04-09 13:18:48 +00:00
|
|
|
GLsizei shader_count;
|
|
|
|
GLuint shaders[2];
|
|
|
|
glGetAttachedShaders(program, ARRAY_SIZE(shaders), &shader_count, shaders);
|
|
|
|
for (int i = 0; i < shader_count; i++)
|
|
|
|
glDeleteShader(shaders[i]);
|
|
|
|
|
|
|
|
glDeleteProgram(program);
|
|
|
|
if (_program == program)
|
|
|
|
_program = 0;
|
|
|
|
}
|
|
|
|
|
2018-05-15 13:22:26 +00:00
|
|
|
void Reset() {
|
2018-10-05 13:07:30 +00:00
|
|
|
_texture = 0xFFFFFFFFu;
|
2019-12-03 20:29:37 +00:00
|
|
|
_texture_params.clear();
|
2018-10-05 13:07:30 +00:00
|
|
|
_src_blend_factor = 0xFFFFFFFFu;
|
|
|
|
_dst_blend_factor = 0xFFFFFFFFu;
|
|
|
|
_clear_r = -1.f;
|
|
|
|
_clear_g = -1.f;
|
|
|
|
_clear_b = -1.f;
|
|
|
|
_clear_a = -1.f;
|
|
|
|
_en_blend = 0xFF;
|
|
|
|
_en_cull_face = 0xFF;
|
|
|
|
_en_depth_test = 0xFF;
|
|
|
|
_en_scissor_test = 0xFF;
|
|
|
|
_en_stencil_test = 0xFF;
|
|
|
|
_cull_face = 0xFFFFFFFFu;
|
|
|
|
_depth_func = 0xFFFFFFFFu;
|
|
|
|
_depth_mask = 0xFF;
|
|
|
|
_program = 0xFFFFFFFFu;
|
|
|
|
_stencil_func = 0xFFFFFFFFu;
|
|
|
|
_stencil_ref = -1;
|
|
|
|
_stencil_fmask = 0;
|
|
|
|
_stencil_sfail = 0xFFFFFFFFu;
|
|
|
|
_stencil_dpfail = 0xFFFFFFFFu;
|
|
|
|
_stencil_dppass = 0xFFFFFFFFu;
|
|
|
|
_stencil_mask = 0;
|
2020-05-11 13:50:16 +00:00
|
|
|
_scissor.x = -1;
|
|
|
|
_scissor.y = -1;
|
|
|
|
_scissor.width = -1;
|
|
|
|
_scissor.height = -1;
|
2020-03-28 16:58:01 +00:00
|
|
|
if (_texture_cache_size > 0)
|
|
|
|
{
|
|
|
|
glDeleteTextures(_texture_cache_size, _texture_ids);
|
|
|
|
_texture_cache_size = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DisableCache()
|
|
|
|
{
|
|
|
|
_disable_cache = true;
|
|
|
|
Reset();
|
|
|
|
}
|
2018-10-05 13:07:30 +00:00
|
|
|
void EnableCache()
|
|
|
|
{
|
2019-04-04 17:06:46 +00:00
|
|
|
_disable_cache = false;
|
2018-10-05 13:07:30 +00:00
|
|
|
Reset();
|
2018-05-15 13:22:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2018-05-16 17:34:45 +00:00
|
|
|
class TextureParameters {
|
|
|
|
public:
|
2018-10-05 13:07:30 +00:00
|
|
|
TextureParameters() : _min_filter(0xFFFFFFFFu), _mag_filter(0xFFFFFFFFu), _wrap_s(0xFFFFFFFFu), _wrap_t(0xFFFFFFFFu) {}
|
2018-05-16 17:34:45 +00:00
|
|
|
|
|
|
|
GLenum _min_filter;
|
|
|
|
GLenum _mag_filter;
|
|
|
|
GLenum _wrap_s;
|
|
|
|
GLenum _wrap_t;
|
|
|
|
};
|
|
|
|
|
2018-10-05 13:07:30 +00:00
|
|
|
void setCapability(GLenum cap, GLboolean value) {
|
|
|
|
GLboolean *pCap = NULL;
|
2018-05-15 14:09:50 +00:00
|
|
|
switch (cap) {
|
|
|
|
case GL_BLEND:
|
|
|
|
pCap = &_en_blend;
|
|
|
|
break;
|
|
|
|
case GL_CULL_FACE:
|
|
|
|
pCap = &_en_cull_face;
|
|
|
|
break;
|
|
|
|
case GL_DEPTH_TEST:
|
|
|
|
pCap = &_en_depth_test;
|
|
|
|
break;
|
|
|
|
case GL_SCISSOR_TEST:
|
|
|
|
pCap = &_en_scissor_test;
|
|
|
|
break;
|
|
|
|
case GL_STENCIL_TEST:
|
|
|
|
pCap = &_en_stencil_test;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (pCap != NULL) {
|
2018-10-05 13:07:30 +00:00
|
|
|
if (*pCap == value && !_disable_cache)
|
2018-05-15 14:09:50 +00:00
|
|
|
return;
|
|
|
|
*pCap = value;
|
|
|
|
}
|
2021-07-05 17:44:08 +00:00
|
|
|
switch (cap) {
|
|
|
|
case GL_BLEND:
|
|
|
|
if (value)
|
|
|
|
glEnable(GL_BLEND);
|
|
|
|
else
|
|
|
|
glDisable(GL_BLEND);
|
|
|
|
break;
|
|
|
|
case GL_CULL_FACE:
|
|
|
|
if (value)
|
|
|
|
glEnable(GL_CULL_FACE);
|
|
|
|
else
|
|
|
|
glDisable(GL_CULL_FACE);
|
|
|
|
break;
|
|
|
|
case GL_DEPTH_TEST:
|
|
|
|
if (value)
|
|
|
|
glEnable(GL_DEPTH_TEST);
|
|
|
|
else
|
|
|
|
glDisable(GL_DEPTH_TEST);
|
|
|
|
break;
|
|
|
|
case GL_SCISSOR_TEST:
|
|
|
|
if (value)
|
|
|
|
glEnable(GL_SCISSOR_TEST);
|
|
|
|
else
|
|
|
|
glDisable(GL_SCISSOR_TEST);
|
|
|
|
break;
|
|
|
|
case GL_STENCIL_TEST:
|
|
|
|
if (value)
|
|
|
|
glEnable(GL_STENCIL_TEST);
|
|
|
|
else
|
|
|
|
glDisable(GL_STENCIL_TEST);
|
|
|
|
break;
|
|
|
|
}
|
2018-05-15 14:09:50 +00:00
|
|
|
}
|
|
|
|
|
2018-10-05 13:07:30 +00:00
|
|
|
GLuint _array_buffer;
|
|
|
|
GLuint _element_array_buffer;
|
2018-05-15 13:22:26 +00:00
|
|
|
GLuint _texture;
|
|
|
|
GLenum _src_blend_factor;
|
|
|
|
GLenum _dst_blend_factor;
|
|
|
|
GLclampf _clear_r;
|
|
|
|
GLclampf _clear_g;
|
|
|
|
GLclampf _clear_b;
|
|
|
|
GLclampf _clear_a;
|
2018-10-05 13:07:30 +00:00
|
|
|
GLboolean _en_blend;
|
|
|
|
GLboolean _en_cull_face;
|
|
|
|
GLboolean _en_depth_test;
|
|
|
|
GLboolean _en_scissor_test;
|
|
|
|
GLboolean _en_stencil_test;
|
2018-05-15 13:22:26 +00:00
|
|
|
GLenum _cull_face;
|
|
|
|
GLenum _depth_func;
|
|
|
|
GLboolean _depth_mask;
|
|
|
|
GLuint _program;
|
|
|
|
GLenum _stencil_func;
|
|
|
|
GLint _stencil_ref;
|
|
|
|
GLuint _stencil_fmask;
|
|
|
|
GLenum _stencil_sfail;
|
|
|
|
GLenum _stencil_dpfail;
|
|
|
|
GLenum _stencil_dppass;
|
|
|
|
GLuint _stencil_mask;
|
2020-05-11 13:50:16 +00:00
|
|
|
struct {
|
|
|
|
GLint x;
|
|
|
|
GLint y;
|
|
|
|
GLsizei width;
|
|
|
|
GLsizei height;
|
|
|
|
} _scissor;
|
2018-05-15 13:22:26 +00:00
|
|
|
GLuint _texture_ids[TEXTURE_ID_CACHE_SIZE];
|
2021-03-27 18:55:28 +00:00
|
|
|
GLsizei _texture_cache_size = 0;
|
2018-05-16 17:34:45 +00:00
|
|
|
std::map<GLuint, TextureParameters> _texture_params;
|
2018-10-05 13:07:30 +00:00
|
|
|
bool _disable_cache;
|
2018-05-15 13:22:26 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
extern GLCache glcache;
|