transitions
[fbgfx] / src / conscr.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include "screen.h"
5 #include "demo.h"
6
7 static int init(void);
8 static void destroy(void);
9 static void start(long trans_time);
10 static void stop(long trans_time);
11 static void draw(void);
12 static float smoothstep(float a, float b, float x);
13
14 static struct screen scr = {
15         "console",
16         init,
17         destroy,
18         start,
19         stop,
20         draw
21 };
22
23 static void *saved_fb;
24 static int fbsize;
25 static long trans_start = -1, trans_dur;
26
27 #define NBLOCKS         32
28 #define MAX_DELAY       0.5
29 static float delay[NBLOCKS];
30 static int blksz;
31
32 struct screen *console_screen(void)
33 {
34         return &scr;
35 }
36
37 static int init(void)
38 {
39         int i;
40         fbsize = fb_width * fb_height * fb_depth / 8;
41
42         if(!(saved_fb = malloc(fbsize))) {
43                 perror("failed to allocate console framebuffer");
44                 return -1;
45         }
46         memcpy(saved_fb, fb_pixels, fbsize);
47
48         blksz = fb_height / NBLOCKS;
49
50         for(i=0; i<NBLOCKS; i++) {
51                 delay[i] = (float)rand() / (float)RAND_MAX * MAX_DELAY;
52         }
53
54         return 0;
55 }
56
57 static void destroy(void)
58 {
59         memcpy(fb_pixels, saved_fb, fbsize);
60         free(saved_fb);
61 }
62
63 static void start(long trans_time)
64 {
65 }
66
67 static void stop(long trans_time)
68 {
69         trans_start = time_msec;
70         trans_dur = trans_time;
71 }
72
73 static void draw(void)
74 {
75         int i, pixsz = fb_depth / 8;
76         long elapsed, offs, rem;
77         unsigned char *dptr = fb_pixels;
78         unsigned char *sptr = saved_fb;
79
80         if(trans_start < 0) {
81                 return;
82         }
83
84         elapsed = time_msec - trans_start;
85
86         for(i=0; i<fb_height; i++) {
87                 int bidx = i / blksz;
88                 float t = (float)elapsed / (float)trans_dur;
89                 offs = fb_width * smoothstep(0, 1.0 - delay[bidx], t - delay[bidx]);
90                 if(offs < 0) offs = 0;
91                 rem = fb_width - offs;
92
93                 if(offs > 0) {
94                         memset(dptr, 0, offs * pixsz);
95                 }
96                 if(rem > 0) {
97                         memcpy(dptr + offs * pixsz, sptr, rem * pixsz);
98                 }
99
100                 dptr += fb_width * pixsz;
101                 sptr += fb_width * pixsz;
102         }
103 }
104
105 static float smoothstep(float a, float b, float x)
106 {
107         if(x < a) return 0.0;
108         if(x >= b) return 1.0;
109
110         x = (x - a) / (b - a);
111         return x * x * (3.0 - 2.0 * x);
112 }