diff options
author | Alexei Shlychkov <x0177296@ti.com> | 2012-07-19 12:00:33 -0700 |
---|---|---|
committer | Ziyann <jaraidaniel@gmail.com> | 2014-10-01 13:00:54 +0200 |
commit | 88fdeb6d1620e09b5b65e4385045ca23bbf36379 (patch) | |
tree | 446f18e90b793149e18cfed7eaedad44a543739e /drivers/misc | |
parent | 1ba2ddcd4059511ac768901a0eca0f13d090424f (diff) | |
download | kernel_samsung_tuna-88fdeb6d1620e09b5b65e4385045ca23bbf36379.zip kernel_samsung_tuna-88fdeb6d1620e09b5b65e4385045ca23bbf36379.tar.gz kernel_samsung_tuna-88fdeb6d1620e09b5b65e4385045ca23bbf36379.tar.bz2 |
gcx: split in several files by function.
Also added GC_SHOW_TIME switch.
Change-Id: Ib166f4c58cefbdc9732c9f5cc5d077a157ef4bee
Signed-off-by: Alexei Shlychkov <x0177296@ti.com>
Diffstat (limited to 'drivers/misc')
-rw-r--r-- | drivers/misc/gcx/gcbv/Makefile | 8 | ||||
-rw-r--r-- | drivers/misc/gcx/gcbv/gcblit.c | 750 | ||||
-rw-r--r-- | drivers/misc/gcx/gcbv/gcbuffer.c | 405 | ||||
-rw-r--r-- | drivers/misc/gcx/gcbv/gcbv.c | 3964 | ||||
-rw-r--r-- | drivers/misc/gcx/gcbv/gcbv.h | 459 | ||||
-rw-r--r-- | drivers/misc/gcx/gcbv/gcfill.c | 272 | ||||
-rw-r--r-- | drivers/misc/gcx/gcbv/gcfilter.c | 128 | ||||
-rw-r--r-- | drivers/misc/gcx/gcbv/gcmap.c | 364 | ||||
-rw-r--r-- | drivers/misc/gcx/gcbv/gcparser.c | 1602 | ||||
-rw-r--r-- | drivers/misc/gcx/gccore/gcdbglog.c | 38 | ||||
-rw-r--r-- | drivers/misc/gcx/gccore/gcmain.c | 9 | ||||
-rw-r--r-- | drivers/misc/gcx/gccore/gcmmu.c | 23 | ||||
-rw-r--r-- | drivers/misc/gcx/gccore/gcmmu.h | 3 | ||||
-rw-r--r-- | drivers/misc/gcx/gcioctl/gcif.c | 280 |
14 files changed, 4527 insertions, 3778 deletions
diff --git a/drivers/misc/gcx/gcbv/Makefile b/drivers/misc/gcx/gcbv/Makefile index 8f02893..9e7e6a5 100644 --- a/drivers/misc/gcx/gcbv/Makefile +++ b/drivers/misc/gcx/gcbv/Makefile @@ -2,4 +2,10 @@ obj-$(CONFIG_GCBV) += gcbv2d.o gcbv2d-y := \ gcmain.o \ - gcbv.o + gcbv.o \ + gcparser.o \ + gcmap.o \ + gcbuffer.o \ + gcfill.o \ + gcblit.o \ + gcfilter.o diff --git a/drivers/misc/gcx/gcbv/gcblit.c b/drivers/misc/gcx/gcbv/gcblit.c new file mode 100644 index 0000000..8fa2a00 --- /dev/null +++ b/drivers/misc/gcx/gcbv/gcblit.c @@ -0,0 +1,750 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2012 Vivante Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * BSD LICENSE + * + * Copyright(c) 2012 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_BLEND (1 << 0) +#define GCZONE_SURF (1 << 1) +#define GCZONE_BLIT (1 << 3) + +GCDBG_FILTERDEF(gcblit, GCZONE_NONE, + "blend", + "surf", + "blit") + + +static enum bverror do_blit_end(struct bvbltparams *bltparams, + struct gcbatch *batch) +{ + enum bverror bverror; + struct gcmobltconfig *gcmobltconfig; + struct gcmostart *gcmostart; + + GCENTER(GCZONE_BLIT); + + GCDBG(GCZONE_BLIT, "finalizing the blit, scrcount = %d\n", + batch->gcblit.srccount); + + /*********************************************************************** + * Configure the operation. + */ + + /* Allocate command buffer. */ + bverror = claim_buffer(bltparams, batch, + sizeof(struct gcmobltconfig), + (void **) &gcmobltconfig); + if (bverror != BVERR_NONE) + goto exit; + + /* Configure multi-source control. */ + gcmobltconfig->multisource_ldst = gcmobltconfig_multisource_ldst; + gcmobltconfig->multisource.raw = 0; + gcmobltconfig->multisource.reg.srccount = batch->gcblit.srccount - 1; + + GCDBG(GCZONE_BLIT, "blockenable = %d\n", batch->blockenable); + if (batch->blockenable) { + gcmobltconfig->multisource.reg.horblock + = GCREG_DE_MULTI_SOURCE_HORIZONTAL_BLOCK_PIXEL16; + gcmobltconfig->multisource.reg.verblock + = GCREG_DE_MULTI_SOURCE_VERTICAL_BLOCK_LINE64; + } else { + gcmobltconfig->multisource.reg.horblock + = GCREG_DE_MULTI_SOURCE_HORIZONTAL_BLOCK_PIXEL128; + gcmobltconfig->multisource.reg.verblock + = GCREG_DE_MULTI_SOURCE_VERTICAL_BLOCK_LINE1; + } + + /* Set destination configuration. */ + GCDBG(GCZONE_BLIT, "format entry = 0x%08X\n", + (unsigned int) batch->dstformat); + GCDBG(GCZONE_BLIT, " swizzle code = %d\n", + batch->dstformat->swizzle); + GCDBG(GCZONE_BLIT, " format code = %d\n", + batch->dstformat->format); + + gcmobltconfig->dstconfig_ldst = gcmobltconfig_dstconfig_ldst; + gcmobltconfig->dstconfig.raw = 0; + gcmobltconfig->dstconfig.reg.swizzle = batch->dstformat->swizzle; + gcmobltconfig->dstconfig.reg.format = batch->dstformat->format; + gcmobltconfig->dstconfig.reg.command = batch->gcblit.multisrc + ? GCREG_DEST_CONFIG_COMMAND_MULTI_SOURCE_BLT + : GCREG_DEST_CONFIG_COMMAND_BIT_BLT; + + /* Set ROP. */ + gcmobltconfig->rop_ldst = gcmobltconfig_rop_ldst; + gcmobltconfig->rop.raw = 0; + gcmobltconfig->rop.reg.type = GCREG_ROP_TYPE_ROP3; + gcmobltconfig->rop.reg.fg = (unsigned char) batch->gcblit.rop; + + /*********************************************************************** + * Start the operation. + */ + + /* Allocate command buffer. */ + bverror = claim_buffer(bltparams, batch, + sizeof(struct gcmostart), + (void **) &gcmostart); + if (bverror != BVERR_NONE) + goto exit; + + /* Set START_DE command. */ + gcmostart->startde.cmd.fld = gcfldstartde; + + /* Set destination rectangle. */ + gcmostart->rect.left = batch->left; + gcmostart->rect.top = batch->top; + gcmostart->rect.right = batch->right; + gcmostart->rect.bottom = batch->bottom; + + GCDBG(GCZONE_BLIT, "dstrect = (%d,%d)-(%d,%d)\n", + gcmostart->rect.left, gcmostart->rect.top, + gcmostart->rect.right, gcmostart->rect.bottom); + + /* Reset the finalizer. */ + batch->batchend = do_end; + + gc_debug_blt(batch->gcblit.srccount, + abs(batch->right - batch->left), + abs(batch->bottom - batch->top)); + +exit: + GCEXITARG(GCZONE_BLIT, "bv%s = %d\n", + (bverror == BVERR_NONE) ? "result" : "error", bverror); + return bverror; +} + +enum bverror do_blit(struct bvbltparams *bltparams, + struct gcbatch *batch, + struct srcinfo *srcinfo) +{ + enum bverror bverror = BVERR_NONE; + struct gccontext *gccontext = get_context(); + + struct gcmosrc *gcmosrc; + struct gcmosrcalpha *gcmosrcalpha; + + unsigned int index; + + struct bvbuffmap *dstmap; + struct bvbuffdesc *dstdesc; + struct bvsurfgeom *dstgeom; + struct bvformatxlate *dstformat; + int dstshiftX, dstshiftY; + int dstalign, dstbyteshift; + + struct bvbuffmap *srcmap; + struct gcalpha *srcgca; + struct bvrect *srcrect; + struct bvbuffdesc *srcdesc; + struct bvsurfgeom *srcgeom; + struct bvformatxlate *srcformat; + int srcshiftX, srcshiftY; + int srcalign, srcbyteshift; + + int srcleft, srctop; + int dstleft, dsttop, dstright, dstbottom; + int srcsurfwidth, srcsurfheight; + unsigned int physwidth, physheight; + int orthogonal; + int multisrc; + + GCENTER(GCZONE_BLIT); + + /* Create source object shortcuts. */ + srcmap = NULL; + srcgca = srcinfo->gca; + srcrect = srcinfo->rect; + srcdesc = srcinfo->buf.desc; + srcgeom = srcinfo->geom; + srcformat = srcinfo->format; + + /* Create destination object shortcuts. */ + dstmap = NULL; + dstdesc = bltparams->dstdesc; + dstgeom = bltparams->dstgeom; + dstformat = batch->dstformat; + + /*********************************************************************** + * Determine source surface alignment offset. + */ + + /* Determine whether the source and the destination are orthogonal + * to each other. */ + orthogonal = (srcinfo->angle % 2) != (batch->dstangle % 2); + + /* Compute adjusted destination rectangle. */ + dstleft = batch->clippedleft + batch->dstoffsetX; + dsttop = batch->clippedtop + batch->dstoffsetY; + dstright = batch->clippedright + batch->dstoffsetX; + dstbottom = batch->clippedbottom + batch->dstoffsetY; + + /* Compute clipped source origin. */ + srcleft = srcrect->left + batch->deltaleft; + srctop = srcrect->top + batch->deltatop; + + GCDBG(GCZONE_SURF, "adjusted dstrect = (%d,%d)-(%d,%d), %dx%d\n", + dstleft, dsttop, dstright, dstbottom, + dstright - dstleft, dstbottom - dsttop); + + /* Compute the source surface shift. */ + switch (srcinfo->angle) { + case ROT_ANGLE_0: + srcshiftX = srcleft - dstleft; + srcshiftY = srctop - dsttop; + break; + + case ROT_ANGLE_90: + srcshiftX = srctop - dsttop; + srcshiftY = (srcgeom->width - srcleft) + - (batch->dstwidth - dstleft); + break; + + case ROT_ANGLE_180: + srcshiftX = (srcgeom->width - srcleft) + - (batch->dstwidth - dstleft); + srcshiftY = (srcgeom->height - srctop) + - (batch->dstheight - dsttop); + break; + + case ROT_ANGLE_270: + srcshiftX = (srcgeom->height - srctop) + - (batch->dstheight - dsttop); + srcshiftY = srcleft - dstleft; + break; + + default: + srcshiftX = 0; + srcshiftY = 0; + } + + /* Compute the source surface offset in bytes. */ + srcbyteshift = srcshiftY * (int) srcgeom->virtstride + + srcshiftX * (int) srcformat->bitspp / 8; + + /* Compute the source offset in pixels needed to compensate + * for the surface base address misalignment if any. */ + srcalign = get_pixel_offset(srcdesc, srcformat, srcbyteshift); + + GCDBG(GCZONE_SURF, "source surface %d:\n", srcinfo->index + 1); + GCDBG(GCZONE_SURF, " surface offset (pixels) = %d,%d\n", + srcshiftX, srcshiftY); + GCDBG(GCZONE_SURF, " surface offset (bytes) = 0x%08X\n", + srcbyteshift); + GCDBG(GCZONE_SURF, " srcalign = %d\n", + srcalign); + + /* Apply the source alignment. */ + srcbyteshift += srcalign * (int) srcformat->bitspp / 8; + srcshiftX += srcalign; + + GCDBG(GCZONE_SURF, " adjusted surface offset (pixels) = %d,%d\n", + srcshiftX, srcshiftY); + GCDBG(GCZONE_SURF, " adjusted surface offset (bytes) = 0x%08X\n", + srcbyteshift); + + /* Determine the destination surface shift. */ + dstshiftX = batch->dstalign; + dstshiftY = (((srcinfo->angle + 3) % 4) == batch->dstangle) + ? srcalign : 0; + + /* Compute the destination surface offset in bytes. */ + dstbyteshift = dstshiftY * (int) dstgeom->virtstride + + dstshiftX * (int) dstformat->bitspp / 8; + + /* Compute the destination offset in pixels needed to compensate + * for the surface base address misalignment if any. */ + dstalign = get_pixel_offset(dstdesc, dstformat, dstbyteshift); + + GCDBG(GCZONE_SURF, "destination surface:\n"); + GCDBG(GCZONE_SURF, " surface offset (pixels) = %d,%d\n", + dstshiftX, dstshiftY); + GCDBG(GCZONE_SURF, " surface offset (bytes) = 0x%08X\n", + dstbyteshift); + GCDBG(GCZONE_SURF, " realignment = %d\n", + dstalign); + + if ((srcformat->format == GCREG_DE_FORMAT_NV12) || + (dstalign != 0) || + ((srcalign != 0) && (srcinfo->angle == batch->dstangle))) { + /* Compute the source offset in pixels needed to compensate + * for the surface base address misalignment if any. */ + srcalign = get_pixel_offset(srcdesc, srcformat, 0); + + /* Compute the surface offsets in bytes. */ + srcbyteshift = srcalign * (int) srcformat->bitspp / 8; + dstbyteshift = batch->dstalign * (int) dstformat->bitspp / 8; + + GCDBG(GCZONE_SURF, "recomputed for single-source setup:\n"); + GCDBG(GCZONE_SURF, " srcalign = %d\n", + srcalign); + GCDBG(GCZONE_SURF, " srcsurf offset (bytes) = 0x%08X\n", + srcbyteshift); + GCDBG(GCZONE_SURF, " dstsurf offset (bytes) = 0x%08X\n", + dstbyteshift); + + switch (srcinfo->angle) { + case ROT_ANGLE_0: + /* Adjust left coordinate. */ + srcleft -= srcalign; + + /* Determine source size. */ + srcsurfwidth = srcgeom->width - srcalign; + srcsurfheight = srcgeom->height; + break; + + case ROT_ANGLE_90: + /* Adjust top coordinate. */ + srctop -= srcalign; + + /* Determine source size. */ + srcsurfwidth = srcgeom->height - srcalign; + srcsurfheight = srcgeom->width; + break; + + case ROT_ANGLE_180: + /* Determine source size. */ + srcsurfwidth = srcgeom->width - srcalign; + srcsurfheight = srcgeom->height; + break; + + case ROT_ANGLE_270: + /* Determine source size. */ + srcsurfwidth = srcgeom->height - srcalign; + srcsurfheight = srcgeom->width; + break; + + default: + srcsurfwidth = 0; + srcsurfheight = 0; + } + + GCDBG(GCZONE_SURF, "srcrect origin = %d,%d\n", + srcleft, srctop); + GCDBG(GCZONE_SURF, "source physical size = %dx%d\n", + srcsurfwidth, srcsurfheight); + + /* Set the physical destination size. */ + physwidth = batch->dstphyswidth; + physheight = batch->dstphysheight; + + /* Disable multi source for YUV and for the cases where + * the destination and the base address alignment does + * not match. */ + multisrc = 0; + GCDBG(GCZONE_SURF, "multi-source disabled.\n"); + } else { + /* Source origin is not used in multi-source setup. */ + srcleft = 0; + srctop = 0; + + /* Adjust the destination to match the source geometry. */ + switch (srcinfo->angle) { + case ROT_ANGLE_0: + dstleft -= srcalign; + dstright -= srcalign; + + /* Apply the source alignment. */ + if ((batch->dstangle == ROT_ANGLE_0) || + (batch->dstangle == ROT_ANGLE_180)) { + physwidth = batch->dstphyswidth - srcalign; + physheight = batch->dstphysheight; + } else { + physwidth = batch->dstphyswidth; + physheight = batch->dstphysheight - srcalign; + } + break; + + case ROT_ANGLE_90: + dsttop -= srcalign; + dstbottom -= srcalign; + + /* Apply the source alignment. */ + if ((batch->dstangle == ROT_ANGLE_0) || + (batch->dstangle == ROT_ANGLE_180)) { + physwidth = batch->dstphyswidth; + physheight = batch->dstphysheight - srcalign; + } else { + physwidth = batch->dstphyswidth - srcalign; + physheight = batch->dstphysheight; + } + break; + + case ROT_ANGLE_180: + /* Apply the source alignment. */ + if ((batch->dstangle == ROT_ANGLE_0) || + (batch->dstangle == ROT_ANGLE_180)) { + physwidth = batch->dstphyswidth - srcalign; + physheight = batch->dstphysheight; + } else { + physwidth = batch->dstphyswidth; + physheight = batch->dstphysheight - srcalign; + } + break; + + case ROT_ANGLE_270: + /* Apply the source alignment. */ + if ((batch->dstangle == ROT_ANGLE_0) || + (batch->dstangle == ROT_ANGLE_180)) { + physwidth = batch->dstphyswidth; + physheight = batch->dstphysheight - srcalign; + } else { + physwidth = batch->dstphyswidth - srcalign; + physheight = batch->dstphysheight; + } + break; + + default: + physwidth = 0; + physheight = 0; + } + + /* Source geometry is now the same as the destination. */ + if (orthogonal) { + srcsurfwidth = physheight; + srcsurfheight = physwidth; + } else { + srcsurfwidth = physwidth; + srcsurfheight = physheight; + } + + /* Enable multi-source. */ + multisrc = 1; + GCDBG(GCZONE_SURF, "multi-source enabled.\n"); + } + + /* Verify if the destination has been modified. */ + if ((batch->dstbyteshift != dstbyteshift) || + (batch->physwidth != physwidth) || + (batch->physheight != physheight)) { + /* Set new values. */ + batch->dstbyteshift = dstbyteshift; + batch->physwidth = physwidth; + batch->physheight = physheight; + + /* Mark as modified. */ + batch->batchflags |= BVBATCH_DST; + } + + /* Check if we need to finalize existing batch. */ + if ((batch->batchend != do_blit_end) || + (batch->gcblit.srccount == 4) || + (batch->gcblit.multisrc == 0) || + (multisrc == 0) || + ((batch->batchflags & (BVBATCH_DST | + BVBATCH_CLIPRECT | + BVBATCH_DESTRECT)) != 0)) { + /* Finalize existing batch if any. */ + bverror = batch->batchend(bltparams, batch); + if (bverror != BVERR_NONE) + goto exit; + + /* Initialize the new batch. */ + batch->batchend = do_blit_end; + batch->blockenable = 0; + batch->gcblit.srccount = 0; + batch->gcblit.multisrc = multisrc; + batch->gcblit.rop = srcinfo->rop; + } + + /* Set destination coordinates. */ + batch->left = dstleft; + batch->top = dsttop; + batch->right = dstright; + batch->bottom = dstbottom; + + /* Map the destination. */ + bverror = do_map(dstdesc, batch, &dstmap); + if (bverror != BVERR_NONE) { + bltparams->errdesc = gccontext->bverrorstr; + goto exit; + } + + /* Set the new destination. */ + bverror = set_dst(bltparams, batch, dstmap); + if (bverror != BVERR_NONE) + goto exit; + + /* Reset the modified flag. */ + batch->batchflags &= ~(BVBATCH_DST | + BVBATCH_CLIPRECT | + BVBATCH_DESTRECT); + + /* Map the source. */ + bverror = do_map(srcdesc, batch, &srcmap); + if (bverror != BVERR_NONE) { + bltparams->errdesc = gccontext->bverrorstr; + goto exit; + } + + /*************************************************************** + ** Configure source. + */ + + /* We need to walk in blocks if the source and the destination + * surfaces are orthogonal to each other. */ + batch->blockenable = orthogonal; + + /* Allocate command buffer. */ + bverror = claim_buffer(bltparams, batch, + sizeof(struct gcmosrc), + (void **) &gcmosrc); + if (bverror != BVERR_NONE) + goto exit; + + /* Shortcut to the register index. */ + index = batch->gcblit.srccount; + + add_fixup(bltparams, batch, &gcmosrc->address, srcbyteshift); + + /* Set surface parameters. */ + gcmosrc->address_ldst = gcmosrc_address_ldst[index]; + gcmosrc->address = GET_MAP_HANDLE(srcmap); + + gcmosrc->stride_ldst = gcmosrc_stride_ldst[index]; + gcmosrc->stride = srcgeom->virtstride; + + gcmosrc->rotation_ldst = gcmosrc_rotation_ldst[index]; + gcmosrc->rotation.raw = 0; + gcmosrc->rotation.reg.surf_width = srcsurfwidth; + + gcmosrc->config_ldst = gcmosrc_config_ldst[index]; + gcmosrc->config.raw = 0; + gcmosrc->config.reg.swizzle = srcformat->swizzle; + gcmosrc->config.reg.format = srcformat->format; + + gcmosrc->origin_ldst = gcmosrc_origin_ldst[index]; + gcmosrc->origin.reg.x = srcleft; + gcmosrc->origin.reg.y = srctop; + + gcmosrc->size_ldst = gcmosrc_size_ldst[index]; + gcmosrc->size.reg = gcregsrcsize_max; + + gcmosrc->rotationheight_ldst + = gcmosrc_rotationheight_ldst[index]; + gcmosrc->rotationheight.reg.height = srcsurfheight; + + gcmosrc->rotationangle_ldst + = gcmosrc_rotationangle_ldst[index]; + gcmosrc->rotationangle.raw = 0; + gcmosrc->rotationangle.reg.src = rotencoding[srcinfo->angle]; + gcmosrc->rotationangle.reg.dst = rotencoding[batch->dstangle]; + gcmosrc->rotationangle.reg.src_mirror = srcinfo->mirror; + gcmosrc->rotationangle.reg.dst_mirror = GCREG_MIRROR_NONE; + + gcmosrc->rop_ldst = gcmosrc_rop_ldst[index]; + gcmosrc->rop.raw = 0; + gcmosrc->rop.reg.type = GCREG_ROP_TYPE_ROP3; + gcmosrc->rop.reg.fg = (unsigned char) batch->gcblit.rop; + + gcmosrc->mult_ldst = gcmosrc_mult_ldst[index]; + gcmosrc->mult.raw = 0; + gcmosrc->mult.reg.srcglobalpremul + = GCREG_COLOR_MULTIPLY_MODES_SRC_GLOBAL_PREMULTIPLY_DISABLE; + + if ((srcgeom->format & OCDFMTDEF_NON_PREMULT) != 0) + gcmosrc->mult.reg.srcpremul + = GCREG_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_ENABLE; + else + gcmosrc->mult.reg.srcpremul + = GCREG_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_DISABLE; + + if ((dstgeom->format & OCDFMTDEF_NON_PREMULT) != 0) { + gcmosrc->mult.reg.dstpremul + = GCREG_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_ENABLE; + + gcmosrc->mult.reg.dstdemul + = GCREG_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY_ENABLE; + } else { + gcmosrc->mult.reg.dstpremul + = GCREG_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_DISABLE; + + gcmosrc->mult.reg.dstdemul + = GCREG_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY_DISABLE; + } + + if (srcformat->format == GCREG_DE_FORMAT_NV12) { + struct gcmosrcplanaryuv *yuv; + int uvshift = srcbyteshift; + +#if 0 + /* TODO: needs rework */ + if (multisrc && (srcsurftop % 2)) { + /* We can't shift the uv plane by an odd number + * of rows. */ + BVSETBLTERROR(BVERR_SRC1RECT, + "src/dst y coordinate combination" + " not supported"); + goto exit; + } +#endif + + bverror = claim_buffer(bltparams, batch, + sizeof(struct gcmosrcplanaryuv), + (void **) &yuv); + if (bverror != BVERR_NONE) + goto exit; + + yuv->uplaneaddress_ldst = + gcmosrc_uplaneaddress_ldst[index]; + yuv->uplanestride_ldst = + gcmosrc_uplanestride_ldst[index]; + yuv->vplaneaddress_ldst = + gcmosrc_vplaneaddress_ldst[index]; + yuv->vplanestride_ldst = + gcmosrc_vplanestride_ldst[index]; + +#if 0 + /* TODO: needs rework */ + if (multisrc) { + /* UV plane is half height. */ + uvshift = (srcsurftop / 2) + * (int) srcgeom->virtstride + + srcsurfleft + * (int) srcformat->bitspp / 8; + } else { + /* No shift needed for single source walker. */ + uvshift = 0; + } +#endif + + GCDBG(GCZONE_SURF, " uvshift = 0x%08X (%d)\n", + uvshift, uvshift); + + /* add fixed offset from Y plane */ + uvshift += srcgeom->virtstride * srcgeom->height; + + GCDBG(GCZONE_SURF, " final uvshift = 0x%08X (%d)\n", + uvshift, uvshift); + + yuv->uplaneaddress = GET_MAP_HANDLE(srcmap); + add_fixup(bltparams, batch, &yuv->uplaneaddress, uvshift); + + yuv->uplanestride = srcgeom->virtstride; + + yuv->vplaneaddress = GET_MAP_HANDLE(srcmap); + add_fixup(bltparams, batch, &yuv->vplaneaddress, uvshift); + + yuv->vplanestride = srcgeom->virtstride; + } + + if (srcgca != NULL) { + gcmosrc->alphacontrol_ldst + = gcmosrc_alphacontrol_ldst[index]; + gcmosrc->alphacontrol.raw = 0; + gcmosrc->alphacontrol.reg.enable + = GCREG_ALPHA_CONTROL_ENABLE_ON; + + /* Allocate command buffer. */ + bverror = claim_buffer(bltparams, batch, + sizeof(struct gcmosrcalpha), + (void **) &gcmosrcalpha); + if (bverror != BVERR_NONE) + goto exit; + + gcmosrcalpha->alphamodes_ldst + = gcmosrcalpha_alphamodes_ldst[index]; + gcmosrcalpha->alphamodes.raw = 0; + gcmosrcalpha->alphamodes.reg.src_global_alpha + = srcgca->src_global_alpha_mode; + gcmosrcalpha->alphamodes.reg.dst_global_alpha + = srcgca->dst_global_alpha_mode; + + gcmosrcalpha->alphamodes.reg.src_blend + = srcgca->srcconfig->factor_mode; + gcmosrcalpha->alphamodes.reg.src_color_reverse + = srcgca->srcconfig->color_reverse; + + gcmosrcalpha->alphamodes.reg.dst_blend + = srcgca->dstconfig->factor_mode; + gcmosrcalpha->alphamodes.reg.dst_color_reverse + = srcgca->dstconfig->color_reverse; + + GCDBG(GCZONE_BLEND, "dst blend:\n"); + GCDBG(GCZONE_BLEND, " factor = %d\n", + gcmosrcalpha->alphamodes.reg.dst_blend); + GCDBG(GCZONE_BLEND, " inverse = %d\n", + gcmosrcalpha->alphamodes.reg.dst_color_reverse); + + GCDBG(GCZONE_BLEND, "src blend:\n"); + GCDBG(GCZONE_BLEND, " factor = %d\n", + gcmosrcalpha->alphamodes.reg.src_blend); + GCDBG(GCZONE_BLEND, " inverse = %d\n", + gcmosrcalpha->alphamodes.reg.src_color_reverse); + + gcmosrcalpha->srcglobal_ldst + = gcmosrcalpha_srcglobal_ldst[index]; + gcmosrcalpha->srcglobal.raw = srcgca->src_global_color; + + gcmosrcalpha->dstglobal_ldst + = gcmosrcalpha_dstglobal_ldst[index]; + gcmosrcalpha->dstglobal.raw = srcgca->dst_global_color; + } else { + GCDBG(GCZONE_BLEND, "blending disabled.\n"); + + gcmosrc->alphacontrol_ldst + = gcmosrc_alphacontrol_ldst[index]; + gcmosrc->alphacontrol.raw = 0; + gcmosrc->alphacontrol.reg.enable + = GCREG_ALPHA_CONTROL_ENABLE_OFF; + } + + batch->gcblit.srccount += 1; + +exit: + GCEXITARG(GCZONE_BLIT, "bv%s = %d\n", + (bverror == BVERR_NONE) ? "result" : "error", bverror); + return bverror; +} diff --git a/drivers/misc/gcx/gcbv/gcbuffer.c b/drivers/misc/gcx/gcbv/gcbuffer.c new file mode 100644 index 0000000..484eb08 --- /dev/null +++ b/drivers/misc/gcx/gcbv/gcbuffer.c @@ -0,0 +1,405 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2012 Vivante Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * BSD LICENSE + * + * Copyright(c) 2012 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_BATCH_ALLOC (1 << 0) +#define GCZONE_BUFFER_ALLOC (1 << 1) +#define GCZONE_FIXUP_ALLOC (1 << 2) +#define GCZONE_FIXUP (1 << 3) + +GCDBG_FILTERDEF(gcbuffer, GCZONE_NONE, + "batchalloc", + "bufferalloc" + "fixupalloc", + "fixup") + + +/******************************************************************************* +** Miscellaneous defines and macros. +*/ + +#define GC_BUFFER_INIT_SIZE \ +( \ + GC_BUFFER_SIZE - max(sizeof(struct gcbuffer), GC_BUFFER_RESERVE) \ +) + +#define GC_BUFFER_RESERVE \ +( \ + sizeof(struct gcmopipesel) + \ + sizeof(struct gcmommumaster) + \ + sizeof(struct gcmommuflush) + \ + sizeof(struct gcmosignal) + \ + sizeof(struct gccmdend) \ +) + + +/******************************************************************************* + * Batch/command buffer management. + */ + +enum bverror do_end(struct bvbltparams *bvbltparams, + struct gcbatch *gcbatch) +{ + return BVERR_NONE; +} + +enum bverror allocate_batch(struct bvbltparams *bvbltparams, + struct gcbatch **gcbatch) +{ + enum bverror bverror; + struct gccontext *gccontext = get_context(); + struct gcbatch *temp; + struct gcbuffer *gcbuffer; + + GCENTER(GCZONE_BATCH_ALLOC); + + /* Lock access to batch management. */ + GCLOCK(&gccontext->batchlock); + + if (list_empty(&gccontext->batchvac)) { + temp = gcalloc(struct gcbatch, sizeof(struct gcbatch)); + if (temp == NULL) { + BVSETBLTERROR(BVERR_OOM, + "batch header allocation failed"); + goto exit; + } + + GCDBG(GCZONE_BATCH_ALLOC, "allocated new batch = 0x%08X\n", + (unsigned int) temp); + } else { + struct list_head *head; + head = gccontext->batchvac.next; + temp = list_entry(head, struct gcbatch, link); + list_del(head); + + GCDBG(GCZONE_BATCH_ALLOC, "reusing batch = 0x%08X\n", + (unsigned int) temp); + } + + memset(temp, 0, sizeof(struct gcbatch)); + temp->structsize = sizeof(struct gcbatch); + temp->batchend = do_end; + INIT_LIST_HEAD(&temp->buffer); + INIT_LIST_HEAD(&temp->unmap); + INIT_LIST_HEAD(&temp->link); + + bverror = append_buffer(bvbltparams, temp, &gcbuffer); + if (bverror != BVERR_NONE) { + free_batch(temp); + goto exit; + } + + *gcbatch = temp; + + GCDBG(GCZONE_BATCH_ALLOC, "batch allocated = 0x%08X\n", + (unsigned int) temp); + +exit: + /* Unlock access to batch management. */ + GCUNLOCK(&gccontext->batchlock); + + GCEXITARG(GCZONE_BATCH_ALLOC, "bv%s = %d\n", + (bverror == BVERR_NONE) ? "result" : "error", bverror); + return bverror; +} + +void free_batch(struct gcbatch *gcbatch) +{ + struct list_head *head; + struct gccontext *gccontext = get_context(); + struct gcbuffer *gcbuffer; + + GCENTERARG(GCZONE_BATCH_ALLOC, "batch = 0x%08X\n", + (unsigned int) gcbatch); + + /* Lock access. */ + GCLOCK(&gccontext->batchlock); + GCLOCK(&gccontext->bufferlock); + GCLOCK(&gccontext->fixuplock); + GCLOCK(&gccontext->maplock); + + /* Free implicit unmappings. */ + list_splice_init(&gcbatch->unmap, &gccontext->unmapvac); + + /* Free command buffers. */ + while (!list_empty(&gcbatch->buffer)) { + head = gcbatch->buffer.next; + gcbuffer = list_entry(head, struct gcbuffer, link); + + /* Free fixups. */ + list_splice_init(&gcbuffer->fixup, &gccontext->fixupvac); + + /* Free the command buffer. */ + list_move(&gcbuffer->link, &gccontext->buffervac); + } + + /* Free the batch. */ + list_add(&gcbatch->link, &gccontext->batchvac); + + /* Unlock access. */ + GCUNLOCK(&gccontext->maplock); + GCUNLOCK(&gccontext->fixuplock); + GCUNLOCK(&gccontext->bufferlock); + GCUNLOCK(&gccontext->batchlock); + + GCEXIT(GCZONE_BATCH_ALLOC); +} + +enum bverror append_buffer(struct bvbltparams *bvbltparams, + struct gcbatch *gcbatch, + struct gcbuffer **gcbuffer) +{ + enum bverror bverror; + struct gccontext *gccontext = get_context(); + struct gcbuffer *temp; + + GCENTERARG(GCZONE_BUFFER_ALLOC, "batch = 0x%08X\n", + (unsigned int) gcbatch); + + /* Lock access to buffer management. */ + GCLOCK(&gccontext->bufferlock); + + if (list_empty(&gccontext->buffervac)) { + temp = gcalloc(struct gcbuffer, GC_BUFFER_SIZE); + if (temp == NULL) { + BVSETBLTERROR(BVERR_OOM, + "command buffer allocation failed"); + goto exit; + } + + list_add_tail(&temp->link, &gcbatch->buffer); + + GCDBG(GCZONE_BUFFER_ALLOC, "allocated new buffer = 0x%08X\n", + (unsigned int) temp); + } else { + struct list_head *head; + head = gccontext->buffervac.next; + temp = list_entry(head, struct gcbuffer, link); + + list_move_tail(&temp->link, &gcbatch->buffer); + + GCDBG(GCZONE_BUFFER_ALLOC, "reusing buffer = 0x%08X\n", + (unsigned int) temp); + } + + INIT_LIST_HEAD(&temp->fixup); + temp->pixelcount = 0; + temp->head = temp->tail = (unsigned int *) (temp + 1); + temp->available = GC_BUFFER_INIT_SIZE; + + GCDBG(GCZONE_BUFFER_ALLOC, "new buffer appended = 0x%08X\n", + (unsigned int) temp); + + *gcbuffer = temp; + bverror = BVERR_NONE; + +exit: + /* Unlock access to buffer management. */ + GCUNLOCK(&gccontext->bufferlock); + + GCEXITARG(GCZONE_BUFFER_ALLOC, "bv%s = %d\n", + (bverror == BVERR_NONE) ? "result" : "error", bverror); + return bverror; +} + +static enum bverror allocate_fixup(struct bvbltparams *bvbltparams, + struct gcbuffer *gcbuffer, + struct gcfixup **gcfixup) +{ + enum bverror bverror = BVERR_NONE; + struct gccontext *gccontext = get_context(); + struct gcfixup *temp; + + if (list_empty(&gccontext->fixupvac)) { + temp = gcalloc(struct gcfixup, sizeof(struct gcfixup)); + if (temp == NULL) { + BVSETBLTERROR(BVERR_OOM, "fixup allocation failed"); + goto exit; + } + + list_add_tail(&temp->link, &gcbuffer->fixup); + + GCDBG(GCZONE_FIXUP_ALLOC, + "new fixup struct allocated = 0x%08X\n", + (unsigned int) temp); + } else { + struct list_head *head; + head = gccontext->fixupvac.next; + temp = list_entry(head, struct gcfixup, link); + + list_move_tail(&temp->link, &gcbuffer->fixup); + + GCDBG(GCZONE_FIXUP_ALLOC, "fixup struct reused = 0x%08X\n", + (unsigned int) temp); + } + + temp->count = 0; + *gcfixup = temp; + +exit: + return bverror; +} + +enum bverror add_fixup(struct bvbltparams *bvbltparams, + struct gcbatch *gcbatch, + unsigned int *ptr, + unsigned int surfoffset) +{ + enum bverror bverror = BVERR_NONE; + struct gccontext *gccontext = get_context(); + struct list_head *head; + struct gcbuffer *buffer; + struct gcfixup *gcfixup; + + GCENTERARG(GCZONE_FIXUP, "batch = 0x%08X, fixup ptr = 0x%08X\n", + (unsigned int) gcbatch, (unsigned int) ptr); + + /* Lock access to fixup management. */ + GCLOCK(&gccontext->fixuplock); + + /* Get the current command buffer. */ + if (list_empty(&gcbatch->buffer)) { + GCERR("no command buffers are allocated"); + goto exit; + } + head = gcbatch->buffer.prev; + buffer = list_entry(head, struct gcbuffer, link); + + /* No fixups? Allocate one. */ + if (list_empty(&buffer->fixup)) { + GCDBG(GCZONE_FIXUP_ALLOC, "no fixups allocated.\n"); + bverror = allocate_fixup(bvbltparams, buffer, &gcfixup); + if (bverror != BVERR_NONE) + goto exit; + } else { + /* Get the current fixup. */ + head = buffer->fixup.prev; + gcfixup = list_entry(head, struct gcfixup, link); + + /* No more room? */ + if (gcfixup->count == GC_FIXUP_MAX) { + GCDBG(GCZONE_FIXUP_ALLOC, + "out of room, allocating new.\n"); + bverror = allocate_fixup(bvbltparams, buffer, &gcfixup); + if (bverror != BVERR_NONE) + goto exit; + } + } + + GCDBG(GCZONE_FIXUP, "buffer = 0x%08X, fixup struct = 0x%08X\n", + (unsigned int) buffer, (unsigned int) gcfixup); + + gcfixup->fixup[gcfixup->count].dataoffset = ptr - buffer->head; + gcfixup->fixup[gcfixup->count].surfoffset = surfoffset; + gcfixup->count += 1; + + GCDBG(GCZONE_FIXUP, "fixup offset = 0x%08X\n", ptr - buffer->head); + GCDBG(GCZONE_FIXUP, "surface offset = 0x%08X\n", surfoffset); + +exit: + /* Unlock access to fixup management. */ + GCUNLOCK(&gccontext->fixuplock); + + GCEXITARG(GCZONE_FIXUP, "bv%s = %d\n", + (bverror == BVERR_NONE) ? "result" : "error", bverror); + return bverror; +} + +enum bverror claim_buffer(struct bvbltparams *bvbltparams, + struct gcbatch *gcbatch, + unsigned int size, + void **buffer) +{ + enum bverror bverror; + struct list_head *head; + struct gcbuffer *gcbuffer; + + GCENTERARG(GCZONE_BUFFER_ALLOC, "batch = 0x%08X, size = %d\n", + (unsigned int) gcbatch, size); + + if (size > GC_BUFFER_INIT_SIZE) { + GCERR("requested size is too big.\n"); + BVSETBLTERROR(BVERR_OOM, + "command buffer allocation failed"); + goto exit; + } + + /* Get the current command buffer. */ + head = gcbatch->buffer.prev; + gcbuffer = list_entry(head, struct gcbuffer, link); + + GCDBG(GCZONE_BUFFER_ALLOC, "buffer = 0x%08X, available = %d\n", + (unsigned int) gcbuffer, gcbuffer->available); + + if (gcbuffer->available < size) { + bverror = append_buffer(bvbltparams, gcbatch, &gcbuffer); + if (bverror != BVERR_NONE) + goto exit; + } + + *buffer = gcbuffer->tail; + gcbuffer->tail = (unsigned int *) + ((unsigned char *) gcbuffer->tail + size); + gcbuffer->available -= size; + gcbatch->size += size; + bverror = BVERR_NONE; + +exit: + GCEXITARG(GCZONE_BUFFER_ALLOC, "bv%s = %d\n", + (bverror == BVERR_NONE) ? "result" : "error", bverror); + return bverror; +} diff --git a/drivers/misc/gcx/gcbv/gcbv.c b/drivers/misc/gcx/gcbv/gcbv.c index cd666d5..170d4b4 100644 --- a/drivers/misc/gcx/gcbv/gcbv.c +++ b/drivers/misc/gcx/gcbv/gcbv.c @@ -52,335 +52,39 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include "gcmain.h" +#include "gcbv.h" #define GCZONE_NONE 0 #define GCZONE_ALL (~0U) #define GCZONE_MAPPING (1 << 0) -#define GCZONE_BUFFER_ALLOC (1 << 1) -#define GCZONE_BUFFER (1 << 2) -#define GCZONE_FIXUP (1 << 3) -#define GCZONE_FORMAT (1 << 4) -#define GCZONE_COLOR (1 << 5) -#define GCZONE_BLEND (1 << 6) -#define GCZONE_DEST (1 << 7) -#define GCZONE_SURF (1 << 8) -#define GCZONE_DO_FILL (1 << 9) -#define GCZONE_DO_BLIT (1 << 10) -#define GCZONE_DO_FILTER (1 << 11) -#define GCZONE_BATCH (1 << 12) -#define GCZONE_BLIT (1 << 13) -#define GCZONE_CACHE (1 << 14) +#define GCZONE_BUFFER (1 << 1) +#define GCZONE_DEST (1 << 2) +#define GCZONE_SRC (1 << 3) +#define GCZONE_MASK (1 << 4) +#define GCZONE_BATCH (1 << 5) +#define GCZONE_BLIT (1 << 6) +#define GCZONE_CACHE (1 << 7) GCDBG_FILTERDEF(gcbv, GCZONE_NONE, "mapping", "buffer", - "fixup", - "format", - "color", - "blend", "dest", - "surf", - "do_fill", - "do_blit", - "do_filter", + "source", + "mask", "batch", "blit", "cache") /******************************************************************************* -** Miscellaneous defines and macros. +** Global driver data access. */ -#if !defined(BVBATCH_DESTRECT) -#define BVBATCH_DESTRECT (BVBATCH_DSTRECT_ORIGIN | BVBATCH_DSTRECT_SIZE) -#endif - -#if !defined(BVBATCH_SRC1RECT) -#define BVBATCH_SRC1RECT (BVBATCH_SRC1RECT_ORIGIN | BVBATCH_SRC1RECT_SIZE) -#endif - -#if !defined(BVBATCH_SRC2RECT) -#define BVBATCH_SRC2RECT (BVBATCH_SRC2RECT_ORIGIN | BVBATCH_SRC2RECT_SIZE) -#endif - -#define EQ_SIZE(rect1, rect2) \ -( \ - (rect1->width == rect2->width) && (rect1->height == rect2->height) \ -) - -#define STRUCTSIZE(structptr, lastmember) \ -( \ - (size_t) &structptr->lastmember + \ - sizeof(structptr->lastmember) - \ - (size_t) structptr \ -) - -#define GET_MAP_HANDLE(map) \ -( \ - ((struct bvbuffmapinfo *) map->handle)->handle \ -) - -#define GC_CLIP_RESET_LEFT ((unsigned short) 0) -#define GC_CLIP_RESET_TOP ((unsigned short) 0) -#define GC_CLIP_RESET_RIGHT ((unsigned short) ((1 << 15) - 1)) -#define GC_CLIP_RESET_BOTTOM ((unsigned short) ((1 << 15) - 1)) - -#define GPU_CMD_SIZE (sizeof(unsigned int) * 2) - -#define GC_BUFFER_RESERVE \ -( \ - sizeof(struct gcmopipesel) + \ - sizeof(struct gcmommumaster) + \ - sizeof(struct gcmommuflush) + \ - sizeof(struct gcmosignal) + \ - sizeof(struct gccmdend) \ -) - -#if GCDEBUG_ENABLE -#define GCDUMPSCHEDULE() { \ - struct list_head *__temphead__; \ - struct gcschedunmap *__tempunmap__; \ - GCDBG(GCZONE_MAPPING, "scheduled unmaps:\n"); \ - list_for_each(__temphead__, &batch->unmap) { \ - __tempunmap__ = list_entry(__temphead__, \ - struct gcschedunmap, \ - link); \ - GCDBG(GCZONE_MAPPING, \ - " handle = 0x%08X\n", \ - (unsigned int) __tempunmap__->handle); \ - } \ +struct gccontext *get_context(void) +{ + static struct gccontext gccontext; + return &gccontext; } -#else -#define GCDUMPSCHEDULE() -#endif - - -/******************************************************************************* -** Internal structures. -*/ - -struct gcblendconfig { - unsigned char factor_mode; - unsigned char color_reverse; - - unsigned char src1used; - unsigned char src2used; -}; - -struct bvblendxlate { - unsigned char match1; - unsigned char match2; - - struct gcblendconfig k1; - struct gcblendconfig k2; -}; - -/* Alpha blending descriptor. */ -struct gcalpha { - unsigned int src_global_color; - unsigned int dst_global_color; - - unsigned char src_global_alpha_mode; - unsigned char dst_global_alpha_mode; - - struct gcblendconfig *k1; - struct gcblendconfig *k2; - - struct gcblendconfig *srcconfig; - struct gcblendconfig *dstconfig; - - unsigned int src1used; - unsigned int src2used; -}; - -/* Used by blitters to define an array of valid sources. */ -struct srcinfo { - /* BLTsville source index (0 for src1 and 1 for src2). */ - int index; - - /* Source surface buffer descriptor. */ - union bvinbuff buf; - - /* Source surface geometry. */ - struct bvsurfgeom *geom; - - /* Source rectangle. */ - struct bvrect *rect; - - /* Source surface format. */ - struct bvformatxlate *format; - - /* Source rotation angle. */ - int angle; - unsigned int rot; - - /* Mirror setting. */ - unsigned int mirror; - - /* ROP. */ - unsigned short rop; - - /* Blending info. */ - struct gcalpha *gca; -}; - -/* bvbuffmap struct attachment. */ -struct bvbuffmapinfo { - /* Mapped handle for the buffer. */ - unsigned long handle; - - /* Number of times the client explicitly mapped this buffer. */ - int usermap; - - /* Number of times implicit mapping happened. */ - int automap; -}; - -/* Operation finalization call. */ -struct gcbatch; -typedef enum bverror (*gcbatchend) (struct bvbltparams *bltparams, - struct gcbatch *batch); - -/* Blit states. */ -struct gcblit { - unsigned int srccount; - unsigned int multisrc; - unsigned short rop; -}; - -/* Batch header. */ -struct gcbatch { - /* Used to ID structure version. */ - unsigned int structsize; - - /* Batch change flags. */ - unsigned long batchflags; - - /* Pointer to the function to finalize the current operation. */ - gcbatchend batchend; - - /* State of the current operation. */ - struct gcblit gcblit; - - /* Destination format. */ - struct bvformatxlate *dstformat; - - /* Clipping deltas; used to correct the source coordinates for - * single source blits. */ - int deltaleft; - int deltatop; - int deltaright; - int deltabottom; - - /* Clipped destination rectangle coordinates. */ - unsigned short clippedleft; - unsigned short clippedtop; - unsigned short clippedright; - unsigned short clippedbottom; - - /* Destination base address alignment in pixels. */ - int dstalign; - - /* Destination origin offset. */ - unsigned int dstoffsetX; - unsigned int dstoffsetY; - - /* Rotation angle. */ - int dstangle; - - /* Geometry size of the destination surface. */ - unsigned int dstwidth; - unsigned int dstheight; - - /* Physical size of the destination surface. */ - unsigned int dstphyswidth; - unsigned int dstphysheight; - - /* Computed destination rectangle coordinates; in multi-source - * setup can be modified to match new destination and source - * geometry. */ - unsigned short left; - unsigned short top; - unsigned short right; - unsigned short bottom; - - /* Physical size of the matched destination and source surfaces - * for multi-source setup. */ - unsigned int physwidth; - unsigned int physheight; - - /* Alignment byte offset for the destination surface; in multi- - * source setup can be modified to match new destination and source - * geometry. */ - int dstbyteshift; - - /* Block walker enable. */ - int blockenable; - -#if GCDEBUG_ENABLE - /* Rectangle validation storage. */ - struct bvrect prevdstrect; - struct bvrect prevsrc1rect; - struct bvrect prevsrc2rect; - struct bvrect prevmaskrect; -#endif - - /* Total size of the command buffer. */ - unsigned int size; - - /* Command buffer list. */ - struct gcbuffer *bufhead; - struct gcbuffer *buftail; - - /* Scheduled implicit unmappings (gcschedunmap). */ - struct list_head unmap; -}; - -/* Vacant batch header. */ -struct gcvacbatch { - struct gcvacbatch *next; -}; - -/* Callback information. */ -struct gccallbackinfo { - /* BLTsville callback function. */ - void (*callbackfn) (struct bvcallbackerror *err, - unsigned long callbackdata); - - /* Callback data. */ - unsigned long callbackdata; - - /* Previous/next callback information. */ - struct list_head link; -}; - -/* Driver context. */ -struct gccontext { - /* Last generated error message. */ - char bverrorstr[128]; - - /* Dynamically allocated structure cache. */ - struct list_head vac_unmap; /* gcschedunmap */ - struct bvbuffmap *vac_buffmap; - struct gcbuffer *vac_buffers; - struct gcfixup *vac_fixups; - struct gcvacbatch *vac_batches; - - /* Callback lists. */ - struct list_head callbacklist; - struct list_head callbackvac; - - /* Access locks. */ - GCLOCK_TYPE batchlock; - GCLOCK_TYPE bufferlock; - GCLOCK_TYPE fixuplock; - GCLOCK_TYPE maplock; - GCLOCK_TYPE callbacklock; -}; - -static struct gccontext gccontext; /******************************************************************************* @@ -391,46 +95,85 @@ static struct gccontext gccontext; #define GCDUMPBATCH(batch) \ dumpbatch(batch) -static void dumpbatch(struct gcbatch *batch) -{ - if ((GCDBGFILTER.zone & (GCZONE_BUFFER)) != 0) { - struct gcbuffer *buffer; - unsigned int i, size; - struct gcfixup *fixup; - - GCDBG(GCZONE_BUFFER, "BATCH DUMP (0x%08X)\n", - (unsigned int) batch); - - buffer = batch->bufhead; - while (buffer != NULL) { - fixup = buffer->fixuphead; - while (fixup != NULL) { - GCDBG(GCZONE_BUFFER, - " Fixup table @ 0x%08X, count = %d:\n", - (unsigned int) fixup, fixup->count); - - for (i = 0; i < fixup->count; i += 1) { - GCDBG(GCZONE_BUFFER, " [%02d]" - " buffer offset = 0x%08X," - " surface offset = 0x%08X\n", - i, - fixup->fixup[i].dataoffset * 4, - fixup->fixup[i].surfoffset); - } +#define GCVERIFYBATCH(changeflags, prevrect, currrect) \ + verify_batch(changeflags, prevrect, currrect) - fixup = fixup->next; +static void dumpbatch(struct gcbatch *gcbatch) +{ + struct list_head *gcbufferhead; + struct gcbuffer *gcbuffer; + struct list_head *gcfixuphead; + struct gcfixup *gcfixup; + unsigned int i, size; + + if ((GCDBGFILTER.zone & (GCZONE_BUFFER)) == 0) + return; + + GCDBG(GCZONE_BUFFER, "BATCH DUMP (0x%08X)\n", + (unsigned int) gcbatch); + + list_for_each(gcbufferhead, &gcbatch->buffer) { + gcbuffer = list_entry(gcbufferhead, struct gcbuffer, link); + + list_for_each(gcfixuphead, &gcbuffer->fixup) { + gcfixup = list_entry(gcfixuphead, struct gcfixup, link); + + GCDBG(GCZONE_BUFFER, + " Fixup table @ 0x%08X, count = %d:\n", + (unsigned int) gcfixup, gcfixup->count); + + for (i = 0; i < gcfixup->count; i += 1) { + GCDBG(GCZONE_BUFFER, " [%02d]" + " buffer offset = 0x%08X," + " surface offset = 0x%08X\n", + i, + gcfixup->fixup[i].dataoffset * 4, + gcfixup->fixup[i].surfoffset); } + } - size = (unsigned char *) buffer->tail - - (unsigned char *) buffer->head; - GCDUMPBUFFER(GCZONE_BUFFER, buffer->head, 0, size); + size = (unsigned char *) gcbuffer->tail + - (unsigned char *) gcbuffer->head; + GCDUMPBUFFER(GCZONE_BUFFER, gcbuffer->head, 0, size); + } +} - buffer = buffer->next; +static void verify_batch(unsigned int changeflags, + struct bvrect *prevrect, + struct bvrect *currrect) +{ + if ((changeflags & 1) == 0) { + /* Origin did not change. */ + if ((prevrect->left != currrect->left) || + (prevrect->top != currrect->top)) { + GCERR("origin changed\n"); + GCERR(" previous = %d,%d\n", + prevrect->left, prevrect->top); + GCERR(" current = %d,%d\n", + currrect->left, currrect->top); + } + } + + if ((changeflags & 2) == 0) { + /* Size did not change. */ + if ((prevrect->width != currrect->width) || + (prevrect->height != currrect->height)) { + GCERR("size changed\n"); + GCERR(" previous = %dx%d\n", + prevrect->width, prevrect->height); + GCERR(" current = %dx%d\n", + currrect->width, currrect->height); } } + + prevrect->left = currrect->left; + prevrect->top = currrect->top; + prevrect->width = currrect->width; + prevrect->height = currrect->height; } #else -# define GCDUMPBATCH(...) +#define GCDUMPBATCH(...) +#define GCVERIFYBATCH(...) #endif @@ -438,29 +181,15 @@ static void dumpbatch(struct gcbatch *batch) * Error handling. */ -#define BVSETERROR(error, message, ...) \ -do { \ - snprintf(gccontext.bverrorstr, sizeof(gccontext.bverrorstr), \ - message, ##__VA_ARGS__); \ - GCDUMPSTRING("%s(%d): [ERROR] %s\n", __func__, __LINE__, \ - gccontext.bverrorstr); \ - bverror = error; \ -} while (0) - -#define BVSETBLTERROR(error, message, ...) \ -do { \ - BVSETERROR(error, message, ##__VA_ARGS__); \ - bltparams->errdesc = gccontext.bverrorstr; \ -} while (0) - #define BVSETBLTSURFERROR(errorid, errordesc) \ do { \ - snprintf(gccontext.bverrorstr, sizeof(gccontext.bverrorstr), \ + struct gccontext *tmpcontext = get_context(); \ + snprintf(tmpcontext->bverrorstr, sizeof(tmpcontext->bverrorstr), \ g_surferr[errorid].message, errordesc.id); \ GCDUMPSTRING("%s(%d): [ERROR] %s\n", __func__, __LINE__, \ - gccontext.bverrorstr); \ + tmpcontext->bverrorstr); \ bverror = errordesc.base + g_surferr[errorid].offset; \ - bltparams->errdesc = gccontext.bverrorstr; \ + bvbltparams->errdesc = tmpcontext->bverrorstr; \ } while (0) #define GCBVERR_DESC 0 @@ -522,27 +251,41 @@ static struct bvsurferrorid g_masksurferr = { "mask", BVERR_MASKDESC }; * Callback info management. */ +/* Callback information. */ +struct gccallbackinfo { + /* BLTsville callback function. */ + void (*callbackfn) (struct bvcallbackerror *err, + unsigned long callbackdata); + + /* Callback data. */ + unsigned long callbackdata; + + /* Previous/next callback information. */ + struct list_head link; +}; + static enum bverror get_callbackinfo(struct gccallbackinfo **gccallbackinfo) { enum bverror bverror; + struct gccontext *gccontext = get_context(); struct gccallbackinfo *temp; /* Lock access to callback info lists. */ - GCLOCK(&gccontext.callbacklock); + GCLOCK(&gccontext->callbacklock); - if (list_empty(&gccontext.callbackvac)) { + if (list_empty(&gccontext->callbackvac)) { temp = gcalloc(struct gccallbackinfo, sizeof(struct gccallbackinfo)); if (temp == NULL) { bverror = BVERR_OOM; goto exit; } - list_add(&temp->link, &gccontext.callbacklist); + list_add(&temp->link, &gccontext->callbacklist); } else { struct list_head *head; - head = gccontext.callbackvac.next; + head = gccontext->callbackvac.next; temp = list_entry(head, struct gccallbackinfo, link); - list_move(head, &gccontext.callbacklist); + list_move(head, &gccontext->callbacklist); } *gccallbackinfo = temp; @@ -550,20 +293,22 @@ static enum bverror get_callbackinfo(struct gccallbackinfo **gccallbackinfo) exit: /* Unlock access to callback info lists. */ - GCUNLOCK(&gccontext.callbacklock); + GCUNLOCK(&gccontext->callbacklock); return bverror; } static void free_callback(struct gccallbackinfo *gccallbackinfo) { + struct gccontext *gccontext = get_context(); + /* Lock access to callback info lists. */ - GCLOCK(&gccontext.callbacklock); + GCLOCK(&gccontext->callbacklock); - list_move(&gccallbackinfo->link, &gccontext.callbackvac); + list_move(&gccallbackinfo->link, &gccontext->callbackvac); /* Unlock access to callback info lists. */ - GCUNLOCK(&gccontext.callbacklock); + GCUNLOCK(&gccontext->callbacklock); } void gccallback(void *callbackparam) @@ -586,1780 +331,59 @@ void gccallback(void *callbackparam) /******************************************************************************* - * Memory management. + * Program the destination. */ -static enum bverror do_map(struct bvbuffdesc *bvbuffdesc, - struct gcbatch *batch, - struct bvbuffmap **map) -{ - static const int mapsize - = sizeof(struct bvbuffmap) - + sizeof(struct bvbuffmapinfo); - - enum bverror bverror; - struct bvbuffmap *bvbuffmap; - struct bvbuffmapinfo *bvbuffmapinfo; - struct bvphysdesc *bvphysdesc; - bool mappedbyothers; - struct gcmap gcmap; - struct gcschedunmap *gcschedunmap; - - GCENTERARG(GCZONE_MAPPING, "bvbuffdesc = 0x%08X\n", - (unsigned int) bvbuffdesc); - - /* Lock access to the mapping list. */ - GCLOCK(&gccontext.maplock); - - /* Try to find existing mapping. */ - bvbuffmap = bvbuffdesc->map; - while (bvbuffmap != NULL) { - if (bvbuffmap->bv_unmap == bv_unmap) - break; - bvbuffmap = bvbuffmap->nextmap; - } - - /* Not mapped yet? */ - if (bvbuffmap == NULL) { - /* New mapping, allocate a record. */ - if (gccontext.vac_buffmap == NULL) { - bvbuffmap = gcalloc(struct bvbuffmap, mapsize); - if (bvbuffmap == NULL) { - BVSETERROR(BVERR_OOM, - "failed to allocate mapping record"); - goto fail; - } - - bvbuffmap->structsize = sizeof(struct bvbuffmap); - bvbuffmap->bv_unmap = bv_unmap; - bvbuffmap->handle = (unsigned long) (bvbuffmap + 1); - } else { - bvbuffmap = gccontext.vac_buffmap; - gccontext.vac_buffmap = bvbuffmap->nextmap; - } - - /* Setup buffer mapping. Here we need to check and make sure - * that the buffer starts at a location that is supported by - * the hw. If it is not, offset is computed and the buffer is - * extended by the value of the offset. */ - gcmap.gcerror = GCERR_NONE; - gcmap.handle = 0; - - if (bvbuffdesc->auxtype == BVAT_PHYSDESC) { - bvphysdesc = (struct bvphysdesc *) bvbuffdesc->auxptr; - - if (bvphysdesc->structsize < - STRUCTSIZE(bvphysdesc, pageoffset)) { - BVSETERROR(BVERR_BUFFERDESC_VERS, - "unsupported bvphysdesc version"); - goto fail; - } - - gcmap.buf.offset = bvphysdesc->pageoffset; - gcmap.pagesize = bvphysdesc->pagesize; - gcmap.pagearray = bvphysdesc->pagearray; - gcmap.size = bvbuffdesc->length; - - GCDBG(GCZONE_MAPPING, "new mapping (%s):\n", - (batch == NULL) ? "explicit" : "implicit"); - GCDBG(GCZONE_MAPPING, "pagesize = %lu\n", - bvphysdesc->pagesize); - GCDBG(GCZONE_MAPPING, "pagearray = 0x%08X\n", - (unsigned int) bvphysdesc->pagearray); - GCDBG(GCZONE_MAPPING, "pageoffset = %lu\n", - bvphysdesc->pageoffset); - GCDBG(GCZONE_MAPPING, "mapping size = %d\n", - gcmap.size); - } else { - gcmap.buf.logical = bvbuffdesc->virtaddr; - gcmap.pagesize = 0; - gcmap.pagearray = NULL; - gcmap.size = bvbuffdesc->length; - - GCDBG(GCZONE_MAPPING, "new mapping (%s):\n", - (batch == NULL) ? "explicit" : "implicit"); - GCDBG(GCZONE_MAPPING, "specified virtaddr = 0x%08X\n", - (unsigned int) bvbuffdesc->virtaddr); - GCDBG(GCZONE_MAPPING, "aligned virtaddr = 0x%08X\n", - (unsigned int) gcmap.buf.logical); - GCDBG(GCZONE_MAPPING, "mapping size = %d\n", - gcmap.size); - } - - gc_map_wrapper(&gcmap); - if (gcmap.gcerror != GCERR_NONE) { - BVSETERROR(BVERR_OOM, - "unable to allocate gccore memory"); - goto fail; - } - - /* Set map handle. */ - bvbuffmapinfo = (struct bvbuffmapinfo *) bvbuffmap->handle; - bvbuffmapinfo->handle = gcmap.handle; - - /* Initialize reference counters. */ - if (batch == NULL) { - /* Explicit mapping. */ - bvbuffmapinfo->usermap = 1; - bvbuffmapinfo->automap = 0; - } else { - /* Implicit mapping; if there are existing mappings - * from other implementations, mark this an explicit - * mapping as well. */ - mappedbyothers = (bvbuffdesc->map != NULL); - GCDBG(GCZONE_MAPPING, "%smapped by others.\n", - mappedbyothers ? "" : "not "); - - bvbuffmapinfo->usermap = mappedbyothers ? 1 : 0; - bvbuffmapinfo->automap = 1; - } - - /* Add the record to the list of mappings. */ - bvbuffmap->nextmap = bvbuffdesc->map; - bvbuffdesc->map = bvbuffmap; - } else { - /* Mapping already exists. */ - bvbuffmapinfo = (struct bvbuffmapinfo *) bvbuffmap->handle; - - /* Advance reference counters. */ - if (batch == NULL) { - /* Explicit mapping. */ - GCDBG(GCZONE_MAPPING, "explicit map.\n"); - bvbuffmapinfo->usermap += 1; - } else { - /* Implicit mapping. */ - GCDBG(GCZONE_MAPPING, "implicit map.\n"); - bvbuffmapinfo->automap += 1; - } - - GCDBG(GCZONE_MAPPING, "mapping exists.\n"); - } - - GCDBG(GCZONE_MAPPING, "bvbuffmap = 0x%08X\n", - (unsigned int) bvbuffmap); - GCDBG(GCZONE_MAPPING, "explicit count = %d\n", - bvbuffmapinfo->usermap); - GCDBG(GCZONE_MAPPING, "implicit count = %d\n", - bvbuffmapinfo->automap); - - /* Schedule for unmapping. */ - if (batch != NULL) { - if (list_empty(&gccontext.vac_unmap)) { - gcschedunmap = gcalloc(struct gcschedunmap, - sizeof(struct gcschedunmap)); - if (gcschedunmap == NULL) { - BVSETERROR(BVERR_OOM, - "failed to schedule unmapping"); - goto fail; - } - list_add(&gcschedunmap->link, &batch->unmap); - } else { - struct list_head *head; - head = gccontext.vac_unmap.next; - gcschedunmap = list_entry(head, - struct gcschedunmap, - link); - list_move(&gcschedunmap->link, &batch->unmap); - } - - gcschedunmap->handle = (unsigned long) bvbuffdesc; - - GCDBG(GCZONE_MAPPING, "scheduled for unmapping.\n"); - GCDUMPSCHEDULE(); - } - - /* Set the map pointer. */ - *map = bvbuffmap; - - /* Unlock access to the mapping list. */ - GCUNLOCK(&gccontext.maplock); - - GCEXITARG(GCZONE_MAPPING, "handle = 0x%08X\n", - bvbuffmapinfo->handle); - return BVERR_NONE; - -fail: - if (bvbuffmap != NULL) { - bvbuffmap->nextmap = gccontext.vac_buffmap; - gccontext.vac_buffmap = bvbuffmap; - } - - /* Unlock access to the mapping list. */ - GCUNLOCK(&gccontext.maplock); - - GCEXITARG(GCZONE_MAPPING, "bverror = %d\n", bverror); - return bverror; -} - -static void unmap_implicit(struct gcbatch *batch) -{ - struct list_head *head, *temphead; - struct gcschedunmap *gcschedunmap; - struct bvbuffdesc *bvbuffdesc; - struct bvbuffmap *prev, *bvbuffmap; - struct bvbuffmapinfo *bvbuffmapinfo; - - GCENTER(GCZONE_MAPPING); - - /* Lock access to the mapping list. */ - GCLOCK(&gccontext.maplock); - - /* Dump the schedule. */ - GCDUMPSCHEDULE(); - - /* Scan scheduled unmappings and remove the ones that are still - * in use. */ - list_for_each_safe(head, temphead, &batch->unmap) { - gcschedunmap = list_entry(head, struct gcschedunmap, link); - - /* Cast the handle. */ - bvbuffdesc = (struct bvbuffdesc *) gcschedunmap->handle; - - /* Find our mapping. */ - prev = NULL; - bvbuffmap = bvbuffdesc->map; - while (bvbuffmap != NULL) { - if (bvbuffmap->bv_unmap == bv_unmap) - break; - prev = bvbuffmap; - bvbuffmap = bvbuffmap->nextmap; - } - - /* Not found? */ - if (bvbuffmap == NULL) { - GCERR("mapping not found for bvbuffdesc 0x%08X.\n", - (unsigned int) bvbuffdesc); - - /* Remove scheduled unmapping. */ - list_move(head, &gccontext.vac_unmap); - continue; - } - - /* Get the info structure. */ - bvbuffmapinfo = (struct bvbuffmapinfo *) bvbuffmap->handle; - - GCDBG(GCZONE_MAPPING, "head = 0x%08X\n", - (unsigned int) gcschedunmap); - GCDBG(GCZONE_MAPPING, " bvbuffmap = 0x%08X\n", - (unsigned int) bvbuffmap); - GCDBG(GCZONE_MAPPING, " handle = 0x%08X\n", - bvbuffmapinfo->handle); - - /* Implicit unmapping. */ - bvbuffmapinfo->automap -= 1; - if (bvbuffmapinfo->automap < 0) { - GCERR("implicit count negative.\n"); - bvbuffmapinfo->automap = 0; - } - - GCDBG(GCZONE_MAPPING, " explicit count = %d\n", - bvbuffmapinfo->usermap); - GCDBG(GCZONE_MAPPING, " implicit count = %d\n", - bvbuffmapinfo->automap); - - /* Still referenced? */ - if (bvbuffmapinfo->usermap || bvbuffmapinfo->automap) { - GCDBG(GCZONE_MAPPING, " still referenced.\n"); - - /* Remove scheduled unmapping. */ - list_move(head, &gccontext.vac_unmap); - continue; - } - - GCDBG(GCZONE_MAPPING, " ready for unmapping.\n"); - - /* Set the handle. */ - gcschedunmap->handle = bvbuffmapinfo->handle; - - /* Remove from the buffer descriptor. */ - if (prev == NULL) - bvbuffdesc->map = bvbuffmap->nextmap; - else - prev->nextmap = bvbuffmap->nextmap; - - /* Add to the vacant list. */ - bvbuffmap->nextmap = gccontext.vac_buffmap; - gccontext.vac_buffmap = bvbuffmap; - } - - /* Dump the schedule. */ - GCDUMPSCHEDULE(); - - /* Unlock access to the mapping list. */ - GCUNLOCK(&gccontext.maplock); - - GCEXIT(GCZONE_MAPPING); -} - - -/******************************************************************************* - * Batch memory manager. - */ - -static enum bverror allocate_batch(struct bvbltparams *bltparams, - struct gcbatch **batch); -static void free_batch(struct gcbatch *batch); -static enum bverror append_buffer(struct bvbltparams *bltparams, - struct gcbatch *batch); - -static enum bverror do_end(struct bvbltparams *bltparams, - struct gcbatch *batch) -{ - return BVERR_NONE; -} - -static enum bverror allocate_batch(struct bvbltparams *bltparams, - struct gcbatch **batch) -{ - enum bverror bverror; - struct gcbatch *temp; - - GCENTER(GCZONE_BATCH); - - /* Lock access to batch management. */ - GCLOCK(&gccontext.batchlock); - - if (gccontext.vac_batches == NULL) { - temp = gcalloc(struct gcbatch, sizeof(struct gcbatch)); - if (temp == NULL) { - BVSETBLTERROR(BVERR_OOM, - "batch header allocation failed"); - goto exit; - } - - GCDBG(GCZONE_BATCH, "allocated new batch = 0x%08X\n", - (unsigned int) temp); - } else { - temp = (struct gcbatch *) gccontext.vac_batches; - gccontext.vac_batches = gccontext.vac_batches->next; - - GCDBG(GCZONE_BATCH, "reusing batch = 0x%08X\n", - (unsigned int) temp); - } - - memset(temp, 0, sizeof(struct gcbatch)); - temp->structsize = sizeof(struct gcbatch); - temp->batchend = do_end; - INIT_LIST_HEAD(&temp->unmap); - - bverror = append_buffer(bltparams, temp); - if (bverror != BVERR_NONE) { - free_batch(temp); - goto exit; - } - - *batch = temp; - - GCDBG(GCZONE_BATCH, "batch allocated = 0x%08X\n", (unsigned int) temp); - -exit: - /* Unlock access to batch management. */ - GCUNLOCK(&gccontext.batchlock); - - GCEXITARG(GCZONE_BATCH, "bv%s = %d\n", - (bverror == BVERR_NONE) ? "result" : "error", bverror); - return bverror; -} - -static void free_batch(struct gcbatch *batch) -{ - struct gcbuffer *buffer; - - GCENTERARG(GCZONE_BATCH, "batch = 0x%08X\n", (unsigned int) batch); - - /* Lock access. */ - GCLOCK(&gccontext.batchlock); - GCLOCK(&gccontext.bufferlock); - GCLOCK(&gccontext.fixuplock); - GCLOCK(&gccontext.maplock); - - list_splice_init(&batch->unmap, &gccontext.vac_unmap); - - buffer = batch->bufhead; - if (buffer != NULL) { - do { - if (buffer->fixuphead != NULL) { - buffer->fixuptail->next = gccontext.vac_fixups; - gccontext.vac_fixups = buffer->fixuphead; - } - buffer = buffer->next; - } while (buffer != NULL); - - batch->buftail->next = gccontext.vac_buffers; - gccontext.vac_buffers = batch->bufhead; - } - - ((struct gcvacbatch *) batch)->next = gccontext.vac_batches; - gccontext.vac_batches = (struct gcvacbatch *) batch; - - /* Unlock access. */ - GCUNLOCK(&gccontext.maplock); - GCUNLOCK(&gccontext.fixuplock); - GCUNLOCK(&gccontext.bufferlock); - GCUNLOCK(&gccontext.batchlock); - - GCEXIT(GCZONE_BATCH); -} - -static enum bverror append_buffer(struct bvbltparams *bltparams, - struct gcbatch *batch) -{ - enum bverror bverror; - struct gcbuffer *temp; - - GCENTERARG(GCZONE_BUFFER_ALLOC, "batch = 0x%08X\n", - (unsigned int) batch); - - /* Lock access to buffer management. */ - GCLOCK(&gccontext.bufferlock); - - if (gccontext.vac_buffers == NULL) { - temp = gcalloc(struct gcbuffer, GC_BUFFER_SIZE); - if (temp == NULL) { - BVSETBLTERROR(BVERR_OOM, - "command buffer allocation failed"); - goto exit; - } - - GCDBG(GCZONE_BUFFER_ALLOC, "allocated new buffer = 0x%08X\n", - (unsigned int) temp); - } else { - temp = gccontext.vac_buffers; - gccontext.vac_buffers = temp->next; - - GCDBG(GCZONE_BUFFER_ALLOC, "reusing buffer = 0x%08X\n", - (unsigned int) temp); - } - - memset(temp, 0, sizeof(struct gcbuffer)); - temp->head = - temp->tail = (unsigned int *) (temp + 1); - temp->available = GC_BUFFER_SIZE - max(sizeof(struct gcbuffer), - GC_BUFFER_RESERVE); - - if (batch->bufhead == NULL) - batch->bufhead = temp; - else - batch->buftail->next = temp; - batch->buftail = temp; - - GCDBG(GCZONE_BUFFER_ALLOC, "new buffer appended = 0x%08X\n", - (unsigned int) temp); - - bverror = BVERR_NONE; - -exit: - /* Unlock access to buffer management. */ - GCUNLOCK(&gccontext.bufferlock); - - GCEXITARG(GCZONE_BUFFER_ALLOC, "bv%s = %d\n", - (bverror == BVERR_NONE) ? "result" : "error", bverror); - return bverror; -} - -static enum bverror add_fixup(struct bvbltparams *bltparams, - struct gcbatch *batch, - unsigned int *fixup, - unsigned int surfoffset) +enum bverror set_dst(struct bvbltparams *bltparams, + struct gcbatch *batch, + struct bvbuffmap *dstmap) { enum bverror bverror = BVERR_NONE; - struct gcbuffer *buffer; - struct gcfixup *temp; - - GCENTERARG(GCZONE_FIXUP, "batch = 0x%08X, fixup ptr = 0x%08X\n", - (unsigned int) batch, (unsigned int) fixup); - - /* Lock access to fixup management. */ - GCLOCK(&gccontext.fixuplock); - - buffer = batch->buftail; - temp = buffer->fixuptail; - - GCDBG(GCZONE_FIXUP, "buffer = 0x%08X, fixup struct = 0x%08X\n", - (unsigned int) buffer, (unsigned int) temp); - - if ((temp == NULL) || (temp->count == GC_FIXUP_MAX)) { - if (gccontext.vac_fixups == NULL) { - temp = gcalloc(struct gcfixup, sizeof(struct gcfixup)); - if (temp == NULL) { - BVSETBLTERROR(BVERR_OOM, - "fixup allocation failed"); - goto exit; - } - - GCDBG(GCZONE_FIXUP, - "new fixup struct allocated = 0x%08X\n", - (unsigned int) temp); - } else { - temp = gccontext.vac_fixups; - gccontext.vac_fixups = temp->next; - - GCDBG(GCZONE_FIXUP, "fixup struct reused = 0x%08X\n", - (unsigned int) temp); - } - - temp->next = NULL; - temp->count = 0; - - if (buffer->fixuphead == NULL) - buffer->fixuphead = temp; - else - buffer->fixuptail->next = temp; - buffer->fixuptail = temp; - - GCDBG(GCZONE_FIXUP, "new fixup struct allocated = 0x%08X\n", - (unsigned int) temp); - - } else { - GCDBG(GCZONE_FIXUP, "fixups accumulated = %d\n", temp->count); - } - - temp->fixup[temp->count].dataoffset = fixup - buffer->head; - temp->fixup[temp->count].surfoffset = surfoffset; - temp->count += 1; - - GCDBG(GCZONE_FIXUP, "fixup offset = 0x%08X\n", fixup - buffer->head); - GCDBG(GCZONE_FIXUP, "surface offset = 0x%08X\n", surfoffset); - -exit: - /* Unlock access to fixup management. */ - GCUNLOCK(&gccontext.fixuplock); - - GCEXITARG(GCZONE_FIXUP, "bv%s = %d\n", - (bverror == BVERR_NONE) ? "result" : "error", bverror); - return bverror; -} - -static enum bverror claim_buffer(struct bvbltparams *bltparams, - struct gcbatch *batch, - unsigned int size, - void **buffer) -{ - enum bverror bverror; - struct gcbuffer *curbuf; - - GCENTERARG(GCZONE_BUFFER_ALLOC, "batch = 0x%08X, size = %d\n", - (unsigned int) batch, size); - - /* Get the current command buffer. */ - curbuf = batch->buftail; + struct gcmodst *gcmodst; - GCDBG(GCZONE_BUFFER_ALLOC, "buffer = 0x%08X, available = %d\n", - (unsigned int) curbuf, curbuf->available); + GCENTER(GCZONE_DEST); - if (curbuf->available < size) { - bverror = append_buffer(bltparams, batch); + /* Did destination surface change? */ + if ((batch->batchflags & BVBATCH_DST) != 0) { + /* Allocate command buffer. */ + bverror = claim_buffer(bltparams, batch, + sizeof(struct gcmodst), + (void **) &gcmodst); if (bverror != BVERR_NONE) goto exit; - curbuf = batch->buftail; - } - - if (curbuf->available < size) { - GCDBG(GCZONE_BUFFER_ALLOC, "requested size is too large.\n"); - BVSETBLTERROR(BVERR_OOM, - "command buffer allocation failed"); - goto exit; - } - - *buffer = curbuf->tail; - curbuf->tail = (unsigned int *) ((unsigned char *) curbuf->tail + size); - curbuf->available -= size; - batch->size += size; - bverror = BVERR_NONE; - -exit: - GCEXITARG(GCZONE_BUFFER_ALLOC, "bv%s = %d\n", - (bverror == BVERR_NONE) ? "result" : "error", bverror); - return bverror; -} - - -/******************************************************************************* - * Pixel format parser. - */ - -/* FIXME/TODO: change to use BLTsvile defines. */ - -#if defined(OCDFMTDEF_ALPHA_SHIFT) -# undef OCDFMTDEF_ALPHA_SHIFT -#endif - -#if defined(OCDFMTDEF_ALPHA_MASK) -# undef OCDFMTDEF_ALPHA_MASK -#endif - -#define OCDFMTDEF_ALPHA_SHIFT 18 -#define OCDFMTDEF_ALPHA_MASK (1 << OCDFMTDEF_ALPHA_SHIFT) - -#define OCDFMTDEF_PLACEMENT_SHIFT 9 -#define OCDFMTDEF_PLACEMENT_MASK (3 << OCDFMTDEF_PLACEMENT_SHIFT) - -#define OCDFMTDEF_BITS_SHIFT 3 -#define OCDFMTDEF_BITS_MASK (3 << OCDFMTDEF_BITS_SHIFT) - -#define OCDFMTDEF_BITS12 (0 << OCDFMTDEF_BITS_SHIFT) -#define OCDFMTDEF_BITS15 (1 << OCDFMTDEF_BITS_SHIFT) -#define OCDFMTDEF_BITS16 (2 << OCDFMTDEF_BITS_SHIFT) -#define OCDFMTDEF_BITS24 (3 << OCDFMTDEF_BITS_SHIFT) - -enum bvformattype { - BVFMT_RGB, - BVFMT_YUV -}; - -struct bvcomponent { - unsigned int shift; - unsigned int size; - unsigned int mask; -}; - -struct bvcsrgb { - struct bvcomponent r; - struct bvcomponent g; - struct bvcomponent b; - struct bvcomponent a; -}; - -struct bvformatxlate { - enum bvformattype type; - unsigned bitspp; - unsigned format; - unsigned swizzle; - struct bvcsrgb rgba; -}; - -#define BVFORMATRGBA(BPP, Format, Swizzle, R, G, B, A) \ -{ \ - BVFMT_RGB, \ - BPP, \ - GCREG_DE_FORMAT_ ## Format, \ - GCREG_DE_SWIZZLE_ ## Swizzle, \ - { R, G, B, A } \ -} - -#define BVCOMP(Shift, Size) \ - { Shift, Size, ((1 << Size) - 1) << Shift } - -#define BVRED(Shift, Size) \ - BVCOMP(Shift, Size) - -#define BVGREEN(Shift, Size) \ - BVCOMP(Shift, Size) - -#define BVBLUE(Shift, Size) \ - BVCOMP(Shift, Size) - -#define BVALPHA(Shift, Size) \ - BVCOMP(Shift, Size) - -#define BVFORMATINVALID \ - { 0, 0, 0, 0, { { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 } } } - -static struct bvformatxlate g_format_nv12 = { - .type = BVFMT_YUV, - .bitspp = 8, - .format = GCREG_DE_FORMAT_NV12, -}; -static struct bvformatxlate g_format_uyvy = { - .type = BVFMT_YUV, - .bitspp = 16, - .format = GCREG_DE_FORMAT_UYVY -}; -static struct bvformatxlate g_format_yuy2 = { - .type = BVFMT_YUV, - .bitspp = 16, - .format = GCREG_DE_FORMAT_YUY2 -}; - -static struct bvformatxlate formatxlate[] = { - /* #0: OCDFMT_xRGB12 - BITS=12 ALPHA=0 REVERSED=0 LEFT_JUSTIFIED=0 */ - BVFORMATRGBA(16, X4R4G4B4, ARGB, - BVRED(8, 4), BVGREEN(4, 4), BVBLUE(0, 4), BVALPHA(12, 0)), - - /* #1: OCDFMT_RGBx12 - BITS=12 ALPHA=0 REVERSED=0 LEFT_JUSTIFIED=1 */ - BVFORMATRGBA(16, X4R4G4B4, RGBA, - BVRED(12, 4), BVGREEN(8, 4), BVBLUE(4, 4), BVALPHA(0, 0)), - - /* #2: OCDFMT_xBGR12 - BITS=12 ALPHA=0 REVERSED=1 LEFT_JUSTIFIED=0 */ - BVFORMATRGBA(16, X4R4G4B4, ABGR, - BVRED(0, 4), BVGREEN(4, 4), BVBLUE(8, 4), BVALPHA(12, 0)), - - /* #3: OCDFMT_BGRx12 - BITS=12 ALPHA=0 REVERSED=1 LEFT_JUSTIFIED=1 */ - BVFORMATRGBA(16, X4R4G4B4, BGRA, - BVRED(4, 4), BVGREEN(8, 4), BVBLUE(12, 4), BVALPHA(0, 0)), - - /* #4: OCDFMT_ARGB12 - BITS=12 ALPHA=1 REVERSED=0 LEFT_JUSTIFIED=0 */ - BVFORMATRGBA(16, A4R4G4B4, ARGB, - BVRED(8, 4), BVGREEN(4, 4), BVBLUE(0, 4), BVALPHA(12, 4)), - - /* #5: OCDFMT_RGBA12 - BITS=12 ALPHA=1 REVERSED=0 LEFT_JUSTIFIED=1 */ - BVFORMATRGBA(16, A4R4G4B4, RGBA, - BVRED(12, 4), BVGREEN(8, 4), BVBLUE(4, 4), BVALPHA(0, 4)), - - /* #6: OCDFMT_ABGR12 - BITS=12 ALPHA=1 REVERSED=1 LEFT_JUSTIFIED=0 */ - BVFORMATRGBA(16, A4R4G4B4, ABGR, - BVRED(0, 4), BVGREEN(4, 4), BVBLUE(8, 4), BVALPHA(12, 4)), - - /* #7: OCDFMT_BGRA12 - BITS=12 ALPHA=1 REVERSED=1 LEFT_JUSTIFIED=1 */ - BVFORMATRGBA(16, A4R4G4B4, BGRA, - BVRED(4, 4), BVGREEN(8, 4), BVBLUE(12, 4), BVALPHA(0, 4)), - - /***********************************************/ - - /* #8: OCDFMT_xRGB15 - BITS=15 ALPHA=0 REVERSED=0 LEFT_JUSTIFIED=0 */ - BVFORMATRGBA(16, X1R5G5B5, ARGB, - BVRED(10, 5), BVGREEN(5, 5), BVBLUE(0, 5), BVALPHA(15, 0)), - - /* #9: OCDFMT_RGBx15 - BITS=15 ALPHA=0 REVERSED=0 LEFT_JUSTIFIED=1 */ - BVFORMATRGBA(16, X1R5G5B5, RGBA, - BVRED(11, 5), BVGREEN(6, 5), BVBLUE(1, 5), BVALPHA(0, 0)), - - /* #10: OCDFMT_xBGR15 - BITS=15 ALPHA=0 REVERSED=1 LEFT_JUSTIFIED=0 */ - BVFORMATRGBA(16, X1R5G5B5, ABGR, - BVRED(0, 5), BVGREEN(5, 5), BVBLUE(10, 5), BVALPHA(15, 0)), - - /* #11: OCDFMT_BGRx15 - BITS=15 ALPHA=0 REVERSED=1 LEFT_JUSTIFIED=1 */ - BVFORMATRGBA(16, X1R5G5B5, BGRA, - BVRED(1, 5), BVGREEN(6, 5), BVBLUE(11, 5), BVALPHA(0, 0)), - - /* #12: OCDFMT_ARGB15 - BITS=15 ALPHA=1 REVERSED=0 LEFT_JUSTIFIED=0 */ - BVFORMATRGBA(16, A1R5G5B5, ARGB, - BVRED(10, 5), BVGREEN(5, 5), BVBLUE(0, 5), BVALPHA(15, 1)), - - /* #13: OCDFMT_RGBA15 - BITS=15 ALPHA=1 REVERSED=0 LEFT_JUSTIFIED=1 */ - BVFORMATRGBA(16, A1R5G5B5, RGBA, - BVRED(11, 5), BVGREEN(6, 5), BVBLUE(1, 5), BVALPHA(0, 1)), - - /* #14: OCDFMT_ABGR15 - BITS=15 ALPHA=1 REVERSED=1 LEFT_JUSTIFIED=0 */ - BVFORMATRGBA(16, A1R5G5B5, ABGR, - BVRED(0, 5), BVGREEN(5, 5), BVBLUE(10, 5), BVALPHA(15, 1)), - - /* #15: OCDFMT_BGRA15 - BITS=15 ALPHA=1 REVERSED=1 LEFT_JUSTIFIED=1 */ - BVFORMATRGBA(16, A1R5G5B5, BGRA, - BVRED(1, 5), BVGREEN(6, 5), BVBLUE(11, 5), BVALPHA(0, 1)), - - /***********************************************/ - - /* #16: OCDFMT_RGB16 - BITS=16 ALPHA=0 REVERSED=0 LEFT_JUSTIFIED=0 */ - BVFORMATRGBA(16, R5G6B5, ARGB, - BVRED(11, 5), BVGREEN(5, 6), BVBLUE(0, 5), BVALPHA(0, 0)), - - /* #17: OCDFMT_RGB16 - BITS=16 ALPHA=0 REVERSED=0 LEFT_JUSTIFIED=1 */ - BVFORMATRGBA(16, R5G6B5, ARGB, - BVRED(11, 5), BVGREEN(5, 6), BVBLUE(0, 5), BVALPHA(0, 0)), - - /* #18: OCDFMT_BGR16 - BITS=16 ALPHA=0 REVERSED=1 LEFT_JUSTIFIED=0 */ - BVFORMATRGBA(16, R5G6B5, ABGR, - BVRED(0, 5), BVGREEN(5, 6), BVBLUE(11, 5), BVALPHA(0, 0)), - - /* #19: OCDFMT_BGR16 - BITS=16 ALPHA=0 REVERSED=1 LEFT_JUSTIFIED=1 */ - BVFORMATRGBA(16, R5G6B5, ABGR, - BVRED(0, 5), BVGREEN(5, 6), BVBLUE(11, 5), BVALPHA(0, 0)), - - /* #20 */ - BVFORMATINVALID, - - /* #21 */ - BVFORMATINVALID, - - /* #22 */ - BVFORMATINVALID, - - /* #23 */ - BVFORMATINVALID, - - /***********************************************/ - - /* #24: OCDFMT_xRGB24 - BITS=24 ALPHA=0 REVERSED=0 LEFT_JUSTIFIED=0 */ - BVFORMATRGBA(32, X8R8G8B8, BGRA, - BVRED(8, 8), BVGREEN(16, 8), BVBLUE(24, 8), BVALPHA(0, 0)), - - /* #25: OCDFMT_RGBx24 - BITS=24 ALPHA=0 REVERSED=0 LEFT_JUSTIFIED=1 */ - BVFORMATRGBA(32, X8R8G8B8, ABGR, - BVRED(0, 8), BVGREEN(8, 8), BVBLUE(16, 8), BVALPHA(24, 0)), - - /* #26: OCDFMT_xBGR24 - BITS=24 ALPHA=0 REVERSED=1 LEFT_JUSTIFIED=0 */ - BVFORMATRGBA(32, X8R8G8B8, RGBA, - BVRED(24, 8), BVGREEN(16, 8), BVBLUE(8, 8), BVALPHA(0, 0)), - - /* #27: OCDFMT_BGRx24 - BITS=24 ALPHA=0 REVERSED=1 LEFT_JUSTIFIED=1 */ - BVFORMATRGBA(32, X8R8G8B8, ARGB, - BVRED(16, 8), BVGREEN(8, 8), BVBLUE(0, 8), BVALPHA(24, 0)), - - /* #28: OCDFMT_ARGB24 - BITS=24 ALPHA=1 REVERSED=0 LEFT_JUSTIFIED=0 */ - BVFORMATRGBA(32, A8R8G8B8, BGRA, - BVRED(8, 8), BVGREEN(16, 8), BVBLUE(24, 8), BVALPHA(0, 8)), - - /* #29: OCDFMT_RGBA24 - BITS=24 ALPHA=1 REVERSED=0 LEFT_JUSTIFIED=1 */ - BVFORMATRGBA(32, A8R8G8B8, ABGR, - BVRED(0, 8), BVGREEN(8, 8), BVBLUE(16, 8), BVALPHA(24, 8)), - - /* #30: OCDFMT_ABGR24 - BITS=24 ALPHA=1 REVERSED=1 LEFT_JUSTIFIED=0 */ - BVFORMATRGBA(32, A8R8G8B8, RGBA, - BVRED(24, 8), BVGREEN(16, 8), BVBLUE(8, 8), BVALPHA(0, 8)), - - /* #31: OCDFMT_BGRA24 - BITS=24 ALPHA=1 REVERSED=1 LEFT_JUSTIFIED=1 */ - BVFORMATRGBA(32, A8R8G8B8, ARGB, - BVRED(16, 8), BVGREEN(8, 8), BVBLUE(0, 8), BVALPHA(24, 8)), -}; - -static int parse_format(enum ocdformat ocdformat, struct bvformatxlate **format) -{ - static unsigned int containers[] = { - 8, /* OCDFMTDEF_CONTAINER_8BIT */ - 16, /* OCDFMTDEF_CONTAINER_16BIT */ - 24, /* OCDFMTDEF_CONTAINER_24BIT */ - 32, /* OCDFMTDEF_CONTAINER_32BIT */ - ~0U, /* reserved */ - 48, /* OCDFMTDEF_CONTAINER_48BIT */ - ~0U, /* reserved */ - 64 /* OCDFMTDEF_CONTAINER_64BIT */ - }; - - unsigned int cs; - unsigned int bits; - unsigned int swizzle; - unsigned int alpha; - unsigned int index; - unsigned int cont; - - GCDBG(GCZONE_FORMAT, "ocdformat = 0x%08X\n", ocdformat); - - switch (ocdformat) { - case OCDFMT_NV12: - GCDBG(GCZONE_FORMAT, "OCDFMT_NV12\n"); - *format = &g_format_nv12; - return 1; - - case OCDFMT_UYVY: - GCDBG(GCZONE_FORMAT, "OCDFMT_UYVY\n"); - *format = &g_format_uyvy; - return 1; - - case OCDFMT_YUY2: - GCDBG(GCZONE_FORMAT, "OCDFMT_YUY2\n"); - *format = &g_format_yuy2; - return 1; - - default: - break; - } - - cs = (ocdformat & OCDFMTDEF_CS_MASK) >> OCDFMTDEF_CS_SHIFT; - bits = (ocdformat & OCDFMTDEF_COMPONENTSIZEMINUS1_MASK) - >> OCDFMTDEF_COMPONENTSIZEMINUS1_SHIFT; - cont = (ocdformat & OCDFMTDEF_CONTAINER_MASK) - >> OCDFMTDEF_CONTAINER_SHIFT; - - switch (cs) { - case (OCDFMTDEF_CS_RGB >> OCDFMTDEF_CS_SHIFT): - GCDBG(GCZONE_FORMAT, "OCDFMTDEF_CS_RGB\n"); - GCDBG(GCZONE_FORMAT, "bits = %d\n", bits); - GCDBG(GCZONE_FORMAT, "cont = %d\n", cont); - - if ((ocdformat & OCDFMTDEF_LAYOUT_MASK) != OCDFMTDEF_PACKED) - return 0; - - swizzle = (ocdformat & OCDFMTDEF_PLACEMENT_MASK) - >> OCDFMTDEF_PLACEMENT_SHIFT; - alpha = (ocdformat & OCDFMTDEF_ALPHA_MASK) - >> OCDFMTDEF_ALPHA_SHIFT; - - GCDBG(GCZONE_FORMAT, "swizzle = %d\n", swizzle); - GCDBG(GCZONE_FORMAT, "alpha = %d\n", alpha); - - index = swizzle | (alpha << 2); - - switch (bits) { - case 12 - 1: - index |= OCDFMTDEF_BITS12; - break; - - case 15 - 1: - index |= OCDFMTDEF_BITS15; - break; - - case 16 - 1: - index |= OCDFMTDEF_BITS16; - break; - - case 24 - 1: - index |= OCDFMTDEF_BITS24; - break; - - default: - return 0; - } - - GCDBG(GCZONE_FORMAT, "index = %d\n", index); - break; - - default: - return 0; - } - - if (formatxlate[index].bitspp != containers[cont]) - return 0; - - *format = &formatxlate[index]; - - GCDBG(GCZONE_FORMAT, "format record = 0x%08X\n", - (unsigned int) &formatxlate[index]); - GCDBG(GCZONE_FORMAT, " bpp = %d\n", formatxlate[index].bitspp); - GCDBG(GCZONE_FORMAT, " format = %d\n", formatxlate[index].format); - GCDBG(GCZONE_FORMAT, " swizzle = %d\n", formatxlate[index].swizzle); - - return 1; -} - -static inline unsigned int extract_component(unsigned int pixel, - struct bvcomponent *desc) -{ - unsigned int component; - unsigned int component8; - - component = (pixel & desc->mask) >> desc->shift; - GCDBG(GCZONE_COLOR, "mask=0x%08X, shift=%d, component=0x%08X\n", - desc->mask, desc->shift, component); - - switch (desc->size) { - case 0: - component8 = 0xFF; - GCDBG(GCZONE_COLOR, "component8=0x%08X\n", component8); - break; - - case 1: - component8 = component ? 0xFF : 0x00; - GCDBG(GCZONE_COLOR, "component8=0x%08X\n", component8); - break; - - case 4: - component8 = component | (component << 4); - GCDBG(GCZONE_COLOR, "component8=0x%08X\n", component8); - break; - - case 5: - component8 = (component << 3) | (component >> 2); - GCDBG(GCZONE_COLOR, "component8=0x%08X\n", component8); - break; - - case 6: - component8 = (component << 2) | (component >> 4); - GCDBG(GCZONE_COLOR, "component8=0x%08X\n", component8); - break; - - default: - component8 = component; - GCDBG(GCZONE_COLOR, "component8=0x%08X\n", component8); - } - - return component8; -} - -static unsigned int getinternalcolor(void *ptr, struct bvformatxlate *format) -{ - unsigned int srcpixel, dstpixel; - unsigned int r, g, b, a; - - switch (format->bitspp) { - case 16: - srcpixel = *(unsigned short *) ptr; - GCDBG(GCZONE_COLOR, "srcpixel=0x%08X\n", srcpixel); - break; - - case 32: - srcpixel = *(unsigned int *) ptr; - GCDBG(GCZONE_COLOR, "srcpixel=0x%08X\n", srcpixel); - break; - - default: - srcpixel = 0; - GCDBG(GCZONE_COLOR, "srcpixel=0x%08X\n", srcpixel); - } - - r = extract_component(srcpixel, &format->rgba.r); - g = extract_component(srcpixel, &format->rgba.g); - b = extract_component(srcpixel, &format->rgba.b); - a = extract_component(srcpixel, &format->rgba.a); - - GCDBG(GCZONE_COLOR, "(r,g,b,a)=0x%02X,0x%02X,0x%02X,0x%02X\n", - r, g, b, a); - - dstpixel = (a << 24) | (r << 16) | (g << 8) | b; - - GCDBG(GCZONE_COLOR, "dstpixel=0x%08X\n", dstpixel); - - return dstpixel; -} - - -/******************************************************************************* - * Alpha blending parser. - */ - -#define BVBLENDMATCH(Mode, Inverse, Normal) \ -( \ - BVBLENDDEF_ ## Mode | \ - BVBLENDDEF_ ## Inverse | \ - BVBLENDDEF_ ## Normal \ -) - -#define BVSRC1USE(Use) \ - Use - -#define BVSRC2USE(Use) \ - Use - -#define BVBLENDUNDEFINED() \ - { ~0, ~0, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } } - -static struct bvblendxlate blendxlate[64] = { - /**********************************************************************/ - /* #0: color factor: 00 00 00 A:(1-C1,C1)=zero - alpha factor: zero ==> 00 00 00 */ - { - 0x00, - 0x00, - - { - GCREG_BLENDING_MODE_ZERO, - GCREG_FACTOR_INVERSE_DISABLE, - BVSRC1USE(0), BVSRC2USE(0), - }, - - { - GCREG_BLENDING_MODE_ZERO, - GCREG_FACTOR_INVERSE_DISABLE, - BVSRC1USE(0), BVSRC2USE(0) - } - }, - - /* #1: color factor: 00 00 01 A:(1-C1,A1)=A1 - alpha factor: A1 ==> 00 00 01 or 00 10 01 */ - { - BVBLENDMATCH(ONLY_A, INV_C1, NORM_A1), - BVBLENDMATCH(ONLY_A, INV_C2, NORM_A1), - - { - GCREG_BLENDING_MODE_NORMAL, - GCREG_FACTOR_INVERSE_ENABLE, - BVSRC1USE(1), BVSRC2USE(0), - }, - - { - GCREG_BLENDING_MODE_NORMAL, - GCREG_FACTOR_INVERSE_DISABLE, - BVSRC1USE(1), BVSRC2USE(1) - } - }, - - /* #2: color factor: 00 00 10 A:(1-C1,C2)=undefined - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* #3: color factor: 00 00 11 A:(1-C1,A2)=A2 - alpha factor: A2 ==> 00 00 11 or 00 10 11 */ - { - BVBLENDMATCH(ONLY_A, INV_C1, NORM_A2), - BVBLENDMATCH(ONLY_A, INV_C2, NORM_A2), - - { - GCREG_BLENDING_MODE_NORMAL, - GCREG_FACTOR_INVERSE_DISABLE, - BVSRC1USE(1), BVSRC2USE(1), - }, - - { - GCREG_BLENDING_MODE_NORMAL, - GCREG_FACTOR_INVERSE_ENABLE, - BVSRC1USE(0), BVSRC2USE(1) - } - }, - - /* #4: color factor: 00 01 00 A:(1-A1,C1)=1-A1 - alpha factor: 1-A1 ==> 00 01 00 or 00 01 10 */ - { - BVBLENDMATCH(ONLY_A, INV_A1, NORM_C1), - BVBLENDMATCH(ONLY_A, INV_A1, NORM_C2), - - { - GCREG_BLENDING_MODE_INVERSED, - GCREG_FACTOR_INVERSE_ENABLE, - BVSRC1USE(1), BVSRC2USE(0), - }, - - { - GCREG_BLENDING_MODE_INVERSED, - GCREG_FACTOR_INVERSE_DISABLE, - BVSRC1USE(1), BVSRC2USE(1) - } - }, - - /* #5: color factor: 00 01 01 A:(1-A1,A1)=undefined - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* #6: color factor: 00 01 10 A:(1-A1,C2)=1-A1 - alpha factor: 1-A1 ==> 00 01 00 or 00 01 10 */ - { - BVBLENDMATCH(ONLY_A, INV_A1, NORM_C1), - BVBLENDMATCH(ONLY_A, INV_A1, NORM_C2), - - { - GCREG_BLENDING_MODE_INVERSED, - GCREG_FACTOR_INVERSE_ENABLE, - BVSRC1USE(1), BVSRC2USE(0), - }, - - { - GCREG_BLENDING_MODE_INVERSED, - GCREG_FACTOR_INVERSE_DISABLE, - BVSRC1USE(1), BVSRC2USE(1) - } - }, - - /* #7: color factor: 00 01 11 A:(1-A1,A2)=undefined - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* #8: color factor: 00 10 00 A:(1-C2,C1)=undefined - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* #9: color factor: 00 10 01 A:(1-C2,A1)=A1 - alpha factor: A1 ==> 00 00 01 or 00 10 01 */ - { - BVBLENDMATCH(ONLY_A, INV_C1, NORM_A1), - BVBLENDMATCH(ONLY_A, INV_C2, NORM_A1), - - { - GCREG_BLENDING_MODE_NORMAL, - GCREG_FACTOR_INVERSE_ENABLE, - BVSRC1USE(1), BVSRC2USE(0), - }, - - { - GCREG_BLENDING_MODE_NORMAL, - GCREG_FACTOR_INVERSE_DISABLE, - BVSRC1USE(1), BVSRC2USE(1) - } - }, - - /* #10: color factor: 00 10 10 A:(1-C2,C2)=undefined - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* #11: color factor: 00 10 11 A:(1-C2,A2)=A2 - alpha factor: A2 ==> 00 00 11 or 00 10 11 */ - { - BVBLENDMATCH(ONLY_A, INV_C1, NORM_A2), - BVBLENDMATCH(ONLY_A, INV_C2, NORM_A2), - - { - GCREG_BLENDING_MODE_NORMAL, - GCREG_FACTOR_INVERSE_DISABLE, - BVSRC1USE(1), BVSRC2USE(1), - }, - - { - GCREG_BLENDING_MODE_NORMAL, - GCREG_FACTOR_INVERSE_ENABLE, - BVSRC1USE(0), BVSRC2USE(1) - } - }, - - /* #12: color factor: 00 11 00 A:(1-A2,C1)=1-A2 - alpha factor: 1-A2 ==> 00 11 00 or 00 11 10 */ - { - BVBLENDMATCH(ONLY_A, INV_A2, NORM_C1), - BVBLENDMATCH(ONLY_A, INV_A2, NORM_C2), - - { - GCREG_BLENDING_MODE_INVERSED, - GCREG_FACTOR_INVERSE_DISABLE, - BVSRC1USE(1), BVSRC2USE(1), - }, - - { - GCREG_BLENDING_MODE_INVERSED, - GCREG_FACTOR_INVERSE_ENABLE, - BVSRC1USE(0), BVSRC2USE(1) - } - }, - - /* #13: color factor: 00 11 01 A:(1-A2,A1)=undefined - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* #14: color factor: 00 11 10 A:(1-A2,C2)=1-A2 - alpha factor: 1-A2 ==> 00 11 00 or 00 11 10 */ - { - BVBLENDMATCH(ONLY_A, INV_A2, NORM_C1), - BVBLENDMATCH(ONLY_A, INV_A2, NORM_C2), - - { - GCREG_BLENDING_MODE_INVERSED, - GCREG_FACTOR_INVERSE_DISABLE, - BVSRC1USE(1), BVSRC2USE(1), - }, - - { - GCREG_BLENDING_MODE_INVERSED, - GCREG_FACTOR_INVERSE_ENABLE, - BVSRC1USE(0), BVSRC2USE(1) - } - }, - - /* #15: color factor: 00 11 11 A:(1-A2,A2)=undefined - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /**********************************************************************/ - /* #16: color factor: 01 00 00 MIN:(1-C1,C1) ==> not supported - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* #17: color factor: 01 00 01 MIN:(1-C1,A1) ==> not supported - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* #18: color factor: 01 00 10 MIN:(1-C1,C2) ==> not supported - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* #19: color factor: 01 00 11 MIN:(1-C1,A2) ==> not supported - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* #20: color factor: 01 01 00 MIN:(1-A1,C1) ==> not supported - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* #21: color factor: 01 01 01 MIN:(1-A1,A1) ==> not supported - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* #22: color factor: 01 01 10 MIN:(1-A1,C2) ==> not supported - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* #23: color factor: 01 01 11 MIN:(1-A1,A2) - alpha factor: one ==> 11 11 11 */ - { - 0x3F, - 0x3F, - - { - GCREG_BLENDING_MODE_SATURATED_DEST_ALPHA, - GCREG_FACTOR_INVERSE_DISABLE, - BVSRC1USE(1), BVSRC2USE(1), - }, - - { - GCREG_BLENDING_MODE_SATURATED_ALPHA, - GCREG_FACTOR_INVERSE_DISABLE, - BVSRC1USE(1), BVSRC2USE(1) - } - }, - - /* #24: color factor: 01 10 00 MIN:(1-C2,C1) ==> not supported - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* #25: color factor: 01 10 01 MIN:(1-C2,A1) ==> not supported - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* #26: color factor: 01 10 10 MIN:(1-C2,C2) ==> not supported - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* #27: color factor: 01 10 11 MIN:(1-C2,A2) ==> not supported - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* #28: color factor: 01 11 00 MIN:(1-A2,C1) ==> not supported - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* #29: color factor: 01 11 01 MIN:(1-A2,A1) - alpha factor: one ==> 11 11 11 */ - { - 0x3F, - 0x3F, - - { - GCREG_BLENDING_MODE_SATURATED_ALPHA, - GCREG_FACTOR_INVERSE_DISABLE, - BVSRC1USE(1), BVSRC2USE(1), - }, - - { - GCREG_BLENDING_MODE_SATURATED_DEST_ALPHA, - GCREG_FACTOR_INVERSE_DISABLE, - BVSRC1USE(1), BVSRC2USE(1) - } - }, - - /* #30: color factor: 01 11 10 MIN:(1-A2,C2) ==> not supported - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* #31: color factor: 01 11 11 MIN:(1-A2,A2) ==> not supported - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /**********************************************************************/ - /* #32: color factor: 10 00 00 MAX:(1-C1,C1) ==> not supported - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* #33: color factor: 10 00 01 MAX:(1-C1,A1) ==> not supported - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* #34: color factor: 10 00 10 MAX:(1-C1,C2) ==> not supported - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* #35: color factor: 10 00 11 MAX:(1-C1,A2) ==> not supported - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* #36: color factor: 10 01 00 MAX:(1-A1,C1) ==> not supported - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* #37: color factor: 10 01 01 MAX:(1-A1,A1) ==> not supported - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* #38: color factor: 10 01 10 MAX:(1-A1,C2) ==> not supported - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* #39: color factor: 10 01 11 MAX:(1-A1,A2) ==> not supported - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* #40: color factor: 10 10 00 MAX:(1-C2,C1) ==> not supported - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* #41: color factor: 10 10 01 MAX:(1-C2,A1) ==> not supported - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* #42: color factor: 10 10 10 MAX:(1-C2,C2) ==> not supported - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* #43: color factor: 10 10 11 MAX:(1-C2,A2) ==> not supported - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* #44: color factor: 10 11 00 MAX:(1-A2,C1) ==> not supported - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* #45: color factor: 10 11 01 MAX:(1-A2,A1) ==> not supported - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* #46: color factor: 10 11 10 MAX:(1-A2,C2) ==> not supported - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* #47: color factor: 10 11 11 MAX:(1-A2,A2) ==> not supported - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /**********************************************************************/ - /* #48: color factor: 11 00 00 C:(1-C1,C1)=undefined - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* #49: color factor: 11 00 01 C:(1-C1,A1)=1-C1 - alpha factor: 1-A1 ==> 00 01 00 or 00 01 10 */ - { - BVBLENDMATCH(ONLY_A, INV_A1, NORM_C1), - BVBLENDMATCH(ONLY_A, INV_A1, NORM_C2), - - { - GCREG_BLENDING_MODE_COLOR_INVERSED, - GCREG_FACTOR_INVERSE_ENABLE, - BVSRC1USE(1), BVSRC2USE(0), - }, - - { - GCREG_BLENDING_MODE_COLOR_INVERSED, - GCREG_FACTOR_INVERSE_DISABLE, - BVSRC1USE(1), BVSRC2USE(1) - } - }, - - /* #50: color factor: 11 00 10 C:(1-C1,C2)=undefined - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* #51: color factor: 11 00 11 C:(1-C1,A2)=1-C1 - alpha factor: 1-A1 ==> 00 01 00 or 00 01 10 */ - { - BVBLENDMATCH(ONLY_A, INV_A1, NORM_C1), - BVBLENDMATCH(ONLY_A, INV_A1, NORM_C2), - - { - GCREG_BLENDING_MODE_COLOR_INVERSED, - GCREG_FACTOR_INVERSE_ENABLE, - BVSRC1USE(1), BVSRC2USE(0), - }, - - { - GCREG_BLENDING_MODE_COLOR_INVERSED, - GCREG_FACTOR_INVERSE_DISABLE, - BVSRC1USE(1), BVSRC2USE(1) - } - }, - - /* #52: color factor: 11 01 00 C:(1-A1,C1)=C1 - alpha factor: A1 ==> 00 00 01 or 00 10 01 */ - { - BVBLENDMATCH(ONLY_A, INV_C1, NORM_A1), - BVBLENDMATCH(ONLY_A, INV_C2, NORM_A1), - - { - GCREG_BLENDING_MODE_COLOR, - GCREG_FACTOR_INVERSE_ENABLE, - BVSRC1USE(1), BVSRC2USE(0), - }, - - { - GCREG_BLENDING_MODE_COLOR, - GCREG_FACTOR_INVERSE_DISABLE, - BVSRC1USE(1), BVSRC2USE(1) - } - }, - - /* #53: color factor: 11 01 01 C:(1-A1,A1)=undefined - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* #54: color factor: 11 01 10 C:(1-A1,C2)=C2 - alpha factor: A2 ==> 00 00 11 or 00 10 11 */ - { - BVBLENDMATCH(ONLY_A, INV_C1, NORM_A2), - BVBLENDMATCH(ONLY_A, INV_C2, NORM_A2), - - { - GCREG_BLENDING_MODE_COLOR, - GCREG_FACTOR_INVERSE_DISABLE, - BVSRC1USE(1), BVSRC2USE(1), - }, - - { - GCREG_BLENDING_MODE_COLOR, - GCREG_FACTOR_INVERSE_ENABLE, - BVSRC1USE(0), BVSRC2USE(1) - } - }, - - /* #55: color factor: 11 01 11 C:(1-A1,A2)=undefined - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* #56: color factor: 11 10 00 C:(1-C2,C1)=undefined - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* #57: color factor: 11 10 01 C:(1-C2,A1)=1-C2 - alpha factor: 1-A2 ==> 00 11 00 or 00 11 10 */ - { - BVBLENDMATCH(ONLY_A, INV_A2, NORM_C1), - BVBLENDMATCH(ONLY_A, INV_A2, NORM_C2), - - { - GCREG_BLENDING_MODE_COLOR_INVERSED, - GCREG_FACTOR_INVERSE_DISABLE, - BVSRC1USE(1), BVSRC2USE(1), - }, - - { - GCREG_BLENDING_MODE_COLOR_INVERSED, - GCREG_FACTOR_INVERSE_ENABLE, - BVSRC1USE(0), BVSRC2USE(1) - } - }, - - /* #58: color factor: 11 10 10 C:(1-C2,C2)=undefined - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* #59: color factor: 11 10 11 C:(1-C2,A2)=1-C2 - alpha factor: 1-A2 ==> 00 11 00 or 00 11 10 */ - { - BVBLENDMATCH(ONLY_A, INV_A2, NORM_C1), - BVBLENDMATCH(ONLY_A, INV_A2, NORM_C2), - - { - GCREG_BLENDING_MODE_COLOR_INVERSED, - GCREG_FACTOR_INVERSE_DISABLE, - BVSRC1USE(1), BVSRC2USE(1), - }, - - { - GCREG_BLENDING_MODE_COLOR_INVERSED, - GCREG_FACTOR_INVERSE_ENABLE, - BVSRC1USE(0), BVSRC2USE(0) - } - }, - - /* #60: color factor: 11 11 00 C:(1-A2,C1)=C1 - alpha factor: A1 ==> 00 00 01 or 00 10 01 */ - { - BVBLENDMATCH(ONLY_A, INV_C1, NORM_A1), - BVBLENDMATCH(ONLY_A, INV_C2, NORM_A1), - - { - GCREG_BLENDING_MODE_COLOR, - GCREG_FACTOR_INVERSE_ENABLE, - BVSRC1USE(1), BVSRC2USE(0), - }, - - { - GCREG_BLENDING_MODE_COLOR, - GCREG_FACTOR_INVERSE_DISABLE, - BVSRC1USE(1), BVSRC2USE(1) - } - }, - - /* #61: color factor: 11 11 01 C:(1-A2,A1)=undefined - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* #62: color factor: 11 11 10 C:(1-A2,C2)=C2 - alpha factor: A2 ==> 00 00 11 or 00 10 11 */ - { - BVBLENDMATCH(ONLY_A, INV_C1, NORM_A2), - BVBLENDMATCH(ONLY_A, INV_C2, NORM_A2), - - { - GCREG_BLENDING_MODE_COLOR, - GCREG_FACTOR_INVERSE_DISABLE, - BVSRC1USE(1), BVSRC2USE(1), - }, - - { - GCREG_BLENDING_MODE_COLOR, - GCREG_FACTOR_INVERSE_ENABLE, - BVSRC1USE(0), BVSRC2USE(1) - } - }, - - /* #63: color factor: 11 11 11 C:(1-A2,A2)=one - alpha factor: one ==> 11 11 11 */ - { - 0x3F, - 0x3F, - - { - GCREG_BLENDING_MODE_ONE, - GCREG_FACTOR_INVERSE_DISABLE, - BVSRC1USE(1), BVSRC2USE(0), - }, - - { - GCREG_BLENDING_MODE_ONE, - GCREG_FACTOR_INVERSE_DISABLE, - BVSRC1USE(0), BVSRC2USE(1) - } - } -}; - -static enum bverror parse_blend(struct bvbltparams *bltparams, - enum bvblend blend, struct gcalpha *gca) -{ - enum bverror bverror; - unsigned int global; - unsigned int k1, k2, k3, k4; - struct bvblendxlate *k1_xlate; - struct bvblendxlate *k2_xlate; - unsigned int alpha; - - GCDBG(GCZONE_BLEND, "blend = 0x%08X (%s)\n", - blend, gc_bvblend_name(blend)); - - if ((blend & BVBLENDDEF_REMOTE) != 0) { - BVSETBLTERROR(BVERR_BLEND, "remote alpha not supported"); - goto exit; - } - - global = (blend & BVBLENDDEF_GLOBAL_MASK) >> BVBLENDDEF_GLOBAL_SHIFT; - - switch (global) { - case (BVBLENDDEF_GLOBAL_NONE >> BVBLENDDEF_GLOBAL_SHIFT): - GCDBG(GCZONE_BLEND, "BVBLENDDEF_GLOBAL_NONE\n"); - - gca->src_global_color = - gca->dst_global_color = 0; - - gca->src_global_alpha_mode = GCREG_GLOBAL_ALPHA_MODE_NORMAL; - gca->dst_global_alpha_mode = GCREG_GLOBAL_ALPHA_MODE_NORMAL; - break; - - case (BVBLENDDEF_GLOBAL_UCHAR >> BVBLENDDEF_GLOBAL_SHIFT): - GCDBG(GCZONE_BLEND, "BVBLENDDEF_GLOBAL_UCHAR\n"); - - gca->src_global_color = - gca->dst_global_color = - ((unsigned int) bltparams->globalalpha.size8) << 24; - - gca->src_global_alpha_mode = GCREG_GLOBAL_ALPHA_MODE_GLOBAL; - gca->dst_global_alpha_mode = GCREG_GLOBAL_ALPHA_MODE_GLOBAL; - break; - - case (BVBLENDDEF_GLOBAL_FLOAT >> BVBLENDDEF_GLOBAL_SHIFT): - GCDBG(GCZONE_BLEND, "BVBLENDDEF_GLOBAL_FLOAT\n"); - - alpha = gcfp2norm8(bltparams->globalalpha.fp); - - gca->src_global_color = - gca->dst_global_color = alpha << 24; - - gca->src_global_alpha_mode = GCREG_GLOBAL_ALPHA_MODE_GLOBAL; - gca->dst_global_alpha_mode = GCREG_GLOBAL_ALPHA_MODE_GLOBAL; - break; - - default: - BVSETBLTERROR(BVERR_BLEND, "invalid global alpha mode"); - goto exit; - } - - /* - Co = k1 x C1 + k2 x C2 - Ao = k3 x A1 + k4 x A2 - */ - - k1 = (blend >> 18) & 0x3F; - k2 = (blend >> 12) & 0x3F; - k3 = (blend >> 6) & 0x3F; - k4 = blend & 0x3F; + /* Add the address fixup. */ + add_fixup(bltparams, batch, &gcmodst->address, + batch->dstbyteshift); - GCDBG(GCZONE_BLEND, "k1 = %d\n", k1); - GCDBG(GCZONE_BLEND, "k2 = %d\n", k2); - GCDBG(GCZONE_BLEND, "k3 = %d\n", k3); - GCDBG(GCZONE_BLEND, "k4 = %d\n", k4); + /* Set surface parameters. */ + gcmodst->address_ldst = gcmodst_address_ldst; + gcmodst->address = GET_MAP_HANDLE(dstmap); + gcmodst->stride = bltparams->dstgeom->virtstride; - k1_xlate = &blendxlate[k1]; - k2_xlate = &blendxlate[k2]; + /* Set surface width and height. */ + gcmodst->rotation.raw = 0; + gcmodst->rotation.reg.surf_width = batch->physwidth; + gcmodst->rotationheight_ldst = gcmodst_rotationheight_ldst; + gcmodst->rotationheight.raw = 0; + gcmodst->rotationheight.reg.height = batch->physheight; - if (((k3 != k1_xlate->match1) && (k3 != k1_xlate->match2)) || - ((k4 != k2_xlate->match1) && (k4 != k2_xlate->match2))) { - BVSETBLTERROR(BVERR_BLEND, - "not supported coefficient combination"); - goto exit; + /* Set clipping. */ + gcmodst->clip_ldst = gcmodst_clip_ldst; + gcmodst->cliplt.raw = 0; + gcmodst->cliprb.raw = 0; + gcmodst->cliprb.reg.right = GC_CLIP_RESET_RIGHT; + gcmodst->cliprb.reg.bottom = GC_CLIP_RESET_BOTTOM; } - gca->k1 = &k1_xlate->k1; - gca->k2 = &k2_xlate->k2; - - gca->src1used = gca->k1->src1used | gca->k2->src1used; - gca->src2used = gca->k1->src2used | gca->k2->src2used; - - bverror = BVERR_NONE; - exit: + GCEXITARG(GCZONE_DEST, "bv%s = %d\n", + (bverror == BVERR_NONE) ? "result" : "error", bverror); return bverror; } /******************************************************************************* - * Rotation and mirror. - */ - -#define BVFLAG_FLIP_MASK 0x00000003 - -#define BVFLAG_FLIP_SRC1_SHIFT 14 -#define BVFLAG_FLIP_SRC2_SHIFT 16 -#define BVFLAG_FLIP_MASK_SHIFT 18 - -#define GCREG_MIRROR_NONE 0x0 -#define GCREG_MIRROR_X 0x1 -#define GCREG_MIRROR_Y 0x2 -#define GCREG_MIRROR_XY 0x3 - -#define GCREG_ROT_ANGLE_ROT0 0x0 -#define GCREG_ROT_ANGLE_ROT90 0x4 -#define GCREG_ROT_ANGLE_ROT180 0x5 -#define GCREG_ROT_ANGLE_ROT270 0x6 - -#define ROT_ANGLE_INVALID -1 -#define ROT_ANGLE_0 0 -#define ROT_ANGLE_90 1 -#define ROT_ANGLE_180 2 -#define ROT_ANGLE_270 3 - -/* NOTE: BLTsville rotation is defined conunter clock wise. */ -static const unsigned int rotencoding[] = { - GCREG_ROT_ANGLE_ROT0, /* ROT_ANGLE_0 */ - GCREG_ROT_ANGLE_ROT270, /* ROT_ANGLE_90 */ - GCREG_ROT_ANGLE_ROT180, /* ROT_ANGLE_180 */ - GCREG_ROT_ANGLE_ROT90 /* ROT_ANGLE_270 */ -}; - -static inline int get_angle(int orientation) -{ - int angle; - - /* Normalize the angle. */ - angle = orientation % 360; - - /* Flip to positive. */ - if (angle < 0) - angle = 360 + angle; - - /* Translate the angle. */ - switch (angle) { - case 0: return ROT_ANGLE_0; - case 90: return ROT_ANGLE_90; - case 180: return ROT_ANGLE_180; - case 270: return ROT_ANGLE_270; - } - - /* Not supported angle. */ - return ROT_ANGLE_INVALID; -} - - -/******************************************************************************* * Surface compare and validation. */ @@ -2428,32 +452,9 @@ static bool same_phys_area(struct bvbuffdesc *surf1, struct bvrect *rect1, return false; } -static bool valid_geom(struct bvbuffdesc *buffdesc, struct bvsurfgeom *geom, - struct bvformatxlate *format) -{ - unsigned int size; - - /* Compute the size of the surface. */ - size = (geom->width * geom->height * format->bitspp) / 8; - - /* Make sure the size is not greater then the surface. */ - if (size > buffdesc->length) { - GCERR("invalid geometry detected:\n"); - GCERR(" specified dimensions: %dx%d, %d bitspp\n", - geom->width, geom->height, format->bitspp); - GCERR(" surface size based on the dimensions: %d\n", - size); - GCERR(" specified surface size: %lu\n", - buffdesc->length); - return false; - } - - return true; -} - static int verify_surface(unsigned int tile, - union bvinbuff *surf, - struct bvsurfgeom *geom) + union bvinbuff *surf, + struct bvsurfgeom *geom) { if (tile) { if (surf->tileparams == NULL) @@ -2483,1337 +484,6 @@ static int verify_surface(unsigned int tile, return -1; } -#if GCDEBUG_ENABLE -# define VERIFYBATCH(changeflags, prevrect, currrect) \ - verify_batch(changeflags, prevrect, currrect) - -static void verify_batch(unsigned int changeflags, - struct bvrect *prevrect, - struct bvrect *currrect) -{ - if ((changeflags & 1) == 0) { - /* Origin did not change. */ - if ((prevrect->left != currrect->left) || - (prevrect->top != currrect->top)) { - GCERR("origin changed\n"); - GCERR(" previous = %d,%d\n", - prevrect->left, prevrect->top); - GCERR(" current = %d,%d\n", - currrect->left, currrect->top); - } - } - - if ((changeflags & 2) == 0) { - /* Size did not change. */ - if ((prevrect->width != currrect->width) || - (prevrect->height != currrect->height)) { - GCERR("size changed\n"); - GCERR(" previous = %dx%d\n", - prevrect->width, prevrect->height); - GCERR(" current = %dx%d\n", - currrect->width, currrect->height); - } - } - - prevrect->left = currrect->left; - prevrect->top = currrect->top; - prevrect->width = currrect->width; - prevrect->height = currrect->height; -} -#else -# define VERIFYBATCH(...) -#endif - -static inline int get_pixeloffset(struct bvbuffdesc *bvbuffdesc, - struct bvformatxlate *format, - int offset) -{ - unsigned int alignment; - int byteoffset; - unsigned int alignedoffset; - int pixeloffset; - - alignment = (format->type == BVFMT_YUV) - ? (64 - 1) - : (16 - 1); - - /* Determine offset in bytes from the base modified by the - * given offset. */ - if (bvbuffdesc->auxtype == BVAT_PHYSDESC) { - struct bvphysdesc *bvphysdesc; - bvphysdesc = (struct bvphysdesc *) bvbuffdesc->auxptr; - byteoffset = bvphysdesc->pageoffset + offset; - } else { - byteoffset = (unsigned int) bvbuffdesc->virtaddr + offset; - } - - /* Compute the aligned offset. */ - alignedoffset = byteoffset & alignment; - - /* Convert to pixels. */ - pixeloffset = alignedoffset * 8 / format->bitspp; - return -pixeloffset; -} - -static enum bverror parse_destination(struct bvbltparams *bltparams, - struct gcbatch *batch) -{ - enum bverror bverror = BVERR_NONE; - - GCENTER(GCZONE_DEST); - - /* Did clipping/destination rects change? */ - if ((batch->batchflags & (BVBATCH_CLIPRECT | - BVBATCH_DESTRECT)) != 0) { - struct bvrect *dstrect; - struct bvrect *cliprect; - int destleft, desttop, destright, destbottom; - int clipleft, cliptop, clipright, clipbottom; - - /* Make shortcuts to the destination objects. */ - dstrect = &bltparams->dstrect; - cliprect = &bltparams->cliprect; - - /* Determine destination rectangle. */ - destleft = dstrect->left; - desttop = dstrect->top; - destright = destleft + dstrect->width; - destbottom = desttop + dstrect->height; - - GCDBG(GCZONE_DEST, "destination rectangle:\n"); - GCDBG(GCZONE_DEST, " dstrect = (%d,%d)-(%d,%d), %dx%d\n", - destleft, desttop, destright, destbottom, - dstrect->width, dstrect->height); - - /* Determine clipping. */ - if ((bltparams->flags & BVFLAG_CLIP) == BVFLAG_CLIP) { - clipleft = cliprect->left; - cliptop = cliprect->top; - clipright = clipleft + cliprect->width; - clipbottom = cliptop + cliprect->height; - - if ((clipleft < GC_CLIP_RESET_LEFT) || - (cliptop < GC_CLIP_RESET_TOP) || - (clipright > GC_CLIP_RESET_RIGHT) || - (clipbottom > GC_CLIP_RESET_BOTTOM) || - (clipright < clipleft) || - (clipbottom < cliptop)) { - BVSETBLTERROR(BVERR_CLIP_RECT, - "invalid clipping rectangle"); - goto exit; - } - - GCDBG(GCZONE_DEST, - " cliprect = (%d,%d)-(%d,%d), %dx%d\n", - clipleft, cliptop, clipright, clipbottom, - cliprect->width, cliprect->height); - } else { - clipleft = GC_CLIP_RESET_LEFT; - cliptop = GC_CLIP_RESET_TOP; - clipright = GC_CLIP_RESET_RIGHT; - clipbottom = GC_CLIP_RESET_BOTTOM; - } - - /* Compute clipping deltas and the adjusted destination rect. */ - if (clipleft <= destleft) { - batch->deltaleft = 0; - batch->clippedleft = destleft; - } else { - batch->deltaleft = clipleft - destleft; - batch->clippedleft = clipleft; - } - - if (cliptop <= desttop) { - batch->deltatop = 0; - batch->clippedtop = desttop; - } else { - batch->deltatop = cliptop - desttop; - batch->clippedtop = cliptop; - } - - if (clipright >= destright) { - batch->deltaright = 0; - batch->clippedright = destright; - } else { - batch->deltaright = clipright - destright; - batch->clippedright = clipright; - } - - if (clipbottom >= destbottom) { - batch->deltabottom = 0; - batch->clippedbottom = destbottom; - } else { - batch->deltabottom = clipbottom - destbottom; - batch->clippedbottom = clipbottom; - } - - /* Validate the rectangle. */ - if ((batch->clippedright > (int) bltparams->dstgeom->width) || - (batch->clippedbottom > (int) bltparams->dstgeom->height)) { - BVSETBLTERROR(BVERR_DSTRECT, - "destination rect exceeds surface size"); - goto exit; - } - - GCDBG(GCZONE_DEST, - " clipped dstrect = (%d,%d)-(%d,%d), %dx%d\n", - batch->clippedleft, batch->clippedtop, - batch->clippedright, batch->clippedbottom, - batch->clippedright - batch->clippedleft, - batch->clippedbottom - batch->clippedtop); - GCDBG(GCZONE_DEST, - " clipping delta = (%d,%d)-(%d,%d)\n", - batch->deltaleft, batch->deltatop, - batch->deltaright, batch->deltabottom); - } - - /* Did the destination surface change? */ - if ((batch->batchflags & BVBATCH_DST) != 0) { - struct bvbuffdesc *dstdesc; - struct bvsurfgeom *dstgeom; - unsigned int stridealign; - - /* Make shortcuts to the destination objects. */ - dstdesc = bltparams->dstdesc; - dstgeom = bltparams->dstgeom; - - /* Check for unsupported dest formats. */ - switch (dstgeom->format) { - case OCDFMT_NV12: - BVSETBLTERROR(BVERR_DSTGEOM_FORMAT, - "destination format unsupported"); - goto exit; - - default: - break; - } - - /* Parse the destination format. */ - GCDBG(GCZONE_FORMAT, "parsing destination format.\n"); - if (!parse_format(dstgeom->format, &batch->dstformat)) { - BVSETBLTERROR(BVERR_DSTGEOM_FORMAT, - "invalid destination format (%d)", - dstgeom->format); - goto exit; - } - - /* Validate geometry. */ - if (!valid_geom(dstdesc, dstgeom, batch->dstformat)) { - BVSETBLTERROR(BVERR_DSTGEOM, - "destination geom exceeds surface size"); - goto exit; - } - - /* Destination stride must be 8 pixel aligned. */ - stridealign = batch->dstformat->bitspp - 1; - if ((dstgeom->virtstride & stridealign) != 0) { - BVSETBLTERROR(BVERR_DSTGEOM_STRIDE, - "destination stride must be 8 pixel " - "aligned."); - goto exit; - } - - /* Parse orientation. */ - batch->dstangle = get_angle(dstgeom->orientation); - if (batch->dstangle == ROT_ANGLE_INVALID) { - BVSETBLTERROR(BVERR_DSTGEOM, - "unsupported destination orientation %d.", - dstgeom->orientation); - } - - /* Compute the destination offset in pixels needed to compensate - * for the surface base address misalignment if any. */ - batch->dstalign = get_pixeloffset(dstdesc, batch->dstformat, 0); - - switch (batch->dstangle) { - case ROT_ANGLE_0: - /* Determine the physical size. */ - batch->dstphyswidth = dstgeom->width - batch->dstalign; - batch->dstphysheight = dstgeom->height; - - /* Determine geometry size. */ - batch->dstwidth = dstgeom->width - batch->dstalign; - batch->dstheight = dstgeom->height; - - /* Determine the origin offset. */ - batch->dstoffsetX = -batch->dstalign; - batch->dstoffsetY = 0; - break; - - case ROT_ANGLE_90: - /* Determine the physical size. */ - batch->dstphyswidth = dstgeom->height - batch->dstalign; - batch->dstphysheight = dstgeom->width; - - /* Determine geometry size. */ - batch->dstwidth = dstgeom->width; - batch->dstheight = dstgeom->height - batch->dstalign; - - /* Determine the origin offset. */ - batch->dstoffsetX = 0; - batch->dstoffsetY = -batch->dstalign; - break; - - case ROT_ANGLE_180: - /* Determine the physical size. */ - batch->dstphyswidth = dstgeom->width - batch->dstalign; - batch->dstphysheight = dstgeom->height; - - /* Determine geometry size. */ - batch->dstwidth = dstgeom->width - batch->dstalign; - batch->dstheight = dstgeom->height; - - /* Determine the origin offset. */ - batch->dstoffsetX = 0; - batch->dstoffsetY = 0; - break; - - case ROT_ANGLE_270: - /* Determine the physical size. */ - batch->dstphyswidth = dstgeom->height - batch->dstalign; - batch->dstphysheight = dstgeom->width; - - /* Determine geometry size. */ - batch->dstwidth = dstgeom->width; - batch->dstheight = dstgeom->height - batch->dstalign; - - /* Determine the origin offset. */ - batch->dstoffsetX = 0; - batch->dstoffsetY = 0; - break; - } - - GCDBG(GCZONE_DEST, "destination surface:\n"); - GCDBG(GCZONE_SURF, " rotation %d degrees.\n", - batch->dstangle * 90); - - if (dstdesc->auxtype == BVAT_PHYSDESC) { - struct bvphysdesc *bvphysdesc; - bvphysdesc = (struct bvphysdesc *) dstdesc->auxptr; - GCDBG(GCZONE_DEST, " page offset = 0x%08X\n", - bvphysdesc->pageoffset); - } else { - GCDBG(GCZONE_DEST, " virtual address = 0x%08X\n", - (unsigned int) dstdesc->virtaddr); - } - - GCDBG(GCZONE_DEST, " stride = %ld\n", - dstgeom->virtstride); - GCDBG(GCZONE_DEST, " geometry size = %dx%d\n", - dstgeom->width, dstgeom->height); - GCDBG(GCZONE_DEST, " aligned geometry size = %dx%d\n", - batch->dstwidth, batch->dstheight); - GCDBG(GCZONE_DEST, " aligned physical size = %dx%d\n", - batch->dstphyswidth, batch->dstphysheight); - GCDBG(GCZONE_DEST, " origin offset (pixels) = %d,%d\n", - batch->dstoffsetX, batch->dstoffsetY); - GCDBG(GCZONE_DEST, " surface offset (pixels) = %d,0\n", - batch->dstalign); - } - -exit: - GCEXITARG(GCZONE_DEST, "bv%s = %d\n", - (bverror == BVERR_NONE) ? "result" : "error", bverror); - return bverror; -} - -static enum bverror parse_source(struct bvbltparams *bltparams, - struct gcbatch *batch, - struct srcinfo *srcinfo) -{ - enum bverror bverror = BVERR_NONE; - struct bvbuffdesc *srcdesc; - struct bvsurfgeom *srcgeom; - struct bvrect *srcrect; - unsigned int stridealign; - - /* Make shortcuts to the source objects. */ - srcdesc = srcinfo->buf.desc; - srcgeom = srcinfo->geom; - srcrect = srcinfo->rect; - - /* Parse the source format. */ - GCDBG(GCZONE_FORMAT, "parsing source%d format.\n", - srcinfo->index + 1); - if (!parse_format(srcgeom->format, &srcinfo->format)) { - BVSETBLTERROR((srcinfo->index == 0) - ? BVERR_SRC1GEOM_FORMAT - : BVERR_SRC2GEOM_FORMAT, - "invalid source #%d format (%d).", - srcinfo->index + 1, - srcgeom->format); - goto exit; - } - - /* Validate source geometry. */ - if (!valid_geom(srcdesc, srcgeom, srcinfo->format)) { - BVSETBLTERROR((srcinfo->index == 0) - ? BVERR_SRC1GEOM - : BVERR_SRC2GEOM, - "source%d geom exceeds surface size.", - srcinfo->index + 1); - goto exit; - } - - /* Source must be 8 pixel aligned. */ - stridealign = srcinfo->format->bitspp - 1; - if ((srcgeom->virtstride & stridealign) != 0) { - BVSETBLTERROR((srcinfo->index == 0) - ? BVERR_SRC1GEOM_STRIDE - : BVERR_SRC2GEOM_STRIDE, - "source stride must be 8 pixel aligned."); - goto exit; - } - - /* Parse orientation. */ - srcinfo->angle = get_angle(srcgeom->orientation); - if (srcinfo->angle == ROT_ANGLE_INVALID) { - BVSETBLTERROR((srcinfo->index == 0) - ? BVERR_SRC1GEOM - : BVERR_SRC2GEOM, - "unsupported source%d orientation %d.", - srcinfo->index + 1, - srcgeom->orientation); - } - - /* Determine source mirror. */ - srcinfo->mirror = (srcinfo->index == 0) - ? (bltparams->flags >> BVFLAG_FLIP_SRC1_SHIFT) - & BVFLAG_FLIP_MASK - : (bltparams->flags >> BVFLAG_FLIP_SRC2_SHIFT) - & BVFLAG_FLIP_MASK; - - GCDBG(GCZONE_SURF, "source surface %d:\n", srcinfo->index + 1); - GCDBG(GCZONE_SURF, " rotation %d degrees.\n", srcinfo->angle * 90); - - if (srcdesc->auxtype == BVAT_PHYSDESC) { - struct bvphysdesc *bvphysdesc; - bvphysdesc = (struct bvphysdesc *) srcdesc->auxptr; - GCDBG(GCZONE_DEST, " page offset = 0x%08X\n", - bvphysdesc->pageoffset); - } else { - GCDBG(GCZONE_DEST, " virtual address = 0x%08X\n", - (unsigned int) srcdesc->virtaddr); - } - - GCDBG(GCZONE_SURF, " stride = %ld\n", - srcgeom->virtstride); - GCDBG(GCZONE_SURF, " geometry size = %dx%d\n", - srcgeom->width, srcgeom->height); - GCDBG(GCZONE_SURF, " rect = (%d,%d)-(%d,%d), %dx%d\n", - srcrect->left, srcrect->top, - srcrect->left + srcrect->width, - srcrect->top + srcrect->height, - srcrect->width, srcrect->height); - GCDBG(GCZONE_SURF, " mirror = %d\n", srcinfo->mirror); - -exit: - return bverror; -} - - -/******************************************************************************* - * Primitive renderers. - */ - -static enum bverror set_dst(struct bvbltparams *bltparams, - struct gcbatch *batch, - struct bvbuffmap *dstmap) -{ - enum bverror bverror = BVERR_NONE; - struct gcmodst *gcmodst; - - GCENTER(GCZONE_DEST); - - /* Did destination surface change? */ - if ((batch->batchflags & BVBATCH_DST) != 0) { - /* Allocate command buffer. */ - bverror = claim_buffer(bltparams, batch, - sizeof(struct gcmodst), - (void **) &gcmodst); - if (bverror != BVERR_NONE) - goto exit; - - /* Add the address fixup. */ - add_fixup(bltparams, batch, &gcmodst->address, - batch->dstbyteshift); - - /* Set surface parameters. */ - gcmodst->address_ldst = gcmodst_address_ldst; - gcmodst->address = GET_MAP_HANDLE(dstmap); - gcmodst->stride = bltparams->dstgeom->virtstride; - - /* Set surface width and height. */ - gcmodst->rotation.raw = 0; - gcmodst->rotation.reg.surf_width = batch->physwidth; - gcmodst->rotationheight_ldst = gcmodst_rotationheight_ldst; - gcmodst->rotationheight.raw = 0; - gcmodst->rotationheight.reg.height = batch->physheight; - - /* Set clipping. */ - gcmodst->clip_ldst = gcmodst_clip_ldst; - gcmodst->cliplt.raw = 0; - gcmodst->cliprb.raw = 0; - gcmodst->cliprb.reg.right = GC_CLIP_RESET_RIGHT; - gcmodst->cliprb.reg.bottom = GC_CLIP_RESET_BOTTOM; - } - -exit: - GCEXITARG(GCZONE_DEST, "bv%s = %d\n", - (bverror == BVERR_NONE) ? "result" : "error", bverror); - return bverror; -} - -static enum bverror do_fill(struct bvbltparams *bltparams, - struct gcbatch *batch, - struct srcinfo *srcinfo) -{ - enum bverror bverror; - int dstbyteshift; - struct gcmofill *gcmofill; - unsigned char *fillcolorptr; - struct bvbuffmap *dstmap = NULL; - - GCENTER(GCZONE_DO_FILL); - - /* Finish previous batch if any. */ - bverror = batch->batchend(bltparams, batch); - if (bverror != BVERR_NONE) - goto exit; - - /* Compute the surface offset in bytes. */ - dstbyteshift = batch->dstalign * (int) batch->dstformat->bitspp / 8; - - /* Verify if the destination parameter have been modified. */ - if ((batch->dstbyteshift != dstbyteshift) || - (batch->physwidth != batch->dstphyswidth) || - (batch->physheight != batch->dstphysheight)) { - /* Set new values. */ - batch->dstbyteshift = dstbyteshift; - batch->physwidth = batch->dstphyswidth; - batch->physheight = batch->dstphysheight; - - /* Mark as modified. */ - batch->batchflags |= BVBATCH_DST; - } - - /* Map the destination. */ - bverror = do_map(bltparams->dstdesc, batch, &dstmap); - if (bverror != BVERR_NONE) { - bltparams->errdesc = gccontext.bverrorstr; - goto exit; - } - - /* Set the new destination. */ - bverror = set_dst(bltparams, batch, dstmap); - if (bverror != BVERR_NONE) - goto exit; - - /* Reset the modified flag. */ - batch->batchflags &= ~(BVBATCH_DST | - BVBATCH_CLIPRECT | - BVBATCH_DESTRECT); - - /*********************************************************************** - ** Allocate command buffer. - */ - - bverror = claim_buffer(bltparams, batch, - sizeof(struct gcmofill), - (void **) &gcmofill); - if (bverror != BVERR_NONE) - goto exit; - - /*********************************************************************** - ** Set dummy source. - */ - - /* Set surface dummy width and height. */ - gcmofill->src.rotation_ldst = gcmofillsrc_rotation_ldst; - gcmofill->src.rotation.raw = 0; - gcmofill->src.rotation.reg.surf_width = 1; - gcmofill->src.config.raw = 0; - - gcmofill->src.rotationheight_ldst = gcmofillsrc_rotationheight_ldst; - gcmofill->src.rotationheight.reg.height = 1; - gcmofill->src.rotationangle.raw = 0; - gcmofill->src.rotationangle.reg.dst = GCREG_ROT_ANGLE_ROT0; - gcmofill->src.rotationangle.reg.dst_mirror = GCREG_MIRROR_NONE; - - /* Disable alpha blending. */ - gcmofill->src.alphacontrol_ldst = gcmofillsrc_alphacontrol_ldst; - gcmofill->src.alphacontrol.raw = 0; - gcmofill->src.alphacontrol.reg.enable = GCREG_ALPHA_CONTROL_ENABLE_OFF; - - /*********************************************************************** - ** Set fill color. - */ - - fillcolorptr - = (unsigned char *) srcinfo->buf.desc->virtaddr - + srcinfo->rect->top * srcinfo->geom->virtstride - + srcinfo->rect->left * srcinfo->format->bitspp / 8; - - gcmofill->clearcolor_ldst = gcmofill_clearcolor_ldst; - gcmofill->clearcolor.raw = getinternalcolor(fillcolorptr, - srcinfo->format); - - /*********************************************************************** - ** Configure and start fill. - */ - - /* Set destination configuration. */ - gcmofill->dstconfig_ldst = gcmofill_dstconfig_ldst; - gcmofill->dstconfig.raw = 0; - gcmofill->dstconfig.reg.swizzle = batch->dstformat->swizzle; - gcmofill->dstconfig.reg.format = batch->dstformat->format; - gcmofill->dstconfig.reg.command = GCREG_DEST_CONFIG_COMMAND_CLEAR; - - /* Set ROP3. */ - gcmofill->rop_ldst = gcmofill_rop_ldst; - gcmofill->rop.raw = 0; - gcmofill->rop.reg.type = GCREG_ROP_TYPE_ROP3; - gcmofill->rop.reg.fg = (unsigned char) bltparams->op.rop; - - /* Set START_DE command. */ - gcmofill->startde.cmd.fld = gcfldstartde; - - /* Set destination rectangle. */ - gcmofill->rect.left = batch->clippedleft + batch->dstoffsetX; - gcmofill->rect.top = batch->clippedtop + batch->dstoffsetY; - gcmofill->rect.right = batch->clippedright + batch->dstoffsetX; - gcmofill->rect.bottom = batch->clippedbottom + batch->dstoffsetY; - -exit: - GCEXITARG(GCZONE_DO_FILL, "bv%s = %d\n", - (bverror == BVERR_NONE) ? "result" : "error", bverror); - return bverror; -} - -#define ENABLE_HW_BLOCK 1 -static enum bverror do_blit_end(struct bvbltparams *bltparams, - struct gcbatch *batch) -{ - enum bverror bverror; - struct gcmobltconfig *gcmobltconfig; - struct gcmostart *gcmostart; - - GCENTER(GCZONE_DO_BLIT); - - GCDBG(GCZONE_DO_BLIT, "finalizing the blit, scrcount = %d\n", - batch->gcblit.srccount); - - /*********************************************************************** - * Configure the operation. - */ - - /* Allocate command buffer. */ - bverror = claim_buffer(bltparams, batch, - sizeof(struct gcmobltconfig), - (void **) &gcmobltconfig); - if (bverror != BVERR_NONE) - goto exit; - - /* Configure multi-source control. */ - gcmobltconfig->multisource_ldst = gcmobltconfig_multisource_ldst; - gcmobltconfig->multisource.raw = 0; - gcmobltconfig->multisource.reg.srccount = batch->gcblit.srccount - 1; - - GCDBG(GCZONE_DO_BLIT, "blockenable = %d\n", batch->blockenable); - if (batch->blockenable && ENABLE_HW_BLOCK) { - gcmobltconfig->multisource.reg.horblock - = GCREG_DE_MULTI_SOURCE_HORIZONTAL_BLOCK_PIXEL16; - gcmobltconfig->multisource.reg.verblock - = GCREG_DE_MULTI_SOURCE_VERTICAL_BLOCK_LINE64; - } else { - gcmobltconfig->multisource.reg.horblock - = GCREG_DE_MULTI_SOURCE_HORIZONTAL_BLOCK_PIXEL128; - gcmobltconfig->multisource.reg.verblock - = GCREG_DE_MULTI_SOURCE_VERTICAL_BLOCK_LINE1; - } - - /* Set destination configuration. */ - GCDBG(GCZONE_DO_BLIT, "format entry = 0x%08X\n", - (unsigned int) batch->dstformat); - GCDBG(GCZONE_DO_BLIT, " swizzle code = %d\n", - batch->dstformat->swizzle); - GCDBG(GCZONE_DO_BLIT, " format code = %d\n", - batch->dstformat->format); - - gcmobltconfig->dstconfig_ldst = gcmobltconfig_dstconfig_ldst; - gcmobltconfig->dstconfig.raw = 0; - gcmobltconfig->dstconfig.reg.swizzle = batch->dstformat->swizzle; - gcmobltconfig->dstconfig.reg.format = batch->dstformat->format; - gcmobltconfig->dstconfig.reg.command = batch->gcblit.multisrc - ? GCREG_DEST_CONFIG_COMMAND_MULTI_SOURCE_BLT - : GCREG_DEST_CONFIG_COMMAND_BIT_BLT; - - /* Set ROP. */ - gcmobltconfig->rop_ldst = gcmobltconfig_rop_ldst; - gcmobltconfig->rop.raw = 0; - gcmobltconfig->rop.reg.type = GCREG_ROP_TYPE_ROP3; - gcmobltconfig->rop.reg.fg = (unsigned char) batch->gcblit.rop; - - /*********************************************************************** - * Start the operation. - */ - - /* Allocate command buffer. */ - bverror = claim_buffer(bltparams, batch, - sizeof(struct gcmostart), - (void **) &gcmostart); - if (bverror != BVERR_NONE) - goto exit; - - /* Set START_DE command. */ - gcmostart->startde.cmd.fld = gcfldstartde; - - /* Set destination rectangle. */ - gcmostart->rect.left = batch->left; - gcmostart->rect.top = batch->top; - gcmostart->rect.right = batch->right; - gcmostart->rect.bottom = batch->bottom; - - GCDBG(GCZONE_DO_BLIT, "dstrect = (%d,%d)-(%d,%d)\n", - gcmostart->rect.left, gcmostart->rect.top, - gcmostart->rect.right, gcmostart->rect.bottom); - - /* Reset the finalizer. */ - batch->batchend = do_end; - - gc_debug_blt(batch->gcblit.srccount, - abs(batch->right - batch->left), - abs(batch->bottom - batch->top)); - -exit: - GCEXITARG(GCZONE_DO_BLIT, "bv%s = %d\n", - (bverror == BVERR_NONE) ? "result" : "error", bverror); - return bverror; -} - -static enum bverror do_blit(struct bvbltparams *bltparams, - struct gcbatch *batch, - struct srcinfo *srcinfo) -{ - enum bverror bverror = BVERR_NONE; - - struct gcmosrc *gcmosrc; - struct gcmosrcalpha *gcmosrcalpha; - - unsigned int index; - - struct bvbuffmap *dstmap; - struct bvbuffdesc *dstdesc; - struct bvsurfgeom *dstgeom; - struct bvformatxlate *dstformat; - int dstshiftX, dstshiftY; - int dstalign, dstbyteshift; - - struct bvbuffmap *srcmap; - struct gcalpha *srcgca; - struct bvrect *srcrect; - struct bvbuffdesc *srcdesc; - struct bvsurfgeom *srcgeom; - struct bvformatxlate *srcformat; - int srcshiftX, srcshiftY; - int srcalign, srcbyteshift; - - int srcleft, srctop; - int dstleft, dsttop, dstright, dstbottom; - int srcsurfwidth, srcsurfheight; - unsigned int physwidth, physheight; - int orthogonal; - int multisrc; - - GCENTER(GCZONE_DO_BLIT); - - /* Create source object shortcuts. */ - srcmap = NULL; - srcgca = srcinfo->gca; - srcrect = srcinfo->rect; - srcdesc = srcinfo->buf.desc; - srcgeom = srcinfo->geom; - srcformat = srcinfo->format; - - /* Create destination object shortcuts. */ - dstmap = NULL; - dstdesc = bltparams->dstdesc; - dstgeom = bltparams->dstgeom; - dstformat = batch->dstformat; - - /*********************************************************************** - * Determine source surface alignment offset. - */ - - /* Determine whether the source and the destination are orthogonal - * to each other. */ - orthogonal = (srcinfo->angle % 2) != (batch->dstangle % 2); - - /* Compute adjusted destination rectangle. */ - dstleft = batch->clippedleft + batch->dstoffsetX; - dsttop = batch->clippedtop + batch->dstoffsetY; - dstright = batch->clippedright + batch->dstoffsetX; - dstbottom = batch->clippedbottom + batch->dstoffsetY; - - /* Compute clipped source origin. */ - srcleft = srcrect->left + batch->deltaleft; - srctop = srcrect->top + batch->deltatop; - - GCDBG(GCZONE_SURF, "adjusted dstrect = (%d,%d)-(%d,%d), %dx%d\n", - dstleft, dsttop, dstright, dstbottom, - dstright - dstleft, dstbottom - dsttop); - - /* Compute the source surface shift. */ - switch (srcinfo->angle) { - case ROT_ANGLE_0: - srcshiftX = srcleft - dstleft; - srcshiftY = srctop - dsttop; - break; - - case ROT_ANGLE_90: - srcshiftX = srctop - dsttop; - srcshiftY = (srcgeom->width - srcleft) - - (batch->dstwidth - dstleft); - break; - - case ROT_ANGLE_180: - srcshiftX = (srcgeom->width - srcleft) - - (batch->dstwidth - dstleft); - srcshiftY = (srcgeom->height - srctop) - - (batch->dstheight - dsttop); - break; - - case ROT_ANGLE_270: - srcshiftX = (srcgeom->height - srctop) - - (batch->dstheight - dsttop); - srcshiftY = srcleft - dstleft; - break; - - default: - srcshiftX = 0; - srcshiftY = 0; - } - - /* Compute the source surface offset in bytes. */ - srcbyteshift = srcshiftY * (int) srcgeom->virtstride - + srcshiftX * (int) srcformat->bitspp / 8; - - /* Compute the source offset in pixels needed to compensate - * for the surface base address misalignment if any. */ - srcalign = get_pixeloffset(srcdesc, srcformat, srcbyteshift); - - GCDBG(GCZONE_SURF, "source surface %d:\n", srcinfo->index + 1); - GCDBG(GCZONE_SURF, " surface offset (pixels) = %d,%d\n", - srcshiftX, srcshiftY); - GCDBG(GCZONE_SURF, " surface offset (bytes) = 0x%08X\n", - srcbyteshift); - GCDBG(GCZONE_SURF, " srcalign = %d\n", - srcalign); - - /* Apply the source alignment. */ - srcbyteshift += srcalign * (int) srcformat->bitspp / 8; - srcshiftX += srcalign; - - GCDBG(GCZONE_SURF, " adjusted surface offset (pixels) = %d,%d\n", - srcshiftX, srcshiftY); - GCDBG(GCZONE_SURF, " adjusted surface offset (bytes) = 0x%08X\n", - srcbyteshift); - - /* Determine the destination surface shift. */ - dstshiftX = batch->dstalign; - dstshiftY = (((srcinfo->angle + 3) % 4) == batch->dstangle) - ? srcalign : 0; - - /* Compute the destination surface offset in bytes. */ - dstbyteshift = dstshiftY * (int) dstgeom->virtstride - + dstshiftX * (int) dstformat->bitspp / 8; - - /* Compute the destination offset in pixels needed to compensate - * for the surface base address misalignment if any. */ - dstalign = get_pixeloffset(dstdesc, dstformat, dstbyteshift); - - GCDBG(GCZONE_SURF, "destination surface:\n"); - GCDBG(GCZONE_SURF, " surface offset (pixels) = %d,%d\n", - dstshiftX, dstshiftY); - GCDBG(GCZONE_SURF, " surface offset (bytes) = 0x%08X\n", - dstbyteshift); - GCDBG(GCZONE_SURF, " realignment = %d\n", - dstalign); - - if ((srcformat->format == GCREG_DE_FORMAT_NV12) || - (dstalign != 0) || - ((srcalign != 0) && (srcinfo->angle == batch->dstangle))) { - /* Compute the source offset in pixels needed to compensate - * for the surface base address misalignment if any. */ - srcalign = get_pixeloffset(srcdesc, srcformat, 0); - - /* Compute the surface offsets in bytes. */ - srcbyteshift = srcalign * (int) srcformat->bitspp / 8; - dstbyteshift = batch->dstalign * (int) dstformat->bitspp / 8; - - GCDBG(GCZONE_SURF, "recomputed for single-source setup:\n"); - GCDBG(GCZONE_SURF, " srcalign = %d\n", - srcalign); - GCDBG(GCZONE_SURF, " srcsurf offset (bytes) = 0x%08X\n", - srcbyteshift); - GCDBG(GCZONE_SURF, " dstsurf offset (bytes) = 0x%08X\n", - dstbyteshift); - - switch (srcinfo->angle) { - case ROT_ANGLE_0: - /* Adjust left coordinate. */ - srcleft -= srcalign; - - /* Determine source size. */ - srcsurfwidth = srcgeom->width - srcalign; - srcsurfheight = srcgeom->height; - break; - - case ROT_ANGLE_90: - /* Adjust top coordinate. */ - srctop -= srcalign; - - /* Determine source size. */ - srcsurfwidth = srcgeom->height - srcalign; - srcsurfheight = srcgeom->width; - break; - - case ROT_ANGLE_180: - /* Determine source size. */ - srcsurfwidth = srcgeom->width - srcalign; - srcsurfheight = srcgeom->height; - break; - - case ROT_ANGLE_270: - /* Determine source size. */ - srcsurfwidth = srcgeom->height - srcalign; - srcsurfheight = srcgeom->width; - break; - - default: - srcsurfwidth = 0; - srcsurfheight = 0; - } - - GCDBG(GCZONE_SURF, "srcrect origin = %d,%d\n", - srcleft, srctop); - GCDBG(GCZONE_SURF, "source physical size = %dx%d\n", - srcsurfwidth, srcsurfheight); - - /* Set the physical destination size. */ - physwidth = batch->dstphyswidth; - physheight = batch->dstphysheight; - - /* Disable multi source for YUV and for the cases where - * the destination and the base address alignment does - * not match. */ - multisrc = 0; - GCDBG(GCZONE_SURF, "multi-source disabled.\n"); - } else { - /* Source origin is not used in multi-source setup. */ - srcleft = 0; - srctop = 0; - - /* Adjust the destination to match the source geometry. */ - switch (srcinfo->angle) { - case ROT_ANGLE_0: - dstleft -= srcalign; - dstright -= srcalign; - - /* Apply the source alignment. */ - if ((batch->dstangle == ROT_ANGLE_0) || - (batch->dstangle == ROT_ANGLE_180)) { - physwidth = batch->dstphyswidth - srcalign; - physheight = batch->dstphysheight; - } else { - physwidth = batch->dstphyswidth; - physheight = batch->dstphysheight - srcalign; - } - break; - - case ROT_ANGLE_90: - dsttop -= srcalign; - dstbottom -= srcalign; - - /* Apply the source alignment. */ - if ((batch->dstangle == ROT_ANGLE_0) || - (batch->dstangle == ROT_ANGLE_180)) { - physwidth = batch->dstphyswidth; - physheight = batch->dstphysheight - srcalign; - } else { - physwidth = batch->dstphyswidth - srcalign; - physheight = batch->dstphysheight; - } - break; - - case ROT_ANGLE_180: - /* Apply the source alignment. */ - if ((batch->dstangle == ROT_ANGLE_0) || - (batch->dstangle == ROT_ANGLE_180)) { - physwidth = batch->dstphyswidth - srcalign; - physheight = batch->dstphysheight; - } else { - physwidth = batch->dstphyswidth; - physheight = batch->dstphysheight - srcalign; - } - break; - - case ROT_ANGLE_270: - /* Apply the source alignment. */ - if ((batch->dstangle == ROT_ANGLE_0) || - (batch->dstangle == ROT_ANGLE_180)) { - physwidth = batch->dstphyswidth; - physheight = batch->dstphysheight - srcalign; - } else { - physwidth = batch->dstphyswidth - srcalign; - physheight = batch->dstphysheight; - } - break; - - default: - physwidth = 0; - physheight = 0; - } - - /* Source geometry is now the same as the destination. */ - if (orthogonal) { - srcsurfwidth = physheight; - srcsurfheight = physwidth; - } else { - srcsurfwidth = physwidth; - srcsurfheight = physheight; - } - - /* Enable multi-source. */ - multisrc = 1; - GCDBG(GCZONE_SURF, "multi-source enabled.\n"); - } - - /* Verify if the destination has been modified. */ - if ((batch->dstbyteshift != dstbyteshift) || - (batch->physwidth != physwidth) || - (batch->physheight != physheight)) { - /* Set new values. */ - batch->dstbyteshift = dstbyteshift; - batch->physwidth = physwidth; - batch->physheight = physheight; - - /* Mark as modified. */ - batch->batchflags |= BVBATCH_DST; - } - - /* Check if we need to finalize existing batch. */ - if ((batch->batchend != do_blit_end) || - (batch->gcblit.srccount == 4) || - (batch->gcblit.multisrc == 0) || - (multisrc == 0) || - ((batch->batchflags & (BVBATCH_DST | - BVBATCH_CLIPRECT | - BVBATCH_DESTRECT)) != 0)) { - /* Finalize existing batch if any. */ - bverror = batch->batchend(bltparams, batch); - if (bverror != BVERR_NONE) - goto exit; - - /* Initialize the new batch. */ - batch->batchend = do_blit_end; - batch->blockenable = 0; - batch->gcblit.srccount = 0; - batch->gcblit.multisrc = multisrc; - batch->gcblit.rop = srcinfo->rop; - } - - /* Set destination coordinates. */ - batch->left = dstleft; - batch->top = dsttop; - batch->right = dstright; - batch->bottom = dstbottom; - - /* Map the destination. */ - bverror = do_map(dstdesc, batch, &dstmap); - if (bverror != BVERR_NONE) { - bltparams->errdesc = gccontext.bverrorstr; - goto exit; - } - - /* Set the new destination. */ - bverror = set_dst(bltparams, batch, dstmap); - if (bverror != BVERR_NONE) - goto exit; - - /* Reset the modified flag. */ - batch->batchflags &= ~(BVBATCH_DST | - BVBATCH_CLIPRECT | - BVBATCH_DESTRECT); - - /* Map the source. */ - bverror = do_map(srcdesc, batch, &srcmap); - if (bverror != BVERR_NONE) { - bltparams->errdesc = gccontext.bverrorstr; - goto exit; - } - - /*************************************************************** - ** Configure source. - */ - - /* We need to walk in blocks if the source and the destination - * surfaces are orthogonal to each other. */ - batch->blockenable = orthogonal; - - /* Allocate command buffer. */ - bverror = claim_buffer(bltparams, batch, - sizeof(struct gcmosrc), - (void **) &gcmosrc); - if (bverror != BVERR_NONE) - goto exit; - - /* Shortcut to the register index. */ - index = batch->gcblit.srccount; - - add_fixup(bltparams, batch, &gcmosrc->address, srcbyteshift); - - /* Set surface parameters. */ - gcmosrc->address_ldst = gcmosrc_address_ldst[index]; - gcmosrc->address = GET_MAP_HANDLE(srcmap); - - gcmosrc->stride_ldst = gcmosrc_stride_ldst[index]; - gcmosrc->stride = srcgeom->virtstride; - - gcmosrc->rotation_ldst = gcmosrc_rotation_ldst[index]; - gcmosrc->rotation.raw = 0; - gcmosrc->rotation.reg.surf_width = srcsurfwidth; - - gcmosrc->config_ldst = gcmosrc_config_ldst[index]; - gcmosrc->config.raw = 0; - gcmosrc->config.reg.swizzle = srcformat->swizzle; - gcmosrc->config.reg.format = srcformat->format; - - gcmosrc->origin_ldst = gcmosrc_origin_ldst[index]; - gcmosrc->origin.reg.x = srcleft; - gcmosrc->origin.reg.y = srctop; - - gcmosrc->size_ldst = gcmosrc_size_ldst[index]; - gcmosrc->size.reg = gcregsrcsize_max; - - gcmosrc->rotationheight_ldst - = gcmosrc_rotationheight_ldst[index]; - gcmosrc->rotationheight.reg.height = srcsurfheight; - - gcmosrc->rotationangle_ldst - = gcmosrc_rotationangle_ldst[index]; - gcmosrc->rotationangle.raw = 0; - gcmosrc->rotationangle.reg.src = rotencoding[srcinfo->angle]; - gcmosrc->rotationangle.reg.dst = rotencoding[batch->dstangle]; - gcmosrc->rotationangle.reg.src_mirror = srcinfo->mirror; - gcmosrc->rotationangle.reg.dst_mirror = GCREG_MIRROR_NONE; - - gcmosrc->rop_ldst = gcmosrc_rop_ldst[index]; - gcmosrc->rop.raw = 0; - gcmosrc->rop.reg.type = GCREG_ROP_TYPE_ROP3; - gcmosrc->rop.reg.fg = (unsigned char) batch->gcblit.rop; - - gcmosrc->mult_ldst = gcmosrc_mult_ldst[index]; - gcmosrc->mult.raw = 0; - gcmosrc->mult.reg.srcglobalpremul - = GCREG_COLOR_MULTIPLY_MODES_SRC_GLOBAL_PREMULTIPLY_DISABLE; - - if ((srcgeom->format & OCDFMTDEF_NON_PREMULT) != 0) - gcmosrc->mult.reg.srcpremul - = GCREG_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_ENABLE; - else - gcmosrc->mult.reg.srcpremul - = GCREG_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_DISABLE; - - if ((dstgeom->format & OCDFMTDEF_NON_PREMULT) != 0) { - gcmosrc->mult.reg.dstpremul - = GCREG_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_ENABLE; - - gcmosrc->mult.reg.dstdemul - = GCREG_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY_ENABLE; - } else { - gcmosrc->mult.reg.dstpremul - = GCREG_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_DISABLE; - - gcmosrc->mult.reg.dstdemul - = GCREG_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY_DISABLE; - } - - if (srcformat->format == GCREG_DE_FORMAT_NV12) { - struct gcmosrcplanaryuv *yuv; - int uvshift = srcbyteshift; - -#if 0 - /* TODO: needs rework */ - if (multisrc && (srcsurftop % 2)) { - /* We can't shift the uv plane by an odd number - * of rows. */ - BVSETBLTERROR(BVERR_SRC1RECT, - "src/dst y coordinate combination" - " not supported"); - goto exit; - } -#endif - - bverror = claim_buffer(bltparams, batch, - sizeof(struct gcmosrcplanaryuv), - (void **) &yuv); - if (bverror != BVERR_NONE) - goto exit; - - yuv->uplaneaddress_ldst = - gcmosrc_uplaneaddress_ldst[index]; - yuv->uplanestride_ldst = - gcmosrc_uplanestride_ldst[index]; - yuv->vplaneaddress_ldst = - gcmosrc_vplaneaddress_ldst[index]; - yuv->vplanestride_ldst = - gcmosrc_vplanestride_ldst[index]; - -#if 0 - /* TODO: needs rework */ - if (multisrc) { - /* UV plane is half height. */ - uvshift = (srcsurftop / 2) - * (int) srcgeom->virtstride - + srcsurfleft - * (int) srcformat->bitspp / 8; - } else { - /* No shift needed for single source walker. */ - uvshift = 0; - } -#endif - - GCDBG(GCZONE_SURF, " uvshift = 0x%08X (%d)\n", - uvshift, uvshift); - - /* add fixed offset from Y plane */ - uvshift += srcgeom->virtstride * srcgeom->height; - - GCDBG(GCZONE_SURF, " final uvshift = 0x%08X (%d)\n", - uvshift, uvshift); - - yuv->uplaneaddress = GET_MAP_HANDLE(srcmap); - add_fixup(bltparams, batch, &yuv->uplaneaddress, uvshift); - - yuv->uplanestride = srcgeom->virtstride; - - yuv->vplaneaddress = GET_MAP_HANDLE(srcmap); - add_fixup(bltparams, batch, &yuv->vplaneaddress, uvshift); - - yuv->vplanestride = srcgeom->virtstride; - } - - if (srcgca != NULL) { - gcmosrc->alphacontrol_ldst - = gcmosrc_alphacontrol_ldst[index]; - gcmosrc->alphacontrol.raw = 0; - gcmosrc->alphacontrol.reg.enable - = GCREG_ALPHA_CONTROL_ENABLE_ON; - - /* Allocate command buffer. */ - bverror = claim_buffer(bltparams, batch, - sizeof(struct gcmosrcalpha), - (void **) &gcmosrcalpha); - if (bverror != BVERR_NONE) - goto exit; - - gcmosrcalpha->alphamodes_ldst - = gcmosrcalpha_alphamodes_ldst[index]; - gcmosrcalpha->alphamodes.raw = 0; - gcmosrcalpha->alphamodes.reg.src_global_alpha - = srcgca->src_global_alpha_mode; - gcmosrcalpha->alphamodes.reg.dst_global_alpha - = srcgca->dst_global_alpha_mode; - - gcmosrcalpha->alphamodes.reg.src_blend - = srcgca->srcconfig->factor_mode; - gcmosrcalpha->alphamodes.reg.src_color_reverse - = srcgca->srcconfig->color_reverse; - - gcmosrcalpha->alphamodes.reg.dst_blend - = srcgca->dstconfig->factor_mode; - gcmosrcalpha->alphamodes.reg.dst_color_reverse - = srcgca->dstconfig->color_reverse; - - GCDBG(GCZONE_BLEND, "dst blend:\n"); - GCDBG(GCZONE_BLEND, " factor = %d\n", - gcmosrcalpha->alphamodes.reg.dst_blend); - GCDBG(GCZONE_BLEND, " inverse = %d\n", - gcmosrcalpha->alphamodes.reg.dst_color_reverse); - - GCDBG(GCZONE_BLEND, "src blend:\n"); - GCDBG(GCZONE_BLEND, " factor = %d\n", - gcmosrcalpha->alphamodes.reg.src_blend); - GCDBG(GCZONE_BLEND, " inverse = %d\n", - gcmosrcalpha->alphamodes.reg.src_color_reverse); - - gcmosrcalpha->srcglobal_ldst - = gcmosrcalpha_srcglobal_ldst[index]; - gcmosrcalpha->srcglobal.raw = srcgca->src_global_color; - - gcmosrcalpha->dstglobal_ldst - = gcmosrcalpha_dstglobal_ldst[index]; - gcmosrcalpha->dstglobal.raw = srcgca->dst_global_color; - } else { - GCDBG(GCZONE_BLEND, "blending disabled.\n"); - - gcmosrc->alphacontrol_ldst - = gcmosrc_alphacontrol_ldst[index]; - gcmosrc->alphacontrol.raw = 0; - gcmosrc->alphacontrol.reg.enable - = GCREG_ALPHA_CONTROL_ENABLE_OFF; - } - - batch->gcblit.srccount += 1; - -exit: - GCEXITARG(GCZONE_DO_BLIT, "bv%s = %d\n", - (bverror == BVERR_NONE) ? "result" : "error", bverror); - return bverror; -} - -static enum bverror do_filter(struct bvbltparams *bltparams, - struct gcbatch *batch, - struct srcinfo *srcinfo) -{ - enum bverror bverror; - GCENTER(GCZONE_DO_FILTER); - - GCDBG(GCZONE_DO_FILTER, "source rectangle:\n"); - GCDBG(GCZONE_DO_FILTER, " stride = %d, geom = %dx%d\n", - srcinfo->geom->virtstride, - srcinfo->geom->width, srcinfo->geom->height); - GCDBG(GCZONE_DO_FILTER, " rotation = %d\n", - get_angle(srcinfo->geom->orientation)); - GCDBG(GCZONE_DO_FILTER, " rect = (%d,%d)-(%d,%d), %dx%d\n", - srcinfo->rect->left, srcinfo->rect->top, - srcinfo->rect->left + srcinfo->rect->width, - srcinfo->rect->top + srcinfo->rect->height, - srcinfo->rect->width, srcinfo->rect->height); - - GCDBG(GCZONE_DO_FILTER, "destination rectangle:\n"); - GCDBG(GCZONE_DO_FILTER, " stride = %d, geom size = %dx%d\n", - bltparams->dstgeom->virtstride, - bltparams->dstgeom->width, bltparams->dstgeom->height); - GCDBG(GCZONE_DO_FILTER, " rotaton = %d\n", - get_angle(bltparams->dstgeom->orientation)); - GCDBG(GCZONE_DO_FILTER, " rect = (%d,%d)-(%d,%d), %dx%d\n", - bltparams->dstrect.left, bltparams->dstrect.top, - bltparams->dstrect.left + bltparams->dstrect.width, - bltparams->dstrect.top + bltparams->dstrect.height, - bltparams->dstrect.width, bltparams->dstrect.height); - - BVSETBLTERROR((srcinfo->index == 0) - ? BVERR_SRC1_HORZSCALE - : BVERR_SRC2_HORZSCALE, - "scaling not supported"); - - GCEXITARG(GCZONE_DO_FILTER, "bv%s = %d\n", - (bverror == BVERR_NONE) ? "result" : "error", bverror); - return bverror; -} - /******************************************************************************* * Library constructor and destructor. @@ -3821,55 +491,72 @@ static enum bverror do_filter(struct bvbltparams *bltparams, void bv_init(void) { + struct gccontext *gccontext = get_context(); + GCDBG_REGISTER(gcbv); - GCLOCK_INIT(&gccontext.batchlock); - GCLOCK_INIT(&gccontext.bufferlock); - GCLOCK_INIT(&gccontext.fixuplock); - GCLOCK_INIT(&gccontext.maplock); - GCLOCK_INIT(&gccontext.callbacklock); - INIT_LIST_HEAD(&gccontext.callbacklist); - INIT_LIST_HEAD(&gccontext.callbackvac); - INIT_LIST_HEAD(&gccontext.vac_unmap); + GCDBG_REGISTER(gcparser); + GCDBG_REGISTER(gcmap); + GCDBG_REGISTER(gcbuffer); + GCDBG_REGISTER(gcfill); + GCDBG_REGISTER(gcblit); + GCDBG_REGISTER(gcfilter); + + GCLOCK_INIT(&gccontext->batchlock); + GCLOCK_INIT(&gccontext->bufferlock); + GCLOCK_INIT(&gccontext->fixuplock); + GCLOCK_INIT(&gccontext->maplock); + GCLOCK_INIT(&gccontext->callbacklock); + + INIT_LIST_HEAD(&gccontext->unmapvac); + INIT_LIST_HEAD(&gccontext->buffervac); + INIT_LIST_HEAD(&gccontext->fixupvac); + INIT_LIST_HEAD(&gccontext->batchvac); + INIT_LIST_HEAD(&gccontext->callbacklist); + INIT_LIST_HEAD(&gccontext->callbackvac); } void bv_exit(void) { + struct gccontext *gccontext = get_context(); + struct bvbuffmap *bvbuffmap; struct list_head *head; - struct gcschedunmap *bufunmap; - struct bvbuffmap *bufmap; - struct gcbuffer *buffer; - struct gcfixup *fixup; - struct gcvacbatch *batch; - - while (!list_empty(&gccontext.vac_unmap)) { - head = gccontext.vac_unmap.next; - bufunmap = list_entry(head, struct gcschedunmap, link); - list_del(head); - gcfree(bufunmap); + struct gcschedunmap *gcschedunmap; + struct gcbuffer *gcbuffer; + struct gcfixup *gcfixup; + struct gcbatch *gcbatch; + + while (gccontext->buffmapvac != NULL) { + bvbuffmap = gccontext->buffmapvac; + gccontext->buffmapvac = bvbuffmap->nextmap; + gcfree(bvbuffmap); } - while (gccontext.vac_buffmap != NULL) { - bufmap = gccontext.vac_buffmap; - gccontext.vac_buffmap = bufmap->nextmap; - gcfree(bufmap); + while (!list_empty(&gccontext->unmapvac)) { + head = gccontext->unmapvac.next; + gcschedunmap = list_entry(head, struct gcschedunmap, link); + list_del(head); + gcfree(gcschedunmap); } - while (gccontext.vac_buffers != NULL) { - buffer = gccontext.vac_buffers; - gccontext.vac_buffers = buffer->next; - gcfree(buffer); + while (!list_empty(&gccontext->buffervac)) { + head = gccontext->buffervac.next; + gcbuffer = list_entry(head, struct gcbuffer, link); + list_del(head); + gcfree(gcbuffer); } - while (gccontext.vac_fixups != NULL) { - fixup = gccontext.vac_fixups; - gccontext.vac_fixups = fixup->next; - gcfree(fixup); + while (!list_empty(&gccontext->fixupvac)) { + head = gccontext->fixupvac.next; + gcfixup = list_entry(head, struct gcfixup, link); + list_del(head); + gcfree(gcfixup); } - while (gccontext.vac_batches != NULL) { - batch = gccontext.vac_batches; - gccontext.vac_batches = batch->next; - gcfree(batch); + while (!list_empty(&gccontext->batchvac)) { + head = gccontext->batchvac.next; + gcbatch = list_entry(head, struct gcbatch, link); + list_del(head); + gcfree(gcbatch); } } @@ -3878,25 +565,25 @@ void bv_exit(void) * Library API. */ -enum bverror bv_map(struct bvbuffdesc *buffdesc) +enum bverror bv_map(struct bvbuffdesc *bvbuffdesc) { enum bverror bverror; struct bvbuffmap *bvbuffmap; - GCENTERARG(GCZONE_MAPPING, "buffdesc = 0x%08X\n", - (unsigned int) buffdesc); + GCENTERARG(GCZONE_MAPPING, "bvbuffdesc = 0x%08X\n", + (unsigned int) bvbuffdesc); - if (buffdesc == NULL) { + if (bvbuffdesc == NULL) { BVSETERROR(BVERR_BUFFERDESC, "bvbuffdesc is NULL"); goto exit; } - if (buffdesc->structsize < STRUCTSIZE(buffdesc, map)) { + if (bvbuffdesc->structsize < STRUCTSIZE(bvbuffdesc, map)) { BVSETERROR(BVERR_BUFFERDESC_VERS, "argument has invalid size"); goto exit; } - bverror = do_map(buffdesc, NULL, &bvbuffmap); + bverror = do_map(bvbuffdesc, NULL, &bvbuffmap); exit: GCEXITARG(GCZONE_MAPPING, "bv%s = %d\n", @@ -3904,33 +591,34 @@ exit: return bverror; } -enum bverror bv_unmap(struct bvbuffdesc *buffdesc) +enum bverror bv_unmap(struct bvbuffdesc *bvbuffdesc) { enum bverror bverror = BVERR_NONE; enum bverror otherbverror = BVERR_NONE; + struct gccontext *gccontext = get_context(); struct bvbuffmap *prev = NULL; struct bvbuffmap *bvbuffmap; struct bvbuffmapinfo *bvbuffmapinfo; struct gcmap gcmap; - GCENTERARG(GCZONE_MAPPING, "buffdesc = 0x%08X\n", - (unsigned int) buffdesc); + GCENTERARG(GCZONE_MAPPING, "bvbuffdesc = 0x%08X\n", + (unsigned int) bvbuffdesc); /* Lock access to the mapping list. */ - GCLOCK(&gccontext.maplock); + GCLOCK(&gccontext->maplock); - if (buffdesc == NULL) { + if (bvbuffdesc == NULL) { BVSETERROR(BVERR_BUFFERDESC, "bvbuffdesc is NULL"); goto exit; } - if (buffdesc->structsize < STRUCTSIZE(buffdesc, map)) { + if (bvbuffdesc->structsize < STRUCTSIZE(bvbuffdesc, map)) { BVSETERROR(BVERR_BUFFERDESC_VERS, "argument has invalid size"); goto exit; } /* Is the buffer mapped? */ - bvbuffmap = buffdesc->map; + bvbuffmap = bvbuffdesc->map; if (bvbuffmap == NULL) { GCDBG(GCZONE_MAPPING, "buffer isn't mapped.\n"); goto exit; @@ -3955,7 +643,7 @@ enum bverror bv_unmap(struct bvbuffdesc *buffdesc) "no mapping from our implementation.\n"); /* No, call other implementations. */ - bverror = buffdesc->map->bv_unmap(buffdesc); + bverror = bvbuffdesc->map->bv_unmap(bvbuffdesc); goto exit; } @@ -3968,16 +656,16 @@ enum bverror bv_unmap(struct bvbuffdesc *buffdesc) /* Remove our mapping. */ if (prev == NULL) - buffdesc->map = bvbuffmap->nextmap; + bvbuffdesc->map = bvbuffmap->nextmap; else prev->nextmap = bvbuffmap->nextmap; /* Call other implementation. */ - otherbverror = buffdesc->map->bv_unmap(buffdesc); + otherbverror = bvbuffdesc->map->bv_unmap(bvbuffdesc); /* Add our mapping back. */ - bvbuffmap->nextmap = buffdesc->map; - buffdesc->map = bvbuffmap; + bvbuffmap->nextmap = bvbuffdesc->map; + bvbuffdesc->map = bvbuffmap; prev = NULL; } else { GCDBG(GCZONE_MAPPING, @@ -4017,7 +705,7 @@ enum bverror bv_unmap(struct bvbuffdesc *buffdesc) /* Remove from the buffer descriptor list. */ if (prev == NULL) - buffdesc->map = bvbuffmap->nextmap; + bvbuffdesc->map = bvbuffmap->nextmap; else prev->nextmap = bvbuffmap->nextmap; @@ -4025,27 +713,28 @@ enum bverror bv_unmap(struct bvbuffdesc *buffdesc) bvbuffmap->structsize = 0; /* Add to the vacant list. */ - bvbuffmap->nextmap = gccontext.vac_buffmap; - gccontext.vac_buffmap = bvbuffmap; + bvbuffmap->nextmap = gccontext->buffmapvac; + gccontext->buffmapvac = bvbuffmap; exit: /* Unlock access to the mapping list. */ - GCUNLOCK(&gccontext.maplock); + GCUNLOCK(&gccontext->maplock); GCEXITARG(GCZONE_MAPPING, "bv%s = %d\n", (bverror == BVERR_NONE) ? "result" : "error", bverror); return bverror; } -enum bverror bv_blt(struct bvbltparams *bltparams) +enum bverror bv_blt(struct bvbltparams *bvbltparams) { enum bverror bverror = BVERR_NONE; + struct gccontext *gccontext = get_context(); struct gcalpha *gca = NULL; struct gcalpha _gca; unsigned int op, type, blend, format; unsigned int batchexec = 0; bool nop = false; - struct gcbatch *batch; + struct gcbatch *gcbatch; struct bvrect *dstrect; int src1used, src2used, maskused; struct srcinfo srcinfo[2]; @@ -4053,106 +742,106 @@ enum bverror bv_blt(struct bvbltparams *bltparams) struct gccommit gccommit; int i, srccount, res; - GCENTERARG(GCZONE_BLIT, "bltparams = 0x%08X\n", - (unsigned int) bltparams); + GCENTERARG(GCZONE_BLIT, "bvbltparams = 0x%08X\n", + (unsigned int) bvbltparams); /* Verify blt parameters structure. */ - if (bltparams == NULL) { + if (bvbltparams == NULL) { BVSETERROR(BVERR_BLTPARAMS_VERS, "bvbltparams is NULL"); goto exit; } - if (bltparams->structsize < STRUCTSIZE(bltparams, callbackdata)) { + if (bvbltparams->structsize < STRUCTSIZE(bvbltparams, callbackdata)) { BVSETERROR(BVERR_BLTPARAMS_VERS, "argument has invalid size"); goto exit; } /* Reset the error message. */ - bltparams->errdesc = NULL; + bvbltparams->errdesc = NULL; /* Verify the destination parameters structure. */ - GCDBG(GCZONE_SURF, "verifying destination parameters.\n"); + GCDBG(GCZONE_DEST, "verifying destination parameters.\n"); - res = verify_surface(0, (union bvinbuff *) &bltparams->dstdesc, - bltparams->dstgeom); + res = verify_surface(0, (union bvinbuff *) &bvbltparams->dstdesc, + bvbltparams->dstgeom); if (res != -1) { BVSETBLTSURFERROR(res, g_destsurferr); goto exit; } /* Extract the operation flags. */ - op = (bltparams->flags & BVFLAG_OP_MASK) >> BVFLAG_OP_SHIFT; - type = (bltparams->flags & BVFLAG_BATCH_MASK) >> BVFLAG_BATCH_SHIFT; + op = (bvbltparams->flags & BVFLAG_OP_MASK) >> BVFLAG_OP_SHIFT; + type = (bvbltparams->flags & BVFLAG_BATCH_MASK) >> BVFLAG_BATCH_SHIFT; switch (type) { case (BVFLAG_BATCH_NONE >> BVFLAG_BATCH_SHIFT): - bverror = allocate_batch(bltparams, &batch); + bverror = allocate_batch(bvbltparams, &gcbatch); if (bverror != BVERR_NONE) { - bltparams->errdesc = gccontext.bverrorstr; + bvbltparams->errdesc = gccontext->bverrorstr; goto exit; } batchexec = 1; - batch->batchflags = 0x7FFFFFFF; + gcbatch->batchflags = 0x7FFFFFFF; GCDBG(GCZONE_BATCH, "BVFLAG_BATCH_NONE(0x%08X)\n", - (unsigned int) batch); + (unsigned int) gcbatch); break; case (BVFLAG_BATCH_BEGIN >> BVFLAG_BATCH_SHIFT): - bverror = allocate_batch(bltparams, &batch); + bverror = allocate_batch(bvbltparams, &gcbatch); if (bverror != BVERR_NONE) { - bltparams->errdesc = gccontext.bverrorstr; + bvbltparams->errdesc = gccontext->bverrorstr; goto exit; } - bltparams->batch = (struct bvbatch *) batch; + bvbltparams->batch = (struct bvbatch *) gcbatch; batchexec = 0; - bltparams->batchflags = - batch->batchflags = 0x7FFFFFFF; + bvbltparams->batchflags = + gcbatch->batchflags = 0x7FFFFFFF; GCDBG(GCZONE_BATCH, "BVFLAG_BATCH_BEGIN(0x%08X)\n", - (unsigned int) batch); + (unsigned int) gcbatch); break; case (BVFLAG_BATCH_CONTINUE >> BVFLAG_BATCH_SHIFT): - batch = (struct gcbatch *) bltparams->batch; - if (batch == NULL) { + gcbatch = (struct gcbatch *) bvbltparams->batch; + if (gcbatch == NULL) { BVSETBLTERROR(BVERR_BATCH, "batch is not initialized"); goto exit; } - if (batch->structsize < STRUCTSIZE(batch, unmap)) { + if (gcbatch->structsize < STRUCTSIZE(gcbatch, unmap)) { BVSETBLTERROR(BVERR_BATCH, "invalid batch"); goto exit; } batchexec = 0; - batch->batchflags = bltparams->batchflags; + gcbatch->batchflags = bvbltparams->batchflags; GCDBG(GCZONE_BATCH, "BVFLAG_BATCH_CONTINUE(0x%08X)\n", - (unsigned int) batch); + (unsigned int) gcbatch); break; case (BVFLAG_BATCH_END >> BVFLAG_BATCH_SHIFT): - batch = (struct gcbatch *) bltparams->batch; - if (batch == NULL) { + gcbatch = (struct gcbatch *) bvbltparams->batch; + if (gcbatch == NULL) { BVSETBLTERROR(BVERR_BATCH, "batch is not initialized"); goto exit; } - if (batch->structsize < STRUCTSIZE(batch, unmap)) { + if (gcbatch->structsize < STRUCTSIZE(gcbatch, unmap)) { BVSETBLTERROR(BVERR_BATCH, "invalid batch"); goto exit; } batchexec = 1; - nop = (bltparams->batchflags & BVBATCH_ENDNOP) != 0; - batch->batchflags = bltparams->batchflags; + nop = (bvbltparams->batchflags & BVBATCH_ENDNOP) != 0; + gcbatch->batchflags = bvbltparams->batchflags; GCDBG(GCZONE_BATCH, "BVFLAG_BATCH_END(0x%08X)\n", - (unsigned int) batch); + (unsigned int) gcbatch); break; default: @@ -4161,23 +850,21 @@ enum bverror bv_blt(struct bvbltparams *bltparams) } GCDBG(GCZONE_BATCH, "batchflags=0x%08X\n", - (unsigned int) batch->batchflags); - - GCDUMPSCHEDULE(); + (unsigned int) gcbatch->batchflags); if (!nop) { /* Get a shortcut to the destination rectangle. */ - dstrect = &bltparams->dstrect; + dstrect = &bvbltparams->dstrect; /* Verify the batch change flags. */ - VERIFYBATCH(batch->batchflags >> 12, - &batch->prevdstrect, dstrect); + GCVERIFYBATCH(gcbatch->batchflags >> 12, + &gcbatch->prevdstrect, dstrect); switch (op) { case (BVFLAG_ROP >> BVFLAG_OP_SHIFT): GCDBG(GCZONE_BLIT, "BVFLAG_ROP\n"); - rop = bltparams->op.rop; + rop = bvbltparams->op.rop; src1used = ((rop & 0xCCCC) >> 2) ^ (rop & 0x3333); src2used = ((rop & 0xF0F0) >> 4) @@ -4189,11 +876,11 @@ enum bverror bv_blt(struct bvbltparams *bltparams) case (BVFLAG_BLEND >> BVFLAG_OP_SHIFT): GCDBG(GCZONE_BLIT, "BVFLAG_BLEND\n"); - blend = bltparams->op.blend; + blend = bvbltparams->op.blend; format = (blend & BVBLENDDEF_FORMAT_MASK) >> BVBLENDDEF_FORMAT_SHIFT; - bverror = parse_blend(bltparams, blend, &_gca); + bverror = parse_blend(bvbltparams, blend, &_gca); if (bverror != BVERR_NONE) goto exit; @@ -4226,7 +913,7 @@ enum bverror bv_blt(struct bvbltparams *bltparams) } /* Parse destination parameters. */ - bverror = parse_destination(bltparams, batch); + bverror = parse_destination(bvbltparams, gcbatch); if (bverror != BVERR_NONE) goto exit; @@ -4234,35 +921,35 @@ enum bverror bv_blt(struct bvbltparams *bltparams) /* Verify the src1 parameters structure. */ if (src1used) { - GCDBG(GCZONE_BLIT, "src1used\n"); - GCDBG(GCZONE_SURF, "verifying source1 parameters.\n"); + GCDBG(GCZONE_SRC, "src1used\n"); + GCDBG(GCZONE_SRC, "verifying source1 parameters.\n"); res = verify_surface( - bltparams->flags & BVBATCH_TILE_SRC1, - &bltparams->src1, bltparams->src1geom); + bvbltparams->flags & BVBATCH_TILE_SRC1, + &bvbltparams->src1, bvbltparams->src1geom); if (res != -1) { BVSETBLTSURFERROR(res, g_src1surferr); goto exit; } /* Verify the batch change flags. */ - VERIFYBATCH(batch->batchflags >> 14, - &batch->prevsrc1rect, - &bltparams->src1rect); + GCVERIFYBATCH(gcbatch->batchflags >> 14, + &gcbatch->prevsrc1rect, + &bvbltparams->src1rect); /* Same as the destination? */ - if (same_phys_area(bltparams->src1.desc, - &bltparams->src1rect, - bltparams->dstdesc, + if (same_phys_area(bvbltparams->src1.desc, + &bvbltparams->src1rect, + bvbltparams->dstdesc, dstrect)) { GCDBG(GCZONE_BLIT, "src1 is the same as dst\n"); } else { srcinfo[srccount].index = 0; - srcinfo[srccount].buf = bltparams->src1; - srcinfo[srccount].geom = bltparams->src1geom; - srcinfo[srccount].rect = &bltparams->src1rect; + srcinfo[srccount].buf = bvbltparams->src1; + srcinfo[srccount].geom = bvbltparams->src1geom; + srcinfo[srccount].rect = &bvbltparams->src1rect; - bverror = parse_source(bltparams, batch, + bverror = parse_source(bvbltparams, gcbatch, &srcinfo[srccount]); if (bverror != BVERR_NONE) goto exit; @@ -4273,35 +960,35 @@ enum bverror bv_blt(struct bvbltparams *bltparams) /* Verify the src2 parameters structure. */ if (src2used) { - GCDBG(GCZONE_BLIT, "src2used\n"); - GCDBG(GCZONE_SURF, "verifying source2 parameters.\n"); + GCDBG(GCZONE_SRC, "src2used\n"); + GCDBG(GCZONE_SRC, "verifying source2 parameters.\n"); res = verify_surface( - bltparams->flags & BVBATCH_TILE_SRC2, - &bltparams->src2, bltparams->src2geom); + bvbltparams->flags & BVBATCH_TILE_SRC2, + &bvbltparams->src2, bvbltparams->src2geom); if (res != -1) { BVSETBLTSURFERROR(res, g_src2surferr); goto exit; } /* Verify the batch change flags. */ - VERIFYBATCH(batch->batchflags >> 16, - &batch->prevsrc2rect, - &bltparams->src2rect); + GCVERIFYBATCH(gcbatch->batchflags >> 16, + &gcbatch->prevsrc2rect, + &bvbltparams->src2rect); /* Same as the destination? */ - if (same_phys_area(bltparams->src2.desc, - &bltparams->src2rect, - bltparams->dstdesc, + if (same_phys_area(bvbltparams->src2.desc, + &bvbltparams->src2rect, + bvbltparams->dstdesc, dstrect)) { GCDBG(GCZONE_BLIT, "src2 is the same as dst\n"); } else { srcinfo[srccount].index = 1; - srcinfo[srccount].buf = bltparams->src2; - srcinfo[srccount].geom = bltparams->src2geom; - srcinfo[srccount].rect = &bltparams->src2rect; + srcinfo[srccount].buf = bvbltparams->src2; + srcinfo[srccount].geom = bvbltparams->src2geom; + srcinfo[srccount].rect = &bvbltparams->src2rect; - bverror = parse_source(bltparams, batch, + bverror = parse_source(bvbltparams, gcbatch, &srcinfo[srccount]); if (bverror != BVERR_NONE) goto exit; @@ -4312,21 +999,21 @@ enum bverror bv_blt(struct bvbltparams *bltparams) /* Verify the mask parameters structure. */ if (maskused) { - GCDBG(GCZONE_BLIT, "maskused\n"); - GCDBG(GCZONE_SURF, "verifying mask parameters.\n"); + GCDBG(GCZONE_MASK, "maskused\n"); + GCDBG(GCZONE_MASK, "verifying mask parameters.\n"); res = verify_surface( - bltparams->flags & BVBATCH_TILE_MASK, - &bltparams->mask, bltparams->maskgeom); + bvbltparams->flags & BVBATCH_TILE_MASK, + &bvbltparams->mask, bvbltparams->maskgeom); if (res != -1) { BVSETBLTSURFERROR(res, g_masksurferr); goto exit; } /* Verify the batch change flags. */ - VERIFYBATCH(batch->batchflags >> 18, - &batch->prevmaskrect, - &bltparams->maskrect); + GCVERIFYBATCH(gcbatch->batchflags >> 18, + &gcbatch->prevmaskrect, + &bvbltparams->maskrect); BVSETBLTERROR(BVERR_OP, "operation with mask not supported"); @@ -4342,7 +1029,7 @@ enum bverror bv_blt(struct bvbltparams *bltparams) } else { for (i = 0; i < srccount; i += 1) { if (gca == NULL) { - srcinfo[i].rop = bltparams->op.rop; + srcinfo[i].rop = bvbltparams->op.rop; srcinfo[i].gca = NULL; } else if ((i + 1) != srccount) { srcinfo[i].rop = 0xCC; @@ -4362,14 +1049,15 @@ enum bverror bv_blt(struct bvbltparams *bltparams) if ((srcinfo[i].rect->width == 1) && (srcinfo[i].rect->height == 1) && - (bltparams->src1.desc->virtaddr)) - bverror = do_fill(bltparams, batch, + (bvbltparams->src1.desc->virtaddr)) + bverror = do_fill(bvbltparams, gcbatch, &srcinfo[i]); else if (EQ_SIZE(srcinfo[i].rect, dstrect)) - bverror = do_blit(bltparams, batch, + bverror = do_blit(bvbltparams, gcbatch, &srcinfo[i]); else - bverror = do_filter(bltparams, batch, + bverror = do_filter(bvbltparams, + gcbatch, &srcinfo[i]); if (bverror != BVERR_NONE) @@ -4384,13 +1072,13 @@ enum bverror bv_blt(struct bvbltparams *bltparams) GCDBG(GCZONE_BLIT, "preparing to submit the batch.\n"); /* Finalize the current operation. */ - bverror = batch->batchend(bltparams, batch); + bverror = gcbatch->batchend(bvbltparams, gcbatch); if (bverror != BVERR_NONE) goto exit; /* Add PE flush. */ GCDBG(GCZONE_BLIT, "appending the flush.\n"); - bverror = claim_buffer(bltparams, batch, + bverror = claim_buffer(bvbltparams, gcbatch, sizeof(struct gcmoflush), (void **) &flush); if (bverror != BVERR_NONE) @@ -4400,7 +1088,7 @@ enum bverror bv_blt(struct bvbltparams *bltparams) flush->flush.reg = gcregflush_pe2D; /* Process asynchronous operation. */ - if ((bltparams->flags & BVFLAG_ASYNC) == 0) { + if ((bvbltparams->flags & BVFLAG_ASYNC) == 0) { GCDBG(GCZONE_BLIT, "synchronous batch.\n"); gccommit.callback = NULL; gccommit.callbackparam = NULL; @@ -4409,9 +1097,9 @@ enum bverror bv_blt(struct bvbltparams *bltparams) struct gccallbackinfo *gccallbackinfo; GCDBG(GCZONE_BLIT, "asynchronous batch (0x%08X):\n", - bltparams->flags); + bvbltparams->flags); - if (bltparams->callbackfn == NULL) { + if (bvbltparams->callbackfn == NULL) { GCDBG(GCZONE_BLIT, "no callback given.\n"); gccommit.callback = NULL; gccommit.callbackparam = NULL; @@ -4425,9 +1113,9 @@ enum bverror bv_blt(struct bvbltparams *bltparams) } gccallbackinfo->callbackfn - = bltparams->callbackfn; + = bvbltparams->callbackfn; gccallbackinfo->callbackdata - = bltparams->callbackdata; + = bvbltparams->callbackdata; gccommit.callback = gccallback; gccommit.callbackparam = gccallbackinfo; @@ -4452,24 +1140,27 @@ enum bverror bv_blt(struct bvbltparams *bltparams) } /* Process scheduled unmappings. */ - unmap_implicit(batch); + do_unmap_implicit(gcbatch); INIT_LIST_HEAD(&gccommit.unmap); - list_splice_init(&batch->unmap, &gccommit.unmap); + list_splice_init(&gcbatch->unmap, &gccommit.unmap); /* Pass the batch for execution. */ - GCDUMPBATCH(batch); + GCDUMPBATCH(gcbatch); gccommit.gcerror = GCERR_NONE; gccommit.entrypipe = GCPIPE_2D; gccommit.exitpipe = GCPIPE_2D; - gccommit.buffer = batch->bufhead; + + INIT_LIST_HEAD(&gccommit.buffer); + list_splice_init(&gcbatch->buffer, &gccommit.buffer); GCDBG(GCZONE_BLIT, "submitting the batch.\n"); gc_commit_wrapper(&gccommit); - /* Move the list of mappings back to batch. */ - list_splice_init(&gccommit.unmap, &batch->unmap); + /* Move the lists back to the batch. */ + list_splice_init(&gccommit.buffer, &gcbatch->buffer); + list_splice_init(&gccommit.unmap, &gcbatch->unmap); /* Error? */ if (gccommit.gcerror != GCERR_NONE) { @@ -4492,10 +1183,9 @@ enum bverror bv_blt(struct bvbltparams *bltparams) } exit: - if ((batch != NULL) && batchexec) { - GCDUMPSCHEDULE(); - free_batch(batch); - bltparams->batch = NULL; + if ((gcbatch != NULL) && batchexec) { + free_batch(gcbatch); + bvbltparams->batch = NULL; } GCEXITARG(GCZONE_BLIT, "bv%s = %d\n", diff --git a/drivers/misc/gcx/gcbv/gcbv.h b/drivers/misc/gcx/gcbv/gcbv.h new file mode 100644 index 0000000..789d710 --- /dev/null +++ b/drivers/misc/gcx/gcbv/gcbv.h @@ -0,0 +1,459 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2012 Vivante Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * BSD LICENSE + * + * Copyright(c) 2012 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. + */ + +#ifndef GCBV_H +#define GCBV_H + +#include "gcmain.h" + +/******************************************************************************* + * Miscellaneous defines and macros. + */ + +#if !defined(BVBATCH_DESTRECT) +#define BVBATCH_DESTRECT (BVBATCH_DSTRECT_ORIGIN | BVBATCH_DSTRECT_SIZE) +#endif + +#if !defined(BVBATCH_SRC1RECT) +#define BVBATCH_SRC1RECT (BVBATCH_SRC1RECT_ORIGIN | BVBATCH_SRC1RECT_SIZE) +#endif + +#if !defined(BVBATCH_SRC2RECT) +#define BVBATCH_SRC2RECT (BVBATCH_SRC2RECT_ORIGIN | BVBATCH_SRC2RECT_SIZE) +#endif + +#define EQ_SIZE(rect1, rect2) \ +( \ + (rect1->width == rect2->width) && (rect1->height == rect2->height) \ +) + +#define STRUCTSIZE(structptr, lastmember) \ +( \ + (size_t) &structptr->lastmember + \ + sizeof(structptr->lastmember) - \ + (size_t) structptr \ +) + +#define GET_MAP_HANDLE(map) \ +( \ + ((struct bvbuffmapinfo *) map->handle)->handle \ +) + +#define GC_CLIP_RESET_LEFT ((unsigned short) 0) +#define GC_CLIP_RESET_TOP ((unsigned short) 0) +#define GC_CLIP_RESET_RIGHT ((unsigned short) ((1 << 15) - 1)) +#define GC_CLIP_RESET_BOTTOM ((unsigned short) ((1 << 15) - 1)) + +#define BVSETERROR(error, message, ...) \ +do { \ + struct gccontext *tmpcontext = get_context(); \ + snprintf(tmpcontext->bverrorstr, sizeof(tmpcontext->bverrorstr), \ + message, ##__VA_ARGS__); \ + GCDUMPSTRING("%s(%d): [ERROR] %s\n", __func__, __LINE__, \ + tmpcontext->bverrorstr); \ + bverror = error; \ +} while (0) + +#define BVSETBLTERROR(error, message, ...) \ +do { \ + struct gccontext *tmpcontext = get_context(); \ + snprintf(tmpcontext->bverrorstr, sizeof(tmpcontext->bverrorstr), \ + message, ##__VA_ARGS__); \ + GCDUMPSTRING("%s(%d): [ERROR] %s\n", __func__, __LINE__, \ + tmpcontext->bverrorstr); \ + bvbltparams->errdesc = tmpcontext->bverrorstr; \ + bverror = error; \ +} while (0) + + +/******************************************************************************* + * Global data structure. + */ + +struct gccontext { + /* Last generated error message. */ + char bverrorstr[128]; + + /* Dynamically allocated structure cache. */ + struct bvbuffmap *buffmapvac; /* bvbuffmap */ + struct list_head unmapvac; /* gcschedunmap */ + struct list_head buffervac; /* gcbuffer */ + struct list_head fixupvac; /* gcfixup */ + struct list_head batchvac; /* gcbatch */ + + /* Callback lists. */ + struct list_head callbacklist; /* gccallbackinfo */ + struct list_head callbackvac; /* gccallbackinfo */ + + /* Access locks. */ + GCLOCK_TYPE batchlock; + GCLOCK_TYPE bufferlock; + GCLOCK_TYPE fixuplock; + GCLOCK_TYPE maplock; + GCLOCK_TYPE callbacklock; +}; + + +/******************************************************************************* + * Mapping structures. + */ + +/* bvbuffmap struct attachment. */ +struct bvbuffmapinfo { + /* Mapped handle for the buffer. */ + unsigned long handle; + + /* Number of times the client explicitly mapped this buffer. */ + int usermap; + + /* Number of times implicit mapping happened. */ + int automap; +}; + + +/******************************************************************************* + * Color format. + */ + +enum bvformattype { + BVFMT_RGB, + BVFMT_YUV +}; + +struct bvcomponent { + unsigned int shift; + unsigned int size; + unsigned int mask; +}; + +struct bvcsrgb { + struct bvcomponent r; + struct bvcomponent g; + struct bvcomponent b; + struct bvcomponent a; +}; + +struct bvformatxlate { + enum bvformattype type; + unsigned bitspp; + unsigned format; + unsigned swizzle; + struct bvcsrgb rgba; +}; + + +/******************************************************************************* + * Alpha blending. + */ + +/* Alpha blending hardware configuration. */ +struct gcblendconfig { + unsigned char factor_mode; + unsigned char color_reverse; + + bool src1used; + bool src2used; +}; + +/* Alpha blending descriptor. */ +struct gcalpha { + unsigned int src_global_color; + unsigned int dst_global_color; + + unsigned char src_global_alpha_mode; + unsigned char dst_global_alpha_mode; + + struct gcblendconfig *k1; + struct gcblendconfig *k2; + + struct gcblendconfig *srcconfig; + struct gcblendconfig *dstconfig; + + bool src1used; + bool src2used; +}; + + +/******************************************************************************* + * Rotation and mirror defines. + */ + +#define GCREG_ROT_ANGLE_ROT0 0x0 +#define GCREG_ROT_ANGLE_ROT90 0x4 +#define GCREG_ROT_ANGLE_ROT180 0x5 +#define GCREG_ROT_ANGLE_ROT270 0x6 + +#define ROT_ANGLE_INVALID -1 +#define ROT_ANGLE_0 0 +#define ROT_ANGLE_90 1 +#define ROT_ANGLE_180 2 +#define ROT_ANGLE_270 3 + +#define GCREG_MIRROR_NONE 0x0 +#define GCREG_MIRROR_X 0x1 +#define GCREG_MIRROR_Y 0x2 +#define GCREG_MIRROR_XY 0x3 + +extern const unsigned int rotencoding[]; + + +/******************************************************************************* + * Batch structures. + */ + +/* Operation finalization call. */ +struct gcbatch; +typedef enum bverror (*gcbatchend) (struct bvbltparams *bvbltparams, + struct gcbatch *gcbatch); + +/* Blit states. */ +struct gcblit { + unsigned int srccount; + unsigned int multisrc; + unsigned short rop; +}; + +/* Batch header. */ +struct gcbatch { + /* Used to ID structure version. */ + unsigned int structsize; + + /* Batch change flags. */ + unsigned long batchflags; + + /* Pointer to the function to finalize the current operation. */ + gcbatchend batchend; + + /* State of the current operation. */ + struct gcblit gcblit; + + /* Destination format. */ + struct bvformatxlate *dstformat; + + /* Clipping deltas; used to correct the source coordinates for + * single source blits. */ + int deltaleft; + int deltatop; + int deltaright; + int deltabottom; + + /* Clipped destination rectangle coordinates. */ + unsigned short clippedleft; + unsigned short clippedtop; + unsigned short clippedright; + unsigned short clippedbottom; + + /* Destination base address alignment in pixels. */ + int dstalign; + + /* Destination origin offset. */ + unsigned int dstoffsetX; + unsigned int dstoffsetY; + + /* Rotation angle. */ + int dstangle; + + /* Geometry size of the destination surface. */ + unsigned int dstwidth; + unsigned int dstheight; + + /* Physical size of the destination surface. */ + unsigned int dstphyswidth; + unsigned int dstphysheight; + + /* Computed destination rectangle coordinates; in multi-source + * setup can be modified to match new destination and source + * geometry. */ + unsigned short left; + unsigned short top; + unsigned short right; + unsigned short bottom; + + /* Physical size of the matched destination and source surfaces + * for multi-source setup. */ + unsigned int physwidth; + unsigned int physheight; + + /* Alignment byte offset for the destination surface; in multi- + * source setup can be modified to match new destination and source + * geometry. */ + int dstbyteshift; + + /* Block walker enable. */ + int blockenable; + +#if GCDEBUG_ENABLE + /* Rectangle validation storage. */ + struct bvrect prevdstrect; + struct bvrect prevsrc1rect; + struct bvrect prevsrc2rect; + struct bvrect prevmaskrect; +#endif + + /* Total size of the command buffer. */ + unsigned int size; + + /* Command buffer list (gcbuffer). */ + struct list_head buffer; + + /* Scheduled implicit unmappings (gcschedunmap). */ + struct list_head unmap; + + /* Batch linked list (gcbatch). */ + struct list_head link; +}; + + +/******************************************************************************* + * srcinfo is used by blitters to define an array of valid sources. + */ + +struct srcinfo { + /* BLTsville source index (0 for src1 and 1 for src2). */ + int index; + + /* Source surface buffer descriptor. */ + union bvinbuff buf; + + /* Source surface geometry. */ + struct bvsurfgeom *geom; + + /* Source rectangle. */ + struct bvrect *rect; + + /* Source surface format. */ + struct bvformatxlate *format; + + /* Source rotation angle. */ + int angle; + unsigned int rot; + + /* Mirror setting. */ + unsigned int mirror; + + /* ROP. */ + unsigned short rop; + + /* Blending info. */ + struct gcalpha *gca; +}; + + +/******************************************************************************* + * Internal API entries. + */ + +/* Get the pointer to the context. */ +struct gccontext *get_context(void); + +/* Parsers. */ +enum bverror parse_format(struct bvbltparams *bvbltparams, + enum ocdformat ocdformat, + struct bvformatxlate **format); +enum bverror parse_blend(struct bvbltparams *bvbltparams, + enum bvblend blend, + struct gcalpha *gca); +enum bverror parse_destination(struct bvbltparams *bvbltparams, + struct gcbatch *gcbatch); +enum bverror parse_source(struct bvbltparams *bvbltparams, + struct gcbatch *gcbatch, + struct srcinfo *srcinfo); + +/* Return surface alignment offset. */ +int get_pixel_offset(struct bvbuffdesc *bvbuffdesc, + struct bvformatxlate *format, + int offset); + +/* Buffer mapping. */ +enum bverror do_map(struct bvbuffdesc *bvbuffdesc, + struct gcbatch *gcbatch, + struct bvbuffmap **map); +void do_unmap_implicit(struct gcbatch *gcbatch); + +/* Batch/command buffer management. */ +enum bverror do_end(struct bvbltparams *bvbltparams, + struct gcbatch *gcbatch); +enum bverror allocate_batch(struct bvbltparams *bvbltparams, + struct gcbatch **gcbatch); +void free_batch(struct gcbatch *gcbatch); +enum bverror append_buffer(struct bvbltparams *bvbltparams, + struct gcbatch *gcbatch, + struct gcbuffer **gcbuffer); + +enum bverror add_fixup(struct bvbltparams *bvbltparams, + struct gcbatch *gcbatch, + unsigned int *fixup, + unsigned int surfoffset); +enum bverror claim_buffer(struct bvbltparams *bvbltparams, + struct gcbatch *gcbatch, + unsigned int size, + void **buffer); + +/* Program the destination. */ +enum bverror set_dst(struct bvbltparams *bltparams, + struct gcbatch *batch, + struct bvbuffmap *dstmap); + +/* Rendering entry points. */ +enum bverror do_fill(struct bvbltparams *bltparams, + struct gcbatch *gcbatch, + struct srcinfo *srcinfo); +enum bverror do_blit(struct bvbltparams *bltparams, + struct gcbatch *gcbatch, + struct srcinfo *srcinfo); +enum bverror do_filter(struct bvbltparams *bvbltparams, + struct gcbatch *gcbatch, + struct srcinfo *srcinfo); + +#endif diff --git a/drivers/misc/gcx/gcbv/gcfill.c b/drivers/misc/gcx/gcbv/gcfill.c new file mode 100644 index 0000000..475467d --- /dev/null +++ b/drivers/misc/gcx/gcbv/gcfill.c @@ -0,0 +1,272 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2012 Vivante Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * BSD LICENSE + * + * Copyright(c) 2012 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_COLOR (1 << 0) +#define GCZONE_FILL (1 << 1) + +GCDBG_FILTERDEF(gcfill, GCZONE_NONE, + "color", + "fill") + + +static inline unsigned int extract_component(unsigned int pixel, + struct bvcomponent *desc) +{ + unsigned int component; + unsigned int component8; + + component = (pixel & desc->mask) >> desc->shift; + GCDBG(GCZONE_COLOR, "mask=0x%08X, shift=%d, component=0x%08X\n", + desc->mask, desc->shift, component); + + switch (desc->size) { + case 0: + component8 = 0xFF; + GCDBG(GCZONE_COLOR, "component8=0x%08X\n", component8); + break; + + case 1: + component8 = component ? 0xFF : 0x00; + GCDBG(GCZONE_COLOR, "component8=0x%08X\n", component8); + break; + + case 4: + component8 = component | (component << 4); + GCDBG(GCZONE_COLOR, "component8=0x%08X\n", component8); + break; + + case 5: + component8 = (component << 3) | (component >> 2); + GCDBG(GCZONE_COLOR, "component8=0x%08X\n", component8); + break; + + case 6: + component8 = (component << 2) | (component >> 4); + GCDBG(GCZONE_COLOR, "component8=0x%08X\n", component8); + break; + + default: + component8 = component; + GCDBG(GCZONE_COLOR, "component8=0x%08X\n", component8); + } + + return component8; +} + +static unsigned int getinternalcolor(void *ptr, struct bvformatxlate *format) +{ + unsigned int srcpixel, dstpixel; + unsigned int r, g, b, a; + + switch (format->bitspp) { + case 16: + srcpixel = *(unsigned short *) ptr; + GCDBG(GCZONE_COLOR, "srcpixel=0x%08X\n", srcpixel); + break; + + case 32: + srcpixel = *(unsigned int *) ptr; + GCDBG(GCZONE_COLOR, "srcpixel=0x%08X\n", srcpixel); + break; + + default: + srcpixel = 0; + GCDBG(GCZONE_COLOR, "srcpixel=0x%08X\n", srcpixel); + } + + r = extract_component(srcpixel, &format->rgba.r); + g = extract_component(srcpixel, &format->rgba.g); + b = extract_component(srcpixel, &format->rgba.b); + a = extract_component(srcpixel, &format->rgba.a); + + GCDBG(GCZONE_COLOR, "(r,g,b,a)=0x%02X,0x%02X,0x%02X,0x%02X\n", + r, g, b, a); + + dstpixel = (a << 24) | (r << 16) | (g << 8) | b; + + GCDBG(GCZONE_COLOR, "dstpixel=0x%08X\n", dstpixel); + + return dstpixel; +} + +enum bverror do_fill(struct bvbltparams *bltparams, + struct gcbatch *batch, + struct srcinfo *srcinfo) +{ + enum bverror bverror; + struct gccontext *gccontext = get_context(); + int dstbyteshift; + struct gcmofill *gcmofill; + unsigned char *fillcolorptr; + struct bvbuffmap *dstmap = NULL; + + GCENTER(GCZONE_FILL); + + /* Finish previous batch if any. */ + bverror = batch->batchend(bltparams, batch); + if (bverror != BVERR_NONE) + goto exit; + + /* Compute the surface offset in bytes. */ + dstbyteshift = batch->dstalign * (int) batch->dstformat->bitspp / 8; + + /* Verify if the destination parameter have been modified. */ + if ((batch->dstbyteshift != dstbyteshift) || + (batch->physwidth != batch->dstphyswidth) || + (batch->physheight != batch->dstphysheight)) { + /* Set new values. */ + batch->dstbyteshift = dstbyteshift; + batch->physwidth = batch->dstphyswidth; + batch->physheight = batch->dstphysheight; + + /* Mark as modified. */ + batch->batchflags |= BVBATCH_DST; + } + + /* Map the destination. */ + bverror = do_map(bltparams->dstdesc, batch, &dstmap); + if (bverror != BVERR_NONE) { + bltparams->errdesc = gccontext->bverrorstr; + goto exit; + } + + /* Set the new destination. */ + bverror = set_dst(bltparams, batch, dstmap); + if (bverror != BVERR_NONE) + goto exit; + + /* Reset the modified flag. */ + batch->batchflags &= ~(BVBATCH_DST | + BVBATCH_CLIPRECT | + BVBATCH_DESTRECT); + + /*********************************************************************** + ** Allocate command buffer. + */ + + bverror = claim_buffer(bltparams, batch, + sizeof(struct gcmofill), + (void **) &gcmofill); + if (bverror != BVERR_NONE) + goto exit; + + /*********************************************************************** + ** Set dummy source. + */ + + /* Set surface dummy width and height. */ + gcmofill->src.rotation_ldst = gcmofillsrc_rotation_ldst; + gcmofill->src.rotation.raw = 0; + gcmofill->src.rotation.reg.surf_width = 1; + gcmofill->src.config.raw = 0; + + gcmofill->src.rotationheight_ldst = gcmofillsrc_rotationheight_ldst; + gcmofill->src.rotationheight.reg.height = 1; + gcmofill->src.rotationangle.raw = 0; + gcmofill->src.rotationangle.reg.dst = GCREG_ROT_ANGLE_ROT0; + gcmofill->src.rotationangle.reg.dst_mirror = GCREG_MIRROR_NONE; + + /* Disable alpha blending. */ + gcmofill->src.alphacontrol_ldst = gcmofillsrc_alphacontrol_ldst; + gcmofill->src.alphacontrol.raw = 0; + gcmofill->src.alphacontrol.reg.enable = GCREG_ALPHA_CONTROL_ENABLE_OFF; + + /*********************************************************************** + ** Set fill color. + */ + + fillcolorptr + = (unsigned char *) srcinfo->buf.desc->virtaddr + + srcinfo->rect->top * srcinfo->geom->virtstride + + srcinfo->rect->left * srcinfo->format->bitspp / 8; + + gcmofill->clearcolor_ldst = gcmofill_clearcolor_ldst; + gcmofill->clearcolor.raw = getinternalcolor(fillcolorptr, + srcinfo->format); + + /*********************************************************************** + ** Configure and start fill. + */ + + /* Set destination configuration. */ + gcmofill->dstconfig_ldst = gcmofill_dstconfig_ldst; + gcmofill->dstconfig.raw = 0; + gcmofill->dstconfig.reg.swizzle = batch->dstformat->swizzle; + gcmofill->dstconfig.reg.format = batch->dstformat->format; + gcmofill->dstconfig.reg.command = GCREG_DEST_CONFIG_COMMAND_CLEAR; + + /* Set ROP3. */ + gcmofill->rop_ldst = gcmofill_rop_ldst; + gcmofill->rop.raw = 0; + gcmofill->rop.reg.type = GCREG_ROP_TYPE_ROP3; + gcmofill->rop.reg.fg = (unsigned char) bltparams->op.rop; + + /* Set START_DE command. */ + gcmofill->startde.cmd.fld = gcfldstartde; + + /* Set destination rectangle. */ + gcmofill->rect.left = batch->clippedleft + batch->dstoffsetX; + gcmofill->rect.top = batch->clippedtop + batch->dstoffsetY; + gcmofill->rect.right = batch->clippedright + batch->dstoffsetX; + gcmofill->rect.bottom = batch->clippedbottom + batch->dstoffsetY; + +exit: + GCEXITARG(GCZONE_FILL, "bv%s = %d\n", + (bverror == BVERR_NONE) ? "result" : "error", bverror); + return bverror; +} diff --git a/drivers/misc/gcx/gcbv/gcfilter.c b/drivers/misc/gcx/gcbv/gcfilter.c new file mode 100644 index 0000000..aa1c11e --- /dev/null +++ b/drivers/misc/gcx/gcbv/gcfilter.c @@ -0,0 +1,128 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2012 Vivante Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * BSD LICENSE + * + * Copyright(c) 2012 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_FILTER (1 << 11) + +GCDBG_FILTERDEF(gcfilter, GCZONE_NONE, + "filter") + +enum bverror do_filter(struct bvbltparams *bltparams, + struct gcbatch *batch, + struct srcinfo *srcinfo) +{ +/* enum bverror bverror = BVERR_NONE;*/ + int verpass; + + GCENTER(GCZONE_FILTER); + + GCDBG(GCZONE_FILTER, "source rectangle:\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); + GCDBG(GCZONE_FILTER, " rect = (%d,%d)-(%d,%d), %dx%d\n", + srcinfo->rect->left, srcinfo->rect->top, + srcinfo->rect->left + srcinfo->rect->width, + srcinfo->rect->top + srcinfo->rect->height, + srcinfo->rect->width, srcinfo->rect->height); + + GCDBG(GCZONE_FILTER, "destination rectangle:\n"); + GCDBG(GCZONE_FILTER, " stride = %d, geom size = %dx%d\n", + bltparams->dstgeom->virtstride, + bltparams->dstgeom->width, bltparams->dstgeom->height); + GCDBG(GCZONE_FILTER, " rotaton = %d\n", + batch->dstangle); + GCDBG(GCZONE_FILTER, " rect = (%d,%d)-(%d,%d), %dx%d\n", + bltparams->dstrect.left, bltparams->dstrect.top, + bltparams->dstrect.left + bltparams->dstrect.width, + bltparams->dstrect.top + bltparams->dstrect.height, + bltparams->dstrect.width, bltparams->dstrect.height); + + /*********************************************************************** + * Update kernel arrays. + */ + + /* Do we need the vertical pass? */ + verpass = (srcinfo->rect->height != bltparams->dstrect.height); + +#if 0 + /* Recompute the table if necessary. */ + gcmONERROR(_CalculateSyncTable( + hardware, + State->newHorKernelSize, + srcRectSize.x, + destRectSize.x, + horKernel + )); + + gcmONERROR(_CalculateSyncTable( + hardware, + State->newVerKernelSize, + srcRectSize.y, + destRectSize.y, + verKernel + )); +#endif + + GCEXITARG(GCZONE_FILTER, "bv%s = %d\n", + (bverror == BVERR_NONE) ? "result" : "error", bverror); + + /* Not implemented yet */ + return BVERR_OP; +} diff --git a/drivers/misc/gcx/gcbv/gcmap.c b/drivers/misc/gcx/gcbv/gcmap.c new file mode 100644 index 0000000..eac76f8 --- /dev/null +++ b/drivers/misc/gcx/gcbv/gcmap.c @@ -0,0 +1,364 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2012 Vivante Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * BSD LICENSE + * + * Copyright(c) 2012 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_MAPPING (1 << 0) + +GCDBG_FILTERDEF(gcmap, GCZONE_NONE, + "mapping") + + +/******************************************************************************* + * Memory management. + */ + +enum bverror do_map(struct bvbuffdesc *bvbuffdesc, + struct gcbatch *batch, + struct bvbuffmap **map) +{ + static const int mapsize + = sizeof(struct bvbuffmap) + + sizeof(struct bvbuffmapinfo); + + enum bverror bverror; + struct gccontext *gccontext = get_context(); + struct bvbuffmap *bvbuffmap; + struct bvbuffmapinfo *bvbuffmapinfo; + struct bvphysdesc *bvphysdesc; + bool mappedbyothers; + struct gcmap gcmap; + struct gcschedunmap *gcschedunmap; + + GCENTERARG(GCZONE_MAPPING, "bvbuffdesc = 0x%08X\n", + (unsigned int) bvbuffdesc); + + /* Lock access to the mapping list. */ + GCLOCK(&gccontext->maplock); + + /* Try to find existing mapping. */ + bvbuffmap = bvbuffdesc->map; + while (bvbuffmap != NULL) { + if (bvbuffmap->bv_unmap == bv_unmap) + break; + bvbuffmap = bvbuffmap->nextmap; + } + + /* Not mapped yet? */ + if (bvbuffmap == NULL) { + /* New mapping, allocate a record. */ + if (gccontext->buffmapvac == NULL) { + bvbuffmap = gcalloc(struct bvbuffmap, mapsize); + if (bvbuffmap == NULL) { + BVSETERROR(BVERR_OOM, + "failed to allocate mapping record"); + goto fail; + } + + bvbuffmap->structsize = sizeof(struct bvbuffmap); + bvbuffmap->bv_unmap = bv_unmap; + bvbuffmap->handle = (unsigned long) (bvbuffmap + 1); + } else { + bvbuffmap = gccontext->buffmapvac; + gccontext->buffmapvac = bvbuffmap->nextmap; + } + + /* Setup buffer mapping. Here we need to check and make sure + * that the buffer starts at a location that is supported by + * the hw. If it is not, offset is computed and the buffer is + * extended by the value of the offset. */ + gcmap.gcerror = GCERR_NONE; + gcmap.handle = 0; + + if (bvbuffdesc->auxtype == BVAT_PHYSDESC) { + bvphysdesc = (struct bvphysdesc *) bvbuffdesc->auxptr; + + if (bvphysdesc->structsize < + STRUCTSIZE(bvphysdesc, pageoffset)) { + BVSETERROR(BVERR_BUFFERDESC_VERS, + "unsupported bvphysdesc version"); + goto fail; + } + + gcmap.buf.offset = bvphysdesc->pageoffset; + gcmap.pagesize = bvphysdesc->pagesize; + gcmap.pagearray = bvphysdesc->pagearray; + gcmap.size = bvbuffdesc->length; + + GCDBG(GCZONE_MAPPING, "new mapping (%s):\n", + (batch == NULL) ? "explicit" : "implicit"); + GCDBG(GCZONE_MAPPING, "pagesize = %lu\n", + bvphysdesc->pagesize); + GCDBG(GCZONE_MAPPING, "pagearray = 0x%08X\n", + (unsigned int) bvphysdesc->pagearray); + GCDBG(GCZONE_MAPPING, "pageoffset = %lu\n", + bvphysdesc->pageoffset); + GCDBG(GCZONE_MAPPING, "mapping size = %d\n", + gcmap.size); + } else { + gcmap.buf.logical = bvbuffdesc->virtaddr; + gcmap.pagesize = 0; + gcmap.pagearray = NULL; + gcmap.size = bvbuffdesc->length; + + GCDBG(GCZONE_MAPPING, "new mapping (%s):\n", + (batch == NULL) ? "explicit" : "implicit"); + GCDBG(GCZONE_MAPPING, "specified virtaddr = 0x%08X\n", + (unsigned int) bvbuffdesc->virtaddr); + GCDBG(GCZONE_MAPPING, "aligned virtaddr = 0x%08X\n", + (unsigned int) gcmap.buf.logical); + GCDBG(GCZONE_MAPPING, "mapping size = %d\n", + gcmap.size); + } + + gc_map_wrapper(&gcmap); + if (gcmap.gcerror != GCERR_NONE) { + BVSETERROR(BVERR_OOM, + "unable to allocate gccore memory"); + goto fail; + } + + /* Set map handle. */ + bvbuffmapinfo = (struct bvbuffmapinfo *) bvbuffmap->handle; + bvbuffmapinfo->handle = gcmap.handle; + + /* Initialize reference counters. */ + if (batch == NULL) { + /* Explicit mapping. */ + bvbuffmapinfo->usermap = 1; + bvbuffmapinfo->automap = 0; + } else { + /* Implicit mapping; if there are existing mappings + * from other implementations, mark this an explicit + * mapping as well. */ + mappedbyothers = (bvbuffdesc->map != NULL); + GCDBG(GCZONE_MAPPING, "%smapped by others.\n", + mappedbyothers ? "" : "not "); + + bvbuffmapinfo->usermap = mappedbyothers ? 1 : 0; + bvbuffmapinfo->automap = 1; + } + + /* Add the record to the list of mappings. */ + bvbuffmap->nextmap = bvbuffdesc->map; + bvbuffdesc->map = bvbuffmap; + } else { + /* Mapping already exists. */ + bvbuffmapinfo = (struct bvbuffmapinfo *) bvbuffmap->handle; + + /* Advance reference counters. */ + if (batch == NULL) { + /* Explicit mapping. */ + GCDBG(GCZONE_MAPPING, "explicit map.\n"); + bvbuffmapinfo->usermap += 1; + } else { + /* Implicit mapping. */ + GCDBG(GCZONE_MAPPING, "implicit map.\n"); + bvbuffmapinfo->automap += 1; + } + + GCDBG(GCZONE_MAPPING, "mapping exists.\n"); + } + + GCDBG(GCZONE_MAPPING, "bvbuffmap = 0x%08X\n", + (unsigned int) bvbuffmap); + GCDBG(GCZONE_MAPPING, "explicit count = %d\n", + bvbuffmapinfo->usermap); + GCDBG(GCZONE_MAPPING, "implicit count = %d\n", + bvbuffmapinfo->automap); + + /* Schedule for unmapping. */ + if (batch != NULL) { + if (list_empty(&gccontext->unmapvac)) { + gcschedunmap = gcalloc(struct gcschedunmap, + sizeof(struct gcschedunmap)); + if (gcschedunmap == NULL) { + BVSETERROR(BVERR_OOM, + "failed to schedule unmapping"); + goto fail; + } + list_add(&gcschedunmap->link, &batch->unmap); + } else { + struct list_head *head; + head = gccontext->unmapvac.next; + gcschedunmap = list_entry(head, + struct gcschedunmap, + link); + list_move(&gcschedunmap->link, &batch->unmap); + } + + gcschedunmap->handle = (unsigned long) bvbuffdesc; + + GCDBG(GCZONE_MAPPING, "scheduled for unmapping.\n"); + } + + /* Set the map pointer. */ + *map = bvbuffmap; + + /* Unlock access to the mapping list. */ + GCUNLOCK(&gccontext->maplock); + + GCEXITARG(GCZONE_MAPPING, "handle = 0x%08X\n", + bvbuffmapinfo->handle); + return BVERR_NONE; + +fail: + if (bvbuffmap != NULL) { + bvbuffmap->nextmap = gccontext->buffmapvac; + gccontext->buffmapvac = bvbuffmap; + } + + /* Unlock access to the mapping list. */ + GCUNLOCK(&gccontext->maplock); + + GCEXITARG(GCZONE_MAPPING, "bverror = %d\n", bverror); + return bverror; +} + +void do_unmap_implicit(struct gcbatch *batch) +{ + struct gccontext *gccontext = get_context(); + struct list_head *head, *temphead; + struct gcschedunmap *gcschedunmap; + struct bvbuffdesc *bvbuffdesc; + struct bvbuffmap *prev, *bvbuffmap; + struct bvbuffmapinfo *bvbuffmapinfo; + + GCENTER(GCZONE_MAPPING); + + /* Lock access to the mapping list. */ + GCLOCK(&gccontext->maplock); + + /* Scan scheduled unmappings and remove the ones that are still + * in use. */ + list_for_each_safe(head, temphead, &batch->unmap) { + gcschedunmap = list_entry(head, struct gcschedunmap, link); + + /* Cast the handle. */ + bvbuffdesc = (struct bvbuffdesc *) gcschedunmap->handle; + + /* Find our mapping. */ + prev = NULL; + bvbuffmap = bvbuffdesc->map; + while (bvbuffmap != NULL) { + if (bvbuffmap->bv_unmap == bv_unmap) + break; + prev = bvbuffmap; + bvbuffmap = bvbuffmap->nextmap; + } + + /* Not found? */ + if (bvbuffmap == NULL) { + GCERR("mapping not found for bvbuffdesc 0x%08X.\n", + (unsigned int) bvbuffdesc); + + /* Remove scheduled unmapping. */ + list_move(head, &gccontext->unmapvac); + continue; + } + + /* Get the info structure. */ + bvbuffmapinfo = (struct bvbuffmapinfo *) bvbuffmap->handle; + + GCDBG(GCZONE_MAPPING, "head = 0x%08X\n", + (unsigned int) gcschedunmap); + GCDBG(GCZONE_MAPPING, " bvbuffmap = 0x%08X\n", + (unsigned int) bvbuffmap); + GCDBG(GCZONE_MAPPING, " handle = 0x%08X\n", + bvbuffmapinfo->handle); + + /* Implicit unmapping. */ + bvbuffmapinfo->automap -= 1; + if (bvbuffmapinfo->automap < 0) { + GCERR("implicit count negative.\n"); + bvbuffmapinfo->automap = 0; + } + + GCDBG(GCZONE_MAPPING, " explicit count = %d\n", + bvbuffmapinfo->usermap); + GCDBG(GCZONE_MAPPING, " implicit count = %d\n", + bvbuffmapinfo->automap); + + /* Still referenced? */ + if (bvbuffmapinfo->usermap || bvbuffmapinfo->automap) { + GCDBG(GCZONE_MAPPING, " still referenced.\n"); + + /* Remove scheduled unmapping. */ + list_move(head, &gccontext->unmapvac); + continue; + } + + GCDBG(GCZONE_MAPPING, " ready for unmapping.\n"); + + /* Set the handle. */ + gcschedunmap->handle = bvbuffmapinfo->handle; + + /* Remove from the buffer descriptor. */ + if (prev == NULL) + bvbuffdesc->map = bvbuffmap->nextmap; + else + prev->nextmap = bvbuffmap->nextmap; + + /* Add to the vacant list. */ + bvbuffmap->nextmap = gccontext->buffmapvac; + gccontext->buffmapvac = bvbuffmap; + } + + /* Unlock access to the mapping list. */ + GCUNLOCK(&gccontext->maplock); + + GCEXIT(GCZONE_MAPPING); +} diff --git a/drivers/misc/gcx/gcbv/gcparser.c b/drivers/misc/gcx/gcbv/gcparser.c new file mode 100644 index 0000000..654fc76 --- /dev/null +++ b/drivers/misc/gcx/gcbv/gcparser.c @@ -0,0 +1,1602 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2012 Vivante Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * BSD LICENSE + * + * Copyright(c) 2012 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_FORMAT (1 << 0) +#define GCZONE_BLEND (1 << 1) +#define GCZONE_DEST (1 << 2) +#define GCZONE_SRC (1 << 3) + +GCDBG_FILTERDEF(gcparser, GCZONE_NONE, + "format", + "blend", + "dest", + "src") + + +/******************************************************************************* + * Pixel format parser. + */ + +/* FIXME/TODO: change to use BLTsvile defines. */ + +#if defined(OCDFMTDEF_ALPHA_SHIFT) +# undef OCDFMTDEF_ALPHA_SHIFT +#endif + +#if defined(OCDFMTDEF_ALPHA_MASK) +# undef OCDFMTDEF_ALPHA_MASK +#endif + +#define OCDFMTDEF_ALPHA_SHIFT 18 +#define OCDFMTDEF_ALPHA_MASK (1 << OCDFMTDEF_ALPHA_SHIFT) + +#define OCDFMTDEF_PLACEMENT_SHIFT 9 +#define OCDFMTDEF_PLACEMENT_MASK (3 << OCDFMTDEF_PLACEMENT_SHIFT) + +#define OCDFMTDEF_BITS_SHIFT 3 +#define OCDFMTDEF_BITS_MASK (3 << OCDFMTDEF_BITS_SHIFT) + +#define OCDFMTDEF_BITS12 (0 << OCDFMTDEF_BITS_SHIFT) +#define OCDFMTDEF_BITS15 (1 << OCDFMTDEF_BITS_SHIFT) +#define OCDFMTDEF_BITS16 (2 << OCDFMTDEF_BITS_SHIFT) +#define OCDFMTDEF_BITS24 (3 << OCDFMTDEF_BITS_SHIFT) + +#define BVFORMATRGBA(BPP, Format, Swizzle, R, G, B, A) \ +{ \ + BVFMT_RGB, \ + BPP, \ + GCREG_DE_FORMAT_ ## Format, \ + GCREG_DE_SWIZZLE_ ## Swizzle, \ + { R, G, B, A } \ +} + +#define BVCOMP(Shift, Size) \ + { Shift, Size, ((1 << Size) - 1) << Shift } + +#define BVRED(Shift, Size) \ + BVCOMP(Shift, Size) + +#define BVGREEN(Shift, Size) \ + BVCOMP(Shift, Size) + +#define BVBLUE(Shift, Size) \ + BVCOMP(Shift, Size) + +#define BVALPHA(Shift, Size) \ + BVCOMP(Shift, Size) + +#define BVFORMATINVALID \ + { 0, 0, 0, 0, { { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 } } } + +static struct bvformatxlate g_format_nv12 = { + .type = BVFMT_YUV, + .bitspp = 8, + .format = GCREG_DE_FORMAT_NV12, +}; +static struct bvformatxlate g_format_uyvy = { + .type = BVFMT_YUV, + .bitspp = 16, + .format = GCREG_DE_FORMAT_UYVY +}; +static struct bvformatxlate g_format_yuy2 = { + .type = BVFMT_YUV, + .bitspp = 16, + .format = GCREG_DE_FORMAT_YUY2 +}; + +static struct bvformatxlate formatxlate[] = { + /* #0: OCDFMT_xRGB12 + BITS=12 ALPHA=0 REVERSED=0 LEFT_JUSTIFIED=0 */ + BVFORMATRGBA(16, X4R4G4B4, ARGB, + BVRED(8, 4), BVGREEN(4, 4), BVBLUE(0, 4), BVALPHA(12, 0)), + + /* #1: OCDFMT_RGBx12 + BITS=12 ALPHA=0 REVERSED=0 LEFT_JUSTIFIED=1 */ + BVFORMATRGBA(16, X4R4G4B4, RGBA, + BVRED(12, 4), BVGREEN(8, 4), BVBLUE(4, 4), BVALPHA(0, 0)), + + /* #2: OCDFMT_xBGR12 + BITS=12 ALPHA=0 REVERSED=1 LEFT_JUSTIFIED=0 */ + BVFORMATRGBA(16, X4R4G4B4, ABGR, + BVRED(0, 4), BVGREEN(4, 4), BVBLUE(8, 4), BVALPHA(12, 0)), + + /* #3: OCDFMT_BGRx12 + BITS=12 ALPHA=0 REVERSED=1 LEFT_JUSTIFIED=1 */ + BVFORMATRGBA(16, X4R4G4B4, BGRA, + BVRED(4, 4), BVGREEN(8, 4), BVBLUE(12, 4), BVALPHA(0, 0)), + + /* #4: OCDFMT_ARGB12 + BITS=12 ALPHA=1 REVERSED=0 LEFT_JUSTIFIED=0 */ + BVFORMATRGBA(16, A4R4G4B4, ARGB, + BVRED(8, 4), BVGREEN(4, 4), BVBLUE(0, 4), BVALPHA(12, 4)), + + /* #5: OCDFMT_RGBA12 + BITS=12 ALPHA=1 REVERSED=0 LEFT_JUSTIFIED=1 */ + BVFORMATRGBA(16, A4R4G4B4, RGBA, + BVRED(12, 4), BVGREEN(8, 4), BVBLUE(4, 4), BVALPHA(0, 4)), + + /* #6: OCDFMT_ABGR12 + BITS=12 ALPHA=1 REVERSED=1 LEFT_JUSTIFIED=0 */ + BVFORMATRGBA(16, A4R4G4B4, ABGR, + BVRED(0, 4), BVGREEN(4, 4), BVBLUE(8, 4), BVALPHA(12, 4)), + + /* #7: OCDFMT_BGRA12 + BITS=12 ALPHA=1 REVERSED=1 LEFT_JUSTIFIED=1 */ + BVFORMATRGBA(16, A4R4G4B4, BGRA, + BVRED(4, 4), BVGREEN(8, 4), BVBLUE(12, 4), BVALPHA(0, 4)), + + /***********************************************/ + + /* #8: OCDFMT_xRGB15 + BITS=15 ALPHA=0 REVERSED=0 LEFT_JUSTIFIED=0 */ + BVFORMATRGBA(16, X1R5G5B5, ARGB, + BVRED(10, 5), BVGREEN(5, 5), BVBLUE(0, 5), BVALPHA(15, 0)), + + /* #9: OCDFMT_RGBx15 + BITS=15 ALPHA=0 REVERSED=0 LEFT_JUSTIFIED=1 */ + BVFORMATRGBA(16, X1R5G5B5, RGBA, + BVRED(11, 5), BVGREEN(6, 5), BVBLUE(1, 5), BVALPHA(0, 0)), + + /* #10: OCDFMT_xBGR15 + BITS=15 ALPHA=0 REVERSED=1 LEFT_JUSTIFIED=0 */ + BVFORMATRGBA(16, X1R5G5B5, ABGR, + BVRED(0, 5), BVGREEN(5, 5), BVBLUE(10, 5), BVALPHA(15, 0)), + + /* #11: OCDFMT_BGRx15 + BITS=15 ALPHA=0 REVERSED=1 LEFT_JUSTIFIED=1 */ + BVFORMATRGBA(16, X1R5G5B5, BGRA, + BVRED(1, 5), BVGREEN(6, 5), BVBLUE(11, 5), BVALPHA(0, 0)), + + /* #12: OCDFMT_ARGB15 + BITS=15 ALPHA=1 REVERSED=0 LEFT_JUSTIFIED=0 */ + BVFORMATRGBA(16, A1R5G5B5, ARGB, + BVRED(10, 5), BVGREEN(5, 5), BVBLUE(0, 5), BVALPHA(15, 1)), + + /* #13: OCDFMT_RGBA15 + BITS=15 ALPHA=1 REVERSED=0 LEFT_JUSTIFIED=1 */ + BVFORMATRGBA(16, A1R5G5B5, RGBA, + BVRED(11, 5), BVGREEN(6, 5), BVBLUE(1, 5), BVALPHA(0, 1)), + + /* #14: OCDFMT_ABGR15 + BITS=15 ALPHA=1 REVERSED=1 LEFT_JUSTIFIED=0 */ + BVFORMATRGBA(16, A1R5G5B5, ABGR, + BVRED(0, 5), BVGREEN(5, 5), BVBLUE(10, 5), BVALPHA(15, 1)), + + /* #15: OCDFMT_BGRA15 + BITS=15 ALPHA=1 REVERSED=1 LEFT_JUSTIFIED=1 */ + BVFORMATRGBA(16, A1R5G5B5, BGRA, + BVRED(1, 5), BVGREEN(6, 5), BVBLUE(11, 5), BVALPHA(0, 1)), + + /***********************************************/ + + /* #16: OCDFMT_RGB16 + BITS=16 ALPHA=0 REVERSED=0 LEFT_JUSTIFIED=0 */ + BVFORMATRGBA(16, R5G6B5, ARGB, + BVRED(11, 5), BVGREEN(5, 6), BVBLUE(0, 5), BVALPHA(0, 0)), + + /* #17: OCDFMT_RGB16 + BITS=16 ALPHA=0 REVERSED=0 LEFT_JUSTIFIED=1 */ + BVFORMATRGBA(16, R5G6B5, ARGB, + BVRED(11, 5), BVGREEN(5, 6), BVBLUE(0, 5), BVALPHA(0, 0)), + + /* #18: OCDFMT_BGR16 + BITS=16 ALPHA=0 REVERSED=1 LEFT_JUSTIFIED=0 */ + BVFORMATRGBA(16, R5G6B5, ABGR, + BVRED(0, 5), BVGREEN(5, 6), BVBLUE(11, 5), BVALPHA(0, 0)), + + /* #19: OCDFMT_BGR16 + BITS=16 ALPHA=0 REVERSED=1 LEFT_JUSTIFIED=1 */ + BVFORMATRGBA(16, R5G6B5, ABGR, + BVRED(0, 5), BVGREEN(5, 6), BVBLUE(11, 5), BVALPHA(0, 0)), + + /* #20 */ + BVFORMATINVALID, + + /* #21 */ + BVFORMATINVALID, + + /* #22 */ + BVFORMATINVALID, + + /* #23 */ + BVFORMATINVALID, + + /***********************************************/ + + /* #24: OCDFMT_xRGB24 + BITS=24 ALPHA=0 REVERSED=0 LEFT_JUSTIFIED=0 */ + BVFORMATRGBA(32, X8R8G8B8, BGRA, + BVRED(8, 8), BVGREEN(16, 8), BVBLUE(24, 8), BVALPHA(0, 0)), + + /* #25: OCDFMT_RGBx24 + BITS=24 ALPHA=0 REVERSED=0 LEFT_JUSTIFIED=1 */ + BVFORMATRGBA(32, X8R8G8B8, ABGR, + BVRED(0, 8), BVGREEN(8, 8), BVBLUE(16, 8), BVALPHA(24, 0)), + + /* #26: OCDFMT_xBGR24 + BITS=24 ALPHA=0 REVERSED=1 LEFT_JUSTIFIED=0 */ + BVFORMATRGBA(32, X8R8G8B8, RGBA, + BVRED(24, 8), BVGREEN(16, 8), BVBLUE(8, 8), BVALPHA(0, 0)), + + /* #27: OCDFMT_BGRx24 + BITS=24 ALPHA=0 REVERSED=1 LEFT_JUSTIFIED=1 */ + BVFORMATRGBA(32, X8R8G8B8, ARGB, + BVRED(16, 8), BVGREEN(8, 8), BVBLUE(0, 8), BVALPHA(24, 0)), + + /* #28: OCDFMT_ARGB24 + BITS=24 ALPHA=1 REVERSED=0 LEFT_JUSTIFIED=0 */ + BVFORMATRGBA(32, A8R8G8B8, BGRA, + BVRED(8, 8), BVGREEN(16, 8), BVBLUE(24, 8), BVALPHA(0, 8)), + + /* #29: OCDFMT_RGBA24 + BITS=24 ALPHA=1 REVERSED=0 LEFT_JUSTIFIED=1 */ + BVFORMATRGBA(32, A8R8G8B8, ABGR, + BVRED(0, 8), BVGREEN(8, 8), BVBLUE(16, 8), BVALPHA(24, 8)), + + /* #30: OCDFMT_ABGR24 + BITS=24 ALPHA=1 REVERSED=1 LEFT_JUSTIFIED=0 */ + BVFORMATRGBA(32, A8R8G8B8, RGBA, + BVRED(24, 8), BVGREEN(16, 8), BVBLUE(8, 8), BVALPHA(0, 8)), + + /* #31: OCDFMT_BGRA24 + BITS=24 ALPHA=1 REVERSED=1 LEFT_JUSTIFIED=1 */ + BVFORMATRGBA(32, A8R8G8B8, ARGB, + BVRED(16, 8), BVGREEN(8, 8), BVBLUE(0, 8), BVALPHA(24, 8)), +}; + +enum bverror parse_format(struct bvbltparams *bvbltparams, + enum ocdformat ocdformat, + struct bvformatxlate **format) +{ + static unsigned int containers[] = { + 8, /* OCDFMTDEF_CONTAINER_8BIT */ + 16, /* OCDFMTDEF_CONTAINER_16BIT */ + 24, /* OCDFMTDEF_CONTAINER_24BIT */ + 32, /* OCDFMTDEF_CONTAINER_32BIT */ + ~0U, /* reserved */ + 48, /* OCDFMTDEF_CONTAINER_48BIT */ + ~0U, /* reserved */ + 64 /* OCDFMTDEF_CONTAINER_64BIT */ + }; + + enum bverror bverror = BVERR_NONE; + unsigned int cs; + unsigned int bits; + unsigned int swizzle; + unsigned int alpha; + unsigned int index; + unsigned int cont; + + GCENTERARG(GCZONE_FORMAT, "ocdformat = 0x%08X\n", ocdformat); + + cs = (ocdformat & OCDFMTDEF_CS_MASK) >> OCDFMTDEF_CS_SHIFT; + bits = (ocdformat & OCDFMTDEF_COMPONENTSIZEMINUS1_MASK) + >> OCDFMTDEF_COMPONENTSIZEMINUS1_SHIFT; + cont = (ocdformat & OCDFMTDEF_CONTAINER_MASK) + >> OCDFMTDEF_CONTAINER_SHIFT; + GCDBG(GCZONE_FORMAT, "cs = %d\n", cs); + GCDBG(GCZONE_FORMAT, "bits = %d\n", bits); + GCDBG(GCZONE_FORMAT, "cont = %d\n", cont); + + switch (cs) { + case (OCDFMTDEF_CS_RGB >> OCDFMTDEF_CS_SHIFT): + GCDBG(GCZONE_FORMAT, "OCDFMTDEF_CS_RGB\n"); + + if ((ocdformat & OCDFMTDEF_LAYOUT_MASK) != OCDFMTDEF_PACKED) { + BVSETBLTERROR(BVERR_UNK, + "only packed RGBA formats are supported"); + goto exit; + } + + swizzle = (ocdformat & OCDFMTDEF_PLACEMENT_MASK) + >> OCDFMTDEF_PLACEMENT_SHIFT; + alpha = (ocdformat & OCDFMTDEF_ALPHA_MASK) + >> OCDFMTDEF_ALPHA_SHIFT; + + GCDBG(GCZONE_FORMAT, "swizzle = %d\n", swizzle); + GCDBG(GCZONE_FORMAT, "alpha = %d\n", alpha); + + index = swizzle | (alpha << 2); + + switch (bits) { + case 12 - 1: + index |= OCDFMTDEF_BITS12; + break; + + case 15 - 1: + index |= OCDFMTDEF_BITS15; + break; + + case 16 - 1: + index |= OCDFMTDEF_BITS16; + break; + + case 24 - 1: + index |= OCDFMTDEF_BITS24; + break; + + default: + BVSETBLTERROR(BVERR_UNK, + "unsupported bit width %d", bits); + goto exit; + } + + GCDBG(GCZONE_FORMAT, "index = %d\n", index); + break; + + case (OCDFMTDEF_CS_YCbCr >> OCDFMTDEF_CS_SHIFT): + GCDBG(GCZONE_FORMAT, "OCDFMTDEF_CS_YCbCr\n"); + + /* FIXME/TODO: add proper YUV parsing. */ + switch (ocdformat) { + case OCDFMT_NV12: + GCDBG(GCZONE_FORMAT, "OCDFMT_NV12\n"); + *format = &g_format_nv12; + goto exit; + + case OCDFMT_UYVY: + GCDBG(GCZONE_FORMAT, "OCDFMT_UYVY\n"); + *format = &g_format_uyvy; + goto exit; + + case OCDFMT_YUY2: + GCDBG(GCZONE_FORMAT, "OCDFMT_YUY2\n"); + *format = &g_format_yuy2; + goto exit; + + default: + BVSETBLTERROR(BVERR_UNK, + "unsupported YUV format %d", ocdformat); + goto exit; + } + + default: + BVSETBLTERROR(BVERR_UNK, + "unsupported color space %d", cs); + goto exit; + } + + if (formatxlate[index].bitspp != containers[cont]) { + BVSETBLTERROR(BVERR_UNK, + "unsupported bit width %d", bits); + goto exit; + } + + *format = &formatxlate[index]; + + GCDBG(GCZONE_FORMAT, "format record = 0x%08X\n", + (unsigned int) &formatxlate[index]); + GCDBG(GCZONE_FORMAT, " bpp = %d\n", formatxlate[index].bitspp); + GCDBG(GCZONE_FORMAT, " format = %d\n", formatxlate[index].format); + GCDBG(GCZONE_FORMAT, " swizzle = %d\n", formatxlate[index].swizzle); + + bverror = BVERR_NONE; + +exit: + GCEXITARG(GCZONE_FORMAT, "bv%s = %d\n", + (bverror == BVERR_NONE) ? "result" : "error", bverror); + return bverror; +} + + +/******************************************************************************* + * Alpha blending parser. + */ + +#define BVBLENDMATCH(Mode, Inverse, Normal) \ +( \ + BVBLENDDEF_ ## Mode | \ + BVBLENDDEF_ ## Inverse | \ + BVBLENDDEF_ ## Normal \ +) + +#define BVSRC1USE(Use) \ + Use + +#define BVSRC2USE(Use) \ + Use + +#define BVBLENDUNDEFINED() \ + { ~0, ~0, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } } + +struct bvblendxlate { + unsigned char match1; + unsigned char match2; + + struct gcblendconfig k1; + struct gcblendconfig k2; +}; + +static struct bvblendxlate blendxlate[64] = { + /**********************************************************************/ + /* #0: color factor: 00 00 00 A:(1-C1,C1)=zero + alpha factor: zero ==> 00 00 00 */ + { + 0x00, + 0x00, + + { + GCREG_BLENDING_MODE_ZERO, + GCREG_FACTOR_INVERSE_DISABLE, + BVSRC1USE(false), BVSRC2USE(false) + }, + + { + GCREG_BLENDING_MODE_ZERO, + GCREG_FACTOR_INVERSE_DISABLE, + BVSRC1USE(false), BVSRC2USE(false) + } + }, + + /* #1: color factor: 00 00 01 A:(1-C1,A1)=A1 + alpha factor: A1 ==> 00 00 01 or 00 10 01 */ + { + BVBLENDMATCH(ONLY_A, INV_C1, NORM_A1), + BVBLENDMATCH(ONLY_A, INV_C2, NORM_A1), + + { + GCREG_BLENDING_MODE_NORMAL, + GCREG_FACTOR_INVERSE_ENABLE, + BVSRC1USE(true), BVSRC2USE(false) + }, + + { + GCREG_BLENDING_MODE_NORMAL, + GCREG_FACTOR_INVERSE_DISABLE, + BVSRC1USE(true), BVSRC2USE(true) + } + }, + + /* #2: color factor: 00 00 10 A:(1-C1,C2)=undefined + alpha factor: N/A */ + BVBLENDUNDEFINED(), + + /* #3: color factor: 00 00 11 A:(1-C1,A2)=A2 + alpha factor: A2 ==> 00 00 11 or 00 10 11 */ + { + BVBLENDMATCH(ONLY_A, INV_C1, NORM_A2), + BVBLENDMATCH(ONLY_A, INV_C2, NORM_A2), + + { + GCREG_BLENDING_MODE_NORMAL, + GCREG_FACTOR_INVERSE_DISABLE, + BVSRC1USE(true), BVSRC2USE(true) + }, + + { + GCREG_BLENDING_MODE_NORMAL, + GCREG_FACTOR_INVERSE_ENABLE, + BVSRC1USE(false), BVSRC2USE(true) + } + }, + + /* #4: color factor: 00 01 00 A:(1-A1,C1)=1-A1 + alpha factor: 1-A1 ==> 00 01 00 or 00 01 10 */ + { + BVBLENDMATCH(ONLY_A, INV_A1, NORM_C1), + BVBLENDMATCH(ONLY_A, INV_A1, NORM_C2), + + { + GCREG_BLENDING_MODE_INVERSED, + GCREG_FACTOR_INVERSE_ENABLE, + BVSRC1USE(true), BVSRC2USE(false) + }, + + { + GCREG_BLENDING_MODE_INVERSED, + GCREG_FACTOR_INVERSE_DISABLE, + BVSRC1USE(true), BVSRC2USE(true) + } + }, + + /* #5: color factor: 00 01 01 A:(1-A1,A1)=undefined + alpha factor: N/A */ + BVBLENDUNDEFINED(), + + /* #6: color factor: 00 01 10 A:(1-A1,C2)=1-A1 + alpha factor: 1-A1 ==> 00 01 00 or 00 01 10 */ + { + BVBLENDMATCH(ONLY_A, INV_A1, NORM_C1), + BVBLENDMATCH(ONLY_A, INV_A1, NORM_C2), + + { + GCREG_BLENDING_MODE_INVERSED, + GCREG_FACTOR_INVERSE_ENABLE, + BVSRC1USE(true), BVSRC2USE(false) + }, + + { + GCREG_BLENDING_MODE_INVERSED, + GCREG_FACTOR_INVERSE_DISABLE, + BVSRC1USE(true), BVSRC2USE(true) + } + }, + + /* #7: color factor: 00 01 11 A:(1-A1,A2)=undefined + alpha factor: N/A */ + BVBLENDUNDEFINED(), + + /* #8: color factor: 00 10 00 A:(1-C2,C1)=undefined + alpha factor: N/A */ + BVBLENDUNDEFINED(), + + /* #9: color factor: 00 10 01 A:(1-C2,A1)=A1 + alpha factor: A1 ==> 00 00 01 or 00 10 01 */ + { + BVBLENDMATCH(ONLY_A, INV_C1, NORM_A1), + BVBLENDMATCH(ONLY_A, INV_C2, NORM_A1), + + { + GCREG_BLENDING_MODE_NORMAL, + GCREG_FACTOR_INVERSE_ENABLE, + BVSRC1USE(true), BVSRC2USE(false) + }, + + { + GCREG_BLENDING_MODE_NORMAL, + GCREG_FACTOR_INVERSE_DISABLE, + BVSRC1USE(true), BVSRC2USE(true) + } + }, + + /* #10: color factor: 00 10 10 A:(1-C2,C2)=undefined + alpha factor: N/A */ + BVBLENDUNDEFINED(), + + /* #11: color factor: 00 10 11 A:(1-C2,A2)=A2 + alpha factor: A2 ==> 00 00 11 or 00 10 11 */ + { + BVBLENDMATCH(ONLY_A, INV_C1, NORM_A2), + BVBLENDMATCH(ONLY_A, INV_C2, NORM_A2), + + { + GCREG_BLENDING_MODE_NORMAL, + GCREG_FACTOR_INVERSE_DISABLE, + BVSRC1USE(true), BVSRC2USE(true) + }, + + { + GCREG_BLENDING_MODE_NORMAL, + GCREG_FACTOR_INVERSE_ENABLE, + BVSRC1USE(false), BVSRC2USE(true) + } + }, + + /* #12: color factor: 00 11 00 A:(1-A2,C1)=1-A2 + alpha factor: 1-A2 ==> 00 11 00 or 00 11 10 */ + { + BVBLENDMATCH(ONLY_A, INV_A2, NORM_C1), + BVBLENDMATCH(ONLY_A, INV_A2, NORM_C2), + + { + GCREG_BLENDING_MODE_INVERSED, + GCREG_FACTOR_INVERSE_DISABLE, + BVSRC1USE(true), BVSRC2USE(true) + }, + + { + GCREG_BLENDING_MODE_INVERSED, + GCREG_FACTOR_INVERSE_ENABLE, + BVSRC1USE(false), BVSRC2USE(true) + } + }, + + /* #13: color factor: 00 11 01 A:(1-A2,A1)=undefined + alpha factor: N/A */ + BVBLENDUNDEFINED(), + + /* #14: color factor: 00 11 10 A:(1-A2,C2)=1-A2 + alpha factor: 1-A2 ==> 00 11 00 or 00 11 10 */ + { + BVBLENDMATCH(ONLY_A, INV_A2, NORM_C1), + BVBLENDMATCH(ONLY_A, INV_A2, NORM_C2), + + { + GCREG_BLENDING_MODE_INVERSED, + GCREG_FACTOR_INVERSE_DISABLE, + BVSRC1USE(true), BVSRC2USE(true) + }, + + { + GCREG_BLENDING_MODE_INVERSED, + GCREG_FACTOR_INVERSE_ENABLE, + BVSRC1USE(false), BVSRC2USE(true) + } + }, + + /* #15: color factor: 00 11 11 A:(1-A2,A2)=undefined + alpha factor: N/A */ + BVBLENDUNDEFINED(), + + /**********************************************************************/ + /* #16: color factor: 01 00 00 MIN:(1-C1,C1) ==> not supported + alpha factor: N/A */ + BVBLENDUNDEFINED(), + + /* #17: color factor: 01 00 01 MIN:(1-C1,A1) ==> not supported + alpha factor: N/A */ + BVBLENDUNDEFINED(), + + /* #18: color factor: 01 00 10 MIN:(1-C1,C2) ==> not supported + alpha factor: N/A */ + BVBLENDUNDEFINED(), + + /* #19: color factor: 01 00 11 MIN:(1-C1,A2) ==> not supported + alpha factor: N/A */ + BVBLENDUNDEFINED(), + + /* #20: color factor: 01 01 00 MIN:(1-A1,C1) ==> not supported + alpha factor: N/A */ + BVBLENDUNDEFINED(), + + /* #21: color factor: 01 01 01 MIN:(1-A1,A1) ==> not supported + alpha factor: N/A */ + BVBLENDUNDEFINED(), + + /* #22: color factor: 01 01 10 MIN:(1-A1,C2) ==> not supported + alpha factor: N/A */ + BVBLENDUNDEFINED(), + + /* #23: color factor: 01 01 11 MIN:(1-A1,A2) + alpha factor: one ==> 11 11 11 */ + { + 0x3F, + 0x3F, + + { + GCREG_BLENDING_MODE_SATURATED_DEST_ALPHA, + GCREG_FACTOR_INVERSE_DISABLE, + BVSRC1USE(true), BVSRC2USE(true) + }, + + { + GCREG_BLENDING_MODE_SATURATED_ALPHA, + GCREG_FACTOR_INVERSE_DISABLE, + BVSRC1USE(true), BVSRC2USE(true) + } + }, + + /* #24: color factor: 01 10 00 MIN:(1-C2,C1) ==> not supported + alpha factor: N/A */ + BVBLENDUNDEFINED(), + + /* #25: color factor: 01 10 01 MIN:(1-C2,A1) ==> not supported + alpha factor: N/A */ + BVBLENDUNDEFINED(), + + /* #26: color factor: 01 10 10 MIN:(1-C2,C2) ==> not supported + alpha factor: N/A */ + BVBLENDUNDEFINED(), + + /* #27: color factor: 01 10 11 MIN:(1-C2,A2) ==> not supported + alpha factor: N/A */ + BVBLENDUNDEFINED(), + + /* #28: color factor: 01 11 00 MIN:(1-A2,C1) ==> not supported + alpha factor: N/A */ + BVBLENDUNDEFINED(), + + /* #29: color factor: 01 11 01 MIN:(1-A2,A1) + alpha factor: one ==> 11 11 11 */ + { + 0x3F, + 0x3F, + + { + GCREG_BLENDING_MODE_SATURATED_ALPHA, + GCREG_FACTOR_INVERSE_DISABLE, + BVSRC1USE(true), BVSRC2USE(true) + }, + + { + GCREG_BLENDING_MODE_SATURATED_DEST_ALPHA, + GCREG_FACTOR_INVERSE_DISABLE, + BVSRC1USE(true), BVSRC2USE(true) + } + }, + + /* #30: color factor: 01 11 10 MIN:(1-A2,C2) ==> not supported + alpha factor: N/A */ + BVBLENDUNDEFINED(), + + /* #31: color factor: 01 11 11 MIN:(1-A2,A2) ==> not supported + alpha factor: N/A */ + BVBLENDUNDEFINED(), + + /**********************************************************************/ + /* #32: color factor: 10 00 00 MAX:(1-C1,C1) ==> not supported + alpha factor: N/A */ + BVBLENDUNDEFINED(), + + /* #33: color factor: 10 00 01 MAX:(1-C1,A1) ==> not supported + alpha factor: N/A */ + BVBLENDUNDEFINED(), + + /* #34: color factor: 10 00 10 MAX:(1-C1,C2) ==> not supported + alpha factor: N/A */ + BVBLENDUNDEFINED(), + + /* #35: color factor: 10 00 11 MAX:(1-C1,A2) ==> not supported + alpha factor: N/A */ + BVBLENDUNDEFINED(), + + /* #36: color factor: 10 01 00 MAX:(1-A1,C1) ==> not supported + alpha factor: N/A */ + BVBLENDUNDEFINED(), + + /* #37: color factor: 10 01 01 MAX:(1-A1,A1) ==> not supported + alpha factor: N/A */ + BVBLENDUNDEFINED(), + + /* #38: color factor: 10 01 10 MAX:(1-A1,C2) ==> not supported + alpha factor: N/A */ + BVBLENDUNDEFINED(), + + /* #39: color factor: 10 01 11 MAX:(1-A1,A2) ==> not supported + alpha factor: N/A */ + BVBLENDUNDEFINED(), + + /* #40: color factor: 10 10 00 MAX:(1-C2,C1) ==> not supported + alpha factor: N/A */ + BVBLENDUNDEFINED(), + + /* #41: color factor: 10 10 01 MAX:(1-C2,A1) ==> not supported + alpha factor: N/A */ + BVBLENDUNDEFINED(), + + /* #42: color factor: 10 10 10 MAX:(1-C2,C2) ==> not supported + alpha factor: N/A */ + BVBLENDUNDEFINED(), + + /* #43: color factor: 10 10 11 MAX:(1-C2,A2) ==> not supported + alpha factor: N/A */ + BVBLENDUNDEFINED(), + + /* #44: color factor: 10 11 00 MAX:(1-A2,C1) ==> not supported + alpha factor: N/A */ + BVBLENDUNDEFINED(), + + /* #45: color factor: 10 11 01 MAX:(1-A2,A1) ==> not supported + alpha factor: N/A */ + BVBLENDUNDEFINED(), + + /* #46: color factor: 10 11 10 MAX:(1-A2,C2) ==> not supported + alpha factor: N/A */ + BVBLENDUNDEFINED(), + + /* #47: color factor: 10 11 11 MAX:(1-A2,A2) ==> not supported + alpha factor: N/A */ + BVBLENDUNDEFINED(), + + /**********************************************************************/ + /* #48: color factor: 11 00 00 C:(1-C1,C1)=undefined + alpha factor: N/A */ + BVBLENDUNDEFINED(), + + /* #49: color factor: 11 00 01 C:(1-C1,A1)=1-C1 + alpha factor: 1-A1 ==> 00 01 00 or 00 01 10 */ + { + BVBLENDMATCH(ONLY_A, INV_A1, NORM_C1), + BVBLENDMATCH(ONLY_A, INV_A1, NORM_C2), + + { + GCREG_BLENDING_MODE_COLOR_INVERSED, + GCREG_FACTOR_INVERSE_ENABLE, + BVSRC1USE(true), BVSRC2USE(false) + }, + + { + GCREG_BLENDING_MODE_COLOR_INVERSED, + GCREG_FACTOR_INVERSE_DISABLE, + BVSRC1USE(true), BVSRC2USE(true) + } + }, + + /* #50: color factor: 11 00 10 C:(1-C1,C2)=undefined + alpha factor: N/A */ + BVBLENDUNDEFINED(), + + /* #51: color factor: 11 00 11 C:(1-C1,A2)=1-C1 + alpha factor: 1-A1 ==> 00 01 00 or 00 01 10 */ + { + BVBLENDMATCH(ONLY_A, INV_A1, NORM_C1), + BVBLENDMATCH(ONLY_A, INV_A1, NORM_C2), + + { + GCREG_BLENDING_MODE_COLOR_INVERSED, + GCREG_FACTOR_INVERSE_ENABLE, + BVSRC1USE(true), BVSRC2USE(false) + }, + + { + GCREG_BLENDING_MODE_COLOR_INVERSED, + GCREG_FACTOR_INVERSE_DISABLE, + BVSRC1USE(true), BVSRC2USE(true) + } + }, + + /* #52: color factor: 11 01 00 C:(1-A1,C1)=C1 + alpha factor: A1 ==> 00 00 01 or 00 10 01 */ + { + BVBLENDMATCH(ONLY_A, INV_C1, NORM_A1), + BVBLENDMATCH(ONLY_A, INV_C2, NORM_A1), + + { + GCREG_BLENDING_MODE_COLOR, + GCREG_FACTOR_INVERSE_ENABLE, + BVSRC1USE(true), BVSRC2USE(false) + }, + + { + GCREG_BLENDING_MODE_COLOR, + GCREG_FACTOR_INVERSE_DISABLE, + BVSRC1USE(true), BVSRC2USE(true) + } + }, + + /* #53: color factor: 11 01 01 C:(1-A1,A1)=undefined + alpha factor: N/A */ + BVBLENDUNDEFINED(), + + /* #54: color factor: 11 01 10 C:(1-A1,C2)=C2 + alpha factor: A2 ==> 00 00 11 or 00 10 11 */ + { + BVBLENDMATCH(ONLY_A, INV_C1, NORM_A2), + BVBLENDMATCH(ONLY_A, INV_C2, NORM_A2), + + { + GCREG_BLENDING_MODE_COLOR, + GCREG_FACTOR_INVERSE_DISABLE, + BVSRC1USE(true), BVSRC2USE(true) + }, + + { + GCREG_BLENDING_MODE_COLOR, + GCREG_FACTOR_INVERSE_ENABLE, + BVSRC1USE(false), BVSRC2USE(true) + } + }, + + /* #55: color factor: 11 01 11 C:(1-A1,A2)=undefined + alpha factor: N/A */ + BVBLENDUNDEFINED(), + + /* #56: color factor: 11 10 00 C:(1-C2,C1)=undefined + alpha factor: N/A */ + BVBLENDUNDEFINED(), + + /* #57: color factor: 11 10 01 C:(1-C2,A1)=1-C2 + alpha factor: 1-A2 ==> 00 11 00 or 00 11 10 */ + { + BVBLENDMATCH(ONLY_A, INV_A2, NORM_C1), + BVBLENDMATCH(ONLY_A, INV_A2, NORM_C2), + + { + GCREG_BLENDING_MODE_COLOR_INVERSED, + GCREG_FACTOR_INVERSE_DISABLE, + BVSRC1USE(true), BVSRC2USE(true) + }, + + { + GCREG_BLENDING_MODE_COLOR_INVERSED, + GCREG_FACTOR_INVERSE_ENABLE, + BVSRC1USE(false), BVSRC2USE(true) + } + }, + + /* #58: color factor: 11 10 10 C:(1-C2,C2)=undefined + alpha factor: N/A */ + BVBLENDUNDEFINED(), + + /* #59: color factor: 11 10 11 C:(1-C2,A2)=1-C2 + alpha factor: 1-A2 ==> 00 11 00 or 00 11 10 */ + { + BVBLENDMATCH(ONLY_A, INV_A2, NORM_C1), + BVBLENDMATCH(ONLY_A, INV_A2, NORM_C2), + + { + GCREG_BLENDING_MODE_COLOR_INVERSED, + GCREG_FACTOR_INVERSE_DISABLE, + BVSRC1USE(true), BVSRC2USE(true) + }, + + { + GCREG_BLENDING_MODE_COLOR_INVERSED, + GCREG_FACTOR_INVERSE_ENABLE, + BVSRC1USE(false), BVSRC2USE(false) + } + }, + + /* #60: color factor: 11 11 00 C:(1-A2,C1)=C1 + alpha factor: A1 ==> 00 00 01 or 00 10 01 */ + { + BVBLENDMATCH(ONLY_A, INV_C1, NORM_A1), + BVBLENDMATCH(ONLY_A, INV_C2, NORM_A1), + + { + GCREG_BLENDING_MODE_COLOR, + GCREG_FACTOR_INVERSE_ENABLE, + BVSRC1USE(true), BVSRC2USE(false) + }, + + { + GCREG_BLENDING_MODE_COLOR, + GCREG_FACTOR_INVERSE_DISABLE, + BVSRC1USE(true), BVSRC2USE(true) + } + }, + + /* #61: color factor: 11 11 01 C:(1-A2,A1)=undefined + alpha factor: N/A */ + BVBLENDUNDEFINED(), + + /* #62: color factor: 11 11 10 C:(1-A2,C2)=C2 + alpha factor: A2 ==> 00 00 11 or 00 10 11 */ + { + BVBLENDMATCH(ONLY_A, INV_C1, NORM_A2), + BVBLENDMATCH(ONLY_A, INV_C2, NORM_A2), + + { + GCREG_BLENDING_MODE_COLOR, + GCREG_FACTOR_INVERSE_DISABLE, + BVSRC1USE(true), BVSRC2USE(true) + }, + + { + GCREG_BLENDING_MODE_COLOR, + GCREG_FACTOR_INVERSE_ENABLE, + BVSRC1USE(false), BVSRC2USE(true) + } + }, + + /* #63: color factor: 11 11 11 C:(1-A2,A2)=one + alpha factor: one ==> 11 11 11 */ + { + 0x3F, + 0x3F, + + { + GCREG_BLENDING_MODE_ONE, + GCREG_FACTOR_INVERSE_DISABLE, + BVSRC1USE(true), BVSRC2USE(false) + }, + + { + GCREG_BLENDING_MODE_ONE, + GCREG_FACTOR_INVERSE_DISABLE, + BVSRC1USE(false), BVSRC2USE(true) + } + } +}; + +enum bverror parse_blend(struct bvbltparams *bvbltparams, + enum bvblend blend, + struct gcalpha *gca) +{ + enum bverror bverror; + unsigned int global; + unsigned int k1, k2, k3, k4; + struct bvblendxlate *k1_xlate; + struct bvblendxlate *k2_xlate; + unsigned int alpha; + + GCENTERARG(GCZONE_BLEND, "blend = 0x%08X (%s)\n", + blend, gc_bvblend_name(blend)); + + if ((blend & BVBLENDDEF_REMOTE) != 0) { + BVSETBLTERROR(BVERR_BLEND, "remote alpha not supported"); + goto exit; + } + + global = (blend & BVBLENDDEF_GLOBAL_MASK) >> BVBLENDDEF_GLOBAL_SHIFT; + + switch (global) { + case (BVBLENDDEF_GLOBAL_NONE >> BVBLENDDEF_GLOBAL_SHIFT): + GCDBG(GCZONE_BLEND, "BVBLENDDEF_GLOBAL_NONE\n"); + + gca->src_global_color = + gca->dst_global_color = 0; + + gca->src_global_alpha_mode = GCREG_GLOBAL_ALPHA_MODE_NORMAL; + gca->dst_global_alpha_mode = GCREG_GLOBAL_ALPHA_MODE_NORMAL; + break; + + case (BVBLENDDEF_GLOBAL_UCHAR >> BVBLENDDEF_GLOBAL_SHIFT): + GCDBG(GCZONE_BLEND, "BVBLENDDEF_GLOBAL_UCHAR\n"); + + gca->src_global_color = + gca->dst_global_color = + ((unsigned int) bvbltparams->globalalpha.size8) << 24; + + gca->src_global_alpha_mode = GCREG_GLOBAL_ALPHA_MODE_GLOBAL; + gca->dst_global_alpha_mode = GCREG_GLOBAL_ALPHA_MODE_GLOBAL; + break; + + case (BVBLENDDEF_GLOBAL_FLOAT >> BVBLENDDEF_GLOBAL_SHIFT): + GCDBG(GCZONE_BLEND, "BVBLENDDEF_GLOBAL_FLOAT\n"); + + alpha = gcfp2norm8(bvbltparams->globalalpha.fp); + + gca->src_global_color = + gca->dst_global_color = alpha << 24; + + gca->src_global_alpha_mode = GCREG_GLOBAL_ALPHA_MODE_GLOBAL; + gca->dst_global_alpha_mode = GCREG_GLOBAL_ALPHA_MODE_GLOBAL; + break; + + default: + BVSETBLTERROR(BVERR_BLEND, "invalid global alpha mode"); + goto exit; + } + + /* + Co = k1 x C1 + k2 x C2 + Ao = k3 x A1 + k4 x A2 + */ + + k1 = (blend >> 18) & 0x3F; + k2 = (blend >> 12) & 0x3F; + k3 = (blend >> 6) & 0x3F; + k4 = blend & 0x3F; + + GCDBG(GCZONE_BLEND, "k1 = %d\n", k1); + GCDBG(GCZONE_BLEND, "k2 = %d\n", k2); + GCDBG(GCZONE_BLEND, "k3 = %d\n", k3); + GCDBG(GCZONE_BLEND, "k4 = %d\n", k4); + + k1_xlate = &blendxlate[k1]; + k2_xlate = &blendxlate[k2]; + + if (((k3 != k1_xlate->match1) && (k3 != k1_xlate->match2)) || + ((k4 != k2_xlate->match1) && (k4 != k2_xlate->match2))) { + BVSETBLTERROR(BVERR_BLEND, + "not supported coefficient combination"); + goto exit; + } + + gca->k1 = &k1_xlate->k1; + gca->k2 = &k2_xlate->k2; + + gca->src1used = gca->k1->src1used | gca->k2->src1used; + gca->src2used = gca->k1->src2used | gca->k2->src2used; + + bverror = BVERR_NONE; + +exit: + GCEXITARG(BVERR_BLEND, "bv%s = %d\n", + (bverror == BVERR_NONE) ? "result" : "error", bverror); + return bverror; +} + + +/******************************************************************************* + * Rotation and mirror. + */ + +#define BVFLAG_FLIP_MASK 0x00000003 + +#define BVFLAG_FLIP_SRC1_SHIFT 14 +#define BVFLAG_FLIP_SRC2_SHIFT 16 +#define BVFLAG_FLIP_MASK_SHIFT 18 + +#define GCREG_MIRROR_NONE 0x0 +#define GCREG_MIRROR_X 0x1 +#define GCREG_MIRROR_Y 0x2 +#define GCREG_MIRROR_XY 0x3 + +#define GCREG_ROT_ANGLE_ROT0 0x0 +#define GCREG_ROT_ANGLE_ROT90 0x4 +#define GCREG_ROT_ANGLE_ROT180 0x5 +#define GCREG_ROT_ANGLE_ROT270 0x6 + +#define ROT_ANGLE_INVALID -1 +#define ROT_ANGLE_0 0 +#define ROT_ANGLE_90 1 +#define ROT_ANGLE_180 2 +#define ROT_ANGLE_270 3 + +/* NOTE: BLTsville rotation is defined conunter clock wise. */ +const unsigned int rotencoding[] = { + GCREG_ROT_ANGLE_ROT0, /* ROT_ANGLE_0 */ + GCREG_ROT_ANGLE_ROT270, /* ROT_ANGLE_90 */ + GCREG_ROT_ANGLE_ROT180, /* ROT_ANGLE_180 */ + GCREG_ROT_ANGLE_ROT90 /* ROT_ANGLE_270 */ +}; + +static inline int get_angle(int orientation) +{ + int angle; + + /* Normalize the angle. */ + angle = orientation % 360; + + /* Flip to positive. */ + if (angle < 0) + angle = 360 + angle; + + /* Translate the angle. */ + switch (angle) { + case 0: return ROT_ANGLE_0; + case 90: return ROT_ANGLE_90; + case 180: return ROT_ANGLE_180; + case 270: return ROT_ANGLE_270; + } + + /* Not supported angle. */ + return ROT_ANGLE_INVALID; +} + + +/******************************************************************************* + * Surface compare and validation. + */ + +static bool valid_geom(struct bvbuffdesc *buffdesc, + struct bvsurfgeom *geom, + struct bvformatxlate *format) +{ + unsigned int size; + + /* Compute the size of the surface. */ + size = (geom->width * geom->height * format->bitspp) / 8; + + /* Make sure the size is not greater then the surface. */ + if (size > buffdesc->length) { + GCERR("invalid geometry detected:\n"); + GCERR(" specified dimensions: %dx%d, %d bitspp\n", + geom->width, geom->height, format->bitspp); + GCERR(" surface size based on the dimensions: %d\n", + size); + GCERR(" specified surface size: %lu\n", + buffdesc->length); + return false; + } + + return true; +} + +int get_pixel_offset(struct bvbuffdesc *bvbuffdesc, + struct bvformatxlate *format, + int offset) +{ + unsigned int alignment; + int byteoffset; + unsigned int alignedoffset; + int pixeloffset; + + alignment = (format->type == BVFMT_YUV) + ? (64 - 1) + : (16 - 1); + + /* Determine offset in bytes from the base modified by the + * given offset. */ + if (bvbuffdesc->auxtype == BVAT_PHYSDESC) { + struct bvphysdesc *bvphysdesc; + bvphysdesc = (struct bvphysdesc *) bvbuffdesc->auxptr; + byteoffset = bvphysdesc->pageoffset + offset; + } else { + byteoffset = (unsigned int) bvbuffdesc->virtaddr + offset; + } + + /* Compute the aligned offset. */ + alignedoffset = byteoffset & alignment; + + /* Convert to pixels. */ + pixeloffset = alignedoffset * 8 / format->bitspp; + return -pixeloffset; +} + +enum bverror parse_destination(struct bvbltparams *bvbltparams, + struct gcbatch *batch) +{ + enum bverror bverror = BVERR_NONE; + + GCENTER(GCZONE_DEST); + + /* Did clipping/destination rects change? */ + if ((batch->batchflags & (BVBATCH_CLIPRECT | + BVBATCH_DESTRECT)) != 0) { + struct bvrect *dstrect; + struct bvrect *cliprect; + int destleft, desttop, destright, destbottom; + int clipleft, cliptop, clipright, clipbottom; + unsigned short clippedleft, clippedtop; + unsigned short clippedright, clippedbottom; + + /* Make shortcuts to the destination objects. */ + dstrect = &bvbltparams->dstrect; + cliprect = &bvbltparams->cliprect; + + /* Determine destination rectangle. */ + destleft = dstrect->left; + desttop = dstrect->top; + destright = destleft + dstrect->width; + destbottom = desttop + dstrect->height; + + GCDBG(GCZONE_DEST, "destination rectangle:\n"); + GCDBG(GCZONE_DEST, " dstrect = (%d,%d)-(%d,%d), %dx%d\n", + destleft, desttop, destright, destbottom, + dstrect->width, dstrect->height); + + /* Determine clipping. */ + if ((bvbltparams->flags & BVFLAG_CLIP) == BVFLAG_CLIP) { + clipleft = cliprect->left; + cliptop = cliprect->top; + clipright = clipleft + cliprect->width; + clipbottom = cliptop + cliprect->height; + + if ((clipleft < GC_CLIP_RESET_LEFT) || + (cliptop < GC_CLIP_RESET_TOP) || + (clipright > GC_CLIP_RESET_RIGHT) || + (clipbottom > GC_CLIP_RESET_BOTTOM) || + (clipright < clipleft) || + (clipbottom < cliptop)) { + BVSETBLTERROR(BVERR_CLIP_RECT, + "invalid clipping rectangle"); + goto exit; + } + + GCDBG(GCZONE_DEST, + " cliprect = (%d,%d)-(%d,%d), %dx%d\n", + clipleft, cliptop, clipright, clipbottom, + cliprect->width, cliprect->height); + } else { + clipleft = GC_CLIP_RESET_LEFT; + cliptop = GC_CLIP_RESET_TOP; + clipright = GC_CLIP_RESET_RIGHT; + clipbottom = GC_CLIP_RESET_BOTTOM; + } + + /* Compute clipping deltas and the adjusted destination rect. */ + if (clipleft <= destleft) { + batch->deltaleft = 0; + clippedleft = destleft; + } else { + batch->deltaleft = clipleft - destleft; + clippedleft = clipleft; + } + + if (cliptop <= desttop) { + batch->deltatop = 0; + clippedtop = desttop; + } else { + batch->deltatop = cliptop - desttop; + clippedtop = cliptop; + } + + if (clipright >= destright) { + batch->deltaright = 0; + clippedright = destright; + } else { + batch->deltaright = clipright - destright; + clippedright = clipright; + } + + if (clipbottom >= destbottom) { + batch->deltabottom = 0; + clippedbottom = destbottom; + } else { + batch->deltabottom = clipbottom - destbottom; + clippedbottom = clipbottom; + } + + /* Validate the rectangle. */ + if ((clippedright > (int) bvbltparams->dstgeom->width) || + (clippedbottom > (int) bvbltparams->dstgeom->height)) { + BVSETBLTERROR(BVERR_DSTRECT, + "destination rect exceeds surface size"); + goto exit; + } + + /* Set clipped coordinates. */ + batch->clippedleft = clippedleft; + batch->clippedtop = clippedtop; + batch->clippedright = clippedright; + batch->clippedbottom = clippedbottom; + + GCDBG(GCZONE_DEST, + " clipped dstrect = (%d,%d)-(%d,%d), %dx%d\n", + clippedleft, clippedtop, clippedright, clippedbottom, + clippedright - clippedleft, clippedbottom - clippedtop); + GCDBG(GCZONE_DEST, + " clipping delta = (%d,%d)-(%d,%d)\n", + batch->deltaleft, batch->deltatop, + batch->deltaright, batch->deltabottom); + } + + /* Did the destination surface change? */ + if ((batch->batchflags & BVBATCH_DST) != 0) { + struct bvbuffdesc *dstdesc; + struct bvsurfgeom *dstgeom; + unsigned int stridealign; + + /* Make shortcuts to the destination objects. */ + dstdesc = bvbltparams->dstdesc; + dstgeom = bvbltparams->dstgeom; + + /* Check for unsupported dest formats. */ + switch (dstgeom->format) { + case OCDFMT_NV12: + BVSETBLTERROR(BVERR_DSTGEOM_FORMAT, + "destination format unsupported"); + goto exit; + + default: + break; + } + + /* Parse the destination format. */ + GCDBG(GCZONE_FORMAT, "parsing destination format.\n"); + if (parse_format(bvbltparams, dstgeom->format, + &batch->dstformat) != BVERR_NONE) { + bverror = BVERR_DSTGEOM_FORMAT; + goto exit; + } + + /* Validate geometry. */ + if (!valid_geom(dstdesc, dstgeom, batch->dstformat)) { + BVSETBLTERROR(BVERR_DSTGEOM, + "destination geom exceeds surface size"); + goto exit; + } + + /* Destination stride must be 8 pixel aligned. */ + stridealign = batch->dstformat->bitspp - 1; + if ((dstgeom->virtstride & stridealign) != 0) { + BVSETBLTERROR(BVERR_DSTGEOM_STRIDE, + "destination stride must be 8 pixel " + "aligned."); + goto exit; + } + + /* Parse orientation. */ + batch->dstangle = get_angle(dstgeom->orientation); + if (batch->dstangle == ROT_ANGLE_INVALID) { + BVSETBLTERROR(BVERR_DSTGEOM, + "unsupported destination orientation %d.", + dstgeom->orientation); + } + + /* Compute the destination offset in pixels needed to compensate + * for the surface base address misalignment if any. */ + batch->dstalign = get_pixel_offset(dstdesc, + batch->dstformat, 0); + + switch (batch->dstangle) { + case ROT_ANGLE_0: + /* Determine the physical size. */ + batch->dstphyswidth = dstgeom->width - batch->dstalign; + batch->dstphysheight = dstgeom->height; + + /* Determine geometry size. */ + batch->dstwidth = dstgeom->width - batch->dstalign; + batch->dstheight = dstgeom->height; + + /* Determine the origin offset. */ + batch->dstoffsetX = -batch->dstalign; + batch->dstoffsetY = 0; + break; + + case ROT_ANGLE_90: + /* Determine the physical size. */ + batch->dstphyswidth = dstgeom->height - batch->dstalign; + batch->dstphysheight = dstgeom->width; + + /* Determine geometry size. */ + batch->dstwidth = dstgeom->width; + batch->dstheight = dstgeom->height - batch->dstalign; + + /* Determine the origin offset. */ + batch->dstoffsetX = 0; + batch->dstoffsetY = -batch->dstalign; + break; + + case ROT_ANGLE_180: + /* Determine the physical size. */ + batch->dstphyswidth = dstgeom->width - batch->dstalign; + batch->dstphysheight = dstgeom->height; + + /* Determine geometry size. */ + batch->dstwidth = dstgeom->width - batch->dstalign; + batch->dstheight = dstgeom->height; + + /* Determine the origin offset. */ + batch->dstoffsetX = 0; + batch->dstoffsetY = 0; + break; + + case ROT_ANGLE_270: + /* Determine the physical size. */ + batch->dstphyswidth = dstgeom->height - batch->dstalign; + batch->dstphysheight = dstgeom->width; + + /* Determine geometry size. */ + batch->dstwidth = dstgeom->width; + batch->dstheight = dstgeom->height - batch->dstalign; + + /* Determine the origin offset. */ + batch->dstoffsetX = 0; + batch->dstoffsetY = 0; + break; + } + + GCDBG(GCZONE_DEST, "destination surface:\n"); + GCDBG(GCZONE_DEST, " rotation %d degrees.\n", + batch->dstangle * 90); + + if (dstdesc->auxtype == BVAT_PHYSDESC) { + struct bvphysdesc *bvphysdesc; + bvphysdesc = (struct bvphysdesc *) dstdesc->auxptr; + GCDBG(GCZONE_DEST, " page offset = 0x%08X\n", + bvphysdesc->pageoffset); + } else { + GCDBG(GCZONE_DEST, " virtual address = 0x%08X\n", + (unsigned int) dstdesc->virtaddr); + } + + GCDBG(GCZONE_DEST, " stride = %ld\n", + dstgeom->virtstride); + GCDBG(GCZONE_DEST, " geometry size = %dx%d\n", + dstgeom->width, dstgeom->height); + GCDBG(GCZONE_DEST, " aligned geometry size = %dx%d\n", + batch->dstwidth, batch->dstheight); + GCDBG(GCZONE_DEST, " aligned physical size = %dx%d\n", + batch->dstphyswidth, batch->dstphysheight); + GCDBG(GCZONE_DEST, " origin offset (pixels) = %d,%d\n", + batch->dstoffsetX, batch->dstoffsetY); + GCDBG(GCZONE_DEST, " surface offset (pixels) = %d,0\n", + batch->dstalign); + } + +exit: + GCEXITARG(GCZONE_DEST, "bv%s = %d\n", + (bverror == BVERR_NONE) ? "result" : "error", bverror); + return bverror; +} + +enum bverror parse_source(struct bvbltparams *bvbltparams, + struct gcbatch *batch, + struct srcinfo *srcinfo) +{ + enum bverror bverror = BVERR_NONE; + struct bvbuffdesc *srcdesc; + struct bvsurfgeom *srcgeom; + struct bvrect *srcrect; + unsigned int stridealign; + + /* Make shortcuts to the source objects. */ + srcdesc = srcinfo->buf.desc; + srcgeom = srcinfo->geom; + srcrect = srcinfo->rect; + + /* Parse the source format. */ + GCDBG(GCZONE_FORMAT, "parsing source%d format.\n", + srcinfo->index + 1); + if (parse_format(bvbltparams, srcgeom->format, + &srcinfo->format) != BVERR_NONE) { + bverror = (srcinfo->index == 0) + ? BVERR_SRC1GEOM_FORMAT + : BVERR_SRC2GEOM_FORMAT; + goto exit; + } + + /* Validate source geometry. */ + if (!valid_geom(srcdesc, srcgeom, srcinfo->format)) { + BVSETBLTERROR((srcinfo->index == 0) + ? BVERR_SRC1GEOM + : BVERR_SRC2GEOM, + "source%d geom exceeds surface size.", + srcinfo->index + 1); + goto exit; + } + + /* Source must be 8 pixel aligned. */ + stridealign = srcinfo->format->bitspp - 1; + if ((srcgeom->virtstride & stridealign) != 0) { + BVSETBLTERROR((srcinfo->index == 0) + ? BVERR_SRC1GEOM_STRIDE + : BVERR_SRC2GEOM_STRIDE, + "source stride must be 8 pixel aligned."); + goto exit; + } + + /* Parse orientation. */ + srcinfo->angle = get_angle(srcgeom->orientation); + if (srcinfo->angle == ROT_ANGLE_INVALID) { + BVSETBLTERROR((srcinfo->index == 0) + ? BVERR_SRC1GEOM + : BVERR_SRC2GEOM, + "unsupported source%d orientation %d.", + srcinfo->index + 1, + srcgeom->orientation); + } + + /* Determine source mirror. */ + srcinfo->mirror = (srcinfo->index == 0) + ? (bvbltparams->flags >> BVFLAG_FLIP_SRC1_SHIFT) + & BVFLAG_FLIP_MASK + : (bvbltparams->flags >> BVFLAG_FLIP_SRC2_SHIFT) + & BVFLAG_FLIP_MASK; + + GCDBG(GCZONE_SRC, "source surface %d:\n", srcinfo->index + 1); + GCDBG(GCZONE_SRC, " rotation %d degrees.\n", srcinfo->angle * 90); + + if (srcdesc->auxtype == BVAT_PHYSDESC) { + struct bvphysdesc *bvphysdesc; + bvphysdesc = (struct bvphysdesc *) srcdesc->auxptr; + GCDBG(GCZONE_DEST, " page offset = 0x%08X\n", + bvphysdesc->pageoffset); + } else { + GCDBG(GCZONE_DEST, " virtual address = 0x%08X\n", + (unsigned int) srcdesc->virtaddr); + } + + GCDBG(GCZONE_SRC, " stride = %ld\n", + srcgeom->virtstride); + GCDBG(GCZONE_SRC, " geometry size = %dx%d\n", + srcgeom->width, srcgeom->height); + GCDBG(GCZONE_SRC, " rect = (%d,%d)-(%d,%d), %dx%d\n", + srcrect->left, srcrect->top, + srcrect->left + srcrect->width, + srcrect->top + srcrect->height, + srcrect->width, srcrect->height); + GCDBG(GCZONE_SRC, " mirror = %d\n", srcinfo->mirror); + +exit: + return bverror; +} diff --git a/drivers/misc/gcx/gccore/gcdbglog.c b/drivers/misc/gcx/gccore/gcdbglog.c index 95f2a14..93c020c 100644 --- a/drivers/misc/gcx/gccore/gcdbglog.c +++ b/drivers/misc/gcx/gccore/gcdbglog.c @@ -66,6 +66,9 @@ /* Specifies spacing for thread messages. */ #define GC_THREAD_INDENT 0 +/* Print the timestamp. */ +#define GC_SHOW_TIME 1 + /* When set to non-zero, specifies how many prints are accumulated in the * buffer before the buffer is flushed. */ #define GC_SHOW_DUMP_LINE 1 @@ -120,6 +123,10 @@ (g_initdone && ((filter == NULL) || ((filter->zone & zone) != 0))) #endif +#if GC_SHOW_TIME +#define GC_TIME_FORMAT "[%5ld.%ld] " +#endif + #if GC_SHOW_DUMP_LINE #define GC_DUMPLINE_FORMAT "[%12d] " #endif @@ -155,14 +162,18 @@ struct itemstring { enum itemtype itemtype; int indent; -#if GC_SHOW_PID - struct task_struct *task; +#if GC_SHOW_TIME + struct timespec timestamp; #endif #if GC_SHOW_DUMP_LINE unsigned int dumpline; #endif +#if GC_SHOW_PID + struct task_struct *task; +#endif + const char *message; va_list messagedata; unsigned int datasize; @@ -376,6 +387,13 @@ static void gc_print_string(struct seq_file *s, struct itemstring *str) int len = 0; char buffer[GC_MAXSTR_LENGTH]; +#if GC_SHOW_TIME + len += snprintf(buffer + len, sizeof(buffer) - len - GC_EOL_RESERVE, + GC_TIME_FORMAT, + str->timestamp.tv_sec, + str->timestamp.tv_nsec); +#endif + #if GC_SHOW_DUMP_LINE len += snprintf(buffer + len, sizeof(buffer) - len - GC_EOL_RESERVE, GC_DUMPLINE_FORMAT, str->dumpline); @@ -1148,14 +1166,18 @@ static void gc_append_string(struct buffout *buffout, item->messagedata = *(va_list *) &messagedata; item->datasize = itemstring->datasize; -#if GC_SHOW_PID - item->task = itemstring->task; +#if GC_SHOW_TIME + item->timestamp = itemstring->timestamp; #endif #if GC_SHOW_DUMP_LINE item->dumpline = itemstring->dumpline; #endif +#if GC_SHOW_PID + item->task = itemstring->task; +#endif + /* Copy argument value. */ if (itemstring->datasize != 0) { GC_DEBUGMSG("copying %d bytes of messagedata.\n", @@ -1258,14 +1280,18 @@ static void gc_print(struct buffout *buffout, unsigned int argsize, itemstring.messagedata = args; itemstring.datasize = argsize; -#if GC_SHOW_PID - itemstring.task = threadinfo->task; +#if GC_SHOW_TIME + ktime_get_ts(&itemstring.timestamp); #endif #if GC_SHOW_DUMP_LINE itemstring.dumpline = ++buffout->dumpline; #endif +#if GC_SHOW_PID + itemstring.task = threadinfo->task; +#endif + /* Print the message. */ #if GC_BUFFERED_OUTPUT gc_append_string(buffout, &itemstring); diff --git a/drivers/misc/gcx/gccore/gcmain.c b/drivers/misc/gcx/gccore/gcmain.c index 03c01eb..6c7f0db 100644 --- a/drivers/misc/gcx/gccore/gcmain.c +++ b/drivers/misc/gcx/gccore/gcmain.c @@ -515,8 +515,8 @@ void gc_commit(struct gccommit *gccommit, bool fromuser) gccorecontext->gcpipe = gccommit->exitpipe; /* Go through all buffers one at a time. */ - gcbuffer = gccommit->buffer; - while (gcbuffer != NULL) { + list_for_each(head, &gccommit->buffer) { + gcbuffer = list_entry(head, struct gcbuffer, link); GCDBG(GCZONE_COMMIT, "gcbuffer = 0x%08X\n", (unsigned int) gcbuffer); @@ -552,12 +552,9 @@ void gc_commit(struct gccommit *gccommit, bool fromuser) } /* Process fixups. */ - gccommit->gcerror = gcmmu_fixup(gcbuffer->fixuphead, logical); + gccommit->gcerror = gcmmu_fixup(&gcbuffer->fixup, logical); if (gccommit->gcerror != GCERR_NONE) goto exit; - - /* Get the next buffer. */ - gcbuffer = gcbuffer->next; } /* Add the callback. */ diff --git a/drivers/misc/gcx/gccore/gcmmu.c b/drivers/misc/gcx/gccore/gcmmu.c index 7c5a671..98136ca 100644 --- a/drivers/misc/gcx/gccore/gcmmu.c +++ b/drivers/misc/gcx/gccore/gcmmu.c @@ -1194,9 +1194,12 @@ void gcmmu_flush_finalize(struct gccmdbuf *gccmdbuf, GCEXIT(GCZONE_FLUSH); } -enum gcerror gcmmu_fixup(struct gcfixup *fixup, unsigned int *data) +enum gcerror gcmmu_fixup(struct list_head *fixuplist, + unsigned int *data) { enum gcerror gcerror = GCERR_NONE; + struct list_head *head; + struct gcfixup *gcfixup; struct gcfixupentry *table; struct gcmmuarena *arena; unsigned int dataoffset; @@ -1205,20 +1208,15 @@ enum gcerror gcmmu_fixup(struct gcfixup *fixup, unsigned int *data) GCENTER(GCZONE_FIXUP); /* Process fixups. */ - while (fixup != NULL) { - /* Verify fixup pointer. */ - if (!virt_addr_valid(fixup)) { - GCERR("bad fixup @ 0x%08X\n", (unsigned int) fixup); - gcerror = GCERR_OODM; - goto exit; - } + list_for_each(head, fixuplist) { + gcfixup = list_entry(head, struct gcfixup, link); GCDBG(GCZONE_FIXUP, "%d fixup(s) @ 0x%08X\n", - fixup->count, (unsigned int) fixup); + gcfixup->count, (unsigned int) gcfixup); /* Apply fixups. */ - table = fixup->fixup; - for (i = 0; i < fixup->count; i += 1) { + table = gcfixup->fixup; + for (i = 0; i < gcfixup->count; i += 1) { GCDBG(GCZONE_FIXUP, "#%d\n", i); GCDBG(GCZONE_FIXUP, " buffer offset = 0x%08X\n", table->dataoffset * 4); @@ -1249,9 +1247,6 @@ enum gcerror gcmmu_fixup(struct gcfixup *fixup, unsigned int *data) table += 1; } - - /* Get the next fixup. */ - fixup = fixup->next; } exit: diff --git a/drivers/misc/gcx/gccore/gcmmu.h b/drivers/misc/gcx/gccore/gcmmu.h index 226f435..445f7fd 100644 --- a/drivers/misc/gcx/gccore/gcmmu.h +++ b/drivers/misc/gcx/gccore/gcmmu.h @@ -265,6 +265,7 @@ void gcmmu_flush_finalize(struct gccmdbuf *openentry, struct gcmommuflush *flushlogical, unsigned int flushaddress); -enum gcerror gcmmu_fixup(struct gcfixup *fixup, unsigned int *data); +enum gcerror gcmmu_fixup(struct list_head *fixuplist, + unsigned int *data); #endif diff --git a/drivers/misc/gcx/gcioctl/gcif.c b/drivers/misc/gcx/gcioctl/gcif.c index 55a2bf6..b0d2ed9 100644 --- a/drivers/misc/gcx/gcioctl/gcif.c +++ b/drivers/misc/gcx/gcioctl/gcif.c @@ -46,105 +46,147 @@ GCDBG_FILTERDEF(ioctl, GCZONE_NONE, "ioctl", "callback") +static GCDEFINE_LOCK(g_fixuplock); +static GCDEFINE_LOCK(g_bufferlock); +static GCDEFINE_LOCK(g_unmaplock); + +static LIST_HEAD(g_buffervac); /* gcbuffer */ +static LIST_HEAD(g_fixupvac); /* gcfixup */ +static LIST_HEAD(g_unmapvac); /* gcschedunmap */ + /******************************************************************************* * Command buffer copy management. */ -static GCLOCK_TYPE g_lock; -struct gcbuffer *g_buffervacant; -struct gcfixup *g_fixupvacant; - -static enum gcerror alloc_buffer(struct gcbuffer **gcbuffer) +static enum gcerror alloc_fixup(struct gcfixup **gcfixup) { enum gcerror gcerror = GCERR_NONE; - struct gcbuffer *temp; + struct gcfixup *temp; - if (g_buffervacant == NULL) { - temp = kmalloc(sizeof(struct gcbuffer), GFP_KERNEL); + GCLOCK(&g_fixuplock); + + if (list_empty(&g_fixupvac)) { + temp = kmalloc(sizeof(struct gcfixup), GFP_KERNEL); if (temp == NULL) { GCERR("out of memory.\n"); gcerror = GCERR_SETGRP(GCERR_OODM, - GCERR_IOCTL_BUF_ALLOC); + GCERR_IOCTL_FIXUP_ALLOC); goto exit; } } else { - temp = g_buffervacant; - g_buffervacant = g_buffervacant->next; + struct list_head *head; + head = g_fixupvac.next; + temp = list_entry(head, struct gcfixup, link); + list_del(head); } - temp->fixuphead = NULL; - temp->next = NULL; + GCUNLOCK(&g_fixuplock); - *gcbuffer = temp; + INIT_LIST_HEAD(&temp->link); + *gcfixup = temp; exit: return gcerror; } -static enum gcerror alloc_fixup(struct gcfixup **gcfixup) +static void free_fixup(struct gcfixup *gcfixup) +{ + GCLOCK(&g_fixuplock); + list_move(&gcfixup->link, &g_fixupvac); + GCUNLOCK(&g_fixuplock); +} + +static void free_fixup_list(struct list_head *fixuplist) +{ + GCLOCK(&g_fixuplock); + list_splice_init(fixuplist, &g_fixupvac); + GCUNLOCK(&g_fixuplock); +} + +static void free_vacant_fixups(void) +{ + struct list_head *head; + struct gcfixup *gcfixup; + + GCLOCK(&g_fixuplock); + while (!list_empty(&g_fixupvac)) { + head = g_fixupvac.next; + gcfixup = list_entry(head, struct gcfixup, link); + list_del(head); + kfree(gcfixup); + } + GCUNLOCK(&g_fixuplock); +} + +static enum gcerror alloc_buffer(struct gcbuffer **gcbuffer) { enum gcerror gcerror = GCERR_NONE; - struct gcfixup *temp; + struct gcbuffer *temp; - if (g_fixupvacant == NULL) { - temp = kmalloc(sizeof(struct gcfixup), GFP_KERNEL); + GCLOCK(&g_bufferlock); + + if (list_empty(&g_buffervac)) { + temp = kmalloc(sizeof(struct gcbuffer), GFP_KERNEL); if (temp == NULL) { GCERR("out of memory.\n"); gcerror = GCERR_SETGRP(GCERR_OODM, - GCERR_IOCTL_FIXUP_ALLOC); + GCERR_IOCTL_BUF_ALLOC); goto exit; } } else { - temp = g_fixupvacant; - g_fixupvacant = g_fixupvacant->next; + struct list_head *head; + head = g_buffervac.next; + temp = list_entry(head, struct gcbuffer, link); + list_del(head); } - *gcfixup = temp; + GCUNLOCK(&g_bufferlock); + + INIT_LIST_HEAD(&temp->fixup); + INIT_LIST_HEAD(&temp->link); + *gcbuffer = temp; exit: return gcerror; } -static void free_buffer_tree(struct gcbuffer *gcbuffer) +static void free_buffer(struct gcbuffer *gcbuffer) { - struct gcbuffer *prev; - struct gcbuffer *curr; - - prev = NULL; - curr = gcbuffer; - while (curr != NULL) { - if (curr->fixuphead != NULL) { - curr->fixuptail->next = g_fixupvacant; - g_fixupvacant = curr->fixuphead; - } + /* Free fixups. */ + free_fixup_list(&gcbuffer->fixup); - prev = curr; - curr = curr->next; - } - - prev->next = g_buffervacant; - g_buffervacant = gcbuffer; + /* Free the buffer. */ + GCLOCK(&g_bufferlock); + list_move(&gcbuffer->link, &g_buffervac); + GCUNLOCK(&g_bufferlock); } -static void destroy_buffer(void) +static void free_buffer_list(struct list_head *bufferlist) { - struct gcbuffer *currbuffer, *tempbuffer; - struct gcfixup *currfixup, *tempfixup; + struct list_head *head; + struct gcbuffer *gcbuffer; - currbuffer = g_buffervacant; - while (currbuffer != NULL) { - tempbuffer = currbuffer; - currbuffer = currbuffer->next; - kfree(tempbuffer); + while (!list_empty(bufferlist)) { + head = bufferlist->next; + gcbuffer = list_entry(head, struct gcbuffer, link); + free_buffer(gcbuffer); } +} - currfixup = g_fixupvacant; - while (currfixup != NULL) { - tempfixup = currfixup; - currfixup = currfixup->next; - kfree(tempfixup); +static void free_vacant_buffers(void) +{ + struct list_head *head; + struct gcbuffer *gcbuffer; + + GCLOCK(&g_bufferlock); + while (!list_empty(&g_buffervac)) { + head = g_buffervac.next; + gcbuffer = list_entry(head, struct gcbuffer, link); + list_del(head); + kfree(gcbuffer); } + GCUNLOCK(&g_bufferlock); } @@ -152,13 +194,13 @@ static void destroy_buffer(void) * Unmap list management. */ -static LIST_HEAD(g_unmapvac); - static enum gcerror alloc_schedunmap(struct gcschedunmap **gcschedunmap) { enum gcerror gcerror = GCERR_NONE; struct gcschedunmap *temp; + GCLOCK(&g_unmaplock); + if (list_empty(&g_unmapvac)) { temp = kmalloc(sizeof(struct gcschedunmap), GFP_KERNEL); if (temp == NULL) { @@ -174,23 +216,42 @@ static enum gcerror alloc_schedunmap(struct gcschedunmap **gcschedunmap) list_del(head); } + GCUNLOCK(&g_unmaplock); + + INIT_LIST_HEAD(&temp->link); *gcschedunmap = temp; exit: return gcerror; } -static void destroy_unmap(void) +static void free_schedunmap(struct gcschedunmap *gcschedunmap) +{ + GCLOCK(&g_unmaplock); + list_move(&gcschedunmap->link, &g_unmapvac); + GCUNLOCK(&g_unmaplock); +} + +static void free_schedunmap_list(struct list_head *schedunmaplist) +{ + GCLOCK(&g_unmaplock); + list_splice_init(schedunmaplist, &g_unmapvac); + GCUNLOCK(&g_unmaplock); +} + +static void free_vacant_unmap(void) { struct list_head *head; struct gcschedunmap *gcschedunmap; + GCLOCK(&g_unmaplock); while (!list_empty(&g_unmapvac)) { head = g_unmapvac.next; gcschedunmap = list_entry(head, struct gcschedunmap, link); list_del(head); kfree(gcschedunmap); } + GCUNLOCK(&g_unmaplock); } @@ -385,19 +446,24 @@ static void destroy_callback(void) static int gc_commit_wrapper(struct gccommit *gccommit) { int ret = 0; - bool locked = false; + bool buffercopied = false; bool unmapcopied = false; struct gccommit cpcommit; - struct gcbuffer *cpbuffer = NULL, *gcbuffer; - struct gcbuffer *headbuffer = NULL, *tailbuffer; - struct gcfixup *cpfixup = NULL, *gcfixup; - struct gcfixupentry *gcfixupentry; - struct gcschedunmap *cpschedunmap, *gcschedunmap; struct gccallbackinfo *gccallbackinfo; - struct list_head *head; - LIST_HEAD(cpunmap); + + struct list_head *gcbufferhead; + struct gcbuffer *cpbuffer, *gcbuffer; + LIST_HEAD(cpbufferlist); + + struct list_head *gcfixuphead; + struct gcfixup *cpfixup, *gcfixup; + struct gcfixupentry *gcfixupentry; int tablesize; + struct list_head *gcschedunmaphead; + struct gcschedunmap *cpschedunmap, *gcschedunmap; + LIST_HEAD(cpunmaplist); + GCENTER(GCZONE_COMMIT); /* Get IOCTL parameters. */ @@ -407,12 +473,10 @@ static int gc_commit_wrapper(struct gccommit *gccommit) goto exit; } - GCLOCK(&g_lock); - locked = true; - - /* Make a copy of the user buffer structures. */ - gcbuffer = cpcommit.buffer; - while (gcbuffer != NULL) { + /* Make a copy of the user buffer list. */ + gcbufferhead = cpcommit.buffer.next; + while (gcbufferhead != &gccommit->buffer) { + gcbuffer = list_entry(gcbufferhead, struct gcbuffer, link); GCDBG(GCZONE_COMMIT, "copying buffer 0x%08X.\n", (unsigned int) gcbuffer); @@ -421,31 +485,26 @@ static int gc_commit_wrapper(struct gccommit *gccommit) if (cpcommit.gcerror != GCERR_NONE) goto exit; - /* Add to the list. */ - if (headbuffer == NULL) - headbuffer = cpbuffer; - else - tailbuffer->next = cpbuffer; - tailbuffer = cpbuffer; - /* Get the data from the user. */ if (copy_from_user(cpbuffer, gcbuffer, sizeof(struct gcbuffer))) { + free_buffer(cpbuffer); GCERR("failed to read data.\n"); cpcommit.gcerror = GCERR_USER_READ; goto exit; } /* Get the next user buffer. */ - gcbuffer = cpbuffer->next; - cpbuffer->next = NULL; + gcbufferhead = cpbuffer->link.next; - /* Get fixups and reset them in the kernel copy. */ - gcfixup = cpbuffer->fixuphead; - cpbuffer->fixuphead = NULL; + /* Add the buffer to the list. */ + list_add_tail(&cpbuffer->link, &cpbufferlist); /* Copy all fixups. */ - while (gcfixup != NULL) { + gcfixuphead = cpbuffer->fixup.next; + INIT_LIST_HEAD(&cpbuffer->fixup); + while (gcfixuphead != &gcbuffer->fixup) { + gcfixup = list_entry(gcfixuphead, struct gcfixup, link); GCDBG(GCZONE_COMMIT, "copying fixup 0x%08X.\n", (unsigned int) gcfixup); @@ -454,28 +513,24 @@ static int gc_commit_wrapper(struct gccommit *gccommit) if (cpcommit.gcerror != GCERR_NONE) goto exit; - /* Add to the list. */ - if (cpbuffer->fixuphead == NULL) - cpbuffer->fixuphead = cpfixup; - else - cpbuffer->fixuptail->next = cpfixup; - cpbuffer->fixuptail = cpfixup; - /* Get the size of the fixup array. */ if (copy_from_user(cpfixup, gcfixup, offsetof(struct gcfixup, fixup))) { + free_fixup(cpfixup); GCERR("failed to read data.\n"); cpcommit.gcerror = GCERR_USER_READ; goto exit; } + /* Get the next fixup. */ + gcfixuphead = cpfixup->link.next; + + /* Add to the list. */ + list_add_tail(&cpfixup->link, &cpbuffer->fixup); + /* Get the fixup array. */ gcfixupentry = gcfixup->fixup; - /* Get the next fixup. */ - gcfixup = cpfixup->next; - cpfixup->next = NULL; - /* Compute the size of the fixup table. */ tablesize = cpfixup->count * sizeof(struct gcfixupentry); @@ -490,12 +545,19 @@ static int gc_commit_wrapper(struct gccommit *gccommit) } } + /* Move the local list to the commit structure. */ + INIT_LIST_HEAD(&cpcommit.buffer); + list_splice_init(&cpbufferlist, &cpcommit.buffer); + buffercopied = true; + /* Copy scheduled unmappings to the local list. */ GCDBG(GCZONE_COMMIT, "copying unmaps.\n"); - head = cpcommit.unmap.next; - while (head != &gccommit->unmap) { + gcschedunmaphead = cpcommit.unmap.next; + while (gcschedunmaphead != &gccommit->unmap) { /* Get a pointer to the user structure. */ - gcschedunmap = list_entry(head, struct gcschedunmap, link); + gcschedunmap = list_entry(gcschedunmaphead, + struct gcschedunmap, + link); GCDBG(GCZONE_COMMIT, "unmap 0x%08X.\n", (unsigned int) gcschedunmap); @@ -507,27 +569,24 @@ static int gc_commit_wrapper(struct gccommit *gccommit) /* Copy unmap record from user. */ if (copy_from_user(cpschedunmap, gcschedunmap, sizeof(struct gcschedunmap))) { - list_add(&cpschedunmap->link, &cpunmap); + free_schedunmap(cpschedunmap); GCERR("failed to read data.\n"); cpcommit.gcerror = GCERR_USER_READ; goto exit; } /* Get the next record. */ - head = cpschedunmap->link.next; + gcschedunmaphead = cpschedunmap->link.next; /* Append to the list. */ - list_add_tail(&cpschedunmap->link, &cpunmap); + list_add_tail(&cpschedunmap->link, &cpunmaplist); } /* Move the local list to the commit structure. */ INIT_LIST_HEAD(&cpcommit.unmap); - list_splice_init(&cpunmap, &cpcommit.unmap); + list_splice_init(&cpunmaplist, &cpcommit.unmap); unmapcopied = true; - GCUNLOCK(&g_lock); - locked = false; - /* Setup callback. */ if (cpcommit.callback != NULL) { GCDBG(GCZONE_COMMIT, "setting up callback.\n"); @@ -550,7 +609,6 @@ static int gc_commit_wrapper(struct gccommit *gccommit) } /* Call the core driver. */ - cpcommit.buffer = headbuffer; gc_commit(&cpcommit, true); exit: @@ -561,12 +619,8 @@ exit: } /* Free temporary resources. */ - if (!locked) - GCLOCK(&g_lock); - if (headbuffer != NULL) - free_buffer_tree(headbuffer); - list_splice(unmapcopied ? &cpcommit.unmap : &cpunmap, &g_unmapvac); - GCUNLOCK(&g_lock); + free_buffer_list(buffercopied ? &cpcommit.buffer : &cpbufferlist); + free_schedunmap_list(unmapcopied ? &cpcommit.unmap : &cpunmaplist); GCEXIT(GCZONE_COMMIT); return ret; @@ -959,7 +1013,6 @@ static int mod_init(void) goto failed; } - GCLOCK_INIT(&g_lock); GCDBG_REGISTER(ioctl); GCDBG(GCZONE_INIT, "device number = %d\n", dev_major); @@ -997,8 +1050,9 @@ static void mod_exit(void) platform_driver_unregister(&gcx_drv); driver_remove_file(&gcx_drv.driver, &driver_attr_version); - destroy_buffer(); - destroy_unmap(); + free_vacant_buffers(); + free_vacant_fixups(); + free_vacant_unmap(); destroy_callback(); } |