ivi-layout.c 57.9 KB
Newer Older
1 2 3
/*
 * Copyright (C) 2013 DENSO CORPORATION
 *
4 5 6 7 8 9 10
 * 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:
11
 *
12 13 14 15 16 17 18 19 20 21 22 23
 * 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.
24 25 26 27
 */

/**
 * Implementation of ivi-layout library. The actual view on ivi_screen is
28
 * not updated until ivi_layout_commit_changes is called. An overview from
29 30 31 32
 * 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.
33
 * 1/ When an API for updating properties of ivi_surface/ivi_layer, it updates
34 35
 *    pending prop of ivi_surface/ivi_layer/ivi_screen which are structure to
 *    store properties.
36
 * 2/ Before calling commitChanges, in case of calling an API to get a property,
37 38 39 40 41 42 43 44
 *    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.
45 46
 *    For example, when a property of ivi_surface is changed from invisibile
 *    to visibile, it behaves like fade-in. When ivi_layout_commitChange is
47 48
 *    called during transition animation, it cancels the transition and
 *    re-start transition to new properties from current properties of final
49
 *    frame just before the cancellation.
50 51 52 53 54 55 56 57
 *
 * 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.
 *
 */
58
#include "config.h"
59 60

#include <string.h>
61
#include <assert.h>
62
#include <stdint.h>
63

64
#include "compositor/weston.h"
65
#include "compositor.h"
66
#include "ivi-shell.h"
67 68
#include "ivi-layout-export.h"
#include "ivi-layout-private.h"
69
#include "ivi-layout-shell.h"
70

71
#include "shared/helpers.h"
72
#include "shared/os-compatibility.h"
73

74 75
#define max(a, b) ((a) > (b) ? (a) : (b))

76 77 78 79 80 81 82 83 84 85 86 87 88 89
struct ivi_layout;

struct ivi_layout_screen {
	struct wl_list link;

	struct ivi_layout *layout;
	struct weston_output *output;

	struct {
		struct wl_list layer_list;
		struct wl_list link;
	} pending;

	struct {
90
		int dirty;
91 92 93 94 95
		struct wl_list layer_list;
		struct wl_list link;
	} order;
};

96 97 98 99 100 101 102 103
struct ivi_rectangle
{
	int32_t x;
	int32_t y;
	int32_t width;
	int32_t height;
};

104 105 106 107 108 109 110 111 112
static struct ivi_layout ivilayout = {0};

struct ivi_layout *
get_instance(void)
{
	return &ivilayout;
}

/**
113
 * Internal API to add/remove an ivi_layer to/from ivi_screen.
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
 */
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;
}

eucan's avatar
eucan committed
143 144
static bool
ivi_view_is_rendered(struct ivi_layout_view *view)
eucan's avatar
eucan committed
145
{
eucan's avatar
eucan committed
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
	return !wl_list_empty(&view->order_link);
}

static void
ivi_view_destroy(struct ivi_layout_view *ivi_view)
{
	wl_list_remove(&ivi_view->transform.link);
	wl_list_remove(&ivi_view->link);
	wl_list_remove(&ivi_view->surf_link);
	wl_list_remove(&ivi_view->pending_link);
	wl_list_remove(&ivi_view->order_link);

	weston_view_destroy(ivi_view->view);

	free(ivi_view);
}

static struct ivi_layout_view*
ivi_view_create(struct ivi_layout_layer *ivilayer,
		struct ivi_layout_surface *ivisurf)
{
	struct ivi_layout_view *ivi_view;

	ivi_view = calloc(1, sizeof *ivi_view);
	if (ivi_view == NULL) {
		weston_log("fails to allocate memory\n");
		return NULL;
	}

	ivi_view->view = weston_view_create(ivisurf->surface);
	if (ivi_view->view == NULL) {
		weston_log("fails to allocate memory\n");
		return NULL;
	}

	weston_matrix_init(&ivi_view->transform.matrix);
	wl_list_init(&ivi_view->transform.link);

	ivi_view->ivisurf = ivisurf;
	ivi_view->on_layer = ivilayer;
	wl_list_insert(&ivilayer->layout->view_list,
		       &ivi_view->link);
	wl_list_insert(&ivisurf->view_list,
		       &ivi_view->surf_link);

	wl_list_init(&ivi_view->pending_link);
	wl_list_init(&ivi_view->order_link);

	return ivi_view;
}

