]> icculus.org git repositories - icculus/iodoom3.git/blob - neo/renderer/draw_r200.cpp
Use the same OpenAL headers on all platforms.
[icculus/iodoom3.git] / neo / renderer / draw_r200.cpp
1 /*
2 ===========================================================================
3
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company. 
6
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).  
8
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code.  If not, see <http://www.gnu.org/licenses/>.
21
22 In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code.  If not, please request a copy in writing from id Software at the address below.
23
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
25
26 ===========================================================================
27 */
28 #include "../idlib/precompiled.h"
29 #pragma hdrstop
30
31 #include "tr_local.h"
32
33 /*
34
35   There are not enough vertex program texture coordinate outputs
36   to have unique texture coordinates for bump, specular, and diffuse,
37   so diffuse and specular are assumed to be the same mapping.
38
39   To handle properly, those cases with different diffuse and specular
40   mapping will need to be run as two passes.
41
42 */
43
44 // changed from 1 to 255 to not conflict with ARB2 program names
45 static int      FPROG_FAST_PATH = 255;
46
47 typedef struct {
48         GLint   numFragmentRegisters;   // 6
49         GLint   numFragmentConstants;   // 8
50         GLint   numPasses;                              // 2
51         GLint   numInstructionsPerPass; // 8
52         GLint   numInstructionsTotal;   // 16
53         GLint   colorAlphaPairing;              // 1
54         GLint   numLoopbackComponenets; // 3
55         GLint   numInputInterpolatorComponents; // 3
56 } atiFragmentShaderInfo_t;
57
58 static atiFragmentShaderInfo_t  fsi;
59
60 typedef struct {
61         // vertex shader invariants
62         int     lightPos;               // light position in object coordinates
63         int     viewerPos;              // viewer position in object coordinates
64         int     lightProjectS;  // projected light s texgen
65         int     lightProjectT;  // projected light t texgen
66         int     lightProjectQ;  // projected light q texgen
67         int     lightFalloffS;  // projected light falloff s texgen
68         int     bumpTransformS; // bump TEX0 S transformation
69         int     bumpTransformT; // bump TEX0 T transformation
70         int     colorTransformS;        // diffuse/specular texture matrix
71         int     colorTransformT;        // diffuse/specular texture matrix
72
73         // vertex shader variants
74         int     texCoords;
75         int     vertexColors;
76         int     normals;
77         int     tangents;
78         int     biTangents;
79
80 } atiVertexShaderInfo_t;
81
82 static atiVertexShaderInfo_t    vsi;
83
84 /*
85 ===================
86 RB_R200_ARB_DrawInteraction
87
88 ===================
89 */
90 static void RB_R200_ARB_DrawInteraction( const drawInteraction_t *din ) {
91         // check for the case we can't handle in a single pass (we could calculate this at shader parse time to optimize)
92         if ( din->diffuseImage != globalImages->blackImage && din->specularImage != globalImages->blackImage
93                 && memcmp( din->specularMatrix, din->diffuseMatrix, sizeof( din->diffuseMatrix ) ) ) {
94 //              common->Printf( "Note: Shader %s drawn as two pass on R200\n", din->surf->shader->getName() );
95
96                 // draw the specular as a separate pass with a black diffuse map
97                 drawInteraction_t       d;
98                 d = *din;
99                 d.diffuseImage = globalImages->blackImage;
100                 memcpy( d.diffuseMatrix, d.specularMatrix, sizeof( d.diffuseMatrix ) );
101                 RB_R200_ARB_DrawInteraction( &d );
102
103                 // now fall through and draw the diffuse pass with a black specular map
104                 d = *din;
105                 din = &d;
106                 d.specularImage = globalImages->blackImage;
107         }
108
109         // load all the vertex program parameters
110         qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_LIGHT_ORIGIN, din->localLightOrigin.ToFloatPtr() );
111         qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_VIEW_ORIGIN, din->localViewOrigin.ToFloatPtr() );
112         qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_LIGHT_PROJECT_S, din->lightProjection[0].ToFloatPtr() );
113         qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_LIGHT_PROJECT_T, din->lightProjection[1].ToFloatPtr() );
114         qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_LIGHT_PROJECT_Q, din->lightProjection[2].ToFloatPtr() );
115         qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_LIGHT_FALLOFF_S, din->lightProjection[3].ToFloatPtr() );
116         qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_BUMP_MATRIX_S, din->bumpMatrix[0].ToFloatPtr() );
117         qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_BUMP_MATRIX_T, din->bumpMatrix[1].ToFloatPtr() );
118         qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_DIFFUSE_MATRIX_S, din->diffuseMatrix[0].ToFloatPtr() );
119         qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_DIFFUSE_MATRIX_T, din->diffuseMatrix[1].ToFloatPtr() );
120         qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_SPECULAR_MATRIX_S, din->diffuseMatrix[0].ToFloatPtr() );
121         qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_SPECULAR_MATRIX_T, din->diffuseMatrix[1].ToFloatPtr() );
122
123         const srfTriangles_t    *tri = din->surf->geo;
124         idDrawVert      *ac = (idDrawVert *)vertexCache.Position( tri->ambientCache );
125         qglVertexPointer( 3, GL_FLOAT, sizeof( idDrawVert ), (void *)&ac->xyz );
126
127         static const float zero[4] = { 0, 0, 0, 0 };
128         static const float one[4] = { 1, 1, 1, 1 };
129         static const float negOne[4] = { -1, -1, -1, -1 };
130
131         switch ( din->vertexColor ) {
132         case SVC_IGNORE:
133                 qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_COLOR_MODULATE, zero );
134                 qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_COLOR_ADD, one );
135                 break;
136         case SVC_MODULATE:
137                 qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_COLOR_MODULATE, one );
138                 qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_COLOR_ADD, zero );
139                 break;
140         case SVC_INVERSE_MODULATE:
141                 qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_COLOR_MODULATE, negOne );
142                 qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_COLOR_ADD, one );
143                 break;
144         }
145
146
147         // texture 0 = light projection
148         // texture 1 = light falloff
149         // texture 2 = surface diffuse
150         // texture 3 = surface specular
151         // texture 4 = surface bump
152         // texture 5 = normalization cube map
153
154         GL_SelectTexture( 5 );
155         if ( din->ambientLight ) {
156                 globalImages->ambientNormalMap->Bind();
157         } else {
158                 globalImages->normalCubeMapImage->Bind();
159         }
160
161         GL_SelectTexture( 4 );
162         din->bumpImage->Bind();
163
164         GL_SelectTexture( 3 );
165         din->specularImage->Bind();
166         qglTexCoordPointer( 3, GL_FLOAT, sizeof( idDrawVert ), (void *)&ac->normal );
167
168         GL_SelectTexture( 2 );
169         din->diffuseImage->Bind();
170         qglTexCoordPointer( 3, GL_FLOAT, sizeof( idDrawVert ), (void *)&ac->tangents[1][0] );
171
172         GL_SelectTexture( 1 );
173         din->lightFalloffImage->Bind();
174         qglTexCoordPointer( 3, GL_FLOAT, sizeof( idDrawVert ), (void *)&ac->tangents[0][0] );
175
176         GL_SelectTexture( 0 );
177         din->lightImage->Bind();
178         qglTexCoordPointer( 2, GL_FLOAT, sizeof( idDrawVert ), (void *)&ac->st[0] );
179
180         qglSetFragmentShaderConstantATI( GL_CON_0_ATI, din->diffuseColor.ToFloatPtr() );
181         qglSetFragmentShaderConstantATI( GL_CON_1_ATI, din->specularColor.ToFloatPtr() );
182
183         if ( din->vertexColor != SVC_IGNORE ) {
184                 qglColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(idDrawVert), (void *)&ac->color );
185                 qglEnableClientState( GL_COLOR_ARRAY );
186
187                 RB_DrawElementsWithCounters( tri );
188
189                 qglDisableClientState( GL_COLOR_ARRAY );
190                 qglColor4f( 1, 1, 1, 1 );
191         } else {
192                 RB_DrawElementsWithCounters( tri );
193         }
194 }
195
196 /*
197 ==================
198 RB_R200_ARB_CreateDrawInteractions
199 ==================
200 */
201 static void RB_R200_ARB_CreateDrawInteractions( const drawSurf_t *surf ) {
202         if ( !surf ) {
203                 return;
204         }
205
206         // force a space calculation for light vectors
207         backEnd.currentSpace = NULL;
208
209         // set the depth test
210         if ( surf->material->Coverage() == MC_TRANSLUCENT /* != C_PERFORATED */ ) {
211                 GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHMASK | GLS_DEPTHFUNC_LESS );
212         } else {
213                 // only draw on the alpha tested pixels that made it to the depth buffer
214                 GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHMASK | GLS_DEPTHFUNC_EQUAL );
215         }
216
217         // start the vertex shader
218         qglBindProgramARB( GL_VERTEX_PROGRAM_ARB, VPROG_R200_INTERACTION );
219         qglEnable(GL_VERTEX_PROGRAM_ARB);
220
221         // start the fragment shader
222         qglBindFragmentShaderATI( FPROG_FAST_PATH );
223 #if defined( MACOS_X )
224         qglEnable( GL_TEXT_FRAGMENT_SHADER_ATI );
225 #else
226         qglEnable( GL_FRAGMENT_SHADER_ATI );
227 #endif
228
229         qglColor4f( 1, 1, 1, 1 );
230
231         GL_SelectTexture( 1 );
232         qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
233         GL_SelectTexture( 2 );
234         qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
235         GL_SelectTexture( 3 );
236         qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
237
238         for ( ; surf ; surf=surf->nextOnLight ) {
239                 RB_CreateSingleDrawInteractions( surf, RB_R200_ARB_DrawInteraction );
240         }
241
242         GL_SelectTexture( 5 );
243         globalImages->BindNull();
244
245         GL_SelectTexture( 4 );
246         globalImages->BindNull();
247
248         GL_SelectTexture( 3 );
249         globalImages->BindNull();
250         qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
251
252         GL_SelectTexture( 2 );
253         globalImages->BindNull();
254         qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
255
256         GL_SelectTexture( 1 );
257         globalImages->BindNull();
258         qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
259
260         GL_SelectTexture( 0 );
261
262         qglDisable( GL_VERTEX_PROGRAM_ARB );
263 #if defined( MACOS_X )
264         qglDisable( GL_TEXT_FRAGMENT_SHADER_ATI );
265 #else
266         qglDisable( GL_FRAGMENT_SHADER_ATI );
267 #endif
268 }
269
270
271
272 /*
273 ==================
274 RB_R200_DrawInteractions
275
276 ==================
277 */
278 void RB_R200_DrawInteractions( void ) {
279         qglEnable( GL_STENCIL_TEST );
280
281         for ( viewLight_t *vLight = backEnd.viewDef->viewLights ; vLight ; vLight = vLight->next ) {
282                 // do fogging later
283                 if ( vLight->lightShader->IsFogLight() ) {
284                         continue;
285                 }
286                 if ( vLight->lightShader->IsBlendLight() ) {
287                         continue;
288                 }
289
290                 backEnd.vLight = vLight;
291
292                 RB_LogComment( "---------- RB_RenderViewLight 0x%p ----------\n", vLight );
293
294                 // clear the stencil buffer if needed
295                 if ( vLight->globalShadows || vLight->localShadows ) {
296                         backEnd.currentScissor = vLight->scissorRect;
297                         if ( r_useScissor.GetBool() ) {
298                                 qglScissor( backEnd.viewDef->viewport.x1 + backEnd.currentScissor.x1, 
299                                         backEnd.viewDef->viewport.y1 + backEnd.currentScissor.y1,
300                                         backEnd.currentScissor.x2 + 1 - backEnd.currentScissor.x1,
301                                         backEnd.currentScissor.y2 + 1 - backEnd.currentScissor.y1 );
302                         }
303                         qglClear( GL_STENCIL_BUFFER_BIT );
304                 } else {
305                         // no shadows, so no need to read or write the stencil buffer
306                         // we might in theory want to use GL_ALWAYS instead of disabling
307                         // completely, to satisfy the invarience rules
308                         qglStencilFunc( GL_ALWAYS, 128, 255 );
309                 }
310
311                 if ( r_useShadowVertexProgram.GetBool() ) {
312                         qglEnable( GL_VERTEX_PROGRAM_ARB );
313                         qglBindProgramARB( GL_VERTEX_PROGRAM_ARB, VPROG_STENCIL_SHADOW );
314                         RB_StencilShadowPass( vLight->globalShadows );
315
316                         RB_R200_ARB_CreateDrawInteractions( vLight->localInteractions );
317
318                         qglEnable( GL_VERTEX_PROGRAM_ARB );
319                         qglBindProgramARB( GL_VERTEX_PROGRAM_ARB, VPROG_STENCIL_SHADOW );
320                         RB_StencilShadowPass( vLight->localShadows );
321
322                         RB_R200_ARB_CreateDrawInteractions( vLight->globalInteractions );
323
324                         qglDisable( GL_VERTEX_PROGRAM_ARB );    // if there weren't any globalInteractions, it would have stayed on
325                 } else {
326                         RB_StencilShadowPass( vLight->globalShadows );
327                         RB_R200_ARB_CreateDrawInteractions( vLight->localInteractions );
328
329                         RB_StencilShadowPass( vLight->localShadows );
330                         RB_R200_ARB_CreateDrawInteractions( vLight->globalInteractions );
331                 }
332
333                 if ( r_skipTranslucent.GetBool() ) {
334                         continue;
335                 }
336
337                 // disable stencil testing for translucent interactions, because
338                 // the shadow isn't calculated at their point, and the shadow
339                 // behind them may be depth fighting with a back side, so there
340                 // isn't any reasonable thing to do
341                 qglStencilFunc( GL_ALWAYS, 128, 255 );
342                 RB_R200_ARB_CreateDrawInteractions( vLight->translucentInteractions );
343         }
344 }
345
346
347 /*
348 =================
349 R_BuildSurfaceFragmentProgram
350 =================
351 */
352 static void R_BuildSurfaceFragmentProgram( int programNum ) {
353         qglBindFragmentShaderATI( programNum );
354
355         qglBeginFragmentShaderATI();
356
357         // texture 0 = light projection
358         // texture 1 = light falloff
359         // texture 2 = surface diffuse
360         // texture 3 = surface specular
361         // texture 4 = surface bump
362         // texture 5 = normalization cube map
363
364         // texcoord 0 = light projection texGen
365         // texcoord 1 = light falloff texGen
366         // texcoord 2 = bumpmap texCoords
367         // texcoord 3 = specular / diffuse texCoords
368         // texcoord 4 = halfangle vector in local tangent space
369         // texcoord 5 = vector to light in local tangent space
370
371         // constant 0 = diffuse modulate
372         // constant 1 = specular modulate
373         // constant 5 = internal use for 0.75 constant
374
375         qglSampleMapATI( GL_REG_0_ATI, GL_TEXTURE0_ARB, GL_SWIZZLE_STQ_DQ_ATI );
376         qglSampleMapATI( GL_REG_1_ATI, GL_TEXTURE1_ARB, GL_SWIZZLE_STR_ATI );
377         qglSampleMapATI( GL_REG_4_ATI, GL_TEXTURE2_ARB, GL_SWIZZLE_STR_ATI );
378         qglSampleMapATI( GL_REG_5_ATI, GL_TEXTURE5_ARB, GL_SWIZZLE_STR_ATI );
379
380         // move the alpha component to the red channel to support rxgb normal map compression
381         if ( globalImages->image_useNormalCompression.GetInteger() == 2 ) {
382                 qglColorFragmentOp1ATI( GL_MOV_ATI, GL_REG_4_ATI, GL_RED_BIT_ATI, GL_NONE,
383                         GL_REG_4_ATI, GL_ALPHA, GL_NONE );
384         }
385
386         // light projection * light falloff
387         qglColorFragmentOp2ATI( GL_MUL_ATI, GL_REG_0_ATI, GL_NONE, GL_NONE,
388                 GL_REG_0_ATI, GL_NONE, GL_NONE,
389                 GL_REG_1_ATI, GL_NONE, GL_NONE );
390
391         // vectorToLight dot bumpMap
392         qglColorFragmentOp2ATI( GL_DOT3_ATI, GL_REG_1_ATI, GL_NONE, GL_SATURATE_BIT_ATI,
393                 GL_REG_4_ATI, GL_NONE, GL_2X_BIT_ATI | GL_BIAS_BIT_ATI,
394                 GL_REG_5_ATI, GL_NONE, GL_2X_BIT_ATI | GL_BIAS_BIT_ATI );
395
396         // bump * light
397         qglColorFragmentOp2ATI( GL_MUL_ATI, GL_REG_0_ATI, GL_NONE, GL_NONE,
398                 GL_REG_0_ATI, GL_NONE, GL_NONE,
399                 GL_REG_1_ATI, GL_NONE, GL_NONE );
400
401         //-------------------
402
403         // carry over the incomingLight calculation
404         qglPassTexCoordATI( GL_REG_0_ATI, GL_REG_0_ATI, GL_SWIZZLE_STR_ATI );
405
406         // sample the diffuse surface map
407         qglSampleMapATI( GL_REG_2_ATI, GL_TEXTURE3_ARB, GL_SWIZZLE_STR_ATI );
408
409         // sample the specular surface map
410         qglSampleMapATI( GL_REG_3_ATI, GL_TEXTURE3_ARB, GL_SWIZZLE_STR_ATI );
411
412         // we will use the surface bump map again
413         qglPassTexCoordATI( GL_REG_4_ATI, GL_REG_4_ATI, GL_SWIZZLE_STR_ATI );
414
415         // normalize the specular halfangle
416         qglSampleMapATI( GL_REG_5_ATI, GL_TEXTURE4_ARB, GL_SWIZZLE_STR_ATI );
417         
418         // R1 = halfangle dot surfaceNormal
419         qglColorFragmentOp2ATI( GL_DOT3_ATI, GL_REG_1_ATI, GL_NONE, GL_SATURATE_BIT_ATI,
420                 GL_REG_4_ATI, GL_NONE, GL_2X_BIT_ATI | GL_BIAS_BIT_ATI,
421                 GL_REG_5_ATI, GL_NONE, GL_2X_BIT_ATI | GL_BIAS_BIT_ATI );
422
423         // R1 = 4 * ( R1 - 0.75 )
424         // subtract 0.75 and quadruple to tighten the specular spot
425         float data[4] = { 0.75, 0.75,  0.75,  0.75 };
426         qglSetFragmentShaderConstantATI( GL_CON_5_ATI, data );
427         qglColorFragmentOp2ATI( GL_SUB_ATI, GL_REG_1_ATI, GL_NONE, GL_4X_BIT_ATI | GL_SATURATE_BIT_ATI,
428                 GL_REG_1_ATI, GL_NONE, GL_NONE,
429                 GL_CON_5_ATI, GL_NONE, GL_NONE );
430
431         // R1 = R1 * R1
432         // sqare the stretched specular result
433         qglColorFragmentOp2ATI( GL_MUL_ATI, GL_REG_1_ATI, GL_NONE, GL_SATURATE_BIT_ATI,
434                 GL_REG_1_ATI, GL_NONE, GL_NONE,
435                 GL_REG_1_ATI, GL_NONE, GL_NONE );
436
437         // R1 = R1 * R3
438         // R1 = specular power * specular texture * 2
439         qglColorFragmentOp2ATI( GL_MUL_ATI, GL_REG_1_ATI, GL_NONE, GL_2X_BIT_ATI | GL_SATURATE_BIT_ATI,
440                 GL_REG_1_ATI, GL_NONE, GL_NONE,
441                 GL_REG_3_ATI, GL_NONE, GL_NONE );
442
443         // R2 = R2 * CONST0
444         // down modulate the diffuse map
445         qglColorFragmentOp2ATI( GL_MUL_ATI, GL_REG_2_ATI, GL_NONE, GL_SATURATE_BIT_ATI,
446                 GL_REG_2_ATI, GL_NONE, GL_NONE,
447                 GL_CON_0_ATI, GL_NONE, GL_NONE );
448
449         // R2 = R2 + R1 * CONST1
450         // diffuse + specular * specular color
451         qglColorFragmentOp3ATI( GL_MAD_ATI, GL_REG_2_ATI, GL_NONE, GL_SATURATE_BIT_ATI,
452                 GL_REG_1_ATI, GL_NONE, GL_NONE,
453                 GL_CON_1_ATI, GL_NONE, GL_NONE,
454                 GL_REG_2_ATI, GL_NONE, GL_NONE );
455
456         // out = reflectance * incoming light
457         qglColorFragmentOp2ATI( GL_MUL_ATI, GL_REG_0_ATI, GL_NONE, GL_SATURATE_BIT_ATI,
458                 GL_REG_0_ATI, GL_NONE, GL_NONE,
459                 GL_REG_2_ATI, GL_NONE, GL_NONE );
460
461         // out * vertex color
462         qglColorFragmentOp2ATI( GL_MUL_ATI, GL_REG_0_ATI, GL_NONE, GL_NONE,
463                 GL_REG_0_ATI, GL_NONE, GL_NONE,
464                 GL_PRIMARY_COLOR_ARB, GL_NONE, GL_NONE );
465
466         // out alpha = 0 to allow blending optimization
467         qglAlphaFragmentOp1ATI( GL_MOV_ATI, GL_REG_0_ATI, GL_NONE,
468                 GL_ZERO, GL_NONE, GL_NONE );
469
470         qglEndFragmentShaderATI();
471
472         GL_CheckErrors();
473 }
474
475 /*
476 =================
477 R_R200_Init
478 =================
479 */
480 void R_R200_Init( void ) {
481         glConfig.allowR200Path = false;
482
483         common->Printf( "----------- R200_Init -----------\n" );
484
485         if ( !glConfig.atiFragmentShaderAvailable || !glConfig.ARBVertexProgramAvailable || !glConfig.ARBVertexBufferObjectAvailable ) {
486                 common->Printf( "Not available.\n" );
487                 return;
488         }
489
490         GL_CheckErrors();
491
492         qglGetIntegerv( GL_NUM_FRAGMENT_REGISTERS_ATI, &fsi.numFragmentRegisters );
493         qglGetIntegerv( GL_NUM_FRAGMENT_CONSTANTS_ATI, &fsi.numFragmentConstants );
494         qglGetIntegerv( GL_NUM_PASSES_ATI, &fsi.numPasses );
495         qglGetIntegerv( GL_NUM_INSTRUCTIONS_PER_PASS_ATI, &fsi.numInstructionsPerPass );
496         qglGetIntegerv( GL_NUM_INSTRUCTIONS_TOTAL_ATI, &fsi.numInstructionsTotal );
497         qglGetIntegerv( GL_COLOR_ALPHA_PAIRING_ATI, &fsi.colorAlphaPairing );
498         qglGetIntegerv( GL_NUM_LOOPBACK_COMPONENTS_ATI, &fsi.numLoopbackComponenets );
499         qglGetIntegerv( GL_NUM_INPUT_INTERPOLATOR_COMPONENTS_ATI, &fsi.numInputInterpolatorComponents );
500
501         common->Printf( "GL_NUM_FRAGMENT_REGISTERS_ATI: %i\n", fsi.numFragmentRegisters );
502         common->Printf( "GL_NUM_FRAGMENT_CONSTANTS_ATI: %i\n", fsi.numFragmentConstants );
503         common->Printf( "GL_NUM_PASSES_ATI: %i\n", fsi.numPasses );
504         common->Printf( "GL_NUM_INSTRUCTIONS_PER_PASS_ATI: %i\n", fsi.numInstructionsPerPass );
505         common->Printf( "GL_NUM_INSTRUCTIONS_TOTAL_ATI: %i\n", fsi.numInstructionsTotal );
506         common->Printf( "GL_COLOR_ALPHA_PAIRING_ATI: %i\n", fsi.colorAlphaPairing );
507         common->Printf( "GL_NUM_LOOPBACK_COMPONENTS_ATI: %i\n", fsi.numLoopbackComponenets );
508         common->Printf( "GL_NUM_INPUT_INTERPOLATOR_COMPONENTS_ATI: %i\n", fsi.numInputInterpolatorComponents );
509
510         common->Printf( "FPROG_FAST_PATH\n" );
511         R_BuildSurfaceFragmentProgram( FPROG_FAST_PATH );
512
513         common->Printf( "---------------------\n" );
514
515         glConfig.allowR200Path = true;
516 }