summaryrefslogtreecommitdiff
path: root/src/refresh/gl/state.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/refresh/gl/state.c')
-rw-r--r--src/refresh/gl/state.c427
1 files changed, 277 insertions, 150 deletions
diff --git a/src/refresh/gl/state.c b/src/refresh/gl/state.c
index 732c103..3d8c6b4 100644
--- a/src/refresh/gl/state.c
+++ b/src/refresh/gl/state.c
@@ -21,89 +21,45 @@ with this program; if not, write to the Free Software Foundation, Inc.,
glState_t gls;
-void GL_BindTexture(int texnum)
+// for uploading
+void GL_ForceTexture(GLuint tmu, GLuint texnum)
{
-#ifdef _DEBUG
- if (gl_nobind->integer && !gls.tmu) {
- texnum = TEXNUM_DEFAULT;
- }
-#endif
+ GL_ActiveTexture(tmu);
- if (gls.texnum[gls.tmu] == texnum) {
+ if (gls.texnums[tmu] == texnum) {
return;
}
qglBindTexture(GL_TEXTURE_2D, texnum);
- gls.texnum[gls.tmu] = texnum;
+ gls.texnums[tmu] = texnum;
c.texSwitches++;
}
-void GL_SelectTMU(int tmu)
+// for drawing
+void GL_BindTexture(GLuint tmu, GLuint texnum)
{
- if (gls.tmu == tmu) {
- return;
- }
-
- if (tmu < 0 || tmu >= gl_config.numTextureUnits) {
- Com_Error(ERR_FATAL, "GL_SelectTMU: bad tmu %d", tmu);
+#ifdef _DEBUG
+ if (gl_nobind->integer && !tmu) {
+ texnum = TEXNUM_DEFAULT;
}
+#endif
- qglActiveTextureARB(GL_TEXTURE0_ARB + tmu);
- qglClientActiveTextureARB(GL_TEXTURE0_ARB + tmu);
-
- gls.tmu = tmu;
-}
-
-void GL_TexEnv(GLenum texenv)
-{
- if (gls.texenv[gls.tmu] == texenv) {
+ if (gls.texnums[tmu] == texnum) {
return;
}
- switch (texenv) {
- case GL_REPLACE:
- case GL_MODULATE:
- case GL_BLEND:
- case GL_ADD:
- qglTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, texenv);
- break;
- default:
- Com_Error(ERR_FATAL, "GL_TexEnv: bad texenv");
- break;
- }
-
- gls.texenv[gls.tmu] = texenv;
-}
+ GL_ActiveTexture(tmu);
-void GL_CullFace(glCullFace_t cull)
-{
- if (gls.cull == cull) {
- return;
- }
- switch (cull) {
- case GLS_CULL_DISABLE:
- qglDisable(GL_CULL_FACE);
- break;
- case GLS_CULL_FRONT:
- qglEnable(GL_CULL_FACE);
- qglCullFace(GL_FRONT);
- break;
- case GLS_CULL_BACK:
- qglEnable(GL_CULL_FACE);
- qglCullFace(GL_BACK);
- break;
- default:
- Com_Error(ERR_FATAL, "GL_CullFace: bad cull");
- break;
- }
+ qglBindTexture(GL_TEXTURE_2D, texnum);
+ gls.texnums[tmu] = texnum;
- gls.cull = cull;
+ c.texSwitches++;
}
-void GL_Bits(glStateBits_t bits)
+void GL_StateBits(glStateBits_t bits)
{
- glStateBits_t diff = bits ^ gls.bits;
+ glStateBits_t diff = bits ^ gls.state_bits;
if (!diff) {
return;
@@ -148,17 +104,165 @@ void GL_Bits(glStateBits_t bits)
}
}
- gls.bits = bits;
+ if (diff & GLS_TEXTURE_REPLACE) {
+ GL_ActiveTexture(0);
+ if (bits & GLS_TEXTURE_REPLACE) {
+ qglTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+ } else {
+ qglTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ }
+ }
+
+ if (diff & GLS_FLOW_ENABLE) {
+ GL_ActiveTexture(0);
+ qglMatrixMode(GL_TEXTURE);
+
+ if (bits & GLS_FLOW_ENABLE) {
+ float scaled, scroll;
+
+ if (bits & GLS_WARP_ENABLE) {
+ scaled = glr.fd.time * 0.5f;
+ scroll = -scaled;
+ } else {
+ scaled = glr.fd.time / 40;
+ scroll = -64 * (scaled - (int)scaled);
+ }
+
+ qglTranslatef(scroll, 0, 0);
+ } else {
+ qglLoadIdentity();
+ }
+
+ qglMatrixMode(GL_MODELVIEW);
+ }
+
+ if (diff & GLS_LIGHTMAP_ENABLE) {
+ GL_ActiveTexture(1);
+ if (bits & GLS_LIGHTMAP_ENABLE) {
+ qglEnable(GL_TEXTURE_2D);
+ } else {
+ qglDisable(GL_TEXTURE_2D);
+ }
+ }
+
+ if ((diff & GLS_WARP_ENABLE) && gl_static.prognum_warp) {
+ if (bits & GLS_WARP_ENABLE) {
+ vec4_t param;
+
+ qglEnable(GL_FRAGMENT_PROGRAM_ARB);
+ qglBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, gl_static.prognum_warp);
+ param[0] = glr.fd.time;
+ param[1] = glr.fd.time;
+ param[2] = param[3] = 0;
+ qglProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, 0, param);
+ } else {
+ qglBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, 0);
+ qglDisable(GL_FRAGMENT_PROGRAM_ARB);
+ }
+ }
+
+ if (diff & GLS_CULL_DISABLE) {
+ if (bits & GLS_CULL_DISABLE) {
+ qglDisable(GL_CULL_FACE);
+ } else {
+ qglEnable(GL_CULL_FACE);
+ }
+ }
+
+ if (diff & GLS_SHADE_SMOOTH) {
+ if (bits & GLS_SHADE_SMOOTH) {
+ qglShadeModel(GL_SMOOTH);
+ } else {
+ qglShadeModel(GL_FLAT);
+ }
+ }
+
+ gls.state_bits = bits;
}
-void GL_Setup2D(void)
+void GL_ArrayBits(glArrayBits_t bits)
{
- qglViewport(0, 0, r_config.width, r_config.height);
+ glArrayBits_t diff = bits ^ gls.array_bits;
+
+ if (!diff) {
+ return;
+ }
+
+ if (diff & GLA_VERTEX) {
+ if (bits & GLA_VERTEX) {
+ qglEnableClientState(GL_VERTEX_ARRAY);
+ } else {
+ qglDisableClientState(GL_VERTEX_ARRAY);
+ }
+ }
+
+ if (diff & GLA_TC) {
+ GL_ClientActiveTexture(0);
+ if (bits & GLA_TC) {
+ qglEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ } else {
+ qglDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ }
+ }
+
+ if (diff & GLA_LMTC) {
+ GL_ClientActiveTexture(1);
+ if (bits & GLA_LMTC) {
+ qglEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ } else {
+ qglDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ }
+ }
+
+ if (diff & GLA_COLOR) {
+ if (bits & GLA_COLOR) {
+ qglEnableClientState(GL_COLOR_ARRAY);
+ } else {
+ qglDisableClientState(GL_COLOR_ARRAY);
+ }
+ }
+
+ gls.array_bits = bits;
+}
+
+void GL_Ortho(GLfloat xmin, GLfloat xmax, GLfloat ymin, GLfloat ymax, GLfloat znear, GLfloat zfar)
+{
+ GLfloat width, height, depth;
+ GLfloat matrix[16];
+
+ width = xmax - xmin;
+ height = ymax - ymin;
+ depth = zfar - znear;
+
+ matrix[0] = 2 / width;
+ matrix[4] = 0;
+ matrix[8] = 0;
+ matrix[12] = -(xmax + xmin) / width;
+
+ matrix[1] = 0;
+ matrix[5] = 2 / height;
+ matrix[9] = 0;
+ matrix[13] = -(ymax + ymin) / height;
+
+ matrix[2] = 0;
+ matrix[6] = 0;
+ matrix[10] = -2 / depth;
+ matrix[14] = -(zfar + znear) / depth;
+
+ matrix[3] = 0;
+ matrix[7] = 0;
+ matrix[11] = 0;
+ matrix[15] = 1;
qglMatrixMode(GL_PROJECTION);
- qglLoadIdentity();
+ qglLoadMatrixf(matrix);
+}
- qglOrtho(0, r_config.width, r_config.height, 0, -1, 1);
+void GL_Setup2D(void)
+{
+ qglViewport(0, 0, r_config.width, r_config.height);
+
+ GL_Ortho(0, r_config.width, r_config.height, 0, -1, 1);
draw.scale = 1;
draw.colors[0].u32 = U32_WHITE;
@@ -172,63 +276,99 @@ void GL_Setup2D(void)
qglMatrixMode(GL_MODELVIEW);
qglLoadIdentity();
-
- GL_Bits(GLS_DEPTHTEST_DISABLE);
- GL_CullFace(GLS_CULL_DISABLE);
}
-void GL_Setup3D(void)
+static void GL_Frustum(void)
{
- GLdouble xmin, xmax, ymin, ymax, zfar;
- int yb = glr.fd.y + glr.fd.height;
+ GLfloat xmin, xmax, ymin, ymax, zfar, znear;
+ GLfloat width, height, depth;
+ GLfloat matrix[16];
- qglViewport(glr.fd.x, r_config.height - yb,
- glr.fd.width, glr.fd.height);
+ znear = gl_znear->value;
- qglMatrixMode(GL_PROJECTION);
- qglLoadIdentity();
+ if (glr.fd.rdflags & RDF_NOWORLDMODEL)
+ zfar = 2048;
+ else
+ zfar = gl_static.world.size * 2;
- ymax = gl_znear->value * tan(glr.fd.fov_y * M_PI / 360.0);
+ ymax = znear * tan(glr.fd.fov_y * M_PI / 360.0);
ymin = -ymax;
- xmax = gl_znear->value * tan(glr.fd.fov_x * M_PI / 360.0);
+ xmax = znear * tan(glr.fd.fov_x * M_PI / 360.0);
xmin = -xmax;
- if (glr.fd.rdflags & RDF_NOWORLDMODEL)
- zfar = 2048;
- else
- zfar = gl_static.world.size * 2;
+ width = xmax - xmin;
+ height = ymax - ymin;
+ depth = zfar - znear;
- qglFrustum(xmin, xmax, ymin, ymax, gl_znear->value, zfar);
+ matrix[0] = 2 * znear / width;
+ matrix[4] = 0;
+ matrix[8] = (xmax + xmin) / width;
+ matrix[12] = 0;
- qglMatrixMode(GL_MODELVIEW);
+ matrix[1] = 0;
+ matrix[5] = 2 * znear / height;
+ matrix[9] = (ymax + ymin) / height;
+ matrix[13] = 0;
+
+ matrix[2] = 0;
+ matrix[6] = 0;
+ matrix[10] = -(zfar + znear) / depth;
+ matrix[14] = -2 * zfar * znear / depth;
+
+ matrix[3] = 0;
+ matrix[7] = 0;
+ matrix[11] = -1;
+ matrix[15] = 0;
+
+ qglMatrixMode(GL_PROJECTION);
+ qglLoadMatrixf(matrix);
+}
+
+static void GL_RotateForViewer(void)
+{
+ GLfloat *matrix = glr.viewmatrix;
AnglesToAxis(glr.fd.viewangles, glr.viewaxis);
- glr.viewmatrix[0] = -glr.viewaxis[1][0];
- glr.viewmatrix[4] = -glr.viewaxis[1][1];
- glr.viewmatrix[8] = -glr.viewaxis[1][2];
- glr.viewmatrix[12] = DotProduct(glr.viewaxis[1], glr.fd.vieworg);
+ matrix[0] = -glr.viewaxis[1][0];
+ matrix[4] = -glr.viewaxis[1][1];
+ matrix[8] = -glr.viewaxis[1][2];
+ matrix[12] = DotProduct(glr.viewaxis[1], glr.fd.vieworg);
- glr.viewmatrix[1] = glr.viewaxis[2][0];
- glr.viewmatrix[5] = glr.viewaxis[2][1];
- glr.viewmatrix[9] = glr.viewaxis[2][2];
- glr.viewmatrix[13] = -DotProduct(glr.viewaxis[2], glr.fd.vieworg);
+ matrix[1] = glr.viewaxis[2][0];
+ matrix[5] = glr.viewaxis[2][1];
+ matrix[9] = glr.viewaxis[2][2];
+ matrix[13] = -DotProduct(glr.viewaxis[2], glr.fd.vieworg);
- glr.viewmatrix[2] = -glr.viewaxis[0][0];
- glr.viewmatrix[6] = -glr.viewaxis[0][1];
- glr.viewmatrix[10] = -glr.viewaxis[0][2];
- glr.viewmatrix[14] = DotProduct(glr.viewaxis[0], glr.fd.vieworg);
+ matrix[2] = -glr.viewaxis[0][0];
+ matrix[6] = -glr.viewaxis[0][1];
+ matrix[10] = -glr.viewaxis[0][2];
+ matrix[14] = DotProduct(glr.viewaxis[0], glr.fd.vieworg);
- glr.viewmatrix[3] = 0;
- glr.viewmatrix[7] = 0;
- glr.viewmatrix[11] = 0;
- glr.viewmatrix[15] = 1;
+ matrix[3] = 0;
+ matrix[7] = 0;
+ matrix[11] = 0;
+ matrix[15] = 1;
- qglLoadMatrixf(glr.viewmatrix);
+ qglMatrixMode(GL_MODELVIEW);
+ qglLoadMatrixf(matrix);
- GL_Bits(GLS_DEFAULT);
- GL_CullFace(GLS_CULL_BACK);
+ // forced matrix upload
+ gls.currentmatrix = matrix;
+}
+
+void GL_Setup3D(void)
+{
+ qglViewport(glr.fd.x, r_config.height - (glr.fd.y + glr.fd.height),
+ glr.fd.width, glr.fd.height);
+
+ GL_Frustum();
+
+ GL_RotateForViewer();
+
+ // enable depth writes before clearing
+ GL_StateBits(GLS_DEFAULT);
qglClear(GL_DEPTH_BUFFER_BIT | gl_static.stencil_buffer_bit);
}
@@ -246,22 +386,35 @@ void GL_SetDefaultState(void)
qglDisable(GL_BLEND);
qglDisable(GL_ALPHA_TEST);
qglAlphaFunc(GL_GREATER, 0.666f);
- qglFrontFace(GL_CW);
qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ qglFrontFace(GL_CW);
+ qglCullFace(GL_BACK);
+ qglEnable(GL_CULL_FACE);
+ qglShadeModel(GL_FLAT);
+
+ if (qglActiveTextureARB && qglClientActiveTextureARB) {
+ qglActiveTextureARB(GL_TEXTURE1_ARB);
+ qglBindTexture(GL_TEXTURE_2D, 0);
+ qglDisable(GL_TEXTURE_2D);
+ qglClientActiveTextureARB(GL_TEXTURE1_ARB);
+ qglDisableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ qglActiveTextureARB(GL_TEXTURE0_ARB);
+ qglBindTexture(GL_TEXTURE_2D, 0);
+ qglEnable(GL_TEXTURE_2D);
+ qglClientActiveTextureARB(GL_TEXTURE0_ARB);
+ qglDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ } else {
+ qglBindTexture(GL_TEXTURE_2D, 0);
+ qglEnable(GL_TEXTURE_2D);
+ qglDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ }
- qglActiveTextureARB(GL_TEXTURE1_ARB);
- qglClientActiveTextureARB(GL_TEXTURE1_ARB);
- qglBindTexture(GL_TEXTURE_2D, 0);
- qglDisable(GL_TEXTURE_2D);
- qglDisableClientState(GL_TEXTURE_COORD_ARRAY);
-
- qglActiveTextureARB(GL_TEXTURE0_ARB);
- qglClientActiveTextureARB(GL_TEXTURE0_ARB);
- qglBindTexture(GL_TEXTURE_2D, 0);
- qglEnable(GL_TEXTURE_2D);
- qglEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ qglMatrixMode(GL_TEXTURE);
+ qglLoadIdentity();
+ qglMatrixMode(GL_MODELVIEW);
- qglEnableClientState(GL_VERTEX_ARRAY);
+ qglDisableClientState(GL_VERTEX_ARRAY);
qglDisableClientState(GL_COLOR_ARRAY);
qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | gl_static.stencil_buffer_bit);
@@ -287,45 +440,19 @@ byte *IMG_ReadPixels(qboolean reverse, int *width, int *height)
void GL_EnableOutlines(void)
{
- if (gls.fp_enabled) {
- qglDisable(GL_FRAGMENT_PROGRAM_ARB);
- }
- qglDisable(GL_TEXTURE_2D);
- qglDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ GL_BindTexture(0, TEXNUM_WHITE);
+ GL_StateBits(GLS_DEFAULT);
+ GL_ArrayBits(GLA_VERTEX);
+ qglColor4f(1, 1, 1, 1);
+
qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
qglDepthRange(0, 0);
- qglColor4f(1, 1, 1, 1);
}
void GL_DisableOutlines(void)
{
qglDepthRange(0, 1);
qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- qglEnableClientState(GL_TEXTURE_COORD_ARRAY);
- qglEnable(GL_TEXTURE_2D);
- if (gls.fp_enabled) {
- qglEnable(GL_FRAGMENT_PROGRAM_ARB);
- }
-}
-
-void GL_EnableWarp(void)
-{
- vec4_t param;
-
- qglEnable(GL_FRAGMENT_PROGRAM_ARB);
- qglBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, gl_static.prognum_warp);
- param[0] = glr.fd.time;
- param[1] = glr.fd.time;
- param[2] = param[3] = 0;
- qglProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, 0, param);
- gls.fp_enabled = qtrue;
-}
-
-void GL_DisableWarp(void)
-{
- qglBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, 0);
- qglDisable(GL_FRAGMENT_PROGRAM_ARB);
- gls.fp_enabled = qfalse;
}
void GL_InitPrograms(void)
@@ -345,7 +472,8 @@ void GL_InitPrograms(void)
Cvar_Set("gl_fragment_program", "0");
}
- if (!qglProgramStringARB) {
+ if (!qglGenProgramsARB || !qglBindProgramARB ||
+ !qglProgramStringARB || !qglDeleteProgramsARB) {
return;
}
@@ -379,4 +507,3 @@ void GL_ShutdownPrograms(void)
QGL_ShutdownExtensions(QGL_ARB_fragment_program);
gl_config.ext_enabled &= ~QGL_ARB_fragment_program;
}
-