static struct ivi_layout_view *
get_ivi_view(struct ivi_layout_layer *ivilayer,
		struct ivi_layout_surface *ivisurf)
{
	struct ivi_layout_view *ivi_view;
eucan's avatar
eucan committed
202 203 204

	assert(ivisurf->surface != NULL);

eucan's avatar
eucan committed
205 206 207 208
	wl_list_for_each(ivi_view, &ivisurf->view_list, surf_link) {
		if (ivi_view->on_layer == ivilayer)
			return ivi_view;
	}
eucan's avatar
eucan committed
209

eucan's avatar
eucan committed
210
	return NULL;
eucan's avatar
eucan committed
211 212
}

213 214 215 216 217 218 219 220 221 222 223 224 225 226
static struct ivi_layout_screen *
get_screen_from_output(struct weston_output *output)
{
	struct ivi_layout *layout = get_instance();
	struct ivi_layout_screen *iviscrn = NULL;

	wl_list_for_each(iviscrn, &layout->screen_list, link) {
		if (iviscrn->output == output)
			return iviscrn;
	}

	return NULL;
}

227
/**
228
 * Called at destruction of wl_surface/ivi_surface
229
 */
230 231
void
ivi_layout_surface_destroy(struct ivi_layout_surface *ivisurf)
232 233
{
	struct ivi_layout *layout = get_instance();
eucan's avatar
eucan committed
234
	struct ivi_layout_view *ivi_view ,*next;
235 236

	if (ivisurf == NULL) {
237
		weston_log("%s: invalid argument\n", __func__);
238 239 240
		return;
	}

241 242 243
	wl_list_remove(&ivisurf->pending.link);
	wl_list_remove(&ivisurf->order.link);
	wl_list_remove(&ivisurf->link);
244

eucan's avatar
eucan committed
245 246 247 248
	wl_list_for_each_safe(ivi_view, next, &ivisurf->view_list, surf_link) {
		ivi_view_destroy(ivi_view);
	}

249 250
	wl_signal_emit(&layout->surface_notification.removed, ivisurf);

251 252
	ivi_layout_remove_all_surface_transitions(ivisurf);

253
	free(ivisurf);
254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307
}

/**
 * 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;

	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->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_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);
308
	/*
309
	 * FIXME: this shall be fixed by ivi-layout-transition.
310 311 312
	 */
	prop->dest_width = 1;
	prop->dest_height = 1;
313 314 315 316 317 318 319
}

/**
 * Internal APIs to be called from ivi_layout_commit_changes.
 */
static void
update_opacity(struct ivi_layout_layer *ivilayer,
eucan's avatar
eucan committed
320 321
	       struct ivi_layout_surface *ivisurf,
	       struct weston_view *view)
322 323 324 325
{
	double layer_alpha = wl_fixed_to_double(ivilayer->prop.opacity);
	double surf_alpha  = wl_fixed_to_double(ivisurf->prop.opacity);

eucan's avatar
eucan committed
326
	view->alpha = layer_alpha * surf_alpha;
327 328
}

329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420
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);
}

421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514
/*
 * 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);
}

515
/**
516
 * This computes the whole transformation matrix:m from surface-local
517
 * coordinates to multi-screen coordinates, which are global coordinates.
518
 * It is assumed that weston_view::geometry.{x,y} are zero.
519
 *
520
 * Additionally, this computes the mask on surface-local coordinates as an
521 522 523
 * ivi_rectangle. This can be set to weston_view_set_mask.
 *
 * The mask is computed by following steps
524
 * - destination rectangle of layer is transformed to multi-screen coordinates,
525 526
 *   global coordinates. This is done by adding weston_output.{x,y} in simple
 *   because there is no scaled and rotated transformation.
527
 * - destination rectangle of layer in multi-screen coordinates needs to be
528 529 530 531
 *   intersected inside of a screen the layer is assigned to. This is because
 *   overlapped region of weston surface in another screen shall not be
 *   displayed according to ivi use case.
 * - destination rectangle of layer
532
 *   - in multi-screen coordinates,
533
 *   - and intersected inside of an assigned screen,
534
 *   is inversed to surface-local coordinates by inversed matrix:m.
535 536
 * - the area is intersected by intersected area between weston_surface and
 *   source rectangle of ivi_surface.
537 538
 */
static void
539
calc_surface_to_global_matrix_and_mask_to_weston_surface(
540
	struct ivi_layout_screen  *iviscrn,
541 542 543 544
	struct ivi_layout_layer *ivilayer,
	struct ivi_layout_surface *ivisurf,
	struct weston_matrix *m,
	struct ivi_rectangle *result)
