2001-04-05 08:42:02 +00:00
/*
2009-02-08 03:27:30 +00:00
* 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 >
* complete rewrite by Ivan Kalvachev 19 Mar 2003
*
* This file is part of MPlayer .
*
* MPlayer is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* MPlayer is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License along
* with MPlayer ; if not , write to the Free Software Foundation , Inc . ,
* 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA .
*/
2003-03-20 01:45:40 +00:00
2009-02-08 03:27:30 +00:00
/*
2003-03-20 01:45:40 +00:00
Wrangings :
2009-02-21 00:30:53 +00:00
- 1 bpp doesn ' t work right for me with ' - double ' and svgalib 1.4 .3 ,
2003-03-20 01:45:40 +00:00
but works OK with svgalib 1.9 .17
2009-02-21 00:30:53 +00:00
- 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 .
2003-03-20 01:45:40 +00:00
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
2003-03-23 00:44:09 +00:00
- denoise3d fails to find common colorspace , use - vf denoise3d , scale
2009-02-21 00:30:53 +00:00
2003-03-20 01:45:40 +00:00
TODO :
- let choose_best_mode take aspect into account
- set palette from mpi - > palette or mpi - > plane [ 1 ]
2003-09-21 23:59:49 +00:00
- make faster OSD black bars clear - need some OSD changes
2003-03-20 01:45:40 +00:00
- Make nicer CONFIG parsing
2009-02-21 00:30:53 +00:00
- change video mode logical width to match img - > stride [ 0 ] - for HW only
2001-04-05 08:42:02 +00:00
*/
# include <stdio.h>
# include <stdlib.h>
2002-09-22 02:33:28 +00:00
# include <string.h>
2001-04-05 08:42:02 +00:00
# include <vga.h>
2001-04-17 17:35:27 +00:00
# include <limits.h>
2001-04-05 08:42:02 +00:00
# include "config.h"
# include "video_out.h"
# include "video_out_internal.h"
2003-03-20 01:45:40 +00:00
# include "fastmemcpy.h"
# include "osdep/getch2.h"
2002-12-21 22:08:14 +00:00
2011-01-26 17:40:52 +00:00
# include "sub/sub.h"
2001-04-24 11:42:04 +00:00
2004-10-28 01:15:53 +00:00
# include "mp_msg.h"
//#include "mp_image.h"
2002-04-18 15:41:33 +00:00
2003-03-20 01:45:40 +00:00
# include <assert.h>
2011-05-03 08:54:31 +00:00
static int query_format ( uint32_t format ) ;
2002-04-18 15:41:33 +00:00
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 ) ;
2001-04-05 08:42:02 +00:00
2003-03-20 01:45:40 +00:00
# define MAXPAGES 16
2003-09-21 23:59:49 +00:00
# define PAGE_EMPTY 0
# define PAGE_BUSY 1
2002-12-21 22:08:14 +00:00
2003-03-20 01:45:40 +00:00
# define CAP_ACCEL_CLEAR 8
# define CAP_ACCEL_PUTIMAGE 4
# define CAP_ACCEL_BACKGR 2
# define CAP_LINEAR 1
2001-04-05 08:42:02 +00:00
2003-03-20 01:45:40 +00:00
static uint8_t zerobuf [ 8192 ] ; //used when clear screen with vga_draw
2001-04-05 08:42:02 +00:00
2003-03-20 01:45:40 +00:00
static int squarepix ;
static int force_vm = 0 ;
static int force_native = 0 ;
static int sync_flip = 0 ;
2003-09-21 23:59:49 +00:00
static int blackbar_osd = 0 ;
static int cpage , max_pages , old_page ;
2001-04-17 06:22:48 +00:00
2003-03-20 01:45:40 +00:00
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 ;
2001-04-05 08:42:02 +00:00
2003-03-20 01:45:40 +00:00
static int image_width , image_height ; // used by OSD
2003-09-21 23:59:49 +00:00
static int x_pos , y_pos ;
2001-04-17 06:22:48 +00:00
2003-03-20 01:45:40 +00:00
static struct {
2009-02-21 08:33:43 +00:00
int yoffset ; //y position of the page
int doffset ; //display start of the page
uint8_t * vbase ; //memory start address of the page
int locks ;
2003-03-20 01:45:40 +00:00
} PageStore [ MAXPAGES ] ;
2007-12-02 14:06:03 +00:00
static const vo_info_t info = {
2003-03-20 01:45:40 +00:00
" SVGAlib " ,
" svga " ,
2003-09-25 01:48:47 +00:00
" Ivan Kalvachev <iive@users.sf.net> " ,
2003-03-20 01:45:40 +00:00
" "
2002-04-18 15:41:33 +00:00
} ;
2002-11-11 15:22:10 +00:00
LIBVO_EXTERN ( svga )
2003-03-20 01:45:40 +00:00
//return number of 1'st free page or -1 if no free one
2007-04-01 21:59:54 +00:00
static inline int page_find_free ( void ) {
2009-02-21 08:33:43 +00:00
int i ;
for ( i = 0 ; i < max_pages ; i + + )
if ( PageStore [ i ] . locks = = PAGE_EMPTY ) return i ;
return - 1 ;
2003-03-20 01:45:40 +00:00
}
2005-08-05 01:24:37 +00:00
static int preinit ( const char * arg )
2002-04-18 15:41:33 +00:00
{
2009-02-21 08:33:43 +00:00
int i , rez ;
char s [ 64 ] ;
2001-04-17 06:22:48 +00:00
2009-02-21 08:33:43 +00:00
getch2_disable ( ) ;
memset ( zerobuf , 0 , sizeof ( zerobuf ) ) ;
force_vm = force_native = squarepix = 0 ;
sync_flip = vo_vsync ;
blackbar_osd = 0 ;
2009-02-21 00:30:53 +00:00
2009-02-21 08:33:43 +00:00
if ( arg ) while ( * arg ) {
if ( ! strncmp ( arg , " sq " , 2 ) ) {
squarepix = 1 ;
arg + = 2 ;
if ( * arg = = ' : ' ) arg + + ;
}
2003-09-21 23:59:49 +00:00
2009-02-21 08:33:43 +00:00
if ( ! strncmp ( arg , " native " , 6 ) ) {
force_native = 1 ;
arg + = 6 ;
if ( * arg = = ' : ' ) arg + + ;
}
2003-09-21 23:59:49 +00:00
2009-02-21 08:33:43 +00:00
if ( ! strncmp ( arg , " bbosd " , 5 ) ) {
blackbar_osd = 1 ;
arg + = 5 ;
if ( * arg = = ' : ' ) arg + + ;
}
2003-09-21 23:59:49 +00:00
2009-02-21 08:33:43 +00:00
if ( ! strncmp ( arg , " retrace " , 7 ) ) {
sync_flip = 1 ;
arg + = 7 ;
if ( * arg = = ' : ' ) arg + + ;
}
2009-02-21 00:30:53 +00:00
2009-02-21 08:33:43 +00:00
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 ) {
mp_msg ( MSGT_VO , MSGL_V , " vo_svga: Forcing mode %i \n " , force_vm ) ;
} else {
force_vm = 0 ;
}
}
arg + = i ;
if ( * arg = = ' : ' ) arg + + ;
2003-09-21 23:59:49 +00:00
}
2003-03-20 01:45:40 +00:00
}
2009-02-21 00:30:53 +00:00
2009-02-21 08:33:43 +00:00
rez = vga_init ( ) ;
if ( rez ! = 0 ) {
mp_msg ( MSGT_VO , MSGL_ERR , " vo_svga: vga_init() returned error=%d \n " , rez ) ;
}
return ! ! rez ;
2003-03-20 01:45:40 +00:00
}
2002-12-21 22:08:14 +00:00
2003-03-20 01:45:40 +00:00
static void svga_clear_box ( int x , int y , int w , int h ) {
2009-02-21 08:33:43 +00:00
uint8_t * rgbplane ;
int i ;
if ( mode_capabilities & CAP_ACCEL_CLEAR ) {
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 ) {
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 + + ) {
2003-03-20 01:45:40 +00:00
//i'm afraid that memcpy is better optimized than memset;)
2009-02-21 08:33:43 +00:00
fast_memcpy ( rgbplane , zerobuf , w * modeinfo - > bytesperpixel ) ;
2003-03-20 01:45:40 +00:00
// memset(rgbplane,0,w*modeinfo->bytesperpixel);
2009-02-21 08:33:43 +00:00
rgbplane + = mode_stride ;
}
return ;
2003-03-20 01:45:40 +00:00
}
2009-02-21 08:33:43 +00:00
//native
2006-04-24 04:23:53 +00:00
mp_msg ( MSGT_VO , MSGL_DBG3 , " vo_svga: clearing box %d,%d - %d,%d with native draw \n " , x , y , w , h ) ;
2009-02-21 08:33:43 +00:00
if ( modeinfo - > bytesperpixel ! = 0 ) w * = modeinfo - > bytesperpixel ;
for ( i = 0 ; i < h ; i + + ) {
vga_drawscansegment ( zerobuf , x , y + i , w ) ;
}
2003-03-20 01:45:40 +00:00
} ;
static uint32_t svga_draw_image ( mp_image_t * mpi ) {
2009-02-21 08:33:43 +00:00
int i , x , y , w , h ;
int stride ;
uint8_t * rgbplane , * base ;
int bytesperline ;
int page ;
if ( mpi - > flags & MP_IMGFLAG_DIRECT ) {
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
}
2009-02-21 00:30:53 +00:00
// if (mpi->flags&MP_IMGFLAGS_DRAWBACK)
2003-03-20 01:45:40 +00:00
// return VO_TRUE;//direct render method 2
2003-09-21 23:59:49 +00:00
//find a free page to draw into
//if there is no one then use the current one
2009-02-21 08:33:43 +00:00
page = page_find_free ( ) ;
if ( page > = 0 ) cpage = page ;
PageStore [ cpage ] . locks = PAGE_BUSY ;
2003-09-21 23:59:49 +00:00
2009-02-21 00:30:53 +00:00
// these variables are used in loops
2012-02-24 14:25:22 +00:00
x = 0 ;
y = 0 ;
2009-02-21 08:33:43 +00:00
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
2003-03-20 01:45:40 +00:00
//ACCELERATE
2009-02-21 08:33:43 +00:00
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 ) ;
2003-03-20 01:45:40 +00:00
2009-02-21 08:33:43 +00:00
vga_accel ( ACCEL_PUTIMAGE , x , y + PageStore [ cpage ] . yoffset , w , h , rgbplane ) ;
return VO_TRUE ;
}
2009-02-21 00:30:53 +00:00
2009-02-21 08:33:43 +00:00
if ( mode_capabilities & CAP_LINEAR ) {
2009-02-21 00:30:53 +00:00
//DIRECT
2009-02-21 08:33:43 +00:00
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
2003-03-20 01:45:40 +00:00
//NATIVE
2009-02-21 08:33:43 +00:00
{
int length ;
length = ( w * mpi - > bpp ) / 8 ;
//one byte per pixel! svgalib innovation
if ( mpi - > imgfmt = = IMGFMT_RG4B | | mpi - > imgfmt = = IMGFMT_BG4B ) length = w ;
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 ;
}
2003-03-20 01:45:40 +00:00
}
2009-02-21 08:33:43 +00:00
return VO_TRUE ;
2003-03-20 01:45:40 +00:00
}
2002-10-09 00:51:04 +00:00
2006-07-08 15:26:36 +00:00
static int bpp_from_vminfo ( vga_modeinfo * vminfo ) {
2009-02-21 08:33:43 +00:00
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 ;
2002-04-18 15:41:33 +00:00
}
2006-07-08 15:26:36 +00:00
static int find_best_svga_mode ( int req_w , int req_h , int req_bpp ) {
2009-02-21 08:33:43 +00:00
int badness , prev_badness ;
int bestmode , lastmode ;
int i ;
vga_modeinfo * vminfo ;
2003-03-20 01:45:40 +00:00
//int best aspect mode // best linear mode // best normal mode (no modeX)
2009-02-21 08:33:43 +00:00
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 ;
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 ;
mp_msg ( MSGT_VO , MSGL_DBG4 , " vo_svga: found good mode %d with badness %d \n " , i , badness ) ;
}
2003-03-20 01:45:40 +00:00
}
2009-02-21 08:33:43 +00:00
return bestmode ;
2003-03-20 01:45:40 +00:00
}
2008-04-02 16:38:34 +00:00
static int control ( uint32_t request , void * data )
2002-04-18 15:41:33 +00:00
{
2003-12-07 15:08:20 +00:00
switch ( request ) {
2009-02-21 08:33:43 +00:00
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 ) ;
2003-12-07 15:08:20 +00:00
}
2009-02-21 08:33:43 +00:00
return VO_NOTIMPL ;
2001-04-05 08:42:02 +00:00
}
2003-03-20 01:45:40 +00:00
//
// This function is called to init the video driver for specific mode
//
2005-08-05 01:24:37 +00:00
static int config ( uint32_t width , uint32_t height , uint32_t d_width ,
2005-04-18 15:52:38 +00:00
uint32_t d_height , uint32_t flags , char * title ,
2003-03-20 01:45:40 +00:00
uint32_t format ) {
2009-02-21 08:33:43 +00:00
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 ;
int32_t req_bpp ;
2009-02-21 00:30:53 +00:00
2009-02-21 08:33:43 +00:00
uint32_t accflags ;
2006-04-24 04:23:53 +00:00
mp_msg ( MSGT_VO , MSGL_V , " vo_svga: config(%i, %i, %i, %i, %08x, %s, %08x) \n " , width , height ,
2003-03-20 01:45:40 +00:00
d_width , d_height , flags , title , format ) ;
//Only RGB modes supported
2009-02-21 08:33:43 +00:00
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 ) {
mp_msg ( MSGT_VO , MSGL_V , " vo_svga: Looking for the best resolution... \n " ) ;
mp_msg ( MSGT_VO , MSGL_V , " vo_svga: req_w: %d, req_h: %d, bpp: %d \n " , req_w , req_h , req_bpp ) ;
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 ) {
2009-07-06 22:15:02 +00:00
mp_tmsg ( MSGT_VO , MSGL_ERR , " [VO_SVGA] Forced vid_mode %d (%s) not available. \n " ,
2009-02-21 08:33:43 +00:00
vid_mode , vga_getmodename ( vid_mode ) ) ;
return 1 ; //error;
}
modeinfo = vga_getmodeinfo ( vid_mode ) ;
if ( ( modeinfo - > width < req_w ) | | ( modeinfo - > height < req_h ) ) {
2009-07-06 22:15:02 +00:00
mp_tmsg ( MSGT_VO , MSGL_ERR , " [VO_SVGA] Forced vid_mode %d (%s) too small. \n " ,
2009-02-21 08:33:43 +00:00
vid_mode , vga_getmodename ( vid_mode ) ) ;
return 1 ;
}
2001-04-17 06:22:48 +00:00
}
2009-02-21 08:33:43 +00:00
mode_bpp = bpp_from_vminfo ( modeinfo ) ;
2009-07-06 22:15:02 +00:00
mp_tmsg ( MSGT_VO , MSGL_INFO , " [VO_SVGA] Vid_mode: %d, %dx%d %dbpp. \n " ,
2009-02-21 08:33:43 +00:00
vid_mode , modeinfo - > width , modeinfo - > height , mode_bpp ) ;
if ( vga_setmode ( vid_mode ) = = - 1 ) {
2009-07-06 22:15:02 +00:00
mp_tmsg ( MSGT_VO , MSGL_ERR , " [VO_SVGA] Vga_setmode(%d) failed. \n " , vid_mode ) ;
2009-02-21 08:33:43 +00:00
uninit ( ) ;
return 1 ; // error
2001-04-14 18:19:40 +00:00
}
2009-02-21 08:33:43 +00:00
/* set 332 palette for 8 bpp */
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 ) ;
2001-04-17 06:22:48 +00:00
}
2009-02-21 08:33:43 +00:00
/* set 121 palette for 4 bpp */
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 ) ;
2003-03-20 01:45:40 +00:00
}
2009-02-21 08:33:43 +00:00
//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 ;
2003-03-20 01:45:40 +00:00
}
2009-02-21 08:33:43 +00:00
//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
}
2003-03-20 01:45:40 +00:00
}
2009-02-21 08:33:43 +00:00
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 ;
}
}
2003-03-20 01:45:40 +00:00
}
2009-02-21 08:33:43 +00:00
} //fi force native
if ( mode_capabilities & CAP_LINEAR ) {
2009-07-06 22:15:02 +00:00
mp_tmsg ( MSGT_VO , MSGL_INFO , " [VO_SVGA] Video mode is linear and memcpy could be used for image transfer. \n " ) ;
2003-03-20 01:45:40 +00:00
}
2009-02-21 08:33:43 +00:00
if ( mode_capabilities & CAP_ACCEL_PUTIMAGE ) {
2009-07-06 22:15:02 +00:00
mp_tmsg ( MSGT_VO , MSGL_INFO , " [VO_SVGA] Video mode has hardware acceleration and put_image could be used. \n " ) ;
mp_tmsg ( MSGT_VO , MSGL_INFO , " [VO_SVGA] If it works for you I would like to know. \n [VO_SVGA] (send log with `mplayer test.avi -v -v -v -v &> svga.log`). Thx! \n " ) ;
2003-03-20 01:45:40 +00:00
}
2009-02-21 00:30:53 +00:00
2003-03-20 01:45:40 +00:00
//here is the place to handle strides for accel_ modes;
2009-02-21 08:33:43 +00:00
mode_stride = modeinfo - > linewidth ;
2009-02-21 00:30:53 +00:00
//we may try to set a bigger stride for video mode that will match the mpi->stride,
2003-03-20 01:45:40 +00:00
//this way we will transfer more data, but HW put_image can do it in backgraund!
2009-02-21 00:30:53 +00:00
//now let's see how many pages we can use
2009-02-21 08:33:43 +00:00
max_pages = modeinfo - > maxpixels / ( modeinfo - > height * modeinfo - > width ) ;
if ( max_pages > MAXPAGES ) max_pages = MAXPAGES ;
if ( ! vo_doublebuffering ) max_pages = 1 ;
2003-03-20 01:45:40 +00:00
//fill PageStore structs
2009-02-21 08:33:43 +00:00
{
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
PageStore [ i ] . locks = PAGE_EMPTY ;
}
2003-03-20 01:45:40 +00:00
}
2009-02-21 08:33:43 +00:00
assert ( max_pages > 0 ) ;
2009-07-06 22:15:02 +00:00
mp_tmsg ( MSGT_VO , MSGL_INFO , " [VO_SVGA] Video mode has %d page(s). \n " , max_pages ) ;
2009-02-21 08:33:43 +00:00
//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 ) ;
cpage = old_page = 0 ;
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
2009-07-06 22:15:02 +00:00
mp_tmsg ( MSGT_VO , MSGL_INFO , " [VO_SVGA] Centering image. Starting at (%d,%d) \n " , x_pos , y_pos ) ;
2002-12-21 22:08:14 +00:00
2009-02-21 08:33:43 +00:00
vga_setdisplaystart ( 0 ) ;
return 0 ;
2001-04-05 08:42:02 +00:00
}
2005-08-05 01:24:37 +00:00
static int draw_slice ( uint8_t * image [ ] , int stride [ ] ,
2003-03-20 01:45:40 +00:00
int w , int h , int x , int y ) {
2009-02-21 08:33:43 +00:00
assert ( 0 ) ;
return VO_ERROR ; //this is yv12 only -> vf_scale should do all transforms
2003-03-20 01:45:40 +00:00
}
2001-04-24 12:21:42 +00:00
2005-08-05 01:24:37 +00:00
static int draw_frame ( uint8_t * src [ ] ) {
2009-02-21 08:33:43 +00:00
assert ( 0 ) ;
return VO_ERROR ; //this one should not be called
2001-04-05 08:42:02 +00:00
}
2001-08-13 11:08:18 +00:00
static void draw_osd ( void )
{
2009-02-21 08:33:43 +00:00
mp_msg ( MSGT_VO , MSGL_DBG4 , " vo_svga: draw_osd() \n " ) ;
//only modes with bytesperpixel>0 can draw OSD
if ( modeinfo - > bytesperpixel = = 0 ) return ;
if ( ! ( mode_capabilities & CAP_LINEAR ) ) return ; //force_native will remove OSD
2009-02-21 00:30:53 +00:00
2009-02-21 08:33:43 +00:00
if ( blackbar_osd ) {
2003-09-21 23:59:49 +00:00
//111
//3 4
//222
2009-02-21 08:33:43 +00:00
svga_clear_box ( 0 , 0 + PageStore [ cpage ] . yoffset ,
modeinfo - > width , y_pos ) ;
svga_clear_box ( 0 , image_height + y_pos + PageStore [ cpage ] . yoffset ,
modeinfo - > width , modeinfo - > height - ( image_height + y_pos ) ) ;
svga_clear_box ( 0 , y_pos + PageStore [ cpage ] . yoffset ,
x_pos , image_height ) ;
svga_clear_box ( image_width + x_pos , y_pos + PageStore [ cpage ] . yoffset ,
modeinfo - > width - ( x_pos + image_width ) , image_height ) ;
2003-09-21 23:59:49 +00:00
// vo_remove_text(modeinfo->width, modeinfo->height, clear_alpha);
2009-02-21 08:33:43 +00:00
vo_draw_text ( modeinfo - > width , modeinfo - > height , draw_alpha ) ;
} else {
vo_draw_text ( image_width , image_height , draw_alpha ) ;
}
2001-08-13 11:08:18 +00:00
}
static void flip_page ( void ) {
2009-02-21 08:33:43 +00:00
PageStore [ old_page ] . locks = PAGE_EMPTY ;
PageStore [ cpage ] . locks = PAGE_BUSY ;
2003-09-21 23:59:49 +00:00
2006-04-24 04:23:53 +00:00
mp_msg ( MSGT_VO , MSGL_DBG3 , " vo_svga: viewing page %d \n " , cpage ) ;
2009-02-21 08:33:43 +00:00
if ( sync_flip & & old_page ! = cpage ) {
mp_msg ( MSGT_VO , MSGL_DBG3 , " vo_svga:vga_waitretrace \n " ) ;
vga_waitretrace ( ) ;
}
vga_setdisplaystart ( PageStore [ cpage ] . doffset ) ;
2009-02-21 00:30:53 +00:00
2009-02-21 08:33:43 +00:00
old_page = cpage ; //cpage will be overwriten on next draw_image
2001-04-05 08:42:02 +00:00
}
static void check_events ( void ) {
}
static void uninit ( void ) {
2009-02-21 08:33:43 +00:00
vga_setmode ( TEXT ) ;
2001-04-05 08:42:02 +00:00
}
2002-01-26 16:01:26 +00:00
2002-04-18 15:41:33 +00:00
/* --------------------------------------------------------------------- */
2005-08-05 01:24:37 +00:00
static int query_format ( uint32_t format ) {
2009-02-21 08:33:43 +00:00
int32_t req_bpp , flags ;
int i , lastmode ;
vga_modeinfo * vminfo ;
2003-03-20 01:45:40 +00:00
2006-04-24 04:23:53 +00:00
mp_msg ( MSGT_VO , MSGL_DBG4 , " vo_svga: query_format=%X \n " , format ) ;
2003-03-20 01:45:40 +00:00
//only RGB modes supported
2009-02-21 08:33:43 +00:00
if ( ( ! IMGFMT_IS_RGB ( format ) ) & & ( ! IMGFMT_IS_BGR ( format ) ) ) return 0 ;
2003-03-20 01:45:40 +00:00
// Reject different endian
2009-07-26 19:53:00 +00:00
# if HAVE_BIGENDIAN
2009-02-21 08:33:43 +00:00
if ( IMGFMT_IS_BGR ( format ) ) return 0 ;
2003-03-20 01:45:40 +00:00
# else
2009-02-21 08:33:43 +00:00
if ( IMGFMT_IS_RGB ( format ) ) return 0 ;
2003-03-20 01:45:40 +00:00
# endif
2002-04-18 15:41:33 +00:00
2009-02-21 08:33:43 +00:00
//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
2003-03-20 01:45:40 +00:00
//scan all modes
2009-02-21 08:33:43 +00:00
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 ( ( force_vm > 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 ;
}
return 0 ;
2002-04-18 15:41:33 +00:00
}
static void draw_alpha ( int x0 , int y0 , int w , int h , unsigned char * src ,
unsigned char * srca , int stride ) {
2009-02-21 08:33:43 +00:00
char * base ;
2003-03-20 01:45:40 +00:00
2006-04-24 04:23:53 +00:00
mp_msg ( MSGT_VO , MSGL_DBG3 , " vo_svga: draw_alpha(x0=%d,y0=%d,w=%d,h=%d,src=%p,srca=%p,stride=%d \n " ,
2003-03-20 01:45:40 +00:00
x0 , y0 , w , h , src , srca , stride ) ;
2009-02-21 08:33:43 +00:00
if ( ! blackbar_osd ) {
//drawing in the image, so place the stuff there
x0 + = x_pos ;
y0 + = y_pos ;
}
2009-02-21 00:30:53 +00:00
2006-04-24 04:23:53 +00:00
mp_msg ( MSGT_VO , MSGL_DBG4 , " vo_svga: OSD draw in page %d \n " , cpage ) ;
2009-02-21 08:33:43 +00:00
base = PageStore [ cpage ] . vbase + y0 * mode_stride + x0 * modeinfo - > bytesperpixel ;
switch ( mode_bpp ) {
case 32 :
vo_draw_alpha_rgb32 ( w , h , src , srca , stride , base , mode_stride ) ;
break ;
case 24 :
vo_draw_alpha_rgb24 ( w , h , src , srca , stride , base , mode_stride ) ;
break ;
case 16 :
vo_draw_alpha_rgb16 ( w , h , src , srca , stride , base , mode_stride ) ;
break ;
case 15 :
vo_draw_alpha_rgb15 ( w , h , src , srca , stride , base , mode_stride ) ;
break ;
}
2002-04-18 15:41:33 +00:00
}
2003-03-20 01:45:40 +00:00
static uint32_t get_image ( mp_image_t * mpi ) {
2009-02-21 08:33:43 +00:00
int page ;
2003-03-20 01:45:40 +00:00
2009-02-21 08:33:43 +00:00
if ( ! IMGFMT_IS_BGR ( mpi - > imgfmt ) & & ! IMGFMT_IS_RGB ( mpi - > imgfmt ) ) {
assert ( 0 ) ; //should never happen
return VO_FALSE ;
}
2009-02-21 00:30:53 +00:00
2009-02-21 08:33:43 +00:00
if (
( ( mpi - > type ! = MP_IMGTYPE_STATIC ) & & ( mpi - > type ! = MP_IMGTYPE_TEMP ) ) | |
( mpi - > flags & MP_IMGFLAG_PLANAR ) | |
( mpi - > flags & MP_IMGFLAG_YUV )
)
2008-05-16 08:33:27 +00:00
return VO_FALSE ;
2003-03-20 01:45:40 +00:00
//reading from video memory is horribly slow
2009-02-21 08:33:43 +00:00
if ( ! ( mpi - > flags & MP_IMGFLAG_READABLE ) & & vo_directrendering & &
( mode_capabilities & CAP_LINEAR ) ) {
2003-09-21 23:59:49 +00:00
//find free page and reserve it
2009-02-21 08:33:43 +00:00
page = page_find_free ( ) ;
if ( page > = 0 ) {
PageStore [ page ] . locks = PAGE_BUSY ;
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 ;
mpi - > priv = ( void * ) page ;
mp_msg ( MSGT_VO , MSGL_DBG3 , " vo_svga: direct render allocated! page=%d \n " , page ) ;
return VO_TRUE ;
}
2002-04-18 15:41:33 +00:00
}
2009-02-21 08:33:43 +00:00
return VO_FALSE ;
2003-03-20 01:45:40 +00:00
}