| 881 |
theseven |
1 |
#include "global.h"
|
|
|
2 |
#include "interface/framebuffer/framebuffer.h"
|
|
|
3 |
#include "sys/util.h"
|
|
|
4 |
|
|
|
5 |
const uint8_t framebuffer_format_wordsize[] =
|
|
|
6 |
{
|
|
|
7 |
[FRAMEBUFFER_FORMAT_I1] = 1,
|
|
|
8 |
[FRAMEBUFFER_FORMAT_X1R1G1B1] = 4,
|
|
|
9 |
[FRAMEBUFFER_FORMAT_I1R1G1B1] = 4,
|
|
|
10 |
[FRAMEBUFFER_FORMAT_X7I1] = 8,
|
|
|
11 |
[FRAMEBUFFER_FORMAT_X5R1G1B1] = 8,
|
|
|
12 |
[FRAMEBUFFER_FORMAT_X2R2G2B2] = 8,
|
|
|
13 |
[FRAMEBUFFER_FORMAT_R2G3B3] = 8,
|
|
|
14 |
[FRAMEBUFFER_FORMAT_X1R5G5B5_LE] = 16,
|
|
|
15 |
[FRAMEBUFFER_FORMAT_X1R5G5B5_BE] = 16,
|
|
|
16 |
[FRAMEBUFFER_FORMAT_R5G6B5_LE] = 16,
|
|
|
17 |
[FRAMEBUFFER_FORMAT_R5G6B5_BE] = 16,
|
|
|
18 |
[FRAMEBUFFER_FORMAT_R8G8B8_LE] = 24,
|
|
|
19 |
[FRAMEBUFFER_FORMAT_R8G8B8_BE] = 24,
|
|
|
20 |
[FRAMEBUFFER_FORMAT_X31I1_LE] = 32,
|
|
|
21 |
[FRAMEBUFFER_FORMAT_X31I1_BE] = 32,
|
|
|
22 |
[FRAMEBUFFER_FORMAT_X8R8G8B8_LE] = 32,
|
|
|
23 |
[FRAMEBUFFER_FORMAT_X8R8G8B8_BE] = 32,
|
|
|
24 |
};
|
|
|
25 |
|
|
|
26 |
uint32_t framebuffer_color_to_rgb888_be(enum framebuffer_format format, uint32_t color)
|
|
|
27 |
{
|
|
|
28 |
uint32_t result = 0xff;
|
|
|
29 |
switch (format)
|
|
|
30 |
{
|
|
|
31 |
case FRAMEBUFFER_FORMAT_X31I1_LE:
|
|
|
32 |
color = swap32(color);
|
|
|
33 |
case FRAMEBUFFER_FORMAT_I1:
|
|
|
34 |
case FRAMEBUFFER_FORMAT_X7I1:
|
|
|
35 |
case FRAMEBUFFER_FORMAT_X31I1_BE:
|
|
|
36 |
result = (color & 1) ? 0xffffff : 0;
|
|
|
37 |
break;
|
|
|
38 |
case FRAMEBUFFER_FORMAT_I1R1G1B1:
|
|
|
39 |
result = (color & 8) ? 0xff : 0x7f;
|
|
|
40 |
case FRAMEBUFFER_FORMAT_X1R1G1B1:
|
|
|
41 |
case FRAMEBUFFER_FORMAT_X5R1G1B1:
|
|
|
42 |
result = ((color & 4) ? (result << 16) : 0) | ((color & 2) ? (result << 8) : 0) | ((color & 1) ? result : 0);
|
|
|
43 |
break;
|
|
|
44 |
case FRAMEBUFFER_FORMAT_X2R2G2B2:
|
|
|
45 |
result = ((color & 0x30) << 18) | ((color & 0xc) << 14) | ((color & 3) << 6);
|
|
|
46 |
result |= result >> 2;
|
|
|
47 |
result |= result >> 4;
|
|
|
48 |
break;
|
|
|
49 |
case FRAMEBUFFER_FORMAT_R2G3B3:
|
|
|
50 |
result = ((color & 0xc0) << 16) | ((color & 0x38) << 10) | ((color & 7) << 5);
|
|
|
51 |
result |= (result & 0xc00000) >> 2;
|
|
|
52 |
result |= (result & 0xf00000) >> 4;
|
|
|
53 |
result |= (result & 0xe0e0) >> 3;
|
|
|
54 |
result |= (result & 0xc0c0) >> 6;
|
|
|
55 |
break;
|
|
|
56 |
case FRAMEBUFFER_FORMAT_X1R5G5B5_LE:
|
|
|
57 |
color = swap16(color);
|
|
|
58 |
case FRAMEBUFFER_FORMAT_X1R5G5B5_BE:
|
|
|
59 |
result = ((color & 0x7c00) << 9) | ((color & 0x3e0) << 6) | ((color & 0x1f) << 3);
|
|
|
60 |
result |= (result & 0xe0e0e0) >> 5;
|
|
|
61 |
break;
|
|
|
62 |
case FRAMEBUFFER_FORMAT_R5G6B5_LE:
|
|
|
63 |
color = swap16(color);
|
|
|
64 |
case FRAMEBUFFER_FORMAT_R5G6B5_BE:
|
|
|
65 |
result = ((color & 0xf800) << 8) | ((color & 0x7e0) << 5) | ((color & 0x1f) << 3);
|
|
|
66 |
result |= (result & 0xe000e0) >> 5;
|
|
|
67 |
result |= (result & 0xc000) >> 6;
|
|
|
68 |
break;
|
|
|
69 |
case FRAMEBUFFER_FORMAT_R8G8B8_LE:
|
|
|
70 |
color <<= 8;
|
|
|
71 |
case FRAMEBUFFER_FORMAT_X8R8G8B8_LE:
|
|
|
72 |
color = swap32(color);
|
|
|
73 |
case FRAMEBUFFER_FORMAT_R8G8B8_BE:
|
|
|
74 |
case FRAMEBUFFER_FORMAT_X8R8G8B8_BE:
|
|
|
75 |
result = color;
|
|
|
76 |
}
|
|
|
77 |
return result;
|
|
|
78 |
}
|
|
|
79 |
|
|
|
80 |
uint32_t framebuffer_color_from_rgb888_be(enum framebuffer_format format, uint32_t color)
|
|
|
81 |
{
|
|
|
82 |
uint32_t result = 0;
|
|
|
83 |
uint8_t r = (color & 0xff0000) >> 16;
|
|
|
84 |
uint8_t g = (color & 0xff00) >> 8;
|
|
|
85 |
uint8_t b = color & 0xff;
|
|
|
86 |
switch (format)
|
|
|
87 |
{
|
|
|
88 |
case FRAMEBUFFER_FORMAT_I1:
|
|
|
89 |
case FRAMEBUFFER_FORMAT_X7I1:
|
|
|
90 |
case FRAMEBUFFER_FORMAT_X31I1_BE:
|
|
|
91 |
result = r + g + b >= 0x180 ? 1 : 0;
|
|
|
92 |
break;
|
|
|
93 |
case FRAMEBUFFER_FORMAT_X31I1_LE:
|
|
|
94 |
result = r + g + b >= 0x180 ? 0x01000000 : 0;
|
|
|
95 |
break;
|
|
|
96 |
case FRAMEBUFFER_FORMAT_X1R1G1B1:
|
|
|
97 |
case FRAMEBUFFER_FORMAT_X5R1G1B1:
|
|
|
98 |
result = ((r & 0x80) >> 5) | ((g & 0x80) >> 6) | ((b & 0x80) >> 7);
|
|
|
99 |
break;
|
|
|
100 |
case FRAMEBUFFER_FORMAT_I1R1G1B1:
|
|
|
101 |
result = r + g + b >= 0x180 ? (8 | (r >= 0x80 ? 4 : 0) | (g >= 0x80 ? 2 : 0) | (b >= 0x80 ? 1 : 0))
|
|
|
102 |
: ((r >= 0x40 ? 4 : 0) | (g >= 0x40 ? 2 : 0) | (b >= 0x40 ? 1 : 0));
|
|
|
103 |
break;
|
|
|
104 |
case FRAMEBUFFER_FORMAT_X2R2G2B2:
|
|
|
105 |
result = (((r - (r >> 2)) >> 6) << 4) | (((g - (g >> 2)) >> 6) << 2) | ((b - (b >> 2)) >> 6);
|
|
|
106 |
break;
|
|
|
107 |
case FRAMEBUFFER_FORMAT_R2G3B3:
|
|
|
108 |
result = (((r - (r >> 2)) >> 6) << 6) | (((g - (g >> 3)) >> 5) << 3) | ((b - (b >> 3)) >> 5);
|
|
|
109 |
break;
|
|
|
110 |
case FRAMEBUFFER_FORMAT_X1R5G5B5_BE:
|
|
|
111 |
result = (((r - (r >> 5)) >> 3) << 10) | (((g - (g >> 5)) >> 3) << 5) | ((b - (b >> 5)) >> 3);
|
|
|
112 |
break;
|
|
|
113 |
case FRAMEBUFFER_FORMAT_X1R5G5B5_LE:
|
|
|
114 |
result = swap16((((r - (r >> 5)) >> 3) << 10) | (((g - (g >> 5)) >> 3) << 5) | ((b - (b >> 5)) >> 3));
|
|
|
115 |
break;
|
|
|
116 |
case FRAMEBUFFER_FORMAT_R5G6B5_BE:
|
|
|
117 |
result = (((r - (r >> 5)) >> 3) << 11) | (((g - (g >> 6)) >> 2) << 5) | ((b - (b >> 5)) >> 3);
|
|
|
118 |
break;
|
|
|
119 |
case FRAMEBUFFER_FORMAT_R5G6B5_LE:
|
|
|
120 |
result = swap16((((r - (r >> 5)) >> 3) << 11) | (((g - (g >> 6)) >> 2) << 5) | ((b - (b >> 5)) >> 3));
|
|
|
121 |
break;
|
|
|
122 |
case FRAMEBUFFER_FORMAT_R8G8B8_LE:
|
|
|
123 |
color <<= 8;
|
|
|
124 |
case FRAMEBUFFER_FORMAT_X8R8G8B8_LE:
|
|
|
125 |
color = swap32(color);
|
|
|
126 |
case FRAMEBUFFER_FORMAT_R8G8B8_BE:
|
|
|
127 |
case FRAMEBUFFER_FORMAT_X8R8G8B8_BE:
|
|
|
128 |
result = color;
|
|
|
129 |
break;
|
|
|
130 |
}
|
|
|
131 |
return result;
|
|
|
132 |
}
|
|
|
133 |
|
|
|
134 |
uint32_t framebuffer_convert_color(enum framebuffer_format from, enum framebuffer_format to, uint32_t color)
|
|
|
135 |
{
|
|
|
136 |
return framebuffer_color_from_rgb888_be(to, framebuffer_color_to_rgb888_be(from, color));
|
|
|
137 |
}
|
|
|
138 |
|
|
|
139 |
uint32_t framebuffer_get_pixel(const struct framebuffer_instance* instance, int x, int y)
|
|
|
140 |
{
|
|
|
141 |
int wsize = framebuffer_format_wordsize[instance->format];
|
|
|
142 |
int bit = (instance->width * y + x) * wsize;
|
|
|
143 |
uint32_t color = (swap32(((uint32_t*)instance->data)[bit >> 5]) >> (32 - (bit & 31) - wsize)) & (0xffffffff >> (32 - wsize));
|
|
|
144 |
if (wsize == 16) return swap16(color);
|
|
|
145 |
if (wsize == 32) return swap32(color);
|
|
|
146 |
return color;
|
|
|
147 |
}
|
|
|
148 |
|
|
|
149 |
void framebuffer_set_pixel(const struct framebuffer_instance* instance, int x, int y, uint32_t color)
|
|
|
150 |
{
|
|
|
151 |
int wsize = framebuffer_format_wordsize[instance->format];
|
|
|
152 |
if (wsize == 16) color = swap16(color);
|
|
|
153 |
else if (wsize == 32) color = swap32(color);
|
|
|
154 |
int bit = (instance->width * y + x) * wsize;
|
|
|
155 |
int byte = bit >> 5;
|
|
|
156 |
bit = 32 - (bit & 31) - wsize;
|
|
|
157 |
uint32_t mask = 0xffffffff >> (32 - wsize);
|
|
|
158 |
uint32_t data = swap32(((uint32_t*)instance->data)[byte]);
|
|
|
159 |
((uint32_t*)instance->data)[byte] = swap32((data & ~(mask << bit)) | ((color & mask) << bit));
|
|
|
160 |
}
|
|
|
161 |
|
|
|
162 |
void framebuffer_fill(const struct framebuffer_instance* instance, int x, int y, int w, int h,
|
|
|
163 |
enum framebuffer_format format, uint32_t color, enum framebuffer_conversion_quality quality)
|
|
|
164 |
{
|
|
|
165 |
int stride = instance->width;
|
|
|
166 |
enum framebuffer_format fmt = instance->format;
|
|
|
167 |
int wsize = framebuffer_format_wordsize[fmt];
|
|
|
168 |
if (format != fmt)
|
|
|
169 |
{
|
|
|
170 |
if (framebuffer_format_wordsize[format] == 16) color = swap16(color);
|
|
|
171 |
else if (framebuffer_format_wordsize[format] == 32) color = swap32(color);
|
|
|
172 |
color = framebuffer_convert_color(format, fmt, color);
|
|
|
173 |
if (wsize == 16) color = swap16(color);
|
|
|
174 |
else if (wsize == 32) color = swap32(color);
|
|
|
175 |
}
|
|
|
176 |
|
|
|
177 |
if (w == stride)
|
|
|
178 |
{
|
|
|
179 |
w *= h;
|
|
|
180 |
h = 1;
|
|
|
181 |
}
|
|
|
182 |
|
|
|
183 |
color &= 0xffffffff >> (32 - wsize);
|
|
|
184 |
while (wsize < 32 && !(w & 1) && !(x & 1) && !(stride & 1))
|
|
|
185 |
{
|
|
|
186 |
color |= color << wsize;
|
|
|
187 |
wsize <<= 1;
|
|
|
188 |
w >>= 1;
|
|
|
189 |
x >>= 1;
|
|
|
190 |
stride >>= 1;
|
|
|
191 |
}
|
|
|
192 |
if (wsize >= 8)
|
|
|
193 |
{
|
|
|
194 |
void* out = instance->data + (y * stride + x) * (wsize >> 3);
|
|
|
195 |
while (h--)
|
|
|
196 |
{
|
|
|
197 |
if (wsize == 32)
|
|
|
198 |
{
|
|
|
199 |
uint32_t* ptr = out;
|
|
|
200 |
int pixels = w;
|
|
|
201 |
while (pixels--) *ptr++ = color;
|
|
|
202 |
}
|
|
|
203 |
else if (wsize == 16)
|
|
|
204 |
{
|
|
|
205 |
uint16_t* ptr = out;
|
|
|
206 |
int pixels = w;
|
|
|
207 |
while (pixels--) *ptr++ = color;
|
|
|
208 |
}
|
|
|
209 |
else memset(out, color, w);
|
|
|
210 |
out += stride * (wsize >> 3);
|
|
|
211 |
}
|
|
|
212 |
return;
|
|
|
213 |
}
|
|
|
214 |
|
|
|
215 |
int mask = 0xffffffff >> (32 - wsize);
|
|
|
216 |
uint32_t* out = instance->data;
|
|
|
217 |
int bit = (y * stride + x) * wsize;
|
|
|
218 |
out += bit >> 5;
|
|
|
219 |
bit &= 31;
|
|
|
220 |
while (h--)
|
|
|
221 |
{
|
|
|
222 |
int pixels = w;
|
|
|
223 |
uint32_t data = swap32(*out);
|
|
|
224 |
while (pixels--)
|
|
|
225 |
{
|
|
|
226 |
if (!bit) data = swap32(*out);
|
|
|
227 |
data = (data & ~(mask << (32 - bit - wsize))) | (color << (32 - bit - wsize));
|
|
|
228 |
bit += wsize;
|
|
|
229 |
if (bit == 32)
|
|
|
230 |
{
|
|
|
231 |
*out++ = swap32(data);
|
|
|
232 |
bit = 0;
|
|
|
233 |
}
|
|
|
234 |
}
|
|
|
235 |
if (bit) *out = swap32(data);
|
|
|
236 |
bit += (stride - w) * wsize;
|
|
|
237 |
out += bit >> 5;
|
|
|
238 |
bit &= 31;
|
|
|
239 |
}
|
|
|
240 |
}
|
|
|
241 |
|
|
|
242 |
void framebuffer_blit(const struct framebuffer_instance* infb, int inx, int iny,
|
|
|
243 |
const struct framebuffer_instance* outfb, int outx, int outy,
|
|
|
244 |
int w, int h, enum framebuffer_conversion_quality quality)
|
|
|
245 |
{
|
|
|
246 |
int instride = infb->width;
|
|
|
247 |
int outstride = outfb->width;
|
|
|
248 |
enum framebuffer_format infmt = infb->format;
|
|
|
249 |
enum framebuffer_format outfmt = outfb->format;
|
|
|
250 |
int inwsize = framebuffer_format_wordsize[infmt];
|
|
|
251 |
int outwsize = framebuffer_format_wordsize[outfmt];
|
|
|
252 |
|
|
|
253 |
if (w == instride && w == outstride)
|
|
|
254 |
{
|
|
|
255 |
w *= h;
|
|
|
256 |
h = 1;
|
|
|
257 |
}
|
|
|
258 |
|
|
|
259 |
if (infmt == outfmt)
|
|
|
260 |
{
|
|
|
261 |
while (inwsize < 32 && !(w & 1) && !(inx & 1) && !(outx & 1) && !(instride & 1) && !(outstride & 1))
|
|
|
262 |
{
|
|
|
263 |
inwsize <<= 1;
|
|
|
264 |
outwsize <<= 1;
|
|
|
265 |
w >>= 1;
|
|
|
266 |
inx >>= 1;
|
|
|
267 |
outx >>= 1;
|
|
|
268 |
instride >>= 1;
|
|
|
269 |
outstride >>= 1;
|
|
|
270 |
}
|
|
|
271 |
if (inwsize >= 8)
|
|
|
272 |
{
|
|
|
273 |
void* in = infb->data + (iny * instride + inx) * (inwsize >> 3);
|
|
|
274 |
void* out = outfb->data + (outy * outstride + outx) * (outwsize >> 3);
|
|
|
275 |
while (h--)
|
|
|
276 |
{
|
|
|
277 |
memcpy(out, in, w * (outwsize >> 3));
|
|
|
278 |
in += (instride - w) * (inwsize >> 3);
|
|
|
279 |
out += (outstride - w) * (outwsize >> 3);
|
|
|
280 |
}
|
|
|
281 |
return;
|
|
|
282 |
}
|
|
|
283 |
}
|
|
|
284 |
|
|
|
285 |
int inmask = 0xffffffff >> (32 - inwsize);
|
|
|
286 |
int outmask = 0xffffffff >> (32 - outwsize);
|
|
|
287 |
uint32_t* in = infb->data;
|
|
|
288 |
uint32_t* out = outfb->data;
|
|
|
289 |
int inbit = (iny * instride + inx) * inwsize;
|
|
|
290 |
int outbit = (outy * outstride + outx) * outwsize;
|
|
|
291 |
in += inbit >> 5;
|
|
|
292 |
out += outbit >> 5;
|
|
|
293 |
inbit &= 31;
|
|
|
294 |
outbit &= 31;
|
|
|
295 |
while (h--)
|
|
|
296 |
{
|
|
|
297 |
int pixels = w;
|
|
|
298 |
uint32_t idata = swap32(*in) << inbit;
|
|
|
299 |
uint32_t odata = swap32(*out);
|
|
|
300 |
while (pixels--)
|
|
|
301 |
{
|
|
|
302 |
if (inbit == 32)
|
|
|
303 |
{
|
|
|
304 |
idata = swap32(*++in);
|
|
|
305 |
inbit = 0;
|
|
|
306 |
}
|
|
|
307 |
if (!outbit) odata = swap32(*out);
|
|
|
308 |
idata = ((idata << inwsize) | (idata >> (32 - inwsize)));
|
|
|
309 |
uint32_t data = idata & inmask;
|
|
|
310 |
if (infmt != outfmt) data = framebuffer_convert_color(infmt, outfmt, data);
|
|
|
311 |
odata = (odata & ~(outmask << (32 - outbit - outwsize))) | (data << (32 - outbit - outwsize));
|
|
|
312 |
inbit += inwsize;
|
|
|
313 |
outbit += outwsize;
|
|
|
314 |
if (outbit == 32)
|
|
|
315 |
{
|
|
|
316 |
*out++ = swap32(odata);
|
|
|
317 |
outbit = 0;
|
|
|
318 |
}
|
|
|
319 |
}
|
|
|
320 |
if (outbit) *out = swap32(odata);
|
|
|
321 |
inbit += (instride - w) * inwsize;
|
|
|
322 |
outbit += (outstride - w) * outwsize;
|
|
|
323 |
in += inbit >> 5;
|
|
|
324 |
out += outbit >> 5;
|
|
|
325 |
inbit &= 31;
|
|
|
326 |
outbit &= 31;
|
|
|
327 |
}
|
|
|
328 |
}
|
|
|
329 |
|
|
|
330 |
void framebuffer_update(const struct framebuffer_instance* instance, int x, int y, int w, int h)
|
|
|
331 |
{
|
|
|
332 |
instance->update_handler(instance->update_handler_arg, instance, x, y, w, h);
|
|
|
333 |
}
|