pepper_bool_t vblank_pending;
pepper_bool_t page_flip_pending;
+ pepper_object_t *primary_plane;
+
/* TODO */
};
#include "drm-internal.h"
+#include <pepper-output-backend.h>
#include <pepper-pixman-renderer.h>
#include <pepper-gl-renderer.h>
}
static void
-drm_output_repaint(void *o, const pepper_list_t *view_list, const pixman_region32_t *damage)
+drm_output_assign_planes(void *o, const pepper_list_t *view_list)
+{
+ drm_output_t *output = (drm_output_t *)o;
+ pepper_list_t *l;
+
+ PEPPER_LIST_FOR_EACH(view_list, l)
+ {
+ pepper_object_t *view = l->item;
+ pepper_view_assign_plane(view, output->base, output->primary_plane);
+ }
+}
+
+static void
+drm_output_repaint(void *o, const pepper_list_t *plane_list)
{
int ret;
drm_output_t *output = (drm_output_t *)o;
+ pepper_list_t *l;
- pepper_renderer_set_target(output->renderer, output->render_target);
- pepper_renderer_repaint_output(output->renderer, output->base, view_list, damage);
+ PEPPER_LIST_FOR_EACH(plane_list, l)
+ {
+ pepper_object_t *plane = l->item;
- update_back_buffer(output);
+ if (plane == output->primary_plane)
+ {
+ pixman_region32_t *damage = pepper_plane_get_damage_region(plane);
+ const pepper_list_t *render_list = pepper_plane_get_render_list(plane);
- if (!output->back_fb)
- return;
+ pepper_renderer_set_target(output->renderer, output->render_target);
+ pepper_renderer_repaint_output(output->renderer, output->base, render_list, damage);
- if (!output->front_fb)
- {
- ret = drmModeSetCrtc(output->drm->drm_fd, output->crtc_id, output->back_fb->id,
- 0, 0, &output->conn_id, 1, output->current_mode);
- }
+ /* NULL means that whole damage region is updated.
+ * If only visible damage region is updated, pass that region to this function
+ * so that pepper core correctly manage remaining damage region. */
+ pepper_plane_subtract_damage_region(plane, NULL);
- ret = drmModePageFlip(output->drm->drm_fd, output->crtc_id, output->back_fb->id,
- DRM_MODE_PAGE_FLIP_EVENT, output);
- if (ret < 0)
- {
- PEPPER_ERROR("Failed to queue pageflip in %s\n", __FUNCTION__);
- return;
- }
+ update_back_buffer(output);
- output->page_flip_pending = PEPPER_TRUE;
+ if (!output->back_fb)
+ return;
- /* TODO: set planes */
+ if (!output->front_fb)
+ {
+ ret = drmModeSetCrtc(output->drm->drm_fd, output->crtc_id, output->back_fb->id,
+ 0, 0, &output->conn_id, 1, output->current_mode);
+ }
+
+ ret = drmModePageFlip(output->drm->drm_fd, output->crtc_id, output->back_fb->id,
+ DRM_MODE_PAGE_FLIP_EVENT, output);
+ if (ret < 0)
+ {
+ PEPPER_ERROR("Failed to queue pageflip in %s\n", __FUNCTION__);
+ return;
+ }
+
+ output->page_flip_pending = PEPPER_TRUE;
+ }
+
+ /* TODO: Cursor plane. */
+
+ /* TODO: drmModeSetPlane(). */
+ }
}
static void
drm_output_get_mode,
drm_output_set_mode,
+ drm_output_assign_planes,
drm_output_repaint,
drm_output_attach_surface,
drm_output_add_frame_listener,
continue;
}
+ output->primary_plane = pepper_output_add_plane(output->base, NULL);
drmModeFreeConnector(conn);
}
drmModeFreeConnector(conn);
continue;
}
+
+ output->primary_plane = pepper_output_add_plane(output->base, NULL);
}
drmModeFreeConnector(conn);
struct wl_signal mode_change_signal;
struct wl_signal frame_signal;
+ pepper_object_t *primary_plane;
/* TODO */
};
#include <sys/stat.h>
#include <unistd.h>
+#include <pepper-output-backend.h>
#include <pepper-pixman-renderer.h>
#include <pepper-gl-renderer.h>
}
static void
-fbdev_output_repaint(void *o, const pepper_list_t *view_list, const pixman_region32_t *damage)
+fbdev_output_assign_planes(void *o, const pepper_list_t *view_list)
{
fbdev_output_t *output = (fbdev_output_t *)o;
- pepper_renderer_repaint_output(output->renderer, output->base, view_list, damage);
+ pepper_list_t *l;
- /* FIXME: composite with damage? */
- if (output->use_shadow)
- pixman_image_composite32(PIXMAN_OP_SRC, output->shadow_image, NULL,
- output->frame_buffer_image, 0, 0, 0, 0, 0, 0,
- output->w, output->h);
+ PEPPER_LIST_FOR_EACH(view_list, l)
+ {
+ pepper_object_t *view = l->item;
+ pepper_view_assign_plane(view, output->base, output->primary_plane);
+ }
+}
+
+static void
+fbdev_output_repaint(void *o, const pepper_list_t *plane_list)
+{
+ fbdev_output_t *output = (fbdev_output_t *)o;
+ pepper_list_t *l;
+
+ PEPPER_LIST_FOR_EACH(plane_list, l)
+ {
+ pepper_object_t *plane = l->item;
+
+ if (plane == output->primary_plane)
+ {
+ const pepper_list_t *render_list = pepper_plane_get_render_list(plane);
+ pixman_region32_t *damage = pepper_plane_get_damage_region(plane);
+
+ pepper_renderer_repaint_output(output->renderer, output->base, render_list, damage);
+
+ /* FIXME: composite with damage? */
+ if (output->use_shadow)
+ pixman_image_composite32(PIXMAN_OP_SRC, output->shadow_image, NULL,
+ output->frame_buffer_image, 0, 0, 0, 0, 0, 0,
+ output->w, output->h);
+ }
+
+ /* TODO: No overlays on fbdev??? */
+ }
}
static void
fbdev_output_get_mode,
fbdev_output_set_mode,
+ fbdev_output_assign_planes,
fbdev_output_repaint,
fbdev_output_attach_surface,
fbdev_output_add_frame_listener,
goto error;
}
+ output->primary_plane = pepper_output_add_plane(output->base, NULL);
wl_list_insert(&fbdev->output_list, &output->link);
+
return PEPPER_TRUE;
error:
lib_LTLIBRARIES = libpepper.la
-include_HEADERS = pepper.h pepper-utils.h
+include_HEADERS = pepper.h pepper-utils.h pepper-output-backend.h
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = pepper.pc
buffer.c \
data-device.c \
view.c \
+ plane.c \
utils-file.c \
utils-map.c \
utils-log.c \
compositor_bind);
wl_list_init(&compositor->surfaces);
wl_list_init(&compositor->seat_list);
- wl_list_init(&compositor->output_list);
+ pepper_list_init(&compositor->output_list);
wl_list_init(&compositor->event_hook_chain);
-
- pepper_list_init(&compositor->root_view_list);
pepper_list_init(&compositor->view_list);
/* Install default input event handler */
CHECK_MAGIC_AND_NON_NULL(cmp, PEPPER_COMPOSITOR);
return compositor->display;
}
-
-void
-pepper_compositor_add_damage(pepper_compositor_t *compositor, const pixman_region32_t *region)
-{
- pepper_output_t *output;
-
- CHECK_MAGIC_AND_NON_NULL(&compositor->base, PEPPER_COMPOSITOR);
-
- wl_list_for_each(output, &compositor->output_list, link)
- pepper_output_add_damage(&output->base, region, output->geometry.x, output->geometry.y);
-}
-
-void
-pepper_compositor_add_damage_rect(pepper_compositor_t *compositor,
- int x, int y, unsigned int w, unsigned int h)
-{
- pixman_region32_t region;
-
- pixman_region32_init_rect(®ion, x, y, w, h);
- pepper_compositor_add_damage(compositor, ®ion);
- pixman_region32_fini(®ion);
-}
-
-void
-pepper_compositor_schedule_repaint(pepper_compositor_t *compositor)
-{
- pepper_output_t *output;
-
- CHECK_MAGIC_AND_NON_NULL(&compositor->base, PEPPER_COMPOSITOR);
-
- wl_list_for_each(output, &compositor->output_list, link)
- pepper_output_schedule_repaint(output);
-}
}
static void
+output_accumulate_damage(pepper_output_t *output)
+{
+ pepper_list_t *l;
+ pixman_region32_t clip;
+ pixman_region32_t plane_clip;
+
+ pixman_region32_init(&clip);
+
+ PEPPER_LIST_FOR_EACH_REVERSE(&output->plane_list, l)
+ {
+ pepper_plane_t *plane = l->item;
+
+ pepper_plane_accumulate_damage(plane, &plane_clip);
+ pixman_region32_copy(&plane->clip_region, &clip);
+ pixman_region32_union(&clip, &clip, &plane_clip);
+ }
+
+ pixman_region32_fini(&clip);
+}
+
+static void
+output_repaint(pepper_output_t *output)
+{
+ pepper_list_t *l;
+
+ PEPPER_LIST_FOR_EACH(&output->compositor->view_list, l)
+ pepper_view_update_geometry((pepper_view_t *)l->item);
+
+ pepper_list_init(&output->view_list);
+
+ /* Build a list of views in sorted z-order that are visible on the given output. */
+ PEPPER_LIST_FOR_EACH(&output->compositor->view_list, l)
+ {
+ pepper_view_t *view = l->item;
+
+ if (!view->visibility || !(view->output_overlap & (1 << output->id)))
+ {
+ /* Detach from the previously assigned plane. */
+ pepper_view_assign_plane(&view->base, &output->base, NULL);
+ continue;
+ }
+
+ pepper_list_insert(&output->view_list, &view->link);
+ view->link.item = view;
+ }
+
+ output->backend->assign_planes(output->data, &output->view_list);
+
+ PEPPER_LIST_FOR_EACH(&output->plane_list, l)
+ pepper_plane_update((pepper_plane_t *)l->item, &output->view_list);
+
+ output_accumulate_damage(output);
+ output->backend->repaint(output->data, &output->plane_list);
+
+ output->frame.pending = PEPPER_TRUE;
+ output->frame.scheduled = PEPPER_FALSE;
+
+ /* TODO: Send frame done to the callback objects of this output. */
+}
+
+static void
handle_output_frame(struct wl_listener *listener, void *data)
{
pepper_output_t *output = pepper_container_of(listener, pepper_output_t, frame.frame_listener);
/* TODO: Better repaint scheduling by putting a delay before repaint. */
if (output->frame.scheduled)
- pepper_output_repaint(output);
+ output_repaint(output);
}
static void
if (!output->frame.pending)
{
/* We can repaint a frame immediately if it is not in pending state. */
- pepper_output_repaint(output);
+ output_repaint(output);
}
}
output->frame.scheduled = PEPPER_TRUE;
}
-void
-pepper_output_repaint(pepper_output_t *output)
+PEPPER_API void
+pepper_output_add_damage_region(pepper_object_t *out, pixman_region32_t *region)
{
- PEPPER_ASSERT(!output->frame.pending);
-
- pepper_compositor_update_views(output->compositor);
-
- output->backend->repaint(output->data, &output->compositor->view_list, &output->damage_region);
- output->frame.pending = PEPPER_TRUE;
- output->frame.scheduled = PEPPER_FALSE;
+ pepper_list_t *l;
+ pepper_output_t *output = (pepper_output_t *)out;
- /* TODO: Send frame done to the callback objects of this output. */
+ CHECK_MAGIC_AND_NON_NULL(out, PEPPER_OUTPUT);
- /* Output has been repainted, so damage region is totally consumed. */
- pixman_region32_clear(&output->damage_region);
+ PEPPER_LIST_FOR_EACH(&output->plane_list, l)
+ pepper_plane_add_damage_region((pepper_plane_t *)l->item, region);
}
PEPPER_API pepper_object_t *
output->geometry.w = output->current_mode->w;
output->geometry.h = output->current_mode->h;
- wl_list_insert(&compositor->output_list, &output->link);
+ pepper_list_insert(&compositor->output_list, &output->link);
+ output->link.item = output;
/* Install listeners. */
output->data_destroy_listener.notify = handle_output_data_destroy;
output->frame.frame_listener.notify = handle_output_frame;
backend->add_frame_listener(data, &output->frame.frame_listener);
- pepper_output_add_damage_whole(&output->base);
+ pepper_list_init(&output->plane_list);
return &output->base;
}
pepper_object_fini(&output->base);
output->compositor->output_id_allocator &= ~(1 << output->id);
- wl_list_remove(&output->link);
+ pepper_list_remove(&output->link, NULL);
if (output->backend && output->data)
output->backend->destroy(output->data);
output->geometry.x = x;
output->geometry.y = y;
- pepper_output_add_damage_whole(out);
+ /* TODO: pepper_output_add_damage_whole(out); */
output_send_geometry(output);
}
}
if (output->backend->set_mode(output->data, mode))
{
- pepper_output_add_damage_whole(out);
+ /* TODO: pepper_output_add_damage_whole(out); */
return PEPPER_TRUE;
}
return PEPPER_FALSE;
}
-
-PEPPER_API void
-pepper_output_add_damage(pepper_object_t *out,
- const pixman_region32_t *region, int x, int y)
-{
- pepper_output_t *output = (pepper_output_t *)out;
- pixman_region32_t damage;
-
- CHECK_MAGIC_AND_NON_NULL(out, PEPPER_OUTPUT);
-
- pixman_region32_init(&damage);
- pixman_region32_copy(&damage, (pixman_region32_t *)region);
- pixman_region32_translate(&damage, x, y);
- pixman_region32_intersect_rect(&damage, &damage, 0, 0, output->geometry.w, output->geometry.h);
-
- if (pixman_region32_not_empty(&damage))
- {
- pixman_region32_union(&output->damage_region, &output->damage_region, &damage);
- pepper_output_schedule_repaint(output);
- }
-
- pixman_region32_fini(&damage);
-}
-
-PEPPER_API void
-pepper_output_add_damage_rect(pepper_object_t *out, int x, int y, unsigned int w, unsigned int h)
-{
- pepper_output_t *output = (pepper_output_t *)out;
- pixman_region32_t damage;
-
- CHECK_MAGIC_AND_NON_NULL(out, PEPPER_OUTPUT);
-
- pixman_region32_init_rect(&damage, x, y, w, h);
- pixman_region32_intersect_rect(&damage, &damage, 0, 0, output->geometry.w, output->geometry.h);
-
- if (pixman_region32_not_empty(&damage))
- pixman_region32_union(&output->damage_region, &output->damage_region, &damage);
-
- pixman_region32_fini(&damage);
- pepper_output_schedule_repaint(output);
-}
-
-PEPPER_API void
-pepper_output_add_damage_whole(pepper_object_t *out)
-{
- pepper_output_t *output = (pepper_output_t *)out;
-
- CHECK_MAGIC_AND_NON_NULL(out, PEPPER_OUTPUT);
- pixman_region32_init_rect(&output->damage_region, 0, 0, output->geometry.w, output->geometry.h);
- pepper_output_schedule_repaint(output);
-}
#include "pepper.h"
#include <wayland-util.h>
#include <pixman.h>
+#include <pepper-output-backend.h>
typedef struct pepper_compositor pepper_compositor_t;
typedef struct pepper_output pepper_output_t;
typedef struct pepper_pointer pepper_pointer_t;
typedef struct pepper_keyboard pepper_keyboard_t;
typedef struct pepper_touch pepper_touch_t;
+typedef struct pepper_plane pepper_plane_t;
#define CHECK_NON_NULL(ptr) \
do { \
CHECK_MAGIC(obj, val); \
} while (0)
-#define PEPPER_MAX_OUTPUT_ID 32
+#define PEPPER_MAX_OUTPUT_COUNT 32
typedef struct pepper_region pepper_region_t;
typedef struct pepper_surface_state pepper_surface_state_t;
+typedef struct pepper_plane_entry pepper_plane_entry_t;
typedef struct pepper_data_source pepper_data_source_t;
typedef struct pepper_data_device pepper_data_device_t;
typedef struct pepper_data_offer pepper_data_offer_t;
PEPPER_POINTER = 0x00000007,
PEPPER_KEYBOARD = 0x00000008,
PEPPER_TOUCH = 0x00000009,
+ PEPPER_PLANE = 0x0000000a,
};
struct pepper_object
struct wl_list surfaces;
struct wl_list regions;
struct wl_list seat_list;
- struct wl_list output_list;
+ pepper_list_t output_list;
uint32_t output_id_allocator;
struct wl_list event_hook_chain;
- pepper_list_t root_view_list;
pepper_list_t view_list;
};
struct wl_global *global;
struct wl_list resources;
- struct wl_list link;
+ pepper_list_t link;
pepper_output_geometry_t geometry;
int32_t scale;
struct wl_listener frame_listener;
} frame;
- /* Region damaged but not repainted. */
- pixman_region32_t damage_region;
+ pepper_list_t plane_list;
+ pepper_list_t view_list;
};
void
pepper_output_schedule_repaint(pepper_output_t *output);
-void
-pepper_output_repaint(pepper_output_t *output);
-
struct pepper_buffer
{
pepper_object_t base;
char *role;
pepper_map_t *user_data_map;
- struct wl_list view_list;
+ pepper_list_t view_list;
};
pepper_surface_t *
pepper_bool_t
pepper_data_device_manager_init(struct wl_display *display);
+struct pepper_plane_entry
+{
+ pepper_render_item_t base;
+
+ pepper_plane_t *plane;
+ struct wl_listener plane_destroy_listener;
+ pepper_bool_t need_damage;
+
+ pepper_list_t link;
+};
+
struct pepper_view
{
pepper_object_t base;
pepper_compositor_t *compositor;
+ pepper_list_t compositor_link;
- /* Hierarchy & Z-order. */
+ /* Hierarchy. */
pepper_view_t *parent;
- pepper_list_t children_list;
pepper_list_t parent_link;
- pepper_list_t z_link;
+ pepper_list_t children_list;
/* Geometry. */
+ pepper_bool_t geometry_dirty;
double x, y;
int w, h;
pepper_mat4_t transform;
- pepper_mat4_t matrix_to_parent;
- pepper_mat4_t matrix_to_global;
+ pepper_mat4_t global_transform;
+
pixman_region32_t bounding_region;
- pepper_bool_t geometry_dirty;
+ pixman_region32_t opaque_region;
/* Visibility. */
pepper_bool_t visibility;
/* Content. */
pepper_surface_t *surface;
- struct wl_list surface_link;
+ pepper_list_t surface_link;
struct wl_listener surface_destroy_listener;
- pixman_region32_t opaque_region;
- pixman_region32_t visible_region;
+ /* Output info. */
+ uint32_t output_overlap;
+ pepper_plane_entry_t plane_entries[PEPPER_MAX_OUTPUT_COUNT];
- pepper_view_state_t state;
+ /* Temporary resource. */
+ pepper_list_t link;
};
void
-pepper_compositor_update_views(pepper_compositor_t *compositor);
+pepper_view_assign_plane(pepper_object_t *view, pepper_object_t *output, pepper_object_t *plane);
+
+void
+pepper_view_damage_below(pepper_view_t *view);
+
+void
+pepper_view_update_geometry(pepper_view_t *view);
+
+struct pepper_plane
+{
+ pepper_object_t base;
+ pepper_output_t *output;
+
+ pepper_list_t entry_list;
+ pixman_region32_t damage_region;
+ pixman_region32_t clip_region;
+
+ pepper_list_t link;
+};
+
+pepper_object_t *
+pepper_plane_create(pepper_object_t *output, pepper_object_t *above_plane);
+
+void
+pepper_plane_destroy(pepper_object_t *plane);
+
+pixman_region32_t *
+pepper_plane_get_damage_region(pepper_object_t *plane);
+
+pixman_region32_t *
+pepper_plane_get_clip_region(pepper_object_t *plane);
+
+const pepper_list_t *
+pepper_plane_get_render_node_list(pepper_object_t *plane);
+
+void
+pepper_plane_subtract_damage_region(pepper_object_t *plane, pixman_region32_t *region);
+
+void
+pepper_plane_add_damage_region(pepper_plane_t *plane, pixman_region32_t *region);
+
+void
+pepper_plane_accumulate_damage(pepper_plane_t *plane, pixman_region32_t *clip);
+
+void
+pepper_plane_update(pepper_plane_t *plane, const pepper_list_t *view_list);
/* Event hook */
struct pepper_event_hook
void *data);
void
-pepper_compositor_add_damage(pepper_compositor_t *compositor, const pixman_region32_t *region);
-
-void
-pepper_compositor_add_damage_rect(pepper_compositor_t *compositor,
- int x, int y, unsigned int w, unsigned int h);
-
-void
pepper_surface_flush_damage(pepper_surface_t *surface);
#endif /* PEPPER_INTERNAL_H */
--- /dev/null
+#ifndef PEPPER_OUTPUT_BACKEND_H
+#define PEPPER_OUTPUT_BACKEND_H
+
+#include <pepper.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct pepper_output_backend pepper_output_backend_t;
+typedef struct pepper_render_item pepper_render_item_t;
+
+struct pepper_output_backend
+{
+ void (*destroy)(void *output);
+
+ void (*add_destroy_listener)(void *output, struct wl_listener *listener);
+ void (*add_mode_change_listener)(void *output, struct wl_listener *listener);
+
+ int32_t (*get_subpixel_order)(void *output);
+ const char * (*get_maker_name)(void *output);
+ const char * (*get_model_name)(void *output);
+
+ int (*get_mode_count)(void *output);
+ void (*get_mode)(void *output, int index, pepper_output_mode_t *mode);
+ pepper_bool_t (*set_mode)(void *output, const pepper_output_mode_t *mode);
+
+ void (*assign_planes)(void *output, const pepper_list_t *view_list);
+ void (*repaint)(void *output, const pepper_list_t *plane_list);
+ void (*attach_surface)(void *output, pepper_object_t *surface, int *w, int *h);
+
+ void (*add_frame_listener)(void *output, struct wl_listener *listener);
+};
+
+PEPPER_API pepper_object_t *
+pepper_compositor_add_output(pepper_object_t *compositor,
+ const pepper_output_backend_t *backend, void *data);
+
+struct pepper_render_item
+{
+ pepper_object_t *view;
+ pepper_mat4_t transform;
+ pixman_region32_t visible_region;
+};
+
+PEPPER_API pepper_object_t *
+pepper_output_add_plane(pepper_object_t *output, pepper_object_t *above_plane);
+
+PEPPER_API void
+pepper_plane_destroy(pepper_object_t *plane);
+
+PEPPER_API pixman_region32_t *
+pepper_plane_get_damage_region(pepper_object_t *plane);
+
+PEPPER_API pixman_region32_t *
+pepper_plane_get_clip_region(pepper_object_t *plane);
+
+PEPPER_API const pepper_list_t *
+pepper_plane_get_render_list(pepper_object_t *plane);
+
+PEPPER_API void
+pepper_plane_subtract_damage_region(pepper_object_t *plane, pixman_region32_t *damage);
+
+PEPPER_API void
+pepper_view_assign_plane(pepper_object_t *view, pepper_object_t *output, pepper_object_t *plane);
+
+PEPPER_API void
+pepper_output_add_damage_region(pepper_object_t *output, pixman_region32_t *region);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PEPPER_OUTPUT_BACKEND_H */
#endif
typedef struct pepper_object pepper_object_t;
-
typedef struct pepper_output_geometry pepper_output_geometry_t;
typedef struct pepper_output_mode pepper_output_mode_t;
-typedef struct pepper_output_backend pepper_output_backend_t;
-
typedef struct pepper_seat_backend pepper_seat_backend_t;
-
typedef struct pepper_input_event pepper_input_event_t;
typedef struct pepper_event_hook pepper_event_hook_t;
-typedef struct pepper_view_state pepper_view_state_t;
-
-struct pepper_view_state
-{
- pepper_object_t *view;
- const pepper_mat4_t *transform;
- const pixman_region32_t *bounding;
- const pixman_region32_t *opaque;
- const pixman_region32_t *visible;
-};
-
struct pepper_output_geometry
{
int32_t x;
int32_t refresh;
};
-struct pepper_output_backend
-{
- void (*destroy)(void *output);
-
- void (*add_destroy_listener)(void *output, struct wl_listener *listener);
- void (*add_mode_change_listener)(void *output, struct wl_listener *listener);
-
- int32_t (*get_subpixel_order)(void *output);
- const char * (*get_maker_name)(void *output);
- const char * (*get_model_name)(void *output);
-
- int (*get_mode_count)(void *output);
- void (*get_mode)(void *output, int index, pepper_output_mode_t *mode);
- pepper_bool_t (*set_mode)(void *output, const pepper_output_mode_t *mode);
-
- void (*repaint)(void *output,
- const pepper_list_t *view_list, const pixman_region32_t *damage);
- void (*attach_surface)(void *output, pepper_object_t *surface, int *w, int *h);
-
- void (*add_frame_listener)(void *output, struct wl_listener *listener);
-};
-
/* Generic object functions. */
PEPPER_API void
pepper_object_set_user_data(pepper_object_t *object, const void *key, void *data,
pepper_compositor_get_display(pepper_object_t *compositor);
PEPPER_API pepper_object_t *
-pepper_compositor_add_output(pepper_object_t *compositor,
- const pepper_output_backend_t *backend,
- void *data);
-
-PEPPER_API pepper_object_t *
pepper_compositor_add_seat(pepper_object_t *compositor,
const pepper_seat_backend_t *backend,
void *data);
PEPPER_API pepper_bool_t
pepper_output_set_mode(pepper_object_t *output, const pepper_output_mode_t *mode);
-PEPPER_API void
-pepper_output_add_damage(pepper_object_t *output,
- const pixman_region32_t *region, int x, int y);
-
-PEPPER_API void
-pepper_output_add_damage_rect(pepper_object_t *output, int x, int y, unsigned int w, unsigned int h);
-
-PEPPER_API void
-pepper_output_add_damage_whole(pepper_object_t *output);
-
/* Input. */
struct pepper_seat_backend
{
--- /dev/null
+#include "pepper-internal.h"
+
+void
+pepper_plane_update(pepper_plane_t *plane, const pepper_list_t *view_list)
+{
+ pepper_list_t *l;
+ double output_x = plane->output->geometry.x;
+ double output_y = plane->output->geometry.y;
+
+ pepper_list_init(&plane->entry_list);
+
+ PEPPER_LIST_FOR_EACH(view_list, l)
+ {
+ pepper_view_t *view = l->item;
+ pepper_plane_entry_t *entry = &view->plane_entries[plane->output->id];
+
+ if (entry->plane == plane)
+ {
+ pepper_list_insert(&plane->entry_list, &entry->link);
+
+ /* Calculate view transform on output local coordinate space. */
+ pepper_mat4_init_translate(&entry->base.transform, -output_x, -output_y, 0.0);
+ pepper_mat4_multiply(&entry->base.transform,
+ &entry->base.transform, &view->global_transform);
+ }
+ }
+}
+
+void
+pepper_plane_accumulate_damage(pepper_plane_t *plane, pixman_region32_t *clip)
+{
+ pepper_list_t *l;
+ int x = plane->output->geometry.x;
+ int y = plane->output->geometry.y;
+ int w = plane->output->geometry.w;
+ int h = plane->output->geometry.h;
+
+ pixman_region32_init(clip);
+
+ PEPPER_LIST_FOR_EACH_REVERSE(&plane->entry_list, l)
+ {
+ pepper_plane_entry_t *entry = l->item;
+ pepper_view_t *view = (pepper_view_t *)entry->base.view;
+
+ pixman_region32_subtract(&entry->base.visible_region, &view->bounding_region, clip);
+ pixman_region32_translate(&entry->base.visible_region, -x, -y);
+ pixman_region32_intersect_rect(&entry->base.visible_region,
+ &entry->base.visible_region, 0, 0, w, h);
+
+ pixman_region32_union(clip, clip, &view->opaque_region);
+
+ if (entry->need_damage)
+ {
+ pepper_view_damage_below(view);
+ entry->need_damage = PEPPER_FALSE;
+ }
+ }
+
+ pixman_region32_translate(clip, -x, -y);
+ pixman_region32_intersect_rect(clip, clip, 0, 0, w, h);
+}
+
+PEPPER_API pepper_object_t *
+pepper_output_add_plane(pepper_object_t *out, pepper_object_t *above_plane)
+{
+ pepper_plane_t *plane;
+ pepper_output_t *output = (pepper_output_t *)out;
+ pepper_plane_t *above = (pepper_plane_t *)above_plane;
+
+ CHECK_MAGIC_AND_NON_NULL(out, PEPPER_OUTPUT);
+ CHECK_MAGIC_IF_NON_NULL(above_plane, PEPPER_PLANE);
+
+ if (above && above->output != output)
+ return NULL;
+
+ plane = (pepper_plane_t *)pepper_object_alloc(sizeof(pepper_plane_t), PEPPER_PLANE);
+ if (!plane)
+ return NULL;
+
+ plane->output = output;
+ plane->link.item = plane;
+
+ if (above)
+ pepper_list_insert(above->link.prev, &plane->link);
+ else
+ pepper_list_insert(output->plane_list.prev, &plane->link);
+
+ pepper_list_init(&plane->entry_list);
+ pixman_region32_init(&plane->damage_region);
+ pixman_region32_init(&plane->clip_region);
+
+ return &plane->base;
+}
+
+void
+pepper_plane_destroy(pepper_object_t *pln)
+{
+ pepper_plane_t *plane = (pepper_plane_t *)pln;
+ pepper_list_t *l;
+
+ CHECK_MAGIC_AND_NON_NULL(pln, PEPPER_PLANE);
+
+ pepper_object_fini(pln);
+
+ PEPPER_LIST_FOR_EACH(&plane->entry_list, l)
+ {
+ pepper_plane_entry_t *entry = l->item;
+ pepper_view_assign_plane(entry->base.view, &plane->output->base, NULL);
+ }
+
+ pepper_list_remove(&plane->link, NULL);
+ pixman_region32_fini(&plane->damage_region);
+ pixman_region32_fini(&plane->clip_region);
+
+ pepper_free(plane);
+}
+
+void
+pepper_plane_add_damage_region(pepper_plane_t *plane, pixman_region32_t *damage)
+{
+ if (!damage)
+ {
+ pixman_region32_union_rect(&plane->damage_region, &plane->damage_region,
+ 0, 0, plane->output->geometry.w, plane->output->geometry.h);
+ pepper_output_schedule_repaint(plane->output);
+ }
+ else if (pixman_region32_not_empty(damage))
+ {
+ pixman_region32_union(&plane->damage_region, &plane->damage_region, damage);
+ pepper_output_schedule_repaint(plane->output);
+ }
+}
+
+PEPPER_API pixman_region32_t *
+pepper_plane_get_damage_region(pepper_object_t *pln)
+{
+ pepper_plane_t *plane = (pepper_plane_t *)pln;
+ CHECK_MAGIC_AND_NON_NULL(pln, PEPPER_PLANE);
+ return &plane->damage_region;
+}
+
+pixman_region32_t *
+pepper_plane_get_clip_region(pepper_object_t *pln)
+{
+ pepper_plane_t *plane = (pepper_plane_t *)pln;
+ CHECK_MAGIC_AND_NON_NULL(pln, PEPPER_PLANE);
+ return &plane->clip_region;
+}
+
+const pepper_list_t *
+pepper_plane_get_render_list(pepper_object_t *pln)
+{
+ pepper_plane_t *plane = (pepper_plane_t *)pln;
+ CHECK_MAGIC_AND_NON_NULL(pln, PEPPER_PLANE);
+ return &plane->entry_list;
+}
+
+void
+pepper_plane_subtract_damage_region(pepper_object_t *pln, pixman_region32_t *damage)
+{
+ pepper_plane_t *plane = (pepper_plane_t *)pln;
+ CHECK_MAGIC_AND_NON_NULL(pln, PEPPER_PLANE);
+ pixman_region32_subtract(&plane->damage_region, &plane->damage_region, damage);
+}
pixman_region32_init(&surface->input_region);
wl_list_init(&surface->frame_callbacks);
- wl_list_init(&surface->view_list);
+ pepper_list_init(&surface->view_list);
return surface;
}
#include <string.h>
static void
+view_mark_plane_entries_damaged(pepper_view_t *view)
+{
+ int i;
+
+ for (i = 0; i < PEPPER_MAX_OUTPUT_COUNT; i++)
+ view->plane_entries[i].need_damage = PEPPER_TRUE;
+}
+
+static void
view_handle_surface_destroy(struct wl_listener *listener, void *data)
{
pepper_view_t *view = pepper_container_of(listener, pepper_view_t, surface_destroy_listener);
return;
view->geometry_dirty = PEPPER_TRUE;
- pepper_compositor_add_damage(view->compositor, &view->visible_region);
+ pepper_view_damage_below(view);
PEPPER_LIST_FOR_EACH(&view->children_list, l)
view_geometry_dirty((pepper_view_t *)l->item);
}
static void
-view_update_geometry(pepper_view_t *view)
+view_update_output_overlap(pepper_view_t *view)
{
- if (view->parent)
- view_update_geometry(view->parent);
+ pepper_list_t *l;
- if (view->geometry_dirty)
+ view->output_overlap = 0;
+
+ PEPPER_LIST_FOR_EACH(&view->compositor->output_list, l)
{
- view->matrix_to_parent.m[ 0] = view->transform.m[ 0] + view->transform.m[12] * view->x;
- view->matrix_to_parent.m[ 1] = view->transform.m[ 1] + view->transform.m[13] * view->x;
- view->matrix_to_parent.m[ 2] = view->transform.m[ 2] + view->transform.m[14] * view->x;
- view->matrix_to_parent.m[ 3] = view->transform.m[ 3] + view->transform.m[15] * view->x;
-
- view->matrix_to_parent.m[ 4] = view->transform.m[ 4] + view->transform.m[12] * view->y;
- view->matrix_to_parent.m[ 5] = view->transform.m[ 5] + view->transform.m[13] * view->y;
- view->matrix_to_parent.m[ 6] = view->transform.m[ 6] + view->transform.m[14] * view->y;
- view->matrix_to_parent.m[ 7] = view->transform.m[ 7] + view->transform.m[15] * view->y;
-
- view->matrix_to_parent.m[ 8] = view->transform.m[ 8];
- view->matrix_to_parent.m[ 9] = view->transform.m[ 9];
- view->matrix_to_parent.m[10] = view->transform.m[10];
- view->matrix_to_parent.m[11] = view->transform.m[11];
-
- view->matrix_to_parent.m[12] = view->transform.m[12];
- view->matrix_to_parent.m[13] = view->transform.m[13];
- view->matrix_to_parent.m[14] = view->transform.m[14];
- view->matrix_to_parent.m[15] = view->transform.m[15];
-
- if (view->parent)
- {
- pepper_mat4_multiply(&view->matrix_to_global,
- &view->parent->matrix_to_global, &view->matrix_to_parent);
- }
- else
+ pepper_output_t *output = l->item;
+ pixman_box32_t box =
{
- pepper_mat4_copy(&view->matrix_to_global, &view->matrix_to_parent);
- }
+ output->geometry.x,
+ output->geometry.y,
+ output->geometry.x + output->geometry.w,
+ output->geometry.y + output->geometry.h
+ };
+
+ if (pixman_region32_contains_rectangle(&view->bounding_region, &box) != PIXMAN_REGION_OUT)
+ view->output_overlap |= (1 << output->id);
+ }
+}
+
+static pepper_list_t *
+view_insert(pepper_view_t *view, pepper_list_t *pos, pepper_bool_t subtree)
+{
+ if (pos->next != &view->compositor_link)
+ {
+ pepper_list_remove(&view->compositor_link, NULL);
+ pepper_list_insert(pos, &view->compositor_link);
- if (view->surface)
+ if (view->visibility)
{
- view->w = view->surface->w;
- view->h = view->surface->h;
+ pepper_view_damage_below(view);
+ view_mark_plane_entries_damaged(view);
}
+ }
+
+ pos = &view->compositor_link;
- /* Bounding region. */
- pixman_region32_init_rect(&view->bounding_region, 0, 0, view->w, view->h);
- transform_region_bounding(&view->bounding_region, &view->matrix_to_global);
+ if (subtree)
+ {
+ pepper_list_t *l;
- /* Opaque region. */
- pixman_region32_init(&view->opaque_region);
+ PEPPER_LIST_FOR_EACH(&view->children_list, l)
+ pos = view_insert((pepper_view_t *)l->item, pos, subtree);
+ }
- if (view->surface && pepper_mat4_is_translation(&view->matrix_to_global))
- {
- pixman_region32_copy(&view->opaque_region, &view->surface->opaque_region);
- pixman_region32_translate(&view->opaque_region,
- view->matrix_to_global.m[3], view->matrix_to_global.m[7]);
- }
+ return pos;
+}
+static void
+view_handle_plane_destroy(struct wl_listener *listener, void *data);
+
+static void
+plane_entry_set_plane(pepper_plane_entry_t *entry, pepper_plane_t *plane)
+{
+ if (entry->plane == plane)
+ return;
+
+ if (entry->plane)
+ {
+ pepper_view_damage_below((pepper_view_t *)entry->base.view);
+ entry->plane = NULL;
+ wl_list_remove(&entry->plane_destroy_listener.link);
+ pixman_region32_fini(&entry->base.visible_region);
+ }
- view->geometry_dirty = PEPPER_FALSE;
+ entry->plane = plane;
+
+ if (entry->plane)
+ {
+ entry->plane_destroy_listener.notify = view_handle_plane_destroy;
+ pepper_object_add_destroy_listener(&plane->base, &entry->plane_destroy_listener);
+ pixman_region32_init(&entry->base.visible_region);
+ entry->need_damage = PEPPER_TRUE;
}
}
+static void
+view_handle_plane_destroy(struct wl_listener *listener, void *data)
+{
+ pepper_plane_entry_t *entry =
+ pepper_container_of(listener, pepper_plane_entry_t, plane_destroy_listener);
+
+ PEPPER_ASSERT(entry->plane != NULL);
+ plane_entry_set_plane(entry, NULL);
+}
+
void
-pepper_compositor_update_views(pepper_compositor_t *compositor)
+pepper_view_assign_plane(pepper_object_t *v, pepper_object_t *out, pepper_object_t *pln)
{
- pepper_list_t *l;
- pixman_region32_t visible;
- pixman_region32_t opaque;
- pixman_region32_t surface_damage;
- pixman_region32_t damage;
+ pepper_view_t *view = (pepper_view_t *)v;
+ pepper_output_t *output = (pepper_output_t *)out;
+ pepper_plane_t *plane = (pepper_plane_t *)pln;
- pixman_region32_init(&visible);
- pixman_region32_init(&opaque);
- pixman_region32_init(&surface_damage);
- pixman_region32_init(&damage);
+ CHECK_MAGIC_AND_NON_NULL(v, PEPPER_VIEW);
+ CHECK_MAGIC_AND_NON_NULL(out, PEPPER_OUTPUT);
+ CHECK_MAGIC_IF_NON_NULL(pln, PEPPER_PLANE);
- /* Update views from front to back. */
- PEPPER_LIST_FOR_EACH_REVERSE(&compositor->view_list, l)
+ if (plane && plane->output != output)
{
- pepper_view_t *view = (pepper_view_t *)(((pepper_view_state_t *)l->item)->view);
+ PEPPER_ERROR("Output mismatch.\n");
+ return;
+ }
- view_update_geometry(view);
+ plane_entry_set_plane(&view->plane_entries[output->id], plane);
+}
- /* Calculate updated visible region. */
- pixman_region32_subtract(&visible, &view->bounding_region, &opaque);
- pixman_region32_subtract(&damage, &visible, &view->visible_region);
+void
+pepper_view_damage_below(pepper_view_t *view)
+{
+ int i;
- /* Inflict damage for the visible region change. */
- pepper_compositor_add_damage(view->compositor, &damage);
+ for (i = 0; i < PEPPER_MAX_OUTPUT_COUNT; i++)
+ {
+ pepper_plane_entry_t *entry = &view->plane_entries[i];
- /* Update visible region of the view. */
- pixman_region32_copy(&view->visible_region, &visible);
+ if (entry->plane)
+ pepper_plane_add_damage_region(entry->plane, &entry->base.visible_region);
+ }
+}
- /* Inflict surface damage. */
- if (pixman_region32_not_empty(&view->surface->damage_region))
- {
- pepper_surface_flush_damage(view->surface);
+void
+pepper_view_update_geometry(pepper_view_t *view)
+{
+ if (!view->geometry_dirty)
+ return;
- pixman_region32_copy(&surface_damage, &view->surface->damage_region);
+ pepper_mat4_init_translate(&view->global_transform, view->x, view->y, 0.0);
+ pepper_mat4_multiply(&view->global_transform, &view->transform, &view->global_transform);
- /* Transform surface damage into global coordinate space. */
- transform_region_bounding(&surface_damage, &view->matrix_to_global);
+ if (view->parent)
+ {
+ pepper_view_update_geometry(view->parent);
+ pepper_mat4_multiply(&view->global_transform,
+ &view->parent->global_transform, &view->global_transform);
+ }
- /* Clip surface damage with view's bounding region. */
- pixman_region32_intersect(&surface_damage, &surface_damage, &view->bounding_region);
+ if (view->surface)
+ {
+ view->w = view->surface->w;
+ view->h = view->surface->h;
+ }
- /* Subtract area covered by opaque views. */
- pixman_region32_subtract(&surface_damage, &surface_damage, &opaque);
+ /* Bounding region. */
+ pixman_region32_init_rect(&view->bounding_region, 0, 0, view->w, view->h);
+ transform_region_bounding(&view->bounding_region, &view->global_transform);
- pepper_compositor_add_damage(view->compositor, &surface_damage);
- }
+ /* Opaque region. */
+ pixman_region32_init(&view->opaque_region);
- /* Accumulate opaque region. */
- pixman_region32_union(&opaque, &opaque, &view->opaque_region);
+ if (view->surface && pepper_mat4_is_translation(&view->global_transform))
+ {
+ pixman_region32_copy(&view->opaque_region, &view->surface->opaque_region);
+ pixman_region32_translate(&view->opaque_region,
+ view->global_transform.m[3], view->global_transform.m[7]);
}
- pixman_region32_fini(&visible);
- pixman_region32_fini(&opaque);
- pixman_region32_fini(&surface_damage);
- pixman_region32_fini(&damage);
+ view->geometry_dirty = PEPPER_FALSE;
+ view_update_output_overlap(view);
+ view_mark_plane_entries_damaged(view);
+}
+
+static void
+view_init(pepper_view_t *view, pepper_compositor_t *compositor)
+{
+ int i;
+
+ view->compositor = compositor;
+ view->compositor_link.item = view;
+ pepper_list_insert(compositor->view_list.prev, &view->compositor_link);
+
+ view->parent_link.item = view;
+ pepper_list_init(&view->children_list);
+
+ pepper_mat4_init_identity(&view->transform);
+ pepper_mat4_init_identity(&view->global_transform);
+ pixman_region32_init(&view->bounding_region);
+ pixman_region32_init(&view->opaque_region);
+
+ for (i = 0; i < PEPPER_MAX_OUTPUT_COUNT; i++)
+ {
+ view->plane_entries[i].base.view = &view->base;
+ view->plane_entries[i].link.item = &view->plane_entries[i];
+ }
}
+
PEPPER_API pepper_object_t *
pepper_compositor_add_surface_view(pepper_object_t *comp, pepper_object_t *sfc)
{
pepper_view_t *view;
pepper_compositor_t *compositor = (pepper_compositor_t *)comp;
+ pepper_surface_t *surface = (pepper_surface_t *)sfc;
CHECK_MAGIC_AND_NON_NULL(comp, PEPPER_COMPOSITOR);
- CHECK_MAGIC_IF_NON_NULL(sfc, PEPPER_SURFACE);
+ CHECK_MAGIC_AND_NON_NULL(sfc, PEPPER_SURFACE);
view = (pepper_view_t *)pepper_object_alloc(sizeof(pepper_view_t), PEPPER_VIEW);
if (!view)
return NULL;
}
- view->compositor = compositor;
+ view_init(view, compositor);
view->x = 0.0;
view->y = 0.0;
+ view->w = surface->w;
+ view->h = surface->h;
- view->w = 0;
- view->h = 0;
-
- pepper_mat4_init_identity(&view->transform);
- pepper_mat4_init_identity(&view->matrix_to_parent);
- pepper_mat4_init_identity(&view->matrix_to_global);
-
- view->parent_link.item = (void *)view;
-
- pepper_list_init(&view->children_list);
- pepper_list_insert(compositor->root_view_list.prev, &view->parent_link);
- pepper_list_insert(compositor->view_list.prev, &view->z_link);
-
- if (sfc)
- {
- pepper_surface_t *surface = (pepper_surface_t *)sfc;
-
- view->surface = surface;
- wl_list_insert(&surface->view_list, &view->surface_link);
-
- view->surface_destroy_listener.notify = view_handle_surface_destroy;
- pepper_object_add_destroy_listener(&surface->base, &view->surface_destroy_listener);
-
- view->w = surface->w;
- view->h = surface->h;
- }
-
- pixman_region32_init_rect(&view->bounding_region, 0, 0, view->w, view->h);
- pixman_region32_init(&view->opaque_region);
- pixman_region32_init(&view->visible_region);
+ view->geometry_dirty = PEPPER_TRUE;
- view->state.view = &view->base;
- view->state.transform = &view->matrix_to_global;
- view->state.bounding = &view->bounding_region;
- view->state.opaque = &view->opaque_region;
- view->state.visible = &view->visible_region;
- view->z_link.item = &view->state;
+ view->surface = surface;
+ view->surface_link.item = view;
+ pepper_list_insert(&surface->view_list, &view->surface_link);
+ view->surface_destroy_listener.notify = view_handle_surface_destroy;
+ pepper_object_add_destroy_listener(&surface->base, &view->surface_destroy_listener);
- view->geometry_dirty = PEPPER_TRUE;
return &view->base;
}
{
pepper_view_t *view = (pepper_view_t *)v;
pepper_list_t *l, *next;
+ int i;
CHECK_MAGIC_AND_NON_NULL(v, PEPPER_VIEW);
pepper_object_fini(&view->base);
view_unmap(view);
+ for (i = 0; i < PEPPER_MAX_OUTPUT_COUNT; i++)
+ plane_entry_set_plane(&view->plane_entries[i], NULL);
+
PEPPER_LIST_FOR_EACH_SAFE(&view->children_list, l, next)
pepper_view_destroy((pepper_object_t *)(l->item));
PEPPER_ASSERT(pepper_list_empty(&view->children_list));
- pepper_list_remove(&view->parent_link, NULL);
- pepper_list_remove(&view->z_link, NULL);
+ if (view->parent)
+ pepper_list_remove(&view->parent_link, NULL);
+
+ pepper_list_remove(&view->compositor_link, NULL);
if (view->surface)
{
- wl_list_remove(&view->surface_link);
+ pepper_list_remove(&view->surface_link, NULL);
wl_list_remove(&view->surface_destroy_listener.link);
}
pixman_region32_fini(&view->opaque_region);
- pixman_region32_fini(&view->visible_region);
pixman_region32_fini(&view->bounding_region);
pepper_free(view);
if (view->parent)
pepper_list_insert(view->parent->children_list.prev, &view->parent_link);
- else
- pepper_list_insert(view->compositor->root_view_list.prev, &view->parent_link);
view_geometry_dirty(view);
}
return &view->parent->base;
}
-static pepper_list_t *
-view_insert(pepper_view_t *view, pepper_list_t *pos, pepper_bool_t subtree)
-{
- if (pos->next != &view->z_link)
- {
- pepper_list_remove(&view->z_link, NULL);
- pepper_list_insert(pos, &view->z_link);
-
- if (view->visibility)
- pepper_compositor_add_damage(view->compositor, &view->visible_region);
- }
-
- pos = &view->z_link;
-
- if (subtree)
- {
- pepper_list_t *l;
-
- PEPPER_LIST_FOR_EACH(&view->children_list, l)
- pos = view_insert((pepper_view_t *)l->item, pos, subtree);
- }
-
- return pos;
-}
-
PEPPER_API pepper_bool_t
pepper_view_stack_above(pepper_object_t *v, pepper_object_t *b, pepper_bool_t subtree)
{
CHECK_MAGIC_AND_NON_NULL(v, PEPPER_VIEW);
CHECK_MAGIC_AND_NON_NULL(b, PEPPER_VIEW);
- view_insert(view, &below->z_link, subtree);
+ view_insert(view, &below->compositor_link, subtree);
return PEPPER_TRUE;
}
CHECK_MAGIC_AND_NON_NULL(v, PEPPER_VIEW);
CHECK_MAGIC_AND_NON_NULL(a, PEPPER_VIEW);
- view_insert(view, above->z_link.prev, subtree);
+ view_insert(view, above->compositor_link.prev, subtree);
return PEPPER_TRUE;
}
{
pepper_view_t *view = (pepper_view_t *)v;
CHECK_MAGIC_AND_NON_NULL(v, PEPPER_VIEW);
- return view->z_link.next->item;
+ return view->compositor_link.next->item;
}
PEPPER_API pepper_object_t *
{
pepper_view_t *view = (pepper_view_t *)v;
CHECK_MAGIC_AND_NON_NULL(v, PEPPER_VIEW);
- return view->z_link.prev->item;
+ return view->compositor_link.prev->item;
}
PEPPER_API const pepper_list_t *
static void
gl_renderer_repaint_output(pepper_renderer_t *renderer, pepper_object_t *out,
- const pepper_list_t *list, const pixman_region32_t *damage)
+ const pepper_list_t *list, pixman_region32_t *damage)
{
gl_renderer_t *gr = (gl_renderer_t *)renderer;
void (*repaint_output)(pepper_renderer_t *renderer,
pepper_object_t *output,
- const pepper_list_t *view_list,
- const pixman_region32_t *damage);
+ const pepper_list_t *render_list,
+ pixman_region32_t *damage);
};
#endif /* PEPPER_RENDER_INTERNAL_H */
PEPPER_API void
pepper_renderer_repaint_output(pepper_renderer_t *renderer, pepper_object_t *output,
- const pepper_list_t *view_list, const pixman_region32_t *damage);
+ const pepper_list_t *view_list, pixman_region32_t *damage);
PEPPER_API pepper_bool_t
pepper_renderer_read_pixels(pepper_renderer_t *renderer, int x, int y, int w, int h,
#include "pepper-pixman-renderer.h"
#include "pepper-render-internal.h"
+#include <pepper-output-backend.h>
typedef struct pixman_renderer pixman_renderer_t;
typedef struct pixman_surface_state pixman_surface_state_t;
}
static void
-repaint_view(pepper_renderer_t *renderer, pepper_object_t *output, pepper_view_state_t *view_state,
- const pixman_region32_t *global_damage) /* global coordinate */
+repaint_view(pepper_renderer_t *renderer, pepper_render_item_t *node, pixman_region32_t *damage)
{
pixman_render_target_t *target = (pixman_render_target_t*)renderer->target;
pixman_region32_t repaint;
- pepper_object_t *view;
- pepper_object_t *view_surf;
- pixman_surface_state_t *ps;
-
- view = view_state->view;
- PEPPER_ASSERT(view);
-
- view_surf = pepper_view_get_surface(view);
- if (!view_surf)
- return;
-
- ps = get_surface_state(renderer, view_surf);
- if (!ps || !ps->image)
- return;
+ pixman_surface_state_t *ps = get_surface_state(renderer, pepper_view_get_surface(node->view));
pixman_region32_init(&repaint);
- pixman_region32_intersect(&repaint, (pixman_region32_t*) view_state->visible,
- (pixman_region32_t*) global_damage);
+ pixman_region32_intersect(&repaint, &node->visible_region, damage);
if (pixman_region32_not_empty(&repaint))
{
- int x, y, w, h;
- const pepper_mat4_t *transform = view_state->transform;
+ int x, y, w, h;
- /* set clip on destination */
pixman_image_set_clip_region32(target->image, &repaint);
/* TODO: consider transform such as rotation */
- x = transform->m[3];
- y = transform->m[7];
- pepper_view_get_size(view, &w, &h);
+ x = node->transform.m[3];
+ y = node->transform.m[7];
+ pepper_view_get_size(node->view, &w, &h);
- /* composite */
pixman_image_composite32(PIXMAN_OP_SRC, ps->image, NULL, target->image,
0, 0, /* src_x, src_y */
0, 0, /* mask_x, mask_y */
static void
pixman_renderer_repaint_output(pepper_renderer_t *renderer, pepper_object_t *output,
- const pepper_list_t *view_list,
- const pixman_region32_t *output_damage)
+ const pepper_list_t *render_list,
+ pixman_region32_t *damage)
{
- pixman_render_target_t *target = (pixman_render_target_t *)renderer->target;
-
- if (target && pixman_region32_not_empty((pixman_region32_t*) output_damage))
+ if (pixman_region32_not_empty(damage))
{
- const pepper_output_geometry_t *geometry;
- pixman_region32_t global_damage;
- pepper_list_t *cur_list;
- pepper_view_state_t *view_state;
-
- /* translate damage to global coordinate */
- geometry = pepper_output_get_geometry(output);
- pixman_region32_init(&global_damage);
- pixman_region32_copy(&global_damage, (pixman_region32_t*) output_damage);
- pixman_region32_translate(&global_damage, geometry->x, geometry->y);
-
- PEPPER_LIST_FOR_EACH_REVERSE(view_list, cur_list)
- {
- view_state = cur_list->item;
- repaint_view(renderer, output, view_state, (const pixman_region32_t *) &global_damage);
- }
-
- pixman_region32_fini(&global_damage);
+ pepper_list_t *l;
+
+ PEPPER_LIST_FOR_EACH_REVERSE(render_list, l)
+ repaint_view(renderer, (pepper_render_item_t *)l->item, damage);
}
}
PEPPER_API void
pepper_renderer_repaint_output(pepper_renderer_t *renderer, pepper_object_t *output,
- const pepper_list_t *view_list, const pixman_region32_t *damage)
+ const pepper_list_t *view_list, pixman_region32_t *damage)
{
renderer->repaint_output(renderer, output, view_list, damage);
}
struct wl_egl_window *window;
} egl;
#endif
+
+ pepper_object_t *primary_plane;
};
struct wayland_seat
#include "wayland-internal.h"
#include <string.h>
#include <stdlib.h>
+#include <pepper-output-backend.h>
#include <pepper-pixman-renderer.h>
#if ENABLE_WAYLAND_BACKEND_EGL && ENABLE_GL_RENDERER
};
static void
-wayland_output_repaint(void *o, const pepper_list_t *view_list, const pixman_region32_t *damage)
+wayland_output_assign_planes(void *o, const pepper_list_t *view_list)
+{
+ wayland_output_t *output = (wayland_output_t *)o;
+ pepper_list_t *l;
+
+ PEPPER_LIST_FOR_EACH(view_list, l)
+ {
+ pepper_object_t *view = l->item;
+ pepper_view_assign_plane(view, output->base, output->primary_plane);
+ }
+}
+
+static void
+wayland_output_repaint(void *o, const pepper_list_t *plane_list)
{
wayland_output_t *output = o;
struct wl_callback *callback;
- if (output->render_pre)
- output->render_pre(output);
+ pepper_list_t *l;
- pepper_renderer_repaint_output(output->renderer, output->base, view_list, damage);
+ PEPPER_LIST_FOR_EACH(plane_list, l)
+ {
+ pepper_object_t *plane = l->item;
+
+ if (plane == output->primary_plane)
+ {
+ const pepper_list_t *render_list = pepper_plane_get_render_list(plane);
+ pixman_region32_t *damage = pepper_plane_get_damage_region(plane);
+
+ if (output->render_pre)
+ output->render_pre(output);
- if (output->render_post)
- output->render_post(output);
+ pepper_renderer_repaint_output(output->renderer, output->base, render_list, damage);
- callback = wl_surface_frame(output->surface);
- wl_callback_add_listener(callback, &frame_listener, output);
- wl_surface_commit(output->surface);
- wl_display_flush(output->conn->display);
+ if (output->render_post)
+ output->render_post(output);
+
+ callback = wl_surface_frame(output->surface);
+ wl_callback_add_listener(callback, &frame_listener, output);
+ wl_surface_commit(output->surface);
+ wl_display_flush(output->conn->display);
+ }
+ }
}
static void
wayland_output_get_mode,
wayland_output_set_mode,
+ wayland_output_assign_planes,
wayland_output_repaint,
wayland_output_attach_surface,
wayland_output_add_frame_listener,
return NULL;
}
+ output->primary_plane = pepper_output_add_plane(output->base, NULL);
return output->base;
}
if (output)
{
/* TODO: Damage only newly exposed area. */
- pepper_output_add_damage_whole(output->base);
+ pepper_output_add_damage_region(output->base, NULL);
}
}
break;
struct x11_output
{
- pepper_object_t *base;
- pepper_x11_connection_t *connection;
+ pepper_object_t *base;
+ pepper_x11_connection_t *connection;
int32_t x, y;
uint32_t w, h;
struct wl_listener conn_destroy_listener;
struct wl_list link;
+
+ pepper_object_t *primary_plane;
};
struct x11_seat
#include "x11-internal.h"
+#include <pepper-output-backend.h>
#include "pepper-gl-renderer.h"
#include "pepper-pixman-renderer.h"
}
static void
-x11_output_repaint(void *o, const pepper_list_t *view_list, const pixman_region32_t *damage)
+x11_output_assign_planes(void *o, const pepper_list_t *view_list)
{
- x11_output_t *output = o;
+ x11_output_t *output = (x11_output_t *)o;
+ pepper_list_t *l;
- pepper_renderer_set_target(output->renderer, output->target);
- pepper_renderer_repaint_output(output->renderer, output->base, view_list, damage);
+ PEPPER_LIST_FOR_EACH(view_list, l)
+ {
+ pepper_object_t *view = l->item;
+ pepper_view_assign_plane(view, output->base, output->primary_plane);
+ }
+}
- if (output->renderer == output->connection->pixman_renderer)
+static void
+x11_output_repaint(void *o, const pepper_list_t *plane_list)
+{
+ x11_output_t *output = o;
+ pepper_list_t *l;
+
+ PEPPER_LIST_FOR_EACH(plane_list, l)
{
- xcb_void_cookie_t cookie;
- xcb_generic_error_t *err;
-
- cookie = xcb_shm_put_image_checked(output->connection->xcb_connection,
- output->window,
- output->gc,
- output->w * output->scale, /* total_width */
- output->h * output->scale, /* total_height */
- 0, /* src_x */
- 0, /* src_y */
- output->shm.w, /* src_w */
- output->shm.h, /* src_h */
- 0, /* dst_x */
- 0, /* dst_y */
- output->depth, /* depth */
- XCB_IMAGE_FORMAT_Z_PIXMAP, /* format */
- 0, /* send_event */
- output->shm.segment, /* xcb shm segment */
- 0); /* offset */
-
- err = xcb_request_check(output->connection->xcb_connection, cookie);
- if (err)
+ pepper_object_t *plane = l->item;
+
+ if (plane == output->primary_plane)
{
- PEPPER_ERROR("Failed to put shm image, err: %d\n", err->error_code);
- free(err);
+ const pepper_list_t *render_list = pepper_plane_get_render_list(plane);
+ pixman_region32_t *damage = pepper_plane_get_damage_region(plane);
+
+ pepper_renderer_set_target(output->renderer, output->target);
+ pepper_renderer_repaint_output(output->renderer, output->base, render_list, damage);
+
+ if (output->renderer == output->connection->pixman_renderer)
+ {
+ xcb_void_cookie_t cookie;
+ xcb_generic_error_t *err;
+
+ cookie = xcb_shm_put_image_checked(output->connection->xcb_connection,
+ output->window,
+ output->gc,
+ output->w * output->scale, /* total_width */
+ output->h * output->scale, /* total_height */
+ 0, /* src_x */
+ 0, /* src_y */
+ output->shm.w, /* src_w */
+ output->shm.h, /* src_h */
+ 0, /* dst_x */
+ 0, /* dst_y */
+ output->depth, /* depth */
+ XCB_IMAGE_FORMAT_Z_PIXMAP, /* format */
+ 0, /* send_event */
+ output->shm.segment, /* xcb shm segment */
+ 0); /* offset */
+
+ err = xcb_request_check(output->connection->xcb_connection, cookie);
+ if (err)
+ {
+ PEPPER_ERROR("Failed to put shm image, err: %d\n", err->error_code);
+ free(err);
+ }
+ }
+
+ /* XXX: frame_done callback called after 10ms, referenced from weston */
+ wl_event_source_timer_update(output->frame_done_timer, 10);
}
- }
- /* XXX: frame_done callback called after 10ms, referenced from weston */
- wl_event_source_timer_update(output->frame_done_timer, 10);
+ /* TODO: Cursor??? */
+ }
}
static void
x11_output_get_mode,
x11_output_set_mode,
+ x11_output_assign_planes,
x11_output_repaint,
x11_output_attach_surface,
x11_output_add_frame_listener,
/* Register output object */
base = pepper_compositor_add_output(connection->compositor,
- &x11_output_backend,
- output);
+ &x11_output_backend, output);
if (!base)
{
PEPPER_ERROR("pepper_compositor_add_output failed\n");
}
output->base = base;
+ output->primary_plane = pepper_output_add_plane(output->base, NULL);
/* X11 input seat create */
if (!connection->use_xinput)