/branches/sparc/kernel/genarch/src/fb/fb.c |
---|
219,8 → 219,10 |
*/ |
static void screen_scroll(void) |
{ |
if (ylogo > 0) |
if (ylogo > 0) { |
logo_hide(); |
return; |
} |
unsigned int row; |
232,11 → 234,13 |
unsigned int x; |
unsigned int col; |
for (col = 0, x = 0; col < cols; col++, x += FONT_WIDTH) { |
for (col = 0, x = 0; col < cols; col++, |
x += FONT_WIDTH) { |
uint8_t glyph; |
if (row < rows - 1) { |
if (backbuf[BB_POS(col, row)] == backbuf[BB_POS(col, row + 1)]) |
if (backbuf[BB_POS(col, row)] == |
backbuf[BB_POS(col, row + 1)]) |
continue; |
glyph = backbuf[BB_POS(col, row + 1)]; |
244,7 → 248,8 |
glyph = 0; |
memcpy(&fb_addr[FB_POS(x, y + yd)], |
&glyphs[GLYPH_POS(glyph, yd)], glyphscanline); |
&glyphs[GLYPH_POS(glyph, yd)], |
glyphscanline); |
} |
} |
} |
293,7 → 298,8 |
case '\t': |
cursor_remove(); |
do { |
glyph_draw((uint8_t) ' ', position % cols, position / cols); |
glyph_draw((uint8_t) ' ', position % cols, |
position / cols); |
position++; |
} while ((position % 8) && (position < cols * rows)); |
break; |
335,11 → 341,15 |
for (y = 0; y < FONT_SCANLINES; y++) { |
unsigned int x; |
for (x = 0; x < FONT_WIDTH; x++) |
rgb_conv(&glyphs[GLYPH_POS(glyph, y) + x * pixelbytes], |
(fb_font[ROW2Y(glyph) + y] & (1 << (7 - x))) ? FG_COLOR : BG_COLOR); |
for (x = 0; x < FONT_WIDTH; x++) { |
void *dst = &glyphs[GLYPH_POS(glyph, y) + |
x * pixelbytes]; |
uint32_t rgb = (fb_font[ROW2Y(glyph) + y] & |
(1 << (7 - x))) ? FG_COLOR : BG_COLOR; |
rgb_conv(dst, rgb); |
} |
} |
} |
/* Prerender background scanline */ |
unsigned int x; |
362,7 → 372,9 |
for (x = 0; x < xres; x++) |
rgb_conv(&fb_addr[FB_POS(x, y)], |
(x < LOGO_WIDTH) ? fb_logo[y * LOGO_WIDTH + x] : LOGO_COLOR); |
(x < LOGO_WIDTH) ? |
fb_logo[y * LOGO_WIDTH + x] : |
LOGO_COLOR); |
} |
} |
376,12 → 388,15 |
unsigned int x; |
unsigned int col; |
for (col = 0, x = 0; col < cols; col++, x += FONT_WIDTH) |
memcpy(&fb_addr[FB_POS(x, y + yd)], |
&glyphs[GLYPH_POS(backbuf[BB_POS(col, row)], yd)], |
glyphscanline); |
for (col = 0, x = 0; col < cols; |
col++, x += FONT_WIDTH) { |
void *d = &fb_addr[FB_POS(x, y + yd)]; |
void *s = &glyphs[GLYPH_POS(backbuf[BB_POS(col, |
row)], yd)]; |
memcpy(d, s, glyphscanline); |
} |
} |
} |
if (COL2X(cols) < xres) { |
unsigned int y; |
391,10 → 406,10 |
memcpy(&fb_addr[FB_POS(COL2X(cols), y)], bgscan, size); |
} |
if (ROW2Y(rowtrim) < yres) { |
if (ROW2Y(rowtrim) + ylogo < yres) { |
unsigned int y; |
for (y = ROW2Y(rowtrim); y < yres; y++) |
for (y = ROW2Y(rowtrim) + ylogo; y < yres; y++) |
memcpy(&fb_addr[FB_POS(0, y)], bgscan, bgscanbytes); |
} |
} |
/branches/sparc/kernel/arch/sparc64/include/drivers/scr.h |
---|
49,6 → 49,7 |
extern scr_type_t scr_type; |
extern void scr_init(ofw_tree_node_t *node); |
extern void scr_redraw(void); |
#endif |
/branches/sparc/kernel/arch/sparc64/src/console.c |
---|
175,6 → 175,7 |
*/ |
void arch_grab_console(void) |
{ |
scr_redraw(); |
switch (kbd_type) { |
#ifdef CONFIG_Z8530 |
case KBD_Z8530: |
/branches/sparc/kernel/arch/sparc64/src/drivers/scr.c |
---|
237,5 → 237,10 |
fb_init(&props); |
} |
void scr_redraw(void) |
{ |
fb_redraw(); |
} |
/** @} |
*/ |
/branches/sparc/kernel/arch/ppc32/src/ppc32.c |
---|
152,6 → 152,7 |
*/ |
void arch_grab_console(void) |
{ |
fb_redraw(); |
cuda_grab(); |
} |
/branches/sparc/kernel/arch/mips32/src/console.c |
---|
36,6 → 36,7 |
#include <arch/console.h> |
#include <arch/drivers/serial.h> |
#include <arch/drivers/msim.h> |
#include <genarch/fb/fb.h> |
void console_init(devno_t devno) |
{ |
50,6 → 51,9 |
*/ |
void arch_grab_console(void) |
{ |
#ifdef CONFIG_FB |
fb_redraw(); |
#endif |
msim_kbd_grab(); |
} |
/branches/sparc/uspace/lib/libc/include/string.h |
---|
35,16 → 35,9 |
#ifndef LIBC_STRING_H_ |
#define LIBC_STRING_H_ |
#include <mem.h> |
#include <sys/types.h> |
#define bzero(ptr, len) memset((ptr), 0, (len)) |
extern void * memset(void *, int, size_t); |
extern void * memcpy(void *, const void *, size_t); |
extern void * memmove(void *, const void *, size_t); |
extern int bcmp(const char *, const char *, size_t); |
extern int strcmp(const char *, const char *); |
extern int strncmp(const char *, const char *, size_t); |
extern int stricmp(const char *, const char *); |
/branches/sparc/uspace/lib/libc/include/mem.h |
---|
0,0 → 1,51 |
/* |
* Copyright (c) 2005 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup libc |
* @{ |
*/ |
/** @file |
*/ |
#ifndef LIBC_MEM_H_ |
#define LIBC_MEM_H_ |
#include <sys/types.h> |
#define bzero(ptr, len) memset((ptr), 0, (len)) |
extern void * memset(void *, int, size_t); |
extern void * memcpy(void *, const void *, size_t); |
extern void * memmove(void *, const void *, size_t); |
extern int bcmp(const char *, const char *, size_t); |
#endif |
/** @} |
*/ |
Property changes: |
Added: svn:mergeinfo |
/branches/sparc/uspace/lib/libc/include/loader/loader.h |
---|
44,7 → 44,7 |
int phone_id; |
} loader_t; |
extern loader_t *loader_spawn(char *name); |
extern loader_t *loader_spawn(const char *name); |
extern int loader_get_task_id(loader_t *, task_id_t *); |
extern int loader_set_pathname(loader_t *, const char *); |
extern int loader_set_args(loader_t *, char *const []); |
/branches/sparc/uspace/lib/libc/generic/loader.c |
---|
50,7 → 50,7 |
* @return Pointer to the loader connection structure (should be |
* de-allocated using free() after use). |
*/ |
loader_t *loader_spawn(char *name) |
loader_t *loader_spawn(const char *name) |
{ |
int phone_id, rc; |
loader_t *ldr; |
/branches/sparc/uspace/lib/libc/generic/string.c |
---|
1,7 → 1,6 |
/* |
* Copyright (c) 2005 Martin Decky |
* Copyright (C) 1998 by Wes Peters <wes@softweyr.com> |
* Copyright (c) 1988, 1993 The Regents of the University of California. |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
35,96 → 34,11 |
*/ |
#include <string.h> |
#include <unistd.h> |
#include <stdlib.h> |
#include <limits.h> |
#include <ctype.h> |
#include <limits.h> |
#include <align.h> |
#include <sys/types.h> |
#include <malloc.h> |
/* Dummy implementation of mem/ functions */ |
void *memset(void *s, int c, size_t n) |
{ |
char *os = s; |
while (n--) |
*(os++) = c; |
return s; |
} |
struct along { |
unsigned long n; |
} __attribute__ ((packed)); |
static void *unaligned_memcpy(void *dst, const void *src, size_t n) |
{ |
int i, j; |
struct along *adst = dst; |
const struct along *asrc = src; |
for (i = 0; i < n / sizeof(unsigned long); i++) |
adst[i].n = asrc[i].n; |
for (j = 0; j < n % sizeof(unsigned long); j++) |
((unsigned char *) (((unsigned long *) dst) + i))[j] = |
((unsigned char *) (((unsigned long *) src) + i))[j]; |
return (char *) dst; |
} |
void *memcpy(void *dst, const void *src, size_t n) |
{ |
int i, j; |
if (((long) dst & (sizeof(long) - 1)) || |
((long) src & (sizeof(long) - 1))) |
return unaligned_memcpy(dst, src, n); |
for (i = 0; i < n / sizeof(unsigned long); i++) |
((unsigned long *) dst)[i] = ((unsigned long *) src)[i]; |
for (j = 0; j < n % sizeof(unsigned long); j++) |
((unsigned char *) (((unsigned long *) dst) + i))[j] = |
((unsigned char *) (((unsigned long *) src) + i))[j]; |
return (char *) dst; |
} |
void *memmove(void *dst, const void *src, size_t n) |
{ |
int i, j; |
if (src > dst) |
return memcpy(dst, src, n); |
for (j = (n % sizeof(unsigned long)) - 1; j >= 0; j--) |
((unsigned char *) ((unsigned long *) dst))[j] = |
((unsigned char *) ((unsigned long *) src))[j]; |
for (i = n / sizeof(unsigned long) - 1; i >=0 ; i--) |
((unsigned long *) dst)[i] = ((unsigned long *) src)[i]; |
return (char *) dst; |
} |
/** Compare two memory areas. |
* |
* @param s1 Pointer to the first area to compare. |
* @param s2 Pointer to the second area to compare. |
* @param len Size of the first area in bytes. Both areas must have |
* the same length. |
* @return If len is 0, return zero. If the areas match, return |
* zero. Otherwise return non-zero. |
*/ |
int bcmp(const char *s1, const char *s2, size_t len) |
{ |
for (; len && *s1++ == *s2++; len--) |
; |
return len; |
} |
/** Count the number of characters in the string, not including terminating 0. |
* |
* @param str String. |
398,52 → 312,37 |
return (char *) memcpy(ret, s1, len); |
} |
/* Ported from FBSD strtok.c 8.1 (Berkeley) 6/4/93 */ |
char * strtok_r(char *s, const char *delim, char **last) |
char *strtok(char *s, const char *delim) |
{ |
char *spanp, *tok; |
int c, sc; |
static char *next; |
if (s == NULL && (s = *last) == NULL) |
return (NULL); |
cont: |
c = *s++; |
for (spanp = (char *)delim; (sc = *spanp++) != 0;) { |
if (c == sc) |
goto cont; |
return strtok_r(s, delim, &next); |
} |
if (c == 0) { /* no non-delimiter characters */ |
*last = NULL; |
return (NULL); |
} |
char *strtok_r(char *s, const char *delim, char **next) |
{ |
char *start, *end; |
tok = s - 1; |
if (s == NULL) |
s = *next; |
for (;;) { |
c = *s++; |
spanp = (char *)delim; |
do { |
if ((sc = *spanp++) == c) { |
if (c == 0) |
s = NULL; |
else |
s[-1] = '\0'; |
*last = s; |
return (tok); |
} |
} while (sc != 0); |
} |
} |
/* Skip over leading delimiters. */ |
while (*s && (strchr(delim, *s) != NULL)) ++s; |
start = s; |
/* Ported from FBSD strtok.c 8.1 (Berkeley) 6/4/93 */ |
char * strtok(char *s, const char *delim) |
{ |
static char *last; |
/* Skip over token characters. */ |
while (*s && (strchr(delim, *s) == NULL)) ++s; |
end = s; |
*next = (*s ? s + 1 : s); |
return (strtok_r(s, delim, &last)); |
if (start == end) { |
return NULL; /* No more tokens. */ |
} |
/* Overwrite delimiter with NULL terminator. */ |
*end = '\0'; |
return start; |
} |
/** @} |
*/ |
/branches/sparc/uspace/lib/libc/generic/mem.c |
---|
0,0 → 1,239 |
/* |
* Copyright (c) 2005 Martin Decky |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup libc |
* @{ |
*/ |
/** @file |
*/ |
#include <mem.h> |
#include <stdlib.h> |
#include <sys/types.h> |
/** Fill memory block with a constant value. */ |
void *memset(void *dest, int b, size_t n) |
{ |
char *pb; |
unsigned long *pw; |
size_t word_size; |
size_t n_words; |
unsigned long pattern; |
size_t i; |
size_t fill; |
/* Fill initial segment. */ |
word_size = sizeof(unsigned long); |
fill = word_size - ((uintptr_t) dest & (word_size - 1)); |
if (fill > n) fill = n; |
pb = dest; |
i = fill; |
while (i-- != 0) |
*pb++ = b; |
/* Compute remaining size. */ |
n -= fill; |
if (n == 0) return dest; |
n_words = n / word_size; |
n = n % word_size; |
pw = (unsigned long *) pb; |
/* Create word-sized pattern for aligned segment. */ |
pattern = 0; |
i = word_size; |
while (i-- != 0) |
pattern = (pattern << 8) | (uint8_t) b; |
/* Fill aligned segment. */ |
i = n_words; |
while (i-- != 0) |
*pw++ = pattern; |
pb = (char *) pw; |
/* Fill final segment. */ |
i = n; |
while (i-- != 0) |
*pb++ = b; |
return dest; |
} |
struct along { |
unsigned long n; |
} __attribute__ ((packed)); |
static void *unaligned_memcpy(void *dst, const void *src, size_t n) |
{ |
int i, j; |
struct along *adst = dst; |
const struct along *asrc = src; |
for (i = 0; i < n / sizeof(unsigned long); i++) |
adst[i].n = asrc[i].n; |
for (j = 0; j < n % sizeof(unsigned long); j++) |
((unsigned char *) (((unsigned long *) dst) + i))[j] = |
((unsigned char *) (((unsigned long *) src) + i))[j]; |
return (char *) dst; |
} |
/** Copy memory block. */ |
void *memcpy(void *dst, const void *src, size_t n) |
{ |
size_t i; |
size_t mod, fill; |
size_t word_size; |
size_t n_words; |
const unsigned long *srcw; |
unsigned long *dstw; |
const uint8_t *srcb; |
uint8_t *dstb; |
word_size = sizeof(unsigned long); |
/* |
* Are source and destination addresses congruent modulo word_size? |
* If not, use unaligned_memcpy(). |
*/ |
if (((uintptr_t) dst & (word_size - 1)) != |
((uintptr_t) src & (word_size - 1))) |
return unaligned_memcpy(dst, src, n); |
/* |
* mod is the address modulo word size. fill is the length of the |
* initial buffer segment before the first word boundary. |
* If the buffer is very short, use unaligned_memcpy(), too. |
*/ |
mod = (uintptr_t) dst & (word_size - 1); |
fill = word_size - mod; |
if (fill > n) fill = n; |
/* Copy the initial segment. */ |
srcb = src; |
dstb = dst; |
i = fill; |
while (i-- != 0) |
*dstb++ = *srcb++; |
/* Compute remaining length. */ |
n -= fill; |
if (n == 0) return dst; |
/* Pointers to aligned segment. */ |
dstw = (unsigned long *) dstb; |
srcw = (const unsigned long *) srcb; |
n_words = n / word_size; /* Number of whole words to copy. */ |
n -= n_words * word_size; /* Remaining bytes at the end. */ |
/* "Fast" copy. */ |
i = n_words; |
while (i-- != 0) |
*dstw++ = *srcw++; |
/* |
* Copy the rest. |
*/ |
srcb = (const uint8_t *) srcw; |
dstb = (uint8_t *) dstw; |
i = n; |
while (i-- != 0) |
*dstb++ = *srcb++; |
return dst; |
} |
/** Move memory block with possible overlapping. */ |
void *memmove(void *dst, const void *src, size_t n) |
{ |
const uint8_t *sp; |
uint8_t *dp; |
/* Nothing to do? */ |
if (src == dst) |
return dst; |
/* Non-overlapping? */ |
if (dst >= src + n || src >= dst + n) { |
return memcpy(dst, src, n); |
} |
/* Which direction? */ |
if (src > dst) { |
/* Forwards. */ |
sp = src; |
dp = dst; |
while (n-- != 0) |
*dp++ = *sp++; |
} else { |
/* Backwards. */ |
sp = src + (n - 1); |
dp = dst + (n - 1); |
while (n-- != 0) |
*dp-- = *sp--; |
} |
return dst; |
} |
/** Compare two memory areas. |
* |
* @param s1 Pointer to the first area to compare. |
* @param s2 Pointer to the second area to compare. |
* @param len Size of the first area in bytes. Both areas must have |
* the same length. |
* @return If len is 0, return zero. If the areas match, return |
* zero. Otherwise return non-zero. |
*/ |
int bcmp(const char *s1, const char *s2, size_t len) |
{ |
for (; len && *s1++ == *s2++; len--) |
; |
return len; |
} |
/** @} |
*/ |
Property changes: |
Added: svn:mergeinfo |
/branches/sparc/uspace/lib/libc/Makefile |
---|
51,6 → 51,7 |
generic/ddi.c \ |
generic/as.c \ |
generic/cap.c \ |
generic/mem.c \ |
generic/string.c \ |
generic/fibril.c \ |
generic/pcb.c \ |
/branches/sparc/uspace/srv/console/console.c |
---|
106,11 → 106,16 |
async_msg_0(fb_info.phone, FB_CLEAR); |
} |
static void curs_visibility(int v) |
static void curs_visibility(bool visible) |
{ |
async_msg_1(fb_info.phone, FB_CURSOR_VISIBILITY, v); |
async_msg_1(fb_info.phone, FB_CURSOR_VISIBILITY, visible); |
} |
static void curs_hide_sync(void) |
{ |
ipc_call_sync_1_0(fb_info.phone, FB_CURSOR_VISIBILITY, false); |
} |
static void curs_goto(int row, int col) |
{ |
async_msg_2(fb_info.phone, FB_CURSOR_GOTO, row, col); |
197,7 → 202,7 |
if (newcons == KERNEL_CONSOLE) { |
async_serialize_start(); |
curs_visibility(0); |
curs_hide_sync(); |
gcons_in_kernel(); |
async_serialize_end(); |
204,7 → 209,7 |
if (__SYSCALL0(SYS_DEBUG_ENABLE_CONSOLE)) |
active_console = KERNEL_CONSOLE; |
else |
newcons == active_console; |
newcons = active_console; |
} |
if (newcons != KERNEL_CONSOLE) { |
218,7 → 223,7 |
conn = &connections[active_console]; |
set_style(&conn->screenbuffer.style); |
curs_visibility(0); |
curs_visibility(false); |
if (interbuffer) { |
for (i = 0; i < conn->screenbuffer.size_x; i++) |
for (j = 0; j < conn->screenbuffer.size_y; j++) { |
/branches/sparc/uspace/srv/fb/fb.c |
---|
71,8 → 71,13 |
#define MAX_PIXMAPS 256 /**< Maximum number of saved pixmaps */ |
#define MAX_VIEWPORTS 128 /**< Viewport is a rectangular area on the screen */ |
/** Function to render a pixel from a RGB value. */ |
typedef void (*rgb_conv_t)(void *, uint32_t); |
/** Function to draw a glyph. */ |
typedef void (*dg_t)(unsigned int x, unsigned int y, bool cursor, |
uint8_t *glyphs, uint8_t glyph, uint32_t fg_color, uint32_t bg_color); |
struct { |
uint8_t *fb_addr; |
99,11 → 104,23 |
unsigned int cols; |
unsigned int rows; |
/* Style and glyphs for text printing */ |
/* |
* Style and glyphs for text printing |
*/ |
/** Current style. */ |
style_t style; |
/** Pre-rendered mask for rendering glyphs. Different viewports |
* might use different drawing functions depending on whether their |
* scanlines are aligned on a word boundary.*/ |
uint8_t *glyphs; |
uint8_t *bgpixel; |
/** Glyph drawing function for this viewport. */ |
dg_t dglyph; |
/* Auto-cursor position */ |
bool cursor_active; |
unsigned int cur_col; |
139,6 → 156,15 |
static bool client_connected = false; /**< Allow only 1 connection */ |
static void draw_glyph_aligned(unsigned int x, unsigned int y, bool cursor, |
uint8_t *glyphs, uint8_t glyph, uint32_t fg_color, uint32_t bg_color); |
static void draw_glyph_fallback(unsigned int x, unsigned int y, bool cursor, |
uint8_t *glyphs, uint8_t glyph, uint32_t fg_color, uint32_t bg_color); |
static void draw_vp_glyph(viewport_t *vport, bool cursor, unsigned int col, |
unsigned int row); |
#define RED(x, bits) ((x >> (8 + 8 + 8 - bits)) & ((1 << bits) - 1)) |
#define GREEN(x, bits) ((x >> (8 + 8 - bits)) & ((1 << bits) - 1)) |
#define BLUE(x, bits) ((x >> (8 - bits)) & ((1 << bits) - 1)) |
219,8 → 245,42 |
= ~((RED(rgb, 3) << 5) | (GREEN(rgb, 2) << 3) | BLUE(rgb, 3)); |
} |
/** Draw a filled rectangle. |
* |
* @note Need real implementation that does not access VRAM twice. |
*/ |
static void draw_filled_rect(unsigned int x0, unsigned int y0, unsigned int x1, |
unsigned int y1, uint32_t color) |
{ |
unsigned int x, y; |
unsigned int copy_bytes; |
/** Redraw viewport |
uint8_t *sp, *dp; |
uint8_t cbuf[4]; |
if (y0 >= y1 || x0 >= x1) return; |
screen.rgb_conv(cbuf, color); |
sp = &screen.fb_addr[FB_POS(x0, y0)]; |
dp = sp; |
/* Draw the first line. */ |
for (x = x0; x < x1; x++) { |
memcpy(dp, cbuf, screen.pixelbytes); |
dp += screen.pixelbytes; |
} |
dp = sp + screen.scanline; |
copy_bytes = (x1 - x0) * screen.pixelbytes; |
/* Draw the remaining lines by copying. */ |
for (y = y0 + 1; y < y1; y++) { |
memcpy(dp, sp, copy_bytes); |
dp += screen.scanline; |
} |
} |
/** Redraw viewport. |
* |
* @param vport Viewport to redraw |
* |
227,48 → 287,31 |
*/ |
static void vport_redraw(viewport_t *vport) |
{ |
unsigned int row; |
unsigned int row, col; |
for (row = 0; row < vport->rows; row++) { |
unsigned int y = vport->y + ROW2Y(row); |
unsigned int yd; |
for (yd = 0; yd < FONT_SCANLINES; yd++) { |
unsigned int x; |
unsigned int col; |
for (col = 0, x = vport->x; col < vport->cols; col++, x += FONT_WIDTH) |
memcpy(&screen.fb_addr[FB_POS(x, y + yd)], |
&vport->glyphs[GLYPH_POS(vport->backbuf[BB_POS(vport, col, row)], yd, false)], |
screen.glyphscanline); |
for (col = 0; col < vport->cols; col++) { |
draw_vp_glyph(vport, false, col, row); |
} |
} |
if (COL2X(vport->cols) < vport->width) { |
unsigned int y; |
for (y = 0; y < vport->height; y++) { |
unsigned int x; |
for (x = COL2X(vport->cols); x < vport->width; x++) |
memcpy(&screen.fb_addr[FB_POS(x, y)], vport->bgpixel, screen.pixelbytes); |
draw_filled_rect( |
vport->x + COL2X(vport->cols), vport->y, |
vport->x + vport->width, vport->y + vport->height, |
vport->style.bg_color); |
} |
} |
if (ROW2Y(vport->rows) < vport->height) { |
unsigned int y; |
for (y = ROW2Y(vport->rows); y < vport->height; y++) { |
unsigned int x; |
for (x = 0; x < vport->width; x++) |
memcpy(&screen.fb_addr[FB_POS(x, y)], vport->bgpixel, screen.pixelbytes); |
draw_filled_rect( |
vport->x, vport->y + ROW2Y(vport->rows), |
vport->x + vport->width, vport->y + vport->height, |
vport->style.bg_color); |
} |
} |
} |
/** Clear viewport |
/** Clear viewport. |
* |
* @param vport Viewport to clear |
* |
279,8 → 322,7 |
vport_redraw(vport); |
} |
/** Scroll viewport by given number of lines |
/** Scroll viewport by the specified number of lines. |
* |
* @param vport Viewport to scroll |
* @param lines Number of lines to scroll |
288,43 → 330,52 |
*/ |
static void vport_scroll(viewport_t *vport, int lines) |
{ |
unsigned int row; |
unsigned int row, col; |
unsigned int x, y; |
uint8_t glyph; |
/* |
* Redraw. |
*/ |
y = vport->y; |
for (row = 0; row < vport->rows; row++) { |
unsigned int y = vport->y + ROW2Y(row); |
unsigned int yd; |
x = vport->x; |
for (col = 0; col < vport->cols; col++) { |
if ((row + lines >= 0) && (row + lines < vport->rows)) { |
glyph = vport->backbuf[BB_POS(vport, col, row + lines)]; |
for (yd = 0; yd < FONT_SCANLINES; yd++) { |
unsigned int x; |
unsigned int col; |
for (col = 0, x = vport->x; col < vport->cols; col++, x += FONT_WIDTH) { |
uint8_t glyph; |
if ((row + lines >= 0) && (row + lines < vport->rows)) { |
if (vport->backbuf[BB_POS(vport, col, row)] == vport->backbuf[BB_POS(vport, col, row + lines)]) |
if (vport->backbuf[BB_POS(vport, col, row)] == glyph) { |
x += FONT_WIDTH; |
continue; |
glyph = vport->backbuf[BB_POS(vport, col, row + lines)]; |
} else |
} |
} else { |
glyph = 0; |
} |
memcpy(&screen.fb_addr[FB_POS(x, y + yd)], |
&vport->glyphs[GLYPH_POS(glyph, yd, false)], screen.glyphscanline); |
(*vport->dglyph)(x, y, false, vport->glyphs, glyph, |
vport->style.fg_color, vport->style.bg_color); |
x += FONT_WIDTH; |
} |
y += FONT_SCANLINES; |
} |
} |
/* |
* Scroll backbuffer. |
*/ |
if (lines > 0) { |
memcpy(vport->backbuf, vport->backbuf + vport->cols * lines, vport->cols * (vport->rows - lines)); |
memset(&vport->backbuf[BB_POS(vport, 0, vport->rows - lines)], 0, vport->cols * lines); |
memmove(vport->backbuf, vport->backbuf + vport->cols * lines, |
vport->cols * (vport->rows - lines)); |
memset(&vport->backbuf[BB_POS(vport, 0, vport->rows - lines)], |
0, vport->cols * lines); |
} else { |
memcpy(vport->backbuf - vport->cols * lines, vport->backbuf, vport->cols * (vport->rows + lines)); |
memmove(vport->backbuf - vport->cols * lines, vport->backbuf, |
vport->cols * (vport->rows + lines)); |
memset(vport->backbuf, 0, - vport->cols * lines); |
} |
} |
/** Render glyphs |
* |
* Convert glyphs from device independent font |
346,18 → 397,11 |
for (x = 0; x < FONT_WIDTH; x++) { |
screen.rgb_conv(&vport->glyphs[GLYPH_POS(glyph, y, false) + x * screen.pixelbytes], |
(fb_font[glyph * FONT_SCANLINES + y] & (1 << (7 - x))) |
? vport->style.fg_color : vport->style.bg_color); |
? 0xffffff : 0x000000); |
uint32_t curcolor; |
if (y < FONT_SCANLINES - 2) |
curcolor = |
screen.rgb_conv(&vport->glyphs[GLYPH_POS(glyph, y, true) + x * screen.pixelbytes], |
(fb_font[glyph * FONT_SCANLINES + y] & (1 << (7 - x))) |
? vport->style.fg_color : vport->style.bg_color; |
else |
curcolor = vport->style.fg_color; |
screen.rgb_conv(&vport->glyphs[GLYPH_POS(glyph, y, true) + x * screen.pixelbytes], curcolor); |
? 0x000000 : 0xffffff); |
} |
} |
} |
392,6 → 436,7 |
unsigned int rows = height / FONT_SCANLINES; |
unsigned int bbsize = cols * rows; |
unsigned int glyphsize = 2 * FONT_GLYPHS * screen.glyphbytes; |
unsigned int word_size = sizeof(unsigned long); |
uint8_t *backbuf = (uint8_t *) malloc(bbsize); |
if (!backbuf) |
428,6 → 473,23 |
viewports[i].glyphs = glyphs; |
viewports[i].bgpixel = bgpixel; |
/* |
* Conditions necessary to select aligned version: |
* |
* - word size is divisible by pixelbytes |
* - cell scanline size is divisible by word size |
* - cell scanlines are word-aligned |
*/ |
if ((word_size % screen.pixelbytes) == 0 && |
(FONT_WIDTH * screen.pixelbytes) % word_size == 0 && |
(x * screen.pixelbytes) % word_size == 0 && |
screen.scanline % word_size == 0) { |
viewports[i].dglyph = draw_glyph_aligned; |
} else { |
viewports[i].dglyph = draw_glyph_fallback; |
} |
viewports[i].cur_col = 0; |
viewports[i].cur_row = 0; |
viewports[i].cursor_active = false; |
504,8 → 566,136 |
} |
/** Draw glyph at given position relative to viewport |
/** Draw a glyph, takes advantage of alignment. |
* |
* This version can only be used if the following conditions are met: |
* |
* - word size is divisible by pixelbytes |
* - cell scanline size is divisible by word size |
* - cell scanlines are word-aligned |
* |
* It makes use of the pre-rendered mask to process (possibly) several |
* pixels at once (word size / pixelbytes pixels at a time are processed) |
* making it very fast. Most notably this version is not applicable at 24 bits |
* per pixel. |
* |
* @param x x coordinate of top-left corner on screen. |
* @param y y coordinate of top-left corner on screen. |
* @param cursor Draw glyph with cursor |
* @param glyphs Pointer to font bitmap. |
* @param glyph Code of the glyph to draw. |
* @param fg_color Foreground color. |
* @param bg_color Backgroudn color. |
*/ |
static void draw_glyph_aligned(unsigned int x, unsigned int y, bool cursor, |
uint8_t *glyphs, uint8_t glyph, uint32_t fg_color, uint32_t bg_color) |
{ |
unsigned int i, yd; |
unsigned long fg_buf, bg_buf; |
unsigned long *maskp, *dp; |
unsigned long mask; |
unsigned int ww, d_add; |
/* |
* Prepare a pair of words, one filled with foreground-color |
* pattern and the other filled with background-color pattern. |
*/ |
for (i = 0; i < sizeof(unsigned long) / screen.pixelbytes; i++) { |
screen.rgb_conv(&((uint8_t *)&fg_buf)[i * screen.pixelbytes], |
fg_color); |
screen.rgb_conv(&((uint8_t *)&bg_buf)[i * screen.pixelbytes], |
bg_color); |
} |
/* Pointer to the current position in the mask. */ |
maskp = (unsigned long *) &glyphs[GLYPH_POS(glyph, 0, cursor)]; |
/* Pointer to the current position on the screen. */ |
dp = (unsigned long *) &screen.fb_addr[FB_POS(x, y)]; |
/* Width of the character cell in words. */ |
ww = FONT_WIDTH * screen.pixelbytes / sizeof(unsigned long); |
/* Offset to add when moving to another screen scanline. */ |
d_add = screen.scanline - FONT_WIDTH * screen.pixelbytes; |
for (yd = 0; yd < FONT_SCANLINES; yd++) { |
/* |
* Now process the cell scanline, combining foreground |
* and background color patters using the pre-rendered mask. |
*/ |
for (i = 0; i < ww; i++) { |
mask = *maskp++; |
*dp++ = (fg_buf & mask) | (bg_buf & ~mask); |
} |
/* Move to the beginning of the next scanline of the cell. */ |
dp = (unsigned long *) ((uint8_t *) dp + d_add); |
} |
} |
/** Draw a glyph, fallback version. |
* |
* This version does not make use of the pre-rendered mask, it uses |
* the font bitmap directly. It works always, but it is slower. |
* |
* @param x x coordinate of top-left corner on screen. |
* @param y y coordinate of top-left corner on screen. |
* @param cursor Draw glyph with cursor |
* @param glyphs Pointer to font bitmap. |
* @param glyph Code of the glyph to draw. |
* @param fg_color Foreground color. |
* @param bg_color Backgroudn color. |
*/ |
void draw_glyph_fallback(unsigned int x, unsigned int y, bool cursor, |
uint8_t *glyphs, uint8_t glyph, uint32_t fg_color, uint32_t bg_color) |
{ |
unsigned int i, j, yd; |
uint8_t fg_buf[4], bg_buf[4]; |
uint8_t *dp, *sp; |
unsigned int d_add; |
uint8_t b; |
/* Pre-render 1x the foreground and background color pixels. */ |
if (cursor) { |
screen.rgb_conv(fg_buf, bg_color); |
screen.rgb_conv(bg_buf, fg_color); |
} else { |
screen.rgb_conv(fg_buf, fg_color); |
screen.rgb_conv(bg_buf, bg_color); |
} |
/* Pointer to the current position on the screen. */ |
dp = (uint8_t *) &screen.fb_addr[FB_POS(x, y)]; |
/* Offset to add when moving to another screen scanline. */ |
d_add = screen.scanline - FONT_WIDTH * screen.pixelbytes; |
for (yd = 0; yd < FONT_SCANLINES; yd++) { |
/* Byte containing bits of the glyph scanline. */ |
b = fb_font[glyph * FONT_SCANLINES + yd]; |
for (i = 0; i < FONT_WIDTH; i++) { |
/* Choose color based on the current bit. */ |
sp = (b & 0x80) ? fg_buf : bg_buf; |
/* Copy the pixel. */ |
for (j = 0; j < screen.pixelbytes; j++) { |
*dp++ = *sp++; |
} |
/* Move to the next bit. */ |
b = b << 1; |
} |
/* Move to the beginning of the next scanline of the cell. */ |
dp += d_add; |
} |
} |
/** Draw glyph at specified position in viewport. |
* |
* @param vport Viewport identification |
* @param cursor Draw glyph with cursor |
* @param col Screen position relative to viewport |
512,20 → 702,19 |
* @param row Screen position relative to viewport |
* |
*/ |
static void draw_glyph(viewport_t *vport, bool cursor, unsigned int col, unsigned int row) |
static void draw_vp_glyph(viewport_t *vport, bool cursor, unsigned int col, |
unsigned int row) |
{ |
unsigned int x = vport->x + COL2X(col); |
unsigned int y = vport->y + ROW2Y(row); |
unsigned int yd; |
uint8_t glyph; |
uint8_t glyph = vport->backbuf[BB_POS(vport, col, row)]; |
glyph = vport->backbuf[BB_POS(vport, col, row)]; |
for (yd = 0; yd < FONT_SCANLINES; yd++) |
memcpy(&screen.fb_addr[FB_POS(x, y + yd)], |
&vport->glyphs[GLYPH_POS(glyph, yd, cursor)], screen.glyphscanline); |
(*vport->dglyph)(x, y, cursor, vport->glyphs, glyph, |
vport->style.fg_color, vport->style.bg_color); |
} |
/** Hide cursor if it is shown |
* |
*/ |
532,7 → 721,7 |
static void cursor_hide(viewport_t *vport) |
{ |
if ((vport->cursor_active) && (vport->cursor_shown)) { |
draw_glyph(vport, false, vport->cur_col, vport->cur_row); |
draw_vp_glyph(vport, false, vport->cur_col, vport->cur_row); |
vport->cursor_shown = false; |
} |
} |
545,7 → 734,7 |
{ |
/* Do not check for cursor_shown */ |
if (vport->cursor_active) { |
draw_glyph(vport, true, vport->cur_col, vport->cur_row); |
draw_vp_glyph(vport, true, vport->cur_col, vport->cur_row); |
vport->cursor_shown = true; |
} |
} |
579,7 → 768,7 |
cursor_hide(vport); |
vport->backbuf[BB_POS(vport, col, row)] = c; |
draw_glyph(vport, false, col, row); |
draw_vp_glyph(vport, false, col, row); |
vport->cur_col = col; |
vport->cur_row = row; |
616,7 → 805,7 |
if (glyph != data[i].character) { |
vport->backbuf[BB_POS(vport, col, row)] = data[i].character; |
draw_glyph(vport, false, col, row); |
draw_vp_glyph(vport, false, col, row); |
} |
} |
cursor_show(vport); |
930,7 → 1119,7 |
if ((pointer_shown) || (!pointer_enabled)) |
return; |
/* Save image under the cursor */ |
/* Save image under the pointer. */ |
if (pointer_vport == -1) { |
pointer_vport = vport_create(pointer_x, pointer_y, pointer_width, pointer_height); |
if (pointer_vport < 0) |
945,7 → 1134,7 |
else |
copy_vp_to_pixmap(&viewports[pointer_vport], &pixmaps[pointer_pixmap]); |
/* Draw cursor */ |
/* Draw mouse pointer. */ |
for (i = 0; i < pointer_height; i++) |
for (j = 0; j < pointer_width; j++) { |
bytepos = i * ((pointer_width - 1) / 8 + 1) + j / 8; |
966,7 → 1155,7 |
static void mouse_hide(void) |
{ |
/* Restore image under the cursor */ |
/* Restore image under the pointer. */ |
if (pointer_shown) { |
draw_pixmap(pointer_vport, pointer_pixmap); |
pointer_shown = 0; |
1291,7 → 1480,6 |
case FB_SET_STYLE: |
vport->style.fg_color = IPC_GET_ARG1(call); |
vport->style.bg_color = IPC_GET_ARG2(call); |
render_glyphs(vport); |
retval = EOK; |
break; |
case FB_GET_RESOLUTION: |