1 /* ----------------------------------------------------------------------- *
3 * Copyright 2006-2007 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("cld; rep; movsl"
45 : "+D" (dst
), "+S" (src
), "+c" (dword_count
));
46 return dst
; /* Updated destination pointer */
49 static inline __attribute__((always_inline
))
50 uint8_t alpha_val(uint8_t fg
, uint8_t bg
, uint8_t alpha
)
54 tmp
= __vesacon_srgb_to_linear
[fg
] * alpha
;
55 tmp
+= __vesacon_srgb_to_linear
[bg
] * (255-alpha
);
57 return __vesacon_linear_to_srgb
[tmp
>> 12];
60 static uint32_t alpha_pixel(uint32_t fg
, uint32_t bg
)
62 uint8_t alpha
= fg
>> 24;
63 uint8_t fg_r
= fg
>> 16;
64 uint8_t fg_g
= fg
>> 8;
66 uint8_t bg_r
= bg
>> 16;
67 uint8_t bg_g
= bg
>> 8;
71 (alpha_val(fg_r
, bg_r
, alpha
) << 16)|
72 (alpha_val(fg_g
, bg_g
, alpha
) << 8)|
73 (alpha_val(fg_b
, bg_b
, alpha
));
76 static void vesacon_update_characters(int row
, int col
, int nrows
, int ncols
)
78 const int height
= __vesacon_font_height
;
79 const int width
= FONT_WIDTH
;
80 uint32_t *bgrowptr
, *bgptr
, bgval
, fgval
;
81 uint32_t fgcolor
= 0, bgcolor
= 0, color
;
82 uint8_t chbits
= 0, chxbits
= 0, chsbits
= 0;
83 int i
, j
, jx
, pixrow
, pixsrow
;
84 struct vesa_char
*rowptr
, *rowsptr
, *cptr
, *csptr
;
85 unsigned int bytes_per_pixel
= __vesacon_bytes_per_pixel
;
86 unsigned long pixel_offset
;
87 uint8_t row_buffer
[VIDEO_X_SIZE
*4], *rowbufptr
;
91 bgrowptr
= &__vesacon_background
[row
*height
+VIDEO_BORDER
][col
*width
+VIDEO_BORDER
];
93 pixel_offset
= ((row
*height
+VIDEO_BORDER
)*VIDEO_X_SIZE
)+
94 (col
*width
+VIDEO_BORDER
);
96 switch (__vesacon_pixel_format
) {
103 case PXF_LE_RGB16_565
:
111 fbrowptr
= ((uint8_t *)__vesa_info
.mi
.lfb_ptr
) +
112 (row
*height
+VIDEO_BORDER
) * __vesa_info
.mi
.logical_scan
+
113 (col
*width
+VIDEO_BORDER
) * bytes_per_pixel
;
115 /* Note that we keep a 1-character guard area around the real text area... */
116 rowptr
= &__vesacon_text_display
[(row
+1)*(TEXT_PIXEL_COLS
/FONT_WIDTH
+2)+(col
+1)];
117 rowsptr
= rowptr
- ((TEXT_PIXEL_COLS
/FONT_WIDTH
+2)+1);
121 for (i
= height
*nrows
; i
>= 0; i
--) {
123 rowbufptr
= row_buffer
;
128 chsbits
= __vesacon_graphics_font
[csptr
->ch
][pixsrow
];
129 if (__unlikely(csptr
== cursor_pointer
))
130 chsbits
|= cursor_pattern
[pixsrow
];
131 sha
= console_color_table
[csptr
->attr
].shadow
;
132 chsbits
&= (sha
& 0x02) ? 0xff : 0x00;
133 chsbits
^= (sha
& 0x01) ? 0xff : 0x00;
134 chsbits
<<= (width
-2);
137 /* Draw two pixels beyond the end of the line. One for the shadow,
138 and one to make sure we have a whole dword of data for the copy
139 operation at the end. Note that this code depends on the fact that
140 all characters begin on dword boundaries in the frame buffer. */
142 for (jx
= 1, j
= width
*ncols
+1; j
>= 0; j
--) {
149 chbits
= __vesacon_graphics_font
[cptr
->ch
][pixrow
];
150 if (__unlikely(cptr
== cursor_pointer
))
151 chbits
|= cursor_pattern
[pixrow
];
152 sha
= console_color_table
[cptr
->attr
].shadow
;
154 chxbits
&= (sha
& 0x02) ? 0xff : 0x00;
155 chxbits
^= (sha
& 0x01) ? 0xff : 0x00;
156 fgcolor
= console_color_table
[cptr
->attr
].argb_fg
;
157 bgcolor
= console_color_table
[cptr
->attr
].argb_bg
;
162 chsbits
= __vesacon_graphics_font
[csptr
->ch
][pixsrow
];
163 if (__unlikely(csptr
== cursor_pointer
))
164 chsbits
|= cursor_pattern
[pixsrow
];
165 sha
= console_color_table
[csptr
->attr
].shadow
;
166 chsbits
&= (sha
& 0x02) ? 0xff : 0x00;
167 chsbits
^= (sha
& 0x01) ? 0xff : 0x00;
176 /* If this pixel is raised, use the offsetted value */
177 bgval
= (chxbits
& 0x80) ? bgptr
[VIDEO_X_SIZE
+1] : *bgptr
;
180 /* If this pixel is set, use the fg color, else the bg color */
181 fgval
= (chbits
& 0x80) ? fgcolor
: bgcolor
;
183 /* Produce the combined color pixel value */
184 color
= alpha_pixel(fgval
, bgval
);
186 /* Apply the shadow (75% shadow) */
187 if ((chsbits
& ~chxbits
) & 0x80) {
192 rowbufptr
= format_pixel(rowbufptr
, color
, __vesacon_pixel_format
);
195 /* Copy to frame buffer */
196 /* Note that the dword_count is rounded down, not up. That's because
197 the row_buffer includes a spillover pixel. */
198 copy_dword(fbrowptr
, row_buffer
, (rowbufptr
-row_buffer
) >> 2);
200 bgrowptr
+= VIDEO_X_SIZE
;
201 fbrowptr
+= __vesa_info
.mi
.logical_scan
;
203 if (++pixrow
== height
) {
204 rowptr
+= TEXT_PIXEL_COLS
/FONT_WIDTH
+2;
207 if (++pixsrow
== height
) {
208 rowsptr
+= TEXT_PIXEL_COLS
/FONT_WIDTH
+2;
214 /* Bounding box for changed text. The (x1, y1) coordinates are +1! */
215 static unsigned int upd_x0
= -1U, upd_x1
, upd_y0
= -1U, upd_y1
;
217 /* Update the range already touched by various variables */
218 void __vesacon_doit(void)
220 if (upd_x1
> upd_x0
&& upd_y1
> upd_y0
) {
221 vesacon_update_characters(upd_y0
, upd_x0
, upd_y1
-upd_y0
, upd_x1
-upd_x0
);
222 upd_x0
= upd_y0
= -1U;
227 /* Mark a range for update; note argument sequence is the same as
228 vesacon_update_characters() */
229 static inline void vesacon_touch(int row
, int col
, int rows
, int cols
)
231 unsigned int y0
= row
;
232 unsigned int x0
= col
;
233 unsigned int y1
= y0
+rows
;
234 unsigned int x1
= x0
+cols
;
246 /* Erase a region of the screen */
247 void __vesacon_erase(int x0
, int y0
, int x1
, int y1
, attr_t attr
)
250 struct vesa_char
*ptr
= &__vesacon_text_display
251 [(y0
+1)*(TEXT_PIXEL_COLS
/FONT_WIDTH
+2)+(x0
+1)];
252 struct vesa_char fill
= {
258 for (y
= y0
; y
<= y1
; y
++) {
259 vesacon_fill(ptr
, fill
, ncols
);
260 ptr
+= TEXT_PIXEL_COLS
/FONT_WIDTH
+2;
263 vesacon_touch(y0
, x0
, y1
-y0
+1, ncols
);
266 /* Scroll the screen up */
267 void __vesacon_scroll_up(int nrows
, attr_t attr
)
269 struct vesa_char
*fromptr
= &__vesacon_text_display
270 [(nrows
+1)*(TEXT_PIXEL_COLS
/FONT_WIDTH
+2)];
271 struct vesa_char
*toptr
= &__vesacon_text_display
272 [(TEXT_PIXEL_COLS
/FONT_WIDTH
+2)];
273 int dword_count
= (__vesacon_text_rows
-nrows
)*(TEXT_PIXEL_COLS
/FONT_WIDTH
+2);
274 struct vesa_char fill
= {
279 toptr
= copy_dword(toptr
, fromptr
, dword_count
);
281 dword_count
= nrows
*(TEXT_PIXEL_COLS
/FONT_WIDTH
+2);
283 vesacon_fill(toptr
, fill
, dword_count
);
285 vesacon_touch(0, 0, __vesacon_text_rows
, TEXT_PIXEL_COLS
/FONT_WIDTH
);
288 /* Draw one character text at a specific area of the screen */
289 void __vesacon_write_char(int x
, int y
, uint8_t ch
, attr_t attr
)
291 struct vesa_char
*ptr
= &__vesacon_text_display
292 [(y
+1)*(TEXT_PIXEL_COLS
/FONT_WIDTH
+2)+(x
+1)];
297 vesacon_touch(y
, x
, 1, 1);
300 void __vesacon_set_cursor(int x
, int y
, int visible
)
302 struct vesa_char
*ptr
= &__vesacon_text_display
303 [(y
+1)*(TEXT_PIXEL_COLS
/FONT_WIDTH
+2)+(x
+1)];
306 vesacon_touch(cursor_y
, cursor_x
, 1, 1);
309 /* Invisible cursor */
310 cursor_pointer
= NULL
;
312 cursor_pointer
= ptr
;
313 vesacon_touch(y
, x
, 1, 1);
320 void __vesacon_init_cursor(int font_height
)
322 int r0
= font_height
- (font_height
< 10 ? 2 : 3);
327 /* cursor_pattern is assumed to be all zero */
328 cursor_pattern
[r0
] = 0xff;
329 cursor_pattern
[r0
+1] = 0xff;
332 void __vesacon_redraw_text(void)
334 vesacon_update_characters(0, 0, __vesacon_text_rows
,
335 TEXT_PIXEL_COLS
/FONT_WIDTH
);