~ubuntu-branches/debian/sid/grub2/sid-200907171837

« back to all changes in this revision

Viewing changes to video/video.c

  • Committer: Bazaar Package Importer
  • Author(s): Robert Millan
  • Date: 2009-07-02 13:23:51 UTC
  • mfrom: (1.1.10 upstream)
  • Revision ID: james.westby@ubuntu.com-20090702132351-tanpn0ryyijp93gu
Tags: 1.96+20090702-1
* New SVN snapshot.
* rules: Remove duplicated files in sparc64-ieee1275 port.
* rules: Comment out -DGRUB_ASSUME_LINUX_HAS_FB_SUPPORT=1 setting.  We'll
  re-evaluate using it when it's more mature.  (Closes: #535026).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
 *  GRUB  --  GRand Unified Bootloader
3
 
 *  Copyright (C) 2006,2007,2008  Free Software Foundation, Inc.
 
3
 *  Copyright (C) 2006,2007,2008,2009  Free Software Foundation, Inc.
4
4
 *
5
5
 *  GRUB is free software: you can redistribute it and/or modify
6
6
 *  it under the terms of the GNU General Public License as published by
19
19
#include <grub/video.h>
20
20
#include <grub/types.h>
21
21
#include <grub/dl.h>
 
22
#include <grub/misc.h>
 
23
#include <grub/mm.h>
22
24
 
23
25
/* The list of video adapters registered to system.  */
24
26
static grub_video_adapter_t grub_video_adapter_list;
59
61
      break;
60
62
}
61
63
 
62
 
/* Setup specified video mode.  */
63
 
grub_err_t
64
 
grub_video_setup (unsigned int width, unsigned int height,
65
 
                  unsigned int mode_type)
66
 
{
67
 
  grub_video_adapter_t p;
68
 
 
69
 
  /* De-activate last set video adapter.  */
70
 
  if (grub_video_adapter_active)
71
 
    {
72
 
      /* Finalize adapter.  */
73
 
      grub_video_adapter_active->fini ();
74
 
      if (grub_errno != GRUB_ERR_NONE)
75
 
        return grub_errno;
76
 
 
77
 
      /* Mark active adapter as not set.  */
78
 
      grub_video_adapter_active = 0;
79
 
    }
80
 
 
81
 
  /* Loop thru all possible video adapter trying to find requested mode.  */
82
 
  for (p = grub_video_adapter_list; p; p = p->next)
83
 
    {
84
 
      /* Try to initialize adapter, if it fails, skip to next adapter.  */
85
 
      p->init ();
86
 
      if (grub_errno != GRUB_ERR_NONE)
87
 
        {
88
 
          grub_errno = GRUB_ERR_NONE;
89
 
          continue;
90
 
        }
91
 
 
92
 
      /* Try to initialize video mode.  */
93
 
      p->setup (width, height, mode_type);
94
 
      if (grub_errno == GRUB_ERR_NONE)
95
 
        {
96
 
          /* Valid mode found from adapter, and it has been activated.
97
 
             Specify it as active adapter.  */
98
 
          grub_video_adapter_active = p;
99
 
          return GRUB_ERR_NONE;
100
 
        }
101
 
      else
102
 
        grub_errno = GRUB_ERR_NONE;
103
 
 
104
 
      /* No valid mode found in this adapter, finalize adapter.  */
105
 
      p->fini ();
106
 
      if (grub_errno != GRUB_ERR_NONE)
107
 
        return grub_errno;
108
 
    }
109
 
 
110
 
  /* We couldn't find suitable adapter for specified mode.  */
111
 
  return grub_error (GRUB_ERR_UNKNOWN_DEVICE, 
112
 
                     "Can't locate valid adapter for mode");
113
 
}
114
 
 
115
64
/* Restore back to initial mode (where applicable).  */
116
65
grub_err_t
117
66
grub_video_restore (void)
140
89
      grub_errno = GRUB_ERR_NONE;
141
90
      return grub_errno;
142
91
    }
143
 
  
 
92
 
144
93
  return grub_video_adapter_active->get_info (mode_info);
145
94
}
146
95
 
152
101
  if (mode_info->bpp == 32)
