1
mirror of https://github.com/mpv-player/mpv synced 2024-10-18 10:25:02 +02:00

Add bicubic texture scaling

git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@18623 b3059339-0415-0410-9bf9-f77b7e298cf2
This commit is contained in:
reimar 2006-06-07 14:07:32 +00:00
parent fd77a846b8
commit 1b0b329dd7
3 changed files with 99 additions and 1 deletions

View File

@ -3077,6 +3077,16 @@ At least three texture units are needed.
Provides saturation and hue control.
This method is fast but inexact.
.RE
.IPs [l|c]scaler=<n>
Select the scaling function to use (seperately for luma and chroma).
Only valid for yuv modes 2, 3 and 4.
.RSss
0: Use simple linear filtering (default)
.br
1: Use bicubic filtering (better quality).
Older cards will not be able to handle this for chroma at least in fullscreen mode.
Also needs one additional texture unit.
.RE
.IPs customprog=<filename>
Load a custom fragment program from <filename>.
See TOOLS/edgedect.fp for an example.

View File

@ -607,9 +607,78 @@ static void glSetupYUVCombinersATI(float uvcos, float uvsin) {
EndFragmentShader();
}
static void store_weights(float x, GLfloat *dst) {
float w0 = (((-1 * x + 3) * x - 3) * x + 1) / 6;
float w1 = ((( 3 * x - 6) * x + 0) * x + 4) / 6;
float w2 = (((-3 * x + 3) * x + 3) * x + 1) / 6;
float w3 = ((( 1 * x + 0) * x + 0) * x + 0) / 6;
*dst++ = 1 + x - w1 / (w0 + w1);
*dst++ = 1 - x + w3 / (w2 + w3);
*dst++ = w0 + w1;
*dst++ = 0;
}
//! to avoid artefacts this should be rather large
#define LOOKUP_BSPLINE_RES (1024)
/**
* \brief creates the 1D lookup texture needed for fast higher-order filtering
* \param unit texture unit to attach texture to
*/
static void gen_spline_lookup_tex(GLenum unit) {
GLfloat tex[4 * (LOOKUP_BSPLINE_RES + 2)];
GLfloat *tp = &tex[4];
int i;
for (i = 0; i < LOOKUP_BSPLINE_RES; i++) {
float x = (float)(i + 0.5) / LOOKUP_BSPLINE_RES;
store_weights(x, tp);
tp += 4;
}
store_weights(0, tex);
store_weights(1, &tex[4 * (LOOKUP_BSPLINE_RES + 1)]);
ActiveTexture(unit);
glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA16, LOOKUP_BSPLINE_RES + 2, 1, GL_RGBA, GL_FLOAT, tex);
glTexParameterf(GL_TEXTURE_1D, GL_TEXTURE_PRIORITY, 1.0);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_REPEAT);
ActiveTexture(GL_TEXTURE0);
}
static const char *bilin_filt_template =
"TEX yuv.%c, fragment.texcoord[%c], texture[%c], %s;";
#define BICUB_FILT_MAIN(textype) \
/* first y-interpolation */ \
"SUB coord.xy, fragment.texcoord[%c], parmx.rara;" \
"SUB coord.zw, coord.xyxy, parmy.arar;" \
"TEX a.r, coord.zwzw, texture[%c], "textype";" \
"ADD coord.zw, coord.xyxy, parmy.agag;" \
"TEX a.g, coord.zwzw, texture[%c], "textype";" \
"LRP a.b, parmy.b, a.rrrr, a.gggg;" \
/* second y-interpolation */ \
"ADD coord.xy, fragment.texcoord[%c], parmx.gaga;" \
"SUB coord.zw, coord.xyxy, parmy.arar;" \
"TEX a.r, coord.zwzw, texture[%c], "textype";" \
"ADD coord.zw, coord.xyxy, parmy.agag;" \
"TEX a.g, coord.zwzw, texture[%c], "textype";" \
"LRP a.a, parmy.b, a.rrrr, a.gggg;" \
/* x-interpolation */ \
"LRP yuv.%c, parmx.b, a.bbbb, a.aaaa;"
static const char *bicub_filt_template_2D =
"MAD coord.xy, fragment.texcoord[%c], {%f, %f}, {0.5, 0.5};"
"TEX parmx, coord.x, texture[%c], 1D;"
"MUL parmx.rg, parmx, {%f, %f};"
"TEX parmy, coord.y, texture[%c], 1D;"
"MUL parmy.rg, parmy, {%f, %f};"
BICUB_FILT_MAIN("2D");
static const char *bicub_filt_template_RECT =
"ADD coord, fragment.texcoord[%c], {0.5, 0.5};"
"TEX parmx, coord.x, texture[%c], 1D;"
"TEX parmy, coord.y, texture[%c], 1D;"
BICUB_FILT_MAIN("RECT");
static const char *yuv_prog_template =
"PARAM ycoef = {%.4f, %.4f, %.4f};"
"PARAM ucoef = {%.4f, %.4f, %.4f};"
@ -656,6 +725,11 @@ static void create_scaler_textures(int scaler, int *texu, char *texs) {
switch (scaler) {
case YUV_SCALER_BILIN:
break;
case YUV_SCALER_BICUB:
texs[0] = (*texu)++;
gen_spline_lookup_tex(GL_TEXTURE0 + texs[0]);
texs[0] += '0';
break;
default:
mp_msg(MSGT_VO, MSGL_ERR, "[gl] unknown scaler type %i\n", scaler);
}
@ -701,6 +775,18 @@ static void add_scaler(int scaler, char **prog_pos, int *remain, char *texs,
snprintf(*prog_pos, *remain, bilin_filt_template, out_comp, in_tex,
in_tex, rect ? "RECT" : "2D");
break;
case YUV_SCALER_BICUB:
if (rect)
snprintf(*prog_pos, *remain, bicub_filt_template_RECT,
in_tex, texs[0], texs[0],
in_tex, in_tex, in_tex, in_tex, in_tex, in_tex, out_comp);
else
snprintf(*prog_pos, *remain, bicub_filt_template_2D,
in_tex, (float)texw, (float)texh,
texs[0], (float)1.0 / texw, (float)1.0 / texw,
texs[0], (float)1.0 / texh, (float)1.0 / texh,
in_tex, in_tex, in_tex, in_tex, in_tex, in_tex, out_comp);
break;
}
*remain -= strlen(*prog_pos);
*prog_pos += strlen(*prog_pos);
@ -724,7 +810,7 @@ static void glSetupYUVFragprog(float brightness, float contrast,
"OPTION ARB_precision_hint_fastest;"
// all scaler variables must go here so they aren't defined
// multiple times when the same scaler is used more than once
"TEMP yuv;";
"TEMP coord, parmx, parmy, a, yuv;";
int prog_remain = sizeof(yuv_prog) - strlen(yuv_prog);
char *prog_pos = &yuv_prog[strlen(yuv_prog)];
int cur_texu = 3;

View File

@ -225,6 +225,8 @@ void glDrawTex(GLfloat x, GLfloat y, GLfloat w, GLfloat h,
#define YUV_CONVERSION_COMBINERS_ATI 5
//! use normal bilinear scaling for textures
#define YUV_SCALER_BILIN 0
//! use higher quality bicubic scaling for textures
#define YUV_SCALER_BICUB 1
//! mask for conversion type
#define YUV_CONVERSION_MASK 0xF
//! mask for scaler type