vo_glamo: sub.h was moved to sub directory in c9026cb3210205b07e2e068467a18ee40f9259a3
[mplayer/glamo.git] / libvo / vo_svga.c
blobd44821df05876cd9f82595c49763b5e6e5eb125d
1 /*
2 * video driver for SVGAlib
3 * by Zoltan Mark Vician <se7en@sch.bme.hu>
4 * Code started: Mon Apr 1 23:25:47 2001
5 * Some changes by Matan Ziv-Av <matan@svgalib.org>
6 * complete rewrite by Ivan Kalvachev 19 Mar 2003
8 * This file is part of MPlayer.
10 * MPlayer is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * MPlayer is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License along
21 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 Wrangings:
27 - 1bpp doesn't work right for me with '-double' and svgalib 1.4.3,
28 but works OK with svgalib 1.9.17
29 - The HW acceleration is not tested - svgalibs supports few chipsets,
30 and i don't have any of them. If it works for you then let me know.
31 I will remove this warning after confirm its status.
32 - retrace sync works only in doublebuffer mode.
33 - the retrace sync may slow down decoding a lot - mplayer is blocked while
34 waiting for retrace
35 - denoise3d fails to find common colorspace, use -vf denoise3d,scale
37 TODO:
38 - let choose_best_mode take aspect into account
39 - set palette from mpi->palette or mpi->plane[1]
40 - make faster OSD black bars clear - need some OSD changes
41 - Make nicer CONFIG parsing
42 - change video mode logical width to match img->stride[0] - for HW only
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
49 #include <vga.h>
51 #include <limits.h>
53 #include "config.h"
54 #include "video_out.h"
55 #include "video_out_internal.h"
56 #include "fastmemcpy.h"
57 #include "osdep/getch2.h"
58 #ifdef CONFIG_VIDIX
59 #include "vosub_vidix.h"
60 #endif
62 #include "sub/sub.h"
64 #include "mp_msg.h"
65 //#include "mp_image.h"
67 #include <assert.h>
70 static void draw_alpha(int x0, int y0, int w, int h, unsigned char *src,
71 unsigned char *srca, int stride);
72 static uint32_t get_image(mp_image_t *mpi);
74 #define MAXPAGES 16
75 #define PAGE_EMPTY 0
76 #define PAGE_BUSY 1
78 #define CAP_ACCEL_CLEAR 8
79 #define CAP_ACCEL_PUTIMAGE 4
80 #define CAP_ACCEL_BACKGR 2
81 #define CAP_LINEAR 1
83 static uint8_t zerobuf[8192];//used when clear screen with vga_draw
85 static int squarepix;
86 static int force_vm=0;
87 static int force_native=0;
88 static int sync_flip=0;
89 static int blackbar_osd=0;
90 static int cpage,max_pages,old_page;
92 static vga_modeinfo * modeinfo;
93 static int mode_stride; //keep it in case of vga_setlogicalwidth
94 static int stride_granularity; //not yet used
95 static int mode_bpp;
96 static int mode_capabilities;
98 static int image_width,image_height; // used by OSD
99 static int x_pos, y_pos;
101 static struct {
102 int yoffset;//y position of the page
103 int doffset;//display start of the page
104 uint8_t * vbase;//memory start address of the page
105 int locks;
106 }PageStore[MAXPAGES];
108 static const vo_info_t info = {
109 "SVGAlib",
110 "svga",
111 "Ivan Kalvachev <iive@users.sf.net>",
115 #ifdef CONFIG_VIDIX
116 static char vidix_name[32] = "";
117 static vidix_grkey_t gr_key;
118 #endif
120 LIBVO_EXTERN(svga)
123 //return number of 1'st free page or -1 if no free one
124 static inline int page_find_free(void){
125 int i;
126 for(i=0;i<max_pages;i++)
127 if(PageStore[i].locks == PAGE_EMPTY) return i;
128 return -1;
131 static int preinit(const char *arg)
133 int i,rez;
134 char s[64];
136 getch2_disable();
137 memset(zerobuf,0,sizeof(zerobuf));
138 force_vm=force_native=squarepix=0;
139 sync_flip=vo_vsync;
140 blackbar_osd=0;
142 if(arg)while(*arg) {
143 #ifdef CONFIG_VIDIX
144 if(memcmp(arg,"vidix",5)==0) {
145 i=6;
146 while(arg[i] && arg[i]!=':') i++;
147 strncpy(vidix_name, arg+6, i-6);
148 vidix_name[i-5]=0;
149 if(arg[i]==':')i++;
150 arg+=i;
151 vidix_preinit(vidix_name, video_out_svga.old_functions);
153 #endif
154 if(!strncmp(arg,"sq",2)) {
155 squarepix=1;
156 arg+=2;
157 if( *arg == ':' ) arg++;
160 if(!strncmp(arg,"native",6)) {
161 force_native=1;
162 arg+=6;
163 if( *arg == ':' ) arg++;
166 if(!strncmp(arg,"bbosd",5)) {
167 blackbar_osd=1;
168 arg+=5;
169 if( *arg == ':' ) arg++;
172 if(!strncmp(arg,"retrace",7)) {
173 sync_flip=1;
174 arg+=7;
175 if( *arg == ':' ) arg++;
178 if(*arg) {
179 i=0;
180 while(arg[i] && arg[i]!=':')i++;
181 if(i<64){
182 strncpy(s, arg, i);
183 s[i]=0;
185 force_vm=vga_getmodenumber(s);
186 if(force_vm>0) {
187 mp_msg(MSGT_VO,MSGL_V, "vo_svga: Forcing mode %i\n",force_vm);
188 }else{
189 force_vm = 0;
192 arg+=i;
193 if(*arg==':')arg++;
197 rez = vga_init();
198 if(rez != 0){
199 mp_msg(MSGT_VO,MSGL_ERR, "vo_svga: vga_init() returned error=%d\n",rez);
201 return !!rez;
204 static void svga_clear_box(int x,int y,int w,int h){
205 uint8_t * rgbplane;
206 int i;
208 if (mode_capabilities&CAP_ACCEL_CLEAR){
209 mp_msg(MSGT_VO,MSGL_DBG3, "vo_svga: clearing box %d,%d - %d,%d with HW acceleration\n",
210 x,y,w,h);
211 if(mode_capabilities&CAP_ACCEL_BACKGR)
212 vga_accel(ACCEL_SYNC);
213 vga_accel(ACCEL_SETFGCOLOR,0);//black
214 vga_accel(ACCEL_FILLBOX,x,y,w,h);
215 return;
217 if (mode_capabilities & CAP_LINEAR){
218 mp_msg(MSGT_VO,MSGL_DBG3, "vo_svga: clearing box %d,%d - %d,%d with memset\n",x,y,w,h);
219 rgbplane=PageStore[0].vbase + (y*mode_stride) + (x*modeinfo->bytesperpixel);
220 for(i=0;i<h;i++){
221 //i'm afraid that memcpy is better optimized than memset;)
222 fast_memcpy(rgbplane,zerobuf,w*modeinfo->bytesperpixel);
223 // memset(rgbplane,0,w*modeinfo->bytesperpixel);
224 rgbplane+=mode_stride;
226 return;
228 //native
229 mp_msg(MSGT_VO,MSGL_DBG3, "vo_svga: clearing box %d,%d - %d,%d with native draw \n",x,y,w,h);
230 if(modeinfo->bytesperpixel!=0) w*=modeinfo->bytesperpixel;
231 for(i=0;i<h;i++){
232 vga_drawscansegment(zerobuf,x,y+i,w);
236 static uint32_t svga_draw_image(mp_image_t *mpi){
237 int i,x,y,w,h;
238 int stride;
239 uint8_t *rgbplane, *base;
240 int bytesperline;
241 int page;
243 if(mpi->flags & MP_IMGFLAG_DIRECT){
244 mp_msg(MSGT_VO,MSGL_DBG3, "vo_svga: drawing direct rendered surface\n");
245 cpage=(uint32_t)mpi->priv;
246 assert((cpage>=0)&&(cpage<max_pages));
247 return VO_TRUE; //it's already done
249 // if (mpi->flags&MP_IMGFLAGS_DRAWBACK)
250 // return VO_TRUE;//direct render method 2
252 //find a free page to draw into
253 //if there is no one then use the current one
254 page = page_find_free();
255 if(page>=0) cpage=page;
256 PageStore[cpage].locks=PAGE_BUSY;
258 // these variables are used in loops
259 x = mpi->x;
260 y = mpi->y;
261 w = mpi->w;
262 h = mpi->h;
263 stride = mpi->stride[0];
264 rgbplane = mpi->planes[0] + y*stride + (x*mpi->bpp)/8;
265 x+=x_pos;//center
266 y+=y_pos;
268 if(mpi->bpp >= 8){//for modes<8 use only native
269 if( (mode_capabilities&CAP_ACCEL_PUTIMAGE) && (x==0) && (w==mpi->width) &&
270 (stride == mode_stride) ){ //only monolite image can be accelerated
271 w=(stride*8)/mpi->bpp;//we transfer pixels in the stride so the source
272 //ACCELERATE
273 mp_msg(MSGT_VO,MSGL_DBG3, "vo_svga: using HW PutImage (x=%d,y=%d,w=%d,h=%d)\n",x,y,w,h);
274 if(mode_capabilities & CAP_ACCEL_BACKGR)
275 vga_accel(ACCEL_SYNC);
277 vga_accel(ACCEL_PUTIMAGE,x,y+PageStore[cpage].yoffset,w,h,rgbplane);
278 return VO_TRUE;
281 if( mode_capabilities&CAP_LINEAR){
282 //DIRECT
283 mp_msg(MSGT_VO,MSGL_DBG3, "vo_svga: using Direct memcpy (x=%d,y=%d,w=%d,h=%d)\n",x,y,w,h);
284 bytesperline=(w*mpi->bpp)/8;
285 base=PageStore[cpage].vbase + (y*mode_stride) + (x*mpi->bpp)/8;
287 for(i=0;i<h;i++){
288 mem2agpcpy(base,rgbplane,bytesperline);
289 base+=mode_stride;
290 rgbplane+=stride;
292 return VO_TRUE;
294 }//(modebpp>=8
297 //NATIVE
299 int length;
300 length=(w*mpi->bpp)/8;
301 //one byte per pixel! svgalib innovation
302 if(mpi->imgfmt==IMGFMT_RG4B || mpi->imgfmt==IMGFMT_BG4B) length=w;
304 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);
305 y+=PageStore[cpage].yoffset;//y position of the page beggining
306 for(i=0;i<h;i++){
307 vga_drawscansegment(rgbplane,x,y+i,length);
308 rgbplane+=stride;
311 return VO_TRUE;
314 static int bpp_from_vminfo(vga_modeinfo *vminfo){
315 switch(vminfo->colors){
316 case 2: return 1;
317 case 16: return 4;
318 case 256: return 8;
319 case 32768: return 15;
320 case 65536: return 16;
321 case 1<<24: return 8*vminfo->bytesperpixel;
323 return 0;
326 static int find_best_svga_mode(int req_w,int req_h, int req_bpp){
327 int badness,prev_badness;
328 int bestmode,lastmode;
329 int i;
330 vga_modeinfo *vminfo;
331 //int best aspect mode // best linear mode // best normal mode (no modeX)
333 prev_badness = 0;//take care of special case below
334 bestmode = 0; //0 is the TEXT mode
335 lastmode = vga_lastmodenumber();
336 for(i=1;i<=lastmode;i++){
337 vminfo = vga_getmodeinfo(i);
338 if( vminfo == NULL ) continue;
339 mp_msg(MSGT_VO,MSGL_DBG4, "vo_svga: testing mode %d (%s)\n",i,vga_getmodename(i));
340 if( vga_hasmode(i) == 0 ) continue;
341 if( req_bpp != bpp_from_vminfo(vminfo) )continue;
342 if( (vminfo->width < req_w) || (vminfo->height < req_h) ) continue;
343 badness=(vminfo->width * vminfo->height) - (req_h * req_w);
344 //put here aspect calculations
345 if(squarepix)
346 if( vminfo->width*3 != vminfo->height*4 ) continue;
348 if( bestmode==0 || prev_badness >= badness ){//modeX etc...
349 prev_badness=badness;
350 bestmode=i;
351 mp_msg(MSGT_VO,MSGL_DBG4, "vo_svga: found good mode %d with badness %d\n",i,badness);
354 return bestmode;
357 static int control(uint32_t request, void *data)
359 switch (request) {
360 case VOCTRL_QUERY_FORMAT:
361 return query_format(*((uint32_t*)data));
362 case VOCTRL_DRAW_IMAGE:
363 return svga_draw_image( (mp_image_t *)data);
364 case VOCTRL_GET_IMAGE:
365 return get_image(data);
368 #ifdef CONFIG_VIDIX
369 if (vidix_name[0])
370 return vidix_control(request, data);
371 #endif
373 return VO_NOTIMPL;
377 // This function is called to init the video driver for specific mode
379 static int config(uint32_t width, uint32_t height, uint32_t d_width,
380 uint32_t d_height, uint32_t flags, char *title,
381 uint32_t format) {
382 int32_t req_w = width;// (d_width > 0 ? d_width : width);
383 int32_t req_h = height;// (d_height > 0 ? d_height : height);
384 uint16_t vid_mode = 0;
385 int32_t req_bpp;
387 uint32_t accflags;
388 mp_msg(MSGT_VO,MSGL_V, "vo_svga: config(%i, %i, %i, %i, %08x, %s, %08x)\n", width, height,
389 d_width, d_height, flags, title, format);
390 //Only RGB modes supported
391 if (!IMGFMT_IS_RGB(format) && !IMGFMT_IS_BGR(format)) {assert(0);return -1;}
392 req_bpp = IMGFMT_BGR_DEPTH(format);
394 if( vo_dbpp!=0 && vo_dbpp!=req_bpp) {assert(0);return-1;}
396 if(!force_vm) {
397 mp_msg(MSGT_VO,MSGL_V, "vo_svga: Looking for the best resolution...\n");
398 mp_msg(MSGT_VO,MSGL_V, "vo_svga: req_w: %d, req_h: %d, bpp: %d\n",req_w,req_h,req_bpp);
399 vid_mode=find_best_svga_mode(req_w,req_h,req_bpp);
400 if(vid_mode==0)
401 return 1;
402 modeinfo=vga_getmodeinfo(vid_mode);
403 }else{//force_vm
404 vid_mode=force_vm;
405 if(vga_hasmode(vid_mode) == 0){
406 mp_tmsg(MSGT_VO,MSGL_ERR, "[VO_SVGA] Forced vid_mode %d (%s) not available.\n",
407 vid_mode,vga_getmodename(vid_mode));
408 return 1; //error;
410 modeinfo=vga_getmodeinfo(vid_mode);
411 if( (modeinfo->width < req_w) || (modeinfo->height < req_h) ){
412 mp_tmsg(MSGT_VO,MSGL_ERR, "[VO_SVGA] Forced vid_mode %d (%s) too small.\n",
413 vid_mode,vga_getmodename(vid_mode));
414 return 1;
417 mode_bpp=bpp_from_vminfo(modeinfo);
419 mp_tmsg(MSGT_VO,MSGL_INFO, "[VO_SVGA] Vid_mode: %d, %dx%d %dbpp.\n",
420 vid_mode,modeinfo->width,modeinfo->height,mode_bpp);
422 if (vga_setmode(vid_mode) == -1) {
423 mp_tmsg(MSGT_VO,MSGL_ERR, "[VO_SVGA] Vga_setmode(%d) failed.\n",vid_mode);
424 uninit();
425 return 1; // error
427 /* set 332 palette for 8 bpp */
428 if(mode_bpp==8){
429 int i;
430 for(i=0; i<256; i++)
431 vga_setpalette(i, ((i>>5)&7)*9, ((i>>2)&7)*9, (i&3)*21);
433 /* set 121 palette for 4 bpp */
434 else if(mode_bpp==4){
435 int i;
436 for(i=0; i<16; i++)
437 vga_setpalette(i, ((i>>3)&1)*63, ((i>>1)&3)*21, (i&1)*63);
439 //if we change the logical width, we should know the granularity
440 stride_granularity=8;//according to man vga_logicalwidth
441 if(modeinfo->flags & EXT_INFO_AVAILABLE){
442 stride_granularity=modeinfo->linewidth_unit;
444 //look for hardware acceleration
445 mode_capabilities=0;//NATIVE;
446 if(!force_native){//if we want to use only native drawers
447 if(modeinfo->flags & HAVE_EXT_SET){//support for hwaccel interface
448 accflags=vga_ext_set(VGA_EXT_AVAILABLE,VGA_AVAIL_ACCEL);
449 if(accflags & ACCELFLAG_FILLBOX) // clear screen
450 mode_capabilities|=CAP_ACCEL_CLEAR;
451 if(accflags & ACCELFLAG_PUTIMAGE)//support for mem->vid transfer
452 mode_capabilities|=CAP_ACCEL_PUTIMAGE;
453 if((accflags & ACCELFLAG_SETMODE) && (accflags & ACCELFLAG_SYNC)){
454 vga_accel(ACCEL_SETMODE,BLITS_IN_BACKGROUND);
455 mode_capabilities|=CAP_ACCEL_BACKGR;//can draw in backgraund
458 if(modeinfo->flags & IS_LINEAR){
459 mode_capabilities|=CAP_LINEAR; //don't use bank & vga_draw
461 else{
462 if(modeinfo->flags & CAPABLE_LINEAR){
463 int vid_mem_size;
464 vid_mem_size = vga_setlinearaddressing();
465 if(vid_mem_size != -1){
466 modeinfo=vga_getmodeinfo(vid_mode);//sometimes they change parameters
467 mode_capabilities|=CAP_LINEAR;
471 }//fi force native
472 if(mode_capabilities&CAP_LINEAR){
473 mp_tmsg(MSGT_VO,MSGL_INFO, "[VO_SVGA] Video mode is linear and memcpy could be used for image transfer.\n");
475 if(mode_capabilities&CAP_ACCEL_PUTIMAGE){
476 mp_tmsg(MSGT_VO,MSGL_INFO, "[VO_SVGA] Video mode has hardware acceleration and put_image could be used.\n");
477 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");
480 //here is the place to handle strides for accel_ modes;
481 mode_stride=modeinfo->linewidth;
482 //we may try to set a bigger stride for video mode that will match the mpi->stride,
483 //this way we will transfer more data, but HW put_image can do it in backgraund!
485 //now let's see how many pages we can use
486 max_pages = modeinfo->maxpixels/(modeinfo->height * modeinfo->width);
487 if(max_pages > MAXPAGES) max_pages = MAXPAGES;
488 if(!vo_doublebuffering) max_pages=1;
489 //fill PageStore structs
491 int i;
492 uint8_t * GRAPH_MEM;
493 int dof;
494 GRAPH_MEM=vga_getgraphmem();
495 for(i=0;i<max_pages;i++){
496 //calculate display offset
497 dof = i * modeinfo->height * modeinfo->width;
498 if(modeinfo->bytesperpixel != 0) dof*=modeinfo->bytesperpixel;
499 //check video chip limitations
500 if( dof != (dof & modeinfo->startaddressrange) ){
501 max_pages=i;//page 0 will never come here
502 break;
504 PageStore[i].yoffset = i * modeinfo->height;//starting y offset
505 PageStore[i].vbase = GRAPH_MEM + i*modeinfo->height*mode_stride; //memory base address
506 PageStore[i].doffset = dof; //display offset
507 PageStore[i].locks = PAGE_EMPTY;
510 assert(max_pages>0);
511 mp_tmsg(MSGT_VO,MSGL_INFO, "[VO_SVGA] Video mode has %d page(s).\n",max_pages);
512 //15bpp
513 if(modeinfo->bytesperpixel!=0)
514 vga_claimvideomemory(max_pages * modeinfo->height * modeinfo->width * modeinfo->bytesperpixel);
515 else
516 vga_claimvideomemory(max_pages * modeinfo->height * modeinfo->width * mode_bpp / 8);
518 cpage=old_page=0;
519 svga_clear_box(0,0,modeinfo->width,modeinfo->height * max_pages);
521 image_height=req_h;
522 image_width=req_w;
523 x_pos = (modeinfo->width - req_w) / 2;
524 y_pos = (modeinfo->height - req_h) / 2;
525 x_pos &= ~(15); //align x offset position to 16 pixels
526 mp_tmsg(MSGT_VO,MSGL_INFO, "[VO_SVGA] Centering image. Starting at (%d,%d)\n",x_pos,y_pos);
528 #ifdef CONFIG_VIDIX
530 if(vidix_name[0]){
531 vidix_init(width, height, x_pos, y_pos, modeinfo->width, modeinfo->height,
532 format, mode_bpp, modeinfo->width,modeinfo->height);
533 mp_tmsg(MSGT_VO,MSGL_INFO, "[VO_SVGA] Using VIDIX. w=%i h=%i mw=%i mh=%i\n",width,height,
534 modeinfo->width,modeinfo->height);
535 vidix_start();
536 /*set colorkey*/
537 if(vidix_grkey_support()){
538 vidix_grkey_get(&gr_key);
539 gr_key.key_op = KEYS_PUT;
540 if (!(vo_colorkey & 0xFF000000)) {
541 gr_key.ckey.op = CKEY_TRUE;
542 gr_key.ckey.red = (vo_colorkey & 0x00FF0000) >> 16;
543 gr_key.ckey.green = (vo_colorkey & 0x0000FF00) >> 8;
544 gr_key.ckey.blue = vo_colorkey & 0x000000FF;
545 } else
546 gr_key.ckey.op = CKEY_FALSE;
547 vidix_grkey_set(&gr_key);
550 #endif
552 vga_setdisplaystart(0);
553 return 0;
556 static int draw_slice(uint8_t *image[],int stride[],
557 int w, int h, int x, int y) {
558 assert(0);
559 return VO_ERROR;//this is yv12 only -> vf_scale should do all transforms
562 static int draw_frame(uint8_t *src[]) {
563 assert(0);
564 return VO_ERROR;//this one should not be called
567 static void draw_osd(void)
569 mp_msg(MSGT_VO,MSGL_DBG4, "vo_svga: draw_osd()\n");
570 //only modes with bytesperpixel>0 can draw OSD
571 if(modeinfo->bytesperpixel==0) return;
572 if(!(mode_capabilities&CAP_LINEAR)) return;//force_native will remove OSD
574 if(blackbar_osd){
575 //111
576 //3 4
577 //222
578 svga_clear_box(0,0 + PageStore[cpage].yoffset,
579 modeinfo->width, y_pos);
580 svga_clear_box(0, image_height + y_pos + PageStore[cpage].yoffset,
581 modeinfo->width, modeinfo->height-(image_height+ y_pos));
582 svga_clear_box(0, y_pos + PageStore[cpage].yoffset,
583 x_pos, image_height);
584 svga_clear_box(image_width + x_pos, y_pos + PageStore[cpage].yoffset,
585 modeinfo->width-(x_pos+image_width), image_height);
586 // vo_remove_text(modeinfo->width, modeinfo->height, clear_alpha);
587 vo_draw_text(modeinfo->width, modeinfo->height, draw_alpha);
588 }else{
589 vo_draw_text(image_width, image_height, draw_alpha);
593 static void flip_page(void) {
594 PageStore[old_page].locks=PAGE_EMPTY;
595 PageStore[cpage].locks=PAGE_BUSY;
597 mp_msg(MSGT_VO,MSGL_DBG3, "vo_svga: viewing page %d\n",cpage);
598 if(sync_flip && old_page!=cpage){
599 mp_msg(MSGT_VO,MSGL_DBG3, "vo_svga:vga_waitretrace\n");
600 vga_waitretrace();
602 vga_setdisplaystart(PageStore[cpage].doffset);
604 old_page=cpage;//cpage will be overwriten on next draw_image
607 static void check_events(void) {
610 static void uninit(void) {
612 #ifdef CONFIG_VIDIX
613 if(vidix_name[0])vidix_term();
614 #endif
615 vga_setmode(TEXT);
618 /* --------------------------------------------------------------------- */
619 static int query_format(uint32_t format) {
620 int32_t req_bpp,flags;
621 int i,lastmode;
622 vga_modeinfo * vminfo;
624 mp_msg(MSGT_VO,MSGL_DBG4, "vo_svga: query_format=%X \n",format);
625 //only RGB modes supported
626 if( (!IMGFMT_IS_RGB(format)) && (!IMGFMT_IS_BGR(format)) ) return 0;
628 // Reject different endian
629 #if HAVE_BIGENDIAN
630 if (IMGFMT_IS_BGR(format)) return 0;
631 #else
632 if (IMGFMT_IS_RGB(format)) return 0;
633 #endif
635 //svgalib supports only BG4B! if we want BGR4 we have to emulate it (sw)
636 if( format==IMGFMT_BGR4 || format==IMGFMT_RGB4) return 0;
637 req_bpp = IMGFMT_RGB_DEPTH(format);
638 if( vo_dbpp>0 && vo_dbpp!=req_bpp ) return 0; //support -bpp options
639 //scan all modes
640 lastmode = vga_lastmodenumber();
641 for(i=1;i<=lastmode;i++){
642 vminfo = vga_getmodeinfo(i);
643 if( vminfo == NULL ) continue;
644 if( vga_hasmode(i) == 0 ) continue;
645 if( req_bpp != bpp_from_vminfo(vminfo) ) continue;
646 if( (force_vm > 0) && (force_vm != i) ) continue;//quick hack
647 flags = VFCAP_CSP_SUPPORTED|
648 VFCAP_CSP_SUPPORTED_BY_HW|
649 VFCAP_ACCEPT_STRIDE|
651 if(req_bpp>8) flags|=VFCAP_OSD;
652 return flags;
654 return 0;
657 static void draw_alpha(int x0, int y0, int w, int h, unsigned char *src,
658 unsigned char *srca, int stride) {
659 char* base;
661 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",
662 x0,y0,w,h,src,srca,stride);
663 if(!blackbar_osd) {
664 //drawing in the image, so place the stuff there
665 x0+=x_pos;
666 y0+=y_pos;
669 mp_msg(MSGT_VO,MSGL_DBG4, "vo_svga: OSD draw in page %d\n",cpage);
670 base=PageStore[cpage].vbase + y0*mode_stride + x0*modeinfo->bytesperpixel;
671 switch (mode_bpp) {
672 case 32:
673 vo_draw_alpha_rgb32(w, h, src, srca, stride, base, mode_stride);
674 break;
675 case 24:
676 vo_draw_alpha_rgb24(w, h, src, srca, stride, base, mode_stride);
677 break;
678 case 16:
679 vo_draw_alpha_rgb16(w, h, src, srca, stride, base, mode_stride);
680 break;
681 case 15:
682 vo_draw_alpha_rgb15(w, h, src, srca, stride, base, mode_stride);
683 break;
687 static uint32_t get_image(mp_image_t *mpi){
688 int page;
690 if(!IMGFMT_IS_BGR(mpi->imgfmt) && !IMGFMT_IS_RGB(mpi->imgfmt) ){
691 assert(0);//should never happen
692 return VO_FALSE;
695 if (
696 ( (mpi->type != MP_IMGTYPE_STATIC) && (mpi->type != MP_IMGTYPE_TEMP)) ||
697 (mpi->flags & MP_IMGFLAG_PLANAR) ||
698 (mpi->flags & MP_IMGFLAG_YUV)
700 return VO_FALSE;
702 //reading from video memory is horribly slow
703 if( !(mpi->flags & MP_IMGFLAG_READABLE) && vo_directrendering &&
704 (mode_capabilities & CAP_LINEAR) ){
706 //find free page and reserve it
707 page=page_find_free();
708 if(page >= 0){
709 PageStore[page].locks=PAGE_BUSY;
711 mpi->flags |= MP_IMGFLAG_DIRECT;
712 mpi->stride[0] = mode_stride;
713 mpi->planes[0] = PageStore[page].vbase +
714 y_pos*mode_stride + (x_pos*mpi->bpp)/8;
715 mpi->priv=(void *)page;
716 mp_msg(MSGT_VO,MSGL_DBG3, "vo_svga: direct render allocated! page=%d\n",page);
717 return VO_TRUE;
721 return VO_FALSE;