From 22f6170009bb4442a9e0c2c2e44954df50a64d58 Mon Sep 17 00:00:00 2001 From: reimar Date: Sun, 4 Apr 2010 11:45:05 +0000 Subject: [PATCH] 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 --- libvo/gl_common.c | 156 ++++++++++++++++++++++++++-------------------- 1 file changed, 87 insertions(+), 69 deletions(-) diff --git a/libvo/gl_common.c b/libvo/gl_common.c index 3408fb2996..07593989ae 100644 --- a/libvo/gl_common.c +++ b/libvo/gl_common.c @@ -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(¶ms->csp_params, 0); break; case YUV_CONVERSION_TEXT_FRAGMENT: - glSetupYUVTextFragment(uvcos, uvsin); + glSetupYUVFragmentATI(¶ms->csp_params, 1); break; case YUV_CONVERSION_FRAGMENT_LOOKUP: case YUV_CONVERSION_FRAGMENT_LOOKUP3D: