mirror of
https://github.com/Fennix-Project/Kernel.git
synced 2025-05-25 22:14:37 +00:00
202 lines
6.3 KiB
C++
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__
|