commit 926560d
Michael Forney
·
2013-09-11 22:56:39 +0000 UTC
parent d6e3d50
renderer: Use planes and wld for rendering
15 files changed,
+362,
-384
+0,
-4
1@@ -24,10 +24,6 @@ PKG_CHECK_MODULES([wayland_server], [wayland-server])
2 PKG_CHECK_MODULES([udev], [libudev])
3 PKG_CHECK_MODULES([xkbcommon], [xkbcommon])
4 PKG_CHECK_MODULES([drm], [libdrm])
5-PKG_CHECK_MODULES([drm_intel], [libdrm_intel])
6-PKG_CHECK_MODULES([intelbatch], [intelbatch])
7-PKG_CHECK_MODULES([gbm], [gbm])
8-PKG_CHECK_MODULES([egl], [egl])
9 PKG_CHECK_MODULES([pixman], [pixman-1])
10 PKG_CHECK_MODULES([wld], [wld])
11
+2,
-4
1@@ -1,7 +1,7 @@
2 # swc: libswc/Makefile.am
3
4 AM_CPPFLAGS = -I$(top_srcdir) -I$(PROTOCOL_DIR)
5-AM_CFLAGS = $(pixman_CFLAGS) $(drm_CFLAGS) $(intelbatch_CFLAGS)
6+AM_CFLAGS = $(drm_CFLAGS) $(pixman_CFLAGS) $(wld_CFLAGS)
7
8 lib_LTLIBRARIES = libswc.la
9
10@@ -9,7 +9,6 @@ libswc_la_SOURCES = \
11 compositor.c compositor.h \
12 util.c util.h \
13 output.c output.h \
14- buffer.c buffer.h \
15 plane.c plane.h \
16 surface.c surface.h \
17 compositor_surface.c compositor_surface.h \
18@@ -31,7 +30,6 @@ libswc_la_SOURCES = \
19 $(PROTOCOL_DIR)/wayland-drm-protocol.c
20
21 libswc_la_LIBADD = $(wayland_server_LIBS) $(udev_LIBS) $(xkbcommon_LIBS) \
22- $(drm_LIBS) $(drm_intel_LIBS) $(gbm_LIBS) $(egl_LIBS) \
23- $(pixman_LIBS) $(intelbatch_LIBS) $(wld_LIBS) \
24+ $(drm_LIBS) $(pixman_LIBS) $(wld_LIBS) \
25 ../launch/liblaunch-protocol.la
26
+0,
-44
1@@ -1,44 +0,0 @@
2-#include "buffer.h"
3-
4-#include <stdio.h>
5-#include <sys/mman.h>
6-#include <libdrm/i915_drm.h>
7-#include <xf86drm.h>
8-#include <xf86drmMode.h>
9-
10-bool swc_buffer_initialize(struct swc_buffer * buffer, struct swc_drm * drm,
11- uint32_t width, uint32_t height)
12-{
13- uint32_t size;
14- uint32_t tiling_mode = I915_TILING_X;
15- unsigned long pitch;
16-
17- buffer->width = width;
18- buffer->height = height;
19-
20- buffer->bo = drm_intel_bo_alloc_tiled(drm->bufmgr, "fb", width, height, 4,
21- &tiling_mode, &pitch, 0);
22-
23- buffer->pitch = pitch;
24-
25- if (drmModeAddFB(drm->fd, width, height, 24, 32, buffer->pitch,
26- buffer->bo->handle, &buffer->id) != 0)
27- {
28- printf("could not create FB from buffer handle\n");
29- goto error_buffer;
30- }
31-
32- return true;
33-
34- error_buffer:
35- drm_intel_bo_unreference(buffer->bo);
36- error_base:
37- return false;
38-}
39-
40-void swc_buffer_finish(struct swc_buffer * buffer, struct swc_drm * drm)
41-{
42- drmModeRmFB(drm->fd, buffer->id);
43- drm_intel_bo_unreference(buffer->bo);
44-}
45-
+0,
-28
1@@ -1,28 +0,0 @@
2-#ifndef SWC_BUFFER_H
3-#define SWC_BUFFER_H 1
4-
5-#include "drm.h"
6-
7-#include <stdbool.h>
8-#include <pixman.h>
9-
10-struct swc_buffer
11-{
12- uint32_t id;
13-
14- drm_intel_bo * bo;
15-
16- uint32_t width, height, pitch;
17-};
18-
19-bool swc_buffer_initialize(struct swc_buffer * buffer, struct swc_drm * drm,
20- uint32_t width, uint32_t height);
21-
22-void swc_buffer_finish(struct swc_buffer * buffer, struct swc_drm * drm);
23-
24-void swc_buffer_ref_image(struct swc_buffer * buffer);
25-
26-void swc_buffer_unref_image(struct swc_buffer * buffer);
27-
28-#endif
29-
+151,
-46
1@@ -4,6 +4,7 @@
2 #include <gbm.h>
3
4 #include "compositor.h"
5+#include "compositor_surface.h"
6 #include "tty.h"
7 #include "output.h"
8 #include "surface.h"
9@@ -14,41 +15,133 @@
10
11 static const char default_seat[] = "seat0";
12
13-struct repaint_operation
14+static void calculate_damage(struct swc_compositor * compositor)
15 {
16- struct swc_compositor * compositor;
17- struct swc_output * output;
18-};
19+ struct swc_surface * surface;
20+ struct swc_compositor_surface_state * state;
21+ pixman_region32_t opaque, surface_opaque;
22+
23+ pixman_region32_clear(&compositor->opaque);
24+ pixman_region32_init(&surface_opaque);
25+
26+ /* Go through surfaces top-down to calculate clipping regions. */
27+ wl_list_for_each(surface, &compositor->surfaces, link)
28+ {
29+ state = surface->class_state;
30+
31+ /* Clip the surface by the opaque region covering it. */
32+ pixman_region32_copy(&state->clip, &compositor->opaque);
33+
34+ /* Translate the opaque region to global coordinates. */
35+ pixman_region32_copy(&surface_opaque, &surface->state.opaque);
36+ pixman_region32_translate(&surface_opaque, surface->geometry.x,
37+ surface->geometry.y);
38+
39+ /* Add the surface's opaque region to the accumulated opaque
40+ * region. */
41+ pixman_region32_union(&compositor->opaque, &compositor->opaque,
42+ &surface_opaque);
43+
44+ if (pixman_region32_not_empty(&surface->state.damage))
45+ {
46+ swc_renderer_flush(&compositor->renderer, surface);
47+
48+ /* Translate surface damage to global coordinates. */
49+ pixman_region32_translate(&surface->state.damage,
50+ surface->geometry.x,
51+ surface->geometry.y);
52+
53+ /* Add the surface damage to the compositor damage. */
54+ pixman_region32_union(&compositor->damage, &compositor->damage,
55+ &surface->state.damage);
56+ pixman_region32_clear(&surface->state.damage);
57+ }
58
59-static void repaint_output(void * data)
60+ if (state->border.damaged)
61+ {
62+ pixman_region32_t border_region, surface_region;
63+
64+ pixman_region32_init_with_extents(&border_region, &state->extents);
65+ pixman_region32_init_rect
66+ (&surface_region, surface->geometry.x, surface->geometry.y,
67+ surface->geometry.width, surface->geometry.height);
68+
69+ pixman_region32_subtract(&border_region, &border_region,
70+ &surface_region);
71+
72+ pixman_region32_union(&compositor->damage, &compositor->damage,
73+ &border_region);
74+
75+ pixman_region32_fini(&border_region);
76+ pixman_region32_fini(&surface_region);
77+
78+ state->border.damaged = false;
79+ }
80+ }
81+
82+ pixman_region32_fini(&surface_opaque);
83+}
84+
85+static void repaint_output(struct swc_compositor * compositor,
86+ struct swc_output * output)
87 {
88- struct repaint_operation * operation = data;
89- struct swc_compositor * compositor = operation->compositor;
90+ pixman_region32_t damage, previous_damage, base_damage;
91+
92+ pixman_region32_init(&damage);
93+ pixman_region32_init(&previous_damage);
94+ pixman_region32_init(&base_damage);
95+
96+ pixman_region32_intersect_rect
97+ (&damage, &compositor->damage, output->geometry.x, output->geometry.y,
98+ output->geometry.width, output->geometry.height);
99+
100+ /* We must save the damage from the previous frame because the back buffer
101+ * is also damaged in this region. */
102+ pixman_region32_copy(&previous_damage, &output->previous_damage);
103+ pixman_region32_copy(&output->previous_damage, &damage);
104+
105+ /* The total damage is composed of the damage from the new frame, and the
106+ * damage from the last frame. */
107+ pixman_region32_union(&damage, &damage, &previous_damage);
108
109- swc_renderer_repaint_output(&compositor->renderer, operation->output,
110- &compositor->surfaces);
111+ pixman_region32_subtract(&base_damage, &damage, &compositor->opaque);
112
113- swc_output_switch_buffer(operation->output);
114+ swc_renderer_set_target(&compositor->renderer, &output->framebuffer_plane);
115+ swc_renderer_repaint(&compositor->renderer, &damage, &base_damage,
116+ &compositor->surfaces);
117
118- free(operation);
119+ pixman_region32_subtract(&compositor->damage, &compositor->damage, &damage);
120+
121+ pixman_region32_fini(&damage);
122+ pixman_region32_fini(&previous_damage);
123+ pixman_region32_fini(&base_damage);
124+
125+ if (!swc_plane_flip(&output->framebuffer_plane))
126+ fprintf(stderr, "Plane flip failed\n");
127 }
128
129-static void schedule_repaint_for_output(struct swc_compositor * compositor,
130- struct swc_output * output)
131+static void perform_update(void * data)
132 {
133- struct wl_event_loop * event_loop;
134- struct repaint_operation * operation;
135+ struct swc_compositor * compositor = data;
136+ struct swc_output * output;
137+ uint32_t updates = compositor->scheduled_updates
138+ & ~compositor->pending_flips;
139
140- if (output->repaint_scheduled)
141- return;
142+ if (updates)
143+ {
144+ printf("performing update\n");
145+ calculate_damage(compositor);
146+
147+ wl_list_for_each(output, &compositor->outputs, link)
148+ {
149+ if (updates & SWC_OUTPUT_MASK(output))
150+ repaint_output(compositor, output);
151+ }
152
153- operation = malloc(sizeof *operation);
154- operation->compositor = compositor;
155- operation->output = output;
156+ compositor->pending_flips |= updates;
157+ compositor->scheduled_updates &= ~updates;
158+ }
159
160- event_loop = wl_display_get_event_loop(compositor->display);
161- wl_event_loop_add_idle(event_loop, &repaint_output, operation);
162- output->repaint_scheduled = true;
163 }
164
165 static bool handle_key(struct swc_keyboard * keyboard, uint32_t time,
166@@ -186,21 +279,22 @@ static void handle_drm_event(struct wl_listener * listener, void * data)
167 struct timeval timeval;
168 uint32_t time;
169
170- output->repaint_scheduled = false;
171- output->front_buffer ^= 1;
172-
173 gettimeofday(&timeval, NULL);
174 time = timeval.tv_sec * 1000 + timeval.tv_usec / 1000;
175
176- /* Handle all frame callbacks for surfaces on this output. */
177- wl_list_for_each(surface, &compositor->surfaces, link)
178- {
179- swc_surface_send_frame_callbacks(surface, time);
180+ compositor->pending_flips &= ~SWC_OUTPUT_MASK(output);
181
182- if (surface->state.buffer)
183- wl_buffer_send_release(&surface->state.buffer->resource);
184+ if (compositor->pending_flips == 0)
185+ {
186+ wl_list_for_each(surface, &compositor->surfaces, link)
187+ swc_surface_send_frame_callbacks(surface, time);
188 }
189
190+ /* If we had scheduled updates that couldn't run because we were
191+ * waiting on a page flip, run them now. */
192+ if (compositor->scheduled_updates)
193+ perform_update(compositor);
194+
195 break;
196 }
197 }
198@@ -295,6 +389,8 @@ bool swc_compositor_initialize(struct swc_compositor * compositor,
199 compositor->display = display;
200 compositor->tty_listener.notify = &handle_tty_event;
201 compositor->drm_listener.notify = &handle_drm_event;
202+ compositor->scheduled_updates = 0;
203+ compositor->pending_flips = 0;
204 compositor->compositor_class.interface
205 = &swc_compositor_class_implementation;
206
207@@ -338,19 +434,10 @@ bool swc_compositor_initialize(struct swc_compositor * compositor,
208 wl_signal_add(&compositor->drm.event_signal, &compositor->drm_listener);
209 swc_drm_add_event_sources(&compositor->drm, event_loop);
210
211- compositor->gbm = gbm_create_device(compositor->drm.fd);
212-
213- if (!compositor->gbm)
214- {
215- printf("could not create gbm device\n");
216- goto error_drm;
217- }
218-
219- if (!swc_renderer_initialize(&compositor->renderer, &compositor->drm,
220- compositor->gbm))
221+ if (!swc_renderer_initialize(&compositor->renderer, &compositor->drm))
222 {
223 printf("could not initialize renderer\n");
224- goto error_gbm;
225+ goto error_drm;
226 }
227
228 outputs = swc_drm_create_outputs(&compositor->drm);
229@@ -367,6 +454,8 @@ bool swc_compositor_initialize(struct swc_compositor * compositor,
230 goto error_renderer;
231 }
232
233+ pixman_region32_init(&compositor->damage);
234+ pixman_region32_init(&compositor->opaque);
235 wl_list_init(&compositor->surfaces);
236 wl_array_init(&compositor->key_bindings);
237 wl_signal_init(&compositor->destroy_signal);
238@@ -387,8 +476,6 @@ bool swc_compositor_initialize(struct swc_compositor * compositor,
239
240 error_renderer:
241 swc_renderer_finalize(&compositor->renderer);
242- error_gbm:
243- gbm_device_destroy(compositor->gbm);
244 error_drm:
245 swc_drm_finish(&compositor->drm);
246 error_seat:
247@@ -415,7 +502,6 @@ void swc_compositor_finish(struct swc_compositor * compositor)
248 free(output);
249 }
250
251- gbm_device_destroy(compositor->gbm);
252 swc_drm_finish(&compositor->drm);
253 swc_seat_finish(&compositor->seat);
254 swc_tty_finish(&compositor->tty);
255@@ -453,3 +539,22 @@ void swc_compositor_add_key_binding(struct swc_compositor * compositor,
256 binding->data = data;
257 }
258
259+void swc_compositor_schedule_update(struct swc_compositor * compositor,
260+ struct swc_output * output)
261+{
262+ bool update_scheduled = compositor->scheduled_updates != 0;
263+
264+ if (compositor->scheduled_updates & SWC_OUTPUT_MASK(output))
265+ return;
266+
267+ compositor->scheduled_updates |= SWC_OUTPUT_MASK(output);
268+
269+ if (!update_scheduled)
270+ {
271+ struct wl_event_loop * event_loop;
272+
273+ event_loop = wl_display_get_event_loop(compositor->display);
274+ wl_event_loop_add_idle(event_loop, &perform_update, compositor);
275+ }
276+}
277+
+0,
-1
1@@ -14,7 +14,6 @@ struct swc_compositor
2 struct wl_display * display;
3
4 struct udev * udev;
5- struct gbm_device * gbm;
6
7 struct swc_tty tty;
8 struct swc_seat seat;
+1,
-2
1@@ -187,8 +187,7 @@ void attach(struct swc_surface * surface, struct wl_resource * resource)
2 struct swc_compositor * compositor = swc_container_of
3 (surface->class, typeof(*compositor), compositor_class);
4
5- swc_renderer_attach(&compositor->renderer, surface,
6- wl_resource_get_user_data(resource));
7+ swc_renderer_attach(&compositor->renderer, surface, resource);
8 }
9
10 void update(struct swc_surface * surface)
+0,
-1
1@@ -257,7 +257,6 @@ static void handle_page_flip(int fd, unsigned int sequence, unsigned int sec,
2 struct swc_output * output = data;
3
4 printf("page flip\n");
5- output->front_buffer ^= 1;
6
7 /* XXX: It doesn't make sense for multiple things to be listening for page
8 * flips (or does it?). Maybe this should be a callback instead? */
+0,
-3
1@@ -4,9 +4,7 @@
2 #include <stdbool.h>
3 #include <stdint.h>
4 #include <libudev.h>
5-#include <gbm.h>
6 #include <wayland-server.h>
7-#include <libdrm/intel_bufmgr.h>
8
9 struct wld_drm_context * context;
10
11@@ -21,7 +19,6 @@ struct swc_drm
12 uint32_t id;
13 char * path;
14
15- drm_intel_bufmgr * bufmgr;
16 struct wld_drm_context * context;
17
18 uint32_t taken_output_ids;
+6,
-42
1@@ -57,14 +57,12 @@ bool swc_output_initialize(struct swc_output * output, struct swc_drm * drm,
2 printf("initializing output with id: %u\n", id);
3
4 output->id = id;
5- output->repaint_scheduled = false;
6- output->front_buffer = 0;
7-
8 output->physical_width = connector->mmWidth;
9 output->physical_height = connector->mmHeight;
10
11 wl_list_init(&output->resources);
12 wl_array_init(&output->modes);
13+ pixman_region32_init(&output->previous_damage);
14
15 output->crtc_id = crtc_id;
16 output->connector_id = connector->connector_id;
17@@ -93,36 +91,18 @@ bool swc_output_initialize(struct swc_output * output, struct swc_drm * drm,
18 output->geometry.width = output->current_mode->width;
19 output->geometry.height = output->current_mode->height;
20
21- /* Create output buffers */
22- if (!swc_buffer_initialize(&output->buffers[0], drm, output->geometry.width,
23- output->geometry.height))
24- {
25- printf("could not initialize buffer 0 for output\n");
26- goto error_base;
27- }
28-
29- if (!swc_buffer_initialize(&output->buffers[1], drm, output->geometry.width,
30- output->geometry.height))
31- {
32- printf("could not initialize buffer 1 for output\n");
33- goto error_buffer0;
34- }
35-
36 output->original_state.crtc = current_crtc;
37
38- if (drmModeSetCrtc(drm->fd, output->crtc_id, output->buffers[0].id, 0, 0,
39- &output->connector_id, 1, &output->current_mode->info) != 0)
40+ /* Create output planes */
41+ if (!swc_plane_initialize(&output->framebuffer_plane,
42+ &swc_framebuffer_plane, output))
43 {
44- printf("could not set crtc for output\n");
45- goto error_buffer1;
46+ printf("failed to initialize framebuffer plane\n");
47+ goto error_base;
48 }
49
50 return true;
51
52- error_buffer1:
53- swc_buffer_finish(&output->buffers[1], drm);
54- error_buffer0:
55- swc_buffer_finish(&output->buffers[0], drm);
56 error_base:
57 return false;
58 }
59@@ -139,9 +119,6 @@ void swc_output_finish(struct swc_output * output)
60 drmModeSetCrtc(output->drm->fd, crtc->crtc_id, crtc->buffer_id, crtc->x,
61 crtc->y, &output->connector_id, 1, &crtc->mode);
62 drmModeFreeCrtc(crtc);
63-
64- swc_buffer_finish(&output->buffers[0], output->drm);
65- swc_buffer_finish(&output->buffers[1], output->drm);
66 }
67
68 void swc_output_add_globals(struct swc_output * output,
69@@ -150,16 +127,3 @@ void swc_output_add_globals(struct swc_output * output,
70 wl_global_create(display, &wl_output_interface, 1, output, &bind_output);
71 }
72
73-void swc_output_switch_buffer(struct swc_output * output)
74-{
75- printf("queueing pageflip\n");
76-
77- /* Queue a page flip */
78- if (drmModePageFlip(output->drm->fd, output->crtc_id,
79- swc_output_get_back_buffer(output)->id,
80- DRM_MODE_PAGE_FLIP_EVENT, output) != 0)
81- {
82- printf("could not queue pageflip\n");
83- }
84-}
85-
+6,
-20
1@@ -1,7 +1,7 @@
2 #ifndef SWC_OUTPUT_H
3 #define SWC_OUTPUT_H 1
4
5-#include "buffer.h"
6+#include "plane.h"
7
8 #include <stdint.h>
9 #include <pixman.h>
10@@ -26,9 +26,11 @@ struct swc_output
11 struct wl_array modes;
12 struct swc_mode * current_mode, * preferred_mode;
13
14- /* Use double buffering */
15- struct swc_buffer buffers[2];
16- uint8_t front_buffer;
17+ /* Output planes. */
18+ struct swc_plane framebuffer_plane;
19+ struct swc_plane cursor_plane;
20+
21+ pixman_region32_t previous_damage;
22
23 /* The CRTC and connector we are using to drive this output */
24 uint32_t crtc_id;
25@@ -39,8 +41,6 @@ struct swc_output
26 drmModeCrtc * crtc;
27 } original_state;
28
29- bool repaint_scheduled;
30-
31 struct wl_list resources;
32 struct wl_list link;
33 };
34@@ -54,19 +54,5 @@ void swc_output_finish(struct swc_output * output);
35 void swc_output_add_globals(struct swc_output * output,
36 struct wl_display * display);
37
38-void swc_output_switch_buffer(struct swc_output * output);
39-
40-static inline struct swc_buffer * swc_output_get_front_buffer
41- (struct swc_output * output)
42-{
43- return &output->buffers[output->front_buffer];
44-}
45-
46-static inline struct swc_buffer * swc_output_get_back_buffer
47- (struct swc_output * output)
48-{
49- return &output->buffers[!output->front_buffer];
50-}
51-
52 #endif
53
+145,
-159
1@@ -1,29 +1,18 @@
2 #include "renderer.h"
3 #include "compositor_surface.h"
4-#include "util.h"
5+#include "drm_buffer.h"
6
7+#include <assert.h>
8 #include <stdio.h>
9-#include <GLES2/gl2.h>
10-#include <libdrm/intel_bufmgr.h>
11-#include <libdrm/drm.h>
12-#include <intelbatch/blt.h>
13-#include <intelbatch/mi.h>
14-#include <xf86drm.h>
15+#include <stdlib.h>
16+#include <wld/wld.h>
17+#include <wld/drm.h>
18
19 struct buffer_state
20 {
21- union
22- {
23- struct
24- {
25- pixman_image_t * image;
26- } shm;
27- struct
28- {
29- drm_intel_bo * bo;
30- uint32_t width, height, pitch;
31- } drm;
32- };
33+ struct wld_drawable * drawable;
34+ /* Only used for SHM buffers */
35+ pixman_image_t * dst, * src;
36 struct wl_listener destroy_listener;
37 };
38
39@@ -40,38 +29,17 @@ static inline uint32_t pixman_format(uint32_t format)
40 return 0;
41 }
42
43-static inline void switch_context(struct swc_renderer * renderer,
44- uint32_t context, struct swc_buffer * buffer)
45+static inline uint32_t wld_format(uint32_t format)
46 {
47- if (renderer->context != context)
48+ switch (format)
49 {
50- /* Leave old context */
51- switch (renderer->context)
52- {
53- case SWC_RENDERER_CONTEXT_NONE:
54- break;
55- case SWC_RENDERER_CONTEXT_BATCH:
56- intel_batch_flush(&renderer->batch);
57- break;
58- case SWC_RENDERER_CONTEXT_SHM:
59- drm_intel_gem_bo_unmap_gtt(buffer->bo);
60- break;
61- }
62-
63- /* Enter new context */
64- switch (context)
65- {
66- case SWC_RENDERER_CONTEXT_NONE:
67- break;
68- case SWC_RENDERER_CONTEXT_BATCH:
69- break;
70- case SWC_RENDERER_CONTEXT_SHM:
71- drm_intel_gem_bo_map_gtt(buffer->bo);
72- break;
73- }
74-
75- renderer->context = context;
76+ case WL_SHM_FORMAT_XRGB8888:
77+ return WLD_FORMAT_XRGB8888;
78+ case WL_SHM_FORMAT_ARGB8888:
79+ return WLD_FORMAT_ARGB8888;
80 }
81+
82+ return 0;
83 }
84
85 static void handle_buffer_destroy(struct wl_listener * listener, void * data)
86@@ -79,6 +47,11 @@ static void handle_buffer_destroy(struct wl_listener * listener, void * data)
87 struct buffer_state * state
88 = swc_container_of(listener, typeof(*state), destroy_listener);
89
90+ wld_destroy_drawable(state->drawable);
91+ if (state->dst)
92+ pixman_image_unref(state->dst);
93+ if (state->src)
94+ pixman_image_unref(state->src);
95 free(state);
96 }
97
98@@ -92,176 +65,189 @@ static inline struct buffer_state * buffer_state(struct wl_resource * resource)
99 : NULL;
100 }
101
102-static void repaint_surface_for_output(struct swc_renderer * renderer,
103- struct swc_surface * surface,
104- struct swc_output * output)
105+static void repaint_surface(struct swc_renderer * renderer,
106+ struct swc_surface * surface,
107+ pixman_region32_t * damage)
108 {
109- struct swc_buffer * back_buffer = swc_output_get_back_buffer(output);
110+ struct swc_render_target * target = &renderer->target;
111+ pixman_region32_t surface_damage;
112+ pixman_region32_t border_damage;
113+ pixman_region32_t surface_region;
114 struct buffer_state * state;
115 struct swc_compositor_surface_state * surface_state = surface->class_state;
116
117 if (!surface->state.buffer)
118 return;
119
120- state = buffer_state(&surface->state.buffer->resource);
121-
122- if (wl_buffer_is_shm(surface->state.buffer))
123- {
124- pixman_image_t * buffer_image;
125+ state = buffer_state(surface->state.buffer);
126+ assert(state);
127
128- switch_context(renderer, SWC_RENDERER_CONTEXT_SHM, back_buffer);
129+ pixman_region32_init_with_extents(&surface_damage, &surface_state->extents);
130+ pixman_region32_init(&border_damage);
131+ pixman_region32_init_rect
132+ (&surface_region, surface->geometry.x, surface->geometry.y,
133+ surface->geometry.width, surface->geometry.height);
134
135- printf("repainting shm surface\n");
136+ pixman_region32_intersect(&surface_damage, damage, &surface_damage);
137+ pixman_region32_subtract(&surface_damage, &surface_damage,
138+ &surface_state->clip);
139+ pixman_region32_subtract(&border_damage, &surface_damage, &surface_region);
140+ pixman_region32_intersect(&surface_damage, &surface_damage,
141+ &surface_region);
142
143- buffer_image = pixman_image_create_bits_no_clear
144- (PIXMAN_x8r8g8b8, back_buffer->width, back_buffer->height,
145- back_buffer->bo->virtual, back_buffer->pitch);
146+ pixman_region32_fini(&surface_region);
147
148- pixman_image_composite32(PIXMAN_OP_SRC,
149- state->shm.image, NULL,
150- buffer_image, 0, 0, 0, 0, 0, 0,
151- surface->geometry.width,
152- surface->geometry.height);
153- }
154- else
155+ if (pixman_region32_not_empty(&surface_damage))
156 {
157- switch_context(renderer, SWC_RENDERER_CONTEXT_BATCH, back_buffer);
158-
159- printf("repainting drm surface\n");
160-
161- drm_intel_bo * src = state->drm.bo;
162- uint32_t src_pitch = state->drm.pitch;
163-
164- xy_src_copy_blt(&renderer->batch, src, src_pitch, 0, 0,
165- back_buffer->bo, back_buffer->pitch,
166- surface->geometry.x + surface_state->border.width,
167- surface->geometry.y + surface_state->border.width,
168- surface->geometry.width, surface->geometry.height);
169+ printf("\tdrm surface %u { x: %d, y: %d, w: %u, h: %u }\n",
170+ wl_resource_get_id(surface->resource),
171+ surface->geometry.x, surface->geometry.y,
172+ surface->geometry.width, surface->geometry.height);
173+
174+ pixman_region32_translate(&surface_damage,
175+ -surface->geometry.x, -surface->geometry.y);
176+ wld_copy_region(state->drawable, target->drawable, &surface_damage,
177+ surface->geometry.x - target->geometry.x,
178+ surface->geometry.y - target->geometry.y);
179 }
180
181+ pixman_region32_fini(&surface_damage);
182+
183 /* Draw border */
184+ if (pixman_region32_not_empty(&border_damage))
185 {
186- switch_context(renderer, SWC_RENDERER_CONTEXT_BATCH, back_buffer);
187-
188- /* Top */
189- xy_color_blt(&renderer->batch, back_buffer->bo, back_buffer->pitch,
190- surface->geometry.x, surface->geometry.y,
191- surface->geometry.x + surface->geometry.width + 2 * surface_state->border.width,
192- surface->geometry.y + surface_state->border.width,
193- surface_state->border.color);
194- /* Bottom */
195- xy_color_blt(&renderer->batch, back_buffer->bo, back_buffer->pitch,
196- surface->geometry.x,
197- surface->geometry.y + surface_state->border.width + surface->geometry.height,
198- surface->geometry.x + surface->geometry.width + 2 * surface_state->border.width,
199- surface->geometry.y + surface->geometry.height + 2 * surface_state->border.width,
200- surface_state->border.color);
201- /* Left */
202- xy_color_blt(&renderer->batch, back_buffer->bo, back_buffer->pitch,
203- surface->geometry.x, surface->geometry.y + surface_state->border.width,
204- surface->geometry.x + surface_state->border.width,
205- surface->geometry.y + + surface_state->border.width + surface->geometry.height,
206- surface_state->border.color);
207- /* Right */
208- xy_color_blt(&renderer->batch, back_buffer->bo, back_buffer->pitch,
209- surface->geometry.x + surface_state->border.width + surface->geometry.width,
210- surface->geometry.y + surface_state->border.width,
211- surface->geometry.x + surface->geometry.width + 2 * surface_state->border.width,
212- surface->geometry.y + surface_state->border.width + surface->geometry.height,
213- surface_state->border.color);
214+ printf("\tborder\n");
215
216+ pixman_region32_translate(&border_damage,
217+ -target->geometry.x, -target->geometry.y);
218+ wld_fill_region(target->drawable, surface_state->border.color,
219+ &border_damage);
220 }
221+
222+ pixman_region32_fini(&border_damage);
223 }
224
225 bool swc_renderer_initialize(struct swc_renderer * renderer,
226- struct swc_drm * drm,
227- struct gbm_device * gbm)
228+ struct swc_drm * drm)
229 {
230 renderer->drm = drm;
231- renderer->gbm = gbm;
232-
233- intel_batch_initialize(&renderer->batch, drm->bufmgr);
234
235 return true;
236 }
237
238 void swc_renderer_finalize(struct swc_renderer * renderer)
239 {
240- intel_batch_finalize(&renderer->batch);
241 }
242
243-void swc_renderer_repaint_output(struct swc_renderer * renderer,
244- struct swc_output * output,
245- struct wl_list * surfaces)
246+void swc_renderer_set_target(struct swc_renderer * renderer,
247+ struct swc_plane * plane)
248 {
249+ struct wld_drawable * drawable = swc_plane_get_buffer(plane);
250+
251+ renderer->target.drawable = drawable;
252+ renderer->target.geometry.x = plane->output->geometry.x + plane->x;
253+ renderer->target.geometry.y = plane->output->geometry.y + plane->y;
254+ renderer->target.geometry.width = drawable->width;
255+ renderer->target.geometry.height = drawable->height;
256+}
257+
258+void swc_renderer_repaint(struct swc_renderer * renderer,
259+ pixman_region32_t * damage,
260+ pixman_region32_t * base_damage,
261+ struct wl_list * surfaces)
262+{
263+ struct swc_render_target * target = &renderer->target;
264 struct swc_surface * surface;
265- struct swc_buffer * back_buffer;
266
267- back_buffer = swc_output_get_back_buffer(output);
268+ printf("rendering to target { x: %d, y: %d, w: %u, h: %u }\n",
269+ target->geometry.x, target->geometry.y,
270+ target->geometry.width, target->geometry.height);
271
272- switch_context(renderer, SWC_RENDERER_CONTEXT_BATCH, back_buffer);
273+ /* Paint base damage black. */
274+ if (pixman_region32_not_empty(base_damage))
275+ {
276+ pixman_region32_translate(base_damage,
277+ -target->geometry.x, -target->geometry.y);
278+ wld_fill_region(target->drawable, 0xff000000, base_damage);
279+ }
280
281- wl_list_for_each(surface, surfaces, link)
282+ wl_list_for_each_reverse(surface, surfaces, link)
283 {
284- if (surface->outputs & (1 << output->id))
285- repaint_surface_for_output(renderer, surface, output);
286+ if (swc_rectangle_overlap(&target->geometry, &surface->geometry))
287+ repaint_surface(renderer, surface, damage);
288 }
289
290- switch_context(renderer, SWC_RENDERER_CONTEXT_NONE, back_buffer);
291+ wld_flush(target->drawable);
292 }
293
294 void swc_renderer_attach(struct swc_renderer * renderer,
295 struct swc_surface * surface,
296- struct wl_buffer * buffer)
297+ struct wl_resource * resource)
298 {
299 struct buffer_state * state;
300- struct gbm_bo * bo;
301+ struct wl_shm_buffer * shm_buffer;
302+ struct swc_drm_buffer * drm_buffer;
303
304- if (!buffer)
305+ if (!resource)
306 return;
307
308 /* Check if we have already seen this buffer. */
309- if ((state = buffer_state(&buffer->resource)))
310+ if ((state = buffer_state(resource)))
311 return;
312
313 if (!(state = malloc(sizeof *state)))
314 return;
315
316- /* SHM buffer */
317- if (wl_buffer_is_shm(buffer))
318+ if ((shm_buffer = wl_shm_buffer_get(resource)))
319 {
320- struct swc_output * output;
321- uint32_t wayland_format = wl_shm_buffer_get_format(buffer);
322-
323- state->shm.image
324- = pixman_image_create_bits(pixman_format(wayland_format),
325- wl_shm_buffer_get_width(buffer),
326- wl_shm_buffer_get_height(buffer),
327- wl_shm_buffer_get_data(buffer),
328- wl_shm_buffer_get_stride(buffer));
329+ uint32_t width = wl_shm_buffer_get_width(shm_buffer),
330+ height = wl_shm_buffer_get_height(shm_buffer),
331+ format = wl_shm_buffer_get_format(shm_buffer),
332+ pitch = wl_shm_buffer_get_stride(shm_buffer);
333+ void * data = wl_shm_buffer_get_data(shm_buffer);
334+
335+ state->drawable = wld_drm_create_drawable(renderer->drm->context,
336+ width, height,
337+ wld_format(format));
338+ state->src = pixman_image_create_bits_no_clear(pixman_format(format),
339+ width, height,
340+ data, pitch);
341+ state->dst = wld_map(state->drawable);
342 }
343- /* DRM buffer */
344- else if ((bo = gbm_bo_import(renderer->gbm, GBM_BO_IMPORT_WL_BUFFER, buffer,
345- GBM_BO_USE_RENDERING)))
346+ else if ((drm_buffer = swc_drm_buffer_get(resource)))
347 {
348- int handle = gbm_bo_get_handle(bo).s32;
349- struct drm_gem_flink flink = { .handle = handle };
350-
351- if (drmIoctl(renderer->drm->fd, DRM_IOCTL_GEM_FLINK, &flink) != 0)
352- {
353- printf("could not flink handle\n");
354+ if (!(state = malloc(sizeof *state)))
355 return;
356- }
357-
358- state->drm.bo
359- = drm_intel_bo_gem_create_from_name(renderer->drm->bufmgr,
360- "surface", flink.name);
361- state->drm.pitch = gbm_bo_get_stride(bo);
362- state->drm.width = gbm_bo_get_width(bo);
363- state->drm.height = gbm_bo_get_height(bo);
364
365- printf("pitch: %u, width: %u, height: %u\n", state->drm.pitch,
366- state->drm.width, state->drm.height);
367+ state->drawable = drm_buffer->drawable;
368+ state->src = NULL;
369+ state->dst = NULL;
370+ }
371+ else
372+ {
373+ fprintf(stderr, "Unsupported buffer type\n");
374+ return;
375 }
376+
377+ state->destroy_listener.notify = &handle_buffer_destroy;
378+ wl_resource_add_destroy_listener(resource, &state->destroy_listener);
379+}
380+
381+void swc_renderer_flush(struct swc_renderer * renderer,
382+ struct swc_surface * surface)
383+{
384+ struct wl_shm_buffer * buffer;
385+ struct buffer_state * state;
386+
387+ if (!(buffer = wl_shm_buffer_get(surface->state.buffer)))
388+ return;
389+
390+ state = buffer_state(surface->state.buffer);
391+ assert(state);
392+
393+ pixman_image_set_clip_region32(state->src, &surface->state.damage);
394+ pixman_image_composite32(PIXMAN_OP_SRC, state->src, NULL, state->dst,
395+ 0, 0, 0, 0, 0, 0,
396+ state->drawable->width, state->drawable->height);
397 }
398
+16,
-14
1@@ -5,35 +5,37 @@
2 #include "surface.h"
3 #include "drm.h"
4
5-#include <intelbatch/batch.h>
6-
7-enum swc_renderer_context
8+struct swc_render_target
9 {
10- SWC_RENDERER_CONTEXT_NONE,
11- SWC_RENDERER_CONTEXT_SHM,
12- SWC_RENDERER_CONTEXT_BATCH
13+ struct wld_drawable * drawable;
14+ pixman_rectangle32_t geometry;
15 };
16
17 struct swc_renderer
18 {
19 struct swc_drm * drm;
20- struct gbm_device * gbm;
21- enum swc_renderer_context context;
22- struct intel_batch batch;
23+ struct swc_render_target target;
24 };
25
26 bool swc_renderer_initialize(struct swc_renderer * renderer,
27- struct swc_drm * drm, struct gbm_device * gbm);
28+ struct swc_drm * drm);
29
30 void swc_renderer_finalize(struct swc_renderer * renderer);
31
32-void swc_renderer_repaint_output(struct swc_renderer * renderer,
33- struct swc_output * output,
34- struct wl_list * surfaces);
35+void swc_renderer_set_target(struct swc_renderer * renderer,
36+ struct swc_plane * plane);
37+
38+void swc_renderer_repaint(struct swc_renderer * renderer,
39+ pixman_region32_t * damage,
40+ pixman_region32_t * base_damage,
41+ struct wl_list * surfaces);
42
43 void swc_renderer_attach(struct swc_renderer * renderer,
44 struct swc_surface * surface,
45- struct wl_buffer * buffer);
46+ struct wl_resource * resource);
47+
48+void swc_renderer_flush(struct swc_renderer * renderer,
49+ struct swc_surface * surface);
50
51 #endif
52
+34,
-15
1@@ -25,9 +25,11 @@
2 #include "event.h"
3 #include "region.h"
4 #include "util.h"
5+#include "drm_buffer.h"
6
7 #include <stdlib.h>
8 #include <stdio.h>
9+#include <wld/wld.h>
10
11 static pixman_box32_t infinite_extents = {
12 .x1 = INT32_MIN, .y1 = INT32_MIN,
13@@ -83,7 +85,7 @@ static void state_finish(struct swc_surface_state * state)
14 * @return: Whether or not the buffer was changed.
15 */
16 static bool state_set_buffer(struct swc_surface_state * state,
17- struct wl_buffer * buffer)
18+ struct wl_resource * buffer)
19 {
20 if (buffer == state->buffer)
21 return false;
22@@ -98,7 +100,7 @@ static bool state_set_buffer(struct swc_surface_state * state,
23 {
24 /* Need to watch the new buffer for destruction so we can remove it
25 * from state. */
26- wl_resource_add_destroy_listener(&buffer->resource,
27+ wl_resource_add_destroy_listener(buffer,
28 &state->buffer_destroy_listener);
29 }
30
31@@ -107,6 +109,17 @@ static bool state_set_buffer(struct swc_surface_state * state,
32 return true;
33 }
34
35+static void set_size(struct swc_surface * surface,
36+ uint32_t width, uint32_t height)
37+{
38+ /* Check if the surface was resized. */
39+ if (width != surface->geometry.width || height != surface->geometry.height)
40+ {
41+ surface->geometry.width = width;
42+ surface->geometry.height = height;
43+ }
44+}
45+
46 static void destroy(struct wl_client * client, struct wl_resource * resource)
47 {
48 wl_resource_destroy(resource);
49@@ -116,14 +129,8 @@ static void attach(struct wl_client * client, struct wl_resource * resource,
50 struct wl_resource * buffer_resource, int32_t x, int32_t y)
51 {
52 struct swc_surface * surface = wl_resource_get_user_data(resource);
53- struct wl_buffer * buffer
54- = buffer_resource ? wl_resource_get_user_data(buffer_resource) : NULL;
55-
56- state_set_buffer(&surface->pending.state, buffer);
57
58- /* Adjust geometry of the surface to match the buffer. */
59- surface->geometry.width = buffer ? buffer->width : 0;
60- surface->geometry.height = buffer ? buffer->height : 0;
61+ state_set_buffer(&surface->pending.state, buffer_resource);
62
63 surface->pending.x = x;
64 surface->pending.y = y;
65@@ -199,16 +206,28 @@ static void commit(struct wl_client * client, struct wl_resource * resource)
66 /* Attach */
67 if (surface->state.buffer != surface->pending.state.buffer)
68 {
69- if (surface->state.buffer)
70+ struct wl_shm_buffer * shm_buffer;
71+ struct swc_drm_buffer * drm_buffer;
72+
73+ if (surface->state.buffer
74+ && surface->state.buffer != surface->pending.state.buffer)
75 {
76- /* Release the old buffer, it's no longer needed. */
77- wl_buffer_send_release(&surface->state.buffer->resource);
78+ wl_buffer_send_release(surface->state.buffer);
79 }
80
81 state_set_buffer(&surface->state, surface->pending.state.buffer);
82
83- surface->class->interface->attach(surface,
84- &surface->state.buffer->resource);
85+ /* Determine size of buffer. */
86+ if ((shm_buffer = wl_shm_buffer_get(surface->state.buffer)))
87+ {
88+ set_size(surface, wl_shm_buffer_get_width(shm_buffer),
89+ wl_shm_buffer_get_height(shm_buffer));
90+ }
91+ else if ((drm_buffer = swc_drm_buffer_get(surface->state.buffer)))
92+ {
93+ set_size(surface, drm_buffer->drawable->width,
94+ drm_buffer->drawable->height);
95+ }
96 }
97
98 /* Damage */
99@@ -369,7 +388,7 @@ void swc_surface_set_class(struct swc_surface * surface,
100 }
101
102
103- surface->class->interface->attach(surface, &surface->state.buffer->resource);
104+ surface->class->interface->attach(surface, surface->state.buffer);
105 surface->class->interface->update(surface);
106 }
107 }
+1,
-1
1@@ -32,7 +32,7 @@ struct swc_surface;
2
3 struct swc_surface_state
4 {
5- struct wl_buffer * buffer;
6+ struct wl_resource * buffer;
7
8 /* The region that needs to be repainted */
9 pixman_region32_t damage;