~hamo/ubuntu/precise/grub2/grub2.hi_res

« back to all changes in this revision

Viewing changes to video/i386/pc/vbe.c

Tags: upstream-1.98+20100705
ImportĀ upstreamĀ versionĀ 1.98+20100705

Show diffs side-by-side

added added

removed removed

Lines of Context:
40
40
static struct
41
41
{
42
42
  struct grub_video_mode_info mode_info;
43
 
  struct grub_video_render_target *front_target;
44
 
  struct grub_video_render_target *back_target;
45
43
 
46
44
  unsigned int bytes_per_scan_line;
47
45
  unsigned int bytes_per_pixel;
48
46
  grub_uint32_t active_vbe_mode;
49
47
  grub_uint8_t *ptr;
50
48
  int index_color_mode;
51
 
 
52
 
  char *offscreen_buffer;
53
 
 
54
 
  grub_size_t page_size;        /* The size of a page in bytes.  */
55
 
 
56
 
  /* For page flipping strategy.  */
57
 
  int displayed_page;           /* The page # that is the front buffer.  */
58
 
  int render_page;              /* The page # that is the back buffer.  */
59
 
 
60
 
  /* Virtual functions.  */
61
 
  grub_video_fb_doublebuf_update_screen_t update_screen;
62
49
} framebuffer;
63
50
 
64
51
static grub_uint32_t initial_vbe_mode;
377
364
  vbe_mode_list = NULL;
378
365
 
379
366
  err = grub_video_fb_fini ();
380
 
  grub_free (framebuffer.offscreen_buffer);
381
367
  return err;
382
368
}
383
369
 
387
373
  respectively.
388
374
*/
389
375
static grub_err_t
390
 
doublebuf_pageflipping_commit (void)
 
376
doublebuf_pageflipping_set_page (int page)
391
377
{
392
378
  /* Tell the video adapter to display the new front page.  */
393
379
  int display_start_line
394
 
    = framebuffer.mode_info.height * framebuffer.displayed_page;
 
380
    = framebuffer.mode_info.height * page;
395
381
 
396
382
  grub_vbe_status_t vbe_err =
397
383
    grub_vbe_bios_set_display_start (0, display_start_line);
403
389
}
404
390
 
405
391
static grub_err_t
406
 
doublebuf_pageflipping_update_screen (struct grub_video_fbrender_target *front
407
 
                                      __attribute__ ((unused)),
408
 
                                      struct grub_video_fbrender_target *back
409
 
                                      __attribute__ ((unused)))
410
 
{
411
 
  int new_displayed_page;
412
 
  struct grub_video_fbrender_target *target;
413
 
  grub_err_t err;
414
 
 
415
 
  /* Swap the page numbers in the framebuffer struct.  */
416
 
  new_displayed_page = framebuffer.render_page;
417
 
  framebuffer.render_page = framebuffer.displayed_page;
418
 
  framebuffer.displayed_page = new_displayed_page;
419
 
 
420
 
  err = doublebuf_pageflipping_commit ();
421
 
  if (err)
422
 
    {
423
 
      /* Restore previous state.  */
424
 
      framebuffer.render_page = framebuffer.displayed_page;
425
 
      framebuffer.displayed_page = new_displayed_page;
426
 
      return err;
427
 
    }
428
 
 
429
 
  if (framebuffer.mode_info.mode_type & GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP)
430
 
    grub_memcpy (framebuffer.ptr + framebuffer.render_page
431
 
                 * framebuffer.page_size, framebuffer.ptr
432
 
                 + framebuffer.displayed_page * framebuffer.page_size,
433
 
                 framebuffer.page_size);
434
 
 
435
 
  target = framebuffer.back_target;
436
 
  framebuffer.back_target = framebuffer.front_target;
437
 
  framebuffer.front_target = target;
438
 
 
439
 
  err = grub_video_fb_get_active_render_target (&target);
440
 
  if (err)
441
 
    return err;
442
 
 
443
 
  if (target == framebuffer.back_target)
444
 
    err = grub_video_fb_set_active_render_target (framebuffer.front_target);
445
 
  else if (target == framebuffer.front_target)
446
 
    err = grub_video_fb_set_active_render_target (framebuffer.back_target);
447
 
 
448
 
  return err;
449
 
}
450
 
 
451
 
static grub_err_t
452
 
doublebuf_pageflipping_init (void)
453
 
