diff options
author | Tom <tomut@yahoo.com> | 2021-07-03 20:36:16 -0600 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-07-04 23:59:17 +0200 |
commit | 6e792553f26a0fb0f4d763d9befe4f79716a81d0 (patch) | |
tree | 88c806936e2e1cb94d58618dec399208330837fc | |
parent | fdae117600925e17dfbab54961dd68ddcfe27dc2 (diff) | |
download | serenity-6e792553f26a0fb0f4d763d9befe4f79716a81d0.zip |
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.
-rw-r--r-- | Kernel/API/FB.h | 10 | ||||
-rw-r--r-- | Userland/Libraries/LibC/sys/ioctl_numbers.h | 7 | ||||
-rw-r--r-- | Userland/Services/WindowServer/Compositor.cpp | 4 | ||||
-rw-r--r-- | Userland/Services/WindowServer/Screen.cpp | 22 | ||||
-rw-r--r-- | Userland/Services/WindowServer/Screen.h | 10 |
5 files changed, 47 insertions, 6 deletions
diff --git a/Kernel/API/FB.h b/Kernel/API/FB.h index 97cd287f4d..7c68f04634 100644 --- a/Kernel/API/FB.h +++ b/Kernel/API/FB.h @@ -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); diff --git a/Userland/Libraries/LibC/sys/ioctl_numbers.h b/Userland/Libraries/LibC/sys/ioctl_numbers.h index c22f884ff6..62f0b2010e 100644 --- a/Userland/Libraries/LibC/sys/ioctl_numbers.h +++ b/Userland/Libraries/LibC/sys/ioctl_numbers.h @@ -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 diff --git a/Userland/Services/WindowServer/Compositor.cpp b/Userland/Services/WindowServer/Compositor.cpp index c77373998e..dfc957dee1 100644 --- a/Userland/Services/WindowServer/Compositor.cpp +++ b/Userland/Services/WindowServer/Compositor.cpp @@ -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); diff --git a/Userland/Services/WindowServer/Screen.cpp b/Userland/Services/WindowServer/Screen.cpp index 0214717e1a..12703f8889 100644 --- a/Userland/Services/WindowServer/Screen.cpp +++ b/Userland/Services/WindowServer/Screen.cpp @@ -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); diff --git a/Userland/Services/WindowServer/Screen.h b/Userland/Services/WindowServer/Screen.h index 4233cc78f1..159e830584 100644 --- a/Userland/Services/WindowServer/Screen.h +++ b/Userland/Services/WindowServer/Screen.h @@ -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)); } } |