2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 2006,2007,2008,2009 Free Software Foundation, Inc.
5 * GRUB is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * GRUB is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
19 #include <grub/time.h>
20 #include <grub/video.h>
21 #include <grub/types.h>
23 #include <grub/extcmd.h>
24 #include <grub/misc.h>
26 #include <grub/font.h>
27 #include <grub/term.h>
28 #include <grub/bitmap.h>
29 #include <grub/bitmap_scale.h>
31 /* Option array indices. */
32 #define ARGINDEX_TEST_TIME 0
33 #define ARGINDEX_DOUBLE_BUF 1
35 static const struct grub_arg_option arg_options
[] = {
36 {"time", 't', 0, "Time to run each test, in seconds.", 0, ARG_TYPE_INT
},
37 {"dbuf", 'd', 0, "Use double buffered graphics.", 0, ARG_TYPE_NONE
},
41 #define DEFAULT_TEST_TIME 5
43 /* Command options -- populated base on command line arguments. */
44 struct videotest_options
50 /* List of video modes to try when an exact resolution is not required. */
51 static const char preferred_mode_list
[] = "1024x768;800x600;640x480";
54 basic_video_test (struct videotest_options
*vt_opts
)
56 grub_video_color_t color
;
57 grub_video_color_t bg
;
63 struct grub_font_glyph
*glyph
;
64 struct grub_video_render_target
*text_layer
;
66 grub_video_color_t palette
[16];
70 if (grub_video_set_mode (preferred_mode_list
, 0) != GRUB_ERR_NONE
)
72 grub_video_enable_double_buffering (vt_opts
->double_buffering
);
74 if (! (fixed
= grub_font_get ("Fixed Regular 20")))
76 grub_error (GRUB_ERR_BAD_FONT
, "No font loaded.");
80 grub_video_get_viewport (&x
, &y
, &width
, &height
);
82 grub_video_create_render_target (&text_layer
, width
, height
,
83 GRUB_VIDEO_MODE_TYPE_RGB
84 | GRUB_VIDEO_MODE_TYPE_ALPHA
);
86 grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY
);
91 color
= grub_video_map_rgb (0, 0, 0);
93 grub_video_fill_rect (color
, 0, 0, width
, height
);
95 color
= grub_video_map_rgb (255, 0, 0);
96 grub_video_fill_rect (color
, 0, 0, 100, 100);
98 color
= grub_video_map_rgb (0, 255, 255);
99 grub_video_fill_rect (color
, 100, 100, 100, 100);
101 glyph
= grub_font_get_glyph (fixed
, '*');
102 grub_font_draw_glyph (glyph
, color
, 200 ,0);
104 grub_video_set_viewport (x
+ 150, y
+ 150,
105 width
- 150 * 2, height
- 150 * 2);
106 color
= grub_video_map_rgb (77, 33, 77);
107 grub_video_fill_rect (color
, 0, 0, width
, height
);
109 grub_video_set_active_render_target (text_layer
);
111 color
= grub_video_map_rgb (255, 255, 0);
112 grub_font_draw_string ("ABCDEFG", fixed
, color
, 16, 100);
113 color
= grub_video_map_rgb (128, 128, 255);
114 grub_font_draw_string ("The quick brown fox jumped over the lazy dog.",
115 fixed
, color
, 16, 150);
117 color
= grub_video_map_rgb (255, 255, 255);
118 glyph
= grub_font_get_glyph (fixed
, '*');
120 for (i
= 0; i
< 16; i
++)
122 color
= grub_video_map_color (i
);
124 grub_font_draw_glyph (glyph
, color
, 16 + i
* 16, 220);
127 grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY
);
129 for (i
= 0; i
< 255; i
++)
131 color
= grub_video_map_rgb (i
, 33, 77);
132 grub_video_fill_rect (color
, 0, 0, width
, height
);
133 grub_video_blit_render_target (text_layer
, GRUB_VIDEO_BLIT_BLEND
, 0, 0,
134 0, 0, width
, height
);
137 color
= grub_video_map_rgb (255, 255, 0);
138 grub_font_draw_string ("Press a key to continue.", fixed
, color
, 10, 60);
139 grub_video_swap_buffers ();
141 grub_video_fill_rect (bg
, 0, 0, info_width
, info_height
); /* Clear info. */
143 grub_errno
= GRUB_ERR_NONE
;
148 /* Simple opaque image blit test.
149 Returns the error status in grub_errno. */
151 bitmap_demo (struct videotest_options
*vt_opts
)
153 if (grub_video_set_mode (preferred_mode_list
, 0) != GRUB_ERR_NONE
)
155 grub_video_enable_double_buffering (vt_opts
->double_buffering
);
157 grub_video_rect_t view
;
158 grub_video_get_viewport ((unsigned *) &view
.x
, (unsigned *) &view
.y
,
159 (unsigned *) &view
.width
,
160 (unsigned *) &view
.height
);
162 grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY
);
163 const int bm1width
= 500, bm1height
= 400;
164 struct grub_video_bitmap
*bitmap1
;
166 if (grub_video_bitmap_create (&bitmap1
, bm1width
, bm1height
,
167 GRUB_VIDEO_BLIT_FORMAT_RGB_888
)
174 grub_uint8_t
*data
= grub_video_bitmap_get_data (bitmap1
);
175 for (y
= 0; y
< bm1height
; y
++)
177 for (x
= 0; x
< bm1width
; x
++)
179 data
[offset
++] = x
^ y
; /* red */
180 data
[offset
++] = (x
* 3) ^ (y
* 3); /* green */
181 data
[offset
++] = (x
* 2) ^ (y
* 2); /* blue */
185 /* Blit the entire bitmap in the center of the screen. */
186 grub_video_blit_bitmap (bitmap1
,
187 GRUB_VIDEO_BLIT_REPLACE
,
188 view
.x
+ (view
.width
- bm1width
) / 2,
189 view
.y
+ (view
.height
- bm1height
) / 2,
190 0, 0, bm1width
, bm1height
);
191 grub_video_swap_buffers ();
194 /* Blit more copies of the bitmap. */
196 grub_video_blit_bitmap (bitmap1
, GRUB_VIDEO_BLIT_REPLACE
,
197 view
.x
, view
.y
, 0, 0, bm1width
, bm1height
);
199 grub_video_blit_bitmap (bitmap1
,
200 GRUB_VIDEO_BLIT_REPLACE
,
201 view
.x
+ view
.width
- bm1width
,
202 view
.y
, 0, 0, bm1width
, bm1height
);
204 grub_video_blit_bitmap (bitmap1
,
205 GRUB_VIDEO_BLIT_REPLACE
,
207 view
.y
+ view
.height
- bm1height
,
208 0, 0, bm1width
, bm1height
);
210 grub_video_blit_bitmap (bitmap1
,
211 GRUB_VIDEO_BLIT_REPLACE
,
212 view
.x
+ view
.width
- bm1width
,
213 view
.y
+ view
.height
- bm1height
,
214 0, 0, bm1width
, bm1height
);
215 grub_video_swap_buffers ();
218 int clearbg
= 0; /* Boolean flag: whether to fill background. */
219 grub_video_color_t bgcolor
= grub_video_map_rgb (16, 16, 96);
221 /* Animate the image sliding in. End when a key is pressed. */
223 int velocityx
= -5000;
224 int velocityy
= -8000;
228 grub_uint32_t frame_count
= 0;
229 grub_uint32_t start_time
= grub_get_time_ms ();
231 while (grub_checkkey () == -1)
233 /* If the time limit option is set, then check if it's exceeded. */
234 if (vt_opts
->test_time
!= 0
235 && grub_get_time_ms () >= start_time
+ vt_opts
->test_time
* 1000)
238 int newx
= positionx
+ velocityx
/ vscale
;
239 int newy
= positiony
+ velocityy
/ vscale
;
241 /* Check collision w/ left */
242 if (newx
< view
.x
&& velocityx
< 0)
244 velocityx
= -velocityx
;
245 newx
= positionx
+ velocityx
/ vscale
;
247 /* Check collision w/ right */
248 if (newx
+ bm1width
> view
.x
+ view
.width
&& velocityx
> 0)
250 velocityx
= -velocityx
;
251 newx
= positionx
+ velocityx
/ vscale
;
253 /* Check collision w/ top */
254 if (newy
< 0 && velocityy
< 0)
256 velocityy
= -velocityy
;
257 newy
= positiony
+ velocityy
/ vscale
;
259 /* Check collision w/ bottom */
260 if (newy
+ bm1height
> view
.y
+ view
.height
&& velocityy
> 0)
262 velocityy
= -velocityy
;
263 newy
= positiony
+ velocityy
/ vscale
;
270 grub_video_fill_rect (bgcolor
, view
.x
, view
.y
, view
.width
,
273 grub_video_blit_bitmap (bitmap1
,
274 GRUB_VIDEO_BLIT_REPLACE
,
276 view
.y
+ positiony
, 0, 0, bm1width
, bm1height
);
277 grub_video_swap_buffers ();
280 /* Acceleration due to gravity...
281 * note that the y coordinate is increasing downward. */
282 velocityy
+= vscale
/ 7;
285 /* Calculate average frame rate. */
286 grub_uint32_t duration
= grub_get_time_ms () - start_time
;
287 grub_uint32_t fps_x10
= 10 * 1000 * frame_count
/ duration
;
289 /* Eat the keystroke. */
290 if (grub_checkkey () != -1)
293 grub_video_bitmap_destroy (bitmap1
);
294 grub_video_restore ();
296 grub_printf ("Average frame rate: %d.%d fps\n", fps_x10
/ 10, fps_x10
% 10);
298 grub_errno
= GRUB_ERR_NONE
;
303 /* Configuration settings for a benchmark run. */
304 struct benchmark_config
306 const char *modespec
;
307 int use_rgba_bitmaps
;
310 /* The video configurations to use for the benchmark. */
311 static struct benchmark_config benchmark_configs
[] = {
318 #define NUM_BENCHMARK_CONFIGS (sizeof(benchmark_configs) \
319 / sizeof(benchmark_configs[0]))
321 struct benchmark_result
323 /* If set to 1, the test was able to run successfully;
324 0 means there was an error. */
327 /* Dimensions of the video mode used. */
331 /* Bits per pixel for the video mode used. */
334 /* All fps are in fps * 10 to achieve one decimal place. */
335 /* Set to 0 to indicate the test could not be run. */
336 grub_int32_t fill_fps
;
337 grub_int32_t blit_fps
;
338 grub_int32_t blend_fps
;
339 grub_int32_t text_ascii_cps
;
340 grub_int32_t text_unicode_cps
;
343 #define BENCHMARK_RESULT_FPS_SCALE 10
344 #define BENCHMARK_RESULT_CPS_SCALE 1
347 move_rectangle_one_step (int *x
, int *y
,
348 int width
, int height
,
349 int *vx
, int *vy
, const grub_video_rect_t
* bounds
)
354 /* Check collision w/ left */
355 if (newx
< bounds
->x
&& *vx
< 0)
360 /* Check collision w/ right */
361 if (newx
+ width
> bounds
->x
+ bounds
->width
&& *vx
> 0)
366 /* Check collision w/ top */
367 if (newy
< 0 && *vy
< 0)
372 /* Check collision w/ bottom */
373 if (newy
+ height
> bounds
->y
+ bounds
->height
&& *vy
> 0)
383 /* Get the length of a UTF-8 encoded character string. */
385 strlen_utf8 (const char *utf8str
)
388 const grub_uint8_t
*ptr
;
391 for (len
= 0, ptr
= (const grub_uint8_t
*) utf8str
;
392 grub_utf8_to_ucs4 (&code
, 1, ptr
, -1, &ptr
) > 0; )
398 /* Test text rendering performance. */
400 benchmark_text (const char *test_str
,
401 grub_int32_t
*cps_result
,
402 struct videotest_options
*vt_opts
,
403 grub_video_rect_t
*view
)
405 grub_uint32_t char_count
;
406 grub_uint64_t start_time
;
407 grub_uint64_t desired_stop_time
;
408 grub_uint32_t duration
;
409 grub_video_color_t black
;
410 grub_video_color_t text_colors
[4];
415 test_str_len
= strlen_utf8 (test_str
);
416 black
= grub_video_map_rgb (0, 0, 0);
417 text_colors
[0] = grub_video_map_rgb (44, 44, 54);
418 text_colors
[1] = grub_video_map_rgb (64, 64, 96);
419 text_colors
[2] = grub_video_map_rgb (80, 80, 140);
420 text_colors
[3] = grub_video_map_rgb (255, 255, 255);
421 font
= grub_font_get ("unifont Regular 10");
424 start_time
= grub_get_time_ms ();
425 desired_stop_time
= start_time
+ vt_opts
->test_time
* 1000;
428 while (grub_get_time_ms () < desired_stop_time
&& grub_checkkey () == -1)
432 grub_video_fill_rect (black
, 0, 0, view
->width
, view
->height
);
434 /* Draw a series of lines in different colors. */
435 for (color_index
= 0; color_index
< 4; color_index
++)
439 for (line_number
= 0; line_number
< 20; line_number
++)
444 x
= 10 - color_index
;
445 y
= (10 - color_index
446 + (line_number
+ 1) * phase
447 + grub_font_get_height (font
) * line_number
448 + grub_font_get_ascent (font
));
449 grub_font_draw_string (test_str
, font
,
450 text_colors
[color_index
], x
, y
);
451 /* Note: Using grub_strlen is not UTF-8-safe. */
452 char_count
+= test_str_len
;
460 grub_video_swap_buffers ();
462 if (grub_checkkey () != -1)
463 grub_getkey (); /* Eat the keypress, if there was one. */
465 /* Calculate average frame rate. */
466 duration
= grub_get_time_ms () - start_time
;
473 *cps_result
= (BENCHMARK_RESULT_CPS_SCALE
* 1000
474 * char_count
/ duration
);
478 /* Run the benchmark test for a particular video mode, which is specified
479 by `*config'. The results of the test are stored in `*result'. */
481 do_benchmark (const struct benchmark_config
*config
,
482 struct benchmark_result
*result
,
483 struct videotest_options
*vt_opts
)
485 struct grub_video_mode_info modeinfo
;
487 result
->test_passed
= 0;
491 result
->fill_fps
= 0;
492 result
->blit_fps
= 0;
493 result
->blend_fps
= 0;
495 if (grub_video_set_mode (config
->modespec
, 0) != GRUB_ERR_NONE
)
497 grub_video_enable_double_buffering (vt_opts
->double_buffering
);
499 if (grub_video_get_info (&modeinfo
) == GRUB_ERR_NONE
)
501 result
->width
= modeinfo
.width
;
502 result
->height
= modeinfo
.height
;
503 result
->bpp
= modeinfo
.bpp
;
506 /* Full screen bitmap blit test. */
508 grub_video_rect_t view
;
509 grub_video_get_viewport ((unsigned *) &view
.x
, (unsigned *) &view
.y
,
510 (unsigned *) &view
.width
,
511 (unsigned *) &view
.height
);
513 grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY
);
516 /* For measuring timing. */
517 grub_uint32_t frame_count
;
518 grub_uint64_t start_time
;
519 grub_uint64_t desired_stop_time
;
520 grub_uint32_t duration
;
525 /* Alternates between 0 and 1 to change the color. */
527 grub_video_color_t fillcolors
[2];
528 fillcolors
[0] = grub_video_map_rgb (0, 0, 255);
529 fillcolors
[1] = grub_video_map_rgb (255, 255, 0);
532 start_time
= grub_get_time_ms ();
533 desired_stop_time
= start_time
+ vt_opts
->test_time
* 1000;
535 while (grub_get_time_ms () < desired_stop_time
&& grub_checkkey () == -1)
537 grub_video_fill_rect (fillcolors
[color_flag
],
538 view
.x
, view
.y
, view
.width
, view
.height
);
539 grub_video_swap_buffers ();
543 if (grub_checkkey () != -1)
544 grub_getkey (); /* Eat the keypress, if there was one. */
546 /* Calculate average frame rate. */
547 duration
= grub_get_time_ms () - start_time
;
550 result
->fill_fps
= 0;
555 (BENCHMARK_RESULT_FPS_SCALE
* 1000
556 * frame_count
/ duration
);
562 /* Generate two bitmaps, the same size as the screen. */
563 const int bitmapwidth
= view
.width
, bitmapheight
= view
.height
;
564 struct grub_video_bitmap
*bitmap1
;
565 struct grub_video_bitmap
*bitmap2
;
566 enum grub_video_blit_format bitmap_format
= config
->use_rgba_bitmaps
567 ? GRUB_VIDEO_BLIT_FORMAT_RGBA_8888
: GRUB_VIDEO_BLIT_FORMAT_RGB_888
;
569 if (grub_video_bitmap_create (&bitmap1
, bitmapwidth
, bitmapheight
,
570 bitmap_format
) != GRUB_ERR_NONE
)
573 if (grub_video_bitmap_create (&bitmap2
, bitmapwidth
, bitmapheight
,
574 bitmap_format
) != GRUB_ERR_NONE
)
576 grub_video_bitmap_destroy (bitmap1
);
586 data
= grub_video_bitmap_get_data (bitmap1
);
587 for (y
= 0; y
< bitmapheight
; y
++)
589 for (x
= 0; x
< bitmapwidth
; x
++)
591 data
[offset
++] = x
^ y
; /* red */
592 data
[offset
++] = (x
* 3) ^ (y
* 3); /* green */
593 data
[offset
++] = (x
* 2) ^ (y
* 2); /* blue */
594 if (config
->use_rgba_bitmaps
)
595 data
[offset
++] = 255;
600 data
= grub_video_bitmap_get_data (bitmap2
);
601 for (y
= 0; y
< bitmapheight
; y
++)
603 for (x
= 0; x
< bitmapwidth
; x
++)
605 data
[offset
++] = x
+ y
; /* red */
606 data
[offset
++] = x
* x
+ y
* y
; /* green */
607 data
[offset
++] = x
* x
/ 4 + y
* y
/ 4; /* blue */
608 if (config
->use_rgba_bitmaps
)
609 data
[offset
++] = 255;
614 /* Now do the blit test, alternating between the two bitmaps. */
616 start_time
= grub_get_time_ms ();
617 desired_stop_time
= start_time
+ vt_opts
->test_time
* 1000;
619 int cur
= 0; /* Which bitmap to draw this frame. */
620 while (grub_get_time_ms () < desired_stop_time
&& grub_checkkey () == -1)
622 struct grub_video_bitmap
*current_bitmap
= cur
== 0 ? bitmap1
: bitmap2
;
623 grub_video_blit_bitmap (current_bitmap
,
624 GRUB_VIDEO_BLIT_REPLACE
,
625 view
.x
, view
.y
, 0, 0, bitmapwidth
,
627 grub_video_swap_buffers ();
631 if (grub_checkkey () != -1)
632 grub_getkey (); /* Eat the keypress, if there was once. */
634 /* Calculate average frame rate. */
635 duration
= grub_get_time_ms () - start_time
;
638 result
->blit_fps
= 0;
643 (BENCHMARK_RESULT_FPS_SCALE
* 1000
644 * frame_count
/ duration
);
647 grub_video_bitmap_destroy (bitmap2
);
648 grub_video_bitmap_destroy (bitmap1
);
654 /* Generate two bitmaps, with alpha translucency. */
655 const int bbw
= view
.width
* 2 / 3;
656 const int bbh
= view
.height
* 2 / 3;
658 if (grub_video_bitmap_create (&bitmap1
, bbw
, bbh
,
659 GRUB_VIDEO_BLIT_FORMAT_RGBA_8888
) !=
663 if (grub_video_bitmap_create (&bitmap2
, bbw
, bbh
,
664 GRUB_VIDEO_BLIT_FORMAT_RGBA_8888
) !=
667 grub_video_bitmap_destroy (bitmap1
);
672 data
= grub_video_bitmap_get_data (bitmap1
);
673 for (y
= 0; y
< bbh
; y
++)
675 for (x
= 0; x
< bbw
; x
++)
677 /* Calculate a to be increasing away from the center. */
678 int dx
= 256 * (x
- bbw
/ 2) / (bbw
/ 2);
679 int dy
= 256 * (y
- bbh
/ 2) / (bbh
/ 2);
680 int a
= dx
* dx
+ dy
* dy
;
681 /* range for a = 0 .. 2*(256^2) = 2*2^16 = 2^17 */
682 a
>>= 17 - 8; /* Make range 0..256. */
686 data
[offset
++] = x
^ y
; /* red */
687 data
[offset
++] = (x
* 3) ^ (y
* 3); /* green */
688 data
[offset
++] = (x
* 2) ^ (y
* 2); /* blue */
689 data
[offset
++] = 255 - a
;
694 data
= grub_video_bitmap_get_data (bitmap2
);
695 for (y
= 0; y
< bbh
; y
++)
697 for (x
= 0; x
< bbw
; x
++)
699 data
[offset
++] = x
+ y
; /* red */
700 data
[offset
++] = x
* x
+ y
* y
; /* green */
701 data
[offset
++] = x
* x
/ 4 + y
* y
/ 4; /* blue */
702 data
[offset
++] = 255;
707 start_time
= grub_get_time_ms ();
708 desired_stop_time
= start_time
+ vt_opts
->test_time
* 1000;
711 grub_video_color_t bgcolor
= grub_video_map_rgb (80, 80, 80);
713 /* Bitmap locations. */
716 int b2x
= view
.width
- bbw
;
718 /* Bitmap velocities. */
724 while (grub_get_time_ms () < desired_stop_time
&& grub_checkkey () == -1)
726 move_rectangle_one_step (&b1x
, &b1y
, bbw
, bbh
, &b1vx
, &b1vy
, &view
);
727 move_rectangle_one_step (&b2x
, &b2y
, bbw
, bbh
, &b2vx
, &b2vy
, &view
);
728 grub_video_fill_rect (bgcolor
, view
.x
, view
.y
, view
.width
, view
.height
);
729 grub_video_blit_bitmap (bitmap2
,
730 GRUB_VIDEO_BLIT_BLEND
,
731 b2x
, b2y
, 0, 0, bbw
, bbh
);
732 grub_video_blit_bitmap (bitmap1
,
733 GRUB_VIDEO_BLIT_BLEND
,
734 b1x
, b1y
, 0, 0, bbw
, bbh
);
735 grub_video_swap_buffers ();
739 if (grub_checkkey () != -1)
740 grub_getkey (); /* Eat the keypress, if there was once. */
742 /* Calculate average frame rate. */
743 duration
= grub_get_time_ms () - start_time
;
746 result
->blend_fps
= 0;
751 (BENCHMARK_RESULT_FPS_SCALE
* 1000
752 * frame_count
/ duration
);
755 grub_video_bitmap_destroy (bitmap2
);
756 grub_video_bitmap_destroy (bitmap1
);
758 /* Text benchmark with 104 characters of English ASCII text. */
759 benchmark_text ("The quick brown fox jumped over the lazy dog. "
761 "THE RAIN IN SPAIN FALLS MAINLY ON THE PLAIN.",
762 &result
->text_ascii_cps
, vt_opts
, &view
);
763 /* Text benchmark with 104 Unicode characters pseudorandomly uniformly
764 distributed over the characters provided by GNU unifont. The string is
766 benchmark_text ("\xE4\x94\x93\xEB\x83\xA6\xE2\x94\x85\xEB\xA8\xB1\xEE\x81"
767 "\xA3\xDD\x9D\xEA\xBC\xA4\xE1\xA3\x86\xEE\x8C\xA5\xE5\x8A"
768 "\x81\xEC\x99\x8A\xE0\xAE\xA1\xE8\xB4\xAC\xE4\x9A\xBD\xE6"
769 "\xB5\xAD\xED\xA4\x98\xEA\x88\x92\xE7\xA2\x9C\xEE\xAC\x8C"
770 "\xE9\x95\x9C\xE5\xB0\x89\xEB\x82\xA2\xE3\x9E\x89\xE8\xA4"
771 "\x87\xE4\xAC\xA0\xE8\x89\xA4\xE7\x8E\xAC\xE6\xA2\x95\xEE"
772 "\xAC\xB9\xE5\x9C\x8D\xEC\x8A\xA5\xE6\xB5\xA2\xE1\xA5\xBA"
773 "\xE2\x93\x80\xE6\x92\xA9\xE3\x9B\xB3\xE2\xB0\x9D\xE2\x95"
774 "\x94\xE7\xAD\x89\xE2\x83\x88\xEA\x8D\xA5\xE5\x8C\x99\xE5"
775 "\x9F\xB9\xE4\x88\x97\xEC\x95\xA6\xC9\xBD\xE5\xA1\x86\xE7"
776 "\xA3\xBE\xEA\x9A\xA9\xE5\x93\x98\xE4\xAD\xB1\xE1\x90\xB8"
777 "\xE4\x8A\x91\xE8\x8B\xBA\xE9\xB5\x80\xE8\xB6\xB1\xE4\x89"
778 "\xB4\xE4\xB8\x82\xDF\x8C\xE6\xAB\x83\xEA\x94\x8F\xEC\xA9"
779 "\xB1\xED\xA0\xA6\xEB\xBA\x89\xE2\xB1\x88\xE7\xA7\xA5\xE3"
780 "\x8A\x92\xE5\xA1\xA5\xEC\xAB\x89\xEA\xB7\x9B\xEA\x92\xBE"
781 "\xEA\xAD\x85\xE3\xB8\x8A\xE0\xB8\xBD\xEE\xB5\x9C\xE1\x93"
782 "\xB7\xE3\xB1\x8A\xE8\x8A\xB8\xEB\xA6\x85\xEE\x8B\xB4\xE1"
783 "\x92\xA7\xE4\x88\x8C\xE0\xA2\xB2\xE5\x9C\xB8\xEC\x94\x86"
784 "\xED\x86\x82\xE2\x87\xBF\xE1\xA4\x81\xE3\x84\x8A\xE2\xA7"
785 "\x8B\xE8\x8F\x84\xED\x98\x9A\xE3\x85\x92\xE9\xA4\x80\xED"
786 "\x86\xB9\xE5\xB6\x9A\xE4\xBF\xBC\xE1\x97\x92\xEE\x86\x90"
787 "\xE2\xB1\x8B\xC3\x83\xEC\x8D\xA4\xED\x9E\x90\xE3\xBB\x8E",
788 &result
->text_unicode_cps
, vt_opts
, &view
);
790 grub_video_restore ();
791 result
->test_passed
= 1;
794 /* Run a benchmark test in a series of video modes.
795 The results are reported in tabular form. This will be helpful to
796 determine how effective various optimizations are. */
798 benchmark_test (struct videotest_options
*vt_opts
)
801 struct benchmark_result results
[NUM_BENCHMARK_CONFIGS
];
803 /* Set option default values. */
804 if (vt_opts
->test_time
== 0)
805 vt_opts
->test_time
= DEFAULT_TEST_TIME
;
807 /* Run benchmarks. */
808 for (i
= 0; i
< NUM_BENCHMARK_CONFIGS
; i
++)
811 do_benchmark (&benchmark_configs
[i
], &results
[i
], vt_opts
);
816 /* Display results. */
817 grub_printf ("Benchmark results (in frames/s):\n");
818 grub_printf ("(W=Width, H=Height, B=Bits per pixel, A=Bitmap Alpha)\n");
819 grub_printf (" TEXT chars/s\n");
820 grub_printf (" W H B A FILL BLIT BLEND ASCII UNICODE\n");
821 for (i
= 0; i
< NUM_BENCHMARK_CONFIGS
; i
++)
823 struct benchmark_config
*c
= &benchmark_configs
[i
];
824 struct benchmark_result
*r
= &results
[i
];
828 grub_printf ("%4dx%4d %2d %d: %4d.%d %4d.%d %4d.%d %5d %5d\n",
829 r
->width
, r
->height
, r
->bpp
,
831 r
->fill_fps
/ BENCHMARK_RESULT_FPS_SCALE
,
832 r
->fill_fps
% BENCHMARK_RESULT_FPS_SCALE
,
833 r
->blit_fps
/ BENCHMARK_RESULT_FPS_SCALE
,
834 r
->blit_fps
% BENCHMARK_RESULT_FPS_SCALE
,
835 r
->blend_fps
/ BENCHMARK_RESULT_FPS_SCALE
,
836 r
->blend_fps
% BENCHMARK_RESULT_FPS_SCALE
,
837 r
->text_ascii_cps
/ BENCHMARK_RESULT_CPS_SCALE
,
838 r
->text_unicode_cps
/ BENCHMARK_RESULT_CPS_SCALE
);
842 grub_printf ("%s Not supported.\n", c
->modespec
);
846 grub_errno
= GRUB_ERR_NONE
;
850 /* Test time functions. */
852 clock_test (struct videotest_options
*vt_opts
)
854 if (grub_video_set_mode ("640x480", 0) != GRUB_ERR_NONE
)
856 grub_video_enable_double_buffering (vt_opts
->double_buffering
);
858 grub_video_rect_t view
;
859 grub_video_get_viewport ((unsigned *) &view
.x
, (unsigned *) &view
.y
,
860 (unsigned *) &view
.width
,
861 (unsigned *) &view
.height
);
863 grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY
);
865 /* Draw a progress bar that animates in sync with time. */
867 grub_video_rect_t bar_frame
;
868 bar_frame
.width
= view
.width
- 2 * view
.width
/ 10;
869 bar_frame
.height
= view
.height
/ 20;
870 bar_frame
.x
= view
.x
+ view
.width
/ 10;
871 bar_frame
.y
= view
.y
+ view
.height
- bar_frame
.height
- view
.height
/ 10;
873 grub_video_color_t bgcolor
= grub_video_map_rgb (50, 50, 50);
874 grub_video_color_t framecolor
= grub_video_map_rgb (255, 255, 255);
875 grub_video_color_t barbgcolor
= grub_video_map_rgb (0, 0, 128);
876 grub_video_color_t barcolor
= grub_video_map_rgb (100, 100, 255);
878 grub_uint32_t frame_count
;
879 grub_uint64_t start_time
;
880 grub_uint64_t barstart
;
881 grub_uint32_t barlength
= 1000;
883 grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY
);
886 start_time
= grub_get_time_ms ();
887 barstart
= grub_get_time_ms ();
889 while (grub_checkkey () == -1)
892 grub_uint32_t bartime
;
893 now
= grub_get_time_ms ();
894 /* If the time limit option is set, then check if it's exceeded. */
895 if (vt_opts
->test_time
!= 0
896 && now
>= start_time
+ vt_opts
->test_time
* 1000)
898 bartime
= now
- barstart
;
899 if (bartime
> barlength
)
901 barstart
= grub_get_time_ms (); /* Start over. */
906 grub_video_fill_rect (bgcolor
, view
.x
, view
.y
, view
.width
, view
.height
);
909 grub_video_fill_rect (framecolor
,
910 bar_frame
.x
- 1, bar_frame
.y
- 1,
911 bar_frame
.width
+ 2, bar_frame
.height
+ 2);
913 /* Bar background. */
914 int barwidth
= bar_frame
.width
* bartime
/ barlength
;
915 grub_video_fill_rect (barbgcolor
, bar_frame
.x
+ barwidth
,
916 bar_frame
.y
, bar_frame
.width
- barwidth
,
918 /* Bar foreground. */
919 grub_video_fill_rect (barcolor
, bar_frame
.x
, bar_frame
.y
,
920 barwidth
, bar_frame
.height
);
921 grub_video_swap_buffers ();
925 grub_uint32_t duration
= grub_get_time_ms () - start_time
;
926 grub_uint32_t fps_x10
= 10 * 1000 * frame_count
/ duration
;
928 if (grub_checkkey () != -1)
929 grub_getkey (); /* Eat the keypress, if there was one. */
930 grub_video_restore ();
931 grub_printf ("Average frame rate: %d.%d fps\n", fps_x10
/ 10, fps_x10
% 10);
935 /* Test double buffering. */
937 doublebuf_test (struct videotest_options
*vt_opts
)
939 if (grub_video_set_mode ("640x480", 0) != GRUB_ERR_NONE
)
941 grub_video_enable_double_buffering (vt_opts
->double_buffering
);
943 grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY
);
945 grub_video_color_t red
= grub_video_map_rgb (255, 50, 50);
946 grub_video_color_t yellow
= grub_video_map_rgb (255, 255, 0);
947 grub_video_color_t green
= grub_video_map_rgb (20, 255, 20);
948 grub_video_color_t blue
= grub_video_map_rgb (50, 50, 255);
949 grub_video_color_t black
= grub_video_map_rgb (0, 0, 0);
950 grub_video_color_t bgcolor
= grub_video_map_rgb (255, 255, 255);
952 grub_video_fill_rect (bgcolor
, 0, 0, 640, 480);
953 grub_video_fill_rect (red
, 100, 100, 200, 200);
954 grub_video_swap_buffers ();
957 grub_video_fill_rect (bgcolor
, 0, 0, 640, 480);
958 grub_video_fill_rect (yellow
, 120, 120, 200, 200);
959 grub_video_swap_buffers ();
962 grub_video_fill_rect (bgcolor
, 0, 0, 640, 480);
963 grub_video_fill_rect (green
, 140, 140, 200, 200);
964 grub_video_swap_buffers ();
967 grub_video_fill_rect (bgcolor
, 0, 0, 640, 480);
968 grub_video_fill_rect (blue
, 160, 160, 200, 200);
969 grub_video_swap_buffers ();
972 grub_video_fill_rect (bgcolor
, 0, 0, 640, 480);
973 grub_video_fill_rect (black
, 180, 180, 200, 200);
974 grub_video_swap_buffers ();
977 grub_video_restore ();
981 /* Test text rendering. */
983 text_test (struct videotest_options
*vt_opts
)
985 grub_video_color_t color
;
999 grub_font_t sanssmall
;
1002 if (grub_video_set_mode (preferred_mode_list
, 0) != GRUB_ERR_NONE
)
1004 grub_video_enable_double_buffering (vt_opts
->double_buffering
);
1006 grub_video_get_viewport ((unsigned int *) &view_x
,
1007 (unsigned int *) &view_y
,
1008 (unsigned int *) &view_width
,
1009 (unsigned int *) &view_height
);
1010 grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY
);
1012 if (!(font1
= grub_font_get ("New Century Schoolbook Regular 24"))
1013 || !(font2
= grub_font_get ("Helvetica Bold 14"))
1014 || !(font3
= grub_font_get ("Helvetica Regular 10"))
1015 || !(sansbig
= grub_font_get ("Helvetica Bold 24"))
1016 || !(sans
= grub_font_get ("Helvetica Bold 14"))
1017 || !(sanssmall
= grub_font_get ("Helvetica Regular 8"))
1018 || !(fixed
= grub_font_get ("Fixed Regular 20")))
1020 grub_video_restore ();
1021 grub_error (GRUB_ERR_BAD_FONT
, "No font loaded.");
1025 color
= grub_video_map_rgb (0, 0, 0);
1026 grub_video_fill_rect (color
, 0, 0, view_width
, view_height
);
1028 color
= grub_video_map_rgb (255, 0, 0);
1029 grub_video_fill_rect (color
, 0, 0, 100, 100);
1031 color
= grub_video_map_rgb (0, 255, 255);
1032 grub_video_fill_rect (color
, 100, 100, 100, 100);
1034 color
= grub_video_map_rgb (255, 255, 255);
1038 s
= "Hello, World!";
1039 for (i
= 0; i
< 24; i
++)
1041 if (xpos
+ grub_font_get_string_width (font1
, s
) >= view_width
)
1043 /* The string will wrap; go to the beginning of the next line. */
1045 ypos
+= (grub_font_get_descent (font1
)
1046 + grub_font_get_ascent (font1
));
1048 grub_font_draw_string ("Hello, World!",
1049 font1
, grub_video_map_rgb (255, 255, 0),
1052 xpos
+= grub_font_get_string_width (font1
, s
);
1057 grub_font_draw_string (grub_font_get_name (font1
),
1058 font1
, grub_video_map_rgb (255, 255, 255),
1060 ypos
+= grub_font_get_descent (font1
) + grub_font_get_ascent (font2
) + 2;
1061 grub_font_draw_string (grub_font_get_name (font2
),
1062 font2
, grub_video_map_rgb (255, 255, 255),
1064 ypos
+= grub_font_get_descent (font2
) + grub_font_get_ascent (font3
) + 2;
1065 grub_font_draw_string (grub_font_get_name (font3
),
1066 font3
, grub_video_map_rgb (255, 255, 255),
1069 ypos
+= 40; /* Spacing. */
1071 grub_font_draw_string ("The quick brown fox jumped over the lazy dog.",
1072 sans
, color
, view_x
+ 16, ypos
);
1073 ypos
+= grub_font_get_descent (sans
) + grub_font_get_leading (sans
);
1075 ypos
+= grub_font_get_ascent (fixed
);
1076 grub_font_draw_string ("The quick brown fox jumped over the lazy dog.",
1077 fixed
, color
, 16, ypos
);
1078 ypos
+= grub_font_get_descent (fixed
) + grub_font_get_leading (fixed
);
1080 ypos
+= 40; /* Spacing. */
1082 /* To convert Unicode characters into UTF-8 for this test, the following
1084 echo -ne '\x00\x00\x26\x3A' | iconv -f UTF-32BE -t UTF-8 | od -t x1
1085 This converts the Unicode character U+263A to UTF-8. */
1088 Code point Description UTF-8 encoding
1089 ----------- ------------------------------ --------------
1090 U+263A unfilled smiley face E2 98 BA
1091 U+00A1 inverted exclamation point C2 A1
1092 U+00A3 British pound currency symbol C2 A3
1093 U+03C4 Greek tau CF 84
1094 U+00E4 lowercase letter a with umlaut C3 A4
1095 U+2124 set 'Z' symbol (integers) E2 84 A4
1096 U+2287 subset symbol E2 8A 87
1097 U+211D set 'R' symbol (real numbers) E2 84 9D */
1100 "Unicode test: happy\xE2\x98\xBA \xC2\xA3 5.00"
1101 " \xC2\xA1\xCF\x84\xC3\xA4u! "
1102 " \xE2\x84\xA4\xE2\x8A\x87\xE2\x84\x9D";
1103 color
= grub_video_map_rgb (128, 128, 255);
1105 /* All characters in the string exist in the 'Fixed 20' (10x20) font. */
1106 ypos
+= grub_font_get_ascent (fixed
);
1107 grub_font_draw_string (s
, fixed
, color
, 16, ypos
);
1108 ypos
+= grub_font_get_descent (fixed
) + grub_font_get_leading (fixed
);
1110 /* Some characters don't exist in the Helvetica font, so the font engine
1111 may fall back to using glyphs from another font that has them. */
1113 ypos
+= grub_font_get_ascent (sansbig
);
1114 grub_font_draw_string (s
, sansbig
, color
, 16, ypos
);
1115 ypos
+= grub_font_get_descent (sansbig
) + grub_font_get_leading (sansbig
);
1117 ypos
+= grub_font_get_ascent (sans
);
1118 grub_font_draw_string (s
, sans
, color
, 16, ypos
);
1119 ypos
+= grub_font_get_descent (sans
) + grub_font_get_leading (sans
);
1121 ypos
+= grub_font_get_ascent (sanssmall
);
1122 grub_font_draw_string (s
, sanssmall
, color
, 16, ypos
);
1123 ypos
+= (grub_font_get_descent (sanssmall
)
1124 + grub_font_get_leading (sanssmall
));
1127 grub_video_swap_buffers ();
1129 grub_video_restore ();
1130 grub_errno
= GRUB_ERR_NONE
;
1134 /* Test bitmap scaling. */
1136 scale_test (struct videotest_options
*vt_opts
)
1138 if (grub_video_set_mode (preferred_mode_list
, 0) != GRUB_ERR_NONE
)
1140 grub_video_enable_double_buffering (vt_opts
->double_buffering
);
1142 grub_errno
= GRUB_ERR_NONE
;
1143 grub_video_rect_t view
;
1144 grub_video_get_viewport ((unsigned *) &view
.x
, (unsigned *) &view
.y
,
1145 (unsigned *) &view
.width
,
1146 (unsigned *) &view
.height
);
1148 grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY
);
1151 if (!(font
= grub_font_get ("Helvetica Regular 10")))
1153 grub_video_restore ();
1154 grub_error (GRUB_ERR_BAD_FONT
, "No font loaded.");
1158 grub_video_color_t color
;
1161 int text_height
= 25;
1163 color
= grub_video_map_rgb (44, 44, 200);
1164 grub_video_fill_rect (color
, view
.x
, view
.y
, view
.width
, view
.height
);
1165 color
= grub_video_map_rgb (255, 255, 255);
1167 grub_font_draw_string ("Loading image",
1168 font
, color
, 10, text_y
+= text_height
);
1170 enum grub_video_bitmap_scale_method scale_method
=
1171 GRUB_VIDEO_BITMAP_SCALE_METHOD_BEST
;
1172 const char *bitmap_name
= "/boot/grub/themes/winter/without-leaves.png";
1173 struct grub_video_bitmap
*bitmap
;
1174 grub_video_bitmap_load (&bitmap
, bitmap_name
);
1175 if (grub_errno
!= GRUB_ERR_NONE
)
1177 grub_font_draw_string ("Error loading bitmap",
1178 font
, color
, 10, text_y
+= text_height
);
1182 grub_font_draw_string ("Original image",
1183 font
, color
, 10, text_y
+= text_height
);
1184 grub_video_blit_bitmap (bitmap
, GRUB_VIDEO_BLIT_BLEND
,
1186 0, 0, grub_video_bitmap_get_width (bitmap
),
1187 grub_video_bitmap_get_height (bitmap
));
1189 struct grub_video_bitmap
*bitmap2
;
1190 if (grub_video_bitmap_create_scaled (&bitmap2
, 40, 40,
1195 grub_font_draw_string ("Error scaling down bitmap",
1196 font
, color
, 10, text_y
+= text_height
);
1200 grub_font_draw_string ("Scaled down version",
1201 font
, color
, 10, text_y
+= text_height
);
1202 grub_video_blit_bitmap (bitmap2
, GRUB_VIDEO_BLIT_BLEND
,
1204 0, 0, grub_video_bitmap_get_width (bitmap2
),
1205 grub_video_bitmap_get_height (bitmap2
));
1206 grub_video_bitmap_destroy (bitmap2
);
1209 struct grub_video_bitmap
*bitmap3
;
1210 if (grub_video_bitmap_create_scaled (&bitmap3
, 500, 300, bitmap
,
1214 grub_font_draw_string ("Error scaling up bitmap",
1215 font
, color
, 10, text_y
+= text_height
);
1219 grub_font_draw_string ("Scaled up version",
1220 font
, color
, 10, text_y
+= text_height
);
1221 grub_video_blit_bitmap (bitmap3
, GRUB_VIDEO_BLIT_BLEND
,
1223 0, 0, grub_video_bitmap_get_width (bitmap3
),
1224 grub_video_bitmap_get_height (bitmap3
));
1225 grub_video_bitmap_destroy (bitmap3
);
1229 grub_video_swap_buffers ();
1231 grub_video_bitmap_destroy (bitmap
);
1232 grub_video_restore ();
1236 /* Print a list of the available tests. */
1237 static void list_tests (void);
1240 Video test command. Takes an argument specifying the test to run.
1243 grub_cmd_videotest (grub_extcmd_t cmd
, int argc
, char **args
)
1245 struct grub_arg_list
*state
= cmd
->state
;
1247 struct videotest_options vt_opts
;
1248 /* Pointer to the test function. */
1249 void (*test_func
) (struct videotest_options
*) = NULL
;
1252 state
[ARGINDEX_TEST_TIME
].set
1253 ? grub_strtoul (state
[ARGINDEX_TEST_TIME
].arg
, 0, 0) : 0;
1254 vt_opts
.double_buffering
= state
[ARGINDEX_DOUBLE_BUF
].set
;
1256 /* Parse command line arguments to determine the test to run. */
1257 for (i
= 0; i
< argc
; i
++)
1259 char *arg
= args
[i
];
1260 if (grub_strcmp (arg
, "list") == 0)
1263 return GRUB_ERR_NONE
;
1265 else if (grub_strcmp (arg
, "basic") == 0)
1267 test_func
= basic_video_test
;
1269 else if (grub_strcmp (arg
, "bench") == 0)
1271 test_func
= benchmark_test
;
1273 else if (grub_strcmp (arg
, "bitmaps") == 0)
1275 test_func
= bitmap_demo
;
1277 else if (grub_strcmp (arg
, "clock") == 0)
1279 test_func
= clock_test
;
1281 else if (grub_strcmp (arg
, "doublebuf") == 0)
1283 test_func
= doublebuf_test
;
1285 else if (grub_strcmp (arg
, "text") == 0)
1287 test_func
= text_test
;
1289 else if (grub_strcmp (arg
, "scale") == 0)
1291 test_func
= scale_test
;
1295 grub_printf ("Error: Unknown test `%s'\n", arg
);
1296 grub_errno
= GRUB_ERR_BAD_ARGUMENT
;
1301 if (test_func
== NULL
)
1303 grub_printf ("Usage: videotest TESTNAME Run a test.\n");
1304 grub_printf (" videotest list List available tests.\n");
1310 test_func (&vt_opts
);
1319 grub_printf ("Available tests\n");
1320 grub_printf ("===============\n");
1321 grub_printf ("basic Basic video test with filled rectangles,\n");
1322 grub_printf (" offscreen rendering targets, some text.\n");
1323 grub_printf ("bench Run a performance benchmark.\n");
1324 grub_printf ("bitmaps Test generating and blitting bitmaps.\n");
1325 grub_printf ("clock Test time functions w/ animated progress bar.\n");
1326 grub_printf ("doublebuf Test double buffering.\n");
1327 grub_printf ("text Test text rendering.\n");
1328 grub_printf ("scale Test image scaling.\n");
1332 static grub_extcmd_t cmd
;
1334 GRUB_MOD_INIT (videotest
)
1336 cmd
= grub_register_extcmd ("videotest",
1338 GRUB_COMMAND_FLAG_BOTH
,
1340 "Run the specified video subsystem test.",
1344 GRUB_MOD_FINI (videotest
)
1346 grub_unregister_extcmd (cmd
);