Added header for OS drawing and a double buffer.
This commit is contained in:
parent
9962ef21f2
commit
e938f76823
@ -6,7 +6,17 @@
|
|||||||
|
|
||||||
namespace std
|
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)
|
#endif // !defined(BAD_APPLE_OS_ALGORITHM_INCLUDED)
|
||||||
|
@ -3,6 +3,7 @@ Import('env')
|
|||||||
any_target_sources = Split('''
|
any_target_sources = Split('''
|
||||||
src/app/main.cpp
|
src/app/main.cpp
|
||||||
|
|
||||||
|
src/os/draw.cpp
|
||||||
src/os/panic.cpp
|
src/os/panic.cpp
|
||||||
src/os/tty.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;
|
block->nextBlock = gNextBlock;
|
||||||
gNextBlock = block;
|
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"
|
} // 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 <cstdio>
|
||||||
#include <cstdlib>
|
|
||||||
#include "boot.hpp"
|
#include "boot.hpp"
|
||||||
|
|
||||||
|
#include "os/draw.hpp"
|
||||||
|
#include "os/tty.hpp"
|
||||||
|
|
||||||
extern "C" int gKernelEnd;
|
extern "C" int gKernelEnd;
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
void initHeapFromEfiMemoryMap(const EfiMemoryMap& memoryMap) noexcept
|
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
|
#if 0
|
||||||
const uint64_t minAddr = reinterpret_cast<uint64_t>(&gKernelEnd);
|
const uint64_t minAddr = reinterpret_cast<uint64_t>(&gKernelEnd);
|
||||||
for (uint32_t addr = firstEntryAddr; addr < firstEntryAddr + bufferLength;)
|
for (uint32_t addr = firstEntryAddr; addr < firstEntryAddr + bufferLength;)
|
||||||
@ -71,35 +96,34 @@ void kernel_main()
|
|||||||
{
|
{
|
||||||
initGlobals();
|
initGlobals();
|
||||||
|
|
||||||
/* Initialize terminal interface */
|
// init the heap (required for the double buffer)
|
||||||
tty::initialize();
|
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 x = 0; x < 100; ++x)
|
||||||
{
|
{
|
||||||
for (int y = 0; y < 100; ++y)
|
for (int y = 0; y < 100; ++y)
|
||||||
{
|
{
|
||||||
setPixel(x, y, {.red = 255});
|
draw::setPixel(x, y, {.red = 255});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
draw::flushPixels();
|
||||||
|
|
||||||
/* Initialize the heap */
|
/* Initialize the heap */
|
||||||
// assert(gMultibootHeader->flags & MULTIBOOT_INFO_MEM_MAP);
|
// assert(gMultibootHeader->flags & MULTIBOOT_INFO_MEM_MAP);
|
||||||
// initHeapFromMultibootHeader(gMultibootHeader->mmap_addr, gMultibootHeader->mmap_length);
|
// initHeapFromMultibootHeader(gMultibootHeader->mmap_addr, gMultibootHeader->mmap_length);
|
||||||
initHeapFromEfiMemoryMap(gBootInfo->memoryMap);
|
|
||||||
|
|
||||||
main();
|
main();
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user