Rev 3742 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 3742 | Rev 3745 | ||
---|---|---|---|
Line 69... | Line 69... | ||
69 | #define MAX_ANIM_LEN 8 |
69 | #define MAX_ANIM_LEN 8 |
70 | #define MAX_ANIMATIONS 4 |
70 | #define MAX_ANIMATIONS 4 |
71 | #define MAX_PIXMAPS 256 /**< Maximum number of saved pixmaps */ |
71 | #define MAX_PIXMAPS 256 /**< Maximum number of saved pixmaps */ |
72 | #define MAX_VIEWPORTS 128 /**< Viewport is a rectangular area on the screen */ |
72 | #define MAX_VIEWPORTS 128 /**< Viewport is a rectangular area on the screen */ |
73 | 73 | ||
- | 74 | /** Function to render a pixel from a RGB value. */ |
|
74 | typedef void (*rgb_conv_t)(void *, uint32_t); |
75 | typedef void (*rgb_conv_t)(void *, uint32_t); |
75 | 76 | ||
- | 77 | /** Function to draw a glyph. */ |
|
- | 78 | typedef void (*dg_t)(unsigned int x, unsigned int y, bool cursor, |
|
- | 79 | uint8_t *glyphs, uint8_t glyph, uint32_t fg_color, uint32_t bg_color); |
|
- | 80 | ||
76 | struct { |
81 | struct { |
77 | uint8_t *fb_addr; |
82 | uint8_t *fb_addr; |
78 | 83 | ||
79 | unsigned int xres; |
84 | unsigned int xres; |
80 | unsigned int yres; |
85 | unsigned int yres; |
Line 97... | Line 102... | ||
97 | 102 | ||
98 | /* Text support in window */ |
103 | /* Text support in window */ |
99 | unsigned int cols; |
104 | unsigned int cols; |
100 | unsigned int rows; |
105 | unsigned int rows; |
101 | 106 | ||
- | 107 | /* |
|
102 | /* Style and glyphs for text printing */ |
108 | * Style and glyphs for text printing |
- | 109 | */ |
|
- | 110 | ||
- | 111 | /** Current style. */ |
|
103 | style_t style; |
112 | style_t style; |
- | 113 | ||
- | 114 | /** Pre-rendered mask for rendering glyphs. Different viewports |
|
- | 115 | * might use different drawing functions depending on whether their |
|
- | 116 | * scanlines are aligned on a word boundary.*/ |
|
104 | uint8_t *glyphs; |
117 | uint8_t *glyphs; |
- | 118 | ||
105 | uint8_t *bgpixel; |
119 | uint8_t *bgpixel; |
- | 120 | ||
- | 121 | /** Glyph drawing function for this viewport. */ |
|
- | 122 | dg_t dglyph; |
|
106 | 123 | ||
107 | /* Auto-cursor position */ |
124 | /* Auto-cursor position */ |
108 | bool cursor_active; |
125 | bool cursor_active; |
109 | unsigned int cur_col; |
126 | unsigned int cur_col; |
110 | unsigned int cur_row; |
127 | unsigned int cur_row; |
Line 137... | Line 154... | ||
137 | static pixmap_t pixmaps[MAX_PIXMAPS]; |
154 | static pixmap_t pixmaps[MAX_PIXMAPS]; |
138 | static viewport_t viewports[128]; |
155 | static viewport_t viewports[128]; |
139 | 156 | ||
140 | static bool client_connected = false; /**< Allow only 1 connection */ |
157 | static bool client_connected = false; /**< Allow only 1 connection */ |
141 | 158 | ||
- | 159 | static void draw_glyph_aligned(unsigned int x, unsigned int y, bool cursor, |
|
- | 160 | uint8_t *glyphs, uint8_t glyph, uint32_t fg_color, uint32_t bg_color); |
|
- | 161 | static void draw_glyph_fallback(unsigned int x, unsigned int y, bool cursor, |
|
- | 162 | uint8_t *glyphs, uint8_t glyph, uint32_t fg_color, uint32_t bg_color); |
|
- | 163 | ||
- | 164 | static void draw_vp_glyph(viewport_t *vport, bool cursor, unsigned int col, |
|
- | 165 | unsigned int row); |
|
- | 166 | ||
- | 167 | ||
142 | #define RED(x, bits) ((x >> (8 + 8 + 8 - bits)) & ((1 << bits) - 1)) |
168 | #define RED(x, bits) ((x >> (8 + 8 + 8 - bits)) & ((1 << bits) - 1)) |
143 | #define GREEN(x, bits) ((x >> (8 + 8 - bits)) & ((1 << bits) - 1)) |
169 | #define GREEN(x, bits) ((x >> (8 + 8 - bits)) & ((1 << bits) - 1)) |
144 | #define BLUE(x, bits) ((x >> (8 - bits)) & ((1 << bits) - 1)) |
170 | #define BLUE(x, bits) ((x >> (8 - bits)) & ((1 << bits) - 1)) |
145 | 171 | ||
146 | #define COL2X(col) ((col) * FONT_WIDTH) |
172 | #define COL2X(col) ((col) * FONT_WIDTH) |
Line 217... | Line 243... | ||
217 | { |
243 | { |
218 | *((uint8_t *) dst) |
244 | *((uint8_t *) dst) |
219 | = ~((RED(rgb, 3) << 5) | (GREEN(rgb, 2) << 3) | BLUE(rgb, 3)); |
245 | = ~((RED(rgb, 3) << 5) | (GREEN(rgb, 2) << 3) | BLUE(rgb, 3)); |
220 | } |
246 | } |
221 | 247 | ||
- | 248 | /** Draw a filled rectangle. |
|
- | 249 | * |
|
- | 250 | * @note Need real implementation that does not access VRAM twice. |
|
- | 251 | */ |
|
- | 252 | static void draw_filled_rect(unsigned int x0, unsigned int y0, unsigned int x1, |
|
- | 253 | unsigned int y1, uint32_t color) |
|
- | 254 | { |
|
- | 255 | unsigned int x, y; |
|
- | 256 | unsigned int copy_bytes; |
|
- | 257 | ||
- | 258 | uint8_t *sp, *dp; |
|
- | 259 | uint8_t cbuf[4]; |
|
- | 260 | ||
- | 261 | if (y0 >= y1 || x0 >= x1) return; |
|
- | 262 | screen.rgb_conv(cbuf, color); |
|
222 | 263 | ||
- | 264 | sp = &screen.fb_addr[FB_POS(x0, y0)]; |
|
- | 265 | dp = sp; |
|
- | 266 | ||
- | 267 | /* Draw the first line. */ |
|
- | 268 | for (x = x0; x < x1; x++) { |
|
- | 269 | memcpy(dp, cbuf, screen.pixelbytes); |
|
- | 270 | dp += screen.pixelbytes; |
|
- | 271 | } |
|
- | 272 | ||
- | 273 | dp = sp + screen.scanline; |
|
- | 274 | copy_bytes = (x1 - x0) * screen.pixelbytes; |
|
- | 275 | ||
- | 276 | /* Draw the remaining lines by copying. */ |
|
- | 277 | for (y = y0 + 1; y < y1; y++) { |
|
- | 278 | memcpy(dp, sp, copy_bytes); |
|
- | 279 | dp += screen.scanline; |
|
- | 280 | } |
|
- | 281 | } |
|
- | 282 | ||
223 | /** Redraw viewport |
283 | /** Redraw viewport. |
224 | * |
284 | * |
225 | * @param vport Viewport to redraw |
285 | * @param vport Viewport to redraw |
226 | * |
286 | * |
227 | */ |
287 | */ |
228 | static void vport_redraw(viewport_t *vport) |
288 | static void vport_redraw(viewport_t *vport) |
229 | { |
289 | { |
230 | unsigned int row; |
290 | unsigned int row, col; |
231 | 291 | ||
232 | for (row = 0; row < vport->rows; row++) { |
292 | for (row = 0; row < vport->rows; row++) { |
233 | unsigned int y = vport->y + ROW2Y(row); |
- | |
234 | unsigned int yd; |
- | |
235 | - | ||
236 | for (yd = 0; yd < FONT_SCANLINES; yd++) { |
293 | for (col = 0; col < vport->cols; col++) { |
237 | unsigned int x; |
- | |
238 | unsigned int col; |
- | |
239 | - | ||
240 | for (col = 0, x = vport->x; col < vport->cols; col++, x += FONT_WIDTH) |
- | |
241 | memcpy(&screen.fb_addr[FB_POS(x, y + yd)], |
- | |
242 | &vport->glyphs[GLYPH_POS(vport->backbuf[BB_POS(vport, col, row)], yd, false)], |
- | |
243 | screen.glyphscanline); |
294 | draw_vp_glyph(vport, false, col, row); |
244 | } |
295 | } |
245 | } |
296 | } |
246 | 297 | ||
247 | if (COL2X(vport->cols) < vport->width) { |
298 | if (COL2X(vport->cols) < vport->width) { |
248 | unsigned int y; |
299 | draw_filled_rect( |
249 | - | ||
250 | for (y = 0; y < vport->height; y++) { |
300 | vport->x + COL2X(vport->cols), vport->y, |
251 | unsigned int x; |
- | |
252 | - | ||
253 | for (x = COL2X(vport->cols); x < vport->width; x++) |
301 | vport->x + vport->width, vport->y + vport->height, |
254 | memcpy(&screen.fb_addr[FB_POS(x, y)], vport->bgpixel, screen.pixelbytes); |
302 | vport->style.bg_color); |
255 | } |
- | |
256 | } |
303 | } |
257 | 304 | ||
258 | if (ROW2Y(vport->rows) < vport->height) { |
305 | if (ROW2Y(vport->rows) < vport->height) { |
259 | unsigned int y; |
306 | draw_filled_rect( |
260 | - | ||
261 | for (y = ROW2Y(vport->rows); y < vport->height; y++) { |
307 | vport->x, vport->y + ROW2Y(vport->rows), |
262 | unsigned int x; |
- | |
263 | - | ||
264 | for (x = 0; x < vport->width; x++) |
308 | vport->x + vport->width, vport->y + vport->height, |
265 | memcpy(&screen.fb_addr[FB_POS(x, y)], vport->bgpixel, screen.pixelbytes); |
309 | vport->style.bg_color); |
266 | } |
- | |
267 | } |
310 | } |
268 | } |
311 | } |
269 | 312 | ||
270 | 313 | ||
271 | /** Clear viewport |
314 | /** Clear viewport. |
272 | * |
315 | * |
273 | * @param vport Viewport to clear |
316 | * @param vport Viewport to clear |
274 | * |
317 | * |
275 | */ |
318 | */ |
276 | static void vport_clear(viewport_t *vport) |
319 | static void vport_clear(viewport_t *vport) |
277 | { |
320 | { |
278 | memset(vport->backbuf, 0, vport->bbsize); |
321 | memset(vport->backbuf, 0, vport->bbsize); |
279 | vport_redraw(vport); |
322 | vport_redraw(vport); |
280 | } |
323 | } |
281 | 324 | ||
282 | - | ||
283 | /** Scroll viewport by given number of lines |
325 | /** Scroll viewport by the specified number of lines. |
284 | * |
326 | * |
285 | * @param vport Viewport to scroll |
327 | * @param vport Viewport to scroll |
286 | * @param lines Number of lines to scroll |
328 | * @param lines Number of lines to scroll |
287 | * |
329 | * |
288 | */ |
330 | */ |
289 | static void vport_scroll(viewport_t *vport, int lines) |
331 | static void vport_scroll(viewport_t *vport, int lines) |
290 | { |
332 | { |
- | 333 | unsigned int row, col; |
|
291 | unsigned int row; |
334 | unsigned int x, y; |
- | 335 | uint8_t glyph; |
|
- | 336 | ||
- | 337 | /* |
|
- | 338 | * Redraw. |
|
- | 339 | */ |
|
292 | 340 | ||
- | 341 | y = vport->y; |
|
293 | for (row = 0; row < vport->rows; row++) { |
342 | for (row = 0; row < vport->rows; row++) { |
294 | unsigned int y = vport->y + ROW2Y(row); |
- | |
295 | unsigned int yd; |
343 | x = vport->x; |
296 | - | ||
297 | for (yd = 0; yd < FONT_SCANLINES; yd++) { |
344 | for (col = 0; col < vport->cols; col++) { |
298 | unsigned int x; |
345 | if ((row + lines >= 0) && (row + lines < vport->rows)) { |
299 | unsigned int col; |
346 | glyph = vport->backbuf[BB_POS(vport, col, row + lines)]; |
300 | 347 | ||
301 | for (col = 0, x = vport->x; col < vport->cols; col++, x += FONT_WIDTH) { |
348 | if (vport->backbuf[BB_POS(vport, col, row)] == glyph) { |
302 | uint8_t glyph; |
349 | x += FONT_WIDTH; |
303 | - | ||
304 | if ((row + lines >= 0) && (row + lines < vport->rows)) { |
- | |
305 | if (vport->backbuf[BB_POS(vport, col, row)] == vport->backbuf[BB_POS(vport, col, row + lines)]) |
- | |
306 | continue; |
350 | continue; |
307 | 351 | } |
|
308 | glyph = vport->backbuf[BB_POS(vport, col, row + lines)]; |
- | |
309 | } else |
352 | } else { |
310 | glyph = 0; |
353 | glyph = 0; |
311 | - | ||
312 | memcpy(&screen.fb_addr[FB_POS(x, y + yd)], |
- | |
313 | &vport->glyphs[GLYPH_POS(glyph, yd, false)], screen.glyphscanline); |
- | |
314 | } |
354 | } |
- | 355 | ||
- | 356 | (*vport->dglyph)(x, y, false, vport->glyphs, glyph, |
|
- | 357 | vport->style.fg_color, vport->style.bg_color); |
|
- | 358 | x += FONT_WIDTH; |
|
315 | } |
359 | } |
- | 360 | y += FONT_SCANLINES; |
|
316 | } |
361 | } |
- | 362 | ||
- | 363 | /* |
|
- | 364 | * Scroll backbuffer. |
|
- | 365 | */ |
|
317 | 366 | ||
318 | if (lines > 0) { |
367 | if (lines > 0) { |
319 | memcpy(vport->backbuf, vport->backbuf + vport->cols * lines, vport->cols * (vport->rows - lines)); |
368 | memmove(vport->backbuf, vport->backbuf + vport->cols * lines, |
- | 369 | vport->cols * (vport->rows - lines)); |
|
320 | memset(&vport->backbuf[BB_POS(vport, 0, vport->rows - lines)], 0, vport->cols * lines); |
370 | memset(&vport->backbuf[BB_POS(vport, 0, vport->rows - lines)], |
- | 371 | 0, vport->cols * lines); |
|
321 | } else { |
372 | } else { |
322 | memcpy(vport->backbuf - vport->cols * lines, vport->backbuf, vport->cols * (vport->rows + lines)); |
373 | memmove(vport->backbuf - vport->cols * lines, vport->backbuf, |
- | 374 | vport->cols * (vport->rows + lines)); |
|
323 | memset(vport->backbuf, 0, - vport->cols * lines); |
375 | memset(vport->backbuf, 0, - vport->cols * lines); |
324 | } |
376 | } |
325 | } |
377 | } |
326 | 378 | ||
327 | - | ||
328 | /** Render glyphs |
379 | /** Render glyphs |
329 | * |
380 | * |
330 | * Convert glyphs from device independent font |
381 | * Convert glyphs from device independent font |
331 | * description to current visual representation. |
382 | * description to current visual representation. |
332 | * |
383 | * |
Line 344... | Line 395... | ||
344 | unsigned int x; |
395 | unsigned int x; |
345 | 396 | ||
346 | for (x = 0; x < FONT_WIDTH; x++) { |
397 | for (x = 0; x < FONT_WIDTH; x++) { |
347 | screen.rgb_conv(&vport->glyphs[GLYPH_POS(glyph, y, false) + x * screen.pixelbytes], |
398 | screen.rgb_conv(&vport->glyphs[GLYPH_POS(glyph, y, false) + x * screen.pixelbytes], |
348 | (fb_font[glyph * FONT_SCANLINES + y] & (1 << (7 - x))) |
399 | (fb_font[glyph * FONT_SCANLINES + y] & (1 << (7 - x))) |
349 | ? vport->style.fg_color : vport->style.bg_color); |
- | |
350 | - | ||
351 | uint32_t curcolor; |
400 | ? 0xffffff : 0x000000); |
352 | 401 | ||
353 | if (y < FONT_SCANLINES - 2) |
402 | screen.rgb_conv(&vport->glyphs[GLYPH_POS(glyph, y, true) + x * screen.pixelbytes], |
354 | curcolor = |
- | |
355 | (fb_font[glyph * FONT_SCANLINES + y] & (1 << (7 - x))) |
403 | (fb_font[glyph * FONT_SCANLINES + y] & (1 << (7 - x))) |
356 | ? vport->style.fg_color : vport->style.bg_color; |
- | |
357 | else |
- | |
358 | curcolor = vport->style.fg_color; |
404 | ? 0x000000 : 0xffffff); |
359 | - | ||
360 | screen.rgb_conv(&vport->glyphs[GLYPH_POS(glyph, y, true) + x * screen.pixelbytes], curcolor); |
- | |
361 | } |
405 | } |
362 | } |
406 | } |
363 | } |
407 | } |
364 | 408 | ||
365 | screen.rgb_conv(vport->bgpixel, vport->style.bg_color); |
409 | screen.rgb_conv(vport->bgpixel, vport->style.bg_color); |
Line 390... | Line 434... | ||
390 | 434 | ||
391 | unsigned int cols = width / FONT_WIDTH; |
435 | unsigned int cols = width / FONT_WIDTH; |
392 | unsigned int rows = height / FONT_SCANLINES; |
436 | unsigned int rows = height / FONT_SCANLINES; |
393 | unsigned int bbsize = cols * rows; |
437 | unsigned int bbsize = cols * rows; |
394 | unsigned int glyphsize = 2 * FONT_GLYPHS * screen.glyphbytes; |
438 | unsigned int glyphsize = 2 * FONT_GLYPHS * screen.glyphbytes; |
- | 439 | unsigned int word_size = sizeof(unsigned long); |
|
395 | 440 | ||
396 | uint8_t *backbuf = (uint8_t *) malloc(bbsize); |
441 | uint8_t *backbuf = (uint8_t *) malloc(bbsize); |
397 | if (!backbuf) |
442 | if (!backbuf) |
398 | return ENOMEM; |
443 | return ENOMEM; |
399 | 444 | ||
Line 425... | Line 470... | ||
425 | viewports[i].style.bg_color = DEFAULT_BGCOLOR; |
470 | viewports[i].style.bg_color = DEFAULT_BGCOLOR; |
426 | viewports[i].style.fg_color = DEFAULT_FGCOLOR; |
471 | viewports[i].style.fg_color = DEFAULT_FGCOLOR; |
427 | 472 | ||
428 | viewports[i].glyphs = glyphs; |
473 | viewports[i].glyphs = glyphs; |
429 | viewports[i].bgpixel = bgpixel; |
474 | viewports[i].bgpixel = bgpixel; |
- | 475 | ||
- | 476 | /* |
|
- | 477 | * Conditions necessary to select aligned version: |
|
- | 478 | * |
|
- | 479 | * - word size is divisible by pixelbytes |
|
- | 480 | * - cell scanline size is divisible by word size |
|
- | 481 | * - cell scanlines are word-aligned |
|
- | 482 | */ |
|
- | 483 | if ((word_size % screen.pixelbytes) == 0 && |
|
- | 484 | (FONT_WIDTH * screen.pixelbytes) % word_size == 0 && |
|
- | 485 | (x * screen.pixelbytes) % word_size == 0 && |
|
- | 486 | screen.scanline % word_size == 0) { |
|
- | 487 | ||
- | 488 | viewports[i].dglyph = draw_glyph_aligned; |
|
- | 489 | } else { |
|
- | 490 | viewports[i].dglyph = draw_glyph_fallback; |
|
430 | 491 | } |
|
- | 492 | ||
431 | viewports[i].cur_col = 0; |
493 | viewports[i].cur_col = 0; |
432 | viewports[i].cur_row = 0; |
494 | viewports[i].cur_row = 0; |
433 | viewports[i].cursor_active = false; |
495 | viewports[i].cursor_active = false; |
434 | viewports[i].cursor_shown = false; |
496 | viewports[i].cursor_shown = false; |
435 | 497 | ||
Line 502... | Line 564... | ||
502 | 564 | ||
503 | return true; |
565 | return true; |
504 | } |
566 | } |
505 | 567 | ||
506 | 568 | ||
- | 569 | /** Draw a glyph, takes advantage of alignment. |
|
- | 570 | * |
|
- | 571 | * This version can only be used if the following conditions are met: |
|
- | 572 | * |
|
- | 573 | * - word size is divisible by pixelbytes |
|
- | 574 | * - cell scanline size is divisible by word size |
|
- | 575 | * - cell scanlines are word-aligned |
|
- | 576 | * |
|
- | 577 | * It makes use of the pre-rendered mask to process (possibly) several |
|
- | 578 | * pixels at once (word size / pixelbytes pixels at a time are processed) |
|
- | 579 | * making it very fast. Most notably this version is not applicable at 24 bits |
|
- | 580 | * per pixel. |
|
- | 581 | * |
|
- | 582 | * @param x x coordinate of top-left corner on screen. |
|
- | 583 | * @param y y coordinate of top-left corner on screen. |
|
- | 584 | * @param cursor Draw glyph with cursor |
|
- | 585 | * @param glyphs Pointer to font bitmap. |
|
- | 586 | * @param glyph Code of the glyph to draw. |
|
- | 587 | * @param fg_color Foreground color. |
|
- | 588 | * @param bg_color Backgroudn color. |
|
- | 589 | */ |
|
- | 590 | static void draw_glyph_aligned(unsigned int x, unsigned int y, bool cursor, |
|
- | 591 | uint8_t *glyphs, uint8_t glyph, uint32_t fg_color, uint32_t bg_color) |
|
- | 592 | { |
|
- | 593 | unsigned int i, yd; |
|
- | 594 | unsigned long fg_buf, bg_buf; |
|
- | 595 | unsigned long *maskp, *dp; |
|
- | 596 | unsigned long mask; |
|
- | 597 | unsigned int ww, d_add; |
|
- | 598 | ||
- | 599 | /* |
|
- | 600 | * Prepare a pair of words, one filled with foreground-color |
|
- | 601 | * pattern and the other filled with background-color pattern. |
|
- | 602 | */ |
|
- | 603 | for (i = 0; i < sizeof(unsigned long) / screen.pixelbytes; i++) { |
|
- | 604 | screen.rgb_conv(&((uint8_t *)&fg_buf)[i * screen.pixelbytes], |
|
- | 605 | fg_color); |
|
- | 606 | screen.rgb_conv(&((uint8_t *)&bg_buf)[i * screen.pixelbytes], |
|
- | 607 | bg_color); |
|
- | 608 | } |
|
- | 609 | ||
- | 610 | ||
- | 611 | /* Pointer to the current position in the mask. */ |
|
- | 612 | maskp = (unsigned long *) &glyphs[GLYPH_POS(glyph, 0, cursor)]; |
|
- | 613 | ||
- | 614 | /* Pointer to the current position on the screen. */ |
|
- | 615 | dp = (unsigned long *) &screen.fb_addr[FB_POS(x, y)]; |
|
- | 616 | ||
- | 617 | /* Width of the character cell in words. */ |
|
- | 618 | ww = FONT_WIDTH * screen.pixelbytes / sizeof(unsigned long); |
|
- | 619 | ||
- | 620 | /* Offset to add when moving to another screen scanline. */ |
|
- | 621 | d_add = screen.scanline - FONT_WIDTH * screen.pixelbytes; |
|
- | 622 | ||
- | 623 | for (yd = 0; yd < FONT_SCANLINES; yd++) { |
|
- | 624 | /* |
|
- | 625 | * Now process the cell scanline, combining foreground |
|
- | 626 | * and background color patters using the pre-rendered mask. |
|
- | 627 | */ |
|
- | 628 | for (i = 0; i < ww; i++) { |
|
- | 629 | mask = *maskp++; |
|
- | 630 | *dp++ = (fg_buf & mask) | (bg_buf & ~mask); |
|
- | 631 | } |
|
- | 632 | ||
- | 633 | /* Move to the beginning of the next scanline of the cell. */ |
|
- | 634 | dp = (unsigned long *) ((uint8_t *) dp + d_add); |
|
- | 635 | } |
|
- | 636 | } |
|
- | 637 | ||
- | 638 | /** Draw a glyph, fallback version. |
|
- | 639 | * |
|
- | 640 | * This version does not make use of the pre-rendered mask, it uses |
|
- | 641 | * the font bitmap directly. It works always, but it is slower. |
|
- | 642 | * |
|
- | 643 | * @param x x coordinate of top-left corner on screen. |
|
- | 644 | * @param y y coordinate of top-left corner on screen. |
|
- | 645 | * @param cursor Draw glyph with cursor |
|
- | 646 | * @param glyphs Pointer to font bitmap. |
|
- | 647 | * @param glyph Code of the glyph to draw. |
|
- | 648 | * @param fg_color Foreground color. |
|
- | 649 | * @param bg_color Backgroudn color. |
|
- | 650 | */ |
|
- | 651 | void draw_glyph_fallback(unsigned int x, unsigned int y, bool cursor, |
|
- | 652 | uint8_t *glyphs, uint8_t glyph, uint32_t fg_color, uint32_t bg_color) |
|
- | 653 | { |
|
- | 654 | unsigned int i, j, yd; |
|
- | 655 | uint8_t fg_buf[4], bg_buf[4]; |
|
- | 656 | uint8_t *dp, *sp; |
|
- | 657 | unsigned int d_add; |
|
- | 658 | uint8_t b; |
|
- | 659 | ||
- | 660 | /* Pre-render 1x the foreground and background color pixels. */ |
|
- | 661 | if (cursor) { |
|
- | 662 | screen.rgb_conv(fg_buf, bg_color); |
|
- | 663 | screen.rgb_conv(bg_buf, fg_color); |
|
- | 664 | } else { |
|
- | 665 | screen.rgb_conv(fg_buf, fg_color); |
|
- | 666 | screen.rgb_conv(bg_buf, bg_color); |
|
- | 667 | } |
|
- | 668 | ||
- | 669 | /* Pointer to the current position on the screen. */ |
|
- | 670 | dp = (uint8_t *) &screen.fb_addr[FB_POS(x, y)]; |
|
- | 671 | ||
- | 672 | /* Offset to add when moving to another screen scanline. */ |
|
- | 673 | d_add = screen.scanline - FONT_WIDTH * screen.pixelbytes; |
|
- | 674 | ||
- | 675 | for (yd = 0; yd < FONT_SCANLINES; yd++) { |
|
- | 676 | /* Byte containing bits of the glyph scanline. */ |
|
- | 677 | b = fb_font[glyph * FONT_SCANLINES + yd]; |
|
- | 678 | ||
- | 679 | for (i = 0; i < FONT_WIDTH; i++) { |
|
- | 680 | /* Choose color based on the current bit. */ |
|
- | 681 | sp = (b & 0x80) ? fg_buf : bg_buf; |
|
- | 682 | ||
- | 683 | /* Copy the pixel. */ |
|
- | 684 | for (j = 0; j < screen.pixelbytes; j++) { |
|
- | 685 | *dp++ = *sp++; |
|
- | 686 | } |
|
- | 687 | ||
- | 688 | /* Move to the next bit. */ |
|
- | 689 | b = b << 1; |
|
- | 690 | } |
|
- | 691 | ||
- | 692 | /* Move to the beginning of the next scanline of the cell. */ |
|
- | 693 | dp += d_add; |
|
- | 694 | } |
|
- | 695 | } |
|
- | 696 | ||
507 | /** Draw glyph at given position relative to viewport |
697 | /** Draw glyph at specified position in viewport. |
508 | * |
698 | * |
509 | * @param vport Viewport identification |
699 | * @param vport Viewport identification |
510 | * @param cursor Draw glyph with cursor |
700 | * @param cursor Draw glyph with cursor |
511 | * @param col Screen position relative to viewport |
701 | * @param col Screen position relative to viewport |
512 | * @param row Screen position relative to viewport |
702 | * @param row Screen position relative to viewport |
513 | * |
703 | * |
514 | */ |
704 | */ |
515 | static void draw_glyph(viewport_t *vport, bool cursor, unsigned int col, unsigned int row) |
705 | static void draw_vp_glyph(viewport_t *vport, bool cursor, unsigned int col, |
- | 706 | unsigned int row) |
|
516 | { |
707 | { |
517 | unsigned int x = vport->x + COL2X(col); |
708 | unsigned int x = vport->x + COL2X(col); |
518 | unsigned int y = vport->y + ROW2Y(row); |
709 | unsigned int y = vport->y + ROW2Y(row); |
519 | unsigned int yd; |
710 | uint8_t glyph; |
520 | 711 | ||
521 | uint8_t glyph = vport->backbuf[BB_POS(vport, col, row)]; |
712 | glyph = vport->backbuf[BB_POS(vport, col, row)]; |
522 | - | ||
523 | for (yd = 0; yd < FONT_SCANLINES; yd++) |
- | |
524 | memcpy(&screen.fb_addr[FB_POS(x, y + yd)], |
- | |
525 | &vport->glyphs[GLYPH_POS(glyph, yd, cursor)], screen.glyphscanline); |
- | |
526 | } |
- | |
527 | 713 | ||
- | 714 | (*vport->dglyph)(x, y, cursor, vport->glyphs, glyph, |
|
- | 715 | vport->style.fg_color, vport->style.bg_color); |
|
- | 716 | } |
|
528 | 717 | ||
529 | /** Hide cursor if it is shown |
718 | /** Hide cursor if it is shown |
530 | * |
719 | * |
531 | */ |
720 | */ |
532 | static void cursor_hide(viewport_t *vport) |
721 | static void cursor_hide(viewport_t *vport) |
533 | { |
722 | { |
534 | if ((vport->cursor_active) && (vport->cursor_shown)) { |
723 | if ((vport->cursor_active) && (vport->cursor_shown)) { |
535 | draw_glyph(vport, false, vport->cur_col, vport->cur_row); |
724 | draw_vp_glyph(vport, false, vport->cur_col, vport->cur_row); |
536 | vport->cursor_shown = false; |
725 | vport->cursor_shown = false; |
537 | } |
726 | } |
538 | } |
727 | } |
539 | 728 | ||
540 | 729 | ||
Line 543... | Line 732... | ||
543 | */ |
732 | */ |
544 | static void cursor_show(viewport_t *vport) |
733 | static void cursor_show(viewport_t *vport) |
545 | { |
734 | { |
546 | /* Do not check for cursor_shown */ |
735 | /* Do not check for cursor_shown */ |
547 | if (vport->cursor_active) { |
736 | if (vport->cursor_active) { |
548 | draw_glyph(vport, true, vport->cur_col, vport->cur_row); |
737 | draw_vp_glyph(vport, true, vport->cur_col, vport->cur_row); |
549 | vport->cursor_shown = true; |
738 | vport->cursor_shown = true; |
550 | } |
739 | } |
551 | } |
740 | } |
552 | 741 | ||
553 | 742 | ||
Line 577... | Line 766... | ||
577 | if ((vport->cursor_active) && (vport->cursor_shown) && |
766 | if ((vport->cursor_active) && (vport->cursor_shown) && |
578 | ((vport->cur_col != col) || (vport->cur_row != row))) |
767 | ((vport->cur_col != col) || (vport->cur_row != row))) |
579 | cursor_hide(vport); |
768 | cursor_hide(vport); |
580 | 769 | ||
581 | vport->backbuf[BB_POS(vport, col, row)] = c; |
770 | vport->backbuf[BB_POS(vport, col, row)] = c; |
582 | draw_glyph(vport, false, col, row); |
771 | draw_vp_glyph(vport, false, col, row); |
583 | 772 | ||
584 | vport->cur_col = col; |
773 | vport->cur_col = col; |
585 | vport->cur_row = row; |
774 | vport->cur_row = row; |
586 | 775 | ||
587 | vport->cur_col++; |
776 | vport->cur_col++; |
Line 614... | Line 803... | ||
614 | 803 | ||
615 | // TODO: use data[i].style |
804 | // TODO: use data[i].style |
616 | 805 | ||
617 | if (glyph != data[i].character) { |
806 | if (glyph != data[i].character) { |
618 | vport->backbuf[BB_POS(vport, col, row)] = data[i].character; |
807 | vport->backbuf[BB_POS(vport, col, row)] = data[i].character; |
619 | draw_glyph(vport, false, col, row); |
808 | draw_vp_glyph(vport, false, col, row); |
620 | } |
809 | } |
621 | } |
810 | } |
622 | cursor_show(vport); |
811 | cursor_show(vport); |
623 | } |
812 | } |
624 | 813 | ||
Line 928... | Line 1117... | ||
928 | int bytepos; |
1117 | int bytepos; |
929 | 1118 | ||
930 | if ((pointer_shown) || (!pointer_enabled)) |
1119 | if ((pointer_shown) || (!pointer_enabled)) |
931 | return; |
1120 | return; |
932 | 1121 | ||
933 | /* Save image under the cursor */ |
1122 | /* Save image under the pointer. */ |
934 | if (pointer_vport == -1) { |
1123 | if (pointer_vport == -1) { |
935 | pointer_vport = vport_create(pointer_x, pointer_y, pointer_width, pointer_height); |
1124 | pointer_vport = vport_create(pointer_x, pointer_y, pointer_width, pointer_height); |
936 | if (pointer_vport < 0) |
1125 | if (pointer_vport < 0) |
937 | return; |
1126 | return; |
938 | } else { |
1127 | } else { |
Line 943... | Line 1132... | ||
943 | if (pointer_pixmap == -1) |
1132 | if (pointer_pixmap == -1) |
944 | pointer_pixmap = save_vp_to_pixmap(&viewports[pointer_vport]); |
1133 | pointer_pixmap = save_vp_to_pixmap(&viewports[pointer_vport]); |
945 | else |
1134 | else |
946 | copy_vp_to_pixmap(&viewports[pointer_vport], &pixmaps[pointer_pixmap]); |
1135 | copy_vp_to_pixmap(&viewports[pointer_vport], &pixmaps[pointer_pixmap]); |
947 | 1136 | ||
948 | /* Draw cursor */ |
1137 | /* Draw mouse pointer. */ |
949 | for (i = 0; i < pointer_height; i++) |
1138 | for (i = 0; i < pointer_height; i++) |
950 | for (j = 0; j < pointer_width; j++) { |
1139 | for (j = 0; j < pointer_width; j++) { |
951 | bytepos = i * ((pointer_width - 1) / 8 + 1) + j / 8; |
1140 | bytepos = i * ((pointer_width - 1) / 8 + 1) + j / 8; |
952 | visibility = pointer_mask_bits[bytepos] & |
1141 | visibility = pointer_mask_bits[bytepos] & |
953 | (1 << (j % 8)); |
1142 | (1 << (j % 8)); |
Line 964... | Line 1153... | ||
964 | } |
1153 | } |
965 | 1154 | ||
966 | 1155 | ||
967 | static void mouse_hide(void) |
1156 | static void mouse_hide(void) |
968 | { |
1157 | { |
969 | /* Restore image under the cursor */ |
1158 | /* Restore image under the pointer. */ |
970 | if (pointer_shown) { |
1159 | if (pointer_shown) { |
971 | draw_pixmap(pointer_vport, pointer_pixmap); |
1160 | draw_pixmap(pointer_vport, pointer_pixmap); |
972 | pointer_shown = 0; |
1161 | pointer_shown = 0; |
973 | } |
1162 | } |
974 | } |
1163 | } |
Line 1289... | Line 1478... | ||
1289 | retval = EOK; |
1478 | retval = EOK; |
1290 | break; |
1479 | break; |
1291 | case FB_SET_STYLE: |
1480 | case FB_SET_STYLE: |
1292 | vport->style.fg_color = IPC_GET_ARG1(call); |
1481 | vport->style.fg_color = IPC_GET_ARG1(call); |
1293 | vport->style.bg_color = IPC_GET_ARG2(call); |
1482 | vport->style.bg_color = IPC_GET_ARG2(call); |
1294 | render_glyphs(vport); |
- | |
1295 | retval = EOK; |
1483 | retval = EOK; |
1296 | break; |
1484 | break; |
1297 | case FB_GET_RESOLUTION: |
1485 | case FB_GET_RESOLUTION: |
1298 | ipc_answer_2(callid, EOK, screen.xres, screen.yres); |
1486 | ipc_answer_2(callid, EOK, screen.xres, screen.yres); |
1299 | continue; |
1487 | continue; |