changeset 261:3b7e4bf7c7ed

- 32/16 bit mode swtiching with DGA2.0 - now use only DGA2.0 API when DGA2.0 is available
author acki2
date Fri, 30 Mar 2001 22:09:38 +0000
parents 1742ea658d0b
children 2c7c77d793df
files libvo/vo_dga.c
diffstat 1 files changed, 304 insertions(+), 93 deletions(-) [+]
line wrap: on
line diff
--- a/libvo/vo_dga.c	Fri Mar 30 17:16:56 2001 +0000
+++ b/libvo/vo_dga.c	Fri Mar 30 22:09:38 2001 +0000
@@ -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_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 uint32_t query_format( uint32_t format )
 {
- printf("vo_dga: query_format\n");
+
+#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){
 
- if( !vo_init() ) return 0; // Can't open X11
- printf("Format: %lx\n", format);
+#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 @@
 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 @@
         }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; 
   }
-  X=(modelines[j].imageWidth-mX)/2;
-  Y=(modelines[j].imageHeight-mY)/2;
+ 
+  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");
+       }
+     }
+  }
   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 @@
   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;
+    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 @@
   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);