545 546 547
{
	const struct ivi_layout_surface_properties *sp = &ivisurf->prop;
	const struct ivi_layout_layer_properties *lp = &ivilayer->prop;
548
	struct weston_output *output = iviscrn->output;
549 550 551 552
	struct ivi_rectangle weston_surface_rect = { 0,
						     0,
						     ivisurf->surface->width,
						     ivisurf->surface->height };
553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568
	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 };
569 570 571 572 573 574 575 576 577
	struct ivi_rectangle screen_dest_rect =    { output->x,
						     output->y,
						     output->width,
						     output->height };
	struct ivi_rectangle layer_dest_rect_in_global =
						   { lp->dest_x + output->x,
						     lp->dest_y + output->y,
						     lp->dest_width,
						     lp->dest_height };
578
	struct ivi_rectangle surface_result;
579
	struct ivi_rectangle layer_dest_rect_in_global_intersected;
580

581 582 583 584 585
	/*
	 * 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
586 587 588
	 * - layer-local coordinates to single screen-local coordinates
	 * - single screen-local coordinates to multi-screen coordinates,
	 *   which are global coordinates.
589
	 */
590 591 592 593 594 595 596
	calc_transformation_matrix(&surface_source_rect,
				   &surface_dest_rect,
				   sp->orientation, m);

	calc_transformation_matrix(&layer_source_rect,
				   &layer_dest_rect,
				   lp->orientation, m);
597

598 599
	weston_matrix_translate(m, output->x, output->y, 0.0f);

600 601 602 603 604 605
	/* this intersected ivi_rectangle would be used for masking
	 * weston_surface
	 */
	ivi_rectangle_intersect(&surface_source_rect, &weston_surface_rect,
				&surface_result);

606 607 608 609 610 611 612
	/*
	 * destination rectangle of layer in multi screens coordinate
	 * is intersected to avoid displaying outside of an assigned screen.
	 */
	ivi_rectangle_intersect(&layer_dest_rect_in_global, &screen_dest_rect,
				&layer_dest_rect_in_global_intersected);

613 614
	/* calc masking area of weston_surface from m */
	calc_inverse_matrix_transform(m,
615
				      &layer_dest_rect_in_global_intersected,
616 617
				      &surface_result,
				      result);
618 619
}

620
static void
621 622
update_prop(struct ivi_layout_screen  *iviscrn,
	    struct ivi_layout_layer *ivilayer,
eucan's avatar
eucan committed
623
	    struct ivi_layout_view *ivi_view)
624
{
eucan's avatar
eucan committed
625
	struct ivi_layout_surface *ivisurf;
626
	struct ivi_rectangle r;
627
	bool can_calc = true;
628

eucan's avatar
eucan committed
629 630 631 632
	assert(ivi_view->on_layer == ivilayer);

	ivisurf = ivi_view->ivisurf;

633
	/*In case of no prop change, this just returns*/
634
	if (!ivilayer->prop.event_mask && !ivisurf->prop.event_mask)
635
		return;
636

eucan's avatar
eucan committed
637
	update_opacity(ivilayer, ivisurf, ivi_view->view);
638

639 640 641 642 643 644 645 646 647 648 649
	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) {
eucan's avatar
eucan committed
650 651
		wl_list_remove(&ivi_view->transform.link);
		weston_matrix_init(&ivi_view->transform.matrix);
652

653
		calc_surface_to_global_matrix_and_mask_to_weston_surface(
eucan's avatar
eucan committed
654
			iviscrn, ivilayer, ivisurf, &ivi_view->transform.matrix, &r);
655

eucan's avatar
eucan committed
656 657 658
		weston_view_set_mask(ivi_view->view, r.x, r.y, r.width, r.height);
		wl_list_insert(&ivi_view->view->geometry.transformation_list,
			       &ivi_view->transform.link);
659

eucan's avatar
eucan committed
660
		weston_view_set_transform_parent(ivi_view->view, NULL);
661 662 663 664
	}

	ivisurf->update_count++;

eucan's avatar
eucan committed
665
	weston_view_geometry_dirty(ivi_view->view);
666

eucan's avatar
eucan committed
667
	weston_surface_damage(ivisurf->surface);
668 669 670 671 672 673 674
}

