From: Seunghun Lee Date: Tue, 11 Oct 2022 09:29:20 +0000 (+0900) Subject: video: Add tizen_viewport implementation X-Git-Tag: accepted/tizen/unified/20230106.165108~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=d9fc2e8b50c6a339e02dd34e569c47b7d2571ac0;p=platform%2Fcore%2Fuifw%2Flibds-tizen.git video: Add tizen_viewport implementation Change-Id: I56840111bfa69fa4de99c8e12e45088712f6c6df --- diff --git a/include/libds-tizen/video.h b/include/libds-tizen/video.h index 0cbf5d7..7358fc8 100644 --- a/include/libds-tizen/video.h +++ b/include/libds-tizen/video.h @@ -12,12 +12,87 @@ struct ds_tizen_video; struct ds_tizen_video_object; +struct ds_tizen_viewport; + +enum ds_tizen_viewport_state_field { + DS_TIZEN_VIEWPORT_STATE_NONE = 0, + DS_TIZEN_VIEWPORT_STATE_TRANSFORM = (1 << 0), + DS_TIZEN_VIEWPORT_STATE_SOURCE = (1 << 1), + DS_TIZEN_VIEWPORT_STATE_DESTINATION = (1 << 2), + DS_TIZEN_VIEWPORT_STATE_FOLLOW_PARENT_TRANSFORM = (1 << 3), +}; + +enum ds_tizen_viewport_destination_type { + DS_TIZEN_VIEWPORT_DESTINATION_TYPE_NONE, + DS_TIZEN_VIEWPORT_DESTINATION_TYPE_RECT, + DS_TIZEN_VIEWPORT_DESTINATION_TYPE_RATIO, + DS_TIZEN_VIEWPORT_DESTINATION_TYPE_MODE, +}; + +enum ds_tizen_viewport_destination_mode_type { + DS_TIZEN_VIEWPORT_DESTINATION_MODE_TYPE_NONE, + DS_TIZEN_VIEWPORT_DESTINATION_MODE_TYPE_LETTER_BOX, + DS_TIZEN_VIEWPORT_DESTINATION_MODE_TYPE_ORIGIN, + DS_TIZEN_VIEWPORT_DESTINATION_MODE_TYPE_FULL, + DS_TIZEN_VIEWPORT_DESTINATION_MODE_TYPE_CROPPED_FULL, + DS_TIZEN_VIEWPORT_DESTINATION_MODE_TYPE_ORIGIN_OR_LETTER, +}; + +struct ds_tizen_viewport_state { + enum ds_tizen_viewport_state_field committed; + + struct { + uint32_t x, y, w, h; + } src; + + struct { + enum ds_tizen_viewport_destination_type type; + + struct { + int32_t x, y; + uint32_t w, h; + } rect; + + struct { + double x, y, w, h; + } ratio; + + struct { + enum ds_tizen_viewport_destination_mode_type type; + + struct { + double h, v; + } ratio; + + struct { + double h, v; + } scale; + + struct { + double h, v; + } align; + + struct { + int x, y, w, h; + } offset; + } mode; + } dst; + + uint32_t transform; + bool follow_parent_transform; +}; + struct ds_event_tizen_video_request_set_property { struct ds_tizen_video_object *object; const char *name; int32_t value; }; +struct ds_tizen_viewport_event_commit { + struct ds_tizen_viewport *viewport; + const struct ds_tizen_viewport_state *state; +}; + struct ds_tizen_video *ds_tizen_video_create(struct wl_display *display); void ds_tizen_video_add_format(struct ds_tizen_video *video, uint32_t format); @@ -35,6 +110,9 @@ void ds_tizen_video_add_destroy_listener(struct ds_tizen_video *video, void ds_tizen_video_add_new_object_listener(struct ds_tizen_video *video, struct wl_listener *listener); +void ds_tizen_video_add_new_viewport_listener(struct ds_tizen_video *video, + struct wl_listener *listener); + struct ds_surface *ds_tizen_video_object_get_surface( struct ds_tizen_video_object *object); @@ -57,6 +135,22 @@ void ds_tizen_video_object_add_request_attribute_allowed_listener( void ds_tizen_video_object_add_request_attribute_disallowed_listener( struct ds_tizen_video_object *object, struct wl_listener *listener); +struct ds_surface *ds_tizen_viewport_get_surface( + struct ds_tizen_viewport *viewport); + +void ds_tizen_viewport_add_destroy_listener(struct ds_tizen_viewport *viewport, + struct wl_listener *listener); + +/* @data: struct ds_tizen_viewport_event_commit */ +void ds_tizen_viewport_add_commit_listener(struct ds_tizen_viewport *viewport, + struct wl_listener *listener); + +void ds_tizen_viewport_add_query_parent_size_listener( + struct ds_tizen_viewport *viewport, struct wl_listener *listener); + +void ds_tizen_viewport_send_parent_size(struct ds_tizen_viewport *viewport, + uint32_t width, uint32_t height); + #ifdef __cplusplus } #endif diff --git a/src/video/meson.build b/src/video/meson.build index e091554..363926b 100644 --- a/src/video/meson.build +++ b/src/video/meson.build @@ -1,5 +1,6 @@ libds_tizen_video_files = [ 'video.c', + 'viewport.c', ] libds_tizen_video_deps = [ diff --git a/src/video/video-private.h b/src/video/video-private.h new file mode 100644 index 0000000..d399603 --- /dev/null +++ b/src/video/video-private.h @@ -0,0 +1,10 @@ +#ifndef DS_TIZEN_VIDEO_PRIVATE_H +#define DS_TIZEN_VIDEO_PRIVATE_H + +#include + +struct ds_tizen_viewport * +create_viewport(struct wl_client *client, struct wl_resource *resource, + uint32_t id, struct wl_resource *surface_resource); + +#endif diff --git a/src/video/video.c b/src/video/video.c index db8bd26..0a258f4 100644 --- a/src/video/video.c +++ b/src/video/video.c @@ -11,6 +11,7 @@ #include "libds-tizen/video.h" #include "shared/pixel_format.h" +#include "video-private.h" #define TIZEN_VIDEO_VERSION 1 @@ -32,6 +33,7 @@ struct ds_tizen_video struct { struct wl_signal destroy; struct wl_signal new_object; + struct wl_signal new_viewport; } events; }; @@ -103,6 +105,7 @@ ds_tizen_video_create(struct wl_display *display) wl_signal_init(&video->events.destroy); wl_signal_init(&video->events.new_object); + wl_signal_init(&video->events.new_viewport); video->display_destroy.notify = video_handle_display_destroy; wl_display_add_destroy_listener(display, &video->display_destroy); @@ -183,6 +186,13 @@ ds_tizen_video_add_new_object_listener(struct ds_tizen_video *video, wl_signal_add(&video->events.new_object, listener); } +WL_EXPORT void +ds_tizen_video_add_new_viewport_listener(struct ds_tizen_video *video, + struct wl_listener *listener) +{ + wl_signal_add(&video->events.new_viewport, listener); +} + WL_EXPORT struct ds_surface * ds_tizen_video_object_get_surface(struct ds_tizen_video_object *object) { @@ -294,7 +304,15 @@ video_handle_get_viewport(struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *surface_resource) { - // TODO + struct ds_tizen_video *video; + struct ds_tizen_viewport *viewport; + + viewport = create_viewport(client, resource, id, surface_resource); + if (!viewport) + return; + + video = wl_resource_get_user_data(resource); + wl_signal_emit(&video->events.new_viewport, viewport); } static void diff --git a/src/video/viewport.c b/src/video/viewport.c new file mode 100644 index 0000000..69b3cd7 --- /dev/null +++ b/src/video/viewport.c @@ -0,0 +1,606 @@ +#include +#include +#include + +#include +#include + +#include "libds-tizen/video.h" + +struct ds_tizen_viewport { + struct wl_resource *resource; + struct wl_resource *mode_resource; + struct ds_surface *surface; + struct ds_surface_viewport *surface_viewport; + + struct ds_tizen_viewport_state current, pending; + + struct wl_listener surface_destroy; + struct wl_listener surface_commit; + + struct { + struct wl_signal destroy; + struct wl_signal commit; + struct wl_signal query_parent_size; + } events; + + bool query_parent_size; +}; + +static const struct tizen_viewport_interface viewport_impl; +static const struct tizen_destination_mode_interface destination_mode_impl; + +static void viewport_handle_resource_destroy(struct wl_resource *resource); +static void viewport_handle_surface_destroy(struct wl_listener *listener, + void *data); +static void viewport_handle_surface_commit(struct wl_listener *listener, + void *data); +static void viewport_destroy(struct ds_tizen_viewport *viewport); +static void viewport_set_follow_parent_transform_pending( + struct ds_tizen_viewport *viewport, bool value); +static void destination_mode_resource_destroy(struct wl_resource *resource); +static enum ds_tizen_viewport_destination_mode_type +destination_mode_type_to_ds_enum(uint32_t type); + +WL_EXPORT struct ds_surface * +ds_tizen_viewport_get_surface(struct ds_tizen_viewport *viewport) +{ + return viewport->surface; +} + +WL_EXPORT void +ds_tizen_viewport_add_destroy_listener(struct ds_tizen_viewport *viewport, + struct wl_listener *listener) +{ + wl_signal_add(&viewport->events.destroy, listener); +} + +WL_EXPORT void +ds_tizen_viewport_add_commit_listener(struct ds_tizen_viewport *viewport, + struct wl_listener *listener) +{ + wl_signal_add(&viewport->events.commit, listener); +} + +WL_EXPORT void +ds_tizen_viewport_add_query_parent_size_listener( + struct ds_tizen_viewport *viewport, struct wl_listener *listener) +{ + wl_signal_add(&viewport->events.query_parent_size, listener); +} + +WL_EXPORT void +ds_tizen_viewport_send_parent_size(struct ds_tizen_viewport *viewport, + uint32_t width, uint32_t height) +{ + if (!viewport->query_parent_size) + return; + + tizen_viewport_send_parent_size(viewport->resource, width, height); +} + +struct ds_tizen_viewport * +create_viewport(struct wl_client *client, struct wl_resource *resource, + uint32_t id, struct wl_resource *surface_resource) +{ + struct ds_tizen_viewport *viewport; + struct ds_surface *surface; + struct ds_surface_viewport *surface_viewport; + + surface = ds_surface_from_resource(resource); + surface_viewport = ds_surface_take_viewport(surface); + if (!surface_viewport) { + wl_resource_post_error(resource, TIZEN_VIDEO_ERROR_VIEWPORT_EXISTS, + "a viewport for that surface already exists"); + return NULL; + } + + viewport = calloc(1, sizeof *viewport); + if (!viewport) + goto err_alloc; + + viewport->resource = wl_resource_create(client, &tizen_viewport_interface, + wl_resource_get_version(resource), id); + if (!viewport->resource) + goto err_resource; + + wl_resource_set_implementation(viewport->resource, &viewport_impl, + viewport, viewport_handle_resource_destroy); + + wl_signal_init(&viewport->events.commit); + wl_signal_init(&viewport->events.query_parent_size); + + viewport->surface_viewport = surface_viewport; + + viewport->surface_destroy.notify = viewport_handle_surface_destroy; + ds_surface_add_destroy_listener(surface, &viewport->surface_destroy); + + viewport->surface_commit.notify = viewport_handle_surface_commit; + ds_surface_add_commit_listener(surface, &viewport->surface_commit); + + return viewport; + +err_resource: + free(viewport); +err_alloc: + ds_surface_viewport_release(surface_viewport); + wl_resource_post_no_memory(resource); + + return NULL; +} + +static void +viewport_handle_destroy(struct wl_client *client, struct wl_resource *resource) +{ + wl_resource_destroy(resource); +} + +static void +viewport_handle_set_transform(struct wl_client *client, + struct wl_resource *resource, uint32_t transform) +{ + struct ds_tizen_viewport *viewport; + + if (transform > WL_OUTPUT_TRANSFORM_FLIPPED_270) { + ds_err("Invalid param: transform(%d)", transform); + return; + } + + viewport = wl_resource_get_user_data(resource); + if (viewport->pending.transform == transform) + return; + + viewport->pending.transform = transform; + viewport->pending.committed |= DS_TIZEN_VIEWPORT_STATE_TRANSFORM; +} + +static void +viewport_handle_set_source(struct wl_client *client, + struct wl_resource *resource, + uint32_t x, uint32_t y, uint32_t width, uint32_t height) +{ + struct ds_tizen_viewport *viewport; + + viewport = wl_resource_get_user_data(resource); + if (viewport->pending.src.x == x && + viewport->pending.src.y == y && + viewport->pending.src.w == width && + viewport->pending.src.h == height) { + return; + } + + viewport->pending.src.x = x; + viewport->pending.src.y = y; + viewport->pending.src.w = width; + viewport->pending.src.h = height; + viewport->pending.committed |= DS_TIZEN_VIEWPORT_STATE_SOURCE; +} + +static void +viewport_handle_set_destination(struct wl_client *client, + struct wl_resource *resource, + int32_t x, int32_t y, uint32_t width, uint32_t height) +{ + struct ds_tizen_viewport *viewport; + + if (width == 0 || height == 0) { + ds_err("Invalid param: destination.rect(%d,%d %dx%d)", + x, y, width, height); + return; + } + + viewport = wl_resource_get_user_data(resource); + if (viewport->pending.dst.type == DS_TIZEN_VIEWPORT_DESTINATION_TYPE_RECT && + viewport->pending.dst.rect.x == x && + viewport->pending.dst.rect.y == y && + viewport->pending.dst.rect.w == width && + viewport->pending.dst.rect.h == height) { + return; + } + + viewport->pending.dst.rect.x = x; + viewport->pending.dst.rect.y = y; + viewport->pending.dst.rect.w = width; + viewport->pending.dst.rect.h = height; + viewport->pending.dst.type = DS_TIZEN_VIEWPORT_DESTINATION_TYPE_RECT; + viewport->pending.committed |= DS_TIZEN_VIEWPORT_STATE_DESTINATION; +} + +static void +viewport_handle_set_destination_ratio(struct wl_client *client, + struct wl_resource *resource, + wl_fixed_t x, wl_fixed_t y, wl_fixed_t width, wl_fixed_t height) +{ + struct ds_tizen_viewport *viewport; + double ratio_x, ratio_y, ratio_w, ratio_h; + + viewport = wl_resource_get_user_data(resource); + if (viewport->pending.dst.type == DS_TIZEN_VIEWPORT_DESTINATION_TYPE_MODE) { + ds_err("Couldn't set viewport destination ratio. " + "tizen_viewport@%d has the mode", + wl_resource_get_id(resource)); + return; + } + + ratio_x = wl_fixed_to_double(x); + ratio_y = wl_fixed_to_double(y); + ratio_w = wl_fixed_to_double(width); + ratio_h = wl_fixed_to_double(height); + if (ratio_x < 0.0 || ratio_x >= 1.0 || + ratio_y < 0.0 || ratio_y >= 1.0 || + ratio_w <= 0.0 || ratio_h <= 0.0) { + ds_err("Invalid param: destination.ratio(%.2f,%.2f %.2fx%.2f)", + ratio_x, ratio_y, ratio_w, ratio_h); + return; + } + + if (viewport->pending.dst.type == DS_TIZEN_VIEWPORT_DESTINATION_TYPE_RATIO && + viewport->pending.dst.ratio.x == ratio_x && + viewport->pending.dst.ratio.y == ratio_y && + viewport->pending.dst.ratio.w == ratio_w && + viewport->pending.dst.ratio.h == ratio_h) { + return; + } + + viewport->pending.dst.ratio.x = ratio_x; + viewport->pending.dst.ratio.y = ratio_y; + viewport->pending.dst.ratio.w = ratio_w; + viewport->pending.dst.ratio.h = ratio_h; + viewport->pending.dst.type = DS_TIZEN_VIEWPORT_DESTINATION_TYPE_RATIO; + viewport->pending.committed |= DS_TIZEN_VIEWPORT_STATE_DESTINATION; +} + +static void +viewport_handle_get_destination_mode(struct wl_client *client, + struct wl_resource *resource, uint32_t id) +{ + struct ds_tizen_viewport *viewport; + + viewport = wl_resource_get_user_data(resource); + if (viewport->mode_resource) { + ds_err("Destination mode resource already exists."); + /* WORKAROUND + * Since there is no error protocol for this case, + * it calls wl_resource_post_no_memory() instead. */ + wl_resource_post_no_memory(resource); + return; + } + + viewport->mode_resource = wl_resource_create(client, + &tizen_destination_mode_interface, + wl_resource_get_version(resource), id); + if (!viewport->mode_resource) { + wl_resource_post_no_memory(resource); + return; + } + wl_resource_set_implementation(viewport->mode_resource, + &destination_mode_impl, viewport, + destination_mode_resource_destroy); + + viewport->pending.dst.mode.type = DS_TIZEN_VIEWPORT_DESTINATION_MODE_TYPE_NONE; + viewport->pending.dst.mode.ratio.h = -1.0; + viewport->pending.dst.mode.scale.h = -1.0; + viewport->pending.dst.mode.align.h = -1.0; +} + +static void +viewport_handle_query_parent_size(struct wl_client *client, + struct wl_resource *resource) +{ + struct ds_tizen_viewport *viewport; + + viewport = wl_resource_get_user_data(resource); + viewport->query_parent_size = true; + wl_signal_emit(&viewport->events.query_parent_size, viewport); +} + +static void +viewport_handle_follow_parent_transform(struct wl_client *client, + struct wl_resource *resource) +{ + struct ds_tizen_viewport *viewport; + + viewport = wl_resource_get_user_data(resource); + viewport_set_follow_parent_transform_pending(viewport, true); +} + +static void +viewport_handle_unfollow_parent_transform(struct wl_client *client, + struct wl_resource *resource) +{ + struct ds_tizen_viewport *viewport; + + viewport = wl_resource_get_user_data(resource); + viewport_set_follow_parent_transform_pending(viewport, false); +} + +static const struct tizen_viewport_interface viewport_impl = { + .destroy = viewport_handle_destroy, + .set_transform = viewport_handle_set_transform, + .set_source = viewport_handle_set_source, + .set_destination = viewport_handle_set_destination, + .set_destination_ratio = viewport_handle_set_destination_ratio, + .get_destination_mode = viewport_handle_get_destination_mode, + .query_parent_size = viewport_handle_query_parent_size, + .follow_parent_transform = viewport_handle_follow_parent_transform, + .unfollow_parent_transform = viewport_handle_unfollow_parent_transform, +}; + +static void +viewport_handle_resource_destroy(struct wl_resource *resource) +{ + struct ds_tizen_viewport *viewport; + + viewport = wl_resource_get_user_data(resource); + if (viewport) + viewport_destroy(viewport); +} + +static void +viewport_handle_surface_destroy(struct wl_listener *listener, void *data) +{ + struct ds_tizen_viewport *viewport; + + viewport = wl_container_of(listener, viewport, surface_destroy); + viewport_destroy(viewport); +} + +static void +viewport_handle_surface_commit(struct wl_listener *listener, void *data) +{ + struct ds_tizen_viewport *viewport; + + viewport = wl_container_of(listener, viewport, surface_commit); + if (viewport->pending.committed == DS_TIZEN_VIEWPORT_STATE_NONE) + return; + + viewport->current = viewport->pending; + viewport->pending.committed = DS_TIZEN_VIEWPORT_STATE_NONE; + + wl_signal_emit(&viewport->events.commit, &viewport->current); +} + +static void +viewport_destroy(struct ds_tizen_viewport *viewport) +{ + wl_signal_emit(&viewport->events.destroy, viewport); + + ds_surface_viewport_release(viewport->surface_viewport); + + wl_resource_set_user_data(viewport->resource, NULL); + wl_list_remove(&viewport->surface_commit.link); + wl_list_remove(&viewport->surface_destroy.link); + free(viewport); +} + +static void +viewport_set_follow_parent_transform_pending(struct ds_tizen_viewport *viewport, + bool value) +{ + viewport->pending.follow_parent_transform = value; + viewport->pending.committed |= + DS_TIZEN_VIEWPORT_STATE_FOLLOW_PARENT_TRANSFORM; +} + +static void +destination_mode_handle_destroy(struct wl_client *client, + struct wl_resource *resource) +{ + wl_resource_destroy(resource); +} + +static void +destination_mode_handle_follow_parent_transform(struct wl_client *client, + struct wl_resource *resource) +{ + struct ds_tizen_viewport *viewport; + + viewport = wl_resource_get_user_data(resource); + viewport_set_follow_parent_transform_pending(viewport, true); +} + +static void +destination_mode_handle_unfollow_parent_transform(struct wl_client *client, + struct wl_resource *resource) +{ + struct ds_tizen_viewport *viewport; + + viewport = wl_resource_get_user_data(resource); + viewport_set_follow_parent_transform_pending(viewport, false); +} + +static void +destination_mode_handle_set(struct wl_client *client, + struct wl_resource *resource, uint32_t type) +{ + struct ds_tizen_viewport *viewport; + enum ds_tizen_viewport_destination_mode_type mode_type; + + if (type > TIZEN_DESTINATION_MODE_TYPE_ORIGIN_OR_LETTER) { + ds_err("Invalid param: type(%d)", type); + return; + } + + mode_type = destination_mode_type_to_ds_enum(type); + viewport = wl_resource_get_user_data(resource); + if (viewport->pending.dst.type == DS_TIZEN_VIEWPORT_DESTINATION_TYPE_MODE && + viewport->pending.dst.mode.type == mode_type) { + return; + } + + viewport->pending.dst.mode.type = mode_type; + viewport->pending.dst.type = DS_TIZEN_VIEWPORT_DESTINATION_TYPE_MODE; +} + +static void +destination_mode_handle_set_ratio(struct wl_client *client, + struct wl_resource *resource, + wl_fixed_t horizontal, wl_fixed_t vertical) +{ + struct ds_tizen_viewport *viewport; + double ratio_h, ratio_v; + + viewport = wl_resource_get_user_data(resource); + + ratio_h = wl_fixed_to_double(horizontal); + ratio_v = wl_fixed_to_double(vertical); + if (ratio_h <= 0.0 || ratio_v <= 0.0) { + if (ratio_h == -1.0) { + viewport->pending.dst.mode.ratio.h = ratio_h; + viewport->pending.committed |= DS_TIZEN_VIEWPORT_STATE_DESTINATION; + } + else { + ds_err("Invalid param: ratio_h(%.2f) ratio_v(%.2f)", + ratio_h, ratio_v); + } + + return; + } + + if (viewport->pending.dst.mode.ratio.h == ratio_h && + viewport->pending.dst.mode.ratio.v == ratio_v) + return; + + viewport->pending.dst.mode.ratio.h = ratio_h; + viewport->pending.dst.mode.ratio.v = ratio_v; + viewport->pending.committed |= DS_TIZEN_VIEWPORT_STATE_DESTINATION; +} + +static void +destination_mode_handle_set_scale(struct wl_client *client, + struct wl_resource *resource, + wl_fixed_t horizontal, wl_fixed_t vertical) +{ + struct ds_tizen_viewport *viewport; + double scale_h, scale_v; + + viewport = wl_resource_get_user_data(resource); + + scale_h = wl_fixed_to_double(horizontal); + scale_v = wl_fixed_to_double(vertical); + if (scale_h <= 0 || scale_v <= 0) { + if (scale_h == -1.0) { + viewport->pending.dst.mode.scale.h = scale_h; + viewport->pending.committed = DS_TIZEN_VIEWPORT_STATE_DESTINATION; + } + else { + ds_err("Invalid param: scale_h(%.2f) scale_v(%.2f)", + scale_h, scale_v); + } + + return; + } + + if (viewport->pending.dst.mode.scale.h == scale_h && + viewport->pending.dst.mode.scale.v == scale_v) + return; + + viewport->pending.dst.mode.scale.h = scale_h; + viewport->pending.dst.mode.scale.v = scale_v; + viewport->pending.committed = DS_TIZEN_VIEWPORT_STATE_DESTINATION; +} + +static void +destination_mode_handle_set_align(struct wl_client *client, + struct wl_resource *resource, + wl_fixed_t horizontal, wl_fixed_t vertical) +{ + struct ds_tizen_viewport *viewport; + double align_h, align_v; + + viewport = wl_resource_get_user_data(resource); + + align_h = wl_fixed_to_double(horizontal); + align_v = wl_fixed_to_double(vertical); + if (align_h == -1.0) { + viewport->pending.dst.mode.align.h = align_h; + viewport->pending.committed = DS_TIZEN_VIEWPORT_STATE_DESTINATION; + return; + } + + if (align_h < 0.0) + align_h = 0.0; + else if (align_h > 1.0) + align_h = 1.0; + + if (align_v < 0.0) + align_v = 0.0; + else if (align_v > 1.0) + align_v = 1.0; + + if (viewport->pending.dst.mode.align.h == align_h && + viewport->pending.dst.mode.align.v == align_v) + return; + + viewport->pending.dst.mode.align.h = align_h; + viewport->pending.dst.mode.align.v = align_v; + viewport->pending.committed = DS_TIZEN_VIEWPORT_STATE_DESTINATION; +} + +static void +destination_mode_handle_set_offset(struct wl_client *client, + struct wl_resource *resource, + int32_t x, int32_t y, int32_t w, int32_t h) +{ + struct ds_tizen_viewport *viewport; + + viewport = wl_resource_get_user_data(resource); + + if (viewport->pending.dst.mode.offset.x == x && + viewport->pending.dst.mode.offset.y == y && + viewport->pending.dst.mode.offset.w == w && + viewport->pending.dst.mode.offset.h == h) + return; + + viewport->pending.dst.mode.offset.x = x; + viewport->pending.dst.mode.offset.y = y; + viewport->pending.dst.mode.offset.w = w; + viewport->pending.dst.mode.offset.h = h; + viewport->pending.committed = DS_TIZEN_VIEWPORT_STATE_DESTINATION; +} + +static const struct tizen_destination_mode_interface destination_mode_impl = { + .destroy = destination_mode_handle_destroy, + .follow_parent_transform = destination_mode_handle_follow_parent_transform, + .unfollow_parent_transform = + destination_mode_handle_unfollow_parent_transform, + .set = destination_mode_handle_set, + .set_ratio = destination_mode_handle_set_ratio, + .set_scale = destination_mode_handle_set_scale, + .set_align = destination_mode_handle_set_align, + .set_offset = destination_mode_handle_set_offset, +}; + +static void destination_mode_resource_destroy(struct wl_resource *resource) +{ + struct ds_tizen_viewport *viewport; + + viewport = wl_resource_get_user_data(resource); + viewport->mode_resource = NULL; + + if (viewport->pending.dst.type == DS_TIZEN_VIEWPORT_DESTINATION_TYPE_MODE) { + viewport->pending.dst.type = DS_TIZEN_VIEWPORT_DESTINATION_TYPE_NONE; + viewport->pending.committed |= DS_TIZEN_VIEWPORT_STATE_DESTINATION; + } +} + +static enum ds_tizen_viewport_destination_mode_type +destination_mode_type_to_ds_enum(uint32_t type) +{ + switch (type) { + case TIZEN_DESTINATION_MODE_TYPE_NONE: + return DS_TIZEN_VIEWPORT_DESTINATION_MODE_TYPE_NONE; + case TIZEN_DESTINATION_MODE_TYPE_LETTER_BOX: + return DS_TIZEN_VIEWPORT_DESTINATION_MODE_TYPE_LETTER_BOX; + case TIZEN_DESTINATION_MODE_TYPE_ORIGIN: + return DS_TIZEN_VIEWPORT_DESTINATION_MODE_TYPE_ORIGIN; + case TIZEN_DESTINATION_MODE_TYPE_FULL: + return DS_TIZEN_VIEWPORT_DESTINATION_MODE_TYPE_FULL; + case TIZEN_DESTINATION_MODE_TYPE_CROPPED_FULL: + return DS_TIZEN_VIEWPORT_DESTINATION_MODE_TYPE_CROPPED_FULL; + case TIZEN_DESTINATION_MODE_TYPE_ORIGIN_OR_LETTER: + return DS_TIZEN_VIEWPORT_DESTINATION_MODE_TYPE_ORIGIN_OR_LETTER; + default: + assert(0 && "cannot reach here"); + } +}