{
454
 
  /* Get video RAM size in bytes.  */
455
 
  grub_size_t vram_size = controller_info.total_memory << 16;
456
 
  grub_err_t err;
457
 
 
458
 
  framebuffer.page_size =
459
 
    framebuffer.mode_info.pitch * framebuffer.mode_info.height;
460
 
 
461
 
  if (2 * framebuffer.page_size > vram_size)
462
 
    return grub_error (GRUB_ERR_OUT_OF_MEMORY,
463
 
                       "Not enough video memory for double buffering.");
464
 
 
465
 
  framebuffer.displayed_page = 0;
466
 
  framebuffer.render_page = 1;
467
 
 
468
 
  framebuffer.update_screen = doublebuf_pageflipping_update_screen;
469
 
 
470
 
  err = grub_video_fb_create_render_target_from_pointer (&framebuffer.front_target, &framebuffer.mode_info, framebuffer.ptr);
471
 
  if (err)
472
 
    return err;
473
 
 
474
 
  err = grub_video_fb_create_render_target_from_pointer (&framebuffer.back_target, &framebuffer.mode_info, framebuffer.ptr + framebuffer.page_size);
475
 
  if (err)
476
 
    {
477
 
      grub_video_fb_delete_render_target (framebuffer.front_target);
478
 
      return err;
479
 
    }
480
 
 
481
 
  /* Set the framebuffer memory data pointer and display the right page.  */
482
 
  err = doublebuf_pageflipping_commit ();
483
 
  if (err)
484
 
    {
485
 
      grub_video_fb_delete_render_target (framebuffer.front_target);
486
 
      grub_video_fb_delete_render_target (framebuffer.back_target);
487
 
      return err;
488
 
    }
489
 
 
490
 
  return GRUB_ERR_NONE;
491
 
}
492
 
 
493
 
/* Select the best double buffering mode available.  */
494
 
static grub_err_t
495
 
double_buffering_init (unsigned int mode_type, unsigned int mode_mask)
496
 
{
497
 
  grub_err_t err;
498
 
  int updating_swap_needed;
499
 
 
500
 
  updating_swap_needed
501
 
    = grub_video_check_mode_flag (mode_type, mode_mask,
502
 
                                  GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP, 0);
503
 
 
504
 
  /* Do double buffering only if it's either requested or efficient.  */
505
 
  if (grub_video_check_mode_flag (mode_type, mode_mask,
506
 
                                  GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED,
507
 
                                  !updating_swap_needed))
508
 
    {
509
 
      framebuffer.mode_info.mode_type |= GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED;
510
 
      if (updating_swap_needed)
511
 
        framebuffer.mode_info.mode_type |= GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP;
512
 
      err = doublebuf_pageflipping_init ();
513
 
      if (!err)
514
 
        return GRUB_ERR_NONE;
515
 
      
516
 
      framebuffer.mode_info.mode_type
517
 
        &= ~(GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED
518
 
             | GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP);
519
 
 
520
 
      grub_errno = GRUB_ERR_NONE;
521
 
    }
522
 
 
523
 
  if (grub_video_check_mode_flag (mode_type, mode_mask,
524
 
                                  GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED,
525
 
                                  0))
526
 
    {
527
 
      framebuffer.mode_info.mode_type 
528
 
        |= (GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED
529
 
            | GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP);
530
 
 
531
 
      err = grub_video_fb_doublebuf_blit_init (&framebuffer.front_target,
532
 
                                               &framebuffer.back_target,
533
 
                                               &framebuffer.update_screen,
534
 
                                               framebuffer.mode_info,
535
 
                                               framebuffer.ptr);
536
 
 
537
 
      if (!err)
538
 
        return GRUB_ERR_NONE;
539
 
 
540
 
      framebuffer.mode_info.mode_type
541
 
        &= ~(GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED
542
 
             | GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP);
543
 
 
544
 
      grub_errno = GRUB_ERR_NONE;
545
 
    }
546
 
 
547
 
  /* Fall back to no double buffering.  */
548
 
  err = grub_video_fb_create_render_target_from_pointer (&framebuffer.front_target, &framebuffer.mode_info, framebuffer.ptr);
549
 
 
550
 
  if (err)
551
 
    return err;
552
 
 
553
 
  framebuffer.back_target = framebuffer.front_target;
554
 
  framebuffer.update_screen = 0;
555
 
 
556
 
  framebuffer.mode_info.mode_type &= ~GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED;
557
 
 
558
 
  return GRUB_ERR_NONE;
559
 
}
560
 
 
561
 
 
562
 
 
563
 
static grub_err_t
564
392
grub_video_vbe_setup (unsigned int width, unsigned int height,
565
393
                      unsigned int mode_type, unsigned int mode_mask)
