initial commit

sources from http://omapzoom.org
diff --git a/Android.mk b/Android.mk
new file mode 100644
index 0000000..f35559b
--- /dev/null
+++ b/Android.mk
@@ -0,0 +1,23 @@
+#
+# Copyright (C) 2013 The CyanogenMod Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+ifneq ($(filter i9100g p3100 p3110 p5100 p5110,$(TARGET_DEVICE)),)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
+
+endif
diff --git a/BoardConfigCommon.mk b/BoardConfigCommon.mk
new file mode 100644
index 0000000..a44100e
--- /dev/null
+++ b/BoardConfigCommon.mk
@@ -0,0 +1,90 @@
+#
+# Copyright (C) 2013 The CyanogenMod Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+COMMON_PATH := device/samsung/omap4-common
+
+BOARD_VENDOR := samsung
+
+PRODUCT_VENDOR_KERNEL_HEADERS := $(COMMON_PATH)/kernel-headers
+TARGET_SPECIFIC_HEADER_PATH := $(COMMON_PATH)/include
+
+# HWComposer
+BOARD_USES_HWCOMPOSER := true
+BOARD_USE_SYSFS_VSYNC_NOTIFICATION := true
+# set if the target supports FBIO_WAITFORVSYNC
+TARGET_HAS_WAITFORVSYNC := true
+
+# Setup custom omap4xxx defines
+BOARD_USE_CUSTOM_LIBION := true
+
+# TI Enhancement Settings (Part 1)
+OMAP_ENHANCEMENT := true
+#OMAP_ENHANCEMENT_BURST_CAPTURE := true
+#OMAP_ENHANCEMENT_S3D := true
+#OMAP_ENHANCEMENT_CPCAM := true
+#OMAP_ENHANCEMENT_VTC := true
+OMAP_ENHANCEMENT_MULTIGPU := true
+BOARD_USE_TI_ENHANCED_DOMX := true
+
+# External SGX Module
+SGX_MODULES:
+	make clean -C $(COMMON_PATH)/pvr-source/eurasiacon/build/linux2/omap4430_android
+	cp $(TARGET_KERNEL_SOURCE)/drivers/video/omap2/omapfb/omapfb.h $(KERNEL_OUT)/drivers/video/omap2/omapfb/omapfb.h
+	make -j8 -C $(COMMON_PATH)/pvr-source/eurasiacon/build/linux2/omap4430_android ARCH=arm KERNEL_CROSS_COMPILE=arm-eabi- CROSS_COMPILE=arm-eabi- KERNELDIR=$(KERNEL_OUT) TARGET_PRODUCT="blaze_tablet" BUILD=release TARGET_SGX=540 PLATFORM_VERSION=4.0
+	mv $(KERNEL_OUT)/../../target/kbuild/pvrsrvkm_sgx540_120.ko $(KERNEL_MODULES_OUT)
+
+TARGET_KERNEL_MODULES += SGX_MODULES
+
+# TI Enhancement Settings (Part 2)
+ifdef BOARD_USE_TI_ENHANCED_DOMX
+    BOARD_USE_TI_DUCATI_H264_PROFILE := true
+    COMMON_GLOBAL_CFLAGS += -DENHANCED_DOMX
+    ENHANCED_DOMX := true
+else
+    DOMX_PATH := hardware/ti/omap4xxx/domx
+endif
+
+ifdef OMAP_ENHANCEMENT
+    COMMON_GLOBAL_CFLAGS += -DOMAP_ENHANCEMENT -DTARGET_OMAP4
+endif
+
+ifdef OMAP_ENHANCEMENT_BURST_CAPTURE
+    COMMON_GLOBAL_CFLAGS += -DOMAP_ENHANCEMENT_BURST_CAPTURE
+endif
+
+ifdef OMAP_ENHANCEMENT_S3D
+    COMMON_GLOBAL_CFLAGS += -DOMAP_ENHANCEMENT_S3D
+endif
+
+ifdef OMAP_ENHANCEMENT_CPCAM
+    COMMON_GLOBAL_CFLAGS += -DOMAP_ENHANCEMENT_CPCAM
+    PRODUCT_MAKEFILES += $(LOCAL_DIR)/sdk_addon/ti_omap_addon.mk
+endif
+
+ifdef OMAP_ENHANCEMENT_VTC
+    COMMON_GLOBAL_CFLAGS += -DOMAP_ENHANCEMENT_VTC
+endif
+
+ifdef USE_ITTIAM_AAC
+    COMMON_GLOBAL_CFLAGS += -DUSE_ITTIAM_AAC
+endif
+
+ifdef OMAP_ENHANCEMENT_MULTIGPU
+    COMMON_GLOBAL_CFLAGS += -DOMAP_ENHANCEMENT_MULTIGPU
+endif
+
+# inherit from the proprietary version
+-include vendor/samsung/omap4-common/BoardConfigVendor.mk
diff --git a/bltsville/Android.mk b/bltsville/Android.mk
new file mode 100644
index 0000000..56a3fa8
--- /dev/null
+++ b/bltsville/Android.mk
@@ -0,0 +1,17 @@
+#
+# Copyright (C) 2011 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+include $(call all-subdir-makefiles)
diff --git a/bltsville/bltsville/README b/bltsville/bltsville/README
new file mode 100755
index 0000000..bf5751b
--- /dev/null
+++ b/bltsville/bltsville/README
@@ -0,0 +1 @@
+git://github.com/graphics/bltsville.git
diff --git a/bltsville/bltsville/blend-854x480-bad.jpg b/bltsville/bltsville/blend-854x480-bad.jpg
new file mode 100644
index 0000000..adc2d6d
--- /dev/null
+++ b/bltsville/bltsville/blend-854x480-bad.jpg
Binary files differ
diff --git a/bltsville/bltsville/blend-854x480-bad2.jpg b/bltsville/bltsville/blend-854x480-bad2.jpg
new file mode 100644
index 0000000..67a01f3
--- /dev/null
+++ b/bltsville/bltsville/blend-854x480-bad2.jpg
Binary files differ
diff --git a/bltsville/bltsville/blend-854x480-roundingerror.jpg b/bltsville/bltsville/blend-854x480-roundingerror.jpg
new file mode 100644
index 0000000..9a12713
--- /dev/null
+++ b/bltsville/bltsville/blend-854x480-roundingerror.jpg
Binary files differ
diff --git a/bltsville/bltsville/blend-854x480-threeblts.jpg b/bltsville/bltsville/blend-854x480-threeblts.jpg
new file mode 100644
index 0000000..3790a29
--- /dev/null
+++ b/bltsville/bltsville/blend-854x480-threeblts.jpg
Binary files differ
diff --git a/bltsville/bltsville/blend-854x480.jpg b/bltsville/bltsville/blend-854x480.jpg
new file mode 100644
index 0000000..c76a433
--- /dev/null
+++ b/bltsville/bltsville/blend-854x480.jpg
Binary files differ
diff --git a/bltsville/bltsville/bvlogo.png b/bltsville/bltsville/bvlogo.png
new file mode 100644
index 0000000..7f9944e
--- /dev/null
+++ b/bltsville/bltsville/bvlogo.png
Binary files differ
diff --git a/bltsville/bltsville/clock-720x480_4x3-fauxtrans.jpg b/bltsville/bltsville/clock-720x480_4x3-fauxtrans.jpg
new file mode 100644
index 0000000..fa3aa68
--- /dev/null
+++ b/bltsville/bltsville/clock-720x480_4x3-fauxtrans.jpg
Binary files differ
diff --git a/bltsville/bltsville/clock-720x480_4x3.png b/bltsville/bltsville/clock-720x480_4x3.png
new file mode 100644
index 0000000..3a7f566
--- /dev/null
+++ b/bltsville/bltsville/clock-720x480_4x3.png
Binary files differ
diff --git a/bltsville/bltsville/concrete-64x36.png b/bltsville/bltsville/concrete-64x36.png
new file mode 100644
index 0000000..cf21f0f
--- /dev/null
+++ b/bltsville/bltsville/concrete-64x36.png
Binary files differ
diff --git a/bltsville/bltsville/include/bltsville.h b/bltsville/bltsville/include/bltsville.h
new file mode 100644
index 0000000..632628e
--- /dev/null
+++ b/bltsville/bltsville/include/bltsville.h
@@ -0,0 +1,602 @@
+/*
+ * bltsville.h
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ *
+ * This file is part of BLTsville, an open application programming interface
+ * (API) for accessing 2-D software or hardware implementations.
+ *
+ * This work is licensed under the Creative Commons Attribution-NoDerivs 3.0
+ * Unported License. To view a copy of this license, visit
+ * http://creativecommons.org/licenses/by-nd/3.0/ or send a letter to
+ * Creative Commons, 444 Castro Street, Suite 900, Mountain View, California,
+ * 94041, USA.
+ */
+
+#ifndef BLTSVILLE_H
+#define BLTSVILLE_H
+
+#include "ocd.h"
+#include "bverror.h"
+#include "bvblend.h"
+#include "bvfilter.h"
+#include "bvbuffdesc.h"
+#include "bvcache.h"
+#include "bventry.h"
+#include "bvsurfgeom.h"
+
+/*
+ * bvrect - This structure is used to specify rectangles in BLTsville.
+ */
+struct bvrect {
+	int left;
+	int top;
+	unsigned int width;
+	unsigned int height;
+};
+
+
+/*
+ * BVFLAG_* - These define the type of BLT to be performed and are placed in
+ * the bvparams.flags element.
+ */
+#define BVFLAG_OP_SHIFT	0
+#define BVFLAG_OP_MASK	(0xF << BVFLAG_OP_SHIFT)
+
+/* 0 reserved */
+#define BVFLAG_ROP	(0x1 << BVFLAG_OP_SHIFT) /* ROP4 spec'd in rop */
+#define BVFLAG_BLEND	(0x2 << BVFLAG_OP_SHIFT) /* blend spec'd in blend */
+/* 3 reserved */
+#define BVFLAG_FILTER	(0x4 << BVFLAG_OP_SHIFT) /* filter spec'd in filter */
+/* 5-F reserved */
+
+#define BVFLAG_KEY_SRC		0x00000010 /* source color key - value spec'd
+					      by pcolorkey; Mutually exclusive
+					      with BVFLAG_KEY_DST */
+#define BVFLAG_KEY_DST		0x00000020 /* dest color key - value spec'd
+					      by pcolorkey; Mutually exclusive
+					      with BVFLAG_KEY_SRC */
+#define BVFLAG_CLIP		0x00000040 /* clipping rectangle spec'd by
+					      cliprect */
+#define BVFLAG_SRCMASK		0x00000080 /* when scaling a masked copy, mask
+					      at the source instead of the
+					      (default) destination */
+
+#define BVFLAG_ASYNC		0x00000100 /* call should return once queued */
+
+#define BVFLAG_TILE_SRC1	0x00000200 /* source 1 is tiled */
+#define BVFLAG_TILE_SRC2	0x00000400 /* source 2 is tiled */
+#define BVFLAG_TILE_MASK	0x00000800 /* mask is tiled */
+
+
+#define BVFLAG_BATCH_SHIFT	12
+#define BVFLAG_BATCH_MASK	(3 << BVFLAG_BATCH_SHIFT)
+
+#define BVFLAG_BATCH_NONE	(0 << BVFLAG_BATCH_SHIFT) /* not batched */
+#define BVFLAG_BATCH_BEGIN	(1 << BVFLAG_BATCH_SHIFT) /* begin batch */
+#define BVFLAG_BATCH_CONTINUE	(2 << BVFLAG_BATCH_SHIFT) /* continue batch */
+#define BVFLAG_BATCH_END	(3 << BVFLAG_BATCH_SHIFT) /* end batch */
+
+
+#define BVFLAG_HORZ_FLIP_SRC1	0x00004000 /* flip src1 horizontally */
+#define BVFLAG_VERT_FLIP_SRC1	0x00008000 /* flip src1 vertically */
+#define BVFLAG_HORZ_FLIP_SRC2	0x00010000 /* flip src2 horizontally */
+#define BVFLAG_VERT_FLIP_SRC2	0x00020000 /* flip src2 vertically */
+#define BVFLAG_HORZ_FLIP_MASK	0x00040000 /* flip mask horizontally */
+#define BVFLAG_VERT_FLIP_MASK	0x00080000 /* flip mask vertically */
+
+
+#define BVFLAG_SCALE_RETURN	0x00100000 /* return scale type used */
+#define BVFLAG_DITHER_RETURN	0x00200000 /* return dither type used */
+
+
+#define BVFLAG_SRC2_AUXDSTRECT	0x00400000 /* src2auxdstrect used */
+#define BVFLAG_MASK_AUXDSTRECT	0x00800000 /* maskauxdstrect used */
+
+#define BVFLAG_TESTPARAMS_NOP	0x01000000 /* test params only - no BLT */
+/**** Bits 25-31 reserved ****/
+
+/*
+ * BVIMPL_* - BLTsville implementations may be combined under managers to
+ * allow clients to take advantage of multiple implementations without doing
+ * so explicitly.  The BVIMPL_* definition are placed into the
+ * bvparams.implementation member by the client to override the manager's
+ * choice of implementation.
+ */
+#define BVIMPL_ANY		0
+#define BVIMPL_FIRST_HW		(1 << 31) /* Continues to the right */
+#define BVIMPL_FIRST_CPU	(1 << 0)  /* Continues to the left */
+
+
+/*
+ * bvscalemode - This specifies the type of scaling to perform.
+ */
+#define BVSCALEDEF_VENDOR_SHIFT 24
+#define BVSCALEDEF_VENDOR_MASK (0xFF << BVSCALEDEF_VENDOR_SHIFT)
+
+#define BVSCALEDEF_VENDOR_ALL (0 << BVSCALEDEF_VENDOR_SHIFT)
+#define BVSCALEDEF_VENDOR_TI  (1 << BVSCALEDEF_VENDOR_SHIFT)
+/* 0xF0-0xFE reserved */
+#define BVSCALEDEF_VENDOR_GENERIC (0xFF << BVSCALEDEF_VENDOR_SHIFT)
+
+/***** VENDOR_GENERIC definitions *****/
+/**** Bits 23-22 indicate classification ****/
+#define BVSCALEDEF_CLASS_SHIFT	22
+#define BVSCALEDEF_IMPLICIT	(0 << BVSCALEDEF_CLASS_SHIFT)
+#define BVSCALEDEF_EXPLICIT	(1 << BVSCALEDEF_CLASS_SHIFT)
+/* 2-3 reserved */
+#define BVSCALEDEF_CLASS_MASK	(3 << BVSCALEDEF_CLASS_SHIFT)
+
+/**** IMPLICIT definitions ****/
+/*** Bits 21-16 indicate the quality (speed) desired ***/
+#define BVSCALEDEF_QUALITY_SHIFT 16
+#define BVSCALEDEF_FASTEST	(0x00 << BVSCALEDEF_QUALITY_SHIFT)
+#define BVSCALEDEF_GOOD		(0x15 << BVSCALEDEF_QUALITY_SHIFT)
+#define BVSCALEDEF_BETTER	(0x2A << BVSCALEDEF_QUALITY_SHIFT)
+#define BVSCALEDEF_BEST		(0x3F << BVSCALEDEF_QUALITY_SHIFT)
+#define BVSCALEDEF_QUALITY_MASK	(0x3F << BVSCALEDEF_QUALITY_SHIFT)
+/* Bits 12-15 are reserved */
+/*** Bits 11-8 indicate the desired technique ***/
+#define BVSCALEDEF_TECHNIQUE_SHIFT 8
+#define BVSCALEDEF_DONT_CARE	(0x0 << BVSCALEDEF_TECHNIQUE_SHIFT)
+#define BVSCALEDEF_NOT_NEAREST_NEIGHBOR	(0x1 << BVSCALEDEF_TECHNIQUE_SHIFT)
+#define BVSCALEDEF_POINT_SAMPLE	(0x2 << BVSCALEDEF_TECHNIQUE_SHIFT)
+#define BVSCALEDEF_INTERPOLATED	(0x3 << BVSCALEDEF_TECHNIQUE_SHIFT)
+#define BVSCALEDEF_TECHNIQUE_MASK	(0xF << BVSCALEDEF_TECHNIQUE_SHIFT)
+/* Bits 2-7 reserved */
+/*** Bits 1-0 indicate the type of image ***/
+#define BVSCALEDEF_TYPE_SHIFT 0
+/* 0 don't know */
+#define BVSCALEDEF_PHOTO	(1 << BVSCALEDEF_TYPE_SHIFT)
+#define BVSCALEDEF_DRAWING	(2 << BVSCALEDEF_TYPE_SHIFT)
+/* 3 reserved */
+#define BVSCALEDEF_TYPE_MASK	(3 << BVSCALEDEF_TYPE_SHIFT)
+
+/**** EXPLICIT definitions ****/
+/* Bits 16-21 reserved */
+#define BVSCALEDEF_HORZ_SHIFT	8
+#define BVSCALEDEF_HORZ_MASK	(0xFF << BVSCALEDEF_HORZ_SHIFT)
+
+#define BVSCALEDEF_VERT_SHIFT	0
+#define BVSCALEDEF_VERT_MASK	(0xFF << BVSCALEDEF_VERT_SHIFT)
+
+#define BVSCALEDEF_NEAREST_NEIGHBOR	0x00
+#define BVSCALEDEF_LINEAR		0x01
+#define BVSCALEDEF_CUBIC		0x02
+#define	BVSCALEDEF_3_TAP		0x03
+/* 0x04 reserved */
+#define BVSCALEDEF_5_TAP		0x05
+/* 0x06 reserved */
+#define BVSCALEDEF_7_TAP		0x07
+/* 0x08 reserved */
+#define BVSCALEDEF_9_TAP		0x09
+/* 0x0A-0xFF reserved */
+
+enum bvscalemode {
+	BVSCALE_FASTEST =	BVSCALEDEF_VENDOR_ALL |
+				BVSCALEDEF_IMPLICIT |
+				BVSCALEDEF_FASTEST |
+				BVSCALEDEF_DONT_CARE,
+	BVSCALE_FASTEST_NOT_NEAREST_NEIGHBOR = BVSCALEDEF_VENDOR_ALL |
+				BVSCALEDEF_IMPLICIT |
+				BVSCALEDEF_FASTEST |
+				BVSCALEDEF_NOT_NEAREST_NEIGHBOR,
+	BVSCALE_FASTEST_POINT_SAMPLE = BVSCALEDEF_VENDOR_ALL |
+				BVSCALEDEF_IMPLICIT |
+				BVSCALEDEF_FASTEST |
+				BVSCALEDEF_POINT_SAMPLE,
+	BVSCALE_FASTEST_INTERPOLATED = BVSCALEDEF_VENDOR_ALL |
+				BVSCALEDEF_IMPLICIT |
+				BVSCALEDEF_FASTEST |
+				BVSCALEDEF_INTERPOLATED,
+	BVSCALE_FASTEST_PHOTO =	BVSCALEDEF_VENDOR_ALL |
+				BVSCALEDEF_IMPLICIT |
+				BVSCALEDEF_FASTEST |
+				BVSCALEDEF_PHOTO,
+	BVSCALE_FASTEST_DRAWING = BVSCALEDEF_VENDOR_ALL |
+				BVSCALEDEF_IMPLICIT |
+				BVSCALEDEF_FASTEST |
+				BVSCALEDEF_DRAWING,
+	BVSCALE_GOOD =		BVSCALEDEF_VENDOR_ALL |
+				BVSCALEDEF_IMPLICIT |
+				BVSCALEDEF_GOOD |
+				BVSCALEDEF_DONT_CARE,
+	BVSCALE_GOOD_POINT_SAMPLE = BVSCALEDEF_VENDOR_ALL |
+				BVSCALEDEF_IMPLICIT |
+				BVSCALEDEF_GOOD |
+				BVSCALEDEF_POINT_SAMPLE,
+	BVSCALE_GOOD_INTERPOLATED = BVSCALEDEF_VENDOR_ALL |
+				BVSCALEDEF_IMPLICIT |
+				BVSCALEDEF_GOOD |
+				BVSCALEDEF_INTERPOLATED,
+	BVSCALE_GOOD_PHOTO =	BVSCALEDEF_VENDOR_ALL |
+				BVSCALEDEF_IMPLICIT |
+				BVSCALEDEF_GOOD |
+				BVSCALEDEF_PHOTO,
+	BVSCALE_GOOD_DRAWING =	BVSCALEDEF_VENDOR_ALL |
+				BVSCALEDEF_IMPLICIT |
+				BVSCALEDEF_GOOD |
+				BVSCALEDEF_DRAWING,
+	BVSCALE_BETTER =	BVSCALEDEF_VENDOR_ALL |
+				BVSCALEDEF_IMPLICIT |
+				BVSCALEDEF_BETTER |
+				BVSCALEDEF_DONT_CARE,
+	BVSCALE_BETTER_POINT_SAMPLE = BVSCALEDEF_VENDOR_ALL |
+				BVSCALEDEF_IMPLICIT |
+				BVSCALEDEF_BETTER |
+				BVSCALEDEF_POINT_SAMPLE,
+	BVSCALE_BETTER_INTERPOLATED = BVSCALEDEF_VENDOR_ALL |
+				BVSCALEDEF_IMPLICIT |
+				BVSCALEDEF_BETTER |
+				BVSCALEDEF_INTERPOLATED,
+	BVSCALE_BETTER_PHOTO =	BVSCALEDEF_VENDOR_ALL |
+				BVSCALEDEF_IMPLICIT |
+				BVSCALEDEF_BETTER |
+				BVSCALEDEF_PHOTO,
+	BVSCALE_BETTER_DRAWING = BVSCALEDEF_VENDOR_ALL |
+				BVSCALEDEF_IMPLICIT |
+				BVSCALEDEF_BETTER |
+				BVSCALEDEF_DRAWING,
+	BVSCALE_BEST =		BVSCALEDEF_VENDOR_ALL |
+				BVSCALEDEF_IMPLICIT |
+				BVSCALEDEF_BEST |
+				BVSCALEDEF_DONT_CARE,
+	BVSCALE_BEST_POINT_SAMPLE = BVSCALEDEF_VENDOR_ALL |
+				BVSCALEDEF_IMPLICIT |
+				BVSCALEDEF_BEST |
+				BVSCALEDEF_POINT_SAMPLE,
+	BVSCALE_BEST_INTERPOLATED = BVSCALEDEF_VENDOR_ALL |
+				BVSCALEDEF_IMPLICIT |
+				BVSCALEDEF_BEST |
+				BVSCALEDEF_INTERPOLATED,
+	BVSCALE_BEST_PHOTO =	BVSCALEDEF_VENDOR_ALL |
+				BVSCALEDEF_IMPLICIT |
+				BVSCALEDEF_BEST |
+				BVSCALEDEF_PHOTO,
+	BVSCALE_BEST_DRAWING =	BVSCALEDEF_VENDOR_ALL |
+				BVSCALEDEF_IMPLICIT |
+				BVSCALEDEF_BEST |
+				BVSCALEDEF_DRAWING,
+
+	BVSCALE_NEAREST_NEIGHBOR = BVSCALEDEF_VENDOR_GENERIC |
+		BVSCALEDEF_EXPLICIT |
+		(BVSCALEDEF_NEAREST_NEIGHBOR << BVSCALEDEF_HORZ_SHIFT) |
+		(BVSCALEDEF_NEAREST_NEIGHBOR << BVSCALEDEF_VERT_SHIFT),
+	BVSCALE_BILINEAR = BVSCALEDEF_VENDOR_GENERIC |
+		BVSCALEDEF_EXPLICIT |
+		(BVSCALEDEF_LINEAR << BVSCALEDEF_HORZ_SHIFT) |
+		(BVSCALEDEF_LINEAR << BVSCALEDEF_VERT_SHIFT),
+	BVSCALE_BICUBIC = BVSCALEDEF_VENDOR_GENERIC |
+		BVSCALEDEF_EXPLICIT |
+		(BVSCALEDEF_CUBIC << BVSCALEDEF_HORZ_SHIFT) |
+		(BVSCALEDEF_CUBIC << BVSCALEDEF_VERT_SHIFT),
+	BVSCALE_3x3_TAP = BVSCALEDEF_VENDOR_GENERIC |
+		BVSCALEDEF_EXPLICIT |
+		(BVSCALEDEF_3_TAP << BVSCALEDEF_HORZ_SHIFT) |
+		(BVSCALEDEF_3_TAP << BVSCALEDEF_VERT_SHIFT),
+	BVSCALE_5x5_TAP = BVSCALEDEF_VENDOR_GENERIC |
+		BVSCALEDEF_EXPLICIT |
+		(BVSCALEDEF_5_TAP << BVSCALEDEF_HORZ_SHIFT) |
+		(BVSCALEDEF_5_TAP << BVSCALEDEF_VERT_SHIFT),
+	BVSCALE_7x7_TAP = BVSCALEDEF_VENDOR_GENERIC |
+		BVSCALEDEF_EXPLICIT |
+		(BVSCALEDEF_7_TAP << BVSCALEDEF_HORZ_SHIFT) |
+		(BVSCALEDEF_7_TAP << BVSCALEDEF_VERT_SHIFT),
+	BVSCALE_9x9_TAP = BVSCALEDEF_VENDOR_GENERIC |
+		BVSCALEDEF_EXPLICIT |
+		(BVSCALEDEF_9_TAP << BVSCALEDEF_HORZ_SHIFT) |
+		(BVSCALEDEF_9_TAP << BVSCALEDEF_VERT_SHIFT),
+
+#ifdef BVSCALE_EXTERNAL_INCLUDE
+#include BVSCALE_EXTERNAL_INCLUDE
+#endif
+};
+
+
+/*
+ * bvdithermode - This defines the type of dithering to use.
+ */
+#define BVDITHERDEF_VENDOR_SHIFT 24
+#define BVDITHERDEF_VENDOR_MASK (0xFF << BVDITHERDEF_VENDOR_SHIFT)
+
+#define BVDITHERDEF_VENDOR_ALL (0 << BVDITHERDEF_VENDOR_SHIFT)
+#define BVDITHERDEF_VENDOR_TI  (1 << BVDITHERDEF_VENDOR_SHIFT)
+/* 0xF0-0xFE reserved */
+#define BVDITHERDEF_VENDOR_GENERIC (0xFF << BVDITHERDEF_VENDOR_SHIFT)
+
+/***** VENDOR_GENERIC definitions *****/
+/* Bits 18-23 reserved */
+/**** Bits 17-16 indicate the type of image - 0 = don't know ****/
+#define BVDITHERDEF_TYPE_SHIFT 16
+#define BVDITHERDEF_PHOTO	(0x01 << BVDITHERDEF_TYPE_SHIFT)
+#define BVDITHERDEF_DRAWING	(0x02 << BVDITHERDEF_TYPE_SHIFT)
+/**** Bits 15-8 indicate the desired technique ****/
+#define BVDITHERDEF_TECHNIQUE_SHIFT 8
+#define BVDITHERDEF_DONT_CARE	(0x00 << BVDITHERDEF_TECHNIQUE_SHIFT)
+#define BVDITHERDEF_RANDOM	(0x01 << BVDITHERDEF_TECHNIQUE_SHIFT)
+#define BVDITHERDEF_ORDERED	(0x02 << BVDITHERDEF_TECHNIQUE_SHIFT)
+#define BVDITHERDEF_DIFFUSED	(0x04 << BVDITHERDEF_TECHNIQUE_SHIFT)
+#define BVDITHERDEF_ON		(0xFF << BVDITHERDEF_TECHNIQUE_SHIFT)
+/**** Bits 7-0 indicate the quality (speed) desired ****/
+#define BVDITHERDEF_QUALITY_SHIFT 0
+#define BVDITHERDEF_FASTEST	(0x00 << BVDITHERDEF_QUALITY_SHIFT)
+#define BVDITHERDEF_GOOD	(0x55 << BVDITHERDEF_QUALITY_SHIFT)
+#define BVDITHERDEF_BETTER	(0xAA << BVDITHERDEF_QUALITY_SHIFT)
+#define BVDITHERDEF_BEST	(0xFF << BVDITHERDEF_QUALITY_SHIFT)
+
+enum bvdithermode {
+	BVDITHER_FASTEST =	BVDITHERDEF_VENDOR_ALL |
+				BVDITHERDEF_FASTEST |
+				BVDITHERDEF_DONT_CARE,
+	BVDITHER_FASTEST_ON =	BVDITHERDEF_VENDOR_ALL |
+				BVDITHERDEF_FASTEST |
+				BVDITHERDEF_ON,
+	BVDITHER_FASTEST_RANDOM = BVDITHERDEF_VENDOR_ALL |
+				BVDITHERDEF_FASTEST |
+				BVDITHERDEF_RANDOM,
+	BVDITHER_FASTEST_ORDERED = BVDITHERDEF_VENDOR_ALL |
+				BVDITHERDEF_FASTEST |
+				BVDITHERDEF_ORDERED,
+	BVDITHER_FASTEST_DIFFUSED = BVDITHERDEF_VENDOR_ALL |
+				BVDITHERDEF_FASTEST |
+				BVDITHERDEF_DIFFUSED,
+	BVDITHER_FASTEST_PHOTO = BVDITHERDEF_VENDOR_ALL |
+				BVDITHERDEF_FASTEST |
+				BVDITHERDEF_PHOTO,
+	BVDITHER_FASTEST_DRAWING = BVDITHERDEF_VENDOR_ALL |
+				BVDITHERDEF_FASTEST |
+				BVDITHERDEF_DRAWING,
+	BVDITHER_GOOD =		BVDITHERDEF_VENDOR_ALL |
+				BVDITHERDEF_GOOD |
+				BVDITHERDEF_DONT_CARE,
+	BVDITHER_GOOD_ON =	BVDITHERDEF_VENDOR_ALL |
+				BVDITHERDEF_GOOD |
+				BVDITHERDEF_ON,
+	BVDITHER_GOOD_RANDOM = BVDITHERDEF_VENDOR_ALL |
+				BVDITHERDEF_GOOD |
+				BVDITHERDEF_RANDOM,
+	BVDITHER_GOOD_ORDERED = BVDITHERDEF_VENDOR_ALL |
+				BVDITHERDEF_GOOD |
+				BVDITHERDEF_ORDERED,
+	BVDITHER_GOOD_DIFFUSED = BVDITHERDEF_VENDOR_ALL |
+				BVDITHERDEF_GOOD |
+				BVDITHERDEF_DIFFUSED,
+	BVDITHER_GOOD_PHOTO =	BVDITHERDEF_VENDOR_ALL |
+				BVDITHERDEF_GOOD |
+				BVDITHERDEF_PHOTO,
+	BVDITHER_GOOD_DRAWING = BVDITHERDEF_VENDOR_ALL |
+				BVDITHERDEF_GOOD |
+				BVDITHERDEF_DRAWING,
+	BVDITHER_BETTER =	BVDITHERDEF_VENDOR_ALL |
+				BVDITHERDEF_BETTER |
+				BVDITHERDEF_DONT_CARE,
+	BVDITHER_BETTER_ON =	BVDITHERDEF_VENDOR_ALL |
+				BVDITHERDEF_BETTER |
+				BVDITHERDEF_ON,
+	BVDITHER_BETTER_RANDOM = BVDITHERDEF_VENDOR_ALL |
+				BVDITHERDEF_BETTER |
+				BVDITHERDEF_RANDOM,
+	BVDITHER_BETTER_ORDERED = BVDITHERDEF_VENDOR_ALL |
+				BVDITHERDEF_BETTER |
+				BVDITHERDEF_ORDERED,
+	BVDITHER_BETTER_DIFFUSED = BVDITHERDEF_VENDOR_ALL |
+				BVDITHERDEF_BETTER |
+				BVDITHERDEF_DIFFUSED,
+	BVDITHER_BETTER_PHOTO =	BVDITHERDEF_VENDOR_ALL |
+				BVDITHERDEF_BETTER |
+				BVDITHERDEF_PHOTO,
+	BVDITHER_BETTER_DRAWING = BVDITHERDEF_VENDOR_ALL |
+				BVDITHERDEF_BETTER |
+				BVDITHERDEF_DRAWING,
+	BVDITHER_BEST =		BVDITHERDEF_VENDOR_ALL |
+				BVDITHERDEF_BEST |
+				BVDITHERDEF_DONT_CARE,
+	BVDITHER_BEST_ON =	BVDITHERDEF_VENDOR_ALL |
+				BVDITHERDEF_BEST |
+				BVDITHERDEF_ON,
+	BVDITHER_BEST_RANDOM = BVDITHERDEF_VENDOR_ALL |
+				BVDITHERDEF_BEST |
+				BVDITHERDEF_RANDOM,
+	BVDITHER_BEST_ORDERED = BVDITHERDEF_VENDOR_ALL |
+				BVDITHERDEF_BEST |
+				BVDITHERDEF_ORDERED,
+	BVDITHER_BEST_DIFFUSED = BVDITHERDEF_VENDOR_ALL |
+				BVDITHERDEF_BEST |
+				BVDITHERDEF_DIFFUSED,
+	BVDITHER_BEST_PHOTO = BVDITHERDEF_VENDOR_ALL |
+				BVDITHERDEF_BEST |
+				BVDITHERDEF_PHOTO,
+	BVDITHER_BEST_DRAWING = BVDITHERDEF_VENDOR_ALL |
+				BVDITHERDEF_BEST |
+				BVDITHERDEF_DRAWING,
+
+	BVDITHER_NONE =		BVDITHERDEF_VENDOR_GENERIC + 0,
+	BVDITHER_ORDERED_2x2 =	BVDITHERDEF_VENDOR_GENERIC + 4,
+	BVDITHER_ORDERED_4x4 =	BVDITHERDEF_VENDOR_GENERIC + 16,
+	BVDITHER_ORDERED_2x2_4x4 = BVDITHERDEF_VENDOR_GENERIC + 4 + 16,
+					/* 2x2 for 6->8, 4x4 for 5->8 */
+
+#ifdef BVDITHER_EXTERNAL_INCLUDE
+#include BVDITHER_EXTERNAL_INCLUDE
+#endif
+};
+
+
+/*
+ * BVTILE_* flags - These specify parameters used when tiling.
+ */
+#define BVTILE_LEFT_SHIFT    0
+#define BVTILE_TOP_SHIFT     (BVTILE_LEFT_SHIFT + 2)
+#define BVTILE_RIGHT_SHIFT   (BVTILE_TOP_SHIFT + 2)
+#define BVTILE_BOTTOM_SHIFT  (BVTILE_RIGHT_SHIFT + 2)
+#define BVTILE_LEFT_REPEAT   (0 << BVTILE_LEFT_SHIFT)	/* ...012301230123 */
+#define BVTILE_TOP_REPEAT    (0 << BVTILE_TOP_SHIFT)	/* ...012301230123 */
+#define BVTILE_RIGHT_REPEAT  (0 << BVTILE_RIGHT_SHIFT)	/* 012301230123... */
+#define BVTILE_BOTTOM_REPEAT (0 << BVTILE_BOTTOM_SHIFT)	/* 012301230123... */
+#define BVTILE_LEFT_MIRROR   (1 << BVTILE_LEFT_SHIFT)	/* ...012332100123 */
+#define BVTILE_TOP_MIRROR    (1 << BVTILE_TOP_SHIFT)	/* ...012332100123 */
+#define BVTILE_RIGHT_MIRROR  (1 << BVTILE_RIGHT_SHIFT)	/* 012332100123... */
+#define BVTILE_BOTTOM_MIRROR (1 << BVTILE_BOTTOM_SHIFT)	/* 012332100123... */
+
+/*
+ * bvtileparams - This structure provides additional parameters needed when
+ * tiling.  This structure replaces the bvbuffdesc in bvbltparams when the
+ * associated BVFLAG_TILE_* flag is set in bvbltparams.flags.
+ */
+struct bvtileparams {
+	unsigned int structsize; /* used to ID structure version */
+	unsigned long flags;	 /* tile flags */
+	void *virtaddr;		 /* pointer to the brush */
+	int dstleft;		 /* horizontal offset */
+	int dsttop;		 /* vertical offset */
+	unsigned int srcwidth;	 /* w/dst width to spec horz scale */
+	unsigned int srcheight;	 /* w/dst height to spec vert scale */
+};
+
+/*
+ * BVBATCH_* - These flags specify the parameters that change between
+ * batched BLTs, when BVFLAG_CONTINUE or BVFLAG_END set.
+ */
+#define BVBATCH_OP		0x00000001 /* type of operation changed */
+#define BVBATCH_KEY		0x00000002 /* color key changed */
+#define BVBATCH_MISCFLAGS	0x00000004 /* other flags changed */
+#define BVBATCH_ALPHA		0x00000008 /* global alpha changed */
+#define BVBATCH_DITHER		0x00000010 /* dither changed */
+#define BVBATCH_SCALE		0x00000020 /* scaling type changed */
+/* Bits 6-7 reserved */
+#define BVBATCH_DST		0x00000100 /* destination surface changed */
+#define BVBATCH_SRC1		0x00000200 /* source 1 surface changed */
+#define BVBATCH_SRC2		0x00000400 /* source 2 surface changed */
+#define BVBATCH_MASK		0x00000800 /* mask surface changed */
+#define BVBATCH_DSTRECT_ORIGIN	0x00001000 /* dest rect origin changed */
+#define BVBATCH_DSTRECT_SIZE	0x00002000 /* dest rect dimensions changed */
+#define BVBATCH_SRC1RECT_ORIGIN	0x00004000 /* src 1 rect origin changed */
+#define BVBATCH_SRC1RECT_SIZE	0x00008000 /* src 1 rect dimensions changed */
+#define BVBATCH_SRC2RECT_ORIGIN	0x00010000 /* src 2 rect origin changed */
+#define BVBATCH_SRC2RECT_SIZE	0x00020000 /* src 2 rect dimensions changed */
+#define BVBATCH_MASKRECT_ORIGIN	0x00040000 /* mask rect origin changed */
+#define BVBATCH_MASKRECT_SIZE	0x00080000 /* mask rect dimensions changed */
+#define BVBATCH_CLIPRECT_ORIGIN	0x00100000 /* Clip rect origin changed */
+#define BVBATCH_CLIPRECT_SIZE	0x00200000 /* Clip rect dimensions changed */
+#define BVBATCH_CLIPRECT	(BVBATCH_CLIPRECT_ORIGIN | \
+				 BVBATCH_CLIPRECT_SIZE)	/* clip rect... */
+							/* ...changed */
+#define BVBATCH_TILE_SRC1	0x00400000 /* tile params for src 1 changed */
+#define BVBATCH_TILE_SRC2	0x00800000 /* tile params for src 2 changed */
+#define BVBATCH_TILE_MASK	0x00100000 /* tile params for mask changed */
+/* Bits 21-30 reserved */
+#define BVBATCH_ENDNOP		0x80000000 /* just end batch, don't do BLT;
+					      only with BVFLAG_BATCH_END */
+
+/*
+ * bvcallbackerror - This structure is passed into the callback function
+ * if an error occurs.
+ */
+struct bvcallbackerror {
+	unsigned int structsize;	/* used to ID structure version */
+	enum bverror error;		/* error during async BLT */
+	char *errdesc;			/* 0-terminated ASCII string
+					   with extended error info (not
+					   for end users) */
+};
+
+/*
+ * bvbatch - an implementation-specific container for batch information;
+ * not used by client; forward declaration here
+ */
+struct bvbatch;
+
+/*
+ * bvinbuff - provides the buffer in bvbltparams
+ */
+union bvinbuff {
+	struct bvbuffdesc *desc;	 /* buffer description when
+					    associated BVFLAG_TILE_*
+					    is not set */
+	struct bvtileparams *tileparams; /* tile params when associated
+					    BVFLAG_TILE_* flag is set */
+};
+
+/*
+ * bvop - used to hold the operation in bvbltparams
+ */
+union bvop {
+	unsigned short rop;		/* when BVFLAG_ROP set */
+	enum bvblend blend;		/* when BVFLAG_BLEND set */
+	struct bvfilter *filter;	/* when BVFLAG_FILTER set */
+};
+
+
+/*
+ * bvbltparams - This structure is passed into bv_blt() to specify the
+ * parameters for a BLT.
+ */
+struct bvbltparams {
+	unsigned int structsize;	/* (i) used to ID structure version */
+	char *errdesc;			/* (o) 0-terminated ASCII string
+					       with extended error info (not
+					       for end users) */
+
+	unsigned long implementation;	/* (i) override manager choice */
+
+	unsigned long flags;		/* (i) see BVFLAG_* above */
+
+	union bvop op;			/* (i) operation; determined by
+					       BVFLAG_OP_MASK bits in flags */
+
+	void *colorkey;			/* (i) pointer to color key pixel
+					       matching non-SUBSAMPLE format
+					       of the keyed surface when
+					       BVFLAG_KEY_* is set */
+
+	union bvalpha globalalpha;	/* (i) global alpha when BVFLAG_BLEND
+					       set in flags and
+					       BVBLENDDEF_GLOBAL_* is set in
+					       blend; typed determined by
+					       BVBLENDDEF_GLOBAL_* */
+
+	enum bvscalemode scalemode;	/* (i/o) type of scaling */
+	enum bvdithermode dithermode;	/* (i/o) type of dither */
+
+	struct bvbuffdesc *dstdesc;	/* (i) dest after bv_map() */
+	struct bvsurfgeom *dstgeom;	/* (i) dest surf fmt and geometry */
+	struct bvrect dstrect;		/* (i) rect into which data written */
+
+	union bvinbuff src1;		/* (i) src1 buffer */
+	struct bvsurfgeom *src1geom;	/* (i) src1 surf fmt and geometry */
+	struct bvrect src1rect;		/* (i) rect from which data is read */
+
+	union bvinbuff src2;		/* (i) src2 buffer */
+	struct bvsurfgeom *src2geom;	/* (i) src2 surf fmt and geometry */
+	struct bvrect src2rect;		/* (i) rect from which data is read */
+
+	union bvinbuff mask;		/* (i) mask buffer */
+	struct bvsurfgeom *maskgeom;	/* (i) mask surf fmt and geometry */
+	struct bvrect maskrect;		/* (i) rect from which data is read */
+
+	struct bvrect cliprect;		/* (i) dest clipping rect when
+					       BVFLAG_CLIP flag set */
+
+	unsigned long batchflags;	/* (i) BVBATCH_* flags used to
+					       indicate params changed between
+					       batch BLTs */
+	struct bvbatch *batch;		/* (i/o) handle for associated batch;
+						 returned when
+						 BVFLAG_BATCH_BEGIN set;
+						 provided to subsequent BLTs
+						 with BVFLAG_BATCH_CONTINUE */
+
+	void (*callbackfn)(struct bvcallbackerror *err,
+			   unsigned long callbackdata); /* (i) callback
+							 function when
+							 BVFLAG_ASYNC is set -
+							 err is 0 when no
+							 error; handle contains
+							 callbackdata below */
+	unsigned long callbackdata;	/* (i) callback data */
+
+	struct bvrect src2auxdstrect;
+	struct bvrect maskauxdstrect;
+};
+
+#endif /* BLTSVILLE_H */
diff --git a/bltsville/bltsville/include/bvblend.h b/bltsville/bltsville/include/bvblend.h
new file mode 100644
index 0000000..f187d81
--- /dev/null
+++ b/bltsville/bltsville/include/bvblend.h
@@ -0,0 +1,508 @@
+/*
+ * bvblend.h
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ *
+ * This file is part of BLTsville, an open application programming interface
+ * (API) for accessing 2-D software or hardware implementations.
+ *
+ * This work is licensed under the Creative Commons Attribution-NoDerivs 3.0
+ * Unported License. To view a copy of this license, visit
+ * http://creativecommons.org/licenses/by-nd/3.0/ or send a letter to
+ * Creative Commons, 444 Castro Street, Suite 900, Mountain View, California,
+ * 94041, USA.
+ */
+
+/*
+ * This file defines the types of shared blends available.
+ *
+ * To extend the list of blends, create a file containing additional
+ * enumerations to be added to enum bvblend below.  Then #define
+ * BVBLEND_EXTERNAL_INCLUDE as the name of that file before including
+ * this file in your project.
+ */
+
+#ifndef BVBLEND_H
+#define BVBLEND_H
+
+/*
+ * bvblend - specifies the type of blending operation to perform; only valid
+ *	     when BVFLAG_BLEND is set in the bvbltparams.flags field.
+ */
+
+/*
+ * The blendmode value is divided into two sections.
+ *
+ * [31:28] The most significant 4 bits indicate the blend format.
+ *
+ * [27:0] The remainder of the bits is defined by the format chosen.
+ *
+ *   3322222222221111111111
+ *   10987654321098765432109876543210
+ *   [  ][                          ]
+ *    |               |
+ *  format    defined by format
+ */
+
+#define BVBLENDDEF_FORMAT_SHIFT 28
+#define BVBLENDDEF_FORMAT_MASK (0xF << BVBLENDDEF_FORMAT_SHIFT)
+
+#define BVBLENDDEF_FORMAT_CLASSIC	(0x0 << BVBLENDDEF_FORMAT_SHIFT)
+#define BVBLENDDEF_FORMAT_ESSENTIAL	(0x1 << BVBLENDDEF_FORMAT_SHIFT)
+
+/*
+ * The BVBLENDDEF_FORMAT_CLASSIC is meant to handle the classic Porter-Duff
+ * equations.  It can also handle the DirectFB blending.
+ * BVBLENDDEF_FORMAT_CLASSIC is based on the following equations:
+ *
+ *   Cd = K1 x C1 + K2 x C2
+ *   Ad = K3 x A1 + K4 x A2
+ *
+ * where:
+ *   Cd: destination color
+ *   C1: source 1 color
+ *   C2: source 2 color
+ *   Ad: destination alpha
+ *   A1: source 1 alpha
+ *   A2: source 2 alpha
+ *   K#: one of the constants defined using the bitfields below.
+ */
+
+/*
+ *  The 28 bits for BVBLENDDEF_FORMAT_CLASSIC are divided into 5 sections.
+ *
+ *  The most significant 4 bits are modifiers, used to include additional
+ *  alpha values from global or remote sources.
+ *
+ *  [27] The most significant bit indicates that a remote alpha is to be
+ *  included in the blend.  The format of this is defined by
+ *  bvbltparams.maskgeom.format.
+ *
+ *  [26] The next bit is reserved.
+ *
+ *  [25:24] The next 2 bits are used to indicate that a global alpha is to be
+ *  included, and what its format is:
+ *    00: no global included
+ *    01: global included; bvbltparams.globalalpha.size8 is used (0 -> 255)
+ *    10: this value is reserved
+ *    11: global included; bvbltparams.flogalalpha.fp is used (0.0 -> 1.0)
+ *
+ *  The remaining bits are divided into 4 sections, one to define each of the
+ *  constants:
+ *
+ *  [23:18] - K1
+ *  [17:12] - K2
+ *  [11:6]  - K3
+ *  [5:0]   - K4
+ *
+ *  The format is the same for all 4 constant fields:
+ *
+ *  [5:4] The first 2 bits of each field indicates the way in which the other
+ *  2 fields are interpreted:
+ *    00: only As: the other two fields contain only As; there should be only
+ *                 one valid A value between the two fields
+ *    01: minimum: the value of the constant is the minimum of the two fields
+ *    10: maximum: the value of the constant is the maximum of the two fields
+ *    11: only Cs: the other two fields contain only Cs; there should be only
+ *                 one valid C value between the two fields
+ *
+ *  [3:2] The middle 2 bits of each field contain the inverse field:
+ *    00: 1-C1 ("don't care" for "only As")
+ *    01: 1-A1 ("don't care" for "only Cs")
+ *    10: 1-C2 ("don't care" for "only As")
+ *    11: 1-A2 ("don't care" for "only Cs")
+ *
+ *  [1:0] The last 2 bits if each field contain the normal field:
+ *    00: C1 ("don't care" for "only As")
+ *    01: A1 ("don't care" for "only Cs")
+ *    10: C2 ("don't care" for "only As")
+ *    11: A2 ("don't care" for "only Cs")
+ *
+ *  EXCEPTIONS:
+ *
+ *  00 00 00 - The value 00 00 00, which normally would indicate "only As"
+ *             with two "don't care" fields, is interpreted as a 0.
+ *
+ *  11 11 11 - The value 11 11 11, which normally would indicate "only Cs"
+ *             with two "don't care" fields, is interpreted as a 1.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Put together, these can define portions of the blend equations that can be
+ * put together in a variety of ways:
+ *
+ *   00 00 00: undefined -> zero
+ *   00 00 01: A1 (preferred)
+ *   00 00 10: undefined
+ *   00 00 11: A2 (preferred)
+ *   00 01 00: 1-A1 (preferred)
+ *   00 01 01: undefined
+ *   00 01 10: 1-A1 (use 00 01 00)
+ *   00 01 11: undefined
+ *   00 10 00: undefined
+ *   00 10 01: A1 (use 00 00 01)
+ *   00 10 10: undefined
+ *   00 10 11: A2 (use 00 00 11)
+ *   00 11 00: 1-A2 (preferred)
+ *   00 11 01: undefined
+ *   00 11 10: 1-A2 (use 00 11 00)
+ *   00 11 11: undefined
+ *
+ *   01 00 00: min(C1,1-C1)
+ *   01 00 01: min(A1,1-C1)
+ *   01 00 10: min(C2,1-C1)
+ *   01 00 11: min(A2,1-C1)
+ *   01 01 00: min(C1,1-A1)
+ *   01 01 01: min(A1,1-A1)
+ *   01 01 10: min(C2,1-A1)
+ *   01 01 11: min(A2,1-A1)
+ *   01 10 00: min(C1,1-C2)
+ *   01 10 01: min(A1,1-C2)
+ *   01 10 10: min(C2,1-C2)
+ *   01 10 11: min(A2,1-C2)
+ *   01 11 00: min(C1,1-A2)
+ *   01 11 01: min(A1,1-A2)
+ *   01 11 10: min(C2,1-A2)
+ *   01 11 11: min(A2,1-A2)
+ *
+ *   10 00 00: max(C1,1-C1)
+ *   10 00 01: max(A1,1-C1)
+ *   10 00 10: max(C2,1-C1)
+ *   10 00 11: max(A2,1-C1)
+ *   10 01 00: max(C1,1-A1)
+ *   10 01 01: max(A1,1-A1)
+ *   10 01 10: max(C2,1-A1)
+ *   10 01 11: max(A2,1-A1)
+ *   10 10 00: max(C1,1-C2)
+ *   10 10 01: max(A1,1-C2)
+ *   10 10 10: max(C2,1-C2)
+ *   10 10 11: max(A2,1-C2)
+ *   10 11 00: max(C1,1-A2)
+ *   10 11 01: max(A1,1-A2)
+ *   10 11 10: max(C2,1-A2)
+ *   10 11 11: max(A2,1-A2)
+ *
+ *   11 00 00: undefined
+ *   11 00 01: 1-C1 (use 11 00 11)
+ *   11 00 10: undefined
+ *   11 00 11: 1-C1 (preferred)
+ *   11 01 00: C1 (use 11 11 00)
+ *   11 01 01: undefined
+ *   11 01 10: C2 (use 11 11 10)
+ *   11 01 11: undefined
+ *   11 10 00: undefined
+ *   11 10 01: 1-C2 (use 11 10 11)
+ *   11 10 10: undefined
+ *   11 10 11: 1-C2 (preferred)
+ *   11 11 00: C1 (preferred)
+ *   11 11 01: undefined
+ *   11 11 10: C2 (preferred)
+ *   11 11 11: undefined -> one
+ *
+ * ==========================================================================
+ * DirectFB
+ * ==========================================================================
+ *
+ * Putting these together into the proper constants, the blending equations
+ * can be built for DirectFB as well:
+ *
+ * For DirectFB, the SetSrcBlendFunction() and SetDstBlendFunction() can
+ * specify 121 combinations of blends (11 x 11). It's impractical to
+ * specify these combinations individually. Instead, the settings indicated
+ * by each call should be bitwise OR'd to make the proper single value used in
+ * BLTsville.
+ *
+ * binary value <- SetSrcBlendFunction()
+ *           [--K1--] [--K2--] [--K3--] [--K4--]
+ * 0000 0000 00 00 00 xx xx xx 00 00 00 xx xx xx <- DSBF_ZERO
+ * 0000 0000 11 11 11 xx xx xx 11 11 11 xx xx xx <- DSBF_ONE
+ * 0000 0000 11 11 00 xx xx xx 00 00 01 xx xx xx <- DSBF_SRCCOLOR
+ * 0000 0000 11 00 11 xx xx xx 00 01 00 xx xx xx <- DSBF_INVSRCCOLOR
+ * 0000 0000 00 00 01 xx xx xx 00 00 01 xx xx xx <- DSBF_SRCALPHA
+ * 0000 0000 00 01 00 xx xx xx 00 01 00 xx xx xx <- DSBF_INVSRCALPHA
+ * 0000 0000 11 11 10 xx xx xx 00 00 11 xx xx xx <- DSBF_DESTCOLOR
+ * 0000 0000 11 10 11 xx xx xx 00 11 00 xx xx xx <- DSBF_INVDESTCOLOR
+ * 0000 0000 00 00 11 xx xx xx 00 00 11 xx xx xx <- DSBF_DESTALPHA
+ * 0000 0000 00 11 00 xx xx xx 00 11 00 xx xx xx <- DSBF_INVDESTALPHA
+ * 0000 0000 01 11 01 xx xx xx 11 11 11 xx xx xx <- DSBF_SRCALPHASAT
+ *
+ * binary value <- SetDstBlendFunction()
+ *           [--K1--] [--K2--] [--K3--] [--K4--]
+ * 0000 0000 xx xx xx 00 00 00 xx xx xx 00 00 00 <- DSBF_ZERO
+ * 0000 0000 xx xx xx 11 11 11 xx xx xx 11 11 11 <- DSBF_ONE
+ * 0000 0000 xx xx xx 11 11 00 xx xx xx 00 00 01 <- DSBF_SRCCOLOR
+ * etc.
+ *
+ * ==========================================================================
+ * Porter-Duff
+ * ==========================================================================
+ *
+ * For Porter-Duff, the equations can be more specifically defined. For
+ * convenience, these are enumerated below. These utilize the local alpha as
+ * indicated. To use global or remote alpha, these enumerations need to be
+ * modified. For example, to include the global alpha in the Porter-Duff
+ * SRC1OVER blend, the blend could be defined like this:
+ *   params.op.blend = BVBLEND_SRC1OVER +
+ *                     BVBLENDDEF_GLOBAL_UCHAR;
+ *
+ * To include the remote alpha, the blend could be defined like this:
+ *   params.op.blend = BVBLEND_SRC1OVER +
+ *                     BVBLENDDEF_REMOTE;
+ *
+ * And to include both:
+ *   params.op.blend = BVBLEND_SRC1OVER +
+ *                     BVBLENDDEF_GLOBAL_UCHAR +
+ *                     BVBLENDDEF_REMOTE;
+ *
+ * Note that if the source color formats include local alphas, the local
+ * alphas, global alpha, and remote alpha will be used together.
+ *
+ * Note also that the equations assume the surfaces are premultiplied. So
+ * if the surface formats indicate that they are not premultiplied, the
+ * alpha multiplication of each color is done prior to using the surface
+ * values in the equations.
+ *
+ * For example, BVBLEND_SRC1OVER specifies the equations:
+ *   Cd = 1 x C1 + (1 - A1) x C2
+ *   Ad = 1 x A1 + (1 - A1) x A2
+ *
+ * If the format of surface 1 is non-premultiplied, the equations
+ * are modified to include the multiplication explicitly:
+ *   Cd = 1 x A1 x C1 + (1 - A1) x C2
+ *   Ad = 1 x A1      + (1 - A1) x A2
+ *
+ * Likewise, if the format of surface 2 is non-premultiplied, the
+ * equations are modified for this:
+ *   Cd = 1 x C1 + (1 - A1) x A2 x C2
+ *   Ad = 1 x A1 + (1 - A1) x A2
+ *
+ * When including global or remote alphas, these values are used to modify
+ * the source 1 value values before being used in the blend equation:
+ *   C1 = Ag x C1
+ *   A1 = Ag x A1
+ *       -or-
+ *   C1 = Ar x C1
+ *   A1 = Ar x A1
+ *       -or-
+ *   C1 = Ag x Ar x C1
+ *   A1 = Ag x Ar x A1
+ *
+ */
+
+#define BVBLENDDEF_MODE_SHIFT	4
+#define BVBLENDDEF_INV_SHIFT	2
+#define BVBLENDDEF_NORM_SHIFT	0
+
+#define BVBLENDDEF_ONLY_A	(0 << BVBLENDDEF_MODE_SHIFT)
+#define BVBLENDDEF_MIN		(1 << BVBLENDDEF_MODE_SHIFT)
+#define BVBLENDDEF_MAX		(2 << BVBLENDDEF_MODE_SHIFT)
+#define BVBLENDDEF_ONLY_C	(3 << BVBLENDDEF_MODE_SHIFT)
+#define BVBLENDDEF_MODE_MASK	(3 << BVBLENDDEF_MODE_SHIFT)
+
+#define BVBLENDDEF_NORM_C1	(0 << BVBLENDDEF_NORM_SHIFT)
+#define BVBLENDDEF_NORM_A1	(1 << BVBLENDDEF_NORM_SHIFT)
+#define BVBLENDDEF_NORM_C2	(2 << BVBLENDDEF_NORM_SHIFT)
+#define BVBLENDDEF_NORM_A2	(3 << BVBLENDDEF_NORM_SHIFT)
+#define BVBLENDDEF_NORM_MASK	(3 << BVBLENDDEF_NORM_SHIFT)
+
+#define BVBLENDDEF_INV_C1	(0 << BVBLENDDEF_INV_SHIFT)
+#define BVBLENDDEF_INV_A1	(1 << BVBLENDDEF_INV_SHIFT)
+#define BVBLENDDEF_INV_C2	(2 << BVBLENDDEF_INV_SHIFT)
+#define BVBLENDDEF_INV_A2	(3 << BVBLENDDEF_INV_SHIFT)
+#define BVBLENDDEF_INV_MASK	(3 << BVBLENDDEF_INV_SHIFT)
+
+#define BVBLENDDEF_ONLY_A_NORM_xx	BVBLENDDEF_NORM_C1
+#define BVBLENDDEF_ONLY_A_INV_xx	BVBLENDDEF_INV_C1
+#define BVBLENDDEF_ONLY_C_NORM_xx	BVBLENDDEF_NORM_A2
+#define BVBLENDDEF_ONLY_C_INV_xx	BVBLENDDEF_INV_A2
+
+#define BVBLENDDEF_ZERO \
+	(BVBLENDDEF_ONLY_A | \
+	 BVBLENDDEF_ONLY_A_NORM_xx | \
+	 BVBLENDDEF_ONLY_A_INV_xx)
+#define BVBLENDDEF_C1 \
+	(BVBLENDDEF_ONLY_C | \
+	 BVBLENDDEF_NORM_C1 | \
+	 BVBLENDDEF_ONLY_C_INV_xx)
+#define BVBLENDDEF_A1 \
+	(BVBLENDDEF_ONLY_A | \
+	 BVBLENDDEF_NORM_A1 | \
+	 BVBLENDDEF_ONLY_A_INV_xx)
+#define BVBLENDDEF_C2 \
+	(BVBLENDDEF_ONLY_C | \
+	 BVBLENDDEF_NORM_C2 | \
+	 BVBLENDDEF_ONLY_C_INV_xx)
+#define BVBLENDDEF_A2 \
+	(BVBLENDDEF_ONLY_A | \
+	 BVBLENDDEF_NORM_A2 | \
+	 BVBLENDDEF_ONLY_A_INV_xx)
+#define BVBLENDDEF_ONE_MINUS_C1 \
+	(BVBLENDDEF_ONLY_C | \
+	 BVBLENDDEF_ONLY_C_NORM_xx | \
+	 BVBLENDDEF_INV_C1)
+#define BVBLENDDEF_ONE_MINUS_A1 \
+	(BVBLENDDEF_ONLY_A | \
+	 BVBLENDDEF_ONLY_A_NORM_xx | \
+	 BVBLENDDEF_INV_A1)
+#define BVBLENDDEF_ONE_MINUS_C2 \
+	(BVBLENDDEF_ONLY_C | \
+	 BVBLENDDEF_ONLY_C_NORM_xx | \
+	 BVBLENDDEF_INV_C2)
+#define BVBLENDDEF_ONE_MINUS_A2 \
+	(BVBLENDDEF_ONLY_A | \
+	 BVBLENDDEF_ONLY_A_NORM_xx | \
+	 BVBLENDDEF_INV_A2)
+#define BVBLENDDEF_ONE \
+	(BVBLENDDEF_ONLY_C | \
+	 BVBLENDDEF_ONLY_C_NORM_xx | \
+	 BVBLENDDEF_ONLY_C_INV_xx)
+
+#define BVBLENDDEF_K_MASK \
+	(BVBLENDDEF_MODE_MASK | \
+	 BVBLENDDEF_INV_MASK  | \
+	 BVBLENDDEF_NORM_MASK)
+
+#define BVBLENDDEF_K1_SHIFT 18
+#define BVBLENDDEF_K2_SHIFT 12
+#define BVBLENDDEF_K3_SHIFT 6
+#define BVBLENDDEF_K4_SHIFT 0
+
+#define BVBLENDDEF_K1_MASK \
+	(BVBLENDDEF_K_MASK << BVBLENDDEF_K1_SHIFT)
+#define BVBLENDDEF_K2_MASK \
+	(BVBLENDDEF_K_MASK << BVBLENDDEF_K2_SHIFT)
+#define BVBLENDDEF_K3_MASK \
+	(BVBLENDDEF_K_MASK << BVBLENDDEF_K3_SHIFT)
+#define BVBLENDDEF_K4_MASK \
+	(BVBLENDDEF_K_MASK << BVBLENDDEF_K4_SHIFT)
+
+#define BVBLENDDEF_CLASSIC_EQUATION_MASK 0x00FFFFFF
+
+/*
+ * The following definitions are be used to modify the enumerations.
+ */
+#define BVBLENDDEF_REMOTE	0x08000000	/* mask surface provides alpha
+						   for source 1 */
+
+/* Bit 26 reserved */
+
+/* These enable global alpha and define the type of globalalpha */
+#define BVBLENDDEF_GLOBAL_SHIFT 24
+#define BVBLENDDEF_GLOBAL_MASK	(3 << BVBLENDDEF_GLOBAL_SHIFT)
+
+#define BVBLENDDEF_GLOBAL_NONE	(0 << BVBLENDDEF_GLOBAL_SHIFT)
+#define BVBLENDDEF_GLOBAL_UCHAR	(1 << BVBLENDDEF_GLOBAL_SHIFT)
+/* 2 reserved */
+#define BVBLENDDEF_GLOBAL_FLOAT	(3 << BVBLENDDEF_GLOBAL_SHIFT)
+
+union bvalpha {
+	unsigned char size8;	/* btwn 0 (0.0) and 255 (1.0) */
+	float fp;		/* btwn 0.0 and 1.0 */
+};
+
+
+enum bvblend {
+  /* Porter-Duff blending equations */
+	BVBLEND_CLEAR = BVBLENDDEF_FORMAT_CLASSIC |
+			(BVBLENDDEF_ZERO << BVBLENDDEF_K1_SHIFT) |
+			(BVBLENDDEF_ZERO << BVBLENDDEF_K2_SHIFT) |
+			(BVBLENDDEF_ZERO << BVBLENDDEF_K3_SHIFT) |
+			(BVBLENDDEF_ZERO << BVBLENDDEF_K4_SHIFT),
+	BVBLEND_SRC1 =	BVBLENDDEF_FORMAT_CLASSIC |
+			(BVBLENDDEF_ONE << BVBLENDDEF_K1_SHIFT) |
+			(BVBLENDDEF_ZERO << BVBLENDDEF_K2_SHIFT) |
+			(BVBLENDDEF_ONE << BVBLENDDEF_K3_SHIFT) |
+			(BVBLENDDEF_ZERO << BVBLENDDEF_K4_SHIFT),
+	BVBLEND_SRC2 =	BVBLENDDEF_FORMAT_CLASSIC |
+			(BVBLENDDEF_ZERO << BVBLENDDEF_K1_SHIFT) |
+			(BVBLENDDEF_ONE << BVBLENDDEF_K2_SHIFT) |
+			(BVBLENDDEF_ZERO << BVBLENDDEF_K3_SHIFT) |
+			(BVBLENDDEF_ONE << BVBLENDDEF_K4_SHIFT),
+	BVBLEND_SRC1OVER = BVBLENDDEF_FORMAT_CLASSIC |
+			(BVBLENDDEF_ONE << BVBLENDDEF_K1_SHIFT) |
+			(BVBLENDDEF_ONE_MINUS_A1 << BVBLENDDEF_K2_SHIFT) |
+			(BVBLENDDEF_ONE << BVBLENDDEF_K3_SHIFT) |
+			(BVBLENDDEF_ONE_MINUS_A1 << BVBLENDDEF_K4_SHIFT),
+	BVBLEND_SRC2OVER = BVBLENDDEF_FORMAT_CLASSIC |
+			(BVBLENDDEF_ONE_MINUS_A2 << BVBLENDDEF_K1_SHIFT) |
+			(BVBLENDDEF_ONE << BVBLENDDEF_K2_SHIFT) |
+			(BVBLENDDEF_ONE_MINUS_A2 << BVBLENDDEF_K3_SHIFT) |
+			(BVBLENDDEF_ONE << BVBLENDDEF_K4_SHIFT),
+	BVBLEND_SRC1IN = BVBLENDDEF_FORMAT_CLASSIC |
+			(BVBLENDDEF_A2 << BVBLENDDEF_K1_SHIFT) |
+			(BVBLENDDEF_ZERO << BVBLENDDEF_K2_SHIFT) |
+			(BVBLENDDEF_A2 << BVBLENDDEF_K3_SHIFT) |
+			(BVBLENDDEF_ZERO << BVBLENDDEF_K4_SHIFT),
+	BVBLEND_SRC2IN = BVBLENDDEF_FORMAT_CLASSIC |
+			(BVBLENDDEF_ZERO << BVBLENDDEF_K1_SHIFT) |
+			(BVBLENDDEF_A1 << BVBLENDDEF_K2_SHIFT) |
+			(BVBLENDDEF_ZERO << BVBLENDDEF_K3_SHIFT) |
+			(BVBLENDDEF_A1 << BVBLENDDEF_K4_SHIFT),
+	BVBLEND_SRC1OUT = BVBLENDDEF_FORMAT_CLASSIC |
+			(BVBLENDDEF_ONE_MINUS_A2 << BVBLENDDEF_K1_SHIFT) |
+			(BVBLENDDEF_ZERO << BVBLENDDEF_K2_SHIFT) |
+			(BVBLENDDEF_ONE_MINUS_A2 << BVBLENDDEF_K3_SHIFT) |
+			(BVBLENDDEF_ZERO << BVBLENDDEF_K4_SHIFT),
+	BVBLEND_SRC2OUT = BVBLENDDEF_FORMAT_CLASSIC |
+			(BVBLENDDEF_ZERO << BVBLENDDEF_K1_SHIFT) |
+			(BVBLENDDEF_ONE_MINUS_A1 << BVBLENDDEF_K2_SHIFT) |
+			(BVBLENDDEF_ZERO << BVBLENDDEF_K3_SHIFT) |
+			(BVBLENDDEF_ONE_MINUS_A1 << BVBLENDDEF_K4_SHIFT),
+	BVBLEND_SRC1ATOP = BVBLENDDEF_FORMAT_CLASSIC |
+			(BVBLENDDEF_A2 << BVBLENDDEF_K1_SHIFT) |
+			(BVBLENDDEF_ONE_MINUS_A1 << BVBLENDDEF_K2_SHIFT) |
+			(BVBLENDDEF_A2 << BVBLENDDEF_K3_SHIFT) |
+			(BVBLENDDEF_ONE_MINUS_A1 << BVBLENDDEF_K4_SHIFT),
+	BVBLEND_SRC2ATOP = BVBLENDDEF_FORMAT_CLASSIC |
+			(BVBLENDDEF_ONE_MINUS_A2 << BVBLENDDEF_K1_SHIFT) |
+			(BVBLENDDEF_A1 << BVBLENDDEF_K2_SHIFT) |
+			(BVBLENDDEF_ONE_MINUS_A2 << BVBLENDDEF_K3_SHIFT) |
+			(BVBLENDDEF_A1 << BVBLENDDEF_K4_SHIFT),
+	BVBLEND_XOR = BVBLENDDEF_FORMAT_CLASSIC |
+			(BVBLENDDEF_ONE_MINUS_A2 << BVBLENDDEF_K1_SHIFT) |
+			(BVBLENDDEF_ONE_MINUS_A1 << BVBLENDDEF_K2_SHIFT) |
+			(BVBLENDDEF_ONE_MINUS_A2 << BVBLENDDEF_K3_SHIFT) |
+			(BVBLENDDEF_ONE_MINUS_A1 << BVBLENDDEF_K4_SHIFT),
+	BVBLEND_PLUS = BVBLENDDEF_FORMAT_CLASSIC |
+			(BVBLENDDEF_ONE << BVBLENDDEF_K1_SHIFT) |
+			(BVBLENDDEF_ONE << BVBLENDDEF_K2_SHIFT) |
+			(BVBLENDDEF_ONE << BVBLENDDEF_K3_SHIFT) |
+			(BVBLENDDEF_ONE << BVBLENDDEF_K4_SHIFT),
+
+/*
+ * For FORMAT_ESSENTIAL, the variety of well-known blending functions from
+ * popular image manipulation programs are specified.
+ */
+
+	BVBLEND_NORMAL = BVBLENDDEF_FORMAT_ESSENTIAL + 0,
+	BVBLEND_LIGHTEN = BVBLENDDEF_FORMAT_ESSENTIAL + 1,
+	BVBLEND_DARKEN = BVBLENDDEF_FORMAT_ESSENTIAL + 2,
+	BVBLEND_MULTIPLY = BVBLENDDEF_FORMAT_ESSENTIAL + 3,
+	BVBLEND_AVERAGE = BVBLENDDEF_FORMAT_ESSENTIAL + 4,
+	BVBLEND_ADD = BVBLENDDEF_FORMAT_ESSENTIAL + 5,
+	BVBLEND_LINEAR_DODGE = BVBLEND_ADD,
+	BVBLEND_SUBTRACT = BVBLENDDEF_FORMAT_ESSENTIAL + 6,
+	BVBLEND_LINEAR_BURN = BVBLEND_SUBTRACT,
+	BVBLEND_DIFFERENCE = BVBLENDDEF_FORMAT_ESSENTIAL + 7,
+	BVBLEND_NEGATE = BVBLENDDEF_FORMAT_ESSENTIAL + 8,
+	BVBLEND_SCREEN = BVBLENDDEF_FORMAT_ESSENTIAL + 9,
+	BVBLEND_EXCLUSION = BVBLENDDEF_FORMAT_ESSENTIAL + 10,
+	BVBLEND_OVERLAY = BVBLENDDEF_FORMAT_ESSENTIAL + 11,
+	BVBLEND_SOFT_LIGHT = BVBLENDDEF_FORMAT_ESSENTIAL + 12,
+	BVBLEND_HARD_LIGHT = BVBLENDDEF_FORMAT_ESSENTIAL + 13,
+	BVBLEND_COLOR_DODGE = BVBLENDDEF_FORMAT_ESSENTIAL + 14,
+	BVBLEND_COLOR_BURN = BVBLENDDEF_FORMAT_ESSENTIAL + 15,
+	BVBLEND_LINEAR_LIGHT = BVBLENDDEF_FORMAT_ESSENTIAL + 16,
+	BVBLEND_VIVID_LIGHT = BVBLENDDEF_FORMAT_ESSENTIAL + 17,
+	BVBLEND_PIN_LIGHT = BVBLENDDEF_FORMAT_ESSENTIAL + 18,
+	BVBLEND_HARD_MIX = BVBLENDDEF_FORMAT_ESSENTIAL + 19,
+	BVBLEND_REFLECT = BVBLENDDEF_FORMAT_ESSENTIAL + 20,
+	BVBLEND_GLOW = BVBLENDDEF_FORMAT_ESSENTIAL + 21,
+	BVBLEND_PHOENIX = BVBLENDDEF_FORMAT_ESSENTIAL + 22,
+
+#ifdef BVBLEND_EXTERNAL_INCLUDE
+#define BVBLEND_EXTERNAL_INCLUDE
+#endif
+};
+
+#endif /* BVBLEND_H */
diff --git a/bltsville/bltsville/include/bvbuffdesc.h b/bltsville/bltsville/include/bvbuffdesc.h
new file mode 100644
index 0000000..98934bc
--- /dev/null
+++ b/bltsville/bltsville/include/bvbuffdesc.h
@@ -0,0 +1,61 @@
+/*
+ * bvbuffdesc.h
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ *
+ * This file is part of BLTsville, an open application programming interface
+ * (API) for accessing 2-D software or hardware implementations.
+ *
+ * This work is licensed under the Creative Commons Attribution-NoDerivs 3.0
+ * Unported License. To view a copy of this license, visit
+ * http://creativecommons.org/licenses/by-nd/3.0/ or send a letter to
+ * Creative Commons, 444 Castro Street, Suite 900, Mountain View, California,
+ * 94041, USA.
+ */
+
+#ifndef BVBUFFDESC_H
+#define BVBUFFDESC_H
+
+/*
+ * bvbuffmap - This is a private structure used by BLTsville
+ * implementations to manage resources associated with a buffer.  A pointer
+ * to this is returned from bv_map() and used in subsequent bv_blt() and
+ * bv_unmap() calls.
+ */
+struct bvbuffmap;
+
+#define BVATDEF_VENDOR_SHIFT	24
+#define BVATDEF_VENDOR_MASK	(0xFF << BVATDEF_VENDOR_SHIFT)
+
+/* Common aux type */
+#define BVATDEF_VENDOR_ALL	(0x00 << BVATDEF_VENDOR_SHIFT)
+
+/* Texas Instruments, Inc. */
+#define BVATDEF_VENDOR_TI	(0x01 << BVATDEF_VENDOR_SHIFT)
+
+enum bvauxtype {
+	BVAT_NONE = 0,	/* auxptr not used */
+	BVAT_reserved1 = /* reserved */
+		BVATDEF_VENDOR_ALL + 1,
+	BVAT_reserved2 = /* reserved */
+		BVATDEF_VENDOR_ALL + 2,
+#ifdef BVAT_EXTERNAL_INCLUDE
+#include BVAT_EXTERNAL_INCLUDE
+#endif
+};
+
+/*
+ * bvbuffdesc - This structure is used to specify the buffer parameters
+ * in a call to bv_map().
+ */
+struct bvbuffdesc {
+	unsigned int structsize;	/* used to identify struct version */
+	void *virtaddr;			/* virtual ptr to start of buffer */
+	unsigned long length;		/* length of the buffer in bytes */
+	struct bvbuffmap *map;		/* resource(s) associated w/buffer */
+	enum bvauxtype auxtype;		/* type of auxptr */
+	void *auxptr;			/* additional buffer description data;
+					type depends on auxtype */
+};
+
+#endif /* BVBUFFDESC_H */
diff --git a/bltsville/bltsville/include/bvcache.h b/bltsville/bltsville/include/bvcache.h
new file mode 100644
index 0000000..d9a3f6d
--- /dev/null
+++ b/bltsville/bltsville/include/bvcache.h
@@ -0,0 +1,45 @@
+/*
+ * bvcache.h
+ *
+ * Copyright (C) 2012 Texas Instruments, Inc.
+ *
+ * This file is part of BLTsville, an open application programming interface
+ * (API) for accessing 2-D software or hardware implementations.
+ *
+ * This work is licensed under the Creative Commons Attribution-NoDerivs 3.0
+ * Unported License. To view a copy of this license, visit
+ * http://creativecommons.org/licenses/by-nd/3.0/ or send a letter to
+ * Creative Commons, 444 Castro Street, Suite 900, Mountain View, California,
+ * 94041, USA.
+ */
+
+#ifndef BVCACHE_H_
+#define BVCACHE_H_
+
+/* Forward declarations */
+struct bvbuffdesc;
+struct bvsurfgeom;
+struct bvrect;
+
+/*
+ * This defines which cache operation the user intends to use
+ * BVCACHE_CPU_TO_DEVICE = clean
+ * BVCACHE_CPU_FROM_DEVICE = invalidate
+ * BVCACHE_BIDIRECTIONAL = flush
+ */
+enum bvcacheop {
+	BVCACHE_BIDIRECTIONAL = 0,
+	BVCACHE_CPU_TO_DEVICE = 1,
+	BVCACHE_CPU_FROM_DEVICE = 2,
+	BVCACHE_RESERVED3 = 3,
+};
+
+struct bvcopparams {
+	unsigned int structsize;	/* used to identify struct version */
+	struct bvbuffdesc *desc;
+	struct bvsurfgeom *geom;
+	struct bvrect     *rect;
+	enum bvcacheop cacheop;
+};
+
+#endif /* BVCACHE_H_ */
diff --git a/bltsville/bltsville/include/bventry.h b/bltsville/bltsville/include/bventry.h
new file mode 100644
index 0000000..0ccfc05
--- /dev/null
+++ b/bltsville/bltsville/include/bventry.h
@@ -0,0 +1,32 @@
+/*
+ * bventry.h
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ *
+ * This file is part of BLTsville, an open application programming interface
+ * (API) for accessing 2-D software or hardware implementations.
+ *
+ * This work is licensed under the Creative Commons Attribution-NoDerivs 3.0
+ * Unported License. To view a copy of this license, visit
+ * http://creativecommons.org/licenses/by-nd/3.0/ or send a letter to
+ * Creative Commons, 444 Castro Street, Suite 900, Mountain View, California,
+ * 94041, USA.
+ */
+
+#ifndef BVENTRY_H
+#define BVENTRY_H
+
+/* Forward declarations */
+struct bvbuffdesc;
+struct bvbltparams;
+struct bvcopparams;
+/*
+ * bv_*() - These are the API calls for BLTsville.  The client needs to
+ * import these from the shared library.
+ */
+typedef enum bverror (*BVFN_MAP)(struct bvbuffdesc *buffdesc);
+typedef enum bverror (*BVFN_BLT)(struct bvbltparams *bltparms);
+typedef enum bverror (*BVFN_UNMAP)(struct bvbuffdesc *buffdesc);
+typedef enum bverror (*BVFN_CACHE)(struct bvcopparams *copparams);
+
+#endif /* BVENTRY_H */
diff --git a/bltsville/bltsville/include/bverror.h b/bltsville/bltsville/include/bverror.h
new file mode 100644
index 0000000..15c3ba7
--- /dev/null
+++ b/bltsville/bltsville/include/bverror.h
@@ -0,0 +1,307 @@
+/*
+ * bverror.h
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ *
+ * This file is part of BLTsville, an open application programming interface
+ * (API) for accessing 2-D software or hardware implementations.
+ *
+ * This work is licensed under the Creative Commons Attribution-NoDerivs 3.0
+ * Unported License. To view a copy of this license, visit
+ * http://creativecommons.org/licenses/by-nd/3.0/ or send a letter to
+ * Creative Commons, 444 Castro Street, Suite 900, Mountain View, California,
+ * 94041, USA.
+ */
+
+#ifndef BVERROR_H
+#define BVERROR_H
+
+/*
+ * bverror - These are error codes returned by BLTsville functions.
+ */
+#define BVERRDEF_VENDOR_SHIFT	24
+#define BVERRDEF_VENDOR_MASK	(0xFF << BVERRDEF_VENDOR_SHIFT)
+
+#define BVERRDEF_VENDOR_ALL	(0x00 << BVERRDEF_VENDOR_SHIFT)
+#define BVERRDEF_VENDOR_TI	(0x01 << BVERRDEF_VENDOR_SHIFT)
+/* 0xF0-0xFF reserved */
+
+enum bverror {
+	BVERR_NONE = 0,		/* no error */
+
+	BVERR_UNK =		/* unknown error */
+		BVERRDEF_VENDOR_ALL + 1,
+	BVERR_OOM =		/* memory allocation failure */
+		BVERRDEF_VENDOR_ALL + 2,
+	BVERR_RSRC =		/* required resource unavailable */
+		BVERRDEF_VENDOR_ALL + 3,
+
+	BVERR_VIRTADDR =	/* virtaddr is bad */
+		BVERRDEF_VENDOR_ALL + 1000,
+	BVERR_VIRTPTR =
+		BVERR_VIRTADDR,	/* for backwards compatibility*/
+
+	BVERR_BUFFERDESC =	/* invalid bvbufferdesc */
+		BVERRDEF_VENDOR_ALL + 10000,
+	BVERR_BUFFERDESC_VERS =	/* bvbufferdesc.structsize too small */
+		BVERRDEF_VENDOR_ALL + 11000,
+	BVERR_BUFFERDESC_VIRTADDR = /* bad bvbufferdesc.virtaddr */
+		BVERRDEF_VENDOR_ALL + 12000,
+	BVERR_BUFFERDESC_LEN =	/* bvbufferdesc.length not supported */
+		BVERRDEF_VENDOR_ALL + 13000,
+	BVERR_BUFFERDESC_ALIGNMENT = /* unsupported buffer base address */
+		BVERRDEF_VENDOR_ALL + 14000,
+
+	BVERR_BLTPARAMS_VERS =	/* bvbltparams.structsize too small */
+		BVERRDEF_VENDOR_ALL + 20000,
+	BVERR_IMPLEMENTATION =	/* bvbltparams.implementation unsupported */
+		BVERRDEF_VENDOR_ALL + 21000,
+	BVERR_FLAGS =		/* bvbltparams.flags unsupported */
+		BVERRDEF_VENDOR_ALL + 22000,
+	BVERR_OP =		/* unsupported operation */
+		BVERRDEF_VENDOR_ALL + 22100,
+	BVERR_KEY =		/* type of color key not supported */
+		BVERRDEF_VENDOR_ALL + 22200,
+	BVERR_SRC1_TILE =	/* src1 tiling not supported */
+		BVERRDEF_VENDOR_ALL + 22300,
+	BVERR_SRC2_TILE =	/* src2 tiling not supported */
+		BVERRDEF_VENDOR_ALL + 22310,
+	BVERR_MASK_TILE =	/* mask tiling not supported */
+		BVERRDEF_VENDOR_ALL + 22320,
+	BVERR_FLIP =		/* flipping not supported */
+		BVERRDEF_VENDOR_ALL + 22400,
+	BVERR_ROP =		/* ROP code not supported */
+		BVERRDEF_VENDOR_ALL + 23000,
+	BVERR_BLEND =		/* blend not supported */
+		BVERRDEF_VENDOR_ALL + 23100,
+	BVERR_GLOBAL_ALPHA =	/* type of global alpha not supported */
+		BVERRDEF_VENDOR_ALL + 23110,
+	BVERR_FILTER =		/* filter type not supported */
+		BVERRDEF_VENDOR_ALL + 23200,
+	BVERR_FILTER_PARAMS_VERS = /* filter parameter structsize too small */
+		BVERRDEF_VENDOR_ALL + 23210,
+	BVERR_FILTER_PARAMS =	/* filter parameters not supported */
+		BVERRDEF_VENDOR_ALL + 23220,
+	BVERR_SCALE_MODE =	/* bvbltparams.scalemode not supported */
+		BVERRDEF_VENDOR_ALL + 24000,
+	BVERR_DITHER_MODE =	/* bvbltparams.dithermode not supported */
+		BVERRDEF_VENDOR_ALL + 25000,
+
+	BVERR_DSTDESC =		/* invalid bvbltparams.dstdesc */
+		BVERRDEF_VENDOR_ALL + 26000,
+	BVERR_DSTDESC_VERS =	/* bvbufferdesc.structsize too small */
+		BVERRDEF_VENDOR_ALL + 26100,
+	BVERR_DSTDESC_VIRTADDR = /* bad bvbufferdesc.virtaddr */
+		BVERRDEF_VENDOR_ALL + 26200,
+	BVERR_DSTDESC_LEN =	/* bvbufferdesc.length not supported */
+		BVERRDEF_VENDOR_ALL + 26300,
+	BVERR_DST_ALIGNMENT =	/* unsupported buffer base address */
+		BVERRDEF_VENDOR_ALL + 26400,
+
+	BVERR_DSTGEOM =		/* invalid bvbltparams.dstgeom */
+		BVERRDEF_VENDOR_ALL + 27000,
+	BVERR_DSTGEOM_VERS =	/* dstgeom.structsize too small */
+		BVERRDEF_VENDOR_ALL + 27100,
+	BVERR_DSTGEOM_FORMAT =	/* bltparams.dstgeom.format not supported */
+		BVERRDEF_VENDOR_ALL + 27200,
+	BVERR_DSTGEOM_STRIDE =	/* bltparams.dstgeom.stride not supported */
+		BVERRDEF_VENDOR_ALL + 27300,
+	BVERR_DSTGEOM_PALETTE =	/* dstgeom.paletteformat not supported */
+		BVERRDEF_VENDOR_ALL + 27400,
+
+
+	BVERR_DSTRECT =		/* bvbltparams.dstrect not supported */
+		BVERRDEF_VENDOR_ALL + 28000,
+
+	BVERR_SRC1DESC =	/* invalid bvbltparams.src1.desc */
+		BVERRDEF_VENDOR_ALL + 29000,
+	BVERR_SRC1DESC_VERS =	/* bvbufferdesc.structsize too small */
+		BVERRDEF_VENDOR_ALL + 29100,
+	BVERR_SRC1DESC_VIRTADDR = /* bad bvbufferdesc.virtaddr */
+		BVERRDEF_VENDOR_ALL + 29200,
+	BVERR_SRC1DESC_LEN =	/* bvbufferdesc.length not supported */
+		BVERRDEF_VENDOR_ALL + 29300,
+	BVERR_SRC1DESC_ALIGNMENT = /* unsupported buffer base address */
+		BVERRDEF_VENDOR_ALL + 29400,
+
+	BVERR_SRC1GEOM =	/* invalid bvbltparams.src1geom */
+		BVERRDEF_VENDOR_ALL + 30000,
+	BVERR_SRC1GEOM_VERS =	/* src1geom.structsize too small */
+		BVERRDEF_VENDOR_ALL + 30100,
+	BVERR_SRC1GEOM_FORMAT =	/* bltparams.src1geom.format not supported */
+		BVERRDEF_VENDOR_ALL + 30200,
+	BVERR_SRC1GEOM_STRIDE =	/* bltparams.src1geom.stride not supported */
+		BVERRDEF_VENDOR_ALL + 30300,
+	BVERR_SRC1GEOM_PALETTE = /* src1geom.paletteformat not supported */
+		BVERRDEF_VENDOR_ALL + 30400,
+
+	BVERR_SRC1RECT =	/* bvbltparams.src1rect not supported */
+		BVERRDEF_VENDOR_ALL + 31000,
+
+	BVERR_SRC1_HORZSCALE = /* horz scale for src1->dst not supported */
+		BVERRDEF_VENDOR_ALL + 31100,
+	BVERR_SRC1_VERTSCALE =	/* vert scale for src1->dst not supported */
+		BVERRDEF_VENDOR_ALL + 31200,
+	BVERR_SRC1_ROT =	/* src1->dst rotation angle not supported */
+		BVERRDEF_VENDOR_ALL + 31300,
+
+	BVERR_SRC1_TILEPARAMS =	/* invalid src1.tileparams */
+		BVERR_SRC1DESC,
+	BVERR_SRC1_TILE_VERS =	/* src1.tileparams.structsize too small */
+		BVERRDEF_VENDOR_ALL + 32000,
+	BVERR_SRC1_TILEPARAMS_VERS =
+		BVERR_SRC1_TILE_VERS,
+	BVERR_SRC1_TILE_FLAGS =	/* tileparams.flags not supported */
+		BVERRDEF_VENDOR_ALL + 32100,
+	BVERR_SRC1_TILEPARAMS_FLAGS =
+		BVERR_SRC1_TILE_FLAGS,
+	BVERR_SRC1_TILE_VIRTADDR =
+		BVERR_SRC1DESC_VIRTADDR,
+	BVERR_SRC1_TILEPARAMS_VIRTADDR =
+		BVERR_SRC1_TILE_VIRTADDR,
+	BVERR_SRC1_TILE_ORIGIN = /* tileparams.left or .top not supported */
+		BVERRDEF_VENDOR_ALL + 32200,
+	BVERR_SRC1_TILEPARAMS_ORIGIN =
+		BVERR_SRC1_TILE_ORIGIN,
+	BVERR_SRC1_TILE_SIZE =	/* tileparams.width or .height not supported */
+		BVERRDEF_VENDOR_ALL + 32300,
+	BVERR_SRC1_TILEPARAMS_SIZE =
+		BVERR_SRC1_TILE_SIZE,
+
+	BVERR_SRC2DESC =	/* invalid bvbltparams.src2.desc */
+		BVERRDEF_VENDOR_ALL + 33000,
+	BVERR_SRC2DESC_VERS =	/* bvbufferdesc.structsize too small */
+		BVERRDEF_VENDOR_ALL + 33100,
+	BVERR_SRC2DESC_VIRTADDR = /* bad bvbufferdesc.virtaddr */
+		BVERRDEF_VENDOR_ALL + 33200,
+	BVERR_SRC2DESC_LEN =	/* bvbufferdesc.length not supported */
+		BVERRDEF_VENDOR_ALL + 33300,
+	BVERR_SRC2DESC_ALIGNMENT = /* unsupported buffer base address */
+		BVERRDEF_VENDOR_ALL + 33400,
+
+	BVERR_SRC2GEOM =	/* invalid bvbltparams.src2geom */
+		BVERRDEF_VENDOR_ALL + 34000,
+	BVERR_SRC2GEOM_VERS =	/* src2geom.structsize too small */
+		BVERRDEF_VENDOR_ALL + 34100,
+	BVERR_SRC2GEOM_FORMAT =	/* bltparams.src2geom.format not supported */
+		BVERRDEF_VENDOR_ALL + 34200,
+	BVERR_SRC2GEOM_STRIDE =	/* bltparams.src2geom.stride not supported */
+		BVERRDEF_VENDOR_ALL + 34300,
+	BVERR_SRC2GEOM_PALETTE = /* src2geom.paletteformat not supported */
+		BVERRDEF_VENDOR_ALL + 34400,
+
+	BVERR_SRC2RECT =	/* bvbltparams.src2rect not supported */
+		BVERRDEF_VENDOR_ALL + 35000,
+
+	BVERR_SRC2_HORZSCALE = /* horz scale for src2->dst not supported */
+		BVERRDEF_VENDOR_ALL + 35100,
+	BVERR_SRC2_VERTSCALE =	/* vert scale for src2->dst not supported */
+		BVERRDEF_VENDOR_ALL + 35200,
+	BVERR_SRC2_ROT =	/* src2->dst rotation angle not supported */
+		BVERRDEF_VENDOR_ALL + 35300,
+
+	BVERR_SRC2_TILEPARAMS =	/* invalid src2.tileparams */
+		BVERR_SRC2DESC,
+	BVERR_SRC2_TILE_VERS =	/* src2.tileparams.structsize too small */
+		BVERRDEF_VENDOR_ALL + 36000,
+	BVERR_SRC2_TILEPARAMS_VERS =
+		BVERR_SRC2_TILE_VERS,
+	BVERR_SRC2_TILE_FLAGS =	/* tileparams.flags not supported */
+		BVERRDEF_VENDOR_ALL + 36100,
+	BVERR_SRC2_TILEPARAMS_FLAGS =
+		BVERR_SRC2_TILE_FLAGS,
+	BVERR_SRC2_TILE_VIRTADDR =
+		BVERR_SRC2DESC_VIRTADDR,
+	BVERR_SRC2_TILEPARAMS_VIRTADDR =
+		BVERR_SRC2_TILE_VIRTADDR,
+	BVERR_SRC2_TILE_ORIGIN = /* tileparams.left or .top not supported */
+		BVERRDEF_VENDOR_ALL + 36200,
+	BVERR_SRC2_TILEPARAMS_ORIGIN =
+		BVERR_SRC2_TILE_ORIGIN,
+	BVERR_SRC2_TILE_SIZE =	/* tileparams.width or .height not supported */
+		BVERRDEF_VENDOR_ALL + 36300,
+	BVERR_SRC2_TILEPARAMS_SIZE =
+		BVERR_SRC2_TILE_SIZE,
+
+	BVERR_MASKDESC =	/* invalid bvbltparams.mask.desc */
+		BVERRDEF_VENDOR_ALL + 37000,
+	BVERR_MASKDESC_VERS =	/* bvbufferdesc.structsize too small */
+		BVERRDEF_VENDOR_ALL + 37100,
+	BVERR_MASKDESC_VIRTADDR = /* bad bvbufferdesc.virtaddr */
+		BVERRDEF_VENDOR_ALL + 37200,
+	BVERR_MASKDESC_LEN =	/* bvbufferdesc.length not supported */
+		BVERRDEF_VENDOR_ALL + 37300,
+	BVERR_MASKDESC_ALIGNMENT = /* unsupported buffer base address */
+		BVERRDEF_VENDOR_ALL + 37400,
+
+	BVERR_MASKGEOM =	/* invalid bvbltparams.maskgeom */
+		BVERRDEF_VENDOR_ALL + 38000,
+	BVERR_MASKGEOM_VERS =	/* maskgeom.structsize too small */
+		BVERRDEF_VENDOR_ALL + 38100,
+	BVERR_MASKGEOM_FORMAT =	/* bltparams.maskgeom.format not supported */
+		BVERRDEF_VENDOR_ALL + 38200,
+	BVERR_MASKGEOM_STRIDE =	/* bltparams.maskgeom.stride not supported */
+		BVERRDEF_VENDOR_ALL + 38300,
+	BVERR_MASKGEOM_PALETTE = /* maskgeom.paletteformat not supported */
+		BVERRDEF_VENDOR_ALL + 38400,
+
+	BVERR_MASKRECT =	/* bvbltparams.maskrect not supported */
+		BVERRDEF_VENDOR_ALL + 39000,
+
+	BVERR_MASK_HORZSCALE = /* horz scale for mask->dst not supported */
+		BVERRDEF_VENDOR_ALL + 39100,
+	BVERR_MASK_VERTSCALE =	/* vert scale for mask->dst not supported */
+		BVERRDEF_VENDOR_ALL + 39200,
+	BVERR_MASK_ROT =	/* mask->dst rotation angle not supported */
+		BVERRDEF_VENDOR_ALL + 39300,
+
+	BVERR_MASK_TILEPARAMS =	/* invalid mask.tileparams */
+		BVERR_MASKDESC,
+	BVERR_MASK_TILE_VERS =	/* mask.tileparams.structsize too small */
+		BVERRDEF_VENDOR_ALL + 40000,
+	BVERR_MASK_TILEPARAMS_VERS =
+		BVERR_MASK_TILE_VERS,
+	BVERR_MASK_TILE_FLAGS =	/* tileparams.flags not supported */
+		BVERRDEF_VENDOR_ALL + 40100,
+	BVERR_MASK_TILEPARAMS_FLAGS =
+		BVERR_MASK_TILE_FLAGS,
+	BVERR_MASK_TILE_VIRTADDR =
+		BVERR_MASKDESC_VIRTADDR,
+	BVERR_MASK_TILEPARAMS_VIRTADDR =
+		BVERR_MASK_TILE_VIRTADDR,
+	BVERR_MASK_TILE_ORIGIN = /* tileparams.left or .top not supported */
+		BVERRDEF_VENDOR_ALL + 40200,
+	BVERR_MASK_TILEPARAMS_ORIGIN =
+		BVERR_MASK_TILE_ORIGIN,
+	BVERR_MASK_TILE_SIZE =	/* tileparams.width or .height not supported */
+		BVERRDEF_VENDOR_ALL + 40300,
+	BVERR_MASK_TILEPARAMS_SIZE =
+		BVERR_MASK_TILE_SIZE,
+
+	BVERR_CLIP_RECT =	/* bvbltparams.cliprect not supported */
+		BVERRDEF_VENDOR_ALL + 41000,
+
+	BVERR_BATCH_FLAGS =	/* bvbltparams.batchflags not supported */
+		BVERRDEF_VENDOR_ALL + 42000,
+	BVERR_BATCH =		/* bvbltparams.batch not valid */
+		BVERRDEF_VENDOR_ALL + 43000,
+
+	BVERR_OP_FAILED =	/* async operation failed to start */
+		BVERRDEF_VENDOR_ALL + 50000,
+	BVERR_OP_INCOMPLETE =	/* async operation failed mid-way */
+		BVERRDEF_VENDOR_ALL + 50001,
+	BVERR_MEMORY_ERROR =	/* async operation triggered memory error */
+		BVERRDEF_VENDOR_ALL + 51000,
+
+	BVERR_FORMAT =		/* unsupported format */
+		BVERRDEF_VENDOR_ALL + 52000,
+
+	BVERR_CACHEOP =		/* unsupported cache operation */
+		BVERRDEF_VENDOR_ALL + 60000,
+
+#ifdef BVERR_EXTERNAL_INCLUDE
+#include BVERR_EXTERNAL_INCLUDE
+#endif
+};
+
+#endif /* BVERROR_H */
diff --git a/bltsville/bltsville/include/bvfilter.h b/bltsville/bltsville/include/bvfilter.h
new file mode 100644
index 0000000..2c98d94
--- /dev/null
+++ b/bltsville/bltsville/include/bvfilter.h
@@ -0,0 +1,51 @@
+/*
+ * bvfilter.h
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ *
+ * This file is part of BLTsville, an open application programming interface
+ * (API) for accessing 2-D software or hardware implementations.
+ *
+ * This work is licensed under the Creative Commons Attribution-NoDerivs 3.0
+ * Unported License. To view a copy of this license, visit
+ * http://creativecommons.org/licenses/by-nd/3.0/ or send a letter to
+ * Creative Commons, 444 Castro Street, Suite 900, Mountain View, California,
+ * 94041, USA.
+ */
+
+/*
+ * This file defines the types of shared filters available and the associated
+ * parameters.
+ *
+ * To extend the list of filters, create a file containing additional
+ * enumerations to be added to enum bvfilter below.  Then #define
+ * BVFILTER_EXTERNAL_INCLUDE as the name of that file before including
+ * this file in your project.  Parameters need to be in a different file.
+ */
+
+#ifndef BVFILTER_H
+#define BVFILTER_H
+
+/*
+ * bvfilter is an enumeration used to designate the type of filter being used.
+ */
+enum bvfiltertype {
+	BVFILTER_DUMMY
+	/* TBD */
+
+#ifdef BVFILTER_EXTERNAL_INCLUDE
+#include BVFILTER_EXTERNAL_INCLUDE
+#endif
+};
+
+/*
+ * bvfilterop contains the filter type and a pointer to the associated
+ * parameters when the BVFLAG_FILTER operation is specified in
+ * bvbltparams.flags.
+ */
+struct bvfilter {
+	enum bvfiltertype filter;
+	void *params;
+};
+
+#endif /* BVFILTER_H */
diff --git a/bltsville/bltsville/include/bvinternal.h b/bltsville/bltsville/include/bvinternal.h
new file mode 100644
index 0000000..06e1bed
--- /dev/null
+++ b/bltsville/bltsville/include/bvinternal.h
@@ -0,0 +1,47 @@
+/*
+ * bvinternal.h
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ *
+ * This file is part of BLTsville, an open application programming interface
+ * (API) for accessing 2-D software or hardware implementations.
+ *
+ * This work is licensed under the Creative Commons Attribution-NoDerivs 3.0
+ * Unported License. To view a copy of this license, visit
+ * http://creativecommons.org/licenses/by-nd/3.0/ or send a letter to
+ * Creative Commons, 444 Castro Street, Suite 900, Mountain View, California,
+ * 94041, USA.
+ */
+
+/*
+ * This file contains definitions used by implementations of BLTsville
+ * 2-D libraries.  It should not be used by clients.
+ */
+
+#ifndef BVINTERNAL_H
+#define BVINTENRAL_H
+
+/*
+ * bvbuffmap - The bvbuffmap structure is used to track resources
+ * associated with a buffer, such as a h/w MMU entry.  The implementations
+ * add bvbuffmap objects when they allocate the resources.  Then when a
+ * buffer is accessed, the implementations can regain access to the
+ * associated resources.  The implementations allocate and populate this
+ * structure when a bv_map() call is made.  It is used in subsequent
+ * bv_blt() and bv_unmap() calls.  The latter frees the associated resource
+ * and the structure (if applicable).  Note that a given resource might be
+ * used by more than one implementation.
+ */
+struct bvbuffmap {
+	unsigned int structsize; /* used to ID structure ver */
+
+	/* function to unmap this resource */
+	BVFN_UNMAP bv_unmap;
+
+	unsigned long handle;	 /* resource-specific info */
+
+	/* pointer to next resource mapping structure */
+	struct bvbuffmap *nextmap;
+};
+
+#endif /* BVINTERNAL_H */
diff --git a/bltsville/bltsville/include/bvsurfgeom.h b/bltsville/bltsville/include/bvsurfgeom.h
new file mode 100644
index 0000000..70029fc
--- /dev/null
+++ b/bltsville/bltsville/include/bvsurfgeom.h
@@ -0,0 +1,41 @@
+/*
+ * bvsurfgeom.h
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ *
+ * This file is part of BLTsville, an open application programming interface
+ * (API) for accessing 2-D software or hardware implementations.
+ *
+ * This work is licensed under the Creative Commons Attribution-NoDerivs 3.0
+ * Unported License. To view a copy of this license, visit
+ * http://creativecommons.org/licenses/by-nd/3.0/ or send a letter to
+ * Creative Commons, 444 Castro Street, Suite 900, Mountain View, California,
+ * 94041, USA.
+ */
+
+#ifndef BVSURFGEOM_H
+#define BVSURFGEOM_H
+
+/*
+ * bvsurfdesc - This structure specifies the way a buffer should be used in a
+ * 2-D context.
+ */
+
+struct bvsurfgeom {
+	unsigned int structsize;	/* used to identify struct version */
+	enum ocdformat format;		/* color format of surface */
+	unsigned int width;		/* width of the surface in pixels */
+	unsigned int height;		/* height of the surface in lines */
+	int orientation;		/* angle of the surface in degrees
+					   (multiple of 90 only) */
+	long virtstride;		/* distance from one pixel to the
+					   pixel immediately below it in
+					   virtual space */
+	enum ocdformat paletteformat;	/* format of palette */
+	void *palette;			/* array of palette entries of
+					   paletteformat; only valid when
+					   format includes BVFMTDEF_LUT;
+					   number of entries is 2^bpp. */
+};
+
+#endif /* BVSURFGEOM_H */
diff --git a/bltsville/bltsville/index.html b/bltsville/bltsville/index.html
new file mode 100644
index 0000000..4b3a96c
--- /dev/null
+++ b/bltsville/bltsville/index.html
@@ -0,0 +1,4362 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office">

+

+<head>

+<meta http-equiv="Content-Language" content="en-us" />

+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

+<title>Welcome to BLTsville</title>

+<style type="text/css">

+.cmd_line {

+	background: #000;

+	color: #fff;

+	padding: 10px;

+}

+.inline_code {

+	font-family: "Courier New", Courier, monospace;

+	font-size: small;

+}

+.code_block {

+	margin-left: 40px;

+	font-family: "Courier New", Courier, monospace;

+	font-size: small;

+}

+.small_code_block_in_table {

+	font-family: "Courier New", Courier, monospace;

+	font-size: x-small;

+}

+.small_code_block {

+	font-family: "Courier New", Courier, monospace;

+	font-size: x-small;

+	margin-left: 40px;

+}

+.underline_code {

+	font-family: "Courier New", Courier, monospace;

+	font-size: small;

+	text-decoration: underline;

+}

+.Code_Header {

+	font-size: xx-large;

+	font-weight: bold;

+	text-align: left;

+	font-family: "Courier New", Courier, monospace;

+}

+.Code_Header_2 {

+	font-size: x-large;

+	font-weight: bold;

+	text-align: left;

+	font-family: "Courier New", Courier, monospace;

+}

+.Code_Header_3 {

+	font-size: large;

+	font-weight: bold;

+	text-align: left;

+	font-family: "Courier New", Courier, monospace;

+}

+.imponly {

+	border: thin solid #666666;

+	margin-left: 40px;

+	background-color: #E5E5E5;

+	font-family: Arial, Helvetica, sans-serif;

+	color: #333333;

+}

+.Header1 {

+	margin: 0px 0 0 0;

+	font-size: xx-large;

+	font-weight: bold;

+	text-align: left;

+	line-height: normal;

+	background-color: #E0E0E0;

+}

+.Header2 {

+	font-size: xx-large;

+	font-weight: bold;

+	margin: 0px;

+	line-height: 100%;

+}

+.Header3 {

+	font-size: x-large;

+	font-weight: bold;

+	margin: 0px;

+	line-height: 100%;

+}

+.Header4 {

+	font-size: large;

+	font-weight: bold;

+	margin: 0px;

+	line-height: 100%;

+}

+.strong_emphasis {

+	text-decoration: underline;

+	font-weight: bold;

+}

+.filename {

+	font-family: Arial, Helvetica, sans-serif;

+	font-size: small;

+}

+.underline {

+	text-decoration: underline;

+}

+.grn_left {

+	text-align: left;

+	color: #009900;

+}

+.left_topbord {

+	text-align: left;

+	border-top-style: solid;

+	border-top-width: 1px;

+}

+.center_topbord {

+	text-align: center;

+	border-top-style: solid;

+	border-top-width: 1px;

+}

+.blue_left_botbord {

+	text-align: left;

+	border-bottom-style: solid;

+	border-bottom-width: 1px;

+	color: #0000FF;

+}

+.blue_center_botbord {

+	text-align: center;

+	border-bottom-style: solid;

+	border-bottom-width: 1px;

+	color: #0000FF;

+}

+.red_center {

+	text-align: center;

+	color: #FF0000;

+}

+.red_left {

+	text-align: left;

+	color: #FF0000;

+}

+.grn_center {

+	text-align: center;

+	color: #009900;

+}

+.red_center_topbord {

+	text-align: center;

+	border-top-style: solid;

+	border-top-width: 1px;

+	color: #FF0000;

+}

+.blu_center_topbord {

+	text-align: center;

+	border-top-style: solid;

+	border-top-width: 1px;

+	color: #0000FF;

+}

+.indent_thick_bord {

+	border-color: #000000;

+	border-style: solid;

+	margin-left: 40px;

+}

+.thin_bord {

+	border-style: solid;

+	border-width: 1px;

+}

+.thin_bord_dbl_botbord {

+	border-left-style: solid;

+	border-left-width: 1px;

+	border-right-style: solid;

+	border-right-width: 1px;

+	border-top-style: solid;

+	border-top-width: 1px;

+	border-bottom-style: double;

+	border-bottom-width: 3px;

+}

+.dl_link {

+	float: right;

+}

+.note {

+	font-family: Arial, Helvetica, sans-serif;

+	font-weight: bold;

+	margin-left: 40px;

+}

+.small_note {

+	font-size: xx-small;

+	line-height: 100%;

+}

+.ctr {

+	text-align: center;

+}

+.glyph_cache {

+	font-family: "Courier New", Courier, monospace;

+	font-size: medium;

+	font-weight: normal;

+	font-style: normal;

+	margin-left: 40px;

+	background-color: #000000;

+	color: #FFFFFF;

+}

+.example {

+	border-style: solid;

+	border-width: 1px;

+	margin-left: 40px;

+	margin-right: 40px;

+}

+.rt_thick_bord {

+	border-right-style: solid;

+	border-right-color: #000000;

+}

+.indent {

+	margin-left: 40px;

+}

+.ctr_thin_bord {

+	border-style: solid;

+	border-width: 1px;

+	text-align: center;

+}

+.indent_thin_bord {

+	border-style: solid;

+	border-width: 1px;

+	margin-left: 40px;

+}

+.bold_sans {

+	font-family: Arial, Helvetica, sans-serif;

+	font-weight: bold;

+}

+.nowrap {

+	border-style: solid;

+	border-width: 1px;

+	white-space: nowrap;

+	font-size: small;

+}

+</style>

+</head>

+

+<body>

+

+<table style="width: 100%; line-height: 100%;">

+	<tr>

+		<td style="width: 484px">

+		<table>

+			<tr>

+				<td>

+				<div style="background-position: center; background-image: url('bvlogo.png'); width: 484px; height: 400px; background-repeat: no-repeat;">

+					<div style="position: relative; left: 0; top: 0;">

+						<a href="http://graphics.github.com/ocd">

+						<img src="ocdtab.png" alt="Now With OCD" style="border-width: 0; position: absolute; top: 0; right: 0;" /></a>

+					</div>

+				</div>

+				</td>

+			</tr>

+			<tr>

+				<td class="ctr"><span class="Header2">Version 2.2</span></td>

+			</tr>

+		</table>

+		</td>

+		<td>

+		<p>BLTsville is the open 2-D API designed to provide an abstract interface for both hardware and software 2-D implementations.</p>

+		<p>BLTs (BLock Transfers) involve the moving around of blocks (rectangles) of pixels.&nbsp; BLTsville is the place 

+		to go for BLTs.</p>

+		<hr />

+		<table style="width: 100%">

+			<tr>

+				<td>

+				<div class="dl_link">

+					<img alt="CC BY-ND" longdesc="Creative Commons Attribution-NoDerivs 3.0 Unported License" src="http://i.creativecommons.org/l/by-nd/3.0/88x31.png" width="88" height="31" /></div>

+				<p class="Header2">License</p>

+				</td>

+			</tr>

+			<tr>

+				<td>

+				<div>

+					<p class="small_note">The API is designed and maintained by Texas Instruments, Inc., but anyone is free 

+					to use it with no cost or obligation.</p>

+					<p>This project is licensed under the <a href="http://creativecommons.org/licenses/by-nd/3.0/">Creative 

+					Commons Attribution-NoDerivs 3.0 Unported License</a> (user mode), and the

+					<a href="http://www.gnu.org/licenses/gpl-2.0.html">GNU General Public License version 2</a> (kernel 

+					mode).</p>

+				</div>

+				</td>

+			</tr>

+		</table>

+		<hr />

+		<table style="width: 100%">

+			<tr>

+				<td>

+				<p class="Header2">Dependencies</p>

+				</td>

+			</tr>

+			<tr>

+				<td>

+				<p>This project is dependent on the <a href="http://graphics.github.com/ocd">Open Color format Defintions 

+				(OCD) project</a>.</p>

+				</td>

+			</tr>

+		</table>

+		<hr />

+		<table style="width: 100%">

+			<tr>

+				<td>

+				<p class="Header2">Source</p>

+				</td>

+			</tr>

+			<tr>

+				<td>

+				<div class="dl_link">

+					<a href="http://github.com/graphics/bltsville/zipball/master">

+					<img width="90" alt="download zip" src="http://github.com/images/modules/download/zip.png" /></a>

+					<a href="http://github.com/graphics/bltsville/tarball/master">

+					<img width="90" alt="download tar" src="http://github.com/images/modules/download/tar.png" /></a>

+				</div>

+				<div>

+					Get the source code (headers) from GitHub at <a href="http://github.com/graphics/bltsville">github.com/graphics/bltsville</a>, 

+					or download the project in <a href="http://github.com/graphics/bltsville/zipball/master">zip</a> or

+					<a href="http://github.com/graphics/bltsville/tarball/master">tar</a> format.</div>

+				<p>You can also clone the project with <a href="http://git-scm.com">Git</a> by running:</p>

+				<pre><a class="cmd_line">$ git clone git://github.com/graphics/bltsville</a></pre>

+				</td>

+			</tr>

+			<tr>

+				<td><hr />

+				<table style="width: 100%">

+					<tr>

+						<td class="Header2">Wiki</td>

+					</tr>

+					<tr>

+						<td><a href="https://github.com/graphics/bltsville/wiki">https://github.com/graphics/bltsville/wiki</a></td>

+					</tr>

+				</table>

+				</td>

+			</tr>

+		</table>

+		</td>

+	</tr>

+</table>

+<hr />

+<p class="Header1">Points of Interest in BLTsville</p>

+<table style="width: 100%">

+	<tr>

+		<td style="width: 50%" valign="top">

+		<ul>

+			<li>Solid fills</li>

+			<li>Pattern fills</li>

+			<li>Copies</li>

+			<li>Color format conversion<ul>

+				<li>Extensive color format support<ul>

+					<li>RGB, BGR</li>

+					<li>RGBA, ARGB, etc.</li>

+					<li>YCbCr (YUV)<ul>

+						<li>subsampling</li>

+						<li>packed</li>

+						<li>planar</li>

+					</ul>

+					</li>

+					<li>Monochrome</li>

+					<li>Alpha-only</li>

+					<li>Look-Up Table (LUT)</li>

+				</ul>

+				</li>

+				<li>Extensible color format</li>

+			</ul>

+			</li>

+			<li>ROP4<ul>

+				<li>Three inputs</li>

+			</ul>

+			</li>

+			<li>Blends<ul>

+				<li>Pre-defined Porter-Duff blends</li>

+				<li>Pre-defined DirectFB support</li>

+				<li>Extensible blends</li>

+			</ul>

+			</li>

+			<li>Multiple </li>

+			<li>Filters<ul>

+				<li>Extensible filters</li>

+			</ul>

+			</li>

+			<li>Independent horizontal and vertical <strong>flipping</strong></li>

+			<li>Independent <strong>scaling</strong> of all three inputs</li>

+			<li>Clipping</li>

+			<li>Independent <strong>rotation</strong> of all three inputs (multiples of 90 degrees)</li>

+		</ul>

+		</td>

+		<td style="width: 50%" valign="top">

+		<ul>

+			<li>Choice of <strong>scaling</strong> type<ul>

+				<li>Quality based choice</li>

+				<li>Speed based choice</li>

+				<li>Image type based choice</li>

+				<li>Specific scale type choice</li>

+				<li>Extensible scale type</li>

+			</ul>

+			</li>

+			<li>Synchronous operations</li>

+			<li>Asynchronous operations<ul>

+				<li>Client notification of BLT completion</li>

+			</ul>

+			</li>

+			<li>Batching<ul>

+				<li>Combine multiple BLTs into group that can be handled more efficiently by implementations<ul>

+					<li>Character BLTs</li>

+					<li>Multi-layer blending</li>

+					<li>ROP/Blend combination with specified ordering</li>

+					<li>etc.</li>

+				</ul>

+				</li>

+				<li>Delta BLTs</li>

+			</ul>

+			</li>

+			<li>Dithering<ul>

+				<li>Quality based choice</li>

+				<li>Speed based choice</li>

+				<li>Image type based choice</li>

+				<li>Specific dither type choice</li>

+				<li>Extensible dither type</li>

+			</ul>

+			</li>

+			<li>Any implementation support<ul>

+				<li>CPU</li>

+				<li>2-D Accelerator</li>

+			</ul>

+			</li>

+		</ul>

+		</td>

+	</tr>

+</table>

+<hr />

+<ul>

+	<li>BLTsville does not dictate capabilities of the implementations<ul>

+		<li>Operations specified either work or return an error indicating that the operation is not supported</li>

+	</ul>

+	</li>

+</ul>

+<hr />

+<p class="Header1">How to Get to BLTsville</p>

+<p>BLTsville&#39;s API is defined in the BLTsville header files.&nbsp; A client must include <span class="inline_code">bltsville.h</span> 

+to access the implementations.&nbsp; This header includes the remaining headers (including <span class="inline_code">ocd.h</span>).</p>

+<p class="note">NOTE:&nbsp; The <span class="underline_code">bvinternal.h</span><span class="underline"> header is for implementations 

+only</span> and should not be used by clients.</p>

+<p>BLTsville has both user mode and a kernel mode interaces.&nbsp; The kernel mode interface is quite similar to (and compatible 

+with) the user mode, but due to the minor differences and license issues, there are two different sets of header files.</p>

+<hr />

+<p class="Header1">History of BLTsville</p>

+<br />

+<p class="Header4">Versions 1.x</p>

+<p>BLTsville was based on a previous closed interface, which had a few implementations and shipped on a few devices.&nbsp; 

+That interface represented the 1.x versions.&nbsp; A lot was learned from that work, and these lessons were used in the 

+founding of BLTsville.</p>

+<p class="Header4">Version 2.0</p>

+<p>This was the initial release of the user mode interface.&nbsp; This version is not compatible with the 1.x versions.&nbsp; 

+Several minor updates were posted, but the API itself did not change, so no changes to the client or implementation were 

+required.</p>

+<p class="Header4">Version 2.1</p>

+<p>This is a minor update to the API, and it adds the kernel mode interface.&nbsp; Some additions to the API have been made.&nbsp; 

+Details of the changes are below with their compatibility matrices.</p>

+<ul>

+	<li><span class="inline_code"><a href="#bv_cache">bv_cache()</a></span> was added to allow manipulation of the CPU cache.&nbsp; 

+	This is an optional interface meant for hardware implementations.</li>

+</ul>

+<table class="indent_thin_bord">

+	<tr>

+		<td class="thin_bord">&nbsp;</td>

+		<td class="ctr_thin_bord"><strong>2.0 Client</strong></td>

+		<td class="ctr_thin_bord"><strong>2.0 Client</strong><br />

+		(w/2.1 Headers)</td>

+		<td class="ctr_thin_bord"><strong>2.1 Client</strong></td>

+	</tr>

+	<tr>

+		<td class="thin_bord"><strong>2.0 Implementation</strong></td>

+		<td class="ctr_thin_bord">compatible</td>

+		<td class="ctr_thin_bord">New function and structure definitions have no effect.</td>

+		<td class="ctr_thin_bord">Client must deal with lack of <span class="inline_code"><a href="#bv_cache">bv_cache()</a></span>.</td>

+	</tr>

+	<tr>

+		<td class="thin_bord"><strong>2.0 Implementation</strong><br />

+		(w/2.1 Headers)</td>

+		<td class="ctr_thin_bord">New function and structure definitions have no effect.</td>

+		<td class="ctr_thin_bord">New function and structure definitions have no effect.</td>

+		<td class="ctr_thin_bord">Client must deal with lack of <span class="inline_code"><a href="#bv_cache">bv_cache()</a></span>.</td>

+	</tr>

+	<tr>

+		<td class="thin_bord"><strong>2.1 Implementation</strong></td>

+		<td class="ctr_thin_bord">New function and structures have no effect.</td>

+		<td class="ctr_thin_bord">New function and structures have no effect.</td>

+		<td class="ctr_thin_bord">compatible</td>

+	</tr>

+</table>

+<ul>

+	<li><span class="inline_code"><a href="#bvbuffdesc">bvbuffdesc</a></span> was extended with the

+	<span class="inline_code"><a href="#bvbuffdesc.auxtype">auxtype</a></span> and <span class="inline_code">

+	<a href="#bvbuffdesc.auxptr">auxptr</a></span> members to allow buffer descriptions beyond a virtual address.&nbsp; 

+	Note that only the kernel mode interface currently includes a standard <span class="inline_code">auxtype</span>, but 

+	user mode interface <span class="inline_code">auxtype</span>s may be added later.&nbsp; Both interfaces provide a mechanism 

+	for individual vendors to add their own <span class="inline_code">auxtype</span>, using the same vendor ID mechanism 

+	as the rest of BLTsville.</li>

+</ul>

+<table class="indent_thin_bord">

+	<tr>

+		<td class="thin_bord">&nbsp;</td>

+		<td class="ctr_thin_bord"><strong>2.0 Client</strong></td>

+		<td class="ctr_thin_bord"><strong>2.0 Client</strong><br />

+		(w/2.1 Headers)</td>

+		<td class="ctr_thin_bord"><strong>2.1 Client</strong></td>

+	</tr>

+	<tr>

+		<td class="thin_bord"><strong>2.0 Implementation</strong></td>

+		<td class="ctr_thin_bord">compatible</td>

+		<td class="ctr_thin_bord">Client must clear <span class="inline_code"><a href="#bvbuffdesc">bvbuffdesc</a></span> 

+		using <span class="inline_code"><span style="white-space: nowrap">sizeof(<a href="#bvbuffdesc">bvbuffdesc</a>)</span></span>.</td>

+		<td class="ctr_thin_bord">Implementation must handle <span class="inline_code">

+		<a href="#bvbuffdesc.structsize">bvbuffdesc.structsize</a> &gt; <span style="white-space: nowrap">sizeof(<a href="#bvbuffdesc">bvbuffdesc</a>)</span></span>.</td>

+	</tr>

+	<tr>

+		<td class="thin_bord"><strong>2.0 Implementation</strong><br />

+		(w/2.1 Headers)</td>

+		<td class="ctr_thin_bord">Implementation must handle <span class="inline_code">

+		<a href="#bvbuffdesc.structsize">bvbuffdesc.structsize</a> &lt; <span style="white-space: nowrap">sizeof(<a href="#bvbuffdesc">bvbuffdesc</a>)</span></span>.</td>

+		<td class="ctr_thin_bord">Client must clear <span class="inline_code"><a href="#bvbuffdesc">bvbuffdesc</a></span> 

+		using <span class="inline_code"><span style="white-space: nowrap">sizeof(<a href="#bvbuffdesc">bvbuffdesc</a>)</span></span>.</td>

+		<td class="ctr_thin_bord">Client must deal with implementation that uses <span class="inline_code">

+		<a href="#bvbuffdesc.virtaddr">bvbuffdesc.virtaddr</a></span> or returns error if <span class="inline_code">

+		<a href="#bvbuffdesc.virtaddr">bvbuffdesc.virtaddr</a></span> is 0.</td>

+	</tr>

+	<tr>

+		<td class="thin_bord"><strong>2.1 Implementation</strong></td>

+		<td class="ctr_thin_bord">Implementation must handle <span class="inline_code">

+		<a href="#bvbuffdesc.structsize">bvbuffdesc.structsize</a> &lt; <span style="white-space: nowrap">sizeof(<a href="#bvbuffdesc">bvbuffdesc</a>)</span></span>.</td>

+		<td class="ctr_thin_bord">Client must clear <span class="inline_code"><a href="#bvbuffdesc">bvbuffdesc</a></span> 

+		using <span class="inline_code"><span style="white-space: nowrap">sizeof(<a href="#bvbuffdesc">bvbuffdesc</a>)</span></span>.</td>

+		<td class="ctr_thin_bord">compatible</td>

+	</tr>

+</table>

+<ul>

+	<li>Added documentation of <a href="#NOP">NOP BLT</a> used as synchronization mechanism for <a href="#BVFLAG_ASYNC">

+	asynchronous BLTs</a>.<ul>

+		<li>Clients that do not use <a href="#BVFLAG_ASYNC">asynchronous BLTs</a> or the <a href="#NOP">NOP BLT</a> will 

+		not be affected.</li>

+		<li>Implementations that do not support the NOP BLT will return an error.&nbsp; This will not cause a problem 

+		for clients when using implementations which are actually synchronous.&nbsp; For clients using asynchronous 

+		implementations, an alternate supported but innocuous BLT will be necessary (e.g. copying a pixel to itself).</li>

+	</ul>

+	</li>

+</ul>

+<p class="Header4">Version 2.2</p>

+<p>This is a minor update which includes the following:</p>

+<ul>

+	<li>Addition of the <span class="inline_code"><a href="#src2auxdstrect">src2auxdstrect</a></span> and

+	<span class="inline_code"><a href="#maskauxdstrect">maskauxdstrect</a></span> members to <span class="inline_code">

+	<a href="#bvbltparams">bvbltparams</a></span> with example.</li>

+	<li>Addition of <span class="inline_code"><a href="#BVFLAG_SRC2_AUXDSTRECT">BVFLAG_SRC2_AUXDSTRECT</a></span> and <span class="inline_code">

+	<a href="#BVFLAG_MASK_AUXDSTRECT">BVFLAG_MASK_AUXDSTRECT</a></span> flags.</li>

+	<li>Added <span class="inline_code"><a href="#BVAT_PHYSADDR">BVAT_PHYSADDR</a></span> to the kernel mode

+	<span class="inline_code"><a href="#bvbuffdesc.auxtype">bvbuffdesc.auxtype</a></span> enumerations.</li>

+	<li>Added clarification to the <span class="inline_code"><a href="#bvphysdesc">bvphysdesc</a></span> documentation.</li>

+</ul>

+<p>Compatibility</p>

+<ul>

+	<li>Clients that do not use the <span class="inline_code"><a href="#BVFLAG_SRC1_AUXDSTRECT">BVFLAG_*_AUXDSTRECT</a></span> 

+	flags will not be affected.</li>

+	<li>Clients using the new (long) <span class="inline_code"><a href="#bvbltparams">bvbltparams</a></span> will work with 

+	older implementations.&nbsp; If the clients set the <span class="inline_code"><a href="#BVFLAG_SRC2_AUXDSTRECT">

+	BVFLAG_*_AUXDSTRECT</a></span> flags, the implementations will return <span class="inline_code">BVERR_FLAGS</span>, 

+	indicating the lack of support for this feature.</li>

+	<li>Implementations supporting the new <span class="inline_code"><a href="#bvbltparams">bvbltparams</a></span> will 

+	accept the older (smaller) version, distinguished by the <span class="inline_code">

+	<a href="#bvbltparams.structsize">structsize</a></span> member.&nbsp; Clients using the older versions will not set 

+	the <span class="inline_code"><a href="#BVFLAG_SRC2_AUXDSTRECT">BVFLAG_*_AUXDSTRECT</a></span> flags, so the new 

+	members will not be utilized.</li>

+	<li>Clients using <span class="inline_code"><a href="#BVAT_PHYSADDR">BVAT_PHYSADDR</a></span> will get an error from 

+	implementations that do not support this enumeration.&nbsp; The <span class="inline_code"><a href="#BVAT_PHYSDESC">

+	BVAT_PHYSDESC</a></span> may be used if supported by the implementation, but care must be taken to ensure the buffer 

+	is defined properly.&nbsp; See <span class="inline_code"><a href="#bvphysdesc">bvphysdesc</a></span> for details.</li>

+</ul>

+<hr />

+<p class="Header1">BLTsville Neighborhoods</p>

+<p>Implementations may be software (CPU) or 2-D hardware, and many may coexist.&nbsp; Each implementation will have an individual 

+entry point, so it can be directly addressed.&nbsp; But there will also be a more general interface for each of these two 

+types of implementations so that system integrators can choose the most appropriate implementation.&nbsp; In other words, 

+the system integrator will choose one software and one 2-D hardware implementation to be the &quot;default&quot; used when a client 

+does not need to choose a specific implementation.</p>

+<p class="Header2">User Mode Interface</p>

+<p>Clients use the standard names below to access the default implementations.&nbsp; The client then imports the pointers 

+to the functions.&nbsp; (The specific name decoration and import method will be dictated by the host Operating System (O/S).)&nbsp; 

+Some examples:</p>

+<ul>

+	<li>CPU:&nbsp; <span class="filename">bltsville_cpu</span><ul>

+		<li>Linux/Android:&nbsp; <span class="filename">libbltsville_cpu.so</span></li>

+		<li>Windows:&nbsp; <span class="filename">bltsville_cpu.dll</span></li>

+		<li>etc.</li>

+	</ul>

+	</li>

+	<li>2-D hardware:&nbsp; <span class="filename">bltsville_hw2d</span><ul>

+		<li>Linux/Android:&nbsp; <span class="filename">libbltsville_hw2d.so</span></li>

+		<li>Windows:&nbsp; <span class="filename">bltsville_hw2d.dll</span></li>

+		<li>etc.</li>

+	</ul>

+	</li>

+</ul>

+<p>Usually these entry points will be symbolic links (either explicit in systems like Linux which support them, or implicit 

+using a thin wrapper) to the specific implementation.&nbsp; This allows system integrators to connect the client with the 

+most capable implementation available in the system.&nbsp; For example, <span class="filename">bltsville_hw2d</span> might 

+be a symbolic link to <span class="filename">bltsville_gc2d</span>.</p>

+<p>In addition, there may be more implementations co-existing in a given system.&nbsp; These will have additional unique 

+names as determined by the vendors.&nbsp; For example:</p>

+<ul>

+	<li>Reference CPU software implementation:&nbsp; <span class="filename">bltsville_refcpu</span></li>

+	<li>System DMA 2-D hardware implementation:&nbsp; <span class="filename">bltsville_mydma</span></li>

+</ul>

+<p class="Header3">Initialization</p>

+<p>In general, each O/S has the ability to manually load a library.&nbsp; This in turn causes a function in the library 

+to be called so the library can perform initialization.&nbsp; Unfortunately, not all O/Ss allow this initialization 

+function to return an error if the initialization fails.&nbsp; Equally unfortunately, it may be necessary for the 

+initialization to be performed in that function.&nbsp; To accommodate this, BLTsville defers the specific initialization 

+to the O/S environment.</p>

+<p class="Header4">Linux/Android</p>

+<p>The client will call <span class="inline_code">dlopen()</span> to open the library.&nbsp; It will then import the

+<span class="inline_code">bv_*()</span> functions, and call them as desired.&nbsp; Initialization will occur in 

+association with one or more of these activities.&nbsp; If the initialization fails, the bv_*() functions will return 

+the <span class="inline_code">BVERR_RSRC</span> error, indicating that a required resource was not obtained.</p>

+<p class="imponly"><strong>Implementations Only<br />

+</strong><br />

+If the library has designated a function with the <span class="inline_code">__attribute__ ((constructor))</span>, that 

+function will be called.&nbsp; Linux implementations may use this function to perform initialization (including opening 

+an interface to an associated kernel module).&nbsp; However, since this function cannot return an error, and thus cannot 

+fail, if the initialization fails, this must be recorded.&nbsp; Then, when the client calls any of the

+<span class="inline_code">bv_*()</span> functions, these should immediately return the <span class="inline_code">

+BVERR_RSRC</span> error, indicating that the library was unable to initialize (obtain a necessary resource).<br />

+<br />

+Linux implementations may also choose to initialize on the first call to a <span class="inline_code">bv_*()</span> 

+function.&nbsp; Failure is likewise indicated by returning the <span class="inline_code">BVERR_RSRC</span> error.<br />

+<br />

+<strong>NOTE:&nbsp; Be careful not to repeatedly attempt initialization when a failure is encountered.&nbsp; Some 

+initializations, and especially initialization failures, can take a long time.&nbsp; This means clients trying to call

+</strong><span class="inline_code"><strong>bv_*()</strong></span><strong> functions (presumably before falling back to 

+alternatives) will be repeatedly penalized if the library can&#39;t initialize.&nbsp; Instead, attempt initialization 

+once, and from them on return <span class="inline_code">BVERR_RSRC</span>.</strong></p>

+<p class="Header2">Kernel Mode Interface</p>

+<p>For most kernel space BLTsville clients, only a 2-D hardware implementation will be used.&nbsp; However, both types of 

+implementations are supported.&nbsp; Clients use the standard names below to access the default implementations and obtain 

+pointers to the functions.&nbsp; (The specific method of obtaining the interface will be dictated by the host Operating 

+System (O/S).)&nbsp; Some examples:</p>

+<ul>

+	<li>CPU<ul>

+		<li>Linux/Android <span class="inline_code">bvcpu_entry()</span></li>

+		<li>etc.</li>

+	</ul>

+	</li>

+	<li>2-D hardware<ul>

+		<li>Linux/Android <span class="inline_code">bv2d_entry()</span></li>

+		<li>etc.</li>

+	</ul>

+	</li>

+</ul>

+<p>These entry points may represent the implementations themselves, but more likely they will link the client to the implementations 

+using more specific names.&nbsp; For example, <span class="inline_code">bv2d_entry()</span> may link the client to

+<span class="inline_code">gcbv_entry()</span>.</p>

+<p>In addition, there may be more implementations co-existing in the kernel.&nbsp; These will require additional unique 

+names as determined by the vendors.&nbsp; For example:</p>

+<ul>

+	<li>Reference CPU software implementation:&nbsp; <span class="inline_code">cpurefbv_entry()</span></li>

+	<li>Vivante GC320 2-D hardware implementation:&nbsp; <span class="inline_code">gcbv_entry()</span></li>

+</ul>

+<hr />

+<p class="Header1">Things To Do In BLTsville</p>

+<p>BLTsville&#39;s interface consists of three or four functions per implementation, which must be imported by the 

+client at run time:</p>

+<ul>

+	<li><span class="inline_code"><a href="#bv_map">bv_map()</a></span></li>

+	<li><span class="inline_code"><a href="#bv_blt">bv_blt()</a></span></li>

+	<li><span class="inline_code"><a href="#bv_unmap">bv_unmap()</a></span></li>

+	<li><span class="inline_code"><a href="#bv_cache">bv_cache()</a></span> (optional)</li>

+</ul>

+<p class="note">NOTE:&nbsp; If the library failed to initialize, these functions will return <span class="inline_code">

+BVERR_RSRC</span>, indicating that a required resource was not obtained.</p>

+<a name="bv_map" class="Code_Header">bv_map()</a>

+<p class="code_block">enum bverror bv_map(<a href="#bvbuffdesc">struct bvbuffdesc* buffdesc</a>);</p>

+<p><span class="strong_emphasis">BLTsville does not allocate buffers.</span>&nbsp;&nbsp; Clients must describe a buffer 

+in BLTsville using the <span class="inline_code"><a href="#bvbuffdesc">bvbuffdesc</a></span> structure so a given implementation 

+can access the buffer.</p>

+<p><span class="inline_code">bv_map()</span> is used to provide the implementation an opportunity to associate hardware 

+resources with the specified buffer.&nbsp; Most hardware requires this type of mapping, and there is usually appreciable 

+overhead associated with it.&nbsp; By providing a separate call for this operation, BLTsville allows the client to move 

+this overhead to the most appropriate time in its execution.</p>

+<p>For a given buffer, the client can call the <span class="inline_code">bv_map()</span> function imported from each implementation 

+to establish the mapping immediately.&nbsp; But this is not required.</p>

+<p>As a special bonus, BLTsville clients can call to any implementation&#39;s <span class="inline_code">bv_map()</span>.&nbsp; 

+This is sufficient to indicate that the client can be trusted to make the corresponding call to

+<span class="inline_code"><a href="#bv_unmap">bv_unmap()</a></span> upon destruction of the buffer.&nbsp; Then when a client 

+calls an implementation&#39;s <span class="inline_code"><a href="#bv_blt">bv_blt()</a></span>, if the mapping needs to be done, 

+it&#39;s done at that time.&nbsp; But the mapping is maintained, so that the overhead is avoided on subsequent

+<span class="inline_code"><a href="#bv_blt">bv_blt()</a></span> calls.&nbsp; This lets implementations use <em>lazy mapping</em> 

+only as necessary.&nbsp; If an implementation is not called, the mapping is not done.</p>

+<p><em>Normally, the lowest overhead </em><span class="inline_code"><em>bv_map()</em></span><em> call will be in the CPU-based 

+implementation.&nbsp; So most clients will want to make a single, low overhead </em><span class="inline_code"><em>bv_map()</em></span><em> 

+call to the bltsville_cpu implementation to avoid the mapping/unmapping overhead on each </em><span class="inline_code">

+<a href="#bv_blt"><em>bv_blt()</em></a></span><em> call, while avoiding the mapping overhead when possible.</em></p>

+<p><em><strong>Calling </strong></em><span class="inline_code"><em><strong>bv_map()</strong></em></span><em><strong> is 

+actually optional prior to calling </strong></em><span class="inline_code"><a href="#bv_blt"><em><strong>bv_blt()</strong></em></a></span><em><strong>.&nbsp; 

+However, if it is not called at least once for a given buffer, it must be assumed that </strong></em>

+<span class="inline_code"><a href="#bv_unmap"><strong><em>bv_unmap()</em></strong></a></span><em><strong> will not be called.&nbsp; 

+So the mapping must be done when </strong></em><span class="inline_code"><a href="#bv_blt"><em><strong>bv_blt()</strong></em></a></span><em><strong> 

+is called, and unmapping done when it is complete.&nbsp; This means the overhead will be incurred for every </strong>

+</em><a href="#bv_blt" class="inline_code"><em><strong>bv_blt()</strong></em></a><em><strong> call which uses that buffer.</strong></em></p>

+<p class="note">NOTE: Obviously any API cannot add capabilities beyond an implementation&#39;s capabilities.&nbsp; So, for example, 

+if an implementation requires memory to be allocated from a special pool of memory, that responsibility falls upon the client.&nbsp; 

+The <span class="inline_code">bv_map()</span> function for that implementation will need to check the characteristics of 

+the memory and return an error if it does not meet the necessary criteria.</p>

+<p class="Header4"><a name="bv_map_Function_Sequences">Function Sequences</a></p>

+<p>To clarify, here are some function sequences and the operations associated with them:</p>

+<table class="indent">

+	<tr>

+		<td class="ctr_thin_bord"><strong>Implementation</strong></td>

+		<td class="ctr_thin_bord"><strong>Function</strong></td>

+		<td class="ctr_thin_bord"><strong>Operation</strong></td>

+	</tr>

+	<tr>

+		<td class="ctr_thin_bord">A</td>

+		<td class="thin_bord"><span class="inline_code"><a href="#bv_blt">bv_blt()</a></span></td>

+		<td class="thin_bord">map A<br />

+		BLT A<br />

+		unmap A</td>

+	</tr>

+	<tr>

+		<td class="ctr_thin_bord">A</td>

+		<td class="thin_bord"><span class="inline_code"><a href="#bv_blt">bv_blt()</a></span></td>

+		<td class="thin_bord">map A<br />

+		BLT A<br />

+		unmap A</td>

+	</tr>

+	<tr>

+		<td class="ctr_thin_bord">B</td>

+		<td class="thin_bord"><span class="inline_code"><a href="#bv_blt">bv_blt()</a></span></td>

+		<td class="thin_bord">map B<br />

+		BLT B<br />

+		unmap B</td>

+	</tr>

+</table>

+<br />

+<table class="indent">

+	<tr>

+		<td class="ctr_thin_bord"><strong>Implementation</strong></td>

+		<td class="ctr_thin_bord"><strong>Function</strong></td>

+		<td class="ctr_thin_bord"><strong>Operation</strong></td>

+	</tr>

+	<tr>

+		<td class="ctr_thin_bord">A</td>

+		<td class="thin_bord"><span class="inline_code"><a href="#bv_map">bv_map()</a></span></td>

+		<td class="thin_bord">map A</td>

+	</tr>

+	<tr>

+		<td class="ctr_thin_bord">A</td>

+		<td class="thin_bord"><span class="inline_code"><a href="#bv_blt">bv_blt()</a></span></td>

+		<td class="thin_bord">BLT A</td>

+	</tr>

+	<tr>

+		<td class="ctr_thin_bord">A</td>

+		<td class="thin_bord"><span class="inline_code"><a href="#bv_blt">bv_blt()</a></span></td>

+		<td class="thin_bord">BLT A</td>

+	</tr>

+	<tr>

+		<td class="ctr_thin_bord">A</td>

+		<td class="thin_bord"><span class="inline_code"><a href="#bv_unmap">bv_unmap()</a></span></td>

+		<td class="thin_bord">unmap A</td>

+	</tr>

+</table>

+<br />

+<table class="indent">

+	<tr>

+		<td class="ctr_thin_bord"><strong>Implementation</strong></td>

+		<td class="ctr_thin_bord"><strong>Function</strong></td>

+		<td class="ctr_thin_bord"><strong>Operation</strong></td>

+	</tr>

+	<tr>

+		<td class="ctr_thin_bord">A</td>

+		<td class="thin_bord"><span class="inline_code"><a href="#bv_map">bv_map()</a></span></td>

+		<td class="thin_bord">map A</td>

+	</tr>

+	<tr>

+		<td class="ctr_thin_bord">B</td>

+		<td class="thin_bord"><span class="inline_code"><a href="#bv_map">bv_map()</a></span></td>

+		<td class="thin_bord">map B</td>

+	</tr>

+	<tr>

+		<td class="ctr_thin_bord">A</td>

+		<td class="thin_bord"><span class="inline_code"><a href="#bv_blt">bv_blt()</a></span></td>

+		<td class="thin_bord">BLT A</td>

+	</tr>

+	<tr>

+		<td class="ctr_thin_bord">B</td>

+		<td class="thin_bord"><span class="inline_code"><a href="#bv_blt">bv_blt()</a></span></td>

+		<td class="thin_bord">BLT B</td>

+	</tr>

+	<tr>

+		<td class="ctr_thin_bord">A</td>

+		<td class="thin_bord"><span class="inline_code"><a href="#bv_unmap">bv_unmap()</a></span></td>

+		<td class="thin_bord">unmap A</td>

+	</tr>

+	<tr>

+		<td class="ctr_thin_bord">B</td>

+		<td class="thin_bord"><span class="inline_code"><a href="#bv_unmap">bv_unmap()</a></span></td>

+		<td class="thin_bord">unmap B</td>

+	</tr>

+</table>

+<br />

+<table class="indent">

+	<tr>

+		<td class="ctr_thin_bord"><strong>Implementation</strong></td>

+		<td class="ctr_thin_bord"><strong>Function</strong></td>

+		<td class="ctr_thin_bord"><strong>Operation</strong></td>

+	</tr>

+	<tr>

+		<td class="ctr_thin_bord">A</td>

+		<td class="thin_bord"><span class="inline_code"><a href="#bv_map">bv_map()</a></span></td>

+		<td class="thin_bord">map A</td>

+	</tr>

+	<tr>

+		<td class="ctr_thin_bord">B</td>

+		<td class="thin_bord"><span class="inline_code"><a href="#bv_blt">bv_blt()</a></span></td>

+		<td class="thin_bord">map B<br />

+		BLT B</td>

+	</tr>

+	<tr>

+		<td class="ctr_thin_bord">B</td>

+		<td class="thin_bord"><span class="inline_code"><a href="#bv_blt">bv_blt()</a></span></td>

+		<td class="thin_bord">BLT B</td>

+	</tr>

+	<tr>

+		<td class="ctr_thin_bord">A</td>

+		<td class="thin_bord"><span class="inline_code"><a href="#bv_unmap">bv_unmap()</a></span></td>

+		<td class="thin_bord">unmap A<br />

+		unmap B</td>

+	</tr>

+</table>

+<br />

+<div class="note">

+	NOTE:&nbsp; Calling <span class="inline_code">bv_map()</span> and <span class="inline_code"><a href="#bv_unmap">

+	bv_unmap()</a></span> with the same <span class="inline_code"><a href="#bvbuffdesc">bvbuffdesc</a></span> from 

+	different, unsynchronized threads, even (especially) from different implementations, will result in undefined 

+	behavior.&nbsp; This is similar to calling <span class="inline_code">malloc()</span> and <span class="inline_code">

+	free()</span> using the same buffer pointer in different, unsynchronized threads.&nbsp; While this may work 

+	sometimes and for some implementations and combinations of implementations, BLTsville does not provide any 

+	synchronization mechanism to make this safe.&nbsp; Clients must ensure that these calls are synchronized in cases 

+	where such behavior appears to be necessary.</div>

+<br />

+<a name="bv_blt" class="Code_Header">bv_blt()</a>

+<p class="code_block">enum bverror bv_blt(<a href="#bvbltparams">struct bvbltparams* bltparams</a>);</p>

+<p>The main function of BLTsville is <span class="inline_code">bv_blt()</span>.&nbsp; A <span class="inline_code">

+<a href="#bvbltparams">bvbltparams</a></span> structure is passed into <span class="inline_code">bv_blt()</span> to trigger 

+the desired 2-D operation.</p>

+<a name="bv_unmap" class="Code_Header">bv_unmap()</a>

+<p class="code_block">enum bverror bv_unmap(<a href="#bvbuffdesc">struct bvbuffdesc* buffdesc</a>);</p>

+<p><span class="inline_code">bv_unmap()</span> is used to free implementation resources associated with a buffer.&nbsp; 

+Normally, if <span class="inline_code"><a href="#bv_map">bv_map()</a></span> was called for a given buffer,

+<span class="inline_code">bv_unmap()</span> should be called as well.</p>

+<p>For convenience, only one <span class="inline_code">bv_unmap()</span> needs to be called for each buffer, regardless 

+of how many implementations were used, including multiple calls to <span class="inline_code"><a href="#bv_map">bv_map()</a></span>.</p>

+<p>Also for convenience, <span class="inline_code">bv_unmap()</span> may be called multiple times on the same buffer.&nbsp; 

+Note that only the first call will actually free (all) the associated resources.&nbsp; See the

+<a href="#bv_map_Function_Sequences">Function Sequences</a> under <span class="inline_code"><a href="#bv_map">bv_map()</a></span> 

+for more details.</p>

+<p class="imponly"><strong>Implementations Only</strong><br />

+<br />

+Implementations must ensure that unmapping of buffers which are in use by asynchronous BLTs are appropriately delayed to 

+avoid improper access.</p>

+<a name="bv_cache" class="Code_Header">bv_cache()</a>

+<p class="code_block">enum bverror bv_cache(<a href="#bvcopprams">struct bvcopparams *copparams</a>);</p>

+<p><span class="inline_code">bv_cache()</span> provides manual CPU cache control to maintain cache coherence of surfaces 

+between the CPU and other hardware.&nbsp; The <a href="#bvbuffdesc">bvcopparams</a> structure provides the information needed 

+to properly manipulate the CPU cache.</p>

+<p>This function is <em>optional</em>.&nbsp; If this function fails to import, it means the implementation does not provide 

+it, but <span class="inline_code"><a href="#bv_map">bv_map()</a></span>,&nbsp; <span class="inline_code">

+<a href="#bv_blt">bv_blt()</a></span>, and <span class="inline_code"><a href="#bv_unmap">bv_unmap()</a></span> may still 

+be used.</p>

+<p><em>In general, this function will be provided with BLTsville implementations which utilize 2-D hardware, even though 

+it manipulates the CPU cache.&nbsp; This is because most systems require a kernel module to manipulate the cache, and this 

+is not always practical to include with a user-mode CPU implementation.</em></p>

+<p><strong>BEWARE:&nbsp; Manipulation of the CPU cache is tricky.&nbsp; Moreover, different CPUs behave differently, so 

+cache manipulation that works on one device may fail on another.&nbsp; Also, mismanaged operation of the cache can have 

+significant impact on overall system performance.&nbsp; And incorrect manipulation of the cache can cause instability or 

+crashes.&nbsp; Please read and understand all of the discussions below before using this function.</strong></p>

+<ol>

+	<li>To avoid system instability, do not perform cache operations on buffers which would not be accessed by BLTsville.</li>

+	<li>For maximum performance, combine adjacent rectangles into one <span class="inline_code">bv_cache()</span> call.&nbsp; 

+	For example, when BLTing a line of characters, do not issue a <span class="inline_code">bv_cache()</span> call for each 

+	character.&nbsp; Instead, make one call to bv_cache() which includes all the characters.</li>

+	<li>When using a hardware BLTsville implementation to read data written into a cached surface by the CPU, use the

+	<span class="inline_code"><a href="#CPU_TO_DEVICE">BVCACHE_CPU_TO_DEVICE</a></span> operation after the CPU has completed 

+	its operation and before the hardware BLTsville operation is initiated.</li>

+	<li>When using a hardware BLTsville implementation to write data into a cached surface that will be read by the CPU, 

+	use the <span class="inline_code"><a href="#CPU_FROM_DEVICE">BVCACHE_CPU_FROM_DEVICE</a></span> operation after the 

+	hardware BLTsville operation has completed (note this means after the callback if the BLT is asynchronous) and before 

+	the CPU accesses the surface.</li>

+	<li>When using a hardware BLTsville implementation to write data into a cached surface that has been written by the 

+	CPU, using the <span class="inline_code"><a href="#CPU_TO_DEVICE">BVCACHE_CPU_TO_DEVICE</a></span> operation after the 

+	CPU has completed its operation and before the hardware BLTsville operation is initiated.<ul>

+		<li class="bold_sans">NOTE:&nbsp; This cache operation may not be necessary on all hardware, but it is good practice to perform it 

+		anyway.&nbsp; This operation will be necessary for a CPU with a write allocation policy on the cache, but may not 

+		be necessary for CPUs without such a configuration.</li>

+		<li class="bold_sans"><strong>NOTE WELL:&nbsp; CPU access to a destination buffer is not always initiated by the client.&nbsp; Buffers 

+		recently allocated may be cleared by the CPU on behalf of the client via the allocation call.&nbsp; Failure to perform 

+		this operation may result in image corruption even if no further CPU accesses are performed on the surface!</strong></li>

+	</ul>

+	</li>

+</ol>

+<table class="example">

+	<tr>

+		<td>

+		<p><strong>Example</strong>:&nbsp; On one particular device, a surface was allocated using the standard user mode

+		<span class="inline_code">malloc()</span>.&nbsp; An image was copied into a portion of this surface using a hardware 

+		implementation of BLTsville.&nbsp; The result was then read by the CPU.</p>

+		<p>Logically, <span class="inline_code">bv_cache()</span> was used to perform a <span class="inline_code">

+		<a href="#CPU_FROM_DEVICE">BVCACHE_CPU_FROM_DEVICE</a></span> operation after the hardware-based BLTsville operation 

+		completed, but before the CPU read was performed.&nbsp; However, corruption appeared both inside the image copied, 

+		as well as outside the image!</p>

+		<p>Both corruptions were caused by not realizing that there was a CPU operation (clear) performed on behalf of the

+		<span class="inline_code">malloc()</span>, for which the proper cache manipulation was not performed.</p>

+		<p>The corruption outside the image was due to data in the cache being invalidated before it reached the memory.&nbsp; 

+		As mentioned above, buffers allocated are normally cleared by the system.&nbsp; In this case, since the buffer used 

+		for the surface was configured with a write allocated cache, this meant that not all writes to clear the buffer 

+		were in memory when the&nbsp; <span class="inline_code"><a href="#CPU_FROM_DEVICE">BVCACHE_CPU_FROM_DEVICE</a></span> 

+		operation was performed.&nbsp; As a result, the uncommitted data in the cache was invalidated and lost, and the 

+		previous contents of the memory remained for the CPU to read.</p>

+		<p>The corruption inside the image was caused by data in the cache being committed to memory after the hardware 

+		BLT completed, but before the <span class="inline_code"><a href="#CPU_FROM_DEVICE">BVCACHE_CPU_FROM_DEVICE</a></span> 

+		operation was executed.</p>

+		<p>Both corruptions were corrected by performing a <span class="inline_code"><a href="#CPU_TO_DEVICE">BVCACHE_CPU_TO_DEVICE</a></span> 

+		operation on the <span class="underline">destination</span> surface <strong>before</strong> performing the BLT (item 

+		5 above), in addition to the <span class="inline_code"><a href="#CPU_FROM_DEVICE">BVCACHE_CPU_FROM_DEVICE</a></span> 

+		operation performed <strong>after</strong> the BLT (item 3 above).</p>

+		</td>

+	</tr>

+</table>

+<br />

+<hr /><a name="bvbltparams" class="Code_Header">bvbltparams</a>

+<p><span class="inline_code">bvbltparams</span> is the central structure in BLTsville.&nbsp; This structure holds the details 

+of the BLT being requested by the client.</p>

+<p class="small_code_block">union bvop {<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned short <a href="#rop">rop</a>;<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; enum bvblend <a href="#blend">blend</a>;<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct bvfilter *<a href="#filter">filter</a>;<br />

+};<br />

+<br />

+struct bvinbuff {<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="#bvbuffdesc">struct bvbuffdesc</a> *<a href="#src1.desc">desc</a>;<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="#bvtileparams">struct bvtileparams</a> *<a href="#src1.tileparams">tileparams</a>;<br />

+};<br />

+<br />

+struct bvbltparams {<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned int <a href="#bvbltparams.structsize">structsize</a>;<br />

+<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char *<a href="#errdesc">errdesc</a>;<br />

+<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned long <a href="#implementation">implementation</a>;<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned long <a href="#flags">flags</a>;<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; union bvop <a href="#op">op</a>;<br />

+<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void *<a href="#colorkey">colorkey</a>;<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; union bvalpha <a href="#globalalpha">globalalpha</a>;<br />

+<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; enum bvscalemode <a href="#scalemode">scalemode</a>;<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; enum bvdithermode <a href="#dithermode">dithermode</a>;<br />

+<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="#bvbuffdesc">struct bvbuffdesc</a> *<a href="#dstdesc">dstdesc</a>;<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="#bvsurfgeom">struct bvsurfgeom</a> *<a href="#dstgeom">dstgeom</a>;<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="#bvrect">struct bvrect</a> <a href="#dstrect">dstrect</a>;<br />

+<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; union bvinbuff <a href="#src1">src1</a>;<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="#bvsurfgeom">struct bvsurfgeom</a> *<a href="#src1geom">src1geom</a>;<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="#bvrect">struct bvrect</a> <a href="#src1rect">src1rect</a>;<br />

+<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; union bvinbuff <a href="#src2">src2</a>;<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="#bvsurfgeom">struct bvsurfgeom</a> *<a href="#src2geom">src2geom</a>;<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="#bvrect">struct bvrect</a> <a href="#src2rect">src2rect</a>;<br />

+<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; union bvinbuff <a href="#mask">mask</a>;<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="#bvsurfgeom">struct bvsurfgeom</a> *<a href="#maskgeom">maskgeom</a>;<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="#bvrect">struct bvrect</a> <a href="#maskrect">maskrect</a>;<br />

+<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="#bvrect">struct bvrect</a> <a href="#cliprect">cliprect</a>;<br />

+<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned long <a href="#batchflags">batchflags</a>;<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct bvbatch *<a href="#batch">batch</a>;<br />

+<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void (*<a href="#callbackfn">callbackfn</a>)(<a href="#bvcallbackerror">struct 

+bvcallbackerror</a> *err,<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 

+unsigned long callbackdata);<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned long <a href="#callbackdata">callbackdata</a>;<br />

+<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="#bvrect">struct bvrect</a> <a href="#src2auxdstrect">src2auxdstrect</a>;<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="#bvrect">struct bvrect</a> <a href="#maskauxdstrect">maskauxdstrect</a>;<br />

+};</p>

+<a name="bvbltparams.structsize" class="Code_Header_2">bvbltparams.structsize</a>

+<p><span class="code_block">unsigned long structsize; /* input */</span></p>

+<p>This member is used to allow backwards and forwards compatibility between versions of BLTsville.&nbsp; It should be set 

+to the <span class="inline_code">sizeof()</span> the structure by the client or implementation, whichever allocated the 

+structure.</p>

+<p>BLTsville is designed to be forwards and backwards compatible between client and library versions.&nbsp; But this compatibility 

+would be eliminated if clients chose to check for a specific version of the BLTsville implementations and fail if the specific 

+version requested was not in place.&nbsp; So, instead of exporting a version number, BLTsville structures use the

+<span class="inline_code">structsize</span> member to indicate the number of bytes in the structure.&nbsp; This is used 

+to communicate between the client and implementation which portions of the structure exist.&nbsp; This effectively bypasses 

+the concept of a version and focuses on the specifics of what changes need to be considered to maintain compatibility.</p>

+<ol>

+	<li>When an old client calls into a new implementation, that implementation will realize if the client only provides 

+	a subset of an updated structure.&nbsp; The implementation will handle this and utilize only that information which 

+	has been provided.&nbsp; New features will be disabled, but functionality will be maintained.</li>

+	<li>When a new client calls into an old implementation, that implementation will ignore the extra members of the structure 

+	and operate in ignorance of them.&nbsp; If these members are necessary for some new functionality, this will be evident 

+	from other fields in the structure, so that the implementation can gracefully fail.</li>

+</ol>

+<p>If <span class="inline_code">structsize</span> is set to a value that is too small for an implementation, it may return 

+a <span class="inline_code"><a href="#BVERR_BLTPARAMS_VERS">BVERR_BLTPARAMS_VERS</a></span> error.</p>

+<p class="Code_Header_2"><a name="bvbltparams.errdesc">bvbltparams.errdesc</a></p>

+<p><span class="code_block">char* errdesc; /* output */</span></p>

+<p><span class="inline_code">errdesc</span> is optionally used by implementations to pass a 0-terminated string with additional 

+debugging information back to clients for debugging purposes.&nbsp; <span class="inline_code">errdesc</span> is not localized 

+or otherwise meant to provide information that is displayed to users.</p>

+<p class="Code_Header_2"><a name="implementation">bvbltparams.implementation</a></p>

+<p class="code_block">unsigned long implementation; /* input */</p>

+<p>Multiple implementations of BLTsville can be combined under managers which can distribute the BLT requests to the implementations 

+based on whatever criteria the manager chooses.&nbsp; This might include availability of the operation, performance, loading, 

+or power state.&nbsp; In such a scenario, the client may need to override or augment the choice made by the manager.&nbsp; 

+This field allows that control.</p>

+<p><strong><em>Note that this feature is extremely complicated, and more detailed documentation needs to be created to allow 

+creation of managers and smooth integration by a client.&nbsp; There are serious issues that must be understood before any 

+manager can be put into place, such as CPU cache coherence and multiple implementation operation interdependence.&nbsp; 

+For now, this field should be set to 0 by clients.</em></strong></p>

+<p>If the implementation cannot respond to the <span class="inline_code">implementation</span> flags set, it may return 

+a <span class="inline_code"><a href="#BVERR_IMPLEMENTATION">BVERR_IMPLEMENTATION</a></span> error.</p>

+<p class="Code_Header_2"><a name="flags">bvbltparams.flags</a></p>

+<p class="code_block">unsigned long flags; /* input */</p>

+<p>The <span class="inline_code">flags</span> member provides the baseline of information to <span class="inline_code">

+<a href="#bv_blt">bv_blt()</a></span> about the type of BLT being requested.</p>

+<p>To maintain compatibility, unused bits in the flags member should be set to 0.</p>

+<p>If the flags set are not supported by the implementation, it may return <span class="inline_code">

+<a href="#BVERR_FLAGS">BVERR_FLAGS</a></span>, or a more specific <a href="#bverror">error code</a>.</p>

+<p class="Code_Header_3"><a name="BVFLAG_OP_">bvbltparams.flags - BVFLAG_OP_*</a></p>

+<p>The <span class="inline_code">op</span> field of the flags member specifies the type of BLT operation to perform.&nbsp; 

+Currently there are three types of BLT operations defined:</p>

+<table class="indent">

+	<tr>

+		<td valign="top">1.</td>

+		<td><span class="inline_code"><strong><a name="BVFLAG_ROP">BVFLAG_ROP</a></strong></span><br />

+		<p>This flag indicates the operation being performed is a raster operation, and the <span class="inline_code">

+		<a href="#op">bvbltparams.op</a></span> union is treated as <span class="inline_code"><a href="#rop">rop</a></span>.&nbsp; 

+		Raster OPerations are binary operations performed on the bits of the inputs.&nbsp; See <span class="inline_code">

+		<a href="#rop">bvbltparams.op.rop</a></span> for details.<br />

+		<br />

+		</p>

+		</td>

+	</tr>

+	<tr>

+		<td valign="top">2.</td>

+		<td>

+		<p><span class="inline_code"><strong><a name="BVFLAG_BLEND">BVFLAG_BLEND</a></strong></span><br />

+		</p>

+		<p>This flag indicates the operation being performed is a blend, and the <span class="inline_code">

+		<a href="#op">bvbltparams.op</a></span> union is treated as <span class="inline_code"><a href="#blend">blend</a></span>.&nbsp; 

+		Blending involves mixing multiple layers of pixels using the specified equations.&nbsp; Surrounding pixels are not 

+		involved in blend operations.&nbsp; See <span class="inline_code"><a href="#blend">bvbltparams.op.blend</a></span> 

+		for details.<br />

+		<br />

+		</p>

+		</td>

+	</tr>

+	<tr>

+		<td valign="top">3.</td>

+		<td><span class="inline_code"><strong><a name="BVFLAG_FILTER">BVFLAG_FILTER</a></strong></span><br />

+		<br />

+		This flag indicates the operation being performed is a filter, and the <span class="inline_code"><a href="#op">bvbltparams.op</a></span> 

+		union is treated as <span class="inline_code"><a href="#filter">filter</a></span>.&nbsp; Filtering involves mixing 

+		multiple layers of pixels.&nbsp; Surrounding pixels are involved in filter operations.&nbsp; See

+		<span class="inline_code"><a href="#filter">bvbltparams.op.filter</a></span> for details.<br />

+		</td>

+	</tr>

+</table>

+<p class="Code_Header_3"><a name="BVFLAG_KEY_SRC">bvbltparams.flags - BVFLAG_KEY_SRC</a>/<a name="BVFLAG_KEY_DST">DST</a></p>

+<p>The <span class="inline_code">BVFLAG_KEY_SRC</span> and <span class="inline_code">BVFLAG_KEY_DST</span> enable source 

+and destination color keying, respectively.&nbsp; When either flag is set, the <span class="inline_code">

+<a href="#colorkey">colorkey</a></span> member of <span class="inline_code"><a href="#bvbltparams">bvbltparams</a></span> 

+is used.</p>

+<p><span class="inline_code">BVFLAG_KEY_SRC</span> and <span class="inline_code">BVFLAG_KEY_DST</span> are mutually exclusive.</p>

+<p>See <span class="inline_code"><a href="#colorkey">bvbltparams.colorkey</a></span> for details.</p>

+<p class="Code_Header_3"><a name="BVFLAG_CLIP">bvbltparams.flags - BVFLAG_CLIP</a></p>

+<p>When <span class="inline_code">BVFLAG_CLIP</span> is set, the <span class="inline_code"><a href="#cliprect">cliprect</a></span> 

+member of <span class="inline_code"><a href="#bvbltparams">bvbltparams</a></span> is used by the implementation as a limiting 

+rectangle on data written to the destination.&nbsp; See <span class="inline_code"><a href="#cliprect">cliprect</a></span> 

+for details.</p>

+<p class="Code_Header_3"><a name="BVFLAG_SRCMASK">bvbltparams.flags - BVFLAG_SRCMASK</a></p>

+<p>Normally, the mask is applied at the destination, after all scaling has been completed (including scaling the mask if 

+necessary).&nbsp; But some environments require that the mask be applied at the sources, before scaling occurs.&nbsp; The

+<span class="inline_code">BVFLAG_SRCMASK</span> flag requests that the implementation use this method if supported.</p>

+<p class="Code_Header_3">bvbltparams.flags - BVFLAG_TILE_*</p>

+<p>Normally, when a source&#39;s size does not match the destination, the source is scaled to fill the destination.&nbsp; But 

+when the corresponding <span class="inline_code">BVFLAG_TILE_*</span> flag is set, this behavior is modified.</p>

+<p>First, the source&#39;s size specifies a tile (or pattern, or brush) to be used to fill the destination.&nbsp; This tile 

+is replicated instead of scaled.</p>

+<p>The origin of the source&#39;s rectangle is used to locate the tile within a larger surface. </p>

+<p>Second, a <span class="inline_code"><a href="#bvbuffdesc">bvbuffdesc</a></span> object is no longer supplied by the client 

+in the bvbltparams structure.&nbsp; In its place is a <span class="inline_code"><a href="#bvtileparams">bvtileparams</a></span> 

+object.</p>

+<p>Refer to the <span class="inline_code"><a href="#bvtileparams">bvtileparams</a></span> structure definition for details.</p>

+<p class="Code_Header_3">bvbltparams.flags - <a name="BVFLAG_HORZ_FLIP">BVFLAG_HORZ</a>/<a name="BVFLAG_VERT_FLIP">VERT_FLIP_*</a></p>

+<p>These flags indicate that the corresponding image is flipped horizontally or vertically as it is used by the operation.</p>

+<p class="Code_Header_3">bvbltparams.flags - BVFLAG_SCALE/DITHER_RETURN</p>

+<p>The scale and dither types can be specified with an implicit type.&nbsp; The implementation will then convert that internally 

+to an explicit scale or dither type.&nbsp; These flags request that the implementation return the explicit type chosen to 

+the client in the corresponding <span class="inline_code"><a href="#scalemode">bvbltparams.scalemode</a></span> and

+<span class="inline_code"><a href="#dithermode">bvbltparams.dithermode</a></span> members.</p>

+<p class="Code_Header_3">bvbltparams.flags - BVFLAG_ASYNC</p>

+<p>This flag allows the client to inform the implementation that it can queue the requested BLT and return from

+<span class="inline_code"><a href="#bv_blt">bv_blt()</a></span> before it has completed.&nbsp; If this bit is not set, when 

+the <span class="inline_code"><a href="#bv_blt">bv_blt()</a></span> returns, the operation is complete.</p>

+<p>Normally, a client will also utilize the <span class="inline_code"><a href="#callbackfn">bvbltparams.callbackfn</a></span> 

+and <span class="inline_code"><a href="#callbackdata">bvbltparams.callbackdata</a></span> members to receive a notification 

+when the BLT has completed.</p>

+<p class="note">NOTE:&nbsp; Asynchronous BLTs are performed in the order in which they are submitted within an implementation.&nbsp; 

+This was done to provide a simple dependency mechanism.&nbsp; 

+However, synchronization between implementations must be handled by the client, using the callback mechanism.</p>

+<p class="note">NOTE:&nbsp; Since asynchronous BLTs are performed in the order in which they are submitted, it follows 

+that a synchronized BLT after a set of asynchronous BLTs may be used as synchronization as well.</p>

+<p class="note"><a name="NOP">NOTE</a>:&nbsp; Certain situations may require manual synchronization without an associated BLT.&nbsp; 

+Rather than introduce an additional BLTsville function call, the method of handling this will be via a NOP BLT.&nbsp; To 

+accomplish a NOP BLT, the client should issue a BLT using the <span class="inline_code"><a href="#rop">

+bvbltparams.op.rop</a></span> code of <span class="inline_code">0xAAAA</span> (copy destination to destination), and 

+with the <span class="inline_code">BVFLAG_ASYNC</span> flag <span class="underline">not</span> set.&nbsp; Alternatively, the NOP BLT may set the

+<span class="inline_code">BVFLAG_ASYNC</span> and provide a <span class="inline_code"><a href="#callbackfn">

+bvbltparams.callbackfn</a></span>.&nbsp; <em>To facilitate implementations, a valid destination surface should be 

+specified.</em></p>

+<p class="imponly"><strong>Implementations Only<br />

+<br />

+</strong>In general, this BLTsville specification has avoided placing any requirement on implementations for specific 

+operations.&nbsp; However, in support of this special case, support for these NOP BLTs will need to be an implementation

+<span class="underline"><strong>requirement</strong></span>. </p>

+<p class="Code_Header_3">bvbltparams.flags - BVFLAG_BATCH_BEGIN/CONTINUE/END</p>

+<p>These flags are used to control batching of BLTs for two main reasons:</p>

+<ol>

+	<li>To group small, similar BLTs to consolidate overhead.&nbsp; For example, the BLTs associated with rendering each 

+	character in a word.</li>

+	<li>To group related BLTs, which may allow an implementation to perform a more efficient, but equivalent set of operations.</li>

+</ol>

+<p>See <a href="#batching">Batching</a> for details.</p>

+<p class="Code_Header_3">bvbltparams.flags - <a name="BVFLAG_SRC2_AUXDSTRECT">BVFLAG_SRC2</a>/<a name="BVFLAG_MASK_AUXDSTRECT">MASK_AUXDSTRECT</a></p>

+<p>These flags are used to indicate that the bvbltparams.src2auxdstrect and bvbltparams.maskauxdstrect are to be used.&nbsp; 

+See these entries below for details. These flags are likely to be ignored except for the special case explained below, 

+so they should be used only when necessary.</p>

+<p class="Code_Header_2"><a name="rop">bvbltparams.op.rop</a></p>

+<p class="code_block">unsigned short op; /* input */ </p>

+<p>When <span class="inline_code"><a href="#BVFLAG_ROP">BVFLAG_ROP</a></span> is set in the <span class="inline_code">

+<a href="#flags">bvbltparams.flags</a></span> member, the <span class="inline_code"><a href="#op">bvbltparams.op</a></span> 

+union is treated as <span class="inline_code">rop</span>.&nbsp; Raster OPerations are binary operations performed on the 

+bits of the inputs:</p>

+<ul>

+	<li>ROP1s have one source:&nbsp; the destination.&nbsp; Two bits are sufficient to specify the four possible (2<sup>2</sup>) 

+	ROP1 operations.</li>

+	<li>ROP2s have two sources:&nbsp; the destination and a source.&nbsp; Four bits are used to specify the sixteen (2<sup>2+2</sup>) 

+	ROP2 operations.</li>

+	<li>ROP3s have three sources:&nbsp; the destination, a source (source 1), and a pattern (a.k.a. brush), which we call 

+	source 2 in BLTsville.&nbsp; Eight bits are used to specify the 256 (2<sup>2+2+2</sup>) ROP3 operations.</li>

+	<li>ROP4s have four sources:&nbsp; the destination, two sources, and a mask.&nbsp; Sixteen bits are used to specify 

+	the 65,536 (2<sup>2+2+2+2</sup>) ROP4 operations.</li>

+</ul>

+<p>BLTsville&#39;s <span class="inline_code">rop</span> element is used to specify a ROP4, but anything from ROP1 up to ROP4 

+can be defined using this member:</p>

+<ul>

+	<li>To specify an 8-bit ROP3 as a 16-bit ROP4, replicate the 8 bits twice:&nbsp; 0x2323.</li>

+	<li>To specify a 4-bit ROP2 as a 16-bit ROP4, replicate the 4 bits four times:&nbsp; 0x2222.</li>

+	<li>To specify a 2-bit ROP1 as a 16-bit ROP4, replicate the 2 bits eight times:&nbsp; 0x5555.</li>

+</ul>

+<p class="note">NOTE:&nbsp;

+By far the most common ROP used will be 0xCCCC, which indicates a simple copy from source 1 to the destination.</p>

+<p>The table below is the magic decoder ring: </p>

+<table class="indent">

+	<tr>

+		<td>Mask</td>

+		<td class="ctr">&nbsp;1&nbsp;</td>

+		<td class="ctr">&nbsp;1&nbsp;</td>

+		<td class="ctr">&nbsp;1&nbsp;</td>

+		<td class="ctr">&nbsp;1&nbsp;</td>

+		<td class="ctr">&nbsp;1&nbsp;</td>

+		<td class="ctr">&nbsp;1&nbsp;</td>

+		<td class="ctr">&nbsp;1&nbsp;</td>

+		<td class="ctr">&nbsp;1&nbsp;</td>

+		<td class="ctr">&nbsp;0&nbsp;</td>

+		<td class="ctr">&nbsp;0&nbsp;</td>

+		<td class="ctr">&nbsp;0&nbsp;</td>

+		<td class="ctr">&nbsp;0&nbsp;</td>

+		<td class="ctr">&nbsp;0&nbsp;</td>

+		<td class="ctr">&nbsp;0&nbsp;</td>

+		<td class="ctr">&nbsp;0&nbsp;</td>

+		<td class="ctr">&nbsp;0&nbsp;</td>

+	</tr>

+	<tr>

+		<td class="red_left">Source 2 </td>

+		<td class="red_center">&nbsp;1&nbsp;</td>

+		<td class="red_center">&nbsp;1&nbsp;</td>

+		<td class="red_center">&nbsp;1&nbsp;</td>

+		<td class="red_center">&nbsp;1&nbsp;</td>

+		<td class="red_center">&nbsp;0&nbsp;</td>

+		<td class="red_center">&nbsp;0&nbsp;</td>

+		<td class="red_center">&nbsp;0&nbsp;</td>

+		<td class="red_center">&nbsp;0&nbsp;</td>

+		<td class="red_center">&nbsp;1&nbsp;</td>

+		<td class="red_center">&nbsp;1&nbsp;</td>

+		<td class="red_center">&nbsp;1&nbsp;</td>

+		<td class="red_center">&nbsp;1&nbsp;</td>

+		<td class="red_center">&nbsp;0&nbsp;</td>

+		<td class="red_center">&nbsp;0&nbsp;</td>

+		<td class="red_center">&nbsp;0&nbsp;</td>

+		<td class="red_center">&nbsp;0&nbsp;</td>

+	</tr>

+	<tr>

+		<td class="grn_left">Source 1 </td>

+		<td class="grn_center">&nbsp;1&nbsp;</td>

+		<td class="grn_center">&nbsp;1&nbsp;</td>

+		<td class="grn_center">&nbsp;0&nbsp;</td>

+		<td class="grn_center">&nbsp;0&nbsp;</td>

+		<td class="grn_center">&nbsp;1&nbsp;</td>

+		<td class="grn_center">&nbsp;1&nbsp;</td>

+		<td class="grn_center">&nbsp;0&nbsp;</td>

+		<td class="grn_center">&nbsp;0&nbsp;</td>

+		<td class="grn_center">&nbsp;1&nbsp;</td>

+		<td class="grn_center">&nbsp;1&nbsp;</td>

+		<td class="grn_center">&nbsp;0&nbsp;</td>

+		<td class="grn_center">&nbsp;0&nbsp;</td>

+		<td class="grn_center">&nbsp;1&nbsp;</td>

+		<td class="grn_center">&nbsp;1&nbsp;</td>

+		<td class="grn_center">&nbsp;0&nbsp;</td>

+		<td class="grn_center">&nbsp;0&nbsp;</td>

+	</tr>

+	<tr>

+		<td class="blue_left_botbord">Destination </td>

+		<td class="blue_center_botbord">&nbsp;1&nbsp;</td>

+		<td class="blue_center_botbord">&nbsp;0&nbsp;</td>

+		<td class="blue_center_botbord">&nbsp;1&nbsp;</td>

+		<td class="blue_center_botbord">&nbsp;0&nbsp;</td>

+		<td class="blue_center_botbord">&nbsp;1&nbsp;</td>

+		<td class="blue_center_botbord">&nbsp;0&nbsp;</td>

+		<td class="blue_center_botbord">&nbsp;1&nbsp;</td>

+		<td class="blue_center_botbord">&nbsp;0&nbsp;</td>

+		<td class="blue_center_botbord">&nbsp;1&nbsp;</td>

+		<td class="blue_center_botbord">&nbsp;0&nbsp;</td>

+		<td class="blue_center_botbord">&nbsp;1&nbsp;</td>

+		<td class="blue_center_botbord">&nbsp;0&nbsp;</td>

+		<td class="blue_center_botbord">&nbsp;1&nbsp;</td>

+		<td class="blue_center_botbord">&nbsp;0&nbsp;</td>

+		<td class="blue_center_botbord">&nbsp;1&nbsp;</td>

+		<td class="blue_center_botbord">&nbsp;0&nbsp;</td>

+	</tr>

+	<tr>

+		<td class="left_topbord">Raster Operation </td>

+		<td class="center_topbord">&nbsp;15&nbsp;</td>

+		<td class="center_topbord">&nbsp;14&nbsp;</td>

+		<td class="center_topbord">&nbsp;13&nbsp;</td>

+		<td class="center_topbord">&nbsp;12&nbsp;</td>

+		<td class="center_topbord">&nbsp;11&nbsp;</td>

+		<td class="center_topbord">&nbsp;10&nbsp;</td>

+		<td class="center_topbord">&nbsp;&nbsp;9&nbsp;</td>

+		<td class="center_topbord">&nbsp;&nbsp;8&nbsp;</td>

+		<td class="center_topbord">&nbsp;&nbsp;7&nbsp;</td>

+		<td class="center_topbord">&nbsp;&nbsp;6&nbsp;</td>

+		<td class="center_topbord">&nbsp;&nbsp;5&nbsp;</td>

+		<td class="center_topbord">&nbsp;&nbsp;4&nbsp;</td>

+		<td class="center_topbord">&nbsp;&nbsp;3&nbsp;</td>

+		<td class="center_topbord">&nbsp;&nbsp;2&nbsp;</td>

+		<td class="center_topbord">&nbsp;&nbsp;1&nbsp;</td>

+		<td class="center_topbord">&nbsp;&nbsp;0&nbsp;</td>

+	</tr>

+</table>

+<br />

+For example, to specify an operation that uses the mask to choose between source 1 and destination (source 1 when mask is 

+1, destination when mask is 0), a client would calculate the bottom line by parsing each column:<br />

+<br />

+When mask is 1 (the first eight columns), the <span class="inline_code">rop</span> matches the source 1 row.&nbsp; When 

+mask is 0 (the last eight columns), the <span class="inline_code">rop</span> matches the destination row.<br />

+<br />

+<table class="indent">

+	<tr>

+		<td class="left_topbord">Raster Operation </td>

+		<td class="red_center_topbord">&nbsp;1&nbsp;</td>

+		<td class="red_center_topbord">&nbsp;1&nbsp;</td>

+		<td class="red_center_topbord">&nbsp;1&nbsp;</td>

+		<td class="red_center_topbord">&nbsp;1&nbsp;</td>

+		<td class="red_center_topbord">&nbsp;0&nbsp;</td>

+		<td class="red_center_topbord">&nbsp;0&nbsp;</td>

+		<td class="red_center_topbord">&nbsp;0&nbsp;</td>

+		<td class="red_center_topbord">&nbsp;0&nbsp;</td>

+		<td class="blu_center_topbord">&nbsp;1&nbsp;</td>

+		<td class="blu_center_topbord">&nbsp;0&nbsp;</td>

+		<td class="blu_center_topbord">&nbsp;1&nbsp;</td>

+		<td class="blu_center_topbord">&nbsp;0&nbsp;</td>

+		<td class="blu_center_topbord">&nbsp;1&nbsp;</td>

+		<td class="blu_center_topbord">&nbsp;0&nbsp;</td>

+		<td class="blu_center_topbord">&nbsp;1&nbsp;</td>

+		<td class="blu_center_topbord">&nbsp;0&nbsp;</td>

+	</tr>

+</table>

+<br />

+So the <span class="inline_code">rop</span> for this operation would be 0xF0AA.<br />

+<br />

+Here is a list of some commonly used raster operations that have been given names:<br />

+<br />

+<table class="indent_thick_bord">

+	<tr>

+		<td class="thin_bord_dbl_botbord"><strong>ROP </strong></td>

+		<td class="thin_bord_dbl_botbord"><strong>Constant</strong></td>

+		<td class="thin_bord_dbl_botbord"><strong>Description</strong></td>

+	</tr>

+	<tr>

+		<td class="thin_bord">BLACKNESS</td>

+		<td class="thin_bord">0x0000</td>

+		<td class="thin_bord">Set all destination bits to black (0).&nbsp; Dest = 0</td>

+	</tr>

+	<tr>

+		<td class="thin_bord">NOTSRCERASE</td>

+		<td class="thin_bord">0x1111</td>

+		<td class="thin_bord">Dest = ~Src1 &amp; ~Dest = ~(Src1 | Dest)</td>

+	</tr>

+	<tr>

+		<td class="thin_bord">NOTSRCCOPY</td>

+		<td class="thin_bord">0x3333</td>

+		<td class="thin_bord">Dest = ~Src1</td>

+	</tr>

+	<tr>

+		<td class="thin_bord">SRCERASE</td>

+		<td class="thin_bord">0x4444</td>

+		<td class="thin_bord">Dest = Src1 &amp; ~Dest</td>

+	</tr>

+	<tr>

+		<td class="thin_bord">DSTINVERT</td>

+		<td class="thin_bord">0x5555</td>

+		<td class="thin_bord">Invert (NOT) the destination bits.&nbsp; Dest = ~Dest</td>

+	</tr>

+	<tr>

+		<td class="thin_bord">PATINVERT</td>

+		<td class="thin_bord">0x5A5A</td>

+		<td class="thin_bord">XOR with Src2.&nbsp; Dest = Src2 ^ Dest</td>

+	</tr>

+	<tr>

+		<td class="thin_bord">SRCINVERT</td>

+		<td class="thin_bord">0x6666</td>

+		<td class="thin_bord">XOR with Src1.&nbsp; Dest = Src1 ^ Dest</td>

+	</tr>

+	<tr>

+		<td class="thin_bord">SRCAND</td>

+		<td class="thin_bord">0x8888</td>

+		<td class="thin_bord">Dest = Src1 &amp; Dest</td>

+	</tr>

+	<tr>

+		<td class="thin_bord">NOP</td>

+		<td class="thin_bord">0xAAAA</td>

+		<td class="thin_bord">Dest = Dest</td>

+	</tr>

+	<tr>

+		<td class="thin_bord">MERGEPAINT</td>

+		<td class="thin_bord">0xBBBB</td>

+		<td class="thin_bord">Dest = ~Src1 | Dest</td>

+	</tr>

+	<tr>

+		<td class="thin_bord">MERGECOPY</td>

+		<td class="thin_bord">0xC0C0</td>

+		<td class="thin_bord">Dest = Src1 &amp; Src2</td>

+	</tr>

+	<tr>

+		<td class="thin_bord">SRCCOPY</td>

+		<td class="thin_bord">0xCCCC</td>

+		<td class="thin_bord">Dest = Src1</td>

+	</tr>

+	<tr>

+		<td class="thin_bord">SRCPAINT</td>

+		<td class="thin_bord">0xEEEE</td>

+		<td class="thin_bord">OR with Src1.&nbsp; Dest = Src1 | Dest</td>

+	</tr>

+	<tr>

+		<td class="thin_bord">PATCOPY</td>

+		<td class="thin_bord">0xF0F0</td>

+		<td class="thin_bord">Copy source 2 to destination.&nbsp; Dest = Src2</td>

+	</tr>

+	<tr>

+		<td class="thin_bord">PATPAINT</td>

+		<td class="thin_bord">0xFBFB</td>

+		<td class="thin_bord">Dest =&nbsp; ~Src1 | Src2 | Dest</td>

+	</tr>

+	<tr>

+		<td class="thin_bord">WHITENESS</td>

+		<td class="thin_bord">0xFFFF</td>

+		<td class="thin_bord">Set all destination bits to white (1).&nbsp; Dest = 1</td>

+	</tr>

+</table>

+<br />

+<span class="Code_Header_2"><a name="blend">bvbltparams.op.blend</a></span>

+<p class="code_block">enum bvblend blend; /* input */</p>

+<p>When <span class="inline_code"><a href="#BVFLAG_BLEND">BVFLAG_BLEND</a></span> is set in the

+<span class="inline_code"><a href="#flags">bvbltparams.flags</a></span> member, the <span class="inline_code">

+<a href="#op">bvbltparams.op</a></span> union is treated as a <span class="inline_code">blend</span>.</p>

+<p>To specify the blend, the client fills in <span class="inline_code">blend</span> with one of the

+<span class="inline_code"><a href="#bvblend">bvblend</a></span> values.</p>

+<p><span class="inline_code"><a href="#bvblend">bvblend</a></span> is an enumeration assembled from sets of fields.&nbsp; 

+The values specified may be extended beyond those that are explicitly defined using the definitions in the

+<span class="filename">bvblend.h</span> header file.</p>

+<p>The first 4 bits are the format.&nbsp; Currently two format groups are defined, but others can be added.&nbsp; The remainder 

+of the bits are used as defined by the individual format:</p>

+<table class="indent">

+	<tr>

+		<td valign="top">1.</td>

+		<td><span class="Code_Header_3">BVBLENDDEF_FORMAT_CLASSIC</span><br />

+		<br />

+		The <span class="inline_code">BVBLENDDEF_FORMAT_CLASSIC</span> is meant to handle the classic Porter-Duff equations. 

+		It can also handle the DirectFB blending.<br />

+		<br />

+		<span class="inline_code">BVBLENDDEF_FORMAT_CLASSIC</span> is based on the following equations:<br />

+		<div>

+			<p class="indent">C<sub>d</sub> = K<sub>1</sub>C<sub>1</sub> + K<sub>2</sub>C<sub>2</sub><br />

+			A<sub>d</sub> = K<sub>3</sub>A<sub>1</sub> + K<sub>4</sub>A<sub>2</sub></p>

+		</div>

+		where:<br />

+		<div>

+			<p class="indent">C<sub>d</sub>: destination color<br />

+			C<sub>1</sub>: source 1 color<br />

+			C<sub>2</sub>: source 2 color<br />

+			A<sub>d</sub>: destination alpha<br />

+			A<sub>1</sub>: source 1 alpha<br />

+			A<sub>2</sub>: source 2 alpha<br />

+			K<sub>#</sub>: one of the constants defined using the bitfields below</p>

+		</div>

+		The 28 bits for <span class="inline_code">BVBLENDDEF_FORMAT_CLASSIC</span> are divided into 5 sections.<br />

+		<br />

+		The most significant 4 bits are modifiers, used to include additional alpha values from global or remote sources.<br />

+		<br />

+		[27] The most significant bit indicates that a remote alpha is to be included in the blend. The format of this is 

+		defined by <span class="inline_code"><a href="#maskgeom">bvbltparams.maskgeom.format</a></span>.<br />

+		<br />

+		[26] The next bit is reserved.<br />

+		<br />

+		[25:24] The next 2 bits are used to indicate that a global alpha is to be included, and what its format is:<br />

+		<div>

+			<p class="indent">00: no global included<br />

+			01: global included; bvbltparams.globalalpha.size8 is used (0 -&gt; 255)<br />

+			10: this value is reserved<br />

+			11: global included; bvbltparams.flogalalpha.fp is used (0.0 -&gt; 1.0) </p>

+		</div>

+		The remaining bits are divided into 4 sections, one to define each of the constants:<br />

+		<br />

+		[23:18] - K1<br />

+		[17:12] - K2<br />

+		[11:6] - K3<br />

+		[5:0] - K4<br />

+		<br />

+		The format is the same for all 4 constant fields:<br />

+		<br />

+		[5:4] The first 2 bits of each field indicates the way in which the other 2 fields are interpreted:<br />

+		<div>

+			<p class="indent">00: only As: the other two fields contain only As; there should be only one valid A value 

+			between the two fields<br />

+			01: minimum: the value of the constant is the minimum of the two fields<br />

+			10: maximum: the value of the constant is the maximum of the two fields<br />

+			11: only Cs: the other two fields contain only Cs; there should be only one valid C value between the two fields</p>

+		</div>

+		[3:2] The middle 2 bits of each field contain the inverse field:<br />

+		<div>

+			<p class="indent">00: 1-C1 (&quot;don&#39;t care&quot; for &quot;only As&quot;)<br />

+			01: 1-A1 (&quot;don&#39;t care&quot; for &quot;only Cs&quot;)<br />

+			10: 1-C2 (&quot;don&#39;t care&quot; for &quot;only As&quot;)<br />

+			11: 1-A2 (&quot;don&#39;t care&quot; for &quot;only Cs&quot;)</p>

+		</div>

+		[1:0] The last 2 bits if each field contain the normal field:<br />

+		<div>

+			<p class="indent">00: C1 (&quot;don&#39;t care&quot; for &quot;only As&quot;)<br />

+			01: A1 (&quot;don&#39;t care&quot; for &quot;only Cs&quot;)<br />

+			10: C2 (&quot;don&#39;t care&quot; for &quot;only As&quot;)<br />

+			11: A2 (&quot;don&#39;t care&quot; for &quot;only Cs&quot;)</p>

+		</div>

+		EXCEPTIONS:<br />

+		<br />

+		00 00 00 - The value 00 00 00, which normally would indicate &quot;only As&quot; with two &quot;don&#39;t care&quot; fields, is interpreted 

+		as a constant of 0.<br />

+		<br />

+		11 11 11 - The value 11 11 11, which normally would indicate &quot;only Cs&quot; with two &quot;don&#39;t care&quot; fields, is interpreted 

+		as a constant of 1.<br />

+		<br />

+		<span class="Header4">Constants</span><br />

+		<br />

+		Put together, these can define portions of the blend equations that can be put together in a variety of ways:<br />

+		<br />

+		<table class="indent_thick_bord">

+			<tr>

+				<td class="rt_thick_bord">

+				<table>

+					<tr>

+						<td class="thin_bord">00 00 00</td>

+						<td class="thin_bord">undefined -&gt; zero</td>

+					</tr>

+					<tr>

+						<td class="thin_bord">00 00 01</td>

+						<td class="thin_bord">A1 (preferred)</td>

+					</tr>

+					<tr>

+						<td class="thin_bord">00 00 10</td>

+						<td class="thin_bord">undefined</td>

+					</tr>

+					<tr>

+						<td class="thin_bord">00 00 11</td>

+						<td class="thin_bord">A2 (preferred)</td>

+					</tr>

+					<tr>

+						<td class="thin_bord">00 01 00</td>

+						<td class="thin_bord">1-A1 (preferred)</td>

+					</tr>

+					<tr>

+						<td class="thin_bord">00 01 01</td>

+						<td class="thin_bord">undefined</td>

+					</tr>

+					<tr>

+						<td class="thin_bord">00 01 10</td>

+						<td class="thin_bord">1-A1 (use 00 01 00)</td>

+					</tr>

+					<tr>

+						<td class="thin_bord">00 01 11</td>

+						<td class="thin_bord">undefined</td>

+					</tr>

+					<tr>

+						<td class="thin_bord">00 10 00</td>

+						<td class="thin_bord">undefined</td>

+					</tr>

+					<tr>

+						<td class="thin_bord">00 10 01</td>

+						<td class="thin_bord">A1 (use 00 00 01)</td>

+					</tr>

+					<tr>

+						<td class="thin_bord">00 10 10</td>

+						<td class="thin_bord">undefined</td>

+					</tr>

+					<tr>

+						<td class="thin_bord">00 10 11</td>

+						<td class="thin_bord">A2 (use 00 00 11)</td>

+					</tr>

+					<tr>

+						<td class="thin_bord">00 11 00</td>

+						<td class="thin_bord">1-A2 (preferred)</td>

+					</tr>

+					<tr>

+						<td class="thin_bord">00 11 01</td>

+						<td class="thin_bord">undefined</td>

+					</tr>

+					<tr>

+						<td class="thin_bord">00 11 10</td>

+						<td class="thin_bord">1-A2 (use 00 11 00)</td>

+					</tr>

+					<tr>

+						<td class="thin_bord">00 11 11</td>

+						<td class="thin_bord">undefined</td>

+					</tr>

+				</table>

+				</td>

+				<td class="rt_thick_bord">

+				<table>

+					<tr>

+						<td class="thin_bord">01 00 00</td>

+						<td class="thin_bord">min(C1,1-C1)</td>

+					</tr>

+					<tr>

+						<td class="thin_bord">01 00 01</td>

+						<td class="thin_bord">min(A1,1-C1)</td>

+					</tr>

+					<tr>

+						<td class="thin_bord">01 00 10</td>

+						<td class="thin_bord">min(C2,1-C1)</td>

+					</tr>

+					<tr>

+						<td class="thin_bord">01 00 11</td>

+						<td class="thin_bord">min(A2,1-C1)</td>

+					</tr>

+					<tr>

+						<td class="thin_bord">01 01 00</td>

+						<td class="thin_bord">min(C1,1-A1)</td>

+					</tr>

+					<tr>

+						<td class="thin_bord">01 01 01</td>

+						<td class="thin_bord">min(A1,1-A1)</td>

+					</tr>

+					<tr>

+						<td class="thin_bord">01 01 10</td>

+						<td class="thin_bord">min(C2,1-A1)</td>

+					</tr>

+					<tr>

+						<td class="thin_bord">01 01 11</td>

+						<td class="thin_bord">min(A2,1-A1)</td>

+					</tr>

+					<tr>

+						<td class="thin_bord">01 10 00</td>

+						<td class="thin_bord">min(C1,1-C2)</td>

+					</tr>

+					<tr>

+						<td class="thin_bord">01 10 01</td>

+						<td class="thin_bord">min(A1,1-C2)</td>

+					</tr>

+					<tr>

+						<td class="thin_bord">01 10 10</td>

+						<td class="thin_bord">min(C2,1-C2)</td>

+					</tr>

+					<tr>

+						<td class="thin_bord">01 10 11</td>

+						<td class="thin_bord">min(A2,1-C2)</td>

+					</tr>

+					<tr>

+						<td class="thin_bord">01 11 00</td>

+						<td class="thin_bord">min(C1,1-A2)</td>

+					</tr>

+					<tr>

+						<td class="thin_bord">01 11 01</td>

+						<td class="thin_bord">min(A1,1-A2)</td>

+					</tr>

+					<tr>

+						<td class="thin_bord">01 11 10</td>

+						<td class="thin_bord">min(C2,1-A2)</td>

+					</tr>

+					<tr>

+						<td class="thin_bord">01 11 11</td>

+						<td class="thin_bord">min(A2,1-A2)</td>

+					</tr>

+				</table>

+				</td>

+				<td class="rt_thick_bord">

+				<table>

+					<tr>

+						<td class="thin_bord">10 00 00</td>

+						<td class="thin_bord">max(C1,1-C1)</td>

+					</tr>

+					<tr>

+						<td class="thin_bord">10 00 01</td>

+						<td class="thin_bord">max(A1,1-C1)</td>

+					</tr>

+					<tr>

+						<td class="thin_bord">10 00 10</td>

+						<td class="thin_bord">max(C2,1-C1)</td>

+					</tr>

+					<tr>

+						<td class="thin_bord">10 00 11</td>

+						<td class="thin_bord">max(A2,1-C1)</td>

+					</tr>

+					<tr>

+						<td class="thin_bord">10 01 00</td>

+						<td class="thin_bord">max(C1,1-A1)</td>

+					</tr>

+					<tr>

+						<td class="thin_bord">10 01 01</td>

+						<td class="thin_bord">max(A1,1-A1)</td>

+					</tr>

+					<tr>

+						<td class="thin_bord">10 01 10</td>

+						<td class="thin_bord">max(C2,1-A1)</td>

+					</tr>

+					<tr>

+						<td class="thin_bord">10 01 11</td>

+						<td class="thin_bord">max(A2,1-A1)</td>

+					</tr>

+					<tr>

+						<td class="thin_bord">10 10 00</td>

+						<td class="thin_bord">max(C1,1-C2)</td>

+					</tr>

+					<tr>

+						<td class="thin_bord">10 10 01</td>

+						<td class="thin_bord">max(A1,1-C2)</td>

+					</tr>

+					<tr>

+						<td class="thin_bord">10 10 10</td>

+						<td class="thin_bord">max(C2,1-C2)</td>

+					</tr>

+					<tr>

+						<td class="thin_bord">10 10 11</td>

+						<td class="thin_bord">max(A2,1-C2)</td>

+					</tr>

+					<tr>

+						<td class="thin_bord">10 11 00</td>

+						<td class="thin_bord">max(C1,1-A2)</td>

+					</tr>

+					<tr>

+						<td class="thin_bord">10 11 01</td>

+						<td class="thin_bord">max(A1,1-A2)</td>

+					</tr>

+					<tr>

+						<td class="thin_bord">10 11 10</td>

+						<td class="thin_bord">max(C2,1-A2)</td>

+					</tr>

+					<tr>

+						<td class="thin_bord">10 11 11</td>

+						<td class="thin_bord">max(A2,1-A2)</td>

+					</tr>

+				</table>

+				</td>

+				<td>

+				<table>

+					<tr>

+						<td class="thin_bord">11 00 00</td>

+						<td class="thin_bord">undefined</td>

+					</tr>

+					<tr>

+						<td class="thin_bord">11 00 01</td>

+						<td class="thin_bord">1-C1 (use 11 00 11)</td>

+					</tr>

+					<tr>

+						<td class="thin_bord">11 00 10</td>

+						<td class="thin_bord">undefined</td>

+					</tr>

+					<tr>

+						<td class="thin_bord">11 00 11</td>

+						<td class="thin_bord">1-C1 (preferred)</td>

+					</tr>

+					<tr>

+						<td class="thin_bord">11 01 00</td>

+						<td class="thin_bord">C1 (use 11 11 00)</td>

+					</tr>

+					<tr>

+						<td class="thin_bord">11 01 01</td>

+						<td class="thin_bord">undefined</td>

+					</tr>

+					<tr>

+						<td class="thin_bord">11 01 10</td>

+						<td class="thin_bord">C2 (use 11 11 10)</td>

+					</tr>

+					<tr>

+						<td class="thin_bord">11 01 11</td>

+						<td class="thin_bord">undefined</td>

+					</tr>

+					<tr>

+						<td class="thin_bord">11 10 00</td>

+						<td class="thin_bord">undefined</td>

+					</tr>

+					<tr>

+						<td class="thin_bord">11 10 01</td>

+						<td class="thin_bord">1-C2 (use 11 10 11)</td>

+					</tr>

+					<tr>

+						<td class="thin_bord">11 10 10</td>

+						<td class="thin_bord">undefined</td>

+					</tr>

+					<tr>

+						<td class="thin_bord">11 10 11</td>

+						<td class="thin_bord">1-C2 (preferred)</td>

+					</tr>

+					<tr>

+						<td class="thin_bord">11 11 00</td>

+						<td class="thin_bord">C1 (preferred)</td>

+					</tr>

+					<tr>

+						<td class="thin_bord">11 11 01</td>

+						<td class="thin_bord">undefined</td>

+					</tr>

+					<tr>

+						<td class="thin_bord">11 11 10</td>

+						<td class="thin_bord">C2 (preferred)</td>

+					</tr>

+					<tr>

+						<td class="thin_bord">11 11 11</td>

+						<td class="thin_bord">undefined -&gt; one</td>

+					</tr>

+				</table>

+				</td>

+			</tr>

+		</table>

+		<span class="Header4"><br />

+		DirectFB Example</span><br />

+		<br />

+		Putting these together into the proper constants, the blending equations can be built for different APIs.&nbsp; 

+		Here is how DirectFB would be mapped:<br />

+		<br />

+		For DirectFB, the

+		<a href="http://directfb.org/docs/DirectFB_Reference_1_2/IDirectFBSurface_SetSrcBlendFunction.html" class="inline_code">

+		SetSrcBlendFunction()</a> and

+		<a href="http://directfb.org/docs/DirectFB_Reference_1_2/IDirectFBSurface_SetDstBlendFunction.html" class="inline_code">

+		SetDstBlendFunction()</a> can specify 121 combinations of blends (11 x 11). It&#39;s impractical to specify these combinations 

+		individually. Instead, the settings indicated by each call should be bitwise OR&#39;d to make the proper single value 

+		used in BLTsville.<br />

+		<br />

+		<table class="code_block">

+			<tr>

+				<td class="ctr">&nbsp;</td>

+				<td colspan="5" class="ctr"><strong>32-bit Binary Value</strong></td>

+			</tr>

+			<tr>

+				<td><strong>

+				<a href="http://directfb.org/docs/DirectFB_Reference_1_2/IDirectFBSurface_SetSrcBlendFunction.html">SetSrcBlendFunction()</a></strong></td>

+				<td class="ctr"><strong>[VendorID]</strong></td>

+				<td class="ctr"><strong>&nbsp;[--K1--] </strong></td>

+				<td class="ctr"><strong>&nbsp;[--K2--] </strong></td>

+				<td class="ctr"><strong>&nbsp;[--K3--] </strong></td>

+				<td class="ctr"><strong>&nbsp;[--K4--] </strong></td>

+			</tr>

+			<tr>

+				<td>DSBF_ZERO</td>

+				<td class="ctr">0000 0000</td>

+				<td class="ctr">00 00 00</td>

+				<td class="ctr">xx xx xx</td>

+				<td class="ctr">00 00 00</td>

+				<td class="ctr">xx xx xx</td>

+			</tr>

+			<tr>

+				<td>DSBF_ONE</td>

+				<td class="ctr">0000 0000</td>

+				<td class="ctr">11 11 11</td>

+				<td class="ctr">xx xx xx</td>

+				<td class="ctr">11 11 11</td>

+				<td class="ctr">xx xx xx</td>

+			</tr>

+			<tr>

+				<td>DSBF_SRCCOLOR</td>

+				<td class="ctr">0000 0000</td>

+				<td class="ctr">11 11 00</td>

+				<td class="ctr">xx xx xx</td>

+				<td class="ctr">00 00 01</td>

+				<td class="ctr">xx xx xx</td>

+			</tr>

+			<tr>

+				<td>DSBF_INVSRCCOLOR</td>

+				<td class="ctr">0000 0000</td>

+				<td class="ctr">11 00 11</td>

+				<td class="ctr">xx xx xx</td>

+				<td class="ctr">00 01 00</td>

+				<td class="ctr">xx xx xx</td>

+			</tr>

+			<tr>

+				<td>DSBF_SRCALPHA</td>

+				<td class="ctr">0000 0000</td>

+				<td class="ctr">00 00 01</td>

+				<td class="ctr">xx xx xx</td>

+				<td class="ctr">00 00 01</td>

+				<td class="ctr">xx xx xx</td>

+			</tr>

+			<tr>

+				<td>DSBF_INVSRCALPHA</td>

+				<td class="ctr">0000 0000</td>

+				<td class="ctr">00 01 00</td>

+				<td class="ctr">xx xx xx</td>

+				<td class="ctr">00 01 00</td>

+				<td class="ctr">xx xx xx</td>

+			</tr>

+			<tr>

+				<td>DSBF_DESTCOLOR</td>

+				<td class="ctr">0000 0000</td>

+				<td class="ctr">11 11 10</td>

+				<td class="ctr">xx xx xx</td>

+				<td class="ctr">00 00 11</td>

+				<td class="ctr">xx xx xx</td>

+			</tr>

+			<tr>

+				<td>DSBF_INVDESTCOLOR</td>

+				<td class="ctr">0000 0000</td>

+				<td class="ctr">11 10 11</td>

+				<td class="ctr">xx xx xx</td>

+				<td class="ctr">00 11 00</td>

+				<td class="ctr">xx xx xx</td>

+			</tr>

+			<tr>

+				<td>DSBF_DESTALPHA</td>

+				<td class="ctr">0000 0000</td>

+				<td class="ctr">00 00 11</td>

+				<td class="ctr">xx xx xx</td>

+				<td class="ctr">00 00 11</td>

+				<td class="ctr">xx xx xx</td>

+			</tr>

+			<tr>

+				<td>DSBF_INVDESTALPHA</td>

+				<td class="ctr">0000 0000</td>

+				<td class="ctr">00 11 00</td>

+				<td class="ctr">xx xx xx</td>

+				<td class="ctr">00 11 00</td>

+				<td class="ctr">xx xx xx</td>

+			</tr>

+			<tr>

+				<td>DSBF_SRCALPHASAT</td>

+				<td class="ctr">0000 0000</td>

+				<td class="ctr">01 11 01</td>

+				<td class="ctr">xx xx xx</td>

+				<td class="ctr">11 11 11</td>

+				<td class="ctr">xx xx xx</td>

+			</tr>

+		</table>

+		<br />

+		<table class="code_block">

+			<tr>

+				<td class="ctr">&nbsp;</td>

+				<td colspan="5" class="ctr"><strong>32-bit Binary Value</strong></td>

+			</tr>

+			<tr>

+				<td><strong>

+				<a href="http://directfb.org/docs/DirectFB_Reference_1_2/IDirectFBSurface_SetDstBlendFunction.html">SetDstBlendFunction()</a></strong></td>

+				<td class="ctr"><strong>[VendorID]</strong></td>

+				<td class="ctr"><strong>&nbsp;[--K1--] </strong></td>

+				<td class="ctr"><strong>&nbsp;[--K2--] </strong></td>

+				<td class="ctr"><strong>&nbsp;[--K3--] </strong></td>

+				<td class="ctr"><strong>&nbsp;[--K4--] </strong></td>

+			</tr>

+			<tr>

+				<td>DSBF_ZERO</td>

+				<td class="ctr">0000 0000</td>

+				<td class="ctr">xx xx xx</td>

+				<td class="ctr">00 00 00</td>

+				<td class="ctr">xx xx xx</td>

+				<td class="ctr">00 00 00</td>

+			</tr>

+			<tr>

+				<td>DSBF_ONE</td>

+				<td class="ctr">0000 0000</td>

+				<td class="ctr">xx xx xx</td>

+				<td class="ctr">11 11 11</td>

+				<td class="ctr">xx xx xx</td>

+				<td class="ctr">11 11 11</td>

+			</tr>

+			<tr>

+				<td>DSBF_SRCCOLOR</td>

+				<td class="ctr">0000 0000</td>

+				<td class="ctr">xx xx xx</td>

+				<td class="ctr">11 11 00</td>

+				<td class="ctr">xx xx xx</td>

+				<td class="ctr">00 00 01</td>

+			</tr>

+			<tr>

+				<td>etc.</td>

+				<td class="ctr">&nbsp;</td>

+				<td class="ctr">&nbsp;</td>

+				<td class="ctr">&nbsp;</td>

+				<td class="ctr">&nbsp;</td>

+				<td>&nbsp;</td>

+			</tr>

+		</table>

+		<br />

+		<span class="Header4">Porter-Duff</span><br />

+		<br />

+		For Porter-Duff blends, the equations can be more specifically defined. For convenience, these are enumerated in 

+		the <span class="inline_code">bvblend.h</span> header. These enumerations utilize only the local alpha in the equations 

+		as indicated. To use global or remote alpha, these enumerations need to be modified. For example, to include the 

+		global alpha in the Porter-Duff <span class="inline_code">BVBLEND_SRC1OVER</span> blend, the blend could be defined 

+		like this:<br />

+		<br />

+		<div>

+			<table class="indent">

+				<tr>

+					<td valign="top"><span class="inline_code">params.op.blend =</span></td>

+					<td><span class="inline_code">BVBLEND_SRC1OVER +<br />

+					BVBLENDDEF_GLOBAL_UCHAR;</span></td>

+				</tr>

+			</table>

+		</div>

+		<br />

+		To include the remote alpha, the blend could be defined like this:<br />

+		<br />

+		<div>

+			<table class="indent">

+				<tr>

+					<td valign="top"><span class="inline_code">params.op.blend =</span></td>

+					<td><span class="inline_code">BVBLEND_SRC1OVER +<br />

+					BVBLENDDEF_REMOTE;</span></td>

+				</tr>

+			</table>

+		</div>

+		<br />

+		And to include both:<br />

+		<br />

+		<div>

+			<table class="indent">

+				<tr>

+					<td valign="top"><span class="inline_code">params.op.blend =</span></td>

+					<td><span class="inline_code">BVBLEND_SRC1OVER +<br />

+					BVBLENDDEF_GLOBAL_UCHAR +<br />

+					BVBLENDDEF_REMOTE;</span></td>

+				</tr>

+			</table>

+		</div>

+		<br />

+		Note that if the source color formats include local alphas, the local alphas, global alpha, and remote alpha will 

+		be used together.<br />

+		<br />

+		Note also that the equations assume the surfaces are premultiplied. So if the surface formats indicate that they 

+		are not premultiplied, the alpha multiplication of each color is done prior to using the surface values in the equations.<br />

+		<br />

+		For example, <span class="inline_code">BVBLEND_SRC1OVER</span> specifies the equations:<br />

+		<table class="indent">

+			<tr>

+				<td>C<sub>d</sub> = C<sub>1</sub> + (1 - A<sub>1</sub>)C<sub>2</sub><br />

+				A<sub>d</sub> = A<sub>1</sub> + (1 - A<sub>1</sub>)A<sub>2</sub> </td>

+			</tr>

+		</table>

+		<br />

+		If the format of surface 1 is non-premultiplied, the equations are modified to include the multiplication explicitly:<br />

+		<br />

+		<table class="indent">

+			<tr>

+				<td>C<sub>d</sub> = A<sub>1</sub>C<sub>1</sub> + (1 - A<sub>1</sub>)C<sub>2</sub><br />

+				A<sub>d</sub> = A<sub>1</sub> + (1 - A<sub>1</sub>)A<sub>2</sub> </td>

+			</tr>

+		</table>

+		<br />

+		Likewise, if the format of surface 2 is non-premultiplied, the equations are modified for this:<br />

+		<br />

+		<table class="indent">

+			<tr>

+				<td>

+				<div>

+					C<sub>d</sub> = C<sub>1</sub> + (1 - A<sub>1</sub>)A<sub>2</sub>C<sub>2</sub><br />

+					A<sub>d</sub> = A<sub>1</sub> + (1 - A<sub>1</sub>)A<sub>2</sub> </div>

+				</td>

+			</tr>

+		</table>

+		<br />

+		When including global or remote alphas, these values are used to modify the source 1 value values before being used 

+		in the blend equation:<br />

+		<br />

+		<table class="indent">

+			<tr>

+				<td class="ctr">C<sub>1</sub> = A<sub>g</sub>C<sub>1</sub><br />

+				A<sub>1</sub> = A<sub>g</sub>A<sub>1</sub></td>

+				<td style="width: 20%" class="ctr">-or-</td>

+				<td class="ctr">C<sub>1</sub> = A<sub>r</sub>C<sub>1</sub><br />

+				A<sub>1</sub> = A<sub>r</sub>A<sub>1</sub></td>

+				<td class="ctr">-or-</td>

+				<td class="ctr">C<sub>1</sub> = A<sub>r</sub>A<sub>g</sub>C<sub>1</sub><br />

+				A<sub>1</sub> = A<sub>r</sub>A<sub>g</sub>A<sub>1</sub></td>

+			</tr>

+		</table>

+		<br />

+		</td>

+	</tr>

+	<tr>

+		<td valign="top">2.</td>

+		<td><span class="Code_Header_3"><strong><a name="BVBLENDDEF_FORMAT_ESSENTIAL0">BVBLENDDEF_FORMAT_ESSENTIAL</a></strong></span><br />

+		<br />

+		The essential blending equations are based on the blending equations in common image manipulation programs.<pre class="indent"><code>BVBLEND_LIGHTEN      max(src1, src2)

+BVBLEND_DARKEN       min(src1, src2)

+BVBLEND_MULTIPLY     (src1 * src2) / 255

+BVBLEND_AVERAGE      (src1 + src2) / 2

+BVBLEND_ADD          src1 + src2 (saturated)

+BVBLEND_SUBTRACT     src1 + src2 - 255 (saturated)

+BVBLEND_DIFFERENCE   abs(src - src2)

+BVBLEND_NEGATION     255 - abs(255 - src1 - src2)

+BVBLEND_SCREEN       255 - (((255 - src1) * (255 - src2)) / 256)

+BVBLEND_EXCLUSION    src1 + src2 - ((2 * src1 * src2) / 255)

+BVBLEND_OVERLAY      (src2 &lt; 128) ? (2 * src1 * src2 / 255) : (255 - 2 * (255 - src1) * (255 - src2) / 255)

+BVBLEND_SOFT_LIGHT   (src2 &lt; 128) ? (2 * ((src1 &gt;&gt; 1) + 64)) * ((float)src2 / 255) : (255 - (2 * (255 - ((src1 &gt;&gt; 1) + 64)) * (float)(255 - src2) / 255))

+BVBLEND_HARD_LIGHT   (src1 &lt; 128) ? (2 * src2 * src1 / 255) : (255 - 2 * (255 - src2) * (255 - src1) / 255)

+BVBLEND_COLOR_DODGE  (src2 == 255) ? src2 : min(255, ((src1 &lt;&lt; 8) / (255 - src2))

+BVBLEND_COLOR_BURN   (src2 == 0) ? src2 : max(0, (255 - ((255 - src1) &lt;&lt; 8 ) / src2))))

+BVBLEND_LINEAR_DODGE same as BVBLEND_ADD

+BVBLEND_LINEAR_BURN  same as BVBLEND_SUBTRACT

+BVBLEND_LINEAR_LIGHT (src2 &lt; 128) ? LINEAR_BURN(src1,(2 * src2)) : LINEAR_DODGE(src1,(2 * (src2 - 128)))

+BVBLEND_VIVID_LIGHT  (src2 &lt; 128) ? COLOR_BURN(src1,(2 * src2)) : COLOR_DODGE(src1,(2 * (src2 - 128))))

+BVBLEND_PIN_LIGHT    (src2 &lt; 128) ? DARKEN(src1,(2 * src2)) : LIGHTEN(src1,(2 * (src2 - 128)))

+BVBLEND_HARD_MIX     (VIVID_LIGHT(src1, src2) &lt; 128) ? 0 : 255

+BVBLEND_REFLECT      (src2 == 255) ? src2 : min(255, (src1 * src1 / (255 - src2)))

+BVBLEND_GLOW         (src1 == 255) ? src1 : min(255, (src2 * src2 / (255 - src1)))

+BVBLEND_PHOENIX      min(src1, src2) - max(src1, src2) + 255)

+BVBLEND_ALPHA        alf * src1 + (1 - alf) * src2)</code></pre>

+		</td>

+	</tr>

+</table>

+<a name="filter" class="Code_Header_2">bvbltparams.op.filter</a>

+<p class="code_block">struct bvfilter *filter; /* input */</p>

+<p>When <span class="inline_code"><a href="#BVFLAG_FILTER">BVFLAG_FILTER</a></span> is set in the

+<span class="inline_code"><a href="#flags">bvbltparams.flags</a></span> member, the <span class="inline_code">

+<a href="#op">bvbltparams.op</a></span> union is treated as a <span class="inline_code">filter</span>.</p>

+<p>To specify the filter, the client fills in <span class="inline_code">filter</span> with one of the

+<span class="inline_code">bvfilter</span> values.</p>

+<p>These values will be extended as general filter types are requested.</p>

+<a name="colorkey" class="Code_Header_2">bvbltparams.colorkey</a>

+<p class="code_block">void *colorkey; /* input */</p>

+<p>When either <span class="inline_code"><a href="#BVFLAG_KEY_SRC">BVFLAG_KEY_SRC</a></span> or

+<span class="inline_code"><a href="#BVFLAG_KEY_DST">BVFLAG_KEY_DST</a></span> is set in the <span class="inline_code">

+<a href="#flags">bvbltparams.flags</a></span> member, <span class="inline_code">colorkey</span> points to a single pixel 

+used as the color key.</p>

+<p>The format of this pixel matches the surface being keyed.&nbsp; i.e. <span class="inline_code"><a href="#bvsurfgeom">

+src1geom.format</a></span> is the format of the color key if <span class="inline_code">BVFLAG_KEY_SRC</span> is set, or

+<span class="inline_code"><a href="#bvsurfgeom">dst.format</a></span> is the format of the color key if

+<span class="inline_code">BVFLAG_KEY_DST</span> is set.</p>

+<p><em>Subsampled formats do not currently support color keying.</em></p>

+<p class="Code_Header_2"><a name="globalalpha">bvbltparams.globalalpha</a></p>

+<p class="code_block">union bvalpha globalalpha; /* input */</p>

+<p>When <span class="inline_code"><a href="#BVFLAG_BLEND">BVFLAG_BLEND</a></span> is set in the

+<span class="inline_code"><a href="#flags">bvbltparams.flags</a></span>, and when the <span class="inline_code">

+<a href="#blend">blend</a></span> chosen requires it, <span class="inline_code">globalalpha</span> is used to provide an 

+alpha blending value for the entire operation.&nbsp; The type is also dependent on the <span class="inline_code">

+<a href="#blend">blend</a></span> chosen.</p>

+<p>For the <span class="inline_code">BVBLENDDEF_FORMAT_CLASSIC</span> blend types, if the <span class="inline_code">BVBLENDDEF_GLOBAL_MASK</span> 

+field is not 0, this field is used.&nbsp; Currently <span class="inline_code">BVBLENDDEF_FORMAT_CLASSIC</span> provides 

+for an 8-bit (unsigned character / byte) format designated by <span class="inline_code">BVBLENDDEF_GLOBAL_UCHAR</span> as 

+well as a 32-bit floating point format designated by <span class="inline_code">BVBLENDDEF_GLOBAL_FLOAT</span>.</p>

+<p class="Code_Header_2"><a name="scalemode">bvbltparams.scalemode</a></p>

+<p class="code_block">enum bvscalemode scalemode; /* input/output */</p>

+<p>This member allows the client to specify the type of scaling to be used.&nbsp; The enumeration begins with 8 bits indicating 

+the vendor.&nbsp; The remaining bits are defined by the vendor.&nbsp; <span class="inline_code">BVSCALEDEF_VENDOR_ALL</span> 

+and <span class="inline_code">BVSCALEDEF_VENDOR_GENERAL</span> are shared by all implementations.</p>

+<p><span class="inline_code">BVSCALEDEF_VENDOR_ALL</span> can be used to specify an implicit scale type.&nbsp; This type 

+is converted to an explicit type by the implementation:</p>

+<table class="indent">

+	<tr>

+		<td class="inline_code">BVSCALE_FASTEST</td>

+		<td>The fastest method of scaling available is used.&nbsp; This may include nearest neighbor.&nbsp; The value of 

+		this enumeration is purposely 0, and is the default scale type.&nbsp; No implementation will return an error for 

+		this setting.</td>

+	</tr>

+	<tr>

+		<td class="inline_code">BVSCALE_FASTEST_NOT_NEAREST_NEIGHBOR</td>

+		<td>The fastest method of scaling available that is not nearest neighbor is used.&nbsp; This may include an alternative 

+		point sample technique.</td>

+	</tr>

+	<tr>

+		<td class="inline_code">BVSCALE_FASTEST_POINT_SAMPLE</td>

+		<td>The fastest method of scaling using a point sample technique.</td>

+	</tr>

+	<tr>

+		<td class="inline_code">BVSCALE_FASTEST_INTERPOLATED</td>

+		<td>The fastest method of scaling using an interpolation technique.</td>

+	</tr>

+	<tr>

+		<td class="inline_code">BVSCALE_FASTEST_PHOTO</td>

+		<td>The fastest method of scaling appropriate for photographs is used.&nbsp; This may include nearest neighbor.&nbsp; 

+		No implementation will return an error for this setting.</td>

+	</tr>

+	<tr>

+		<td class="inline_code">BVSCALE_FASTEST_DRAWING</td>

+		<td>The fastest method of scaling appropriate for drawings is used.&nbsp; This may include nearest neighbor.&nbsp; 

+		No implementation will return an error for this setting.</td>

+	</tr>

+	<tr>

+		<td class="inline_code">BVSCALE_GOOD</td>

+		<td>A scaling technique is chosen that may be higher quality than the <span class="inline_code">BVSCALE_FASTEST</span> 

+		choice.&nbsp; This may include nearest neighbor.&nbsp; No implementation will return an error for this setting.</td>

+	</tr>

+	<tr>

+		<td class="inline_code">BVSCALE_GOOD_POINT_SAMPLE</td>

+		<td>A point sample scaling technique is chosen that may be higher quality than the <span class="inline_code">BVSCALE_FASTEST_POINT_SAMPLE</span> 

+		choice.&nbsp; This may include nearest neighbor.</td>

+	</tr>

+	<tr>

+		<td class="inline_code">BVSCALE_GOOD_INTERPOLATED</td>

+		<td>An interpolated scaling technique is chosen that may be higher quality than the <span class="inline_code">BVSCALE_FASTEST_INTERPOLATED</span> 

+		choice.</td>

+	</tr>

+	<tr>

+		<td class="inline_code">BVSCALE_GOOD_PHOTO</td>

+		<td>A scaling technique appropriate for photographs is chosen that may be higher quality than the

+		<span class="inline_code">BVSCALE_FASTEST_PHOTO</span> choice.&nbsp; This may include nearest neighbor.&nbsp; No 

+		implementation will return an error for this setting.</td>

+	</tr>

+	<tr>

+		<td class="inline_code">BVSCALE_GOOD_DRAWING</td>

+		<td>A scaling technique appropriate for drawings is chosen that may be higher quality than the

+		<span class="inline_code">BVSCALE_FASTEST_DRAWING</span> choice.&nbsp; This may include nearest neighbor.&nbsp; 

+		No implementation will return an error for this setting.</td>

+	</tr>

+	<tr>

+		<td class="inline_code">BVSCALE_BETTER</td>

+		<td>A scaling technique is chosen that may be higher quality than the <span class="inline_code">BVSCALE_GOOD</span> 

+		choice.&nbsp; This may include nearest neighbor.&nbsp; No implementation will return an error for this setting.</td>

+	</tr>

+	<tr>

+		<td class="inline_code">BVSCALE_BETTER_POINT_SAMPLE</td>

+		<td>A point sample scaling technique is chosen that may be higher quality than the <span class="inline_code">BVSCALE_GOOD_POINT_SAMPLE</span> 

+		choice.&nbsp; This may include nearest neighbor.</td>

+	</tr>

+	<tr>

+		<td class="inline_code">BVSCALE_BETTER_INTERPOLATED</td>

+		<td>An interpolated scaling technique is chosen that may be higher quality than the <span class="inline_code">BVSCALE_GOOD_INTERPOLATED</span> 

+		choice.</td>

+	</tr>

+	<tr>

+		<td class="inline_code">BVSCALE_BETTER_PHOTO</td>

+		<td>A scaling technique appropriate for photographs is chosen that may be higher quality than the

+		<span class="inline_code">BVSCALE_GOOD_PHOTO</span> choice.&nbsp; This may include nearest neighbor.&nbsp; No implementation 

+		will return an error for this setting.</td>

+	</tr>

+	<tr>

+		<td class="inline_code">BVSCALE_BETTER_DRAWING</td>

+		<td>A scaling technique appropriate for drawings is chosen that may be higher quality than the

+		<span class="inline_code">BVSCALE_GOOD_DRAWING</span> choice.&nbsp; This may include nearest neighbor.&nbsp; No 

+		implementation will return an error for this setting.</td>

+	</tr>

+	<tr>

+		<td class="inline_code">BVSCALE_BEST</td>

+		<td>The highest quality scaling technique is chosen.&nbsp; This may include nearest neighbor.&nbsp; No implementation 

+		will return an error for this setting.</td>

+	</tr>

+	<tr>

+		<td class="inline_code">BVSCALE_BEST_POINT_SAMPLE</td>

+		<td>The highest quality point sample technique is chosen.</td>

+	</tr>

+	<tr>

+		<td class="inline_code">BVSCALE_BEST_INTERPOLATED</td>

+		<td>The highest quality interpolated scaling technique is chosen.</td>

+	</tr>

+	<tr>

+		<td class="inline_code">BVSCALE_BEST_PHOTO</td>

+		<td>The highest quality scaling technique appropriate for photographs is chosen.&nbsp; This may include nearest 

+		neighbor.&nbsp; No implementation will return an error for this setting.</td>

+	</tr>

+	<tr>

+		<td class="inline_code">BVSCALE_BEST_DRAWING</td>

+		<td>The highest quality scaling technique appropriate for drawings is chosen.&nbsp; This may include nearest neighbor.&nbsp; 

+		No implementation will return an error for this setting.</td>

+	</tr>

+</table>

+<br />

+<span class="inline_code">BVSCALEDEF_VENDOR_GENERAL</span> can be used to specify one of the shared explicit scale types.&nbsp; 

+At this point, only a limited number of explicit scale types are defined: <br />

+<br />

+<table class="indent">

+	<tr>

+		<td class="inline_code">BVSCALE_NEAREST_NEIGHBOR</td>

+		<td>This is a point sample scaling technique where the resampled destination pixel is set to the value of the closest 

+		source pixel.</td>

+	</tr>

+	<tr>

+		<td class="inline_code">BVSCALE_BILINEAR</td>

+		<td>This is an interpolated scaling technique where the resampled destination pixel is set to a value linearly interpolated 

+		in two dimensions from the four closest source pixels.</td>

+	</tr>

+	<tr>

+		<td class="inline_code">BVSCALE_BICUBIC</td>

+		<td>This is an interpolated scaling technique where the resampled destination pixel is set to a value calculated 

+		using cubic interpolation in two dimensions.</td>

+	</tr>

+	<tr>

+		<td class="inline_code">BVSCALE_3x3_TAP</td>

+		<td>&nbsp;</td>

+	</tr>

+	<tr>

+		<td class="inline_code">BVSCALE_5x5_TAP</td>

+		<td>&nbsp;</td>

+	</tr>

+	<tr>

+		<td class="inline_code">BVSCALE_7x7_TAP</td>

+		<td>&nbsp;</td>

+	</tr>

+	<tr>

+		<td class="inline_code">BVSCALE_9x9_TAP</td>

+		<td>&nbsp;</td>

+	</tr>

+</table>

+<p>If the client wants to know the explicit type chosen by a given implementation, it can set <span class="inline_code">

+BVFLAG_SCALE_RETURN</span> in the <span class="inline_code"><a href="#flags">bvbltparams.flags</a></span> member, and the 

+explicit scale type is returned in the <span class="inline_code">scalemode</span> member.</p>

+<p class="note">NOTE:&nbsp; Extending the <span class="inline_code">BVSCALEDEF_VENDOR_GENERAL</span> scale types or obtaining 

+a vendor ID can be accomplished by submitting a patch.</p>

+<p class="Code_Header_2"><a name="dithermode">bvbltparams.dithermode</a></p>

+<p class="code_block">enum bvdithermode dithermode; /* input/output */</p>

+<p>This member allows the client to specify the type of dithering to be used, when the output format has fewer bits of depth 

+than the internal calculation.&nbsp; The enumeration begins with 8 bits indicating the vendor.&nbsp; The remaining bits 

+are defined by the vendor.&nbsp; <span class="inline_code">BVDITHERDEF_VENDOR_ALL</span> and <span class="inline_code">BVDITHERDEF_VENDOR_GENERAL</span> 

+are shared by all implementations.</p>

+<p><span class="inline_code">BVDITHERDEF_VENDOR_ALL</span> can be used to specify an implicit dither type.&nbsp; This type 

+is converted to an explicit type by the implementation:</p>

+<table class="indent">

+	<tr>

+		<td class="inline_code">BVDITHER_FASTEST</td>

+		<td>The fastest method of dithering available is used.&nbsp; This may include no dithering (truncation).&nbsp; The 

+		value of this enumeration is purposely 0, and is the default dither type.&nbsp; No implementation will return an 

+		error for this setting.</td>

+	</tr>

+	<tr>

+		<td class="inline_code">BVDITHER_FASTEST_ON</td>

+		<td>The fastest method of dithering available is used.&nbsp; This will not include no dithering.</td>

+	</tr>

+	<tr>

+		<td class="inline_code">BVDITHER_FASTEST_RANDOM</td>

+		<td>The fastest method of dithering using a random technique.</td>

+	</tr>

+	<tr>

+		<td class="inline_code">BVDITHER_FASTEST_ORDERED</td>

+		<td>The fastest method of dithering using an ordered diffusion technique.</td>

+	</tr>

+	<tr>

+		<td class="inline_code">BVDITHER_FASTEST_DIFFUSED</td>

+		<td>The fastest method of dithering using an error diffusion technique.</td>

+	</tr>

+	<tr>

+		<td class="inline_code">BVDITHER_FASTEST_PHOTO</td>

+		<td>The fastest method of dithering appropriate for photographs is used.&nbsp; This may include no dithering.&nbsp; 

+		No implementation will return an error for this setting.</td>

+	</tr>

+	<tr>

+		<td class="inline_code">BVDITHER_FASTEST_DRAWING</td>

+		<td>The fastest method of dithering appropriate for drawings is used.&nbsp; This may include no dithering.&nbsp; 

+		No implementation will return an error for this setting.</td>

+	</tr>

+	<tr>

+		<td class="inline_code">BVDITHER_GOOD</td>

+		<td>A dithering technique is chosen that may be higher quality than the <span class="inline_code">BVDITHER_FASTEST</span> 

+		choice.&nbsp; This may include no dithering.&nbsp; No implementation will return an error for this setting.</td>

+	</tr>

+	<tr>

+		<td class="inline_code">BVDITHER_GOOD_ON</td>

+		<td>Any dithering technique available is used.&nbsp; This will not include no dithering.&nbsp; This may be higher 

+		quality than <span class="inline_code">BVDITHER_FASTEST_ON</span>.</td>

+	</tr>

+	<tr>

+		<td class="inline_code">BVDITHER_GOOD_RANDOM</td>

+		<td>A random dithering technique is chosen that may be higher quality than the <span class="inline_code">BVDITHER_FASTEST_RANDOM</span> 

+		choice.</td>

+	</tr>

+	<tr>

+		<td class="inline_code">BVDITHER_GOOD_ORDERED</td>

+		<td>An ordered dithering technique is chosen that may be higher quality than the <span class="inline_code">BVDITHER_FASTEST_ORDERED</span> 

+		choice.</td>

+	</tr>

+	<tr>

+		<td class="inline_code">BVDITHER_GOOD_DIFFUSED</td>

+		<td>A diffused dithering technique is chosen that may be higher quality than the <span class="inline_code">BVDITHER_FASTEST_DIFFUSED</span> 

+		choice.</td>

+	</tr>

+	<tr>

+		<td class="inline_code">BVDITHER_GOOD_PHOTO</td>

+		<td>A dithering technique appropriate for photographs is chosen that may be higher quality than the

+		<span class="inline_code">BVDITHER_FASTEST_PHOTO</span> choice.&nbsp; This may include no dithering.&nbsp; No implementation 

+		will return an error for this setting.</td>

+	</tr>

+	<tr>

+		<td class="inline_code">BVDITHER_GOOD_DRAWING</td>

+		<td>A dithering technique appropriate for drawings is chosen that may be higher quality than the

+		<span class="inline_code">BVDITHER_FASTEST_DRAWING</span> choice.&nbsp; This may include no dithering.&nbsp; No 

+		implementation will return an error for this setting.</td>

+	</tr>

+	<tr>

+		<td class="inline_code">BVDITHER_BETTER</td>

+		<td>A dithering technique is chosen that may be higher quality than the <span class="inline_code">BVDITHER_GOOD</span> 

+		choice.&nbsp; This may include no dithering.&nbsp; No implementation will return an error for this setting.</td>

+	</tr>

+	<tr>

+		<td class="inline_code">BVDITHER_BETTER_ON</td>

+		<td>Any dithering technique available is used.&nbsp; This will not include no dithering.&nbsp; This may be higher 

+		quality than <span class="inline_code">BVDITHER_GOOD_ON</span>.</td>

+	</tr>

+	<tr>

+		<td class="inline_code">BVDITHER_BETTER_RANDOM</td>

+		<td>A random dithering technique is chosen that may be higher quality than the <span class="inline_code">BVDITHER_GOOD_RANDOM</span> 

+		choice.</td>

+	</tr>

+	<tr>

+		<td class="inline_code">BVDITHER_BETTER_ORDERED</td>

+		<td>An ordered dithering technique is chosen that may be higher quality than the <span class="inline_code">BVDITHER_GOOD_ORDERED</span> 

+		choice.</td>

+	</tr>

+	<tr>

+		<td class="inline_code">BVDITHER_BETTER_DIFFUSED</td>

+		<td>A diffused dithering technique is chosen that may be higher quality than the <span class="inline_code">BVDITHER_GOOD_DIFFUSED</span> 

+		choice.</td>

+	</tr>

+	<tr>

+		<td class="inline_code">BVDITHER_BETTER_PHOTO</td>

+		<td>A scaling technique appropriate for photographs is chosen that may be higher quality than the

+		<span class="inline_code">BVSCALE_GOOD_PHOTO</span> choice.&nbsp; No implementation will return an error for this 

+		setting.</td>

+	</tr>

+	<tr>

+		<td class="inline_code">BVDITHER_BETTER_DRAWING</td>

+		<td>A scaling technique appropriate for drawings is chosen that may be higher quality than the

+		<span class="inline_code">BVSCALE_GOOD_DRAWING</span> choice.&nbsp; No implementation will return an error for this 

+		setting.</td>

+	</tr>

+	<tr>

+		<td class="inline_code">BVDITHER_BEST</td>

+		<td>The highest quality dithering technique is chosen.&nbsp; This may include no dithering.&nbsp; No implementation 

+		will return an error for this setting.</td>

+	</tr>

+	<tr>

+		<td class="inline_code">BVDITHER_BEST_ON</td>

+		<td>Any dithering technique available is used.&nbsp; This will not include no dithering.&nbsp; This may be higher 

+		quality than <span class="inline_code">BVDITHER_BEST_ON</span>.</td>

+	</tr>

+	<tr>

+		<td class="inline_code">BVDITHER_BEST_RANDOM</td>

+		<td>The highest quality random dithering technique is chosen.</td>

+	</tr>

+	<tr>

+		<td class="inline_code">BVDITHER_BEST_ORDERED</td>

+		<td>The highest quality ordered dithering technique is chosen.</td>

+	</tr>

+	<tr>

+		<td class="inline_code">BVDITHER_BEST_DIFFUSED</td>

+		<td>The highest quality diffused dithering technique is chosen.</td>

+	</tr>

+	<tr>

+		<td class="inline_code">BVDITHER_BEST_PHOTO</td>

+		<td>The highest quality dithering technique appropriate for photographs is chosen.&nbsp; This may include no dithering.&nbsp; 

+		No implementation will return an error for this setting.</td>

+	</tr>

+	<tr>

+		<td class="inline_code">BVDITHER_BEST_DRAWING</td>

+		<td>The highest quality dithering technique appropriate for drawings is chosen.&nbsp; This may include no dithering.&nbsp; 

+		No implementation will return an error for this setting.</td>

+	</tr>

+</table>

+<br />

+<span class="inline_code">BVDITHERDEF_VENDOR_GENERAL</span> can be used to specify one of the shared explicit dithering 

+types.&nbsp; At this point, only a limited number of explicit dither types are defined:<br />

+<br />

+<table class="indent">

+	<tr>

+		<td class="inline_code">BVDITHER_NONE</td>

+		<td>No dithering is performed.&nbsp; Internal pixel component values are truncated to the destination component 

+		bit depth.</td>

+	</tr>

+	<tr>

+		<td class="inline_code">BVDITHER_ORDERED_2x2</td>

+		<td>&nbsp;</td>

+	</tr>

+	<tr>

+		<td class="inline_code">BVDITHER_ORDERED_4x4</td>

+		<td>&nbsp;</td>

+	</tr>

+	<tr>

+		<td class="inline_code">BVDITHER_ORDERED_2x2_4x4</td>

+		<td>2x2 ordered dither is used for components with the lowest bit reduction.&nbsp; 4x4 ordered dither is used for 

+		the components with the highest bit reduction.&nbsp; (E.g. RGB24 to RGB565 will use 2x2 ordered dither for the green 

+		component and 4x4 ordered dither for the red and blue components.)</td>

+	</tr>

+</table>

+<p>If the client wants to know the explicit type chosen by a given implementation, it can set <span class="inline_code">

+BVFLAG_DITHER_RETURN</span> in the <span class="inline_code"><a href="#flags">bvbltparams.flags</a></span> member, and the 

+explicit scale type is returned in the <span class="inline_code">dithermode</span> member.</p>

+<p class="note">NOTE:&nbsp; Extending the <span class="inline_code">BVDITHERDEF_VENDOR_GENERAL</span> scale types or obtaining 

+a vendor ID can be accomplished by submitting a patch.</p>

+<p class="Code_Header_2"><a name="dstdesc">bvbltparams.dstdesc</a></p>

+<p class="code_block"><a href="#bvbuffdesc">struct bvbuffdesc</a> *dstdesc;</p>

+<p><span class="inline_code">dstdesc</span> is used to specify the destination buffer.&nbsp; If the buffer has not been 

+mapped with a call to <span class="inline_code"><a href="#bv_map">bv_map()</a></span>, <span class="inline_code">

+<a href="#bv_blt">bv_blt()</a></span> will map the buffer as necessary to perform the BLT and then unmap afterwards.&nbsp; 

+See <span class="inline_code"><a href="#bvbuffdesc">bvbuffdesc</a></span> for details.</p>

+<p class="Code_Header_2"><a name="dstgeom">bvbltparams.dstgeom</a></p>

+<p class="code_block"><a href="#bvsurfgeom">struct bvsurfgeom</a> *dstgeom;</p>

+<p><span class="inline_code">dstgeom</span> is used to specify the geometry of the surface contained in the destination 

+buffer.&nbsp; See <span class="inline_code"><a href="#bvsurfgeom">bvsurfgeom</a></span> for details.</p>

+<p class="Code_Header_2"><a name="dstrect">bvbltparams.dstrect</a></p>

+<p class="code_block"><a href="#bvrect">struct bvrect</a> dstrect;</p>

+<p><span class="inline_code">dstrect</span> is used to specify the destination rectangle to receive the BLT.&nbsp; This 

+rectangle is clipped by <span class="inline_code"><a href="#cliprect">bvbltparams.cliprect</a></span> when

+<span class="inline_code"><a href="#BVFLAG_CLIP">BVFLAG_CLIP</a></span> is set in the <span class="inline_code">

+<a href="#flags">bvbltparams.flags</a></span> member.</p>

+<p class="Code_Header_2">bvbltparams.<a name="src1.desc">src1</a>/<a name="src2.desc">src2</a>/<a name="mask.desc">mask.desc</a></p>

+<p class="code_block"><a href="#bvbuffdesc">struct bvbuffdesc</a> *src1.desc;<br />

+<a href="#bvbuffdesc">struct bvbuffdesc</a> *src2.desc;<br />

+<a href="#bvbuffdesc">struct bvbuffdesc</a> *mask.desc;</p>

+<p>These members are used to identify the buffer for the source1, source2, and mask surfaces when the associated

+<span class="inline_code">BVFLAG_TILE_*</span> flag is not set.&nbsp; The buffer is the memory in which the surface lies.&nbsp; 

+See the <span class="inline_code"><a href="#src1geom">bvbltparams.src1/src2/maskgeom</a></span> for the format and layout/geometry 

+of the surface.</p>

+<p class="note">NOTE WELL:&nbsp; Clients should never change the value of a <span class="inline_code">

+<a href="#bvbuffdesc">bvbuffdesc</a></span> structure while a buffer is mapped.</p>

+<p class="Code_Header_2">bvbltparams.<a name="src1.tileparams">src1</a>/<a name="src2.tileparams">src2</a>/<a name="mask.tileparams">mask.tileparams</a></p>

+<p class="code_block"><a href="#bvtileparams">struct bvtileparams</a> *src1.tileparams;<br />

+<a href="#bvtileparams">struct bvtileparams</a> *src2.tileparams;<br />

+<a href="#bvtileparams">struct bvtileparams</a> *mask.tileparams;</p>

+<p>These members are used to identify the buffer for the source1, source2, and mask surfaces when the associated

+<span class="inline_code">BVFLAG_TILE_*</span> flag is set.&nbsp; The buffer is the memory in which the surface lies.&nbsp; 

+This differs from the <span class="inline_code"><a href="#src1.desc">src1/src2/mask.desc</a></span> identity by providing 

+more information needed for tiling and by not requiring mapping (for hardware implementations that support tiling, the tile 

+data is usually moved into an on-chip cache).</p>

+<p class="Code_Header_2">bvbltparams.<a name="src1geom">src1</a>/<a name="src2geom">src2</a>/<a name="maskgeom">maskgeom</a></p>

+<p class="code_block"><a href="#bvsurfgeom">struct bvsurfgeom</a> src1geom;<br />

+<a href="#bvsurfgeom">struct bvsurfgeom</a> src2geom;<br />

+<a href="#bvsurfgeom">struct bvsurfgeom</a> maskgeom;</p>

+<p>These members describe the format and layout/geometry of their respective surfaces.&nbsp; Separating

+<span class="inline_code"><a href="#bvsurfgeom">bvsurfgeom</a></span> from the <span class="inline_code">

+<a href="#bvbuffdesc">bvbuffdesc</a></span> allows easy use of buffers for multiple geometries without remapping.&nbsp; 

+See <span class="inline_code"><a href="#bvsurfgeom">bvsurfgeom</a></span> and <span class="inline_code">

+<a href="#bvbuffdesc">bvbuffdesc</a></span> for details.</p>

+<p class="Code_Header_2">bbvbltparams.src1/src2/maskrect</p>

+<p class="code_block"><a href="#bvrect">struct bvrect</a> src1rect;<br />

+<a href="#bvrect">struct bvrect</a> src2rect;<br />

+<a href="#bvrect">struct bvrect</a> maskrect;</p>

+<p>These members specify the rectangle from which data is read for the BLT.&nbsp; These rectangles are clipped by a scaled 

+version of the <span class="inline_code"><a href="#cliprect">bvbltparams.cliprect</a></span>&nbsp; (scaling is based on 

+the relationship between them and the <span class="inline_code"><a href="#dstrect">bvbltparams.dstrect</a></span>) when

+<span class="inline_code"><a href="#BVFLAG_CLIP">BVFLAG_CLIP</a></span> is set in the <span class="inline_code">

+<a href="#flags">bvbltparams.flags</a></span> member.</p>

+<table class="example">

+	<tr>

+		<td>

+		<p><strong>Example:</strong></p>

+		<a href="#src1rect" class="inline_code">src1rect</a> = (0, 0) - (400 x 200)<br />

+		<a href="#dstrect" class="inline_code">dstrect</a> = (0, 0) - (800 x 600)<br />

+		<a href="#cliprect" class="inline_code">cliprect</a> = (10, 30) - (300 x 300)<p>The scaling ratio of the

+		<a href="#dstrect" class="inline_code">dstrect</a> to the <a href="#src1rect" class="inline_code">src1rect</a> is 

+		(800/400,&nbsp; 600/300) or (2, 3).&nbsp; Using this, the effective source 1 clipping rectangle becomes (10/2, 30/3) 

+		- (300/2 x 300/3) or (5, 10) - (150 x 100).</p>

+		</td>

+	</tr>

+</table>

+<p>This approach allows fractional clipping at the source using a method which is simpler to implement than fractional coordinates.</p>

+<p class="note">NOTE:&nbsp; In BLTsville, reading outside the source rectangle is forbidden.&nbsp; So scaling algorithms 

+which require pixels around a particular source pixel must utilize boundary techniques (mirror, repeat, clamp, etc.) at 

+the edges of the source rectangle.&nbsp; However, if the clipping rectangle, when translated back to the source rectangle, 

+leaves space between it and the source rectangle, pixels outside the clipped region may be accessed by the implementation.</p>

+<p class="Code_Header_2"><a name="cliprect">bvbltparams.cliprect</a></p>

+<p class="code_block"><a href="#bvrect">struct bvrect</a> cliprect;</p>

+<p><span class="inline_code">cliprect</span> is used to specify a rectangle that limits what region of the destination is 

+written.&nbsp; This is most useful for scaling operations, where the necessary scaling factor will not allow translation 

+of the destination rectangle back to the source on an integer pixel boundary.</p>

+<p class="note">NOTE:&nbsp; If <span class="inline_code">cliprect</span> exceeds the destination surface, the behavior is 

+undefined. </p>

+<p>For example, if the goal is to show a 640 x 480 video on a 1920 x 1080 screen, the video would be stretched to 1440 x 

+1080 to maintain the proper aspect ratio.&nbsp; So the relevant rectangles would be:</p>

+<table class="indent">

+	<tr>

+		<td class="thin_bord"><strong>src1rect</strong></td>

+		<td class="thin_bord"><strong>dstrect</strong></td>

+	</tr>

+	<tr>

+		<td class="thin_bord">(0, 0) - 640 x 480</td>

+		<td class="thin_bord">(240, 0) - 1440 x 1080</td>

+	</tr>

+</table>

+<p>However, to handle a 640 x 480 pop-up window that appears centered on the screen, in front of the video, the single BLT 

+may be broken into four smaller BLTs pieced around the popup.&nbsp; These rectangles would need to be:</p>

+<table class="indent">

+	<tr>

+		<td class="thin_bord"><strong>src1rect</strong></td>

+		<td class="thin_bord"><strong>dstrect</strong></td>

+	</tr>

+	<tr>

+		<td class="thin_bord">(0, 0) - 640 x 133.333...</td>

+		<td class="thin_bord">(240, 0) - 1440 x 300</td>

+	</tr>

+	<tr>

+		<td class="thin_bord">(0, 133.333...) - 284.444... x 213.333...</td>

+		<td class="thin_bord">(240, 300) - 400 x 480</td>

+	</tr>

+	<tr>

+		<td class="thin_bord">(568.888..., 133.333...) - 284.444... x 213.333...</td>

+		<td class="thin_bord">(1280, 300) - 400 x 480</td>

+	</tr>

+	<tr>

+		<td class="thin_bord">(0, 346.666...) - 640 x 133.333...</td>

+		<td class="thin_bord">(240, 780) - 1440 x 300</td>

+	</tr>

+</table>

+<p>Since this is a scaling factor of 2.25x, translating the required destination rectangles back to the source results in 

+non-integer coordinates and dimensions, as illustrated above.&nbsp; And adjusting the source rectangles to the nearest integer 

+values will result in visible discontinuities at the boundaries between the rectangles.</p>

+<p>Instead, using the <span class="inline_code">cliprect</span>, this situation can be handled more easily:</p>

+<table class="indent">

+	<tr>

+		<td class="thin_bord"><strong>src1rect</strong></td>

+		<td class="thin_bord"><strong>dstrect</strong></td>

+		<td class="thin_bord"><strong>cliprect</strong></td>

+	</tr>

+	<tr>

+		<td class="thin_bord">(0, 0) - 640 x 480</td>

+		<td class="thin_bord">(240, 0) - 1440 x 1080</td>

+		<td class="thin_bord">(240, 0) - 1440 x 300</td>

+	</tr>

+	<tr>

+		<td class="thin_bord">(0, 0) - 640 x 480</td>

+		<td class="thin_bord">(240, 0) - 1440 x 1080</td>

+		<td class="thin_bord">(240, 300) - 400 x 480</td>

+	</tr>

+	<tr>

+		<td class="thin_bord">(0, 0) - 640 x 480</td>

+		<td class="thin_bord">(240, 0) - 1440 x 1080</td>

+		<td class="thin_bord">(1280, 300) - 400 x 480</td>

+	</tr>

+	<tr>

+		<td class="thin_bord">(0, 0) - 640 x 480</td>

+		<td class="thin_bord">(240, 0) - 1440 x 1080</td>

+		<td class="thin_bord">(240, 780) - 1440 x 300</td>

+	</tr>

+</table>

+<p class="Code_Header_2"><a name="batchflags">bvbltparams.batchflags</a></p>

+<p class="code_block">unsigned long batchflags;</p>

+<p><span class="inline_code">batchflags</span> are used by the client as a hint to indicate to the implementation which 

+parameters are changing between successive BLTs of a batch.&nbsp; The flags may be used when the

+<span class="inline_code"><a href="#flags">bvbltparams.flags</a></span> has <span class="inline_code">

+<a href="#BVFLAG_BATCH_CONTINUE">BVFLAG_BATCH_CONTINUE</a></span> or <span class="inline_code">

+<a href="#BVFLAG_BATCH_END">BVFLAG_BATCH_END</a></span> set.</p>

+<table style="" class="indent">

+	<tr>

+		<td><span class="inline_code"><a name="BVBATCH_OP">BVBATCH_OP</a></span></td>

+		<td>indicates that the operation type (<span class="inline_code"><a href="#BVFLAG_ROP">BVFLAG_ROP</a></span>,

+		<span class="inline_code"><a href="#BVFLAG_BLEND">BVFLAG_BLEND</a></span>, <span class="inline_code">

+		<a href="#BVFLAG_FILTER">BVFLAG_FILTER</a></span>, etc.) has changed.</td>

+	</tr>

+	<tr>

+		<td><span class="inline_code"><a name="BVBATCH_KEY">BVBATCH_KEY</a></span></td>

+		<td>indicates that the <span class="inline_code"><a href="#colorkey">bvbltparams.colorkey</a></span> or the color 

+		key mode (<span class="inline_code"><a href="#BVFLAG_KEY_SRC">BVFLAG_KEY_SRC</a></span>/<span class="inline_code"><a href="#BVFLAG_KEY_DST">BVFLAG_KEY_DST</a></span>) 

+		has changed.</td>

+	</tr>

+	<tr>

+		<td><span class="inline_code"><a name="BVBATCH_MISCFLAGS">BVBATCH_MISCFLAGS</a></span></td>

+		<td>indicates that <span class="inline_code"><a href="#flags">bvbltparams.flags</a></span> other than the operation, 

+		color key, or clip flag have changes.</td>

+	</tr>

+	<tr>

+		<td><span class="inline_code"><a name="BVBATCH_ALPHA">BVBATCH_ALPHA</a></span></td>

+		<td>indicates that <span class="inline_code"><a href="#globalalpha">bvbltparams.globalalpha</a></span> or global 

+		alpha type has changed.</td>

+	</tr>

+	<tr>

+		<td><a name="BVBATCH_DITHER" class="inline_code">BVBATCH_DITHER</a></td>

+		<td>indicates that <span class="inline_code"><a href="#dithermode">bvbltparams.dithermode</a></span> has changed.</td>

+	</tr>

+	<tr>

+		<td><span class="inline_code"><a name="BVBATCH_SCALE">BVBATCH_SCALE</a></span></td>

+		<td>indicates that <span class="inline_code"><a href="#scalemode">bvbltparams.scalemode</a></span> has changed.</td>

+	</tr>

+	<tr>

+		<td><span class="inline_code"><a name="BVBATCH_DST">BVBATCH_DST</a></span></td>

+		<td>indicates that the destination surface (<span class="inline_code"><a href="#dstdesc">bvbltparams.dstdesc</a></span>,

+		<span class="inline_code"><a href="#dstgeom">bvbltparams.dstgeom</a></span> ,or <span class="inline_code">

+		<a href="#dstrect">bvbltparams.dstrect</a></span>) has changed.</td>

+	</tr>

+	<tr>

+		<td><span class="inline_code"><a name="BVBATCH_SRC1">BVBATCH_SRC1</a></span> </td>

+		<td>indicates that the source 1 surface (<span class="inline_code"><a href="#src1.desc">bvbltparams.src1.desc</a></span> 

+		or <span class="inline_code"><a href="#src1.tileparams">bvbltparams.src1.tileparams</a></span>, or

+		<span class="inline_code"><a href="#src1geom">bvbltparams.src1geom</a></span>) has changed.</td>

+	</tr>

+	<tr>

+		<td><span class="inline_code"><a name="BVBATCH_SRC2">BVBATCH_SRC2</a></span> </td>

+		<td>indicates that the source 2 surface (<span class="inline_code"><a href="#src2.desc">bvbltparams.src2.desc</a></span> 

+		or <span class="inline_code"><a href="#src2.tileparams">bvbltparams.src2.tileparams</a></span>, or

+		<span class="inline_code"><a href="#src2geom">bvbltparams.src2geom</a></span>) has changed.</td>

+	</tr>

+	<tr>

+		<td><span class="inline_code"><a name="BVBATCH_MASK">BVBATCH_MASK</a></span> </td>

+		<td>indicates that the mask surface (<span class="inline_code"><a href="#mask.desc">bvbltparams.mask.desc</a></span> 

+		or <span class="inline_code"><a href="#mask.tileparams">bvbltparams.mask.tileparams</a></span>, or

+		<span class="inline_code"><a href="#maskgeom">bvbltparams.maskgeom</a></span>) has changed.</td>

+	</tr>

+	<tr>

+		<td><span class="inline_code"><a name="BVBATCH_DSTRECT_ORIGIN">BVBATCH_DSTRECT_ORIGIN</a></span></td>

+		<td>indicates that <span class="inline_code"><a href="#dstrect">bvbltparams.dstrect.left</a></span> or

+		<span class="inline_code"><a href="#dstrect">top</a></span> has changed.</td>

+	</tr>

+	<tr>

+		<td><span class="inline_code"><a name="BVBATCH_DSTRECT_SIZE">BVBATCH_DSTRECT_SIZE</a></span></td>

+		<td>indicates that the <span class="inline_code"><a href="#dstrect">bvbltparams.dstrect.width</a></span> or

+		<a href="#dstrect">height</a> has changed.</td>

+	</tr>

+	<tr>

+		<td><span class="inline_code"><a name="BVBATCH_SRC1RECT_ORIGIN">BVBATCH_SRC1RECT_ORIGIN</a></span></td>

+		<td>indicates that <span class="inline_code"><a href="#src1rect">bvbltparams.src1rect.left</a></span> or

+		<span class="inline_code"><a href="#dstrect">top</a></span> has changed.</td>

+	</tr>

+	<tr>

+		<td><span class="inline_code"><a name="BVBATCH_SRC1RECT_SIZE">BVBATCH_SRC1RECT_SIZE</a></span></td>

+		<td>indicates that the <span class="inline_code"><a href="#src1rect">bvbltparams.src1rect.width</a></span> or

+		<a href="#src1rect">height</a> has changed.</td>

+	</tr>

+	<tr>

+		<td><span class="inline_code"><a name="BVBATCH_SRC2RECT_ORIGIN">BVBATCH_SRC2RECT_ORIGIN</a></span></td>

+		<td>indicates that <span class="inline_code"><a href="#src2rect">bvbltparams.src2rect.left</a></span> or

+		<span class="inline_code"><a href="#src2rect">top</a></span> has changed.</td>

+	</tr>

+	<tr>

+		<td><span class="inline_code"><a name="BVBATCH_SRC2RECT_SIZE">BVBATCH_SRC2RECT_SIZE</a></span></td>

+		<td>indicates that the <span class="inline_code"><a href="#src2rect">bvbltparams.src2rect.width</a></span> or

+		<a href="#src2rect">height</a> has changed.</td>

+	</tr>

+	<tr>

+		<td><span class="inline_code"><a name="BVBATCH_MASKRECT_ORIGIN">BVBATCH_MASKRECT_ORIGIN</a></span></td>

+		<td>indicates that <span class="inline_code"><a href="#maskrect">bvbltparams.maskrect.left</a></span> or

+		<span class="inline_code"><a href="#maskrect">top</a></span> has changed.</td>

+	</tr>

+	<tr>

+		<td><span class="inline_code"><a name="BVBATCH_MASKRECT_SIZE">BVBATCH_MASKRECT_SIZE</a></span></td>

+		<td>indicates that the <span class="inline_code"><a href="#maskrect">bvbltparams.maskrect.width</a></span> or

+		<a href="#maskrect">height</a> has changed.</td>

+	</tr>

+	<tr>

+		<td><span class="inline_code"><a name="BVBATCH_CLIPRECT_ORIGIN">BVBATCH_CLIPRECT_ORIGIN</a></span></td>

+		<td>indicates that <span class="inline_code"><a href="#cliprect">bvbltparams.cliprect.left</a></span> or

+		<span class="inline_code"><a href="#cliprect">top</a></span> has changed.</td>

+	</tr>

+	<tr>

+		<td><span class="inline_code"><a name="BVBATCH_CLIPRECT_SIZE">BVBATCH_CLIPRECT_SIZE</a></span></td>

+		<td>indicates that the <span class="inline_code"><a href="#cliprect">bvbltparams.cliprect.width</a></span> or

+		<a href="#cliprect">height</a> has changed.</td>

+	</tr>

+	<tr>

+		<td><span class="inline_code"><a name="BVBATCH_TILE_SRC1">BVBATCH_TILE_SRC1</a></span></td>

+		<td>indicates that the <span class="inline_code"><a href="#src1.tileparams">bvbltparams.src1.tileparams</a></span> 

+		has changed.</td>

+	</tr>

+	<tr>

+		<td><span class="inline_code"><a name="BVBATCH_TILE_SRC2">BVBATCH_TILE_SRC2</a></span></td>

+		<td>indicates that the <span class="inline_code"><a href="#src2.tileparams">bvbltparams.src2.tileparams</a></span> 

+		has changed.</td>

+	</tr>

+	<tr>

+		<td><span class="inline_code"><a name="BVBATCH_TILE_MASK">BVBATCH_TILE_MASK</a></span></td>

+		<td>indicates that the <span class="inline_code"><a href="#mask.tileparams">bvbltparams.mask.tileparams</a></span> 

+		has changed.</td>

+	</tr>

+	<tr>

+		<td><span class="inline_code"><a name="BVBATCH_ENDNOP">BVBATCH_ENDNOP</a></span></td>

+		<td>is a special flag used with <span class="inline_code"><a href="#batch_end">BVFLAG_BATCH_END</a></span>, for 

+		clients that do not have information that a batch is ending until after the last BLT has been issued.&nbsp; When 

+		this flag is set, no BLT is done, but the batch is ended.</td>

+	</tr>

+</table>

+<p class="note">NOTE:&nbsp; These flags are hints, and may be used or not by a BLTsville implementation.&nbsp; So if

+<span class="inline_code"><a href="#bvbltparams">bvbltparams</a></span> members are changed between BLTs in a batch, but 

+the <span class="inline_code">bvbltparams.batchflags</span> member is not correctly updated, the resulting behavior on different 

+implementations will not be consistent.</p>

+<p class="Code_Header_2"><a name="batch">bvbltparams.batch</a></p>

+<p class="code_block"><a href="#bvbatch">struct bvbatch</a> *batch;</p>

+<p>This member is used as a batch handle, so that multiple batches can be under construction at the same time.</p>

+<p class="Code_Header_2"><a name="callbackfn">bvbltparams.callbackfn</a></p>

+<p class="code_block">void (*callbackfn)(<a href="#bvcallbackerror">struct bvcallbackerror</a> *err, unsigned long

+<a href="#callbackdata">callbackdata</a>);</p>

+<p>This member is a pointer to a client-supplied function which is called by the implementation when

+<span class="inline_code"><a href="#BVFLAG_ASYNC">BVFLAG_ASYNC</a></span> is set and the BLT is complete.&nbsp; If this 

+member is NULL, no callback is performed.&nbsp; When there is no error, the <span class="inline_code">err</span> 

+parameter will be set to 0;</p>

+<p class="note">NOTE:&nbsp; This function <span class="underline">can be called</span> before the

+<span class="inline_code"><a href="#bv_blt">bv_blt()</a></span> call has returned.</p>

+<p class="Code_Header_2"><a name="callbackdata">bvbltparams.callbackdata</a></p>

+<p class="code_block">unsigned long callbackdata;</p>

+<p>This member is used as the parameter passed back by the <span class="inline_code"><a href="#callbackfn">bvbltparams.callbackfn</a></span>.&nbsp; 

+This can be anything from an identifying index to a pointer used by the client.</p>

+<p class="Code_Header_2">bvbltparams.<a name="src2auxdstrect">src2</a>/<a name="maskauxdstrect">maskauxdstrect</a></p>

+<p class="code_block">struct bvrect src2auxdstrect;<br />

+struct bvrect maskauxdstrect;</p>

+<p>These two members are used only when the associated <span class="inline_code"><a href="#BVFLAG_SRC2_AUXDSTRECT">

+BVFLAG_SRC2</a></span>/<span class="inline_code"><a href="#BVFLAG_MASK_AUXDSTRECT">MASK_AUXDSTRECT</a></span> flags are 

+set.&nbsp; They are only necessary (and should only be used) in the case where scaling of the inputs differs and the 

+entire source images are not being used.&nbsp; <span class="inline_code"><a href="#dstrect">bvbltparams.dstrect</a></span> is always 

+used to specify the destination of source 1 image.&nbsp; When the associated flags are set, these two members are used 

+to specify the destination of the source 2 and mask images, instead of <span class="inline_code"><a href="#dstrect">

+bvbltparams.dstrect</a></span>.</p>

+<p>These flags must be used with the <span class="inline_code"><a href="#BVFLAG_CLIP">BVFLAG_CLIP</a></span> flag.&nbsp; 

+And if the resulting clipped destination does not include all enabled destination rectangles, the results are undefined.</p>

+<div class="example"><strong>Example:</strong>&nbsp; We have two images that we want to merge and view on an 854x480 LCD panel.&nbsp; One 

+image is a small background image with 16:9 (64x36) aspect ratio that we want to stretch to fill the screen.&nbsp; 

+The other is a standard definition 720x480 (4:3 aspect ratio) image with transparency we want to blend on top of our 

+background.<br />

+<table align="center">

+	<tr>

+		<td>

+			<table>

+				<tr>

+					<td class="ctr"><img alt="" src="concrete-64x36.png" width="64" height="36" /></td>

+				</tr>

+				<tr>

+					<td class="ctr">(shown actual size)</td>

+				</tr>

+			</table>

+		</td>

+		<td>

+			<table class="ctr">

+				<tr>

+					<td><img alt="" src="clock-720x480_4x3-fauxtrans.jpg" width="360" height="240" /></td>

+				</tr>

+				<tr>

+					<td class="ctr">(shown 1/2x; not adjusted for aspect ratio)</td>

+				</tr>

+			</table>

+		</td>

+	</tr>

+</table>

+We want to blend the second image onto the center of the first, scaling both, so that it looks like this:<br />

+<table align="center">

+	<tr>

+		<td><img alt="" src="blend-854x480.jpg" width="427" height="240" /></td>

+	</tr>

+	<tr>

+		<td class="ctr">(shown 1/2x)</td>

+	</tr>

+</table>

+The screen is effectively a 16:9 aspect ratio (we can ignore the fraction of a pixel here), which matches our 

+background image.&nbsp; So the background image just needs to be scaled from 64x36 to 854x480.<br />

+<br />

+	However, since the second image has a 4:3 aspect ratio, it will not cover the entire background image if we want to 

+	maintain its aspect ratio.&nbsp; Our second image is not as wide as our 16:9 image, which means it&#39;s height will match 

+	the screen height, but the width will be smaller.&nbsp; Since the screen is 480 lines (pixels) high, to maintain our 4:3 

+	aspect ratio, our second image will need to be 640 pixels wide (4 * 480 / 3).&nbsp; So it will need to be scaled from 

+	720x480 to 640x480.<br />

+<br />

+As we mentioned, we would like to center the 640 pixel image on our 854 pixel wide screen.&nbsp; That means the left edge 

+of the image will be at pixel 107 ( (854 - 640) / 2 ).&nbsp; So the leftmost 107 columns of pixels will just be a copy 

+of the left portion of the background image.&nbsp; Likewise, the rightmost 107 columns will be a copy of the right 

+portion of the background image.&nbsp; Only the middle section should be blended.<br />

+<table align="center">

+	<tr>

+		<td><img alt="" src="blend-854x480-threeblts.jpg" width="427" height="240" /></td>

+	</tr>

+	<tr>

+		<td class="ctr">(shown 1/2x)</td>

+	</tr>

+</table>

+	The side two BLTs are quite easy with BLTsville, by using the clipping rectangle:<br />

+<br />

+<table class="indent"><tr><td>

+<span class="inline_code">bvbltparams.flags = BVFLAG_ROP | BVFLAG_CLIP;<br />

+bvbltparams.op.rop = 0xCCCC;<br />

+<br />

+bvbltparams.src1.desc = bkgnddesc;<br />

+bvbltparams.src1geom = bkgndgeom;<br />

+bvbltparams.src1rect.left = 0;<br />

+bvbltparams.src1rect.top = 0;<br />

+bvbltparams.src1width = 64;<br />

+bvbltparams.src1height = 36;<br />

+<br />

+bvbltparams.dstdesc = screendesc;<br />

+bvbltparams.dstgeom = screengeom;<br />

+bvbltparams.dstrect.left = 0;<br />

+bvbltparams.dstrect.top = 0;<br />

+bvbltparams.dstrect.width = 854;<br />

+bvbltparams.dstrect.height = 480;<br />

+<br />

+bvbltparams.cliprect.left = 0;<br />

+bvbltparams.cliprect.top = 0;<br />

+bvbltparams.cliprect.width = 107;<br />

+bvbltparams.cliprect.height = 480;<br />

+bv_blt(&amp;bvbltparams);<br />

+<br />

+bvbltparams.cliprect.left += 640;<br />

+bv_blt(&amp;bvbltparams);</span></td></tr></table>

+<br />

+	However, if we try the same approach with the middle BLT, we run into problems:<br />

+<br />

+<table class="indent"><tr><td>

+<span class="inline_code">bvbltparams.flags = BVFLAG_BLEND | BVFLAG_CLIP;<br />

+bvbltparams.op.blend = BVBLEND_SRC1OVER;<br />

+<br />

+bvbltparams.src1.desc = foregnddesc;<br />

+bvbltparams.src1geom = foregndgeom;<br />

+bvbltparams.src1rect.left = 0;<br />

+bvbltparams.src1rect.top = 0;<br />

+bvbltparams.src1rect.width = 720;<br />

+bvbltparams.src1rect.height = 480;<br />

+<br />

+bvbltparams.src2.desc = bkgnddesc;<br />

+bvbltparams.src2geom = bkgndgeom;<br />

+bvbltparams.src2rect.left = 0;<br />

+bvbltparams.src2rect.top = 0;<br />

+bvbltparams.src2width = 64;<br />

+bvbltparams.src2height = 36;<br />

+<br />

+bvbltparams.cliprect.left = 107;<br />

+bvbltparams.cliprect.top = 0;<br />

+bvbltparams.cliprect.width = 640;<br />

+bvbltparams.cliprect.height = 480;<br />

+bv_blt(&amp;bvbltparams);</span></td></tr></table>

+<table align="center">

+	<tr>

+		<td><img alt="" src="blend-854x480-bad.jpg" width="427" height="240" /></td>

+	</tr>

+	<tr>

+		<td class="ctr">(shown 1/2x)</td>

+	</tr>

+</table>

+	The result is that the foreground image is stretched horizontally.&nbsp; That&#39;s because the scaling factor is 

+	derived from the source (1) rectangle and the destination rectangle, which is the full width of the screen.&nbsp; 

+	Since we were also scaling the background, we set the destination rectangle to cover the screen, as we did in the 

+	previous two BLTs.<br />

+	<br />

+	The edges of our foreground image are also cropped, since we were only modifying the middle of the screen.<br />

+	<br />

+	What if we change the destination rectangle?<br />

+	<br />

+<table class="indent"><tr><td>

+<span class="inline_code">bvbltparams.dstrect.left = 107;<br />

+bvbltparams.dstrect.top = 0;<br />

+bvbltparams.dstrect.width = 640;<br />

+bvbltparams.dstrect.height = 480;<br />

+<br />

+bv_blt(&amp;bvbltparams);</span></td></tr></table>

+<table align="center">

+	<tr>

+		<td><img alt="" src="blend-854x480-bad2.jpg" width="427" height="240" /></td>

+	</tr>

+	<tr>

+		<td class="ctr">(shown 1/2x)</td>

+	</tr>

+</table>

+	Here we get the proper scaling of the foreground image, but the background image is scaled improperly.<br />

+	<br />

+	What if we adjust the source rectangles?&nbsp;

+For our purposes, we want all of the foreground image, but we only need the middle of the background image.&nbsp; So 

+	we can manually specify the middle of the background image by modifying the source 2 rectangle:<br />

+	<br />

+<table class="indent"><tr><td>

+<span class="inline_code">bvbltparams.src2rect.left = 107 * 64 / 854;<br />

+bvbltparams.src2rect.width = 640 * 64 / 854;</span></td></tr></table><br />

+Nice, but what are those values?<br />

+<br />

+<table class="indent"><tr><td>

+107 * 1280 / 854 = 8.0187...<br />

+640 * 1280 / 854 = 47.9625...<br />

+</td></tr></table>

+<br />

+	In BLTsville, all rectangle parameters are expressed in integers (this also allows BLTsville to be used in the 

+	kernels where floating point variables are not allowed).&nbsp; The clipping rectangle then handles introducing the 

+	necessary source pixel subdivision (by translating the clipping rectangle back to the source rectangle in the 

+	implementation).&nbsp; So what happens if we actually do use these values as integers?<br />

+<br />

+<table class="indent"><tr><td>

+<span class="inline_code">bvbltparams.src2rect.left = 8;<br />

+bvbltparams.src2rect.top = 0;<br />

+bvbltparams.src2rect.width = 47;<br />

+bvbltparams.src2height = 36;<br />

+<br />

+bv_blt(&amp;bvbltparams);</span></td></tr></table>

+<br />

+	And this is what we get:<br />

+<table align="center">

+	<tr>

+		<td><img alt="" src="blend-854x480-roundingerror.jpg" width="427" height="240" /></td>

+	</tr>

+	<tr>

+		<td class="ctr">(shown 1/2x)</td>

+	</tr>

+</table>

+	Closer, but not quite.&nbsp; Rounding the values above to integers still results in visible errors at the boundaries 

+	between the middle and the side BLTs (the one on the right is a bit more visible at this reduced size, but if you 

+	view the full image, you&#39;ll see the left one as well), because the left edge and scaling (and right edge as a 

+	result) don&#39;t match the alignment and scaling done for the BLTs on the side.&nbsp; <p class="note">NOTE:&nbsp; This artifact is not always obvious in still images.&nbsp; 

+	The images here were chosen to make the artifacts obvious in this documentation.&nbsp; But even if the static images 

+	appear correct, movement of the images (e.g. moving the foreground image across the background image) or changes in 

+	the blending (e.g. fading the foreground image out and finally removing it), will show these less obvious 

+	discrepancies.</p>This is actually what the 

+	clipping rectangle is for.&nbsp; It&#39;s meant to allow us to always specify the source and destination rectangles the 

+	same, but move the clipping window around on the destination to get just the pixels we want.&nbsp; That way the 

+	scaling and alignment area always the same.&nbsp; Unfortunately, for this special case, we really need a way to 

+	specify different scaling factors for the different inputs.&nbsp; The src2auxdstrect (and maskauxdstrect, when 

+	needed) have been added to provide this capability.<br />

+	<br />

+	Here is how this set of BLTs can be done:<br />

+<br />

+<table class="indent"><tr><td>

+<span class="inline_code">bvbltparams.flags = BVFLAG_ROP | BVFLAG_CLIP;<br />

+bvbltparams.op.rop = 0xCCCC;<br />

+<br />

+bvbltparams.src1.desc = bkgnddesc;<br />

+bvbltparams.src1geom = bkgndgeom;<br />

+bvbltparams.src1rect.left = 0;<br />

+bvbltparams.src1rect.top = 0;<br />

+bvbltparams.src1width = 64;<br />

+bvbltparams.src1height = 36;<br />

+<br />

+bvbltparams.dstdesc = screendesc;<br />

+bvbltparams.dstgeom = screengeom;<br />

+bvbltparams.dstrect.left = 0;<br />

+bvbltparams.dstrect.top = 0;<br />

+bvbltparams.dstrect.width = 854;<br />

+bvbltparams.dstrect.height = 480;<br />

+<br />

+bvbltparams.cliprect.left = 0;<br />

+bvbltparams.cliprect.top = 0;<br />

+bvbltparams.cliprect.width = 107;<br />

+bvbltparams.cliprect.height = 480;<br />

+bv_blt(&amp;bvbltparams);<br />

+<br />

+bvbltparams.cliprect.left += 640;<br />

+bv_blt(&amp;bvbltparams);<br />

+<br />

+bvbltparams.flags = BVFLAG_BLEND | BVFLAG_CLIP | BVFLAG_SRC2_AUXDSTRECT;<br />

+bvbltparams.op.blend = BVBLEND_SRC1OVER;<br />

+<br />

+bvbltparams.src1.desc = foregnddesc;<br />

+bvbltparams.src1geom = foregndgeom;<br />

+bvbltparams.src1rect.left = 0;<br />

+bvbltparams.src1rect.top = 0;<br />

+bvbltparams.src1rect.width = 720;<br />

+bvbltparams.src1rect.height = 480;<br />

+<br />

+bvbltparams.dstrect.left = 107;<br />

+bvbltparams.dstrect.top = 0;<br />

+bvbltparams.dstrect.width = 640;<br />

+bvbltparams.dstrect.height = 480;<br />

+<br />

+bvbltparams.src2.desc = bkgnddesc;<br />

+bvbltparams.src2geom = bkgndgeom;<br />

+bvbltparams.src2rect.left = 0;<br />

+bvbltparams.src2rect.top = 0;<br />

+bvbltparams.src2width = 64;<br />

+bvbltparams.src2height = 36;<br />

+<br />

+bvbltparams.src2auxdstrect.left = 0;<br />

+bvbltparams.src2auxdstrect.top = 0;<br />

+bvbltparams.src2auxdstrect.width = 854;<br />

+bvbltparams.src2auxdstrect.height = 480;<br />

+<br />

+bvbltparams.cliprect.left = 107;<br />

+bvbltparams.cliprect.top = 0;<br />

+bvbltparams.cliprect.width = 640;<br />

+bvbltparams.cliprect.height = 480;<br />

+bv_blt(&amp;bvbltparams);</span></td></tr></table>

+<br />

+Using this approach, we get the desired output:<br />

+<table align="center">

+	<tr>

+		<td><img alt="" src="blend-854x480.jpg" width="427" height="240" /></td>

+	</tr>

+	<tr>

+		<td class="ctr">(shown 1/2x)</td>

+	</tr>

+</table>

+	It may also be clear that in that last BLT, the clip rectangle isn&#39;t really necessary.&nbsp; This is good, because 

+	it frees up the clipping rectangle to be used to further subdivide the image if necessary (e.g. if partially 

+	occluded).<br />

+</div>

+<br />

+<hr />

+<p class="Code_Header"><a name="bvrect">bvrect</a></p>

+<p class="small_code_block">struct bvrect {<br />

+&nbsp;&nbsp;&nbsp; int <a href="#bvrect.left">left</a>;<br />

+&nbsp;&nbsp;&nbsp; int <a href="#bvrect.top">top</a>;<br />

+&nbsp;&nbsp;&nbsp; unsigned int <a href="#bvrect.width">width</a>;<br />

+&nbsp;&nbsp;&nbsp; unsigned int <a href="#bvrect.height">height</a>;<br />

+};</p>

+<p class="Code_Header_2"><a name="bvrect.left">bvrect.left</a></p>

+<p class="code_block">int left;</p>

+<p>This member indicates the left edge of the rectangle, measured in pixels from the left edge of the surface.&nbsp; Note 

+that this value <span class="underline">can</span> be negative, indicating that the rectangle begins before the left edge 

+of the surface.&nbsp; However, this is only allowed when a rectangle is clipped to the surface.&nbsp; If, after clipping, 

+the left edge of the rectangle is still negative, this is an error.</p>

+<p class="Code_Header_2"><a name="bvrect.top">bvrect.top</a></p>

+<p class="code_block">int top;</p>

+<p>This member indicates the top edge of the rectangle, measured in lines of

+<a href="#bfbuffdesc.virtstride" class="inline_code">bvbuffdesc.virtstride</a> bytes from the top edge of the surface.&nbsp; 

+Note that this value <span class="underline">can</span> be negative, indicating that the rectangle begins before the top 

+edge of the surface.&nbsp; However, this is only allowed when a rectangle is clipped to the surface.&nbsp; If, after clipping, 

+the top edge of the rectangle is still negative, this is an error.</p>

+<p class="Code_Header_2"><a name="bvrect.width">bvrect.width</a></p>

+<p class="code_block">unsigned int width;</p>

+<p>This member indicates the width of the rectangle, measured in pixels.&nbsp; Note that this value

+<span class="underline">cannot</span> be negative.&nbsp; (Horizontal flipping is indicated using the

+<span class="inline_code"><a href="#BVFLAG_HORZ_FLIP">BVFLAG_HORZ_FLIP_*</a></span> flags.)&nbsp; The value of this member 

+may exceed the width of the associated surface.&nbsp; However, this is only allowed when a rectangle is clipped to the surface.&nbsp; 

+If, after clipping, the right edge of the rectangle still exceeds the width of the surface, this is an error.</p>

+<p class="Code_Header_2"><a name="bvrect.height">bvrect.height</a></p>

+<p class="code_block">unsigned int height;</p>

+<p>This member indicates the height of the rectangle, measured in lines of <span class="inline_code">

+<a href="#bvbuffdesc.virtstride">bvbuffdesc.virtstride</a></span> bytes.&nbsp; Note that this value

+<span class="underline">cannot</span> be negative.&nbsp; (Vertical flipping is indicated using the

+<span class="inline_code"><a href="#BVFLAG_VERT_FLIP">BVFLAG_VERT_FLIP_*</a></span> flags.)&nbsp; The value of this member 

+may exceed the width of the associated surface.&nbsp; However, this is only allowed when a rectangle is clipped to the surface.&nbsp; 

+If, after clipping, the right edge of the rectangle still exceeds the height of the surface, this is an error.</p>

+<hr />

+<a name="bvcopparams" class="Code_Header">bvcopparams</a>

+<p><span class="inline_code">bvcopparams</span> is used to define the cache operation to be performed by

+<span class="inline_code"><a href="#bv_cache">bv_cache()</a></span>.</p>

+<p class="small_code_block">struct bvcopparams {<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned int <a href="#bvcopparams.structsize">structsize</a>;<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="#bvbuffdesc">struct bvbuffdesc</a> *<a href="#bvcopparams.desc">desc</a>;<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="#bvsurfgeom">struct bvsurfgeom</a> *<a href="#bvcopparams.geom">geom</a>;<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="#bvrect">struct bvrect</a>&nbsp;&nbsp;&nbsp;&nbsp; *<a href="#bvcopparams.rect">rect</a>;<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; enum bvcacheop&nbsp; <a href="#bvcopparams.cacheop">cacheop</a>;<br />

+};</p>

+<a name="bvcopparams.structsize" class="Code_Header_2">bvcopparams.structsize</a>

+<p><span class="code_block">unsigned long structsize; /* input */</span></p>

+<p>This member is used for compatibility between BLTsville versions.&nbsp; (See <span class="inline_code">

+<a href="#bvbltparams.structsize">bvbltparams.structsize</a></span> for an explanation.) </p>

+<p class="Code_Header_2"><a name="bvcopparams.desc">bvcopparams.desc</a></p>

+<p class="code_block"><a href="#bvbuffdesc">struct bvbuffdesc</a> *desc;</p>

+<p>This member points to the <span class="inline_code"><a href="#bvbuffdesc">bvbuffdesc</a></span> of the surface for which 

+the cache is being manipulated.&nbsp; This buffer should have been mapped with a call to <span class="inline_code">

+<a href="#bv_map">bv_map()</a></span>.</p>

+<p class="note">NOTE:&nbsp; Implementations may choose to dynamically map the surface as with <span class="inline_code">

+<a href="#bv_blt">bv_blt()</a></span>, however in many systems, this will not function properly due to dynamic paging which 

+can occur when a surface is not locked.</p>

+<p><span class="Code_Header_2"><a name="bvcopparams.geom">bvcopparams.geom</a></span></p>

+<p class="code_block"><a href="#bvsurfgeom">struct bvsurfgeom</a> *geom;</p>

+<p>This member points to the <span class="inline_code"><a href="#bvsurfgeom">bvsurfgeom</a></span> of the surface for which 

+the cache is being manipulated.</p>

+<p><span class="Code_Header_2"><a name="bvcopparams.rect">bvcopparams.rect</a></span></p>

+<p class="code_block"><a href="#bvrect">struct bvrect</a> *rect;</p>

+<p>This member points to the <span class="inline_code"><a href="bvrect">bvrect</a></span> describing the rectangle of the 

+surface which is being manipulated.</p>

+<p><span class="Code_Header_2"><a name="bvcopparams.cacheop">bvcopparams.cacheop</a></span></p>

+<p class="code_block">enum bvcacheop cacheop;</p>

+<p>This member specifies the cache operation to be performed.&nbsp; It is an enumeration from the following list:</p>

+<table style="" class="indent">

+	<tr>

+		<td><span class="inline_code"><a name="BVCACHE_BIDIRECTIONAL">BVCACHE_BIDIRECTIONAL</a></span></td>

+		<td>(This usually performs a cache flush operation.)</td>

+	</tr>

+	<tr>

+		<td><span class="inline_code"><a name="BVCACHE_CPU_TO_DEVICE">BVCACHE_CPU_TO_DEVICE</a></span></td>

+		<td>Performs the appropriate cache operation to ensure data can be transferred correctly when it was written with 

+		the CPU, but will be read by the 2-D device.&nbsp; (This is usually a cache clean operation.)</td>

+	</tr>

+	<tr>

+		<td><span class="inline_code"><a name="BVCACHE_CPU_FROM_DEVICE">BVCACHE_CPU_FROM_DEVICE</a></span></td>

+		<td>Performs the appropriate cache operation to ensure data can be transferred correctly when it was written by 

+		the 2-D device, but will be read by the CPU.&nbsp; (This is usually a cache invalidate operation.)</td>

+	</tr>

+</table>

+<br />

+<hr />

+<p class="Code_Header"><a name="bvbuffdesc">bvbuffdesc</a></p>

+<p>This structure is used in conjunction with a <span class="inline_code"><a href="#bvsurfgeom">bvsurfgeom</a></span> structure 

+to specify the characteristics of a graphic surface.&nbsp; This structure specifies the memory buffer itself.</p>

+<p class="small_code_block">struct bvbuffdesc {<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned int <a href="#bvbuffdesc.structsize">structsize</a>;<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void *<a href="#bvbuffdesc.virtaddr">virtaddr</a>;<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned long <a href="#bvbuffdesc.length">length</a>;<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="#bvbuffmap">struct bvbuffmap</a> *<a href="#bvbuffdesc.map">map</a>;<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; enum bvauxtype <a href="#bvbuffdesc.auxtype">auxtype</a>;<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void *<a href="#bvbuffdesc.auxptr">auxptr</a>;<br />

+};</p>

+<p class="Code_Header_2"><a name="bvbuffdesc.structsize">bvbuffdesc.structsize</a></p>

+<p class="code_block">unsigned int structsize;</p>

+<p>This member is used for compatibility between BLTsville versions.&nbsp; (See <span class="inline_code">

+<a href="#bvbltparams.structsize">bvbltparams.structsize</a></span> for an explanation.) </p>

+<p class="Code_Header_2"><a name="bvbuffdesc.virtaddr">bvbuffdesc.virtaddr</a></p>

+<p class="code_block">void *virtaddr;</p>

+<p>This member is used to indicate the CPU virtual address of the start of the buffer.&nbsp; This value must be provided 

+unless the <span class="inline_code"><a href="#bvbuffdesc.auxtype">auxtype</a></span>/<span class="inline_code"><a href="#bvbuffdesc.auxptr">auxptr</a></span> 

+members below are used.&nbsp; At that time, this member is optional, and the <span class="inline_code">

+<a href="#auxptr">auxptr</a></span> usually has higher priority than this member.</p>

+<p class="imponly"><strong>Implementations Only</strong><br />

+<br />

+Note that this is always the beginning of the buffer.&nbsp; This means that if the <span class="inline_code">

+<a href="#bvsurfgeom.virtaddr">bvsurfgeom.virtstride</a></span> is negative, or the <a href="#bvsurfgeom.orientation">bvsurfgeom.orientation</a> 

+does not normalize to 0º&nbsp; (i.e. <span class="inline_code">orientation % 360 != 0</span>), implementations may need 

+to use a modified version of <span class="inline_code">virtaddr</span> internally to operate correctly.</p>

+<p class="Code_Header_2"><a name="bvbuffdesc.length">bvbuffdesc.length</a></p>

+<p class="code_block">unsigned long length;</p>

+<p>This member specifies the length of the buffer in bytes.</p>

+<p class="note">NOTE:&nbsp; When used with a <span class="inline_code"><a href="#bvsurfgeom">bvsurfgeom</a></span> structure,

+<span class="inline_code">length</span> should be greater than or equal to <span class="inline_code">

+<a href="#bvsurfgeom.height">bvsurfgeom.height</a> * <a href="#bvsurfgeom.virtstride">bvsurfgeom.virtstride</a></span>.</p>

+<p class="Code_Header_2"><a name="bvbuffdesc.map">bvbuffdesc.map</a></p>

+<p class="code_block">struct bvbuffmap *map;</p>

+<p>This member is used by the implementations and should <span class="underline"><strong>NEVER</strong></span> be manipulated 

+by the client.&nbsp; When the <span class="inline_code">bvbuffdesc</span> structure is created, this member should be set 

+to 0, indicating that no implementations have mapped the buffer.&nbsp; After a buffer has been mapped using a call to

+<span class="inline_code"><a href="#bv_map">bv_map()</a></span>, this member should be left as-is by clients.&nbsp; (The 

+implementation will set this back to 0 before returning from <span class="inline_code"><a href="#bv_unmap">bv_unmap()</a></span>.)</p>

+<p class="imponly"><strong>Implementations Only</strong><br />

+<br />

+This member points to a linked list of <span class="inline_code"><a href="#bvbuffmap">bvbuffmap</a></span> structures associated 

+with the buffer.&nbsp; Each <span class="inline_code"><a href="#bvbuffmap">bvbuffmap</a></span> is added to the list as 

+the buffer is mapped by a given implementation.&nbsp; This may be done with an explicit call to

+<span class="inline_code"><a href="#bv_map">bv_map()</a></span>, or implicitly with a call to <span class="inline_code">

+<a href="#bv_blt">bv_blt()</a></span>, after a call to <span class="inline_code"><a href="#bv_map">bv_map()</a></span> from 

+a different implementation.<br />

+<br />

+Implementations should not assume that the first entry in the list is their <span class="inline_code">

+<a href="#bvbuffmap">bvbuffmap</a></span>.&nbsp; Instead, implementations should compare the <span class="inline_code">

+<a href="#bv_unmap">bv_unmap()</a></span> pointer in the structure to their own function address.</p>

+<p class="Code_Header_2"><a name="bvbuffdesc.auxtype">bvbuffdesc.auxtype</a></p>

+<p class="code_block">enum bvauxtype auxtype;</p>

+<p>This member is used to identify the type of additional information about the buffer provided by

+<span class="inline_code"><a href="#bvbuffdesc.auxptr">auxptr</a></span>.&nbsp; Currently no values are defined for the 

+user mode interface, so it should be initialized to 0 or <span class="inline_code">BVAT_NONE</span>.&nbsp; See the

+<a href="#Kernel_Mode_Interface">Kernel Mode Interface</a> for details on the values defined for the kernel mode interface.</p>

+<p class="Code_Header_2"><a name="bvbuffdesc.auxptr">bvbuffdesc.auxptr</a></p>

+<p class="code_block">void *auxptr;</p>

+<p>This member is used to point to additional information about the buffer.&nbsp; The type of this pointer is determined 

+by the <span class="inline_code"><a href="#auxtype">auxtype</a></span> value.&nbsp; Currently there are no types defined 

+for the user mode interface, so this member is ignored.&nbsp; See the <a href="#Kernel_Mode_Interface">Kernel Mode Interface</a> 

+for details on the types defined for the kernel mode interface. </p>

+<hr /><br />

+<table style="" class="imponly">

+	<tr>

+		<td>

+		<p><strong>Implementations Only</strong></p>

+		<p class="Code_Header"><a name="bvbuffmap">bvbuffmap</a></p>

+		<p>This structure is used from the bvbuffdesc.map member to allow implementations to associate their own data with 

+		a buffer.</p>

+		<p class="small_code_block"><span class="small_code_block_in_table">struct bvbuffmap {<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned int <a href="#bvbuffmap.structsize">structsize</a>;<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BVFN_UNMAP <a href="#bvbuffmap.bv_unmap">bv_unmap</a>;<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned long <a href="#bvbuffmap.handle">handle</a>;<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct bvbuffmap *<a href="#bvbuffmap.nextmap">nextmap</a>;<br />

+		};</span></p>

+		<p class="Code_Header_2"><a name="bvbuffmap.structsize">bvbuffmap.structsize</a></p>

+		<p class="code_block">unsigned int structsize;</p>

+		<p>This member is used for compatibility between BLTsville versions.&nbsp; (See <span class="inline_code">

+		<a href="#bvbltparams.structsize">bvbltparams.structsize</a></span> for an explanation.) </p>

+		<p class="Code_Header_2"><a name="bvbuffmap.bv_unmap">bvbuffmap.bv_unmap</a></p>

+		<p class="code_block">BVFN_UNMAP bv_unmap;</p>

+		<p>This member holds the pointer to the <span class="inline_code"><a href="#bv_unmap">bv_unmap()</a></span> function 

+		of the implementation associated with the <span class="inline_code">bvbuffmap</span> structure.&nbsp; It serves 

+		to allow implementations to identify their <span class="inline_code">bvbuffmap</span> structure in the linked list, 

+		as well as to allow implementations to call each other&#39;s <span class="inline_code"><a href="#bv_unmap">bv_unmap()</a></span> 

+		calls from their own.</p>

+		<p class="Code_Header_2"><a name="bvbuffmap.handle">bvbuffmap.handle</a></p>

+		<p class="code_block">unsigned long handle;</p>

+		<p>This member is used to hold an implementation-specific piece of data.</p>

+		<p class="Code_Header_2"><a name="bvbuffmap.nextmap">bvbuffmap.nextmap</a></p>

+		<p class="code_block">struct bvbuffmap *nextmap;</p>

+		<p>This member holds a pointer to the next bvbuffmap structure in the linked list.&nbsp; If this member is 0, there 

+		are no more entries in the list.<br />

+		<br />

+		<span class="note">NOTE:&nbsp; The Linux/Android Kernel Mode Interface differs slightly from this structure.&nbsp; 

+		Refer to the <a href="#Kernel_Mode_Interface">Kernel Mode Interface</a> section for details.</span></p>

+		</td>

+	</tr>

+</table>

+<br />

+<hr />

+<p class="Code_Header"><a name="bvsurfgeom">bvsurfgeom</a></p>

+<p>This structure is used in conjunction with a <span class="inline_code"><a href="#bvbuffdesc">bvbuffdesc</a></span> structure 

+to specify the characteristics of a graphic surface.&nbsp; This structure specifies the surface geometric characteristics.</p>

+<p class="note">NOTE:&nbsp; This structure was separated from <span class="inline_code"><a href="#bvbuffdesc">bvbuffdesc</a></span> 

+to afford much flexibility to the client.&nbsp; Using the same <span class="inline_code"><a href="#bvbuffdesc">bvbuffdesc</a></span> 

+structure with different <span class="inline_code">bvsurfgeom</span> structures or using the same

+<span class="inline_code">bvsurfgeom</span> structure with different <span class="inline_code"><a href="#bvbuffdesc">bvbuffdesc</a></span> 

+structures may be of benefit.&nbsp; See the <a href="#bvsurfgeom_examples">examples</a> at the bottom of this section.</p>

+<p class="small_code_block">struct bvcopparams {<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned int <a href="#bvsurfgeom.structsize">structsize</a>;<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="http://graphics.github.com/ocd/">enum ocdformat</a> format;<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned int width;<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned int height;<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int orientation;<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; long virtstride;<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="http://graphics.github.com/ocd/">enum ocdformat</a> paletteformat;<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void *palette;<br />

+};</p>

+<p class="Code_Header_2"><a name="bvsurfgeom.structsize">bvsurfgeom.structsize</a></p>

+<p class="inline_code">unsigned int structsize;</p>

+<p>This member is used for compatibility between BLTsville versions.&nbsp; (See <span class="inline_code">

+<a href="#bvbltparams.structsize">bvbltparams.structsize</a></span> for an explanation.) </p>

+<p class="Code_Header_2"><a name="bvsurfgeom.format">bvsurfgeom.format</a></p>

+<p class="code_block"><a href="http://graphics.github.com/ocd/">enum ocdformat</a> format;</p>

+<p>This member specifies the format of the surface using the <a href="http://graphics.github.com/ocd">Open Color format 

+Definitions (OCD)</a>.</p>

+<p class="Code_Header_2"><a name="bvsurfgeom.width">bvsurfgeom.width</a></p>

+<p class="code_block">unsigned int width;</p>

+<p>This member specifies the width of the surface in pixels.&nbsp; This size does not have to be equivalent to the

+<span class="inline_code"><a href="#bvsurfgeom.virtstride">virtstride</a></span> size.</p>

+<p class="imponly"><strong>Implementations Only</strong><br />

+<br />

+Implementations should never assume that <span class="inline_code">width</span> is equivalent to

+<span class="inline_code"><a href="#bvsurfgeom.virtstride">virtstride</a></span>.</p>

+<p class="Code_Header_2"><a name="bvsurfgeom.height">bvsurfgeom.height</a></p>

+<p class="code_block">unsigned int height;</p>

+<p>This member specifies the height of the surface in lines of <span class="inline_code">

+<a href="#bvsurfgeom.virtstride">virtstride</a></span> width.</p>

+<p class="Code_Header_2"><a name="bvsurfgeom.orientation">bvsurfgeom.orientation</a></p>

+<p class="code_block">int orientation;</p>

+<p>This member specifies the orientation or angle of the surface in degrees.&nbsp; Since BLTsville is designed only to specify 

+orthogonal rectangles, this value must be a multiple of 90º.&nbsp; This value <span class="underline">may</span> be negative.&nbsp;

+<em>(Extending BLTsville to handle non-orthogonal rectangles may be considered if there is sufficient interest.)</em></p>

+<p class="imponly"><strong>Implementations Only</strong><br />

+<br />

+Implementations should normalize orientation angles.&nbsp; For example, a client that sets the orientation to -450º should 

+behave as if the value of 270º were specified. </p>

+<p class="Code_Header_2"><a name="bvsurfgeom.virtstride">bvsurfgeom.virtstride</a></p>

+<p class="code_block">long virtstride;</p>

+<p>This member specifies the horizontal stride of the surface in bytes for an unrotated surface.&nbsp; The stride represents 

+the number of bytes needed to move from one pixel to the pixel immediately below it.&nbsp; This value

+<span class="underline">may</span> be negative.</p>

+<p class="note">NOTE:&nbsp; This means the <span class="inline_code">orientation</span> does not affect the

+<span class="inline_code">virtstride</span>.&nbsp; However, rotating a surface usually results in a different configuration 

+(i.e. <span class="inline_code">width</span>), which <span class="underline">will</span> affect the

+<span class="inline_code">virtstride</span>.&nbsp; For example, a 320 x 240 x 32 bpp 0º surface might have a

+<span class="inline_code">virtstride</span> of 1280 bytes (320 pixels/line * 32 bits/pixel / 8 bits/byte).&nbsp; When the 

+orientation is set to 180º, the <span class="inline_code">virtstride</span> would be the same.&nbsp; But when the orientation 

+is set to 90º (or 270º), the <span class="inline_code">virtstride</span> would most likely need to be set to 960 bytes (240 

+pixels/line * 32 bits/pixel / 8 bits/byte). </p>

+<p class="imponly"><strong>Implementations Only</strong><br />

+<br />

+Implementations that do not support a negative <span class="inline_code">virtstride</span> must compensate using whatever 

+mechanism is appropriate for the implementation.&nbsp; For example, using a vertical flipping/mirroring setting.</p>

+<p class="note">NOTE:&nbsp; The <span class="inline_code">virtstride</span> name must be maintained for backwards compatibility.&nbsp; 

+However, no situation should arise where the client would need to provide two different strides for the virtual and physical 

+views of a surface (there are situations where a physical stride will need to be available within the implementation, but 

+the client will not be the one to supply it), so <em>physstride</em> will most likely never be needed.&nbsp; However, when 

+a client provides a physical description of the buffer (see the <a href="#Kernel_Mode_Interface">Kernel Mode Interface</a> 

+section below), the <span class="inline_code">virtstride</span> entry should be used to provide the physical stride.</p>

+<p class="Code_Header_2"><a name="bvsurfgeom.paletteformat">bvsurfgeom.paletteformat</a></p>

+<p class="code_block"><a href="http://graphics.github.com/ocd/">enum ocdformat</a> paletteformat;</p>

+<p>This member specifies the format of the palette supplied via the <span class="inline_code">

+<a href="#bvsurfgeom.palette">palette</a></span> member for palettized formats using the

+<a href="http://graphics.github.com/ocd">Open Color format Definitions (OCD)</a>.</p>

+<p class="Code_Header_2"><a name="bvsurfgeom.palette">bvsurfgeom.palette</a></p>

+<p class="code_block">void *palette;</p>

+<p>This member points to a palette used for palettized formats.&nbsp; The format of the palette is specified by the

+<span class="inline_code"><a href="#bvsurfgeom.palette">paletteformat</a></span> member.&nbsp; Palettes are packed based 

+on their container size:</p>

+<table class="indent">

+	<tr>

+		<td class="ctr_thin_bord"><strong>Palette Format</strong></td>

+		<td class="ctr_thin_bord"><strong>Palette Layout (byte address)</strong></td>

+		<td class="ctr_thin_bord"><strong>Palette Layout (little endian)</strong></td>

+	</tr>

+	<tr class="small_code_block_in_table">

+		<td class="thin_bord">OCDFMT_xRGB12</td>

+		<td class="ctr_thin_bord">n/a</td>

+		<td class="thin_bord">

+		<table style="width: 100%">

+			<tr>

+				<td class="thin_bord">*(((unsigned short *)palette) + 0)</td>

+				<td class="thin_bord">0xFrgb</td>

+			</tr>

+			<tr>

+				<td class="thin_bord">*(((unsigned short *)palette) + 1)</td>

+				<td class="thin_bord">0xFrgb</td>

+			</tr>

+			<tr>

+				<td class="thin_bord">...</td>

+				<td class="thin_bord">...</td>

+			</tr>

+			<tr>

+				<td class="thin_bord">*(((unsigned short *)palette) + n - 1)</td>

+				<td class="thin_bord">0xFrgb</td>

+			</tr>

+		</table>

+		</td>

+	</tr>

+	<tr class="small_code_block_in_table">

+		<td class="thin_bord">OCDFMT_RGB24</td>

+		<td class="thin_bord">

+		<table style="width: 100%">

+			<tr>

+				<td class="thin_bord">*(((unsigned char *)palette) + 0)</td>

+				<td class="thin_bord">red0</td>

+			</tr>

+			<tr>

+				<td class="thin_bord">*(((unsigned char *)palette) + 1)</td>

+				<td class="thin_bord">green0</td>

+			</tr>

+			<tr>

+				<td class="thin_bord">*(((unsigned char *)palette) + 2)</td>

+				<td class="thin_bord">blue0</td>

+			</tr>

+			<tr>

+				<td class="thin_bord">*(((unsigned char *)palette) + 3)</td>

+				<td class="thin_bord">red1</td>

+			</tr>

+			<tr>

+				<td class="thin_bord">*(((unsigned char *)palette) + 4)</td>

+				<td class="thin_bord">green1</td>

+			</tr>

+			<tr>

+				<td class="thin_bord">*(((unsigned char *)palette) + 5)</td>

+				<td class="thin_bord">blue1</td>

+			</tr>

+			<tr>

+				<td class="thin_bord">...</td>

+				<td class="thin_bord">&nbsp;</td>

+			</tr>

+			<tr>

+				<td class="thin_bord">*(((unsigned char *)palette) + (3 * n) - 3)</td>

+				<td class="thin_bord">redNm1</td>

+			</tr>

+			<tr>

+				<td class="thin_bord">*(((unsigned char *)palette) + (3 * n) - 2)</td>

+				<td class="thin_bord">greenNm1</td>

+			</tr>

+			<tr>

+				<td class="thin_bord">*(((unsigned char *)palette) + (3 * n) - 1)</td>

+				<td class="thin_bord">blueNm1</td>

+			</tr>

+		</table>

+		</td>

+		<td class="ctr_thin_bord">n/a</td>

+	</tr>

+	<tr class="small_code_block_in_table">

+		<td class="thin_bord">OCDFMT_RGBx24</td>

+		<td class="thin_bord">

+		<table style="width: 100%">

+			<tr>

+				<td class="thin_bord">*(((unsigned char *)palette) + 0)</td>

+				<td class="thin_bord">red0</td>

+			</tr>

+			<tr>

+				<td class="thin_bord">*(((unsigned char *)palette) + 1)</td>

+				<td class="thin_bord">green0</td>

+			</tr>

+			<tr>

+				<td class="thin_bord">*(((unsigned char *)palette) + 2)</td>

+				<td class="thin_bord">blue0</td>

+			</tr>

+			<tr>

+				<td class="thin_bord">*(((unsigned char *)palette) + 3)</td>

+				<td class="thin_bord">0xFF</td>

+			</tr>

+			<tr>

+				<td class="thin_bord">*(((unsigned char *)palette) + 4)</td>

+				<td class="thin_bord">red1</td>

+			</tr>

+			<tr>

+				<td class="thin_bord">*(((unsigned char *)palette) + 5)</td>

+				<td class="thin_bord">green1</td>

+			</tr>

+			<tr>

+				<td class="thin_bord">*(((unsigned char *)palette) + 6)</td>

+				<td class="thin_bord">blue1</td>

+			</tr>

+			<tr>

+				<td class="thin_bord">*(((unsigned char *)palette) + 7)</td>

+				<td class="thin_bord">0xFF</td>

+			</tr>

+			<tr>

+				<td class="thin_bord">...</td>

+				<td class="thin_bord">&nbsp;</td>

+			</tr>

+			<tr>

+				<td class="thin_bord">*(((unsigned char *)palette) + (4 * n) - 4)</td>

+				<td class="thin_bord">redNm1</td>

+			</tr>

+			<tr>

+				<td class="thin_bord">*(((unsigned char *)palette) + (4 * n) - 3)</td>

+				<td class="thin_bord">greenNm1</td>

+			</tr>

+			<tr>

+				<td class="thin_bord">*(((unsigned char *)palette) + (4 * n) - 2)</td>

+				<td class="thin_bord">blueNm1</td>

+			</tr>

+			<tr>

+				<td class="thin_bord">*(((unsigned char *)palette) + (4 * n) - 1)</td>

+				<td class="thin_bord">0xFF</td>

+			</tr>

+		</table>

+		</td>

+		<td class="thin_bord">

+		<table style="width: 100%">

+			<tr>

+				<td class="thin_bord">*(((unsigned long *)palette) + 0)</td>

+				<td class="thin_bord">0xFFbbggrr<br />

+				</td>

+			</tr>

+			<tr class="thin_bord">

+				<td class="thin_bord">&nbsp;</td>

+				<td class="thin_bord">&nbsp;</td>

+			</tr>

+			<tr class="thin_bord">

+				<td class="thin_bord">&nbsp;</td>

+				<td class="thin_bord">&nbsp;</td>

+			</tr>

+			<tr class="thin_bord">

+				<td class="thin_bord">&nbsp;</td>

+				<td class="thin_bord">&nbsp;</td>

+			</tr>

+			<tr class="thin_bord">

+				<td class="thin_bord">*(((unsigned long *)palette) + 1)<br />

+				</td>

+				<td class="thin_bord">0xFFbbggrr<br />

+				</td>

+			</tr>

+			<tr class="thin_bord">

+				<td class="thin_bord">&nbsp;</td>

+				<td class="thin_bord">&nbsp;</td>

+			</tr>

+			<tr class="thin_bord">

+				<td class="thin_bord">&nbsp;</td>

+				<td class="thin_bord">&nbsp;</td>

+			</tr>

+			<tr class="thin_bord">

+				<td class="thin_bord">&nbsp;</td>

+				<td class="thin_bord">&nbsp;</td>

+			</tr>

+			<tr class="thin_bord">

+				<td class="thin_bord">...</td>

+				<td class="thin_bord">&nbsp;</td>

+			</tr>

+			<tr class="thin_bord">

+				<td class="thin_bord">*(((unsigned long *)palette) + n - 1)|<br />

+				</td>

+				<td class="thin_bord">0xFFbbggrr<br />

+				</td>

+			</tr>

+			<tr class="thin_bord">

+				<td class="thin_bord">&nbsp;</td>

+				<td class="thin_bord">&nbsp;</td>

+			</tr>

+			<tr class="thin_bord">

+				<td class="thin_bord">&nbsp;</td>

+				<td class="thin_bord">&nbsp;</td>

+			</tr>

+			<tr class="thin_bord">

+				<td class="thin_bord">&nbsp;</td>

+				<td class="thin_bord">&nbsp;</td>

+			</tr>

+		</table>

+		</td>

+	</tr>

+</table>

+<p class="note">NOTE:&nbsp; Use of subsampled formats for <span class="inline_code">paletteformat</span> is currently undefined.</p>

+<p class="Header4"><a name="bvsurfgeom_examples">Examples</a></p>

+<p>Mixing and matching <span class="inline_code"><a href="#bvbuffdesc">bvbuffdesc</a></span> and

+<span class="inline_code">bvsurfgeom</span> structures provides maximum flexibility for a client.</p>

+<table style="width: 100%" class="example">

+	<tr>

+		<td><strong>Example:</strong>&nbsp; Using two different <span class="inline_code">bvsurfgeom</span> structures with 

+		the same <span class="inline_code"><a href="#bvbuffdesc">bvbuffdesc</a></span> structure allows in-place format 

+		conversion:</td>

+	</tr>

+	<tr>

+		<td>

+		<p class="indent"><span class="small_code_block_in_table">...<br />

+		// Convert premultiplied image to non-premultiplied in place<br />

+		struct

+		bvbltparams parms;<br />

+		...<br />

+		struct

+		bvbuffdesc buff;<br />

+		...<br />

+		struct

+		bvsurfgeom srcgeom, dstgeom;<br />

+		...<br />

+		srcgeom.format = OCDFMT_RGBA24;<br />

+		dstgeom.format = OCDFMT_nRGBA24;<br />

+		...<br />

+		parms.src1.desc = &amp;buff;<br />

+		parms.src1geom = &amp;srcgeom;<br />

+		parms.dstdesc = &amp;buff;<br />

+		parms.dstgeom = &amp;dstgeom;<br />

+		...<br />

+		bv_blt(&amp;parms);<br />

+		... </span></p>

+		</td>

+	</tr>

+</table>

+<br />

+<table style="width: 100%" class="example">

+	<tr>

+		<td><strong>Example:</strong>&nbsp; Using three different <span class="inline_code"><a href="#bvbuffdesc">bvbuffdesc</a></span> 

+		structures with the same <span class="inline_code">bvsurfgeom</span> structure reduces code and copy errors:</td>

+	</tr>

+	<tr>

+		<td>

+		<p class="indent"><span class="small_code_block_in_table">...<br />

+		// Blend two images of the same size<br />

+		struct

+		bvbltparams parms;<br />

+		...<br />

+		struct

+		bvbuffdesc src1buff, src2buff, dstbuff;<br />

+		...<br />

+		struct

+		bvsurfgeom geom;<br />

+		...<br />

+		parms.src1.desc = &amp;src1buff;<br />

+		parms.src1geom = &amp;geom;<br />

+		parms.src2.desc = &amp;src2buff;<br />

+		parms.src2geom = &amp;geom;<br />

+		parms.dstdesc = &amp;dstbuff;<br />

+		parms.dstgeom = &amp;dstgeom;<br />

+		...<br />

+		bv_blt(&amp;parms);<br />

+		... </span></p>

+		</td>

+	</tr>

+</table>

+<br />

+<hr />

+<p class="Code_Header"><a name="bvtileparams">bvtileparams</a></p>

+<p>This structure is used to define the parameters necessary to use a small image as a tile or block that will be repeated 

+when used as a source.&nbsp; This structure is used in conjunction with the associated <span class="inline_code">

+<a href="#bvsurfgeom">bvsurfgeom</a></span> and the associated <span class="inline_code"><a href="#bvrect">bvrect</a></span> 

+to determine the operation that is performed.</p>

+<p class="small_code_block">struct bvcopparams {<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned int <a href="#bvtileparams.structsize">structsize</a>;<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned long <a href="#bvtileparams.flags">flags</a>;<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void *<a href="#bvtileparams.virtaddr">virtaddr</a>;<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int <a href="#bvtileparams.dstleft">dstleft</a>;<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int <a href="#bvtileparams.dsttop">dsttop</a>;<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned int <a href="#bvtileparams.srcwidth">srcwidth</a>;<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned int <a href="#bvtileparams.srcheight">srcheight</a>;<br />

+};</p>

+<p class="Code_Header_2"><a name="bvtileparams.structsize">bvtileparams.structsize</a></p>

+<p class="code_block">unsigned int structsize;</p>

+<p>This member is used for compatibility between BLTsville versions.&nbsp; (See <span class="inline_code">

+<a href="#bvbltparams.structsize">bvbltparams.structsize</a></span> for an explanation.) </p>

+<p class="Code_Header_2"><a name="bvtileparams.flags">bvtileparams.flags</a></p>

+<p class="code_block">unsigned long flags;</p>

+<p>This member specifies some additional information for the tiling operation.&nbsp; It can be composed as the binary OR 

+of one selection for each edge (left, top, right, and bottom) from the following flags:</p>

+<table style="" class="indent">

+	<tr>

+		<td><span class="inline_code"><a name="BVTILE_LEFT_REPEAT">BVTILE_LEFT_REPEAT</a></span></td>

+		<td>indicates that the tile is repeated to the left of the destination alignment location.</td>

+	</tr>

+	<tr>

+		<td><span class="inline_code"><a name="BVTILE_TOP_REPEAT">BVTILE_TOP_REPEAT</a></span></td>

+		<td>indicates that the tile is repeated above the destination alignment location.</td>

+	</tr>

+	<tr>

+		<td><span class="inline_code"><a name="BVTILE_RIGHT_REPEAT">BVTILE_RIGHT_REPEAT</a></span></td>

+		<td>indicates that the tile is repeated to the right of the destination alignment location.</td>

+	</tr>

+	<tr>

+		<td><span class="inline_code"><a name="BVTILE_BOTTOM_REPEAT">BVTILE_BOTTOM_REPEAT</a></span></td>

+		<td>indicates that the tile is repeated below the destination alignment location.</td>

+	</tr>

+	<tr>

+		<td><a name="BVTILE_LEFT_MIRROR" class="inline_code">BVTILE_LEFT_MIRROR</a></td>

+		<td>indicates that the tile is mirrored to the left of the destination alignment location.</td>

+	</tr>

+	<tr>

+		<td><span class="inline_code"><a name="BVTILE_TOP_MIRROR">BVTILE_TOP_MIRROR</a></span></td>

+		<td>indicates that the tile is mirrored above the destination alignment location.</td>

+	</tr>

+	<tr>

+		<td><span class="inline_code"><a name="BVTILE_RIGHT_MIRROR">BVTILE_RIGHT_MIRROR</a></span></td>

+		<td>indicates that the tile is mirrored to the right of the destination alignment location.</td>

+	</tr>

+	<tr>

+		<td><span class="inline_code"><a name="BVTILE_BOTTOM_MIRROR">BVTILE_BOTTOM_MIRROR</a></span></td>

+		<td>indicates that the tile is mirrored below the destination alignment location.</td>

+	</tr>

+</table>

+<p class="Code_Header_2"><a name="bvtileparams.virtaddr">bvtileparams.virtaddr</a></p>

+<p class="code_block">void *virtaddr;</p>

+<p>This member is used to indicate the CPU virtual address of the start of the buffer.</p>

+<p class="imponly"><strong>Implementations Only</strong><br />

+<br />

+Note that this is always the beginning of the buffer.&nbsp; This means that if the <span class="inline_code">

+<a href="#bvsurfgeom.virtaddr">bvsurfgeom.virtstride</a></span> is negative, or the <a href="#bvsurfgeom.orientation">bvsurfgeom.orientation</a> 

+does not normalize to 0º&nbsp; (i.e. <span class="inline_code">orientation % 360 != 0</span>), implementations may need 

+to use a modified version of <span class="inline_code">virtaddr</span> internally to operate correctly.</p>

+<p class="Code_Header_2"><a name="bvtileparams.dstleft">bvtileparams.dstleft</a></p>

+<p class="code_block">int dstleft;</p>

+<p>This member is used to designate the left edge of the location of the tile in the destination for alignment purposes 

+(alignment location).&nbsp; Note that the <span class="inline_code"><a href="#bvrect">bvrect</a></span> of the destination 

+specifies the region which is filled by the tile.</p>

+<p class="Code_Header_2"><a name="bvtileparams.dsttop">bvtileparams.dsttop</a></p>

+<p class="code_block">int dsttop;</p>

+<p>This member is used to designate the top edge of the location of the tile in the destination for alignment purposes (alignment 

+location).&nbsp; Note that the <span class="inline_code"><a href="#bvrect">bvrect</a></span> of the destination specifies 

+the region which is filled by the tile.</p>

+<p class="Code_Header_2"><a name="bvtileparams.srcwidth">bvtileparams.srcwidth</a></p>

+<p class="code_block">unsigned int srcwidth;</p>

+<p>This member is used to designate the width of the source for purposes of scaling.&nbsp; The relationship between this 

+field and the <span class="inline_code"><a href="#bvrect.width">bvrect.width</a></span> of the associated source surface 

+determines the horizontal scaling factor.</p>

+<p class="Code_Header_2"><a name="bvtileparams.srcheight">bvtileparams.srcheight</a></p>

+<p class="code_block">unsigned int srcheight;</p>

+<p>This member is used to designate the height of the source for purposes of scaling.&nbsp; The relationship between this 

+field and the <span class="inline_code"><a href="#bvrect.height">bvrect.height</a></span> of the associated source surface 

+determines the vertical scaling factor.</p>

+<hr />

+<p class="Code_Header"><a name="bvcallbackerror">bvcallbackerror</a></p>

+<p>This structure is used to provide error information to the client of a BLT that failed within an asynchronous operation.&nbsp; 

+The errors will be limited to those that occur within the implementation.</p>

+<p class="note">NOTE:&nbsp; Parameter errors should never be returned in this structure.&nbsp; These should have been returned 

+to the client before the BLT was ever initiated.</p>

+<p class="small_code_block">struct bvcallbackerror {<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned int <a href="#bvcallbackerror.structsize">structsize</a>;<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="#bverror">enum bverror</a> <a href="#bvcallbackerror.error">error</a>;<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char *<a href="#bvcallbackerror.errdesc">errdesc</a>;<br />

+};</p>

+<p class="Code_Header_2"><a name="bvcallbackerror.structsize">bvcallbackerror.structsize</a></p>

+<p class="code_block">unsigned int structsize;</p>

+<p>This member is used for compatibility between BLTsville versions.&nbsp; (See <span class="inline_code">

+<a href="#bvbltparams.structsize">bvbltparams.structsize</a></span> for an explanation.) </p>

+<p class="Code_Header_2"><a name="bvcallbackerror.error">bvcallbackerror.error</a></p>

+<p class="code_block"><a href="#bverror">enum bverror</a> error;</p>

+<p>This member is used to indicate the error encountered.&nbsp; In general, these will be error like these:</p>

+<table class="indent">

+	<tr>

+		<td class="inline_code">BVERR_OP_FAILED</td>

+		<td>The operation failed for unspecified reasons.&nbsp; The destination buffer was not modified.</td>

+	</tr>

+	<tr>

+		<td class="inline_code">BVERR_OP_INCOMPLETE</td>

+		<td>The operation only partially completed.&nbsp; The destination buffer is in an undefined state.</td>

+	</tr>

+	<tr>

+		<td class="inline_code">BVERR_MEMORY_ERROR</td>

+		<td>The operation resulted in a memory error, most likely due to an attempt to access invalid memory.&nbsp; The 

+		destination buffer is in an undefined state.</td>

+	</tr>

+</table>

+<p class="Code_Header_2"><a name="bvcallbackerror.errdesc">bvcallbackerror.errdesc</a></p>

+<p class="code_block">char *errdesc;</p>

+<p><span class="inline_code">errdesc</span> is optionally used by implementations to pass a 0-terminated string with additional 

+debugging information back to clients for debugging purposes.&nbsp; <span class="inline_code">errdesc</span> is not localized 

+or otherwise meant to provide information that is displayed to users.</p>

+<hr />

+<p class="Header1">Batching<a name="batching"></a></p>

+<p>Batching is the single most powerful feature in BLTsville.&nbsp; It is used for two major purposes:</p>

+<ol>

+	<li>To group similar BLTs which use most of the same parameters so that they can be handled more efficiently by the 

+	implementation.</li>

+	<li>To group BLTs that should go together so that implementations can use special features that go beyond what seems 

+	to be expressed by the BLTsville API.</li>

+</ol>

+<p class="note">NOTE:&nbsp; It is important to realize that BLTs batched together may be done <span class="underline">in 

+any order</span>, and in fact may not even be done in the way specified.&nbsp; This includes the BLTs being done as they 

+are submitted, or no operations performed until the batch submission is completed with

+<a href="#BVFLAG_BATCH_END" class="inline_code">BVFLAG_BATCH_END</a>.&nbsp; This means the client must not rely on intermediate 

+results within a batch.</p>

+<p class="note">NOTE:&nbsp; Because BLTs can be performed in a variety of ways, callbacks for individual BLTs would have 

+no consistent meaning.&nbsp; So, when batching is mixed with <span class="inline_code"><a href="#BVFLAG_ASYNC">BVFLAG_ASYNC</a></span>, 

+only the callback for the last BLT occurs.</p>

+<p class="note">NOTE:&nbsp; Since implementations can perform batched BLTs in a variety of ways, even synchronous batched 

+BLTs can be effectively asynchronous.&nbsp; Therefore, only the last BLT determines the synchronicity of the entire batch.&nbsp; 

+i.e. the <span class="inline_code"><a href="#BVFLAG_ASYNC">BVFLAG_ASYNC</a></span> flag is only heeded when combined with

+<span class="inline_code"><a href="#BVFLAG_BATCH_END">BVFLAG_BATCH_END</a>.</span></p>

+<p class="note">NOTE: Failure during the performance of a batch (different from an error on submission--indicated by the 

+contents of the <a href="#bvcallbackerror" class="inline_code">bvcallbackerror</a> structure) will result in an unknown 

+state for all destination buffers.&nbsp; Do not assume that a given implementation&#39;s state in this case represents the state 

+which will be encountered for a different implementation.</p>

+<p class="note">NOTE: Because of the indeterminate nature of the execution of a batch of BLTs, a &quot;batch abort&quot; would not 

+result in a known state either.&nbsp; As stated above, a given implementation may have already performed earlier BLTs in 

+a batch as the batch is submitted.&nbsp; So errors encountered during the submission of a batch must be handled by the client, 

+and then the batch must be terminated normally using <a href="#BVFLAG_BATCH_END" class="inline_code">BVFLAG_BATCH_END</a>.</p>

+<p class="Header2">Batches For Grouping Similar BLTs</p>

+<p>Often, groups of similar BLTs are performed, with changes to only a few parameters.&nbsp; Some implementations have the 

+ability to re-use previous settings, coupled with these changes, to perform new BLTs.</p>

+<p>One good example of this in in rendering text, similar to that you are reading now.&nbsp; In most systems, a glyph cache 

+is maintained to hold the characters of a given font, rasterized with the specific characteristics desired (e.g. bold, italics, 

+etc.).&nbsp; Each font in the glyph cache is normally created using a font rasterization engine from a vector-based font, 

+such as FreeType.&nbsp; This technology allows fonts to be described in terms of curves and lines instead of pixels, which 

+means they can be created as needed, in any size desirable.</p>

+<table style="" class="glyph_cache">

+	<tr>

+		<td class="glyph_cache">&nbsp; !&quot;#$%&amp;&#39;()*+&#39;-./0123456789:;&lt;=&gt;?<br />

+		@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_<br />

+		`abcdefghijklmnopqrstuvwxyz{|}~</td>

+	</tr>

+</table>

+<p>Then, when a character needs to be rendered, it is copied from the pre-rendered glyph cache.&nbsp; This is much more 

+efficient than performing the font rasterization from the vector description each time a character is used.</p>

+<p>With some hardware implementations, the setup to trigger the copy of these characters from the glyph cache to the target 

+surface can be quite significant, when compared to the number of pixels actually affected.&nbsp; For example, each character 

+might consist of something on the order of&nbsp; 10 x 14, or about 140 pixels.&nbsp; Programming a typical hardware BLTer 

+may require tens of commands for each character.</p>

+<p>But note that each of these BLTs differs by only a few parameters.&nbsp; Specifically, once the source and destination 

+surfaces have been specified, and the operation described, only the source and destination rectangles change between BLTs. 

+To alleviate much of this overhead, most implementations will allow the configuration of a previous BLT to be used again, 

+with only those parameters which change provided for the subsequent BLTs.</p>

+<p>BLTsville provides access to this capability via the batch mechanism.</p>

+<p>For rendering a word using a monospaced font like this, the client might construct the batch like this:</p>

+<p class="small_code_block">struct bvbuffdesc screendesc = {sizeof(struct bvbuffdesc}, 0};<br />

+struct bvsurfgeom screengeom = {sizeof(struct bvsurfgeom), 0};<br />

+struct bvbuffdesc glyphcachedesc = {sizeof(struct bvbuffdesc), 0};<br />

+struct bvsurfgeom glyphcachegeom = {sizeof(struct bvsurfgeom), 0};<br />

+struct bvtileparams solidcolortileparams = {sizeof(struct bvtileparams), 0};<br />

+struct bvbuffgeom solidcolorgeom = {sizeof(struct bvsurfgeom), 0};<br />

+<br />

+struct bvbltparams bltparams = {sizeof(struct bvbltparams), 0};<br />

+<br />

+int charsperline = 32;<br />

+int fontwidth = 10;<br />

+int fontheight = 14;<br />

+int i = 0;<br />

+<br />

+screendesc.virtaddr = screenaddr;<br />

+screendesc.length = screenstride * screenheight;<br />

+screengeom.format = OCDFMT_RGB24;<br />

+screengeom.width = screenwidth;<br />

+screengeom.height = screenheight;<br />

+screengeom.virtstride = screenstride;<br />

+<br />

+glyphcachedesc.virtaddr = glyphcacheaddr;<br />

+glyphcachedesc.length = glyphcachestride * glyphcacheheight;<br />

+glyphcachegeom.format = OCDFMT_ALPHA8;<br />

+glyphcachegeom.width = glyphcachewidth;<br />

+glyphcachegeom.height = glyphcacheheight;<br />

+glyphcachegeom.virtstride = glyphstride;<br />

+<br />

+solidcolortileparams.virtaddr = &amp;solidcolor;<br />

+solidcolortileparams.srcwidth = 1;<br />

+solidcolortileparams.srcheight = 1;<br />

+solidcolorgeom.format = OCDFMT_RGB24;<br />

+<br />

+bltparams.flags = BVFLAG_BLEND | BVFLAG_SRC1_TILED | BVFLAG_BATCH_BEGIN;<br />

+bltparams.op.blend = BVBLEND_SRCOVER + BVBLENDDEF_REMOTE;<br />

+bltparams.dstdesc = &amp;screendesc;<br />

+bltparams.dstgeom = &amp;screengeom;<br />

+bltparams.src1.tileparams = &amp;solidcolortileparams;<br />

+bltparams.src1geom = &amp;solidcolorgeom;<br />

+bltparams.src2.desc = &amp;screendesc;<br />

+bltparams.src2geom = &amp;screengeom;<br />

+bltparams.mask.desc = &amp;glyphcachedesc;<br />

+bltparams.maskgeom = &amp;glyphcachegeom;<br />

+<br />

+bltparams.dstrect.left = bltparams.src2rect.left = screenrect.left;<br />

+bltparams.dstrect.top = bltparams.src2rect.top = screenrect.top;<br />

+<br />

+bltparams.maskrect.width = bltparams.dstrect.width = bltparams.src2rect.width = fontwidth;<br />

+bltparams.maskrect.height = bltparams.dstrect.height = bltparams.src2rect.height = fontheight;<br />

+<br />

+bltparams.maskrect.left = ((text[i] - &#39; &#39;) % charsperline) * fontwidth;<br />

+bltparams.maskrect.top = ((text[i] - &#39; &#39;) / charsperline) * fontheight;<br />

+<br />

+bv_blt(&amp;bltparams);<br />

+<br />

+i++;<br />

+if(i &lt; textlen)<br />

+{<br />

+&nbsp; bltparams.flags = (bltparams.flags &amp; ~BVFLAG_BATCH_MASK) | BVFLAG_BATCH_CONTINUE;<br />

+&nbsp; bltparams.batchflags = BVBATCH_DSTRECT_ORIGIN | BVBATCH_SRC2RECT_ORIGIN | BVBATCH_MASKRECT_ORIGIN;<br />

+<br />

+&nbsp; do<br />

+&nbsp; {<br />

+&nbsp;&nbsp;&nbsp; bltparams.dstrect.left += fontwidth;<br />

+&nbsp;&nbsp;&nbsp; bltparams.src2rect.left = bltparams.dstrect.left;<br />

+<br />

+&nbsp;&nbsp;&nbsp; bltparams.maskrect.left = ((text[i] - &#39; &#39;) % charsperline) * fontwidth;<br />

+&nbsp;&nbsp;&nbsp; bltparams.maskrect.top = ((text[i] - &#39; &#39;) / charsperline) * fontheight;<br />

+<br />

+&nbsp;&nbsp;&nbsp; bv_blt(&amp;bltparams);<br />

+<br />

+&nbsp;&nbsp;&nbsp; i++;<br />

+&nbsp; }while(i &lt; textlen);<br />

+}<br />

+<br />

+bltparams.flags = (bltparams.flags &amp; ~BVFLAG_BATCH_MASK) | BVFLAG_BATCH_END;<br />

+bltparams.batchflags = BVBATCH_ENDNOP;<br />

+<br />

+bv_blt(&amp;bltparams);</p>

+<p class="note">NOTE:&nbsp; bvbltparams.batchflags is just a hit.&nbsp; Not all implementations support deltas in 

+batching, so clients must not change the values of members of <span class="inline_code"><a href="#bvbltparams">

+bvbltparams</a></span> (or structures it 

+references) between BLTs.&nbsp; These values may be used.</p>

+<p class="Header2">Batches For Special Feature BLTs</p>

+<p>Enabling special features of some implementations is a special challenge.&nbsp; But BLTsville is up the task.</p>

+<p>For example, perhaps an implementation is capable of blending four layers at the same time.&nbsp; But BLTsville only allows 

+blending to be specified using two layers at a time.&nbsp; How can this be accomplished?</p>

+<p>The most prevalent blending reference used is the <a href="http://dx.doi.org/10.1145/800031.808606">Porter-Duff 

+whitepaper</a>, which specifies blending of two sources (A and B).&nbsp; So any N-source blend (N &gt; 2) would require the blends to be 

+specified as a grouping of N - 1 two-source blends in order to utilize the 

+Porter-Duff equations.&nbsp; That&#39;s how such a blend is specified in BLTsville:</p>

+<p class="small_code_block">bltparams.dstrect.width = bltparams.src1rect.width = bltparams.src2rect.width = dstgeom.width;<br />

+bltparams.dstrect.height = bltparams.src1rect.height = bltparams.src2rect.height = dstgeom.height; <br />

+<br />

+bltparams.flags = BVFLAG_BLEND | BVFLAG_BATCH_BEGIN;<br />

+bltparams.op.blend = BVBLEND_SRCOVER;<br />

+bltparams.dstdesc = &amp;dstdesc;<br />

+bltparams.dstgeom = &amp;dstgeom;<br />

+bltparams.src1.desc = &amp;src1desc;<br />

+bltparams.src1geom = &amp;src1geom;<br />

+bltparams.src2.desc = &amp;src2desc;<br />

+bltparams.src2geom = &amp;src2geom;<br />

+<br />

+bv_blt(&amp;bltparams);<br />

+<br />

+bltparams.src1.desc = &amp;src3desc;<br />

+bltparams.src1geom = &amp;src3geom;<br />

+bltparams.dstdesc = &amp;dstdesc;<br />

+bltparams.dstgeom = &amp;dstgeom;<br />

+<br />

+bltparams.flags = (bltparams.flags &amp; ~BVFLAG_BATCH_MASK) | BVFLAG_BATCH_CONTINUE;<br />

+bltparams.batch = BVBATCH_SRC1 | BVBATCH_SRC2;<br />

+<br />

+bv_blt(&amp;bltparams);<br />

+<br />

+bltparams.src1.desc = &amp;src4desc;<br />

+bltparams.src1geom = &amp;src4geom;<br />

+<br />

+bltparams.flags = (bltparams.flags &amp; ~BVFLAG_BATCH_MASK) | BVFLAG_BATCH_END;<br />

+bltparams.batch = BVBATCH_SRC1;<br />

+<br />

+bv_blt(&amp;bltparams);</p>

+<p>The driver for an implementation that can perform this pair of operations as one BLT would be tasked with recognizing 

+that the batch contained BLTs which can be combined.</p>

+<p>The fantastic thing about this approach is that an implementation without the ability to blend N sources in one pass would perform 

+the blends separately, but the result would be identical.&nbsp; Moreover, implementations with the ability to combine 

+different numbers of operations would likewise produce the same results, even they they used a different number of 

+internal steps.&nbsp; Here&#39;s an example:</p>

+<table align="center">

+	<tr>

+		<td>

+<table>

+	<tr>

+		<td class="ctr_thin_bord"><strong>Number of<br />

+		Layers to<br />

+		Blend</strong></td>

+		<td class="ctr_thin_bord"><strong>BLTsville<br />

+		Operations</strong></td>

+		<td class="ctr_thin_bord"><strong>Implementation<br />

+		Capable of<br />

+		Blending One<br />

+		Source with a<br />

+		Destination</strong><br />

+				(2 inputs)</td>

+		<td class="ctr_thin_bord"><strong>Implementation<br />

+		Capable of<br />

+		Blending Two<br />

+		Sources to a<br />

+		Destination</strong><br />

+				(2 inputs)</td>

+		<td class="ctr_thin_bord"><strong>Implementation<br />

+		Capable of<br />

+		Blending Four<br />

+		Sources to a<br />

+		Destination</strong><br />

+				(4 inputs)</td>

+		<td class="ctr_thin_bord"><strong>Implementation<br />

+		Capable of<br />

+		Blending Eight<br />

+		Sources with<br />

+		a Destination</strong><br />

+		(5 inputs)</td>

+	</tr>

+	<tr>

+		<td class="ctr_thin_bord">2</td>

+		<td class="nowrap">A over B =&gt; O</td>

+		<td class="nowrap">B =&gt; O<br />

+		A over O =&gt; O</td>

+		<td class="nowrap">A over B =&gt; O</td>

+		<td class="nowrap">A over B =&gt; O</td>

+		<td class="nowrap">A over B =&gt; O</td>

+	</tr>

+	<tr>

+		<td class="ctr_thin_bord">3</td>

+		<td class="nowrap">B over C =&gt; O<br />

+		A over O =&gt; O</td>

+		<td class="nowrap">C =&gt; O<br />

+		B over O =&gt; O<br />

+		A over O =&gt; O</td>

+		<td class="nowrap">B over C =&gt; O<br />

+		A over O =&gt; O</td>

+		<td class="nowrap">A over B over C =&gt; O</td>

+		<td class="nowrap">A over B over C =&gt; O</td>

+	</tr>

+	<tr>

+		<td class="ctr_thin_bord">4</td>

+		<td class="nowrap">C over D =&gt; O<br />

+		B over O =&gt; O<br />

+		A over O =&gt; O</td>

+		<td class="nowrap">D =&gt; O<br />

+		C over O =&gt; O<br />

+		B over O =&gt; O<br />

+		A over O =&gt; O</td>

+		<td class="nowrap"> C over D =&gt; O<br />

+		B over O =&gt; O<br />

+		A over O =&gt; O</td>

+		<td class="nowrap"> A over B over C over D =&gt; O</td>

+		<td class="nowrap"> A over B over C over D =&gt; O</td>

+	</tr>

+	<tr>

+		<td class="ctr_thin_bord">5</td>

+		<td class="nowrap">D over E =&gt; O<br />

+		C over O =&gt; O<br />

+		B over O =&gt; O<br />

+		A over O =&gt; O</td>

+		<td class="nowrap">E =&gt; O<br />

+		D over O =&gt; O<br />

+		C over O =&gt; O<br />

+		B over O =&gt; O<br />

+		A over O =&gt; O</td>

+		<td class="nowrap">D over E =&gt; O<br />

+		C over O =&gt; O<br />

+		B over O =&gt; O<br />

+		A over O =&gt; O</td>

+		<td class="nowrap">D over E =&gt; O<br />

+		A over B over C over O =&gt; O</td>

+		<td class="nowrap">E =&gt; O<br />

+		A over B over C over D over O =&gt; O</td>

+	</tr>

+	<tr>

+		<td class="ctr_thin_bord">6</td>

+		<td class="nowrap">E over F =&gt; O<br />

+		D over O =&gt; O<br />

+		C over O =&gt; O<br />

+		B over O =&gt; O<br />

+		A over O =&gt; O</td>

+		<td class="nowrap">F =&gt; O<br />

+		E over O =&gt; O<br />

+		D over O =&gt; O<br />

+		C over O =&gt; O<br />

+		B over O =&gt; O<br />

+		A over O =&gt; O</td>

+		<td class="nowrap">E over F =&gt; O<br />

+		D over O =&gt; O<br />

+		C over O =&gt; O<br />

+		B over O =&gt; O<br />

+		A over O =&gt; O</td>

+		<td class="nowrap">D over E over F =&gt; O<br />

+		A over B over C over O =&gt; O</td>

+		<td class="nowrap">E over F =&gt; O<br />

+		A over B over C over D over O =&gt; O</td>

+	</tr>

+	<tr>

+		<td class="ctr_thin_bord">7</td>

+		<td class="nowrap">F over G =&gt; O<br />

+		E over O =&gt; O<br />

+		D over O =&gt; O<br />

+		C over O =&gt; O<br />

+		B over O =&gt; O<br />

+		A over O =&gt; O</td>

+		<td class="nowrap">G =&gt; O<br />

+		F over O =&gt; O<br />

+		E over O =&gt; O<br />

+		D over O =&gt; O<br />

+		C over O =&gt; O<br />

+		B over O =&gt; O<br />

+		A over O =&gt; O</td>

+		<td class="nowrap">F over G =&gt; O<br />

+		E over O =&gt; O<br />

+		D over O =&gt; O<br />

+		C over O =&gt; O<br />

+		B over O =&gt; O<br />

+		A over O =&gt; O</td>

+		<td class="nowrap">D over E over F over G =&gt; O<br />

+		A over B over C over O =&gt; O</td>

+		<td class="nowrap">E over F over G =&gt; O<br />

+		A over B over C over D over O =&gt; O</td>

+	</tr>

+	<tr>

+		<td class="ctr_thin_bord">8</td>

+		<td class="nowrap">G over H =&gt; O<br />

+		F over O =&gt; O<br />

+		E over O =&gt; O<br />

+		D over O =&gt; O<br />

+		C over O =&gt; O<br />

+		B over O =&gt; O<br />

+		A over O =&gt; O</td>

+		<td class="nowrap">H =&gt; O<br />

+		G over O =&gt; O<br />

+		F over O =&gt; O<br />

+		E over O =&gt; O<br />

+		D over O =&gt; O<br />

+		C over O =&gt; O<br />

+		B over O =&gt; O<br />

+		A over O =&gt; O</td>

+		<td class="nowrap">G over H =&gt; O<br />

+		F over O =&gt; O<br />

+		E over O =&gt; O<br />

+		D over O =&gt; O<br />

+		C over O =&gt; O<br />

+		B over O =&gt; O<br />

+		A over O =&gt; O</td>

+		<td class="nowrap">G over H =&gt; O<br />

+		D over E over F over O =&gt; O<br />

+		A over B over C over O =&gt; O</td>

+		<td class="nowrap">E over F over G over H =&gt; O<br />

+		A over B over C over D over O =&gt; O</td>

+	</tr>

+	<tr>

+		<td class="ctr_thin_bord">9</td>

+		<td class="nowrap">H over I =&gt; O<br />

+		G over O =&gt; O<br />

+		F over O =&gt; O<br />

+		E over O =&gt; O<br />

+		D over O =&gt; O<br />

+		C over O =&gt; O<br />

+		B over O =&gt; O<br />

+		A over O =&gt; O</td>

+		<td class="nowrap">I =&gt; O<br />

+		H over O =&gt; O<br />

+		G over O =&gt; O<br />

+		F over O =&gt; O<br />

+		E over O =&gt; O<br />

+		D over O =&gt; O<br />

+		C over O =&gt; O<br />

+		B over O =&gt; O<br />

+		A over O =&gt; O</td>

+		<td class="nowrap">H over I =&gt; O<br />

+		G over O =&gt; O<br />

+		F over O =&gt; O<br />

+		E over O =&gt; O<br />

+		D over O =&gt; O<br />

+		C over O =&gt; O<br />

+		B over O =&gt; O<br />

+		A over O =&gt; O</td>

+		<td class="nowrap">G over H over I =&gt; O<br />

+		D over E over F over O =&gt; O<br />

+		A over B over C over O =&gt; O</td>

+		<td class="nowrap">I =&gt; O<br />

+		E over F over G over H over O =&gt; O<br />

+		A over B over C over D over O =&gt; O</td>

+	</tr>

+</table>

+</td>

+	</tr>

+	<tr>

+		<td class="ctr">Comparison of batched BLTsville calls with internal operations, based on implementation capabilities.

+</td>

+	</tr>

+</table>

+<p class="note">NOTE: As mentioned above a batch of BLTs may be serviced in any number of ways.&nbsp; In this example, the 

+destination buffer may be used for intermediate results, so it is important that this buffer not be used during the batch--i.e. 

+as a displayed buffer.</p>

+<hr />

+<p class="Header1"><a name="start">Where to Start</a></p>

+<p><em>(Note that error checking is omitted in all the examples below for clarity.)</em> </p>

+<p>1.&nbsp; Clients begin by opening one or more BLTsville implementations dynamically.&nbsp; The specific method of doing 

+this is dependent on the operating system.&nbsp; For example, Linux might do this like this:</p>

+<p class="small_code_block">struct bltsvillelib<br />

+{<br />

+&nbsp; char* name;<br />

+&nbsp; void* handle;<br />

+&nbsp; BVFN_MAP bv_map;<br />

+&nbsp; BVFN_BLT bv_blt;<br />

+&nbsp; BVFN_UNMAP bv_unmap;<br />

+}; <br />

+<br />

+struct bltsville bvlib[] =<br />

+{<br />

+&nbsp; { &quot;libbltsville_cpu.so&quot;, 0 },<br />

+&nbsp; { &quot;libbltsville_2d.so&quot;, 0 }<br />

+};<br />

+const int NUMBVLIBS = sizeof(bvlib) / sizeof(struct bltsvillelib);<br />

+<br />

+for(int i = 0; i &lt; NUMLIBS; i++)<br />

+{<br />

+&nbsp; bvlib[i].handle = dlopen(bvlib[i].name, RTLD_LOCAL | RTLD_LAZY);<br />

+&nbsp; bvlib[i].bv_map = (BVFN_MAP)dlsym(bvlib[i].handle, &quot;bv_map&quot;);<br />

+&nbsp; bvlib[i].bv_blt = (BVFN_BLT)dlsym(bvlib[i].handle, &quot;bv_blt&quot;);<br />

+&nbsp; bvlib[i].bv_unmap = (BVFN_BLT)dlsym(bvlib[i].handle, &quot;bv_unmap&quot;);<br />

+}<br />

+</p>

+<p>2.&nbsp; Clients then need to create a <span class="inline_code"><a href="#bvbuffdesc">bvbuffdesc</a></span> object for 

+each buffer to be accessed in BLTsville:</p>

+<table class="indent">

+	<tr>

+		<td valign="top">

+		<p class="small_code_block_in_table">struct bvbuffdesc buff =<br />

+&nbsp; {sizeof(struct bvbuffdesc), 0};<br />

+		<br />

+		buff.virtaddr = buffptr;<br />

+		buff.length = bufflength;</p>

+		</td>

+		<td class="ctr">&nbsp;or&nbsp</td>

+		<td valign="top">

+		<p class="inline_code"><span class="small_code_block_in_table">struct bvbuffdesc buff;<br />

+		<br />

+		memset(&amp;buff, 0, sizeof(buff));<br />

+		buff.structsize = sizeof(buff);<br />

+		buff.virtaddr = buffptr;<br />

+		buff.length = bufflength;</span></p>

+		</td>

+	</tr>

+</table>

+<p class="strong_emphasis">Note that the client must ensure that the map element and any additional members in

+<span class="inline_code"><a href="#bvbuffdesc">bvbuffdesc</a></span> are initialized to 0.</p>

+<p>3.&nbsp; Next the buffer can be mapped to give the hardware implementations a chance to associate any necessary resources 

+with the buffer:</p>

+<table class="indent">

+	<tr>

+		<td valign="top">

+		<p class="small_code_block_in_table">/* do nothing */ </p>

+		</td>

+		<td class="ctr">&nbsp;or&nbsp;</td>

+		<td valign="top">

+		<p class="small_code_block_in_table">bvlib[0].bv_map(&amp;buff); </p>

+		</td>

+		<td class="ctr">&nbsp;or&nbsp;</td>

+		<td valign="top">

+		<p class="small_code_block_in_table">for(int i = 0; i &lt; NUMLIBS; i++)<br />

+		{<br />

+&nbsp; if(bvlib[i].bv_map)<br />

+&nbsp;&nbsp;&nbsp; bvlib[i].bv_map(&amp;buff);<br />

+		}</p>

+		</td>

+	</tr>

+</table>

+<br />

+<table style="width: 100%">

+	<tr>

+		<td valign="top">a. </td>

+		<td>This step is actually optional, as indicated above.&nbsp; However, if the client does not explicitly call

+		<span class="inline_code"><a href="#bv_map">bv_map()</a></span>, the mapping must be done by the implementation 

+		to associate the necessary resources with the buffer.&nbsp; So this mapping must be done later, when

+		<span class="inline_code"><a href="#bv_blt">bv_blt()</a></span> is called.&nbsp; Additionally, since the client 

+		did not call <span class="inline_code"><a href="#bv_map">bv_map()</a></span>, it is unlikely that the client will 

+		call <span class="inline_code"><a href="#bv_unmap">bv_unmap()</a></span> to allow the implementation to free the 

+		resources associated with the buffer.&nbsp; So the implementation will internally unmap the resources after completing 

+		the BLT.&nbsp; This means that the mapping and unmapping overhead will be encountered on every call to

+		<span class="inline_code"><a href="#bv_blt">bv_blt()</a></span>.<br />

+		<em><br />

+		In general, the CPU implementations have (almost) no overhead associated with mapping and unmapping.&nbsp; So opting 

+		not to make the <span class="inline_code"><a href="#bv_map">bv_map()</a></span> call for CPU implementations is 

+		likely to have negligible difference in <span class="inline_code"><a href="#bv_blt">bv_blt()</a></span> performance.<br />

+		</em></td>

+	</tr>

+	<tr>

+		<td valign="top">b. </td>

+		<td>Calling <span class="inline_code"><a href="#bv_map">bv_map()</a></span> once for each buffer is enough to tell 

+		the implementations that the client can be trusted to call <span class="inline_code"><a href="#bv_unmap">bv_unmap()</a></span> 

+		when work with the buffer is complete, as indicated above.&nbsp; It does not matter which implementation&#39;s

+		<span class="inline_code"><a href="#bv_map">bv_map()</a></span> is called.&nbsp; However, that implementation is 

+		the only one which will perform the mapping immediately.&nbsp; All other implementations will perform a <em>lazy 

+		mapping</em> only when their <span class="inline_code"><a href="#bv_blt">bv_blt()</a></span> call is invoked.<br />

+		<br />

+		This allows the client to avoid the overhead of mapping and unmapping the buffers on each

+		<span class="inline_code"><a href="#bv_blt">bv_blt()</a></span> call.&nbsp; It also avoids the associated mapping 

+		and unmapping overhead if a given implementation is never used.<br />

+		<br />

+		<em>As mentioned above, the CPU implementations have (almost) no overhead associated with mapping and unmapping, 

+		so they are a good choice to use for the call to <span class="inline_code"><a href="#bv_map">bv_map()</a></span>.<br />

+		</em></td>

+	</tr>

+	<tr>

+		<td valign="top">c. </td>

+		<td>If the client wants direct control over the mapping and unmapping overhead, it can call the

+		<span class="inline_code"><a href="#bv_map">bv_map()</a></span> function of each implementation, as indicated above.&nbsp; 

+		Each implementation will perform the mapping at that time, so that the overhead will not appear on subsequent calls 

+		to <span class="inline_code"><a href="#bv_blt">bv_blt()</a></span>. </td>

+	</tr>

+</table>

+<p>4.&nbsp; Next the client must create <span class="inline_code"><a href="#bvsurfgeom">bvsurfgeom</a></span> objects for 

+each way in which a buffer will be accessed.&nbsp; Often, there is only one way in which a buffer is accessed, so there 

+will be the same number of buffers, <span class="inline_code"><a href="#bvbuffdesc">bvbuffdesc</a></span>, and

+<span class="inline_code"><a href="#bvsurfgeom">bvsurfgeom</a></span> objects.&nbsp; If that&#39;s the case, it may be convenient 

+for the client to combine them into a parent structure.&nbsp; It may even be possible to share a single bvbuffgeom structure 

+among buffers.&nbsp; Or there will be times when it is necessary to treat a buffer in different ways for different BLTs.&nbsp; 

+Having these two structures separated allows all of these combinations.</p>

+<table class="indent">

+	<tr>

+		<td valign="top">

+		<p class="small_code_block_in_table">struct bvsurfgeom geom =<br />

+&nbsp; {sizeof(struct bvsurfgeom), 0};<br />

+		<br />

+		geom.format = OCDFMT_RGB24;<br />

+		geom.width = width;<br />

+		geom.height = height;<br />

+		geom.virtstride = stride;</p>

+		</td>

+		<td class="ctr">&nbsp;or&nbsp;</td>

+		<td valign="top">

+		<p class="inline_code"><span class="small_code_block_in_table">struct bvsurfgeom geom;

+		<br />

+		memset(&amp;geom, 0, sizeof(geom));<br />

+		geom.structsize = sizeof(geom);<br />

+		geom.width = width;<br />

+		geom.height = height;<br />

+		geom.virtstride = stride;</span></p>

+		</td>

+	</tr>

+</table>

+<p class="strong_emphasis">Note that the client must ensure that any additional members in <span class="inline_code">

+<a href="#bvsurfgeom">bvsurfgeom</a></span> are initialized to 0 for future compatibility.</p>

+<p>5.&nbsp; Now the client is ready to fill in a bvbltparams structure to specify the type of BLT requested.&nbsp; Here 

+is an example of a simple copy from the lower right corner of a surface to the upper left:</p>

+<p class="small_code_block">struct bvbltparams bltparams = {sizeof(struct bvbltparams), 0};<br />

+<br />

+bltparams.flags = BVFLAG_ROP;<br />

+bltparams.op.rop = 0xCCCC; /* SRCCOPY */<br />

+bltparams.dstdesc = &amp;buff;<br />

+bltparams.dstgeom = &amp;geom;<br />

+bltparams.dstrect.left = 0;<br />

+bltparams.dstrect.top = 0;<br />

+bltparams.dstwidth = width / 2;<br />

+bltparams.dstheight = height / 2;<br />

+bltparams.src1.desc = &amp;buff;<br />

+bltparams.src1geom = &amp;geom;<br />

+bltparams.src1rect.left = width / 2;<br />

+bltparams.src1rect.top = height / 2;<br />

+bltparams.src1rect.width = width / 2;<br />

+bltparams.src1rect.height = height / 2;</p>

+<p>6.&nbsp; And next the client can trigger the BLT by calling <span class="inline_code"><a href="#bv_blt">bv_blt()</a></span>:</p>

+<p class="small_code_block">bv_blt(&amp;bltparams); </p>

+<p><em>If the client cannot complete the requested BLT, it returns a </em><span class="inline_code"><a href="#bverror">

+<em>bverror</em></a></span><em> indicating the issue. </em></p>

+<p>7.&nbsp; Finally, the client should clean up:</p>

+<p class="small_code_block">bv_unmap(&amp;buff); </p>

+<hr />

+<p class="Header1"><a name="Kernel_Mode_Interface">Kernel Mode Interface</a></p>

+<p>The kernel mode interface differs only slightly from the user mode interface.&nbsp; Currently there are two differences 

+in the general kernel interface, and one in the Linux/Android interface:</p>

+<p class="Code_Header_2">bvbuffdesc.auxtype/auxptr</p>

+<p><span class="inline_code"><a href="#bvbuffdesc.auxtype">bvbuffdesc.auxtype</a></span> is an <span class="inline_code">enum</span>, 

+indicating the type of the

+<span class="inline_code"><a href="#bvbuffdesc.auxptr">bvbuffdesc.auxptr</a></span>.&nbsp; The enumeration values and 

+the associated types are:</p>

+<table class="indent_thick_bord">

+	<tr>

+		<td class="thin_bord_dbl_botbord"><span class="inline_code"><a href="#bvbuffdesc.auxtype">bvbuffdesc.auxtype</a></span></td>

+		<td class="thin_bord_dbl_botbord">

+<span class="inline_code"><a href="#bvbuffdesc.auxptr">bvbuffdesc.auxptr</a></span> type</td>

+		<td class="thin_bord_dbl_botbord">Notes</td>

+	</tr>

+	<tr>

+		<td class="thin_bord"><span class="inline_code"><a name="BVAT_PHYSDESC">BVAT_PHYSDESC</a></span></td>

+		<td class="thin_bord">

+<a href="#bvphysdesc" class="inline_code">bvphysdesc</a></td>

+		<td class="thin_bord">Used to specify the physical pages of a physically discontiguous buffer constructed using 

+		a single page size.&nbsp; This may be used with physically contiguous buffers as well, but

+		<span class="inline_code"><a href="#BVAT_PHYSADDR">BVAT_PHYSADDR</a></span> is preferred.</td>

+	</tr>

+	<tr>

+		<td class="thin_bord"><span class="inline_code"><a name="BVAT_PHYSADDR">BVAT_PHYSADDR</a></span></td>

+		<td class="thin_bord">physical address</td>

+		<td class="thin_bord">Used to specify the starting physical address of a physically contiguous buffer.</td>

+	</tr>

+</table>

+<p>The methods of describing the buffer using physical addresses is not exposed in user mode for security reasons.</p>

+<hr />

+<p class="Code_Header"><a name="bvphysdesc">bvphysdesc</a></p>

+<p class="small_code_block">struct bvphysdesc {<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned int <a href="#bvphysdesc.structsize">structsize</a>;<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned long <a href="#bvphysdesc.pagesize">pagesize</a>;<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned long *<a href="#bvphysdesc.pagearray">pagearray</a>;<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned int <a href="#bvphysdesc.pagecount">pagecount</a>;<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned long <a href="#bvphysdesc.pageoffset">pageoffset</a>;<br />

+};</p>

+<p class="Code_Header_2"><a name="bvphysdesc.structsize">bvphysdesc.structsize</a></p>

+<p class="code_block">unsigned int structsize;</p>

+<p>This member is used for compatibility between BLTsville versions.&nbsp; (See <span class="inline_code">

+<a href="#bvbltparams.structsize">bvbltparams.structsize</a></span> for an explanation.) </p>

+<p class="Code_Header_2"><a name="bvphysdesc.pagesize">bvphysdesc.pagesize</a></p>

+<p class="code_block">unsigned long pagesize;</p>

+<p>This member indicates the size of the physical pages containing the buffer.&nbsp; <span class="inline_code">BVAT_PHYSDESC</span>/<span class="inline_code">bvphysdesc

+</span>does not support buffers which reside in pages that are not all the same size.&nbsp; <span class="inline_code">

+bvphysdesc.pagesize</span> is used to indicate the length of the pages in the <span class="inline_code">

+<a href="#bvphysdesc.pagearray">bvphysdesc.pagearray</a></span> as well as the expected alignment of those pages.&nbsp; If this value is 0, the default 

+page size of the system is assumed.</p>

+<p class="note">NOTE:&nbsp; When used with physically contiguous buffers, this member should be set to the length of the 

+buffer, which is the same as the value in <span class="inline_code"><a href="#bvbuffdesc.length">bvbuffdesc.length</a></span>.</p>

+<p class="Code_Header_2"><a name="bvphysdesc.pagearray">bvphysdesc.pagearray</a></p>

+<p class="code_block">unsigned long *pagearray;</p>

+<p>This member is an array of <span class="inline_code">unsigned long</span>s holding the physical addresses of the pages 

+holding the buffer.&nbsp; The array contains <span class="inline_code"><a href="#bvphysdesc.pagecount">pagecount</a></span> 

+entries.&nbsp; The specific format of the physical addresses is O/S dependent.&nbsp; However, <span class="inline_code">

+BVAT_PHYSDESC</span>/<span class="inline_code">bvphysdesc</span> only supports 32-bit physical addresses.</p>

+<p>Addresses in this array must be aligned on <span class="inline_code"><a href="#bvphysdesc.pagesize">

+bvphysdesc.pagesize</a></span> boundaries.&nbsp; Use the <span class="inline_code"><a href="#bvphysdesc.pageoffset">

+bvphysdesc.pageoffset</a></span> member to indicate the offset from the start of the first page to the beginning of the 

+buffer.</p>

+<p class="note">NOTE:&nbsp; When used with physically contiguous buffers, the first (only) address in this array should 

+be aligned on the system default page boundary, and the <span class="inline_code"><a href="#bvphysdesc.pageoffset">

+bvphysdesc.pageoffset</a></span> member should be used to indicate the offset from that address to the beginning of the 

+buffer.</p>

+<p class="Code_Header_2"><a name="bvphysdesc.pagecount">bvphysdesc.pagecount</a></p>

+<p class="code_block">unsigned int pagecount;</p>

+<p>This member indicates the number of pages in the array pointed to by <span class="inline_code">

+<a href="#bvphysdesc.pagearray">bvphysdesc.pagearray</a></span>.</p>

+<p class="note">NOTE:&nbsp; When used with physically contiguous buffers, this member should be set to 1.</p>

+<p class="Code_Header_2"><a name="bvphysdesc.pageoffset">bvphysdesc.pageoffset</a></p>

+<p class="code_block">unsigned long pageoffset;</p>

+<p>This member indicates the number of bytes from the start of the first page (<span class="inline_code">*pagearray</span>) 

+to the start of the buffer.&nbsp; The value must be less than <span class="inline_code"><a href="#bvphysdesc.pagesize">

+bvphysdesc.pagesize</a></span>.</p>

+<p class="imponly"><strong>Implementations Only</strong><br />

+<br />

+Implementations should not ignore this member.</p>

+<hr />

+<p class="Header2">bventry</p>

+<p>Kernel mode entry cannot be the same as the user mode.&nbsp; The specific method of accessing the kernel interface is 

+O/S specific.&nbsp; However, the following interface is currently defined for the specified O/Ss:</p>

+<table class="example">

+	<tr>

+		<td>

+		<p class="Header4">Linux/Android</p>

+		<p class="Code_Header"><a name="bventry">bventry</a></p>

+		<p>This structure is used to obtain the pointers to the implementation&#39;s BLTsville calls.&nbsp; The client can call 

+		the default <span class="inline_code">bv2d_entry()</span> function to obtain the pointers to the implementation 

+		chosen by the system integrators, or it can call a specific function to get the pointers for a specific implementation 

+		(e.g. <span class="inline_code">gcbv_entry()</span>).</p>

+		<p class="small_code_block">struct bventry {<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned int <a href="#bventry.structsize">structsize</a>;<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="#bv_map">BVFN_MAP</a> <a href="#bventry.bv_map">bv_map</a>;<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="#bv_unmap">BVFN_UNMAP</a> <a href="#bventry.bv_unmap">bv_unmap</a>;<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="#bv_blt">BVFN_BLT</a> <a href="#bventry.bv_blt">bv_blt</a>;<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="#bv_cache">BVFN_CACHE</a> <a href="#bventry.bv_cache">bv_cache</a>;<br />

+		};</p>

+		<p class="Code_Header_2"><a name="bventry.structsize">bventry.structsize</a></p>

+		<p class="code_block">unsigned int structsize;</p>

+		<p>This member is used for compatibility between BLTsville versions.&nbsp; (See <span class="inline_code">

+		<a href="#bvbltparams.structsize">bvbltparams.structsize</a></span> for an explanation.) </p>

+		<p class="Code_Header_2"><a name="bventry.bv_map">bventry.bv_map</a>/<a name="bventry.bv_unmap">bv_unmap</a>/<a name="bventry.bv_blt">bv_blt</a>/<a name="bventry.bv_cache">bv_cache</a></p>

+		<p class="code_block">BVFN_MAP bv_map;<br />

+		BVFN_UNMAP bv_unmap;<br />

+		BVFN_BLT bv_blt;<br />

+		BVFN_CACHE bv_cache;</p>

+		<p>These members hold pointers to the functions for the specific implementation queried with a call to

+		<span class="inline_code">*_entry()</span>.</p>

+		<p class="note">NOTE:&nbsp; <span class="inline_code"><a href="#bv_cache">bv_cache()</a></span> is optional, so 

+		this pointer may be set to 0.</p>

+		</td>

+	</tr>

+</table>

+<br />

+<hr /><br />

+<p class="Header2">Linux/Android Deviation</p>

+<p>Although the linked list used in the <span class="inline_code"><a href="#bvbuffmap">bvbuffmap</a></span> structure is 

+not complicated, there may be a requirement to use the standard Linux/Android kernel linked list in that environment.&nbsp; 

+To facilitate this, the <span class="inline_code"><a href="#bvbuffmap.map">bvbuffmap.map</a></span> entry is replaced by 

+the following entry for Linux/Android <span class="underline">kernel mode only</span>:</p>

+<p class="Code_Header"><a name="bvbuffmap.node" class="Code_Header_2">bvbuffmap.node</a></p>

+<p class="code_block">struct list_head node;</p>

+<p>This member is used to reference the containing linked list for the <span class="inline_code"><a href="#bvbuffmap">bvbuffmap</a></span> 

+structures associated with the buffer.</p>

+

+</body>

+

+</html>
diff --git a/bltsville/bltsville/ocdtab.png b/bltsville/bltsville/ocdtab.png
new file mode 100644
index 0000000..239c9bb
--- /dev/null
+++ b/bltsville/bltsville/ocdtab.png
Binary files differ
diff --git a/bltsville/gcbv/Android.mk b/bltsville/gcbv/Android.mk
new file mode 100644
index 0000000..a978401
--- /dev/null
+++ b/bltsville/gcbv/Android.mk
@@ -0,0 +1,86 @@
+#
+# 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/gcparser.c \
+	mirror/gcmap.c \
+	mirror/gcbuffer.c \
+	mirror/gcfill.c \
+	mirror/gcblit.c \
+	mirror/gcfilter.c \
+	mirror/gcdbglog.c
+
+LOCAL_CFLAGS :=
+
+LOCAL_C_INCLUDES := \
+	$(LOCAL_PATH)/mirror \
+	$(LOCAL_PATH)/mirror/include \
+	$(COMMON_PATH)/bltsville/bltsville/include \
+	$(COMMON_PATH)/bltsville/ocd/include
+
+VERSION_H := $(COMMON_PATH)/bltsville/gcbv/version.h
+BV_VERSION := $(shell grep "VER_FILEVERSION_STR" $(VERSION_H) | sed "s,.*\"\([0-9.]*\)\\\0.*,\1,")
+
+LOCAL_SHARED_LIBRARIES := \
+    libcutils \
+
+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
+
+include $(BUILD_SHARED_LIBRARY)
+
+#Creating SymLinks
+#libbltsville_gc2d.so -> libbltsville_gc2d.VERSION.so
+#libbltsville_hw2d.so -> libbltsville_gc2d.so
+SYMLINKS := $(TARGET_OUT_VENDOR)/lib/libbltsville_gc2d.so
+$(SYMLINKS): GC2D_BINARY := ./$(LOCAL_MODULE)$(LOCAL_MODULE_SUFFIX)
+$(SYMLINKS): $(LOCAL_INSTALLED_MODULE) $(LOCAL_PATH)/Android.mk
+	@echo "Symlink: $@ -> $(GC2D_BINARY)"
+	@rm -rf $@
+	$(hide) ln -fs $(GC2D_BINARY) $@
+
+SYMLINKS1 := $(TARGET_OUT_VENDOR)/lib/libbltsville_hw2d.so
+$(SYMLINKS1): LINK_BINARY := ./libbltsville_gc2d.so
+$(SYMLINKS1): $(LOCAL_INSTALLED_MODULE) $(LOCAL_PATH)/Android.mk
+	@echo "Symlink: $@ -> $(LINK_BINARY)"
+	@rm -rf $@
+	$(hide) ln -fs $(LINK_BINARY) $@
+
+ALL_DEFAULT_INSTALLED_MODULES += $(SYMLINKS) $(SYMLINKS1)
+
+# for mm/mmm
+all_modules: $(SYMLINKS) $(SYMLINKS1)
+
diff --git a/bltsville/gcbv/gcmain.c b/bltsville/gcbv/gcmain.c
new file mode 100644
index 0000000..7d8b0bd
--- /dev/null
+++ b/bltsville/gcbv/gcmain.c
@@ -0,0 +1,531 @@
+/*
+ * 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.
+ */
+
+#include "gcmain.h"
+#include "gcbv.h"
+#include <semaphore.h>
+
+#if ANDROID
+#include <cutils/log.h>
+#include <cutils/process_name.h>
+#endif
+
+#define GCZONE_NONE		0
+#define GCZONE_ALL		(~0U)
+#define GCZONE_INIT		(1 << 0)
+#define GCZONE_CALLBACK		(1 << 1)
+
+GCDBG_FILTERDEF(gcmain, GCZONE_NONE,
+		"init",
+		"callback")
+
+
+static int g_handle;
+
+
+/*******************************************************************************
+ * Callback manager.
+ */
+enum gccallbackinfo_status {
+	UNINIT,
+	SUPPORTED,
+	UNSUPPORTED
+};
+
+static const char * const g_statusNames[] = {
+	"UNINIT",
+	"SUPPORTED",
+	"UNSUPPORTED"
+};
+
+struct gccallbackinfo {
+	/* Callback status */
+	enum gccallbackinfo_status status;
+
+	/* Callback handle. */
+	unsigned long handle;
+
+	/* Termination semaphore. */
+	sem_t stop;
+
+	/* Callback thread handle. */
+	pthread_t thread;
+
+    /* Start/stop mutex */
+	pthread_mutex_t mutex;
+};
+
+struct gccallbackinfo g_callbackinfo = {
+	.status = UNINIT
+};
+
+static void *callbackthread(void *_gccallbackinfo)
+{
+	struct gccallbackinfo *gccallbackinfo;
+	struct gcicallbackwait 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;
+		}
+	}
+
+	return NULL;
+}
+
+static int callback_start(struct gccallbackinfo *gccallbackinfo)
+{
+	int result = 0;
+	struct gcicallback gccmdcallback;
+
+	GCENTER(GCZONE_CALLBACK);
+
+	pthread_mutex_lock(&gccallbackinfo->mutex);
+
+	if (gccallbackinfo->status != UNINIT) {
+		pthread_mutex_unlock(&gccallbackinfo->mutex);
+		return 0;
+	}
+
+	gccmdcallback.handle = 0;
+
+	gccallbackinfo->status =
+#if ANDROID
+		/* The Android zygote process refuses to fork if there is
+		 * more than one thread present. */
+		(strcmp(get_process_name(), "zygote") == 0) ? UNSUPPORTED :
+#endif
+		SUPPORTED;
+
+	GCDBG(GCZONE_CALLBACK, "callback status: %s\n",
+	      g_statusNames[gccallbackinfo->status]);
+
+	if (gccallbackinfo->status == SUPPORTED) {
+		/* Initialize callback. */
+		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 termination 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;
+		}
+
+		gccmdcallback.handle = 0;
+	}
+
+fail:
+	if (gccmdcallback.handle != 0) {
+		ioctl(g_handle, GCIOCTL_CALLBACK_FREE, &gccmdcallback);
+		gccallbackinfo->handle = 0;
+	}
+
+	pthread_mutex_unlock(&gccallbackinfo->mutex);
+
+	GCEXITARG(GCZONE_CALLBACK, "result=%d", result);
+	return result;
+}
+
+static void callback_stop(struct gccallbackinfo *gccallbackinfo)
+{
+	struct gcicallback gccmdcallback;
+
+	GCENTER(GCZONE_CALLBACK);
+
+	pthread_mutex_lock(&gccallbackinfo->mutex);
+
+	if (gccallbackinfo->status == SUPPORTED) {
+		if (gccallbackinfo->thread) {
+			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. */
+		gccmdcallback.handle = gccallbackinfo->handle;
+		ioctl(g_handle, GCIOCTL_CALLBACK_FREE, &gccmdcallback);
+		gccallbackinfo->handle = 0;
+	}
+
+	gccallbackinfo->status == UNINIT;
+
+	pthread_mutex_unlock(&gccallbackinfo->mutex);
+
+	GCEXIT(GCZONE_CALLBACK);
+}
+
+
+/*******************************************************************************
+ * IOCTL wrappers.
+ */
+
+#if GCDEBUG_ENABLE && 0
+#define GCPRINTDELAY() sleep(1)
+#else
+#define GCPRINTDELAY()
+#endif
+
+void gc_getcaps_wrapper(struct gcicaps *gcicaps)
+{
+	int result;
+
+	GCPRINTDELAY();
+
+	result = ioctl(g_handle, GCIOCTL_GETCAPS, gcicaps);
+	if (result != 0) {
+		GCERR("ioctl failed (%d).\n", result);
+		gcicaps->gcerror = GCERR_IOCTL;
+	}
+}
+
+void gc_map_wrapper(struct gcimap *gcmap)
+{
+	int result;
+
+	GCPRINTDELAY();
+	result = ioctl(g_handle, GCIOCTL_MAP, gcmap);
+
+	if (result != 0) {
+		GCERR("ioctl failed (%d).\n", result);
+		gcmap->gcerror = GCERR_IOCTL;
+	}
+}
+
+void gc_unmap_wrapper(struct gcimap *gcmap)
+{
+	int result;
+
+	GCPRINTDELAY();
+	result = ioctl(g_handle, GCIOCTL_UNMAP, gcmap);
+
+	if (result != 0) {
+		GCERR("ioctl failed (%d).\n", result);
+		gcmap->gcerror = GCERR_IOCTL;
+	}
+}
+
+void gc_commit_wrapper(struct gcicommit *gccommit)
+{
+	int result;
+
+	GCPRINTDELAY();
+
+	/* Callback start is delayed until needed to handle a case
+	 * where it's unsupported on Android. */
+	if (gccommit->callback)
+		callback_start(&g_callbackinfo);
+
+	gccommit->handle = g_callbackinfo.handle;
+	result = ioctl(g_handle, GCIOCTL_COMMIT, gccommit);
+
+	if (result != 0) {
+		GCERR("ioctl failed (%d).\n", result);
+		gccommit->gcerror = GCERR_IOCTL;
+	}
+}
+
+void gc_callback_wrapper(struct gcicallbackarm *gcicallbackarm)
+{
+	int result;
+
+	GCPRINTDELAY();
+
+	callback_start(&g_callbackinfo);
+
+	gcicallbackarm->handle = g_callbackinfo.handle;
+	result = ioctl(g_handle, GCIOCTL_CALLBACK_ARM, gcicallbackarm);
+	if (result != 0) {
+		GCERR("ioctl failed (%d).\n", result);
+		gcicallbackarm->gcerror = GCERR_IOCTL;
+	}
+}
+
+
+/*******************************************************************************
+ * Convert floating point in 0..1 range to an 8-bit value in range 0..255.
+ */
+
+union gcfp {
+	struct {
+		unsigned int mantissa:23;
+		unsigned int exponent:8;
+		unsigned int sign:1;
+	} comp;
+
+	float value;
+};
+
+unsigned char gcfp2norm8(float value)
+{
+	union gcfp gcfp;
+	int exponent;
+	unsigned int mantissa;
+	int shift;
+
+	/* Get access to components. */
+	gcfp.value = value;
+
+	/* Clamp negatives. */
+	if (gcfp.comp.sign)
+		return 0;
+
+	/* Get unbiased exponent. */
+	exponent = (int) gcfp.comp.exponent - 127;
+
+	/* Clamp if too large. */
+	if (exponent >= 0)
+		return 255;
+
+	/* Clamp if too small. */
+	if (exponent < -8)
+		return 0;
+
+	/* Determine the shift value. */
+	shift = (23 - 8) - exponent;
+
+	/* Compute the mantissa. */
+	mantissa = (gcfp.comp.mantissa | 0x00800000) >> shift;
+
+	/* Normalize. */
+	mantissa = (mantissa * 255) >> 8;
+
+	return (unsigned char) mantissa;
+}
+
+
+/*******************************************************************************
+ * Surface allocation.
+ */
+
+enum bverror allocate_surface(struct bvbuffdesc **bvbuffdesc,
+			      void **buffer,
+			      unsigned int size)
+{
+	enum bverror bverror = BVERR_NONE;
+	struct bvbuffdesc *tempbuffdesc = NULL;
+	void *tempbuff = NULL;
+	unsigned long base;
+
+	/* Allocate surface buffer descriptor. */
+	tempbuffdesc = gcalloc(struct bvbuffdesc, sizeof(struct bvbuffdesc));
+	if (tempbuffdesc == NULL) {
+		BVSETERROR(BVERR_OOM, "failed to allocate surface");
+		goto exit;
+	}
+
+	/* Initialize buffer descriptor. */
+	tempbuffdesc->structsize = sizeof(struct bvbuffdesc);
+	tempbuffdesc->virtaddr = NULL;
+	tempbuffdesc->length = size;
+	tempbuffdesc->map = NULL;
+	tempbuffdesc->auxtype = BVAT_NONE;
+	tempbuffdesc->auxptr = NULL;
+
+	/* Allocate the surface. */
+	tempbuff = gcalloc(void, size + GC_MAX_BASE_ALIGN);
+	if (tempbuff == NULL) {
+		BVSETERROR(BVERR_OOM, "failed to allocate surface");
+		goto exit;
+	}
+
+	/* Align the base address. */
+	tempbuffdesc->virtaddr
+		= (void *) (((unsigned long) tempbuff + GC_MAX_BASE_ALIGN - 1)
+					& ~(GC_MAX_BASE_ALIGN - 1));
+
+	/* Set return pointers. */
+	*bvbuffdesc = tempbuffdesc;
+	*buffer = tempbuff;
+	return BVERR_NONE;
+
+exit:
+	free_surface(tempbuffdesc, tempbuff);
+	return bverror;
+}
+
+void free_surface(struct bvbuffdesc *bvbuffdesc,
+		  void *buffer)
+{
+	gcfree(buffer);
+	gcfree(bvbuffdesc);
+}
+
+
+/*******************************************************************************
+ * Cache operation wrapper.
+ */
+
+enum bverror gcbvcacheop(int count, struct c2dmrgn rgn[],
+			 enum bvcacheop cacheop)
+{
+	int result;
+	struct gcicache 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.
+ */
+
+void  __attribute__((constructor)) dev_init(void)
+{
+	char *env;
+
+	env = getenv("GCBV_DEBUG");
+	if (env && (atol(env) != 0))
+		GCDBG_ENABLEDUMP();
+
+	GCDBG_INIT();
+	GCDBG_REGISTER(gcmain);
+
+	GCENTER(GCZONE_INIT);
+
+	g_handle = open("/dev/gcioctl", O_RDWR);
+	if (g_handle == -1) {
+		GCERR("failed to open device (%d).\n", errno);
+		goto fail;
+	}
+
+	bv_init();
+
+	pthread_mutex_init(&g_callbackinfo.mutex, 0);
+
+	GCEXIT(GCZONE_INIT);
+	return;
+
+fail:
+	if (g_handle > 0) {
+		close(g_handle);
+		g_handle = 0;
+	}
+
+	GCEXIT(GCZONE_INIT);
+}
+
+void __attribute__((destructor)) dev_exit(void)
+{
+	GCENTER(GCZONE_INIT);
+
+	bv_exit();
+	callback_stop(&g_callbackinfo);
+
+	if (g_handle != 0) {
+		close(g_handle);
+		g_handle = 0;
+	}
+
+	GCEXIT(GCZONE_INIT);
+	GCDBG_EXIT();
+}
+
diff --git a/bltsville/gcbv/gcmain.h b/bltsville/gcbv/gcmain.h
new file mode 100644
index 0000000..6d6489c
--- /dev/null
+++ b/bltsville/gcbv/gcmain.h
@@ -0,0 +1,143 @@
+/*
+ * 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.
+ */
+
+#ifndef GCMAIN_H
+#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 <gcx.h>
+#include <gcioctl.h>
+#include <bltsville.h>
+#include <bvinternal.h>
+#include <bverror.h>
+
+#define GC_DEV_NAME	"gc2duser"
+
+
+/*******************************************************************************
+ * 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 max(x, y) (x > y ? x : y)
+#define min(x, y) (x < y ? x : y)
+
+#define EXPORT_SYMBOL(sym)
+
+#define gc_debug_blt(...)
+
+typedef int64_t s64;
+typedef uint64_t u64;
+
+#define div_u64(x, y) ((x) / (y))
+#define div_s64(x, y) ((x) / (y))
+#define div64_u64(x, y) ((x) / (y))
+#define div64_s64(x, y) ((x) / (y))
+
+#define PAGE_SHIFT              12
+#define PAGE_SIZE               (1 << PAGE_SHIFT)
+#define PAGE_MASK               (~(PAGE_SIZE-1))
+
+/*******************************************************************************
+ * 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.
+ */
+
+void gc_getcaps_wrapper(struct gcicaps *gcicaps);
+void gc_map_wrapper(struct gcimap *gcimap);
+void gc_unmap_wrapper(struct gcimap *gcimap);
+void gc_commit_wrapper(struct gcicommit *gcicommit);
+void gc_callback_wrapper(struct gcicallbackarm *gcicallbackarm);
+
+
+/*******************************************************************************
+ * Surface allocation.
+ */
+enum bverror allocate_surface(struct bvbuffdesc **bvbuffdesc,
+			      void **buffer,
+			      unsigned int size);
+
+void free_surface(struct bvbuffdesc *bvbuffdesc,
+		  void *buffer);
+
+
+/*******************************************************************************
+ * Floating point conversions.
+ */
+
+unsigned char gcfp2norm8(float value);
+
+
+/*******************************************************************************
+ * Cache operation wrapper.
+ */
+
+enum bverror gcbvcacheop(int count, struct c2dmrgn rgn[],
+			 enum bvcacheop cacheop);
+
+
+/*******************************************************************************
+ * 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/bltsville/gcbv/mirror/gcblit.c b/bltsville/gcbv/mirror/gcblit.c
new file mode 100644
index 0000000..5dae273
--- /dev/null
+++ b/bltsville/gcbv/mirror/gcblit.c
@@ -0,0 +1,771 @@
+/*
+ * Copyright(c) 2012,
+ * Texas Instruments, Inc. and Vivante Corporation.
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *   * Neither the name of Vivante Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "gcbv.h"
+
+#define GCZONE_NONE		0
+#define GCZONE_ALL		(~0U)
+#define GCZONE_BLEND		(1 << 0)
+#define GCZONE_SURF		(1 << 1)
+#define GCZONE_BLIT		(1 << 3)
+
+GCDBG_FILTERDEF(blit, GCZONE_NONE,
+		"blend",
+		"surf",
+		"blit")
+
+
+static enum bverror do_blit_end(struct bvbltparams *bvbltparams,
+				struct gcbatch *batch)
+{
+	enum bverror bverror;
+	struct gcblit *gcblit;
+	struct gcmobltconfig *gcmobltconfig;
+	struct gcmostartde *gcmostartde;
+
+	GCENTER(GCZONE_BLIT);
+
+	/* Get a shortcut to the operation specific data. */
+	gcblit = &batch->op.blit;
+
+	GCDBG(GCZONE_BLIT, "finalizing the blit, scrcount = %d\n",
+	      gcblit->srccount);
+
+	/***********************************************************************
+	 * Configure the operation.
+	 */
+
+	/* Allocate command buffer. */
+	bverror = claim_buffer(bvbltparams, batch,
+			       sizeof(struct gcmobltconfig),
+			       (void **) &gcmobltconfig);
+	if (bverror != BVERR_NONE)
+		goto exit;
+
+	/* Configure multi-source control. */
+	gcmobltconfig->multisource_ldst = gcmobltconfig_multisource_ldst;
+	gcmobltconfig->multisource.raw = 0;
+	gcmobltconfig->multisource.reg.srccount = gcblit->srccount - 1;
+
+	GCDBG(GCZONE_BLIT, "blockenable = %d\n", gcblit->blockenable);
+	if (gcblit->blockenable) {
+		gcmobltconfig->multisource.reg.horblock
+			= GCREG_DE_MULTI_SOURCE_HORIZONTAL_BLOCK_PIXEL16;
+		gcmobltconfig->multisource.reg.verblock
+			= GCREG_DE_MULTI_SOURCE_VERTICAL_BLOCK_LINE64;
+	} else {
+		gcmobltconfig->multisource.reg.horblock
+			= GCREG_DE_MULTI_SOURCE_HORIZONTAL_BLOCK_PIXEL128;
+		gcmobltconfig->multisource.reg.verblock
+			= GCREG_DE_MULTI_SOURCE_VERTICAL_BLOCK_LINE1;
+	}
+
+	/* Set destination configuration. */
+	GCDBG(GCZONE_BLIT, "  swizzle code = %d\n", gcblit->swizzle);
+	GCDBG(GCZONE_BLIT, "  format code = %d\n", gcblit->format);
+
+	gcmobltconfig->dstconfig_ldst = gcmobltconfig_dstconfig_ldst;
+	gcmobltconfig->dstconfig.raw = 0;
+	gcmobltconfig->dstconfig.reg.swizzle = gcblit->swizzle;
+	gcmobltconfig->dstconfig.reg.format = gcblit->format;
+	gcmobltconfig->dstconfig.reg.command = gcblit->multisrc
+		? GCREG_DEST_CONFIG_COMMAND_MULTI_SOURCE_BLT
+		: GCREG_DEST_CONFIG_COMMAND_BIT_BLT;
+
+	/***********************************************************************
+	 * Start the operation.
+	 */
+
+	/* Allocate command buffer. */
+	bverror = claim_buffer(bvbltparams, batch,
+			       sizeof(struct gcmostartde),
+			       (void **) &gcmostartde);
+	if (bverror != BVERR_NONE)
+		goto exit;
+
+	/* Set START_DE command. */
+	gcmostartde->startde.cmd.fld = gcfldstartde;
+
+	/* Set destination rectangle. */
+	gcmostartde->rect.left = gcblit->dstrect.left;
+	gcmostartde->rect.top = gcblit->dstrect.top;
+	gcmostartde->rect.right = gcblit->dstrect.right;
+	gcmostartde->rect.bottom = gcblit->dstrect.bottom;
+
+	GCDBG(GCZONE_BLIT, "dstrect = (%d,%d)-(%d,%d)\n",
+	      gcmostartde->rect.left, gcmostartde->rect.top,
+	      gcmostartde->rect.right, gcmostartde->rect.bottom);
+
+	/* Reset the finalizer. */
+	batch->batchend = do_end;
+
+	gc_debug_blt(gcblit->srccount,
+		     abs(gcblit->dstrect.right - gcblit->dstrect.left),
+		     abs(gcblit->dstrect.bottom - gcblit->dstrect.top));
+
+exit:
+	GCEXITARG(GCZONE_BLIT, "bv%s = %d\n",
+		  (bverror == BVERR_NONE) ? "result" : "error", bverror);
+	return bverror;
+}
+
+enum bverror do_blit(struct bvbltparams *bvbltparams,
+		     struct gcbatch *batch,
+		     struct surfaceinfo *srcinfo)
+{
+	enum bverror bverror = BVERR_NONE;
+	struct gccontext *gccontext = get_context();
+
+	struct gcmosrc0 *gcmosrc0;
+	struct gcmosrc *gcmosrc;
+	struct gcblit *gcblit;
+
+	unsigned int index;
+	struct bvbuffmap *dstmap = NULL;
+	struct bvbuffmap *srcmap = NULL;
+
+	struct surfaceinfo *dstinfo;
+	int dstshiftX, dstshiftY;
+	int dstpixalign, dstbyteshift;
+	int dstoffsetX, dstoffsetY;
+
+	int srcshiftX, srcshiftY, srctopedge;
+	struct gcrect srcclipped;
+	int srcsurfwidth, srcsurfheight;
+	unsigned int physwidth, physheight;
+	int orthogonal;
+	int multisrc;
+
+	GCENTER(GCZONE_BLIT);
+
+	/* 3-plane source not supported. */
+	if ((srcinfo->format.type == BVFMT_YUV) &&
+	    (srcinfo->format.cs.yuv.planecount == 3)) {
+		BVSETBLTERROR((srcinfo->index == 0)
+					? BVERR_SRC1GEOM_FORMAT
+					: BVERR_SRC2GEOM_FORMAT,
+			      "unsupported source%d format.",
+			      srcinfo->index + 1);
+		goto exit;
+	}
+
+	/* Get a shortcut to the destination surface. */
+	dstinfo = &batch->dstinfo;
+
+	/* Parse destination parameters. */
+	bverror = parse_destination(bvbltparams, batch);
+	if (bverror != BVERR_NONE)
+		goto exit;
+
+	/* Setup rotation. */
+	process_dest_rotation(bvbltparams, batch);
+
+
+	/***********************************************************************
+	 * Determine source surface alignment offset.
+	 */
+
+	/* Determine whether the source and the destination are orthogonal
+	 * to each other. */
+	orthogonal = (srcinfo->angle % 2) != (dstinfo->angle % 2);
+
+	/* Compute clipped source rectangle. */
+	srcclipped.left   = srcinfo->rect.left   + batch->clipdelta.left;
+	srcclipped.top    = srcinfo->rect.top    + batch->clipdelta.top;
+	srcclipped.right  = srcinfo->rect.right  + batch->clipdelta.right;
+	srcclipped.bottom = srcinfo->rect.bottom + batch->clipdelta.bottom;
+	GCPRINT_RECT(GCZONE_SURF, "clipped source", &srcclipped);
+
+	/* Validate the source rectangle. */
+	if (!valid_rect(srcinfo->geom, &srcclipped)) {
+		BVSETBLTERROR((srcinfo->index == 0)
+					? BVERR_SRC1RECT
+					: BVERR_SRC2RECT,
+			      "invalid source rectangle.");
+		goto exit;
+	}
+
+	/* Compute the source surface shift. */
+	switch (srcinfo->angle) {
+	case ROT_ANGLE_0:
+		srctopedge = srcclipped.top;
+		srcshiftX = srcclipped.left - batch->dstadjusted.left;
+		srcshiftY = srctopedge - batch->dstadjusted.top;
+		break;
+
+	case ROT_ANGLE_90:
+		srctopedge = srcinfo->geom->width - srcclipped.left;
+		srcshiftX = srcclipped.top - batch->dstadjusted.top;
+		srcshiftY = srctopedge
+			  - (batch->dstwidth - batch->dstadjusted.left);
+		srctopedge += 1;
+		break;
+
+	case ROT_ANGLE_180:
+		srctopedge = srcinfo->geom->height - srcclipped.top;
+		srcshiftX = (srcinfo->geom->width - srcclipped.left)
+			  - (batch->dstwidth - batch->dstadjusted.left);
+		srcshiftY = srctopedge
+			  - (batch->dstheight - batch->dstadjusted.top);
+		srctopedge += 1;
+		break;
+
+	case ROT_ANGLE_270:
+		srctopedge = srcclipped.left;
+		srcshiftX = (srcinfo->geom->height - srcclipped.top)
+			  - (batch->dstheight - batch->dstadjusted.top);
+		srcshiftY = srctopedge - batch->dstadjusted.left;
+		break;
+
+	default:
+		srctopedge = 0;
+		srcshiftX = 0;
+		srcshiftY = 0;
+	}
+
+	/* We cannot be in the middle of a sample, currently only YUV formats
+	 * can have subsamples. Adjust vertical position as necessary.
+	 * Horizontal position will be adjusted based on the byte offset and
+	 * base address alignment requirement. This assumes that if we are
+	 * aligned on the base address, then we are also aligned at the
+	 * beginning of a sample. */
+	if (srcinfo->format.type == BVFMT_YUV) {
+		int mody = (srctopedge + srcshiftY)
+			 % srcinfo->format.cs.yuv.ysample;
+
+		if (mody < 0)
+			mody = srcinfo->format.cs.yuv.ysample + mody;
+
+		srcshiftY -= mody;
+		srcinfo->ypixalign = -mody;
+	} else {
+		srcinfo->ypixalign = 0;
+	}
+
+	/* Compute the source surface offset in bytes. */
+	srcinfo->bytealign = srcshiftY * (int) srcinfo->geom->virtstride
+			   + srcshiftX * (int) srcinfo->format.bitspp / 8;
+
+	/* Compute the source offset in pixels needed to compensate
+	 * for the surface base address misalignment if any. */
+	srcinfo->xpixalign = get_pixel_offset(srcinfo, srcinfo->bytealign);
+
+	GCDBG(GCZONE_SURF, "source surface %d:\n", srcinfo->index + 1);
+	GCDBG(GCZONE_SURF, "  surface offset (pixels) = %d,%d\n",
+	      srcshiftX, srcshiftY);
+	GCDBG(GCZONE_SURF, "  surface offset (bytes) = 0x%08X\n",
+	      srcinfo->bytealign);
+	GCDBG(GCZONE_SURF, "  srcpixalign = %d,%d\n",
+	      srcinfo->xpixalign, srcinfo->ypixalign);
+
+	/* Apply the source alignment. */
+	srcinfo->bytealign += srcinfo->xpixalign
+			   * (int) srcinfo->format.bitspp / 8;
+	srcshiftX += srcinfo->xpixalign;
+
+	/* NOTE: at this point the source is ready to be presented,
+	 * srcinfo->xpixalign and srcinfo->ypixalign represent additional
+	 * adjustments for the DESTINATION. */
+
+	GCDBG(GCZONE_SURF, "  adjusted surface offset (pixels) = %d,%d\n",
+	      srcshiftX, srcshiftY);
+	GCDBG(GCZONE_SURF, "  adjusted surface offset (bytes) = 0x%08X\n",
+	      srcinfo->bytealign);
+
+	/* Compute U/V plane offsets. */
+	if ((srcinfo->format.type == BVFMT_YUV) &&
+	    (srcinfo->format.cs.yuv.planecount > 1))
+		set_computeyuv(srcinfo, srcshiftX, srcshiftY);
+
+	/* Set precomputed destination adjustments based on the destination
+	 * base address misalignment only. */
+	dstshiftX = dstinfo->xpixalign;
+	dstshiftY = dstinfo->ypixalign;
+
+	/* Apply source adjustemnts. */
+	if (srcinfo->angle == dstinfo->angle) {
+		dstshiftX += srcinfo->xpixalign;
+		dstshiftY += srcinfo->ypixalign;
+	} else if (((srcinfo->angle + 3) % 4) == dstinfo->angle) {
+		dstshiftY += srcinfo->xpixalign;
+	} else if (((srcinfo->angle + 1) % 4) == dstinfo->angle) {
+		dstshiftX += srcinfo->ypixalign;
+	}
+
+	/* Compute the destination surface offset in bytes. */
+	dstbyteshift = dstshiftY * (int) dstinfo->geom->virtstride
+		     + dstshiftX * (int) dstinfo->format.bitspp / 8;
+
+	/* Compute the destination offset in pixels needed to compensate
+	 * for the surface base address misalignment if any. If dstpixalign
+	 * comes out anything other than zero, multisource blit cannot be
+	 * performed. */
+	dstpixalign = get_pixel_offset(dstinfo, dstbyteshift);
+
+	GCDBG(GCZONE_SURF, "destination surface:\n");
+	GCDBG(GCZONE_SURF, "  surface offset (pixels) = %d,%d\n",
+	      dstshiftX, dstshiftY);
+	GCDBG(GCZONE_SURF, "  surface offset (bytes) = 0x%08X\n",
+	      dstbyteshift);
+	GCDBG(GCZONE_SURF, "  realignment = %d\n",
+	      dstpixalign);
+
+	if ((dstpixalign != 0) ||
+	    ((srcinfo->xpixalign != 0) && (srcinfo->angle == dstinfo->angle))) {
+		/* Adjust the destination to match the source geometry. */
+		switch (srcinfo->angle) {
+		case ROT_ANGLE_0:
+			/* Adjust coordinates. */
+			srcclipped.left -= srcshiftX;
+			srcclipped.top  -= srcshiftY;
+
+			/* Determine source size. */
+			srcsurfwidth = srcinfo->geom->width
+				     - srcinfo->xpixalign;
+			srcsurfheight = srcinfo->geom->height;
+			break;
+
+		case ROT_ANGLE_90:
+			/* Adjust top coordinate. */
+			srcclipped.top -= srcshiftX;
+
+			/* Determine source size. */
+			srcsurfwidth = srcinfo->geom->height
+				     - srcinfo->xpixalign;
+			srcsurfheight = srcinfo->geom->width;
+			break;
+
+		case ROT_ANGLE_180:
+			/* Determine source size. */
+			srcsurfwidth = srcinfo->geom->width
+				     - srcinfo->xpixalign;
+			srcsurfheight = srcinfo->geom->height;
+			break;
+
+		case ROT_ANGLE_270:
+			/* Adjust coordinates. */
+			srcclipped.left -= srcshiftY;
+
+			/* Determine source size. */
+			srcsurfwidth = srcinfo->geom->height
+				     - srcinfo->xpixalign;
+			srcsurfheight = srcinfo->geom->width;
+			break;
+
+		default:
+			srcsurfwidth = 0;
+			srcsurfheight = 0;
+		}
+
+		GCDBG(GCZONE_SURF, "srcrect origin = %d,%d\n",
+		      srcclipped.left, srcclipped.top);
+		GCDBG(GCZONE_SURF, "source physical size = %dx%d\n",
+		      srcsurfwidth, srcsurfheight);
+
+		/* Overwrite destination byte offset. */
+		dstbyteshift = dstinfo->bytealign;
+
+		/* No adjustment necessary for single-source. */
+		dstoffsetX = 0;
+		dstoffsetY = 0;
+
+		/* Set the physical destination size. */
+		physwidth = dstinfo->physwidth;
+		physheight = dstinfo->physheight;
+
+		/* Disable multi source for the cases where the destination
+		 * and the source address alignments do not match. */
+		multisrc = 0;
+		GCDBG(GCZONE_SURF, "multi-source disabled.\n");
+	} else {
+		/* Source origin is not used in multi-source setup. */
+		srcclipped.left = 0;
+		srcclipped.top = 0;
+
+		/* Adjust the destination to match the source geometry. */
+		switch (srcinfo->angle) {
+		case ROT_ANGLE_0:
+			/* Adjust the destination horizontally. */
+			dstoffsetX = srcinfo->xpixalign;
+			dstoffsetY = srcinfo->ypixalign;
+
+			/* Apply the source alignment. */
+			if ((dstinfo->angle % 2) == 0) {
+				physwidth  = dstinfo->physwidth
+					   - srcinfo->xpixalign;
+				physheight = dstinfo->physheight
+					   - srcinfo->ypixalign;
+			} else {
+				physwidth  = dstinfo->physwidth
+					   - srcinfo->ypixalign;
+				physheight = dstinfo->physheight
+					   - srcinfo->xpixalign;
+			}
+			break;
+
+		case ROT_ANGLE_90:
+			/* Adjust the destination vertically. */
+			dstoffsetX = srcinfo->ypixalign;
+			dstoffsetY = srcinfo->xpixalign;
+
+			/* Apply the source alignment. */
+			if ((dstinfo->angle % 2) == 0) {
+				physwidth  = dstinfo->physwidth
+					   - srcinfo->ypixalign;
+				physheight = dstinfo->physheight
+					   - srcinfo->xpixalign;
+			} else {
+				physwidth  = dstinfo->physwidth
+					   - srcinfo->xpixalign;
+				physheight = dstinfo->physheight
+					   - srcinfo->ypixalign;
+			}
+			break;
+
+		case ROT_ANGLE_180:
+			/* No adjustment necessary. */
+			dstoffsetX = 0;
+			dstoffsetY = 0;
+
+			/* Apply the source alignment. */
+			if ((dstinfo->angle % 2) == 0) {
+				physwidth  = dstinfo->physwidth
+					   - srcinfo->xpixalign;
+				physheight = dstinfo->physheight
+					   - srcinfo->ypixalign;
+			} else {
+				physwidth  = dstinfo->physwidth
+					   - srcinfo->ypixalign;
+				physheight = dstinfo->physheight
+					   - srcinfo->xpixalign;
+			}
+			break;
+
+		case ROT_ANGLE_270:
+			/* No adjustment necessary. */
+			dstoffsetX = 0;
+			dstoffsetY = 0;
+
+			/* Apply the source alignment. */
+			if ((dstinfo->angle % 2) == 0) {
+				physwidth  = dstinfo->physwidth
+					   - srcinfo->ypixalign;
+				physheight = dstinfo->physheight
+					   - srcinfo->xpixalign;
+			} else {
+				physwidth  = dstinfo->physwidth
+					   - srcinfo->xpixalign;
+				physheight = dstinfo->physheight
+					   - srcinfo->ypixalign;
+			}
+			break;
+
+		default:
+			physwidth = 0;
+			physheight = 0;
+			dstoffsetX = 0;
+			dstoffsetY = 0;
+		}
+
+		/* Source geometry is now the same as the destination. */
+		if (orthogonal) {
+			srcsurfwidth = physheight;
+			srcsurfheight = physwidth;
+		} else {
+			srcsurfwidth = physwidth;
+			srcsurfheight = physheight;
+		}
+
+		/* Enable multi-source. */
+		multisrc = 1;
+		GCDBG(GCZONE_SURF, "multi-source enabled.\n");
+	}
+
+	/* Misaligned source may cause the destination parameters
+	 * to change, verify whether this has happened. */
+	if ((batch->dstbyteshift != dstbyteshift) ||
+	    (batch->dstphyswidth != physwidth) ||
+	    (batch->dstphysheight != physheight) ||
+	    (batch->dstoffsetX != dstoffsetX) ||
+	    (batch->dstoffsetY != dstoffsetY)) {
+		/* Set new values. */
+		batch->dstbyteshift = dstbyteshift;
+		batch->dstphyswidth = physwidth;
+		batch->dstphysheight = physheight;
+		batch->dstoffsetX = dstoffsetX;
+		batch->dstoffsetY = dstoffsetY;
+
+		/* Now we need to end the current batch and program
+		 * the hardware with the new destination. */
+		batch->batchflags |= BVBATCH_DST;
+	}
+
+	/* Check if we need to finalize existing batch. */
+	if ((batch->batchend != do_blit_end) ||
+	    (batch->op.blit.srccount == 4) ||
+	    (batch->op.blit.multisrc == 0) ||
+	    (multisrc == 0) ||
+	    ((batch->batchflags & (BVBATCH_DST |
+				   BVBATCH_CLIPRECT |
+				   BVBATCH_DESTRECT)) != 0)) {
+		/* Finalize existing batch if any. */
+		bverror = batch->batchend(bvbltparams, batch);
+		if (bverror != BVERR_NONE)
+			goto exit;
+
+		/* Blit batch. */
+		batch->batchend = do_blit_end;
+
+		/* Initialize the new batch. */
+		gcblit = &batch->op.blit;
+		gcblit->blockenable = 0;
+		gcblit->srccount = 0;
+		gcblit->multisrc = multisrc;
+
+		/* Set the destination format. */
+		gcblit->format  = dstinfo->format.format;
+		gcblit->swizzle = dstinfo->format.swizzle;
+
+		/* Set the destination coordinates. */
+		gcblit->dstrect.left   = batch->dstadjusted.left   - dstoffsetX;
+		gcblit->dstrect.top    = batch->dstadjusted.top    - dstoffsetY;
+		gcblit->dstrect.right  = batch->dstadjusted.right  - dstoffsetX;
+		gcblit->dstrect.bottom = batch->dstadjusted.bottom - dstoffsetY;
+
+		/* Map the destination. */
+		bverror = do_map(dstinfo->buf.desc, batch, &dstmap);
+		if (bverror != BVERR_NONE) {
+			bvbltparams->errdesc = gccontext->bverrorstr;
+			goto exit;
+		}
+
+		/* Set the new destination. */
+		bverror = set_dst(bvbltparams, batch, dstmap);
+		if (bverror != BVERR_NONE)
+			goto exit;
+
+		/* Reset the modified flag. */
+		batch->batchflags &= ~(BVBATCH_DST |
+				       BVBATCH_CLIPRECT |
+				       BVBATCH_DESTRECT);
+	}
+
+	/* Map the source. */
+	bverror = do_map(srcinfo->buf.desc, batch, &srcmap);
+	if (bverror != BVERR_NONE) {
+		bvbltparams->errdesc = gccontext->bverrorstr;
+		goto exit;
+	}
+
+	/***********************************************************************
+	** Configure source.
+	*/
+
+	/* We need to walk in blocks if the source and the destination
+	 * surfaces are orthogonal to each other. */
+	batch->op.blit.blockenable |= orthogonal;
+
+	/* Shortcut to the register index. */
+	index = batch->op.blit.srccount;
+
+	/* Set surface parameters. */
+	if (index == 0) {
+		/* Allocate command buffer. */
+		bverror = claim_buffer(bvbltparams, batch,
+				       sizeof(struct gcmosrc0),
+				       (void **) &gcmosrc0);
+		if (bverror != BVERR_NONE)
+			goto exit;
+
+		add_fixup(bvbltparams, batch, &gcmosrc0->address,
+			  srcinfo->bytealign);
+
+		gcmosrc0->config_ldst = gcmosrc0_config_ldst;
+		gcmosrc0->address = GET_MAP_HANDLE(srcmap);
+		gcmosrc0->stride = srcinfo->geom->virtstride;
+		gcmosrc0->rotation.raw = 0;
+		gcmosrc0->rotation.reg.surf_width = srcsurfwidth;
+		gcmosrc0->config.raw = 0;
+		gcmosrc0->config.reg.swizzle = srcinfo->format.swizzle;
+		gcmosrc0->config.reg.format = srcinfo->format.format;
+		gcmosrc0->origin.reg.x = srcclipped.left;
+		gcmosrc0->origin.reg.y = srcclipped.top;
+		gcmosrc0->size.reg = gcregsrcsize_max;
+
+		gcmosrc0->rotation_ldst = gcmosrc0_rotation_ldst;
+		gcmosrc0->rotationheight.reg.height = srcsurfheight;
+		gcmosrc0->rotationangle.raw = 0;
+		gcmosrc0->rotationangle.reg.src = rotencoding[srcinfo->angle];
+		gcmosrc0->rotationangle.reg.dst = rotencoding[dstinfo->angle];
+		gcmosrc0->rotationangle.reg.src_mirror = srcinfo->mirror;
+		gcmosrc0->rotationangle.reg.dst_mirror = GCREG_MIRROR_NONE;
+
+		gcmosrc0->rop_ldst = gcmosrc0_rop_ldst;
+		gcmosrc0->rop.raw = 0;
+		gcmosrc0->rop.reg.type = GCREG_ROP_TYPE_ROP3;
+		gcmosrc0->rop.reg.fg = (unsigned char) srcinfo->rop;
+
+		gcmosrc0->mult_ldst = gcmosrc0_mult_ldst;
+		gcmosrc0->mult.raw = 0;
+		gcmosrc0->mult.reg.srcglobalpremul
+		= GCREG_COLOR_MULTIPLY_MODES_SRC_GLOBAL_PREMULTIPLY_DISABLE;
+
+		if (srcinfo->format.premultiplied)
+			gcmosrc0->mult.reg.srcpremul
+			= GCREG_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_DISABLE;
+		else
+			gcmosrc0->mult.reg.srcpremul
+			= GCREG_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_ENABLE;
+
+		if (dstinfo->format.premultiplied) {
+			gcmosrc0->mult.reg.dstpremul
+			= GCREG_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_DISABLE;
+
+			gcmosrc0->mult.reg.dstdemul
+			= GCREG_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY_DISABLE;
+		} else {
+			gcmosrc0->mult.reg.dstpremul
+			= GCREG_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_ENABLE;
+
+			gcmosrc0->mult.reg.dstdemul
+			= GCREG_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY_ENABLE;
+		}
+
+		/* Program blending. */
+		bverror = set_blending(bvbltparams, batch, srcinfo);
+		if (bverror != BVERR_NONE)
+			goto exit;
+
+		/* Program YUV source. */
+		if (srcinfo->format.type == BVFMT_YUV) {
+			bverror = set_yuvsrc(bvbltparams, batch,
+					     srcinfo, srcmap);
+			if (bverror != BVERR_NONE)
+				goto exit;
+		}
+	} else {
+		/* Allocate command buffer. */
+		bverror = claim_buffer(bvbltparams, batch,
+				       sizeof(struct gcmosrc),
+				       (void **) &gcmosrc);
+		if (bverror != BVERR_NONE)
+			goto exit;
+
+		add_fixup(bvbltparams, batch, &gcmosrc->address,
+			  srcinfo->bytealign);
+
+		gcmosrc->address_ldst = gcmosrc_address_ldst[index];
+		gcmosrc->address = GET_MAP_HANDLE(srcmap);
+		gcmosrc->stride_ldst = gcmosrc_stride_ldst[index];
+		gcmosrc->stride = srcinfo->geom->virtstride;
+
+		gcmosrc->rotation_ldst = gcmosrc_rotation_ldst[index];
+		gcmosrc->rotation.raw = 0;
+		gcmosrc->rotation.reg.surf_width = srcsurfwidth;
+
+		gcmosrc->config_ldst = gcmosrc_config_ldst[index];
+		gcmosrc->config.raw = 0;
+		gcmosrc->config.reg.swizzle = srcinfo->format.swizzle;
+		gcmosrc->config.reg.format = srcinfo->format.format;
+
+		gcmosrc->origin_ldst = gcmosrc_origin_ldst[index];
+		gcmosrc->origin.reg.x = srcclipped.left;
+		gcmosrc->origin.reg.y = srcclipped.top;
+
+		gcmosrc->size_ldst = gcmosrc_size_ldst[index];
+		gcmosrc->size.reg = gcregsrcsize_max;
+
+		gcmosrc->rotationheight_ldst
+			= gcmosrc_rotationheight_ldst[index];
+		gcmosrc->rotationheight.reg.height = srcsurfheight;
+
+		gcmosrc->rotationangle_ldst
+			= gcmosrc_rotationangle_ldst[index];
+		gcmosrc->rotationangle.raw = 0;
+		gcmosrc->rotationangle.reg.src = rotencoding[srcinfo->angle];
+		gcmosrc->rotationangle.reg.dst = rotencoding[dstinfo->angle];
+		gcmosrc->rotationangle.reg.src_mirror = srcinfo->mirror;
+		gcmosrc->rotationangle.reg.dst_mirror = GCREG_MIRROR_NONE;
+
+		gcmosrc->rop_ldst = gcmosrc_rop_ldst[index];
+		gcmosrc->rop.raw = 0;
+		gcmosrc->rop.reg.type = GCREG_ROP_TYPE_ROP3;
+		gcmosrc->rop.reg.fg = (unsigned char) srcinfo->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 (srcinfo->format.premultiplied)
+			gcmosrc->mult.reg.srcpremul
+			= GCREG_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_DISABLE;
+		else
+			gcmosrc->mult.reg.srcpremul
+			= GCREG_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_ENABLE;
+
+		if (dstinfo->format.premultiplied) {
+			gcmosrc->mult.reg.dstpremul
+			= GCREG_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_DISABLE;
+
+			gcmosrc->mult.reg.dstdemul
+			= GCREG_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY_DISABLE;
+		} else {
+			gcmosrc->mult.reg.dstpremul
+			= GCREG_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_ENABLE;
+
+			gcmosrc->mult.reg.dstdemul
+			= GCREG_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY_ENABLE;
+		}
+
+		/* Program blending. */
+		bverror = set_blending_index(bvbltparams, batch,
+					     srcinfo, index);
+		if (bverror != BVERR_NONE)
+			goto exit;
+
+		/* Program YUV source. */
+		if (srcinfo->format.type == BVFMT_YUV) {
+			bverror = set_yuvsrc_index(bvbltparams, batch,
+						   srcinfo, srcmap, index);
+			if (bverror != BVERR_NONE)
+				goto exit;
+		}
+	}
+
+	batch->op.blit.srccount += 1;
+
+exit:
+	GCEXITARG(GCZONE_BLIT, "bv%s = %d\n",
+		  (bverror == BVERR_NONE) ? "result" : "error", bverror);
+	return bverror;
+}
diff --git a/bltsville/gcbv/mirror/gcbuffer.c b/bltsville/gcbv/mirror/gcbuffer.c
new file mode 100644
index 0000000..7c77d4a
--- /dev/null
+++ b/bltsville/gcbv/mirror/gcbuffer.c
@@ -0,0 +1,383 @@
+/*
+ * Copyright(c) 2012,
+ * Texas Instruments, Inc. and Vivante Corporation.
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *   * Neither the name of Vivante Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "gcbv.h"
+
+#define GCZONE_NONE		0
+#define GCZONE_ALL		(~0U)
+#define GCZONE_BATCH_ALLOC	(1 << 0)
+#define GCZONE_BUFFER_ALLOC	(1 << 1)
+#define GCZONE_FIXUP_ALLOC	(1 << 2)
+#define GCZONE_FIXUP		(1 << 3)
+
+GCDBG_FILTERDEF(buffer, GCZONE_NONE,
+		"batchalloc",
+		"bufferalloc"
+		"fixupalloc",
+		"fixup")
+
+
+/*******************************************************************************
+** Miscellaneous defines and macros.
+*/
+
+#define GC_BUFFER_INIT_SIZE \
+( \
+	GC_BUFFER_SIZE - max(sizeof(struct gcbuffer), GC_BUFFER_RESERVE) \
+)
+
+#define GC_BUFFER_RESERVE \
+( \
+	sizeof(struct gcmopipesel) + \
+	sizeof(struct gcmommumaster) + \
+	sizeof(struct gcmommuflush) + \
+	sizeof(struct gcmosignal) + \
+	sizeof(struct gccmdend) \
+)
+
+
+/*******************************************************************************
+ * Batch/command buffer management.
+ */
+
+enum bverror do_end(struct bvbltparams *bvbltparams,
+		    struct gcbatch *gcbatch)
+{
+	return BVERR_NONE;
+}
+
+enum bverror allocate_batch(struct bvbltparams *bvbltparams,
+			    struct gcbatch **gcbatch)
+{
+	enum bverror bverror;
+	struct gccontext *gccontext = get_context();
+	struct gcbatch *temp;
+	struct gcbuffer *gcbuffer;
+
+	GCENTER(GCZONE_BATCH_ALLOC);
+
+	/* Lock access to batch management. */
+	GCLOCK(&gccontext->batchlock);
+
+	if (list_empty(&gccontext->batchvac)) {
+		temp = gcalloc(struct gcbatch, sizeof(struct gcbatch));
+		if (temp == NULL) {
+			BVSETBLTERROR(BVERR_OOM,
+				      "batch header allocation failed");
+			goto exit;
+		}
+
+		GCDBG(GCZONE_BATCH_ALLOC, "allocated new batch = 0x%08X\n",
+		      (unsigned int) temp);
+	} else {
+		struct list_head *head;
+		head = gccontext->batchvac.next;
+		temp = list_entry(head, struct gcbatch, link);
+		list_del(head);
+
+		GCDBG(GCZONE_BATCH_ALLOC, "reusing batch = 0x%08X\n",
+		      (unsigned int) temp);
+	}
+
+	memset(temp, 0, sizeof(struct gcbatch));
+	temp->structsize = sizeof(struct gcbatch);
+	temp->batchend = do_end;
+	INIT_LIST_HEAD(&temp->buffer);
+	INIT_LIST_HEAD(&temp->unmap);
+	INIT_LIST_HEAD(&temp->link);
+
+	bverror = append_buffer(bvbltparams, temp, &gcbuffer);
+	if (bverror != BVERR_NONE) {
+		free_batch(temp);
+		goto exit;
+	}
+
+	*gcbatch = temp;
+
+	GCDBG(GCZONE_BATCH_ALLOC, "batch allocated = 0x%08X\n",
+	      (unsigned int) temp);
+
+exit:
+	/* Unlock access to batch management. */
+	GCUNLOCK(&gccontext->batchlock);
+
+	GCEXITARG(GCZONE_BATCH_ALLOC, "bv%s = %d\n",
+		  (bverror == BVERR_NONE) ? "result" : "error", bverror);
+	return bverror;
+}
+
+void free_batch(struct gcbatch *gcbatch)
+{
+	struct list_head *head;
+	struct gccontext *gccontext = get_context();
+	struct gcbuffer *gcbuffer;
+
+	GCENTERARG(GCZONE_BATCH_ALLOC, "batch = 0x%08X\n",
+		   (unsigned int) gcbatch);
+
+	/* Lock access. */
+	GCLOCK(&gccontext->batchlock);
+	GCLOCK(&gccontext->bufferlock);
+	GCLOCK(&gccontext->fixuplock);
+	GCLOCK(&gccontext->maplock);
+
+	/* Free implicit unmappings. */
+	list_splice_init(&gcbatch->unmap, &gccontext->unmapvac);
+
+	/* Free command buffers. */
+	while (!list_empty(&gcbatch->buffer)) {
+		head = gcbatch->buffer.next;
+		gcbuffer = list_entry(head, struct gcbuffer, link);
+
+		/* Free fixups. */
+		list_splice_init(&gcbuffer->fixup, &gccontext->fixupvac);
+
+		/* Free the command buffer. */
+		list_move(&gcbuffer->link, &gccontext->buffervac);
+	}
+
+	/* Free the batch. */
+	list_add(&gcbatch->link, &gccontext->batchvac);
+
+	/* Unlock access. */
+	GCUNLOCK(&gccontext->maplock);
+	GCUNLOCK(&gccontext->fixuplock);
+	GCUNLOCK(&gccontext->bufferlock);
+	GCUNLOCK(&gccontext->batchlock);
+
+	GCEXIT(GCZONE_BATCH_ALLOC);
+}
+
+enum bverror append_buffer(struct bvbltparams *bvbltparams,
+			   struct gcbatch *gcbatch,
+			   struct gcbuffer **gcbuffer)
+{
+	enum bverror bverror;
+	struct gccontext *gccontext = get_context();
+	struct gcbuffer *temp;
+
+	GCENTERARG(GCZONE_BUFFER_ALLOC, "batch = 0x%08X\n",
+		   (unsigned int) gcbatch);
+
+	/* Lock access to buffer management. */
+	GCLOCK(&gccontext->bufferlock);
+
+	if (list_empty(&gccontext->buffervac)) {
+		temp = gcalloc(struct gcbuffer, GC_BUFFER_SIZE);
+		if (temp == NULL) {
+			BVSETBLTERROR(BVERR_OOM,
+				      "command buffer allocation failed");
+			goto exit;
+		}
+
+		list_add_tail(&temp->link, &gcbatch->buffer);
+
+		GCDBG(GCZONE_BUFFER_ALLOC, "allocated new buffer = 0x%08X\n",
+		      (unsigned int) temp);
+	} else {
+		struct list_head *head;
+		head = gccontext->buffervac.next;
+		temp = list_entry(head, struct gcbuffer, link);
+
+		list_move_tail(&temp->link, &gcbatch->buffer);
+
+		GCDBG(GCZONE_BUFFER_ALLOC, "reusing buffer = 0x%08X\n",
+		      (unsigned int) temp);
+	}
+
+	INIT_LIST_HEAD(&temp->fixup);
+	temp->pixelcount = 0;
+	temp->head = temp->tail = (unsigned int *) (temp + 1);
+	temp->available = GC_BUFFER_INIT_SIZE;
+
+	GCDBG(GCZONE_BUFFER_ALLOC, "new buffer appended = 0x%08X\n",
+	      (unsigned int) temp);
+
+	*gcbuffer = temp;
+	bverror = BVERR_NONE;
+
+exit:
+	/* Unlock access to buffer management. */
+	GCUNLOCK(&gccontext->bufferlock);
+
+	GCEXITARG(GCZONE_BUFFER_ALLOC, "bv%s = %d\n",
+		  (bverror == BVERR_NONE) ? "result" : "error", bverror);
+	return bverror;
+}
+
+static enum bverror allocate_fixup(struct bvbltparams *bvbltparams,
+				   struct gcbuffer *gcbuffer,
+				   struct gcfixup **gcfixup)
+{
+	enum bverror bverror = BVERR_NONE;
+	struct gccontext *gccontext = get_context();
+	struct gcfixup *temp;
+
+	if (list_empty(&gccontext->fixupvac)) {
+		temp = gcalloc(struct gcfixup, sizeof(struct gcfixup));
+		if (temp == NULL) {
+			BVSETBLTERROR(BVERR_OOM, "fixup allocation failed");
+			goto exit;
+		}
+
+		list_add_tail(&temp->link, &gcbuffer->fixup);
+
+		GCDBG(GCZONE_FIXUP_ALLOC,
+		      "new fixup struct allocated = 0x%08X\n",
+		      (unsigned int) temp);
+	} else {
+		struct list_head *head;
+		head = gccontext->fixupvac.next;
+		temp = list_entry(head, struct gcfixup, link);
+
+		list_move_tail(&temp->link, &gcbuffer->fixup);
+
+		GCDBG(GCZONE_FIXUP_ALLOC, "fixup struct reused = 0x%08X\n",
+			(unsigned int) temp);
+	}
+
+	temp->count = 0;
+	*gcfixup = temp;
+
+exit:
+	return bverror;
+}
+
+enum bverror add_fixup(struct bvbltparams *bvbltparams,
+		       struct gcbatch *gcbatch,
+		       unsigned int *ptr,
+		       unsigned int surfoffset)
+{
+	enum bverror bverror = BVERR_NONE;
+	struct gccontext *gccontext = get_context();
+	struct list_head *head;
+	struct gcbuffer *buffer;
+	struct gcfixup *gcfixup;
+
+	GCENTERARG(GCZONE_FIXUP, "batch = 0x%08X, fixup ptr = 0x%08X\n",
+		   (unsigned int) gcbatch, (unsigned int) ptr);
+
+	/* Lock access to fixup management. */
+	GCLOCK(&gccontext->fixuplock);
+
+	/* Get the current command buffer. */
+	if (list_empty(&gcbatch->buffer)) {
+		GCERR("no command buffers are allocated");
+		goto exit;
+	}
+	head = gcbatch->buffer.prev;
+	buffer = list_entry(head, struct gcbuffer, link);
+
+	/* No fixups? Allocate one. */
+	if (list_empty(&buffer->fixup)) {
+		GCDBG(GCZONE_FIXUP_ALLOC, "no fixups allocated.\n");
+		bverror = allocate_fixup(bvbltparams, buffer, &gcfixup);
+		if (bverror != BVERR_NONE)
+			goto exit;
+	} else {
+		/* Get the current fixup. */
+		head = buffer->fixup.prev;
+		gcfixup = list_entry(head, struct gcfixup, link);
+
+		/* No more room? */
+		if (gcfixup->count == GC_FIXUP_MAX) {
+			GCDBG(GCZONE_FIXUP_ALLOC,
+			      "out of room, allocating new.\n");
+			bverror = allocate_fixup(bvbltparams, buffer, &gcfixup);
+			if (bverror != BVERR_NONE)
+				goto exit;
+		}
+	}
+
+	GCDBG(GCZONE_FIXUP, "buffer = 0x%08X, fixup struct = 0x%08X\n",
+	      (unsigned int) buffer, (unsigned int) gcfixup);
+
+	gcfixup->fixup[gcfixup->count].dataoffset = ptr - buffer->head;
+	gcfixup->fixup[gcfixup->count].surfoffset = surfoffset;
+	gcfixup->count += 1;
+
+	GCDBG(GCZONE_FIXUP, "fixup offset = 0x%08X\n", ptr - buffer->head);
+	GCDBG(GCZONE_FIXUP, "surface offset = 0x%08X\n", surfoffset);
+
+exit:
+	/* Unlock access to fixup management. */
+	GCUNLOCK(&gccontext->fixuplock);
+
+	GCEXITARG(GCZONE_FIXUP, "bv%s = %d\n",
+		  (bverror == BVERR_NONE) ? "result" : "error", bverror);
+	return bverror;
+}
+
+enum bverror claim_buffer(struct bvbltparams *bvbltparams,
+			  struct gcbatch *gcbatch,
+			  unsigned int size,
+			  void **buffer)
+{
+	enum bverror bverror;
+	struct list_head *head;
+	struct gcbuffer *gcbuffer;
+
+	GCENTERARG(GCZONE_BUFFER_ALLOC, "batch = 0x%08X, size = %d\n",
+		   (unsigned int) gcbatch, size);
+
+	if (size > GC_BUFFER_INIT_SIZE) {
+		GCERR("requested size is too big.\n");
+		BVSETBLTERROR(BVERR_OOM,
+			      "command buffer allocation failed");
+		goto exit;
+	}
+
+	/* Get the current command buffer. */
+	head = gcbatch->buffer.prev;
+	gcbuffer = list_entry(head, struct gcbuffer, link);
+
+	GCDBG(GCZONE_BUFFER_ALLOC, "buffer = 0x%08X, available = %d\n",
+	      (unsigned int) gcbuffer, gcbuffer->available);
+
+	if (gcbuffer->available < size) {
+		bverror = append_buffer(bvbltparams, gcbatch, &gcbuffer);
+		if (bverror != BVERR_NONE)
+			goto exit;
+	}
+
+	*buffer = gcbuffer->tail;
+	gcbuffer->tail = (unsigned int *)
+			((unsigned char *) gcbuffer->tail + size);
+	gcbuffer->available -= size;
+	gcbatch->size += size;
+	bverror = BVERR_NONE;
+
+exit:
+	GCEXITARG(GCZONE_BUFFER_ALLOC, "bv%s = %d\n",
+		  (bverror == BVERR_NONE) ? "result" : "error", bverror);
+	return bverror;
+}
diff --git a/bltsville/gcbv/mirror/gcbv.c b/bltsville/gcbv/mirror/gcbv.c
new file mode 100644
index 0000000..86d656e
--- /dev/null
+++ b/bltsville/gcbv/mirror/gcbv.c
@@ -0,0 +1,2008 @@
+/*
+ * Copyright(c) 2012,
+ * Texas Instruments, Inc. and Vivante Corporation.
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *   * Neither the name of Vivante Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "gcbv.h"
+
+#define GCZONE_NONE		0
+#define GCZONE_ALL		(~0U)
+#define GCZONE_MAPPING		(1 << 0)
+#define GCZONE_BUFFER		(1 << 1)
+#define GCZONE_DEST		(1 << 2)
+#define GCZONE_SRC		(1 << 3)
+#define GCZONE_MASK		(1 << 4)
+#define GCZONE_BATCH		(1 << 5)
+#define GCZONE_BLIT		(1 << 6)
+#define GCZONE_CACHE		(1 << 7)
+#define GCZONE_CALLBACK		(1 << 8)
+#define GCZONE_TEMP		(1 << 9)
+#define GCZONE_BLEND		(1 << 10)
+
+GCDBG_FILTERDEF(bv, GCZONE_NONE,
+		"mapping",
+		"buffer",
+		"dest",
+		"source",
+		"mask",
+		"batch",
+		"blit",
+		"cache",
+		"callback",
+		"tempbuffer",
+		"blending")
+
+
+/*******************************************************************************
+** Global driver data access.
+*/
+
+struct gccontext *get_context(void)
+{
+	static struct gccontext gccontext;
+	return &gccontext;
+}
+
+
+/*******************************************************************************
+ * Debugging.
+ */
+
+#if GCDEBUG_ENABLE
+#define GCDUMPBATCH(batch) \
+	dumpbatch(batch)
+
+#define GCVERIFYBATCH(changeflags, prevrect, currrect) \
+	verify_batch(changeflags, prevrect, currrect)
+
+static void dumpbatch(struct gcbatch *gcbatch)
+{
+	struct list_head *gcbufferhead;
+	struct gcbuffer *gcbuffer;
+	struct list_head *gcfixuphead;
+	struct gcfixup *gcfixup;
+	unsigned int i, size;
+
+	if ((GCDBGFILTER.zone & (GCZONE_BUFFER)) == 0)
+		return;
+
+	GCDBG(GCZONE_BUFFER, "BATCH DUMP (0x%08X)\n",
+		(unsigned int) gcbatch);
+
+	list_for_each(gcbufferhead, &gcbatch->buffer) {
+		gcbuffer = list_entry(gcbufferhead, struct gcbuffer, link);
+
+		list_for_each(gcfixuphead, &gcbuffer->fixup) {
+			gcfixup = list_entry(gcfixuphead, struct gcfixup, link);
+
+			GCDBG(GCZONE_BUFFER,
+				"  Fixup table @ 0x%08X, count = %d:\n",
+				(unsigned int) gcfixup, gcfixup->count);
+
+			for (i = 0; i < gcfixup->count; i += 1) {
+				GCDBG(GCZONE_BUFFER, "  [%02d]"
+					" buffer offset = 0x%08X,"
+					" surface offset = 0x%08X\n",
+					i,
+					gcfixup->fixup[i].dataoffset * 4,
+					gcfixup->fixup[i].surfoffset);
+			}
+		}
+
+		size = (unsigned char *) gcbuffer->tail
+		     - (unsigned char *) gcbuffer->head;
+		GCDUMPBUFFER(GCZONE_BUFFER, gcbuffer->head, 0, size);
+	}
+}
+
+static void verify_batch(unsigned int changeflags,
+				struct bvrect *prevrect,
+				struct bvrect *currrect)
+{
+	if ((changeflags & 1) == 0) {
+		/* Origin did not change. */
+		if ((prevrect->left != currrect->left) ||
+			(prevrect->top != currrect->top)) {
+			GCERR("origin changed\n");
+			GCERR("  previous = %d,%d\n",
+				prevrect->left, prevrect->top);
+			GCERR("  current = %d,%d\n",
+				currrect->left, currrect->top);
+		}
+	}
+
+	if ((changeflags & 2) == 0) {
+		/* Size did not change. */
+		if ((prevrect->width != currrect->width) ||
+			(prevrect->height != currrect->height)) {
+			GCERR("size changed\n");
+			GCERR("  previous = %dx%d\n",
+				prevrect->width, prevrect->height);
+			GCERR("  current = %dx%d\n",
+				currrect->width, currrect->height);
+		}
+	}
+
+	prevrect->left = currrect->left;
+	prevrect->top = currrect->top;
+	prevrect->width = currrect->width;
+	prevrect->height = currrect->height;
+}
+#else
+#define GCDUMPBATCH(...)
+#define GCVERIFYBATCH(...)
+#endif
+
+
+/*******************************************************************************
+ * Error handling.
+ */
+
+#define BVSETBLTSURFERROR(errorid, errordesc) \
+do { \
+	struct gccontext *tmpcontext = get_context(); \
+	snprintf(tmpcontext->bverrorstr, sizeof(tmpcontext->bverrorstr), \
+		 g_surferr[errorid].message, errordesc.id); \
+	GCDUMPSTRING("%s(%d): [ERROR] %s\n", __func__, __LINE__, \
+		     tmpcontext->bverrorstr); \
+	bverror = errordesc.base + g_surferr[errorid].offset; \
+	bvbltparams->errdesc = tmpcontext->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 desc structure is not set" },
+
+	/* GCBVERR_DESC_VERS */
+	{  100, "%s desc structure has invalid size" },
+
+	/* GCBVERR_DESC_VIRTADDR */
+	{  200, "%s desc virtual pointer is not set" },
+
+	/* GCBVERR_TILE: FIXME/TODO define error code */
+	{    0, "%s tileparams structure is not set" },
+
+	/* GCBVERR_TILE_VERS */
+	{ 3000, "%s tileparams structure has invalid size" },
+
+	/* GCBVERR_TILE_VIRTADDR: FIXME/TODO define error code */
+	{  200, "%s tileparams virtual pointer is not set" },
+
+	/* GCBVERR_GEOM */
+	{ 1000, "%s geom structure is not set" },
+
+	/* GCBVERR_GEOM_VERS */
+	{ 1100, "%s geom structure has invalid size" },
+
+	/* GCBVERR_GEOM_FORMAT */
+	{ 1200, "%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.
+ */
+
+/* BLTsville callback function. */
+struct gccallbackbltsville {
+	/* Function pointer. */
+	void (*fn) (struct bvcallbackerror *err, unsigned long callbackdata);
+
+	/* Callback data. */
+	unsigned long data;
+};
+
+/* Information for freeing a surface. */
+struct gccallbackfreesurface {
+	/* Pointer to the buffer descriptor. */
+	struct bvbuffdesc *desc;
+
+	/* Pointer to the buffer. */
+	void *ptr;
+};
+
+/* Callback information. */
+struct gccallbackinfo {
+	union {
+		/* BLTsville callback function. */
+		struct gccallbackbltsville callback;
+
+		/* Information for freeing a surface. */
+		struct gccallbackfreesurface freesurface;
+	} info;
+
+	/* Previous/next callback information. */
+	struct list_head link;
+};
+
+static enum bverror get_callbackinfo(struct gccallbackinfo **gccallbackinfo)
+{
+	enum bverror bverror;
+	struct gccontext *gccontext = get_context();
+	struct gccallbackinfo *temp;
+
+	/* Lock access to callback info lists. */
+	GCLOCK(&gccontext->callbacklock);
+
+	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)
+{
+	struct gccontext *gccontext = get_context();
+
+	/* 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 callbackbltsville(void *callbackinfo)
+{
+	struct gccallbackinfo *gccallbackinfo;
+
+	GCENTER(GCZONE_CALLBACK);
+
+	gccallbackinfo = (struct gccallbackinfo *) callbackinfo;
+	GCDBG(GCZONE_CALLBACK, "bltsville_callback = 0x%08X\n",
+	      (unsigned int) gccallbackinfo->info.callback.fn);
+	GCDBG(GCZONE_CALLBACK, "bltsville_param    = 0x%08X\n",
+	      (unsigned int) gccallbackinfo->info.callback.data);
+
+	gccallbackinfo->info.callback.fn(NULL,
+					 gccallbackinfo->info.callback.data);
+	free_callback(gccallbackinfo);
+
+	GCEXIT(GCZONE_CALLBACK);
+}
+
+void callbackfreesurface(void *callbackinfo)
+{
+	struct gccallbackinfo *gccallbackinfo;
+
+	GCENTER(GCZONE_CALLBACK);
+
+	gccallbackinfo = (struct gccallbackinfo *) callbackinfo;
+	GCDBG(GCZONE_CALLBACK, "freeing descriptir @ 0x%08X\n",
+	      (unsigned int) gccallbackinfo->info.freesurface.desc);
+	GCDBG(GCZONE_CALLBACK, "freeing memory @ 0x%08X\n",
+	      (unsigned int) gccallbackinfo->info.freesurface.ptr);
+
+	free_surface(gccallbackinfo->info.freesurface.desc,
+		     gccallbackinfo->info.freesurface.ptr);
+	free_callback(gccallbackinfo);
+
+	GCEXIT(GCZONE_CALLBACK);
+}
+
+
+/*******************************************************************************
+ * Temporary buffer management.
+ */
+
+enum bverror allocate_temp(struct bvbltparams *bvbltparams,
+			   unsigned int size)
+{
+	enum bverror bverror;
+	struct gccontext *gccontext = get_context();
+
+	GCENTER(GCZONE_TEMP);
+
+	/* Existing buffer too small? */
+	if ((gccontext->tmpbuffdesc != NULL) &&
+	    (gccontext->tmpbuffdesc->length < size)) {
+		GCDBG(GCZONE_TEMP, "freeing current buffer.\n");
+		bverror = free_temp(true);
+		if (bverror != BVERR_NONE) {
+			bvbltparams->errdesc = gccontext->bverrorstr;
+			goto exit;
+		}
+	}
+
+	/* Allocate new buffer if necessary. */
+	if ((size > 0) && (gccontext->tmpbuffdesc == NULL)) {
+		/* Allocate temporary surface. */
+		bverror = allocate_surface(&gccontext->tmpbuffdesc,
+					   &gccontext->tmpbuff,
+					   size);
+		if (bverror != BVERR_NONE) {
+			bvbltparams->errdesc = gccontext->bverrorstr;
+			goto exit;
+		}
+
+		GCDBG(GCZONE_TEMP, "buffdesc @ 0x%08X\n",
+		      gccontext->tmpbuffdesc);
+		GCDBG(GCZONE_TEMP, "allocated @ 0x%08X\n",
+		      gccontext->tmpbuff);
+		GCDBG(GCZONE_TEMP, "size = %d\n",
+		      size);
+
+		/* Map the buffer explicitly. */
+		bverror = bv_map(gccontext->tmpbuffdesc);
+		if (bverror != BVERR_NONE) {
+			bvbltparams->errdesc = gccontext->bverrorstr;
+			goto exit;
+		}
+	}
+
+	/* Success. */
+	bverror = BVERR_NONE;
+
+exit:
+	GCEXIT(GCZONE_TEMP);
+	return bverror;
+}
+
+enum bverror free_temp(bool schedule)
+{
+	enum bverror bverror;
+	struct gccontext *gccontext = get_context();
+	struct gccallbackinfo *gccallbackinfo;
+	struct gcicallbackarm gcicallbackarm;
+
+	/* Is the buffer allocated? */
+	if (gccontext->tmpbuffdesc == NULL) {
+		bverror = BVERR_NONE;
+		goto exit;
+	}
+
+	/* Unmap the buffer. */
+	bverror = bv_unmap(gccontext->tmpbuffdesc);
+	if (bverror != BVERR_NONE)
+		goto exit;
+
+	/* Cannot be mapped. */
+	if (gccontext->tmpbuffdesc->map != NULL) {
+		BVSETERROR(BVERR_OOM, "temporary buffer is still mapped");
+		goto exit;
+	}
+
+	/* Free the buffer. */
+	if (schedule) {
+		bverror = get_callbackinfo(&gccallbackinfo);
+		if (bverror != BVERR_NONE) {
+			BVSETERROR(BVERR_OOM,
+				   "callback allocation failed");
+			goto exit;
+		}
+
+		gccallbackinfo->info.freesurface.desc = gccontext->tmpbuffdesc;
+		gccallbackinfo->info.freesurface.ptr = gccontext->tmpbuff;
+		gcicallbackarm.callback = callbackfreesurface;
+		gcicallbackarm.callbackparam = gccallbackinfo;
+
+		/* Schedule to free the buffer. */
+		gc_callback_wrapper(&gcicallbackarm);
+
+		/* Error? */
+		if (gcicallbackarm.gcerror != GCERR_NONE) {
+			BVSETERROR(BVERR_OOM, "unable to schedule callback");
+			goto exit;
+		}
+	} else {
+		/* Free the buffer immediately. */
+		free_surface(gccontext->tmpbuffdesc, gccontext->tmpbuff);
+	}
+
+	/* Reset the buffer descriptor. */
+	gccontext->tmpbuffdesc = NULL;
+	gccontext->tmpbuff = NULL;
+
+exit:
+	return bverror;
+}
+
+
+/*******************************************************************************
+ * Program the destination.
+ */
+
+enum bverror set_dst(struct bvbltparams *bvbltparams,
+		     struct gcbatch *batch,
+		     struct bvbuffmap *dstmap)
+{
+	enum bverror bverror = BVERR_NONE;
+	struct gcmodst *gcmodst;
+
+	GCENTER(GCZONE_DEST);
+
+	/* Did destination surface change? */
+	if ((batch->batchflags & BVBATCH_DST) != 0) {
+		/* Allocate command buffer. */
+		bverror = claim_buffer(bvbltparams, batch,
+				       sizeof(struct gcmodst),
+				       (void **) &gcmodst);
+		if (bverror != BVERR_NONE)
+			goto exit;
+
+		/* Add the address fixup. */
+		add_fixup(bvbltparams, batch, &gcmodst->address,
+			  batch->dstbyteshift);
+
+		/* Set surface parameters. */
+		gcmodst->config_ldst = gcmodst_config_ldst;
+		gcmodst->address = GET_MAP_HANDLE(dstmap);
+		gcmodst->stride = bvbltparams->dstgeom->virtstride;
+
+		/* Set surface width and height. */
+		gcmodst->rotation.raw = 0;
+		gcmodst->rotation.reg.surf_width = batch->dstphyswidth;
+		gcmodst->rotationheight_ldst = gcmodst_rotationheight_ldst;
+		gcmodst->rotationheight.raw = 0;
+		gcmodst->rotationheight.reg.height = batch->dstphysheight;
+
+		/* Disable hardware clipping. */
+		gcmodst->clip_ldst = gcmodst_clip_ldst;
+		gcmodst->cliplt.raw = 0;
+		gcmodst->cliprb.raw = 0;
+		gcmodst->cliprb.reg.right = GC_CLIP_RESET_RIGHT;
+		gcmodst->cliprb.reg.bottom = GC_CLIP_RESET_BOTTOM;
+	}
+
+exit:
+	GCEXITARG(GCZONE_DEST, "bv%s = %d\n",
+		  (bverror == BVERR_NONE) ? "result" : "error", bverror);
+	return bverror;
+}
+
+/*******************************************************************************
+ * Program blending.
+ */
+
+enum bverror set_blending(struct bvbltparams *bvbltparams,
+			  struct gcbatch *batch,
+			  struct surfaceinfo *srcinfo)
+{
+	enum bverror bverror = BVERR_NONE;
+	struct gcmoalphaoff *gcmoalphaoff;
+	struct gcmoalpha *gcmoalpha;
+	struct gcmoglobal *gcmoglobal;
+	struct gcalpha *gca;
+
+	GCENTER(GCZONE_BLEND);
+
+	gca = srcinfo->gca;
+	if (gca == NULL) {
+		bverror = claim_buffer(bvbltparams, batch,
+				       sizeof(struct gcmoalphaoff),
+				       (void **) &gcmoalphaoff);
+		if (bverror != BVERR_NONE)
+			goto exit;
+
+		gcmoalphaoff->control_ldst = gcmoalphaoff_control_ldst[0];
+		gcmoalphaoff->control.reg = gcregalpha_off;
+
+		GCDBG(GCZONE_BLEND, "blending disabled.\n");
+	} else {
+		bverror = claim_buffer(bvbltparams, batch,
+				       sizeof(struct gcmoalpha),
+				       (void **) &gcmoalpha);
+		if (bverror != BVERR_NONE)
+			goto exit;
+
+		gcmoalpha->config_ldst = gcmoalpha_config_ldst;
+		gcmoalpha->control.reg = gcregalpha_on;
+
+		gcmoalpha->mode.raw = 0;
+		gcmoalpha->mode.reg.src_global_alpha_mode
+			= gca->src_global_alpha_mode;
+		gcmoalpha->mode.reg.dst_global_alpha_mode
+			= gca->dst_global_alpha_mode;
+
+		gcmoalpha->mode.reg.src_blend
+			= gca->srcconfig->factor_mode;
+		gcmoalpha->mode.reg.src_color_reverse
+			= gca->srcconfig->color_reverse;
+
+		gcmoalpha->mode.reg.dst_blend
+			= gca->dstconfig->factor_mode;
+		gcmoalpha->mode.reg.dst_color_reverse
+			= gca->dstconfig->color_reverse;
+
+		GCDBG(GCZONE_BLEND, "dst blend:\n");
+		GCDBG(GCZONE_BLEND, "  factor = %d\n",
+			gcmoalpha->mode.reg.dst_blend);
+		GCDBG(GCZONE_BLEND, "  inverse = %d\n",
+			gcmoalpha->mode.reg.dst_color_reverse);
+
+		GCDBG(GCZONE_BLEND, "src blend:\n");
+		GCDBG(GCZONE_BLEND, "  factor = %d\n",
+			gcmoalpha->mode.reg.src_blend);
+		GCDBG(GCZONE_BLEND, "  inverse = %d\n",
+			gcmoalpha->mode.reg.src_color_reverse);
+
+		if ((gca->src_global_alpha_mode
+			!= GCREG_GLOBAL_ALPHA_MODE_NORMAL) ||
+		    (gca->dst_global_alpha_mode
+			!= GCREG_GLOBAL_ALPHA_MODE_NORMAL)) {
+			bverror = claim_buffer(bvbltparams, batch,
+					       sizeof(struct gcmoglobal),
+					       (void **) &gcmoglobal);
+			if (bverror != BVERR_NONE)
+				goto exit;
+
+			gcmoglobal->color_ldst = gcmoglobal_color_ldst;
+			gcmoglobal->srcglobal.raw = gca->src_global_color;
+			gcmoglobal->dstglobal.raw = gca->dst_global_color;
+		}
+	}
+
+exit:
+	GCEXITARG(GCZONE_BLEND, "bv%s = %d\n",
+		  (bverror == BVERR_NONE) ? "result" : "error", bverror);
+	return bverror;
+}
+
+enum bverror set_blending_index(struct bvbltparams *bvbltparams,
+				struct gcbatch *batch,
+				struct surfaceinfo *srcinfo,
+				unsigned int index)
+{
+	enum bverror bverror = BVERR_NONE;
+	struct gcmoalphaoff *gcmoalphaoff;
+	struct gcmoxsrcalpha *gcmoxsrcalpha;
+	struct gcmoxsrcglobal *gcmoxsrcglobal;
+	struct gcalpha *gca;
+
+	GCENTER(GCZONE_BLEND);
+
+	gca = srcinfo->gca;
+	if (gca == NULL) {
+		bverror = claim_buffer(bvbltparams, batch,
+				       sizeof(struct gcmoalphaoff),
+				       (void **) &gcmoalphaoff);
+		if (bverror != BVERR_NONE)
+			goto exit;
+
+		gcmoalphaoff->control_ldst = gcmoalphaoff_control_ldst[index];
+		gcmoalphaoff->control.reg = gcregalpha_off;
+
+		GCDBG(GCZONE_BLEND, "blending disabled.\n");
+	} else {
+		bverror = claim_buffer(bvbltparams, batch,
+				       sizeof(struct gcmoxsrcalpha),
+				       (void **) &gcmoxsrcalpha);
+		if (bverror != BVERR_NONE)
+			goto exit;
+
+		gcmoxsrcalpha->control_ldst = gcmoxsrcalpha_control_ldst[index];
+		gcmoxsrcalpha->control.reg = gcregalpha_on;
+
+		gcmoxsrcalpha->mode_ldst = gcmoxsrcalpha_mode_ldst[index];
+		gcmoxsrcalpha->mode.raw = 0;
+		gcmoxsrcalpha->mode.reg.src_global_alpha_mode
+			= gca->src_global_alpha_mode;
+		gcmoxsrcalpha->mode.reg.dst_global_alpha_mode
+			= gca->dst_global_alpha_mode;
+
+		gcmoxsrcalpha->mode.reg.src_blend
+			= gca->srcconfig->factor_mode;
+		gcmoxsrcalpha->mode.reg.src_color_reverse
+			= gca->srcconfig->color_reverse;
+
+		gcmoxsrcalpha->mode.reg.dst_blend
+			= gca->dstconfig->factor_mode;
+		gcmoxsrcalpha->mode.reg.dst_color_reverse
+			= gca->dstconfig->color_reverse;
+
+		GCDBG(GCZONE_BLEND, "dst blend:\n");
+		GCDBG(GCZONE_BLEND, "  factor = %d\n",
+			gcmoxsrcalpha->mode.reg.dst_blend);
+		GCDBG(GCZONE_BLEND, "  inverse = %d\n",
+			gcmoxsrcalpha->mode.reg.dst_color_reverse);
+
+		GCDBG(GCZONE_BLEND, "src blend:\n");
+		GCDBG(GCZONE_BLEND, "  factor = %d\n",
+			gcmoxsrcalpha->mode.reg.src_blend);
+		GCDBG(GCZONE_BLEND, "  inverse = %d\n",
+			gcmoxsrcalpha->mode.reg.src_color_reverse);
+
+		if ((gca->src_global_alpha_mode
+			!= GCREG_GLOBAL_ALPHA_MODE_NORMAL) ||
+		    (gca->dst_global_alpha_mode
+			!= GCREG_GLOBAL_ALPHA_MODE_NORMAL)) {
+			bverror = claim_buffer(bvbltparams, batch,
+					       sizeof(struct gcmoxsrcglobal),
+					       (void **) &gcmoxsrcglobal);
+			if (bverror != BVERR_NONE)
+				goto exit;
+
+			gcmoxsrcglobal->srcglobal_ldst
+				= gcmoxsrcglobal_srcglobal_ldst[index];
+			gcmoxsrcglobal->srcglobal.raw = gca->src_global_color;
+
+			gcmoxsrcglobal->dstglobal_ldst
+				= gcmoxsrcglobal_dstglobal_ldst[index];
+			gcmoxsrcglobal->dstglobal.raw = gca->dst_global_color;
+		}
+	}
+
+exit:
+	GCEXITARG(GCZONE_BLEND, "bv%s = %d\n",
+		  (bverror == BVERR_NONE) ? "result" : "error", bverror);
+	return bverror;
+}
+
+/*******************************************************************************
+ * Program YUV source.
+ */
+
+void set_computeyuv(struct surfaceinfo *srcinfo, int x, int y)
+{
+	int pixalign, bytealign;
+	unsigned int height1, size1;
+	unsigned int height2, size2;
+	unsigned int origin;
+	int ssX, ssY;
+
+	GCENTER(GCZONE_SRC);
+
+	/* Compute base address alignment. */
+	pixalign = get_pixel_offset(srcinfo, 0);
+	bytealign = (pixalign * (int) srcinfo->format.bitspp) / 8;
+
+	/* Determine the physical height of the first plane. */
+	height1 = ((srcinfo->angle % 2) == 0)
+		? srcinfo->geom->height
+		: srcinfo->geom->width;
+
+	/* Determine the size of the first plane. */
+	size1 = srcinfo->geom->virtstride * height1;
+
+	/* Determine the stride of the second plane. */
+	srcinfo->stride2 = srcinfo->geom->virtstride
+			 / srcinfo->format.cs.yuv.xsample;
+
+	/* Determine subsample pixel position. */
+	ssX = x / srcinfo->format.cs.yuv.xsample;
+	ssY = y / srcinfo->format.cs.yuv.ysample;
+
+	switch (srcinfo->format.cs.yuv.planecount) {
+	case 2:
+		/* U and V are interleaved in one plane. */
+		ssX *= 2;
+		srcinfo->stride2 *= 2;
+
+		/* Determnine the origin offset. */
+		origin = ssY * srcinfo->stride2 + ssX;
+
+		/* Compute the alignment of the second plane. */
+		srcinfo->bytealign2 = bytealign + size1 + origin;
+
+		GCDBG(GCZONE_SRC, "plane2 offset (bytes) = 0x%08X\n",
+			srcinfo->bytealign2);
+		GCDBG(GCZONE_SRC, "plane2 stride = %d\n",
+			srcinfo->stride2);
+		break;
+
+	case 3:
+		/* Determine the physical height of the U/V planes. */
+		height2 = height1 / srcinfo->format.cs.yuv.ysample;
+
+		/* Determine the size of the U/V planes. */
+		size2 = srcinfo->stride2 * height2;
+
+		/* Determnine the origin offset. */
+		origin = ssY * srcinfo->stride2 + ssX;
+
+		/* Compute the alignment of the U/V planes. */
+		srcinfo->bytealign2 = bytealign + size1 + origin;
+		srcinfo->bytealign3 = bytealign + size1 + size2 + origin;
+
+		/* Determine the stride of the U/V planes. */
+		srcinfo->stride3 = srcinfo->stride2;
+
+		GCDBG(GCZONE_SRC, "plane2 offset (bytes) = 0x%08X\n",
+		      srcinfo->bytealign2);
+		GCDBG(GCZONE_SRC, "plane2 stride = %d\n",
+			srcinfo->stride2);
+		GCDBG(GCZONE_SRC, "plane3 offset (bytes) = 0x%08X\n",
+		      srcinfo->bytealign3);
+		GCDBG(GCZONE_SRC, "plane3 stride = %d\n",
+			srcinfo->stride3);
+		break;
+	}
+
+	GCEXIT(GCZONE_SRC);
+}
+
+enum bverror set_yuvsrc(struct bvbltparams *bvbltparams,
+			struct gcbatch *batch,
+			struct surfaceinfo *srcinfo,
+			struct bvbuffmap *srcmap)
+{
+	enum bverror bverror = BVERR_NONE;
+	struct gcmoyuv1 *gcmoyuv1;
+	struct gcmoyuv2 *gcmoyuv2;
+	struct gcmoyuv3 *gcmoyuv3;
+
+	GCENTER(GCZONE_SRC);
+
+	GCDBG(GCZONE_SRC, "plane count %d.\n",
+	      srcinfo->format.cs.yuv.planecount);
+
+	switch (srcinfo->format.cs.yuv.planecount) {
+	case 1:
+		bverror = claim_buffer(bvbltparams, batch,
+				       sizeof(struct gcmoyuv1),
+				       (void **) &gcmoyuv1);
+		if (bverror != BVERR_NONE)
+			goto exit;
+
+		/* Set YUV parameters. */
+		gcmoyuv1->pectrl_ldst = gcmoyuv_pectrl_ldst;
+		gcmoyuv1->pectrl.raw = 0;
+		gcmoyuv1->pectrl.reg.standard
+			= srcinfo->format.cs.yuv.std;
+		gcmoyuv1->pectrl.reg.swizzle
+			= srcinfo->format.swizzle;
+		gcmoyuv1->pectrl.reg.convert
+			= GCREG_PE_CONTROL_YUVRGB_DISABLED;
+		break;
+
+	case 2:
+		bverror = claim_buffer(bvbltparams, batch,
+					sizeof(struct gcmoyuv2),
+					(void **) &gcmoyuv2);
+		if (bverror != BVERR_NONE)
+			goto exit;
+
+		/* Set YUV parameters. */
+		gcmoyuv2->pectrl_ldst = gcmoyuv_pectrl_ldst;
+		gcmoyuv2->pectrl.raw = 0;
+		gcmoyuv2->pectrl.reg.standard
+			= srcinfo->format.cs.yuv.std;
+		gcmoyuv2->pectrl.reg.swizzle
+			= srcinfo->format.swizzle;
+		gcmoyuv2->pectrl.reg.convert
+			= GCREG_PE_CONTROL_YUVRGB_DISABLED;
+
+		/* Program U/V plane. */
+		add_fixup(bvbltparams, batch, &gcmoyuv2->uplaneaddress,
+			  srcinfo->bytealign2);
+		gcmoyuv2->plane_ldst = gcmoyuv2_plane_ldst;
+		gcmoyuv2->uplaneaddress = GET_MAP_HANDLE(srcmap);
+		gcmoyuv2->uplanestride = srcinfo->stride2;
+		break;
+
+	case 3:
+		bverror = claim_buffer(bvbltparams, batch,
+					sizeof(struct gcmoyuv3),
+					(void **) &gcmoyuv3);
+		if (bverror != BVERR_NONE)
+			goto exit;
+
+		/* Set YUV parameters. */
+		gcmoyuv3->pectrl_ldst = gcmoyuv_pectrl_ldst;
+		gcmoyuv3->pectrl.raw = 0;
+		gcmoyuv3->pectrl.reg.standard
+			= srcinfo->format.cs.yuv.std;
+		gcmoyuv3->pectrl.reg.swizzle
+			= srcinfo->format.swizzle;
+		gcmoyuv3->pectrl.reg.convert
+			= GCREG_PE_CONTROL_YUVRGB_DISABLED;
+
+		/* Program U/V planes. */
+		add_fixup(bvbltparams, batch, &gcmoyuv3->uplaneaddress,
+			  srcinfo->bytealign2);
+		add_fixup(bvbltparams, batch, &gcmoyuv3->vplaneaddress,
+			  srcinfo->bytealign3);
+		gcmoyuv3->plane_ldst = gcmoyuv3_plane_ldst;
+		gcmoyuv3->uplaneaddress = GET_MAP_HANDLE(srcmap);
+		gcmoyuv3->uplanestride  = srcinfo->stride2;
+		gcmoyuv3->vplaneaddress = GET_MAP_HANDLE(srcmap);
+		gcmoyuv3->vplanestride  = srcinfo->stride3;
+		break;
+
+	default:
+		GCERR("invlaid plane count %d.\n",
+		      srcinfo->format.cs.yuv.planecount);
+	}
+
+exit:
+	GCEXITARG(GCZONE_SRC, "bv%s = %d\n",
+		  (bverror == BVERR_NONE) ? "result" : "error", bverror);
+	return bverror;
+}
+
+enum bverror set_yuvsrc_index(struct bvbltparams *bvbltparams,
+			      struct gcbatch *batch,
+			      struct surfaceinfo *srcinfo,
+			      struct bvbuffmap *srcmap,
+			      unsigned int index)
+{
+	enum bverror bverror = BVERR_NONE;
+	struct gcmoxsrcyuv1 *gcmoxsrcyuv1;
+	struct gcmoxsrcyuv2 *gcmoxsrcyuv2;
+	struct gcmoxsrcyuv3 *gcmoxsrcyuv3;
+
+	GCENTER(GCZONE_SRC);
+
+	GCDBG(GCZONE_SRC, "plane count %d.\n",
+	      srcinfo->format.cs.yuv.planecount);
+
+	switch (srcinfo->format.cs.yuv.planecount) {
+	case 1:
+		bverror = claim_buffer(bvbltparams, batch,
+				       sizeof(struct gcmoxsrcyuv1),
+				       (void **) &gcmoxsrcyuv1);
+		if (bverror != BVERR_NONE)
+			goto exit;
+
+		/* Set YUV parameters. */
+		gcmoxsrcyuv1->pectrl_ldst
+			= gcmoxsrcyuv_pectrl_ldst[index];
+		gcmoxsrcyuv1->pectrl.raw = 0;
+		gcmoxsrcyuv1->pectrl.reg.standard
+			= srcinfo->format.cs.yuv.std;
+		gcmoxsrcyuv1->pectrl.reg.swizzle
+			= srcinfo->format.swizzle;
+		gcmoxsrcyuv1->pectrl.reg.convert
+			= GCREG_PE_CONTROL_YUVRGB_DISABLED;
+		break;
+
+	case 2:
+		bverror = claim_buffer(bvbltparams, batch,
+					sizeof(struct gcmoxsrcyuv2),
+					(void **) &gcmoxsrcyuv2);
+		if (bverror != BVERR_NONE)
+			goto exit;
+
+		/* Set YUV parameters. */
+		gcmoxsrcyuv2->pectrl_ldst
+			= gcmoxsrcyuv_pectrl_ldst[index];
+		gcmoxsrcyuv2->pectrl.raw = 0;
+		gcmoxsrcyuv2->pectrl.reg.standard
+			= srcinfo->format.cs.yuv.std;
+		gcmoxsrcyuv2->pectrl.reg.swizzle
+			= srcinfo->format.swizzle;
+		gcmoxsrcyuv2->pectrl.reg.convert
+			= GCREG_PE_CONTROL_YUVRGB_DISABLED;
+
+		/* Program U/V plane. */
+		add_fixup(bvbltparams, batch, &gcmoxsrcyuv2->uplaneaddress,
+			  srcinfo->bytealign2);
+		gcmoxsrcyuv2->uplaneaddress_ldst
+			= gcmoxsrcyuv_uplaneaddress_ldst[index];
+		gcmoxsrcyuv2->uplaneaddress = GET_MAP_HANDLE(srcmap);
+		gcmoxsrcyuv2->uplanestride_ldst
+			= gcmoxsrcyuv_uplanestride_ldst[index];
+		gcmoxsrcyuv2->uplanestride = srcinfo->stride2;
+		break;
+
+	case 3:
+		bverror = claim_buffer(bvbltparams, batch,
+					sizeof(struct gcmoxsrcyuv3),
+					(void **) &gcmoxsrcyuv3);
+		if (bverror != BVERR_NONE)
+			goto exit;
+
+		/* Set YUV parameters. */
+		gcmoxsrcyuv3->pectrl_ldst
+			= gcmoxsrcyuv_pectrl_ldst[index];
+		gcmoxsrcyuv3->pectrl.raw = 0;
+		gcmoxsrcyuv3->pectrl.reg.standard
+			= srcinfo->format.cs.yuv.std;
+		gcmoxsrcyuv3->pectrl.reg.swizzle
+			= srcinfo->format.swizzle;
+		gcmoxsrcyuv3->pectrl.reg.convert
+			= GCREG_PE_CONTROL_YUVRGB_DISABLED;
+
+		/* Program U/V planes. */
+		add_fixup(bvbltparams, batch, &gcmoxsrcyuv3->uplaneaddress,
+			  srcinfo->bytealign2);
+		add_fixup(bvbltparams, batch, &gcmoxsrcyuv3->vplaneaddress,
+			  srcinfo->bytealign3);
+		gcmoxsrcyuv3->uplaneaddress_ldst
+			= gcmoxsrcyuv_uplaneaddress_ldst[index];
+		gcmoxsrcyuv3->uplaneaddress = GET_MAP_HANDLE(srcmap);
+		gcmoxsrcyuv3->uplanestride_ldst
+			= gcmoxsrcyuv_uplanestride_ldst[index];
+		gcmoxsrcyuv3->uplanestride  = srcinfo->stride2;
+		gcmoxsrcyuv3->vplaneaddress_ldst
+			= gcmoxsrcyuv_vplaneaddress_ldst[index];
+		gcmoxsrcyuv3->vplaneaddress = GET_MAP_HANDLE(srcmap);
+		gcmoxsrcyuv3->vplanestride_ldst
+			= gcmoxsrcyuv_vplanestride_ldst[index];
+		gcmoxsrcyuv3->vplanestride  = srcinfo->stride3;
+		break;
+
+	default:
+		GCERR("invlaid plane count %d.\n",
+		      srcinfo->format.cs.yuv.planecount);
+	}
+
+exit:
+	GCEXITARG(GCZONE_SRC, "bv%s = %d\n",
+		  (bverror == BVERR_NONE) ? "result" : "error", bverror);
+	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 int verify_surface(unsigned int tile,
+			  union bvinbuff *surf,
+			  struct bvsurfgeom *geom)
+{
+	if (tile) {
+		if (surf->tileparams == NULL)
+			return GCBVERR_TILE;
+
+		if (surf->tileparams->structsize <
+		    STRUCTSIZE(surf->tileparams, srcheight))
+			return GCBVERR_TILE_VERS;
+
+		/* FIXME/TODO */
+		return GCBVERR_TILE;
+	} else {
+		if (surf->desc == NULL)
+			return GCBVERR_DESC;
+
+		if (surf->desc->structsize < STRUCTSIZE(surf->desc, map))
+			return GCBVERR_DESC_VERS;
+	}
+
+	if (geom == NULL)
+		return GCBVERR_GEOM;
+
+	if (geom->structsize < STRUCTSIZE(geom, palette))
+		return GCBVERR_GEOM_VERS;
+
+	/* Validation successful. */
+	return -1;
+}
+
+
+/*******************************************************************************
+ * Library constructor and destructor.
+ */
+
+void bv_init(void)
+{
+	struct gccontext *gccontext = get_context();
+	struct gcicaps gcicaps;
+	unsigned i, j;
+
+	GCDBG_REGISTER(bv);
+	GCDBG_REGISTER(parser);
+	GCDBG_REGISTER(map);
+	GCDBG_REGISTER(buffer);
+	GCDBG_REGISTER(fill);
+	GCDBG_REGISTER(blit);
+	GCDBG_REGISTER(filter);
+
+	GCLOCK_INIT(&gccontext->batchlock);
+	GCLOCK_INIT(&gccontext->bufferlock);
+	GCLOCK_INIT(&gccontext->fixuplock);
+	GCLOCK_INIT(&gccontext->maplock);
+	GCLOCK_INIT(&gccontext->callbacklock);
+
+	INIT_LIST_HEAD(&gccontext->unmapvac);
+	INIT_LIST_HEAD(&gccontext->buffervac);
+	INIT_LIST_HEAD(&gccontext->fixupvac);
+	INIT_LIST_HEAD(&gccontext->batchvac);
+	INIT_LIST_HEAD(&gccontext->callbacklist);
+	INIT_LIST_HEAD(&gccontext->callbackvac);
+
+	/* Initialize the filter cache. */
+	for (i = 0; i < GC_FILTER_COUNT; i += 1)
+		for (j = 0; j < GC_TAP_COUNT; j += 1)
+			INIT_LIST_HEAD(&gccontext->filtercache[i][j].list);
+
+	/* Query hardware caps. */
+	gc_getcaps_wrapper(&gcicaps);
+	if (gcicaps.gcerror == GCERR_NONE) {
+		gccontext->gcmodel = gcicaps.gcmodel;
+		gccontext->gcrevision = gcicaps.gcrevision;
+		gccontext->gcdate = gcicaps.gcdate;
+		gccontext->gctime = gcicaps.gctime;
+		gccontext->gcfeatures = gcicaps.gcfeatures;
+		gccontext->gcfeatures0 = gcicaps.gcfeatures0;
+		gccontext->gcfeatures1 = gcicaps.gcfeatures1;
+		gccontext->gcfeatures2 = gcicaps.gcfeatures2;
+		gccontext->gcfeatures3 = gcicaps.gcfeatures3;
+	}
+}
+
+void bv_exit(void)
+{
+	struct gccontext *gccontext = get_context();
+	struct bvbuffmap *bvbuffmap;
+	struct list_head *head;
+	struct gcschedunmap *gcschedunmap;
+	struct gcbuffer *gcbuffer;
+	struct gcfixup *gcfixup;
+	struct gcbatch *gcbatch;
+	struct gccallbackinfo *gccallbackinfo;
+
+	while (gccontext->buffmapvac != NULL) {
+		bvbuffmap = gccontext->buffmapvac;
+		gccontext->buffmapvac = bvbuffmap->nextmap;
+		gcfree(bvbuffmap);
+	}
+
+	while (!list_empty(&gccontext->unmapvac)) {
+		head = gccontext->unmapvac.next;
+		gcschedunmap = list_entry(head, struct gcschedunmap, link);
+		list_del(head);
+		gcfree(gcschedunmap);
+	}
+
+	while (!list_empty(&gccontext->buffervac)) {
+		head = gccontext->buffervac.next;
+		gcbuffer = list_entry(head, struct gcbuffer, link);
+		list_del(head);
+		gcfree(gcbuffer);
+	}
+
+	while (!list_empty(&gccontext->fixupvac)) {
+		head = gccontext->fixupvac.next;
+		gcfixup = list_entry(head, struct gcfixup, link);
+		list_del(head);
+		gcfree(gcfixup);
+	}
+
+	while (!list_empty(&gccontext->batchvac)) {
+		head = gccontext->batchvac.next;
+		gcbatch = list_entry(head, struct gcbatch, link);
+		list_del(head);
+		gcfree(gcbatch);
+	}
+
+	while (!list_empty(&gccontext->callbacklist)) {
+		head = gccontext->callbacklist.next;
+		list_move(head, &gccontext->callbackvac);
+	}
+
+	while (!list_empty(&gccontext->callbackvac)) {
+		head = gccontext->callbackvac.next;
+		gccallbackinfo = list_entry(head, struct gccallbackinfo, link);
+		list_del(head);
+		gcfree(gccallbackinfo);
+	}
+
+	free_temp(false);
+}
+
+
+/*******************************************************************************
+ * Library API.
+ */
+
+enum bverror bv_map(struct bvbuffdesc *bvbuffdesc)
+{
+	enum bverror bverror;
+	struct bvbuffmap *bvbuffmap;
+
+	GCENTERARG(GCZONE_MAPPING, "bvbuffdesc = 0x%08X\n",
+		   (unsigned int) bvbuffdesc);
+
+	if (bvbuffdesc == NULL) {
+		BVSETERROR(BVERR_BUFFERDESC, "bvbuffdesc is NULL");
+		goto exit;
+	}
+
+	if (bvbuffdesc->structsize < STRUCTSIZE(bvbuffdesc, map)) {
+		BVSETERROR(BVERR_BUFFERDESC_VERS, "argument has invalid size");
+		goto exit;
+	}
+
+	bverror = do_map(bvbuffdesc, NULL, &bvbuffmap);
+
+exit:
+	GCEXITARG(GCZONE_MAPPING, "bv%s = %d\n",
+		  (bverror == BVERR_NONE) ? "result" : "error", bverror);
+	return bverror;
+}
+
+enum bverror bv_unmap(struct bvbuffdesc *bvbuffdesc)
+{
+	enum bverror bverror = BVERR_NONE;
+	enum bverror otherbverror = BVERR_NONE;
+	struct gccontext *gccontext = get_context();
+	struct bvbuffmap *prev = NULL;
+	struct bvbuffmap *bvbuffmap;
+	struct bvbuffmapinfo *bvbuffmapinfo;
+	struct gcimap gcimap;
+
+	GCENTERARG(GCZONE_MAPPING, "bvbuffdesc = 0x%08X\n",
+		   (unsigned int) bvbuffdesc);
+
+	/* Lock access to the mapping list. */
+	GCLOCK(&gccontext->maplock);
+
+	if (bvbuffdesc == NULL) {
+		BVSETERROR(BVERR_BUFFERDESC, "bvbuffdesc is NULL");
+		goto exit;
+	}
+
+	if (bvbuffdesc->structsize < STRUCTSIZE(bvbuffdesc, map)) {
+		BVSETERROR(BVERR_BUFFERDESC_VERS, "argument has invalid size");
+		goto exit;
+	}
+
+	/* Is the buffer mapped? */
+	bvbuffmap = bvbuffdesc->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 = bvbuffdesc->map->bv_unmap(bvbuffdesc);
+			goto exit;
+		}
+
+		if (bvbuffmap->structsize
+				< STRUCTSIZE(bvbuffmap, nextmap)) {
+			BVSETERROR(BVERR_BUFFERDESC_VERS,
+				   "unsupported bvbuffdesc version");
+			goto exit;
+		}
+
+		/* Remove our mapping. */
+		if (prev == NULL)
+			bvbuffdesc->map = bvbuffmap->nextmap;
+		else
+			prev->nextmap = bvbuffmap->nextmap;
+
+		/* Call other implementation. */
+		otherbverror = bvbuffdesc->map->bv_unmap(bvbuffdesc);
+
+		/* Add our mapping back. */
+		bvbuffmap->nextmap = bvbuffdesc->map;
+		bvbuffdesc->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(&gcimap, 0, sizeof(gcimap));
+	gcimap.handle = bvbuffmapinfo->handle;
+	gc_unmap_wrapper(&gcimap);
+	if (gcimap.gcerror != GCERR_NONE) {
+		BVSETERROR(BVERR_OOM, "unable to free gccore memory");
+		goto exit;
+	}
+
+	/* Remove from the buffer descriptor list. */
+	if (prev == NULL)
+		bvbuffdesc->map = bvbuffmap->nextmap;
+	else
+		prev->nextmap = bvbuffmap->nextmap;
+
+	/* Invalidate the record. */
+	bvbuffmap->structsize = 0;
+
+	/* Add to the vacant list. */
+	bvbuffmap->nextmap = gccontext->buffmapvac;
+	gccontext->buffmapvac = 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 *bvbltparams)
+{
+	enum bverror bverror = BVERR_NONE;
+	struct gccontext *gccontext = get_context();
+	struct gcalpha *gca = NULL;
+	struct gcalpha _gca;
+	unsigned int op, type, blend, format;
+	unsigned int batchexec = 0;
+	bool nop = false;
+	struct gcbatch *gcbatch;
+	struct bvrect *dstrect;
+	int src1used, src2used, maskused;
+	struct surfaceinfo srcinfo[2];
+	struct bvrect *srcrect[2];
+	unsigned short rop;
+	struct gcicommit gcicommit;
+	int i, srccount, res;
+
+	GCENTERARG(GCZONE_BLIT, "bvbltparams = 0x%08X\n",
+		   (unsigned int) bvbltparams);
+
+	/* Verify blt parameters structure. */
+	if (bvbltparams == NULL) {
+		BVSETERROR(BVERR_BLTPARAMS_VERS, "bvbltparams is NULL");
+		goto exit;
+	}
+
+	if (bvbltparams->structsize < STRUCTSIZE(bvbltparams, callbackdata)) {
+		BVSETERROR(BVERR_BLTPARAMS_VERS, "argument has invalid size");
+		goto exit;
+	}
+
+	/* Reset the error message. */
+	bvbltparams->errdesc = NULL;
+
+	/* Verify the destination parameters structure. */
+	res = verify_surface(0, (union bvinbuff *) &bvbltparams->dstdesc,
+				bvbltparams->dstgeom);
+	if (res != -1) {
+		BVSETBLTSURFERROR(res, g_destsurferr);
+		goto exit;
+	}
+
+	/* Extract the operation flags. */
+	op = (bvbltparams->flags & BVFLAG_OP_MASK) >> BVFLAG_OP_SHIFT;
+	type = (bvbltparams->flags & BVFLAG_BATCH_MASK) >> BVFLAG_BATCH_SHIFT;
+	GCDBG(GCZONE_BLIT, "op = %d\n", op);
+	GCDBG(GCZONE_BLIT, "type = %d\n", type);
+
+	switch (type) {
+	case (BVFLAG_BATCH_NONE >> BVFLAG_BATCH_SHIFT):
+		bverror = allocate_batch(bvbltparams, &gcbatch);
+		if (bverror != BVERR_NONE) {
+			bvbltparams->errdesc = gccontext->bverrorstr;
+			goto exit;
+		}
+
+		batchexec = 1;
+		gcbatch->batchflags = 0x7FFFFFFF;
+
+		GCDBG(GCZONE_BATCH, "BVFLAG_BATCH_NONE(0x%08X)\n",
+		      (unsigned int) gcbatch);
+		break;
+
+	case (BVFLAG_BATCH_BEGIN >> BVFLAG_BATCH_SHIFT):
+		bverror = allocate_batch(bvbltparams, &gcbatch);
+		if (bverror != BVERR_NONE) {
+			bvbltparams->errdesc = gccontext->bverrorstr;
+			goto exit;
+		}
+
+		bvbltparams->batch = (struct bvbatch *) gcbatch;
+
+		batchexec = 0;
+		bvbltparams->batchflags =
+		gcbatch->batchflags = 0x7FFFFFFF;
+
+		GCDBG(GCZONE_BATCH, "BVFLAG_BATCH_BEGIN(0x%08X)\n",
+		      (unsigned int) gcbatch);
+		break;
+
+	case (BVFLAG_BATCH_CONTINUE >> BVFLAG_BATCH_SHIFT):
+		gcbatch = (struct gcbatch *) bvbltparams->batch;
+		if (gcbatch == NULL) {
+			BVSETBLTERROR(BVERR_BATCH, "batch is not initialized");
+			goto exit;
+		}
+
+		if (gcbatch->structsize < STRUCTSIZE(gcbatch, unmap)) {
+			BVSETBLTERROR(BVERR_BATCH, "invalid batch");
+			goto exit;
+		}
+
+		batchexec = 0;
+		gcbatch->batchflags = bvbltparams->batchflags;
+
+		GCDBG(GCZONE_BATCH, "BVFLAG_BATCH_CONTINUE(0x%08X)\n",
+		      (unsigned int) gcbatch);
+		break;
+
+	case (BVFLAG_BATCH_END >> BVFLAG_BATCH_SHIFT):
+		gcbatch = (struct gcbatch *) bvbltparams->batch;
+		if (gcbatch == NULL) {
+			BVSETBLTERROR(BVERR_BATCH, "batch is not initialized");
+			goto exit;
+		}
+
+		if (gcbatch->structsize < STRUCTSIZE(gcbatch, unmap)) {
+			BVSETBLTERROR(BVERR_BATCH, "invalid batch");
+			goto exit;
+		}
+
+		batchexec = 1;
+		nop = (bvbltparams->batchflags & BVBATCH_ENDNOP) != 0;
+		gcbatch->batchflags = bvbltparams->batchflags;
+
+		GCDBG(GCZONE_BATCH, "BVFLAG_BATCH_END(0x%08X)\n",
+		      (unsigned int) gcbatch);
+		break;
+
+	default:
+		BVSETBLTERROR(BVERR_BATCH, "unrecognized batch type");
+		goto exit;
+	}
+
+	GCDBG(GCZONE_BATCH, "batchflags=0x%08X\n",
+		(unsigned int) gcbatch->batchflags);
+
+	if (!nop) {
+		/* Get a shortcut to the destination rectangle. */
+		dstrect = &bvbltparams->dstrect;
+
+		/* Verify the batch change flags. */
+		GCVERIFYBATCH(gcbatch->batchflags >> 12,
+			      &gcbatch->prevdstrect, dstrect);
+
+		switch (op) {
+		case (BVFLAG_ROP >> BVFLAG_OP_SHIFT):
+			GCDBG(GCZONE_BLIT, "BVFLAG_ROP\n");
+
+			rop = bvbltparams->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 = bvbltparams->op.blend;
+			format = (blend & BVBLENDDEF_FORMAT_MASK)
+			       >> BVBLENDDEF_FORMAT_SHIFT;
+
+			bverror = parse_blend(bvbltparams, 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;
+		}
+
+		/* Reset the number of sources. */
+		srccount = 0;
+
+		/* Verify the src1 parameters structure. */
+		if (src1used) {
+			GCDBG(GCZONE_SRC, "source #1: used\n");
+			res = verify_surface(
+				bvbltparams->flags & BVBATCH_TILE_SRC1,
+				&bvbltparams->src1, bvbltparams->src1geom);
+			if (res != -1) {
+				BVSETBLTSURFERROR(res, g_src1surferr);
+				goto exit;
+			}
+
+			/* Verify the batch change flags. */
+			GCVERIFYBATCH(gcbatch->batchflags >> 14,
+				      &gcbatch->prevsrc1rect,
+				      &bvbltparams->src1rect);
+
+			/* Same as the destination? */
+			if (same_phys_area(bvbltparams->src1.desc,
+					   &bvbltparams->src1rect,
+					   bvbltparams->dstdesc,
+					   dstrect)) {
+				GCDBG(GCZONE_BLIT, "  same as destination\n");
+			} else {
+				srcinfo[srccount].index = 0;
+				srcinfo[srccount].buf = bvbltparams->src1;
+				srcinfo[srccount].geom = bvbltparams->src1geom;
+				srcinfo[srccount].newgeom
+					= gcbatch->batchflags
+						& BVBATCH_SRC1;
+				srcinfo[srccount].newrect
+					= gcbatch->batchflags
+						& (BVBATCH_SRC1RECT_ORIGIN |
+						   BVBATCH_SRC1RECT_SIZE);
+				srcrect[srccount] = &bvbltparams->src1rect;
+
+				bverror = parse_source(bvbltparams, gcbatch,
+						       &bvbltparams->src1rect,
+						       &srcinfo[srccount]);
+				if (bverror != BVERR_NONE)
+					goto exit;
+
+				srccount += 1;
+			}
+		}
+
+		/* Verify the src2 parameters structure. */
+		if (src2used) {
+			GCDBG(GCZONE_SRC, "source #2: used\n");
+			res = verify_surface(
+				bvbltparams->flags & BVBATCH_TILE_SRC2,
+				&bvbltparams->src2, bvbltparams->src2geom);
+			if (res != -1) {
+				BVSETBLTSURFERROR(res, g_src2surferr);
+				goto exit;
+			}
+
+			/* Verify the batch change flags. */
+			GCVERIFYBATCH(gcbatch->batchflags >> 16,
+				      &gcbatch->prevsrc2rect,
+				      &bvbltparams->src2rect);
+
+			/* Same as the destination? */
+			if (same_phys_area(bvbltparams->src2.desc,
+					   &bvbltparams->src2rect,
+					   bvbltparams->dstdesc,
+					   dstrect)) {
+				GCDBG(GCZONE_BLIT, "  same as destination\n");
+			} else {
+				srcinfo[srccount].index = 1;
+				srcinfo[srccount].buf = bvbltparams->src2;
+				srcinfo[srccount].geom = bvbltparams->src2geom;
+				srcinfo[srccount].newgeom
+					= gcbatch->batchflags
+						& BVBATCH_SRC2;
+				srcinfo[srccount].newrect
+					= gcbatch->batchflags
+						& (BVBATCH_SRC2RECT_ORIGIN |
+						   BVBATCH_SRC2RECT_SIZE);
+				srcrect[srccount] = &bvbltparams->src2rect;
+
+				bverror = parse_source(bvbltparams, gcbatch,
+						       &bvbltparams->src2rect,
+						       &srcinfo[srccount]);
+				if (bverror != BVERR_NONE)
+					goto exit;
+
+				srccount += 1;
+			}
+		}
+
+		/* Verify the mask parameters structure. */
+		if (maskused) {
+			GCDBG(GCZONE_MASK, "mask: used\n");
+			res = verify_surface(
+				bvbltparams->flags & BVBATCH_TILE_MASK,
+				&bvbltparams->mask, bvbltparams->maskgeom);
+			if (res != -1) {
+				BVSETBLTSURFERROR(res, g_masksurferr);
+				goto exit;
+			}
+
+			/* Verify the batch change flags. */
+			GCVERIFYBATCH(gcbatch->batchflags >> 18,
+				      &gcbatch->prevmaskrect,
+				      &bvbltparams->maskrect);
+
+			BVSETBLTERROR(BVERR_OP,
+				      "operation with mask not supported");
+			goto exit;
+		}
+
+		GCDBG(GCZONE_BLIT, "srccount = %d\n", srccount);
+
+		if (srccount == 0) {
+			BVSETBLTERROR(BVERR_OP,
+				      "operation not supported");
+			goto exit;
+		} else {
+			for (i = 0; i < srccount; i += 1) {
+				int srcw, srch;
+				GCDBG(GCZONE_BLIT,
+				      "processing source %d.\n",
+				      srcinfo[i].index + 1);
+
+				if (gca == NULL) {
+					GCDBG(GCZONE_BLIT,
+					      "  blending disabled.\n");
+					srcinfo[i].rop = bvbltparams->op.rop;
+					srcinfo[i].gca = NULL;
+				} else if ((i + 1) != srccount) {
+					GCDBG(GCZONE_BLIT,
+					      "  disabling blending for "
+					      "the first source.\n");
+					srcinfo[i].rop = 0xCC;
+					srcinfo[i].gca = NULL;
+				} else {
+					GCDBG(GCZONE_BLIT,
+					      "  enabling blending.\n");
+					srcinfo[i].rop = 0xCC;
+					srcinfo[i].gca = gca;
+
+					if (srccount == 1) {
+						gca->srcconfig = gca->k1;
+						gca->dstconfig = gca->k2;
+					} else {
+						gca->srcconfig = gca->k2;
+						gca->dstconfig = gca->k1;
+					}
+				}
+
+				GCDBG(GCZONE_BLIT, "  srcsize %dx%d.\n",
+				      srcrect[i]->width, srcrect[i]->height);
+				GCDBG(GCZONE_BLIT, "  dstsize %dx%d.\n",
+				      dstrect->width, dstrect->height);
+
+				srcw = srcrect[i]->width;
+				srch = srcrect[i]->height;
+				if ((srcw == 1) && (srch == 1) &&
+				    (bvbltparams->src1.desc->virtaddr)) {
+					GCDBG(GCZONE_BLIT, "  op: fill.\n");
+					bverror = do_fill(bvbltparams,
+							  gcbatch,
+							  &srcinfo[i]);
+				} else if ((srcw == dstrect->width) &&
+					   (srch == dstrect->height)) {
+					GCDBG(GCZONE_BLIT, "  op: bitblit.\n");
+					bverror = do_blit(bvbltparams,
+							  gcbatch,
+							  &srcinfo[i]);
+				} else {
+					GCDBG(GCZONE_BLIT, "  op: filter.\n");
+					bverror = do_filter(bvbltparams,
+							    gcbatch,
+							    &srcinfo[i]);
+				}
+
+				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 = gcbatch->batchend(bvbltparams, gcbatch);
+		if (bverror != BVERR_NONE)
+			goto exit;
+
+		/* Add PE flush. */
+		GCDBG(GCZONE_BLIT, "appending the flush.\n");
+		bverror = claim_buffer(bvbltparams, gcbatch,
+				       sizeof(struct gcmoflush),
+				       (void **) &flush);
+		if (bverror != BVERR_NONE)
+			goto exit;
+
+		flush->flush_ldst = gcmoflush_flush_ldst;
+		flush->flush.reg = gcregflush_pe2D;
+
+		/* Process asynchronous operation. */
+		if ((bvbltparams->flags & BVFLAG_ASYNC) == 0) {
+			GCDBG(GCZONE_BLIT, "synchronous batch.\n");
+			gcicommit.callback = NULL;
+			gcicommit.callbackparam = NULL;
+			gcicommit.asynchronous = false;
+		} else {
+			struct gccallbackinfo *gccallbackinfo;
+
+			GCDBG(GCZONE_BLIT, "asynchronous batch (0x%08X):\n",
+			      bvbltparams->flags);
+
+			if (bvbltparams->callbackfn == NULL) {
+				GCDBG(GCZONE_BLIT, "no callback given.\n");
+				gcicommit.callback = NULL;
+				gcicommit.callbackparam = NULL;
+			} else {
+				bverror = get_callbackinfo(&gccallbackinfo);
+				if (bverror != BVERR_NONE) {
+					BVSETBLTERROR(BVERR_OOM,
+						      "callback allocation "
+						      "failed");
+					goto exit;
+				}
+
+				gccallbackinfo->info.callback.fn
+					= bvbltparams->callbackfn;
+				gccallbackinfo->info.callback.data
+					= bvbltparams->callbackdata;
+
+				gcicommit.callback = callbackbltsville;
+				gcicommit.callbackparam = gccallbackinfo;
+
+				GCDBG(GCZONE_BLIT,
+				      "gcbv_callback = 0x%08X\n",
+				      (unsigned int) gcicommit.callback);
+				GCDBG(GCZONE_BLIT,
+				      "gcbv_param    = 0x%08X\n",
+				      (unsigned int) gcicommit.callbackparam);
+				GCDBG(GCZONE_BLIT,
+				      "bltsville_callback = 0x%08X\n",
+				      (unsigned int)
+				      gccallbackinfo->info.callback.fn);
+				GCDBG(GCZONE_BLIT,
+				      "bltsville_param    = 0x%08X\n",
+				      (unsigned int)
+				      gccallbackinfo->info.callback.data);
+			}
+
+			gcicommit.asynchronous = true;
+		}
+
+		/* Process scheduled unmappings. */
+		do_unmap_implicit(gcbatch);
+
+		INIT_LIST_HEAD(&gcicommit.unmap);
+		list_splice_init(&gcbatch->unmap, &gcicommit.unmap);
+
+		/* Pass the batch for execution. */
+		GCDUMPBATCH(gcbatch);
+
+		gcicommit.gcerror = GCERR_NONE;
+		gcicommit.entrypipe = GCPIPE_2D;
+		gcicommit.exitpipe = GCPIPE_2D;
+
+		INIT_LIST_HEAD(&gcicommit.buffer);
+		list_splice_init(&gcbatch->buffer, &gcicommit.buffer);
+
+		GCDBG(GCZONE_BLIT, "submitting the batch.\n");
+		gc_commit_wrapper(&gcicommit);
+
+		/* Move the lists back to the batch. */
+		list_splice_init(&gcicommit.buffer, &gcbatch->buffer);
+		list_splice_init(&gcicommit.unmap, &gcbatch->unmap);
+
+		/* Error? */
+		if (gcicommit.gcerror != GCERR_NONE) {
+			switch (gcicommit.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 ((gcbatch != NULL) && batchexec) {
+		free_batch(gcbatch);
+		bvbltparams->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;
+	unsigned int true_width, true_height;
+
+	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;
+	}
+
+	if (copparams->geom->orientation % 180 != 0) {
+		true_width = copparams->rect->height;
+		true_height = copparams->rect->width;
+	} else {
+		true_width = copparams->rect->width;
+		true_height = copparams->rect->height;
+	}
+
+	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;
+
+		default:
+			bverror = BVERR_FORMAT;
+			goto exit;
+		}
+
+		rgn[0].span = true_width * bytespp;
+		rgn[0].lines = true_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 = true_width;
+		rgn[0].lines = true_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 = true_width;
+		rgn[1].lines = true_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/bltsville/gcbv/mirror/gcbv.h b/bltsville/gcbv/mirror/gcbv.h
new file mode 100644
index 0000000..6392d4f
--- /dev/null
+++ b/bltsville/gcbv/mirror/gcbv.h
@@ -0,0 +1,590 @@
+/*
+ * 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 GCBV_H
+#define GCBV_H
+
+#include "gcmain.h"
+
+/*******************************************************************************
+ * Miscellaneous defines and macros.
+ */
+
+#define GC_MAX_BASE_ALIGN 64
+
+#if !defined(BVBATCH_DESTRECT)
+#define BVBATCH_DESTRECT (BVBATCH_DSTRECT_ORIGIN | BVBATCH_DSTRECT_SIZE)
+#endif
+
+#if !defined(BVBATCH_SRC1RECT)
+#define BVBATCH_SRC1RECT (BVBATCH_SRC1RECT_ORIGIN | BVBATCH_SRC1RECT_SIZE)
+#endif
+
+#if !defined(BVBATCH_SRC2RECT)
+#define BVBATCH_SRC2RECT (BVBATCH_SRC2RECT_ORIGIN | BVBATCH_SRC2RECT_SIZE)
+#endif
+
+#define STRUCTSIZE(structptr, lastmember) \
+( \
+	(size_t) &structptr->lastmember + \
+	sizeof(structptr->lastmember) - \
+	(size_t) structptr \
+)
+
+#define GET_MAP_HANDLE(map) \
+( \
+	((struct bvbuffmapinfo *) map->handle)->handle \
+)
+
+#define GC_CLIP_RESET_LEFT	((unsigned short) 0)
+#define GC_CLIP_RESET_TOP	((unsigned short) 0)
+#define GC_CLIP_RESET_RIGHT	((unsigned short) ((1 << 15) - 1))
+#define GC_CLIP_RESET_BOTTOM	((unsigned short) ((1 << 15) - 1))
+
+#define BVSETERROR(error, message, ...) \
+do { \
+	struct gccontext *tmpcontext = get_context(); \
+	snprintf(tmpcontext->bverrorstr, sizeof(tmpcontext->bverrorstr), \
+		 message, ##__VA_ARGS__); \
+	GCDUMPSTRING("%s(%d): [ERROR] %s\n", __func__, __LINE__, \
+		     tmpcontext->bverrorstr); \
+	bverror = error; \
+} while (0)
+
+#define BVSETBLTERROR(error, message, ...) \
+do { \
+	struct gccontext *tmpcontext = get_context(); \
+	snprintf(tmpcontext->bverrorstr, sizeof(tmpcontext->bverrorstr), \
+		 message, ##__VA_ARGS__); \
+	GCDUMPSTRING("%s(%d): [ERROR] %s\n", __func__, __LINE__, \
+		     tmpcontext->bverrorstr); \
+	bvbltparams->errdesc = tmpcontext->bverrorstr; \
+	bverror = error; \
+} while (0)
+
+#define GCPRINT_RECT(zone, name, rect) \
+{ \
+	GCDBG(zone, \
+	      name " = (%d,%d)-(%d,%d), %dx%d\n", \
+	      (rect)->left, (rect)->top, \
+	      (rect)->right, (rect)->bottom, \
+	      (rect)->right - (rect)->left, \
+	      (rect)->bottom - (rect)->top); \
+}
+
+
+/*******************************************************************************
+ * Kernel table definitions.
+ */
+
+#define GC_TAP_COUNT		9
+#define GC_PHASE_BITS		5
+#define GC_PHASE_MAX_COUNT	(1 << GC_PHASE_BITS)
+#define GC_PHASE_LOAD_COUNT	(GC_PHASE_MAX_COUNT / 2 + 1)
+#define GC_COEFFICIENT_COUNT	(GC_PHASE_LOAD_COUNT * GC_TAP_COUNT)
+#define GC_FILTER_CACHE_MAX	10
+
+enum gcfiltertype {
+	GC_FILTER_SYNC,
+	GC_FILTER_BLUR,
+
+	/* Number of supported filter types. */
+	GC_FILTER_COUNT
+};
+
+struct gcfilterkernel {
+	enum gcfiltertype type;
+	unsigned int kernelsize;
+	unsigned int srcsize;
+	unsigned int dstsize;
+	unsigned int scalefactor;
+	short kernelarray[GC_COEFFICIENT_COUNT];
+	struct list_head link;
+};
+
+struct gcfiltercache {
+	unsigned int count;
+	struct list_head list;			/* gcfilterkernel */
+};
+
+
+/*******************************************************************************
+ * Global data structure.
+ */
+
+struct gccontext {
+	/* Last generated error message. */
+	char bverrorstr[128];
+
+	/* Capabilities and characteristics. */
+	unsigned int gcmodel;
+	unsigned int gcrevision;
+	unsigned int gcdate;
+	unsigned int gctime;
+	union gcfeatures gcfeatures;
+	union gcfeatures0 gcfeatures0;
+	union gcfeatures1 gcfeatures1;
+	union gcfeatures2 gcfeatures2;
+	union gcfeatures3 gcfeatures3;
+
+	/* Dynamically allocated structure cache. */
+	struct bvbuffmap *buffmapvac;		/* bvbuffmap */
+	struct list_head unmapvac;		/* gcschedunmap */
+	struct list_head buffervac;		/* gcbuffer */
+	struct list_head fixupvac;		/* gcfixup */
+	struct list_head batchvac;		/* gcbatch */
+
+	/* Callback lists. */
+	struct list_head callbacklist;		/* gccallbackinfo */
+	struct list_head callbackvac;		/* gccallbackinfo */
+
+	/* Access locks. */
+	GCLOCK_TYPE batchlock;
+	GCLOCK_TYPE bufferlock;
+	GCLOCK_TYPE fixuplock;
+	GCLOCK_TYPE maplock;
+	GCLOCK_TYPE callbacklock;
+
+	/* Kernel table cache. */
+	struct gcfilterkernel *loadedfilter;	/* gcfilterkernel */
+	struct gcfiltercache filtercache[GC_FILTER_COUNT][GC_TAP_COUNT];
+
+	/* Temporary buffer descriptor. */
+	struct bvbuffdesc *tmpbuffdesc;
+	void *tmpbuff;
+};
+
+
+/*******************************************************************************
+ * Mapping structures.
+ */
+
+/* bvbuffmap struct attachment. */
+struct bvbuffmapinfo {
+	/* Mapped handle for the buffer. */
+	unsigned long handle;
+
+	/* Number of times the client explicitly mapped this buffer. */
+	int usermap;
+
+	/* Number of times implicit mapping happened. */
+	int automap;
+};
+
+
+/*******************************************************************************
+ * Color format.
+ */
+
+#define BVFMT_RGB	1
+#define BVFMT_YUV	2
+
+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 int type;
+	unsigned int bitspp;
+	unsigned int allocbitspp;
+	unsigned int format;
+	unsigned int swizzle;
+	bool premultiplied;
+
+	union {
+		struct {
+			const struct bvcsrgb *comp;
+		} rgb;
+
+		struct {
+			unsigned int std;
+			unsigned int planecount;
+			unsigned int xsample;
+			unsigned int ysample;
+		} yuv;
+	} cs;
+};
+
+
+/*******************************************************************************
+ * Alpha blending.
+ */
+
+/* Alpha blending hardware configuration. */
+struct gcblendconfig {
+	unsigned char factor_mode;
+	unsigned char color_reverse;
+
+	bool src1used;
+	bool src2used;
+};
+
+/* Alpha blending descriptor. */
+struct gcalpha {
+	unsigned int src_global_color;
+	unsigned int dst_global_color;
+
+	unsigned char src_global_alpha_mode;
+	unsigned char dst_global_alpha_mode;
+
+	struct gcblendconfig *k1;
+	struct gcblendconfig *k2;
+
+	struct gcblendconfig *srcconfig;
+	struct gcblendconfig *dstconfig;
+
+	bool src1used;
+	bool src2used;
+};
+
+
+/*******************************************************************************
+ * Rotation and mirror defines.
+ */
+
+#define GCREG_ROT_ANGLE_ROT0	0x0
+#define GCREG_ROT_ANGLE_ROT90	0x4
+#define GCREG_ROT_ANGLE_ROT180	0x5
+#define GCREG_ROT_ANGLE_ROT270	0x6
+
+#define ROT_ANGLE_INVALID	-1
+#define ROT_ANGLE_0		0
+#define ROT_ANGLE_90		1
+#define ROT_ANGLE_180		2
+#define ROT_ANGLE_270		3
+
+#define GCREG_MIRROR_NONE	0x0
+#define GCREG_MIRROR_X		0x1
+#define GCREG_MIRROR_Y		0x2
+#define GCREG_MIRROR_XY		0x3
+
+extern const unsigned int rotencoding[];
+
+
+/*******************************************************************************
+ * Surface descriptor.
+ */
+
+struct surfaceinfo {
+	/* BLTsville source index (-1 for dst, 0 for src1 and 1 for src2). */
+	int index;
+
+	/* Surface buffer descriptor. */
+	union bvinbuff buf;
+
+	/* Surface geometry. */
+	struct bvsurfgeom *geom;
+	bool newgeom;
+
+	/* Rectangle to source from/render to. */
+	struct gcrect rect;
+	bool newrect;
+
+	/* Surface format. */
+	struct bvformatxlate format;
+
+	/* Physical size of the surface (accounted for rotation). */
+	unsigned int physwidth;
+	unsigned int physheight;
+
+	/* Base address alignment. */
+	int xpixalign;
+	int ypixalign;
+	int bytealign;
+	int bytealign2;
+	int bytealign3;
+	int stride2;
+	int stride3;
+
+	/* Rotation angle. */
+	int angle;
+
+	/* Mirror setting. */
+	unsigned int mirror;
+
+	/* ROP. */
+	unsigned short rop;
+
+	/* Blending info. */
+	struct gcalpha *gca;
+};
+
+
+/*******************************************************************************
+ * Batch structures.
+ */
+
+/* Operation finalization call. */
+struct gcbatch;
+typedef enum bverror (*gcbatchend) (struct bvbltparams *bvbltparams,
+				    struct gcbatch *gcbatch);
+
+/* Blit states. */
+struct gcblit {
+	/* Number of sources in the operation. */
+	unsigned int srccount;
+
+	/* Multi source enable flag. */
+	unsigned int multisrc;
+
+	/* Computed destination rectangle coordinates; in multi-source
+	 * setup can be modified to match new destination and source
+	 * geometry. */
+	struct gcrect dstrect;
+
+	/* Block walker enable. */
+	int blockenable;
+
+	/* Destination format and swizzle */
+	unsigned int format;
+	unsigned int swizzle;
+};
+
+/* Filter states. */
+struct gcfilter {
+	/* Kernel size. */
+	unsigned int horkernelsize;
+	unsigned int verkernelsize;
+
+	/* Scale factors. */
+	unsigned int horscalefactor;
+	unsigned int verscalefactor;
+
+	/* Destination angle. */
+	bool angleoverride;
+	int dstangle;
+
+	/* Geometry size that follows angle adjustments. */
+	struct bvsurfgeom dstgeom;
+
+	/* Original source and destination rectangles adjusted
+	 * by the source angle. */
+	struct gcrect dstrect;
+	struct gcrect dstrectaux;
+
+	/* Clipped destination rectangle adjusted by the source angle. */
+	struct gcrect dstclipped;
+	struct gcrect dstclippedaux;
+
+	/* Destination rectangles that were clipped, adjusted for
+	 * the surface misalignment and the source angle. */
+	struct gcrect dstadjusted;
+	struct gcrect dstadjustedaux;
+};
+
+/* 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 {
+		struct gcblit blit;
+		struct gcfilter filter;
+	} op;
+
+	/* Destination surface. */
+	struct surfaceinfo dstinfo;
+
+	/* Aux rectangle present. */
+	bool haveaux;
+	struct gcrect dstrectaux;
+
+	/* Clipped destination rectangle coordinates. */
+	struct gcrect dstclipped;
+	struct gcrect dstclippedaux;
+
+	/* Destination rectangles that were clipped and adjusted for
+	 * surface misalignment if any. */
+	struct gcrect dstadjusted;
+	struct gcrect dstadjustedaux;
+
+	/* Clipping deltas; used to correct the source coordinates for
+	 * single source blits. */
+	struct gcrect clipdelta;
+
+	/* Adjusted geometry size of the destination surface. */
+	unsigned int dstwidth;
+	unsigned int dstheight;
+
+	/* Physical size of the source and destination surfaces. */
+	unsigned int srcphyswidth;
+	unsigned int srcphysheight;
+	unsigned int dstphyswidth;
+	unsigned int dstphysheight;
+
+	/* Alignment byte offset for the destination surface; in multi-
+	 * source setup can be modified to match new destination and source
+	 * geometry. */
+	int dstbyteshift;
+
+	/* Destination rectangle adjustment offsets. */
+	int dstoffsetX;
+	int dstoffsetY;
+
+#if GCDEBUG_ENABLE
+	/* Rectangle validation storage. */
+	struct bvrect prevdstrect;
+	struct bvrect prevsrc1rect;
+	struct bvrect prevsrc2rect;
+	struct bvrect prevmaskrect;
+#endif
+
+	/* Total size of the command buffer. */
+	unsigned int size;
+
+	/* Command buffer list (gcbuffer). */
+	struct list_head buffer;
+
+	/* Scheduled implicit unmappings (gcschedunmap). */
+	struct list_head unmap;
+
+	/* Batch linked list (gcbatch). */
+	struct list_head link;
+};
+
+
+/*******************************************************************************
+ * Internal API entries.
+ */
+
+/* Get the pointer to the context. */
+struct gccontext *get_context(void);
+
+/* Validation. */
+bool valid_rect(struct bvsurfgeom *bvsurfgeom, struct gcrect *gcrect);
+
+/* Parsers. */
+enum bverror parse_format(struct bvbltparams *bvbltparams,
+			  struct surfaceinfo *surfaceinfo);
+enum bverror parse_blend(struct bvbltparams *bvbltparams,
+			 enum bvblend blend,
+			 struct gcalpha *gca);
+enum bverror parse_destination(struct bvbltparams *bvbltparams,
+			       struct gcbatch *gcbatch);
+enum bverror parse_source(struct bvbltparams *bvbltparams,
+			  struct gcbatch *gcbatch,
+			  struct bvrect *srcrect,
+			  struct surfaceinfo *srcinfo);
+enum bverror parse_scalemode(struct bvbltparams *bvbltparams,
+			     struct gcbatch *batch);
+
+/* Setup destination rotation parameters. */
+void process_dest_rotation(struct bvbltparams *bvbltparams,
+			   struct gcbatch *batch);
+
+/* Return surface alignment offset. */
+int get_pixel_offset(struct surfaceinfo *surfaceinfo, int offset);
+
+/* Buffer mapping. */
+enum bverror do_map(struct bvbuffdesc *bvbuffdesc,
+		    struct gcbatch *gcbatch,
+		    struct bvbuffmap **map);
+void do_unmap_implicit(struct gcbatch *gcbatch);
+
+/* Batch/command buffer management. */
+enum bverror do_end(struct bvbltparams *bvbltparams,
+		    struct gcbatch *gcbatch);
+enum bverror allocate_batch(struct bvbltparams *bvbltparams,
+			    struct gcbatch **gcbatch);
+void free_batch(struct gcbatch *gcbatch);
+enum bverror append_buffer(struct bvbltparams *bvbltparams,
+			   struct gcbatch *gcbatch,
+			   struct gcbuffer **gcbuffer);
+
+enum bverror add_fixup(struct bvbltparams *bvbltparams,
+		       struct gcbatch *gcbatch,
+		       unsigned int *fixup,
+		       unsigned int surfoffset);
+enum bverror claim_buffer(struct bvbltparams *bvbltparams,
+			  struct gcbatch *gcbatch,
+			  unsigned int size,
+			  void **buffer);
+
+/* Temporary buffer management. */
+enum bverror allocate_temp(struct bvbltparams *bvbltparams,
+			   unsigned int size);
+enum bverror free_temp(bool schedule);
+
+/* Program the destination. */
+enum bverror set_dst(struct bvbltparams *bltparams,
+		     struct gcbatch *batch,
+		     struct bvbuffmap *dstmap);
+
+/* Program blending. */
+enum bverror set_blending(struct bvbltparams *bvbltparams,
+			  struct gcbatch *batch,
+			  struct surfaceinfo *srcinfo);
+enum bverror set_blending_index(struct bvbltparams *bvbltparams,
+				struct gcbatch *batch,
+				struct surfaceinfo *srcinfo,
+				unsigned int index);
+
+/* Program YUV source. */
+void set_computeyuv(struct surfaceinfo *srcinfo, int x, int y);
+enum bverror set_yuvsrc(struct bvbltparams *bvbltparams,
+			struct gcbatch *batch,
+			struct surfaceinfo *srcinfo,
+			struct bvbuffmap *srcmap);
+enum bverror set_yuvsrc_index(struct bvbltparams *bvbltparams,
+			      struct gcbatch *batch,
+			      struct surfaceinfo *srcinfo,
+			      struct bvbuffmap *srcmap,
+			      unsigned int index);
+
+/* Rendering entry points. */
+enum bverror do_fill(struct bvbltparams *bltparams,
+		     struct gcbatch *gcbatch,
+		     struct surfaceinfo *srcinfo);
+enum bverror do_blit(struct bvbltparams *bltparams,
+		     struct gcbatch *gcbatch,
+		     struct surfaceinfo *srcinfo);
+enum bverror do_filter(struct bvbltparams *bvbltparams,
+		       struct gcbatch *gcbatch,
+		       struct surfaceinfo *srcinfo);
+
+#endif
diff --git a/bltsville/gcbv/mirror/gcdbglog.c b/bltsville/gcbv/mirror/gcdbglog.c
new file mode 100644
index 0000000..9743897
--- /dev/null
+++ b/bltsville/gcbv/mirror/gcdbglog.c
@@ -0,0 +1,1684 @@
+/*
+ * 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 ANDROID
+#include <cutils/log.h>
+#endif
+
+#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
+
+/* Print buffers like C arrays. */
+#define GC_C_BUFFER		0
+
+
+/*******************************************************************************
+ * 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.
+ */
+
+#if ANDROID
+#define GC_PRINTK(s, fmt, ...) \
+	LOGI(fmt, ##__VA_ARGS__);
+#else
+#define GC_PRINTK(s, fmt, ...) \
+	printf(fmt, ##__VA_ARGS__);
+#endif
+
+#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;) {
+#if GC_C_BUFFER
+		GC_PRINTK(s, "%s\t0x%08X,\n", buffer, data32[i++]);
+#else
+		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;
+		}
+#endif
+	}
+}
+
+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.left
+						= buffer[i] & 0xFFFF;
+
+					info->src[0].rect.top
+						= (buffer[i] >> 16) & 0xFFFF;
+					break;
+
+				case gcregSrcSizeRegAddrs:
+					info->src[0].rect.right
+						= buffer[i] & 0xFFFF;
+
+					info->src[0].rect.bottom
+						= (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.left
+						= buffer[i] & 0xFFFF;
+
+					info->src[index].rect.top
+						= (buffer[i] >> 16) & 0xFFFF;
+					break;
+
+				case gcregBlock4SrcSizeRegAddrs:
+				case gcregBlock4SrcSizeRegAddrs + 1:
+				case gcregBlock4SrcSizeRegAddrs + 2:
+				case gcregBlock4SrcSizeRegAddrs + 3:
+					index = addr & 3;
+					info->src[index].rect.right
+						= buffer[i] & 0xFFFF;
+
+					info->src[index].rect.bottom
+						= (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].left
+						= buffer[i] & 0xFFFF;
+				info->dst.rect[j].top
+						= (buffer[i] >> 16) & 0xFFFF;
+				i += 1;
+
+				info->dst.rect[j].right
+						= buffer[i] & 0xFFFF;
+				info->dst.rect[j].bottom
+						= (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/bltsville/gcbv/mirror/gcfill.c b/bltsville/gcbv/mirror/gcfill.c
new file mode 100644
index 0000000..458be75
--- /dev/null
+++ b/bltsville/gcbv/mirror/gcfill.c
@@ -0,0 +1,258 @@
+/*
+ * Copyright(c) 2012,
+ * Texas Instruments, Inc. and Vivante Corporation.
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *   * Neither the name of Vivante Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "gcbv.h"
+
+#define GCZONE_NONE		0
+#define GCZONE_ALL		(~0U)
+#define GCZONE_COLOR		(1 << 0)
+#define GCZONE_FILL		(1 << 1)
+
+GCDBG_FILTERDEF(fill, GCZONE_NONE,
+		"color",
+		"fill")
+
+
+static inline unsigned int extract_component(unsigned int pixel,
+					     const 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->cs.rgb.comp->r);
+	g = extract_component(srcpixel, &format->cs.rgb.comp->g);
+	b = extract_component(srcpixel, &format->cs.rgb.comp->b);
+	a = extract_component(srcpixel, &format->cs.rgb.comp->a);
+
+	GCDBG(GCZONE_COLOR, "(r,g,b,a)=0x%02X,0x%02X,0x%02X,0x%02X\n",
+	      r, g, b, a);
+
+	dstpixel = (a << 24) | (r << 16) | (g <<  8) | b;
+
+	GCDBG(GCZONE_COLOR, "dstpixel=0x%08X\n", dstpixel);
+
+	return dstpixel;
+}
+
+enum bverror do_fill(struct bvbltparams *bvbltparams,
+		     struct gcbatch *batch,
+		     struct surfaceinfo *srcinfo)
+{
+	enum bverror bverror;
+	struct gccontext *gccontext = get_context();
+	struct surfaceinfo *dstinfo;
+	struct gcmofill *gcmofill;
+	unsigned char *fillcolorptr;
+	struct bvbuffmap *dstmap = NULL;
+
+	GCENTER(GCZONE_FILL);
+
+	/* Finish previous batch if any. */
+	bverror = batch->batchend(bvbltparams, batch);
+	if (bverror != BVERR_NONE)
+		goto exit;
+
+	/* Parse destination parameters. */
+	bverror = parse_destination(bvbltparams, batch);
+	if (bverror != BVERR_NONE)
+		goto exit;
+
+	/* Setup rotation. */
+	process_dest_rotation(bvbltparams, batch);
+
+	/* Get a shortcut to the destination surface. */
+	dstinfo = &batch->dstinfo;
+
+	/* Verify if the destination parameter have been modified. */
+	if ((batch->dstbyteshift != dstinfo->bytealign) ||
+	    (batch->dstphyswidth != dstinfo->physwidth) ||
+	    (batch->dstphysheight != dstinfo->physheight)) {
+		/* Set new values. */
+		batch->dstbyteshift = dstinfo->bytealign;
+		batch->dstphyswidth = dstinfo->physwidth;
+		batch->dstphysheight = dstinfo->physheight;
+
+		/* Mark as modified. */
+		batch->batchflags |= BVBATCH_DST;
+	}
+
+	/* Map the destination. */
+	bverror = do_map(bvbltparams->dstdesc, batch, &dstmap);
+	if (bverror != BVERR_NONE) {
+		bvbltparams->errdesc = gccontext->bverrorstr;
+		goto exit;
+	}
+
+	/* Set the new destination. */
+	bverror = set_dst(bvbltparams, batch, dstmap);
+	if (bverror != BVERR_NONE)
+		goto exit;
+
+	/* Reset the modified flag. */
+	batch->batchflags &= ~(BVBATCH_DST |
+			       BVBATCH_CLIPRECT |
+			       BVBATCH_DESTRECT);
+
+	/***********************************************************************
+	** Allocate command buffer.
+	*/
+
+	bverror = claim_buffer(bvbltparams, batch,
+			       sizeof(struct gcmofill),
+			       (void **) &gcmofill);
+	if (bverror != BVERR_NONE)
+		goto exit;
+
+	/***********************************************************************
+	** Set dummy source.
+	*/
+
+	/* Set surface dummy width and height. */
+	gcmofill->src.rotation_ldst = gcmofillsrc_rotation_ldst;
+	gcmofill->src.rotation.raw = 0;
+	gcmofill->src.rotation.reg.surf_width = 1;
+	gcmofill->src.config.raw = 0;
+
+	gcmofill->src.rotationheight_ldst = gcmofillsrc_rotationheight_ldst;
+	gcmofill->src.rotationheight.reg.height = 1;
+	gcmofill->src.rotationangle.raw = 0;
+	gcmofill->src.rotationangle.reg.dst = GCREG_ROT_ANGLE_ROT0;
+	gcmofill->src.rotationangle.reg.dst_mirror = GCREG_MIRROR_NONE;
+
+	/* Disable alpha blending. */
+	gcmofill->src.alphacontrol_ldst = gcmofillsrc_alphacontrol_ldst;
+	gcmofill->src.alphacontrol.raw = 0;
+	gcmofill->src.alphacontrol.reg.enable = GCREG_ALPHA_CONTROL_ENABLE_OFF;
+
+	/***********************************************************************
+	** Set fill color.
+	*/
+
+	fillcolorptr
+		= (unsigned char *) srcinfo->buf.desc->virtaddr
+		+ srcinfo->rect.top * srcinfo->geom->virtstride
+		+ srcinfo->rect.left * srcinfo->format.bitspp / 8;
+
+	gcmofill->clearcolor_ldst = gcmofill_clearcolor_ldst;
+	gcmofill->clearcolor.raw = getinternalcolor(fillcolorptr,
+						    &srcinfo->format);
+
+	/***********************************************************************
+	** Configure and start fill.
+	*/
+
+	/* Set destination configuration. */
+	gcmofill->dstconfig_ldst = gcmofill_dstconfig_ldst;
+	gcmofill->dstconfig.raw = 0;
+	gcmofill->dstconfig.reg.swizzle = dstinfo->format.swizzle;
+	gcmofill->dstconfig.reg.format = dstinfo->format.format;
+	gcmofill->dstconfig.reg.command = GCREG_DEST_CONFIG_COMMAND_CLEAR;
+
+	/* Set ROP3. */
+	gcmofill->rop_ldst = gcmofill_rop_ldst;
+	gcmofill->rop.raw = 0;
+	gcmofill->rop.reg.type = GCREG_ROP_TYPE_ROP3;
+	gcmofill->rop.reg.fg = (unsigned char) bvbltparams->op.rop;
+
+	/* Set START_DE command. */
+	gcmofill->startde.cmd.fld = gcfldstartde;
+
+	/* Set destination rectangle. */
+	gcmofill->rect.left = batch->dstadjusted.left;
+	gcmofill->rect.top = batch->dstadjusted.top;
+	gcmofill->rect.right = batch->dstadjusted.right;
+	gcmofill->rect.bottom = batch->dstadjusted.bottom;
+
+exit:
+	GCEXITARG(GCZONE_FILL, "bv%s = %d\n",
+		  (bverror == BVERR_NONE) ? "result" : "error", bverror);
+	return bverror;
+}
diff --git a/bltsville/gcbv/mirror/gcfilter.c b/bltsville/gcbv/mirror/gcfilter.c
new file mode 100644
index 0000000..525e242
--- /dev/null
+++ b/bltsville/gcbv/mirror/gcfilter.c
@@ -0,0 +1,1788 @@
+/*
+ * Copyright(c) 2012,
+ * Texas Instruments, Inc. and Vivante Corporation.
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *   * Neither the name of Vivante Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "gcbv.h"
+
+#define GCZONE_NONE		0
+#define GCZONE_ALL		(~0U)
+#define GCZONE_KERNEL		(1 << 0)
+#define GCZONE_FILTER		(1 << 1)
+#define GCZONE_BLEND		(1 << 2)
+#define GCZONE_TYPE		(1 << 3)
+#define GCZONE_SRC		(1 << 4)
+#define GCZONE_DEST		(1 << 5)
+#define GCZONE_SURF		(1 << 6)
+
+GCDBG_FILTERDEF(filter, GCZONE_NONE,
+		"kernel",
+		"filter",
+		"blend",
+		"type",
+		"src",
+		"dest",
+		"surf")
+
+
+/*******************************************************************************
+ * Miscellaneous defines.
+ */
+
+#define GC_BYTES_PER_CACHELINE	(64)
+#define GC_BITS_PER_CACHELINE	(GC_BYTES_PER_CACHELINE * 8)
+#define GC_CACHELINE_ALIGN_16	(GC_BITS_PER_CACHELINE / 16 - 1)
+#define GC_CACHELINE_ALIGN_32	(GC_BITS_PER_CACHELINE / 32 - 1)
+
+enum gcscaletype {
+	GC_SCALE_OPF,
+	GC_SCALE_HOR,
+	GC_SCALE_VER,
+	GC_SCALE_HOR_FLIPPED,
+	GC_SCALE_VER_FLIPPED
+};
+
+/*******************************************************************************
+ * Scale factor format: unsigned 1.31 fixed point.
+ */
+
+#define GC_SCALE_TYPE		unsigned int
+#define GC_SCALE_FRACTION	31
+#define GC_SCALE_ONE		((GC_SCALE_TYPE) (1 << GC_SCALE_FRACTION))
+
+
+/*******************************************************************************
+ * X coordinate format: signed 4.28 fixed point.
+ */
+
+#define GC_COORD_TYPE		int
+#define GC_COORD_FRACTION	28
+#define GC_COORD_PI		((GC_COORD_TYPE) 0x3243F6C0)
+#define GC_COORD_2OVERPI	((GC_COORD_TYPE) 0x0A2F9832)
+#define GC_COORD_PIOVER2	((GC_COORD_TYPE) 0x1921FB60)
+#define GC_COORD_ZERO		((GC_COORD_TYPE) 0)
+#define GC_COORD_HALF		((GC_COORD_TYPE) (1 << (GC_COORD_FRACTION - 1)))
+#define GC_COORD_ONE		((GC_COORD_TYPE) (1 << GC_COORD_FRACTION))
+#define GC_COORD_NEGONE		((GC_COORD_TYPE) (~GC_COORD_ONE + 1))
+#define GC_COORD_SUBPIX_STEP	((GC_COORD_TYPE) \
+				(1 << (GC_COORD_FRACTION - GC_PHASE_BITS)))
+
+
+/*******************************************************************************
+ * Hardware coefficient format: signed 2.14 fixed point.
+ */
+
+#define GC_COEF_TYPE		short
+#define GC_COEF_FRACTION	14
+#define GC_COEF_ZERO		((GC_COEF_TYPE) 0)
+#define GC_COEF_ONE		((GC_COEF_TYPE) (1 << GC_COEF_FRACTION))
+#define GC_COEF_NEGONE		((GC_COEF_TYPE) (~GC_COEF_ONE + 1))
+
+
+/*******************************************************************************
+ * Weight sum format: x.28 fixed point.
+ */
+
+#define GC_SUM_TYPE		long long
+#define GC_SUM_FRACTION		GC_COORD_FRACTION
+
+
+/*******************************************************************************
+ * Math shortcuts.
+ */
+
+#define computescale(dstsize, srcsize) ((GC_SCALE_TYPE) \
+	div_u64(((u64) (dstsize)) << GC_SCALE_FRACTION, (srcsize)) \
+)
+
+#define normweight(weight, sum) ((GC_COORD_TYPE) \
+	div64_s64(((s64) (weight)) << GC_COORD_FRACTION, (sum)) \
+)
+
+#define convertweight(weight) ((GC_COEF_TYPE) \
+	((weight) >> (GC_COORD_FRACTION - GC_COEF_FRACTION)) \
+)
+
+
+/*******************************************************************************
+ * Fixed point SINE function. Takes a positive value in range [0..pi/2].
+ */
+
+static GC_COORD_TYPE sine(GC_COORD_TYPE x)
+{
+	static const GC_COORD_TYPE sinetable[] = {
+		0x00000000, 0x001FFFEB, 0x003FFF55, 0x005FFDC0,
+		0x007FFAAB, 0x009FF596, 0x00BFEE01, 0x00DFE36C,
+		0x00FFD557, 0x011FC344, 0x013FACB2, 0x015F9120,
+		0x017F7010, 0x019F4902, 0x01BF1B78, 0x01DEE6F2,
+		0x01FEAAEE, 0x021E66F0, 0x023E1A7C, 0x025DC50C,
+		0x027D6624, 0x029CFD48, 0x02BC89F8, 0x02DC0BB8,
+		0x02FB8204, 0x031AEC64, 0x033A4A5C, 0x03599B64,
+		0x0378DF08, 0x039814CC, 0x03B73C2C, 0x03D654B0,
+		0x03F55DDC, 0x04145730, 0x04334030, 0x04521868,
+		0x0470DF58, 0x048F9488, 0x04AE3770, 0x04CCC7A8,
+		0x04EB44A8, 0x0509ADF8, 0x05280328, 0x054643B0,
+		0x05646F28, 0x05828508, 0x05A084E0, 0x05BE6E38,
+		0x05DC4098, 0x05F9FB80, 0x06179E88, 0x06352928,
+		0x06529AF8, 0x066FF380, 0x068D3248, 0x06AA56D8,
+		0x06C760C0, 0x06E44F90, 0x070122C8, 0x071DD9F8,
+		0x073A74B8, 0x0756F290, 0x07735308, 0x078F95B0,
+		0x07ABBA20, 0x07C7BFD8, 0x07E3A678, 0x07FF6D88,
+		0x081B14A0, 0x08369B40, 0x08520110, 0x086D4590,
+		0x08886860, 0x08A36910, 0x08BE4730, 0x08D90250,
+		0x08F39A20, 0x090E0E10, 0x09285DD0, 0x094288E0,
+		0x095C8EF0, 0x09766F90, 0x09902A60, 0x09A9BEE0,
+		0x09C32CC0, 0x09DC7390, 0x09F592F0, 0x0A0E8A70,
+		0x0A2759C0, 0x0A400070, 0x0A587E20, 0x0A70D270,
+		0x0A88FD00, 0x0AA0FD60, 0x0AB8D350, 0x0AD07E50,
+		0x0AE7FE10, 0x0AFF5230, 0x0B167A50, 0x0B2D7610,
+		0x0B444520, 0x0B5AE730, 0x0B715BC0, 0x0B87A290,
+		0x0B9DBB40, 0x0BB3A580, 0x0BC960F0, 0x0BDEED30,
+		0x0BF44A00, 0x0C0976F0, 0x0C1E73D0, 0x0C334020,
+		0x0C47DBB0, 0x0C5C4620, 0x0C707F20, 0x0C848660,
+		0x0C985B80, 0x0CABFE50, 0x0CBF6E60, 0x0CD2AB80,
+		0x0CE5B550, 0x0CF88B80, 0x0D0B2DE0, 0x0D1D9C10,
+		0x0D2FD5C0, 0x0D41DAB0, 0x0D53AAA0, 0x0D654540,
+		0x0D76AA40, 0x0D87D970, 0x0D98D280, 0x0DA99530,
+		0x0DBA2140, 0x0DCA7650, 0x0DDA9450, 0x0DEA7AD0,
+		0x0DFA29B0, 0x0E09A0B0, 0x0E18DF80, 0x0E27E5F0,
+		0x0E36B3C0, 0x0E4548B0, 0x0E53A490, 0x0E61C720,
+		0x0E6FB020, 0x0E7D5F70, 0x0E8AD4C0, 0x0E980FF0,
+		0x0EA510B0, 0x0EB1D6F0, 0x0EBE6260, 0x0ECAB2D0,
+		0x0ED6C810, 0x0EE2A200, 0x0EEE4070, 0x0EF9A310,
+		0x0F04C9E0, 0x0F0FB490, 0x0F1A6300, 0x0F24D510,
+		0x0F2F0A80, 0x0F390340, 0x0F42BF10, 0x0F4C3DE0,
+		0x0F557F70, 0x0F5E83C0, 0x0F674A80, 0x0F6FD3B0,
+		0x0F781F20, 0x0F802CB0, 0x0F87FC40, 0x0F8F8DA0,
+		0x0F96E0D0, 0x0F9DF5B0, 0x0FA4CC00, 0x0FAB63D0,
+		0x0FB1BCF0, 0x0FB7D740, 0x0FBDB2B0, 0x0FC34F30,
+		0x0FC8ACA0, 0x0FCDCAF0, 0x0FD2AA10, 0x0FD749E0,
+		0x0FDBAA50, 0x0FDFCB50, 0x0FE3ACD0, 0x0FE74EC0,
+		0x0FEAB110, 0x0FEDD3C0, 0x0FF0B6B0, 0x0FF359F0,
+		0x0FF5BD50, 0x0FF7E0E0, 0x0FF9C490, 0x0FFB6850,
+		0x0FFCCC30, 0x0FFDF010, 0x0FFED400, 0x0FFF77F0,
+		0x0FFFDBF0, 0x0FFFFFE0, 0x0FFFE3D0, 0x0FFF87D0,
+		0x0FFEEBC0, 0x0FFE0FC0, 0x0FFCF3D0, 0x0FFB97E0
+	};
+
+	enum {
+		indexwidth = 8,
+		intwidth = 1,
+		indexshift = intwidth
+			   + GC_COORD_FRACTION
+			   - indexwidth
+	};
+
+	unsigned int p1, p2;
+	GC_COORD_TYPE p1x, p2x;
+	GC_COORD_TYPE p1y, p2y;
+	GC_COORD_TYPE dx, dy;
+	GC_COORD_TYPE a, b;
+	GC_COORD_TYPE result;
+
+	/* Determine the indices of two closest points in the table. */
+	p1 = ((unsigned int) x) >> indexshift;
+	p2 =  p1 + 1;
+
+	if ((p1 >= countof(sinetable)) || (p2 >= countof(sinetable))) {
+		GCERR("invalid table index.\n");
+		return GC_COORD_ZERO;
+	}
+
+	/* Determine the coordinates of the two closest points.  */
+	p1x = p1 << indexshift;
+	p2x = p2 << indexshift;
+
+	p1y = sinetable[p1];
+	p2y = sinetable[p2];
+
+	/* Determine the deltas. */
+	dx = p2x - p1x;
+	dy = p2y - p1y;
+
+	/* Find the slope and the y-intercept. */
+	b = (GC_COORD_TYPE) div64_s64(((s64) dy) << GC_COORD_FRACTION, dx);
+	a = p1y - (GC_COORD_TYPE) (((s64) b * p1x) >> GC_COORD_FRACTION);
+
+	/* Compute the result. */
+	result = a + (GC_COORD_TYPE) (((s64) b * x) >> GC_COORD_FRACTION);
+	return result;
+}
+
+
+/*******************************************************************************
+ * SINC function used in filter kernel generation.
+ */
+
+static GC_COORD_TYPE sinc_filter(GC_COORD_TYPE x, int radius)
+{
+	GC_COORD_TYPE result;
+	s64 radius64;
+	s64 pit, pitd;
+	s64 normpit, normpitd;
+	int negpit, negpitd;
+	int quadpit, quadpitd;
+	GC_COORD_TYPE sinpit, sinpitd;
+	GC_COORD_TYPE f1, f2;
+
+	if (x == GC_COORD_ZERO)
+		return GC_COORD_ONE;
+
+	radius64 = abs(radius) << GC_COORD_FRACTION;
+	if (x > radius64)
+		return GC_COORD_ZERO;
+
+	pit  = (((s64) GC_COORD_PI) * x) >> GC_COORD_FRACTION;
+	pitd = div_s64(pit, radius);
+
+	/* Sine table only has values for the first positive quadrant,
+	 * remove the sign here. */
+	if (pit < 0) {
+		normpit = -pit;
+		negpit = 1;
+	} else {
+		normpit = pit;
+		negpit = 0;
+	}
+
+	if (pitd < 0) {
+		normpitd = -pitd;
+		negpitd = 1;
+	} else {
+		normpitd = pitd;
+		negpitd = 0;
+	}
+
+	/* Determine which quadrant we are in. */
+	quadpit = (int) ((normpit * GC_COORD_2OVERPI)
+		>> (2 * GC_COORD_FRACTION));
+	quadpitd = (int) ((normpitd * GC_COORD_2OVERPI)
+		>> (2 * GC_COORD_FRACTION));
+
+	/* Move coordinates to the first quadrant. */
+	normpit -= (s64) GC_COORD_PIOVER2 * quadpit;
+	normpitd -= (s64) GC_COORD_PIOVER2 * quadpitd;
+
+	/* Normalize the quadrant numbers. */
+	quadpit %= 4;
+	quadpitd %= 4;
+
+	/* Flip the coordinates if necessary. */
+	if ((quadpit == 1) || (quadpit == 3))
+		normpit = GC_COORD_PIOVER2 - normpit;
+
+	if ((quadpitd == 1) || (quadpitd == 3))
+		normpitd = GC_COORD_PIOVER2 - normpitd;
+
+	sinpit = sine((GC_COORD_TYPE) normpit);
+	sinpitd = sine((GC_COORD_TYPE) normpitd);
+
+	/* Negate depending on the quadrant. */
+	if (negpit) {
+		if ((quadpit == 0) || (quadpit == 1))
+			sinpit = -sinpit;
+	} else {
+		if ((quadpit == 2) || (quadpit == 3))
+			sinpit = -sinpit;
+	}
+
+	if (negpitd) {
+		if ((quadpitd == 0) || (quadpitd == 1))
+			sinpitd = -sinpitd;
+	} else {
+		if ((quadpitd == 2) || (quadpitd == 3))
+			sinpitd = -sinpitd;
+	}
+
+	f1 = (GC_COORD_TYPE)
+	     div64_s64(((s64) sinpit) << GC_COORD_FRACTION, pit);
+	f2 = (GC_COORD_TYPE)
+	     div64_s64(((s64) sinpitd) << GC_COORD_FRACTION, pitd);
+
+	result = (GC_COORD_TYPE) ((((s64) f1) * f2)
+	       >> GC_COORD_FRACTION);
+
+	return result;
+}
+
+
+/*******************************************************************************
+ * Filter kernel generator based on SINC function.
+ */
+
+static void calculate_sync_filter(struct gcfilterkernel *gcfilterkernel)
+{
+	GC_SCALE_TYPE scale;
+	GC_COORD_TYPE subpixset[GC_TAP_COUNT];
+	GC_COORD_TYPE subpixeloffset;
+	GC_COORD_TYPE x, weight;
+	GC_SUM_TYPE weightsum;
+	short convweightsum;
+	int kernelhalf, padding;
+	int subpixpos, kernelpos;
+	short *kernelarray;
+	short count, adjustfrom, adjustment;
+	int index;
+
+	/* Compute the scale factor. */
+	scale = (gcfilterkernel->dstsize >= gcfilterkernel->srcsize)
+	      ? GC_SCALE_ONE
+	      : computescale(gcfilterkernel->dstsize, gcfilterkernel->srcsize);
+
+	/* Calculate the kernel half. */
+	kernelhalf = (int) (gcfilterkernel->kernelsize >> 1);
+
+	/* Init the subpixel offset. */
+	subpixeloffset = GC_COORD_HALF;
+
+	/* Determine kernel padding size. */
+	padding = (GC_TAP_COUNT - gcfilterkernel->kernelsize) / 2;
+
+	/* Set initial kernel array pointer. */
+	kernelarray = gcfilterkernel->kernelarray;
+
+	/* Loop through each subpixel. */
+	for (subpixpos = 0; subpixpos < GC_PHASE_LOAD_COUNT; subpixpos += 1) {
+		/* Compute weights. */
+		weightsum = GC_COORD_ZERO;
+		for (kernelpos = 0; kernelpos < GC_TAP_COUNT; kernelpos += 1) {
+			/* Determine the current index. */
+			index = kernelpos - padding;
+
+			/* Pad with zeros left side. */
+			if (index < 0) {
+				subpixset[kernelpos] = GC_COORD_ZERO;
+				continue;
+			}
+
+			/* Pad with zeros right side. */
+			if (index >= (int) gcfilterkernel->kernelsize) {
+				subpixset[kernelpos] = GC_COORD_ZERO;
+				continue;
+			}
+
+			/* "Filter off" case. */
+			if (gcfilterkernel->kernelsize == 1) {
+				subpixset[kernelpos] = GC_COORD_ONE;
+
+				/* Update the sum of the weights. */
+				weightsum += GC_COORD_ONE;
+				continue;
+			}
+
+			/* Compute X coordinate. */
+			x = ((index - kernelhalf) << GC_COORD_FRACTION)
+			  + subpixeloffset;
+
+			/* Scale the coordinate. */
+			x = (GC_COORD_TYPE)
+			    ((((s64) x) * scale) >> GC_SCALE_FRACTION);
+
+			/* Compute the weight. */
+			subpixset[kernelpos] = sinc_filter(x, kernelhalf);
+
+			/* Update the sum of the weights. */
+			weightsum += subpixset[kernelpos];
+		}
+
+		/* Convert the weights to the hardware format. */
+		convweightsum = 0;
+		for (kernelpos = 0; kernelpos < GC_TAP_COUNT; kernelpos += 1) {
+			/* Normalize the current weight. */
+			weight = normweight(subpixset[kernelpos], weightsum);
+
+			/* Convert the weight to fixed point. */
+			if (weight == GC_COORD_ZERO)
+				kernelarray[kernelpos] = GC_COEF_ZERO;
+			else if (weight >= GC_COORD_ONE)
+				kernelarray[kernelpos] = GC_COEF_ONE;
+			else if (weight <= GC_COORD_NEGONE)
+				kernelarray[kernelpos] = GC_COEF_NEGONE;
+			else
+				kernelarray[kernelpos] = convertweight(weight);
+
+			/* Compute the sum of all coefficients. */
+			convweightsum += kernelarray[kernelpos];
+		}
+
+		/* Adjust the fixed point coefficients so that the sum is 1. */
+		count = GC_COEF_ONE - convweightsum;
+		if (count < 0) {
+			count = -count;
+			adjustment = -1;
+		} else {
+			adjustment = 1;
+		}
+
+		if (count > GC_TAP_COUNT) {
+			GCERR("adjust count is too high = %d\n", count);
+		} else {
+			adjustfrom = (GC_TAP_COUNT - count) / 2;
+			for (kernelpos = 0; kernelpos < count; kernelpos += 1)
+				kernelarray[adjustfrom + kernelpos]
+					+= adjustment;
+		}
+
+		/* Advance the array pointer. */
+		kernelarray += GC_TAP_COUNT;
+
+		/* Advance to the next subpixel. */
+		subpixeloffset -= GC_COORD_SUBPIX_STEP;
+	}
+}
+
+
+/*******************************************************************************
+ * Loads a filter into the GPU.
+ */
+
+static enum bverror load_filter(struct bvbltparams *bvbltparams,
+				struct gcbatch *batch,
+				enum gcfiltertype type,
+				unsigned int kernelsize,
+				unsigned int scalefactor,
+				unsigned int srcsize,
+				unsigned int dstsize,
+				struct gccmdldstate arraystate)
+{
+	enum bverror bverror = BVERR_NONE;
+	struct gccontext *gccontext = get_context();
+	struct gcfiltercache *filtercache;
+	struct list_head *filterlist;
+	struct list_head *filterhead;
+	struct gcfilterkernel *gcfilterkernel;
+	struct gcmofilterkernel *gcmofilterkernel;
+
+	GCDBG(GCZONE_KERNEL, "kernelsize = %d\n", kernelsize);
+	GCDBG(GCZONE_KERNEL, "srcsize = %d\n", srcsize);
+	GCDBG(GCZONE_KERNEL, "dstsize = %d\n", dstsize);
+	GCDBG(GCZONE_KERNEL, "scalefactor = 0x%08X\n", scalefactor);
+
+	/* Is the filter already loaded? */
+	if ((gccontext->loadedfilter != NULL) &&
+	    (gccontext->loadedfilter->type == type) &&
+	    (gccontext->loadedfilter->kernelsize == kernelsize) &&
+	    (gccontext->loadedfilter->scalefactor == scalefactor)) {
+		GCDBG(GCZONE_KERNEL, "filter already computed.\n");
+		gcfilterkernel = gccontext->loadedfilter;
+		goto load;
+	}
+
+	/* Get the proper filter cache. */
+	filtercache = &gccontext->filtercache[type][kernelsize];
+	filterlist = &filtercache->list;
+
+	/* Try to find existing filter. */
+	GCDBG(GCZONE_KERNEL, "scanning for existing filter.\n");
+	list_for_each(filterhead, filterlist) {
+		gcfilterkernel = list_entry(filterhead,
+					    struct gcfilterkernel,
+					    link);
+		if (gcfilterkernel->scalefactor == scalefactor) {
+			GCDBG(GCZONE_KERNEL, "filter found @ 0x%08X.\n",
+			      (unsigned int) gcfilterkernel);
+			break;
+		}
+	}
+
+	/* Found the filter? */
+	if (filterhead != filterlist) {
+		/* Move the filter to the head of the list. */
+		if (filterlist->next != filterhead) {
+			GCDBG(GCZONE_KERNEL, "moving to the head.\n");
+			list_move(filterhead, filterlist);
+		}
+	} else {
+		GCDBG(GCZONE_KERNEL, "filter not found.\n");
+		if (filtercache->count == GC_FILTER_CACHE_MAX) {
+			GCDBG(GCZONE_KERNEL,
+			      "reached the maximum number of filters.\n");
+			filterhead = filterlist->prev;
+			list_move(filterhead, filterlist);
+
+			gcfilterkernel = list_entry(filterhead,
+						    struct gcfilterkernel,
+						    link);
+		} else {
+			GCDBG(GCZONE_KERNEL, "allocating new filter.\n");
+			gcfilterkernel = gcalloc(struct gcfilterkernel,
+						 sizeof(struct gcfilterkernel));
+			if (gcfilterkernel == NULL) {
+				BVSETBLTERROR(BVERR_OOM,
+					      "filter allocation failed");
+				goto exit;
+			}
+
+			list_add(&gcfilterkernel->link, filterlist);
+		}
+
+		/* Update the number of filters. */
+		filtercache->count += 1;
+
+		/* Initialize the filter. */
+		gcfilterkernel->type = type;
+		gcfilterkernel->kernelsize = kernelsize;
+		gcfilterkernel->srcsize = srcsize;
+		gcfilterkernel->dstsize = dstsize;
+		gcfilterkernel->scalefactor = scalefactor;
+
+		/* Compute the coefficients. */
+		calculate_sync_filter(gcfilterkernel);
+	}
+
+load:
+	GCDBG(GCZONE_KERNEL, "loading filter.\n");
+
+	/* Load the filter. */
+	bverror = claim_buffer(bvbltparams, batch,
+			       sizeof(struct gcmofilterkernel),
+			       (void **) &gcmofilterkernel);
+	if (bverror != BVERR_NONE)
+		goto exit;
+
+	gcmofilterkernel->kernelarray_ldst = arraystate;
+	memcpy(&gcmofilterkernel->kernelarray,
+	       gcfilterkernel->kernelarray,
+	       sizeof(gcfilterkernel->kernelarray));
+
+	/* Set the filter. */
+	gccontext->loadedfilter = gcfilterkernel;
+
+exit:
+	return bverror;
+}
+
+
+/*******************************************************************************
+ * Compute the scale factor.
+ */
+
+static inline unsigned int get_scale_factor(unsigned int srcsize,
+					    unsigned int dstsize)
+{
+	if ((srcsize <= 1) || (dstsize <= 1))
+		return 0;
+
+	return ((srcsize - 1) << 16) / (dstsize - 1);
+}
+
+
+/*******************************************************************************
+ * Rotates the specified rectangle to the specified angle.
+ */
+
+static void rotate_gcrect(int angle,
+			  struct bvsurfgeom *srcgeom, struct gcrect *srcrect,
+			  struct bvsurfgeom *dstgeom, struct gcrect *dstrect)
+{
+	unsigned int width, height;
+	struct gcrect rect;
+
+	GCENTER(GCZONE_SURF);
+
+	GCDBG(GCZONE_SURF, "src geom size = %dx%d\n",
+	      srcgeom->width, srcgeom->height);
+
+	switch (angle) {
+	case ROT_ANGLE_0:
+		GCDBG(GCZONE_SURF, "ROT_ANGLE_0\n");
+
+		if (dstgeom != srcgeom) {
+			dstgeom->width  = srcgeom->width;
+			dstgeom->height = srcgeom->height;
+		}
+
+		if (dstrect != srcrect)
+			*dstrect = *srcrect;
+		break;
+
+	case ROT_ANGLE_90:
+		GCDBG(GCZONE_SURF, "ROT_ANGLE_90\n");
+
+		width  = srcgeom->width;
+		height = srcgeom->height;
+
+		dstgeom->width  = height;
+		dstgeom->height = width;
+
+		rect.left   = height - srcrect->bottom;
+		rect.top    = srcrect->left;
+		rect.right  = height - srcrect->top;
+		rect.bottom = srcrect->right;
+
+		*dstrect = rect;
+		break;
+
+	case ROT_ANGLE_180:
+		GCDBG(GCZONE_SURF, "ROT_ANGLE_180\n");
+
+		width  = srcgeom->width;
+		height = srcgeom->height;
+
+		if (dstgeom != srcgeom) {
+			dstgeom->width  = width;
+			dstgeom->height = height;
+		}
+
+		rect.left   = width  - srcrect->right;
+		rect.top    = height - srcrect->bottom;
+		rect.right  = width  - srcrect->left;
+		rect.bottom = height - srcrect->top;
+
+		*dstrect = rect;
+		break;
+
+	case ROT_ANGLE_270:
+		GCDBG(GCZONE_SURF, "ROT_ANGLE_270\n");
+
+		width  = srcgeom->width;
+		height = srcgeom->height;
+
+		dstgeom->width  = height;
+		dstgeom->height = width;
+
+		rect.left   = srcrect->top;
+		rect.top    = width - srcrect->right;
+		rect.right  = srcrect->bottom;
+		rect.bottom = width - srcrect->left;
+
+		*dstrect = rect;
+		break;
+	}
+
+	GCEXIT(GCZONE_SURF);
+}
+
+
+/*******************************************************************************
+ * Setup destination rotation parameters.
+ */
+
+void process_rotation(struct bvbltparams *bvbltparams,
+		      struct gcbatch *batch,
+		      struct surfaceinfo *srcinfo,
+		      int adjangle)
+{
+	GCENTER(GCZONE_DEST);
+
+	if (srcinfo->newgeom ||
+	    ((batch->batchflags & (BVBATCH_CLIPRECT |
+				   BVBATCH_DESTRECT |
+				   BVBATCH_DST)) != 0)) {
+		bool orthogonal;
+		struct gcfilter *gcfilter;
+		struct surfaceinfo *dstinfo;
+		int dstoffsetX, dstoffsetY;
+
+		/* Get some shortcuts. */
+		dstinfo = &batch->dstinfo;