Mercurial > mplayer.hg
comparison libvo/gl_common.c @ 30953:d3f31670562d
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).
author | reimar |
---|---|
date | Sun, 04 Apr 2010 11:45:05 +0000 |
parents | 994f301a13f6 |
children | a5c6b37b3af6 |
comparison
equal
deleted
inserted
replaced
30952:994f301a13f6 | 30953:d3f31670562d |
---|---|
761 mpglCombinerParameteri(GL_NUM_GENERAL_COMBINERS_NV, 2); | 761 mpglCombinerParameteri(GL_NUM_GENERAL_COMBINERS_NV, 2); |
762 } | 762 } |
763 | 763 |
764 /** | 764 /** |
765 * \brief Setup ATI version of register combiners for YUV to RGB conversion. | 765 * \brief Setup ATI version of register combiners for YUV to RGB conversion. |
766 * \param uvcos used for saturation and hue adjustment | 766 * \param csp_params parameters used for colorspace conversion |
767 * \param uvsin used for saturation and hue adjustment | 767 * \param text if set use the GL_ATI_text_fragment_shader API as |
768 * | 768 * used on OS X. |
769 * ATI called this fragment shader, but the name is confusing in the | 769 */ |
770 * light of a very different OpenGL 2.0 extension with the same name | 770 static void glSetupYUVFragmentATI(struct mp_csp_params *csp_params, |
771 */ | 771 int text) { |
772 static void glSetupYUVCombinersATI(float uvcos, float uvsin) { | |
773 GLfloat ucoef[4]; | |
774 GLfloat vcoef[4]; | |
775 GLint i; | 772 GLint i; |
776 if (!mpglBeginFragmentShader || !mpglEndFragmentShader || | 773 float yuv2rgb[3][4]; |
777 !mpglSetFragmentShaderConstant || !mpglSampleMap || | 774 |
778 !mpglColorFragmentOp2 || !mpglColorFragmentOp3) { | |
779 mp_msg(MSGT_VO, MSGL_FATAL, "[gl] Combiner (ATI) functions missing!\n"); | |
780 return; | |
781 } | |
782 mpglGetIntegerv(GL_NUM_FRAGMENT_REGISTERS_ATI, &i); | |
783 if (i < 3) | |
784 mp_msg(MSGT_VO, MSGL_ERR, | |
785 "[gl] 3 registers needed for YUV combiner (ATI) support (found %i)\n", i); | |
786 mpglGetIntegerv (GL_MAX_TEXTURE_UNITS, &i); | 775 mpglGetIntegerv (GL_MAX_TEXTURE_UNITS, &i); |
787 if (i < 3) | 776 if (i < 3) |
788 mp_msg(MSGT_VO, MSGL_ERR, | 777 mp_msg(MSGT_VO, MSGL_ERR, |
789 "[gl] 3 texture units needed for YUV combiner (ATI) support (found %i)\n", i); | 778 "[gl] 3 texture units needed for YUV combiner (ATI) support (found %i)\n", i); |
790 fillUVcoeff(ucoef, vcoef, uvcos, uvsin); | 779 |
791 mpglBeginFragmentShader(); | 780 mp_get_yuv2rgb_coeffs(csp_params, yuv2rgb); |
792 mpglSetFragmentShaderConstant(GL_CON_0_ATI, ucoef); | 781 for (i = 0; i < 3; i++) { |
793 mpglSetFragmentShaderConstant(GL_CON_1_ATI, vcoef); | 782 int j; |
794 mpglSampleMap(GL_REG_0_ATI, GL_TEXTURE0, GL_SWIZZLE_STR_ATI); | 783 yuv2rgb[i][3] -= -0.5 * (yuv2rgb[i][1] + yuv2rgb[i][2]); |
795 mpglSampleMap(GL_REG_1_ATI, GL_TEXTURE1, GL_SWIZZLE_STR_ATI); | 784 for (j = 0; j < 4; j++) { |
796 mpglSampleMap(GL_REG_2_ATI, GL_TEXTURE2, GL_SWIZZLE_STR_ATI); | 785 yuv2rgb[i][j] *= 0.125; |
797 // UV first, like this green component cannot overflow | 786 yuv2rgb[i][j] += 0.5; |
798 mpglColorFragmentOp2(GL_MUL_ATI, GL_REG_1_ATI, GL_NONE, GL_NONE, | 787 if (yuv2rgb[i][j] > 1) |
799 GL_REG_1_ATI, GL_NONE, GL_BIAS_BIT_ATI, | 788 yuv2rgb[i][j] = 1; |
800 GL_CON_0_ATI, GL_NONE, GL_BIAS_BIT_ATI); | 789 if (yuv2rgb[i][j] < 0) |
801 mpglColorFragmentOp3(GL_MAD_ATI, GL_REG_2_ATI, GL_NONE, GL_4X_BIT_ATI, | 790 yuv2rgb[i][j] = 0; |
802 GL_REG_2_ATI, GL_NONE, GL_BIAS_BIT_ATI, | 791 } |
803 GL_CON_1_ATI, GL_NONE, GL_BIAS_BIT_ATI, | 792 } |
804 GL_REG_1_ATI, GL_NONE, GL_NONE); | 793 if (text == 0) { |
805 mpglColorFragmentOp2(GL_ADD_ATI, GL_REG_0_ATI, GL_NONE, GL_NONE, | 794 GLfloat c0[4] = {yuv2rgb[0][0], yuv2rgb[1][0], yuv2rgb[2][0]}; |
806 GL_REG_0_ATI, GL_NONE, GL_NONE, | 795 GLfloat c1[4] = {yuv2rgb[0][1], yuv2rgb[1][1], yuv2rgb[2][1]}; |
807 GL_REG_2_ATI, GL_NONE, GL_NONE); | 796 GLfloat c2[4] = {yuv2rgb[0][2], yuv2rgb[1][2], yuv2rgb[2][2]}; |
808 mpglEndFragmentShader(); | 797 GLfloat c3[4] = {yuv2rgb[0][3], yuv2rgb[1][3], yuv2rgb[2][3]}; |
809 } | 798 if (!mpglBeginFragmentShader || !mpglEndFragmentShader || |
810 | 799 !mpglSetFragmentShaderConstant || !mpglSampleMap || |
811 /** | 800 !mpglColorFragmentOp2 || !mpglColorFragmentOp3) { |
812 * \brief Variant of glYUVSetupCombinersATI using the API | 801 mp_msg(MSGT_VO, MSGL_FATAL, "[gl] Combiner (ATI) functions missing!\n"); |
813 * implemented by Apple. | 802 return; |
814 */ | 803 } |
815 static void glSetupYUVTextFragment(float uvcos, float uvsin) { | 804 mpglGetIntegerv(GL_NUM_FRAGMENT_REGISTERS_ATI, &i); |
816 static const char template[] = | 805 if (i < 3) |
817 "!!ATIfs1.0\n" | 806 mp_msg(MSGT_VO, MSGL_ERR, |
818 "StartConstants;\n" | 807 "[gl] 3 registers needed for YUV combiner (ATI) support (found %i)\n", i); |
819 " CONSTANT c0 = {%f, %f, %f};\n" | 808 mpglBeginFragmentShader(); |
820 " CONSTANT c1 = {%f, %f, %f};\n" | 809 mpglSetFragmentShaderConstant(GL_CON_0_ATI, c0); |
821 "EndConstants;\n" | 810 mpglSetFragmentShaderConstant(GL_CON_1_ATI, c1); |
822 "StartOutputPass;\n" | 811 mpglSetFragmentShaderConstant(GL_CON_2_ATI, c2); |
823 " SampleMap r0, t0.str;\n" | 812 mpglSetFragmentShaderConstant(GL_CON_3_ATI, c3); |
824 " SampleMap r1, t1.str;\n" | 813 mpglSampleMap(GL_REG_0_ATI, GL_TEXTURE0, GL_SWIZZLE_STR_ATI); |
825 " SampleMap r2, t2.str;\n" | 814 mpglSampleMap(GL_REG_1_ATI, GL_TEXTURE1, GL_SWIZZLE_STR_ATI); |
826 " MUL r1, r1.bias, c0.bias;\n" | 815 mpglSampleMap(GL_REG_2_ATI, GL_TEXTURE2, GL_SWIZZLE_STR_ATI); |
827 " MAD r2.4x, r2.bias, c1.bias, r1;\n" | 816 mpglColorFragmentOp2(GL_MUL_ATI, GL_REG_1_ATI, GL_NONE, GL_NONE, |
828 " ADD r0, r0, r2;\n" | 817 GL_REG_1_ATI, GL_NONE, GL_BIAS_BIT_ATI, |
829 "EndPass;\n"; | 818 GL_CON_1_ATI, GL_NONE, GL_BIAS_BIT_ATI); |
830 GLfloat ucoef[4]; | 819 mpglColorFragmentOp3(GL_MAD_ATI, GL_REG_2_ATI, GL_NONE, GL_NONE, |
831 GLfloat vcoef[4]; | 820 GL_REG_2_ATI, GL_NONE, GL_BIAS_BIT_ATI, |
832 char buffer[512]; | 821 GL_CON_2_ATI, GL_NONE, GL_BIAS_BIT_ATI, |
833 | 822 GL_REG_1_ATI, GL_NONE, GL_NONE); |
834 fillUVcoeff(ucoef, vcoef, uvcos, uvsin); | 823 mpglColorFragmentOp3(GL_MAD_ATI, GL_REG_0_ATI, GL_NONE, GL_NONE, |
835 snprintf(buffer, sizeof(buffer), template, | 824 GL_REG_0_ATI, GL_NONE, GL_NONE, |
836 ucoef[0], ucoef[1], ucoef[2], | 825 GL_CON_0_ATI, GL_NONE, GL_BIAS_BIT_ATI, |
837 vcoef[0], vcoef[1], vcoef[2]); | 826 GL_REG_2_ATI, GL_NONE, GL_NONE); |
838 mp_msg(MSGT_VO, MSGL_DBG2, "[gl] generated fragment program:\n%s\n", buffer); | 827 mpglColorFragmentOp2(GL_ADD_ATI, GL_REG_0_ATI, GL_NONE, GL_8X_BIT_ATI, |
839 loadGPUProgram(GL_TEXT_FRAGMENT_SHADER_ATI, buffer); | 828 GL_REG_0_ATI, GL_NONE, GL_NONE, |
829 GL_CON_3_ATI, GL_NONE, GL_BIAS_BIT_ATI); | |
830 mpglEndFragmentShader(); | |
831 } else { | |
832 static const char template[] = | |
833 "!!ATIfs1.0\n" | |
834 "StartConstants;\n" | |
835 " CONSTANT c0 = {%e, %e, %e};\n" | |
836 " CONSTANT c1 = {%e, %e, %e};\n" | |
837 " CONSTANT c2 = {%e, %e, %e};\n" | |
838 " CONSTANT c3 = {%e, %e, %e};\n" | |
839 "EndConstants;\n" | |
840 "StartOutputPass;\n" | |
841 " SampleMap r0, t0.str;\n" | |
842 " SampleMap r1, t1.str;\n" | |
843 " SampleMap r2, t2.str;\n" | |
844 " MUL r1.rgb, r1.bias, c1.bias;\n" | |
845 " MAD r2.rgb, r2.bias, c2.bias, r1;\n" | |
846 " MAD r0.rgb, r0, c0.bias, r2;\n" | |
847 " ADD r0.rgb.8x, r0, c3.bias;\n" | |
848 "EndPass;\n"; | |
849 char buffer[512]; | |
850 snprintf(buffer, sizeof(buffer), template, | |
851 yuv2rgb[0][0], yuv2rgb[1][0], yuv2rgb[2][0], | |
852 yuv2rgb[0][1], yuv2rgb[1][1], yuv2rgb[2][1], | |
853 yuv2rgb[0][2], yuv2rgb[1][2], yuv2rgb[2][2], | |
854 yuv2rgb[0][3], yuv2rgb[1][3], yuv2rgb[2][3]); | |
855 mp_msg(MSGT_VO, MSGL_DBG2, "[gl] generated fragment program:\n%s\n", buffer); | |
856 loadGPUProgram(GL_TEXT_FRAGMENT_SHADER_ATI, buffer); | |
857 } | |
840 } | 858 } |
841 | 859 |
842 /** | 860 /** |
843 * \brief helper function for gen_spline_lookup_tex | 861 * \brief helper function for gen_spline_lookup_tex |
844 * \param x subpixel-position ((0,1) range) to calculate weights for | 862 * \param x subpixel-position ((0,1) range) to calculate weights for |
1373 switch (YUV_CONVERSION(params->type)) { | 1391 switch (YUV_CONVERSION(params->type)) { |
1374 case YUV_CONVERSION_COMBINERS: | 1392 case YUV_CONVERSION_COMBINERS: |
1375 glSetupYUVCombiners(uvcos, uvsin); | 1393 glSetupYUVCombiners(uvcos, uvsin); |
1376 break; | 1394 break; |
1377 case YUV_CONVERSION_COMBINERS_ATI: | 1395 case YUV_CONVERSION_COMBINERS_ATI: |
1378 glSetupYUVCombinersATI(uvcos, uvsin); | 1396 glSetupYUVFragmentATI(¶ms->csp_params, 0); |
1379 break; | 1397 break; |
1380 case YUV_CONVERSION_TEXT_FRAGMENT: | 1398 case YUV_CONVERSION_TEXT_FRAGMENT: |
1381 glSetupYUVTextFragment(uvcos, uvsin); | 1399 glSetupYUVFragmentATI(¶ms->csp_params, 1); |
1382 break; | 1400 break; |
1383 case YUV_CONVERSION_FRAGMENT_LOOKUP: | 1401 case YUV_CONVERSION_FRAGMENT_LOOKUP: |
1384 case YUV_CONVERSION_FRAGMENT_LOOKUP3D: | 1402 case YUV_CONVERSION_FRAGMENT_LOOKUP3D: |
1385 case YUV_CONVERSION_FRAGMENT: | 1403 case YUV_CONVERSION_FRAGMENT: |
1386 case YUV_CONVERSION_FRAGMENT_POW: | 1404 case YUV_CONVERSION_FRAGMENT_POW: |