+static qboolean R_BlendFuncAllowsColormod(int src, int dst)
+{
+ // a blendfunc allows colormod if:
+ // a) it can never keep the destination pixel invariant, or
+ // b) it can keep the destination pixel invariant, and still can do so if colormodded
+ // this is to prevent unintended side effects from colormod
+
+ // in formulas:
+ // IF there is a (s, sa) for which for all (d, da),
+ // s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
+ // THEN, for this (s, sa) and all (colormod, d, da):
+ // s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
+ // OBVIOUSLY, this means that
+ // s*colormod * src(s*colormod, d, sa, da) = 0
+ // dst(s*colormod, d, sa, da) = 1
+
+ // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
+
+ // main condition to leave dst color invariant:
+ // s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
+ // src == GL_ZERO:
+ // s * 0 + d * dst(s, d, sa, da) == d
+ // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
+ // => colormod is a problem for GL_SRC_COLOR only
+ // src == GL_ONE:
+ // s + d * dst(s, d, sa, da) == d
+ // => s == 0
+ // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
+ // => colormod is never problematic for these
+ // src == GL_SRC_COLOR:
+ // s*s + d * dst(s, d, sa, da) == d
+ // => s == 0
+ // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
+ // => colormod is never problematic for these
+ // src == GL_ONE_MINUS_SRC_COLOR:
+ // s*(1-s) + d * dst(s, d, sa, da) == d
+ // => s == 0 or s == 1
+ // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
+ // => colormod is a problem for GL_SRC_COLOR only
+ // src == GL_DST_COLOR
+ // s*d + d * dst(s, d, sa, da) == d
+ // => s == 1
+ // => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
+ // => colormod is always a problem
+ // or
+ // => s == 0
+ // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
+ // => colormod is never problematic for these
+ // => BUT, we do not know s! We must assume it is problematic
+ // then... except in GL_ONE case, where we know all invariant
+ // cases are fine
+ // src == GL_ONE_MINUS_DST_COLOR
+ // s*(1-d) + d * dst(s, d, sa, da) == d
+ // => s == 0 (1-d is impossible to handle for our desired result)
+ // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
+ // => colormod is never problematic for these
+ // src == GL_SRC_ALPHA
+ // s*sa + d * dst(s, d, sa, da) == d
+ // => s == 0, or sa == 0
+ // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
+ // => colormod breaks in the case GL_SRC_COLOR only
+ // src == GL_ONE_MINUS_SRC_ALPHA
+ // s*(1-sa) + d * dst(s, d, sa, da) == d
+ // => s == 0, or sa == 1
+ // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
+ // => colormod breaks in the case GL_SRC_COLOR only
+ // src == GL_DST_ALPHA
+ // s*da + d * dst(s, d, sa, da) == d
+ // => s == 0
+ // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
+ // => colormod is never problematic for these
+
+ switch(src)
+ {
+ case GL_ZERO:
+ case GL_ONE_MINUS_SRC_COLOR:
+ case GL_SRC_ALPHA:
+ case GL_ONE_MINUS_SRC_ALPHA:
+ if(dst == GL_SRC_COLOR)
+ return false;
+ return true;
+ case GL_ONE:
+ case GL_SRC_COLOR:
+ case GL_ONE_MINUS_DST_COLOR:
+ case GL_DST_ALPHA:
+ case GL_ONE_MINUS_DST_ALPHA:
+ return true;
+ case GL_DST_COLOR:
+ if(dst == GL_ONE)
+ return true;
+ return false;
+ default:
+ return false;
+ }
+}