updated version
This commit is contained in:
14
.clangd
Normal file
14
.clangd
Normal file
@@ -0,0 +1,14 @@
|
||||
# .clangd
|
||||
CompileFlags:
|
||||
Add:
|
||||
- -I./include # Add your project's include directory
|
||||
- -std=gnu11 # Use C11 standard with GNU extensions
|
||||
- -Wall # Enable all warnings
|
||||
- -Wextra # Extra warnings
|
||||
- -Wno-unused-parameter # Optional: suppress some noisy warnings
|
||||
|
||||
Index:
|
||||
Threads: 0 # Use all available cores for indexing
|
||||
|
||||
Diagnostics:
|
||||
Suppress: [] # You can list warnings/errors to ignore if needed
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,2 +1,3 @@
|
||||
.DS_Store
|
||||
/build
|
||||
*.o
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#define CUSTOM_STRING_MAX_LEN 64
|
||||
#define CUSTOM_STRING_MAX_LEN 256
|
||||
|
||||
typedef struct {
|
||||
char buffer[CUSTOM_STRING_MAX_LEN];
|
||||
|
||||
@@ -3,21 +3,25 @@
|
||||
#define FONT_PACK_H
|
||||
#include <stdint.h>
|
||||
|
||||
#define FONT_WIDTH 16
|
||||
#define FONT_WIDTH 16
|
||||
#define FONT_HEIGHT 16
|
||||
#define FONT_BITMAP_SIZE ((FONT_WIDTH * FONT_HEIGHT) / 8) // 32 bytes per character
|
||||
#define FONT_BITMAP_SIZE \
|
||||
((FONT_WIDTH * FONT_HEIGHT) / 8) // 32 bytes per character
|
||||
static const uint8_t empty_char_16x16[32] = {0};
|
||||
|
||||
typedef struct {
|
||||
const uint8_t *bitmaps[26]; // Pointers to each 16x16 bitmap
|
||||
const uint8_t *bitmaps[26]; // Pointers to each 16x16 bitmap
|
||||
} FontPack;
|
||||
|
||||
extern const FontPack basic_font_pack;
|
||||
|
||||
static inline const uint8_t *font_get_char_bitmap(const FontPack *pack, char c) {
|
||||
if (c >= 'A' && c <= 'Z')
|
||||
return pack->bitmaps[c - 'A'];
|
||||
return empty_char_16x16; // Or point to empty_char_16x16
|
||||
static inline const uint8_t *font_get_char_bitmap(const FontPack *pack,
|
||||
char c) {
|
||||
if (c >= 'a' && c <= 'z') // convert to uppercase
|
||||
c = c - 'a' + 'A';
|
||||
if (c >= 'A' && c <= 'Z')
|
||||
return pack->bitmaps[c - 'A'];
|
||||
return empty_char_16x16; // fallback for other characters
|
||||
}
|
||||
|
||||
#endif // FONT_PACK_H
|
||||
|
||||
@@ -53,6 +53,14 @@ static void uart_print_int(unsigned int value)
|
||||
uart_putc(buffer[i]);
|
||||
}
|
||||
|
||||
static char uart_getc_nonblocking(void)
|
||||
{
|
||||
if (UART0_FR & (1 << 4)) // RXFE = receive FIFO empty
|
||||
return 0; // indicate no data
|
||||
return (char)(UART0_DR & 0xFF);
|
||||
}
|
||||
|
||||
|
||||
// UART_IO instance with function pointers assigned
|
||||
static const UART_IO uart_io = {
|
||||
.putc = uart_putc,
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include "font_pack.h"
|
||||
#include <math.h> // For sqrt, round
|
||||
|
||||
|
||||
typedef struct RenderObject {
|
||||
unsigned int x, y;
|
||||
@@ -27,6 +29,11 @@ typedef struct Renderer {
|
||||
void (*draw_rect)(struct Renderer *renderer, RenderObject *obj);
|
||||
void (*draw_text)(struct Renderer *renderer, RenderText *text);
|
||||
void (*draw_objects)(struct Renderer *renderer, RenderObject *objs[], unsigned int count);
|
||||
void (*draw_line)(struct Renderer *renderer, int x0, int y0, int x1, int y1, unsigned int color);
|
||||
void (*draw_circle)(struct Renderer *renderer, int cx, int cy, int radius, unsigned int color);
|
||||
void (*fill_circle)(struct Renderer *renderer, int cx, int cy, int radius, unsigned int color);
|
||||
void (*draw_triangle)(struct Renderer *renderer, int x0, int y0, int x1, int y1, int x2, int y2, unsigned int color);
|
||||
void (*fill_triangle)(struct Renderer *renderer, int x0, int y0, int x1, int y1, int x2, int y2, unsigned int color);
|
||||
} Renderer;
|
||||
|
||||
// ===== Window definition =====
|
||||
|
||||
108
src/main.c
108
src/main.c
@@ -1,81 +1,65 @@
|
||||
#include "renderer.h"
|
||||
#include "String.h"
|
||||
#include "color.h"
|
||||
#include "font_pack.h"
|
||||
#include "io.h"
|
||||
#include "String.h"
|
||||
#include "renderer.h"
|
||||
|
||||
static void delay_1s(void)
|
||||
{
|
||||
volatile unsigned long count = 80000000; // Example for ~1 sec at ~80 MHz CPU
|
||||
while (count--)
|
||||
{
|
||||
__asm__ volatile("nop");
|
||||
}
|
||||
static void delay_1s(void) {
|
||||
volatile unsigned long count = 80000000; // Example for ~1 sec at ~80 MHz CPU
|
||||
while (count--) {
|
||||
__asm__ volatile("nop");
|
||||
}
|
||||
}
|
||||
|
||||
void delay_seconds(unsigned int seconds)
|
||||
{
|
||||
for (unsigned int i = 0; i < seconds; i++)
|
||||
{
|
||||
delay_1s();
|
||||
}
|
||||
void delay_seconds(unsigned int seconds) {
|
||||
for (unsigned int i = 0; i < seconds; i++) {
|
||||
delay_1s();
|
||||
}
|
||||
}
|
||||
|
||||
int kernel_main(void)
|
||||
{
|
||||
String str;
|
||||
cs_init(&str);
|
||||
cs_set(&str, "HELLO MARIO");
|
||||
uart_io.puts("Initializing renderer...\n");
|
||||
int kernel_main(void) {
|
||||
String str;
|
||||
cs_init(&str);
|
||||
cs_set(&str, "HELLO MARIO");
|
||||
uart_io.puts("Initializing renderer...\n");
|
||||
|
||||
Renderer renderer;
|
||||
if (!renderer_init(&renderer))
|
||||
{
|
||||
uart_io.puts("Failed to allocate framebuffer.\n");
|
||||
while (1)
|
||||
;
|
||||
Renderer renderer;
|
||||
if (!renderer_init(&renderer)) {
|
||||
uart_io.puts("Failed to allocate framebuffer.\n");
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
uart_io.puts("Framebuffer allocated.\n");
|
||||
|
||||
RenderObject background = {0, 0, renderer.width, renderer.height, COLOR_RED};
|
||||
|
||||
while (1) {
|
||||
// Non-blocking UART input
|
||||
char c = uart_getc_nonblocking();
|
||||
|
||||
if (c >= 32 && c <= 126) { // printable
|
||||
cs_append_char(&str, c);
|
||||
} else if (c == '\b' || c == 127) { // backspace
|
||||
if (str.length > 0) {
|
||||
str.length--;
|
||||
str.buffer[str.length] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
uart_io.puts("Framebuffer allocated.\n");
|
||||
uart_io.puts("Width: ");
|
||||
uart_io.print_int(renderer.width);
|
||||
uart_io.puts("\nHeight: ");
|
||||
uart_io.print_int(renderer.height);
|
||||
uart_io.putc('\n');
|
||||
|
||||
RenderObject background = {0, 0, renderer.width, renderer.height, COLOR_RED};
|
||||
// Create a fresh RenderText each loop
|
||||
RenderText text = {
|
||||
.base = {
|
||||
.x = 20,
|
||||
.y = 30,
|
||||
.color = 0xFFFFFFFF},
|
||||
.base = {.x = 20, .y = 30, .color = 0xFFFFFFFF},
|
||||
.text = str.buffer,
|
||||
.font = &basic_font_pack,
|
||||
};
|
||||
|
||||
while (1)
|
||||
{
|
||||
renderer.clear_screen(&renderer, background.color);
|
||||
renderer.draw_text(&renderer, &text);
|
||||
renderer.clear_screen(&renderer, background.color);
|
||||
renderer.draw_text(&renderer, &text);
|
||||
|
||||
char c = uart_getc();
|
||||
// uart_puts(str.buffer);
|
||||
|
||||
if (c >= 32 && c <= 126) // Printable ASCII
|
||||
{
|
||||
cs_append_char(&str, c);
|
||||
}
|
||||
else if (c == '\b' || c == 127) // Backspace support
|
||||
{
|
||||
if (str.length > 0)
|
||||
{
|
||||
str.length--;
|
||||
str.buffer[str.length] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
uart_puts(str.buffer);
|
||||
renderer.draw_text(&renderer, &text);
|
||||
|
||||
delay_seconds(4);
|
||||
}
|
||||
// Short delay for smoother typingi
|
||||
delay_seconds(1);
|
||||
}
|
||||
}
|
||||
|
||||
322
src/renderer.c
322
src/renderer.c
@@ -6,6 +6,10 @@
|
||||
|
||||
volatile unsigned int __attribute__((aligned(16))) mbox[36];
|
||||
|
||||
// --------------------
|
||||
// Utility functions
|
||||
// --------------------
|
||||
|
||||
// Small delay loop
|
||||
static inline void delay(int n)
|
||||
{
|
||||
@@ -13,139 +17,47 @@ static inline void delay(int n)
|
||||
__asm__ volatile("nop");
|
||||
}
|
||||
|
||||
// Mailbox call function for communication with GPU
|
||||
// Integer absolute value
|
||||
static inline int int_abs(int x) { return x < 0 ? -x : x; }
|
||||
|
||||
// Integer min/max
|
||||
static inline int int_min(int a, int b) { return a < b ? a : b; }
|
||||
static inline int int_max(int a, int b) { return a > b ? a : b; }
|
||||
|
||||
// --------------------
|
||||
// Mailbox communication
|
||||
// --------------------
|
||||
unsigned int mailbox_call(unsigned int channel)
|
||||
{
|
||||
unsigned int r = ((unsigned int)((unsigned long)&mbox) & ~0xF) | (channel & 0xF);
|
||||
|
||||
// Wait until mailbox not full
|
||||
while (*(volatile unsigned int *)(MBOX_BASE + 0x18) & 0x80000000)
|
||||
delay(100);
|
||||
|
||||
// Write the channel combined with mailbox address
|
||||
*(volatile unsigned int *)(MBOX_BASE + 0x20) = r;
|
||||
|
||||
while (1)
|
||||
{
|
||||
// Wait for response
|
||||
while (*(volatile unsigned int *)(MBOX_BASE + 0x18) & 0x40000000)
|
||||
delay(100);
|
||||
|
||||
// Check if response is for our message
|
||||
if (*(volatile unsigned int *)(MBOX_BASE + 0x00) == r)
|
||||
{
|
||||
// Return true if response is successful
|
||||
return mbox[1] == 0x80000000;
|
||||
}
|
||||
}
|
||||
}
|
||||
void draw_text_impl(Renderer *renderer, RenderText *text_obj) {
|
||||
if (!renderer || !text_obj || !text_obj->text || !text_obj->font) {
|
||||
return; // Invalid inputs
|
||||
}
|
||||
|
||||
unsigned int x0 = text_obj->base.x;
|
||||
unsigned int y0 = text_obj->base.y;
|
||||
unsigned int color = text_obj->base.color;
|
||||
const char *str = text_obj->text;
|
||||
// --------------------
|
||||
// Drawing primitives
|
||||
// --------------------
|
||||
|
||||
// For each character in string
|
||||
for (const char *p = str; *p != '\0'; p++) {
|
||||
unsigned char c = (unsigned char)*p; // Ensure unsigned char for safety
|
||||
|
||||
// Get bitmap (guaranteed non-NULL due to empty_char_16x16 fallback)
|
||||
const uint8_t *bitmap = font_get_char_bitmap(text_obj->font, c);
|
||||
|
||||
// Draw this single character (16x16)
|
||||
for (unsigned int y = 0; y < FONT_HEIGHT; y++) {
|
||||
// Read two bytes separately to avoid alignment issues
|
||||
uint16_t row = ((uint16_t)bitmap[y * 2] << 8) | bitmap[y * 2 + 1];
|
||||
for (unsigned int bit = 0; bit < FONT_WIDTH; bit++) {
|
||||
if (row & (1 << (15 - bit))) { // Check 16 bits, MSB first
|
||||
unsigned int px = x0 + bit;
|
||||
unsigned int py = y0 + y;
|
||||
if (px < renderer->width && py < renderer->height) {
|
||||
// Assume 32-bit pixels; pitch in bytes
|
||||
unsigned int *pixel = &renderer->fb[py * (renderer->pitch / 4) + px];
|
||||
*pixel = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Advance x for next char
|
||||
x0 += FONT_WIDTH + 1;
|
||||
}
|
||||
}
|
||||
// Initialize the framebuffer via mailbox property channel
|
||||
bool renderer_init(Renderer *renderer)
|
||||
// Draw a single pixel
|
||||
static inline void draw_pixel(Renderer *renderer, int x, int y, unsigned int color)
|
||||
{
|
||||
mbox[0] = 35 * 4; // Buffer size in bytes
|
||||
mbox[1] = 0; // Request
|
||||
|
||||
// Set physical width and height
|
||||
mbox[2] = 0x48003;
|
||||
mbox[3] = 8;
|
||||
mbox[4] = 8;
|
||||
mbox[5] = 640;
|
||||
mbox[6] = 480;
|
||||
|
||||
// Set virtual width and height
|
||||
mbox[7] = 0x48004;
|
||||
mbox[8] = 8;
|
||||
mbox[9] = 8;
|
||||
mbox[10] = 640;
|
||||
mbox[11] = 480;
|
||||
|
||||
// Set depth (bits per pixel)
|
||||
mbox[12] = 0x48005;
|
||||
mbox[13] = 4;
|
||||
mbox[14] = 4;
|
||||
mbox[15] = 32;
|
||||
|
||||
// Allocate framebuffer
|
||||
mbox[16] = 0x40001;
|
||||
mbox[17] = 8;
|
||||
mbox[18] = 8;
|
||||
mbox[19] = 16; // alignment
|
||||
mbox[20] = 0;
|
||||
|
||||
// Get pitch
|
||||
mbox[21] = 0x40008;
|
||||
mbox[22] = 4;
|
||||
mbox[23] = 4;
|
||||
mbox[24] = 0;
|
||||
|
||||
// End tag
|
||||
mbox[25] = 0;
|
||||
|
||||
if (!mailbox_call(MBOX_CH_PROP))
|
||||
return false;
|
||||
|
||||
renderer->width = mbox[5];
|
||||
renderer->height = mbox[6];
|
||||
renderer->pitch = mbox[24];
|
||||
renderer->fb = (volatile unsigned int *)(mbox[19] & 0x3FFFFFFF);
|
||||
|
||||
renderer->clear_screen = clear_screen_impl;
|
||||
renderer->draw_rect = draw_rect_impl;
|
||||
renderer->draw_text = draw_text_impl;
|
||||
renderer->draw_objects = draw_objects_impl;
|
||||
|
||||
return true;
|
||||
}
|
||||
// Render function implementations
|
||||
|
||||
void clear_screen_impl(Renderer *renderer, unsigned int color)
|
||||
{
|
||||
for (unsigned int y = 0; y < renderer->height; y++)
|
||||
{
|
||||
for (unsigned int x = 0; x < renderer->width; x++)
|
||||
{
|
||||
renderer->fb[y * (renderer->pitch / 4) + x] = color;
|
||||
}
|
||||
}
|
||||
if (x >= 0 && y >= 0 && x < (int)renderer->width && y < (int)renderer->height)
|
||||
renderer->fb[y * (renderer->pitch / 4) + x] = color;
|
||||
}
|
||||
|
||||
// Draw a rectangle
|
||||
void draw_rect_impl(Renderer *renderer, RenderObject *obj)
|
||||
{
|
||||
unsigned int max_y = obj->y + obj->height;
|
||||
@@ -157,18 +69,198 @@ void draw_rect_impl(Renderer *renderer, RenderObject *obj)
|
||||
max_x = renderer->width;
|
||||
|
||||
for (unsigned int y = obj->y; y < max_y; y++)
|
||||
{
|
||||
for (unsigned int x = obj->x; x < max_x; x++)
|
||||
{
|
||||
renderer->fb[y * (renderer->pitch / 4) + x] = obj->color;
|
||||
}
|
||||
}
|
||||
|
||||
// Clear the screen
|
||||
void clear_screen_impl(Renderer *renderer, unsigned int color)
|
||||
{
|
||||
for (unsigned int y = 0; y < renderer->height; y++)
|
||||
for (unsigned int x = 0; x < renderer->width; x++)
|
||||
renderer->fb[y * (renderer->pitch / 4) + x] = color;
|
||||
}
|
||||
|
||||
// Draw a line using Bresenham's algorithm
|
||||
void draw_line_impl(Renderer *renderer, int x0, int y0, int x1, int y1, unsigned int color)
|
||||
{
|
||||
int dx = int_abs(x1 - x0);
|
||||
int sx = x0 < x1 ? 1 : -1;
|
||||
int dy = -int_abs(y1 - y0);
|
||||
int sy = y0 < y1 ? 1 : -1;
|
||||
int err = dx + dy;
|
||||
|
||||
while (1)
|
||||
{
|
||||
draw_pixel(renderer, x0, y0, color);
|
||||
if (x0 == x1 && y0 == y1) break;
|
||||
int e2 = 2 * err;
|
||||
if (e2 >= dy) { err += dy; x0 += sx; }
|
||||
if (e2 <= dx) { err += dx; y0 += sy; }
|
||||
}
|
||||
}
|
||||
|
||||
// Draw a circle outline using midpoint algorithm
|
||||
void draw_circle_impl(Renderer *renderer, int cx, int cy, int radius, unsigned int color)
|
||||
{
|
||||
int x = radius;
|
||||
int y = 0;
|
||||
int err = 0;
|
||||
|
||||
while (x >= y)
|
||||
{
|
||||
draw_pixel(renderer, cx + x, cy + y, color);
|
||||
draw_pixel(renderer, cx + y, cy + x, color);
|
||||
draw_pixel(renderer, cx - y, cy + x, color);
|
||||
draw_pixel(renderer, cx - x, cy + y, color);
|
||||
draw_pixel(renderer, cx - x, cy - y, color);
|
||||
draw_pixel(renderer, cx - y, cy - x, color);
|
||||
draw_pixel(renderer, cx + y, cy - x, color);
|
||||
draw_pixel(renderer, cx + x, cy - y, color);
|
||||
|
||||
y += 1;
|
||||
if (err <= 0) err += 2*y + 1;
|
||||
if (err > 0) { x -= 1; err -= 2*x + 1; }
|
||||
}
|
||||
}
|
||||
|
||||
// Fill a circle
|
||||
void fill_circle_impl(Renderer *renderer, int cx, int cy, int radius, unsigned int color)
|
||||
{
|
||||
for (int y = -radius; y <= radius; y++)
|
||||
for (int x = -radius; x <= radius; x++)
|
||||
if (x*x + y*y <= radius*radius)
|
||||
draw_pixel(renderer, cx + x, cy + y, color);
|
||||
}
|
||||
|
||||
// Draw triangle outline
|
||||
void draw_triangle_impl(Renderer *renderer,
|
||||
int x0, int y0,
|
||||
int x1, int y1,
|
||||
int x2, int y2,
|
||||
unsigned int color)
|
||||
{
|
||||
draw_line_impl(renderer, x0, y0, x1, y1, color);
|
||||
draw_line_impl(renderer, x1, y1, x2, y2, color);
|
||||
draw_line_impl(renderer, x2, y2, x0, y0, color);
|
||||
}
|
||||
|
||||
// Fill triangle using barycentric coordinates
|
||||
void fill_triangle_impl(Renderer *renderer,
|
||||
int x0, int y0,
|
||||
int x1, int y1,
|
||||
int x2, int y2,
|
||||
unsigned int color)
|
||||
{
|
||||
int minX = int_min(int_min(x0, x1), x2);
|
||||
int maxX = int_max(int_max(x0, x1), x2);
|
||||
int minY = int_min(int_min(y0, y1), y2);
|
||||
int maxY = int_max(int_max(y0, y1), y2);
|
||||
|
||||
for (int y = minY; y <= maxY; y++)
|
||||
for (int x = minX; x <= maxX; x++)
|
||||
{
|
||||
int w0 = (x1 - x0)*(y - y0) - (x - x0)*(y1 - y0);
|
||||
int w1 = (x2 - x1)*(y - y1) - (x - x1)*(y2 - y1);
|
||||
int w2 = (x0 - x2)*(y - y2) - (x - x2)*(y0 - y2);
|
||||
if ((w0 >= 0 && w1 >= 0 && w2 >= 0) || (w0 <= 0 && w1 <= 0 && w2 <= 0))
|
||||
draw_pixel(renderer, x, y, color);
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------
|
||||
// Text rendering
|
||||
// --------------------
|
||||
void draw_text_impl(Renderer *renderer, RenderText *text_obj)
|
||||
{
|
||||
if (!renderer || !text_obj || !text_obj->text || !text_obj->font) return;
|
||||
|
||||
unsigned int x0 = text_obj->base.x;
|
||||
unsigned int y0 = text_obj->base.y;
|
||||
unsigned int color = text_obj->base.color;
|
||||
const char *str = text_obj->text;
|
||||
unsigned int line_spacing = 2;
|
||||
|
||||
for (const char *p = str; *p != '\0'; p++)
|
||||
{
|
||||
unsigned char c = (unsigned char)*p;
|
||||
if (c == '\n')
|
||||
{
|
||||
x0 = text_obj->base.x;
|
||||
y0 += FONT_HEIGHT + line_spacing;
|
||||
if (y0 + FONT_HEIGHT > renderer->height) break;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c >= 'a' && c <= 'z') c = c - 'a' + 'A';
|
||||
if (!(c >= 'A' && c <= 'Z')) c = ' ';
|
||||
|
||||
if (x0 + FONT_WIDTH > renderer->width)
|
||||
{
|
||||
x0 = text_obj->base.x;
|
||||
y0 += FONT_HEIGHT + line_spacing;
|
||||
if (y0 + FONT_HEIGHT > renderer->height) break;
|
||||
}
|
||||
|
||||
const uint8_t *bitmap = font_get_char_bitmap(text_obj->font, c);
|
||||
for (unsigned int y = 0; y < FONT_HEIGHT; y++)
|
||||
{
|
||||
uint16_t row = ((uint16_t)bitmap[y*2] << 8) | bitmap[y*2 + 1];
|
||||
for (unsigned int bit = 0; bit < FONT_WIDTH; bit++)
|
||||
if (row & (1 << (15 - bit)))
|
||||
draw_pixel(renderer, x0 + bit, y0 + y, color);
|
||||
}
|
||||
|
||||
x0 += FONT_WIDTH + 1;
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------
|
||||
// Draw multiple objects
|
||||
// --------------------
|
||||
void draw_objects_impl(Renderer *renderer, RenderObject *objs[], unsigned int count)
|
||||
{
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
draw_rect_impl(renderer, objs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------
|
||||
// Renderer initialization
|
||||
// --------------------
|
||||
bool renderer_init(Renderer *renderer)
|
||||
{
|
||||
mbox[0] = 35 * 4;
|
||||
mbox[1] = 0;
|
||||
|
||||
// Physical width/height
|
||||
mbox[2] = 0x48003; mbox[3] = 8; mbox[4] = 8; mbox[5] = 640; mbox[6] = 480;
|
||||
// Virtual width/height
|
||||
mbox[7] = 0x48004; mbox[8] = 8; mbox[9] = 8; mbox[10] = 640; mbox[11] = 480;
|
||||
// Depth
|
||||
mbox[12] = 0x48005; mbox[13] = 4; mbox[14] = 4; mbox[15] = 32;
|
||||
// Allocate framebuffer
|
||||
mbox[16] = 0x40001; mbox[17] = 8; mbox[18] = 8; mbox[19] = 16; mbox[20] = 0;
|
||||
// Get pitch
|
||||
mbox[21] = 0x40008; mbox[22] = 4; mbox[23] = 4; mbox[24] = 0;
|
||||
// End tag
|
||||
mbox[25] = 0;
|
||||
|
||||
if (!mailbox_call(MBOX_CH_PROP)) return false;
|
||||
|
||||
renderer->width = mbox[5];
|
||||
renderer->height = mbox[6];
|
||||
renderer->pitch = mbox[24];
|
||||
renderer->fb = (volatile unsigned int *)(mbox[19] & 0x3FFFFFFF);
|
||||
|
||||
renderer->clear_screen = clear_screen_impl;
|
||||
renderer->draw_rect = draw_rect_impl;
|
||||
renderer->draw_text = draw_text_impl;
|
||||
renderer->draw_objects = draw_objects_impl;
|
||||
renderer->draw_line = draw_line_impl;
|
||||
renderer->draw_circle = draw_circle_impl;
|
||||
renderer->fill_circle = fill_circle_impl;
|
||||
renderer->draw_triangle = draw_triangle_impl;
|
||||
renderer->fill_triangle = fill_triangle_impl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user