diff options
Diffstat (limited to 'bltsville/gcbv/mirror/gcfilter.c')
-rw-r--r-- | bltsville/gcbv/mirror/gcfilter.c | 1788 |
1 files changed, 0 insertions, 1788 deletions
diff --git a/bltsville/gcbv/mirror/gcfilter.c b/bltsville/gcbv/mirror/gcfilter.c deleted file mode 100644 index 525e242..0000000 --- a/bltsville/gcbv/mirror/gcfilter.c +++ /dev/null @@ -1,1788 +0,0 @@ -/* - * Copyright(c) 2012, - * Texas Instruments, Inc. and Vivante Corporation. - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Vivante Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include "gcbv.h" - -#define GCZONE_NONE 0 -#define GCZONE_ALL (~0U) -#define GCZONE_KERNEL (1 << 0) -#define GCZONE_FILTER (1 << 1) -#define GCZONE_BLEND (1 << 2) -#define GCZONE_TYPE (1 << 3) -#define GCZONE_SRC (1 << 4) -#define GCZONE_DEST (1 << 5) -#define GCZONE_SURF (1 << 6) - -GCDBG_FILTERDEF(filter, GCZONE_NONE, - "kernel", - "filter", - "blend", - "type", - "src", - "dest", - "surf") - - -/******************************************************************************* - * Miscellaneous defines. - */ - -#define GC_BYTES_PER_CACHELINE (64) -#define GC_BITS_PER_CACHELINE (GC_BYTES_PER_CACHELINE * 8) -#define GC_CACHELINE_ALIGN_16 (GC_BITS_PER_CACHELINE / 16 - 1) -#define GC_CACHELINE_ALIGN_32 (GC_BITS_PER_CACHELINE / 32 - 1) - -enum gcscaletype { - GC_SCALE_OPF, - GC_SCALE_HOR, - GC_SCALE_VER, - GC_SCALE_HOR_FLIPPED, - GC_SCALE_VER_FLIPPED -}; - -/******************************************************************************* - * Scale factor format: unsigned 1.31 fixed point. - */ - -#define GC_SCALE_TYPE unsigned int -#define GC_SCALE_FRACTION 31 -#define GC_SCALE_ONE ((GC_SCALE_TYPE) (1 << GC_SCALE_FRACTION)) - - -/******************************************************************************* - * X coordinate format: signed 4.28 fixed point. - */ - -#define GC_COORD_TYPE int -#define GC_COORD_FRACTION 28 -#define GC_COORD_PI ((GC_COORD_TYPE) 0x3243F6C0) -#define GC_COORD_2OVERPI ((GC_COORD_TYPE) 0x0A2F9832) -#define GC_COORD_PIOVER2 ((GC_COORD_TYPE) 0x1921FB60) -#define GC_COORD_ZERO ((GC_COORD_TYPE) 0) -#define GC_COORD_HALF ((GC_COORD_TYPE) (1 << (GC_COORD_FRACTION - 1))) -#define GC_COORD_ONE ((GC_COORD_TYPE) (1 << GC_COORD_FRACTION)) -#define GC_COORD_NEGONE ((GC_COORD_TYPE) (~GC_COORD_ONE + 1)) -#define GC_COORD_SUBPIX_STEP ((GC_COORD_TYPE) \ - (1 << (GC_COORD_FRACTION - GC_PHASE_BITS))) - - -/******************************************************************************* - * Hardware coefficient format: signed 2.14 fixed point. - */ - -#define GC_COEF_TYPE short -#define GC_COEF_FRACTION 14 -#define GC_COEF_ZERO ((GC_COEF_TYPE) 0) -#define GC_COEF_ONE ((GC_COEF_TYPE) (1 << GC_COEF_FRACTION)) -#define GC_COEF_NEGONE ((GC_COEF_TYPE) (~GC_COEF_ONE + 1)) - - -/******************************************************************************* - * Weight sum format: x.28 fixed point. - */ - -#define GC_SUM_TYPE long long -#define GC_SUM_FRACTION GC_COORD_FRACTION - - -/******************************************************************************* - * Math shortcuts. - */ - -#define computescale(dstsize, srcsize) ((GC_SCALE_TYPE) \ - div_u64(((u64) (dstsize)) << GC_SCALE_FRACTION, (srcsize)) \ -) - -#define normweight(weight, sum) ((GC_COORD_TYPE) \ - div64_s64(((s64) (weight)) << GC_COORD_FRACTION, (sum)) \ -) - -#define convertweight(weight) ((GC_COEF_TYPE) \ - ((weight) >> (GC_COORD_FRACTION - GC_COEF_FRACTION)) \ -) - - -/******************************************************************************* - * Fixed point SINE function. Takes a positive value in range [0..pi/2]. - */ - -static GC_COORD_TYPE sine(GC_COORD_TYPE x) -{ - static const GC_COORD_TYPE sinetable[] = { - 0x00000000, 0x001FFFEB, 0x003FFF55, 0x005FFDC0, - 0x007FFAAB, 0x009FF596, 0x00BFEE01, 0x00DFE36C, - 0x00FFD557, 0x011FC344, 0x013FACB2, 0x015F9120, - 0x017F7010, 0x019F4902, 0x01BF1B78, 0x01DEE6F2, - 0x01FEAAEE, 0x021E66F0, 0x023E1A7C, 0x025DC50C, - 0x027D6624, 0x029CFD48, 0x02BC89F8, 0x02DC0BB8, - 0x02FB8204, 0x031AEC64, 0x033A4A5C, 0x03599B64, - 0x0378DF08, 0x039814CC, 0x03B73C2C, 0x03D654B0, - 0x03F55DDC, 0x04145730, 0x04334030, 0x04521868, - 0x0470DF58, 0x048F9488, 0x04AE3770, 0x04CCC7A8, - 0x04EB44A8, 0x0509ADF8, 0x05280328, 0x054643B0, - 0x05646F28, 0x05828508, 0x05A084E0, 0x05BE6E38, - 0x05DC4098, 0x05F9FB80, 0x06179E88, 0x06352928, - 0x06529AF8, 0x066FF380, 0x068D3248, 0x06AA56D8, - 0x06C760C0, 0x06E44F90, 0x070122C8, 0x071DD9F8, - 0x073A74B8, 0x0756F290, 0x07735308, 0x078F95B0, - 0x07ABBA20, 0x07C7BFD8, 0x07E3A678, 0x07FF6D88, - 0x081B14A0, 0x08369B40, 0x08520110, 0x086D4590, - 0x08886860, 0x08A36910, 0x08BE4730, 0x08D90250, - 0x08F39A20, 0x090E0E10, 0x09285DD0, 0x094288E0, - 0x095C8EF0, 0x09766F90, 0x09902A60, 0x09A9BEE0, - 0x09C32CC0, 0x09DC7390, 0x09F592F0, 0x0A0E8A70, - 0x0A2759C0, 0x0A400070, 0x0A587E20, 0x0A70D270, - 0x0A88FD00, 0x0AA0FD60, 0x0AB8D350, 0x0AD07E50, - 0x0AE7FE10, 0x0AFF5230, 0x0B167A50, 0x0B2D7610, - 0x0B444520, 0x0B5AE730, 0x0B715BC0, 0x0B87A290, - 0x0B9DBB40, 0x0BB3A580, 0x0BC960F0, 0x0BDEED30, - 0x0BF44A00, 0x0C0976F0, 0x0C1E73D0, 0x0C334020, - 0x0C47DBB0, 0x0C5C4620, 0x0C707F20, 0x0C848660, - 0x0C985B80, 0x0CABFE50, 0x0CBF6E60, 0x0CD2AB80, - 0x0CE5B550, 0x0CF88B80, 0x0D0B2DE0, 0x0D1D9C10, - 0x0D2FD5C0, 0x0D41DAB0, 0x0D53AAA0, 0x0D654540, - 0x0D76AA40, 0x0D87D970, 0x0D98D280, 0x0DA99530, - 0x0DBA2140, 0x0DCA7650, 0x0DDA9450, 0x0DEA7AD0, - 0x0DFA29B0, 0x0E09A0B0, 0x0E18DF80, 0x0E27E5F0, - 0x0E36B3C0, 0x0E4548B0, 0x0E53A490, 0x0E61C720, - 0x0E6FB020, 0x0E7D5F70, 0x0E8AD4C0, 0x0E980FF0, - 0x0EA510B0, 0x0EB1D6F0, 0x0EBE6260, 0x0ECAB2D0, - 0x0ED6C810, 0x0EE2A200, 0x0EEE4070, 0x0EF9A310, - 0x0F04C9E0, 0x0F0FB490, 0x0F1A6300, 0x0F24D510, - 0x0F2F0A80, 0x0F390340, 0x0F42BF10, 0x0F4C3DE0, - 0x0F557F70, 0x0F5E83C0, 0x0F674A80, 0x0F6FD3B0, - 0x0F781F20, 0x0F802CB0, 0x0F87FC40, 0x0F8F8DA0, - 0x0F96E0D0, 0x0F9DF5B0, 0x0FA4CC00, 0x0FAB63D0, - 0x0FB1BCF0, 0x0FB7D740, 0x0FBDB2B0, 0x0FC34F30, - 0x0FC8ACA0, 0x0FCDCAF0, 0x0FD2AA10, 0x0FD749E0, - 0x0FDBAA50, 0x0FDFCB50, 0x0FE3ACD0, 0x0FE74EC0, - 0x0FEAB110, 0x0FEDD3C0, 0x0FF0B6B0, 0x0FF359F0, - 0x0FF5BD50, 0x0FF7E0E0, 0x0FF9C490, 0x0FFB6850, - 0x0FFCCC30, 0x0FFDF010, 0x0FFED400, 0x0FFF77F0, - 0x0FFFDBF0, 0x0FFFFFE0, 0x0FFFE3D0, 0x0FFF87D0, - 0x0FFEEBC0, 0x0FFE0FC0, 0x0FFCF3D0, 0x0FFB97E0 - }; - - enum { - indexwidth = 8, - intwidth = 1, - indexshift = intwidth - + GC_COORD_FRACTION - - indexwidth - }; - - unsigned int p1, p2; - GC_COORD_TYPE p1x, p2x; - GC_COORD_TYPE p1y, p2y; - GC_COORD_TYPE dx, dy; - GC_COORD_TYPE a, b; - GC_COORD_TYPE result; - - /* Determine the indices of two closest points in the table. */ - p1 = ((unsigned int) x) >> indexshift; - p2 = p1 + 1; - - if ((p1 >= countof(sinetable)) || (p2 >= countof(sinetable))) { - GCERR("invalid table index.\n"); - return GC_COORD_ZERO; - } - - /* Determine the coordinates of the two closest points. */ - p1x = p1 << indexshift; - p2x = p2 << indexshift; - - p1y = sinetable[p1]; - p2y = sinetable[p2]; - - /* Determine the deltas. */ - dx = p2x - p1x; - dy = p2y - p1y; - - /* Find the slope and the y-intercept. */ - b = (GC_COORD_TYPE) div64_s64(((s64) dy) << GC_COORD_FRACTION, dx); - a = p1y - (GC_COORD_TYPE) (((s64) b * p1x) >> GC_COORD_FRACTION); - - /* Compute the result. */ - result = a + (GC_COORD_TYPE) (((s64) b * x) >> GC_COORD_FRACTION); - return result; -} - - -/******************************************************************************* - * SINC function used in filter kernel generation. - */ - -static GC_COORD_TYPE sinc_filter(GC_COORD_TYPE x, int radius) -{ - GC_COORD_TYPE result; - s64 radius64; - s64 pit, pitd; - s64 normpit, normpitd; - int negpit, negpitd; - int quadpit, quadpitd; - GC_COORD_TYPE sinpit, sinpitd; - GC_COORD_TYPE f1, f2; - - if (x == GC_COORD_ZERO) - return GC_COORD_ONE; - - radius64 = abs(radius) << GC_COORD_FRACTION; - if (x > radius64) - return GC_COORD_ZERO; - - pit = (((s64) GC_COORD_PI) * x) >> GC_COORD_FRACTION; - pitd = div_s64(pit, radius); - - /* Sine table only has values for the first positive quadrant, - * remove the sign here. */ - if (pit < 0) { - normpit = -pit; - negpit = 1; - } else { - normpit = pit; - negpit = 0; - } - - if (pitd < 0) { - normpitd = -pitd; - negpitd = 1; - } else { - normpitd = pitd; - negpitd = 0; - } - - /* Determine which quadrant we are in. */ - quadpit = (int) ((normpit * GC_COORD_2OVERPI) - >> (2 * GC_COORD_FRACTION)); - quadpitd = (int) ((normpitd * GC_COORD_2OVERPI) - >> (2 * GC_COORD_FRACTION)); - - /* Move coordinates to the first quadrant. */ - normpit -= (s64) GC_COORD_PIOVER2 * quadpit; - normpitd -= (s64) GC_COORD_PIOVER2 * quadpitd; - - /* Normalize the quadrant numbers. */ - quadpit %= 4; - quadpitd %= 4; - - /* Flip the coordinates if necessary. */ - if ((quadpit == 1) || (quadpit == 3)) - normpit = GC_COORD_PIOVER2 - normpit; - - if ((quadpitd == 1) || (quadpitd == 3)) - normpitd = GC_COORD_PIOVER2 - normpitd; - - sinpit = sine((GC_COORD_TYPE) normpit); - sinpitd = sine((GC_COORD_TYPE) normpitd); - - /* Negate depending on the quadrant. */ - if (negpit) { - if ((quadpit == 0) || (quadpit == 1)) - sinpit = -sinpit; - } else { - if ((quadpit == 2) || (quadpit == 3)) - sinpit = -sinpit; - } - - if (negpitd) { - if ((quadpitd == 0) || (quadpitd == 1)) - sinpitd = -sinpitd; - } else { - if ((quadpitd == 2) || (quadpitd == 3)) - sinpitd = -sinpitd; - } - - f1 = (GC_COORD_TYPE) - div64_s64(((s64) sinpit) << GC_COORD_FRACTION, pit); - f2 = (GC_COORD_TYPE) - div64_s64(((s64) sinpitd) << GC_COORD_FRACTION, pitd); - - result = (GC_COORD_TYPE) ((((s64) f1) * f2) - >> GC_COORD_FRACTION); - - return result; -} - - -/******************************************************************************* - * Filter kernel generator based on SINC function. - */ - -static void calculate_sync_filter(struct gcfilterkernel *gcfilterkernel) -{ - GC_SCALE_TYPE scale; - GC_COORD_TYPE subpixset[GC_TAP_COUNT]; - GC_COORD_TYPE subpixeloffset; - GC_COORD_TYPE x, weight; - GC_SUM_TYPE weightsum; - short convweightsum; - int kernelhalf, padding; - int subpixpos, kernelpos; - short *kernelarray; - short count, adjustfrom, adjustment; - int index; - - /* Compute the scale factor. */ - scale = (gcfilterkernel->dstsize >= gcfilterkernel->srcsize) - ? GC_SCALE_ONE - : computescale(gcfilterkernel->dstsize, gcfilterkernel->srcsize); - - /* Calculate the kernel half. */ - kernelhalf = (int) (gcfilterkernel->kernelsize >> 1); - - /* Init the subpixel offset. */ - subpixeloffset = GC_COORD_HALF; - - /* Determine kernel padding size. */ - padding = (GC_TAP_COUNT - gcfilterkernel->kernelsize) / 2; - - /* Set initial kernel array pointer. */ - kernelarray = gcfilterkernel->kernelarray; - - /* Loop through each subpixel. */ - for (subpixpos = 0; subpixpos < GC_PHASE_LOAD_COUNT; subpixpos += 1) { - /* Compute weights. */ - weightsum = GC_COORD_ZERO; - for (kernelpos = 0; kernelpos < GC_TAP_COUNT; kernelpos += 1) { - /* Determine the current index. */ - index = kernelpos - padding; - - /* Pad with zeros left side. */ - if (index < 0) { - subpixset[kernelpos] = GC_COORD_ZERO; - continue; - } - - /* Pad with zeros right side. */ - if (index >= (int) gcfilterkernel->kernelsize) { - subpixset[kernelpos] = GC_COORD_ZERO; - continue; - } - - /* "Filter off" case. */ - if (gcfilterkernel->kernelsize == 1) { - subpixset[kernelpos] = GC_COORD_ONE; - - /* Update the sum of the weights. */ - weightsum += GC_COORD_ONE; - continue; - } - - /* Compute X coordinate. */ - x = ((index - kernelhalf) << GC_COORD_FRACTION) - + subpixeloffset; - - /* Scale the coordinate. */ - x = (GC_COORD_TYPE) - ((((s64) x) * scale) >> GC_SCALE_FRACTION); - - /* Compute the weight. */ - subpixset[kernelpos] = sinc_filter(x, kernelhalf); - - /* Update the sum of the weights. */ - weightsum += subpixset[kernelpos]; - } - - /* Convert the weights to the hardware format. */ - convweightsum = 0; - for (kernelpos = 0; kernelpos < GC_TAP_COUNT; kernelpos += 1) { - /* Normalize the current weight. */ - weight = normweight(subpixset[kernelpos], weightsum); - - /* Convert the weight to fixed point. */ - if (weight == GC_COORD_ZERO) - kernelarray[kernelpos] = GC_COEF_ZERO; - else if (weight >= GC_COORD_ONE) - kernelarray[kernelpos] = GC_COEF_ONE; - else if (weight <= GC_COORD_NEGONE) - kernelarray[kernelpos] = GC_COEF_NEGONE; - else - kernelarray[kernelpos] = convertweight(weight); - - /* Compute the sum of all coefficients. */ - convweightsum += kernelarray[kernelpos]; - } - - /* Adjust the fixed point coefficients so that the sum is 1. */ - count = GC_COEF_ONE - convweightsum; - if (count < 0) { - count = -count; - adjustment = -1; - } else { - adjustment = 1; - } - - if (count > GC_TAP_COUNT) { - GCERR("adjust count is too high = %d\n", count); - } else { - adjustfrom = (GC_TAP_COUNT - count) / 2; - for (kernelpos = 0; kernelpos < count; kernelpos += 1) - kernelarray[adjustfrom + kernelpos] - += adjustment; - } - - /* Advance the array pointer. */ - kernelarray += GC_TAP_COUNT; - - /* Advance to the next subpixel. */ - subpixeloffset -= GC_COORD_SUBPIX_STEP; - } -} - - -/******************************************************************************* - * Loads a filter into the GPU. - */ - -static enum bverror load_filter(struct bvbltparams *bvbltparams, - struct gcbatch *batch, - enum gcfiltertype type, - unsigned int kernelsize, - unsigned int scalefactor, - unsigned int srcsize, - unsigned int dstsize, - struct gccmdldstate arraystate) -{ - enum bverror bverror = BVERR_NONE; - struct gccontext *gccontext = get_context(); - struct gcfiltercache *filtercache; - struct list_head *filterlist; - struct list_head *filterhead; - struct gcfilterkernel *gcfilterkernel; - struct gcmofilterkernel *gcmofilterkernel; - - GCDBG(GCZONE_KERNEL, "kernelsize = %d\n", kernelsize); - GCDBG(GCZONE_KERNEL, "srcsize = %d\n", srcsize); - GCDBG(GCZONE_KERNEL, "dstsize = %d\n", dstsize); - GCDBG(GCZONE_KERNEL, "scalefactor = 0x%08X\n", scalefactor); - - /* Is the filter already loaded? */ - if ((gccontext->loadedfilter != NULL) && - (gccontext->loadedfilter->type == type) && - (gccontext->loadedfilter->kernelsize == kernelsize) && - (gccontext->loadedfilter->scalefactor == scalefactor)) { - GCDBG(GCZONE_KERNEL, "filter already computed.\n"); - gcfilterkernel = gccontext->loadedfilter; - goto load; - } - - /* Get the proper filter cache. */ - filtercache = &gccontext->filtercache[type][kernelsize]; - filterlist = &filtercache->list; - - /* Try to find existing filter. */ - GCDBG(GCZONE_KERNEL, "scanning for existing filter.\n"); - list_for_each(filterhead, filterlist) { - gcfilterkernel = list_entry(filterhead, - struct gcfilterkernel, - link); - if (gcfilterkernel->scalefactor == scalefactor) { - GCDBG(GCZONE_KERNEL, "filter found @ 0x%08X.\n", - (unsigned int) gcfilterkernel); - break; - } - } - - /* Found the filter? */ - if (filterhead != filterlist) { - /* Move the filter to the head of the list. */ - if (filterlist->next != filterhead) { - GCDBG(GCZONE_KERNEL, "moving to the head.\n"); - list_move(filterhead, filterlist); - } - } else { - GCDBG(GCZONE_KERNEL, "filter not found.\n"); - if (filtercache->count == GC_FILTER_CACHE_MAX) { - GCDBG(GCZONE_KERNEL, - "reached the maximum number of filters.\n"); - filterhead = filterlist->prev; - list_move(filterhead, filterlist); - - gcfilterkernel = list_entry(filterhead, - struct gcfilterkernel, - link); - } else { - GCDBG(GCZONE_KERNEL, "allocating new filter.\n"); - gcfilterkernel = gcalloc(struct gcfilterkernel, - sizeof(struct gcfilterkernel)); - if (gcfilterkernel == NULL) { - BVSETBLTERROR(BVERR_OOM, - "filter allocation failed"); - goto exit; - } - - list_add(&gcfilterkernel->link, filterlist); - } - - /* Update the number of filters. */ - filtercache->count += 1; - - /* Initialize the filter. */ - gcfilterkernel->type = type; - gcfilterkernel->kernelsize = kernelsize; - gcfilterkernel->srcsize = srcsize; - gcfilterkernel->dstsize = dstsize; - gcfilterkernel->scalefactor = scalefactor; - - /* Compute the coefficients. */ - calculate_sync_filter(gcfilterkernel); - } - -load: - GCDBG(GCZONE_KERNEL, "loading filter.\n"); - - /* Load the filter. */ - bverror = claim_buffer(bvbltparams, batch, - sizeof(struct gcmofilterkernel), - (void **) &gcmofilterkernel); - if (bverror != BVERR_NONE) - goto exit; - - gcmofilterkernel->kernelarray_ldst = arraystate; - memcpy(&gcmofilterkernel->kernelarray, - gcfilterkernel->kernelarray, - sizeof(gcfilterkernel->kernelarray)); - - /* Set the filter. */ - gccontext->loadedfilter = gcfilterkernel; - -exit: - return bverror; -} - - -/******************************************************************************* - * Compute the scale factor. - */ - -static inline unsigned int get_scale_factor(unsigned int srcsize, - unsigned int dstsize) -{ - if ((srcsize <= 1) || (dstsize <= 1)) - return 0; - - return ((srcsize - 1) << 16) / (dstsize - 1); -} - - -/******************************************************************************* - * Rotates the specified rectangle to the specified angle. - */ - -static void rotate_gcrect(int angle, - struct bvsurfgeom *srcgeom, struct gcrect *srcrect, - struct bvsurfgeom *dstgeom, struct gcrect *dstrect) -{ - unsigned int width, height; - struct gcrect rect; - - GCENTER(GCZONE_SURF); - - GCDBG(GCZONE_SURF, "src geom size = %dx%d\n", - srcgeom->width, srcgeom->height); - - switch (angle) { - case ROT_ANGLE_0: - GCDBG(GCZONE_SURF, "ROT_ANGLE_0\n"); - - if (dstgeom != srcgeom) { - dstgeom->width = srcgeom->width; - dstgeom->height = srcgeom->height; - } - - if (dstrect != srcrect) - *dstrect = *srcrect; - break; - - case ROT_ANGLE_90: - GCDBG(GCZONE_SURF, "ROT_ANGLE_90\n"); - - width = srcgeom->width; - height = srcgeom->height; - - dstgeom->width = height; - dstgeom->height = width; - - rect.left = height - srcrect->bottom; - rect.top = srcrect->left; - rect.right = height - srcrect->top; - rect.bottom = srcrect->right; - - *dstrect = rect; - break; - - case ROT_ANGLE_180: - GCDBG(GCZONE_SURF, "ROT_ANGLE_180\n"); - - width = srcgeom->width; - height = srcgeom->height; - - if (dstgeom != srcgeom) { - dstgeom->width = width; - dstgeom->height = height; - } - - rect.left = width - srcrect->right; - rect.top = height - srcrect->bottom; - rect.right = width - srcrect->left; - rect.bottom = height - srcrect->top; - - *dstrect = rect; - break; - - case ROT_ANGLE_270: - GCDBG(GCZONE_SURF, "ROT_ANGLE_270\n"); - - width = srcgeom->width; - height = srcgeom->height; - - dstgeom->width = height; - dstgeom->height = width; - - rect.left = srcrect->top; - rect.top = width - srcrect->right; - rect.right = srcrect->bottom; - rect.bottom = width - srcrect->left; - - *dstrect = rect; - break; - } - - GCEXIT(GCZONE_SURF); -} - - -/******************************************************************************* - * Setup destination rotation parameters. - */ - -void process_rotation(struct bvbltparams *bvbltparams, - struct gcbatch *batch, - struct surfaceinfo *srcinfo, - int adjangle) -{ - GCENTER(GCZONE_DEST); - - if (srcinfo->newgeom || - ((batch->batchflags & (BVBATCH_CLIPRECT | - BVBATCH_DESTRECT | - BVBATCH_DST)) != 0)) { - bool orthogonal; - struct gcfilter *gcfilter; - struct surfaceinfo *dstinfo; - int dstoffsetX, dstoffsetY; - - /* Get some shortcuts. */ - dstinfo = &batch->dstinfo; - gcfilter = &batch->op.filter; - - /* Compute the adjusted destination angle. */ - gcfilter->dstangle - = (dstinfo->angle + (4 - srcinfo->angle)) % 4; - GCDBG(GCZONE_DEST, "dstangle = %d\n", gcfilter->dstangle); - - /* Determine whether the new and the old destination angles - * are orthogonal to each other. */ - orthogonal = (gcfilter->dstangle % 2) != (dstinfo->angle % 2); - - switch (gcfilter->dstangle) { - case ROT_ANGLE_0: - /* Determine the origin offset. */ - dstoffsetX = dstinfo->xpixalign; - dstoffsetY = dstinfo->ypixalign; - - /* Determine geometry size. */ - if (orthogonal) { - batch->dstwidth = dstinfo->geom->height - - dstinfo->xpixalign; - batch->dstheight = dstinfo->geom->width - - dstinfo->ypixalign; - } else { - batch->dstwidth = dstinfo->geom->width - - dstinfo->xpixalign; - batch->dstheight = dstinfo->geom->height - - dstinfo->ypixalign; - } - - /* Determine the physical size. */ - dstinfo->physwidth = batch->dstwidth; - dstinfo->physheight = batch->dstheight; - break; - - case ROT_ANGLE_90: - /* Determine the origin offset. */ - dstoffsetX = dstinfo->ypixalign; - dstoffsetY = dstinfo->xpixalign; - - if (orthogonal) { - /* Determine geometry size. */ - batch->dstwidth = dstinfo->geom->height - - dstinfo->ypixalign; - batch->dstheight = dstinfo->geom->width - - dstinfo->xpixalign; - - /* Determine the physical size. */ - dstinfo->physwidth = dstinfo->geom->width - - dstinfo->xpixalign; - dstinfo->physheight = dstinfo->geom->height - - dstinfo->ypixalign; - } else { - /* Determine geometry size. */ - batch->dstwidth = dstinfo->geom->width - - dstinfo->ypixalign; - batch->dstheight = dstinfo->geom->height - - dstinfo->xpixalign; - - /* Determine the physical size. */ - dstinfo->physwidth = dstinfo->geom->height - - dstinfo->xpixalign; - dstinfo->physheight = dstinfo->geom->width - - dstinfo->ypixalign; - } - break; - - case ROT_ANGLE_180: - /* Determine the origin offset. */ - dstoffsetX = 0; - dstoffsetY = 0; - - /* Determine geometry size. */ - if (orthogonal) { - batch->dstwidth = dstinfo->geom->height - - dstinfo->xpixalign; - batch->dstheight = dstinfo->geom->width - - dstinfo->ypixalign; - } else { - batch->dstwidth = dstinfo->geom->width - - dstinfo->xpixalign; - batch->dstheight = dstinfo->geom->height - - dstinfo->ypixalign; - } - - /* Determine the physical size. */ - dstinfo->physwidth = batch->dstwidth; - dstinfo->physheight = batch->dstheight; - break; - - case ROT_ANGLE_270: - /* Determine the origin offset. */ - dstoffsetX = 0; - dstoffsetY = 0; - - if (orthogonal) { - /* Determine geometry size. */ - batch->dstwidth = dstinfo->geom->height - = dstinfo->ypixalign; - batch->dstheight = dstinfo->geom->width - - dstinfo->xpixalign; - - /* Determine the physical size. */ - dstinfo->physwidth = dstinfo->geom->width - - dstinfo->xpixalign; - dstinfo->physheight = dstinfo->geom->height - - dstinfo->ypixalign; - } else { - /* Determine geometry size. */ - batch->dstwidth = dstinfo->geom->width - - dstinfo->ypixalign; - batch->dstheight = dstinfo->geom->height - - dstinfo->xpixalign; - - /* Determine the physical size. */ - dstinfo->physwidth = dstinfo->geom->height - - dstinfo->xpixalign; - dstinfo->physheight = dstinfo->geom->width - - dstinfo->ypixalign; - } - break; - - default: - dstoffsetX = 0; - dstoffsetY = 0; - } - - /* Rotate the original destination rectangle - * to match the new angle. */ - rotate_gcrect(adjangle, - dstinfo->geom, &dstinfo->rect, - &gcfilter->dstgeom, &gcfilter->dstrect); - - /* Rotate the clipped destination rectangle. */ - rotate_gcrect(adjangle, - dstinfo->geom, &batch->dstclipped, - &gcfilter->dstgeom, &gcfilter->dstclipped); - - /* Compute the adjusted the destination rectangle. */ - gcfilter->dstadjusted.left - = gcfilter->dstclipped.left - dstoffsetX; - gcfilter->dstadjusted.top - = gcfilter->dstclipped.top - dstoffsetY; - gcfilter->dstadjusted.right - = gcfilter->dstclipped.right - dstoffsetX; - gcfilter->dstadjusted.bottom - = gcfilter->dstclipped.bottom - dstoffsetY; - - GCPRINT_RECT(GCZONE_DEST, "rotated dstrect", - &gcfilter->dstrect); - GCPRINT_RECT(GCZONE_DEST, "rotated dstclipped", - &gcfilter->dstclipped); - GCPRINT_RECT(GCZONE_DEST, "rotated dstadjusted", - &gcfilter->dstadjusted); - - if (batch->haveaux) { - /* Rotate the original aux destination rectangle - * to match the new angle. */ - rotate_gcrect(adjangle, dstinfo->geom, - &batch->dstrectaux, &gcfilter->dstgeom, - &gcfilter->dstrectaux); - - /* Rotate the aux destination rectangle. */ - rotate_gcrect(adjangle, dstinfo->geom, - &batch->dstclippedaux, &gcfilter->dstgeom, - &gcfilter->dstclippedaux); - - /* Compute the adjust the aux destination rectangle. */ - gcfilter->dstadjustedaux.left - = batch->dstclippedaux.left - dstoffsetX; - gcfilter->dstadjustedaux.top - = batch->dstclippedaux.top - dstoffsetY; - gcfilter->dstadjustedaux.right - = batch->dstclippedaux.right - dstoffsetX; - gcfilter->dstadjustedaux.bottom - = batch->dstclippedaux.bottom - dstoffsetY; - - GCPRINT_RECT(GCZONE_DEST, "rotated dstrectaux", - &gcfilter->dstrectaux); - GCPRINT_RECT(GCZONE_DEST, "rotated dstclippedaux", - &gcfilter->dstclippedaux); - GCPRINT_RECT(GCZONE_DEST, "rotated dstadjustedaux", - &gcfilter->dstadjustedaux); - } - - GCDBG(GCZONE_DEST, "aligned geometry size = %dx%d\n", - batch->dstwidth, batch->dstheight); - GCDBG(GCZONE_DEST, "aligned physical size = %dx%d\n", - dstinfo->physwidth, dstinfo->physheight); - GCDBG(GCZONE_DEST, "origin offset (pixels) = %d,%d\n", - dstoffsetX, dstoffsetY); - } - - GCEXIT(GCZONE_DEST); -} - - -/******************************************************************************* - * Rasterizer setup. - */ - -static enum bverror startvr(struct bvbltparams *bvbltparams, - struct gcbatch *batch, - struct bvbuffmap *srcmap, - struct bvbuffmap *dstmap, - struct surfaceinfo *srcinfo, - struct surfaceinfo *dstinfo, - unsigned int srcx, - unsigned int srcy, - struct gcrect *dstrect, - int srcangle, - int dstangle, - enum gcscaletype scaletype) -{ - enum bverror bverror; - struct gccontext *gccontext = get_context(); - struct gcfilter *gcfilter; - - struct gcmovrdst *gcmovrdst; - struct gcmovrsrc *gcmovrsrc; - struct gcmostartvr *gcmostartvr; - - struct gcrect srcrect; - - GCENTERARG(GCZONE_FILTER, "scaletype = %d\n", scaletype); - - /* Get a shortcut to the filter properties. */ - gcfilter = &batch->op.filter; - - /*********************************************************************** - * Program the destination. - */ - - GCDBG(GCZONE_FILTER, "destination:\n"); - GCDBG(GCZONE_FILTER, " angle = %d\n", dstangle); - 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); - GCDBG(GCZONE_FILTER, " swizzle = %d\n", dstinfo->format.swizzle); - GCDBG(GCZONE_FILTER, " premul = %d\n", dstinfo->format.premultiplied); - GCDBG(GCZONE_FILTER, " physwidth = %d\n", dstinfo->physwidth); - GCDBG(GCZONE_FILTER, " physheight = %d\n", dstinfo->physheight); - GCPRINT_RECT(GCZONE_FILTER, " rect", dstrect); - - /* Allocate command buffer. */ - bverror = claim_buffer(bvbltparams, batch, - sizeof(struct gcmovrdst), - (void **) &gcmovrdst); - if (bverror != BVERR_NONE) - goto exit; - - /* Add the address fixup. */ - add_fixup(bvbltparams, batch, &gcmovrdst->address, dstinfo->bytealign); - - /* Set surface parameters. */ - gcmovrdst->config_ldst = gcmovrdst_config_ldst; - gcmovrdst->address = GET_MAP_HANDLE(dstmap); - gcmovrdst->stride = dstinfo->geom->virtstride; - gcmovrdst->config.raw = 0; - gcmovrdst->config.reg.swizzle = dstinfo->format.swizzle; - gcmovrdst->config.reg.format = dstinfo->format.format; - - /* Set surface width and height. */ - gcmovrdst->rotation.raw = 0; - gcmovrdst->rotation.reg.surf_width = dstinfo->physwidth; - gcmovrdst->rotationheight_ldst = gcmovrdst_rotationheight_ldst; - gcmovrdst->rotationheight.raw = 0; - gcmovrdst->rotationheight.reg.height = dstinfo->physheight; - - /*********************************************************************** - * Program the source. - */ - - /* Determine adjusted source bounding rectangle and origin. */ - srcrect = srcinfo->rect; - 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,%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); - GCDBG(GCZONE_FILTER, " swizzle = %d\n", srcinfo->format.swizzle); - GCDBG(GCZONE_FILTER, " premul = %d\n", srcinfo->format.premultiplied); - GCDBG(GCZONE_FILTER, " physwidth = %d\n", srcinfo->physwidth); - GCDBG(GCZONE_FILTER, " physheight = %d\n", srcinfo->physheight); - GCPRINT_RECT(GCZONE_FILTER, " rect", &srcrect); - - GCDBG(GCZONE_FILTER, "src origin: 0x%08X,0x%08X\n", srcx, srcy); - - /* Allocate command buffer. */ - bverror = claim_buffer(bvbltparams, batch, - sizeof(struct gcmovrsrc), - (void **) &gcmovrsrc); - if (bverror != BVERR_NONE) - goto exit; - - add_fixup(bvbltparams, batch, &gcmovrsrc->address, srcinfo->bytealign); - - gcmovrsrc->config_ldst = gcmovrsrc_config_ldst; - - gcmovrsrc->address = GET_MAP_HANDLE(srcmap); - gcmovrsrc->stride = srcinfo->geom->virtstride; - - gcmovrsrc->rotation.raw = 0; - gcmovrsrc->rotation.reg.surf_width = srcinfo->physwidth; - - gcmovrsrc->config.raw = 0; - gcmovrsrc->config.reg.swizzle = srcinfo->format.swizzle; - gcmovrsrc->config.reg.format = srcinfo->format.format; - - if (gccontext->gcfeatures2.reg.l2cachefor420 && - (srcinfo->format.type == BVFMT_YUV) && - (srcinfo->format.cs.yuv.planecount > 1) && - ((srcinfo->angle & 1) != 0)) - gcmovrsrc->config.reg.disable420L2cache - = GCREG_SRC_CONFIG_DISABLE420_L2_CACHE_DISABLED; - - gcmovrsrc->pos_ldst = gcmovrsrc_pos_ldst; - - /* Source image bounding box. */ - gcmovrsrc->lt.reg.left = srcrect.left; - gcmovrsrc->lt.reg.top = srcrect.top; - gcmovrsrc->rb.reg.right = srcrect.right; - gcmovrsrc->rb.reg.bottom = srcrect.bottom; - - /* Fractional origin. */ - gcmovrsrc->x = srcx; - gcmovrsrc->y = srcy; - - /* Program rotation. */ - gcmovrsrc->rotation_ldst = gcmovrsrc_rotation_ldst; - gcmovrsrc->rotationheight.reg.height = srcinfo->physheight; - gcmovrsrc->rotationangle.raw = 0; - gcmovrsrc->rotationangle.reg.src = rotencoding[srcangle]; - gcmovrsrc->rotationangle.reg.dst = rotencoding[dstangle]; - gcmovrsrc->rotationangle.reg.src_mirror = srcinfo->mirror; - gcmovrsrc->rotationangle.reg.dst_mirror = dstinfo->mirror; - - gcmovrsrc->rop_ldst = gcmovrsrc_rop_ldst; - gcmovrsrc->rop.raw = 0; - gcmovrsrc->rop.reg.type = GCREG_ROP_TYPE_ROP3; - gcmovrsrc->rop.reg.fg = 0xCC; - - /* Program multiply modes. */ - gcmovrsrc->mult_ldst = gcmovrsrc_mult_ldst; - gcmovrsrc->mult.raw = 0; - gcmovrsrc->mult.reg.srcglobalpremul - = GCREG_COLOR_MULTIPLY_MODES_SRC_GLOBAL_PREMULTIPLY_DISABLE; - - if (srcinfo->format.premultiplied) - gcmovrsrc->mult.reg.srcpremul - = GCREG_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_DISABLE; - else - gcmovrsrc->mult.reg.srcpremul - = GCREG_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_ENABLE; - - if (dstinfo->format.premultiplied) { - gcmovrsrc->mult.reg.dstpremul - = GCREG_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_DISABLE; - - gcmovrsrc->mult.reg.dstdemul - = GCREG_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY_DISABLE; - } else { - gcmovrsrc->mult.reg.dstpremul - = GCREG_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_ENABLE; - - gcmovrsrc->mult.reg.dstdemul - = GCREG_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY_ENABLE; - } - - /* Program YUV source. */ - if (srcinfo->format.type == BVFMT_YUV) { - bverror = set_yuvsrc(bvbltparams, batch, srcinfo, srcmap); - if (bverror != BVERR_NONE) - goto exit; - } - - /*********************************************************************** - * Program blending. - */ - - bverror = set_blending(bvbltparams, batch, srcinfo); - if (bverror != BVERR_NONE) - goto exit; - - /*********************************************************************** - * Start the operation. - */ - - bverror = claim_buffer(bvbltparams, batch, - sizeof(struct gcmostartvr), - (void **) &gcmostartvr); - if (bverror != BVERR_NONE) - goto exit; - - switch (scaletype) { - case GC_SCALE_OPF: - gcmostartvr->scalex = gcfilter->horscalefactor; - gcmostartvr->scaley = gcfilter->verscalefactor; - gcmostartvr->config = gcregvrconfig_onepass; - break; - - case GC_SCALE_HOR: - gcmostartvr->scalex = gcfilter->horscalefactor; - gcmostartvr->scaley = 0; - gcmostartvr->config = gcregvrconfig_horizontal; - break; - - case GC_SCALE_VER: - gcmostartvr->scalex = 0; - gcmostartvr->scaley = gcfilter->verscalefactor; - gcmostartvr->config = gcregvrconfig_vertical; - break; - - case GC_SCALE_HOR_FLIPPED: - gcmostartvr->scalex = 0; - gcmostartvr->scaley = gcfilter->horscalefactor; - gcmostartvr->config = gcregvrconfig_vertical; - break; - - case GC_SCALE_VER_FLIPPED: - gcmostartvr->scalex = gcfilter->verscalefactor; - gcmostartvr->scaley = 0; - gcmostartvr->config = gcregvrconfig_horizontal; - break; - } - - gcmostartvr->scale_ldst = gcmostartvr_scale_ldst; - gcmostartvr->rect_ldst = gcmostartvr_rect_ldst; - gcmostartvr->config_ldst = gcmostartvr_config_ldst; - - gcmostartvr->lt.left = dstrect->left; - gcmostartvr->lt.top = dstrect->top; - gcmostartvr->rb.right = dstrect->right; - gcmostartvr->rb.bottom = dstrect->bottom; - -exit: - GCEXITARG(GCZONE_FILTER, "bv%s = %d\n", - (bverror == BVERR_NONE) ? "result" : "error", bverror); - return bverror; -} - - -/******************************************************************************* - * Main fiter entry. - */ - -enum bverror do_filter(struct bvbltparams *bvbltparams, - struct gcbatch *batch, - struct surfaceinfo *srcinfo) -{ - enum bverror bverror = BVERR_NONE; - struct gccontext *gccontext = get_context(); - - struct gcfilter *gcfilter; - struct surfaceinfo *dstinfo; - - bool scalex, scaley; - bool singlepass, twopass; - - struct gcrect *srcrect; - struct gcrect *dstrect; - struct gcrect *dstclipped; - struct gcrect *dstadjusted; - - struct bvsurfgeom dstrotated0geom; - struct gcrect dstrotated0; - - struct gcrect dstdelta; - struct gcrect srcdelta; - struct gcrect srcclipped; - - struct bvbuffmap *srcmap = NULL; - struct bvbuffmap *tmpmap = NULL; - struct bvbuffmap *dstmap = NULL; - - struct gcmovrconfigex *gcmovrconfigex; - - int adjangle; - unsigned int srcx, srcy; - unsigned int srcwidth, srcheight; - unsigned int dstwidth, dstheight; - unsigned int horscalefactor, verscalefactor; - unsigned int kernelsize; - - GCENTER(GCZONE_FILTER); - - /* Get some shortcuts. */ - dstinfo = &batch->dstinfo; - gcfilter = &batch->op.filter; - - /* Finish previous batch if any. */ - bverror = batch->batchend(bvbltparams, batch); - if (bverror != BVERR_NONE) - goto exit; - - /* ROP is not supported by the filters. */ - if ((srcinfo->rop & 0xFF) != 0xCC) { - BVSETBLTERROR(BVERR_ROP, - "only copy ROP is supported in scaling mode"); - goto exit; - } - - /* Parse the scale mode. */ - bverror = parse_scalemode(bvbltparams, batch); - if (bverror != BVERR_NONE) - goto exit; - - /* Parse destination parameters. */ - bverror = parse_destination(bvbltparams, batch); - if (bverror != BVERR_NONE) - goto exit; - - /* Compute the source alignments needed to compensate - * for the surface base address misalignment if any. */ - 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,%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) && - (srcinfo->format.cs.yuv.planecount > 1)) - set_computeyuv(srcinfo, 0, 0); - - /* Determine physical size. */ - if ((srcinfo->angle % 2) == 0) { - srcinfo->physwidth = srcinfo->geom->width - - srcinfo->xpixalign; - srcinfo->physheight = srcinfo->geom->height - - srcinfo->ypixalign; - } else { - srcinfo->physwidth = srcinfo->geom->height - - srcinfo->xpixalign; - srcinfo->physheight = srcinfo->geom->width - - srcinfo->ypixalign; - } - GCDBG(GCZONE_SRC, "source physical size = %dx%d\n", - srcinfo->physwidth, srcinfo->physheight); - - /* OPF does not support source rotation, which can be compensated by - * using destination rotation. Compute the adjustment angle. - * For simplicity use the same algorythm for both OPF and TPF. */ - adjangle = (4 - srcinfo->angle) % 4; - GCDBG(GCZONE_DEST, "adjangle = %d\n", adjangle); - - /* Compute destination rotation. */ - process_rotation(bvbltparams, batch, srcinfo, adjangle); - - /* Rotate the source rectangle to 0 degree. */ - srcrect = &srcinfo->rect; - GCPRINT_RECT(GCZONE_FILTER, "full src", srcrect); - rotate_gcrect(adjangle, - srcinfo->geom, srcrect, - srcinfo->geom, srcrect); - GCPRINT_RECT(GCZONE_FILTER, "full adjusted src", srcrect); - - /* Get destination rect shortcuts. */ - if ((srcinfo->index == 1) && batch->haveaux) { - dstrect = &gcfilter->dstrectaux; - dstclipped = &gcfilter->dstclippedaux; - dstadjusted = &gcfilter->dstadjustedaux; - } else { - dstrect = &gcfilter->dstrect; - dstclipped = &gcfilter->dstclipped; - dstadjusted = &gcfilter->dstadjusted; - } - - GCPRINT_RECT(GCZONE_FILTER, "full adjusted dst", dstrect); - GCPRINT_RECT(GCZONE_FILTER, "clipped adjusted dst", dstclipped); - GCPRINT_RECT(GCZONE_FILTER, "aligned adjusted dst", dstadjusted); - - /* Determine the source and destination rectangles. */ - srcwidth = srcrect->right - srcrect->left; - srcheight = srcrect->bottom - srcrect->top; - dstwidth = dstrect->right - dstrect->left; - dstheight = dstrect->bottom - dstrect->top; - - GCDBG(GCZONE_FILTER, "adjusted input src size: %dx%d\n", - srcwidth, srcheight); - GCDBG(GCZONE_FILTER, "adjusted input dst size: %dx%d\n", - dstwidth, dstheight); - - /* Determine the data path. */ - scalex = (srcwidth != dstwidth); - scaley = (srcheight != dstheight); - - twopass = scalex && scaley; - if (twopass) { - if (((gcfilter->horkernelsize == 3) || - (gcfilter->horkernelsize == 5)) && - ((gcfilter->verkernelsize == 3) || - (gcfilter->verkernelsize == 5))) { - singlepass = true; - twopass = false; - } else { - singlepass = false; - } - } else { - /* Two pass filter in one pass mode. */ - if (!scalex && !scaley) - GCERR("no scaling needed.\n"); - - GCDBG(GCZONE_FILTER, "only %s scaling needed.\n", - scalex ? "horizontal" : "vertical"); - - singlepass = false; - } - - /* Compute the scale factors. */ - gcfilter->horscalefactor = - horscalefactor = get_scale_factor(srcwidth, dstwidth); - GCDBG(GCZONE_FILTER, "horscalefactor = 0x%08X\n", horscalefactor); - - gcfilter->verscalefactor = - verscalefactor = get_scale_factor(srcheight, dstheight); - GCDBG(GCZONE_FILTER, "verscalefactor = 0x%08X\n", verscalefactor); - - /* Compute the destination offsets. */ - dstdelta.left = dstclipped->left - dstrect->left; - dstdelta.top = dstclipped->top - dstrect->top; - dstdelta.right = dstclipped->right - dstrect->left; - dstdelta.bottom = dstclipped->bottom - dstrect->top; - GCDBG(GCZONE_FILTER, "dst deltas = (%d,%d)-(%d,%d)\n", - dstdelta.left, dstdelta.top, dstdelta.right, dstdelta.bottom); - - /* Compute the source offsets. */ - srcdelta.left = dstdelta.left * horscalefactor; - srcdelta.top = dstdelta.top * verscalefactor; - srcdelta.right = (dstdelta.right - 1) * horscalefactor + (1 << 16); - srcdelta.bottom = (dstdelta.bottom - 1) * verscalefactor + (1 << 16); - - /* Before rendering each destination pixel, the HW will select the - * corresponding source center pixel to apply the kernel around. - * To make this process precise we need to add 0.5 to source initial - * coordinates here; this will make HW pick the next source pixel if - * the fraction is equal or greater then 0.5. */ - srcdelta.left += 0x00008000; - srcdelta.top += 0x00008000; - srcdelta.right += 0x00008000; - srcdelta.bottom += 0x00008000; - GCDBG(GCZONE_FILTER, "src deltas = " - "(0x%08X,0x%08X)-(0x%08X,0x%08X)\n", - srcdelta.left, srcdelta.top, srcdelta.right, srcdelta.bottom); - GCDBG(GCZONE_FILTER, "src deltas (int) = (%d,%d)-(%d,%d)\n", - srcdelta.left >> 16, srcdelta.top >> 16, - srcdelta.right >> 16, srcdelta.bottom >> 16); - - /* Determine clipped source rectangle. */ - srcclipped.left = srcrect->left + (srcdelta.left >> 16); - srcclipped.top = srcrect->top + (srcdelta.top >> 16); - srcclipped.right = srcrect->left + (srcdelta.right >> 16); - srcclipped.bottom = srcrect->top + (srcdelta.bottom >> 16); - - GCDBG(GCZONE_FILTER, "source:\n"); - GCDBG(GCZONE_FILTER, " stride = %d, geom = %dx%d\n", - srcinfo->geom->virtstride, - srcinfo->geom->width, srcinfo->geom->height); - GCDBG(GCZONE_FILTER, " rotation = %d\n", - srcinfo->angle); - GCPRINT_RECT(GCZONE_FILTER, " clipped rect", &srcclipped); - - GCDBG(GCZONE_FILTER, "destination:\n"); - GCDBG(GCZONE_FILTER, " stride = %d, geom size = %dx%d\n", - dstinfo->geom->virtstride, - dstinfo->geom->width, dstinfo->geom->height); - GCDBG(GCZONE_FILTER, " rotation = %d\n", - dstinfo->angle); - GCPRINT_RECT(GCZONE_FILTER, " clipped rect", dstclipped); - - /* Validate the source rectangle. */ - if (!valid_rect(srcinfo->geom, &srcclipped)) { - BVSETBLTERROR((srcinfo->index == 0) - ? BVERR_SRC1RECT - : BVERR_SRC2RECT, - "invalid source rectangle."); - goto exit; - } - - /* Map the source. */ - bverror = do_map(srcinfo->buf.desc, batch, &srcmap); - if (bverror != BVERR_NONE) { - bvbltparams->errdesc = gccontext->bverrorstr; - goto exit; - } - - /* Map the destination. */ - bverror = do_map(dstinfo->buf.desc, batch, &dstmap); - if (bverror != BVERR_NONE) { - bvbltparams->errdesc = gccontext->bverrorstr; - goto exit; - } - - /* Do single pass filter if we can. */ - if (singlepass) { - GCDBG(GCZONE_TYPE, "single pass\n"); - - /* Determine the kernel size to use. */ - kernelsize = max(gcfilter->horkernelsize, - gcfilter->verkernelsize); - - /* Set kernel size. */ - bverror = claim_buffer(bvbltparams, batch, - sizeof(struct gcmovrconfigex), - (void **) &gcmovrconfigex); - if (bverror != BVERR_NONE) - goto exit; - - gcmovrconfigex->config_ldst = gcmovrconfigex_config_ldst; - gcmovrconfigex->config.raw = ~0U; - gcmovrconfigex->config.reg.kernelsize = kernelsize; - gcmovrconfigex->config.reg.mask_kernelsize - = GCREG_VR_CONFIG_EX_MASK_FILTER_TAP_ENABLED; - - /* Setup single pass. */ - srcx = (srcrect->left << 16) + srcdelta.left; - srcy = (srcrect->top << 16) + srcdelta.top; - GCDBG(GCZONE_SRC, "src origin: 0x%08X,0x%08X\n", srcx, srcy); - - /* Load the horizontal filter. */ - bverror = load_filter(bvbltparams, batch, - GC_FILTER_SYNC, - gcfilter->horkernelsize, - gcfilter->horscalefactor, - srcwidth, dstwidth, - gcmofilterkernel_horizontal_ldst); - if (bverror != BVERR_NONE) - goto exit; - - /* Load the vertical filter. */ - bverror = load_filter(bvbltparams, batch, - GC_FILTER_SYNC, - gcfilter->verkernelsize, - gcfilter->verscalefactor, - srcheight, dstheight, - gcmofilterkernel_vertical_ldst); - if (bverror != BVERR_NONE) - goto exit; - - /* Start the operation. */ - bverror = startvr(bvbltparams, batch, - srcmap, dstmap, srcinfo, dstinfo, - srcx, srcy, dstadjusted, - ROT_ANGLE_0, gcfilter->dstangle, - GC_SCALE_OPF); - } else if (twopass) { - unsigned int horkernelhalf; - unsigned int leftextra, rightextra; - unsigned int tmprectwidth, tmprectheight; - unsigned int tmpalignmask, dstalignmask; - unsigned int tmpsize; - struct surfaceinfo tmpinfo; - struct bvsurfgeom tmpgeom; - - GCDBG(GCZONE_TYPE, "two pass\n"); - - /* Initialize the temporaty surface geometry. */ - tmpgeom.structsize = sizeof(struct bvsurfgeom); - tmpgeom.orientation = 0; - tmpgeom.paletteformat = 0; - tmpgeom.palette = NULL; - - /* Initialize the temporaty surface descriptor. */ - tmpinfo.index = -1; - tmpinfo.geom = &tmpgeom; - tmpinfo.angle = gcfilter->dstangle; - tmpinfo.mirror = GCREG_MIRROR_NONE; - tmpinfo.rop = 0; - GCDBG(GCZONE_FILTER, "tmp angle = %d\n", tmpinfo.angle); - - /* Transfer blending parameters from the source to the - * temporary buffer so that the blending would happen - * on the second pass. */ - tmpinfo.gca = srcinfo->gca; - srcinfo->gca = NULL; - - /* Determine temporary surface format. */ - if (srcinfo->format.type == BVFMT_YUV) { - if (tmpinfo.angle == ROT_ANGLE_0) { - GCDBG(GCZONE_FILTER, - "tmp format = 4:2:2\n"); - tmpgeom.format = OCDFMT_YUYV; - parse_format(bvbltparams, &tmpinfo); - } else { - GCDBG(GCZONE_FILTER, - "tmp format = dst format\n"); - tmpgeom.format = dstinfo->geom->format; - tmpinfo.format = dstinfo->format; - } - } else { - GCDBG(GCZONE_FILTER, - "tmp format = src format\n"); - tmpgeom.format = srcinfo->geom->format; - tmpinfo.format = srcinfo->format; - } - - /* Determine pixel alignment masks. */ - tmpalignmask = GC_BITS_PER_CACHELINE - / tmpinfo.format.bitspp - 1; - dstalignmask = GC_BITS_PER_CACHELINE - / dstinfo->format.bitspp - 1; - - /* In partial filter blit cases, the vertical pass has to render - * more pixel information to the left and to the right of the - * temporary image so that the next pass has its necessary - * kernel information on the edges of the image. */ - horkernelhalf = gcfilter->horkernelsize >> 1; - - leftextra = srcdelta.left >> 16; - rightextra = srcwidth - (srcdelta.right >> 16); - - if (leftextra > horkernelhalf) - leftextra = horkernelhalf; - - if (rightextra > horkernelhalf) - rightextra = horkernelhalf; - - GCDBG(GCZONE_FILTER, "leftextra = %d, rightextra = %d\n", - leftextra, rightextra); - - /* Determine the source origin. */ - srcx = ((srcrect->left - leftextra) << 16) + srcdelta.left; - srcy = (srcrect->top << 16) + srcdelta.top; - GCDBG(GCZONE_SRC, "src origin: 0x%08X,0x%08X\n", srcx, srcy); - GCDBG(GCZONE_SRC, "src origin (int): %d,%d\n", - srcx >> 16, srcy >> 16); - - /* Determine the size of the temporary rectangle. */ - tmprectwidth = leftextra + rightextra - + ((srcdelta.right >> 16) - (srcdelta.left >> 16)); - tmprectheight = dstadjusted->bottom - dstadjusted->top; - GCDBG(GCZONE_FILTER, "tmp rect size: %dx%d\n", - tmprectwidth, tmprectheight); - - /* Determine the temporary destination coordinates. */ - switch (tmpinfo.angle) { - case ROT_ANGLE_0: - case ROT_ANGLE_180: - tmpinfo.rect.left = (srcx >> 16) & tmpalignmask; - tmpinfo.rect.top = 0; - tmpinfo.rect.right = tmpinfo.rect.left + tmprectwidth; - tmpinfo.rect.bottom = tmprectheight; - - tmpgeom.width = (tmpinfo.rect.right + tmpalignmask) - & ~tmpalignmask; - tmpgeom.height = tmprectheight; - - tmpinfo.physwidth = tmpgeom.width; - tmpinfo.physheight = tmpgeom.height; - break; - - case ROT_ANGLE_90: - tmpinfo.rect.left = 0; - tmpinfo.rect.top = dstadjusted->left & dstalignmask; - tmpinfo.rect.right = tmprectwidth; - tmpinfo.rect.bottom = tmpinfo.rect.top + tmprectheight; - - tmpgeom.width = tmprectwidth; - tmpgeom.height = (tmpinfo.rect.bottom + tmpalignmask) - & ~tmpalignmask; - - tmpinfo.physwidth = tmpgeom.height; - tmpinfo.physheight = tmpgeom.width; - break; - - case ROT_ANGLE_270: - tmpinfo.rect.left = 0; - tmpinfo.rect.right = tmprectwidth; - tmpinfo.rect.bottom = dstadjusted->left & dstalignmask; - - tmpgeom.width = tmprectwidth; - tmpgeom.height = (tmpinfo.rect.bottom + tmprectheight - + tmpalignmask) & ~tmpalignmask; - - tmpinfo.rect.bottom = tmpgeom.height - - tmpinfo.rect.bottom; - tmpinfo.rect.top = tmpinfo.rect.bottom - - tmprectheight; - - tmpinfo.physwidth = tmpgeom.height; - tmpinfo.physheight = tmpgeom.width; - break; - } - - GCPRINT_RECT(GCZONE_DEST, "tmp dest", &tmpinfo.rect); - GCDBG(GCZONE_FILTER, "tmp geometry size = %dx%d\n", - tmpgeom.width, tmpgeom.height); - GCDBG(GCZONE_FILTER, "tmp physical size = %dx%d\n", - tmpinfo.physwidth, tmpinfo.physheight); - - /* Determine the size of the temporaty surface. */ - tmpgeom.virtstride = (tmpinfo.physwidth - * tmpinfo.format.bitspp) / 8; - tmpsize = tmpgeom.virtstride * tmpinfo.physheight; - tmpsize += GC_BYTES_PER_CACHELINE; - tmpsize = (tmpsize + ~PAGE_MASK) & PAGE_MASK; - GCDBG(GCZONE_FILTER, "tmp stride = %d\n", tmpgeom.virtstride); - GCDBG(GCZONE_FILTER, "tmp size (bytes) = %d\n", tmpsize); - - /* Allocate the temporary buffer. */ - bverror = allocate_temp(bvbltparams, tmpsize); - if (bverror != BVERR_NONE) - goto exit; - - /* Map the temporary buffer. */ - tmpinfo.buf.desc = gccontext->tmpbuffdesc; - bverror = do_map(tmpinfo.buf.desc, batch, &tmpmap); - if (bverror != BVERR_NONE) { - bvbltparams->errdesc = gccontext->bverrorstr; - goto exit; - } - - /* Compute the temp buffer alignments needed to compensate - * for the surface base address misalignment if any. */ - tmpinfo.xpixalign = 0; - tmpinfo.ypixalign = 0; - tmpinfo.bytealign = (get_pixel_offset(&tmpinfo, 0) - * (int) tmpinfo.format.bitspp) / 8; - GCDBG(GCZONE_SRC, "tmp offset (pixels) = %d,%d\n", - tmpinfo.xpixalign, tmpinfo.ypixalign); - GCDBG(GCZONE_SRC, "tmp offset (bytes) = %d\n", - tmpinfo.bytealign); - - /* Load the vertical filter. */ - bverror = load_filter(bvbltparams, batch, - GC_FILTER_SYNC, - gcfilter->verkernelsize, - gcfilter->verscalefactor, - srcheight, dstheight, - gcmofilterkernel_shared_ldst); - if (bverror != BVERR_NONE) - goto exit; - - /* Start the operation. */ - GCDBG(GCZONE_TYPE, "vertical pass\n"); - bverror = startvr(bvbltparams, batch, - srcmap, tmpmap, srcinfo, &tmpinfo, - srcx, srcy, &tmpinfo.rect, - ROT_ANGLE_0, tmpinfo.angle, - GC_SCALE_VER); - if (bverror != BVERR_NONE) - goto exit; - - /* Fake no rotation. */ - adjangle = (4 - tmpinfo.angle) % 4; - GCDBG(GCZONE_DEST, "adjangle = %d\n", adjangle); - - /* Rotate the source rectangle to 0 degree. */ - rotate_gcrect(adjangle, - tmpinfo.geom, &tmpinfo.rect, - tmpinfo.geom, &tmpinfo.rect); - GCPRINT_RECT(GCZONE_DEST, "tmp src", &tmpinfo.rect); - - /* Rotate the destination rectangle to 0 degree. */ - rotate_gcrect(adjangle, - &gcfilter->dstgeom, dstclipped, - &dstrotated0geom, &dstrotated0); - GCPRINT_RECT(GCZONE_DEST, "dest", &dstrotated0); - - /* Apply adjustment. */ - dstrotated0.left -= dstinfo->xpixalign; - dstrotated0.right -= dstinfo->xpixalign; - - /* Determine the source origin. */ - switch (tmpinfo.angle) { - case ROT_ANGLE_0: - srcx = ((tmpinfo.rect.left + leftextra) << 16) - + (srcdelta.left & 0xFFFF); - srcy = (tmpinfo.rect.top << 16) - + (srcdelta.top & 0xFFFF); - break; - - case ROT_ANGLE_90: - srcx = (tmpinfo.rect.left << 16) - + (srcdelta.top & 0xFFFF); - srcy = ((tmpinfo.rect.top + rightextra) << 16) - + (srcdelta.left & 0xFFFF); - break; - - case ROT_ANGLE_180: - srcx = ((tmpinfo.rect.left + rightextra) << 16) - + (srcdelta.left & 0xFFFF); - srcy = (tmpinfo.rect.top << 16) - + (srcdelta.top & 0xFFFF); - break; - - case ROT_ANGLE_270: - srcx = (tmpinfo.rect.left << 16) - + (srcdelta.top & 0xFFFF); - srcy = ((tmpinfo.rect.top + leftextra) << 16) - + (srcdelta.left & 0xFFFF); - break; - } - - GCDBG(GCZONE_SRC, "src origin: 0x%08X,0x%08X\n", srcx, srcy); - - /* Load the horizontal filter. */ - bverror = load_filter(bvbltparams, batch, - GC_FILTER_SYNC, - gcfilter->horkernelsize, - gcfilter->horscalefactor, - srcwidth, dstwidth, - gcmofilterkernel_shared_ldst); - if (bverror != BVERR_NONE) - goto exit; - - /* Start the operation. */ - GCDBG(GCZONE_TYPE, "horizontal pass\n"); - bverror = startvr(bvbltparams, batch, - tmpmap, dstmap, &tmpinfo, dstinfo, - srcx, srcy, &dstrotated0, - ROT_ANGLE_0, ROT_ANGLE_0, - ((gcfilter->dstangle % 2) == 0) - ? GC_SCALE_HOR - : GC_SCALE_HOR_FLIPPED); - if (bverror != BVERR_NONE) - goto exit; - } else { - GCDBG(GCZONE_TYPE, "two pass (%s pass config).\n", - scalex ? "horizontal" : "vertical"); - - /* Setup single pass. */ - srcx = (srcrect->left << 16) + srcdelta.left; - srcy = (srcrect->top << 16) + srcdelta.top; - GCDBG(GCZONE_SRC, "src origin: 0x%08X,0x%08X\n", srcx, srcy); - - if (scalex) { - /* Load the horizontal filter. */ - bverror = load_filter(bvbltparams, batch, - GC_FILTER_SYNC, - gcfilter->horkernelsize, - gcfilter->horscalefactor, - srcwidth, dstwidth, - gcmofilterkernel_shared_ldst); - if (bverror != BVERR_NONE) - goto exit; - - /* Start the operation. */ - bverror = startvr(bvbltparams, batch, - srcmap, dstmap, srcinfo, dstinfo, - srcx, srcy, dstadjusted, - ROT_ANGLE_0, gcfilter->dstangle, - GC_SCALE_HOR); - if (bverror != BVERR_NONE) - goto exit; - } else { - /* Load the vertical filter. */ - bverror = load_filter(bvbltparams, batch, - GC_FILTER_SYNC, - gcfilter->verkernelsize, - gcfilter->verscalefactor, - srcheight, dstheight, - gcmofilterkernel_shared_ldst); - if (bverror != BVERR_NONE) - goto exit; - - /* Start the operation. */ - bverror = startvr(bvbltparams, batch, - srcmap, dstmap, srcinfo, dstinfo, - srcx, srcy, dstadjusted, - ROT_ANGLE_0, gcfilter->dstangle, - GC_SCALE_VER); - if (bverror != BVERR_NONE) - goto exit; - } - } - -exit: - GCEXITARG(GCZONE_FILTER, "bv%s = %d\n", - (bverror == BVERR_NONE) ? "result" : "error", bverror); - return bverror; -} |