1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 12:47:35 +00:00

Let userland retain the window backing store while drawing into it.

To start painting, call:
gui$get_window_backing_store()

Then finish up with:
gui$release_window_backing_store()

Process will retain the underlying GraphicsBitmap behind the scenes.
This fixes racing between the WindowServer and GUI clients.

This patch also adds a WSWindowLocker that is exactly what it sounds like.
This commit is contained in:
Andreas Kling 2019-01-24 23:40:12 +01:00
parent ccf3fc4618
commit 86eae0f8df
22 changed files with 244 additions and 102 deletions

View file

@ -1,6 +1,7 @@
#pragma once
#include "Color.h"
#include "Rect.h"
#include "Size.h"
#include <AK/Retainable.h>
#include <AK/RetainPtr.h>
@ -20,6 +21,7 @@ public:
RGBA32* scanline(int y);
const RGBA32* scanline(int y) const;
Rect rect() const { return { {}, m_size }; }
Size size() const { return m_size; }
int width() const { return m_size.width(); }
int height() const { return m_size.height(); }

View file

@ -7,6 +7,8 @@
#ifdef LIBGUI
#include <LibGUI/GWidget.h>
#include <LibGUI/GWindow.h>
#include <LibC/gui.h>
#include <LibC/stdio.h>
#endif
#define DEBUG_WIDGET_UNDERDRAW
@ -22,12 +24,20 @@ Painter::Painter(GraphicsBitmap& bitmap)
Painter::Painter(GWidget& widget)
: m_font(&widget.font())
{
m_target = widget.backing();
GUI_WindowBackingStoreInfo backing;
int rc = gui_get_window_backing_store(widget.window()->window_id(), &backing);
if (rc < 0) {
perror("gui_get_window_backing_store");
exit(1);
}
m_backing_store_id = backing.backing_store_id;
m_target = GraphicsBitmap::create_wrapper(backing.size, backing.pixels);
ASSERT(m_target);
m_window = widget.window();
m_translation.move_by(widget.relative_position());
// NOTE: m_clip_rect is in Window coordinates since we are painting into its backing store.
m_clip_rect = widget.relative_rect();
m_clip_rect.intersect(m_target->rect());
#ifdef DEBUG_WIDGET_UNDERDRAW
// If the widget is not opaque, let's not mess it up with debugging color.
@ -39,6 +49,11 @@ Painter::Painter(GWidget& widget)
Painter::~Painter()
{
#ifdef LIBGUI
m_target = nullptr;
int rc = gui_release_window_backing_store(m_backing_store_id);
ASSERT(rc == 0);
#endif
}
void Painter::fill_rect(const Rect& a_rect, Color color)
@ -47,6 +62,9 @@ void Painter::fill_rect(const Rect& a_rect, Color color)
rect.move_by(m_translation);
rect.intersect(m_clip_rect);
if (rect.is_empty())
return;
RGBA32* dst = m_target->scanline(rect.top()) + rect.left();
const unsigned dst_skip = m_target->width();
@ -266,3 +284,13 @@ void Painter::blit(const Point& position, const GraphicsBitmap& source, const Re
src += src_skip;
}
}
void Painter::set_clip_rect(const Rect& rect)
{
m_clip_rect = Rect::intersection(rect, m_target->rect());
}
void Painter::clear_clip_rect()
{
m_clip_rect = m_target->rect();
}

View file

@ -40,8 +40,8 @@ public:
void set_draw_op(DrawOp op) { m_draw_op = op; }
DrawOp draw_op() const { return m_draw_op; }
void set_clip_rect(const Rect& rect) { m_clip_rect = rect; }
void clear_clip_rect() { m_clip_rect = { 0, 0, 1024, 768 }; }
void set_clip_rect(const Rect& rect);
void clear_clip_rect();
Rect clip_rect() const { return m_clip_rect; }
private:
@ -53,6 +53,7 @@ private:
RetainPtr<GraphicsBitmap> m_target;
#ifdef LIBGUI
GWindow* m_window { nullptr };
void* m_backing_store_id { nullptr };
#endif
DrawOp m_draw_op { DrawOp::Copy };
};