commit 0dc0ed3
Michael Forney
·
2014-01-17 03:52:26 +0000 UTC
parent 4d25523
Implement screens
15 files changed,
+318,
-185
+44,
-69
1@@ -7,6 +7,7 @@
2 #include "output.h"
3 #include "pointer.h"
4 #include "region.h"
5+#include "screen.h"
6 #include "seat.h"
7 #include "surface.h"
8 #include "util.h"
9@@ -195,50 +196,51 @@ static void update_extents(struct swc_surface * surface)
10 view->border.damaged = true;
11 }
12
13-static void update_outputs(struct swc_surface * surface)
14+static void update_screens(struct swc_surface * surface)
15 {
16 struct view * view = (void *) surface->view;
17- struct swc_compositor * compositor = view->compositor;
18- uint32_t old_outputs = surface->outputs, new_outputs = 0,
19- entered_outputs, left_outputs, changed_outputs;
20+ uint32_t old_screens = surface->screens, new_screens = 0,
21+ entered_screens, left_screens, changed_screens;
22+ struct swc_screen_internal * screen;
23 struct swc_output * output;
24 struct wl_client * client;
25 struct wl_resource * resource;
26
27 if (view->mapped)
28 {
29- wl_list_for_each(output, &compositor->outputs, link)
30+ wl_list_for_each(screen, &swc.screens, link)
31 {
32- if (swc_rectangle_overlap(&output->geometry, &surface->geometry))
33- new_outputs |= SWC_OUTPUT_MASK(output);
34+ if (swc_rectangle_overlap(&screen->base.geometry, &surface->geometry))
35+ new_screens |= swc_screen_mask(screen);
36 }
37 }
38
39- if (new_outputs == old_outputs)
40+ if (new_screens == old_screens)
41 return;
42
43- entered_outputs = new_outputs & ~old_outputs;
44- left_outputs = old_outputs & ~new_outputs;
45- changed_outputs = old_outputs ^ new_outputs;
46+ entered_screens = new_screens & ~old_screens;
47+ left_screens = old_screens & ~new_screens;
48+ changed_screens = old_screens ^ new_screens;
49
50- wl_list_for_each(output, &compositor->outputs, link)
51+ wl_list_for_each(screen, &swc.screens, link)
52 {
53- if (!(changed_outputs & SWC_OUTPUT_MASK(output)))
54+ if (!(changed_screens & swc_screen_mask(screen)))
55 continue;
56
57+ output = CONTAINER_OF(screen->outputs.next, typeof(*output), link);
58 client = wl_resource_get_client(surface->resource);
59 resource = wl_resource_find_for_client(&output->resources, client);
60
61 if (resource)
62 {
63- if (entered_outputs & SWC_OUTPUT_MASK(output))
64+ if (entered_screens & swc_screen_mask(screen))
65 wl_surface_send_enter(surface->resource, resource);
66- else if (left_outputs & SWC_OUTPUT_MASK(output))
67+ else if (left_screens & swc_screen_mask(screen))
68 wl_surface_send_leave(surface->resource, resource);
69 }
70 }
71
72- surface->outputs = new_outputs;
73+ surface->screens = new_screens;
74 }
75
76 static void update(struct swc_view * view);
77@@ -258,7 +260,7 @@ static void handle_surface_event(struct wl_listener * listener, void * data)
78
79 update_extents(surface);
80 update(&view->base);
81- update_outputs(surface);
82+ update_screens(surface);
83
84 break;
85 }
86@@ -284,16 +286,15 @@ static void attach(struct swc_view * base, struct swc_buffer * buffer)
87 static void update(struct swc_view * base)
88 {
89 struct view * view = (void *) base;
90- struct swc_compositor * compositor = view->compositor;
91- struct swc_output * output;
92+ struct swc_screen_internal * screen;
93
94 if (!view->mapped)
95 return;
96
97- wl_list_for_each(output, &compositor->outputs, link)
98+ wl_list_for_each(screen, &swc.screens, link)
99 {
100- if (view->surface->outputs & SWC_OUTPUT_MASK(output))
101- swc_compositor_schedule_update(compositor, output);
102+ if (view->surface->screens & swc_screen_mask(screen))
103+ swc_compositor_schedule_update(view->compositor, screen);
104 }
105 }
106
107@@ -321,7 +322,7 @@ static void move(struct swc_view * base, int32_t x, int32_t y)
108
109 damage_below_surface(surface);
110 update(&view->base);
111- update_outputs(surface);
112+ update_screens(surface);
113 update(&view->base);
114 }
115 }
116@@ -382,7 +383,7 @@ void swc_compositor_surface_show(struct swc_surface * surface)
117 pixman_region32_clear(&view->clip);
118
119 damage_surface(surface);
120- update_outputs(surface);
121+ update_screens(surface);
122 update(&view->base);
123 wl_list_insert(&compositor->surfaces, &surface->link);
124 }
125@@ -403,7 +404,7 @@ void swc_compositor_surface_hide(struct swc_surface * surface)
126 view->mapped = false;
127
128 damage_below_surface(surface);
129- update_outputs(surface);
130+ update_screens(surface);
131 wl_list_remove(&surface->link);
132 }
133
134@@ -509,10 +510,12 @@ static void calculate_damage(struct swc_compositor * compositor)
135 pixman_region32_fini(&surface_opaque);
136 }
137
138-static void repaint_output(struct swc_compositor * compositor,
139- struct swc_output * output,
140+static void repaint_screen(struct swc_compositor * compositor,
141+ struct swc_screen_internal * screen,
142 pixman_region32_t * damage)
143 {
144+ struct swc_output * output
145+ = CONTAINER_OF(screen->outputs.next, typeof(*output), link);
146 pixman_region32_t base_damage;
147 struct render_target target;
148
149@@ -520,10 +523,8 @@ static void repaint_output(struct swc_compositor * compositor,
150 pixman_region32_subtract(&base_damage, damage, &compositor->opaque);
151
152 target.buffer = swc_plane_get_buffer(&output->framebuffer_plane);
153- target.geometry.x = output->framebuffer_plane.output->geometry.x
154- + output->framebuffer_plane.x;
155- target.geometry.y = output->framebuffer_plane.output->geometry.y
156- + output->framebuffer_plane.y;
157+ target.geometry.x = screen->base.geometry.x + output->framebuffer_plane.x;
158+ target.geometry.y = screen->base.geometry.y + output->framebuffer_plane.y;
159 target.geometry.width = target.buffer->width;
160 target.geometry.height = target.buffer->height;
161
162@@ -539,12 +540,13 @@ static void repaint_output(struct swc_compositor * compositor,
163 static void update_output_damage(struct swc_output * output,
164 pixman_region32_t * damage)
165 {
166+ struct swc_rectangle * geometry = &output->screen->base.geometry;
167+
168 pixman_region32_union
169 (&output->current_damage, &output->current_damage, damage);
170 pixman_region32_intersect_rect
171 (&output->current_damage, &output->current_damage,
172- output->geometry.x, output->geometry.y,
173- output->geometry.width, output->geometry.height);
174+ geometry->x, geometry->y, geometry->width, geometry->height);
175 }
176
177 static void flush_output_damage(struct swc_output * output,
178@@ -564,6 +566,7 @@ static void flush_output_damage(struct swc_output * output,
179 static void perform_update(void * data)
180 {
181 struct swc_compositor * compositor = data;
182+ struct swc_screen_internal * screen;
183 struct swc_output * output;
184 pixman_region32_t damage;
185 uint32_t updates = compositor->scheduled_updates
186@@ -577,19 +580,20 @@ static void perform_update(void * data)
187 calculate_damage(compositor);
188 pixman_region32_init(&damage);
189
190- wl_list_for_each(output, &compositor->outputs, link)
191+ wl_list_for_each(screen, &swc.screens, link)
192 {
193- if (!(compositor->scheduled_updates & SWC_OUTPUT_MASK(output)))
194+ if (!(compositor->scheduled_updates & swc_screen_mask(screen)))
195 continue;
196
197+ output = CONTAINER_OF(screen->outputs.next, typeof(*output), link);
198 update_output_damage(output, &compositor->damage);
199
200 /* Don't repaint the output if it is waiting for a page flip. */
201- if (compositor->pending_flips & SWC_OUTPUT_MASK(output))
202+ if (compositor->pending_flips & swc_screen_mask(screen))
203 continue;
204
205 flush_output_damage(output, &damage);
206- repaint_output(compositor, output, &damage);
207+ repaint_screen(compositor, screen, &damage);
208 }
209
210 pixman_region32_fini(&damage);
211@@ -725,7 +729,6 @@ bool swc_compositor_initialize(struct swc_compositor * compositor,
212 struct wl_display * display,
213 struct wl_event_loop * event_loop)
214 {
215- struct wl_list * outputs;
216 uint32_t keysym;
217
218 compositor->display = display;
219@@ -739,20 +742,6 @@ bool swc_compositor_initialize(struct swc_compositor * compositor,
220
221 wl_signal_add(&swc.drm->event_signal, &compositor->drm_listener);
222
223- outputs = swc_drm_create_outputs();
224-
225- if (outputs)
226- {
227- wl_list_init(&compositor->outputs);
228- wl_list_insert_list(&compositor->outputs, outputs);
229- free(outputs);
230- }
231- else
232- {
233- printf("could not create outputs\n");
234- return false;
235- }
236-
237 pixman_region32_init(&compositor->damage);
238 pixman_region32_init(&compositor->opaque);
239 wl_list_init(&compositor->surfaces);
240@@ -774,38 +763,24 @@ bool swc_compositor_initialize(struct swc_compositor * compositor,
241
242 void swc_compositor_finish(struct swc_compositor * compositor)
243 {
244- struct swc_output * output, * tmp;
245-
246- wl_list_for_each_safe(output, tmp, &compositor->outputs, link)
247- {
248- swc_output_finish(output);
249- free(output);
250- }
251 }
252
253 void swc_compositor_add_globals(struct swc_compositor * compositor,
254 struct wl_display * display)
255 {
256- struct swc_output * output;
257-
258 wl_global_create(display, &wl_compositor_interface, 3, compositor,
259 &bind_compositor);
260-
261- wl_list_for_each(output, &compositor->outputs, link)
262- {
263- swc_output_add_globals(output, display);
264- }
265 }
266
267 void swc_compositor_schedule_update(struct swc_compositor * compositor,
268- struct swc_output * output)
269+ struct swc_screen_internal * screen)
270 {
271 bool update_scheduled = compositor->scheduled_updates != 0;
272
273- if (compositor->scheduled_updates & SWC_OUTPUT_MASK(output))
274+ if (compositor->scheduled_updates & swc_screen_mask(screen))
275 return;
276
277- compositor->scheduled_updates |= SWC_OUTPUT_MASK(output);
278+ compositor->scheduled_updates |= swc_screen_mask(screen);
279
280 if (!update_scheduled)
281 {
+2,
-4
1@@ -5,13 +5,11 @@
2
3 #include <wayland-server.h>
4
5-struct swc_output;
6+struct swc_screen_internal;
7
8 struct swc_compositor
9 {
10 struct wl_display * display;
11-
12- struct wl_list outputs;
13 struct wl_list surfaces;
14
15 /* Internal state related to repainting the screen. */
16@@ -44,7 +42,7 @@ void swc_compositor_add_globals(struct swc_compositor * compositor,
17 struct wl_display * display);
18
19 void swc_compositor_schedule_update(struct swc_compositor * compositor,
20- struct swc_output * output);
21+ struct swc_screen_internal * screen);
22
23 bool swc_compositor_add_surface(struct swc_compositor * compositor,
24 struct swc_surface * surface);
+17,
-40
1@@ -25,6 +25,7 @@
2 #include "event.h"
3 #include "internal.h"
4 #include "output.h"
5+#include "screen.h"
6 #include "wayland_buffer.h"
7
8 #include <stdio.h>
9@@ -47,7 +48,7 @@ static struct
10 uint32_t id;
11 char * path;
12
13- uint32_t taken_output_ids;
14+ uint32_t taken_ids;
15
16 struct wl_global * global;
17 struct wl_event_source * event_source;
18@@ -248,7 +249,7 @@ static bool find_available_crtc(drmModeRes * resources,
19
20 static bool find_available_id(uint32_t * id)
21 {
22- uint32_t index = __builtin_ffsl(~drm.taken_output_ids);
23+ uint32_t index = __builtin_ffsl(~drm.taken_ids);
24
25 if (index == 0)
26 return false;
27@@ -335,7 +336,7 @@ bool swc_drm_initialize(const char * seat_name)
28 goto error0;
29 }
30
31- drm.taken_output_ids = 0;
32+ drm.taken_ids = 0;
33 drm.path = strdup(udev_device_get_devnode(drm_device));
34 udev_device_unref(drm_device);
35 swc.drm->fd = swc_launch_open_device(drm.path, O_RDWR | O_CLOEXEC);
36@@ -402,25 +403,19 @@ void swc_drm_finalize()
37 close(swc.drm->fd);
38 }
39
40-struct wl_list * swc_drm_create_outputs()
41+bool swc_drm_create_screens(struct wl_list * screens)
42 {
43 drmModeRes * resources;
44 drmModeConnector * connector;
45 drmModeCrtc * crtc;
46 uint32_t index;
47- uint32_t x = 0;
48 struct swc_output * output;
49- struct wl_list * outputs;
50 uint32_t taken_crtcs = 0;
51
52- outputs = malloc(sizeof(struct wl_list));
53- wl_list_init(outputs);
54-
55- resources = drmModeGetResources(swc.drm->fd);
56- if (!resources)
57+ if (!(resources = drmModeGetResources(swc.drm->fd)))
58 {
59 printf("couldn't get DRM resources\n");
60- goto error;
61+ return false;
62 }
63
64 printf("crtc count: %u\n", resources->count_crtcs);
65@@ -444,7 +439,8 @@ struct wl_list * swc_drm_create_outputs()
66 drmModeFreeEncoder(encoder);
67 }
68
69- for (index = 0; index < resources->count_connectors; ++index)
70+ for (index = 0; index < resources->count_connectors;
71+ ++index, drmModeFreeConnector(connector))
72 {
73 connector = drmModeGetConnector(swc.drm->fd,
74 resources->connectors[index]);
75@@ -472,41 +468,22 @@ struct wl_list * swc_drm_create_outputs()
76 break;
77 }
78
79- output = malloc(sizeof(struct swc_output));
80-
81- output->geometry.x = x;
82- output->geometry.y = 0;
83-
84- if (!swc_output_initialize(output, id,
85- resources->crtcs[crtc_index], connector))
86- {
87- drmModeFreeConnector(connector);
88- free(output);
89+ if (!(output = swc_output_new(resources->crtcs[crtc_index], connector)))
90 continue;
91- }
92+
93+ output->screen = swc_screen_new(resources->crtcs[crtc_index],
94+ output);
95+ output->screen->id = id;
96
97 taken_crtcs |= 1 << crtc_index;
98- drm.taken_output_ids |= 1 << id;
99+ drm.taken_ids |= 1 << id;
100
101- wl_list_insert(outputs, &output->link);
102- x += output->geometry.width;
103+ wl_list_insert(screens, &output->screen->link);
104 }
105-
106- drmModeFreeConnector(connector);
107 }
108
109 drmModeFreeResources(resources);
110
111- if (wl_list_empty(outputs))
112- {
113- printf("couldn't find any outputs\n");
114- goto error;
115- }
116-
117- return outputs;
118-
119- error:
120- free(outputs);
121- return NULL;
122+ return true;
123 }
124
+1,
-1
1@@ -27,7 +27,7 @@ struct swc_drm
2 bool swc_drm_initialize(const char * seat);
3 void swc_drm_finalize();
4
5-struct wl_list * swc_drm_create_outputs();
6+bool swc_drm_create_screens(struct wl_list * screens);
7
8 #endif
9
+3,
-0
1@@ -24,6 +24,8 @@
2 #ifndef SWC_INTERNAL_H
3 #define SWC_INTERNAL_H
4
5+#include <wayland-util.h>
6+
7 struct swc
8 {
9 struct wl_display * display;
10@@ -34,6 +36,7 @@ struct swc
11
12 const struct swc_seat_global * const seat;
13 const struct swc_bindings_global * const bindings;
14+ struct wl_list screens;
15 struct swc_compositor * compositor;
16 struct swc_shm * const shm;
17 struct swc_drm * const drm;
+2,
-1
1@@ -59,7 +59,8 @@ SWC_SOURCES += \
2 libswc/window.c \
3 libswc/shell.c \
4 libswc/shell_surface.c \
5- libswc/bindings.c
6+ libswc/bindings.c \
7+ libswc/screen.c
8
9 ifeq ($(ENABLE_XWAYLAND),1)
10 $(dir)_CFLAGS += -DENABLE_XWAYLAND
+37,
-26
1@@ -2,6 +2,7 @@
2 #include "drm.h"
3 #include "internal.h"
4 #include "mode.h"
5+#include "screen.h"
6 #include "util.h"
7
8 #include <stdio.h>
9@@ -14,6 +15,7 @@ static void bind_output(struct wl_client * client, void * data,
10 uint32_t version, uint32_t id)
11 {
12 struct swc_output * output = data;
13+ struct swc_screen_internal * screen = output->screen;
14 struct swc_mode * mode;
15 struct wl_resource * resource;
16 uint32_t flags;
17@@ -26,9 +28,10 @@ static void bind_output(struct wl_client * client, void * data,
18 &swc_remove_resource);
19 wl_list_insert(&output->resources, wl_resource_get_link(resource));
20
21- wl_output_send_geometry(resource, output->geometry.x, output->geometry.y,
22- output->physical_width, output->physical_height, 0, "unknown",
23- "unknown", WL_OUTPUT_TRANSFORM_NORMAL);
24+ wl_output_send_geometry
25+ (resource, screen->base.geometry.x, screen->base.geometry.y,
26+ output->physical_width, output->physical_height, 0, "unknown",
27+ "unknown", WL_OUTPUT_TRANSFORM_NORMAL);
28
29 wl_array_for_each(mode, &output->modes)
30 {
31@@ -46,18 +49,29 @@ static void bind_output(struct wl_client * client, void * data,
32 wl_output_send_done(resource);
33 }
34
35-bool swc_output_initialize(struct swc_output * output,
36- uint32_t id, uint32_t crtc_id,
37- drmModeConnector * connector)
38+struct swc_output * swc_output_new(uint32_t crtc_id, drmModeConnector * connector)
39 {
40+ struct swc_output * output;
41 drmModeEncoder * encoder;
42 drmModeCrtc * current_crtc;
43 struct swc_mode * modes;
44 uint32_t index;
45
46- printf("initializing output with id: %u\n", id);
47+ if (!(output = malloc(sizeof *output)))
48+ {
49+ ERROR("Failed to allocated output\n");
50+ goto error0;
51+ }
52+
53+ output->global = wl_global_create(swc.display, &wl_output_interface, 2,
54+ output, &bind_output);
55+
56+ if (!output->global)
57+ {
58+ ERROR("Failed to create output global\n");
59+ goto error1;
60+ }
61
62- output->id = id;
63 output->physical_width = connector->mmWidth;
64 output->physical_height = connector->mmHeight;
65
66@@ -66,8 +80,8 @@ bool swc_output_initialize(struct swc_output * output,
67 pixman_region32_init(&output->current_damage);
68 pixman_region32_init(&output->previous_damage);
69
70- output->crtc_id = crtc_id;
71- output->connector_id = connector->connector_id;
72+ output->crtc = crtc_id;
73+ output->connector = connector->connector_id;
74
75 /* Determine the current CRTC of this output. */
76 encoder = drmModeGetEncoder(swc.drm->fd, connector->encoder_id);
77@@ -90,9 +104,6 @@ bool swc_output_initialize(struct swc_output * output,
78 if (output->preferred_mode)
79 output->current_mode = output->preferred_mode;
80
81- output->geometry.width = output->current_mode->width;
82- output->geometry.height = output->current_mode->height;
83-
84 output->original_state.crtc = current_crtc;
85
86 /* Create output planes */
87@@ -100,22 +111,26 @@ bool swc_output_initialize(struct swc_output * output,
88 &swc_framebuffer_plane, output))
89 {
90 printf("failed to initialize framebuffer plane\n");
91- goto error_base;
92+ goto error2;
93 }
94
95 if (!swc_plane_initialize(&output->cursor_plane, &swc_cursor_plane, output))
96 {
97 printf("failed to initialize cursor plane\n");
98- goto error_base;
99+ goto error2;
100 }
101
102- return true;
103+ return output;
104
105- error_base:
106- return false;
107+ error2:
108+ wl_global_destroy(output->global);
109+ error1:
110+ free(output);
111+ error0:
112+ return NULL;
113 }
114
115-void swc_output_finish(struct swc_output * output)
116+void swc_output_destroy(struct swc_output * output)
117 {
118 struct swc_mode * mode;
119 drmModeCrtc * crtc = output->original_state.crtc;
120@@ -125,13 +140,9 @@ void swc_output_finish(struct swc_output * output)
121 wl_array_release(&output->modes);
122
123 drmModeSetCrtc(swc.drm->fd, crtc->crtc_id, crtc->buffer_id, crtc->x,
124- crtc->y, &output->connector_id, 1, &crtc->mode);
125+ crtc->y, &output->connector, 1, &crtc->mode);
126 drmModeFreeCrtc(crtc);
127-}
128-
129-void swc_output_add_globals(struct swc_output * output,
130- struct wl_display * display)
131-{
132- wl_global_create(display, &wl_output_interface, 2, output, &bind_output);
133+ wl_global_destroy(output->global);
134+ free(output);
135 }
136
+7,
-15
1@@ -8,16 +8,13 @@
2 #include <wayland-util.h>
3 #include <xf86drmMode.h>
4
5-#define SWC_OUTPUT_MASK(output) (1 << (output)->id)
6-
7 struct wl_display;
8
9 struct swc_output
10 {
11- uint32_t id;
12+ struct swc_screen_internal * screen;
13
14- /* The geometry of this output */
15- struct swc_rectangle geometry;
16+ /* The physical dimensions (in mm) of this output */
17 uint32_t physical_width, physical_height;
18
19 struct wl_array modes;
20@@ -29,26 +26,21 @@ struct swc_output
21
22 pixman_region32_t current_damage, previous_damage;
23
24- /* The CRTC and connector we are using to drive this output */
25- uint32_t crtc_id;
26- uint32_t connector_id;
27+ /* The DRM connector corresponding to this output */
28+ uint32_t crtc, connector;
29
30 struct
31 {
32 drmModeCrtc * crtc;
33 } original_state;
34
35+ struct wl_global * global;
36 struct wl_list resources;
37 struct wl_list link;
38 };
39
40-bool swc_output_initialize(struct swc_output * output, uint32_t id, uint32_t crtc_id,
41- drmModeConnector * connector);
42-
43-void swc_output_finish(struct swc_output * output);
44-
45-void swc_output_add_globals(struct swc_output * output,
46- struct wl_display * display);
47+struct swc_output * swc_output_new(uint32_t crtc_id, drmModeConnector * connector);
48+void swc_output_destroy(struct swc_output * output);
49
50 #endif
51
+8,
-6
1@@ -26,6 +26,7 @@
2 #include "internal.h"
3 #include "mode.h"
4 #include "output.h"
5+#include "screen.h"
6
7 #include <stdlib.h>
8 #include <stdio.h>
9@@ -43,8 +44,8 @@ static bool framebuffer_initialize(struct swc_plane * plane)
10 {
11 struct framebuffer * fb = swc_double_buffer_front(&plane->double_buffer);
12
13- return drmModeSetCrtc(swc.drm->fd, plane->output->crtc_id,
14- fb->id, 0, 0, &plane->output->connector_id, 1,
15+ return drmModeSetCrtc(swc.drm->fd, plane->output->crtc,
16+ fb->id, 0, 0, &plane->output->connector, 1,
17 &plane->output->current_mode->info) == 0;
18 }
19
20@@ -59,7 +60,8 @@ static void * framebuffer_create_buffer(struct swc_plane * plane)
21 goto error0;
22
23 buffer = wld_create_buffer(swc.drm->context,
24- output->geometry.width, output->geometry.height,
25+ output->screen->base.geometry.width,
26+ output->screen->base.geometry.height,
27 WLD_FORMAT_XRGB8888);
28
29 if (!buffer)
30@@ -109,7 +111,7 @@ static bool framebuffer_flip(struct swc_plane * plane)
31 struct swc_output * output = plane->output;
32 struct framebuffer * fb = swc_double_buffer_back(&plane->double_buffer);
33
34- return drmModePageFlip(swc.drm->fd, output->crtc_id, fb->id,
35+ return drmModePageFlip(swc.drm->fd, output->crtc, fb->id,
36 DRM_MODE_PAGE_FLIP_EVENT, output) == 0;
37 }
38
39@@ -149,13 +151,13 @@ static bool cursor_flip(struct swc_plane * plane)
40 union wld_object object;
41
42 wld_export(buffer, WLD_DRM_OBJECT_HANDLE, &object);
43- return drmModeSetCursor(swc.drm->fd, plane->output->crtc_id,
44+ return drmModeSetCursor(swc.drm->fd, plane->output->crtc,
45 object.u32, 64, 64) == 0;
46 }
47
48 static bool cursor_move(struct swc_plane * plane, int32_t x, int32_t y)
49 {
50- return drmModeMoveCursor(swc.drm->fd, plane->output->crtc_id, x, y) == 0;
51+ return drmModeMoveCursor(swc.drm->fd, plane->output->crtc, x, y) == 0;
52 }
53
54 const struct swc_plane_interface swc_cursor_plane = {
+94,
-0
1@@ -0,0 +1,94 @@
2+/* swc: libswc/screen.c
3+ *
4+ * Copyright (c) 2013, 2014 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 "screen.h"
26+#include "drm.h"
27+#include "internal.h"
28+#include "mode.h"
29+#include "output.h"
30+
31+#include <stdlib.h>
32+#include <sys/param.h>
33+
34+#define INTERNAL(screen) ((struct swc_screen_internal *) (screen))
35+
36+bool swc_screens_initialize()
37+{
38+ wl_list_init(&swc.screens);
39+
40+ if (!swc_drm_create_screens(&swc.screens))
41+ return false;
42+
43+ if (wl_list_empty(&swc.screens))
44+ return false;
45+
46+ return true;
47+}
48+
49+void swc_screens_finalize()
50+{
51+ struct swc_screen_internal * screen, * tmp;
52+
53+ wl_list_for_each_safe(screen, tmp, &swc.screens, link)
54+ free(screen);
55+}
56+
57+struct swc_screen_internal * swc_screen_new(uint32_t crtc,
58+ struct swc_output * output)
59+{
60+ struct swc_screen_internal * screen;
61+ int32_t x = 0;
62+
63+ /* Simple heuristic for initial screen positioning. */
64+ wl_list_for_each(screen, &swc.screens, link)
65+ x = MAX(x, screen->base.geometry.x + screen->base.geometry.width);
66+
67+ if (!(screen = malloc(sizeof *screen)))
68+ goto error0;
69+
70+ screen->base.geometry.x = x;
71+ screen->base.geometry.y = 0;
72+ screen->base.geometry.width = output->preferred_mode->width;
73+ screen->base.geometry.height = output->preferred_mode->height;
74+ screen->base.usable_geometry = screen->base.geometry;
75+ wl_signal_init(&screen->base.event_signal);
76+ wl_list_init(&screen->outputs);
77+ wl_list_insert(&INTERNAL(screen)->outputs, &output->link);
78+
79+ swc.manager->new_screen(&screen->base);
80+
81+ return screen;
82+
83+ error0:
84+ return NULL;
85+}
86+
87+void swc_screen_destroy(struct swc_screen_internal * screen)
88+{
89+ struct swc_output * output, * next;
90+
91+ wl_list_for_each_safe(output, next, &screen->outputs, link)
92+ swc_output_destroy(output);
93+ free(screen);
94+}
95+
+56,
-0
1@@ -0,0 +1,56 @@
2+/* swc: libswc/screen.h
3+ *
4+ * Copyright (c) 2013, 2014 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_SCREEN_H
26+#define SWC_SCREEN_H
27+
28+#include "swc.h"
29+
30+#include <wayland-util.h>
31+
32+struct swc_output;
33+
34+struct swc_screen_internal
35+{
36+ struct swc_screen base;
37+
38+ uint8_t id;
39+
40+ struct wl_list outputs;
41+ struct wl_list modifiers;
42+ struct wl_list link;
43+};
44+
45+bool swc_screens_initialize();
46+void swc_screens_finalize();
47+
48+struct swc_screen_internal * swc_screen_new(uint32_t crtc,
49+ struct swc_output * output);
50+void swc_screen_destroy(struct swc_screen_internal * screen);
51+static inline uint32_t swc_screen_mask(struct swc_screen_internal * screen)
52+{
53+ return 1 << screen->id;
54+}
55+
56+#endif
57+
+1,
-1
1@@ -383,7 +383,7 @@ struct swc_surface * swc_surface_new(struct wl_client * client,
2 return NULL;
3
4 /* Initialize the surface. */
5- surface->outputs = 0;
6+ surface->screens = 0;
7 surface->geometry.x = 0;
8 surface->geometry.y = 0;
9 surface->geometry.width = 0;
+1,
-1
1@@ -90,7 +90,7 @@ struct swc_surface
2 struct wl_listener view_listener;
3 void * view_state;
4
5- uint32_t outputs;
6+ uint32_t screens;
7 struct swc_rectangle geometry;
8
9 struct wl_signal event_signal;
+28,
-17
1@@ -28,11 +28,12 @@
2 #include "drm.h"
3 #include "internal.h"
4 #include "keyboard.h"
5-#include "output.h"
6 #include "pointer.h"
7+#include "screen.h"
8 #include "seat.h"
9 #include "shell.h"
10 #include "shm.h"
11+#include "util.h"
12 #include "window.h"
13 #ifdef ENABLE_XWAYLAND
14 # include "xserver.h"
15@@ -57,7 +58,8 @@ struct swc swc = {
16 static void setup_compositor()
17 {
18 pixman_region32_t pointer_region;
19- struct swc_output * output;
20+ struct swc_screen_internal * screen;
21+ struct swc_rectangle * geometry;
22
23 wl_list_insert(&swc.seat->keyboard->handlers,
24 &swc.bindings->keyboard_handler->link);
25@@ -68,12 +70,12 @@ static void setup_compositor()
26 /* Calculate pointer region */
27 pixman_region32_init(&pointer_region);
28
29- wl_list_for_each(output, &compositor.outputs, link)
30+ wl_list_for_each(screen, &swc.screens, link)
31 {
32+ geometry = &screen->base.geometry;
33 pixman_region32_union_rect(&pointer_region, &pointer_region,
34- output->geometry.x, output->geometry.y,
35- output->geometry.width,
36- output->geometry.height);
37+ geometry->x, geometry->y,
38+ geometry->width, geometry->height);
39 }
40
41 swc_pointer_set_region(swc.seat->pointer, &pointer_region);
42@@ -108,10 +110,16 @@ bool swc_initialize(struct wl_display * display,
43 goto error2;
44 }
45
46+ if (!swc_screens_initialize())
47+ {
48+ ERROR("Could not initialize screens\n");
49+ goto error3;
50+ }
51+
52 if (!swc_compositor_initialize(&compositor, display, swc.event_loop))
53 {
54 ERROR("Could not initialize compositor\n");
55- goto error3;
56+ goto error4;
57 }
58
59 swc_compositor_add_globals(&compositor, display);
60@@ -119,32 +127,32 @@ bool swc_initialize(struct wl_display * display,
61 if (!swc_data_device_manager_initialize())
62 {
63 ERROR("Could not initialize data device manager\n");
64- goto error4;
65+ goto error5;
66 }
67
68 if (!swc_seat_initialize())
69 {
70 ERROR("Could not initialize seat\n");
71- goto error5;
72+ goto error6;
73 }
74
75 if (!swc_bindings_initialize())
76 {
77 ERROR("Could not initialize bindings\n");
78- goto error6;
79+ goto error7;
80 }
81
82 if (!swc_shell_initialize())
83 {
84 ERROR("Could not initialize shell\n");
85- goto error7;
86+ goto error8;
87 }
88
89 #ifdef ENABLE_XWAYLAND
90 if (!swc_xserver_initialize())
91 {
92 ERROR("Could not initialize xwayland\n");
93- goto error8;
94+ goto error9;
95 }
96 #endif
97
98@@ -152,16 +160,18 @@ bool swc_initialize(struct wl_display * display,
99
100 return true;
101
102- error8:
103+ error9:
104 swc_shell_finalize();
105- error7:
106+ error8:
107 swc_bindings_finalize();
108- error6:
109+ error7:
110 swc_seat_finalize();
111- error5:
112+ error6:
113 swc_data_device_manager_finalize();
114- error4:
115+ error5:
116 swc_compositor_finish(&compositor);
117+ error4:
118+ swc_screens_finalize();
119 error3:
120 swc_shm_finalize();
121 error2:
122@@ -183,6 +193,7 @@ void swc_finalize()
123 swc_seat_finalize();
124 swc_data_device_manager_finalize();
125 swc_compositor_finish(&compositor);
126+ swc_screens_finalize();
127 swc_shm_finalize();
128 swc_drm_finalize();
129 udev_unref(swc.udev);
+17,
-4
1@@ -134,12 +134,25 @@ void swc_window_set_border(struct swc_window * window,
2 enum
3 {
4 /**
5- * Sent when either the total_geometry or usable_geometry of the screen has
6+ * Sent when the screen is about to be destroyed.
7+ *
8+ * After this event is sent, the screen is not longer valid.
9+ */
10+ SWC_SCREEN_DESTROYED,
11+
12+ /**
13+ * Sent when the total area of the screen is changed.
14+ */
15+ SWC_SCREEN_GEOMETRY_CHANGED,
16+
17+ /**
18+ * Sent when the geometry of the screen available for laying out windows is
19 * changed.
20 *
21- * The data member of this event points to the rectangle which changed.
22+ * Display servers should respond to this event by making sure all visible
23+ * windows are within this area.
24 */
25- SWC_SCREEN_GEOMETRY_CHANGED
26+ SWC_SCREEN_USABLE_GEOMETRY_CHANGED
27 };
28
29 struct swc_screen
30@@ -149,7 +162,7 @@ struct swc_screen
31 /**
32 * The total area of the screen.
33 */
34- struct swc_rectangle total_geometry;
35+ struct swc_rectangle geometry;
36
37 /**
38 * The area of the screen available for placing windows.