1 /* ----------------------------------------------------------------------- *
3 * Copyright 2006-2008 H. Peter Anvin - All Rights Reserved
5 * Permission is hereby granted, free of charge, to any person
6 * obtaining a copy of this software and associated documentation
7 * files (the "Software"), to deal in the Software without
8 * restriction, including without limitation the rights to use,
9 * copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom
11 * the Software is furnished to do so, subject to the following
14 * The above copyright notice and this permission notice shall
15 * be included in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
19 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24 * OTHER DEALINGS IN THE SOFTWARE.
26 * ----------------------------------------------------------------------- */
36 * Visible cursor information
38 static uint8_t cursor_pattern
[FONT_MAX_HEIGHT
];
39 static struct vesa_char
*cursor_pointer
= NULL
;
40 static int cursor_x
, cursor_y
;
42 static inline void *copy_dword(void *dst
, void *src
, size_t dword_count
)
44 asm volatile ("rep; movsl":"+D" (dst
), "+S"(src
), "+c"(dword_count
));
45 return dst
; /* Updated destination pointer */
48 static inline __attribute__ ((always_inline
))
49 uint8_t alpha_val(uint8_t fg
, uint8_t bg
, uint8_t alpha
)
53 tmp
= __vesacon_srgb_to_linear
[fg
] * alpha
;
54 tmp
+= __vesacon_srgb_to_linear
[bg
] * (255 - alpha
);
56 return __vesacon_linear_to_srgb
[tmp
>> 12];
59 static uint32_t alpha_pixel(uint32_t fg
, uint32_t bg
)
61 uint8_t alpha
= fg
>> 24;
62 uint8_t fg_r
= fg
>> 16;
63 uint8_t fg_g
= fg
>> 8;
65 uint8_t bg_r
= bg
>> 16;
66 uint8_t bg_g
= bg
>> 8;
70 (alpha_val(fg_r
, bg_r
, alpha
) << 16) |
71 (alpha_val(fg_g
, bg_g
, alpha
) << 8) | (alpha_val(fg_b
, bg_b
, alpha
));
74 static void vesacon_update_characters(int row
, int col
, int nrows
, int ncols
)
76 const int height
= __vesacon_font_height
;
77 const int width
= FONT_WIDTH
;
78 uint32_t *bgrowptr
, *bgptr
, bgval
, fgval
;
79 uint32_t fgcolor
= 0, bgcolor
= 0, color
;
80 uint8_t chbits
= 0, chxbits
= 0, chsbits
= 0;
81 int i
, j
, jx
, pixrow
, pixsrow
;
82 struct vesa_char
*rowptr
, *rowsptr
, *cptr
, *csptr
;
83 unsigned int bytes_per_pixel
= __vesacon_bytes_per_pixel
;
84 unsigned long pixel_offset
;
85 uint32_t row_buffer
[__vesa_info
.mi
.h_res
], *rowbufptr
;
89 pixel_offset
= ((row
* height
+ VIDEO_BORDER
) * __vesa_info
.mi
.h_res
) +
90 (col
* width
+ VIDEO_BORDER
);
92 bgrowptr
= &__vesacon_background
[pixel_offset
];
93 fbrowptr
= (row
* height
+ VIDEO_BORDER
) * __vesa_info
.mi
.logical_scan
+
94 (col
* width
+ VIDEO_BORDER
) * bytes_per_pixel
;
96 /* Note that we keep a 1-character guard area around the real text area... */
97 rowptr
= &__vesacon_text_display
[(row
+1)*(__vesacon_text_cols
+2)+(col
+1)];
98 rowsptr
= rowptr
- ((__vesacon_text_cols
+2)+1);
100 pixsrow
= height
- 1;
102 for (i
= height
* nrows
; i
>= 0; i
--) {
104 rowbufptr
= row_buffer
;
109 chsbits
= __vesacon_graphics_font
[csptr
->ch
][pixsrow
];
110 if (__unlikely(csptr
== cursor_pointer
))
111 chsbits
|= cursor_pattern
[pixsrow
];
112 sha
= console_color_table
[csptr
->attr
].shadow
;
113 chsbits
&= (sha
& 0x02) ? 0xff : 0x00;
114 chsbits
^= (sha
& 0x01) ? 0xff : 0x00;
115 chsbits
<<= (width
- 2);
118 /* Draw two pixels beyond the end of the line. One for the shadow,
119 and one to make sure we have a whole dword of data for the copy
120 operation at the end. Note that this code depends on the fact that
121 all characters begin on dword boundaries in the frame buffer. */
123 for (jx
= 1, j
= width
* ncols
+ 1; j
>= 0; j
--) {
130 chbits
= __vesacon_graphics_font
[cptr
->ch
][pixrow
];
131 if (__unlikely(cptr
== cursor_pointer
))
132 chbits
|= cursor_pattern
[pixrow
];
133 sha
= console_color_table
[cptr
->attr
].shadow
;
135 chxbits
&= (sha
& 0x02) ? 0xff : 0x00;
136 chxbits
^= (sha
& 0x01) ? 0xff : 0x00;
137 fgcolor
= console_color_table
[cptr
->attr
].argb_fg
;
138 bgcolor
= console_color_table
[cptr
->attr
].argb_bg
;
143 chsbits
= __vesacon_graphics_font
[csptr
->ch
][pixsrow
];
144 if (__unlikely(csptr
== cursor_pointer
))
145 chsbits
|= cursor_pattern
[pixsrow
];
146 sha
= console_color_table
[csptr
->attr
].shadow
;
147 chsbits
&= (sha
& 0x02) ? 0xff : 0x00;
148 chsbits
^= (sha
& 0x01) ? 0xff : 0x00;
157 /* If this pixel is raised, use the offsetted value */
158 bgval
= (chxbits
& 0x80)
159 ? bgptr
[__vesa_info
.mi
.h_res
+ 1] : *bgptr
;
162 /* If this pixel is set, use the fg color, else the bg color */
163 fgval
= (chbits
& 0x80) ? fgcolor
: bgcolor
;
165 /* Produce the combined color pixel value */
166 color
= alpha_pixel(fgval
, bgval
);
168 /* Apply the shadow (75% shadow) */
169 if ((chsbits
& ~chxbits
) & 0x80) {
174 *rowbufptr
++ = color
;
177 /* Copy to frame buffer */
178 __vesacon_copy_to_screen(fbrowptr
, row_buffer
, rowbufptr
- row_buffer
);
180 bgrowptr
+= __vesa_info
.mi
.h_res
;
181 fbrowptr
+= __vesa_info
.mi
.logical_scan
;
183 if (++pixrow
== height
) {
184 rowptr
+= __vesacon_text_cols
+ 2;
187 if (++pixsrow
== height
) {
188 rowsptr
+= __vesacon_text_cols
+ 2;
194 /* Bounding box for changed text. The (x1, y1) coordinates are +1! */
195 static unsigned int upd_x0
= -1U, upd_x1
, upd_y0
= -1U, upd_y1
;
197 /* Update the range already touched by various variables */
198 void __vesacon_doit(void)
200 if (upd_x1
> upd_x0
&& upd_y1
> upd_y0
) {
201 vesacon_update_characters(upd_y0
, upd_x0
, upd_y1
- upd_y0
,
203 upd_x0
= upd_y0
= -1U;
208 /* Mark a range for update; note argument sequence is the same as
209 vesacon_update_characters() */
210 static inline void vesacon_touch(int row
, int col
, int rows
, int cols
)
212 unsigned int y0
= row
;
213 unsigned int x0
= col
;
214 unsigned int y1
= y0
+ rows
;
215 unsigned int x1
= x0
+ cols
;
227 /* Erase a region of the screen */
228 void __vesacon_erase(int x0
, int y0
, int x1
, int y1
, attr_t attr
)
231 struct vesa_char
*ptr
= &__vesacon_text_display
232 [(y0
+ 1) * (__vesacon_text_cols
+ 2) + (x0
+ 1)];
233 struct vesa_char fill
= {
237 int ncols
= x1
- x0
+ 1;
239 for (y
= y0
; y
<= y1
; y
++) {
240 vesacon_fill(ptr
, fill
, ncols
);
241 ptr
+= __vesacon_text_cols
+ 2;
244 vesacon_touch(y0
, x0
, y1
- y0
+ 1, ncols
);
247 /* Scroll the screen up */
248 void __vesacon_scroll_up(int nrows
, attr_t attr
)
250 struct vesa_char
*fromptr
= &__vesacon_text_display
251 [(nrows
+ 1) * (__vesacon_text_cols
+ 2)];
252 struct vesa_char
*toptr
= &__vesacon_text_display
253 [(__vesacon_text_cols
+ 2)];
255 (__vesacon_text_rows
- nrows
) * (__vesacon_text_cols
+ 2);
256 struct vesa_char fill
= {
261 toptr
= copy_dword(toptr
, fromptr
, dword_count
);
263 dword_count
= nrows
* (__vesacon_text_cols
+ 2);
265 vesacon_fill(toptr
, fill
, dword_count
);
267 vesacon_touch(0, 0, __vesacon_text_rows
, __vesacon_text_cols
);
270 /* Draw one character text at a specific area of the screen */
271 void __vesacon_write_char(int x
, int y
, uint8_t ch
, attr_t attr
)
273 struct vesa_char
*ptr
= &__vesacon_text_display
274 [(y
+ 1) * (__vesacon_text_cols
+ 2) + (x
+ 1)];
279 vesacon_touch(y
, x
, 1, 1);
282 void __vesacon_set_cursor(int x
, int y
, bool visible
)
284 struct vesa_char
*ptr
= &__vesacon_text_display
285 [(y
+ 1) * (__vesacon_text_cols
+ 2) + (x
+ 1)];
288 vesacon_touch(cursor_y
, cursor_x
, 1, 1);
291 /* Invisible cursor */
292 cursor_pointer
= NULL
;
294 cursor_pointer
= ptr
;
295 vesacon_touch(y
, x
, 1, 1);
302 void __vesacon_init_cursor(int font_height
)
304 int r0
= font_height
- (font_height
< 10 ? 2 : 3);
309 memset(cursor_pattern
, 0, font_height
);
310 cursor_pattern
[r0
] = 0xff;
311 cursor_pattern
[r0
+ 1] = 0xff;
314 void __vesacon_redraw_text(void)
316 vesacon_update_characters(0, 0, __vesacon_text_rows
, __vesacon_text_cols
);