Kernel/include/display.hpp

202 lines
6.3 KiB
C++

#ifndef __FENNIX_KERNEL_DISPLAY_H__
#define __FENNIX_KERNEL_DISPLAY_H__
#include <types.h>
#include <boot/binfo.h>
#include <memory.hpp>
#include <debug.h>
#include <cstring>
namespace Video
{
#define PSF1_MAGIC0 0x36
#define PSF1_MAGIC1 0x04
#define PSF2_MAGIC0 0x72
#define PSF2_MAGIC1 0xb5
#define PSF2_MAGIC2 0x4a
#define PSF2_MAGIC3 0x86
struct PSF1_HEADER
{
uint8_t magic[2];
uint8_t mode;
uint8_t charsize;
};
struct PSF2_HEADER
{
uint8_t magic[4];
uint32_t version;
uint32_t headersize;
uint32_t flags;
uint32_t length;
uint32_t charsize;
uint32_t height, width;
};
typedef struct _PSF1_FONT
{
PSF1_HEADER *Header;
void *GlyphBuffer;
} PSF1_FONT;
typedef struct _PSF2_FONT
{
PSF2_HEADER *Header;
void *GlyphBuffer;
} PSF2_FONT;
enum FontType
{
None,
PCScreenFont1,
PCScreenFont2
};
struct FontInfo
{
uint64_t *StartAddress;
uint64_t *EndAddress;
PSF1_FONT *PSF1Font;
PSF2_FONT *PSF2Font;
uint32_t Width, Height;
FontType Type;
};
class Font
{
private:
FontInfo Info;
public:
FontInfo GetInfo() { return Info; }
Font(uint64_t *Start, uint64_t *End, FontType Type);
~Font();
};
struct ScreenBuffer
{
void *Buffer = nullptr;
uint32_t Width, Height;
uint64_t Size;
uint32_t Color;
uint32_t CursorX, CursorY;
long Checksum;
};
class Display
{
private:
BootInfo::FramebufferInfo framebuffer;
Font *CurrentFont;
ScreenBuffer *Buffers[256];
bool ColorIteration = false;
int ColorPickerIteration = 0;
public:
Font *GetCurrentFont() { return CurrentFont; }
void SetCurrentFont(Font *Font) { CurrentFont = Font; }
void CreateBuffer(uint32_t Width, uint32_t Height, int Index)
{
if (Width == 0 && Height == 0)
{
Width = this->framebuffer.Width;
Height = this->framebuffer.Height;
debug("No width and height specified, using %ldx%lld", Width, Height);
}
uint64_t Size = this->framebuffer.Pitch * Height;
if (!this->Buffers[Index])
{
if (this->Buffers[Index]->Checksum != 0xDEAD5C9EE7)
{
ScreenBuffer *buffer = new ScreenBuffer;
buffer->Buffer = KernelAllocator.RequestPages(TO_PAGES(Size));
buffer->Width = Width;
buffer->Height = Height;
buffer->Size = Size;
buffer->Color = 0xFFFFFF;
buffer->CursorX = 0;
buffer->CursorY = 0;
this->Buffers[Index] = buffer;
memset(this->Buffers[Index]->Buffer, 0, Size);
this->Buffers[Index]->Checksum = 0xDEAD5C9EE7;
}
else
warn("Buffer %d already exists, skipping creation", Index);
}
else
warn("Buffer %d already exists, skipping creation", Index);
}
void SetBuffer(int Index) { memcpy(this->framebuffer.BaseAddress, this->Buffers[Index]->Buffer, this->Buffers[Index]->Size); }
ScreenBuffer *GetBuffer(int Index) { return this->Buffers[Index]; }
void ClearBuffer(int Index) { memset(this->Buffers[Index]->Buffer, 0, this->Buffers[Index]->Size); }
void DeleteBuffer(int Index)
{
if (this->Buffers[Index] == nullptr)
return;
KernelAllocator.FreePages(this->Buffers[Index]->Buffer, TO_PAGES(this->Buffers[Index]->Size));
this->Buffers[Index]->Checksum = 0; // Making sure that the buffer is not used anymore
delete this->Buffers[Index];
}
void SetBufferCursor(int Index, uint32_t X, uint32_t Y)
{
this->Buffers[Index]->CursorX = X;
this->Buffers[Index]->CursorY = Y;
}
void GetBufferCursor(int Index, uint32_t *X, uint32_t *Y)
{
*X = this->Buffers[Index]->CursorX;
*Y = this->Buffers[Index]->CursorY;
}
void SetPixel(uint32_t X, uint32_t Y, uint32_t Color, int Index)
{
if (X >= this->Buffers[Index]->Width)
X = this->Buffers[Index]->Width - 1;
if (Y >= this->Buffers[Index]->Height)
Y = this->Buffers[Index]->Height - 1;
uint32_t *Pixel = (uint32_t *)((uint64_t)this->Buffers[Index]->Buffer + (Y * this->Buffers[Index]->Width + X) * (this->framebuffer.BitsPerPixel / 8));
*Pixel = Color;
}
uint32_t GetPixel(uint32_t X, uint32_t Y, int Index)
{
if (X >= this->Buffers[Index]->Width || Y >= this->Buffers[Index]->Height)
return 0;
uint32_t *Pixel = (uint32_t *)((uint64_t)this->Buffers[Index]->Buffer + (Y * this->Buffers[Index]->Width + X) * (this->framebuffer.BitsPerPixel / 8));
return *Pixel;
}
void Scroll(int Index, int Lines)
{
if (Lines == 0)
return;
if (Lines > 0)
{
for (uint32_t i = 0; i < this->CurrentFont->GetInfo().Height; i++) // TODO: Make this more efficient.
{
memmove(this->Buffers[Index]->Buffer,
(uint8_t *)this->Buffers[Index]->Buffer + (this->Buffers[Index]->Width * (this->framebuffer.BitsPerPixel / 8) * Lines),
this->Buffers[Index]->Size - (this->Buffers[Index]->Width * (this->framebuffer.BitsPerPixel / 8) * Lines));
memset((uint8_t *)this->Buffers[Index]->Buffer + (this->Buffers[Index]->Size - (this->Buffers[Index]->Width * (this->framebuffer.BitsPerPixel / 8) * Lines)),
0,
this->Buffers[Index]->Width * (this->framebuffer.BitsPerPixel / 8) * Lines);
}
}
}
char Print(char Char, int Index, bool WriteToUART = false);
Display(BootInfo::FramebufferInfo Info, bool LoadDefaultFont = true);
~Display();
};
}
#endif // !__FENNIX_KERNEL_DISPLAY_H__