153
102
    {
154
103
      if ((mode_info->red_mask_size == 8)
155
 
          && (mode_info->red_field_pos == 0)
156
 
          && (mode_info->green_mask_size == 8)
157
 
          && (mode_info->green_field_pos == 8)
158
 
          && (mode_info->blue_mask_size == 8)
159
 
          && (mode_info->blue_field_pos == 16)
160
 
          && (mode_info->reserved_mask_size == 8)
161
 
          && (mode_info->reserved_field_pos == 24))
162
 
        {
163
 
          return GRUB_VIDEO_BLIT_FORMAT_R8G8B8A8;
164
 
        }
 
104
          && (mode_info->red_field_pos == 16)
 
105
          && (mode_info->green_mask_size == 8)
 
106
          && (mode_info->green_field_pos == 8)
 
107
          && (mode_info->blue_mask_size == 8)
 
108
          && (mode_info->blue_field_pos == 0))
 
109
        {
 
110
          return GRUB_VIDEO_BLIT_FORMAT_BGRA_8888;
 
111
        }
 
112
      else if ((mode_info->red_mask_size == 8)
 
113
               && (mode_info->red_field_pos == 0)
 
114
               && (mode_info->green_mask_size == 8)
 
115
               && (mode_info->green_field_pos == 8)
 
116
               && (mode_info->blue_mask_size == 8)
 
117
               && (mode_info->blue_field_pos == 16))
 
118
        {
 
119
          return GRUB_VIDEO_BLIT_FORMAT_RGBA_8888;
 
120
        }
165
121
    }
166
 
 
167
122
  /* Check if we have any known 24 bit modes.  */
168
 
  if (mode_info->bpp == 24)
 
123
  else if (mode_info->bpp == 24)
169
124
    {
170
125
      if ((mode_info->red_mask_size == 8)
171
 
          && (mode_info->red_field_pos == 0)
172
 
          && (mode_info->green_mask_size == 8)
173
 
          && (mode_info->green_field_pos == 8)
174
 
          && (mode_info->blue_mask_size == 8)
175
 
          && (mode_info->blue_field_pos == 16))
176
 
        {
177
 
          return GRUB_VIDEO_BLIT_FORMAT_R8G8B8;
178
 
        }
179
 
    }
 
126
          && (mode_info->red_field_pos == 16)
 
127
          && (mode_info->green_mask_size == 8)
 
128
          && (mode_info->green_field_pos == 8)
 
129
          && (mode_info->blue_mask_size == 8)
 
130
          && (mode_info->blue_field_pos == 0))
 
131
        {
 
132
          return GRUB_VIDEO_BLIT_FORMAT_BGR_888;
 
133
        }
 
134
      else if ((mode_info->red_mask_size == 8)
 
135
               && (mode_info->red_field_pos == 0)
 
136
               && (mode_info->green_mask_size == 8)
 
137
               && (mode_info->green_field_pos == 8)
 
138
               && (mode_info->blue_mask_size == 8)
 
139
               && (mode_info->blue_field_pos == 16))
 
140
        {
 
141
          return GRUB_VIDEO_BLIT_FORMAT_RGB_888;
 
142
        }
 
143
    }
 
144
  /* Check if we have any known 16 bit modes.  */
 
145
  else if (mode_info->bpp == 16)
 
146
    {
 
147
      if ((mode_info->red_mask_size == 5)
 
148
          && (mode_info->red_field_pos == 11)
 
149
          && (mode_info->green_mask_size == 6)
 
150
          && (mode_info->green_field_pos == 5)
 
151
          && (mode_info->blue_mask_size == 5)
 
152
          && (mode_info->blue_field_pos == 0))
 
153
        {
 
154
          return GRUB_VIDEO_BLIT_FORMAT_BGR_565;
 
155
        }
 
156
      else if ((mode_info->red_mask_size == 5)
 
157
               && (mode_info->red_field_pos == 0)
 
158
               && (mode_info->green_mask_size == 6)
 
159
               && (mode_info->green_field_pos == 5)
 
160
               && (mode_info->blue_mask_size == 5)
 
161
               && (mode_info->blue_field_pos == 11))
 
162
        {
 
163
          return GRUB_VIDEO_BLIT_FORMAT_RGB_565;
 
164
        }
 
165
    }
 
166
 
 
167
  /* Backup route.  Unknown format.  */
180
168
 
181
169
  /* If there are more than 8 bits per color, assume RGB(A) mode.  */
182
170
  if (mode_info->bpp > 8)
183
171
    {
184
172
      if (mode_info->reserved_mask_size > 0)
185
 
        {
186
 
          return GRUB_VIDEO_BLIT_FORMAT_RGBA;
187
 
        }
188
 
      return GRUB_VIDEO_BLIT_FORMAT_RGB;
 
173
        {
 
174
          return GRUB_VIDEO_BLIT_FORMAT_RGBA;
 
175
        }
 
176
      else
 
177
        {
 
178
          return GRUB_VIDEO_BLIT_FORMAT_RGB;
 
179
        }
189
180
    }
