[fb] Change to embedding PSF file
Moved old PSF parsing code from kernel, and switched to embedding whole PSF instead of just glyph data to make font class the same code paths for both cases.
This commit is contained in:
@@ -4,8 +4,6 @@
|
||||
#include "kutil/no_construct.h"
|
||||
#include "kutil/printf.h"
|
||||
#include "console.h"
|
||||
#include "font.h"
|
||||
#include "screen.h"
|
||||
#include "serial.h"
|
||||
|
||||
|
||||
@@ -15,212 +13,12 @@ static kutil::no_construct<console> __g_console_storage;
|
||||
console &g_console = __g_console_storage.value;
|
||||
|
||||
|
||||
class console::screen_out
|
||||
{
|
||||
public:
|
||||
screen_out(screen *s, font *f) :
|
||||
m_font(f),
|
||||
m_screen(s),
|
||||
m_size(s->width() / f->width(), s->height() / f->height()),
|
||||
m_fg(0xffffff),
|
||||
m_bg(0),
|
||||
m_first(0),
|
||||
m_data(nullptr),
|
||||
m_attrs(nullptr),
|
||||
m_palette(nullptr)
|
||||
{
|
||||
const unsigned count = m_size.size();
|
||||
const size_t attrs_size = 2 * count;
|
||||
|
||||
m_data = new char[count];
|
||||
kutil::memset(m_data, 0, count);
|
||||
|
||||
m_palette = new screen::pixel_t[256];
|
||||
fill_palette();
|
||||
|
||||
m_attrs = new uint16_t[count];
|
||||
set_color(7, 0); // Grey on black default
|
||||
for (unsigned i = 0; i < count; ++i) m_attrs[i] = m_attr;
|
||||
|
||||
repaint();
|
||||
}
|
||||
|
||||
~screen_out()
|
||||
{
|
||||
delete [] m_data;
|
||||
delete [] m_palette;
|
||||
delete [] m_attrs;
|
||||
}
|
||||
|
||||
void fill_palette()
|
||||
{
|
||||
unsigned index = 0;
|
||||
|
||||
// Manually add the 16 basic ANSI colors
|
||||
m_palette[index++] = m_screen->color(0x00, 0x00, 0x00);
|
||||
m_palette[index++] = m_screen->color(0xcd, 0x00, 0x00);
|
||||
m_palette[index++] = m_screen->color(0x00, 0xcd, 0x00);
|
||||
m_palette[index++] = m_screen->color(0xcd, 0xcd, 0x00);
|
||||
m_palette[index++] = m_screen->color(0x00, 0x00, 0xee);
|
||||
m_palette[index++] = m_screen->color(0xcd, 0x00, 0xcd);
|
||||
m_palette[index++] = m_screen->color(0x00, 0xcd, 0xcd);
|
||||
m_palette[index++] = m_screen->color(0xe5, 0xe5, 0xe5);
|
||||
m_palette[index++] = m_screen->color(0x7f, 0x7f, 0x7f);
|
||||
m_palette[index++] = m_screen->color(0xff, 0x00, 0x00);
|
||||
m_palette[index++] = m_screen->color(0x00, 0xff, 0x00);
|
||||
m_palette[index++] = m_screen->color(0xff, 0xff, 0x00);
|
||||
m_palette[index++] = m_screen->color(0x00, 0x50, 0xff);
|
||||
m_palette[index++] = m_screen->color(0xff, 0x00, 0xff);
|
||||
m_palette[index++] = m_screen->color(0x00, 0xff, 0xff);
|
||||
m_palette[index++] = m_screen->color(0xff, 0xff, 0xff);
|
||||
|
||||
// Build the high-color portion of the table
|
||||
const uint32_t intensity[] = {0, 0x5f, 0x87, 0xaf, 0xd7, 0xff};
|
||||
const uint32_t intensities = sizeof(intensity) / sizeof(uint32_t);
|
||||
|
||||
for (uint32_t r = 0; r < intensities; ++r) {
|
||||
for (uint32_t g = 0; g < intensities; ++g) {
|
||||
for (uint32_t b = 0; b < intensities; ++b) {
|
||||
m_palette[index++] = m_screen->color(
|
||||
intensity[r], intensity[g], intensity[b]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Build the greyscale portion of the table
|
||||
for (uint8_t i = 0x08; i <= 0xee; i += 10)
|
||||
m_palette[index++] = m_screen->color(i, i, i);
|
||||
}
|
||||
|
||||
void repaint()
|
||||
{
|
||||
m_screen->fill(m_bg);
|
||||
if (!m_data) return;
|
||||
|
||||
for (unsigned y = 0; y < m_size.y; ++y) {
|
||||
const char *line = line_pointer(y);
|
||||
const uint16_t *attrs = attr_pointer(y);
|
||||
for (unsigned x = 0; x < m_size.x; ++x) {
|
||||
const uint16_t attr = attrs[x];
|
||||
|
||||
set_color(static_cast<uint8_t>(attr),
|
||||
static_cast<uint8_t>(attr >> 8));
|
||||
|
||||
m_font->draw_glyph(
|
||||
m_screen,
|
||||
line[x] ? line[x] : ' ',
|
||||
m_fg,
|
||||
m_bg,
|
||||
x * m_font->width(),
|
||||
y * m_font->height());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void scroll(unsigned lines)
|
||||
{
|
||||
if (!m_data) {
|
||||
m_pos.x = 0;
|
||||
m_pos.y = 0;
|
||||
} else {
|
||||
unsigned bytes = lines * m_size.x;
|
||||
char *line = line_pointer(0);
|
||||
for (unsigned i = 0; i < bytes; ++i)
|
||||
*line++ = 0;
|
||||
|
||||
m_first = (m_first + lines) % m_size.y;
|
||||
m_pos.y -= lines;
|
||||
}
|
||||
repaint();
|
||||
}
|
||||
|
||||
void set_color(uint8_t fg, uint8_t bg)
|
||||
{
|
||||
m_bg = m_palette[bg];
|
||||
m_fg = m_palette[fg];
|
||||
m_attr = (bg << 8) | fg;
|
||||
}
|
||||
|
||||
void putc(char c)
|
||||
{
|
||||
char *line = line_pointer(m_pos.y);
|
||||
uint16_t *attrs = attr_pointer(m_pos.y);
|
||||
|
||||
|
||||
switch (c) {
|
||||
case '\t':
|
||||
m_pos.x = (m_pos.x + 4) / 4 * 4;
|
||||
break;
|
||||
|
||||
case '\r':
|
||||
m_pos.x = 0;
|
||||
break;
|
||||
|
||||
case '\n':
|
||||
m_pos.x = 0;
|
||||
m_pos.y++;
|
||||
break;
|
||||
|
||||
default: {
|
||||
if (line) line[m_pos.x] = c;
|
||||
if (attrs) attrs[m_pos.x] = m_attr;
|
||||
|
||||
const unsigned x = m_pos.x * m_font->width();
|
||||
const unsigned y = m_pos.y * m_font->height();
|
||||
m_font->draw_glyph(m_screen, c, m_fg, m_bg, x, y);
|
||||
|
||||
m_pos.x++;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_pos.x >= m_size.x) {
|
||||
m_pos.x = m_pos.x % m_size.x;
|
||||
m_pos.y++;
|
||||
}
|
||||
|
||||
if (m_pos.y >= m_size.y) {
|
||||
scroll(1);
|
||||
line = line_pointer(m_pos.y);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
char * line_pointer(unsigned line)
|
||||
{
|
||||
if (!m_data) return nullptr;
|
||||
return m_data + ((m_first + line) % m_size.y) * m_size.x;
|
||||
}
|
||||
|
||||
uint16_t * attr_pointer(unsigned line)
|
||||
{
|
||||
if (!m_attrs) return nullptr;
|
||||
return m_attrs + ((m_first + line) % m_size.y) * m_size.x;
|
||||
}
|
||||
|
||||
font *m_font;
|
||||
screen *m_screen;
|
||||
|
||||
kutil::coord<unsigned> m_size;
|
||||
kutil::coord<unsigned> m_pos;
|
||||
screen::pixel_t m_fg, m_bg;
|
||||
uint16_t m_attr;
|
||||
|
||||
size_t m_first;
|
||||
|
||||
char *m_data;
|
||||
uint16_t *m_attrs;
|
||||
screen::pixel_t *m_palette;
|
||||
};
|
||||
|
||||
|
||||
console::console() :
|
||||
m_screen(nullptr),
|
||||
m_serial(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
console::console(serial_port *serial) :
|
||||
m_screen(nullptr),
|
||||
m_serial(serial)
|
||||
{
|
||||
if (m_serial) {
|
||||
@@ -239,9 +37,6 @@ console::echo()
|
||||
void
|
||||
console::set_color(uint8_t fg, uint8_t bg)
|
||||
{
|
||||
if (m_screen)
|
||||
m_screen->set_color(fg, bg);
|
||||
|
||||
if (m_serial) {
|
||||
const char *fgseq = "\x1b[38;5;";
|
||||
while (*fgseq)
|
||||
@@ -276,8 +71,6 @@ console::puts(const char *message)
|
||||
void
|
||||
console::putc(char c)
|
||||
{
|
||||
if (m_screen) m_screen->putc(c);
|
||||
|
||||
if (m_serial) {
|
||||
if (c == '\n') m_serial->write('\r');
|
||||
m_serial->write(c);
|
||||
@@ -291,9 +84,3 @@ void console::vprintf(const char *fmt, va_list args)
|
||||
vsnprintf_(buffer, buf_size, fmt, args);
|
||||
puts(buffer);
|
||||
}
|
||||
|
||||
void
|
||||
console::init_screen(screen *s, font *f)
|
||||
{
|
||||
m_screen = new screen_out(s, f);
|
||||
}
|
||||
|
||||
@@ -2,9 +2,7 @@
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
|
||||
class font;
|
||||
struct kernel_data;
|
||||
class screen;
|
||||
class serial_port;
|
||||
|
||||
class console
|
||||
@@ -35,13 +33,9 @@ public:
|
||||
|
||||
void echo();
|
||||
|
||||
void init_screen(screen *s, font *f);
|
||||
|
||||
static console * get();
|
||||
|
||||
private:
|
||||
class screen_out;
|
||||
screen_out *m_screen;
|
||||
serial_port *m_serial;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
#include "kutil/assert.h"
|
||||
#include "font.h"
|
||||
|
||||
/* PSF2 header format
|
||||
* Taken from the Linux KBD documentation
|
||||
* http://www.win.tue.nl/~aeb/linux/kbd/font-formats-1.html
|
||||
*/
|
||||
|
||||
const static uint8_t magic[] = {0x72, 0xb5, 0x4a, 0x86};
|
||||
const static uint32_t max_version = 0;
|
||||
|
||||
const static uint8_t unicode_sep = 0xff;
|
||||
const static uint8_t unicode_start = 0xfe;
|
||||
|
||||
/* bits used in flags */
|
||||
enum psf2_flags {
|
||||
psf2_has_unicode = 0x00000001
|
||||
};
|
||||
|
||||
struct psf2_header {
|
||||
uint8_t magic[4];
|
||||
uint32_t version;
|
||||
uint32_t header_size; // offset of bitmaps in file
|
||||
uint32_t flags;
|
||||
uint32_t length; // number of glyphs
|
||||
uint32_t charsize; // number of bytes for each character
|
||||
uint32_t height, width; // max dimensions of glyphs
|
||||
};
|
||||
|
||||
|
||||
font::font(void const *data) :
|
||||
m_size(0, 0),
|
||||
m_count(0),
|
||||
m_data(nullptr)
|
||||
{
|
||||
psf2_header const *psf2 = static_cast<psf2_header const *>(data);
|
||||
for (int i = 0; i < sizeof(magic); ++i) {
|
||||
kassert(psf2->magic[i] == magic[i], "Bad font magic number.");
|
||||
}
|
||||
|
||||
m_data = static_cast<uint8_t const *>(data) + psf2->header_size;
|
||||
m_size.x = psf2->width;
|
||||
m_size.y = psf2->height;
|
||||
m_count = psf2->length;
|
||||
}
|
||||
|
||||
void
|
||||
font::draw_glyph(
|
||||
screen *s,
|
||||
uint32_t glyph,
|
||||
screen::pixel_t fg,
|
||||
screen::pixel_t bg,
|
||||
unsigned x,
|
||||
unsigned y) const
|
||||
{
|
||||
unsigned bwidth = (m_size.x+7)/8;
|
||||
uint8_t const *data = m_data + (glyph * glyph_bytes());
|
||||
|
||||
for (int dy = 0; dy < m_size.y; ++dy) {
|
||||
for (int dx = 0; dx < bwidth; ++dx) {
|
||||
uint8_t byte = data[dy * bwidth + dx];
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
if (dx*8 + i >= m_size.x) continue;
|
||||
const uint8_t mask = 1 << (7-i);
|
||||
uint32_t c = (byte & mask) ? fg : bg;
|
||||
s->draw_pixel(x + dx*8 + i, y + dy, c);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
|
||||
#include "kutil/coord.h"
|
||||
#include "screen.h"
|
||||
|
||||
class font
|
||||
{
|
||||
public:
|
||||
font(void const *data);
|
||||
|
||||
unsigned glyph_bytes() const { return m_size.y * ((m_size.x + 7) / 8); }
|
||||
unsigned count() const { return m_count; }
|
||||
unsigned width() const { return m_size.x; }
|
||||
unsigned height() const { return m_size.y; }
|
||||
bool valid() const { return m_count > 0; }
|
||||
|
||||
void draw_glyph(
|
||||
screen *s,
|
||||
uint32_t glyph,
|
||||
screen::pixel_t fg,
|
||||
screen::pixel_t bg,
|
||||
unsigned x,
|
||||
unsigned y) const;
|
||||
|
||||
private:
|
||||
kutil::coord<unsigned> m_size;
|
||||
unsigned m_count;
|
||||
uint8_t const *m_data;
|
||||
|
||||
font() = delete;
|
||||
};
|
||||
|
||||
@@ -45,16 +45,15 @@ run_constructors()
|
||||
|
||||
extern void __kernel_assert(const char *, unsigned, const char *);
|
||||
|
||||
/// TODO: not this. this is awful.
|
||||
uintptr_t fb_loc = 0;
|
||||
size_t fb_size = 0;
|
||||
|
||||
/// Bootstrap the memory managers.
|
||||
void memory_initialize_pre_ctors(kernel::args::header *kargs);
|
||||
void memory_initialize_post_ctors(kernel::args::header *kargs);
|
||||
|
||||
using namespace kernel;
|
||||
|
||||
/// TODO: not this. this is awful.
|
||||
args::framebuffer *fb = nullptr;
|
||||
|
||||
void
|
||||
init_console()
|
||||
{
|
||||
@@ -137,8 +136,7 @@ kernel_main(args::header *header)
|
||||
}
|
||||
|
||||
if (header->video.size > 0) {
|
||||
fb_size = header->video.size;
|
||||
fb_loc = header->video.phys_addr;
|
||||
fb = memory::to_virtual<args::framebuffer>(reinterpret_cast<uintptr_t>(&header->video));
|
||||
}
|
||||
|
||||
log::debug(logs::boot, " jsix header is at: %016lx", header);
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
#include "screen.h"
|
||||
|
||||
template <typename T>
|
||||
static int popcount(T x)
|
||||
{
|
||||
int c = 0;
|
||||
while (x) {
|
||||
c += (x & 1);
|
||||
x = x >> 1;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static int ctz(T x)
|
||||
{
|
||||
int c = 0;
|
||||
while ((x & 1) == 0) {
|
||||
x = x >> 1;
|
||||
++c;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
screen::color_masks::color_masks(pixel_t r, pixel_t g, pixel_t b) :
|
||||
r(r), g(g), b(b)
|
||||
{
|
||||
rshift = static_cast<uint8_t>(ctz(r) - (8 - popcount(r)));
|
||||
gshift = static_cast<uint8_t>(ctz(g) - (8 - popcount(g)));
|
||||
bshift = static_cast<uint8_t>(ctz(b) - (8 - popcount(b)));
|
||||
}
|
||||
|
||||
screen::color_masks::color_masks(const color_masks &o) :
|
||||
rshift(o.rshift), gshift(o.gshift), bshift(o.bshift),
|
||||
r(o.r), g(o.g), b(o.b)
|
||||
{
|
||||
}
|
||||
|
||||
screen::screen(
|
||||
void *framebuffer,
|
||||
unsigned hres, unsigned vres,
|
||||
pixel_t rmask, pixel_t gmask, pixel_t bmask) :
|
||||
m_framebuffer(static_cast<pixel_t *>(framebuffer)),
|
||||
m_masks(rmask, gmask, bmask),
|
||||
m_resolution(hres, vres)
|
||||
{
|
||||
}
|
||||
|
||||
screen::pixel_t
|
||||
screen::color(uint8_t r, uint8_t g, uint8_t b) const
|
||||
{
|
||||
return
|
||||
((static_cast<uint32_t>(r) << m_masks.rshift) & m_masks.r) |
|
||||
((static_cast<uint32_t>(g) << m_masks.gshift) & m_masks.g) |
|
||||
((static_cast<uint32_t>(b) << m_masks.bshift) & m_masks.b);
|
||||
}
|
||||
|
||||
void
|
||||
screen::fill(pixel_t color)
|
||||
{
|
||||
const size_t len = m_resolution.size();
|
||||
for (size_t i = 0; i < len; ++i)
|
||||
m_framebuffer[i] = color;
|
||||
}
|
||||
|
||||
void
|
||||
screen::draw_pixel(unsigned x, unsigned y, pixel_t color)
|
||||
{
|
||||
m_framebuffer[x + y * m_resolution.x] = color;
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
#pragma once
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "kutil/coord.h"
|
||||
|
||||
class screen
|
||||
{
|
||||
public:
|
||||
using pixel_t = uint32_t;
|
||||
|
||||
screen(
|
||||
void *framebuffer,
|
||||
unsigned hres, unsigned vres,
|
||||
pixel_t rmask, pixel_t gmask, pixel_t bmask);
|
||||
|
||||
unsigned width() const { return m_resolution.x; }
|
||||
unsigned height() const { return m_resolution.y; }
|
||||
|
||||
pixel_t color(uint8_t r, uint8_t g, uint8_t b) const;
|
||||
|
||||
void fill(pixel_t color);
|
||||
void draw_pixel(unsigned x, unsigned y, pixel_t color);
|
||||
|
||||
private:
|
||||
struct color_masks {
|
||||
uint8_t rshift, gshift, bshift;
|
||||
pixel_t r, g, b;
|
||||
color_masks(pixel_t r, pixel_t g, pixel_t b);
|
||||
color_masks(const color_masks &other);
|
||||
};
|
||||
|
||||
pixel_t *m_framebuffer;
|
||||
color_masks m_masks;
|
||||
kutil::coord<unsigned> m_resolution;
|
||||
|
||||
screen() = delete;
|
||||
};
|
||||
Reference in New Issue
Block a user