commit d027243
Michael Forney
·
2013-06-21 08:35:34 +0000 UTC
parent 96ab570
surface: Properly handle buffer attach and destroy
+67,
-18
1@@ -10,9 +10,21 @@ static pixman_box32_t infinite_extents = {
2 .x2 = INT32_MAX, .y2 = INT32_MAX
3 };
4
5+/**
6+ * Removes a buffer from a surface state.
7+ */
8+static void handle_buffer_destroy(struct wl_listener * listener, void * data)
9+{
10+ struct swc_surface_state * state;
11+
12+ state = wl_container_of(listener, state, buffer_destroy_listener);
13+ state->buffer = NULL;
14+}
15+
16 static void state_initialize(struct swc_surface_state * state)
17 {
18 state->buffer = NULL;
19+ state->buffer_destroy_listener.notify = &handle_buffer_destroy;
20
21 pixman_region32_init(&state->damage);
22 pixman_region32_init(&state->opaque);
23@@ -25,6 +37,12 @@ static void state_finish(struct swc_surface_state * state)
24 {
25 struct wl_resource * resource, * tmp;
26
27+ if (state->buffer)
28+ {
29+ /* Remove any buffer listeners */
30+ wl_list_remove(&state->buffer_destroy_listener.link);
31+ }
32+
33 pixman_region32_fini(&state->damage);
34 pixman_region32_fini(&state->opaque);
35 pixman_region32_fini(&state->input);
36@@ -34,6 +52,37 @@ static void state_finish(struct swc_surface_state * state)
37 wl_resource_destroy(resource);
38 }
39
40+/**
41+ * In order to set the buffer of a surface state (current or pending), we need
42+ * to manage the destroy listeners we have for the new and old buffer.
43+ *
44+ * @return: Whether or not the buffer was changed.
45+ */
46+static bool state_set_buffer(struct swc_surface_state * state,
47+ struct wl_buffer * buffer)
48+{
49+ if (buffer == state->buffer)
50+ return false;
51+
52+ if (state->buffer)
53+ {
54+ /* No longer need to worry about the old buffer being destroyed. */
55+ wl_list_remove(&state->buffer_destroy_listener.link);
56+ }
57+
58+ if (buffer)
59+ {
60+ /* Need to watch the new buffer for destruction so we can remove it
61+ * from state. */
62+ wl_resource_add_destroy_listener(&buffer->resource,
63+ &state->buffer_destroy_listener);
64+ }
65+
66+ state->buffer = buffer;
67+
68+ return true;
69+}
70+
71 static void destroy(struct wl_client * client, struct wl_resource * resource)
72 {
73 wl_resource_destroy(resource);
74@@ -43,25 +92,17 @@ static void attach(struct wl_client * client, struct wl_resource * resource,
75 struct wl_resource * buffer_resource, int32_t x, int32_t y)
76 {
77 struct swc_surface * surface = wl_resource_get_user_data(resource);
78+ struct wl_buffer * buffer
79+ = buffer_resource ? wl_resource_get_user_data(buffer_resource) : NULL;
80
81- surface->pending.x = x;
82- surface->pending.y = y;
83-
84- if (buffer_resource)
85- {
86- struct wl_buffer * buffer = wl_resource_get_user_data(buffer_resource);
87+ state_set_buffer(&surface->pending.state, buffer);
88
89- surface->pending.state.buffer = buffer;
90- surface->geometry.width = buffer->width;
91- surface->geometry.height = buffer->height;
92- }
93- else
94- {
95- surface->pending.state.buffer = NULL;
96+ /* Adjust geometry of the surface to match the buffer. */
97+ surface->geometry.width = buffer ? buffer->width : 0;
98+ surface->geometry.height = buffer ? buffer->height : 0;
99
100- surface->geometry.width = 0;
101- surface->geometry.height = 0;
102- }
103+ surface->pending.x = x;
104+ surface->pending.y = y;
105 }
106
107 static void damage(struct wl_client * client, struct wl_resource * resource,
108@@ -129,9 +170,17 @@ static void commit(struct wl_client * client, struct wl_resource * resource)
109
110 event.data = surface;
111
112- if (surface->pending.state.buffer != surface->state.buffer)
113+ /* Attach */
114+ if (surface->state.buffer != surface->pending.state.buffer)
115 {
116- surface->state.buffer = surface->pending.state.buffer;
117+ if (surface->state.buffer)
118+ {
119+ /* Release the old buffer, it's no longer needed. */
120+ wl_buffer_send_release(&surface->state.buffer->resource);
121+ }
122+
123+ state_set_buffer(&surface->state, surface->pending.state.buffer);
124+
125 event.type = SWC_SURFACE_ATTACH;
126 wl_signal_emit(&surface->event_signal, &event);
127 }
+1,
-0
1@@ -27,6 +27,7 @@ struct swc_surface_state
2 pixman_region32_t input;
3
4 struct wl_list frame_callbacks;
5+ struct wl_listener buffer_destroy_listener;
6 };
7
8 struct swc_surface