1 /*
2 Copyright (C) 1997-2001 Id Software, Inc.
3 
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 
13 See the GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19 
20 //
21 // rb_state.c
22 // FIXME TODO:
23 // - Statebit pushing, which will require that all state changes are local to the backend
24 //
25 
26 #include "rb_local.h"
27 
28 rb_glState_t	rb_glState;
29 
30 /*
31 ==============================================================================
32 
33 	STATEBIT MANAGEMENT
34 
35 ==============================================================================
36 */
37 
38 /*
39 ===============
40 RB_StateForBits
41 ===============
42 */
RB_StateForBits(uint32 bits1)43 void RB_StateForBits (uint32 bits1)
44 {
45 	uint32	diff;
46 
47 	// Process bit group one
48 	diff = bits1 ^ rb_glState.stateBits1;
49 	if (diff) {
50 		// Alpha testing
51 		if (diff & SB1_ATEST_BITS) {
52 			switch (bits1 & SB1_ATEST_BITS) {
53 			case 0:
54 				qglDisable (GL_ALPHA_TEST);
55 				break;
56 			case SB1_ATEST_GT0:
57 				qglEnable (GL_ALPHA_TEST);
58 				qglAlphaFunc (GL_GREATER, 0);
59 				break;
60 			case SB1_ATEST_LT128:
61 				qglEnable (GL_ALPHA_TEST);
62 				qglAlphaFunc (GL_LESS, 0.5f);
63 				break;
64 			case SB1_ATEST_GE128:
65 				qglEnable (GL_ALPHA_TEST);
66 				qglAlphaFunc (GL_GEQUAL, 0.5f);
67 				break;
68 			default:
69 				assert (0);
70 				break;
71 			}
72 
73 			ri.pc.stateChanges++;
74 		}
75 
76 		// Blending
77 		if (diff & SB1_BLEND_ON) {
78 			if (bits1 & SB1_BLEND_ON)
79 				qglEnable (GL_BLEND);
80 			else
81 				qglDisable (GL_BLEND);
82 			ri.pc.stateChanges++;
83 		}
84 
85 		if (diff & (SB1_BLENDSRC_BITS|SB1_BLENDDST_BITS)
86 		&& bits1 & (SB1_BLENDSRC_BITS|SB1_BLENDDST_BITS)) {
87 			GLenum	sFactor, dFactor;
88 
89 			switch (bits1 & SB1_BLENDSRC_BITS) {
90 			case SB1_BLENDSRC_ZERO:					sFactor = GL_ZERO;					break;
91 			case SB1_BLENDSRC_ONE:					sFactor = GL_ONE;					break;
92 			case SB1_BLENDSRC_DST_COLOR:			sFactor = GL_DST_COLOR;				break;
93 			case SB1_BLENDSRC_ONE_MINUS_DST_COLOR:	sFactor = GL_ONE_MINUS_DST_COLOR;	break;
94 			case SB1_BLENDSRC_SRC_ALPHA:			sFactor = GL_SRC_ALPHA;				break;
95 			case SB1_BLENDSRC_ONE_MINUS_SRC_ALPHA:	sFactor = GL_ONE_MINUS_SRC_ALPHA;	break;
96 			case SB1_BLENDSRC_DST_ALPHA:			sFactor = GL_DST_ALPHA;				break;
97 			case SB1_BLENDSRC_ONE_MINUS_DST_ALPHA:	sFactor = GL_ONE_MINUS_DST_ALPHA;	break;
98 			case SB1_BLENDSRC_SRC_ALPHA_SATURATE:	sFactor = GL_SRC_ALPHA_SATURATE;	break;
99 			default:								assert (0);							break;
100 			}
101 
102 			switch (bits1 & SB1_BLENDDST_BITS) {
103 			case SB1_BLENDDST_ZERO:					dFactor = GL_ZERO;					break;
104 			case SB1_BLENDDST_ONE:					dFactor = GL_ONE;					break;
105 			case SB1_BLENDDST_SRC_COLOR:			dFactor = GL_SRC_COLOR;				break;
106 			case SB1_BLENDDST_ONE_MINUS_SRC_COLOR:	dFactor = GL_ONE_MINUS_SRC_COLOR;	break;
107 			case SB1_BLENDDST_SRC_ALPHA:			dFactor = GL_SRC_ALPHA;				break;
108 			case SB1_BLENDDST_ONE_MINUS_SRC_ALPHA:	dFactor = GL_ONE_MINUS_SRC_ALPHA;	break;
109 			case SB1_BLENDDST_DST_ALPHA:			dFactor = GL_DST_ALPHA;				break;
110 			case SB1_BLENDDST_ONE_MINUS_DST_ALPHA:	dFactor = GL_ONE_MINUS_DST_ALPHA;	break;
111 			default:								assert (0);							break;
112 			}
113 
114 			qglBlendFunc (sFactor, dFactor);
115 			ri.pc.stateChanges++;
116 		}
117 
118 		// Culling
119 		if (diff & SB1_CULL_BITS) {
120 			switch (bits1 & SB1_CULL_BITS) {
121 			case 0:
122 				qglDisable (GL_CULL_FACE);
123 				break;
124 			case SB1_CULL_FRONT:
125 				qglCullFace (GL_FRONT);
126 				qglEnable (GL_CULL_FACE);
127 				break;
128 			case SB1_CULL_BACK:
129 				qglCullFace (GL_BACK);
130 				qglEnable (GL_CULL_FACE);
131 				break;
132 			default:
133 				assert (0);
134 				break;
135 			}
136 			ri.pc.stateChanges++;
137 		}
138 
139 		// Depth masking
140 		if (diff & SB1_DEPTHMASK_ON) {
141 			if (bits1 & SB1_DEPTHMASK_ON)
142 				qglDepthMask (GL_TRUE);
143 			else
144 				qglDepthMask (GL_FALSE);
145 			ri.pc.stateChanges++;
146 		}
147 
148 		// Depth testing
149 		if (diff & SB1_DEPTHTEST_ON) {
150 			if (bits1 & SB1_DEPTHTEST_ON)
151 				qglEnable (GL_DEPTH_TEST);
152 			else
153 				qglDisable (GL_DEPTH_TEST);
154 			ri.pc.stateChanges++;
155 		}
156 
157 		// Polygon offset
158 		if (diff & SB1_POLYOFFSET_ON) {
159 			if (bits1 & SB1_POLYOFFSET_ON) {
160 				qglEnable (GL_POLYGON_OFFSET_FILL);
161 				qglPolygonOffset (r_offsetFactor->intVal, r_offsetUnits->intVal);
162 			}
163 			else
164 				qglDisable (GL_POLYGON_OFFSET_FILL);
165 			ri.pc.stateChanges++;
166 		}
167 
168 		// Save for the next diff
169 		rb_glState.stateBits1 = bits1;
170 	}
171 }
172 
173 /*
174 ==============================================================================
175 
176 	TEXTURE STATE
177 
178 ==============================================================================
179 */
180 
181 /*
182 ===============
183 RB_BindTexture
184 ===============
185 */
RB_BindTexture(image_t * image)186 void RB_BindTexture (image_t *image)
187 {
188 	// Performance evaluation option
189 	if (gl_nobind->intVal || !image)
190 		image = ri.noTexture;
191 
192 	// Determine if it's already bound
193 	if (rb_glState.texBound[rb_glState.texUnit] == image)
194 		return;
195 	rb_glState.texBound[rb_glState.texUnit] = image;
196 
197 	// Nope, bind it
198 	qglBindTexture (image->target, image->texNum);
199 
200 	// Performance counters
201 	if (r_speeds->intVal) {
202 		ri.pc.textureBinds++;
203 		if (image->visFrame != ri.frameCount) {
204 			image->visFrame = ri.frameCount;
205 			ri.pc.texturesInUse++;
206 			ri.pc.texelsInUse += image->upWidth * image->upHeight;
207 		}
208 	}
209 }
210 
211 
212 /*
213 ===============
214 RB_SelectTexture
215 ===============
216 */
RB_SelectTexture(texUnit_t texUnit)217 void RB_SelectTexture (texUnit_t texUnit)
218 {
219 	if (texUnit == rb_glState.texUnit)
220 		return;
221 	if (texUnit > ri.config.maxTexUnits) {
222 		Com_Error (ERR_DROP, "Attempted selection of an out of bounds (%d) texture unit!", texUnit);
223 		return;
224 	}
225 
226 	// Select the unit
227 	rb_glState.texUnit = texUnit;
228 	if (ri.config.extArbMultitexture) {
229 		qglActiveTextureARB (texUnit + GL_TEXTURE0_ARB);
230 		qglClientActiveTextureARB (texUnit + GL_TEXTURE0_ARB);
231 	}
232 	else if (ri.config.extSGISMultiTexture) {
233 		qglSelectTextureSGIS (texUnit + GL_TEXTURE0_SGIS);
234 	}
235 	else {
236 		return;
237 	}
238 
239 	// Performance counter
240 	ri.pc.textureUnitChanges++;
241 }
242 
243 
244 /*
245 ===============
246 RB_TextureEnv
247 ===============
248 */
RB_TextureEnv(GLfloat mode)249 void RB_TextureEnv (GLfloat mode)
250 {
251 	if (mode == GL_ADD && !ri.config.extTexEnvAdd)
252 		mode = GL_MODULATE;
253 
254 	if (mode != rb_glState.texEnvModes[rb_glState.texUnit]) {
255 		qglTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, mode);
256 		rb_glState.texEnvModes[rb_glState.texUnit] = mode;
257 
258 		// Performance counter
259 		ri.pc.textureEnvChanges++;
260 	}
261 }
262 
263 
264 /*
265 ===============
266 RB_TextureTarget
267 
268 Supplements qglEnable/qglDisable on GL_TEXTURE_1D/2D/3D/CUBE_MAP_ARB.
269 ===============
270 */
RB_TextureTarget(GLenum target)271 void RB_TextureTarget (GLenum target)
272 {
273 	if (target == rb_glState.texTarget[rb_glState.texUnit])
274 		return;
275 
276 	if (rb_glState.texTarget[rb_glState.texUnit])
277 		qglDisable (rb_glState.texTarget[rb_glState.texUnit]);
278 
279 	rb_glState.texTarget[rb_glState.texUnit] = target;
280 
281 	if (target)
282 		qglEnable (target);
283 }
284 
285 
286 /*
287 ===============
288 RB_LoadTexMatrix
289 ===============
290 */
RB_LoadTexMatrix(mat4x4_t m)291 void RB_LoadTexMatrix (mat4x4_t m)
292 {
293 	qglLoadMatrixf (m);
294 	rb_glState.texMatIdentity[rb_glState.texUnit] = qFalse;
295 }
296 
297 
298 /*
299 ===============
300 RB_LoadIdentityTexMatrix
301 ===============
302 */
RB_LoadIdentityTexMatrix(void)303 void RB_LoadIdentityTexMatrix (void)
304 {
305 	if (!rb_glState.texMatIdentity[rb_glState.texUnit]) {
306 		qglLoadIdentity ();
307 		rb_glState.texMatIdentity[rb_glState.texUnit] = qTrue;
308 	}
309 }
310 
311 /*
312 ==============================================================================
313 
314 	PROGRAM STATE
315 
316 ==============================================================================
317 */
318 
319 /*
320 ===============
321 RB_BindProgram
322 ===============
323 */
RB_BindProgram(program_t * program)324 void RB_BindProgram (program_t *program)
325 {
326 	switch (program->target) {
327 	case GL_FRAGMENT_PROGRAM_ARB:
328 		if (rb_glState.boundFragProgram == program->progNum)
329 			return;
330 		rb_glState.boundFragProgram = program->progNum;
331 
332 		qglBindProgramARB (GL_FRAGMENT_PROGRAM_ARB, program->progNum);
333 		break;
334 
335 	case GL_VERTEX_PROGRAM_ARB:
336 		if (rb_glState.boundVertProgram == program->progNum)
337 			return;
338 		rb_glState.boundVertProgram = program->progNum;
339 
340 		qglBindProgramARB (GL_VERTEX_PROGRAM_ARB, program->progNum);
341 		break;
342 
343 #ifdef _DEBUG
344 	default:
345 		assert (0);
346 		break;
347 #endif // _DEBUG
348 	}
349 }
350 
351 /*
352 ==============================================================================
353 
354 	GENERIC STATE MANAGEMENT
355 
356 ==============================================================================
357 */
358 
359 /*
360 ==================
361 RB_SetupGL2D
362 ==================
363 */
RB_SetupGL2D(void)364 void RB_SetupGL2D (void)
365 {
366 	// State
367 	rb_glState.in2D = qTrue;
368 	rb_glState.stateBits1 &= ~SB1_DEPTHMASK_ON;
369 	qglDepthMask (GL_FALSE);
370 
371 	// Set 2D virtual screen size
372 	qglViewport (0, 0, ri.config.vidWidth, ri.config.vidHeight);
373 	qglScissor (0, 0, ri.config.vidWidth, ri.config.vidHeight);
374 
375 	qglMatrixMode (GL_PROJECTION);
376 	qglLoadIdentity ();
377 	qglOrtho (0, ri.config.vidWidth, ri.config.vidHeight, 0, -99999, 99999);
378 
379 	qglMatrixMode (GL_MODELVIEW);
380 	qglLoadIdentity ();
381 }
382 
383 
384 /*
385 =============
386 RB_SetupGL3D
387 =============
388 */
RB_SetupGL3D(void)389 void RB_SetupGL3D (void)
390 {
391 	// State
392 	rb_glState.in2D = qFalse;
393 	rb_glState.stateBits1 |= SB1_DEPTHMASK_ON;
394 	qglDepthMask (GL_TRUE);
395 
396 	// Set up viewport
397 	if (!ri.scn.mirrorView && !ri.scn.portalView) {
398 		qglScissor (ri.def.x, ri.config.vidHeight - ri.def.height - ri.def.y, ri.def.width, ri.def.height);
399 		qglViewport (ri.def.x, ri.config.vidHeight - ri.def.height - ri.def.y, ri.def.width, ri.def.height);
400 		qglClear (GL_DEPTH_BUFFER_BIT);
401 	}
402 
403 	// Set up projection matrix
404 	R_SetupProjectionMatrix (&ri.def, ri.scn.projectionMatrix);
405 	if (ri.scn.mirrorView)
406 		ri.scn.projectionMatrix[0] = -ri.scn.projectionMatrix[0];
407 
408 	qglMatrixMode (GL_PROJECTION);
409 	qglLoadMatrixf (ri.scn.projectionMatrix);
410 
411 	// Set up the world view matrix
412 	R_SetupModelviewMatrix (&ri.def, ri.scn.worldViewMatrix);
413 
414 	qglMatrixMode (GL_MODELVIEW);
415 	qglLoadMatrixf (ri.scn.worldViewMatrix);
416 
417 	// Handle portal/mirror rendering
418 	if (ri.scn.mirrorView || ri.scn.portalView) {
419 		GLdouble	clip[4];
420 
421 		clip[0] = ri.scn.clipPlane.normal[0];
422 		clip[1] = ri.scn.clipPlane.normal[1];
423 		clip[2] = ri.scn.clipPlane.normal[2];
424 		clip[3] = -ri.scn.clipPlane.dist;
425 
426 		qglClipPlane (GL_CLIP_PLANE0, clip);
427 		qglEnable (GL_CLIP_PLANE0);
428 	}
429 }
430 
431 
432 /*
433 ================
434 RB_ClearBuffers
435 ================
436 */
RB_ClearBuffers(void)437 void RB_ClearBuffers (void)
438 {
439 	int			clearBits;
440 
441 	clearBits = GL_DEPTH_BUFFER_BIT;
442 	if (gl_clear->intVal) {
443 		qglClearColor (0.5f, 0.5f, 0.5f, 1.0f);
444 		clearBits |= GL_COLOR_BUFFER_BIT;
445 	}
446 
447 	if (ri.useStencil && gl_shadows->intVal) {
448 		qglClearStencil (128);
449 		clearBits |= GL_STENCIL_BUFFER_BIT;
450 	}
451 
452 	qglClear (clearBits);
453 
454 	qglDepthRange (0, 1);
455 }
456 
457 
458 /*
459 ==================
460 RB_SetDefaultState
461 
462 Sets our default OpenGL state
463 ==================
464 */
RB_SetDefaultState(void)465 void RB_SetDefaultState (void)
466 {
467 	texUnit_t	i;
468 
469 	rb_glState.stateBits1 = 0;
470 
471 	qglFinish ();
472 
473 	qglColor4f (1, 1, 1, 1);
474 	qglClearColor (0.5f, 0.5f, 0.5f, 1.0f);
475 
476 	qglEnable (GL_SCISSOR_TEST);
477 
478 	qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
479 	qglPolygonOffset (0, 0);
480 
481 	// Texture-unit specific
482 	for (i=MAX_TEXUNITS-1 ; i>=0 ; i--) {
483 		rb_glState.texBound[i] = NULL;
484 		rb_glState.texEnvModes[i] = 0;
485 		rb_glState.texMatIdentity[i] = qTrue;
486 		if (i >= ri.config.maxTexUnits)
487 			continue;
488 
489 		// Texture
490 		RB_SelectTexture (i);
491 
492 		qglDisable (GL_TEXTURE_1D);
493 		qglBindTexture (GL_TEXTURE_1D, 0);
494 
495 		if (ri.config.extTex3D) {
496 			qglDisable (GL_TEXTURE_3D);
497 			qglBindTexture (GL_TEXTURE_3D, 0);
498 		}
499 		if (ri.config.extTexCubeMap) {
500 			qglDisable (GL_TEXTURE_CUBE_MAP_ARB);
501 			qglBindTexture (GL_TEXTURE_CUBE_MAP_ARB, 0);
502 		}
503 
504 		if (i == 0) {
505 			qglEnable (GL_TEXTURE_2D);
506 			rb_glState.texTarget[i] = GL_TEXTURE_2D;
507 		}
508 		else {
509 			qglDisable (GL_TEXTURE_2D);
510 			rb_glState.texTarget[i] = 0;
511 		}
512 		qglBindTexture (GL_TEXTURE_2D, 0);
513 
514 		// Texgen
515 		qglDisable (GL_TEXTURE_GEN_S);
516 		qglDisable (GL_TEXTURE_GEN_T);
517 		qglDisable (GL_TEXTURE_GEN_R);
518 		qglDisable (GL_TEXTURE_GEN_Q);
519 	}
520 
521 	// Fragment programs
522 	if (ri.config.extFragmentProgram)
523 		qglDisable (GL_FRAGMENT_PROGRAM_ARB);
524 
525 	// Vertex programs
526 	if (ri.config.extVertexProgram)
527 		qglDisable (GL_VERTEX_PROGRAM_ARB);
528 
529 	// Stencil testing
530 	if (ri.useStencil)
531 		qglDisable (GL_STENCIL_TEST);
532 
533 	// Polygon offset testing
534 	qglDisable (GL_POLYGON_OFFSET_FILL);
535 
536 	// Depth testing
537 	qglDisable (GL_DEPTH_TEST);
538 	qglDepthFunc (GL_LEQUAL);
539 	qglDepthRange (0, 1);
540 
541 	// Face culling
542 	qglDisable (GL_CULL_FACE);
543 	qglCullFace (GL_FRONT);
544 	rb_glState.stateBits1 |= SB1_CULL_FRONT;
545 
546 	// Alpha testing
547 	qglDisable (GL_ALPHA_TEST);
548 	qglAlphaFunc (GL_GREATER, 0);
549 
550 	// Blending
551 	qglDisable (GL_BLEND);
552 	qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
553 	rb_glState.stateBits1 |= SB1_BLENDSRC_SRC_ALPHA|SB1_BLENDDST_ONE_MINUS_SRC_ALPHA;
554 
555 	// Model shading
556 	qglShadeModel (GL_SMOOTH);
557 
558 	// Check for errors
559 	GL_CheckForError ("RB_SetDefaultState");
560 }
561