changeset 35005:b1a1dcae9760

Replace MESA YCBCR support by the Apple variant. This adds hardware support for yuy2 and uyvy color formats when running on OSX. In addition add some hacks to make it fast (at least on PPC Mac Mini running OSX 10.5), ca. 20% faster than -vo corevideo. The MESA YCBCR variant never worked properly and has become even more broken and thus been disabled in most maintained drivers and thus is really a dead-end.
author reimar
date Sat, 18 Aug 2012 15:54:34 +0000
parents 9a8cd462b5da
children 733628daff6f
files DOCS/man/en/mplayer.1 libvo/gl_common.c libvo/gl_common.h libvo/vo_gl.c
diffstat 4 files changed, 42 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- a/DOCS/man/en/mplayer.1	Thu Aug 16 19:55:37 2012 +0000
+++ b/DOCS/man/en/mplayer.1	Sat Aug 18 15:54:34 2012 +0000
@@ -4189,8 +4189,8 @@
 Requires GLX_SGI_swap_control support to work.
 With some (most/all?) implementations this only works in fullscreen mode.
 .IPs ycbcr
-Use the GL_MESA_ycbcr_texture extension to convert YUV to RGB.
-In most cases this is probably slower than doing software conversion to RGB.
+Use the GL_APPLE_ycbcr_422 extension to convert YUV to RGB.
+Note that this will enable a few special settings to get into a special driver fast-path.
 .IPs yuv=<n>
 Select the type of YUV to RGB conversion.
 The default is auto-detection deciding between values 0 and 2.
--- a/libvo/gl_common.c	Thu Aug 16 19:55:37 2012 +0000
+++ b/libvo/gl_common.c	Sat Aug 18 15:54:34 2012 +0000
@@ -306,14 +306,12 @@
       *gl_format = GL_LUMINANCE;
       *gl_type = GL_UNSIGNED_BYTE;
       break;
+    case IMGFMT_YUY2:
     case IMGFMT_UYVY:
-    // IMGFMT_YUY2 would be more logical for the _REV format,
-    // but gives clearly swapped colors.
-    case IMGFMT_YVYU:
-      *gl_texfmt = GL_YCBCR_MESA;
+      *gl_texfmt = GL_RGB;
       *bpp = 16;
-      *gl_format = GL_YCBCR_MESA;
-      *gl_type = fmt == IMGFMT_UYVY ? GL_UNSIGNED_SHORT_8_8 : GL_UNSIGNED_SHORT_8_8_REV;
+      *gl_format = GL_YCBCR_422_APPLE;
+      *gl_type = fmt == IMGFMT_YUY2 ? GL_UNSIGNED_SHORT_8_8 : GL_UNSIGNED_SHORT_8_8_REV;
       break;
 #if 0
     // we do not support palettized formats, although the format the
@@ -573,6 +571,9 @@
   memset(init, val, stride * h);
   glAdjustAlignment(stride);
   mpglPixelStorei(GL_UNPACK_ROW_LENGTH, w);
