From 3e5a0cdf3bea40440f5940db6b7d62d74847f258 Mon Sep 17 00:00:00 2001 From: Jeffy Chen Date: Fri, 1 Nov 2019 17:55:06 +0800 Subject: [PATCH 5/6] pixman_image_composite32: Support rockchip RGA 2D accel Disabled by default, set env PIXMAN_USE_RGA=1 to enable. Signed-off-by: Jeffy Chen --- configure.ac | 7 ++ pixman/Makefile.am | 2 +- pixman/pixman.c | 278 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 286 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 43e9b20..5db5f9b 100644 --- a/configure.ac +++ b/configure.ac @@ -187,6 +187,13 @@ PIXMAN_CHECK_CFLAG([-Wdeclaration-after-statement]) PIXMAN_CHECK_CFLAG([-Wno-unused-local-typedefs]) PIXMAN_CHECK_CFLAG([-fno-strict-aliasing]) +dnl check for rockchip RGA +PKG_CHECK_MODULES(RGA, [librga], + AC_DEFINE(HAVE_RGA, 1, [Have rockchip RGA])], + AC_MSG_NOTICE([Without rockchip RGA])) +AC_SUBST(RGA_CFLAGS) +AC_SUBST(RGA_LIBS) + dnl ========================================================================= dnl OpenMP for the test suite? dnl diff --git a/pixman/Makefile.am b/pixman/Makefile.am index 8f780a1..a9669ab 100644 --- a/pixman/Makefile.am +++ b/pixman/Makefile.am @@ -3,7 +3,7 @@ include $(top_srcdir)/pixman/Makefile.sources lib_LTLIBRARIES = libpixman-1.la libpixman_1_la_LDFLAGS = -version-info $(LT_VERSION_INFO) -no-undefined @PTHREAD_LDFLAGS@ -libpixman_1_la_LIBADD = @PTHREAD_LIBS@ -lm +libpixman_1_la_LIBADD = @PTHREAD_LIBS@ -lm $(RGA_LIBS) libpixman_1_la_SOURCES = $(libpixman_sources) $(libpixman_headers) libpixmanincludedir = $(includedir)/pixman-1 diff --git a/pixman/pixman.c b/pixman/pixman.c index cd7479a..371e421 100644 --- a/pixman/pixman.c +++ b/pixman/pixman.c @@ -28,8 +28,19 @@ #endif #include "pixman-private.h" +#include #include +#ifdef HAVE_RGA +#include +#include +#endif + +#define CLAMP(v, low, high) \ + (((v) < low)? low : (((v) > high) ? high : (v))) + +#define ANGLE(n) ((n) < 0 ? (n) + 360 : (n)) + pixman_implementation_t *global_implementation; #ifdef TOOLCHAIN_SUPPORTS_ATTRIBUTE_CONSTRUCTOR @@ -540,6 +551,267 @@ analyze_extent (pixman_image_t *image, return TRUE; } +#ifdef HAVE_RGA +static RgaSURF_FORMAT +rga_get_format (pixman_image_t * image) +{ + switch (image->bits.format) + { + case PIXMAN_a8r8g8b8: + case PIXMAN_x8r8g8b8: + return RK_FORMAT_BGRA_8888; + case PIXMAN_a8b8g8r8: + return RK_FORMAT_RGBA_8888; + case PIXMAN_x8b8g8r8: + return RK_FORMAT_RGBX_8888; + case PIXMAN_r8g8b8: + return RK_FORMAT_BGR_888; + case PIXMAN_b8g8r8: + return RK_FORMAT_RGB_888; + case PIXMAN_r5g6b5: + return RK_FORMAT_RGB_565; + case PIXMAN_a1b5g5r5: + case PIXMAN_x1b5g5r5: + return RK_FORMAT_RGBA_5551; + case PIXMAN_yv12: + return RK_FORMAT_YCrCb_420_P; + case PIXMAN_i420: + return RK_FORMAT_YCbCr_420_P; + case PIXMAN_nv12: + return RK_FORMAT_YCbCr_420_SP; + case PIXMAN_nv16: + return RK_FORMAT_YCbCr_422_SP; + default: + return RK_FORMAT_UNKNOWN; + } +} + +static pixman_bool_t +rga_check_image (pixman_image_t * image) +{ + if (!image) + return FALSE; + + /* TODO: Support this */ + if (image->bits.rowstride <= 0) + return FALSE; + + /* RGA requires image width/height larger than 2 */ + if (image->bits.width <= 2 || image->bits.height <= 2) + return FALSE; + + return rga_get_format (image) != RK_FORMAT_UNKNOWN; +} + +static pixman_bool_t +pixman_transform_to_rga_rotate (pixman_transform_t * transform, int * rotate) +{ + pixman_vector_t v; + double x, y, dx, dy; + int r1, r2; + + *rotate = 0; + + if (!transform) + return TRUE; + + if (transform->matrix[2][0] || transform->matrix[2][1] || + !transform->matrix[2][2]) + return FALSE; + + dx = transform->matrix[0][2] / (double) transform->matrix[2][2]; + dy = transform->matrix[1][2] / (double) transform->matrix[2][2]; + + v.vector[0] = pixman_int_to_fixed (1); + v.vector[1] = pixman_int_to_fixed (0); + v.vector[2] = pixman_fixed_1; + if (!pixman_transform_point_3d (transform, &v)) + return FALSE; + + x = pixman_fixed_to_double (v.vector[0]) - dx; + y = pixman_fixed_to_double (v.vector[1]) - dy; + r1 = (int) ANGLE (atan2 (y, x) * 180 / M_PI); + + /* Only support 0/90/180/270 rotations */ + if (r1 % 90) + return FALSE; + + v.vector[0] = pixman_int_to_fixed (0); + v.vector[1] = pixman_int_to_fixed (1); + v.vector[2] = pixman_fixed_1; + if (!pixman_transform_point_3d (transform, &v)) + return FALSE; + + x = pixman_fixed_to_double (v.vector[0]) - dx; + y = pixman_fixed_to_double (v.vector[1]) - dy; + r2 = (int) ANGLE (atan2 (y, x) * 180 / M_PI - 90); + + /* TODO: Support reflect */ + if (r1 != r2) + return FALSE; + + /* Reverse the rotation */ + if (r1 == 90) + *rotate = HAL_TRANSFORM_ROT_270; + else if (r1 == 180) + *rotate = HAL_TRANSFORM_ROT_180; + else if (r1 == 270) + *rotate = HAL_TRANSFORM_ROT_90; + + return TRUE; +} + +static pixman_bool_t +pixman_composite_try_rga (pixman_composite_info_t * info, + const pixman_box32_t * pbox, int n, + pixman_implementation_t * imp, + pixman_composite_func_t func, + int src_x, int src_y, int dest_x, int dest_y) +{ + pixman_image_t * src = info->src_image; + pixman_image_t * mask = info->mask_image; + pixman_image_t * dest = info->dest_image; + pixman_transform_t * transform; + rga_info_t src_info = { 0 }; + rga_info_t dst_info = { 0 }; + int src_stride, is_yuv; + + static int rga_supported = 1; + static int rga_inited = 0; + const char *buf; + + buf = getenv ("PIXMAN_USE_RGA"); + if (!buf || strcmp (buf, "1")) + return FALSE; + + if (!rga_supported) + return FALSE; + + if (!rga_inited) { + if (c_RkRgaInit () < 0) { + rga_supported = 0; + return FALSE; + } + rga_inited = 1; + } + + if (mask || src == dest) + return FALSE; + + if (!rga_check_image (src) || !rga_check_image (dest)) + return FALSE; + + /* TODO: Support more op */ + if (info->op == PIXMAN_OP_OVER) + src_info.blend = 0xFF0405; + else if (info->op != PIXMAN_OP_SRC) + return FALSE; + + /* TODO: Support SOLID */ + if (src->type != BITS) + return FALSE; + + transform = src->common.transform; + if (!pixman_transform_to_rga_rotate (transform, &src_info.rotation)) + return FALSE; + + src_info.mmuFlag = 1; + src_info.virAddr = src->bits.bits; + + dst_info.mmuFlag = 1; + dst_info.virAddr = dest->bits.bits; + + switch (src->bits.format) { + case PIXMAN_yv12: + case PIXMAN_i420: + case PIXMAN_nv12: + case PIXMAN_nv16: + is_yuv = 1; + + /* rowstride = rowstride_bytes / (int) sizeof (uint32_t) */ + src_stride = src->bits.rowstride * (int) sizeof (uint32_t); + break; + default: + is_yuv = 0; + src_stride = src->bits.rowstride; + break; + } + + while (n--) + { + pixman_box16_t box; + int sx, sy, sw, sh, dx, dy, dw, dh; + + dx = pbox[n].x1; + dy = pbox[n].y1; + dw = pbox[n].x2 - pbox[n].x1; + dh = pbox[n].y2 - pbox[n].y1; + + box.x1 = pbox[n].x1 + src_x - dest_x; + box.y1 = pbox[n].y1 + src_y - dest_y; + box.x2 = pbox[n].x2 + src_x - dest_x; + box.y2 = pbox[n].y2 + src_y - dest_y; + + if (transform) + pixman_transform_bounds (transform, &box); + + sx = CLAMP(box.x1, 0, src_stride); + sy = CLAMP(box.y1, 0, src->bits.height); + sw = CLAMP(box.x2 - box.x1, 0, src_stride); + sh = CLAMP(box.y2 - box.y1, 0, src->bits.height); + + /* TODO: Support repeat? */ + if (sw != dw || sh != dh) + goto bail; + + if (is_yuv) { + /* RGA requires yuv image rect align to 2 */ + sx = (sx + 1) & ~1; + sy = (sy + 1) & ~1; + sw = sw & ~1; + sh = sh & ~1; + + /* RGA requires yuv image stride align to 2 */ + if (src_stride % 2) + goto bail; + } + + /* RGA requires w >= 2 and h >= 2 */ + if (sw < 2 || sh < 2 || dw < 2 || dh < 2) + goto bail; + + /* RGA has scale limits */ + if ((double) sw / dw > 16 || (double) dw / sw > 16 || + (double) sh / dh > 16 || (double) dh / sh > 16) + goto bail; + + rga_set_rect (&src_info.rect, sx, sy, sw, sh, + src_stride, src->bits.height, rga_get_format (src)); + + rga_set_rect (&dst_info.rect, dx, dy, dw, dh, + dest->bits.rowstride, dest->bits.height, + rga_get_format (dest)); + + if (c_RkRgaBlit (&src_info, &dst_info, NULL) < 0) + goto bail; + + continue; + +bail: + info->src_x = pbox[n].x1 + src_x - dest_x; + info->src_y = pbox[n].y1 + src_y - dest_y; + info->dest_x = pbox[n].x1; + info->dest_y = pbox[n].y1; + info->width = pbox[n].x2 - pbox[n].x1; + info->height = pbox[n].y2 - pbox[n].y1; + + func (imp, info); + } + + return TRUE; +} +#endif + /* * Work around GCC bug causing crashes in Mozilla with SSE2 * @@ -686,6 +958,12 @@ pixman_image_composite32 (pixman_op_t op, pbox = pixman_region32_rectangles (®ion, &n); +#ifdef HAVE_RGA + if (pixman_composite_try_rga (&info, pbox, n, imp, func, + src_x, src_y, dest_x, dest_y)) + goto out; +#endif + while (n--) { info.src_x = pbox->x1 + src_x - dest_x; -- 2.20.1