79 lines
2.1 KiB
C++
79 lines
2.1 KiB
C++
#include "fs/devices/FramebufferDevice.h"
|
|
#include "arch/MMU.h"
|
|
#include "memory/SharedMemory.h"
|
|
#include "video/Framebuffer.h"
|
|
#include <bits/ioctl-defs.h>
|
|
#include <luna/CString.h>
|
|
|
|
Result<void> FramebufferDevice::create()
|
|
{
|
|
auto device = (SharedPtr<Device>)TRY(make_shared<FramebufferDevice>());
|
|
return DeviceRegistry::register_special_device(DeviceRegistry::Framebuffer, 0, device, 0600);
|
|
}
|
|
|
|
Result<usize> FramebufferDevice::read(u8*, usize, usize) const
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
Result<usize> FramebufferDevice::write(const u8* buf, usize offset, usize length)
|
|
{
|
|
if ((offset + length) > size()) length = size() - offset;
|
|
|
|
memcpy(Framebuffer::ptr() + offset, buf, length);
|
|
|
|
return length;
|
|
}
|
|
|
|
Result<u64> FramebufferDevice::query_shared_memory(off_t offset, usize count)
|
|
{
|
|
if (offset + (count * ARCH_PAGE_SIZE) > Framebuffer::size()) return err(EINVAL);
|
|
|
|
if (!m_shmid.has_value())
|
|
{
|
|
u64 shmid = TRY(SharedMemory::create(Framebuffer::ptr() + offset, offset, count));
|
|
m_shmid = shmid;
|
|
auto* shm = g_shared_memory_map.try_get_ref(shmid);
|
|
shm->device = SharedPtr<Device> { this };
|
|
return shmid;
|
|
}
|
|
|
|
auto* shm = g_shared_memory_map.try_get_ref(*m_shmid);
|
|
if (!shm)
|
|
{
|
|
m_shmid = {};
|
|
return query_shared_memory(offset, count);
|
|
}
|
|
if (shm->offset > offset)
|
|
{
|
|
TRY(shm->grow_backward(Framebuffer::ptr() + offset, (shm->offset - offset) / ARCH_PAGE_SIZE));
|
|
}
|
|
if (shm->frames.size() < count)
|
|
{
|
|
TRY(shm->grow_forward(Framebuffer::ptr() + offset + (shm->frames.size() * ARCH_PAGE_SIZE),
|
|
count - shm->frames.size()));
|
|
}
|
|
return *m_shmid;
|
|
}
|
|
|
|
usize FramebufferDevice::size() const
|
|
{
|
|
return Framebuffer::size();
|
|
}
|
|
|
|
bool FramebufferDevice::will_block_if_read() const
|
|
{
|
|
return false;
|
|
}
|
|
|
|
Result<u64> FramebufferDevice::ioctl(int request, void*)
|
|
{
|
|
switch (request)
|
|
{
|
|
case FB_GET_WIDTH: return (u64)Framebuffer::width();
|
|
case FB_GET_HEIGHT: return (u64)Framebuffer::height();
|
|
case FB_GET_SCANLINE: return (u64)Framebuffer::scanline();
|
|
default: return err(EINVAL);
|
|
}
|
|
}
|