summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCraig Stout <craig.stout@ti.com>2012-06-14 11:10:30 -0700
committerCraig Stout <craig.stout@ti.com>2012-06-14 20:08:19 -0700
commit8b1254def8dfc3d843bc22acc3c66295d42d1718 (patch)
tree2f706e0dddf53a979b344b91242436d25c24fc47
parent6878136fd3840c22571cf5d1925d2b2a769dace6 (diff)
downloadhardware_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.mk56
-rw-r--r--gcbv/gc2d.h11
-rw-r--r--gcbv/gcbv.c3207
-rw-r--r--gcbv/gcioctl.h137
-rw-r--r--gcbv/gcmain.c287
-rw-r--r--gcbv/gcmain.h54
-rw-r--r--gcbv/mirror/gcbv.c4156
-rw-r--r--gcbv/mirror/gcdbglog.c1696
-rw-r--r--gcbv/mirror/include/cache-2dmanager.h103
-rw-r--r--gcbv/mirror/include/gcdbglog.h412
-rw-r--r--gcbv/mirror/include/gcerror.h (renamed from gcbv/gcerror.h)97
-rw-r--r--gcbv/mirror/include/gcioctl.h263
-rw-r--r--gcbv/mirror/include/gclist.h630
-rw-r--r--gcbv/mirror/include/gcreg.h (renamed from gcbv/gcreg.h)903
-rw-r--r--gcbv/mirror/include/gcx.h100
-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"