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/bitmap.h>
28 #include <grub/command.h>
30 #define DEFAULT_VIDEO_WIDTH 640
31 #define DEFAULT_VIDEO_HEIGHT 480
32 #define DEFAULT_VIDEO_FLAGS 0
34 #define DEFAULT_BORDER_WIDTH 10
36 #define DEFAULT_STANDARD_COLOR 0x07
37 #define DEFAULT_NORMAL_COLOR 0x07
38 #define DEFAULT_HIGHLIGHT_COLOR 0x70
40 struct grub_dirty_region
48 struct grub_colored_char
50 /* An Unicode codepoint. */
54 grub_video_color_t fg_color
;
55 grub_video_color_t bg_color
;
57 /* The width of this character minus one. */
60 /* The column index of this character. */
64 struct grub_virtual_screen
66 /* Dimensions of the virtual screen in pixels. */
70 /* Offset in the display in pixels. */
71 unsigned int offset_x
;
72 unsigned int offset_y
;
74 /* TTY Character sizes in pixes. */
75 unsigned int normal_char_width
;
76 unsigned int normal_char_height
;
78 /* Virtual screen TTY size in characters. */
82 /* Current cursor location in characters. */
83 unsigned int cursor_x
;
84 unsigned int cursor_y
;
86 /* Current cursor state. */
92 /* Terminal color settings. */
93 grub_uint8_t standard_color_setting
;
94 grub_uint8_t normal_color_setting
;
95 grub_uint8_t highlight_color_setting
;
96 grub_uint8_t term_color
;
99 grub_video_color_t fg_color
;
100 grub_video_color_t bg_color
;
102 /* Text buffer for virtual screen. Contains (columns * rows) number
104 struct grub_colored_char
*text_buffer
;
107 static struct grub_virtual_screen virtual_screen
;
109 static grub_dl_t my_mod
;
110 static struct grub_video_mode_info mode_info
;
112 static struct grub_video_render_target
*text_layer
;
114 static unsigned int bitmap_width
;
115 static unsigned int bitmap_height
;
116 static struct grub_video_bitmap
*bitmap
;
118 static struct grub_dirty_region dirty_region
;
120 static void dirty_region_reset (void);
122 static int dirty_region_is_empty (void);
124 static void dirty_region_add (int x
, int y
,
125 unsigned int width
, unsigned int height
);
127 static unsigned int calculate_normal_character_width (grub_font_t font
);
129 static unsigned char calculate_character_width (struct grub_font_glyph
*glyph
);
132 set_term_color (grub_uint8_t term_color
)
134 struct grub_video_render_target
*old_target
;
136 /* Save previous target and switch to text layer. */
137 grub_video_get_active_render_target (&old_target
);
138 grub_video_set_active_render_target (text_layer
);
140 /* Map terminal color to text layer compatible video colors. */
141 virtual_screen
.fg_color
= grub_video_map_color(term_color
& 0x0f);
143 /* Special case: use black as transparent color. */
144 if (((term_color
>> 4) & 0x0f) == 0)
146 virtual_screen
.bg_color
= grub_video_map_rgba(0, 0, 0, 0);
150 virtual_screen
.bg_color
= grub_video_map_color((term_color
>> 4) & 0x0f);
153 /* Restore previous target. */
154 grub_video_set_active_render_target (old_target
);
158 grub_virtual_screen_free (void)
160 /* If virtual screen has been allocated, free it. */
161 if (virtual_screen
.text_buffer
!= 0)
162 grub_free (virtual_screen
.text_buffer
);
164 /* Reset virtual screen data. */
165 grub_memset (&virtual_screen
, 0, sizeof (virtual_screen
));
167 /* Free render targets. */
168 grub_video_delete_render_target (text_layer
);
173 grub_virtual_screen_setup (unsigned int x
, unsigned int y
,
174 unsigned int width
, unsigned int height
,
175 const char *font_name
)
177 /* Free old virtual screen. */
178 grub_virtual_screen_free ();
180 /* Initialize with default data. */
181 virtual_screen
.font
= grub_font_get (font_name
);
182 if (!virtual_screen
.font
)
183 return grub_error (GRUB_ERR_BAD_FONT
,
185 virtual_screen
.width
= width
;
186 virtual_screen
.height
= height
;
187 virtual_screen
.offset_x
= x
;
188 virtual_screen
.offset_y
= y
;
189 virtual_screen
.normal_char_width
=
190 calculate_normal_character_width (virtual_screen
.font
);
191 virtual_screen
.normal_char_height
=
192 grub_font_get_max_char_height (virtual_screen
.font
);
193 virtual_screen
.cursor_x
= 0;
194 virtual_screen
.cursor_y
= 0;
195 virtual_screen
.cursor_state
= 1;
197 /* Calculate size of text buffer. */
198 virtual_screen
.columns
= virtual_screen
.width
/ virtual_screen
.normal_char_width
;
199 virtual_screen
.rows
= virtual_screen
.height
/ virtual_screen
.normal_char_height
;
201 /* Allocate memory for text buffer. */
202 virtual_screen
.text_buffer
=
203 (struct grub_colored_char
*) grub_malloc (virtual_screen
.columns
204 * virtual_screen
.rows
205 * sizeof (*virtual_screen
.text_buffer
));
206 if (grub_errno
!= GRUB_ERR_NONE
)
209 /* Create new render target for text layer. */
210 grub_video_create_render_target (&text_layer
,
211 virtual_screen
.width
,
212 virtual_screen
.height
,
213 GRUB_VIDEO_MODE_TYPE_RGB
214 | GRUB_VIDEO_MODE_TYPE_ALPHA
);
215 if (grub_errno
!= GRUB_ERR_NONE
)
218 /* As we want to have colors compatible with rendering target,
219 we can only have those after mode is initialized. */
220 grub_video_set_active_render_target (text_layer
);
222 virtual_screen
.standard_color_setting
= DEFAULT_STANDARD_COLOR
;
223 virtual_screen
.normal_color_setting
= DEFAULT_NORMAL_COLOR
;
224 virtual_screen
.highlight_color_setting
= DEFAULT_HIGHLIGHT_COLOR
;
226 virtual_screen
.term_color
= virtual_screen
.normal_color_setting
;
228 set_term_color (virtual_screen
.term_color
);
230 grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY
);
236 grub_gfxterm_init (void)
240 int width
= DEFAULT_VIDEO_WIDTH
;
241 int height
= DEFAULT_VIDEO_HEIGHT
;
243 int flags
= DEFAULT_VIDEO_FLAGS
;
244 grub_video_color_t color
;
246 /* Select the font to use. */
247 font_name
= grub_env_get ("gfxterm_font");
249 font_name
= ""; /* Allow fallback to any font. */
251 /* Parse gfxmode environment variable if set. */
252 modevar
= grub_env_get ("gfxmode");
262 /* Take copy of env.var. as we don't want to modify that. */
263 tmp
= grub_strdup (modevar
);
266 if (grub_errno
!= GRUB_ERR_NONE
)
269 /* Initialize next mode. */
272 /* Loop until all modes has been tested out. */
273 while (next_mode
!= NULL
)
275 /* Use last next_mode as current mode. */
278 /* Reset video mode settings. */
279 width
= DEFAULT_VIDEO_WIDTH
;
280 height
= DEFAULT_VIDEO_HEIGHT
;
282 flags
= DEFAULT_VIDEO_FLAGS
;
284 /* Save position of next mode and separate modes. */
285 next_mode
= grub_strchr(next_mode
, ';');
292 /* Skip whitespace. */
293 while (grub_isspace (*tmp
))
296 /* Initialize token holders. */
301 /* Parse <width>x<height>[x<depth>]*/
303 /* Find width value. */
305 param
= grub_strchr(param
, 'x');
310 /* First setup error message. */
311 rc
= grub_error (GRUB_ERR_BAD_ARGUMENT
,
312 "Invalid mode: %s\n",
315 /* Free memory before returning. */
324 width
= grub_strtoul (value
, 0, 0);
325 if (grub_errno
!= GRUB_ERR_NONE
)
329 /* First setup error message. */
330 rc
= grub_error (GRUB_ERR_BAD_ARGUMENT
,
331 "Invalid mode: %s\n",
334 /* Free memory before returning. */
340 /* Find height value. */
342 param
= grub_strchr(param
, 'x');
345 height
= grub_strtoul (value
, 0, 0);
346 if (grub_errno
!= GRUB_ERR_NONE
)
350 /* First setup error message. */
351 rc
= grub_error (GRUB_ERR_BAD_ARGUMENT
,
352 "Invalid mode: %s\n",
355 /* Free memory before returning. */
363 /* We have optional color depth value. */
367 height
= grub_strtoul (value
, 0, 0);
368 if (grub_errno
!= GRUB_ERR_NONE
)
372 /* First setup error message. */
373 rc
= grub_error (GRUB_ERR_BAD_ARGUMENT
,
374 "Invalid mode: %s\n",
377 /* Free memory before returning. */
383 /* Convert color depth value. */
385 depth
= grub_strtoul (value
, 0, 0);
386 if (grub_errno
!= GRUB_ERR_NONE
)
390 /* First setup error message. */
391 rc
= grub_error (GRUB_ERR_BAD_ARGUMENT
,
392 "Invalid mode: %s\n",
395 /* Free memory before returning. */
402 /* Try out video mode. */
404 /* If we have 8 or less bits, then assume that it is indexed color mode. */
405 if ((depth
<= 8) && (depth
!= -1))
406 flags
|= GRUB_VIDEO_MODE_TYPE_INDEX_COLOR
;
408 /* We have more than 8 bits, then assume that it is RGB color mode. */
410 flags
|= GRUB_VIDEO_MODE_TYPE_RGB
;
412 /* If user requested specific depth, forward that information to driver. */
414 flags
|= (depth
<< GRUB_VIDEO_MODE_TYPE_DEPTH_POS
)
415 & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK
;
417 /* Try to initialize requested mode. Ignore any errors. */
419 if (grub_video_setup (width
, height
, flags
) != GRUB_ERR_NONE
)
425 /* Figure out what mode we ended up. */
426 if (grub_video_get_info (&mode_info
) != GRUB_ERR_NONE
)
428 /* Couldn't get video mode info, restore old mode and continue to next one. */
431 grub_video_restore ();
435 /* Restore state of error stack. */
438 /* Mode found! Exit loop. */
447 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
448 "No suitable mode found.");
452 /* No gfxmode variable set, use defaults. */
454 /* If we have 8 or less bits, then assume that it is indexed color mode. */
455 if ((depth
<= 8) && (depth
!= -1))
456 flags
|= GRUB_VIDEO_MODE_TYPE_INDEX_COLOR
;
458 /* We have more than 8 bits, then assume that it is RGB color mode. */
460 flags
|= GRUB_VIDEO_MODE_TYPE_RGB
;
462 /* If user requested specific depth, forward that information to driver. */
464 flags
|= (depth
<< GRUB_VIDEO_MODE_TYPE_DEPTH_POS
)
465 & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK
;
467 /* Initialize user requested mode. */
468 if (grub_video_setup (width
, height
, flags
) != GRUB_ERR_NONE
)
471 /* Figure out what mode we ended up. */
472 if (grub_video_get_info (&mode_info
) != GRUB_ERR_NONE
)
474 grub_video_restore ();
479 /* Make sure screen is black. */
480 color
= grub_video_map_rgb (0, 0, 0);
481 grub_video_fill_rect (color
, 0, 0, mode_info
.width
, mode_info
.height
);
484 /* Leave borders for virtual screen. */
485 width
= mode_info
.width
- (2 * DEFAULT_BORDER_WIDTH
);
486 height
= mode_info
.height
- (2 * DEFAULT_BORDER_WIDTH
);
488 /* Create virtual screen. */
489 if (grub_virtual_screen_setup (DEFAULT_BORDER_WIDTH
, DEFAULT_BORDER_WIDTH
,
490 width
, height
, font_name
) != GRUB_ERR_NONE
)
492 grub_video_restore ();
496 /* Mark whole screen as dirty. */
497 dirty_region_reset ();
498 dirty_region_add (0, 0, mode_info
.width
, mode_info
.height
);
500 return (grub_errno
= GRUB_ERR_NONE
);
504 grub_gfxterm_fini (void)
508 grub_video_bitmap_destroy (bitmap
);
512 grub_virtual_screen_free ();
514 grub_video_restore ();
516 return GRUB_ERR_NONE
;
520 redraw_screen_rect (unsigned int x
, unsigned int y
,
521 unsigned int width
, unsigned int height
)
523 grub_video_color_t color
;
525 grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY
);
530 /* Render bitmap as background. */
531 grub_video_blit_bitmap (bitmap
, GRUB_VIDEO_BLIT_REPLACE
, x
, y
,
535 /* If bitmap is smaller than requested blit area, use background
537 color
= virtual_screen
.bg_color
;
539 /* Fill right side of the bitmap if needed. */
540 if ((x
+ width
>= bitmap_width
) && (y
< bitmap_height
))
542 int w
= (x
+ width
) - bitmap_width
;
546 if (y
+ height
>= bitmap_height
)
548 h
= bitmap_height
- y
;
551 if (bitmap_width
> tx
)
556 /* Render background layer. */
557 grub_video_fill_rect (color
, tx
, y
, w
, h
);
560 /* Fill bottom side of the bitmap if needed. */
561 if (y
+ height
>= bitmap_height
)
563 int h
= (y
+ height
) - bitmap_height
;
566 if (bitmap_height
> ty
)
571 /* Render background layer. */
572 grub_video_fill_rect (color
, x
, ty
, width
, h
);
575 /* Render text layer as blended. */
576 grub_video_blit_render_target (text_layer
, GRUB_VIDEO_BLIT_BLEND
, x
, y
,
577 x
- virtual_screen
.offset_x
,
578 y
- virtual_screen
.offset_y
,
583 /* Render background layer. */
584 color
= virtual_screen
.bg_color
;
585 grub_video_fill_rect (color
, x
, y
, width
, height
);
587 /* Render text layer as replaced (to get texts background color). */
588 grub_video_blit_render_target (text_layer
, GRUB_VIDEO_BLIT_REPLACE
, x
, y
,
589 x
- virtual_screen
.offset_x
,
590 y
- virtual_screen
.offset_y
,
596 dirty_region_reset (void)
598 dirty_region
.top_left_x
= -1;
599 dirty_region
.top_left_y
= -1;
600 dirty_region
.bottom_right_x
= -1;
601 dirty_region
.bottom_right_y
= -1;
605 dirty_region_is_empty (void)
607 if ((dirty_region
.top_left_x
== -1)
608 || (dirty_region
.top_left_y
== -1)
609 || (dirty_region
.bottom_right_x
== -1)
610 || (dirty_region
.bottom_right_y
== -1))
616 dirty_region_add (int x
, int y
, unsigned int width
, unsigned int height
)
618 if ((width
== 0) || (height
== 0))
621 if (dirty_region_is_empty ())
623 dirty_region
.top_left_x
= x
;
624 dirty_region
.top_left_y
= y
;
625 dirty_region
.bottom_right_x
= x
+ width
- 1;
626 dirty_region
.bottom_right_y
= y
+ height
- 1;
630 if (x
< dirty_region
.top_left_x
)
631 dirty_region
.top_left_x
= x
;
632 if (y
< dirty_region
.top_left_y
)
633 dirty_region
.top_left_y
= y
;
634 if ((x
+ (int)width
- 1) > dirty_region
.bottom_right_x
)
635 dirty_region
.bottom_right_x
= x
+ width
- 1;
636 if ((y
+ (int)height
- 1) > dirty_region
.bottom_right_y
)
637 dirty_region
.bottom_right_y
= y
+ height
- 1;
642 dirty_region_add_virtualscreen (void)
644 /* Mark virtual screen as dirty. */
645 dirty_region_add (virtual_screen
.offset_x
, virtual_screen
.offset_y
,
646 virtual_screen
.width
, virtual_screen
.height
);
651 dirty_region_redraw (void)
658 if (dirty_region_is_empty ())
661 x
= dirty_region
.top_left_x
;
662 y
= dirty_region
.top_left_y
;
664 width
= dirty_region
.bottom_right_x
- x
+ 1;
665 height
= dirty_region
.bottom_right_y
- y
+ 1;
667 redraw_screen_rect (x
, y
, width
, height
);
669 dirty_region_reset ();
675 struct grub_colored_char
*p
;
676 struct grub_font_glyph
*glyph
;
677 grub_video_color_t color
;
678 grub_video_color_t bgcolor
;
685 /* Find out active character. */
686 p
= (virtual_screen
.text_buffer
687 + virtual_screen
.cursor_x
688 + (virtual_screen
.cursor_y
* virtual_screen
.columns
));
692 /* Get glyph for character. */
693 glyph
= grub_font_get_glyph (virtual_screen
.font
, p
->code
);
694 ascent
= grub_font_get_ascent (virtual_screen
.font
);
696 width
= virtual_screen
.normal_char_width
* calculate_character_width(glyph
);
697 height
= virtual_screen
.normal_char_height
;
700 bgcolor
= p
->bg_color
;
702 x
= virtual_screen
.cursor_x
* virtual_screen
.normal_char_width
;
703 y
= virtual_screen
.cursor_y
* virtual_screen
.normal_char_height
;
705 /* Render glyph to text layer. */
706 grub_video_set_active_render_target (text_layer
);
707 grub_video_fill_rect (bgcolor
, x
, y
, width
, height
);
708 grub_font_draw_glyph (glyph
, color
, x
, y
+ ascent
);
709 grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY
);
711 /* Mark character to be drawn. */
712 dirty_region_add (virtual_screen
.offset_x
+ x
, virtual_screen
.offset_y
+ y
,
717 draw_cursor (int show
)
727 grub_video_color_t color
;
729 /* Determine cursor properties and position on text layer. */
730 x
= virtual_screen
.cursor_x
* virtual_screen
.normal_char_width
;
731 width
= virtual_screen
.normal_char_width
;
732 color
= virtual_screen
.fg_color
;
733 y
= (virtual_screen
.cursor_y
* virtual_screen
.normal_char_height
734 + grub_font_get_ascent (virtual_screen
.font
));
737 /* Render cursor to text layer. */
738 grub_video_set_active_render_target (text_layer
);
739 grub_video_fill_rect (color
, x
, y
, width
, height
);
740 grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY
);
742 /* Mark cursor to be redrawn. */
743 dirty_region_add (virtual_screen
.offset_x
+ x
,
744 virtual_screen
.offset_y
+ y
,
753 grub_video_color_t color
;
755 /* If we don't have background bitmap, remove cursor. */
761 /* Redraw only changed regions. */
762 dirty_region_redraw ();
765 /* Scroll text buffer with one line to up. */
766 grub_memmove (virtual_screen
.text_buffer
,
767 virtual_screen
.text_buffer
+ virtual_screen
.columns
,
768 sizeof (*virtual_screen
.text_buffer
)
769 * virtual_screen
.columns
770 * (virtual_screen
.rows
- 1));
772 /* Clear last line in text buffer. */
773 for (i
= virtual_screen
.columns
* (virtual_screen
.rows
- 1);
774 i
< virtual_screen
.columns
* virtual_screen
.rows
;
777 virtual_screen
.text_buffer
[i
].code
= ' ';
778 virtual_screen
.text_buffer
[i
].fg_color
= virtual_screen
.fg_color
;
779 virtual_screen
.text_buffer
[i
].bg_color
= virtual_screen
.bg_color
;
780 virtual_screen
.text_buffer
[i
].width
= 0;
781 virtual_screen
.text_buffer
[i
].index
= 0;
784 /* Scroll physical screen. */
785 grub_video_set_active_render_target (text_layer
);
786 color
= virtual_screen
.bg_color
;
787 grub_video_scroll (color
, 0, -virtual_screen
.normal_char_height
);
788 grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY
);
790 /* If we have bitmap, re-draw screen, otherwise scroll physical screen too. */
793 /* Mark virtual screen to be redrawn. */
794 dirty_region_add_virtualscreen ();
798 /* Clear new border area. */
799 grub_video_fill_rect (color
,
800 virtual_screen
.offset_x
, virtual_screen
.offset_y
,
801 virtual_screen
.width
, virtual_screen
.normal_char_height
);
803 /* Scroll physical screen. */
804 grub_video_scroll (color
, 0, -virtual_screen
.normal_char_height
);
806 /* Draw cursor if visible. */
807 if (virtual_screen
.cursor_state
)
813 grub_gfxterm_putchar (grub_uint32_t c
)
819 /* Erase current cursor, if any. */
820 if (virtual_screen
.cursor_state
)
823 if (c
== '\b' || c
== '\n' || c
== '\r')
828 if (virtual_screen
.cursor_x
> 0)
829 virtual_screen
.cursor_x
--;
833 if (virtual_screen
.cursor_y
>= virtual_screen
.rows
- 1)
836 virtual_screen
.cursor_y
++;
840 virtual_screen
.cursor_x
= 0;
846 struct grub_font_glyph
*glyph
;
847 struct grub_colored_char
*p
;
848 unsigned char char_width
;
850 /* Get properties of the character. */
851 glyph
= grub_font_get_glyph (virtual_screen
.font
, c
);
853 /* Calculate actual character width for glyph. This is number of
854 times of normal_font_width. */
855 char_width
= calculate_character_width(glyph
);
857 /* If we are about to exceed line length, wrap to next line. */
858 if (virtual_screen
.cursor_x
+ char_width
> virtual_screen
.columns
)
861 /* Find position on virtual screen, and fill information. */
862 p
= (virtual_screen
.text_buffer
+
863 virtual_screen
.cursor_x
+
864 virtual_screen
.cursor_y
* virtual_screen
.columns
);
866 p
->fg_color
= virtual_screen
.fg_color
;
867 p
->bg_color
= virtual_screen
.bg_color
;
868 p
->width
= char_width
- 1;
871 /* If we have large glyph, add fixup info. */
876 for (i
= 1; i
< char_width
; i
++)
879 p
[i
].width
= char_width
- 1;
887 /* Make sure we scroll screen when needed and wrap line correctly. */
888 virtual_screen
.cursor_x
+= char_width
;
889 if (virtual_screen
.cursor_x
>= virtual_screen
.columns
)
891 virtual_screen
.cursor_x
= 0;
893 if (virtual_screen
.cursor_y
>= virtual_screen
.rows
- 1)
896 virtual_screen
.cursor_y
++;
900 /* Redraw cursor if it should be visible. */
901 /* Note: This will redraw the character as well, which means that the
902 above call to write_char is redundant when the cursor is showing. */
903 if (virtual_screen
.cursor_state
)
907 /* Use ASCII characters to determine normal character width. */
909 calculate_normal_character_width (grub_font_t font
)
911 struct grub_font_glyph
*glyph
;
912 unsigned int width
= 0;
915 /* Get properties of every printable ASCII character. */
916 for (i
= 32; i
< 127; i
++)
918 glyph
= grub_font_get_glyph (font
, i
);
920 /* Skip unknown characters. Should never happen on normal conditions. */
924 if (glyph
->device_width
> width
)
925 width
= glyph
->device_width
;
932 calculate_character_width (struct grub_font_glyph
*glyph
)
934 if (! glyph
|| glyph
->device_width
== 0)
937 return (glyph
->device_width
938 + (virtual_screen
.normal_char_width
- 1))
939 / virtual_screen
.normal_char_width
;
943 grub_gfxterm_getcharwidth (grub_uint32_t c
)
945 struct grub_font_glyph
*glyph
;
946 unsigned char char_width
;
948 /* Get properties of the character. */
949 glyph
= grub_font_get_glyph (virtual_screen
.font
, c
);
951 /* Calculate actual character width for glyph. */
952 char_width
= calculate_character_width (glyph
);
958 grub_virtual_screen_getwh (void)
960 return (virtual_screen
.columns
<< 8) | virtual_screen
.rows
;
964 grub_virtual_screen_getxy (void)
966 return ((virtual_screen
.cursor_x
<< 8) | virtual_screen
.cursor_y
);
970 grub_gfxterm_gotoxy (grub_uint8_t x
, grub_uint8_t y
)
972 if (x
>= virtual_screen
.columns
)
973 x
= virtual_screen
.columns
- 1;
975 if (y
>= virtual_screen
.rows
)
976 y
= virtual_screen
.rows
- 1;
978 /* Erase current cursor, if any. */
979 if (virtual_screen
.cursor_state
)
982 virtual_screen
.cursor_x
= x
;
983 virtual_screen
.cursor_y
= y
;
985 /* Draw cursor if visible. */
986 if (virtual_screen
.cursor_state
)
991 grub_virtual_screen_cls (void)
995 for (i
= 0; i
< virtual_screen
.columns
* virtual_screen
.rows
; i
++)
997 virtual_screen
.text_buffer
[i
].code
= ' ';
998 virtual_screen
.text_buffer
[i
].fg_color
= virtual_screen
.fg_color
;
999 virtual_screen
.text_buffer
[i
].bg_color
= virtual_screen
.bg_color
;
1000 virtual_screen
.text_buffer
[i
].width
= 0;
1001 virtual_screen
.text_buffer
[i
].index
= 0;
1004 virtual_screen
.cursor_x
= virtual_screen
.cursor_y
= 0;
1008 grub_gfxterm_cls (void)
1010 grub_video_color_t color
;
1012 /* Clear virtual screen. */
1013 grub_virtual_screen_cls ();
1015 /* Clear text layer. */
1016 grub_video_set_active_render_target (text_layer
);
1017 color
= virtual_screen
.bg_color
;
1018 grub_video_fill_rect (color
, 0, 0, mode_info
.width
, mode_info
.height
);
1019 grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY
);
1021 /* Mark virtual screen to be redrawn. */
1022 dirty_region_add_virtualscreen ();
1026 grub_virtual_screen_setcolorstate (grub_term_color_state state
)
1030 case GRUB_TERM_COLOR_STANDARD
:
1031 virtual_screen
.term_color
= virtual_screen
.standard_color_setting
;
1034 case GRUB_TERM_COLOR_NORMAL
:
1035 virtual_screen
.term_color
= virtual_screen
.normal_color_setting
;
1038 case GRUB_TERM_COLOR_HIGHLIGHT
:
1039 virtual_screen
.term_color
= virtual_screen
.highlight_color_setting
;
1046 /* Change color to virtual terminal. */
1047 set_term_color (virtual_screen
.term_color
);
1051 grub_virtual_screen_setcolor (grub_uint8_t normal_color
,
1052 grub_uint8_t highlight_color
)
1054 virtual_screen
.normal_color_setting
= normal_color
;
1055 virtual_screen
.highlight_color_setting
= highlight_color
;
1059 grub_virtual_screen_getcolor (grub_uint8_t
*normal_color
,
1060 grub_uint8_t
*highlight_color
)
1062 *normal_color
= virtual_screen
.normal_color_setting
;
1063 *highlight_color
= virtual_screen
.highlight_color_setting
;
1067 grub_gfxterm_setcursor (int on
)
1069 if (virtual_screen
.cursor_state
!= on
)
1071 if (virtual_screen
.cursor_state
)
1076 virtual_screen
.cursor_state
= on
;
1081 grub_gfxterm_refresh (void)
1083 /* Redraw only changed regions. */
1084 dirty_region_redraw ();
1088 grub_gfxterm_background_image_cmd (grub_command_t cmd
__attribute__ ((unused
)),
1092 /* Check that we have video adapter active. */
1093 if (grub_video_get_info(NULL
) != GRUB_ERR_NONE
)
1096 /* Destroy existing background bitmap if loaded. */
1099 grub_video_bitmap_destroy (bitmap
);
1102 /* Mark whole screen as dirty. */
1103 dirty_region_reset ();
1104 dirty_region_add (0, 0, mode_info
.width
, mode_info
.height
);
1107 /* If filename was provided, try to load that. */
1110 /* Try to load new one. */
1111 grub_video_bitmap_load (&bitmap
, args
[0]);
1112 if (grub_errno
!= GRUB_ERR_NONE
)
1115 /* If bitmap was loaded correctly, display it. */
1118 /* Determine bitmap dimensions. */
1119 bitmap_width
= grub_video_bitmap_get_width (bitmap
);
1120 bitmap_height
= grub_video_bitmap_get_width (bitmap
);
1122 /* Mark whole screen as dirty. */
1123 dirty_region_reset ();
1124 dirty_region_add (0, 0, mode_info
.width
, mode_info
.height
);
1129 grub_errno
= GRUB_ERR_NONE
;
1133 static struct grub_term_output grub_video_term
=
1136 .init
= grub_gfxterm_init
,
1137 .fini
= grub_gfxterm_fini
,
1138 .putchar
= grub_gfxterm_putchar
,
1139 .getcharwidth
= grub_gfxterm_getcharwidth
,
1140 .getwh
= grub_virtual_screen_getwh
,
1141 .getxy
= grub_virtual_screen_getxy
,
1142 .gotoxy
= grub_gfxterm_gotoxy
,
1143 .cls
= grub_gfxterm_cls
,
1144 .setcolorstate
= grub_virtual_screen_setcolorstate
,
1145 .setcolor
= grub_virtual_screen_setcolor
,
1146 .getcolor
= grub_virtual_screen_getcolor
,
1147 .setcursor
= grub_gfxterm_setcursor
,
1148 .refresh
= grub_gfxterm_refresh
,
1153 static grub_command_t cmd
;
1155 GRUB_MOD_INIT(term_gfxterm
)
1158 grub_term_register_output ("gfxterm", &grub_video_term
);
1159 cmd
= grub_register_command ("background_image",
1160 grub_gfxterm_background_image_cmd
,
1161 0, "Load background image for active terminal");
1164 GRUB_MOD_FINI(term_gfxterm
)
1166 grub_unregister_command (cmd
);
1167 grub_term_unregister_output (&grub_video_term
);