grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH] 2/5 VBE double buffering


From: Vesa Jääskeläinen
Subject: Re: [PATCH] 2/5 VBE double buffering
Date: Sat, 31 Jan 2009 23:16:44 +0200
User-agent: Thunderbird 2.0.0.19 (Windows/20081209)

Colin D Bennett wrote:
> This patch adds double buffering support support to the VBE
> video driver including page flipping and blitting from an offscreen back
> buffer.
> 
> The patch is against GRUB trunk revision 1964.

Unless we come up with better idea we can go with this time being...
Check the comments below and act accordingly...

> === modified file 'include/grub/video.h'
> --- include/grub/video.h      2009-01-02 15:26:06 +0000
> +++ include/grub/video.h      2009-01-31 17:48:10 +0000
> @@ -47,10 +47,10 @@
>  #define GRUB_VIDEO_MODE_TYPE_DEPTH_MASK              0x0000ff00
>  #define GRUB_VIDEO_MODE_TYPE_DEPTH_POS               8
>  
> -/* Defined predefined render targets.  */
> -#define GRUB_VIDEO_RENDER_TARGET_DISPLAY     ((struct 
> grub_video_render_target *) 0)
> -#define GRUB_VIDEO_RENDER_TARGET_FRONT_BUFFER        ((struct 
> grub_video_render_target *) 0)
> -#define GRUB_VIDEO_RENDER_TARGET_BACK_BUFFER ((struct 
> grub_video_render_target *) 1)
> +/* The basic render target representing the whole display.  This always
> +   renders to the back buffer when double-buffering is in use.  */
> +#define GRUB_VIDEO_RENDER_TARGET_DISPLAY \
> +  ((struct grub_video_render_target *) 0)
>  
>  /* Defined blitting formats.  */
>  enum grub_video_blit_format
> 
> === modified file 'video/i386/pc/vbe.c'
> --- video/i386/pc/vbe.c       2009-01-02 15:26:06 +0000
> +++ video/i386/pc/vbe.c       2009-01-31 17:48:10 +0000
> @@ -62,6 +62,7 @@
>  static struct
>  {
>    struct grub_video_render_target render_target;

We do not use comments at end of line. Please move it to line before
actual variable it is describing.

> +  int is_double_buffered;       /* Is the video mode double buffered? */
>  
>    unsigned int bytes_per_scan_line;
>    unsigned int bytes_per_pixel;
> @@ -76,6 +77,24 @@
>  static grub_uint32_t mode_in_use = 0x55aa;
>  static grub_uint16_t *mode_list;
>  

Ditto for below. And after '.' in comment there should be two spaces.

> +static struct 
> +{
> +  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. */
> +
> +  /* For blit strategy. */
> +  grub_uint8_t *offscreen_buffer;
> +
> +  /* Virtual functions. */
> +  int (*update_screen) (void);
> +  int (*destroy) (void);
> +} doublebuf_state;
> +
> +static void double_buffering_init (void);
> +
>  static void *
>  real2pm (grub_vbe_farptr_t ptr)
>  {
> @@ -375,6 +394,7 @@
>    /* Reset frame buffer and render target variables.  */
>    grub_memset (&framebuffer, 0, sizeof(framebuffer));
>    render_target = &framebuffer.render_target;
> +  grub_memset (&doublebuf_state, 0, sizeof(doublebuf_state));
>  
>    return GRUB_ERR_NONE;
>  }
> @@ -390,6 +410,9 @@
>      /* TODO: Decide, is this something we want to do.  */
>      return grub_errno;
>  
> +  if (doublebuf_state.destroy)
> +    doublebuf_state.destroy();
> +
>    /* TODO: Free any resources allocated by driver.  */
>    grub_free (mode_list);
>    mode_list = 0;
> @@ -532,9 +555,12 @@
>        render_target->viewport.width = active_mode_info.x_resolution;
>        render_target->viewport.height = active_mode_info.y_resolution;
>  
> -      /* Set framebuffer pointer and mark it as non allocated.  */
> +      /* Mark framebuffer memory as non allocated.  */
>        render_target->is_allocated = 0;
> -      render_target->data = framebuffer.ptr;

Please add empty line here to group it a bit nicer.

> +      /* Set up double buffering information. */
> +      framebuffer.is_double_buffered =
> +        ((mode_type & GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED) != 0);
> +      double_buffering_init ();
>  
>        /* Copy default palette to initialize emulated palette.  */
>        for (i = 0;
> @@ -555,6 +581,166 @@
>    return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no matching mode found.");
>  }
>  
> +/* 
> +   Set framebuffer render target page and display the proper page, based on
> +   `doublebuf_state.render_page' and `doublebuf_state.displayed_page',
> +   respectively. 
> +
> +   Returns 0 upon success, nonzero upon failure.
> + */
> +static int
> +doublebuf_pageflipping_commit (void)
> +{

Dot spaces..

> +  /* Set the render target's data pointer to the start of the render_page. */
> +  framebuffer.render_target.data =
> +    ((char *) framebuffer.ptr) +
> +    doublebuf_state.page_size * doublebuf_state.render_page;
> +
> +  /* Tell the video adapter to display the new front page. */
> +  int display_start_line =
> +    framebuffer.render_target.mode_info.height 
> +    * doublebuf_state.displayed_page;
> + 
> +  grub_vbe_status_t vbe_err = 
> +    grub_vbe_bios_set_display_start (0, display_start_line);
> +  if (vbe_err != GRUB_VBE_STATUS_OK)
> +    return 1;
> +
> +  return 0;
> +}
> +
> +static int
> +doublebuf_pageflipping_update_screen (void)
> +{

Same here...

> +  /* Swap the page numbers in the framebuffer struct. */
> +  int new_displayed_page = doublebuf_state.render_page;
> +  doublebuf_state.render_page = doublebuf_state.displayed_page;
> +  doublebuf_state.displayed_page = new_displayed_page;
> +
> +  return doublebuf_pageflipping_commit ();
> +}
> +
> +static int
> +doublebuf_pageflipping_destroy (void)
> +{
> +  doublebuf_state.update_screen = 0;
> +  doublebuf_state.destroy = 0;
> +  return 0;
> +}
> +
> +static int
> +doublebuf_pageflipping_init (void)
> +{
> +  doublebuf_state.page_size =
> +    framebuffer.bytes_per_scan_line * render_target->mode_info.height;
> +  
> +  /* Get video RAM size in bytes.  */
> +  grub_size_t vram_size = controller_info.total_memory << 16;
> +

Create new line for comment...

> +  if (2 * doublebuf_state.page_size > vram_size)
> +    return 1;   /* Not enough video memory for 2 pages. */
> +
> +  doublebuf_state.displayed_page = 0;
> +  doublebuf_state.render_page = 1;
> +
> +  doublebuf_state.update_screen = doublebuf_pageflipping_update_screen;
> +  doublebuf_state.destroy = doublebuf_pageflipping_destroy;
> +

Same *2 below...

> +  /* Set the framebuffer memory data pointer and display the right page. */
> +  if (doublebuf_pageflipping_commit () != GRUB_ERR_NONE)
> +    return 1;   /* Unable to set the display start.  */
> +
> +  framebuffer.render_target.mode_info.mode_type
> +    |= GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED;
> +  return 0;
> +}
> +
> +static int
> +doublebuf_blit_update_screen (void)
> +{
> +  grub_memcpy (framebuffer.ptr,
> +               doublebuf_state.offscreen_buffer, 
> +               doublebuf_state.page_size);
> +  return 0;
> +}
> +
> +static int
> +doublebuf_blit_destroy (void)
> +{
> +  grub_free (doublebuf_state.offscreen_buffer);
> +  doublebuf_state.offscreen_buffer = 0;
> +
> +  doublebuf_state.update_screen = 0;
> +  doublebuf_state.destroy = 0;
> +  return 0;
> +}
> +
> +static int
> +doublebuf_blit_init (void)
> +{
> +  doublebuf_state.page_size =
> +    framebuffer.bytes_per_scan_line * render_target->mode_info.height;
> +
> +  doublebuf_state.offscreen_buffer = (grub_uint8_t *)
> +    grub_malloc (doublebuf_state.page_size);

Here too... Ok... and the rest in the file ;)

> +  if (doublebuf_state.offscreen_buffer == 0)
> +    return 1;   /* Error.  */
> +
> +  framebuffer.render_target.data = doublebuf_state.offscreen_buffer;
> +  doublebuf_state.update_screen = doublebuf_blit_update_screen;
> +  doublebuf_state.destroy = doublebuf_blit_destroy;
> +
> +  framebuffer.render_target.mode_info.mode_type
> +    |= GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED;
> +  return 0;
> +}
> +
> +static int
> +doublebuf_null_update_screen (void)
> +{
> +  return 0;
> +}
> +
> +static int
> +doublebuf_null_destroy (void)
> +{
> +  doublebuf_state.update_screen = 0;
> +  doublebuf_state.destroy = 0;
> +  return 0;
> +}
> +
> +static int
> +doublebuf_null_init (void)
> +{
> +  framebuffer.render_target.data = framebuffer.ptr;
> +  doublebuf_state.update_screen = doublebuf_null_update_screen;
> +  doublebuf_state.destroy = doublebuf_null_destroy;
> +
> +  framebuffer.render_target.mode_info.mode_type
> +    &= ~GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED;
> +  return 0;
> +}
> +
> +/* Select the best double buffering mode available.  */
> +static void
> +double_buffering_init (void)
> +{
> +  if (doublebuf_state.destroy)
> +    doublebuf_state.destroy();
> +
> +  if (framebuffer.is_double_buffered)
> +    {
> +      if (doublebuf_pageflipping_init () == 0)
> +        return;
> +
> +      if (doublebuf_blit_init () == 0)
> +        return;
> +    }
> +
> +  /* Fall back to no double buffering. */
> +  doublebuf_null_init ();
> +}
> +
>  static grub_err_t
>  grub_video_vbe_get_info (struct grub_video_mode_info *mode_info)
>  {
> @@ -1443,7 +1629,10 @@
>  static grub_err_t
>  grub_video_vbe_swap_buffers (void)
>  {
> -  /* TODO: Implement buffer swapping.  */
> +  if (doublebuf_state.update_screen () != 0)
> +    return grub_error (GRUB_ERR_INVALID_COMMAND,
> +                       "Double buffer update failed");
> +
>    return GRUB_ERR_NONE;
>  }
>  
> @@ -1542,17 +1731,13 @@
>  static grub_err_t
>  grub_video_vbe_set_active_render_target (struct grub_video_render_target 
> *target)
>  {
> -  if (target == GRUB_VIDEO_RENDER_TARGET_FRONT_BUFFER)
> +  if (target == GRUB_VIDEO_RENDER_TARGET_DISPLAY)
>      {
>        render_target = &framebuffer.render_target;
>  
>        return GRUB_ERR_NONE;
>      }
>  
> -  if (target == GRUB_VIDEO_RENDER_TARGET_BACK_BUFFER)
> -    return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
> -                       "double buffering not implemented yet.");
> -
>    if (! target->data)
>      return grub_error (GRUB_ERR_BAD_ARGUMENT,
>                         "invalid render target given.");





reply via email to

[Prev in Thread] Current Thread [Next in Thread]