Mercurial > sdl-ios-xcode
comparison src/video/fbcon/SDL_fbvideo.c @ 1215:d082d2d66ec8
Added support for parsing /etc/fb.modes, based on Stephane Marchesin's patch
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Mon, 02 Jan 2006 09:08:05 +0000 |
parents | 50f4e7e4d117 |
children | ae9981987c2f |
comparison
equal
deleted
inserted
replaced
1214:31103dbf1c26 | 1215:d082d2d66ec8 |
---|---|
49 #include "SDL_fbevents_c.h" | 49 #include "SDL_fbevents_c.h" |
50 #include "SDL_fb3dfx.h" | 50 #include "SDL_fb3dfx.h" |
51 #include "SDL_fbmatrox.h" | 51 #include "SDL_fbmatrox.h" |
52 #include "SDL_fbriva.h" | 52 #include "SDL_fbriva.h" |
53 | 53 |
54 /*#define FBCON_DEBUG*/ | |
54 | 55 |
55 #if defined(i386) && defined(FB_TYPE_VGA_PLANES) | 56 #if defined(i386) && defined(FB_TYPE_VGA_PLANES) |
56 #define VGA16_FBCON_SUPPORT | 57 #define VGA16_FBCON_SUPPORT |
57 #ifndef FB_AUX_VGA_PLANES_VGA4 | 58 #ifndef FB_AUX_VGA_PLANES_VGA4 |
58 #define FB_AUX_VGA_PLANES_VGA4 0 | 59 #define FB_AUX_VGA_PLANES_VGA4 0 |
232 VideoBootStrap FBCON_bootstrap = { | 233 VideoBootStrap FBCON_bootstrap = { |
233 "fbcon", "Linux Framebuffer Console", | 234 "fbcon", "Linux Framebuffer Console", |
234 FB_Available, FB_CreateDevice | 235 FB_Available, FB_CreateDevice |
235 }; | 236 }; |
236 | 237 |
238 #define FB_MODES_DB "/etc/fb.modes" | |
239 | |
240 static int read_fbmodes_line(FILE*f, char* line, int length) | |
241 { | |
242 int blank; | |
243 char* c; | |
244 int i; | |
245 | |
246 blank=0; | |
247 /* find a relevant line */ | |
248 do | |
249 { | |
250 if (fgets(line,length,f)<=0) | |
251 return 0; | |
252 c=line; | |
253 while(((*c=='\t')||(*c==' '))&&(*c!=0)) | |
254 c++; | |
255 | |
256 if ((*c=='\n')||(*c=='#')||(*c==0)) | |
257 blank=1; | |
258 else | |
259 blank=0; | |
260 } | |
261 while(blank); | |
262 /* remove whitespace at the begining of the string */ | |
263 i=0; | |
264 do | |
265 { | |
266 line[i]=c[i]; | |
267 i++; | |
268 } | |
269 while(c[i]!=0); | |
270 return 1; | |
271 } | |
272 | |
273 static int read_fbmodes_mode(FILE *f, struct fb_var_screeninfo *vinfo) | |
274 { | |
275 char line[1024]; | |
276 char option[256]; | |
277 | |
278 /* Find a "geometry" */ | |
279 do { | |
280 if (read_fbmodes_line(f, line, sizeof(line))==0) | |
281 return 0; | |
282 if (strncmp(line,"geometry",8)==0) | |
283 break; | |
284 } | |
285 while(1); | |
286 | |
287 sscanf(line, "geometry %d %d %d %d %d", &vinfo->xres, &vinfo->yres, | |
288 &vinfo->xres_virtual, &vinfo->yres_virtual, &vinfo->bits_per_pixel); | |
289 if (read_fbmodes_line(f, line, sizeof(line))==0) | |
290 return 0; | |
291 | |
292 sscanf(line, "timings %d %d %d %d %d %d %d", &vinfo->pixclock, | |
293 &vinfo->left_margin, &vinfo->right_margin, &vinfo->upper_margin, | |
294 &vinfo->lower_margin, &vinfo->hsync_len, &vinfo->vsync_len); | |
295 | |
296 vinfo->sync=0; | |
297 vinfo->vmode=FB_VMODE_NONINTERLACED; | |
298 | |
299 /* Parse misc options */ | |
300 do { | |
301 if (read_fbmodes_line(f, line, sizeof(line))==0) | |
302 return 0; | |
303 | |
304 if (strncmp(line,"hsync",5)==0) { | |
305 sscanf(line,"hsync %s",option); | |
306 if (strncmp(option,"high",4)==0) | |
307 vinfo->sync |= FB_SYNC_HOR_HIGH_ACT; | |
308 } | |
309 else if (strncmp(line,"vsync",5)==0) { | |
310 sscanf(line,"vsync %s",option); | |
311 if (strncmp(option,"high",4)==0) | |
312 vinfo->sync |= FB_SYNC_VERT_HIGH_ACT; | |
313 } | |
314 else if (strncmp(line,"csync",5)==0) { | |
315 sscanf(line,"csync %s",option); | |
316 if (strncmp(option,"high",4)==0) | |
317 vinfo->sync |= FB_SYNC_COMP_HIGH_ACT; | |
318 } | |
319 else if (strncmp(line,"extsync",5)==0) { | |
320 sscanf(line,"extsync %s",option); | |
321 if (strncmp(option,"true",4)==0) | |
322 vinfo->sync |= FB_SYNC_EXT; | |
323 } | |
324 else if (strncmp(line,"laced",5)==0) { | |
325 sscanf(line,"laced %s",option); | |
326 if (strncmp(option,"true",4)==0) | |
327 vinfo->vmode |= FB_VMODE_INTERLACED; | |
328 } | |
329 else if (strncmp(line,"double",6)==0) { | |
330 sscanf(line,"double %s",option); | |
331 if (strncmp(option,"true",4)==0) | |
332 vinfo->vmode |= FB_VMODE_DOUBLE; | |
333 } | |
334 } | |
335 while(strncmp(line,"endmode",7)!=0); | |
336 | |
337 return 1; | |
338 } | |
339 | |
237 static int FB_CheckMode(_THIS, struct fb_var_screeninfo *vinfo, | 340 static int FB_CheckMode(_THIS, struct fb_var_screeninfo *vinfo, |
238 int index, unsigned int *w, unsigned int *h) | 341 int index, unsigned int *w, unsigned int *h) |
239 { | 342 { |
240 int mode_okay; | 343 int mode_okay; |
241 | 344 |
257 } | 360 } |
258 } | 361 } |
259 return mode_okay; | 362 return mode_okay; |
260 } | 363 } |
261 | 364 |
262 static int FB_AddMode(_THIS, int index, unsigned int w, unsigned int h) | 365 static int FB_AddMode(_THIS, int index, unsigned int w, unsigned int h, int check_timings) |
263 { | 366 { |
264 SDL_Rect *mode; | 367 SDL_Rect *mode; |
265 int i; | 368 int i; |
266 int next_mode; | 369 int next_mode; |
267 | 370 |
275 return(0); | 378 return(0); |
276 } | 379 } |
277 } | 380 } |
278 | 381 |
279 /* Only allow a mode if we have a valid timing for it */ | 382 /* Only allow a mode if we have a valid timing for it */ |
280 next_mode = -1; | 383 if ( check_timings ) { |
281 for ( i=0; i<(sizeof(vesa_timings)/sizeof(vesa_timings[0])); ++i ) { | 384 int found_timing = 0; |
282 if ( (w == vesa_timings[i].xres) && | 385 for ( i=0; i<(sizeof(vesa_timings)/sizeof(vesa_timings[0])); ++i ) { |
283 (h == vesa_timings[i].yres) && vesa_timings[i].pixclock ) { | 386 if ( (w == vesa_timings[i].xres) && |
284 next_mode = i; | 387 (h == vesa_timings[i].yres) && vesa_timings[i].pixclock ) { |
285 break; | 388 found_timing = 1; |
286 } | 389 break; |
287 } | 390 } |
288 if ( next_mode == -1 ) { | 391 } |
392 if ( !found_timing ) { | |
289 #ifdef FBCON_DEBUG | 393 #ifdef FBCON_DEBUG |
290 fprintf(stderr, "No valid timing line for mode %dx%d\n", w, h); | 394 fprintf(stderr, "No valid timing line for mode %dx%d\n", w, h); |
291 #endif | 395 #endif |
292 return(0); | 396 return(0); |
397 } | |
293 } | 398 } |
294 | 399 |
295 /* Set up the new video mode rectangle */ | 400 /* Set up the new video mode rectangle */ |
296 mode = (SDL_Rect *)malloc(sizeof *mode); | 401 mode = (SDL_Rect *)malloc(sizeof *mode); |
297 if ( mode == NULL ) { | 402 if ( mode == NULL ) { |
321 SDL_nummodes[index]++; | 426 SDL_nummodes[index]++; |
322 | 427 |
323 return(0); | 428 return(0); |
324 } | 429 } |
325 | 430 |
431 static int cmpmodes(const void *va, const void *vb) | |
432 { | |
433 const SDL_Rect *a = *(const SDL_Rect**)va; | |
434 const SDL_Rect *b = *(const SDL_Rect**)vb; | |
435 if ( a->h == b->h ) | |
436 return b->w - a->w; | |
437 else | |
438 return b->h - a->h; | |
439 } | |
440 | |
441 static int FB_SortModes(_THIS) | |
442 { | |
443 int i; | |
444 for ( i=0; i<NUM_MODELISTS; ++i ) { | |
445 if ( SDL_nummodes[i] > 0 ) { | |
446 qsort(SDL_modelist[i], SDL_nummodes[i], sizeof *SDL_modelist[i], cmpmodes); | |
447 } | |
448 } | |
449 } | |
450 | |
326 static int FB_VideoInit(_THIS, SDL_PixelFormat *vformat) | 451 static int FB_VideoInit(_THIS, SDL_PixelFormat *vformat) |
327 { | 452 { |
328 struct fb_fix_screeninfo finfo; | 453 struct fb_fix_screeninfo finfo; |
329 struct fb_var_screeninfo vinfo; | 454 struct fb_var_screeninfo vinfo; |
330 int i, j; | 455 int i, j; |
331 int current_index; | 456 int current_index; |
332 unsigned int current_w; | 457 unsigned int current_w; |
333 unsigned int current_h; | 458 unsigned int current_h; |
334 const char *SDL_fbdev; | 459 const char *SDL_fbdev; |
460 FILE *modesdb; | |
335 | 461 |
336 /* Initialize the library */ | 462 /* Initialize the library */ |
337 SDL_fbdev = getenv("SDL_FBDEV"); | 463 SDL_fbdev = getenv("SDL_FBDEV"); |
338 if ( SDL_fbdev == NULL ) { | 464 if ( SDL_fbdev == NULL ) { |
339 SDL_fbdev = "/dev/fb0"; | 465 SDL_fbdev = "/dev/fb0"; |
461 | 587 |
462 /* Query for the list of available video modes */ | 588 /* Query for the list of available video modes */ |
463 current_w = vinfo.xres; | 589 current_w = vinfo.xres; |
464 current_h = vinfo.yres; | 590 current_h = vinfo.yres; |
465 current_index = ((vinfo.bits_per_pixel+7)/8)-1; | 591 current_index = ((vinfo.bits_per_pixel+7)/8)-1; |
592 modesdb = fopen(FB_MODES_DB, "r"); | |
593 for ( i=0; i<NUM_MODELISTS; ++i ) { | |
594 SDL_nummodes[i] = 0; | |
595 SDL_modelist[i] = NULL; | |
596 } | |
466 if ( getenv("SDL_FB_BROKEN_MODES") != NULL ) { | 597 if ( getenv("SDL_FB_BROKEN_MODES") != NULL ) { |
467 FB_AddMode(this, current_index, current_w, current_h); | 598 FB_AddMode(this, current_index, current_w, current_h, 0); |
599 } else if(modesdb) { | |
600 while ( read_fbmodes_mode(modesdb, &vinfo) ) { | |
601 for ( i=0; i<NUM_MODELISTS; ++i ) { | |
602 unsigned int w, h; | |
603 | |
604 /* See if we are querying for the current mode */ | |
605 w = vinfo.xres; | |
606 h = vinfo.yres; | |
607 if ( i == current_index ) { | |
608 if ( (current_w > w) || (current_h > h) ) { | |
609 /* Only check once */ | |
610 FB_AddMode(this, i, current_w, current_h, 0); | |
611 current_index = -1; | |
612 } | |
613 } | |
614 if ( FB_CheckMode(this, &vinfo, i, &w, &h) ) { | |
615 FB_AddMode(this, i, w, h, 0); | |
616 } | |
617 } | |
618 } | |
619 fclose(modesdb); | |
620 FB_SortModes(this); | |
468 } else { | 621 } else { |
469 for ( i=0; i<NUM_MODELISTS; ++i ) { | 622 for ( i=0; i<NUM_MODELISTS; ++i ) { |
470 SDL_nummodes[i] = 0; | |
471 SDL_modelist[i] = NULL; | |
472 for ( j=0; j<(sizeof(checkres)/sizeof(checkres[0])); ++j ) { | 623 for ( j=0; j<(sizeof(checkres)/sizeof(checkres[0])); ++j ) { |
473 unsigned int w, h; | 624 unsigned int w, h; |
474 | 625 |
475 /* See if we are querying for the current mode */ | 626 /* See if we are querying for the current mode */ |
476 w = checkres[j].w; | 627 w = checkres[j].w; |
477 h = checkres[j].h; | 628 h = checkres[j].h; |
478 if ( i == current_index ) { | 629 if ( i == current_index ) { |
479 if ( (current_w > w) || (current_h > h) ) { | 630 if ( (current_w > w) || (current_h > h) ) { |
480 /* Only check once */ | 631 /* Only check once */ |
481 FB_AddMode(this, i, current_w, current_h); | 632 FB_AddMode(this, i, current_w, current_h, 0); |
482 current_index = -1; | 633 current_index = -1; |
483 } | 634 } |
484 } | 635 } |
485 if ( FB_CheckMode(this, &vinfo, i, &w, &h) ) { | 636 if ( FB_CheckMode(this, &vinfo, i, &w, &h) ) { |
486 FB_AddMode(this, i, w, h); | 637 FB_AddMode(this, i, w, h, 1); |
487 } | 638 } |
488 } | 639 } |
489 } | 640 } |
490 } | 641 } |
491 | 642 |
609 #endif | 760 #endif |
610 | 761 |
611 static int choose_fbmodes_mode(struct fb_var_screeninfo *vinfo) | 762 static int choose_fbmodes_mode(struct fb_var_screeninfo *vinfo) |
612 { | 763 { |
613 int matched; | 764 int matched; |
614 FILE *fbmodes; | 765 FILE *modesdb; |
766 struct fb_var_screeninfo cinfo; | |
615 | 767 |
616 matched = 0; | 768 matched = 0; |
617 fbmodes = fopen("/etc/fb.modes", "r"); | 769 modesdb = fopen(FB_MODES_DB, "r"); |
618 if ( fbmodes ) { | 770 if ( modesdb ) { |
619 /* FIXME: Parse the mode definition file */ | 771 /* Parse the mode definition file */ |
620 fclose(fbmodes); | 772 while ( read_fbmodes_mode(modesdb, &cinfo) ) { |
773 if ( vinfo->xres == cinfo.xres && | |
774 vinfo->yres == cinfo.yres ) { | |
775 matched = 1; | |
776 break; | |
777 } | |
778 } | |
779 fclose(modesdb); | |
621 } | 780 } |
622 return(matched); | 781 return(matched); |
623 } | 782 } |
624 | 783 |
625 static int choose_vesa_mode(struct fb_var_screeninfo *vinfo) | 784 static int choose_vesa_mode(struct fb_var_screeninfo *vinfo) |