+void R_SetupShader_SetPermutation(shadermode_t mode, unsigned int permutation)
+{
+ r_glsl_permutation_t *perm = &r_glsl_permutations[mode][permutation];
+ if (r_glsl_permutation != perm)
+ {
+ r_glsl_permutation = perm;
+ if (!r_glsl_permutation->program)
+ {
+ if (!r_glsl_permutation->compiled)
+ R_GLSL_CompilePermutation(mode, permutation);
+ if (!r_glsl_permutation->program)
+ {
+ // remove features until we find a valid permutation
+ int i;
+ for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
+ {
+ // reduce i more quickly whenever it would not remove any bits
+ int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
+ if (!(permutation & j))
+ continue;
+ permutation -= j;
+ r_glsl_permutation = &r_glsl_permutations[mode][permutation];
+ if (!r_glsl_permutation->compiled)
+ R_GLSL_CompilePermutation(mode, permutation);
+ if (r_glsl_permutation->program)
+ break;
+ }
+ if (i >= SHADERPERMUTATION_COUNT)
+ {
+ Con_Printf("OpenGL 2.0 shaders disabled - unable to find a working shader permutation fallback on this driver (set r_glsl 1 if you want to try again)\n");
+ Cvar_SetValueQuick(&r_glsl, 0);
+ R_GLSL_Restart_f(); // unload shaders
+ return; // no bit left to clear
+ }
+ }
+ }
+ CHECKGLERROR
+ qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
+ }
+}
+
+void R_SetupGenericShader(qboolean usetexture)
+{
+ if (gl_support_fragment_shader)
+ {
+ if (r_glsl.integer && r_glsl_usegeneric.integer)
+ R_SetupShader_SetPermutation(SHADERMODE_GENERIC, usetexture ? SHADERPERMUTATION_DIFFUSE : 0);
+ else if (r_glsl_permutation)
+ {
+ r_glsl_permutation = NULL;
+ qglUseProgramObjectARB(0);CHECKGLERROR
+ }
+ }
+}
+
+void R_SetupGenericTwoTextureShader(int texturemode)
+{
+ if (gl_support_fragment_shader)
+ {
+ if (r_glsl.integer && r_glsl_usegeneric.integer)
+ R_SetupShader_SetPermutation(SHADERMODE_GENERIC, SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
+ else if (r_glsl_permutation)
+ {
+ r_glsl_permutation = NULL;
+ qglUseProgramObjectARB(0);CHECKGLERROR
+ }
+ }
+ if (!r_glsl_permutation)
+ {
+ if (texturemode == GL_DECAL && gl_combine.integer)
+ texturemode = GL_INTERPOLATE_ARB;
+ R_Mesh_TexCombine(1, texturemode, texturemode, 1, 1);
+ }
+}
+
+void R_SetupDepthOrShadowShader(void)
+{
+ if (gl_support_fragment_shader)
+ {
+ if (r_glsl.integer && r_glsl_usegeneric.integer)
+ R_SetupShader_SetPermutation(SHADERMODE_DEPTH_OR_SHADOW, 0);
+ else if (r_glsl_permutation)
+ {
+ r_glsl_permutation = NULL;
+ qglUseProgramObjectARB(0);CHECKGLERROR
+ }
+ }
+}
+