+  // This needs to be here before the very first TexImage call to get
+  // best performance on PPC Mac Mini running OSX 10.5
+  mpglTexParameteri(target, GL_TEXTURE_STORAGE_HINT_APPLE, GL_STORAGE_CACHED_APPLE);
   mpglTexImage2D(target, 0, fmt, w, h, 0, format, type, init);
   if (format == GL_LUMINANCE && type == GL_UNSIGNED_SHORT) {
     // ensure we get enough bits
@@ -662,6 +663,8 @@
     case GL_UNSIGNED_SHORT_1_5_5_5_REV:
     case GL_UNSIGNED_SHORT_5_6_5:
     case GL_UNSIGNED_SHORT_5_6_5_REV:
+    case GL_UNSIGNED_SHORT_8_8:
+    case GL_UNSIGNED_SHORT_8_8_REV:
       return 2;
     case GL_UNSIGNED_BYTE:
       component_size = 1;
@@ -677,6 +680,7 @@
       return component_size;
     case GL_LUMINANCE_ALPHA:
       return 2 * component_size;
+    case GL_YCBCR_422_APPLE:
     case GL_YCBCR_MESA:
       return 2;
     case GL_RGB:
@@ -700,7 +704,8 @@
  * \param y y offset in texture
  * \param w width of the texture part to upload
  * \param h height of the texture part to upload
- * \param slice height of an upload slice, 0 for all at once
+ * \param slice height of an upload slice, 0 for all at once, -1 forces use of
+ *              TexImage instead of TexSubImage
  * \ingroup gltexture
  */
 void glUploadTex(GLenum target, GLenum format, GLenum type,
@@ -709,7 +714,7 @@
   const uint8_t *data = dataptr;
   int y_max = y + h;
   if (w <= 0 || h <= 0) return;
-  if (slice <= 0)
+  if (slice == 0)
     slice = h;
   if (stride < 0) {
     data += (h - 1) * stride;
@@ -722,6 +727,12 @@
   // this is not always correct, but should work for MPlayer
   glAdjustAlignment(stride);
   mpglPixelStorei(GL_UNPACK_ROW_LENGTH, stride / glFmt2bpp(format, type));
+  if (slice < 0) {
+    mpglPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
+    mpglTexImage2D(target, 0, GL_RGB, w, h, 0, format, type, data);
+    mpglPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE);
+    return;
+  }
   for (; y + slice <= y_max; y += slice) {
     mpglTexSubImage2D(target, 0, x, y, w, slice, format, type, data);
     data += stride * slice;
--- a/libvo/gl_common.h	Thu Aug 16 19:55:37 2012 +0000
+++ b/libvo/gl_common.h	Sat Aug 18 15:54:34 2012 +0000
@@ -257,6 +257,9 @@
 #ifndef GL_UNSIGNED_SHORT_8_8_REV
 #define GL_UNSIGNED_SHORT_8_8_REV 0x85BB
 #endif
+#ifndef GL_YCBCR_422_APPLE
+#define GL_YCBCR_422_APPLE 0x85B9
+#endif
 #ifndef GL_YCBCR_MESA
 #define GL_YCBCR_MESA 0x8757
 #endif
@@ -287,6 +290,12 @@
 #ifndef GL_UNPACK_CLIENT_STORAGE_APPLE
 #define GL_UNPACK_CLIENT_STORAGE_APPLE 0x85B2
 #endif
+#ifndef GL_TEXTURE_STORAGE_HINT_APPLE
+#define GL_TEXTURE_STORAGE_HINT_APPLE 0x85BC
+#endif
+#ifndef GL_STORAGE_CACHED_APPLE
+#define GL_STORAGE_CACHED_APPLE 0x85BE
+#endif
 #ifndef GL_FRAGMENT_PROGRAM
 #define GL_FRAGMENT_PROGRAM 0x8804
 #endif
--- a/libvo/vo_gl.c	Thu Aug 16 19:55:37 2012 +0000
+++ b/libvo/vo_gl.c	Sat Aug 18 15:54:34 2012 +0000
@@ -117,6 +117,7 @@
 static float noise_strength;
 static int yuvconvtype;
 static int use_rectangle;
+static int using_tex_rect;
 static int err_shown;
 static uint32_t image_width;
 static uint32_t image_height;
@@ -438,7 +439,7 @@
       texSize(i->w, i->h, &sx, &sy);
       mpglBindTexture(gl_target, *curtex++);
     }
-    glDrawTex(i->dst_x, i->dst_y, i->w, i->h, x, y, i->w, i->h, sx, sy, use_rectangle == 1, 0, 0, 0);
+    glDrawTex(i->dst_x, i->dst_y, i->w, i->h, x, y, i->w, i->h, sx, sy, using_tex_rect, 0, 0, 0);
   }
   mpglEndList();
   mpglBindTexture(gl_target, 0);
@@ -544,7 +545,8 @@
 static int initGl(uint32_t d_width, uint32_t d_height) {
   GLint scale_type = get_scale_type(0);
   autodetectGlExtensions();
-  gl_target = use_rectangle == 1 ? GL_TEXTURE_RECTANGLE : GL_TEXTURE_2D;
+  using_tex_rect = gl_format == GL_YCBCR_422_APPLE || use_rectangle == 1;
+  gl_target = using_tex_rect ? GL_TEXTURE_RECTANGLE : GL_TEXTURE_2D;
   yuvconvtype = SET_YUV_CONVERSION(use_yuv) |
                 SET_YUV_LUM_SCALER(lscale) |
                 SET_YUV_CHROM_SCALER(cscale);
@@ -786,14 +788,14 @@
   mpglNewList(osdaDispList[osdtexCnt], GL_COMPILE);
   // render alpha
   mpglBindTexture(gl_target, osdatex[osdtexCnt]);
-  glDrawTex(x0, y0, w, h, 0, 0, w, h, sx, sy, use_rectangle == 1, 0, 0, 0);
+  glDrawTex(x0, y0, w, h, 0, 0, w, h, sx, sy, using_tex_rect, 0, 0, 0);
   mpglEndList();
 #endif
   osdDispList[osdtexCnt] = mpglGenLists(1);
   mpglNewList(osdDispList[osdtexCnt], GL_COMPILE);
   // render OSD
   mpglBindTexture(gl_target, osdtex[osdtexCnt]);
-  glDrawTex(x0, y0, w, h, 0, 0, w, h, sx, sy, use_rectangle == 1, 0, 0, 0);
+  glDrawTex(x0, y0, w, h, 0, 0, w, h, sx, sy, using_tex_rect, 0, 0, 0);
   mpglEndList();
 
   osdtexCnt++;
@@ -872,20 +874,20 @@
     glDrawTex(0, 0, image_width, image_height,
               0, 0, image_width >> 1, image_height,
               texture_width, texture_height,
-              use_rectangle == 1, is_yuv,
+              using_tex_rect, is_yuv,
               mpi_flipped ^ vo_flipped, stereo_mode == GL_3D_STIPPLE);
     glEnable3DRight(stereo_mode);
     glDrawTex(0, 0, image_width, image_height,
               image_width >> 1, 0, image_width >> 1, image_height,
               texture_width, texture_height,
-              use_rectangle == 1, is_yuv,
+              using_tex_rect, is_yuv,
               mpi_flipped ^ vo_flipped, stereo_mode == GL_3D_STIPPLE);
     glDisable3D(stereo_mode);
   } else {
     glDrawTex(0, 0, image_width, image_height,
               0, 0, image_width, image_height,
               texture_width, texture_height,
-              use_rectangle == 1, is_yuv,
+              using_tex_rect, is_yuv,
               mpi_flipped ^ vo_flipped, 0);
   }
   if (is_yuv || custom_prog)
@@ -1038,7 +1040,8 @@
 }
 
 static uint32_t draw_image(mp_image_t *mpi) {
-  int slice = slice_height;
+  // Ask for TexImage instead of TexSubImage for the rectangle + YCBCR + nodr special case.
+  int slice = gl_target == GL_TEXTURE_RECTANGLE && gl_format == GL_YCBCR_422_APPLE ? -1 : slice_height;
   int stride[3];
   unsigned char *planes[3];
   mp_image_t mpi2 = *mpi;
@@ -1151,7 +1154,7 @@
     // ideally MPlayer should be fixed instead not to use Y800 when it has the choice
     if (!use_yuv && (format == IMGFMT_Y8 || format == IMGFMT_Y800))
         return 0;
-    if (!use_ycbcr && (format == IMGFMT_UYVY || format == IMGFMT_YVYU))
+    if (!use_ycbcr && (format == IMGFMT_YUY2 || format == IMGFMT_UYVY))
         return 0;
     if (many_fmts &&
          glFindFormat(format, NULL, NULL, NULL, NULL))