summaryrefslogtreecommitdiffstats
path: root/libvo
diff options
context:
space:
mode:
authoriive <iive@b3059339-0415-0410-9bf9-f77b7e298cf2>2003-03-20 01:45:40 +0000
committeriive <iive@b3059339-0415-0410-9bf9-f77b7e298cf2>2003-03-20 01:45:40 +0000
commitaf885100d37183720c8752a565a8164f0a76b4e1 (patch)
treef2b445cf30efbf309de2f34f165133e53fa97402 /libvo
parent9a1bfa7ec1ef32e1ab316024e93fc6f8f059ce87 (diff)
downloadmpv-af885100d37183720c8752a565a8164f0a76b4e1.tar.bz2
mpv-af885100d37183720c8752a565a8164f0a76b4e1.tar.xz
new svga driver - support double buffering, fast_memcpy, direct render and HW acceleration
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@9622 b3059339-0415-0410-9bf9-f77b7e298cf2
Diffstat (limited to 'libvo')
-rw-r--r--libvo/vo_svga.c1286
1 files changed, 564 insertions, 722 deletions
diff --git a/libvo/vo_svga.c b/libvo/vo_svga.c
index ae25882718..2c1d0fc57a 100644
--- a/libvo/vo_svga.c
+++ b/libvo/vo_svga.c
@@ -1,9 +1,29 @@
/*
+
Video driver for SVGAlib
by Zoltan Mark Vician <se7en@sch.bme.hu>
Code started: Mon Apr 1 23:25:47 2001
-
Some changes by Matan Ziv-Av <matan@svgalib.org>
+ Compleat rewrite by Ivan Kalvachev 19 Mar 2003:
+
+Wrangings:
+ - 1bpp doesn't work right for me with '-double' and svgalib 1.4.3,
+ but works OK with svgalib 1.9.17
+ - The HW acceleration is not tested - svgalibs supports few chipsets,
+ and i don't have any of them. If it works for you then let me know.
+ I will remove this warning after confirm its status.
+ - retrace sync works only in doublebuffer mode.
+ - the retrace sync may slow down decoding a lot - mplayer is blocked while
+ waiting for retrace
+ - denoice3d fails to find common colorspace, vf_scale doesn't help - I work on it.
+
+TODO:
+ - OSD without flicker (w/h & w/o double buffer)
+ - let choose_best_mode take aspect into account
+ - set palette from mpi->palette or mpi->plane[1]
+ - let OSD draw in black bars - need some OSD changes
+ - Make nicer CONFIG parsing
+ - change video mode logical width to match img->stride[0] - for HW only
*/
#include <stdio.h>
@@ -17,74 +37,67 @@
#include "config.h"
#include "video_out.h"
#include "video_out_internal.h"
-
+#include "fastmemcpy.h"
+#include "osdep/getch2.h"
#ifdef CONFIG_VIDIX
#include "vosub_vidix.h"
#endif
#include "sub.h"
-#include "../postproc/rgb2rgb.h"
#include "../mp_msg.h"
//#include "../mp_image.h"
+#include <assert.h>
+
+//silence warnings, probably it have to go in some global header
+#define UNUSED(x) ((void)(x))
+
+extern int vo_doublebuffering;
extern int vo_directrendering;
extern int vo_dbpp;
extern int verbose;
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);
-static uint8_t *yuvbuf = NULL, *bppbuf = NULL;
-static uint8_t *GRAPH_MEM;
-
-static int BYTESPERPIXEL, WIDTH, HEIGHT, LINEWIDTH;
-static int frame, maxframes, oldmethod=0;
-static int directrender;
+#define MAXPAGES 16
-static int force_vm=0;
-static int squarepix=0;
+#define CAP_ACCEL_CLEAR 8
+#define CAP_ACCEL_PUTIMAGE 4
+#define CAP_ACCEL_BACKGR 2
+#define CAP_LINEAR 1
-static uint32_t pformat;
-static uint32_t orig_w, orig_h, maxw, maxh; // Width, height
-static uint8_t buf0[8192];
-static uint8_t *buffer;
+static uint8_t zerobuf[8192];//used when clear screen with vga_draw
-typedef struct vga_modelist_s {
- uint16_t modenum;
- vga_modeinfo modeinfo;
- struct vga_modelist_s *next;
- } vga_modelist_t;
-
-vga_modelist_t *modelist = NULL;
-
-static uint8_t bpp;
-static uint8_t bpp_conv = 0;
-static uint32_t pformat;
-
-#define BPP_15 1
-#define BPP_16 2
-#define BPP_24 4
-#define BPP_32 8
-#define BPP_8 16
-#define BPP_4 32
-#define BPP_1 64
-static uint8_t bpp_avail = 0;
+static int squarepix;
+static int force_vm=0;
+static int force_native=0;
+static int sync_flip=0;
+static int cpage=0, max_pages;
-static uint8_t checked = 0;
+static vga_modeinfo * modeinfo;
+static int mode_stride; //keep it in case of vga_setlogicalwidth
+static int stride_granularity; //not yet used
+static int mode_bpp;
+static int mode_capabilities;
+static int image_width,image_height; // used by OSD
static uint32_t x_pos, y_pos;
+static struct {
+ int yoffset;//y position of the page
+ int doffset;//display start of the page
+ void * vbase;//memory start address of the page
+}PageStore[MAXPAGES];
+
static vo_info_t info = {
- "SVGAlib",
- "svga",
- "Zoltan Mark Vician <se7en@sch.bme.hu>",
- ""
+ "SVGAlib",
+ "svga",
+ "Ivan Kalvachev <iive@sf.net>",
+ ""
};
#ifdef CONFIG_VIDIX
@@ -93,782 +106,611 @@ static char vidix_name[32] = "";
LIBVO_EXTERN(svga)
+/*
+probably this should be in separate pages.c file so
+all vo_drivers can use it, do it if you like it.
+TODO
+direct render with IP buffering support - for vo_tdfx_vid
+*/
+
+#define PAGES_MAX MAXPAGES
+#define Page_Empty 0
+#define Page_Durty 1
+
+static int page_locks[PAGES_MAX];
+static int pagecurrent;
+static int pagetoshow;
+static int pagesmax;
+
+static void page_init(int max){
+int i;
+ for(i=0;i<max;i++){
+ page_locks[i]=0;
+ }
+ pagetoshow=pagecurrent=0;
+ pagesmax=max;
+}
+//internal use function
+//return number of 1'st free page or -1 if no free one
+static int page_find_free(){
+int i;
+ for(i=0;i<pagesmax;i++)
+ if(page_locks[i]==Page_Empty) return i;
+ return -1;
+}
+
+//return the number of page we may draw directly of -1 if no such
+static int page_get_image(){
+int pg;
+ pg=page_find_free();
+ if(pg>=0) page_locks[pg]=Page_Durty;
+ return pg;
+}
+
+//return the number of page we should draw into.
+static int page_draw_image(){
+int pg;
+ pg=page_find_free();
+ if(pg<0) pg=pagecurrent;
+ page_locks[pg]=Page_Durty;
+ pagetoshow=pg;
+ return pg;
+}
+
+static void page_draw_gotten_image(int pg){
+assert((pg>=0)&&(pg<PAGES_MAX));
+ pagetoshow=pg;
+}
+
+//return the number of the page to show
+static int page_flip_page(){
+ page_locks[pagecurrent]=Page_Empty;
+ pagecurrent=pagetoshow;
+assert(pagecurrent>=0);
+ //movequeue;
+ page_locks[pagecurrent]=Page_Durty;
+ return pagecurrent;
+}
+//------------ END OF PAGE CODE -------------
+
static uint32_t preinit(const char *arg)
{
- int i;
-
- for(i=0;i<8192;i++) buf0[i]=0;
-
- if(vo_directrendering) {
- maxframes=0;
- } else {
- maxframes=1;
- }
+int i;
+char s[64];
+ getch2_disable();
+ memset(zerobuf,0,sizeof(zerobuf));
+ force_vm=force_native=squarepix=0;
+
if(arg)while(*arg) {
- if(!strncmp(arg,"old",3)) {
- oldmethod=1;
- arg+=3;
- if( *arg == ':' ) arg++;
- }
-
#ifdef CONFIG_VIDIX
- if(memcmp(arg,"vidix",5)==0) {
- int i;
- i=6;
- while(arg[i] && arg[i]!=':') i++;
- strncpy(vidix_name, arg+6, i-6);
- vidix_name[i-5]=0;
- if(arg[i]==':')i++;
- arg+=i;
- vidix_preinit(vidix_name, &video_out_svga);
- }
+ if(memcmp(arg,"vidix",5)==0) {
+ i=6;
+ while(arg[i] && arg[i]!=':') i++;
+ strncpy(vidix_name, arg+6, i-6);
+ vidix_name[i-5]=0;
+ if(arg[i]==':')i++;
+ arg+=i;
+ vidix_preinit(vidix_name, &video_out_svga);
+ }
#endif
- if(!strncmp(arg,"sq",2)) {
- squarepix=1;
- arg+=2;
- if( *arg == ':' ) arg++;
- }
+ if(!strncmp(arg,"sq",2)) {
+ squarepix=1;
+ arg+=2;
+ if( *arg == ':' ) arg++;
+ }
+
+ if(!strncmp(arg,"native",6)) {
+ force_native=1;
+ arg+=6;
+ if( *arg == ':' ) arg++;
+ }
- if(*arg) {
- int i;
- char s[64];
-printf("arg is %s\n",arg);
- i=0;
- while(arg[i] && arg[i]!=':')i++;
- strncpy(s, arg, i);
- s[i]=0;
- arg+=i;
- if(*arg==':')arg++;
-printf("i=%i new arg is %s\n",i, arg);
- i=vga_getmodenumber(s);
- if(i>0) {
- force_vm = i;
- if(verbose)printf("vo_svga: Forcing mode %i\n",force_vm);
- }
- }
+ if(!strncmp(arg,"retrace",7)) {
+ sync_flip=1;
+ arg+=7;
+ if( *arg == ':' ) arg++;
+ }
+
+ if(*arg) {
+ i=0;
+ while(arg[i] && arg[i]!=':')i++;
+ strncpy(s, arg, i);
+ s[i]=0;
+ arg+=i;
+ if(*arg==':')arg++;
+ i=vga_getmodenumber(s);
+ if(i>0) {
+ force_vm = i;
+ if(verbose)
+ printf("vo_svga: Forcing mode %i\n",force_vm);
+ }
+ }
}
+
+ vga_init();
+ return 0;
+}
- if (!checked) {
- if (checksupportedmodes()) // Looking for available video modes
- return(1);
+static void svga_clear_box(int x,int y,int w,int h){
+uint8_t * rgbplane;
+int i;
+
+ if (mode_capabilities&CAP_ACCEL_CLEAR){
+ if(verbose > 2)
+ printf("vo_svga: clearing box %d,%d - %d,%d with HW acceleration\n",
+ x,y,w,h);
+ if(mode_capabilities&CAP_ACCEL_BACKGR)
+ vga_accel(ACCEL_SYNC);
+ vga_accel(ACCEL_SETFGCOLOR,0);//black
+ vga_accel(ACCEL_FILLBOX,x,y,w,h);
+ return;
}
+ if (mode_capabilities & CAP_LINEAR){
+ if(verbose > 2)
+ printf("vo_svga: clearing box %d,%d - %d,%d with memset\n",x,y,w,h);
+ rgbplane=PageStore[0].vbase + (y*mode_stride) + (x*modeinfo->bytesperpixel);
+ for(i=0;i<h;i++){
+//i'm afraid that memcpy is better optimized than memset;)
+ memcpy(rgbplane,zerobuf,w*modeinfo->bytesperpixel);
+// memset(rgbplane,0,w*modeinfo->bytesperpixel);
+ rgbplane+=mode_stride;
+ }
+ return;
+ }
+ //native
+ if(verbose > 2)
+ printf("vo_svga: clearing box %d,%d - %d,%d with native draw \n",x,y,w,h);
+ if(modeinfo->bytesperpixel!=0) w*=modeinfo->bytesperpixel;
+ for(i=0;i<h;i++){
+ vga_drawscansegment(zerobuf,x,y+i,w);
+ }
+};
+
+static uint32_t svga_draw_image(mp_image_t *mpi){
+int i,x,y,w,h;
+int stride;
+uint8_t *rgbplane, *base;
+int bytesperline;
+
+ if(mpi->flags & MP_IMGFLAG_DIRECT){
+ if(verbose > 2)
+ printf("vo_svga: drawing direct rendered surface\n");
+ cpage=(uint32_t)mpi->priv;
+ page_draw_gotten_image(cpage);
+ return VO_TRUE; //it's already done
+ }
+// if (mpi->flags&MP_IMGFLAGS_DRAWBACK)
+// return VO_TRUE;//direct render method 2
+ cpage=page_draw_image();
+// these variables are used in loops
+ x = mpi->x;
+ y = mpi->y;
+ w = mpi->w;
+ h = mpi->h;
+ stride = mpi->stride[0];
+ rgbplane = mpi->planes[0] + y*stride + (x*mpi->bpp)/8;
+ x+=x_pos;//center
+ y+=y_pos;
+
+ if(mpi->bpp >= 8){//for modes<8 use only native
+ if( (mode_capabilities&CAP_ACCEL_PUTIMAGE) && (x==0) && (w==mpi->width) &&
+ (stride == mode_stride) ){ //only monolite image can be accelerated
+ w=(stride*8)/mpi->bpp;//we transfer pixels in the stride so the source
+//ACCELERATE
+ if(verbose>2)
+ printf("vo_svga: using HW PutImage (x=%d,y=%d,w=%d,h=%d)\n",x,y,w,h);
+ if(mode_capabilities & CAP_ACCEL_BACKGR)
+ vga_accel(ACCEL_SYNC);
+
+ vga_accel(ACCEL_PUTIMAGE,x,y+PageStore[cpage].yoffset,w,h,rgbplane);
+ return VO_TRUE;
+ }
+
+ if( mode_capabilities&CAP_LINEAR){
+//DIRECT
+ if(verbose>2)
+ printf("vo_svga: using Direct memcpy (x=%d,y=%d,w=%d,h=%d)\n",x,y,w,h);
+ bytesperline=(w*mpi->bpp)/8;
+ base=PageStore[cpage].vbase + (y*mode_stride) + (x*mpi->bpp)/8;
+
+ for(i=0;i<h;i++){
+ mem2agpcpy(base,rgbplane,bytesperline);
+ base+=mode_stride;
+ rgbplane+=stride;
+ }
+ return VO_TRUE;
+ }
+ }//(modebpp>=8
+
+
+//NATIVE
+ {
+ int length;
+ length=(w*mpi->bpp)/8;
+ //one byte per pixel! svgalib innovation
+ if(mpi->imgfmt==IMGFMT_RG4B || mpi->imgfmt==IMGFMT_BG4B) length=w;
+
+ if(verbose>2)
+ printf("vo_svga: using Native vga_draw(x=%d,y=%d,w=%d,h=%d)\n",x,y,w,h);
+ y+=PageStore[cpage].yoffset;//y position of the page beggining
+ for(i=0;i<h;i++){
+ vga_drawscansegment(rgbplane,x,y+i,length);
+ rgbplane+=stride;
+ }
+ }
+ return VO_TRUE;
+}
+int bpp_from_vminfo(vga_modeinfo *vminfo){
+ switch(vminfo->colors){
+ case 2: return 1;
+ case 16: return 4;
+ case 256: return 8;
+ case 32768: return 15;
+ case 65536: return 16;
+ case 1<<24: return 8*vminfo->bytesperpixel;
+ }
return 0;
}
+int find_best_svga_mode(int req_w,int req_h, int req_bpp){
+ int badness,prev_badness;
+ int bestmode,lastmode;
+ int i;
+ vga_modeinfo *vminfo;
+//int best aspect mode // best linear mode // best normal mode (no modeX)
+
+ prev_badness = req_w * req_h;
+ bestmode = 0; //0 is the TEXT mode
+ lastmode = vga_lastmodenumber();
+ for(i=1;i<lastmode;i++){
+ vminfo = vga_getmodeinfo(i);
+ if( vminfo == NULL ) continue;
+ if( vga_hasmode(i) == 0 ) continue;
+ if( req_bpp != bpp_from_vminfo(vminfo) )continue;
+ if( (vminfo->width < req_w) || (vminfo->height < req_h) ) continue;
+ badness=(vminfo->width * vminfo->height) - (req_h * req_w);
+ //put here aspect calculations
+ if(squarepix)
+ if( vminfo->width*3 != vminfo->height*4 ) continue;
+
+ if( prev_badness >= badness ){//modeX etc...
+ prev_badness=badness;
+ bestmode=i;
+ if(verbose>3)
+ printf("vo_svga: found good mode %d with badness %d\n",i,badness);
+ }
+ }
+ return bestmode;
+}
+
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);
+ case VOCTRL_QUERY_FORMAT:
+ return query_format(*((uint32_t*)data));
+ case VOCTRL_DRAW_IMAGE:
+ return svga_draw_image( (mp_image_t *)data);
+ case VOCTRL_GET_IMAGE:
+ return get_image(data);
}
return VO_NOTIMPL;
}
+//
+// This function is called to init the video driver for specific mode
+//
static uint32_t config(uint32_t width, uint32_t height, uint32_t d_width,
- uint32_t d_height, uint32_t flags, char *title,
- uint32_t format) {
- uint32_t req_w = (d_width > 0 ? d_width : width);
- uint32_t req_h = (d_height > 0 ? d_height : height);
+ uint32_t d_height, uint32_t flags, char *title,
+ uint32_t format) {
+ int32_t req_w = width;// (d_width > 0 ? d_width : width);
+ int32_t req_h = height;// (d_height > 0 ? d_height : height);
uint16_t vid_mode = 0;
- 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(verbose)
- printf("vo_svga: config(%i, %i, %i, %i, %08x, %s, %08x)\n", width, height,
- d_width, d_height, flags, title, format);
-
- bpp_avail = 0;
- while (list != NULL) {
- if ((list->modeinfo.width >= req_w) && (list->modeinfo.height >= req_h)) {
- switch (list->modeinfo.colors) {
- case 32768: bpp_avail |= BPP_15; break;
- case 65536: bpp_avail |= BPP_16; break;
- case 256 : bpp_avail |= BPP_8; break;
- case 16 : bpp_avail |= BPP_4; break;
- case 2 : bpp_avail |= BPP_1; break;
- }
- switch (list->modeinfo.bytesperpixel) {
- case 3: bpp_avail |= BPP_24; break;
- case 4: bpp_avail |= BPP_32; break;
- }
- }
- list = list->next;
- }
+ int32_t req_bpp;
- pformat = format;
-
- // bpp check
- bpp_conv = 0;
- if (!vo_dbpp) {
- if (!IMGFMT_IS_RGB(format) && !IMGFMT_IS_BGR(format)) bpp = 32;
- else bpp = format & 255;
- if (verbose)
- printf("vo_svga: vo_dbpp == 0, bpp: %d\n",bpp);
- switch (bpp) {
- case 32: if (!(bpp_avail & BPP_32)) {
- printf("vo_svga: Haven't found video mode which fit to: %dx%d %dbpp\n",req_w,req_h,bpp);
- printf("vo_svga: Maybe you should try -bpp\n");
- return(1);
- }
- break;
- case 24: if (!(bpp_avail & BPP_24)) {
- if (!(bpp_avail & BPP_32)) {
- printf("vo_svga: Haven't found video mode which fit to: %dx%d %dbpp\n",req_w,req_h,bpp);
- printf("vo_svga: Maybe you should try -bpp\n");
- return(1);
- } else {
- bpp = 32;
- bpp_conv = 1;
- printf("vo_svga: BPP conversion 24->32\n");
- }
- }
- break;
- case 16: if (!(bpp_avail & BPP_16)) {
- printf("vo_svga: Haven't found video mode which fit to: %dx%d %dbpp\n",req_w,req_h,bpp);
- printf("vo_svga: Maybe you should try -bpp\n");
- return(1);
- }
- break;
- case 15: if (!(bpp_avail & BPP_15)) {
- if (!(bpp_avail & BPP_16)) {
- printf("vo_svga: Haven't found video mode which fit to: %dx%d %dbpp\n",req_w,req_h,bpp);
- printf("vo_svga: Maybe you should try -bpp\n");
- return(1);
- } else {
- bpp = 16;
- bpp_conv = 1;
- printf("vo_svga: BPP conversion 15->16\n");
- }
- }
- break;
- case 8: if (!(bpp_avail & BPP_8)) {
- printf("vo_svga: Haven't found video mode which fit to: %dx%d %dbpp\n",req_w,req_h,bpp);
- printf("vo_svga: Maybe you should try -bpp\n");
- return(1);
- }
- break;
- case 4: if (!(bpp_avail & BPP_4)) {
- printf("vo_svga: Haven't found video mode which fit to: %dx%d %dbpp\n",req_w,req_h,bpp);
- printf("vo_svga: Maybe you should try -bpp\n");
- return(1);
- }
- break;
- case 1: if (!(bpp_avail & BPP_1)) {
- printf("vo_svga: Haven't found video mode which fit to: %dx%d %dbpp\n",req_w,req_h,bpp);
- printf("vo_svga: Maybe you should try -bpp\n");
- return(1);
- }
- break;
+ uint32_t accflags;
+ if(verbose)
+ printf("vo_svga: config(%i, %i, %i, %i, %08x, %s, %08x)\n", width, height,
+ d_width, d_height, flags, title, format);
+//Only RGB modes supported
+ if (!IMGFMT_IS_RGB(format) && !IMGFMT_IS_BGR(format)) {assert(0);return -1;}
+ req_bpp = IMGFMT_BGR_DEPTH(format);
+
+ if( vo_dbpp!=0 && vo_dbpp!=req_bpp) {assert(0);return-1;}
+
+ if(!force_vm) {
+ if (verbose) {
+ printf("vo_svga: Looking for the best resolution...\n");
+ printf("vo_svga: req_w: %d, req_h: %d, bpp: %d\n",req_w,req_h,req_bpp);
}
- } else {
- bpp = vo_dbpp;
- if (verbose)
- printf("vo_svga: vo_dbpp == %d\n",bpp);
- switch (bpp) {
- case 32: if (!(bpp_avail & BPP_32)) {
- printf("vo_svga: %dbpp not supported in %dx%d (or larger resolution) by HW or SVGAlib\n",bpp,req_w,req_h);
- return(1);
- }
- break;
- case 24: if (!(bpp_avail & BPP_24)) {
- printf("vo_svga: %dbpp not supported in %dx%d (or larger resolution) by HW or SVGAlib\n",bpp,req_w,req_h);
- return(1);
- }
- break;
- case 16: if (!(bpp_avail & BPP_16)) {
- printf("vo_svga: %dbpp not supported in %dx%d (or larger resolution) by HW or SVGAlib\n",bpp,req_w,req_h);
- return(1);
- }
- break;
- case 15: if (!(bpp_avail & BPP_15)) {
- printf("vo_svga: %dbpp not supported in %dx%d (or larger resolution) by HW or SVGAlib\n",bpp,req_w,req_h);
- return(1);
- }
- break;
- case 8: if (!(bpp_avail & BPP_8)) {
- printf("vo_svga: %dbpp not supported in %dx%d (or larger resolution) by HW or SVGAlib\n",bpp,req_w,req_h);
- return(1);
- }
- break;
- case 4: if (!(bpp_avail & BPP_4)) {
- printf("vo_svga: %dbpp not supported in %dx%d (or larger resolution) by HW or SVGAlib\n",bpp,req_w,req_h);
- return(1);
- }
- break;
- case 1: if (!(bpp_avail & BPP_1)) {
- printf("vo_svga: %dbpp not supported in %dx%d (or larger resolution) by HW or SVGAlib\n",bpp,req_w,req_h);
- return(1);
- }
- break;
- }
+ vid_mode=find_best_svga_mode(req_w,req_h,req_bpp);
+ if(vid_mode==0)
+ return 1;
+ modeinfo=vga_getmodeinfo(vid_mode);
+ }else{//force_vm
+ vid_mode=force_vm;
+ if(vga_hasmode(vid_mode) != 0){
+ printf("vo_svga: forced vid_mode %d (%s) not available\n",
+ vid_mode,vga_getmodename(vid_mode));
+ return 1; //error;
}
-
- list = modelist;
- if (verbose) {
- printf("vo_svga: Looking for the best resolution...\n");
- printf("vo_svga: req_w: %d, req_h: %d, bpp: %d\n",req_w,req_h,bpp);
- }
- while (list != NULL) {
- if ((list->modeinfo.width >= req_w) && (list->modeinfo.height >= req_h)) {
- if (verbose) {
- switch (list->modeinfo.colors) {
- case 2 : printf("vo_svga: vid_mode: %d, %dx%d 1bpp\n",
- list->modenum,list->modeinfo.width,list->modeinfo.height);
- break;
- case 16 : printf("vo_svga: vid_mode: %d, %dx%d 4bpp\n",
- list->modenum,list->modeinfo.width,list->modeinfo.height);
- break;
- case 256 : printf("vo_svga: vid_mode: %d, %dx%d 8bpp\n",
- list->modenum,list->modeinfo.width,list->modeinfo.height);
- break;
- 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);
- 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);
- break;
- case 4: printf("vo_svga: vid_mode: %d, %dx%d 32bpp\n",
- list->modenum,list->modeinfo.width,list->modeinfo.height);
- break;
- }
- }
- switch (bpp) {
- case 32: if (list->modeinfo.bytesperpixel == 4)
- if ((list->modeinfo.width < buf_w) || (list->modeinfo.height < buf_h)) {
- vid_mode = list->modenum;
- buf_w = list->modeinfo.width;
- buf_h = list->modeinfo.height;
- res_widescr = (((buf_w*1.0)/buf_h) > (4.0/3)) ? 1 : 0;
- }
- break;
- case 24: if (list->modeinfo.bytesperpixel == 3)
- if ((list->modeinfo.width < buf_w) || (list->modeinfo.height < buf_h)) {
- vid_mode = list->modenum;
- buf_w = list->modeinfo.width;
- buf_h = list->modeinfo.height;
- res_widescr = (((buf_w*1.0)/buf_h) > (4.0/3)) ? 1 : 0;
- }
- break;
- case 16: if (list->modeinfo.colors == 65536)
- if ((list->modeinfo.width < buf_w) || (list->modeinfo.height < buf_h)) {
- vid_mode = list->modenum;
- buf_w = list->modeinfo.width;
- buf_h = list->modeinfo.height;
- res_widescr = (((buf_w*1.0)/buf_h) > (4.0/3)) ? 1 : 0;
- }
- break;
- case 15: if (list->modeinfo.colors == 32768)
- if ((list->modeinfo.width < buf_w) || (list->modeinfo.height < buf_h)) {
- vid_mode = list->modenum;
- buf_w = list->modeinfo.width;
- buf_h = list->modeinfo.height;
- res_widescr = (((buf_w*1.0)/buf_h) > (4.0/3)) ? 1 : 0;
- }
- break;
- case 8: if (list->modeinfo.colors == 256)
- if ((list->modeinfo.width < buf_w) || (list->modeinfo.height < buf_h)) {
- vid_mode = list->modenum;
- buf_w = list->modeinfo.width;
- buf_h = list->modeinfo.height;
- res_widescr = (((buf_w*1.0)/buf_h) > (4.0/3)) ? 1 : 0;
- }
- break;
- case 4: if (list->modeinfo.colors ==16)
- if ((list->modeinfo.width < buf_w) || (list->modeinfo.height < buf_h)) {
- vid_mode = list->modenum;
- buf_w = list->modeinfo.width;
- buf_h = list->modeinfo.height;
- res_widescr = (((buf_w*1.0)/buf_h) > (4.0/3)) ? 1 : 0;
- }
- break;
- case 1: if (list->modeinfo.colors == 2)
- if ((list->modeinfo.width < buf_w) || (list->modeinfo.height < buf_h)) {
- vid_mode = list->modenum;
- buf_w = list->modeinfo.width;
- buf_h = list->modeinfo.height;
- res_widescr = (((buf_w*1.0)/buf_h) > (4.0/3)) ? 1 : 0;
- }
- break;
- }
+ modeinfo=vga_getmodeinfo(vid_mode);
+ if( (modeinfo->width < req_w) || (modeinfo->height < req_h) ){
+ printf("vo_svga: forced vid_mode %d (%s) too small\n",
+ vid_mode,vga_getmodename(vid_mode));
+ return 1;
}
- list = list->next;
- }
-
- if(force_vm) {
- list=modelist;
- while(list) {
- if(list->modenum == force_vm) {
- buf_w = list->modeinfo.width;
- buf_h = list->modeinfo.height;
- res_widescr = (((buf_w*1.0)/buf_h) > (4.0/3)) ? 1 : 0;
- switch(list->modeinfo.colors) {
- case 2:
- bpp=1;
- bpp_conv=0;
- break;
- case 16:
- bpp=4;
- bpp_conv=0;
- break;
- case 256:
- bpp=8;
- bpp_conv=0;
- break;
- case 32768:
- bpp=16;
- bpp_conv=1;
- break;
- case 65536:
- bpp=16;
- bpp_conv=0;
- break;
- case (1<<24):
- if(list->modeinfo.bytesperpixel == 3) {
- bpp=32;
- bpp_conv=1;
- } else {
- bpp=32;
- bpp_conv=0;
- }
- break;
- }
- vid_mode=force_vm;
- list=NULL;
- } else list=list->next;
- }
}
-
-
- if (verbose)
- printf("vo_svga: vid_mode: %d\n",vid_mode);
+ mode_bpp=bpp_from_vminfo(modeinfo);
+
+ printf("vo_svga: vid_mode: %d, %dx%d %dbpp\n",
+ vid_mode,modeinfo->width,modeinfo->height,mode_bpp);
+
if (vga_setmode(vid_mode) == -1) {
printf("vo_svga: vga_setmode(%d) failed.\n",vid_mode);
uninit();
- return(1); // error
+ return 1; // error
}
-
/* set 332 palette for 8 bpp */
- if(bpp==8){
+ if(mode_bpp==8){
int i;
for(i=0; i<256; i++)
vga_setpalette(i, ((i>>5)&7)*9, ((i>>2)&7)*9, (i&3)*21);
}
/* set 121 palette for 4 bpp */
- else if(bpp==4){
+ else if(mode_bpp==4){
int i;
for(i=0; i<16; i++)
vga_setpalette(i, ((i>>3)&1)*63, ((i>>1)&3)*21, (i&1)*63);
+ }
+ //if we change the logical width, we should know the granularity
+ stride_granularity=8;//according to man vga_logicalwidth
+ if(modeinfo->flags & EXT_INFO_AVAILABLE){
+ stride_granularity=modeinfo->linewidth_unit;
}
-
- WIDTH=vga_getxdim();
- HEIGHT=vga_getydim();
- BYTESPERPIXEL=(bpp+4)>>3;
- LINEWIDTH=vga_getmodeinfo(vid_mode)->linewidth;
-
- if( (vid_mode<10 || vid_mode==145) && (bpp==8 || bpp==4)) LINEWIDTH*=8;
- else
- if(vga_getmodeinfo(vid_mode)->flags & CAPABLE_LINEAR)
-// if (vga_version>0x1430)//remove this to get more speed (or black screen)
- vga_setlinearaddressing();
-
- if(oldmethod) {
- buffer=malloc(HEIGHT*LINEWIDTH);
- maxframes=0;
- } else if ((vga_getmodeinfo(vid_mode)->flags&IS_LINEAR)) {
- directrender=1;
- if(verbose) printf("vo_svga: Using direct rendering to linear video ram.\n");
- }
-
- vga_claimvideomemory((maxframes+1)*HEIGHT*LINEWIDTH);
- GRAPH_MEM=vga_getgraphmem();
- frame=0;
- fillbox(0,0,WIDTH,HEIGHT*(maxframes+1),0);
+ //look for hardware acceleration
+ mode_capabilities=0;//NATIVE;
+ if(!force_native){//if we want to use only native drawers
+ if(modeinfo->flags & HAVE_EXT_SET){//support for hwaccel interface
+ accflags=vga_ext_set(VGA_EXT_AVAILABLE,VGA_AVAIL_ACCEL);
+ if(accflags & ACCELFLAG_FILLBOX) // clear screen
+ mode_capabilities|=CAP_ACCEL_CLEAR;
+ if(accflags & ACCELFLAG_PUTIMAGE)//support for mem->vid transfer
+ mode_capabilities|=CAP_ACCEL_PUTIMAGE;
+ if((accflags & ACCELFLAG_SETMODE) && (accflags & ACCELFLAG_SYNC)){
+ vga_accel(ACCEL_SETMODE,BLITS_IN_BACKGROUND);
+ mode_capabilities|=CAP_ACCEL_BACKGR;//can draw in backgraund
+ }
+ }
+ if(modeinfo->flags & IS_LINEAR){
+ mode_capabilities|=CAP_LINEAR; //don't use bank & vga_draw
+ }
+ else{
+ if(modeinfo->flags & CAPABLE_LINEAR){
+ int vid_mem_size;
+ vid_mem_size = vga_setlinearaddressing();
+ if(vid_mem_size != -1){
+ modeinfo=vga_getmodeinfo(vid_mode);//sometimes they change parameters
+ mode_capabilities|=CAP_LINEAR;
+ }
+ }
+ }
+ }//fi force native
- orig_w = width;
- orig_h = height;
- maxw = req_w;
- maxh = req_h;
-
- if (bpp_conv) {
- bppbuf = malloc(maxw * maxh * BYTESPERPIXEL);
- if (bppbuf == NULL) {
- printf("vo_svga: bppbuf -> Not enough memory for buffering!\n");
- uninit();
- return (1);
- }
+//here is the place to handle strides for accel_ modes;
+ mode_stride=modeinfo->linewidth;
+//we may try to set a bigger stride for video mode that will match the mpi->stride,
+//this way we will transfer more data, but HW put_image can do it in backgraund!
+
+//now lets see how many pages we can use
+ max_pages = modeinfo->maxpixels/(modeinfo->height * modeinfo->width);
+ if(max_pages > MAXPAGES) max_pages = MAXPAGES;
+ if(!vo_doublebuffering) max_pages=1;
+//fill PageStore structs
+ {
+ int i;
+ uint8_t * GRAPH_MEM;
+ int dof;
+ GRAPH_MEM=vga_getgraphmem();
+ for(i=0;i<max_pages;i++){
+ //calculate display offset
+ dof = i * modeinfo->height * modeinfo->width;
+ if(modeinfo->bytesperpixel != 0) dof*=modeinfo->bytesperpixel;
+ //check video chip limitations
+ if( dof != (dof & modeinfo->startaddressrange) ){
+ max_pages=i;//page 0 will never come here
+ break;
+ }
+ PageStore[i].yoffset = i * modeinfo->height;//starting y offset
+ PageStore[i].vbase = GRAPH_MEM + i*modeinfo->height*mode_stride; //memory base address
+ PageStore[i].doffset = dof; //display offset
+ }
}
+ assert(max_pages>0);
+ printf("vo_svga: video mode have %d page(s)\n",max_pages);
+ page_init(max_pages);
+ //15bpp
+ if(modeinfo->bytesperpixel!=0)
+ vga_claimvideomemory(max_pages * modeinfo->height * modeinfo->width * modeinfo->bytesperpixel);
+ else
+ vga_claimvideomemory(max_pages * modeinfo->height * modeinfo->width * mode_bpp / 8);
-#ifdef CONFIG_VIDIX
- if(!vidix_name[0]){
-#endif
- maxw = width; /* No scaling */
- maxh = height;
-#ifdef CONFIG_VIDIX
- }
-#endif
- if (pformat == IMGFMT_YV12) {
- if(bpp==4)
- yuv2rgb_init(bpp|128, MODE_RGB);
- else
- yuv2rgb_init(bpp, MODE_RGB);
- }
+ svga_clear_box(0,0,modeinfo->width,modeinfo->height * max_pages);
+
+ image_height=req_h;
+ image_width=req_w;
+ x_pos = (modeinfo->width - req_w) / 2;
+ y_pos = (modeinfo->height - req_h) / 2;
+ x_pos &= ~(15); //align x offset position to 16 pixels
+ printf("vo_svga: centering image. start at (%d,%d)\n",x_pos,y_pos);
- x_pos = (WIDTH - maxw) / 2;
- y_pos = (HEIGHT - maxh) / 2;
-
#ifdef CONFIG_VIDIX
+
if(vidix_name[0]){
- vidix_init(width, height, x_pos, y_pos, maxw, maxh, format, bpp,
- WIDTH, HEIGHT);
- printf("vo_svga: Using VIDIX. w=%i h=%i mw=%i mh=%i\n",width,height,maxw,maxh);
- vidix_start();
+ vidix_init(width, height, x_pos, y_pos, modeinfo->width, modeinfo->height,
+ format, mode_bpp, modeinfo->width,modeinfo->height);
+ printf("vo_svga: Using VIDIX. w=%i h=%i mw=%i mh=%i\n",width,height,
+ modeinfo->width,modeinfo->height);
+ vidix_start();
}
#endif
- if(bpp==1)
- yuvbuf = malloc((maxw+7)/8 * maxh);
- else
- yuvbuf = malloc(maxw * maxh * BYTESPERPIXEL);
-
- if (yuvbuf == NULL) {
- printf("vo_svga: yuvbuf -> Not enough memory for buffering!\n");
- uninit();
- return (1);
- }
- printf("vo_svga: SVGAlib resolution: %dx%d %dbpp - ", WIDTH, HEIGHT, bpp);
- 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 uint32_t draw_frame(uint8_t *src[]) {
- uint8_t *s=src[0];
- if (bpp_conv) {
- switch(bpp) {
- case 32:
- rgb24to32(src[0],bppbuf,maxw * maxh * 3);
- break;
- case 16:
- rgb15to16(src[0],bppbuf,maxw * maxh * 2);
- break;
- }
- s = bppbuf;
- }
- putbox(x_pos, y_pos, maxw, maxh, s, 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;
-
- if(directrender) {
- yuv2rgb(GRAPH_MEM+(frame*HEIGHT+y+y_pos)*LINEWIDTH+(x+x_pos)*BYTESPERPIXEL,
- image[0], image[1], image[2], w, h, LINEWIDTH, stride[0], stride[1]);
- } else {
- if(bpp==1)
- yuv2rgb(yuvbuf, image[0], image[1], image[2], w, h, (orig_w+7)/8, stride[0], stride[1]);
- else
- yuv2rgb(yuvbuf, image[0], image[1], image[2], w, h, orig_w * BYTESPERPIXEL,
- stride[0], stride[1]);
+static uint32_t draw_slice(uint8_t *image[],int stride[],
+