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)