static void
commit_changes(struct ivi_layout *layout)
{
	struct ivi_layout_screen  *iviscrn  = NULL;
	struct ivi_layout_layer   *ivilayer = NULL;
eucan's avatar
eucan committed
675
	struct ivi_layout_view *ivi_view  = NULL;
676 677 678

	wl_list_for_each(iviscrn, &layout->screen_list, link) {
		wl_list_for_each(ivilayer, &iviscrn->order.layer_list, order.link) {
679 680 681 682 683 684 685
			/*
			 * If ivilayer is invisible, weston_view of ivisurf doesn't
			 * need to be modified.
			 */
			if (ivilayer->prop.visibility == false)
				continue;

eucan's avatar
eucan committed
686
			wl_list_for_each(ivi_view, &ivilayer->order.view_list, order_link) {
687 688 689 690
				/*
				 * If ivilayer is invisible, weston_view of ivisurf doesn't
				 * need to be modified.
				 */
eucan's avatar
eucan committed
691
				if (ivi_view->ivisurf->prop.visibility == false)
692 693
					continue;

eucan's avatar
eucan committed
694
				update_prop(iviscrn, ivilayer, ivi_view);
695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710
			}
		}
	}
}

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) {
Dawid Gajownik's avatar
Dawid Gajownik committed
711
		if (ivisurf->pending.prop.transition_type == IVI_LAYOUT_TRANSITION_VIEW_DEFAULT) {
712 713 714 715 716 717 718 719 720 721 722 723
			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);

Dawid Gajownik's avatar
Dawid Gajownik committed
724
			if (ivisurf->pending.prop.visibility) {
725 726 727 728 729 730 731 732 733 734 735 736 737
				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;

Dawid Gajownik's avatar
Dawid Gajownik committed
738
		} else if (ivisurf->pending.prop.transition_type == IVI_LAYOUT_TRANSITION_VIEW_DEST_RECT_ONLY) {
739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759
			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;

Dawid Gajownik's avatar
Dawid Gajownik committed
760
		} else if (ivisurf->pending.prop.transition_type == IVI_LAYOUT_TRANSITION_VIEW_FADE_ONLY) {
761
			configured = 0;
Dawid Gajownik's avatar
Dawid Gajownik committed
762
			if (ivisurf->pending.prop.visibility) {
763 764 765 766 767 768 769 770 771 772 773 774 775 776
				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;

777 778 779 780 781
			if (configured && !is_surface_transition(ivisurf)) {
				shell_surface_send_configure(ivisurf->surface,
							     ivisurf->prop.dest_width,
							     ivisurf->prop.dest_height);
			}
782 783 784 785 786 787 788 789 790 791 792
		} 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;

793 794 795 796 797
			if (configured && !is_surface_transition(ivisurf)) {
				shell_surface_send_configure(ivisurf->surface,
							     ivisurf->prop.dest_width,
							     ivisurf->prop.dest_height);
			}
798 799 800 801 802 803 804
		}
	}
}

