GSoC #07 VBE double buffering
PATCH 1/1 GSoC #07 VBE double buffering
This patch adds double buffering support to the VBE video driver. It uses page flipping if possible, and falls back on using an offscreen buffer which is blitted to video memory if page flipping is not possible.
Regards,
Colin
2008-08-30 Colin D Bennett <[email protected]>
VBE smart double buffering using page flipping or blitting.
* include/grub/video.h (GRUB_VIDEO_RENDER_TARGET_FRONT_BUFFER):
Removed.
(GRUB_VIDEO_RENDER_TARGET_BACK_BUFFER): Removed.
* video/i386/pc/vbe.c (framebuffer): Added is_double_buffered field. (doublebuf_state): New struct.
(double_buffering_init): New function. (grub_video_vbe_init): Clear doublebuf_state. (grub_video_vbe_fini): Destroy doublebuf_state. (grub_video_vbe_setup): Call double_buffering_init to initialize double buffering.
(doublebuf_pageflipping_commit): New function. (doublebuf_pageflipping_update_screen): New function. (doublebuf_pageflipping_destroy): New function. (doublebuf_pageflipping_init): New function. (doublebuf_blit_update_screen): New function. (doublebuf_blit_destroy): New function. (doublebuf_blit_init): New function. (doublebuf_null_update_screen): New function. (doublebuf_null_destroy): New function. (doublebuf_null_init): New function. (double_buffering_init): New function. (grub_video_vbe_swap_buffers): Implement buffer swapping. (grub_video_vbe_set_active_render_target): Handle special target GRUB_VIDEO_RENDER_TARGET_DISPLAY and neither GRUB_VIDEO_RENDER_TARGET_FRONT_BUFFER nor GRUB_VIDEO_RENDER_TARGET_BACK_BUFFER.
=== modified file 'include/grub/video.h'
grub/video.h +8 -4
@@ -47,10 +47,11 @@#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) +/* Predefined render target: */ +/* The render target that client code should render to. */ +#define GRUB_VIDEO_RENDER_TARGET_DISPLAY \ + ((struct grub_video_render_target *) 0) +/* Defined blitting formats. */ enum grub_video_blit_format
@@ -267,6 +268,9 @@grub_err_t grub_video_scroll (grub_video_color_t color,int dx,int dy); +/* Swap the pages referred to by the front buffer and back buffer render +* targets, and the page previously referred to by the back buffer is made +* visible on the display. */ grub_err_t grub_video_swap_buffers (void ); grub_err_t grub_video_create_render_target (struct grub_video_render_target **result,
=== modified file 'video/i386/pc/vbe.c'
i386/pc/vbe.c +196 -10
262 lines not on this page · raw message
PATCH 1/1 GSoC #07 VBE double buffering (vs r1885)
Clean patch against trunk SVN revision 1885.
Regards,
Colin
=== modified file 'include/grub/video.h'
grub/video.h +4 -4
@@ -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'
i386/pc/vbe.c +193 -8
256 lines not on this page · raw message
Re: [PATCH] GSoC #07 VBE double buffering (vs r1885)
Quoted 4 lines · Colin D Bennett
Clean patch against trunk SVN revision 1885.
Regards,
Colin
Thanks for the re-base.
In your opinion how should rendering of double buffered screen be different from single buffered?
Eg. who is responsible to handle those differences?
Thanks,
Vesa Jääskeläinen
Re: [PATCH] GSoC #07 VBE double buffering (vs r1885)
Quoted 8 lines · On Sun, 05 Oct 2008 11:52:08 +0300 Vesa J____skel__inen <[email protected]> wrote:
Quoted 4 lines · Colin D Bennett
Clean patch against trunk SVN revision 1885.
Regards,
ColinThanks for the re-base.
Quoted 7 lines
In your opinion how should rendering of double buffered screen be different from single buffered?
Eg. who is responsible to handle those differences?
Thanks,
VesaJ__skel_inen
Generally, the client code should (IMO) do the following, which will work for both a double-buffered and a non-double-buffered video mode:
(by 'client', I mean the code that is using the video API)
// Render the graphical elements to the back buffer. grub_video_fill_rect (...); grub_video_draw_string (...); grub_video_blit_bitmap (...);
// Make the back buffer contents visible.
grub_video_swap_buffers (); // NOP in single buffered mode
For double buffered mode, this properly renders the graphics using double buffering. For non double buffered mode, the "back buffer" and the "front buffer" are one and the same, and the 'swap_buffers' operation does nothing.
I think the main difference between rendering to a single buffered versus a double buffered screen is the fact that when rendering using single buffering, the client code can update only the changed parts of the screen, but for double buffering it must update the whole screen.
In single buffered mode, you can incrementally modify the video memory contents based on the last rendered frame. However, in double buffered mode the last rendered frame might not be in the back buffer after calling swap_buffers, depending on the double buffering strategy selected at runtime:
1. when page flipping is in use, the back buffer will contain the contents of the screen before the *prior* call to swap_buffers.
2. when the back buffer is in main memory (the blit strategy), the back buffer will actually retain its contents after swap_buffers, since the buffers cannot actually be swapped (thus perhaps the 'swap_buffers' name is not the most accurate description of the essence of this function, but it gets the general message across).
In the gfxmenu code, I decided that, at least to start with, to always render complete frames on the screen. In this way, the code functions properly whether or not double buffering is in use, and it is kept simple. This worked well for the menu screen, and has good performance in my tests even on my 1 GHz VIA C3 machine. I figure that it's more important to get it working properly, and then optimize the performance later where it might be needed.
The main current performance problem lies in the way that the gfxterm works when embedded in the double buffered gfxmenu screen. It is causing a full screen redraw every time a character or a string is changed on the terminal. I've thought about this a lot in the past and I don't have a simple answer, though I have a lot of ideas (switch to single buffering temporarily (--), pre-render a bitmap of the rest of the screen (-), coalesce updates to the gfxterm (++), ...).
Regards,
Colin