1 /* ----------------------------------------------------------------------- *
3 * Copyright 2006 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 * ----------------------------------------------------------------------- */
34 * Linear alpha blending. Useless for anything that's actually
35 * depends on color accuracy (because of gamma), but it's fine for
38 * This algorithm is exactly equivalent to (alpha*fg+(255-alpha)*bg)/255
39 * for all 8-bit values, but is substantially faster.
41 static inline __attribute__((always_inline
))
42 uint8_t alpha_val(uint8_t fg
, uint8_t bg
, uint8_t alpha
)
44 unsigned int tmp
= 1 + alpha
*fg
+ (255-alpha
)*bg
;
45 return (tmp
+ (tmp
>> 8)) >> 8;
48 static uint32_t alpha_pixel(uint32_t fg
, uint32_t bg
)
50 uint8_t alpha
= fg
>> 24;
51 uint8_t fg_r
= fg
>> 16;
52 uint8_t fg_g
= fg
>> 8;
54 uint8_t bg_r
= bg
>> 16;
55 uint8_t bg_g
= bg
>> 8;
59 (alpha_val(fg_r
, bg_r
, alpha
) << 16)|
60 (alpha_val(fg_g
, bg_g
, alpha
) << 8)|
61 (alpha_val(fg_b
, bg_b
, alpha
));
64 static void vesacon_update_characters(int row
, int col
, int nrows
, int ncols
)
66 const int height
= __vesacon_font_height
;
67 const int width
= FONT_WIDTH
;
68 uint32_t *bgrowptr
, *bgptr
, *fbrowptr
, *fbptr
, bgval
, fgval
;
69 uint32_t fgcolor
= 0, bgcolor
= 0, color
;
70 uint8_t chbits
= 0, chxbits
= 0, chsbits
= 0;
71 int i
, j
, pixrow
, pixsrow
;
72 struct vesa_char
*rowptr
, *rowsptr
, *cptr
, *csptr
;
74 bgrowptr
= &__vesacon_background
[row
*height
+VIDEO_BORDER
][col
*width
+VIDEO_BORDER
];
75 fbrowptr
= ((uint32_t *)__vesa_info
.mi
.lfb_ptr
)+
76 ((row
*height
+VIDEO_BORDER
)*VIDEO_X_SIZE
)+(col
*width
+VIDEO_BORDER
);
78 /* Note that we keep a 1-character guard area around the real text area... */
79 rowptr
= &__vesacon_text_display
[(row
+1)*(TEXT_PIXEL_COLS
/FONT_WIDTH
+2)+(col
+1)];
80 rowsptr
= rowptr
- ((TEXT_PIXEL_COLS
/FONT_WIDTH
+2)+1);
84 for (i
= height
*nrows
; i
>= 0; i
--) {
91 chsbits
= __vesacon_graphics_font
[csptr
->ch
][pixsrow
];
92 chsbits
&= (csptr
->sha
& 0x02) ? 0xff : 0x00;
93 chsbits
^= (csptr
->sha
& 0x01) ? 0xff : 0x00;
97 for (j
= width
*ncols
; j
>= 0; j
--) {
102 switch (j
% FONT_WIDTH
) {
104 chbits
= __vesacon_graphics_font
[cptr
->ch
][pixrow
];
106 chxbits
&= (cptr
->sha
& 0x02) ? 0xff : 0x00;
107 chxbits
^= (cptr
->sha
& 0x01) ? 0xff : 0x00;
108 fgcolor
= console_color_table
[cptr
->attr
].argb_fg
;
109 bgcolor
= console_color_table
[cptr
->attr
].argb_bg
;
113 chsbits
= __vesacon_graphics_font
[csptr
->ch
][pixsrow
];
114 chsbits
&= (csptr
->sha
& 0x02) ? 0xff : 0x00;
115 chsbits
^= (csptr
->sha
& 0x01) ? 0xff : 0x00;
122 /* If this pixel is raised, use the offsetted value */
123 bgval
= (chxbits
& 0x80) ? bgptr
[VIDEO_X_SIZE
+1] : *bgptr
;
126 /* If this pixel is set, use the fg color, else the bg color */
127 fgval
= (chbits
& 0x80) ? fgcolor
: bgcolor
;
129 /* Produce the combined color pixel value */
130 color
= alpha_pixel(fgval
, bgval
);
132 /* Apply the shadow (75% shadow) */
133 if ((chsbits
& ~chxbits
) & 0x80) {
141 bgrowptr
+= VIDEO_X_SIZE
;
142 fbrowptr
+= VIDEO_X_SIZE
;
144 if (++pixrow
== height
) {
145 rowptr
+= TEXT_PIXEL_COLS
/FONT_WIDTH
+2;
148 if (++pixsrow
== height
) {
149 rowsptr
+= TEXT_PIXEL_COLS
/FONT_WIDTH
+2;
155 /* Fill a number of characters... */
156 static inline struct vesa_char
*vesacon_fill(struct vesa_char
*ptr
,
157 struct vesa_char fill
,
160 asm volatile("cld; rep; stosl"
161 : "+D" (ptr
), "+c" (count
)
168 /* Erase a region of the screen */
169 void __vesacon_erase(int x0
, int y0
, int x1
, int y1
, uint8_t attr
, int rev
)
172 struct vesa_char
*ptr
= &__vesacon_text_display
173 [(y0
+1)*(TEXT_PIXEL_COLS
/FONT_WIDTH
+2)+(x0
+1)];
174 struct vesa_char fill
= {
181 for (y
= y0
; y
<= y1
; y
++) {
182 vesacon_fill(ptr
, fill
, ncols
);
183 ptr
+= TEXT_PIXEL_COLS
/FONT_WIDTH
+2;
186 vesacon_update_characters(y0
, x0
, y1
-y0
+1, ncols
);
189 /* Scroll the screen up */
190 void __vesacon_scroll_up(int nrows
, uint8_t attr
, int rev
)
192 struct vesa_char
*fromptr
= &__vesacon_text_display
193 [(nrows
+1)*(TEXT_PIXEL_COLS
/FONT_WIDTH
+2)];
194 struct vesa_char
*toptr
= &__vesacon_text_display
195 [(TEXT_PIXEL_COLS
/FONT_WIDTH
+2)];
196 int dword_count
= (__vesacon_text_rows
-nrows
)*(TEXT_PIXEL_COLS
/FONT_WIDTH
+2);
197 struct vesa_char fill
= {
203 asm volatile("cld ; rep ; movsl"
204 : "+D" (toptr
), "+S" (fromptr
), "+c" (dword_count
));
206 dword_count
= nrows
*(TEXT_PIXEL_COLS
/FONT_WIDTH
+2);
208 /* Danger, Will Robinson: this is wrong if rev != SHADOW_NORMAL */
209 vesacon_fill(toptr
, fill
, dword_count
);
211 vesacon_update_characters(0, 0, __vesacon_text_rows
,
212 TEXT_PIXEL_COLS
/FONT_WIDTH
);
215 /* Draw text at a specific area of the screen */
216 void __vesacon_write_at(int x
, int y
, const char *str
,
217 uint8_t attr
, int rev
)
220 struct vesa_char
*ptr
= &__vesacon_text_display
221 [(y
+1)*(TEXT_PIXEL_COLS
/FONT_WIDTH
+2)+(x
+1)];
233 vesacon_update_characters(y
, x
, 1, n
);
236 /* Draw one character text at a specific area of the screen */
237 void __vesacon_write_char(int x
, int y
, char ch
, uint8_t attr
, int rev
)
239 struct vesa_char
*ptr
= &__vesacon_text_display
240 [(y
+1)*(TEXT_PIXEL_COLS
/FONT_WIDTH
+2)+(x
+1)];
246 vesacon_update_characters(y
, x
, 1, 1);