comparison libvo/vo_svga.c @ 9621:3ef467aac4a1

new svga driver - support double buffering, fast_memcpy, direct render and HW acceleration
author iive
date Thu, 20 Mar 2003 01:45:40 +0000
parents a076d22664b5
children 0e6d7f48309e
comparison
equal deleted inserted replaced
9620:ce4cd85498f3 9621:3ef467aac4a1
1 /* 1 /*
2
2 Video driver for SVGAlib 3 Video driver for SVGAlib
3 by Zoltan Mark Vician <se7en@sch.bme.hu> 4 by Zoltan Mark Vician <se7en@sch.bme.hu>
4 Code started: Mon Apr 1 23:25:47 2001 5 Code started: Mon Apr 1 23:25:47 2001
5
6 Some changes by Matan Ziv-Av <matan@svgalib.org> 6 Some changes by Matan Ziv-Av <matan@svgalib.org>
7 Compleat rewrite by Ivan Kalvachev 19 Mar 2003:
8
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 - denoice3d fails to find common colorspace, vf_scale doesn't help - I work on it.
19
20 TODO:
21 - OSD without flicker (w/h & w/o double buffer)
22 - let choose_best_mode take aspect into account
23 - set palette from mpi->palette or mpi->plane[1]
24 - let OSD draw in black bars - need some OSD changes
25 - Make nicer CONFIG parsing
26 - change video mode logical width to match img->stride[0] - for HW only
7 */ 27 */
8 28
9 #include <stdio.h> 29 #include <stdio.h>
10 #include <stdlib.h> 30 #include <stdlib.h>
11 #include <string.h> 31 #include <string.h>
15 #include <limits.h> 35 #include <limits.h>
16 36
17 #include "config.h" 37 #include "config.h"
18 #include "video_out.h" 38 #include "video_out.h"
19 #include "video_out_internal.h" 39 #include "video_out_internal.h"
20 40 #include "fastmemcpy.h"
41 #include "osdep/getch2.h"
21 #ifdef CONFIG_VIDIX 42 #ifdef CONFIG_VIDIX
22 #include "vosub_vidix.h" 43 #include "vosub_vidix.h"
23 #endif 44 #endif
24 45
25 #include "sub.h" 46 #include "sub.h"
26 #include "../postproc/rgb2rgb.h"
27 47
28 #include "../mp_msg.h" 48 #include "../mp_msg.h"
29 //#include "../mp_image.h" 49 //#include "../mp_image.h"
30 50
51 #include <assert.h>
52
53 //silence warnings, probably it have to go in some global header
54 #define UNUSED(x) ((void)(x))
55
56 extern int vo_doublebuffering;
31 extern int vo_directrendering; 57 extern int vo_directrendering;
32 extern int vo_dbpp; 58 extern int vo_dbpp;
33 extern int verbose; 59 extern int verbose;
34 60
35 static uint32_t query_format(uint32_t format); 61 static uint32_t query_format(uint32_t format);
36 static int checksupportedmodes();
37 static void putbox(int x, int y, int w, int h, uint8_t *buf,int prog);
38 static void fillbox(int x, int y, int w, int h, uint32_t c);
39 static void draw_alpha(int x0, int y0, int w, int h, unsigned char *src, 62 static void draw_alpha(int x0, int y0, int w, int h, unsigned char *src,
40 unsigned char *srca, int stride); 63 unsigned char *srca, int stride);
41 static uint32_t get_image(mp_image_t *mpi); 64 static uint32_t get_image(mp_image_t *mpi);
42 65
43 static uint8_t *yuvbuf = NULL, *bppbuf = NULL; 66 #define MAXPAGES 16
44 static uint8_t *GRAPH_MEM; 67
45 68 #define CAP_ACCEL_CLEAR 8
46 static int BYTESPERPIXEL, WIDTH, HEIGHT, LINEWIDTH; 69 #define CAP_ACCEL_PUTIMAGE 4
47 static int frame, maxframes, oldmethod=0; 70 #define CAP_ACCEL_BACKGR 2
48 static int directrender; 71 #define CAP_LINEAR 1
49 72
73 static uint8_t zerobuf[8192];//used when clear screen with vga_draw
74
75 static int squarepix;
50 static int force_vm=0; 76 static int force_vm=0;
51 static int squarepix=0; 77 static int force_native=0;
52 78 static int sync_flip=0;
53 static uint32_t pformat; 79 static int cpage=0, max_pages;
54 static uint32_t orig_w, orig_h, maxw, maxh; // Width, height 80
55 static uint8_t buf0[8192]; 81 static vga_modeinfo * modeinfo;
56 static uint8_t *buffer; 82 static int mode_stride; //keep it in case of vga_setlogicalwidth
57 83 static int stride_granularity; //not yet used
58 typedef struct vga_modelist_s { 84 static int mode_bpp;
59 uint16_t modenum; 85 static int mode_capabilities;
60 vga_modeinfo modeinfo; 86
61 struct vga_modelist_s *next; 87 static int image_width,image_height; // used by OSD
62 } vga_modelist_t;
63
64 vga_modelist_t *modelist = NULL;
65
66 static uint8_t bpp;
67 static uint8_t bpp_conv = 0;
68 static uint32_t pformat;
69
70 #define BPP_15 1
71 #define BPP_16 2
72 #define BPP_24 4
73 #define BPP_32 8
74 #define BPP_8 16
75 #define BPP_4 32
76 #define BPP_1 64
77 static uint8_t bpp_avail = 0;
78
79 static uint8_t checked = 0;
80
81 static uint32_t x_pos, y_pos; 88 static uint32_t x_pos, y_pos;
82 89
90 static struct {
91 int yoffset;//y position of the page
92 int doffset;//display start of the page
93 void * vbase;//memory start address of the page
94 }PageStore[MAXPAGES];
95
83 static vo_info_t info = { 96 static vo_info_t info = {
84 "SVGAlib", 97 "SVGAlib",
85 "svga", 98 "svga",
86 "Zoltan Mark Vician <se7en@sch.bme.hu>", 99 "Ivan Kalvachev <iive@sf.net>",
87 "" 100 ""
88 }; 101 };
89 102
90 #ifdef CONFIG_VIDIX 103 #ifdef CONFIG_VIDIX
91 static char vidix_name[32] = ""; 104 static char vidix_name[32] = "";
92 #endif 105 #endif
93 106
94 LIBVO_EXTERN(svga) 107 LIBVO_EXTERN(svga)
95 108
109 /*
110 probably this should be in separate pages.c file so
111 all vo_drivers can use it, do it if you like it.
112 TODO
113 direct render with IP buffering support - for vo_tdfx_vid
114 */
115
116 #define PAGES_MAX MAXPAGES
117 #define Page_Empty 0
118 #define Page_Durty 1
119
120 static int page_locks[PAGES_MAX];
121 static int pagecurrent;
122 static int pagetoshow;
123 static int pagesmax;
124
125 static void page_init(int max){
126 int i;
127 for(i=0;i<max;i++){
128 page_locks[i]=0;
129 }
130 pagetoshow=pagecurrent=0;
131 pagesmax=max;
132 }
133 //internal use function
134 //return number of 1'st free page or -1 if no free one
135 static int page_find_free(){
136 int i;
137 for(i=0;i<pagesmax;i++)
138 if(page_locks[i]==Page_Empty) return i;
139 return -1;
140 }
141
142 //return the number of page we may draw directly of -1 if no such
143 static int page_get_image(){
144 int pg;
145 pg=page_find_free();
146 if(pg>=0) page_locks[pg]=Page_Durty;
147 return pg;
148 }
149
150 //return the number of page we should draw into.
151 static int page_draw_image(){
152 int pg;
153 pg=page_find_free();
154 if(pg<0) pg=pagecurrent;
155 page_locks[pg]=Page_Durty;
156 pagetoshow=pg;
157 return pg;
158 }
159
160 static void page_draw_gotten_image(int pg){
161 assert((pg>=0)&&(pg<PAGES_MAX));
162 pagetoshow=pg;
163 }
164
165 //return the number of the page to show
166 static int page_flip_page(){
167 page_locks[pagecurrent]=Page_Empty;
168 pagecurrent=pagetoshow;
169 assert(pagecurrent>=0);
170 //movequeue;
171 page_locks[pagecurrent]=Page_Durty;
172 return pagecurrent;
173 }
174 //------------ END OF PAGE CODE -------------
175
96 static uint32_t preinit(const char *arg) 176 static uint32_t preinit(const char *arg)
97 { 177 {
98 int i; 178 int i;
99 179 char s[64];
100 for(i=0;i<8192;i++) buf0[i]=0; 180
101 181 getch2_disable();
102 if(vo_directrendering) { 182 memset(zerobuf,0,sizeof(zerobuf));
103 maxframes=0; 183 force_vm=force_native=squarepix=0;
104 } else { 184
105 maxframes=1;
106 }
107
108 if(arg)while(*arg) { 185 if(arg)while(*arg) {
109 if(!strncmp(arg,"old",3)) {
110 oldmethod=1;
111 arg+=3;
112 if( *arg == ':' ) arg++;
113 }
114
115 #ifdef CONFIG_VIDIX 186 #ifdef CONFIG_VIDIX
116 if(memcmp(arg,"vidix",5)==0) { 187 if(memcmp(arg,"vidix",5)==0) {
117 int i; 188 i=6;
118 i=6; 189 while(arg[i] && arg[i]!=':') i++;
119 while(arg[i] && arg[i]!=':') i++; 190 strncpy(vidix_name, arg+6, i-6);
120 strncpy(vidix_name, arg+6, i-6); 191 vidix_name[i-5]=0;
121 vidix_name[i-5]=0; 192 if(arg[i]==':')i++;
122 if(arg[i]==':')i++; 193 arg+=i;
123 arg+=i; 194 vidix_preinit(vidix_name, &video_out_svga);
124 vidix_preinit(vidix_name, &video_out_svga); 195 }
125 }
126 #endif 196 #endif
127 if(!strncmp(arg,"sq",2)) { 197 if(!strncmp(arg,"sq",2)) {
128 squarepix=1; 198 squarepix=1;
129 arg+=2; 199 arg+=2;
130 if( *arg == ':' ) arg++; 200 if( *arg == ':' ) arg++;
131 } 201 }
202
203 if(!strncmp(arg,"native",6)) {
204 force_native=1;
205 arg+=6;
206 if( *arg == ':' ) arg++;
207 }
132 208
133 if(*arg) { 209 if(!strncmp(arg,"retrace",7)) {
134 int i; 210 sync_flip=1;
135 char s[64]; 211 arg+=7;
136 printf("arg is %s\n",arg); 212 if( *arg == ':' ) arg++;
137 i=0; 213 }
138 while(arg[i] && arg[i]!=':')i++; 214
139 strncpy(s, arg, i); 215 if(*arg) {
140 s[i]=0; 216 i=0;
141 arg+=i; 217 while(arg[i] && arg[i]!=':')i++;
142 if(*arg==':')arg++; 218 strncpy(s, arg, i);
143 printf("i=%i new arg is %s\n",i, arg); 219 s[i]=0;
144 i=vga_getmodenumber(s); 220 arg+=i;
145 if(i>0) { 221 if(*arg==':')arg++;
146 force_vm = i; 222 i=vga_getmodenumber(s);
147 if(verbose)printf("vo_svga: Forcing mode %i\n",force_vm); 223 if(i>0) {
148 } 224 force_vm = i;
149 } 225 if(verbose)
150 } 226 printf("vo_svga: Forcing mode %i\n",force_vm);
151 227 }
152 if (!checked) { 228 }
153 if (checksupportedmodes()) // Looking for available video modes 229 }
154 return(1); 230
155 } 231 vga_init();
156
157 return 0; 232 return 0;
233 }
234
235 static void svga_clear_box(int x,int y,int w,int h){
236 uint8_t * rgbplane;
237 int i;
238
239 if (mode_capabilities&CAP_ACCEL_CLEAR){
240 if(verbose > 2)
241 printf("vo_svga: clearing box %d,%d - %d,%d with HW acceleration\n",
242 x,y,w,h);
243 if(mode_capabilities&CAP_ACCEL_BACKGR)
244 vga_accel(ACCEL_SYNC);
245 vga_accel(ACCEL_SETFGCOLOR,0);//black
246 vga_accel(ACCEL_FILLBOX,x,y,w,h);
247 return;
248 }
249 if (mode_capabilities & CAP_LINEAR){
250 if(verbose > 2)
251 printf("vo_svga: clearing box %d,%d - %d,%d with memset\n",x,y,w,h);
252 rgbplane=PageStore[0].vbase + (y*mode_stride) + (x*modeinfo->bytesperpixel);
253 for(i=0;i<h;i++){
254 //i'm afraid that memcpy is better optimized than memset;)
255 memcpy(rgbplane,zerobuf,w*modeinfo->bytesperpixel);
256 // memset(rgbplane,0,w*modeinfo->bytesperpixel);
257 rgbplane+=mode_stride;
258 }
259 return;
260 }
261 //native
262 if(verbose > 2)
263 printf("vo_svga: clearing box %d,%d - %d,%d with native draw \n",x,y,w,h);
264 if(modeinfo->bytesperpixel!=0) w*=modeinfo->bytesperpixel;
265 for(i=0;i<h;i++){
266 vga_drawscansegment(zerobuf,x,y+i,w);
267 }
268 };
269
270 static uint32_t svga_draw_image(mp_image_t *mpi){
271 int i,x,y,w,h;
272 int stride;
273 uint8_t *rgbplane, *base;
274 int bytesperline;
275
276 if(mpi->flags & MP_IMGFLAG_DIRECT){
277 if(verbose > 2)
278 printf("vo_svga: drawing direct rendered surface\n");
279 cpage=(uint32_t)mpi->priv;
280 page_draw_gotten_image(cpage);
281 return VO_TRUE; //it's already done
282 }
283 // if (mpi->flags&MP_IMGFLAGS_DRAWBACK)
284 // return VO_TRUE;//direct render method 2
285 cpage=page_draw_image();
286 // these variables are used in loops
287 x = mpi->x;
288 y = mpi->y;
289 w = mpi->w;
290 h = mpi->h;
291 stride = mpi->stride[0];
292 rgbplane = mpi->planes[0] + y*stride + (x*mpi->bpp)/8;
293 x+=x_pos;//center
294 y+=y_pos;
295
296 if(mpi->bpp >= 8){//for modes<8 use only native
297 if( (mode_capabilities&CAP_ACCEL_PUTIMAGE) && (x==0) && (w==mpi->width) &&
298 (stride == mode_stride) ){ //only monolite image can be accelerated
299 w=(stride*8)/mpi->bpp;//we transfer pixels in the stride so the source
300 //ACCELERATE
301 if(verbose>2)
302 printf("vo_svga: using HW PutImage (x=%d,y=%d,w=%d,h=%d)\n",x,y,w,h);
303 if(mode_capabilities & CAP_ACCEL_BACKGR)
304 vga_accel(ACCEL_SYNC);
305
306 vga_accel(ACCEL_PUTIMAGE,x,y+PageStore[cpage].yoffset,w,h,rgbplane);
307 return VO_TRUE;
308 }
309
310 if( mode_capabilities&CAP_LINEAR){
311 //DIRECT
312 if(verbose>2)
313 printf("vo_svga: using Direct memcpy (x=%d,y=%d,w=%d,h=%d)\n",x,y,w,h);
314 bytesperline=(w*mpi->bpp)/8;
315 base=PageStore[cpage].vbase + (y*mode_stride) + (x*mpi->bpp)/8;
316
317 for(i=0;i<h;i++){
318 mem2agpcpy(base,rgbplane,bytesperline);
319 base+=mode_stride;
320 rgbplane+=stride;
321 }
322 return VO_TRUE;
323 }
324 }//(modebpp>=8
325
326
327 //NATIVE
328 {
329 int length;
330 length=(w*mpi->bpp)/8;
331 //one byte per pixel! svgalib innovation
332 if(mpi->imgfmt==IMGFMT_RG4B || mpi->imgfmt==IMGFMT_BG4B) length=w;
333
334 if(verbose>2)
335 printf("vo_svga: using Native vga_draw(x=%d,y=%d,w=%d,h=%d)\n",x,y,w,h);
336 y+=PageStore[cpage].yoffset;//y position of the page beggining
337 for(i=0;i<h;i++){
338 vga_drawscansegment(rgbplane,x,y+i,length);
339 rgbplane+=stride;
340 }
341 }
342 return VO_TRUE;
343 }
344
345 int bpp_from_vminfo(vga_modeinfo *vminfo){
346 switch(vminfo->colors){
347 case 2: return 1;
348 case 16: return 4;
349 case 256: return 8;
350 case 32768: return 15;
351 case 65536: return 16;
352 case 1<<24: return 8*vminfo->bytesperpixel;
353 }
354 return 0;
355 }
356
357 int find_best_svga_mode(int req_w,int req_h, int req_bpp){
358 int badness,prev_badness;
359 int bestmode,lastmode;
360 int i;
361 vga_modeinfo *vminfo;
362 //int best aspect mode // best linear mode // best normal mode (no modeX)
363
364 prev_badness = req_w * req_h;
365 bestmode = 0; //0 is the TEXT mode
366 lastmode = vga_lastmodenumber();
367 for(i=1;i<lastmode;i++){
368 vminfo = vga_getmodeinfo(i);
369 if( vminfo == NULL ) continue;
370 if( vga_hasmode(i) == 0 ) continue;
371 if( req_bpp != bpp_from_vminfo(vminfo) )continue;
372 if( (vminfo->width < req_w) || (vminfo->height < req_h) ) continue;
373 badness=(vminfo->width * vminfo->height) - (req_h * req_w);
374 //put here aspect calculations
375 if(squarepix)
376 if( vminfo->width*3 != vminfo->height*4 ) continue;
377
378 if( prev_badness >= badness ){//modeX etc...
379 prev_badness=badness;
380 bestmode=i;
381 if(verbose>3)
382 printf("vo_svga: found good mode %d with badness %d\n",i,badness);
383 }
384 }
385 return bestmode;
158 } 386 }
159 387
160 static uint32_t control(uint32_t request, void *data, ...) 388 static uint32_t control(uint32_t request, void *data, ...)
161 { 389 {
162 switch (request) { 390 switch (request) {
163 case VOCTRL_QUERY_FORMAT: 391 case VOCTRL_QUERY_FORMAT:
164 return query_format(*((uint32_t*)data)); 392 return query_format(*((uint32_t*)data));
165 case VOCTRL_GET_IMAGE: 393 case VOCTRL_DRAW_IMAGE:
166 return get_image(data); 394 return svga_draw_image( (mp_image_t *)data);
395 case VOCTRL_GET_IMAGE:
396 return get_image(data);
167 } 397 }
168 return VO_NOTIMPL; 398 return VO_NOTIMPL;
169 } 399 }
170 400
401 //
402 // This function is called to init the video driver for specific mode
403 //
171 static uint32_t config(uint32_t width, uint32_t height, uint32_t d_width, 404 static uint32_t config(uint32_t width, uint32_t height, uint32_t d_width,
172 uint32_t d_height, uint32_t flags, char *title, 405 uint32_t d_height, uint32_t flags, char *title,
173 uint32_t format) { 406 uint32_t format) {
174 uint32_t req_w = (d_width > 0 ? d_width : width); 407 int32_t req_w = width;// (d_width > 0 ? d_width : width);
175 uint32_t req_h = (d_height > 0 ? d_height : height); 408 int32_t req_h = height;// (d_height > 0 ? d_height : height);
176 uint16_t vid_mode = 0; 409 uint16_t vid_mode = 0;
177 uint8_t res_widescr, vid_widescr = (((req_w*1.0)/req_h) > (4.0/3)) ? 1 : 0; 410 int32_t req_bpp;
178 uint16_t buf_w = USHRT_MAX, buf_h = USHRT_MAX; 411
179 vga_modelist_t *list = modelist; 412 uint32_t accflags;
180
181 if(verbose) 413 if(verbose)
182 printf("vo_svga: config(%i, %i, %i, %i, %08x, %s, %08x)\n", width, height, 414 printf("vo_svga: config(%i, %i, %i, %i, %08x, %s, %08x)\n", width, height,
183 d_width, d_height, flags, title, format); 415 d_width, d_height, flags, title, format);
184 416 //Only RGB modes supported
185 bpp_avail = 0; 417 if (!IMGFMT_IS_RGB(format) && !IMGFMT_IS_BGR(format)) {assert(0);return -1;}
186 while (list != NULL) { 418 req_bpp = IMGFMT_BGR_DEPTH(format);
187 if ((list->modeinfo.width >= req_w) && (list->modeinfo.height >= req_h)) { 419
188 switch (list->modeinfo.colors) { 420 if( vo_dbpp!=0 && vo_dbpp!=req_bpp) {assert(0);return-1;}
189 case 32768: bpp_avail |= BPP_15; break; 421
190 case 65536: bpp_avail |= BPP_16; break; 422 if(!force_vm) {
191 case 256 : bpp_avail |= BPP_8; break; 423 if (verbose) {
192 case 16 : bpp_avail |= BPP_4; break; 424 printf("vo_svga: Looking for the best resolution...\n");
193 case 2 : bpp_avail |= BPP_1; break; 425 printf("vo_svga: req_w: %d, req_h: %d, bpp: %d\n",req_w,req_h,req_bpp);
194 } 426 }
195 switch (list->modeinfo.bytesperpixel) { 427 vid_mode=find_best_svga_mode(req_w,req_h,req_bpp);
196 case 3: bpp_avail |= BPP_24; break; 428 if(vid_mode==0)
197 case 4: bpp_avail |= BPP_32; break; 429 return 1;
198 } 430 modeinfo=vga_getmodeinfo(vid_mode);
199 } 431 }else{//force_vm
200 list = list->next; 432 vid_mode=force_vm;
201 } 433 if(vga_hasmode(vid_mode) != 0){
202 434 printf("vo_svga: forced vid_mode %d (%s) not available\n",
203 pformat = format; 435 vid_mode,vga_getmodename(vid_mode));
204 436 return 1; //error;
205 // bpp check 437 }
206 bpp_conv = 0; 438 modeinfo=vga_getmodeinfo(vid_mode);
207 if (!vo_dbpp) { 439 if( (modeinfo->width < req_w) || (modeinfo->height < req_h) ){
208 if (!IMGFMT_IS_RGB(format) && !IMGFMT_IS_BGR(format)) bpp = 32; 440 printf("vo_svga: forced vid_mode %d (%s) too small\n",
209 else bpp = format & 255; 441 vid_mode,vga_getmodename(vid_mode));
210 if (verbose) 442 return 1;
211 printf("vo_svga: vo_dbpp == 0, bpp: %d\n",bpp); 443 }
212 switch (bpp) { 444 }
213 case 32: if (!(bpp_avail & BPP_32)) { 445 mode_bpp=bpp_from_vminfo(modeinfo);
214 printf("vo_svga: Haven't found video mode which fit to: %dx%d %dbpp\n",req_w,req_h,bpp); 446
215 printf("vo_svga: Maybe you should try -bpp\n"); 447 printf("vo_svga: vid_mode: %d, %dx%d %dbpp\n",
216 return(1); 448 vid_mode,modeinfo->width,modeinfo->height,mode_bpp);
217 } 449
218 break;
219 case 24: if (!(bpp_avail & BPP_24)) {
220 if (!(bpp_avail & BPP_32)) {
221 printf("vo_svga: Haven't found video mode which fit to: %dx%d %dbpp\n",req_w,req_h,bpp);
222 printf("vo_svga: Maybe you should try -bpp\n");
223 return(1);
224 } else {
225 bpp = 32;
226 bpp_conv = 1;
227 printf("vo_svga: BPP conversion 24->32\n");
228 }
229 }
230 break;
231 case 16: if (!(bpp_avail & BPP_16)) {
232 printf("vo_svga: Haven't found video mode which fit to: %dx%d %dbpp\n",req_w,req_h,bpp);
233 printf("vo_svga: Maybe you should try -bpp\n");
234 return(1);
235 }
236 break;
237 case 15: if (!(bpp_avail & BPP_15)) {
238 if (!(bpp_avail & BPP_16)) {
239 printf("vo_svga: Haven't found video mode which fit to: %dx%d %dbpp\n",req_w,req_h,bpp);
240 printf("vo_svga: Maybe you should try -bpp\n");
241 return(1);
242 } else {
243 bpp = 16;
244 bpp_conv = 1;
245 printf("vo_svga: BPP conversion 15->16\n");
246 }
247 }
248 break;
249 case 8: if (!(bpp_avail & BPP_8)) {
250 printf("vo_svga: Haven't found video mode which fit to: %dx%d %dbpp\n",req_w,req_h,bpp);
251 printf("vo_svga: Maybe you should try -bpp\n");
252 return(1);
253 }
254 break;
255 case 4: if (!(bpp_avail & BPP_4)) {
256 printf("vo_svga: Haven't found video mode which fit to: %dx%d %dbpp\n",req_w,req_h,bpp);
257 printf("vo_svga: Maybe you should try -bpp\n");
258 return(1);
259 }
260 break;
261 case 1: if (!(bpp_avail & BPP_1)) {
262 printf("vo_svga: Haven't found video mode which fit to: %dx%d %dbpp\n",req_w,req_h,bpp);
263 printf("vo_svga: Maybe you should try -bpp\n");
264 return(1);
265 }
266 break;
267 }
268 } else {
269 bpp = vo_dbpp;
270 if (verbose)
271 printf("vo_svga: vo_dbpp == %d\n",bpp);
272 switch (bpp) {
273 case 32: if (!(bpp_avail & BPP_32)) {
274 printf("vo_svga: %dbpp not supported in %dx%d (or larger resolution) by HW or SVGAlib\n",bpp,req_w,req_h);
275 return(1);
276 }
277 break;
278 case 24: if (!(bpp_avail & BPP_24)) {
279 printf("vo_svga: %dbpp not supported in %dx%d (or larger resolution) by HW or SVGAlib\n",bpp,req_w,req_h);
280 return(1);
281 }
282 break;
283 case 16: if (!(bpp_avail & BPP_16)) {
284 printf("vo_svga: %dbpp not supported in %dx%d (or larger resolution) by HW or SVGAlib\n",bpp,req_w,req_h);
285 return(1);
286 }
287 break;
288 case 15: if (!(bpp_avail & BPP_15)) {
289 printf("vo_svga: %dbpp not supported in %dx%d (or larger resolution) by HW or SVGAlib\n",bpp,req_w,req_h);
290 return(1);
291 }
292 break;
293 case 8: if (!(bpp_avail & BPP_8)) {
294 printf("vo_svga: %dbpp not supported in %dx%d (or larger resolution) by HW or SVGAlib\n",bpp,req_w,req_h);
295 return(1);
296 }
297 break;
298 case 4: if (!(bpp_avail & BPP_4)) {
299 printf("vo_svga: %dbpp not supported in %dx%d (or larger resolution) by HW or SVGAlib\n",bpp,req_w,req_h);
300 return(1);
301 }
302 break;
303 case 1: if (!(bpp_avail & BPP_1)) {
304 printf("vo_svga: %dbpp not supported in %dx%d (or larger resolution) by HW or SVGAlib\n",bpp,req_w,req_h);
305 return(1);
306 }
307 break;
308 }
309 }
310
311 list = modelist;
312 if (verbose) {
313 printf("vo_svga: Looking for the best resolution...\n");
314 printf("vo_svga: req_w: %d, req_h: %d, bpp: %d\n",req_w,req_h,bpp);
315 }
316 while (list != NULL) {
317 if ((list->modeinfo.width >= req_w) && (list->modeinfo.height >= req_h)) {
318 if (verbose) {
319 switch (list->modeinfo.colors) {
320 case 2 : printf("vo_svga: vid_mode: %d, %dx%d 1bpp\n",
321 list->modenum,list->modeinfo.width,list->modeinfo.height);
322 break;
323 case 16 : printf("vo_svga: vid_mode: %d, %dx%d 4bpp\n",
324 list->modenum,list->modeinfo.width,list->modeinfo.height);
325 break;
326 case 256 : printf("vo_svga: vid_mode: %d, %dx%d 8bpp\n",
327 list->modenum,list->modeinfo.width,list->modeinfo.height);
328 break;
329 case 32768: printf("vo_svga: vid_mode: %d, %dx%d 15bpp\n",
330 list->modenum,list->modeinfo.width,list->modeinfo.height);
331 break;
332 case 65536: printf("vo_svga: vid_mode: %d, %dx%d 16bpp\n",
333 list->modenum,list->modeinfo.width,list->modeinfo.height);
334 break;
335 }
336 switch (list->modeinfo.bytesperpixel) {
337 case 3: printf("vo_svga: vid_mode: %d, %dx%d 24bpp\n",
338 list->modenum,list->modeinfo.width,list->modeinfo.height);
339 break;
340 case 4: printf("vo_svga: vid_mode: %d, %dx%d 32bpp\n",
341 list->modenum,list->modeinfo.width,list->modeinfo.height);
342 break;
343 }
344 }
345 switch (bpp) {
346 case 32: if (list->modeinfo.bytesperpixel == 4)
347 if ((list->modeinfo.width < buf_w) || (list->modeinfo.height < buf_h)) {
348 vid_mode = list->modenum;
349 buf_w = list->modeinfo.width;
350 buf_h = list->modeinfo.height;
351 res_widescr = (((buf_w*1.0)/buf_h) > (4.0/3)) ? 1 : 0;
352 }
353 break;
354 case 24: if (list->modeinfo.bytesperpixel == 3)
355 if ((list->modeinfo.width < buf_w) || (list->modeinfo.height < buf_h)) {
356 vid_mode = list->modenum;
357 buf_w = list->modeinfo.width;
358 buf_h = list->modeinfo.height;
359 res_widescr = (((buf_w*1.0)/buf_h) > (4.0/3)) ? 1 : 0;
360 }
361 break;
362 case 16: if (list->modeinfo.colors == 65536)
363 if ((list->modeinfo.width < buf_w) || (list->modeinfo.height < buf_h)) {
364 vid_mode = list->modenum;
365 buf_w = list->modeinfo.width;
366 buf_h = list->modeinfo.height;
367 res_widescr = (((buf_w*1.0)/buf_h) > (4.0/3)) ? 1 : 0;
368 }
369 break;
370 case 15: if (list->modeinfo.colors == 32768)
371 if ((list->modeinfo.width < buf_w) || (list->modeinfo.height < buf_h)) {
372 vid_mode = list->modenum;
373 buf_w = list->modeinfo.width;
374 buf_h = list->modeinfo.height;
375 res_widescr = (((buf_w*1.0)/buf_h) > (4.0/3)) ? 1 : 0;
376 }
377 break;
378 case 8: if (list->modeinfo.colors == 256)
379 if ((list->modeinfo.width < buf_w) || (list->modeinfo.height < buf_h)) {
380 vid_mode = list->modenum;
381 buf_w = list->modeinfo.width;
382 buf_h = list->modeinfo.height;
383 res_widescr = (((buf_w*1.0)/buf_h) > (4.0/3)) ? 1 : 0;
384 }
385 break;
386 case 4: if (list->modeinfo.colors ==16)
387 if ((list->modeinfo.width < buf_w) || (list->modeinfo.height < buf_h)) {
388 vid_mode = list->modenum;
389 buf_w = list->modeinfo.width;
390 buf_h = list->modeinfo.height;
391 res_widescr = (((buf_w*1.0)/buf_h) > (4.0/3)) ? 1 : 0;
392 }
393 break;
394 case 1: if (list->modeinfo.colors == 2)
395 if ((list->modeinfo.width < buf_w) || (list->modeinfo.height < buf_h)) {
396 vid_mode = list->modenum;
397 buf_w = list->modeinfo.width;
398 buf_h = list->modeinfo.height;
399 res_widescr = (((buf_w*1.0)/buf_h) > (4.0/3)) ? 1 : 0;
400 }
401 break;
402 }
403 }
404 list = list->next;
405 }
406
407 if(force_vm) {
408 list=modelist;
409 while(list) {
410 if(list->modenum == force_vm) {
411 buf_w = list->modeinfo.width;
412 buf_h = list->modeinfo.height;
413 res_widescr = (((buf_w*1.0)/buf_h) > (4.0/3)) ? 1 : 0;
414 switch(list->modeinfo.colors) {
415 case 2:
416 bpp=1;
417 bpp_conv=0;
418 break;
419 case 16:
420 bpp=4;
421 bpp_conv=0;
422 break;
423 case 256:
424 bpp=8;
425 bpp_conv=0;
426 break;
427 case 32768:
428 bpp=16;
429 bpp_conv=1;
430 break;
431 case 65536:
432 bpp=16;
433 bpp_conv=0;
434 break;
435 case (1<<24):
436 if(list->modeinfo.bytesperpixel == 3) {
437 bpp=32;
438 bpp_conv=1;
439 } else {
440 bpp=32;
441 bpp_conv=0;
442 }
443 break;
444 }
445 vid_mode=force_vm;
446 list=NULL;
447 } else list=list->next;
448 }
449 }
450
451
452 if (verbose)
453 printf("vo_svga: vid_mode: %d\n",vid_mode);
454 if (vga_setmode(vid_mode) == -1) { 450 if (vga_setmode(vid_mode) == -1) {
455 printf("vo_svga: vga_setmode(%d) failed.\n",vid_mode); 451 printf("vo_svga: vga_setmode(%d) failed.\n",vid_mode);
456 uninit(); 452 uninit();
457 return(1); // error 453 return 1; // error
458 } 454 }
459
460 /* set 332 palette for 8 bpp */ 455 /* set 332 palette for 8 bpp */
461 if(bpp==8){ 456 if(mode_bpp==8){
462 int i; 457 int i;
463 for(i=0; i<256; i++) 458 for(i=0; i<256; i++)
464 vga_setpalette(i, ((i>>5)&7)*9, ((i>>2)&7)*9, (i&3)*21); 459 vga_setpalette(i, ((i>>5)&7)*9, ((i>>2)&7)*9, (i&3)*21);
465 } 460 }
466 /* set 121 palette for 4 bpp */ 461 /* set 121 palette for 4 bpp */
467 else if(bpp==4){ 462 else if(mode_bpp==4){
468 int i; 463 int i;
469 for(i=0; i<16; i++) 464 for(i=0; i<16; i++)
470 vga_setpalette(i, ((i>>3)&1)*63, ((i>>1)&3)*21, (i&1)*63); 465 vga_setpalette(i, ((i>>3)&1)*63, ((i>>1)&3)*21, (i&1)*63);
471 } 466 }
472 467 //if we change the logical width, we should know the granularity
473 WIDTH=vga_getxdim(); 468 stride_granularity=8;//according to man vga_logicalwidth
474 HEIGHT=vga_getydim(); 469 if(modeinfo->flags & EXT_INFO_AVAILABLE){
475 BYTESPERPIXEL=(bpp+4)>>3; 470 stride_granularity=modeinfo->linewidth_unit;
476 LINEWIDTH=vga_getmodeinfo(vid_mode)->linewidth; 471 }
477 472 //look for hardware acceleration
478 if( (vid_mode<10 || vid_mode==145) && (bpp==8 || bpp==4)) LINEWIDTH*=8; 473 mode_capabilities=0;//NATIVE;
474 if(!force_native){//if we want to use only native drawers
475 if(modeinfo->flags & HAVE_EXT_SET){//support for hwaccel interface
476 accflags=vga_ext_set(VGA_EXT_AVAILABLE,VGA_AVAIL_ACCEL);
477 if(accflags & ACCELFLAG_FILLBOX) // clear screen
478 mode_capabilities|=CAP_ACCEL_CLEAR;
479 if(accflags & ACCELFLAG_PUTIMAGE)//support for mem->vid transfer
480 mode_capabilities|=CAP_ACCEL_PUTIMAGE;
481 if((accflags & ACCELFLAG_SETMODE) && (accflags & ACCELFLAG_SYNC)){
482 vga_accel(ACCEL_SETMODE,BLITS_IN_BACKGROUND);
483 mode_capabilities|=CAP_ACCEL_BACKGR;//can draw in backgraund
484 }
485 }
486 if(modeinfo->flags & IS_LINEAR){
487 mode_capabilities|=CAP_LINEAR; //don't use bank & vga_draw
488 }
489 else{
490 if(modeinfo->flags & CAPABLE_LINEAR){
491 int vid_mem_size;
492 vid_mem_size = vga_setlinearaddressing();
493 if(vid_mem_size != -1){
494 modeinfo=vga_getmodeinfo(vid_mode);//sometimes they change parameters
495 mode_capabilities|=CAP_LINEAR;
496 }
497 }
498 }
499 }//fi force native
500
501 //here is the place to handle strides for accel_ modes;
502 mode_stride=modeinfo->linewidth;
503 //we may try to set a bigger stride for video mode that will match the mpi->stride,
504 //this way we will transfer more data, but HW put_image can do it in backgraund!
505
506 //now lets see how many pages we can use
507 max_pages = modeinfo->maxpixels/(modeinfo->height * modeinfo->width);
508 if(max_pages > MAXPAGES) max_pages = MAXPAGES;
509 if(!vo_doublebuffering) max_pages=1;
510 //fill PageStore structs
511 {
512 int i;
513 uint8_t * GRAPH_MEM;
514 int dof;
515 GRAPH_MEM=vga_getgraphmem();
516 for(i=0;i<max_pages;i++){
517 //calculate display offset
518 dof = i * modeinfo->height * modeinfo->width;
519 if(modeinfo->bytesperpixel != 0) dof*=modeinfo->bytesperpixel;
520 //check video chip limitations
521 if( dof != (dof & modeinfo->startaddressrange) ){
522 max_pages=i;//page 0 will never come here
523 break;
524 }
525 PageStore[i].yoffset = i * modeinfo->height;//starting y offset
526 PageStore[i].vbase = GRAPH_MEM + i*modeinfo->height*mode_stride; //memory base address
527 PageStore[i].doffset = dof; //display offset
528 }
529 }
530 assert(max_pages>0);
531 printf("vo_svga: video mode have %d page(s)\n",max_pages);
532 page_init(max_pages);
533 //15bpp
534 if(modeinfo->bytesperpixel!=0)
535 vga_claimvideomemory(max_pages * modeinfo->height * modeinfo->width * modeinfo->bytesperpixel);
479 else 536 else
480 if(vga_getmodeinfo(vid_mode)->flags & CAPABLE_LINEAR) 537 vga_claimvideomemory(max_pages * modeinfo->height * modeinfo->width * mode_bpp / 8);
481 // if (vga_version>0x1430)//remove this to get more speed (or black screen) 538
482 vga_setlinearaddressing(); 539 svga_clear_box(0,0,modeinfo->width,modeinfo->height * max_pages);
483 540
484 if(oldmethod) { 541 image_height=req_h;
485 buffer=malloc(HEIGHT*LINEWIDTH); 542 image_width=req_w;
486 maxframes=0; 543 x_pos = (modeinfo->width - req_w) / 2;
487 } else if ((vga_getmodeinfo(vid_mode)->flags&IS_LINEAR)) { 544 y_pos = (modeinfo->height - req_h) / 2;
488 directrender=1; 545 x_pos &= ~(15); //align x offset position to 16 pixels
489 if(verbose) printf("vo_svga: Using direct rendering to linear video ram.\n"); 546 printf("vo_svga: centering image. start at (%d,%d)\n",x_pos,y_pos);
490 }
491
492 vga_claimvideomemory((maxframes+1)*HEIGHT*LINEWIDTH);
493 GRAPH_MEM=vga_getgraphmem();
494 frame=0;
495 fillbox(0,0,WIDTH,HEIGHT*(maxframes+1),0);
496
497 orig_w = width;
498 orig_h = height;
499 maxw = req_w;
500 maxh = req_h;
501
502 if (bpp_conv) {
503 bppbuf = malloc(maxw * maxh * BYTESPERPIXEL);
504 if (bppbuf == NULL) {
505 printf("vo_svga: bppbuf -> Not enough memory for buffering!\n");
506 uninit();
507 return (1);
508 }
509 }
510 547
511 #ifdef CONFIG_VIDIX 548 #ifdef CONFIG_VIDIX
512 if(!vidix_name[0]){ 549
513 #endif
514 maxw = width; /* No scaling */
515 maxh = height;
516 #ifdef CONFIG_VIDIX
517 }
518 #endif
519 if (pformat == IMGFMT_YV12) {
520 if(bpp==4)
521 yuv2rgb_init(bpp|128, MODE_RGB);
522 else
523 yuv2rgb_init(bpp, MODE_RGB);
524 }
525
526 x_pos = (WIDTH - maxw) / 2;
527 y_pos = (HEIGHT - maxh) / 2;
528
529 #ifdef CONFIG_VIDIX
530 if(vidix_name[0]){ 550 if(vidix_name[0]){
531 vidix_init(width, height, x_pos, y_pos, maxw, maxh, format, bpp, 551 vidix_init(width, height, x_pos, y_pos, modeinfo->width, modeinfo->height,
532 WIDTH, HEIGHT); 552 format, mode_bpp, modeinfo->width,modeinfo->height);
533 printf("vo_svga: Using VIDIX. w=%i h=%i mw=%i mh=%i\n",width,height,maxw,maxh); 553 printf("vo_svga: Using VIDIX. w=%i h=%i mw=%i mh=%i\n",width,height,
534 vidix_start(); 554 modeinfo->width,modeinfo->height);
555 vidix_start();
535 } 556 }
536 #endif 557 #endif
537 558
538 if(bpp==1)
539 yuvbuf = malloc((maxw+7)/8 * maxh);
540 else
541 yuvbuf = malloc(maxw * maxh * BYTESPERPIXEL);
542
543 if (yuvbuf == NULL) {
544 printf("vo_svga: yuvbuf -> Not enough memory for buffering!\n");
545 uninit();
546 return (1);
547 }
548 printf("vo_svga: SVGAlib resolution: %dx%d %dbpp - ", WIDTH, HEIGHT, bpp);
549 if (maxw != orig_w || maxh != orig_h) printf("Video scaled to: %dx%d\n",maxw,maxh);
550 else printf("No video scaling\n");
551
552 vga_setdisplaystart(0); 559 vga_setdisplaystart(0);
553
554 return (0); 560 return (0);
555 } 561 }
556 562
563 static uint32_t draw_slice(uint8_t *image[],int stride[],
564 int w, int h, int x, int y) {
565 assert(0);
566 UNUSED(image);UNUSED(stride);
567 UNUSED(w);UNUSED(h);
568 UNUSED(x);UNUSED(y);
569
570 return VO_ERROR;//this is yv12 only -> vf_scale should do all transforms
571 }
572
557 static uint32_t draw_frame(uint8_t *src[]) { 573 static uint32_t draw_frame(uint8_t *src[]) {
558 uint8_t *s=src[0]; 574 assert(0);
559 if (bpp_conv) { 575 UNUSED(src);
560 switch(bpp) { 576 return VO_ERROR;//this one should not be called
561 case 32:
562 rgb24to32(src[0],bppbuf,maxw * maxh * 3);
563 break;
564 case 16:
565 rgb15to16(src[0],bppbuf,maxw * maxh * 2);
566 break;
567 }
568 s = bppbuf;
569 }
570 putbox(x_pos, y_pos, maxw, maxh, s, 1);
571 return (0);
572 }
573
574 static uint32_t draw_slice(uint8_t *image[], int stride[],
575 int w, int h, int x, int y) {
576 uint8_t *src = yuvbuf;
577 uint32_t sw, sh;
578
579 if(directrender) {
580 yuv2rgb(GRAPH_MEM+(frame*HEIGHT+y+y_pos)*LINEWIDTH+(x+x_pos)*BYTESPERPIXEL,
581 image[0], image[1], image[2], w, h, LINEWIDTH, stride[0], stride[1]);
582 } else {
583 if(bpp==1)
584 yuv2rgb(yuvbuf, image[0], image[1], image[2], w, h, (orig_w+7)/8, stride[0], stride[1]);
585 else
586 yuv2rgb(yuvbuf, image[0], image[1], image[2], w, h, orig_w * BYTESPERPIXEL,
587 stride[0], stride[1]);
588
589 putbox(x + x_pos, y + y_pos, w, h, src, 1);
590 }
591
592 return (0);
593 } 577 }
594 578
595 static void draw_osd(void) 579 static void draw_osd(void)
596 { 580 {
597 if(oldmethod) { 581 // for now draw only over the image
598 if (y_pos) { 582 // vo_draw_text(modeinfo->width, modeinfo->height, draw_alpha);//black bar OSD
599 fillbox(0, 0, WIDTH, y_pos, 0); 583 vo_draw_text(image_width, image_height, draw_alpha);
600 fillbox(0, HEIGHT - y_pos, WIDTH, y_pos, 0);
601 if (x_pos) {
602 int hmy=HEIGHT - (y_pos<<1);
603 fillbox(0, y_pos, x_pos, hmy, 0);
604 fillbox(WIDTH - x_pos, y_pos, x_pos, hmy, 0);
605 }
606 } else if (x_pos) {
607 fillbox(0, y_pos, x_pos, HEIGHT, 0);
608 fillbox(WIDTH - x_pos, y_pos, x_pos, HEIGHT, 0);
609 }
610 vo_draw_text(WIDTH, HEIGHT, draw_alpha);
611 } else
612 vo_draw_text(maxw, maxh, draw_alpha);
613 } 584 }
614 585
615 static void flip_page(void) { 586 static void flip_page(void) {
616 if(oldmethod) { 587 static int oldpage=-1;
617 int i; 588 int page;
618 uint8_t *b; 589 page = page_flip_page();
619 b=buffer; 590 if(verbose > 2)
620 for(i=0;i<HEIGHT;i++){ 591 printf("vo_svga: viewing page %d\n",page);
621 vga_drawscansegment(b,0,i,LINEWIDTH); 592 if(sync_flip && oldpage!=page){
622 b+=LINEWIDTH; 593 vga_waitretrace();
623 } 594 printf("vo_svga:vga_waitretraced\n");
624 } else { 595 }
625 if(maxframes) { 596 vga_setdisplaystart(PageStore[cpage].doffset);
626 vga_setdisplaystart(frame*HEIGHT*LINEWIDTH); 597 oldpage=page;
627 frame++;
628 if(frame>maxframes)frame=0;
629 }
630 }
631 } 598 }
632 599
633 static void check_events(void) { 600 static void check_events(void) {
634 } 601 }
635 602
636 static void uninit(void) { 603 static void uninit(void) {
637 vga_modelist_t *list = modelist;
638 604
639 #ifdef CONFIG_VIDIX 605 #ifdef CONFIG_VIDIX
640 if(vidix_name[0])vidix_term(); 606 if(vidix_name[0])vidix_term();
641 #endif 607 #endif
642
643 vga_setmode(TEXT); 608 vga_setmode(TEXT);
644 609 }
645 if (bppbuf != NULL)
646 free(bppbuf);
647 bppbuf=NULL;
648 if (yuvbuf != NULL)
649 free(yuvbuf);
650
651 while (modelist != NULL) {
652 list=modelist;
653 modelist=modelist->next;
654 free(list);
655 }
656 checked = 0;
657 }
658
659 610
660 /* --------------------------------------------------------------------- */ 611 /* --------------------------------------------------------------------- */
661
662 static uint32_t add_mode(uint16_t mode, vga_modeinfo minfo) {
663 vga_modelist_t *list;
664
665 if(squarepix && (minfo.height*4 != minfo.width*3)) return 0;
666
667 if (modelist == NULL) {
668 modelist = (vga_modelist_t *) malloc(sizeof(vga_modelist_t));
669 if (modelist == NULL) {
670 printf("vo_svga: add_mode() failed. Not enough memory for modelist.");
671 return(1); // error
672 }
673 modelist->modenum = mode;
674 modelist->modeinfo = minfo;
675 modelist->next = NULL;
676 } else {
677 list = modelist;
678 while (list->next != NULL)
679 list = list->next;
680 list->next = (vga_modelist_t *) malloc(sizeof(vga_modelist_t));
681 if (list->next == NULL) {
682 printf("vo_svga: add_mode() failed. Not enough memory for modelist.");
683 return(1); // error
684 }
685 list = list->next;
686 list->modenum = mode;
687 list->modeinfo = minfo;
688 list->next = NULL;
689 }
690 return (0);
691 }
692
693 static int checksupportedmodes() {
694 uint16_t i, max;
695 vga_modeinfo *minfo;
696
697 checked = 1;
698 getch2_disable();
699 vga_init();
700 vga_disabledriverreport();
701 max = vga_lastmodenumber();
702 if (verbose >= 2)
703 printf("vo_svga: Max mode : %i\n",max);
704 for (i = 1; i <= max; i++)
705 if (vga_hasmode(i) > 0) {
706 minfo = vga_getmodeinfo(i);
707 switch (minfo->colors) {
708 case 2 : bpp_avail |= BPP_1 ; break;
709 case 16 : bpp_avail |= BPP_4 ; break;
710 case 256 : bpp_avail |= BPP_8 ; break;
711 case 32768: bpp_avail |= BPP_15; break;
712 case 65536: bpp_avail |= BPP_16; break;
713 }
714 switch (minfo->bytesperpixel) {
715 case 3: bpp_avail |= BPP_24; break;
716 case 4: bpp_avail |= BPP_32; break;
717 }
718 if (verbose >= 2)
719 printf("vo_svga: Mode found: %s\n",vga_getmodename(i));
720 if (add_mode(i, *minfo))
721 return(1);
722 }
723 return(0);
724 }
725
726
727 static uint32_t query_format(uint32_t format) { 612 static uint32_t query_format(uint32_t format) {
728 uint32_t res = 0; 613 int32_t req_bpp,flags;
729 614 int i,lastmode;
730 if (!checked) { 615 vga_modeinfo * vminfo;
731 if (checksupportedmodes()) // Looking for available video modes 616
732 return(0); 617 if (verbose >3)
733 } 618 printf("vo_svga: query_format=%X \n",format);
734 619 //only RGB modes supported
735 // if (vo_dbpp) => There is NO conversion!!! 620 if( (!IMGFMT_IS_RGB(format)) && (!IMGFMT_IS_BGR(format)) ) return 0;
736 if (vo_dbpp) { 621
737 if (format == IMGFMT_YV12) return (1); 622 // Reject different endian
738 switch (vo_dbpp) { 623 #ifdef WORDS_BIGENDIAN
739 case 32: if ((format == IMGFMT_RGB32) || (format == IMGFMT_BGR32)) 624 if (IMGFMT_IS_BGR(format)) return 0;
740 return ((bpp_avail & BPP_32) ? 1 : 0); 625 #else
741 break; 626 if (IMGFMT_IS_RGB(format)) return 0;
742 case 24: if ((format == IMGFMT_RGB24) || (format == IMGFMT_BGR24)) 627 #endif
743 return ((bpp_avail & BPP_24) ? 1 : 0); 628
744 break; 629 //svgalib supports only BG4B! if we want BGR4 we have to emulate it (sw)
745 case 16: if ((format == IMGFMT_RGB16) || (format == IMGFMT_BGR16)) 630 if( format==IMGFMT_BGR4 || format==IMGFMT_RGB4) return 0;
746 return ((bpp_avail & BPP_16) ? 1 : 0); 631 req_bpp = IMGFMT_RGB_DEPTH(format);
747 break; 632 if( vo_dbpp>0 && vo_dbpp!=req_bpp ) return 0; //support -bpp options
748 case 15: if ((format == IMGFMT_RGB15) || (format == IMGFMT_BGR15)) 633 //scan all modes
749 return ((bpp_avail & BPP_15) ? 1 : 0); 634 lastmode = vga_lastmodenumber();
750 break; 635 for(i=1;i<lastmode;i++){
751 case 8 : if ((format == IMGFMT_RGB8 ) || (format == IMGFMT_BGR8)) 636 vminfo = vga_getmodeinfo(i);
752 return ((bpp_avail & BPP_8 ) ? 1 : 0); 637 if( vminfo == NULL ) continue;
753 break; 638 if( vga_hasmode(i) == 0 ) continue;
754 case 4 : if ((format == IMGFMT_RG4B ) || (format == IMGFMT_BG4B)) 639 if( req_bpp != bpp_from_vminfo(vminfo) ) continue;
755 return ((bpp_avail & BPP_4 ) ? 1 : 0); 640 if( (force_vm > 0) && (force_vm != i) ) continue;//quick hack
756 break; 641 flags = VFCAP_CSP_SUPPORTED|
757 case 1 : if ((format == IMGFMT_RGB1 ) || (format == IMGFMT_BGR1)) 642 VFCAP_CSP_SUPPORTED_BY_HW|
758 return ((bpp_avail & BPP_1 ) ? 1 : 0); 643 VFCAP_ACCEPT_STRIDE|
759 break; 644 0;
760 } 645 if(req_bpp>8) flags|=VFCAP_OSD;
761 } else { 646 return flags;
762 switch (format) { 647 }
763 case IMGFMT_RGB32: 648 return 0;
764 case IMGFMT_BGR32: return ((bpp_avail & BPP_32) ? 1 : 0); break;
765 case IMGFMT_RGB24:
766 case IMGFMT_BGR24: {
767 res = (bpp_avail & BPP_24) ? 1 : 0;
768 if (!res)
769 res = (bpp_avail & BPP_32) ? 1 : 0;
770 return (res);
771 } break;
772 case IMGFMT_RGB16:
773 case IMGFMT_BGR16: return ((bpp_avail & BPP_16) ? 1 : 0); break;
774 case IMGFMT_RGB15:
775 case IMGFMT_BGR15: {
776 res = (bpp_avail & BPP_15) ? 1 : 0;
777 if (!res)
778 res = (bpp_avail & BPP_16) ? 1 : 0;
779 return (res);
780 } break;
781 case IMGFMT_YV12: return (1); break;
782 }
783 }
784 return (0);
785 }
786
787 static void putbox(int x, int y, int w, int h, uint8_t *buf, int prog) {
788 int base, add, wid;
789 if(bpp==1)
790 wid=(w+7)/8;
791 else
792 wid=w*BYTESPERPIXEL;
793
794 if(oldmethod) {
795 add=wid*prog;
796 while( (h--) > 0 ) {
797 if(bpp==1)
798 memcpy(buffer+(x+7)/8+(y++)*LINEWIDTH, buf, wid);
799 else
800 memcpy(buffer+x*BYTESPERPIXEL+(y++)*LINEWIDTH, buf, wid);
801 buf+=add;
802 }
803 } else {
804 add=wid*prog;
805 base=frame*HEIGHT;
806 while( (h--) > 0 ) {
807 vga_drawscansegment(buf, x, (y++)+base, wid);
808 buf+=add;
809 }
810 }
811 }
812
813 static void fillbox(int x, int y, int w, int h, uint32_t c) {
814 putbox(x,y,w,h,buf0,0);
815 } 649 }
816 650
817 static void draw_alpha(int x0, int y0, int w, int h, unsigned char *src, 651 static void draw_alpha(int x0, int y0, int w, int h, unsigned char *src,
818 unsigned char *srca, int stride) { 652 unsigned char *srca, int stride) {
819 char* base; 653 char* base;
820 654 int bytelen;
821 if(oldmethod) { 655
822 base=buffer; 656 if(verbose>2)
823 } else 657 printf("vo_svga: draw_alpha(x0=%d,y0=%d,w=%d,h=%d,src=%p,srca=%p,stride=%d\n",
824 base=((frame*HEIGHT+y_pos)*WIDTH+x_pos)*BYTESPERPIXEL + GRAPH_MEM ; 658 x0,y0,w,h,src,srca,stride);
825 659 x0+=x_pos;// in case of drawing over image
826 switch (bpp) { 660 y0+=y_pos;
661
662 //only modes with bytesperpixel>0 can draw OSD
663 if(modeinfo->bytesperpixel==0) return;
664 // if(!(mode_capabilities&CAP_LINEAR)) return;//force_native will remove OSD
665
666 base=PageStore[cpage].vbase + y0*mode_stride + x0*modeinfo->bytesperpixel;
667 bytelen = modeinfo->width * modeinfo->bytesperpixel;
668 switch (mode_bpp) {
827 case 32: 669 case 32:
828 vo_draw_alpha_rgb32(w, h, src, srca, stride, base+4*(y0*WIDTH+x0), 4*WIDTH); 670 vo_draw_alpha_rgb32(w, h, src, srca, stride, base, bytelen);
829 break; 671 break;
830 case 24: 672 case 24:
831 vo_draw_alpha_rgb24(w, h, src, srca, stride, base+3*(y0*WIDTH+x0), 3*WIDTH); 673 vo_draw_alpha_rgb24(w, h, src, srca, stride, base, bytelen);
832 break; 674 break;
833 case 16: 675 case 16:
834 vo_draw_alpha_rgb16(w, h, src, srca, stride, base+2*(y0*WIDTH+x0), 2*WIDTH); 676 vo_draw_alpha_rgb16(w, h, src, srca, stride, base, bytelen);
835 break; 677 break;
836 case 15: 678 case 15:
837 vo_draw_alpha_rgb15(w, h, src, srca, stride, base+2*(y0*WIDTH+x0), 2*WIDTH); 679 vo_draw_alpha_rgb15(w, h, src, srca, stride, base, bytelen);
838 break; 680 break;
839 } 681 }
840 } 682 }
841 683
842 static uint32_t get_image(mp_image_t *mpi) 684 static uint32_t get_image(mp_image_t *mpi){
843 { 685 int page;
844 if (/* zoomFlag || */ 686
845 !IMGFMT_IS_BGR(mpi->imgfmt) || 687 if(!IMGFMT_IS_BGR(mpi->imgfmt) && !IMGFMT_IS_RGB(mpi->imgfmt) ){
846 ((mpi->type != MP_IMGTYPE_STATIC) && (mpi->type != MP_IMGTYPE_TEMP)) || 688 assert(0);//should never happen
847 (mpi->flags & MP_IMGFLAG_PLANAR) || 689 return(VO_FALSE);
848 (mpi->flags & MP_IMGFLAG_YUV) /* 690 }
849 (mpi->width != image_width) || 691
850 (mpi->height != image_height) */ 692 if (
851 ) 693 ( (mpi->type != MP_IMGTYPE_STATIC) && (mpi->type != MP_IMGTYPE_TEMP)) ||
852 return(VO_FALSE); 694 (mpi->flags & MP_IMGFLAG_PLANAR) ||
853 if(!directrender) 695 (mpi->flags & MP_IMGFLAG_YUV)
854 return (VO_FALSE); 696 )
855 /* 697 return(VO_FALSE);
856 if (Flip_Flag) 698
857 { 699 //reading from video memory is horribly slow
858 mpi->stride[0] = -image_width*((bpp+7)/8); 700 if( !(mpi->flags & MP_IMGFLAG_READABLE) && vo_directrendering &&
859 mpi->planes[0] = ImageData - mpi->stride[0]*(image_height-1); 701 (mode_capabilities & CAP_LINEAR) ){
860 } 702 page=page_get_image();
861 else 703 if(page >= 0){
862 */ 704 mpi->flags |= MP_IMGFLAG_DIRECT;
863 { 705 mpi->stride[0] = mode_stride;
864 mpi->stride[0] = LINEWIDTH; 706 mpi->planes[0] = PageStore[page].vbase +
865 if(oldmethod) { 707 y_pos*mode_stride + (x_pos*mpi->bpp)/8;
866 mpi->planes[0] = buffer; 708 (int)mpi->priv=page;
867 } else 709 if(verbose>2)
868 mpi->planes[0] = GRAPH_MEM; 710 printf("vo_svga: direct render allocated! page=%d\n",page);
869 } 711 return(VO_TRUE);
870 mpi->flags |= MP_IMGFLAG_DIRECT; 712 }
871 713 }
872 return(VO_TRUE); 714
873 } 715 return(VO_FALSE);
874 716 }