vo_svga.c

来自「君正早期ucos系统(只有早期的才不没有打包成库),MPLAYER,文件系统,图」· C语言 代码 · 共 755 行 · 第 1/2 页

C
755
字号
/*  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 -  denoise3d fails to find common colorspace, use -vf denoise3d,scale   TODO: - let choose_best_mode take aspect into account - set palette from mpi->palette or mpi->plane[1] - make faster OSD black bars clear - need some OSD changes - Make nicer CONFIG parsing - change video mode logical width to match img->stride[0] - for HW only */#include <mplaylib.h>#include <mplaylib.h>#include <mplaylib.h>#include <vga.h>#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 "mp_msg.h"#include "help_mp.h"//#include "mp_image.h"#include <assert.h>//silence warnings, probably it have to go in some global header#define UNUSED(x) ((void)(x)) 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);#define MAXPAGES 16#define PAGE_EMPTY 0#define PAGE_BUSY 1#define CAP_ACCEL_CLEAR 8#define CAP_ACCEL_PUTIMAGE 4#define CAP_ACCEL_BACKGR 2#define CAP_LINEAR 1static uint8_t zerobuf[8192];//used when clear screen with vga_drawstatic int squarepix;static int force_vm=0;static int force_native=0;static int sync_flip=0;static int blackbar_osd=0;static int cpage,max_pages,old_page;static vga_modeinfo * modeinfo;static int mode_stride; //keep it in case of vga_setlogicalwidthstatic int stride_granularity; //not yet usedstatic int mode_bpp;static int mode_capabilities;static int image_width,image_height; // used by OSDstatic int 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  int locks;}PageStore[MAXPAGES];static vo_info_t info = {    "SVGAlib",    "svga",    "Ivan Kalvachev <iive@users.sf.net>",    ""};#ifdef CONFIG_VIDIXstatic char vidix_name[32] = "";static vidix_grkey_t gr_key;#endifLIBVO_EXTERN(svga)//return number of 1'st free page or -1 if no free onestatic inline int page_find_free(void){int i;  for(i=0;i<max_pages;i++)    if(PageStore[i].locks == PAGE_EMPTY) return i;  return -1;}static int preinit(const char *arg){int i;char s[64];  getch2_disable();  memset(zerobuf,0,sizeof(zerobuf));  force_vm=force_native=squarepix=0;  sync_flip=vo_vsync;  blackbar_osd=0;    if(arg)while(*arg) {#ifdef CONFIG_VIDIX      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,"native",6)) {      force_native=1;      arg+=6;      if( *arg == ':' ) arg++;    }    if(!strncmp(arg,"bbosd",5)) {      blackbar_osd=1;      arg+=5;      if( *arg == ':' ) arg++;    }    if(!strncmp(arg,"retrace",7)) {      sync_flip=1;      arg+=7;      if( *arg == ':' ) arg++;    }        if(*arg) {      i=0;      while(arg[i] && arg[i]!=':')i++;      if(i<64){        strncpy(s, arg, i);        s[i]=0;        force_vm=vga_getmodenumber(s);        if(force_vm>0) {          if( mp_msg_test(MSGT_VO,MSGL_V) ) mp_msg(MSGT_VO,MSGL_V, "vo_svga: Forcing mode %i\n",force_vm);        }else{           force_vm = 0;        }      }      arg+=i;      if(*arg==':')arg++;    }  }    vga_init();  return 0;}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( mp_msg_test(MSGT_VO,MSGL_DBG3) )      mp_msg(MSGT_VO,MSGL_DBG3, "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( mp_msg_test(MSGT_VO,MSGL_DBG3) )      mp_msg(MSGT_VO,MSGL_DBG3, "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;)      fast_memcpy(rgbplane,zerobuf,w*modeinfo->bytesperpixel);//    memset(rgbplane,0,w*modeinfo->bytesperpixel);      rgbplane+=mode_stride;    }    return;  }  //native  if( mp_msg_test(MSGT_VO,MSGL_DBG3) )    mp_msg(MSGT_VO,MSGL_DBG3, "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;int page;  if(mpi->flags & MP_IMGFLAG_DIRECT){    if( mp_msg_test(MSGT_VO,MSGL_DBG3) )      mp_msg(MSGT_VO,MSGL_DBG3, "vo_svga: drawing direct rendered surface\n");    cpage=(uint32_t)mpi->priv;    assert((cpage>=0)&&(cpage<max_pages));    return VO_TRUE; //it's already done  }//  if (mpi->flags&MP_IMGFLAGS_DRAWBACK) //  return VO_TRUE;//direct render method 2//find a free page to draw into//if there is no one then use the current one  page = page_find_free();  if(page>=0) cpage=page;  PageStore[cpage].locks=PAGE_BUSY;// 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( mp_msg_test(MSGT_VO,MSGL_DBG3) )        mp_msg(MSGT_VO,MSGL_DBG3, "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( mp_msg_test(MSGT_VO,MSGL_DBG3) )        mp_msg(MSGT_VO,MSGL_DBG3, "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( mp_msg_test(MSGT_VO,MSGL_DBG3) )      mp_msg(MSGT_VO,MSGL_DBG3, "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;}static 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;}static 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 = 0;//take care of special case below  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( mp_msg_test(MSGT_VO,MSGL_DBG4) )      mp_msg(MSGT_VO,MSGL_DBG4, "vo_svga: testing mode %d (%s)\n",i,vga_getmodename(i));    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( bestmode==0 || prev_badness >= badness ){//modeX etc...      prev_badness=badness;      bestmode=i;      if( mp_msg_test(MSGT_VO,MSGL_DBG4) )        mp_msg(MSGT_VO,MSGL_DBG4, "vo_svga: found good mode %d with badness %d\n",i,badness);    }  }  return bestmode;}static int control(uint32_t request, void *data, ...){  switch (request) {    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);  }#ifdef CONFIG_VIDIX  if (vidix_name) {    switch (request) {    case VOCTRL_SET_EQUALIZER:    {      va_list ap;      int value;          va_start(ap, data);      value = va_arg(ap, int);      va_end(ap);      return vidix_control(request, data, value);    }    case VOCTRL_GET_EQUALIZER:    {      va_list ap;      int *value;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?