weston/ivi-shell/ivi-layout.c
Nobuhiko Tanibata acbcc6c978 ivi-layout: implement surface clipping
View clip region is set in surface-local coordinates. To compute that
region, the ivi-layer destination rectangle in the global coordinates
are transformed back into the surface-local coordinates.

The transformation is computed by first forming the transformation
matric for the forward mappings, and then inverting it. The inverse
matric is used to transform the destination rectangles to the
surface-local coordinate system. The intersection of the rectangles is
the view clip mask.

Signed-off-by: Nobuhiko Tanibata <NOBUHIKO_TANIBATA@xddp.denso.co.jp>
Reviewed-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
Reviewed-by: Bryce Harrington <bryce@osg.samsung.com>
2015-08-26 11:12:49 +03:00

3013 lines
81 KiB
C

/*
* Copyright (C) 2013 DENSO CORPORATION
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/**
* Implementation of ivi-layout library. The actual view on ivi_screen is
* not updated till calling ivi_layout_commit_changes. A overview from
* calling API for updating properties of ivi_surface/ivi_layer to asking
* compositor to compose them by using weston_compositor_schedule_repaint,
* 0/ initialize this library by ivi_layout_init_with_compositor
* with (struct weston_compositor *ec) from ivi-shell.
* 1/ When a API for updating properties of ivi_surface/ivi_layer, it updates
* pending prop of ivi_surface/ivi_layer/ivi_screen which are structure to
* store properties.
* 2/ Before calling commitChanges, in case of calling a API to get a property,
* return current property, not pending property.
* 3/ At the timing of calling ivi_layout_commitChanges, pending properties
* are applied to properties.
*
* *) ivi_layout_commitChanges is also called by transition animation
* per each frame. See ivi-layout-transition.c in details. Transition
* animation interpolates frames between previous properties of ivi_surface
* and new ones.
* For example, when a property of ivi_surface is changed from invisibility
* to visibility, it behaves like fade-in. When ivi_layout_commitChange is
* called during transition animation, it cancels the transition and
* re-start transition to new properties from current properties of final
* frame just before the the cancellation.
*
* 4/ According properties, set transformation by using weston_matrix and
* weston_view per ivi_surfaces and ivi_layers in while loop.
* 5/ Set damage and trigger transform by using weston_view_geometry_dirty.
* 6/ Notify update of properties.
* 7/ Trigger composition by weston_compositor_schedule_repaint.
*
*/
#include "config.h"
#include <string.h>
#include <assert.h>
#include "compositor.h"
#include "ivi-layout-export.h"
#include "ivi-layout-private.h"
#include "shared/helpers.h"
#include "shared/os-compatibility.h"
#define max(a, b) ((a) > (b) ? (a) : (b))
struct link_layer {
struct ivi_layout_layer *ivilayer;
struct wl_list link;
struct wl_list link_to_layer;
};
struct link_screen {
struct ivi_layout_screen *iviscrn;
struct wl_list link;
struct wl_list link_to_screen;
};
struct listener_layout_notification {
void *userdata;
struct wl_listener listener;
};
struct ivi_layout;
struct ivi_layout_screen {
struct wl_list link;
struct wl_list link_to_layer;
uint32_t id_screen;
struct ivi_layout *layout;
struct weston_output *output;
struct {
struct wl_list layer_list;
struct wl_list link;
} pending;
struct {
int dirty;
struct wl_list layer_list;
struct wl_list link;
} order;
};
struct ivi_layout_notification_callback {
void *callback;
void *data;
};
struct ivi_rectangle
{
int32_t x;
int32_t y;
int32_t width;
int32_t height;
};
static void
remove_notification(struct wl_list *listener_list, void *callback, void *userdata);
static struct ivi_layout ivilayout = {0};
struct ivi_layout *
get_instance(void)
{
return &ivilayout;
}
/**
* Internal API to add/remove a link to ivi_surface from ivi_layer.
*/
static void
add_link_to_surface(struct ivi_layout_layer *ivilayer,
struct link_layer *link_layer)
{
struct link_layer *link = NULL;
wl_list_for_each(link, &ivilayer->link_to_surface, link_to_layer) {
if (link == link_layer)
return;
}
wl_list_insert(&ivilayer->link_to_surface, &link_layer->link_to_layer);
}
static void
remove_link_to_surface(struct ivi_layout_layer *ivilayer)
{
struct link_layer *link = NULL;
struct link_layer *next = NULL;
wl_list_for_each_safe(link, next, &ivilayer->link_to_surface, link_to_layer) {
wl_list_remove(&link->link_to_layer);
wl_list_remove(&link->link);
free(link);
}
wl_list_init(&ivilayer->link_to_surface);
}
/**
* Internal API to add a link to ivi_layer from ivi_screen.
*/
static void
add_link_to_layer(struct ivi_layout_screen *iviscrn,
struct link_screen *link_screen)
{
wl_list_insert(&iviscrn->link_to_layer, &link_screen->link_to_screen);
}
/**
* Internal API to add/remove a ivi_surface from ivi_layer.
*/
static void
add_ordersurface_to_layer(struct ivi_layout_surface *ivisurf,
struct ivi_layout_layer *ivilayer)
{
struct link_layer *link_layer = NULL;
link_layer = malloc(sizeof *link_layer);
if (link_layer == NULL) {
weston_log("fails to allocate memory\n");
return;
}
link_layer->ivilayer = ivilayer;
wl_list_insert(&ivisurf->layer_list, &link_layer->link);
add_link_to_surface(ivilayer, link_layer);
}
static void
remove_ordersurface_from_layer(struct ivi_layout_surface *ivisurf)
{
struct link_layer *link_layer = NULL;
struct link_layer *next = NULL;
wl_list_for_each_safe(link_layer, next, &ivisurf->layer_list, link) {
wl_list_remove(&link_layer->link);
wl_list_remove(&link_layer->link_to_layer);
free(link_layer);
}
wl_list_init(&ivisurf->layer_list);
}
/**
* Internal API to add/remove a ivi_layer to/from ivi_screen.
*/
static void
add_orderlayer_to_screen(struct ivi_layout_layer *ivilayer,
struct ivi_layout_screen *iviscrn)
{
struct link_screen *link_scrn = NULL;
link_scrn = malloc(sizeof *link_scrn);
if (link_scrn == NULL) {
weston_log("fails to allocate memory\n");
return;
}
link_scrn->iviscrn = iviscrn;
wl_list_insert(&ivilayer->screen_list, &link_scrn->link);
add_link_to_layer(iviscrn, link_scrn);
}
static void
remove_orderlayer_from_screen(struct ivi_layout_layer *ivilayer)
{
struct link_screen *link_scrn = NULL;
struct link_screen *next = NULL;
wl_list_for_each_safe(link_scrn, next, &ivilayer->screen_list, link) {
wl_list_remove(&link_scrn->link);
wl_list_remove(&link_scrn->link_to_screen);
free(link_scrn);
}
wl_list_init(&ivilayer->screen_list);
}
/**
* Internal API to add/remove a ivi_layer to/from ivi_screen.
*/
static struct ivi_layout_surface *
get_surface(struct wl_list *surf_list, uint32_t id_surface)
{
struct ivi_layout_surface *ivisurf;
wl_list_for_each(ivisurf, surf_list, link) {
if (ivisurf->id_surface == id_surface) {
return ivisurf;
}
}
return NULL;
}
static struct ivi_layout_layer *
get_layer(struct wl_list *layer_list, uint32_t id_layer)
{
struct ivi_layout_layer *ivilayer;
wl_list_for_each(ivilayer, layer_list, link) {
if (ivilayer->id_layer == id_layer) {
return ivilayer;
}
}
return NULL;
}
static void
remove_configured_listener(struct ivi_layout_surface *ivisurf)
{
struct wl_listener *link = NULL;
struct wl_listener *next = NULL;
wl_list_for_each_safe(link, next, &ivisurf->configured.listener_list, link) {
wl_list_remove(&link->link);
}
}
static void
remove_all_notification(struct wl_list *listener_list)
{
struct wl_listener *listener = NULL;
struct wl_listener *next = NULL;
wl_list_for_each_safe(listener, next, listener_list, link) {
struct listener_layout_notification *notification = NULL;
wl_list_remove(&listener->link);
notification =
container_of(listener,
struct listener_layout_notification,
listener);
free(notification->userdata);
free(notification);
}
}
static void
ivi_layout_surface_remove_notification(struct ivi_layout_surface *ivisurf)
{
if (ivisurf == NULL) {
weston_log("ivi_layout_surface_remove_notification: invalid argument\n");
return;
}
remove_all_notification(&ivisurf->property_changed.listener_list);
}
static void
ivi_layout_surface_remove_notification_by_callback(struct ivi_layout_surface *ivisurf,
surface_property_notification_func callback,
void *userdata)
{
if (ivisurf == NULL) {
weston_log("ivi_layout_surface_remove_notification_by_callback: invalid argument\n");
return;
}
remove_notification(&ivisurf->property_changed.listener_list, callback, userdata);
}
/**
* Called at destruction of wl_surface/ivi_surface
*/
void
ivi_layout_surface_destroy(struct ivi_layout_surface *ivisurf)
{
struct ivi_layout *layout = get_instance();
if (ivisurf == NULL) {
weston_log("%s: invalid argument\n", __func__);
return;
}
wl_list_remove(&ivisurf->transform.link);
wl_list_remove(&ivisurf->pending.link);
wl_list_remove(&ivisurf->order.link);
wl_list_remove(&ivisurf->link);
remove_ordersurface_from_layer(ivisurf);
wl_signal_emit(&layout->surface_notification.removed, ivisurf);
remove_configured_listener(ivisurf);
ivi_layout_surface_remove_notification(ivisurf);
free(ivisurf);
}
/**
* Internal API to check ivi_layer/ivi_surface already added in ivi_layer/ivi_screen.
* Called by ivi_layout_layer_add_surface/ivi_layout_screenAddLayer
*/
static int
is_surface_in_layer(struct ivi_layout_surface *ivisurf,
struct ivi_layout_layer *ivilayer)
{
struct ivi_layout_surface *surf = NULL;
wl_list_for_each(surf, &ivilayer->pending.surface_list, pending.link) {
if (surf->id_surface == ivisurf->id_surface) {
return 1;
}
}
return 0;
}
static int
is_layer_in_screen(struct ivi_layout_layer *ivilayer,
struct ivi_layout_screen *iviscrn)
{
struct ivi_layout_layer *layer = NULL;
wl_list_for_each(layer, &iviscrn->pending.layer_list, pending.link) {
if (layer->id_layer == ivilayer->id_layer) {
return 1;
}
}
return 0;
}
/**
* Internal API to initialize ivi_screens found from output_list of weston_compositor.
* Called by ivi_layout_init_with_compositor.
*/
static void
create_screen(struct weston_compositor *ec)
{
struct ivi_layout *layout = get_instance();
struct ivi_layout_screen *iviscrn = NULL;
struct weston_output *output = NULL;
int32_t count = 0;
wl_list_for_each(output, &ec->output_list, link) {
iviscrn = calloc(1, sizeof *iviscrn);
if (iviscrn == NULL) {
weston_log("fails to allocate memory\n");
continue;
}
iviscrn->layout = layout;
iviscrn->id_screen = count;
count++;
iviscrn->output = output;
wl_list_init(&iviscrn->pending.layer_list);
wl_list_init(&iviscrn->pending.link);
wl_list_init(&iviscrn->order.layer_list);
wl_list_init(&iviscrn->order.link);
wl_list_init(&iviscrn->link_to_layer);
wl_list_insert(&layout->screen_list, &iviscrn->link);
}
}
/**
* Internal APIs to initialize properties of ivi_surface/ivi_layer when they are created.
*/
static void
init_layer_properties(struct ivi_layout_layer_properties *prop,
int32_t width, int32_t height)
{
memset(prop, 0, sizeof *prop);
prop->opacity = wl_fixed_from_double(1.0);
prop->source_width = width;
prop->source_height = height;
prop->dest_width = width;
prop->dest_height = height;
}
static void
init_surface_properties(struct ivi_layout_surface_properties *prop)
{
memset(prop, 0, sizeof *prop);
prop->opacity = wl_fixed_from_double(1.0);
/*
* FIXME: this shall be finxed by ivi-layout-transition.
*/
prop->dest_width = 1;
prop->dest_height = 1;
}
/**
* Internal APIs to be called from ivi_layout_commit_changes.
*/
static void
update_opacity(struct ivi_layout_layer *ivilayer,
struct ivi_layout_surface *ivisurf)
{
double layer_alpha = wl_fixed_to_double(ivilayer->prop.opacity);
double surf_alpha = wl_fixed_to_double(ivisurf->prop.opacity);
if ((ivilayer->event_mask & IVI_NOTIFICATION_OPACITY) ||
(ivisurf->event_mask & IVI_NOTIFICATION_OPACITY)) {
struct weston_view *tmpview = NULL;
wl_list_for_each(tmpview, &ivisurf->surface->views, surface_link) {
if (tmpview == NULL) {
continue;
}
tmpview->alpha = layer_alpha * surf_alpha;
}
}
}
static void
get_rotate_values(enum wl_output_transform orientation,
float *v_sin,
float *v_cos)
{
switch (orientation) {
case WL_OUTPUT_TRANSFORM_90:
*v_sin = 1.0f;
*v_cos = 0.0f;
break;
case WL_OUTPUT_TRANSFORM_180:
*v_sin = 0.0f;
*v_cos = -1.0f;
break;
case WL_OUTPUT_TRANSFORM_270:
*v_sin = -1.0f;
*v_cos = 0.0f;
break;
case WL_OUTPUT_TRANSFORM_NORMAL:
default:
*v_sin = 0.0f;
*v_cos = 1.0f;
break;
}
}
static void
get_scale(enum wl_output_transform orientation,
float dest_width,
float dest_height,
float source_width,
float source_height,
float *scale_x,
float *scale_y)
{
switch (orientation) {
case WL_OUTPUT_TRANSFORM_90:
*scale_x = dest_width / source_height;
*scale_y = dest_height / source_width;
break;
case WL_OUTPUT_TRANSFORM_180:
*scale_x = dest_width / source_width;
*scale_y = dest_height / source_height;
break;
case WL_OUTPUT_TRANSFORM_270:
*scale_x = dest_width / source_height;
*scale_y = dest_height / source_width;
break;
case WL_OUTPUT_TRANSFORM_NORMAL:
default:
*scale_x = dest_width / source_width;
*scale_y = dest_height / source_height;
break;
}
}
static void
calc_transformation_matrix(struct ivi_rectangle *source_rect,
struct ivi_rectangle *dest_rect,
enum wl_output_transform orientation,
struct weston_matrix *m)
{
float source_center_x;
float source_center_y;
float vsin;
float vcos;
float scale_x;
float scale_y;
float translate_x;
float translate_y;
source_center_x = source_rect->x + source_rect->width * 0.5f;
source_center_y = source_rect->y + source_rect->height * 0.5f;
weston_matrix_translate(m, -source_center_x, -source_center_y, 0.0f);
get_rotate_values(orientation, &vsin, &vcos);
weston_matrix_rotate_xy(m, vcos, vsin);
get_scale(orientation,
dest_rect->width,
dest_rect->height,
source_rect->width,
source_rect->height,
&scale_x,
&scale_y);
weston_matrix_scale(m, scale_x, scale_y, 1.0f);
translate_x = dest_rect->width * 0.5f + dest_rect->x;
translate_y = dest_rect->height * 0.5f + dest_rect->y;
weston_matrix_translate(m, translate_x, translate_y, 0.0f);
}
/*
* This computes intersected rect_output from two ivi_rectangles
*/
static void
ivi_rectangle_intersect(const struct ivi_rectangle *rect1,
const struct ivi_rectangle *rect2,
struct ivi_rectangle *rect_output)
{
int32_t rect1_right = rect1->x + rect1->width;
int32_t rect1_bottom = rect1->y + rect1->height;
int32_t rect2_right = rect2->x + rect2->width;
int32_t rect2_bottom = rect2->y + rect2->height;
rect_output->x = max(rect1->x, rect2->x);
rect_output->y = max(rect1->y, rect2->y);
rect_output->width = rect1_right < rect2_right ?
rect1_right - rect_output->x :
rect2_right - rect_output->x;
rect_output->height = rect1_bottom < rect2_bottom ?
rect1_bottom - rect_output->y :
rect2_bottom - rect_output->y;
if (rect_output->width < 0 || rect_output->height < 0) {
rect_output->width = 0;
rect_output->height = 0;
}
}
/*
* Transform rect_input by the inverse of matrix, intersect with boundingbox,
* and store the result in rect_output.
* The boundingbox must be given in the same coordinate space as rect_output.
* Additionally, there are the following restrictions on the matrix:
* - no projective transformations
* - no skew
* - only multiples of 90-degree rotations supported
*
* In failure case of weston_matrix_invert, rect_output is set to boundingbox
* as a fail-safe with log.
*/
static void
calc_inverse_matrix_transform(const struct weston_matrix *matrix,
const struct ivi_rectangle *rect_input,
const struct ivi_rectangle *boundingbox,
struct ivi_rectangle *rect_output)
{
struct weston_matrix m;
struct weston_vector top_left;
struct weston_vector bottom_right;
assert(boundingbox != rect_output);
if (weston_matrix_invert(&m, matrix) < 0) {
weston_log("ivi-shell: calc_inverse_matrix_transform fails to invert a matrix.\n");
weston_log("ivi-shell: boundingbox is set to the rect_output.\n");
rect_output->x = boundingbox->x;
rect_output->y = boundingbox->y;
rect_output->width = boundingbox->width;
rect_output->height = boundingbox->height;
}
/* The vectors and matrices involved will always produce f[3] == 1.0. */
top_left.f[0] = rect_input->x;
top_left.f[1] = rect_input->y;
top_left.f[2] = 0.0f;
top_left.f[3] = 1.0f;
bottom_right.f[0] = rect_input->x + rect_input->width;
bottom_right.f[1] = rect_input->y + rect_input->height;
bottom_right.f[2] = 0.0f;
bottom_right.f[3] = 1.0f;
weston_matrix_transform(&m, &top_left);
weston_matrix_transform(&m, &bottom_right);
if (top_left.f[0] < bottom_right.f[0]) {
rect_output->x = top_left.f[0];
rect_output->width = bottom_right.f[0] - rect_output->x;
} else {
rect_output->x = bottom_right.f[0];
rect_output->width = top_left.f[0] - rect_output->x;
}
if (top_left.f[1] < bottom_right.f[1]) {
rect_output->y = top_left.f[1];
rect_output->height = bottom_right.f[1] - rect_output->y;
} else {
rect_output->y = bottom_right.f[1];
rect_output->height = top_left.f[1] - rect_output->y;
}
ivi_rectangle_intersect(rect_output, boundingbox, rect_output);
}
/**
* This computes the whole transformation matrix:m from surface-local
* coordinates to global coordinates. It is assumed that
* weston_view::geometry.{x,y} are zero.
*
* Additionally, this computes the mask on surface-local coordinates as a
* ivi_rectangle. This can be set to weston_view_set_mask.
*
* The mask is computed by following steps
* - destination rectangle of layer is inversed to surface-local cooodinates
* by inversed matrix:m.
* - the area is intersected by intersected area between weston_surface and
* source rectangle of ivi_surface.
*/
static void
calc_surface_to_global_matrix_and_mask_to_weston_surface(
struct ivi_layout_layer *ivilayer,
struct ivi_layout_surface *ivisurf,
struct weston_matrix *m,
struct ivi_rectangle *result)
{
const struct ivi_layout_surface_properties *sp = &ivisurf->prop;
const struct ivi_layout_layer_properties *lp = &ivilayer->prop;
struct ivi_rectangle weston_surface_rect = { 0,
0,
ivisurf->surface->width,
ivisurf->surface->height };
struct ivi_rectangle surface_source_rect = { sp->source_x,
sp->source_y,
sp->source_width,
sp->source_height };
struct ivi_rectangle surface_dest_rect = { sp->dest_x,
sp->dest_y,
sp->dest_width,
sp->dest_height };
struct ivi_rectangle layer_source_rect = { lp->source_x,
lp->source_y,
lp->source_width,
lp->source_height };
struct ivi_rectangle layer_dest_rect = { lp->dest_x,
lp->dest_y,
lp->dest_width,
lp->dest_height };
struct ivi_rectangle surface_result;
/*
* the whole transformation matrix:m from surface-local
* coordinates to global coordinates, which is computed by
* two steps,
* - surface-local coordinates to layer-local coordinates
* - layer-local coordinates to global coordinates
*/
calc_transformation_matrix(&surface_source_rect,
&surface_dest_rect,
sp->orientation, m);
calc_transformation_matrix(&layer_source_rect,
&layer_dest_rect,
lp->orientation, m);
/* this intersected ivi_rectangle would be used for masking
* weston_surface
*/
ivi_rectangle_intersect(&surface_source_rect, &weston_surface_rect,
&surface_result);
/* calc masking area of weston_surface from m */
calc_inverse_matrix_transform(m,
&layer_dest_rect,
&surface_result,
result);
}
static void
update_prop(struct ivi_layout_layer *ivilayer,
struct ivi_layout_surface *ivisurf)
{
struct weston_view *tmpview;
struct ivi_rectangle r;
bool can_calc = true;
if (!ivilayer->event_mask && !ivisurf->event_mask) {
return;
}
update_opacity(ivilayer, ivisurf);
wl_list_for_each(tmpview, &ivisurf->surface->views, surface_link) {
if (tmpview != NULL) {
break;
}
}
if (ivisurf->prop.source_width == 0 || ivisurf->prop.source_height == 0) {
weston_log("ivi-shell: source rectangle is not yet set by ivi_layout_surface_set_source_rectangle\n");
can_calc = false;
}
if (ivisurf->prop.dest_width == 0 || ivisurf->prop.dest_height == 0) {
weston_log("ivi-shell: destination rectangle is not yet set by ivi_layout_surface_set_destination_rectangle\n");
can_calc = false;
}
if (can_calc) {
wl_list_remove(&ivisurf->transform.link);
weston_matrix_init(&ivisurf->transform.matrix);
calc_surface_to_global_matrix_and_mask_to_weston_surface(
ivilayer, ivisurf, &ivisurf->transform.matrix, &r);
if (tmpview != NULL) {
weston_view_set_mask(tmpview, r.x, r.y, r.width, r.height);
wl_list_insert(&tmpview->geometry.transformation_list,
&ivisurf->transform.link);
weston_view_set_transform_parent(tmpview, NULL);
}
}
ivisurf->update_count++;
if (tmpview != NULL) {
weston_view_geometry_dirty(tmpview);
}
if (ivisurf->surface != NULL) {
weston_surface_damage(ivisurf->surface);
}
}
static void
commit_changes(struct ivi_layout *layout)
{
struct ivi_layout_screen *iviscrn = NULL;
struct ivi_layout_layer *ivilayer = NULL;
struct ivi_layout_surface *ivisurf = NULL;
wl_list_for_each(iviscrn, &layout->screen_list, link) {
wl_list_for_each(ivilayer, &iviscrn->order.layer_list, order.link) {
wl_list_for_each(ivisurf, &ivilayer->order.surface_list, order.link) {
update_prop(ivilayer, ivisurf);
}
}
}
}
static void
commit_surface_list(struct ivi_layout *layout)
{
struct ivi_layout_surface *ivisurf = NULL;
int32_t dest_x = 0;
int32_t dest_y = 0;
int32_t dest_width = 0;
int32_t dest_height = 0;
int32_t configured = 0;
wl_list_for_each(ivisurf, &layout->surface_list, link) {
if (ivisurf->pending.prop.transition_type == IVI_LAYOUT_TRANSITION_VIEW_DEFAULT) {
dest_x = ivisurf->prop.dest_x;
dest_y = ivisurf->prop.dest_y;
dest_width = ivisurf->prop.dest_width;
dest_height = ivisurf->prop.dest_height;
ivi_layout_transition_move_resize_view(ivisurf,
ivisurf->pending.prop.dest_x,
ivisurf->pending.prop.dest_y,
ivisurf->pending.prop.dest_width,
ivisurf->pending.prop.dest_height,
ivisurf->pending.prop.transition_duration);
if (ivisurf->pending.prop.visibility) {
ivi_layout_transition_visibility_on(ivisurf, ivisurf->pending.prop.transition_duration);
} else {
ivi_layout_transition_visibility_off(ivisurf, ivisurf->pending.prop.transition_duration);
}
ivisurf->prop = ivisurf->pending.prop;
ivisurf->prop.dest_x = dest_x;
ivisurf->prop.dest_y = dest_y;
ivisurf->prop.dest_width = dest_width;
ivisurf->prop.dest_height = dest_height;
ivisurf->prop.transition_type = IVI_LAYOUT_TRANSITION_NONE;
ivisurf->pending.prop.transition_type = IVI_LAYOUT_TRANSITION_NONE;
} else if (ivisurf->pending.prop.transition_type == IVI_LAYOUT_TRANSITION_VIEW_DEST_RECT_ONLY) {
dest_x = ivisurf->prop.dest_x;
dest_y = ivisurf->prop.dest_y;
dest_width = ivisurf->prop.dest_width;
dest_height = ivisurf->prop.dest_height;
ivi_layout_transition_move_resize_view(ivisurf,
ivisurf->pending.prop.dest_x,
ivisurf->pending.prop.dest_y,
ivisurf->pending.prop.dest_width,
ivisurf->pending.prop.dest_height,
ivisurf->pending.prop.transition_duration);
ivisurf->prop = ivisurf->pending.prop;
ivisurf->prop.dest_x = dest_x;
ivisurf->prop.dest_y = dest_y;
ivisurf->prop.dest_width = dest_width;
ivisurf->prop.dest_height = dest_height;
ivisurf->prop.transition_type = IVI_LAYOUT_TRANSITION_NONE;
ivisurf->pending.prop.transition_type = IVI_LAYOUT_TRANSITION_NONE;
} else if (ivisurf->pending.prop.transition_type == IVI_LAYOUT_TRANSITION_VIEW_FADE_ONLY) {
configured = 0;
if (ivisurf->pending.prop.visibility) {
ivi_layout_transition_visibility_on(ivisurf, ivisurf->pending.prop.transition_duration);
} else {
ivi_layout_transition_visibility_off(ivisurf, ivisurf->pending.prop.transition_duration);
}
if (ivisurf->prop.dest_width != ivisurf->pending.prop.dest_width ||
ivisurf->prop.dest_height != ivisurf->pending.prop.dest_height) {
configured = 1;
}
ivisurf->prop = ivisurf->pending.prop;
ivisurf->prop.transition_type = IVI_LAYOUT_TRANSITION_NONE;
ivisurf->pending.prop.transition_type = IVI_LAYOUT_TRANSITION_NONE;
if (configured && !is_surface_transition(ivisurf))
wl_signal_emit(&ivisurf->configured, ivisurf);
} else {
configured = 0;
if (ivisurf->prop.dest_width != ivisurf->pending.prop.dest_width ||
ivisurf->prop.dest_height != ivisurf->pending.prop.dest_height) {
configured = 1;
}
ivisurf->prop = ivisurf->pending.prop;
ivisurf->prop.transition_type = IVI_LAYOUT_TRANSITION_NONE;
ivisurf->pending.prop.transition_type = IVI_LAYOUT_TRANSITION_NONE;
if (configured && !is_surface_transition(ivisurf))
wl_signal_emit(&ivisurf->configured, ivisurf);
}
}
}
static void
commit_layer_list(struct ivi_layout *layout)
{
struct ivi_layout_layer *ivilayer = NULL;
struct ivi_layout_surface *ivisurf = NULL;
struct ivi_layout_surface *next = NULL;
wl_list_for_each(ivilayer, &layout->layer_list, link) {
if (ivilayer->pending.prop.transition_type == IVI_LAYOUT_TRANSITION_LAYER_MOVE) {
ivi_layout_transition_move_layer(ivilayer, ivilayer->pending.prop.dest_x, ivilayer->pending.prop.dest_y, ivilayer->pending.prop.transition_duration);
} else if (ivilayer->pending.prop.transition_type == IVI_LAYOUT_TRANSITION_LAYER_FADE) {
ivi_layout_transition_fade_layer(ivilayer,ivilayer->pending.prop.is_fade_in,
ivilayer->pending.prop.start_alpha,ivilayer->pending.prop.end_alpha,
NULL, NULL,
ivilayer->pending.prop.transition_duration);
}
ivilayer->pending.prop.transition_type = IVI_LAYOUT_TRANSITION_NONE;
ivilayer->prop = ivilayer->pending.prop;
if (!ivilayer->order.dirty) {
continue;
}
wl_list_for_each_safe(ivisurf, next, &ivilayer->order.surface_list,
order.link) {
remove_ordersurface_from_layer(ivisurf);
wl_list_remove(&ivisurf->order.link);
wl_list_init(&ivisurf->order.link);
ivisurf->event_mask |= IVI_NOTIFICATION_REMOVE;
}
assert(wl_list_empty(&ivilayer->order.surface_list));
wl_list_for_each(ivisurf, &ivilayer->pending.surface_list,
pending.link) {
wl_list_remove(&ivisurf->order.link);
wl_list_insert(&ivilayer->order.surface_list,
&ivisurf->order.link);
add_ordersurface_to_layer(ivisurf, ivilayer);
ivisurf->event_mask |= IVI_NOTIFICATION_ADD;
}
ivilayer->order.dirty = 0;
}
}
static void
commit_screen_list(struct ivi_layout *layout)
{
struct ivi_layout_screen *iviscrn = NULL;
struct ivi_layout_layer *ivilayer = NULL;
struct ivi_layout_layer *next = NULL;
struct ivi_layout_surface *ivisurf = NULL;
wl_list_for_each(iviscrn, &layout->screen_list, link) {
if (iviscrn->order.dirty) {
wl_list_for_each_safe(ivilayer, next,
&iviscrn->order.layer_list, order.link) {
remove_orderlayer_from_screen(ivilayer);
wl_list_remove(&ivilayer->order.link);
wl_list_init(&ivilayer->order.link);
ivilayer->event_mask |= IVI_NOTIFICATION_REMOVE;
}
assert(wl_list_empty(&iviscrn->order.layer_list));
wl_list_for_each(ivilayer, &iviscrn->pending.layer_list,
pending.link) {
wl_list_insert(&iviscrn->order.layer_list,
&ivilayer->order.link);
add_orderlayer_to_screen(ivilayer, iviscrn);
ivilayer->event_mask |= IVI_NOTIFICATION_ADD;
}
iviscrn->order.dirty = 0;
}
/* Clear view list of layout ivi_layer */
wl_list_init(&layout->layout_layer.view_list.link);
wl_list_for_each(ivilayer, &iviscrn->order.layer_list, order.link) {
if (ivilayer->prop.visibility == false)
continue;
wl_list_for_each(ivisurf, &ivilayer->order.surface_list, order.link) {
struct weston_view *tmpview = NULL;
wl_list_for_each(tmpview, &ivisurf->surface->views, surface_link) {
if (tmpview != NULL) {
break;
}
}
if (ivisurf->prop.visibility == false)
continue;
if (ivisurf->surface == NULL || tmpview == NULL)
continue;
weston_layer_entry_insert(&layout->layout_layer.view_list,
&tmpview->layer_link);
ivisurf->surface->output = iviscrn->output;
}
}
break;
}
}
static void
commit_transition(struct ivi_layout* layout)
{
if (wl_list_empty(&layout->pending_transition_list)) {
return;
}
wl_list_insert_list(&layout->transitions->transition_list,
&layout->pending_transition_list);
wl_list_init(&layout->pending_transition_list);
wl_event_source_timer_update(layout->transitions->event_source, 1);
}
static void
send_surface_prop(struct ivi_layout_surface *ivisurf)
{
wl_signal_emit(&ivisurf->property_changed, ivisurf);
ivisurf->event_mask = 0;
}
static void
send_layer_prop(struct ivi_layout_layer *ivilayer)
{
wl_signal_emit(&ivilayer->property_changed, ivilayer);
ivilayer->event_mask = 0;
}
static void
send_prop(struct ivi_layout *layout)
{
struct ivi_layout_layer *ivilayer = NULL;
struct ivi_layout_surface *ivisurf = NULL;
wl_list_for_each_reverse(ivilayer, &layout->layer_list, link) {
if (ivilayer->event_mask)
send_layer_prop(ivilayer);
}
wl_list_for_each_reverse(ivisurf, &layout->surface_list, link) {
if (ivisurf->event_mask)
send_surface_prop(ivisurf);
}
}
static void
clear_surface_pending_list(struct ivi_layout_layer *ivilayer)
{
struct ivi_layout_surface *surface_link = NULL;
struct ivi_layout_surface *surface_next = NULL;
wl_list_for_each_safe(surface_link, surface_next,
&ivilayer->pending.surface_list, pending.link) {
wl_list_remove(&surface_link->pending.link);
wl_list_init(&surface_link->pending.link);
}
}
static void
clear_surface_order_list(struct ivi_layout_layer *ivilayer)
{
struct ivi_layout_surface *surface_link = NULL;
struct ivi_layout_surface *surface_next = NULL;
wl_list_for_each_safe(surface_link, surface_next,
&ivilayer->order.surface_list, order.link) {
wl_list_remove(&surface_link->order.link);
wl_list_init(&surface_link->order.link);
}
}
static void
layer_created(struct wl_listener *listener, void *data)
{
struct ivi_layout_layer *ivilayer = data;
struct listener_layout_notification *notification =
container_of(listener,
struct listener_layout_notification,
listener);
struct ivi_layout_notification_callback *created_callback =
notification->userdata;
((layer_create_notification_func)created_callback->callback)
(ivilayer, created_callback->data);
}
static void
layer_removed(struct wl_listener *listener, void *data)
{
struct ivi_layout_layer *ivilayer = data;
struct listener_layout_notification *notification =
container_of(listener,
struct listener_layout_notification,
listener);
struct ivi_layout_notification_callback *removed_callback =
notification->userdata;
((layer_remove_notification_func)removed_callback->callback)
(ivilayer, removed_callback->data);
}
static void
layer_prop_changed(struct wl_listener *listener, void *data)
{
struct ivi_layout_layer *ivilayer = data;
struct listener_layout_notification *layout_listener =
container_of(listener,
struct listener_layout_notification,
listener);
struct ivi_layout_notification_callback *prop_callback =
layout_listener->userdata;
((layer_property_notification_func)prop_callback->callback)
(ivilayer, &ivilayer->prop, ivilayer->event_mask, prop_callback->data);
}
static void
surface_created(struct wl_listener *listener, void *data)
{
struct ivi_layout_surface *ivisurface = data;
struct listener_layout_notification *notification =
container_of(listener,
struct listener_layout_notification,
listener);
struct ivi_layout_notification_callback *created_callback =
notification->userdata;
((surface_create_notification_func)created_callback->callback)
(ivisurface, created_callback->data);
}
static void
surface_removed(struct wl_listener *listener, void *data)
{
struct ivi_layout_surface *ivisurface = data;
struct listener_layout_notification *notification =
container_of(listener,
struct listener_layout_notification,
listener);
struct ivi_layout_notification_callback *removed_callback =
notification->userdata;
((surface_remove_notification_func)removed_callback->callback)
(ivisurface, removed_callback->data);
}
static void
surface_prop_changed(struct wl_listener *listener, void *data)
{
struct ivi_layout_surface *ivisurf = data;
struct listener_layout_notification *layout_listener =
container_of(listener,
struct listener_layout_notification,
listener);
struct ivi_layout_notification_callback *prop_callback =
layout_listener->userdata;
((surface_property_notification_func)prop_callback->callback)
(ivisurf, &ivisurf->prop, ivisurf->event_mask, prop_callback->data);
ivisurf->event_mask = 0;
}
static void
surface_configure_changed(struct wl_listener *listener,
void *data)
{
struct ivi_layout_surface *ivisurface = data;
struct listener_layout_notification *notification =
container_of(listener,
struct listener_layout_notification,
listener);
struct ivi_layout_notification_callback *configure_changed_callback =
notification->userdata;
((surface_configure_notification_func)configure_changed_callback->callback)
(ivisurface, configure_changed_callback->data);
}
static int32_t
add_notification(struct wl_signal *signal,
wl_notify_func_t callback,
void *userdata)
{
struct listener_layout_notification *notification = NULL;
notification = malloc(sizeof *notification);
if (notification == NULL) {
weston_log("fails to allocate memory\n");
free(userdata);
return IVI_FAILED;
}
notification->listener.notify = callback;
notification->userdata = userdata;
wl_signal_add(signal, &notification->listener);
return IVI_SUCCEEDED;
}
static void
remove_notification(struct wl_list *listener_list, void *callback, void *userdata)
{
struct wl_listener *listener = NULL;
struct wl_listener *next = NULL;
wl_list_for_each_safe(listener, next, listener_list, link) {
struct listener_layout_notification *notification =
container_of(listener,
struct listener_layout_notification,
listener);
struct ivi_layout_notification_callback *notification_callback =
notification->userdata;
if ((notification_callback->callback != callback) ||
(notification_callback->data != userdata)) {
continue;
}
wl_list_remove(&listener->link);
free(notification->userdata);
free(notification);
}
}
/**
* Exported APIs of ivi-layout library are implemented from here.
* Brief of APIs is described in ivi-layout-export.h.
*/
static int32_t
ivi_layout_add_notification_create_layer(layer_create_notification_func callback,
void *userdata)
{
struct ivi_layout *layout = get_instance();
struct ivi_layout_notification_callback *created_callback = NULL;
if (callback == NULL) {
weston_log("ivi_layout_add_notification_create_layer: invalid argument\n");
return IVI_FAILED;
}
created_callback = malloc(sizeof *created_callback);
if (created_callback == NULL) {
weston_log("fails to allocate memory\n");
return IVI_FAILED;
}
created_callback->callback = callback;
created_callback->data = userdata;
return add_notification(&layout->layer_notification.created,
layer_created,
created_callback);
}
static void
ivi_layout_remove_notification_create_layer(layer_create_notification_func callback,
void *userdata)
{
struct ivi_layout *layout = get_instance();
remove_notification(&layout->layer_notification.created.listener_list, callback, userdata);
}
static int32_t
ivi_layout_add_notification_remove_layer(layer_remove_notification_func callback,
void *userdata)
{
struct ivi_layout *layout = get_instance();
struct ivi_layout_notification_callback *removed_callback = NULL;
if (callback == NULL) {
weston_log("ivi_layout_add_notification_remove_layer: invalid argument\n");
return IVI_FAILED;
}
removed_callback = malloc(sizeof *removed_callback);
if (removed_callback == NULL) {
weston_log("fails to allocate memory\n");
return IVI_FAILED;
}
removed_callback->callback = callback;
removed_callback->data = userdata;
return add_notification(&layout->layer_notification.removed,
layer_removed,
removed_callback);
}
static void
ivi_layout_remove_notification_remove_layer(layer_remove_notification_func callback,
void *userdata)
{
struct ivi_layout *layout = get_instance();
remove_notification(&layout->layer_notification.removed.listener_list, callback, userdata);
}
static int32_t
ivi_layout_add_notification_create_surface(surface_create_notification_func callback,
void *userdata)
{
struct ivi_layout *layout = get_instance();
struct ivi_layout_notification_callback *created_callback = NULL;
if (callback == NULL) {
weston_log("ivi_layout_add_notification_create_surface: invalid argument\n");
return IVI_FAILED;
}
created_callback = malloc(sizeof *created_callback);
if (created_callback == NULL) {
weston_log("fails to allocate memory\n");
return IVI_FAILED;
}
created_callback->callback = callback;
created_callback->data = userdata;
return add_notification(&layout->surface_notification.created,
surface_created,
created_callback);
}
static void
ivi_layout_remove_notification_create_surface(surface_create_notification_func callback,
void *userdata)
{
struct ivi_layout *layout = get_instance();
remove_notification(&layout->surface_notification.created.listener_list, callback, userdata);
}
static int32_t
ivi_layout_add_notification_remove_surface(surface_remove_notification_func callback,
void *userdata)
{
struct ivi_layout *layout = get_instance();
struct ivi_layout_notification_callback *removed_callback = NULL;
if (callback == NULL) {
weston_log("ivi_layout_add_notification_remove_surface: invalid argument\n");
return IVI_FAILED;
}
removed_callback = malloc(sizeof *removed_callback);
if (removed_callback == NULL) {
weston_log("fails to allocate memory\n");
return IVI_FAILED;
}
removed_callback->callback = callback;
removed_callback->data = userdata;
return add_notification(&layout->surface_notification.removed,
surface_removed,
removed_callback);
}
static void
ivi_layout_remove_notification_remove_surface(surface_remove_notification_func callback,
void *userdata)
{
struct ivi_layout *layout = get_instance();
remove_notification(&layout->surface_notification.removed.listener_list, callback, userdata);
}
static int32_t
ivi_layout_add_notification_configure_surface(surface_configure_notification_func callback,
void *userdata)
{
struct ivi_layout *layout = get_instance();
struct ivi_layout_notification_callback *configure_changed_callback = NULL;
if (callback == NULL) {
weston_log("ivi_layout_add_notification_configure_surface: invalid argument\n");
return IVI_FAILED;
}
configure_changed_callback = malloc(sizeof *configure_changed_callback);
if (configure_changed_callback == NULL) {
weston_log("fails to allocate memory\n");
return IVI_FAILED;
}
configure_changed_callback->callback = callback;
configure_changed_callback->data = userdata;
return add_notification(&layout->surface_notification.configure_changed,
surface_configure_changed,
configure_changed_callback);
}
static void
ivi_layout_remove_notification_configure_surface(surface_configure_notification_func callback,
void *userdata)
{
struct ivi_layout *layout = get_instance();
remove_notification(&layout->surface_notification.configure_changed.listener_list, callback, userdata);
}
uint32_t
ivi_layout_get_id_of_surface(struct ivi_layout_surface *ivisurf)
{
return ivisurf->id_surface;
}
static uint32_t
ivi_layout_get_id_of_layer(struct ivi_layout_layer *ivilayer)
{
return ivilayer->id_layer;
}
static uint32_t
ivi_layout_get_id_of_screen(struct ivi_layout_screen *iviscrn)
{
return iviscrn->id_screen;
}
static struct ivi_layout_layer *
ivi_layout_get_layer_from_id(uint32_t id_layer)
{
struct ivi_layout *layout = get_instance();
struct ivi_layout_layer *ivilayer = NULL;
wl_list_for_each(ivilayer, &layout->layer_list, link) {
if (ivilayer->id_layer == id_layer) {
return ivilayer;
}
}
return NULL;
}
struct ivi_layout_surface *
ivi_layout_get_surface_from_id(uint32_t id_surface)
{
struct ivi_layout *layout = get_instance();
struct ivi_layout_surface *ivisurf = NULL;
wl_list_for_each(ivisurf, &layout->surface_list, link) {
if (ivisurf->id_surface == id_surface) {
return ivisurf;
}
}
return NULL;
}
static struct ivi_layout_screen *
ivi_layout_get_screen_from_id(uint32_t id_screen)
{
struct ivi_layout *layout = get_instance();
struct ivi_layout_screen *iviscrn = NULL;
wl_list_for_each(iviscrn, &layout->screen_list, link) {
/* FIXME : select iviscrn from screen_list by id_screen */
return iviscrn;
break;
}
return NULL;
}
static int32_t
ivi_layout_get_screen_resolution(struct ivi_layout_screen *iviscrn,
int32_t *pWidth, int32_t *pHeight)
{
struct weston_output *output = NULL;
if (iviscrn == NULL || pWidth == NULL || pHeight == NULL) {
weston_log("ivi_layout_get_screen_resolution: invalid argument\n");
return IVI_FAILED;
}
output = iviscrn->output;
*pWidth = output->current_mode->width;
*pHeight = output->current_mode->height;
return IVI_SUCCEEDED;
}
static int32_t
ivi_layout_surface_add_notification(struct ivi_layout_surface *ivisurf,
surface_property_notification_func callback,
void *userdata)
{
struct listener_layout_notification* notification = NULL;
struct ivi_layout_notification_callback *prop_callback = NULL;
if (ivisurf == NULL || callback == NULL) {
weston_log("ivi_layout_surface_add_notification: invalid argument\n");
return IVI_FAILED;
}
notification = malloc(sizeof *notification);
if (notification == NULL) {
weston_log("fails to allocate memory\n");
return IVI_FAILED;
}
prop_callback = malloc(sizeof *prop_callback);
if (prop_callback == NULL) {
weston_log("fails to allocate memory\n");
return IVI_FAILED;
}
prop_callback->callback = callback;
prop_callback->data = userdata;
notification->listener.notify = surface_prop_changed;
notification->userdata = prop_callback;
wl_signal_add(&ivisurf->property_changed, &notification->listener);
return IVI_SUCCEEDED;
}
static const struct ivi_layout_layer_properties *
ivi_layout_get_properties_of_layer(struct ivi_layout_layer *ivilayer)
{
if (ivilayer == NULL) {
weston_log("ivi_layout_get_properties_of_layer: invalid argument\n");
return NULL;
}
return &ivilayer->prop;
}
static int32_t
ivi_layout_get_screens(int32_t *pLength, struct ivi_layout_screen ***ppArray)
{
struct ivi_layout *layout = get_instance();
struct ivi_layout_screen *iviscrn = NULL;
int32_t length = 0;
int32_t n = 0;
if (pLength == NULL || ppArray == NULL) {
weston_log("ivi_layout_get_screens: invalid argument\n");
return IVI_FAILED;
}
length = wl_list_length(&layout->screen_list);
if (length != 0) {
/* the Array must be free by module which called this function */
*ppArray = calloc(length, sizeof(struct ivi_layout_screen *));
if (*ppArray == NULL) {
weston_log("fails to allocate memory\n");
return IVI_FAILED;
}
wl_list_for_each(iviscrn, &layout->screen_list, link) {
(*ppArray)[n++] = iviscrn;
}
}
*pLength = length;
return IVI_SUCCEEDED;
}
static int32_t
ivi_layout_get_screens_under_layer(struct ivi_layout_layer *ivilayer,
int32_t *pLength,
struct ivi_layout_screen ***ppArray)
{
struct link_screen *link_scrn = NULL;
int32_t length = 0;
int32_t n = 0;
if (ivilayer == NULL || pLength == NULL || ppArray == NULL) {
weston_log("ivi_layout_get_screens_under_layer: invalid argument\n");
return IVI_FAILED;
}
length = wl_list_length(&ivilayer->screen_list);
if (length != 0) {
/* the Array must be free by module which called this function */
*ppArray = calloc(length, sizeof(struct ivi_layout_screen *));
if (*ppArray == NULL) {
weston_log("fails to allocate memory\n");
return IVI_FAILED;
}
wl_list_for_each(link_scrn, &ivilayer->screen_list, link) {
(*ppArray)[n++] = link_scrn->iviscrn;
}
}
*pLength = length;
return IVI_SUCCEEDED;
}
static int32_t
ivi_layout_get_layers(int32_t *pLength, struct ivi_layout_layer ***ppArray)
{
struct ivi_layout *layout = get_instance();
struct ivi_layout_layer *ivilayer = NULL;
int32_t length = 0;
int32_t n = 0;
if (pLength == NULL || ppArray == NULL) {
weston_log("ivi_layout_get_layers: invalid argument\n");
return IVI_FAILED;
}
length = wl_list_length(&layout->layer_list);
if (length != 0) {
/* the Array must be free by module which called this function */
*ppArray = calloc(length, sizeof(struct ivi_layout_layer *));
if (*ppArray == NULL) {
weston_log("fails to allocate memory\n");
return IVI_FAILED;
}
wl_list_for_each(ivilayer, &layout->layer_list, link) {
(*ppArray)[n++] = ivilayer;
}
}
*pLength = length;
return IVI_SUCCEEDED;
}
static int32_t
ivi_layout_get_layers_on_screen(struct ivi_layout_screen *iviscrn,
int32_t *pLength,
struct ivi_layout_layer ***ppArray)
{
struct ivi_layout_layer *ivilayer = NULL;
int32_t length = 0;
int32_t n = 0;
if (iviscrn == NULL || pLength == NULL || ppArray == NULL) {
weston_log("ivi_layout_get_layers_on_screen: invalid argument\n");
return IVI_FAILED;
}
length = wl_list_length(&iviscrn->order.layer_list);
if (length != 0) {
/* the Array must be free by module which called this function */
*ppArray = calloc(length, sizeof(struct ivi_layout_layer *));
if (*ppArray == NULL) {
weston_log("fails to allocate memory\n");
return IVI_FAILED;
}
wl_list_for_each(ivilayer, &iviscrn->order.layer_list, order.link) {
(*ppArray)[n++] = ivilayer;
}
}
*pLength = length;
return IVI_SUCCEEDED;
}
static int32_t
ivi_layout_get_layers_under_surface(struct ivi_layout_surface *ivisurf,
int32_t *pLength,
struct ivi_layout_layer ***ppArray)
{
struct link_layer *link_layer = NULL;
int32_t length = 0;
int32_t n = 0;
if (ivisurf == NULL || pLength == NULL || ppArray == NULL) {
weston_log("ivi_layout_getLayers: invalid argument\n");
return IVI_FAILED;
}
length = wl_list_length(&ivisurf->layer_list);
if (length != 0) {
/* the Array must be free by module which called this function */
*ppArray = calloc(length, sizeof(struct ivi_layout_layer *));
if (*ppArray == NULL) {
weston_log("fails to allocate memory\n");
return IVI_FAILED;
}
wl_list_for_each(link_layer, &ivisurf->layer_list, link) {
(*ppArray)[n++] = link_layer->ivilayer;
}
}
*pLength = length;
return IVI_SUCCEEDED;
}
static
int32_t
ivi_layout_get_surfaces(int32_t *pLength, struct ivi_layout_surface ***ppArray)
{
struct ivi_layout *layout = get_instance();
struct ivi_layout_surface *ivisurf = NULL;
int32_t length = 0;
int32_t n = 0;
if (pLength == NULL || ppArray == NULL) {
weston_log("ivi_layout_get_surfaces: invalid argument\n");
return IVI_FAILED;
}
length = wl_list_length(&layout->surface_list);
if (length != 0) {
/* the Array must be free by module which called this function */
*ppArray = calloc(length, sizeof(struct ivi_layout_surface *));
if (*ppArray == NULL) {
weston_log("fails to allocate memory\n");
return IVI_FAILED;
}
wl_list_for_each(ivisurf, &layout->surface_list, link) {
(*ppArray)[n++] = ivisurf;
}
}
*pLength = length;
return IVI_SUCCEEDED;
}
static int32_t
ivi_layout_get_surfaces_on_layer(struct ivi_layout_layer *ivilayer,
int32_t *pLength,
struct ivi_layout_surface ***ppArray)
{
struct ivi_layout_surface *ivisurf = NULL;
int32_t length = 0;
int32_t n = 0;
if (ivilayer == NULL || pLength == NULL || ppArray == NULL) {
weston_log("ivi_layout_getSurfaceIDsOnLayer: invalid argument\n");
return IVI_FAILED;
}
length = wl_list_length(&ivilayer->order.surface_list);
if (length != 0) {
/* the Array must be free by module which called this function */
*ppArray = calloc(length, sizeof(struct ivi_layout_surface *));
if (*ppArray == NULL) {
weston_log("fails to allocate memory\n");
return IVI_FAILED;
}
wl_list_for_each(ivisurf, &ivilayer->order.surface_list, order.link) {
(*ppArray)[n++] = ivisurf;
}
}
*pLength = length;
return IVI_SUCCEEDED;
}
static struct ivi_layout_layer *
ivi_layout_layer_create_with_dimension(uint32_t id_layer,
int32_t width, int32_t height)
{
struct ivi_layout *layout = get_instance();
struct ivi_layout_layer *ivilayer = NULL;
ivilayer = get_layer(&layout->layer_list, id_layer);
if (ivilayer != NULL) {
weston_log("id_layer is already created\n");
++ivilayer->ref_count;
return ivilayer;
}
ivilayer = calloc(1, sizeof *ivilayer);
if (ivilayer == NULL) {
weston_log("fails to allocate memory\n");
return NULL;
}
ivilayer->ref_count = 1;
wl_signal_init(&ivilayer->property_changed);
wl_list_init(&ivilayer->screen_list);
wl_list_init(&ivilayer->link_to_surface);
ivilayer->layout = layout;
ivilayer->id_layer = id_layer;
init_layer_properties(&ivilayer->prop, width, height);
ivilayer->event_mask = 0;
wl_list_init(&ivilayer->pending.surface_list);
wl_list_init(&ivilayer->pending.link);
ivilayer->pending.prop = ivilayer->prop;
wl_list_init(&ivilayer->order.surface_list);
wl_list_init(&ivilayer->order.link);
wl_list_insert(&layout->layer_list, &ivilayer->link);
wl_signal_emit(&layout->layer_notification.created, ivilayer);
return ivilayer;
}
static void
ivi_layout_layer_remove_notification(struct ivi_layout_layer *ivilayer)
{
if (ivilayer == NULL) {
weston_log("ivi_layout_layer_remove_notification: invalid argument\n");
return;
}
remove_all_notification(&ivilayer->property_changed.listener_list);
}
static void
ivi_layout_layer_remove_notification_by_callback(struct ivi_layout_layer *ivilayer,
layer_property_notification_func callback,
void *userdata)
{
if (ivilayer == NULL) {
weston_log("ivi_layout_layer_remove_notification_by_callback: invalid argument\n");
return;
}
remove_notification(&ivilayer->property_changed.listener_list, callback, userdata);
}
static void
ivi_layout_layer_destroy(struct ivi_layout_layer *ivilayer)
{
struct ivi_layout *layout = get_instance();
if (ivilayer == NULL) {
weston_log("ivi_layout_layer_remove: invalid argument\n");
return;
}
if (--ivilayer->ref_count > 0)
return;
wl_signal_emit(&layout->layer_notification.removed, ivilayer);
clear_surface_pending_list(ivilayer);
clear_surface_order_list(ivilayer);
wl_list_remove(&ivilayer->pending.link);
wl_list_remove(&ivilayer->order.link);
wl_list_remove(&ivilayer->link);
remove_orderlayer_from_screen(ivilayer);
remove_link_to_surface(ivilayer);
ivi_layout_layer_remove_notification(ivilayer);
free(ivilayer);
}
int32_t
ivi_layout_layer_set_visibility(struct ivi_layout_layer *ivilayer,
bool newVisibility)
{
struct ivi_layout_layer_properties *prop = NULL;
if (ivilayer == NULL) {
weston_log("ivi_layout_layer_set_visibility: invalid argument\n");
return IVI_FAILED;
}
prop = &ivilayer->pending.prop;
prop->visibility = newVisibility;
if (ivilayer->prop.visibility != newVisibility)
ivilayer->event_mask |= IVI_NOTIFICATION_VISIBILITY;
else
ivilayer->event_mask &= ~IVI_NOTIFICATION_VISIBILITY;
return IVI_SUCCEEDED;
}
static bool
ivi_layout_layer_get_visibility(struct ivi_layout_layer *ivilayer)
{
if (ivilayer == NULL) {
weston_log("ivi_layout_layer_get_visibility: invalid argument\n");
return false;
}
return ivilayer->prop.visibility;
}
int32_t
ivi_layout_layer_set_opacity(struct ivi_layout_layer *ivilayer,
wl_fixed_t opacity)
{
struct ivi_layout_layer_properties *prop = NULL;
if (ivilayer == NULL ||
opacity < wl_fixed_from_double(0.0) ||
wl_fixed_from_double(1.0) < opacity) {
weston_log("ivi_layout_layer_set_opacity: invalid argument\n");
return IVI_FAILED;
}
prop = &ivilayer->pending.prop;
prop->opacity = opacity;
if (ivilayer->prop.opacity != opacity)
ivilayer->event_mask |= IVI_NOTIFICATION_OPACITY;
else
ivilayer->event_mask &= ~IVI_NOTIFICATION_OPACITY;
return IVI_SUCCEEDED;
}
wl_fixed_t
ivi_layout_layer_get_opacity(struct ivi_layout_layer *ivilayer)
{
if (ivilayer == NULL) {
weston_log("ivi_layout_layer_get_opacity: invalid argument\n");
return wl_fixed_from_double(0.0);
}
return ivilayer->prop.opacity;
}
static int32_t
ivi_layout_layer_set_source_rectangle(struct ivi_layout_layer *ivilayer,
int32_t x, int32_t y,
int32_t width, int32_t height)
{
struct ivi_layout_layer_properties *prop = NULL;
if (ivilayer == NULL) {
weston_log("ivi_layout_layer_set_source_rectangle: invalid argument\n");
return IVI_FAILED;
}
prop = &ivilayer->pending.prop;
prop->source_x = x;
prop->source_y = y;
prop->source_width = width;
prop->source_height = height;
if (ivilayer->prop.source_x != x || ivilayer->prop.source_y != y ||
ivilayer->prop.source_width != width ||
ivilayer->prop.source_height != height)
ivilayer->event_mask |= IVI_NOTIFICATION_SOURCE_RECT;
else
ivilayer->event_mask &= ~IVI_NOTIFICATION_SOURCE_RECT;
return IVI_SUCCEEDED;
}
static int32_t
ivi_layout_layer_set_destination_rectangle(struct ivi_layout_layer *ivilayer,
int32_t x, int32_t y,
int32_t width, int32_t height)
{
struct ivi_layout_layer_properties *prop = NULL;
if (ivilayer == NULL) {
weston_log("ivi_layout_layer_set_destination_rectangle: invalid argument\n");
return IVI_FAILED;
}
prop = &ivilayer->pending.prop;
prop->dest_x = x;
prop->dest_y = y;
prop->dest_width = width;
prop->dest_height = height;
if (ivilayer->prop.dest_x != x || ivilayer->prop.dest_y != y ||
ivilayer->prop.dest_width != width ||
ivilayer->prop.dest_height != height)
ivilayer->event_mask |= IVI_NOTIFICATION_DEST_RECT;
else
ivilayer->event_mask &= ~IVI_NOTIFICATION_DEST_RECT;
return IVI_SUCCEEDED;
}
static int32_t
ivi_layout_layer_get_dimension(struct ivi_layout_layer *ivilayer,
int32_t *dest_width, int32_t *dest_height)
{
if (ivilayer == NULL || dest_width == NULL || dest_height == NULL) {
weston_log("ivi_layout_layer_get_dimension: invalid argument\n");
return IVI_FAILED;
}
*dest_width = ivilayer->prop.dest_width;
*dest_height = ivilayer->prop.dest_height;
return IVI_SUCCEEDED;
}
static int32_t
ivi_layout_layer_set_dimension(struct ivi_layout_layer *ivilayer,
int32_t dest_width, int32_t dest_height)
{
struct ivi_layout_layer_properties *prop = NULL;
if (ivilayer == NULL) {
weston_log("ivi_layout_layer_set_dimension: invalid argument\n");
return IVI_FAILED;
}
prop = &ivilayer->pending.prop;
prop->dest_width = dest_width;
prop->dest_height = dest_height;
if (ivilayer->prop.dest_width != dest_width ||
ivilayer->prop.dest_height != dest_height)
ivilayer->event_mask |= IVI_NOTIFICATION_DIMENSION;
else
ivilayer->event_mask &= ~IVI_NOTIFICATION_DIMENSION;
return IVI_SUCCEEDED;
}
int32_t
ivi_layout_layer_get_position(struct ivi_layout_layer *ivilayer,
int32_t *dest_x, int32_t *dest_y)
{
if (ivilayer == NULL || dest_x == NULL || dest_y == NULL) {
weston_log("ivi_layout_layer_get_position: invalid argument\n");
return IVI_FAILED;
}
*dest_x = ivilayer->prop.dest_x;
*dest_y = ivilayer->prop.dest_y;
return IVI_SUCCEEDED;
}
int32_t
ivi_layout_layer_set_position(struct ivi_layout_layer *ivilayer,
int32_t dest_x, int32_t dest_y)
{
struct ivi_layout_layer_properties *prop = NULL;
if (ivilayer == NULL) {
weston_log("ivi_layout_layer_set_position: invalid argument\n");
return IVI_FAILED;
}
prop = &ivilayer->pending.prop;
prop->dest_x = dest_x;
prop->dest_y = dest_y;
if (ivilayer->prop.dest_x != dest_x || ivilayer->prop.dest_y != dest_y)
ivilayer->event_mask |= IVI_NOTIFICATION_POSITION;
else
ivilayer->event_mask &= ~IVI_NOTIFICATION_POSITION;
return IVI_SUCCEEDED;
}
static int32_t
ivi_layout_layer_set_orientation(struct ivi_layout_layer *ivilayer,
enum wl_output_transform orientation)
{
struct ivi_layout_layer_properties *prop = NULL;
if (ivilayer == NULL) {
weston_log("ivi_layout_layer_set_orientation: invalid argument\n");
return IVI_FAILED;
}
prop = &ivilayer->pending.prop;
prop->orientation = orientation;
if (ivilayer->prop.orientation != orientation)
ivilayer->event_mask |= IVI_NOTIFICATION_ORIENTATION;
else
ivilayer->event_mask &= ~IVI_NOTIFICATION_ORIENTATION;
return IVI_SUCCEEDED;
}
static enum wl_output_transform
ivi_layout_layer_get_orientation(struct ivi_layout_layer *ivilayer)
{
if (ivilayer == NULL) {
weston_log("ivi_layout_layer_get_orientation: invalid argument\n");
return 0;
}
return ivilayer->prop.orientation;
}
int32_t
ivi_layout_layer_set_render_order(struct ivi_layout_layer *ivilayer,
struct ivi_layout_surface **pSurface,
int32_t number)
{
struct ivi_layout *layout = get_instance();
struct ivi_layout_surface *ivisurf = NULL;
struct ivi_layout_surface *next = NULL;
uint32_t *id_surface = NULL;
int32_t i = 0;
if (ivilayer == NULL) {
weston_log("ivi_layout_layer_set_render_order: invalid argument\n");
return IVI_FAILED;
}
clear_surface_pending_list(ivilayer);
for (i = 0; i < number; i++) {
id_surface = &pSurface[i]->id_surface;
wl_list_for_each_safe(ivisurf, next, &layout->surface_list, link) {
if (*id_surface != ivisurf->id_surface) {
continue;
}
wl_list_remove(&ivisurf->pending.link);
wl_list_insert(&ivilayer->pending.surface_list,
&ivisurf->pending.link);
break;
}
}
ivilayer->order.dirty = 1;
return IVI_SUCCEEDED;
}
int32_t
ivi_layout_surface_set_visibility(struct ivi_layout_surface *ivisurf,
bool newVisibility)
{
struct ivi_layout_surface_properties *prop = NULL;
if (ivisurf == NULL) {
weston_log("ivi_layout_surface_set_visibility: invalid argument\n");
return IVI_FAILED;
}
prop = &ivisurf->pending.prop;
prop->visibility = newVisibility;
if (ivisurf->prop.visibility != newVisibility)
ivisurf->event_mask |= IVI_NOTIFICATION_VISIBILITY;
else
ivisurf->event_mask &= ~IVI_NOTIFICATION_VISIBILITY;
return IVI_SUCCEEDED;
}
bool
ivi_layout_surface_get_visibility(struct ivi_layout_surface *ivisurf)
{
if (ivisurf == NULL) {
weston_log("ivi_layout_surface_get_visibility: invalid argument\n");
return false;
}
return ivisurf->prop.visibility;
}
int32_t
ivi_layout_surface_set_opacity(struct ivi_layout_surface *ivisurf,
wl_fixed_t opacity)
{
struct ivi_layout_surface_properties *prop = NULL;
if (ivisurf == NULL ||
opacity < wl_fixed_from_double(0.0) ||
wl_fixed_from_double(1.0) < opacity) {
weston_log("ivi_layout_surface_set_opacity: invalid argument\n");
return IVI_FAILED;
}
prop = &ivisurf->pending.prop;
prop->opacity = opacity;
if (ivisurf->prop.opacity != opacity)
ivisurf->event_mask |= IVI_NOTIFICATION_OPACITY;
else
ivisurf->event_mask &= ~IVI_NOTIFICATION_OPACITY;
return IVI_SUCCEEDED;
}
wl_fixed_t
ivi_layout_surface_get_opacity(struct ivi_layout_surface *ivisurf)
{
if (ivisurf == NULL) {
weston_log("ivi_layout_surface_get_opacity: invalid argument\n");
return wl_fixed_from_double(0.0);
}
return ivisurf->prop.opacity;
}
int32_t
ivi_layout_surface_set_destination_rectangle(struct ivi_layout_surface *ivisurf,
int32_t x, int32_t y,
int32_t width, int32_t height)
{
struct ivi_layout_surface_properties *prop = NULL;
if (ivisurf == NULL) {
weston_log("ivi_layout_surface_set_destination_rectangle: invalid argument\n");
return IVI_FAILED;
}
prop = &ivisurf->pending.prop;
prop->start_x = prop->dest_x;
prop->start_y = prop->dest_y;
prop->dest_x = x;
prop->dest_y = y;
prop->start_width = prop->dest_width;
prop->start_height = prop->dest_height;
prop->dest_width = width;
prop->dest_height = height;
if (ivisurf->prop.dest_x != x || ivisurf->prop.dest_y != y ||
ivisurf->prop.dest_width != width ||
ivisurf->prop.dest_height != height)
ivisurf->event_mask |= IVI_NOTIFICATION_DEST_RECT;
else
ivisurf->event_mask &= ~IVI_NOTIFICATION_DEST_RECT;
return IVI_SUCCEEDED;
}
static int32_t
ivi_layout_surface_set_dimension(struct ivi_layout_surface *ivisurf,
int32_t dest_width, int32_t dest_height)
{
struct ivi_layout_surface_properties *prop = NULL;
if (ivisurf == NULL) {
weston_log("ivi_layout_surface_set_dimension: invalid argument\n");
return IVI_FAILED;
}
prop = &ivisurf->pending.prop;
prop->dest_width = dest_width;
prop->dest_height = dest_height;
if (ivisurf->prop.dest_width != dest_width ||
ivisurf->prop.dest_height != dest_height)
ivisurf->event_mask |= IVI_NOTIFICATION_DIMENSION;
else
ivisurf->event_mask &= ~IVI_NOTIFICATION_DIMENSION;
return IVI_SUCCEEDED;
}
int32_t
ivi_layout_surface_get_dimension(struct ivi_layout_surface *ivisurf,
int32_t *dest_width, int32_t *dest_height)
{
if (ivisurf == NULL || dest_width == NULL || dest_height == NULL) {
weston_log("ivi_layout_surface_get_dimension: invalid argument\n");
return IVI_FAILED;
}
*dest_width = ivisurf->prop.dest_width;
*dest_height = ivisurf->prop.dest_height;
return IVI_SUCCEEDED;
}
static int32_t
ivi_layout_surface_set_position(struct ivi_layout_surface *ivisurf,
int32_t dest_x, int32_t dest_y)
{
struct ivi_layout_surface_properties *prop = NULL;
if (ivisurf == NULL) {
weston_log("ivi_layout_surface_set_position: invalid argument\n");
return IVI_FAILED;
}
prop = &ivisurf->pending.prop;
prop->dest_x = dest_x;
prop->dest_y = dest_y;
if (ivisurf->prop.dest_x != dest_x || ivisurf->prop.dest_y != dest_y)
ivisurf->event_mask |= IVI_NOTIFICATION_POSITION;
else
ivisurf->event_mask &= ~IVI_NOTIFICATION_POSITION;
return IVI_SUCCEEDED;
}
static int32_t
ivi_layout_surface_get_position(struct ivi_layout_surface *ivisurf,
int32_t *dest_x, int32_t *dest_y)
{
if (ivisurf == NULL || dest_x == NULL || dest_y == NULL) {
weston_log("ivi_layout_surface_get_position: invalid argument\n");
return IVI_FAILED;
}
*dest_x = ivisurf->prop.dest_x;
*dest_y = ivisurf->prop.dest_y;
return IVI_SUCCEEDED;
}
static int32_t
ivi_layout_surface_set_orientation(struct ivi_layout_surface *ivisurf,
enum wl_output_transform orientation)
{
struct ivi_layout_surface_properties *prop = NULL;
if (ivisurf == NULL) {
weston_log("ivi_layout_surface_set_orientation: invalid argument\n");
return IVI_FAILED;
}
prop = &ivisurf->pending.prop;
prop->orientation = orientation;
if (ivisurf->prop.orientation != orientation)
ivisurf->event_mask |= IVI_NOTIFICATION_ORIENTATION;
else
ivisurf->event_mask &= ~IVI_NOTIFICATION_ORIENTATION;
return IVI_SUCCEEDED;
}
static enum wl_output_transform
ivi_layout_surface_get_orientation(struct ivi_layout_surface *ivisurf)
{
if (ivisurf == NULL) {
weston_log("ivi_layout_surface_get_orientation: invalid argument\n");
return 0;
}
return ivisurf->prop.orientation;
}
static int32_t
ivi_layout_screen_add_layer(struct ivi_layout_screen *iviscrn,
struct ivi_layout_layer *addlayer)
{
struct ivi_layout *layout = get_instance();
struct ivi_layout_layer *ivilayer = NULL;
struct ivi_layout_layer *next = NULL;
int is_layer_in_scrn = 0;
if (iviscrn == NULL || addlayer == NULL) {
weston_log("ivi_layout_screen_add_layer: invalid argument\n");
return IVI_FAILED;
}
is_layer_in_scrn = is_layer_in_screen(addlayer, iviscrn);
if (is_layer_in_scrn == 1) {
weston_log("ivi_layout_screen_add_layer: addlayer is already available\n");
return IVI_SUCCEEDED;
}
wl_list_for_each_safe(ivilayer, next, &layout->layer_list, link) {
if (ivilayer->id_layer == addlayer->id_layer) {
wl_list_remove(&ivilayer->pending.link);
wl_list_insert(&iviscrn->pending.layer_list,
&ivilayer->pending.link);
break;
}
}
iviscrn->order.dirty = 1;
return IVI_SUCCEEDED;
}
static int32_t
ivi_layout_screen_set_render_order(struct ivi_layout_screen *iviscrn,
struct ivi_layout_layer **pLayer,
const int32_t number)
{
struct ivi_layout *layout = get_instance();
struct ivi_layout_layer *ivilayer = NULL;
struct ivi_layout_layer *next = NULL;
uint32_t *id_layer = NULL;
int32_t i = 0;
if (iviscrn == NULL) {
weston_log("ivi_layout_screen_set_render_order: invalid argument\n");
return IVI_FAILED;
}
wl_list_for_each_safe(ivilayer, next,
&iviscrn->pending.layer_list, pending.link) {
wl_list_remove(&ivilayer->pending.link);
wl_list_init(&ivilayer->pending.link);
}
assert(wl_list_empty(&iviscrn->pending.layer_list));
for (i = 0; i < number; i++) {
id_layer = &pLayer[i]->id_layer;
wl_list_for_each(ivilayer, &layout->layer_list, link) {
if (*id_layer != ivilayer->id_layer) {
continue;
}
wl_list_remove(&ivilayer->pending.link);
wl_list_insert(&iviscrn->pending.layer_list,
&ivilayer->pending.link);
break;
}
}
iviscrn->order.dirty = 1;
return IVI_SUCCEEDED;
}
static struct weston_output *
ivi_layout_screen_get_output(struct ivi_layout_screen *iviscrn)
{
return iviscrn->output;
}
/**
* This function is used by the additional ivi-module because of dumping ivi_surface sceenshot.
* The ivi-module, e.g. ivi-controller.so, is in wayland-ivi-extension of Genivi's Layer Management.
* This function is used to get the result of drawing by clients.
*/
static struct weston_surface *
ivi_layout_surface_get_weston_surface(struct ivi_layout_surface *ivisurf)
{
return ivisurf != NULL ? ivisurf->surface : NULL;
}
static int32_t
ivi_layout_surface_get_size(struct ivi_layout_surface *ivisurf,
int32_t *width, int32_t *height,
int32_t *stride)
{
int32_t w;
int32_t h;
const size_t bytespp = 4; /* PIXMAN_a8b8g8r8 */
if (ivisurf == NULL || ivisurf->surface == NULL) {
weston_log("%s: invalid argument\n", __func__);
return IVI_FAILED;
}
weston_surface_get_content_size(ivisurf->surface, &w, &h);
if (width != NULL)
*width = w;
if (height != NULL)
*height = h;
if (stride != NULL)
*stride = w * bytespp;
return IVI_SUCCEEDED;
}
static int32_t
ivi_layout_layer_add_notification(struct ivi_layout_layer *ivilayer,
layer_property_notification_func callback,
void *userdata)
{
struct ivi_layout_notification_callback *prop_callback = NULL;
if (ivilayer == NULL || callback == NULL) {
weston_log("ivi_layout_layer_add_notification: invalid argument\n");
return IVI_FAILED;
}
prop_callback = malloc(sizeof *prop_callback);
if (prop_callback == NULL) {
weston_log("fails to allocate memory\n");
return IVI_FAILED;
}
prop_callback->callback = callback;
prop_callback->data = userdata;
return add_notification(&ivilayer->property_changed,
layer_prop_changed,
prop_callback);
}
static const struct ivi_layout_surface_properties *
ivi_layout_get_properties_of_surface(struct ivi_layout_surface *ivisurf)
{
if (ivisurf == NULL) {
weston_log("ivi_layout_get_properties_of_surface: invalid argument\n");
return NULL;
}
return &ivisurf->prop;
}
static int32_t
ivi_layout_layer_add_surface(struct ivi_layout_layer *ivilayer,
struct ivi_layout_surface *addsurf)
{
struct ivi_layout *layout = get_instance();
struct ivi_layout_surface *ivisurf = NULL;
struct ivi_layout_surface *next = NULL;
int is_surf_in_layer = 0;
if (ivilayer == NULL || addsurf == NULL) {
weston_log("ivi_layout_layer_add_surface: invalid argument\n");
return IVI_FAILED;
}
is_surf_in_layer = is_surface_in_layer(addsurf, ivilayer);
if (is_surf_in_layer == 1) {
weston_log("ivi_layout_layer_add_surface: addsurf is already available\n");
return IVI_SUCCEEDED;
}
wl_list_for_each_safe(ivisurf, next, &layout->surface_list, link) {
if (ivisurf->id_surface == addsurf->id_surface) {
wl_list_remove(&ivisurf->pending.link);
wl_list_insert(&ivilayer->pending.surface_list,
&ivisurf->pending.link);
break;
}
}
ivilayer->order.dirty = 1;
return IVI_SUCCEEDED;
}
static void
ivi_layout_layer_remove_surface(struct ivi_layout_layer *ivilayer,
struct ivi_layout_surface *remsurf)
{
struct ivi_layout_surface *ivisurf = NULL;
struct ivi_layout_surface *next = NULL;
if (ivilayer == NULL || remsurf == NULL) {
weston_log("ivi_layout_layer_remove_surface: invalid argument\n");
return;
}
wl_list_for_each_safe(ivisurf, next,
&ivilayer->pending.surface_list, pending.link) {
if (ivisurf->id_surface == remsurf->id_surface) {
wl_list_remove(&ivisurf->pending.link);
wl_list_init(&ivisurf->pending.link);
break;
}
}
ivilayer->order.dirty = 1;
}
static int32_t
ivi_layout_surface_set_source_rectangle(struct ivi_layout_surface *ivisurf,
int32_t x, int32_t y,
int32_t width, int32_t height)
{
struct ivi_layout_surface_properties *prop = NULL;
if (ivisurf == NULL) {
weston_log("ivi_layout_surface_set_source_rectangle: invalid argument\n");
return IVI_FAILED;
}
prop = &ivisurf->pending.prop;
prop->source_x = x;
prop->source_y = y;
prop->source_width = width;
prop->source_height = height;
if (ivisurf->prop.source_x != x || ivisurf->prop.source_y != y ||
ivisurf->prop.source_width != width ||
ivisurf->prop.source_height != height)
ivisurf->event_mask |= IVI_NOTIFICATION_SOURCE_RECT;
else
ivisurf->event_mask &= ~IVI_NOTIFICATION_SOURCE_RECT;
return IVI_SUCCEEDED;
}
int32_t
ivi_layout_commit_changes(void)
{
struct ivi_layout *layout = get_instance();
commit_surface_list(layout);
commit_layer_list(layout);
commit_screen_list(layout);
commit_transition(layout);
commit_changes(layout);
send_prop(layout);
weston_compositor_schedule_repaint(layout->compositor);
return IVI_SUCCEEDED;
}
static int32_t
ivi_layout_layer_set_transition(struct ivi_layout_layer *ivilayer,
enum ivi_layout_transition_type type,
uint32_t duration)
{
if (ivilayer == NULL) {
weston_log("%s: invalid argument\n", __func__);
return -1;
}
ivilayer->pending.prop.transition_type = type;
ivilayer->pending.prop.transition_duration = duration;
return 0;
}
static int32_t
ivi_layout_layer_set_fade_info(struct ivi_layout_layer* ivilayer,
uint32_t is_fade_in,
double start_alpha, double end_alpha)
{
if (ivilayer == NULL) {
weston_log("%s: invalid argument\n", __func__);
return -1;
}
ivilayer->pending.prop.is_fade_in = is_fade_in;
ivilayer->pending.prop.start_alpha = start_alpha;
ivilayer->pending.prop.end_alpha = end_alpha;
return 0;
}
static int32_t
ivi_layout_surface_set_transition_duration(struct ivi_layout_surface *ivisurf,
uint32_t duration)
{
struct ivi_layout_surface_properties *prop;
if (ivisurf == NULL) {
weston_log("%s: invalid argument\n", __func__);
return -1;
}
prop = &ivisurf->pending.prop;
prop->transition_duration = duration*10;
return 0;
}
static int32_t
ivi_layout_surface_set_transition(struct ivi_layout_surface *ivisurf,
enum ivi_layout_transition_type type,
uint32_t duration)
{
struct ivi_layout_surface_properties *prop;
if (ivisurf == NULL) {
weston_log("%s: invalid argument\n", __func__);
return -1;
}
prop = &ivisurf->pending.prop;
prop->transition_type = type;
prop->transition_duration = duration;
return 0;
}
static int32_t
ivi_layout_surface_dump(struct weston_surface *surface,
void *target, size_t size,int32_t x, int32_t y,
int32_t width, int32_t height)
{
int result = 0;
if (surface == NULL) {
weston_log("%s: invalid argument\n", __func__);
return IVI_FAILED;
}
result = weston_surface_copy_content(
surface, target, size,
x, y, width, height);
return result == 0 ? IVI_SUCCEEDED : IVI_FAILED;
}
/**
* methods of interaction between ivi-shell with ivi-layout
*/
struct weston_view *
ivi_layout_get_weston_view(struct ivi_layout_surface *surface)
{
struct weston_view *tmpview = NULL;
if (surface == NULL)
return NULL;
wl_list_for_each(tmpview, &surface->surface->views, surface_link)
{
if (tmpview != NULL) {
break;
}
}
return tmpview;
}
void
ivi_layout_surface_configure(struct ivi_layout_surface *ivisurf,
int32_t width, int32_t height)
{
struct ivi_layout *layout = get_instance();
/* emit callback which is set by ivi-layout api user */
wl_signal_emit(&layout->surface_notification.configure_changed,
ivisurf);
}
static int32_t
ivi_layout_surface_set_content_observer(struct ivi_layout_surface *ivisurf,
ivi_controller_surface_content_callback callback,
void* userdata)
{
int32_t ret = IVI_FAILED;
if (ivisurf != NULL) {
ivisurf->content_observer.callback = callback;
ivisurf->content_observer.userdata = userdata;
ret = IVI_SUCCEEDED;
}
return ret;
}
struct ivi_layout_surface*
ivi_layout_surface_create(struct weston_surface *wl_surface,
uint32_t id_surface)
{
struct ivi_layout *layout = get_instance();
struct ivi_layout_surface *ivisurf = NULL;
struct weston_view *tmpview = NULL;
if (wl_surface == NULL) {
weston_log("ivi_layout_surface_create: invalid argument\n");
return NULL;
}
ivisurf = get_surface(&layout->surface_list, id_surface);
if (ivisurf != NULL) {
if (ivisurf->surface != NULL) {
weston_log("id_surface(%d) is already created\n", id_surface);
return NULL;
}
}
ivisurf = calloc(1, sizeof *ivisurf);
if (ivisurf == NULL) {
weston_log("fails to allocate memory\n");
return NULL;
}
wl_signal_init(&ivisurf->property_changed);
wl_signal_init(&ivisurf->configured);
wl_list_init(&ivisurf->layer_list);
ivisurf->id_surface = id_surface;
ivisurf->layout = layout;
ivisurf->surface = wl_surface;
tmpview = weston_view_create(wl_surface);
if (tmpview == NULL) {
weston_log("fails to allocate memory\n");
}
ivisurf->surface->width_from_buffer = 0;
ivisurf->surface->height_from_buffer = 0;
weston_matrix_init(&ivisurf->transform.matrix);
wl_list_init(&ivisurf->transform.link);
init_surface_properties(&ivisurf->prop);
ivisurf->event_mask = 0;
ivisurf->pending.prop = ivisurf->prop;
wl_list_init(&ivisurf->pending.link);
wl_list_init(&ivisurf->order.link);
wl_list_init(&ivisurf->order.layer_list);
wl_list_insert(&layout->surface_list, &ivisurf->link);
wl_signal_emit(&layout->surface_notification.created, ivisurf);
return ivisurf;
}
void
ivi_layout_init_with_compositor(struct weston_compositor *ec)
{
struct ivi_layout *layout = get_instance();
layout->compositor = ec;
wl_list_init(&layout->surface_list);
wl_list_init(&layout->layer_list);
wl_list_init(&layout->screen_list);
wl_signal_init(&layout->layer_notification.created);
wl_signal_init(&layout->layer_notification.removed);
wl_signal_init(&layout->surface_notification.created);
wl_signal_init(&layout->surface_notification.removed);
wl_signal_init(&layout->surface_notification.configure_changed);
/* Add layout_layer at the last of weston_compositor.layer_list */
weston_layer_init(&layout->layout_layer, ec->layer_list.prev);
create_screen(ec);
layout->transitions = ivi_layout_transition_set_create(ec);
wl_list_init(&layout->pending_transition_list);
}
void
ivi_layout_surface_add_configured_listener(struct ivi_layout_surface* ivisurf,
struct wl_listener* listener)
{
wl_signal_add(&ivisurf->configured, listener);
}
static struct ivi_controller_interface ivi_controller_interface = {
/**
* commit all changes
*/
.commit_changes = ivi_layout_commit_changes,
/**
* surface controller interfaces
*/
.add_notification_create_surface = ivi_layout_add_notification_create_surface,
.remove_notification_create_surface = ivi_layout_remove_notification_create_surface,
.add_notification_remove_surface = ivi_layout_add_notification_remove_surface,
.remove_notification_remove_surface = ivi_layout_remove_notification_remove_surface,
.add_notification_configure_surface = ivi_layout_add_notification_configure_surface,
.remove_notification_configure_surface = ivi_layout_remove_notification_configure_surface,
.get_surfaces = ivi_layout_get_surfaces,
.get_id_of_surface = ivi_layout_get_id_of_surface,
.get_surface_from_id = ivi_layout_get_surface_from_id,
.get_properties_of_surface = ivi_layout_get_properties_of_surface,
.get_surfaces_on_layer = ivi_layout_get_surfaces_on_layer,
.surface_set_visibility = ivi_layout_surface_set_visibility,
.surface_get_visibility = ivi_layout_surface_get_visibility,
.surface_set_opacity = ivi_layout_surface_set_opacity,
.surface_get_opacity = ivi_layout_surface_get_opacity,
.surface_set_source_rectangle = ivi_layout_surface_set_source_rectangle,
.surface_set_destination_rectangle = ivi_layout_surface_set_destination_rectangle,
.surface_set_position = ivi_layout_surface_set_position,
.surface_get_position = ivi_layout_surface_get_position,
.surface_set_dimension = ivi_layout_surface_set_dimension,
.surface_get_dimension = ivi_layout_surface_get_dimension,
.surface_set_orientation = ivi_layout_surface_set_orientation,
.surface_get_orientation = ivi_layout_surface_get_orientation,
.surface_set_content_observer = ivi_layout_surface_set_content_observer,
.surface_add_notification = ivi_layout_surface_add_notification,
.surface_remove_notification = ivi_layout_surface_remove_notification,
.surface_get_weston_surface = ivi_layout_surface_get_weston_surface,
.surface_set_transition = ivi_layout_surface_set_transition,
.surface_set_transition_duration = ivi_layout_surface_set_transition_duration,
/**
* layer controller interfaces
*/
.add_notification_create_layer = ivi_layout_add_notification_create_layer,
.remove_notification_create_layer = ivi_layout_remove_notification_create_layer,
.add_notification_remove_layer = ivi_layout_add_notification_remove_layer,
.remove_notification_remove_layer = ivi_layout_remove_notification_remove_layer,
.layer_create_with_dimension = ivi_layout_layer_create_with_dimension,
.layer_destroy = ivi_layout_layer_destroy,
.get_layers = ivi_layout_get_layers,
.get_id_of_layer = ivi_layout_get_id_of_layer,
.get_layer_from_id = ivi_layout_get_layer_from_id,
.get_properties_of_layer = ivi_layout_get_properties_of_layer,
.get_layers_under_surface = ivi_layout_get_layers_under_surface,
.get_layers_on_screen = ivi_layout_get_layers_on_screen,
.layer_set_visibility = ivi_layout_layer_set_visibility,
.layer_get_visibility = ivi_layout_layer_get_visibility,
.layer_set_opacity = ivi_layout_layer_set_opacity,
.layer_get_opacity = ivi_layout_layer_get_opacity,
.layer_set_source_rectangle = ivi_layout_layer_set_source_rectangle,
.layer_set_destination_rectangle = ivi_layout_layer_set_destination_rectangle,
.layer_set_position = ivi_layout_layer_set_position,
.layer_get_position = ivi_layout_layer_get_position,
.layer_set_dimension = ivi_layout_layer_set_dimension,
.layer_get_dimension = ivi_layout_layer_get_dimension,
.layer_set_orientation = ivi_layout_layer_set_orientation,
.layer_get_orientation = ivi_layout_layer_get_orientation,
.layer_add_surface = ivi_layout_layer_add_surface,
.layer_remove_surface = ivi_layout_layer_remove_surface,
.layer_set_render_order = ivi_layout_layer_set_render_order,
.layer_add_notification = ivi_layout_layer_add_notification,
.layer_remove_notification = ivi_layout_layer_remove_notification,
.layer_set_transition = ivi_layout_layer_set_transition,
/**
* screen controller interfaces part1
*/
.get_screen_from_id = ivi_layout_get_screen_from_id,
.get_screen_resolution = ivi_layout_get_screen_resolution,
.get_screens = ivi_layout_get_screens,
.get_screens_under_layer = ivi_layout_get_screens_under_layer,
.screen_add_layer = ivi_layout_screen_add_layer,
.screen_set_render_order = ivi_layout_screen_set_render_order,
.screen_get_output = ivi_layout_screen_get_output,
/**
* animation
*/
.transition_move_layer_cancel = ivi_layout_transition_move_layer_cancel,
.layer_set_fade_info = ivi_layout_layer_set_fade_info,
/**
* surface content dumping for debugging
*/
.surface_get_size = ivi_layout_surface_get_size,
.surface_dump = ivi_layout_surface_dump,
/**
* remove notification by callback on property changes of ivi_surface/layer
*/
.surface_remove_notification_by_callback = ivi_layout_surface_remove_notification_by_callback,
.layer_remove_notification_by_callback = ivi_layout_layer_remove_notification_by_callback,
/**
* screen controller interfaces part2
*/
.get_id_of_screen = ivi_layout_get_id_of_screen
};
int
load_controller_modules(struct weston_compositor *compositor, const char *modules,
int *argc, char *argv[])
{
const char *p, *end;
char buffer[256];
int (*controller_module_init)(struct weston_compositor *compositor,
int *argc, char *argv[],
const struct ivi_controller_interface *interface,
size_t interface_version);
if (modules == NULL)
return 0;
p = modules;
while (*p) {
end = strchrnul(p, ',');
snprintf(buffer, sizeof buffer, "%.*s", (int)(end - p), p);
controller_module_init = weston_load_module(buffer, "controller_module_init");
if (!controller_module_init)
return -1;
if (controller_module_init(compositor, argc, argv,
&ivi_controller_interface,
sizeof(struct ivi_controller_interface)) != 0) {
weston_log("ivi-shell: Initialization of controller module fails");
return -1;
}
p = end;
while (*p == ',')
p++;
}
return 0;
}