mirror of https://github.com/mpv-player/mpv
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:
parent
4a8486f844
commit
22f6170009
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue