[MPlayer-dev-eng] New stereo output mode for OpenGL video driver

Wolfgang Draxinger wdraxinger.maillist at draxit.de
Sat Dec 24 19:35:29 CET 2011


On Sat, 24 Dec 2011 16:10:48 +0100
Reimar Döffinger <Reimar.Doeffinger at gmx.de> wrote:

> If there's an issue it can be quickly fixed if the same code is used
> everywhere, when different code is used for the same thing you end up
> with half-working, half-broken code quite quickly.

And sometimes fixing something makes sense for only one codepath, but
may break others. In the case of stipple patterns I see little sense in
using that function. It's meant for the usual video texture uploads. If
something changes there, this doesn't mean, stipple patterns now work
differently, too.

> There are far more methods, unfortunately.

I know, but I've never seen them in the wild, except for short test
clips.
 
> As you say glTexSubImage2D would work for this.
> In addition -vf stereo3d filter is there to do all those conversions.

What I don't like about doing this with a filter is, that it eats CPU
cycles, and has the mentioned caveats. The only benefit I see in using
a filter is, that it works for all backends.

My revised patch follows:


diff --git a/libvo/gl_common.c b/libvo/gl_common.c
index 5c46b6f..282e1eb 100644
--- a/libvo/gl_common.c
+++ b/libvo/gl_common.c
@@ -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);
+void (GLAPIENTRY *mpglPolygonStipple)(const GLubyte*);
 
 /**
  * \defgroup glextfunctions OpenGL extension functions
@@ -447,6 +448,7 @@ static const extfunc_desc_t extfuncs[] = {
   DEF_FUNC_DESC(ShadeModel),
   DEF_FUNC_DESC(GetIntegerv),
   DEF_FUNC_DESC(ColorMask),
+  DEF_FUNC_DESC(PolygonStipple),
 
   // here start the real extensions
   {&mpglGenBuffers, NULL, {"glGenBuffers", "glGenBuffersARB", NULL}},
@@ -1588,6 +1590,208 @@ void glDisableYUVConversion(GLenum target, int type) {
   }
 }
 
+/* Stipple patterns for row and column interlacing.
+ * Used for interlaced stereo output. */
+
+static GLubyte const stipple_row_even[]={
+  0xff,0xff,0xff,0xff,
+  0x00,0x00,0x00,0x00,
+  0xff,0xff,0xff,0xff,
+  0x00,0x00,0x00,0x00,
+  0xff,0xff,0xff,0xff,
+  0x00,0x00,0x00,0x00,
+  0xff,0xff,0xff,0xff,
+  0x00,0x00,0x00,0x00,
+  0xff,0xff,0xff,0xff,
+  0x00,0x00,0x00,0x00,
+  0xff,0xff,0xff,0xff,
+  0x00,0x00,0x00,0x00,
+  0xff,0xff,0xff,0xff,
+  0x00,0x00,0x00,0x00,
+  0xff,0xff,0xff,0xff,
+  0x00,0x00,0x00,0x00,
+  0xff,0xff,0xff,0xff,
+  0x00,0x00,0x00,0x00,
+  0xff,0xff,0xff,0xff,
+  0x00,0x00,0x00,0x00,
+  0xff,0xff,0xff,0xff,
+  0x00,0x00,0x00,0x00,
+  0xff,0xff,0xff,0xff,
+  0x00,0x00,0x00,0x00,
+  0xff,0xff,0xff,0xff,
+  0x00,0x00,0x00,0x00,
+  0xff,0xff,0xff,0xff,
+  0x00,0x00,0x00,0x00,
+  0xff,0xff,0xff,0xff,
+  0x00,0x00,0x00,0x00,
+  0xff,0xff,0xff,0xff,
+  0x00,0x00,0x00,0x00,
+  0xff,0xff,0xff,0xff,
+};
+static GLubyte const * const stipple_row_odd = stipple_row_even + 4;
+
+static GLubyte const stipple_column_even[]={
+  0xaa,0xaa,0xaa,0xaa,
+  0xaa,0xaa,0xaa,0xaa,
+  0xaa,0xaa,0xaa,0xaa,
+  0xaa,0xaa,0xaa,0xaa,
+  0xaa,0xaa,0xaa,0xaa,
+  0xaa,0xaa,0xaa,0xaa,
+  0xaa,0xaa,0xaa,0xaa,
+  0xaa,0xaa,0xaa,0xaa,
+  0xaa,0xaa,0xaa,0xaa,
+  0xaa,0xaa,0xaa,0xaa,
+  0xaa,0xaa,0xaa,0xaa,
+  0xaa,0xaa,0xaa,0xaa,
+  0xaa,0xaa,0xaa,0xaa,
+  0xaa,0xaa,0xaa,0xaa,
+  0xaa,0xaa,0xaa,0xaa,
+  0xaa,0xaa,0xaa,0xaa,
+  0xaa,0xaa,0xaa,0xaa,
+  0xaa,0xaa,0xaa,0xaa,
+  0xaa,0xaa,0xaa,0xaa,
+  0xaa,0xaa,0xaa,0xaa,
+  0xaa,0xaa,0xaa,0xaa,
+  0xaa,0xaa,0xaa,0xaa,
+  0xaa,0xaa,0xaa,0xaa,
+  0xaa,0xaa,0xaa,0xaa,
+  0xaa,0xaa,0xaa,0xaa,
+  0xaa,0xaa,0xaa,0xaa,
+  0xaa,0xaa,0xaa,0xaa,
+  0xaa,0xaa,0xaa,0xaa,
+  0xaa,0xaa,0xaa,0xaa,
+  0xaa,0xaa,0xaa,0xaa,
+  0xaa,0xaa,0xaa,0xaa,
+  0xaa,0xaa,0xaa,0xaa,
+};
+
+static GLubyte const stipple_column_odd[]={
+  0x55,0x55,0x55,0x55,
+  0x55,0x55,0x55,0x55,
+  0x55,0x55,0x55,0x55,
+  0x55,0x55,0x55,0x55,
+  0x55,0x55,0x55,0x55,
+  0x55,0x55,0x55,0x55,
+  0x55,0x55,0x55,0x55,
+  0x55,0x55,0x55,0x55,
+  0x55,0x55,0x55,0x55,
+  0x55,0x55,0x55,0x55,
+  0x55,0x55,0x55,0x55,
+  0x55,0x55,0x55,0x55,
+  0x55,0x55,0x55,0x55,
+  0x55,0x55,0x55,0x55,
+  0x55,0x55,0x55,0x55,
+  0x55,0x55,0x55,0x55,
+  0x55,0x55,0x55,0x55,
+  0x55,0x55,0x55,0x55,
+  0x55,0x55,0x55,0x55,
+  0x55,0x55,0x55,0x55,
+  0x55,0x55,0x55,0x55,
+  0x55,0x55,0x55,0x55,
+  0x55,0x55,0x55,0x55,
+  0x55,0x55,0x55,0x55,
+  0x55,0x55,0x55,0x55,
+  0x55,0x55,0x55,0x55,
+  0x55,0x55,0x55,0x55,
+  0x55,0x55,0x55,0x55,
+  0x55,0x55,0x55,0x55,
+  0x55,0x55,0x55,0x55,
+  0x55,0x55,0x55,0x55,
+  0x55,0x55,0x55,0x55,
+};
+
+static GLubyte const stipple_checkerboard_even[] = {
+  0xaa,0xaa,0xaa,0xaa,
+  0x55,0x55,0x55,0x55,
+  0xaa,0xaa,0xaa,0xaa,
+  0x55,0x55,0x55,0x55,
+  0xaa,0xaa,0xaa,0xaa,
+  0x55,0x55,0x55,0x55,
+  0xaa,0xaa,0xaa,0xaa,
+  0x55,0x55,0x55,0x55,
+  0xaa,0xaa,0xaa,0xaa,
+  0x55,0x55,0x55,0x55,
+  0xaa,0xaa,0xaa,0xaa,
+  0x55,0x55,0x55,0x55,
+  0xaa,0xaa,0xaa,0xaa,
+  0x55,0x55,0x55,0x55,
+  0xaa,0xaa,0xaa,0xaa,
+  0x55,0x55,0x55,0x55,
+  0xaa,0xaa,0xaa,0xaa,
+  0x55,0x55,0x55,0x55,
+  0xaa,0xaa,0xaa,0xaa,
+  0x55,0x55,0x55,0x55,
+  0xaa,0xaa,0xaa,0xaa,
+  0x55,0x55,0x55,0x55,
+  0xaa,0xaa,0xaa,0xaa,
+  0x55,0x55,0x55,0x55,
+  0xaa,0xaa,0xaa,0xaa,
+  0x55,0x55,0x55,0x55,
+  0xaa,0xaa,0xaa,0xaa,
+  0x55,0x55,0x55,0x55,
+  0xaa,0xaa,0xaa,0xaa,
+  0x55,0x55,0x55,0x55,
+  0xaa,0xaa,0xaa,0xaa,
+  0x55,0x55,0x55,0x55,
+  0xaa,0xaa,0xaa,0xaa,
+};
+static GLubyte const * const stipple_checkerboard_odd = stipple_checkerboard_even + 4;
+
+static GLubyte const stipple_none[] = {
+  0xff,0xff,0xff,0xff,
+  0xff,0xff,0xff,0xff,
+  0xff,0xff,0xff,0xff,
+  0xff,0xff,0xff,0xff,
+  0xff,0xff,0xff,0xff,
+  0xff,0xff,0xff,0xff,
+  0xff,0xff,0xff,0xff,
+  0xff,0xff,0xff,0xff,
+  0xff,0xff,0xff,0xff,
+  0xff,0xff,0xff,0xff,
+  0xff,0xff,0xff,0xff,
+  0xff,0xff,0xff,0xff,
+  0xff,0xff,0xff,0xff,
+  0xff,0xff,0xff,0xff,
+  0xff,0xff,0xff,0xff,
+  0xff,0xff,0xff,0xff,
+  0xff,0xff,0xff,0xff,
+  0xff,0xff,0xff,0xff,
+  0xff,0xff,0xff,0xff,
+  0xff,0xff,0xff,0xff,
+  0xff,0xff,0xff,0xff,
+  0xff,0xff,0xff,0xff,
+  0xff,0xff,0xff,0xff,
+  0xff,0xff,0xff,0xff,
+  0xff,0xff,0xff,0xff,
+  0xff,0xff,0xff,0xff,
+  0xff,0xff,0xff,0xff,
+  0xff,0xff,0xff,0xff,
+  0xff,0xff,0xff,0xff,
+  0xff,0xff,0xff,0xff,
+  0xff,0xff,0xff,0xff,
+  0xff,0xff,0xff,0xff
+};
+
+/* TODO:
+ * In the current implementation the interlacing happens relative
+ * to the OpenGL viewport. However to reliably work on display that
+ * employ interlacing for stereo image spearation, the interlacing
+ * must happen relative to the screen origin.
+ *
+ * This leaves to be implemented:
+ *  - at window move events the origin of the window interior origin
+ *    in screen coordinates must be determined and that taken into
+ *    account choosing the stipple pattern.
+ *  - a nice have to feature was retrieving the EDID of the display
+ *    showing the sub screen in which the mplayer window is placed,
+ *    and using vendor/model information therein to load from a
+ *    (compiled in) database which interlacing order to use.
+ *
+ * A further nice-to-have feature was a anti-ghost implementation
+ * where the image of the other eye, multiplied with a value
+ * -1 < x < 0 is added to compensate for ghosting.
+ */
+
 void glEnable3DLeft(int type) {
   GLint buffer;
   if (type & GL_3D_SWAP)
@@ -1615,6 +1819,24 @@ void glEnable3DLeft(int type) {
       }
       mpglDrawBuffer(buffer);
       break;
+    case GL_3D_ROWINTERLACE:
+      mpglEnable(GL_POLYGON_STIPPLE);
+      mpglPixelStorei(GL_UNPACK_ALIGNMENT,1);
+      mpglPixelStorei(GL_UNPACK_ROW_LENGTH,0);
+      mpglPolygonStipple(stipple_row_even);
+      break;
+    case GL_3D_COLUMNINTERLACE:
+      mpglEnable(GL_POLYGON_STIPPLE);
+      mpglPixelStorei(GL_UNPACK_ALIGNMENT,1);
+      mpglPixelStorei(GL_UNPACK_ROW_LENGTH,0);
+      mpglPolygonStipple(stipple_column_even);
+      break;
+    case GL_3D_CHECKERBOARDINTERLACE:
+      mpglEnable(GL_POLYGON_STIPPLE);
+      mpglPixelStorei(GL_UNPACK_ALIGNMENT,1);
+      mpglPixelStorei(GL_UNPACK_ROW_LENGTH,0);
+      mpglPolygonStipple(stipple_checkerboard_even);
+      break;
   }
 }
 
