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
|
#include <framebuffer.h>
#include <mailbox.h>
#include <string.h>
#include <stddef.h>
#include <stdint.h>
#define WIDTH 640
#define HEIGHT 480
#define DEPTH 24
#define ALIGNMENT 16 // Framebuffer byte alignment.
static Framebuffer framebuffer = {};
bool framebuffer_init(uint32_t* error) {
// TODO: We can combine both messages, this one and the one below, into a
// single array and make a single call to mbox_write().
MAIL_T uint32_t InitFramebuffer[24] = {
/*00*/96, // Size in bytes, aligned to MAIL_ALIGN.
/*01*/MAILBOX_REQUEST,
/*02*/TAG_FRAMEBUFFER_SET_PHYSICAL_SCREEN_SIZE, 8, MAILBOX_REQUEST, WIDTH, HEIGHT,
/*07*/TAG_FRAMEBUFFER_SET_VIRTUAL_SCREEN_SIZE, 8, MAILBOX_REQUEST, WIDTH, HEIGHT,
/*12*/TAG_FRAMEBUFFER_SET_DEPTH, 4, MAILBOX_REQUEST, DEPTH,
/*16*/TAG_FRAMEBUFFER_ALLOCATE, 8, MAILBOX_REQUEST, ALIGNMENT, 0,
/*21*/TAG_END,
/*22*/0, 0 // Padding.
};
const uint32_t result = mbox_write(PROPERTY_CHANNEL, InitFramebuffer);
if (result != MAILBOX_SUCCESS) {
goto end;
}
// The input mail is overwritten with the response.
//
// TAG_FRAMEBUFFER_ALLOCATE response:
// u32 fb base address
// u32 fb size
// TODO: Do we need & 0x3FFFFFFF? Something about converting GPU address space
// to ARM address space.
// TODO: Should we read back the pitch, or does pitch match width?
framebuffer = (Framebuffer) {
.pixels = (Pixel*)((uintptr_t)InitFramebuffer[19] & 0x3FFFFFFF),
.size = InitFramebuffer[20],
.width = InitFramebuffer[5],
.height = InitFramebuffer[6],
.depth = InitFramebuffer[15]
};
end:
*error = result;
return result == MAILBOX_SUCCESS;
}
const Framebuffer* framebuffer_get() {
return &framebuffer;
}
void framebuffer_present(const Pixel* pixels) {
memcpy(framebuffer.pixels, pixels, framebuffer.size);
}
void framebuffer_clear(Pixel colour) {
const uint32_t num_channels = framebuffer.depth / 8;
const uint32_t num_pixels = framebuffer.size / num_channels;
volatile Pixel* fb = framebuffer.pixels;
for (size_t i = 0; i < num_pixels; i++) {
fb->r = colour.r;
fb->g = colour.g;
fb->b = colour.b;
fb++;
}
}
|