diff options
Diffstat (limited to 'src/framebuffer.c')
-rw-r--r-- | src/framebuffer.c | 84 |
1 files changed, 50 insertions, 34 deletions
diff --git a/src/framebuffer.c b/src/framebuffer.c index c3845b1..6505ace 100644 --- a/src/framebuffer.c +++ b/src/framebuffer.c | |||
@@ -1,58 +1,74 @@ | |||
1 | #include <framebuffer.h> | 1 | #include <framebuffer.h> |
2 | 2 | ||
3 | #include <mailbox.h> | 3 | #include <mailbox.h> |
4 | #include <string.h> | ||
4 | 5 | ||
5 | #include <stddef.h> | 6 | #include <stddef.h> |
6 | #include <stdint.h> | 7 | #include <stdint.h> |
7 | 8 | ||
8 | #define WIDTH 640 | 9 | #define WIDTH 640 |
9 | #define HEIGHT 480 | 10 | #define HEIGHT 480 |
10 | #define DEPTH 32 | 11 | #define DEPTH 24 |
11 | #define ALIGNMENT 16 // Framebuffer byte alignment. | 12 | #define ALIGNMENT 16 // Framebuffer byte alignment. |
12 | 13 | ||
13 | typedef struct Framebuffer { | ||
14 | volatile void* pixels; | ||
15 | size_t size; | ||
16 | } Framebuffer; | ||
17 | |||
18 | static Framebuffer framebuffer = {}; | 14 | static Framebuffer framebuffer = {}; |
19 | 15 | ||
20 | bool framebuffer_init(uint32_t* error) { | 16 | bool framebuffer_init(uint32_t* error) { |
21 | MAIL_T uint32_t ConfigureScreen[20] = { | 17 | // TODO: We can combine both messages, this one and the one below, into a |
22 | 80, // Size in bytes, aligned to MAIL_ALIGN. | 18 | // single array and make a single call to mbox_write(). |
23 | MAILBOX_REQUEST, | 19 | MAIL_T uint32_t InitFramebuffer[24] = { |
24 | TAG_FRAMEBUFFER_SET_PHYSICAL_SCREEN_SIZE, 8, MAILBOX_REQUEST, WIDTH, HEIGHT, | 20 | /*00*/96, // Size in bytes, aligned to MAIL_ALIGN. |
25 | TAG_FRAMEBUFFER_SET_VIRTUAL_SCREEN_SIZE, 8, MAILBOX_REQUEST, WIDTH, HEIGHT, | 21 | /*01*/MAILBOX_REQUEST, |
26 | TAG_FRAMEBUFFER_SET_DEPTH, 4, MAILBOX_REQUEST, DEPTH, | 22 | /*02*/TAG_FRAMEBUFFER_SET_PHYSICAL_SCREEN_SIZE, 8, MAILBOX_REQUEST, WIDTH, HEIGHT, |
27 | TAG_END, | 23 | /*07*/TAG_FRAMEBUFFER_SET_VIRTUAL_SCREEN_SIZE, 8, MAILBOX_REQUEST, WIDTH, HEIGHT, |
28 | 0, 0, 0 // Padding. | 24 | /*12*/TAG_FRAMEBUFFER_SET_DEPTH, 4, MAILBOX_REQUEST, DEPTH, |
29 | }; | 25 | /*16*/TAG_FRAMEBUFFER_ALLOCATE, 8, MAILBOX_REQUEST, ALIGNMENT, 0, |
30 | mbox_write(PROPERTY_CHANNEL, ConfigureScreen); | 26 | /*21*/TAG_END, |
31 | const Mail* response = mbox_read(PROPERTY_CHANNEL); | 27 | /*22*/0, 0 // Padding. |
32 | if (response->code != MAILBOX_SUCCESS) { | ||
33 | goto end; | ||
34 | } | ||
35 | |||
36 | MAIL_T uint32_t InitFramebuffer[8] = { | ||
37 | 32, // Size in bytes, aligned to MAIL_ALIGN. | ||
38 | MAILBOX_REQUEST, | ||
39 | TAG_FRAMEBUFFER_ALLOCATE, 8, MAILBOX_REQUEST, ALIGNMENT, 0, | ||
40 | TAG_END | ||
41 | }; | 28 | }; |
42 | mbox_write(PROPERTY_CHANNEL, InitFramebuffer); | 29 | const uint32_t result = mbox_write(PROPERTY_CHANNEL, InitFramebuffer); |
43 | response = mbox_read(PROPERTY_CHANNEL); | 30 | if (result != MAILBOX_SUCCESS) { |
44 | if (response->code != MAILBOX_SUCCESS) { | ||
45 | goto end; | 31 | goto end; |
46 | } | 32 | } |
47 | 33 | ||
48 | // The input mail is overwritten with the response. | 34 | // The input mail is overwritten with the response. |
35 | // | ||
36 | // TAG_FRAMEBUFFER_ALLOCATE response: | ||
49 | // u32 fb base address | 37 | // u32 fb base address |
50 | // u32 fb size | 38 | // u32 fb size |
51 | framebuffer.pixels = (void*)(uintptr_t)InitFramebuffer[5]; | 39 | // TODO: Do we need & 0x3FFFFFFF? Something about converting GPU address space |
52 | framebuffer.size = InitFramebuffer[6]; | 40 | // to ARM address space. |
53 | 41 | // TODO: Should we read back the pitch, or does pitch match width? | |
42 | framebuffer = (Framebuffer) { | ||
43 | .pixels = (Pixel*)((uintptr_t)InitFramebuffer[19] & 0x3FFFFFFF), | ||
44 | .size = InitFramebuffer[20], | ||
45 | .width = InitFramebuffer[5], | ||
46 | .height = InitFramebuffer[6], | ||
47 | .depth = InitFramebuffer[15] | ||
48 | }; | ||
49 | |||
54 | end: | 50 | end: |
55 | *error = response->code; | 51 | *error = result; |
56 | return response->code == MAILBOX_SUCCESS; | 52 | return result == MAILBOX_SUCCESS; |
53 | } | ||
54 | |||
55 | const Framebuffer* framebuffer_get() { | ||
56 | return &framebuffer; | ||
57 | } | ||
58 | |||
59 | void framebuffer_present(const Pixel* pixels) { | ||
60 | memcpy(framebuffer.pixels, pixels, framebuffer.size); | ||
61 | } | ||
62 | |||
63 | void framebuffer_clear(Pixel colour) { | ||
64 | const uint32_t num_channels = framebuffer.depth / 8; | ||
65 | const uint32_t num_pixels = framebuffer.size / num_channels; | ||
66 | volatile Pixel* fb = framebuffer.pixels; | ||
67 | for (size_t i = 0; i < num_pixels; i++) { | ||
68 | fb->r = colour.r; | ||
69 | fb->g = colour.g; | ||
70 | fb->b = colour.b; | ||
71 | fb++; | ||
72 | } | ||
57 | } | 73 | } |
58 | 74 | ||