WindowServer: Query driver for framebuffer offset

Depending on the driver, the second buffer may not be located right
after the first, e.g. it may be page aligned. This removes this
assumption and queries the driver for the appropriate offset.
This commit is contained in:
Tom 2021-07-03 20:36:16 -06:00 committed by Andreas Kling
parent fdae117600
commit 6e792553f2
5 changed files with 47 additions and 6 deletions

View file

@ -28,6 +28,16 @@ ALWAYS_INLINE int fb_set_resolution(int fd, FBResolution* info)
return ioctl(fd, FB_IOCTL_SET_RESOLUTION, info);
}
ALWAYS_INLINE int fb_get_buffer_offset(int fd, int index, unsigned* offset)
{
FBBufferOffset fb_buffer_offset;
fb_buffer_offset.buffer_index = index;
int result = ioctl(fd, FB_IOCTL_GET_BUFFER_OFFSET, &fb_buffer_offset);
if (result == 0)
*offset = fb_buffer_offset.offset;
return result;
}
ALWAYS_INLINE int fb_get_buffer(int fd, int* index)
{
return ioctl(fd, FB_IOCTL_GET_BUFFER, index);

View file

@ -30,6 +30,11 @@ struct FBRect {
unsigned height;
};
struct FBBufferOffset {
int buffer_index;
unsigned offset;
};
struct FBFlushRects {
int buffer_index;
unsigned count;
@ -55,6 +60,7 @@ enum IOCtlNumber {
FB_IOCTL_GET_RESOLUTION,
FB_IOCTL_SET_RESOLUTION,
FB_IOCTL_GET_BUFFER,
FB_IOCTL_GET_BUFFER_OFFSET,
FB_IOCTL_SET_BUFFER,
FB_IOCTL_FLUSH_BUFFERS,
SIOCSIFADDR,
@ -88,6 +94,7 @@ enum IOCtlNumber {
#define FB_IOCTL_GET_RESOLUTION FB_IOCTL_GET_RESOLUTION
#define FB_IOCTL_SET_RESOLUTION FB_IOCTL_SET_RESOLUTION
#define FB_IOCTL_GET_BUFFER FB_IOCTL_GET_BUFFER
#define FB_IOCTL_GET_BUFFER_OFFSET FB_IOCTL_GET_BUFFER_OFFSET
#define FB_IOCTL_SET_BUFFER FB_IOCTL_SET_BUFFER
#define FB_IOCTL_FLUSH_BUFFERS FB_IOCTL_FLUSH_BUFFERS
#define SIOCSIFADDR SIOCSIFADDR

View file

@ -87,12 +87,12 @@ void Compositor::ScreenData::init_bitmaps(Compositor& compositor, Screen& screen
auto size = screen.size();
m_front_bitmap = Gfx::Bitmap::create_wrapper(Gfx::BitmapFormat::BGRx8888, size, screen.scale_factor(), screen.pitch(), screen.scanline(0));
m_front_bitmap = Gfx::Bitmap::create_wrapper(Gfx::BitmapFormat::BGRx8888, size, screen.scale_factor(), screen.pitch(), screen.scanline(0, 0));
m_front_painter = make<Gfx::Painter>(*m_front_bitmap);
m_front_painter->translate(-screen.rect().location());
if (m_screen_can_set_buffer)
m_back_bitmap = Gfx::Bitmap::create_wrapper(Gfx::BitmapFormat::BGRx8888, size, screen.scale_factor(), screen.pitch(), screen.scanline(screen.physical_height()));
m_back_bitmap = Gfx::Bitmap::create_wrapper(Gfx::BitmapFormat::BGRx8888, size, screen.scale_factor(), screen.pitch(), screen.scanline(1, 0));
else
m_back_bitmap = Gfx::Bitmap::create(Gfx::BitmapFormat::BGRx8888, size, screen.scale_factor());
m_back_painter = make<Gfx::Painter>(*m_back_bitmap);

View file

@ -225,6 +225,19 @@ bool Screen::set_resolution(bool initial)
m_framebuffer = (Gfx::RGBA32*)mmap(nullptr, m_size_in_bytes, PROT_READ | PROT_WRITE, MAP_SHARED, m_framebuffer_fd, 0);
VERIFY(m_framebuffer && m_framebuffer != (void*)-1);
if (m_can_set_buffer) {
unsigned buffer_offset = 0;
rc = fb_get_buffer_offset(m_framebuffer_fd, 1, &buffer_offset);
if (rc == 0) {
m_back_buffer_offset = buffer_offset;
} else {
// fall back to assuming the second buffer starts right after the last line of the first
m_back_buffer_offset = physical_resolution.pitch * physical_resolution.height;
}
} else {
m_back_buffer_offset = 0;
}
}
m_info.resolution = { physical_resolution.width, physical_resolution.height };
@ -255,6 +268,15 @@ void Screen::set_buffer(int index)
VERIFY(rc == 0);
}
size_t Screen::buffer_offset(int index) const
{
if (index == 0)
return 0;
if (index == 1)
return m_back_buffer_offset;
VERIFY_NOT_REACHED();
}
void ScreenInput::set_acceleration_factor(double factor)
{
VERIFY(factor >= mouse_accel_min && factor <= mouse_accel_max);

View file

@ -147,6 +147,7 @@ public:
bool can_set_buffer() { return m_can_set_buffer; }
void set_buffer(int index);
size_t buffer_offset(int index) const;
int physical_width() const { return width() * scale_factor(); }
int physical_height() const { return height() * scale_factor(); }
@ -156,7 +157,7 @@ public:
int height() const { return m_virtual_rect.height(); }
int scale_factor() const { return m_info.scale_factor; }
Gfx::RGBA32* scanline(int y);
Gfx::RGBA32* scanline(int buffer_index, int y);
Gfx::IntSize physical_size() const { return { physical_width(), physical_height() }; }
@ -190,7 +191,8 @@ private:
static Vector<int, default_scale_factors_in_use_count> s_scale_factors_in_use;
size_t m_index { 0 };
size_t m_size_in_bytes;
size_t m_size_in_bytes { 0 };
size_t m_back_buffer_offset { 0 };
Gfx::RGBA32* m_framebuffer { nullptr };
bool m_can_set_buffer { false };
@ -204,9 +206,9 @@ private:
ScreenLayout::Screen& m_info;
};
inline Gfx::RGBA32* Screen::scanline(int y)
inline Gfx::RGBA32* Screen::scanline(int buffer_index, int y)
{
return reinterpret_cast<Gfx::RGBA32*>(((u8*)m_framebuffer) + (y * m_pitch));
return reinterpret_cast<Gfx::RGBA32*>(((u8*)m_framebuffer) + buffer_offset(buffer_index) + (y * m_pitch));
}
}