mirror of
https://github.com/mpv-player/mpv
synced 2025-03-04 21:27:58 +00: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:
parent
fd77a846b8
commit
1b0b329dd7
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user