Mercurial > mplayer.hg
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 } |