Adding upstream version 3.30~pre4.
[syslinux-debian/hramrach.git] / com32 / lib / sys / vesa / drawtxt.c
blob820fc40e683f7ba2d5779c87974f94c11d7aa766
1 /* ----------------------------------------------------------------------- *
2 *
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
12 * conditions:
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 * ----------------------------------------------------------------------- */
28 #include <inttypes.h>
29 #include <colortbl.h>
30 #include "vesa.h"
31 #include "video.h"
34 * Linear alpha blending. Useless for anything that's actually
35 * depends on color accuracy (because of gamma), but it's fine for
36 * what we want.
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;
53 uint8_t fg_b = fg;
54 uint8_t bg_r = bg >> 16;
55 uint8_t bg_g = bg >> 8;
56 uint8_t bg_b = bg;
58 return
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);
81 pixrow = 0;
82 pixsrow = height-1;
84 for (i = height*nrows; i >= 0; i--) {
85 bgptr = bgrowptr;
86 fbptr = fbrowptr;
88 cptr = rowptr;
89 csptr = rowsptr;
91 chsbits = __vesacon_graphics_font[csptr->ch][pixsrow];
92 chsbits &= (csptr->sha & 0x02) ? 0xff : 0x00;
93 chsbits ^= (csptr->sha & 0x01) ? 0xff : 0x00;
94 chsbits <<= 6;
95 csptr++;
97 for (j = width*ncols; j >= 0; j--) {
98 chbits <<= 1;
99 chsbits <<= 1;
100 chxbits <<= 1;
102 switch (j % FONT_WIDTH) {
103 case 0:
104 chbits = __vesacon_graphics_font[cptr->ch][pixrow];
105 chxbits = chbits;
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;
110 cptr++;
111 break;
112 case FONT_WIDTH-1:
113 chsbits = __vesacon_graphics_font[csptr->ch][pixsrow];
114 chsbits &= (csptr->sha & 0x02) ? 0xff : 0x00;
115 chsbits ^= (csptr->sha & 0x01) ? 0xff : 0x00;
116 csptr++;
117 break;
118 default:
119 break;
122 /* If this pixel is raised, use the offsetted value */
123 bgval = (chxbits & 0x80) ? bgptr[VIDEO_X_SIZE+1] : *bgptr;
124 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) {
134 color >>= 2;
135 color &= 0x3f3f3f;
138 *fbptr++ = color;
141 bgrowptr += VIDEO_X_SIZE;
142 fbrowptr += VIDEO_X_SIZE;
144 if (++pixrow == height) {
145 rowptr += TEXT_PIXEL_COLS/FONT_WIDTH+2;
146 pixrow = 0;
148 if (++pixsrow == height) {
149 rowsptr += TEXT_PIXEL_COLS/FONT_WIDTH+2;
150 pixsrow = 0;
155 /* Fill a number of characters... */
156 static inline struct vesa_char *vesacon_fill(struct vesa_char *ptr,
157 struct vesa_char fill,
158 unsigned int count)
160 asm volatile("cld; rep; stosl"
161 : "+D" (ptr), "+c" (count)
162 : "a" (fill)
163 : "memory");
165 return ptr;
168 /* Erase a region of the screen */
169 void __vesacon_erase(int x0, int y0, int x1, int y1, uint8_t attr, int rev)
171 int y;
172 struct vesa_char *ptr = &__vesacon_text_display
173 [(y0+1)*(TEXT_PIXEL_COLS/FONT_WIDTH+2)+(x0+1)];
174 struct vesa_char fill = {
175 .ch = ' ',
176 .attr = attr,
177 .sha = rev
179 int ncols = x1-x0+1;
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 = {
198 .ch = ' ',
199 .attr = attr,
200 .sha = rev,
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)
219 int n = 0;
220 struct vesa_char *ptr = &__vesacon_text_display
221 [(y+1)*(TEXT_PIXEL_COLS/FONT_WIDTH+2)+(x+1)];
223 while (*str) {
224 ptr->ch = *str;
225 ptr->attr = attr;
226 ptr->sha = rev;
228 n++;
229 str++;
230 ptr++;
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)];
242 ptr->ch = ch;
243 ptr->attr = attr;
244 ptr->sha = rev;
246 vesacon_update_characters(y, x, 1, 1);