Move most framebuffer handling to video_fb.c
This commit is contained in:
parent
94bf3dd564
commit
26162102fa
3 changed files with 252 additions and 240 deletions
|
@ -119,11 +119,18 @@ typedef grub_err_t
|
||||||
(*grub_video_fb_doublebuf_update_screen_t) (struct grub_video_fbrender_target *front,
|
(*grub_video_fb_doublebuf_update_screen_t) (struct grub_video_fbrender_target *front,
|
||||||
struct grub_video_fbrender_target *back);
|
struct grub_video_fbrender_target *back);
|
||||||
|
|
||||||
|
typedef grub_err_t (*grub_video_fb_set_page_t) (int page);
|
||||||
|
|
||||||
grub_err_t
|
grub_err_t
|
||||||
grub_video_fb_doublebuf_blit_init (struct grub_video_fbrender_target **front,
|
grub_video_fb_setup (unsigned int mode_type, unsigned int mode_mask,
|
||||||
struct grub_video_fbrender_target **back,
|
struct grub_video_mode_info *mode_info,
|
||||||
grub_video_fb_doublebuf_update_screen_t *update_screen,
|
volatile void *page0_ptr,
|
||||||
struct grub_video_mode_info mode_info,
|
grub_video_fb_set_page_t set_page_in,
|
||||||
void *framebuf);
|
volatile void *page1_ptr);
|
||||||
|
grub_err_t
|
||||||
|
grub_video_fb_swap_buffers (void);
|
||||||
|
grub_err_t
|
||||||
|
grub_video_fb_get_info_and_fini (struct grub_video_mode_info *mode_info,
|
||||||
|
void **framebuf);
|
||||||
|
|
||||||
#endif /* ! GRUB_VIDEO_FB_HEADER */
|
#endif /* ! GRUB_VIDEO_FB_HEADER */
|
||||||
|
|
|
@ -26,8 +26,16 @@
|
||||||
#include <grub/bitmap.h>
|
#include <grub/bitmap.h>
|
||||||
|
|
||||||
static struct grub_video_fbrender_target *render_target;
|
static struct grub_video_fbrender_target *render_target;
|
||||||
|
static struct grub_video_fbrender_target *front_target;
|
||||||
|
static struct grub_video_fbrender_target *back_target;
|
||||||
struct grub_video_palette_data *palette;
|
struct grub_video_palette_data *palette;
|
||||||
static unsigned int palette_size;
|
static unsigned int palette_size;
|
||||||
|
/* For page flipping strategy. */
|
||||||
|
static int displayed_page; /* The page # that is the front buffer. */
|
||||||
|
static int render_page; /* The page # that is the back buffer. */
|
||||||
|
static grub_video_fb_set_page_t set_page;
|
||||||
|
static char *offscreen_buffer;
|
||||||
|
static grub_video_fb_doublebuf_update_screen_t update_screen;
|
||||||
|
|
||||||
/* Specify "standard" VGA palette, some video cards may
|
/* Specify "standard" VGA palette, some video cards may
|
||||||
need this and this will also be used when using RGB modes. */
|
need this and this will also be used when using RGB modes. */
|
||||||
|
@ -58,8 +66,11 @@ grub_video_fb_init (void)
|
||||||
{
|
{
|
||||||
grub_free (palette);
|
grub_free (palette);
|
||||||
render_target = 0;
|
render_target = 0;
|
||||||
|
front_target = 0;
|
||||||
|
back_target = 0;
|
||||||
palette = 0;
|
palette = 0;
|
||||||
palette_size = 0;
|
palette_size = 0;
|
||||||
|
set_page = 0;
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,10 +79,15 @@ grub_video_fb_fini (void)
|
||||||
{
|
{
|
||||||
/* TODO: destroy render targets. */
|
/* TODO: destroy render targets. */
|
||||||
|
|
||||||
|
grub_free (offscreen_buffer);
|
||||||
grub_free (palette);
|
grub_free (palette);
|
||||||
render_target = 0;
|
render_target = 0;
|
||||||
|
front_target = 0;
|
||||||
|
back_target = 0;
|
||||||
palette = 0;
|
palette = 0;
|
||||||
palette_size = 0;
|
palette_size = 0;
|
||||||
|
set_page = 0;
|
||||||
|
offscreen_buffer = 0;
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1221,6 +1237,10 @@ grub_video_fb_delete_render_target (struct grub_video_fbrender_target *target)
|
||||||
grub_err_t
|
grub_err_t
|
||||||
grub_video_fb_set_active_render_target (struct grub_video_fbrender_target *target)
|
grub_video_fb_set_active_render_target (struct grub_video_fbrender_target *target)
|
||||||
{
|
{
|
||||||
|
if (target == (struct grub_video_fbrender_target *)
|
||||||
|
GRUB_VIDEO_RENDER_TARGET_DISPLAY)
|
||||||
|
target = back_target;
|
||||||
|
|
||||||
if (! target->data)
|
if (! target->data)
|
||||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||||
"invalid render target given");
|
"invalid render target given");
|
||||||
|
@ -1235,6 +1255,9 @@ grub_video_fb_get_active_render_target (struct grub_video_fbrender_target **targ
|
||||||
{
|
{
|
||||||
*target = render_target;
|
*target = render_target;
|
||||||
|
|
||||||
|
if (*target == back_target)
|
||||||
|
*target = (struct grub_video_fbrender_target *) GRUB_VIDEO_RENDER_TARGET_DISPLAY;
|
||||||
|
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1247,16 +1270,14 @@ doublebuf_blit_update_screen (struct grub_video_fbrender_target *front,
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
grub_err_t
|
static grub_err_t
|
||||||
grub_video_fb_doublebuf_blit_init (struct grub_video_fbrender_target **front,
|
grub_video_fb_doublebuf_blit_init (struct grub_video_fbrender_target **front,
|
||||||
struct grub_video_fbrender_target **back,
|
struct grub_video_fbrender_target **back,
|
||||||
grub_video_fb_doublebuf_update_screen_t *update_screen,
|
|
||||||
struct grub_video_mode_info mode_info,
|
struct grub_video_mode_info mode_info,
|
||||||
void *framebuf)
|
void *framebuf)
|
||||||
{
|
{
|
||||||
grub_err_t err;
|
grub_err_t err;
|
||||||
int page_size = mode_info.pitch * mode_info.height;
|
int page_size = mode_info.pitch * mode_info.height;
|
||||||
void *offscreen_buffer;
|
|
||||||
|
|
||||||
err = grub_video_fb_create_render_target_from_pointer (front, &mode_info,
|
err = grub_video_fb_create_render_target_from_pointer (front, &mode_info,
|
||||||
framebuf);
|
framebuf);
|
||||||
|
@ -1283,7 +1304,200 @@ grub_video_fb_doublebuf_blit_init (struct grub_video_fbrender_target **front,
|
||||||
}
|
}
|
||||||
(*back)->is_allocated = 1;
|
(*back)->is_allocated = 1;
|
||||||
|
|
||||||
*update_screen = doublebuf_blit_update_screen;
|
update_screen = doublebuf_blit_update_screen;
|
||||||
|
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static grub_err_t
|
||||||
|
doublebuf_pageflipping_update_screen (struct grub_video_fbrender_target *front
|
||||||
|
__attribute__ ((unused)),
|
||||||
|
struct grub_video_fbrender_target *back
|
||||||
|
__attribute__ ((unused)))
|
||||||
|
{
|
||||||
|
int new_displayed_page;
|
||||||
|
struct grub_video_fbrender_target *target;
|
||||||
|
grub_err_t err;
|
||||||
|
|
||||||
|
/* Swap the page numbers in the framebuffer struct. */
|
||||||
|
new_displayed_page = render_page;
|
||||||
|
render_page = displayed_page;
|
||||||
|
displayed_page = new_displayed_page;
|
||||||
|
|
||||||
|
err = set_page (displayed_page);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
/* Restore previous state. */
|
||||||
|
render_page = displayed_page;
|
||||||
|
displayed_page = new_displayed_page;
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
target = back_target;
|
||||||
|
back_target = front_target;
|
||||||
|
front_target = target;
|
||||||
|
|
||||||
|
if (front_target->mode_info.mode_type & GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP)
|
||||||
|
grub_memcpy (back_target->data, front_target->data,
|
||||||
|
back_target->mode_info.pitch * back_target->mode_info.height);
|
||||||
|
|
||||||
|
err = grub_video_fb_get_active_render_target (&target);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
if (render_target == back_target)
|
||||||
|
render_target = front_target;
|
||||||
|
else if (target == front_target)
|
||||||
|
render_target = back_target;
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static grub_err_t
|
||||||
|
doublebuf_pageflipping_init (struct grub_video_mode_info *mode_info,
|
||||||
|
volatile void *page0_ptr,
|
||||||
|
grub_video_fb_set_page_t set_page_in,
|
||||||
|
volatile void *page1_ptr)
|
||||||
|
{
|
||||||
|
grub_err_t err;
|
||||||
|
|
||||||
|
displayed_page = 0;
|
||||||
|
render_page = 1;
|
||||||
|
|
||||||
|
update_screen = doublebuf_pageflipping_update_screen;
|
||||||
|
|
||||||
|
err = grub_video_fb_create_render_target_from_pointer (&front_target,
|
||||||
|
mode_info,
|
||||||
|
(void *) page0_ptr);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
err = grub_video_fb_create_render_target_from_pointer (&back_target,
|
||||||
|
mode_info,
|
||||||
|
(void *) page1_ptr);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
grub_video_fb_delete_render_target (front_target);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the framebuffer memory data pointer and display the right page. */
|
||||||
|
err = set_page_in (displayed_page);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
grub_video_fb_delete_render_target (front_target);
|
||||||
|
grub_video_fb_delete_render_target (back_target);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
set_page = set_page_in;
|
||||||
|
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Select the best double buffering mode available. */
|
||||||
|
grub_err_t
|
||||||
|
grub_video_fb_setup (unsigned int mode_type, unsigned int mode_mask,
|
||||||
|
struct grub_video_mode_info *mode_info,
|
||||||
|
volatile void *page0_ptr,
|
||||||
|
grub_video_fb_set_page_t set_page_in,
|
||||||
|
volatile void *page1_ptr)
|
||||||
|
{
|
||||||
|
grub_err_t err;
|
||||||
|
int updating_swap_needed;
|
||||||
|
|
||||||
|
updating_swap_needed
|
||||||
|
= grub_video_check_mode_flag (mode_type, mode_mask,
|
||||||
|
GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP, 0);
|
||||||
|
|
||||||
|
/* Do double buffering only if it's either requested or efficient. */
|
||||||
|
if (set_page_in && grub_video_check_mode_flag (mode_type, mode_mask,
|
||||||
|
GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED,
|
||||||
|
!updating_swap_needed))
|
||||||
|
{
|
||||||
|
mode_info->mode_type |= GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED;
|
||||||
|
if (updating_swap_needed)
|
||||||
|
mode_info->mode_type |= GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP;
|
||||||
|
|
||||||
|
err = doublebuf_pageflipping_init (mode_info, page0_ptr,
|
||||||
|
set_page_in,
|
||||||
|
page1_ptr);
|
||||||
|
if (!err)
|
||||||
|
{
|
||||||
|
render_target = back_target;
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
mode_info->mode_type &= ~(GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED
|
||||||
|
| GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP);
|
||||||
|
|
||||||
|
grub_errno = GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (grub_video_check_mode_flag (mode_type, mode_mask,
|
||||||
|
GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED,
|
||||||
|
0))
|
||||||
|
{
|
||||||
|
mode_info->mode_type |= (GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED
|
||||||
|
| GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP);
|
||||||
|
|
||||||
|
err = grub_video_fb_doublebuf_blit_init (&front_target,
|
||||||
|
&back_target,
|
||||||
|
*mode_info,
|
||||||
|
(void *) page0_ptr);
|
||||||
|
|
||||||
|
if (!err)
|
||||||
|
{
|
||||||
|
render_target = back_target;
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
mode_info->mode_type &= ~(GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED
|
||||||
|
| GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP);
|
||||||
|
|
||||||
|
grub_errno = GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fall back to no double buffering. */
|
||||||
|
err = grub_video_fb_create_render_target_from_pointer (&front_target,
|
||||||
|
mode_info,
|
||||||
|
(void *) page0_ptr);
|
||||||
|
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
back_target = front_target;
|
||||||
|
update_screen = 0;
|
||||||
|
|
||||||
|
mode_info->mode_type &= ~GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED;
|
||||||
|
|
||||||
|
render_target = back_target;
|
||||||
|
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
grub_err_t
|
||||||
|
grub_video_fb_swap_buffers (void)
|
||||||
|
{
|
||||||
|
grub_err_t err;
|
||||||
|
if (!update_screen)
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
|
||||||
|
err = update_screen (front_target, back_target);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_err_t
|
||||||
|
grub_video_fb_get_info_and_fini (struct grub_video_mode_info *mode_info,
|
||||||
|
void **framebuf)
|
||||||
|
{
|
||||||
|
grub_memcpy (mode_info, &(front_target->mode_info), sizeof (*mode_info));
|
||||||
|
*framebuf = front_target->data;
|
||||||
|
|
||||||
|
grub_video_fb_fini ();
|
||||||
|
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,25 +40,12 @@ static grub_uint32_t last_set_mode = 3;
|
||||||
static struct
|
static struct
|
||||||
{
|
{
|
||||||
struct grub_video_mode_info mode_info;
|
struct grub_video_mode_info mode_info;
|
||||||
struct grub_video_render_target *front_target;
|
|
||||||
struct grub_video_render_target *back_target;
|
|
||||||
|
|
||||||
unsigned int bytes_per_scan_line;
|
unsigned int bytes_per_scan_line;
|
||||||
unsigned int bytes_per_pixel;
|
unsigned int bytes_per_pixel;
|
||||||
grub_uint32_t active_vbe_mode;
|
grub_uint32_t active_vbe_mode;
|
||||||
grub_uint8_t *ptr;
|
grub_uint8_t *ptr;
|
||||||
int index_color_mode;
|
int index_color_mode;
|
||||||
|
|
||||||
char *offscreen_buffer;
|
|
||||||
|
|
||||||
grub_size_t page_size; /* The size of a page in bytes. */
|
|
||||||
|
|
||||||
/* For page flipping strategy. */
|
|
||||||
int displayed_page; /* The page # that is the front buffer. */
|
|
||||||
int render_page; /* The page # that is the back buffer. */
|
|
||||||
|
|
||||||
/* Virtual functions. */
|
|
||||||
grub_video_fb_doublebuf_update_screen_t update_screen;
|
|
||||||
} framebuffer;
|
} framebuffer;
|
||||||
|
|
||||||
static grub_uint32_t initial_vbe_mode;
|
static grub_uint32_t initial_vbe_mode;
|
||||||
|
@ -377,7 +364,6 @@ grub_video_vbe_fini (void)
|
||||||
vbe_mode_list = NULL;
|
vbe_mode_list = NULL;
|
||||||
|
|
||||||
err = grub_video_fb_fini ();
|
err = grub_video_fb_fini ();
|
||||||
grub_free (framebuffer.offscreen_buffer);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -387,11 +373,11 @@ grub_video_vbe_fini (void)
|
||||||
respectively.
|
respectively.
|
||||||
*/
|
*/
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
doublebuf_pageflipping_commit (void)
|
doublebuf_pageflipping_set_page (int page)
|
||||||
{
|
{
|
||||||
/* Tell the video adapter to display the new front page. */
|
/* Tell the video adapter to display the new front page. */
|
||||||
int display_start_line
|
int display_start_line
|
||||||
= framebuffer.mode_info.height * framebuffer.displayed_page;
|
= framebuffer.mode_info.height * page;
|
||||||
|
|
||||||
grub_vbe_status_t vbe_err =
|
grub_vbe_status_t vbe_err =
|
||||||
grub_vbe_bios_set_display_start (0, display_start_line);
|
grub_vbe_bios_set_display_start (0, display_start_line);
|
||||||
|
@ -402,164 +388,6 @@ doublebuf_pageflipping_commit (void)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static grub_err_t
|
|
||||||
doublebuf_pageflipping_update_screen (struct grub_video_fbrender_target *front
|
|
||||||
__attribute__ ((unused)),
|
|
||||||
struct grub_video_fbrender_target *back
|
|
||||||
__attribute__ ((unused)))
|
|
||||||
{
|
|
||||||
int new_displayed_page;
|
|
||||||
struct grub_video_fbrender_target *target;
|
|
||||||
grub_err_t err;
|
|
||||||
|
|
||||||
/* Swap the page numbers in the framebuffer struct. */
|
|
||||||
new_displayed_page = framebuffer.render_page;
|
|
||||||
framebuffer.render_page = framebuffer.displayed_page;
|
|
||||||
framebuffer.displayed_page = new_displayed_page;
|
|
||||||
|
|
||||||
err = doublebuf_pageflipping_commit ();
|
|
||||||
if (err)
|
|
||||||
{
|
|
||||||
/* Restore previous state. */
|
|
||||||
framebuffer.render_page = framebuffer.displayed_page;
|
|
||||||
framebuffer.displayed_page = new_displayed_page;
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (framebuffer.mode_info.mode_type & GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP)
|
|
||||||
grub_memcpy (framebuffer.ptr + framebuffer.render_page
|
|
||||||
* framebuffer.page_size, framebuffer.ptr
|
|
||||||
+ framebuffer.displayed_page * framebuffer.page_size,
|
|
||||||
framebuffer.page_size);
|
|
||||||
|
|
||||||
target = framebuffer.back_target;
|
|
||||||
framebuffer.back_target = framebuffer.front_target;
|
|
||||||
framebuffer.front_target = target;
|
|
||||||
|
|
||||||
err = grub_video_fb_get_active_render_target (&target);
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
if (target == framebuffer.back_target)
|
|
||||||
err = grub_video_fb_set_active_render_target (framebuffer.front_target);
|
|
||||||
else if (target == framebuffer.front_target)
|
|
||||||
err = grub_video_fb_set_active_render_target (framebuffer.back_target);
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
static grub_err_t
|
|
||||||
doublebuf_pageflipping_init (void)
|
|
||||||
{
|
|
||||||
/* Get video RAM size in bytes. */
|
|
||||||
grub_size_t vram_size = controller_info.total_memory << 16;
|
|
||||||
grub_err_t err;
|
|
||||||
|
|
||||||
framebuffer.page_size =
|
|
||||||
framebuffer.mode_info.pitch * framebuffer.mode_info.height;
|
|
||||||
|
|
||||||
if (2 * framebuffer.page_size > vram_size)
|
|
||||||
return grub_error (GRUB_ERR_OUT_OF_MEMORY,
|
|
||||||
"Not enough video memory for double buffering.");
|
|
||||||
|
|
||||||
framebuffer.displayed_page = 0;
|
|
||||||
framebuffer.render_page = 1;
|
|
||||||
|
|
||||||
framebuffer.update_screen = doublebuf_pageflipping_update_screen;
|
|
||||||
|
|
||||||
err = grub_video_fb_create_render_target_from_pointer (&framebuffer.front_target, &framebuffer.mode_info, framebuffer.ptr);
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
err = grub_video_fb_create_render_target_from_pointer (&framebuffer.back_target, &framebuffer.mode_info, framebuffer.ptr + framebuffer.page_size);
|
|
||||||
if (err)
|
|
||||||
{
|
|
||||||
grub_video_fb_delete_render_target (framebuffer.front_target);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set the framebuffer memory data pointer and display the right page. */
|
|
||||||
err = doublebuf_pageflipping_commit ();
|
|
||||||
if (err)
|
|
||||||
{
|
|
||||||
grub_video_fb_delete_render_target (framebuffer.front_target);
|
|
||||||
grub_video_fb_delete_render_target (framebuffer.back_target);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
return GRUB_ERR_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Select the best double buffering mode available. */
|
|
||||||
static grub_err_t
|
|
||||||
double_buffering_init (unsigned int mode_type, unsigned int mode_mask)
|
|
||||||
{
|
|
||||||
grub_err_t err;
|
|
||||||
int updating_swap_needed;
|
|
||||||
|
|
||||||
updating_swap_needed
|
|
||||||
= grub_video_check_mode_flag (mode_type, mode_mask,
|
|
||||||
GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP, 0);
|
|
||||||
|
|
||||||
/* Do double buffering only if it's either requested or efficient. */
|
|
||||||
if (grub_video_check_mode_flag (mode_type, mode_mask,
|
|
||||||
GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED,
|
|
||||||
!updating_swap_needed))
|
|
||||||
{
|
|
||||||
framebuffer.mode_info.mode_type |= GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED;
|
|
||||||
if (updating_swap_needed)
|
|
||||||
framebuffer.mode_info.mode_type |= GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP;
|
|
||||||
err = doublebuf_pageflipping_init ();
|
|
||||||
if (!err)
|
|
||||||
return GRUB_ERR_NONE;
|
|
||||||
|
|
||||||
framebuffer.mode_info.mode_type
|
|
||||||
&= ~(GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED
|
|
||||||
| GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP);
|
|
||||||
|
|
||||||
grub_errno = GRUB_ERR_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (grub_video_check_mode_flag (mode_type, mode_mask,
|
|
||||||
GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED,
|
|
||||||
0))
|
|
||||||
{
|
|
||||||
framebuffer.mode_info.mode_type
|
|
||||||
|= (GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED
|
|
||||||
| GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP);
|
|
||||||
|
|
||||||
err = grub_video_fb_doublebuf_blit_init (&framebuffer.front_target,
|
|
||||||
&framebuffer.back_target,
|
|
||||||
&framebuffer.update_screen,
|
|
||||||
framebuffer.mode_info,
|
|
||||||
framebuffer.ptr);
|
|
||||||
|
|
||||||
if (!err)
|
|
||||||
return GRUB_ERR_NONE;
|
|
||||||
|
|
||||||
framebuffer.mode_info.mode_type
|
|
||||||
&= ~(GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED
|
|
||||||
| GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP);
|
|
||||||
|
|
||||||
grub_errno = GRUB_ERR_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Fall back to no double buffering. */
|
|
||||||
err = grub_video_fb_create_render_target_from_pointer (&framebuffer.front_target, &framebuffer.mode_info, framebuffer.ptr);
|
|
||||||
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
framebuffer.back_target = framebuffer.front_target;
|
|
||||||
framebuffer.update_screen = 0;
|
|
||||||
|
|
||||||
framebuffer.mode_info.mode_type &= ~GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED;
|
|
||||||
|
|
||||||
return GRUB_ERR_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
grub_video_vbe_setup (unsigned int width, unsigned int height,
|
grub_video_vbe_setup (unsigned int width, unsigned int height,
|
||||||
unsigned int mode_type, unsigned int mode_mask)
|
unsigned int mode_type, unsigned int mode_mask)
|
||||||
|
@ -684,15 +512,24 @@ grub_video_vbe_setup (unsigned int width, unsigned int height,
|
||||||
|
|
||||||
framebuffer.mode_info.blit_format = grub_video_get_blit_format (&framebuffer.mode_info);
|
framebuffer.mode_info.blit_format = grub_video_get_blit_format (&framebuffer.mode_info);
|
||||||
|
|
||||||
/* Set up double buffering and targets. */
|
{
|
||||||
err = double_buffering_init (mode_type, mode_mask);
|
/* Get video RAM size in bytes. */
|
||||||
if (err)
|
grub_size_t vram_size = controller_info.total_memory << 16;
|
||||||
return err;
|
grub_size_t page_size; /* The size of a page in bytes. */
|
||||||
|
|
||||||
err = grub_video_fb_set_active_render_target (framebuffer.back_target);
|
page_size = framebuffer.mode_info.pitch * framebuffer.mode_info.height;
|
||||||
|
|
||||||
if (err)
|
if (vram_size >= 2 * page_size)
|
||||||
return err;
|
err = grub_video_fb_setup (mode_type, mode_mask,
|
||||||
|
&framebuffer.mode_info,
|
||||||
|
framebuffer.ptr,
|
||||||
|
doublebuf_pageflipping_set_page,
|
||||||
|
framebuffer.ptr + page_size);
|
||||||
|
else
|
||||||
|
err = grub_video_fb_setup (mode_type, mode_mask,
|
||||||
|
&framebuffer.mode_info,
|
||||||
|
framebuffer.ptr, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
/* Copy default palette to initialize emulated palette. */
|
/* Copy default palette to initialize emulated palette. */
|
||||||
err = grub_video_fb_set_palette (0, GRUB_VIDEO_FBSTD_NUMCOLORS,
|
err = grub_video_fb_set_palette (0, GRUB_VIDEO_FBSTD_NUMCOLORS,
|
||||||
|
@ -723,59 +560,13 @@ grub_video_vbe_set_palette (unsigned int start, unsigned int count,
|
||||||
return grub_video_fb_set_palette (start, count, palette_data);
|
return grub_video_fb_set_palette (start, count, palette_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static grub_err_t
|
|
||||||
grub_video_vbe_swap_buffers (void)
|
|
||||||
{
|
|
||||||
grub_err_t err;
|
|
||||||
if (!framebuffer.update_screen)
|
|
||||||
return GRUB_ERR_NONE;
|
|
||||||
|
|
||||||
err = framebuffer.update_screen (framebuffer.front_target,
|
|
||||||
framebuffer.back_target);
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
return GRUB_ERR_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static grub_err_t
|
|
||||||
grub_video_vbe_set_active_render_target (struct grub_video_render_target *target)
|
|
||||||
{
|
|
||||||
if (target == GRUB_VIDEO_RENDER_TARGET_DISPLAY)
|
|
||||||
target = framebuffer.back_target;
|
|
||||||
|
|
||||||
return grub_video_fb_set_active_render_target (target);
|
|
||||||
}
|
|
||||||
|
|
||||||
static grub_err_t
|
|
||||||
grub_video_vbe_get_active_render_target (struct grub_video_render_target **target)
|
|
||||||
{
|
|
||||||
grub_err_t err;
|
|
||||||
err = grub_video_fb_get_active_render_target (target);
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
if (*target == framebuffer.back_target)
|
|
||||||
*target = GRUB_VIDEO_RENDER_TARGET_DISPLAY;
|
|
||||||
|
|
||||||
return GRUB_ERR_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
grub_video_vbe_get_info_and_fini (struct grub_video_mode_info *mode_info,
|
grub_video_vbe_get_info_and_fini (struct grub_video_mode_info *mode_info,
|
||||||
void **framebuf)
|
void **framebuf)
|
||||||
{
|
{
|
||||||
grub_memcpy (mode_info, &(framebuffer.mode_info), sizeof (*mode_info));
|
|
||||||
*framebuf = (char *) framebuffer.ptr
|
|
||||||
+ framebuffer.displayed_page * framebuffer.page_size;
|
|
||||||
|
|
||||||
grub_free (vbe_mode_list);
|
grub_free (vbe_mode_list);
|
||||||
vbe_mode_list = NULL;
|
vbe_mode_list = NULL;
|
||||||
|
return grub_video_fb_get_info_and_fini (mode_info, framebuf);
|
||||||
grub_video_fb_fini ();
|
|
||||||
grub_free (framebuffer.offscreen_buffer);
|
|
||||||
|
|
||||||
return GRUB_ERR_NONE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct grub_video_adapter grub_video_vbe_adapter =
|
static struct grub_video_adapter grub_video_vbe_adapter =
|
||||||
|
@ -800,11 +591,11 @@ static struct grub_video_adapter grub_video_vbe_adapter =
|
||||||
.blit_bitmap = grub_video_fb_blit_bitmap,
|
.blit_bitmap = grub_video_fb_blit_bitmap,
|
||||||
.blit_render_target = grub_video_fb_blit_render_target,
|
.blit_render_target = grub_video_fb_blit_render_target,
|
||||||
.scroll = grub_video_fb_scroll,
|
.scroll = grub_video_fb_scroll,
|
||||||
.swap_buffers = grub_video_vbe_swap_buffers,
|
.swap_buffers = grub_video_fb_swap_buffers,
|
||||||
.create_render_target = grub_video_fb_create_render_target,
|
.create_render_target = grub_video_fb_create_render_target,
|
||||||
.delete_render_target = grub_video_fb_delete_render_target,
|
.delete_render_target = grub_video_fb_delete_render_target,
|
||||||
.set_active_render_target = grub_video_vbe_set_active_render_target,
|
.set_active_render_target = grub_video_fb_set_active_render_target,
|
||||||
.get_active_render_target = grub_video_vbe_get_active_render_target,
|
.get_active_render_target = grub_video_fb_get_active_render_target,
|
||||||
|
|
||||||
.next = 0
|
.next = 0
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue