changeset 31567:0ffe9f97fc9f

Add initial stereo support to -vo gl.
author reimar
date Mon, 05 Jul 2010 19:19:56 +0000
parents 761346c3b10e
children 476ca8c5dbd0
files DOCS/man/en/mplayer.1 libvo/gl_common.c libvo/gl_common.h libvo/vo_gl.c
diffstat 4 files changed, 139 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/DOCS/man/en/mplayer.1	Mon Jul 05 18:24:02 2010 +0000
+++ b/DOCS/man/en/mplayer.1	Mon Jul 05 19:19:56 2010 +0000
@@ -3988,6 +3988,27 @@
 For details see lscale.
 .IPs filter-strength=<value>
 Set the effect strength for the lscale/cscale filters that support it.
+.IPs stereo=<value>
+Select a method for stereo display.
+You may have to use -aspect to fix the aspect value.
+Experimental, do not expect too much from it.
+.RSss
+0: Normal 2D display
+.br
+1: left-right split input to full-color red-cyan stereo.
+.br
+2: left-right split input to full-color red-cyan stereo.
+.br
+3: left-right split input to quadbuffered stereo.
+Only supported by very few OpenGL cards, thus untested and not working.
+.RE
+.RE
+.sp 1
+.RS
+The following options are only useful if writing your own fragment programs.
+.RE
+.sp 1
+.RSs
 .IPs customprog=<filename>
 Load a custom fragment program from <filename>.
 See TOOLS/edgedect.fp for an example.
--- a/libvo/gl_common.c	Mon Jul 05 18:24:02 2010 +0000
+++ b/libvo/gl_common.c	Mon Jul 05 19:19:56 2010 +0000
@@ -92,6 +92,7 @@
 void (GLAPIENTRY *mpglColorMaterial)(GLenum, GLenum);
 void (GLAPIENTRY *mpglShadeModel)(GLenum);
 void (GLAPIENTRY *mpglGetIntegerv)(GLenum, GLint *);
+void (GLAPIENTRY *mpglColorMask)(GLboolean, GLboolean, GLboolean, GLboolean);
 
 /**
  * \defgroup glextfunctions OpenGL extension functions
@@ -436,6 +437,7 @@
   DEF_FUNC_DESC(ColorMaterial),
   DEF_FUNC_DESC(ShadeModel),
   DEF_FUNC_DESC(GetIntegerv),
+  DEF_FUNC_DESC(ColorMask),
 
   // here start the real extensions
   {&mpglGenBuffers, NULL, {"glGenBuffers", "glGenBuffersARB", NULL}},
@@ -1542,6 +1544,89 @@
   }
 }
 
+void glEnable3DLeft(int type) {
+  GLint buffer;
+  switch (type) {
+    case GL_3D_RED_CYAN:
+      mpglColorMask(GL_TRUE,  GL_FALSE, GL_FALSE, GL_FALSE);
+      break;
+    case GL_3D_GREEN_MAGENTA:
+      mpglColorMask(GL_FALSE, GL_TRUE,  GL_FALSE, GL_FALSE);
+      break;
+    case GL_3D_QUADBUFFER:
+      mpglGetIntegerv(GL_DRAW_BUFFER, &buffer);
+      switch (buffer) {
+        case GL_FRONT:
+        case GL_FRONT_LEFT:
+        case GL_FRONT_RIGHT:
+          buffer = GL_FRONT_LEFT;
+          break;
+        case GL_BACK:
+        case GL_BACK_LEFT:
+        case GL_BACK_RIGHT:
+          buffer = GL_BACK_LEFT;
+          break;
+      }
+      mpglDrawBuffer(buffer);
+      break;
+  }
+}
+
+void glEnable3DRight(int type) {
+  GLint buffer;
+  switch (type) {
+    case GL_3D_RED_CYAN:
+      mpglColorMask(GL_FALSE, GL_TRUE,  GL_TRUE,  GL_FALSE);
+      break;
+    case GL_3D_GREEN_MAGENTA:
+      mpglColorMask(GL_TRUE,  GL_FALSE, GL_TRUE,  GL_FALSE);
+      break;
+    case GL_3D_QUADBUFFER:
+      mpglGetIntegerv(GL_DRAW_BUFFER, &buffer);
+      switch (buffer) {
+        case GL_FRONT:
+        case GL_FRONT_LEFT:
+        case GL_FRONT_RIGHT:
+          buffer = GL_FRONT_RIGHT;
+          break;
+        case GL_BACK:
+        case GL_BACK_LEFT:
+        case GL_BACK_RIGHT:
+          buffer = GL_BACK_RIGHT;
+          break;
+      }
+      mpglDrawBuffer(buffer);
+      break;
+  }
+}
+
+void glDisable3D(int type) {
+  GLint buffer;
+  switch (type) {
+    case GL_3D_RED_CYAN:
+    case GL_3D_GREEN_MAGENTA:
+      mpglColorMask(GL_TRUE,  GL_TRUE,  GL_TRUE,  GL_TRUE);
+      break;
+    case GL_3D_QUADBUFFER:
+      mpglDrawBuffer(vo_doublebuffering ? GL_BACK : GL_FRONT);
+      mpglGetIntegerv(GL_DRAW_BUFFER, &buffer);
+      switch (buffer) {
+        case GL_FRONT:
+        case GL_FRONT_LEFT:
+        case GL_FRONT_RIGHT:
+          buffer = GL_FRONT;
+          break;
+        case GL_BACK:
+        case GL_BACK_LEFT:
+        case GL_BACK_RIGHT:
+          buffer = GL_BACK;
+          break;
+      }
+      mpglDrawBuffer(buffer);
+      break;
+  }
+}
+
 /**
  * \brief draw a texture part at given 2D coordinates
  * \param x screen top coordinate
--- a/libvo/gl_common.h	Mon Jul 05 18:24:02 2010 +0000
+++ b/libvo/gl_common.h	Mon Jul 05 19:19:56 2010 +0000
@@ -363,6 +363,14 @@
 void glEnableYUVConversion(GLenum target, int type);
 void glDisableYUVConversion(GLenum target, int type);
 
+#define GL_3D_RED_CYAN        1
+#define GL_3D_GREEN_MAGENTA   2
+#define GL_3D_QUADBUFFER      3
+
+void glEnable3DLeft(int type);
+void glEnable3DRight(int type);
+void glDisable3D(int type);
+
 /** \addtogroup glcontext
   * \{ */
 //! could not set new window, will continue drawing into the old one.
