diff libvo/vo_gl2.c @ 30097:9d724e6def3e

Support all planar YUV formats in OpenGL vos.
author reimar
date Wed, 30 Dec 2009 11:32:24 +0000
parents b7a703cf9178
children 11e3ee8cd05e
line wrap: on
line diff
--- a/libvo/vo_gl2.c	Wed Dec 30 11:08:44 2009 +0000
+++ b/libvo/vo_gl2.c	Wed Dec 30 11:32:24 2009 +0000
@@ -88,6 +88,7 @@
 static int      gl_bilinear=1;
 static int      gl_antialias=0;
 static int      use_yuv;
+static int      is_yuv;
 static int      use_glFinish;
 
 static void (*draw_alpha_fnc)
@@ -184,7 +185,7 @@
     s*=2;
   texture_height=s;
 
-  if (image_format != IMGFMT_YV12)
+  if (!is_yuv)
   gl_internal_format = getInternalFormat();
 
   /* Test the max texture size */
@@ -263,7 +264,7 @@
       glGenTextures (1, &(tsq->texobj));
 
       glBindTexture (GL_TEXTURE_2D, tsq->texobj);
-      if (image_format == IMGFMT_YV12) {
+      if (is_yuv) {
         glGenTextures(2, tsq->uvtexobjs);
         ActiveTexture(GL_TEXTURE1);
         glBindTexture (GL_TEXTURE_2D, tsq->uvtexobjs[0]);
@@ -276,13 +277,15 @@
                        texture_width, texture_height, 0);
 
       glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
-      if (image_format == IMGFMT_YV12) {
+      if (is_yuv) {
+        int xs, ys;
+        mp_get_chroma_shift(image_format, &xs, &ys);
         ActiveTexture(GL_TEXTURE1);
         glCreateClearTex(GL_TEXTURE_2D, gl_internal_format, gl_bitmap_format,  gl_bitmap_type, GL_LINEAR,
-                         texture_width / 2, texture_height / 2, 128);
+                         texture_width >> xs, texture_height >> ys, 128);
         ActiveTexture(GL_TEXTURE2);
         glCreateClearTex(GL_TEXTURE_2D, gl_internal_format, gl_bitmap_format,  gl_bitmap_type, GL_LINEAR,
-                         texture_width / 2, texture_height / 2, 128);
+                         texture_width >> xs, texture_height >> ys, 128);
         ActiveTexture(GL_TEXTURE0);
       }
 
@@ -381,7 +384,7 @@
 
   glColor3f(1.0,1.0,1.0);
 
-  if (image_format == IMGFMT_YV12)
+  if (is_yuv)
     glEnableYUVConversion(GL_TEXTURE_2D, use_yuv);
   for (y = 0; y < texnumy; y++) {
     int thish = texture_height;
@@ -392,7 +395,7 @@
       if (x == texnumx - 1 && image_width % texture_width)
         thisw = image_width % texture_width;
       glBindTexture (GL_TEXTURE_2D, square->texobj);
-      if (image_format == IMGFMT_YV12) {
+      if (is_yuv) {
         ActiveTexture(GL_TEXTURE1);
         glBindTexture (GL_TEXTURE_2D, square->uvtexobjs[0]);
         ActiveTexture(GL_TEXTURE2);
@@ -409,11 +412,11 @@
       glDrawTex(square->fx, square->fy, square->fw, square->fh,
                 0, 0, texture_width, texture_height,
                 texture_width, texture_height,
-                0, image_format == IMGFMT_YV12, 0);
+                0, is_yuv, 0);
       square++;
     } /* for all texnumx */
   } /* for all texnumy */
-  if (image_format == IMGFMT_YV12)
+  if (is_yuv)
     glDisableYUVConversion(GL_TEXTURE_2D, use_yuv);
   texdirty = 0;
 }
@@ -565,10 +568,11 @@
   glDepthMask(GL_FALSE);
   glDisable(GL_CULL_FACE);
   glEnable (GL_TEXTURE_2D);