190
181
 
191
182
  /* Assume as indexcolor mode.  */
269
260
 
270
261
/* Unmap video color back to RGBA components.  */
271
262
grub_err_t
272
 
grub_video_unmap_color (grub_video_color_t color, grub_uint8_t *red, 
273
 
                        grub_uint8_t *green, grub_uint8_t *blue, 
 
263
grub_video_unmap_color (grub_video_color_t color, grub_uint8_t *red,
 
264
                        grub_uint8_t *green, grub_uint8_t *blue,
274
265
                        grub_uint8_t *alpha)
275
266
{
276
267
  if (! grub_video_adapter_active)
294
285
  return grub_video_adapter_active->fill_rect (color, x, y, width, height);
295
286
}
296
287
 
297
 
/* Blit glyph to screen using specified color.  */
298
 
grub_err_t
299
 
grub_video_blit_glyph (struct grub_font_glyph *glyph,
300
 
                       grub_video_color_t color, int x, int y)
301
 
{
302
 
  if (! grub_video_adapter_active)
303
 
    return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
304
 
 
305
 
  return grub_video_adapter_active->blit_glyph (glyph, color, x, y);
306
 
}
307
 
 
308
288
/* Blit bitmap to screen.  */
309
289
grub_err_t
310
290
grub_video_blit_bitmap (struct grub_video_bitmap *bitmap,
399
379
  return grub_video_adapter_active->get_active_render_target (target);
400
380
}
401
381
 
 
382
grub_err_t
 
383
grub_video_set_mode (char *modestring,
 
384
                     int NESTED_FUNC_ATTR (*hook) (grub_video_adapter_t p,
 
385
                                                   struct grub_video_mode_info *mode_info))
 
386
{
 
387
  char *tmp;
 
388
  char *next_mode;
 
389
  char *current_mode;
 
390
  char *param;
 
391
  char *value;
 
392
  char *modevar;
 
393
  int width = -1;
 
394
  int height = -1;
 
395
  int depth = -1;
 
396
  int flags = 0;
 
397
 
 
398
  /* Take copy of env.var. as we don't want to modify that.  */
 
399
  modevar = grub_strdup (modestring);
 
400
 
 
401
  /* Initialize next mode.  */
 
402
  next_mode = modevar;
 
403
 
 
404
  if (! modevar)
 
405
    return grub_error (GRUB_ERR_OUT_OF_MEMORY,
 
406
                       "couldn't allocate space for local modevar copy");
 
407
 
 
408
  if (grub_memcmp (next_mode, "keep", sizeof ("keep")) == 0
 
409
      || grub_memcmp (next_mode, "keep,", sizeof ("keep,") - 1) == 0
 
410
      || grub_memcmp (next_mode, "keep;", sizeof ("keep;") - 1) == 0)
 
411
    {
 
412
      struct grub_video_mode_info mode_info;
 
413
      int suitable = 1;
 
414
      grub_err_t err;
 
415
 
 
416
      grub_memset (&mode_info, 0, sizeof (mode_info));
 
417
 
 
418
      if (grub_video_adapter_active)
 
419
        {
 
420
          err = grub_video_get_info (&mode_info);
 
421
          if (err)
 
422
            {
 
423
              suitable = 0;
 
424
              grub_errno = GRUB_ERR_NONE;
 
425
            }
 
426
        }
 
427
      else
 
428
        mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_PURE_TEXT;
 
429
 
 
430
      if (suitable && hook)
 
431
        suitable = hook (grub_video_adapter_active, &mode_info);
 
432
      if (suitable)
 
433
        {
 
434
          grub_free (modevar);
 
435
          return GRUB_ERR_NONE;
 
436
        }
 
437
      next_mode += sizeof ("keep") - 1;
 
438
      if (! *next_mode)
 
439
        {
 
440
          grub_free (modevar);
 
441
 
 
442
          return grub_error (GRUB_ERR_BAD_ARGUMENT,
 
443
                             "No suitable mode found.");
 
444
        }
 
445
 
 
446
      /* Skip separator. */
 
447
      next_mode++;
 
448
    }
 
449
 
 
450
  /* De-activate last set video adapter.  */
 
451
  if (grub_video_adapter_active)
 
452
    {
 
453
      /* Finalize adapter.  */
 
454
      grub_video_adapter_active->fini ();
 
455
      if (grub_errno != GRUB_ERR_NONE)
 
456
        grub_errno = GRUB_ERR_NONE;
 
457
 
 
458
      /* Mark active adapter as not set.  */
 
459
      grub_video_adapter_active = 0;
 
460
    }
 
461
 
 
462
  /* Loop until all modes has been tested out.  */
 
463
  while (next_mode != NULL)
 
464
    {
 
465
      /* Use last next_mode as current mode.  */
 
466
      tmp = next_mode;
 
467
 
 
468
      /* Reset video mode settings.  */
 
469
      width = -1;
 
470
      height = -1;
 
471
      depth = -1;
 
472
      flags = 0;
 
473
 
 
474
      /* Save position of next mode and separate modes.  */
 
475
      for (; *next_mode; next_mode++)
 
476
        if (*next_mode == ',' || *next_mode == ';')
 
477
          break;
 
478
      if (*next_mode)
 
479
        {
 
480
          *next_mode = 0;
 
481
          next_mode++;
 
482
        }
 
483
      else
 
484
        next_mode = 0;
 
485
 
 
486
      /* Skip whitespace.  */
 
487
      while (grub_isspace (*tmp))
 
488
        tmp++;
 
489
 
 
490
      /* Initialize token holders.  */
 
491
      current_mode = tmp;
 
492
      param = tmp;
 
493
      value = NULL;
 
494
 
 
495
      /* XXX: we assume that we're in pure text mode if
 
496
         no video mode is initialized. Is it always true? */
 
497
      if (grub_strcmp (param, "text") == 0)
 
498
        {
 
499
          struct grub_video_mode_info mode_info;
 
500
 
 
501
          grub_memset (&mode_info, 0, sizeof (mode_info));
 
502
          mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_PURE_TEXT;
 
503
 
 
504
          if (! hook || hook (0, &mode_info))
 
505
            {
 
506
              /* Valid mode found from adapter, and it has been activated.
 
507
                 Specify it as active adapter.  */
 
508
              grub_video_adapter_active = NULL;
 
509
 
 
510
              /* Free memory.  */
 
511
              grub_free (modevar);
 
512
 
 
513
              return GRUB_ERR_NONE;
 
514
            }
 
515
        }
 
516
 
 
517
      /* Parse <width>x<height>[x<depth>]*/
 
518
 
 
519
      /* Find width value.  */
 
520
      value = param;
 
521
      param = grub_strchr(param, 'x');
 
522
      if (param == NULL)
 
523
        {
 
524
          grub_err_t rc;
 
525
 
 
526
          /* First setup error message.  */
 
527
          rc = grub_error (GRUB_ERR_BAD_ARGUMENT,
 
528
                           "Invalid mode: %s\n",
 
529
                           current_mode);
 
530
 
 
531
          /* Free memory before returning.  */
 
532
          grub_free (modevar);
 
533
 
 
534
          return rc;
 
535
        }
 
536
 
 
537
      *param = 0;
 
538
      param++;
 
539
 
 
540
      width = grub_strtoul (value, 0, 0);
 
541
      if (grub_errno != GRUB_ERR_NONE)
 
542
        {
 
543
          grub_err_t rc;
 
544
 
 
545
          /* First setup error message.  */
 
546
          rc = grub_error (GRUB_ERR_BAD_ARGUMENT,
 
547
                           "Invalid mode: %s\n",
 
548
                           current_mode);
 
549
 
 
550
          /* Free memory before returning.  */
 
551
          grub_free (modevar);
 
552
 
 
553
          return rc;
 
554
        }
 
555
 
 
556
      /* Find height value.  */
 
557
      value = param;
 
558
      param = grub_strchr(param, 'x');
 
559
      if (param == NULL)
 
560
        {
 
561
          height = grub_strtoul (value, 0, 0);
 
562
          if (grub_errno != GRUB_ERR_NONE)
 
563
            {
 
564
              grub_err_t rc;
 
565
 
 
566
              /* First setup error message.  */
 
567
              rc = grub_error (GRUB_ERR_BAD_ARGUMENT,
 
568
                               "Invalid mode: %s\n",
 
569
                               current_mode);
 
570
 
 
571
              /* Free memory before returning.  */
 
572
              grub_free (modevar);
 
573
 
 
574
              return rc;
 
575
            }
 
576
        }
 
577
      else
 
578
        {
 
579
          /* We have optional color depth value.  */
 
580
          *param = 0;
 
581
          param++;
 
582
 
 
583
          height = grub_strtoul (value, 0, 0);
 
584
          if (grub_errno != GRUB_ERR_NONE)
 
585
            {
 
586
              grub_err_t rc;
 
587
 
 
588
              /* First setup error message.  */
 
589
              rc = grub_error (GRUB_ERR_BAD_ARGUMENT,
 
590
                               "Invalid mode: %s\n",
 
591
                               current_mode);
 
592
 
 
593
              /* Free memory before returning.  */
 
594
              grub_free (modevar);
 
595
 
 
596
              return rc;
 
597
            }
 
598
 
 
599
          /* Convert color depth value.  */
 
600
          value = param;
 
601
          depth = grub_strtoul (value, 0, 0);
 
602
          if (grub_errno != GRUB_ERR_NONE)
 
603
            {
 
604
              grub_err_t rc;
 
605
 
 
606
              /* First setup error message.  */
 
607
              rc = grub_error (GRUB_ERR_BAD_ARGUMENT,
 
608
                               "Invalid mode: %s\n",
 
609
                               current_mode);
 
610
 
 
611
              /* Free memory before returning.  */
 
612
              grub_free (modevar);
 
613
 
 
614
              return rc;
 
615
            }
 
616
        }
 
617
 
 
618
      /* Try out video mode.  */
 
619
 
 
620
      /* If we have 8 or less bits, then assume that it is indexed color mode.  */
 
621
      if ((depth <= 8) && (depth != -1))
 
622
        flags |= GRUB_VIDEO_MODE_TYPE_INDEX_COLOR;
 
623
 
 
624
      /* We have more than 8 bits, then assume that it is RGB color mode.  */
 
625
      if (depth > 8)
 
626
        flags |= GRUB_VIDEO_MODE_TYPE_RGB;
 
627
 
 
628
      /* If user requested specific depth, forward that information to driver.  */
 
629
      if (depth != -1)
 
630
        flags |= (depth << GRUB_VIDEO_MODE_TYPE_DEPTH_POS)
 
631
          & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK;
 
632
 
 
633
      /* Try to initialize requested mode.  Ignore any errors.  */
 
634
      grub_video_adapter_t p;
 
635
 
 
636
      /* Loop thru all possible video adapter trying to find requested mode.  */
 
637
      for (p = grub_video_adapter_list; p; p = p->next)
 
638
        {
 
639
          grub_err_t err;
 
640
          struct grub_video_mode_info mode_info;
 
641
 
 
642
          grub_memset (&mode_info, 0, sizeof (mode_info));
 
643
 
 
644
          /* Try to initialize adapter, if it fails, skip to next adapter.  */
 
645
          err = p->init ();
 
646
          if (err != GRUB_ERR_NONE)
 
647
            {
 
648
              grub_errno = GRUB_ERR_NONE;
 
649
              continue;
 
650
            }
 
651
 
 
652
          /* Try to initialize video mode.  */
 
653
          err = p->setup (width, height, flags);
 
654
          if (err != GRUB_ERR_NONE)
 
655
            {
 
656
              p->fini ();
 
657
              grub_errno = GRUB_ERR_NONE;
 
658
              continue;
 
659
            }
 
660
 
 
661
          err = p->get_info (&mode_info);
 
662
          if (err != GRUB_ERR_NONE)
 
663
            {
 
664
              p->fini ();
 
665
              grub_errno = GRUB_ERR_NONE;
 
666
              continue;
 
667
            }
 
668
 
 
669
          if (hook && ! hook (p, &mode_info))
 
670
            {
 
671
              p->fini ();
 
672
              grub_errno = GRUB_ERR_NONE;
 
673
              continue;
 
674
            }
 
675
 
 
676
          /* Valid mode found from adapter, and it has been activated.
 
677
             Specify it as active adapter.  */
 
678
          grub_video_adapter_active = p;
 
679
 
 
680
          /* Free memory.  */
 
681
          grub_free (modevar);
 
682
 
 
683
          return GRUB_ERR_NONE;
 
684
        }
 
685
 
 
686
    }
 
687
 
 
688
  /* Free memory.  */
 
689
  grub_free (modevar);
 
690
 
 
691
  return grub_error (GRUB_ERR_BAD_ARGUMENT,
 
692
                     "No suitable mode found.");
 
693
}
 
694
 
402
695
/* Initialize Video API module.  */
403
696
GRUB_MOD_INIT(video_video)
404
697
{