qcom/display: Update HALs
- Update the display HAL from Code Aurora Forum
- Add updated overlay library
- Enable HWC with basic video going through overlay
- Cleanup some files
Change-Id: I65c687c51be458cee71213c79e03eeda962d9086
diff --git a/libcopybit/Android.mk b/libcopybit/Android.mk
new file mode 100644
index 0000000..24663b7
--- /dev/null
+++ b/libcopybit/Android.mk
@@ -0,0 +1,59 @@
+# Copyright (C) 2008 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.
+
+
+LOCAL_PATH:= $(call my-dir)
+# HAL module implemenation, not prelinked and stored in
+# hw/<COPYPIX_HARDWARE_MODULE_ID>.<ro.board.platform>.so
+
+ifeq ($(TARGET_USES_C2D_COMPOSITION),true)
+ include $(CLEAR_VARS)
+ LOCAL_PRELINK_MODULE := false
+ LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
+ LOCAL_SHARED_LIBRARIES := liblog libdl libcutils libmemalloc libutils
+ LOCAL_SRC_FILES := copybit_c2d.cpp software_converter.cpp
+ LOCAL_MODULE := copybit.$(TARGET_BOARD_PLATFORM)
+ LOCAL_C_INCLUDES += hardware/qcom/display/libgralloc
+ LOCAL_CFLAGS += -DCOPYBIT_Z180=1 -DC2D_SUPPORT_DISPLAY=1
+ LOCAL_MODULE_TAGS := optional
+ include $(BUILD_SHARED_LIBRARY)
+else
+ ifneq ($(call is-chipset-in-board-platform,msm7630),true)
+ ifeq ($(call is-board-platform-in-list,$(MSM7K_BOARD_PLATFORMS)),true)
+ include $(CLEAR_VARS)
+ ifeq ($(ARCH_ARM_HAVE_NEON),true)
+ LOCAL_CFLAGS += -D__ARM_HAVE_NEON
+ endif
+ ifeq ($(call is-board-platform,msm7627a),true)
+ LOCAL_CFLAGS += -DTARGET_7x27A
+ endif
+ ifeq ($(TARGET_GRALLOC_USES_ASHMEM),true)
+ LOCAL_CFLAGS += -DUSE_ASHMEM
+ ifeq ($(call is-chipset-prefix-in-board-platform,msm7627),true)
+ LOCAL_CFLAGS += -DTARGET_7x27
+ endif
+ endif
+
+ LOCAL_PRELINK_MODULE := false
+ LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
+ LOCAL_SHARED_LIBRARIES := liblog libmemalloc
+ LOCAL_SRC_FILES := software_converter.cpp copybit.cpp
+ LOCAL_MODULE := copybit.$(TARGET_BOARD_PLATFORM)
+ LOCAL_MODULE_TAGS := optional
+ LOCAL_C_INCLUDES += $(TARGET_OUT_HEADERS)/qcom/display/libgralloc
+ LOCAL_CFLAGS += -DCOPYBIT_MSM7K=1
+ include $(BUILD_SHARED_LIBRARY)
+ endif
+ endif
+endif
diff --git a/libcopybit/MODULE_LICENSE_APACHE2 b/libcopybit/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/libcopybit/MODULE_LICENSE_APACHE2
diff --git a/libcopybit/NOTICE b/libcopybit/NOTICE
new file mode 100644
index 0000000..9c1e63a
--- /dev/null
+++ b/libcopybit/NOTICE
@@ -0,0 +1,189 @@
+
+ Copyright (c) 2008, 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.
+
+ 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.
+
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
diff --git a/libcopybit/c2d2.h b/libcopybit/c2d2.h
new file mode 100644
index 0000000..8c7d05b
--- /dev/null
+++ b/libcopybit/c2d2.h
@@ -0,0 +1,618 @@
+/* Copyright (c) 2010-2012, Code Aurora Forum. 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 Code Aurora Forum, 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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 __c2d2_h_
+#define __c2d2_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef C2D_API
+#define C2D_API /* define API export as needed */
+#endif
+#if !defined(int32) && !defined(_INT32_DEFINED)
+typedef int int32;
+#define _INT32_DEFINED
+#endif
+#if !defined(uint32) && !defined(_UINT32_DEFINED)
+typedef unsigned int uint32;
+#define _UINT32_DEFINED
+#endif
+
+/*****************************************************************************/
+/*********************** Blit definitions *****************************/
+/*****************************************************************************/
+
+/* Status codes, returned by any blit function */
+typedef enum {
+ C2D_STATUS_OK = 0,
+ C2D_STATUS_NOT_SUPPORTED = 1,
+ C2D_STATUS_OUT_OF_MEMORY = 2,
+ C2D_STATUS_INVALID_PARAM = 3,
+ C2D_STATUS_SURFACE_IN_USE = 4,
+} C2D_STATUS;
+
+
+/* Definitions of color format modes, used together with color formats */
+typedef enum {
+ C2D_FORMAT_PACK_INTO_32BIT = (1 << 8), /* pack into dword if set */
+ C2D_FORMAT_SWAP_ENDIANNESS = (1 << 9), /* swaps the order */
+ C2D_FORMAT_LINEAR_SPACE = (1 << 10), /* linear color space */
+ C2D_FORMAT_PREMULTIPLIED = (1 << 11), /* alpha premultiplied */
+ C2D_FORMAT_INVERT_ALPHA = (1 << 12), /* inverts alpha */
+ C2D_FORMAT_DISABLE_ALPHA = (1 << 13), /* disables alpha */
+ C2D_FORMAT_INTERLACED = (1 << 14), /* YUV line-interlaced */
+ C2D_FORMAT_TRANSPARENT = (1 << 15), /* YUV 1-bit alpha in Y */
+ C2D_FORMAT_MACROTILED = (1 << 16), /* tiled in macro level */
+ C2D_FORMAT_TILED_4x4 = (1 << 17), /* 4x4 tiled format */
+ C2D_FORMAT_SWAP_RB = (1 << 18), /* Swap R & B color components */
+} C2D_FORMAT_MODE;
+
+/* Definitions of supported RGB formats, used in C2D_RGB_SURFACE_DEF.
+ * The bits of each color channel are packed into a machine word
+ * representing a single pixel from left to right (MSB to LSB) in the
+ * order indicated by format name. For the sub-byte formats the pixels
+ * are packed into bytes from left to right (MSbit to LSBit).
+ * If the C2D_FORMAT_PACK_INTO_32BIT bit is set, the minimal
+ * machine word used for pixel storage is 32-bit and the whole word
+ * is reversed if endianness is swapped.
+ * If the C2D_FORMAT_SWAP_ENDIANNESS bit is set, the order within a
+ * minimal machine word representing a pixel
+ * is reversed for both sub-byte and multi-byte formats.
+ * If the C2D_FORMAT_LINEAR_SPACE bit is set, the color space of
+ * the formats below is considered linear, if applicable.
+ * If the C2D_FORMAT_PREMULTIPLIED bit is set, the color channels
+ * are premultiplied with the alpha, if applicable.
+ * If the C2D_FORMAT_INVERT_ALPHA bit is set, the alpha interpretation
+ * is inverted: 0 - opaque, 1 - transparent, if applicable.
+ * If the C2D_FORMAT_DISABLE_ALPHA bit is set, the alpha channel serves
+ * as a placeholder and is ignored during blit, if applicable.
+ * If the C2D_FORMAT_MACROTILED bit is set, the surface is in the
+ * tiled format : 64x32 for 8bpp, 32x32 for 16bpp formats */
+typedef enum {
+ C2D_COLOR_FORMAT_1 = 0, /* 1-bit alpha/color expansion */
+
+ C2D_COLOR_FORMAT_2_PALETTE = 1, /* 2-bit indices for palette */
+ C2D_COLOR_FORMAT_4_PALETTE = 2, /* 4-bit indices for palette */
+ C2D_COLOR_FORMAT_8_PALETTE = 3, /* 8-bit indices for palette */
+
+ C2D_COLOR_FORMAT_2_L = 4, /* 2-bit grayscale */
+ C2D_COLOR_FORMAT_4_L = 5, /* 4-bit grayscale */
+ C2D_COLOR_FORMAT_8_L = 6, /* 8-bit grayscale */
+
+ C2D_COLOR_FORMAT_2_A = 7, /* 2-bit alpha only */
+ C2D_COLOR_FORMAT_4_A = 8, /* 4-bit alpha only */
+ C2D_COLOR_FORMAT_8_A = 9, /* 8-bit alpha only */
+
+ C2D_COLOR_FORMAT_444_RGB = 10, /* 12-bit colors */
+ C2D_COLOR_FORMAT_565_RGB = 11, /* 16-bit colors */
+ C2D_COLOR_FORMAT_888_RGB = 12, /* 24-bit colors */
+
+ C2D_COLOR_FORMAT_1555_ARGB = 13, /* 16-bit colors (1-bit alpha) */
+ C2D_COLOR_FORMAT_4444_ARGB = 14, /* 16-bit colors (4-bit alpha) */
+ C2D_COLOR_FORMAT_8565_ARGB = 15, /* 24-bit colors (8-bit alpha) */
+ C2D_COLOR_FORMAT_8888_ARGB = 16, /* 32-bit colors (8-bit alpha) */
+
+ C2D_COLOR_FORMAT_5551_RGBA = 17, /* 16-bit colors (1-bit alpha) */
+ C2D_COLOR_FORMAT_4444_RGBA = 18, /* 16-bit colors (4-bit alpha) */
+ C2D_COLOR_FORMAT_5658_RGBA = 19, /* 24-bit colors (8-bit alpha) */
+ C2D_COLOR_FORMAT_8888_RGBA = 20, /* 32-bit colors (8-bit alpha) */
+
+ /* derived RGB color formats (base format + mode bits) */
+
+} C2D_RGB_FORMAT;
+
+/* Definitions of supported YUV formats, used in C2D_YUV_SURFACE_DEF.
+ * Each of Y,U,V channels usually takes 1 byte and therefore is
+ * individually addressable. The definitions below show how Y,U,V
+ * channels are packed into macropixels for each particular format.
+ * The order is from left (smaller byte addresses) to right (larger
+ * byte addresses). The first three digits (4xx) denote the chroma
+ * subsampling in standard YUV notation. The digits in the macropixel
+ * denote that the whole block (from the previous digit or from the
+ * beginning) has to be repeated the number of times. Underscores
+ * between Y,U,V channels are used to describe separate planes for
+ * planar YUV formats. Formats are mapped to numbers so that future
+ * versions with various YUV permutations are easy to add.
+ * If the C2D_FORMAT_INTERLACED bit is set, the line order is
+ * interlaced: 0,2,4,...1,3,5... if applicable.
+ * If the C2D_FORMAT_TRANSPARENT bit is set, the least significant
+ * bit of Y channel serves as alpha: 0 - transparent, 1 - opaque. */
+typedef enum {
+ C2D_COLOR_FORMAT_411_YYUYYV = 110, /* packed, 12-bit */
+ C2D_COLOR_FORMAT_411_YUYYVY = 111, /* packed, 12-bit */
+ C2D_COLOR_FORMAT_411_UYYVYY = 112, /* packed, 12-bit, "Y411" */
+ C2D_COLOR_FORMAT_411_YUYV2Y4 = 116, /* packed, 12-bit */
+ C2D_COLOR_FORMAT_411_UYVY2Y4 = 117, /* packed, 12-bit, "Y41P" */
+
+ C2D_COLOR_FORMAT_422_YUYV = 120, /* packed, 16-bit, "YUY2" */
+ C2D_COLOR_FORMAT_422_UYVY = 121, /* packed, 16-bit, "UYVY" */
+ C2D_COLOR_FORMAT_422_YVYU = 122, /* packed, 16-bit, "YVYU" */
+ C2D_COLOR_FORMAT_422_VYUY = 123, /* packed, 16-bit */
+
+ C2D_COLOR_FORMAT_444_YUV = 130, /* packed, 24-bit */
+ C2D_COLOR_FORMAT_444_UYV = 131, /* packed, 24-bit, "IYU2" */
+ C2D_COLOR_FORMAT_444_AYUV = 136, /* packed, 24-bit, "AYUV" */
+
+ C2D_COLOR_FORMAT_410_Y_UV = 150, /* planar, Y + interleaved UV */
+ C2D_COLOR_FORMAT_411_Y_UV = 151, /* planar, Y + interleaved UV */
+ C2D_COLOR_FORMAT_420_Y_UV = 152, /* planar, Y + interleaved UV */
+ C2D_COLOR_FORMAT_422_Y_UV = 153, /* planar, Y + interleaved UV */
+ C2D_COLOR_FORMAT_444_Y_UV = 154, /* planar, Y + interleaved UV */
+
+ C2D_COLOR_FORMAT_410_Y_VU = 160, /* planar, Y + interleaved VU */
+ C2D_COLOR_FORMAT_411_Y_VU = 161, /* planar, Y + interleaved VU */
+ C2D_COLOR_FORMAT_420_Y_VU = 162, /* planar, Y + interleaved VU */
+ C2D_COLOR_FORMAT_422_Y_VU = 163, /* planar, Y + interleaved VU */
+ C2D_COLOR_FORMAT_444_Y_VU = 164, /* planar, Y + interleaved VU */
+
+ C2D_COLOR_FORMAT_410_Y_U_V = 170, /* planar, Y + U + V separate */
+ C2D_COLOR_FORMAT_411_Y_U_V = 171, /* planar, Y + U + V separate */
+ C2D_COLOR_FORMAT_420_Y_V_U = 172, /* planar, Y + V + U separate */
+ C2D_COLOR_FORMAT_420_Y_U_V = 173, /* planar, Y + U + V separate */
+ C2D_COLOR_FORMAT_422_Y_U_V = 174, /* planar, Y + U + V separate */
+ C2D_COLOR_FORMAT_444_Y_U_V = 175, /* planar, Y + U + V separate */
+
+ C2D_COLOR_FORMAT_800_Y = 190, /* planar, Y only, grayscale */
+
+ /* derived YUV color formats (base format + mode bits), FOURCC */
+
+ C2D_COLOR_FORMAT_411_Y411 = 112,
+ C2D_COLOR_FORMAT_411_Y41P = 117,
+ C2D_COLOR_FORMAT_411_IY41 = 117 | (1 << 14),
+ C2D_COLOR_FORMAT_411_Y41T = 117 | (1 << 15),
+
+ C2D_COLOR_FORMAT_422_YUY2 = 120,
+ C2D_COLOR_FORMAT_422_IUYV = 121 | (1 << 14),
+ C2D_COLOR_FORMAT_422_Y42T = 121 | (1 << 15),
+ C2D_COLOR_FORMAT_444_IYU2 = 131,
+
+ C2D_COLOR_FORMAT_420_NV12 = 152,
+ C2D_COLOR_FORMAT_420_NV21 = 162,
+
+ C2D_COLOR_FORMAT_410_YUV9 = 170,
+ C2D_COLOR_FORMAT_410_YVU9 = 170,
+ C2D_COLOR_FORMAT_411_Y41B = 171,
+ C2D_COLOR_FORMAT_420_YV12 = 172,
+ C2D_COLOR_FORMAT_420_IYUV = 173,
+ C2D_COLOR_FORMAT_420_I420 = 173,
+ C2D_COLOR_FORMAT_422_YV16 = 174,
+ C2D_COLOR_FORMAT_422_Y42B = 174,
+
+ C2D_COLOR_FORMAT_800_Y800 = 190,
+
+} C2D_YUV_FORMAT;
+
+
+/* Configuration bits, used in the config_mask field of C2D_OBJECT struct */
+typedef enum {
+ C2D_SOURCE_RECT_BIT = (1 << 0), /* enables source_rect field */
+ C2D_MIRROR_H_BIT = (1 << 1), /* enables horizontal flipping */
+ C2D_MIRROR_V_BIT = (1 << 2), /* enables vertical flipping */
+ C2D_SOURCE_TILE_BIT = (1 << 3), /* enables source surface tiling */
+ C2D_TARGET_RECT_BIT = (1 << 4), /* enables target_rect field */
+ C2D_ROTATE_BIT = (1 << 5), /* enables all rotation fields */
+ C2D_SCISSOR_RECT_BIT = (1 << 6), /* enables scissor_rect field */
+ C2D_MASK_SURFACE_BIT = (1 << 7), /* enables mask_surface_id field */
+ C2D_MASK_ALIGN_BIT = (1 << 8), /* aligns mask to source_rect */
+ C2D_MASK_SCALE_BIT = (1 << 9), /* enables mask surface scaling */
+ C2D_MASK_TILE_BIT = (1 << 10), /* enables mask surface tiling */
+ C2D_GLOBAL_ALPHA_BIT = (1 << 11), /* enables global_alpha field */
+ C2D_COLOR_KEY_BIT = (1 << 12), /* enables color_key field */
+ C2D_NO_PIXEL_ALPHA_BIT = (1 << 13), /* disables source alpha channel */
+ C2D_NO_BILINEAR_BIT = (1 << 14), /* disables bilinear on scaling */
+ C2D_NO_ANTIALIASING_BIT = (1 << 15), /* disables antialiasing on edges */
+ C2D_DRAW_LINE_BIT = (1 << 16), /* enables line drawing with source rectangle */
+ C2D_DRAW_LINE_NOLAST = (1 << 17), /* disable last pixel draw for line */
+} C2D_SOURCE_CONFIG;
+
+/* Target configuration bits, defines rotation + mirroring.
+ * Mirror is applied prior to rotation if enabled. */
+typedef enum {
+ C2D_TARGET_MIRROR_H = (1 << 0), /* horizontal flip */
+ C2D_TARGET_MIRROR_V = (1 << 1), /* vertical flip */
+ C2D_TARGET_ROTATE_0 = (0 << 2), /* no rotation */
+ C2D_TARGET_ROTATE_90 = (1 << 2), /* 90 degree rotation */
+ C2D_TARGET_ROTATE_180 = (2 << 2), /* 180 degree rotation */
+ C2D_TARGET_ROTATE_270 = (3 << 2), /* 270 degree rotation, 90 + 180 */
+ C2D_TARGET_MASK_ALIGN = (1 << 4), /* aligns mask to target scissor */
+ C2D_TARGET_MASK_SCALE = (1 << 5), /* enables mask scaling */
+ C2D_TARGET_MASK_TILE = (1 << 6), /* enables mask tiling */
+ C2D_TARGET_COLOR_KEY = (1 << 7), /* enables target_color_key */
+ C2D_TARGET_NO_PIXEL_ALPHA = (1 << 8), /* disables target alpha channel */
+} C2D_TARGET_CONFIG;
+
+#define C2D_TARGET_ROTATION_MASK (C2D_TARGET_ROTATE_90*3)
+
+/* Additional blend modes, can be used with both source and target configs.
+ If none of the below is set, the default "SRC over DST" is applied. */
+typedef enum {
+ C2D_ALPHA_BLEND_SRC_OVER = (0 << 20), /* Default, Porter-Duff "SRC over DST" */
+ C2D_ALPHA_BLEND_SRC = (1 << 20), /* Porter-Duff "SRC" */
+ C2D_ALPHA_BLEND_SRC_IN = (2 << 20), /* Porter-Duff "SRC in DST" */
+ C2D_ALPHA_BLEND_DST_IN = (3 << 20), /* Porter-Duff "DST in SRC" */
+ C2D_ALPHA_BLEND_SRC_OUT = (4 << 20), /* Porter-Duff "SRC out DST" */
+ C2D_ALPHA_BLEND_DST_OUT = (5 << 20), /* Porter-Duff "DST out SRC" */
+ C2D_ALPHA_BLEND_DST_OVER = (6 << 20), /* Porter-Duff "DST over SRC" */
+ C2D_ALPHA_BLEND_SRC_ATOP = (7 << 20), /* Porter-Duff "SRC ATOP" */
+ C2D_ALPHA_BLEND_DST_ATOP = (8 << 20), /* Porter-Duff "DST ATOP" */
+ C2D_ALPHA_BLEND_XOR = (9 << 20), /* Xor */
+ C2D_ALPHA_BLEND_MULTIPLY = (10 << 20), /* OpenVG "MULTIPLY" */
+ C2D_ALPHA_BLEND_SCREEN = (11 << 20), /* OpenVG "SCREEN" */
+ C2D_ALPHA_BLEND_DARKEN = (12 << 20), /* OpenVG "DARKEN" */
+ C2D_ALPHA_BLEND_LIGHTEN = (13 << 20), /* OpenVG "LIGHTEN" */
+ C2D_ALPHA_BLEND_ADDITIVE = (14 << 20), /* OpenVG "ADDITIVE" */
+ C2D_ALPHA_BLEND_DIRECT = (15 << 20), /* Direct alpha blitting */
+ C2D_ALPHA_BLEND_INVERTC = (16 << 20), /* Invert color */
+ C2D_ALPHA_BLEND_NONE = (1 << 25), /* disables alpha blending */
+} C2D_ALPHA_BLEND_MODE;
+
+
+/* Surface caps enumeration */
+typedef enum {
+ C2D_SOURCE = (1 << 0), /* allows to use as a source */
+ C2D_TARGET = (1 << 1), /* allows to use as a target */
+ C2D_MASK = (1 << 2), /* allows to use as a mask */
+ C2D_PALETTE = (1 << 3), /* allows to use as a palette */
+} C2D_SURFACE_BITS;
+
+/* Surface type enumeration */
+typedef enum {
+ C2D_SURFACE_RGB_HOST = 1, /* Host memory RGB surface */
+ C2D_SURFACE_RGB_EXT = 2, /* External memory RGB surface */
+ C2D_SURFACE_YUV_HOST = 3, /* Host memory YUV surface */
+ C2D_SURFACE_YUV_EXT = 4, /* External memory YUV surface */
+ C2D_SURFACE_WITH_PHYS = (1<<3), /* physical address already mapped */
+ /* this bit is valid with HOST types */
+ C2D_SURFACE_WITH_PHYS_DUMMY = (1<<4), /* physical address already mapped */
+ /* this bit is valid with HOST types */
+} C2D_SURFACE_TYPE;
+
+/* Structure for registering a RGB buffer as a blit surface */
+typedef struct {
+ uint32 format; /* RGB color format plus additional mode bits */
+ uint32 width; /* defines width in pixels */
+ uint32 height; /* defines height in pixels */
+ void *buffer; /* pointer to the RGB buffer */
+ void *phys; /* physical address */
+ int32 stride; /* defines stride in bytes, negative stride is allowed */
+} C2D_RGB_SURFACE_DEF;
+
+/* Structure for registering a YUV plane(s) as a blit surface */
+typedef struct {
+ uint32 format; /* YUV color format plus additional mode bits */
+ uint32 width; /* defines width in pixels */
+ uint32 height; /* defines height in pixels */
+ void *plane0; /* holds the whole buffer if YUV format is not planar */
+ void *phys0; /* physical address */
+ int32 stride0; /* stride in bytes if YUV format is not planar */
+ void *plane1; /* holds UV or VU plane for planar interleaved */
+ void *phys1; /* physical address */
+ int32 stride1; /* stride for UV or VU plane for planar interleaved */
+ void *plane2; /* holds the 3. plane, ignored if YUV format is not planar */
+ void *phys2; /* physical address */
+ int32 stride2; /* stride for the 3. plane, ignored if YUV format is not planar */
+} C2D_YUV_SURFACE_DEF;
+
+
+/* Rectangle definition */
+typedef struct {
+ int32 x; /* upper-left x */
+ int32 y; /* upper-left y */
+ int32 width; /* width */
+ int32 height; /* height */
+} C2D_RECT;
+
+/* C2D_OBJECT encapsulates the blit parameters for a source surface.
+ * The fg_color defines color in target format for bits equal to 1
+ * in the source C2D_COLOR_FORMAT_1 format. It also defines rendering
+ * color for all alpha-only source formats. If the surface_id is 0
+ * the fg_color defines a constant fill color used instead of the surface.
+ * The bg_color defines color in target format for bits equal to 0
+ * in the source C2D_COLOR_FORMAT_1 format, otherwise both are ignored.
+ * The palette_id is used for all palette source formats, otherwise ignored.
+
+ * The source_rect first defines the content of the source surface,
+ * it is then horizontally/vertically flipped if C2D_MIRROR_*_BIT is set,
+ * then scaled with bilinear interpolation to exactly fit target_rect
+ * or repeated across target_rect if C2D_SOURCE_TILE_BIT is set,
+ * target_rect is then rotated clockwise by an arbitrary angle in degrees
+ * around the rot_orig_x/y, defined relative to target_rect's top left point,
+ * and then clipped to scissor_rect defined in target coordinate system.
+
+ * Finally alpha blending is applied before pixels get written into the target.
+ * Surface's pixel alpha is combined with mask alpha and with global alpha.
+ * Mask surface follows all transformations applied to the source surface.
+ * Source color key defines transparent color, applied together with alpha. */
+typedef struct C2D_OBJECT_STR {
+ uint32 surface_id; /* source surface */
+
+ uint32 fg_color; /* foreground color */
+ uint32 bg_color; /* background color */
+ uint32 palette_id; /* one-dimensional horizontal palette surface */
+
+ uint32 config_mask; /* defines which fields below are enabled */
+
+ C2D_RECT source_rect; /* region of the source surface, 16.16 fp */
+ C2D_RECT target_rect; /* position and scaling in target, 16.16 fp */
+
+ int32 rot_orig_x; /* rotation origin relative to target_rect's... */
+ int32 rot_orig_y; /* ...top left point, both are 16.16 fp */
+ int32 rotation; /* clock-wise rotation in degrees, 16.16 fp */
+
+ C2D_RECT scissor_rect; /* defines the clip rectangle in target surface */
+
+ uint32 mask_surface_id; /* source alpha-mask surface */
+ uint32 global_alpha; /* 0 = fully transparent, 255 = fully opaque */
+ uint32 color_key; /* transparent color for the source surface */
+
+ struct C2D_OBJECT_STR *next; /* pointer to the next object or NULL */
+} C2D_OBJECT;
+
+
+/*****************************************************************************/
+/**************************** C2D API 2.0 ********************************/
+/*****************************************************************************/
+
+/******************************************************************************
+ * Functions to create/destroy surfaces */
+
+/* Creates a generic blit surface according to its type.
+ * Pass a combination of desired surface bits according to planned usage.
+ * Accepted values for surface_bits may include bits from C2D_SURFACE_BITS,
+ * and also from C2D_DISPLAY for compatibility with HW display controller.
+ * For host memory types the memory is preallocated outside the API
+ * and should remain valid until surface is destroyed.
+ * For external memory types the memory is allocated within API.
+ * On success, the non-zero surface identifier is returned.
+ * All numbers greater that 0 are valid surface identifiers, 0 is invalid.
+
+ * Host memory RGB surface:
+ * surface_type = C2D_SURFACE_RGB_HOST
+ * surface_definition = C2D_RGB_SURFACE_DEF
+ * all fields in definition structure should be set
+
+ * External memory RGB surface:
+ * surface_type = C2D_SURFACE_RGB_EXT
+ * surface_definition = C2D_RGB_SURFACE_DEF
+ * buffer field in definition structure is ignored
+
+ * Host memory YUV surface:
+ * surface_type = C2D_SURFACE_YUV_HOST
+ * surface_definition = C2D_YUV_SURFACE_DEF
+ * one or all plane and stride fields in definition structure
+ * should be set depending on whether the format is planar or not
+
+ * External memory YUV surface:
+ * surface_type = C2D_SURFACE_YUV_EXT
+ * surface_definition = C2D_YUV_SURFACE_DEF
+ * all plane and stride fields in definition structure are ignored */
+C2D_API C2D_STATUS c2dCreateSurface( uint32 *surface_id,
+ uint32 surface_bits,
+ C2D_SURFACE_TYPE surface_type,
+ void *surface_definition );
+
+/* Requests properties of the specified surface. */
+C2D_API C2D_STATUS c2dQuerySurface( uint32 surface_id,
+ uint32 *surface_bits,
+ C2D_SURFACE_TYPE *surface_type,
+ uint32 *width, uint32 *height,
+ uint32 *format );
+
+/* Destroys a generic blit surface.
+ * For external memory surfaces also deallocates the memory.
+ * It is safe to free any external resources associated with a given
+ * surface on c2dCreateSurface call after this function returns. */
+C2D_API C2D_STATUS c2dDestroySurface( uint32 surface_id );
+
+
+/******************************************************************************
+ * Functions to modify/exchange surface data */
+
+/* The format of fill_color is the same as color format being used
+ * for specified surface. If fill_rect is NULL the whole surface is filled.
+ * Alpha-blending is not performed while filling.
+ * The operation is complete when function returns. */
+C2D_API C2D_STATUS c2dFillSurface( uint32 surface_id,
+ uint32 fill_color,
+ C2D_RECT *fill_rect );
+
+/* Writes data located in host memory into the specified surface.
+ * The chunk of host memory is identified with surface_type and
+ * surface_definition, no surface registration needed in this case.
+ * Only C2D_SURFACE_RGB_HOST, C2D_SURFACE_YUV_HOST are accepted.
+ * If only part of the host memory buffer should be loaded, it should
+ * be configured in surface_definition using width, height and stride.
+ * The x and y are defined in target surface coordinate space.
+ * Color conversion has to be done, if color formats differ.
+ * Alpha-blending is not performed while writing.
+ * The operation is complete when function returns. */
+C2D_API C2D_STATUS c2dWriteSurface( uint32 surface_id,
+ C2D_SURFACE_TYPE surface_type,
+ void *surface_definition,
+ int32 x, int32 y );
+
+/* Reads data from the specified surface into the host memory.
+ * The chunk of host memory is identified with surface_type and
+ * surface_definition, no surface registration needed in this case.
+ * Only C2D_SURFACE_RGB_HOST, C2D_SURFACE_YUV_HOST are accepted.
+ * If only part of the surface should be read, it should
+ * be configured in surface_definition using width, height and stride.
+ * The x and y are defined in source surface coordinate space.
+ * Color conversion has to be done, if color formats differ.
+ * Alpha-blending is not performed while reading.
+ * The operation is complete when function returns. */
+C2D_API C2D_STATUS c2dReadSurface( uint32 surface_id,
+ C2D_SURFACE_TYPE surface_type,
+ void *surface_definition,
+ int32 x, int32 y );
+
+/* Notifies c2d imlementation that surface has been updated from outside the API,
+ * if updated_rect is NULL then the whole surface has been updated. */
+C2D_API C2D_STATUS c2dSurfaceUpdated( uint32 surface_id,
+ C2D_RECT *updated_rect );
+
+/* Updates surface information.
+ * Could be called only for host surfaces set with parameter "C2D_SURFACE_WITH_PHYS".
+ * Count for surface planes have to be same than for already allocated surface */
+C2D_API C2D_STATUS c2dUpdateSurface( uint32 surface_id,
+ uint32 surface_bits,
+ C2D_SURFACE_TYPE surface_type,
+ void *surface_definition );
+
+/******************************************************************************
+ * Functions to do actual blit */
+
+/* Draw a list of blit objects into the given target.
+ * The target_config is a bitwise OR of values from C2D_TARGET_CONFIG.
+ * The target transformation creates the effect that target surface
+ * is transformed before the blit and then transformed back
+ * after blit, however no physical target transform is performed.
+ * The objects_list is a linked list of blit objects, no more
+ * than num_objects is drawn from the given list.
+ * If num_objects is 0, the whole list is drawn.
+ * The blit is not guaranteed to complete after function returns. */
+C2D_API C2D_STATUS c2dDraw( uint32 target_id,
+ uint32 target_config, C2D_RECT *target_scissor,
+ uint32 target_mask_id, uint32 target_color_key,
+ C2D_OBJECT *objects_list, uint32 num_objects );
+
+
+/* timstamp set in the blit commands flush */
+typedef void* c2d_ts_handle;
+
+/* Forces any pending blit to complete for a given target.
+ * Non-blocking. All input surfaces for this target except those
+ * which are shared with other targets are expected to be immediately
+ * writable after client has been waiting returned timestamp with
+ * c2dWaitTimestamp funtion or c2dFinish has been called for same target */
+C2D_API C2D_STATUS c2dFlush( uint32 target_id, c2d_ts_handle *timestamp);
+
+
+/* Waits the pending timestamp */
+C2D_API C2D_STATUS c2dWaitTimestamp( c2d_ts_handle timestamp );
+
+
+/* Forces any pending blit to complete for a given target.
+ * Blocking version, returns when blit is done.
+ * All input surfaces for this target except those which are shared with
+ * other targets are expected to be immediately
+ * writable after this function returns. */
+C2D_API C2D_STATUS c2dFinish( uint32 target_id );
+
+
+/*****************************************************************************/
+/****************************** Display API **********************************/
+/*****************************************************************************/
+
+
+/* Display input enumeration */
+typedef enum {
+ C2D_DISPLAY_INPUT_0 = 0, /*!< default input */
+ C2D_DISPLAY_INPUT_1 = (1<<16), /*!< Overlay 1 */
+ C2D_DISPLAY_INPUT_2 = (1<<17), /*!< Overlay 2... */
+} C2D_DISPLAY_INPUT;
+
+
+/******************************************************************************
+ * Functions for display output. */
+
+/* Functionality described in this section is optional and is
+ * provided only for the cases when blit HW
+ * is tightly bound to the display controller. */
+
+/* Display enumeration, may also be used in surface caps */
+typedef enum {
+ C2D_DISPLAY_MAIN = (1 << 10), /* main display */
+ C2D_DISPLAY_SECONDARY = (1 << 11), /* secondary display */
+ C2D_DISPLAY_TV_OUT = (1 << 12), /* tv-out */
+} C2D_DISPLAY;
+
+/* Display window enumeration */
+typedef enum {
+ C2D_DISPLAY_OVERLAY = C2D_DISPLAY_INPUT_1, /*!< Overlay window bit. This defines display input.
+ When defined the surface is set on the overlay window
+ otherwise the surface is set on the background window. */
+} C2D_DISPLAY_WINDOW; /*!< Window bit set with display parameter */
+
+
+/* Display update modes */
+typedef enum {
+ C2D_DISPLAY_MODE_TEAR_SYNC = (1 << 0), /* enables tearing sync */
+ C2D_DISPLAY_MODE_SURF_REMOVE = (1 << 1), /* Remove surface from given display + input */
+} C2D_DISPLAY_MODE;
+
+
+/* Sets the given surface as a current display front buffer.
+ * Several displays can be specified as an output if supported.
+ * Still only one input can be specified at a time fro display/displays.
+ * The surface remains shown until it gets replaced with another one. */
+C2D_API C2D_STATUS c2dDisplaySetSurface( uint32 display,
+ uint32 surface_id, uint32 mode );
+
+/* Returns the current surface for a particular display.
+ * Only one display can be specified at a time.
+ * The latest surface set with compDisplaySetSurface or
+ * the default pre-allocated surface is returned. */
+C2D_API C2D_STATUS c2dDisplayGetSurface( uint32 display,
+ uint32 *surface_id );
+
+/* Returns the properties for a particular display.
+ * Only one display can be specified at a time. */
+C2D_API C2D_STATUS c2dDisplayGetProperties( uint32 display,
+ uint32 *width, uint32 *height,
+ uint32 *format );
+
+/* Sets the properties for a particular display input.
+ * Only one display + input can be specified at a time.
+ * C2D_OBJECT used to set input rect(target rect),
+ * blending operations, rotation...etc for display source */
+C2D_API C2D_STATUS c2dDisplaySetObject( uint32 display,
+ uint32 target_config, uint32 target_color_key,
+ C2D_OBJECT * c2dObject, uint32 mode);
+
+/* allows user to map a memory region to the gpu. only supported on linux
+ * mem_fd is the fd of the memory region, hostptr is the host pointer to the region,
+ * len and offset are the size and offset of the memory.
+ * flags is one of the memory types supported by gsl
+ * gpaddr is passed by refernce back to the user
+ */
+C2D_API C2D_STATUS c2dMapAddr ( int mem_fd, void * hostptr, uint32 len, uint32 offset, uint32 flags, void ** gpuaddr);
+
+/* allows user to unmap memory region mapped by c2dMapAddr.
+ * gpaddr is the gpuaddr to unmap */
+C2D_API C2D_STATUS c2dUnMapAddr (void * gpuaddr);
+
+/*****************************************************************************/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __c2d2_h_ */
diff --git a/libcopybit/copybit.cpp b/libcopybit/copybit.cpp
new file mode 100644
index 0000000..886d12b
--- /dev/null
+++ b/libcopybit/copybit.cpp
@@ -0,0 +1,553 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (c) 2010 - 2011, Code Aurora Forum. All rights reserved.
+ *
+ * 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.
+ */
+
+
+#define LOG_TAG "copybit"
+
+#include <cutils/log.h>
+
+#include <linux/msm_mdp.h>
+#include <linux/fb.h>
+
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+
+#include <copybit.h>
+
+#include "gralloc_priv.h"
+#include "software_converter.h"
+
+#define DEBUG_MDP_ERRORS 1
+
+/******************************************************************************/
+
+#if defined(COPYBIT_MSM7K)
+#define MAX_SCALE_FACTOR (4)
+#define MAX_DIMENSION (4096)
+#elif defined(COPYBIT_QSD8K)
+#define MAX_SCALE_FACTOR (8)
+#define MAX_DIMENSION (2048)
+#else
+#error "Unsupported MDP version"
+#endif
+
+/******************************************************************************/
+
+/** State information for each device instance */
+struct copybit_context_t {
+ struct copybit_device_t device;
+ int mFD;
+ uint8_t mAlpha;
+ int mFlags;
+};
+
+/**
+ * Common hardware methods
+ */
+
+static int open_copybit(const struct hw_module_t* module, const char* name,
+ struct hw_device_t** device);
+
+static struct hw_module_methods_t copybit_module_methods = {
+open: open_copybit
+};
+
+/*
+ * The COPYBIT Module
+ */
+struct copybit_module_t HAL_MODULE_INFO_SYM = {
+common: {
+tag: HARDWARE_MODULE_TAG,
+ version_major: 1,
+ version_minor: 0,
+ id: COPYBIT_HARDWARE_MODULE_ID,
+ name: "QCT MSM7K COPYBIT Module",
+ author: "Google, Inc.",
+ methods: ©bit_module_methods
+ }
+};
+
+/******************************************************************************/
+
+/** min of int a, b */
+static inline int min(int a, int b) {
+ return (a<b) ? a : b;
+}
+
+/** max of int a, b */
+static inline int max(int a, int b) {
+ return (a>b) ? a : b;
+}
+
+/** scale each parameter by mul/div. Assume div isn't 0 */
+static inline void MULDIV(uint32_t *a, uint32_t *b, int mul, int div) {
+ if (mul != div) {
+ *a = (mul * *a) / div;
+ *b = (mul * *b) / div;
+ }
+}
+
+/** Determine the intersection of lhs & rhs store in out */
+static void intersect(struct copybit_rect_t *out,
+ const struct copybit_rect_t *lhs,
+ const struct copybit_rect_t *rhs) {
+ out->l = max(lhs->l, rhs->l);
+ out->t = max(lhs->t, rhs->t);
+ out->r = min(lhs->r, rhs->r);
+ out->b = min(lhs->b, rhs->b);
+}
+
+/** convert COPYBIT_FORMAT to MDP format */
+static int get_format(int format) {
+ switch (format) {
+ case HAL_PIXEL_FORMAT_RGB_565: return MDP_RGB_565;
+ case HAL_PIXEL_FORMAT_RGBX_8888: return MDP_RGBX_8888;
+ case HAL_PIXEL_FORMAT_RGB_888: return MDP_RGB_888;
+ case HAL_PIXEL_FORMAT_RGBA_8888: return MDP_RGBA_8888;
+ case HAL_PIXEL_FORMAT_BGRA_8888: return MDP_BGRA_8888;
+ case HAL_PIXEL_FORMAT_YCrCb_422_SP: return MDP_Y_CBCR_H2V1;
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP: return MDP_Y_CBCR_H2V2;
+ case HAL_PIXEL_FORMAT_YCbCr_422_SP: return MDP_Y_CRCB_H2V1;
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP: return MDP_Y_CRCB_H2V2;
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO: return MDP_Y_CBCR_H2V2_ADRENO;
+ }
+ return -1;
+}
+
+/** convert from copybit image to mdp image structure */
+static void set_image(struct mdp_img *img, const struct copybit_image_t *rhs)
+{
+ private_handle_t* hnd = (private_handle_t*)rhs->handle;
+ if(hnd == NULL){
+ ALOGE("copybit: Invalid handle");
+ return;
+ }
+ img->width = rhs->w;
+ img->height = rhs->h;
+ img->format = get_format(rhs->format);
+ img->offset = hnd->offset;
+ img->memory_id = hnd->fd;
+}
+/** setup rectangles */
+static void set_rects(struct copybit_context_t *dev,
+ struct mdp_blit_req *e,
+ const struct copybit_rect_t *dst,
+ const struct copybit_rect_t *src,
+ const struct copybit_rect_t *scissor,
+ uint32_t horiz_padding,
+ uint32_t vert_padding) {
+ struct copybit_rect_t clip;
+ intersect(&clip, scissor, dst);
+
+ e->dst_rect.x = clip.l;
+ e->dst_rect.y = clip.t;
+ e->dst_rect.w = clip.r - clip.l;
+ e->dst_rect.h = clip.b - clip.t;
+
+ uint32_t W, H, delta_x, delta_y;
+ if (dev->mFlags & COPYBIT_TRANSFORM_ROT_90) {
+ delta_x = (clip.t - dst->t);
+ delta_y = (dst->r - clip.r);
+ e->src_rect.w = (clip.b - clip.t);
+ e->src_rect.h = (clip.r - clip.l);
+ W = dst->b - dst->t;
+ H = dst->r - dst->l;
+ } else {
+ delta_x = (clip.l - dst->l);
+ delta_y = (clip.t - dst->t);
+ e->src_rect.w = (clip.r - clip.l);
+ e->src_rect.h = (clip.b - clip.t);
+ W = dst->r - dst->l;
+ H = dst->b - dst->t;
+ }
+
+ MULDIV(&delta_x, &e->src_rect.w, src->r - src->l, W);
+ MULDIV(&delta_y, &e->src_rect.h, src->b - src->t, H);
+
+ e->src_rect.x = delta_x + src->l;
+ e->src_rect.y = delta_y + src->t;
+
+ if (dev->mFlags & COPYBIT_TRANSFORM_FLIP_V) {
+ if (dev->mFlags & COPYBIT_TRANSFORM_ROT_90) {
+ e->src_rect.x = (src->l + src->r) - (e->src_rect.x + e->src_rect.w);
+ }else{
+ e->src_rect.y = (src->t + src->b) - (e->src_rect.y + e->src_rect.h);
+ }
+ }
+
+ if (dev->mFlags & COPYBIT_TRANSFORM_FLIP_H) {
+ if (dev->mFlags & COPYBIT_TRANSFORM_ROT_90) {
+ e->src_rect.y = (src->t + src->b) - (e->src_rect.y + e->src_rect.h);
+ }else{
+ e->src_rect.x = (src->l + src->r) - (e->src_rect.x + e->src_rect.w);
+ }
+ }
+}
+
+/** setup mdp request */
+static void set_infos(struct copybit_context_t *dev,
+ struct mdp_blit_req *req, int flags)
+{
+ req->alpha = dev->mAlpha;
+ req->transp_mask = MDP_TRANSP_NOP;
+ req->flags = dev->mFlags | flags;
+#if defined(COPYBIT_QSD8K)
+ req->flags |= MDP_BLEND_FG_PREMULT;
+#endif
+}
+
+/** copy the bits */
+static int msm_copybit(struct copybit_context_t *dev, void const *list)
+{
+ int err = ioctl(dev->mFD, MSMFB_BLIT,
+ (struct mdp_blit_req_list const*)list);
+ ALOGE_IF(err<0, "copyBits failed (%s)", strerror(errno));
+ if (err == 0) {
+ return 0;
+ } else {
+#if DEBUG_MDP_ERRORS
+ struct mdp_blit_req_list const* l =
+ (struct mdp_blit_req_list const*)list;
+ for (int i=0 ; i<l->count ; i++) {
+ ALOGE("%d: src={w=%d, h=%d, f=%d, rect={%d,%d,%d,%d}}\n"
+ " dst={w=%d, h=%d, f=%d, rect={%d,%d,%d,%d}}\n"
+ " flags=%08lx"
+ ,
+ i,
+ l->req[i].src.width,
+ l->req[i].src.height,
+ l->req[i].src.format,
+ l->req[i].src_rect.x,
+ l->req[i].src_rect.y,
+ l->req[i].src_rect.w,
+ l->req[i].src_rect.h,
+ l->req[i].dst.width,
+ l->req[i].dst.height,
+ l->req[i].dst.format,
+ l->req[i].dst_rect.x,
+ l->req[i].dst_rect.y,
+ l->req[i].dst_rect.w,
+ l->req[i].dst_rect.h,
+ l->req[i].flags
+ );
+ }
+#endif
+ return -errno;
+ }
+}
+
+/*****************************************************************************/
+
+/** Set a parameter to value */
+static int set_parameter_copybit(
+ struct copybit_device_t *dev,
+ int name,
+ int value)
+{
+ struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
+ int status = 0;
+ if (ctx) {
+ switch(name) {
+ case COPYBIT_ROTATION_DEG:
+ switch (value) {
+ case 0:
+ ctx->mFlags &= ~0x7;
+ break;
+ case 90:
+ ctx->mFlags &= ~0x7;
+ ctx->mFlags |= MDP_ROT_90;
+ break;
+ case 180:
+ ctx->mFlags &= ~0x7;
+ ctx->mFlags |= MDP_ROT_180;
+ break;
+ case 270:
+ ctx->mFlags &= ~0x7;
+ ctx->mFlags |= MDP_ROT_270;
+ break;
+ default:
+ ALOGE("Invalid value for COPYBIT_ROTATION_DEG");
+ status = -EINVAL;
+ break;
+ }
+ break;
+ case COPYBIT_PLANE_ALPHA:
+ if (value < 0) value = MDP_ALPHA_NOP;
+ if (value >= 256) value = 255;
+ ctx->mAlpha = value;
+ break;
+ case COPYBIT_DITHER:
+ if (value == COPYBIT_ENABLE) {
+ ctx->mFlags |= MDP_DITHER;
+ } else if (value == COPYBIT_DISABLE) {
+ ctx->mFlags &= ~MDP_DITHER;
+ }
+ break;
+ case COPYBIT_BLUR:
+ if (value == COPYBIT_ENABLE) {
+ ctx->mFlags |= MDP_BLUR;
+ } else if (value == COPYBIT_DISABLE) {
+ ctx->mFlags &= ~MDP_BLUR;
+ }
+ break;
+ case COPYBIT_PREMULTIPLIED_ALPHA:
+ if(value == COPYBIT_ENABLE) {
+ ctx->mFlags |= MDP_BLEND_FG_PREMULT;
+ } else if (value == COPYBIT_DISABLE) {
+ ctx->mFlags &= ~MDP_BLEND_FG_PREMULT;
+ }
+ break;
+ case COPYBIT_TRANSFORM:
+ ctx->mFlags &= ~0x7;
+ ctx->mFlags |= value & 0x7;
+ break;
+ default:
+ status = -EINVAL;
+ break;
+ }
+ } else {
+ status = -EINVAL;
+ }
+ return status;
+}
+
+/** Get a static info value */
+static int get(struct copybit_device_t *dev, int name)
+{
+ struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
+ int value;
+ if (ctx) {
+ switch(name) {
+ case COPYBIT_MINIFICATION_LIMIT:
+ value = MAX_SCALE_FACTOR;
+ break;
+ case COPYBIT_MAGNIFICATION_LIMIT:
+ value = MAX_SCALE_FACTOR;
+ break;
+ case COPYBIT_SCALING_FRAC_BITS:
+ value = 32;
+ break;
+ case COPYBIT_ROTATION_STEP_DEG:
+ value = 90;
+ break;
+ default:
+ value = -EINVAL;
+ }
+ } else {
+ value = -EINVAL;
+ }
+ return value;
+}
+
+/** do a stretch blit type operation */
+static int stretch_copybit(
+ struct copybit_device_t *dev,
+ struct copybit_image_t const *dst,
+ struct copybit_image_t const *src,
+ struct copybit_rect_t const *dst_rect,
+ struct copybit_rect_t const *src_rect,
+ struct copybit_region_t const *region)
+{
+ struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
+ int status = 0;
+ private_handle_t *yv12_handle = NULL;
+ if (ctx) {
+ struct {
+ uint32_t count;
+ struct mdp_blit_req req[12];
+ } list;
+
+ if (ctx->mAlpha < 255) {
+ switch (src->format) {
+ // we don't support plane alpha with RGBA formats
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ case HAL_PIXEL_FORMAT_BGRA_8888:
+ case HAL_PIXEL_FORMAT_RGBA_5551:
+ case HAL_PIXEL_FORMAT_RGBA_4444:
+ ALOGE ("%s : Unsupported Pixel format %d", __FUNCTION__,
+ src->format);
+ return -EINVAL;
+ }
+ }
+
+ if (src_rect->l < 0 || src_rect->r > src->w ||
+ src_rect->t < 0 || src_rect->b > src->h) {
+ // this is always invalid
+ ALOGE ("%s : Invalid source rectangle : src_rect l %d t %d r %d b %d",\
+ __FUNCTION__, src_rect->l, src_rect->t, src_rect->r, src_rect->b);
+
+ return -EINVAL;
+ }
+
+ if (src->w > MAX_DIMENSION || src->h > MAX_DIMENSION) {
+ ALOGE ("%s : Invalid source dimensions w %d h %d", __FUNCTION__, src->w, src->h);
+ return -EINVAL;
+ }
+
+ if (dst->w > MAX_DIMENSION || dst->h > MAX_DIMENSION) {
+ ALOGE ("%s : Invalid DST dimensions w %d h %d", __FUNCTION__, dst->w, dst->h);
+ return -EINVAL;
+ }
+
+ if(src->format == HAL_PIXEL_FORMAT_YV12) {
+ int usage = GRALLOC_USAGE_PRIVATE_ADSP_HEAP |
+ GRALLOC_USAGE_PRIVATE_MM_HEAP;
+ if (0 == alloc_buffer(&yv12_handle,src->w,src->h,
+ src->format, usage)){
+ if(0 == convertYV12toYCrCb420SP(src,yv12_handle)){
+ (const_cast<copybit_image_t *>(src))->format =
+ HAL_PIXEL_FORMAT_YCrCb_420_SP;
+ (const_cast<copybit_image_t *>(src))->handle =
+ yv12_handle;
+ (const_cast<copybit_image_t *>(src))->base =
+ (void *)yv12_handle->base;
+ }
+ else{
+ ALOGE("Error copybit conversion from yv12 failed");
+ if(yv12_handle)
+ free_buffer(yv12_handle);
+ return -EINVAL;
+ }
+ }
+ else{
+ ALOGE("Error:unable to allocate memeory for yv12 software conversion");
+ return -EINVAL;
+ }
+ }
+ const uint32_t maxCount = sizeof(list.req)/sizeof(list.req[0]);
+ const struct copybit_rect_t bounds = { 0, 0, dst->w, dst->h };
+ struct copybit_rect_t clip;
+ list.count = 0;
+ status = 0;
+ while ((status == 0) && region->next(region, &clip)) {
+ intersect(&clip, &bounds, &clip);
+ mdp_blit_req* req = &list.req[list.count];
+ int flags = 0;
+
+ private_handle_t* src_hnd = (private_handle_t*)src->handle;
+ if(src_hnd != NULL && src_hnd->flags & private_handle_t::PRIV_FLAGS_DO_NOT_FLUSH) {
+ flags |= MDP_BLIT_NON_CACHED;
+ }
+
+ set_infos(ctx, req, flags);
+ set_image(&req->dst, dst);
+ set_image(&req->src, src);
+ set_rects(ctx, req, dst_rect, src_rect, &clip, src->horiz_padding, src->vert_padding);
+
+ if (req->src_rect.w<=0 || req->src_rect.h<=0)
+ continue;
+
+ if (req->dst_rect.w<=0 || req->dst_rect.h<=0)
+ continue;
+
+ if (++list.count == maxCount) {
+ status = msm_copybit(ctx, &list);
+ list.count = 0;
+ }
+ }
+ if ((status == 0) && list.count) {
+ status = msm_copybit(ctx, &list);
+ }
+ } else {
+ ALOGE ("%s : Invalid COPYBIT context", __FUNCTION__);
+ status = -EINVAL;
+ }
+ if(yv12_handle)
+ free_buffer(yv12_handle);
+ return status;
+}
+
+/** Perform a blit type operation */
+static int blit_copybit(
+ struct copybit_device_t *dev,
+ struct copybit_image_t const *dst,
+ struct copybit_image_t const *src,
+ struct copybit_region_t const *region)
+{
+ struct copybit_rect_t dr = { 0, 0, dst->w, dst->h };
+ struct copybit_rect_t sr = { 0, 0, src->w, src->h };
+ return stretch_copybit(dev, dst, src, &dr, &sr, region);
+}
+
+/*****************************************************************************/
+
+/** Close the copybit device */
+static int close_copybit(struct hw_device_t *dev)
+{
+ struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
+ if (ctx) {
+ close(ctx->mFD);
+ free(ctx);
+ }
+ return 0;
+}
+
+/** Open a new instance of a copybit device using name */
+static int open_copybit(const struct hw_module_t* module, const char* name,
+ struct hw_device_t** device)
+{
+ int status = -EINVAL;
+ copybit_context_t *ctx;
+ ctx = (copybit_context_t *)malloc(sizeof(copybit_context_t));
+ memset(ctx, 0, sizeof(*ctx));
+
+ ctx->device.common.tag = HARDWARE_DEVICE_TAG;
+ ctx->device.common.version = 1;
+ ctx->device.common.module = const_cast<hw_module_t*>(module);
+ ctx->device.common.close = close_copybit;
+ ctx->device.set_parameter = set_parameter_copybit;
+ ctx->device.get = get;
+ ctx->device.blit = blit_copybit;
+ ctx->device.stretch = stretch_copybit;
+ ctx->mAlpha = MDP_ALPHA_NOP;
+ ctx->mFlags = 0;
+ ctx->mFD = open("/dev/graphics/fb0", O_RDWR, 0);
+ if (ctx->mFD < 0) {
+ status = errno;
+ ALOGE("Error opening frame buffer errno=%d (%s)",
+ status, strerror(status));
+ status = -status;
+ } else {
+ struct fb_fix_screeninfo finfo;
+ if (ioctl(ctx->mFD, FBIOGET_FSCREENINFO, &finfo) == 0) {
+ if (strncmp(finfo.id, "msmfb", 5) == 0) {
+ /* Success */
+ status = 0;
+ } else {
+ ALOGE("Error not msm frame buffer");
+ status = -EINVAL;
+ }
+ } else {
+ ALOGE("Error executing ioctl for screen info");
+ status = -errno;
+ }
+ }
+
+ if (status == 0) {
+ *device = &ctx->device.common;
+ } else {
+ close_copybit(&ctx->device.common);
+ }
+ return status;
+}
diff --git a/libcopybit/copybit.h b/libcopybit/copybit.h
new file mode 100644
index 0000000..6384dfe
--- /dev/null
+++ b/libcopybit/copybit.h
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2008 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.
+ */
+
+#ifndef ANDROID_COPYBIT_INTERFACE_H
+#define ANDROID_COPYBIT_INTERFACE_H
+
+#include <hardware/hardware.h>
+
+#include <stdint.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+__BEGIN_DECLS
+
+/**
+ * The id of this module
+ */
+#define COPYBIT_HARDWARE_MODULE_ID "copybit"
+
+/**
+ * Name of the graphics device to open
+ */
+#define COPYBIT_HARDWARE_COPYBIT0 "copybit0"
+
+/* supported pixel-formats. these must be compatible with
+ * graphics/PixelFormat.java, ui/PixelFormat.h, pixelflinger/format.h
+ */
+enum {
+ COPYBIT_FORMAT_RGBA_8888 = HAL_PIXEL_FORMAT_RGBA_8888,
+ COPYBIT_FORMAT_RGBX_8888 = HAL_PIXEL_FORMAT_RGBX_8888,
+ COPYBIT_FORMAT_RGB_888 = HAL_PIXEL_FORMAT_RGB_888,
+ COPYBIT_FORMAT_RGB_565 = HAL_PIXEL_FORMAT_RGB_565,
+ COPYBIT_FORMAT_BGRA_8888 = HAL_PIXEL_FORMAT_BGRA_8888,
+ COPYBIT_FORMAT_RGBA_5551 = HAL_PIXEL_FORMAT_RGBA_5551,
+ COPYBIT_FORMAT_RGBA_4444 = HAL_PIXEL_FORMAT_RGBA_4444,
+ COPYBIT_FORMAT_YCbCr_422_SP = 0x10,
+ COPYBIT_FORMAT_YCrCb_420_SP = 0x11,
+};
+
+/* name for copybit_set_parameter */
+enum {
+ /* rotation of the source image in degrees (0 to 359) */
+ COPYBIT_ROTATION_DEG = 1,
+ /* plane alpha value */
+ COPYBIT_PLANE_ALPHA = 2,
+ /* enable or disable dithering */
+ COPYBIT_DITHER = 3,
+ /* transformation applied (this is a superset of COPYBIT_ROTATION_DEG) */
+ COPYBIT_TRANSFORM = 4,
+ /* blurs the copied bitmap. The amount of blurring cannot be changed
+ * at this time. */
+ COPYBIT_BLUR = 5,
+ /* Informs the copybit that the source and destination contains
+ premultiplied alpha */
+ COPYBIT_PREMULTIPLIED_ALPHA = 6,
+ /* FB width */
+ COPYBIT_FRAMEBUFFER_WIDTH = 7,
+ /* FB height */
+ COPYBIT_FRAMEBUFFER_HEIGHT = 8,
+};
+
+/* values for copybit_set_parameter(COPYBIT_TRANSFORM) */
+enum {
+ /* flip source image horizontally */
+ COPYBIT_TRANSFORM_FLIP_H = HAL_TRANSFORM_FLIP_H,
+ /* flip source image vertically */
+ COPYBIT_TRANSFORM_FLIP_V = HAL_TRANSFORM_FLIP_V,
+ /* rotate source image 90 degres */
+ COPYBIT_TRANSFORM_ROT_90 = HAL_TRANSFORM_ROT_90,
+ /* rotate source image 180 degres */
+ COPYBIT_TRANSFORM_ROT_180 = HAL_TRANSFORM_ROT_180,
+ /* rotate source image 270 degres */
+ COPYBIT_TRANSFORM_ROT_270 = HAL_TRANSFORM_ROT_270,
+};
+
+/* enable/disable value copybit_set_parameter */
+enum {
+ COPYBIT_DISABLE = 0,
+ COPYBIT_ENABLE = 1
+};
+
+/* use get_static_info() to query static informations about the hardware */
+enum {
+ /* Maximum amount of minification supported by the hardware*/
+ COPYBIT_MINIFICATION_LIMIT = 1,
+ /* Maximum amount of magnification supported by the hardware */
+ COPYBIT_MAGNIFICATION_LIMIT = 2,
+ /* Number of fractional bits support by the scaling engine */
+ COPYBIT_SCALING_FRAC_BITS = 3,
+ /* Supported rotation step in degres. */
+ COPYBIT_ROTATION_STEP_DEG = 4,
+};
+
+/* Image structure */
+struct copybit_image_t {
+ /* width */
+ uint32_t w;
+ /* height */
+ uint32_t h;
+ /* format COPYBIT_FORMAT_xxx */
+ int32_t format;
+ /* base of buffer with image */
+ void *base;
+ /* handle to the image */
+ native_handle_t* handle;
+ /* number of pixels added for the stride */
+ uint32_t horiz_padding;
+ /* number of pixels added for the vertical stride */
+ uint32_t vert_padding;
+};
+
+/* Rectangle */
+struct copybit_rect_t {
+ /* left */
+ int l;
+ /* top */
+ int t;
+ /* right */
+ int r;
+ /* bottom */
+ int b;
+};
+
+/* Region */
+struct copybit_region_t {
+ int (*next)(struct copybit_region_t const *region, struct copybit_rect_t *rect);
+};
+
+/**
+ * Every hardware module must have a data structure named HAL_MODULE_INFO_SYM
+ * and the fields of this data structure must begin with hw_module_t
+ * followed by module specific information.
+ */
+struct copybit_module_t {
+ struct hw_module_t common;
+};
+
+/**
+ * Every device data structure must begin with hw_device_t
+ * followed by module specific public methods and attributes.
+ */
+struct copybit_device_t {
+ struct hw_device_t common;
+
+ /**
+ * Set a copybit parameter.
+ *
+ * @param dev from open
+ * @param name one for the COPYBIT_NAME_xxx
+ * @param value one of the COPYBIT_VALUE_xxx
+ *
+ * @return 0 if successful
+ */
+ int (*set_parameter)(struct copybit_device_t *dev, int name, int value);
+
+ /**
+ * Get a static copybit information.
+ *
+ * @param dev from open
+ * @param name one of the COPYBIT_STATIC_xxx
+ *
+ * @return value or -EINVAL if error
+ */
+ int (*get)(struct copybit_device_t *dev, int name);
+
+ /**
+ * Execute the bit blit copy operation
+ *
+ * @param dev from open
+ * @param dst is the destination image
+ * @param src is the source image
+ * @param region the clip region
+ *
+ * @return 0 if successful
+ */
+ int (*blit)(struct copybit_device_t *dev,
+ struct copybit_image_t const *dst,
+ struct copybit_image_t const *src,
+ struct copybit_region_t const *region);
+
+ /**
+ * Execute the stretch bit blit copy operation
+ *
+ * @param dev from open
+ * @param dst is the destination image
+ * @param src is the source image
+ * @param dst_rect is the destination rectangle
+ * @param src_rect is the source rectangle
+ * @param region the clip region
+ *
+ * @return 0 if successful
+ */
+ int (*stretch)(struct copybit_device_t *dev,
+ struct copybit_image_t const *dst,
+ struct copybit_image_t const *src,
+ struct copybit_rect_t const *dst_rect,
+ struct copybit_rect_t const *src_rect,
+ struct copybit_region_t const *region);
+};
+
+
+/** convenience API for opening and closing a device */
+
+static inline int copybit_open(const struct hw_module_t* module,
+ struct copybit_device_t** device) {
+ return module->methods->open(module,
+ COPYBIT_HARDWARE_COPYBIT0, (struct hw_device_t**)device);
+}
+
+static inline int copybit_close(struct copybit_device_t* device) {
+ return device->common.close(&device->common);
+}
+
+
+__END_DECLS
+
+#endif // ANDROID_COPYBIT_INTERFACE_H
diff --git a/libcopybit/copybit_c2d.cpp b/libcopybit/copybit_c2d.cpp
new file mode 100644
index 0000000..72aa279
--- /dev/null
+++ b/libcopybit/copybit_c2d.cpp
@@ -0,0 +1,1477 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+ *
+ * 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.
+ */
+
+#define LOG_TAG "copybit_c2d"
+
+#include <cutils/log.h>
+
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+
+#include <linux/msm_kgsl.h>
+
+#include <EGL/eglplatform.h>
+#include <cutils/native_handle.h>
+#include <cutils/ashmem.h>
+#include <linux/ashmem.h>
+#include <gralloc_priv.h>
+
+#include <copybit.h>
+#include <alloc_controller.h>
+#include <memalloc.h>
+
+#include "c2d2.h"
+#include "software_converter.h"
+
+#include <dlfcn.h>
+
+using gralloc::IMemAlloc;
+using gralloc::IonController;
+using gralloc::alloc_data;
+using android::sp;
+
+C2D_STATUS (*LINK_c2dCreateSurface)( uint32 *surface_id,
+ uint32 surface_bits,
+ C2D_SURFACE_TYPE surface_type,
+ void *surface_definition );
+
+C2D_STATUS (*LINK_c2dUpdateSurface)( uint32 surface_id,
+ uint32 surface_bits,
+ C2D_SURFACE_TYPE surface_type,
+ void *surface_definition );
+
+C2D_STATUS (*LINK_c2dReadSurface)( uint32 surface_id,
+ C2D_SURFACE_TYPE surface_type,
+ void *surface_definition,
+ int32 x, int32 y );
+
+C2D_STATUS (*LINK_c2dDraw)( uint32 target_id,
+ uint32 target_config, C2D_RECT *target_scissor,
+ uint32 target_mask_id, uint32 target_color_key,
+ C2D_OBJECT *objects_list, uint32 num_objects );
+
+C2D_STATUS (*LINK_c2dFinish)( uint32 target_id);
+
+C2D_STATUS (*LINK_c2dFlush)( uint32 target_id, c2d_ts_handle *timestamp);
+
+C2D_STATUS (*LINK_c2dWaitTimestamp)( c2d_ts_handle timestamp );
+
+C2D_STATUS (*LINK_c2dDestroySurface)( uint32 surface_id );
+
+C2D_STATUS (*LINK_c2dMapAddr) ( int mem_fd, void * hostptr, uint32 len, uint32 offset, uint32 flags, void ** gpuaddr);
+
+C2D_STATUS (*LINK_c2dUnMapAddr) ( void * gpuaddr);
+
+/******************************************************************************/
+
+#if defined(COPYBIT_Z180)
+#define MAX_SCALE_FACTOR (4096)
+#define MAX_DIMENSION (4096)
+#else
+#error "Unsupported HW version"
+#endif
+
+#define NUM_SURFACES 3
+
+enum {
+ RGB_SURFACE,
+ YUV_SURFACE_2_PLANES,
+ YUV_SURFACE_3_PLANES
+};
+
+enum eConversionType {
+ CONVERT_TO_ANDROID_FORMAT,
+ CONVERT_TO_C2D_FORMAT
+};
+
+enum eC2DFlags {
+ FLAGS_PREMULTIPLIED_ALPHA = 1<<0,
+ FLAGS_YUV_DESTINATION = 1<<1
+};
+
+static android::sp<gralloc::IAllocController> sAlloc = 0;
+/******************************************************************************/
+
+/** State information for each device instance */
+struct copybit_context_t {
+ struct copybit_device_t device;
+ unsigned int src[NUM_SURFACES]; /* src surfaces */
+ unsigned int dst[NUM_SURFACES]; /* dst surfaces */
+ unsigned int trg_transform; /* target transform */
+ C2D_OBJECT blitState;
+ void *libc2d2;
+ alloc_data temp_src_buffer;
+ alloc_data temp_dst_buffer;
+ int fb_width;
+ int fb_height;
+ bool isPremultipliedAlpha;
+};
+
+struct blitlist{
+ uint32_t count;
+ C2D_OBJECT blitObjects[12];
+};
+
+struct bufferInfo {
+ int width;
+ int height;
+ int format;
+};
+
+struct yuvPlaneInfo {
+ int yStride; //luma stride
+ int plane1_stride;
+ int plane2_stride;
+ int plane1_offset;
+ int plane2_offset;
+};
+
+/**
+ * Common hardware methods
+ */
+
+static int open_copybit(const struct hw_module_t* module, const char* name,
+ struct hw_device_t** device);
+
+static struct hw_module_methods_t copybit_module_methods = {
+open: open_copybit
+};
+
+/*
+ * The COPYBIT Module
+ */
+struct copybit_module_t HAL_MODULE_INFO_SYM = {
+common: {
+tag: HARDWARE_MODULE_TAG,
+ version_major: 1,
+ version_minor: 0,
+ id: COPYBIT_HARDWARE_MODULE_ID,
+ name: "QCT COPYBIT C2D 2.0 Module",
+ author: "Qualcomm",
+ methods: ©bit_module_methods
+ }
+};
+
+
+/* convert COPYBIT_FORMAT to C2D format */
+static int get_format(int format) {
+ switch (format) {
+ case HAL_PIXEL_FORMAT_RGB_565: return C2D_COLOR_FORMAT_565_RGB;
+ case HAL_PIXEL_FORMAT_RGBX_8888: return C2D_COLOR_FORMAT_8888_ARGB |
+ C2D_FORMAT_SWAP_RB |
+ C2D_FORMAT_DISABLE_ALPHA;
+ case HAL_PIXEL_FORMAT_RGBA_8888: return C2D_COLOR_FORMAT_8888_ARGB |
+ C2D_FORMAT_SWAP_RB;
+ case HAL_PIXEL_FORMAT_BGRA_8888: return C2D_COLOR_FORMAT_8888_ARGB;
+ case HAL_PIXEL_FORMAT_RGBA_5551: return C2D_COLOR_FORMAT_5551_RGBA;
+ case HAL_PIXEL_FORMAT_RGBA_4444: return C2D_COLOR_FORMAT_4444_RGBA;
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP: return C2D_COLOR_FORMAT_420_NV12;
+ case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:return C2D_COLOR_FORMAT_420_NV12;
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP: return C2D_COLOR_FORMAT_420_NV21;
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: return C2D_COLOR_FORMAT_420_NV12 |
+ C2D_FORMAT_MACROTILED;
+ default: ALOGE("%s: invalid format (0x%x", __FUNCTION__, format); return -EINVAL;
+ }
+ return -EINVAL;
+}
+
+/* Get the C2D formats needed for conversion to YUV */
+static int get_c2d_format_for_yuv_destination(int halFormat) {
+ switch (halFormat) {
+ // We do not swap the RB when the target is YUV
+ case HAL_PIXEL_FORMAT_RGBX_8888: return C2D_COLOR_FORMAT_8888_ARGB |
+ C2D_FORMAT_DISABLE_ALPHA;
+ case HAL_PIXEL_FORMAT_RGBA_8888: return C2D_COLOR_FORMAT_8888_ARGB;
+ // The U and V need to be interchanged when the target is YUV
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP: return C2D_COLOR_FORMAT_420_NV21;
+ case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:return C2D_COLOR_FORMAT_420_NV21;
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP: return C2D_COLOR_FORMAT_420_NV12;
+ default: return get_format(halFormat);
+ }
+ return -EINVAL;
+}
+
+/* ------------------------------------------------------------------- *//*!
+ * \internal
+ * \brief Get the bpp for a particular color format
+ * \param color format
+ * \return bits per pixel
+ *//* ------------------------------------------------------------------- */
+int c2diGetBpp(int32 colorformat)
+{
+
+ int c2dBpp = 0;
+
+ switch(colorformat&0xFF)
+ {
+ case C2D_COLOR_FORMAT_4444_RGBA:
+ case C2D_COLOR_FORMAT_4444_ARGB:
+ case C2D_COLOR_FORMAT_1555_ARGB:
+ case C2D_COLOR_FORMAT_565_RGB:
+ case C2D_COLOR_FORMAT_5551_RGBA:
+ c2dBpp = 16;
+ break;
+ case C2D_COLOR_FORMAT_8888_RGBA:
+ case C2D_COLOR_FORMAT_8888_ARGB:
+ c2dBpp = 32;
+ break;
+ case C2D_COLOR_FORMAT_8_L:
+ case C2D_COLOR_FORMAT_8_A:
+ c2dBpp = 8;
+ break;
+ case C2D_COLOR_FORMAT_4_A:
+ c2dBpp = 4;
+ break;
+ case C2D_COLOR_FORMAT_1:
+ c2dBpp = 1;
+ break;
+ default:
+ ALOGE("%s ERROR", __func__);
+ break;
+ }
+ return c2dBpp;
+}
+
+static uint32 c2d_get_gpuaddr( struct private_handle_t *handle)
+{
+ uint32 memtype, *gpuaddr;
+ C2D_STATUS rc;
+
+ if(!handle)
+ return 0;
+
+ if (handle->flags & (private_handle_t::PRIV_FLAGS_USES_PMEM |
+ private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP))
+ memtype = KGSL_USER_MEM_TYPE_PMEM;
+ else if (handle->flags & private_handle_t::PRIV_FLAGS_USES_ASHMEM)
+ memtype = KGSL_USER_MEM_TYPE_ASHMEM;
+ else if (handle->flags & private_handle_t::PRIV_FLAGS_USES_ION)
+ memtype = KGSL_USER_MEM_TYPE_ION;
+ else {
+ ALOGE("Invalid handle flags: 0x%x", handle->flags);
+ return 0;
+ }
+
+ rc = LINK_c2dMapAddr(handle->fd, (void*)handle->base, handle->size, handle->offset, memtype, (void**)&gpuaddr);
+ if (rc == C2D_STATUS_OK) {
+ return (uint32) gpuaddr;
+ }
+ return 0;
+}
+
+static int is_supported_rgb_format(int format)
+{
+ switch(format) {
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ case HAL_PIXEL_FORMAT_RGBX_8888:
+ case HAL_PIXEL_FORMAT_RGB_565:
+ case HAL_PIXEL_FORMAT_BGRA_8888:
+ case HAL_PIXEL_FORMAT_RGBA_5551:
+ case HAL_PIXEL_FORMAT_RGBA_4444: {
+ return COPYBIT_SUCCESS;
+ }
+ default:
+ return COPYBIT_FAILURE;
+ }
+}
+
+static int get_num_planes(int format)
+{
+ switch(format) {
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+ case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: {
+ return 2;
+ }
+ case HAL_PIXEL_FORMAT_YV12: {
+ return 3;
+ }
+ default:
+ return COPYBIT_FAILURE;
+ }
+}
+
+static int is_supported_yuv_format(int format)
+{
+ switch(format) {
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+ case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: {
+ return COPYBIT_SUCCESS;
+ }
+ default:
+ return COPYBIT_FAILURE;
+ }
+}
+
+static int is_valid_destination_format(int format)
+{
+ if (format == HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED) {
+ // C2D does not support NV12Tile as a destination format.
+ return COPYBIT_FAILURE;
+ }
+ return COPYBIT_SUCCESS;
+}
+
+static int calculate_yuv_offset_and_stride(const bufferInfo& info,
+ yuvPlaneInfo& yuvInfo)
+{
+ int width = info.width;
+ int height = info.height;
+ int format = info.format;
+
+ int aligned_height = 0;
+ int aligned_width = 0, size = 0;
+
+ switch (format) {
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: {
+ /* NV12 Tile buffers have their luma height aligned to 32bytes and width
+ * aligned to 128 bytes. The chroma offset starts at an 8K boundary
+ */
+ aligned_height = ALIGN(height, 32);
+ aligned_width = ALIGN(width, 128);
+ size = aligned_width * aligned_height;
+ yuvInfo.plane1_offset = ALIGN(size,8192);
+ yuvInfo.yStride = aligned_width;
+ yuvInfo.plane1_stride = aligned_width;
+ break;
+ }
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+ case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP: {
+ aligned_width = ALIGN(width, 32);
+ yuvInfo.yStride = aligned_width;
+ yuvInfo.plane1_stride = aligned_width;
+ if (HAL_PIXEL_FORMAT_NV12_ENCODEABLE == format) {
+ // The encoder requires a 2K aligned chroma offset
+ yuvInfo.plane1_offset = ALIGN(aligned_width * height, 2048);
+ } else
+ yuvInfo.plane1_offset = aligned_width * height;
+
+ break;
+ }
+ default: {
+ return COPYBIT_FAILURE;
+ }
+ }
+ return COPYBIT_SUCCESS;
+}
+
+/** create C2D surface from copybit image */
+static int set_image( uint32 surfaceId, const struct copybit_image_t *rhs,
+ int *cformat, uint32_t *mapped, const eC2DFlags flags)
+{
+ struct private_handle_t* handle = (struct private_handle_t*)rhs->handle;
+ C2D_SURFACE_TYPE surfaceType;
+ int status = COPYBIT_SUCCESS;
+
+ if (flags & FLAGS_YUV_DESTINATION) {
+ *cformat = get_c2d_format_for_yuv_destination(rhs->format);
+ } else {
+ *cformat = get_format(rhs->format);
+ }
+
+ if(*cformat == -EINVAL) {
+ ALOGE("%s: invalid format", __FUNCTION__);
+ return -EINVAL;
+ }
+
+ if(handle == NULL) {
+ ALOGE("%s: invalid handle", __func__);
+ return -EINVAL;
+ }
+
+ if (handle->gpuaddr == 0) {
+ handle->gpuaddr = c2d_get_gpuaddr(handle);
+ if(!handle->gpuaddr) {
+ ALOGE("%s: c2d_get_gpuaddr failed", __FUNCTION__);
+ return COPYBIT_FAILURE;
+ }
+ *mapped = 1;
+ }
+
+ /* create C2D surface */
+ if(is_supported_rgb_format(rhs->format) == COPYBIT_SUCCESS) {
+ /* RGB */
+ C2D_RGB_SURFACE_DEF surfaceDef;
+
+ surfaceType = (C2D_SURFACE_TYPE) (C2D_SURFACE_RGB_HOST | C2D_SURFACE_WITH_PHYS);
+
+ surfaceDef.phys = (void*) handle->gpuaddr;
+ surfaceDef.buffer = (void*) (handle->base);
+
+ surfaceDef.format = *cformat |
+ ((flags & FLAGS_PREMULTIPLIED_ALPHA) ? C2D_FORMAT_PREMULTIPLIED : 0);
+ surfaceDef.width = rhs->w;
+ surfaceDef.height = rhs->h;
+ int aligned_width = ALIGN(surfaceDef.width,32);
+ surfaceDef.stride = (aligned_width * c2diGetBpp(surfaceDef.format))>>3;
+
+ if(LINK_c2dUpdateSurface( surfaceId,C2D_TARGET | C2D_SOURCE, surfaceType, &surfaceDef)) {
+ ALOGE("%s: RGB Surface c2dUpdateSurface ERROR", __FUNCTION__);
+ goto error;
+ status = COPYBIT_FAILURE;
+ }
+ } else if (is_supported_yuv_format(rhs->format) == COPYBIT_SUCCESS) {
+ C2D_YUV_SURFACE_DEF surfaceDef;
+ memset(&surfaceDef, 0, sizeof(surfaceDef));
+ surfaceType = (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS);
+ surfaceDef.format = *cformat;
+
+ bufferInfo info;
+ info.width = rhs->w;
+ info.height = rhs->h;
+ info.format = rhs->format;
+
+ yuvPlaneInfo yuvInfo;
+ status = calculate_yuv_offset_and_stride(info, yuvInfo);
+ if(status != COPYBIT_SUCCESS) {
+ ALOGE("%s: calculate_yuv_offset_and_stride error", __FUNCTION__);
+ goto error;
+ }
+
+ surfaceDef.width = rhs->w;
+ surfaceDef.height = rhs->h;
+ surfaceDef.plane0 = (void*) (handle->base);
+ surfaceDef.phys0 = (void*) (handle->gpuaddr);
+ surfaceDef.stride0 = yuvInfo.yStride;
+
+ surfaceDef.plane1 = (void*) (handle->base + yuvInfo.plane1_offset);
+ surfaceDef.phys1 = (void*) (handle->gpuaddr + yuvInfo.plane1_offset);
+ surfaceDef.stride1 = yuvInfo.plane1_stride;
+ if (3 == get_num_planes(rhs->format)) {
+ surfaceDef.plane2 = (void*) (handle->base + yuvInfo.plane2_offset);
+ surfaceDef.phys2 = (void*) (handle->gpuaddr + yuvInfo.plane2_offset);
+ surfaceDef.stride2 = yuvInfo.plane2_stride;
+ }
+
+ if(LINK_c2dUpdateSurface( surfaceId,C2D_TARGET | C2D_SOURCE, surfaceType,
+ &surfaceDef)) {
+ ALOGE("%s: YUV Surface c2dUpdateSurface ERROR", __FUNCTION__);
+ goto error;
+ status = COPYBIT_FAILURE;
+ }
+ } else {
+ ALOGE("%s: invalid format 0x%x", __FUNCTION__, rhs->format);
+ goto error;
+ status = COPYBIT_FAILURE;
+ }
+
+ return status;
+
+error:
+ if(*mapped == 1) {
+ LINK_c2dUnMapAddr( (void*) handle->gpuaddr);
+ handle->gpuaddr = 0;
+ *mapped = 0;
+ }
+ return status;
+}
+
+static int set_src_image( uint32 *surfaceId, const struct copybit_image_t *rhs,
+ int *cformat, uint32 *mapped)
+{
+ struct private_handle_t* handle = (struct private_handle_t*)rhs->handle;
+ *cformat = get_format(rhs->format);
+ C2D_SURFACE_TYPE surfaceType;
+ uint32 gpuaddr = (uint32)handle->gpuaddr;
+ int status = COPYBIT_SUCCESS;
+
+ if (handle->gpuaddr == 0)
+ {
+ handle->gpuaddr = c2d_get_gpuaddr( handle);
+ if(!handle->gpuaddr)
+ return COPYBIT_FAILURE;
+
+ *mapped = 1;
+ }
+
+ /* create C2D surface */
+ if(is_supported_rgb_format(rhs->format) == COPYBIT_SUCCESS) {
+ /* RGB */
+ C2D_RGB_SURFACE_DEF surfaceDef;
+ surfaceType = (C2D_SURFACE_TYPE) (C2D_SURFACE_RGB_HOST | C2D_SURFACE_WITH_PHYS | C2D_SURFACE_WITH_PHYS_DUMMY);
+
+ surfaceDef.phys = (void*) handle->gpuaddr;
+ surfaceDef.buffer = (void*) (handle->base);
+ surfaceDef.buffer = (void*) (handle->base + handle->offset);
+
+ surfaceDef.format = get_format(rhs->format);
+ surfaceDef.width = rhs->w;
+ surfaceDef.height = rhs->h;
+ surfaceDef.stride = ALIGN(((surfaceDef.width * c2diGetBpp(surfaceDef.format))>>3), 32);
+
+ if(LINK_c2dCreateSurface( surfaceId, C2D_TARGET, surfaceType,(void*)&surfaceDef)) {
+ ALOGE("%s: LINK_c2dCreateSurface error", __FUNCTION__);
+ status = COPYBIT_FAILURE;
+ goto error;
+ }
+ } else if(is_supported_yuv_format(rhs->format) == COPYBIT_SUCCESS) {
+ /* YUV */
+ C2D_YUV_SURFACE_DEF surfaceDef;
+ int offset = 0;
+ int yStride = 0;
+ int uvStride = 0;
+ memset(&surfaceDef, 0, sizeof(surfaceDef));
+
+ surfaceType = (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS | C2D_SURFACE_WITH_PHYS_DUMMY);
+ surfaceDef.format = get_format(rhs->format);
+ bufferInfo info;
+ info.width = rhs->w;
+ info.height = rhs->h;
+ info.format = rhs->format;
+
+ yuvPlaneInfo yuvInfo;
+ status = calculate_yuv_offset_and_stride(info, yuvInfo);
+ if(status != COPYBIT_SUCCESS) {
+ ALOGE("%s: calculate_yuv_offset_and_stride error", __FUNCTION__);
+ goto error;
+ }
+
+ surfaceDef.width = rhs->w;
+ surfaceDef.height = rhs->h;
+ surfaceDef.plane0 = (void*) (handle->base);
+ surfaceDef.phys0 = (void*) handle->gpuaddr;
+ surfaceDef.stride0 = yuvInfo.yStride;
+
+ surfaceDef.plane1 = (void*) (handle->base + yuvInfo.plane1_offset);
+ surfaceDef.phys1 = (void*) (handle->gpuaddr + yuvInfo.plane1_offset);
+ surfaceDef.stride1 = yuvInfo.plane1_stride;
+
+ if(LINK_c2dCreateSurface( surfaceId, C2D_TARGET | C2D_SOURCE, surfaceType,
+ (void*)&surfaceDef)) {
+ ALOGE("%s: YUV surface LINK_c2dCreateSurface error", __func__);
+ status = COPYBIT_FAILURE;
+ goto error;
+ }
+ } else {
+ ALOGE("%s: Invalid format 0x%x", __FUNCTION__, rhs->format);
+ status = COPYBIT_FAILURE;
+ }
+
+ return COPYBIT_SUCCESS;
+
+error:
+ if(*mapped == 1) {
+ LINK_c2dUnMapAddr( (void*) handle->gpuaddr);
+ handle->gpuaddr = 0;
+ *mapped = 0;
+ }
+ return status;
+}
+
+void unset_image( uint32 surfaceId, const struct copybit_image_t *rhs,
+ uint32 mmapped)
+{
+ struct private_handle_t* handle = (struct private_handle_t*)rhs->handle;
+
+ if (mmapped && handle->gpuaddr) {
+ // Unmap this gpuaddr
+ LINK_c2dUnMapAddr( (void*) handle->gpuaddr);
+ handle->gpuaddr = 0;
+ }
+}
+
+static int blit_to_target( uint32 surfaceId, const struct copybit_image_t *rhs)
+{
+ struct private_handle_t* handle = (struct private_handle_t*)rhs->handle;
+ uint32 cformat = get_format(rhs->format);
+ C2D_SURFACE_TYPE surfaceType;
+ uint32 memoryMapped = 0;
+ int status = COPYBIT_SUCCESS;
+
+ if (!handle->gpuaddr) {
+ handle->gpuaddr = c2d_get_gpuaddr(handle);
+ if(!handle->gpuaddr)
+ return COPYBIT_FAILURE;
+
+ memoryMapped = 1;
+ }
+
+ /* create C2D surface */
+
+ if(cformat) {
+ /* RGB */
+ C2D_RGB_SURFACE_DEF surfaceDef;
+ memset(&surfaceDef, 0, sizeof(surfaceDef));
+
+ surfaceDef.buffer = (void*) handle->base;
+ surfaceDef.phys = (void*) handle->gpuaddr;
+
+ surfaceType = C2D_SURFACE_RGB_HOST;
+ surfaceDef.format = get_format(rhs->format);
+ surfaceDef.width = rhs->w;
+ surfaceDef.height = rhs->h;
+ surfaceDef.stride = ALIGN(((surfaceDef.width * c2diGetBpp(surfaceDef.format))>>3), 32);
+
+ if(LINK_c2dReadSurface(surfaceId, surfaceType, (void*)&surfaceDef, 0, 0)) {
+ ALOGE("%s: LINK_c2dReadSurface ERROR", __func__);
+ status = COPYBIT_FAILURE;
+ goto done;
+ }
+ }
+ else {
+ /* YUV */
+ /* TODO */
+ }
+
+done:
+ if (memoryMapped) {
+ LINK_c2dUnMapAddr( (void*) handle->gpuaddr);
+ handle->gpuaddr = 0;
+ }
+ return status;
+}
+
+/** setup rectangles */
+static void set_rects(struct copybit_context_t *ctx,
+ C2D_OBJECT *c2dObject,
+ const struct copybit_rect_t *dst,
+ const struct copybit_rect_t *src,
+ const struct copybit_rect_t *scissor)
+{
+ // Set the target rect.
+ if((ctx->trg_transform & C2D_TARGET_ROTATE_90) &&
+ (ctx->trg_transform & C2D_TARGET_ROTATE_180)) {
+ /* target rotation is 270 */
+ c2dObject->target_rect.x = (dst->t)<<16;
+ c2dObject->target_rect.y = ctx->fb_width?(ALIGN(ctx->fb_width,32)- dst->r):dst->r;
+ c2dObject->target_rect.y = c2dObject->target_rect.y<<16;
+ c2dObject->target_rect.height = ((dst->r) - (dst->l))<<16;
+ c2dObject->target_rect.width = ((dst->b) - (dst->t))<<16;
+ } else if(ctx->trg_transform & C2D_TARGET_ROTATE_90) {
+ c2dObject->target_rect.x = ctx->fb_height?(ctx->fb_height - dst->b):dst->b;
+ c2dObject->target_rect.x = c2dObject->target_rect.x<<16;
+ c2dObject->target_rect.y = (dst->l)<<16;
+ c2dObject->target_rect.height = ((dst->r) - (dst->l))<<16;
+ c2dObject->target_rect.width = ((dst->b) - (dst->t))<<16;
+ } else if(ctx->trg_transform & C2D_TARGET_ROTATE_180) {
+ c2dObject->target_rect.y = ctx->fb_height?(ctx->fb_height - dst->b):dst->b;
+ c2dObject->target_rect.y = c2dObject->target_rect.y<<16;
+ c2dObject->target_rect.x = ctx->fb_width?(ALIGN(ctx->fb_width,32) - dst->r):dst->r;
+ c2dObject->target_rect.x = c2dObject->target_rect.x<<16;
+ c2dObject->target_rect.height = ((dst->b) - (dst->t))<<16;
+ c2dObject->target_rect.width = ((dst->r) - (dst->l))<<16;
+ } else {
+ c2dObject->target_rect.x = (dst->l)<<16;
+ c2dObject->target_rect.y = (dst->t)<<16;
+ c2dObject->target_rect.height = ((dst->b) - (dst->t))<<16;
+ c2dObject->target_rect.width = ((dst->r) - (dst->l))<<16;
+ }
+ c2dObject->config_mask |= C2D_TARGET_RECT_BIT;
+
+ // Set the source rect
+ c2dObject->source_rect.x = (src->l)<<16;
+ c2dObject->source_rect.y = (src->t)<<16;
+ c2dObject->source_rect.height = ((src->b) - (src->t))<<16;
+ c2dObject->source_rect.width = ((src->r) - (src->l))<<16;
+ c2dObject->config_mask |= C2D_SOURCE_RECT_BIT;
+
+ // Set the scissor rect
+ c2dObject->scissor_rect.x = scissor->l;
+ c2dObject->scissor_rect.y = scissor->t;
+ c2dObject->scissor_rect.height = (scissor->b) - (scissor->t);
+ c2dObject->scissor_rect.width = (scissor->r) - (scissor->l);
+ c2dObject->config_mask |= C2D_SCISSOR_RECT_BIT;
+}
+
+/** copy the bits */
+static int msm_copybit(struct copybit_context_t *dev, blitlist *list, uint32 target)
+{
+ int objects;
+
+ for(objects = 0; objects < list->count; objects++) {
+ list->blitObjects[objects].next = &(list->blitObjects[objects+1]);
+ }
+
+ if(LINK_c2dDraw(target,dev->trg_transform, 0x0, 0, 0, list->blitObjects,
+ list->count)) {
+ ALOGE("%s: LINK_c2dDraw ERROR", __FUNCTION__);
+ return COPYBIT_FAILURE;
+ }
+
+ return COPYBIT_SUCCESS;
+}
+
+/*****************************************************************************/
+
+/** Set a parameter to value */
+static int set_parameter_copybit(
+ struct copybit_device_t *dev,
+ int name,
+ int value)
+{
+ struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
+ if (!ctx) {
+ ALOGE("%s: null context", __FUNCTION__);
+ return -EINVAL;
+ }
+
+ switch(name) {
+ case COPYBIT_ROTATION_DEG:
+ ctx->blitState.rotation = value<<16;
+ /* SRC rotation */
+ if(!value)
+ ctx->blitState.config_mask &=~C2D_ROTATE_BIT;;
+ break;
+ case COPYBIT_PLANE_ALPHA:
+ if (value < 0) value = 0;
+ if (value >= 256) value = 255;
+
+ ctx->blitState.global_alpha = value;
+
+ if(ctx->blitState.global_alpha<255)
+ ctx->blitState.config_mask |= C2D_GLOBAL_ALPHA_BIT;
+ else
+ ctx->blitState.config_mask &=~C2D_GLOBAL_ALPHA_BIT;
+ break;
+ case COPYBIT_DITHER:
+ /* TODO */
+ break;
+ case COPYBIT_BLUR:
+ /* TODO */
+ break;
+ case COPYBIT_TRANSFORM:
+ ctx->blitState.config_mask &=~C2D_ROTATE_BIT;
+ ctx->blitState.config_mask &=~C2D_MIRROR_H_BIT;
+ ctx->blitState.config_mask &=~C2D_MIRROR_V_BIT;
+ ctx->trg_transform = C2D_TARGET_ROTATE_0;
+
+ if((value&0x7) == COPYBIT_TRANSFORM_ROT_180)
+ ctx->trg_transform = C2D_TARGET_ROTATE_180;
+ else if((value&0x7) == COPYBIT_TRANSFORM_ROT_270)
+ ctx->trg_transform = C2D_TARGET_ROTATE_90;
+ else {
+ if(value©BIT_TRANSFORM_FLIP_H)
+ ctx->blitState.config_mask |= C2D_MIRROR_H_BIT;
+ if(value©BIT_TRANSFORM_FLIP_V)
+ ctx->blitState.config_mask |= C2D_MIRROR_V_BIT;
+ if(value©BIT_TRANSFORM_ROT_90)
+ ctx->trg_transform = C2D_TARGET_ROTATE_270;
+ }
+ break;
+ case COPYBIT_PREMULTIPLIED_ALPHA:
+ (value == COPYBIT_ENABLE) ? ctx->isPremultipliedAlpha = true :
+ ctx->isPremultipliedAlpha = false;
+ break;
+ case COPYBIT_FRAMEBUFFER_WIDTH:
+ ctx->fb_width = value;
+ break;
+ case COPYBIT_FRAMEBUFFER_HEIGHT:
+ ctx->fb_height = value;
+ break;
+ default:
+ ALOGE("%s: default case param=0x%x", __FUNCTION__, name);
+ return -EINVAL;
+ break;
+ }
+
+ return COPYBIT_SUCCESS;
+}
+
+/** Get a static info value */
+static int get(struct copybit_device_t *dev, int name)
+{
+ struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
+ int value;
+
+ if (!ctx) {
+ ALOGE("%s: null context error", __FUNCTION__);
+ return -EINVAL;
+ }
+
+ switch(name) {
+ case COPYBIT_MINIFICATION_LIMIT:
+ value = MAX_SCALE_FACTOR;
+ break;
+ case COPYBIT_MAGNIFICATION_LIMIT:
+ value = MAX_SCALE_FACTOR;
+ break;
+ case COPYBIT_SCALING_FRAC_BITS:
+ value = 32;
+ break;
+ case COPYBIT_ROTATION_STEP_DEG:
+ value = 1;
+ break;
+ default:
+ ALOGE("%s: default case param=0x%x", __FUNCTION__, name);
+ value = -EINVAL;
+ }
+ return value;
+}
+
+static int is_alpha(int cformat)
+{
+ int alpha = 0;
+ switch (cformat & 0xFF) {
+ case C2D_COLOR_FORMAT_8888_ARGB:
+ case C2D_COLOR_FORMAT_8888_RGBA:
+ case C2D_COLOR_FORMAT_5551_RGBA:
+ case C2D_COLOR_FORMAT_4444_ARGB:
+ alpha = 1;
+ break;
+ default:
+ alpha = 0;
+ break;
+ }
+
+ if(alpha && (cformat&C2D_FORMAT_DISABLE_ALPHA))
+ alpha = 0;
+
+ return alpha;
+}
+
+/* Function to check if we need a temporary buffer for the blit.
+ * This would happen if the requested destination stride and the
+ * C2D stride do not match. We ignore RGB buffers, since their
+ * stride is always aligned to 32.
+ */
+static bool need_temp_buffer(struct copybit_image_t const *img)
+{
+ if (COPYBIT_SUCCESS == is_supported_rgb_format(img->format))
+ return false;
+
+ struct private_handle_t* handle = (struct private_handle_t*)img->handle;
+
+ // The width parameter in the handle contains the aligned_w. We check if we
+ // need to convert based on this param. YUV formats have bpp=1, so checking
+ // if the requested stride is aligned should suffice.
+ if (0 == (handle->width)%32) {
+ return false;
+ }
+
+ return true;
+}
+
+/* Function to extract the information from the copybit image and set the corresponding
+ * values in the bufferInfo struct.
+ */
+static void populate_buffer_info(struct copybit_image_t const *img, bufferInfo& info)
+{
+ info.width = img->w;
+ info.height = img->h;
+ info.format = img->format;
+}
+
+/* Function to get the required size for a particular format, inorder for C2D to perform
+ * the blit operation.
+ */
+static size_t get_size(const bufferInfo& info)
+{
+ size_t size = 0;
+ int w = info.width;
+ int h = info.height;
+ int aligned_w = ALIGN(w, 32);
+ switch(info.format) {
+ case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+ {
+ // Chroma for this format is aligned to 2K.
+ size = ALIGN((aligned_w*h), 2048) +
+ ALIGN(w/2, 32) * h/2 *2;
+ size = ALIGN(size, 4096);
+ } break;
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+ {
+ size = aligned_w*h +
+ ALIGN(w/2, 32) * h/2 *2;
+ size = ALIGN(size, 4096);
+ } break;
+ default: break;
+ }
+ return size;
+}
+
+/* Function to allocate memory for the temporary buffer. This memory is
+ * allocated from Ashmem. It is the caller's responsibility to free this
+ * memory.
+ */
+static int get_temp_buffer(const bufferInfo& info, alloc_data& data)
+{
+ ALOGD("%s E", __FUNCTION__);
+ // Alloc memory from system heap
+ data.base = 0;
+ data.fd = -1;
+ data.offset = 0;
+ data.size = get_size(info);
+ data.align = getpagesize();
+ data.uncached = true;
+ int allocFlags = GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP;
+
+ if (sAlloc == 0) {
+ sAlloc = gralloc::IAllocController::getInstance(false);
+ }
+
+ if (sAlloc == 0) {
+ ALOGE("%s: sAlloc is still NULL", __FUNCTION__);
+ return COPYBIT_FAILURE;
+ }
+
+ int err = sAlloc->allocate(data, allocFlags, 0);
+ if (0 != err) {
+ ALOGE("%s: allocate failed", __FUNCTION__);
+ return COPYBIT_FAILURE;
+ }
+
+ ALOGD("%s X", __FUNCTION__);
+ return err;
+}
+
+/* Function to free the temporary allocated memory.*/
+static void free_temp_buffer(alloc_data &data)
+{
+ if (-1 != data.fd) {
+ sp<IMemAlloc> memalloc = sAlloc->getAllocator(data.allocType);
+ memalloc->free_buffer(data.base, data.size, 0, data.fd);
+ }
+}
+
+/* Function to perform the software color conversion. Convert the
+ * C2D compatible format to the Android compatible format
+ */
+static int copy_image(private_handle_t *src_handle,
+ struct copybit_image_t const *rhs,
+ eConversionType conversionType)
+{
+ if (src_handle->fd == -1) {
+ ALOGE("%s: src_handle fd is invalid", __FUNCTION__);
+ return COPYBIT_FAILURE;
+ }
+
+ // Copy the info.
+ int ret = COPYBIT_SUCCESS;
+ switch(rhs->format) {
+ case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+ {
+ if (CONVERT_TO_ANDROID_FORMAT == conversionType) {
+ return convert_yuv_c2d_to_yuv_android(src_handle, rhs);
+ } else {
+ return convert_yuv_android_to_yuv_c2d(src_handle, rhs);
+ }
+
+ } break;
+ default: {
+ ALOGE("%s: invalid format 0x%x", __FUNCTION__, rhs->format);
+ ret = COPYBIT_FAILURE;
+ } break;
+ }
+ return ret;
+}
+
+static void delete_handle(private_handle_t *handle)
+{
+ if (handle) {
+ delete handle;
+ handle = 0;
+ }
+}
+/** do a stretch blit type operation */
+static int stretch_copybit_internal(
+ struct copybit_device_t *dev,
+ struct copybit_image_t const *dst,
+ struct copybit_image_t const *src,
+ struct copybit_rect_t const *dst_rect,
+ struct copybit_rect_t const *src_rect,
+ struct copybit_region_t const *region,
+ bool enableBlend)
+{
+ struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
+ int status = COPYBIT_SUCCESS;
+ uint32 maxCount;
+ uint32 src_mapped = 0, trg_mapped = 0;
+ blitlist list;
+ C2D_OBJECT *req;
+ memset(&list, 0, sizeof(list));
+ int cformat;
+ c2d_ts_handle timestamp;
+ uint32 src_surface_index = 0, dst_surface_index = 0;
+
+ if (!ctx) {
+ ALOGE("%s: null context error", __FUNCTION__);
+ return -EINVAL;
+ }
+
+ if (src->w > MAX_DIMENSION || src->h > MAX_DIMENSION) {
+ ALOGE("%s: src dimension error", __FUNCTION__);
+ return -EINVAL;
+ }
+
+ if (dst->w > MAX_DIMENSION || dst->h > MAX_DIMENSION) {
+ ALOGE("%s : dst dimension error dst w %d h %d", __FUNCTION__, dst->w, dst->h);
+ return -EINVAL;
+ }
+
+ maxCount = sizeof(list.blitObjects)/sizeof(C2D_OBJECT);
+
+ struct copybit_rect_t clip;
+ list.count = 0;
+
+ if (is_valid_destination_format(dst->format) == COPYBIT_FAILURE) {
+ ALOGE("%s: Invalid destination format format = 0x%x", __FUNCTION__, dst->format);
+ return COPYBIT_FAILURE;
+ }
+
+ bool isYUVDestination = false;
+ if (is_supported_rgb_format(dst->format) == COPYBIT_SUCCESS) {
+ dst_surface_index = RGB_SURFACE;
+ } else if (is_supported_yuv_format(dst->format) == COPYBIT_SUCCESS) {
+ isYUVDestination = true;
+ int num_planes = get_num_planes(dst->format);
+ if (num_planes == 2) {
+ dst_surface_index = YUV_SURFACE_2_PLANES;
+ } else if (num_planes == 3) {
+ dst_surface_index = YUV_SURFACE_3_PLANES;
+ } else {
+ ALOGE("%s: dst number of YUV planes is invalid dst format = 0x%x",
+ __FUNCTION__, dst->format);
+ return COPYBIT_FAILURE;
+ }
+ } else {
+ ALOGE("%s: Invalid dst surface format 0x%x", __FUNCTION__, dst->format);
+ return COPYBIT_FAILURE;
+ }
+
+ copybit_image_t dst_image;
+ dst_image.w = dst->w;
+ dst_image.h = dst->h;
+ dst_image.format = dst->format;
+ dst_image.handle = dst->handle;
+ // Check if we need a temp. copy for the destination. We'd need this the destination
+ // width is not aligned to 32. This case occurs for YUV formats. RGB formats are
+ // aligned to 32.
+ bool needTempDestination = need_temp_buffer(dst);
+ bufferInfo dst_info;
+ populate_buffer_info(dst, dst_info);
+ private_handle_t* dst_hnd = new private_handle_t(-1, 0, 0, 0, dst_info.format,
+ dst_info.width, dst_info.height);
+ if (dst_hnd == NULL) {
+ ALOGE("%s: dst_hnd is null", __FUNCTION__);
+ return COPYBIT_FAILURE;
+ }
+ if (needTempDestination) {
+ if (get_size(dst_info) != ctx->temp_dst_buffer.size) {
+ free_temp_buffer(ctx->temp_dst_buffer);
+ // Create a temp buffer and set that as the destination.
+ if (COPYBIT_FAILURE == get_temp_buffer(dst_info, ctx->temp_dst_buffer)) {
+ ALOGE("%s: get_temp_buffer(dst) failed", __FUNCTION__);
+ delete_handle(dst_hnd);
+ return COPYBIT_FAILURE;
+ }
+ }
+ dst_hnd->fd = ctx->temp_dst_buffer.fd;
+ dst_hnd->size = ctx->temp_dst_buffer.size;
+ dst_hnd->flags = ctx->temp_dst_buffer.allocType;
+ dst_hnd->base = (int)(ctx->temp_dst_buffer.base);
+ dst_hnd->offset = ctx->temp_dst_buffer.offset;
+ dst_hnd->gpuaddr = 0;
+ dst_image.handle = dst_hnd;
+ }
+
+ int flags = 0;
+ flags |= (ctx->isPremultipliedAlpha) ? FLAGS_PREMULTIPLIED_ALPHA : 0;
+ flags |= (isYUVDestination) ? FLAGS_YUV_DESTINATION : 0;
+
+ status = set_image( ctx->dst[dst_surface_index], &dst_image,
+ &cformat, &trg_mapped, (eC2DFlags)flags);
+ if(status) {
+ ALOGE("%s: dst: set_image error", __FUNCTION__);
+ delete_handle(dst_hnd);
+ return COPYBIT_FAILURE;
+ }
+
+ if(is_supported_rgb_format(src->format) == COPYBIT_SUCCESS) {
+ src_surface_index = RGB_SURFACE;
+ } else if (is_supported_yuv_format(src->format) == COPYBIT_SUCCESS) {
+ int num_planes = get_num_planes(src->format);
+ if (num_planes == 2) {
+ src_surface_index = YUV_SURFACE_2_PLANES;
+ } else if (num_planes == 3) {
+ src_surface_index = YUV_SURFACE_3_PLANES;
+ } else {
+ ALOGE("%s: src number of YUV planes is invalid src format = 0x%x",
+ __FUNCTION__, src->format);
+ delete_handle(dst_hnd);
+ return -EINVAL;
+ }
+ } else {
+ ALOGE("%s: Invalid source surface format 0x%x", __FUNCTION__, src->format);
+ delete_handle(dst_hnd);
+ return -EINVAL;
+ }
+
+ copybit_image_t src_image;
+ src_image.w = src->w;
+ src_image.h = src->h;
+ src_image.format = src->format;
+ src_image.handle = src->handle;
+
+ bool needTempSource = need_temp_buffer(src);
+ bufferInfo src_info;
+ populate_buffer_info(src, src_info);
+ private_handle_t* src_hnd = new private_handle_t(-1, 0, 0, 0, src_info.format,
+ src_info.width, src_info.height);
+ if (NULL == src_hnd) {
+ ALOGE("%s: src_hnd is null", __FUNCTION__);
+ delete_handle(dst_hnd);
+ return COPYBIT_FAILURE;
+ }
+ if (needTempSource) {
+ if (get_size(src_info) != ctx->temp_src_buffer.size) {
+ free_temp_buffer(ctx->temp_src_buffer);
+ // Create a temp buffer and set that as the destination.
+ if (COPYBIT_SUCCESS != get_temp_buffer(src_info, ctx->temp_src_buffer)) {
+ ALOGE("%s: get_temp_buffer(src) failed", __FUNCTION__);
+ delete_handle(dst_hnd);
+ delete_handle(src_hnd);
+ return COPYBIT_FAILURE;
+ }
+ }
+ src_hnd->fd = ctx->temp_src_buffer.fd;
+ src_hnd->size = ctx->temp_src_buffer.size;
+ src_hnd->flags = ctx->temp_src_buffer.allocType;
+ src_hnd->base = (int)(ctx->temp_src_buffer.base);
+ src_hnd->offset = ctx->temp_src_buffer.offset;
+ src_hnd->gpuaddr = 0;
+ src_image.handle = src_hnd;
+
+ // Copy the source.
+ copy_image((private_handle_t *)src->handle, &src_image, CONVERT_TO_C2D_FORMAT);
+
+ // Flush the cache
+ sp<IMemAlloc> memalloc = sAlloc->getAllocator(src_hnd->flags);
+ if (memalloc->clean_buffer((void *)(src_hnd->base), src_hnd->size,
+ src_hnd->offset, src_hnd->fd)) {
+ ALOGE("%s: clean_buffer failed", __FUNCTION__);
+ delete_handle(dst_hnd);
+ delete_handle(src_hnd);
+ return COPYBIT_FAILURE;
+ }
+ }
+
+ status = set_image( ctx->src[src_surface_index], &src_image,
+ &cformat, &src_mapped, (eC2DFlags)flags);
+ if(status) {
+ ALOGE("%s: set_src_image error", __FUNCTION__);
+ delete_handle(dst_hnd);
+ delete_handle(src_hnd);
+ return COPYBIT_FAILURE;
+ }
+
+ if (enableBlend) {
+ if(ctx->blitState.config_mask & C2D_GLOBAL_ALPHA_BIT) {
+ ctx->blitState.config_mask &= ~C2D_ALPHA_BLEND_NONE;
+ if(!(ctx->blitState.global_alpha)) {
+ // src alpha is zero
+ unset_image( ctx->src[src_surface_index],
+ &src_image, src_mapped);
+ unset_image( ctx->dst[dst_surface_index],
+ &dst_image, trg_mapped);
+ delete_handle(dst_hnd);
+ delete_handle(src_hnd);
+ return status;
+ }
+ } else {
+ if(is_alpha(cformat))
+ ctx->blitState.config_mask &= ~C2D_ALPHA_BLEND_NONE;
+ else
+ ctx->blitState.config_mask |= C2D_ALPHA_BLEND_NONE;
+ }
+ } else {
+ ctx->blitState.config_mask |= C2D_ALPHA_BLEND_NONE;
+ }
+
+ ctx->blitState.surface_id = ctx->src[src_surface_index];
+
+ while ((status == 0) && region->next(region, &clip)) {
+ req = &(list.blitObjects[list.count]);
+ memcpy(req,&ctx->blitState,sizeof(C2D_OBJECT));
+
+ set_rects(ctx, req, dst_rect, src_rect, &clip);
+
+ if (++list.count == maxCount) {
+ status = msm_copybit(ctx, &list, ctx->dst[dst_surface_index]);
+ list.count = 0;
+ }
+ }
+ if ((status == 0) && list.count) {
+ status = msm_copybit(ctx, &list, ctx->dst[dst_surface_index]);
+ }
+
+ if(LINK_c2dFinish(ctx->dst[dst_surface_index])) {
+ ALOGE("%s: LINK_c2dFinish ERROR", __FUNCTION__);
+ }
+
+ unset_image( ctx->src[src_surface_index], &src_image,
+ src_mapped);
+ unset_image( ctx->dst[dst_surface_index], &dst_image,
+ trg_mapped);
+ if (needTempDestination) {
+ // copy the temp. destination without the alignment to the actual destination.
+ copy_image(dst_hnd, dst, CONVERT_TO_ANDROID_FORMAT);
+ // Invalidate the cache.
+ sp<IMemAlloc> memalloc = sAlloc->getAllocator(dst_hnd->flags);
+ memalloc->clean_buffer((void *)(dst_hnd->base), dst_hnd->size,
+ dst_hnd->offset, dst_hnd->fd);
+ }
+ delete_handle(dst_hnd);
+ delete_handle(src_hnd);
+ ctx->isPremultipliedAlpha = false;
+ ctx->fb_width = 0;
+ ctx->fb_height = 0;
+ return status;
+}
+
+static int stretch_copybit(
+ struct copybit_device_t *dev,
+ struct copybit_image_t const *dst,
+ struct copybit_image_t const *src,
+ struct copybit_rect_t const *dst_rect,
+ struct copybit_rect_t const *src_rect,
+ struct copybit_region_t const *region)
+{
+ struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
+ bool needsBlending = (ctx->blitState.global_alpha != 0);
+ return stretch_copybit_internal(dev, dst, src, dst_rect, src_rect,
+ region, needsBlending);
+}
+
+/** Perform a blit type operation */
+static int blit_copybit(
+ struct copybit_device_t *dev,
+ struct copybit_image_t const *dst,
+ struct copybit_image_t const *src,
+ struct copybit_region_t const *region)
+{
+ struct copybit_rect_t dr = { 0, 0, dst->w, dst->h };
+ struct copybit_rect_t sr = { 0, 0, src->w, src->h };
+ return stretch_copybit_internal(dev, dst, src, &dr, &sr, region, false);
+}
+
+/*****************************************************************************/
+
+/** Close the copybit device */
+static int close_copybit(struct hw_device_t *dev)
+{
+ struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
+ if (ctx) {
+ for(int i = 0; i <NUM_SURFACES; i++) {
+ LINK_c2dDestroySurface(ctx->dst[i]);
+ LINK_c2dDestroySurface(ctx->src[i]);
+ }
+
+ if (ctx->libc2d2) {
+ ::dlclose(ctx->libc2d2);
+ ALOGV("dlclose(libc2d2)");
+ }
+
+ free_temp_buffer(ctx->temp_src_buffer);
+ free_temp_buffer(ctx->temp_dst_buffer);
+ free(ctx);
+ }
+
+ return 0;
+}
+
+/** Open a new instance of a copybit device using name */
+static int open_copybit(const struct hw_module_t* module, const char* name,
+ struct hw_device_t** device)
+{
+ int status = COPYBIT_SUCCESS;
+ C2D_RGB_SURFACE_DEF surfDefinition = {0};
+ C2D_YUV_SURFACE_DEF yuvSurfaceDef = {0} ;
+ struct copybit_context_t *ctx;
+ char fbName[64];
+
+ ctx = (struct copybit_context_t *)malloc(sizeof(struct copybit_context_t));
+ if(!ctx) {
+ ALOGE("%s: malloc failed", __FUNCTION__);
+ return COPYBIT_FAILURE;
+ }
+
+ /* initialize drawstate */
+ memset(ctx, 0, sizeof(*ctx));
+
+ for (int i=0; i< NUM_SURFACES; i++) {
+ ctx->dst[i] = -1;
+ ctx->src[i] = -1;
+ }
+
+ ctx->libc2d2 = ::dlopen("libC2D2.so", RTLD_NOW);
+ if (!ctx->libc2d2) {
+ ALOGE("FATAL ERROR: could not dlopen libc2d2.so: %s", dlerror());
+ goto error;
+ }
+ *(void **)&LINK_c2dCreateSurface = ::dlsym(ctx->libc2d2,
+ "c2dCreateSurface");
+ *(void **)&LINK_c2dUpdateSurface = ::dlsym(ctx->libc2d2,
+ "c2dUpdateSurface");
+ *(void **)&LINK_c2dReadSurface = ::dlsym(ctx->libc2d2,
+ "c2dReadSurface");
+ *(void **)&LINK_c2dDraw = ::dlsym(ctx->libc2d2, "c2dDraw");
+ *(void **)&LINK_c2dFlush = ::dlsym(ctx->libc2d2, "c2dFlush");
+ *(void **)&LINK_c2dFinish = ::dlsym(ctx->libc2d2, "c2dFinish");
+ *(void **)&LINK_c2dWaitTimestamp = ::dlsym(ctx->libc2d2,
+ "c2dWaitTimestamp");
+ *(void **)&LINK_c2dDestroySurface = ::dlsym(ctx->libc2d2,
+ "c2dDestroySurface");
+ *(void **)&LINK_c2dMapAddr = ::dlsym(ctx->libc2d2,
+ "c2dMapAddr");
+ *(void **)&LINK_c2dUnMapAddr = ::dlsym(ctx->libc2d2,
+ "c2dUnMapAddr");
+
+ if (!LINK_c2dCreateSurface || !LINK_c2dUpdateSurface || !LINK_c2dReadSurface
+ || !LINK_c2dDraw || !LINK_c2dFlush || !LINK_c2dWaitTimestamp || !LINK_c2dFinish
+ || !LINK_c2dDestroySurface) {
+ ALOGE("%s: dlsym ERROR", __FUNCTION__);
+ goto error;
+ }
+
+ ctx->device.common.tag = HARDWARE_DEVICE_TAG;
+ ctx->device.common.version = 1;
+ ctx->device.common.module = (hw_module_t*)(module);
+ ctx->device.common.close = close_copybit;
+ ctx->device.set_parameter = set_parameter_copybit;
+ ctx->device.get = get;
+ ctx->device.blit = blit_copybit;
+ ctx->device.stretch = stretch_copybit;
+ ctx->blitState.config_mask = C2D_NO_BILINEAR_BIT | C2D_NO_ANTIALIASING_BIT;
+ ctx->trg_transform = C2D_TARGET_ROTATE_0;
+
+ /* Create RGB Surface */
+ surfDefinition.buffer = (void*)0xdddddddd;
+ surfDefinition.phys = (void*)0xdddddddd;
+ surfDefinition.stride = 1 * 4;
+ surfDefinition.width = 1;
+ surfDefinition.height = 1;
+ surfDefinition.format = C2D_COLOR_FORMAT_8888_ARGB;
+ if (LINK_c2dCreateSurface(&(ctx->dst[RGB_SURFACE]), C2D_TARGET | C2D_SOURCE,
+ (C2D_SURFACE_TYPE)(C2D_SURFACE_RGB_HOST |
+ C2D_SURFACE_WITH_PHYS | C2D_SURFACE_WITH_PHYS_DUMMY ), &surfDefinition)) {
+ ALOGE("%s: create ctx->dst[RGB_SURFACE] failed", __FUNCTION__);
+ ctx->dst[RGB_SURFACE] = -1;
+ goto error;
+ }
+
+
+ if (LINK_c2dCreateSurface(&(ctx->src[RGB_SURFACE]), C2D_TARGET | C2D_SOURCE,
+ (C2D_SURFACE_TYPE)(C2D_SURFACE_RGB_HOST |
+ C2D_SURFACE_WITH_PHYS | C2D_SURFACE_WITH_PHYS_DUMMY), &surfDefinition)) {
+ ALOGE("%s: create ctx->src[RGB_SURFACE] failed", __FUNCTION__);
+ ctx->src[RGB_SURFACE] = -1;
+ goto error;
+ }
+
+ /* Create YUV source surface */
+ yuvSurfaceDef.format = C2D_COLOR_FORMAT_420_NV12;
+
+ yuvSurfaceDef.width = 4;
+ yuvSurfaceDef.height = 4;
+ yuvSurfaceDef.plane0 = (void*)0xaaaaaaaa;
+ yuvSurfaceDef.phys0 = (void*) 0xaaaaaaaa;
+ yuvSurfaceDef.stride0 = 4;
+
+ yuvSurfaceDef.plane1 = (void*)0xaaaaaaaa;
+ yuvSurfaceDef.phys1 = (void*) 0xaaaaaaaa;
+ yuvSurfaceDef.stride1 = 4;
+
+ if (LINK_c2dCreateSurface(&(ctx->src[YUV_SURFACE_2_PLANES]),
+ C2D_TARGET | C2D_SOURCE,
+ (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST|C2D_SURFACE_WITH_PHYS | C2D_SURFACE_WITH_PHYS_DUMMY),
+ &yuvSurfaceDef)) {
+ ALOGE("%s: create ctx->src[YUV_SURFACE_2_PLANES] failed", __FUNCTION__);
+ ctx->src[YUV_SURFACE_2_PLANES] = -1;
+ goto error;
+ }
+
+ if (LINK_c2dCreateSurface(&(ctx->dst[YUV_SURFACE_2_PLANES]),
+ C2D_TARGET | C2D_SOURCE,
+ (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS | C2D_SURFACE_WITH_PHYS_DUMMY),
+ &yuvSurfaceDef)) {
+ ALOGE("%s: create ctx->dst[YUV_SURFACE_2_PLANES] failed", __FUNCTION__);
+ ctx->dst[YUV_SURFACE_2_PLANES] = -1;
+ goto error;
+ }
+
+ yuvSurfaceDef.format = C2D_COLOR_FORMAT_420_YV12;
+ yuvSurfaceDef.plane2 = (void*)0xaaaaaaaa;
+ yuvSurfaceDef.phys2 = (void*) 0xaaaaaaaa;
+ yuvSurfaceDef.stride2 = 4;
+
+ if (LINK_c2dCreateSurface(&(ctx->src[YUV_SURFACE_3_PLANES]),
+ C2D_TARGET | C2D_SOURCE,
+ (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS | C2D_SURFACE_WITH_PHYS_DUMMY),
+ &yuvSurfaceDef)) {
+ ALOGE("%s: create ctx->src[YUV_SURFACE_3_PLANES] failed", __FUNCTION__);
+ ctx->src[YUV_SURFACE_3_PLANES] = -1;
+ goto error;
+ }
+
+ if (LINK_c2dCreateSurface(&(ctx->dst[YUV_SURFACE_3_PLANES]),
+ C2D_TARGET | C2D_SOURCE,
+ (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS | C2D_SURFACE_WITH_PHYS_DUMMY),
+ &yuvSurfaceDef)) {
+ ALOGE("%s: create ctx->dst[YUV_SURFACE_3_PLANES] failed", __FUNCTION__);
+ ctx->dst[YUV_SURFACE_3_PLANES] = -1;
+ goto error;
+ }
+
+ ctx->temp_src_buffer.fd = -1;
+ ctx->temp_src_buffer.base = 0;
+ ctx->temp_src_buffer.size = 0;
+
+ ctx->temp_dst_buffer.fd = -1;
+ ctx->temp_dst_buffer.base = 0;
+ ctx->temp_dst_buffer.size = 0;
+
+ ctx->fb_width = 0;
+ ctx->fb_height = 0;
+ ctx->isPremultipliedAlpha = false;
+
+ *device = &ctx->device.common;
+ return status;
+
+error:
+ for (int i = 0; i<NUM_SURFACES; i++) {
+ if (-1 != (ctx->src[i])) {
+ LINK_c2dDestroySurface(ctx->src[i]);
+ ctx->src[i] = -1;
+ }
+ if (-1 != (ctx->dst[i])) {
+ LINK_c2dDestroySurface(ctx->dst[i]);
+ ctx->dst[i] = -1;
+ }
+ }
+ if (ctx->libc2d2)
+ ::dlclose(ctx->libc2d2);
+ if (ctx)
+ free(ctx);
+ status = COPYBIT_FAILURE;
+ *device = NULL;
+
+ return status;
+}
diff --git a/libcopybit/copybit_priv.h b/libcopybit/copybit_priv.h
new file mode 100644
index 0000000..fd1b27e
--- /dev/null
+++ b/libcopybit/copybit_priv.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2011, Code Aurora Forum. 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 Code Aurora Forum, 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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 <copybit.h>
+struct copybit_iterator : public copybit_region_t {
+ copybit_iterator(const copybit_rect_t& rect) {
+ mRect = rect;
+ mCount = 1;
+ this->next = iterate;
+ }
+private:
+ static int iterate(copybit_region_t const * self, copybit_rect_t* rect) {
+ if (!self || !rect) {
+ return 0;
+ }
+
+ copybit_iterator const* me = static_cast<copybit_iterator const*>(self);
+ if (me->mCount) {
+ rect->l = me->mRect.l;
+ rect->t = me->mRect.t;
+ rect->r = me->mRect.r;
+ rect->b = me->mRect.b;
+ me->mCount--;
+ return 1;
+ }
+ return 0;
+ }
+ copybit_rect_t mRect;
+ mutable int mCount;
+};
diff --git a/libcopybit/software_converter.cpp b/libcopybit/software_converter.cpp
new file mode 100644
index 0000000..c9bb674
--- /dev/null
+++ b/libcopybit/software_converter.cpp
@@ -0,0 +1,263 @@
+/*
+ * Copyright (c) 2011, Code Aurora Forum. 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 Code Aurora Forum, 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#define LOG_TAG "copybit"
+#include <cutils/log.h>
+#include <stdlib.h>
+#include <errno.h>
+#include "software_converter.h"
+
+/** Convert YV12 to YCrCb_420_SP */
+int convertYV12toYCrCb420SP(const copybit_image_t *src, private_handle_t *yv12_handle)
+{
+ private_handle_t* hnd = (private_handle_t*)src->handle;
+
+ if(hnd == NULL || yv12_handle == NULL){
+ ALOGE("Invalid handle");
+ return -1;
+ }
+
+ // Please refer to the description of YV12 in hardware.h
+ // for the formulae used to calculate buffer sizes and offsets
+
+ // In a copybit_image_t, w is the stride and
+ // stride - horiz_padding is the actual width
+ // vertical stride is the same as height, so not considered
+ unsigned int stride = src->w;
+ unsigned int width = src->w - src->horiz_padding;
+ unsigned int height = src->h;
+ unsigned int y_size = stride * src->h;
+ unsigned int c_width = ALIGN(stride/2, 16);
+ unsigned int c_size = c_width * src->h/2;
+ unsigned int chromaPadding = c_width - width/2;
+ unsigned int chromaSize = c_size * 2;
+ unsigned char* newChroma = (unsigned char *)(yv12_handle->base + y_size);
+ unsigned char* oldChroma = (unsigned char*)(hnd->base + y_size);
+ memcpy((char *)yv12_handle->base,(char *)hnd->base,y_size);
+
+#ifdef __ARM_HAVE_NEON
+ /* interleave */
+ if(!chromaPadding) {
+ unsigned char * t1 = newChroma;
+ unsigned char * t2 = oldChroma;
+ unsigned char * t3 = t2 + chromaSize/2;
+ for(unsigned int i=0; i < (chromaSize/2)>>3; i++) {
+ __asm__ __volatile__ (
+ "vld1.u8 d0, [%0]! \n"
+ "vld1.u8 d1, [%1]! \n"
+ "vst2.u8 {d0, d1}, [%2]! \n"
+ :"+r"(t2), "+r"(t3), "+r"(t1)
+ :
+ :"memory","d0","d1"
+ );
+
+ }
+ }
+#else //__ARM_HAVE_NEON
+ if(!chromaPadding) {
+ for(unsigned int i = 0; i< chromaSize/2; i++) {
+ newChroma[i*2] = oldChroma[i];
+ newChroma[i*2+1] = oldChroma[i+chromaSize/2];
+ }
+
+ }
+#endif
+ // If the image is not aligned to 16 pixels,
+ // convert using the C routine below
+ // r1 tracks the row of the source buffer
+ // r2 tracks the row of the destination buffer
+ // The width/2 checks are to avoid copying
+ // from the padding
+
+ if(chromaPadding) {
+ unsigned int r1 = 0, r2 = 0, i = 0, j = 0;
+ while(r1 < height/2) {
+ if(j == width) {
+ j = 0;
+ r2++;
+ continue;
+ }
+ if (j+1 == width) {
+ newChroma[r2*width + j] = oldChroma[r1*c_width+i];
+ r2++;
+ newChroma[r2*width] = oldChroma[r1*c_width+i+c_size];
+ j = 1;
+ } else {
+ newChroma[r2*width + j] = oldChroma[r1*c_width+i];
+ newChroma[r2*width + j + 1] = oldChroma[r1*c_width+i+c_size];
+ j+=2;
+ }
+ i++;
+ if (i == width/2 ) {
+ i = 0;
+ r1++;
+ }
+ }
+ }
+
+ return 0;
+}
+
+struct copyInfo{
+ int width;
+ int height;
+ int src_stride;
+ int dst_stride;
+ int src_plane1_offset;
+ int src_plane2_offset;
+ int dst_plane1_offset;
+ int dst_plane2_offset;
+};
+
+/* Internal function to do the actual copy of source to destination */
+static int copy_source_to_destination(const int src_base, const int dst_base,
+ copyInfo& info)
+{
+ if (!src_base || !dst_base) {
+ ALOGE("%s: invalid memory src_base = 0x%x dst_base=0x%x",
+ __FUNCTION__, src_base, dst_base);
+ return COPYBIT_FAILURE;
+ }
+
+ int width = info.width;
+ int height = info.height;
+ unsigned char *src = (unsigned char*)src_base;
+ unsigned char *dst = (unsigned char*)dst_base;
+
+ // Copy the luma
+ for (int i = 0; i < height; i++) {
+ memcpy(dst, src, width);
+ src += info.src_stride;
+ dst += info.dst_stride;
+ }
+
+ // Copy plane 1
+ src = (unsigned char*)(src_base + info.src_plane1_offset);
+ dst = (unsigned char*)(dst_base + info.dst_plane1_offset);
+ width = width/2;
+ height = height/2;
+ for (int i = 0; i < height; i++) {
+ memcpy(dst, src, info.src_stride);
+ src += info.src_stride;
+ dst += info.dst_stride;
+ }
+ return 0;
+}
+
+
+/*
+ * Function to convert the c2d format into an equivalent Android format
+ *
+ * @param: source buffer handle
+ * @param: destination image
+ *
+ * @return: return status
+ */
+int convert_yuv_c2d_to_yuv_android(private_handle_t *hnd,
+ struct copybit_image_t const *rhs)
+{
+ ALOGD("Enter %s", __FUNCTION__);
+ if (!hnd || !rhs) {
+ ALOGE("%s: invalid inputs hnd=%p rhs=%p", __FUNCTION__, hnd, rhs);
+ return COPYBIT_FAILURE;
+ }
+
+ int ret = COPYBIT_SUCCESS;
+ private_handle_t *dst_hnd = (private_handle_t *)rhs->handle;
+
+ copyInfo info;
+ info.width = rhs->w;
+ info.height = rhs->h;
+ info.src_stride = ALIGN(info.width, 32);
+ info.dst_stride = ALIGN(info.width, 16);
+ switch(rhs->format) {
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP: {
+ info.src_plane1_offset = info.src_stride*info.height;
+ info.dst_plane1_offset = info.dst_stride*info.height;
+ } break;
+ case HAL_PIXEL_FORMAT_NV12_ENCODEABLE: {
+ // Chroma is 2K aligned for the NV12 encodeable format.
+ info.src_plane1_offset = ALIGN(info.src_stride*info.height, 2048);
+ info.dst_plane1_offset = ALIGN(info.dst_stride*info.height, 2048);
+ } break;
+ default:
+ ALOGE("%s: unsupported format (format=0x%x)", __FUNCTION__,
+ rhs->format);
+ return COPYBIT_FAILURE;
+ }
+
+ ret = copy_source_to_destination(hnd->base, dst_hnd->base, info);
+ return ret;
+}
+
+/*
+ * Function to convert the Android format into an equivalent C2D format
+ *
+ * @param: source buffer handle
+ * @param: destination image
+ *
+ * @return: return status
+ */
+int convert_yuv_android_to_yuv_c2d(private_handle_t *hnd,
+ struct copybit_image_t const *rhs)
+{
+ if (!hnd || !rhs) {
+ ALOGE("%s: invalid inputs hnd=%p rhs=%p", __FUNCTION__, hnd, rhs);
+ return COPYBIT_FAILURE;
+ }
+
+ int ret = COPYBIT_SUCCESS;
+ private_handle_t *dst_hnd = (private_handle_t *)rhs->handle;
+
+ copyInfo info;
+ info.width = rhs->w;
+ info.height = rhs->h;
+ info.src_stride = ALIGN(hnd->width, 16);
+ info.dst_stride = ALIGN(info.width, 32);
+ switch(rhs->format) {
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP: {
+ info.src_plane1_offset = info.src_stride*info.height;
+ info.dst_plane1_offset = info.dst_stride*info.height;
+ } break;
+ case HAL_PIXEL_FORMAT_NV12_ENCODEABLE: {
+ // Chroma is 2K aligned for the NV12 encodeable format.
+ info.src_plane1_offset = ALIGN(info.src_stride*info.height, 2048);
+ info.dst_plane1_offset = ALIGN(info.dst_stride*info.height, 2048);
+ } break;
+ default:
+ ALOGE("%s: unsupported format (format=0x%x)", __FUNCTION__,
+ rhs->format);
+ return -1;
+ }
+
+ ret = copy_source_to_destination(hnd->base, dst_hnd->base, info);
+ return ret;
+}
diff --git a/libcopybit/software_converter.h b/libcopybit/software_converter.h
new file mode 100644
index 0000000..54b503d
--- /dev/null
+++ b/libcopybit/software_converter.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2011, Code Aurora Forum. 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 Code Aurora Forum, 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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 <copybit.h>
+#include "gralloc_priv.h"
+#include "gr.h"
+
+#define COPYBIT_SUCCESS 0
+#define COPYBIT_FAILURE -1
+
+int convertYV12toYCrCb420SP(const copybit_image_t *src,private_handle_t *yv12_handle);
+
+/*
+ * Function to convert the c2d format into an equivalent Android format
+ *
+ * @param: source buffer handle
+ * @param: destination image
+ *
+ * @return: return status
+ */
+int convert_yuv_c2d_to_yuv_android(private_handle_t *hnd,
+ struct copybit_image_t const *rhs);
+
+
+/*
+ * Function to convert the Android format into an equivalent C2D format
+ *
+ * @param: source buffer handle
+ * @param: destination image
+ *
+ * @return: return status
+ */
+int convert_yuv_android_to_yuv_c2d(private_handle_t *hnd,
+ struct copybit_image_t const *rhs);