-  if (image_format == IMGFMT_YV12) {
+  if (is_yuv) {
+    int xs, ys;
     gl_conversion_params_t params = {GL_TEXTURE_2D, use_yuv,
           0.0, 1.0, 0.0, 1.0, 1.0, 1.0, 1.0,
-          texture_width, texture_height};
+          texture_width, texture_height, 0, 0, 0};
     switch (use_yuv) {
       case YUV_CONVERSION_FRAGMENT_LOOKUP:
         glGenTextures(1, &lookupTex);
@@ -586,6 +590,9 @@
         BindProgram(GL_FRAGMENT_PROGRAM, fragprog);
         break;
     }
+    mp_get_chroma_shift(image_format, &xs, &ys);
+    params.chrom_texw = params.texw >> xs;
+    params.chrom_texh = params.texh >> ys;
     glSetupYUVConversion(&params);
   }
 
@@ -613,11 +620,14 @@
 static int
 config(uint32_t width, uint32_t height, uint32_t d_width, uint32_t d_height, uint32_t flags, char *title, uint32_t format)
 {
+  int xs, ys;
   const unsigned char * glVersion;
 
   image_height = height;
   image_width = width;
   image_format = format;
+  is_yuv = mp_get_chroma_shift(image_format, &xs, &ys) > 0;
+  is_yuv |= (xs << 8) | (ys << 16);
 
   int_pause = 0;
 
@@ -750,6 +760,8 @@
   int rem_h = h;
   struct TexSquare *texline = &texgrid[y / texture_height * texnumx];
   int subtex_y = y % texture_width;
+  int xs, ys;
+  mp_get_chroma_shift(image_format, &xs, &ys);
   while (rem_h > 0) {
     int rem_w = w;
     struct TexSquare *tsq = &texline[x / texture_width];
@@ -769,24 +781,24 @@
       ActiveTexture(GL_TEXTURE1);
       glBindTexture(GL_TEXTURE_2D, tsq->uvtexobjs[0]);
       glUploadTex(GL_TEXTURE_2D, gl_bitmap_format,  gl_bitmap_type,
-                  uptr, ustride, subtex_x / 2, subtex_y / 2,
-                  subtex_w / 2, subtex_h / 2, 0);
+                  uptr, ustride, subtex_x >> xs, subtex_y >> ys,
+                  subtex_w >> xs, subtex_h >> ys, 0);
       ActiveTexture(GL_TEXTURE2);
       glBindTexture(GL_TEXTURE_2D, tsq->uvtexobjs[1]);
       glUploadTex(GL_TEXTURE_2D, gl_bitmap_format,  gl_bitmap_type,
-                  vptr, vstride, subtex_x / 2, subtex_y / 2,
-                  subtex_w / 2, subtex_h / 2, 0);
+                  vptr, vstride, subtex_x >> xs, subtex_y >> ys,
+                  subtex_w >> xs, subtex_h >> ys, 0);
       subtex_x = 0;
       yptr += subtex_w;
-      uptr += subtex_w / 2;
-      vptr += subtex_w / 2;
+      uptr += subtex_w >> xs;
+      vptr += subtex_w >> xs;
       tsq++;
       rem_w -= subtex_w;
     }
     subtex_y = 0;
     yptr += subtex_h * ystride - w;
-    uptr += subtex_h / 2 * ustride - w / 2;
-    vptr += subtex_h / 2 * vstride - w / 2;
+    uptr += (subtex_h >> ys) * ustride - (w >> xs);
+    vptr += (subtex_h >> ys) * vstride - (w >> xs);
     texline += texnumx;
     rem_h -= subtex_h;
   }
@@ -797,7 +809,7 @@
 static int
 draw_frame(uint8_t *src[])
 {
-  if (image_format == IMGFMT_YV12) {
+  if (is_yuv) {
     mp_msg(MSGT_VO, MSGL_ERR, "[gl2] error: draw_frame called for YV12!\n");
     return 0;
   }
@@ -810,12 +822,10 @@
 static int
 query_format(uint32_t format)
 {
+  if (use_yuv && mp_get_chroma_shift(format, NULL, NULL))
+    return VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW | VFCAP_OSD |
+           VFCAP_HWSCALE_UP | VFCAP_HWSCALE_DOWN | VFCAP_ACCEPT_STRIDE;
   switch(format) {
-    case IMGFMT_YV12:
-      if (use_yuv)
-        return VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW | VFCAP_OSD |
-               VFCAP_HWSCALE_UP | VFCAP_HWSCALE_DOWN | VFCAP_ACCEPT_STRIDE;
-      break;
 #ifdef __APPLE__
     case IMGFMT_RGB32:
 #else