Contents of /trunk/linterm_tools/fw_builder/bootsplash/mng.c
Parent Directory | Revision Log
Revision 658 -
(show annotations)
(download)
Mon Jan 14 16:57:24 2008 UTC (16 years, 8 months ago) by niro
File MIME type: text/plain
File size: 9395 byte(s)
Mon Jan 14 16:57:24 2008 UTC (16 years, 8 months ago) by niro
File MIME type: text/plain
File size: 9395 byte(s)
initial import
1 | /* |
2 | * fbmngplay - fb console MNG player. |
3 | * (c) 2001-2002 by Stefan Reinauer, <stepan@suse.de> |
4 | * |
5 | * This program is based on mngplay, part of libmng, written and (C) by |
6 | * Ralph Giles <giles@ashlu.bc.ca> |
7 | * |
8 | * This program my be redistributed under the terms of the |
9 | * GNU General Public Licence, version 2, or at your preference, |
10 | * any later version. |
11 | */ |
12 | |
13 | #include <unistd.h> |
14 | #include <sys/time.h> |
15 | |
16 | #include "fbmngplay.h" |
17 | #include "console.h" |
18 | #include "mng.h" |
19 | |
20 | mngstuff *mng; |
21 | unsigned char *bufferstream; |
22 | unsigned long bufferpos = 0, buffersize = 0; |
23 | |
24 | /* |
25 | * callbacks for the mng decoder |
26 | */ |
27 | |
28 | /* memory allocation; data must be zeroed */ |
29 | mng_ptr mngalloc(mng_uint32 size) |
30 | { |
31 | return (mng_ptr) calloc(1, size); |
32 | } |
33 | |
34 | /* memory deallocation */ |
35 | void mngfree(mng_ptr p, mng_uint32 size) |
36 | { |
37 | free(p); |
38 | return; |
39 | } |
40 | |
41 | mng_bool mngopenstream(mng_handle mng) |
42 | { |
43 | mngstuff *mymng; |
44 | |
45 | /* look up our stream struct */ |
46 | mymng = (mngstuff *) mng_get_userdata(mng); |
47 | |
48 | /* open the file */ |
49 | mymng->file = fopen(mymng->filename, "rb"); |
50 | if (mymng->file == NULL) { |
51 | fprintf(stderr, "unable to open '%s'\n", mymng->filename); |
52 | run = 0; |
53 | return MNG_FALSE; |
54 | } |
55 | |
56 | if (buffered) { |
57 | unsigned long len; |
58 | fseek(mymng->file, 0, SEEK_END); |
59 | len = ftell(mymng->file); |
60 | rewind(mymng->file); |
61 | bufferstream = malloc(len); |
62 | if (!bufferstream) { |
63 | /* Not enough memory for buffers |
64 | * -> we go back to unbuffered mode |
65 | */ |
66 | printf("Reverted to non buffered mode.\n"); |
67 | buffered = 0; |
68 | return MNG_TRUE; |
69 | } |
70 | buffersize = len; |
71 | fread(bufferstream, 1, len, mymng->file); |
72 | bufferpos = 0; |
73 | fclose(mymng->file); |
74 | mymng->file = NULL; |
75 | } |
76 | |
77 | return MNG_TRUE; |
78 | } |
79 | |
80 | mng_bool mngclosestream(mng_handle mng) |
81 | { |
82 | mngstuff *mymng; |
83 | |
84 | /* look up our stream struct */ |
85 | mymng = (mngstuff *) mng_get_userdata(mng); |
86 | |
87 | /* close the file */ |
88 | if (mymng->file) |
89 | fclose(mymng->file); |
90 | mymng->file = NULL; /* for safety */ |
91 | |
92 | if (bufferstream) { |
93 | free(bufferstream); |
94 | bufferstream = 0; |
95 | buffersize = 0; |
96 | bufferpos = 0; |
97 | } |
98 | return MNG_TRUE; |
99 | } |
100 | |
101 | /* feed data to the decoder */ |
102 | mng_bool mngreadstream(mng_handle mng, mng_ptr buffer, |
103 | mng_uint32 size, mng_uint32 * bytesread) |
104 | { |
105 | mngstuff *mymng; |
106 | |
107 | /* look up our stream struct */ |
108 | mymng = (mngstuff *) mng_get_userdata(mng); |
109 | if (!buffered) { |
110 | /* read the requested amount of data from the file */ |
111 | *bytesread = fread(buffer, 1, size, mymng->file); |
112 | } else { |
113 | *bytesread = (buffersize - bufferpos) < |
114 | size ? (buffersize - bufferpos) : size; |
115 | memcpy(buffer, bufferstream + bufferpos, *bytesread); |
116 | bufferpos += (*bytesread); |
117 | } |
118 | return MNG_TRUE; |
119 | } |
120 | |
121 | mng_bool mnggetbackgroundbuffer(mng_handle mng) |
122 | { |
123 | unsigned char *background, *src; |
124 | mngstuff *mymng = mng_get_userdata(mng); |
125 | mng_uint32 width = mymng->width, height = mymng->height; |
126 | int bytes = (mymng->fbbpp >> 3); |
127 | |
128 | if (mymng->background) |
129 | return MNG_TRUE; |
130 | |
131 | /* If we're not on the right terminal, don't |
132 | * initialize background yet. |
133 | */ |
134 | if (sconly && current_console() != start_console) |
135 | return MNG_FALSE; |
136 | |
137 | background = (unsigned char *) malloc(width * height * bytes); |
138 | if (background == NULL) { |
139 | fprintf(stderr, "could not allocate background buffer.\n"); |
140 | exit(0); |
141 | } |
142 | |
143 | mymng->background = background; |
144 | src = |
145 | mymng->display + (mymng->fbwidth * mymng->fby + |
146 | mymng->fbx) * bytes; |
147 | |
148 | while (height--) { |
149 | memcpy(background, src, width * bytes); |
150 | background += width * bytes; |
151 | src += mymng->fbrow; |
152 | } |
153 | |
154 | return MNG_TRUE; |
155 | } |
156 | |
157 | /* the header's been read. set up the display stuff */ |
158 | mng_bool mngprocessheader(mng_handle mng, |
159 | mng_uint32 width, mng_uint32 height) |
160 | { |
161 | mngstuff *mymng; |
162 | unsigned char *copybuffer; |
163 | |
164 | mymng = (mngstuff *) mng_get_userdata(mng); |
165 | mymng->width = width; |
166 | mymng->height = height; |
167 | |
168 | copybuffer = (unsigned char *) malloc(width * height * 4); |
169 | if (copybuffer == NULL) { |
170 | fprintf(stderr, "could not allocate copy buffer.\n"); |
171 | exit(0); |
172 | } |
173 | mymng->copybuffer = copybuffer; |
174 | |
175 | /* Try to get background buffer */ |
176 | mnggetbackgroundbuffer(mng); |
177 | |
178 | /* tell the mng decoder about our bit-depth choice */ |
179 | /* FIXME: this works on intel. is it correct in general? */ |
180 | mng_set_canvasstyle(mng, MNG_CANVAS_BGRA8); |
181 | |
182 | return MNG_TRUE; |
183 | } |
184 | |
185 | /* return a row pointer for the decoder to fill */ |
186 | mng_ptr mnggetcanvasline(mng_handle mng, mng_uint32 line) |
187 | { |
188 | mngstuff *mymng; |
189 | mng_ptr row; |
190 | |
191 | /* dereference our structure */ |
192 | mymng = (mngstuff *) mng_get_userdata(mng); |
193 | |
194 | /* we assume any necessary locking has happened |
195 | outside, in the frame level code */ |
196 | row = mymng->copybuffer + mymng->width * 4 * line; |
197 | |
198 | return (row); |
199 | } |
200 | |
201 | /* timer */ |
202 | mng_uint32 mnggetticks(mng_handle mng) |
203 | { |
204 | mng_uint32 ticks; |
205 | struct timeval tv; |
206 | struct timezone tz; |
207 | |
208 | gettimeofday(&tv, &tz); |
209 | ticks = (tv.tv_sec * 1000) + (tv.tv_usec / 1000); |
210 | |
211 | return (ticks); |
212 | } |
213 | |
214 | static inline void copyline(unsigned char *dest, unsigned char *src, |
215 | unsigned char *background, mngstuff * mymng) |
216 | { |
217 | // BGRA8 |
218 | unsigned int i = mymng->width; |
219 | unsigned int fr, fg, fb, br, bg, bb, r, g, b, a; |
220 | unsigned short output, input; |
221 | |
222 | while (i--) { |
223 | fb = *src++; |
224 | fg = *src++; |
225 | fr = *src++; |
226 | |
227 | a = *src++; |
228 | a = a * mymng->alpha / 100; |
229 | switch (mymng->fbbpp) { |
230 | case 16: |
231 | input = *((unsigned short *) background)++; |
232 | |
233 | br = (input >> mng->fbredo) << (8 - mng->fbredl); |
234 | bg = (input >> mng->fbgreeno) << (8 - |
235 | mng->fbgreenl); |
236 | bb = (input >> mng->fbblueo) << (8 - mng->fbbluel); |
237 | br &= 0xf8; |
238 | bg &= 0xfc; |
239 | bb &= 0xff; |
240 | #if 0 |
241 | br = (input >> 8) & 0xf8; |
242 | bg = (input >> 3) & 0xfc; |
243 | bb = input << 3 & 0xff; |
244 | #endif |
245 | break; |
246 | case 24: |
247 | bb = *background++; |
248 | bg = *background++; |
249 | br = *background++; |
250 | break; |
251 | case 32: |
252 | bb = *background++; |
253 | bg = *background++; |
254 | br = *background++; |
255 | background++; |
256 | break; |
257 | default: |
258 | br = 0; |
259 | bg = 0; |
260 | bb = 0; |
261 | printf("depth not supported.\n"); |
262 | run = 0; |
263 | break; |
264 | } |
265 | |
266 | r = ((fr * a) + (br * (0x100 - a))) >> 8; |
267 | g = ((fg * a) + (bg * (0x100 - a))) >> 8; |
268 | b = ((fb * a) + (bb * (0x100 - a))) >> 8; |
269 | |
270 | switch (mymng->fbbpp) { |
271 | case 16: |
272 | // dumb 24->16 bit conversion. |
273 | r >>= (8 - mng->fbredl); |
274 | g >>= (8 - mng->fbgreenl); |
275 | b >>= (8 - mng->fbbluel); |
276 | |
277 | output = |
278 | (r << mng->fbredo) | (g << mng-> |
279 | fbgreeno) | (b << mng-> |
280 | fbblueo); |
281 | |
282 | *((unsigned short *) dest)++ = output; |
283 | break; |
284 | case 24: |
285 | *dest++ = b; |
286 | *dest++ = g; |
287 | *dest++ = r; |
288 | break; |
289 | case 32: |
290 | *dest++ = b; |
291 | *dest++ = g; |
292 | *dest++ = r; |
293 | dest++; |
294 | break; |
295 | default: |
296 | break; |
297 | } |
298 | } |
299 | } |
300 | |
301 | mng_bool mngrefresh(mng_handle mng, mng_uint32 x, mng_uint32 y, |
302 | mng_uint32 w, mng_uint32 h) |
303 | { |
304 | mngstuff *mymng = mng_get_userdata(mng); |
305 | unsigned char *background; |
306 | unsigned char *dest, *src; |
307 | int bytes = (mymng->fbbpp >> 3); |
308 | |
309 | if (sconly && current_console() != start_console) |
310 | return MNG_TRUE; |
311 | |
312 | /* When we read the header, we might still |
313 | * have been on a different console |
314 | */ |
315 | |
316 | if (!(mymng->background)) |
317 | mnggetbackgroundbuffer(mng); |
318 | |
319 | background = mymng->background; |
320 | |
321 | dest = |
322 | mymng->display + (mymng->fby * mymng->fbwidth + |
323 | mymng->fbx) * bytes; |
324 | src = mymng->copybuffer; |
325 | |
326 | /* refresh the screen with the new frame */ |
327 | while (h-- > 0) { |
328 | copyline(dest, src, background, mymng); |
329 | |
330 | dest += mymng->fbrow; |
331 | background += mymng->width * bytes; |
332 | /* 4 bytes per pixel due to RGBA */ |
333 | src += 4 * mymng->width; |
334 | } |
335 | |
336 | /* remove traces in alpha transparent pictures. */ |
337 | memset(mymng->copybuffer, 0, 4 * mymng->width * mymng->height); |
338 | |
339 | return MNG_TRUE; |
340 | } |
341 | |
342 | /* interframe delay callback */ |
343 | mng_bool mngsettimer(mng_handle mng, mng_uint32 msecs) |
344 | { |
345 | mngstuff *mymng; |
346 | |
347 | /* look up our stream struct */ |
348 | mymng = (mngstuff *) mng_get_userdata(mng); |
349 | |
350 | /* set the timer for when the decoder wants to be woken */ |
351 | mymng->delay = msecs; |
352 | |
353 | return MNG_TRUE; |
354 | } |
355 | |
356 | mng_bool mngerror(mng_handle mng, mng_int32 code, mng_int8 severity, |
357 | mng_chunkid chunktype, mng_uint32 chunkseq, |
358 | mng_int32 extra1, mng_int32 extra2, mng_pchar text) |
359 | { |
360 | mngstuff *mymng; |
361 | char chunk[5]; |
362 | |
363 | /* dereference our data so we can get the filename */ |
364 | mymng = (mngstuff *) mng_get_userdata(mng); |
365 | /* pull out the chuck type as a string */ |
366 | // FIXME: does this assume unsigned char? |
367 | chunk[0] = (char) ((chunktype >> 24) & 0xFF); |
368 | chunk[1] = (char) ((chunktype >> 16) & 0xFF); |
369 | chunk[2] = (char) ((chunktype >> 8) & 0xFF); |
370 | chunk[3] = (char) ((chunktype) & 0xFF); |
371 | chunk[4] = '\0'; |
372 | |
373 | /* output the error */ |
374 | fprintf(stderr, "error playing '%s' chunk %s (%d):\n", |
375 | mymng->filename, chunk, chunkseq); |
376 | fprintf(stderr, "%s\n", text); |
377 | |
378 | return 0; |
379 | } |
380 | |
381 | int mngquit(mng_handle mng) |
382 | { |
383 | mngstuff *mymng; |
384 | |
385 | /* dereference our data so we can free it */ |
386 | mymng = (mngstuff *) mng_get_userdata(mng); |
387 | |
388 | /* cleanup. this will call mymngclosestream */ |
389 | mng_cleanup(&mng); |
390 | |
391 | /* free our data */ |
392 | free(mymng); |
393 | |
394 | exit(0); |
395 | } |
396 | |
397 | void cleanup(void) |
398 | { |
399 | mngquit(mng->mng); |
400 | exit(0); |
401 | } |
402 | |
403 | void restore_area(void) |
404 | { |
405 | int height, width; |
406 | unsigned char *dest, *background; |
407 | |
408 | if (sconly && current_console() != start_console) |
409 | return; |
410 | |
411 | /* when we didn't manage to get a background until |
412 | * now, we don't have anything to restore anyways. |
413 | */ |
414 | |
415 | if (!(mng->background)) |
416 | return; |
417 | |
418 | background = mng->background; |
419 | height = mng->height; |
420 | width = mng->width; |
421 | dest = mng->display + ((mng->fbwidth * mng->fby + mng->fbx) * |
422 | (mng->fbbpp >> 3)); |
423 | |
424 | while (height--) { |
425 | memcpy(dest, background, width * (mng->fbbpp >> 3)); |
426 | background += width * (mng->fbbpp >> 3); |
427 | dest += mng->fbrow; |
428 | } |
429 | } |