2021-01-12 18:22:11 +00:00
|
|
|
/* SPDX-License-Identifier: MIT */
|
|
|
|
|
2021-02-12 19:09:49 +00:00
|
|
|
#include "assert.h"
|
2021-01-12 18:22:11 +00:00
|
|
|
#include "fb.h"
|
2021-02-12 19:09:49 +00:00
|
|
|
#include "string.h"
|
2021-01-12 18:22:11 +00:00
|
|
|
#include "utils.h"
|
|
|
|
#include "xnuboot.h"
|
|
|
|
|
2021-02-12 19:09:49 +00:00
|
|
|
#define FB_DEPTH_FLAG_RETINA 0x10000
|
|
|
|
#define FB_DEPTH_MASK 0xff
|
2021-01-12 18:22:11 +00:00
|
|
|
|
2021-02-12 19:09:49 +00:00
|
|
|
fb_t fb;
|
2021-01-12 18:22:11 +00:00
|
|
|
|
2021-02-12 19:09:49 +00:00
|
|
|
static struct {
|
|
|
|
u32 *ptr;
|
|
|
|
u32 width;
|
|
|
|
u32 height;
|
|
|
|
} logo;
|
|
|
|
|
|
|
|
extern u8 _binary_build_bootlogo_128_bin_start[];
|
|
|
|
extern u8 _binary_build_bootlogo_256_bin_start[];
|
2021-01-12 18:22:11 +00:00
|
|
|
|
2021-02-12 21:27:39 +00:00
|
|
|
extern u8 _binary_build_font_bin_start[];
|
|
|
|
extern u8 _binary_build_font_retina_bin_start[];
|
|
|
|
|
2021-01-12 18:22:11 +00:00
|
|
|
void fb_init(void)
|
|
|
|
{
|
2021-02-12 19:09:49 +00:00
|
|
|
fb.ptr = (void *)cur_boot_args.video.base;
|
|
|
|
fb.stride = cur_boot_args.video.stride / 4;
|
|
|
|
fb.width = cur_boot_args.video.width;
|
|
|
|
fb.height = cur_boot_args.video.height;
|
|
|
|
fb.depth = cur_boot_args.video.depth & FB_DEPTH_MASK;
|
|
|
|
printf("fb init: %dx%d (%d) [s=%d] @%p\n", fb.width, fb.height, fb.depth, fb.stride, fb.ptr);
|
2021-01-12 18:22:11 +00:00
|
|
|
|
2021-02-12 19:09:49 +00:00
|
|
|
if (cur_boot_args.video.depth & FB_DEPTH_FLAG_RETINA) {
|
|
|
|
logo.ptr = (void *)_binary_build_bootlogo_256_bin_start;
|
|
|
|
logo.width = logo.height = 256;
|
2021-01-12 18:22:11 +00:00
|
|
|
} else {
|
2021-02-12 19:09:49 +00:00
|
|
|
logo.ptr = (void *)_binary_build_bootlogo_128_bin_start;
|
|
|
|
logo.width = logo.height = 128;
|
2021-01-12 18:22:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-12 19:09:49 +00:00
|
|
|
static void fb_set_pixel(u32 x, u32 y, rgb_t c)
|
2021-01-12 18:22:11 +00:00
|
|
|
{
|
2021-02-12 19:09:49 +00:00
|
|
|
fb.ptr[x + y * fb.stride] = (c.b << 2) | (c.g << 12) | (c.r << 22);
|
2021-01-12 18:22:11 +00:00
|
|
|
}
|
|
|
|
|
2021-02-12 19:09:49 +00:00
|
|
|
void fb_blit(u32 x, u32 y, u32 w, u32 h, void *data, u32 stride)
|
2021-01-12 18:22:11 +00:00
|
|
|
{
|
2021-02-12 19:09:49 +00:00
|
|
|
u8 *p = data;
|
2021-01-12 18:22:11 +00:00
|
|
|
|
2021-02-12 19:09:49 +00:00
|
|
|
for (u32 i = 0; i < h; i++) {
|
|
|
|
for (u32 j = 0; j < w; j++) {
|
|
|
|
rgb_t color = {.r = p[(j + i * stride) * 4],
|
|
|
|
.g = p[(j + i * stride) * 4 + 1],
|
|
|
|
.b = p[(j + i * stride) * 4 + 2]};
|
|
|
|
fb_set_pixel(x + j, y + i, color);
|
|
|
|
}
|
|
|
|
}
|
2021-01-12 18:22:11 +00:00
|
|
|
}
|
|
|
|
|
2021-02-12 19:09:49 +00:00
|
|
|
void fb_fill(u32 x, u32 y, u32 w, u32 h, rgb_t color)
|
2021-01-12 18:22:11 +00:00
|
|
|
{
|
2021-02-12 19:09:49 +00:00
|
|
|
for (u32 i = 0; i < h; i++)
|
|
|
|
for (u32 j = 0; j < w; j++)
|
|
|
|
fb_set_pixel(x + j, y + i, color);
|
2021-01-12 18:22:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void fb_display_logo(void)
|
|
|
|
{
|
|
|
|
printf("fb: display logo\n");
|
2021-02-12 19:09:49 +00:00
|
|
|
fb_blit((fb.width - logo.width) / 2, (fb.height - logo.height) / 2, logo.width, logo.height,
|
|
|
|
logo.ptr, logo.width);
|
2021-01-12 18:22:11 +00:00
|
|
|
}
|