WindowServer+LibGfx: Improve non-standard bitmap pitch handling

Up until now, the only way to create a Bitmap with a non-standard
pitch was to use the wrapper; This was unsuitable for back and temp
buffers within WindowServer.

This commit adds another optional parameter for specifying the pitch
in a backwards-compatible way. The change in WindowServer will likely
fix most cases of screen misalignment when running on baremetal.
This commit is contained in:
sdomi 2024-09-21 03:10:09 +02:00 committed by Tim Schumacher
parent 466838d0a7
commit c8a068496a
3 changed files with 11 additions and 10 deletions

View file

@ -64,9 +64,9 @@ static bool size_would_overflow(BitmapFormat format, IntSize size, int scale_fac
return Checked<size_t>::multiplication_would_overflow(pitch, size.height() * scale_factor);
}
ErrorOr<NonnullRefPtr<Bitmap>> Bitmap::create(BitmapFormat format, IntSize size, int scale_factor)
ErrorOr<NonnullRefPtr<Bitmap>> Bitmap::create(BitmapFormat format, IntSize size, int scale_factor, Optional<size_t> pitch)
{
auto backing_store = TRY(Bitmap::allocate_backing_store(format, size, scale_factor));
auto backing_store = TRY(Bitmap::allocate_backing_store(format, size, scale_factor, pitch));
return AK::adopt_nonnull_ref_or_enomem(new (nothrow) Bitmap(format, size, scale_factor, backing_store));
}
@ -583,7 +583,7 @@ Gfx::ShareableBitmap Bitmap::to_shareable_bitmap() const
return Gfx::ShareableBitmap { bitmap_or_error.release_value_but_fixme_should_propagate_errors(), Gfx::ShareableBitmap::ConstructWithKnownGoodBitmap };
}
ErrorOr<BackingStore> Bitmap::allocate_backing_store(BitmapFormat format, IntSize size, int scale_factor)
ErrorOr<BackingStore> Bitmap::allocate_backing_store(BitmapFormat format, IntSize size, int scale_factor, Optional<size_t> pitch)
{
if (size.is_empty())
return Error::from_string_literal("Gfx::Bitmap backing store size is empty");
@ -591,13 +591,14 @@ ErrorOr<BackingStore> Bitmap::allocate_backing_store(BitmapFormat format, IntSiz
if (size_would_overflow(format, size, scale_factor))
return Error::from_string_literal("Gfx::Bitmap backing store size overflow");
auto const pitch = minimum_pitch(size.width() * scale_factor, format);
auto const data_size_in_bytes = size_in_bytes(pitch, size.height() * scale_factor);
if (!pitch.has_value())
pitch = minimum_pitch(size.width() * scale_factor, format);
auto const data_size_in_bytes = size_in_bytes(pitch.value(), size.height() * scale_factor);
void* data = kcalloc(1, data_size_in_bytes);
if (data == nullptr)
return Error::from_errno(errno);
return BackingStore { data, pitch, data_size_in_bytes };
return BackingStore { data, pitch.value(), data_size_in_bytes };
}
bool Bitmap::visually_equals(Bitmap const& other) const

View file

@ -97,7 +97,7 @@ enum class RotationDirection {
class Bitmap : public RefCounted<Bitmap> {
public:
[[nodiscard]] static ErrorOr<NonnullRefPtr<Bitmap>> create(BitmapFormat, IntSize, int intrinsic_scale = 1);
[[nodiscard]] static ErrorOr<NonnullRefPtr<Bitmap>> create(BitmapFormat, IntSize, int intrinsic_scale = 1, Optional<size_t> pitch = {});
[[nodiscard]] static ErrorOr<NonnullRefPtr<Bitmap>> create_shareable(BitmapFormat, IntSize, int intrinsic_scale = 1);
[[nodiscard]] static ErrorOr<NonnullRefPtr<Bitmap>> create_wrapper(BitmapFormat, IntSize, int intrinsic_scale, size_t pitch, void*, Function<void()>&& destruction_callback = {});
[[nodiscard]] static ErrorOr<NonnullRefPtr<Bitmap>> load_from_file(StringView path, int scale_factor = 1, Optional<IntSize> ideal_size = {});
@ -240,7 +240,7 @@ private:
Bitmap(BitmapFormat, IntSize, int, size_t pitch, void*, Function<void()>&& destruction_callback);
Bitmap(BitmapFormat, Core::AnonymousBuffer, IntSize, int);
static ErrorOr<BackingStore> allocate_backing_store(BitmapFormat format, IntSize size, int scale_factor);
static ErrorOr<BackingStore> allocate_backing_store(BitmapFormat format, IntSize size, int scale_factor, Optional<size_t> pitch = {});
IntSize m_size;
int m_scale;

View file

@ -116,12 +116,12 @@ void CompositorScreenData::init_bitmaps(Compositor& compositor, Screen& screen)
if (m_screen_can_set_buffer)
m_back_bitmap = Gfx::Bitmap::create_wrapper(Gfx::BitmapFormat::BGRx8888, size, screen.scale_factor(), screen.pitch(), screen.scanline(1, 0)).release_value_but_fixme_should_propagate_errors();
else
m_back_bitmap = Gfx::Bitmap::create(Gfx::BitmapFormat::BGRx8888, size, screen.scale_factor()).release_value_but_fixme_should_propagate_errors();
m_back_bitmap = Gfx::Bitmap::create(Gfx::BitmapFormat::BGRx8888, size, screen.scale_factor(), screen.pitch()).release_value_but_fixme_should_propagate_errors();
m_back_painter = make<Gfx::Painter>(*m_back_bitmap);
m_back_painter->translate(-screen.rect().location());
m_temp_bitmap = nullptr;
m_temp_bitmap = Gfx::Bitmap::create(Gfx::BitmapFormat::BGRx8888, size, screen.scale_factor()).release_value_but_fixme_should_propagate_errors();
m_temp_bitmap = Gfx::Bitmap::create(Gfx::BitmapFormat::BGRx8888, size, screen.scale_factor(), screen.pitch()).release_value_but_fixme_should_propagate_errors();
m_temp_painter = make<Gfx::Painter>(*m_temp_bitmap);
m_temp_painter->translate(-screen.rect().location());