changeset 5679:30f196ff3bec

This patch replaces vo_svga.c with an improved version that does not use vgagl library, supports direct rendering and page flipping, and is generally a lot faster. - by Matan Ziv-Av <matan@svgalib.org>
author arpi
date Thu, 18 Apr 2002 15:41:33 +0000
parents 8849904de1db
children 7bd2883ee0ec
files libvo/vo_svga.c
diffstat 1 files changed, 320 insertions(+), 232 deletions(-) [+]
line wrap: on
line diff
--- a/libvo/vo_svga.c	Thu Apr 18 15:32:30 2002 +0000
+++ b/libvo/vo_svga.c	Thu Apr 18 15:41:33 2002 +0000
@@ -1,16 +1,15 @@
 /*
-  Video driver for SVGAlib - alpha, slow
+  Video driver for SVGAlib 
   by Zoltan Mark Vician <se7en@sch.bme.hu>
   Code started: Mon Apr  1 23:25:47 2001
-  
-  Uses HW acceleration if your card is supported by SVGAlib.
+
+  Some changes by Matan Ziv-Av <matan@svgalib.org>
 */
 
 #include <stdio.h>
 #include <stdlib.h>
 
 #include <vga.h>
-#include <vgagl.h>
 
 #include <limits.h>
 
@@ -21,30 +20,32 @@
 #include "sub.h"
 #include "../postproc/rgb2rgb.h"
 
+#include "../mp_msg.h"
+//#include "../mp_image.h"
+
+extern int vo_directrendering;
 extern int vo_dbpp;
 extern int verbose;
 
-LIBVO_EXTERN(svga)
-
-static vo_info_t vo_info = {
-	"SVGAlib",
-        "svga",
-        "Zoltan Mark Vician <se7en@sch.bme.hu>",
-        ""
-};
-
-// SVGAlib definitions
+static uint32_t query_format(uint32_t format);
+static int checksupportedmodes();
+static void putbox(int x, int y, int w, int h, uint8_t *buf,int prog);
+static void fillbox(int x, int y, int w, int h, uint32_t c);
+static void draw_alpha(int x0, int y0, int w, int h, unsigned char *src,
+                       unsigned char *srca, int stride);
+static uint32_t get_image(mp_image_t *mpi);
 
-GraphicsContext *screen;
-GraphicsContext *virt;
+static uint8_t *yuvbuf = NULL, *bppbuf = NULL;
+static uint8_t *GRAPH_MEM;
 
-static uint8_t *scalebuf = NULL, *yuvbuf = NULL, *bppbuf = NULL;
+static int BYTESPERPIXEL, WIDTH, HEIGHT, LINEWIDTH;
+static int frame, maxframes, oldmethod=0;
 
+static uint32_t pformat;
 static uint32_t orig_w, orig_h, maxw, maxh; // Width, height
-static float scaling = 1.0;
-static uint32_t x_pos, y_pos; // Position
+static uint8_t buf0[8192];
+static uint8_t *buffer;
 
