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 * ----------------------------------------------------------------------- */
35 * Visible cursor information
37 static uint8_t cursor_pattern
[FONT_MAX_HEIGHT
];
38 static struct vesa_char
*cursor_pointer
= NULL
;
39 static int cursor_x
, cursor_y
;
41 static inline void *copy_dword(void *dst
, void *src
, size_t dword_count
)
43 asm volatile("cld; rep; movsl"
44 : "+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)|
72 (alpha_val(fg_b
, bg_b
, alpha
));
75 static void vesacon_update_characters(int row
, int col
, int nrows
, int ncols
)
77 const int height
= __vesacon_font_height
;
78 const int width
= FONT_WIDTH
;
79 uint32_t *bgrowptr
, *bgptr
, bgval
, fgval
;
80 uint32_t fgcolor
= 0, bgcolor
= 0, color
;
81 uint8_t chbits
= 0, chxbits
= 0, chsbits
= 0;
82 int i
, j
, jx
, pixrow
, pixsrow
;
83 struct vesa_char
*rowptr
, *rowsptr
, *cptr
, *csptr
;
84 unsigned int bytes_per_pixel
= __vesacon_bytes_per_pixel
;
85 unsigned long pixel_offset
;
86 uint32_t row_buffer
[VIDEO_X_SIZE
], *rowbufptr
;
90 bgrowptr
= &__vesacon_background
[row
*height
+VIDEO_BORDER
][col
*width
+VIDEO_BORDER
];
92 pixel_offset
= ((row
*height
+VIDEO_BORDER
)*VIDEO_X_SIZE
)+
93 (col
*width
+VIDEO_BORDER
);
95 fbrowptr
= (row
*height
+VIDEO_BORDER
) * __vesa_info
.mi
.logical_scan
+
96 (col
*width
+VIDEO_BORDER
) * bytes_per_pixel
;
98 /* Note that we keep a 1-character guard area around the real text area... */
99 rowptr
= &__vesacon_text_display
[(row
+1)*(TEXT_PIXEL_COLS
/FONT_WIDTH
+2)+(col
+1)];
100 rowsptr
= rowptr
- ((TEXT_PIXEL_COLS
/FONT_WIDTH
+2)+1);
104 for (i
= height
*nrows
; i
>= 0; i
--) {
106 rowbufptr
= row_buffer
;
111 chsbits
= __vesacon_graphics_font
[csptr
->ch
][pixsrow
];
112 if (__unlikely(csptr
== cursor_pointer
))
113 chsbits
|= cursor_pattern
[pixsrow
];
114 sha
= console_color_table
[csptr
->attr
].shadow
;
115 chsbits
&= (sha
& 0x02) ? 0xff : 0x00;
116 chsbits
^= (sha
& 0x01) ? 0xff : 0x00;
117 chsbits
<<= (width
-2);
120 /* Draw two pixels beyond the end of the line. One for the shadow,
121 and one to make sure we have a whole dword of data for the copy
122 operation at the end. Note that this code depends on the fact that
123 all characters begin on dword boundaries in the frame buffer. */
125 for (jx
= 1, j
= width
*ncols
+1; j
>= 0; j
--) {
132 chbits
= __vesacon_graphics_font
[cptr
->ch
][pixrow
];
133 if (__unlikely(cptr
== cursor_pointer
))
134 chbits
|= cursor_pattern
[pixrow
];
135 sha
= console_color_table
[cptr
->attr
].shadow
;
137 chxbits
&= (sha
& 0x02) ? 0xff : 0x00;
138 chxbits
^= (sha
& 0x01) ? 0xff : 0x00;
139 fgcolor
= console_color_table
[cptr
->attr
].argb_fg
;
140 bgcolor
= console_color_table
[cptr
->attr
].argb_bg
;
145 chsbits
= __vesacon_graphics_font
[csptr
->ch
][pixsrow
];
146 if (__unlikely(csptr
== cursor_pointer
))
147 chsbits
|= cursor_pattern
[pixsrow
];
148 sha
= console_color_table
[csptr
->attr
].shadow
;
149 chsbits
&= (sha
& 0x02) ? 0xff : 0x00;
150 chsbits
^= (sha
& 0x01) ? 0xff : 0x00;
159 /* If this pixel is raised, use the offsetted value */
160 bgval
= (chxbits
& 0x80) ? bgptr
[VIDEO_X_SIZE
+1] : *bgptr
;
163 /* If this pixel is set, use the fg color, else the bg color */
164 fgval
= (chbits
& 0x80) ? fgcolor
: bgcolor
;
166 /* Produce the combined color pixel value */
167 color
= alpha_pixel(fgval
, bgval
);
169 /* Apply the shadow (75% shadow) */
170 if ((chsbits
& ~chxbits
) & 0x80) {
175 *rowbufptr
++ = color
;
178 /* Copy to frame buffer */
179 __vesacon_copy_to_screen(fbrowptr
, row_buffer
, rowbufptr
-row_buffer
);
181 bgrowptr
+= VIDEO_X_SIZE
;
182 fbrowptr
+= __vesa_info
.mi
.logical_scan
;
184 if (++pixrow
== height
) {
185 rowptr
+= TEXT_PIXEL_COLS
/FONT_WIDTH
+2;
188 if (++pixsrow
== height
) {
189 rowsptr
+= TEXT_PIXEL_COLS
/FONT_WIDTH
+2;
195 /* Bounding box for changed text. The (x1, y1) coordinates are +1! */
196 static unsigned int upd_x0
= -1U, upd_x1
, upd_y0
= -1U, upd_y1
;
198 /* Update the range already touched by various variables */
199 void __vesacon_doit(void)
201 if (upd_x1
> upd_x0
&& upd_y1
> upd_y0
) {
202 vesacon_update_characters(upd_y0
, upd_x0
, upd_y1
-upd_y0
, upd_x1
-upd_x0
);
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)*(TEXT_PIXEL_COLS
/FONT_WIDTH
+2)+(x0
+1)];
233 struct vesa_char fill
= {
239 for (y
= y0
; y
<= y1
; y
++) {
240 vesacon_fill(ptr
, fill
, ncols
);
241 ptr
+= TEXT_PIXEL_COLS
/FONT_WIDTH
+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)*(TEXT_PIXEL_COLS
/FONT_WIDTH
+2)];
252 struct vesa_char
*toptr
= &__vesacon_text_display
253 [(TEXT_PIXEL_COLS
/FONT_WIDTH
+2)];
254 int dword_count
= (__vesacon_text_rows
-nrows
)*(TEXT_PIXEL_COLS
/FONT_WIDTH
+2);
255 struct vesa_char fill
= {
260 toptr
= copy_dword(toptr
, fromptr
, dword_count
);
262 dword_count
= nrows
*(TEXT_PIXEL_COLS
/FONT_WIDTH
+2);
264 vesacon_fill(toptr
, fill
, dword_count
);
266 vesacon_touch(0, 0, __vesacon_text_rows
, TEXT_PIXEL_COLS
/FONT_WIDTH
);
269 /* Draw one character text at a specific area of the screen */
270 void __vesacon_write_char(int x
, int y
, uint8_t ch
, attr_t attr
)
272 struct vesa_char
*ptr
= &__vesacon_text_display
273 [(y
+1)*(TEXT_PIXEL_COLS
/FONT_WIDTH
+2)+(x
+1)];
278 vesacon_touch(y
, x
, 1, 1);
281 void __vesacon_set_cursor(int x
, int y
, int visible
)
283 struct vesa_char
*ptr
= &__vesacon_text_display
284 [(y
+1)*(TEXT_PIXEL_COLS
/FONT_WIDTH
+2)+(x
+1)];
287 vesacon_touch(cursor_y
, cursor_x
, 1, 1);
290 /* Invisible cursor */
291 cursor_pointer
= NULL
;
293 cursor_pointer
= ptr
;
294 vesacon_touch(y
, x
, 1, 1);
301 void __vesacon_init_cursor(int font_height
)
303 int r0
= font_height
- (font_height
< 10 ? 2 : 3);
308 /* cursor_pattern is assumed to be all zero */
309 cursor_pattern
[r0
] = 0xff;
310 cursor_pattern
[r0
+1] = 0xff;
313 void __vesacon_redraw_text(void)
315 vesacon_update_characters(0, 0, __vesacon_text_rows
,
316 TEXT_PIXEL_COLS
/FONT_WIDTH
);