diff options
author | Alexei Shlychkov <x0177296@ti.com> | 2012-10-11 10:46:42 -0700 |
---|---|---|
committer | Ziyann <jaraidaniel@gmail.com> | 2014-10-01 13:01:04 +0200 |
commit | b0e93e9906b03a3661d0d29d63015e15565d3216 (patch) | |
tree | a777b2f5bf963a09f25baafa8e729ec11d2d9aab | |
parent | 36383ebef70b9e962233f61b4fcff20d5c2b5969 (diff) | |
download | kernel_samsung_tuna-b0e93e9906b03a3661d0d29d63015e15565d3216.zip kernel_samsung_tuna-b0e93e9906b03a3661d0d29d63015e15565d3216.tar.gz kernel_samsung_tuna-b0e93e9906b03a3661d0d29d63015e15565d3216.tar.bz2 |
gcx: fixed surface offset calculations.
This is primarily to fix YUV plane location
calculations, but RGB formats are affected as well.
Change-Id: I2877c3c0ec35c03425903c2df9de08ba201cf091
Signed-off-by: Alexei Shlychkov <x0177296@ti.com>
-rw-r--r-- | drivers/misc/gcx/gcbv/gcblit.c | 129 | ||||
-rw-r--r-- | drivers/misc/gcx/gcbv/gcbv.c | 185 | ||||
-rw-r--r-- | drivers/misc/gcx/gcbv/gcbv.h | 10 | ||||
-rw-r--r-- | drivers/misc/gcx/gcbv/gcfilter.c | 120 | ||||
-rw-r--r-- | drivers/misc/gcx/gcbv/gcparser.c | 120 |
5 files changed, 361 insertions, 203 deletions
diff --git a/drivers/misc/gcx/gcbv/gcblit.c b/drivers/misc/gcx/gcbv/gcblit.c index 04fa86a..f8a768e 100644 --- a/drivers/misc/gcx/gcbv/gcblit.c +++ b/drivers/misc/gcx/gcbv/gcblit.c @@ -225,6 +225,7 @@ enum bverror do_blit(struct bvbltparams *bvbltparams, srcclipped.top = srcinfo->rect.top + batch->clipdelta.top; srcclipped.right = srcinfo->rect.right + batch->clipdelta.right; srcclipped.bottom = srcinfo->rect.bottom + batch->clipdelta.bottom; + GCPRINT_RECT(GCZONE_SURF, "clipped source", &srcclipped); /* Validate the source rectangle. */ if (!valid_rect(srcinfo->geom, &srcclipped)) { @@ -266,37 +267,65 @@ enum bverror do_blit(struct bvbltparams *bvbltparams, srcshiftY = 0; } + /* We cannot be in the middle of a sample, currently only YUV formats + * can have subsamples. Adjust vertical position as necessary. + * Horizontal position will be adjusted based on the byte offset and + * base address alignment requirement. This assumes that if we are + * aligned on the base address, then we are also aligned at the + * beginning of a sample. */ + if (srcinfo->format.type == BVFMT_YUV) { + int mody = srcshiftY % srcinfo->format.cs.yuv.ysample; + if (mody < 0) + mody = srcinfo->format.cs.yuv.ysample + mody; + + srcshiftY -= mody; + srcinfo->ypixalign = -mody; + } else { + srcinfo->ypixalign = 0; + } + /* Compute the source surface offset in bytes. */ srcinfo->bytealign = srcshiftY * (int) srcinfo->geom->virtstride + srcshiftX * (int) srcinfo->format.bitspp / 8; /* Compute the source offset in pixels needed to compensate * for the surface base address misalignment if any. */ - srcinfo->pixalign = get_pixel_offset(srcinfo, srcinfo->bytealign); + srcinfo->xpixalign = get_pixel_offset(srcinfo, srcinfo->bytealign); GCDBG(GCZONE_SURF, "source surface %d:\n", srcinfo->index + 1); GCDBG(GCZONE_SURF, " surface offset (pixels) = %d,%d\n", srcshiftX, srcshiftY); GCDBG(GCZONE_SURF, " surface offset (bytes) = 0x%08X\n", srcinfo->bytealign); - GCDBG(GCZONE_SURF, " srcpixalign = %d\n", - srcinfo->pixalign); + GCDBG(GCZONE_SURF, " srcpixalign = %d,%d\n", + srcinfo->xpixalign, srcinfo->ypixalign); /* Apply the source alignment. */ - srcinfo->bytealign += srcinfo->pixalign + srcinfo->bytealign += srcinfo->xpixalign * (int) srcinfo->format.bitspp / 8; - srcshiftX += srcinfo->pixalign; + srcshiftX += srcinfo->xpixalign; GCDBG(GCZONE_SURF, " adjusted surface offset (pixels) = %d,%d\n", srcshiftX, srcshiftY); GCDBG(GCZONE_SURF, " adjusted surface offset (bytes) = 0x%08X\n", srcinfo->bytealign); - /* Determine the destination surface shift. Vertical shift only applies - * if the destination angle is ahead by 270 degrees. */ - dstshiftX = dstinfo->pixalign; - dstshiftY = (((srcinfo->angle + 3) % 4) == dstinfo->angle) - ? srcinfo->pixalign : 0; + /* Compute U/V plane offsets. */ + if (srcinfo->format.type == BVFMT_YUV) + set_computeyuv(srcinfo, srcshiftX, srcshiftY); + + /* Determine the destination surface shift. */ + dstshiftX = dstinfo->xpixalign; + dstshiftY = dstinfo->ypixalign; + + if (srcinfo->angle == dstinfo->angle) { + dstshiftX += srcinfo->xpixalign; + dstshiftY += srcinfo->ypixalign; + } else if (((srcinfo->angle + 3) % 4) == dstinfo->angle) { + dstshiftY += srcinfo->xpixalign; + } else if (((srcinfo->angle + 1) % 4) == dstinfo->angle) { + dstshiftX += srcinfo->ypixalign; + } /* Compute the destination surface offset in bytes. */ dstbyteshift = dstshiftY * (int) dstinfo->geom->virtstride @@ -315,55 +344,63 @@ enum bverror do_blit(struct bvbltparams *bvbltparams, dstpixalign); if ((dstpixalign != 0) || - ((srcinfo->pixalign != 0) && (srcinfo->angle == dstinfo->angle))) { + ((srcinfo->xpixalign != 0) && (srcinfo->angle == dstinfo->angle))) { /* Compute the source offset in pixels needed to compensate * for the surface base address misalignment if any. */ - srcinfo->pixalign = get_pixel_offset(srcinfo, 0); + srcinfo->xpixalign = get_pixel_offset(srcinfo, 0); + srcinfo->ypixalign = 0; /* Compute the surface offsets in bytes. */ - srcinfo->bytealign = srcinfo->pixalign + srcinfo->bytealign = srcinfo->xpixalign * (int) srcinfo->format.bitspp / 8; + /* Overwrite destination byte offset. */ + dstbyteshift = dstinfo->bytealign; + GCDBG(GCZONE_SURF, "recomputed for single-source setup:\n"); - GCDBG(GCZONE_SURF, " srcpixalign = %d\n", - srcinfo->pixalign); + GCDBG(GCZONE_SURF, " srcpixalign = %d,%d\n", + srcinfo->xpixalign, srcinfo->ypixalign); GCDBG(GCZONE_SURF, " srcsurf offset (bytes) = 0x%08X\n", srcinfo->bytealign); GCDBG(GCZONE_SURF, " dstsurf offset (bytes) = 0x%08X\n", dstinfo->bytealign); + /* Compute U/V plane offsets. */ + if (srcinfo->format.type == BVFMT_YUV) + set_computeyuv(srcinfo, 0, 0); + switch (srcinfo->angle) { case ROT_ANGLE_0: /* Adjust left coordinate. */ - srcclipped.left -= srcinfo->pixalign; + srcclipped.left -= srcinfo->xpixalign; /* Determine source size. */ srcsurfwidth = srcinfo->geom->width - - srcinfo->pixalign; + - srcinfo->xpixalign; srcsurfheight = srcinfo->geom->height; break; case ROT_ANGLE_90: /* Adjust top coordinate. */ - srcclipped.top -= srcinfo->pixalign; + srcclipped.top -= srcinfo->xpixalign; /* Determine source size. */ srcsurfwidth = srcinfo->geom->height - - srcinfo->pixalign; + - srcinfo->xpixalign; srcsurfheight = srcinfo->geom->width; break; case ROT_ANGLE_180: /* Determine source size. */ srcsurfwidth = srcinfo->geom->width - - srcinfo->pixalign; + - srcinfo->xpixalign; srcsurfheight = srcinfo->geom->height; break; case ROT_ANGLE_270: /* Determine source size. */ srcsurfwidth = srcinfo->geom->height - - srcinfo->pixalign; + - srcinfo->xpixalign; srcsurfheight = srcinfo->geom->width; break; @@ -386,7 +423,7 @@ enum bverror do_blit(struct bvbltparams *bvbltparams, physheight = dstinfo->physheight; /* Disable multi source for the cases where the destination - * and the base address alignment does not match. */ + * and the source address alignments do not match. */ multisrc = 0; GCDBG(GCZONE_SURF, "multi-source disabled.\n"); } else { @@ -398,37 +435,41 @@ enum bverror do_blit(struct bvbltparams *bvbltparams, switch (srcinfo->angle) { case ROT_ANGLE_0: /* Adjust the destination horizontally. */ - dstoffsetX = srcinfo->pixalign; - dstoffsetY = 0; + dstoffsetX = srcinfo->xpixalign; + dstoffsetY = srcinfo->ypixalign; /* Apply the source alignment. */ if ((dstinfo->angle == ROT_ANGLE_0) || (dstinfo->angle == ROT_ANGLE_180)) { physwidth = dstinfo->physwidth - - srcinfo->pixalign; - physheight = dstinfo->physheight; + - srcinfo->xpixalign; + physheight = dstinfo->physheight + - srcinfo->ypixalign; } else { - physwidth = dstinfo->physwidth; + physwidth = dstinfo->physwidth + - srcinfo->ypixalign; physheight = dstinfo->physheight - - srcinfo->pixalign; + - srcinfo->xpixalign; } break; case ROT_ANGLE_90: /* Adjust the destination vertically. */ - dstoffsetX = 0; - dstoffsetY = srcinfo->pixalign; + dstoffsetX = srcinfo->ypixalign; + dstoffsetY = srcinfo->xpixalign; /* Apply the source alignment. */ if ((dstinfo->angle == ROT_ANGLE_0) || (dstinfo->angle == ROT_ANGLE_180)) { - physwidth = dstinfo->physwidth; + physwidth = dstinfo->physwidth + - srcinfo->ypixalign; physheight = dstinfo->physheight - - srcinfo->pixalign; + - srcinfo->xpixalign; } else { physwidth = dstinfo->physwidth - - srcinfo->pixalign; - physheight = dstinfo->physheight; + - srcinfo->xpixalign; + physheight = dstinfo->physheight + - srcinfo->ypixalign; } break; @@ -441,12 +482,14 @@ enum bverror do_blit(struct bvbltparams *bvbltparams, if ((dstinfo->angle == ROT_ANGLE_0) || (dstinfo->angle == ROT_ANGLE_180)) { physwidth = dstinfo->physwidth - - srcinfo->pixalign; - physheight = dstinfo->physheight; + - srcinfo->xpixalign; + physheight = dstinfo->physheight + - srcinfo->ypixalign; } else { - physwidth = dstinfo->physwidth; + physwidth = dstinfo->physwidth + - srcinfo->ypixalign; physheight = dstinfo->physheight - - srcinfo->pixalign; + - srcinfo->xpixalign; } break; @@ -458,13 +501,15 @@ enum bverror do_blit(struct bvbltparams *bvbltparams, /* Apply the source alignment. */ if ((dstinfo->angle == ROT_ANGLE_0) || (dstinfo->angle == ROT_ANGLE_180)) { - physwidth = dstinfo->physwidth; + physwidth = dstinfo->physwidth + - srcinfo->ypixalign; physheight = dstinfo->physheight - - srcinfo->pixalign; + - srcinfo->xpixalign; } else { physwidth = dstinfo->physwidth - - srcinfo->pixalign; - physheight = dstinfo->physheight; + - srcinfo->xpixalign; + physheight = dstinfo->physheight + - srcinfo->ypixalign; } break; diff --git a/drivers/misc/gcx/gcbv/gcbv.c b/drivers/misc/gcx/gcbv/gcbv.c index d86d550..c5da5f7 100644 --- a/drivers/misc/gcx/gcbv/gcbv.c +++ b/drivers/misc/gcx/gcbv/gcbv.c @@ -726,6 +726,91 @@ exit: * Program YUV source. */ +void set_computeyuv(struct surfaceinfo *srcinfo, int x, int y) +{ + int pixalign, bytealign; + unsigned int height1, size1; + unsigned int height2, size2; + unsigned int origin; + int ssX, ssY; + + GCENTER(GCZONE_SRC); + + switch (srcinfo->format.cs.yuv.planecount) { + case 2: + /* Compute base address alignment. */ + pixalign = get_pixel_offset(srcinfo, 0); + bytealign = (pixalign * (int) srcinfo->format.bitspp) / 8; + + /* Determine physical height. */ + height1 = ((srcinfo->angle % 2) == 0) + ? srcinfo->geom->height + : srcinfo->geom->width; + + /* Determine the second plane stride. */ + srcinfo->stride2 = srcinfo->geom->virtstride + / srcinfo->format.cs.yuv.xsample; + + /* Determine subsample pixel position. */ + ssX = x / srcinfo->format.cs.yuv.xsample; + ssY = y / srcinfo->format.cs.yuv.ysample; + + /* U and V are interleaved in one plane. */ + ssX *= 2; + srcinfo->stride2 *= 2; + + /* Determine the size of the first plane. */ + size1 = srcinfo->geom->virtstride * height1; + + /* Determnine the origin offset. */ + origin = ssY * srcinfo->stride2 + ssX; + + /* Compute the second plane alignment. */ + srcinfo->bytealign2 = bytealign + size1 + origin; + GCDBG(GCZONE_SRC, "plane2 offset (bytes) = 0x%08X\n", + srcinfo->bytealign2); + break; + + case 3: + /* Compute base address alignment. */ + pixalign = get_pixel_offset(srcinfo, 0); + bytealign = (pixalign * (int) srcinfo->format.bitspp) / 8; + + /* Determine physical height. */ + height1 = ((srcinfo->angle % 2) == 0) + ? srcinfo->geom->height + : srcinfo->geom->width; + height2 = height1 / srcinfo->format.cs.yuv.ysample; + + /* Determine the U and V stride. */ + srcinfo->stride2 = + srcinfo->stride3 = srcinfo->geom->virtstride + / srcinfo->format.cs.yuv.xsample; + + /* Determine subsample pixel position. */ + ssX = x / srcinfo->format.cs.yuv.xsample; + ssY = y / srcinfo->format.cs.yuv.ysample; + + /* Determine the size of the planes. */ + size1 = srcinfo->geom->virtstride * height1; + size2 = srcinfo->stride2 * height2; + + /* Determnine the origin offset. */ + origin = ssY * srcinfo->stride2 + ssX; + + /* Compute the second plane alignment. */ + srcinfo->bytealign2 = bytealign + size1 + origin; + srcinfo->bytealign3 = bytealign + size1 + size2 + origin; + GCDBG(GCZONE_SRC, " plane2 offset (bytes) = 0x%08X\n", + srcinfo->bytealign2); + GCDBG(GCZONE_SRC, " plane3 offset (bytes) = 0x%08X\n", + srcinfo->bytealign3); + break; + } + + GCEXIT(GCZONE_SRC); +} + enum bverror set_yuvsrc(struct bvbltparams *bvbltparams, struct gcbatch *batch, struct surfaceinfo *srcinfo, @@ -735,8 +820,6 @@ enum bverror set_yuvsrc(struct bvbltparams *bvbltparams, struct gcmoyuv1 *gcmoyuv1; struct gcmoyuv2 *gcmoyuv2; struct gcmoyuv3 *gcmoyuv3; - int ushift, vshift; - unsigned int srcheight; GCENTER(GCZONE_SRC); @@ -751,6 +834,7 @@ enum bverror set_yuvsrc(struct bvbltparams *bvbltparams, if (bverror != BVERR_NONE) goto exit; + /* Set YUV parameters. */ gcmoyuv1->pectrl_ldst = gcmoyuv_pectrl_ldst; gcmoyuv1->pectrl.raw = 0; gcmoyuv1->pectrl.reg.standard @@ -768,6 +852,7 @@ enum bverror set_yuvsrc(struct bvbltparams *bvbltparams, if (bverror != BVERR_NONE) goto exit; + /* Set YUV parameters. */ gcmoyuv2->pectrl_ldst = gcmoyuv_pectrl_ldst; gcmoyuv2->pectrl.raw = 0; gcmoyuv2->pectrl.reg.standard @@ -777,22 +862,12 @@ enum bverror set_yuvsrc(struct bvbltparams *bvbltparams, gcmoyuv2->pectrl.reg.convert = GCREG_PE_CONTROL_YUVRGB_DISABLED; - srcheight = ((srcinfo->angle % 2) == 0) - ? srcinfo->geom->height - : srcinfo->geom->width; - - ushift = srcinfo->bytealign - + srcinfo->geom->virtstride - * srcheight; - GCDBG(GCZONE_SRC, "ushift = 0x%08X (%d)\n", - ushift, ushift); - + /* Program U/V plane. */ add_fixup(bvbltparams, batch, &gcmoyuv2->uplaneaddress, - ushift); - + srcinfo->bytealign2); gcmoyuv2->plane_ldst = gcmoyuv2_plane_ldst; gcmoyuv2->uplaneaddress = GET_MAP_HANDLE(srcmap); - gcmoyuv2->uplanestride = srcinfo->geom->virtstride; + gcmoyuv2->uplanestride = srcinfo->stride2; break; case 3: @@ -802,6 +877,7 @@ enum bverror set_yuvsrc(struct bvbltparams *bvbltparams, if (bverror != BVERR_NONE) goto exit; + /* Set YUV parameters. */ gcmoyuv3->pectrl_ldst = gcmoyuv_pectrl_ldst; gcmoyuv3->pectrl.raw = 0; gcmoyuv3->pectrl.reg.standard @@ -811,32 +887,16 @@ enum bverror set_yuvsrc(struct bvbltparams *bvbltparams, gcmoyuv3->pectrl.reg.convert = GCREG_PE_CONTROL_YUVRGB_DISABLED; - srcheight = ((srcinfo->angle % 2) == 0) - ? srcinfo->geom->height - : srcinfo->geom->width; - - ushift = srcinfo->bytealign - + srcinfo->geom->virtstride - * srcheight; - vshift = ushift - + srcinfo->geom->virtstride - * srcheight / 4; - - GCDBG(GCZONE_SRC, "ushift = 0x%08X (%d)\n", - ushift, ushift); - GCDBG(GCZONE_SRC, "vshift = 0x%08X (%d)\n", - vshift, vshift); - + /* Program U/V planes. */ add_fixup(bvbltparams, batch, &gcmoyuv3->uplaneaddress, - ushift); + srcinfo->bytealign2); add_fixup(bvbltparams, batch, &gcmoyuv3->vplaneaddress, - vshift); - + srcinfo->bytealign3); gcmoyuv3->plane_ldst = gcmoyuv3_plane_ldst; gcmoyuv3->uplaneaddress = GET_MAP_HANDLE(srcmap); - gcmoyuv3->uplanestride = srcinfo->geom->virtstride / 2; + gcmoyuv3->uplanestride = srcinfo->stride2; gcmoyuv3->vplaneaddress = GET_MAP_HANDLE(srcmap); - gcmoyuv3->vplanestride = srcinfo->geom->virtstride / 2; + gcmoyuv3->vplanestride = srcinfo->stride2; break; default: @@ -860,8 +920,6 @@ enum bverror set_yuvsrc_index(struct bvbltparams *bvbltparams, struct gcmoxsrcyuv1 *gcmoxsrcyuv1; struct gcmoxsrcyuv2 *gcmoxsrcyuv2; struct gcmoxsrcyuv3 *gcmoxsrcyuv3; - int ushift, vshift; - unsigned int srcheight; GCENTER(GCZONE_SRC); @@ -876,6 +934,7 @@ enum bverror set_yuvsrc_index(struct bvbltparams *bvbltparams, if (bverror != BVERR_NONE) goto exit; + /* Set YUV parameters. */ gcmoxsrcyuv1->pectrl_ldst = gcmoxsrcyuv_pectrl_ldst[index]; gcmoxsrcyuv1->pectrl.raw = 0; @@ -894,6 +953,7 @@ enum bverror set_yuvsrc_index(struct bvbltparams *bvbltparams, if (bverror != BVERR_NONE) goto exit; + /* Set YUV parameters. */ gcmoxsrcyuv2->pectrl_ldst = gcmoxsrcyuv_pectrl_ldst[index]; gcmoxsrcyuv2->pectrl.raw = 0; @@ -904,26 +964,15 @@ enum bverror set_yuvsrc_index(struct bvbltparams *bvbltparams, gcmoxsrcyuv2->pectrl.reg.convert = GCREG_PE_CONTROL_YUVRGB_DISABLED; - srcheight = ((srcinfo->angle % 2) == 0) - ? srcinfo->geom->height - : srcinfo->geom->width; - - ushift = srcinfo->bytealign - + srcinfo->geom->virtstride - * srcheight; - GCDBG(GCZONE_SRC, "ushift = 0x%08X (%d)\n", - ushift, ushift); - + /* Program U/V plane. */ add_fixup(bvbltparams, batch, &gcmoxsrcyuv2->uplaneaddress, - ushift); - + srcinfo->bytealign2); gcmoxsrcyuv2->uplaneaddress_ldst = gcmoxsrcyuv_uplaneaddress_ldst[index]; gcmoxsrcyuv2->uplaneaddress = GET_MAP_HANDLE(srcmap); - gcmoxsrcyuv2->uplanestride_ldst = gcmoxsrcyuv_uplanestride_ldst[index]; - gcmoxsrcyuv2->uplanestride = srcinfo->geom->virtstride; + gcmoxsrcyuv2->uplanestride = srcinfo->stride2; break; case 3: @@ -933,6 +982,7 @@ enum bverror set_yuvsrc_index(struct bvbltparams *bvbltparams, if (bverror != BVERR_NONE) goto exit; + /* Set YUV parameters. */ gcmoxsrcyuv3->pectrl_ldst = gcmoxsrcyuv_pectrl_ldst[index]; gcmoxsrcyuv3->pectrl.raw = 0; @@ -943,42 +993,23 @@ enum bverror set_yuvsrc_index(struct bvbltparams *bvbltparams, gcmoxsrcyuv3->pectrl.reg.convert = GCREG_PE_CONTROL_YUVRGB_DISABLED; - srcheight = ((srcinfo->angle % 2) == 0) - ? srcinfo->geom->height - : srcinfo->geom->width; - - ushift = srcinfo->bytealign - + srcinfo->geom->virtstride - * srcheight; - vshift = ushift - + srcinfo->geom->virtstride - * srcheight / 4; - - GCDBG(GCZONE_SRC, "ushift = 0x%08X (%d)\n", - ushift, ushift); - GCDBG(GCZONE_SRC, "vshift = 0x%08X (%d)\n", - vshift, vshift); - + /* Program U/V planes. */ add_fixup(bvbltparams, batch, &gcmoxsrcyuv3->uplaneaddress, - ushift); + srcinfo->bytealign2); add_fixup(bvbltparams, batch, &gcmoxsrcyuv3->vplaneaddress, - vshift); - + srcinfo->bytealign3); gcmoxsrcyuv3->uplaneaddress_ldst = gcmoxsrcyuv_uplaneaddress_ldst[index]; gcmoxsrcyuv3->uplaneaddress = GET_MAP_HANDLE(srcmap); - gcmoxsrcyuv3->uplanestride_ldst = gcmoxsrcyuv_uplanestride_ldst[index]; - gcmoxsrcyuv3->uplanestride = srcinfo->geom->virtstride / 2; - + gcmoxsrcyuv3->uplanestride = srcinfo->stride2; gcmoxsrcyuv3->vplaneaddress_ldst = gcmoxsrcyuv_vplaneaddress_ldst[index]; gcmoxsrcyuv3->vplaneaddress = GET_MAP_HANDLE(srcmap); - gcmoxsrcyuv3->vplanestride_ldst = gcmoxsrcyuv_vplanestride_ldst[index]; - gcmoxsrcyuv3->vplanestride = srcinfo->geom->virtstride / 2; + gcmoxsrcyuv3->vplanestride = srcinfo->stride2; break; default: @@ -1416,6 +1447,8 @@ enum bverror bv_blt(struct bvbltparams *bvbltparams) /* Extract the operation flags. */ op = (bvbltparams->flags & BVFLAG_OP_MASK) >> BVFLAG_OP_SHIFT; type = (bvbltparams->flags & BVFLAG_BATCH_MASK) >> BVFLAG_BATCH_SHIFT; + GCDBG(GCZONE_BLIT, "op = %d\n", op); + GCDBG(GCZONE_BLIT, "type = %d\n", type); switch (type) { case (BVFLAG_BATCH_NONE >> BVFLAG_BATCH_SHIFT): diff --git a/drivers/misc/gcx/gcbv/gcbv.h b/drivers/misc/gcx/gcbv/gcbv.h index bc82aec..90f956f 100644 --- a/drivers/misc/gcx/gcbv/gcbv.h +++ b/drivers/misc/gcx/gcbv/gcbv.h @@ -259,6 +259,8 @@ struct bvformatxlate { struct { unsigned int std; unsigned int planecount; + unsigned int xsample; + unsigned int ysample; } yuv; } cs; }; @@ -346,8 +348,13 @@ struct surfaceinfo { unsigned int physheight; /* Base address alignment. */ - int pixalign; + int xpixalign; + int ypixalign; int bytealign; + int bytealign2; + int bytealign3; + int stride2; + int stride3; /* Rotation angle. */ int angle; @@ -580,6 +587,7 @@ enum bverror set_blending_index(struct bvbltparams *bvbltparams, unsigned int index); /* Program YUV source. */ +void set_computeyuv(struct surfaceinfo *srcinfo, int x, int y); enum bverror set_yuvsrc(struct bvbltparams *bvbltparams, struct gcbatch *batch, struct surfaceinfo *srcinfo, diff --git a/drivers/misc/gcx/gcbv/gcfilter.c b/drivers/misc/gcx/gcbv/gcfilter.c index 427f6f9..1dd7a29 100644 --- a/drivers/misc/gcx/gcbv/gcfilter.c +++ b/drivers/misc/gcx/gcbv/gcfilter.c @@ -736,18 +736,20 @@ void process_rotation(struct bvbltparams *bvbltparams, switch (gcfilter->dstangle) { case ROT_ANGLE_0: /* Determine the origin offset. */ - dstoffsetX = dstinfo->pixalign; - dstoffsetY = 0; + dstoffsetX = dstinfo->xpixalign; + dstoffsetY = dstinfo->ypixalign; /* Determine geometry size. */ if (orthogonal) { batch->dstwidth = dstinfo->geom->height - - dstinfo->pixalign; - batch->dstheight = dstinfo->geom->width; + - dstinfo->xpixalign; + batch->dstheight = dstinfo->geom->width + - dstinfo->ypixalign; } else { batch->dstwidth = dstinfo->geom->width - - dstinfo->pixalign; - batch->dstheight = dstinfo->geom->height; + - dstinfo->xpixalign; + batch->dstheight = dstinfo->geom->height + - dstinfo->ypixalign; } /* Determine the physical size. */ @@ -757,29 +759,33 @@ void process_rotation(struct bvbltparams *bvbltparams, case ROT_ANGLE_90: /* Determine the origin offset. */ - dstoffsetX = 0; - dstoffsetY = dstinfo->pixalign; + dstoffsetX = dstinfo->ypixalign; + dstoffsetY = dstinfo->xpixalign; if (orthogonal) { /* Determine geometry size. */ - batch->dstwidth = dstinfo->geom->height; + batch->dstwidth = dstinfo->geom->height + - dstinfo->ypixalign; batch->dstheight = dstinfo->geom->width - - dstinfo->pixalign; + - dstinfo->xpixalign; /* Determine the physical size. */ - dstinfo->physwidth = dstinfo->geom->width - - dstinfo->pixalign; - dstinfo->physheight = dstinfo->geom->height; + dstinfo->physwidth = dstinfo->geom->width + - dstinfo->xpixalign; + dstinfo->physheight = dstinfo->geom->height + - dstinfo->ypixalign; } else { /* Determine geometry size. */ - batch->dstwidth = dstinfo->geom->width; + batch->dstwidth = dstinfo->geom->width + - dstinfo->ypixalign; batch->dstheight = dstinfo->geom->height - - dstinfo->pixalign; + - dstinfo->xpixalign; /* Determine the physical size. */ dstinfo->physwidth = dstinfo->geom->height - - dstinfo->pixalign; - dstinfo->physheight = dstinfo->geom->width; + - dstinfo->xpixalign; + dstinfo->physheight = dstinfo->geom->width + - dstinfo->ypixalign; } break; @@ -791,12 +797,14 @@ void process_rotation(struct bvbltparams *bvbltparams, /* Determine geometry size. */ if (orthogonal) { batch->dstwidth = dstinfo->geom->height - - dstinfo->pixalign; - batch->dstheight = dstinfo->geom->width; + - dstinfo->xpixalign; + batch->dstheight = dstinfo->geom->width + - dstinfo->ypixalign; } else { batch->dstwidth = dstinfo->geom->width - - dstinfo->pixalign; - batch->dstheight = dstinfo->geom->height; + - dstinfo->xpixalign; + batch->dstheight = dstinfo->geom->height + - dstinfo->ypixalign; } /* Determine the physical size. */ @@ -811,24 +819,28 @@ void process_rotation(struct bvbltparams *bvbltparams, if (orthogonal) { /* Determine geometry size. */ - batch->dstwidth = dstinfo->geom->height; + batch->dstwidth = dstinfo->geom->height + = dstinfo->ypixalign; batch->dstheight = dstinfo->geom->width - - dstinfo->pixalign; + - dstinfo->xpixalign; /* Determine the physical size. */ dstinfo->physwidth = dstinfo->geom->width - - dstinfo->pixalign; - dstinfo->physheight = dstinfo->geom->height; + - dstinfo->xpixalign; + dstinfo->physheight = dstinfo->geom->height + - dstinfo->ypixalign; } else { /* Determine geometry size. */ - batch->dstwidth = dstinfo->geom->width; + batch->dstwidth = dstinfo->geom->width + - dstinfo->ypixalign; batch->dstheight = dstinfo->geom->height - - dstinfo->pixalign; + - dstinfo->xpixalign; /* Determine the physical size. */ dstinfo->physwidth = dstinfo->geom->height - - dstinfo->pixalign; - dstinfo->physheight = dstinfo->geom->width; + - dstinfo->xpixalign; + dstinfo->physheight = dstinfo->geom->width + - dstinfo->ypixalign; } break; @@ -945,7 +957,8 @@ static enum bverror startvr(struct bvbltparams *bvbltparams, GCDBG(GCZONE_FILTER, "destination:\n"); GCDBG(GCZONE_FILTER, " angle = %d\n", dstangle); - GCDBG(GCZONE_FILTER, " pixalign = %d\n", dstinfo->pixalign); + GCDBG(GCZONE_FILTER, " pixalign = %d,%d\n", + dstinfo->xpixalign, dstinfo->ypixalign); GCDBG(GCZONE_FILTER, " bytealign = %d\n", dstinfo->bytealign); GCDBG(GCZONE_FILTER, " virtstride = %d\n", dstinfo->geom->virtstride); GCDBG(GCZONE_FILTER, " format = %d\n", dstinfo->format.format); @@ -986,13 +999,14 @@ static enum bverror startvr(struct bvbltparams *bvbltparams, /* Determine adjusted source bounding rectangle and origin. */ srcrect = srcinfo->rect; - srcrect.left -= srcinfo->pixalign; - srcrect.right -= srcinfo->pixalign; - srcx -= (srcinfo->pixalign << 16); + srcrect.left -= srcinfo->xpixalign; + srcrect.right -= srcinfo->xpixalign; + srcx -= (srcinfo->xpixalign << 16); GCDBG(GCZONE_FILTER, "source:\n"); GCDBG(GCZONE_FILTER, " angle = %d\n", srcangle); - GCDBG(GCZONE_FILTER, " pixalign = %d\n", srcinfo->pixalign); + GCDBG(GCZONE_FILTER, " pixalign = %d,%d\n", + srcinfo->xpixalign, srcinfo->ypixalign); GCDBG(GCZONE_FILTER, " bytealign = %d\n", srcinfo->bytealign); GCDBG(GCZONE_FILTER, " virtstride = %d\n", srcinfo->geom->virtstride); GCDBG(GCZONE_FILTER, " format = %d\n", srcinfo->format.format); @@ -1230,23 +1244,30 @@ enum bverror do_filter(struct bvbltparams *bvbltparams, /* Compute the source alignments needed to compensate * for the surface base address misalignment if any. */ - srcinfo->pixalign = get_pixel_offset(srcinfo, 0); - srcinfo->bytealign = (srcinfo->pixalign + srcinfo->xpixalign = get_pixel_offset(srcinfo, 0); + srcinfo->ypixalign = 0; + srcinfo->bytealign = (srcinfo->xpixalign * (int) srcinfo->format.bitspp) / 8; - GCDBG(GCZONE_SRC, "source surface offset (pixels) = %d,0\n", - srcinfo->pixalign); + GCDBG(GCZONE_SRC, "source surface offset (pixels) = %d,%d\n", + srcinfo->xpixalign, srcinfo->ypixalign); GCDBG(GCZONE_SRC, "source surface offset (bytes) = %d\n", srcinfo->bytealign); + /* Compute U/V plane offsets. */ + if (srcinfo->format.type == BVFMT_YUV) + set_computeyuv(srcinfo, 0, 0); + /* Determine physical size. */ if ((srcinfo->angle % 2) == 0) { srcinfo->physwidth = srcinfo->geom->width - - srcinfo->pixalign; - srcinfo->physheight = srcinfo->geom->height; + - srcinfo->xpixalign; + srcinfo->physheight = srcinfo->geom->height + - srcinfo->ypixalign; } else { srcinfo->physwidth = srcinfo->geom->height - - srcinfo->pixalign; - srcinfo->physheight = srcinfo->geom->width; + - srcinfo->xpixalign; + srcinfo->physheight = srcinfo->geom->width + - srcinfo->ypixalign; } GCDBG(GCZONE_SRC, "source physical size = %dx%d\n", srcinfo->physwidth, srcinfo->physheight); @@ -1587,16 +1608,17 @@ enum bverror do_filter(struct bvbltparams *bvbltparams, /* Compute the temp alignments needed to compensate * for the surface base address misalignment if any. */ - tmpinfo.pixalign = get_pixel_offset(&tmpinfo, 0); - tmpinfo.bytealign = (tmpinfo.pixalign + tmpinfo.xpixalign = get_pixel_offset(&tmpinfo, 0); + tmpinfo.ypixalign = 0; + tmpinfo.bytealign = (tmpinfo.xpixalign * (int) tmpinfo.format.bitspp) / 8; - GCDBG(GCZONE_SRC, "tmp offset (pixels) = %d,0\n", - tmpinfo.pixalign); + GCDBG(GCZONE_SRC, "tmp offset (pixels) = %d,%d\n", + tmpinfo.xpixalign, tmpinfo.ypixalign); GCDBG(GCZONE_SRC, "tmp offset (bytes) = %d\n", tmpinfo.bytealign); /* Adjust physical size. */ - tmpinfo.physwidth -= tmpinfo.pixalign; + tmpinfo.physwidth -= tmpinfo.xpixalign; GCDBG(GCZONE_FILTER, "tmp adjusted physical dims: %dx%d\n", tmpinfo.physwidth, tmpinfo.physheight); @@ -1637,8 +1659,8 @@ enum bverror do_filter(struct bvbltparams *bvbltparams, GCPRINT_RECT(GCZONE_DEST, "dest", &dstrotated0); /* Apply adjustment. */ - dstrotated0.left -= dstinfo->pixalign; - dstrotated0.right -= dstinfo->pixalign; + dstrotated0.left -= dstinfo->xpixalign; + dstrotated0.right -= dstinfo->xpixalign; /* Determine the source origin. */ srcx = ((leftextra + tmpinfo.rect.left) << 16) diff --git a/drivers/misc/gcx/gcbv/gcparser.c b/drivers/misc/gcx/gcbv/gcparser.c index 4759908..3ba401e 100644 --- a/drivers/misc/gcx/gcbv/gcparser.c +++ b/drivers/misc/gcx/gcbv/gcparser.c @@ -416,6 +416,8 @@ enum bverror parse_format(struct bvbltparams *bvbltparams, ? GCREG_PE_CONTROL_UV_SWIZZLE_VU : GCREG_PE_CONTROL_UV_SWIZZLE_UV; format->cs.yuv.planecount = 1; + format->cs.yuv.xsample = 2; + format->cs.yuv.ysample = 1; break; default: @@ -448,6 +450,8 @@ enum bverror parse_format(struct bvbltparams *bvbltparams, ? GCREG_PE_CONTROL_UV_SWIZZLE_VU : GCREG_PE_CONTROL_UV_SWIZZLE_UV; format->cs.yuv.planecount = 2; + format->cs.yuv.xsample = 2; + format->cs.yuv.ysample = 2; break; case OCDFMTDEF_3_PLANE_STACKED @@ -468,6 +472,8 @@ enum bverror parse_format(struct bvbltparams *bvbltparams, ? GCREG_PE_CONTROL_UV_SWIZZLE_VU : GCREG_PE_CONTROL_UV_SWIZZLE_UV; format->cs.yuv.planecount = 3; + format->cs.yuv.xsample = 2; + format->cs.yuv.ysample = 2; break; default: @@ -1264,12 +1270,35 @@ static inline int get_angle(int orientation) bool valid_rect(struct bvsurfgeom *bvsurfgeom, struct gcrect *gcrect) { - return ((gcrect->left >= 0) && - (gcrect->top >= 0) && - ((gcrect->right - gcrect->left) > 0) && - ((gcrect->bottom - gcrect->top) > 0) && - (gcrect->right <= (int) bvsurfgeom->width) && - (gcrect->bottom <= (int) bvsurfgeom->height)); + int width, height; + + if ((gcrect->left < 0) || (gcrect->top < 0)) { + GCERR("invalid rectangle origin: %d,%d.\n", + gcrect->left, gcrect->top); + return false; + } + + width = gcrect->right - gcrect->left; + height = gcrect->bottom - gcrect->top; + if ((width <= 0) || (height <= 0)) { + GCERR("invalid rectangle size: %d,%d.\n", + width, height); + return false; + } + + if (gcrect->right > (int) bvsurfgeom->width) { + GCERR("right coordinate (%d) exceeds surface width (%d).\n", + gcrect->right, bvsurfgeom->width); + return false; + } + + if (gcrect->bottom > (int) bvsurfgeom->height) { + GCERR("bottom coordinate (%d) exceeds surface height (%d).\n", + gcrect->bottom, bvsurfgeom->height); + return false; + } + + return true; } static bool valid_geom(struct surfaceinfo *surfaceinfo) @@ -1343,11 +1372,14 @@ int get_pixel_offset(struct surfaceinfo *surfaceinfo, int offset) * given offset. */ if (surfaceinfo->buf.desc->auxtype == BVAT_PHYSDESC) { struct bvphysdesc *bvphysdesc; - bvphysdesc = (struct bvphysdesc *) surfaceinfo->buf.desc->auxptr; - GCDBG(GCZONE_OFFSET, "physical descriptor @ 0x%08X\n", + GCDBG(GCZONE_OFFSET, "physical descriptor = 0x%08X\n", bvphysdesc); + GCDBG(GCZONE_OFFSET, "first page = 0x%08X\n", + bvphysdesc->pagearray[0]); + GCDBG(GCZONE_OFFSET, "page offset = 0x%08X\n", + bvphysdesc->pageoffset); byteoffset = bvphysdesc->pageoffset + offset; } else { @@ -1365,7 +1397,7 @@ int get_pixel_offset(struct surfaceinfo *surfaceinfo, int offset) pixeloffset = alignedoffset * 8 / surfaceinfo->format.bitspp; GCDBG(GCZONE_OFFSET, "alignedoffset = %d\n", alignedoffset); - GCDBG(GCZONE_OFFSET, "pixeloffset = %d\n", pixeloffset); + GCDBG(GCZONE_OFFSET, "pixeloffset = %d\n", -pixeloffset); GCEXIT(GCZONE_OFFSET); return -pixeloffset; @@ -1412,8 +1444,9 @@ enum bverror parse_destination(struct bvbltparams *bvbltparams, /* Compute the destination alignments needed to compensate * for the surface base address misalignment if any. */ - dstinfo->pixalign = get_pixel_offset(dstinfo, 0); - dstinfo->bytealign = (dstinfo->pixalign + dstinfo->xpixalign = get_pixel_offset(dstinfo, 0); + dstinfo->ypixalign = 0; + dstinfo->bytealign = (dstinfo->xpixalign * (int) dstinfo->format.bitspp) / 8; GCDBG(GCZONE_DEST, " buffer length = %d\n", @@ -1425,6 +1458,10 @@ enum bverror parse_destination(struct bvbltparams *bvbltparams, struct bvphysdesc *bvphysdesc; bvphysdesc = (struct bvphysdesc *) dstinfo->buf.desc->auxptr; + GCDBG(GCZONE_DEST, " physical descriptor = 0x%08X\n", + bvphysdesc); + GCDBG(GCZONE_DEST, " first page = 0x%08X\n", + bvphysdesc->pagearray[0]); GCDBG(GCZONE_DEST, " page offset = 0x%08X\n", bvphysdesc->pageoffset); } else { @@ -1436,8 +1473,8 @@ enum bverror parse_destination(struct bvbltparams *bvbltparams, dstinfo->geom->virtstride); GCDBG(GCZONE_DEST, " geometry size = %dx%d\n", dstinfo->geom->width, dstinfo->geom->height); - GCDBG(GCZONE_DEST, " surface offset (pixels) = %d,0\n", - dstinfo->pixalign); + GCDBG(GCZONE_DEST, " surface offset (pixels) = %d,%d\n", + dstinfo->xpixalign, dstinfo->ypixalign); GCDBG(GCZONE_DEST, " surface offset (bytes) = %d\n", dstinfo->bytealign); @@ -1597,7 +1634,7 @@ enum bverror parse_destination(struct bvbltparams *bvbltparams, &batch->dstclippedaux); } - GCPRINT_RECT(GCZONE_DEST, " clipped rect", + GCPRINT_RECT(GCZONE_DEST, " clipped dest", &batch->dstclipped); /* Validate the destination rectangle. */ @@ -1608,7 +1645,7 @@ enum bverror parse_destination(struct bvbltparams *bvbltparams, } if (batch->haveaux) { - GCPRINT_RECT(GCZONE_DEST, " clipped aux rect", + GCPRINT_RECT(GCZONE_DEST, " clipped aux dest", &batch->dstclippedaux); /* Validate the aux destination rectangle. */ @@ -1652,13 +1689,14 @@ void process_dest_rotation(struct bvbltparams *bvbltparams, switch (dstinfo->angle) { case ROT_ANGLE_0: /* Determine the origin offset. */ - dstoffsetX = dstinfo->pixalign; - dstoffsetY = 0; + dstoffsetX = dstinfo->xpixalign; + dstoffsetY = dstinfo->ypixalign; /* Determine geometry size. */ batch->dstwidth = dstinfo->geom->width - - dstinfo->pixalign; - batch->dstheight = dstinfo->geom->height; + - dstinfo->xpixalign; + batch->dstheight = dstinfo->geom->height + - dstinfo->ypixalign; /* Determine the physical size. */ dstinfo->physwidth = batch->dstwidth; @@ -1667,18 +1705,20 @@ void process_dest_rotation(struct bvbltparams *bvbltparams, case ROT_ANGLE_90: /* Determine the origin offset. */ - dstoffsetX = 0; - dstoffsetY = dstinfo->pixalign; + dstoffsetX = dstinfo->ypixalign; + dstoffsetY = dstinfo->xpixalign; /* Determine geometry size. */ - batch->dstwidth = dstinfo->geom->width; + batch->dstwidth = dstinfo->geom->width + - dstinfo->ypixalign; batch->dstheight = dstinfo->geom->height - - dstinfo->pixalign; + - dstinfo->xpixalign; /* Determine the physical size. */ dstinfo->physwidth = dstinfo->geom->height - - dstinfo->pixalign; - dstinfo->physheight = dstinfo->geom->width; + - dstinfo->xpixalign; + dstinfo->physheight = dstinfo->geom->width + - dstinfo->ypixalign; break; case ROT_ANGLE_180: @@ -1688,8 +1728,9 @@ void process_dest_rotation(struct bvbltparams *bvbltparams, /* Determine geometry size. */ batch->dstwidth = dstinfo->geom->width - - dstinfo->pixalign; - batch->dstheight = dstinfo->geom->height; + - dstinfo->xpixalign; + batch->dstheight = dstinfo->geom->height + - dstinfo->ypixalign; /* Determine the physical size. */ dstinfo->physwidth = batch->dstwidth; @@ -1702,14 +1743,16 @@ void process_dest_rotation(struct bvbltparams *bvbltparams, dstoffsetY = 0; /* Determine geometry size. */ - batch->dstwidth = dstinfo->geom->width; + batch->dstwidth = dstinfo->geom->width + - dstinfo->ypixalign; batch->dstheight = dstinfo->geom->height - - dstinfo->pixalign; + - dstinfo->xpixalign; /* Determine the physical size. */ dstinfo->physwidth = dstinfo->geom->height - - dstinfo->pixalign; - dstinfo->physheight = dstinfo->geom->width; + - dstinfo->xpixalign; + dstinfo->physheight = dstinfo->geom->width + - dstinfo->ypixalign; break; default: @@ -1752,6 +1795,7 @@ enum bverror parse_source(struct bvbltparams *bvbltparams, { enum bverror bverror = BVERR_NONE; + GCENTER(GCZONE_SRC); GCDBG(GCZONE_SRC, "parsing source #%d\n", srcinfo->index + 1); @@ -1788,8 +1832,12 @@ enum bverror parse_source(struct bvbltparams *bvbltparams, if (srcinfo->buf.desc->auxtype == BVAT_PHYSDESC) { struct bvphysdesc *bvphysdesc; bvphysdesc = (struct bvphysdesc *) srcinfo->buf.desc->auxptr; + GCDBG(GCZONE_SRC, " physical descriptor = 0x%08X\n", + bvphysdesc); + GCDBG(GCZONE_SRC, " first page = 0x%08X\n", + bvphysdesc->pagearray[0]); GCDBG(GCZONE_SRC, " page offset = 0x%08X\n", - bvphysdesc->pageoffset); + bvphysdesc->pageoffset); } else { GCDBG(GCZONE_SRC, " virtual address = 0x%08X\n", (unsigned int) srcinfo->buf.desc->virtaddr); @@ -1818,7 +1866,7 @@ enum bverror parse_source(struct bvbltparams *bvbltparams, /* Planar YUV? */ if ((srcinfo->format.type == BVFMT_YUV) && (srcinfo->format.cs.yuv.planecount > 1)) { - int pixalign; + int xpixalign; /* Source rotation is not supported. */ if (srcinfo->angle != ROT_ANGLE_0) { @@ -1831,8 +1879,8 @@ enum bverror parse_source(struct bvbltparams *bvbltparams, } /* Check base address alignment. */ - pixalign = get_pixel_offset(srcinfo, 0); - if (pixalign != 0) { + xpixalign = get_pixel_offset(srcinfo, 0); + if (xpixalign != 0) { BVSETBLTERROR((srcinfo->index == 0) ? BVERR_SRC1DESC_ALIGNMENT : BVERR_SRC2DESC_ALIGNMENT, @@ -1853,6 +1901,8 @@ enum bverror parse_source(struct bvbltparams *bvbltparams, } exit: + GCEXITARG(GCZONE_SRC, "bv%s = %d\n", + (bverror == BVERR_NONE) ? "result" : "error", bverror); return bverror; } |