source: bootcd/isolinux/syslinux-6.03/com32/lib/sys/vesa/drawtxt.c @ e16e8f2

Last change on this file since e16e8f2 was e16e8f2, checked in by Edwin Eefting <edwin@datux.nl>, 3 years ago

bootstuff

  • Property mode set to 100644
File size: 8.9 KB
Line 
1/* ----------------------------------------------------------------------- *
2 *
3 *   Copyright 2006-2008 H. Peter Anvin - All Rights Reserved
4 *
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:
13 *
14 *   The above copyright notice and this permission notice shall
15 *   be included in all copies or substantial portions of the Software.
16 *
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.
25 *
26 * ----------------------------------------------------------------------- */
27
28#include <inttypes.h>
29#include <colortbl.h>
30#include <string.h>
31#include "vesa.h"
32#include "video.h"
33#include "fill.h"
34
35/*
36 * Visible cursor information
37 */
38static uint8_t cursor_pattern[FONT_MAX_HEIGHT];
39static struct vesa_char *cursor_pointer = NULL;
40static int cursor_x, cursor_y;
41
42static inline void *copy_dword(void *dst, void *src, size_t dword_count)
43{
44    asm volatile ("rep; movsl":"+D" (dst), "+S"(src), "+c"(dword_count));
45    return dst;                 /* Updated destination pointer */
46}
47
48static inline __attribute__ ((always_inline))
49uint8_t alpha_val(uint8_t fg, uint8_t bg, uint8_t alpha)
50{
51    unsigned int tmp;
52
53    tmp = __vesacon_srgb_to_linear[fg] * alpha;
54    tmp += __vesacon_srgb_to_linear[bg] * (255 - alpha);
55
56    return __vesacon_linear_to_srgb[tmp >> 12];
57}
58
59static uint32_t alpha_pixel(uint32_t fg, uint32_t bg)
60{
61    uint8_t alpha = fg >> 24;
62    uint8_t fg_r = fg >> 16;
63    uint8_t fg_g = fg >> 8;
64    uint8_t fg_b = fg;
65    uint8_t bg_r = bg >> 16;
66    uint8_t bg_g = bg >> 8;
67    uint8_t bg_b = bg;
68
69    return
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));
72}
73
74static void vesacon_update_characters(int row, int col, int nrows, int ncols)
75{
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;
86    size_t fbrowptr;
87    uint8_t sha;
88
89    pixel_offset = ((row * height + VIDEO_BORDER) * __vesa_info.mi.h_res) +
90        (col * width + VIDEO_BORDER);
91
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;
95
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);
99    pixrow = 0;
100    pixsrow = height - 1;
101
102    for (i = height * nrows; i >= 0; i--) {
103        bgptr = bgrowptr;
104        rowbufptr = row_buffer;
105
106        cptr = rowptr;
107        csptr = rowsptr;
108
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);
116        csptr++;
117
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. */
122
123        for (jx = 1, j = width * ncols + 1; j >= 0; j--) {
124            chbits <<= 1;
125            chsbits <<= 1;
126            chxbits <<= 1;
127
128            switch (jx) {
129            case 1:
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;
134                chxbits = chbits;
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;
139                cptr++;
140                jx--;
141                break;
142            case 0:
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;
149                csptr++;
150                jx = width - 1;
151                break;
152            default:
153                jx--;
154                break;
155            }
156
157            /* If this pixel is raised, use the offsetted value */
158            bgval = (chxbits & 0x80)
159                ? bgptr[__vesa_info.mi.h_res + 1] : *bgptr;
160            bgptr++;
161
162            /* If this pixel is set, use the fg color, else the bg color */
163            fgval = (chbits & 0x80) ? fgcolor : bgcolor;
164
165            /* Produce the combined color pixel value */
166            color = alpha_pixel(fgval, bgval);
167
168            /* Apply the shadow (75% shadow) */
169            if ((chsbits & ~chxbits) & 0x80) {
170                color >>= 2;
171                color &= 0x3f3f3f;
172            }
173
174            *rowbufptr++ = color;
175        }
176
177        /* Copy to frame buffer */
178        __vesacon_copy_to_screen(fbrowptr, row_buffer, rowbufptr - row_buffer);
179
180        bgrowptr += __vesa_info.mi.h_res;
181        fbrowptr += __vesa_info.mi.logical_scan;
182
183        if (++pixrow == height) {
184            rowptr += __vesacon_text_cols + 2;
185            pixrow = 0;
186        }
187        if (++pixsrow == height) {
188            rowsptr += __vesacon_text_cols + 2;
189            pixsrow = 0;
190        }
191    }
192}
193
194/* Bounding box for changed text.  The (x1, y1) coordinates are +1! */
195static unsigned int upd_x0 = -1U, upd_x1, upd_y0 = -1U, upd_y1;
196
197/* Update the range already touched by various variables */
198void __vesacon_doit(void)
199{
200    if (upd_x1 > upd_x0 && upd_y1 > upd_y0) {
201        vesacon_update_characters(upd_y0, upd_x0, upd_y1 - upd_y0,
202                                  upd_x1 - upd_x0);
203        upd_x0 = upd_y0 = -1U;
204        upd_x1 = upd_y1 = 0;
205    }
206}
207
208/* Mark a range for update; note argument sequence is the same as
209   vesacon_update_characters() */
210static inline void vesacon_touch(int row, int col, int rows, int cols)
211{
212    unsigned int y0 = row;
213    unsigned int x0 = col;
214    unsigned int y1 = y0 + rows;
215    unsigned int x1 = x0 + cols;
216
217    if (y0 < upd_y0)
218        upd_y0 = y0;
219    if (y1 > upd_y1)
220        upd_y1 = y1;
221    if (x0 < upd_x0)
222        upd_x0 = x0;
223    if (x1 > upd_x1)
224        upd_x1 = x1;
225}
226
227/* Erase a region of the screen */
228void __vesacon_erase(int x0, int y0, int x1, int y1, attr_t attr)
229{
230    int y;
231    struct vesa_char *ptr = &__vesacon_text_display
232        [(y0 + 1) * (__vesacon_text_cols + 2) + (x0 + 1)];
233    struct vesa_char fill = {
234        .ch = ' ',
235        .attr = attr,
236    };
237    int ncols = x1 - x0 + 1;
238
239    for (y = y0; y <= y1; y++) {
240        vesacon_fill(ptr, fill, ncols);
241        ptr += __vesacon_text_cols + 2;
242    }
243
244    vesacon_touch(y0, x0, y1 - y0 + 1, ncols);
245}
246
247/* Scroll the screen up */
248void __vesacon_scroll_up(int nrows, attr_t attr)
249{
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)];
254    int dword_count =
255        (__vesacon_text_rows - nrows) * (__vesacon_text_cols + 2);
256    struct vesa_char fill = {
257        .ch = ' ',
258        .attr = attr,
259    };
260
261    toptr = copy_dword(toptr, fromptr, dword_count);
262
263    dword_count = nrows * (__vesacon_text_cols + 2);
264
265    vesacon_fill(toptr, fill, dword_count);
266
267    vesacon_touch(0, 0, __vesacon_text_rows, __vesacon_text_cols);
268}
269
270/* Draw one character text at a specific area of the screen */
271void __vesacon_write_char(int x, int y, uint8_t ch, attr_t attr)
272{
273    struct vesa_char *ptr = &__vesacon_text_display
274        [(y + 1) * (__vesacon_text_cols + 2) + (x + 1)];
275
276    ptr->ch = ch;
277    ptr->attr = attr;
278
279    vesacon_touch(y, x, 1, 1);
280}
281
282void __vesacon_set_cursor(int x, int y, bool visible)
283{
284    struct vesa_char *ptr = &__vesacon_text_display
285        [(y + 1) * (__vesacon_text_cols + 2) + (x + 1)];
286
287    if (cursor_pointer)
288        vesacon_touch(cursor_y, cursor_x, 1, 1);
289
290    if (!visible) {
291        /* Invisible cursor */
292        cursor_pointer = NULL;
293    } else {
294        cursor_pointer = ptr;
295        vesacon_touch(y, x, 1, 1);
296    }
297
298    cursor_x = x;
299    cursor_y = y;
300}
301
302void __vesacon_init_cursor(int font_height)
303{
304    int r0 = font_height - (font_height < 10 ? 2 : 3);
305
306    if (r0 < 0)
307        r0 = 0;
308
309    memset(cursor_pattern, 0, font_height);
310    cursor_pattern[r0] = 0xff;
311    cursor_pattern[r0 + 1] = 0xff;
312}
313
314void __vesacon_redraw_text(void)
315{
316    vesacon_update_characters(0, 0, __vesacon_text_rows, __vesacon_text_cols);
317}
Note: See TracBrowser for help on using the repository browser.