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, &current_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;