diff options
author | Tobias Jakobi <tjakobi@math.uni-bielefeld.de> | 2015-11-30 12:12:19 +0900 |
---|---|---|
committer | Emil Velikov <emil.l.velikov@gmail.com> | 2015-12-18 17:42:54 +0000 |
commit | 676462c43e97896caa891b1e0aeb27d5d4f13637 (patch) | |
tree | 4ebc62fa3aa07d3b6566d963e2adc71f8d5a7d75 | |
parent | 51fd93bc38a33df33f7bf6cbf1ae3fbf74a47dba (diff) |
exynos/fimg2d: add g2d_move
We already have g2d_copy() which implements G2D copy
operations from one buffer to another. However we can't
do a overlapping copy operation in one buffer.
Add g2d_move() which acts like the standard memmove()
and properly handles overlapping copies.
Signed-off-by: Tobias Jakobi <tjakobi@math.uni-bielefeld.de>
-rw-r--r-- | exynos/exynos_fimg2d.c | 95 | ||||
-rw-r--r-- | exynos/exynos_fimg2d.h | 3 |
2 files changed, 98 insertions, 0 deletions
diff --git a/exynos/exynos_fimg2d.c b/exynos/exynos_fimg2d.c index 3bef93b0..7f1d105a 100644 --- a/exynos/exynos_fimg2d.c +++ b/exynos/exynos_fimg2d.c @@ -567,6 +567,101 @@ g2d_copy(struct g2d_context *ctx, struct g2d_image *src, } /** + * g2d_move - copy content inside single buffer. + * Similar to libc's memmove() this copies a rectangular + * region of the provided buffer to another location, while + * properly handling the situation where source and + * destination rectangle overlap. + * + * @ctx: a pointer to g2d_context structure. + * @img: a pointer to g2d_image structure providing + * buffer information. + * @src_x: x position of source rectangle. + * @src_y: y position of source rectangle. + * @dst_x: x position of destination rectangle. + * @dst_y: y position of destination rectangle. + * @w: width of rectangle to move. + * @h: height of rectangle to move. + */ +int +g2d_move(struct g2d_context *ctx, struct g2d_image *img, + unsigned int src_x, unsigned int src_y, + unsigned int dst_x, unsigned dst_y, unsigned int w, + unsigned int h) +{ + union g2d_rop4_val rop4; + union g2d_point_val pt; + union g2d_direction_val dir; + unsigned int src_w, src_h, dst_w, dst_h; + + src_w = w; + src_h = h; + if (src_x + img->width > w) + src_w = img->width - src_x; + if (src_y + img->height > h) + src_h = img->height - src_y; + + dst_w = w; + dst_h = w; + if (dst_x + img->width > w) + dst_w = img->width - dst_x; + if (dst_y + img->height > h) + dst_h = img->height - dst_y; + + w = MIN(src_w, dst_w); + h = MIN(src_h, dst_h); + + if (w == 0 || h == 0) { + fprintf(stderr, MSG_PREFIX "invalid width or height.\n"); + return -EINVAL; + } + + if (g2d_check_space(ctx, 13, 2)) + return -ENOSPC; + + g2d_add_cmd(ctx, DST_SELECT_REG, G2D_SELECT_MODE_BGCOLOR); + g2d_add_cmd(ctx, SRC_SELECT_REG, G2D_SELECT_MODE_NORMAL); + + g2d_add_cmd(ctx, DST_COLOR_MODE_REG, img->color_mode); + g2d_add_cmd(ctx, SRC_COLOR_MODE_REG, img->color_mode); + + g2d_add_base_addr(ctx, img, g2d_dst); + g2d_add_base_addr(ctx, img, g2d_src); + + g2d_add_cmd(ctx, DST_STRIDE_REG, img->stride); + g2d_add_cmd(ctx, SRC_STRIDE_REG, img->stride); + + dir.val[0] = dir.val[1] = 0; + + if (dst_x >= src_x) + dir.data.src_x_direction = dir.data.dst_x_direction = 1; + if (dst_y >= src_y) + dir.data.src_y_direction = dir.data.dst_y_direction = 1; + + g2d_set_direction(ctx, &dir); + + pt.data.x = src_x; + pt.data.y = src_y; + g2d_add_cmd(ctx, SRC_LEFT_TOP_REG, pt.val); + pt.data.x = src_x + w; + pt.data.y = src_y + h; + g2d_add_cmd(ctx, SRC_RIGHT_BOTTOM_REG, pt.val); + + pt.data.x = dst_x; + pt.data.y = dst_y; + g2d_add_cmd(ctx, DST_LEFT_TOP_REG, pt.val); + pt.data.x = dst_x + w; + pt.data.y = dst_y + h; + g2d_add_cmd(ctx, DST_RIGHT_BOTTOM_REG, pt.val); + + rop4.val = 0; + rop4.data.unmasked_rop3 = G2D_ROP3_SRC; + g2d_add_cmd(ctx, ROP4_REG, rop4.val); + + return g2d_flush(ctx); +} + +/** * g2d_copy_with_scale - copy contents in source buffer to destination buffer * scaling up or down properly. * diff --git a/exynos/exynos_fimg2d.h b/exynos/exynos_fimg2d.h index a2c22da7..a825c683 100644 --- a/exynos/exynos_fimg2d.h +++ b/exynos/exynos_fimg2d.h @@ -299,6 +299,9 @@ int g2d_copy(struct g2d_context *ctx, struct g2d_image *src, struct g2d_image *dst, unsigned int src_x, unsigned int src_y, unsigned int dst_x, unsigned int dst_y, unsigned int w, unsigned int h); +int g2d_move(struct g2d_context *ctx, struct g2d_image *img, + unsigned int src_x, unsigned int src_y, unsigned int dst_x, + unsigned dst_y, unsigned int w, unsigned int h); int g2d_copy_with_scale(struct g2d_context *ctx, struct g2d_image *src, struct g2d_image *dst, unsigned int src_x, unsigned int src_y, unsigned int src_w, |