Added header for OS drawing and a double buffer.

This commit is contained in:
Patrick 2024-01-15 18:09:48 +01:00
parent 9962ef21f2
commit e938f76823
6 changed files with 187 additions and 20 deletions

View File

@ -6,7 +6,17 @@
namespace std
{
template<typename T>
constexpr const T& min(const T& left, const T& right)
{
return right < left ? right : left;
}
template<typename T>
constexpr const T& max(const T& left, const T& right)
{
return right > left ? right : left;
}
}
#endif // !defined(BAD_APPLE_OS_ALGORITHM_INCLUDED)

View File

@ -3,6 +3,7 @@ Import('env')
any_target_sources = Split('''
src/app/main.cpp
src/os/draw.cpp
src/os/panic.cpp
src/os/tty.cpp

View File

@ -0,0 +1,69 @@
#pragma once
#if !defined(BAD_APPLE_OS_DRAW_HPP_INCLUDED)
#define BAD_APPLE_OS_DRAW_HPP_INCLUDED
#include <stdint.h>
#include <vector>
namespace draw
{
const unsigned SIZE_FULL = static_cast<unsigned>(-1);
struct Pixel
{
uint8_t blue = 0;
uint8_t green = 0;
uint8_t red = 0;
uint8_t reserved_ = 0;
};
class Framebuffer
{
protected:
Pixel* mBase = nullptr;
unsigned mWidth = 0;
unsigned mHeight = 0;
unsigned mPitch = 0;
public:
Framebuffer() = default;
Framebuffer(const Framebuffer&) = default;
Framebuffer(Pixel* base, unsigned width, unsigned height, unsigned pitch) noexcept
: mBase(base), mWidth(width), mHeight(height), mPitch(pitch) {}
[[nodiscard]] Pixel* getBase() const noexcept { return mBase; }
[[nodiscard]] unsigned getWidth() const noexcept { return mWidth; }
[[nodiscard]] unsigned getHeight() const noexcept { return mHeight; }
[[nodiscard]] unsigned getPitch() const noexcept { return mPitch; }
[[nodiscard]] unsigned getBufferSize() const noexcept { return mPitch * mHeight * sizeof(Pixel); }
void setPixel(unsigned posX, unsigned posY, Pixel pixel) noexcept;
};
class OwningFramebuffer : public Framebuffer
{
private:
std::vector<Pixel> mPixels;
public:
OwningFramebuffer() = default;
OwningFramebuffer(const OwningFramebuffer&) noexcept = default;
OwningFramebuffer(OwningFramebuffer&&) noexcept = default;
OwningFramebuffer(unsigned width, unsigned height, unsigned pitch) noexcept;
OwningFramebuffer& operator=(const OwningFramebuffer&) noexcept = default;
OwningFramebuffer& operator=(OwningFramebuffer&&) noexcept = default;
static OwningFramebuffer makeFrom(const Framebuffer& other) noexcept
{
return OwningFramebuffer(other.getWidth(), other.getHeight(), other.getPitch());
}
};
void initializeDefaultFramebuffer(const Framebuffer& framebuffer) noexcept;
void setPixelDirect(unsigned posX, unsigned posY, Pixel pixel) noexcept;
void setPixel(unsigned posX, unsigned posY, Pixel pixel) noexcept;
void flushPixels() noexcept;
}
#endif // !defined(BAD_APPLE_OS_FRAMEBUFFER_HPP_INCLUDED)

View File

@ -106,4 +106,15 @@ void free(void* memory) noexcept
block->nextBlock = gNextBlock;
gNextBlock = block;
}
int __cxa_atexit(void (*func)(void*), void* arg, void* dsoHandle)
{
(void) func;
(void) arg;
(void) dsoHandle;
// NOOP for now
// TODO
return 0;
}
} // extern "C"

View File

@ -0,0 +1,52 @@
#include "os/draw.hpp"
#include <cstring>
namespace draw
{
namespace
{
Framebuffer gFramebuffer;
OwningFramebuffer gDoubleBuffer;
}
OwningFramebuffer::OwningFramebuffer(unsigned width, unsigned height, unsigned pitch) noexcept
: Framebuffer(nullptr, width, height, pitch)
{
mPixels.resize(height * pitch);
mBase = mPixels.data();
}
void Framebuffer::setPixel(unsigned int posX, unsigned int posY, Pixel pixel) noexcept
{
if (posX >= mWidth || posY > mHeight) {
return;
}
mBase[posY * mPitch + posX] = pixel;
}
void initializeDefaultFramebuffer(const Framebuffer& framebuffer) noexcept
{
gFramebuffer = framebuffer;
gDoubleBuffer = OwningFramebuffer::makeFrom(gFramebuffer);
}
void setPixelDirect(unsigned posX, unsigned posY, Pixel pixel) noexcept
{
gFramebuffer.setPixel(posX, posY, pixel);
// also set it in the double buffer, otherwise it will be lost on flush
gDoubleBuffer.setPixel(posX, posY, pixel);
}
void setPixel(unsigned posX, unsigned posY, Pixel pixel) noexcept
{
gDoubleBuffer.setPixel(posX, posY, pixel);
}
void flushPixels() noexcept
{
std::memcpy(gFramebuffer.getBase(), gDoubleBuffer.getBase(), gFramebuffer.getBufferSize());
}
}

View File

@ -1,16 +1,41 @@
#include "os/tty.hpp"
#include <cstdio>
#include <cstdlib>
#include "boot.hpp"
#include "os/draw.hpp"
#include "os/tty.hpp"
extern "C" int gKernelEnd;
namespace
{
void initHeapFromEfiMemoryMap(const EfiMemoryMap& memoryMap) noexcept
{
const uint64_t minAddr = reinterpret_cast<uint64_t>(&gKernelEnd);
for (const EFI_MEMORY_DESCRIPTOR& descriptor : memoryMap)
{
// TODO: what about other types?
if (descriptor.Type != EfiConventionalMemory)
{
continue;
}
uint64_t addr = descriptor.PhysicalStart;
uint64_t len = descriptor.NumberOfPages * 4096; // TODO: is this the correct page size?
// anything before the kernel we ignore
if (addr < minAddr)
{
// if the entire entry is before the kernel, continue
if (addr + len <= minAddr)
{
continue;
}
// otherwise shrink it and use the rest
len -= (minAddr - addr);
addr = minAddr;
}
__ba_registerAllocatableMemory(reinterpret_cast<void*>(addr), len);
}
#if 0
const uint64_t minAddr = reinterpret_cast<uint64_t>(&gKernelEnd);
for (uint32_t addr = firstEntryAddr; addr < firstEntryAddr + bufferLength;)
@ -71,35 +96,34 @@ void kernel_main()
{
initGlobals();
/* Initialize terminal interface */
tty::initialize();
// init the heap (required for the double buffer)
initHeapFromEfiMemoryMap(gBootInfo->memoryMap);
std::printf("Kernel End: %p\n", &gKernelEnd);
// initialize the framebuffer
draw::initializeDefaultFramebuffer({
/* base = */ static_cast<draw::Pixel*>(gBootInfo->displayInfo.frameBufferBase),
/* width = */ gBootInfo->displayInfo.frameBufferWidth,
/* height = */ gBootInfo->displayInfo.frameBufferHeight,
/* pitch = */ gBootInfo->displayInfo.frameBufferPitch / 4
});
// initialize terminal interface
// tty::initialize();
// std::printf("Kernel End: %p\n", &gKernelEnd);
struct Pixel
{
uint8_t blue = 0;
uint8_t green = 0;
uint8_t red = 0;
uint8_t reserved = 0;
};
auto setPixel = [](unsigned x, unsigned y, Pixel color)
{
Pixel* framebuffer = static_cast<Pixel*>(gBootInfo->displayInfo.frameBufferBase);
framebuffer[y * gBootInfo->displayInfo.frameBufferPitch / 4 + x] = color;
};
for (int x = 0; x < 100; ++x)
{
for (int y = 0; y < 100; ++y)
{
setPixel(x, y, {.red = 255});
draw::setPixel(x, y, {.red = 255});
}
}
draw::flushPixels();
/* Initialize the heap */
// assert(gMultibootHeader->flags & MULTIBOOT_INFO_MEM_MAP);
// initHeapFromMultibootHeader(gMultibootHeader->mmap_addr, gMultibootHeader->mmap_length);
initHeapFromEfiMemoryMap(gBootInfo->memoryMap);
main();