GRUB_MOD_LICENSE ("GPLv3+");
+typedef grub_err_t (*grub_video_fb_doublebuf_update_screen_t) (void);
+typedef volatile void *framebuf_t;
+
static struct
{
struct grub_video_fbrender_target *render_target;
- struct grub_video_fbrender_target *front_target;
struct grub_video_fbrender_target *back_target;
struct grub_video_palette_data *palette;
+ framebuf_t pages[2];
unsigned int palette_size;
/* For page flipping strategy. */
int displayed_page; /* The page # that is the front buffer. */
{
grub_free (framebuffer.palette);
framebuffer.render_target = 0;
- framebuffer.front_target = 0;
framebuffer.back_target = 0;
framebuffer.palette = 0;
framebuffer.palette_size = 0;
grub_free (framebuffer.offscreen_buffer);
grub_free (framebuffer.palette);
framebuffer.render_target = 0;
- framebuffer.front_target = 0;
framebuffer.back_target = 0;
framebuffer.palette = 0;
framebuffer.palette_size = 0;
}
static grub_err_t
-doublebuf_blit_update_screen (struct grub_video_fbrender_target *front,
- struct grub_video_fbrender_target *back)
+doublebuf_blit_update_screen (void)
{
- grub_memcpy (front->data, back->data,
- front->mode_info.pitch * front->mode_info.height);
+ grub_memcpy ((void *) framebuffer.pages[0], framebuffer.back_target->data,
+ framebuffer.back_target->mode_info.pitch
+ * framebuffer.back_target->mode_info.height);
return GRUB_ERR_NONE;
}
static grub_err_t
-grub_video_fb_doublebuf_blit_init (struct grub_video_fbrender_target **front,
- struct grub_video_fbrender_target **back,
+grub_video_fb_doublebuf_blit_init (struct grub_video_fbrender_target **back,
struct grub_video_mode_info mode_info,
- void *framebuf)
+ volatile void *framebuf)
{
grub_err_t err;
- int page_size = mode_info.pitch * mode_info.height;
-
- err = grub_video_fb_create_render_target_from_pointer (front, &mode_info,
- framebuf);
- if (err)
- return err;
+ grub_size_t page_size = mode_info.pitch * mode_info.height;
framebuffer.offscreen_buffer = grub_malloc (page_size);
if (! framebuffer.offscreen_buffer)
- {
- grub_video_fb_delete_render_target (*front);
- *front = 0;
- return grub_errno;
- }
+ return grub_errno;
- err = grub_video_fb_create_render_target_from_pointer (back, &mode_info,
+ err = grub_video_fb_create_render_target_from_pointer (&framebuffer.back_target,
+ &mode_info,
framebuffer.offscreen_buffer);
if (err)
{
- grub_video_fb_delete_render_target (*front);
grub_free (framebuffer.offscreen_buffer);
framebuffer.offscreen_buffer = 0;
- *front = 0;
return grub_errno;
}
(*back)->is_allocated = 1;
framebuffer.update_screen = doublebuf_blit_update_screen;
+ framebuffer.pages[0] = framebuf;
+ framebuffer.displayed_page = 0;
+ framebuffer.render_page = 0;
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)))
+doublebuf_pageflipping_update_screen (void)
{
int new_displayed_page;
- struct grub_video_fbrender_target *target;
grub_err_t err;
+ grub_memcpy ((void *) framebuffer.pages[framebuffer.render_page],
+ framebuffer.back_target->data,
+ framebuffer.back_target->mode_info.pitch
+ * framebuffer.back_target->mode_info.height);
+
/* Swap the page numbers in the framebuffer struct. */
new_displayed_page = framebuffer.render_page;
framebuffer.render_page = framebuffer.displayed_page;
return err;
}
- target = framebuffer.back_target;
- framebuffer.back_target = framebuffer.front_target;
- framebuffer.front_target = target;
-
- if (framebuffer.front_target->mode_info.mode_type
- & GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP)
- grub_memcpy (framebuffer.back_target->data, framebuffer.front_target->data,
- framebuffer.back_target->mode_info.pitch
- * framebuffer.back_target->mode_info.height);
-
- err = grub_video_fb_get_active_render_target (&target);
- if (err)
- return err;
-
- if (framebuffer.render_target == framebuffer.back_target)
- framebuffer.render_target = framebuffer.front_target;
- else if (framebuffer.render_target == framebuffer.front_target)
- framebuffer.render_target = framebuffer.back_target;
-
- return err;
+ return GRUB_ERR_NONE;
}
static grub_err_t
volatile void *page1_ptr)
{
grub_err_t err;
+ grub_size_t page_size = mode_info->pitch * mode_info->height;
- 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,
- mode_info,
- (void *) page0_ptr);
- if (err)
- return err;
+ framebuffer.offscreen_buffer = grub_malloc (page_size);
+ if (! framebuffer.offscreen_buffer)
+ {
+ return grub_errno;
+ }
err = grub_video_fb_create_render_target_from_pointer (&framebuffer.back_target,
mode_info,
- (void *) page1_ptr);
+ framebuffer.offscreen_buffer);
+
if (err)
{
- grub_video_fb_delete_render_target (framebuffer.front_target);
- return err;
+ grub_free (framebuffer.offscreen_buffer);
+ framebuffer.offscreen_buffer = 0;
+ return grub_errno;
}
+ framebuffer.back_target->is_allocated = 1;
+
+ framebuffer.displayed_page = 0;
+ framebuffer.render_page = 1;
+
+ framebuffer.update_screen = doublebuf_pageflipping_update_screen;
+ framebuffer.pages[0] = page0_ptr;
+ framebuffer.pages[1] = page1_ptr;
/* Set the framebuffer memory data pointer and display the right page. */
err = set_page_in (framebuffer.displayed_page);
if (err)
{
- grub_video_fb_delete_render_target (framebuffer.front_target);
grub_video_fb_delete_render_target (framebuffer.back_target);
return err;
}
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))
+ 1))
{
mode_info->mode_type |= GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED;
- if (updating_swap_needed)
- mode_info->mode_type |= GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP;
+ mode_info->mode_type |= GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP;
err = doublebuf_pageflipping_init (mode_info, page0_ptr,
set_page_in,
if (grub_video_check_mode_flag (mode_type, mode_mask,
GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED,
- 0))
+ 1))
{
/* It was much nicer with the cast directly at function call but
some older gcc versions don't accept it properly.*/
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,
+ err = grub_video_fb_doublebuf_blit_init (&framebuffer.back_target,
*mode_info,
tmp);
}
/* Fall back to no double buffering. */
- err = grub_video_fb_create_render_target_from_pointer (&framebuffer.front_target,
+ err = grub_video_fb_create_render_target_from_pointer (&framebuffer.back_target,
mode_info,
(void *) page0_ptr);
if (err)
return err;
- framebuffer.back_target = framebuffer.front_target;
framebuffer.update_screen = 0;
+ framebuffer.pages[0] = page0_ptr;
+ framebuffer.displayed_page = 0;
+ framebuffer.render_page = 0;
+ framebuffer.set_page = 0;
mode_info->mode_type &= ~GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED;
if (!framebuffer.update_screen)
return GRUB_ERR_NONE;
- err = framebuffer.update_screen (framebuffer.front_target,
- framebuffer.back_target);
+ err = framebuffer.update_screen ();
if (err)
return err;
grub_video_fb_get_info_and_fini (struct grub_video_mode_info *mode_info,
void **framebuf)
{
- grub_memcpy (mode_info, &(framebuffer.front_target->mode_info),
+ grub_memcpy (mode_info, &(framebuffer.back_target->mode_info),
sizeof (*mode_info));
/* We are about to load a kernel. Switch back to page zero, since some
kernel drivers expect that. */
- if ((mode_info->mode_type & GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED)
- && framebuffer.set_page && framebuffer.displayed_page != 0)
+ if (framebuffer.set_page && framebuffer.displayed_page != 0)
{
- /* Ensure both pages are exactly in sync. */
- grub_memcpy (framebuffer.back_target->data,
- framebuffer.front_target->data,
- framebuffer.back_target->mode_info.pitch
- * framebuffer.back_target->mode_info.height);
- grub_video_swap_buffers ();
+ framebuffer.update_screen ();
}
- *framebuf = framebuffer.front_target->data;
+ *framebuf = (void *) framebuffer.pages[framebuffer.displayed_page];
grub_video_fb_fini ();
static struct
{
struct grub_video_mode_info mode_info;
- struct grub_video_render_target *render_target;
grub_uint8_t *ptr;
} framebuffer;
grub_dprintf ("video", "IEEE1275: initialising FB @ %p %dx%dx%d\n",
framebuffer.ptr, framebuffer.mode_info.width,
framebuffer.mode_info.height, framebuffer.mode_info.bpp);
-
- err = grub_video_fb_create_render_target_from_pointer
- (&framebuffer.render_target, &framebuffer.mode_info, framebuffer.ptr);
+ err = grub_video_fb_setup (mode_type, mode_mask,
+ &framebuffer.mode_info,
+ framebuffer.ptr, NULL, NULL);
if (err)
- {
- grub_dprintf ("video", "IEEE1275: Couldn't create FB target\n");
- return err;
- }
-
- err = grub_video_fb_set_active_render_target (framebuffer.render_target);
-
- if (err)
- {
- grub_dprintf ("video", "IEEE1275: Couldn't set FB target\n");
- return err;
- }
+ return err;
grub_video_ieee1275_set_palette (0, GRUB_VIDEO_FBSTD_NUMCOLORS,
grub_video_fbstd_colors);
return err;
}
-static grub_err_t
-grub_video_ieee1275_swap_buffers (void)
-{
- /* TODO: Implement buffer swapping. */
- return GRUB_ERR_NONE;
-}
-
-static grub_err_t
-grub_video_ieee1275_set_active_render_target (struct grub_video_render_target *target)
-{
- if (target == GRUB_VIDEO_RENDER_TARGET_DISPLAY)
- target = framebuffer.render_target;
-
- return grub_video_fb_set_active_render_target (target);
-}
-
static grub_err_t
grub_video_ieee1275_get_info_and_fini (struct grub_video_mode_info *mode_info,
void **framebuf)
.blit_bitmap = grub_video_fb_blit_bitmap,
.blit_render_target = grub_video_fb_blit_render_target,
.scroll = grub_video_fb_scroll,
- .swap_buffers = grub_video_ieee1275_swap_buffers,
+ .swap_buffers = grub_video_fb_swap_buffers,
.create_render_target = grub_video_fb_create_render_target,
.delete_render_target = grub_video_fb_delete_render_target,
- .set_active_render_target = grub_video_ieee1275_set_active_render_target,
+ .set_active_render_target = grub_video_fb_set_active_render_target,
.get_active_render_target = grub_video_fb_get_active_render_target,
.next = 0