summaryrefslogtreecommitdiffstats
path: root/libvo
diff options
context:
space:
mode:
authorreimar <reimar@b3059339-0415-0410-9bf9-f77b7e298cf2>2005-10-01 12:49:28 +0000
committerreimar <reimar@b3059339-0415-0410-9bf9-f77b7e298cf2>2005-10-01 12:49:28 +0000
commitd28ad7d31df95ebfa34c1876002b5c7119712b7f (patch)
tree8e5a2b1da40bdfde2644cceca52d732346ab5027 /libvo
parentebd7dadd8857e03e2164c1b871a80ef1f4ca0dd2 (diff)
downloadmpv-d28ad7d31df95ebfa34c1876002b5c7119712b7f.tar.bz2
mpv-d28ad7d31df95ebfa34c1876002b5c7119712b7f.tar.xz
Support for ATI specific YUV->RGB conversion.
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@16626 b3059339-0415-0410-9bf9-f77b7e298cf2
Diffstat (limited to 'libvo')
-rw-r--r--libvo/gl_common.c121
-rw-r--r--libvo/gl_common.h50
2 files changed, 154 insertions, 17 deletions
diff --git a/libvo/gl_common.c b/libvo/gl_common.c
index b5939902c2..218538c527 100644
--- a/libvo/gl_common.c
+++ b/libvo/gl_common.c
@@ -35,6 +35,15 @@ void (APIENTRY *CombinerInput)(GLenum, GLenum, GLenum, GLenum, GLenum,
void (APIENTRY *CombinerOutput)(GLenum, GLenum, GLenum, GLenum, GLenum,
GLenum, GLenum, GLboolean, GLboolean,
GLboolean);
+void (APIENTRY *BeginFragmentShader)(void);
+void (APIENTRY *EndFragmentShader)(void);
+void (APIENTRY *SampleMap)(GLuint, GLuint, GLenum);
+void (APIENTRY *ColorFragmentOp2)(GLenum, GLuint, GLuint, GLuint, GLuint,
+ GLuint, GLuint, GLuint, GLuint, GLuint);
+void (APIENTRY *ColorFragmentOp3)(GLenum, GLuint, GLuint, GLuint, GLuint,
+ GLuint, GLuint, GLuint, GLuint, GLuint,
+ GLuint, GLuint, GLuint);
+void (APIENTRY *SetFragmentShaderConstant)(GLuint, const GLfloat *);
void (APIENTRY *ActiveTexture)(GLenum);
void (APIENTRY *BindTexture)(GLenum, GLuint);
void (APIENTRY *MultiTexCoord2f)(GLenum, GLfloat, GLfloat);
@@ -274,6 +283,12 @@ static void getFunctions(void *(*getProcAddress)(const GLubyte *)) {
CombinerOutput = getProcAddress("glCombinerOutput");
if (!CombinerOutput)
CombinerOutput = getProcAddress("glCombinerOutputNV");
+ BeginFragmentShader = getProcAddress("glBeginFragmentShaderATI");
+ EndFragmentShader = getProcAddress("glEndFragmentShaderATI");
+ SampleMap = getProcAddress("glSampleMapATI");
+ ColorFragmentOp2 = getProcAddress("glColorFragmentOp2ATI");
+ ColorFragmentOp3 = getProcAddress("glColorFragmentOp3ATI");
+ SetFragmentShaderConstant = getProcAddress("glSetFragmentShaderConstantATI");
ActiveTexture = getProcAddress("glActiveTexture");
if (!ActiveTexture)
ActiveTexture = getProcAddress("glActiveTextureARB");
@@ -480,6 +495,28 @@ void glUploadTex(GLenum target, GLenum format, GLenum type,
glTexSubImage2D(target, 0, x, y, w, y_max - y, format, type, data);
}
+static void fillUVcoeff(GLfloat *ucoef, GLfloat *vcoef,
+ float uvcos, float uvsin) {
+ int i;
+ ucoef[0] = 0 * uvcos + 1.403 * uvsin;
+ vcoef[0] = 0 * uvsin + 1.403 * uvcos;
+ ucoef[1] = -0.344 * uvcos + -0.714 * uvsin;
+ vcoef[1] = -0.344 * uvsin + -0.714 * uvcos;
+ ucoef[2] = 1.770 * uvcos + 0 * uvsin;
+ vcoef[2] = 1.770 * uvsin + 0 * uvcos;
+ ucoef[3] = 0;
+ vcoef[3] = 0;
+ // Coefficients (probably) must be in [0, 1] range, whereas they originally
+ // are in [-2, 2] range, so here comes the trick:
+ // First put them in the [-0.5, 0.5] range, then add 0.5.
+ // This can be undone with the HALF_BIAS and SCALE_BY_FOUR arguments
+ // for CombinerInput and CombinerOutput (or the respective ATI variants)
+ for (i = 0; i < 4; i++) {
+ ucoef[i] = ucoef[i] * 0.25 + 0.5;
+ vcoef[i] = vcoef[i] * 0.25 + 0.5;
+ }
+}
+
/**
* \brief Setup register combiners for YUV to RGB conversion.
* \param uvcos used for saturation and hue adjustment
@@ -502,23 +539,7 @@ static void glSetupYUVCombiners(float uvcos, float uvsin) {
mp_msg(MSGT_VO, MSGL_FATAL, "[gl] Combiner functions missing!\n");
return;
}
- ucoef[0] = 0 * uvcos + 1.403 * uvsin;
- vcoef[0] = 0 * uvsin + 1.403 * uvcos;
- ucoef[1] = -0.344 * uvcos + -0.714 * uvsin;
- vcoef[1] = -0.344 * uvsin + -0.714 * uvcos;
- ucoef[2] = 1.770 * uvcos + 0 * uvsin;
- vcoef[2] = 1.770 * uvsin + 0 * uvcos;
- ucoef[3] = 0;
- vcoef[3] = 0;
- // Coefficients (probably) must be in [0, 1] range, whereas they originally
- // are in [-2, 2] range, so here comes the trick:
- // First put them in the [-0.5, 0.5] range, then add 0.5.
- // This can be undone with the HALF_BIAS and SCALE_BY_FOUR arguments
- // for CombinerInput and CombinerOutput
- for (i = 0; i < 4; i++) {
- ucoef[i] = ucoef[i] * 0.25 + 0.5;
- vcoef[i] = vcoef[i] * 0.25 + 0.5;
- }
+ fillUVcoeff(ucoef, vcoef, uvcos, uvsin);
CombinerParameterfv(GL_CONSTANT_COLOR0_NV, ucoef);
CombinerParameterfv(GL_CONSTANT_COLOR1_NV, vcoef);
@@ -552,6 +573,53 @@ static void glSetupYUVCombiners(float uvcos, float uvsin) {
CombinerParameteri(GL_NUM_GENERAL_COMBINERS_NV, 2);
}
+/**
+ * \brief Setup ATI version of register combiners for YUV to RGB conversion.
+ * \param uvcos used for saturation and hue adjustment
+ * \param uvsin used for saturation and hue adjustment
+ *
+ * ATI called this fragment shader, but the name is confusing in the
+ * light of a very different OpenGL 2.0 extension with the same name
+ */
+static void glSetupYUVCombinersATI(float uvcos, float uvsin) {
+ GLfloat ucoef[4];
+ GLfloat vcoef[4];
+ GLint i;
+ glGetIntegerv(GL_NUM_FRAGMENT_REGISTERS_ATI, &i);
+ if (i < 3)
+ mp_msg(MSGT_VO, MSGL_ERR,
+ "[gl] 3 registers needed for YUV combiner (ATI) support (found %i)\n", i);
+ glGetIntegerv (GL_MAX_TEXTURE_UNITS, &i);
+ if (i < 3)
+ mp_msg(MSGT_VO, MSGL_ERR,
+ "[gl] 3 texture units needed for YUV combiner (ATI) support (found %i)\n", i);
+ if (!BeginFragmentShader || !EndFragmentShader ||
+ !SetFragmentShaderConstant || !SampleMap ||
+ !ColorFragmentOp2 || !ColorFragmentOp3) {
+ mp_msg(MSGT_VO, MSGL_FATAL, "[gl] Combiner (ATI) functions missing!\n");
+ return;
+ }
+ fillUVcoeff(ucoef, vcoef, uvcos, uvsin);
+ BeginFragmentShader();
+ SetFragmentShaderConstant(GL_CON_0_ATI, ucoef);
+ SetFragmentShaderConstant(GL_CON_1_ATI, vcoef);
+ SampleMap(GL_REG_0_ATI, GL_TEXTURE0, GL_SWIZZLE_STR_ATI);
+ SampleMap(GL_REG_1_ATI, GL_TEXTURE1, GL_SWIZZLE_STR_ATI);
+ SampleMap(GL_REG_2_ATI, GL_TEXTURE2, GL_SWIZZLE_STR_ATI);
+ // UV first, like this green component cannot overflow
+ ColorFragmentOp2(GL_MUL_ATI, GL_REG_1_ATI, GL_NONE, GL_NONE,
+ GL_REG_1_ATI, GL_NONE, GL_BIAS_BIT_ATI,
+ GL_CON_0_ATI, GL_NONE, GL_BIAS_BIT_ATI);
+ ColorFragmentOp3(GL_MAD_ATI, GL_REG_2_ATI, GL_NONE, GL_4X_BIT_ATI,
+ GL_REG_2_ATI, GL_NONE, GL_BIAS_BIT_ATI,
+ GL_CON_1_ATI, GL_NONE, GL_BIAS_BIT_ATI,
+ GL_REG_1_ATI, GL_NONE, GL_NONE);
+ ColorFragmentOp2(GL_ADD_ATI, GL_REG_0_ATI, GL_NONE, GL_NONE,
+ GL_REG_0_ATI, GL_NONE, GL_NONE,
+ GL_REG_2_ATI, GL_NONE, GL_NONE);
+ EndFragmentShader();
+}
+
static const char *yuv_prog_template =
"!!ARBfp1.0\n"
"OPTION ARB_precision_hint_fastest;"
@@ -713,6 +781,9 @@ void glSetupYUVConversion(GLenum target, int type,
case YUV_CONVERSION_COMBINERS:
glSetupYUVCombiners(uvcos, uvsin);
break;
+ case YUV_CONVERSION_COMBINERS_ATI:
+ glSetupYUVCombinersATI(uvcos, uvsin);
+ break;
case YUV_CONVERSION_FRAGMENT_LOOKUP:
{
unsigned char lookup_data[4 * LOOKUP_RES];
@@ -752,6 +823,14 @@ void inline glEnableYUVConversion(GLenum target, int type) {
ActiveTexture(GL_TEXTURE0);
glEnable(GL_REGISTER_COMBINERS_NV);
break;
+ case YUV_CONVERSION_COMBINERS_ATI:
+ ActiveTexture(GL_TEXTURE1);
+ glEnable(target);
+ ActiveTexture(GL_TEXTURE2);
+ glEnable(target);
+ ActiveTexture(GL_TEXTURE0);
+ glEnable(GL_FRAGMENT_SHADER_ATI);
+ break;
case YUV_CONVERSION_FRAGMENT_LOOKUP:
case YUV_CONVERSION_FRAGMENT_POW:
case YUV_CONVERSION_FRAGMENT:
@@ -777,6 +856,14 @@ void inline glDisableYUVConversion(GLenum target, int type) {
ActiveTexture(GL_TEXTURE0);
glDisable(GL_REGISTER_COMBINERS_NV);
break;
+ case YUV_CONVERSION_COMBINERS_ATI:
+ ActiveTexture(GL_TEXTURE1);
+ glDisable(target);
+ ActiveTexture(GL_TEXTURE2);
+ glDisable(target);
+ ActiveTexture(GL_TEXTURE0);
+ glDisable(GL_FRAGMENT_SHADER_ATI);
+ break;
case YUV_CONVERSION_FRAGMENT_LOOKUP:
case YUV_CONVERSION_FRAGMENT_POW:
case YUV_CONVERSION_FRAGMENT:
diff --git a/libvo/gl_common.h b/libvo/gl_common.h
index 2f967e8c1d..fe73ecc73a 100644
--- a/libvo/gl_common.h
+++ b/libvo/gl_common.h
@@ -76,6 +76,45 @@
#ifndef GL_SPARE0_NV
#define GL_SPARE0_NV 0x852E
#endif
+#ifndef GL_FRAGMENT_SHADER_ATI
+#define GL_FRAGMENT_SHADER_ATI 0x8920
+#endif
+#ifndef GL_NUM_FRAGMENT_REGISTERS_ATI
+#define GL_NUM_FRAGMENT_REGISTERS_ATI 0x896E
+#endif
+#ifndef GL_REG_0_ATI
+#define GL_REG_0_ATI 0x8921
+#endif
+#ifndef GL_REG_1_ATI
+#define GL_REG_1_ATI 0x8922
+#endif
+#ifndef GL_REG_2_ATI
+#define GL_REG_2_ATI 0x8923
+#endif
+#ifndef GL_CON_0_ATI
+#define GL_CON_0_ATI 0x8941
+#endif
+#ifndef GL_CON_1_ATI
+#define GL_CON_1_ATI 0x8942
+#endif
+#ifndef GL_ADD_ATI
+#define GL_ADD_ATI 0x8963
+#endif
+#ifndef GL_MUL_ATI
+#define GL_MUL_ATI 0x8964
+#endif
+#ifndef GL_MAD_ATI
+#define GL_MAD_ATI 0x8968
+#endif
+#ifndef GL_SWIZZLE_STR_ATI
+#define GL_SWIZZLE_STR_ATI 0x8976
+#endif
+#ifndef GL_4X_BIT_ATI
+#define GL_4X_BIT_ATI 2
+#endif
+#ifndef GL_BIAS_BIT_ATI
+#define GL_BIAS_BIT_ATI 8
+#endif
#ifndef GL_MAX_TEXTURE_UNITS
#define GL_MAX_TEXTURE_UNITS 0x84E2
#endif
@@ -171,6 +210,8 @@ void glDrawTex(GLfloat x, GLfloat y, GLfloat w, GLfloat h,
#define YUV_CONVERSION_FRAGMENT_POW 3
//! use a fragment program with additional table lookup for YUV conversion
#define YUV_CONVERSION_FRAGMENT_LOOKUP 4
+//! use ATI specific register combiners ("fragment program")
+#define YUV_CONVERSION_COMBINERS_ATI 5
/** \} */
void glSetupYUVConversion(GLenum target, int type,
float brightness, float contrast,
@@ -210,6 +251,15 @@ extern void (APIENTRY *CombinerInput)(GLenum, GLenum, GLenum, GLenum, GLenum,
extern void (APIENTRY *CombinerOutput)(GLenum, GLenum, GLenum, GLenum, GLenum,
GLenum, GLenum, GLboolean, GLboolean,
GLboolean);
+extern void (APIENTRY *BeginFragmentShader)(void);
+extern void (APIENTRY *EndFragmentShader)(void);
+extern void (APIENTRY *SampleMap)(GLuint, GLuint, GLenum);
+extern void (APIENTRY *ColorFragmentOp2)(GLenum, GLuint, GLuint, GLuint, GLuint,
+ GLuint, GLuint, GLuint, GLuint, GLuint);
+extern void (APIENTRY *ColorFragmentOp3)(GLenum, GLuint, GLuint, GLuint, GLuint,
+ GLuint, GLuint, GLuint, GLuint, GLuint,
+ GLuint, GLuint, GLuint);
+extern void (APIENTRY *SetFragmentShaderConstant)(GLuint, const GLfloat *);
extern void (APIENTRY *ActiveTexture)(GLenum);
extern void (APIENTRY *BindTexture)(GLenum, GLuint);
extern void (APIENTRY *MultiTexCoord2f)(GLenum, GLfloat, GLfloat);