Mercurial > mplayer.hg
annotate libvo/vo_svga.c @ 501:bfc86f5a5ba7
PES supported again, VOB 0x1F0 problems fixed
author | arpi_esp |
---|---|
date | Wed, 18 Apr 2001 01:56:10 +0000 |
parents | 108be5ee3b1a |
children | 75c689abb763 |
rev | line source |
---|---|
285 | 1 /* |
292 | 2 Video driver for SVGAlib - alpha, slow |
285 | 3 by Zoltan Mark Vician <se7en@sch.bme.hu> |
381 | 4 Code started: Mon Apr 1 23:25:47 2001 |
407 | 5 |
6 Uses HW acceleration if your card is supported by SVGAlib. | |
285 | 7 */ |
8 | |
9 #include <stdio.h> | |
10 #include <stdlib.h> | |
11 | |
12 #include <vga.h> | |
13 #include <vgagl.h> | |
14 | |
485 | 15 #include <limits.h> |
16 | |
285 | 17 #include "config.h" |
18 #include "video_out.h" | |
19 #include "video_out_internal.h" | |
20 | |
21 #include "yuv2rgb.h" | |
377 | 22 #include "mmx.h" |
285 | 23 |
407 | 24 extern void rgb15to16_mmx(char* s0,char* d0,int count); |
485 | 25 extern int vo_dbpp; |
407 | 26 |
285 | 27 LIBVO_EXTERN(svga) |
28 | |
29 static vo_info_t vo_info = { | |
30 "SVGAlib", | |
31 "svga", | |
32 "Zoltan Mark Vician <se7en@sch.bme.hu>", | |
33 "" | |
34 }; | |
35 | |
36 // SVGAlib definitions | |
37 | |
38 GraphicsContext *screen; | |
39 GraphicsContext *virt; | |
40 | |
407 | 41 static uint8_t *scalebuf = NULL, *yuvbuf = NULL, *bppbuf = NULL; |
285 | 42 |
43 static uint32_t orig_w, orig_h, maxw, maxh; // Width, height | |
377 | 44 static float scaling = 1.0; |
285 | 45 static uint32_t x_pos, y_pos; // Position |
46 | |
483 | 47 // SVGAlib - list of detected modes |
48 typedef struct vga_modelist_s { | |
49 uint16_t modenum; | |
50 vga_modeinfo modeinfo; | |
51 struct vga_modelist_s *next; | |
52 } vga_modelist_t; | |
447 | 53 |
483 | 54 vga_modelist_t *modelist = NULL; |
55 | |
327 | 56 static uint8_t bpp; |
483 | 57 static uint8_t bpp_conv = 0; |
448
198b46b739d8
qrva eletbe nem kene cvs-t elbaszni inkabb ne nyuljatok hozza baz+
arpi_esp
parents:
447
diff
changeset
|
58 static uint32_t pformat; |
447 | 59 |
483 | 60 #define BPP_15 1 |
61 #define BPP_16 2 | |
62 #define BPP_24 4 | |
63 #define BPP_32 8 | |
64 static uint8_t bpp_avail = 0; | |
65 | |
285 | 66 static uint8_t checked = 0; |
483 | 67 |
485 | 68 static uint32_t add_mode(uint16_t mode, vga_modeinfo minfo) { |
483 | 69 vga_modelist_t *list; |
285 | 70 |
483 | 71 if (modelist == NULL) { |
485 | 72 modelist = (vga_modelist_t *) malloc(sizeof(vga_modelist_t)); |
483 | 73 if (modelist == NULL) { |
74 printf("vo_svga: add_mode() failed. Not enough memory for modelist."); | |
75 return(1); // error | |
76 } | |
485 | 77 modelist->modenum = mode; |
78 modelist->modeinfo = minfo; | |
79 modelist->next = NULL; | |
483 | 80 } else { |
81 list = modelist; | |
82 while (list->next != NULL) | |
83 list = list->next; | |
485 | 84 list->next = (vga_modelist_t *) malloc(sizeof(vga_modelist_t)); |
483 | 85 if (list->next == NULL) { |
86 printf("vo_svga: add_mode() failed. Not enough memory for modelist."); | |
87 return(1); // error | |
88 } | |
89 list = list->next; | |
90 list->modenum = mode; | |
91 list->modeinfo = minfo; | |
92 list->next = NULL; | |
93 } | |
485 | 94 return (0); |
483 | 95 } |
96 | |
97 static int checksupportedmodes() { | |
485 | 98 uint16_t i, max; |
483 | 99 vga_modeinfo *minfo; |
285 | 100 |
101 checked = 1; | |
102 vga_init(); | |
103 vga_disabledriverreport(); | |
485 | 104 max = vga_lastmodenumber(); |
105 for (i = 1; i < max; i++) | |
483 | 106 if (vga_hasmode(i) > 0) { |
107 minfo = vga_getmodeinfo(i); | |
108 switch (minfo->colors) { | |
109 case 32768: bpp_avail |= BPP_15; break; | |
110 case 65536: bpp_avail |= BPP_16; break; | |
111 } | |
112 switch (minfo->bytesperpixel) { | |
113 case 3: bpp_avail |= BPP_24; break; | |
114 case 4: bpp_avail |= BPP_32; break; | |
115 } | |
116 if (add_mode(i, *minfo)) | |
117 return(1); | |
118 } | |
485 | 119 return(0); |
285 | 120 } |
121 | |
122 static uint32_t init(uint32_t width, uint32_t height, uint32_t d_width, | |
123 uint32_t d_height, uint32_t fullscreen, char *title, | |
124 uint32_t format) { | |
483 | 125 uint32_t req_w = (d_width > 0 ? d_width : width); |
126 uint32_t req_h = (d_height > 0 ? d_height : height); | |
127 uint16_t vid_mode = 0; | |
128 uint8_t widescreen = (((req_w*1.0)/req_h) > (4.0/3)) ? 1 : 0; | |
485 | 129 uint16_t buf_w = USHRT_MAX, buf_h = USHRT_MAX; |
483 | 130 vga_modelist_t *list = modelist; |
387 | 131 |
285 | 132 if (!checked) { |
485 | 133 if (checksupportedmodes()) // Looking for available video modes |
483 | 134 return(1); |
285 | 135 } |
407 | 136 |
483 | 137 bpp_avail = 0; |
138 while (list != NULL) { | |
139 if ((list->modeinfo.width >= req_w) && (list->modeinfo.height >= req_h)) { | |
485 | 140 // printf("w: %d, h: %d, bpp: %d, colors: %d\n",list->modeinfo.width,list->modeinfo.height,list->modeinfo.bytesperpixel,list->modeinfo.colors); |
483 | 141 switch (list->modeinfo.colors) { |
142 case 32768: bpp_avail |= BPP_15; break; | |
143 case 65536: bpp_avail |= BPP_16; break; | |
144 } | |
145 switch (list->modeinfo.bytesperpixel) { | |
146 case 3: bpp_avail |= BPP_24; break; | |
147 case 4: bpp_avail |= BPP_32; break; | |
148 } | |
149 } | |
150 list = list->next; | |
151 } | |
152 | |
285 | 153 pformat = format; |
411 | 154 |
483 | 155 // bpp check |
156 bpp_conv = 0; | |
411 | 157 if (!vo_dbpp) { |
158 if (format == IMGFMT_YV12) bpp = 32; | |
159 else bpp = format & 255; | |
485 | 160 // printf("bpp: %d\n",bpp); |
483 | 161 switch (bpp) { |
162 case 32: if (!(bpp_avail & BPP_32)) { | |
163 printf("vo_svga: Haven't found video mode which fit to: %dx%d %dbpp\n",req_w,req_h,bpp); | |
485 | 164 printf("vo_svga: Maybe you should try -bpp\n"); |
483 | 165 return(1); |
166 } | |
167 break; | |
168 case 24: if (!(bpp_avail & BPP_24)) | |
169 if (!(bpp_avail & BPP_32)) { | |
170 printf("vo_svga: Haven't found video mode which fit to: %dx%d %dbpp\n",req_w,req_h,bpp); | |
485 | 171 printf("vo_svga: Maybe you should try -bpp\n"); |
483 | 172 return(1); |
173 } else { | |
174 bpp = 32; | |
175 bpp_conv = 1; | |
176 } | |
177 break; | |
178 case 16: if (!(bpp_avail & BPP_16)) { | |
179 printf("vo_svga: Haven't found video mode which fit to: %dx%d %dbpp\n",req_w,req_h,bpp); | |
180 printf("vo_svga: Maybe you should try -bpp\n"); | |
181 return(1); | |
182 } | |
183 break; | |
184 case 15: if (!(bpp_avail & BPP_15)) | |
185 if (!(bpp_avail & BPP_16)) { | |
186 printf("vo_svga: Haven't found video mode which fit to: %dx%d %dbpp\n",req_w,req_h,bpp); | |
187 printf("vo_svga: Maybe you should try -bpp\n"); | |
188 return(1); | |
189 } else { | |
190 bpp = 16; | |
191 bpp_conv = 1; | |
192 } | |
193 break; | |
194 } | |
411 | 195 } else { |
196 bpp = vo_dbpp; | |
197 switch (bpp) { | |
483 | 198 case 32: if (!(bpp_avail & BPP_32)) { |
485 | 199 printf("vo_svga: %dbpp not supported in %dx%d (or larger resoltuion) by HW or SVGAlib\n",bpp,req_w,req_h); |
411 | 200 return(1); |
201 } | |
485 | 202 break; |
483 | 203 case 24: if (!(bpp_avail & BPP_24)) { |
485 | 204 printf("vo_svga: %dbpp not supported in %dx%d (or larger resoltuion) by HW or SVGAlib\n",bpp,req_w,req_h); |
411 | 205 return(1); |
206 } | |
485 | 207 break; |
483 | 208 case 16: if (!(bpp_avail & BPP_16)) { |
485 | 209 printf("vo_svga: %dbpp not supported in %dx%d (or larger resoltuion) by HW or SVGAlib\n",bpp,req_w,req_h); |
411 | 210 return(1); |
211 } | |
485 | 212 break; |
483 | 213 case 15: if (!(bpp_avail & BPP_15)) { |
485 | 214 printf("vo_svga: %dbpp not supported in %dx%d (or larger resoltuion) by HW or SVGAlib\n",bpp,req_w,req_h); |
411 | 215 return(1); |
216 } | |
485 | 217 break; |
411 | 218 } |
219 } | |
483 | 220 |
221 list = modelist; | |
485 | 222 // printf("req_w: %d, req_h: %d\n",req_w,req_h); |
223 while (list != NULL) { | |
483 | 224 if ((list->modeinfo.width >= req_w) && (list->modeinfo.height >= req_h)) { |
485 | 225 // printf("w: %d, h: %d, bpp: %d, colors: %d, req_bpp: %d\n",list->modeinfo.width,list->modeinfo.height,list->modeinfo.bytesperpixel,list->modeinfo.colors,bpp); |
285 | 226 switch (bpp) { |
483 | 227 case 32: if (list->modeinfo.bytesperpixel == 4) |
485 | 228 if ((list->modeinfo.width < buf_w) || (list->modeinfo.height < buf_h)) { |
229 vid_mode = list->modenum; | |
230 buf_w = list->modeinfo.width; | |
231 buf_h = list->modeinfo.height; | |
232 } | |
233 break; | |
483 | 234 case 24: if (list->modeinfo.bytesperpixel == 3) |
485 | 235 if ((list->modeinfo.width < buf_w) || (list->modeinfo.height < buf_h)) { |
236 vid_mode = list->modenum; | |
237 buf_w = list->modeinfo.width; | |
238 buf_h = list->modeinfo.height; | |
239 } | |
240 break; | |
483 | 241 case 16: if (list->modeinfo.colors == 65536) |
485 | 242 if ((list->modeinfo.width < buf_w) || (list->modeinfo.height < buf_h)) { |
243 vid_mode = list->modenum; | |
244 buf_w = list->modeinfo.width; | |
245 buf_h = list->modeinfo.height; | |
246 } | |
247 break; | |
483 | 248 case 15: if (list->modeinfo.colors == 32768) |
485 | 249 if ((list->modeinfo.width < buf_w) || (list->modeinfo.height < buf_h)) { |
250 vid_mode = list->modenum; | |
251 buf_w = list->modeinfo.width; | |
252 buf_h = list->modeinfo.height; | |
253 } | |
254 break; | |
285 | 255 } |
483 | 256 } |
257 list = list->next; | |
407 | 258 } |
485 | 259 |
260 // printf("vid_mode: %d\n",vid_mode); | |
407 | 261 vga_setlinearaddressing(); |
485 | 262 if (vga_setmode(vid_mode) == -1) { |
286 | 263 printf("vo_svga: vga_setmode(%d) failed.\n",vid_mode); |
483 | 264 uninit(); |
285 | 265 return(1); // error |
485 | 266 } |
267 if (gl_setcontextvga(vid_mode)) { | |
286 | 268 printf("vo_svga: gl_setcontextvga(%d) failed.\n",vid_mode); |
483 | 269 uninit(); |
285 | 270 return(1); // error |
286 | 271 } |
285 | 272 screen = gl_allocatecontext(); |
273 gl_getcontext(screen); | |
485 | 274 if (gl_setcontextvgavirtual(vid_mode)) { |
286 | 275 printf("vo_svga: gl_setcontextvgavirtual(%d) failed.\n",vid_mode); |
483 | 276 uninit(); |
285 | 277 return(1); // error |
286 | 278 } |
285 | 279 virt = gl_allocatecontext(); |
280 gl_getcontext(virt); | |
281 gl_setcontext(virt); | |
282 gl_clearscreen(0); | |
283 | |
485 | 284 if (bpp_conv) { |
483 | 285 bppbuf = malloc(maxw * maxh * BYTESPERPIXEL); |
485 | 286 if (bppbuf == NULL) { |
287 printf("vo_svga: bppbuf -> Not enough memory for buffering!\n"); | |
288 uninit(); | |
289 return (1); | |
290 } | |
483 | 291 } |
292 | |
285 | 293 orig_w = width; |
294 orig_h = height; | |
343 | 295 if ((fullscreen & 0x04) && (WIDTH != orig_w)) { |
483 | 296 if (!widescreen) { |
292 | 297 maxh = HEIGHT; |
298 scaling = maxh / (orig_h * 1.0); | |
299 maxw = (uint32_t) (orig_w * scaling); | |
300 scalebuf = malloc(maxw * maxh * BYTESPERPIXEL); | |
483 | 301 if (scalebuf == NULL) { |
485 | 302 printf("vo_svga: scalebuf -> Not enough memory for buffering!\n"); |
407 | 303 uninit(); |
304 return (1); | |
305 } | |
292 | 306 } else { |
307 maxw = WIDTH; | |
308 scaling = maxw / (orig_w * 1.0); | |
309 maxh = (uint32_t) (orig_h * scaling); | |
310 scalebuf = malloc(maxw * maxh * BYTESPERPIXEL); | |
483 | 311 if (scalebuf == NULL) { |
485 | 312 printf("vo_svga: scalebuf -> Not enough memory for buffering!\n"); |
407 | 313 uninit(); |
314 return (1); | |
315 } | |
292 | 316 } |
285 | 317 } else { |
318 maxw = orig_w; | |
319 maxh = orig_h; | |
320 } | |
321 x_pos = (WIDTH - maxw) / 2; | |
322 y_pos = (HEIGHT - maxh) / 2; | |
323 | |
324 if (pformat == IMGFMT_YV12) { | |
325 yuv2rgb_init(bpp, MODE_RGB); | |
326 yuvbuf = malloc(maxw * maxh * BYTESPERPIXEL); | |
483 | 327 if (yuvbuf == NULL) { |
485 | 328 printf("vo_svga: yuvbuf -> Not enough memory for buffering!\n"); |
407 | 329 uninit(); |
330 return (1); | |
331 } | |
285 | 332 } |
377 | 333 |
485 | 334 // printf("bpp_conv: %d\n",bpp_conv); |
292 | 335 printf("SVGAlib resolution: %dx%d %dbpp - ", WIDTH, HEIGHT, bpp); |
293 | 336 if (maxw != orig_w || maxh != orig_h) printf("Video scaled to: %dx%d\n",maxw,maxh); |
285 | 337 else printf("No video scaling\n"); |
338 | |
339 return (0); | |
340 } | |
341 | |
342 static uint32_t query_format(uint32_t format) { | |
485 | 343 uint32_t res = 0; |
407 | 344 |
483 | 345 if (!checked) { |
346 if (checksupportedmodes()) // Looking for available video modes | |
347 return(0); | |
348 } | |
485 | 349 |
350 // if (vo_dbpp) => There is NO conversion!!! | |
351 if (vo_dbpp) { | |
352 switch (vo_dbpp) { | |
488 | 353 case 32: if ((format == IMGFMT_RGB32) || (format == IMGFMT_BGR32)) |
485 | 354 return ((bpp_avail & BPP_32) ? 1 : 0); |
355 break; | |
488 | 356 case 24: if ((format == IMGFMT_RGB24) || (format == IMGFMT_BGR24)) |
485 | 357 return ((bpp_avail & BPP_24) ? 1 : 0); |
358 break; | |
488 | 359 case 16: if ((format == IMGFMT_RGB16) || (format == IMGFMT_BGR16)) |
485 | 360 return ((bpp_avail & BPP_16) ? 1 : 0); |
361 break; | |
488 | 362 case 15: if ((format == IMGFMT_RGB15) || (format == IMGFMT_BGR15)) |
485 | 363 return ((bpp_avail & BPP_15) ? 1 : 0); |
364 break; | |
407 | 365 } |
488 | 366 } else { |
485 | 367 switch (format) { |
368 case IMGFMT_RGB32: | |
488 | 369 case IMGFMT_BGR32: return ((bpp_avail & BPP_32) ? 1 : 0); break; |
485 | 370 case IMGFMT_RGB24: |
488 | 371 case IMGFMT_BGR24: { |
485 | 372 res = (bpp_avail & BPP_24) ? 1 : 0; |
373 if (!res) | |
374 res = (bpp_avail & BPP_32) ? 1 : 0; | |
375 return (res); | |
376 } break; | |
377 case IMGFMT_RGB16: | |
488 | 378 case IMGFMT_BGR16: return ((bpp_avail & BPP_16) ? 1 : 0); break; |
485 | 379 case IMGFMT_RGB15: |
488 | 380 case IMGFMT_BGR15: { |
485 | 381 res = (bpp_avail & BPP_15) ? 1 : 0; |
382 if (!res) | |
383 res = (bpp_avail & BPP_16) ? 1 : 0; | |
384 return (res); | |
385 } break; | |
386 case IMGFMT_YV12: return (1); break; | |
285 | 387 } |
488 | 388 } |
285 | 389 return (0); |
390 } | |
391 | |
392 static const vo_info_t* get_info(void) { | |
393 return (&vo_info); | |
394 } | |
395 | |
396 static void draw_alpha(int x0, int y0, int w, int h, unsigned char *src, | |
397 unsigned char *srca, int stride) { | |
327 | 398 switch (bpp) { |
399 case 32: | |
400 vo_draw_alpha_rgb32(w, h, src, srca, stride, virt->vbuf+4*(y0*WIDTH+x0), 4*WIDTH); | |
401 break; | |
402 case 24: | |
403 vo_draw_alpha_rgb24(w, h, src, srca, stride, virt->vbuf+3*(y0*WIDTH+x0), 3*WIDTH); | |
404 break; | |
405 case 16: | |
406 vo_draw_alpha_rgb16(w, h, src, srca, stride, virt->vbuf+2*(y0*WIDTH+x0), 2*WIDTH); | |
407 break; | |
408 case 15: | |
409 vo_draw_alpha_rgb15(w, h, src, srca, stride, virt->vbuf+2*(y0*WIDTH+x0), 2*WIDTH); | |
410 break; | |
411 } | |
285 | 412 } |
413 | |
414 static uint32_t draw_frame(uint8_t *src[]) { | |
415 if (pformat == IMGFMT_YV12) { | |
416 yuv2rgb(yuvbuf, src[0], src[1], src[2], orig_w, orig_h, orig_w * BYTESPERPIXEL, orig_w, orig_w / 2); | |
417 src[0] = yuvbuf; | |
418 } | |
483 | 419 if (scalebuf != NULL) { |
285 | 420 gl_scalebox(orig_w, orig_h, src[0], maxw, maxh, scalebuf); |
421 src[0] = scalebuf; | |
422 } | |
407 | 423 if (bpp_conv) { |
485 | 424 uint16_t *source = (uint16_t *) src[0]; |
407 | 425 uint16_t *dest = (uint16_t *) bppbuf; |
426 uint16_t *end; | |
427 | |
428 switch(bpp) { | |
485 | 429 case 32: { |
430 end = source + (maxw * maxh * 2); | |
431 while (source < end) { | |
432 *dest++ = *source++; | |
433 (uint8_t *)dest = (uint8_t *)source; | |
407 | 434 *(((uint8_t *)dest)+1) = 0; |
435 dest++; | |
485 | 436 source++; |
407 | 437 } |
485 | 438 } break; |
439 case 16: { | |
407 | 440 #ifdef HAVE_MMX |
441 rgb15to16_mmx(src[0],bppbuf,maxw * maxh * 2); | |
442 #else | |
443 register uint16_t srcdata; | |
444 | |
485 | 445 end = source + (maxw * maxh); |
446 while (source < end) { | |
447 srcdata = *source++; | |
407 | 448 *dest++ = (srcdata & 0x1f) | ((srcdata & 0x7fe0) << 1); |
449 } | |
450 #endif | |
485 | 451 } break; |
407 | 452 } |
453 src[0] = bppbuf; | |
454 } | |
285 | 455 gl_putbox(x_pos, y_pos, maxw, maxh, src[0]); |
456 } | |
457 | |
458 static uint32_t draw_slice(uint8_t *image[], int stride[], | |
459 int w, int h, int x, int y) { | |
460 uint8_t *src = yuvbuf; | |
377 | 461 uint32_t sw, sh; |
462 | |
463 emms(); | |
464 sw = (uint32_t) (w * scaling); | |
465 sh = (uint32_t) (h * scaling); | |
285 | 466 yuv2rgb(yuvbuf, image[0], image[1], image[2], w, h, orig_w * BYTESPERPIXEL, stride[0], stride[1]); |
483 | 467 if (scalebuf != NULL) { |
377 | 468 gl_scalebox(w, h, yuvbuf, sw, sh, scalebuf); |
285 | 469 src = scalebuf; |
470 } | |
377 | 471 gl_putbox((int)(x * scaling) + x_pos, (int)(y * scaling) + y_pos, sw, sh, src); |
285 | 472 } |
473 | |
474 static void flip_page(void) { | |
292 | 475 if (y_pos) { |
476 gl_fillbox(0, 0, WIDTH, y_pos, 0); | |
477 gl_fillbox(0, HEIGHT - y_pos, WIDTH, y_pos, 0); | |
478 } else { | |
479 gl_fillbox(0, 0, x_pos, HEIGHT, 0); | |
480 gl_fillbox(WIDTH - x_pos, 0, x_pos, HEIGHT, 0); | |
327 | 481 } |
486 | 482 vo_draw_text(WIDTH, HEIGHT, draw_alpha); |
285 | 483 gl_copyscreen(screen); |
484 } | |
485 | |
486 static void check_events(void) { | |
487 } | |
488 | |
489 static void uninit(void) { | |
483 | 490 vga_modelist_t *list = modelist; |
491 | |
285 | 492 gl_freecontext(screen); |
493 gl_freecontext(virt); | |
494 vga_setmode(TEXT); | |
483 | 495 if (bppbuf != NULL) |
407 | 496 free(bppbuf); |
483 | 497 if (scalebuf != NULL) |
285 | 498 free(scalebuf); |
483 | 499 if (yuvbuf != NULL) |
285 | 500 free(yuvbuf); |
483 | 501 if (modelist != NULL) { |
502 while (modelist->next != NULL) { | |
503 list = modelist; | |
504 while (list->next != NULL) | |
505 list = list->next; | |
506 free(list); | |
507 } | |
508 free(modelist); | |
509 } | |
285 | 510 } |
511 |