@@ -1645,6 +1867,24 @@ void glEnable3DRight(int type) {
       }
       mpglDrawBuffer(buffer);
       break;
+    case GL_3D_ROWINTERLACE:
+      mpglEnable(GL_POLYGON_STIPPLE);
+      mpglPixelStorei(GL_UNPACK_ALIGNMENT,1);
+      mpglPixelStorei(GL_UNPACK_ROW_LENGTH,0);
+      mpglPolygonStipple(stipple_row_odd);
+      break;
+    case GL_3D_COLUMNINTERLACE:
+      mpglEnable(GL_POLYGON_STIPPLE);
+      mpglPixelStorei(GL_UNPACK_ALIGNMENT,1);
+      mpglPixelStorei(GL_UNPACK_ROW_LENGTH,0);
+      mpglPolygonStipple(stipple_column_odd);
+      break;
+    case GL_3D_CHECKERBOARDINTERLACE:
+      mpglEnable(GL_POLYGON_STIPPLE);
+      mpglPixelStorei(GL_UNPACK_ALIGNMENT,1);
+      mpglPixelStorei(GL_UNPACK_ROW_LENGTH,0);
+      mpglPolygonStipple(stipple_checkerboard_odd);
+      break;
   }
 }
 
@@ -1672,6 +1912,12 @@ void glDisable3D(int type) {
       }
       mpglDrawBuffer(buffer);
       break;
