[MPlayer-dev-eng] patch for quadbuffered stereo using "-vo gl2:stereo"
Stuart Levy
slevy at ncsa.uiuc.edu
Wed Nov 28 22:16:03 CET 2007
On Wed, Nov 28, 2007 at 08:59:23PM +0100, Reimar Döffinger wrote:
[...]
> > +static void drawTextureDisplay ( float tex0, float tex1 )
> > {
[...]
> > + itx0 = (int) (tex0 * texnumx);
> > + itx1 = (int) ceilf(tex1 * texnumx);
> > +
>
> Instead of this "mess", why not just adding a proper transformation
> matrix? You wouldn't even have to change drawTextureDisplay, just change
> the matrix one level above. In addition this would be much easier to
> adjust for e.g. left image above right image and similar things.
drawTextureDisplay() does need the extra information passed in,
since in stereo mode, it must draw only the left-half pixels of
the source image when drawing to GL_BACK_LEFT, and then the
right half pixels in the second pass, instead of the usual case
which draws all the pixels. So just a transform matrix
wouldn't do. Right? And I need to compute which texture tiles
are covered by the necessary piece of source image, etc.
I could do the fxoff/fxscale conversions in a matrix -- something like
glPushMatrix();
glScalef( 1.0f/(tex1-tex0), 1.0f, 1.0f );
glTranslatef( -tex0, 0.0f, 0.0f );
...
glDrawTex(square->fx, square->fy, square->fw, square->fh, ... );
...
glPopMatrix();
but is that any clearer?
> Please make any code that uses glDrawBuffer revert it to GL_BACK
> instead immediately afterwards.
OK, thanks.
> > + if (quadbuffer_stereo)
> > + mp_msg(MSGT_VO, MSGL_FATAL, "[gl2] no Quadbuffered Stereo GLX support present\n");
> > + else
> > + mp_msg(MSGT_VO, MSGL_FATAL, "[gl2] no GLX support present\n");
>
> The old message was wrong anyway, and the one you add might not be right
> either, there can well be quadbuffer stereo support and it still will fail,
> e.g. because there is no doublebuffer support.
> It should just be replaced by something like "no suitable GLX visual found",
> and that is independent of this patch.
There's a new variant in the new attached patch -- how do you like this?
I think it might be nice to mention that quadbuffered stereo is required
in case of error, since most opengl implementations have all the
other requirements.
> > +#if 0
> > + if (quadbuffer_stereo) {
> > + /* v. Winckler's patch had just d_width /= 2, but that doesn't seem right either.
> > + * Mplayer experts please help! Meanwhile, leave this section out.
> > + * Then users must still give explicit -x and -y options as in
> > + * mplayer -vo gl2:stereo -x <SCREENWIDTH> -y <SCREENHEIGHT> movie...
> > + * At least *that* works. But default window doesn't, nor does -fs,
> > + * both apparently confused by double-wide aspect ratio of stereo anim files.
> > + */
> > + width /= 2;
> > + d_width /= 2;
> > + }
> > +#endif
>
> I guess you give the wrong -monitoraspect. If you want it automated you
> probably at least have to hack VOCTRL_UPDATE_SCREENINFO
Could you explain more about what should be updated? I don't know even
what the fields mean, let alone which ones I'm free to change at what point.
Presumably mplayer is getting a correct idea about the monitor aspect;
for example, 1.777:1 on a 1920x1080 stereo-capable display.
And the pixels are square, both on the display and in the designed animation.
But the animation file might have a size like 3840x1080 or 2560x720,
i.e. 3.555:1. To make this work right, somehow in the gl2:stereo code
I need to mislead mplayer about the image aspect ratio.
E.g. if the animation file is 3840x1080, then
mplayer -vo gl2:stereo should open a 1920x1080 window.
Should I just go change vo_dwidth somewhere? Or use something like
initGl( quadbuffer_stereo ? vo_dwidth/2 : vo_dwidth, vo_dheight )
?
> > // glFlush();
> > if (use_glFinish)
> > - glFinish();
> > + glFinish();
>
> Cosmetic.
OK. I hope you agree that code like
if (use_glFinish)
glFinish();
(with matching indentation on both lines)
is uglier than it should be,
but won't try to change that in this patch.
> > @@ -859,6 +924,8 @@
> > " 3: use fragment program with gamma correction.\n"
> > " 4: use fragment program with gamma correction via lookup.\n"
> > " 5: use ATI-specific method (for older cards).\n"
> > + " stereo\n"
> > + " use quadbuffered stereo: left-half image to left eye, etc.\n"
>
> No tabs please (unless the surrounding code uses them).
Righto. Here's another try.
Index: libvo/vo_gl2.c
===================================================================
--- libvo/vo_gl2.c (revision 25184)
+++ libvo/vo_gl2.c (working copy)
@@ -7,6 +7,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <math.h>
#include "config.h"
#include "mp_msg.h"
@@ -46,6 +47,11 @@
/* local data */
static unsigned char *ImageData=NULL;
+// QuadBuffer Stereo
+static unsigned char quadbuffer_stereo = 0;
+
+
+
#ifdef GL_WIN32
static int gl_vinfo = 0;
static HGLRC gl_context = 0;
@@ -358,23 +364,31 @@
}
-static void drawTextureDisplay (void)
+static void drawTextureDisplay ( float tex0, float tex1 )
{
struct TexSquare *square = texgrid;
int x, y;
+ int itx0, itx1;
+ GLfloat fxoff = tex0;
+ GLfloat fxscale = 1.0f / (tex1 - tex0);
+
glColor3f(1.0,1.0,1.0);
+ itx0 = (int) (tex0 * texnumx);
+ itx1 = (int) ceilf(tex1 * texnumx);
+
if (image_format == IMGFMT_YV12)
glEnableYUVConversion(GL_TEXTURE_2D, use_yuv);
for (y = 0; y < texnumy; y++) {
int thish = texture_height;
if (y == texnumy - 1 && image_height % texture_height)
thish = image_height % texture_height;
- for (x = 0; x < texnumx; x++) {
+ for (x = itx0; x < itx1; x++) {
int thisw = texture_width;
if (x == texnumx - 1 && image_width % texture_width)
thisw = image_width % texture_width;
+ square = texgrid + y*texnumx + x;
glBindTexture (GL_TEXTURE_2D, square->texobj);
if (image_format == IMGFMT_YV12) {
ActiveTexture(GL_TEXTURE1);
@@ -390,11 +404,10 @@
0, 0, thisw, thish, 0);
}
- glDrawTex(square->fx, square->fy, square->fw, square->fh,
+ glDrawTex((square->fx - fxoff) * fxscale, square->fy, square->fw * fxscale, square->fh,
0, 0, texture_width, texture_height,
texture_width, texture_height,
0, image_format == IMGFMT_YV12, 0);
- square++;
} /* for all texnumx */
} /* for all texnumy */
if (image_format == IMGFMT_YV12)
@@ -432,18 +445,26 @@
static void draw_alpha_32(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride){
vo_draw_alpha_rgb32(w,h,src,srca,stride,ImageData+4*(y0*image_width+x0),4*image_width);
+ if (quadbuffer_stereo)
+ vo_draw_alpha_rgb32(w,h,src,srca,stride,ImageData+4*(y0*image_width+x0+image_width/2),4*image_width);
}
static void draw_alpha_24(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride){
vo_draw_alpha_rgb24(w,h,src,srca,stride,ImageData+3*(y0*image_width+x0),3*image_width);
+ if (quadbuffer_stereo)
+ vo_draw_alpha_rgb24(w,h,src,srca,stride,ImageData+3*(y0*image_width+x0+image_width/2),3*image_width);
}
static void draw_alpha_16(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride){
vo_draw_alpha_rgb16(w,h,src,srca,stride,ImageData+2*(y0*image_width+x0),2*image_width);
+ if (quadbuffer_stereo)
+ vo_draw_alpha_rgb16(w,h,src,srca,stride,ImageData+2*(y0*image_width+x0+image_width/2),2*image_width);
}
static void draw_alpha_15(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride){
vo_draw_alpha_rgb15(w,h,src,srca,stride,ImageData+2*(y0*image_width+x0),2*image_width);
+ if (quadbuffer_stereo)
+ vo_draw_alpha_rgb15(w,h,src,srca,stride,ImageData+2*(y0*image_width+x0+image_width/2),2*image_width);
}
static void draw_alpha_null(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride){
@@ -483,6 +504,11 @@
/* furthermore it must be RGBA (not color indexed) ... */
res = glXGetConfig(dpy, vi_list + i, GLX_RGBA, &val);
if (res || val == False) continue;
+ /* assure quadbuffered stereo if requested */
+ if (quadbuffer_stereo) {
+ res = glXGetConfig(dpy, vi_list + i, GLX_STEREO, &val);
+ if (res || val == False) continue;
+ }
/* prefer less depth buffer size, */
res = glXGetConfig(dpy, vi_list + i, GLX_DEPTH_SIZE, &val);
if (res) continue;
@@ -530,7 +556,8 @@
}
vinfo = choose_glx_visual(mDisplay,mScreen,&vinfo_buf) < 0 ? NULL : &vinfo_buf;
if (vinfo == NULL) {
- mp_msg(MSGT_VO, MSGL_FATAL, "[gl2] no GLX support present\n");
+ mp_msg(MSGT_VO, MSGL_FATAL, "[gl2] no suitable GLX visual found%s\n",
+ quadbuffer_stereo ? " (need quadbuffered stereo for '-vo gl2:stereo')" : "");
return -1;
}
@@ -593,8 +620,16 @@
glClearColor( 0.0f,0.0f,0.0f,0.0f );
glClear( GL_COLOR_BUFFER_BIT );
+ if ( quadbuffer_stereo ) {
+ glDrawBuffer(GL_BACK_LEFT);
+ drawTextureDisplay( 0.0f, 0.5f );
+ glDrawBuffer(GL_BACK_RIGHT);
+ drawTextureDisplay( 0.5f, 1.0f );
+ glDrawBuffer(GL_BACK);
- drawTextureDisplay ();
+ } else {
+ drawTextureDisplay ( 0.0f, 1.0f );
+ }
return 0;
}
@@ -611,6 +646,20 @@
image_width = width;
image_format = format;
+#if 0
+ if (quadbuffer_stereo) {
+ /* v. Winckler's patch had just d_width /= 2, but that doesn't seem right either.
+ * Mplayer experts please help! Meanwhile, leave this section out.
+ * Then users must still give explicit -x and -y options as in
+ * mplayer -vo gl2:stereo -x <SCREENWIDTH> -y <SCREENHEIGHT> movie...
+ * At least *that* works. But default window doesn't, nor does -fs,
+ * both apparently confused by double-wide aspect ratio of stereo anim files.
+ */
+ width /= 2;
+ d_width /= 2;
+ }
+#endif
+
int_pause = 0;
#ifdef HAVE_NEW_GUI
@@ -718,13 +767,21 @@
static void draw_osd(void)
{
if (ImageData)
- vo_draw_text(image_width,image_height,draw_alpha_fnc);
+ vo_draw_text( quadbuffer_stereo ? image_width/2 : image_width, image_height,draw_alpha_fnc);
}
static void
flip_page(void)
{
- drawTextureDisplay();
+ if ( quadbuffer_stereo ) {
+ glDrawBuffer( GL_BACK_LEFT );
+ drawTextureDisplay( 0.0f, 0.5f );
+ glDrawBuffer( GL_BACK_RIGHT );
+ drawTextureDisplay( 0.5f, 1.0f );
+ glDrawBuffer( GL_BACK );
+ } else {
+ drawTextureDisplay( 0.0f, 1.0f );
+ }
// glFlush();
if (use_glFinish)
@@ -732,7 +789,9 @@
swapGlBuffers();
if (vo_fs) // Avoid flickering borders in fullscreen mode
+ {
glClear (GL_COLOR_BUFFER_BIT);
+ }
}
static int draw_slice(uint8_t *src[], int stride[], int w,int h,int x,int y)
@@ -837,6 +896,7 @@
static opt_t subopts[] = {
{"yuv", OPT_ARG_INT, &use_yuv, (opt_test_f)int_non_neg},
{"glfinish", OPT_ARG_BOOL, &use_glFinish, NULL},
+ {"stereo", OPT_ARG_BOOL, &quadbuffer_stereo, NULL},
{NULL}
};
@@ -859,6 +919,8 @@
" 3: use fragment program with gamma correction.\n"
" 4: use fragment program with gamma correction via lookup.\n"
" 5: use ATI-specific method (for older cards).\n"
+ " stereo\n"
+ " use quadbuffered stereo: left-half image to left eye, etc.\n"
"\n" );
return -1;
}
More information about the MPlayer-dev-eng
mailing list