summaryrefslogtreecommitdiffstats
path: root/libvo/vo_dga.c
diff options
context:
space:
mode:
authoracki2 <acki2@b3059339-0415-0410-9bf9-f77b7e298cf2>2001-03-30 22:09:38 +0000
committeracki2 <acki2@b3059339-0415-0410-9bf9-f77b7e298cf2>2001-03-30 22:09:38 +0000
commit59ea3d5640751f682e1df1920ff617831ec584be (patch)
treefa9ef68878d5fe4d12fd81ff964ade22ed4058a3 /libvo/vo_dga.c
parent80147bb9fb9ff25fb4d8e82580439863a3a9d976 (diff)
downloadmpv-59ea3d5640751f682e1df1920ff617831ec584be.tar.bz2
mpv-59ea3d5640751f682e1df1920ff617831ec584be.tar.xz
- 32/16 bit mode swtiching with DGA2.0
- now use only DGA2.0 API when DGA2.0 is available git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@262 b3059339-0415-0410-9bf9-f77b7e298cf2
Diffstat (limited to 'libvo/vo_dga.c')
-rw-r--r--libvo/vo_dga.c397
1 files changed, 304 insertions, 93 deletions
diff --git a/libvo/vo_dga.c b/libvo/vo_dga.c
index 2ee0072ca0..8c1ec4c4ec 100644
--- a/libvo/vo_dga.c
+++ b/libvo/vo_dga.c
@@ -15,7 +15,20 @@
* o this is alpha
* o covers only common video card formats
* o works only on intel architectures
+ *
+ * 30/02/2001
*
+ * o query_format(): with DGA 2.0 it returns all depths it supports
+ * (even 16 when running 32 and vice versa)
+ * Checks for (hopefully!) compatible RGBmasks in 15/16 bit modes
+ * o added some more criterions for resolution switching
+ * o cleanup
+ * o with DGA2.0 present, ONLY DGA2.0 functions are used
+ * o for 15/16 modes ONLY RGB 555 is supported, since the divx-codec
+ * happens to map the data this way. If your graphics card supports
+ * this, you're well off and may use these modes; for mpeg
+ * movies things could be different, but I was too lazy to implement
+ * it ...
*/
@@ -24,13 +37,12 @@
#include <stdlib.h>
#include <string.h>
-
-//#include "linux/keycodes.h"
#include "config.h"
#include "video_out.h"
#include "video_out_internal.h"
#include "yuv2rgb.h"
+
LIBVO_EXTERN( dga )
#include <X11/Xlib.h>
@@ -61,6 +73,7 @@ static int vo_dga_src_skip; // bytes to skip after copying one line
static int vo_dga_vp_skip; // dto. for dest
static int vo_dga_lines; // num of lines to copy
static int vo_dga_src_format;
+static int vo_dga_planes; // bits per pixel on screen
static unsigned char *vo_dga_base;
static Display *vo_dga_dpy;
@@ -158,14 +171,82 @@ static const vo_info_t* get_info( void )
static uint32_t query_format( uint32_t format )
{
- printf("vo_dga: query_format\n");
- if( !vo_init() ) return 0; // Can't open X11
- printf("Format: %lx\n", format);
+#ifdef HAVE_DGA2
+ XDGAMode *modelines;
+ int modecount;
+ Display *qdisp;
+#endif
+
+ int i,k,dummy;
+ static int dga_depths_init = 0;
+ static int dga_depths = 0; // each bit that is set represents
+ // a depth the X-Server is capable
+ // of displaying
+
+
+ if( !vo_init() ) return 0; // Can't open X11
+
+ if(dga_depths_init == 0){
+#ifdef HAVE_DGA2
+
+ if((qdisp = XOpenDisplay(0))==NULL){
+ printf("vo_dga: Can't open display!\n");
+ return 0;
+ }
+ modelines=XDGAQueryModes(qdisp, XDefaultScreen(qdisp),&modecount);
+ for(i=0; i< modecount; i++){
+ if( ( (modelines[i].bitsPerPixel == 15 ||
+ modelines[i].bitsPerPixel == 16) &&
+ modelines[i].redMask == 0x7c00 &&
+ modelines[i].greenMask == 0x03e0 &&
+ modelines[i].blueMask == 0x001f
+ ) ||
+ ( modelines[i].bitsPerPixel != 15 &&
+ modelines[i].bitsPerPixel != 16
+ )
+ )
+ {
+ for(k=0, dummy=1; k<modelines[i].bitsPerPixel-1; k++)dummy <<=1;
+ dga_depths |= dummy;
+ }
+
+ }
+ XCloseDisplay(qdisp);
+
+#else
+
+ for(k=0, dummy=1; k<vo_depthonscreen-1; k++)dummy <<=1;
+ dga_depths |= dummy;
+ // hope this shift is ok; heard that on some systems only up to 8 digits
+ // may be shifted at a time. SIGH! It IS so.
+ // test for RGB masks !!!! (if depthonscreen != 24 or 32 !!!)
+ if( !(vo_depthonscreen == 24 || vo_depthonscreen == 32 ) ){
+ printf("vo_dga: You're running 15/16 bit X Server; your hardware might use unsuitable RGB-mask!\n");
+ }
+#endif
+ dga_depths_init = 1;
+
+ if( dga_depths == 0){
+ printf("vo_dga: Sorry, there seems to be no suitable depth available!\n");
+ printf(" Try running X in 24 or 32 bit mode!!!\n");
+ return 0;
+ }else{
+ for(i=0, dummy=1; i< 32; i++){
+ if(dummy& dga_depths){
+ printf("vo_dga: may use %2d bits per pixel\n", i+1);
+ }
+ dummy <<= 1;
+ }
+ }
+ }
if( format==IMGFMT_YV12 ) return 1;
+ for(k=0, dummy=1; k<(format&0xFF)-1; k++)dummy<<=1;
+
if( ( format&IMGFMT_BGR_MASK )==IMGFMT_BGR &&
- ( format&0xFF )==vo_depthonscreen ) return 1;
+ ( dummy & dga_depths )) return 1;
+
return 0;
}
@@ -175,71 +256,28 @@ static void
uninit(void)
{
+#ifdef HAVE_DGA2
+ XDGADevice *dgadevice;
+#endif
+
vo_dga_is_running = 0;
printf("vo_dga: in uninit\n");
XUngrabPointer (vo_dga_dpy, CurrentTime);
XUngrabKeyboard (vo_dga_dpy, CurrentTime);
+#ifdef HAVE_DGA2
+ dgadevice = XDGASetMode(vo_dga_dpy, XDefaultScreen(vo_dga_dpy), 0);
+ if(dgadevice != NULL){
+ XFree(dgadevice);
+ }
+ XDGACloseFramebuffer(vo_dga_dpy, XDefaultScreen(vo_dga_dpy));
+#else
XF86DGADirectVideo (vo_dga_dpy, XDefaultScreen(vo_dga_dpy), 0);
+#endif
XCloseDisplay(vo_dga_dpy);
}
-//---------------------------------------------------------
-
-static uint32_t init( uint32_t width, uint32_t height,
- uint32_t d_width,uint32_t d_height,
- uint32_t fullscreen,char *title,uint32_t format )
-{
-
- int bank, ram;
- int x_off, y_off;
-
-#ifdef HAVE_DGA2
-// needed to change DGA video mode
- int modecount,mX, mY, mVBI, i,j;
- int X,Y;
- XDGAMode *modelines=NULL;
- XDGADevice *dgadevice;
-#endif
-
- if( vo_dga_is_running )return -1;
-
- if( !vo_init() ){
- printf("vo_dga: vo_init() failed!\n");
- return 0;
- }
-
- if((vo_dga_dpy = XOpenDisplay(0))==NULL)
- {
- printf ("vo_dga: Can't open display\n");
- return 1;
- }
-#ifdef HAVE_DGA2
-// Code to change the video mode added by Michael Graffam
-// mgraffam@idsi.net
- if (modelines==NULL)
- modelines=XDGAQueryModes(vo_dga_dpy, XDefaultScreen(vo_dga_dpy),&modecount);
-
- mX=modelines[0].imageWidth;
- mY=modelines[0].imageHeight;
- mVBI = modelines[0].verticalRefresh;
- X=d_width; Y=d_height;
-
- printf("vo_dga: Using DGA 2.0 mode changing support\n");
- j=0;
- // offbyone-error !!! i<=modecount is WRONG !!!
- for (i=1; i<modecount; i++)
- {
- if( modelines[i].bitsPerPixel == vo_depthonscreen &&
- modelines[i].maxViewportX)
- {
- printf("vo_dga: (%3d) Trying %4d x %4d @ %3d Hz @ %2d bpp ..",
- i,
- modelines[i].viewportWidth,
- modelines[i].viewportHeight,
- (unsigned int) modelines[i].verticalRefresh,
- modelines[i].bitsPerPixel );
-
+#if 0
if (
(modelines[i].viewportWidth >= X) &&
(modelines[i].viewportHeight >= Y) &&
@@ -290,23 +328,209 @@ static uint32_t init( uint32_t width, uint32_t height,
}else{
printf(".no\n");
}
+#endif
+
+
+//----------------------------------------------------------
+
+int check_mode( int x, int y,
+ int new_x, int new_y, int new_vbi,
+ int *old_x, int *old_y, int *old_vbi){
+
+ if (
+ (new_x >= x) &&
+ (new_y >= y) &&
+ (
+ // prefer a better resolution either in X or in Y
+ // as long as the other dimension is at least the same
+ //
+ // hmm ... MAYBE it would be more clever to focus on the
+ // x-resolution; I had 712x400 and 640x480 and the movie
+ // was 640x360; 640x480 would be the 'right thing' here
+ // but since 712x400 was queried first I got this one.
+ // I think there should be a cmd-line switch to let the
+ // user choose the mode he likes ... (acki2)
+
+ (
+ ((new_x < *old_x) &&
+ !(new_y > *old_y)) ||
+ ((new_y < *old_y) &&
+ !(new_x > *old_x))
+ )
+ // but if we get an identical resolution choose
+ // the one with the lower refreshrate (saves bandwidth !!!)
+ // as long as it's above 50 Hz (acki2 on 30/3/2001)
+ ||
+ (
+ (new_x == *old_x) &&
+ (new_y == *old_y) &&
+ (
+ (
+ new_vbi >= *old_vbi && *old_vbi < 50
+ )
+ ||
+ (
+ *old_vbi >= 50 &&
+ new_vbi < *old_vbi &&
+ new_vbi >= 50
+ )
+ )
+ )
+ )
+ )
+ {
+ *old_x = new_x;
+ *old_y = new_y;
+ *old_vbi = new_vbi;
+ return 1;
+ }else{
+ return 0;
}
+}
+
+
+
+//---------------------------------------------------------
+
+static uint32_t init( uint32_t width, uint32_t height,
+ uint32_t d_width,uint32_t d_height,
+ uint32_t fullscreen,char *title,uint32_t format )
+{
+
+ int x_off, y_off;
+
+#ifdef HAVE_DGA2
+ // needed to change DGA video mode
+ int modecount,mX, mY, mVBI, i,j;
+ int dga_modenum;
+ XDGAMode *modelines=NULL;
+ XDGADevice *dgadevice;
+#else
+ int bank, ram;
+#endif
+
+ if( vo_dga_is_running )return -1;
+
+
+ if( !vo_init() ){
+ printf("vo_dga: vo_init() failed!\n");
+ return 0;
+ }
+
+ if (format == IMGFMT_YV12 ){
+ vo_dga_planes = vo_depthonscreen;
+ vo_dga_planes = vo_dga_planes == 15 ? 16 : vo_dga_planes;
+ }else{
+ vo_dga_planes = (format & 0xff);
+
+ // hack!!! here we should only get what we told in query_format()
+ // but mplayer is somewhat generous about 15/16bit depth ...
+
+ vo_dga_planes = vo_dga_planes == 15 ? 16 : vo_dga_planes;
+ }
+
+ if((vo_dga_dpy = XOpenDisplay(0))==NULL)
+ {
+ printf ("vo_dga: Can't open display\n");
+ return 1;
+ }
+
+ vo_dga_bpp = (vo_dga_planes+7) >> 3;
+
+// choose a suitable mode ...
+
+#ifdef HAVE_DGA2
+// Code to change the video mode added by Michael Graffam
+// mgraffam@idsi.net
+ if (modelines==NULL)
+ modelines=XDGAQueryModes(vo_dga_dpy, XDefaultScreen(vo_dga_dpy),&modecount);
+
+ mX=modelines[0].imageWidth;
+ mY=modelines[0].imageHeight;
+ mVBI = modelines[0].verticalRefresh;
+
+
+ printf("vo_dga: Using DGA 2.0 mode changing support\n");
+ j=0;
+ // offbyone-error !!! i<=modecount is WRONG !!!
+ for (i=1; i<modecount; i++)
+ {
+ if( modelines[i].bitsPerPixel == vo_dga_planes)
+ {
+ printf("vo_dga: (%3d) Trying %4d x %4d @ %3d Hz @ %2d bpp ..",
+ i,
+ modelines[i].viewportWidth,
+ modelines[i].viewportHeight,
+ (unsigned int) modelines[i].verticalRefresh,
+ modelines[i].bitsPerPixel );
+
+ if ( check_mode(d_width, d_height,
+ modelines[i].viewportWidth,
+ modelines[i].viewportHeight,
+ (unsigned) modelines[i].verticalRefresh,
+ &mX, &mY, &mVBI ))
+ {
+ j = i;
+ printf(".ok!!\n");
+ }else{
+ printf(".no\n");
+ }
+ }
}
- X=(modelines[j].imageWidth-mX)/2;
- Y=(modelines[j].imageHeight-mY)/2;
printf("vo_dga: Selected video mode %4d x %4d @ %3d Hz for image size %3d x %3d.\n",
mX, mY, mVBI, width, height);
- XF86DGASetViewPort (vo_dga_dpy, XDefaultScreen(vo_dga_dpy), X,Y);
- dgadevice=XDGASetMode(vo_dga_dpy, XDefaultScreen(vo_dga_dpy), modelines[j].num);
+ vo_dga_vp_width =mX;
+ vo_dga_vp_height = mY;
+ vo_dga_width = modelines[j].bytesPerScanline / vo_dga_bpp;
+ dga_modenum = modelines[j].num;
+
+ XFree(modelines);
+ modelines = NULL;
+
+#else
+
+ printf("vo_dga: DGA 1.0 compatibility code: mode switching not supported (yet)!\n");
+
+ // assume these values are already known at this stage some day
+ // so that the following check for video <-> screen size can be done ...
+
+ vo_dga_vp_width = 1280;
+ vo_dga_vp_height = 1024;
+
+#endif
+
+
+ vo_dga_src_format = format;
+ vo_dga_src_width = width;
+ vo_dga_src_height = height;
+
+ if(vo_dga_src_width > vo_dga_vp_width ||
+ vo_dga_src_height > vo_dga_vp_height)
+ {
+ printf("vo_dga: Sorry, video larger than viewport is not yet supported!\n");
+ // ugly, do something nicer in the future ...
+ return 1;
+ }
+
+// now lets start the DGA thing
+
+#ifdef HAVE_DGA2
+
+ if (!XDGAOpenFramebuffer(vo_dga_dpy, XDefaultScreen(vo_dga_dpy))){
+ printf("vo_dga: Framebuffer mapping failed!!!\n");
+ XCloseDisplay(vo_dga_dpy);
+ return 1;
+ }
+ dgadevice=XDGASetMode(vo_dga_dpy, XDefaultScreen(vo_dga_dpy), dga_modenum);
XDGASync(vo_dga_dpy, XDefaultScreen(vo_dga_dpy));
- XFree(modelines);
+ vo_dga_base = dgadevice->data;
XFree(dgadevice);
- // end mode change code
+
+ XDGASetViewport (vo_dga_dpy, XDefaultScreen(vo_dga_dpy), 0, 0, XDGAFlipRetrace);
+
#else
- printf("vo_dga: DGA 1.0 compatibility code\n");
-#endif
XF86DGAGetViewPortSize(vo_dga_dpy,XDefaultScreen(vo_dga_dpy),
&vo_dga_vp_width,
@@ -315,38 +539,29 @@ static uint32_t init( uint32_t width, uint32_t height,
XF86DGAGetVideo (vo_dga_dpy, XDefaultScreen(vo_dga_dpy),
(char **)&vo_dga_base, &vo_dga_width, &bank, &ram);
-#ifndef HAVE_DGA2
+ XF86DGADirectVideo (vo_dga_dpy, XDefaultScreen(vo_dga_dpy),
+ XF86DGADirectGraphics | XF86DGADirectMouse |
+ XF86DGADirectKeyb);
+
XF86DGASetViewPort (vo_dga_dpy, XDefaultScreen(vo_dga_dpy), 0, 0);
+
#endif
// do some more checkings here ...
- if( format==IMGFMT_YV12 )
- yuv2rgb_init( vo_depthonscreen, MODE_RGB );
- vo_dga_src_format = format;
- vo_dga_src_width = width;
- vo_dga_src_height = height;
- vo_dga_bpp = (vo_depthonscreen+7) >> 3;
+ if( format==IMGFMT_YV12 )
+ yuv2rgb_init( vo_dga_planes == 16 ? 15 : vo_dga_planes , MODE_RGB );
printf("vo_dga: bytes/line: %d, screen res: %dx%d, depth: %d, base: %08x, bpp: %d\n",
vo_dga_width, vo_dga_vp_width,
- vo_dga_vp_height, vo_depthonscreen, vo_dga_base,
+ vo_dga_vp_height, vo_dga_planes, vo_dga_base,
vo_dga_bpp);
- printf("vo_dga: video res: %dx%d\n", vo_dga_src_width, vo_dga_src_height);
-
- if(vo_dga_src_width > vo_dga_vp_width ||
- vo_dga_src_height > vo_dga_vp_height){
- printf("vo_dga: Sorry, video larger than viewport is not yet supported!\n");
- // ugly, do something nicer in the future ...
- return 1;
- }
x_off = (vo_dga_vp_width - vo_dga_src_width)>>1;
y_off = (vo_dga_vp_height - vo_dga_src_height)>>1;
- vo_dga_bytes_per_line = vo_dga_src_width * vo_dga_bpp; // todo
- vo_dga_lines = vo_dga_src_height; // todo
-
+ vo_dga_bytes_per_line = vo_dga_src_width * vo_dga_bpp;
+ vo_dga_lines = vo_dga_src_height;
vo_dga_src_offset = 0;
vo_dga_vp_offset = (y_off * vo_dga_width + x_off ) * vo_dga_bpp;
@@ -356,10 +571,6 @@ static uint32_t init( uint32_t width, uint32_t height,
printf("vo_dga: vp_off=%d, vp_skip=%d, bpl=%d\n",
vo_dga_vp_offset, vo_dga_vp_skip, vo_dga_bytes_per_line);
-
- XF86DGADirectVideo (vo_dga_dpy, XDefaultScreen(vo_dga_dpy),
- XF86DGADirectGraphics | XF86DGADirectMouse |
- XF86DGADirectKeyb);
XGrabKeyboard (vo_dga_dpy, DefaultRootWindow(vo_dga_dpy), True,
GrabModeAsync,GrabModeAsync, CurrentTime);