Vegastrike 0.5.1 rc1  1.0
Original sources for Vegastrike Evolved
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
gl_state.cpp
Go to the documentation of this file.
1 /*
2  * Vega Strike
3  * Copyright (C) 2001-2002 Alan Shieh
4  *
5  * http://vegastrike.sourceforge.net/
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20  */
21 #define GL_STATE_CPP
22 #include "gl_globals.h"
23 #undef GL_STATE_CPP
24 
25 #include "gfxlib.h"
26 #include "vegastrike.h"
27 #include "vs_globals.h"
28 #include <stack>
29 
30 #ifndef GL_CONSTANT_ALPHA
31 #define GL_CONSTANT_ALPHA 0x8003
32 #endif
33 #ifndef GL_ONE_MINUS_CONSTANT_ALPHA
34 #define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004
35 #endif
36 #ifndef GL_ONE_MINUS_CONSTANT_COLOR
37 #define GL_ONE_MINUS_CONSTANT_COLOR 0x8002
38 #endif
39 #ifndef GL_CONSTANT_COLOR
40 #define GL_CONSTANT_COLOR 0x8001
41 #endif
42 
43 GLenum bTex[32] = {
44  0, 0, 0, 0, 0, 0, 0, 0,
45  0, 0, 0, 0, 0, 0, 0, 0,
46  0, 0, 0, 0, 0, 0, 0, 0,
47  0, 0, 0, 0, 0, 0, 0, 0,
48 };
49 
50 GLenum GetGLTextureTarget( enum TEXTURE_TARGET texture_target )
51 {
52  GLenum tt;
53  switch (texture_target)
54  {
55  case TEXTURE1D:
56  tt = GL_TEXTURE_1D;
57  break;
58  case TEXTURE2D:
59  tt = GL_TEXTURE_2D;
60  break;
61 #ifdef GL_EXT_texture3D
62  case TEXTURE3D:
63  tt = GL_TEXTURE_3D;
64  break;
65 #endif
66 #ifdef NV_CUBE_MAP
67  case CUBEMAP:
69  break;
70 #endif
71  case TEXTURERECT:
73  break;
74  default:
75  assert( false );
76  }
77  return tt;
78 }
79 
80 int activeTextureStage = -1; //FIXME Shouldn't this be a member of a class?, or at least be an official global variable?
81 
82 static inline bool _GFXActiveTextureValid()
83 {
84  return !( activeTextureStage && (activeTextureStage >= static_cast<int>(gl_options.Multitexture)) );
85 }
86 
87 extern GFXBOOL GFXLIGHTING;
88 
89 void /*GFXDRVAPI*/ GFXEnable( const STATE state )
90 {
91  switch (state)
92  {
93  case LIGHTING:
94  glEnable( GL_LIGHTING );
96  break;
97  case DEPTHTEST:
98  glEnable( GL_DEPTH_TEST );
99  glDepthFunc( GL_LEQUAL );
100  //glDepthFunc (GL_ALWAYS);
101  break;
102  case DEPTHWRITE:
103  glDepthMask( GL_TRUE );
104  break;
105  case COLORWRITE:
106  glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
107  break;
108  case TEXTURE0:
109  /*if (bTex[0] != GL_TEXTURE_2D) {
110  * GFXActiveTexture(0);
111  * if (bTex[0]) glDisable(bTex[0]);
112  * glEnable (bTex[0]=GL_TEXTURE_2D);
113  * }*/
114  //NOTE: The above code should be used, but since not all parts of VS use the GFX,
115  //we will use GFXEnable() / GFXDisable() as syncrhonization methods (they will
116  //assure correct settings of texture units 1 & 2, used during GUI rendering.
117  GFXActiveTexture( 0 );
118 #ifdef NV_CUBE_MAP
119  glDisable( GL_TEXTURE_CUBE_MAP_EXT );
120 #endif
121  glEnable( bTex[0] = GL_TEXTURE_2D );
122  break;
123  case TEXTURE1:
124  /*if (gl_options.Multitexture) {
125  * GFXActiveTexture (1);
126  * #ifdef NV_CUBE_MAP
127  * if (bTex[1] != GL_TEXTURE_CUBE_MAP_EXT) {
128  * if (bTex[1]) glDisable(bTex[1]);
129  * glEnable (bTex[1]=GL_TEXTURE_CUBE_MAP_EXT);
130  * }
131  * #else
132  * if (bTex[1] != GL_TEXTURE_2D) {
133  * if (bTex[1]) glDisable(bTex[1]);
134  * glEnable (bTex[1]=GL_TEXTURE_2D);
135  * }
136  * #endif
137  * }*/
138  //NOTE: The above code should be used, but since not all parts of VS use the GFX,
139  //we will use GFXEnable() / GFXDisable() as syncrhonization methods (they will
140  //assure correct settings of texture units 1 & 2, both in the GL and their proxy
141  //states in the GFX. Those two units are used during GUI rendering bypassing the GFX.
142  if (gl_options.Multitexture) {
143  GFXActiveTexture( 1 );
144 #ifdef NV_CUBE_MAP
145  glDisable( GL_TEXTURE_2D );
146  glEnable( bTex[1] = GL_TEXTURE_CUBE_MAP_EXT );
147 #else
148  glEnable( bTex[1] = GL_TEXTURE_2D );
149 #endif
150  }
151  break;
152  case CULLFACE:
153  glEnable( GL_CULL_FACE );
154  break;
155  case SMOOTH:
157  glEnable( GL_LINE_SMOOTH );
159  glEnable( GL_POINT_SMOOTH );
160  break;
161  case STENCIL:
162  glEnable( GL_STENCIL );
163  break;
164  }
165 }
166 
167 void GFXToggleTexture( bool enable, int whichstage, enum TEXTURE_TARGET target )
168 {
169  if ( (whichstage < static_cast<int>(gl_options.Multitexture)) || (whichstage == 0) ) {
170  GLenum tt = GetGLTextureTarget( target );
171  GLenum btt = (enable ? tt : 0);
172  if (bTex[whichstage] != btt) {
173  GFXActiveTexture( whichstage );
174  if (bTex[whichstage])
175  glDisable( bTex[whichstage] );
176  if (enable)
177  glEnable( bTex[whichstage] = tt );
178 
179  else
180  bTex[whichstage] = 0;
181  }
182  }
183 }
184 
185 void /*GFXDRVAPI*/ GFXDisable( const STATE state )
186 {
187  switch (state)
188  {
189  case LIGHTING:
190  glDisable( GL_LIGHTING );
192  break;
193  case DEPTHTEST:
194  glDisable( GL_DEPTH_TEST );
195  break;
196  case DEPTHWRITE:
197  glDepthMask( GL_FALSE );
198  break;
199  case COLORWRITE:
200  glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
201  break;
202  case TEXTURE0:
203  /*if (bTex[0]) {
204  * GFXActiveTexture(0);
205  * glDisable (bTex[0]);
206  * bTex[0] = 0;
207  * }*/
208  //NOTE: The above code should be used, but since not all parts of VS use the GFX,
209  //we will use GFXEnable() / GFXDisable() as syncrhonization methods (they will
210  //assure correct settings of texture units 1 & 2, both in the GL and their proxy
211  //states in the GFX. Those two units are used during GUI rendering bypassing the GFX.
212  GFXActiveTexture( 0 );
213 #ifdef NV_CUBE_MAP
214  glDisable( GL_TEXTURE_CUBE_MAP_EXT );
215 #endif
216  glDisable( GL_TEXTURE_2D );
217  bTex[0] = 0;
218  break;
219  case TEXTURE1:
220  /*if (bTex[1]&&gl_options.Multitexture) {
221  * GFXActiveTexture(1);
222  * glDisable(bTex[1]);
223  * bTex[1] = 0;
224  * }*/
225  //NOTE: The above code should be used, but since not all parts of VS use the GFX,
226  //we will use GFXEnable() / GFXDisable() as syncrhonization methods (they will
227  //assure correct settings of texture units 1 & 2, both in the GL and their proxy
228  //states in the GFX. Those two units are used during GUI rendering bypassing the GFX.
229  if (gl_options.Multitexture) {
230  GFXActiveTexture( 1 );
231 #ifdef NV_CUBE_MAP
232  glDisable( GL_TEXTURE_CUBE_MAP_EXT );
233 #endif
234  glDisable( GL_TEXTURE_2D );
235  bTex[1] = 0;
236  }
237  break;
238  case CULLFACE:
239  glDisable( GL_CULL_FACE );
240  break;
241  case SMOOTH:
242  glDisable( GL_LINE_SMOOTH );
243  glDisable( GL_POINT_SMOOTH );
244  break;
245  case STENCIL:
246  glDisable( GL_STENCIL );
247  break;
248  }
249 }
250 
251 #ifndef GL_CLAMP_TO_EDGE_EXT
252 #define GL_CLAMP_TO_EDGE_EXT 0x812F
253 #endif
254 #ifndef GL_CLAMP_TO_BORDER_ARB
255 #define GL_CLAMP_TO_BORDER_ARB 0x812D
256 #endif
257 
258 void GFXTextureAddressMode( const ADDRESSMODE mode, enum TEXTURE_TARGET target )
259 {
260  if ( !_GFXActiveTextureValid() ) return;
261  GLenum tt = GetGLTextureTarget( target );
262  float BColor[4] = {0, 0, 0, 0}; //set border color to clear... dunno if we wanna change?
263  GLenum wm1, wm2;
264  switch (mode)
265  {
267  case WRAP:
268  wm1 = GL_REPEAT;
269  wm2 = 0;
270  break;
271  case BORDER:
272  wm1 = GL_CLAMP;
274  glTexParameterfv( GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, BColor );
275  //nobreak
276  case CLAMP:
277  wm1 = GL_CLAMP;
278  wm2 = GL_CLAMP_TO_EDGE_EXT;
279  break;
280  case MIRROR: //nope not goin here I hope nVidia extension?
281  default:
282  return; //won't work
283  }
284  glTexParameteri( tt, GL_TEXTURE_WRAP_S, wm1 );
285  if (target != TEXTURE1D)
286  glTexParameteri( tt, GL_TEXTURE_WRAP_T, wm1 );
287  if (target == TEXTURE3D || target == CUBEMAP)
288  glTexParameteri( tt, GL_TEXTURE_WRAP_R, wm1 );
289  if (wm2) {
290  glTexParameteri( tt, GL_TEXTURE_WRAP_S, wm2 );
291  if (target != TEXTURE1D)
292  glTexParameteri( tt, GL_TEXTURE_WRAP_T, wm2 );
293  if (target == TEXTURE3D || target == CUBEMAP)
294  glTexParameteri( tt, GL_TEXTURE_WRAP_R, wm2 );
295  }
296 }
297 
298 struct BlendMode
299 {
302  {
303  sfactor = dfactor = ONE;
304  }
305 }
307 
308 using std::stack;
309 stack< BlendMode >blendstack;
310 
311 void /*GFXDRVAPI*/ GFXGetBlendMode( enum BLENDFUNC &src, enum BLENDFUNC &dst )
312 {
313  src = currBlendMode.sfactor;
314  dst = currBlendMode.dfactor;
315 }
316 
317 static GLenum blendToGL(const enum BLENDFUNC func)
318 {
319  switch (func)
320  {
321  default:
322  case ZERO: return GL_ZERO;
323  case ONE: return GL_ONE;
324  case SRCALPHA: return GL_SRC_ALPHA;
325  case INVSRCALPHA: return GL_ONE_MINUS_SRC_ALPHA;
326  case DESTALPHA: return GL_DST_ALPHA;
327  case INVDESTALPHA: return GL_ONE_MINUS_DST_ALPHA;
328  case DESTCOLOR: return GL_DST_COLOR;
329  case INVDESTCOLOR: return GL_ONE_MINUS_DST_COLOR;
330  case SRCALPHASAT: return GL_SRC_ALPHA_SATURATE;
331 #ifndef _WIN32
332  case CONSTALPHA: return GL_CONSTANT_ALPHA;
334  case CONSTCOLOR: return GL_CONSTANT_COLOR;
336 #endif
337  case SRCCOLOR: return GL_SRC_COLOR;
338  case INVSRCCOLOR: return GL_ONE_MINUS_SRC_COLOR;
339  }
340 }
341 
342 void GFXBlendMode( const enum BLENDFUNC src, const enum BLENDFUNC dst )
343 {
344  GLenum sfactor = blendToGL(src);
345  GLenum dfactor = blendToGL(dst);
346  glBlendFunc( sfactor, dfactor );
347  currBlendMode.sfactor = src;
348  currBlendMode.dfactor = dst;
349 }
350 
352 {
353  blendstack.push( currBlendMode );
354 }
355 
357 {
358  if ( !blendstack.empty() ) {
359  currBlendMode = blendstack.top();
361  blendstack.pop();
362  }
363 }
364 
365 void GFXColorMaterial( int LIGHTTARG )
366 {
367  if (LIGHTTARG) {
368  glEnable( GL_COLOR_MATERIAL );
369  switch (LIGHTTARG)
370  {
371  case EMISSION:
372  glColorMaterial( GL_FRONT_AND_BACK, GL_EMISSION );
373  break;
374  case AMBIENT:
375  glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT );
376  break;
377  case DIFFUSE:
378  glColorMaterial( GL_FRONT_AND_BACK, GL_DIFFUSE );
379  break;
380  case (AMBIENT|DIFFUSE):
381  glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE );
382  break;
383  case SPECULAR:
384  glColorMaterial( GL_FRONT_AND_BACK, GL_SPECULAR );
385  break;
386  }
387  } else {
388  glDisable( GL_COLOR_MATERIAL );
389  }
390 }
391 
393 
395 {
396  return cur_depth_func;
397 }
398 
399 void GFXDepthFunc( enum DEPTHFUNC dfunc )
400 {
401  GLenum func;
402  switch (dfunc)
403  {
404  case NEVER:
405  func = GL_NEVER;
406  break;
407  case LESS:
408  func = GL_LESS;
409  break;
410  case EQUAL:
411  func = GL_EQUAL;
412  break;
413  case LEQUAL:
414  func = GL_LEQUAL;
415  break;
416  case GREATER:
417  func = GL_GREATER;
418  break;
419  case NEQUAL:
420  func = GL_NOTEQUAL;
421  break;
422  case GEQUAL:
423  func = GL_GEQUAL;
424  break;
425  case ALWAYS:
426  func = GL_ALWAYS;
427  break;
428  default:
429  func = GL_NEVER;
430  break;
431  }
432  glDepthFunc( func );
433  cur_depth_func = dfunc;
434 }
435 
437 static int cur_stencil_func_ref = 0;
438 static unsigned int cur_stencil_func_mask = ~0;
439 static unsigned int cur_stencil_mask = ~0;
443 
445 {
446  return cur_stencil_func;
447 }
448 
449 void GFXStencilFunc( enum DEPTHFUNC *pFunc, int *pRef, int *pMask )
450 {
451  if (pFunc) *pFunc = cur_stencil_func;
452  if (pRef) *pRef = cur_stencil_func_ref;
453  if (pMask) *pMask = cur_stencil_func_mask;
454 }
455 
456 void GFXStencilFunc( enum DEPTHFUNC sfunc, int ref, unsigned int mask )
457 {
458  GLenum func;
459  switch (sfunc)
460  {
461  case NEVER:
462  func = GL_NEVER;
463  break;
464  case LESS:
465  func = GL_LESS;
466  break;
467  case EQUAL:
468  func = GL_EQUAL;
469  break;
470  case LEQUAL:
471  func = GL_LEQUAL;
472  break;
473  case GREATER:
474  func = GL_GREATER;
475  break;
476  case NEQUAL:
477  func = GL_NOTEQUAL;
478  break;
479  case GEQUAL:
480  func = GL_GEQUAL;
481  break;
482  case ALWAYS:
483  func = GL_ALWAYS;
484  break;
485  default:
486  func = GL_NEVER;
487  break;
488  }
489  glStencilFunc( func, (GLint) ref, (GLuint) mask );
490  cur_stencil_func = sfunc;
491  cur_stencil_func_ref = ref;
492  cur_stencil_func_mask = mask;
493 }
494 
495 void GFXStencilOp( enum STENCILOP *pFail, enum STENCILOP *pZfail, enum STENCILOP *pZpass )
496 {
497  if (pFail) *pFail = cur_stencil_op_f;
498  if (pZfail) *pZfail = cur_stencil_op_zf;
499  if (pZpass) *pZpass = cur_stencil_op_zp;
500 }
501 
502 void GFXStencilOp( enum STENCILOP fail, enum STENCILOP zfail, enum STENCILOP zpass )
503 {
504  GLenum ffunc, zffunc, zpfunc;
505  switch (fail)
506  {
507  case KEEP:
508  ffunc = GL_KEEP;
509  break;
510  case CLEAR:
511  ffunc = GL_ZERO;
512  break;
513  case REPLACE:
514  ffunc = GL_REPLACE;
515  break;
516  case INCR:
517  ffunc = GL_INCR;
518  break;
519  case DECR:
520  ffunc = GL_DECR;
521  break;
522  case INVERT:
523  ffunc = GL_INVERT;
524  break;
525  default:
526  ffunc = GL_KEEP;
527  break;
528  }
529  switch (zfail)
530  {
531  case KEEP:
532  zffunc = GL_KEEP;
533  break;
534  case CLEAR:
535  zffunc = GL_ZERO;
536  break;
537  case REPLACE:
538  zffunc = GL_REPLACE;
539  break;
540  case INCR:
541  zffunc = GL_INCR;
542  break;
543  case DECR:
544  zffunc = GL_DECR;
545  break;
546  case INVERT:
547  zffunc = GL_INVERT;
548  break;
549  default:
550  zffunc = GL_KEEP;
551  break;
552  }
553  switch (zpass)
554  {
555  case KEEP:
556  zpfunc = GL_KEEP;
557  break;
558  case CLEAR:
559  zpfunc = GL_ZERO;
560  break;
561  case REPLACE:
562  zpfunc = GL_REPLACE;
563  break;
564  case INCR:
565  zpfunc = GL_INCR;
566  break;
567  case DECR:
568  zpfunc = GL_DECR;
569  break;
570  case INVERT:
571  zpfunc = GL_INVERT;
572  break;
573  default:
574  zpfunc = GL_KEEP;
575  break;
576  }
577  glStencilOp( ffunc, zffunc, zpfunc );
578  cur_stencil_op_f = fail;
579  cur_stencil_op_zf = zfail;
580  cur_stencil_op_zp = zpass;
581 }
582 
583 unsigned int GFXStencilMask()
584 {
585  return cur_stencil_mask;
586 }
587 
588 void GFXStencilMask( unsigned int mask )
589 {
590  glStencilMask( (GLuint) mask );
591  cur_stencil_mask = mask;
592 }
593 
594 void GFXActiveTexture( const int stage )
595 {
596 #if !defined (IRIX)
598  glActiveTextureARB_p( GL_TEXTURE0_ARB+stage );
599  activeTextureStage = stage;
600  } else {
601  activeTextureStage = stage; //This ensures consistent behavior - they shouldn't even call us
602  }
603 #endif
604 }
605 
606 void GFXAlphaTest( const enum DEPTHFUNC df, const float ref )
607 {
608  if (df == ALWAYS) {
609  glDisable( GL_ALPHA_TEST );
610  return;
611  } else {
612  glEnable( GL_ALPHA_TEST );
613  }
614  GLenum tmp;
615  switch (df)
616  {
617  case NEVER:
618  tmp = GL_NEVER;
619  break;
620  case LESS:
621  tmp = GL_LESS;
622  break;
623  case EQUAL:
624  tmp = GL_EQUAL;
625  break;
626  case LEQUAL:
627  tmp = GL_LEQUAL;
628  break;
629  case GREATER:
630  tmp = GL_GREATER;
631  break;
632  case NEQUAL:
633  tmp = GL_NOTEQUAL;
634  break;
635  case GEQUAL:
636  tmp = GL_GEQUAL;
637  break;
638  default:
639  case ALWAYS:
640  tmp = GL_ALWAYS;
641  break;
642  }
643  glAlphaFunc( tmp, ref );
644 }
645