566
394
{
684
512
 
685
513
      framebuffer.mode_info.blit_format = grub_video_get_blit_format (&framebuffer.mode_info);
686
514
 
687
 
      /* Set up double buffering and targets.  */
688
 
      err = double_buffering_init (mode_type, mode_mask);
689
 
      if (err)
690
 
        return err;
691
 
 
692
 
      err = grub_video_fb_set_active_render_target (framebuffer.back_target);
693
 
 
694
 
      if (err)
695
 
        return err;
 
515
      {
 
516
        /* Get video RAM size in bytes.  */
 
517
        grub_size_t vram_size = controller_info.total_memory << 16;
 
518
        grub_size_t page_size;        /* The size of a page in bytes.  */
 
519
 
 
520
        page_size = framebuffer.mode_info.pitch * framebuffer.mode_info.height;
 
521
 
 
522
        if (vram_size >= 2 * page_size)
 
523
          err = grub_video_fb_setup (mode_type, mode_mask,
 
524
                                     &framebuffer.mode_info,
 
525
                                     framebuffer.ptr,
 
526
                                     doublebuf_pageflipping_set_page,
 
527
                                     framebuffer.ptr + page_size);
 
528
        else
 
529
          err = grub_video_fb_setup (mode_type, mode_mask,
 
530
                                     &framebuffer.mode_info,
 
531
                                     framebuffer.ptr, 0, 0);
 
532
      }
696
533
 
697
534
      /* Copy default palette to initialize emulated palette.  */
698
535
      err = grub_video_fb_set_palette (0, GRUB_VIDEO_FBSTD_NUMCOLORS,
724
561
}
725
562
 
726
563
static grub_err_t
727
 
grub_video_vbe_swap_buffers (void)
728
 
{
729
 
  grub_err_t err;
730
 
  if (!framebuffer.update_screen)
731
 
    return GRUB_ERR_NONE;
732
 
 
733
 
  err = framebuffer.update_screen (framebuffer.front_target,
734
 
                                   framebuffer.back_target);
735
 
  if (err)
736
 
    return err;
737
 
 
738
 
  return GRUB_ERR_NONE;
739
 
}
740
 
 
741
 
static grub_err_t
742
 
grub_video_vbe_set_active_render_target (struct grub_video_render_target *target)
743
 
{
744
 
  if (target == GRUB_VIDEO_RENDER_TARGET_DISPLAY)
745
 
      target = framebuffer.back_target;
746
 
 
747
 
  return grub_video_fb_set_active_render_target (target);
748
 
}
749
 
 
750
 
static grub_err_t
751
 
grub_video_vbe_get_active_render_target (struct grub_video_render_target **target)
752
 
{
753
 
  grub_err_t err;
754
 
  err = grub_video_fb_get_active_render_target (target);
755
 
  if (err)
756
 
    return err;
757
 
 
758
 
  if (*target == framebuffer.back_target)
759
 
    *target = GRUB_VIDEO_RENDER_TARGET_DISPLAY;
760
 
 
761
 
  return GRUB_ERR_NONE;
762
 
}
763
 
 
764
 
static grub_err_t
765
564
grub_video_vbe_get_info_and_fini (struct grub_video_mode_info *mode_info,
766
565
                                  void **framebuf)
767
566
{
768
 
  grub_memcpy (mode_info, &(framebuffer.mode_info), sizeof (*mode_info));
769
 
  *framebuf = (char *) framebuffer.ptr
770
 
    + framebuffer.displayed_page * framebuffer.page_size;
771
 
 
772
567
  grub_free (vbe_mode_list);
773
568
  vbe_mode_list = NULL;
774
 
 
775
 
  grub_video_fb_fini ();
776
 
  grub_free (framebuffer.offscreen_buffer);
777
 
 
778
 
  return GRUB_ERR_NONE;
 
569
  return grub_video_fb_get_info_and_fini (mode_info, framebuf);
779
570
}
780
571
 
781
572
static struct grub_video_adapter grub_video_vbe_adapter =
783
574
    .name = "VESA BIOS Extension Video Driver",
784
575
    .id = GRUB_VIDEO_DRIVER_VBE,
785
576
 
 
577
    .prio = GRUB_VIDEO_ADAPTER_PRIO_FIRMWARE,
 
578
 
786
579
    .init = grub_video_vbe_init,
787
580
    .fini = grub_video_vbe_fini,
788
581
    .setup = grub_video_vbe_setup,
800
593
    .blit_bitmap = grub_video_fb_blit_bitmap,
801
594
    .blit_render_target = grub_video_fb_blit_render_target,
802
595
    .scroll = grub_video_fb_scroll,
803
 
    .swap_buffers = grub_video_vbe_swap_buffers,
 
596
    .swap_buffers = grub_video_fb_swap_buffers,
804
597
    .create_render_target = grub_video_fb_create_render_target,
805
598
    .delete_render_target = grub_video_fb_delete_render_target,
806
 
    .set_active_render_target = grub_video_vbe_set_active_render_target,
807
 
    .get_active_render_target = grub_video_vbe_get_active_render_target,
 
599
    .set_active_render_target = grub_video_fb_set_active_render_target,
 
600
    .get_active_render_target = grub_video_fb_get_active_render_target,
808
601
 
809
602
    .next = 0
810
603
  };