Share more code between the two ATI fragment shader YUV to RGB

conversion methods and extend them to support more accurate
conversion (though at the cost of some speed).


git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@30995 b3059339-0415-0410-9bf9-f77b7e298cf2
This commit is contained in:
reimar 2010-04-04 11:45:05 +00:00
parent 4a8486f844
commit 22f6170009
1 changed files with 87 additions and 69 deletions

View File

@ -763,80 +763,98 @@ static void glSetupYUVCombiners(float uvcos, float uvsin) {
/**
* \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
* \param csp_params parameters used for colorspace conversion
* \param text if set use the GL_ATI_text_fragment_shader API as
* used on OS X.
*/
static void glSetupYUVCombinersATI(float uvcos, float uvsin) {
GLfloat ucoef[4];
GLfloat vcoef[4];
static void glSetupYUVFragmentATI(struct mp_csp_params *csp_params,
int text) {
GLint i;
if (!mpglBeginFragmentShader || !mpglEndFragmentShader ||
!mpglSetFragmentShaderConstant || !mpglSampleMap ||
!mpglColorFragmentOp2 || !mpglColorFragmentOp3) {
mp_msg(MSGT_VO, MSGL_FATAL, "[gl] Combiner (ATI) functions missing!\n");
return;
}
mpglGetIntegerv(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);
float yuv2rgb[3][4];
mpglGetIntegerv (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);
fillUVcoeff(ucoef, vcoef, uvcos, uvsin);
mpglBeginFragmentShader();
mpglSetFragmentShaderConstant(GL_CON_0_ATI, ucoef);
mpglSetFragmentShaderConstant(GL_CON_1_ATI, vcoef);
mpglSampleMap(GL_REG_0_ATI, GL_TEXTURE0, GL_SWIZZLE_STR_ATI);
mpglSampleMap(GL_REG_1_ATI, GL_TEXTURE1, GL_SWIZZLE_STR_ATI);
mpglSampleMap(GL_REG_2_ATI, GL_TEXTURE2, GL_SWIZZLE_STR_ATI);
// UV first, like this green component cannot overflow
mpglColorFragmentOp2(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);
mpglColorFragmentOp3(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);
mpglColorFragmentOp2(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);
mpglEndFragmentShader();
}
/**
* \brief Variant of glYUVSetupCombinersATI using the API
* implemented by Apple.
*/
static void glSetupYUVTextFragment(float uvcos, float uvsin) {
static const char template[] =
"!!ATIfs1.0\n"
"StartConstants;\n"
" CONSTANT c0 = {%f, %f, %f};\n"
" CONSTANT c1 = {%f, %f, %f};\n"
"EndConstants;\n"
"StartOutputPass;\n"
" SampleMap r0, t0.str;\n"
" SampleMap r1, t1.str;\n"
" SampleMap r2, t2.str;\n"
" MUL r1, r1.bias, c0.bias;\n"
" MAD r2.4x, r2.bias, c1.bias, r1;\n"
" ADD r0, r0, r2;\n"
"EndPass;\n";
GLfloat ucoef[4];
GLfloat vcoef[4];
char buffer[512];
fillUVcoeff(ucoef, vcoef, uvcos, uvsin);
snprintf(buffer, sizeof(buffer), template,
ucoef[0], ucoef[1], ucoef[2],
vcoef[0], vcoef[1], vcoef[2]);
mp_msg(MSGT_VO, MSGL_DBG2, "[gl] generated fragment program:\n%s\n", buffer);
loadGPUProgram(GL_TEXT_FRAGMENT_SHADER_ATI, buffer);
mp_get_yuv2rgb_coeffs(csp_params, yuv2rgb);
for (i = 0; i < 3; i++) {
int j;
yuv2rgb[i][3] -= -0.5 * (yuv2rgb[i][1] + yuv2rgb[i][2]);
for (j = 0; j < 4; j++) {
yuv2rgb[i][j] *= 0.125;
yuv2rgb[i][j] += 0.5;
if (yuv2rgb[i][j] > 1)
yuv2rgb[i][j] = 1;
if (yuv2rgb[i][j] < 0)
yuv2rgb[i][j] = 0;
}
}
if (text == 0) {
GLfloat c0[4] = {yuv2rgb[0][0], yuv2rgb[1][0], yuv2rgb[2][0]};
GLfloat c1[4] = {yuv2rgb[0][1], yuv2rgb[1][1], yuv2rgb[2][1]};
GLfloat c2[4] = {yuv2rgb[0][2], yuv2rgb[1][2], yuv2rgb[2][2]};
GLfloat c3[4] = {yuv2rgb[0][3], yuv2rgb[1][3], yuv2rgb[2][3]};
if (!mpglBeginFragmentShader || !mpglEndFragmentShader ||
!mpglSetFragmentShaderConstant || !mpglSampleMap ||
!mpglColorFragmentOp2 || !mpglColorFragmentOp3) {
mp_msg(MSGT_VO, MSGL_FATAL, "[gl] Combiner (ATI) functions missing!\n");
return;
}
mpglGetIntegerv(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);
mpglBeginFragmentShader();
mpglSetFragmentShaderConstant(GL_CON_0_ATI, c0);
mpglSetFragmentShaderConstant(GL_CON_1_ATI, c1);
mpglSetFragmentShaderConstant(GL_CON_2_ATI, c2);
mpglSetFragmentShaderConstant(GL_CON_3_ATI, c3);
mpglSampleMap(GL_REG_0_ATI, GL_TEXTURE0, GL_SWIZZLE_STR_ATI);
mpglSampleMap(GL_REG_1_ATI, GL_TEXTURE1, GL_SWIZZLE_STR_ATI);
mpglSampleMap(GL_REG_2_ATI, GL_TEXTURE2, GL_SWIZZLE_STR_ATI);
mpglColorFragmentOp2(GL_MUL_ATI, GL_REG_1_ATI, GL_NONE, GL_NONE,
GL_REG_1_ATI, GL_NONE, GL_BIAS_BIT_ATI,
GL_CON_1_ATI, GL_NONE, GL_BIAS_BIT_ATI);
mpglColorFragmentOp3(GL_MAD_ATI, GL_REG_2_ATI, GL_NONE, GL_NONE,
GL_REG_2_ATI, GL_NONE, GL_BIAS_BIT_ATI,
GL_CON_2_ATI, GL_NONE, GL_BIAS_BIT_ATI,
GL_REG_1_ATI, GL_NONE, GL_NONE);
mpglColorFragmentOp3(GL_MAD_ATI, GL_REG_0_ATI, GL_NONE, GL_NONE,
GL_REG_0_ATI, GL_NONE, GL_NONE,
GL_CON_0_ATI, GL_NONE, GL_BIAS_BIT_ATI,
GL_REG_2_ATI, GL_NONE, GL_NONE);
mpglColorFragmentOp2(GL_ADD_ATI, GL_REG_0_ATI, GL_NONE, GL_8X_BIT_ATI,
GL_REG_0_ATI, GL_NONE, GL_NONE,
GL_CON_3_ATI, GL_NONE, GL_BIAS_BIT_ATI);
mpglEndFragmentShader();
} else {
static const char template[] =
"!!ATIfs1.0\n"
"StartConstants;\n"
" CONSTANT c0 = {%e, %e, %e};\n"
" CONSTANT c1 = {%e, %e, %e};\n"
" CONSTANT c2 = {%e, %e, %e};\n"
" CONSTANT c3 = {%e, %e, %e};\n"
"EndConstants;\n"
"StartOutputPass;\n"
" SampleMap r0, t0.str;\n"
" SampleMap r1, t1.str;\n"
" SampleMap r2, t2.str;\n"
" MUL r1.rgb, r1.bias, c1.bias;\n"
" MAD r2.rgb, r2.bias, c2.bias, r1;\n"
" MAD r0.rgb, r0, c0.bias, r2;\n"
" ADD r0.rgb.8x, r0, c3.bias;\n"
"EndPass;\n";
char buffer[512];
snprintf(buffer, sizeof(buffer), template,
yuv2rgb[0][0], yuv2rgb[1][0], yuv2rgb[2][0],
yuv2rgb[0][1], yuv2rgb[1][1], yuv2rgb[2][1],
yuv2rgb[0][2], yuv2rgb[1][2], yuv2rgb[2][2],
yuv2rgb[0][3], yuv2rgb[1][3], yuv2rgb[2][3]);
mp_msg(MSGT_VO, MSGL_DBG2, "[gl] generated fragment program:\n%s\n", buffer);
loadGPUProgram(GL_TEXT_FRAGMENT_SHADER_ATI, buffer);
}
}
/**
@ -1375,10 +1393,10 @@ void glSetupYUVConversion(gl_conversion_params_t *params) {
glSetupYUVCombiners(uvcos, uvsin);
break;
case YUV_CONVERSION_COMBINERS_ATI:
glSetupYUVCombinersATI(uvcos, uvsin);
glSetupYUVFragmentATI(&params->csp_params, 0);
break;
case YUV_CONVERSION_TEXT_FRAGMENT:
glSetupYUVTextFragment(uvcos, uvsin);
glSetupYUVFragmentATI(&params->csp_params, 1);
break;
case YUV_CONVERSION_FRAGMENT_LOOKUP:
case YUV_CONVERSION_FRAGMENT_LOOKUP3D: