typo fixes
[mplayer/greg.git] / libvo / vo_svga.c
blob6da2821e9336939bd0103da808ced03ad6041d0f
1 /*
3 Video driver for SVGAlib
4 by Zoltan Mark Vician <se7en@sch.bme.hu>
5 Code started: Mon Apr 1 23:25:47 2001
6 Some changes by Matan Ziv-Av <matan@svgalib.org>
7 Compleat rewrite by Ivan Kalvachev 19 Mar 2003:
9 Wrangings:
10 - 1bpp doesn't work right for me with '-double' and svgalib 1.4.3,
11 but works OK with svgalib 1.9.17
12 - The HW acceleration is not tested - svgalibs supports few chipsets,
13 and i don't have any of them. If it works for you then let me know.
14 I will remove this warning after confirm its status.
15 - retrace sync works only in doublebuffer mode.
16 - the retrace sync may slow down decoding a lot - mplayer is blocked while
17 waiting for retrace
18 - denoise3d fails to find common colorspace, use -vf denoise3d,scale
20 TODO:
21 - let choose_best_mode take aspect into account
22 - set palette from mpi->palette or mpi->plane[1]
23 - make faster OSD black bars clear - need some OSD changes
24 - Make nicer CONFIG parsing
25 - change video mode logical width to match img->stride[0] - for HW only
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
32 #include <vga.h>
34 #include <limits.h>
36 #include "config.h"
37 #include "video_out.h"
38 #include "video_out_internal.h"
39 #include "fastmemcpy.h"
40 #include "osdep/getch2.h"
41 #ifdef CONFIG_VIDIX
42 #include "vosub_vidix.h"
43 #endif
45 #include "sub.h"
47 #include "mp_msg.h"
48 #include "help_mp.h"
49 //#include "mp_image.h"
51 #include <assert.h>
53 //silence warnings, probably it have to go in some global header
54 #define UNUSED(x) ((void)(x))
57 static int query_format(uint32_t format);
58 static void draw_alpha(int x0, int y0, int w, int h, unsigned char *src,
59 unsigned char *srca, int stride);
60 static uint32_t get_image(mp_image_t *mpi);
62 #define MAXPAGES 16
63 #define PAGE_EMPTY 0
64 #define PAGE_BUSY 1
66 #define CAP_ACCEL_CLEAR 8
67 #define CAP_ACCEL_PUTIMAGE 4
68 #define CAP_ACCEL_BACKGR 2
69 #define CAP_LINEAR 1
71 static uint8_t zerobuf[8192];//used when clear screen with vga_draw
73 static int squarepix;
74 static int force_vm=0;
75 static int force_native=0;
76 static int sync_flip=0;
77 static int blackbar_osd=0;
78 static int cpage,max_pages,old_page;
80 static vga_modeinfo * modeinfo;
81 static int mode_stride; //keep it in case of vga_setlogicalwidth
82 static int stride_granularity; //not yet used
83 static int mode_bpp;
84 static int mode_capabilities;
86 static int image_width,image_height; // used by OSD
87 static int x_pos, y_pos;
89 static struct {
90 int yoffset;//y position of the page
91 int doffset;//display start of the page
92 void * vbase;//memory start address of the page
93 int locks;
94 }PageStore[MAXPAGES];
96 static vo_info_t info = {
97 "SVGAlib",
98 "svga",
99 "Ivan Kalvachev <iive@users.sf.net>",
103 #ifdef CONFIG_VIDIX
104 static char vidix_name[32] = "";
105 static vidix_grkey_t gr_key;
106 #endif
108 LIBVO_EXTERN(svga)
111 //return number of 1'st free page or -1 if no free one
112 static inline int page_find_free(){
113 int i;
114 for(i=0;i<max_pages;i++)
115 if(PageStore[i].locks == PAGE_EMPTY) return i;
116 return -1;
119 static int preinit(const char *arg)
121 int i;
122 char s[64];
124 getch2_disable();
125 memset(zerobuf,0,sizeof(zerobuf));
126 force_vm=force_native=squarepix=0;
127 sync_flip=vo_vsync;
128 blackbar_osd=0;
130 if(arg)while(*arg) {
131 #ifdef CONFIG_VIDIX
132 if(memcmp(arg,"vidix",5)==0) {
133 i=6;
134 while(arg[i] && arg[i]!=':') i++;
135 strncpy(vidix_name, arg+6, i-6);
136 vidix_name[i-5]=0;
137 if(arg[i]==':')i++;
138 arg+=i;
139 vidix_preinit(vidix_name, &video_out_svga);
141 #endif
142 if(!strncmp(arg,"sq",2)) {
143 squarepix=1;
144 arg+=2;
145 if( *arg == ':' ) arg++;
148 if(!strncmp(arg,"native",6)) {
149 force_native=1;
150 arg+=6;
151 if( *arg == ':' ) arg++;
154 if(!strncmp(arg,"bbosd",5)) {
155 blackbar_osd=1;
156 arg+=5;
157 if( *arg == ':' ) arg++;
160 if(!strncmp(arg,"retrace",7)) {
161 sync_flip=1;
162 arg+=7;
163 if( *arg == ':' ) arg++;
166 if(*arg) {
167 i=0;
168 while(arg[i] && arg[i]!=':')i++;
169 if(i<64){
170 strncpy(s, arg, i);
171 s[i]=0;
173 force_vm=vga_getmodenumber(s);
174 if(force_vm>0) {
175 if( mp_msg_test(MSGT_VO,MSGL_V) ) mp_msg(MSGT_VO,MSGL_V, "vo_svga: Forcing mode %i\n",force_vm);
176 }else{
177 force_vm = 0;
180 arg+=i;
181 if(*arg==':')arg++;
185 vga_init();
186 return 0;
189 static void svga_clear_box(int x,int y,int w,int h){
190 uint8_t * rgbplane;
191 int i;
193 if (mode_capabilities&CAP_ACCEL_CLEAR){
194 if( mp_msg_test(MSGT_VO,MSGL_DBG3) )
195 mp_msg(MSGT_VO,MSGL_DBG3, "vo_svga: clearing box %d,%d - %d,%d with HW acceleration\n",
196 x,y,w,h);
197 if(mode_capabilities&CAP_ACCEL_BACKGR)
198 vga_accel(ACCEL_SYNC);
199 vga_accel(ACCEL_SETFGCOLOR,0);//black
200 vga_accel(ACCEL_FILLBOX,x,y,w,h);
201 return;
203 if (mode_capabilities & CAP_LINEAR){
204 if( mp_msg_test(MSGT_VO,MSGL_DBG3) )
205 mp_msg(MSGT_VO,MSGL_DBG3, "vo_svga: clearing box %d,%d - %d,%d with memset\n",x,y,w,h);
206 rgbplane=PageStore[0].vbase + (y*mode_stride) + (x*modeinfo->bytesperpixel);
207 for(i=0;i<h;i++){
208 //i'm afraid that memcpy is better optimized than memset;)
209 memcpy(rgbplane,zerobuf,w*modeinfo->bytesperpixel);
210 // memset(rgbplane,0,w*modeinfo->bytesperpixel);
211 rgbplane+=mode_stride;
213 return;
215 //native
216 if( mp_msg_test(MSGT_VO,MSGL_DBG3) )
217 mp_msg(MSGT_VO,MSGL_DBG3, "vo_svga: clearing box %d,%d - %d,%d with native draw \n",x,y,w,h);
218 if(modeinfo->bytesperpixel!=0) w*=modeinfo->bytesperpixel;
219 for(i=0;i<h;i++){
220 vga_drawscansegment(zerobuf,x,y+i,w);
224 static uint32_t svga_draw_image(mp_image_t *mpi){
225 int i,x,y,w,h;
226 int stride;
227 uint8_t *rgbplane, *base;
228 int bytesperline;
229 int page;
231 if(mpi->flags & MP_IMGFLAG_DIRECT){
232 if( mp_msg_test(MSGT_VO,MSGL_DBG3) )
233 mp_msg(MSGT_VO,MSGL_DBG3, "vo_svga: drawing direct rendered surface\n");
234 cpage=(uint32_t)mpi->priv;
235 assert((cpage>=0)&&(cpage<max_pages));
236 return VO_TRUE; //it's already done
238 // if (mpi->flags&MP_IMGFLAGS_DRAWBACK)
239 // return VO_TRUE;//direct render method 2
241 //find a free page to draw into
242 //if there is no one then use the current one
243 page = page_find_free();
244 if(page>=0) cpage=page;
245 PageStore[cpage].locks=PAGE_BUSY;
247 // these variables are used in loops
248 x = mpi->x;
249 y = mpi->y;
250 w = mpi->w;
251 h = mpi->h;
252 stride = mpi->stride[0];
253 rgbplane = mpi->planes[0] + y*stride + (x*mpi->bpp)/8;
254 x+=x_pos;//center
255 y+=y_pos;
257 if(mpi->bpp >= 8){//for modes<8 use only native
258 if( (mode_capabilities&CAP_ACCEL_PUTIMAGE) && (x==0) && (w==mpi->width) &&
259 (stride == mode_stride) ){ //only monolite image can be accelerated
260 w=(stride*8)/mpi->bpp;//we transfer pixels in the stride so the source
261 //ACCELERATE
262 if( mp_msg_test(MSGT_VO,MSGL_DBG3) )
263 mp_msg(MSGT_VO,MSGL_DBG3, "vo_svga: using HW PutImage (x=%d,y=%d,w=%d,h=%d)\n",x,y,w,h);
264 if(mode_capabilities & CAP_ACCEL_BACKGR)
265 vga_accel(ACCEL_SYNC);
267 vga_accel(ACCEL_PUTIMAGE,x,y+PageStore[cpage].yoffset,w,h,rgbplane);
268 return VO_TRUE;
271 if( mode_capabilities&CAP_LINEAR){
272 //DIRECT
273 if( mp_msg_test(MSGT_VO,MSGL_DBG3) )
274 mp_msg(MSGT_VO,MSGL_DBG3, "vo_svga: using Direct memcpy (x=%d,y=%d,w=%d,h=%d)\n",x,y,w,h);
275 bytesperline=(w*mpi->bpp)/8;
276 base=PageStore[cpage].vbase + (y*mode_stride) + (x*mpi->bpp)/8;
278 for(i=0;i<h;i++){
279 mem2agpcpy(base,rgbplane,bytesperline);
280 base+=mode_stride;
281 rgbplane+=stride;
283 return VO_TRUE;
285 }//(modebpp>=8
288 //NATIVE
290 int length;
291 length=(w*mpi->bpp)/8;
292 //one byte per pixel! svgalib innovation
293 if(mpi->imgfmt==IMGFMT_RG4B || mpi->imgfmt==IMGFMT_BG4B) length=w;
295 if( mp_msg_test(MSGT_VO,MSGL_DBG3) )
296 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);
297 y+=PageStore[cpage].yoffset;//y position of the page beggining
298 for(i=0;i<h;i++){
299 vga_drawscansegment(rgbplane,x,y+i,length);
300 rgbplane+=stride;
303 return VO_TRUE;
306 int bpp_from_vminfo(vga_modeinfo *vminfo){
307 switch(vminfo->colors){
308 case 2: return 1;
309 case 16: return 4;
310 case 256: return 8;
311 case 32768: return 15;
312 case 65536: return 16;
313 case 1<<24: return 8*vminfo->bytesperpixel;
315 return 0;
318 int find_best_svga_mode(int req_w,int req_h, int req_bpp){
319 int badness,prev_badness;
320 int bestmode,lastmode;
321 int i;
322 vga_modeinfo *vminfo;
323 //int best aspect mode // best linear mode // best normal mode (no modeX)
325 prev_badness = 0;//take care of special case below
326 bestmode = 0; //0 is the TEXT mode
327 lastmode = vga_lastmodenumber();
328 for(i=1;i<=lastmode;i++){
329 vminfo = vga_getmodeinfo(i);
330 if( vminfo == NULL ) continue;
331 if( mp_msg_test(MSGT_VO,MSGL_DBG4) )
332 mp_msg(MSGT_VO,MSGL_DBG4, "vo_svga: testing mode %d (%s)\n",i,vga_getmodename(i));
333 if( vga_hasmode(i) == 0 ) continue;
334 if( req_bpp != bpp_from_vminfo(vminfo) )continue;
335 if( (vminfo->width < req_w) || (vminfo->height < req_h) ) continue;
336 badness=(vminfo->width * vminfo->height) - (req_h * req_w);
337 //put here aspect calculations
338 if(squarepix)
339 if( vminfo->width*3 != vminfo->height*4 ) continue;
341 if( bestmode==0 || prev_badness >= badness ){//modeX etc...
342 prev_badness=badness;
343 bestmode=i;
344 if( mp_msg_test(MSGT_VO,MSGL_DBG4) )
345 mp_msg(MSGT_VO,MSGL_DBG4, "vo_svga: found good mode %d with badness %d\n",i,badness);
348 return bestmode;
351 static int control(uint32_t request, void *data, ...)
353 switch (request) {
354 case VOCTRL_QUERY_FORMAT:
355 return query_format(*((uint32_t*)data));
356 case VOCTRL_DRAW_IMAGE:
357 return svga_draw_image( (mp_image_t *)data);
358 case VOCTRL_GET_IMAGE:
359 return get_image(data);
362 #ifdef CONFIG_VIDIX
363 if (vidix_name) {
364 switch (request) {
365 case VOCTRL_SET_EQUALIZER:
367 va_list ap;
368 int value;
370 va_start(ap, data);
371 value = va_arg(ap, int);
372 va_end(ap);
374 return vidix_control(request, data, (int *)value);
376 case VOCTRL_GET_EQUALIZER:
378 va_list ap;
379 int *value;
381 va_start(ap, data);
382 value = va_arg(ap, int*);
383 va_end(ap);
385 return vidix_control(request, data, value);
388 return vidix_control(request, data);
390 #endif
392 return VO_NOTIMPL;
396 // This function is called to init the video driver for specific mode
398 static int config(uint32_t width, uint32_t height, uint32_t d_width,
399 uint32_t d_height, uint32_t flags, char *title,
400 uint32_t format) {
401 int32_t req_w = width;// (d_width > 0 ? d_width : width);
402 int32_t req_h = height;// (d_height > 0 ? d_height : height);
403 uint16_t vid_mode = 0;
404 int32_t req_bpp;
406 uint32_t accflags;
407 if( mp_msg_test(MSGT_VO,MSGL_V) )
408 mp_msg(MSGT_VO,MSGL_V, "vo_svga: config(%i, %i, %i, %i, %08x, %s, %08x)\n", width, height,
409 d_width, d_height, flags, title, format);
410 //Only RGB modes supported
411 if (!IMGFMT_IS_RGB(format) && !IMGFMT_IS_BGR(format)) {assert(0);return -1;}
412 req_bpp = IMGFMT_BGR_DEPTH(format);
414 if( vo_dbpp!=0 && vo_dbpp!=req_bpp) {assert(0);return-1;}
416 if(!force_vm) {
417 if ( mp_msg_test(MSGT_VO,MSGL_V) ) {
418 mp_msg(MSGT_VO,MSGL_V, "vo_svga: Looking for the best resolution...\n");
419 mp_msg(MSGT_VO,MSGL_V, "vo_svga: req_w: %d, req_h: %d, bpp: %d\n",req_w,req_h,req_bpp);
421 vid_mode=find_best_svga_mode(req_w,req_h,req_bpp);
422 if(vid_mode==0)
423 return 1;
424 modeinfo=vga_getmodeinfo(vid_mode);
425 }else{//force_vm
426 vid_mode=force_vm;
427 if(vga_hasmode(vid_mode) == 0){
428 mp_msg(MSGT_VO,MSGL_ERR, MSGTR_LIBVO_SVGA_ForcedVidmodeNotAvailable,
429 vid_mode,vga_getmodename(vid_mode));
430 return 1; //error;
432 modeinfo=vga_getmodeinfo(vid_mode);
433 if( (modeinfo->width < req_w) || (modeinfo->height < req_h) ){
434 mp_msg(MSGT_VO,MSGL_ERR, MSGTR_LIBVO_SVGA_ForcedVidmodeTooSmall,
435 vid_mode,vga_getmodename(vid_mode));
436 return 1;
439 mode_bpp=bpp_from_vminfo(modeinfo);
441 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_SVGA_Vidmode,
442 vid_mode,modeinfo->width,modeinfo->height,mode_bpp);
444 if (vga_setmode(vid_mode) == -1) {
445 mp_msg(MSGT_VO,MSGL_ERR, MSGTR_LIBVO_SVGA_VgasetmodeFailed,vid_mode);
446 uninit();
447 return 1; // error
449 /* set 332 palette for 8 bpp */
450 if(mode_bpp==8){
451 int i;
452 for(i=0; i<256; i++)
453 vga_setpalette(i, ((i>>5)&7)*9, ((i>>2)&7)*9, (i&3)*21);
455 /* set 121 palette for 4 bpp */
456 else if(mode_bpp==4){
457 int i;
458 for(i=0; i<16; i++)
459 vga_setpalette(i, ((i>>3)&1)*63, ((i>>1)&3)*21, (i&1)*63);
461 //if we change the logical width, we should know the granularity
462 stride_granularity=8;//according to man vga_logicalwidth
463 if(modeinfo->flags & EXT_INFO_AVAILABLE){
464 stride_granularity=modeinfo->linewidth_unit;
466 //look for hardware acceleration
467 mode_capabilities=0;//NATIVE;
468 if(!force_native){//if we want to use only native drawers
469 if(modeinfo->flags & HAVE_EXT_SET){//support for hwaccel interface
470 accflags=vga_ext_set(VGA_EXT_AVAILABLE,VGA_AVAIL_ACCEL);
471 if(accflags & ACCELFLAG_FILLBOX) // clear screen
472 mode_capabilities|=CAP_ACCEL_CLEAR;
473 if(accflags & ACCELFLAG_PUTIMAGE)//support for mem->vid transfer
474 mode_capabilities|=CAP_ACCEL_PUTIMAGE;
475 if((accflags & ACCELFLAG_SETMODE) && (accflags & ACCELFLAG_SYNC)){
476 vga_accel(ACCEL_SETMODE,BLITS_IN_BACKGROUND);
477 mode_capabilities|=CAP_ACCEL_BACKGR;//can draw in backgraund
480 if(modeinfo->flags & IS_LINEAR){
481 mode_capabilities|=CAP_LINEAR; //don't use bank & vga_draw
483 else{
484 if(modeinfo->flags & CAPABLE_LINEAR){
485 int vid_mem_size;
486 vid_mem_size = vga_setlinearaddressing();
487 if(vid_mem_size != -1){
488 modeinfo=vga_getmodeinfo(vid_mode);//sometimes they change parameters
489 mode_capabilities|=CAP_LINEAR;
493 }//fi force native
494 if(mode_capabilities&CAP_LINEAR){
495 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_SVGA_VideoModeIsLinearAndMemcpyCouldBeUsed);
497 if(mode_capabilities&CAP_ACCEL_PUTIMAGE){
498 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_SVGA_VideoModeHasHardwareAcceleration);
499 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_SVGA_IfItWorksForYouIWouldLikeToKnow);
502 //here is the place to handle strides for accel_ modes;
503 mode_stride=modeinfo->linewidth;
504 //we may try to set a bigger stride for video mode that will match the mpi->stride,
505 //this way we will transfer more data, but HW put_image can do it in backgraund!
507 //now let's see how many pages we can use
508 max_pages = modeinfo->maxpixels/(modeinfo->height * modeinfo->width);
509 if(max_pages > MAXPAGES) max_pages = MAXPAGES;
510 if(!vo_doublebuffering) max_pages=1;
511 //fill PageStore structs
513 int i;
514 uint8_t * GRAPH_MEM;
515 int dof;
516 GRAPH_MEM=vga_getgraphmem();
517 for(i=0;i<max_pages;i++){
518 //calculate display offset
519 dof = i * modeinfo->height * modeinfo->width;
520 if(modeinfo->bytesperpixel != 0) dof*=modeinfo->bytesperpixel;
521 //check video chip limitations
522 if( dof != (dof & modeinfo->startaddressrange) ){
523 max_pages=i;//page 0 will never come here
524 break;
526 PageStore[i].yoffset = i * modeinfo->height;//starting y offset
527 PageStore[i].vbase = GRAPH_MEM + i*modeinfo->height*mode_stride; //memory base address
528 PageStore[i].doffset = dof; //display offset
529 PageStore[i].locks = PAGE_EMPTY;
532 assert(max_pages>0);
533 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_SVGA_VideoModeHas,max_pages);
534 //15bpp
535 if(modeinfo->bytesperpixel!=0)
536 vga_claimvideomemory(max_pages * modeinfo->height * modeinfo->width * modeinfo->bytesperpixel);
537 else
538 vga_claimvideomemory(max_pages * modeinfo->height * modeinfo->width * mode_bpp / 8);
540 cpage=old_page=0;
541 svga_clear_box(0,0,modeinfo->width,modeinfo->height * max_pages);
543 image_height=req_h;
544 image_width=req_w;
545 x_pos = (modeinfo->width - req_w) / 2;
546 y_pos = (modeinfo->height - req_h) / 2;
547 x_pos &= ~(15); //align x offset position to 16 pixels
548 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_SVGA_CenteringImageStartAt,x_pos,y_pos);
550 #ifdef CONFIG_VIDIX
552 if(vidix_name[0]){
553 vidix_init(width, height, x_pos, y_pos, modeinfo->width, modeinfo->height,
554 format, mode_bpp, modeinfo->width,modeinfo->height);
555 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_SVGA_UsingVidix,width,height,
556 modeinfo->width,modeinfo->height);
557 vidix_start();
558 /*set colorkey*/
559 if(vidix_grkey_support()){
560 vidix_grkey_get(&gr_key);
561 gr_key.key_op = KEYS_PUT;
562 if (!(vo_colorkey & 0xFF000000)) {
563 gr_key.ckey.op = CKEY_TRUE;
564 gr_key.ckey.red = (vo_colorkey & 0x00FF0000) >> 16;
565 gr_key.ckey.green = (vo_colorkey & 0x0000FF00) >> 8;
566 gr_key.ckey.blue = vo_colorkey & 0x000000FF;
567 } else
568 gr_key.ckey.op = CKEY_FALSE;
569 vidix_grkey_set(&gr_key);
572 #endif
574 vga_setdisplaystart(0);
575 return (0);
578 static int draw_slice(uint8_t *image[],int stride[],
579 int w, int h, int x, int y) {
580 assert(0);
581 UNUSED(image);UNUSED(stride);
582 UNUSED(w);UNUSED(h);
583 UNUSED(x);UNUSED(y);
585 return VO_ERROR;//this is yv12 only -> vf_scale should do all transforms
588 static int draw_frame(uint8_t *src[]) {
589 assert(0);
590 UNUSED(src);
591 return VO_ERROR;//this one should not be called
594 static void draw_osd(void)
596 if( mp_msg_test(MSGT_VO,MSGL_DBG4) )
597 mp_msg(MSGT_VO,MSGL_DBG4, "vo_svga: draw_osd()\n");
598 //only modes with bytesperpixel>0 can draw OSD
599 if(modeinfo->bytesperpixel==0) return;
600 if(!(mode_capabilities&CAP_LINEAR)) return;//force_native will remove OSD
602 if(blackbar_osd){
603 //111
604 //3 4
605 //222
606 svga_clear_box(0,0 + PageStore[cpage].yoffset,
607 modeinfo->width, y_pos);
608 svga_clear_box(0, image_height + y_pos + PageStore[cpage].yoffset,
609 modeinfo->width, modeinfo->height-(image_height+ y_pos));
610 svga_clear_box(0, y_pos + PageStore[cpage].yoffset,
611 x_pos, image_height);
612 svga_clear_box(image_width + x_pos, y_pos + PageStore[cpage].yoffset,
613 modeinfo->width-(x_pos+image_width), image_height);
614 // vo_remove_text(modeinfo->width, modeinfo->height, clear_alpha);
615 vo_draw_text(modeinfo->width, modeinfo->height, draw_alpha);
616 }else{
617 vo_draw_text(image_width, image_height, draw_alpha);
621 static void flip_page(void) {
622 PageStore[old_page].locks=PAGE_EMPTY;
623 PageStore[cpage].locks=PAGE_BUSY;
625 if( mp_msg_test(MSGT_VO,MSGL_DBG3) )
626 mp_msg(MSGT_VO,MSGL_DBG3, "vo_svga: viewing page %d\n",cpage);
627 if(sync_flip && old_page!=cpage){
628 if( mp_msg_test(MSGT_VO,MSGL_DBG3) ) mp_msg(MSGT_VO,MSGL_DBG3, "vo_svga:vga_waitretrace\n");
629 vga_waitretrace();
631 vga_setdisplaystart(PageStore[cpage].doffset);
633 old_page=cpage;//cpage will be overwriten on next draw_image
636 static void check_events(void) {
639 static void uninit(void) {
641 #ifdef CONFIG_VIDIX
642 if(vidix_name[0])vidix_term();
643 #endif
644 vga_setmode(TEXT);
647 /* --------------------------------------------------------------------- */
648 static int query_format(uint32_t format) {
649 int32_t req_bpp,flags;
650 int i,lastmode;
651 vga_modeinfo * vminfo;
653 if ( mp_msg_test(MSGT_VO,MSGL_DBG4) )
654 mp_msg(MSGT_VO,MSGL_DBG4, "vo_svga: query_format=%X \n",format);
655 //only RGB modes supported
656 if( (!IMGFMT_IS_RGB(format)) && (!IMGFMT_IS_BGR(format)) ) return 0;
658 // Reject different endian
659 #ifdef WORDS_BIGENDIAN
660 if (IMGFMT_IS_BGR(format)) return 0;
661 #else
662 if (IMGFMT_IS_RGB(format)) return 0;
663 #endif
665 //svgalib supports only BG4B! if we want BGR4 we have to emulate it (sw)
666 if( format==IMGFMT_BGR4 || format==IMGFMT_RGB4) return 0;
667 req_bpp = IMGFMT_RGB_DEPTH(format);
668 if( vo_dbpp>0 && vo_dbpp!=req_bpp ) return 0; //support -bpp options
669 //scan all modes
670 lastmode = vga_lastmodenumber();
671 for(i=1;i<=lastmode;i++){
672 vminfo = vga_getmodeinfo(i);
673 if( vminfo == NULL ) continue;
674 if( vga_hasmode(i) == 0 ) continue;
675 if( req_bpp != bpp_from_vminfo(vminfo) ) continue;
676 if( (force_vm > 0) && (force_vm != i) ) continue;//quick hack
677 flags = VFCAP_CSP_SUPPORTED|
678 VFCAP_CSP_SUPPORTED_BY_HW|
679 VFCAP_ACCEPT_STRIDE|
681 if(req_bpp>8) flags|=VFCAP_OSD;
682 return flags;
684 return 0;
687 static void draw_alpha(int x0, int y0, int w, int h, unsigned char *src,
688 unsigned char *srca, int stride) {
689 char* base;
691 if( mp_msg_test(MSGT_VO,MSGL_DBG3) )
692 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",
693 x0,y0,w,h,src,srca,stride);
694 if(!blackbar_osd) {
695 //drawing in the image, so place the stuff there
696 x0+=x_pos;
697 y0+=y_pos;
700 if( mp_msg_test(MSGT_VO,MSGL_DBG4) )
701 mp_msg(MSGT_VO,MSGL_DBG4, "vo_svga: OSD draw in page %d\n",cpage);
702 base=PageStore[cpage].vbase + y0*mode_stride + x0*modeinfo->bytesperpixel;
703 switch (mode_bpp) {
704 case 32:
705 vo_draw_alpha_rgb32(w, h, src, srca, stride, base, mode_stride);
706 break;
707 case 24:
708 vo_draw_alpha_rgb24(w, h, src, srca, stride, base, mode_stride);
709 break;
710 case 16:
711 vo_draw_alpha_rgb16(w, h, src, srca, stride, base, mode_stride);
712 break;
713 case 15:
714 vo_draw_alpha_rgb15(w, h, src, srca, stride, base, mode_stride);
715 break;
719 static uint32_t get_image(mp_image_t *mpi){
720 int page;
722 if(!IMGFMT_IS_BGR(mpi->imgfmt) && !IMGFMT_IS_RGB(mpi->imgfmt) ){
723 assert(0);//should never happen
724 return(VO_FALSE);
727 if (
728 ( (mpi->type != MP_IMGTYPE_STATIC) && (mpi->type != MP_IMGTYPE_TEMP)) ||
729 (mpi->flags & MP_IMGFLAG_PLANAR) ||
730 (mpi->flags & MP_IMGFLAG_YUV)
732 return(VO_FALSE);
734 //reading from video memory is horribly slow
735 if( !(mpi->flags & MP_IMGFLAG_READABLE) && vo_directrendering &&
736 (mode_capabilities & CAP_LINEAR) ){
738 //find free page and reserve it
739 page=page_find_free();
740 if(page >= 0){
741 PageStore[page].locks=PAGE_BUSY;
743 mpi->flags |= MP_IMGFLAG_DIRECT;
744 mpi->stride[0] = mode_stride;
745 mpi->planes[0] = PageStore[page].vbase +
746 y_pos*mode_stride + (x_pos*mpi->bpp)/8;
747 mpi->priv=(void *)page;
748 if( mp_msg_test(MSGT_VO,MSGL_DBG3) )
749 mp_msg(MSGT_VO,MSGL_DBG3, "vo_svga: direct render allocated! page=%d\n",page);
750 return(VO_TRUE);
754 return(VO_FALSE);