enlightenment/src/bin/e_wayland/e_output.c

191 lines
5.1 KiB
C

#include "e.h"
/* local function prototypes */
static void _e_output_cb_bind(struct wl_client *client, void *data, unsigned int version EINA_UNUSED, unsigned int id);
static void _e_output_cb_unbind(struct wl_resource *resource);
static void _e_output_cb_idle_repaint(void *data);
EAPI void
e_output_init(E_Output *output, E_Compositor *comp, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h, unsigned int transform)
{
/* set some output properties */
output->compositor = comp;
output->x = x;
output->y = y;
output->w = w;
output->h = h;
output->mm_w = w;
output->mm_h = h;
output->dirty = EINA_TRUE;
output->transform = transform;
pixman_region32_init(&output->repaint.prev_damage);
pixman_region32_init_rect(&output->repaint.region, x, y, w, h);
pixman_region32_union(&comp->plane.damage, &comp->plane.damage,
&output->repaint.region);
e_output_repaint_schedule(output);
wl_list_init(&output->wl.resources);
wl_signal_init(&output->signals.frame);
wl_signal_init(&output->signals.destroy);
output->id = ffs(~comp->output_pool) - 1;
comp->output_pool |= (1 << output->id);
/* add this output to the registry */
output->wl.global =
wl_display_add_global(comp->wl.display, &wl_output_interface,
output, _e_output_cb_bind);
}
EAPI void
e_output_shutdown(E_Output *output)
{
E_Compositor *comp;
/* check for valid output */
if (!output) return;
wl_signal_emit(&output->signals.destroy, output);
pixman_region32_fini(&output->repaint.region);
pixman_region32_fini(&output->repaint.prev_damage);
comp = output->compositor;
comp->output_pool &= ~(1 << output->id);
wl_display_remove_global(comp->wl.display, output->wl.global);
}
EAPI void
e_output_repaint(E_Output *output, unsigned int secs)
{
E_Compositor *comp;
E_Surface *es;
E_Surface_Frame *cb, *cbnext;
pixman_region32_t damage;
Eina_List *l;
struct wl_list frames;
comp = output->compositor;
EINA_LIST_FOREACH(comp->surfaces, l, es)
{
if (es->plane != &comp->plane) continue;
e_surface_damage_below(es);
es->plane = &comp->plane;
e_surface_damage(es);
}
wl_list_init(&frames);
EINA_LIST_FOREACH(comp->surfaces, l, es)
{
if (es->output != output) continue;
wl_list_insert_list(&frames, &es->frames);
wl_list_init(&es->frames);
}
e_compositor_damage_calculate(comp);
pixman_region32_init(&damage);
pixman_region32_intersect(&damage, &comp->plane.damage,
&output->repaint.region);
pixman_region32_subtract(&damage, &damage, &comp->plane.clip);
if (output->cb_repaint) output->cb_repaint(output, &damage);
pixman_region32_fini(&damage);
output->repaint.needed = EINA_FALSE;
e_compositor_repick(comp);
wl_event_loop_dispatch(comp->wl.input_loop, 0);
/* send surface frame callback done */
wl_list_for_each_safe(cb, cbnext, &frames, link)
{
wl_callback_send_done(cb->resource, secs);
wl_resource_destroy(cb->resource);
}
}
EAPI void
e_output_repaint_schedule(E_Output *output)
{
E_Compositor *comp;
struct wl_event_loop *loop;
comp = output->compositor;
loop = wl_display_get_event_loop(comp->wl.display);
output->repaint.needed = EINA_TRUE;
if (output->repaint.scheduled) return;
wl_event_loop_add_idle(loop, _e_output_cb_idle_repaint, output);
output->repaint.scheduled = EINA_TRUE;
if (comp->wl.input_loop_source)
wl_event_source_remove(comp->wl.input_loop_source);
comp->wl.input_loop_source = NULL;
}
EAPI void
e_output_damage(E_Output *output)
{
E_Compositor *comp;
comp = output->compositor;
pixman_region32_union(&comp->plane.damage,
&comp->plane.damage, &output->repaint.region);
e_output_repaint_schedule(output);
}
/* local functions */
static void
_e_output_cb_bind(struct wl_client *client, void *data, unsigned int version EINA_UNUSED, unsigned int id)
{
E_Output *output;
E_Output_Mode *mode;
Eina_List *l;
struct wl_resource *resource;
/* check for valid output */
if (!(output = data)) return;
/* add this output to the client */
resource =
wl_client_add_object(client, &wl_output_interface, NULL, id, output);
wl_list_insert(&output->wl.resources, &resource->link);
/* setup destroy callback */
resource->destroy = _e_output_cb_unbind;
/* send out this output's geometry */
wl_output_send_geometry(resource, output->x, output->y,
output->mm_w, output->mm_h, output->subpixel,
output->make, output->model, output->transform);
/* send output mode */
EINA_LIST_FOREACH(output->modes, l, mode)
wl_output_send_mode(resource, mode->flags, mode->w, mode->h,
mode->refresh);
}
static void
_e_output_cb_unbind(struct wl_resource *resource)
{
wl_list_remove(&resource->link);
free(resource);
}
static void
_e_output_cb_idle_repaint(void *data)
{
E_Output *output;
if (!(output = data)) return;
if (output->cb_repaint_start)
output->cb_repaint_start(output);
}