summaryrefslogtreecommitdiffstats
path: root/bltsville/gcbv/mirror/gcfilter.c
diff options
context:
space:
mode:
Diffstat (limited to 'bltsville/gcbv/mirror/gcfilter.c')
-rw-r--r--bltsville/gcbv/mirror/gcfilter.c1788
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;
-}