Added a test for MUIA_Listview_SelectChange.
[AROS.git] / arch / arm-raspi / boot / bc / screen_fb.c
blobbc5f140f37d7d62eb4b610782d59ed54275adcc9
1 /*
2 Copyright © 2013, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Graphical framebuffer console.
6 */
8 #include <bootconsole.h>
9 #include <string.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)
29 unsigned int len;
31 for (len = 0; len < scr_Width; len++)
33 if (s[len] == 0)
34 break;
37 return len;
40 /* Render a character at (xc, yc) */
41 static void RenderChar(unsigned char c, unsigned int xc, unsigned int yc)
43 unsigned int x, y;
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 */
48 if (fb_Mirror)
49 fb_Mirror[scr_Width * yc + xc] = c;
51 /* Render zero bytes as spaces (do not depend on particular font) */
52 if (c == '\0')
53 c = ' ';
55 /* Now render it on the screen */
56 for (y = 0; y < fontHeight; y++)
58 unsigned char in = *font++;
59 void *p = ptr;
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)
69 case 4:
70 *((int *)p) = val;
71 break;
73 case 3:
74 /* qemu's truecolor modes are known to be 3 bytes per pixel */
75 *((short *)p) = val;
76 *((char *)p + 2) = val;
77 break;
79 case 2:
80 *((short *)p) = val;
81 break;
83 case 1:
84 *((char *)p) = val;
85 break;
88 p += fb_BytesPerPix;
89 in <<= 1;
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);
105 fb_Resize(height);
108 void fb_Resize(unsigned int height)
110 scr_Height = height / fontHeight;
112 fb_Clear();
115 void fb_Clear(void)
117 void *ptr = scr_FrameBuffer;
118 unsigned int i;
120 /* Reset current position */
121 scr_XPos = 0;
122 scr_YPos = 0;
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 */
132 if (fb_Mirror)
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 */
139 if (chr == 0)
140 return;
142 if (chr == 0xFF)
144 fb_Clear();
145 return;
148 /* Reached end of line ? New line if so. */
149 if ((chr == '\n') || (scr_XPos >= scr_Width))
151 scr_XPos = 0;
152 scr_YPos++;
155 if (scr_YPos >= scr_Height)
157 if (fb_Mirror)
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;
163 unsigned int xc, yc;
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)
184 destLen = srcLen;
186 for (xc = 0; xc < destLen; xc++)
187 RenderChar(ptr[xc], xc, yc);
189 /* Go to the next line in fb_Mirror buffer */
190 ptr += scr_Width;
191 /* Source becomes destination */
192 destLen = srcLen;
195 /* Clear the bottom line */
196 for (xc = 0; xc < destLen; xc++)
197 RenderChar(0, xc, scr_YPos);
199 else
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;
210 if (chr == '\n')
211 return;
213 /* Draw the character at current position and increment current column */
214 RenderChar(chr, scr_XPos++, scr_YPos);