diff options
author | Craig Stout <craig.stout@ti.com> | 2012-06-14 11:10:30 -0700 |
---|---|---|
committer | Craig Stout <craig.stout@ti.com> | 2012-06-14 20:08:19 -0700 |
commit | 8b1254def8dfc3d843bc22acc3c66295d42d1718 (patch) | |
tree | 2f706e0dddf53a979b344b91242436d25c24fc47 | |
parent | 6878136fd3840c22571cf5d1925d2b2a769dace6 (diff) | |
download | hardware_ti_omap4-8b1254def8dfc3d843bc22acc3c66295d42d1718.zip hardware_ti_omap4-8b1254def8dfc3d843bc22acc3c66295d42d1718.tar.gz hardware_ti_omap4-8b1254def8dfc3d843bc22acc3c66295d42d1718.tar.bz2 |
bltsville: userspace gc320 implementation.
Change-Id: Ifcb693466f6d3b5cb2232a1cccdf07cfa97bb0c5
Signed-off-by: Craig Stout <craig.stout@ti.com>
-rw-r--r-- | gcbv/Android.mk | 56 | ||||
-rw-r--r-- | gcbv/gc2d.h | 11 | ||||
-rw-r--r-- | gcbv/gcbv.c | 3207 | ||||
-rw-r--r-- | gcbv/gcioctl.h | 137 | ||||
-rw-r--r-- | gcbv/gcmain.c | 287 | ||||
-rw-r--r-- | gcbv/gcmain.h | 54 | ||||
-rw-r--r-- | gcbv/mirror/gcbv.c | 4156 | ||||
-rw-r--r-- | gcbv/mirror/gcdbglog.c | 1696 | ||||
-rw-r--r-- | gcbv/mirror/include/cache-2dmanager.h | 103 | ||||
-rw-r--r-- | gcbv/mirror/include/gcdbglog.h | 412 | ||||
-rw-r--r-- | gcbv/mirror/include/gcerror.h (renamed from gcbv/gcerror.h) | 97 | ||||
-rw-r--r-- | gcbv/mirror/include/gcioctl.h | 263 | ||||
-rw-r--r-- | gcbv/mirror/include/gclist.h | 630 | ||||
-rw-r--r-- | gcbv/mirror/include/gcreg.h (renamed from gcbv/gcreg.h) | 903 | ||||
-rw-r--r-- | gcbv/mirror/include/gcx.h | 100 | ||||
-rw-r--r-- | gcbv/version.h (renamed from gcbv/gcx.h) | 19 |
16 files changed, 8495 insertions, 3636 deletions
diff --git a/gcbv/Android.mk b/gcbv/Android.mk new file mode 100644 index 0000000..706ea27 --- /dev/null +++ b/gcbv/Android.mk @@ -0,0 +1,56 @@ +# +# Copyright (c) 2012, +# Texas Instruments, Inc. and Vivante Corporation. +# +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Texas Instruments, Inc. 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 TEXAS INSTRUMENTS, INC. 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. +# + +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) +LOCAL_SRC_FILES := \ + gcmain.c \ + mirror/gcbv.c \ + mirror/gcdbglog.c + +LOCAL_CFLAGS := + +LOCAL_C_INCLUDES := \ + $(LOCAL_PATH)/mirror/include \ + external/bltsville/bltsville/include \ + external/bltsville/ocd/include + +VERSION_H := external/bltsville/gcbv/version.h +BV_VERSION := $(shell grep "VER_FILEVERSION_STR" $(VERSION_H) | sed "s,.*\"\([0-9.]*\)\\\0.*,\1,") + +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE := libbltsville_gc2d +LOCAL_MODULE_SUFFIX := .$(BV_VERSION).so +LOCAL_PRELINK_MODULE := false +LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/../vendor/lib + +$(shell ln -fs ./libbltsville_gc2d.$(BV_VERSION).so $(LOCAL_MODULE_PATH)/libbltsville_gc2d.so) +$(shell ln -fs ./libbltsville_gc2d.so $(LOCAL_MODULE_PATH)/libbltsville_hw2d.so) + +include $(BUILD_SHARED_LIBRARY) diff --git a/gcbv/gc2d.h b/gcbv/gc2d.h index 2a10b6e..66b40ab 100644 --- a/gcbv/gc2d.h +++ b/gcbv/gc2d.h @@ -1,5 +1,7 @@ /* - * Copyright (c) 2011, Texas Instruments, Inc. + * Copyright (c) 2012, + * Texas Instruments, Inc. and Vivante Corporation + * * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -32,8 +34,9 @@ #include <bvinternal.h> #include <ocd.h> -enum bverror bv_map(struct bvbuffdesc *buffdesc); -enum bverror bv_unmap(struct bvbuffdesc *buffdesc); -enum bverror bv_blt(struct bvbltparams *bltparams); +enum bverror gcbv_map(struct bvbuffdesc *buffdesc); +enum bverror gcbv_unmap(struct bvbuffdesc *buffdesc); +enum bverror gcbv_blt(struct bvbltparams *bltparams); +enum bverror gcbv_cache(struct bvcopparams *copparams); #endif diff --git a/gcbv/gcbv.c b/gcbv/gcbv.c deleted file mode 100644 index a1a442c..0000000 --- a/gcbv/gcbv.c +++ /dev/null @@ -1,3207 +0,0 @@ -/* - * 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 <gcx.h> -#include <gcioctl.h> -#include <gc2d.h> -#include "gcmain.h" - -#ifndef GC_DUMP -# define GC_DUMP 0 -#endif - -#if GC_DUMP -# define GC_PRINT gcdump -#else -# define GC_PRINT(...) -#endif - -/******************************************************************************* -** Miscellaneous defines and macros. -*/ - -#define EQ_ORIGIN(rect1, rect2) \ -( \ - (rect1.left == rect2.left) && (rect1.top == rect2.top) \ -) - -#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 GC_BASE_ALIGN 16 - -#define GPU_CMD_SIZE (sizeof(unsigned int) * 2) - -/******************************************************************************* -** Internal structures. -*/ - -/* Used by blitters to define an array of valid sources. */ -struct srcdesc { - int index; - union bvinbuff buf; - struct bvsurfgeom *geom; - struct bvrect *rect; -}; - -/* bvbuffmap struct attachment. */ -struct bvbuffmapinfo { - unsigned long handle; /* Mapped handle for the buffer. */ - - int usermap; /* Number of times the client explicitely - mapped this buffer. */ - - int automap; /* Number of times automapping happened. */ -}; - -/* Defines a link list of scheduled unmappings. */ -struct gcschedunmap { - struct bvbuffdesc *bvbuffdesc; - struct gcschedunmap *next; -}; - -/* Operation finalization call. */ -struct gcbatch; -typedef enum bverror (*gcbatchend) (struct bvbltparams *bltparams, - struct gcbatch *batch); - -/* Blit states. */ -struct gcblit { - unsigned int srccount; - struct gccmdstartderect dstrect; -}; - -/* Batch header. */ -struct gcbatch { - unsigned int structsize; /* Used to ID structure version. */ - - gcbatchend batchend; /* Pointer to the function to finilize - the current operation. */ - union { - struct gcblit gcblit; - } op; /* States of the current operation. */ - - unsigned int size; /* Total size of the command buffer. */ - - struct gcbuffer *bufhead; /* Command buffer list. */ - struct gcbuffer *buftail; - - struct gcschedunmap *unmap; /* Scheduled unmappings. */ -}; - -/* Vacant batch header. */ -struct gcvacbatch { - struct gcvacbatch *next; -}; - -/* Driver context. */ -struct gccontext { - char bverrorstr[128]; /* Last generated error message. */ - - struct bvbuffmap *vac_buffmap; /* Vacant mappping structures. */ - struct gcschedunmap *vac_unmap; /* Vacant unmapping structures. */ - - struct gcbuffer *vac_buffers; /* Vacant command buffers. */ - struct gcfixup *vac_fixups; /* Vacant fixups. */ - struct gcvacbatch *vac_batches; /* Vacant batches. */ -}; - -static struct gccontext gccontext; - -/******************************************************************************* - * Debugging. - */ - -#if GC_DUMP -static void dumpbuffer(struct gcbatch *batch) -{ - unsigned int bufcount = 0; - struct gcbuffer *buffer; - unsigned int datacount, i, j, cmd; - struct gcfixup *fixup; - - GC_PRINT(GC_INFO_MSG " BATCH DUMP (0x%08X)\n", - __func__, __LINE__, (unsigned int) batch); - - buffer = batch->bufhead; - while (buffer != NULL) { - GC_PRINT(GC_INFO_MSG " Command buffer #%d (0x%08X)\n", - __func__, __LINE__, ++bufcount, (unsigned int) buffer); - - fixup = buffer->fixuphead; - while (fixup != NULL) { - GC_PRINT(GC_INFO_MSG - " Fixup table @ 0x%08X, count = %d:\n", - __func__, __LINE__, - (unsigned int) fixup, fixup->count); - - for (i = 0; i < fixup->count; i += 1) { - GC_PRINT(GC_INFO_MSG - " [%02d] buffer offset = 0x%08X, " - "surface offset = 0x%08X\n", - __func__, __LINE__, - i, - fixup->fixup[i].dataoffset * 4, - fixup->fixup[i].surfoffset); - } - - fixup = fixup->next; - } - - datacount = buffer->tail - buffer->head; - for (i = 0; i < datacount;) { - cmd = GETFIELD(buffer->head[i], - GCREG_COMMAND_LOAD_STATE, - COMMAND_OPCODE); - - if (cmd == REGVALUE(GCREG_COMMAND_LOAD_STATE, - COMMAND_OPCODE, LOAD_STATE)) { - unsigned int count, addr; - - count = GETFIELD(buffer->head[i], - GCREG_COMMAND_LOAD_STATE, - COMMAND_COUNT); - - addr = GETFIELD(buffer->head[i], - GCREG_COMMAND_LOAD_STATE, - COMMAND_ADDRESS); - - GC_PRINT(GC_INFO_MSG - " 0x%08X: 0x%08X STATE(0x%04X, %d)\n", - __func__, __LINE__, - (i << 2), buffer->head[i], addr, count); - i += 1; - - count |= 1; - for (j = 0; j < count; i += 1, j += 1) { - GC_PRINT(GC_INFO_MSG " %16c0x%08X\n", - __func__, __LINE__, - ' ', buffer->head[i]); - } - } else if (cmd == REGVALUE(GCREG_COMMAND_START_DE, - COMMAND_OPCODE, START_DE)) { - unsigned int count; - unsigned int x1, y1, x2, y2; - - count = GETFIELD(buffer->head[i], - GCREG_COMMAND_START_DE, - COMMAND_COUNT); - - GC_PRINT(GC_INFO_MSG - " 0x%08X: 0x%08X STARTDE(%d)\n", - __func__, __LINE__, - (i << 2), buffer->head[i], count); - i += 1; - - GC_PRINT(GC_INFO_MSG " %16c0x%08X\n", - __func__, __LINE__, - ' ', buffer->head[i]); - i += 1; - - for (j = 0; j < count; j += 1) { - x1 = GETFIELD(buffer->head[i], - GCREG_COMMAND_TOP_LEFT, X); - y1 = GETFIELD(buffer->head[i], - GCREG_COMMAND_TOP_LEFT, Y); - - GC_PRINT(GC_INFO_MSG - " %16c0x%08X LT(%d,%d)\n", - __func__, __LINE__, - ' ', buffer->head[i], x1, y1); - - i += 1; - - x2 = GETFIELD(buffer->head[i], - GCREG_COMMAND_BOTTOM_RIGHT, X); - y2 = GETFIELD(buffer->head[i], - GCREG_COMMAND_BOTTOM_RIGHT, Y); - - GC_PRINT(GC_INFO_MSG - " %16c0x%08X RB(%d,%d)\n", - __func__, __LINE__, - ' ', buffer->head[i], x2, y2); - - i += 1; - } - } else { - GC_PRINT(GC_INFO_MSG - " unsupported command: %d\n", - __func__, __LINE__, cmd); - } - } - - buffer = buffer->next; - } -} -#endif - -/******************************************************************************* - * Error handling. - */ - -#define SETERROR(message) \ -do { \ - snprintf(gccontext.bverrorstr, sizeof(gccontext.bverrorstr), \ - "%s(%d): " message, __func__, __LINE__); \ - GC_PRINT(GC_ERR_MSG " %s\n", __func__, __LINE__, \ - gccontext.bverrorstr); \ -} while (0) - -#define SETERRORARG(message, arg) \ -do { \ - snprintf(gccontext.bverrorstr, sizeof(gccontext.bverrorstr), \ - "%s(%d): " message, __func__, __LINE__, arg); \ - GC_PRINT(GC_ERR_MSG " %s\n", __func__, __LINE__, \ - gccontext.bverrorstr); \ -} while (0) - -#define BVSETERROR(error, message) \ -do { \ - SETERROR(message); \ - bverror = error; \ -} while (0) - -#define BVSETERRORARG(error, message, arg) \ -do { \ - SETERRORARG(message, arg); \ - bverror = error; \ -} while (0) - -#define BVSETBLTERROR(error, message) \ -do { \ - BVSETERROR(error, message); \ - bltparams->errdesc = gccontext.bverrorstr; \ -} while (0) - -#define BVSETBLTERRORARG(error, message, arg) \ -do { \ - BVSETERRORARG(error, message, arg); \ - bltparams->errdesc = gccontext.bverrorstr; \ -} while (0) - -#define BVSETSURFERROR(errorid, errordesc) \ -do { \ - snprintf(gccontext.bverrorstr, sizeof(gccontext.bverrorstr), \ - g_surferr[errorid].message, __func__, __LINE__, errordesc.id); \ - GC_PRINT(GC_ERR_MSG " %s\n", __func__, __LINE__, \ - gccontext.bverrorstr); \ - bverror = errordesc.base + g_surferr[errorid].offset; \ -} while (0) - -#define BVSETBLTSURFERROR(errorid, errordesc) \ -do { \ - BVSETSURFERROR(errorid, errordesc); \ - bltparams->errdesc = gccontext.bverrorstr; \ -} while (0) - -#define BVERR_DESC 0 -#define BVERR_DESC_VERS 1 -#define BVERR_DESC_VIRTADDR 2 -#define BVERR_TILE 3 -#define BVERR_TILE_VERS 4 -#define BVERR_TILE_VIRTADDR 5 -#define BVERR_GEOM 6 -#define BVERR_GEOM_VERS 7 -#define BVERR_GEOM_FORMAT 8 - -struct bvsurferrorid { - char *id; - enum bverror base; -}; - -struct bvsurferror { - unsigned int offset; - char *message; -}; - -static struct bvsurferror g_surferr[] = { - /* BVERR_DESC */ - { 0, "%s(%d): %s desc structure is not set" }, - - /* BVERR_DESC_VERS */ - { 100, "%s(%d): %s desc structure has invalid size" }, - - /* BVERR_DESC_VIRTADDR */ - { 200, "%s(%d): %s desc virtual pointer is not set" }, - - /* BVERR_TILE: FIXME/TODO define error code */ - { 0, "%s(%d): %s tileparams structure is not set" }, - - /* BVERR_TILE_VERS */ - { 3000, "%s(%d): %s tileparams structure has invalid size" }, - - /* BVERR_TILE_VIRTADDR: FIXME/TODO define error code */ - { 200, "%s(%d): %s tileparams virtual pointer is not set" }, - - /* BVERR_GEOM */ - { 1000, "%s(%d): %s geom structure is not set" }, - - /* BVERR_GEOM_VERS */ - { 1100, "%s(%d): %s geom structure has invalid size" }, - - /* BVERR_GEOM_FORMAT */ - { 1200, "%s(%d): %s invalid format specified" }, -}; - -static struct bvsurferrorid g_destsurferr = { "dst", BVERR_DSTDESC }; -static struct bvsurferrorid g_src1surferr = { "src1", BVERR_SRC1DESC }; -static struct bvsurferrorid g_src2surferr = { "src2", BVERR_SRC2DESC }; -static struct bvsurferrorid g_masksurferr = { "mask", BVERR_MASKDESC }; - -/******************************************************************************* - * Threads etc... TBD - */ - -#if 0 -#define MAX_THRD 1 -static pthread_t id[MAX_THRD]; - -/* TODO: check that we aren't using more logic than we need */ -static void sig_handler(int sig) -{ - GC_PRINT(GC_INFO_MSG " %s(%d): %lx:%d\n", __func__, __LINE__, - (unsigned long) pthread_self(), sig); - sleep(2); sched_yield(); -} - -/* TODO: check that we aren't using more logic than we need */ -static void *thread(void *p) -{ - int r = 0; - sigset_t set; - struct sigaction sa; - - sigemptyset(&set); - sa.sa_handler = sig_handler; - sa.sa_flags = SA_RESTART; - sigaction(SIGUSR1, &sa, NULL); - - while (1) { - GC_PRINT(GC_INFO_MSG " %s(%d)\n", __func__, __LINE__); - sigwait(&set, &r); - GC_PRINT(GC_INFO_MSG " %s(%d)\n", __func__, __LINE__); - } - - return NULL; -} -#endif - -/******************************************************************************* - * Memory management. - */ - -static enum bverror do_map(struct bvbuffdesc *buffdesc, int client, - struct bvbuffmap **map) -{ - static const int mapsize - = sizeof(struct bvbuffmap) - + sizeof(struct bvbuffmapinfo); - - enum bverror bverror; - struct bvbuffmap *bvbuffmap; - struct bvbuffmapinfo *bvbuffmapinfo; - struct gcmap gcmap; - void *logical; - unsigned int offset; - - /* Try to find existing mapping. */ - bvbuffmap = buffdesc->map; - while (bvbuffmap != NULL) { - if (bvbuffmap->bv_unmap == bv_unmap) - break; - bvbuffmap = bvbuffmap->nextmap; - } - - /* Already mapped? */ - if (bvbuffmap != NULL) { - bvbuffmapinfo = (struct bvbuffmapinfo *) bvbuffmap->handle; - - if (client) - bvbuffmapinfo->usermap += 1; - else - bvbuffmapinfo->automap += 1; - - *map = bvbuffmap; - return BVERR_NONE; - } - - /* 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 exit; - } - - 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; - } - - /* Align the base address as required by 2D hardware. */ - logical = (void *) ((unsigned int) buffdesc->virtaddr - & ~(GC_BASE_ALIGN - 1)); - offset = (unsigned int) buffdesc->virtaddr - & (GC_BASE_ALIGN - 1); - - /* Map the buffer. */ - gcmap.gcerror = GCERR_NONE; - gcmap.logical = logical; - gcmap.size = buffdesc->length + offset; - gcmap.handle = 0; - - gc_map_wrapper(&gcmap); - if (gcmap.gcerror != GCERR_NONE) { - BVSETERRORARG(BVERR_UNK, "mapping error occured (0x%08X)", - gcmap.gcerror); - goto exit; - } - - bvbuffmapinfo = (struct bvbuffmapinfo *) bvbuffmap->handle; - - bvbuffmapinfo->handle = gcmap.handle; - - if (client) { - bvbuffmapinfo->usermap = 1; - bvbuffmapinfo->automap = 0; - } else { - bvbuffmapinfo->usermap = 0; - bvbuffmapinfo->automap = 1; - } - - bvbuffmap->nextmap = buffdesc->map; - buffdesc->map = bvbuffmap; - - *map = bvbuffmap; - return BVERR_NONE; - -exit: - if (bvbuffmap != NULL) { - bvbuffmap->nextmap = gccontext.vac_buffmap; - gccontext.vac_buffmap = bvbuffmap; - } - - return bverror; -} - -static enum bverror do_unmap(struct bvbuffdesc *buffdesc, int client) -{ - enum bverror bverror; - struct bvbuffmap *prev = NULL; - struct bvbuffmap *bvbuffmap; - struct bvbuffmapinfo *bvbuffmapinfo; - struct gcmap gcmap; - - /* Try to find existing mapping. */ - bvbuffmap = buffdesc->map; - while (bvbuffmap != NULL) { - if (bvbuffmap->bv_unmap == bv_unmap) - break; - prev = bvbuffmap; - bvbuffmap = bvbuffmap->nextmap; - } - - /* No mapping found? */ - if (bvbuffmap == NULL) { - bverror = BVERR_NONE; - goto exit; - } - - /* Get the info structure. */ - bvbuffmapinfo = (struct bvbuffmapinfo *) bvbuffmap->handle; - - /* Dereference. */ - if (client) - bvbuffmapinfo->usermap = 0; - else - bvbuffmapinfo->automap -= 1; - - /* Still referenced? */ - if (bvbuffmapinfo->usermap || bvbuffmapinfo->automap) { - bverror = BVERR_NONE; - goto exit; - } - - /* Setup buffer unmapping. */ - gcmap.gcerror = GCERR_NONE; - gcmap.logical = buffdesc->virtaddr; - gcmap.size = buffdesc->length; - gcmap.handle = GET_MAP_HANDLE(bvbuffmap); - - /* Remove mapping record. */ - if (prev == NULL) - buffdesc->map = bvbuffmap->nextmap; - else - prev->nextmap = bvbuffmap->nextmap; - - bvbuffmap->nextmap = gccontext.vac_buffmap; - gccontext.vac_buffmap = bvbuffmap; - - /* Unmap the buffer. */ - gc_unmap_wrapper(&gcmap); - if (gcmap.gcerror != GCERR_NONE) { - BVSETERRORARG(BVERR_UNK, "unmapping error occured (0x%08X)", - gcmap.gcerror); - goto exit; - } - - bverror = BVERR_NONE; - -exit: - return bverror; -} - -static enum bverror schedule_unmap(struct gcbatch *batch, - struct bvbuffdesc *buffdesc) -{ - enum bverror bverror; - struct gcschedunmap *gcschedunmap; - - if (gccontext.vac_unmap == NULL) { - gcschedunmap = gcalloc(struct gcschedunmap, - sizeof(struct gcschedunmap)); - if (gcschedunmap == NULL) { - BVSETERROR(BVERR_OOM, "failed to schedule unmapping"); - goto exit; - } - } else { - gcschedunmap = gccontext.vac_unmap; - gccontext.vac_unmap = gcschedunmap->next; - } - - gcschedunmap->bvbuffdesc = buffdesc; - gcschedunmap->next = batch->unmap; - batch->unmap = gcschedunmap; - - bverror = BVERR_NONE; - -exit: - return bverror; -} - -static enum bverror process_scheduled_unmap(struct gcbatch *batch) -{ - enum bverror bverror = BVERR_NONE; - struct gcschedunmap *gcschedunmap; - - while (batch->unmap != NULL) { - gcschedunmap = batch->unmap; - - bverror = do_unmap(gcschedunmap->bvbuffdesc, 0); - if (bverror != BVERR_NONE) - break; - - batch->unmap = gcschedunmap->next; - gcschedunmap->next = gccontext.vac_unmap; - gccontext.vac_unmap = gcschedunmap; - } - - return bverror; -} - -/******************************************************************************* - * Batch memory manager. - */ - -static enum bverror allocate_batch(struct gcbatch **batch); -static void free_batch(struct gcbatch *batch); -static enum bverror append_buffer(struct gcbatch *batch); - -static enum bverror do_end(struct bvbltparams *bltparams, - struct gcbatch *batch) -{ - GC_PRINT(GC_INFO_MSG " dummy operation end\n", __func__, __LINE__); - return BVERR_NONE; -} - -static enum bverror allocate_batch(struct gcbatch **batch) -{ - enum bverror bverror; - struct gcbatch *temp; - - if (gccontext.vac_batches == NULL) { - temp = gcalloc(struct gcbatch, sizeof(struct gcbatch)); - if (temp == NULL) { - BVSETERROR(BVERR_OOM, - "batch header allocation failed"); - goto exit; - } - } else { - temp = (struct gcbatch *) gccontext.vac_batches; - gccontext.vac_batches = gccontext.vac_batches->next; - } - - memset(temp, 0, sizeof(struct gcbatch)); - temp->structsize = sizeof(struct gcbatch); - temp->batchend = do_end; - - bverror = append_buffer(temp); - if (bverror != BVERR_NONE) { - free_batch(temp); - goto exit; - } - - *batch = temp; - -exit: - return bverror; -} - -static void free_batch(struct gcbatch *batch) -{ - struct gcbuffer *buffer; - - 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; -} - -static enum bverror append_buffer(struct gcbatch *batch) -{ - enum bverror bverror; - struct gcbuffer *temp; - - GC_PRINT(GC_INFO_MSG " batch = 0x%08X\n", - __func__, __LINE__, (unsigned int) batch); - - if (gccontext.vac_buffers == NULL) { - temp = gcalloc(struct gcbuffer, GC_BUFFER_SIZE); - if (temp == NULL) { - BVSETERROR(BVERR_OOM, - "command buffer allocation failed"); - goto exit; - } - } else { - temp = gccontext.vac_buffers; - gccontext.vac_buffers = temp->next; - } - - memset(temp, 0, sizeof(struct gcbuffer)); - temp->head = - temp->tail = (unsigned int *) (temp + 1); - temp->available = GC_BUFFER_SIZE - sizeof(struct gcbuffer); - - if (batch->bufhead == NULL) - batch->bufhead = temp; - else - batch->buftail->next = temp; - batch->buftail = temp; - - GC_PRINT(GC_INFO_MSG " new buffer appended = 0x%08X\n", - __func__, __LINE__, (unsigned int) temp); - - bverror = BVERR_NONE; - -exit: - return bverror; -} - -static enum bverror add_fixup(struct gcbatch *batch, unsigned int *fixup, - unsigned int surfoffset) -{ - enum bverror bverror; - struct gcbuffer *buffer; - struct gcfixup *temp; - - GC_PRINT(GC_INFO_MSG " batch = 0x%08X, fixup ptr = 0x%08X\n", - __func__, __LINE__, (unsigned int) batch, (unsigned int) fixup); - - buffer = batch->buftail; - temp = buffer->fixuptail; - - GC_PRINT(GC_INFO_MSG " buffer = 0x%08X, fixup struct = 0x%08X\n", - __func__, __LINE__, (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) { - BVSETERROR(BVERR_OOM, - "fixup allocation failed"); - goto exit; - } - } else { - temp = gccontext.vac_fixups; - gccontext.vac_fixups = temp->next; - } - - temp->next = NULL; - temp->count = 0; - - if (buffer->fixuphead == NULL) - buffer->fixuphead = temp; - else - buffer->fixuptail->next = temp; - buffer->fixuptail = temp; - - GC_PRINT(GC_INFO_MSG " new fixup struct allocated = 0x%08X\n", - __func__, __LINE__, (unsigned int) temp); - - } else { - GC_PRINT(GC_INFO_MSG " fixups accumulated = %d\n", - __func__, __LINE__, temp->count); - } - - temp->fixup[temp->count].dataoffset = fixup - buffer->head; - temp->fixup[temp->count].surfoffset = surfoffset; - temp->count += 1; - - GC_PRINT(GC_INFO_MSG " fixup offset = 0x%08X\n", - __func__, __LINE__, fixup - buffer->head); - GC_PRINT(GC_INFO_MSG " surface offset = 0x%08X\n", - __func__, __LINE__, surfoffset); - - bverror = BVERR_NONE; - -exit: - return bverror; -} - -static enum bverror claim_buffer(struct gcbatch *batch, - unsigned int size, - void **buffer) -{ - enum bverror bverror; - struct gcbuffer *curbuf; - - /* Get the current command buffer. */ - curbuf = batch->buftail; - - GC_PRINT(GC_INFO_MSG " batch = 0x%08X, buffer = 0x%08X\n", - __func__, __LINE__, - (unsigned int) batch, (unsigned int) curbuf); - - GC_PRINT(GC_INFO_MSG " available = %d, requested = %d\n", - __func__, __LINE__, curbuf->available, size); - - if (curbuf->available < size) { - bverror = append_buffer(batch); - if (bverror != BVERR_NONE) - goto exit; - - curbuf = batch->buftail; - } - - *buffer = curbuf->tail; - curbuf->tail = (unsigned int *) ((unsigned char *) curbuf->tail + size); - curbuf->available -= size; - batch->size += size; - bverror = BVERR_NONE; - -exit: - 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) - -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 { - unsigned bitspp; - unsigned format; - unsigned swizzle; - struct bvcsrgb rgba; -}; - -#define BVFORMATRGBA(BPP, Format, Swizzle, R, G, B, A) \ -{ \ - 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 } } } - -static struct bvformatxlate formatxlate[] = { - /* BITS=12 ALPHA=0 REVERSED=0 LEFT_JUSTIFIED=0 */ - BVFORMATRGBA(16, X4R4G4B4, RGBA, - BVRED(12, 4), BVGREEN(8, 4), BVBLUE(4, 4), BVALPHA(0, 0)), - - /* BITS=12 ALPHA=0 REVERSED=0 LEFT_JUSTIFIED=1 */ - BVFORMATRGBA(16, X4R4G4B4, ARGB, - BVRED(8, 4), BVGREEN(4, 4), BVBLUE(0, 4), BVALPHA(12, 0)), - - /* BITS=12 ALPHA=0 REVERSED=1 LEFT_JUSTIFIED=0 */ - BVFORMATRGBA(16, X4R4G4B4, BGRA, - BVRED(4, 4), BVGREEN(8, 4), BVBLUE(12, 4), BVALPHA(0, 0)), - - /* BITS=12 ALPHA=0 REVERSED=1 LEFT_JUSTIFIED=1 */ - BVFORMATRGBA(16, X4R4G4B4, ABGR, - BVRED(0, 4), BVGREEN(4, 4), BVBLUE(8, 4), BVALPHA(12, 0)), - - /* BITS=12 ALPHA=1 REVERSED=0 LEFT_JUSTIFIED=0 */ - BVFORMATRGBA(16, A4R4G4B4, RGBA, - BVRED(12, 4), BVGREEN(8, 4), BVBLUE(4, 4), BVALPHA(0, 4)), - - /* BITS=12 ALPHA=1 REVERSED=0 LEFT_JUSTIFIED=1 */ - BVFORMATRGBA(16, A4R4G4B4, ARGB, - BVRED(8, 4), BVGREEN(4, 4), BVBLUE(0, 4), BVALPHA(12, 4)), - - /* BITS=12 ALPHA=1 REVERSED=1 LEFT_JUSTIFIED=0 */ - BVFORMATRGBA(16, A4R4G4B4, BGRA, - BVRED(4, 4), BVGREEN(8, 4), BVBLUE(12, 4), BVALPHA(0, 4)), - - /* BITS=12 ALPHA=1 REVERSED=1 LEFT_JUSTIFIED=1 */ - BVFORMATRGBA(16, A4R4G4B4, ABGR, - BVRED(0, 4), BVGREEN(4, 4), BVBLUE(8, 4), BVALPHA(12, 4)), - - /***********************************************/ - - /* BITS=15 ALPHA=0 REVERSED=0 LEFT_JUSTIFIED=0 */ - BVFORMATRGBA(16, X1R5G5B5, RGBA, - BVRED(11, 5), BVGREEN(6, 5), BVBLUE(1, 5), BVALPHA(0, 0)), - - /* BITS=15 ALPHA=0 REVERSED=0 LEFT_JUSTIFIED=1 */ - BVFORMATRGBA(16, X1R5G5B5, ARGB, - BVRED(10, 5), BVGREEN(5, 5), BVBLUE(0, 5), BVALPHA(15, 0)), - - /* BITS=15 ALPHA=0 REVERSED=1 LEFT_JUSTIFIED=0 */ - BVFORMATRGBA(16, X1R5G5B5, BGRA, - BVRED(1, 5), BVGREEN(6, 5), BVBLUE(11, 5), BVALPHA(0, 0)), - - /* BITS=15 ALPHA=0 REVERSED=1 LEFT_JUSTIFIED=1 */ - BVFORMATRGBA(16, X1R5G5B5, ABGR, - BVRED(0, 5), BVGREEN(5, 5), BVBLUE(10, 5), BVALPHA(15, 0)), - - /* BITS=15 ALPHA=1 REVERSED=0 LEFT_JUSTIFIED=0 */ - BVFORMATRGBA(16, A1R5G5B5, RGBA, - BVRED(11, 5), BVGREEN(6, 5), BVBLUE(1, 5), BVALPHA(0, 1)), - - /* BITS=15 ALPHA=1 REVERSED=0 LEFT_JUSTIFIED=1 */ - BVFORMATRGBA(16, A1R5G5B5, ARGB, - BVRED(10, 5), BVGREEN(5, 5), BVBLUE(0, 5), BVALPHA(15, 1)), - - /* BITS=15 ALPHA=1 REVERSED=1 LEFT_JUSTIFIED=0 */ - BVFORMATRGBA(16, A1R5G5B5, BGRA, - BVRED(1, 5), BVGREEN(6, 5), BVBLUE(11, 5), BVALPHA(0, 1)), - - /* BITS=15 ALPHA=1 REVERSED=1 LEFT_JUSTIFIED=1 */ - BVFORMATRGBA(16, A1R5G5B5, ABGR, - BVRED(0, 5), BVGREEN(5, 5), BVBLUE(10, 5), BVALPHA(15, 1)), - - /***********************************************/ - - /* 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)), - - /* 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)), - - /* 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)), - - /* 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)), - - /* BITS=16 ALPHA=1 REVERSED=0 LEFT_JUSTIFIED=0 */ - BVFORMATINVALID, - - /* BITS=16 ALPHA=1 REVERSED=0 LEFT_JUSTIFIED=1 */ - BVFORMATINVALID, - - /* BITS=16 ALPHA=1 REVERSED=1 LEFT_JUSTIFIED=0 */ - BVFORMATINVALID, - - /* BITS=16 ALPHA=1 REVERSED=1 LEFT_JUSTIFIED=1 */ - BVFORMATINVALID, - - /***********************************************/ - - /* BITS=24 ALPHA=0 REVERSED=0 LEFT_JUSTIFIED=0 */ - BVFORMATRGBA(32, X8R8G8B8, RGBA, - BVRED(24, 8), BVGREEN(16, 8), BVBLUE(8, 8), BVALPHA(0, 0)), - - /* BITS=24 ALPHA=0 REVERSED=0 LEFT_JUSTIFIED=1 */ - BVFORMATRGBA(32, X8R8G8B8, ARGB, - BVRED(16, 8), BVGREEN(8, 8), BVBLUE(0, 8), BVALPHA(0, 0)), - - /* BITS=24 ALPHA=0 REVERSED=1 LEFT_JUSTIFIED=0 */ - BVFORMATRGBA(32, X8R8G8B8, BGRA, - BVRED(8, 8), BVGREEN(16, 8), BVBLUE(24, 8), BVALPHA(0, 0)), - - /* BITS=24 ALPHA=0 REVERSED=1 LEFT_JUSTIFIED=1 */ - BVFORMATRGBA(32, X8R8G8B8, ABGR, - BVRED(0, 8), BVGREEN(8, 8), BVBLUE(16, 8), BVALPHA(0, 0)), - - /* BITS=24 ALPHA=1 REVERSED=0 LEFT_JUSTIFIED=0 */ - BVFORMATRGBA(32, A8R8G8B8, RGBA, - BVRED(24, 8), BVGREEN(16, 8), BVBLUE(8, 8), BVALPHA(0, 8)), - - /* BITS=24 ALPHA=1 REVERSED=0 LEFT_JUSTIFIED=1 */ - BVFORMATRGBA(32, A8R8G8B8, ARGB, - BVRED(16, 8), BVGREEN(8, 8), BVBLUE(0, 8), BVALPHA(24, 8)), - - /* BITS=24 ALPHA=1 REVERSED=1 LEFT_JUSTIFIED=0 */ - BVFORMATRGBA(32, A8R8G8B8, BGRA, - BVRED(8, 8), BVGREEN(16, 8), BVBLUE(24, 8), BVALPHA(0, 8)), - - /* BITS=24 ALPHA=1 REVERSED=1 LEFT_JUSTIFIED=1 */ - BVFORMATRGBA(32, A8R8G8B8, ABGR, - BVRED(0, 8), BVGREEN(8, 8), BVBLUE(16, 8), BVALPHA(24, 0)), -}; - -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; - - GC_PRINT(GC_INFO_MSG " ocdformat = 0x%08X\n", - __func__, __LINE__, 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; - - switch (cs) { - case (OCDFMTDEF_CS_RGB >> OCDFMTDEF_CS_SHIFT): - GC_PRINT(GC_INFO_MSG " OCDFMTDEF_CS_RGB\n", - __func__, __LINE__); - - GC_PRINT(GC_INFO_MSG " bits = %d\n", - __func__, __LINE__, bits); - - GC_PRINT(GC_INFO_MSG " cont = %d\n", - __func__, __LINE__, 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; - - GC_PRINT(GC_INFO_MSG " swizzle = %d\n", - __func__, __LINE__, swizzle); - - GC_PRINT(GC_INFO_MSG " alpha = %d\n", - __func__, __LINE__, 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; - } - - GC_PRINT(GC_INFO_MSG " index = %d\n", - __func__, __LINE__, index); - - break; - - default: - return 0; - } - - if (formatxlate[index].bitspp != containers[cont]) - return 0; - - *format = &formatxlate[index]; - - 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; - - switch (desc->size) { - case 0: - component8 = 0xFF; - break; - - case 1: - component8 = component ? 0xFF : 0x00; - break; - - case 4: - component8 = component | (component << 4); - break; - - case 5: - component8 = (component << 3) | (component >> 2); - break; - - case 6: - component8 = (component << 2) | (component >> 4); - break; - - default: - component8 = component; - } - - return component8; -} - -static unsigned int getinternalcolor(void *ptr, struct bvformatxlate *format) -{ - unsigned int pixel; - unsigned int r, g, b, a; - - switch (format->bitspp) { - case 16: - pixel = *(unsigned short *) ptr; - break; - - case 32: - pixel = *(unsigned int *) ptr; - break; - - default: - pixel = 0; - } - - r = extract_component(pixel, &format->rgba.r); - g = extract_component(pixel, &format->rgba.g); - b = extract_component(pixel, &format->rgba.b); - a = extract_component(pixel, &format->rgba.a); - - return (a << 24) | - (r << 16) | - (g << 8) | - b; -} - -/******************************************************************************* - * Alpha blending parser. - */ - -struct gcblendconfig { - unsigned char factor_mode; - unsigned char color_reverse; - - unsigned char destuse; - unsigned char srcuse; -}; - -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 *src_config; - struct gcblendconfig *dst_config; -}; - -struct bvblendxlate { - unsigned char match1; - unsigned char match2; - - struct gcblendconfig dst; - struct gcblendconfig src; -}; - -#define BVBLENDMATCH(Mode, Inverse, Normal) \ -( \ - BVBLENDDEF_ ## Mode | \ - BVBLENDDEF_ ## Inverse | \ - BVBLENDDEF_ ## Normal \ -) - -#define BVDEST(Use) \ - Use - -#define BVSRC(Use) \ - Use - -#define BVBLENDUNDEFINED() \ - { ~0, ~0, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } } - -static struct bvblendxlate blendxlate[64] = { - /**********************************************************************/ - /* color factor: 00 00 00 A:(1-Cd,Cd)=zero - alpha factor: zero ==> 00 00 00 */ - { - 0x00, - 0x00, - - { - /* k1 * Cd = 0 * Cd - k3 * Ad = 0 * Ad */ - GCREG_BLENDING_MODE_ZERO, - GCREG_FACTOR_INVERSE_DISABLE, - BVDEST(0), BVSRC(0), - }, - - { - /* k2 * Cs = 0 * Cs - k4 * As = 0 * As */ - GCREG_BLENDING_MODE_ZERO, - GCREG_FACTOR_INVERSE_DISABLE, - BVDEST(0), BVSRC(0) - } - }, - - /* color factor: 00 00 01 A:(1-Cd,Ad)=Ad - alpha factor: Ad ==> 00 00 01 or 00 10 01 */ - { - BVBLENDMATCH(ONLY_A, INV_C1, NORM_A1), - BVBLENDMATCH(ONLY_A, INV_C2, NORM_A1), - - { - /* k1 * Cd = Ad * Cd - k3 * Ad = Ad * Ad */ - GCREG_BLENDING_MODE_NORMAL, - GCREG_FACTOR_INVERSE_ENABLE, - BVDEST(1), BVSRC(0), - }, - - { - /* k2 * Cs = Ad * Cs - k4 * As = Ad * As */ - GCREG_BLENDING_MODE_NORMAL, - GCREG_FACTOR_INVERSE_DISABLE, - BVDEST(1), BVSRC(1) - } - }, - - /* color factor: 00 00 10 A:(1-Cd,Cs)=undefined - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* color factor: 00 00 11 A:(1-Cd,As)=As - alpha factor: As ==> 00 00 11 or 00 10 11 */ - { - BVBLENDMATCH(ONLY_A, INV_C1, NORM_A2), - BVBLENDMATCH(ONLY_A, INV_C2, NORM_A2), - - { - /* k1 * Cd = As * Cd - k3 * Ad = As * Ad */ - GCREG_BLENDING_MODE_NORMAL, - GCREG_FACTOR_INVERSE_DISABLE, - BVDEST(1), BVSRC(1), - }, - - { - /* k2 * Cs = As * Cs - k4 * As = As * As */ - GCREG_BLENDING_MODE_NORMAL, - GCREG_FACTOR_INVERSE_ENABLE, - BVDEST(0), BVSRC(1) - } - }, - - /* color factor: 00 01 00 A:(1-Ad,Cd)=1-Ad - alpha factor: 1-Ad ==> 00 01 00 or 00 01 10 */ - { - BVBLENDMATCH(ONLY_A, INV_A1, NORM_C1), - BVBLENDMATCH(ONLY_A, INV_A1, NORM_C2), - - { - /* k1 * Cd = (1 - Ad) * Cd - k3 * Ad = (1 - Ad) * Ad */ - GCREG_BLENDING_MODE_INVERSED, - GCREG_FACTOR_INVERSE_ENABLE, - BVDEST(1), BVSRC(0), - }, - - { - /* k2 * Cs = (1 - Ad) * Cs - k4 * As = (1 - Ad) * As */ - GCREG_BLENDING_MODE_INVERSED, - GCREG_FACTOR_INVERSE_DISABLE, - BVDEST(1), BVSRC(1) - } - }, - - /* color factor: 00 01 01 A:(1-Ad,Ad)=undefined - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* color factor: 00 01 10 A:(1-Ad,Cs)=1-Ad - alpha factor: 1-Ad ==> 00 01 00 or 00 01 10 */ - { - BVBLENDMATCH(ONLY_A, INV_A1, NORM_C1), - BVBLENDMATCH(ONLY_A, INV_A1, NORM_C2), - - { - /* k1 * Cd = (1 - Ad) * Cd - k3 * Ad = (1 - Ad) * Ad */ - GCREG_BLENDING_MODE_INVERSED, - GCREG_FACTOR_INVERSE_ENABLE, - BVDEST(1), BVSRC(0), - }, - - { - /* k2 * Cs = (1 - Ad) * Cs - k4 * As = (1 - Ad) * As */ - GCREG_BLENDING_MODE_INVERSED, - GCREG_FACTOR_INVERSE_DISABLE, - BVDEST(1), BVSRC(1) - } - }, - - /* color factor: 00 01 11 A:(1-Ad,As)=undefined - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* color factor: 00 10 00 A:(1-Cs,Cd)=undefined - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* color factor: 00 10 01 A:(1-Cs,Ad)=Ad - alpha factor: Ad ==> 00 00 01 or 00 10 01 */ - { - BVBLENDMATCH(ONLY_A, INV_C1, NORM_A1), - BVBLENDMATCH(ONLY_A, INV_C2, NORM_A1), - - { - /* k1 * Cd = Ad * Cd - k3 * Ad = Ad * Ad */ - GCREG_BLENDING_MODE_NORMAL, - GCREG_FACTOR_INVERSE_ENABLE, - BVDEST(1), BVSRC(0), - }, - - { - /* k2 * Cs = Ad * Cs - k4 * As = Ad * As */ - GCREG_BLENDING_MODE_NORMAL, - GCREG_FACTOR_INVERSE_DISABLE, - BVDEST(1), BVSRC(1) - } - }, - - /* color factor: 00 10 10 A:(1-Cs,Cs)=undefined - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* color factor: 00 10 11 A:(1-Cs,As)=As - alpha factor: As ==> 00 00 11 or 00 10 11 */ - { - BVBLENDMATCH(ONLY_A, INV_C1, NORM_A2), - BVBLENDMATCH(ONLY_A, INV_C2, NORM_A2), - - { - /* k1 * Cd = As * Cd - k3 * Ad = As * Ad */ - GCREG_BLENDING_MODE_NORMAL, - GCREG_FACTOR_INVERSE_DISABLE, - BVDEST(1), BVSRC(1), - }, - - { - /* k2 * Cs = As * Cs - k4 * As = As * As */ - GCREG_BLENDING_MODE_NORMAL, - GCREG_FACTOR_INVERSE_ENABLE, - BVDEST(0), BVSRC(1) - } - }, - - /* color factor: 00 11 00 A:(1-As,Cd)=1-As - alpha factor: 1-As ==> 00 11 00 or 00 11 10 */ - { - BVBLENDMATCH(ONLY_A, INV_A2, NORM_C1), - BVBLENDMATCH(ONLY_A, INV_A2, NORM_C2), - - { - /* k1 * Cd = (1 - As) * Cd - k3 * Ad = (1 - As) * Ad */ - GCREG_BLENDING_MODE_INVERSED, - GCREG_FACTOR_INVERSE_DISABLE, - BVDEST(1), BVSRC(1), - }, - - { - /* k2 * Cs = (1 - As) * Cs - k4 * As = (1 - As) * As */ - GCREG_BLENDING_MODE_INVERSED, - GCREG_FACTOR_INVERSE_ENABLE, - BVDEST(0), BVSRC(1) - } - }, - - /* color factor: 00 11 01 A:(1-As,Ad)=undefined - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* color factor: 00 11 10 A:(1-As,Cs)=1-As - alpha factor: 1-As ==> 00 11 00 or 00 11 10 */ - { - BVBLENDMATCH(ONLY_A, INV_A2, NORM_C1), - BVBLENDMATCH(ONLY_A, INV_A2, NORM_C2), - - { - /* k1 * Cd = (1 - As) * Cd - k3 * Ad = (1 - As) * Ad */ - GCREG_BLENDING_MODE_INVERSED, - GCREG_FACTOR_INVERSE_DISABLE, - BVDEST(1), BVSRC(1), - }, - - { - /* k2 * Cs = (1 - As) * Cs - k4 * As = (1 - As) * As */ - GCREG_BLENDING_MODE_INVERSED, - GCREG_FACTOR_INVERSE_ENABLE, - BVDEST(0), BVSRC(1) - } - }, - - /* color factor: 00 11 11 A:(1-As,As)=undefined - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /**********************************************************************/ - /* color factor: 01 00 00 MIN:(1-Cd,Cd) ==> not supported - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* color factor: 01 00 01 MIN:(1-Cd,Ad) ==> not supported - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* color factor: 01 00 10 MIN:(1-Cd,Cs) ==> not supported - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* color factor: 01 00 11 MIN:(1-Cd,As) ==> not supported - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* color factor: 01 01 00 MIN:(1-Ad,Cd) ==> not supported - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* color factor: 01 01 01 MIN:(1-Ad,Ad) ==> not supported - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* color factor: 01 01 10 MIN:(1-Ad,Cs) ==> not supported - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* color factor: 01 01 11 MIN:(1-Ad,As) - alpha factor: one ==> 11 11 11 */ - { - 0x3F, - 0x3F, - - { - /* k1 * Cd = MIN:(1 - Ad, As) * Cd - k3 * Ad = 1 * Ad */ - GCREG_BLENDING_MODE_SATURATED_DEST_ALPHA, - GCREG_FACTOR_INVERSE_DISABLE, - BVDEST(1), BVSRC(1), - }, - - { - /* k2 * Cs = MIN:(1 - Ad, As) * Cs - k4 * As = 1 * As */ - GCREG_BLENDING_MODE_SATURATED_ALPHA, - GCREG_FACTOR_INVERSE_DISABLE, - BVDEST(1), BVSRC(1) - } - }, - - /* color factor: 01 10 00 MIN:(1-Cs,Cd) ==> not supported - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* color factor: 01 10 01 MIN:(1-Cs,Ad) ==> not supported - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* color factor: 01 10 10 MIN:(1-Cs,Cs) ==> not supported - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* color factor: 01 10 11 MIN:(1-Cs,As) ==> not supported - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* color factor: 01 11 00 MIN:(1-As,Cd) ==> not supported - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* color factor: 01 11 01 MIN:(1-As,Ad) - alpha factor: one ==> 11 11 11 */ - { - 0x3F, - 0x3F, - - { - /* k1 * Cd = MIN:(1 - As, Ad) * Cd - k3 * Ad = 1 * Ad */ - GCREG_BLENDING_MODE_SATURATED_ALPHA, - GCREG_FACTOR_INVERSE_DISABLE, - BVDEST(1), BVSRC(1), - }, - - { - /* k2 * Cs = MIN:(1 - As, Ad) * Cs - k4 * As = 1 * As */ - GCREG_BLENDING_MODE_SATURATED_DEST_ALPHA, - GCREG_FACTOR_INVERSE_DISABLE, - BVDEST(1), BVSRC(1) - } - }, - - /* color factor: 01 11 10 MIN:(1-As,Cs) ==> not supported - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* color factor: 01 11 11 MIN:(1-As,As) ==> not supported - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /**********************************************************************/ - /* color factor: 10 00 00 MAX:(1-Cd,Cd) ==> not supported - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* color factor: 10 00 01 MAX:(1-Cd,Ad) ==> not supported - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* color factor: 10 00 10 MAX:(1-Cd,Cs) ==> not supported - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* color factor: 10 00 11 MAX:(1-Cd,As) ==> not supported - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* color factor: 10 01 00 MAX:(1-Ad,Cd) ==> not supported - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* color factor: 10 01 01 MAX:(1-Ad,Ad) ==> not supported - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* color factor: 10 01 10 MAX:(1-Ad,Cs) ==> not supported - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* color factor: 10 01 11 MAX:(1-Ad,As) ==> not supported - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* color factor: 10 10 00 MAX:(1-Cs,Cd) ==> not supported - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* color factor: 10 10 01 MAX:(1-Cs,Ad) ==> not supported - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* color factor: 10 10 10 MAX:(1-Cs,Cs) ==> not supported - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* color factor: 10 10 11 MAX:(1-Cs,As) ==> not supported - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* color factor: 10 11 00 MAX:(1-As,Cd) ==> not supported - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* color factor: 10 11 01 MAX:(1-As,Ad) ==> not supported - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* color factor: 10 11 10 MAX:(1-As,Cs) ==> not supported - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* color factor: 10 11 11 MAX:(1-As,As) ==> not supported - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /**********************************************************************/ - /* color factor: 11 00 00 C:(1-Cd,Cd)=undefined - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* color factor: 11 00 01 C:(1-Cd,Ad)=1-Cd - alpha factor: 1-Ad ==> 00 01 00 or 00 01 10 */ - { - BVBLENDMATCH(ONLY_A, INV_A1, NORM_C1), - BVBLENDMATCH(ONLY_A, INV_A1, NORM_C2), - - { - /* k1 * Cd = (1 - Cd) * Cd - k3 * Ad = (1 - Ad) * Ad */ - GCREG_BLENDING_MODE_COLOR_INVERSED, - GCREG_FACTOR_INVERSE_ENABLE, - BVDEST(1), BVSRC(0), - }, - - { - /* k2 * Cs = (1 - Cd) * Cs - k4 * As = (1 - Ad) * As */ - GCREG_BLENDING_MODE_COLOR_INVERSED, - GCREG_FACTOR_INVERSE_DISABLE, - BVDEST(1), BVSRC(1) - } - }, - - /* color factor: 11 00 10 C:(1-Cd,Cs)=undefined - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* color factor: 11 00 11 C:(1-Cd,As)=1-Cd - alpha factor: 1-Ad ==> 00 01 00 or 00 01 10 */ - { - BVBLENDMATCH(ONLY_A, INV_A1, NORM_C1), - BVBLENDMATCH(ONLY_A, INV_A1, NORM_C2), - - { - /* k1 * Cd = (1 - Cd) * Cd - k3 * Ad = (1 - Ad) * Ad */ - GCREG_BLENDING_MODE_COLOR_INVERSED, - GCREG_FACTOR_INVERSE_ENABLE, - BVDEST(1), BVSRC(0), - }, - - { - /* k2 * Cs = (1 - Cd) * Cs - k4 * As = (1 - Ad) * As */ - GCREG_BLENDING_MODE_COLOR_INVERSED, - GCREG_FACTOR_INVERSE_DISABLE, - BVDEST(1), BVSRC(1) - } - }, - - /* color factor: 11 01 00 C:(1-Ad,Cd)=Cd - alpha factor: Ad ==> 00 00 01 or 00 10 01 */ - { - BVBLENDMATCH(ONLY_A, INV_C1, NORM_A1), - BVBLENDMATCH(ONLY_A, INV_C2, NORM_A1), - - { - /* k1 * Cd = Cd * Cd - k3 * Ad = Ad * Ad */ - GCREG_BLENDING_MODE_COLOR, - GCREG_FACTOR_INVERSE_ENABLE, - BVDEST(1), BVSRC(0), - }, - - { - /* k2 * Cs = Cd * Cs - k4 * As = Ad * As */ - GCREG_BLENDING_MODE_COLOR, - GCREG_FACTOR_INVERSE_DISABLE, - BVDEST(1), BVSRC(1) - } - }, - - /* color factor: 11 01 01 C:(1-Ad,Ad)=undefined - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* color factor: 11 01 10 C:(1-Ad,Cs)=Cs - alpha factor: As ==> 00 00 11 or 00 10 11 */ - { - BVBLENDMATCH(ONLY_A, INV_C1, NORM_A2), - BVBLENDMATCH(ONLY_A, INV_C2, NORM_A2), - - { - /* k1 * Cd = Cs * Cd - k3 * Ad = As * Ad */ - GCREG_BLENDING_MODE_COLOR, - GCREG_FACTOR_INVERSE_DISABLE, - BVDEST(1), BVSRC(1), - }, - - { - /* k2 * Cs = Cs * Cs - k4 * As = As * As */ - GCREG_BLENDING_MODE_COLOR, - GCREG_FACTOR_INVERSE_ENABLE, - BVDEST(0), BVSRC(1) - } - }, - - /* color factor: 11 01 11 C:(1-Ad,As)=undefined - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* color factor: 11 10 00 C:(1-Cs,Cd)=undefined - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* color factor: 11 10 01 C:(1-Cs,Ad)=1-Cs - alpha factor: 1-As ==> 00 11 00 or 00 11 10 */ - { - BVBLENDMATCH(ONLY_A, INV_A2, NORM_C1), - BVBLENDMATCH(ONLY_A, INV_A2, NORM_C2), - - { - /* k1 * Cd = (1 - Cs) * Cd - k3 * Ad = (1 - As) * Ad */ - GCREG_BLENDING_MODE_COLOR_INVERSED, - GCREG_FACTOR_INVERSE_DISABLE, - BVDEST(1), BVSRC(1), - }, - - { - /* k2 * Cs = (1 - Cs) * Cs - k4 * As = (1 - As) * As */ - GCREG_BLENDING_MODE_COLOR_INVERSED, - GCREG_FACTOR_INVERSE_ENABLE, - BVDEST(0), BVSRC(1) - } - }, - - /* color factor: 11 10 10 C:(1-Cs,Cs)=undefined - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* color factor: 11 10 11 C:(1-Cs,As)=1-Cs - alpha factor: 1-As ==> 00 11 00 or 00 11 10 */ - { - BVBLENDMATCH(ONLY_A, INV_A2, NORM_C1), - BVBLENDMATCH(ONLY_A, INV_A2, NORM_C2), - - { - /* k1 * Cd = (1 - Cs) * Cd - k3 * Ad = (1 - As) * Ad */ - GCREG_BLENDING_MODE_COLOR_INVERSED, - GCREG_FACTOR_INVERSE_DISABLE, - BVDEST(1), BVSRC(1), - }, - - { - /* k2 * Cs = (1 - Cs) * Cs - k4 * As = (1 - As) * As */ - GCREG_BLENDING_MODE_COLOR_INVERSED, - GCREG_FACTOR_INVERSE_ENABLE, - BVDEST(0), BVSRC(0) - } - }, - - /* color factor: 11 11 00 C:(1-As,Cd)=Cd - alpha factor: Ad ==> 00 00 01 or 00 10 01 */ - { - BVBLENDMATCH(ONLY_A, INV_C1, NORM_A1), - BVBLENDMATCH(ONLY_A, INV_C2, NORM_A1), - - { - /* k1 * Cd = Cd * Cd - k3 * Ad = Ad * Ad */ - GCREG_BLENDING_MODE_COLOR, - GCREG_FACTOR_INVERSE_ENABLE, - BVDEST(1), BVSRC(0), - }, - - { - /* k2 * Cs = Cd * Cs - k4 * As = Ad * As */ - GCREG_BLENDING_MODE_COLOR, - GCREG_FACTOR_INVERSE_DISABLE, - BVDEST(1), BVSRC(1) - } - }, - - /* color factor: 11 11 01 C:(1-As,Ad)=undefined - alpha factor: N/A */ - BVBLENDUNDEFINED(), - - /* color factor: 11 11 10 C:(1-As,Cs)=Cs - alpha factor: As ==> 00 00 11 or 00 10 11 */ - { - BVBLENDMATCH(ONLY_A, INV_C1, NORM_A2), - BVBLENDMATCH(ONLY_A, INV_C2, NORM_A2), - - { - /* k1 * Cd = Cs * Cd - k3 * Ad = As * Ad */ - GCREG_BLENDING_MODE_COLOR, - GCREG_FACTOR_INVERSE_DISABLE, - BVDEST(1), BVSRC(1), - }, - - { - /* k2 * Cs = Cs * Cs - k4 * As = As * As */ - GCREG_BLENDING_MODE_COLOR, - GCREG_FACTOR_INVERSE_ENABLE, - BVDEST(0), BVSRC(1) - } - }, - - /* color factor: 11 11 11 C:(1-As,As)=one - alpha factor: one ==> 11 11 11 */ - { - 0x3F, - 0x3F, - - { - /* k1 * Cd = 1 * Cd - k3 * Ad = 1 * Ad */ - GCREG_BLENDING_MODE_ONE, - GCREG_FACTOR_INVERSE_DISABLE, - BVDEST(1), BVSRC(0), - }, - - { - /* k2 * Cs = 1 * Cs - k4 * As = 1 * As */ - GCREG_BLENDING_MODE_ONE, - GCREG_FACTOR_INVERSE_DISABLE, - BVDEST(0), BVSRC(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 *dstxlate; - struct bvblendxlate *srcxlate; - unsigned int alpha; - - 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): - GC_PRINT(GC_INFO_MSG " BVBLENDDEF_GLOBAL_NONE\n", - __func__, __LINE__); - - gca->src_global_alpha_mode = GCREG_GLOBAL_ALPHA_MODE_NORMAL; - gca->dst_global_alpha_mode = GCREG_GLOBAL_ALPHA_MODE_NORMAL; - - gca->src_global_alpha_mode = - gca->dst_global_alpha_mode = 0; - break; - - case (BVBLENDDEF_GLOBAL_UCHAR >> BVBLENDDEF_GLOBAL_SHIFT): - GC_PRINT(GC_INFO_MSG " BVBLENDDEF_GLOBAL_UCHAR\n", - __func__, __LINE__); - - 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): - GC_PRINT(GC_INFO_MSG " BVBLENDDEF_GLOBAL_FLOAT\n", - __func__, __LINE__); - - 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 Cd + k2 x Cs - Ao = k3 x Ad + k4 x As - */ - - k1 = (blend >> 18) & 0x3F; - k2 = (blend >> 12) & 0x3F; - k3 = (blend >> 6) & 0x3F; - k4 = blend & 0x3F; - - GC_PRINT(GC_INFO_MSG " blend = 0x%08X\n", __func__, __LINE__, blend); - GC_PRINT(GC_INFO_MSG " k1 = %d\n", __func__, __LINE__, k1); - GC_PRINT(GC_INFO_MSG " k2 = %d\n", __func__, __LINE__, k2); - GC_PRINT(GC_INFO_MSG " k3 = %d\n", __func__, __LINE__, k3); - GC_PRINT(GC_INFO_MSG " k4 = %d\n", __func__, __LINE__, k4); - - dstxlate = &blendxlate[k1]; - srcxlate = &blendxlate[k2]; - - if (((k3 != dstxlate->match1) && (k3 != dstxlate->match2)) || - ((k4 != srcxlate->match1) && (k4 != srcxlate->match2))) { - BVSETBLTERROR(BVERR_BLEND, - "not supported coefficient combination"); - goto exit; - } - - gca->src_config = &dstxlate->dst; - gca->dst_config = &srcxlate->src; - - bverror = BVERR_NONE; - -exit: - return bverror; -} - -/******************************************************************************* - * Surface validation. - */ - -static int verify_surface(unsigned int tile, - union bvinbuff *surf, - struct bvsurfgeom *geom, - struct bvrect *rect) -{ - if (tile) { - if (surf->tileparams == NULL) - return BVERR_TILE; - - if (surf->tileparams->structsize != STRUCTSIZE(surf->tileparams, - srcheight)) - return BVERR_TILE_VERS; - - if (surf->tileparams->virtaddr == NULL) - return BVERR_TILE_VIRTADDR; - - /* FIXME/TODO */ - return BVERR_TILE; - } else { - if (surf->desc == NULL) - return BVERR_DESC; - - if (surf->desc->structsize != STRUCTSIZE(surf->desc, map)) - return BVERR_DESC_VERS; - - if (surf->desc->virtaddr == NULL) - return BVERR_DESC_VIRTADDR; - } - - if (geom == NULL) - return BVERR_GEOM; - - if (geom->structsize != STRUCTSIZE(geom, palette)) - return BVERR_GEOM_VERS; - -#if GC_DUMP - { - struct bvformatxlate *format; - if (parse_format(geom->format, &format)) { - unsigned int geomsize; - unsigned int rectsize; - - geomsize - = (geom->width - * geom->height - * format->bitspp) / 8; - - rectsize - = (rect->top + rect->height - 1) - * geom->virtstride - + ((rect->left + rect->width) - * format->bitspp) / 8; - - if (geomsize > surf->desc->length) { - GC_PRINT(GC_INFO_MSG - " *** invalid geometry %dx%d\n", - __func__, __LINE__, - geom->width, geom->height); - } - - if (rectsize > surf->desc->length) { - GC_PRINT(GC_INFO_MSG - " *** invalid rectangle " - "(%d,%d %dx%d)\n", - __func__, __LINE__, - rect->left, rect->top, - rect->width, rect->height); - } - } - } -#endif - - return -1; -} - -/******************************************************************************* - * Primitive renderers. - */ - -static enum bverror do_fill(struct bvbltparams *bltparams, - struct gcbatch *batch, - struct srcdesc *srcdesc) -{ - enum bverror bverror; - enum bverror unmap_bverror; - - struct gcmofill *gcmofill; - - unsigned char *fillcolorptr; - - struct bvformatxlate *srcformat; - struct bvformatxlate *dstformat; - - struct bvbuffmap *dstmap = NULL; - struct bvsurfgeom *dstgeom = bltparams->dstgeom; - struct bvrect *dstrect = &bltparams->dstrect; - unsigned int dstoffset; - - if (!parse_format(srcdesc->geom->format, &srcformat)) { - BVSETBLTERRORARG((srcdesc->index == 0) - ? BVERR_SRC1GEOM_FORMAT - : BVERR_SRC2GEOM_FORMAT, - "invalid source format (%d)", - srcdesc->geom->format); - goto exit; - } - - if (!parse_format(dstgeom->format, &dstformat)) { - BVSETBLTERRORARG(BVERR_DSTGEOM_FORMAT, - "invalid destination format (%d)", - dstgeom->format); - goto exit; - } - - bverror = do_map(bltparams->dstdesc, 0, &dstmap); - if (bverror != BVERR_NONE) { - bltparams->errdesc = gccontext.bverrorstr; - goto exit; - } - - dstoffset = (((unsigned int) bltparams->dstdesc->virtaddr - & (GC_BASE_ALIGN - 1)) * 8) / dstformat->bitspp; - - bverror = claim_buffer(batch, sizeof(struct gcmofill), - (void **) &gcmofill); - if (bverror != BVERR_NONE) { - BVSETBLTERROR(BVERR_OOM, "failed to allocate command buffer"); - goto exit; - } - - memset(gcmofill, 0, sizeof(struct gcmofill)); - - GC_PRINT(GC_INFO_MSG " allocated %d of commmand buffer\n", - __func__, __LINE__, sizeof(struct gcmofill)); - - /*********************************************************************** - ** Set destination. - */ - - add_fixup(batch, &gcmofill->dst.address, 0); - - /* Set surface parameters. */ - gcmofill->dst.address_ldst = gcmodst_address_ldst; - gcmofill->dst.address = GET_MAP_HANDLE(dstmap); - gcmofill->dst.stride = dstgeom->virtstride; - gcmofill->dst.config.reg.swizzle = dstformat->swizzle; - gcmofill->dst.config.reg.format = dstformat->format; - - /* Set surface width and height. */ - gcmofill->dst.rotation.reg.surf_width = dstgeom->width + dstoffset; - gcmofill->dst.rotationheight_ldst = gcmodst_rotationheight_ldst; - gcmofill->dst.rotationheight.reg.height = dstgeom->height; - - /* Set BLT command. */ - gcmofill->dst.config.reg.command = GCREG_DEST_CONFIG_COMMAND_CLEAR; - - /* Set clipping. */ - gcmofill->dst.clip.lt_ldst = gcmoclip_lt_ldst; - - if ((bltparams->flags & BVFLAG_CLIP) == BVFLAG_CLIP) { - gcmofill->dst.clip.lt.reg.left - = bltparams->cliprect.left + dstoffset; - gcmofill->dst.clip.lt.reg.top - = bltparams->cliprect.top; - gcmofill->dst.clip.rb.reg.right - = gcmofill->dst.clip.lt.reg.left - + bltparams->cliprect.width; - gcmofill->dst.clip.rb.reg.bottom - = gcmofill->dst.clip.lt.reg.top - + bltparams->cliprect.height; - } else { - gcmofill->dst.clip.lt.reg.left = GC_CLIP_RESET_LEFT; - gcmofill->dst.clip.lt.reg.top = GC_CLIP_RESET_TOP; - gcmofill->dst.clip.rb.reg.right = GC_CLIP_RESET_RIGHT; - gcmofill->dst.clip.rb.reg.bottom = GC_CLIP_RESET_BOTTOM; - } - - /*********************************************************************** - ** Set source. - */ - - /* Set surface dummy width and height. */ - gcmofill->src.rotation_ldst = gcmofillsrc_rotation_ldst; - gcmofill->src.rotation.reg.surf_width = dstgeom->width; - gcmofill->src.rotationheight_ldst = gcmofillsrc_rotationheight_ldst; - gcmofill->src.rotationheight.reg.height = dstgeom->height; - - /* Set ROP3. */ - gcmofill->src.rop_ldst = gcmofillsrc_rop_ldst; - gcmofill->src.rop.reg.type = GCREG_ROP_TYPE_ROP3; - gcmofill->src.rop.reg.fg = (unsigned char) bltparams->op.rop; - - /*********************************************************************** - ** Set fill color. - */ - - fillcolorptr - = (unsigned char *) srcdesc->buf.desc->virtaddr - + srcdesc->rect->top * srcdesc->geom->virtstride - + srcdesc->rect->left * srcformat->bitspp / 8; - - gcmofill->clearcolor_ldst = gcmofill_clearcolor_ldst; - gcmofill->clearcolor.raw = getinternalcolor(fillcolorptr, srcformat); - - /*********************************************************************** - ** Configure and start fill. - */ - - /* Set START_DE command. */ - gcmofill->start.startde.cmd.fld = gcfldstartde; - - /* Set destination rectangle. */ - gcmofill->start.rect.left - = dstrect->left + dstoffset; - gcmofill->start.rect.top - = dstrect->top; - gcmofill->start.rect.right - = gcmofill->start.rect.left + dstrect->width; - gcmofill->start.rect.bottom - = gcmofill->start.rect.top + dstrect->height; - - /* Flush PE cache. */ - gcmofill->start.flush.flush_ldst = gcmoflush_flush_ldst; - gcmofill->start.flush.flush.reg = gcregflush_pe2D; - -exit: - if (dstmap != NULL) { - unmap_bverror = schedule_unmap(batch, bltparams->dstdesc); - if ((unmap_bverror != BVERR_NONE) && (bverror == BVERR_NONE)) { - bltparams->errdesc = gccontext.bverrorstr; - bverror = unmap_bverror; - } - } - - return bverror; -} - -static enum bverror do_blit_end(struct bvbltparams *bltparams, - struct gcbatch *batch) -{ - enum bverror bverror; - struct gcmomultisrc *gcmomultisrc; - struct gcmostart *gcmostart; - unsigned int buffersize; - - GC_PRINT(GC_INFO_MSG " finalizing the blit, scrcount = %d\n", - __func__, __LINE__, batch->op.gcblit.srccount); - - buffersize - = sizeof(struct gcmomultisrc) - + sizeof(struct gcmostart); - - bverror = claim_buffer(batch, buffersize, (void **) &gcmomultisrc); - if (bverror != BVERR_NONE) { - BVSETBLTERROR(BVERR_OOM, "failed to allocate command buffer"); - goto exit; - } - - /* Reset the finalizer. */ - batch->batchend = do_end; - - /*********************************************************************** - ** Set multi-source control. - */ - - gcmomultisrc->control_ldst = gcmomultisrc_control_ldst; - gcmomultisrc->control.reg.srccount = batch->op.gcblit.srccount - 1; - gcmomultisrc->control.reg.horblock - = GCREG_DE_MULTI_SOURCE_HORIZONTAL_BLOCK_PIXEL128; - - gcmostart = (struct gcmostart *) (gcmomultisrc + 1); - - /* Set START_DE command. */ - gcmostart->startde.cmd.fld = gcfldstartde; - - /* Set destination rectangle. */ - gcmostart->rect = batch->op.gcblit.dstrect; - - /* Flush PE cache. */ - gcmostart->flush.flush_ldst = gcmoflush_flush_ldst; - gcmostart->flush.flush.reg = gcregflush_pe2D; - -exit: - return bverror; -} - -static enum bverror do_blit(struct bvbltparams *bltparams, - struct gcbatch *batch, - struct srcdesc *srcdesc, - unsigned int srccount, - struct gcalpha *gca) -{ - enum bverror bverror; - enum bverror unmap_bverror; - - unsigned int buffersize; - void *buffer; - struct gcmodst *gcmodst; - struct gcmosrc *gcmosrc; - - unsigned int i, index; - unsigned int startblit; - - struct bvformatxlate *srcformat[2]; - struct bvbuffmap *srcmap[2] = { NULL, NULL }; - struct bvsurfgeom *srcgeom; - struct bvrect *srcrect; - int srcsurfleft, srcsurftop; - int srcleft[2], srctop[2]; - int srcshift[2]; - int srcoffset; - int srcadjust; - - struct bvformatxlate *dstformat; - struct bvbuffmap *dstmap = NULL; - struct bvsurfgeom *dstgeom = bltparams->dstgeom; - unsigned int dstleft, dsttop; - unsigned int dstright, dstbottom; - unsigned int dstoffset; - - unsigned int multiblit = 1; - - if (!parse_format(dstgeom->format, &dstformat)) { - BVSETBLTERRORARG(BVERR_DSTGEOM_FORMAT, - "invalid destination format (%d)", - dstgeom->format); - goto exit; - } - - bverror = do_map(bltparams->dstdesc, 0, &dstmap); - if (bverror != BVERR_NONE) { - bltparams->errdesc = gccontext.bverrorstr; - goto exit; - } - - /* Determine destination coordinates. */ - dstleft = bltparams->dstrect.left; - dsttop = bltparams->dstrect.top; - dstright = bltparams->dstrect.width + dstleft; - dstbottom = bltparams->dstrect.height + dsttop; - - dstoffset = (((unsigned int) bltparams->dstdesc->virtaddr - & (GC_BASE_ALIGN - 1)) * 8) / dstformat->bitspp; - - GC_PRINT(GC_INFO_MSG " dstaddr = 0x%08X\n", - __func__, __LINE__, - (unsigned int) bltparams->dstdesc->virtaddr); - - GC_PRINT(GC_INFO_MSG " dstsurf = %dx%d, stride = %ld\n", - __func__, __LINE__, - bltparams->dstgeom->width, bltparams->dstgeom->height, - bltparams->dstgeom->virtstride); - - GC_PRINT(GC_INFO_MSG " dstrect = (%d,%d)-(%d,%d), dstoffset = %d\n", - __func__, __LINE__, - dstleft, dsttop, dstright, dstbottom, dstoffset); - - GC_PRINT(GC_INFO_MSG " dstrect = %dx%d\n", - __func__, __LINE__, - bltparams->dstrect.width, bltparams->dstrect.height); - - dstleft += dstoffset; - dstright += dstoffset; - - /* Set destination coordinates. */ - batch->op.gcblit.dstrect.left = dstleft; - batch->op.gcblit.dstrect.top = dsttop; - batch->op.gcblit.dstrect.right = dstright; - batch->op.gcblit.dstrect.bottom = dstbottom; - - for (i = 0; i < srccount; i += 1) { - srcgeom = srcdesc[i].geom; - srcrect = srcdesc[i].rect; - - if (!parse_format(srcgeom->format, &srcformat[i])) { - BVSETBLTERRORARG((srcdesc[i].index == 0) - ? BVERR_SRC1GEOM_FORMAT - : BVERR_SRC2GEOM_FORMAT, - "invalid source format (%d)", - srcgeom->format); - goto exit; - } - - srcoffset = (((unsigned int) srcdesc[i].buf.desc->virtaddr - & (GC_BASE_ALIGN - 1)) * 8) - / srcformat[i]->bitspp; - - GC_PRINT(GC_INFO_MSG " srcaddr[%d] = 0x%08X\n", - __func__, __LINE__, - i, (unsigned int) srcdesc[i].buf.desc->virtaddr); - - GC_PRINT(GC_INFO_MSG " srcsurf%d = %dx%d, stride%d = %ld\n", - __func__, __LINE__, - i, srcgeom->width, srcgeom->height, - i, srcgeom->virtstride); - - GC_PRINT(GC_INFO_MSG - " srcrect%d = (%d,%d)-(%d,%d), srcoffset%d = %d\n", - __func__, __LINE__, - i, - srcrect->left, srcrect->top, - srcrect->left + srcrect->width, - srcrect->top + srcrect->height, - i, - srcoffset); - - GC_PRINT(GC_INFO_MSG " srcrect%d = %dx%d\n", - __func__, __LINE__, - i, srcrect->width, srcrect->height); - - srcsurfleft = srcrect->left - dstleft + srcoffset; - srcsurftop = srcrect->top - dsttop; - - GC_PRINT(GC_INFO_MSG " source %d surface origin = %d,%d\n", - __func__, __LINE__, i, srcsurfleft, srcsurftop); - - srcadjust = srcsurfleft % 4; - srcsurfleft -= srcadjust; - srcleft[i] = dstleft + srcadjust; - srctop[i] = dsttop; - - GC_PRINT(GC_INFO_MSG " srcadjust%d = %d\n", - __func__, __LINE__, i, srcadjust); - - GC_PRINT(GC_INFO_MSG - " adjusted source %d surface origin = %d,%d\n", - __func__, __LINE__, i, srcsurfleft, srcsurftop); - - GC_PRINT(GC_INFO_MSG " source %d rectangle origin = %d,%d\n", - __func__, __LINE__, i, srcleft[i], srctop[i]); - - srcshift[i] - = srcsurftop * (int) srcgeom->virtstride - + srcsurfleft * (int) srcformat[i]->bitspp / 8; - - if (srcadjust != 0) - multiblit = 0; - - GC_PRINT(GC_INFO_MSG " srcshift[%d] = 0x%08X\n", - __func__, __LINE__, i, srcshift[i]); - - bverror = do_map(srcdesc[i].buf.desc, 0, &srcmap[i]); - if (bverror != BVERR_NONE) { - bltparams->errdesc = gccontext.bverrorstr; - goto exit; - } - } - - GC_PRINT(GC_INFO_MSG " multiblit = %d\n", - __func__, __LINE__, multiblit); - - if ((batch->batchend == do_blit_end) && - (batch->op.gcblit.srccount < 4)) { - GC_PRINT(GC_ERR_MSG " adding new source to the operation\n", - __func__, __LINE__); - - startblit = 0; - buffersize = sizeof(struct gcmosrc) * srccount; - } else { - if (batch->batchend == do_blit_end) { - GC_PRINT(GC_INFO_MSG - " maximum number of sources reached\n", - __func__, __LINE__); - } else { - GC_PRINT(GC_INFO_MSG - " another operation in progress\n", - __func__, __LINE__); - } - - bverror = batch->batchend(bltparams, batch); - if (bverror != BVERR_NONE) - goto exit; - - startblit = 1; - buffersize - = sizeof(struct gcmodst) - + sizeof(struct gcmosrc) * srccount; - - batch->batchend = do_blit_end; - batch->op.gcblit.srccount = 0; - } - - bverror = claim_buffer(batch, buffersize, &buffer); - if (bverror != BVERR_NONE) { - BVSETBLTERROR(BVERR_OOM, "failed to allocate command buffer"); - goto exit; - } - - memset(buffer, 0, buffersize); - - GC_PRINT(GC_INFO_MSG " allocated %d of commmand buffer\n", - __func__, __LINE__, buffersize); - - /*********************************************************************** - ** Set destination. - */ - - if (startblit) { - GC_PRINT(GC_INFO_MSG " processing the destiantion\n", - __func__, __LINE__); - - gcmodst = (struct gcmodst *) buffer; - - add_fixup(batch, &gcmodst->address, 0); - - /* Set surface parameters. */ - gcmodst->address_ldst = gcmodst_address_ldst; - gcmodst->address = GET_MAP_HANDLE(dstmap); - gcmodst->stride = dstgeom->virtstride; - gcmodst->config.reg.swizzle = dstformat->swizzle; - gcmodst->config.reg.format = dstformat->format; - - /* Set surface width and height. */ - gcmodst->rotation.reg.surf_width = dstgeom->width + dstoffset; - gcmodst->rotationheight_ldst = gcmodst_rotationheight_ldst; - gcmodst->rotationheight.reg.height = dstgeom->height; - - /* Set BLT command. */ - gcmodst->config.reg.command = multiblit - ? GCREG_DEST_CONFIG_COMMAND_MULTI_SOURCE_BLT - : GCREG_DEST_CONFIG_COMMAND_BIT_BLT; - - /* Set clipping. */ - gcmodst->clip.lt_ldst = gcmoclip_lt_ldst; - - if ((bltparams->flags & BVFLAG_CLIP) == BVFLAG_CLIP) { - gcmodst->clip.lt.reg.left - = bltparams->cliprect.left + dstoffset; - gcmodst->clip.lt.reg.top - = bltparams->cliprect.top; - gcmodst->clip.rb.reg.right - = gcmodst->clip.lt.reg.left - + bltparams->cliprect.width; - gcmodst->clip.rb.reg.bottom - = gcmodst->clip.lt.reg.top - + bltparams->cliprect.height; - } else { - gcmodst->clip.lt.reg.left = GC_CLIP_RESET_LEFT; - gcmodst->clip.lt.reg.top = GC_CLIP_RESET_TOP; - gcmodst->clip.rb.reg.right = GC_CLIP_RESET_RIGHT; - gcmodst->clip.rb.reg.bottom = GC_CLIP_RESET_BOTTOM; - } - - /* Determine location of source states. */ - gcmosrc = (struct gcmosrc *) (gcmodst + 1); - } else { - GC_PRINT(GC_INFO_MSG " skipping the destiantion\n", - __func__, __LINE__); - - /* Determine location of source states. */ - gcmosrc = (struct gcmosrc *) buffer; - } - - /*********************************************************************** - ** Set source(s). - */ - - GC_PRINT(GC_INFO_MSG " processing %d sources\n", - __func__, __LINE__, srccount); - - index = batch->op.gcblit.srccount; - - for (i = 0; i < srccount; i += 1, index += 1) { - srcgeom = srcdesc[i].geom; - - add_fixup(batch, &gcmosrc->address, srcshift[i]); - - /* Set surface parameters. */ - gcmosrc->address_ldst = gcmosrc_address_ldst[index]; - gcmosrc->address = GET_MAP_HANDLE(srcmap[i]); - - gcmosrc->stride_ldst = gcmosrc_stride_ldst[index]; - gcmosrc->stride = srcgeom->virtstride; - - gcmosrc->rotation_ldst = gcmosrc_rotation_ldst[index]; - gcmosrc->rotation.reg.surf_width = dstleft + srcgeom->width; - - gcmosrc->config_ldst = gcmosrc_config_ldst[index]; - gcmosrc->config.reg.swizzle = srcformat[i]->swizzle; - gcmosrc->config.reg.format = srcformat[i]->format; - - gcmosrc->origin_ldst = gcmosrc_origin_ldst[index]; - if (multiblit) { - gcmosrc->origin.reg = gcregsrcorigin_min; - } else { - gcmosrc->origin.reg.x = srcleft[i]; - gcmosrc->origin.reg.y = srctop[i]; - } - - gcmosrc->size_ldst = gcmosrc_size_ldst[index]; - gcmosrc->size.reg = gcregsrcsize_max; - - gcmosrc->rotationheight_ldst - = gcmosrc_rotationheight_ldst[index]; - gcmosrc->rotationheight.reg.height = dsttop + srcgeom->height; - - gcmosrc->rop_ldst = gcmosrc_rop_ldst[index]; - gcmosrc->rop.reg.type = GCREG_ROP_TYPE_ROP3; - gcmosrc->rop.reg.fg = (gca != NULL) - ? 0xCC : (unsigned char) bltparams->op.rop; - - gcmosrc->mult_ldst = gcmosrc_mult_ldst[index]; - 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; - } - - gcmosrc->alphacontrol_ldst = gcmosrc_alphacontrol_ldst[index]; - gcmosrc->alphamodes_ldst = gcmosrc_alphamodes_ldst[index]; - gcmosrc->srcglobal_ldst = gcmosrc_srcglobal_ldst[index]; - gcmosrc->dstglobal_ldst = gcmosrc_dstglobal_ldst[index]; - - if ((gca != NULL) && ((srccount == 1) || (i > 0))) { - gcmosrc->alphacontrol.reg.enable - = GCREG_ALPHA_CONTROL_ENABLE_ON; - - gcmosrc->alphamodes.reg.src_global_alpha - = gca->src_global_alpha_mode; - gcmosrc->alphamodes.reg.dst_global_alpha - = gca->dst_global_alpha_mode; - gcmosrc->alphamodes.reg.src_blend - = gca->src_config->factor_mode; - gcmosrc->alphamodes.reg.dst_blend - = gca->dst_config->factor_mode; - gcmosrc->alphamodes.reg.src_color_reverse - = gca->src_config->color_reverse; - gcmosrc->alphamodes.reg.dst_color_reverse - = gca->dst_config->color_reverse; - - gcmosrc->srcglobal.raw = gca->src_global_color; - gcmosrc->dstglobal.raw = gca->dst_global_color; - } else - gcmosrc->alphacontrol.reg.enable - = GCREG_ALPHA_CONTROL_ENABLE_OFF; - - gcmosrc += 1; - batch->op.gcblit.srccount += 1; - } - -exit: - for (i = 0; i < 2; i += 1) - if (srcmap[i] != NULL) { - unmap_bverror = schedule_unmap(batch, - srcdesc[i].buf.desc); - if ((unmap_bverror != BVERR_NONE) && - (bverror == BVERR_NONE)) { - bltparams->errdesc = gccontext.bverrorstr; - bverror = unmap_bverror; - } - } - - if (dstmap != NULL) { - unmap_bverror = schedule_unmap(batch, bltparams->dstdesc); - if ((unmap_bverror != BVERR_NONE) && (bverror == BVERR_NONE)) { - bltparams->errdesc = gccontext.bverrorstr; - bverror = unmap_bverror; - } - } - - return bverror; -} - -static enum bverror do_filter(struct bvbltparams *bltparams, - struct gcbatch *batch) -{ - enum bverror bverror; - BVSETBLTERROR(BVERR_UNK, "FIXME/TODO"); - return bverror; -} - -/******************************************************************************* - * Library constructor and destructor. - */ - -void bv_init(void) -{ -} - -void bv_exit(void) -{ - struct bvbuffmap *bufmap; - struct gcschedunmap *bufunmap; - struct gcbuffer *buffer; - struct gcfixup *fixup; - struct gcvacbatch *batch; - - while (gccontext.vac_buffmap != NULL) { - bufmap = gccontext.vac_buffmap; - gccontext.vac_buffmap = bufmap->nextmap; - gcfree(bufmap); - } - - while (gccontext.vac_unmap != NULL) { - bufunmap = gccontext.vac_unmap; - gccontext.vac_unmap = bufunmap->next; - gcfree(bufunmap); - } - - while (gccontext.vac_buffers != NULL) { - buffer = gccontext.vac_buffers; - gccontext.vac_buffers = buffer->next; - gcfree(buffer); - } - - while (gccontext.vac_fixups != NULL) { - fixup = gccontext.vac_fixups; - gccontext.vac_fixups = fixup->next; - gcfree(fixup); - } - - while (gccontext.vac_batches != NULL) { - batch = gccontext.vac_batches; - gccontext.vac_batches = batch->next; - gcfree(batch); - } -} - -/******************************************************************************* - * Library API. - */ - -enum bverror bv_map(struct bvbuffdesc *buffdesc) -{ - enum bverror bverror; - struct bvbuffmap *bvbuffmap; - - /* FIXME/TODO: add check for initialization success. */ - - if (buffdesc == NULL) { - BVSETERROR(BVERR_UNK, "invalid argument"); - goto exit; - } - - if (buffdesc->structsize != STRUCTSIZE(buffdesc, map)) { - BVSETERROR(BVERR_BUFFERDESC_VERS, "argument has invalid size"); - goto exit; - } - - bverror = do_map(buffdesc, 1, &bvbuffmap); - -exit: - return bverror; -} -EXPORT_SYMBOL(bv_map); - -enum bverror bv_unmap(struct bvbuffdesc *buffdesc) -{ - enum bverror bverror; - struct bvbuffmap *bvbuffmap; - struct bvbuffmapinfo *bvbuffmapinfo; - - /* FIXME/TODO: add check for initialization success. */ - - if (buffdesc == NULL) { - BVSETERROR(BVERR_UNK, "invalid argument"); - goto exit; - } - - if (buffdesc->structsize != STRUCTSIZE(buffdesc, map)) { - BVSETERROR(BVERR_BUFFERDESC_VERS, "argument has invalid size"); - goto exit; - } - - bvbuffmap = buffdesc->map; - if (bvbuffmap == NULL) - return BVERR_NONE; - - if (bvbuffmap->structsize != STRUCTSIZE(bvbuffmap, nextmap)) { - BVSETERROR(BVERR_UNK, "invalid map structure size"); - goto exit; - } - - /* Not our mapping? */ - if (bvbuffmap->bv_unmap != bv_unmap) { - bverror = bvbuffmap->bv_unmap(buffdesc); - goto exit; - } - - /* Get the info structure. */ - bvbuffmapinfo = (struct bvbuffmapinfo *) bvbuffmap->handle; - - /* Are there any existing auto-mappings? */ - if (bvbuffmapinfo->automap) { - /* Reset user mappings if any. */ - bvbuffmapinfo->usermap = 0; - - /* Are there mappings from alternative implementations? */ - if (bvbuffmap->nextmap != NULL) { - /* Temporarily remove the record from the mapping - list so that other implementations can proceeed. */ - buffdesc->map = bvbuffmap->nextmap; - - /* Call other implementations. */ - bverror = bv_unmap(buffdesc); - - /* Link the record back into the list. */ - bvbuffmap->nextmap = buffdesc->map; - buffdesc->map = bvbuffmap; - } else - bverror = BVERR_NONE; - - /* No auto-mappings, must be user mapping. */ - } else { - /* Unmap the buffer. */ - bverror = do_unmap(buffdesc, 1); - if (bverror != BVERR_NONE) - goto exit; - - /* Call other implementations. */ - bverror = bv_unmap(buffdesc); - } - -exit: - return bverror; -} -EXPORT_SYMBOL(bv_unmap); - -enum bverror bv_blt(struct bvbltparams *bltparams) -{ - enum bverror bverror = BVERR_NONE; - struct gcalpha *gca = NULL; - struct gcalpha _gca; - unsigned int op, type; - unsigned int batchflags; - unsigned int batchexec = 0; - struct gcbatch *batch; - int src1used, src2used, maskused; - struct srcdesc srcdesc[2]; - unsigned short rop, blend, format; - struct gccommit gccommit; - int srccount, res; - - /* FIXME/TODO: add check for initialization success. */ - - /* Verify blt parameters structure. */ - if (bltparams == NULL) { - BVSETERROR(BVERR_UNK, - "pointer to bvbltparams struct is expected"); - goto exit; - } - - if (bltparams->structsize != STRUCTSIZE(bltparams, callbackdata)) { - BVSETERROR(BVERR_BLTPARAMS_VERS, "argument has invalid size"); - goto exit; - } - - /* Reset the error message. */ - bltparams->errdesc = NULL; - - /* Verify the destination parameters structure. */ - res = verify_surface(0, (union bvinbuff *) &bltparams->dstdesc, - bltparams->dstgeom, &bltparams->dstrect); - 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; - - switch (type) { - case (BVFLAG_BATCH_NONE >> BVFLAG_BATCH_SHIFT): - GC_PRINT(GC_INFO_MSG " BVFLAG_BATCH_NONE\n", - __func__, __LINE__); - bverror = allocate_batch(&batch); - if (bverror != BVERR_NONE) { - bltparams->errdesc = gccontext.bverrorstr; - goto exit; - } - - batchexec = 1; - batchflags = 0x7FFFFFFF; - break; - - case (BVFLAG_BATCH_BEGIN >> BVFLAG_BATCH_SHIFT): - GC_PRINT(GC_INFO_MSG " BVFLAG_BATCH_BEGIN\n", - __func__, __LINE__); - bverror = allocate_batch(&batch); - if (bverror != BVERR_NONE) { - bltparams->errdesc = gccontext.bverrorstr; - goto exit; - } - - bltparams->batch = (struct bvbatch *) batch; - - batchexec = 0; - bltparams->batchflags = - batchflags = 0x7FFFFFFF; - break; - - case (BVFLAG_BATCH_CONTINUE >> BVFLAG_BATCH_SHIFT): - GC_PRINT(GC_INFO_MSG " BVFLAG_BATCH_CONTINUE\n", - __func__, __LINE__); - batch = (struct gcbatch *) bltparams->batch; - if (batch == NULL) { - BVSETBLTERROR(BVERR_BATCH, "batch is not initialized"); - goto exit; - } - - if (batch->structsize != STRUCTSIZE(batch, unmap)) { - BVSETBLTERROR(BVERR_BATCH, "invalid batch"); - goto exit; - } - - batchexec = 0; - batchflags = bltparams->batchflags; - break; - - case (BVFLAG_BATCH_END >> BVFLAG_BATCH_SHIFT): - GC_PRINT(GC_INFO_MSG " BVFLAG_BATCH_END\n", - __func__, __LINE__); - batch = (struct gcbatch *) bltparams->batch; - if (batch == NULL) { - BVSETBLTERROR(BVERR_BATCH, "batch is not initialized"); - goto exit; - } - - if (batch->structsize != STRUCTSIZE(batch, unmap)) { - BVSETBLTERROR(BVERR_BATCH, "invalid batch"); - goto exit; - } - - batchexec = 1; - batchflags = (bltparams->batchflags & BVBATCH_ENDNOP) - ? 0 - : bltparams->batchflags; - break; - - default: - BVSETBLTERROR(BVERR_BATCH, "unrecognized batch type"); - goto exit; - } - - GC_PRINT(GC_INFO_MSG " batchflags=0x%08X\n", - __func__, __LINE__, batchflags); - - if (batchflags != 0) { - switch (op) { - case (BVFLAG_ROP >> BVFLAG_OP_SHIFT): - GC_PRINT(GC_INFO_MSG " BVFLAG_ROP\n", - __func__, __LINE__); - rop = bltparams->op.rop; - src1used = ((rop & 0xCCCC) >> 2) - ^ (rop & 0x3333); - src2used = ((rop & 0xF0F0) >> 4) - ^ (rop & 0x0F0F); - maskused = ((rop & 0xFF00) >> 8) - ^ (rop & 0x00FF); - break; - - case (BVFLAG_BLEND >> BVFLAG_OP_SHIFT): - GC_PRINT(GC_INFO_MSG " BVFLAG_BLEND\n", - __func__, __LINE__); - blend = bltparams->op.blend; - format = (blend & BVBLENDDEF_FORMAT_MASK) - >> BVBLENDDEF_FORMAT_SHIFT; - - bverror = parse_blend(bltparams, - bltparams->op.blend, &_gca); - if (bverror != BVERR_NONE) - goto exit; - - gca = &_gca; - - /* FIXME/TODO: logic here is incorrect */ - switch (format) { - case (BVBLENDDEF_FORMAT_CLASSIC - >> BVBLENDDEF_FORMAT_SHIFT): - src1used - = gca->dst_config->destuse - | gca->src_config->destuse; - src2used - = gca->dst_config->srcuse - | gca->src_config->srcuse; - maskused - = blend & BVBLENDDEF_REMOTE; - break; - - default: - BVSETBLTERROR(BVERR_BLEND, - "unrecognized blend format"); - goto exit; - } - break; - - case (BVFLAG_FILTER >> BVFLAG_OP_SHIFT): - GC_PRINT(GC_INFO_MSG " BVFLAG_FILTER\n", - __func__, __LINE__); - BVSETBLTERROR(BVERR_UNK, "FIXME/TODO"); - goto exit; - - default: - BVSETBLTERROR(BVERR_OP, "unrecognized operation"); - goto exit; - } - - srccount = 0; - - /* Verify the src1 parameters structure. */ - if (src1used) { - GC_PRINT(GC_INFO_MSG " src1used\n", - __func__, __LINE__); - - res = verify_surface( - bltparams->flags & BVBATCH_TILE_SRC1, - &bltparams->src1, bltparams->src1geom, - &bltparams->src1rect); - if (res != -1) { - BVSETBLTSURFERROR(res, g_src1surferr); - goto exit; - } - - /* Same as the destination? */ - if ((bltparams->src1.desc->virtaddr - == bltparams->dstdesc->virtaddr) && - EQ_ORIGIN(bltparams->src1rect, - bltparams->dstrect) && - EQ_SIZE(bltparams->src1rect, - bltparams->dstrect)) { - GC_PRINT(GC_INFO_MSG - " src1 is the same as dst\n", - __func__, __LINE__); - } else { - srcdesc[srccount].index = 0; - srcdesc[srccount].buf = bltparams->src1; - srcdesc[srccount].geom = bltparams->src1geom; - srcdesc[srccount].rect = &bltparams->src1rect; - - srccount += 1; - } - } - - /* Verify the src2 parameters structure. */ - if (src2used) { - GC_PRINT(GC_INFO_MSG " src2used\n", - __func__, __LINE__); - - res = verify_surface( - bltparams->flags & BVBATCH_TILE_SRC2, - &bltparams->src2, bltparams->src2geom, - &bltparams->src2rect); - if (res != -1) { - BVSETBLTSURFERROR(res, g_src2surferr); - goto exit; - } - - /* Same as the destination? */ - if ((bltparams->src2.desc->virtaddr - == bltparams->dstdesc->virtaddr) && - EQ_ORIGIN(bltparams->src2rect, - bltparams->dstrect) && - EQ_SIZE(bltparams->src2rect, - bltparams->dstrect)) { - GC_PRINT(GC_INFO_MSG - " src2 is the same as dst\n", - __func__, __LINE__); - } else { - srcdesc[srccount].index = 1; - srcdesc[srccount].buf = bltparams->src2; - srcdesc[srccount].geom = bltparams->src2geom; - srcdesc[srccount].rect = &bltparams->src2rect; - - srccount += 1; - } - } - - /* Verify the mask parameters structure. */ - if (maskused) { - GC_PRINT(GC_INFO_MSG " maskused\n", - __func__, __LINE__); - res = verify_surface( - bltparams->flags & BVBATCH_TILE_MASK, - &bltparams->mask, bltparams->maskgeom, - &bltparams->maskrect); - if (res != -1) { - BVSETBLTSURFERROR(res, g_masksurferr); - goto exit; - } - - BVSETERROR(BVERR_UNK, "FIXME/TODO"); - goto exit; - } - - GC_PRINT(GC_INFO_MSG " srccount = %d\n", - __func__, __LINE__, srccount); - - switch (srccount) { - case 0: - bverror = do_blit(bltparams, batch, NULL, 0, gca); - break; - - case 1: - if (EQ_SIZE((*srcdesc[0].rect), bltparams->dstrect)) - bverror = do_blit(bltparams, batch, - srcdesc, 1, gca); - else if ((srcdesc[0].rect->width == 1) && - (srcdesc[0].rect->height == 1)) - bverror = do_fill(bltparams, batch, srcdesc); - else - bverror = do_filter(bltparams, batch); - break; - - case 2: - if (EQ_SIZE((*srcdesc[0].rect), bltparams->dstrect)) - if (EQ_SIZE((*srcdesc[1].rect), - bltparams->dstrect)) - bverror = do_blit(bltparams, batch, - srcdesc, 2, gca); - else - BVSETBLTERROR( - BVERR_UNK, "FIXME/TODO"); - else - if (EQ_SIZE((*srcdesc[1].rect), - bltparams->dstrect)) - BVSETBLTERROR( - BVERR_UNK, "FIXME/TODO"); - else - BVSETBLTERROR( - BVERR_UNK, "FIXME/TODO"); - } - } - - if (batchexec) { - /* Finalize the current operation. */ - bverror = batch->batchend(bltparams, batch); - if (bverror != BVERR_NONE) - goto exit; - -#if GC_DUMP - dumpbuffer(batch); -#endif - - gccommit.gcerror = GCERR_NONE; - gccommit.buffer = batch->bufhead; - - gc_commit_wrapper(&gccommit); - if (gccommit.gcerror != GCERR_NONE) { - BVSETBLTERRORARG(BVERR_UNK, - "blit error occured (0x%08X)", - gccommit.gcerror); - goto exit; - } - } - -exit: - if ((batch != NULL) && batchexec) { - process_scheduled_unmap(batch); - free_batch(batch); - bltparams->batch = NULL; - } - - return bverror; -} -EXPORT_SYMBOL(bv_blt); diff --git a/gcbv/gcioctl.h b/gcbv/gcioctl.h deleted file mode 100644 index 8d966c3..0000000 --- a/gcbv/gcioctl.h +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (c) 2011, Texas Instruments, Inc. - * 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 Texas Instruments, Inc. 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 TEXAS INSTRUMENTS, INC. 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 GCIOCTL_H -#define GCIOCTL_H - -#include "gcerror.h" -#include <bverror.h> - -/* IOCTL parameters. */ -#define GCIOCTL_TYPE 0x5D -#define GCIOCTL_BASE 0x5D - -/******************************************************************************* - * Commit API entry. - */ - -struct gccommit; -struct gcbuffer; -struct gcfixup; - -#define GCIOCTL_COMMIT _IOWR(GCIOCTL_TYPE, GCIOCTL_BASE + 0x10, struct gccommit) - -/* Commit header; contains pointers to the head and the tail of a linked list - of command buffers to execute. */ -struct gccommit { - enum gcerror gcerror; /* Return status code. */ - struct gcbuffer *buffer; /* Command buffer list. */ -}; - -/* Command buffer header. */ -#define GC_BUFFER_SIZE 81920 -struct gcbuffer { - struct gcfixup *fixuphead; /* Address fixup list. */ - struct gcfixup *fixuptail; - - unsigned int pixelcount; /* Number of pixels to be rendered. */ - - unsigned int *head; /* Pointers to the head and tail */ - unsigned int *tail; /* of the command buffer. */ - - unsigned int available; /* Number of bytes available in the - buffer. */ - struct gcbuffer *next; /* Pointer to the next commmand - buffer. */ -}; - -/* Fixup entry. */ -struct gcfixupentry { - unsigned int dataoffset; /* Offset into the commmand buffer - where fixup is to be performed. */ - unsigned int surfoffset; /* Offset to be added to the base - address of the surface. */ -}; - -/* Address fixup array. */ -#define GC_FIXUP_MAX 1024 -struct gcfixup { - struct gcfixup *next; - unsigned int count; - struct gcfixupentry fixup[GC_FIXUP_MAX]; -}; - -/******************************************************************************* - * Map/unmap API entries. - */ - -struct gcmap; - -#define GCIOCTL_MAP _IOWR(GCIOCTL_TYPE, GCIOCTL_BASE + 0x20, struct gcmap) -#define GCIOCTL_UNMAP _IOWR(GCIOCTL_TYPE, GCIOCTL_BASE + 0x21, struct gcmap) - -struct gcmap { - enum gcerror gcerror; /* Return status code. */ - unsigned int handle; /* Mapped handle of the buffer. */ - - void *logical; /* Pointer to the buffer. */ - unsigned int size; /* Size of the buffer. */ - unsigned long pagecount; /* Number of physical pages */ - unsigned long *pagearray; /* List of physical pages */ -}; - -/******************************************************************************* - * BLTsville: blit API entry. - */ - -struct gcbvblt; - -#define GCIOCTL_BVBLT _IOWR(GCIOCTL_TYPE, GCIOCTL_BASE + 0x30, struct gcbvblt) - -struct gcbvblt { - enum bverror bverror; /* Return status code. */ - struct bvbltparams *bltparams; /* Blit parameters. */ - char *errdesc; /* Blit error message. */ - int errdesclen; /* Maximum length of the error - message. */ -}; - -/******************************************************************************* - * BLTsville: map/unmap API entries. - */ - -struct gcbvmap; - -#define GCIOCTL_BVMAP _IOWR(GCIOCTL_TYPE, GCIOCTL_BASE + 0x40, struct gcbvmap) -#define GCIOCTL_BVUNMAP _IOWR(GCIOCTL_TYPE, GCIOCTL_BASE + 0x41, struct gcbvmap) - -struct gcbvmap { - enum bverror bverror; /* Return status code. */ - struct bvbuffdesc *buffdesc; /* Surface descriptor. */ -}; - -#endif diff --git a/gcbv/gcmain.c b/gcbv/gcmain.c index 87dcab5..52fd331 100644 --- a/gcbv/gcmain.c +++ b/gcbv/gcmain.c @@ -1,5 +1,7 @@ /* - * Copyright (c) 2011, Texas Instruments, Inc. + * Copyright (c) 2012, + * Texas Instruments, Inc. and Vivante Corporation + * * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -25,46 +27,182 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include <gcx.h> -#include <gc2d.h> #include "gcmain.h" +#include <semaphore.h> -#ifndef GC_DUMP -# define GC_DUMP 0 -#endif +#define GCZONE_NONE 0 +#define GCZONE_ALL (~0U) +#define GCZONE_INIT (1 << 0) +#define GCZONE_CALLBACK (1 << 1) -#if GC_DUMP -# define GC_PRINT gcdump -#else -# define GC_PRINT(...) -#endif +GCDBG_FILTERDEF(gcmain, GCZONE_NONE, + "init", + "callback") + + +static int g_handle; -static int g_fd; /* Open device file descriptor. */ /******************************************************************************* - * IOCTL wrappers. + * Callback manager. */ -#if GC_DUMP -# define GC_IOCTL(result, id, data) \ - { \ - sleep(1); \ - result = ioctl(g_fd, id, data); \ +struct gccallbackinfo { + /* Callback handle. */ + unsigned long handle; + + /* Termination semaphore. */ + sem_t stop; + + /* Callback thread handle. */ + pthread_t thread; +}; + +struct gccallbackinfo g_callbackinfo; + +static void *callbackthread(void *_gccallbackinfo) +{ + struct gccallbackinfo *gccallbackinfo; + struct gccmdcallbackwait gccmdcallbackwait; + int result; + + /* Get callback info. */ + gccallbackinfo = (struct gccallbackinfo *) _gccallbackinfo; + + /* Initialize the command. */ + gccmdcallbackwait.handle = gccallbackinfo->handle; + gccmdcallbackwait.timeoutms = 2000; + + /* Enter wait loop. */ + while (1) { + /* Call the kernel to wait for callback event. */ + result = ioctl(g_handle, GCIOCTL_CALLBACK_WAIT, + &gccmdcallbackwait); + if (result == 0) { + if (gccmdcallbackwait.gcerror == GCERR_NONE) { + /* Work completed. */ + GCDBG(GCZONE_CALLBACK, "callback 0x%08X(0x%08X).\n", + (unsigned int) gccmdcallbackwait.callback, + (unsigned int) gccmdcallbackwait.callbackparam); + + /* Invoke the callback. */ + gccmdcallbackwait.callback( + gccmdcallbackwait.callbackparam); + } else if (gccmdcallbackwait.gcerror == GCERR_TIMEOUT) { + /* Timeout. */ + GCDBG(GCZONE_CALLBACK, "callback wait timeout.\n"); + } else { + /* Error occurred. */ + GCERR("callback wait failed (0x%08X).\n", + gccmdcallbackwait.gcerror); + break; + } + } + else if (result != -EINTR) { + GCERR("callback wait ioctl failed (%d).\n", result); + break; + } + + /* Stop requested? */ + if (sem_trywait(&gccallbackinfo->stop) == 0) { + GCDBG(GCZONE_CALLBACK, "terminating.\n"); + break; + } } -#else -# define GC_IOCTL(result, id, data) \ - { \ - result = ioctl(g_fd, id, data); \ + + return NULL; +} + +static int callback_start(struct gccallbackinfo *gccallbackinfo) +{ + int result; + struct gccmdcallback gccmdcallback; + + /* Initialize callback. */ + gccmdcallback.handle = 0; + result = ioctl(g_handle, GCIOCTL_CALLBACK_ALLOC, &gccmdcallback); + if (result != 0) { + GCERR("callback ioctl failed (%d).\n", result); + goto fail; + } + + if (gccmdcallback.gcerror != GCERR_NONE) { + GCERR("failed to initialize callback mechanism (0x%08X).\n", + gccmdcallback.gcerror); + goto fail; + } + + gccallbackinfo->handle = gccmdcallback.handle; + + /* Initialize the termiantion semaphore. */ + result = sem_init(&gccallbackinfo->stop, 0, 0); + if (result != 0) { + GCERR("callback semaphore init failed (%d).\n", result); + goto fail; + } + + /* Start the thread. */ + result = pthread_create(&gccallbackinfo->thread, NULL, + callbackthread, gccallbackinfo); + if (result != 0) { + GCERR("failed to start callback thread.\n"); + goto fail; + } + + /* Success. */ + return 0; + +fail: + if (gccmdcallback.handle != 0) + ioctl(g_handle, GCIOCTL_CALLBACK_FREE, &gccmdcallback); + + return result; +} + +static void callback_stop(struct gccallbackinfo *gccallbackinfo) +{ + struct gccmdcallback gccmdcallback; + + /* Stop the thread. */ + GCDBG(GCZONE_CALLBACK, "stopping active client."); + + sem_post(&gccallbackinfo->stop); + pthread_kill(gccallbackinfo->thread, SIGINT); + + GCDBG(GCZONE_CALLBACK, "waiting to join callback thread...\n"); + + pthread_join(gccallbackinfo->thread, NULL); + + gccallbackinfo->thread = 0; + + /* Free kernel resources. */ + if (gccmdcallback.handle != 0) { + gccmdcallback.handle = gccallbackinfo->handle; + ioctl(g_handle, GCIOCTL_CALLBACK_FREE, &gccmdcallback); + gccallbackinfo->handle = 0; } +} + + +/******************************************************************************* + * IOCTL wrappers. + */ + +#if GCDEBUG_ENABLE && 0 +#define GCPRINTDELAY() sleep(1) +#else +#define GCPRINTDELAY() #endif void gc_map_wrapper(struct gcmap *gcmap) { int result; - GC_IOCTL(result, GCIOCTL_MAP, gcmap); + + GCPRINTDELAY(); + result = ioctl(g_handle, GCIOCTL_MAP, gcmap); + if (result != 0) { - GC_PRINT(GC_ERR_MSG "ioctl failed (%d)\n", - __func__, __LINE__, result); + GCERR("ioctl failed (%d).\n", result); gcmap->gcerror = GCERR_IOCTL; } } @@ -72,10 +210,12 @@ void gc_map_wrapper(struct gcmap *gcmap) void gc_unmap_wrapper(struct gcmap *gcmap) { int result; - GC_IOCTL(result, GCIOCTL_UNMAP, gcmap); + + GCPRINTDELAY(); + result = ioctl(g_handle, GCIOCTL_UNMAP, gcmap); + if (result != 0) { - GC_PRINT(GC_ERR_MSG "ioctl failed (%d)\n", - __func__, __LINE__, result); + GCERR("ioctl failed (%d).\n", result); gcmap->gcerror = GCERR_IOCTL; } } @@ -83,14 +223,18 @@ void gc_unmap_wrapper(struct gcmap *gcmap) void gc_commit_wrapper(struct gccommit *gccommit) { int result; - GC_IOCTL(result, GCIOCTL_COMMIT, gccommit); + + GCPRINTDELAY(); + gccommit->handle = g_callbackinfo.handle; + result = ioctl(g_handle, GCIOCTL_COMMIT, gccommit); + if (result != 0) { - GC_PRINT(GC_ERR_MSG "ioctl failed (%d)\n", - __func__, __LINE__, result); + GCERR("ioctl failed (%d).\n", result); gccommit->gcerror = GCERR_IOCTL; } } + /******************************************************************************* * Convert floating point in 0..1 range to an 8-bit value in range 0..255. */ @@ -142,36 +286,87 @@ unsigned char gcfp2norm8(float value) return (unsigned char) mantissa; } + +/******************************************************************************* + * Cache operation wrapper. + */ + +enum bverror gcbvcacheop(int count, struct c2dmrgn rgn[], + enum bvcacheop cacheop) +{ + int result; + struct gccachexfer xfer; + + if ((count < 0) || (count > 3)) + return BVERR_CACHEOP; + + xfer.count = count; + xfer.dir = cacheop; + memcpy(xfer.rgn, rgn, count * sizeof(struct c2dmrgn)); + + GCPRINTDELAY(); + result = ioctl(g_handle, GCIOCTL_CACHE, &xfer); + + if (result != 0) + GCERR("ioctl failed (%d).\n", result); + + return BVERR_NONE; +} + + /******************************************************************************* * Device init/cleanup. */ -extern void dev_init(void) __attribute__((constructor)); -extern void dev_init(void) +void __attribute__((constructor)) dev_init(void) { - GC_PRINT(GC_INFO_MSG "\n", __func__, __LINE__); + char* env; + + env = getenv("GCBV_DEBUG"); + if (env && (atol(env) != 0)) + GCDBG_ENABLEDUMP(); + + GCDBG_INIT(); + GCDBG_REGISTER(gcmain); - g_fd = open("/dev/gcioctl", O_RDWR); - if (g_fd == -1) { - GC_PRINT(GC_ERR_MSG " failed to open device (%d)\n", - __func__, __LINE__, errno); - goto exit; + GCENTER(GCZONE_INIT); + + g_handle = open("/dev/gcioctl", O_RDWR); + if (g_handle == -1) { + GCERR("failed to open device (%d).\n", errno); + goto fail; } + if (callback_start(&g_callbackinfo) != 0) + goto fail; + bv_init(); -exit:; + GCEXIT(GCZONE_INIT); + return; + +fail: + if (g_handle > 0) { + close(g_handle); + g_handle = 0; + } + + GCEXIT(GCZONE_INIT); } -extern void dev_exit(void) __attribute__((destructor)); -extern void dev_exit(void) +void __attribute__((destructor)) dev_exit(void) { - GC_PRINT(GC_INFO_MSG "\n", __func__, __LINE__); + GCENTER(GCZONE_INIT); bv_exit(); + callback_stop(&g_callbackinfo); - if (g_fd != 0) { - close(g_fd); - g_fd = 0; + if (g_handle != 0) { + close(g_handle); + g_handle = 0; } + + GCEXIT(GCZONE_INIT); + GCDBG_EXIT(); } + diff --git a/gcbv/gcmain.h b/gcbv/gcmain.h index 3c69701..de2f3c2 100644 --- a/gcbv/gcmain.h +++ b/gcbv/gcmain.h @@ -1,5 +1,7 @@ /* - * Copyright (c) 2011, Texas Instruments, Inc. + * Copyright (c) 2012, + * Texas Instruments, Inc. and Vivante Corporation + * * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,28 +31,55 @@ #define GCMAIN_H #include <stdio.h> +#include <stdlib.h> +#include <stdbool.h> #include <errno.h> #include <fcntl.h> #include <unistd.h> #include <sys/ioctl.h> -#include "gcioctl.h" +#include <gcx.h> +#include <gcioctl.h> +#include <bltsville.h> +#include <bvinternal.h> +#include <bverror.h> + +#define GC_DEV_NAME "gc2duser" -#define DEV_NAME "gc2dusr" /******************************************************************************* * Miscellaneous macros. */ +/* Not present in userspace bltsville headers */ +#define BVAT_PHYSDESC 0xDEADBEEF + #define gcalloc(type, size) \ (type *) malloc(size) #define gcfree(ptr) \ free(ptr) -#define gcdump fprintf +#define max(x, y) (x > y ? x : y) +#define min(x, y) (x < y ? x : y) #define EXPORT_SYMBOL(sym) +#define gc_debug_blt(...) + + +/******************************************************************************* + * Not defined in bltsville userspace headers. + */ + +struct bvphysdesc { + unsigned int structsize; /* used to identify struct version */ + unsigned long pagesize; /* page size in bytes */ + unsigned long *pagearray; /* array of physical pages */ + unsigned int pagecount; /* number of pages in the pagearray */ + unsigned long pageoffset; /* page offset in bytes */ +}; + + /******************************************************************************* * IOCTL wrappers. */ @@ -59,17 +88,32 @@ void gc_map_wrapper(struct gcmap *gcmap); void gc_unmap_wrapper(struct gcmap *gcmap); void gc_commit_wrapper(struct gccommit *gccommit); + /******************************************************************************* * Floating point conversions. */ unsigned char gcfp2norm8(float value); + +/******************************************************************************* + * Cache operation wrapper. + */ + +enum bverror gcbvcacheop(int count, struct c2dmrgn rgn[], + enum bvcacheop cacheop); + + /******************************************************************************* - * BLTsville initialization/cleanup. + * BLTsville API. */ void bv_init(void); void bv_exit(void); +enum bverror bv_map(struct bvbuffdesc *buffdesc); +enum bverror bv_unmap(struct bvbuffdesc *buffdesc); +enum bverror bv_blt(struct bvbltparams *bltparams); +enum bverror bv_cache(struct bvcopparams *copparams); + #endif diff --git a/gcbv/mirror/gcbv.c b/gcbv/mirror/gcbv.c new file mode 100644 index 0000000..9f913ae --- /dev/null +++ b/gcbv/mirror/gcbv.c @@ -0,0 +1,4156 @@ +/* + * 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, + * Texas Instruments, Inc. and 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, + * Texas Instruments, Inc. and Vivante Corporation. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Vivante Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "gcmain.h" + +#define GCZONE_NONE 0 +#define GCZONE_ALL (~0U) +#define GCZONE_MAPPING (1 << 0) +#define GCZONE_BUFFER (1 << 1) +#define GCZONE_FIXUP (1 << 2) +#define GCZONE_FORMAT (1 << 3) +#define GCZONE_COLOR (1 << 4) +#define GCZONE_BLEND (1 << 5) +#define GCZONE_DEST (1 << 6) +#define GCZONE_SURF (1 << 7) +#define GCZONE_DO_FILL (1 << 8) +#define GCZONE_DO_BLIT (1 << 9) +#define GCZONE_DO_FILTER (1 << 10) +#define GCZONE_CLIP (1 << 11) +#define GCZONE_BATCH (1 << 12) +#define GCZONE_BLIT (1 << 13) +#define GCZONE_CACHE (1 << 14) + +GCDBG_FILTERDEF(gcbv, GCZONE_NONE, + "mapping", + "buffer", + "fixup", + "format", + "color", + "blend", + "dest", + "surf", + "do_fill", + "do_blit", + "do_filter", + "clip", + "batch", + "blit", + "cache") + + +/******************************************************************************* +** Miscellaneous defines and macros. +*/ + +#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 GC_BASE_ALIGN 64 + +#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); \ + } \ +} +#else +#define GCDUMPSCHEDULE() +#endif + + +/******************************************************************************* +** Internal structures. +*/ + +/* Used by blitters to define an array of valid sources. */ +struct srcinfo { + int index; + union bvinbuff buf; + struct bvsurfgeom *geom; + struct bvrect *rect; +}; + +/* 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; + + /* Clipping deltas; used to correct the source coordinates for + * single source blits. */ + int deltaleft; + int deltatop; + int deltaright; + int deltabottom; + + /* Destination format. */ + struct bvformatxlate *dstformat; + + /* Destination rectangle coordinates. */ + unsigned short dstleft; + unsigned short dsttop; + unsigned short dstright; + unsigned short dstbottom; + + /* Destination base address alignment offset in pixels. */ + unsigned int dstoffset; + +#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; + + +/******************************************************************************* + * Debugging. + */ + +#if GCDEBUG_ENABLE +#define GCDUMPBATCH(batch) \ + dumpbatch(batch) + +static void dumpbatch(struct gcbatch *batch) +{ + if ((GCDBGFILTER.zone & GCZONE_BATCH) != 0) { + struct gcbuffer *buffer; + unsigned int i, size; + struct gcfixup *fixup; + + GCDBG(GCZONE_BATCH, "BATCH DUMP (0x%08X)\n", + (unsigned int) batch); + + buffer = batch->bufhead; + while (buffer != NULL) { + fixup = buffer->fixuphead; + while (fixup != NULL) { + GCDBG(GCZONE_BATCH, + " Fixup table @ 0x%08X, count = %d:\n", + (unsigned int) fixup, fixup->count); + + for (i = 0; i < fixup->count; i += 1) { + GCDBG(GCZONE_BATCH, " [%02d]" + " buffer offset = 0x%08X," + " surface offset = 0x%08X\n", + i, + fixup->fixup[i].dataoffset * 4, + fixup->fixup[i].surfoffset); + } + + fixup = fixup->next; + } + + size = (unsigned char *) buffer->tail + - (unsigned char *) buffer->head; + GCDUMPBUFFER(GCZONE_BUFFER, buffer->head, 0, size); + + buffer = buffer->next; + } + } +} +#else +# define GCDUMPBATCH(...) +#endif + + +/******************************************************************************* + * Error handling. + */ + +#define SETERROR(message) \ +do { \ + snprintf(gccontext.bverrorstr, sizeof(gccontext.bverrorstr), \ + "%s(%d): " message, __func__, __LINE__); \ + GCDUMPSTRING("%s\n", gccontext.bverrorstr); \ +} while (0) + +#define SETERRORARG(message, arg) \ +do { \ + snprintf(gccontext.bverrorstr, sizeof(gccontext.bverrorstr), \ + "%s(%d): " message, __func__, __LINE__, arg); \ + GCDUMPSTRING("%s\n", gccontext.bverrorstr); \ +} while (0) + +#define BVSETERROR(error, message) \ +do { \ + SETERROR(message); \ + bverror = error; \ +} while (0) + +#define BVSETERRORARG(error, message, arg) \ +do { \ + SETERRORARG(message, arg); \ + bverror = error; \ +} while (0) + +#define BVSETBLTERROR(error, message) \ +do { \ + BVSETERROR(error, message); \ + bltparams->errdesc = gccontext.bverrorstr; \ +} while (0) + +#define BVSETBLTERRORARG(error, message, arg) \ +do { \ + BVSETERRORARG(error, message, arg); \ + bltparams->errdesc = gccontext.bverrorstr; \ +} while (0) + +#define BVSETSURFERROR(errorid, errordesc) \ +do { \ + snprintf(gccontext.bverrorstr, sizeof(gccontext.bverrorstr), \ + g_surferr[errorid].message, __func__, __LINE__, errordesc.id); \ + GCDUMPSTRING("%s\n", gccontext.bverrorstr); \ + bverror = errordesc.base + g_surferr[errorid].offset; \ +} while (0) + +#define BVSETBLTSURFERROR(errorid, errordesc) \ +do { \ + BVSETSURFERROR(errorid, errordesc); \ + bltparams->errdesc = gccontext.bverrorstr; \ +} while (0) + +#define GCBVERR_DESC 0 +#define GCBVERR_DESC_VERS 1 +#define GCBVERR_DESC_VIRTADDR 2 +#define GCBVERR_TILE 3 +#define GCBVERR_TILE_VERS 4 +#define GCBVERR_TILE_VIRTADDR 5 +#define GCBVERR_GEOM 6 +#define GCBVERR_GEOM_VERS 7 +#define GCBVERR_GEOM_FORMAT 8 + +struct bvsurferrorid { + char *id; + enum bverror base; +}; + +struct bvsurferror { + unsigned int offset; + char *message; +}; + +static struct bvsurferror g_surferr[] = { + /* GCBVERR_DESC */ + { 0, "%s(%d): %s desc structure is not set" }, + + /* GCBVERR_DESC_VERS */ + { 100, "%s(%d): %s desc structure has invalid size" }, + + /* GCBVERR_DESC_VIRTADDR */ + { 200, "%s(%d): %s desc virtual pointer is not set" }, + + /* GCBVERR_TILE: FIXME/TODO define error code */ + { 0, "%s(%d): %s tileparams structure is not set" }, + + /* GCBVERR_TILE_VERS */ + { 3000, "%s(%d): %s tileparams structure has invalid size" }, + + /* GCBVERR_TILE_VIRTADDR: FIXME/TODO define error code */ + { 200, "%s(%d): %s tileparams virtual pointer is not set" }, + + /* GCBVERR_GEOM */ + { 1000, "%s(%d): %s geom structure is not set" }, + + /* GCBVERR_GEOM_VERS */ + { 1100, "%s(%d): %s geom structure has invalid size" }, + + /* GCBVERR_GEOM_FORMAT */ + { 1200, "%s(%d): %s invalid format specified" }, +}; + +static struct bvsurferrorid g_destsurferr = { "dst", BVERR_DSTDESC }; +static struct bvsurferrorid g_src1surferr = { "src1", BVERR_SRC1DESC }; +static struct bvsurferrorid g_src2surferr = { "src2", BVERR_SRC2DESC }; +static struct bvsurferrorid g_masksurferr = { "mask", BVERR_MASKDESC }; + + +/******************************************************************************* + * Callback info management. + */ + +static enum bverror get_callbackinfo(struct gccallbackinfo **gccallbackinfo) +{ + enum bverror bverror; + struct gccallbackinfo *temp; + + /* Lock access to callback info lists. */ + GCLOCK(&gccontext.callbacklock); + + 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); + } else { + struct list_head *head; + head = gccontext.callbackvac.next; + temp = list_entry(head, struct gccallbackinfo, link); + list_move(head, &gccontext.callbacklist); + } + + *gccallbackinfo = temp; + bverror = BVERR_NONE; + +exit: + /* Unlock access to callback info lists. */ + GCUNLOCK(&gccontext.callbacklock); + + return bverror; +} + +static void free_callback(struct gccallbackinfo *gccallbackinfo) +{ + /* Lock access to callback info lists. */ + GCLOCK(&gccontext.callbacklock); + + list_move(&gccallbackinfo->link, &gccontext.callbackvac); + + /* Unlock access to callback info lists. */ + GCUNLOCK(&gccontext.callbacklock); +} + +void gccallback(void *callbackparam) +{ + struct gccallbackinfo *gccallbackinfo; + + GCENTER(GCZONE_BLIT); + + gccallbackinfo = (struct gccallbackinfo *) callbackparam; + GCDBG(GCZONE_BLIT, "bltsville_callback = 0x%08X\n", + (unsigned int) gccallbackinfo->callbackfn); + GCDBG(GCZONE_BLIT, "bltsville_param = 0x%08X\n", + (unsigned int) gccallbackinfo->callbackdata); + + gccallbackinfo->callbackfn(NULL, gccallbackinfo->callbackdata); + free_callback(gccallbackinfo); + + GCEXIT(GCZONE_BLIT); +} + + +/******************************************************************************* + * Memory management. + */ + +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; + unsigned int offset; + 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 + & ~(GC_BASE_ALIGN - 1); + offset = bvphysdesc->pageoffset + & (GC_BASE_ALIGN - 1); + gcmap.pagesize = bvphysdesc->pagesize; + gcmap.pagearray = bvphysdesc->pagearray; + + 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, "specified pageoffset = %lu\n", + bvphysdesc->pageoffset); + GCDBG(GCZONE_MAPPING, "aligned pageoffset = %d\n", + gcmap.buf.offset); + } else { + gcmap.buf.logical + = (void *) ((unsigned int) bvbuffdesc->virtaddr + & ~(GC_BASE_ALIGN - 1)); + offset = (unsigned int) bvbuffdesc->virtaddr + & (GC_BASE_ALIGN - 1); + gcmap.pagesize = 0; + gcmap.pagearray = NULL; + + 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); + } + + gcmap.size = offset + bvbuffdesc->length; + + GCDBG(GCZONE_MAPPING, "surface offset = %d\n", offset); + 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 gcbatch **batch); +static void free_batch(struct gcbatch *batch); +static enum bverror append_buffer(struct gcbatch *batch); + +static enum bverror do_end(struct bvbltparams *bltparams, + struct gcbatch *batch) +{ + return BVERR_NONE; +} + +static enum bverror allocate_batch(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) { + BVSETERROR(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(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 gcbatch *batch) +{ + enum bverror bverror; + struct gcbuffer *temp; + + GCENTERARG(GCZONE_BUFFER, "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) { + BVSETERROR(BVERR_OOM, + "command buffer allocation failed"); + goto exit; + } + + GCDBG(GCZONE_BUFFER, "allocated new buffer = 0x%08X\n", + (unsigned int) temp); + } else { + temp = gccontext.vac_buffers; + gccontext.vac_buffers = temp->next; + + GCDBG(GCZONE_BUFFER, "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, "new buffer appended = 0x%08X\n", + (unsigned int) temp); + + bverror = BVERR_NONE; + +exit: + /* Unlock access to buffer management. */ + GCUNLOCK(&gccontext.bufferlock); + + GCEXITARG(GCZONE_BUFFER, "bv%s = %d\n", + (bverror == BVERR_NONE) ? "result" : "error", bverror); + return bverror; +} + +static enum bverror add_fixup(struct gcbatch *batch, unsigned int *fixup, + unsigned int surfoffset) +{ + enum bverror bverror; + 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) { + BVSETERROR(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); + + bverror = BVERR_NONE; + +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 gcbatch *batch, + unsigned int size, + void **buffer) +{ + enum bverror bverror; + struct gcbuffer *curbuf; + + GCENTERARG(GCZONE_BUFFER, "batch = 0x%08X, size = %d\n", + (unsigned int) batch, size); + + /* Get the current command buffer. */ + curbuf = batch->buftail; + + GCDBG(GCZONE_BUFFER, "buffer = 0x%08X, available = %d\n", + (unsigned int) curbuf, curbuf->available); + + if (curbuf->available < size) { + bverror = append_buffer(batch); + if (bverror != BVERR_NONE) + goto exit; + + curbuf = batch->buftail; + } + + if (curbuf->available < size) { + GCDBG(GCZONE_BUFFER, "requested size is too large.\n"); + BVSETERROR(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, "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) + +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 { + unsigned bitspp; + unsigned format; + unsigned swizzle; + struct bvcsrgb rgba; +}; + +#define BVFORMATRGBA(BPP, Format, Swizzle, R, G, B, A) \ +{ \ + 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 } } } + +static struct bvformatxlate g_format_nv12 = { + .bitspp = 8, + .format = GCREG_DE_FORMAT_NV12, +}; + +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; + + 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. + */ + +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; +}; + +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; + + unsigned int src1used; + unsigned int src2used; +}; + +#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; + + 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: + return bverror; +} + + +/******************************************************************************* + * Surface compare and validation. + */ + +static inline bool equal_rects(struct bvrect *rect1, struct bvrect *rect2) +{ + if (rect1->left != rect2->left) + return false; + + if (rect1->top != rect2->top) + return false; + + if (rect1->width != rect2->width) + return false; + + if (rect1->height != rect2->height) + return false; + + return true; +} + +/* The function verifies whether the two buffer descriptors and rectangles + define the same physical area. */ +static bool same_phys_area(struct bvbuffdesc *surf1, struct bvrect *rect1, + struct bvbuffdesc *surf2, struct bvrect *rect2) +{ + struct bvphysdesc *physdesc1; + struct bvphysdesc *physdesc2; + + /* If pointers are the same, things are much easier. */ + if (surf1 == surf2) + /* Compare the rectangles. For simplicity we don't consider + cases with partially overlapping rectangles at this time. */ + return equal_rects(rect1, rect2); + + /* Assume diffrent areas if the types are different. */ + if (surf1->auxtype != surf2->auxtype) + return false; + + if (surf1->auxtype == BVAT_PHYSDESC) { + physdesc1 = (struct bvphysdesc *) surf1->auxptr; + physdesc2 = (struct bvphysdesc *) surf2->auxptr; + + /* Same physical descriptor? */ + if (physdesc1 == physdesc2) + return equal_rects(rect1, rect2); + + /* Same page array? */ + if (physdesc1->pagearray == physdesc2->pagearray) + return equal_rects(rect1, rect2); + + /* Pageoffsets must match since different buffers + * can share the same first page (eg nv12). + */ + if (physdesc1->pageoffset != physdesc2->pageoffset) + return false; + + /* Assume the same surface if first pages match. */ + if (physdesc1->pagearray[0] == physdesc2->pagearray[0]) + return equal_rects(rect1, rect2); + + } else { + if (surf1->virtaddr == surf2->virtaddr) + return equal_rects(rect1, rect2); + } + + 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) +{ + int ret; + + GCENTER(GCZONE_SURF); + + if (tile) { + if (surf->tileparams == NULL) { + ret = GCBVERR_TILE; + goto exit; + } + + if (surf->tileparams->structsize < + STRUCTSIZE(surf->tileparams, srcheight)) { + ret = GCBVERR_TILE_VERS; + goto exit; + } + + /* FIXME/TODO */ + ret = GCBVERR_TILE; + goto exit; + } else { + if (surf->desc == NULL) { + ret = GCBVERR_DESC; + goto exit; + } + + if (surf->desc->structsize < STRUCTSIZE(surf->desc, map)) { + ret = GCBVERR_DESC_VERS; + goto exit; + } + } + + if (geom == NULL) { + ret = GCBVERR_GEOM; + goto exit; + } + + if (geom->structsize < STRUCTSIZE(geom, palette)) { + ret = GCBVERR_GEOM_VERS; + goto exit; + } + + /* Validation successful. */ + ret = -1; + +exit: + GCEXITARG(GCZONE_SURF, "ret = %d\n", ret); + return ret; +} + +#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 + + +/******************************************************************************* + * Primitive renderers. + */ + +static enum bverror set_dst(struct bvbltparams *bltparams, + struct gcbatch *batch, + struct bvbuffmap *dstmap) +{ + enum bverror bverror = BVERR_NONE; + struct bvsurfgeom *dstgeom = bltparams->dstgeom; + struct gcmodst *gcmodst; + unsigned int dstoffset; + + GCENTER(GCZONE_DEST); + + /* Did destination surface change? */ + if ((batch->batchflags & BVBATCH_DST) == 0) + goto exit; + + GCDBG(GCZONE_DEST, "destination surface changed.\n"); + + /* Parse the destination format. */ + GCDBG(GCZONE_FORMAT, "parsing the destination format.\n"); + if (!parse_format(dstgeom->format, &batch->dstformat)) { + BVSETBLTERRORARG(BVERR_DSTGEOM_FORMAT, + "invalid destination format (%d)", + dstgeom->format); + goto exit; + } + + /* Validate geometry. */ + if (!valid_geom(bltparams->dstdesc, bltparams->dstgeom, + batch->dstformat)) { + BVSETBLTERROR(BVERR_DSTGEOM, + "destination geom exceeds surface size"); + goto exit; + } + + /* Compute the destination offset in pixels needed to compensate + for the surface base address misalignment if any. */ + dstoffset = (((unsigned int) bltparams->dstdesc->virtaddr + & (GC_BASE_ALIGN - 1)) * 8) + / batch->dstformat->bitspp; + + /* Have to reset clipping with the new offset. */ + if (dstoffset != batch->dstoffset) { + batch->dstoffset = dstoffset; + batch->batchflags |= BVBATCH_CLIPRECT_ORIGIN; + } + + /* Allocate command buffer. */ + bverror = claim_buffer(batch, sizeof(struct gcmodst), + (void **) &gcmodst); + if (bverror != BVERR_NONE) { + BVSETBLTERROR(BVERR_OOM, + "failed to allocate command buffer"); + goto exit; + } + + /* Add the address fixup. */ + add_fixup(batch, &gcmodst->address, 0); + + /* Set surface parameters. */ + gcmodst->address_ldst = gcmodst_address_ldst; + gcmodst->address = GET_MAP_HANDLE(dstmap); + gcmodst->stride = dstgeom->virtstride; + + /* Set surface width and height. */ + gcmodst->rotation.raw = 0; + gcmodst->rotation.reg.surf_width = dstgeom->width + dstoffset; + gcmodst->rotationheight_ldst = gcmodst_rotationheight_ldst; + gcmodst->rotationheight.raw = 0; + gcmodst->rotationheight.reg.height = dstgeom->height; + + GCDBG(GCZONE_DEST, "destination surface:\n"); + GCDBG(GCZONE_DEST, " dstvirtaddr = 0x%08X\n", + (unsigned int) bltparams->dstdesc->virtaddr); + GCDBG(GCZONE_DEST, " dstaddr = 0x%08X\n", + (unsigned int) GET_MAP_HANDLE(dstmap)); + GCDBG(GCZONE_DEST, " dstoffset = %d\n", dstoffset); + GCDBG(GCZONE_DEST, " dstsurf = %dx%d, stride = %ld\n", + dstgeom->width, dstgeom->height, dstgeom->virtstride); + +exit: + GCEXITARG(GCZONE_DEST, "bv%s = %d\n", + (bverror == BVERR_NONE) ? "result" : "error", bverror); + return bverror; +} + +static enum bverror set_clip(struct bvbltparams *bltparams, + struct gcbatch *batch) +{ + enum bverror bverror = BVERR_NONE; + struct bvrect *dstrect = &bltparams->dstrect; + struct bvrect *cliprect = &bltparams->cliprect; + int destleft, desttop, destright, destbottom; + int clipleft, cliptop, clipright, clipbottom; + int clippedleft, clippedtop, clippedright, clippedbottom; + int clipleftadj, cliprightadj; + struct gcmoclip *gcmoclip; + + GCENTER(GCZONE_CLIP); + + /* Did clipping/destination rects change? */ + if ((batch->batchflags & (BVBATCH_CLIPRECT_ORIGIN | + BVBATCH_CLIPRECT_SIZE | + BVBATCH_DSTRECT_ORIGIN | + BVBATCH_DSTRECT_SIZE)) == 0) + goto exit; + + GCDBG(GCZONE_CLIP, "destination clipping changed.\n"); + + /* Determine destination rectangle. */ + destleft = dstrect->left; + desttop = dstrect->top; + destright = dstrect->left + dstrect->width; + destbottom = dstrect->top + dstrect->height; + + /* Determine clipping. */ + if ((bltparams->flags & BVFLAG_CLIP) == BVFLAG_CLIP) { + clipleft = cliprect->left; + cliptop = cliprect->top; + clipright = cliprect->left + cliprect->width; + clipbottom = cliprect->top + 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; + } + } 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 = destleft + batch->deltaleft; + } + + if (cliptop <= desttop) { + batch->deltatop = 0; + clippedtop = desttop; + } else { + batch->deltatop = cliptop - desttop; + clippedtop = desttop + batch->deltatop; + } + + if (clipright >= destright) { + batch->deltaright = 0; + clippedright = destright; + } else { + batch->deltaright = clipright - destright; + clippedright = destright + batch->deltaright; + } + + if (clipbottom >= destbottom) { + batch->deltabottom = 0; + clippedbottom = destbottom; + } else { + batch->deltabottom = clipbottom - destbottom; + clippedbottom = destbottom + batch->deltabottom; + } + + /* Validate the rectangle. */ + if ((clippedright > (int) bltparams->dstgeom->width) || + (clippedbottom > (int) bltparams->dstgeom->height)) { + BVSETBLTERROR(BVERR_DSTRECT, + "destination rect exceeds surface size"); + goto exit; + } + + /* Set the destination rectangle. */ + batch->dstleft = clippedleft; + batch->dsttop = clippedtop; + batch->dstright = clippedright; + batch->dstbottom = clippedbottom; + + /* Allocate command buffer. */ + bverror = claim_buffer(batch, sizeof(struct gcmoclip), + (void **) &gcmoclip); + if (bverror != BVERR_NONE) { + BVSETBLTERROR(BVERR_OOM, + "failed to allocate command buffer"); + goto exit; + } + + /* Compute adjusted clipping. */ + clipleftadj = min(clipleft + (int) batch->dstoffset, + (int) GC_CLIP_RESET_RIGHT); + cliprightadj = min(clipright + (int) batch->dstoffset, + (int) GC_CLIP_RESET_RIGHT); + + /* Set clipping. */ + gcmoclip->lt_ldst = gcmoclip_lt_ldst; + gcmoclip->lt.raw = 0; + gcmoclip->lt.reg.left = clipleftadj; + gcmoclip->lt.reg.top = cliptop; + gcmoclip->rb.raw = 0; + gcmoclip->rb.reg.right = cliprightadj; + gcmoclip->rb.reg.bottom = clipbottom; + + GCDBG(GCZONE_CLIP, "destination rectangle:\n"); + GCDBG(GCZONE_CLIP, " dstrect = (%d,%d)-(%d,%d), %dx%d\n", + destleft, desttop, destright, destbottom, + destright - destleft, destbottom - desttop); + + GCDBG(GCZONE_CLIP, " clipping rect = (%d,%d)-(%d,%d), %dx%d\n", + clipleft, cliptop, clipright, clipbottom, + clipright - clipleft, clipbottom - cliptop); + + GCDBG(GCZONE_CLIP, + " adjusted clipping rect = (%d,%d)-(%d,%d), %dx%d\n", + clipleftadj, cliptop, cliprightadj, clipbottom, + cliprightadj - clipleftadj, clipbottom - cliptop); + + GCDBG(GCZONE_CLIP, " clipping delta = (%d,%d)-(%d,%d)\n", + batch->deltaleft, batch->deltatop, + batch->deltaright, batch->deltabottom); + + GCDBG(GCZONE_CLIP, " clipped dstrect = (%d,%d)-(%d,%d), %dx%d\n", + clippedleft, clippedtop, clippedright, clippedbottom, + clippedright - clippedleft, clippedbottom - clippedtop); + +exit: + GCEXITARG(GCZONE_CLIP, "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; + struct gcmofill *gcmofill; + unsigned char *fillcolorptr; + struct bvformatxlate *srcformat; + struct bvsurfgeom *dstgeom = bltparams->dstgeom; + struct bvbuffmap *dstmap = NULL; + + GCENTER(GCZONE_DO_FILL); + + /* Finish previous batch if any. */ + bverror = batch->batchend(bltparams, batch); + if (bverror != BVERR_NONE) + goto exit; + + /* 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; + + /* Update clipping/destination rect if necessary. */ + bverror = set_clip(bltparams, batch); + if (bverror != BVERR_NONE) + goto exit; + + /* Parse the source format. */ + GCDBG(GCZONE_FORMAT, "parsing the source format.\n"); + + if (!parse_format(srcinfo->geom->format, &srcformat)) { + BVSETBLTERRORARG((srcinfo->index == 0) + ? BVERR_SRC1GEOM_FORMAT + : BVERR_SRC2GEOM_FORMAT, + "invalid source format (%d)", + srcinfo->geom->format); + goto exit; + } + + /* Validate soource geometry. */ + if (!valid_geom(srcinfo->buf.desc, srcinfo->geom, srcformat)) { + BVSETBLTERRORARG((srcinfo->index == 0) + ? BVERR_SRC1GEOM + : BVERR_SRC2GEOM, + "source%d geom exceeds surface size", + srcinfo->index + 1); + goto exit; + } + + bverror = claim_buffer(batch, sizeof(struct gcmofill), + (void **) &gcmofill); + if (bverror != BVERR_NONE) { + BVSETBLTERROR(BVERR_OOM, "failed to allocate command buffer"); + goto exit; + } + + /*********************************************************************** + ** Set 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 = dstgeom->width; + gcmofill->src.config.raw = 0; + gcmofill->src.rotationheight_ldst = gcmofillsrc_rotationheight_ldst; + gcmofill->src.rotationheight.reg.height = dstgeom->height; + + /* 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 * srcformat->bitspp / 8; + + gcmofill->clearcolor_ldst = gcmofill_clearcolor_ldst; + gcmofill->clearcolor.raw = getinternalcolor(fillcolorptr, srcformat); + + /*********************************************************************** + ** Configure and start fill. + */ + + /* Set destination configuration. */ + gcmofill->start.config_ldst = gcmostart_config_ldst; + gcmofill->start.config.raw = 0; + gcmofill->start.config.reg.swizzle = batch->dstformat->swizzle; + gcmofill->start.config.reg.format = batch->dstformat->format; + gcmofill->start.config.reg.command = GCREG_DEST_CONFIG_COMMAND_CLEAR; + + /* Set ROP3. */ + gcmofill->start.rop_ldst = gcmostart_rop_ldst; + gcmofill->start.rop.raw = 0; + gcmofill->start.rop.reg.type = GCREG_ROP_TYPE_ROP3; + gcmofill->start.rop.reg.fg = (unsigned char) bltparams->op.rop; + + /* Set START_DE command. */ + gcmofill->start.startde.cmd.fld = gcfldstartde; + + /* Set destination rectangle. */ + gcmofill->start.rect.left = batch->dstleft + batch->dstoffset; + gcmofill->start.rect.top = batch->dsttop; + gcmofill->start.rect.right = batch->dstright + batch->dstoffset; + gcmofill->start.rect.bottom = batch->dstbottom; + +exit: + GCEXITARG(GCZONE_DO_FILL, "bv%s = %d\n", + (bverror == BVERR_NONE) ? "result" : "error", bverror); + return bverror; +} + +static enum bverror do_blit_end(struct bvbltparams *bltparams, + struct gcbatch *batch) +{ + enum bverror bverror; + struct gcmomultisrc *gcmomultisrc; + struct gcmostart *gcmostart; + unsigned int buffersize; + + GCENTER(GCZONE_DO_BLIT); + + GCDBG(GCZONE_BATCH, "finalizing the blit, scrcount = %d\n", + batch->gcblit.srccount); + + /* Allocate command buffer. */ + buffersize + = sizeof(struct gcmomultisrc) + + sizeof(struct gcmostart); + + bverror = claim_buffer(batch, buffersize, + (void **) &gcmomultisrc); + if (bverror != BVERR_NONE) { + BVSETBLTERROR(BVERR_OOM, "failed to allocate command buffer"); + goto exit; + } + + /* Configure multi-source control. */ + gcmomultisrc->control_ldst = gcmomultisrc_control_ldst; + gcmomultisrc->control.raw = 0; + gcmomultisrc->control.reg.srccount = batch->gcblit.srccount - 1; + gcmomultisrc->control.reg.horblock + = GCREG_DE_MULTI_SOURCE_HORIZONTAL_BLOCK_PIXEL128; + + /* Skip to the next structure. */ + gcmostart = (struct gcmostart *) (gcmomultisrc + 1); + + /* 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); + + gcmostart->config_ldst = gcmostart_config_ldst; + gcmostart->config.raw = 0; + gcmostart->config.reg.swizzle = batch->dstformat->swizzle; + gcmostart->config.reg.format = batch->dstformat->format; + gcmostart->config.reg.command = batch->gcblit.multisrc + ? GCREG_DEST_CONFIG_COMMAND_MULTI_SOURCE_BLT + : GCREG_DEST_CONFIG_COMMAND_BIT_BLT; + + /* Set ROP. */ + gcmostart->rop_ldst = gcmostart_rop_ldst; + gcmostart->rop.raw = 0; + gcmostart->rop.reg.type = GCREG_ROP_TYPE_ROP3; + gcmostart->rop.reg.fg = (unsigned char) batch->gcblit.rop; + + /* Set START_DE command. */ + gcmostart->startde.cmd.fld = gcfldstartde; + + /* Set destination rectangle. */ + gcmostart->rect.left = batch->dstleft + batch->dstoffset; + gcmostart->rect.top = batch->dsttop; + gcmostart->rect.right = batch->dstright + batch->dstoffset; + gcmostart->rect.bottom = batch->dstbottom; + + /* Reset the finalizer. */ + batch->batchend = do_end; + + gc_debug_blt(batch->gcblit.srccount, + abs(batch->dstright - batch->dstleft), + abs(batch->dsttop - batch->dstbottom)); + +exit: + GCEXITARG(GCZONE_DO_BLIT, "bv%s = %d\n", + (bverror == BVERR_NONE) ? "result" : "error", bverror); + return bverror; +} + + +static inline int get_offset(struct bvbuffdesc *desc) +{ + int offset; + + if (desc->auxtype == BVAT_PHYSDESC) { + struct bvphysdesc *pdesc; + pdesc = (struct bvphysdesc *) desc->auxptr; + + offset = pdesc->pageoffset & + (GC_BASE_ALIGN - 1); + } else { + offset = (unsigned int) desc->virtaddr & + (GC_BASE_ALIGN - 1); + } + return offset; +} + +static enum bverror do_blit(struct bvbltparams *bltparams, + struct gcbatch *batch, + struct srcinfo *srcinfo, + unsigned int srccount, + struct gcalpha *gca) +{ + enum bverror bverror = BVERR_NONE; + + struct gcmosrc *gcmosrc; + struct gcmosrcalpha *gcmosrcalpha; + + unsigned int i, index; + + struct bvbuffmap *dstmap = NULL; + struct bvsurfgeom *dstgeom = bltparams->dstgeom; + struct bvrect *dstrect = &bltparams->dstrect; + + struct bvformatxlate *srcformat; + struct bvbuffmap *srcmap[2] = { NULL, NULL }; + struct bvbuffdesc *srcdesc; + struct bvsurfgeom *srcgeom; + struct bvrect *srcrect; + int srcleft, srctop, srcright, srcbottom; + int srcoffset, srcsurfleft, srcsurftop; + int srcshift, srcadjust, srcalign; + int multisrc; + + GCENTER(GCZONE_DO_BLIT); + + /* Did destination change? */ + if ((batch->batchflags & (BVBATCH_DST | + BVBATCH_CLIPRECT_ORIGIN | + BVBATCH_CLIPRECT_SIZE | + BVBATCH_DSTRECT_ORIGIN | + BVBATCH_DSTRECT_SIZE)) != 0) { + /* Finalize the previous blit if any. */ + bverror = batch->batchend(bltparams, batch); + if (bverror != BVERR_NONE) + goto exit; + } + + /* 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; + + /* Update clipping/destination rect if necessary. */ + bverror = set_clip(bltparams, batch); + if (bverror != BVERR_NONE) + goto exit; + + for (i = 0; i < srccount; i += 1) { + /*************************************************************** + ** Parse the source format. + */ + + srcdesc = srcinfo[i].buf.desc; + srcgeom = srcinfo[i].geom; + srcrect = srcinfo[i].rect; + + /* Parse the source format. */ + GCDBG(GCZONE_FORMAT, "parsing the source format.\n"); + + if (!parse_format(srcgeom->format, &srcformat)) { + BVSETBLTERRORARG((srcinfo[i].index == 0) + ? BVERR_SRC1GEOM_FORMAT + : BVERR_SRC2GEOM_FORMAT, + "invalid source format (%d)", + srcgeom->format); + goto exit; + } + + /* Validate soource geometry. */ + if (!valid_geom(srcdesc, srcgeom, srcformat)) { + BVSETBLTERRORARG((srcinfo->index == 0) + ? BVERR_SRC1GEOM + : BVERR_SRC2GEOM, + "source%d geom exceeds surface size", + srcinfo->index + 1); + goto exit; + } + + srcright = srcrect->left + srcrect->width + batch->deltaright; + srcbottom = srcrect->top + srcrect->height + batch->deltabottom; + + /* Validate the rectangle. */ + if ((srcright > (int) srcgeom->width) || + (srcbottom > (int) srcgeom->height)) { + BVSETBLTERRORARG((srcinfo->index == 0) + ? BVERR_SRC1RECT + : BVERR_SRC2RECT, + "source%d rect exceeds surface size", + srcinfo->index + 1); + goto exit; + } + + GCDBG(GCZONE_SURF, "source surface %d:\n", i); + GCDBG(GCZONE_SURF, " srcaddr[%d] = 0x%08X\n", + i, (unsigned int) srcdesc->virtaddr); + + GCDBG(GCZONE_SURF, " srcsurf = %dx%d, stride = %ld\n", + srcgeom->width, srcgeom->height, + srcgeom->virtstride); + + GCDBG(GCZONE_SURF, " srcrect = (%d,%d)-(%d,%d), %dx%d\n", + srcrect->left, srcrect->top, + srcrect->left + srcrect->width, + srcrect->top + srcrect->height, + srcrect->width, srcrect->height); + + /*************************************************************** + ** Determine source placement. + */ + + /* Compute the source offset in pixels needed to compensate + for the surface base address misalignment if any. */ + srcoffset = get_offset(srcdesc) * 8 / srcformat->bitspp; + + GCDBG(GCZONE_SURF, " source offset = %d\n", srcoffset); + + srcsurfleft = srcrect->left - dstrect->left + srcoffset; + srcsurftop = srcrect->top - dstrect->top; + + GCDBG(GCZONE_SURF, " source surfaceorigin = %d,%d\n", + srcsurfleft, srcsurftop); + + /* (srcsurfleft,srcsurftop) are the coordinates of the source + surface origin. PE requires alignment of the base + address. Compute the alignment requirement in pixels. */ + srcalign = 16 * 8 / srcformat->bitspp; + + GCDBG(GCZONE_SURF, " srcalign = %d\n", srcalign); + + /* Compute the number of pixels the origin has to be + aligned by. */ + srcadjust = srcsurfleft % srcalign; + + GCDBG(GCZONE_SURF, " srcadjust = %d\n", srcadjust); + + /* TODO: multisrc with nv12 format */ + multisrc = (srcformat->format == GCREG_DE_FORMAT_NV12) ? 0 : + (srcadjust == 0); + + GCDBG(GCZONE_DO_BLIT, " multisrc = %d\n", multisrc); + + if (multisrc) { + /* Adjust the origin. */ + srcsurfleft -= srcadjust; + + GCDBG(GCZONE_SURF, + " adjusted source surface origin = %d,%d\n", + srcsurfleft, srcsurftop); + + /* Adjust the source rectangle for the + * single source walker. + */ + srcleft = dstrect->left + batch->deltaleft + srcadjust; + srctop = dstrect->top + batch->deltatop; + + GCDBG(GCZONE_SURF, + " source %d rectangle origin = %d,%d\n", + i, srcleft, srctop); + + /* Compute the surface offset in bytes. */ + srcshift + = srcsurftop * (int) srcgeom->virtstride + + srcsurfleft * (int) srcformat->bitspp / 8; + + GCDBG(GCZONE_SURF, " srcshift = 0x%08X (%d)\n", + srcshift, srcshift); + } else { + srcadjust = srcoffset % srcalign; + + GCDBG(GCZONE_SURF, " single source srcadjust = %d\n", + srcadjust); + + srcleft = srcrect->left + batch->deltaleft + srcadjust; + srctop = srcrect->top + batch->deltatop; + + GCDBG(GCZONE_SURF, + " source %d rectangle origin = %d,%d\n", + i, srcleft, srctop); + + /* No shift needed for single source walker */ + srcshift = 0; + } + + /*************************************************************** + ** Finalize existing blit if necessary. + */ + + if ((batch->batchend != do_blit_end) || + (batch->gcblit.srccount == 4) || + !batch->gcblit.multisrc || !multisrc) { + /* Finalize the previous blit if any. */ + bverror = batch->batchend(bltparams, batch); + if (bverror != BVERR_NONE) + goto exit; + + /* Initialize the new batch. */ + batch->batchend = do_blit_end; + batch->gcblit.srccount = 0; + batch->gcblit.multisrc = multisrc; + batch->gcblit.rop = (gca != NULL) + ? 0xCC : bltparams->op.rop; + } + + /*************************************************************** + ** Map the source. + */ + + bverror = do_map(srcdesc, batch, &srcmap[i]); + if (bverror != BVERR_NONE) { + bltparams->errdesc = gccontext.bverrorstr; + goto exit; + } + + /*************************************************************** + ** Configure source. + */ + + /* Allocate command buffer. */ + bverror = claim_buffer(batch, sizeof(struct gcmosrc), + (void **) &gcmosrc); + if (bverror != BVERR_NONE) { + BVSETBLTERROR(BVERR_OOM, + "failed to allocate command buffer"); + goto exit; + } + + /* Shortcut to the register index. */ + index = batch->gcblit.srccount; + + add_fixup(batch, &gcmosrc->address, srcshift); + + /* Set surface parameters. */ + gcmosrc->address_ldst = gcmosrc_address_ldst[index]; + gcmosrc->address = GET_MAP_HANDLE(srcmap[i]); + + 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 + = dstrect->left + srcgeom->width; + + 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]; + if (multisrc) + gcmosrc->origin.reg = gcregsrcorigin_min; + else { + 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 + = dstrect->top + srcgeom->height; + + 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; + + 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; + } + + bverror = claim_buffer(batch, + sizeof(struct gcmosrcplanaryuv), + (void **) &yuv); + if (bverror != BVERR_NONE) { + BVSETBLTERROR(BVERR_OOM, + "failed to allocate command buffer for planar yuv"); + 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 (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; + } + + 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[i]); + add_fixup(batch, &yuv->uplaneaddress, uvshift); + + yuv->uplanestride = srcgeom->virtstride; + + yuv->vplaneaddress = GET_MAP_HANDLE(srcmap[i]); + add_fixup(batch, &yuv->vplaneaddress, uvshift); + + yuv->vplanestride = srcgeom->virtstride; + } + + if ((gca != NULL) && ((srccount == 1) || (i > 0))) { + 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(batch, + sizeof(struct gcmosrcalpha), + (void **) &gcmosrcalpha); + if (bverror != BVERR_NONE) { + BVSETBLTERROR(BVERR_OOM, + "failed to allocate command buffer"); + goto exit; + } + + gcmosrcalpha->alphamodes_ldst + = gcmosrcalpha_alphamodes_ldst[index]; + gcmosrcalpha->alphamodes.raw = 0; + gcmosrcalpha->alphamodes.reg.src_global_alpha + = gca->src_global_alpha_mode; + gcmosrcalpha->alphamodes.reg.dst_global_alpha + = gca->dst_global_alpha_mode; + + if (srccount == 1) { + GCDBG(GCZONE_BLEND, "k1 sets src blend.\n"); + GCDBG(GCZONE_BLEND, "k2 sets dst blend.\n"); + + gcmosrcalpha->alphamodes.reg.src_blend + = gca->k1->factor_mode; + gcmosrcalpha->alphamodes.reg.src_color_reverse + = gca->k1->color_reverse; + + gcmosrcalpha->alphamodes.reg.dst_blend + = gca->k2->factor_mode; + gcmosrcalpha->alphamodes.reg.dst_color_reverse + = gca->k2->color_reverse; + } else { + GCDBG(GCZONE_BLEND, "k1 sets dst blend.\n"); + GCDBG(GCZONE_BLEND, "k2 sets src blend.\n"); + + gcmosrcalpha->alphamodes.reg.src_blend + = gca->k2->factor_mode; + gcmosrcalpha->alphamodes.reg.src_color_reverse + = gca->k2->color_reverse; + + gcmosrcalpha->alphamodes.reg.dst_blend + = gca->k1->factor_mode; + gcmosrcalpha->alphamodes.reg.dst_color_reverse + = gca->k1->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 = gca->src_global_color; + + gcmosrcalpha->dstglobal_ldst + = gcmosrcalpha_dstglobal_ldst[index]; + gcmosrcalpha->dstglobal.raw = gca->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) +{ + enum bverror bverror; + GCENTER(GCZONE_DO_FILTER); + BVSETBLTERROR(BVERR_SRC1_HORZSCALE, "scaling not supported"); + GCEXITARG(GCZONE_DO_FILTER, "bv%s = %d\n", + (bverror == BVERR_NONE) ? "result" : "error", bverror); + return bverror; +} + + +/******************************************************************************* + * Library constructor and destructor. + */ + +void bv_init(void) +{ + 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); +} + +void bv_exit(void) +{ + 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); + } + + while (gccontext.vac_buffmap != NULL) { + bufmap = gccontext.vac_buffmap; + gccontext.vac_buffmap = bufmap->nextmap; + gcfree(bufmap); + } + + while (gccontext.vac_buffers != NULL) { + buffer = gccontext.vac_buffers; + gccontext.vac_buffers = buffer->next; + gcfree(buffer); + } + + while (gccontext.vac_fixups != NULL) { + fixup = gccontext.vac_fixups; + gccontext.vac_fixups = fixup->next; + gcfree(fixup); + } + + while (gccontext.vac_batches != NULL) { + batch = gccontext.vac_batches; + gccontext.vac_batches = batch->next; + gcfree(batch); + } +} + + +/******************************************************************************* + * Library API. + */ + +enum bverror bv_map(struct bvbuffdesc *buffdesc) +{ + enum bverror bverror; + struct bvbuffmap *bvbuffmap; + + GCENTERARG(GCZONE_MAPPING, "buffdesc = 0x%08X\n", + (unsigned int) buffdesc); + + if (buffdesc == NULL) { + BVSETERROR(BVERR_BUFFERDESC, "bvbuffdesc is NULL"); + goto exit; + } + + if (buffdesc->structsize < STRUCTSIZE(buffdesc, map)) { + BVSETERROR(BVERR_BUFFERDESC_VERS, "argument has invalid size"); + goto exit; + } + + bverror = do_map(buffdesc, NULL, &bvbuffmap); + +exit: + GCEXITARG(GCZONE_MAPPING, "bv%s = %d\n", + (bverror == BVERR_NONE) ? "result" : "error", bverror); + return bverror; +} + +enum bverror bv_unmap(struct bvbuffdesc *buffdesc) +{ + enum bverror bverror = BVERR_NONE; + enum bverror otherbverror = BVERR_NONE; + struct bvbuffmap *prev = NULL; + struct bvbuffmap *bvbuffmap; + struct bvbuffmapinfo *bvbuffmapinfo; + struct gcmap gcmap; + + GCENTERARG(GCZONE_MAPPING, "buffdesc = 0x%08X\n", + (unsigned int) buffdesc); + + /* Lock access to the mapping list. */ + GCLOCK(&gccontext.maplock); + + if (buffdesc == NULL) { + BVSETERROR(BVERR_BUFFERDESC, "bvbuffdesc is NULL"); + goto exit; + } + + if (buffdesc->structsize < STRUCTSIZE(buffdesc, map)) { + BVSETERROR(BVERR_BUFFERDESC_VERS, "argument has invalid size"); + goto exit; + } + + /* Is the buffer mapped? */ + bvbuffmap = buffdesc->map; + if (bvbuffmap == NULL) { + GCDBG(GCZONE_MAPPING, "buffer isn't mapped.\n"); + goto exit; + } + + /* Try to find our mapping. */ + while (bvbuffmap != NULL) { + if (bvbuffmap->bv_unmap == bv_unmap) + break; + prev = bvbuffmap; + bvbuffmap = bvbuffmap->nextmap; + } + + /* Are there other implementations? */ + if ((prev != NULL) || (bvbuffmap->nextmap != NULL)) { + GCDBG(GCZONE_MAPPING, + "have mappings from other implementations.\n"); + + /* Was our mapping found? */ + if (bvbuffmap == NULL) { + GCDBG(GCZONE_MAPPING, + "no mapping from our implementation.\n"); + + /* No, call other implementations. */ + bverror = buffdesc->map->bv_unmap(buffdesc); + goto exit; + } + + if (bvbuffmap->structsize + < STRUCTSIZE(bvbuffmap, nextmap)) { + BVSETERROR(BVERR_BUFFERDESC_VERS, + "unsupported bvbuffdesc version"); + goto exit; + } + + /* Remove our mapping. */ + if (prev == NULL) + buffdesc->map = bvbuffmap->nextmap; + else + prev->nextmap = bvbuffmap->nextmap; + + /* Call other implementation. */ + otherbverror = buffdesc->map->bv_unmap(buffdesc); + + /* Add our mapping back. */ + bvbuffmap->nextmap = buffdesc->map; + buffdesc->map = bvbuffmap; + prev = NULL; + } else { + GCDBG(GCZONE_MAPPING, + "no mappings from other implementations.\n"); + } + + /* Get the info structure. */ + bvbuffmapinfo = (struct bvbuffmapinfo *) bvbuffmap->handle; + + GCDBG(GCZONE_MAPPING, "bvbuffmap = 0x%08X\n", (unsigned int) bvbuffmap); + GCDBG(GCZONE_MAPPING, "handle = 0x%08X\n", bvbuffmapinfo->handle); + + /* Explicit unmapping. */ + if (bvbuffmapinfo->usermap == 0) + GCERR("explicit count is already zero.\n"); + bvbuffmapinfo->usermap = 0; + + GCDBG(GCZONE_MAPPING, "explicit count = %d\n", + bvbuffmapinfo->usermap); + GCDBG(GCZONE_MAPPING, "implicit count = %d\n", + bvbuffmapinfo->automap); + + /* Do we have implicit mappings? */ + if (bvbuffmapinfo->automap > 0) { + GCDBG(GCZONE_MAPPING, "have implicit unmappings.\n"); + goto exit; + } + + /* Unmap the buffer. */ + memset(&gcmap, 0, sizeof(gcmap)); + gcmap.handle = bvbuffmapinfo->handle; + gc_unmap_wrapper(&gcmap); + if (gcmap.gcerror != GCERR_NONE) { + BVSETERROR(BVERR_OOM, "unable to free gccore memory"); + goto exit; + } + + /* Remove from the buffer descriptor list. */ + if (prev == NULL) + buffdesc->map = bvbuffmap->nextmap; + else + prev->nextmap = bvbuffmap->nextmap; + + /* Invalidate the record. */ + bvbuffmap->structsize = 0; + + /* Add to the vacant list. */ + bvbuffmap->nextmap = gccontext.vac_buffmap; + gccontext.vac_buffmap = bvbuffmap; + +exit: + /* Unlock access to the mapping list. */ + 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 bverror = BVERR_NONE; + struct gcalpha *gca = NULL; + struct gcalpha _gca; + unsigned int op, type, blend, format; + unsigned int batchexec = 0; + bool nop = false; + struct gcbatch *batch; + int src1used, src2used, maskused; + struct srcinfo srcinfo[2]; + unsigned short rop; + struct gccommit gccommit; + int srccount, res; + + GCENTERARG(GCZONE_BLIT, "bltparams = 0x%08X\n", + (unsigned int) bltparams); + + /* Verify blt parameters structure. */ + if (bltparams == NULL) { + BVSETERROR(BVERR_BLTPARAMS_VERS, "bvbltparams is NULL"); + goto exit; + } + + if (bltparams->structsize < STRUCTSIZE(bltparams, callbackdata)) { + BVSETERROR(BVERR_BLTPARAMS_VERS, "argument has invalid size"); + goto exit; + } + + /* Reset the error message. */ + bltparams->errdesc = NULL; + + /* Verify the destination parameters structure. */ + GCDBG(GCZONE_SURF, "verifying destination parameters.\n"); + + res = verify_surface(0, (union bvinbuff *) &bltparams->dstdesc, + bltparams->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; + + switch (type) { + case (BVFLAG_BATCH_NONE >> BVFLAG_BATCH_SHIFT): + bverror = allocate_batch(&batch); + if (bverror != BVERR_NONE) { + bltparams->errdesc = gccontext.bverrorstr; + goto exit; + } + + batchexec = 1; + batch->batchflags = 0x7FFFFFFF; + + GCDBG(GCZONE_BATCH, "BVFLAG_BATCH_NONE(0x%08X)\n", + (unsigned int) batch); + break; + + case (BVFLAG_BATCH_BEGIN >> BVFLAG_BATCH_SHIFT): + bverror = allocate_batch(&batch); + if (bverror != BVERR_NONE) { + bltparams->errdesc = gccontext.bverrorstr; + goto exit; + } + + bltparams->batch = (struct bvbatch *) batch; + + batchexec = 0; + bltparams->batchflags = + batch->batchflags = 0x7FFFFFFF; + + GCDBG(GCZONE_BATCH, "BVFLAG_BATCH_BEGIN(0x%08X)\n", + (unsigned int) batch); + break; + + case (BVFLAG_BATCH_CONTINUE >> BVFLAG_BATCH_SHIFT): + batch = (struct gcbatch *) bltparams->batch; + if (batch == NULL) { + BVSETBLTERROR(BVERR_BATCH, "batch is not initialized"); + goto exit; + } + + if (batch->structsize < STRUCTSIZE(batch, unmap)) { + BVSETBLTERROR(BVERR_BATCH, "invalid batch"); + goto exit; + } + + batchexec = 0; + batch->batchflags = bltparams->batchflags; + + GCDBG(GCZONE_BATCH, "BVFLAG_BATCH_CONTINUE(0x%08X)\n", + (unsigned int) batch); + break; + + case (BVFLAG_BATCH_END >> BVFLAG_BATCH_SHIFT): + batch = (struct gcbatch *) bltparams->batch; + if (batch == NULL) { + BVSETBLTERROR(BVERR_BATCH, "batch is not initialized"); + goto exit; + } + + if (batch->structsize < STRUCTSIZE(batch, unmap)) { + BVSETBLTERROR(BVERR_BATCH, "invalid batch"); + goto exit; + } + + batchexec = 1; + nop = (bltparams->batchflags & BVBATCH_ENDNOP) != 0; + batch->batchflags = bltparams->batchflags; + + GCDBG(GCZONE_BATCH, "BVFLAG_BATCH_END(0x%08X)\n", + (unsigned int) batch); + break; + + default: + BVSETBLTERROR(BVERR_BATCH, "unrecognized batch type"); + goto exit; + } + + GCDBG(GCZONE_BATCH, "batchflags=0x%08X\n", + (unsigned int) batch->batchflags); + + GCDUMPSCHEDULE(); + + if (!nop) { + /* Verify the batch change flags. */ + VERIFYBATCH(batch->batchflags >> 12, &batch->prevdstrect, + &bltparams->dstrect); + + switch (op) { + case (BVFLAG_ROP >> BVFLAG_OP_SHIFT): + GCDBG(GCZONE_BLIT, "BVFLAG_ROP\n"); + + rop = bltparams->op.rop; + src1used = ((rop & 0xCCCC) >> 2) + ^ (rop & 0x3333); + src2used = ((rop & 0xF0F0) >> 4) + ^ (rop & 0x0F0F); + maskused = ((rop & 0xFF00) >> 8) + ^ (rop & 0x00FF); + break; + + case (BVFLAG_BLEND >> BVFLAG_OP_SHIFT): + GCDBG(GCZONE_BLIT, "BVFLAG_BLEND\n"); + + blend = bltparams->op.blend; + format = (blend & BVBLENDDEF_FORMAT_MASK) + >> BVBLENDDEF_FORMAT_SHIFT; + + bverror = parse_blend(bltparams, blend, &_gca); + if (bverror != BVERR_NONE) + goto exit; + + gca = &_gca; + + switch (format) { + case (BVBLENDDEF_FORMAT_CLASSIC + >> BVBLENDDEF_FORMAT_SHIFT): + src1used = gca->src1used; + src2used = gca->src2used; + maskused = blend & BVBLENDDEF_REMOTE; + break; + + default: + BVSETBLTERROR(BVERR_BLEND, + "unrecognized blend format"); + goto exit; + } + break; + + case (BVFLAG_FILTER >> BVFLAG_OP_SHIFT): + GCDBG(GCZONE_BLIT, "BVFLAG_FILTER\n"); + BVSETBLTERROR(BVERR_OP, + "filter operation not supported"); + goto exit; + + default: + BVSETBLTERROR(BVERR_OP, "unrecognized operation"); + goto exit; + } + + srccount = 0; + + /* Verify the src1 parameters structure. */ + if (src1used) { + GCDBG(GCZONE_BLIT, "src1used\n"); + GCDBG(GCZONE_SURF, "verifying source1 parameters.\n"); + + res = verify_surface( + bltparams->flags & BVBATCH_TILE_SRC1, + &bltparams->src1, bltparams->src1geom); + if (res != -1) { + BVSETBLTSURFERROR(res, g_src1surferr); + goto exit; + } + + /* Verify the batch change flags. */ + VERIFYBATCH(batch->batchflags >> 14, + &batch->prevsrc1rect, + &bltparams->src1rect); + + /* Same as the destination? */ + if (same_phys_area(bltparams->src1.desc, + &bltparams->src1rect, + bltparams->dstdesc, + &bltparams->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; + + srccount += 1; + } + } + + /* Verify the src2 parameters structure. */ + if (src2used) { + GCDBG(GCZONE_BLIT, "src2used\n"); + GCDBG(GCZONE_SURF, "verifying source2 parameters.\n"); + + res = verify_surface( + bltparams->flags & BVBATCH_TILE_SRC2, + &bltparams->src2, bltparams->src2geom); + if (res != -1) { + BVSETBLTSURFERROR(res, g_src2surferr); + goto exit; + } + + /* Verify the batch change flags. */ + VERIFYBATCH(batch->batchflags >> 16, + &batch->prevsrc2rect, + &bltparams->src2rect); + + /* Same as the destination? */ + if (same_phys_area(bltparams->src2.desc, + &bltparams->src2rect, + bltparams->dstdesc, + &bltparams->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; + + srccount += 1; + } + } + + /* Verify the mask parameters structure. */ + if (maskused) { + GCDBG(GCZONE_BLIT, "maskused\n"); + GCDBG(GCZONE_SURF, "verifying mask parameters.\n"); + + res = verify_surface( + bltparams->flags & BVBATCH_TILE_MASK, + &bltparams->mask, bltparams->maskgeom); + if (res != -1) { + BVSETBLTSURFERROR(res, g_masksurferr); + goto exit; + } + + /* Verify the batch change flags. */ + VERIFYBATCH(batch->batchflags >> 18, + &batch->prevmaskrect, + &bltparams->maskrect); + + BVSETERROR(BVERR_OP, + "operation with mask not supported"); + goto exit; + } + + GCDBG(GCZONE_BLIT, "srccount = %d\n", srccount); + + switch (srccount) { + case 0: + bverror = do_blit(bltparams, batch, NULL, 0, gca); + if (bverror != BVERR_NONE) + goto exit; + break; + + case 1: + if (EQ_SIZE((*srcinfo[0].rect), bltparams->dstrect)) + bverror = do_blit(bltparams, batch, + srcinfo, 1, gca); + else if ((srcinfo[0].rect->width == 1) && + (srcinfo[0].rect->height == 1)) + bverror = do_fill(bltparams, batch, srcinfo); + else + bverror = do_filter(bltparams, batch); + if (bverror != BVERR_NONE) + goto exit; + break; + + case 2: + if (EQ_SIZE((*srcinfo[0].rect), bltparams->dstrect)) + if (EQ_SIZE((*srcinfo[1].rect), + bltparams->dstrect)) + bverror = do_blit(bltparams, batch, + srcinfo, 2, gca); + else + BVSETBLTERROR(BVERR_SRC2_HORZSCALE, + "scaling not supported"); + else + if (EQ_SIZE((*srcinfo[1].rect), + bltparams->dstrect)) + BVSETBLTERROR(BVERR_SRC1_HORZSCALE, + "scaling not supported"); + else + BVSETBLTERROR(BVERR_SRC1_HORZSCALE, + "scaling not supported"); + if (bverror != BVERR_NONE) + goto exit; + } + } + + if (batchexec) { + struct gcmoflush *flush; + + GCDBG(GCZONE_BLIT, "preparing to submit the batch.\n"); + + /* Finalize the current operation. */ + bverror = batch->batchend(bltparams, batch); + if (bverror != BVERR_NONE) + goto exit; + + /* Add PE flush. */ + GCDBG(GCZONE_BLIT, "appending the flush.\n"); + bverror = claim_buffer(batch, sizeof(struct gcmoflush), + (void **) &flush); + if (bverror != BVERR_NONE) { + BVSETBLTERROR(BVERR_OOM, + "failed to allocate command buffer"); + goto exit; + } + + flush->flush_ldst = gcmoflush_flush_ldst; + flush->flush.reg = gcregflush_pe2D; + + /* Process asynchronous operation. */ + if ((bltparams->flags & BVFLAG_ASYNC) == 0) { + GCDBG(GCZONE_BLIT, "synchronous batch.\n"); + gccommit.callback = NULL; + gccommit.callbackparam = NULL; + gccommit.asynchronous = false; + } else { + struct gccallbackinfo *gccallbackinfo; + + GCDBG(GCZONE_BLIT, "asynchronous batch (0x%08X):\n", + bltparams->flags); + + if (bltparams->callbackfn == NULL) { + GCDBG(GCZONE_BLIT, "no callback given.\n"); + gccommit.callback = NULL; + gccommit.callbackparam = NULL; + } else { + bverror = get_callbackinfo(&gccallbackinfo); + if (bverror != BVERR_NONE) { + BVSETBLTERROR(BVERR_OOM, + "callback allocation failed"); + goto exit; + } + + gccallbackinfo->callbackfn + = bltparams->callbackfn; + gccallbackinfo->callbackdata + = bltparams->callbackdata; + + gccommit.callback = gccallback; + gccommit.callbackparam = gccallbackinfo; + + GCDBG(GCZONE_BLIT, + "gcbv_callback = 0x%08X\n", + (unsigned int) gccommit.callback); + GCDBG(GCZONE_BLIT, + "gcbv_param = 0x%08X\n", + (unsigned int) gccommit.callbackparam); + GCDBG(GCZONE_BLIT, + "bltsville_callback = 0x%08X\n", + (unsigned int) + gccallbackinfo->callbackfn); + GCDBG(GCZONE_BLIT, + "bltsville_param = 0x%08X\n", + (unsigned int) + gccallbackinfo->callbackdata); + } + + gccommit.asynchronous = true; + } + + /* Process scheduled unmappings. */ + unmap_implicit(batch); + + INIT_LIST_HEAD(&gccommit.unmap); + list_splice_init(&batch->unmap, &gccommit.unmap); + + /* Pass the batch for execution. */ + GCDUMPBATCH(batch); + + gccommit.gcerror = GCERR_NONE; + gccommit.entrypipe = GCPIPE_2D; + gccommit.exitpipe = GCPIPE_2D; + gccommit.buffer = batch->bufhead; + + 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); + + /* Error? */ + if (gccommit.gcerror != GCERR_NONE) { + switch (gccommit.gcerror) { + case GCERR_OODM: + case GCERR_CTX_ALLOC: + BVSETBLTERROR(BVERR_OOM, + "unable to allocate gccore memory"); + goto exit; + default: + BVSETBLTERROR(BVERR_RSRC, + "gccore error"); + + goto exit; + } + } + + GCDBG(GCZONE_BLIT, "batch is submitted.\n"); + } + +exit: + if ((batch != NULL) && batchexec) { + GCDUMPSCHEDULE(); + free_batch(batch); + bltparams->batch = NULL; + } + + GCEXITARG(GCZONE_BLIT, "bv%s = %d\n", + (bverror == BVERR_NONE) ? "result" : "error", bverror); + return bverror; +} + +enum bverror bv_cache(struct bvcopparams *copparams) +{ + enum bverror bverror = BVERR_NONE; + unsigned int bytespp = 0; /* bytes per pixel */ + unsigned long vert_offset, horiz_offset; + + struct c2dmrgn rgn[3]; + int container_size = 0; + + unsigned long subsample; + unsigned long vendor; + unsigned long layout; + unsigned long size; + unsigned long container; + + subsample = copparams->geom->format & OCDFMTDEF_SUBSAMPLE_MASK; + vendor = copparams->geom->format & OCDFMTDEF_VENDOR_MASK; + layout = copparams->geom->format & OCDFMTDEF_LAYOUT_MASK; + size = copparams->geom->format & OCDFMTDEF_COMPONENTSIZEMINUS1_MASK; + container = copparams->geom->format & OCDFMTDEF_CONTAINER_MASK; + + if (vendor != OCDFMTDEF_VENDOR_ALL) { + bverror = BVERR_FORMAT; + goto exit; + } + + switch (container) { + case OCDFMTDEF_CONTAINER_8BIT: + container_size = 8; + break; + case OCDFMTDEF_CONTAINER_16BIT: + container_size = 16; + break; + case OCDFMTDEF_CONTAINER_24BIT: + container_size = 24; + break; + case OCDFMTDEF_CONTAINER_32BIT: + container_size = 32; + break; + case OCDFMTDEF_CONTAINER_48BIT: + container_size = 48; + break; + case OCDFMTDEF_CONTAINER_64BIT: + container_size = 64; + break; + } + + switch (layout) { + case OCDFMTDEF_PACKED: + switch (subsample) { + case OCDFMTDEF_SUBSAMPLE_NONE: + if (size >= 8) { + bytespp = container_size / 8; + } else { + GCERR("format not supported.\n"); + bverror = BVERR_FORMAT; + goto exit; + } + break; + + case OCDFMTDEF_SUBSAMPLE_422_YCbCr: + bytespp = (container_size / 2) / 8; + break; + + case OCDFMTDEF_SUBSAMPLE_420_YCbCr: + bverror = BVERR_FORMAT; + goto exit; + break; + + case OCDFMTDEF_SUBSAMPLE_411_YCbCr: + bverror = BVERR_FORMAT; + goto exit; + break; + + default: + bverror = BVERR_FORMAT; + goto exit; + } + + rgn[0].span = copparams->rect->width * bytespp; + rgn[0].lines = copparams->rect->height; + rgn[0].stride = copparams->geom->virtstride; + horiz_offset = copparams->rect->left * bytespp; + vert_offset = copparams->rect->top; + + rgn[0].start = (void *) ((unsigned long) + copparams->desc->virtaddr + + vert_offset * rgn[0].stride + + horiz_offset); + + gcbvcacheop(1, rgn, copparams->cacheop); + break; + + case OCDFMTDEF_2_PLANE_YCbCr: + /* 1 byte per pixel */ + rgn[0].span = copparams->rect->width; + rgn[0].lines = copparams->rect->height; + rgn[0].stride = copparams->geom->virtstride; + rgn[0].start = (void *) + ((unsigned long) copparams->desc->virtaddr + + copparams->rect->top * rgn[0].stride + + copparams->rect->left); + + rgn[1].span = copparams->rect->width; + rgn[1].lines = copparams->rect->height / 2; + rgn[1].stride = copparams->geom->virtstride; + rgn[1].start = rgn[0].start + + copparams->geom->height * rgn[0].stride; + + GCDBG(GCZONE_CACHE, + "virtaddr %p start[0] 0x%08x start[1] 0x%08x\n", + copparams->desc->virtaddr, rgn[0].start, rgn[1].start); + + gcbvcacheop(2, rgn, copparams->cacheop); + break; + + default: + GCERR("format 0x%x (%d) not supported.\n", + copparams->geom->format, copparams->geom->format); + bverror = BVERR_FORMAT; + break; + } + +exit: + if (bverror != BVERR_NONE) + GCERR("bverror = %d\n", bverror); + + return bverror; +} diff --git a/gcbv/mirror/gcdbglog.c b/gcbv/mirror/gcdbglog.c new file mode 100644 index 0000000..7a1a125 --- /dev/null +++ b/gcbv/mirror/gcdbglog.c @@ -0,0 +1,1696 @@ +/* + * 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, + * Texas Instruments, Inc. and 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, + * Texas Instruments, Inc. and Vivante Corporation. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Vivante Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <stdarg.h> +#include <stdio.h> +#include <unistd.h> +#include <gcx.h> +#include "gcmain.h" + + +#if GCDEBUG_ENABLE + +/******************************************************************************* + * Debug switches. + */ + +/* Dumping enable default state. */ +#define GC_DUMP_ENABLE 0 + +/* Ignore all zones as if they were all enabled in all modules. */ +#define GC_IGNORE_ZONES 0 + +/* When enabled, all output is collected into a buffer with a predefined size. + * GC_DUMP_BUFFER_SIZE determines the size of the buffer and GC_ENABLE_OVERFLOW + * controls what happens when the buffer gets full. */ +#define GC_BUFFERED_OUTPUT 0 + +/* Debug output buffer size. */ +#define GC_DUMP_BUFFER_SIZE (200 * 1024) + +/* If disabled, the contents of the buffer will be dumped to the console when + * the buffer gets full. + * If enabled, wrap around mode is enabled where when the buffer gets full, + * the oldest entries are overwritten with the new entrie. To dump the buffer + * to the console gc_dump_flush must be called explicitly. */ +#define GC_ENABLE_OVERFLOW 1 + +/* Specifies how many prints are accumulated in the buffer before the buffer is + * flushed. Set to zero to disable auto dumping mode. */ +#define GC_FLUSH_COUNT 0 + +/* Specifies the maximum number of threads that will be tracked in an attempt + * to visually separate messages from different threads. To disable thread + * tracking, set to 0 or 1. */ +#define GC_THREAD_COUNT 20 + +/* Specifies spacing for thread messages. */ +#define GC_THREAD_INDENT 0 + +/* 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 + +/* If enabled, each print statement will be preceeded with the current + * process ID. */ +#define GC_SHOW_PID 1 + +/* If enabled, internal logging validation code is turned on. */ +#define GC_DEBUG_SELF 0 + +/* Maximum length of a dump string. */ +#define GC_MAXSTR_LENGTH 256 + + +/******************************************************************************* + * Miscellaneous macros. + */ + +#define GC_PTR2INT(p) \ +( \ + (unsigned int) (p) \ +) + +#define GC_ALIGN(n, align) \ +( \ + ((n) + ((align) - 1)) & ~((align) - 1) \ +) + +#define GC_PTRALIGNMENT(p, alignment) \ +( \ + GC_ALIGN(GC_PTR2INT(p), alignment) - GC_PTR2INT(p) \ +) + +#define GC_VARARG_ALIGNMENT sizeof(unsigned long long) + +#if defined(GCDBGFILTER) +#undef GCDBGFILTER +#endif + +#define GCDBGFILTER \ + (*filter) + +#if GC_IGNORE_ZONES +#define GC_VERIFY_ENABLE(filter, zone) \ + (g_initdone) +#else +#define GC_VERIFY_ENABLE(filter, zone) \ + (g_initdone && ((filter == NULL) || ((filter->zone & zone) != 0))) +#endif + +#if GC_SHOW_DUMP_LINE +#define GC_DUMPLINE_FORMAT "[%12d] " +#endif + +#if GC_SHOW_PID +#define GC_PID_FORMAT "[pid=%04X] " +#endif + +#define GC_EOL_RESERVE 1 + +/******************************************************************************* + * Dump item header definition. + */ + +enum itemtype { + GC_BUFITEM_NONE, + GC_BUFITEM_STRING, + GC_BUFITEM_BUFFER +}; + +/* Common item head/buffer terminator. */ +struct itemhead { + enum itemtype type; +}; + + +/******************************************************************************* + * Supported dump items. + */ + +/* GC_BUFITEM_STRING: buffered string. */ +struct itemstring { + enum itemtype itemtype; + int indent; + +#if GC_SHOW_PID + pid_t pid; +#endif + +#if GC_SHOW_DUMP_LINE + unsigned int dumpline; +#endif + + const char *message; + va_list messagedata; + unsigned int datasize; +}; + +/* GC_BUFITEM_BUFFER: buffered memory. */ +enum buffertype { + GC_BUFTYPE_GENERIC, + GC_BUFTYPE_COMMAND, + GC_BUFTYPE_SURFACE +}; + +#define GC_GENERIC_DATA_COUNT 8 +#define GC_SURFACE_DATA_COUNT 64 + +struct itembuffer { + enum itemtype itemtype; + enum buffertype buffertype; + int indent; + + unsigned int surfwidth; + unsigned int surfheight; + unsigned int surfbpp; + unsigned int x1, y1; + unsigned int x2, y2; + + unsigned int datasize; + unsigned int gpuaddr; +}; + + +/******************************************************************************* + * Debug output buffer. + */ + +struct threadinfo { + pid_t pid; + int msgindent; + int threadindent; +}; + +struct buffout { + int enable; + +#if GC_THREAD_COUNT > 1 + unsigned int threadcount; + struct threadinfo threadinfo[1 + GC_THREAD_COUNT]; +#else + struct threadinfo threadinfo[1]; +#endif + +#if GC_SHOW_DUMP_LINE + unsigned int dumpline; +#endif + +#if GC_BUFFERED_OUTPUT + int start; + int index; + int count; + unsigned char *buffer; +#endif +}; + +static struct buffout g_outputbuffer = { + .enable = GC_DUMP_ENABLE +}; + + +/******************************************************************************* + * Globals. + */ + +static unsigned int g_initdone; +static GCDEFINE_LOCK(g_lockmutex); +static struct list_head gc_filterlist = LIST_HEAD_INIT(gc_filterlist); + + +/******************************************************************************* + * Item size functions. + */ + +#if GC_BUFFERED_OUTPUT +static int get_item_size_terminator(struct itemhead *item) +{ + return sizeof(struct itemhead); +} + +static int get_item_size_string(struct itemhead *item) +{ + struct itemstring *itemstring = (struct itemstring *) item; + unsigned int vlen = *((unsigned char **) &itemstring->messagedata) + - ((unsigned char *) itemstring); + return vlen + itemstring->datasize; +} + +static int get_item_size_buffer(struct itemhead *item) +{ + struct itembuffer *itembuffer = (struct itembuffer *) item; + return sizeof(struct itembuffer) + itembuffer->datasize; +} + +#if GC_ENABLE_OVERFLOW +typedef int (*getitemsize) (struct itemhead *item); + +static getitemsize g_itemsize[] = { + get_item_size_terminator, + get_item_size_string, + get_item_size_buffer +}; +#endif +#endif + + +/******************************************************************************* + * Printing functions. + */ + +#define GC_PRINTK(s, fmt, ...) \ + printf(fmt, ##__VA_ARGS__); \ + +#if GC_DEBUG_SELF +# define GC_DEBUGMSG(fmt, ...) \ + GC_PRINTK(NULL, "[%s:%d] " fmt, __func__, __LINE__, \ + ##__VA_ARGS__) +#else +# define GC_DEBUGMSG(...) {} +#endif + +static struct threadinfo *get_threadinfo(struct buffout *buffout) +{ +#if GC_THREAD_COUNT > 1 + struct threadinfo *threadinfo; + unsigned int i, count; + pid_t pid; + + /* Get current pid. */ + pid = gettid(); + + /* Try to locate thread record. */ + count = buffout->threadcount + 1; + for (i = 1; i < count; i += 1) + if (buffout->threadinfo[i].pid == pid) + return &buffout->threadinfo[i]; + + /* Not found, still have room? */ + if (buffout->threadcount < GC_THREAD_COUNT) { + threadinfo = &buffout->threadinfo[count]; + threadinfo->pid = pid; + threadinfo->msgindent = 0; + threadinfo->threadindent = buffout->threadcount + * GC_THREAD_INDENT; + buffout->threadcount += 1; + return threadinfo; + } + + /* Too many threads, use the common entry. */ + GC_PRINTK(NULL, "%s(%d) [ERROR] reached the maximum thread number.\n", + __func__, __LINE__); + threadinfo = buffout->threadinfo; + threadinfo->pid = pid; + return threadinfo; +#else + struct threadinfo *threadinfo; + threadinfo = buffout->threadinfo; + +#if GC_SHOW_PID + threadinfo->pid = pid; +#else + threadinfo->pid = 0; +#endif + + return threadinfo; +#endif +} + +static int gc_get_indent(int indent, char *buffer, int buffersize) +{ + static const int MAX_INDENT = 80; + int len, _indent; + + _indent = indent % MAX_INDENT; + if (_indent > buffersize) + _indent = buffersize - 1; + + for (len = 0; len < _indent; len += 1) + buffer[len] = ' '; + + buffer[len] = '\0'; + return len; +} + +static void gc_print_string(struct seq_file *s, struct itemstring *str) +{ + int len = 0; + char buffer[GC_MAXSTR_LENGTH]; + +#if GC_SHOW_DUMP_LINE + len += snprintf(buffer + len, sizeof(buffer) - len - GC_EOL_RESERVE, + GC_DUMPLINE_FORMAT, str->dumpline); +#endif + +#if GC_SHOW_PID + len += snprintf(buffer + len, sizeof(buffer) - len - GC_EOL_RESERVE, + GC_PID_FORMAT, str->pid); +#endif + + /* Append the indent string. */ + len += gc_get_indent(str->indent, buffer + len, + sizeof(buffer) - len - GC_EOL_RESERVE); + + /* Format the string. */ + len += vsnprintf(buffer + len, sizeof(buffer) - len - GC_EOL_RESERVE, + str->message, str->messagedata); + + /* Add end-of-line if missing. */ + if (buffer[len - 1] != '\n') + buffer[len++] = '\n'; + buffer[len] = '\0'; + + /* Print the string. */ + GC_PRINTK(s, "%s", buffer); +} + +static void gc_print_generic(struct seq_file *s, struct itembuffer *item, + unsigned char *data) +{ + char buffer[GC_MAXSTR_LENGTH]; + unsigned int i, indent, len; + + /* Append the indent string. */ + indent = gc_get_indent(item->indent, buffer, sizeof(buffer)); + + /* Print the title. */ + GC_PRINTK(s, "%sBUFFER @ 0x%08X\n", + buffer, item->gpuaddr); + + /* Print the buffer. */ + for (i = 0, len = indent; i < item->datasize; i += 4) { + if ((i % GC_GENERIC_DATA_COUNT) == 0) { + if (i != 0) { + /* Print the string. */ + GC_PRINTK(s, "%s\n", buffer); + + /* Reset the line. */ + len = indent; + } + + len += snprintf(buffer + len, sizeof(buffer) - len, + "0x%08X: ", item->gpuaddr + i); + } + + /* Append the data value. */ + len += snprintf(buffer + len, sizeof(buffer) - len, + " 0x%08X", *(unsigned int *) (data + i)); + } + + /* Print the last partial string. */ + if ((i % GC_SURFACE_DATA_COUNT) != 0) + GC_PRINTK(s, "%s\n", buffer); +} + +static char *gc_module_name(unsigned int index) +{ + switch (index) { + case GCREG_COMMAND_STALL_STALL_SOURCE_FRONT_END: + return "FE"; + + case GCREG_COMMAND_STALL_STALL_SOURCE_PIXEL_ENGINE: + return "PE"; + + case GCREG_COMMAND_STALL_STALL_SOURCE_DRAWING_ENGINE: + return "DE"; + + default: + return "*INVALID*"; + } +} + +static void gc_print_command(struct seq_file *s, struct itembuffer *item, + unsigned char *data) +{ + char buffer[GC_MAXSTR_LENGTH]; + unsigned int *data32; + unsigned int i, j, datacount; + unsigned int command, count, addr; + unsigned int delay, src, dst; + unsigned int x1, y1, x2, y2; + + /* Append the indent string. */ + gc_get_indent(item->indent, buffer, sizeof(buffer)); + + /* Print the title. */ + GC_PRINTK(s, "%sCOMMAND BUFFER @ 0x%08X\n", buffer, item->gpuaddr); + GC_PRINTK(s, "%s size = %d\n", buffer, item->datasize); + + datacount = (item->datasize + 3) / 4; + data32 = (unsigned int *) data; + for (i = 0; i < datacount;) { + command = (data32[i] >> 27) & 0x1F; + + switch (command) { + case GCREG_COMMAND_OPCODE_LOAD_STATE: + count = (data32[i] >> 16) & 0x3F; + addr = data32[i] & 0xFFFF; + GC_PRINTK(s, "%s 0x%08X: 0x%08X STATE(0x%04X, %d)\n", + buffer, item->gpuaddr + (i << 2), + data32[i], addr, count); + i += 1; + + count |= 1; + for (j = 0; j < count; i += 1, j += 1) + GC_PRINTK(s, "%s%14c0x%08X\n", + buffer, ' ', data32[i]); + break; + + case GCREG_COMMAND_OPCODE_END: + GC_PRINTK(s, "%s 0x%08X: 0x%08X END()\n", + buffer, item->gpuaddr + (i << 2), + data32[i]); + i += 1; + + GC_PRINTK(s, "%s%14c0x%08X\n", + buffer, ' ', data32[i]); + i += 1; + break; + + case GCREG_COMMAND_OPCODE_NOP: + GC_PRINTK(s, "%s 0x%08X: 0x%08X NOP()\n", + buffer, item->gpuaddr + (i << 2), + data32[i]); + i += 1; + + GC_PRINTK(s, "%s" "%14c0x%08X\n", + buffer, ' ', data32[i]); + i += 1; + break; + + case GCREG_COMMAND_OPCODE_STARTDE: + count = (data32[i] >> 8) & 0xFF; + GC_PRINTK(s, "%s 0x%08X: 0x%08X STARTDE(%d)\n", + buffer, item->gpuaddr + (i << 2), + data32[i], count); + i += 1; + + GC_PRINTK(s, "%s" "%14c0x%08X\n", + buffer, ' ', data32[i]); + i += 1; + + for (j = 0; j < count; j += 1) { + x1 = data32[i] & 0xFFFF; + y1 = (data32[i] >> 16) & 0xFFFF; + GC_PRINTK(s, "%s%14c0x%08X LT(%d,%d)\n", + buffer, ' ', data32[i], x1, y1); + i += 1; + + x2 = data32[i] & 0xFFFF; + y2 = (data32[i] >> 16) & 0xFFFF; + GC_PRINTK(s, "%s%14c0x%08X RB(%d,%d)\n", + buffer, ' ', data32[i], x2, y2); + i += 1; + } + break; + + case GCREG_COMMAND_OPCODE_WAIT: + delay = data32[i] & 0xFFFF; + GC_PRINTK(s, "%s 0x%08X: 0x%08X WAIT(%d)\n", + buffer, item->gpuaddr + (i << 2), + data32[i], delay); + i += 1; + + GC_PRINTK(s, "%s%14c0x%08X\n", buffer, ' ', data32[i]); + i += 1; + break; + + case GCREG_COMMAND_OPCODE_LINK: + count = data32[i] & 0xFFFF; + addr = data32[i + 1]; + GC_PRINTK(s, "%s 0x%08X: 0x%08X " + "LINK(0x%08X-0x%08X, %d)\n", + buffer, item->gpuaddr + (i << 2), + data32[i], addr, addr + count * 8, + count); + i += 1; + + GC_PRINTK(s, "%s%14c0x%08X\n", buffer, ' ', data32[i]); + i += 1; + break; + + case GCREG_COMMAND_OPCODE_STALL: + src = data32[i + 1] & 0x1F; + dst = (data32[i + 1] >> 8) & 0x1F; + + GC_PRINTK(s, "%s 0x%08X: 0x%08X STALL(%s-%s)\n", + buffer, item->gpuaddr + (i << 2), + data32[i], + gc_module_name(src), + gc_module_name(dst)); + i += 1; + + GC_PRINTK(s, "%s" "%14c0x%08X\n", + buffer, ' ', data32[i]); + i += 1; + break; + + default: + GC_PRINTK(s, "%s 0x%08X: 0x%08X UNKNOWN COMMAND\n", + buffer, item->gpuaddr + (i << 2), + data32[i]); + i += 2; + } + } +} + +static void gc_flush_line(struct seq_file *s, char *buffer, + unsigned int indent, unsigned int *len, + unsigned int count, unsigned char checksum) +{ + unsigned int _len; + char countstr[10]; + + /* Correct data count. */ + count %= GC_SURFACE_DATA_COUNT; + if (count == 0) + count = GC_SURFACE_DATA_COUNT; + + snprintf(countstr, sizeof(countstr), "%02X", count); + buffer[indent + 1] = countstr[0]; + buffer[indent + 2] = countstr[1]; + + /* Append the checksum. */ + _len = *len; + _len += snprintf(buffer + _len, sizeof(buffer) - _len, + "%02X", checksum); + + /* Print the string. */ + GC_PRINTK(s, "%s\n", buffer); + + /* Reset the length. */ + *len = indent; +} + +static void gc_print_surface(struct seq_file *s, struct itembuffer *itembuffer, + unsigned char *data) +{ + char buffer[GC_MAXSTR_LENGTH]; + unsigned int i, indent, len; + unsigned int prevupper32 = ~0U; + unsigned int currupper32; + unsigned int offset, address; + unsigned int width, height; + + /* Append the indent string. */ + indent = gc_get_indent(itembuffer->indent, buffer, sizeof(buffer)); + + /* Print the title. */ + GC_PRINTK(s, "%sIMAGE SURFACE @ 0x%08X\n", + buffer, itembuffer->gpuaddr); + + GC_PRINTK(s, "%s surface size = %dx%d\n", + buffer, itembuffer->surfwidth, itembuffer->surfheight); + + GC_PRINTK(s, "%s surface colordepth = %d\n", + buffer, itembuffer->surfbpp); + + GC_PRINTK(s, "%s dumping rectangle = (%d,%d)-(%d,%d)\n", + buffer, itembuffer->x1, itembuffer->y1, + itembuffer->x2, itembuffer->y2); + + /* Add TGA header. */ + width = itembuffer->x2 - itembuffer->x1; + height = itembuffer->y2 - itembuffer->y1; + GC_PRINTK(s, ":12000000000002000000000000000000" + "%02X%02X%02X%02X%02X2000\n", + (width & 0xFF), ((width >> 8) & 0xFF), + (height & 0xFF), ((height >> 8) & 0xFF), + itembuffer->surfbpp * 8); + + /* TGA skip header. */ + offset = 18; + + /* Print the buffer. */ + for (i = 0, len = indent; i < itembuffer->datasize; i += 1) { + /* Determine the current address. */ + address = offset + i; + + /* Determine the current higher 16 bits of the address. */ + currupper32 = address >> 16; + + /* Did it change? */ + if (currupper32 != prevupper32) { + /* Print the previous data if any. */ + if ((i % GC_SURFACE_DATA_COUNT) != 0) + gc_flush_line(s, buffer, indent, &len, i, 0); + + /* Set new upper address. */ + prevupper32 = currupper32; + GC_PRINTK(s, ":02000004%04X00\n", prevupper32); + + /* Add the line prefix. */ + len += snprintf(buffer + len, + sizeof(buffer) - len - 2, + ":xx%04X00", address & 0xFFFF); + } else if ((i % GC_SURFACE_DATA_COUNT) == 0) { + len += snprintf(buffer + len, + sizeof(buffer) - len - 2, + ":xx%04X00", address & 0xFFFF); + } + + /* Append the data value. */ + len += snprintf(buffer + len, + sizeof(buffer) - len - 2, + "%02X", data[i]); + + /* End of line? */ + if (((i + 1) % GC_SURFACE_DATA_COUNT) == 0) + gc_flush_line(s, buffer, indent, &len, i + 1, 0); + } + + /* Print the last partial string. */ + if ((i % GC_SURFACE_DATA_COUNT) != 0) + gc_flush_line(s, buffer, indent, &len, i, 0); + + /* End of dump. */ + GC_PRINTK(s, ":00000001FF\n"); +} + +typedef void (*printbuffer) (struct seq_file *s, struct itembuffer *itembuffer, + unsigned char *data); + +static printbuffer g_printbuffer[] = { + gc_print_generic, + gc_print_command, + gc_print_surface +}; + +static void gc_print_buffer(struct seq_file *s, struct itembuffer *itembuffer, + unsigned char *data) +{ + if (((int) itembuffer->buffertype < 0) || + (itembuffer->buffertype >= countof(g_printbuffer))) { + GC_PRINTK(s, "BUFFER ENTRY 0x%08X\n", + (unsigned int) itembuffer); + GC_PRINTK(s, "INVALID BUFFER TYPE %d\n", + itembuffer->buffertype); + } else { + g_printbuffer[itembuffer->buffertype](s, itembuffer, data); + } +} + + +/******************************************************************************* + * Print function wrappers. + */ + +#if GC_BUFFERED_OUTPUT +static unsigned int gc_print_none(struct seq_file *s, struct buffout *buffout, + struct itemhead *item) +{ + /* Return the size of the node. */ + return get_item_size_terminator(item); +} + +static unsigned int gc_print_string_wrapper(struct seq_file *s, + struct buffout *buffout, + struct itemhead *item) +{ + /* Print the message. */ + gc_print_string(s, (struct itemstring *) item); + + /* Return the size of the node. */ + return get_item_size_string(item); +} + +static unsigned int gc_print_buffer_wrapper(struct seq_file *s, + struct buffout *buffout, + struct itemhead *item) +{ + unsigned char *data; + struct itembuffer *itembuffer = (struct itembuffer *) item; + + /* Compute data address. */ + data = (unsigned char *) (itembuffer + 1); + + /* Print the message. */ + gc_print_buffer(s, (struct itembuffer *) item, data); + + /* Return the size of the node. */ + return get_item_size_buffer(item); +} + +typedef unsigned int (*printitem) (struct seq_file *s, struct buffout *buffout, + struct itemhead *item); + +static printitem g_printarray[] = { + gc_print_none, + gc_print_string_wrapper, + gc_print_buffer_wrapper +}; +#endif + + +/******************************************************************************* + * Private functions. + */ + +unsigned int gc_get_bpp(unsigned int format) +{ + unsigned int bpp; + + switch (format) { + case GCREG_DE_FORMAT_INDEX8: + case GCREG_DE_FORMAT_A8: + bpp = 1; + break; + + case GCREG_DE_FORMAT_X4R4G4B4: + case GCREG_DE_FORMAT_A4R4G4B4: + case GCREG_DE_FORMAT_X1R5G5B5: + case GCREG_DE_FORMAT_A1R5G5B5: + case GCREG_DE_FORMAT_R5G6B5: + case GCREG_DE_FORMAT_YUY2: + case GCREG_DE_FORMAT_UYVY: + case GCREG_DE_FORMAT_RG16: + bpp = 2; + break; + + case GCREG_DE_FORMAT_X8R8G8B8: + case GCREG_DE_FORMAT_A8R8G8B8: + bpp = 4; + break; + + default: + bpp = 0; + } + + return bpp; +} + +#if GC_BUFFERED_OUTPUT +static void gc_buffer_flush(struct seq_file *s, struct buffout *buffout) +{ + int i, skip; + struct itemhead *item; + + if (buffout->count == 0) + return; + + GC_PRINTK(s, "****************************************" + "****************************************\n"); + GC_PRINTK(s, "FLUSHING DEBUG OUTPUT BUFFER (%d elements).\n", + buffout->count); + +#if !GC_ENABLE_OVERFLOW + { + int occupied = (100 * (buffout->index - buffout->start)) + / GC_DUMP_BUFFER_SIZE; + if (buffout->start != 0) + GC_PRINTK(s, " START = %d\n", buffout->start); + GC_PRINTK(s, " INDEX = %d\n", buffout->index); + GC_PRINTK(s, " BUFFER USE = %d%%\n", occupied); + } +#endif + + GC_PRINTK(s, "****************************************" + "****************************************\n"); + + item = (struct itemhead *) &buffout->buffer[buffout->start]; + GC_DEBUGMSG("start=%d.\n", buffout->start); + + for (i = 0; i < buffout->count; i += 1) { + GC_DEBUGMSG("printing item %d of type %d @ 0x%08X.\n", + i, item->type, (unsigned int) item); + skip = (*g_printarray[item->type]) (s, buffout, item); + + item = (struct itemhead *) ((unsigned char *) item + skip); + GC_DEBUGMSG("next item @ 0x%08X.\n", (unsigned int) item); + + if (item->type == GC_BUFITEM_NONE) { + GC_DEBUGMSG("reached the end of buffer.\n"); + item = (struct itemhead *) buffout->buffer; + } + } + + GC_DEBUGMSG("resetting the buffer.\n"); + buffout->start = 0; + buffout->index = 0; + buffout->count = 0; +} + +static struct itemhead *gc_allocate_item(struct buffout *buffout, int size) +{ + struct itemhead *item, *next; + int endofbuffer = (buffout->index + size + >= GC_DUMP_BUFFER_SIZE - sizeof(struct itemhead)); + +#if GC_ENABLE_OVERFLOW + int skip, bufferoverflow; + + bufferoverflow = (buffout->index < buffout->start) && + (buffout->index + size >= buffout->start); + + if (endofbuffer || bufferoverflow) { + if (endofbuffer) { + if (buffout->index < buffout->start) { + item = (struct itemhead *) + &buffout->buffer[buffout->start]; + + while (item->type != GC_BUFITEM_NONE) { + skip = (*g_itemsize[item->type]) (item); + + buffout->start += skip; + buffout->count -= 1; + + item->type = GC_BUFITEM_NONE; + item = (struct itemhead *) + ((unsigned char *) item + skip); + } + + buffout->start = 0; + } + + buffout->index = 0; + } + + item = (struct itemhead *) &buffout->buffer[buffout->start]; + + while (buffout->start - buffout->index <= size) { + skip = (*g_itemsize[item->type]) (item); + + buffout->start += skip; + buffout->count -= 1; + + item->type = GC_BUFITEM_NONE; + item = (struct itemhead *) + ((unsigned char *) item + skip); + + if (item->type == GC_BUFITEM_NONE) { + buffout->start = 0; + break; + } + } + } +#else + if (endofbuffer) { + GC_PRINTK(NULL, "message buffer full; " + "forcing message flush.\n\n"); + gc_buffer_flush(NULL, buffout); + } +#endif + + item = (struct itemhead *) &buffout->buffer[buffout->index]; + + buffout->index += size; + buffout->count += 1; + + next = (struct itemhead *) ((unsigned char *) item + size); + next->type = GC_BUFITEM_NONE; + + return item; +} + +static void gc_append_string(struct buffout *buffout, + struct itemstring *itemstring) +{ + unsigned char *messagedata; + struct itemstring *item; + unsigned int alignment; + int size, freesize; + int allocsize; + + /* Determine the maximum item size. */ + allocsize = sizeof(struct itemstring) + itemstring->datasize + + GC_VARARG_ALIGNMENT; + + /* Allocate the item. */ + item = (struct itemstring *) gc_allocate_item(buffout, allocsize); + GC_DEBUGMSG("allocated %d bytes @ 0x%08X.\n", + allocsize, (unsigned int) item); + + /* Compute the initial message data pointer. */ + messagedata = (unsigned char *) (item + 1); + + /* Align the data pointer as necessary. */ + alignment = GC_PTRALIGNMENT(messagedata, GC_VARARG_ALIGNMENT); + messagedata += alignment; + GC_DEBUGMSG("messagedata @ 0x%08X.\n", (unsigned int) messagedata); + + /* Set item data. */ + item->itemtype = GC_BUFITEM_STRING; + item->indent = itemstring->indent; + item->message = itemstring->message; + item->messagedata = *(va_list *) &messagedata; + item->datasize = itemstring->datasize; + +#if GC_SHOW_PID + item->pid = itemstring->pid; +#endif + +#if GC_SHOW_DUMP_LINE + item->dumpline = itemstring->dumpline; +#endif + + /* Copy argument value. */ + if (itemstring->datasize != 0) { + GC_DEBUGMSG("copying %d bytes of messagedata.\n", + itemstring->datasize); + memcpy(messagedata, + *(unsigned char **) &itemstring->messagedata, + itemstring->datasize); + } + + /* Compute the actual node size. */ + size = sizeof(struct itemstring) + itemstring->datasize + alignment; + GC_DEBUGMSG("adjusted item size=%d.\n", size); + + /* Free extra memory if any. */ + freesize = allocsize - size; + GC_DEBUGMSG("freesize=%d.\n", freesize); + + if (freesize != 0) { + struct itemhead *next; + buffout->index -= freesize; + next = (struct itemhead *) ((unsigned char *) item + size); + next->type = GC_BUFITEM_NONE; + } + +#if GC_BUFFERED_OUTPUT && GC_FLUSH_COUNT + if (buffout->count >= GC_FLUSH_COUNT) { + GC_PRINTK(NULL, "reached %d message count; " + "forcing message flush.\n\n", buffout->count); + gc_buffer_flush(NULL, buffout); + } +#endif +} + +static void gc_append_buffer(struct buffout *buffout, + struct itembuffer *itembuffer, + unsigned int *data) +{ + struct itembuffer *item; + int allocsize; + + /* Determine the item size. */ + allocsize = sizeof(struct itembuffer) + itembuffer->datasize; + + /* Allocate the item. */ + item = (struct itembuffer *) gc_allocate_item(buffout, allocsize); + GC_DEBUGMSG("allocated %d bytes @ 0x%08X.\n", + allocsize, (unsigned int) item); + + /* Set item data. */ + *item = *itembuffer; + + /* Copy data. */ + memcpy(item + 1, data, itembuffer->datasize); + +#if GC_BUFFERED_OUTPUT && GC_FLUSH_COUNT + if (buffout->count >= GC_FLUSH_COUNT) { + GC_PRINTK(NULL, "reached %d message count; " + "forcing message flush.\n\n", buffout->count); + gc_buffer_flush(NULL, buffout); + } +#endif +} +#endif + +static void gc_print(struct buffout *buffout, unsigned int argsize, + const char *message, va_list args) +{ + struct itemstring itemstring; + struct threadinfo *threadinfo; + + GCLOCK(&g_lockmutex); + + /* Locate thead entry. */ + threadinfo = get_threadinfo(buffout); + + /* Form the indent string. */ + if (strncmp(message, "--", 2) == 0) + threadinfo->msgindent -= 2; + + /* Fill in the sructure. */ + itemstring.itemtype = GC_BUFITEM_STRING; + itemstring.indent = threadinfo->msgindent + + threadinfo->threadindent; + itemstring.message = message; + itemstring.messagedata = args; + itemstring.datasize = argsize; + +#if GC_SHOW_PID + itemstring.pid = threadinfo->pid; +#endif + +#if GC_SHOW_DUMP_LINE + itemstring.dumpline = ++buffout->dumpline; +#endif + + /* Print the message. */ +#if GC_BUFFERED_OUTPUT + gc_append_string(buffout, &itemstring); +#else + gc_print_string(NULL, &itemstring); +#endif + + /* Check increasing indent. */ + if (strncmp(message, "++", 2) == 0) + threadinfo->msgindent += 2; + + GCUNLOCK(&g_lockmutex); +} + + +/******************************************************************************* + * Dumping functions. + */ + +void gc_dump_string(struct gcdbgfilter *filter, unsigned int zone, + const char *message, ...) +{ + va_list args; + unsigned int i, count, argsize; + + if (!g_outputbuffer.enable) + return; + + if (message == NULL) + GC_DEBUGMSG("message is NULL.\n"); + + if (GC_VERIFY_ENABLE(filter, zone)) { + for (i = 0, count = 0; message[i]; i += 1) + if (message[i] == '%') + count += 1; + + argsize = count * sizeof(unsigned int); + GC_DEBUGMSG("argsize=%d.\n", argsize); + + va_start(args, message); + gc_print(&g_outputbuffer, argsize, message, args); + va_end(args); + } +} +EXPORT_SYMBOL(gc_dump_string); + +void gc_dump_string_sized(struct gcdbgfilter *filter, unsigned int zone, + unsigned int argsize, const char *message, ...) +{ + va_list args; + + if (!g_outputbuffer.enable) + return; + + if (GC_VERIFY_ENABLE(filter, zone)) { + va_start(args, message); + gc_print(&g_outputbuffer, argsize, message, args); + va_end(args); + } +} +EXPORT_SYMBOL(gc_dump_string_sized); + +void gc_dump_cmd_buffer(struct gcdbgfilter *filter, unsigned int zone, + void *ptr, unsigned int gpuaddr, unsigned int datasize) +{ + struct itembuffer itembuffer; + struct threadinfo *threadinfo; + + if (!g_outputbuffer.enable) + return; + + if (GC_VERIFY_ENABLE(filter, zone)) { + GCLOCK(&g_lockmutex); + + /* Locate thead entry. */ + threadinfo = get_threadinfo(&g_outputbuffer); + + /* Fill in the sructure. */ + itembuffer.itemtype = GC_BUFITEM_BUFFER; + itembuffer.buffertype = GC_BUFTYPE_COMMAND; + itembuffer.indent = threadinfo->msgindent + + threadinfo->threadindent; + itembuffer.datasize = datasize; + itembuffer.gpuaddr = gpuaddr; + + /* Print the message. */ +#if GC_BUFFERED_OUTPUT + gc_append_buffer(NULL, &g_outputbuffer, &itembuffer, + (unsigned int *) ptr); +#else + gc_print_buffer(NULL, &itembuffer, + (unsigned char *) ptr); +#endif + + GCUNLOCK(&g_lockmutex); + } +} +EXPORT_SYMBOL(gc_dump_cmd_buffer); + +void gc_dump_buffer(struct gcdbgfilter *filter, unsigned int zone, + void *ptr, unsigned int gpuaddr, + unsigned int datasize) +{ + struct itembuffer itembuffer; + struct threadinfo *threadinfo; + + if (!g_outputbuffer.enable) + return; + + if (GC_VERIFY_ENABLE(filter, zone)) { + GCLOCK(&g_lockmutex); + + /* Locate thead entry. */ + threadinfo = get_threadinfo(&g_outputbuffer); + + /* Fill in the sructure. */ + itembuffer.itemtype = GC_BUFITEM_BUFFER; + itembuffer.buffertype = GC_BUFTYPE_GENERIC; + itembuffer.indent = threadinfo->msgindent + + threadinfo->threadindent; + itembuffer.datasize = datasize; + itembuffer.gpuaddr = gpuaddr; + + /* Print the message. */ +#if GC_BUFFERED_OUTPUT + gc_append_buffer(NULL, &g_outputbuffer, &itembuffer, + (unsigned int *) ptr); +#else + gc_print_buffer(NULL, &itembuffer, + (unsigned char *) ptr); +#endif + + GCUNLOCK(&g_lockmutex); + } +} +EXPORT_SYMBOL(gc_dump_buffer); + + +/******************************************************************************* + * Dumping control functions. + */ + +void gc_dump_enable(void) +{ + GCLOCK(&g_lockmutex); + + g_outputbuffer.enable = 1; + GC_PRINTK(NULL, "gcx dumping is enabled.\n"); + + GCUNLOCK(&g_lockmutex); +} +EXPORT_SYMBOL(gc_dump_enable); + +void gc_dump_disable(void) +{ + GCLOCK(&g_lockmutex); + + g_outputbuffer.enable = 0; + GC_PRINTK(NULL, "gcx dumping is disabled.\n"); + + GCUNLOCK(&g_lockmutex); +} +EXPORT_SYMBOL(gc_dump_disable); + +void gc_dump_show_enabled(struct seq_file *s) +{ + struct list_head *filterhead; + struct gcdbgfilter *filter; + unsigned int i, zone; + + GCLOCK(&g_lockmutex); + + GC_PRINTK(s, "gcx logging is %s\n", g_outputbuffer.enable + ? "enabled" : "disabled"); + + list_for_each(filterhead, &gc_filterlist) { + filter = list_entry(filterhead, struct gcdbgfilter, + link); + + GC_PRINTK(s, "gcx filter '%s':\n", filter->filtername); + GC_PRINTK(s, " zone mask = 0x%08X%s\n", filter->zone, + (filter->zone == 0) + ? " (all disabled)" : ""); + + for (i = 0; filter->zonename[i] != NULL; i++) { + zone = 1 << i; + GC_PRINTK(s, " 0x%08X: %10s%s\n", + zone, filter->zonename[i], + ((filter->zone & zone) != 0) + ? " (enabled)" : ""); + } + } + + GCUNLOCK(&g_lockmutex); +} +EXPORT_SYMBOL(gc_dump_show_enabled); + +void gc_dump_filter_enable(const char *filtername, int zone) +{ + struct list_head *filterhead; + struct gcdbgfilter *filter; + unsigned int filterfound = 0; + unsigned int havesetzones = 0; + + GCLOCK(&g_lockmutex); + + GC_PRINTK(NULL, "modifying zone mask for filter %s:\n", filtername); + + list_for_each(filterhead, &gc_filterlist) { + filter = list_entry(filterhead, struct gcdbgfilter, + link); + + if (strcasecmp(filtername, filter->filtername) == 0) { + GC_PRINTK(NULL, " 0x%08X --> 0x%08X\n", + filter->zone, zone); + filter->zone = zone; + filterfound = 1; + } + + if (filter->zone != 0) + havesetzones = 1; + } + + GCUNLOCK(&g_lockmutex); + + if (!filterfound) + GC_PRINTK(NULL, " couldn't find filter %s.\n", filtername); + + if (havesetzones && !g_outputbuffer.enable) + gc_dump_enable(); + else if (!havesetzones && g_outputbuffer.enable) + gc_dump_disable(); +} +EXPORT_SYMBOL(gc_dump_filter_enable); + +void gc_dbg_add_client(struct gcdbgfilter *filter) +{ + list_add(&filter->link, &gc_filterlist); +} +EXPORT_SYMBOL(gc_dbg_add_client); + +void gc_dump_flush(struct seq_file *s) +{ +#if GC_BUFFERED_OUTPUT + GCLOCK(&g_lockmutex); + + /* + * Not dumping through debugfs for now because we have + * too much data and it'd require us to implement the + * seq_file iterator interface. + */ + gc_buffer_flush(NULL, &g_outputbuffer); + + GCUNLOCK(&g_lockmutex); +#endif +} +EXPORT_SYMBOL(gc_dump_flush); + +void gc_dump_reset(void) +{ +#if GC_BUFFERED_OUTPUT + GCLOCK(&g_lockmutex); + + g_outputbuffer.start = 0; + g_outputbuffer.index = 0; + g_outputbuffer.count = 0; + + GC_PRINTK(NULL, "gcx logging buffer is reset.\n"); + + GCUNLOCK(&g_lockmutex); +#endif +} +EXPORT_SYMBOL(gc_dump_reset); + + +/******************************************************************************* + * Command buffer parser. + */ + +int gc_parse_command_buffer(unsigned int *buffer, unsigned int size, + struct gccommandinfo *info) +{ + int res; + unsigned int i, j, itemcount, index, oldsrc; + unsigned int command, count, addr; + + memset(info, 0, sizeof(struct gccommandinfo)); + info->command = ~0U; + + oldsrc = 0; + + itemcount = (size + 3) / 4; + for (i = 0; i < itemcount;) { + command = (buffer[i] >> 27) & 0x1F; + + switch (command) { + case GCREG_COMMAND_OPCODE_LOAD_STATE: + count = (buffer[i] >> 16) & 0x3F; + addr = buffer[i] & 0xFFFF; + i += 1; + + for (j = 0; j < count; j += 1) { + switch (addr) { + case gcregDestAddressRegAddrs: + info->dst.surf.address = buffer[i]; + break; + + case gcregDestStrideRegAddrs: + info->dst.surf.stride = buffer[i]; + break; + + case gcregDestRotationConfigRegAddrs: + info->dst.surf.width + = buffer[i] & 0xFFFF; + break; + + case gcregDstRotationHeightRegAddrs: + info->dst.surf.height + = buffer[i] & 0xFFFF; + break; + + case gcregDestConfigRegAddrs: + info->command + = (buffer[i] >> 12) & 0xF; + + info->dst.surf.swizzle + = (buffer[i] >> 16) & 0x3; + + info->dst.surf.format + = buffer[i] & 0x1F; + + info->dst.surf.bpp = gc_get_bpp( + info->dst.surf.format); + break; + + case gcregSrcAddressRegAddrs: + info->src[0].surf.address = buffer[i]; + oldsrc = 1; + break; + + case gcregSrcStrideRegAddrs: + info->src[0].surf.stride = buffer[i]; + break; + + case gcregSrcRotationConfigRegAddrs: + info->src[0].surf.width + = buffer[i] & 0xFFFF; + break; + + case gcregSrcRotationHeightRegAddrs: + info->src[0].surf.height + = buffer[i] & 0xFFFF; + break; + + case gcregSrcConfigRegAddrs: + info->src[0].surf.swizzle + = (buffer[i] >> 20) & 0x3; + + info->src[0].surf.format + = (buffer[i] >> 24) & 0x1F; + + info->src[0].surf.bpp = gc_get_bpp( + info->src[0].surf.format); + break; + + case gcregSrcOriginRegAddrs: + info->src[0].rect.l + = buffer[i] & 0xFFFF; + + info->src[0].rect.t + = (buffer[i] >> 16) & 0xFFFF; + break; + + case gcregSrcSizeRegAddrs: + info->src[0].rect.r + = buffer[i] & 0xFFFF; + + info->src[0].rect.b + = (buffer[i] >> 16) & 0xFFFF; + break; + + case gcregBlock4SrcAddressRegAddrs: + case gcregBlock4SrcAddressRegAddrs + 1: + case gcregBlock4SrcAddressRegAddrs + 2: + case gcregBlock4SrcAddressRegAddrs + 3: + index = addr & 3; + info->src[index].surf.address + = buffer[i]; + break; + + case gcregBlock4SrcStrideRegAddrs: + case gcregBlock4SrcStrideRegAddrs + 1: + case gcregBlock4SrcStrideRegAddrs + 2: + case gcregBlock4SrcStrideRegAddrs + 3: + index = addr & 3; + info->src[index].surf.stride + = buffer[i]; + break; + + case gcregBlock4SrcRotationConfigRegAddrs: + case gcregBlock4SrcRotationConfigRegAddrs + 1: + case gcregBlock4SrcRotationConfigRegAddrs + 2: + case gcregBlock4SrcRotationConfigRegAddrs + 3: + index = addr & 3; + info->src[index].surf.width + = buffer[i] & 0xFFFF; + break; + + case gcregBlock4SrcRotationHeightRegAddrs: + case gcregBlock4SrcRotationHeightRegAddrs + 1: + case gcregBlock4SrcRotationHeightRegAddrs + 2: + case gcregBlock4SrcRotationHeightRegAddrs + 3: + index = addr & 3; + info->src[0].surf.height + = buffer[i] & 0xFFFF; + break; + + case gcregBlock4SrcConfigRegAddrs: + case gcregBlock4SrcConfigRegAddrs + 1: + case gcregBlock4SrcConfigRegAddrs + 2: + case gcregBlock4SrcConfigRegAddrs + 3: + index = addr & 3; + info->src[index].surf.swizzle + = (buffer[i] >> 20) & 0x3; + + info->src[index].surf.format + = (buffer[i] >> 24) & 0x1F; + + info->src[index].surf.bpp = gc_get_bpp( + info->src[index].surf.format); + break; + + case gcregBlock4SrcOriginRegAddrs: + case gcregBlock4SrcOriginRegAddrs + 1: + case gcregBlock4SrcOriginRegAddrs + 2: + case gcregBlock4SrcOriginRegAddrs + 3: + index = addr & 3; + info->src[index].rect.l + = buffer[i] & 0xFFFF; + + info->src[index].rect.t + = (buffer[i] >> 16) & 0xFFFF; + break; + + case gcregBlock4SrcSizeRegAddrs: + case gcregBlock4SrcSizeRegAddrs + 1: + case gcregBlock4SrcSizeRegAddrs + 2: + case gcregBlock4SrcSizeRegAddrs + 3: + index = addr & 3; + info->src[index].rect.r + = buffer[i] & 0xFFFF; + + info->src[index].rect.b + = (buffer[i] >> 16) & 0xFFFF; + break; + + case gcregDEMultiSourceRegAddrs: + info->srccount = (buffer[i] & 0x7) + 1; + break; + } + + addr += 1; + i += 1; + } + + i += ((~count) & 1); + break; + + case GCREG_COMMAND_OPCODE_END: + case GCREG_COMMAND_OPCODE_NOP: + case GCREG_COMMAND_OPCODE_WAIT: + case GCREG_COMMAND_OPCODE_LINK: + case GCREG_COMMAND_OPCODE_STALL: + i += 2; + break; + + case GCREG_COMMAND_OPCODE_STARTDE: + info->dst.rectcount = (buffer[i] >> 8) & 0xFF; + i += 2; + + for (j = 0; j < info->dst.rectcount; j += 1) { + info->dst.rect[j].l + = buffer[i] & 0xFFFF; + info->dst.rect[j].t + = (buffer[i] >> 16) & 0xFFFF; + i += 1; + + info->dst.rect[j].r + = buffer[i] & 0xFFFF; + info->dst.rect[j].b + = (buffer[i] >> 16) & 0xFFFF; + i += 1; + } + break; + + default: + res = 0; + gc_dump_string(NULL, 0, + "bad command (%d) " + "while parsing the command stream", + command); + goto exit; + } + + } + + /* Enable old source. */ + if ((info->srccount == 0) && oldsrc) + info->srccount = 1; + + /* Success. */ + res = 1; + +exit: + return res; +} +EXPORT_SYMBOL(gc_parse_command_buffer); + + +/******************************************************************************* + * Bltsville debugging. + */ + +char *gc_bvblend_name(enum bvblend blend) +{ + switch (blend) { + case BVBLEND_CLEAR: return "BVBLEND_CLEAR"; + case BVBLEND_SRC1: return "BVBLEND_SRC1"; + case BVBLEND_SRC2: return "BVBLEND_SRC2"; + case BVBLEND_SRC1OVER: return "BVBLEND_SRC1OVER"; + case BVBLEND_SRC2OVER: return "BVBLEND_SRC2OVER"; + case BVBLEND_SRC1IN: return "BVBLEND_SRC1IN"; + case BVBLEND_SRC2IN: return "BVBLEND_SRC2IN"; + case BVBLEND_SRC1OUT: return "BVBLEND_SRC1OUT"; + case BVBLEND_SRC2OUT: return "BVBLEND_SRC2OUT"; + case BVBLEND_SRC1ATOP: return "BVBLEND_SRC1ATOP"; + case BVBLEND_SRC2ATOP: return "BVBLEND_SRC2ATOP"; + case BVBLEND_XOR: return "BVBLEND_XOR"; + case BVBLEND_PLUS: return "BVBLEND_PLUS"; + case BVBLEND_NORMAL: return "BVBLEND_NORMAL"; + case BVBLEND_LIGHTEN: return "BVBLEND_LIGHTEN"; + case BVBLEND_DARKEN: return "BVBLEND_DARKEN"; + case BVBLEND_MULTIPLY: return "BVBLEND_MULTIPLY"; + case BVBLEND_AVERAGE: return "BVBLEND_AVERAGE"; + case BVBLEND_ADD: return "BVBLEND_ADD"; + case BVBLEND_SUBTRACT: return "BVBLEND_SUBTRACT"; + case BVBLEND_DIFFERENCE: return "BVBLEND_DIFFERENCE"; + case BVBLEND_NEGATE: return "BVBLEND_NEGATE"; + case BVBLEND_SCREEN: return "BVBLEND_SCREEN"; + case BVBLEND_EXCLUSION: return "BVBLEND_EXCLUSION"; + case BVBLEND_OVERLAY: return "BVBLEND_OVERLAY"; + case BVBLEND_SOFT_LIGHT: return "BVBLEND_SOFT_LIGHT"; + case BVBLEND_HARD_LIGHT: return "BVBLEND_HARD_LIGHT"; + case BVBLEND_COLOR_DODGE: return "BVBLEND_COLOR_DODGE"; + case BVBLEND_COLOR_BURN: return "BVBLEND_COLOR_BURN"; + case BVBLEND_LINEAR_LIGHT: return "BVBLEND_LINEAR_LIGHT"; + case BVBLEND_VIVID_LIGHT: return "BVBLEND_VIVID_LIGHT"; + case BVBLEND_PIN_LIGHT: return "BVBLEND_PIN_LIGHT"; + case BVBLEND_HARD_MIX: return "BVBLEND_HARD_MIX"; + case BVBLEND_REFLECT: return "BVBLEND_REFLECT"; + case BVBLEND_GLOW: return "BVBLEND_GLOW"; + case BVBLEND_PHOENIX: return "BVBLEND_PHOENIX"; + default: return "[UNKNOWN]"; + } +} +EXPORT_SYMBOL(gc_bvblend_name); + + +/******************************************************************************* + * Initialization/cleanup. + */ + +void gcdbg_init(void) +{ +#if GC_BUFFERED_OUTPUT + /* Allocate the debug buffer. */ + g_outputbuffer.buffer = kmalloc(GC_DUMP_BUFFER_SIZE, GFP_KERNEL); + if (g_outputbuffer.buffer == NULL) { + GC_PRINTK(NULL, "failed to allocate dump buffer.\n"); + return; + } +#endif + + g_initdone = 1; +} + +void gcdbg_exit(void) +{ +#if GC_BUFFERED_OUTPUT + if (g_outputbuffer.buffer != NULL) { + kfree(g_outputbuffer.buffer); + g_outputbuffer.buffer = NULL; + } +#endif + + g_initdone = 0; +} + +#endif /* GCDEBUG_ENABLE */ diff --git a/gcbv/mirror/include/cache-2dmanager.h b/gcbv/mirror/include/cache-2dmanager.h new file mode 100644 index 0000000..a013514 --- /dev/null +++ b/gcbv/mirror/include/cache-2dmanager.h @@ -0,0 +1,103 @@ +/* + * 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, + * Texas Instruments, Inc. and 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, + * Texas Instruments, Inc. and Vivante Corporation. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Vivante Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CACHE_2DMANAGER_H_ +#define CACHE_2DMANAGER_H_ + +/* The value below only applies to OMAP4 */ +#define L1CACHE_SIZE 32768 +#define L2CACHE_SIZE 1048576 + +#define L1THRESHOLD L1CACHE_SIZE +#define L2THRESHOLD L2CACHE_SIZE + +struct c2dmrgn { + char *start; /* addr of upper left of rect */ + size_t span; /* bytes to be operated on per line */ + size_t lines; /* lines to be operated on */ + long stride; /* bytes per line */ +}; + +/* + * c2dm_l1cache(count, rgns, dir) + * + * L1 Cache operations in 2D + * + * - count - number of regions + * - rgns - array of regions + * - dir - cache operation direction + * + */ +void c2dm_l1cache(int count, struct c2dmrgn rgns[], int dir); + +/* + * c2dm_l2cache(count, rgns, dir) + * + * L2 Cache operations in 2D + * + * - count - number of regions + * - rgns - array of regions + * - dir - cache operation direction + * + */ +void c2dm_l2cache(int count, struct c2dmrgn rgns[], int dir); + + +#endif /* CACHE_2DMANAGER_H_ */ diff --git a/gcbv/mirror/include/gcdbglog.h b/gcbv/mirror/include/gcdbglog.h new file mode 100644 index 0000000..23df118 --- /dev/null +++ b/gcbv/mirror/include/gcdbglog.h @@ -0,0 +1,412 @@ +/* + * 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, + * Texas Instruments, Inc. and 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, + * Texas Instruments, Inc. and Vivante Corporation. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Vivante Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef GCDBGLOG_H +#define GCDBGLOG_H + +#include "gclist.h" +#include <bltsville.h> +struct gcmmucontext; + + +/******************************************************************************* + * Debug logging switches. + */ + +/* Enables internal gccore logging backend. */ +#if !defined(GCDEBUG_ENABLE) +#define GCDEBUG_ENABLE 0 /* Enabled for development branch only. */ +#endif + +/* Enables linux builtin logging backend. */ +#if !defined(GCDEBUG_LINUXLOGS) +#define GCDEBUG_LINUXLOGS 0 +#endif + +#if GCDEBUG_ENABLE && GCDEBUG_LINUXLOGS +#error GCDEBUG_ENABLE and GCDEBUG_LINUXLOGS cannot be enabled simultaneously. +#endif + + +/******************************************************************************* + * Dumping interface macro for release mode. + */ + +#if !GCDEBUG_ENABLE && !GCDEBUG_LINUXLOGS +#define GCDBG_INIT(...) +#define GCDBG_EXIT(...) +#define GCDBG_FILTERDEF(...) +#define GCDBG_REGISTER(...) +#define GCENTER(...) +#define GCEXIT(...) +#define GCENTERARG(...) +#define GCEXITARG(...) +#define GCDBG(...) {} +#define GCERR(...) {} +#define GCDUMPSTRING(...) {} +#define GCDUMPBUFFER(...) {} +#define GCDUMPARENA(...) {} +#define GCDUMPARENAS(...) {} +#define GCGPUSTATUS(...) {} +#endif + +#if !GCDEBUG_ENABLE +#define GCDBG_REPORT_MISSING() \ + printf("gcx logging is not integrated.\n") + +#define GCDBG_SHOWENABLED(s) \ + GCDBG_REPORT_MISSING() + +#define GCDBG_ENABLEDUMP() \ + GCDBG_REPORT_MISSING() + +#define GCDBG_DISABLEDUMP() \ + GCDBG_REPORT_MISSING() + +#define GCDBG_SETFILTER(filtername, zone) \ + GCDBG_REPORT_MISSING() + +#define GCDBG_FLUSHDUMP(s) \ + GCDBG_REPORT_MISSING() + +#define GCDBG_RESETDUMP() \ + GCDBG_REPORT_MISSING() + +#endif + + +/******************************************************************************* + * Dumping macros not specific to a particular logging backend. + */ + +#if GCDEBUG_ENABLE || GCDEBUG_LINUXLOGS + +#define GC_MOD_PREFIX \ + GC_DEV_NAME ": %s(%d) " + +#define GCDUMPARENA(zone, text, arena) \ +do { \ + GCDBG(zone, text " @ 0x%08X:\n", (unsigned int) arena); \ + GCDBG(zone, " number of pages = %u\n", \ + (arena)->count); \ + GCDBG(zone, " from (absolute/mtlb/stlb) = 0x%08X / %u / %u\n", \ + (arena)->start.absolute, \ + (arena)->start.loc.mtlb, \ + (arena)->start.loc.stlb); \ + GCDBG(zone, " to (absolute/mtlb/stlb) = 0x%08X / %u / %u\n", \ + (arena)->end.absolute, \ + (arena)->end.loc.mtlb, \ + (arena)->end.loc.stlb); \ +} while (false) + +#define GCDUMPARENAS(zone, text, arenahead) \ +do { \ + GCDBG(zone, "%s:\n", text); \ + \ + if (list_empty(arenahead)) { \ + GCDBG(zone, " no arenas defined in the list.\n"); \ + } else { \ + struct list_head *entry; \ + struct gcmmuarena *arena; \ + \ + list_for_each(entry, arenahead) { \ + arena = list_entry(entry, struct gcmmuarena, link); \ + GCDUMPARENA(zone, "arena", arena); \ + } \ + } \ +} while (false) + +#endif + +#define GC_FUNC_ENTER "++" +#define GC_FUNC_EXIT "--" + + +/******************************************************************************* + * Dumping macros for internal gccore logging backend. + */ + +#if GCDEBUG_ENABLE + +#define GCDBGFILTER \ + g_gcdbgfilter + +#define GCDBG_INIT() \ + gcdbg_init() + +#define GCDBG_EXIT() \ + gcdbg_exit() + +#define GCDBG_FILTERDEF(name, initzone, ...) \ + static struct gcdbgfilter GCDBGFILTER = { \ + .link = LIST_HEAD_INIT(GCDBGFILTER.link), \ + .filtername = #name, \ + .zone = initzone, \ + .zonename = { __VA_ARGS__, NULL } \ + }; \ + \ + struct gcdbgfilter *name ## _dbgfilter(void) \ + { \ + return &GCDBGFILTER; \ + } + +#define GCDBG_REGISTER(name) \ +do { \ + struct gcdbgfilter *name ## _dbgfilter(void); \ + gc_dbg_add_client(name ## _dbgfilter()); \ +} while (0) + +#define GCDBG_SHOWENABLED(s) \ + gc_dump_show_enabled(s) + +#define GCDBG_ENABLEDUMP() \ + gc_dump_enable() + +#define GCDBG_DISABLEDUMP() \ + gc_dump_disable() + +#define GCDBG_SETFILTER(filtername, zone) \ + gc_dump_filter_enable(filtername, zone) + +#define GCDBG_FLUSHDUMP(s) \ + gc_dump_flush(s) + +#define GCDBG_RESETDUMP() \ + gc_dump_reset() + +#define GCENTER(zone) \ + gc_dump_string(&GCDBGFILTER, zone, GC_FUNC_ENTER GC_MOD_PREFIX "\n", \ + __func__, __LINE__) + +#define GCEXIT(zone) \ + gc_dump_string(&GCDBGFILTER, zone, GC_FUNC_EXIT GC_MOD_PREFIX "\n", \ + __func__, __LINE__) + +#define GCENTERARG(zone, msg, ...) \ + gc_dump_string(&GCDBGFILTER, zone, GC_FUNC_ENTER GC_MOD_PREFIX msg, \ + __func__, __LINE__, ##__VA_ARGS__) + +#define GCEXITARG(zone, msg, ...) \ + gc_dump_string(&GCDBGFILTER, zone, GC_FUNC_EXIT GC_MOD_PREFIX msg, \ + __func__, __LINE__, ##__VA_ARGS__) + +#define GCDBG(zone, msg, ...) \ + gc_dump_string(&GCDBGFILTER, zone, GC_MOD_PREFIX msg, \ + __func__, __LINE__, ##__VA_ARGS__) + +#define GCERR(msg, ...) \ + gc_dump_string(NULL, 0, GC_MOD_PREFIX "[ERROR] " msg, \ + __func__, __LINE__, ##__VA_ARGS__) + +#define GCDUMPSTRING(msg, ...) \ + gc_dump_string(NULL, 0, msg, ##__VA_ARGS__) + +#define GCDUMPBUFFER(zone, ptr, gpuaddr, datasize) \ + gc_dump_cmd_buffer(&GCDBGFILTER, zone, ptr, gpuaddr, datasize) + +#endif + + +/******************************************************************************* + * Dumping macros for linux builtin logging backend. + */ + +#if GCDEBUG_LINUXLOGS + +#define GCDBG_INIT() +#define GCDBG_EXIT() +#define GCDBG_FILTERDEF(...) +#define GCDBG_REGISTER(...) + +#define GCENTER(zone) \ + GCDBG(zone, GC_FUNC_ENTER " %s(%d)\n", __func__, __LINE__) + +#define GCEXIT(zone) \ + GCDBG(zone, GC_FUNC_EXIT " %s(%d)\n", __func__, __LINE__) + +#define GCENTERARG(zone, msg, ...) \ + GCDBG(zone, GC_FUNC_ENTER " %s(%d) " msg "\n", \ + __func__, __LINE__, ##__VA_ARGS__) + +#define GCEXITARG(zone, msg, ...) \ + GCDBG(zone, GC_FUNC_EXIT " %s(%d) " msg "\n", \ + __func__, __LINE__, ##__VA_ARGS__) + +#define GCDBG(zone, msg, ...) \ + dev_dbg(gc_get_dev(), msg, ##__VA_ARGS__) + +#define GCERR(msg, ...) \ + GCDBG(0, msg, ##__VA_ARGS__) + +#define GCDUMPSTRING(msg, ...) \ + GCDBG(0, msg, ##__VA_ARGS__) + +#define GCDUMPBUFFER(...) {} +#define GCGPUSTATUS(...) {} + +#endif + + +/******************************************************************************* + * Command buffer parser. + */ + +struct gcrect { + int l; + int t; + int r; + int b; +}; + +struct gcsurfaceinfo { + unsigned int width; + unsigned int height; + unsigned int address; + unsigned int stride; + unsigned int swizzle; + unsigned int format; + unsigned int bpp; +}; + +struct gcsourceinfo { + struct gcsurfaceinfo surf; + struct gcrect rect; +}; + +struct gcdestinfo { + struct gcsurfaceinfo surf; + unsigned int rectcount; + struct gcrect rect[256]; +}; + +struct gccommandinfo { + unsigned int command; + unsigned int srccount; + struct gcsourceinfo src[4]; + struct gcdestinfo dst; +}; + +/* Parse the specified command buffer and fill in the structure. */ +int gc_parse_command_buffer(unsigned int *buffer, unsigned int size, + struct gccommandinfo *info); + + +/******************************************************************************* + * Filter structure. + */ + +struct gcdbgfilter { + struct list_head link; + char *filtername; + unsigned int zone; + const char *zonename[]; +}; + + +/******************************************************************************* + * Debug init/exit functions. + */ + +void gcdbg_init(void); +void gcdbg_exit(void); + + +/******************************************************************************* + * Dumping functions. + */ + +/* String dumping. */ +void gc_dump_string(struct gcdbgfilter *filter, unsigned int zone, + const char *message, ...); +void gc_dump_string_sized(struct gcdbgfilter *filter, unsigned int zone, + unsigned int argsize, const char *message, ...); + +/* Dump command buffer. */ +void gc_dump_cmd_buffer(struct gcdbgfilter *filter, unsigned int zone, + void *ptr, unsigned int gpuaddr, unsigned int datasize); + +/* Dump generic buffer. */ +void gc_dump_buffer(struct gcdbgfilter *filter, unsigned int zone, + void *ptr, unsigned int gpuaddr, unsigned int datasize); + + +/******************************************************************************* + * Bltsville debugging. + */ + +char *gc_bvblend_name(enum bvblend blend); + + +/******************************************************************************* + * Dumping control. + */ + +struct seq_file; + +struct device *gc_get_dev(void); +void gc_dump_show_enabled(struct seq_file *s); +void gc_dump_enable(void); +void gc_dump_disable(void); +void gc_dump_filter_enable(const char *filtername, int zone); +void gc_dump_flush(struct seq_file *s); +void gc_dump_reset(void); +void gc_dbg_add_client(struct gcdbgfilter *filter); + +#endif diff --git a/gcbv/gcerror.h b/gcbv/mirror/include/gcerror.h index 88309a8..35b074d 100644 --- a/gcbv/gcerror.h +++ b/gcbv/mirror/include/gcerror.h @@ -1,28 +1,61 @@ /* - * Copyright (c) 2011, Texas Instruments, Inc. + * 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, + * Texas Instruments, Inc. and 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, + * Texas Instruments, Inc. and Vivante Corporation. + * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Texas Instruments, Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. + * + * * 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 TEXAS INSTRUMENTS, INC. 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. + * 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 GCERROR_H @@ -115,9 +148,36 @@ enum gcerror { = GCERR_GROUP(0x01020), /**** Command queue errors. */ - GCERR_CMD_ALLOC /* Buffer allocation. */ + GCERR_CMD_ENTRY_PIPE /* Entry pipe is invalid. */ = GCERR_GROUP(0x02000), + GCERR_CMD_EXIT_PIPE /* Exit pipe is invalid. */ + = GCERR_GROUP(0x02010), + + GCERR_CMD_MAPPED /* Command buffer mapping error. */ + = GCERR_GROUP(0x02020), + + GCERR_CMD_CONSISTENCY /* Inconsistent mapping. */ + = GCERR_GROUP(0x02030), + + GCERR_CMD_ALLOC /* Buffer allocation. */ + = GCERR_GROUP(0x02040), + + GCERR_CMD_QUEUE_ALLOC /* Buffer queue allocation. */ + = GCERR_GROUP(0x02050), + + GCERR_CMD_EVENT_ALLOC /* Event allocation. */ + = GCERR_GROUP(0x02060), + + GCERR_CMD_INT_ALLOC /* Interrupt allocation. */ + = GCERR_GROUP(0x02070), + + GCERR_CMD_ISR /* ISR initialization. */ + = GCERR_GROUP(0x02080), + + GCERR_CMD_THREAD /* Thread initialization. */ + = GCERR_GROUP(0x02090), + /**** MMU errors. */ GCERR_MMU_CTXT_BAD /* Invalid context. */ = GCERR_GROUP(0x03000), @@ -177,6 +237,9 @@ enum gcerror { GCERR_POWER_IRQ_ON /* Failed to install IRQ handler. */ = GCERR_GROUP(0x04020), + GCERR_POWER_PULSE /* Pulse skipping error. */ + = GCERR_GROUP(0x04030), + /**** GCIOCTL module errors. */ GCERR_IOCTL_CTX_ALLOC /* Context wrapper allocation. */ = GCERR_GROUP(0x11000), diff --git a/gcbv/mirror/include/gcioctl.h b/gcbv/mirror/include/gcioctl.h new file mode 100644 index 0000000..9a105ab --- /dev/null +++ b/gcbv/mirror/include/gcioctl.h @@ -0,0 +1,263 @@ +/* + * 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, + * Texas Instruments, Inc. and 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, + * Texas Instruments, Inc. and Vivante Corporation. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Vivante Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef GCIOCTL_H +#define GCIOCTL_H + +#include "gclist.h" +#include "gcerror.h" +#include "cache-2dmanager.h" +#include <bverror.h> + +/* IOCTL parameters. */ +#define GCIOCTL_TYPE 0x5D +#define GCIOCTL_BASE 0x5D + + +/******************************************************************************* + * Commit API entry. + */ + +#define GCIOCTL_COMMIT _IOWR(GCIOCTL_TYPE, GCIOCTL_BASE + 0x10, struct gccommit) + +/* GPU graphics pipe definition. */ +enum gcpipe { + GCPIPE_UNKNOWN, + GCPIPE_2D, + GCPIPE_3D +}; + +/* Commit header; contains pointers to the head and the tail of a linked list + of command buffers to execute. */ +struct gccommit { + /* Return status code. */ + enum gcerror gcerror; + + /* Entry graphics pipe specifies the pipe the GPU is expected to be in + * for successfull execution of the specified command buffers in this + * call. Exit graphics pipe specifies the state of the GPU after the + * buffers are executed. */ + enum gcpipe entrypipe; + enum gcpipe exitpipe; + + /* Pointer to the list of command buffers to be executed. */ + struct gcbuffer *buffer; + + /* Pointer to the callback function to be called when the GPU completes + * execution of all buffers specified in this call. This member can be + * NULL if no callback is desired. callbackparam specifies data to be + * passed to the callback. */ + void (*callback) (void *callbackparam); + void *callbackparam; + unsigned long handle; + + /* If asynchronous is set to true, the call returns immediately without + * waiting until all specified buffers have been executed. If set to + * false, the call does not return until execution is finished. */ + bool asynchronous; + + /* Scheduled unmappings (gcschedunmap). */ + struct list_head unmap; +}; + +/* Command buffer header. */ +#define GC_BUFFER_SIZE (32 * 1024) +struct gcbuffer { + /* Pointers to the head and tail of the command buffer fixup list. */ + struct gcfixup *fixuphead; + struct gcfixup *fixuptail; + + /* Number of pixels to be rendered. */ + unsigned int pixelcount; + + /* Pointers to the head and tail of the command buffer list. */ + unsigned int *head; + unsigned int *tail; + + /* Number of bytes available in the buffer for allocation. */ + unsigned int available; + + /* Pointer to the next commmand buffer. + * TODO: change to kernel style linked list. */ + struct gcbuffer *next; +}; + +/* Fixup entry. */ +struct gcfixupentry { + /* Offset into the commmand buffer where fixup is to be performed. */ + unsigned int dataoffset; + + /* Offset to be added to the translated address. */ + unsigned int surfoffset; +}; + +/* Address fixup array. */ +#define GC_FIXUP_MAX 1024 +struct gcfixup { + /* Pointer to the next fixup array. + * TODO: change to kernel style linked list. */ + struct gcfixup *next; + + /* Fixup array. */ + unsigned int count; + struct gcfixupentry fixup[GC_FIXUP_MAX]; +}; + +/* Defines a link list of scheduled unmappings. */ +struct gcschedunmap { + /* Map handle. */ + unsigned long handle; + + /* Previous/next unmapping info. */ + struct list_head link; +}; + + +/******************************************************************************* + * Map/unmap API entries. + */ + +#define GCIOCTL_MAP _IOWR(GCIOCTL_TYPE, GCIOCTL_BASE + 0x20, struct gcmap) +#define GCIOCTL_UNMAP _IOWR(GCIOCTL_TYPE, GCIOCTL_BASE + 0x21, struct gcmap) + +struct gcmap { + /* Return status code. */ + enum gcerror gcerror; + + /* Mapped handle of the buffer. */ + unsigned long handle; + + union { + /* Pointer to the buffer to be mapped; + * used when pagearray is not provided (set to NULL). */ + void *logical; + + /* Page offset of the buffer to be mapped; + * used when pagearray is provided. */ + unsigned int offset; + } buf; + + /* Size of a physical page, 0 for default. */ + unsigned int pagesize; + + /* Pointer to array of physical pages. */ + unsigned long *pagearray; + + /* Size of the buffer to be mappped. */ + unsigned int size; +}; + + +/***************************************************************************** + * Cache manipulation API entries. + */ + +#define GCIOCTL_CACHE _IOW(GCIOCTL_TYPE, GCIOCTL_BASE + 0x30, \ + struct gccachexfer) + +struct gccachexfer { + /* Number of regions. */ + int count; + + /* The most regions that we deal with is 3. */ + struct c2dmrgn rgn[3]; + + /* Direction of data. */ + int dir; +}; + + +/******************************************************************************* + * Callback API entry. + */ + +#define GCIOCTL_CALLBACK_ALLOC _IOW(GCIOCTL_TYPE, GCIOCTL_BASE + 0x40, \ + struct gccmdcallback) +#define GCIOCTL_CALLBACK_FREE _IOW(GCIOCTL_TYPE, GCIOCTL_BASE + 0x41, \ + struct gccmdcallback) +#define GCIOCTL_CALLBACK_WAIT _IOW(GCIOCTL_TYPE, GCIOCTL_BASE + 0x42, \ + struct gccmdcallbackwait) + +struct gccmdcallback { + /* Error code. */ + enum gcerror gcerror; + + /* Callback handle. */ + unsigned long handle; +}; + +struct gccmdcallbackwait { + /* Error code. */ + enum gcerror gcerror; + + /* Callback handle. */ + unsigned long handle; + + /* Timeout in milliseconds. */ + unsigned long timeoutms; + + /* OUT: if the call succeeds, callback and callbackparam are + * initialized with the callback to call. */ + void (*callback) (void *callbackparam); + void *callbackparam; +}; + + +#endif diff --git a/gcbv/mirror/include/gclist.h b/gcbv/mirror/include/gclist.h new file mode 100644 index 0000000..33c9743 --- /dev/null +++ b/gcbv/mirror/include/gclist.h @@ -0,0 +1,630 @@ +/* + * 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, + * Texas Instruments, Inc. and 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, + * Texas Instruments, Inc. and Vivante Corporation. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Vivante Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _GCLIST_H +#define _GCLIST_H +#ifdef __cplusplus +extern "C" { +#endif + +/* Adaptation of Linux kernel double linked list. */ + +#define LIST_POISON1 ((void *) 0x00100100) +#define LIST_POISON2 ((void *) 0x00200200) + +#if !defined(countof) +#define countof(a) \ + (sizeof(a) / sizeof(a[0])) +#endif + +#if !defined(offsetof) +#define offsetof(type, member) \ + ((size_t) &((type *) 0)->member) +#endif + +#if !defined(containerof) +#define containerof(ptr, type, member) \ + ((type *) ((char *) ptr - offsetof(type, member))) +#endif + +struct list_head { + struct list_head *next, *prev; +}; + +#define LIST_HEAD_INIT(name) { &(name), &(name) } + +#define LIST_HEAD(name) \ + struct list_head name = LIST_HEAD_INIT(name) + +static void INIT_LIST_HEAD(struct list_head *list) +{ + list->next = list; + list->prev = list; +} + +/* Insert a new entry between two known consecutive entries. + * This is only for internal list manipulation where we know + * the prev/next entries already! */ +static void __list_add(struct list_head *entry, + struct list_head *prev, + struct list_head *next) +{ + next->prev = entry; + entry->next = next; + entry->prev = prev; + prev->next = entry; +} + +/** + * list_add - add a new entry + * @newentry: new entry to be added + * @head: list head to add it after + * + * Insert a new entry after the specified head. + * This is good for implementing stacks. + */ +static void list_add(struct list_head *newentry, + struct list_head *head) +{ + __list_add(newentry, head, head->next); +} + + +/** + * list_add_tail - add a new entry + * @newentry: new entry to be added + * @head: list head to add it before + * + * Insert a new entry before the specified head. + * This is useful for implementing queues. + */ +static void list_add_tail(struct list_head *newentry, + struct list_head *head) +{ + __list_add(newentry, head->prev, head); +} + +/* Delete a list entry by making the prev/next entries point to each other. + * This is only for internal list manipulation where we know + * the prev/next entries already! */ +static void __list_del(struct list_head *prev, + struct list_head *next) +{ + next->prev = prev; + prev->next = next; +} + +/** + * list_del - deletes entry from list. + * @entry: the element to delete from the list. + * Note: list_empty() on entry does not return true after this, + * the entry is in an undefined state. + */ +static void __list_del_entry(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); +} + +static void list_del(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + entry->next = LIST_POISON1; + entry->prev = LIST_POISON2; +} + +/** + * list_replace - replace old entry by new one + * @oldentry : the element to be replaced + * @newentry : the new element to insert + * + * If @old was empty, it will be overwritten. + */ +static void list_replace(struct list_head *oldentry, + struct list_head *newentry) +{ + newentry->next = oldentry->next; + newentry->next->prev = newentry; + newentry->prev = oldentry->prev; + newentry->prev->next = newentry; +} + +static void list_replace_init(struct list_head *oldentry, + struct list_head *newentry) +{ + list_replace(oldentry, newentry); + INIT_LIST_HEAD(oldentry); +} + +/** + * list_del_init - deletes entry from list and reinitialize it. + * @entry: the element to delete from the list. + */ +static void list_del_init(struct list_head *entry) +{ + __list_del_entry(entry); + INIT_LIST_HEAD(entry); +} + +/** + * list_move - delete from one list and add as another's head + * @list: the entry to move + * @head: the head that will precede our entry + */ +static void list_move(struct list_head *list, + struct list_head *head) +{ + __list_del_entry(list); + list_add(list, head); +} + +/** + * list_move_tail - delete from one list and add as another's tail + * @list: the entry to move + * @head: the head that will follow our entry + */ +static void list_move_tail(struct list_head *list, + struct list_head *head) +{ + __list_del_entry(list); + list_add_tail(list, head); +} + +/** + * list_is_last - tests whether @list is the last entry in list @head + * @list: the entry to test + * @head: the head of the list + */ +static int list_is_last(const struct list_head *list, + const struct list_head *head) +{ + return list->next == head; +} + +/** + * list_empty - tests whether a list is empty + * @head: the list to test. + */ +static int list_empty(const struct list_head *head) +{ + return (head->next == NULL) || (head->next == head); +} + +/** + * list_empty_careful - tests whether a list is empty and not being modified + * @head: the list to test + * + * Description: + * tests whether a list is empty _and_ checks that no other CPU might be + * in the process of modifying either member (next or prev) + * + * NOTE: using list_empty_careful() without synchronization + * can only be safe if the only activity that can happen + * to the list entry is list_del_init(). Eg. it cannot be used + * if another CPU could re-list_add() it. + */ +static int list_empty_careful(const struct list_head *head) +{ + struct list_head *next = head->next; + return (next == head) && (next == head->prev); +} + +/** + * list_rotate_left - rotate the list to the left + * @head: the head of the list + */ +static void list_rotate_left(struct list_head *head) +{ + struct list_head *first; + + if (!list_empty(head)) { + first = head->next; + list_move_tail(first, head); + } +} + +/** + * list_is_singular - tests whether a list has just one entry. + * @head: the list to test. + */ +static int list_is_singular(const struct list_head *head) +{ + return !list_empty(head) && (head->next == head->prev); +} + +static void __list_cut_position(struct list_head *list, + struct list_head *head, + struct list_head *entry) +{ + struct list_head *new_first = entry->next; + list->next = head->next; + list->next->prev = list; + list->prev = entry; + entry->next = list; + head->next = new_first; + new_first->prev = head; +} + +/** + * list_cut_position - cut a list into two + * @list: a new list to add all removed entries + * @head: a list with entries + * @entry: an entry within head, could be the head itself + * and if so we won't cut the list + * + * This helper moves the initial part of @head, up to and + * including @entry, from @head to @list. You should + * pass on @entry an element you know is on @head. @list + * should be an empty list or a list you do not care about + * losing its data. + */ +static void list_cut_position(struct list_head *list, + struct list_head *head, + struct list_head *entry) +{ + if (list_empty(head)) + return; + if (list_is_singular(head) && + (head->next != entry && head != entry)) + return; + if (entry == head) + INIT_LIST_HEAD(list); + else + __list_cut_position(list, head, entry); +} + +static void __list_splice(const struct list_head *list, + struct list_head *prev, + struct list_head *next) +{ + struct list_head *first = list->next; + struct list_head *last = list->prev; + + first->prev = prev; + prev->next = first; + + last->next = next; + next->prev = last; +} + +/** + * list_splice - join two lists, this is designed for stacks + * @list: the new list to add. + * @head: the place to add it in the first list. + */ +static void list_splice(const struct list_head *list, + struct list_head *head) +{ + if (!list_empty(list)) + __list_splice(list, head, head->next); +} + +/** + * list_splice_tail - join two lists, each list being a queue + * @list: the new list to add. + * @head: the place to add it in the first list. + */ +static void list_splice_tail(struct list_head *list, + struct list_head *head) +{ + if (!list_empty(list)) + __list_splice(list, head->prev, head); +} + +/** + * list_splice_init - join two lists and reinitialise the emptied list. + * @list: the new list to add. + * @head: the place to add it in the first list. + * + * The list at @list is reinitialised + */ +static void list_splice_init(struct list_head *list, + struct list_head *head) +{ + if (!list_empty(list)) { + __list_splice(list, head, head->next); + INIT_LIST_HEAD(list); + } +} + +/** + * list_splice_tail_init - join two lists and reinitialise the emptied list + * @list: the new list to add. + * @head: the place to add it in the first list. + * + * Each of the lists is a queue. + * The list at @list is reinitialised + */ +static void list_splice_tail_init(struct list_head *list, + struct list_head *head) +{ + if (!list_empty(list)) { + __list_splice(list, head->prev, head); + INIT_LIST_HEAD(list); + } +} + +/** + * list_entry - get the struct for this entry + * @ptr: the &struct list_head pointer. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_struct within the struct. + */ +#define list_entry(ptr, type, member) \ + containerof(ptr, type, member) + +/** + * list_first_entry - get the first element from a list + * @ptr: the list head to take the element from. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_struct within the struct. + * + * Note, that list is expected to be not empty. + */ +#define list_first_entry(ptr, type, member) \ + list_entry((ptr)->next, type, member) + +/** + * list_for_each - iterate over a list + * @pos: the &struct list_head to use as a loop cursor. + * @head: the head for your list. + */ +#define list_for_each(pos, head) \ + for (pos = (head)->next; pos != (head); pos = pos->next) + +/** + * __list_for_each - iterate over a list + * @pos: the &struct list_head to use as a loop cursor. + * @head: the head for your list. + * + * This variant doesn't differ from list_for_each() any more. + * We don't do prefetching in either case. + */ +#define __list_for_each(pos, head) \ + for (pos = (head)->next; pos != (head); pos = pos->next) + +/** + * list_for_each_prev - iterate over a list backwards + * @pos: the &struct list_head to use as a loop cursor. + * @head: the head for your list. + */ +#define list_for_each_prev(pos, head) \ + for (pos = (head)->prev; pos != (head); pos = pos->prev) + +/** + * list_for_each_safe - iterate over a list safe against removal of list entry + * @pos: the &struct list_head to use as a loop cursor. + * @n: another &struct list_head to use as temporary storage + * @head: the head for your list. + */ +#define list_for_each_safe(pos, n, head) \ + for (pos = (head)->next, n = pos->next; pos != (head); \ + pos = n, n = pos->next) + +/** + * list_for_each_prev_safe - iterate over a list backwards safe against removal + * of list entry + * @pos: the &struct list_head to use as a loop cursor. + * @n: another &struct list_head to use as temporary storage + * @head: the head for your list. + */ +#define list_for_each_prev_safe(pos, n, head) \ + for (pos = (head)->prev, n = pos->prev; \ + pos != (head); \ + pos = n, n = pos->prev) + +/** + * list_for_each_entry - iterate over list of given type + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry(pos, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member)) + +/** + * list_for_each_entry_reverse - iterate backwards over list of given type. + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry_reverse(pos, head, member) \ + for (pos = list_entry((head)->prev, typeof(*pos), member); \ + &pos->member != (head); \ + pos = list_entry(pos->member.prev, typeof(*pos), member)) + +/** + * list_prepare_entry - prepare a pos entry for use in + * list_for_each_entry_continue() + * @pos: the type * to use as a start point + * @head: the head of the list + * @member: the name of the list_struct within the struct. + * + * Prepares a pos entry for use as a start point in + * list_for_each_entry_continue(). + */ +#define list_prepare_entry(pos, head, member) \ + ((pos) ? : list_entry(head, typeof(*pos), member)) + +/** + * list_for_each_entry_continue - continue iteration over list of given type + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + * + * Continue to iterate over list of given type, continuing after + * the current position. + */ + #define list_for_each_entry_continue(pos, head, member) \ + for (pos = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member)) + +/** + * list_for_each_entry_continue_reverse - iterate backwards from the given point + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + * + * Start to iterate over list of given type backwards, continuing after + * the current position. + */ +#define list_for_each_entry_continue_reverse(pos, head, member) \ + for (pos = list_entry(pos->member.prev, typeof(*pos), member); \ + &pos->member != (head); \ + pos = list_entry(pos->member.prev, typeof(*pos), member)) + +/** + * list_for_each_entry_from - iterate over list of given type from the current + * point + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + * + * Iterate over list of given type, continuing from current position. + */ +#define list_for_each_entry_from(pos, head, member) \ + for (; &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member)) + +/** + * list_for_each_entry_safe - iterate over list of given type safe against + * removal of list entry + * @pos: the type * to use as a loop cursor. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry_safe(pos, n, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member), \ + n = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.next, typeof(*n), member)) + +/** + * list_for_each_entry_safe_continue - continue list iteration safe against + * removal + * @pos: the type * to use as a loop cursor. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + * + * Iterate over list of given type, continuing after current point, + * safe against removal of list entry. + */ +#define list_for_each_entry_safe_continue(pos, n, head, member) \ + for (pos = list_entry(pos->member.next, typeof(*pos), member), \ + n = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.next, typeof(*n), member)) + +/** + * list_for_each_entry_safe_from - iterate over list from current point + * safe against removal + * @pos: the type * to use as a loop cursor. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + * + * Iterate over list of given type from current point, safe against + * removal of list entry. + */ +#define list_for_each_entry_safe_from(pos, n, head, member) \ + for (n = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.next, typeof(*n), member)) + +/** + * list_for_each_entry_safe_reverse - iterate backwards over list safe + * against removal + * @pos: the type * to use as a loop cursor. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + * + * Iterate backwards over list of given type, safe against removal + * of list entry. + */ +#define list_for_each_entry_safe_reverse(pos, n, head, member) \ + for (pos = list_entry((head)->prev, typeof(*pos), member), \ + n = list_entry(pos->member.prev, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.prev, typeof(*n), member)) + +/** + * list_safe_reset_next - reset a stale list_for_each_entry_safe loop + * @pos: the loop cursor used in the list_for_each_entry_safe loop + * @n: temporary storage used in list_for_each_entry_safe + * @member: the name of the list_struct within the struct. + * + * list_safe_reset_next is not safe to use in general if the list may be + * modified concurrently (eg. the lock is dropped in the loop body). An + * exception to this is if the cursor element (pos) is pinned in the list, + * and list_safe_reset_next is called after re-taking the lock and before + * completing the current iteration of the loop body. + */ +#define list_safe_reset_next(pos, n, member) \ + n = list_entry(pos->member.next, typeof(*pos), member) + +#ifdef __cplusplus +} +#endif +#endif diff --git a/gcbv/gcreg.h b/gcbv/mirror/include/gcreg.h index 803cfb6..9aa128f 100644 --- a/gcbv/gcreg.h +++ b/gcbv/mirror/include/gcreg.h @@ -1,28 +1,61 @@ /* - * Copyright (c) 2011, Vivante Corporation. + * 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, + * Texas Instruments, Inc. and 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, + * Texas Instruments, Inc. and Vivante Corporation. + * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Vivante Corporation nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. + * + * * 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 VIVANTE CORPORATON 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. + * 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 __gcreg_h @@ -32,54 +65,52 @@ ** Register access macros. */ -#define __GCSTART(reg_field) \ +#define GCREGSTART(reg_field) \ ( \ 0 ? reg_field \ ) -#define __GCEND(reg_field) \ +#define GCREGEND(reg_field) \ ( \ 1 ? reg_field \ ) -#define __GCGETSIZE(reg_field) \ +#define GCREGSIZE(reg_field) \ ( \ - __GCEND(reg_field) - __GCSTART(reg_field) + 1 \ + GCREGEND(reg_field) - GCREGSTART(reg_field) + 1 \ ) -#define __GCALIGN(data, reg_field) \ +#define GCREGALIGN(data, reg_field) \ ( \ - ((unsigned int) (data)) << __GCSTART(reg_field) \ + ((unsigned int) (data)) << GCREGSTART(reg_field) \ ) -#define __GCMASK(reg_field) \ - ((__GCGETSIZE(reg_field) == 32) \ - ? ~0U \ - : (unsigned int) (~(~0UL << __GCGETSIZE(reg_field)))) +#define GCREGMASK(reg_field) \ +( \ + GCREGALIGN(~0UL >> (32 - GCREGSIZE(reg_field)), reg_field) \ +) -#define SETFIELDVAL(data, reg, field, value) \ +#define GCSETFIELDVAL(data, reg, field, value) \ ( \ - (((unsigned int) (data)) \ - & ~__GCALIGN(__GCMASK(reg##_##field), reg##_##field)) \ - | __GCALIGN(reg##_##field##_##value \ - & __GCMASK(reg##_##field), reg##_##field) \ + (((unsigned int) (data)) & ~GCREGMASK(reg##_##field)) \ + | (GCREGALIGN(reg##_##field##_##value, reg##_##field) \ + & GCREGMASK(reg##_##field)) \ ) -#define SETFIELD(data, reg, field, value) \ +#define GCSETFIELD(data, reg, field, value) \ ( \ - (((unsigned int) (data)) \ - & ~__GCALIGN(__GCMASK(reg##_##field), reg##_##field)) \ - | __GCALIGN((unsigned int) (value) \ - & __GCMASK(reg##_##field), reg##_##field) \ + (((unsigned int) (data)) & ~GCREGMASK(reg##_##field)) \ + | (GCREGALIGN((unsigned int) (value), reg##_##field) \ + & GCREGMASK(reg##_##field)) \ ) -#define GETFIELD(data, reg, field) \ +#define GCGETFIELD(data, reg, field) \ ( \ - ((((unsigned int) (data)) >> __GCSTART(reg##_##field)) \ - & __GCMASK(reg##_##field)) \ + (((unsigned int) (data)) & GCREGMASK(reg##_##field)) \ + >> GCREGSTART(reg##_##field) \ ) -#define REGVALUE(reg, field, val) \ +#define GCREGVALUE(reg, field, val) \ ( \ reg##_##field##_##val \ ) @@ -1456,6 +1487,339 @@ union gcidle { #define GC_TOTAL_READ_LASTS_COUNT_Type U32 /******************************************************************************* +** Register gcGpOut0 +*/ + +/* General Purpose output register0. R/W but not connected to anywhere. */ + +#define GC_GP_OUT0_Address 0x00064 +#define GC_GP_OUT0_MSB 15 +#define GC_GP_OUT0_LSB 0 +#define GC_GP_OUT0_BLK 0 +#define GC_GP_OUT0_Count 1 +#define GC_GP_OUT0_FieldMask 0xFFFFFFFF +#define GC_GP_OUT0_ReadMask 0xFFFFFFFF +#define GC_GP_OUT0_WriteMask 0xFFFFFFFF +#define GC_GP_OUT0_ResetValue 0x00000000 + +#define GC_GP_OUT0_COUNT 31 : 0 +#define GC_GP_OUT0_COUNT_End 31 +#define GC_GP_OUT0_COUNT_Start 0 +#define GC_GP_OUT0_COUNT_Type U32 + +/******************************************************************************* +** Register gcGpOut1 +*/ + +/* General Purpose output register1. R/W but not connected to anywhere. */ + +#define GC_GP_OUT1_Address 0x00068 +#define GC_GP_OUT1_MSB 15 +#define GC_GP_OUT1_LSB 0 +#define GC_GP_OUT1_BLK 0 +#define GC_GP_OUT1_Count 1 +#define GC_GP_OUT1_FieldMask 0xFFFFFFFF +#define GC_GP_OUT1_ReadMask 0xFFFFFFFF +#define GC_GP_OUT1_WriteMask 0xFFFFFFFF +#define GC_GP_OUT1_ResetValue 0x00000000 + +#define GC_GP_OUT1_COUNT 31 : 0 +#define GC_GP_OUT1_COUNT_End 31 +#define GC_GP_OUT1_COUNT_Start 0 +#define GC_GP_OUT1_COUNT_Type U32 + +/******************************************************************************* +** Register gcGpOut2 +*/ + +/* General Purpose output register2. R/W but not connected to anywhere. */ + +#define GC_GP_OUT2_Address 0x0006C +#define GC_GP_OUT2_MSB 15 +#define GC_GP_OUT2_LSB 0 +#define GC_GP_OUT2_BLK 0 +#define GC_GP_OUT2_Count 1 +#define GC_GP_OUT2_FieldMask 0xFFFFFFFF +#define GC_GP_OUT2_ReadMask 0xFFFFFFFF +#define GC_GP_OUT2_WriteMask 0xFFFFFFFF +#define GC_GP_OUT2_ResetValue 0x00000000 + +#define GC_GP_OUT2_COUNT 31 : 0 +#define GC_GP_OUT2_COUNT_End 31 +#define GC_GP_OUT2_COUNT_Start 0 +#define GC_GP_OUT2_COUNT_Type U32 + +/******************************************************************************* +** Register gcAxiControl +*/ + +/* Special Handling on AXI Bus */ + +#define GC_AXI_CONTROL_Address 0x00070 +#define GC_AXI_CONTROL_MSB 15 +#define GC_AXI_CONTROL_LSB 0 +#define GC_AXI_CONTROL_BLK 0 +#define GC_AXI_CONTROL_Count 1 +#define GC_AXI_CONTROL_FieldMask 0x00000001 +#define GC_AXI_CONTROL_ReadMask 0x00000001 +#define GC_AXI_CONTROL_WriteMask 0x00000001 +#define GC_AXI_CONTROL_ResetValue 0x00000000 + +#define GC_AXI_CONTROL_WR_FULL_BURST_MODE 0 : 0 +#define GC_AXI_CONTROL_WR_FULL_BURST_MODE_End 0 +#define GC_AXI_CONTROL_WR_FULL_BURST_MODE_Start 0 +#define GC_AXI_CONTROL_WR_FULL_BURST_MODE_Type U01 +#define GC_AXI_CONTROL_WR_FULL_BURST_MODE_NO_BURST_RESET_VALUE 0x0 +#define GC_AXI_CONTROL_WR_FULL_BURST_MODE_BURST_RESET_VALUE 0x1 + +/******************************************************************************* +** Register GCMinorFeatures1 +*/ + +/* Shows which features are enabled in this chip. This register has no set + reset value. It varies with the implementation. */ + +#define GC_MINOR_FEATURES1_Address 0x00074 +#define GC_MINOR_FEATURES1_MSB 15 +#define GC_MINOR_FEATURES1_LSB 0 +#define GC_MINOR_FEATURES1_BLK 0 +#define GC_MINOR_FEATURES1_Count 1 +#define GC_MINOR_FEATURES1_FieldMask 0xFFFFFFFF +#define GC_MINOR_FEATURES1_ReadMask 0xFFFFFFFF +#define GC_MINOR_FEATURES1_WriteMask 0x00000000 +#define GC_MINOR_FEATURES1_ResetValue 0x00000000 + +/* Resolve UV swizzle. */ +#define GC_MINOR_FEATURES1_RSUV_SWIZZLE 0 : 0 +#define GC_MINOR_FEATURES1_RSUV_SWIZZLE_End 0 +#define GC_MINOR_FEATURES1_RSUV_SWIZZLE_Start 0 +#define GC_MINOR_FEATURES1_RSUV_SWIZZLE_Type U01 +#define GC_MINOR_FEATURES1_RSUV_SWIZZLE_NONE 0x0 +#define GC_MINOR_FEATURES1_RSUV_SWIZZLE_AVAILABLE 0x1 + +/* V2 compression. */ +#define GC_MINOR_FEATURES1_V2_COMPRESSION 1 : 1 +#define GC_MINOR_FEATURES1_V2_COMPRESSION_End 1 +#define GC_MINOR_FEATURES1_V2_COMPRESSION_Start 1 +#define GC_MINOR_FEATURES1_V2_COMPRESSION_Type U01 +#define GC_MINOR_FEATURES1_V2_COMPRESSION_NONE 0x0 +#define GC_MINOR_FEATURES1_V2_COMPRESSION_AVAILABLE 0x1 + +/* Double buffering support for VG (second TS-->VG semaphore is present). */ +#define GC_MINOR_FEATURES1_VG_DOUBLE_BUFFER 2 : 2 +#define GC_MINOR_FEATURES1_VG_DOUBLE_BUFFER_End 2 +#define GC_MINOR_FEATURES1_VG_DOUBLE_BUFFER_Start 2 +#define GC_MINOR_FEATURES1_VG_DOUBLE_BUFFER_Type U01 +#define GC_MINOR_FEATURES1_VG_DOUBLE_BUFFER_NONE 0x0 +#define GC_MINOR_FEATURES1_VG_DOUBLE_BUFFER_AVAILABLE 0x1 + +#define GC_MINOR_FEATURES1_BUG_FIXES1 3 : 3 +#define GC_MINOR_FEATURES1_BUG_FIXES1_End 3 +#define GC_MINOR_FEATURES1_BUG_FIXES1_Start 3 +#define GC_MINOR_FEATURES1_BUG_FIXES1_Type U01 +#define GC_MINOR_FEATURES1_BUG_FIXES1_NONE 0x0 +#define GC_MINOR_FEATURES1_BUG_FIXES1_AVAILABLE 0x1 + +#define GC_MINOR_FEATURES1_BUG_FIXES2 4 : 4 +#define GC_MINOR_FEATURES1_BUG_FIXES2_End 4 +#define GC_MINOR_FEATURES1_BUG_FIXES2_Start 4 +#define GC_MINOR_FEATURES1_BUG_FIXES2_Type U01 +#define GC_MINOR_FEATURES1_BUG_FIXES2_NONE 0x0 +#define GC_MINOR_FEATURES1_BUG_FIXES2_AVAILABLE 0x1 + +/* Texture has stride and memory addressing. */ +#define GC_MINOR_FEATURES1_TEXTURE_STRIDE 5 : 5 +#define GC_MINOR_FEATURES1_TEXTURE_STRIDE_End 5 +#define GC_MINOR_FEATURES1_TEXTURE_STRIDE_Start 5 +#define GC_MINOR_FEATURES1_TEXTURE_STRIDE_Type U01 +#define GC_MINOR_FEATURES1_TEXTURE_STRIDE_NONE 0x0 +#define GC_MINOR_FEATURES1_TEXTURE_STRIDE_AVAILABLE 0x1 + +#define GC_MINOR_FEATURES1_BUG_FIXES3 6 : 6 +#define GC_MINOR_FEATURES1_BUG_FIXES3_End 6 +#define GC_MINOR_FEATURES1_BUG_FIXES3_Start 6 +#define GC_MINOR_FEATURES1_BUG_FIXES3_Type U01 +#define GC_MINOR_FEATURES1_BUG_FIXES3_NONE 0x0 +#define GC_MINOR_FEATURES1_BUG_FIXES3_AVAILABLE 0x1 + +#define GC_MINOR_FEATURES1_CORRECT_AUTO_DISABLE 7 : 7 +#define GC_MINOR_FEATURES1_CORRECT_AUTO_DISABLE_End 7 +#define GC_MINOR_FEATURES1_CORRECT_AUTO_DISABLE_Start 7 +#define GC_MINOR_FEATURES1_CORRECT_AUTO_DISABLE_Type U01 +#define GC_MINOR_FEATURES1_CORRECT_AUTO_DISABLE_NONE 0x0 +#define GC_MINOR_FEATURES1_CORRECT_AUTO_DISABLE_AVAILABLE 0x1 + +#define GC_MINOR_FEATURES1_AUTO_RESTART_TS 8 : 8 +#define GC_MINOR_FEATURES1_AUTO_RESTART_TS_End 8 +#define GC_MINOR_FEATURES1_AUTO_RESTART_TS_Start 8 +#define GC_MINOR_FEATURES1_AUTO_RESTART_TS_Type U01 +#define GC_MINOR_FEATURES1_AUTO_RESTART_TS_NONE 0x0 +#define GC_MINOR_FEATURES1_AUTO_RESTART_TS_AVAILABLE 0x1 + +#define GC_MINOR_FEATURES1_BUG_FIXES4 9 : 9 +#define GC_MINOR_FEATURES1_BUG_FIXES4_End 9 +#define GC_MINOR_FEATURES1_BUG_FIXES4_Start 9 +#define GC_MINOR_FEATURES1_BUG_FIXES4_Type U01 +#define GC_MINOR_FEATURES1_BUG_FIXES4_NONE 0x0 +#define GC_MINOR_FEATURES1_BUG_FIXES4_AVAILABLE 0x1 + +#define GC_MINOR_FEATURES1_L2_WINDOWING 10 : 10 +#define GC_MINOR_FEATURES1_L2_WINDOWING_End 10 +#define GC_MINOR_FEATURES1_L2_WINDOWING_Start 10 +#define GC_MINOR_FEATURES1_L2_WINDOWING_Type U01 +#define GC_MINOR_FEATURES1_L2_WINDOWING_NONE 0x0 +#define GC_MINOR_FEATURES1_L2_WINDOWING_AVAILABLE 0x1 + +#define GC_MINOR_FEATURES1_HALF_FLOAT_PIPE 11 : 11 +#define GC_MINOR_FEATURES1_HALF_FLOAT_PIPE_End 11 +#define GC_MINOR_FEATURES1_HALF_FLOAT_PIPE_Start 11 +#define GC_MINOR_FEATURES1_HALF_FLOAT_PIPE_Type U01 +#define GC_MINOR_FEATURES1_HALF_FLOAT_PIPE_NONE 0x0 +#define GC_MINOR_FEATURES1_HALF_FLOAT_PIPE_AVAILABLE 0x1 + +#define GC_MINOR_FEATURES1_PIXEL_DITHER 12 : 12 +#define GC_MINOR_FEATURES1_PIXEL_DITHER_End 12 +#define GC_MINOR_FEATURES1_PIXEL_DITHER_Start 12 +#define GC_MINOR_FEATURES1_PIXEL_DITHER_Type U01 +#define GC_MINOR_FEATURES1_PIXEL_DITHER_NONE 0x0 +#define GC_MINOR_FEATURES1_PIXEL_DITHER_AVAILABLE 0x1 + +#define GC_MINOR_FEATURES1_TWO_STENCIL_REFERENCE 13 : 13 +#define GC_MINOR_FEATURES1_TWO_STENCIL_REFERENCE_End 13 +#define GC_MINOR_FEATURES1_TWO_STENCIL_REFERENCE_Start 13 +#define GC_MINOR_FEATURES1_TWO_STENCIL_REFERENCE_Type U01 +#define GC_MINOR_FEATURES1_TWO_STENCIL_REFERENCE_NONE 0x0 +#define GC_MINOR_FEATURES1_TWO_STENCIL_REFERENCE_AVAILABLE 0x1 + +#define GC_MINOR_FEATURES1_EXTENDED_PIXEL_FORMAT 14 : 14 +#define GC_MINOR_FEATURES1_EXTENDED_PIXEL_FORMAT_End 14 +#define GC_MINOR_FEATURES1_EXTENDED_PIXEL_FORMAT_Start 14 +#define GC_MINOR_FEATURES1_EXTENDED_PIXEL_FORMAT_Type U01 +#define GC_MINOR_FEATURES1_EXTENDED_PIXEL_FORMAT_NONE 0x0 +#define GC_MINOR_FEATURES1_EXTENDED_PIXEL_FORMAT_AVAILABLE 0x1 + +/* EEZ and HZ are correct. */ +#define GC_MINOR_FEATURES1_CORRECT_MIN_MAX_DEPTH 15 : 15 +#define GC_MINOR_FEATURES1_CORRECT_MIN_MAX_DEPTH_End 15 +#define GC_MINOR_FEATURES1_CORRECT_MIN_MAX_DEPTH_Start 15 +#define GC_MINOR_FEATURES1_CORRECT_MIN_MAX_DEPTH_Type U01 +#define GC_MINOR_FEATURES1_CORRECT_MIN_MAX_DEPTH_NONE 0x0 +#define GC_MINOR_FEATURES1_CORRECT_MIN_MAX_DEPTH_AVAILABLE 0x1 + +/* Dither and filter+alpha available. */ +#define GC_MINOR_FEATURES1_DITHER_AND_FILTER_PLUS_ALPHA_2D 16 : 16 +#define GC_MINOR_FEATURES1_DITHER_AND_FILTER_PLUS_ALPHA_2D_End 16 +#define GC_MINOR_FEATURES1_DITHER_AND_FILTER_PLUS_ALPHA_2D_Start 16 +#define GC_MINOR_FEATURES1_DITHER_AND_FILTER_PLUS_ALPHA_2D_Type U01 +#define GC_MINOR_FEATURES1_DITHER_AND_FILTER_PLUS_ALPHA_2D_NONE 0x0 +#define GC_MINOR_FEATURES1_DITHER_AND_FILTER_PLUS_ALPHA_2D_AVAILABLE 0x1 + +#define GC_MINOR_FEATURES1_BUG_FIXES5 17 : 17 +#define GC_MINOR_FEATURES1_BUG_FIXES5_End 17 +#define GC_MINOR_FEATURES1_BUG_FIXES5_Start 17 +#define GC_MINOR_FEATURES1_BUG_FIXES5_Type U01 +#define GC_MINOR_FEATURES1_BUG_FIXES5_NONE 0x0 +#define GC_MINOR_FEATURES1_BUG_FIXES5_AVAILABLE 0x1 + +#define GC_MINOR_FEATURES1_NEW_2D 18 : 18 +#define GC_MINOR_FEATURES1_NEW_2D_End 18 +#define GC_MINOR_FEATURES1_NEW_2D_Start 18 +#define GC_MINOR_FEATURES1_NEW_2D_Type U01 +#define GC_MINOR_FEATURES1_NEW_2D_NONE 0x0 +#define GC_MINOR_FEATURES1_NEW_2D_AVAILABLE 0x1 + +#define GC_MINOR_FEATURES1_NEW_FLOATING_POINT_ARITHMETIC 19 : 19 +#define GC_MINOR_FEATURES1_NEW_FLOATING_POINT_ARITHMETIC_End 19 +#define GC_MINOR_FEATURES1_NEW_FLOATING_POINT_ARITHMETIC_Start 19 +#define GC_MINOR_FEATURES1_NEW_FLOATING_POINT_ARITHMETIC_Type U01 +#define GC_MINOR_FEATURES1_NEW_FLOATING_POINT_ARITHMETIC_NONE 0x0 +#define GC_MINOR_FEATURES1_NEW_FLOATING_POINT_ARITHMETIC_AVAILABLE 0x1 + +#define GC_MINOR_FEATURES1_TEXTURE_HORIZONTAL_ALIGNMENT_SELECT 20 : 20 +#define GC_MINOR_FEATURES1_TEXTURE_HORIZONTAL_ALIGNMENT_SELECT_End 20 +#define GC_MINOR_FEATURES1_TEXTURE_HORIZONTAL_ALIGNMENT_SELECT_Start 20 +#define GC_MINOR_FEATURES1_TEXTURE_HORIZONTAL_ALIGNMENT_SELECT_Type U01 +#define GC_MINOR_FEATURES1_TEXTURE_HORIZONTAL_ALIGNMENT_SELECT_NONE 0x0 +#define GC_MINOR_FEATURES1_TEXTURE_HORIZONTAL_ALIGNMENT_SELECT_AVAILABLE 0x1 + +#define GC_MINOR_FEATURES1_NON_POWER_OF_TWO 21 : 21 +#define GC_MINOR_FEATURES1_NON_POWER_OF_TWO_End 21 +#define GC_MINOR_FEATURES1_NON_POWER_OF_TWO_Start 21 +#define GC_MINOR_FEATURES1_NON_POWER_OF_TWO_Type U01 +#define GC_MINOR_FEATURES1_NON_POWER_OF_TWO_NONE 0x0 +#define GC_MINOR_FEATURES1_NON_POWER_OF_TWO_AVAILABLE 0x1 + +#define GC_MINOR_FEATURES1_LINEAR_TEXTURE_SUPPORT 22 : 22 +#define GC_MINOR_FEATURES1_LINEAR_TEXTURE_SUPPORT_End 22 +#define GC_MINOR_FEATURES1_LINEAR_TEXTURE_SUPPORT_Start 22 +#define GC_MINOR_FEATURES1_LINEAR_TEXTURE_SUPPORT_Type U01 +#define GC_MINOR_FEATURES1_LINEAR_TEXTURE_SUPPORT_NONE 0x0 +#define GC_MINOR_FEATURES1_LINEAR_TEXTURE_SUPPORT_AVAILABLE 0x1 + +#define GC_MINOR_FEATURES1_HALTI0 23 : 23 +#define GC_MINOR_FEATURES1_HALTI0_End 23 +#define GC_MINOR_FEATURES1_HALTI0_Start 23 +#define GC_MINOR_FEATURES1_HALTI0_Type U01 +#define GC_MINOR_FEATURES1_HALTI0_NONE 0x0 +#define GC_MINOR_FEATURES1_HALTI0_AVAILABLE 0x1 + +#define GC_MINOR_FEATURES1_CORRECT_OVERFLOW_VG 24 : 24 +#define GC_MINOR_FEATURES1_CORRECT_OVERFLOW_VG_End 24 +#define GC_MINOR_FEATURES1_CORRECT_OVERFLOW_VG_Start 24 +#define GC_MINOR_FEATURES1_CORRECT_OVERFLOW_VG_Type U01 +#define GC_MINOR_FEATURES1_CORRECT_OVERFLOW_VG_NONE 0x0 +#define GC_MINOR_FEATURES1_CORRECT_OVERFLOW_VG_AVAILABLE 0x1 + +#define GC_MINOR_FEATURES1_NEGATIVE_LOG_FIX 25 : 25 +#define GC_MINOR_FEATURES1_NEGATIVE_LOG_FIX_End 25 +#define GC_MINOR_FEATURES1_NEGATIVE_LOG_FIX_Start 25 +#define GC_MINOR_FEATURES1_NEGATIVE_LOG_FIX_Type U01 +#define GC_MINOR_FEATURES1_NEGATIVE_LOG_FIX_NONE 0x0 +#define GC_MINOR_FEATURES1_NEGATIVE_LOG_FIX_AVAILABLE 0x1 + +#define GC_MINOR_FEATURES1_RESOLVE_OFFSET 26 : 26 +#define GC_MINOR_FEATURES1_RESOLVE_OFFSET_End 26 +#define GC_MINOR_FEATURES1_RESOLVE_OFFSET_Start 26 +#define GC_MINOR_FEATURES1_RESOLVE_OFFSET_Type U01 +#define GC_MINOR_FEATURES1_RESOLVE_OFFSET_NONE 0x0 +#define GC_MINOR_FEATURES1_RESOLVE_OFFSET_AVAILABLE 0x1 + +#define GC_MINOR_FEATURES1_OK_TO_GATE_AXI_CLOCK 27 : 27 +#define GC_MINOR_FEATURES1_OK_TO_GATE_AXI_CLOCK_End 27 +#define GC_MINOR_FEATURES1_OK_TO_GATE_AXI_CLOCK_Start 27 +#define GC_MINOR_FEATURES1_OK_TO_GATE_AXI_CLOCK_Type U01 +#define GC_MINOR_FEATURES1_OK_TO_GATE_AXI_CLOCK_NONE 0x0 +#define GC_MINOR_FEATURES1_OK_TO_GATE_AXI_CLOCK_AVAILABLE 0x1 + +#define GC_MINOR_FEATURES1_MMU 28 : 28 +#define GC_MINOR_FEATURES1_MMU_End 28 +#define GC_MINOR_FEATURES1_MMU_Start 28 +#define GC_MINOR_FEATURES1_MMU_Type U01 +#define GC_MINOR_FEATURES1_MMU_NONE 0x0 +#define GC_MINOR_FEATURES1_MMU_AVAILABLE 0x1 + +#define GC_MINOR_FEATURES1_WIDE_LINE 29 : 29 +#define GC_MINOR_FEATURES1_WIDE_LINE_End 29 +#define GC_MINOR_FEATURES1_WIDE_LINE_Start 29 +#define GC_MINOR_FEATURES1_WIDE_LINE_Type U01 +#define GC_MINOR_FEATURES1_WIDE_LINE_NONE 0x0 +#define GC_MINOR_FEATURES1_WIDE_LINE_AVAILABLE 0x1 + +#define GC_MINOR_FEATURES1_BUG_FIXES6 30 : 30 +#define GC_MINOR_FEATURES1_BUG_FIXES6_End 30 +#define GC_MINOR_FEATURES1_BUG_FIXES6_Start 30 +#define GC_MINOR_FEATURES1_BUG_FIXES6_Type U01 +#define GC_MINOR_FEATURES1_BUG_FIXES6_NONE 0x0 +#define GC_MINOR_FEATURES1_BUG_FIXES6_AVAILABLE 0x1 + +#define GC_MINOR_FEATURES1_FC_FLUSH_STALL 31 : 31 +#define GC_MINOR_FEATURES1_FC_FLUSH_STALL_End 31 +#define GC_MINOR_FEATURES1_FC_FLUSH_STALL_Start 31 +#define GC_MINOR_FEATURES1_FC_FLUSH_STALL_Type U01 +#define GC_MINOR_FEATURES1_FC_FLUSH_STALL_NONE 0x0 +#define GC_MINOR_FEATURES1_FC_FLUSH_STALL_AVAILABLE 0x1 + +/******************************************************************************* ** Register gcTotalCycles */ @@ -1503,62 +1867,75 @@ union gcidle { #define GC_TOTAL_IDLE_CYCLES_CYCLES_Type U32 /******************************************************************************* +** Command opcodes. +*/ + +#define GCREG_COMMAND_OPCODE_LOAD_STATE 0x01 +#define GCREG_COMMAND_OPCODE_END 0x02 +#define GCREG_COMMAND_OPCODE_NOP 0x03 +#define GCREG_COMMAND_OPCODE_STARTDE 0x04 +#define GCREG_COMMAND_OPCODE_WAIT 0x07 +#define GCREG_COMMAND_OPCODE_LINK 0x08 +#define GCREG_COMMAND_OPCODE_STALL 0x09 +#define GCREG_COMMAND_OPCODE_CALL 0x0A +#define GCREG_COMMAND_OPCODE_RETURN 0x0B + +/******************************************************************************* ** Command gcregCommandLoadState */ /* When enabled, convert 16.16 fixed point into 32-bit floating point. */ -#define GCREG_COMMAND_LOAD_STATE_COMMAND_FLOAT 26 : 26 -#define GCREG_COMMAND_LOAD_STATE_COMMAND_FLOAT_End 26 -#define GCREG_COMMAND_LOAD_STATE_COMMAND_FLOAT_Start 26 -#define GCREG_COMMAND_LOAD_STATE_COMMAND_FLOAT_Type U01 -#define GCREG_COMMAND_LOAD_STATE_COMMAND_FLOAT_NORMAL 0x0 -#define GCREG_COMMAND_LOAD_STATE_COMMAND_FLOAT_FIXED16_DOT16 0x1 +#define GCREG_COMMAND_LOAD_STATE_FLOAT 26 : 26 +#define GCREG_COMMAND_LOAD_STATE_FLOAT_End 26 +#define GCREG_COMMAND_LOAD_STATE_FLOAT_Start 26 +#define GCREG_COMMAND_LOAD_STATE_FLOAT_Type U01 +#define GCREG_COMMAND_LOAD_STATE_FLOAT_NORMAL 0x0 +#define GCREG_COMMAND_LOAD_STATE_FLOAT_FIXED16_DOT16 0x1 /* Number of states. 0 = 1024. */ -#define GCREG_COMMAND_LOAD_STATE_COMMAND_COUNT 25 : 16 -#define GCREG_COMMAND_LOAD_STATE_COMMAND_COUNT_End 25 -#define GCREG_COMMAND_LOAD_STATE_COMMAND_COUNT_Start 16 -#define GCREG_COMMAND_LOAD_STATE_COMMAND_COUNT_Type U10 +#define GCREG_COMMAND_LOAD_STATE_COUNT 25 : 16 +#define GCREG_COMMAND_LOAD_STATE_COUNT_End 25 +#define GCREG_COMMAND_LOAD_STATE_COUNT_Start 16 +#define GCREG_COMMAND_LOAD_STATE_COUNT_Type U10 /* Starting state address. */ -#define GCREG_COMMAND_LOAD_STATE_COMMAND_ADDRESS 15 : 0 -#define GCREG_COMMAND_LOAD_STATE_COMMAND_ADDRESS_End 15 -#define GCREG_COMMAND_LOAD_STATE_COMMAND_ADDRESS_Start 0 -#define GCREG_COMMAND_LOAD_STATE_COMMAND_ADDRESS_Type U16 +#define GCREG_COMMAND_LOAD_STATE_ADDRESS 15 : 0 +#define GCREG_COMMAND_LOAD_STATE_ADDRESS_End 15 +#define GCREG_COMMAND_LOAD_STATE_ADDRESS_Start 0 +#define GCREG_COMMAND_LOAD_STATE_ADDRESS_Type U16 -#define GCREG_COMMAND_LOAD_STATE_COMMAND_OPCODE 31 : 27 -#define GCREG_COMMAND_LOAD_STATE_COMMAND_OPCODE_End 31 -#define GCREG_COMMAND_LOAD_STATE_COMMAND_OPCODE_Start 27 -#define GCREG_COMMAND_LOAD_STATE_COMMAND_OPCODE_Type U05 -#define GCREG_COMMAND_LOAD_STATE_COMMAND_OPCODE_LOAD_STATE 0x01 +#define GCREG_COMMAND_LOAD_STATE_OPCODE 31 : 27 +#define GCREG_COMMAND_LOAD_STATE_OPCODE_End 31 +#define GCREG_COMMAND_LOAD_STATE_OPCODE_Start 27 +#define GCREG_COMMAND_LOAD_STATE_OPCODE_Type U05 struct gccmdldstate { - /* gcregCommandLoadState:GCREG_COMMAND_LOAD_STATE_COMMAND_ADDRESS */ + /* gcregCommandLoadState:GCREG_COMMAND_LOAD_STATE_ADDRESS */ unsigned int address:16; - /* gcregCommandLoadState:GCREG_COMMAND_LOAD_STATE_COMMAND_COUNT */ + /* gcregCommandLoadState:GCREG_COMMAND_LOAD_STATE_COUNT */ unsigned int count:10; - /* gcregCommandLoadState:GCREG_COMMAND_LOAD_STATE_COMMAND_FLOAT */ + /* gcregCommandLoadState:GCREG_COMMAND_LOAD_STATE_FLOAT */ unsigned int fixed:1; - /* gcregCommandLoadState:GCREG_COMMAND_LOAD_STATE_COMMAND_OPCODE */ + /* gcregCommandLoadState:GCREG_COMMAND_LOAD_STATE_OPCODE */ unsigned int opcode:5; }; #define GCLDSTATE(Address, Count) \ { \ - /* gcregCommandLoadState:GCREG_COMMAND_LOAD_STATE_COMMAND_ADDRESS */ \ + /* gcregCommandLoadState:GCREG_COMMAND_LOAD_STATE_ADDRESS */ \ Address, \ \ - /* gcregCommandLoadState:GCREG_COMMAND_LOAD_STATE_COMMAND_COUNT */ \ + /* gcregCommandLoadState:GCREG_COMMAND_LOAD_STATE_COUNT */ \ Count, \ \ - /* gcregCommandLoadState:GCREG_COMMAND_LOAD_STATE_COMMAND_FLOAT */ \ - GCREG_COMMAND_LOAD_STATE_COMMAND_FLOAT_NORMAL, \ + /* gcregCommandLoadState:GCREG_COMMAND_LOAD_STATE_FLOAT */ \ + GCREG_COMMAND_LOAD_STATE_FLOAT_NORMAL, \ \ - /* gcregCommandLoadState:GCREG_COMMAND_LOAD_STATE_COMMAND_OPCODE */ \ - GCREG_COMMAND_LOAD_STATE_COMMAND_OPCODE_LOAD_STATE \ + /* gcregCommandLoadState:GCREG_COMMAND_LOAD_STATE_OPCODE */ \ + GCREG_COMMAND_OPCODE_LOAD_STATE \ } /******************************************************************************* @@ -1566,37 +1943,38 @@ struct gccmdldstate { */ /* Send event when END is completed. */ -#define GCREG_COMMAND_END_COMMAND_EVENT_ENABLE 8 : 8 -#define GCREG_COMMAND_END_COMMAND_EVENT_ENABLE_End 8 -#define GCREG_COMMAND_END_COMMAND_EVENT_ENABLE_Start 8 -#define GCREG_COMMAND_END_COMMAND_EVENT_ENABLE_Type U01 +#define GCREG_COMMAND_END_EVENT 8 : 8 +#define GCREG_COMMAND_END_EVENT_End 8 +#define GCREG_COMMAND_END_EVENT_Start 8 +#define GCREG_COMMAND_END_EVENT_Type U01 +#define GCREG_COMMAND_END_EVENT_DISABLE 0x0 +#define GCREG_COMMAND_END_EVENT_ENABLE 0x1 /* Event ID to be send. */ -#define GCREG_COMMAND_END_COMMAND_EVENT_ID 4 : 0 -#define GCREG_COMMAND_END_COMMAND_EVENT_ID_End 4 -#define GCREG_COMMAND_END_COMMAND_EVENT_ID_Start 0 -#define GCREG_COMMAND_END_COMMAND_EVENT_ID_Type U05 +#define GCREG_COMMAND_END_EVENT_ID 4 : 0 +#define GCREG_COMMAND_END_EVENT_ID_End 4 +#define GCREG_COMMAND_END_EVENT_ID_Start 0 +#define GCREG_COMMAND_END_EVENT_ID_Type U05 -#define GCREG_COMMAND_END_COMMAND_OPCODE 31 : 27 -#define GCREG_COMMAND_END_COMMAND_OPCODE_End 31 -#define GCREG_COMMAND_END_COMMAND_OPCODE_Start 27 -#define GCREG_COMMAND_END_COMMAND_OPCODE_Type U05 -#define GCREG_COMMAND_END_COMMAND_OPCODE_END 0x02 +#define GCREG_COMMAND_END_OPCODE 31 : 27 +#define GCREG_COMMAND_END_OPCODE_End 31 +#define GCREG_COMMAND_END_OPCODE_Start 27 +#define GCREG_COMMAND_END_OPCODE_Type U05 struct gcfldend { - /* gcregCommandEnd:GCREG_COMMAND_END_COMMAND_EVENT_ID */ + /* gcregCommandEnd:GCREG_COMMAND_END_EVENT_ID */ unsigned int signalid:5; /* gcregCommandEnd:reserved */ unsigned int _reserved_5_7:3; - /* gcregCommandEnd:GCREG_COMMAND_END_COMMAND_EVENT_ENABLE */ + /* gcregCommandEnd:GCREG_COMMAND_END_EVENT_ENABLE */ unsigned int signal:1; /* gcregCommandEnd:reserved */ unsigned int _reserved_9_26:18; - /* gcregCommandEnd:GCREG_COMMAND_END_COMMAND_OPCODE */ + /* gcregCommandEnd:GCREG_COMMAND_END_OPCODE */ unsigned int opcode:5; }; @@ -1611,38 +1989,46 @@ struct gccmdend { unsigned int _filler; }; -static const struct gcfldend gcfldend = { - /* gcregCommandEnd:GCREG_COMMAND_END_COMMAND_EVENT_ID */ - 0, +static const struct gccmdend gccmdend_const = { + /* cmd */ + { + /* fld */ + { + /* gcregCommandEnd:GCREG_COMMAND_END_EVENT_ID */ + 0, - /* gcregCommandEnd:reserved */ - 0, + /* gcregCommandEnd:reserved */ + 0, - /* gcregCommandEnd:GCREG_COMMAND_END_COMMAND_EVENT_ENABLE */ - 0, + /* gcregCommandEnd:GCREG_COMMAND_END_EVENT */ + GCREG_COMMAND_END_EVENT_DISABLE, - /* gcregCommandEnd:reserved */ - 0, + /* gcregCommandEnd:reserved */ + 0, - /* gcregCommandEnd:GCREG_COMMAND_END_COMMAND_OPCODE */ - GCREG_COMMAND_END_COMMAND_OPCODE_END + /* gcregCommandEnd:GCREG_COMMAND_END_OPCODE */ + GCREG_COMMAND_OPCODE_END + } + }, + + /* Alignment filler. */ + 0 }; /******************************************************************************* ** Command gcregCommandNop */ -#define GCREG_COMMAND_NOP_COMMAND_OPCODE 31 : 27 -#define GCREG_COMMAND_NOP_COMMAND_OPCODE_End 31 -#define GCREG_COMMAND_NOP_COMMAND_OPCODE_Start 27 -#define GCREG_COMMAND_NOP_COMMAND_OPCODE_Type U05 -#define GCREG_COMMAND_NOP_COMMAND_OPCODE_NOP 0x03 +#define GCREG_COMMAND_NOP_OPCODE 31 : 27 +#define GCREG_COMMAND_NOP_OPCODE_End 31 +#define GCREG_COMMAND_NOP_OPCODE_Start 27 +#define GCREG_COMMAND_NOP_OPCODE_Type U05 struct gcfldnop { /* gcregCommandNop:reserve */ unsigned int _reserved_0_26:27; - /* gcregCommandNop:GCREG_COMMAND_NOP_COMMAND_OPCODE */ + /* gcregCommandNop:GCREG_COMMAND_NOP_OPCODE */ unsigned int opcode:5; }; @@ -1657,12 +2043,21 @@ struct gccmdnop { unsigned int _filler; }; -static const struct gcfldnop gcfldnop = { - /* gcregCommandNop:reserve */ - 0, +static const struct gccmdnop gccmdnop_const = { + /* cmd */ + { + /* fld */ + { + /* gcregCommandNop:reserve */ + 0, + + /* gcregCommandNop:GCREG_COMMAND_NOP_OPCODE */ + GCREG_COMMAND_OPCODE_NOP + } + }, - /* gcregCommandNop:GCREG_COMMAND_NOP_COMMAND_OPCODE */ - GCREG_COMMAND_NOP_COMMAND_OPCODE_NOP + /* Alignment filler. */ + 0 }; /******************************************************************************* @@ -1675,36 +2070,35 @@ static const struct gcfldnop gcfldnop = { /* Number of 32-bit data words to send. ** The data follows the rectangles, aligned at 64-bit. */ -#define GCREG_COMMAND_START_DE_COMMAND_DATA_COUNT 26 : 16 -#define GCREG_COMMAND_START_DE_COMMAND_DATA_COUNT_End 26 -#define GCREG_COMMAND_START_DE_COMMAND_DATA_COUNT_Start 16 -#define GCREG_COMMAND_START_DE_COMMAND_DATA_COUNT_Type U11 +#define GCREG_COMMAND_STARTDE_DATA_COUNT 26 : 16 +#define GCREG_COMMAND_STARTDE_DATA_COUNT_End 26 +#define GCREG_COMMAND_STARTDE_DATA_COUNT_Start 16 +#define GCREG_COMMAND_STARTDE_DATA_COUNT_Type U11 /* Number of rectangles to send. ** The rectangles follow the command, aligned at 64-bit. */ -#define GCREG_COMMAND_START_DE_COMMAND_COUNT 15 : 8 -#define GCREG_COMMAND_START_DE_COMMAND_COUNT_End 15 -#define GCREG_COMMAND_START_DE_COMMAND_COUNT_Start 8 -#define GCREG_COMMAND_START_DE_COMMAND_COUNT_Type U08 +#define GCREG_COMMAND_STARTDE_COUNT 15 : 8 +#define GCREG_COMMAND_STARTDE_COUNT_End 15 +#define GCREG_COMMAND_STARTDE_COUNT_Start 8 +#define GCREG_COMMAND_STARTDE_COUNT_Type U08 -#define GCREG_COMMAND_START_DE_COMMAND_OPCODE 31 : 27 -#define GCREG_COMMAND_START_DE_COMMAND_OPCODE_End 31 -#define GCREG_COMMAND_START_DE_COMMAND_OPCODE_Start 27 -#define GCREG_COMMAND_START_DE_COMMAND_OPCODE_Type U05 -#define GCREG_COMMAND_START_DE_COMMAND_OPCODE_START_DE 0x04 +#define GCREG_COMMAND_STARTDE_OPCODE 31 : 27 +#define GCREG_COMMAND_STARTDE_OPCODE_End 31 +#define GCREG_COMMAND_STARTDE_OPCODE_Start 27 +#define GCREG_COMMAND_STARTDE_OPCODE_Type U05 struct gcfldstartde { /* gcregCommandStartDE:reserved */ unsigned int _reserved_0_7:8; - /* gcregCommandStartDE:GCREG_COMMAND_START_DE_COMMAND_COUNT */ + /* gcregCommandStartDE:GCREG_COMMAND_STARTDE_COUNT */ unsigned int rectcount:8; - /* gcregCommandStartDE:GCREG_COMMAND_START_DE_COMMAND_DATA_COUNT */ + /* gcregCommandStartDE:GCREG_COMMAND_STARTDE_DATA_COUNT */ unsigned int datacount:11; - /* gcregCommandStartDE:GCREG_COMMAND_START_DE_COMMAND_OPCODE */ + /* gcregCommandStartDE:GCREG_COMMAND_STARTDE_OPCODE */ unsigned int opcode:5; }; @@ -1722,14 +2116,14 @@ static const struct gcfldstartde gcfldstartde = { /* gcregCommandStartDE:reserved */ 0, - /* gcregCommandStartDE:GCREG_COMMAND_START_DE_COMMAND_COUNT */ + /* gcregCommandStartDE:GCREG_COMMAND_STARTDE_COUNT */ 1, - /* gcregCommandStartDE:GCREG_COMMAND_START_DE_COMMAND_DATA_COUNT */ + /* gcregCommandStartDE:GCREG_COMMAND_STARTDE_DATA_COUNT */ 0, - /* gcregCommandStartDE:GCREG_COMMAND_START_DE_COMMAND_OPCODE */ - GCREG_COMMAND_START_DE_COMMAND_OPCODE_START_DE + /* gcregCommandStartDE:GCREG_COMMAND_STARTDE_OPCODE */ + GCREG_COMMAND_OPCODE_STARTDE }; /* Offset TopLeft @@ -1777,25 +2171,24 @@ struct gccmdstartderect { */ /* Number of cycles to wait until the next command gets fetched. */ -#define GCREG_COMMAND_WAIT_COMMAND_DELAY 15 : 0 -#define GCREG_COMMAND_WAIT_COMMAND_DELAY_End 15 -#define GCREG_COMMAND_WAIT_COMMAND_DELAY_Start 0 -#define GCREG_COMMAND_WAIT_COMMAND_DELAY_Type U16 +#define GCREG_COMMAND_WAIT_DELAY 15 : 0 +#define GCREG_COMMAND_WAIT_DELAY_End 15 +#define GCREG_COMMAND_WAIT_DELAY_Start 0 +#define GCREG_COMMAND_WAIT_DELAY_Type U16 -#define GCREG_COMMAND_WAIT_COMMAND_OPCODE 31 : 27 -#define GCREG_COMMAND_WAIT_COMMAND_OPCODE_End 31 -#define GCREG_COMMAND_WAIT_COMMAND_OPCODE_Start 27 -#define GCREG_COMMAND_WAIT_COMMAND_OPCODE_Type U05 -#define GCREG_COMMAND_WAIT_COMMAND_OPCODE_WAIT 0x07 +#define GCREG_COMMAND_WAIT_OPCODE 31 : 27 +#define GCREG_COMMAND_WAIT_OPCODE_End 31 +#define GCREG_COMMAND_WAIT_OPCODE_Start 27 +#define GCREG_COMMAND_WAIT_OPCODE_Type U05 struct gcfldwait { - /* gcregCommandWait:GCREG_COMMAND_WAIT_COMMAND_DELAY */ + /* gcregCommandWait:GCREG_COMMAND_WAIT_DELAY */ unsigned int delay:16; /* gcregCommandWait:reserved */ unsigned int _reserved_16_26:11; - /* gcregCommandWait:GCREG_COMMAND_WAIT_COMMAND_OPCODE */ + /* gcregCommandWait:GCREG_COMMAND_WAIT_OPCODE */ unsigned int opcode:5; }; @@ -1810,14 +2203,14 @@ struct gccmdwait { }; static const struct gcfldwait gcfldwait200 = { - /* gcregCommandWait:GCREG_COMMAND_WAIT_COMMAND_DELAY */ + /* gcregCommandWait:GCREG_COMMAND_WAIT_DELAY */ 200, /* gcregCommandWait:reserved */ 0, - /* gcregCommandWait:GCREG_COMMAND_WAIT_COMMAND_OPCODE */ - GCREG_COMMAND_WAIT_COMMAND_OPCODE_WAIT + /* gcregCommandWait:GCREG_COMMAND_WAIT_OPCODE */ + GCREG_COMMAND_OPCODE_WAIT }; /******************************************************************************* @@ -1828,16 +2221,15 @@ static const struct gcfldwait gcfldwait200 = { ** nothing else will be fetched. So, make sure that the last command in the ** new command buffer is either an END, a LINK, a CALL, or a RETURN. */ -#define GCREG_COMMAND_LINK_COMMAND_PREFETCH 15 : 0 -#define GCREG_COMMAND_LINK_COMMAND_PREFETCH_End 15 -#define GCREG_COMMAND_LINK_COMMAND_PREFETCH_Start 0 -#define GCREG_COMMAND_LINK_COMMAND_PREFETCH_Type U16 +#define GCREG_COMMAND_LINK_PREFETCH 15 : 0 +#define GCREG_COMMAND_LINK_PREFETCH_End 15 +#define GCREG_COMMAND_LINK_PREFETCH_Start 0 +#define GCREG_COMMAND_LINK_PREFETCH_Type U16 -#define GCREG_COMMAND_LINK_COMMAND_OPCODE 31 : 27 -#define GCREG_COMMAND_LINK_COMMAND_OPCODE_End 31 -#define GCREG_COMMAND_LINK_COMMAND_OPCODE_Start 27 -#define GCREG_COMMAND_LINK_COMMAND_OPCODE_Type U05 -#define GCREG_COMMAND_LINK_COMMAND_OPCODE_LINK 0x08 +#define GCREG_COMMAND_LINK_OPCODE 31 : 27 +#define GCREG_COMMAND_LINK_OPCODE_End 31 +#define GCREG_COMMAND_LINK_OPCODE_Start 27 +#define GCREG_COMMAND_LINK_OPCODE_Type U05 /* Offset Address ** ~~~~~~~~~~~~~~ */ @@ -1850,13 +2242,13 @@ static const struct gcfldwait gcfldwait200 = { #define GCREG_COMMAND_LINK_ADDRESS_ADDRESS_Type U31 struct gcfldlink { - /* gcregCommandLink:GCREG_COMMAND_LINK_COMMAND_PREFETCH */ + /* gcregCommandLink:GCREG_COMMAND_LINK_PREFETCH */ unsigned int count:16; /* gcregCommandLink:reserved */ unsigned int _reserved_16_26:11; - /* gcregCommandLink:GCREG_COMMAND_LINK_COMMAND_OPCODE */ + /* gcregCommandLink:GCREG_COMMAND_LINK_OPCODE */ unsigned int opcode:5; }; @@ -1870,15 +2262,26 @@ struct gccmdlink { unsigned int address; }; +static const struct gcfldlink gcfldlink2 = { + /* gcregCommandLink:GCREG_COMMAND_LINK_PREFETCH */ + 2, + + /* gcregCommandLink:reserved */ + 0, + + /* gcregCommandLink:GCREG_COMMAND_LINK_OPCODE */ + GCREG_COMMAND_OPCODE_LINK +}; + static const struct gcfldlink gcfldlink4 = { - /* gcregCommandLink:GCREG_COMMAND_LINK_COMMAND_PREFETCH */ + /* gcregCommandLink:GCREG_COMMAND_LINK_PREFETCH */ 4, /* gcregCommandLink:reserved */ 0, - /* gcregCommandLink:GCREG_COMMAND_LINK_COMMAND_OPCODE */ - GCREG_COMMAND_LINK_COMMAND_OPCODE_LINK + /* gcregCommandLink:GCREG_COMMAND_LINK_OPCODE */ + GCREG_COMMAND_OPCODE_LINK }; /******************************************************************************* @@ -1887,11 +2290,10 @@ static const struct gcfldlink gcfldlink4 = { /* Offset Command ** ~~~~~~~~~~~~~~ */ -#define GCREG_COMMAND_STALL_COMMAND_OPCODE 31 : 27 -#define GCREG_COMMAND_STALL_COMMAND_OPCODE_End 31 -#define GCREG_COMMAND_STALL_COMMAND_OPCODE_Start 27 -#define GCREG_COMMAND_STALL_COMMAND_OPCODE_Type U05 -#define GCREG_COMMAND_STALL_COMMAND_OPCODE_STALL 0x09 +#define GCREG_COMMAND_STALL_OPCODE 31 : 27 +#define GCREG_COMMAND_STALL_OPCODE_End 31 +#define GCREG_COMMAND_STALL_OPCODE_Start 27 +#define GCREG_COMMAND_STALL_OPCODE_Type U05 /* Offset Stall ** ~~~~~~~~~~~~ */ @@ -1915,7 +2317,7 @@ struct gcfldstall { /* gcregCommandStall:reserved */ unsigned int _reserved_0_26:27; - /* gcregCommandStall:GCREG_COMMAND_STALL_COMMAND_OPCODE */ + /* gcregCommandStall:GCREG_COMMAND_STALL_OPCODE */ unsigned int opcode:5; }; @@ -1949,8 +2351,8 @@ static const struct gcfldstall gcfldstall = { /* gcregCommandStall:reserved */ 0, - /* gcregCommandStall:GCREG_COMMAND_STALL_COMMAND_OPCODE */ - GCREG_COMMAND_STALL_COMMAND_OPCODE_STALL + /* gcregCommandStall:GCREG_COMMAND_STALL_OPCODE */ + GCREG_COMMAND_OPCODE_STALL }; static const struct gcfldstallarg gcfldstall_fe_pe = { @@ -1978,16 +2380,15 @@ static const struct gcfldstallarg gcfldstall_fe_pe = { ** nothing else will be fetched. So, make sure that the last command in the ** new command buffer is either an END, a LINK, a CALL, or a RETURN. */ -#define GCREG_COMMAND_CALL_COMMAND_PREFETCH 15 : 0 -#define GCREG_COMMAND_CALL_COMMAND_PREFETCH_End 15 -#define GCREG_COMMAND_CALL_COMMAND_PREFETCH_Start 0 -#define GCREG_COMMAND_CALL_COMMAND_PREFETCH_Type U16 +#define GCREG_COMMAND_CALL_PREFETCH 15 : 0 +#define GCREG_COMMAND_CALL_PREFETCH_End 15 +#define GCREG_COMMAND_CALL_PREFETCH_Start 0 +#define GCREG_COMMAND_CALL_PREFETCH_Type U16 -#define GCREG_COMMAND_CALL_COMMAND_OPCODE 31 : 27 -#define GCREG_COMMAND_CALL_COMMAND_OPCODE_End 31 -#define GCREG_COMMAND_CALL_COMMAND_OPCODE_Start 27 -#define GCREG_COMMAND_CALL_COMMAND_OPCODE_Type U05 -#define GCREG_COMMAND_CALL_COMMAND_OPCODE_CALL 0x0A +#define GCREG_COMMAND_CALL_OPCODE 31 : 27 +#define GCREG_COMMAND_CALL_OPCODE_End 31 +#define GCREG_COMMAND_CALL_OPCODE_Start 27 +#define GCREG_COMMAND_CALL_OPCODE_Type U05 /* Offset Address ** ~~~~~~~~~~~~~~ */ @@ -2018,13 +2419,13 @@ static const struct gcfldstallarg gcfldstall_fe_pe = { #define GCREG_COMMAND_CALL_RETURN_ADDRESS_ADDRESS_Type U31 struct gccmdcall { - /* gcregCommandCall:GCREG_COMMAND_CALL_COMMAND_PREFETCH */ + /* gcregCommandCall:GCREG_COMMAND_CALL_PREFETCH */ unsigned int count:16; /* gcregCommandCall:reserved */ unsigned int _reserved_16_26:11; - /* gcregCommandCall:GCREG_COMMAND_CALL_COMMAND_OPCODE */ + /* gcregCommandCall:GCREG_COMMAND_CALL_OPCODE */ unsigned int opcode:5; /* gcregCommandCall:GCREG_COMMAND_CALL_ADDRESS_ADDRESS */ @@ -2041,17 +2442,16 @@ struct gccmdcall { ** Command gccmdCommandReturn */ -#define GCREG_COMMAND_RETURN_COMMAND_OPCODE 31 : 27 -#define GCREG_COMMAND_RETURN_COMMAND_OPCODE_End 31 -#define GCREG_COMMAND_RETURN_COMMAND_OPCODE_Start 27 -#define GCREG_COMMAND_RETURN_COMMAND_OPCODE_Type U05 -#define GCREG_COMMAND_RETURN_COMMAND_OPCODE_RETURN 0x0B +#define GCREG_COMMAND_RETURN_OPCODE 31 : 27 +#define GCREG_COMMAND_RETURN_OPCODE_End 31 +#define GCREG_COMMAND_RETURN_OPCODE_Start 27 +#define GCREG_COMMAND_RETURN_OPCODE_Type U05 struct gcfldret { /* gccmdCommandReturn:reserve */ unsigned int _reserved_0_26:27; - /* gccmdCommandReturn:GCREG_COMMAND_RETURN_COMMAND_OPCODE */ + /* gccmdCommandReturn:GCREG_COMMAND_RETURN_OPCODE */ unsigned int opcode:5; }; @@ -2070,8 +2470,8 @@ static const struct gcfldret gcfldret = { /* gccmdCommandReturn:reserve */ 0, - /* gccmdCommandReturn:GCREG_COMMAND_RETURN_COMMAND_OPCODE */ - GCREG_COMMAND_RETURN_COMMAND_OPCODE_RETURN + /* gccmdCommandReturn:GCREG_COMMAND_RETURN_OPCODE */ + GCREG_COMMAND_OPCODE_RETURN }; /******************************************************************************* @@ -2149,6 +2549,14 @@ static const struct gcregpipeselect gcregpipeselect_2D = { 0 }; +static const struct gcregpipeselect gcregpipeselect_3D = { + /* gcregPipeSelectRegAddrs:GCREG_PIPE_SELECT_PIPE */ + GCREG_PIPE_SELECT_PIPE_PIPE3D, + + /* gcregPipeSelectRegAddrs:reserved */ + 0 +}; + /******************************************************************************* ** State gcregEvent */ @@ -7883,6 +8291,28 @@ struct gcmosema { ** Modular operations: mmuinit */ +struct gcmoterminator { + union { + struct gcmosignal done; + struct gccmdnop nop; + } u1; + + union { + struct gccmdwait wait; + struct gccmdlink linknext; + struct gccmdend end; + } u2; + + union { + struct gccmdlink linkwait; + struct gccmdnop nop; + } u3; +}; + +/******************************************************************************* +** Modular operations: mmuinit +*/ + static const struct gccmdldstate gcmommuinit_safe_ldst = GCLDSTATE(gcregMMUSafeAddressRegAddrs, 2); @@ -7982,7 +8412,7 @@ struct gcmoclip { */ static const struct gccmdldstate gcmodst_address_ldst = - GCLDSTATE(gcregDestAddressRegAddrs, 4); + GCLDSTATE(gcregDestAddressRegAddrs, 3); static const struct gccmdldstate gcmodst_rotationheight_ldst = GCLDSTATE(gcregDstRotationHeightRegAddrs, 1); @@ -8003,15 +8433,6 @@ struct gcmodst { unsigned int raw; } rotation; - /* gcregDestConfigRegAddrs */ - union { - struct gcregdstconfig reg; - unsigned int raw; - } config; - - /* Alignment filler. */ - unsigned int _filler; - /* gcregDstRotationHeightRegAddrs */ struct gccmdldstate rotationheight_ldst; @@ -8020,8 +8441,6 @@ struct gcmodst { struct gcregdstrotationheight reg; unsigned int raw; } rotationheight; - - struct gcmoclip clip; }; /******************************************************************************* @@ -8042,6 +8461,34 @@ static const struct gccmdldstate gcmosrc_stride_ldst[4] = { GCLDSTATE(gcregBlock4SrcStrideRegAddrs + 3, 1), }; +static const struct gccmdldstate gcmosrc_uplaneaddress_ldst[4] = { + GCLDSTATE(gcregUPlaneAddressRegAddrs + 0, 1), + GCLDSTATE(gcregUPlaneAddressRegAddrs + 1, 1), + GCLDSTATE(gcregUPlaneAddressRegAddrs + 2, 1), + GCLDSTATE(gcregUPlaneAddressRegAddrs + 3, 1), +}; + +static const struct gccmdldstate gcmosrc_uplanestride_ldst[4] = { + GCLDSTATE(gcregUPlaneStrideRegAddrs + 0, 1), + GCLDSTATE(gcregUPlaneStrideRegAddrs + 1, 1), + GCLDSTATE(gcregUPlaneStrideRegAddrs + 2, 1), + GCLDSTATE(gcregUPlaneStrideRegAddrs + 3, 1), +}; + +static const struct gccmdldstate gcmosrc_vplaneaddress_ldst[4] = { + GCLDSTATE(gcregVPlaneAddressRegAddrs + 0, 1), + GCLDSTATE(gcregVPlaneAddressRegAddrs + 1, 1), + GCLDSTATE(gcregVPlaneAddressRegAddrs + 2, 1), + GCLDSTATE(gcregVPlaneAddressRegAddrs + 3, 1), +}; + +static const struct gccmdldstate gcmosrc_vplanestride_ldst[4] = { + GCLDSTATE(gcregVPlaneStrideRegAddrs + 0, 1), + GCLDSTATE(gcregVPlaneStrideRegAddrs + 1, 1), + GCLDSTATE(gcregVPlaneStrideRegAddrs + 2, 1), + GCLDSTATE(gcregVPlaneStrideRegAddrs + 3, 1), +}; + static const struct gccmdldstate gcmosrc_rotation_ldst[4] = { GCLDSTATE(gcregBlock4SrcRotationConfigRegAddrs + 0, 1), GCLDSTATE(gcregBlock4SrcRotationConfigRegAddrs + 1, 1), @@ -8098,21 +8545,21 @@ static const struct gccmdldstate gcmosrc_alphacontrol_ldst[4] = { GCLDSTATE(gcregBlock4AlphaControlRegAddrs + 3, 1), }; -static const struct gccmdldstate gcmosrc_alphamodes_ldst[4] = { +static const struct gccmdldstate gcmosrcalpha_alphamodes_ldst[4] = { GCLDSTATE(gcregBlock4AlphaModesRegAddrs + 0, 1), GCLDSTATE(gcregBlock4AlphaModesRegAddrs + 1, 1), GCLDSTATE(gcregBlock4AlphaModesRegAddrs + 2, 1), GCLDSTATE(gcregBlock4AlphaModesRegAddrs + 3, 1), }; -static const struct gccmdldstate gcmosrc_srcglobal_ldst[4] = { +static const struct gccmdldstate gcmosrcalpha_srcglobal_ldst[4] = { GCLDSTATE(gcregBlock4GlobalSrcColorRegAddrs + 0, 1), GCLDSTATE(gcregBlock4GlobalSrcColorRegAddrs + 1, 1), GCLDSTATE(gcregBlock4GlobalSrcColorRegAddrs + 2, 1), GCLDSTATE(gcregBlock4GlobalSrcColorRegAddrs + 3, 1), }; -static const struct gccmdldstate gcmosrc_dstglobal_ldst[4] = { +static const struct gccmdldstate gcmosrcalpha_dstglobal_ldst[4] = { GCLDSTATE(gcregBlock4GlobalDestColorRegAddrs + 0, 1), GCLDSTATE(gcregBlock4GlobalDestColorRegAddrs + 1, 1), GCLDSTATE(gcregBlock4GlobalDestColorRegAddrs + 2, 1), @@ -8203,7 +8650,27 @@ struct gcmosrc { struct gcregalphacontrol reg; unsigned int raw; } alphacontrol; +}; + +struct gcmosrcplanaryuv { + /* gcregUPlaneAddressRegAddrs */ + struct gccmdldstate uplaneaddress_ldst; + unsigned int uplaneaddress; + /* gcregUPlaneStrideRegAddrs */ + struct gccmdldstate uplanestride_ldst; + unsigned int uplanestride; + + /* gcregVPlaneAddressRegAddrs */ + struct gccmdldstate vplaneaddress_ldst; + unsigned int vplaneaddress; + + /* gcregVPlaneStrideRegAddrs */ + struct gccmdldstate vplanestride_ldst; + unsigned int vplanestride; +}; + +struct gcmosrcalpha { /* gcregBlock4AlphaModesRegAddrs */ struct gccmdldstate alphamodes_ldst; @@ -8254,13 +8721,34 @@ struct gcmomultisrc { ** Modular operations: startde */ +static const struct gccmdldstate gcmostart_config_ldst = + GCLDSTATE(gcregDestConfigRegAddrs, 1); + +static const struct gccmdldstate gcmostart_rop_ldst = + GCLDSTATE(gcregRopRegAddrs, 1); + struct gcmostart { + /* gcregDestConfigRegAddrs */ + struct gccmdldstate config_ldst; + + /* gcregDestConfigRegAddrs */ + union { + struct gcregdstconfig reg; + unsigned int raw; + } config; + + /* gcregRopRegAddrs */ + struct gccmdldstate rop_ldst; + + /* gcregRopRegAddrs */ + union { + struct gcregrop reg; + unsigned int raw; + } rop; + /* Start DE command. */ struct gccmdstartde startde; struct gccmdstartderect rect; - - /* PE cache flush. */ - struct gcmoflush flush; }; /******************************************************************************* @@ -8273,8 +8761,8 @@ static const struct gccmdldstate gcmofillsrc_rotation_ldst = static const struct gccmdldstate gcmofillsrc_rotationheight_ldst = GCLDSTATE(gcregSrcRotationHeightRegAddrs, 1); -static const struct gccmdldstate gcmofillsrc_rop_ldst = - GCLDSTATE(gcregRopRegAddrs, 1); +static const struct gccmdldstate gcmofillsrc_alphacontrol_ldst = + GCLDSTATE(gcregAlphaControlRegAddrs, 1); struct gcmofillsrc { /* gcregSrcRotationConfigRegAddrs */ @@ -8304,14 +8792,14 @@ struct gcmofillsrc { unsigned int raw; } rotationheight; - /* gcregRopRegAddrs */ - struct gccmdldstate rop_ldst; + /* gcregAlphaControlRegAddrs */ + struct gccmdldstate alphacontrol_ldst; - /* gcregRopRegAddrs */ + /* gcregAlphaControlRegAddrs */ union { - struct gcregrop reg; + struct gcregalphacontrol reg; unsigned int raw; - } rop; + } alphacontrol; }; /******************************************************************************* @@ -8322,7 +8810,6 @@ static const struct gccmdldstate gcmofill_clearcolor_ldst = GCLDSTATE(gcregClearPixelValue32RegAddrs, 1); struct gcmofill { - struct gcmodst dst; struct gcmofillsrc src; /* gcregClearPixelValue32RegAddrs */ diff --git a/gcbv/mirror/include/gcx.h b/gcbv/mirror/include/gcx.h new file mode 100644 index 0000000..431c3c5 --- /dev/null +++ b/gcbv/mirror/include/gcx.h @@ -0,0 +1,100 @@ +/* + * 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, + * Texas Instruments, Inc. and 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, + * Texas Instruments, Inc. and Vivante Corporation. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Vivante Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef GCX_H +#define GCX_H + +#include <pthread.h> +#include "gcerror.h" +#include "gcreg.h" +#include "gcdbglog.h" + +#ifndef countof +#define countof(a) \ + (sizeof(a) / sizeof(a[0])) +#endif + +#define GCLOCK_TYPE \ + pthread_mutex_t + +#define GCDEFINE_LOCK(name) \ + pthread_mutex_t name = PTHREAD_MUTEX_INITIALIZER + +#define GCLOCK_INIT(lock) \ + if (pthread_mutex_init(lock, NULL)) { \ + GCERR("failed to init mutex.\n"); \ + } + +#define GCLOCK_DESTROY(lock) \ + if (pthread_mutex_destroy(lock)) { \ + GCERR("failed to destroy mutex.\n"); \ + } + +#define GCLOCK(lock) \ + if (pthread_mutex_lock(lock)) { \ + GCERR("failed to lock mutex.\n"); \ + } + +#define GCUNLOCK(lock) \ + if (pthread_mutex_unlock(lock)) { \ + GCERR("failed to unlock mutex.\n"); \ + } + +#endif diff --git a/gcbv/gcx.h b/gcbv/version.h index 17bcf91..7f0a43f 100644 --- a/gcbv/gcx.h +++ b/gcbv/version.h @@ -1,5 +1,7 @@ /* - * Copyright (c) 2011, Texas Instruments, Inc. + * Copyright (c) 2012, + * Texas Instruments, Inc. and Vivante Corporation + * * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -25,14 +27,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef GCX_H -#define GCX_H - -#include "gcerror.h" -#include "gcreg.h" - -/* Debug print prefixes. */ -#define GC_INFO_MSG stdout, DEV_NAME ": %s(%d)" -#define GC_ERR_MSG stderr, DEV_NAME ": %s(%d)" - -#endif +#define VER_FILEVERSION 2,1,0,0 +#define VER_FILEVERSION_STR "2.1.0.0\0" +#define VER_PRODUCTVERSION 2,1,0,0 +#define VER_PRODUCTVERSION_STR "2.1\0" |