+    case GL_3D_ROWINTERLACE:
+    case GL_3D_COLUMNINTERLACE:
+    case GL_3D_CHECKERBOARDINTERLACE:
+      glDisable(GL_POLYGON_STIPPLE);
+      mpglPolygonStipple(stipple_none);
+      break;
   }
 }
 
diff --git a/libvo/gl_common.h b/libvo/gl_common.h
index c48812e..b82bfa9 100644
--- a/libvo/gl_common.h
+++ b/libvo/gl_common.h
@@ -386,10 +386,13 @@ void glSetupYUVConversion(gl_conversion_params_t *params);
 void glEnableYUVConversion(GLenum target, int type);
 void glDisableYUVConversion(GLenum target, int type);
 
-#define GL_3D_SWAP           32
-#define GL_3D_RED_CYAN        1
-#define GL_3D_GREEN_MAGENTA   2
-#define GL_3D_QUADBUFFER      3
+#define GL_3D_SWAP                  32
+#define GL_3D_RED_CYAN              1
+#define GL_3D_GREEN_MAGENTA         2
+#define GL_3D_QUADBUFFER            3
+#define GL_3D_ROWINTERLACE          4
+#define GL_3D_COLUMNINTERLACE       5
+#define GL_3D_CHECKERBOARDINTERLACE 6
 
 void glEnable3DLeft(int type);
 void glEnable3DRight(int type);
@@ -494,6 +497,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 *mpglPolygonStipple)(const GLubyte*);
 
 extern void (GLAPIENTRY *mpglGenBuffers)(GLsizei, GLuint *);
 extern void (GLAPIENTRY *mpglDeleteBuffers)(GLsizei, const GLuint *);
diff --git a/libvo/vo_gl.c b/libvo/vo_gl.c
index 892c02e..e947753 100644
--- a/libvo/vo_gl.c
+++ b/libvo/vo_gl.c
@@ -1297,6 +1297,9 @@ static int preinit_internal(const char *arg, int allow_sw)
               "    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\n"
+              "    4: side-by-side to row interlaced stereo\n"
+              "    5: side-by-side to column interlaced stereo\n"
+              "    6: side-by-side to checkerboard interlaced stereo\n"
               "  backend=<n>\n"
               "   -1: auto-select\n"
               "    0: Win32/WGL\n"



More information about the MPlayer-dev-eng mailing list