commit 9c6a405
Michael Forney
·
2013-09-11 07:34:53 +0000 UTC
parent d0a9e34
Introduce surface classes
11 files changed,
+642,
-136
+1,
-0
1@@ -11,6 +11,7 @@ libswc_la_SOURCES = \
2 output.c output.h \
3 buffer.c buffer.h \
4 surface.c surface.h \
5+ compositor_surface.c compositor_surface.h \
6 region.c region.h \
7 renderer.c renderer.h \
8 input_focus.c input_focus.h \
+7,
-50
1@@ -170,33 +170,6 @@ static void handle_tty_event(struct wl_listener * listener, void * data)
2 }
3 }
4
5-static void handle_surface_event(struct wl_listener * listener, void * data)
6-{
7- struct swc_event * event = data;
8- struct swc_surface * surface = event->data;
9- struct swc_compositor * compositor = surface->compositor_state.compositor;
10-
11- switch (event->type)
12- {
13- case SWC_SURFACE_ATTACH:
14- swc_renderer_attach(&compositor->renderer, &compositor->outputs,
15- surface, surface->state.buffer);
16- break;
17- case SWC_SURFACE_REPAINT:
18- {
19- struct swc_output * output;
20-
21- wl_list_for_each(output, &compositor->outputs, link)
22- {
23- if (surface->output_mask & (1 << output->id))
24- schedule_repaint_for_output(compositor, output);
25- }
26-
27- break;
28- }
29- }
30-}
31-
32 static void handle_drm_event(struct wl_listener * listener, void * data)
33 {
34 struct swc_event * event = data;
35@@ -266,6 +239,11 @@ static void create_surface(struct wl_client * client,
36 struct swc_surface * surface;
37 struct swc_output * output;
38
39+ printf("compositor.create_surface\n");
40+
41+ output = swc_container_of(compositor->outputs.next, typeof(*output), link);
42+
43+ /* Initialize surface. */
44 surface = swc_surface_new(client, id);
45
46 if (!surface)
47@@ -273,29 +251,6 @@ static void create_surface(struct wl_client * client,
48 wl_resource_post_no_memory(resource);
49 return;
50 }
51-
52- printf("compositor_create_surface: %p\n", surface);
53-
54- output = swc_container_of(compositor->outputs.next, typeof(*output), link);
55-
56- /* Initialize compositor state */
57- surface->compositor_state = (struct swc_compositor_surface_state) {
58- .compositor = compositor,
59- .event_listener = {
60- .notify = &handle_surface_event
61- },
62- .destroy_listener = {
63- .notify = &handle_surface_destroy
64- }
65- };
66-
67- wl_signal_add(&surface->event_signal,
68- &surface->compositor_state.event_listener);
69- wl_resource_add_destroy_listener(surface->resource,
70- &surface->compositor_state.destroy_listener);
71-
72- wl_list_insert(compositor->surfaces.prev, &surface->link);
73- surface->output_mask |= 1 << output->id;
74 }
75
76 static void create_region(struct wl_client * client,
77@@ -340,6 +295,8 @@ bool swc_compositor_initialize(struct swc_compositor * compositor,
78 compositor->display = display;
79 compositor->tty_listener.notify = &handle_tty_event;
80 compositor->drm_listener.notify = &handle_drm_event;
81+ compositor->compositor_class.interface
82+ = &swc_compositor_class_implementation;
83
84 compositor->udev = udev_new();
85
+20,
-0
1@@ -27,6 +27,23 @@ struct swc_compositor
2 struct wl_list surfaces;
3 struct wl_array key_bindings;
4
5+ /* Internal state related to repainting the screen. */
6+ struct
7+ {
8+ pixman_region32_t damage;
9+ pixman_region32_t opaque;
10+
11+ /* A mask of outputs that have been repainted but are waiting on a page
12+ * flip. */
13+ uint32_t pending_flips;
14+
15+ /* A mask of outputs that are scheduled to be repainted on the next
16+ * idle. */
17+ uint32_t scheduled_updates;
18+ };
19+
20+ struct swc_surface_class compositor_class;
21+
22 struct wl_listener tty_listener;
23 struct wl_listener drm_listener;
24
25@@ -45,5 +62,8 @@ void swc_compositor_add_key_binding(struct swc_compositor * compositor,
26 uint32_t modifiers, xkb_keysym_t key,
27 swc_binding_handler_t handler, void * data);
28
29+void swc_compositor_schedule_update(struct swc_compositor * compositor,
30+ struct swc_output * output);
31+
32 #endif
33
+321,
-0
1@@ -0,0 +1,321 @@
2+/* swc: compositor_surface.c
3+ *
4+ * Copyright (c) 2013 Michael Forney
5+ *
6+ * Permission is hereby granted, free of charge, to any person obtaining a copy
7+ * of this software and associated documentation files (the "Software"), to deal
8+ * in the Software without restriction, including without limitation the rights
9+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+ * copies of the Software, and to permit persons to whom the Software is
11+ * furnished to do so, subject to the following conditions:
12+ *
13+ * The above copyright notice and this permission notice shall be included in
14+ * all copies or substantial portions of the Software.
15+ *
16+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+ * SOFTWARE.
23+ */
24+
25+#include "compositor_surface.h"
26+#include "compositor.h"
27+#include "util.h"
28+
29+#include <stdio.h>
30+#include <stdlib.h>
31+
32+static bool add(struct swc_surface * surface);
33+static void remove_(struct swc_surface * surface);
34+static void attach(struct swc_surface * surface, struct wl_resource * resource);
35+static void update(struct swc_surface * surface);
36+static void move(struct swc_surface * surface, int32_t x, int32_t y);
37+
38+const struct swc_surface_class_interface swc_compositor_class_implementation = {
39+ .add = &add,
40+ .remove = &remove_,
41+ .attach = &attach,
42+ .update = &update,
43+ .move = &move
44+};
45+
46+/**
47+ * Adds damage from the region below a surface, taking into account it's clip
48+ * region, to the region specified by `damage'.
49+ */
50+static void damage_below_surface(struct swc_surface * surface)
51+{
52+ struct swc_compositor * compositor = swc_container_of
53+ (surface->class, typeof(*compositor), compositor_class);
54+ struct swc_compositor_surface_state * state = surface->class_state;
55+ pixman_region32_t damage_below;
56+
57+ pixman_region32_init_with_extents(&damage_below, &state->extents);
58+ pixman_region32_subtract(&damage_below, &damage_below, &state->clip);
59+ pixman_region32_union(&compositor->damage, &compositor->damage,
60+ &damage_below);
61+ pixman_region32_fini(&damage_below);
62+}
63+
64+/**
65+ * Completely damages the surface and its border.
66+ */
67+static void damage_surface(struct swc_surface * surface)
68+{
69+ struct swc_compositor_surface_state * state = surface->class_state;
70+ printf("damaging surface\n");
71+
72+ pixman_region32_fini(&surface->state.damage);
73+ pixman_region32_init_rect(&surface->state.damage, 0, 0,
74+ surface->geometry.width,
75+ surface->geometry.height);
76+ state->border.damaged = true;
77+}
78+
79+static void update_extents(struct swc_surface * surface)
80+{
81+ struct swc_compositor_surface_state * state = surface->class_state;
82+
83+ state->extents.x1 = surface->geometry.x - state->border.width;
84+ state->extents.y1 = surface->geometry.y - state->border.width;
85+ state->extents.x2 = surface->geometry.x + surface->geometry.width
86+ + state->border.width;
87+ state->extents.y2 = surface->geometry.y + surface->geometry.height
88+ + state->border.width;
89+
90+ /* Damage border. */
91+ state->border.damaged = true;
92+}
93+
94+static void update_outputs(struct swc_surface * surface)
95+{
96+ struct swc_compositor * compositor = swc_container_of
97+ (surface->class, typeof(*compositor), compositor_class);
98+ struct swc_compositor_surface_state * state = surface->class_state;
99+ uint32_t old_outputs = surface->outputs, new_outputs = 0,
100+ entered_outputs, left_outputs, changed_outputs;
101+ struct swc_output * output;
102+ struct wl_client * client;
103+ struct wl_resource * resource;
104+
105+ if (state->mapped)
106+ {
107+ wl_list_for_each(output, &compositor->outputs, link)
108+ {
109+ if (swc_rectangle_overlap(&output->geometry, &surface->geometry))
110+ new_outputs |= SWC_OUTPUT_MASK(output);
111+ }
112+ }
113+
114+ if (new_outputs == old_outputs)
115+ return;
116+
117+ entered_outputs = new_outputs & ~old_outputs;
118+ left_outputs = old_outputs & ~new_outputs;
119+ changed_outputs = old_outputs ^ new_outputs;
120+
121+ wl_list_for_each(output, &compositor->outputs, link)
122+ {
123+ if (!(changed_outputs & SWC_OUTPUT_MASK(output)))
124+ continue;
125+
126+ client = wl_resource_get_client(surface->resource);
127+ resource = wl_resource_find_for_client(&output->resources, client);
128+
129+ if (resource)
130+ {
131+ if (entered_outputs & SWC_OUTPUT_MASK(output))
132+ wl_surface_send_enter(surface->resource, resource);
133+ else if (left_outputs & SWC_OUTPUT_MASK(output))
134+ wl_surface_send_leave(surface->resource, resource);
135+ }
136+ }
137+
138+ surface->outputs = new_outputs;
139+}
140+
141+/* Compositor class */
142+bool add(struct swc_surface * surface)
143+{
144+ struct swc_compositor * compositor = swc_container_of
145+ (surface->class, typeof(*compositor), compositor_class);
146+ struct swc_compositor_surface_state * state;
147+
148+ state = malloc(sizeof *state);
149+
150+ if (!state)
151+ return false;
152+
153+ state->compositor = compositor;
154+ state->extents.x1 = surface->geometry.x;
155+ state->extents.y1 = surface->geometry.y;
156+ state->extents.x2 = surface->geometry.x + surface->geometry.width;
157+ state->extents.y2 = surface->geometry.y + surface->geometry.height;
158+ state->border.width = 0;
159+ state->border.color = 0x000000;
160+ state->border.damaged = false;
161+ state->mapped = false;
162+
163+ wl_signal_add(&surface->event_signal, &state->event_listener);
164+
165+ pixman_region32_init(&state->clip);
166+
167+ surface->class_state = state;
168+
169+ return true;
170+}
171+
172+void remove_(struct swc_surface * surface)
173+{
174+ struct swc_compositor * compositor = swc_container_of
175+ (surface->class, typeof(*compositor), compositor_class);
176+ struct swc_compositor_surface_state * state = surface->class_state;
177+
178+ swc_compositor_surface_hide(surface);
179+
180+ wl_list_remove(&state->event_listener.link);
181+ pixman_region32_fini(&state->clip);
182+
183+ free(state);
184+}
185+
186+void attach(struct swc_surface * surface, struct wl_resource * resource)
187+{
188+ struct swc_compositor * compositor = swc_container_of
189+ (surface->class, typeof(*compositor), compositor_class);
190+
191+ swc_renderer_attach(&compositor->renderer, surface,
192+ wl_resource_get_user_data(resource));
193+}
194+
195+void update(struct swc_surface * surface)
196+{
197+ struct swc_compositor * compositor = swc_container_of
198+ (surface->class, typeof(*compositor), compositor_class);
199+ struct swc_compositor_surface_state * state = surface->class_state;
200+ struct swc_output * output;
201+
202+ if (!state->mapped)
203+ return;
204+
205+ wl_list_for_each(output, &compositor->outputs, link)
206+ {
207+ if (surface->outputs & SWC_OUTPUT_MASK(output))
208+ swc_compositor_schedule_update(compositor, output);
209+ }
210+}
211+
212+void move(struct swc_surface * surface, int32_t x, int32_t y)
213+{
214+ struct swc_compositor * compositor = swc_container_of
215+ (surface->class, typeof(*compositor), compositor_class);
216+ struct swc_compositor_surface_state * state = surface->class_state;
217+
218+ if (x == surface->geometry.x && y == surface->geometry.y)
219+ return;
220+
221+ if (state->mapped)
222+ damage_below_surface(surface);
223+
224+ surface->geometry.x = x;
225+ surface->geometry.y = y;
226+
227+ update_extents(surface);
228+
229+ if (state->mapped)
230+ {
231+ /* Assume worst-case no clipping until we draw the next frame (in case
232+ * the surface gets moved again before that). */
233+ pixman_region32_init(&state->clip);
234+
235+ damage_below_surface(surface);
236+ update(surface);
237+ update_outputs(surface);
238+ update(surface);
239+ }
240+}
241+
242+void swc_compositor_surface_show(struct swc_surface * surface)
243+{
244+ struct swc_compositor * compositor = swc_container_of
245+ (surface->class, typeof(*compositor), compositor_class);
246+ struct swc_compositor_surface_state * state = surface->class_state;
247+
248+ if (surface->class->interface != &swc_compositor_class_implementation)
249+ return;
250+
251+ if (state->mapped)
252+ return;
253+
254+ printf("showing surface %u\n", wl_resource_get_id(surface->resource));
255+
256+ state->mapped = true;
257+
258+ /* Assume worst-case no clipping until we draw the next frame (in case the
259+ * surface gets moved before that. */
260+ pixman_region32_clear(&state->clip);
261+
262+ damage_surface(surface);
263+ update_outputs(surface);
264+ update(surface);
265+ wl_list_insert(&compositor->surfaces, &surface->link);
266+}
267+
268+void swc_compositor_surface_hide(struct swc_surface * surface)
269+{
270+ struct swc_compositor * compositor = swc_container_of
271+ (surface->class, typeof(*compositor), compositor_class);
272+ struct swc_compositor_surface_state * state = surface->class_state;
273+
274+ if (surface->class->interface != &swc_compositor_class_implementation)
275+ return;
276+
277+ if (!state->mapped)
278+ return;
279+
280+ /* Update all the outputs the surface was on. */
281+ update(surface);
282+
283+ state->mapped = false;
284+
285+ damage_below_surface(surface);
286+ update_outputs(surface);
287+ wl_list_remove(&surface->link);
288+}
289+
290+void swc_compositor_surface_set_border_width(struct swc_surface * surface,
291+ uint32_t width)
292+{
293+ struct swc_compositor_surface_state * state = surface->class_state;
294+
295+ if (state->border.width == width)
296+ return;
297+
298+ state->border.width = width;
299+ state->border.damaged = true;
300+
301+ /* XXX: Damage above surface for transparent surfaces? */
302+
303+ update_extents(surface);
304+ update(surface);
305+}
306+
307+void swc_compositor_surface_set_border_color(struct swc_surface * surface,
308+ uint32_t color)
309+{
310+ struct swc_compositor_surface_state * state = surface->class_state;
311+
312+ if (state->border.color == color)
313+ return;
314+
315+ state->border.color = color;
316+ state->border.damaged = true;
317+
318+ /* XXX: Damage above surface for transparent surfaces? */
319+
320+ update(surface);
321+}
322+
+69,
-0
1@@ -0,0 +1,69 @@
2+/* swc: compositor_surface.h
3+ *
4+ * Copyright (c) 2013 Michael Forney
5+ *
6+ * Permission is hereby granted, free of charge, to any person obtaining a copy
7+ * of this software and associated documentation files (the "Software"), to deal
8+ * in the Software without restriction, including without limitation the rights
9+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+ * copies of the Software, and to permit persons to whom the Software is
11+ * furnished to do so, subject to the following conditions:
12+ *
13+ * The above copyright notice and this permission notice shall be included in
14+ * all copies or substantial portions of the Software.
15+ *
16+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+ * SOFTWARE.
23+ */
24+
25+#ifndef SWC_COMPOSITOR_SURFACE_H
26+#define SWC_COMPOSITOR_SURFACE_H 1
27+
28+#include "surface.h"
29+
30+#include <wayland-server.h>
31+#include <pixman.h>
32+
33+struct swc_compositor_surface_state
34+{
35+ struct swc_compositor * compositor;
36+
37+ /* The box that the surface covers (including it's border). */
38+ pixman_box32_t extents;
39+
40+ /* The region that is covered by opaque regions of surfaces above this
41+ * surface. */
42+ pixman_region32_t clip;
43+
44+ struct
45+ {
46+ uint32_t width;
47+ uint32_t color;
48+ bool damaged;
49+ } border;
50+
51+ bool mapped;
52+
53+ struct wl_listener event_listener;
54+};
55+
56+extern const struct swc_surface_class_interface
57+ swc_compositor_class_implementation;
58+
59+void swc_compositor_surface_show(struct swc_surface * surface);
60+
61+void swc_compositor_surface_hide(struct swc_surface * surface);
62+
63+void swc_compositor_surface_set_border_width(struct swc_surface * surface,
64+ uint32_t width);
65+
66+void swc_compositor_surface_set_border_color(struct swc_surface * surface,
67+ uint32_t color);
68+
69+#endif
70+
+2,
-0
1@@ -9,6 +9,8 @@
2 #include <wayland-server.h>
3 #include <xf86drmMode.h>
4
5+#define SWC_OUTPUT_MASK(output) (1 << (output)->id)
6+
7 struct swc_output
8 {
9 /* Outputs need IDs so surfaces can keep track of which output they are
+78,
-31
1@@ -1,4 +1,6 @@
2 #include "renderer.h"
3+#include "compositor_surface.h"
4+#include "util.h"
5
6 #include <stdio.h>
7 #include <GLES2/gl2.h>
8@@ -8,6 +10,23 @@
9 #include <intelbatch/mi.h>
10 #include <xf86drm.h>
11
12+struct buffer_state
13+{
14+ union
15+ {
16+ struct
17+ {
18+ pixman_image_t * image;
19+ } shm;
20+ struct
21+ {
22+ drm_intel_bo * bo;
23+ uint32_t width, height, pitch;
24+ } drm;
25+ };
26+ struct wl_listener destroy_listener;
27+};
28+
29 static inline uint32_t format_wayland_to_pixman(uint32_t wayland_format)
30 {
31 switch (wayland_format)
32@@ -55,15 +74,37 @@ static inline void switch_context(struct swc_renderer * renderer,
33 }
34 }
35
36+static void handle_buffer_destroy(struct wl_listener * listener, void * data)
37+{
38+ struct buffer_state * state
39+ = swc_container_of(listener, typeof(*state), destroy_listener);
40+
41+ free(state);
42+}
43+
44+static inline struct buffer_state * buffer_state(struct wl_resource * resource)
45+{
46+ struct wl_listener * listener
47+ = wl_resource_get_destroy_listener(resource, &handle_buffer_destroy);
48+
49+ return listener ? swc_container_of(listener, struct buffer_state,
50+ destroy_listener)
51+ : NULL;
52+}
53+
54 static void repaint_surface_for_output(struct swc_renderer * renderer,
55 struct swc_surface * surface,
56 struct swc_output * output)
57 {
58 struct swc_buffer * back_buffer = swc_output_get_back_buffer(output);
59+ struct buffer_state * state;
60+ struct swc_compositor_surface_state * surface_state = surface->class_state;
61
62 if (!surface->state.buffer)
63 return;
64
65+ state = buffer_state(&surface->state.buffer->resource);
66+
67 if (wl_buffer_is_shm(surface->state.buffer))
68 {
69 pixman_image_t * buffer_image;
70@@ -77,7 +118,7 @@ static void repaint_surface_for_output(struct swc_renderer * renderer,
71 back_buffer->bo->virtual, back_buffer->pitch);
72
73 pixman_image_composite32(PIXMAN_OP_SRC,
74- surface->renderer_state.shm.image, NULL,
75+ state->shm.image, NULL,
76 buffer_image, 0, 0, 0, 0, 0, 0,
77 surface->geometry.width,
78 surface->geometry.height);
79@@ -88,13 +129,13 @@ static void repaint_surface_for_output(struct swc_renderer * renderer,
80
81 printf("repainting drm surface\n");
82
83- drm_intel_bo * src = surface->renderer_state.drm.bo;
84- uint32_t src_pitch = surface->renderer_state.drm.pitch;
85+ drm_intel_bo * src = state->drm.bo;
86+ uint32_t src_pitch = state->drm.pitch;
87
88 xy_src_copy_blt(&renderer->batch, src, src_pitch, 0, 0,
89 back_buffer->bo, back_buffer->pitch,
90- surface->geometry.x + surface->border.width,
91- surface->geometry.y + surface->border.width,
92+ surface->geometry.x + surface_state->border.width,
93+ surface->geometry.y + surface_state->border.width,
94 surface->geometry.width, surface->geometry.height);
95 }
96
97@@ -105,29 +146,29 @@ static void repaint_surface_for_output(struct swc_renderer * renderer,
98 /* Top */
99 xy_color_blt(&renderer->batch, back_buffer->bo, back_buffer->pitch,
100 surface->geometry.x, surface->geometry.y,
101- surface->geometry.x + surface->geometry.width + 2 * surface->border.width,
102- surface->geometry.y + surface->border.width,
103- surface->border.color);
104+ surface->geometry.x + surface->geometry.width + 2 * surface_state->border.width,
105+ surface->geometry.y + surface_state->border.width,
106+ surface_state->border.color);
107 /* Bottom */
108 xy_color_blt(&renderer->batch, back_buffer->bo, back_buffer->pitch,
109 surface->geometry.x,
110- surface->geometry.y + surface->border.width + surface->geometry.height,
111- surface->geometry.x + surface->geometry.width + 2 * surface->border.width,
112- surface->geometry.y + surface->geometry.height + 2 * surface->border.width,
113- surface->border.color);
114+ surface->geometry.y + surface_state->border.width + surface->geometry.height,
115+ surface->geometry.x + surface->geometry.width + 2 * surface_state->border.width,
116+ surface->geometry.y + surface->geometry.height + 2 * surface_state->border.width,
117+ surface_state->border.color);
118 /* Left */
119 xy_color_blt(&renderer->batch, back_buffer->bo, back_buffer->pitch,
120- surface->geometry.x, surface->geometry.y + surface->border.width,
121- surface->geometry.x + surface->border.width,
122- surface->geometry.y + + surface->border.width + surface->geometry.height,
123- surface->border.color);
124+ surface->geometry.x, surface->geometry.y + surface_state->border.width,
125+ surface->geometry.x + surface_state->border.width,
126+ surface->geometry.y + + surface_state->border.width + surface->geometry.height,
127+ surface_state->border.color);
128 /* Right */
129 xy_color_blt(&renderer->batch, back_buffer->bo, back_buffer->pitch,
130- surface->geometry.x + surface->border.width + surface->geometry.width,
131- surface->geometry.y + surface->border.width,
132- surface->geometry.x + surface->geometry.width + 2 * surface->border.width,
133- surface->geometry.y + surface->border.width + surface->geometry.height,
134- surface->border.color);
135+ surface->geometry.x + surface_state->border.width + surface->geometry.width,
136+ surface->geometry.y + surface_state->border.width,
137+ surface->geometry.x + surface->geometry.width + 2 * surface_state->border.width,
138+ surface->geometry.y + surface_state->border.width + surface->geometry.height,
139+ surface_state->border.color);
140
141 }
142 }
143@@ -162,10 +203,8 @@ void swc_renderer_repaint_output(struct swc_renderer * renderer,
144
145 wl_list_for_each(surface, surfaces, link)
146 {
147- if (surface->output_mask & (1 << output->id))
148- {
149+ if (surface->outputs & (1 << output->id))
150 repaint_surface_for_output(renderer, surface, output);
151- }
152 }
153
154 switch_context(renderer, SWC_RENDERER_CONTEXT_NONE, back_buffer);
155@@ -175,18 +214,26 @@ void swc_renderer_attach(struct swc_renderer * renderer,
156 struct swc_surface * surface,
157 struct wl_buffer * buffer)
158 {
159+ struct buffer_state * state;
160 struct gbm_bo * bo;
161
162 if (!buffer)
163 return;
164
165+ /* Check if we have already seen this buffer. */
166+ if ((state = buffer_state(&buffer->resource)))
167+ return;
168+
169+ if (!(state = malloc(sizeof *state)))
170+ return;
171+
172 /* SHM buffer */
173 if (wl_buffer_is_shm(buffer))
174 {
175 struct swc_output * output;
176 uint32_t wayland_format = wl_shm_buffer_get_format(buffer);
177
178- surface->renderer_state.shm.image
179+ state->shm.image
180 = pixman_image_create_bits(format_wayland_to_pixman(wayland_format),
181 wl_shm_buffer_get_width(buffer),
182 wl_shm_buffer_get_height(buffer),
183@@ -206,15 +253,15 @@ void swc_renderer_attach(struct swc_renderer * renderer,
184 return;
185 }
186
187- surface->renderer_state.drm.bo
188+ state->drm.bo
189 = drm_intel_bo_gem_create_from_name(renderer->drm->bufmgr,
190 "surface", flink.name);
191- surface->renderer_state.drm.pitch = gbm_bo_get_stride(bo);
192- surface->renderer_state.drm.width = gbm_bo_get_width(bo);
193- surface->renderer_state.drm.height = gbm_bo_get_height(bo);
194+ state->drm.pitch = gbm_bo_get_stride(bo);
195+ state->drm.width = gbm_bo_get_width(bo);
196+ state->drm.height = gbm_bo_get_height(bo);
197
198- printf("pitch: %u, width: %u, height: %u\n", surface->renderer_state.drm.pitch,
199- surface->renderer_state.drm.width, surface->renderer_state.drm.height);
200+ printf("pitch: %u, width: %u, height: %u\n", state->drm.pitch,
201+ state->drm.width, state->drm.height);
202 }
203 }
204
+70,
-7
1@@ -1,3 +1,26 @@
2+/* swc: surface.c
3+ *
4+ * Copyright (c) 2013 Michael Forney
5+ *
6+ * Permission is hereby granted, free of charge, to any person obtaining a copy
7+ * of this software and associated documentation files (the "Software"), to deal
8+ * in the Software without restriction, including without limitation the rights
9+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+ * copies of the Software, and to permit persons to whom the Software is
11+ * furnished to do so, subject to the following conditions:
12+ *
13+ * The above copyright notice and this permission notice shall be included in
14+ * all copies or substantial portions of the Software.
15+ *
16+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+ * SOFTWARE.
23+ */
24+
25 #include "surface.h"
26 #include "event.h"
27 #include "region.h"
28@@ -184,8 +207,8 @@ static void commit(struct wl_client * client, struct wl_resource * resource)
29
30 state_set_buffer(&surface->state, surface->pending.state.buffer);
31
32- event.type = SWC_SURFACE_ATTACH;
33- wl_signal_emit(&surface->event_signal, &event);
34+ surface->class->interface->attach(surface,
35+ &surface->state.buffer->resource);
36 }
37
38 /* Damage */
39@@ -221,8 +244,7 @@ static void commit(struct wl_client * client, struct wl_resource * resource)
40 surface->pending.state.buffer = surface->state.buffer;
41 wl_list_init(&surface->pending.state.frame_callbacks);
42
43- event.type = SWC_SURFACE_REPAINT;
44- wl_signal_emit(&surface->event_signal, &event);
45+ surface->class->interface->update(surface);
46 }
47
48 void set_buffer_transform(struct wl_client * client,
49@@ -256,6 +278,9 @@ static void surface_destroy(struct wl_resource * resource)
50 if (surface->shell_destructor)
51 surface->shell_destructor(surface);
52
53+ if (surface->class && surface->class->interface->remove)
54+ surface->class->interface->remove(surface);
55+
56 /* Finish the surface. */
57 state_finish(&surface->state);
58 state_finish(&surface->pending.state);
59@@ -281,15 +306,15 @@ struct swc_surface * swc_surface_new(struct wl_client * client, uint32_t id)
60 return NULL;
61
62 /* Initialize the surface. */
63- surface->output_mask = 0;
64+ surface->outputs = 0;
65 surface->geometry.x = 0;
66 surface->geometry.y = 0;
67 surface->geometry.width = 0;
68 surface->geometry.height = 0;
69- surface->border.width = 0;
70- surface->border.color = 0x000000;
71 surface->shell_data = NULL;
72 surface->shell_destructor = NULL;
73+ surface->class = NULL;
74+ surface->class_state = NULL;
75
76 state_initialize(&surface->state);
77 state_initialize(&surface->pending.state);
78@@ -323,3 +348,41 @@ void swc_surface_send_frame_callbacks(struct swc_surface * surface,
79 wl_list_init(&surface->state.frame_callbacks);
80 }
81
82+void swc_surface_set_class(struct swc_surface * surface,
83+ const struct swc_surface_class * class)
84+{
85+ if (surface->class == class)
86+ return;
87+
88+ if (surface->class && surface->class->interface->remove)
89+ surface->class->interface->remove(surface);
90+
91+ surface->class = class;
92+
93+ if (surface->class)
94+ {
95+ if (surface->class->interface->add
96+ && !surface->class->interface->add(surface))
97+ {
98+ surface->class = NULL;
99+ return;
100+ }
101+
102+
103+ surface->class->interface->attach(surface, &surface->state.buffer->resource);
104+ surface->class->interface->update(surface);
105+ }
106+}
107+
108+void swc_surface_update(struct swc_surface * surface)
109+{
110+ if (surface->class)
111+ surface->class->interface->update(surface);
112+}
113+
114+void swc_surface_move(struct swc_surface * surface, int32_t x, int32_t y)
115+{
116+ if (surface->class)
117+ surface->class->interface->move(surface, x, y);
118+}
119+
+63,
-18
1@@ -1,17 +1,34 @@
2+/* swc: surface.h
3+ *
4+ * Copyright (c) 2013 Michael Forney
5+ *
6+ * Permission is hereby granted, free of charge, to any person obtaining a copy
7+ * of this software and associated documentation files (the "Software"), to deal
8+ * in the Software without restriction, including without limitation the rights
9+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+ * copies of the Software, and to permit persons to whom the Software is
11+ * furnished to do so, subject to the following conditions:
12+ *
13+ * The above copyright notice and this permission notice shall be included in
14+ * all copies or substantial portions of the Software.
15+ *
16+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+ * SOFTWARE.
23+ */
24+
25 #ifndef SWC_SURFACE_H
26 #define SWC_SURFACE_H 1
27
28-#include "surface_state.h"
29-
30 #include <stdbool.h>
31 #include <wayland-server.h>
32 #include <pixman.h>
33
34-enum swc_surface_event
35-{
36- SWC_SURFACE_ATTACH,
37- SWC_SURFACE_REPAINT
38-};
39+struct swc_surface;
40
41 struct swc_surface_state
42 {
43@@ -30,15 +47,41 @@ struct swc_surface_state
44 struct wl_listener buffer_destroy_listener;
45 };
46
47+/**
48+ * A surface class is a set of operations that can be performed on a surface.
49+ * This gives the compositor the ability to classify surfaces, treating some
50+ * specially (for example, a cursor surface).
51+ */
52+struct swc_surface_class_interface
53+{
54+ /* Called when a surface is added to the class. */
55+ bool (* add)(struct swc_surface * surface);
56+
57+ /* Called when a surface is removed from the class. */
58+ void (* remove)(struct swc_surface * surface);
59+
60+ /* Called when a new buffer is attached to a surface. */
61+ void (* attach)(struct swc_surface * surface,
62+ struct wl_resource * resource);
63+
64+ /* Called after a surface requests a commit. */
65+ void (* update)(struct swc_surface * surface);
66+
67+ /* Moves the surface to the specified coordinates. */
68+ void (* move)(struct swc_surface * surface, int32_t x, int32_t y);
69+};
70+
71+struct swc_surface_class
72+{
73+ const struct swc_surface_class_interface * interface;
74+};
75+
76 struct swc_surface
77 {
78 struct wl_resource * resource;
79
80 struct swc_surface_state state;
81
82- union swc_renderer_surface_state renderer_state;
83- struct swc_compositor_surface_state compositor_state;
84-
85 /* For usage by a shell implementation. */
86 void * shell_data;
87
88@@ -54,15 +97,11 @@ struct swc_surface
89 int32_t x, y;
90 } pending;
91
92- pixman_rectangle32_t geometry;
93+ const struct swc_surface_class * class;
94+ void * class_state;
95
96- struct
97- {
98- uint32_t width;
99- uint32_t color;
100- } border;
101-
102- uint32_t output_mask;
103+ uint32_t outputs;
104+ pixman_rectangle32_t geometry;
105
106 struct wl_signal event_signal;
107 struct wl_list link;
108@@ -72,6 +111,12 @@ struct swc_surface * swc_surface_new(struct wl_client * client, uint32_t id);
109
110 void swc_surface_send_frame_callbacks(struct swc_surface * surface,
111 uint32_t time);
112+void swc_surface_set_class(struct swc_surface * surface,
113+ const struct swc_surface_class * class);
114+
115+void swc_surface_update(struct swc_surface * surface);
116+
117+void swc_surface_move(struct swc_surface * surface, int32_t x, int32_t y);
118
119 #endif
120
+0,
-30
1@@ -1,30 +0,0 @@
2-#ifndef SWC_SURFACE_STATE_H
3-#define SWC_SURFACE_STATE_H 1
4-
5-#include <libdrm/intel_bufmgr.h>
6-
7-#include <wayland-server.h>
8-#include <pixman.h>
9-
10-union swc_renderer_surface_state
11-{
12- struct
13- {
14- pixman_image_t * image;
15- } shm;
16- struct
17- {
18- drm_intel_bo * bo;
19- uint32_t width, height, pitch;
20- } drm;
21-};
22-
23-struct swc_compositor_surface_state
24-{
25- struct swc_compositor * compositor;
26- struct wl_listener destroy_listener;
27- struct wl_listener event_listener;
28-};
29-
30-#endif
31-
+11,
-0
1@@ -2,7 +2,9 @@
2 #define SWC_UTIL_H 1
3
4 #include <stdbool.h>
5+#include <sys/param.h>
6 #include <wayland-server.h>
7+#include <pixman.h>
8
9 #ifndef offsetof
10 # define offsetof __builtin_offsetof
11@@ -15,6 +17,15 @@
12
13 void swc_remove_resource(struct wl_resource * resource);
14
15+static inline bool swc_rectangle_overlap
16+ (pixman_rectangle32_t * r1, pixman_rectangle32_t * r2)
17+{
18+ return (MAX(r1->x + r1->width, r2->x + r2->width) - MIN(r1->x, r2->x)
19+ < r1->width + r2->width)
20+ && (MAX(r1->y + r1->height, r2->y + r2->height) - MIN(r1->y, r2->y)
21+ < r1->height + r2->height);
22+}
23+
24 int swc_launch_open_input_device(int socket, const char * path, int flags);
25 bool swc_launch_drm_master(int socket, int fd, bool set);
26