diff --git a/Userland/Libraries/LibGUI/Window.cpp b/Userland/Libraries/LibGUI/Window.cpp index c874d74c42..78fe6a3157 100644 --- a/Userland/Libraries/LibGUI/Window.cpp +++ b/Userland/Libraries/LibGUI/Window.cpp @@ -728,7 +728,7 @@ OwnPtr Window::create_backing_store(const Gfx::IntSize& size return {}; } - auto bitmap = Gfx::Bitmap::create_with_anon_fd(format, anon_fd, size, Gfx::Bitmap::ShouldCloseAnonymousFile::No); + auto bitmap = Gfx::Bitmap::create_with_anon_fd(format, anon_fd, size, {}, Gfx::Bitmap::ShouldCloseAnonymousFile::No); if (!bitmap) return {}; return make(bitmap.release_nonnull()); diff --git a/Userland/Libraries/LibGfx/Bitmap.cpp b/Userland/Libraries/LibGfx/Bitmap.cpp index 1d3097e207..dcaba24a77 100644 --- a/Userland/Libraries/LibGfx/Bitmap.cpp +++ b/Userland/Libraries/LibGfx/Bitmap.cpp @@ -115,7 +115,7 @@ RefPtr Bitmap::create_shareable(BitmapFormat format, const IntSize& size auto anon_fd = anon_create(round_up_to_power_of_two(data_size, PAGE_SIZE), O_CLOEXEC); if (anon_fd < 0) return nullptr; - return Bitmap::create_with_anon_fd(format, anon_fd, size, ShouldCloseAnonymousFile::No); + return Bitmap::create_with_anon_fd(format, anon_fd, size, {}, ShouldCloseAnonymousFile::No); } #endif @@ -190,7 +190,7 @@ static bool check_size(const IntSize& size, BitmapFormat format, unsigned actual return true; } -RefPtr Bitmap::create_with_anon_fd(BitmapFormat format, int anon_fd, const IntSize& size, ShouldCloseAnonymousFile should_close_anon_fd) +RefPtr Bitmap::create_with_anon_fd(BitmapFormat format, int anon_fd, const IntSize& size, const Vector& palette, ShouldCloseAnonymousFile should_close_anon_fd) { void* data = nullptr; { @@ -216,7 +216,7 @@ RefPtr Bitmap::create_with_anon_fd(BitmapFormat format, int anon_fd, con } } - return adopt(*new Bitmap(format, anon_fd, size, data)); + return adopt(*new Bitmap(format, anon_fd, size, data, palette)); } RefPtr Bitmap::create_with_shared_buffer(BitmapFormat format, NonnullRefPtr&& shared_buffer, const IntSize& size, const Vector& palette) @@ -330,7 +330,7 @@ Bitmap::Bitmap(BitmapFormat format, NonnullRefPtr&& shared_buffer, allocate_palette_from_format(m_format, palette); } -Bitmap::Bitmap(BitmapFormat format, int anon_fd, const IntSize& size, void* data) +Bitmap::Bitmap(BitmapFormat format, int anon_fd, const IntSize& size, void* data, const Vector& palette) : m_size(size) , m_data(data) , m_pitch(minimum_pitch(size.width(), format)) @@ -339,8 +339,11 @@ Bitmap::Bitmap(BitmapFormat format, int anon_fd, const IntSize& size, void* data , m_purgeable(true) , m_anon_fd(anon_fd) { - ASSERT(!is_indexed()); + ASSERT(!is_indexed() || !palette.is_empty()); ASSERT(!size_would_overflow(format, size)); + + if (is_indexed(m_format)) + allocate_palette_from_format(m_format, palette); } RefPtr Bitmap::clone() const @@ -430,7 +433,7 @@ RefPtr Bitmap::to_bitmap_backed_by_anon_fd() const auto anon_fd = anon_create(round_up_to_power_of_two(size_in_bytes(), PAGE_SIZE), O_CLOEXEC); if (anon_fd < 0) return nullptr; - auto bitmap = Bitmap::create_with_anon_fd(m_format, anon_fd, m_size, ShouldCloseAnonymousFile::No); + auto bitmap = Bitmap::create_with_anon_fd(m_format, anon_fd, m_size, palette_to_vector(), ShouldCloseAnonymousFile::No); if (!bitmap) return nullptr; memcpy(bitmap->scanline(0), scanline(0), size_in_bytes()); diff --git a/Userland/Libraries/LibGfx/Bitmap.h b/Userland/Libraries/LibGfx/Bitmap.h index 0809b43cc5..09b90222d6 100644 --- a/Userland/Libraries/LibGfx/Bitmap.h +++ b/Userland/Libraries/LibGfx/Bitmap.h @@ -56,6 +56,21 @@ enum class BitmapFormat { RGBA32, }; +inline bool is_valid_bitmap_format(unsigned format) +{ + switch (format) { + case (unsigned)BitmapFormat::Invalid: + case (unsigned)BitmapFormat::Indexed1: + case (unsigned)BitmapFormat::Indexed2: + case (unsigned)BitmapFormat::Indexed4: + case (unsigned)BitmapFormat::Indexed8: + case (unsigned)BitmapFormat::RGB32: + case (unsigned)BitmapFormat::RGBA32: + return true; + } + return false; +} + enum class StorageFormat { Indexed8, RGB32, @@ -98,7 +113,7 @@ public: static RefPtr create_purgeable(BitmapFormat, const IntSize&); static RefPtr create_wrapper(BitmapFormat, const IntSize&, size_t pitch, void*); static RefPtr load_from_file(const StringView& path); - static RefPtr create_with_anon_fd(BitmapFormat, int anon_fd, const IntSize&, ShouldCloseAnonymousFile); + static RefPtr create_with_anon_fd(BitmapFormat, int anon_fd, const IntSize&, const Vector& palette, ShouldCloseAnonymousFile); static RefPtr create_with_shared_buffer(BitmapFormat, NonnullRefPtr&&, const IntSize&); static RefPtr create_with_shared_buffer(BitmapFormat, NonnullRefPtr&&, const IntSize&, const Vector& palette); static RefPtr create_from_serialized_byte_buffer(ByteBuffer&& buffer); @@ -241,7 +256,7 @@ private: Bitmap(BitmapFormat, const IntSize&, Purgeable, const BackingStore&); Bitmap(BitmapFormat, const IntSize&, size_t pitch, void*); Bitmap(BitmapFormat, NonnullRefPtr&&, const IntSize&, const Vector& palette); - Bitmap(BitmapFormat, int anon_fd, const IntSize&, void*); + Bitmap(BitmapFormat, int anon_fd, const IntSize&, void*, const Vector& palette); static Optional allocate_backing_store(BitmapFormat, const IntSize&, Purgeable); diff --git a/Userland/Libraries/LibGfx/ShareableBitmap.cpp b/Userland/Libraries/LibGfx/ShareableBitmap.cpp index 1edf498096..c59a2d0dad 100644 --- a/Userland/Libraries/LibGfx/ShareableBitmap.cpp +++ b/Userland/Libraries/LibGfx/ShareableBitmap.cpp @@ -52,9 +52,14 @@ bool encode(Encoder& encoder, const Gfx::ShareableBitmap& shareable_bitmap) encoder << shareable_bitmap.is_valid(); if (!shareable_bitmap.is_valid()) return true; - encoder << IPC::File(shareable_bitmap.bitmap()->anon_fd()); - encoder << shareable_bitmap.width(); - encoder << shareable_bitmap.height(); + auto& bitmap = *shareable_bitmap.bitmap(); + encoder << IPC::File(bitmap.anon_fd()); + encoder << bitmap.size(); + encoder << (u32)bitmap.format(); + if (bitmap.is_indexed()) { + auto palette = bitmap.palette_to_vector(); + encoder << palette; + } return true; } @@ -68,13 +73,23 @@ bool decode(Decoder& decoder, Gfx::ShareableBitmap& shareable_bitmap) return true; } IPC::File anon_file; - Gfx::IntSize size; if (!decoder.decode(anon_file)) return false; + Gfx::IntSize size; if (!decoder.decode(size)) return false; - - auto bitmap = Gfx::Bitmap::create_with_anon_fd(Gfx::BitmapFormat::RGBA32, anon_file.take_fd(), size, Gfx::Bitmap::ShouldCloseAnonymousFile::Yes); + u32 raw_bitmap_format; + if (!decoder.decode(raw_bitmap_format)) + return false; + if (!Gfx::is_valid_bitmap_format(raw_bitmap_format)) + return false; + auto bitmap_format = (Gfx::BitmapFormat)raw_bitmap_format; + Vector palette; + if (Gfx::Bitmap::is_indexed(bitmap_format)) { + if (!decoder.decode(palette)) + return false; + } + auto bitmap = Gfx::Bitmap::create_with_anon_fd(bitmap_format, anon_file.take_fd(), size, palette, Gfx::Bitmap::ShouldCloseAnonymousFile::Yes); if (!bitmap) return false; shareable_bitmap = Gfx::ShareableBitmap { bitmap.release_nonnull(), Gfx::ShareableBitmap::ConstructWithKnownGoodBitmap }; diff --git a/Userland/Services/WindowServer/ClientConnection.cpp b/Userland/Services/WindowServer/ClientConnection.cpp index 482294de57..199d8bf5cb 100644 --- a/Userland/Services/WindowServer/ClientConnection.cpp +++ b/Userland/Services/WindowServer/ClientConnection.cpp @@ -571,6 +571,7 @@ OwnPtr ClientConnection:: message.has_alpha_channel() ? Gfx::BitmapFormat::RGBA32 : Gfx::BitmapFormat::RGB32, message.anon_file().take_fd(), message.size(), + {}, Gfx::Bitmap::ShouldCloseAnonymousFile::Yes); window.set_backing_store(move(backing_store), message.serial()); }