commit 170445e
Michael Forney
·
2014-01-17 01:46:12 +0000 UTC
parent 300de28
Refactor planes
17 files changed,
+664,
-468
+201,
-104
1@@ -20,6 +20,15 @@
2 #include <wld/drm.h>
3 #include <xkbcommon/xkbcommon-keysyms.h>
4
5+struct screen
6+{
7+ struct wld_surface * surface;
8+ struct wld_buffer * next_buffer, * current_buffer;
9+ struct swc_view * view;
10+ struct wl_listener view_listener;
11+ struct wl_listener event_listener;
12+};
13+
14 struct view
15 {
16 struct swc_view base;
17@@ -44,12 +53,156 @@ struct view
18 struct wl_list link;
19 };
20
21+static void perform_update(void * data);
22+
23+static void buffer_destroy(void * data)
24+{
25+ struct swc_buffer * buffer = data;
26+
27+ swc_buffer_finalize(buffer);
28+ free(buffer);
29+}
30+
31+struct swc_buffer * buffer_get(struct wld_buffer * wld)
32+{
33+ if (wld->destroy_data)
34+ return wld->data;
35+
36+ struct swc_buffer * buffer;
37+
38+ if (!(buffer = malloc(sizeof *buffer)))
39+ goto error0;
40+
41+ if (!swc_buffer_initialize(buffer, wld))
42+ goto error1;
43+
44+ wld->data = buffer;
45+ wld->destroy_data = &buffer_destroy;
46+
47+ return buffer;
48+
49+error1:
50+ free(buffer);
51+error0:
52+ return NULL;
53+}
54+
55+static void handle_screen_event(struct wl_listener * listener, void * data)
56+{
57+ struct swc_event * event = data;
58+
59+ if (event->type == SWC_SCREEN_DESTROYED)
60+ {
61+ struct screen * screen
62+ = CONTAINER_OF(listener, typeof(*screen), event_listener);
63+
64+ wld_destroy_surface(screen->surface);
65+ free(screen);
66+ }
67+}
68+
69+static struct screen * screen_get(struct swc_screen * base)
70+{
71+ struct wl_listener * listener
72+ = wl_signal_get(&base->event_signal, &handle_screen_event);
73+ struct screen * screen;
74+
75+ return listener ? CONTAINER_OF(listener, typeof(*screen), event_listener)
76+ : NULL;
77+}
78+
79+static void handle_screen_view_event(struct wl_listener * listener, void * data)
80+{
81+ struct swc_event * event = data;
82+ struct swc_view_event_data * event_data = event->data;
83+
84+ switch (event->type)
85+ {
86+ case SWC_VIEW_EVENT_FRAME:
87+ {
88+ struct swc_screen_internal * base = CONTAINER_OF
89+ (event_data->view, typeof(*base), planes.framebuffer.view);
90+ struct screen * screen;
91+ struct view * view;
92+
93+ if (!(screen = screen_get(&base->base)))
94+ return;
95+
96+ swc.compositor->pending_flips &= ~swc_screen_mask(base);
97+
98+ if (swc.compositor->pending_flips == 0)
99+ {
100+ wl_list_for_each(view, &swc.compositor->views, link)
101+ swc_view_frame(&view->base, event_data->frame.time);
102+ }
103+
104+ if (screen->current_buffer)
105+ wld_surface_release(screen->surface, screen->current_buffer);
106+
107+ screen->current_buffer = screen->next_buffer;
108+
109+ /* If we had scheduled updates that couldn't run because we were
110+ * waiting on a page flip, run them now. */
111+ if (swc.compositor->scheduled_updates)
112+ perform_update(swc.compositor);
113+ break;
114+ }
115+ }
116+}
117+
118+static bool screen_swap_buffers(struct screen * screen)
119+{
120+ struct swc_buffer * buffer;
121+
122+ screen->next_buffer = wld_surface_take(screen->surface);
123+ buffer = buffer_get(screen->next_buffer);
124+
125+ if (!swc_view_attach(screen->view, buffer))
126+ {
127+ ERROR("Failed to attach next frame to screen\n");
128+ return false;
129+ }
130+
131+ return true;
132+}
133+
134+static struct screen * screen_new(struct swc_screen_internal * base)
135+{
136+ struct screen * screen;
137+
138+ if (!(screen = malloc(sizeof *screen)))
139+ goto error0;
140+
141+ screen->surface = wld_create_surface(swc.drm->context,
142+ base->base.geometry.width,
143+ base->base.geometry.height,
144+ WLD_FORMAT_XRGB8888);
145+
146+ if (!screen->surface)
147+ goto error1;
148+
149+ screen->view = &base->planes.framebuffer.view;
150+ screen->view_listener.notify = &handle_screen_view_event;
151+ wl_signal_add(&screen->view->event_signal, &screen->view_listener);
152+ screen->event_listener.notify = &handle_screen_event;
153+ wl_signal_add(&base->base.event_signal, &screen->event_listener);
154+ screen->current_buffer = NULL;
155+ screen_swap_buffers(screen);
156+
157+ return screen;
158+
159+error1:
160+ free(screen);
161+error0:
162+ return NULL;
163+}
164+
165 /* Rendering {{{ */
166
167 struct render_target
168 {
169- struct wld_buffer * buffer;
170- struct swc_rectangle geometry;
171+ struct wld_surface * surface;
172+ const struct swc_rectangle * geometry;
173 uint32_t mask;
174 };
175
176@@ -78,8 +231,8 @@ static void repaint_view(struct render_target * target, struct view * view,
177 {
178 pixman_region32_translate(&view_damage, -geometry->x, -geometry->y);
179 wld_copy_region(swc.drm->renderer, view->base.buffer->wld,
180- geometry->x - target->geometry.x,
181- geometry->y - target->geometry.y, &view_damage);
182+ geometry->x - target->geometry->x,
183+ geometry->y - target->geometry->y, &view_damage);
184 }
185
186 pixman_region32_fini(&view_damage);
187@@ -90,7 +243,7 @@ static void repaint_view(struct render_target * target, struct view * view,
188 DEBUG("\t\tRedrawing border\n");
189
190 pixman_region32_translate(&border_damage,
191- -target->geometry.x, -target->geometry.y);
192+ -target->geometry->x, -target->geometry->y);
193 wld_fill_region(swc.drm->renderer, view->border.color, &border_damage);
194 }
195
196@@ -105,14 +258,16 @@ static void renderer_repaint(struct render_target * target,
197 struct view * view;
198
199 DEBUG("Rendering to target { x: %d, y: %d, w: %u, h: %u }\n",
200- target->geometry.x, target->geometry.y,
201- target->geometry.width, target->geometry.height);
202+ target->geometry->x, target->geometry->y,
203+ target->geometry->width, target->geometry->height);
204+
205+ wld_set_target_surface(swc.drm->renderer, target->surface);
206
207 /* Paint base damage black. */
208 if (pixman_region32_not_empty(base_damage))
209 {
210 pixman_region32_translate(base_damage,
211- -target->geometry.x, -target->geometry.y);
212+ -target->geometry->x, -target->geometry->y);
213 wld_fill_region(swc.drm->renderer, 0xff000000, base_damage);
214 }
215
216@@ -445,65 +600,53 @@ static void calculate_damage(struct swc_compositor * compositor)
217 pixman_region32_fini(&surface_opaque);
218 }
219
220-static void repaint_screen(struct swc_compositor * compositor,
221- struct swc_screen_internal * screen,
222- pixman_region32_t * damage)
223+static void update_screen(struct swc_compositor * compositor,
224+ struct swc_screen_internal * base)
225 {
226- struct swc_output * output
227- = CONTAINER_OF(screen->outputs.next, typeof(*output), link);
228- pixman_region32_t base_damage;
229- struct render_target target;
230-
231- pixman_region32_init(&base_damage);
232- pixman_region32_subtract(&base_damage, damage, &compositor->opaque);
233-
234- target.buffer = swc_plane_get_buffer(&output->framebuffer_plane);
235- target.geometry.x = screen->base.geometry.x + output->framebuffer_plane.x;
236- target.geometry.y = screen->base.geometry.y + output->framebuffer_plane.y;
237- target.geometry.width = target.buffer->width;
238- target.geometry.height = target.buffer->height;
239- target.mask = swc_screen_mask(screen);
240+ struct screen * screen;
241+ const struct swc_rectangle * geometry = &base->base.geometry;
242+ pixman_region32_t damage;
243
244- renderer_repaint(&target, damage, &base_damage, &compositor->views);
245+ if (!(compositor->scheduled_updates & swc_screen_mask(base)))
246+ return;
247
248- pixman_region32_fini(&base_damage);
249+ if (!(screen = screen_get(&base->base)))
250+ return;
251
252- if (!swc_plane_flip(&output->framebuffer_plane))
253- fprintf(stderr, "Plane flip failed\n");
254-}
255+ pixman_region32_init(&damage);
256+ pixman_region32_intersect_rect(&damage, &compositor->damage,
257+ geometry->x, geometry->y,
258+ geometry->width, geometry->height);
259+ pixman_region32_translate(&damage, -geometry->x, -geometry->y);
260+ pixman_region32_union(&screen->next_buffer->damage,
261+ &screen->next_buffer->damage, &damage);
262+
263+ /* Don't repaint the screen if it is waiting for a page flip. */
264+ if (compositor->pending_flips & swc_screen_mask(base))
265+ return;
266
267-static void update_output_damage(struct swc_output * output,
268- pixman_region32_t * damage)
269-{
270- struct swc_rectangle * geometry = &output->screen->base.geometry;
271+ struct render_target target;
272+ pixman_region32_t * total_damage, base_damage;
273
274- pixman_region32_union
275- (&output->current_damage, &output->current_damage, damage);
276- pixman_region32_intersect_rect
277- (&output->current_damage, &output->current_damage,
278- geometry->x, geometry->y, geometry->width, geometry->height);
279-}
280+ total_damage = wld_surface_damage(screen->surface,
281+ &screen->next_buffer->damage);
282+ pixman_region32_translate(total_damage, geometry->x, geometry->y);
283+ pixman_region32_init(&base_damage);
284+ pixman_region32_subtract(&base_damage, total_damage, &compositor->opaque);
285
286-static void flush_output_damage(struct swc_output * output,
287- pixman_region32_t * damage)
288-{
289- /* The total damage is composed of the damage from the new frame, and the
290- * damage from the last frame. */
291- pixman_region32_union(damage,
292- &output->current_damage, &output->previous_damage);
293+ target.surface = screen->surface;
294+ target.mask = swc_screen_mask(base);
295+ target.geometry = geometry;
296
297- /* We must save the damage from the previous frame because the back buffer
298- * is also damaged in this region. */
299- pixman_region32_copy(&output->previous_damage, &output->current_damage);
300- pixman_region32_clear(&output->current_damage);
301+ renderer_repaint(&target, total_damage, &base_damage, &compositor->views);
302+ pixman_region32_fini(&base_damage);
303+ screen_swap_buffers(screen);
304 }
305
306 static void perform_update(void * data)
307 {
308 struct swc_compositor * compositor = data;
309 struct swc_screen_internal * screen;
310- struct swc_output * output;
311- pixman_region32_t damage;
312 uint32_t updates = compositor->scheduled_updates
313 & ~compositor->pending_flips;
314
315@@ -513,25 +656,10 @@ static void perform_update(void * data)
316 DEBUG("Performing update\n");
317
318 calculate_damage(compositor);
319- pixman_region32_init(&damage);
320
321 wl_list_for_each(screen, &swc.screens, link)
322- {
323- if (!(compositor->scheduled_updates & swc_screen_mask(screen)))
324- continue;
325+ update_screen(compositor, screen);
326
327- output = CONTAINER_OF(screen->outputs.next, typeof(*output), link);
328- update_output_damage(output, &compositor->damage);
329-
330- /* Don't repaint the output if it is waiting for a page flip. */
331- if (compositor->pending_flips & swc_screen_mask(screen))
332- continue;
333-
334- flush_output_damage(output, &damage);
335- repaint_screen(compositor, screen, &damage);
336- }
337-
338- pixman_region32_fini(&damage);
339 /* XXX: Should assert that all damage was covered by some output */
340 pixman_region32_clear(&compositor->damage);
341 compositor->pending_flips |= updates;
342@@ -568,38 +696,6 @@ static bool handle_motion(struct swc_pointer * pointer, uint32_t time)
343 return false;
344 }
345
346-static void handle_drm_event(struct wl_listener * listener, void * data)
347-{
348- struct swc_event * event = data;
349- struct swc_compositor * compositor;
350-
351- compositor = CONTAINER_OF(listener, typeof(*compositor), drm_listener);
352-
353- switch (event->type)
354- {
355- case SWC_DRM_PAGE_FLIP:
356- {
357- struct swc_drm_event_data * event_data = event->data;
358- struct view * view;
359-
360- compositor->pending_flips &= ~SWC_OUTPUT_MASK(event_data->output);
361-
362- if (compositor->pending_flips == 0)
363- {
364- wl_list_for_each(view, &compositor->views, link)
365- swc_view_frame(&view->base, event_data->time);
366- }
367-
368- /* If we had scheduled updates that couldn't run because we were
369- * waiting on a page flip, run them now. */
370- if (compositor->scheduled_updates)
371- perform_update(compositor);
372-
373- break;
374- }
375- }
376-}
377-
378 static void handle_terminate(uint32_t time, uint32_t value, void * data)
379 {
380 struct wl_display * display = data;
381@@ -664,10 +760,10 @@ bool swc_compositor_initialize(struct swc_compositor * compositor,
382 struct wl_display * display,
383 struct wl_event_loop * event_loop)
384 {
385+ struct swc_screen_internal * screen;
386 uint32_t keysym;
387
388 compositor->display = display;
389- compositor->drm_listener.notify = &handle_drm_event;
390 compositor->scheduled_updates = 0;
391 compositor->pending_flips = 0;
392 compositor->pointer_handler = (struct swc_pointer_handler) {
393@@ -675,12 +771,13 @@ bool swc_compositor_initialize(struct swc_compositor * compositor,
394 .motion = &handle_motion
395 };
396
397- wl_signal_add(&swc.drm->event_signal, &compositor->drm_listener);
398-
399 pixman_region32_init(&compositor->damage);
400 pixman_region32_init(&compositor->opaque);
401 wl_list_init(&compositor->views);
402
403+ wl_list_for_each(screen, &swc.screens, link)
404+ screen_new(screen);
405+
406 swc_add_key_binding(SWC_MOD_CTRL | SWC_MOD_ALT, XKB_KEY_BackSpace,
407 &handle_terminate, display);
408
+0,
-2
1@@ -28,8 +28,6 @@ struct swc_compositor
2 };
3
4 struct swc_pointer_handler pointer_handler;
5-
6- struct wl_listener drm_listener;
7 };
8
9 bool swc_compositor_initialize(struct swc_compositor * compositor,
+107,
-0
1@@ -0,0 +1,107 @@
2+/* swc: cursor_plane.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 "cursor_plane.h"
26+#include "buffer.h"
27+#include "drm.h"
28+#include "internal.h"
29+#include "util.h"
30+
31+#include <errno.h>
32+#include <wld/wld.h>
33+#include <wld/drm.h>
34+#include <xf86drmMode.h>
35+
36+static bool update(struct swc_view * view)
37+{
38+ return true;
39+}
40+
41+static bool attach(struct swc_view * view, struct swc_buffer * buffer)
42+{
43+ struct swc_cursor_plane * plane = CONTAINER_OF(view, typeof(*plane), view);
44+
45+ if (buffer)
46+ {
47+ union wld_object object;
48+
49+ if (!wld_export(buffer->wld, WLD_DRM_OBJECT_HANDLE, &object))
50+ {
51+ ERROR("Could not get export buffer to DRM handle\n");
52+ return false;
53+ }
54+
55+ if (drmModeSetCursor(swc.drm->fd, plane->crtc, object.u32,
56+ buffer->wld->width, buffer->wld->height) != 0)
57+ {
58+ ERROR("Could not set cursor: %s\n", strerror(errno));
59+ return false;
60+ }
61+ }
62+ else
63+ {
64+ if (drmModeSetCursor(swc.drm->fd, plane->crtc, 0, 0, 0) != 0)
65+ {
66+ ERROR("Could not unset cursor: %s\n", strerror(errno));
67+ return false;
68+ }
69+ }
70+
71+ return true;
72+}
73+
74+static bool move(struct swc_view * view, int32_t x, int32_t y)
75+{
76+ struct swc_cursor_plane * plane = CONTAINER_OF(view, typeof(*plane), view);
77+
78+ if (drmModeMoveCursor(swc.drm->fd, plane->crtc, x, y) != 0)
79+ {
80+ ERROR("Could not move cursor: %s\n", strerror(errno));
81+ return false;
82+ }
83+
84+ return true;
85+}
86+
87+static const struct swc_view_impl view_impl = {
88+ .update = &update,
89+ .attach = &attach,
90+ .move = &move
91+};
92+
93+bool swc_cursor_plane_initialize(struct swc_cursor_plane * plane, uint32_t crtc)
94+{
95+ if (drmModeSetCursor(swc.drm->fd, crtc, 0, 0, 0) != 0)
96+ return false;
97+
98+ plane->crtc = crtc;
99+ swc_view_initialize(&plane->view, &view_impl);
100+
101+ return true;
102+}
103+
104+void swc_cursor_plane_finalize(struct swc_cursor_plane * plane)
105+{
106+ drmModeSetCursor(swc.drm->fd, plane->crtc, 0, 0, 0);
107+}
108+
+41,
-0
1@@ -0,0 +1,41 @@
2+/* swc: libswc/cursor_plane.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_CURSOR_PLANE_H
26+#define SWC_CURSOR_PLANE_H
27+
28+#include "view.h"
29+
30+struct swc_cursor_plane
31+{
32+ struct swc_view view;
33+ uint32_t crtc;
34+};
35+
36+bool swc_cursor_plane_initialize(struct swc_cursor_plane * plane,
37+ uint32_t crtc);
38+
39+void swc_cursor_plane_finalize(struct swc_cursor_plane * plane);
40+
41+#endif
42+
+5,
-12
1@@ -26,6 +26,7 @@
2 #include "internal.h"
3 #include "output.h"
4 #include "screen.h"
5+#include "util.h"
6 #include "wayland_buffer.h"
7
8 #include <stdio.h>
9@@ -267,15 +268,9 @@ static void handle_vblank(int fd, unsigned int sequence, unsigned int sec,
10 static void handle_page_flip(int fd, unsigned int sequence, unsigned int sec,
11 unsigned int usec, void * data)
12 {
13- struct swc_output * output = data;
14- struct swc_drm_event_data event_data = {
15- .time = sec * 1000 + usec / 1000,
16- .output = output
17- };
18-
19- /* XXX: It doesn't make sense for multiple things to be listening for page
20- * flips (or does it?). Maybe this should be a callback instead? */
21- swc_send_event(&swc.drm->event_signal, SWC_DRM_PAGE_FLIP, &event_data);
22+ struct swc_drm_handler * handler = data;
23+
24+ handler->page_flip(handler, sec * 1000 + usec / 1000);
25 }
26
27 static drmEventContext event_context = {
28@@ -315,8 +310,6 @@ bool swc_drm_initialize(const char * seat_name)
29 const char * sysnum;
30 char * end;
31
32- wl_signal_init(&swc.drm->event_signal);
33-
34 struct udev_device * drm_device = find_primary_drm_device(seat_name);
35
36 if (!drm_device)
37@@ -468,7 +461,7 @@ bool swc_drm_create_screens(struct wl_list * screens)
38 break;
39 }
40
41- if (!(output = swc_output_new(resources->crtcs[crtc_index], connector)))
42+ if (!(output = swc_output_new(connector)))
43 continue;
44
45 output->screen = swc_screen_new(resources->crtcs[crtc_index],
+2,
-9
1@@ -5,15 +5,9 @@
2 #include <stdint.h>
3 #include <wayland-server.h>
4
5-enum swc_drm_event_type
6+struct swc_drm_handler
7 {
8- SWC_DRM_PAGE_FLIP
9-};
10-
11-struct swc_drm_event_data
12-{
13- uint32_t time;
14- struct swc_output * output;
15+ void (* page_flip)(struct swc_drm_handler * handler, uint32_t time);
16 };
17
18 struct swc_drm
19@@ -21,7 +15,6 @@ struct swc_drm
20 int fd;
21 struct wld_context * context;
22 struct wld_renderer * renderer;
23- struct wl_signal event_signal;
24 };
25
26 bool swc_drm_initialize(const char * seat);
+208,
-0
1@@ -0,0 +1,208 @@
2+/* swc: framebuffer_plane.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 "framebuffer_plane.h"
26+#include "buffer.h"
27+#include "drm.h"
28+#include "internal.h"
29+#include "util.h"
30+
31+#include <errno.h>
32+#include <wld/wld.h>
33+#include <wld/drm.h>
34+#include <xf86drm.h>
35+#include <xf86drmMode.h>
36+
37+struct framebuffer
38+{
39+ uint32_t id;
40+ struct wl_listener destroy_listener;
41+};
42+
43+static void handle_buffer_destroy(struct wl_listener * listener, void * data)
44+{
45+ struct framebuffer * framebuffer
46+ = CONTAINER_OF(listener, typeof(*framebuffer), destroy_listener);
47+
48+ drmModeRmFB(swc.drm->fd, framebuffer->id);
49+ free(framebuffer);
50+}
51+
52+static struct framebuffer * framebuffer_get(struct swc_buffer * buffer)
53+{
54+ struct wl_listener * listener
55+ = wl_signal_get(&buffer->destroy_signal, &handle_buffer_destroy);
56+ struct framebuffer * framebuffer;
57+
58+ if (listener)
59+ {
60+ framebuffer = CONTAINER_OF(listener, typeof(*framebuffer),
61+ destroy_listener);
62+ }
63+ else
64+ {
65+ struct wld_buffer * wld = buffer->wld;
66+ union wld_object object;
67+
68+ if (!wld_export(wld, WLD_DRM_OBJECT_HANDLE, &object))
69+ {
70+ ERROR("Could not get buffer handle\n");
71+ goto error0;
72+ }
73+
74+
75+ if (!(framebuffer = malloc(sizeof *framebuffer)))
76+ goto error0;
77+
78+ if (drmModeAddFB(swc.drm->fd, wld->width, wld->height, 24, 32,
79+ wld->pitch, object.u32, &framebuffer->id) != 0)
80+ {
81+ goto error1;
82+ }
83+
84+ framebuffer->destroy_listener.notify = &handle_buffer_destroy;
85+ wl_signal_add(&buffer->destroy_signal, &framebuffer->destroy_listener);
86+ }
87+
88+ return framebuffer;
89+
90+ error1:
91+ free(framebuffer);
92+ error0:
93+ return NULL;
94+}
95+
96+static bool update(struct swc_view * view)
97+{
98+ return true;
99+}
100+
101+static bool attach(struct swc_view * view, struct swc_buffer * buffer)
102+{
103+ struct swc_framebuffer_plane * plane
104+ = CONTAINER_OF(view, typeof(*plane), view);
105+ struct framebuffer * framebuffer = framebuffer_get(buffer);
106+
107+ if (!framebuffer)
108+ return false;
109+
110+ if (drmModePageFlip(swc.drm->fd, plane->crtc, framebuffer->id,
111+ DRM_MODE_PAGE_FLIP_EVENT, &plane->drm_handler) != 0)
112+ {
113+ if (errno == EINVAL)
114+ {
115+ WARNING("Page flip failed with EINVAL, trying to set CRTC\n");
116+
117+ if (drmModeSetCrtc(swc.drm->fd, plane->crtc, framebuffer->id, 0, 0,
118+ plane->connectors.data,
119+ plane->connectors.size / 4,
120+ &plane->mode.info) == 0)
121+ {
122+ swc_view_frame(&plane->view, swc_time());
123+ }
124+ else
125+ {
126+ ERROR("Could not set CRTC to next framebuffer: %s\n",
127+ strerror(errno));
128+ return false;
129+ }
130+ }
131+ else
132+ {
133+ ERROR("Could not schedule page flip: %s\n", strerror(errno));
134+ return false;
135+ }
136+ }
137+
138+ return true;
139+}
140+
141+const static struct swc_view_impl view_impl = {
142+ .update = &update,
143+ .attach = &attach
144+};
145+
146+static void handle_page_flip(struct swc_drm_handler * handler, uint32_t time)
147+{
148+ struct swc_framebuffer_plane * plane
149+ = CONTAINER_OF(handler, typeof(*plane), drm_handler);
150+
151+ swc_view_frame(&plane->view, time);
152+}
153+
154+bool swc_framebuffer_plane_initialize(struct swc_framebuffer_plane * plane,
155+ uint32_t crtc, drmModeModeInfoPtr mode,
156+ uint32_t * connectors,
157+ uint32_t num_connectors)
158+{
159+ uint32_t * plane_connectors;
160+
161+ if (!(plane->original_crtc_state = drmModeGetCrtc(swc.drm->fd, crtc)))
162+ {
163+ ERROR("Failed to get CRTC state for CRTC %u: %s\n",
164+ crtc, strerror(errno));
165+ goto error0;
166+ }
167+
168+ wl_array_init(&plane->connectors);
169+ plane_connectors = wl_array_add(&plane->connectors,
170+ num_connectors * sizeof connectors[0]);
171+
172+ if (!plane_connectors)
173+ {
174+ ERROR("Failed to allocate connector array\n");
175+ goto error1;
176+ }
177+
178+ memcpy(plane_connectors, connectors, num_connectors * sizeof connectors[0]);
179+
180+ if (drmModeSetCrtc(swc.drm->fd, crtc, -1, 0, 0,
181+ connectors, num_connectors, mode) != 0)
182+ {
183+ ERROR("Failed to set CRTC: %s\n", strerror(errno));
184+ goto error2;
185+ }
186+
187+ plane->crtc = crtc;
188+ plane->drm_handler.page_flip = &handle_page_flip;
189+ swc_view_initialize(&plane->view, &view_impl);
190+ swc_mode_initialize(&plane->mode, mode);
191+
192+ return true;
193+
194+ error2:
195+ wl_array_release(&plane->connectors);
196+ error1:
197+ drmModeFreeCrtc(plane->original_crtc_state);
198+ error0:
199+ return false;
200+}
201+
202+void swc_framebuffer_plane_finalize(struct swc_framebuffer_plane * plane)
203+{
204+ drmModeCrtcPtr crtc = plane->original_crtc_state;
205+ drmModeSetCrtc(swc.drm->fd, crtc->crtc_id, crtc->buffer_id,
206+ crtc->x, crtc->y, NULL, 0, &crtc->mode);
207+ drmModeFreeCrtc(crtc);
208+}
209+
+52,
-0
1@@ -0,0 +1,52 @@
2+/* swc: libswc/framebuffer_plane.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_FRAMEBUFFER_PLANE_H
26+#define SWC_FRAMEBUFFER_PLANE_H
27+
28+#include "drm.h"
29+#include "mode.h"
30+#include "surface.h"
31+#include "view.h"
32+
33+#include <xf86drmMode.h>
34+
35+struct swc_framebuffer_plane
36+{
37+ uint32_t crtc;
38+ drmModeCrtcPtr original_crtc_state;
39+ struct swc_mode mode;
40+ struct swc_view view;
41+ struct swc_drm_handler drm_handler;
42+ struct wl_array connectors;
43+};
44+
45+bool swc_framebuffer_plane_initialize(struct swc_framebuffer_plane * plane,
46+ uint32_t crtc, drmModeModeInfoPtr mode,
47+ uint32_t * connectors,
48+ uint32_t num_connectors);
49+
50+void swc_framebuffer_plane_finalize(struct swc_framebuffer_plane * plane);
51+
52+#endif
53+
+2,
-1
1@@ -33,9 +33,10 @@ SWC_SOURCES = \
2 libswc/view.c \
3 libswc/buffer.c \
4 libswc/wayland_buffer.c \
5+ libswc/cursor_plane.c \
6+ libswc/framebuffer_plane.c \
7 libswc/util.c \
8 libswc/output.c \
9- libswc/plane.c \
10 libswc/surface.c \
11 libswc/region.c \
12 libswc/input_focus.c \
+7,
-0
1@@ -39,3 +39,10 @@ void swc_mode_finish(struct swc_mode * mode)
2 {
3 }
4
5+bool swc_mode_equal(const struct swc_mode * mode1, const struct swc_mode * mode2)
6+{
7+ return mode1->width == mode2->width
8+ && mode1->height == mode2->height
9+ && mode1->refresh == mode2->refresh;
10+}
11+
+2,
-0
1@@ -44,5 +44,7 @@ struct swc_mode
2 bool swc_mode_initialize(struct swc_mode * mode, drmModeModeInfo * mode_info);
3 void swc_mode_finish(struct swc_mode * mode);
4
5+bool swc_mode_equal(const struct swc_mode * mode1, const struct swc_mode * mode2);
6+
7 #endif
8
+5,
-36
1@@ -38,7 +38,7 @@ static void bind_output(struct wl_client * client, void * data,
2 flags = 0;
3 if (mode->preferred)
4 flags |= WL_OUTPUT_MODE_PREFERRED;
5- if (output->current_mode == mode)
6+ if (swc_mode_equal(&screen->planes.framebuffer.mode, mode))
7 flags |= WL_OUTPUT_MODE_CURRENT;
8
9 wl_output_send_mode(resource, flags, mode->width, mode->height,
10@@ -49,11 +49,9 @@ static void bind_output(struct wl_client * client, void * data,
11 wl_output_send_done(resource);
12 }
13
14-struct swc_output * swc_output_new(uint32_t crtc_id, drmModeConnector * connector)
15+struct swc_output * swc_output_new(drmModeConnectorPtr connector)
16 {
17 struct swc_output * output;
18- drmModeEncoder * encoder;
19- drmModeCrtc * current_crtc;
20 struct swc_mode * modes;
21 uint32_t index;
22
23@@ -80,46 +78,21 @@ struct swc_output * swc_output_new(uint32_t crtc_id, drmModeConnector * connecto
24 pixman_region32_init(&output->current_damage);
25 pixman_region32_init(&output->previous_damage);
26
27- output->crtc = crtc_id;
28 output->connector = connector->connector_id;
29
30- /* Determine the current CRTC of this output. */
31- encoder = drmModeGetEncoder(swc.drm->fd, connector->encoder_id);
32- current_crtc = drmModeGetCrtc(swc.drm->fd, encoder->crtc_id);
33- drmModeFreeEncoder(encoder);
34-
35 modes = wl_array_add(&output->modes, connector->count_modes * sizeof *modes);
36
37+ if (!modes)
38+ goto error2;
39+
40 for (index = 0; index < connector->count_modes; ++index)
41 {
42 swc_mode_initialize(&modes[index], &connector->modes[index]);
43
44- if (memcmp(&modes[index].info, ¤t_crtc->mode,
45- sizeof(drmModeModeInfo)) == 0)
46- output->current_mode = &modes[index];
47 if (modes[index].preferred)
48 output->preferred_mode = &modes[index];
49 }
50
51- if (output->preferred_mode)
52- output->current_mode = output->preferred_mode;
53-
54- output->original_state.crtc = current_crtc;
55-
56- /* Create output planes */
57- if (!swc_plane_initialize(&output->framebuffer_plane,
58- &swc_framebuffer_plane, output))
59- {
60- printf("failed to initialize framebuffer plane\n");
61- goto error2;
62- }
63-
64- if (!swc_plane_initialize(&output->cursor_plane, &swc_cursor_plane, output))
65- {
66- printf("failed to initialize cursor plane\n");
67- goto error2;
68- }
69-
70 return output;
71
72 error2:
73@@ -133,15 +106,11 @@ struct swc_output * swc_output_new(uint32_t crtc_id, drmModeConnector * connecto
74 void swc_output_destroy(struct swc_output * output)
75 {
76 struct swc_mode * mode;
77- drmModeCrtc * crtc = output->original_state.crtc;
78
79 wl_array_for_each(mode, &output->modes)
80 swc_mode_finish(mode);
81 wl_array_release(&output->modes);
82
83- drmModeSetCrtc(swc.drm->fd, crtc->crtc_id, crtc->buffer_id, crtc->x,
84- crtc->y, &output->connector, 1, &crtc->mode);
85- drmModeFreeCrtc(crtc);
86 wl_global_destroy(output->global);
87 free(output);
88 }
+3,
-14
1@@ -1,8 +1,6 @@
2 #ifndef SWC_OUTPUT_H
3 #define SWC_OUTPUT_H
4
5-#include "plane.h"
6-
7 #include <stdint.h>
8 #include <pixman.h>
9 #include <wayland-util.h>
10@@ -18,28 +16,19 @@ struct swc_output
11 uint32_t physical_width, physical_height;
12
13 struct wl_array modes;
14- struct swc_mode * current_mode, * preferred_mode;
15-
16- /* Output planes. */
17- struct swc_plane framebuffer_plane;
18- struct swc_plane cursor_plane;
19+ struct swc_mode * preferred_mode;
20
21 pixman_region32_t current_damage, previous_damage;
22
23 /* The DRM connector corresponding to this output */
24- uint32_t crtc, connector;
25-
26- struct
27- {
28- drmModeCrtc * crtc;
29- } original_state;
30+ uint32_t connector;
31
32 struct wl_global * global;
33 struct wl_list resources;
34 struct wl_list link;
35 };
36
37-struct swc_output * swc_output_new(uint32_t crtc_id, drmModeConnector * connector);
38+struct swc_output * swc_output_new(drmModeConnector * connector);
39 void swc_output_destroy(struct swc_output * output);
40
41 #endif
+0,
-224
1@@ -1,224 +0,0 @@
2-/* swc: plane.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 "plane.h"
26-#include "drm.h"
27-#include "internal.h"
28-#include "mode.h"
29-#include "output.h"
30-#include "screen.h"
31-
32-#include <stdlib.h>
33-#include <stdio.h>
34-#include <libdrm/drm.h>
35-#include <wld/wld.h>
36-#include <wld/drm.h>
37-
38-struct framebuffer
39-{
40- struct wld_buffer * buffer;
41- uint32_t id;
42-};
43-
44-static bool framebuffer_initialize(struct swc_plane * plane)
45-{
46- struct framebuffer * fb = swc_double_buffer_front(&plane->double_buffer);
47-
48- return drmModeSetCrtc(swc.drm->fd, plane->output->crtc,
49- fb->id, 0, 0, &plane->output->connector, 1,
50- &plane->output->current_mode->info) == 0;
51-}
52-
53-static void * framebuffer_create_buffer(struct swc_plane * plane)
54-{
55- struct wld_buffer * buffer;
56- struct swc_output * output = plane->output;
57- struct framebuffer * fb;
58- union wld_object object;
59-
60- if (!(fb = malloc(sizeof *fb)))
61- goto error0;
62-
63- buffer = wld_create_buffer(swc.drm->context,
64- output->screen->base.geometry.width,
65- output->screen->base.geometry.height,
66- WLD_FORMAT_XRGB8888);
67-
68- if (!buffer)
69- {
70- fprintf(stderr, "Could not create DRM buffer for framebuffer\n");
71- goto error1;
72- }
73-
74- wld_export(buffer, WLD_DRM_OBJECT_HANDLE, &object);
75-
76- if (drmModeAddFB(swc.drm->fd, buffer->width, buffer->height,
77- 24, 32, buffer->pitch, object.u32, &fb->id) != 0)
78- {
79- fprintf(stderr, "drmModeAddFB failed\n");
80- goto error2;
81- }
82-
83- fb->buffer = buffer;
84-
85- return buffer;
86-
87- error2:
88- wld_destroy_buffer(buffer);
89- error1:
90- free(buffer);
91- error0:
92- return NULL;
93-}
94-
95-static void framebuffer_destroy_buffer(struct swc_plane * plane, void * data)
96-{
97- struct framebuffer * fb = data;
98-
99- drmModeRmFB(swc.drm->fd, fb->id);
100- wld_destroy_buffer(fb->buffer);
101-}
102-
103-static struct wld_buffer * framebuffer_get_buffer(void * data)
104-{
105- struct framebuffer * fb = data;
106-
107- return fb->buffer;
108-}
109-
110-static bool framebuffer_flip(struct swc_plane * plane)
111-{
112- struct swc_output * output = plane->output;
113- struct framebuffer * fb = swc_double_buffer_back(&plane->double_buffer);
114-
115- return drmModePageFlip(swc.drm->fd, output->crtc, fb->id,
116- DRM_MODE_PAGE_FLIP_EVENT, output) == 0;
117-}
118-
119-const struct swc_plane_interface swc_framebuffer_plane = {
120- .initialize = &framebuffer_initialize,
121- .create_buffer = &framebuffer_create_buffer,
122- .destroy_buffer = &framebuffer_destroy_buffer,
123- .get_buffer = &framebuffer_get_buffer,
124- .flip = &framebuffer_flip
125-};
126-
127-static bool cursor_initialize(struct swc_plane * plane)
128-{
129- return true;
130-}
131-
132-static void * cursor_create_buffer(struct swc_plane * plane)
133-{
134- return wld_create_buffer(swc.drm->context, 64, 64, WLD_FORMAT_ARGB8888);
135-}
136-
137-static void cursor_destroy_buffer(struct swc_plane * plane, void * data)
138-{
139- struct wld_buffer * buffer = data;
140-
141- wld_destroy_buffer(buffer);
142-}
143-
144-static struct wld_buffer * cursor_get_buffer(void * data)
145-{
146- return data;
147-}
148-
149-static bool cursor_flip(struct swc_plane * plane)
150-{
151- struct wld_buffer * buffer = swc_double_buffer_back(&plane->double_buffer);
152- union wld_object object;
153-
154- wld_export(buffer, WLD_DRM_OBJECT_HANDLE, &object);
155- return drmModeSetCursor(swc.drm->fd, plane->output->crtc,
156- object.u32, 64, 64) == 0;
157-}
158-
159-static bool cursor_move(struct swc_plane * plane, int32_t x, int32_t y)
160-{
161- return drmModeMoveCursor(swc.drm->fd, plane->output->crtc, x, y) == 0;
162-}
163-
164-const struct swc_plane_interface swc_cursor_plane = {
165- .initialize = &cursor_initialize,
166- .create_buffer = &cursor_create_buffer,
167- .destroy_buffer = &cursor_destroy_buffer,
168- .get_buffer = &cursor_get_buffer,
169- .flip = &cursor_flip,
170- .move = &cursor_move
171-};
172-
173-bool swc_plane_initialize(struct swc_plane * plane,
174- const struct swc_plane_interface * interface,
175- struct swc_output * output)
176-{
177- plane->interface = interface;
178- plane->output = output;
179- plane->double_buffer.buffers[0] = interface->create_buffer(plane);
180- plane->double_buffer.buffers[1] = interface->create_buffer(plane);
181- plane->double_buffer.front = 0;
182- plane->x = 0;
183- plane->y = 0;
184-
185- return plane->interface->initialize(plane);
186-}
187-
188-void swc_plane_finish(struct swc_plane * plane)
189-{
190- plane->interface->destroy_buffer(plane, plane->double_buffer.buffers[0]);
191- plane->interface->destroy_buffer(plane, plane->double_buffer.buffers[1]);
192-}
193-
194-bool swc_plane_flip(struct swc_plane * plane)
195-{
196- if (plane->interface->flip(plane))
197- {
198- swc_double_buffer_swap(&plane->double_buffer);
199-
200- return true;
201- }
202- else
203- return false;
204-}
205-
206-bool swc_plane_move(struct swc_plane * plane, int32_t x, int32_t y)
207-{
208- if (plane->interface->move(plane, x, y))
209- {
210- plane->x = x;
211- plane->y = y;
212-
213- return true;
214- }
215- else
216- return false;
217-}
218-
219-struct wld_buffer * swc_plane_get_buffer(struct swc_plane * plane)
220-{
221- void * back = swc_double_buffer_back(&plane->double_buffer);
222-
223- return plane->interface->get_buffer(back);
224-}
225-
+0,
-66
1@@ -1,66 +0,0 @@
2-/* swc: plane.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_PLANE_H
26-#define SWC_PLANE_H
27-
28-#include "util.h"
29-
30-struct swc_plane;
31-
32-struct swc_plane_interface
33-{
34- bool (* initialize)(struct swc_plane * plane);
35- void * (* create_buffer)(struct swc_plane * plane);
36- void (* destroy_buffer)(struct swc_plane * plane, void * data);
37- struct wld_buffer * (* get_buffer)(void * data);
38- bool (* flip)(struct swc_plane * plane);
39- bool (* move)(struct swc_plane * plane, int32_t x, int32_t y);
40-};
41-
42-struct swc_plane
43-{
44- const struct swc_plane_interface * interface;
45- struct swc_output * output;
46-
47- struct swc_double_buffer double_buffer;
48-
49- /* Relative to the output's origin. */
50- int32_t x, y;
51-};
52-
53-bool swc_plane_initialize(struct swc_plane * plane,
54- const struct swc_plane_interface * interface,
55- struct swc_output * output);
56-
57-bool swc_plane_flip(struct swc_plane * plane);
58-
59-bool swc_plane_move(struct swc_plane * plane, int32_t x, int32_t y);
60-
61-struct wld_buffer * swc_plane_get_buffer(struct swc_plane * plane);
62-
63-extern const struct swc_plane_interface swc_framebuffer_plane;
64-extern const struct swc_plane_interface swc_cursor_plane;
65-
66-#endif
67-
+21,
-0
1@@ -26,6 +26,7 @@
2 #include "internal.h"
3 #include "mode.h"
4 #include "output.h"
5+#include "util.h"
6
7 #include <stdlib.h>
8 #include <sys/param.h>
9@@ -75,10 +76,28 @@ struct swc_screen_internal * swc_screen_new(uint32_t crtc,
10 wl_list_init(&screen->outputs);
11 wl_list_insert(&INTERNAL(screen)->outputs, &output->link);
12
13+ if (!swc_framebuffer_plane_initialize(&screen->planes.framebuffer, crtc,
14+ &output->preferred_mode->info,
15+ &output->connector, 1))
16+ {
17+ ERROR("Failed to initialize framebuffer plane\n");
18+ goto error1;
19+ }
20+
21+ if (!swc_cursor_plane_initialize(&screen->planes.cursor, crtc))
22+ {
23+ ERROR("Failed to initialize cursor plane\n");
24+ goto error2;
25+ }
26+
27 swc.manager->new_screen(&screen->base);
28
29 return screen;
30
31+ error2:
32+ swc_framebuffer_plane_finalize(&screen->planes.framebuffer);
33+ error1:
34+ free(screen);
35 error0:
36 return NULL;
37 }
38@@ -89,6 +108,8 @@ void swc_screen_destroy(struct swc_screen_internal * screen)
39
40 wl_list_for_each_safe(output, next, &screen->outputs, link)
41 swc_output_destroy(output);
42+ swc_framebuffer_plane_finalize(&screen->planes.framebuffer);
43+ swc_cursor_plane_finalize(&screen->planes.cursor);
44 free(screen);
45 }
46
+8,
-0
1@@ -25,6 +25,8 @@
2 #define SWC_SCREEN_H
3
4 #include "swc.h"
5+#include "cursor_plane.h"
6+#include "framebuffer_plane.h"
7
8 #include <wayland-util.h>
9
10@@ -36,6 +38,12 @@ struct swc_screen_internal
11
12 uint8_t id;
13
14+ struct
15+ {
16+ struct swc_framebuffer_plane framebuffer;
17+ struct swc_cursor_plane cursor;
18+ } planes;
19+
20 struct wl_list outputs;
21 struct wl_list modifiers;
22 struct wl_list link;