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