1From 3e5a0cdf3bea40440f5940db6b7d62d74847f258 Mon Sep 17 00:00:00 2001 2From: Jeffy Chen <jeffy.chen@rock-chips.com> 3Date: Fri, 1 Nov 2019 17:55:06 +0800 4Subject: [PATCH 5/6] pixman_image_composite32: Support rockchip RGA 2D accel 5 6Disabled by default, set env PIXMAN_USE_RGA=1 to enable. 7 8Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com> 9--- 10 configure.ac | 7 ++ 11 pixman/Makefile.am | 2 +- 12 pixman/pixman.c | 278 +++++++++++++++++++++++++++++++++++++++++++++ 13 3 files changed, 286 insertions(+), 1 deletion(-) 14 15diff --git a/configure.ac b/configure.ac 16index 43e9b20..5db5f9b 100644 17--- a/configure.ac 18+++ b/configure.ac 19@@ -187,6 +187,13 @@ PIXMAN_CHECK_CFLAG([-Wdeclaration-after-statement]) 20 PIXMAN_CHECK_CFLAG([-Wno-unused-local-typedefs]) 21 PIXMAN_CHECK_CFLAG([-fno-strict-aliasing]) 22 23+dnl check for rockchip RGA 24+PKG_CHECK_MODULES(RGA, [librga], 25+ AC_DEFINE(HAVE_RGA, 1, [Have rockchip RGA])], 26+ AC_MSG_NOTICE([Without rockchip RGA])) 27+AC_SUBST(RGA_CFLAGS) 28+AC_SUBST(RGA_LIBS) 29+ 30 dnl ========================================================================= 31 dnl OpenMP for the test suite? 32 dnl 33diff --git a/pixman/Makefile.am b/pixman/Makefile.am 34index 8f780a1..a9669ab 100644 35--- a/pixman/Makefile.am 36+++ b/pixman/Makefile.am 37@@ -3,7 +3,7 @@ include $(top_srcdir)/pixman/Makefile.sources 38 lib_LTLIBRARIES = libpixman-1.la 39 40 libpixman_1_la_LDFLAGS = -version-info $(LT_VERSION_INFO) -no-undefined @PTHREAD_LDFLAGS@ 41-libpixman_1_la_LIBADD = @PTHREAD_LIBS@ -lm 42+libpixman_1_la_LIBADD = @PTHREAD_LIBS@ -lm $(RGA_LIBS) 43 libpixman_1_la_SOURCES = $(libpixman_sources) $(libpixman_headers) 44 45 libpixmanincludedir = $(includedir)/pixman-1 46diff --git a/pixman/pixman.c b/pixman/pixman.c 47index cd7479a..371e421 100644 48--- a/pixman/pixman.c 49+++ b/pixman/pixman.c 50@@ -28,8 +28,19 @@ 51 #endif 52 #include "pixman-private.h" 53 54+#include <math.h> 55 #include <stdlib.h> 56 57+#ifdef HAVE_RGA 58+#include <rga/rga.h> 59+#include <rga/RgaApi.h> 60+#endif 61+ 62+#define CLAMP(v, low, high) \ 63+ (((v) < low)? low : (((v) > high) ? high : (v))) 64+ 65+#define ANGLE(n) ((n) < 0 ? (n) + 360 : (n)) 66+ 67 pixman_implementation_t *global_implementation; 68 69 #ifdef TOOLCHAIN_SUPPORTS_ATTRIBUTE_CONSTRUCTOR 70@@ -540,6 +551,267 @@ analyze_extent (pixman_image_t *image, 71 return TRUE; 72 } 73 74+#ifdef HAVE_RGA 75+static RgaSURF_FORMAT 76+rga_get_format (pixman_image_t * image) 77+{ 78+ switch (image->bits.format) 79+ { 80+ case PIXMAN_a8r8g8b8: 81+ case PIXMAN_x8r8g8b8: 82+ return RK_FORMAT_BGRA_8888; 83+ case PIXMAN_a8b8g8r8: 84+ return RK_FORMAT_RGBA_8888; 85+ case PIXMAN_x8b8g8r8: 86+ return RK_FORMAT_RGBX_8888; 87+ case PIXMAN_r8g8b8: 88+ return RK_FORMAT_BGR_888; 89+ case PIXMAN_b8g8r8: 90+ return RK_FORMAT_RGB_888; 91+ case PIXMAN_r5g6b5: 92+ return RK_FORMAT_RGB_565; 93+ case PIXMAN_a1b5g5r5: 94+ case PIXMAN_x1b5g5r5: 95+ return RK_FORMAT_RGBA_5551; 96+ case PIXMAN_yv12: 97+ return RK_FORMAT_YCrCb_420_P; 98+ case PIXMAN_i420: 99+ return RK_FORMAT_YCbCr_420_P; 100+ case PIXMAN_nv12: 101+ return RK_FORMAT_YCbCr_420_SP; 102+ case PIXMAN_nv16: 103+ return RK_FORMAT_YCbCr_422_SP; 104+ default: 105+ return RK_FORMAT_UNKNOWN; 106+ } 107+} 108+ 109+static pixman_bool_t 110+rga_check_image (pixman_image_t * image) 111+{ 112+ if (!image) 113+ return FALSE; 114+ 115+ /* TODO: Support this */ 116+ if (image->bits.rowstride <= 0) 117+ return FALSE; 118+ 119+ /* RGA requires image width/height larger than 2 */ 120+ if (image->bits.width <= 2 || image->bits.height <= 2) 121+ return FALSE; 122+ 123+ return rga_get_format (image) != RK_FORMAT_UNKNOWN; 124+} 125+ 126+static pixman_bool_t 127+pixman_transform_to_rga_rotate (pixman_transform_t * transform, int * rotate) 128+{ 129+ pixman_vector_t v; 130+ double x, y, dx, dy; 131+ int r1, r2; 132+ 133+ *rotate = 0; 134+ 135+ if (!transform) 136+ return TRUE; 137+ 138+ if (transform->matrix[2][0] || transform->matrix[2][1] || 139+ !transform->matrix[2][2]) 140+ return FALSE; 141+ 142+ dx = transform->matrix[0][2] / (double) transform->matrix[2][2]; 143+ dy = transform->matrix[1][2] / (double) transform->matrix[2][2]; 144+ 145+ v.vector[0] = pixman_int_to_fixed (1); 146+ v.vector[1] = pixman_int_to_fixed (0); 147+ v.vector[2] = pixman_fixed_1; 148+ if (!pixman_transform_point_3d (transform, &v)) 149+ return FALSE; 150+ 151+ x = pixman_fixed_to_double (v.vector[0]) - dx; 152+ y = pixman_fixed_to_double (v.vector[1]) - dy; 153+ r1 = (int) ANGLE (atan2 (y, x) * 180 / M_PI); 154+ 155+ /* Only support 0/90/180/270 rotations */ 156+ if (r1 % 90) 157+ return FALSE; 158+ 159+ v.vector[0] = pixman_int_to_fixed (0); 160+ v.vector[1] = pixman_int_to_fixed (1); 161+ v.vector[2] = pixman_fixed_1; 162+ if (!pixman_transform_point_3d (transform, &v)) 163+ return FALSE; 164+ 165+ x = pixman_fixed_to_double (v.vector[0]) - dx; 166+ y = pixman_fixed_to_double (v.vector[1]) - dy; 167+ r2 = (int) ANGLE (atan2 (y, x) * 180 / M_PI - 90); 168+ 169+ /* TODO: Support reflect */ 170+ if (r1 != r2) 171+ return FALSE; 172+ 173+ /* Reverse the rotation */ 174+ if (r1 == 90) 175+ *rotate = HAL_TRANSFORM_ROT_270; 176+ else if (r1 == 180) 177+ *rotate = HAL_TRANSFORM_ROT_180; 178+ else if (r1 == 270) 179+ *rotate = HAL_TRANSFORM_ROT_90; 180+ 181+ return TRUE; 182+} 183+ 184+static pixman_bool_t 185+pixman_composite_try_rga (pixman_composite_info_t * info, 186+ const pixman_box32_t * pbox, int n, 187+ pixman_implementation_t * imp, 188+ pixman_composite_func_t func, 189+ int src_x, int src_y, int dest_x, int dest_y) 190+{ 191+ pixman_image_t * src = info->src_image; 192+ pixman_image_t * mask = info->mask_image; 193+ pixman_image_t * dest = info->dest_image; 194+ pixman_transform_t * transform; 195+ rga_info_t src_info = { 0 }; 196+ rga_info_t dst_info = { 0 }; 197+ int src_stride, is_yuv; 198+ 199+ static int rga_supported = 1; 200+ static int rga_inited = 0; 201+ const char *buf; 202+ 203+ buf = getenv ("PIXMAN_USE_RGA"); 204+ if (!buf || strcmp (buf, "1")) 205+ return FALSE; 206+ 207+ if (!rga_supported) 208+ return FALSE; 209+ 210+ if (!rga_inited) { 211+ if (c_RkRgaInit () < 0) { 212+ rga_supported = 0; 213+ return FALSE; 214+ } 215+ rga_inited = 1; 216+ } 217+ 218+ if (mask || src == dest) 219+ return FALSE; 220+ 221+ if (!rga_check_image (src) || !rga_check_image (dest)) 222+ return FALSE; 223+ 224+ /* TODO: Support more op */ 225+ if (info->op == PIXMAN_OP_OVER) 226+ src_info.blend = 0xFF0405; 227+ else if (info->op != PIXMAN_OP_SRC) 228+ return FALSE; 229+ 230+ /* TODO: Support SOLID */ 231+ if (src->type != BITS) 232+ return FALSE; 233+ 234+ transform = src->common.transform; 235+ if (!pixman_transform_to_rga_rotate (transform, &src_info.rotation)) 236+ return FALSE; 237+ 238+ src_info.mmuFlag = 1; 239+ src_info.virAddr = src->bits.bits; 240+ 241+ dst_info.mmuFlag = 1; 242+ dst_info.virAddr = dest->bits.bits; 243+ 244+ switch (src->bits.format) { 245+ case PIXMAN_yv12: 246+ case PIXMAN_i420: 247+ case PIXMAN_nv12: 248+ case PIXMAN_nv16: 249+ is_yuv = 1; 250+ 251+ /* rowstride = rowstride_bytes / (int) sizeof (uint32_t) */ 252+ src_stride = src->bits.rowstride * (int) sizeof (uint32_t); 253+ break; 254+ default: 255+ is_yuv = 0; 256+ src_stride = src->bits.rowstride; 257+ break; 258+ } 259+ 260+ while (n--) 261+ { 262+ pixman_box16_t box; 263+ int sx, sy, sw, sh, dx, dy, dw, dh; 264+ 265+ dx = pbox[n].x1; 266+ dy = pbox[n].y1; 267+ dw = pbox[n].x2 - pbox[n].x1; 268+ dh = pbox[n].y2 - pbox[n].y1; 269+ 270+ box.x1 = pbox[n].x1 + src_x - dest_x; 271+ box.y1 = pbox[n].y1 + src_y - dest_y; 272+ box.x2 = pbox[n].x2 + src_x - dest_x; 273+ box.y2 = pbox[n].y2 + src_y - dest_y; 274+ 275+ if (transform) 276+ pixman_transform_bounds (transform, &box); 277+ 278+ sx = CLAMP(box.x1, 0, src_stride); 279+ sy = CLAMP(box.y1, 0, src->bits.height); 280+ sw = CLAMP(box.x2 - box.x1, 0, src_stride); 281+ sh = CLAMP(box.y2 - box.y1, 0, src->bits.height); 282+ 283+ /* TODO: Support repeat? */ 284+ if (sw != dw || sh != dh) 285+ goto bail; 286+ 287+ if (is_yuv) { 288+ /* RGA requires yuv image rect align to 2 */ 289+ sx = (sx + 1) & ~1; 290+ sy = (sy + 1) & ~1; 291+ sw = sw & ~1; 292+ sh = sh & ~1; 293+ 294+ /* RGA requires yuv image stride align to 2 */ 295+ if (src_stride % 2) 296+ goto bail; 297+ } 298+ 299+ /* RGA requires w >= 2 and h >= 2 */ 300+ if (sw < 2 || sh < 2 || dw < 2 || dh < 2) 301+ goto bail; 302+ 303+ /* RGA has scale limits */ 304+ if ((double) sw / dw > 16 || (double) dw / sw > 16 || 305+ (double) sh / dh > 16 || (double) dh / sh > 16) 306+ goto bail; 307+ 308+ rga_set_rect (&src_info.rect, sx, sy, sw, sh, 309+ src_stride, src->bits.height, rga_get_format (src)); 310+ 311+ rga_set_rect (&dst_info.rect, dx, dy, dw, dh, 312+ dest->bits.rowstride, dest->bits.height, 313+ rga_get_format (dest)); 314+ 315+ if (c_RkRgaBlit (&src_info, &dst_info, NULL) < 0) 316+ goto bail; 317+ 318+ continue; 319+ 320+bail: 321+ info->src_x = pbox[n].x1 + src_x - dest_x; 322+ info->src_y = pbox[n].y1 + src_y - dest_y; 323+ info->dest_x = pbox[n].x1; 324+ info->dest_y = pbox[n].y1; 325+ info->width = pbox[n].x2 - pbox[n].x1; 326+ info->height = pbox[n].y2 - pbox[n].y1; 327+ 328+ func (imp, info); 329+ } 330+ 331+ return TRUE; 332+} 333+#endif 334+ 335 /* 336 * Work around GCC bug causing crashes in Mozilla with SSE2 337 * 338@@ -686,6 +958,12 @@ pixman_image_composite32 (pixman_op_t op, 339 340 pbox = pixman_region32_rectangles (®ion, &n); 341 342+#ifdef HAVE_RGA 343+ if (pixman_composite_try_rga (&info, pbox, n, imp, func, 344+ src_x, src_y, dest_x, dest_y)) 345+ goto out; 346+#endif 347+ 348 while (n--) 349 { 350 info.src_x = pbox->x1 + src_x - dest_x; 351-- 3522.20.1 353 354