commit fae91de
Michael Forney
·
2013-07-25 07:52:05 +0000 UTC
parent a4f8758
wayland: Implement damage tracking (including copy and submit)
M
TODO
+0,
-1
1@@ -2,6 +2,5 @@ TODO
2 ====
3 - Non-monochrome text rendering
4 - Probably requires 3d engine blending for intel backend
5-- Optional damage tracking and handling for Wayland drawables
6 - Add doxygen documentation
7
+75,
-1
1@@ -50,8 +50,10 @@ struct wayland_drawable
2 struct wl_buffer * wl;
3 struct wld_drawable * drawable;
4 bool busy;
5+ pixman_region32_t damage;
6 } buffers[2];
7 uint8_t front_buffer;
8+ uint32_t damage_tracking;
9 };
10
11 _Static_assert(offsetof(struct wayland_drawable, base) == 0,
12@@ -194,7 +196,8 @@ void wld_wayland_destroy_context(struct wld_wayland_context * wayland)
13
14 struct wld_drawable * wld_wayland_create_drawable
15 (struct wld_wayland_context * context, struct wl_surface * surface,
16- uint32_t width, uint32_t height, enum wld_format format)
17+ uint32_t width, uint32_t height, enum wld_format format,
18+ uint32_t damage_flags)
19 {
20 struct wayland_drawable * wayland;
21
22@@ -218,8 +221,11 @@ struct wld_drawable * wld_wayland_create_drawable
23
24 wayland->buffers[0].busy = false;
25 wayland->buffers[1].busy = false;
26+ pixman_region32_init(&wayland->buffers[0].damage);
27+ pixman_region32_init(&wayland->buffers[1].damage);
28 wayland->front_buffer = 0;
29 wayland->surface = surface;
30+ wayland->damage_tracking = damage_flags;
31
32 wayland->base.interface = &wayland_draw;
33 wayland->base.width = width;
34@@ -240,6 +246,20 @@ struct wld_drawable * wld_wayland_create_drawable
35 return NULL;
36 }
37
38+void wld_wayland_drawable_set_damage_tracking(struct wld_drawable * drawable,
39+ uint32_t flags)
40+{
41+ struct wayland_drawable * wayland = (void *) drawable;
42+
43+ if (!wayland->damage_tracking && flags)
44+ {
45+ pixman_region32_clear(&wayland->buffers[0].damage);
46+ pixman_region32_clear(&wayland->buffers[1].damage);
47+ }
48+
49+ wayland->damage_tracking = flags;
50+}
51+
52 int wayland_roundtrip(struct wl_display * display,
53 struct wl_event_queue * queue)
54 {
55@@ -293,6 +313,16 @@ static void begin(struct wayland_drawable * wayland)
56 {
57 /* Wait for the back buffer to become available. */
58 wait_for_backbuf(wayland);
59+
60+ /* Copy across damage from front buffer. */
61+ if (wayland->damage_tracking & WLD_WAYLAND_DAMAGE_COPY
62+ && pixman_region32_not_empty(&FRONTBUF(wayland).damage))
63+ {
64+ wld_copy_region(FRONTBUF(wayland).drawable,
65+ BACKBUF(wayland).drawable,
66+ &FRONTBUF(wayland).damage, 0, 0);
67+ pixman_region32_clear(&FRONTBUF(wayland).damage);
68+ }
69 }
70
71 static void wayland_fill_rectangle(struct wld_drawable * drawable,
72@@ -303,6 +333,13 @@ static void wayland_fill_rectangle(struct wld_drawable * drawable,
73
74 begin(wayland);
75 wld_fill_rectangle(BACKBUF(wayland).drawable, color, x, y, width, height);
76+
77+ if (wayland->damage_tracking)
78+ {
79+ pixman_region32_union_rect(&BACKBUF(wayland).damage,
80+ &BACKBUF(wayland).damage,
81+ x, y, width, height);
82+ }
83 }
84
85 static void wayland_fill_region(struct wld_drawable * drawable, uint32_t color,
86@@ -312,6 +349,12 @@ static void wayland_fill_region(struct wld_drawable * drawable, uint32_t color,
87
88 begin(wayland);
89 wld_fill_region(BACKBUF(wayland).drawable, color, region);
90+
91+ if (wayland->damage_tracking)
92+ {
93+ pixman_region32_union(&BACKBUF(wayland).damage,
94+ &BACKBUF(wayland).damage, region);
95+ }
96 }
97
98 static void wayland_copy_rectangle(struct wld_drawable * src_drawable,
99@@ -337,20 +380,49 @@ static void wayland_draw_text_utf8(struct wld_drawable * drawable,
100 const char * text, int32_t length,
101 struct wld_extents * extents)
102 {
103+ struct wld_extents extents0;
104 struct wayland_drawable * wayland = (void *) drawable;
105
106+ if (wayland->damage_tracking && !extents)
107+ extents = &extents0;
108+
109 begin(wayland);
110 wld_draw_text_utf8_n(BACKBUF(wayland).drawable, &font->base, color,
111 x, y, text, length, extents);
112+
113+ if (wayland->damage_tracking)
114+ {
115+ pixman_region32_union_rect(&BACKBUF(wayland).damage,
116+ &BACKBUF(wayland).damage,
117+ x, y - font->base.ascent,
118+ extents->advance, font->base.height);
119+ }
120 }
121
122 static void wayland_flush(struct wld_drawable * drawable)
123 {
124 struct wayland_drawable * wayland = (void *) drawable;
125+ pixman_region32_t damage;
126
127 wait_for_backbuf(wayland);
128
129 wld_flush(BACKBUF(wayland).drawable);
130+
131+ if (wayland->damage_tracking & WLD_WAYLAND_DAMAGE_SUBMIT)
132+ {
133+ pixman_box32_t * box;
134+ int num_boxes;
135+
136+ box = pixman_region32_rectangles(&BACKBUF(wayland).damage, &num_boxes);
137+
138+ while (num_boxes--)
139+ {
140+ wl_surface_damage(wayland->surface, box->x1, box->y1,
141+ box->x2 - box->x1, box->y2 - box->y1);
142+ ++box;
143+ }
144+ }
145+
146 wl_surface_attach(wayland->surface, BACKBUF(wayland).wl, 0, 0);
147 wl_surface_commit(wayland->surface);
148
149@@ -367,5 +439,7 @@ static void wayland_destroy(struct wld_drawable * drawable)
150 wl_buffer_destroy(wayland->buffers[1].wl);
151 wld_destroy_drawable(wayland->buffers[0].drawable);
152 wld_destroy_drawable(wayland->buffers[1].drawable);
153+ pixman_region32_fini(&wayland->buffers[0].damage);
154+ pixman_region32_fini(&wayland->buffers[1].damage);
155 }
156
+32,
-1
1@@ -49,6 +49,25 @@ enum wld_wayland_interface_id
2 WLD_SHM
3 };
4
5+enum wld_wayland_damage_flags
6+{
7+ /**
8+ * Copy the damaged region from the front buffer to the back buffer after
9+ * swapping buffers.
10+ *
11+ * This allows you to think of the drawable as a single image.
12+ */
13+ WLD_WAYLAND_DAMAGE_COPY = 1 << 0,
14+
15+ /**
16+ * Submit the damaged region to the compositor before swapping buffers.
17+ *
18+ * If this is not selected, you must manually damage the surface before
19+ * calling wld_flush.
20+ */
21+ WLD_WAYLAND_DAMAGE_SUBMIT = 1 << 1
22+};
23+
24 /**
25 * Create a new drawing context which uses various available Wayland interfaces
26 * (such as wl_shm and wl_drm) to create buffers backed by drawables specific
27@@ -72,10 +91,22 @@ void wld_wayland_destroy_context(struct wld_wayland_context * context);
28 /**
29 * Create a new Wayland drawable for the given surface with a particular pixel
30 * format.
31+ *
32+ * @param damage_flags Initial damage tracking mode.
33+ * @see enum wld_wayland_damage_tracking_flags
34 */
35 struct wld_drawable * wld_wayland_create_drawable
36 (struct wld_wayland_context * context, struct wl_surface * surface,
37- uint32_t width, uint32_t height, enum wld_format format);
38+ uint32_t width, uint32_t height, enum wld_format format,
39+ uint32_t damage_flags);
40+
41+/**
42+ * Enable or disable damage tracking on the specified Wayland drawable.
43+ *
44+ * @see enum wld_wayland_damage_tracking_flags
45+ */
46+void wld_wayland_drawable_set_damage_tracking(struct wld_drawable * drawable,
47+ uint32_t flags);
48
49 #endif
50