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/term.h>
20 #include <grub/types.h>
22 #include <grub/misc.h>
23 #include <grub/font.h>
26 #include <grub/video.h>
27 #include <grub/gfxterm.h>
28 #include <grub/bitmap.h>
29 #include <grub/bitmap_scale.h>
30 #include <grub/extcmd.h>
32 #define DEFAULT_VIDEO_MODE "1024x768,800x600,640x480"
33 #define DEFAULT_BORDER_WIDTH 10
35 #define DEFAULT_STANDARD_COLOR 0x07
36 #define DEFAULT_NORMAL_COLOR 0x07
37 #define DEFAULT_HIGHLIGHT_COLOR 0x70
39 struct grub_dirty_region
47 struct grub_colored_char
49 /* An Unicode codepoint. */
53 grub_video_color_t fg_color
;
54 grub_video_color_t bg_color
;
56 /* The width of this character minus one. */
59 /* The column index of this character. */
63 struct grub_virtual_screen
65 /* Dimensions of the virtual screen in pixels. */
69 /* Offset in the display in pixels. */
70 unsigned int offset_x
;
71 unsigned int offset_y
;
73 /* TTY Character sizes in pixes. */
74 unsigned int normal_char_width
;
75 unsigned int normal_char_height
;
77 /* Virtual screen TTY size in characters. */
81 /* Current cursor location in characters. */
82 unsigned int cursor_x
;
83 unsigned int cursor_y
;
85 /* Current cursor state. */
91 /* Terminal color settings. */
92 grub_uint8_t standard_color_setting
;
93 grub_uint8_t normal_color_setting
;
94 grub_uint8_t highlight_color_setting
;
95 grub_uint8_t term_color
;
98 grub_video_color_t fg_color
;
99 grub_video_color_t bg_color
;
101 /* Text buffer for virtual screen. Contains (columns * rows) number
103 struct grub_colored_char
*text_buffer
;
107 static struct grub_video_render_target
*render_target
;
108 static grub_video_rect_t window
;
109 static struct grub_virtual_screen virtual_screen
;
110 static grub_gfxterm_repaint_callback_t repaint_callback
;
112 static grub_err_t
init_window (struct grub_video_render_target
*target
,
113 int x
, int y
, int width
, int height
,
114 const char *font_name
, int border_width
);
116 static void destroy_window (void);
119 static struct grub_video_render_target
*text_layer
;
121 static unsigned int bitmap_width
;
122 static unsigned int bitmap_height
;
123 static struct grub_video_bitmap
*bitmap
;
125 static struct grub_dirty_region dirty_region
;
127 static void dirty_region_reset (void);
129 static int dirty_region_is_empty (void);
131 static void dirty_region_add (int x
, int y
,
132 unsigned int width
, unsigned int height
);
134 static unsigned int calculate_normal_character_width (grub_font_t font
);
136 static unsigned char calculate_character_width (struct grub_font_glyph
*glyph
);
139 set_term_color (grub_uint8_t term_color
)
141 struct grub_video_render_target
*old_target
;
143 /* Save previous target and switch to text layer. */
144 grub_video_get_active_render_target (&old_target
);
145 grub_video_set_active_render_target (text_layer
);
147 /* Map terminal color to text layer compatible video colors. */
148 virtual_screen
.fg_color
= grub_video_map_color(term_color
& 0x0f);
150 /* Special case: use black as transparent color. */
151 if (((term_color
>> 4) & 0x0f) == 0)
153 virtual_screen
.bg_color
= grub_video_map_rgba(0, 0, 0, 0);
157 virtual_screen
.bg_color
= grub_video_map_color((term_color
>> 4) & 0x0f);
160 /* Restore previous target. */
161 grub_video_set_active_render_target (old_target
);
165 grub_virtual_screen_free (void)
167 /* If virtual screen has been allocated, free it. */
168 if (virtual_screen
.text_buffer
!= 0)
169 grub_free (virtual_screen
.text_buffer
);
171 /* Reset virtual screen data. */
172 grub_memset (&virtual_screen
, 0, sizeof (virtual_screen
));
174 /* Free render targets. */
175 grub_video_delete_render_target (text_layer
);
180 grub_virtual_screen_setup (unsigned int x
, unsigned int y
,
181 unsigned int width
, unsigned int height
,
182 const char *font_name
)
184 /* Free old virtual screen. */
185 grub_virtual_screen_free ();
187 /* Initialize with default data. */
188 virtual_screen
.font
= grub_font_get (font_name
);
189 if (!virtual_screen
.font
)
190 return grub_error (GRUB_ERR_BAD_FONT
,
192 virtual_screen
.width
= width
;
193 virtual_screen
.height
= height
;
194 virtual_screen
.offset_x
= x
;
195 virtual_screen
.offset_y
= y
;
196 virtual_screen
.normal_char_width
=
197 calculate_normal_character_width (virtual_screen
.font
);
198 virtual_screen
.normal_char_height
=
199 grub_font_get_max_char_height (virtual_screen
.font
);
200 virtual_screen
.cursor_x
= 0;
201 virtual_screen
.cursor_y
= 0;
202 virtual_screen
.cursor_state
= 1;
204 /* Calculate size of text buffer. */
205 virtual_screen
.columns
= virtual_screen
.width
/ virtual_screen
.normal_char_width
;
206 virtual_screen
.rows
= virtual_screen
.height
/ virtual_screen
.normal_char_height
;
208 /* Allocate memory for text buffer. */
209 virtual_screen
.text_buffer
=
210 (struct grub_colored_char
*) grub_malloc (virtual_screen
.columns
211 * virtual_screen
.rows
212 * sizeof (*virtual_screen
.text_buffer
));
213 if (grub_errno
!= GRUB_ERR_NONE
)
216 /* Create new render target for text layer. */
217 grub_video_create_render_target (&text_layer
,
218 virtual_screen
.width
,
219 virtual_screen
.height
,
220 GRUB_VIDEO_MODE_TYPE_RGB
221 | GRUB_VIDEO_MODE_TYPE_ALPHA
);
222 if (grub_errno
!= GRUB_ERR_NONE
)
225 /* As we want to have colors compatible with rendering target,
226 we can only have those after mode is initialized. */
227 grub_video_set_active_render_target (text_layer
);
229 virtual_screen
.standard_color_setting
= DEFAULT_STANDARD_COLOR
;
230 virtual_screen
.normal_color_setting
= DEFAULT_NORMAL_COLOR
;
231 virtual_screen
.highlight_color_setting
= DEFAULT_HIGHLIGHT_COLOR
;
233 virtual_screen
.term_color
= virtual_screen
.normal_color_setting
;
235 set_term_color (virtual_screen
.term_color
);
237 grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY
);
242 static int NESTED_FUNC_ATTR
video_hook (grub_video_adapter_t p
__attribute__ ((unused
)),
243 struct grub_video_mode_info
*info
)
245 return ! (info
->mode_type
& GRUB_VIDEO_MODE_TYPE_PURE_TEXT
);
249 init_window (struct grub_video_render_target
*target
,
250 int x
, int y
, int width
, int height
,
251 const char *font_name
, int border_width
)
253 /* Clean up any prior instance. */
256 /* Create virtual screen. */
257 if (grub_virtual_screen_setup (border_width
, border_width
,
258 width
- 2 * border_width
,
259 height
- 2 * border_width
,
266 /* Set the render target. */
267 render_target
= target
;
269 /* Set window bounds. */
272 window
.width
= width
;
273 window
.height
= height
;
275 /* Mark whole window as dirty. */
276 dirty_region_reset ();
277 dirty_region_add (0, 0, width
, height
);
283 grub_gfxterm_init_window (struct grub_video_render_target
*target
,
284 int x
, int y
, int width
, int height
,
285 const char *font_name
, int border_width
)
288 init_window (target
, x
, y
, width
, height
, font_name
, border_width
);
293 grub_gfxterm_init (void)
295 const char *font_name
;
297 struct grub_video_mode_info mode_info
;
301 /* If gfxterm has already been initialized by calling the init_window
302 function, then leave it alone when it is set as the current terminal. */
304 return GRUB_ERR_NONE
;
306 /* Select the font to use. */
307 font_name
= grub_env_get ("gfxterm_font");
309 font_name
= ""; /* Allow fallback to any font. */
311 /* Parse gfxmode environment variable if set. */
312 modevar
= grub_env_get ("gfxmode");
313 if (! modevar
|| *modevar
== 0)
314 err
= grub_video_set_mode (DEFAULT_VIDEO_MODE
, video_hook
);
317 tmp
= grub_malloc (grub_strlen (modevar
)
318 + sizeof (DEFAULT_VIDEO_MODE
) + 1);
321 grub_sprintf (tmp
, "%s;" DEFAULT_VIDEO_MODE
, modevar
);
322 err
= grub_video_set_mode (tmp
, video_hook
);
329 err
= grub_video_get_info (&mode_info
);
330 /* Figure out what mode we ended up. */
334 /* Make sure screen is black. */
335 grub_video_fill_rect (grub_video_map_rgb (0, 0, 0),
336 0, 0, mode_info
.width
, mode_info
.height
);
339 /* Select the font to use. */
340 font_name
= grub_env_get ("gfxterm_font");
342 font_name
= ""; /* Allow fallback to any font. */
344 /* Leave borders for virtual screen. */
345 if (init_window (GRUB_VIDEO_RENDER_TARGET_DISPLAY
,
346 0, 0, mode_info
.width
, mode_info
.height
,
348 DEFAULT_BORDER_WIDTH
) != GRUB_ERR_NONE
)
350 grub_video_restore ();
358 destroy_window (void)
362 grub_video_bitmap_destroy (bitmap
);
366 repaint_callback
= 0;
367 grub_virtual_screen_free ();
371 grub_gfxterm_destroy_window (void)
378 grub_gfxterm_fini (void)
380 /* Don't destroy an explicitly initialized terminal instance when it is
381 unset as the current terminal. */
385 grub_video_restore ();
388 /* Clear error state. */
389 return (grub_errno
= GRUB_ERR_NONE
);
393 redraw_screen_rect (unsigned int x
, unsigned int y
,
394 unsigned int width
, unsigned int height
)
396 grub_video_color_t color
;
397 grub_video_rect_t saved_view
;
399 grub_video_set_active_render_target (render_target
);
400 /* Save viewport and set it to our window. */
401 grub_video_get_viewport ((unsigned *) &saved_view
.x
,
402 (unsigned *) &saved_view
.y
,
403 (unsigned *) &saved_view
.width
,
404 (unsigned *) &saved_view
.height
);
405 grub_video_set_viewport (window
.x
, window
.y
, window
.width
, window
.height
);
409 /* Render bitmap as background. */
410 grub_video_blit_bitmap (bitmap
, GRUB_VIDEO_BLIT_REPLACE
, x
, y
,
414 /* If bitmap is smaller than requested blit area, use background
416 color
= virtual_screen
.bg_color
;
418 /* Fill right side of the bitmap if needed. */
419 if ((x
+ width
>= bitmap_width
) && (y
< bitmap_height
))
421 int w
= (x
+ width
) - bitmap_width
;
425 if (y
+ height
>= bitmap_height
)
427 h
= bitmap_height
- y
;
430 if (bitmap_width
> tx
)
435 /* Render background layer. */
436 grub_video_fill_rect (color
, tx
, y
, w
, h
);
439 /* Fill bottom side of the bitmap if needed. */
440 if (y
+ height
>= bitmap_height
)
442 int h
= (y
+ height
) - bitmap_height
;
445 if (bitmap_height
> ty
)
450 /* Render background layer. */
451 grub_video_fill_rect (color
, x
, ty
, width
, h
);
454 /* Render text layer as blended. */
455 grub_video_blit_render_target (text_layer
, GRUB_VIDEO_BLIT_BLEND
, x
, y
,
456 x
- virtual_screen
.offset_x
,
457 y
- virtual_screen
.offset_y
,
462 /* Render background layer. */
463 color
= virtual_screen
.bg_color
;
464 grub_video_fill_rect (color
, x
, y
, width
, height
);
466 /* Render text layer as replaced (to get texts background color). */
467 grub_video_blit_render_target (text_layer
, GRUB_VIDEO_BLIT_REPLACE
, x
, y
,
468 x
- virtual_screen
.offset_x
,
469 y
- virtual_screen
.offset_y
,
473 /* Restore saved viewport. */
474 grub_video_set_viewport (saved_view
.x
, saved_view
.y
,
475 saved_view
.width
, saved_view
.height
);
476 grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY
);
478 if (repaint_callback
)
479 repaint_callback (x
, y
, width
, height
);
483 dirty_region_reset (void)
485 dirty_region
.top_left_x
= -1;
486 dirty_region
.top_left_y
= -1;
487 dirty_region
.bottom_right_x
= -1;
488 dirty_region
.bottom_right_y
= -1;
492 dirty_region_is_empty (void)
494 if ((dirty_region
.top_left_x
== -1)
495 || (dirty_region
.top_left_y
== -1)
496 || (dirty_region
.bottom_right_x
== -1)
497 || (dirty_region
.bottom_right_y
== -1))
503 dirty_region_add (int x
, int y
, unsigned int width
, unsigned int height
)
505 if ((width
== 0) || (height
== 0))
508 if (dirty_region_is_empty ())
510 dirty_region
.top_left_x
= x
;
511 dirty_region
.top_left_y
= y
;
512 dirty_region
.bottom_right_x
= x
+ width
- 1;
513 dirty_region
.bottom_right_y
= y
+ height
- 1;
517 if (x
< dirty_region
.top_left_x
)
518 dirty_region
.top_left_x
= x
;
519 if (y
< dirty_region
.top_left_y
)
520 dirty_region
.top_left_y
= y
;
521 if ((x
+ (int)width
- 1) > dirty_region
.bottom_right_x
)
522 dirty_region
.bottom_right_x
= x
+ width
- 1;
523 if ((y
+ (int)height
- 1) > dirty_region
.bottom_right_y
)
524 dirty_region
.bottom_right_y
= y
+ height
- 1;
529 dirty_region_add_virtualscreen (void)
531 /* Mark virtual screen as dirty. */
532 dirty_region_add (virtual_screen
.offset_x
, virtual_screen
.offset_y
,
533 virtual_screen
.width
, virtual_screen
.height
);
538 dirty_region_redraw (void)
545 if (dirty_region_is_empty ())
548 x
= dirty_region
.top_left_x
;
549 y
= dirty_region
.top_left_y
;
551 width
= dirty_region
.bottom_right_x
- x
+ 1;
552 height
= dirty_region
.bottom_right_y
- y
+ 1;
554 redraw_screen_rect (x
, y
, width
, height
);
556 dirty_region_reset ();
557 grub_video_swap_buffers ();
563 struct grub_colored_char
*p
;
564 struct grub_font_glyph
*glyph
;
565 grub_video_color_t color
;
566 grub_video_color_t bgcolor
;
573 /* Find out active character. */
574 p
= (virtual_screen
.text_buffer
575 + virtual_screen
.cursor_x
576 + (virtual_screen
.cursor_y
* virtual_screen
.columns
));
580 /* Get glyph for character. */
581 glyph
= grub_font_get_glyph (virtual_screen
.font
, p
->code
);
582 ascent
= grub_font_get_ascent (virtual_screen
.font
);
584 width
= virtual_screen
.normal_char_width
* calculate_character_width(glyph
);
585 height
= virtual_screen
.normal_char_height
;
588 bgcolor
= p
->bg_color
;
590 x
= virtual_screen
.cursor_x
* virtual_screen
.normal_char_width
;
591 y
= virtual_screen
.cursor_y
* virtual_screen
.normal_char_height
;
593 /* Render glyph to text layer. */
594 grub_video_set_active_render_target (text_layer
);
595 grub_video_fill_rect (bgcolor
, x
, y
, width
, height
);
596 grub_font_draw_glyph (glyph
, color
, x
, y
+ ascent
);
597 grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY
);
599 /* Mark character to be drawn. */
600 dirty_region_add (virtual_screen
.offset_x
+ x
, virtual_screen
.offset_y
+ y
,
605 draw_cursor (int show
)
615 grub_video_color_t color
;
617 /* Determine cursor properties and position on text layer. */
618 x
= virtual_screen
.cursor_x
* virtual_screen
.normal_char_width
;
619 width
= virtual_screen
.normal_char_width
;
620 color
= virtual_screen
.fg_color
;
621 y
= (virtual_screen
.cursor_y
* virtual_screen
.normal_char_height
622 + grub_font_get_ascent (virtual_screen
.font
));
625 /* Render cursor to text layer. */
626 grub_video_set_active_render_target (text_layer
);
627 grub_video_fill_rect (color
, x
, y
, width
, height
);
628 grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY
);
630 /* Mark cursor to be redrawn. */
631 dirty_region_add (virtual_screen
.offset_x
+ x
,
632 virtual_screen
.offset_y
+ y
,
641 grub_video_color_t color
;
643 /* If we don't have background bitmap, remove cursor. */
649 /* Redraw only changed regions. */
650 dirty_region_redraw ();
653 /* Scroll text buffer with one line to up. */
654 grub_memmove (virtual_screen
.text_buffer
,
655 virtual_screen
.text_buffer
+ virtual_screen
.columns
,
656 sizeof (*virtual_screen
.text_buffer
)
657 * virtual_screen
.columns
658 * (virtual_screen
.rows
- 1));
660 /* Clear last line in text buffer. */
661 for (i
= virtual_screen
.columns
* (virtual_screen
.rows
- 1);
662 i
< virtual_screen
.columns
* virtual_screen
.rows
;
665 virtual_screen
.text_buffer
[i
].code
= ' ';
666 virtual_screen
.text_buffer
[i
].fg_color
= virtual_screen
.fg_color
;
667 virtual_screen
.text_buffer
[i
].bg_color
= virtual_screen
.bg_color
;
668 virtual_screen
.text_buffer
[i
].width
= 0;
669 virtual_screen
.text_buffer
[i
].index
= 0;
672 /* Scroll physical screen. */
673 grub_video_set_active_render_target (text_layer
);
674 color
= virtual_screen
.bg_color
;
675 grub_video_scroll (color
, 0, -virtual_screen
.normal_char_height
);
676 grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY
);
678 /* If we have bitmap, re-draw screen, otherwise scroll physical screen too. */
681 /* Mark virtual screen to be redrawn. */
682 dirty_region_add_virtualscreen ();
686 grub_video_rect_t saved_view
;
687 grub_video_set_active_render_target (render_target
);
688 /* Save viewport and set it to our window. */
689 grub_video_get_viewport ((unsigned *) &saved_view
.x
,
690 (unsigned *) &saved_view
.y
,
691 (unsigned *) &saved_view
.width
,
692 (unsigned *) &saved_view
.height
);
693 grub_video_set_viewport (window
.x
, window
.y
, window
.width
, window
.height
);
695 /* Clear new border area. */
696 grub_video_fill_rect (color
,
697 virtual_screen
.offset_x
, virtual_screen
.offset_y
,
698 virtual_screen
.width
, virtual_screen
.normal_char_height
);
700 /* Scroll physical screen. */
701 grub_video_scroll (color
, 0, -virtual_screen
.normal_char_height
);
703 /* Restore saved viewport. */
704 grub_video_set_viewport (saved_view
.x
, saved_view
.y
,
705 saved_view
.width
, saved_view
.height
);
706 grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY
);
708 /* Draw cursor if visible. */
709 if (virtual_screen
.cursor_state
)
713 if (repaint_callback
)
714 repaint_callback (window
.x
, window
.y
, window
.width
, window
.height
);
718 grub_gfxterm_putchar (grub_uint32_t c
)
724 /* Erase current cursor, if any. */
725 if (virtual_screen
.cursor_state
)
728 if (c
== '\b' || c
== '\n' || c
== '\r')
733 if (virtual_screen
.cursor_x
> 0)
734 virtual_screen
.cursor_x
--;
738 if (virtual_screen
.cursor_y
>= virtual_screen
.rows
- 1)
741 virtual_screen
.cursor_y
++;
745 virtual_screen
.cursor_x
= 0;
751 struct grub_font_glyph
*glyph
;
752 struct grub_colored_char
*p
;
753 unsigned char char_width
;
755 /* Get properties of the character. */
756 glyph
= grub_font_get_glyph (virtual_screen
.font
, c
);
758 /* Calculate actual character width for glyph. This is number of
759 times of normal_font_width. */
760 char_width
= calculate_character_width(glyph
);
762 /* If we are about to exceed line length, wrap to next line. */
763 if (virtual_screen
.cursor_x
+ char_width
> virtual_screen
.columns
)
766 /* Find position on virtual screen, and fill information. */
767 p
= (virtual_screen
.text_buffer
+
768 virtual_screen
.cursor_x
+
769 virtual_screen
.cursor_y
* virtual_screen
.columns
);
771 p
->fg_color
= virtual_screen
.fg_color
;
772 p
->bg_color
= virtual_screen
.bg_color
;
773 p
->width
= char_width
- 1;
776 /* If we have large glyph, add fixup info. */
781 for (i
= 1; i
< char_width
; i
++)
784 p
[i
].width
= char_width
- 1;
792 /* Make sure we scroll screen when needed and wrap line correctly. */
793 virtual_screen
.cursor_x
+= char_width
;
794 if (virtual_screen
.cursor_x
>= virtual_screen
.columns
)
796 virtual_screen
.cursor_x
= 0;
798 if (virtual_screen
.cursor_y
>= virtual_screen
.rows
- 1)
801 virtual_screen
.cursor_y
++;
805 /* Redraw cursor if it should be visible. */
806 /* Note: This will redraw the character as well, which means that the
807 above call to write_char is redundant when the cursor is showing. */
808 if (virtual_screen
.cursor_state
)
812 /* Use ASCII characters to determine normal character width. */
814 calculate_normal_character_width (grub_font_t font
)
816 struct grub_font_glyph
*glyph
;
817 unsigned int width
= 0;
820 /* Get properties of every printable ASCII character. */
821 for (i
= 32; i
< 127; i
++)
823 glyph
= grub_font_get_glyph (font
, i
);
825 /* Skip unknown characters. Should never happen on normal conditions. */
829 if (glyph
->device_width
> width
)
830 width
= glyph
->device_width
;
837 calculate_character_width (struct grub_font_glyph
*glyph
)
839 if (! glyph
|| glyph
->device_width
== 0)
842 return (glyph
->device_width
843 + (virtual_screen
.normal_char_width
- 1))
844 / virtual_screen
.normal_char_width
;
848 grub_gfxterm_getcharwidth (grub_uint32_t c
__attribute__((unused
)))
850 struct grub_font_glyph
*glyph
;
851 unsigned char char_width
;
853 /* Get properties of the character. */
854 glyph
= grub_font_get_glyph (virtual_screen
.font
, c
);
856 /* Calculate actual character width for glyph. */
857 char_width
= calculate_character_width (glyph
);
863 grub_virtual_screen_getwh (void)
865 return (virtual_screen
.columns
<< 8) | virtual_screen
.rows
;
869 grub_virtual_screen_getxy (void)
871 return ((virtual_screen
.cursor_x
<< 8) | virtual_screen
.cursor_y
);
875 grub_gfxterm_gotoxy (grub_uint8_t x
, grub_uint8_t y
)
877 if (x
>= virtual_screen
.columns
)
878 x
= virtual_screen
.columns
- 1;
880 if (y
>= virtual_screen
.rows
)
881 y
= virtual_screen
.rows
- 1;
883 /* Erase current cursor, if any. */
884 if (virtual_screen
.cursor_state
)
887 virtual_screen
.cursor_x
= x
;
888 virtual_screen
.cursor_y
= y
;
890 /* Draw cursor if visible. */
891 if (virtual_screen
.cursor_state
)
896 grub_virtual_screen_cls (void)
900 for (i
= 0; i
< virtual_screen
.columns
* virtual_screen
.rows
; i
++)
902 virtual_screen
.text_buffer
[i
].code
= ' ';
903 virtual_screen
.text_buffer
[i
].fg_color
= virtual_screen
.fg_color
;
904 virtual_screen
.text_buffer
[i
].bg_color
= virtual_screen
.bg_color
;
905 virtual_screen
.text_buffer
[i
].width
= 0;
906 virtual_screen
.text_buffer
[i
].index
= 0;
909 virtual_screen
.cursor_x
= virtual_screen
.cursor_y
= 0;
913 grub_gfxterm_cls (void)
915 grub_video_color_t color
;
917 /* Clear virtual screen. */
918 grub_virtual_screen_cls ();
920 /* Clear text layer. */
921 grub_video_set_active_render_target (text_layer
);
922 color
= virtual_screen
.bg_color
;
923 grub_video_fill_rect (color
, 0, 0,
924 virtual_screen
.width
, virtual_screen
.height
);
925 grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY
);
927 /* Mark virtual screen to be redrawn. */
928 dirty_region_add_virtualscreen ();
932 grub_virtual_screen_setcolorstate (grub_term_color_state state
)
936 case GRUB_TERM_COLOR_STANDARD
:
937 virtual_screen
.term_color
= virtual_screen
.standard_color_setting
;
940 case GRUB_TERM_COLOR_NORMAL
:
941 virtual_screen
.term_color
= virtual_screen
.normal_color_setting
;
944 case GRUB_TERM_COLOR_HIGHLIGHT
:
945 virtual_screen
.term_color
= virtual_screen
.highlight_color_setting
;
952 /* Change color to virtual terminal. */
953 set_term_color (virtual_screen
.term_color
);
957 grub_virtual_screen_setcolor (grub_uint8_t normal_color
,
958 grub_uint8_t highlight_color
)
960 virtual_screen
.normal_color_setting
= normal_color
;
961 virtual_screen
.highlight_color_setting
= highlight_color
;
965 grub_virtual_screen_getcolor (grub_uint8_t
*normal_color
,
966 grub_uint8_t
*highlight_color
)
968 *normal_color
= virtual_screen
.normal_color_setting
;
969 *highlight_color
= virtual_screen
.highlight_color_setting
;
973 grub_gfxterm_setcursor (int on
)
975 if (virtual_screen
.cursor_state
!= on
)
977 if (virtual_screen
.cursor_state
)
982 virtual_screen
.cursor_state
= on
;
987 grub_gfxterm_refresh (void)
989 /* Redraw only changed regions. */
990 dirty_region_redraw ();
994 grub_gfxterm_set_repaint_callback (grub_gfxterm_repaint_callback_t func
)
996 repaint_callback
= func
;
999 /* Option array indices. */
1000 #define BACKGROUND_CMD_ARGINDEX_MODE 0
1002 static const struct grub_arg_option background_image_cmd_options
[] =
1004 {"mode", 'm', 0, "Background image mode (`stretch', `normal').", 0,
1010 grub_gfxterm_background_image_cmd (grub_extcmd_t cmd
,
1014 struct grub_arg_list
*state
= cmd
->state
;
1016 /* Check that we have video adapter active. */
1017 if (grub_video_get_info(NULL
) != GRUB_ERR_NONE
)
1020 /* Destroy existing background bitmap if loaded. */
1023 grub_video_bitmap_destroy (bitmap
);
1026 /* Mark whole screen as dirty. */
1027 dirty_region_reset ();
1028 dirty_region_add (0, 0, window
.width
, window
.height
);
1031 /* If filename was provided, try to load that. */
1034 /* Try to load new one. */
1035 grub_video_bitmap_load (&bitmap
, args
[0]);
1036 if (grub_errno
!= GRUB_ERR_NONE
)
1039 /* Determine if the bitmap should be scaled to fit the screen. */
1040 if (!state
[BACKGROUND_CMD_ARGINDEX_MODE
].set
1041 || grub_strcmp (state
[BACKGROUND_CMD_ARGINDEX_MODE
].arg
,
1044 if (window
.width
!= (int) grub_video_bitmap_get_width (bitmap
)
1045 || window
.height
!= (int) grub_video_bitmap_get_height (bitmap
))
1047 struct grub_video_bitmap
*scaled_bitmap
;
1048 grub_video_bitmap_create_scaled (&scaled_bitmap
,
1052 GRUB_VIDEO_BITMAP_SCALE_METHOD_BEST
);
1053 if (grub_errno
== GRUB_ERR_NONE
)
1055 /* Replace the original bitmap with the scaled one. */
1056 grub_video_bitmap_destroy (bitmap
);
1057 bitmap
= scaled_bitmap
;
1063 /* If bitmap was loaded correctly, display it. */
1066 /* Determine bitmap dimensions. */
1067 bitmap_width
= grub_video_bitmap_get_width (bitmap
);
1068 bitmap_height
= grub_video_bitmap_get_height (bitmap
);
1070 /* Mark whole screen as dirty. */
1071 dirty_region_reset ();
1072 dirty_region_add (0, 0, window
.width
, window
.height
);
1077 grub_errno
= GRUB_ERR_NONE
;
1081 static struct grub_term_output grub_video_term
=
1084 .init
= grub_gfxterm_init
,
1085 .fini
= grub_gfxterm_fini
,
1086 .putchar
= grub_gfxterm_putchar
,
1087 .getcharwidth
= grub_gfxterm_getcharwidth
,
1088 .getwh
= grub_virtual_screen_getwh
,
1089 .getxy
= grub_virtual_screen_getxy
,
1090 .gotoxy
= grub_gfxterm_gotoxy
,
1091 .cls
= grub_gfxterm_cls
,
1092 .setcolorstate
= grub_virtual_screen_setcolorstate
,
1093 .setcolor
= grub_virtual_screen_setcolor
,
1094 .getcolor
= grub_virtual_screen_getcolor
,
1095 .setcursor
= grub_gfxterm_setcursor
,
1096 .refresh
= grub_gfxterm_refresh
,
1102 grub_gfxterm_get_term (void)
1104 return &grub_video_term
;
1107 static grub_extcmd_t background_image_cmd_handle
;
1109 GRUB_MOD_INIT(term_gfxterm
)
1113 grub_term_register_output ("gfxterm", &grub_video_term
);
1114 background_image_cmd_handle
=
1115 grub_register_extcmd ("background_image",
1116 grub_gfxterm_background_image_cmd
,
1117 GRUB_COMMAND_FLAG_BOTH
,
1118 "background_image [-m (stretch|normal)] FILE",
1119 "Load background image for active terminal.",
1120 background_image_cmd_options
);
1123 GRUB_MOD_FINI(term_gfxterm
)
1125 grub_unregister_extcmd (background_image_cmd_handle
);
1126 grub_term_unregister_output (&grub_video_term
);