mirror of
https://gitlab.com/sortix/sortix.git
synced 2023-02-13 20:55:38 -05:00
Refactor graphical resolution changes.
This commit is contained in:
parent
0342e03073
commit
e7c5d032d1
16 changed files with 481 additions and 126 deletions
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 2014 Jonas 'Sortie' Termansen.
|
||||
* Copyright (c) 2012, 2014, 2016 Jonas 'Sortie' Termansen.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -38,7 +38,10 @@
|
|||
#include <sortix/kernel/textbuffer.h>
|
||||
#include <sortix/kernel/video.h>
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
#include "x86-family/memorymanagement.h"
|
||||
#endif
|
||||
|
||||
#include "lfbtextbuffer.h"
|
||||
#include "bga.h"
|
||||
|
||||
|
@ -100,20 +103,22 @@ public:
|
|||
virtual ~BGADevice();
|
||||
|
||||
public:
|
||||
virtual struct dispmsg_crtc_mode GetCurrentMode(uint64_t connector) const;
|
||||
virtual uint64_t GetConnectorCount();
|
||||
virtual bool GetDefaultMode(uint64_t connector, struct dispmsg_crtc_mode* mode);
|
||||
virtual bool GetCurrentMode(uint64_t connector, struct dispmsg_crtc_mode* mode);
|
||||
virtual bool SwitchMode(uint64_t connector, struct dispmsg_crtc_mode mode);
|
||||
virtual bool Supports(uint64_t connector, struct dispmsg_crtc_mode mode) const;
|
||||
virtual struct dispmsg_crtc_mode* GetModes(uint64_t connector, size_t* num_modes) const;
|
||||
virtual off_t FrameSize() const;
|
||||
virtual bool Supports(uint64_t connector, struct dispmsg_crtc_mode mode);
|
||||
virtual struct dispmsg_crtc_mode* GetModes(uint64_t connector, size_t* num_modes);
|
||||
virtual off_t FrameSize();
|
||||
virtual ssize_t WriteAt(ioctx_t* ctx, off_t off, const void* buf, size_t count);
|
||||
virtual ssize_t ReadAt(ioctx_t* ctx, off_t off, void* buf, size_t count);
|
||||
virtual TextBuffer* CreateTextBuffer(uint64_t connector);
|
||||
virtual TextBuffer* CreateTextBuffer(uint64_t connector, struct dispmsg_crtc_mode mode);
|
||||
|
||||
public:
|
||||
bool Initialize();
|
||||
|
||||
private:
|
||||
bool DetectModes() const;
|
||||
bool DetectModes();
|
||||
uint16_t WriteRegister(uint16_t index, uint16_t value);
|
||||
uint16_t ReadRegister(uint16_t index);
|
||||
uint16_t GetCapability(uint16_t index);
|
||||
|
@ -121,8 +126,8 @@ private:
|
|||
bool SupportsResolution(uint16_t width, uint16_t height, uint16_t depth);
|
||||
|
||||
private:
|
||||
mutable size_t num_modes;
|
||||
mutable struct dispmsg_crtc_mode* modes;
|
||||
size_t num_modes;
|
||||
struct dispmsg_crtc_mode* modes;
|
||||
struct dispmsg_crtc_mode current_mode;
|
||||
addralloc_t fb_alloc;
|
||||
addralloc_t mmio_alloc;
|
||||
|
@ -223,32 +228,91 @@ bool BGADevice::SetVideoMode(uint16_t width, uint16_t height, uint16_t depth, bo
|
|||
return true;
|
||||
}
|
||||
|
||||
uint64_t BGADevice::GetConnectorCount()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
// TODO: Need a better method of detecting available/desired resolutions.
|
||||
bool BGADevice::SupportsResolution(uint16_t width, uint16_t height, uint16_t depth)
|
||||
{
|
||||
if ( !width || !height || !depth )
|
||||
return false;
|
||||
return errno = EINVAL, false;
|
||||
if ( maxxres < width || maxyres < height || maxbpp < depth )
|
||||
return false;
|
||||
return errno = EINVAL, false;
|
||||
// TODO: Is this actually a restriction?
|
||||
if ( width % 8U )
|
||||
return false;
|
||||
// TODO: This is not a restriction in VirtualBox anymore at least.
|
||||
//if ( width % 8U )
|
||||
// return errno = EINVAL, false;
|
||||
// TODO: Can we determine this more closely in advance? Perhaps if the
|
||||
// framebuffer we will be using is larger than video memory?
|
||||
return true;
|
||||
}
|
||||
|
||||
struct dispmsg_crtc_mode BGADevice::GetCurrentMode(uint64_t connector) const
|
||||
bool BGADevice::GetDefaultMode(uint64_t connector,
|
||||
struct dispmsg_crtc_mode* mode_out)
|
||||
{
|
||||
if ( connector != 0 )
|
||||
if ( connector )
|
||||
return errno = EINVAL, false;
|
||||
|
||||
bool good = false;
|
||||
uint32_t xres;
|
||||
uint32_t yres;
|
||||
uint32_t bpp;
|
||||
if ( connector == 0 && Log::fallback_framebuffer &&
|
||||
SupportsResolution(Log::fallback_framebuffer_width,
|
||||
Log::fallback_framebuffer_height,
|
||||
32) )
|
||||
{
|
||||
errno = EINVAL;
|
||||
struct dispmsg_crtc_mode mode;
|
||||
memset(&mode, 0, sizeof(mode));
|
||||
return mode;
|
||||
xres = Log::fallback_framebuffer_width;
|
||||
yres = Log::fallback_framebuffer_height;
|
||||
bpp = 32;
|
||||
}
|
||||
else if ( connector == 0 && Log::fallback_framebuffer &&
|
||||
SupportsResolution(Log::fallback_framebuffer_width,
|
||||
Log::fallback_framebuffer_height,
|
||||
Log::fallback_framebuffer_bpp) )
|
||||
{
|
||||
xres = Log::fallback_framebuffer_width;
|
||||
yres = Log::fallback_framebuffer_height;
|
||||
bpp = Log::fallback_framebuffer_bpp;
|
||||
}
|
||||
else
|
||||
{
|
||||
return errno = EINVAL, false;
|
||||
}
|
||||
|
||||
return current_mode;
|
||||
struct dispmsg_crtc_mode mode;
|
||||
memset(&mode, 0, sizeof(0));
|
||||
mode.driver_index = 0;
|
||||
mode.magic = 0;
|
||||
mode.control = DISPMSG_CONTROL_VALID | DISPMSG_CONTROL_DEFAULT;
|
||||
if ( good )
|
||||
mode.control |= DISPMSG_CONTROL_GOOD_DEFAULT;
|
||||
mode.fb_format = bpp;
|
||||
mode.view_xres = xres;
|
||||
mode.view_yres = yres;
|
||||
mode.fb_location = 0;
|
||||
mode.pitch = xres * (bpp + 7) / 8;
|
||||
mode.surf_off_x = 0;
|
||||
mode.surf_off_y = 0;
|
||||
mode.start_x = 0;
|
||||
mode.start_y = 0;
|
||||
mode.end_x = 0;
|
||||
mode.end_y = 0;
|
||||
mode.desktop_height = yres;
|
||||
*mode_out = mode;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BGADevice::GetCurrentMode(uint64_t connector,
|
||||
struct dispmsg_crtc_mode* mode)
|
||||
{
|
||||
if ( connector != 0 )
|
||||
return false;
|
||||
*mode = current_mode;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BGADevice::SwitchMode(uint64_t connector, struct dispmsg_crtc_mode mode)
|
||||
|
@ -259,13 +323,6 @@ bool BGADevice::SwitchMode(uint64_t connector, struct dispmsg_crtc_mode mode)
|
|||
if ( connector != 0 )
|
||||
return errno = EINVAL, false;
|
||||
|
||||
size_t new_framesize = (size_t) mode.view_xres *
|
||||
(size_t) mode.view_yres *
|
||||
((size_t) mode.fb_format + 7) / 8UL;
|
||||
// TODO: Use a better error code than ENOSPC?
|
||||
if ( fb_alloc.size < new_framesize )
|
||||
return errno = ENOSPC, false;
|
||||
|
||||
if ( !SetVideoMode(mode.view_xres, mode.view_yres, mode.fb_format, false) )
|
||||
return false;
|
||||
|
||||
|
@ -274,7 +331,7 @@ bool BGADevice::SwitchMode(uint64_t connector, struct dispmsg_crtc_mode mode)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool BGADevice::Supports(uint64_t connector, struct dispmsg_crtc_mode mode) const
|
||||
bool BGADevice::Supports(uint64_t connector, struct dispmsg_crtc_mode mode)
|
||||
{
|
||||
if ( connector != 0 )
|
||||
return errno = EINVAL, false;
|
||||
|
@ -303,10 +360,17 @@ bool BGADevice::Supports(uint64_t connector, struct dispmsg_crtc_mode mode) cons
|
|||
mode.fb_format != VBE_DISPI_BPP_32 )
|
||||
return errno = ENOSYS, false;
|
||||
|
||||
return ((BGADevice*) this)->SupportsResolution(mode.view_xres, mode.view_yres, mode.fb_format);
|
||||
size_t new_framesize = (size_t) mode.view_xres *
|
||||
(size_t) mode.view_yres *
|
||||
((size_t) mode.fb_format + 7) / 8UL;
|
||||
// TODO: Use a better error code than ENOSPC?
|
||||
if ( fb_alloc.size < new_framesize )
|
||||
return errno = ENOSPC, false;
|
||||
|
||||
return SupportsResolution(mode.view_xres, mode.view_yres, mode.fb_format);
|
||||
}
|
||||
|
||||
struct dispmsg_crtc_mode* BGADevice::GetModes(uint64_t connector, size_t* retnum) const
|
||||
struct dispmsg_crtc_mode* BGADevice::GetModes(uint64_t connector, size_t* retnum)
|
||||
{
|
||||
if ( connector != 0 )
|
||||
return errno = EINVAL, (struct dispmsg_crtc_mode*) NULL;
|
||||
|
@ -322,7 +386,7 @@ struct dispmsg_crtc_mode* BGADevice::GetModes(uint64_t connector, size_t* retnum
|
|||
return result;
|
||||
}
|
||||
|
||||
off_t BGADevice::FrameSize() const
|
||||
off_t BGADevice::FrameSize()
|
||||
{
|
||||
return (off_t) fb_alloc.size;
|
||||
}
|
||||
|
@ -351,7 +415,7 @@ ssize_t BGADevice::ReadAt(ioctx_t* ctx, off_t off, void* buf, size_t count)
|
|||
return count;
|
||||
}
|
||||
|
||||
bool BGADevice::DetectModes() const
|
||||
bool BGADevice::DetectModes()
|
||||
{
|
||||
num_modes = 0;
|
||||
unsigned bpp = VBE_DISPI_BPP_32;
|
||||
|
@ -401,15 +465,19 @@ bool BGADevice::DetectModes() const
|
|||
return true;
|
||||
}
|
||||
|
||||
TextBuffer* BGADevice::CreateTextBuffer(uint64_t connector)
|
||||
TextBuffer* BGADevice::CreateTextBuffer(uint64_t connector,
|
||||
struct dispmsg_crtc_mode mode)
|
||||
{
|
||||
if ( !Supports(connector, mode) )
|
||||
return NULL;
|
||||
|
||||
if ( connector != 0 )
|
||||
return errno = EINVAL, (TextBuffer*) NULL;
|
||||
|
||||
uint8_t* lfb = (uint8_t*) fb_alloc.from;
|
||||
uint32_t lfbformat = current_mode.fb_format;
|
||||
size_t scansize = current_mode.view_xres * current_mode.fb_format / 8UL;
|
||||
return CreateLFBTextBuffer(lfb, lfbformat, current_mode.view_xres, current_mode.view_yres, scansize);
|
||||
uint32_t lfbformat = mode.fb_format;
|
||||
size_t scansize = mode.view_xres * mode.fb_format / 8UL;
|
||||
return CreateLFBTextBuffer(lfb, lfbformat, mode.view_xres, mode.view_yres, scansize);
|
||||
}
|
||||
|
||||
static void TryInitializeDevice(uint32_t devaddr)
|
||||
|
@ -498,6 +566,8 @@ static void TryInitializeDevice(uint32_t devaddr)
|
|||
delete bga_device;
|
||||
return;
|
||||
}
|
||||
|
||||
Video::ConfigureDevice(bga_device);
|
||||
}
|
||||
|
||||
void Init()
|
||||
|
|
|
@ -33,6 +33,9 @@ static const uint32_t DISPMSG_CONTROL_VALID = 1 << 0;
|
|||
static const uint32_t DISPMSG_CONTROL_VGA = 1 << 1;
|
||||
static const uint32_t DISPMSG_CONTROL_OTHER_RESOLUTIONS = 1 << 2;
|
||||
static const uint32_t DISPMSG_CONTROL_FALLBACK = 1 << 3;
|
||||
static const uint32_t DISPMSG_CONTROL_DEFAULT = 1 << 4;
|
||||
static const uint32_t DISPMSG_CONTROL_GOOD_DEFAULT = 1 << 5;
|
||||
static const uint32_t DISPMSG_CONTROL_VM_AUTO_SCALE = 1 << 6;
|
||||
|
||||
struct dispmsg_string
|
||||
{
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2011, 2012, 2013, 2014, 2015 Jonas 'Sortie' Termansen.
|
||||
* Copyright (c) 2011, 2012, 2013, 2014, 2015, 2016 Jonas 'Sortie' Termansen.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -30,6 +30,7 @@ typedef struct multiboot_info multiboot_info_t;
|
|||
|
||||
namespace Sortix {
|
||||
|
||||
class TextBuffer;
|
||||
class TextBufferHandle;
|
||||
|
||||
} // namespace Sortix
|
||||
|
@ -126,6 +127,9 @@ inline size_t PrintFV(const char* format, va_list list)
|
|||
|
||||
void Init(multiboot_info_t* bootinfo);
|
||||
void Center(const char* string);
|
||||
void BeginReplace();
|
||||
void CancelReplace();
|
||||
void FinishReplace(TextBuffer* textbuf);
|
||||
|
||||
} // namespace Log
|
||||
} // namespace Sortix
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 2013, 2014, 2015 Jonas 'Sortie' Termansen.
|
||||
* Copyright (c) 2012, 2013, 2014, 2015, 2016 Jonas 'Sortie' Termansen.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -76,22 +76,24 @@ class TextBuffer
|
|||
{
|
||||
public:
|
||||
virtual ~TextBuffer() { }
|
||||
virtual size_t Width() const = 0;
|
||||
virtual size_t Height() const = 0;
|
||||
virtual TextChar GetChar(TextPos pos) const = 0;
|
||||
virtual size_t Width() = 0;
|
||||
virtual size_t Height() = 0;
|
||||
virtual TextChar GetChar(TextPos pos) = 0;
|
||||
virtual void SetChar(TextPos pos, TextChar c) = 0;
|
||||
virtual void Scroll(ssize_t off, TextChar fillwith) = 0;
|
||||
virtual void Move(TextPos to, TextPos from, size_t numchars) = 0;
|
||||
virtual void Fill(TextPos from, TextPos to, TextChar fillwith) = 0;
|
||||
virtual bool GetCursorEnabled() const = 0;
|
||||
virtual bool GetCursorEnabled() = 0;
|
||||
virtual void SetCursorEnabled(bool enablecursor) = 0;
|
||||
virtual TextPos GetCursorPos() const = 0;
|
||||
virtual TextPos GetCursorPos() = 0;
|
||||
virtual void SetCursorPos(TextPos cursorpos) = 0;
|
||||
virtual void SpawnThreads() = 0;
|
||||
virtual void Invalidate() = 0;
|
||||
virtual bool EmergencyIsImpaired() = 0;
|
||||
virtual bool EmergencyRecoup() = 0;
|
||||
virtual void EmergencyReset() = 0;
|
||||
virtual void Resume() = 0;
|
||||
virtual void Pause() = 0;
|
||||
|
||||
};
|
||||
|
||||
|
@ -107,7 +109,9 @@ public:
|
|||
~TextBufferHandle();
|
||||
TextBuffer* Acquire();
|
||||
void Release(TextBuffer* textbuf);
|
||||
void Replace(TextBuffer* newtextbuf);
|
||||
void BeginReplace();
|
||||
void CancelReplace();
|
||||
void FinishReplace(TextBuffer* newtextbuf);
|
||||
bool EmergencyIsImpaired();
|
||||
bool EmergencyRecoup();
|
||||
void EmergencyReset();
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 2014, 2015 Jonas 'Sortie' Termansen.
|
||||
* Copyright (c) 2012, 2014, 2015, 2016 Jonas 'Sortie' Termansen.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -36,14 +36,19 @@ class VideoDevice
|
|||
{
|
||||
public:
|
||||
virtual ~VideoDevice() { }
|
||||
virtual struct dispmsg_crtc_mode GetCurrentMode(uint64_t connector) const = 0;
|
||||
virtual uint64_t GetConnectorCount() = 0;
|
||||
virtual bool GetDefaultMode(uint64_t connector, struct dispmsg_crtc_mode* mode) = 0;
|
||||
virtual bool GetCurrentMode(uint64_t connector, struct dispmsg_crtc_mode* mode) = 0;
|
||||
virtual bool SwitchMode(uint64_t connector, struct dispmsg_crtc_mode mode) = 0;
|
||||
virtual bool Supports(uint64_t connector, struct dispmsg_crtc_mode mode) const = 0;
|
||||
virtual struct dispmsg_crtc_mode* GetModes(uint64_t connector, size_t* nummodes) const = 0;
|
||||
virtual off_t FrameSize() const = 0;
|
||||
virtual bool Supports(uint64_t connector, struct dispmsg_crtc_mode mode) = 0;
|
||||
virtual struct dispmsg_crtc_mode* GetModes(uint64_t connector, size_t* nummodes) = 0;
|
||||
virtual off_t FrameSize() = 0;
|
||||
virtual ssize_t WriteAt(ioctx_t* ctx, off_t off, const void* buf, size_t count) = 0;
|
||||
virtual ssize_t ReadAt(ioctx_t* ctx, off_t off, void* buf, size_t count) = 0;
|
||||
virtual TextBuffer* CreateTextBuffer(uint64_t connector) = 0;
|
||||
virtual TextBuffer* CreateTextBuffer(uint64_t connector, struct dispmsg_crtc_mode mode) = 0;
|
||||
|
||||
public:
|
||||
uint64_t device_index;
|
||||
|
||||
};
|
||||
|
||||
|
@ -53,6 +58,9 @@ namespace Sortix {
|
|||
namespace Video {
|
||||
|
||||
bool RegisterDevice(const char* name, VideoDevice* device);
|
||||
bool ConfigureDevice(VideoDevice* device);
|
||||
bool ResizeDisplay(uint64_t device, uint64_t connector, uint32_t xres,
|
||||
uint32_t yres, uint32_t bpp);
|
||||
|
||||
} // namespace Video
|
||||
} // namespace Sortix
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 2013, 2014, 2015 Jonas 'Sortie' Termansen.
|
||||
* Copyright (c) 2012, 2013, 2014, 2015, 2016 Jonas 'Sortie' Termansen.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -105,10 +105,10 @@ LFBTextBuffer* CreateLFBTextBuffer(uint8_t* lfb, uint32_t lfbformat,
|
|||
}
|
||||
ret->cursorenabled = true;
|
||||
ret->cursorpos = TextPos(0, 0);
|
||||
for ( size_t y = 0; y < yres; y++ )
|
||||
memset(lfb + scansize * y, 0, ret->bytes_per_pixel * xres);
|
||||
ret->emergency_state = false;
|
||||
ret->invalidated = false;
|
||||
ret->need_clear = true;
|
||||
ret->exit_after_pause = false;
|
||||
|
||||
if ( !kernel_process )
|
||||
return ret;
|
||||
|
@ -149,10 +149,21 @@ LFBTextBuffer::~LFBTextBuffer()
|
|||
{
|
||||
if ( queue_thread )
|
||||
{
|
||||
TextBufferCmd cmd;
|
||||
cmd.type = TEXTBUFCMD_EXIT;
|
||||
IssueCommand(&cmd);
|
||||
kthread_mutex_lock(&queue_lock);
|
||||
if ( queue_is_paused )
|
||||
{
|
||||
queue_is_paused = false;
|
||||
exit_after_pause = true;
|
||||
kthread_cond_signal(&queue_resume);
|
||||
}
|
||||
else
|
||||
{
|
||||
TextBufferCmd cmd;
|
||||
cmd.type = TEXTBUFCMD_EXIT;
|
||||
kthread_mutex_unlock(&queue_lock);
|
||||
IssueCommand(&cmd);
|
||||
kthread_mutex_lock(&queue_lock);
|
||||
}
|
||||
while ( queue_thread )
|
||||
kthread_cond_wait(&queue_exit, &queue_lock);
|
||||
kthread_mutex_unlock(&queue_lock);
|
||||
|
@ -163,12 +174,12 @@ LFBTextBuffer::~LFBTextBuffer()
|
|||
delete[] queue;
|
||||
}
|
||||
|
||||
size_t LFBTextBuffer::Width() const
|
||||
size_t LFBTextBuffer::Width()
|
||||
{
|
||||
return columns;
|
||||
}
|
||||
|
||||
size_t LFBTextBuffer::Height() const
|
||||
size_t LFBTextBuffer::Height()
|
||||
{
|
||||
return rows;
|
||||
}
|
||||
|
@ -363,16 +374,17 @@ void LFBTextBuffer::IssueCommand(TextBufferCmd* cmd)
|
|||
queue[(queue_offset + queue_used++) % queue_length] = *cmd;
|
||||
}
|
||||
|
||||
void LFBTextBuffer::StopRendering()
|
||||
bool LFBTextBuffer::StopRendering()
|
||||
{
|
||||
if ( !queue_thread || emergency_state )
|
||||
return;
|
||||
return false;
|
||||
TextBufferCmd cmd;
|
||||
cmd.type = TEXTBUFCMD_PAUSE;
|
||||
IssueCommand(&cmd);
|
||||
ScopedLock lock(&queue_lock);
|
||||
while ( !queue_is_paused )
|
||||
kthread_cond_wait(&queue_paused, &queue_lock);
|
||||
return true;
|
||||
}
|
||||
|
||||
void LFBTextBuffer::ResumeRendering()
|
||||
|
@ -380,17 +392,20 @@ void LFBTextBuffer::ResumeRendering()
|
|||
if ( !queue_thread || emergency_state )
|
||||
return;
|
||||
ScopedLock lock(&queue_lock);
|
||||
if ( !queue_is_paused )
|
||||
return;
|
||||
queue_is_paused = false;
|
||||
kthread_cond_signal(&queue_resume);
|
||||
}
|
||||
|
||||
TextChar LFBTextBuffer::GetChar(TextPos pos) const
|
||||
TextChar LFBTextBuffer::GetChar(TextPos pos)
|
||||
{
|
||||
if ( UsablePosition(pos) )
|
||||
{
|
||||
((LFBTextBuffer*) this)->StopRendering();
|
||||
bool was_rendering = StopRendering();
|
||||
TextChar ret = chars[pos.y * columns + pos.x];
|
||||
((LFBTextBuffer*) this)->ResumeRendering();
|
||||
if ( was_rendering )
|
||||
ResumeRendering();
|
||||
return ret;
|
||||
}
|
||||
return {0, 0, 0};
|
||||
|
@ -408,11 +423,12 @@ void LFBTextBuffer::SetChar(TextPos pos, TextChar c)
|
|||
IssueCommand(&cmd);
|
||||
}
|
||||
|
||||
bool LFBTextBuffer::GetCursorEnabled() const
|
||||
bool LFBTextBuffer::GetCursorEnabled()
|
||||
{
|
||||
((LFBTextBuffer*) this)->StopRendering();
|
||||
bool was_rendering = StopRendering();
|
||||
bool ret = cursorenabled;
|
||||
((LFBTextBuffer*) this)->ResumeRendering();
|
||||
if ( was_rendering )
|
||||
ResumeRendering();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -424,11 +440,12 @@ void LFBTextBuffer::SetCursorEnabled(bool enablecursor)
|
|||
IssueCommand(&cmd);
|
||||
}
|
||||
|
||||
TextPos LFBTextBuffer::GetCursorPos() const
|
||||
TextPos LFBTextBuffer::GetCursorPos()
|
||||
{
|
||||
((LFBTextBuffer*) this)->StopRendering();
|
||||
bool was_rendering = StopRendering();
|
||||
TextPos ret = cursorpos;
|
||||
((LFBTextBuffer*) this)->ResumeRendering();
|
||||
if ( was_rendering )
|
||||
ResumeRendering();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -675,6 +692,13 @@ void LFBTextBuffer::RenderThread()
|
|||
while ( queue_is_paused )
|
||||
kthread_cond_wait(&queue_resume, &queue_lock);
|
||||
pause_requested = false;
|
||||
if ( exit_after_pause )
|
||||
{
|
||||
queue_thread = false;
|
||||
kthread_cond_signal(&queue_exit);
|
||||
kthread_mutex_unlock(&queue_lock);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -761,4 +785,20 @@ void LFBTextBuffer::EmergencyReset()
|
|||
SetCursorPos(TextPos{0, 0});
|
||||
}
|
||||
|
||||
void LFBTextBuffer::Resume()
|
||||
{
|
||||
if ( need_clear )
|
||||
{
|
||||
for ( size_t y = 0; y < pixelsy; y++ )
|
||||
memset(lfb + scansize * y, 0, bytes_per_pixel * pixelsx);
|
||||
need_clear = false;
|
||||
}
|
||||
ResumeRendering();
|
||||
}
|
||||
|
||||
void LFBTextBuffer::Pause()
|
||||
{
|
||||
StopRendering();
|
||||
}
|
||||
|
||||
} // namespace Sortix
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 2013, 2014, 2015 Jonas 'Sortie' Termansen.
|
||||
* Copyright (c) 2012, 2013, 2014, 2015, 2016 Jonas 'Sortie' Termansen.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -64,22 +64,24 @@ private:
|
|||
|
||||
public:
|
||||
virtual ~LFBTextBuffer();
|
||||
virtual size_t Width() const;
|
||||
virtual size_t Height() const;
|
||||
virtual TextChar GetChar(TextPos pos) const;
|
||||
virtual size_t Width();
|
||||
virtual size_t Height();
|
||||
virtual TextChar GetChar(TextPos pos);
|
||||
virtual void SetChar(TextPos pos, TextChar c);
|
||||
virtual void Scroll(ssize_t off, TextChar fillwith);
|
||||
virtual void Move(TextPos to, TextPos from, size_t numchars);
|
||||
virtual void Fill(TextPos from, TextPos to, TextChar fillwith);
|
||||
virtual bool GetCursorEnabled() const;
|
||||
virtual bool GetCursorEnabled();
|
||||
virtual void SetCursorEnabled(bool enablecursor);
|
||||
virtual TextPos GetCursorPos() const;
|
||||
virtual TextPos GetCursorPos();
|
||||
virtual void SetCursorPos(TextPos newcursorpos);
|
||||
virtual void SpawnThreads();
|
||||
virtual void Invalidate();
|
||||
virtual bool EmergencyIsImpaired();
|
||||
virtual bool EmergencyRecoup();
|
||||
virtual void EmergencyReset();
|
||||
virtual void Resume();
|
||||
virtual void Pause();
|
||||
|
||||
public:
|
||||
virtual void RenderThread();
|
||||
|
@ -97,7 +99,7 @@ private:
|
|||
void DoMove(TextPos to, TextPos from, size_t numchars);
|
||||
void DoFill(TextPos from, TextPos to, TextChar fillwith);
|
||||
void IssueCommand(TextBufferCmd* cmd);
|
||||
void StopRendering();
|
||||
bool StopRendering();
|
||||
void ResumeRendering();
|
||||
bool IsCommandIdempotent(const TextBufferCmd* cmd) const;
|
||||
void ExecuteCommand(TextBufferCmd* cmd,
|
||||
|
@ -138,6 +140,8 @@ private:
|
|||
TextPos cursorpos;
|
||||
bool emergency_state;
|
||||
bool invalidated;
|
||||
bool need_clear;
|
||||
bool exit_after_pause;
|
||||
size_t execute_amount;
|
||||
|
||||
};
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2011, 2012, 2013, 2014, 2015 Jonas 'Sortie' Termansen.
|
||||
* Copyright (c) 2011, 2012, 2013, 2014, 2015, 2016 Jonas 'Sortie' Termansen.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -246,5 +246,20 @@ void Center(const char* string)
|
|||
}
|
||||
}
|
||||
|
||||
void BeginReplace()
|
||||
{
|
||||
((TextTerminal*) Log::device_pointer)->BeginReplace();
|
||||
}
|
||||
|
||||
void CancelReplace()
|
||||
{
|
||||
((TextTerminal*) Log::device_pointer)->CancelReplace();
|
||||
}
|
||||
|
||||
void FinishReplace(TextBuffer* textbuf)
|
||||
{
|
||||
((TextTerminal*) Log::device_pointer)->FinishReplace(textbuf);
|
||||
}
|
||||
|
||||
} // namespace Log
|
||||
} // namespace Sortix
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 2013, 2015 Jonas 'Sortie' Termansen.
|
||||
* Copyright (c) 2012, 2013, 2015, 2016 Jonas 'Sortie' Termansen.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -94,13 +94,77 @@ void TextBufferHandle::EmergencyRelease(TextBuffer* textbuf)
|
|||
(void) textbuf;
|
||||
}
|
||||
|
||||
void TextBufferHandle::Replace(TextBuffer* newtextbuf)
|
||||
void TextBufferHandle::BeginReplace()
|
||||
{
|
||||
ScopedLock lock(&mutex);
|
||||
kthread_mutex_lock(&mutex);
|
||||
while ( 0 < numused )
|
||||
kthread_cond_wait(&unusedcond, &mutex);
|
||||
if ( textbuf )
|
||||
textbuf->Pause();
|
||||
}
|
||||
|
||||
void TextBufferHandle::CancelReplace()
|
||||
{
|
||||
if ( textbuf )
|
||||
textbuf->Resume();
|
||||
kthread_mutex_unlock(&mutex);
|
||||
}
|
||||
|
||||
void TextBufferHandle::FinishReplace(TextBuffer* newtextbuf)
|
||||
{
|
||||
// TODO: This shouldn't redraw when a graphical app is in control of the
|
||||
// screen. Might even leak information from the console.
|
||||
newtextbuf->Resume();
|
||||
if ( textbuf )
|
||||
{
|
||||
size_t src_width = textbuf->Width();
|
||||
size_t src_height = textbuf->Height();
|
||||
size_t dst_width = newtextbuf->Width();
|
||||
size_t dst_height = newtextbuf->Height();
|
||||
bool cursor_enabled = textbuf->GetCursorEnabled();
|
||||
TextPos src_cursor = textbuf->GetCursorPos();
|
||||
size_t src_y_after_cursor = src_height ? src_cursor.y + 1 : 0;
|
||||
size_t src_y_count = dst_height < src_y_after_cursor ? dst_height : src_y_after_cursor;
|
||||
size_t src_y_from = src_y_after_cursor - src_y_count;
|
||||
TextPos dst_cursor = src_cursor;
|
||||
dst_cursor.y += src_y_from;
|
||||
newtextbuf->SetCursorEnabled(false);
|
||||
for ( size_t dst_y = 0; dst_y < dst_height; dst_y++ )
|
||||
{
|
||||
// TODO: Ability to center the boot cat.
|
||||
size_t src_y = src_y_from + dst_y;
|
||||
for ( size_t dst_x = 0; dst_x < dst_width; dst_x++ )
|
||||
{
|
||||
size_t src_x = dst_x;
|
||||
TextPos src_pos{src_x, src_y};
|
||||
TextPos dst_pos{dst_x, dst_y};
|
||||
TextChar tc{0, 0, 0};
|
||||
if ( src_x < src_width && src_y < src_height )
|
||||
tc = textbuf->GetChar(src_pos);
|
||||
else if ( src_width && src_height )
|
||||
{
|
||||
TextPos templ_pos;
|
||||
templ_pos.x = src_y < src_width ? src_y : src_x- 1;
|
||||
templ_pos.y = src_y < src_height ? src_y : src_height - 1;
|
||||
tc = textbuf->GetChar(templ_pos);
|
||||
tc.c = 0;
|
||||
tc.attr = 0;
|
||||
}
|
||||
newtextbuf->SetChar(dst_pos, tc);
|
||||
if ( src_x == src_cursor.x && src_y == src_cursor.y )
|
||||
dst_cursor = dst_pos;
|
||||
}
|
||||
}
|
||||
if ( dst_width <= dst_cursor.x )
|
||||
dst_cursor.x = dst_width ? dst_cursor.x - 1 : 0;
|
||||
if ( dst_height <= dst_cursor.y )
|
||||
dst_cursor.y = dst_height ? dst_cursor.y - 1 : 0;
|
||||
newtextbuf->SetCursorPos(dst_cursor);
|
||||
newtextbuf->SetCursorEnabled(cursor_enabled);
|
||||
}
|
||||
delete textbuf;
|
||||
textbuf = newtextbuf;
|
||||
kthread_mutex_unlock(&mutex);
|
||||
}
|
||||
|
||||
} // namespace Sortix
|
||||
|
|
|
@ -133,6 +133,32 @@ bool TextTerminal::Invalidate()
|
|||
return true;
|
||||
}
|
||||
|
||||
void TextTerminal::BeginReplace()
|
||||
{
|
||||
kthread_mutex_lock(&termlock);
|
||||
textbufhandle->BeginReplace();
|
||||
}
|
||||
|
||||
void TextTerminal::CancelReplace()
|
||||
{
|
||||
textbufhandle->CancelReplace();
|
||||
kthread_mutex_unlock(&termlock);
|
||||
}
|
||||
|
||||
void TextTerminal::FinishReplace(TextBuffer* new_textbuf)
|
||||
{
|
||||
textbufhandle->FinishReplace(new_textbuf);
|
||||
TextBuffer* textbuf = textbufhandle->Acquire();
|
||||
size_t new_width = textbuf->Width();
|
||||
size_t new_height = textbuf->Height();
|
||||
textbufhandle->Release(textbuf);
|
||||
if ( new_width < column )
|
||||
column = new_width;
|
||||
if ( new_height <= line )
|
||||
line = new_height ? new_height - 1 : 0;
|
||||
kthread_mutex_unlock(&termlock);
|
||||
}
|
||||
|
||||
bool TextTerminal::EmergencyIsImpaired()
|
||||
{
|
||||
// This is during a kernel emergency where preemption has been disabled and
|
||||
|
|
|
@ -41,6 +41,9 @@ public:
|
|||
void GetCursor(size_t* column, size_t* row) const;
|
||||
bool Sync();
|
||||
bool Invalidate();
|
||||
void BeginReplace();
|
||||
void CancelReplace();
|
||||
void FinishReplace(TextBuffer* textbuf);
|
||||
bool EmergencyIsImpaired();
|
||||
bool EmergencyRecoup();
|
||||
void EmergencyReset();
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 2013, 2014, 2015 Jonas 'Sortie' Termansen.
|
||||
* Copyright (c) 2012, 2013, 2014, 2015, 2016 Jonas 'Sortie' Termansen.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -74,17 +74,17 @@ size_t VGATextBuffer::OffsetOfPos(TextPos pos) const
|
|||
return pos.y * width + pos.x;
|
||||
}
|
||||
|
||||
size_t VGATextBuffer::Width() const
|
||||
size_t VGATextBuffer::Width()
|
||||
{
|
||||
return width;
|
||||
}
|
||||
|
||||
size_t VGATextBuffer::Height() const
|
||||
size_t VGATextBuffer::Height()
|
||||
{
|
||||
return height;
|
||||
}
|
||||
|
||||
TextChar VGATextBuffer::GetChar(TextPos pos) const
|
||||
TextChar VGATextBuffer::GetChar(TextPos pos)
|
||||
{
|
||||
if ( UsablePosition(pos) )
|
||||
return chars[OffsetOfPos(pos)];
|
||||
|
@ -153,7 +153,7 @@ void VGATextBuffer::Fill(TextPos from, TextPos to, TextChar fillwith)
|
|||
}
|
||||
}
|
||||
|
||||
bool VGATextBuffer::GetCursorEnabled() const
|
||||
bool VGATextBuffer::GetCursorEnabled()
|
||||
{
|
||||
return cursorenabled;
|
||||
}
|
||||
|
@ -164,7 +164,7 @@ void VGATextBuffer::SetCursorEnabled(bool enablecursor)
|
|||
UpdateCursor();
|
||||
}
|
||||
|
||||
TextPos VGATextBuffer::GetCursorPos() const
|
||||
TextPos VGATextBuffer::GetCursorPos()
|
||||
{
|
||||
return cursorpos;
|
||||
}
|
||||
|
@ -207,4 +207,13 @@ void VGATextBuffer::EmergencyReset()
|
|||
SetCursorPos(TextPos{0, 0});
|
||||
}
|
||||
|
||||
void VGATextBuffer::Resume()
|
||||
{
|
||||
UpdateCursor();
|
||||
}
|
||||
|
||||
void VGATextBuffer::Pause()
|
||||
{
|
||||
}
|
||||
|
||||
} // namespace Sortix
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 2013, 2014, 2015 Jonas 'Sortie' Termansen.
|
||||
* Copyright (c) 2012, 2013, 2014, 2015, 2016 Jonas 'Sortie' Termansen.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -29,22 +29,24 @@ class VGATextBuffer : public TextBuffer
|
|||
public:
|
||||
VGATextBuffer(uint16_t* vga, TextChar* chars, size_t width, size_t height);
|
||||
virtual ~VGATextBuffer();
|
||||
virtual size_t Width() const;
|
||||
virtual size_t Height() const;
|
||||
virtual TextChar GetChar(TextPos pos) const;
|
||||
virtual size_t Width();
|
||||
virtual size_t Height();
|
||||
virtual TextChar GetChar(TextPos pos);
|
||||
virtual void SetChar(TextPos pos, TextChar c);
|
||||
virtual void Scroll(ssize_t off, TextChar fillwith);
|
||||
virtual void Move(TextPos to, TextPos from, size_t numchars);
|
||||
virtual void Fill(TextPos from, TextPos to, TextChar fillwith);
|
||||
virtual bool GetCursorEnabled() const;
|
||||
virtual bool GetCursorEnabled();
|
||||
virtual void SetCursorEnabled(bool enablecursor);
|
||||
virtual TextPos GetCursorPos() const;
|
||||
virtual TextPos GetCursorPos();
|
||||
virtual void SetCursorPos(TextPos cursorpos);
|
||||
virtual void SpawnThreads();
|
||||
virtual void Invalidate();
|
||||
virtual bool EmergencyIsImpaired();
|
||||
virtual bool EmergencyRecoup();
|
||||
virtual void EmergencyReset();
|
||||
virtual void Resume();
|
||||
virtual void Pause();
|
||||
|
||||
private:
|
||||
bool UsablePosition(TextPos pos) const;
|
||||
|
|
127
kernel/video.cpp
127
kernel/video.cpp
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 2014, 2015 Jonas 'Sortie' Termansen.
|
||||
* Copyright (c) 2012, 2014, 2015, 2016 Jonas 'Sortie' Termansen.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -33,10 +33,10 @@
|
|||
namespace Sortix {
|
||||
namespace Video {
|
||||
|
||||
const uint64_t ONE_AND_ONLY_DEVICE = 0;
|
||||
const uint64_t ONE_AND_ONLY_CONNECTOR = 0;
|
||||
static const uint64_t CONSOLE_DEVICE = 0;
|
||||
static const uint64_t CONSOLE_CONNECTOR = 0;
|
||||
|
||||
kthread_mutex_t video_lock = KTHREAD_MUTEX_INITIALIZER;
|
||||
static kthread_mutex_t video_lock = KTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
struct DeviceEntry
|
||||
{
|
||||
|
@ -44,9 +44,9 @@ struct DeviceEntry
|
|||
VideoDevice* device;
|
||||
};
|
||||
|
||||
size_t num_devices = 0;
|
||||
size_t devices_length = 0;
|
||||
DeviceEntry* devices = NULL;
|
||||
static size_t num_devices = 0;
|
||||
static size_t devices_length = 0;
|
||||
static DeviceEntry* devices = NULL;
|
||||
|
||||
bool RegisterDevice(const char* name, VideoDevice* device)
|
||||
{
|
||||
|
@ -73,9 +73,89 @@ bool RegisterDevice(const char* name, VideoDevice* device)
|
|||
size_t index = num_devices++;
|
||||
devices[index].name = drivername;
|
||||
devices[index].device = device;
|
||||
device->device_index = index;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool SetVideoMode(VideoDevice* device,
|
||||
uint64_t connector,
|
||||
struct dispmsg_crtc_mode mode)
|
||||
{
|
||||
uint64_t device_index = device->device_index;
|
||||
TextBuffer* textbuf = NULL;
|
||||
if ( device_index == CONSOLE_DEVICE && connector == CONSOLE_CONNECTOR )
|
||||
{
|
||||
if ( !(textbuf = device->CreateTextBuffer(connector, mode)) )
|
||||
return false;
|
||||
Log::BeginReplace();
|
||||
}
|
||||
if ( !device->SwitchMode(connector, mode) )
|
||||
{
|
||||
if ( textbuf )
|
||||
{
|
||||
Log::CancelReplace();
|
||||
delete textbuf;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if ( textbuf )
|
||||
{
|
||||
Log::FinishReplace(textbuf);
|
||||
Log::fallback_framebuffer = NULL;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ConfigureDevice(VideoDevice* device)
|
||||
{
|
||||
bool success = true;
|
||||
ScopedLock lock(&video_lock);
|
||||
uint64_t connectors_count = device->GetConnectorCount();
|
||||
for ( uint64_t connector = 0; connector < connectors_count; connector++ )
|
||||
{
|
||||
struct dispmsg_crtc_mode mode;
|
||||
if ( !device->GetDefaultMode(connector, &mode) ||
|
||||
!SetVideoMode(device, connector, mode) )
|
||||
success = false;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
bool ResizeDisplay(uint64_t device_index, uint64_t connector, uint32_t xres,
|
||||
uint32_t yres, uint32_t bpp)
|
||||
{
|
||||
ScopedLock lock(&video_lock);
|
||||
|
||||
if ( num_devices <= device_index )
|
||||
return errno = ENODEV, false;
|
||||
|
||||
DeviceEntry* device_entry = &devices[device_index];
|
||||
VideoDevice* device = device_entry->device;
|
||||
|
||||
// TODO: xres/yres/bpp == 0 means unchanged, so get current mode.
|
||||
if ( xres == 0 || yres == 0 || bpp == 0 )
|
||||
return true;
|
||||
struct dispmsg_crtc_mode mode;
|
||||
memset(&mode, 0, sizeof(0));
|
||||
mode.driver_index = 0;
|
||||
mode.magic = 0;
|
||||
mode.control = DISPMSG_CONTROL_VALID;
|
||||
mode.fb_format = bpp;
|
||||
mode.view_xres = xres;
|
||||
mode.view_yres = yres;
|
||||
mode.fb_location = 0;
|
||||
mode.pitch = xres * (bpp + 7) / 8;
|
||||
mode.surf_off_x = 0;
|
||||
mode.surf_off_y = 0;
|
||||
mode.start_x = 0;
|
||||
mode.start_y = 0;
|
||||
mode.end_x = 0;
|
||||
mode.end_y = 0;
|
||||
mode.desktop_height = yres;
|
||||
|
||||
return SetVideoMode(device, connector, mode);
|
||||
}
|
||||
|
||||
__attribute__((unused))
|
||||
static bool TransmitString(struct dispmsg_string* dest, const char* str)
|
||||
{
|
||||
|
@ -246,19 +326,13 @@ static int SetCrtcMode(void* ptr, size_t size)
|
|||
{
|
||||
DeviceEntry* device_entry = &devices[msg.device];
|
||||
VideoDevice* device = device_entry->device;
|
||||
if ( !device->SwitchMode(msg.connector, msg.mode) )
|
||||
|
||||
if ( !SetVideoMode(device, msg.connector, msg.mode) )
|
||||
return -1;
|
||||
// TODO: This could potentially fail.
|
||||
if ( msg.device == ONE_AND_ONLY_DEVICE &&
|
||||
msg.connector == ONE_AND_ONLY_CONNECTOR )
|
||||
{
|
||||
Log::fallback_framebuffer = NULL;
|
||||
Log::device_textbufhandle->Replace(device->CreateTextBuffer(msg.connector));
|
||||
}
|
||||
}
|
||||
else if ( Log::fallback_framebuffer &&
|
||||
msg.device == ONE_AND_ONLY_DEVICE &&
|
||||
msg.connector == ONE_AND_ONLY_CONNECTOR )
|
||||
msg.device == CONSOLE_DEVICE &&
|
||||
msg.connector == CONSOLE_CONNECTOR )
|
||||
{
|
||||
struct dispmsg_crtc_mode fallback_mode = GetLogFallbackMode();
|
||||
if ( memcmp(&msg.mode, &fallback_mode, sizeof(msg.mode)) != 0 )
|
||||
|
@ -286,8 +360,8 @@ static int GetCrtcMode(void* ptr, size_t size)
|
|||
|
||||
struct dispmsg_crtc_mode mode;
|
||||
if ( Log::fallback_framebuffer &&
|
||||
msg.device == ONE_AND_ONLY_DEVICE &&
|
||||
msg.connector == ONE_AND_ONLY_CONNECTOR )
|
||||
msg.device == CONSOLE_DEVICE &&
|
||||
msg.connector == CONSOLE_CONNECTOR )
|
||||
{
|
||||
mode = GetLogFallbackMode();
|
||||
}
|
||||
|
@ -295,10 +369,7 @@ static int GetCrtcMode(void* ptr, size_t size)
|
|||
{
|
||||
DeviceEntry* device_entry = &devices[msg.device];
|
||||
VideoDevice* device = device_entry->device;
|
||||
// TODO: There is no real way to detect failure here.
|
||||
errno = 0;
|
||||
mode = device->GetCurrentMode(msg.connector);
|
||||
if ( !(mode.control & DISPMSG_CONTROL_VALID) && errno != 0 )
|
||||
if ( !device->GetCurrentMode(msg.connector, &mode) )
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
|
@ -335,8 +406,8 @@ static int GetCrtcModes(void* ptr, size_t size)
|
|||
return -1;
|
||||
}
|
||||
else if ( Log::fallback_framebuffer &&
|
||||
msg.device == ONE_AND_ONLY_DEVICE &&
|
||||
msg.connector == ONE_AND_ONLY_CONNECTOR )
|
||||
msg.device == CONSOLE_DEVICE &&
|
||||
msg.connector == CONSOLE_CONNECTOR )
|
||||
{
|
||||
if ( !(modes = new struct dispmsg_crtc_mode[1]) )
|
||||
return -1;
|
||||
|
@ -384,7 +455,7 @@ static int GetMemorySize(void* ptr, size_t size)
|
|||
ScopedLock lock(&video_lock);
|
||||
|
||||
if ( Log::fallback_framebuffer &&
|
||||
msg.device == ONE_AND_ONLY_DEVICE )
|
||||
msg.device == CONSOLE_DEVICE )
|
||||
{
|
||||
msg.memory_size = Log::fallback_framebuffer_width *
|
||||
Log::fallback_framebuffer_height *
|
||||
|
@ -423,7 +494,7 @@ static int WriteMemory(void* ptr, size_t size)
|
|||
ScopedLock lock(&video_lock);
|
||||
|
||||
if ( Log::fallback_framebuffer &&
|
||||
msg.device == ONE_AND_ONLY_DEVICE )
|
||||
msg.device == CONSOLE_DEVICE )
|
||||
{
|
||||
size_t ideal_pitch = Log::fallback_framebuffer_width *
|
||||
Log::fallback_framebuffer_bpp / 8;
|
||||
|
@ -493,7 +564,7 @@ static int ReadMemory(void* ptr, size_t size)
|
|||
ScopedLock lock(&video_lock);
|
||||
|
||||
if ( Log::fallback_framebuffer &&
|
||||
msg.device == ONE_AND_ONLY_DEVICE )
|
||||
msg.device == CONSOLE_DEVICE )
|
||||
{
|
||||
size_t ideal_pitch = Log::fallback_framebuffer_width *
|
||||
Log::fallback_framebuffer_bpp / 8;
|
||||
|
|
|
@ -544,10 +544,28 @@ int main(void)
|
|||
(dgdn.device = display.device, true) &&
|
||||
(dispmsg_issue(&dgdn, sizeof(dgdn)) == 0 || errno != ENODEV) )
|
||||
{
|
||||
struct dispmsg_get_crtc_mode get_mode;
|
||||
memset(&get_mode, 0, sizeof(get_mode));
|
||||
get_mode.msgid = DISPMSG_GET_CRTC_MODE;
|
||||
get_mode.device = 0;
|
||||
get_mode.connector = 0;
|
||||
bool good = false;
|
||||
if ( dispmsg_issue(&get_mode, sizeof(get_mode)) == 0 )
|
||||
{
|
||||
good = (get_mode.mode.control & DISPMSG_CONTROL_VALID) &&
|
||||
(get_mode.mode.control & DISPMSG_CONTROL_GOOD_DEFAULT);
|
||||
if ( get_mode.mode.control & DISPMSG_CONTROL_VM_AUTO_SCALE )
|
||||
{
|
||||
text("The display resolution will automatically change to "
|
||||
"match the size of the virtual machine window.\n\n");
|
||||
good = true;
|
||||
}
|
||||
}
|
||||
const char* def = good ? "no" : "yes";
|
||||
while ( true )
|
||||
{
|
||||
prompt(input, sizeof(input),
|
||||
"Select a default display resolution? (yes/no)", "yes");
|
||||
"Select a default display resolution? (yes/no)", def);
|
||||
if ( strcasecmp(input, "no") && strcasecmp(input, "yes") )
|
||||
continue;
|
||||
bool was_no = strcasecmp(input, "no") == 0;
|
||||
|
@ -556,10 +574,6 @@ int main(void)
|
|||
break;
|
||||
if ( execute((const char*[]) { "chvideomode", NULL }, "f") != 0 )
|
||||
continue;
|
||||
struct dispmsg_get_crtc_mode get_mode;
|
||||
get_mode.msgid = DISPMSG_GET_CRTC_MODE;
|
||||
get_mode.device = 0;
|
||||
get_mode.connector = 0;
|
||||
if ( dispmsg_issue(&get_mode, sizeof(get_mode)) < 0 )
|
||||
break;
|
||||
if ( !(get_mode.mode.control & DISPMSG_CONTROL_VALID) )
|
||||
|
|
|
@ -439,10 +439,28 @@ int main(void)
|
|||
(dgdn.device = display.device, true) &&
|
||||
(dispmsg_issue(&dgdn, sizeof(dgdn)) == 0 || errno != ENODEV) )
|
||||
{
|
||||
struct dispmsg_get_crtc_mode get_mode;
|
||||
memset(&get_mode, 0, sizeof(get_mode));
|
||||
get_mode.msgid = DISPMSG_GET_CRTC_MODE;
|
||||
get_mode.device = 0;
|
||||
get_mode.connector = 0;
|
||||
bool good = false;
|
||||
if ( dispmsg_issue(&get_mode, sizeof(get_mode)) == 0 )
|
||||
{
|
||||
good = (get_mode.mode.control & DISPMSG_CONTROL_VALID) &&
|
||||
(get_mode.mode.control & DISPMSG_CONTROL_GOOD_DEFAULT);
|
||||
if ( get_mode.mode.control & DISPMSG_CONTROL_VM_AUTO_SCALE )
|
||||
{
|
||||
text("The display resolution will automatically change to "
|
||||
"match the size of the virtual machine window.\n\n");
|
||||
good = true;
|
||||
}
|
||||
}
|
||||
const char* def = good ? "no" : "yes";
|
||||
while ( true )
|
||||
{
|
||||
prompt(input, sizeof(input),
|
||||
"Select display resolution? (yes/no)", "yes");
|
||||
"Select display resolution? (yes/no)", def);
|
||||
if ( strcasecmp(input, "no") && strcasecmp(input, "yes") )
|
||||
continue;
|
||||
if ( strcasecmp(input, "no") == 0 )
|
||||
|
|
Loading…
Reference in a new issue