@@ -460,6 +468,7 @@
 extern void (GLAPIENTRY *mpglColorMaterial)(GLenum, GLenum);
 extern void (GLAPIENTRY *mpglShadeModel)(GLenum);
 extern void (GLAPIENTRY *mpglGetIntegerv)(GLenum, GLint *);
+extern void (GLAPIENTRY *mpglColorMask)(GLboolean, GLboolean, GLboolean, GLboolean);
 
 extern void (GLAPIENTRY *mpglGenBuffers)(GLsizei, GLuint *);
 extern void (GLAPIENTRY *mpglDeleteBuffers)(GLsizei, const GLuint *);
--- a/libvo/vo_gl.c	Mon Jul 05 18:24:02 2010 +0000
+++ b/libvo/vo_gl.c	Mon Jul 05 19:19:56 2010 +0000
@@ -155,6 +155,7 @@
 static int custom_tlin;
 static int custom_trect;
 static int mipmap_gen;
+static int stereo_mode;
 
 static int int_pause;
 static int eq_bri = 0;
@@ -788,11 +789,27 @@
   mpglColor3f(1,1,1);
   if (is_yuv || custom_prog)
     glEnableYUVConversion(gl_target, yuvconvtype);
+  if (stereo_mode) {
+    glEnable3DLeft(stereo_mode);
+    glDrawTex(0, 0, image_width, image_height,
+              0, 0, image_width >> 1, image_height,
+              texture_width, texture_height,
+              use_rectangle == 1, is_yuv,
+              mpi_flipped ^ vo_flipped);
+    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,
+              mpi_flipped ^ vo_flipped);
+    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,
             mpi_flipped ^ vo_flipped);
+  }
   if (is_yuv || custom_prog)
     glDisableYUVConversion(gl_target, yuvconvtype);
 }
@@ -1098,6 +1115,7 @@
   {"customtrect",  OPT_ARG_BOOL, &custom_trect, NULL},
   {"mipmapgen",    OPT_ARG_BOOL, &mipmap_gen,   NULL},
   {"osdcolor",     OPT_ARG_INT,  &osd_color,    NULL},
+  {"stereo",       OPT_ARG_INT,  &stereo_mode,  NULL},
   {NULL}
 };
 
@@ -1129,6 +1147,7 @@
     custom_trect = 0;
     mipmap_gen = 0;
     osd_color = 0xffffff;
+    stereo_mode = 0;
     if (subopt_parse(arg, subopts) != 0) {
       mp_msg(MSGT_VO, MSGL_FATAL,
               "\n-vo gl command line help:\n"
@@ -1202,6 +1221,11 @@
               "    generate mipmaps for the video image (use with TXB in customprog)\n"
               "  osdcolor=<0xAARRGGBB>\n"
               "    use the given color for the OSD\n"
+              "  stereo=<n>\n"
+              "    0: normal display\n"
+              "    1: side-by-side to red-cyan stereo\n"
+              "    2: side-by-side to green-magenta stereo\n"
+              "    3: side-by-side to quadbuffer stereo (broken?)\n"
               "\n" );
       return -1;
     }