Added header for OS drawing and a double buffer.
This commit is contained in:
parent
9962ef21f2
commit
e938f76823
@ -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)
|
||||
|
@ -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
|
||||
|
||||
|
69
targets/_any/include/os/draw.hpp
Normal file
69
targets/_any/include/os/draw.hpp
Normal 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)
|
@ -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"
|
52
targets/_any/src/os/draw.cpp
Normal file
52
targets/_any/src/os/draw.cpp
Normal 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());
|
||||
}
|
||||
}
|
@ -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();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user