static void
commit_layer_list(struct ivi_layout *layout)
{
eucan's avatar
eucan committed
805
	struct ivi_layout_view *ivi_view = NULL;
806
	struct ivi_layout_layer   *ivilayer = NULL;
eucan's avatar
eucan committed
807
	struct ivi_layout_view *next     = NULL;
808 809

	wl_list_for_each(ivilayer, &layout->layer_list, link) {
Dawid Gajownik's avatar
Dawid Gajownik committed
810
		if (ivilayer->pending.prop.transition_type == IVI_LAYOUT_TRANSITION_LAYER_MOVE) {
811
			ivi_layout_transition_move_layer(ivilayer, ivilayer->pending.prop.dest_x, ivilayer->pending.prop.dest_y, ivilayer->pending.prop.transition_duration);
Dawid Gajownik's avatar
Dawid Gajownik committed
812
		} else if (ivilayer->pending.prop.transition_type == IVI_LAYOUT_TRANSITION_LAYER_FADE) {
813 814 815 816 817 818 819 820 821
			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;

822
		if (!ivilayer->order.dirty) {
823 824 825
			continue;
		}

eucan's avatar
eucan committed
826 827 828 829 830
		wl_list_for_each_safe(ivi_view, next, &ivilayer->order.view_list,
					 order_link) {
			wl_list_remove(&ivi_view->order_link);
			wl_list_init(&ivi_view->order_link);
			ivi_view->ivisurf->prop.event_mask |= IVI_NOTIFICATION_REMOVE;
831 832
		}

eucan's avatar
eucan committed
833
		assert(wl_list_empty(&ivilayer->order.view_list));
834

eucan's avatar
eucan committed
835 836 837 838 839
		wl_list_for_each(ivi_view, &ivilayer->pending.view_list,
					 pending_link) {
			wl_list_remove(&ivi_view->order_link);
			wl_list_insert(&ivilayer->order.view_list, &ivi_view->order_link);
			ivi_view->ivisurf->prop.event_mask |= IVI_NOTIFICATION_ADD;
840
		}
841 842

		ivilayer->order.dirty = 0;
843 844 845 846 847 848 849 850 851
	}
}

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;
eucan's avatar
eucan committed
852
	struct ivi_layout_view *ivi_view = NULL;
853

854 855 856
	/* Clear view list of layout ivi_layer */
	wl_list_init(&layout->layout_layer.view_list.link);

857
	wl_list_for_each(iviscrn, &layout->screen_list, link) {
858
		if (iviscrn->order.dirty) {
859 860
			wl_list_for_each_safe(ivilayer, next,
					      &iviscrn->order.layer_list, order.link) {
eucan's avatar
eucan committed
861
				ivilayer->on_screen = NULL;
862
				wl_list_remove(&ivilayer->order.link);
863
				wl_list_init(&ivilayer->order.link);
864
				ivilayer->prop.event_mask |= IVI_NOTIFICATION_REMOVE;
865 866
			}

867
			assert(wl_list_empty(&iviscrn->order.layer_list));
868 869 870

			wl_list_for_each(ivilayer, &iviscrn->pending.layer_list,
					 pending.link) {
871 872 873
				/* FIXME: avoid to insert order.link to multiple screens */
				wl_list_remove(&ivilayer->order.link);

874 875
				wl_list_insert(&iviscrn->order.layer_list,
					       &ivilayer->order.link);
eucan's avatar
eucan committed
876
				ivilayer->on_screen = iviscrn;
877
				ivilayer->prop.event_mask |= IVI_NOTIFICATION_ADD;
878 879
			}

880 881
			iviscrn->order.dirty = 0;
		}
882 883 884 885 886

		wl_list_for_each(ivilayer, &iviscrn->order.layer_list, order.link) {
			if (ivilayer->prop.visibility == false)
				continue;

eucan's avatar
eucan committed
887 888
			wl_list_for_each(ivi_view, &ivilayer->order.view_list, order_link) {
				if (ivi_view->ivisurf->prop.visibility == false)
889
					continue;
eucan's avatar
eucan committed
890

891
				weston_layer_entry_insert(&layout->layout_layer.view_list,
eucan's avatar
eucan committed
892
							  &ivi_view->view->layer_link);
893

eucan's avatar
eucan committed
894
				ivi_view->view->output = iviscrn->output;
895 896
				ivi_view->ivisurf->surface->is_mapped = true;
				ivi_view->view->is_mapped = true;
897 898 899 900 901 902 903 904
			}
		}
	}
}

static void
commit_transition(struct ivi_layout* layout)
{
Dawid Gajownik's avatar
Dawid Gajownik committed
905
	if (wl_list_empty(&layout->pending_transition_list)) {
906 907 908 909 910 911 912 913 914 915 916 917 918 919 920
		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);
921
	ivisurf->pending.prop.event_mask = 0;
922 923 924 925 926 927
}

static void
send_layer_prop(struct ivi_layout_layer *ivilayer)
{
	wl_signal_emit(&ivilayer->property_changed, ivilayer);
928
	ivilayer->pending.prop.event_mask = 0;
929 930 931 932 933 934 935 936 937
}

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) {
938
		if (ivilayer->prop.event_mask)
939
			send_layer_prop(ivilayer);
940 941 942
	}

	wl_list_for_each_reverse(ivisurf, &layout->surface_list, link) {
943
		if (ivisurf->prop.event_mask)
944
			send_surface_prop(ivisurf);
945 946 947 948
	}
}

static void
eucan's avatar
eucan committed
949
clear_view_pending_list(struct ivi_layout_layer *ivilayer)
950
{
eucan's avatar
eucan committed
951 952
	struct ivi_layout_view *view_link = NULL;
	struct ivi_layout_view *view_next = NULL;
953

eucan's avatar
eucan committed
954 955 956 957
	wl_list_for_each_safe(view_link, view_next,
			      &ivilayer->pending.view_list, pending_link) {
		wl_list_remove(&view_link->pending_link);
		wl_list_init(&view_link->pending_link);
958 959 960 961 962 963 964
	}
}

