From e50261ae34cc47276b722f70261c44c5dd3af309 Mon Sep 17 00:00:00 2001 From: Chris Michael Date: Mon, 10 Jun 2013 14:51:56 +0100 Subject: [PATCH] Big giant rendering commit from work so I can continue at home. Signed-off-by: Chris Michael --- src/bin/e_wayland/e.h | 1 + src/bin/e_wayland/e_comp.c | 19 +- src/bin/e_wayland/e_comp.h | 1 - src/bin/e_wayland/e_output.c | 81 ++++++++- src/bin/e_wayland/e_output.h | 8 +- src/bin/e_wayland/e_renderer.c | 322 +++++++++++++++++++++++++++++++-- src/bin/e_wayland/e_renderer.h | 20 +- src/bin/e_wayland/e_surface.c | 101 ++++------- src/bin/e_wayland/e_surface.h | 14 +- 9 files changed, 475 insertions(+), 92 deletions(-) diff --git a/src/bin/e_wayland/e.h b/src/bin/e_wayland/e.h index eaf774226..9287bc0aa 100644 --- a/src/bin/e_wayland/e.h +++ b/src/bin/e_wayland/e.h @@ -126,6 +126,7 @@ void *alloca (size_t); # include # include # include +# include # endif # ifdef HAVE_HAL diff --git a/src/bin/e_wayland/e_comp.c b/src/bin/e_wayland/e_comp.c index 234b8035b..e6df76915 100644 --- a/src/bin/e_wayland/e_comp.c +++ b/src/bin/e_wayland/e_comp.c @@ -289,6 +289,8 @@ e_compositor_damage_calculate(E_Compositor *comp) Eina_List *l; pixman_region32_t clip, opaque; + printf("E_Comp Damage Calculate\n"); + /* check for valid compositor */ if (!comp) return; @@ -367,6 +369,14 @@ _e_comp_cb_surface_create(struct wl_client *client, struct wl_resource *resource return; } + /* ask the renderer to create any internal representation of this surface + * that it may need */ + if (!comp->renderer->surface_create(es)) + { + e_surface_destroy(es); + return; + } + /* set surface plane to compositor primary plane */ es->plane = &comp->plane; @@ -386,7 +396,7 @@ static void _e_comp_cb_surface_destroy(struct wl_resource *resource) { E_Surface *es; - E_Surface_Frame *cb; + E_Surface_Frame *cb, *cbnext; printf("E_Comp Surface Destroy\n"); @@ -403,7 +413,7 @@ _e_comp_cb_surface_destroy(struct wl_resource *resource) if (es->mapped) e_surface_unmap(es); /* remove any pending frame callbacks */ - EINA_LIST_FREE(es->pending.frames, cb) + wl_list_for_each_safe(cb, cbnext, &es->pending.frames, link) wl_resource_destroy(&cb->resource); pixman_region32_fini(&es->pending.damage); @@ -417,6 +427,9 @@ _e_comp_cb_surface_destroy(struct wl_resource *resource) /* remove any buffer references */ e_buffer_reference(&es->buffer.reference, NULL); + if (_e_comp->renderer->surface_destroy) + _e_comp->renderer->surface_destroy(es); + /* free regions */ pixman_region32_fini(&es->damage); pixman_region32_fini(&es->opaque); @@ -424,7 +437,7 @@ _e_comp_cb_surface_destroy(struct wl_resource *resource) pixman_region32_fini(&es->clip); /* remove any active frame callbacks */ - EINA_LIST_FREE(es->frames, cb) + wl_list_for_each_safe(cb, cbnext, &es->frames, link) wl_resource_destroy(&cb->resource); /* free the surface structure */ diff --git a/src/bin/e_wayland/e_comp.h b/src/bin/e_wayland/e_comp.h index 4a96fb233..bb014bebb 100644 --- a/src/bin/e_wayland/e_comp.h +++ b/src/bin/e_wayland/e_comp.h @@ -54,7 +54,6 @@ struct _E_Compositor Eina_List *inputs; Eina_List *surfaces; - void (*attach) (E_Surface *es, struct wl_buffer *buffer); void (*cb_ping) (void *surface, unsigned int serial); }; diff --git a/src/bin/e_wayland/e_output.c b/src/bin/e_wayland/e_output.c index bd6f50bfd..640676d2e 100644 --- a/src/bin/e_wayland/e_output.c +++ b/src/bin/e_wayland/e_output.c @@ -3,6 +3,7 @@ /* 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) @@ -18,6 +19,10 @@ e_output_init(E_Output *output, E_Compositor *comp, Evas_Coord x, Evas_Coord y, output->dirty = EINA_TRUE; output->transform = transform; + 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); @@ -50,12 +55,75 @@ 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; + + printf("Output Repaint\n"); comp = output->compositor; - /* TODO: assign planes */ + 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; + + /* TODO: comp repick ? */ + + 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; + + printf("Output Repaint Schedule\n"); + + 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; } /* local functions */ @@ -95,3 +163,14 @@ _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); +} diff --git a/src/bin/e_wayland/e_output.h b/src/bin/e_wayland/e_output.h index 74122d554..f0bbdbcbd 100644 --- a/src/bin/e_wayland/e_output.h +++ b/src/bin/e_wayland/e_output.h @@ -33,6 +33,9 @@ struct _E_Output struct { + pixman_region32_t region; + pixman_region32_t prev_damage; + Eina_Bool needed : 1; Eina_Bool scheduled : 1; } repaint; @@ -50,16 +53,19 @@ struct _E_Output struct wl_signal destroy; } signals; + void *state; + /* TODO: add backlight and dpms support */ void (*cb_repaint_start)(E_Output *output); - void (*cb_repaint)(E_Output *output, E_Region *damage); + void (*cb_repaint)(E_Output *output, pixman_region32_t *damage); void (*cb_destroy)(E_Output *output); }; 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); EAPI void e_output_shutdown(E_Output *output); EAPI void e_output_repaint(E_Output *output, unsigned int secs); +EAPI void e_output_repaint_schedule(E_Output *output); # endif #endif diff --git a/src/bin/e_wayland/e_renderer.c b/src/bin/e_wayland/e_renderer.c index f35529dbb..3e0ab4ca9 100644 --- a/src/bin/e_wayland/e_renderer.c +++ b/src/bin/e_wayland/e_renderer.c @@ -1,14 +1,55 @@ #include "e.h" +typedef struct _E_Renderer_Output_State E_Renderer_Output_State; +typedef struct _E_Renderer_Surface_State E_Renderer_Surface_State; + +struct _E_Renderer_Output_State +{ +#ifdef HAVE_WAYLAND_EGL + EGLSurface surface; + pixman_region32_t buffer[2]; +#endif + pixman_image_t *shadow; + void *shadow_buffer; + pixman_image_t *hw_buffer; +}; + +struct _E_Renderer_Surface_State +{ +#ifdef HAVE_WAYLAND_EGL + GLfloat color[4]; + GLuint textures[3]; + GLenum target; + + EGLImageKHR images[3]; + + E_Shader *shader; + + pixman_region32_t texture_damage; + + int num_text; + int num_images; + int pitch, height; +#endif + pixman_image_t *image; + E_Buffer_Reference buffer_reference; +}; + /* local function prototypes */ -static int _e_renderer_cb_pixels_read(E_Output *output, int format, void *pixels, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h); +static void _e_renderer_region_repaint(E_Surface *surface, E_Output *output, pixman_region32_t *region, pixman_region32_t *surface_region, pixman_op_t pixman_op); +static void _e_renderer_surfaces_repaint(E_Output *output, pixman_region32_t *damage); +static void _e_renderer_surface_draw(E_Surface *surface, E_Output *output, pixman_region32_t *damage); +static Eina_Bool _e_renderer_cb_pixels_read(E_Output *output, int format, void *pixels, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h); +static void _e_renderer_cb_output_buffer_set(E_Output *output, pixman_image_t *buffer); static void _e_renderer_cb_output_repaint(E_Output *output, pixman_region32_t *damage); -static void void _e_renderer_cb_damage_flush)(E_Surface *surface); -static void void _e_renderer_cb_attach(E_Surface *surface, struct wl_buffer *buffer); -static int _e_renderer_cb_surface_create(E_Surface *surface); +static void _e_renderer_cb_damage_flush(E_Surface *surface); +static void _e_renderer_cb_attach(E_Surface *surface, struct wl_buffer *buffer); +static Eina_Bool _e_renderer_cb_output_create(E_Output *output, unsigned int window); +static void _e_renderer_cb_output_destroy(E_Output *output); +static Eina_Bool _e_renderer_cb_surface_create(E_Surface *surface); static void _e_renderer_cb_surface_destroy(E_Surface *surface); static void _e_renderer_cb_surface_color_set(E_Surface *surface, int r, int g, int b, int a); -static void _e_renderer_cb_destroy)(E_Compositor *comp); +static void _e_renderer_cb_destroy(E_Compositor *comp); EAPI Eina_Bool e_renderer_create(E_Compositor *comp) @@ -18,11 +59,17 @@ e_renderer_create(E_Compositor *comp) /* try to allocate space for new renderer */ if (!(rend = E_NEW(E_Renderer, 1))) return EINA_FALSE; + /* FIXME: Vary these based on software or gl + * NB: This code current ONLY does software */ + /* setup renderer functions */ rend->pixels_read = _e_renderer_cb_pixels_read; + rend->output_buffer_set = _e_renderer_cb_output_buffer_set; rend->output_repaint = _e_renderer_cb_output_repaint; rend->damage_flush = _e_renderer_cb_damage_flush; rend->attach = _e_renderer_cb_attach; + rend->output_create = _e_renderer_cb_output_create; + rend->output_destroy = _e_renderer_cb_output_destroy; rend->surface_create = _e_renderer_cb_surface_create; rend->surface_destroy = _e_renderer_cb_surface_destroy; rend->surface_color_set = _e_renderer_cb_surface_color_set; @@ -34,40 +81,285 @@ e_renderer_create(E_Compositor *comp) } /* local functions */ -static int +static void +_e_renderer_region_repaint(E_Surface *surface, E_Output *output, pixman_region32_t *region, pixman_region32_t *surf_region, pixman_op_t pixman_op) +{ + E_Renderer *rend; + E_Renderer_Output_State *out_state; + E_Renderer_Surface_State *surf_state; + pixman_region32_t fregion; + pixman_fixed_t fw = 0, fh = 0; + + printf("E_Renderer Region Repaint\n"); + + rend = output->compositor->renderer; + out_state = output->state; + surf_state = surface->state; + + pixman_region32_init(&fregion); + if (surf_region) + { + pixman_region32_copy(&fregion, surf_region); + pixman_region32_translate(&fregion, + surface->geometry.x, surface->geometry.y); + pixman_region32_intersect(&fregion, &fregion, region); + } + else + pixman_region32_copy(&fregion, region); + + pixman_image_set_clip_region32(out_state->shadow, &fregion); + pixman_image_set_filter(surf_state->image, PIXMAN_FILTER_NEAREST, NULL, 0); + + pixman_image_composite32(pixman_op, surf_state->image, NULL, + out_state->shadow, 0, 0, 0, 0, 0, 0, + pixman_image_get_width(out_state->shadow), + pixman_image_get_height(out_state->shadow)); + pixman_image_set_clip_region32(out_state->shadow, NULL); + pixman_region32_fini(&fregion); +} + +static void +_e_renderer_surfaces_repaint(E_Output *output, pixman_region32_t *damage) +{ + E_Compositor *comp; + Eina_List *l; + E_Surface *es; + + printf("E_Renderer Surfaces Repaint\n"); + + comp = output->compositor; + EINA_LIST_FOREACH(comp->surfaces, l, es) + { + if (es->plane == &comp->plane) + _e_renderer_surface_draw(es, output, damage); + } +} + +static void +_e_renderer_surface_draw(E_Surface *surface, E_Output *output, pixman_region32_t *damage) +{ + E_Renderer_Surface_State *state; + pixman_region32_t repaint, blend; + + printf("E_Renderer Surface Draw\n"); + + if (!surface) return; + if (!surface->output) surface->output = output; + if (surface->output != output) return; + + if (!(state = surface->state)) return; + + if (!state->image) return; + + pixman_region32_init(&repaint); + pixman_region32_intersect(&repaint, &surface->opaque, damage); + pixman_region32_subtract(&repaint, &repaint, &surface->clip); + + if (!pixman_region32_not_empty(&repaint)) + { + pixman_region32_fini(&repaint); + return; + } + + /* TODO: handle transforms ? */ + + pixman_region32_init_rect(&blend, 0, 0, + surface->geometry.w, surface->geometry.h); + pixman_region32_subtract(&blend, &blend, &surface->opaque); + + if (pixman_region32_not_empty(&surface->opaque)) + _e_renderer_region_repaint(surface, output, &repaint, + &surface->opaque, PIXMAN_OP_SRC); + + if (pixman_region32_not_empty(&blend)) + _e_renderer_region_repaint(surface, output, &repaint, + &blend, PIXMAN_OP_OVER); + + pixman_region32_fini(&blend); + pixman_region32_fini(&repaint); +} + +static Eina_Bool _e_renderer_cb_pixels_read(E_Output *output, int format, void *pixels, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h) { - return 1; + E_Renderer_Output_State *state; + pixman_image_t *buffer; + + printf("E_Renderer Pixels Read\n"); + + if (!(state = output->state)) return EINA_FALSE; + if (!state->hw_buffer) return EINA_FALSE; + + buffer = + pixman_image_create_bits(format, w, h, pixels, + (PIXMAN_FORMAT_BPP(format) / 8) * w); + + pixman_image_composite32(PIXMAN_OP_SRC, state->hw_buffer, NULL, + buffer, 0, 0, 0, 0, 0, 0, + pixman_image_get_width(state->hw_buffer), + pixman_image_get_height(state->hw_buffer)); + pixman_image_set_transform(state->hw_buffer, NULL); + pixman_image_unref(buffer); + + return EINA_TRUE; +} + +static void +_e_renderer_cb_output_buffer_set(E_Output *output, pixman_image_t *buffer) +{ + E_Renderer_Output_State *state; + + printf("E_Renderer Output Buffer Set\n"); + + state = output->state; + if (state->hw_buffer) pixman_image_unref(state->hw_buffer); + state->hw_buffer = buffer; + if (state->hw_buffer) + { + /* output->compositor->read_format; */ + pixman_image_ref(state->hw_buffer); + } } static void _e_renderer_cb_output_repaint(E_Output *output, pixman_region32_t *damage) { + E_Renderer_Output_State *state; + pixman_region32_t region; + printf("E_Renderer Output Repaint\n"); + + state = output->state; + if (!state->hw_buffer) return; + + /* repaint surfaces */ + _e_renderer_surfaces_repaint(output, damage); + + /* copy to hw */ + pixman_region32_init(®ion); + pixman_region32_copy(®ion, damage); + + /* global to output ? */ + + pixman_image_set_clip_region32(state->hw_buffer, ®ion); + pixman_image_composite32(PIXMAN_OP_SRC, state->shadow, NULL, + state->hw_buffer, 0, 0, 0, 0, 0, 0, + pixman_image_get_width(state->hw_buffer), + pixman_image_get_height(state->hw_buffer)); + pixman_image_set_clip_region32(state->hw_buffer, NULL); + pixman_region32_copy(&output->repaint.prev_damage, damage); + + wl_signal_emit(&output->signals.frame, output); } -static void void -_e_renderer_cb_damage_flush)(E_Surface *surface) +static void +_e_renderer_cb_damage_flush(E_Surface *surface) { - + printf("E_Renderer Damage Flush\n"); } -static void void +static void _e_renderer_cb_attach(E_Surface *surface, struct wl_buffer *buffer) { + E_Renderer_Surface_State *state; + pixman_format_code_t format; + Evas_Coord w = 0, h = 0; + void *data; + int stride = 0; + state = surface->state; + + e_buffer_reference(&state->buffer_reference, buffer); + + if (state->image) pixman_image_unref(state->image); + state->image = NULL; + + if (!buffer) return; + + printf("E_Renderer Attach\n"); + + switch (wl_shm_buffer_get_format(buffer)) + { + case WL_SHM_FORMAT_XRGB8888: + format = PIXMAN_x8r8g8b8; + break; + case WL_SHM_FORMAT_ARGB8888: + format = PIXMAN_a8r8g8b8; + break; + } + + w = wl_shm_buffer_get_width(buffer); + h = wl_shm_buffer_get_height(buffer); + data = wl_shm_buffer_get_data(buffer); + stride = wl_shm_buffer_get_stride(buffer); + + state->image = pixman_image_create_bits(format, w, h, data, stride); } -static int +static Eina_Bool +_e_renderer_cb_output_create(E_Output *output, unsigned int window) +{ + E_Renderer_Output_State *state; + + /* try to allocate space for output state */ + if (!(state = E_NEW(E_Renderer_Output_State, 1))) + return EINA_FALSE; + + state->shadow_buffer = malloc(output->w * output->h * sizeof(int)); + if (!state->shadow_buffer) return EINA_FALSE; + + state->shadow = + pixman_image_create_bits(PIXMAN_x8r8g8b8, output->w, output->h, + state->shadow_buffer, output->w * sizeof(int)); + if (!state->shadow) + { + free(state->shadow_buffer); + free(state); + return EINA_FALSE; + } + + output->state = state; + + return EINA_TRUE; +} + +static void +_e_renderer_cb_output_destroy(E_Output *output) +{ + printf("E_Renderer Output Destroy\n"); +} + +static Eina_Bool _e_renderer_cb_surface_create(E_Surface *surface) { - return 1; + E_Renderer_Surface_State *state; + + if (!(state = E_NEW(E_Renderer_Surface_State, 1))) + return EINA_FALSE; + + printf("E_Renderer Surface Create\n"); + + surface->state = state; + + return EINA_TRUE; } static void _e_renderer_cb_surface_destroy(E_Surface *surface) { + E_Renderer_Surface_State *state; + printf("E_Renderer Surface Destroy\n"); + + if ((state = surface->state)) + { + if (state->image) pixman_image_unref(state->image); + state->image = NULL; + } + + e_buffer_reference(&state->buffer_reference, NULL); + + E_FREE(state); } static void @@ -77,8 +369,8 @@ _e_renderer_cb_surface_color_set(E_Surface *surface, int r, int g, int b, int a) } static void -_e_renderer_cb_destroy)(E_Compositor *comp) +_e_renderer_cb_destroy(E_Compositor *comp) { - + printf("E_Renderer Destroy\n"); } diff --git a/src/bin/e_wayland/e_renderer.h b/src/bin/e_wayland/e_renderer.h index 137d214ab..933b12e91 100644 --- a/src/bin/e_wayland/e_renderer.h +++ b/src/bin/e_wayland/e_renderer.h @@ -14,7 +14,7 @@ typedef struct _E_Renderer E_Renderer; # define EGL_TEXTURE_Y_U_V_WL 0x31D7 # define EGL_TEXTURE_Y_UV_WL 0x31D8 # define EGL_TEXTURE_Y_XUXV_WL 0x31D9 -# define EGL_TEXTURE_EXTERNAL_WL 0x31DA + struct wl_display; struct wl_buffer; # ifdef EGL_EGLEXT_PROTOTYPES @@ -26,6 +26,15 @@ typedef EGLBoolean (EGLAPIENTRYP PFNEGLBINDWAYLANDDISPLAYWL) (EGLDisplay dpy, st typedef EGLBoolean (EGLAPIENTRYP PFNEGLUNBINDWAYLANDDISPLAYWL) (EGLDisplay dpy, struct wl_display *display); typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYWAYLANDBUFFERWL) (EGLDisplay dpy, struct wl_buffer *buffer, EGLint attribute, EGLint *value); # endif + +# ifndef EGL_TEXTURE_EXTERNAL_WL +# define EGL_TEXTURE_EXTERNAL_WL 0x31DA +# endif + +# ifndef EGL_BUFFER_AGE_EXT +# define EGL_BUFFER_AGE_EXT 0x313D +# endif + # endif struct _E_Renderer @@ -52,7 +61,7 @@ struct _E_Renderer Eina_Bool have_unpack : 1; Eina_Bool have_bind : 1; - Eina_bool have_external : 1; + Eina_Bool have_external : 1; Eina_Bool have_buffer_age : 1; struct @@ -69,11 +78,14 @@ struct _E_Renderer } shaders; # endif - int (*pixels_read)(E_Output *output, int format, void *pixels, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h); + Eina_Bool (*pixels_read)(E_Output *output, int format, void *pixels, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h); + void (*output_buffer_set)(E_Output *output, pixman_image_t *buffer); void (*output_repaint)(E_Output *output, pixman_region32_t *damage); void (*damage_flush)(E_Surface *surface); void (*attach)(E_Surface *surface, struct wl_buffer *buffer); - int (*surface_create)(E_Surface *surface); + Eina_Bool (*output_create)(E_Output *output, unsigned int window); + void (*output_destroy)(E_Output *output); + Eina_Bool (*surface_create)(E_Surface *surface); void (*surface_destroy)(E_Surface *surface); void (*surface_color_set)(E_Surface *surface, int r, int g, int b, int a); void (*destroy)(E_Compositor *comp); diff --git a/src/bin/e_wayland/e_surface.c b/src/bin/e_wayland/e_surface.c index 3e0954d24..e74acd396 100644 --- a/src/bin/e_wayland/e_surface.c +++ b/src/bin/e_wayland/e_surface.c @@ -38,6 +38,8 @@ e_surface_new(unsigned int id) /* initialize the link */ wl_list_init(&es->wl.link); + wl_list_init(&es->frames); + wl_list_init(&es->pending.frames); pixman_region32_init(&es->damage); pixman_region32_init(&es->opaque); @@ -84,7 +86,7 @@ e_surface_attach(E_Surface *es, struct wl_buffer *buffer) } /* call renderer attach */ - if (_e_comp->attach) _e_comp->attach(es, buffer); + if (_e_comp->renderer->attach) _e_comp->renderer->attach(es, buffer); } EAPI void @@ -103,7 +105,18 @@ e_surface_damage(E_Surface *es) pixman_region32_union_rect(&es->damage, &es->damage, 0, 0, es->geometry.w, es->geometry.h); - /* TODO: schedule repaint */ + e_surface_repaint_schedule(es); +} + +EAPI void +e_surface_damage_below(E_Surface *es) +{ + pixman_region32_t damage; + + pixman_region32_init(&damage); + pixman_region32_subtract(&damage, &es->opaque, &es->clip); + pixman_region32_union(&es->plane->damage, &es->plane->damage, &damage); + pixman_region32_fini(&damage); } EAPI void @@ -129,7 +142,10 @@ e_surface_damage_calculate(E_Surface *es, pixman_region32_t *opaque) { /* if this is an shm buffer, flush any pending damage */ if (wl_buffer_is_shm(es->buffer.reference.buffer)) - e_compositor_damage_flush(_e_comp, es); + { + if (_e_comp->renderer->damage_flush) + _e_comp->renderer->damage_flush(es); + } } /* TODO: handle transforms */ @@ -147,49 +163,6 @@ e_surface_damage_calculate(E_Surface *es, pixman_region32_t *opaque) pixman_region32_copy(&es->clip, opaque); } -EAPI void -e_surface_buffer_set(E_Surface *es, struct wl_buffer *buffer) -{ - pixman_format_code_t format; - Evas_Coord w = 0, h = 0; - int stride = 0; - void *pixels; - - /* check for valid surface */ - if (!es) return; - - /* destory any existing image */ - /* if (es->image) pixman_image_unref(es->image); */ - /* es->image = NULL; */ - - /* check for valid buffer */ - if (!buffer) return; - - /* get buffer format */ - switch (wl_shm_buffer_get_format(buffer)) - { - case WL_SHM_FORMAT_XRGB8888: - format = PIXMAN_x8r8g8b8; - break; - case WL_SHM_FORMAT_ARGB8888: - format = PIXMAN_a8r8g8b8; - break; - default: - e_buffer_reference(&es->buffer.reference, NULL); - return; - break; - } - - /* get buffer information */ - w = wl_shm_buffer_get_width(buffer); - h = wl_shm_buffer_get_height(buffer); - pixels = wl_shm_buffer_get_data(buffer); - stride = wl_shm_buffer_get_stride(buffer); - - /* create surface image */ - /* es->image = pixman_image_create_bits(format, w, h, pixels, stride); */ -} - EAPI void e_surface_show(E_Surface *es) { @@ -199,6 +172,21 @@ e_surface_show(E_Surface *es) /* ecore_evas_show(es->ee); */ } +EAPI void +e_surface_repaint_schedule(E_Surface *es) +{ + E_Output *output; + Eina_List *l; + + printf("E_Surface Repaint Schedule\n"); + + EINA_LIST_FOREACH(_e_comp->outputs, l, output) + { + if (es->output == output) + e_output_repaint_schedule(output); + } +} + /* local functions */ static void _e_surface_cb_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *resource) @@ -310,12 +298,11 @@ _e_surface_cb_commit(struct wl_client *client EINA_UNUSED, struct wl_resource *r pixman_region32_intersect(&es->input, &es->input, &es->pending.input); /* add any pending frame callbacks to main list and free pending */ - EINA_LIST_FREE(es->pending.frames, cb) - es->frames = eina_list_append(es->frames, cb); + wl_list_insert_list(&es->frames, &es->pending.frames); + wl_list_init(&es->pending.frames); /* schedule repaint */ - /* evas_damage_rectangle_add(es->evas, es->damage->x, es->damage->y, */ - /* es->damage->w, es->damage->h); */ + e_surface_repaint_schedule(es); } static void @@ -334,8 +321,6 @@ _e_surface_cb_frame(struct wl_client *client, struct wl_resource *resource, unsi return; } - cb->surface = es; - /* setup the callback object */ cb->resource.object.interface = &wl_callback_interface; cb->resource.object.id = id; @@ -347,7 +332,7 @@ _e_surface_cb_frame(struct wl_client *client, struct wl_resource *resource, unsi wl_client_add_resource(client, &cb->resource); /* append the callback to pending frames */ - es->pending.frames = eina_list_prepend(es->pending.frames, cb); + wl_list_insert(es->pending.frames.prev, &cb->link); } static void @@ -413,20 +398,12 @@ _e_surface_cb_buffer_destroy(struct wl_listener *listener, void *data EINA_UNUSE static void _e_surface_frame_cb_destroy(struct wl_resource *resource) { - E_Surface *es; E_Surface_Frame *cb; /* try to cast the resource to our callback */ if (!(cb = resource->data)) return; - es = cb->surface; + wl_list_remove(&cb->link); - /* remove this callback from the pending frames callback list */ - es->pending.frames = eina_list_remove(es->pending.frames, cb); - - /* remove this callback from the frames callback list */ - es->frames = eina_list_remove(es->frames, cb); - - /* free the callback structure */ E_FREE(cb); } diff --git a/src/bin/e_wayland/e_surface.h b/src/bin/e_wayland/e_surface.h index a8b4a85fe..5345de523 100644 --- a/src/bin/e_wayland/e_surface.h +++ b/src/bin/e_wayland/e_surface.h @@ -25,7 +25,7 @@ struct _E_Surface { struct wl_buffer *buffer; struct wl_listener buffer_destroy; - Eina_List *frames; + struct wl_list frames; pixman_region32_t damage, opaque, input; @@ -37,10 +37,11 @@ struct _E_Surface pixman_region32_t opaque; pixman_region32_t clip; pixman_region32_t input; - /* pixman_image_t *image; */ - Eina_List *frames; + struct wl_list frames; + E_Plane *plane; + E_Output *output; struct { @@ -53,6 +54,8 @@ struct _E_Surface Eina_Bool mapped : 1; + void *state; + void (*map)(E_Surface *surface, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h); void (*unmap)(E_Surface *surface); void (*configure)(E_Surface *surface, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h); @@ -60,18 +63,19 @@ struct _E_Surface struct _E_Surface_Frame { - E_Surface *surface; struct wl_resource resource; + struct wl_list link; }; EAPI E_Surface *e_surface_new(unsigned int id); EAPI void e_surface_attach(E_Surface *es, struct wl_buffer *buffer); EAPI void e_surface_unmap(E_Surface *es); EAPI void e_surface_damage(E_Surface *es); +EAPI void e_surface_damage_below(E_Surface *es); EAPI void e_surface_destroy(E_Surface *es); EAPI void e_surface_damage_calculate(E_Surface *es, pixman_region32_t *opaque); -EAPI void e_surface_buffer_set(E_Surface *es, struct wl_buffer *buffer); EAPI void e_surface_show(E_Surface *es); +EAPI void e_surface_repaint_schedule(E_Surface *es); # endif #endif