-// SVGAlib - list of detected modes
 typedef struct vga_modelist_s {
           uint16_t modenum;
           vga_modeinfo modeinfo;
@@ -65,60 +66,43 @@
 
 static uint8_t checked = 0;
 
-static uint32_t add_mode(uint16_t mode, vga_modeinfo minfo) {
-  vga_modelist_t *list;
+static uint32_t x_pos, y_pos;
+
+LIBVO_EXTERN(svga)
 
-  if (modelist == NULL) {
-    modelist = (vga_modelist_t *) malloc(sizeof(vga_modelist_t));
-    if (modelist == NULL) {
-      printf("vo_svga: add_mode() failed. Not enough memory for modelist.");
-      return(1); // error
-    }
-    modelist->modenum = mode;
-    modelist->modeinfo = minfo;
-    modelist->next = NULL;
+static vo_info_t vo_info = {
+	"SVGAlib",
+        "svga",
+        "Zoltan Mark Vician <se7en@sch.bme.hu>",
+        ""
+};
+
+static uint32_t preinit(const char *arg)
+{
+  int i;
+  
+  for(i=0;i<8192;i++) buf0[i]=0;
+  
+  if(vo_directrendering) {
+      maxframes=0;
   } else {
-      list = modelist;
-      while (list->next != NULL)
-        list = list->next;
-      list->next = (vga_modelist_t *) malloc(sizeof(vga_modelist_t));
-      if (list->next == NULL) {
-        printf("vo_svga: add_mode() failed. Not enough memory for modelist.");
-        return(1); // error
-      }
-      list = list->next;
-      list->modenum = mode;
-      list->modeinfo = minfo;
-      list->next = NULL;
-    }  
-  return (0);
+      maxframes=1;
+  }
+
+printf("vo_svga: preinit - maxframes=%i\n",maxframes);
+  
+  return 0;
 }
 
-static int checksupportedmodes() {
-  uint16_t i, max;
-  vga_modeinfo *minfo;
-  
-  checked = 1;
-  vga_init();
-  vga_disabledriverreport();
-  max = vga_lastmodenumber();
-  for (i = 1; i < max; i++)
-    if (vga_hasmode(i) > 0) {
-      minfo = vga_getmodeinfo(i);
-      switch (minfo->colors) {
-        case 32768: bpp_avail |= BPP_15; break;
-        case 65536: bpp_avail |= BPP_16; break;
-      }
-      switch (minfo->bytesperpixel) {
-        case 3: bpp_avail |= BPP_24; break;
-        case 4: bpp_avail |= BPP_32; break;
-      }
-      if (verbose >= 2)
-        printf("vo_svga: Mode found: %s\n",vga_getmodename(i));
-      if (add_mode(i, *minfo))
-        return(1);
-    }
-  return(0);
+static uint32_t control(uint32_t request, void *data, ...)
+{
+  switch (request) {
+  case VOCTRL_QUERY_FORMAT:
+    return query_format(*((uint32_t*)data));
+  case VOCTRL_GET_IMAGE:
+    return get_image(data);
+  }
+  return VO_NOTIMPL;
 }
 
 static uint32_t config(uint32_t width, uint32_t height, uint32_t d_width,
@@ -130,7 +114,7 @@
   uint8_t res_widescr, vid_widescr = (((req_w*1.0)/req_h) > (4.0/3)) ? 1 : 0;
   uint16_t buf_w = USHRT_MAX, buf_h = USHRT_MAX;
   vga_modelist_t *list = modelist;
-  
+
   if (!checked) {
     if (checksupportedmodes()) // Looking for available video modes 
       return(1);
@@ -235,15 +219,19 @@
     if ((list->modeinfo.width >= req_w) && (list->modeinfo.height >= req_h)) {
       if (verbose) {
         switch (list->modeinfo.colors) {
-          case 32768: printf("vo_svga: vid_mode: %d, %dx%d 15bpp\n",list->modenum,list->modeinfo.width,list->modeinfo.height);
+          case 32768: printf("vo_svga: vid_mode: %d, %dx%d 15bpp\n",
+                             list->modenum,list->modeinfo.width,list->modeinfo.height);
 	              break;
-          case 65536: printf("vo_svga: vid_mode: %d, %dx%d 16bpp\n",list->modenum,list->modeinfo.width,list->modeinfo.height);
+          case 65536: printf("vo_svga: vid_mode: %d, %dx%d 16bpp\n",
+                             list->modenum,list->modeinfo.width,list->modeinfo.height);
 	              break;
         }
         switch (list->modeinfo.bytesperpixel) {
-          case 3: printf("vo_svga: vid_mode: %d, %dx%d 24bpp\n",list->modenum,list->modeinfo.width,list->modeinfo.height);
+          case 3: printf("vo_svga: vid_mode: %d, %dx%d 24bpp\n",
+                         list->modenum,list->modeinfo.width,list->modeinfo.height);
 	          break;
-          case 4: printf("vo_svga: vid_mode: %d, %dx%d 32bpp\n",list->modenum,list->modeinfo.width,list->modeinfo.height);
+          case 4: printf("vo_svga: vid_mode: %d, %dx%d 32bpp\n",
+                         list->modenum,list->modeinfo.width,list->modeinfo.height);
 	          break;
         }
       }
@@ -284,8 +272,16 @@
     }
     list = list->next;
   }
+  
+  if((vo_subdevice) && (strlen(vo_subdevice)>2)) {
+     if(!strncmp(vo_subdevice,"old",3)) {
+        oldmethod=1;
+        vo_subdevice+=3;
+        if( *vo_subdevice == ',' ) vo_subdevice++;
+     }
+  }
 
-  if(vo_subdevice) {
+  if((vo_subdevice)  && *vo_subdevice) {
       int vm;
       vm=vga_getmodenumber(vo_subdevice);
       list=modelist;
@@ -326,24 +322,26 @@
     uninit();
     return(1); // error
   } 
+
+  WIDTH=vga_getxdim();
+  HEIGHT=vga_getydim();
+  BYTESPERPIXEL=(bpp+1)>>3;
+  LINEWIDTH=WIDTH*BYTESPERPIXEL;
   vga_setlinearaddressing();
-  if (gl_setcontextvga(vid_mode)) {
-    printf("vo_svga: gl_setcontextvga(%d) failed.\n",vid_mode);
-    uninit();
-    return(1); // error
+  if(oldmethod) {
+     buffer=malloc(HEIGHT*LINEWIDTH);
+     maxframes=0;
   }
-  screen = gl_allocatecontext();
-  gl_getcontext(screen);
-  if (gl_setcontextvgavirtual(vid_mode)) {
-    printf("vo_svga: gl_setcontextvgavirtual(%d) failed.\n",vid_mode);
-    uninit();
-    return(1); // error
-  }
-  virt = gl_allocatecontext();
-  gl_getcontext(virt);
-  gl_setcontext(virt);
-  gl_clearscreen(0);
+  vga_claimvideomemory((maxframes+1)*HEIGHT*LINEWIDTH);
+  GRAPH_MEM=vga_getgraphmem();
+  frame=0;
+  fillbox(0,0,WIDTH,HEIGHT*(maxframes+1),0);
   
+  orig_w = width;
+  orig_h = height;
+  maxw = orig_w;
+  maxh = orig_h;
+
   if (bpp_conv) {
     bppbuf = malloc(maxw * maxh * BYTESPERPIXEL);
     if (bppbuf == NULL) {
@@ -352,35 +350,7 @@
       return (1);
     }  
   }
-
-  orig_w = width;
-  orig_h = height;
-  if ((fullscreen & 0x04) && (WIDTH != orig_w) && (HEIGHT != orig_h)) {
-    if (!vid_widescr || !res_widescr) {
-      maxh = HEIGHT;
-      scaling = maxh / (orig_h * 1.0);
-      maxw = (uint32_t) (orig_w * scaling);
-      scalebuf = malloc(maxw * maxh * BYTESPERPIXEL);
-      if (scalebuf == NULL) {
-        printf("vo_svga: scalebuf -> Not enough memory for buffering!\n");
-	uninit();
-	return (1);
-      }
-    } else {
-        maxw = WIDTH;
-        scaling = maxw / (orig_w * 1.0);
-        maxh = (uint32_t) (orig_h * scaling);
-        scalebuf = malloc(maxw * maxh * BYTESPERPIXEL);
-        if (scalebuf == NULL) {
-          printf("vo_svga: scalebuf -> Not enough memory for buffering!\n");
-	  uninit();
-	  return (1);
-        }
-      }
-  } else {
-      maxw = orig_w;
-      maxh = orig_h;
-    }
+  
   x_pos = (WIDTH - maxw) / 2;
   y_pos = (HEIGHT - maxh) / 2;
   
@@ -398,9 +368,177 @@
   if (maxw != orig_w || maxh != orig_h) printf("Video scaled to: %dx%d\n",maxw,maxh);
   else printf("No video scaling\n");
 
+  vga_setdisplaystart(0);
+
+  return (0);
+}
+
+static const vo_info_t* get_info(void) {
+  return (&vo_info);
+}
+
+static uint32_t draw_frame(uint8_t *src[]) {
+  if (pformat == IMGFMT_YV12) {
+    yuv2rgb(yuvbuf, src[0], src[1], src[2], orig_w, orig_h, orig_w * BYTESPERPIXEL, orig_w, orig_w / 2);
+    src[0] = yuvbuf;
+  }
+  if (bpp_conv) {
+    switch(bpp) {
+      case 32: {
+        uint8_t *source = src[0];
+        uint8_t *dest = bppbuf;
+	register uint32_t i = 0;
+    
+	while (i < (maxw * maxh * 4)) {
+	  dest[i] = source[i];
+	  dest[i+1] = source[i+1];
+	  dest[i+2] = source[i+2];
+	  dest[i+3] = 0;
+	  i += 4;
+	}
+      } break;
+      case 16: {
+        rgb15to16(src[0],bppbuf,maxw * maxh * 2);
+      } break;
+    }
+    src[0] = bppbuf;
+  }
+  putbox(x_pos, y_pos, maxw, maxh, src[0], 1);
+  
+  return (0);
+}
+
+static uint32_t draw_slice(uint8_t *image[], int stride[], 
+                           int w, int h, int x, int y) {
+  uint8_t *src = yuvbuf;
+  uint32_t sw, sh;
+  
+  yuv2rgb(yuvbuf, image[0], image[1], image[2], w, h, orig_w * BYTESPERPIXEL, stride[0], stride[1]);
+  putbox(x + x_pos, y + y_pos, w, h, src, 1);
+
   return (0);
 }
 
+static void draw_osd(void)
+{
+  if(oldmethod) {
+      if (y_pos) {
+        fillbox(0, 0, WIDTH, y_pos, 0);
+        fillbox(0, HEIGHT - y_pos, WIDTH, y_pos, 0);
+        if (x_pos) {
+           int hmy=HEIGHT - (y_pos<<1); 
+           fillbox(0, y_pos, x_pos, hmy, 0);
+           fillbox(WIDTH - x_pos, y_pos, x_pos, hmy, 0);
+        }
+      } else if (x_pos) {
+        fillbox(0, y_pos, x_pos, HEIGHT, 0);
+        fillbox(WIDTH - x_pos, y_pos, x_pos, HEIGHT, 0);
+      }
+      vo_draw_text(WIDTH, HEIGHT, draw_alpha);
+  } else 
+  vo_draw_text(maxw, maxh, draw_alpha);
+}
+
+static void flip_page(void) {
+    if(oldmethod)  {
+       int i;
+       uint8_t *b;
+       b=buffer;
+       for(i=0;i<HEIGHT;i++){ 
+          vga_drawscansegment(b,0,i,LINEWIDTH);
+          b+=LINEWIDTH;
+       }
+    } else {
+        if(maxframes) {
+            vga_setdisplaystart(frame*HEIGHT*LINEWIDTH);
+            frame++;
+            if(frame>maxframes)frame=0;
+        }
+    }
+}
+
+static void check_events(void) {
+}
+
+static void uninit(void) {
+  vga_modelist_t *list = modelist;
+
+  vga_setmode(TEXT);
+
+  if (bppbuf != NULL)
+    free(bppbuf);
+  if (yuvbuf != NULL)
+    free(yuvbuf);
+  while (modelist != NULL) {
+       list=modelist;
+       modelist=modelist->next;
+       free(list);
+  }
+  checked = 0;
+}
+
+
+/* --------------------------------------------------------------------- */
+
+static uint32_t add_mode(uint16_t mode, vga_modeinfo minfo) {
+  vga_modelist_t *list;
+
+  if (modelist == NULL) {
+    modelist = (vga_modelist_t *) malloc(sizeof(vga_modelist_t));
+    if (modelist == NULL) {
+      printf("vo_svga: add_mode() failed. Not enough memory for modelist.");
+      return(1); // error
+    }
+    modelist->modenum = mode;
+    modelist->modeinfo = minfo;
+    modelist->next = NULL;
+  } else {
+      list = modelist;
+      while (list->next != NULL)
+        list = list->next;
+      list->next = (vga_modelist_t *) malloc(sizeof(vga_modelist_t));
+      if (list->next == NULL) {
+        printf("vo_svga: add_mode() failed. Not enough memory for modelist.");
+        return(1); // error
+      }
+      list = list->next;
+      list->modenum = mode;
+      list->modeinfo = minfo;
+      list->next = NULL;
+    }  
+  return (0);
+}
+
+static int checksupportedmodes() {
+  uint16_t i, max;
+  vga_modeinfo *minfo;
+  
+  checked = 1;
+  vga_init();
+  vga_disabledriverreport();
+  max = vga_lastmodenumber();
+  if (verbose >= 2)
+    printf("vo_svga: Max mode : %i\n",max);
+  for (i = 1; i <= max; i++)
+    if (vga_hasmode(i) > 0) {
+      minfo = vga_getmodeinfo(i);
+      switch (minfo->colors) {
+        case 32768: bpp_avail |= BPP_15; break;
+        case 65536: bpp_avail |= BPP_16; break;
+      }
+      switch (minfo->bytesperpixel) {
+        case 3: bpp_avail |= BPP_24; break;
+        case 4: bpp_avail |= BPP_32; break;
+      }
+      if (verbose >= 2)
+        printf("vo_svga: Mode found: %s\n",vga_getmodename(i));
+      if (add_mode(i, *minfo))
+        return(1);
+    }
+  return(0);
+}
+
+
 static uint32_t query_format(uint32_t format) {
   uint32_t res = 0;
 
@@ -452,134 +590,84 @@
   return (0);
 }
 
-static const vo_info_t* get_info(void) {
-  return (&vo_info);
+static void putbox(int x, int y, int w, int h, uint8_t *buf, int prog) {
+    int base, add, wid;
+    if(oldmethod) {
+        wid=w*BYTESPERPIXEL;
+        add=wid*prog;
+        while( (h--) > 0 ) {
+            memcpy(buffer+x*BYTESPERPIXEL+(y++)*LINEWIDTH, buf, wid);
+            buf+=add;
+        }    
+    } else {
+        wid=w*BYTESPERPIXEL;
+        add=wid*prog;
+        base=frame*HEIGHT;
+        while( (h--) > 0 ) {
+            vga_drawscansegment(buf, x, (y++)+base, wid);
+            buf+=add;
+        }
+    }
+}
+
+static void fillbox(int x, int y, int w, int h, uint32_t c) {
+    putbox(x,y,w,h,buf0,0);
 }
 
 static void draw_alpha(int x0, int y0, int w, int h, unsigned char *src,
                        unsigned char *srca, int stride) {
+  int base;
+  
+  if(oldmethod) {
+     base=buffer;
+  } else 
+     base=((frame*HEIGHT+y_pos)*WIDTH+x_pos)*BYTESPERPIXEL + GRAPH_MEM ;
+     
   switch (bpp) {
     case 32: 
-      vo_draw_alpha_rgb32(w, h, src, srca, stride, virt->vbuf+4*(y0*WIDTH+x0), 4*WIDTH);
+      vo_draw_alpha_rgb32(w, h, src, srca, stride, base+4*(y0*WIDTH+x0), 4*WIDTH);
       break;
     case 24: 
-      vo_draw_alpha_rgb24(w, h, src, srca, stride, virt->vbuf+3*(y0*WIDTH+x0), 3*WIDTH);
+      vo_draw_alpha_rgb24(w, h, src, srca, stride, base+3*(y0*WIDTH+x0), 3*WIDTH);
       break;
     case 16:
-      vo_draw_alpha_rgb16(w, h, src, srca, stride, virt->vbuf+2*(y0*WIDTH+x0), 2*WIDTH);
+      vo_draw_alpha_rgb16(w, h, src, srca, stride, base+2*(y0*WIDTH+x0), 2*WIDTH);
       break;
     case 15:
-      vo_draw_alpha_rgb15(w, h, src, srca, stride, virt->vbuf+2*(y0*WIDTH+x0), 2*WIDTH);
+      vo_draw_alpha_rgb15(w, h, src, srca, stride, base+2*(y0*WIDTH+x0), 2*WIDTH);
       break;
   }
-}		
-
-static uint32_t draw_frame(uint8_t *src[]) {
-  if (pformat == IMGFMT_YV12) {
-    yuv2rgb(yuvbuf, src[0], src[1], src[2], orig_w, orig_h, orig_w * BYTESPERPIXEL, orig_w, orig_w / 2);
-    src[0] = yuvbuf;
-  }
-  if (scalebuf != NULL) {
-    gl_scalebox(orig_w, orig_h, src[0], maxw, maxh, scalebuf);
-    src[0] = scalebuf;
-  }
-  if (bpp_conv) {
-    switch(bpp) {
-      case 32: {
-        uint8_t *source = src[0];
-        uint8_t *dest = bppbuf;
-	register uint32_t i = 0;
-    
-	while (i < (maxw * maxh * 4)) {
-	  dest[i] = source[i];
-	  dest[i+1] = source[i+1];
-	  dest[i+2] = source[i+2];
-	  dest[i+3] = 0;
-	  i += 4;
-	}
-      } break;
-      case 16: {
-        rgb15to16(src[0],bppbuf,maxw * maxh * 2);
-      } break;
-    }
-    src[0] = bppbuf;
-  }
-  gl_putbox(x_pos, y_pos, maxw, maxh, src[0]);
-  
-  return (0);
-}
-
-static uint32_t draw_slice(uint8_t *image[], int stride[], 
-                           int w, int h, int x, int y) {
-  uint8_t *src = yuvbuf;
-  uint32_t sw, sh;
-  
-  yuv2rgb(yuvbuf, image[0], image[1], image[2], w, h, orig_w * BYTESPERPIXEL, stride[0], stride[1]);
-  sw = (uint32_t) (w * scaling);
-  sh = (uint32_t) (h * scaling);
-  if (scalebuf != NULL) {
-    gl_scalebox(w, h, yuvbuf, sw, sh, scalebuf);
-    src = scalebuf;
-  }
-  gl_putbox((int)(x * scaling) + x_pos, (int)(y * scaling) + y_pos, sw, sh, src);
-
-  return (0);
-}
-
-static void draw_osd(void)
-{
-  if (y_pos) {
-    gl_fillbox(0, 0, WIDTH, y_pos, 0);
-    gl_fillbox(0, HEIGHT - y_pos, WIDTH, y_pos, 0);
-    if (x_pos) {
-       int hmy=HEIGHT - (y_pos<<1); 
-       gl_fillbox(0, y_pos, x_pos, hmy, 0);
-       gl_fillbox(WIDTH - x_pos, y_pos, x_pos, hmy, 0);
-    }
-  } else if (x_pos) {
-    gl_fillbox(0, y_pos, x_pos, HEIGHT, 0);
-    gl_fillbox(WIDTH - x_pos, y_pos, x_pos, HEIGHT, 0);
-  }
-
-  vo_draw_text(WIDTH, HEIGHT, draw_alpha);
-}
-
-static void flip_page(void) {
-  gl_copyscreen(screen);
-}
-
-static void check_events(void) {
-}
-
-static void uninit(void) {
-  vga_modelist_t *list = modelist;
-
-  gl_freecontext(screen);
-  gl_freecontext(virt);
-  vga_setmode(TEXT);
-  if (bppbuf != NULL)
-    free(bppbuf);
-  if (scalebuf != NULL)
-    free(scalebuf);
-  if (yuvbuf != NULL)
-    free(yuvbuf);
-  while (modelist != NULL) {
-       list=modelist;
-       modelist=modelist->next;
-       free(list);
-  }
 }
 
-static uint32_t preinit(const char *arg)
+static uint32_t get_image(mp_image_t *mpi)
 {
-  return 0;
+    if (/* zoomFlag || */
+	!IMGFMT_IS_BGR(mpi->imgfmt) ||
+	((mpi->type != MP_IMGTYPE_STATIC) && (mpi->type != MP_IMGTYPE_TEMP)) ||
+	(mpi->flags & MP_IMGFLAG_PLANAR) ||
+	(mpi->flags & MP_IMGFLAG_YUV) /*
+	(mpi->width != image_width) ||
+	(mpi->height != image_height) */
+    )
+	return(VO_FALSE);
+
+/*
+    if (Flip_Flag)
+    {
+	mpi->stride[0] = -image_width*((bpp+7)/8);
+	mpi->planes[0] = ImageData - mpi->stride[0]*(image_height-1);
+    }
+    else
+*/
+    {
+	mpi->stride[0] = LINEWIDTH;
+        if(oldmethod) {
+	       mpi->planes[0] = buffer;
+        } else
+	mpi->planes[0] = GRAPH_MEM;
+    }
+    mpi->flags |= MP_IMGFLAG_DIRECT;
+    
+    return(VO_TRUE);
 }
 
-static uint32_t control(uint32_t request, void *data, ...)
-{
-  switch (request) {
-  case VOCTRL_QUERY_FORMAT:
-    return query_format(*((uint32_t*)data));
-  }
-  return VO_NOTIMPL;
-}