From af885100d37183720c8752a565a8164f0a76b4e1 Mon Sep 17 00:00:00 2001 From: iive Date: Thu, 20 Mar 2003 01:45:40 +0000 Subject: 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 --- libvo/vo_svga.c | 1286 ++++++++++++++++++++++++------------------------------- 1 file changed, 564 insertions(+), 722 deletions(-) (limited to 'libvo') 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 Code started: Mon Apr 1 23:25:47 2001 - Some changes by Matan Ziv-Av + 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 @@ -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 + +//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 ", - "" + "SVGAlib", + "svga", + "Ivan Kalvachev ", + "" }; #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=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=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;ibytesperpixel); +// 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;iflags & 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=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;icolors){ + 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;iwidth < 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;iheight * 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[], + int w, int h, int x, int y) { +assert(0); +UNUSED(image);UNUSED(stride); +UNUSED(w);UNUSED(h); +UNUSED(x);UNUSED(y); - putbox(x + x_pos, y + y_pos, w, h, src, 1); - } + return VO_ERROR;//this is yv12 only -> vf_scale should do all transforms +} - return (0); +static uint32_t draw_frame(uint8_t *src[]) { +assert(0); +UNUSED(src); + return VO_ERROR;//this one should not be called } 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); +// for now draw only over the image +// vo_draw_text(modeinfo->width, modeinfo->height, draw_alpha);//black bar OSD + vo_draw_text(image_width, image_height, draw_alpha); } static void flip_page(void) { - if(oldmethod) { - int i; - uint8_t *b; - b=buffer; - for(i=0;imaxframes)frame=0; - } - } +static int oldpage=-1; +int page; + page = page_flip_page(); + if(verbose > 2) + printf("vo_svga: viewing page %d\n",page); + if(sync_flip && oldpage!=page){ + vga_waitretrace(); + printf("vo_svga:vga_waitretraced\n"); + } + vga_setdisplaystart(PageStore[cpage].doffset); + oldpage=page; } static void check_events(void) { } static void uninit(void) { - vga_modelist_t *list = modelist; #ifdef CONFIG_VIDIX if(vidix_name[0])vidix_term(); #endif - vga_setmode(TEXT); - - if (bppbuf != NULL) - free(bppbuf); - bppbuf=NULL; - 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(squarepix && (minfo.height*4 != minfo.width*3)) return 0; - - 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; - getch2_disable(); - 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 2 : bpp_avail |= BPP_1 ; break; - case 16 : bpp_avail |= BPP_4 ; break; - case 256 : bpp_avail |= BPP_8 ; break; - 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; +int32_t req_bpp,flags; +int i,lastmode; +vga_modeinfo * vminfo; + + if (verbose >3) + printf("vo_svga: query_format=%X \n",format); +//only RGB modes supported + if( (!IMGFMT_IS_RGB(format)) && (!IMGFMT_IS_BGR(format)) ) return 0; + +// Reject different endian +#ifdef WORDS_BIGENDIAN + if (IMGFMT_IS_BGR(format)) return 0; +#else + if (IMGFMT_IS_RGB(format)) return 0; +#endif - if (!checked) { - if (checksupportedmodes()) // Looking for available video modes - return(0); + //svgalib supports only BG4B! if we want BGR4 we have to emulate it (sw) + if( format==IMGFMT_BGR4 || format==IMGFMT_RGB4) return 0; + req_bpp = IMGFMT_RGB_DEPTH(format); + if( vo_dbpp>0 && vo_dbpp!=req_bpp ) return 0; //support -bpp options +//scan all modes + lastmode = vga_lastmodenumber(); + for(i=1;i 0) && (force_vm != i) ) continue;//quick hack + flags = VFCAP_CSP_SUPPORTED| + VFCAP_CSP_SUPPORTED_BY_HW| + VFCAP_ACCEPT_STRIDE| + 0; + if(req_bpp>8) flags|=VFCAP_OSD; + return flags; } - - // if (vo_dbpp) => There is NO conversion!!! - if (vo_dbpp) { - if (format == IMGFMT_YV12) return (1); - switch (vo_dbpp) { - case 32: if ((format == IMGFMT_RGB32) || (format == IMGFMT_BGR32)) - return ((bpp_avail & BPP_32) ? 1 : 0); - break; - case 24: if ((format == IMGFMT_RGB24) || (format == IMGFMT_BGR24)) - return ((bpp_avail & BPP_24) ? 1 : 0); - break; - case 16: if ((format == IMGFMT_RGB16) || (format == IMGFMT_BGR16)) - return ((bpp_avail & BPP_16) ? 1 : 0); - break; - case 15: if ((format == IMGFMT_RGB15) || (format == IMGFMT_BGR15)) - return ((bpp_avail & BPP_15) ? 1 : 0); - break; - case 8 : if ((format == IMGFMT_RGB8 ) || (format == IMGFMT_BGR8)) - return ((bpp_avail & BPP_8 ) ? 1 : 0); - break; - case 4 : if ((format == IMGFMT_RG4B ) || (format == IMGFMT_BG4B)) - return ((bpp_avail & BPP_4 ) ? 1 : 0); - break; - case 1 : if ((format == IMGFMT_RGB1 ) || (format == IMGFMT_BGR1)) - return ((bpp_avail & BPP_1 ) ? 1 : 0); - break; - } - } else { - switch (format) { - case IMGFMT_RGB32: - case IMGFMT_BGR32: return ((bpp_avail & BPP_32) ? 1 : 0); break; - case IMGFMT_RGB24: - case IMGFMT_BGR24: { - res = (bpp_avail & BPP_24) ? 1 : 0; - if (!res) - res = (bpp_avail & BPP_32) ? 1 : 0; - return (res); - } break; - case IMGFMT_RGB16: - case IMGFMT_BGR16: return ((bpp_avail & BPP_16) ? 1 : 0); break; - case IMGFMT_RGB15: - case IMGFMT_BGR15: { - res = (bpp_avail & BPP_15) ? 1 : 0; - if (!res) - res = (bpp_avail & BPP_16) ? 1 : 0; - return (res); - } break; - case IMGFMT_YV12: return (1); break; - } - } - return (0); -} - -static void putbox(int x, int y, int w, int h, uint8_t *buf, int prog) { - int base, add, wid; - if(bpp==1) - wid=(w+7)/8; - else - wid=w*BYTESPERPIXEL; - - if(oldmethod) { - add=wid*prog; - while( (h--) > 0 ) { - if(bpp==1) - memcpy(buffer+(x+7)/8+(y++)*LINEWIDTH, buf, wid); - else - memcpy(buffer+x*BYTESPERPIXEL+(y++)*LINEWIDTH, buf, wid); - buf+=add; - } - } else { - 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); + return 0; } static void draw_alpha(int x0, int y0, int w, int h, unsigned char *src, unsigned char *srca, int stride) { char* base; + int bytelen; + + if(verbose>2) + printf("vo_svga: draw_alpha(x0=%d,y0=%d,w=%d,h=%d,src=%p,srca=%p,stride=%d\n", + x0,y0,w,h,src,srca,stride); + x0+=x_pos;// in case of drawing over image + y0+=y_pos; - if(oldmethod) { - base=buffer; - } else - base=((frame*HEIGHT+y_pos)*WIDTH+x_pos)*BYTESPERPIXEL + GRAPH_MEM ; - - switch (bpp) { + //only modes with bytesperpixel>0 can draw OSD + if(modeinfo->bytesperpixel==0) return; +// if(!(mode_capabilities&CAP_LINEAR)) return;//force_native will remove OSD + + base=PageStore[cpage].vbase + y0*mode_stride + x0*modeinfo->bytesperpixel; + bytelen = modeinfo->width * modeinfo->bytesperpixel; + switch (mode_bpp) { case 32: - vo_draw_alpha_rgb32(w, h, src, srca, stride, base+4*(y0*WIDTH+x0), 4*WIDTH); + vo_draw_alpha_rgb32(w, h, src, srca, stride, base, bytelen); break; case 24: - vo_draw_alpha_rgb24(w, h, src, srca, stride, base+3*(y0*WIDTH+x0), 3*WIDTH); + vo_draw_alpha_rgb24(w, h, src, srca, stride, base, bytelen); break; case 16: - vo_draw_alpha_rgb16(w, h, src, srca, stride, base+2*(y0*WIDTH+x0), 2*WIDTH); + vo_draw_alpha_rgb16(w, h, src, srca, stride, base, bytelen); break; case 15: - vo_draw_alpha_rgb15(w, h, src, srca, stride, base+2*(y0*WIDTH+x0), 2*WIDTH); + vo_draw_alpha_rgb15(w, h, src, srca, stride, base, bytelen); break; } } -static uint32_t get_image(mp_image_t *mpi) -{ - 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(!directrender) - 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; +static uint32_t get_image(mp_image_t *mpi){ +int page; + + if(!IMGFMT_IS_BGR(mpi->imgfmt) && !IMGFMT_IS_RGB(mpi->imgfmt) ){ + assert(0);//should never happen + return(VO_FALSE); + } + + if ( + ( (mpi->type != MP_IMGTYPE_STATIC) && (mpi->type != MP_IMGTYPE_TEMP)) || + (mpi->flags & MP_IMGFLAG_PLANAR) || + (mpi->flags & MP_IMGFLAG_YUV) + ) + return(VO_FALSE); + +//reading from video memory is horribly slow + if( !(mpi->flags & MP_IMGFLAG_READABLE) && vo_directrendering && + (mode_capabilities & CAP_LINEAR) ){ + page=page_get_image(); + if(page >= 0){ + mpi->flags |= MP_IMGFLAG_DIRECT; + mpi->stride[0] = mode_stride; + mpi->planes[0] = PageStore[page].vbase + + y_pos*mode_stride + (x_pos*mpi->bpp)/8; + (int)mpi->priv=page; + if(verbose>2) + printf("vo_svga: direct render allocated! page=%d\n",page); + return(VO_TRUE); } - mpi->flags |= MP_IMGFLAG_DIRECT; - - return(VO_TRUE); -} + } + return(VO_FALSE); +} -- cgit v1.2.3