[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