-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathraw-client.c
152 lines (125 loc) · 3.71 KB
/
raw-client.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
/* this is to serve as a minimal - no dependencies application
* integrating with an mmm compositor - this example is minimal
* enough that it doesn't even rely on the mmm .c file
*/
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#define WIDTH 512
#define HEIGHT 384
#define BPP 4
#define MMM_PID 0x18
#define MMM_TITLE 0xb0
#define MMM_WIDTH 0x5b0
#define MMM_HEIGHT 0x5b4
#define MMM_DESIRED_WIDTH 0x5d8
#define MMM_DESIRED_HEIGHT 0x5dc
#define MMM_DAMAGE_WIDTH 0x5e8
#define MMM_DAMAGE_HEIGHT 0x5ec
#define MMM_STRIDE 0x5b8
#define MMM_FB_OFFSET 0x5bc
#define MMM_FLIP_STATE 0x5c0
#define MMM_SIZE 0x48c70
#define MMM_FLIP_INIT 0
#define MMM_FLIP_NEUTRAL 1
#define MMM_FLIP_DRAWING 2
#define MMM_FLIP_WAIT_FLIP 3
#define MMM_FLIP_FLIPPING 4
#define PEEK(addr) (*(int32_t*)(&ram_base[addr]))
#define POKE(addr,val) do{(*(int32_t*)(&ram_base[addr]))=(val); }while(0)
static uint8_t *ram_base = NULL;
static uint8_t *pico_fb (int width, int height)
{
char path[512];
int fd;
int size = MMM_SIZE + width * height * BPP;
const char *mmm_path = getenv ("MMM_PATH");
if (!mmm_path)
{
fprintf (stderr, "this minimalistic demo requires to be launched as the argument of an mmm host being launched; for example $ mmm.sdl ./raw-client\n");
/* copy over the fork launcher from lib? */
return NULL;
}
sprintf (path, "%s/fb.XXXXXX", mmm_path);
fd = mkstemp (path);
pwrite (fd, "", 1, size);
fsync (fd);
chmod (path, 511);
ram_base = mmap (NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
memset (ram_base, 0, size);
strcpy ((void*)ram_base + MMM_TITLE, "foo");
POKE (MMM_FLIP_STATE, MMM_FLIP_INIT);
POKE (MMM_PID, (uint32_t)getpid());
POKE (MMM_WIDTH, width);
POKE (MMM_HEIGHT, height);
POKE (MMM_DESIRED_WIDTH, width);
POKE (MMM_DESIRED_HEIGHT, height);
POKE (MMM_STRIDE, width * BPP);
POKE (MMM_FB_OFFSET, MMM_SIZE); /* we write where to find out fb */
POKE (MMM_FLIP_STATE, MMM_FLIP_NEUTRAL);
return (uint8_t*) & (PEEK(MMM_SIZE));
}
static void pico_exit (void)
{
if (ram_base)
munmap (ram_base, MMM_SIZE * PEEK (MMM_WIDTH) * PEEK (MMM_HEIGHT) * BPP);
ram_base = NULL;
}
static void wait_sync (void)
{
/* this client will block if there is no compositor */
while (PEEK(MMM_FLIP_STATE) != MMM_FLIP_NEUTRAL)
usleep (5000);
POKE (MMM_FLIP_STATE, MMM_FLIP_DRAWING);
}
static void flip_buffer (void)
{
/* we need to indicate damage to the buffers to
* get auto updates with hosts that are smart about updates
*/
POKE (MMM_DAMAGE_WIDTH, PEEK (MMM_WIDTH));
POKE (MMM_DAMAGE_HEIGHT, PEEK (MMM_HEIGHT));
/* indicate that we're ready for a flip */
POKE (MMM_FLIP_STATE, MMM_FLIP_WAIT_FLIP);
}
int main (int argc, char **argv)
{
uint8_t *pixels = pico_fb (512, 384);
if (!pixels)
return -1;
int frame;
int val = 0;
int dir = 1;
for (frame = 0; frame < 100000; frame ++)
{
int x, y;
int i;
wait_sync ();
i = 0;
for (y = 0 ; y < HEIGHT; y ++)
for (x = 0; x < WIDTH; x ++)
{
float d = (x - WIDTH/2) * (x - WIDTH / 2) +
(y - HEIGHT/2) * (y - HEIGHT / 2);
pixels[i + 0] = (x & y) + frame;
pixels[i + 1] = val;
pixels[i + 2] = (x - WIDTH/2) * frame / ((y-HEIGHT/2)+0.5);
pixels[i + 3] = d * 800 / frame;
i += 4;
}
flip_buffer ();
val += dir;
if (val >= 255 || val < 0)
{
dir *= -1;
val += dir;
}
}
pico_exit ();
return 0;
}