From: Seunghun Lee Date: Thu, 7 Nov 2019 07:47:47 +0000 (+0900) Subject: e_comp_wl: Added an API to get buffer/output viewport and transform of E_Client. X-Git-Tag: submit/tizen/20191112.105927~4 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F83%2F217383%2F7;p=platform%2Fupstream%2Fenlightenment.git e_comp_wl: Added an API to get buffer/output viewport and transform of E_Client. Change-Id: I72e21d5052030ff92453fba231d4f5a432eca76f --- diff --git a/src/bin/e_comp_wl.c b/src/bin/e_comp_wl.c index a14d5a5f5c..b72482c4f4 100644 --- a/src/bin/e_comp_wl.c +++ b/src/bin/e_comp_wl.c @@ -5739,3 +5739,277 @@ e_comp_wl_surface_state_buffer_set(E_Comp_Wl_Surface_State *state, E_Comp_Wl_Buf { _e_comp_wl_surface_state_buffer_set(state, buffer); } + +static void +buffer_transform(int width, int height, uint32_t transform, int32_t scale, + int sx, int sy, int *dx, int *dy) +{ + switch (transform) + { + case WL_OUTPUT_TRANSFORM_NORMAL: + default: + *dx = sx, *dy = sy; + break; + case WL_OUTPUT_TRANSFORM_FLIPPED: + *dx = width - sx, *dy = sy; + break; + case WL_OUTPUT_TRANSFORM_90: + *dx = height - sy, *dy = sx; + break; + case WL_OUTPUT_TRANSFORM_FLIPPED_90: + *dx = height - sy, *dy = width - sx; + break; + case WL_OUTPUT_TRANSFORM_180: + *dx = width - sx, *dy = height - sy; + break; + case WL_OUTPUT_TRANSFORM_FLIPPED_180: + *dx = sx, *dy = height - sy; + break; + case WL_OUTPUT_TRANSFORM_270: + *dx = sy, *dy = width - sx; + break; + case WL_OUTPUT_TRANSFORM_FLIPPED_270: + *dx = sy, *dy = sx; + break; + } + + *dx *= scale; + *dy *= scale; +} + +static void +_buffer_viewport_get(E_Comp_Wl_Buffer_Viewport *vp, int bw, int bh, Eina_Rectangle *out) +{ + int x1, y1, x2, y2; + int tx1, ty1, tx2, ty2; + int width_from_buffer, height_from_buffer; + + switch (vp->buffer.transform) + { + case WL_OUTPUT_TRANSFORM_90: + case WL_OUTPUT_TRANSFORM_270: + case WL_OUTPUT_TRANSFORM_FLIPPED_90: + case WL_OUTPUT_TRANSFORM_FLIPPED_270: + width_from_buffer = bh / vp->buffer.scale; + height_from_buffer = bw / vp->buffer.scale; + break; + default: + width_from_buffer = bw / vp->buffer.scale; + height_from_buffer = bh / vp->buffer.scale; + break; + } + + if (vp->buffer.src_width == wl_fixed_from_int(-1)) + { + x1 = 0.0; + y1 = 0.0; + x2 = width_from_buffer; + y2 = height_from_buffer; + } + else + { + x1 = wl_fixed_to_int(vp->buffer.src_x); + y1 = wl_fixed_to_int(vp->buffer.src_y); + x2 = wl_fixed_to_int(vp->buffer.src_x + vp->buffer.src_width); + y2 = wl_fixed_to_int(vp->buffer.src_y + vp->buffer.src_height); + } + + buffer_transform(width_from_buffer, height_from_buffer, + vp->buffer.transform, vp->buffer.scale, x1, y1, &tx1, &ty1); + buffer_transform(width_from_buffer, height_from_buffer, + vp->buffer.transform, vp->buffer.scale, x2, y2, &tx2, &ty2); + + out->x = (tx1 <= tx2) ? tx1 : tx2; + out->y = (ty1 <= ty2) ? ty1 : ty2; + out->w = (tx1 <= tx2) ? tx2 - tx1 : tx1 - tx2; + out->h = (ty1 <= ty2) ? ty2 - ty1 : ty1 - ty2; +} + +/** + * Convert given four coordinates to elements of rectangle + * @in p[4] Coordinates to be converted + * @out rect x, y, width, and height + * transform Angle which represents TDM_TRANSFORM of rectangle + * @return EINA_FALSE in following case, otherwise EINA_TRUE. + * 1. The given coordinates are not represented by rectangle. + * 2. All angles except for 0, 90, 180, 270. + */ +static Eina_Bool +_coords_to_rectangle_convert(Evas_Point p[4], Eina_Rectangle *rect, uint *rotation) +{ + Eina_Bool ret = EINA_FALSE; + + if ((p[0].y == p[1].y) && (p[1].x == p[2].x) && (p[2].y == p[3].y) && (p[3].x == p[0].x)) + { + /* 0 or 180 */ + if ((p[0].x < p[2].x) && (p[0].y < p[2].y)) + { + if (rotation) + *rotation = TDM_TRANSFORM_NORMAL; + + if (rect) + EINA_RECTANGLE_SET(rect, p[0].x, p[0].y, p[2].x - p[0].x, p[2].y - p[0].y); + + ret = EINA_TRUE; + } + else if ((p[0].x > p[2].x) && (p[0].y > p[2].y)) + { + if (rotation) + *rotation = TDM_TRANSFORM_180; + + if (rect) + EINA_RECTANGLE_SET(rect, p[2].x, p[2].y, p[0].x - p[2].x, p[0].y - p[2].y); + + ret = EINA_TRUE; + } + } + else if ((p[0].x == p[1].x) && (p[1].y == p[2].y) && (p[2].x == p[3].x) && (p[3].y == p[0].y)) + { + /* 90 or 270 */ + if ((p[0].x > p[2].x) && (p[0].y < p[2].y)) + { + if (rotation) + *rotation = TDM_TRANSFORM_90; + + if (rect) + EINA_RECTANGLE_SET(rect, p[2].x, p[0].y, p[0].x - p[2].x, p[2].y - p[0].y); + + ret = EINA_TRUE; + } + else if ((p[0].x < p[2].x) && (p[0].y > p[2].y)) + { + if (rotation) + *rotation = TDM_TRANSFORM_270; + + if (rect) + EINA_RECTANGLE_SET(rect, p[0].x, p[2].y, p[2].x - p[0].x, p[0].y - p[2].y); + + ret = EINA_TRUE; + } + } + + return ret; +} + +static Eina_Bool +_output_viewport_get_from_evas_map(const Evas_Map *m, Eina_Rectangle *out, unsigned int *rotation) +{ + Evas_Point p[4]; + int i; + + for (i = 0; i < 4; i++) + evas_map_point_coord_get(m, i, &p[i].x, &p[i].y, NULL); + + if (!_coords_to_rectangle_convert(p, out, rotation)) + { + DBG("Cannot convert given coords to rectangle.\n" + "p1(%d %d) p2(%d %d) p3(%d %d) p4(%d %d)", + p[0].x, p[0].y, p[1].x, p[1].y, + p[2].x, p[2].y, p[3].x, p[3].y); + return EINA_FALSE; + } + + return EINA_TRUE; +} + +static unsigned int +_transform_merge_with_rotation(enum wl_output_transform transform, unsigned int rotation) +{ + int trans_rotation, flip; + + trans_rotation = transform & 0x3; + flip = transform & 0x4; + + return (flip + (trans_rotation + rotation) % 4); +} + +static void +_e_comp_wl_surface_output_viewport_get(E_Client *ec, Eina_Rectangle *out) +{ + E_Comp_Wl_Subsurf_Data *sdata = NULL; + + if (!out) + return; + + if (!ec->comp_data) + return; + + sdata = ec->comp_data->sub.data; + if (sdata) + { + if (sdata->parent) + { + out->x = sdata->parent->x + sdata->position.x; + out->y = sdata->parent->y + sdata->position.y; + } + else + { + out->x = sdata->position.x; + out->y = sdata->position.y; + } + } + else + { + out->x = ec->x; + out->y = ec->y; + } + + out->w = ec->comp_data->width_from_viewport; + out->w = (out->w + 1) & ~1; + out->h = ec->comp_data->height_from_viewport; + + e_comp_object_frame_xy_unadjust(ec->frame, out->x, out->y, &out->x, &out->y); + e_comp_object_frame_wh_unadjust(ec->frame, out->w, out->h, &out->w, &out->h); +} + +EINTERN Eina_Bool +e_comp_wl_surface_viewport_get(E_Client *ec, Eina_Rectangle *buffer_viewport, Eina_Rectangle *output_viewport, unsigned int *transform) +{ + E_Comp_Wl_Buffer *buffer; + E_Comp_Wl_Buffer_Viewport *vp; + const Evas_Map *m; + enum wl_output_transform buffer_transform; + unsigned int rotation; + Eina_Bool res = EINA_FALSE; + + EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE); + + if (e_object_is_del(E_OBJECT(ec))) + return EINA_FALSE; + + vp = &ec->comp_data->scaler.buffer_viewport; + + if (buffer_viewport) + { + buffer = ec->comp_data->buffer_ref.buffer; + /* Getting a viewport of buffer needs geometry of buffer. */ + if (!buffer) + return EINA_FALSE; + + _buffer_viewport_get(vp, buffer->w, buffer->h, buffer_viewport); + } + + if ((output_viewport) || (transform)) + { + m = evas_object_map_get(ec->frame); + if (m) + res = _output_viewport_get_from_evas_map(m, output_viewport, &rotation); + else + _e_comp_wl_surface_output_viewport_get(ec, output_viewport); + + if (transform) + { + buffer_transform = e_comp_wl_output_buffer_transform_get(ec); + /* NOTE Merge transform value from evas_map with E_Comp_Wl_Buffer_Viewport's one. + * Since buffer.transform isn't applied using evas_map, + * it has to be taken into account here to apply buffer.transform + * and rotation of e_client_transform together. */ + if (res) + *transform = _transform_merge_with_rotation(buffer_transform, rotation); + else + *transform = (unsigned int)buffer_transform; + } + } + + return EINA_TRUE; +} diff --git a/src/bin/e_comp_wl.h b/src/bin/e_comp_wl.h index 75afbcebfc..882e177058 100644 --- a/src/bin/e_comp_wl.h +++ b/src/bin/e_comp_wl.h @@ -611,5 +611,6 @@ EINTERN void e_comp_wl_hook_call(E_Comp_Wl_Hook_Point hookpoint, E_Client *ec EINTERN void e_comp_wl_surface_state_finish(E_Comp_Wl_Surface_State *state); EINTERN void e_comp_wl_surface_state_buffer_set(E_Comp_Wl_Surface_State *state, E_Comp_Wl_Buffer *buffer); +EINTERN Eina_Bool e_comp_wl_surface_viewport_get(E_Client *ec, Eina_Rectangle *buffer_viewport, Eina_Rectangle *output_viewport, unsigned int *transform); # endif #endif