/**
 * Exported APIs of ivi-layout library are implemented from here.
 * Brief of APIs is described in ivi-layout-export.h.
 */
965
static int32_t
966
ivi_layout_add_listener_create_layer(struct wl_listener *listener)
967 968 969
{
	struct ivi_layout *layout = get_instance();

970 971
	if (listener == NULL) {
		weston_log("ivi_layout_add_listener_create_layer: invalid argument\n");
972 973 974
		return IVI_FAILED;
	}

975
	wl_signal_add(&layout->layer_notification.created, listener);
976

977
	return IVI_SUCCEEDED;
978 979
}

980
static int32_t
981
ivi_layout_add_listener_remove_layer(struct wl_listener *listener)
982 983 984
{
	struct ivi_layout *layout = get_instance();

985 986
	if (listener == NULL) {
		weston_log("ivi_layout_add_listener_remove_layer: invalid argument\n");
987 988 989
		return IVI_FAILED;
	}

990
	wl_signal_add(&layout->layer_notification.removed, listener);
991

992
	return IVI_SUCCEEDED;
993 994
}

995
static int32_t
996
ivi_layout_add_listener_create_surface(struct wl_listener *listener)
997 998 999
{
	struct ivi_layout *layout = get_instance();

1000 1001
	if (listener == NULL) {
		weston_log("ivi_layout_add_listener_create_surface: invalid argument\n");
1002 1003 1004
		return IVI_FAILED;
	}

1005
	wl_signal_add(&layout->surface_notification.created, listener);
1006

1007
	return IVI_SUCCEEDED;
1008 1009
}

1010
static int32_t
1011
ivi_layout_add_listener_remove_surface(struct wl_listener *listener)
1012 1013 1014
{
	struct ivi_layout *layout = get_instance();

1015 1016
	if (listener == NULL) {
		weston_log("ivi_layout_add_listener_remove_surface: invalid argument\n");
1017 1018 1019
		return IVI_FAILED;
	}

1020
	wl_signal_add(&layout->surface_notification.removed, listener);
1021

1022
	return IVI_SUCCEEDED;
1023 1024
}

1025
static int32_t
1026
ivi_layout_add_listener_configure_surface(struct wl_listener *listener)
1027 1028 1029
{
	struct ivi_layout *layout = get_instance();

1030 1031
	if (listener == NULL) {
		weston_log("ivi_layout_add_listener_configure_surface: invalid argument\n");
1032 1033 1034
		return IVI_FAILED;
	}

1035
	wl_signal_add(&layout->surface_notification.configure_changed, listener);
1036

1037
	return IVI_SUCCEEDED;
1038 1039
}

1040
uint32_t
1041 1042 1043 1044 1045
ivi_layout_get_id_of_surface(struct ivi_layout_surface *ivisurf)
{
	return ivisurf->id_surface;
}

1046
static uint32_t
1047 1048 1049 1050 1051
ivi_layout_get_id_of_layer(struct ivi_layout_layer *ivilayer)
{
	return ivilayer->id_layer;
}

1052
static struct ivi_layout_layer *
1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066
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;
}

1067
struct ivi_layout_surface *
1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081
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;
}

1082
static int32_t
1083 1084
ivi_layout_surface_add_listener(struct ivi_layout_surface *ivisurf,
				    struct wl_listener *listener)
1085
{
1086 1087
	if (ivisurf == NULL || listener == NULL) {
		weston_log("ivi_layout_surface_add_listener: invalid argument\n");
1088 1089 1090
		return IVI_FAILED;
	}

1091
	wl_signal_add(&ivisurf->property_changed, listener);
1092 1093 1094 1095

	return IVI_SUCCEEDED;
}

1096
static const struct ivi_layout_layer_properties *
1097 1098 1099 1100 1101 1102 1103 1104 1105 1106
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;
}

1107
static int32_t
1108 1109
ivi_layout_get_screens_under_layer(struct ivi_layout_layer *ivilayer,
				   int32_t *pLength,
1110
				   struct weston_output ***ppArray)
1111 1112 1113 1114 1115 1116 1117 1118 1119
{
	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;
	}

eucan's avatar
eucan committed
1120 1121
	if (ivilayer->on_screen != NULL)
		length = 1;
1122

