commit fae91de

Michael Forney  ·  2013-07-25 07:52:05 +0000 UTC
parent a4f8758
wayland: Implement damage tracking (including copy and submit)
3 files changed,  +107, -3
M TODO
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