changeset 18622:dd9a6e8005f3

Add bicubic texture scaling
author reimar
date Wed, 07 Jun 2006 14:07:32 +0000
parents 0001a9a9f1a9
children 960cd1af26f2
files DOCS/man/en/mplayer.1 libvo/gl_common.c libvo/gl_common.h
diffstat 3 files changed, 99 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/DOCS/man/en/mplayer.1	Wed Jun 07 13:39:06 2006 +0000
+++ b/DOCS/man/en/mplayer.1	Wed Jun 07 14:07:32 2006 +0000
@@ -3077,6 +3077,16 @@
 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.
--- a/libvo/gl_common.c	Wed Jun 07 13:39:06 2006 +0000
+++ b/libvo/gl_common.c	Wed Jun 07 14:07:32 2006 +0000
@@ -607,9 +607,78 @@
   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 @@
   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 @@
       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 @@
     "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;
--- a/libvo/gl_common.h	Wed Jun 07 13:39:06 2006 +0000
+++ b/libvo/gl_common.h	Wed Jun 07 14:07:32 2006 +0000
@@ -225,6 +225,8 @@
 #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