Dawid Gajownik's avatar
Dawid Gajownik committed
1123
	if (length != 0) {
1124
		/* the Array must be free by module which called this function */
1125
		*ppArray = calloc(length, sizeof(struct weston_output *));
1126 1127 1128 1129 1130
		if (*ppArray == NULL) {
			weston_log("fails to allocate memory\n");
			return IVI_FAILED;
		}

1131
		(*ppArray)[n++] = ivilayer->on_screen->output;
1132 1133 1134 1135 1136 1137 1138
	}

	*pLength = length;

	return IVI_SUCCEEDED;
}

1139
static int32_t
1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153
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);

Dawid Gajownik's avatar
Dawid Gajownik committed
1154
	if (length != 0) {
1155
		/* the Array must be freed by module which called this function */
1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171
		*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;
}

1172
static int32_t
1173
ivi_layout_get_layers_on_screen(struct weston_output *output,
1174 1175 1176
				int32_t *pLength,
				struct ivi_layout_layer ***ppArray)
{
1177
	struct ivi_layout_screen *iviscrn = NULL;
1178 1179 1180 1181
	struct ivi_layout_layer *ivilayer = NULL;
	int32_t length = 0;
	int32_t n = 0;

1182
	if (output == NULL || pLength == NULL || ppArray == NULL) {
1183 1184 1185 1186
		weston_log("ivi_layout_get_layers_on_screen: invalid argument\n");
		return IVI_FAILED;
	}

1187
	iviscrn = get_screen_from_output(output);
1188 1189
	length = wl_list_length(&iviscrn->order.layer_list);

Dawid Gajownik's avatar
Dawid Gajownik committed
1190
	if (length != 0) {
1191
		/* the Array must be freed by module which called this function */
1192 1193 1194 1195 1196 1197
		*ppArray = calloc(length, sizeof(struct ivi_layout_layer *));
		if (*ppArray == NULL) {
			weston_log("fails to allocate memory\n");
			return IVI_FAILED;
		}

1198
		wl_list_for_each(ivilayer, &iviscrn->order.layer_list, order.link) {
1199 1200 1201 1202 1203 1204 1205 1206 1207
			(*ppArray)[n++] = ivilayer;
		}
	}

	*pLength = length;

	return IVI_SUCCEEDED;
}

1208
static int32_t
1209 1210 1211 1212
ivi_layout_get_layers_under_surface(struct ivi_layout_surface *ivisurf,
				    int32_t *pLength,
				    struct ivi_layout_layer ***ppArray)
{
eucan's avatar
eucan committed
1213
	struct ivi_layout_view *ivi_view;
1214 1215 1216 1217 1218 1219 1220 1221
	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;
	}

eucan's avatar
eucan committed
1222 1223 1224 1225
	if (!wl_list_empty(&ivisurf->view_list)) {
		/* the Array must be free by module which called this function */
		length = wl_list_length(&ivisurf->view_list);
		*ppArray = calloc(length, sizeof(struct ivi_layout_layer *));
1226 1227 1228 1229 1230
		if (*ppArray == NULL) {
			weston_log("fails to allocate memory\n");
			return IVI_FAILED;
		}

eucan's avatar
eucan committed
1231 1232 1233 1234 1235 1236
		wl_list_for_each_reverse(ivi_view, &ivisurf->view_list, surf_link) {
			if (ivi_view_is_rendered(ivi_view))
				(*ppArray)[n++] = ivi_view->on_layer;
			else
				length--;
		}
1237 1238 1239 1240
	}

	*pLength = length;

eucan's avatar
eucan committed
1241 1242 1243 1244 1245
	if (!length) {
		free(*ppArray);
		*ppArray = NULL;
	}

1246 1247 1248
	return IVI_SUCCEEDED;
}

1249 1250
static
int32_t
1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264
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);

Dawid Gajownik's avatar
Dawid Gajownik committed
1265
	if (length != 0) {
1266
		/* the Array must be freed by module which called this function */
1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282
		*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;
}

1283
static int32_t
1284 1285 1286 1287
ivi_layout_get_surfaces_on_layer(struct ivi_layout_layer *ivilayer,
				 int32_t *pLength,
				 struct ivi_layout_surface ***ppArray)
{
eucan's avatar
eucan committed
1288
	struct ivi_layout_view *ivi_view = NULL;
1289 1290 1291 1292 1293 1294 1295 1296
	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;
	}

eucan's avatar
eucan committed
1297
	length = wl_list_length(&ivilayer->order.view_list);
