From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with archive (Exim 4.43) id 1KmLTQ-0006QK-CX for mharc-grub-devel@gnu.org; Sun, 05 Oct 2008 00:44:04 -0400 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1KmLTO-0006Q6-Cx for grub-devel@gnu.org; Sun, 05 Oct 2008 00:44:02 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1KmLTL-0006Pm-T5 for grub-devel@gnu.org; Sun, 05 Oct 2008 00:44:00 -0400 Received: from [199.232.76.173] (port=46420 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1KmLTL-0006Pj-PI for grub-devel@gnu.org; Sun, 05 Oct 2008 00:43:59 -0400 Received: from gateway02.websitewelcome.com ([69.93.106.20]:36156) by monty-python.gnu.org with smtp (Exim 4.60) (envelope-from ) id 1KmLTL-0003iz-M4 for grub-devel@gnu.org; Sun, 05 Oct 2008 00:44:00 -0400 Received: (qmail 8141 invoked from network); 5 Oct 2008 05:00:07 -0000 Received: from gator297.hostgator.com (74.53.228.114) by gateway02.websitewelcome.com with SMTP; 5 Oct 2008 05:00:07 -0000 Received: from c-67-185-142-228.hsd1.wa.comcast.net ([67.185.142.228]:55376 helo=localhost) by gator297.hostgator.com with esmtpsa (TLSv1:AES128-SHA:128) (Exim 4.68) (envelope-from ) id 1KmLT9-0000wi-Pk for grub-devel@gnu.org; Sat, 04 Oct 2008 23:43:47 -0500 Date: Sat, 4 Oct 2008 21:43:28 -0700 From: Colin D Bennett To: grub-devel@gnu.org Message-ID: <20081004214328.57e8f709@gibibit.com> In-Reply-To: <20080830235833.3b29b3c2@gamma.lan> References: <20080830235833.3b29b3c2@gamma.lan> X-Mailer: Claws Mail 3.5.0 (GTK+ 2.12.11; i686-pc-linux-gnu) Mime-Version: 1.0 Content-Type: multipart/signed; boundary="Sig_/nrMENW07vs4KfPu.wmdROvh"; protocol="application/pgp-signature"; micalg=PGP-SHA1 X-AntiAbuse: This header was added to track abuse, please include it with any abuse report X-AntiAbuse: Primary Hostname - gator297.hostgator.com X-AntiAbuse: Original Domain - gnu.org X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12] X-AntiAbuse: Sender Address Domain - gibibit.com X-detected-operating-system: by monty-python.gnu.org: GNU/Linux 2.6 (newer, 3) Subject: [PATCH] GSoC #07 VBE double buffering (vs r1885) X-BeenThere: grub-devel@gnu.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: The development of GRUB 2 List-Id: The development of GRUB 2 List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 05 Oct 2008 04:44:03 -0000 --Sig_/nrMENW07vs4KfPu.wmdROvh Content-Type: multipart/mixed; boundary="MP_/GJ8HTpPRlXAP5VqtFbwynbV" --MP_/GJ8HTpPRlXAP5VqtFbwynbV Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: quoted-printable Content-Disposition: inline Clean patch against trunk SVN revision 1885. Regards, Colin --MP_/GJ8HTpPRlXAP5VqtFbwynbV Content-Type: text/x-patch; name=07_vbe-doublebuf_r1885.patch Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename=07_vbe-doublebuf_r1885.patch =3D=3D=3D modified file 'include/grub/video.h' --- include/grub/video.h 2008-09-07 14:55:58 +0000 +++ include/grub/video.h 2008-10-05 04:29:17 +0000 @@ -47,10 +47,10 @@ #define GRUB_VIDEO_MODE_TYPE_DEPTH_MASK 0x0000ff00 #define GRUB_VIDEO_MODE_TYPE_DEPTH_POS 8 =20 -/* 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_t= arget *) 0) -#define GRUB_VIDEO_RENDER_TARGET_BACK_BUFFER ((struct grub_video_render_ta= rget *) 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) =20 /* Defined blitting formats. */ enum grub_video_blit_format =3D=3D=3D modified file 'video/i386/pc/vbe.c' --- video/i386/pc/vbe.c 2008-09-07 14:55:58 +0000 +++ video/i386/pc/vbe.c 2008-10-05 04:29:17 +0000 @@ -63,6 +63,7 @@ static struct { struct grub_video_render_target render_target; + int is_double_buffered; /* Is the video mode double buffered? */ =20 unsigned int bytes_per_scan_line; unsigned int bytes_per_pixel; @@ -77,6 +78,24 @@ static grub_uint32_t mode_in_use =3D 0x55aa; static grub_uint16_t *mode_list; =20 +static struct=20 +{ + 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) { @@ -376,6 +395,7 @@ /* Reset frame buffer and render target variables. */ grub_memset (&framebuffer, 0, sizeof(framebuffer)); render_target =3D &framebuffer.render_target; + grub_memset (&doublebuf_state, 0, sizeof(doublebuf_state)); =20 return GRUB_ERR_NONE; } @@ -391,6 +411,9 @@ /* TODO: Decide, is this something we want to do. */ return grub_errno; =20 + if (doublebuf_state.destroy) + doublebuf_state.destroy(); + /* TODO: Free any resources allocated by driver. */ grub_free (mode_list); mode_list =3D 0; @@ -533,9 +556,12 @@ render_target->viewport.width =3D active_mode_info.x_resolution; render_target->viewport.height =3D active_mode_info.y_resolution; =20 - /* Set framebuffer pointer and mark it as non allocated. */ + /* Mark framebuffer memory as non allocated. */ render_target->is_allocated =3D 0; - render_target->data =3D framebuffer.ptr; + /* Set up double buffering information. */ + framebuffer.is_double_buffered =3D + ((mode_type & GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED) !=3D 0); + double_buffering_init (); =20 /* Copy default palette to initialize emulated palette. */ for (i =3D 0; @@ -556,6 +582,166 @@ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no matching mode found."); } =20 +/*=20 + Set framebuffer render target page and display the proper page, based on + `doublebuf_state.render_page' and `doublebuf_state.displayed_page', + respectively.=20 + + Returns 0 upon success, nonzero upon failure. + */ +static int +doublebuf_pageflipping_commit (void) +{ + /* Set the render target's data pointer to the start of the render_page.= */ + framebuffer.render_target.data =3D + ((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 =3D + framebuffer.render_target.mode_info.height=20 + * doublebuf_state.displayed_page; +=20 + grub_vbe_status_t vbe_err =3D=20 + grub_vbe_bios_set_display_start (0, display_start_line); + if (vbe_err !=3D GRUB_VBE_STATUS_OK) + return 1; + + return 0; +} + +static int +doublebuf_pageflipping_update_screen (void) +{ + /* Swap the page numbers in the framebuffer struct. */ + int new_displayed_page =3D doublebuf_state.render_page; + doublebuf_state.render_page =3D doublebuf_state.displayed_page; + doublebuf_state.displayed_page =3D new_displayed_page; + + return doublebuf_pageflipping_commit (); +} + +static int +doublebuf_pageflipping_destroy (void) +{ + doublebuf_state.update_screen =3D 0; + doublebuf_state.destroy =3D 0; + return 0; +} + +static int +doublebuf_pageflipping_init (void) +{ + doublebuf_state.page_size =3D + framebuffer.bytes_per_scan_line * render_target->mode_info.height; + =20 + /* Get video RAM size in bytes. */ + grub_size_t vram_size =3D controller_info.total_memory << 16; + + if (2 * doublebuf_state.page_size > vram_size) + return 1; /* Not enough video memory for 2 pages. */ + + doublebuf_state.displayed_page =3D 0; + doublebuf_state.render_page =3D 1; + + doublebuf_state.update_screen =3D doublebuf_pageflipping_update_screen; + doublebuf_state.destroy =3D doublebuf_pageflipping_destroy; + + /* Set the framebuffer memory data pointer and display the right page. */ + if (doublebuf_pageflipping_commit () !=3D GRUB_ERR_NONE) + return 1; /* Unable to set the display start. */ + + framebuffer.render_target.mode_info.mode_type + |=3D GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED; + return 0; +} + +static int +doublebuf_blit_update_screen (void) +{ + grub_memcpy (framebuffer.ptr, + doublebuf_state.offscreen_buffer,=20 + doublebuf_state.page_size); + return 0; +} + +static int +doublebuf_blit_destroy (void) +{ + grub_free (doublebuf_state.offscreen_buffer); + doublebuf_state.offscreen_buffer =3D 0; + + doublebuf_state.update_screen =3D 0; + doublebuf_state.destroy =3D 0; + return 0; +} + +static int +doublebuf_blit_init (void) +{ + doublebuf_state.page_size =3D + framebuffer.bytes_per_scan_line * render_target->mode_info.height; + + doublebuf_state.offscreen_buffer =3D (grub_uint8_t *) + grub_malloc (doublebuf_state.page_size); + if (doublebuf_state.offscreen_buffer =3D=3D 0) + return 1; /* Error. */ + + framebuffer.render_target.data =3D doublebuf_state.offscreen_buffer; + doublebuf_state.update_screen =3D doublebuf_blit_update_screen; + doublebuf_state.destroy =3D doublebuf_blit_destroy; + + framebuffer.render_target.mode_info.mode_type + |=3D 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 =3D 0; + doublebuf_state.destroy =3D 0; + return 0; +} + +static int +doublebuf_null_init (void) +{ + framebuffer.render_target.data =3D framebuffer.ptr; + doublebuf_state.update_screen =3D doublebuf_null_update_screen; + doublebuf_state.destroy =3D doublebuf_null_destroy; + + framebuffer.render_target.mode_info.mode_type + &=3D ~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 () =3D=3D 0) + return; + + if (doublebuf_blit_init () =3D=3D 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) { @@ -1475,7 +1661,10 @@ static grub_err_t grub_video_vbe_swap_buffers (void) { - /* TODO: Implement buffer swapping. */ + if (doublebuf_state.update_screen () !=3D 0) + return grub_error (GRUB_ERR_INVALID_COMMAND, + "Double buffer update failed"); + return GRUB_ERR_NONE; } =20 @@ -1574,17 +1763,13 @@ static grub_err_t grub_video_vbe_set_active_render_target (struct grub_video_render_target *= target) { - if (target =3D=3D GRUB_VIDEO_RENDER_TARGET_FRONT_BUFFER) + if (target =3D=3D GRUB_VIDEO_RENDER_TARGET_DISPLAY) { render_target =3D &framebuffer.render_target; =20 return GRUB_ERR_NONE; } =20 - if (target =3D=3D 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."); --MP_/GJ8HTpPRlXAP5VqtFbwynbV-- --Sig_/nrMENW07vs4KfPu.wmdROvh Content-Type: application/pgp-signature; name=signature.asc Content-Disposition: attachment; filename=signature.asc -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.9 (GNU/Linux) iEYEARECAAYFAkjoRfMACgkQokx8fzcGbYfxgwCdHVX9WAKRtqmSZ3LfBe5kk4W9 9hgAn07Z2Dxzy0xnptBbkoCDw56VMXnj =J8pq -----END PGP SIGNATURE----- --Sig_/nrMENW07vs4KfPu.wmdROvh--