2 Copyright © 2013, The AROS Development Team. All rights reserved.
5 Desc: Graphical framebuffer console.
8 #include <bootconsole.h>
12 * Framebuffer access can be extremely slow, so we use a mirror buffer.
13 * Our mirror is a monochrome text-mode representation of the screen.
14 * Unused positions are filled with zero bytes, this helps to determine
15 * line lengths for faster scrolling.
16 * These variables need to survive accross warm reboot, so we explicitly place them in .data section.
18 __attribute__((section(".data"))) char *fb_Mirror
= NULL
;
20 __attribute__((section(".data"))) static unsigned int fb_BytesPerLine
= 0; /* Bytes per line */
21 __attribute__((section(".data"))) static unsigned int fb_BytesPerPix
= 0; /* Bytes per pixel */
24 * Calculate length of current line in the fb_Mirror buffer.
25 * Similar to strlen() but takes into account maximum line length.
27 static unsigned int lineLen(const char *s
)
31 for (len
= 0; len
< scr_Width
; len
++)
40 /* Render a character at (xc, yc) */
41 static void RenderChar(unsigned char c
, unsigned int xc
, unsigned int yc
)
44 const unsigned char *font
= &fontData
[c
* fontHeight
];
45 void *ptr
= scr_FrameBuffer
+ fb_BytesPerLine
* yc
* fontHeight
+ fb_BytesPerPix
* xc
* fontWidth
;
47 /* Store our character in the mirror buffer */
49 fb_Mirror
[scr_Width
* yc
+ xc
] = c
;
51 /* Render zero bytes as spaces (do not depend on particular font) */
55 /* Now render it on the screen */
56 for (y
= 0; y
< fontHeight
; y
++)
58 unsigned char in
= *font
++;
61 for (x
= 0; x
< fontWidth
; x
++)
63 /* Get pixel from the font data */
64 int val
= (in
& 0x80) ? -1 : 0;
66 /* Draw the pixel. Do it in a single VRAM access, again to speed up */
67 switch (fb_BytesPerPix
)
74 /* qemu's truecolor modes are known to be 3 bytes per pixel */
76 *((char *)p
+ 2) = val
;
91 ptr
+= fb_BytesPerLine
;
95 void * malloc(size_t size
);
97 void fb_Init(unsigned int width
, unsigned int height
, unsigned int depth
, unsigned int pitch
)
99 scr_Width
= width
/ fontWidth
;
100 fb_BytesPerPix
= depth
>> 3;
101 fb_BytesPerLine
= pitch
;
103 fb_Mirror
= malloc(scr_Width
* (height
+ fontHeight
- 1) / fontHeight
);
108 void fb_Resize(unsigned int height
)
110 scr_Height
= height
/ fontHeight
;
117 void *ptr
= scr_FrameBuffer
;
120 /* Reset current position */
124 /* Clear the framebuffer, line by line */
125 for (i
= 0; i
< scr_Height
* fontHeight
; i
++)
127 memset(ptr
, 0, fb_BytesPerPix
* scr_Width
* fontWidth
);
128 ptr
+= fb_BytesPerLine
;
131 /* Clear mirror buffer */
133 memset(fb_Mirror
, 0, scr_Width
* scr_Height
);
136 void fb_Putc(char chr
)
138 /* Ignore null bytes, they are output by formatting routines as terminators */
148 /* Reached end of line ? New line if so. */
149 if ((chr
== '\n') || (scr_XPos
>= scr_Width
))
155 if (scr_YPos
>= scr_Height
)
159 /* destLen contains length of line being erased */
160 unsigned int destLen
= lineLen(fb_Mirror
);
161 /* ptr contains address of line being scrolled */
162 char *ptr
= fb_Mirror
+ scr_Width
;
165 /* Reset line number */
166 scr_YPos
= scr_Height
- 1;
169 * Reprint the whole fb_Mirror (starting from the second line) at (0, 0).
170 * Update only used parts in order to speed up the scrolling.
172 for (yc
= 0; yc
< scr_YPos
; yc
++)
174 /* Calculate length of the line being scrolled */
175 unsigned int srcLen
= lineLen(ptr
);
178 * The next line (being reprinted on top ot the current one)
179 * must completely cover it, so we must copy a minimum of 'destLen' bytes.
180 * Mirror buffer contains zero bytes at unused positions, they will be
181 * rendered as blank spaces, erasing the previous text.
183 if (srcLen
> destLen
)
186 for (xc
= 0; xc
< destLen
; xc
++)
187 RenderChar(ptr
[xc
], xc
, yc
);
189 /* Go to the next line in fb_Mirror buffer */
191 /* Source becomes destination */
195 /* Clear the bottom line */
196 for (xc
= 0; xc
< destLen
; xc
++)
197 RenderChar(0, xc
, scr_YPos
);
201 /* We dont have a mirror buffer */
202 memmove((void *)scr_FrameBuffer
, (void *)scr_FrameBuffer
+ (fontHeight
* (fb_BytesPerPix
* scr_Width
* fontWidth
)), (((scr_Height
- 1) * fontHeight
) * (fb_BytesPerPix
* scr_Width
* fontWidth
)));
204 /* Clear last line on screen */
205 memset((void *)(scr_FrameBuffer
+ (((scr_Height
- 1) * fontHeight
) * (fb_BytesPerPix
* scr_Width
* fontWidth
))), 0, fb_BytesPerPix
* scr_Width
* fontWidth
* fontHeight
);
206 scr_YPos
= scr_Height
- 1;
213 /* Draw the character at current position and increment current column */
214 RenderChar(chr
, scr_XPos
++, scr_YPos
);