1298 1299

	if (length != 0) {
1300
		/* the Array must be freed by module which called this function */
1301 1302 1303 1304 1305 1306
		*ppArray = calloc(length, sizeof(struct ivi_layout_surface *));
		if (*ppArray == NULL) {
			weston_log("fails to allocate memory\n");
			return IVI_FAILED;
		}

eucan's avatar
eucan committed
1307 1308
		wl_list_for_each(ivi_view, &ivilayer->order.view_list, order_link) {
			(*ppArray)[n++] = ivi_view->ivisurf;
1309 1310 1311 1312 1313 1314 1315 1316
		}
	}

	*pLength = length;

	return IVI_SUCCEEDED;
}

1317
static struct ivi_layout_layer *
1318 1319 1320 1321 1322 1323 1324 1325 1326
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");
1327
		++ivilayer->ref_count;
1328 1329 1330 1331 1332 1333 1334 1335 1336
		return ivilayer;
	}

	ivilayer = calloc(1, sizeof *ivilayer);
	if (ivilayer == NULL) {
		weston_log("fails to allocate memory\n");
		return NULL;
	}

1337
	ivilayer->ref_count = 1;
1338 1339 1340 1341 1342 1343
	wl_signal_init(&ivilayer->property_changed);
	ivilayer->layout = layout;
	ivilayer->id_layer = id_layer;

	init_layer_properties(&ivilayer->prop, width, height);

eucan's avatar
eucan committed
1344
	wl_list_init(&ivilayer->pending.view_list);
1345 1346 1347
	wl_list_init(&ivilayer->pending.link);
	ivilayer->pending.prop = ivilayer->prop;

eucan's avatar
eucan committed
1348
	wl_list_init(&ivilayer->order.view_list);
1349 1350 1351 1352 1353 1354 1355 1356 1357
	wl_list_init(&ivilayer->order.link);

	wl_list_insert(&layout->layer_list, &ivilayer->link);

	wl_signal_emit(&layout->layer_notification.created, ivilayer);

	return ivilayer;
}

1358
static void
1359
ivi_layout_layer_destroy(struct ivi_layout_layer *ivilayer)
1360 1361
{
	struct ivi_layout *layout = get_instance();
eucan's avatar
eucan committed
1362
	struct ivi_layout_view *ivi_view, *next;
1363 1364 1365 1366 1367 1368

	if (ivilayer == NULL) {
		weston_log("ivi_layout_layer_remove: invalid argument\n");
		return;
	}

1369 1370 1371
	if (--ivilayer->ref_count > 0)
		return;

eucan's avatar
eucan committed
1372 1373 1374 1375 1376
	/*Destroy all ivi_views*/
	wl_list_for_each_safe(ivi_view, next, &layout->view_list, link) {
		if (ivi_view->on_layer == ivilayer)
			ivi_view_destroy(ivi_view);
	}
1377

eucan's avatar
eucan committed
1378
	wl_signal_emit(&layout->layer_notification.removed, ivilayer);
1379

1380 1381 1382 1383
	wl_list_remove(&ivilayer->pending.link);
	wl_list_remove(&ivilayer->order.link);
	wl_list_remove(&ivilayer->link);

1384 1385 1386
	free(ivilayer);
}

1387
int32_t
1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400
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;

1401
	if (ivilayer->prop.visibility != newVisibility)
1402
		prop->event_mask |= IVI_NOTIFICATION_VISIBILITY;
1403
	else
1404
		prop->event_mask &= ~IVI_NOTIFICATION_VISIBILITY;
1405 1406 1407 1408

	return IVI_SUCCEEDED;
}

1409
int32_t
1410 1411 1412 1413 1414
ivi_layout_layer_set_opacity(struct ivi_layout_layer *ivilayer,
			     wl_fixed_t opacity)
{
	struct ivi_layout_layer_properties *prop = NULL;

1415 1416 1417
	if (ivilayer == NULL ||
	    opacity < wl_fixed_from_double(0.0) ||
	    wl_fixed_from_double(1.0) < opacity) {
1418 1419 1420 1421 1422 1423 1424
		weston_log("ivi_layout_layer_set_opacity: invalid argument\n");
		return IVI_FAILED;
	}

	prop = &ivilayer->pending.prop;
	prop->opacity = opacity;

1425
	if (ivilayer->prop.opacity != opacity)
1426
		prop->event_mask |= IVI_NOTIFICATION_OPACITY;