LibGfx+LibGUI: Make Gfx::ShareableBitmap transmit indexed palettes

This commit is contained in:
Andreas Kling 2021-01-16 23:57:57 +01:00
parent b5d98c0945
commit 8a61aba1e5
Notes: sideshowbarker 2024-07-18 23:09:37 +09:00
5 changed files with 49 additions and 15 deletions
Userland

View file

@ -728,7 +728,7 @@ OwnPtr<WindowBackingStore> 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<WindowBackingStore>(bitmap.release_nonnull());

View file

@ -115,7 +115,7 @@ RefPtr<Bitmap> 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> Bitmap::create_with_anon_fd(BitmapFormat format, int anon_fd, const IntSize& size, ShouldCloseAnonymousFile should_close_anon_fd)
RefPtr<Bitmap> Bitmap::create_with_anon_fd(BitmapFormat format, int anon_fd, const IntSize& size, const Vector<RGBA32>& palette, ShouldCloseAnonymousFile should_close_anon_fd)
{
void* data = nullptr;
{
@ -216,7 +216,7 @@ RefPtr<Bitmap> 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> Bitmap::create_with_shared_buffer(BitmapFormat format, NonnullRefPtr<SharedBuffer>&& shared_buffer, const IntSize& size, const Vector<RGBA32>& palette)
@ -330,7 +330,7 @@ Bitmap::Bitmap(BitmapFormat format, NonnullRefPtr<SharedBuffer>&& 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<RGBA32>& 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<Gfx::Bitmap> Bitmap::clone() const
@ -430,7 +433,7 @@ RefPtr<Bitmap> 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());

View file

@ -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<Bitmap> create_purgeable(BitmapFormat, const IntSize&);
static RefPtr<Bitmap> create_wrapper(BitmapFormat, const IntSize&, size_t pitch, void*);
static RefPtr<Bitmap> load_from_file(const StringView& path);
static RefPtr<Bitmap> create_with_anon_fd(BitmapFormat, int anon_fd, const IntSize&, ShouldCloseAnonymousFile);
static RefPtr<Bitmap> create_with_anon_fd(BitmapFormat, int anon_fd, const IntSize&, const Vector<RGBA32>& palette, ShouldCloseAnonymousFile);
static RefPtr<Bitmap> create_with_shared_buffer(BitmapFormat, NonnullRefPtr<SharedBuffer>&&, const IntSize&);
static RefPtr<Bitmap> create_with_shared_buffer(BitmapFormat, NonnullRefPtr<SharedBuffer>&&, const IntSize&, const Vector<RGBA32>& palette);
static RefPtr<Bitmap> 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<SharedBuffer>&&, const IntSize&, const Vector<RGBA32>& palette);
Bitmap(BitmapFormat, int anon_fd, const IntSize&, void*);
Bitmap(BitmapFormat, int anon_fd, const IntSize&, void*, const Vector<RGBA32>& palette);
static Optional<BackingStore> allocate_backing_store(BitmapFormat, const IntSize&, Purgeable);

View file

@ -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<Gfx::RGBA32> 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 };

View file

@ -571,6 +571,7 @@ OwnPtr<Messages::WindowServer::SetWindowBackingStoreResponse> 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());
}