From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with archive (Exim 4.43) id 1LTMih-0007Ej-OZ for mharc-grub-devel@gnu.org; Sat, 31 Jan 2009 15:45:39 -0500 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1LTMig-0007ER-0Q for grub-devel@gnu.org; Sat, 31 Jan 2009 15:45:38 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1LTMie-0007EB-3U for grub-devel@gnu.org; Sat, 31 Jan 2009 15:45:37 -0500 Received: from [199.232.76.173] (port=45790 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1LTMid-0007E6-To for grub-devel@gnu.org; Sat, 31 Jan 2009 15:45:35 -0500 Received: from gateway07.websitewelcome.com ([67.18.81.23]:54116) by monty-python.gnu.org with smtp (Exim 4.60) (envelope-from ) id 1LTMic-0001iB-RG for grub-devel@gnu.org; Sat, 31 Jan 2009 15:45:35 -0500 Received: (qmail 18147 invoked from network); 31 Jan 2009 21:04:22 -0000 Received: from gator297.hostgator.com (74.53.228.114) by gateway07.websitewelcome.com with SMTP; 31 Jan 2009 21:04:22 -0000 Received: from [67.185.177.95] (port=53311 helo=localhost) by gator297.hostgator.com with esmtpsa (TLSv1:AES128-SHA:128) (Exim 4.69) (envelope-from ) id 1LTMiT-0002oA-Q6 for grub-devel@gnu.org; Sat, 31 Jan 2009 14:45:26 -0600 Date: Sat, 31 Jan 2009 12:45:26 -0800 From: Colin D Bennett To: The development of GRUB 2 Message-ID: <20090131124526.2a2c1bd6@gibibit.com> X-Mailer: Claws Mail 3.7.0 (GTK+ 2.14.7; i686-pc-linux-gnu) Mime-Version: 1.0 Content-Type: multipart/signed; boundary="Sig_/38q.+hnGers4YI.VG4hKnzA"; 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] 4/5 Videotest enhancements 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: Sat, 31 Jan 2009 20:45:38 -0000 --Sig_/38q.+hnGers4YI.VG4hKnzA Content-Type: multipart/mixed; boundary="MP_/ubbpVz//wlDqZrrt=+Cc3eP" --MP_/ubbpVz//wlDqZrrt=+Cc3eP Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: quoted-printable Content-Disposition: inline This patch improves the videotest command by adding a number of different tests for particular features. The 'videotest text' test tests the rendering of Unicode UTF-8 text, for instance, and the 'videotest bench' command runs a video performance benchmark. The original videotest command is accessed by executing 'videotest basic'. The patch also adds the type 'grub_rect_t', which simply defines a rectangle and is required for the graphical menu patch. The patch is against GRUB trunk revision 1964. Regards, Colin --MP_/ubbpVz//wlDqZrrt=+Cc3eP Content-Type: text/x-patch Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename=04_videotest.patch =3D=3D=3D modified file 'commands/videotest.c' --- commands/videotest.c 2009-01-05 23:01:00 +0000 +++ commands/videotest.c 2009-01-31 20:42:48 +0000 @@ -16,6 +16,7 @@ * along with GRUB. If not, see . */ =20 +#include #include #include #include @@ -25,31 +26,59 @@ #include #include #include - -static grub_err_t -grub_cmd_videotest (struct grub_arg_list *state __attribute__ ((unused)), - int argc __attribute__ ((unused)), - char **args __attribute__ ((unused))) -{ +#include +#include +#include /* to test grub_vbe_bios_set_display_start= */ + +/* Option array indices. */ +#define ARGINDEX_TEST_TIME 0 +#define ARGINDEX_DOUBLE_BUF 1 + +static const struct grub_arg_option arg_options[] =3D { + {"time", 't', 0, "Time to run each test, in seconds.", 0, ARG_TYPE_INT}, + {"dbuf", 'd', 0, "Use double buffered graphics.", 0, ARG_TYPE_NONE}, + {0, 0, 0, 0, 0, 0} +}; + +#define DEFAULT_TEST_TIME 5 + +/* Command options -- populated base on command line arguments. */ +struct videotest_options +{ + int test_time; + int double_buffering; +}; + + +static void +basic_video_test (struct videotest_options *vt_opts) +{ + int mode_type =3D GRUB_VIDEO_MODE_TYPE_INDEX_COLOR; + if (vt_opts->double_buffering) + mode_type |=3D GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED; if (grub_video_setup (1024, 768, GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) !=3D GRUB_ERR_NO= NE) - return grub_errno; + return; =20 grub_video_color_t color; + grub_video_color_t bg; unsigned int x; unsigned int y; unsigned int width; unsigned int height; int i; - grub_font_t sansbig; - grub_font_t sans; - grub_font_t sanssmall; - grub_font_t fixed; struct grub_font_glyph *glyph; struct grub_video_render_target *text_layer; + grub_font_t fixed; grub_video_color_t palette[16]; - const char *str; - int texty; + int info_width; + int info_height; + + if (! (fixed =3D grub_font_get ("Fixed 20"))) + { + grub_error (GRUB_ERR_BAD_FONT, "No font loaded."); + return; + } =20 grub_video_get_viewport (&x, &y, &width, &height); =20 @@ -59,7 +88,11 @@ =20 grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY); =20 + info_width =3D 500; + info_height =3D 100; + color =3D grub_video_map_rgb (0, 0, 0); + bg =3D color; grub_video_fill_rect (color, 0, 0, width, height); =20 color =3D grub_video_map_rgb (255, 0, 0); @@ -68,13 +101,6 @@ color =3D grub_video_map_rgb (0, 255, 255); grub_video_fill_rect (color, 100, 100, 100, 100); =20 - sansbig =3D grub_font_get ("Helvetica Bold 24"); - sans =3D grub_font_get ("Helvetica Bold 14"); - sanssmall =3D grub_font_get ("Helvetica 8"); - fixed =3D grub_font_get ("Fixed 20"); - if (! sansbig || ! sans || ! sanssmall || ! fixed) - return grub_error (GRUB_ERR_BAD_FONT, "No font loaded."); - glyph =3D grub_font_get_glyph (fixed, '*'); grub_font_draw_glyph (glyph, color, 200 ,0); =20 @@ -85,17 +111,920 @@ =20 grub_video_set_active_render_target (text_layer); =20 - color =3D grub_video_map_rgb (255, 255, 255); - - texty =3D 32; - grub_font_draw_string ("The quick brown fox jumped over the lazy dog.", - sans, color, 16, texty); - texty +=3D grub_font_get_descent (sans) + grub_font_get_leading (sans); - - texty +=3D grub_font_get_ascent (fixed); - grub_font_draw_string ("The quick brown fox jumped over the lazy dog.", - fixed, color, 16, texty); - texty +=3D grub_font_get_descent (fixed) + grub_font_get_leading (fixed); + color =3D grub_video_map_rgb (255, 255, 0); + grub_font_draw_string ("ABCDEFG", fixed, color, 16, 100); + color =3D grub_video_map_rgb (128, 128, 255); + grub_font_draw_string ("The quick brown fox jumped over the lazy dog.", + fixed, color, 16, 150); + + color =3D grub_video_map_rgb (255, 255, 255); + glyph =3D grub_font_get_glyph (fixed, '*'); + + for (i =3D 0; i < 16; i++) + { + color =3D grub_video_map_color (i); + palette[i] =3D color; + grub_font_draw_glyph (glyph, color, 16 + i * 16, 220); + } + + grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY); + + for (i =3D 0; i < 255; i++) + { + color =3D grub_video_map_rgb (i, 33, 77); + grub_video_fill_rect (color, 0, 0, width, height); + grub_video_blit_render_target (text_layer, GRUB_VIDEO_BLIT_BLEND, 0,= 0, + 0, 0, width, height); + } + + color =3D grub_video_map_rgb (255, 255, 0); + grub_font_draw_string ("Press a key to continue.", fixed, color, 10, 60); + grub_video_swap_buffers (); + grub_getkey (); + grub_video_fill_rect (bg, 0, 0, info_width, info_height); /* Clear info= . */ + + /* Test VBE set display start address. */ + /* This should scroll the screen, first vertically, + * then horizontally. The horizontal scrolling seems to + * only have a resolution of about 16 pixels on my VIA Mini-ITX. */ + grub_font_draw_string ("Testing VBE 'Set display start' operation " + "for horizontal scrolling...", + fixed, color, 10, 20); + grub_video_swap_buffers (); + int vbestatus; + int vbeok =3D 0; + int vbeerr =3D 0; + for (i =3D 0; i < 50; i++) + { + vbestatus =3D grub_vbe_bios_set_display_start (0, i); + if (vbestatus =3D=3D GRUB_VBE_STATUS_OK) + vbeok++; + else + vbeerr++; + } + + grub_font_draw_string ("Press a key to continue.", fixed, color, 10, 60); + grub_video_swap_buffers (); + grub_getkey (); + grub_video_fill_rect (bg, 0, 0, info_width, info_height); /* Clear info= . */ + grub_video_swap_buffers (); + + grub_font_draw_string ("Testing VBE 'Set display start' operation " + "for vertical scrolling...", + fixed, color, 10, 40); + grub_video_swap_buffers (); + for (i =3D 0; i < 50; i++) + { + vbestatus =3D grub_vbe_bios_set_display_start (i, 50); + if (vbestatus =3D=3D GRUB_VBE_STATUS_OK) + vbeok++; + else + vbeerr++; + } + + grub_font_draw_string ("Press a key to continue.", fixed, color, 10, 60); + grub_video_swap_buffers (); + grub_getkey (); + grub_video_fill_rect (bg, 0, 0, info_width, info_height); /* Clear info= . */ + grub_video_swap_buffers (); + + grub_video_delete_render_target (text_layer); + grub_video_restore (); + + grub_printf ("VBE set_display_start status: %d\n", vbestatus); + grub_printf ("ok: %d\n", vbeok); + grub_printf ("errors: %d\n", vbeerr); + + grub_errno =3D GRUB_ERR_NONE; +} +=0C + + +/** + * Simple opaque image blit test. + * Returns the error status in grub_errno. + */ +static void +bitmap_demo (struct videotest_options *vt_opts) +{ + int mode_type =3D GRUB_VIDEO_MODE_TYPE_RGB; + if (vt_opts->double_buffering) + mode_type |=3D GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED; + if (grub_video_setup (1024, 768, mode_type) !=3D GRUB_ERR_NONE) + return; + + grub_video_rect_t view; + grub_video_get_viewport ((unsigned *) &view.x, (unsigned *) &view.y, + (unsigned *) &view.width, + (unsigned *) &view.height); + + grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY); + const int bm1width =3D 500, bm1height =3D 400; + struct grub_video_bitmap *bitmap1; + + if (grub_video_bitmap_create (&bitmap1, bm1width, bm1height, + GRUB_VIDEO_BLIT_FORMAT_RGB_888) + !=3D GRUB_ERR_NONE) + return; + + int offset =3D 0; + int x; + int y; + grub_uint8_t *data =3D grub_video_bitmap_get_data (bitmap1); + for (y =3D 0; y < bm1height; y++) + { + for (x =3D 0; x < bm1width; x++) + { + data[offset++] =3D x ^ y; /* red */ + data[offset++] =3D (x * 3) ^ (y * 3); /* green */ + data[offset++] =3D (x * 2) ^ (y * 2); /* blue */ + } + } + + /* Blit the entire bitmap in the center of the screen. */ + grub_video_blit_bitmap (bitmap1, + GRUB_VIDEO_BLIT_REPLACE, + view.x + (view.width - bm1width) / 2, + view.y + (view.height - bm1height) / 2, + 0, 0, bm1width, bm1height); + grub_video_swap_buffers (); + grub_getkey (); + + /* Blit more copies of the bitmap. */ + /* Upper left. */ + grub_video_blit_bitmap (bitmap1, GRUB_VIDEO_BLIT_REPLACE, + view.x, view.y, 0, 0, bm1width, bm1height); + /* Upper right. */ + grub_video_blit_bitmap (bitmap1, + GRUB_VIDEO_BLIT_REPLACE, + view.x + view.width - bm1width, + view.y, 0, 0, bm1width, bm1height); + /* Lower left. */ + grub_video_blit_bitmap (bitmap1, + GRUB_VIDEO_BLIT_REPLACE, + view.x, + view.y + view.height - bm1height, + 0, 0, bm1width, bm1height); + /* Lower right. */ + grub_video_blit_bitmap (bitmap1, + GRUB_VIDEO_BLIT_REPLACE, + view.x + view.width - bm1width, + view.y + view.height - bm1height, + 0, 0, bm1width, bm1height); + grub_video_swap_buffers (); + grub_getkey (); + + int clearbg =3D 0; /* Boolean flag: whether to fill backgro= und. */ + grub_video_color_t bgcolor =3D grub_video_map_rgb (16, 16, 96); + + /* Animate the image sliding in. End when a key is pressed. */ + int vscale =3D 1000; + int velocityx =3D -5000; + int velocityy =3D -8000; + int positionx =3D 100; + int positiony =3D 300; + + grub_uint32_t frame_count =3D 0; + grub_uint32_t start_time =3D grub_get_time_ms (); + + while (grub_checkkey () =3D=3D -1) + { + /* If the time limit option is set, then check if it's exceeded. */ + if (vt_opts->test_time !=3D 0 + && grub_get_time_ms () >=3D start_time + vt_opts->test_time * 10= 00) + break; + + int newx =3D positionx + velocityx / vscale; + int newy =3D positiony + velocityy / vscale; + + /* Check collision w/ left */ + if (newx < view.x && velocityx < 0) + { + velocityx =3D -velocityx; + newx =3D positionx + velocityx / vscale; + } + /* Check collision w/ right */ + if (newx + bm1width > view.x + view.width && velocityx > 0) + { + velocityx =3D -velocityx; + newx =3D positionx + velocityx / vscale; + } + /* Check collision w/ top */ + if (newy < 0 && velocityy < 0) + { + velocityy =3D -velocityy; + newy =3D positiony + velocityy / vscale; + } + /* Check collision w/ bottom */ + if (newy + bm1height > view.y + view.height && velocityy > 0) + { + velocityy =3D -velocityy; + newy =3D positiony + velocityy / vscale; + } + + positionx =3D newx; + positiony =3D newy; + + if (clearbg) + grub_video_fill_rect (bgcolor, view.x, view.y, view.width, + view.height); + + grub_video_blit_bitmap (bitmap1, + GRUB_VIDEO_BLIT_REPLACE, + view.x + positionx, + view.y + positiony, 0, 0, bm1width, bm1heigh= t); + grub_video_swap_buffers (); + frame_count++; + + /* Acceleration due to gravity... + * note that the y coordinate is increasing downward. */ + velocityy +=3D vscale / 7; + } + + /* Calculate average frame rate. */ + grub_uint32_t duration =3D grub_get_time_ms () - start_time; + grub_uint32_t fps_x10 =3D 10 * 1000 * frame_count / duration; + + /* Eat the keystroke. */ + if (grub_checkkey () !=3D -1) + grub_getkey (); + + grub_video_bitmap_destroy (bitmap1); + grub_video_restore (); + + grub_printf ("Average frame rate: %d.%d fps\n", fps_x10 / 10, fps_x10 % = 10); + + grub_errno =3D GRUB_ERR_NONE; +} +=0C + + +/* Configuration settings for a benchmark run. */ +struct benchmark_config +{ + int width; + int height; + unsigned int mode_type; + int use_rgba_bitmaps; +}; + +/* Macro to make the benchmark_configs[] declaration more concise. */ +#define MODE_TYPE_RGB(bpp) (GRUB_VIDEO_MODE_TYPE_RGB \ + | ((bpp) << GRUB_VIDEO_MODE_TYPE_DEPTH_POS)) + +/* The video configurations to use for the benchmark. */ +static struct benchmark_config benchmark_configs[] =3D { + {320, 200, MODE_TYPE_RGB (0), 0}, + {640, 480, MODE_TYPE_RGB (0), 0}, + {1024, 768, MODE_TYPE_RGB (0), 0}, + {1024, 768, MODE_TYPE_RGB (0), 1}, +}; + +#define NUM_BENCHMARK_CONFIGS (sizeof(benchmark_configs) \ + / sizeof(benchmark_configs[0])) + +struct benchmark_result +{ + /* If set to 1, the test was able to run successfully; + * 0 means there was an error. */ + int test_passed; + + /* Bits per pixel for the video mode used. */ + int bpp; + + /* All fps are in fps * 10 to achieve one decimal place. */ + /* Set to 0 to indicate the test could not be run. */ + grub_int32_t fill_fps; + grub_int32_t blit_fps; + grub_int32_t blend_fps; +}; + +#define BENCHMARK_RESULT_FPS_SCALE 10 + +static void +move_rectangle_one_step (int *x, int *y, + int width, int height, + int *vx, int *vy, const grub_video_rect_t * bound= s) +{ + int newx =3D *x + *vx; + int newy =3D *y + *vy; + + /* Check collision w/ left */ + if (newx < bounds->x && *vx < 0) + { + *vx =3D -*vx; + newx =3D *x + *vx; + } + /* Check collision w/ right */ + if (newx + width > bounds->x + bounds->width && *vx > 0) + { + *vx =3D -*vx; + newx =3D *x + *vx; + } + /* Check collision w/ top */ + if (newy < 0 && *vy < 0) + { + *vy =3D -*vy; + newy =3D *y + *vy; + } + /* Check collision w/ bottom */ + if (newy + height > bounds->y + bounds->height && *vy > 0) + { + *vy =3D -*vy; + newy =3D *y + *vy; + } + + *x =3D newx; + *y =3D newy; +} + +/** + * Run the benchmark test for a particular video mode, which is specified + * by ``*config``. The results of the test are stored in ``*result``. + */ +static void +do_benchmark (const struct benchmark_config *config, + struct benchmark_result *result, + struct videotest_options *vt_opts) +{ + struct grub_video_mode_info modeinfo; + + result->test_passed =3D 0; + result->fill_fps =3D 0; + result->blit_fps =3D 0; + result->blend_fps =3D 0; + result->bpp =3D 0; + + int mode_type =3D config->mode_type; + if (vt_opts->double_buffering) + mode_type |=3D GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED; + if (grub_video_setup (config->width, config->height, + mode_type) !=3D GRUB_ERR_NONE) + return; + + if (grub_video_get_info (&modeinfo) =3D=3D GRUB_ERR_NONE) + result->bpp =3D modeinfo.bpp; + + /* Full screen bitmap blit test. */ + + grub_video_rect_t view; + grub_video_get_viewport ((unsigned *) &view.x, (unsigned *) &view.y, + (unsigned *) &view.width, + (unsigned *) &view.height); + + grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY); + + + /* For measuring timing. */ + grub_uint32_t frame_count; + grub_uint64_t start_time; + grub_uint64_t desired_stop_time; + grub_uint32_t duration; + + + /*** FILL TEST ***/ + + /* Alternates between 0 and 1 to change the color. */ + int color_flag =3D 0; + grub_video_color_t fillcolors[2]; + fillcolors[0] =3D grub_video_map_rgb (0, 0, 255); + fillcolors[1] =3D grub_video_map_rgb (255, 255, 0); + + frame_count =3D 0; + start_time =3D grub_get_time_ms (); + desired_stop_time =3D start_time + vt_opts->test_time * 1000; + + while (grub_get_time_ms () < desired_stop_time && grub_checkkey () =3D= =3D -1) + { + grub_video_fill_rect (fillcolors[color_flag], + view.x, view.y, view.width, view.height); + grub_video_swap_buffers (); + color_flag ^=3D 1; + frame_count++; + } + if (grub_checkkey () !=3D -1) + grub_getkey (); /* Eat the keypress, if there was one. */ + + /* Calculate average frame rate. */ + duration =3D grub_get_time_ms () - start_time; + if (duration =3D=3D 0) + { + result->fill_fps =3D 0; + } + else + { + result->fill_fps =3D + (BENCHMARK_RESULT_FPS_SCALE * 1000 + * frame_count / duration); + } + + + /*** BLIT TEST ***/ + + /* Generate two bitmaps, the same size as the screen. */ + const int bitmapwidth =3D view.width, bitmapheight =3D view.height; + struct grub_video_bitmap *bitmap1; + struct grub_video_bitmap *bitmap2; + enum grub_video_blit_format bitmap_format =3D config->use_rgba_bitmaps + ? GRUB_VIDEO_BLIT_FORMAT_RGBA_8888 : GRUB_VIDEO_BLIT_FORMAT_RGB_888; + + if (grub_video_bitmap_create (&bitmap1, bitmapwidth, bitmapheight, + bitmap_format) !=3D GRUB_ERR_NONE) + return; + + if (grub_video_bitmap_create (&bitmap2, bitmapwidth, bitmapheight, + bitmap_format) !=3D GRUB_ERR_NONE) + { + grub_video_bitmap_destroy (bitmap1); + return; + } + + int offset; + int x; + int y; + grub_uint8_t *data; + + offset =3D 0; + data =3D grub_video_bitmap_get_data (bitmap1); + for (y =3D 0; y < bitmapheight; y++) + { + for (x =3D 0; x < bitmapwidth; x++) + { + data[offset++] =3D x ^ y; /* red */ + data[offset++] =3D (x * 3) ^ (y * 3); /* green */ + data[offset++] =3D (x * 2) ^ (y * 2); /* blue */ + if (config->use_rgba_bitmaps) + data[offset++] =3D 255; + } + } + + offset =3D 0; + data =3D grub_video_bitmap_get_data (bitmap2); + for (y =3D 0; y < bitmapheight; y++) + { + for (x =3D 0; x < bitmapwidth; x++) + { + data[offset++] =3D x + y; /* red */ + data[offset++] =3D x * x + y * y; /* green */ + data[offset++] =3D x * x / 4 + y * y / 4; /* blue */ + if (config->use_rgba_bitmaps) + data[offset++] =3D 255; + } + } + + + /* Now do the blit test, alternating between the two bitmaps. */ + frame_count =3D 0; + start_time =3D grub_get_time_ms (); + desired_stop_time =3D start_time + vt_opts->test_time * 1000; + + int cur =3D 0; /* Which bitmap to draw this frame. */ + while (grub_get_time_ms () < desired_stop_time && grub_checkkey () =3D= =3D -1) + { + struct grub_video_bitmap *current_bitmap =3D cur =3D=3D 0 ? bitmap1 = : bitmap2; + grub_video_blit_bitmap (current_bitmap, + GRUB_VIDEO_BLIT_REPLACE, + view.x, view.y, 0, 0, bitmapwidth, + bitmapheight); + grub_video_swap_buffers (); + frame_count++; + cur ^=3D 1; + } + if (grub_checkkey () !=3D -1) + grub_getkey (); /* Eat the keypress, if there was once. */ + + /* Calculate average frame rate. */ + duration =3D grub_get_time_ms () - start_time; + if (duration =3D=3D 0) + { + result->blit_fps =3D 0; + } + else + { + result->blit_fps =3D + (BENCHMARK_RESULT_FPS_SCALE * 1000 + * frame_count / duration); + } + + grub_video_bitmap_destroy (bitmap2); + grub_video_bitmap_destroy (bitmap1); + + + + /*** BLEND TEST ***/ + + /* Generate two bitmaps, with alpha translucency. */ + const int bbw =3D view.width * 2 / 3; + const int bbh =3D view.height * 2 / 3; + + if (grub_video_bitmap_create (&bitmap1, bbw, bbh, + GRUB_VIDEO_BLIT_FORMAT_RGBA_8888) !=3D + GRUB_ERR_NONE) + return; + + if (grub_video_bitmap_create (&bitmap2, bbw, bbh, + GRUB_VIDEO_BLIT_FORMAT_RGBA_8888) !=3D + GRUB_ERR_NONE) + { + grub_video_bitmap_destroy (bitmap1); + return; + } + + offset =3D 0; + data =3D grub_video_bitmap_get_data (bitmap1); + for (y =3D 0; y < bbh; y++) + { + for (x =3D 0; x < bbw; x++) + { + /* Calculate a to be increasing away from the center. */ + int dx =3D 256 * (x - bbw / 2) / (bbw / 2); + int dy =3D 256 * (y - bbh / 2) / (bbh / 2); + int a =3D dx * dx + dy * dy; + /* range for a =3D 0 .. 2*(256^2) =3D 2*2^16 =3D 2^17 */ + a >>=3D 17 - 8; /* Make range 0..256. */ + if (a > 255) + a =3D 255; + + data[offset++] =3D x ^ y; /* red */ + data[offset++] =3D (x * 3) ^ (y * 3); /* green */ + data[offset++] =3D (x * 2) ^ (y * 2); /* blue */ + data[offset++] =3D 255 - a; + } + } + + offset =3D 0; + data =3D grub_video_bitmap_get_data (bitmap2); + for (y =3D 0; y < bbh; y++) + { + for (x =3D 0; x < bbw; x++) + { + data[offset++] =3D x + y; /* red */ + data[offset++] =3D x * x + y * y; /* green */ + data[offset++] =3D x * x / 4 + y * y / 4; /* blue */ + data[offset++] =3D 255; + } + } + + frame_count =3D 0; + start_time =3D grub_get_time_ms (); + desired_stop_time =3D start_time + vt_opts->test_time * 1000; + + + grub_video_color_t bgcolor =3D grub_video_map_rgb (80, 80, 80); + + /* Bitmap locations. */ + int b1x =3D 0; + int b1y =3D 0; + int b2x =3D view.width - bbw; + int b2y =3D 0; + /* Bitmap velocities. */ + int b1vx =3D 8; + int b1vy =3D 12; + int b2vx =3D -10; + int b2vy =3D 9; + + while (grub_get_time_ms () < desired_stop_time && grub_checkkey () =3D= =3D -1) + { + move_rectangle_one_step (&b1x, &b1y, bbw, bbh, &b1vx, &b1vy, &view); + move_rectangle_one_step (&b2x, &b2y, bbw, bbh, &b2vx, &b2vy, &view); + grub_video_fill_rect (bgcolor, view.x, view.y, view.width, view.heig= ht); + grub_video_blit_bitmap (bitmap2, + GRUB_VIDEO_BLIT_BLEND, + b2x, b2y, 0, 0, bbw, bbh); + grub_video_blit_bitmap (bitmap1, + GRUB_VIDEO_BLIT_BLEND, + b1x, b1y, 0, 0, bbw, bbh); + grub_video_swap_buffers (); + frame_count++; + cur ^=3D 1; + } + if (grub_checkkey () !=3D -1) + grub_getkey (); /* Eat the keypress, if there was once. */ + + /* Calculate average frame rate. */ + duration =3D grub_get_time_ms () - start_time; + if (duration =3D=3D 0) + { + result->blend_fps =3D 0; + } + else + { + result->blend_fps =3D + (BENCHMARK_RESULT_FPS_SCALE * 1000 + * frame_count / duration); + } + + grub_video_bitmap_destroy (bitmap2); + grub_video_bitmap_destroy (bitmap1); + + grub_video_restore (); + result->test_passed =3D 1; +} + +/** + * Run a benchmark test in a series of video modes. + * The results are reported in tabular form. This will be helpful to + * determine how effective various optimizations are. + */ +static void +benchmark_test (struct videotest_options *vt_opts) +{ + unsigned int i; + struct benchmark_result results[NUM_BENCHMARK_CONFIGS]; + + /* Set option default values. */ + if (vt_opts->test_time =3D=3D 0) + vt_opts->test_time =3D DEFAULT_TEST_TIME; + + /* Run benchmarks. */ + for (i =3D 0; i < NUM_BENCHMARK_CONFIGS; i++) + { + grub_error_push (); + do_benchmark (&benchmark_configs[i], &results[i], vt_opts); + } + + grub_print_error (); + + /* Display results. */ + grub_printf ("Benchmark results (in frames/s):\n"); + grub_printf ("(W=3DWidth, H=3DHeight, B=3DBits per pixel,\n" + " T=3DMode Type, A=3DBitmap Alpha)\n"); + grub_printf (" W H B T A FILL BLIT BLEND\n"); + for (i =3D 0; i < NUM_BENCHMARK_CONFIGS; i++) + { + struct benchmark_config *c =3D &benchmark_configs[i]; + struct benchmark_result *r =3D &results[i]; + + if (r->test_passed) + { + grub_printf ("%4dx%4d %2d %d %d: %4d.%d %4d.%d %4d.%d\n", + c->width, c->height, r->bpp, + c->mode_type & 0x0F, + c->use_rgba_bitmaps, + r->fill_fps / BENCHMARK_RESULT_FPS_SCALE, + r->fill_fps % BENCHMARK_RESULT_FPS_SCALE, + r->blit_fps / BENCHMARK_RESULT_FPS_SCALE, + r->blit_fps % BENCHMARK_RESULT_FPS_SCALE, + r->blend_fps / BENCHMARK_RESULT_FPS_SCALE, + r->blend_fps % BENCHMARK_RESULT_FPS_SCALE); + } + else + { + grub_printf ("%4dx%4d %2d %d Not supported.\n", + c->width, c->height, + ((c->mode_type & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK) + >> GRUB_VIDEO_MODE_TYPE_DEPTH_POS), + c->mode_type & 0x0F); + } + } + + grub_errno =3D GRUB_ERR_NONE; +} +=0C + +/** + * Test time functions. + */ +static void +clock_test (struct videotest_options *vt_opts) +{ + int mode_type =3D GRUB_VIDEO_MODE_TYPE_RGB; + if (vt_opts->double_buffering) + mode_type |=3D GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED; + if (grub_video_setup (640, 480, mode_type) !=3D GRUB_ERR_NONE) + return; + + grub_video_rect_t view; + grub_video_get_viewport ((unsigned *) &view.x, (unsigned *) &view.y, + (unsigned *) &view.width, + (unsigned *) &view.height); + + grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY); + + /* Draw a progress bar that animates in sync with time. */ + + grub_video_rect_t bar_frame; + bar_frame.width =3D view.width - 2 * view.width / 10; + bar_frame.height =3D view.height / 20; + bar_frame.x =3D view.x + view.width / 10; + bar_frame.y =3D view.y + view.height - bar_frame.height - view.height / = 10; + + grub_video_color_t bgcolor =3D grub_video_map_rgb (50, 50, 50); + grub_video_color_t framecolor =3D grub_video_map_rgb (255, 255, 255); + grub_video_color_t barbgcolor =3D grub_video_map_rgb (0, 0, 128); + grub_video_color_t barcolor =3D grub_video_map_rgb (100, 100, 255); + + grub_uint32_t frame_count; + grub_uint64_t start_time; + grub_uint64_t barstart; + grub_uint32_t barlength =3D 1000; + + grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY); + + frame_count =3D 0; + start_time =3D grub_get_time_ms (); + barstart =3D grub_get_time_ms (); + + while (grub_checkkey () =3D=3D -1) + { + grub_uint64_t now; + grub_uint32_t bartime; + now =3D grub_get_time_ms (); + /* If the time limit option is set, then check if it's exceeded. */ + if (vt_opts->test_time !=3D 0 + && now >=3D start_time + vt_opts->test_time * 1000) + break; + bartime =3D now - barstart; + if (bartime > barlength) + { + barstart =3D grub_get_time_ms (); /* Start over. */ + bartime =3D barlength; + } + + /* Clear screen. */ + grub_video_fill_rect (bgcolor, view.x, view.y, view.width, view.heig= ht); + + /* Border. */ + grub_video_fill_rect (framecolor, + bar_frame.x - 1, bar_frame.y - 1, + bar_frame.width + 2, bar_frame.height + 2); + + /* Bar background. */ + int barwidth =3D bar_frame.width * bartime / barlength; + grub_video_fill_rect (barbgcolor, bar_frame.x + barwidth, + bar_frame.y, bar_frame.width - barwidth, + bar_frame.height); + /* Bar foreground. */ + grub_video_fill_rect (barcolor, bar_frame.x, bar_frame.y, + barwidth, bar_frame.height); + grub_video_swap_buffers (); + frame_count++; + } + + grub_uint32_t duration =3D grub_get_time_ms () - start_time; + grub_uint32_t fps_x10 =3D 10 * 1000 * frame_count / duration; + + if (grub_checkkey () !=3D -1) + grub_getkey (); /* Eat the keypress, if there was one. */ + grub_video_restore (); + grub_printf ("Average frame rate: %d.%d fps\n", fps_x10 / 10, fps_x10 % = 10); +} +=0C + +/** + * Test double buffering. + */ +static void +doublebuf_test (struct videotest_options *vt_opts) +{ + int mode_type =3D GRUB_VIDEO_MODE_TYPE_RGB; + if (vt_opts->double_buffering) + mode_type |=3D GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED; + if (grub_video_setup (640, 480, mode_type) !=3D GRUB_ERR_NONE) + return; + + grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY); + + grub_video_color_t red =3D grub_video_map_rgb (255, 50, 50); + grub_video_color_t yellow =3D grub_video_map_rgb (255, 255, 0); + grub_video_color_t green =3D grub_video_map_rgb (20, 255, 20); + grub_video_color_t blue =3D grub_video_map_rgb (50, 50, 255); + grub_video_color_t black =3D grub_video_map_rgb (0, 0, 0); + grub_video_color_t bgcolor =3D grub_video_map_rgb (255, 255, 255); + + grub_video_fill_rect (bgcolor, 0, 0, 640, 480); + grub_video_fill_rect (red, 100, 100, 200, 200); + grub_video_swap_buffers (); + grub_getkey (); + + grub_video_fill_rect (bgcolor, 0, 0, 640, 480); + grub_video_fill_rect (yellow, 120, 120, 200, 200); + grub_video_swap_buffers (); + grub_getkey (); + + grub_video_fill_rect (bgcolor, 0, 0, 640, 480); + grub_video_fill_rect (green, 140, 140, 200, 200); + grub_video_swap_buffers (); + grub_getkey (); + + grub_video_fill_rect (bgcolor, 0, 0, 640, 480); + grub_video_fill_rect (blue, 160, 160, 200, 200); + grub_video_swap_buffers (); + grub_getkey (); + + grub_video_fill_rect (bgcolor, 0, 0, 640, 480); + grub_video_fill_rect (black, 180, 180, 200, 200); + grub_video_swap_buffers (); + grub_getkey (); + + grub_video_restore (); +} +=0C + +/** + * Test text rendering. + */ +static void +text_test (struct videotest_options *vt_opts) +{ + grub_video_color_t color; + const char *s; + int view_x; + int view_y; + int view_width; + int view_height; + int xpos; + int ypos; + int i; + grub_font_t font1; + grub_font_t font2; + grub_font_t font3; + grub_font_t sansbig; + grub_font_t sans; + grub_font_t sanssmall; + grub_font_t fixed; + + int mode_type =3D GRUB_VIDEO_MODE_TYPE_RGB; + if (vt_opts->double_buffering) + mode_type |=3D GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED; + if (grub_video_setup (1024, 768, mode_type) !=3D GRUB_ERR_NONE) + return; + + grub_video_get_viewport ((unsigned int *) &view_x, + (unsigned int *) &view_y, + (unsigned int *) &view_width, + (unsigned int *) &view_height); + grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY); + + if (!(font1 =3D grub_font_get ("New Century Schoolbook 24")) + || !(font2 =3D grub_font_get ("Helvetica Bold 14")) + || !(font3 =3D grub_font_get ("Helvetica 10")) + || !(sansbig =3D grub_font_get ("Helvetica Bold 24")) + || !(sans =3D grub_font_get ("Helvetica Bold 14")) + || !(sanssmall =3D grub_font_get ("Helvetica 8")) + || !(fixed =3D grub_font_get ("Fixed 20"))) + { + grub_video_restore (); + grub_error (GRUB_ERR_BAD_FONT, "No font loaded."); + return; + } + + color =3D grub_video_map_rgb (0, 0, 0); + grub_video_fill_rect (color, 0, 0, view_width, view_height); + + color =3D grub_video_map_rgb (255, 0, 0); + grub_video_fill_rect (color, 0, 0, 100, 100); + + color =3D grub_video_map_rgb (0, 255, 255); + grub_video_fill_rect (color, 100, 100, 100, 100); + + color =3D grub_video_map_rgb (255, 255, 255); + + xpos =3D 10; + ypos =3D 30; + s =3D "Hello, World!"; + for (i =3D 0; i < 24; i++) + { + if (xpos + grub_font_get_string_width (font1, s) >=3D view_width) + { + /* The string will wrap; go to the beginning of the next line. = */ + xpos =3D 10; + ypos +=3D (grub_font_get_descent (font1) + + grub_font_get_ascent (font1)); + } + grub_font_draw_string ("Hello, World!", + font1, grub_video_map_rgb (255, 255, 0), + xpos, ypos); + + xpos +=3D grub_font_get_string_width (font1, s); + } + + xpos =3D 240; + ypos =3D 280; + grub_font_draw_string (grub_font_get_name (font1), + font1, grub_video_map_rgb (255, 255, 255), + xpos, ypos); + ypos +=3D grub_font_get_descent (font1) + grub_font_get_ascent (font2) += 2; + grub_font_draw_string (grub_font_get_name (font2), + font2, grub_video_map_rgb (255, 255, 255), + xpos, ypos); + ypos +=3D grub_font_get_descent (font2) + grub_font_get_ascent (font3) += 2; + grub_font_draw_string (grub_font_get_name (font3), + font3, grub_video_map_rgb (255, 255, 255), + xpos, ypos); + + ypos +=3D 40; /* Spacing. */ + + grub_font_draw_string ("The quick brown fox jumped over the lazy dog.", + sans, color, view_x + 16, ypos); + ypos +=3D grub_font_get_descent (sans) + grub_font_get_leading (sans); + + ypos +=3D grub_font_get_ascent (fixed); + grub_font_draw_string ("The quick brown fox jumped over the lazy dog.", + fixed, color, 16, ypos); + ypos +=3D grub_font_get_descent (fixed) + grub_font_get_leading (fixed); + + ypos +=3D 40; /* Spacing. */ =20 /* To convert Unicode characters into UTF-8 for this test, the following command is useful: @@ -114,78 +1043,254 @@ U+2287 subset symbol E2 8A 87 U+211D set 'R' symbol (real numbers) E2 84 9D */ =20 - str =3D + s =3D "Unicode test: happy\xE2\x98\xBA \xC2\xA3 5.00" " \xC2\xA1\xCF\x84\xC3\xA4u! " " \xE2\x84\xA4\xE2\x8A\x87\xE2\x84\x9D"; color =3D grub_video_map_rgb (128, 128, 255); =20 /* All characters in the string exist in the 'Fixed 20' (10x20) font. */ - texty +=3D grub_font_get_ascent(fixed); - grub_font_draw_string (str, fixed, color, 16, texty); - texty +=3D grub_font_get_descent (fixed) + grub_font_get_leading (fixed); - - /* Some character don't exist in the Helvetica font, so the font engine - will fall back to using glyphs from another font that does contain th= em. - TODO The font engine should be smart about selecting a replacement fo= nt - and prioritize fonts with similar sizes. */ - - texty +=3D grub_font_get_ascent(sansbig); - grub_font_draw_string (str, sansbig, color, 16, texty); - texty +=3D grub_font_get_descent (sansbig) + grub_font_get_leading (sans= big); - - texty +=3D grub_font_get_ascent(sans); - grub_font_draw_string (str, sans, color, 16, texty); - texty +=3D grub_font_get_descent (sans) + grub_font_get_leading (sans); - - texty +=3D grub_font_get_ascent(sanssmall); - grub_font_draw_string (str, sanssmall, color, 16, texty); - texty +=3D (grub_font_get_descent (sanssmall) + ypos +=3D grub_font_get_ascent (fixed); + grub_font_draw_string (s, fixed, color, 16, ypos); + ypos +=3D grub_font_get_descent (fixed) + grub_font_get_leading (fixed); + + /* Some characters don't exist in the Helvetica font, so the font engine + may fall back to using glyphs from another font that has them. */ + + ypos +=3D grub_font_get_ascent (sansbig); + grub_font_draw_string (s, sansbig, color, 16, ypos); + ypos +=3D grub_font_get_descent (sansbig) + grub_font_get_leading (sansb= ig); + + ypos +=3D grub_font_get_ascent (sans); + grub_font_draw_string (s, sans, color, 16, ypos); + ypos +=3D grub_font_get_descent (sans) + grub_font_get_leading (sans); + + ypos +=3D grub_font_get_ascent (sanssmall); + grub_font_draw_string (s, sanssmall, color, 16, ypos); + ypos +=3D (grub_font_get_descent (sanssmall) + grub_font_get_leading (sanssmall)); =20 - glyph =3D grub_font_get_glyph (fixed, '*'); - - for (i =3D 0; i < 16; i++) - { - color =3D grub_video_map_color (i); - palette[i] =3D color; - grub_font_draw_glyph (glyph, color, 16 + i * 16, 220); - } + + grub_video_swap_buffers (); + grub_getkey (); + grub_video_restore (); + grub_errno =3D GRUB_ERR_NONE; +} +=0C + +/** + * Test bitmap scaling. + */ +static void +scale_test (struct videotest_options *vt_opts) +{ + int mode_type =3D GRUB_VIDEO_MODE_TYPE_RGB; + if (vt_opts->double_buffering) + mode_type |=3D GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED; + if (grub_video_setup (1024, 768, mode_type) !=3D GRUB_ERR_NONE) + return; + + grub_errno =3D GRUB_ERR_NONE; + grub_video_rect_t view; + grub_video_get_viewport ((unsigned *) &view.x, (unsigned *) &view.y, + (unsigned *) &view.width, + (unsigned *) &view.height); =20 grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY); =20 - for (i =3D 0; i < 255; i++) - { - color =3D grub_video_map_rgb (i, 33, 77); - grub_video_fill_rect (color, 0, 0, width, height); - grub_video_blit_render_target (text_layer, GRUB_VIDEO_BLIT_BLEND, 0,= 0, - 0, 0, width, height); - } - + grub_font_t font; + if (!(font =3D grub_font_get ("Helvetica 10"))) + { + grub_video_restore (); + grub_error (GRUB_ERR_BAD_FONT, "No font loaded."); + return; + } + + grub_video_color_t color; + + int text_y =3D 0; + int text_height =3D 25; + + color =3D grub_video_map_rgb (44, 44, 200); + grub_video_fill_rect (color, view.x, view.y, view.width, view.height); + color =3D grub_video_map_rgb (255, 255, 255); + + grub_font_draw_string ("Loading image", + font, color, 10, text_y +=3D text_height); + + enum grub_video_bitmap_scale_method scale_method =3D + GRUB_VIDEO_BITMAP_SCALE_METHOD_BEST; + const char *bitmap_name =3D "/boot/grub/themes/winter/without-leaves.png= "; + struct grub_video_bitmap *bitmap; + grub_video_bitmap_load (&bitmap, bitmap_name); + if (grub_errno !=3D GRUB_ERR_NONE) + { + grub_font_draw_string ("Error loading bitmap", + font, color, 10, text_y +=3D text_height); + } + else + { + grub_font_draw_string ("Original image", + font, color, 10, text_y +=3D text_height); + grub_video_blit_bitmap (bitmap, GRUB_VIDEO_BLIT_BLEND, + 400, text_y - 10, + 0, 0, grub_video_bitmap_get_width (bitmap), + grub_video_bitmap_get_height (bitmap)); + + struct grub_video_bitmap *bitmap2; + if (grub_video_bitmap_create_scaled (&bitmap2, 40, 40, + bitmap, + scale_method) + !=3D GRUB_ERR_NONE) + { + grub_font_draw_string ("Error scaling down bitmap", + font, color, 10, text_y +=3D text_height); + } + else + { + grub_font_draw_string ("Scaled down version", + font, color, 10, text_y +=3D text_height); + grub_video_blit_bitmap (bitmap2, GRUB_VIDEO_BLIT_BLEND, + 400, text_y + 100, + 0, 0, grub_video_bitmap_get_width (bitma= p2), + grub_video_bitmap_get_height (bitmap2)); + grub_video_bitmap_destroy (bitmap2); + } + + struct grub_video_bitmap *bitmap3; + if (grub_video_bitmap_create_scaled (&bitmap3, 500, 300, bitmap, + scale_method) + !=3D GRUB_ERR_NONE) + { + grub_font_draw_string ("Error scaling up bitmap", + font, color, 10, text_y +=3D text_height); + } + else + { + grub_font_draw_string ("Scaled up version", + font, color, 10, text_y +=3D text_height); + grub_video_blit_bitmap (bitmap3, GRUB_VIDEO_BLIT_BLEND, + 400, text_y + 50, + 0, 0, grub_video_bitmap_get_width (bitma= p3), + grub_video_bitmap_get_height (bitmap3)); + grub_video_bitmap_destroy (bitmap3); + } + } + + grub_video_swap_buffers (); grub_getkey (); - - grub_video_delete_render_target (text_layer); - + grub_video_bitmap_destroy (bitmap); grub_video_restore (); - - for (i =3D 0; i < 16; i++) - grub_printf("color %d: %08x\n", i, palette[i]); - - grub_errno =3D GRUB_ERR_NONE; +} +=0C + +/** Print a list of the available tests. */ +static void list_tests (void); + +/** + * Video test command. Takes an argument specifying the test to run. + */ +static grub_err_t +grub_cmd_videotest (struct grub_arg_list *state, int argc, char **args) +{ + int i; + struct videotest_options vt_opts; + /* Pointer to the test function. */ + void (*test_func) (struct videotest_options *) =3D NULL; + + vt_opts.test_time =3D + state[ARGINDEX_TEST_TIME].set + ? grub_strtoul (state[ARGINDEX_TEST_TIME].arg, 0, 0) : 0; + vt_opts.double_buffering =3D state[ARGINDEX_DOUBLE_BUF].set; + + /* Parse command line arguments to determine the test to run. */ + for (i =3D 0; i < argc; i++) + { + char *arg =3D args[i]; + if (grub_strcmp (arg, "list") =3D=3D 0) + { + list_tests (); + return GRUB_ERR_NONE; + } + else if (grub_strcmp (arg, "basic") =3D=3D 0) + { + test_func =3D basic_video_test; + } + else if (grub_strcmp (arg, "bench") =3D=3D 0) + { + test_func =3D benchmark_test; + } + else if (grub_strcmp (arg, "bitmaps") =3D=3D 0) + { + test_func =3D bitmap_demo; + } + else if (grub_strcmp (arg, "clock") =3D=3D 0) + { + test_func =3D clock_test; + } + else if (grub_strcmp (arg, "doublebuf") =3D=3D 0) + { + test_func =3D doublebuf_test; + } + else if (grub_strcmp (arg, "text") =3D=3D 0) + { + test_func =3D text_test; + } + else if (grub_strcmp (arg, "scale") =3D=3D 0) + { + test_func =3D scale_test; + } + else + { + grub_printf ("Error: Unknown test `%s'\n", arg); + grub_errno =3D GRUB_ERR_BAD_ARGUMENT; + return grub_errno; + } + } + + if (test_func =3D=3D NULL) + { + grub_printf ("Usage: videotest TESTNAME Run a test.\n"); + grub_printf (" videotest list List available tests.\n"); + grub_printf ("\n"); + list_tests (); + } + else + { + test_func (&vt_opts); + } + return grub_errno; } =20 -GRUB_MOD_INIT(videotest) +static void +list_tests (void) +{ + grub_printf ("Available tests\n"); + grub_printf ("=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D\n"); + grub_printf ("basic Basic video test with filled rectangles,\n"); + grub_printf (" offscreen rendering targets, some text.\n"); + grub_printf ("bench Run a performance benchmark.\n"); + grub_printf ("bitmaps Test generating and blitting bitmaps.\n"); + grub_printf ("clock Test time functions w/ animated progress bar.\= n"); + grub_printf ("doublebuf Test double buffering.\n"); + grub_printf ("text Test text rendering.\n"); + grub_printf ("scale Test image scaling.\n"); + grub_printf ("\n"); +} + + +GRUB_MOD_INIT (videotest) { grub_register_command ("videotest", grub_cmd_videotest, GRUB_COMMAND_FLAG_BOTH, - "videotest", - "Test video subsystem", - 0); + "videotest TEST", + "Run the specified video subsystem test.", + arg_options); } =20 -GRUB_MOD_FINI(videotest) +GRUB_MOD_FINI (videotest) { grub_unregister_command ("videotest"); } =3D=3D=3D modified file 'include/grub/video.h' --- include/grub/video.h 2009-01-05 16:34:09 +0000 +++ include/grub/video.h 2009-01-31 20:42:48 +0000 @@ -160,6 +160,16 @@ grub_uint8_t a; /* Reserved bits value (0-255). */ }; =20 +/* A 2D rectangle type. */ +struct grub_video_rect +{ + int x; + int y; + int width; + int height; +}; +typedef struct grub_video_rect grub_video_rect_t; + struct grub_video_adapter { /* The video adapter name. */ --MP_/ubbpVz//wlDqZrrt=+Cc3eP-- --Sig_/38q.+hnGers4YI.VG4hKnzA Content-Type: application/pgp-signature; name=signature.asc Content-Disposition: attachment; filename=signature.asc -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.9 (GNU/Linux) iEYEARECAAYFAkmEuGgACgkQokx8fzcGbYfOpwCfXaZvCPqm5jkLE0cZnzDUAv8D MMkAn2cwXoTBYSqCxxGrOO6RaG2aDZEL =tKGB -----END PGP SIGNATURE----- --Sig_/38q.+hnGers4YI.VG4hKnzA--