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/Android.mk b/Android.mk
index 127a6de..73024a0 100644
--- a/Android.mk
+++ b/Android.mk
@@ -1,11 +1,9 @@
#Enables the listed display HAL modules
-#Libs to be built for all targets (including SDK)
display-hals := libqcomui
-
#libs to be built for QCOM targets only
#ifeq ($(call is-vendor-board-platform,QCOM),true)
-display-hals += libgralloc libgenlock libcopybit
+display-hals += libgralloc libgenlock libcopybit libhwcomposer liboverlay
#endif
include $(call all-named-subdir-makefiles,$(display-hals))
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);
diff --git a/libgenlock/Android.mk b/libgenlock/Android.mk
index 740d6ce..6ae8909 100644
--- a/libgenlock/Android.mk
+++ b/libgenlock/Android.mk
@@ -4,8 +4,7 @@
LOCAL_PRELINK_MODULE := false
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)
LOCAL_SHARED_LIBRARIES := liblog libcutils
-LOCAL_C_INCLUDES :=
-LOCAL_C_INCLUDES += hardware/qcom/display/libgralloc
+LOCAL_C_INCLUDES := hardware/qcom/display/libgralloc
LOCAL_ADDITIONAL_DEPENDENCIES :=
LOCAL_SRC_FILES := genlock.cpp
LOCAL_CFLAGS:= -DLOG_TAG=\"libgenlock\"
diff --git a/libgenlock/genlock.cpp b/libgenlock/genlock.cpp
index 5d5536b..bfec641 100644
--- a/libgenlock/genlock.cpp
+++ b/libgenlock/genlock.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-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
@@ -43,7 +43,7 @@
#endif
namespace {
- /* Internal function to map the userspace locks to the kernel lock types */
+/* Internal function to map the userspace locks to the kernel lock types */
int get_kernel_lock_type(genlock_lock_type lockType)
{
int kLockType = 0;
@@ -62,7 +62,7 @@
/* Internal function to perform the actual lock/unlock operations */
genlock_status_t perform_lock_unlock_operation(native_handle_t *buffer_handle,
- int lockType, int timeout)
+ int lockType, int timeout)
{
if (private_handle_t::validate(buffer_handle)) {
ALOGE("%s: handle is invalid", __FUNCTION__);
@@ -73,7 +73,7 @@
if ((hnd->flags & private_handle_t::PRIV_FLAGS_UNSYNCHRONIZED) == 0) {
if (hnd->genlockPrivFd < 0) {
ALOGE("%s: the lock has not been created, or has not been attached",
- __FUNCTION__);
+ __FUNCTION__);
return GENLOCK_FAILURE;
}
@@ -85,7 +85,7 @@
if (ioctl(hnd->genlockPrivFd, GENLOCK_IOC_LOCK, &lock)) {
ALOGE("%s: GENLOCK_IOC_LOCK failed (lockType0x%x, err=%s fd=%d)", __FUNCTION__,
- lockType, strerror(errno), hnd->fd);
+ lockType, strerror(errno), hnd->fd);
if (ETIMEDOUT == errno)
return GENLOCK_TIMEDOUT;
@@ -132,7 +132,7 @@
int fd = open(GENLOCK_DEVICE, O_RDWR);
if (fd < 0) {
ALOGE("%s: open genlock device failed (err=%s)", __FUNCTION__,
- strerror(errno));
+ strerror(errno));
return GENLOCK_FAILURE;
}
@@ -140,7 +140,7 @@
genlock_lock lock;
if (ioctl(fd, GENLOCK_IOC_NEW, NULL)) {
ALOGE("%s: GENLOCK_IOC_NEW failed (error=%s)", __FUNCTION__,
- strerror(errno));
+ strerror(errno));
close_genlock_fd_and_handle(fd, lock.fd);
ret = GENLOCK_FAILURE;
}
@@ -149,7 +149,7 @@
if (GENLOCK_FAILURE != ret) {
if (ioctl(fd, GENLOCK_IOC_EXPORT, &lock)) {
ALOGE("%s: GENLOCK_IOC_EXPORT failed (error=%s)", __FUNCTION__,
- strerror(errno));
+ strerror(errno));
close_genlock_fd_and_handle(fd, lock.fd);
ret = GENLOCK_FAILURE;
}
@@ -219,7 +219,7 @@
int fd = open(GENLOCK_DEVICE, O_RDWR);
if (fd < 0) {
ALOGE("%s: open genlock device failed (err=%s)", __FUNCTION__,
- strerror(errno));
+ strerror(errno));
return GENLOCK_FAILURE;
}
@@ -228,7 +228,7 @@
lock.fd = hnd->genlockHandle;
if (ioctl(fd, GENLOCK_IOC_ATTACH, &lock)) {
ALOGE("%s: GENLOCK_IOC_ATTACH failed (err=%s)", __FUNCTION__,
- strerror(errno));
+ strerror(errno));
close_genlock_fd_and_handle(fd, lock.fd);
ret = GENLOCK_FAILURE;
}
@@ -253,8 +253,8 @@
* @return error status.
*/
genlock_status_t genlock_lock_buffer(native_handle_t *buffer_handle,
- genlock_lock_type_t lockType,
- int timeout)
+ genlock_lock_type_t lockType,
+ int timeout)
{
genlock_status_t ret = GENLOCK_NO_ERROR;
#ifdef USE_GENLOCK
@@ -280,7 +280,7 @@
*
* @param: handle of the buffer to be unlocked.
* @return: error status.
-*/
+ */
genlock_status_t genlock_unlock_buffer(native_handle_t *buffer_handle)
{
genlock_status_t ret = GENLOCK_NO_ERROR;
diff --git a/libgenlock/genlock.h b/libgenlock/genlock.h
index b394410..0995557 100644
--- a/libgenlock/genlock.h
+++ b/libgenlock/genlock.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-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
@@ -36,80 +36,80 @@
extern "C" {
#endif
-/* Genlock lock types */
-typedef enum genlock_lock_type{
- GENLOCK_READ_LOCK = 1<<0, // Read lock
- GENLOCK_WRITE_LOCK = 1<<1, // Write lock
-}genlock_lock_type_t;
+ /* Genlock lock types */
+ typedef enum genlock_lock_type{
+ GENLOCK_READ_LOCK = 1<<0, // Read lock
+ GENLOCK_WRITE_LOCK = 1<<1, // Write lock
+ }genlock_lock_type_t;
-/* Genlock return values */
-typedef enum genlock_status{
- GENLOCK_NO_ERROR = 0,
- GENLOCK_TIMEDOUT,
- GENLOCK_FAILURE,
-} genlock_status_t;
+ /* Genlock return values */
+ typedef enum genlock_status{
+ GENLOCK_NO_ERROR = 0,
+ GENLOCK_TIMEDOUT,
+ GENLOCK_FAILURE,
+ } genlock_status_t;
-/* Genlock defines */
+ /* Genlock defines */
#define GENLOCK_MAX_TIMEOUT 1000 // Max 1s timeout
-/*
- * Create a genlock lock. The genlock lock file descriptor and the lock
- * handle are stored in the buffer_handle.
- *
- * @param: handle of the buffer
- * @return error status.
- */
-genlock_status_t genlock_create_lock(native_handle_t *buffer_handle);
+ /*
+ * Create a genlock lock. The genlock lock file descriptor and the lock
+ * handle are stored in the buffer_handle.
+ *
+ * @param: handle of the buffer
+ * @return error status.
+ */
+ genlock_status_t genlock_create_lock(native_handle_t *buffer_handle);
-/*
- * Release a genlock lock associated with the handle.
- *
- * @param: handle of the buffer
- * @return error status.
- */
-genlock_status_t genlock_release_lock(native_handle_t *buffer_handle);
+ /*
+ * Release a genlock lock associated with the handle.
+ *
+ * @param: handle of the buffer
+ * @return error status.
+ */
+ genlock_status_t genlock_release_lock(native_handle_t *buffer_handle);
-/*
- * Attach a lock to the buffer handle passed via an IPC.
- *
- * @param: handle of the buffer
- * @return error status.
- */
-genlock_status_t genlock_attach_lock(native_handle_t *buffer_handle);
+ /*
+ * Attach a lock to the buffer handle passed via an IPC.
+ *
+ * @param: handle of the buffer
+ * @return error status.
+ */
+ genlock_status_t genlock_attach_lock(native_handle_t *buffer_handle);
-/*
- * Lock the buffer specified by the buffer handle. The lock held by the buffer
- * is specified by the lockType. This function will block if a write lock is
- * requested on the buffer which has previously been locked for a read or write
- * operation. A buffer can be locked by multiple clients for read. An optional
- * timeout value can be specified. By default, there is no timeout.
- *
- * @param: handle of the buffer
- * @param: type of lock to be acquired by the buffer.
- * @param: timeout value in ms. GENLOCK_MAX_TIMEOUT is the maximum timeout value.
- * @return error status.
- */
-genlock_status_t genlock_lock_buffer(native_handle_t *buffer_handle,
- genlock_lock_type_t lockType,
- int timeout);
+ /*
+ * Lock the buffer specified by the buffer handle. The lock held by the buffer
+ * is specified by the lockType. This function will block if a write lock is
+ * requested on the buffer which has previously been locked for a read or write
+ * operation. A buffer can be locked by multiple clients for read. An optional
+ * timeout value can be specified. By default, there is no timeout.
+ *
+ * @param: handle of the buffer
+ * @param: type of lock to be acquired by the buffer.
+ * @param: timeout value in ms. GENLOCK_MAX_TIMEOUT is the maximum timeout value.
+ * @return error status.
+ */
+ genlock_status_t genlock_lock_buffer(native_handle_t *buffer_handle,
+ genlock_lock_type_t lockType,
+ int timeout);
-/*
- * Unlocks a buffer that has previously been locked by the client.
- *
- * @param: handle of the buffer to be unlocked.
- * @return: error status.
-*/
-genlock_status_t genlock_unlock_buffer(native_handle_t *buffer_handle);
+ /*
+ * Unlocks a buffer that has previously been locked by the client.
+ *
+ * @param: handle of the buffer to be unlocked.
+ * @return: error status.
+ */
+ genlock_status_t genlock_unlock_buffer(native_handle_t *buffer_handle);
-/*
- * Blocks the calling process until the lock held on the handle is unlocked.
- *
- * @param: handle of the buffer
- * @param: timeout value for the wait.
- * return: error status.
- */
-genlock_status_t genlock_wait(native_handle_t *buffer_handle, int timeout);
+ /*
+ * Blocks the calling process until the lock held on the handle is unlocked.
+ *
+ * @param: handle of the buffer
+ * @param: timeout value for the wait.
+ * return: error status.
+ */
+ genlock_status_t genlock_wait(native_handle_t *buffer_handle, int timeout);
#ifdef __cplusplus
}
diff --git a/libgralloc/Android.mk b/libgralloc/Android.mk
index 5377d86..44108c7 100644
--- a/libgralloc/Android.mk
+++ b/libgralloc/Android.mk
@@ -11,65 +11,48 @@
# 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.
-
-# Use this flag until pmem/ashmem is implemented in the new gralloc
LOCAL_PATH := $(call my-dir)
# HAL module implemenation, not prelinked and stored in
# hw/<OVERLAY_HARDWARE_MODULE_ID>.<ro.product.board>.so
include $(CLEAR_VARS)
-LOCAL_PRELINK_MODULE := false
-LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
-LOCAL_SHARED_LIBRARIES := liblog libcutils libGLESv1_CM libutils libmemalloc libQcomUI
-LOCAL_SHARED_LIBRARIES += libgenlock
+LOCAL_PRELINK_MODULE := false
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
+LOCAL_SHARED_LIBRARIES := liblog libcutils libutils libmemalloc
+LOCAL_SHARED_LIBRARIES += libgenlock libQcomUI libGLESv1_CM
+LOCAL_C_INCLUDES := hardware/qcom/display/liboverlay/
+LOCAL_C_INCLUDES += hardware/qcom/display/libgenlock
+LOCAL_C_INCLUDES += hardware/qcom/display/libqcomui
+LOCAL_MODULE := gralloc.$(TARGET_BOARD_PLATFORM)
+LOCAL_MODULE_TAGS := optional
+LOCAL_CFLAGS := -DLOG_TAG=\"$(TARGET_BOARD_PLATFORM).gralloc\" \
+ -DDEBUG_CALC_FPS
+LOCAL_SRC_FILES := gpu.cpp gralloc.cpp framebuffer.cpp mapper.cpp
-LOCAL_C_INCLUDES += hardware/qcom/display/libgenlock
-LOCAL_C_INCLUDES += hardware/qcom/display/libqcomui
-LOCAL_ADDITIONAL_DEPENDENCIES +=
-LOCAL_SRC_FILES := framebuffer.cpp \
- gpu.cpp \
- gralloc.cpp \
- mapper.cpp
+ifeq ($(TARGET_USES_POST_PROCESSING),true)
+ LOCAL_CFLAGS += -DUSES_POST_PROCESSING
+ LOCAL_C_INCLUDES += $(TARGET_OUT_HEADERS)/pp/inc
+endif
-LOCAL_MODULE := gralloc.$(TARGET_BOARD_PLATFORM)
-LOCAL_MODULE_TAGS := optional
-LOCAL_CFLAGS:= -DLOG_TAG=\"$(TARGET_BOARD_PLATFORM).gralloc\" -DHOST -DDEBUG_CALC_FPS
-
-ifeq ($(call is-board-platform,msm7627_surf msm7627_6x),true)
- LOCAL_CFLAGS += -DTARGET_MSM7x27
+ifeq ($(TARGET_USES_MDP3), true)
+ LOCAL_CFLAGS += -DUSE_MDP3
endif
ifeq ($(TARGET_HAVE_HDMI_OUT),true)
LOCAL_CFLAGS += -DHDMI_DUAL_DISPLAY
- LOCAL_C_INCLUDES += hardware/qcom/display/liboverlay
LOCAL_SHARED_LIBRARIES += liboverlay
endif
-
-ifeq ($(TARGET_USES_SF_BYPASS),true)
- LOCAL_CFLAGS += -DSF_BYPASS
-endif
-
-ifeq ($(TARGET_GRALLOC_USES_ASHMEM),true)
- LOCAL_CFLAGS += -DUSE_ASHMEM
-endif
-
include $(BUILD_SHARED_LIBRARY)
#MemAlloc Library
include $(CLEAR_VARS)
LOCAL_PRELINK_MODULE := false
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)
-LOCAL_C_INCLUDES += hardware/qcom/display/libqcomui
-LOCAL_ADDITIONAL_DEPENDENCIES +=
+LOCAL_C_INCLUDES := hardware/qcom/display/libqcomui
LOCAL_SHARED_LIBRARIES := liblog libcutils libutils
-LOCAL_SRC_FILES := ionalloc.cpp \
- alloc_controller.cpp
+LOCAL_SRC_FILES := ionalloc.cpp alloc_controller.cpp
LOCAL_CFLAGS:= -DLOG_TAG=\"memalloc\"
-
-ifeq ($(TARGET_USES_ION),true)
- LOCAL_CFLAGS += -DUSE_ION
-endif
-
+LOCAL_CFLAGS += -DUSE_ION
LOCAL_MODULE := libmemalloc
LOCAL_MODULE_TAGS := optional
include $(BUILD_SHARED_LIBRARY)
diff --git a/libgralloc/alloc_controller.cpp b/libgralloc/alloc_controller.cpp
index 47cdc68..1356b2f 100644
--- a/libgralloc/alloc_controller.cpp
+++ b/libgralloc/alloc_controller.cpp
@@ -34,24 +34,26 @@
#include "alloc_controller.h"
#include "memalloc.h"
#include "ionalloc.h"
+#include "pmemalloc.h"
#include "ashmemalloc.h"
#include "gr.h"
+#include "qcomutils/comptype.h"
using namespace gralloc;
using android::sp;
-const int GRALLOC_HEAP_MASK = GRALLOC_USAGE_PRIVATE_ADSP_HEAP |
- GRALLOC_USAGE_PRIVATE_UI_CONTIG_HEAP |
- GRALLOC_USAGE_PRIVATE_SMI_HEAP |
- GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP |
- GRALLOC_USAGE_PRIVATE_IOMMU_HEAP |
- GRALLOC_USAGE_PRIVATE_MM_HEAP |
- GRALLOC_USAGE_PRIVATE_WRITEBACK_HEAP |
- GRALLOC_USAGE_PRIVATE_CAMERA_HEAP;
+const int GRALLOC_HEAP_MASK = GRALLOC_USAGE_PRIVATE_ADSP_HEAP |
+ GRALLOC_USAGE_PRIVATE_UI_CONTIG_HEAP |
+ GRALLOC_USAGE_PRIVATE_SMI_HEAP |
+ GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP |
+ GRALLOC_USAGE_PRIVATE_IOMMU_HEAP |
+ GRALLOC_USAGE_PRIVATE_MM_HEAP |
+ GRALLOC_USAGE_PRIVATE_WRITEBACK_HEAP |
+ GRALLOC_USAGE_PRIVATE_CAMERA_HEAP;
//Common functions
-static bool canFallback(int compositionType, int usage, bool triedSystem)
+static bool canFallback(int usage, bool triedSystem)
{
// Fallback to system heap when alloc fails unless
// 1. Composition type is MDP
@@ -60,11 +62,12 @@
// 4. The heap type is protected
// 5. The buffer is meant for external display only
- if(compositionType == MDP_COMPOSITION)
+ if(QCCompositionType::getInstance().getCompositionType() & COMPOSITION_TYPE_MDP)
return false;
if(triedSystem)
return false;
- if(usage & (GRALLOC_HEAP_MASK | GRALLOC_USAGE_PROTECTED))
+ if(usage & (GRALLOC_HEAP_MASK | GRALLOC_USAGE_PROTECTED |
+ GRALLOC_USAGE_PRIVATE_CP_BUFFER))
return false;
if(usage & (GRALLOC_HEAP_MASK | GRALLOC_USAGE_EXTERNAL_ONLY))
return false;
@@ -107,13 +110,15 @@
}
int IonController::allocate(alloc_data& data, int usage,
- int compositionType)
+ int compositionType)
{
int ionFlags = 0;
int ret;
bool noncontig = false;
data.uncached = useUncached(usage);
+ data.allocType = 0;
+
if(usage & GRALLOC_USAGE_PRIVATE_UI_CONTIG_HEAP)
ionFlags |= ION_HEAP(ION_SF_HEAP_ID);
@@ -134,11 +139,13 @@
if(usage & GRALLOC_USAGE_PRIVATE_CAMERA_HEAP)
ionFlags |= ION_HEAP(ION_CAMERA_HEAP_ID);
- if(usage & GRALLOC_USAGE_PROTECTED)
+ if(usage & GRALLOC_USAGE_PRIVATE_CP_BUFFER)
ionFlags |= ION_SECURE;
if(usage & GRALLOC_USAGE_PRIVATE_DO_NOT_MAP)
- data.allocType = private_handle_t::PRIV_FLAGS_NOT_MAPPED;
+ data.allocType |= private_handle_t::PRIV_FLAGS_NOT_MAPPED;
+ else
+ data.allocType &= ~(private_handle_t::PRIV_FLAGS_NOT_MAPPED);
// if no flags are set, default to
// SF + IOMMU heaps, so that bypass can work
@@ -149,9 +156,9 @@
data.flags = ionFlags;
ret = mIonAlloc->alloc_buffer(data);
+
// Fallback
- if(ret < 0 && canFallback(compositionType,
- usage,
+ if(ret < 0 && canFallback(usage,
(ionFlags & ION_SYSTEM_HEAP_ID)))
{
ALOGW("Falling back to system heap");
@@ -161,7 +168,7 @@
}
if(ret >= 0 ) {
- data.allocType = private_handle_t::PRIV_FLAGS_USES_ION;
+ data.allocType |= private_handle_t::PRIV_FLAGS_USES_ION;
if(noncontig)
data.allocType |= private_handle_t::PRIV_FLAGS_NONCONTIGUOUS_MEM;
if(ionFlags & ION_SECURE)
@@ -183,14 +190,14 @@
return memalloc;
}
-#if 0
//-------------- PmemKernelController-----------------------//
-
+//XXX: Remove - we're not using pmem anymore
+#if 0
PmemKernelController::PmemKernelController()
{
- mPmemAdspAlloc = new PmemKernelAlloc(DEVICE_PMEM_ADSP);
- // XXX: Right now, there is no need to maintain an instance
- // of the SMI allocator as we need it only in a few cases
+ mPmemAdspAlloc = new PmemKernelAlloc(DEVICE_PMEM_ADSP);
+ // XXX: Right now, there is no need to maintain an instance
+ // of the SMI allocator as we need it only in a few cases
}
PmemKernelController::~PmemKernelController()
@@ -198,7 +205,7 @@
}
int PmemKernelController::allocate(alloc_data& data, int usage,
- int compositionType)
+ int compositionType)
{
int ret = 0;
bool adspFallback = false;
@@ -258,12 +265,13 @@
}
int PmemAshmemController::allocate(alloc_data& data, int usage,
- int compositionType)
+ int compositionType)
{
int ret = 0;
+ data.allocType = 0;
// Make buffers cacheable by default
- data.uncached = false;
+ data.uncached = false;
// Override if we explicitly need uncached buffers
if (usage & GRALLOC_USAGE_PRIVATE_UNCACHED)
@@ -298,7 +306,7 @@
// Fallback
if(ret >= 0 ) {
data.allocType = private_handle_t::PRIV_FLAGS_USES_PMEM;
- } else if(ret < 0 && canFallback(compositionType, usage, false)) {
+ } else if(ret < 0 && canFallback(usage, false)) {
ALOGW("Falling back to ashmem");
ret = mAshmemAlloc->alloc_buffer(data);
if(ret >= 0) {
@@ -327,9 +335,8 @@
return memalloc;
}
#endif
-
size_t getBufferSizeAndDimensions(int width, int height, int format,
- int& alignedw, int &alignedh)
+ int& alignedw, int &alignedh)
{
size_t size;
@@ -376,16 +383,25 @@
if (HAL_PIXEL_FORMAT_NV12_ENCODEABLE == format) {
// The encoder requires a 2K aligned chroma offset.
size = ALIGN(alignedw*alignedh, 2048) +
- (ALIGN(alignedw/2, 16) * (alignedh/2))*2;
+ (ALIGN(alignedw/2, 16) * (alignedh/2))*2;
} else {
size = alignedw*alignedh +
(ALIGN(alignedw/2, 16) * (alignedh/2))*2;
}
size = ALIGN(size, 4096);
break;
-
+ case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+ case HAL_PIXEL_FORMAT_YCrCb_422_SP:
+ if(width & 1) {
+ ALOGE("width is odd for the YUV422_SP format");
+ return -EINVAL;
+ }
+ alignedw = ALIGN(width, 16);
+ alignedh = height;
+ size = ALIGN(alignedw * alignedh * 2, 4096);
+ break;
default:
- ALOGE("unrecognized pixel format: %d", format);
+ ALOGE("unrecognized pixel format: 0x%x", format);
return -EINVAL;
}
@@ -397,31 +413,31 @@
// to free the buffer using the free_buffer function
int alloc_buffer(private_handle_t **pHnd, int w, int h, int format, int usage)
{
- alloc_data data;
- int alignedw, alignedh;
- android::sp<gralloc::IAllocController> sAlloc =
- gralloc::IAllocController::getInstance(false);
- data.base = 0;
- data.fd = -1;
- data.offset = 0;
- data.size = getBufferSizeAndDimensions(w, h, format, alignedw, alignedh);
- data.align = getpagesize();
- data.uncached = useUncached(usage);
- int allocFlags = usage;
+ alloc_data data;
+ int alignedw, alignedh;
+ android::sp<gralloc::IAllocController> sAlloc =
+ gralloc::IAllocController::getInstance(false);
+ data.base = 0;
+ data.fd = -1;
+ data.offset = 0;
+ data.size = getBufferSizeAndDimensions(w, h, format, alignedw, alignedh);
+ data.align = getpagesize();
+ data.uncached = useUncached(usage);
+ int allocFlags = usage;
- int err = sAlloc->allocate(data, allocFlags, 0);
- if (0 != err) {
- ALOGE("%s: allocate failed", __FUNCTION__);
- return -ENOMEM;
- }
+ int err = sAlloc->allocate(data, allocFlags, 0);
+ if (0 != err) {
+ ALOGE("%s: allocate failed", __FUNCTION__);
+ return -ENOMEM;
+ }
- private_handle_t* hnd = new private_handle_t(data.fd, data.size,
- data.allocType, 0, format, alignedw, alignedh);
- hnd->base = (int) data.base;
- hnd->offset = data.offset;
- hnd->gpuaddr = 0;
- *pHnd = hnd;
- return 0;
+ private_handle_t* hnd = new private_handle_t(data.fd, data.size,
+ data.allocType, 0, format, alignedw, alignedh);
+ hnd->base = (int) data.base;
+ hnd->offset = data.offset;
+ hnd->gpuaddr = 0;
+ *pHnd = hnd;
+ return 0;
}
void free_buffer(private_handle_t *hnd)
diff --git a/libgralloc/alloc_controller.h b/libgralloc/alloc_controller.h
index 6c907d1..134ad40 100644
--- a/libgralloc/alloc_controller.h
+++ b/libgralloc/alloc_controller.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-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
@@ -33,82 +33,82 @@
namespace gralloc {
- struct alloc_data;
- class IMemAlloc;
- class IonAlloc;
+struct alloc_data;
+class IMemAlloc;
+class IonAlloc;
- class IAllocController : public android::RefBase {
+class IAllocController : public android::RefBase {
- public:
- /* Allocate using a suitable method
- * Returns the type of buffer allocated
- */
- virtual int allocate(alloc_data& data, int usage,
- int compositionType) = 0;
+ public:
+ /* Allocate using a suitable method
+ * Returns the type of buffer allocated
+ */
+ virtual int allocate(alloc_data& data, int usage,
+ int compositionType) = 0;
- virtual android::sp<IMemAlloc> getAllocator(int flags) = 0;
+ virtual android::sp<IMemAlloc> getAllocator(int flags) = 0;
- virtual ~IAllocController() {};
+ virtual ~IAllocController() {};
- static android::sp<IAllocController> getInstance(bool useMasterHeap);
+ static android::sp<IAllocController> getInstance(bool useMasterHeap);
- private:
- static android::sp<IAllocController> sController;
+ private:
+ static android::sp<IAllocController> sController;
- };
+};
- class IonController : public IAllocController {
+class IonController : public IAllocController {
- public:
- virtual int allocate(alloc_data& data, int usage,
- int compositionType);
+ public:
+ virtual int allocate(alloc_data& data, int usage,
+ int compositionType);
- virtual android::sp<IMemAlloc> getAllocator(int flags);
+ virtual android::sp<IMemAlloc> getAllocator(int flags);
- IonController();
+ IonController();
- private:
- android::sp<IonAlloc> mIonAlloc;
+ private:
+ android::sp<IonAlloc> mIonAlloc;
- };
+};
- class PmemKernelController : public IAllocController {
+class PmemKernelController : public IAllocController {
- public:
- virtual int allocate(alloc_data& data, int usage,
- int compositionType);
+ public:
+ virtual int allocate(alloc_data& data, int usage,
+ int compositionType);
- virtual android::sp<IMemAlloc> getAllocator(int flags);
+ virtual android::sp<IMemAlloc> getAllocator(int flags);
- PmemKernelController ();
+ PmemKernelController ();
- ~PmemKernelController ();
+ ~PmemKernelController ();
- private:
- android::sp<IMemAlloc> mPmemAdspAlloc;
+ private:
+ android::sp<IMemAlloc> mPmemAdspAlloc;
- };
+};
- // Main pmem controller - this should only
- // be used within gralloc
- class PmemAshmemController : public IAllocController {
+// Main pmem controller - this should only
+// be used within gralloc
+class PmemAshmemController : public IAllocController {
- public:
- virtual int allocate(alloc_data& data, int usage,
- int compositionType);
+ public:
+ virtual int allocate(alloc_data& data, int usage,
+ int compositionType);
- virtual android::sp<IMemAlloc> getAllocator(int flags);
+ virtual android::sp<IMemAlloc> getAllocator(int flags);
- PmemAshmemController();
+ PmemAshmemController();
- ~PmemAshmemController();
+ ~PmemAshmemController();
- private:
- android::sp<IMemAlloc> mPmemUserspaceAlloc;
- android::sp<IMemAlloc> mAshmemAlloc;
- android::sp<IAllocController> mPmemKernelCtrl;
+ private:
+ android::sp<IMemAlloc> mPmemUserspaceAlloc;
+ android::sp<IMemAlloc> mAshmemAlloc;
+ android::sp<IAllocController> mPmemKernelCtrl;
- };
+};
} //end namespace gralloc
#endif // GRALLOC_ALLOCCONTROLLER_H
diff --git a/libgralloc/ashmemalloc.cpp b/libgralloc/ashmemalloc.cpp
index 8397e21..b659d90 100644
--- a/libgralloc/ashmemalloc.cpp
+++ b/libgralloc/ashmemalloc.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-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
@@ -53,14 +53,14 @@
} else {
if (ashmem_set_prot_region(fd, prot) < 0) {
ALOGE("ashmem_set_prot_region(fd=%d, prot=%x) failed (%s)",
- fd, prot, strerror(errno));
+ fd, prot, strerror(errno));
close(fd);
err = -errno;
} else {
base = mmap(0, data.size, prot, MAP_SHARED|MAP_POPULATE|MAP_LOCKED, fd, 0);
if (base == MAP_FAILED) {
ALOGE("alloc mmap(fd=%d, size=%d, prot=%x) failed (%s)",
- fd, data.size, prot, strerror(errno));
+ fd, data.size, prot, strerror(errno));
close(fd);
err = -errno;
} else {
@@ -74,7 +74,7 @@
data.offset = offset;
clean_buffer(base, data.size, offset, fd);
ALOGD("ashmem: Allocated buffer base:%p size:%d fd:%d",
- base, data.size, fd);
+ base, data.size, fd);
}
return err;
@@ -84,7 +84,7 @@
int AshmemAlloc::free_buffer(void* base, size_t size, int offset, int fd)
{
ALOGD("ashmem: Freeing buffer base:%p size:%d fd:%d",
- base, size, fd);
+ base, size, fd);
int err = 0;
if(!base) {
@@ -102,15 +102,15 @@
void *base = 0;
base = mmap(0, size, PROT_READ| PROT_WRITE,
- MAP_SHARED|MAP_POPULATE, fd, 0);
+ MAP_SHARED|MAP_POPULATE, fd, 0);
*pBase = base;
if(base == MAP_FAILED) {
ALOGE("ashmem: Failed to map memory in the client: %s",
- strerror(errno));
+ strerror(errno));
err = -errno;
} else {
ALOGD("ashmem: Mapped buffer base:%p size:%d fd:%d",
- base, size, fd);
+ base, size, fd);
}
return err;
}
@@ -121,7 +121,7 @@
int err = munmap(base, size);
if(err) {
ALOGE("ashmem: Failed to unmap memory at %p: %s",
- base, strerror(errno));
+ base, strerror(errno));
}
return err;
diff --git a/libgralloc/ashmemalloc.h b/libgralloc/ashmemalloc.h
index 051dcd1..50daf04 100644
--- a/libgralloc/ashmemalloc.h
+++ b/libgralloc/ashmemalloc.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-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
@@ -34,23 +34,23 @@
#include <linux/ion.h>
namespace gralloc {
- class AshmemAlloc : public IMemAlloc {
+class AshmemAlloc : public IMemAlloc {
- public:
- virtual int alloc_buffer(alloc_data& data);
+ public:
+ virtual int alloc_buffer(alloc_data& data);
- virtual int free_buffer(void *base, size_t size,
- int offset, int fd);
+ virtual int free_buffer(void *base, size_t size,
+ int offset, int fd);
- virtual int map_buffer(void **pBase, size_t size,
- int offset, int fd);
+ virtual int map_buffer(void **pBase, size_t size,
+ int offset, int fd);
- virtual int unmap_buffer(void *base, size_t size,
- int offset);
+ virtual int unmap_buffer(void *base, size_t size,
+ int offset);
- virtual int clean_buffer(void*base, size_t size,
- int offset, int fd);
+ virtual int clean_buffer(void*base, size_t size,
+ int offset, int fd);
- };
+};
}
#endif /* GRALLOC_ASHMEMALLOC_H */
diff --git a/libgralloc/fb_priv.h b/libgralloc/fb_priv.h
new file mode 100644
index 0000000..677d1c1
--- /dev/null
+++ b/libgralloc/fb_priv.h
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (c) 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.
+ */
+
+#ifndef FB_PRIV_H
+#define FB_PRIV_H
+#include <linux/fb.h>
+
+#define NUM_FRAMEBUFFERS_MIN 2
+//XXX: Enable triple framebuffers
+#define NUM_FRAMEBUFFERS_MAX 2
+
+#define NO_SURFACEFLINGER_SWAPINTERVAL
+#define COLOR_FORMAT(x) (x & 0xFFF) // Max range for colorFormats is 0 - FFF
+
+#ifdef __cplusplus
+template <class T>
+struct Node
+{
+ T data;
+ Node<T> *next;
+};
+
+template <class T>
+class Queue
+{
+ public:
+ Queue(): front(NULL), back(NULL), len(0) {dummy = new T;}
+ ~Queue()
+ {
+ clear();
+ delete dummy;
+ }
+ void push(const T& item) //add an item to the back of the queue
+ {
+ if(len != 0) { //if the queue is not empty
+ back->next = new Node<T>; //create a new node
+ back = back->next; //set the new node as the back node
+ back->data = item;
+ back->next = NULL;
+ } else {
+ back = new Node<T>;
+ back->data = item;
+ back->next = NULL;
+ front = back;
+ }
+ len++;
+ }
+ void pop() //remove the first item from the queue
+ {
+ if (isEmpty())
+ return; //if the queue is empty, no node to dequeue
+ T item = front->data;
+ Node<T> *tmp = front;
+ front = front->next;
+ delete tmp;
+ if(front == NULL) //if the queue is empty, update the back pointer
+ back = NULL;
+ len--;
+ return;
+ }
+ T& getHeadValue() const //return the value of the first item in the queue
+ { //without modification to the structure
+ if (isEmpty()) {
+ ALOGE("Error can't get head of empty queue");
+ return *dummy;
+ }
+ return front->data;
+ }
+
+ bool isEmpty() const //returns true if no elements are in the queue
+ {
+ return (front == NULL);
+ }
+
+ size_t size() const //returns the amount of elements in the queue
+ {
+ return len;
+ }
+
+ private:
+ Node<T> *front;
+ Node<T> *back;
+ size_t len;
+ void clear()
+ {
+ while (!isEmpty())
+ pop();
+ }
+ T *dummy;
+};
+#endif
+
+enum hdmi_mirroring_state {
+ HDMI_NO_MIRRORING,
+ HDMI_UI_MIRRORING,
+};
+
+struct private_handle_t;
+
+struct qbuf_t {
+ buffer_handle_t buf;
+ int idx;
+};
+
+enum buf_state {
+ SUB,
+ REF,
+ AVL
+};
+
+enum {
+ // flag to indicate we'll post this buffer
+ PRIV_USAGE_LOCKED_FOR_POST = 0x80000000,
+ PRIV_MIN_SWAP_INTERVAL = 0,
+ PRIV_MAX_SWAP_INTERVAL = 1,
+};
+
+
+struct avail_t {
+ pthread_mutex_t lock;
+ pthread_cond_t cond;
+ bool is_avail;
+ buf_state state;
+};
+
+struct private_module_t {
+ gralloc_module_t base;
+
+ struct private_handle_t* framebuffer;
+ uint32_t fbFormat;
+ uint32_t flags;
+ uint32_t numBuffers;
+ uint32_t bufferMask;
+ pthread_mutex_t lock;
+ buffer_handle_t currentBuffer;
+
+ struct fb_var_screeninfo info;
+ struct fb_fix_screeninfo finfo;
+ float xdpi;
+ float ydpi;
+ float fps;
+ uint32_t swapInterval;
+ Queue<struct qbuf_t> disp; // non-empty when buffer is ready for display
+ int currentIdx;
+ struct avail_t avail[NUM_FRAMEBUFFERS_MAX];
+ pthread_mutex_t qlock;
+ pthread_cond_t qpost;
+#if defined(__cplusplus) && defined(HDMI_DUAL_DISPLAY)
+ int orientation;
+ int videoOverlay; // VIDEO_OVERLAY - 2D or 3D
+ int secureVideoOverlay; // VideoOverlay is secure
+ uint32_t currentOffset;
+ int enableHDMIOutput; // holds the type of external display
+ bool trueMirrorSupport;
+ bool exitHDMIUILoop;
+ float actionsafeWidthRatio;
+ float actionsafeHeightRatio;
+ bool hdmiStateChanged;
+ hdmi_mirroring_state hdmiMirroringState;
+ pthread_mutex_t overlayLock;
+ pthread_cond_t overlayPost;
+#endif
+};
+
+
+
+#endif /* FB_PRIV_H */
diff --git a/libgralloc/framebuffer.cpp b/libgralloc/framebuffer.cpp
index b6b4a8f..4935785 100644
--- a/libgralloc/framebuffer.cpp
+++ b/libgralloc/framebuffer.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2008 The Android Open Source Project
-* Copyright (c) 2010-2012 Code Aurora Forum. All rights reserved.
+ * 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.
@@ -17,15 +17,11 @@
#include <sys/mman.h>
-#include <dlfcn.h>
-
-#include <cutils/ashmem.h>
#include <cutils/log.h>
#include <cutils/properties.h>
-#include <utils/Timers.h>
+#include <dlfcn.h>
#include <hardware/hardware.h>
-#include <hardware/gralloc.h>
#include <fcntl.h>
#include <errno.h>
@@ -33,9 +29,6 @@
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
-#include <utils/Timers.h>
-
-#include <cutils/log.h>
#include <cutils/atomic.h>
#include <linux/fb.h>
@@ -44,18 +37,15 @@
#include <GLES/gl.h>
#include "gralloc_priv.h"
+#include "fb_priv.h"
#include "gr.h"
-#ifdef NO_SURFACEFLINGER_SWAPINTERVAL
#include <cutils/properties.h>
-#endif
+#include <qcomutils/profiler.h>
-#include <qcom_ui.h>
+#include "overlay.h"
+namespace ovutils = overlay::utils;
-#define FB_DEBUG 0
-
-#if defined(HDMI_DUAL_DISPLAY)
#define EVEN_OUT(x) if (x & 0x0001) {x--;}
-using overlay::Overlay;
/** min of int a, b */
static inline int min(int a, int b) {
return (a<b) ? a : b;
@@ -64,50 +54,31 @@
static inline int max(int a, int b) {
return (a>b) ? a : b;
}
-#endif
char framebufferStateName[] = {'S', 'R', 'A'};
-/*****************************************************************************/
-
-enum {
- MDDI_PANEL = '1',
- EBI2_PANEL = '2',
- LCDC_PANEL = '3',
- EXT_MDDI_PANEL = '4',
- TV_PANEL = '5'
-};
-
enum {
PAGE_FLIP = 0x00000001,
- LOCKED = 0x00000002
+ LOCKED = 0x00000002
};
struct fb_context_t {
framebuffer_device_t device;
};
-static int neworientation;
-
-/*****************************************************************************/
-
-static void
-msm_copy_buffer(buffer_handle_t handle, int fd,
- int width, int height, int format,
- int x, int y, int w, int h);
static int fb_setSwapInterval(struct framebuffer_device_t* dev,
- int interval)
+ int interval)
{
char pval[PROPERTY_VALUE_MAX];
- property_get("debug.gr.swapinterval", pval, "-1");
+ property_get("debug.egl.swapinterval", pval, "-1");
int property_interval = atoi(pval);
if (property_interval >= 0)
interval = property_interval;
fb_context_t* ctx = (fb_context_t*)dev;
private_module_t* m = reinterpret_cast<private_module_t*>(
- dev->common.module);
+ dev->common.module);
if (interval < dev->minSwapInterval || interval > dev->maxSwapInterval)
return -EINVAL;
@@ -116,13 +87,13 @@
}
static int fb_setUpdateRect(struct framebuffer_device_t* dev,
- int l, int t, int w, int h)
+ int l, int t, int w, int h)
{
if (((w|h) <= 0) || ((l|t)<0))
return -EINVAL;
fb_context_t* ctx = (fb_context_t*)dev;
private_module_t* m = reinterpret_cast<private_module_t*>(
- dev->common.module);
+ dev->common.module);
m->info.reserved[0] = 0x54445055; // "UPDT";
m->info.reserved[1] = (uint16_t)l | ((uint32_t)t << 16);
m->info.reserved[2] = (uint16_t)(l+w) | ((uint32_t)(t+h) << 16);
@@ -150,7 +121,7 @@
// post buf out to display synchronously
private_handle_t const* hnd = reinterpret_cast<private_handle_t const*>
- (nxtBuf.buf);
+ (nxtBuf.buf);
const size_t offset = hnd->base - m->framebuffer->base;
m->info.activate = FB_ACTIVATE_VBL;
m->info.yoffset = offset / m->finfo.line_length;
@@ -173,28 +144,30 @@
int nxtAvail = ((nxtBuf.idx + 1) % m->numBuffers);
pthread_mutex_lock(&(m->avail[nxtBuf.idx].lock));
m->avail[nxtBuf.idx].is_avail = true;
- m->avail[nxtBuf.idx].state = REF;
- pthread_cond_broadcast(&(m->avail[nxtBuf.idx].cond));
+ m->avail[nxtBuf.idx].state = SUB;
+ pthread_cond_signal(&(m->avail[nxtBuf.idx].cond));
pthread_mutex_unlock(&(m->avail[nxtBuf.idx].lock));
} else {
+#if 0 //XXX: Triple FB
pthread_mutex_lock(&(m->avail[nxtBuf.idx].lock));
if (m->avail[nxtBuf.idx].state != SUB) {
ALOGE_IF(m->swapInterval != 0, "[%d] state %c, expected %c", nxtBuf.idx,
- framebufferStateName[m->avail[nxtBuf.idx].state],
- framebufferStateName[SUB]);
+ framebufferStateName[m->avail[nxtBuf.idx].state],
+ framebufferStateName[SUB]);
}
+
m->avail[nxtBuf.idx].state = REF;
pthread_mutex_unlock(&(m->avail[nxtBuf.idx].lock));
-
- pthread_mutex_lock(&(m->avail[cur_buf].lock));
- m->avail[cur_buf].is_avail = true;
if (m->avail[cur_buf].state != REF) {
ALOGE_IF(m->swapInterval != 0, "[%d] state %c, expected %c", cur_buf,
- framebufferStateName[m->avail[cur_buf].state],
- framebufferStateName[REF]);
+ framebufferStateName[m->avail[cur_buf].state],
+ framebufferStateName[SUB]);
}
m->avail[cur_buf].state = AVL;
- pthread_cond_broadcast(&(m->avail[cur_buf].cond));
+#endif
+ pthread_mutex_lock(&(m->avail[cur_buf].lock));
+ m->avail[cur_buf].is_avail = true;
+ pthread_cond_signal(&(m->avail[cur_buf].cond));
pthread_mutex_unlock(&(m->avail[cur_buf].lock));
}
cur_buf = nxtBuf.idx;
@@ -205,14 +178,19 @@
#if defined(HDMI_DUAL_DISPLAY)
static int closeHDMIChannel(private_module_t* m)
{
+ // XXX - when enabling HDMI
+#if 0
Overlay* pTemp = m->pobjOverlay;
if(pTemp != NULL)
pTemp->closeChannel();
+#endif
return 0;
}
+// XXX - Complete when enabling HDMI
+#if 0
static void getSecondaryDisplayDestinationInfo(private_module_t* m, overlay_rect&
- rect, int& orientation)
+ rect, int& orientation)
{
Overlay* pTemp = m->pobjOverlay;
int width = pTemp->getFBWidth();
@@ -224,10 +202,10 @@
switch(rot) {
// ROT_0
case 0:
- // ROT_180
+ // ROT_180
case HAL_TRANSFORM_ROT_180:
pTemp->getAspectRatioPosition(fbwidth, fbheight,
- &rect);
+ &rect);
if(rot == HAL_TRANSFORM_ROT_180)
orientation = HAL_TRANSFORM_ROT_180;
else
@@ -242,7 +220,7 @@
//Width and height will be swapped as there
//is rotation
pTemp->getAspectRatioPosition(fbheight, fbwidth,
- &rect);
+ &rect);
if(rot == HAL_TRANSFORM_ROT_90)
orientation = HAL_TRANSFORM_ROT_270;
@@ -252,82 +230,175 @@
}
return;
}
+#endif
+
+/* Determine overlay state based on whether hardware supports true UI
+ mirroring and whether video is playing or not */
+static ovutils::eOverlayState getOverlayState(struct private_module_t* module)
+{
+ overlay2::Overlay& ov = *(Overlay::getInstance());
+
+ // Default to existing state
+ ovutils::eOverlayState state = ov.getState();
+
+ // Sanity check
+ if (!module) {
+ ALOGE("%s: NULL module", __FUNCTION__);
+ return state;
+ }
+
+ // Check if video is playing or not
+ if (module->videoOverlay) {
+ // Video is playing, check if hardware supports true UI mirroring
+ if (module->trueMirrorSupport) {
+ // True UI mirroring is supported by hardware
+ if (ov.getState() == ovutils::OV_2D_VIDEO_ON_PANEL) {
+ // Currently playing 2D video
+ state = ovutils::OV_2D_TRUE_UI_MIRROR;
+ } else if (ov.getState() == ovutils::OV_3D_VIDEO_ON_2D_PANEL) {
+ // Currently playing M3D video
+ // FIXME: Support M3D true UI mirroring
+ state = ovutils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV;
+ }
+ } else {
+ // True UI mirroring is not supported by hardware
+ if (ov.getState() == ovutils::OV_2D_VIDEO_ON_PANEL) {
+ // Currently playing 2D video
+ state = ovutils::OV_2D_VIDEO_ON_PANEL_TV;
+ } else if (ov.getState() == ovutils::OV_3D_VIDEO_ON_2D_PANEL) {
+ // Currently playing M3D video
+ state = ovutils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV;
+ }
+ }
+ } else {
+ // Video is not playing, true UI mirroring support is irrelevant
+ state = ovutils::OV_UI_MIRROR;
+ }
+
+ return state;
+}
+
+/* Set overlay state */
+static void setOverlayState(ovutils::eOverlayState state)
+{
+ overlay2::Overlay& ov = *(Overlay::getInstance());
+ ov.setState(state);
+}
static void *hdmi_ui_loop(void *ptr)
{
- private_module_t* m = reinterpret_cast<private_module_t*>(
- ptr);
+ private_module_t* m = reinterpret_cast<private_module_t*>(ptr);
while (1) {
pthread_mutex_lock(&m->overlayLock);
while(!(m->hdmiStateChanged))
pthread_cond_wait(&(m->overlayPost), &(m->overlayLock));
+
m->hdmiStateChanged = false;
if (m->exitHDMIUILoop) {
pthread_mutex_unlock(&m->overlayLock);
return NULL;
}
- bool waitForVsync = true;
- int flags = WAIT_FOR_VSYNC;
- if (m->pobjOverlay) {
- Overlay* pTemp = m->pobjOverlay;
- if (m->hdmiMirroringState == HDMI_NO_MIRRORING)
- closeHDMIChannel(m);
- else if(m->hdmiMirroringState == HDMI_UI_MIRRORING) {
- if (!pTemp->isChannelUP()) {
- int alignedW = ALIGN(m->info.xres, 32);
- private_handle_t const* hnd =
- reinterpret_cast<private_handle_t const*>(m->framebuffer);
- overlay_buffer_info info;
- info.width = alignedW;
- info.height = hnd->height;
- info.format = hnd->format;
- info.size = hnd->size;
+ // No need to mirror UI if HDMI is not on
+ if (!m->enableHDMIOutput) {
+ ALOGE_IF(FB_DEBUG, "%s: hdmi not ON", __FUNCTION__);
+ pthread_mutex_unlock(&m->overlayLock);
+ continue;
+ }
- if (m->trueMirrorSupport)
- flags &= ~WAIT_FOR_VSYNC;
- // start the overlay Channel for mirroring
- // m->enableHDMIOutput corresponds to the fbnum
- if (pTemp->startChannel(info, m->enableHDMIOutput,
- false, true, 0, VG0_PIPE, flags)) {
- pTemp->setFd(m->framebuffer->fd);
- pTemp->setCrop(0, 0, m->info.xres, m->info.yres);
- } else
- closeHDMIChannel(m);
- }
+ overlay2::OverlayMgr* ovMgr =
+ overlay2::OverlayMgrSingleton::getOverlayMgr();
+ overlay2::Overlay& ov = ovMgr->ov();
- if (pTemp->isChannelUP()) {
- overlay_rect destRect;
- int rot = 0;
- int currOrientation = 0;
- getSecondaryDisplayDestinationInfo(m, destRect, rot);
- pTemp->getOrientation(currOrientation);
- if(rot != currOrientation) {
- pTemp->setTransform(rot);
- }
- EVEN_OUT(destRect.x);
- EVEN_OUT(destRect.y);
- EVEN_OUT(destRect.w);
- EVEN_OUT(destRect.h);
- int currentX = 0, currentY = 0;
- uint32_t currentW = 0, currentH = 0;
- if (pTemp->getPosition(currentX, currentY, currentW, currentH)) {
- if ((currentX != destRect.x) || (currentY != destRect.y) ||
- (currentW != destRect.w) || (currentH != destRect.h)) {
- pTemp->setPosition(destRect.x, destRect.y, destRect.w,
- destRect.h);
- }
- }
- if (m->trueMirrorSupport) {
- // if video is started the UI channel should be NO_WAIT.
- flags = !m->videoOverlay ? WAIT_FOR_VSYNC : 0;
- pTemp->updateOverlayFlags(flags);
- }
- pTemp->queueBuffer(m->currentOffset);
- }
+ // Set overlay state
+ ovutils::eOverlayState state = getOverlayState(m);
+ setOverlayState(state);
+
+ // Determine the RGB pipe for UI depending on the state
+ ovutils::eDest dest = ovutils::OV_PIPE_ALL;
+ if (state == ovutils::OV_2D_TRUE_UI_MIRROR) {
+ // True UI mirroring state: external RGB pipe is OV_PIPE2
+ dest = ovutils::OV_PIPE2;
+ } else if (state == ovutils::OV_UI_MIRROR) {
+ // UI-only mirroring state: external RGB pipe is OV_PIPE0
+ dest = ovutils::OV_PIPE0;
+ } else {
+ // No UI in this case
+ pthread_mutex_unlock(&m->overlayLock);
+ continue;
+ }
+
+ if (m->hdmiMirroringState == HDMI_UI_MIRRORING) {
+ int alignedW = ALIGN(m->info.xres, 32);
+
+ private_handle_t const* hnd =
+ reinterpret_cast<private_handle_t const*>(m->framebuffer);
+ unsigned int width = alignedW;
+ unsigned int height = hnd->height;
+ unsigned int format = hnd->format;
+ unsigned int size = hnd->size/m->numBuffers;
+
+ ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
+ // External display connected during secure video playback
+ // Open secure UI session
+ // NOTE: when external display is already connected and then secure
+ // playback is started, we dont have to do anything
+ if (m->secureVideoOverlay) {
+ ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
}
- else
- closeHDMIChannel(m);
+
+ ovutils::Whf whf(width, height, format, size);
+ ovutils::PipeArgs parg(mdpFlags,
+ ovutils::OVERLAY_TRANSFORM_0,
+ whf,
+ ovutils::WAIT,
+ ovutils::ZORDER_0,
+ ovutils::IS_FG_OFF,
+ ovutils::ROT_FLAG_ENABLED);
+ ovutils::PipeArgs pargs[ovutils::MAX_PIPES] = { parg, parg, parg };
+ bool ret = ov.setSource(pargs, dest);
+ if (!ret) {
+ ALOGE("%s setSource failed", __FUNCTION__);
+ }
+
+ // we need to communicate m->orientation that will get some
+ // modifications within setParameter func.
+ // FIXME that is ugly.
+ const ovutils::Params prms (ovutils::OVERLAY_TRANSFORM_UI,
+ m->orientation);
+ ov.setParameter(prms, dest);
+ if (!ret) {
+ ALOGE("%s setParameter failed transform", __FUNCTION__);
+ }
+
+ // x,y,w,h
+ ovutils::Dim dcrop(0, 0, m->info.xres, m->info.yres);
+ ov.setMemoryId(m->framebuffer->fd, dest);
+ ret = ov.setCrop(dcrop, dest);
+ if (!ret) {
+ ALOGE("%s setCrop failed", __FUNCTION__);
+ }
+
+ ovutils::Dim pdim (m->info.xres,
+ m->info.yres,
+ 0,
+ 0,
+ m->orientation);
+ ret = ov.setPosition(pdim, dest);
+ if (!ret) {
+ ALOGE("%s setPosition failed", __FUNCTION__);
+ }
+
+ if (!ov.commit(dest)) {
+ ALOGE("%s commit fails", __FUNCTION__);
+ }
+
+ ret = ov.queueBuffer(m->currentOffset, dest);
+ if (!ret) {
+ ALOGE("%s queueBuffer failed", __FUNCTION__);
+ }
+ } else {
+ setOverlayState(ovutils::OV_CLOSED);
}
pthread_mutex_unlock(&m->overlayLock);
}
@@ -336,20 +407,30 @@
static int fb_videoOverlayStarted(struct framebuffer_device_t* dev, int started)
{
+ ALOGE_IF(FB_DEBUG, "%s started=%d", __FUNCTION__, started);
private_module_t* m = reinterpret_cast<private_module_t*>(
- dev->common.module);
+ dev->common.module);
pthread_mutex_lock(&m->overlayLock);
- Overlay* pTemp = m->pobjOverlay;
if(started != m->videoOverlay) {
m->videoOverlay = started;
+ m->hdmiStateChanged = true;
if (!m->trueMirrorSupport) {
- m->hdmiStateChanged = true;
- if (started && pTemp) {
+ if (started) {
m->hdmiMirroringState = HDMI_NO_MIRRORING;
- closeHDMIChannel(m);
+ ovutils::eOverlayState state = getOverlayState(m);
+ setOverlayState(state);
} else if (m->enableHDMIOutput)
m->hdmiMirroringState = HDMI_UI_MIRRORING;
- pthread_cond_signal(&(m->overlayPost));
+ } else {
+ if (m->videoOverlay == VIDEO_3D_OVERLAY_STARTED) {
+ ALOGE_IF(FB_DEBUG, "3D Video Started, stop mirroring!");
+ m->hdmiMirroringState = HDMI_NO_MIRRORING;
+ ovutils::eOverlayState state = getOverlayState(m);
+ setOverlayState(state);
+ }
+ else if (m->enableHDMIOutput) {
+ m->hdmiMirroringState = HDMI_UI_MIRRORING;
+ }
}
}
pthread_mutex_unlock(&m->overlayLock);
@@ -358,14 +439,13 @@
static int fb_enableHDMIOutput(struct framebuffer_device_t* dev, int externaltype)
{
+ ALOGE_IF(FB_DEBUG, "%s externaltype=%d", __FUNCTION__, externaltype);
private_module_t* m = reinterpret_cast<private_module_t*>(
- dev->common.module);
+ dev->common.module);
pthread_mutex_lock(&m->overlayLock);
- Overlay* pTemp = m->pobjOverlay;
//Check if true mirroring can be supported
- m->trueMirrorSupport = FrameBufferInfo::getInstance()->canSupportTrueMirroring();
+ m->trueMirrorSupport = ovutils::FrameBufferInfo::getInstance()->supportTrueMirroring();
m->enableHDMIOutput = externaltype;
- ALOGE("In fb_enableHDMIOutput: externaltype = %d", m->enableHDMIOutput);
if(externaltype) {
if (m->trueMirrorSupport) {
m->hdmiMirroringState = HDMI_UI_MIRRORING;
@@ -373,9 +453,11 @@
if(!m->videoOverlay)
m->hdmiMirroringState = HDMI_UI_MIRRORING;
}
- } else if (!externaltype && pTemp) {
+ } else if (!externaltype) {
+ // Either HDMI is disconnected or suspend occurred
m->hdmiMirroringState = HDMI_NO_MIRRORING;
- closeHDMIChannel(m);
+ ovutils::eOverlayState state = getOverlayState(m);
+ setOverlayState(state);
}
m->hdmiStateChanged = true;
pthread_cond_signal(&(m->overlayPost));
@@ -383,58 +465,132 @@
return 0;
}
-
-static int fb_setActionSafeWidthRatio(struct framebuffer_device_t* dev, float asWidthRatio)
-{
- private_module_t* m = reinterpret_cast<private_module_t*>(
- dev->common.module);
- pthread_mutex_lock(&m->overlayLock);
- m->actionsafeWidthRatio = asWidthRatio;
- pthread_mutex_unlock(&m->overlayLock);
- return 0;
-}
-
-static int fb_setActionSafeHeightRatio(struct framebuffer_device_t* dev, float asHeightRatio)
-{
- private_module_t* m = reinterpret_cast<private_module_t*>(
- dev->common.module);
- pthread_mutex_lock(&m->overlayLock);
- m->actionsafeHeightRatio = asHeightRatio;
- pthread_mutex_unlock(&m->overlayLock);
- return 0;
-}
-
static int fb_orientationChanged(struct framebuffer_device_t* dev, int orientation)
{
private_module_t* m = reinterpret_cast<private_module_t*>(
- dev->common.module);
+ dev->common.module);
pthread_mutex_lock(&m->overlayLock);
neworientation = orientation;
pthread_mutex_unlock(&m->overlayLock);
return 0;
}
+
+static int handle_open_secure_start(private_module_t* m) {
+ pthread_mutex_lock(&m->overlayLock);
+ m->hdmiMirroringState = HDMI_NO_MIRRORING;
+ m->secureVideoOverlay = true;
+ pthread_mutex_unlock(&m->overlayLock);
+ return 0;
+}
+
+static int handle_open_secure_end(private_module_t* m) {
+ pthread_mutex_lock(&m->overlayLock);
+ if (m->enableHDMIOutput) {
+ if (m->trueMirrorSupport) {
+ m->hdmiMirroringState = HDMI_UI_MIRRORING;
+ } else if(!m->videoOverlay) {
+ m->hdmiMirroringState = HDMI_UI_MIRRORING;
+ }
+ m->hdmiStateChanged = true;
+ pthread_cond_signal(&(m->overlayPost));
+ }
+ pthread_mutex_unlock(&m->overlayLock);
+ return 0;
+}
+
+static int handle_close_secure_start(private_module_t* m) {
+ pthread_mutex_lock(&m->overlayLock);
+ m->hdmiMirroringState = HDMI_NO_MIRRORING;
+ m->secureVideoOverlay = false;
+ pthread_mutex_unlock(&m->overlayLock);
+ return 0;
+}
+
+static int handle_close_secure_end(private_module_t* m) {
+ pthread_mutex_lock(&m->overlayLock);
+ if (m->enableHDMIOutput) {
+ if (m->trueMirrorSupport) {
+ m->hdmiMirroringState = HDMI_UI_MIRRORING;
+ } else if(!m->videoOverlay) {
+ m->hdmiMirroringState = HDMI_UI_MIRRORING;
+ }
+ m->hdmiStateChanged = true;
+ pthread_cond_signal(&(m->overlayPost));
+ }
+ pthread_mutex_unlock(&m->overlayLock);
+ return 0;
+}
#endif
+
+
+/* fb_perform - used to add custom event and handle them in fb HAL
+ * Used for external display related functions as of now
+ */
+static int fb_perform(struct framebuffer_device_t* dev, int event, int value)
+{
+ private_module_t* m = reinterpret_cast<private_module_t*>(
+ dev->common.module);
+ switch(event) {
+#if defined(HDMI_DUAL_DISPLAY)
+ case EVENT_EXTERNAL_DISPLAY:
+ fb_enableHDMIOutput(dev, value);
+ break;
+ case EVENT_VIDEO_OVERLAY:
+ fb_videoOverlayStarted(dev, value);
+ break;
+ case EVENT_ORIENTATION_CHANGE:
+ fb_orientationChanged(dev, value);
+ break;
+ case EVENT_OVERLAY_STATE_CHANGE:
+ if (value == OVERLAY_STATE_CHANGE_START) {
+ // When state change starts, get a lock on overlay
+ pthread_mutex_lock(&m->overlayLock);
+ } else if (value == OVERLAY_STATE_CHANGE_END) {
+ // When state change is complete, unlock overlay
+ pthread_mutex_unlock(&m->overlayLock);
+ }
+ break;
+ case EVENT_OPEN_SECURE_START:
+ handle_open_secure_start(m);
+ break;
+ case EVENT_OPEN_SECURE_END:
+ handle_open_secure_end(m);
+ break;
+ case EVENT_CLOSE_SECURE_START:
+ handle_close_secure_start(m);
+ break;
+ case EVENT_CLOSE_SECURE_END:
+ handle_close_secure_end(m);
+ break;
+#endif
+ default:
+ ALOGE("In %s: UNKNOWN Event = %d!!!", __FUNCTION__, event);
+ break;
+ }
+ return 0;
+}
+
+
static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer)
{
if (private_handle_t::validate(buffer) < 0)
return -EINVAL;
- int nxtIdx, futureIdx = -1;
+ int nxtIdx;//, futureIdx = -1;
bool reuse;
struct qbuf_t qb;
fb_context_t* ctx = (fb_context_t*)dev;
private_handle_t const* hnd = reinterpret_cast<private_handle_t const*>(buffer);
private_module_t* m = reinterpret_cast<private_module_t*>(
- dev->common.module);
+ dev->common.module);
if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) {
reuse = false;
nxtIdx = (m->currentIdx + 1) % m->numBuffers;
- futureIdx = (nxtIdx + 1) % m->numBuffers;
-
+ //futureIdx = (nxtIdx + 1) % m->numBuffers;
if (m->swapInterval == 0) {
// if SwapInterval = 0 and no buffers available then reuse
// current buf for next rendering so don't post new buffer
@@ -450,24 +606,25 @@
if(!reuse){
// unlock previous ("current") Buffer and lock the new buffer
m->base.lock(&m->base, buffer,
- private_module_t::PRIV_USAGE_LOCKED_FOR_POST,
- 0,0, m->info.xres, m->info.yres, NULL);
+ PRIV_USAGE_LOCKED_FOR_POST,
+ 0,0, m->info.xres, m->info.yres, NULL);
// post/queue the new buffer
pthread_mutex_lock(&(m->avail[nxtIdx].lock));
- if (m->avail[nxtIdx].is_avail != true) {
- ALOGE_IF(m->swapInterval != 0, "Found %d buf to be not avail", nxtIdx);
- }
-
m->avail[nxtIdx].is_avail = false;
+#if 0 //XXX: Triple FB
+ if (m->avail[nxtIdx].is_avail != true) {
+ ALOGE_IF(m->swapInterval != 0, "Found %d buf to be not avail", nxtIdx);
+ }
if (m->avail[nxtIdx].state != AVL) {
ALOGD("[%d] state %c, expected %c", nxtIdx,
- framebufferStateName[m->avail[nxtIdx].state],
- framebufferStateName[AVL]);
+ framebufferStateName[m->avail[nxtIdx].state],
+ framebufferStateName[AVL]);
}
m->avail[nxtIdx].state = SUB;
+#endif
pthread_mutex_unlock(&(m->avail[nxtIdx].lock));
qb.idx = nxtIdx;
@@ -486,40 +643,12 @@
if (m->currentBuffer)
m->base.unlock(&m->base, m->currentBuffer);
m->base.lock(&m->base, buffer,
- private_module_t::PRIV_USAGE_LOCKED_FOR_POST,
+ PRIV_USAGE_LOCKED_FOR_POST,
0,0, m->info.xres, m->info.yres, NULL);
m->currentBuffer = buffer;
}
- } else {
- void* fb_vaddr;
- void* buffer_vaddr;
- m->base.lock(&m->base, m->framebuffer,
- GRALLOC_USAGE_SW_WRITE_RARELY,
- 0, 0, m->info.xres, m->info.yres,
- &fb_vaddr);
-
- m->base.lock(&m->base, buffer,
- GRALLOC_USAGE_SW_READ_RARELY,
- 0, 0, m->info.xres, m->info.yres,
- &buffer_vaddr);
-
- //memcpy(fb_vaddr, buffer_vaddr, m->finfo.line_length * m->info.yres);
-
- msm_copy_buffer(
- m->framebuffer, m->framebuffer->fd,
- m->info.xres, m->info.yres, m->fbFormat,
- m->info.xoffset, m->info.yoffset,
- m->info.width, m->info.height);
-
- m->base.unlock(&m->base, buffer);
- m->base.unlock(&m->base, m->framebuffer);
}
-
- ALOGD_IF(FB_DEBUG, "Framebuffer state: [0] = %c [1] = %c [2] = %c",
- framebufferStateName[m->avail[0].state],
- framebufferStateName[m->avail[1].state],
- framebufferStateName[m->avail[2].state]);
return 0;
}
@@ -534,7 +663,7 @@
static int fb_lockBuffer(struct framebuffer_device_t* dev, int index)
{
private_module_t* m = reinterpret_cast<private_module_t*>(
- dev->common.module);
+ dev->common.module);
// Return immediately if the buffer is available
if ((m->avail[index].state == AVL) || (m->swapInterval == 0))
@@ -543,15 +672,13 @@
pthread_mutex_lock(&(m->avail[index].lock));
while (m->avail[index].state != AVL) {
pthread_cond_wait(&(m->avail[index].cond),
- &(m->avail[index].lock));
+ &(m->avail[index].lock));
}
pthread_mutex_unlock(&(m->avail[index].lock));
return 0;
}
-/*****************************************************************************/
-
int mapFrameBufferLocked(struct private_module_t* module)
{
// already initialized...
@@ -559,9 +686,9 @@
return 0;
}
char const * const device_template[] = {
- "/dev/graphics/fb%u",
- "/dev/fb%u",
- 0 };
+ "/dev/graphics/fb%u",
+ "/dev/fb%u",
+ 0 };
int fd = -1;
int i=0;
@@ -592,11 +719,11 @@
info.activate = FB_ACTIVATE_NOW;
/* Interpretation of offset for color fields: All offsets are from the right,
- * inside a "pixel" value, which is exactly 'bits_per_pixel' wide (means: you
- * can use the offset as right argument to <<). A pixel afterwards is a bit
- * stream and is written to video memory as that unmodified. This implies
- * big-endian byte order if bits_per_pixel is greater than 8.
- */
+ * inside a "pixel" value, which is exactly 'bits_per_pixel' wide (means: you
+ * can use the offset as right argument to <<). A pixel afterwards is a bit
+ * stream and is written to video memory as that unmodified. This implies
+ * big-endian byte order if bits_per_pixel is greater than 8.
+ */
if(info.bits_per_pixel == 32) {
/*
@@ -617,7 +744,8 @@
* RGBA instead of RGBX. */
if (property_get("debug.sf.hw", property, NULL) > 0 && atoi(property) == 0)
module->fbFormat = HAL_PIXEL_FORMAT_RGBX_8888;
- else if(property_get("debug.composition.type", property, NULL) > 0 && (strncmp(property, "mdp", 3) == 0))
+ else if(property_get("debug.composition.type", property, NULL) > 0 &&
+ (strncmp(property, "mdp", 3) == 0))
module->fbFormat = HAL_PIXEL_FORMAT_RGBX_8888;
else
module->fbFormat = HAL_PIXEL_FORMAT_RGBA_8888;
@@ -641,7 +769,7 @@
int size = roundUpToPageSize(info.yres * info.xres * (info.bits_per_pixel/8));
/*
- * Request NUM_BUFFERS screens (at lest 2 for page flipping)
+ * Request NUM_BUFFERS screens (at least 2 for page flipping)
*/
int numberOfBuffers = (int)(finfo.smem_len/size);
ALOGV("num supported framebuffers in kernel = %d", numberOfBuffers);
@@ -673,7 +801,7 @@
info.yres_virtual = size / line_length;
flags &= ~PAGE_FLIP;
ALOGW("page flipping not supported (yres_virtual=%d, requested=%d)",
- info.yres_virtual, info.yres*2);
+ info.yres_virtual, info.yres*2);
}
if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1)
@@ -691,35 +819,35 @@
//The reserved[4] field is used to store FPS by the driver.
float fps = info.reserved[4];
- ALOGI( "using (fd=%d)\n"
- "id = %s\n"
- "xres = %d px\n"
- "yres = %d px\n"
- "xres_virtual = %d px\n"
- "yres_virtual = %d px\n"
- "bpp = %d\n"
- "r = %2u:%u\n"
- "g = %2u:%u\n"
- "b = %2u:%u\n",
- fd,
- finfo.id,
- info.xres,
- info.yres,
- info.xres_virtual,
- info.yres_virtual,
- info.bits_per_pixel,
- info.red.offset, info.red.length,
- info.green.offset, info.green.length,
- info.blue.offset, info.blue.length
- );
+ ALOGI("using (fd=%d)\n"
+ "id = %s\n"
+ "xres = %d px\n"
+ "yres = %d px\n"
+ "xres_virtual = %d px\n"
+ "yres_virtual = %d px\n"
+ "bpp = %d\n"
+ "r = %2u:%u\n"
+ "g = %2u:%u\n"
+ "b = %2u:%u\n",
+ fd,
+ finfo.id,
+ info.xres,
+ info.yres,
+ info.xres_virtual,
+ info.yres_virtual,
+ info.bits_per_pixel,
+ info.red.offset, info.red.length,
+ info.green.offset, info.green.length,
+ info.blue.offset, info.blue.length
+ );
- ALOGI( "width = %d mm (%f dpi)\n"
- "height = %d mm (%f dpi)\n"
- "refresh rate = %.2f Hz\n",
- info.width, xdpi,
- info.height, ydpi,
- fps
- );
+ ALOGI("width = %d mm (%f dpi)\n"
+ "height = %d mm (%f dpi)\n"
+ "refresh rate = %.2f Hz\n",
+ info.width, xdpi,
+ info.height, ydpi,
+ fps
+ );
if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1)
@@ -739,12 +867,12 @@
char pval[PROPERTY_VALUE_MAX];
property_get("debug.gr.swapinterval", pval, "1");
module->swapInterval = atoi(pval);
- if (module->swapInterval < private_module_t::PRIV_MIN_SWAP_INTERVAL ||
- module->swapInterval > private_module_t::PRIV_MAX_SWAP_INTERVAL) {
+ if (module->swapInterval < PRIV_MIN_SWAP_INTERVAL ||
+ module->swapInterval > PRIV_MAX_SWAP_INTERVAL) {
module->swapInterval = 1;
ALOGW("Out of range (%d to %d) value for debug.gr.swapinterval, using 1",
- private_module_t::PRIV_MIN_SWAP_INTERVAL,
- private_module_t::PRIV_MAX_SWAP_INTERVAL);
+ PRIV_MIN_SWAP_INTERVAL,
+ PRIV_MAX_SWAP_INTERVAL);
}
#else
@@ -765,9 +893,9 @@
}
/* create display update thread */
- pthread_t thread1;
- if (pthread_create(&thread1, NULL, &disp_loop, (void *) module)) {
- return -errno;
+ pthread_t disp_thread;
+ if (pthread_create(&disp_thread, NULL, &disp_loop, (void *) module)) {
+ return -errno;
}
/*
@@ -778,10 +906,12 @@
module->numBuffers = info.yres_virtual / info.yres;
module->bufferMask = 0;
//adreno needs page aligned offsets. Align the fbsize to pagesize.
- size_t fbSize = roundUpToPageSize(finfo.line_length * info.yres) * module->numBuffers;
+ size_t fbSize = roundUpToPageSize(finfo.line_length * info.yres)*
+ module->numBuffers;
module->framebuffer = new private_handle_t(fd, fbSize,
- private_handle_t::PRIV_FLAGS_USES_PMEM, BUFFER_TYPE_UI,
- module->fbFormat, info.xres, info.yres);
+ private_handle_t::PRIV_FLAGS_USES_PMEM,
+ BUFFER_TYPE_UI,
+ module->fbFormat, info.xres, info.yres);
void* vaddr = mmap(0, fbSize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
if (vaddr == MAP_FAILED) {
ALOGE("Error mapping the framebuffer (%s)", strerror(errno));
@@ -794,7 +924,6 @@
/* Overlay for HDMI*/
pthread_mutex_init(&(module->overlayLock), NULL);
pthread_cond_init(&(module->overlayPost), NULL);
- module->pobjOverlay = new Overlay();
module->currentOffset = 0;
module->exitHDMIUILoop = false;
module->hdmiStateChanged = false;
@@ -822,7 +951,7 @@
fb_context_t* ctx = (fb_context_t*)dev;
#if defined(HDMI_DUAL_DISPLAY)
private_module_t* m = reinterpret_cast<private_module_t*>(
- ctx->device.common.module);
+ ctx->device.common.module);
pthread_mutex_lock(&m->overlayLock);
m->exitHDMIUILoop = true;
pthread_cond_signal(&(m->overlayPost));
@@ -835,7 +964,7 @@
}
int fb_device_open(hw_module_t const* module, const char* name,
- hw_device_t** device)
+ hw_device_t** device)
{
int status = -EINVAL;
if (!strcmp(name, GRALLOC_HARDWARE_FB0)) {
@@ -849,22 +978,14 @@
memset(dev, 0, sizeof(*dev));
/* initialize the procs */
- dev->device.common.tag = HARDWARE_DEVICE_TAG;
- dev->device.common.version = 0;
- dev->device.common.module = const_cast<hw_module_t*>(module);
- dev->device.common.close = fb_close;
+ dev->device.common.tag = HARDWARE_DEVICE_TAG;
+ dev->device.common.version = 0;
+ dev->device.common.module = const_cast<hw_module_t*>(module);
+ dev->device.common.close = fb_close;
dev->device.setSwapInterval = fb_setSwapInterval;
dev->device.post = fb_post;
- dev->device.setUpdateRect = 0;
+ dev->device.setUpdateRect = 0;
dev->device.compositionComplete = fb_compositionComplete;
- //dev->device.lockBuffer = fb_lockBuffer;
-#if defined(HDMI_DUAL_DISPLAY)
- dev->device.orientationChanged = fb_orientationChanged;
- dev->device.videoOverlayStarted = fb_videoOverlayStarted;
- dev->device.enableHDMIOutput = fb_enableHDMIOutput;
- dev->device.setActionSafeWidthRatio = fb_setActionSafeWidthRatio;
- dev->device.setActionSafeHeightRatio = fb_setActionSafeHeightRatio;
-#endif
private_module_t* m = (private_module_t*)module;
status = mapFrameBuffer(m);
@@ -878,11 +999,10 @@
const_cast<float&>(dev->device.xdpi) = m->xdpi;
const_cast<float&>(dev->device.ydpi) = m->ydpi;
const_cast<float&>(dev->device.fps) = m->fps;
- const_cast<int&>(dev->device.minSwapInterval) = private_module_t::PRIV_MIN_SWAP_INTERVAL;
- const_cast<int&>(dev->device.maxSwapInterval) = private_module_t::PRIV_MAX_SWAP_INTERVAL;
- //const_cast<int&>(dev->device.numFramebuffers) = m->numBuffers;
+ const_cast<int&>(dev->device.minSwapInterval) = PRIV_MIN_SWAP_INTERVAL;
+ const_cast<int&>(dev->device.maxSwapInterval) = PRIV_MAX_SWAP_INTERVAL;
if (m->finfo.reserved[0] == 0x5444 &&
- m->finfo.reserved[1] == 0x5055) {
+ m->finfo.reserved[1] == 0x5055) {
dev->device.setUpdateRect = fb_setUpdateRect;
ALOGD("UPDATE_ON_DEMAND supported");
}
@@ -895,43 +1015,3 @@
}
return status;
}
-
-/* Copy a pmem buffer to the framebuffer */
-
-static void
-msm_copy_buffer(buffer_handle_t handle, int fd,
- int width, int height, int format,
- int x, int y, int w, int h)
-{
- struct {
- unsigned int count;
- mdp_blit_req req;
- } blit;
- private_handle_t *priv = (private_handle_t*) handle;
-
- memset(&blit, 0, sizeof(blit));
- blit.count = 1;
-
- blit.req.flags = 0;
- blit.req.alpha = 0xff;
- blit.req.transp_mask = 0xffffffff;
-
- blit.req.src.width = width;
- blit.req.src.height = height;
- blit.req.src.offset = 0;
- blit.req.src.memory_id = priv->fd;
-
- blit.req.dst.width = width;
- blit.req.dst.height = height;
- blit.req.dst.offset = 0;
- blit.req.dst.memory_id = fd;
- blit.req.dst.format = format;
-
- blit.req.src_rect.x = blit.req.dst_rect.x = x;
- blit.req.src_rect.y = blit.req.dst_rect.y = y;
- blit.req.src_rect.w = blit.req.dst_rect.w = w;
- blit.req.src_rect.h = blit.req.dst_rect.h = h;
-
- if (ioctl(fd, MSMFB_BLIT, &blit))
- ALOGE("MSMFB_BLIT failed = %d", -errno);
-}
diff --git a/libgralloc/gpu.cpp b/libgralloc/gpu.cpp
old mode 100755
new mode 100644
index 77ad174..0ec8d73
--- a/libgralloc/gpu.cpp
+++ b/libgralloc/gpu.cpp
@@ -32,34 +32,12 @@
using android::sp;
gpu_context_t::gpu_context_t(const private_module_t* module,
- sp<IAllocController> alloc_ctrl ) :
+ sp<IAllocController> alloc_ctrl ) :
mAllocCtrl(alloc_ctrl)
{
// Zero out the alloc_device_t
memset(static_cast<alloc_device_t*>(this), 0, sizeof(alloc_device_t));
- char property[PROPERTY_VALUE_MAX];
- if (property_get("debug.sf.hw", property, NULL) > 0) {
- if(atoi(property) == 0) {
- //debug.sf.hw = 0
- compositionType = CPU_COMPOSITION;
- } else { //debug.sf.hw = 1
- // Get the composition type
- property_get("debug.composition.type", property, NULL);
- if (property == NULL) {
- compositionType = GPU_COMPOSITION;
- } else if ((strncmp(property, "mdp", 3)) == 0) {
- compositionType = MDP_COMPOSITION;
- } else if ((strncmp(property, "c2d", 3)) == 0) {
- compositionType = C2D_COMPOSITION;
- } else {
- compositionType = GPU_COMPOSITION;
- }
- }
- } else { //debug.sf.hw is not set. Use cpu composition
- compositionType = CPU_COMPOSITION;
- }
-
// Initialize the procs
common.tag = HARDWARE_DEVICE_TAG;
common.version = 0;
@@ -74,7 +52,7 @@
}
int gpu_context_t::gralloc_alloc_framebuffer_locked(size_t size, int usage,
- buffer_handle_t* pHandle)
+ buffer_handle_t* pHandle)
{
private_module_t* m = reinterpret_cast<private_module_t*>(common.module);
@@ -136,7 +114,7 @@
int gpu_context_t::gralloc_alloc_framebuffer(size_t size, int usage,
- buffer_handle_t* pHandle)
+ buffer_handle_t* pHandle)
{
private_module_t* m = reinterpret_cast<private_module_t*>(common.module);
pthread_mutex_lock(&m->lock);
@@ -162,7 +140,7 @@
else
data.align = getpagesize();
data.pHandle = (unsigned int) pHandle;
- err = mAllocCtrl->allocate(data, usage, compositionType);
+ err = mAllocCtrl->allocate(data, usage, 0);
if (usage & GRALLOC_USAGE_PRIVATE_UNSYNCHRONIZED) {
flags |= private_handle_t::PRIV_FLAGS_UNSYNCHRONIZED;
@@ -179,7 +157,8 @@
if (err == 0) {
flags |= data.allocType;
private_handle_t* hnd = new private_handle_t(data.fd, size, flags,
- bufferType, format, width, height);
+ bufferType, format, width,
+ height);
hnd->offset = data.offset;
hnd->base = int(data.base) + data.offset;
@@ -217,7 +196,8 @@
}
int gpu_context_t::alloc_impl(int w, int h, int format, int usage,
- buffer_handle_t* pHandle, int* pStride, size_t bufferSize) {
+ buffer_handle_t* pHandle, int* pStride,
+ size_t bufferSize) {
if (!pHandle || !pStride)
return -EINVAL;
@@ -234,8 +214,9 @@
// All buffers marked as protected or for external
// display need to go to overlay
if ((usage & GRALLOC_USAGE_EXTERNAL_DISP) ||
- (usage & GRALLOC_USAGE_PROTECTED)) {
- bufferType = BUFFER_TYPE_VIDEO;
+ (usage & GRALLOC_USAGE_PROTECTED) ||
+ (usage & GRALLOC_USAGE_PRIVATE_CP_BUFFER)) {
+ bufferType = BUFFER_TYPE_VIDEO;
}
int err;
if (usage & GRALLOC_USAGE_HW_FB) {
@@ -268,12 +249,12 @@
int index = (hnd->base - m->framebuffer->base) / bufferSize;
m->bufferMask &= ~(1<<index);
} else {
+ terminateBuffer(&m->base, const_cast<private_handle_t*>(hnd));
sp<IMemAlloc> memalloc = mAllocCtrl->getAllocator(hnd->flags);
int err = memalloc->free_buffer((void*)hnd->base, (size_t) hnd->size,
- hnd->offset, hnd->fd);
+ hnd->offset, hnd->fd);
if(err)
return err;
- terminateBuffer(&m->base, const_cast<private_handle_t*>(hnd));
}
// Release the genlock
@@ -287,7 +268,8 @@
}
int gpu_context_t::gralloc_alloc(alloc_device_t* dev, int w, int h, int format,
- int usage, buffer_handle_t* pHandle, int* pStride)
+ int usage, buffer_handle_t* pHandle,
+ int* pStride)
{
if (!dev) {
return -EINVAL;
@@ -295,8 +277,10 @@
gpu_context_t* gpu = reinterpret_cast<gpu_context_t*>(dev);
return gpu->alloc_impl(w, h, format, usage, pHandle, pStride, 0);
}
-int gpu_context_t::gralloc_alloc_size(alloc_device_t* dev, int w, int h, int format,
- int usage, buffer_handle_t* pHandle, int* pStride, int bufferSize)
+int gpu_context_t::gralloc_alloc_size(alloc_device_t* dev, int w, int h,
+ int format, int usage,
+ buffer_handle_t* pHandle, int* pStride,
+ int bufferSize)
{
if (!dev) {
return -EINVAL;
@@ -307,7 +291,7 @@
int gpu_context_t::gralloc_free(alloc_device_t* dev,
- buffer_handle_t handle)
+ buffer_handle_t handle)
{
if (private_handle_t::validate(handle) < 0)
return -EINVAL;
diff --git a/libgralloc/gpu.h b/libgralloc/gpu.h
index 301c411..487f4d1 100644
--- a/libgralloc/gpu.h
+++ b/libgralloc/gpu.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2008 The Android Open Source Project
- * Copyright (c) 2011 Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-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.
@@ -28,54 +28,51 @@
#include <utils/RefBase.h>
#include "gralloc_priv.h"
+#include <fb_priv.h>
namespace gralloc {
- class IAllocController;
- class gpu_context_t : public alloc_device_t {
- public:
- gpu_context_t(const private_module_t* module,
- android::sp<IAllocController>alloc_ctrl);
+class IAllocController;
+class gpu_context_t : public alloc_device_t {
+ public:
+ gpu_context_t(const private_module_t* module,
+ android::sp<IAllocController>alloc_ctrl);
- int gralloc_alloc_framebuffer_locked(size_t size, int usage,
- buffer_handle_t* pHandle);
+ int gralloc_alloc_framebuffer_locked(size_t size, int usage,
+ buffer_handle_t* pHandle);
- int gralloc_alloc_framebuffer(size_t size, int usage,
- buffer_handle_t* pHandle);
+ int gralloc_alloc_framebuffer(size_t size, int usage,
+ buffer_handle_t* pHandle);
- int gralloc_alloc_buffer(size_t size, int usage,
- buffer_handle_t* pHandle,
- int bufferType, int format,
- int width, int height);
+ int gralloc_alloc_buffer(size_t size, int usage,
+ buffer_handle_t* pHandle,
+ int bufferType, int format,
+ int width, int height);
- int free_impl(private_handle_t const* hnd);
+ int free_impl(private_handle_t const* hnd);
- int alloc_impl(int w, int h, int format, int usage,
- buffer_handle_t* pHandle, int* pStride,
- size_t bufferSize = 0);
+ int alloc_impl(int w, int h, int format, int usage,
+ buffer_handle_t* pHandle, int* pStride,
+ size_t bufferSize = 0);
- static int gralloc_alloc(alloc_device_t* dev, int w, int h,
- int format, int usage,
- buffer_handle_t* pHandle,
- int* pStride);
+ static int gralloc_alloc(alloc_device_t* dev, int w, int h,
+ int format, int usage,
+ buffer_handle_t* pHandle,
+ int* pStride);
- static int gralloc_free(alloc_device_t* dev, buffer_handle_t handle);
+ static int gralloc_free(alloc_device_t* dev, buffer_handle_t handle);
- static int gralloc_alloc_size(alloc_device_t* dev,
- int w, int h, int format,
- int usage, buffer_handle_t* pHandle,
- int* pStride, int bufferSize);
+ static int gralloc_alloc_size(alloc_device_t* dev,
+ int w, int h, int format,
+ int usage, buffer_handle_t* pHandle,
+ int* pStride, int bufferSize);
- static int gralloc_close(struct hw_device_t *dev);
+ static int gralloc_close(struct hw_device_t *dev);
- int get_composition_type() const { return compositionType; }
-
-
- private:
- android::sp<IAllocController> mAllocCtrl;
- int compositionType;
- void getGrallocInformationFromFormat(int inputFormat,
- int *colorFormat,
- int *bufferType);
- };
+ private:
+ android::sp<IAllocController> mAllocCtrl;
+ void getGrallocInformationFromFormat(int inputFormat,
+ int *colorFormat,
+ int *bufferType);
+};
}
#endif // GRALLOC_GPU_H
diff --git a/libgralloc/gr.h b/libgralloc/gr.h
index cc36d9a..b330da9 100644
--- a/libgralloc/gr.h
+++ b/libgralloc/gr.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2008 The Android Open Source Project
- * Copyright (c) 2011 Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-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.
@@ -51,11 +51,11 @@
int mapFrameBufferLocked(struct private_module_t* module);
int terminateBuffer(gralloc_module_t const* module, private_handle_t* hnd);
size_t getBufferSizeAndDimensions(int width, int height, int format,
- int& alignedw, int &alignedh);
+ int& alignedw, int &alignedh);
int decideBufferHandlingMechanism(int format, const char *compositionUsed,
- int hasBlitEngine, int *needConversion,
- int *useBufferDirectly);
+ int hasBlitEngine, int *needConversion,
+ int *useBufferDirectly);
// Allocate buffer from width, height, format into a private_handle_t
// It is the responsibility of the caller to free the buffer
@@ -66,10 +66,10 @@
class Locker {
pthread_mutex_t mutex;
-public:
+ public:
class Autolock {
Locker& locker;
- public:
+ public:
inline Autolock(Locker& locker) : locker(locker) { locker.lock(); }
inline ~Autolock() { locker.unlock(); }
};
diff --git a/libgralloc/gralloc.cpp b/libgralloc/gralloc.cpp
index a98baf8..cf57fee 100644
--- a/libgralloc/gralloc.cpp
+++ b/libgralloc/gralloc.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2008, The Android Open Source Project
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-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.
@@ -36,71 +36,71 @@
using android::sp;
int fb_device_open(const hw_module_t* module, const char* name,
- hw_device_t** device);
+ hw_device_t** device);
static int gralloc_device_open(const hw_module_t* module, const char* name,
- hw_device_t** device);
+ hw_device_t** device);
extern int gralloc_lock(gralloc_module_t const* module,
- buffer_handle_t handle, int usage,
- int l, int t, int w, int h,
- void** vaddr);
+ buffer_handle_t handle, int usage,
+ int l, int t, int w, int h,
+ void** vaddr);
extern int gralloc_unlock(gralloc_module_t const* module,
- buffer_handle_t handle);
+ buffer_handle_t handle);
extern int gralloc_register_buffer(gralloc_module_t const* module,
- buffer_handle_t handle);
+ buffer_handle_t handle);
extern int gralloc_unregister_buffer(gralloc_module_t const* module,
- buffer_handle_t handle);
+ buffer_handle_t handle);
extern int gralloc_perform(struct gralloc_module_t const* module,
- int operation, ... );
+ int operation, ... );
// HAL module methods
static struct hw_module_methods_t gralloc_module_methods = {
- open: gralloc_device_open
+open: gralloc_device_open
};
// HAL module initialize
struct private_module_t HAL_MODULE_INFO_SYM = {
- base: {
- common: {
- tag: HARDWARE_MODULE_TAG,
- version_major: 1,
- version_minor: 0,
- id: GRALLOC_HARDWARE_MODULE_ID,
- name: "Graphics Memory Allocator Module",
- author: "The Android Open Source Project",
- methods: &gralloc_module_methods,
- dso: 0,
- reserved: {0},
- },
- registerBuffer: gralloc_register_buffer,
- unregisterBuffer: gralloc_unregister_buffer,
- lock: gralloc_lock,
- unlock: gralloc_unlock,
- perform: gralloc_perform,
- reserved_proc: {0},
- },
- framebuffer: 0,
- fbFormat: 0,
- flags: 0,
- numBuffers: 0,
- bufferMask: 0,
- lock: PTHREAD_MUTEX_INITIALIZER,
- currentBuffer: 0,
+base: {
+ common: {
+ tag: HARDWARE_MODULE_TAG,
+ version_major: 1,
+ version_minor: 0,
+ id: GRALLOC_HARDWARE_MODULE_ID,
+ name: "Graphics Memory Allocator Module",
+ author: "The Android Open Source Project",
+ methods: &gralloc_module_methods,
+ dso: 0,
+ reserved: {0},
+ },
+ registerBuffer: gralloc_register_buffer,
+ unregisterBuffer: gralloc_unregister_buffer,
+ lock: gralloc_lock,
+ unlock: gralloc_unlock,
+ perform: gralloc_perform,
+ reserved_proc: {0},
+ },
+framebuffer: 0,
+fbFormat: 0,
+flags: 0,
+numBuffers: 0,
+bufferMask: 0,
+lock: PTHREAD_MUTEX_INITIALIZER,
+currentBuffer: 0,
};
// Open Gralloc device
int gralloc_device_open(const hw_module_t* module, const char* name,
- hw_device_t** device)
+ hw_device_t** device)
{
int status = -EINVAL;
if (!strcmp(name, GRALLOC_HARDWARE_GPU0)) {
const private_module_t* m = reinterpret_cast<const private_module_t*>(
- module);
+ module);
gpu_context_t *dev;
sp<IAllocController> alloc_ctrl = IAllocController::getInstance(true);
dev = new gpu_context_t(m, alloc_ctrl);
diff --git a/libgralloc/gralloc_priv.h b/libgralloc/gralloc_priv.h
index 0679621..846a611 100644
--- a/libgralloc/gralloc_priv.h
+++ b/libgralloc/gralloc_priv.h
@@ -28,13 +28,6 @@
#include <cutils/native_handle.h>
-#include <linux/fb.h>
-
-#if defined(__cplusplus) && defined(HDMI_DUAL_DISPLAY)
-#include "overlayLib.h"
-using namespace overlay;
-#endif
-
#include <cutils/log.h>
enum {
@@ -87,6 +80,14 @@
* other EXTERNAL_ONLY buffers are available. Used during suspend.
*/
GRALLOC_USAGE_EXTERNAL_BLOCK = 0x00020000,
+
+ /* Use this flag to request content protected buffers. Please note
+ * that this flag is different from the GRALLOC_USAGE_PROTECTED flag
+ * which can be used for buffers that are not secured for DRM
+ * but still need to be protected from screen captures
+ * 0x00040000 is reserved and these values are subject to change.
+ */
+ GRALLOC_USAGE_PRIVATE_CP_BUFFER = 0x00080000,
};
enum {
@@ -96,107 +97,12 @@
};
-enum {
- GPU_COMPOSITION,
- C2D_COMPOSITION,
- MDP_COMPOSITION,
- CPU_COMPOSITION,
-};
-
-/* numbers of max buffers for page flipping */
-#define NUM_FRAMEBUFFERS_MIN 2
-#define NUM_FRAMEBUFFERS_MAX 3
-
-/* number of default bufers for page flipping */
-#define NUM_DEF_FRAME_BUFFERS 2
-#define NO_SURFACEFLINGER_SWAPINTERVAL
#define INTERLACE_MASK 0x80
#define S3D_FORMAT_MASK 0xFF000
-#define COLOR_FORMAT(x) (x & 0xFFF) // Max range for colorFormats is 0 - FFF
#define DEVICE_PMEM "/dev/pmem"
#define DEVICE_PMEM_ADSP "/dev/pmem_adsp"
#define DEVICE_PMEM_SMIPOOL "/dev/pmem_smipool"
/*****************************************************************************/
-#ifdef __cplusplus
-
-//XXX: Remove framebuffer specific classes and defines to a different header
-template <class T>
-struct Node
-{
- T data;
- Node<T> *next;
-};
-
-template <class T>
-class Queue
-{
-public:
- Queue(): front(NULL), back(NULL), len(0) {dummy = new T;}
- ~Queue()
- {
- clear();
- delete dummy;
- }
- void push(const T& item) //add an item to the back of the queue
- {
- if(len != 0) { //if the queue is not empty
- back->next = new Node<T>; //create a new node
- back = back->next; //set the new node as the back node
- back->data = item;
- back->next = NULL;
- } else {
- back = new Node<T>;
- back->data = item;
- back->next = NULL;
- front = back;
- }
- len++;
- }
- void pop() //remove the first item from the queue
- {
- if (isEmpty())
- return; //if the queue is empty, no node to dequeue
- T item = front->data;
- Node<T> *tmp = front;
- front = front->next;
- delete tmp;
- if(front == NULL) //if the queue is empty, update the back pointer
- back = NULL;
- len--;
- return;
- }
- T& getHeadValue() const //return the value of the first item in the queue
- { //without modification to the structure
- if (isEmpty()) {
- ALOGE("Error can't get head of empty queue");
- return *dummy;
- }
- return front->data;
- }
-
- bool isEmpty() const //returns true if no elements are in the queue
- {
- return (front == NULL);
- }
-
- size_t size() const //returns the amount of elements in the queue
- {
- return len;
- }
-
-private:
- Node<T> *front;
- Node<T> *back;
- size_t len;
- void clear()
- {
- while (!isEmpty())
- pop();
- }
- T *dummy;
-};
-#endif
-
enum {
/* OEM specific HAL formats */
HAL_PIXEL_FORMAT_NV12_ENCODEABLE = 0x102,
@@ -206,6 +112,8 @@
HAL_PIXEL_FORMAT_YCrCb_422_SP = 0x10B,
HAL_PIXEL_FORMAT_R_8 = 0x10D,
HAL_PIXEL_FORMAT_RG_88 = 0x10E,
+ HAL_PIXEL_FORMAT_YCbCr_444_SP = 0x10F,
+ HAL_PIXEL_FORMAT_YCrCb_444_SP = 0x110,
HAL_PIXEL_FORMAT_INTERLACE = 0x180,
};
@@ -224,89 +132,8 @@
};
enum {
- BUFFER_TYPE_UI = 0,
- BUFFER_TYPE_VIDEO
-};
-
-#if defined(HDMI_DUAL_DISPLAY)
-enum hdmi_mirroring_state {
- HDMI_NO_MIRRORING,
- HDMI_UI_MIRRORING,
- HDMI_ORIGINAL_RESOLUTION_MIRRORING
-};
-#endif
-/*****************************************************************************/
-
-struct private_module_t;
-struct private_handle_t;
-struct PmemAllocator;
-
-struct qbuf_t {
- buffer_handle_t buf;
- int idx;
-};
-
-enum buf_state {
- SUB,
- REF,
- AVL
-};
-
-struct avail_t {
- pthread_mutex_t lock;
- pthread_cond_t cond;
-#ifdef __cplusplus
- bool is_avail;
- buf_state state;
-#endif
-};
-
-struct private_module_t {
- gralloc_module_t base;
-
- struct private_handle_t* framebuffer;
- uint32_t fbFormat;
- uint32_t flags;
- uint32_t numBuffers;
- uint32_t bufferMask;
- pthread_mutex_t lock;
- buffer_handle_t currentBuffer;
-
- struct fb_var_screeninfo info;
- struct fb_fix_screeninfo finfo;
- float xdpi;
- float ydpi;
- float fps;
- int swapInterval;
-#ifdef __cplusplus
- Queue<struct qbuf_t> disp; // non-empty when buffer is ready for display
-#endif
- int currentIdx;
- struct avail_t avail[NUM_FRAMEBUFFERS_MAX];
- pthread_mutex_t qlock;
- pthread_cond_t qpost;
-
- enum {
- // flag to indicate we'll post this buffer
- PRIV_USAGE_LOCKED_FOR_POST = 0x80000000,
- PRIV_MIN_SWAP_INTERVAL = 0,
- PRIV_MAX_SWAP_INTERVAL = 1,
- };
-#if defined(__cplusplus) && defined(HDMI_DUAL_DISPLAY)
- Overlay* pobjOverlay;
- int orientation;
- bool videoOverlay;
- uint32_t currentOffset;
- int enableHDMIOutput; // holds the type of external display
- bool trueMirrorSupport;
- bool exitHDMIUILoop;
- float actionsafeWidthRatio;
- float actionsafeHeightRatio;
- bool hdmiStateChanged;
- hdmi_mirroring_state hdmiMirroringState;
- pthread_mutex_t overlayLock;
- pthread_cond_t overlayPost;
-#endif
+ BUFFER_TYPE_UI = 0,
+ BUFFER_TYPE_VIDEO
};
/*****************************************************************************/
@@ -314,87 +141,114 @@
#ifdef __cplusplus
struct private_handle_t : public native_handle {
#else
-struct private_handle_t {
- native_handle_t nativeHandle;
+ struct private_handle_t {
+ native_handle_t nativeHandle;
#endif
- enum {
- PRIV_FLAGS_FRAMEBUFFER = 0x00000001,
- PRIV_FLAGS_USES_PMEM = 0x00000002,
- PRIV_FLAGS_USES_PMEM_ADSP = 0x00000004,
- PRIV_FLAGS_USES_ION = 0x00000008,
- PRIV_FLAGS_USES_ASHMEM = 0x00000010,
- PRIV_FLAGS_NEEDS_FLUSH = 0x00000020,
- PRIV_FLAGS_DO_NOT_FLUSH = 0x00000040,
- PRIV_FLAGS_SW_LOCK = 0x00000080,
- PRIV_FLAGS_NONCONTIGUOUS_MEM = 0x00000100,
- PRIV_FLAGS_HWC_LOCK = 0x00000200, // Set by HWC when storing the handle
- PRIV_FLAGS_SECURE_BUFFER = 0x00000400,
- PRIV_FLAGS_UNSYNCHRONIZED = 0x00000800, // For explicit synchronization
- PRIV_FLAGS_NOT_MAPPED = 0x00001000, // Not mapped in userspace
- PRIV_FLAGS_EXTERNAL_ONLY = 0x00002000, // Display on external only
- PRIV_FLAGS_EXTERNAL_BLOCK = 0x00004000, // Display only this buffer on external
- };
+ enum {
+ PRIV_FLAGS_FRAMEBUFFER = 0x00000001,
+ PRIV_FLAGS_USES_PMEM = 0x00000002,
+ PRIV_FLAGS_USES_PMEM_ADSP = 0x00000004,
+ PRIV_FLAGS_USES_ION = 0x00000008,
+ PRIV_FLAGS_USES_ASHMEM = 0x00000010,
+ PRIV_FLAGS_NEEDS_FLUSH = 0x00000020,
+ PRIV_FLAGS_DO_NOT_FLUSH = 0x00000040,
+ PRIV_FLAGS_SW_LOCK = 0x00000080,
+ PRIV_FLAGS_NONCONTIGUOUS_MEM = 0x00000100,
+ // Set by HWC when storing the handle
+ PRIV_FLAGS_HWC_LOCK = 0x00000200,
+ PRIV_FLAGS_SECURE_BUFFER = 0x00000400,
+ // For explicit synchronization
+ PRIV_FLAGS_UNSYNCHRONIZED = 0x00000800,
+ // Not mapped in userspace
+ PRIV_FLAGS_NOT_MAPPED = 0x00001000,
+ // Display on external only
+ PRIV_FLAGS_EXTERNAL_ONLY = 0x00002000,
+ // Display only this buffer on external
+ PRIV_FLAGS_EXTERNAL_BLOCK = 0x00004000,
+ };
- // file-descriptors
- int fd;
- int genlockHandle; // genlock handle to be dup'd by the binder
- // ints
- int magic;
- int flags;
- int size;
- int offset;
- int bufferType;
-
- // FIXME: the attributes below should be out-of-line
- int base;
- int gpuaddr; // The gpu address mapped into the mmu. If using ashmem, set to 0 They don't care
- int pid;
- int format;
- int width;
- int height;
- int genlockPrivFd; // local fd of the genlock device.
+ // file-descriptors
+ int fd;
+ // genlock handle to be dup'd by the binder
+ int genlockHandle;
+ // ints
+ int magic;
+ int flags;
+ int size;
+ int offset;
+ int bufferType;
+ int base;
+ // The gpu address mapped into the mmu.
+ // If using ashmem, set to 0, they don't care
+ int gpuaddr;
+ int pid;
+ int format;
+ int width;
+ int height;
+ // local fd of the genlock device.
+ int genlockPrivFd;
#ifdef __cplusplus
- static const int sNumInts = 12;
- static const int sNumFds = 2;
- static const int sMagic = 'gmsm';
+ static const int sNumInts = 12;
+ static const int sNumFds = 2;
+ static const int sMagic = 'gmsm';
- private_handle_t(int fd, int size, int flags, int bufferType, int format, int width, int height) :
- fd(fd), genlockHandle(-1), magic(sMagic), flags(flags), size(size), offset(0),
- bufferType(bufferType), base(0), gpuaddr(0), pid(getpid()), format(format),
- width(width), height(height), genlockPrivFd(-1)
- {
- version = sizeof(native_handle);
- numInts = sNumInts;
- numFds = sNumFds;
- }
- ~private_handle_t() {
- magic = 0;
- }
+ private_handle_t(int fd, int size, int flags, int bufferType,
+ int format,int width, int height) :
+ fd(fd), genlockHandle(-1), magic(sMagic),
+ flags(flags), size(size), offset(0),
+ bufferType(bufferType), base(0), gpuaddr(0),
+ pid(getpid()), format(format),
+ width(width), height(height), genlockPrivFd(-1)
+ {
+ version = sizeof(native_handle);
+ numInts = sNumInts;
+ numFds = sNumFds;
+ }
+ ~private_handle_t() {
+ magic = 0;
+ }
- bool usesPhysicallyContiguousMemory() {
- return (flags & PRIV_FLAGS_USES_PMEM) != 0;
- }
+ bool usesPhysicallyContiguousMemory() {
+ return (flags & PRIV_FLAGS_USES_PMEM) != 0;
+ }
- static int validate(const native_handle* h) {
- const private_handle_t* hnd = (const private_handle_t*)h;
- if (!h || h->version != sizeof(native_handle) ||
+ static int validate(const native_handle* h) {
+ const private_handle_t* hnd = (const private_handle_t*)h;
+ if (!h || h->version != sizeof(native_handle) ||
h->numInts != sNumInts || h->numFds != sNumFds ||
hnd->magic != sMagic)
- {
- ALOGE("invalid gralloc handle (at %p)", h);
- return -EINVAL;
+ {
+ ALOGD("Invalid gralloc handle (at %p): "
+ "ver(%d/%d) ints(%d/%d) fds(%d/%d) magic(%c%c%c%c/%c%c%c%c)",
+ h,
+ h ? h->version : -1, sizeof(native_handle),
+ h ? h->numInts : -1, sNumInts,
+ h ? h->numFds : -1, sNumFds,
+ hnd ? (((hnd->magic >> 24) & 0xFF)?
+ ((hnd->magic >> 24) & 0xFF) : '-') : '?',
+ hnd ? (((hnd->magic >> 16) & 0xFF)?
+ ((hnd->magic >> 16) & 0xFF) : '-') : '?',
+ hnd ? (((hnd->magic >> 8) & 0xFF)?
+ ((hnd->magic >> 8) & 0xFF) : '-') : '?',
+ hnd ? (((hnd->magic >> 0) & 0xFF)?
+ ((hnd->magic >> 0) & 0xFF) : '-') : '?',
+ (sMagic >> 24) & 0xFF,
+ (sMagic >> 16) & 0xFF,
+ (sMagic >> 8) & 0xFF,
+ (sMagic >> 0) & 0xFF);
+ return -EINVAL;
+ }
+ return 0;
}
- return 0;
- }
- static private_handle_t* dynamicCast(const native_handle* in) {
- if (validate(in) == 0) {
- return (private_handle_t*) in;
+ static private_handle_t* dynamicCast(const native_handle* in) {
+ if (validate(in) == 0) {
+ return (private_handle_t*) in;
+ }
+ return NULL;
}
- return NULL;
- }
#endif
-};
+ };
#endif /* GRALLOC_PRIV_H_ */
diff --git a/libgralloc/ionalloc.cpp b/libgralloc/ionalloc.cpp
index 9ff0a5e..7c8fbf4 100644
--- a/libgralloc/ionalloc.cpp
+++ b/libgralloc/ionalloc.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-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
@@ -48,7 +48,7 @@
if(mIonFd < 0 ) {
ALOGE("%s: Failed to open ion device - %s",
- __FUNCTION__, strerror(errno));
+ __FUNCTION__, strerror(errno));
mIonFd = FD_INIT;
return -errno;
}
@@ -64,6 +64,7 @@
int IonAlloc::alloc_buffer(alloc_data& data)
{
+ Locker::Autolock _l(mLock);
int err = 0;
int ionSyncFd = FD_INIT;
int iFd = FD_INIT;
@@ -84,12 +85,11 @@
if(data.uncached) {
// Use the sync FD to alloc and map
// when we need uncached memory
- // FIX: О–DSYNC defined to open uncached - add that in kernel
- //ionSyncFd = open(ION_DEVICE, O_RDONLY|O_DSYNC);
- ionSyncFd = open(ION_DEVICE, O_RDONLY);
+ // XXX: Change O_SYNC to O_DSYNC when available in bionic
+ ionSyncFd = open(ION_DEVICE, O_RDONLY|O_SYNC);
if(ionSyncFd < 0) {
ALOGE("%s: Failed to open ion device - %s",
- __FUNCTION__, strerror(errno));
+ __FUNCTION__, strerror(errno));
return -errno;
}
iFd = ionSyncFd;
@@ -111,7 +111,7 @@
if(ioctl(iFd, ION_IOC_MAP, &fd_data)) {
err = -errno;
ALOGE("%s: ION_IOC_MAP failed with error - %s",
- __FUNCTION__, strerror(errno));
+ __FUNCTION__, strerror(errno));
ioctl(mIonFd, ION_IOC_FREE, &handle_data);
if(ionSyncFd >= 0)
close(ionSyncFd);
@@ -119,15 +119,15 @@
return err;
}
- //if(!(data.flags & ION_SECURE) &&
- if(!(data.allocType & private_handle_t::PRIV_FLAGS_NOT_MAPPED)) {
+ if(!(data.flags & ION_SECURE) &&
+ !(data.allocType & private_handle_t::PRIV_FLAGS_NOT_MAPPED)) {
base = mmap(0, ionAllocData.len, PROT_READ|PROT_WRITE,
- MAP_SHARED, fd_data.fd, 0);
+ MAP_SHARED, fd_data.fd, 0);
if(base == MAP_FAILED) {
err = -errno;
ALOGE("%s: Failed to map the allocated memory: %s",
- __FUNCTION__, strerror(errno));
+ __FUNCTION__, strerror(errno));
ioctl(mIonFd, ION_IOC_FREE, &handle_data);
ionSyncFd = FD_INIT;
return err;
@@ -146,15 +146,16 @@
data.fd = fd_data.fd;
ioctl(mIonFd, ION_IOC_FREE, &handle_data);
ALOGD("ion: Allocated buffer base:%p size:%d fd:%d",
- data.base, ionAllocData.len, data.fd);
+ data.base, ionAllocData.len, data.fd);
return 0;
}
int IonAlloc::free_buffer(void* base, size_t size, int offset, int fd)
{
+ Locker::Autolock _l(mLock);
ALOGD("ion: Freeing buffer base:%p size:%d fd:%d",
- base, size, fd);
+ base, size, fd);
int err = 0;
err = open_device();
if (err)
@@ -177,15 +178,15 @@
return err;
base = mmap(0, size, PROT_READ| PROT_WRITE,
- MAP_SHARED, fd, 0);
+ MAP_SHARED, fd, 0);
*pBase = base;
if(base == MAP_FAILED) {
err = -errno;
ALOGD("ion: Failed to map memory in the client: %s",
- strerror(errno));
+ strerror(errno));
} else {
ALOGD("ion: Mapped buffer base:%p size:%d offset:%d fd:%d",
- base, size, offset, fd);
+ base, size, offset, fd);
}
return err;
}
@@ -197,7 +198,7 @@
if(munmap(base, size)) {
err = -errno;
ALOGE("ion: Failed to unmap memory at %p : %s",
- base, strerror(errno));
+ base, strerror(errno));
}
return err;
@@ -218,7 +219,7 @@
if (ioctl(mIonFd, ION_IOC_IMPORT, &fd_data)) {
err = -errno;
ALOGE("%s: ION_IOC_IMPORT failed with error - %s",
- __FUNCTION__, strerror(errno));
+ __FUNCTION__, strerror(errno));
return err;
}
@@ -230,7 +231,7 @@
if(ioctl(mIonFd, ION_IOC_CLEAN_INV_CACHES, &flush_data)) {
err = -errno;
ALOGE("%s: ION_IOC_CLEAN_INV_CACHES failed with error - %s",
- __FUNCTION__, strerror(errno));
+ __FUNCTION__, strerror(errno));
ioctl(mIonFd, ION_IOC_FREE, &handle_data);
return err;
}
diff --git a/libgralloc/ionalloc.h b/libgralloc/ionalloc.h
index be26cd7..083f106 100644
--- a/libgralloc/ionalloc.h
+++ b/libgralloc/ionalloc.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-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
@@ -31,39 +31,44 @@
#define GRALLOC_IONALLOC_H
#include "memalloc.h"
+#include "gr.h"
+//#include <linux/ion.h>
+//XXX: Move to bionic
#include "ion_msm.h"
namespace gralloc {
- class IonAlloc : public IMemAlloc {
+class IonAlloc : public IMemAlloc {
- public:
- virtual int alloc_buffer(alloc_data& data);
+ public:
+ virtual int alloc_buffer(alloc_data& data);
- virtual int free_buffer(void *base, size_t size,
- int offset, int fd);
+ virtual int free_buffer(void *base, size_t size,
+ int offset, int fd);
- virtual int map_buffer(void **pBase, size_t size,
- int offset, int fd);
+ virtual int map_buffer(void **pBase, size_t size,
+ int offset, int fd);
- virtual int unmap_buffer(void *base, size_t size,
- int offset);
+ virtual int unmap_buffer(void *base, size_t size,
+ int offset);
- virtual int clean_buffer(void*base, size_t size,
- int offset, int fd);
+ virtual int clean_buffer(void*base, size_t size,
+ int offset, int fd);
- IonAlloc() { mIonFd = FD_INIT; }
+ IonAlloc() { mIonFd = FD_INIT; }
- ~IonAlloc() { close_device(); }
+ ~IonAlloc() { close_device(); }
- private:
- int mIonFd;
+ private:
+ int mIonFd;
- int open_device();
+ int open_device();
- void close_device();
+ void close_device();
- };
+ mutable Locker mLock;
+
+};
}
diff --git a/libgralloc/mapper.cpp b/libgralloc/mapper.cpp
old mode 100755
new mode 100644
index c7ee7d4..4249f3f
--- a/libgralloc/mapper.cpp
+++ b/libgralloc/mapper.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2008 The Android Open Source Project
- * Copyright (c) 2011 Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-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.
@@ -58,8 +58,8 @@
}
static int gralloc_map(gralloc_module_t const* module,
- buffer_handle_t handle,
- void** vaddr)
+ buffer_handle_t handle,
+ void** vaddr)
{
private_handle_t* hnd = (private_handle_t*)handle;
void *mappedAddress;
@@ -68,22 +68,22 @@
size_t size = hnd->size;
sp<IMemAlloc> memalloc = getAllocator(hnd->flags) ;
int err = memalloc->map_buffer(&mappedAddress, size,
- hnd->offset, hnd->fd);
+ hnd->offset, hnd->fd);
if(err) {
ALOGE("Could not mmap handle %p, fd=%d (%s)",
- handle, hnd->fd, strerror(errno));
+ handle, hnd->fd, strerror(errno));
hnd->base = 0;
return -errno;
}
if (mappedAddress == MAP_FAILED) {
ALOGE("Could not mmap handle %p, fd=%d (%s)",
- handle, hnd->fd, strerror(errno));
+ handle, hnd->fd, strerror(errno));
hnd->base = 0;
return -errno;
}
hnd->base = intptr_t(mappedAddress) + hnd->offset;
- //ALOGD("gralloc_map() succeeded fd=%d, off=%d, size=%d, vaddr=%p",
+ //LOGD("gralloc_map() succeeded fd=%d, off=%d, size=%d, vaddr=%p",
// hnd->fd, hnd->offset, hnd->size, mappedAddress);
}
*vaddr = (void*)hnd->base;
@@ -91,7 +91,7 @@
}
static int gralloc_unmap(gralloc_module_t const* module,
- buffer_handle_t handle)
+ buffer_handle_t handle)
{
private_handle_t* hnd = (private_handle_t*)handle;
if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
@@ -116,7 +116,7 @@
/*****************************************************************************/
int gralloc_register_buffer(gralloc_module_t const* module,
- buffer_handle_t handle)
+ buffer_handle_t handle)
{
if (private_handle_t::validate(handle) < 0)
return -EINVAL;
@@ -164,7 +164,7 @@
}
int gralloc_unregister_buffer(gralloc_module_t const* module,
- buffer_handle_t handle)
+ buffer_handle_t handle)
{
if (private_handle_t::validate(handle) < 0)
return -EINVAL;
@@ -195,7 +195,7 @@
}
int terminateBuffer(gralloc_module_t const* module,
- private_handle_t* hnd)
+ private_handle_t* hnd)
{
/*
* If the buffer has been mapped during a lock operation, it's time
@@ -215,7 +215,8 @@
gralloc_unmap(module, hnd);
}
} else {
- ALOGE("terminateBuffer: unmapping a non pmem/ashmem buffer flags = 0x%x", hnd->flags);
+ ALOGE("terminateBuffer: unmapping a non pmem/ashmem buffer flags = 0x%x",
+ hnd->flags);
gralloc_unmap(module, hnd);
}
}
@@ -224,9 +225,9 @@
}
int gralloc_lock(gralloc_module_t const* module,
- buffer_handle_t handle, int usage,
- int l, int t, int w, int h,
- void** vaddr)
+ buffer_handle_t handle, int usage,
+ int l, int t, int w, int h,
+ void** vaddr)
{
if (private_handle_t::validate(handle) < 0)
return -EINVAL;
@@ -254,10 +255,10 @@
int timeout = GENLOCK_MAX_TIMEOUT;
if (GENLOCK_NO_ERROR != genlock_lock_buffer((native_handle_t *)handle,
- (genlock_lock_type)lockType,
- timeout)) {
+ (genlock_lock_type)lockType,
+ timeout)) {
ALOGE("%s: genlock_lock_buffer (lockType=0x%x) failed", __FUNCTION__,
- lockType);
+ lockType);
return -EINVAL;
} else {
// Mark this buffer as locked for SW read/write operation.
@@ -274,7 +275,7 @@
}
int gralloc_unlock(gralloc_module_t const* module,
- buffer_handle_t handle)
+ buffer_handle_t handle)
{
if (private_handle_t::validate(handle) < 0)
return -EINVAL;
@@ -285,9 +286,9 @@
int err;
sp<IMemAlloc> memalloc = getAllocator(hnd->flags) ;
err = memalloc->clean_buffer((void*)hnd->base,
- hnd->size, hnd->offset, hnd->fd);
+ hnd->size, hnd->offset, hnd->fd);
ALOGE_IF(err < 0, "cannot flush handle %p (offs=%x len=%x, flags = 0x%x) err=%s\n",
- hnd, hnd->offset, hnd->size, hnd->flags, strerror(errno));
+ hnd, hnd->offset, hnd->size, hnd->flags, strerror(errno));
hnd->flags &= ~private_handle_t::PRIV_FLAGS_NEEDS_FLUSH;
}
@@ -305,7 +306,7 @@
/*****************************************************************************/
int gralloc_perform(struct gralloc_module_t const* module,
- int operation, ... )
+ int operation, ... )
{
int res = -EINVAL;
va_list args;
@@ -324,12 +325,12 @@
native_handle_t** handle = va_arg(args, native_handle_t**);
int memoryFlags = va_arg(args, int);
private_handle_t* hnd = (private_handle_t*)native_handle_create(
- private_handle_t::sNumFds, private_handle_t::sNumInts);
+ private_handle_t::sNumFds, private_handle_t::sNumInts);
hnd->magic = private_handle_t::sMagic;
hnd->fd = fd;
unsigned int contigFlags = GRALLOC_USAGE_PRIVATE_ADSP_HEAP |
- GRALLOC_USAGE_PRIVATE_UI_CONTIG_HEAP |
- GRALLOC_USAGE_PRIVATE_SMI_HEAP;
+ GRALLOC_USAGE_PRIVATE_UI_CONTIG_HEAP |
+ GRALLOC_USAGE_PRIVATE_SMI_HEAP;
if (memoryFlags & contigFlags) {
// check if the buffer is a pmem buffer
@@ -338,7 +339,7 @@
hnd->flags = private_handle_t::PRIV_FLAGS_USES_ION;
else
hnd->flags = private_handle_t::PRIV_FLAGS_USES_PMEM |
- private_handle_t::PRIV_FLAGS_DO_NOT_FLUSH;
+ private_handle_t::PRIV_FLAGS_DO_NOT_FLUSH;
} else {
if (memoryFlags & GRALLOC_USAGE_PRIVATE_ION)
hnd->flags = private_handle_t::PRIV_FLAGS_USES_ION;
diff --git a/libgralloc/memalloc.h b/libgralloc/memalloc.h
index 13a54e7..349078d 100644
--- a/libgralloc/memalloc.h
+++ b/libgralloc/memalloc.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-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
@@ -35,50 +35,50 @@
namespace gralloc {
- struct alloc_data {
- void *base;
- int fd;
- int offset;
- size_t size;
- size_t align;
- unsigned int pHandle;
- bool uncached;
- unsigned int flags;
- int allocType;
+struct alloc_data {
+ void *base;
+ int fd;
+ int offset;
+ size_t size;
+ size_t align;
+ unsigned int pHandle;
+ bool uncached;
+ unsigned int flags;
+ int allocType;
+};
+
+class IMemAlloc : public android::RefBase {
+
+ public:
+ // Allocate buffer - fill in the alloc_data
+ // structure and pass it in. Mapped address
+ // and fd are returned in the alloc_data struct
+ virtual int alloc_buffer(alloc_data& data) = 0;
+
+ // Free buffer
+ virtual int free_buffer(void *base, size_t size,
+ int offset, int fd) = 0;
+
+ // Map buffer
+ virtual int map_buffer(void **pBase, size_t size,
+ int offset, int fd) = 0;
+
+ // Unmap buffer
+ virtual int unmap_buffer(void *base, size_t size,
+ int offset) = 0;
+
+ // Clean and invalidate
+ virtual int clean_buffer(void *base, size_t size,
+ int offset, int fd) = 0;
+
+ // Destructor
+ virtual ~IMemAlloc() {};
+
+ enum {
+ FD_INIT = -1,
};
- class IMemAlloc : public android::RefBase {
-
- public:
- // Allocate buffer - fill in the alloc_data
- // structure and pass it in. Mapped address
- // and fd are returned in the alloc_data struct
- virtual int alloc_buffer(alloc_data& data) = 0;
-
- // Free buffer
- virtual int free_buffer(void *base, size_t size,
- int offset, int fd) = 0;
-
- // Map buffer
- virtual int map_buffer(void **pBase, size_t size,
- int offset, int fd) = 0;
-
- // Unmap buffer
- virtual int unmap_buffer(void *base, size_t size,
- int offset) = 0;
-
- // Clean and invalidate
- virtual int clean_buffer(void *base, size_t size,
- int offset, int fd) = 0;
-
- // Destructor
- virtual ~IMemAlloc() {};
-
- enum {
- FD_INIT = -1,
- };
-
- };
+};
} // end gralloc namespace
#endif // GRALLOC_MEMALLOC_H
diff --git a/libgralloc/pmem_bestfit_alloc.cpp b/libgralloc/pmem_bestfit_alloc.cpp
index e3875e9..3b91dec 100644
--- a/libgralloc/pmem_bestfit_alloc.cpp
+++ b/libgralloc/pmem_bestfit_alloc.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2009 The Android Open Source Project
- * Copyright (c) 2011 Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-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.
@@ -24,12 +24,12 @@
const int SimpleBestFitAllocator::kMemoryAlign = 32;
SimpleBestFitAllocator::SimpleBestFitAllocator()
- : mHeapSize(0)
+: mHeapSize(0)
{
}
SimpleBestFitAllocator::SimpleBestFitAllocator(size_t size)
- : mHeapSize(0)
+: mHeapSize(0)
{
setSize(size);
}
@@ -113,13 +113,13 @@
mList.insertBefore(free_chunk, split);
}
- LOGE_IF(((free_chunk->start*kMemoryAlign)&(pagesize-1)),
- "page is not aligned!!!");
+ ALOGE_IF(((free_chunk->start*kMemoryAlign)&(pagesize-1)),
+ "page is not aligned!!!");
const ssize_t tail_free = free_size - (size+extra);
if (tail_free > 0) {
chunk_t* split = new chunk_t(
- free_chunk->start + free_chunk->size, tail_free);
+ free_chunk->start + free_chunk->size, tail_free);
mList.insertAfter(free_chunk, split);
}
}
@@ -128,33 +128,33 @@
// we are out of PMEM. Print pmem stats
// check if there is any leak or fragmentation
- LOGD (" Out of PMEM. Dumping PMEM stats for debugging");
- LOGD (" ------------- PRINT PMEM STATS --------------");
+ ALOGD (" Out of PMEM. Dumping PMEM stats for debugging");
+ ALOGD (" ------------- PRINT PMEM STATS --------------");
cur = mList.head();
static uint32_t node_count;
static uint64_t allocated, free_space;
while (cur) {
- LOGD (" Node %d -> Start Address : %u Size %u Free info %d",\
- node_count++, cur->start, cur->size, cur->free);
+ ALOGD (" Node %d -> Start Address : %u Size %u Free info %d",\
+ node_count++, cur->start, cur->size, cur->free);
- // if cur-> free is 1 , the node is free
- // calculate the total allocated and total free stats also
+ // if cur-> free is 1 , the node is free
+ // calculate the total allocated and total free stats also
- if (cur->free)
- free_space += cur->size;
- else
- allocated += cur->size;
- // read next node
- cur = cur->next;
+ if (cur->free)
+ free_space += cur->size;
+ else
+ allocated += cur->size;
+ // read next node
+ cur = cur->next;
}
- LOGD (" Total Allocated: %l Total Free: %l", allocated, free_space );
+ ALOGD (" Total Allocated: %l Total Free: %l", allocated, free_space );
node_count = 0;
allocated = 0;
free_space = 0;
- LOGD ("----------------------------------------------");
+ ALOGD ("----------------------------------------------");
return -ENOMEM;
}
@@ -164,9 +164,9 @@
chunk_t* cur = mList.head();
while (cur) {
if (cur->start == start) {
- LOG_FATAL_IF(cur->free,
- "block at offset 0x%08lX of size 0x%08lX already freed",
- cur->start*kMemoryAlign, cur->size*kMemoryAlign);
+ ALOG_FATAL_IF(cur->free,
+ "block at offset 0x%08lX of size 0x%08lX already freed",
+ cur->start*kMemoryAlign, cur->size*kMemoryAlign);
// merge freed blocks together
chunk_t* freed = cur;
@@ -183,9 +183,9 @@
cur = n;
} while (cur && cur->free);
- LOG_FATAL_IF(!freed->free,
- "freed block at offset 0x%08lX of size 0x%08lX is not free!",
- freed->start * kMemoryAlign, freed->size * kMemoryAlign);
+ ALOG_FATAL_IF(!freed->free,
+ "freed block at offset 0x%08lX of size 0x%08lX is not free!",
+ freed->start * kMemoryAlign, freed->size * kMemoryAlign);
return freed;
}
diff --git a/libgralloc/pmem_bestfit_alloc.h b/libgralloc/pmem_bestfit_alloc.h
index 2ea8452..4346ec3 100644
--- a/libgralloc/pmem_bestfit_alloc.h
+++ b/libgralloc/pmem_bestfit_alloc.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2009 The Android Open Source Project
- * Copyright (c) 2011 Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-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.
@@ -36,8 +36,8 @@
NODE* mFirst;
NODE* mLast;
-public:
- LinkedList() : mFirst(0), mLast(0) { }
+ public:
+ LinkedList() : mFirst(0), mLast(0) { }
bool isEmpty() const { return mFirst == 0; }
NODE const* head() const { return mFirst; }
NODE* head() { return mFirst; }
@@ -53,11 +53,11 @@
}
void insertBefore(NODE* node, NODE* newNode) {
- newNode->prev = node->prev;
- newNode->next = node;
- if (node->prev == 0) mFirst = newNode;
- else node->prev->next = newNode;
- node->prev = newNode;
+ newNode->prev = node->prev;
+ newNode->next = node;
+ if (node->prev == 0) mFirst = newNode;
+ else node->prev->next = newNode;
+ node->prev = newNode;
}
void insertHead(NODE* newNode) {
@@ -94,36 +94,36 @@
class SimpleBestFitAllocator : public gralloc::PmemUserspaceAlloc::Allocator
{
-public:
+ public:
- SimpleBestFitAllocator();
- SimpleBestFitAllocator(size_t size);
- virtual ~SimpleBestFitAllocator();
+ SimpleBestFitAllocator();
+ SimpleBestFitAllocator(size_t size);
+ virtual ~SimpleBestFitAllocator();
- virtual ssize_t setSize(size_t size);
+ virtual ssize_t setSize(size_t size);
- virtual ssize_t allocate(size_t size, uint32_t flags = 0);
- virtual ssize_t deallocate(size_t offset);
- virtual size_t size() const;
+ virtual ssize_t allocate(size_t size, uint32_t flags = 0);
+ virtual ssize_t deallocate(size_t offset);
+ virtual size_t size() const;
-private:
- struct chunk_t {
- chunk_t(size_t start, size_t size)
- : start(start), size(size), free(1), prev(0), next(0) {
- }
- size_t start;
- size_t size : 28;
- int free : 4;
- mutable chunk_t* prev;
- mutable chunk_t* next;
- };
+ private:
+ struct chunk_t {
+ chunk_t(size_t start, size_t size)
+ : start(start), size(size), free(1), prev(0), next(0) {
+ }
+ size_t start;
+ size_t size : 28;
+ int free : 4;
+ mutable chunk_t* prev;
+ mutable chunk_t* next;
+ };
- ssize_t alloc(size_t size, uint32_t flags);
- chunk_t* dealloc(size_t start);
+ ssize_t alloc(size_t size, uint32_t flags);
+ chunk_t* dealloc(size_t start);
- static const int kMemoryAlign;
- mutable Locker mLock;
- LinkedList<chunk_t> mList;
- size_t mHeapSize;
+ static const int kMemoryAlign;
+ mutable Locker mLock;
+ LinkedList<chunk_t> mList;
+ size_t mHeapSize;
};
#endif /* GRALLOC_ALLOCATOR_H_ */
diff --git a/libgralloc/pmemalloc.cpp b/libgralloc/pmemalloc.cpp
index ccbf127..2286fb0 100644
--- a/libgralloc/pmemalloc.cpp
+++ b/libgralloc/pmemalloc.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-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
@@ -126,17 +126,17 @@
ALOGD("%s: Total pmem size: %d", __FUNCTION__, size);
if (err < 0) {
ALOGE("%s: PMEM_GET_TOTAL_SIZE failed (%d), limp mode", mPmemDev,
- err);
+ err);
size = 8<<20; // 8 MiB
}
mAllocator->setSize(size);
void* base = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd,
- 0);
+ 0);
if (base == MAP_FAILED) {
err = -errno;
ALOGE("%s: Failed to map pmem master fd: %s", mPmemDev,
- strerror(errno));
+ strerror(errno));
base = 0;
close(fd);
fd = -1;
@@ -147,7 +147,7 @@
} else {
err = -errno;
ALOGE("%s: Failed to open pmem device: %s", mPmemDev,
- strerror(errno));
+ strerror(errno));
}
return err;
}
@@ -203,13 +203,13 @@
if (err < 0) {
ALOGE("%s: Failed to initialize pmem sub-heap: %d", mPmemDev,
- err);
+ err);
close(fd);
mAllocator->deallocate(offset);
fd = -1;
} else {
ALOGD("%s: Allocated buffer base:%p size:%d offset:%d fd:%d",
- mPmemDev, base, size, offset, fd);
+ mPmemDev, base, size, offset, fd);
memset((char*)base + offset, 0, size);
//Clean cache before flushing to ensure pmem is properly flushed
err = clean_buffer((void*)((intptr_t) base + offset), size, offset, fd);
@@ -230,12 +230,12 @@
int PmemUserspaceAlloc::free_buffer(void* base, size_t size, int offset, int fd)
{
ALOGD("%s: Freeing buffer base:%p size:%d offset:%d fd:%d",
- mPmemDev, base, size, offset, fd);
+ mPmemDev, base, size, offset, fd);
int err = 0;
if (fd >= 0) {
int err = unmapSubRegion(fd, offset, size);
ALOGE_IF(err<0, "PMEM_UNMAP failed (%s), fd=%d, sub.offset=%u, "
- "sub.size=%u", strerror(errno), fd, offset, size);
+ "sub.size=%u", strerror(errno), fd, offset, size);
if (err == 0) {
// we can't deallocate the memory in case of UNMAP failure
// because it would give that process access to someone else's
@@ -252,15 +252,15 @@
int err = 0;
size += offset;
void *base = mmap(0, size, PROT_READ| PROT_WRITE,
- MAP_SHARED, fd, 0);
+ MAP_SHARED, fd, 0);
*pBase = base;
if(base == MAP_FAILED) {
err = -errno;
ALOGE("%s: Failed to map buffer size:%d offset:%d fd:%d Error: %s",
- mPmemDev, size, offset, fd, strerror(errno));
+ mPmemDev, size, offset, fd, strerror(errno));
} else {
ALOGD("%s: Mapped buffer base:%p size:%d offset:%d fd:%d",
- mPmemDev, base, size, offset, fd);
+ mPmemDev, base, size, offset, fd);
}
return err;
@@ -273,16 +273,15 @@
base = (void*)(intptr_t(base) - offset);
size += offset;
ALOGD("%s: Unmapping buffer base:%p size:%d offset:%d",
- mPmemDev , base, size, offset);
+ mPmemDev , base, size, offset);
if (munmap(base, size) < 0) {
-
err = -errno;
ALOGE("%s: Failed to unmap memory at %p :%s",
- mPmemDev, base, strerror(errno));
+ mPmemDev, base, strerror(errno));
}
- return err;
+ return err;
}
int PmemUserspaceAlloc::clean_buffer(void *base, size_t size, int offset, int fd)
@@ -327,7 +326,7 @@
if (base == MAP_FAILED) {
err = -errno;
ALOGE("%s: failed to map pmem fd: %s", mPmemDev,
- strerror(errno));
+ strerror(errno));
close(fd);
return err;
}
@@ -337,7 +336,7 @@
data.offset = 0;
data.fd = fd;
ALOGD("%s: Allocated buffer base:%p size:%d fd:%d",
- mPmemDev, base, size, fd);
+ mPmemDev, base, size, fd);
return 0;
}
@@ -345,7 +344,7 @@
int PmemKernelAlloc::free_buffer(void* base, size_t size, int offset, int fd)
{
ALOGD("%s: Freeing buffer base:%p size:%d fd:%d",
- mPmemDev, base, size, fd);
+ mPmemDev, base, size, fd);
int err = unmap_buffer(base, size, offset);
close(fd);
@@ -356,15 +355,15 @@
{
int err = 0;
void *base = mmap(0, size, PROT_READ| PROT_WRITE,
- MAP_SHARED, fd, 0);
+ MAP_SHARED, fd, 0);
*pBase = base;
if(base == MAP_FAILED) {
err = -errno;
ALOGE("%s: Failed to map memory in the client: %s",
- mPmemDev, strerror(errno));
+ mPmemDev, strerror(errno));
} else {
ALOGD("%s: Mapped buffer base:%p size:%d, fd:%d",
- mPmemDev, base, size, fd);
+ mPmemDev, base, size, fd);
}
return err;
@@ -376,7 +375,7 @@
if (munmap(base, size)) {
err = -errno;
ALOGW("%s: Error unmapping memory at %p: %s",
- mPmemDev, base, strerror(err));
+ mPmemDev, base, strerror(err));
}
return err;
diff --git a/libgralloc/pmemalloc.h b/libgralloc/pmemalloc.h
index 4aed0b1..82794ec 100644
--- a/libgralloc/pmemalloc.h
+++ b/libgralloc/pmemalloc.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-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
@@ -35,72 +35,72 @@
#include "memalloc.h"
namespace gralloc {
- class PmemUserspaceAlloc : public IMemAlloc {
+class PmemUserspaceAlloc : public IMemAlloc {
+ public:
+ class Allocator: public android::RefBase {
public:
- class Allocator: public android::RefBase {
- public:
- virtual ~Allocator() {};
- virtual ssize_t setSize(size_t size) = 0;
- virtual size_t size() const = 0;
- virtual ssize_t allocate(size_t size, uint32_t flags = 0) = 0;
- virtual ssize_t deallocate(size_t offset) = 0;
- };
-
- virtual int alloc_buffer(alloc_data& data);
-
- virtual int free_buffer(void *base, size_t size,
- int offset, int fd);
-
- virtual int map_buffer(void **pBase, size_t size,
- int offset, int fd);
-
- virtual int unmap_buffer(void *base, size_t size,
- int offset);
-
- virtual int clean_buffer(void*base, size_t size,
- int offset, int fd);
-
- PmemUserspaceAlloc();
-
- ~PmemUserspaceAlloc();
-
- private:
- int mMasterFd;
- void* mMasterBase;
- const char* mPmemDev;
- android::sp<Allocator> mAllocator;
- pthread_mutex_t mLock;
- int init_pmem_area();
- int init_pmem_area_locked();
-
+ virtual ~Allocator() {};
+ virtual ssize_t setSize(size_t size) = 0;
+ virtual size_t size() const = 0;
+ virtual ssize_t allocate(size_t size, uint32_t flags = 0) = 0;
+ virtual ssize_t deallocate(size_t offset) = 0;
};
- class PmemKernelAlloc : public IMemAlloc {
+ virtual int alloc_buffer(alloc_data& data);
- public:
- virtual int alloc_buffer(alloc_data& data);
+ virtual int free_buffer(void *base, size_t size,
+ int offset, int fd);
- virtual int free_buffer(void *base, size_t size,
- int offset, int fd);
+ virtual int map_buffer(void **pBase, size_t size,
+ int offset, int fd);
- virtual int map_buffer(void **pBase, size_t size,
- int offset, int fd);
+ virtual int unmap_buffer(void *base, size_t size,
+ int offset);
- virtual int unmap_buffer(void *base, size_t size,
- int offset);
+ virtual int clean_buffer(void*base, size_t size,
+ int offset, int fd);
- virtual int clean_buffer(void*base, size_t size,
- int offset, int fd);
+ PmemUserspaceAlloc();
- PmemKernelAlloc(const char* device);
+ ~PmemUserspaceAlloc();
- ~PmemKernelAlloc();
- private:
- const char* mPmemDev;
+ private:
+ int mMasterFd;
+ void* mMasterBase;
+ const char* mPmemDev;
+ android::sp<Allocator> mAllocator;
+ pthread_mutex_t mLock;
+ int init_pmem_area();
+ int init_pmem_area_locked();
+
+};
+
+class PmemKernelAlloc : public IMemAlloc {
+
+ public:
+ virtual int alloc_buffer(alloc_data& data);
+
+ virtual int free_buffer(void *base, size_t size,
+ int offset, int fd);
+
+ virtual int map_buffer(void **pBase, size_t size,
+ int offset, int fd);
+
+ virtual int unmap_buffer(void *base, size_t size,
+ int offset);
+
+ virtual int clean_buffer(void*base, size_t size,
+ int offset, int fd);
+
+ PmemKernelAlloc(const char* device);
+
+ ~PmemKernelAlloc();
+ private:
+ const char* mPmemDev;
- };
+};
}
#endif /* GRALLOC_PMEMALLOC_H */
diff --git a/libhwcomposer/Android.mk b/libhwcomposer/Android.mk
index a600f97..7cb5c6f 100644
--- a/libhwcomposer/Android.mk
+++ b/libhwcomposer/Android.mk
@@ -1,39 +1,18 @@
LOCAL_PATH := $(call my-dir)
-
-# HAL module implemenation, not prelinked and stored in
-# hw/<OVERLAY_HARDWARE_MODULE_ID>.<ro.product.board>.so
include $(CLEAR_VARS)
LOCAL_PRELINK_MODULE := false
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
-LOCAL_SHARED_LIBRARIES := liblog libcutils libEGL libhardware libutils liboverlay
-LOCAL_SHARED_LIBRARIES += libgenlock libQcomUI libmemalloc
-
-LOCAL_SRC_FILES := \
- hwcomposer.cpp \
- external_display_only.h
-
+LOCAL_SHARED_LIBRARIES := liblog libcutils libhardware libutils
+LOCAL_SHARED_LIBRARIES += libEGL liboverlay libgenlock
+LOCAL_SRC_FILES := hwc.cpp \
+ hwc_overlay.cpp \
+ hwc_utils.cpp
LOCAL_MODULE := hwcomposer.$(TARGET_BOARD_PLATFORM)
-LOCAL_CFLAGS:= -DLOG_TAG=\"$(TARGET_BOARD_PLATFORM).hwcomposer\" -DDEBUG_CALC_FPS
-
-LOCAL_C_INCLUDES += hardware/qcom/display/libgralloc
-LOCAL_C_INCLUDES += hardware/qcom/display/liboverlay
-LOCAL_C_INCLUDES += hardware/qcom/display/libcopybit
+LOCAL_C_INCLUDES := hardware/qcom/display/libgralloc
LOCAL_C_INCLUDES += hardware/qcom/display/libgenlock
+LOCAL_C_INCLUDES += hardware/qcom/display/liboverlay
LOCAL_C_INCLUDES += hardware/qcom/display/libqcomui
-LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
+LOCAL_CFLAGS:= -DLOG_TAG=\"$(TARGET_BOARD_PLATFORM).hwcomposer\"
-LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
-ifeq ($(TARGET_HAVE_HDMI_OUT),true)
-LOCAL_CFLAGS += -DHDMI_DUAL_DISPLAY
-endif
-ifeq ($(TARGET_USES_OVERLAY),true)
-LOCAL_CFLAGS += -DUSE_OVERLAY
-endif
-ifeq ($(TARGET_HAVE_BYPASS),true)
-LOCAL_CFLAGS += -DCOMPOSITION_BYPASS
-endif
-ifeq ($(TARGET_USE_HDMI_AS_PRIMARY),true)
-LOCAL_CFLAGS += -DHDMI_AS_PRIMARY
-endif
-LOCAL_MODULE_TAGS := optional eng
+LOCAL_MODULE_TAGS := optional
include $(BUILD_SHARED_LIBRARY)
diff --git a/libhwcomposer/external_display_only.h b/libhwcomposer/external_display_only.h
deleted file mode 100644
index fa24642..0000000
--- a/libhwcomposer/external_display_only.h
+++ /dev/null
@@ -1,498 +0,0 @@
-/*
- * Copyright (c) 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.
- */
-
-#define EXTDEBUG 0
-class ExtDispOnly {
-
- enum ExternalOnlyMode {
- EXT_ONLY_MODE_OFF = 0,
- EXT_ONLY_MODE_ON = 1,
- };
-
- enum {
- MAX_EXT_ONLY_LAYERS = 2,
- };
-
-public:
- /* Initialize, allocate data members */
- static void init();
-
- /* Deallocate data members */
- static void destroy();
-
- /* Closes all the overlay channels */
- static void close();
-
- /* Prepare overlay and configures mdp pipes */
- static int prepare(hwc_context_t *ctx, hwc_layer_t *layer, int index,
- bool waitForVsync);
-
- /* Returns status of external-only mode */
- static bool isModeOn();
-
- /* Updates stats and pipe config related to external_only and external_block layers
- * If we are staring or stopping this mode, update default mirroring.
- */
- static int update(hwc_context_t* ctx, hwc_layer_list_t* list);
-
- /* Stores the locked handle for the buffer that was successfully queued */
- static void storeLockedHandles(hwc_layer_list_t* list);
-
- /* Queue buffers to mdp for display */
- static int draw(hwc_context_t *ctx, hwc_layer_list_t *list);
-
-private:
- /* Locks a buffer and marks it as locked */
- static void lockBuffer(native_handle_t *hnd);
-
- /* Unlocks a buffer and clears the locked flag */
- static void unlockBuffer(native_handle_t *hnd);
-
- /* Unlocks buffers queued in previous round (and displayed by now)
- * Clears the handle cache.
- */
- static void unlockPreviousBuffers();
-
- /* Closes the a range of overlay channels */
- static void closeRange(int start);
-
- /* Start default external mirroring */
- static void startDefaultMirror(hwc_context_t* ctx);
-
- /* Stop default external mirroring */
- static void stopDefaultMirror(hwc_context_t* ctx);
-
- /* Checks if external-only mode is starting */
- static bool isExtModeStarting(hwc_context_t* ctx, const int&
- numExtLayers);
-
- /* Checks if external-only mode is stopping */
- static bool isExtModeStopping(hwc_context_t* ctx, const int&
- numExtLayers);
-
- //Data members
-#if defined (HDMI_DUAL_DISPLAY) && defined (USE_OVERLAY)
- static overlay::OverlayUI* sOvExtUI[MAX_EXT_ONLY_LAYERS];
- static native_handle_t* sPreviousExtHandle[MAX_EXT_ONLY_LAYERS];
- static ExternalOnlyMode sExtOnlyMode;
- static int sNumExtOnlyLayers;
- static bool sSkipLayerPresent;
- static bool sBlockLayerPresent;
- static int sBlockLayerIndex;
-#endif
-}; //class ExtDispOnly
-
-void ExtDispOnly::lockBuffer(native_handle_t *hnd) {
-#if defined (HDMI_DUAL_DISPLAY) && defined (USE_OVERLAY)
- private_handle_t* phnd = (private_handle_t*)hnd;
-
- //Genlock is reference counted and recursive.
- //Do not accidently lock a locked buffer.
- if(phnd && (phnd->flags & private_handle_t::PRIV_FLAGS_HWC_LOCK)) {
- LOGE_IF(EXTDEBUG, "%s: handle %p already locked", __func__, phnd);
- return;
- }
- if (GENLOCK_FAILURE == genlock_lock_buffer(hnd, GENLOCK_READ_LOCK,
- GENLOCK_MAX_TIMEOUT)) {
- LOGE("%s: genlock_lock_buffer(READ) failed", __func__);
- return;
- }
- phnd->flags |= private_handle_t::PRIV_FLAGS_HWC_LOCK;
- LOGE_IF(EXTDEBUG, "%s: locked handle = %p", __func__, hnd);
-#endif
-}
-
-void ExtDispOnly::unlockBuffer(native_handle_t *hnd) {
-#if defined (HDMI_DUAL_DISPLAY) && defined (USE_OVERLAY)
- //Check if buffer is still around
- if(private_handle_t::validate(hnd) != 0) {
- LOGE("%s Handle already deallocated", __func__);
- return;
- }
-
- private_handle_t* phnd = (private_handle_t*)hnd;
-
- //Check if buffer was locked in the first place
- if((phnd->flags & private_handle_t::PRIV_FLAGS_HWC_LOCK) == 0) {
- LOGE("%s Handle not locked, cannot unlock", __func__);
- return;
- }
-
- //Actually try to unlock
- if (GENLOCK_FAILURE == genlock_unlock_buffer(hnd)) {
- LOGE("%s: genlock_unlock_buffer failed", __func__);
- return;
- }
-
- //Clear the locked flag
- phnd->flags &= ~private_handle_t::PRIV_FLAGS_HWC_LOCK;
- LOGE_IF(EXTDEBUG, "%s: unlocked handle = %p", __func__, hnd);
-#endif
-}
-
-void ExtDispOnly::unlockPreviousBuffers() {
-#if defined (HDMI_DUAL_DISPLAY) && defined (USE_OVERLAY)
- for(int i = 0; (i < MAX_EXT_ONLY_LAYERS) && sPreviousExtHandle[i]; i++) {
- LOGE_IF(EXTDEBUG, "%s", __func__);
- ExtDispOnly::unlockBuffer(sPreviousExtHandle[i]);
- sPreviousExtHandle[i] = NULL;
- }
-#endif
-}
-
-void ExtDispOnly::init() {
-#if defined (HDMI_DUAL_DISPLAY) && defined (USE_OVERLAY)
- for(int i = 0; i < MAX_EXT_ONLY_LAYERS; i++) {
- sOvExtUI[i] = new overlay::OverlayUI();
- sPreviousExtHandle[i] = NULL;
- }
- sExtOnlyMode = EXT_ONLY_MODE_OFF;
- sNumExtOnlyLayers = 0;
- sSkipLayerPresent = false;
- sBlockLayerPresent = false;
- sBlockLayerIndex = -1;
- LOGE_IF(EXTDEBUG, "%s", __func__);
-#endif
-}
-
-void ExtDispOnly::destroy() {
-#if defined (HDMI_DUAL_DISPLAY) && defined (USE_OVERLAY)
- for(int i = 0; i < MAX_EXT_ONLY_LAYERS; i++) {
- delete sOvExtUI[i];
- }
-#endif
-}
-
-void ExtDispOnly::closeRange(int start) {
-#if defined (HDMI_DUAL_DISPLAY) && defined (USE_OVERLAY)
- for (int index = start; index < MAX_EXT_ONLY_LAYERS; index++) {
- if(sPreviousExtHandle[index]) {
- LOGE_IF(EXTDEBUG, "%s", __func__);
- ExtDispOnly::unlockBuffer(sPreviousExtHandle[index]);
- sPreviousExtHandle[index] = NULL;
- }
- sOvExtUI[index]->closeChannel();
- }
-#endif
-}
-
-void inline ExtDispOnly::close() {
-#if defined (HDMI_DUAL_DISPLAY) && defined (USE_OVERLAY)
- closeRange(0);
-#endif
-}
-
-int ExtDispOnly::prepare(hwc_context_t *ctx, hwc_layer_t *layer, int index,
- bool waitForVsync) {
-#if defined (HDMI_DUAL_DISPLAY) && defined (USE_OVERLAY)
- if(ctx->mHDMIEnabled == EXT_DISPLAY_OFF ||
- ctx->pendingHDMI == true)
- return -1;
-
- if (ctx && sOvExtUI[index]) {
- private_hwc_module_t* hwcModule = reinterpret_cast<
- private_hwc_module_t*>(ctx->device.common.module);
- if (!hwcModule) {
- LOGE("%s null module", __func__);
- return -1;
- }
- private_handle_t *hnd = (private_handle_t *)layer->handle;
- if(!hnd) {
- LOGE("%s handle null", __func__);
- return -1;
- }
- overlay::OverlayUI *ovUI = sOvExtUI[index];
- int ret = 0;
- //int orientation = layer->transform;
- //Assuming layers will always be source landscape
- const int orientation = 0;
- overlay_buffer_info info;
- hwc_rect_t sourceCrop = layer->sourceCrop;
- info.width = sourceCrop.right - sourceCrop.left;
- info.height = sourceCrop.bottom - sourceCrop.top;
- info.format = hnd->format;
- info.size = hnd->size;
-
-
- const int fbnum = ctx->mHDMIEnabled; //HDMI or WFD
- const bool isFg = false;
- //Just to differentiate zorders for different layers
- const int zorder = index;
- const bool isVGPipe = true;
- ovUI->setSource(info, orientation);
- ovUI->setDisplayParams(fbnum, waitForVsync, isFg, zorder, isVGPipe);
- const int fbWidth = ovUI->getFBWidth();
- const int fbHeight = ovUI->getFBHeight();
- ovUI->setPosition(0, 0, fbWidth, fbHeight);
- if(ovUI->commit() != overlay::NO_ERROR) {
- LOGE("%s: Overlay Commit failed", __func__);
- return -1;
- }
- }
- LOGE_IF(EXTDEBUG, "%s", __func__);
-#endif
- return overlay::NO_ERROR;
-}
-
-inline void ExtDispOnly::startDefaultMirror(hwc_context_t* ctx) {
-#if defined (HDMI_DUAL_DISPLAY) && defined (USE_OVERLAY)
- hwc_composer_device_t* dev = (hwc_composer_device_t*) ctx;
- private_hwc_module_t* hwcModule =
- reinterpret_cast<private_hwc_module_t*>(dev->common.module);
- framebuffer_device_t *fbDev = hwcModule->fbDevice;
- if (fbDev) {
- //mHDMIEnabled could be HDMI/WFD/NO EXTERNAL
- fbDev->enableHDMIOutput(fbDev, ctx->mHDMIEnabled);
- }
-#endif
-}
-
-inline void ExtDispOnly::stopDefaultMirror(hwc_context_t* ctx) {
-#if defined (HDMI_DUAL_DISPLAY) && defined (USE_OVERLAY)
- hwc_composer_device_t* dev = (hwc_composer_device_t*) ctx;
- private_hwc_module_t* hwcModule =
- reinterpret_cast<private_hwc_module_t*>(dev->common.module);
- framebuffer_device_t *fbDev = hwcModule->fbDevice;
- if (fbDev) {
- fbDev->enableHDMIOutput(fbDev, EXT_DISPLAY_OFF);
- }
-#endif
-}
-
-inline bool ExtDispOnly::isExtModeStarting(hwc_context_t* ctx, const int&
- numExtLayers) {
-#if defined (HDMI_DUAL_DISPLAY) && defined (USE_OVERLAY)
- return ((sExtOnlyMode == EXT_ONLY_MODE_OFF) && numExtLayers);
-#endif
- return false;
-}
-
-inline bool ExtDispOnly::isExtModeStopping(hwc_context_t* ctx, const int&
- numExtLayers) {
-#if defined (HDMI_DUAL_DISPLAY) && defined (USE_OVERLAY)
- return ((sExtOnlyMode == EXT_ONLY_MODE_ON) && (numExtLayers == 0));
-#endif
- return false;
-}
-
-inline bool ExtDispOnly::isModeOn() {
-#if defined (HDMI_DUAL_DISPLAY) && defined (USE_OVERLAY)
- return (sExtOnlyMode == EXT_ONLY_MODE_ON);
-#endif
- return false;
-}
-
-int ExtDispOnly::update(hwc_context_t* ctx, hwc_layer_list_t* list) {
-#if defined (HDMI_DUAL_DISPLAY) && defined (USE_OVERLAY)
- int aNumExtLayers = 0;
- bool aSkipLayerPresent = false;
- bool aBlockLayerPresent = false;
- int aBlockLayerIndex = -1;
-
- //Book-keeping done each cycle
- for (size_t i = 0; i < list->numHwLayers; i++) {
- private_handle_t *hnd = (private_handle_t *)list->hwLayers[i].handle;
- // Dont draw in this round
- if(list->hwLayers[i].flags & HWC_SKIP_LAYER) {
- aSkipLayerPresent = true;
- }
- if(hnd && (hnd->flags & private_handle_t::PRIV_FLAGS_EXTERNAL_ONLY)) {
- aNumExtLayers++;
- // No way we can let this be drawn by GPU to fb0
- if(list->hwLayers[i].flags & HWC_SKIP_LAYER) {
- list->hwLayers[i].flags &= ~ HWC_SKIP_LAYER;
- }
- list->hwLayers[i].flags |= HWC_USE_EXT_ONLY;
- list->hwLayers[i].compositionType = HWC_USE_OVERLAY;
- list->hwLayers[i].hints &= ~HWC_HINT_CLEAR_FB;
- //EXTERNAL_BLOCK is always an add-on
- if(hnd && (hnd->flags &
- private_handle_t::PRIV_FLAGS_EXTERNAL_BLOCK)) {
- aBlockLayerPresent = true;
- aBlockLayerIndex = i;
- list->hwLayers[i].flags |= HWC_USE_EXT_BLOCK;
- }
- }
- }
-
- //Update Default mirroring state
- if (isExtModeStarting(ctx, aNumExtLayers)) {
- stopDefaultMirror(ctx);
- } else if (isExtModeStopping(ctx, aNumExtLayers)) {
- startDefaultMirror(ctx);
- }
-
- //Cache our stats
- sExtOnlyMode = aNumExtLayers ? EXT_ONLY_MODE_ON : EXT_ONLY_MODE_OFF;
- sNumExtOnlyLayers = aNumExtLayers;
- sSkipLayerPresent = aSkipLayerPresent;
- sBlockLayerPresent = aBlockLayerPresent;
- sBlockLayerIndex = aBlockLayerIndex;
-
- LOGE_IF(EXTDEBUG, "%s: numExtLayers = %d skipLayerPresent = %d", __func__,
- aNumExtLayers, aSkipLayerPresent);
- //If skip layer present return. Buffers to be unlocked in draw phase.
- if(aSkipLayerPresent) {
- return overlay::NO_ERROR;
- }
-
- //If External is not connected, dont setup pipes, just return
- if(ctx->mHDMIEnabled == EXT_DISPLAY_OFF ||
- ctx->pendingHDMI == true) {
- ExtDispOnly::close();
- return -1;
- }
-
-
- //Update pipes
- bool waitForVsync = true;
- bool index = 0;
-
- if (aBlockLayerPresent) {
- ExtDispOnly::closeRange(1);
- ExtDispOnly::prepare(ctx, &(list->hwLayers[aBlockLayerIndex]),
- index, waitForVsync);
- } else if (aNumExtLayers) {
- ExtDispOnly::closeRange(aNumExtLayers);
- for (size_t i = 0; i < list->numHwLayers; i++) {
- private_handle_t *hnd = (private_handle_t *)list->hwLayers[i].handle;
- if(hnd && hnd->flags & private_handle_t::PRIV_FLAGS_EXTERNAL_ONLY) {
- waitForVsync = (index == (aNumExtLayers - 1));
- ExtDispOnly::prepare(ctx, &(list->hwLayers[i]),
- index, waitForVsync);
- index++;
- }
- }
- } else {
- ExtDispOnly::close();
- }
-#endif
- return overlay::NO_ERROR;
-}
-
-void ExtDispOnly::storeLockedHandles(hwc_layer_list_t* list) {
-#if defined (HDMI_DUAL_DISPLAY) && defined (USE_OVERLAY)
- int index = 0;
- if(sBlockLayerPresent) {
- private_handle_t *hnd = (private_handle_t *)
- list->hwLayers[sBlockLayerIndex].handle;
- if(list->hwLayers[sBlockLayerIndex].flags & HWC_USE_EXT_ONLY) {
- if(!(hnd->flags & private_handle_t::PRIV_FLAGS_HWC_LOCK)) {
- ExtDispOnly::lockBuffer(hnd);
- }
- sPreviousExtHandle[index] = hnd;
- LOGE_IF(EXTDEBUG, "%s BLOCK: handle = %p", __func__, hnd);
- return;
- }
- }
- for(int i = 0; i < list->numHwLayers; i++) {
- private_handle_t *hnd = (private_handle_t *)list->hwLayers[i].handle;
- if(list->hwLayers[i].flags & HWC_USE_EXT_ONLY) {
- if(!(hnd->flags & private_handle_t::PRIV_FLAGS_HWC_LOCK)) {
- ExtDispOnly::lockBuffer(hnd);
- }
- sPreviousExtHandle[index] = hnd;
- index++;
- LOGE_IF(EXTDEBUG, "%s: handle = %p", __func__, hnd);
- }
- }
-#endif
-}
-
-int ExtDispOnly::draw(hwc_context_t *ctx, hwc_layer_list_t *list) {
-#if defined (HDMI_DUAL_DISPLAY) && defined (USE_OVERLAY)
- LOGE_IF(EXTDEBUG, "%s", __func__);
- if(ctx->mHDMIEnabled == EXT_DISPLAY_OFF ||
- ctx->pendingHDMI == true) {
- ExtDispOnly::close();
- return -1;
- }
-
- int ret = overlay::NO_ERROR;
- int index = 0;
-
- //If skip layer present or list invalid unlock and return.
- if(sSkipLayerPresent || list == NULL) {
- ExtDispOnly::unlockPreviousBuffers();
- return overlay::NO_ERROR;
- }
-
- if(sBlockLayerPresent) {
- private_handle_t *hnd = (private_handle_t*)
- list->hwLayers[sBlockLayerIndex].handle;
- ExtDispOnly::lockBuffer(hnd);
- ret = sOvExtUI[index]->queueBuffer(hnd);
- if (ret) {
- LOGE("%s queueBuffer failed", __func__);
- // Unlock the locked buffer
- ExtDispOnly::unlockBuffer(hnd);
- ExtDispOnly::close();
- return -1;
- }
- ExtDispOnly::unlockPreviousBuffers();
- ExtDispOnly::storeLockedHandles(list);
- return overlay::NO_ERROR;
- }
-
- for(int i = 0; i < list->numHwLayers; i++) {
- private_handle_t *hnd = (private_handle_t *)list->hwLayers[i].handle;
- if(hnd && list->hwLayers[i].flags & HWC_USE_EXT_ONLY) {
- overlay::OverlayUI *ovUI = sOvExtUI[index];
- ExtDispOnly::lockBuffer(hnd);
- ret = ovUI->queueBuffer(hnd);
- if (ret) {
- LOGE("%s queueBuffer failed", __func__);
- // Unlock the all the currently locked buffers
- for (int j = 0; j <= i; j++) {
- private_handle_t *tmphnd =
- (private_handle_t *)list->hwLayers[j].handle;
- if(hnd && list->hwLayers[j].flags & HWC_USE_EXT_ONLY)
- ExtDispOnly::unlockBuffer(tmphnd);
- }
- ExtDispOnly::close();
- return -1;
- }
- index++;
- }
- }
- ExtDispOnly::unlockPreviousBuffers();
- ExtDispOnly::storeLockedHandles(list);
-#endif
- return overlay::NO_ERROR;
-}
-
-#if defined (HDMI_DUAL_DISPLAY) && defined (USE_OVERLAY)
-overlay::OverlayUI* ExtDispOnly::sOvExtUI[MAX_EXT_ONLY_LAYERS];
-native_handle_t* ExtDispOnly::sPreviousExtHandle[MAX_EXT_ONLY_LAYERS];
-ExtDispOnly::ExternalOnlyMode ExtDispOnly::sExtOnlyMode;
-int ExtDispOnly::sNumExtOnlyLayers;
-bool ExtDispOnly::sSkipLayerPresent;
-bool ExtDispOnly::sBlockLayerPresent;
-int ExtDispOnly::sBlockLayerIndex;
-#endif
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
new file mode 100644
index 0000000..afd2aa9
--- /dev/null
+++ b/libhwcomposer/hwc.cpp
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * Copyright (C) 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.
+ */
+
+#include <fcntl.h>
+#include <errno.h>
+
+#include <cutils/log.h>
+#include <cutils/atomic.h>
+#include <EGL/egl.h>
+
+#include "hwc_utils.h"
+
+using namespace qhwc;
+
+static int hwc_device_open(const struct hw_module_t* module,
+ const char* name,
+ struct hw_device_t** device);
+
+static struct hw_module_methods_t hwc_module_methods = {
+ open: hwc_device_open
+};
+
+hwc_module_t HAL_MODULE_INFO_SYM = {
+ common: {
+ tag: HARDWARE_MODULE_TAG,
+ version_major: 2,
+ version_minor: 0,
+ id: HWC_HARDWARE_MODULE_ID,
+ name: "Qualcomm Hardware Composer Module",
+ author: "CodeAurora Forum",
+ methods: &hwc_module_methods,
+ dso: 0,
+ reserved: {0},
+ }
+};
+
+/*
+ * Save callback functions registered to HWC
+ */
+static void hwc_registerProcs(struct hwc_composer_device* dev,
+ hwc_procs_t const* procs)
+{
+ hwc_context_t* ctx = (hwc_context_t*)(dev);
+ if(!ctx) {
+ ALOGE("%s: Invalid context", __FUNCTION__);
+ return;
+ }
+ ctx->device.reserved_proc[0] = (void*)procs;
+}
+
+static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list)
+{
+ hwc_context_t* ctx = (hwc_context_t*)(dev);
+ if (LIKELY(list)) {
+ getLayerStats(ctx, list);
+ cleanOverlays(ctx);
+ for (int i=list->numHwLayers-1; i >= 0 ; i--) {
+ private_handle_t *hnd =
+ (private_handle_t *)list->hwLayers[i].handle;
+ if (isSkipLayer(&list->hwLayers[i])) {
+ break;
+ } else if(isYuvBuffer(hnd)) {
+ handleYUV(ctx,&list->hwLayers[i]);
+ } else {
+ list->hwLayers[i].compositionType = HWC_FRAMEBUFFER;
+ }
+ }
+ }
+ return 0;
+}
+
+static int hwc_set(hwc_composer_device_t *dev,
+ hwc_display_t dpy,
+ hwc_surface_t sur,
+ hwc_layer_list_t* list)
+{
+ int ret = 0;
+ hwc_context_t* ctx = (hwc_context_t*)(dev);
+ if (LIKELY(list)) {
+ for (size_t i=0; i<list->numHwLayers; i++) {
+ if (list->hwLayers[i].flags & HWC_SKIP_LAYER) {
+ continue;
+ } else if (list->hwLayers[i].compositionType == HWC_USE_OVERLAY) {
+ drawLayerUsingOverlay(ctx, &(list->hwLayers[i]));
+ }
+ }
+ //XXX: Handle vsync with FBIO_WAITFORVSYNC ioctl
+ //All other operations (including pan display) should be NOWAIT
+ EGLBoolean sucess = eglSwapBuffers((EGLDisplay)dpy, (EGLSurface)sur);
+ } else {
+ //XXX: put in a wrapper for non overlay targets
+ setOverlayState(ctx, ovutils::OV_CLOSED);
+ }
+ ctx->qbuf->unlockAllPrevious();
+ return ret;
+}
+
+static int hwc_device_close(struct hw_device_t *dev)
+{
+ if(!dev) {
+ ALOGE("hwc_device_close null device pointer");
+ return -1;
+ }
+ closeContext((hwc_context_t*)dev);
+ free(dev);
+
+ return 0;
+}
+
+static int hwc_device_open(const struct hw_module_t* module, const char* name,
+ struct hw_device_t** device)
+{
+ int status = -EINVAL;
+
+ if (!strcmp(name, HWC_HARDWARE_COMPOSER)) {
+ struct hwc_context_t *dev;
+ dev = (hwc_context_t*)malloc(sizeof(*dev));
+ memset(dev, 0, sizeof(*dev));
+ initContext(dev);
+ dev->device.common.tag = HARDWARE_DEVICE_TAG;
+ dev->device.common.version = 0;
+ dev->device.common.module = const_cast<hw_module_t*>(module);
+ dev->device.common.close = hwc_device_close;
+ dev->device.prepare = hwc_prepare;
+ dev->device.set = hwc_set;
+ dev->device.registerProcs = hwc_registerProcs;
+ *device = &dev->device.common;
+ status = 0;
+ }
+ return status;
+}
diff --git a/libhwcomposer/hwc_overlay.cpp b/libhwcomposer/hwc_overlay.cpp
new file mode 100644
index 0000000..00f53e9
--- /dev/null
+++ b/libhwcomposer/hwc_overlay.cpp
@@ -0,0 +1,294 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * Copyright (C) 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.
+ */
+
+#include "hwc_utils.h"
+
+namespace qhwc {
+// Determine overlay state based on decoded video info
+static ovutils::eOverlayState determineOverlayState(hwc_context_t* ctx,
+ uint32_t bypassLayer,
+ uint32_t format)
+{
+ ovutils::eOverlayState state = ovutils::OV_CLOSED;
+
+ // Sanity check
+ if (!ctx) {
+ ALOGE("%s: NULL ctx", __FUNCTION__);
+ return state;
+ }
+
+ overlay::Overlay& ov = *(ctx->mOverlay);
+ state = ov.getState();
+
+ // If there are any bypassLayers, state is based on number of layers
+ if ((bypassLayer > 0) && (ctx->hdmiEnabled == EXT_TYPE_NONE)) {
+ if (bypassLayer == 1) {
+ state = ovutils::OV_BYPASS_1_LAYER;
+ } else if (bypassLayer == 2) {
+ state = ovutils::OV_BYPASS_2_LAYER;
+ } else if (bypassLayer == 3) {
+ state = ovutils::OV_BYPASS_3_LAYER;
+ }
+ return state;
+ }
+
+ // RGB is ambiguous for determining overlay state
+ if (ovutils::isRgb(ovutils::getMdpFormat(format))) {
+ return state;
+ }
+
+ // Content type is either 2D or 3D
+ uint32_t fmt3D = 0;//XXX: 3D - ovutils::getS3DFormat(format);
+
+ // Determine state based on the external display, content type, and hw type
+ if (ctx->hdmiEnabled == EXT_TYPE_HDMI) {
+ // External display is HDMI
+ if (fmt3D) {
+ // Content type is 3D
+ if (ovutils::is3DTV()) {
+ // TV panel type is 3D
+ state = ovutils::OV_3D_VIDEO_ON_3D_TV;
+ } else {
+ // TV panel type is 2D
+ state = ovutils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV;
+ }
+ } else {
+ // Content type is 2D
+ if (ovutils::FrameBufferInfo::getInstance()->supportTrueMirroring()) {
+ // True UI mirroring is supported
+ state = ovutils::OV_2D_TRUE_UI_MIRROR;
+ } else {
+ // True UI mirroring is not supported
+ state = ovutils::OV_2D_VIDEO_ON_PANEL_TV;
+ }
+ }
+ } else if (ctx->hdmiEnabled == EXT_TYPE_WIFI) {
+ // External display is Wifi (currently unsupported)
+ ALOGE("%s: WIFI external display is unsupported", __FUNCTION__);
+ return state;
+ } else {
+ // No external display (primary panel only)
+ if (fmt3D) {
+ // Content type is 3D
+ if (ovutils::usePanel3D()) {
+ // Primary panel type is 3D
+ state = ovutils::OV_3D_VIDEO_ON_3D_PANEL;
+ } else {
+ // Primary panel type is 2D
+ state = ovutils::OV_3D_VIDEO_ON_2D_PANEL;
+ }
+ } else {
+ // Content type is 2D
+ state = ovutils::OV_2D_VIDEO_ON_PANEL;
+ }
+ }
+
+ return state;
+}
+
+void setOverlayState(hwc_context_t *ctx, ovutils::eOverlayState state)
+{
+ if (!ctx) {
+ ALOGE("%s: NULL ctx", __FUNCTION__);
+ return;
+ }
+
+ overlay::Overlay *ov = ctx->mOverlay;
+ if (!ov) {
+ ALOGE("%s: NULL OV object", __FUNCTION__);
+ return;
+ }
+ ov->setState(state);
+}
+
+bool prepareOverlay(hwc_context_t *ctx, hwc_layer_t *layer)
+{
+ bool ret = false;
+ if (LIKELY(ctx->mOverlay)) {
+ private_handle_t *hnd = (private_handle_t *)layer->handle;
+ overlay::Overlay& ov = *(ctx->mOverlay);
+ ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size);
+
+ // Set overlay state
+ ovutils::eOverlayState state = determineOverlayState(ctx, 0, info.format);
+ setOverlayState(ctx, state);
+
+ ovutils::eDest dest = ovutils::OV_PIPE_ALL;
+
+ // In the true UI mirroring case, video needs to go to OV_PIPE0 (for
+ // primary) and OV_PIPE1 (for external)
+ if (state == ovutils::OV_2D_TRUE_UI_MIRROR) {
+ dest = static_cast<ovutils::eDest>(
+ ovutils::OV_PIPE0 | ovutils::OV_PIPE1);
+ }
+
+ // Order order order
+ // setSource - just setting source
+ // setParameter - changes src w/h/f accordingly
+ // setCrop - ROI - that is src_rect
+ // setPosition - need to do scaling
+ // commit - commit changes to mdp driver
+ // queueBuffer - not here, happens when draw is called
+
+ ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
+ if (hnd->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) {
+ ovutils::setMdpFlags(mdpFlags,
+ ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
+ }
+
+ // FIXME: Use source orientation for TV when source is portrait
+ int transform = layer->transform & FINAL_TRANSFORM_MASK;
+ ovutils::eTransform orient =
+ static_cast<ovutils::eTransform>(transform);
+
+ ovutils::eWait waitFlag = ovutils::NO_WAIT;
+ if (ctx->skipComposition == true) {
+ waitFlag = ovutils::WAIT;
+ }
+
+ ovutils::eIsFg isFgFlag = ovutils::IS_FG_OFF;
+ if (ctx->numHwLayers == 1) {
+ isFgFlag = ovutils::IS_FG_SET;
+ }
+
+ ovutils::PipeArgs parg(mdpFlags,
+ orient,
+ info,
+ waitFlag,
+ ovutils::ZORDER_0,
+ isFgFlag,
+ ovutils::ROT_FLAG_DISABLED);
+ ovutils::PipeArgs pargs[ovutils::MAX_PIPES] = { parg, parg, parg };
+ ret = ov.setSource(pargs, dest);
+ if (!ret) {
+ ALOGE("%s: setSource failed", __FUNCTION__);
+ return ret;
+ }
+
+ const ovutils::Params prms (ovutils::OVERLAY_TRANSFORM, orient);
+ ret = ov.setParameter(prms, dest);
+ if (!ret) {
+ ALOGE("%s: setParameter failed transform %x", __FUNCTION__, orient);
+ return ret;
+ }
+
+ hwc_rect_t sourceCrop = layer->sourceCrop;
+ // x,y,w,h
+ ovutils::Dim dcrop(sourceCrop.left, sourceCrop.top, // x, y
+ sourceCrop.right - sourceCrop.left, // w
+ sourceCrop.bottom - sourceCrop.top);// h
+ ret = ov.setCrop(dcrop, dest);
+ if (!ret) {
+ ALOGE("%s: setCrop failed", __FUNCTION__);
+ return ret;
+ }
+
+ int orientation = 0;
+ ovutils::Dim dim;
+ hwc_rect_t displayFrame = layer->displayFrame;
+ dim.x = displayFrame.left;
+ dim.y = displayFrame.top;
+ dim.w = (displayFrame.right - displayFrame.left);
+ dim.h = (displayFrame.bottom - displayFrame.top);
+ dim.o = orientation;
+
+ ret = ov.setPosition(dim, dest);
+ if (!ret) {
+ ALOGE("%s: setPosition failed", __FUNCTION__);
+ return ret;
+ }
+ if (!ov.commit(dest)) {
+ ALOGE("%s: commit fails", __FUNCTION__);
+ return false;
+ }
+ }
+ return true;
+}
+
+bool drawLayerUsingOverlay(hwc_context_t *ctx, hwc_layer_t *layer)
+{
+ private_handle_t *hnd = (private_handle_t *)layer->handle;
+
+ // Lock this buffer for read.
+ ctx->qbuf->lockAndAdd(hnd);
+ bool ret = true;
+ overlay::Overlay& ov = *(ctx->mOverlay);
+ ovutils::eOverlayState state = ov.getState();
+
+ // Differentiate between states that need to wait for vsync
+ switch (state) {
+ case ovutils::OV_2D_VIDEO_ON_PANEL_TV:
+ case ovutils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV:
+ case ovutils::OV_2D_TRUE_UI_MIRROR:
+ // If displaying on both primary and external, must play each
+ // pipe individually since wait for vsync needs to be done at
+ // the end. Do the following:
+ // - Play external
+ // - Play primary
+ // - Wait for external vsync to be done
+ // NOTE: In these states
+ // - primary VG = OV_PIPE0
+ // - external VG = OV_PIPE1
+ // - external RGB = OV_PIPE2
+ // - Only in true UI mirroring case, played by fb
+
+ // Same FD for both primary and external VG pipes
+ ov.setMemoryId(hnd->fd, static_cast<ovutils::eDest>(
+ ovutils::OV_PIPE0 | ovutils::OV_PIPE1));
+
+ // Play external
+ if (!ov.queueBuffer(hnd->offset, ovutils::OV_PIPE1)) {
+ ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
+ ret = false;
+ }
+
+ // Play primary
+ if (!ov.queueBuffer(hnd->offset, ovutils::OV_PIPE0)) {
+ ALOGE("%s: queueBuffer failed for primary", __FUNCTION__);
+ ret = false;
+ }
+
+ // Wait for external vsync to be done
+ if (!ov.waitForVsync(ovutils::OV_PIPE1)) {
+ ALOGE("%s: waitForVsync failed for external", __FUNCTION__);
+ ret = false;
+ }
+ break;
+ default:
+ // In most cases, displaying only to one (primary or external)
+ // so use OV_PIPE_ALL since overlay will ignore NullPipes
+ ov.setMemoryId(hnd->fd, ovutils::OV_PIPE_ALL);
+ if (!ov.queueBuffer(hnd->offset, ovutils::OV_PIPE_ALL)) {
+ ALOGE("%s: queueBuffer failed", __FUNCTION__);
+ ret = false;
+ }
+ break;
+ }
+
+ if (!ret) {
+ ALOGE("%s: failed", __FUNCTION__);
+ }
+ return ret;
+}
+
+void cleanOverlays(hwc_context_t *ctx )
+{
+ //XXX: handle for HDMI
+ if(0 == ctx->yuvBufferCount)
+ setOverlayState(ctx, ovutils::OV_CLOSED);
+}
+}; //namespace qhwc
diff --git a/libhwcomposer/hwc_qbuf.h b/libhwcomposer/hwc_qbuf.h
new file mode 100644
index 0000000..a0ade8c
--- /dev/null
+++ b/libhwcomposer/hwc_qbuf.h
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * Copyright (C) 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.
+ */
+
+// -----------------------------------------------------------------------------
+// QueuedBufferStore
+//This class holds currently and previously queued buffers.
+//Provides utilities to store, lock, remove, unlock.
+
+namespace qhwc{
+static const int MAX_QUEUED_BUFS = 4;
+class QueuedBufferStore {
+ public:
+ QueuedBufferStore() {
+ clearCurrent();
+ clearPrevious();
+ }
+ ~QueuedBufferStore() {}
+ void lockAndAdd(private_handle_t*);
+ void unlockAllPrevious();
+
+ private:
+ QueuedBufferStore& operator=(const QueuedBufferStore&);
+ QueuedBufferStore(const QueuedBufferStore&);
+ bool lockBuffer(private_handle_t *hnd);
+ void unlockBuffer(private_handle_t *hnd);
+ void clearCurrent();
+ void clearPrevious();
+ void mvCurrToPrev();
+
+ //members
+ private_handle_t *current[MAX_QUEUED_BUFS]; //holds buf being queued
+ private_handle_t *previous[MAX_QUEUED_BUFS]; //holds bufs queued in prev round
+ int curCount;
+ int prevCount;
+};
+
+//Store and lock current drawing round buffers
+inline void QueuedBufferStore::lockAndAdd(private_handle_t *hnd) {
+ if(lockBuffer(hnd))
+ current[curCount++] = hnd;
+}
+
+//Unlock all previous drawing round buffers
+inline void QueuedBufferStore::unlockAllPrevious() {
+ //Unlock
+ for(int i = 0; i < prevCount; i++) {
+ unlockBuffer(previous[i]);
+ previous[i] = NULL;
+ }
+ //Move current hnd to previous
+ mvCurrToPrev();
+ //Clear current
+ clearCurrent();
+}
+
+//Clear currentbuf store
+inline void QueuedBufferStore::clearCurrent() {
+ for(int i = 0; i < MAX_QUEUED_BUFS; i++)
+ current[i] = NULL;
+ curCount = 0;
+}
+
+//Clear previousbuf store
+inline void QueuedBufferStore::clearPrevious() {
+ for(int i = 0; i < MAX_QUEUED_BUFS; i++)
+ previous[i] = NULL;
+ prevCount = 0;
+}
+
+//Copy from current to previous
+inline void QueuedBufferStore::mvCurrToPrev() {
+ for(int i = 0; i < curCount; i++)
+ previous[i] = current[i];
+ prevCount = curCount;
+}
+
+inline bool QueuedBufferStore::lockBuffer(private_handle_t *hnd) {
+ if (GENLOCK_FAILURE == genlock_lock_buffer(hnd, GENLOCK_READ_LOCK,
+ GENLOCK_MAX_TIMEOUT)) {
+ ALOGE("%s: genlock_lock_buffer(READ) failed", __func__);
+ return false;
+ }
+ return true;
+}
+
+inline void QueuedBufferStore::unlockBuffer(private_handle_t *hnd) {
+ //Check if buffer is still around
+ if(private_handle_t::validate(hnd) != 0) {
+ ALOGE("%s Invalid Handle", __func__);
+ return;
+ }
+ //Actually try to unlock
+ if (GENLOCK_FAILURE == genlock_unlock_buffer(hnd)) {
+ ALOGE("%s: genlock_unlock_buffer failed", __func__);
+ return;
+ }
+}
+// -----------------------------------------------------------------------------
+};//namespace
+
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
new file mode 100644
index 0000000..13873f8
--- /dev/null
+++ b/libhwcomposer/hwc_utils.cpp
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * Copyright (C) 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.
+ */
+
+#include "hwc_utils.h"
+
+namespace qhwc {
+void initContext(hwc_context_t *ctx)
+{
+ //XXX: target specific initializations here
+ openFramebufferDevice(ctx);
+ ctx->mOverlay = overlay::Overlay::getInstance();
+ ctx->qbuf = new QueuedBufferStore();
+
+}
+
+void closeContext(hwc_context_t *ctx)
+{
+ if(ctx->mOverlay) {
+ delete ctx->mOverlay;
+ ctx->mOverlay = NULL;
+ }
+ if(ctx->fbDev) {
+ framebuffer_close(ctx->fbDev);
+ ctx->fbDev = NULL;
+ }
+
+ if(ctx->qbuf) {
+ delete ctx->qbuf;
+ ctx->qbuf = NULL;
+ }
+}
+
+// Opens Framebuffer device
+void openFramebufferDevice(hwc_context_t *ctx) {
+ hw_module_t const *module;
+ if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) {
+ framebuffer_open(module, &(ctx->fbDev));
+ }
+}
+
+void dumpLayer(hwc_layer_t const* l)
+{
+ ALOGD("\ttype=%d, flags=%08x, handle=%p, tr=%02x, blend=%04x, {%d,%d,%d,%d}"
+ ", {%d,%d,%d,%d}",
+ l->compositionType, l->flags, l->handle, l->transform, l->blending,
+ l->sourceCrop.left,
+ l->sourceCrop.top,
+ l->sourceCrop.right,
+ l->sourceCrop.bottom,
+ l->displayFrame.left,
+ l->displayFrame.top,
+ l->displayFrame.right,
+ l->displayFrame.bottom);
+}
+
+void getLayerStats(hwc_context_t *ctx, const hwc_layer_list_t *list)
+{
+ int yuvBufCount = 0;
+ int layersNotUpdatingCount = 0;
+ for (size_t i=0 ; i<list->numHwLayers; i++) {
+ private_handle_t *hnd = (private_handle_t *)list->hwLayers[i].handle;
+ if (isYuvBuffer(hnd)) {
+ yuvBufCount++;
+ }
+ }
+ // Number of video/camera layers drawable with overlay
+ ctx->yuvBufferCount = yuvBufCount;
+ ctx->numHwLayers = list->numHwLayers;
+ return;
+}
+
+void handleYUV(hwc_context_t *ctx, hwc_layer_t *layer)
+{
+ private_handle_t *hnd =
+ (private_handle_t *)layer->handle;
+ //XXX: Handle targets not using overlay
+ if(prepareOverlay(ctx, layer)) {
+ layer->compositionType = HWC_USE_OVERLAY;
+ layer->hints |= HWC_HINT_CLEAR_FB;
+ }
+}
+};//namespace
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
new file mode 100644
index 0000000..b1c7871
--- /dev/null
+++ b/libhwcomposer/hwc_utils.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * Copyright (C) 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.
+ */
+
+#ifndef HWC_UTILS_H
+#define HWC_UTILS_H
+#include <cutils/log.h>
+#include <gralloc_priv.h>
+#include <hardware/hwcomposer.h>
+#include <hardware/hardware.h>
+#include <hardware/gralloc.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fb_priv.h>
+#include <overlay.h>
+#include <qcom_ui.h>
+#include <genlock.h>
+#include "hwc_qbuf.h"
+
+#define ALIGN(x, align) (((x) + ((align)-1)) & ~((align)-1))
+#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true ))
+#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false ))
+
+struct hwc_context_t;
+namespace qhwc {
+
+// -----------------------------------------------------------------------------
+// Utility functions - implemented in hwc_utils.cpp
+void dumpLayer(hwc_layer_t const* l);
+void getLayerStats(hwc_context_t *ctx, const hwc_layer_list_t *list);
+void handleYUV(hwc_context_t *ctx, hwc_layer_t *layer);
+void initContext(hwc_context_t *ctx);
+void closeContext(hwc_context_t *ctx);
+void openFramebufferDevice(hwc_context_t *ctx);
+
+// Inline utility functions
+static inline bool isSkipLayer(const hwc_layer_t* l) {
+ return (UNLIKELY(l && (l->flags & HWC_SKIP_LAYER)));
+}
+
+// Returns true if the buffer is yuv
+static inline bool isYuvBuffer(const private_handle_t* hnd) {
+ return (hnd && (hnd->bufferType == BUFFER_TYPE_VIDEO));
+}
+
+//Return true if buffer is marked locked
+static inline bool isBufferLocked(const private_handle_t* hnd) {
+ return (hnd && (private_handle_t::PRIV_FLAGS_HWC_LOCK & hnd->flags));
+}
+
+// -----------------------------------------------------------------------------
+// Overlay specific functions - inline or implemented in hwc_overlay.cpp
+bool prepareOverlay(hwc_context_t *ctx, hwc_layer_t *layer);
+//XXX: Refine draw functions
+bool drawLayerUsingOverlay(hwc_context_t *ctx, hwc_layer_t *layer);
+//XXX: Refine
+void cleanOverlays(hwc_context_t *ctx );
+void setOverlayState(hwc_context_t* ctx, ovutils::eOverlayState state);
+
+// -----------------------------------------------------------------------------
+// Copybit specific functions - inline or implemented in hwc_copybit.cpp
+
+
+
+// -----------------------------------------------------------------------------
+// HDMI specific functions - inline or implemented in hwc_hdmi.cpp
+
+
+
+} //qhwc namespace
+
+
+
+// -----------------------------------------------------------------------------
+// HWC context
+// This structure contains overall state
+struct hwc_context_t {
+ hwc_composer_device_t device;
+ // Layer variables
+ int yuvBufferCount;
+ int hdmiEnabled;
+ int numHwLayers;
+ bool skipComposition;
+
+ //Framebuffer device
+ framebuffer_device_t *fbDev;
+
+ //Overlay object - NULL for non overlay devices
+ overlay::Overlay *mOverlay;
+
+ //QueuedBufferStore to hold buffers for overlay
+ qhwc::QueuedBufferStore *qbuf;
+};
+
+
+
+
+#endif //HWC_UTILS_H
diff --git a/libhwcomposer/hwcomposer.cpp b/libhwcomposer/hwcomposer.cpp
deleted file mode 100755
index c43fa04..0000000
--- a/libhwcomposer/hwcomposer.cpp
+++ /dev/null
@@ -1,1734 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdlib.h>
-#include <stdint.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <hardware/hardware.h>
-
-#include <fcntl.h>
-#include <errno.h>
-
-#include <cutils/log.h>
-#include <cutils/atomic.h>
-#include <cutils/properties.h>
-
-#include <hardware/hwcomposer.h>
-#include <overlayLib.h>
-#include <overlayLibUI.h>
-#include <copybit.h>
-
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-#include <ui/android_native_buffer.h>
-#include <gralloc_priv.h>
-#include <genlock.h>
-#include <qcom_ui.h>
-#include <gr.h>
-
-/*****************************************************************************/
-#define ALIGN(x, align) (((x) + ((align)-1)) & ~((align)-1))
-#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true ))
-#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false ))
-
-#ifdef COMPOSITION_BYPASS
-#define MAX_BYPASS_LAYERS 3
-#define BYPASS_DEBUG 0
-#define BYPASS_INDEX_OFFSET 4
-
-enum BypassState {
- BYPASS_ON,
- BYPASS_OFF,
- BYPASS_OFF_PENDING,
-};
-
-enum BypassBufferLockState {
- BYPASS_BUFFER_UNLOCKED,
- BYPASS_BUFFER_LOCKED,
-};
-#endif
-
-enum HWCLayerType{
- HWC_SINGLE_VIDEO = 0x1,
- HWC_ORIG_RESOLUTION = 0x2,
- HWC_S3D_LAYER = 0x4,
- HWC_STOP_UI_MIRRORING_MASK = 0xF
-};
-
-enum eHWCOverlayStatus {
- HWC_OVERLAY_OPEN,
- HWC_OVERLAY_PREPARE_TO_CLOSE,
- HWC_OVERLAY_CLOSED
-};
-
-struct hwc_context_t {
- hwc_composer_device_t device;
- /* our private state goes below here */
- overlay::Overlay* mOverlayLibObject;
- native_handle_t *previousOverlayHandle;
-#ifdef COMPOSITION_BYPASS
- overlay::OverlayUI* mOvUI[MAX_BYPASS_LAYERS];
- native_handle_t* previousBypassHandle[MAX_BYPASS_LAYERS];
- BypassBufferLockState bypassBufferLockState[MAX_BYPASS_LAYERS];
- int layerindex[MAX_BYPASS_LAYERS];
- int nPipesUsed;
- BypassState bypassState;
-#endif
-#if defined HDMI_DUAL_DISPLAY
- external_display mHDMIEnabled; // Type of external display
- bool pendingHDMI;
-#endif
- int previousLayerCount;
- eHWCOverlayStatus hwcOverlayStatus;
-};
-
-static int hwc_device_open(const struct hw_module_t* module, const char* name,
- struct hw_device_t** device);
-
-static struct hw_module_methods_t hwc_module_methods = {
- open: hwc_device_open
-};
-
-
-struct private_hwc_module_t {
- hwc_module_t base;
- copybit_device_t *copybitEngine;
- framebuffer_device_t *fbDevice;
- int compositionType;
- bool isBypassEnabled; //from build.prop ro.sf.compbypass.enable
-};
-
-struct private_hwc_module_t HAL_MODULE_INFO_SYM = {
- base: {
- common: {
- tag: HARDWARE_MODULE_TAG,
- version_major: 1,
- version_minor: 0,
- id: HWC_HARDWARE_MODULE_ID,
- name: "Hardware Composer Module",
- author: "The Android Open Source Project",
- methods: &hwc_module_methods,
- }
- },
- copybitEngine: NULL,
- fbDevice: NULL,
- compositionType: 0,
- isBypassEnabled: false,
-};
-
-//Only at this point would the compiler know all storage class sizes.
-//The header has hooks which need to know those beforehand.
-#include "external_display_only.h"
-
-/*****************************************************************************/
-
-static void dump_layer(hwc_layer_t const* l) {
- LOGD("\ttype=%d, flags=%08x, handle=%p, tr=%02x, blend=%04x, {%d,%d,%d,%d}, {%d,%d,%d,%d}",
- l->compositionType, l->flags, l->handle, l->transform, l->blending,
- l->sourceCrop.left,
- l->sourceCrop.top,
- l->sourceCrop.right,
- l->sourceCrop.bottom,
- l->displayFrame.left,
- l->displayFrame.top,
- l->displayFrame.right,
- l->displayFrame.bottom);
-}
-
-static inline int min(const int& a, const int& b) {
- return (a < b) ? a : b;
-}
-
-static inline int max(const int& a, const int& b) {
- return (a > b) ? a : b;
-}
-#ifdef COMPOSITION_BYPASS
-void setLayerbypassIndex(hwc_layer_t* layer, const int bypass_index)
-{
- layer->flags &= ~HWC_BYPASS_INDEX_MASK;
- layer->flags |= bypass_index << BYPASS_INDEX_OFFSET;
-}
-
-int getLayerbypassIndex(hwc_layer_t* layer)
-{
- int byp_index = -1;
-
- if(layer->flags & HWC_COMP_BYPASS) {
- byp_index = ((layer->flags & HWC_BYPASS_INDEX_MASK) >> BYPASS_INDEX_OFFSET);
- byp_index = (byp_index < MAX_BYPASS_LAYERS ? byp_index : -1 );
- }
- return byp_index;
-}
-
-void unlockPreviousBypassBuffers(hwc_context_t* ctx) {
- // Unlock the previous bypass buffers. We can blindly unlock the buffers here,
- // because buffers will be in this list only if the lock was successfully acquired.
- for(int i = 0; i < MAX_BYPASS_LAYERS && ctx->previousBypassHandle[i]; i++) {
- private_handle_t *hnd = (private_handle_t*) ctx->previousBypassHandle[i];
-
- // Validate the handle to make sure it hasn't been deallocated.
- if (private_handle_t::validate(ctx->previousBypassHandle[i])) {
- continue;
- }
- // Check if the handle was locked previously
- if (private_handle_t::PRIV_FLAGS_HWC_LOCK & hnd->flags) {
- if (GENLOCK_FAILURE == genlock_unlock_buffer(ctx->previousBypassHandle[i])) {
- LOGE("%s: genlock_unlock_buffer failed", __FUNCTION__);
- } else {
- ctx->previousBypassHandle[i] = NULL;
- // Reset the lock flag
- hnd->flags &= ~private_handle_t::PRIV_FLAGS_HWC_LOCK;
- }
- }
- }
-}
-
-void print_info(hwc_layer_t* layer)
-{
- hwc_rect_t sourceCrop = layer->sourceCrop;
- hwc_rect_t displayFrame = layer->displayFrame;
-
- int s_l = sourceCrop.left;
- int s_t = sourceCrop.top;
- int s_r = sourceCrop.right;
- int s_b = sourceCrop.bottom;
-
- int d_l = displayFrame.left;
- int d_t = displayFrame.top;
- int d_r = displayFrame.right;
- int d_b = displayFrame.bottom;
-
- LOGE_IF(BYPASS_DEBUG, "src:[%d,%d,%d,%d] (%d x %d) dst:[%d,%d,%d,%d] (%d x %d)",
- s_l, s_t, s_r, s_b, (s_r - s_l), (s_b - s_t),
- d_l, d_t, d_r, d_b, (d_r - d_l), (d_b - d_t));
-}
-
-//Crops source buffer against destination and FB boundaries
-void calculate_crop_rects(hwc_rect_t& crop, hwc_rect_t& dst, int hw_w, int hw_h) {
-
- int& crop_x = crop.left;
- int& crop_y = crop.top;
- int& crop_r = crop.right;
- int& crop_b = crop.bottom;
- int crop_w = crop.right - crop.left;
- int crop_h = crop.bottom - crop.top;
-
- int& dst_x = dst.left;
- int& dst_y = dst.top;
- int& dst_r = dst.right;
- int& dst_b = dst.bottom;
- int dst_w = dst.right - dst.left;
- int dst_h = dst.bottom - dst.top;
-
- if(dst_x < 0) {
- float scale_x = crop_w * 1.0f / dst_w;
- float diff_factor = (scale_x * abs(dst_x));
- crop_x = crop_x + (int)diff_factor;
- crop_w = crop_r - crop_x;
-
- dst_x = 0;
- dst_w = dst_r - dst_x;;
- }
- if(dst_r > hw_w) {
- float scale_x = crop_w * 1.0f / dst_w;
- float diff_factor = scale_x * (dst_r - hw_w);
- crop_r = crop_r - diff_factor;
- crop_w = crop_r - crop_x;
-
- dst_r = hw_w;
- dst_w = dst_r - dst_x;
- }
- if(dst_y < 0) {
- float scale_y = crop_h * 1.0f / dst_h;
- float diff_factor = scale_y * abs(dst_y);
- crop_y = crop_y + diff_factor;
- crop_h = crop_b - crop_y;
-
- dst_y = 0;
- dst_h = dst_b - dst_y;
- }
- if(dst_b > hw_h) {
- float scale_y = crop_h * 1.0f / dst_h;
- float diff_factor = scale_y * (dst_b - hw_h);
- crop_b = crop_b - diff_factor;
- crop_h = crop_b - crop_y;
-
- dst_b = hw_h;
- dst_h = dst_b - dst_y;
- }
-
- LOGE_IF(BYPASS_DEBUG,"crop: [%d,%d,%d,%d] dst:[%d,%d,%d,%d]",
- crop_x, crop_y, crop_w, crop_h,dst_x, dst_y, dst_w, dst_h);
-}
-
-/*
- * Configures pipe(s) for composition bypass
- */
-static int prepareBypass(hwc_context_t *ctx, hwc_layer_t *layer,
- int nPipeIndex, int vsync_wait, int isFG) {
-
- if (ctx && ctx->mOvUI[nPipeIndex]) {
- overlay::OverlayUI *ovUI = ctx->mOvUI[nPipeIndex];
-
- private_hwc_module_t* hwcModule = reinterpret_cast<
- private_hwc_module_t*>(ctx->device.common.module);
- if (!hwcModule) {
- LOGE("%s: NULL Module", __FUNCTION__);
- return -1;
- }
-
- private_handle_t *hnd = (private_handle_t *)layer->handle;
- if(!hnd) {
- LOGE("%s: layer handle is NULL", __FUNCTION__);
- return -1;
- }
-
- int hw_w = hwcModule->fbDevice->width;
- int hw_h = hwcModule->fbDevice->height;
-
- hwc_rect_t sourceCrop = layer->sourceCrop;
- hwc_rect_t displayFrame = layer->displayFrame;
-
- const int src_w = sourceCrop.right - sourceCrop.left;
- const int src_h = sourceCrop.bottom - sourceCrop.top;
-
- hwc_rect_t crop = sourceCrop;
- int crop_w = crop.right - crop.left;
- int crop_h = crop.bottom - crop.top;
-
- hwc_rect_t dst = displayFrame;
- int dst_w = dst.right - dst.left;
- int dst_h = dst.bottom - dst.top;
-
- if(hnd != NULL && (hnd->flags & private_handle_t::PRIV_FLAGS_NONCONTIGUOUS_MEM )) {
- LOGE("%s: Unable to setup bypass due to non-pmem memory",__FUNCTION__);
- return -1;
- }
-
- if(dst.left < 0 || dst.top < 0 || dst.right > hw_w || dst.bottom > hw_h) {
- LOGE_IF(BYPASS_DEBUG,"%s: Destination has negative coordinates", __FUNCTION__);
-
- calculate_crop_rects(crop, dst, hw_w, hw_h);
-
- //Update calulated width and height
- crop_w = crop.right - crop.left;
- crop_h = crop.bottom - crop.top;
-
- dst_w = dst.right - dst.left;
- dst_h = dst.bottom - dst.top;
- }
-
- if( (dst_w > hw_w)|| (dst_h > hw_h)) {
- LOGE_IF(BYPASS_DEBUG,"%s: Destination rectangle exceeds FB resolution", __FUNCTION__);
- print_info(layer);
- dst_w = hw_w;
- dst_h = hw_h;
- }
-
- overlay_buffer_info info;
- info.width = src_w;
- info.height = src_h;
- info.format = hnd->format;
- info.size = hnd->size;
-
- int fbnum = 0;
- int orientation = layer->transform;
- const bool useVGPipe = (nPipeIndex != (MAX_BYPASS_LAYERS-1));
- //only last layer should wait for vsync
- const bool waitForVsync = vsync_wait;
- const bool isFg = isFG;
- //Just to differentiate zorders for different layers
- const int zorder = nPipeIndex;
-
- ovUI->setSource(info, orientation);
- ovUI->setCrop(crop.left, crop.top, crop_w, crop_h);
- ovUI->setDisplayParams(fbnum, waitForVsync, isFg, zorder, useVGPipe);
- ovUI->setPosition(dst.left, dst.top, dst_w, dst_h);
-
- LOGE_IF(BYPASS_DEBUG,"%s: Bypass set: crop[%d,%d,%d,%d] dst[%d,%d,%d,%d] waitforVsync: %d \
- isFg: %d zorder: %d VG = %d nPipe: %d",__FUNCTION__,
- crop.left, crop.top, crop_w, crop_h,
- dst.left, dst.top, dst_w, dst_h,
- waitForVsync, isFg, zorder, useVGPipe, nPipeIndex );
-
- if(ovUI->commit() != overlay::NO_ERROR) {
- LOGE("%s: Overlay Commit failed", __FUNCTION__);
- return -1;
- }
- }
- return 0;
-}
-
-/*
- * Checks if doing comp. bypass is possible.
- * It is possible if
- * 1. No MDP pipe is used
- * 2. Rotation is not needed
- * 3. We have atmost MAX_BYPASS_LAYERS
- */
-inline static bool isBypassDoable(hwc_composer_device_t *dev, const int yuvCount,
- const hwc_layer_list_t* list) {
- hwc_context_t* ctx = (hwc_context_t*)(dev);
- private_hwc_module_t* hwcModule = reinterpret_cast<private_hwc_module_t*>(
- dev->common.module);
- //Check if enabled in build.prop
- if(hwcModule->isBypassEnabled == false) {
- return false;
- }
-
- if(list->numHwLayers < 1) {
- return false;
- }
-
-#if defined HDMI_DUAL_DISPLAY
- //Disable bypass when HDMI is enabled
- if(ctx->mHDMIEnabled || ctx->pendingHDMI) {
- return false;
- }
-#endif
-
- if(ExtDispOnly::isModeOn()) {
- return false;
- }
-
- //Bypass is not efficient if rotation or asynchronous mode is needed.
- for(int i = 0; i < list->numHwLayers; ++i) {
- if(list->hwLayers[i].transform) {
- return false;
- }
- if(list->hwLayers[i].flags & HWC_LAYER_ASYNCHRONOUS) {
- return false;
- }
- }
-
- return (yuvCount == 0) && (ctx->hwcOverlayStatus == HWC_OVERLAY_CLOSED)
- && (list->numHwLayers <= MAX_BYPASS_LAYERS);
-}
-
-void setBypassLayerFlags(hwc_context_t* ctx, hwc_layer_list_t* list)
-{
- for(int index = 0 ; index < MAX_BYPASS_LAYERS; index++ )
- {
- int layer_index = ctx->layerindex[index];
- if(layer_index >= 0) {
- hwc_layer_t* layer = &(list->hwLayers[layer_index]);
-
- layer->flags |= HWC_COMP_BYPASS;
- layer->compositionType = HWC_USE_OVERLAY;
- layer->hints |= HWC_HINT_CLEAR_FB;
- }
- }
-
- if( list->numHwLayers > ctx->nPipesUsed ) {
- list->flags &= ~HWC_SKIP_COMPOSITION; //Compose to FB
- } else {
- list->flags |= HWC_SKIP_COMPOSITION; // Dont
- }
-}
-
-bool setupBypass(hwc_context_t* ctx, hwc_layer_list_t* list) {
- int nPipeIndex, vsync_wait, isFG;
- int numHwLayers = list->numHwLayers;
- int nPipeAvailable = MAX_BYPASS_LAYERS;
-
- for (int index = 0 ; (index < numHwLayers) && nPipeAvailable; index++) {
-
- hwc_layer_t* layer = &(list->hwLayers[index]);
-
- nPipeIndex = MAX_BYPASS_LAYERS - nPipeAvailable;
- //Set VSYNC wait is needed only for the last pipe queued
- vsync_wait = (nPipeIndex == (numHwLayers-1));
- //Set isFG to true for layer with z-order zero
- isFG = !index;
-
- //Clear Bypass flags for the layer
- layer->flags &= ~HWC_COMP_BYPASS;
- layer->flags |= HWC_BYPASS_INDEX_MASK;
-
- if( prepareBypass(ctx, &(list->hwLayers[index]), nPipeIndex, vsync_wait, isFG) != 0 ) {
- LOGE_IF(BYPASS_DEBUG, "%s: layer %d failed to configure bypass for pipe index: %d",
- __FUNCTION__, index, nPipeIndex);
- return false;
- } else {
- ctx->layerindex[nPipeIndex] = index;
- setLayerbypassIndex(layer, nPipeIndex);
- nPipeAvailable--;
- }
- }
- ctx->nPipesUsed = MAX_BYPASS_LAYERS - nPipeAvailable;
- return true;
-}
-
-void unsetBypassLayerFlags(hwc_layer_list_t* list) {
- if (!list)
- return;
-
- for (int index = 0 ; index < list->numHwLayers; index++) {
- if(list->hwLayers[index].flags & HWC_COMP_BYPASS) {
- list->hwLayers[index].flags &= ~HWC_COMP_BYPASS;
- }
- }
-}
-
-void unsetBypassBufferLockState(hwc_context_t* ctx) {
- for (int i= 0; i< MAX_BYPASS_LAYERS; i++) {
- ctx->bypassBufferLockState[i] = BYPASS_BUFFER_UNLOCKED;
- }
-}
-
-void storeLockedBypassHandle(hwc_layer_list_t* list, hwc_context_t* ctx) {
- if (!list)
- return;
-
- for(int index = 0; index < MAX_BYPASS_LAYERS; index++ ) {
- hwc_layer_t layer = list->hwLayers[ctx->layerindex[index]];
-
- if (layer.flags & HWC_COMP_BYPASS) {
- private_handle_t *hnd = (private_handle_t*)layer.handle;
-
- if (ctx->bypassBufferLockState[index] == BYPASS_BUFFER_LOCKED) {
- ctx->previousBypassHandle[index] = (native_handle_t*)layer.handle;
- hnd->flags |= private_handle_t::PRIV_FLAGS_HWC_LOCK;
- } else {
- ctx->previousBypassHandle[index] = NULL;
- }
- }
- }
-}
-
-void closeExtraPipes(hwc_context_t* ctx) {
-
- int pipes_used = ctx->nPipesUsed;
-
- //Unused pipes must be of higher z-order
- for (int i = pipes_used ; i < MAX_BYPASS_LAYERS; i++) {
- if (ctx->previousBypassHandle[i]) {
- private_handle_t *hnd = (private_handle_t*) ctx->previousBypassHandle[i];
-
- if (!private_handle_t::validate(ctx->previousBypassHandle[i])) {
- if (GENLOCK_FAILURE == genlock_unlock_buffer(ctx->previousBypassHandle[i])) {
- LOGE("%s: genlock_unlock_buffer failed", __FUNCTION__);
- } else {
- ctx->previousBypassHandle[i] = NULL;
- ctx->bypassBufferLockState[i] = BYPASS_BUFFER_UNLOCKED;
- hnd->flags &= ~private_handle_t::PRIV_FLAGS_HWC_LOCK;
- }
- }
- }
- ctx->mOvUI[i]->closeChannel();
- ctx->layerindex[i] = -1;
- }
-}
-#endif //COMPOSITION_BYPASS
-
-static int setVideoOverlayStatusInGralloc(hwc_context_t* ctx, const bool enable) {
-#if defined HDMI_DUAL_DISPLAY
- private_hwc_module_t* hwcModule = reinterpret_cast<private_hwc_module_t*>(
- ctx->device.common.module);
- if(!hwcModule) {
- LOGE("%s: invalid params", __FUNCTION__);
- return -1;
- }
-
- framebuffer_device_t *fbDev = hwcModule->fbDevice;
- if (!fbDev) {
- LOGE("%s: fbDev is NULL", __FUNCTION__);
- return -1;
- }
-
- // Inform the gralloc to stop or start UI mirroring
- fbDev->videoOverlayStarted(fbDev, enable);
-#endif
- return 0;
-}
-
-static void setHWCOverlayStatus(hwc_context_t *ctx, bool isVideoPresent) {
-
- switch (ctx->hwcOverlayStatus) {
- case HWC_OVERLAY_OPEN:
- ctx->hwcOverlayStatus =
- isVideoPresent ? HWC_OVERLAY_OPEN : HWC_OVERLAY_PREPARE_TO_CLOSE;
- break;
- case HWC_OVERLAY_PREPARE_TO_CLOSE:
- ctx->hwcOverlayStatus =
- isVideoPresent ? HWC_OVERLAY_OPEN : HWC_OVERLAY_CLOSED;
- break;
- case HWC_OVERLAY_CLOSED:
- ctx->hwcOverlayStatus =
- isVideoPresent ? HWC_OVERLAY_OPEN : HWC_OVERLAY_CLOSED;
- break;
- default:
- LOGE("%s: Invalid hwcOverlayStatus (status =%d)", __FUNCTION__,
- ctx->hwcOverlayStatus);
- break;
- }
-}
-
-static int hwc_closeOverlayChannels(hwc_context_t* ctx) {
-#ifdef USE_OVERLAY
- overlay::Overlay *ovLibObject = ctx->mOverlayLibObject;
- if(!ovLibObject) {
- LOGE("%s: invalid params", __FUNCTION__);
- return -1;
- }
-
- if (HWC_OVERLAY_PREPARE_TO_CLOSE == ctx->hwcOverlayStatus) {
- // Video mirroring is going on, and we do not have any layers to
- // mirror directly. Close the current video channel and inform the
- // gralloc to start UI mirroring
- ovLibObject->closeChannel();
- // Inform the gralloc that video overlay has stopped.
- setVideoOverlayStatusInGralloc(ctx, false);
- }
-#endif
- return 0;
-}
-
-/*
- * Configures mdp pipes
- */
-static int prepareOverlay(hwc_context_t *ctx, hwc_layer_t *layer, const int flags) {
- int ret = 0;
-
-#ifdef COMPOSITION_BYPASS
- if(ctx && (ctx->bypassState != BYPASS_OFF)) {
- ctx->nPipesUsed = 0;
- closeExtraPipes(ctx);
- ctx->bypassState = BYPASS_OFF;
- }
-#endif
-
- if (LIKELY(ctx && ctx->mOverlayLibObject)) {
- private_hwc_module_t* hwcModule =
- reinterpret_cast<private_hwc_module_t*>(ctx->device.common.module);
- if (UNLIKELY(!hwcModule)) {
- LOGE("prepareOverlay null module ");
- return -1;
- }
-
- private_handle_t *hnd = (private_handle_t *)layer->handle;
- overlay::Overlay *ovLibObject = ctx->mOverlayLibObject;
- overlay_buffer_info info;
- info.width = hnd->width;
- info.height = hnd->height;
- info.format = hnd->format;
- info.size = hnd->size;
-
- int hdmiConnected = 0;
-
-#if defined HDMI_DUAL_DISPLAY
- if(!ctx->pendingHDMI) //makes sure the UI channel is opened first
- hdmiConnected = (int)ctx->mHDMIEnabled;
-#endif
- ret = ovLibObject->setSource(info, layer->transform,
- hdmiConnected, flags);
- if (!ret) {
- LOGE("prepareOverlay setSource failed");
- return -1;
- }
-
- ret = ovLibObject->setTransform(layer->transform);
- if (!ret) {
- LOGE("prepareOverlay setTransform failed transform %x",
- layer->transform);
- return -1;
- }
-
- hwc_rect_t sourceCrop = layer->sourceCrop;
- ret = ovLibObject->setCrop(sourceCrop.left, sourceCrop.top,
- (sourceCrop.right - sourceCrop.left),
- (sourceCrop.bottom - sourceCrop.top));
- if (!ret) {
- LOGE("prepareOverlay setCrop failed");
- return -1;
- }
-#if defined HDMI_DUAL_DISPLAY
- // Send the device orientation to overlayLib
- if(hwcModule) {
- framebuffer_device_t *fbDev = reinterpret_cast<framebuffer_device_t*>
- (hwcModule->fbDevice);
- if(fbDev) {
- private_module_t* m = reinterpret_cast<private_module_t*>(
- fbDev->common.module);
- if(m)
- ovLibObject->setDeviceOrientation(m->orientation);
- }
- }
-#endif
- if (layer->flags & HWC_USE_ORIGINAL_RESOLUTION) {
- framebuffer_device_t* fbDev = hwcModule->fbDevice;
- ret = ovLibObject->setPosition(0, 0,
- fbDev->width, fbDev->height);
- } else {
- hwc_rect_t displayFrame = layer->displayFrame;
- ret = ovLibObject->setPosition(displayFrame.left, displayFrame.top,
- (displayFrame.right - displayFrame.left),
- (displayFrame.bottom - displayFrame.top));
- }
- if (!ret) {
- LOGE("prepareOverlay setPosition failed");
- return -1;
- }
- }
- return 0;
-}
-
-void unlockPreviousOverlayBuffer(hwc_context_t* ctx)
-{
- if (ctx->previousOverlayHandle) {
- // Validate the handle before attempting to use it.
- if (!private_handle_t::validate(ctx->previousOverlayHandle)) {
- private_handle_t *hnd = (private_handle_t*)ctx->previousOverlayHandle;
- // Unlock any previously locked buffers
- if (private_handle_t::PRIV_FLAGS_HWC_LOCK & hnd->flags) {
- if (GENLOCK_NO_ERROR == genlock_unlock_buffer(ctx->previousOverlayHandle)) {
- ctx->previousOverlayHandle = NULL;
- hnd->flags &= ~private_handle_t::PRIV_FLAGS_HWC_LOCK;
- } else {
- LOGE("%s: genlock_unlock_buffer failed", __FUNCTION__);
- }
- }
- }
- }
-}
-
-bool canSkipComposition(hwc_context_t* ctx, int yuvBufferCount, int currentLayerCount,
- int numLayersNotUpdating)
-{
- if (!ctx) {
- LOGE("%s: invalid context",__FUNCTION__);
- return false;
- }
-
- hwc_composer_device_t* dev = (hwc_composer_device_t *)(ctx);
- private_hwc_module_t* hwcModule = reinterpret_cast<private_hwc_module_t*>(
- dev->common.module);
- if (hwcModule->compositionType == COMPOSITION_TYPE_CPU)
- return false;
-
- //Video / Camera case
- if (yuvBufferCount == 1) {
- //If the previousLayerCount is anything other than the current count, it
- //means something changed and we need to compose atleast once to FB.
- if (currentLayerCount != ctx->previousLayerCount) {
- ctx->previousLayerCount = currentLayerCount;
- return false;
- }
- // We either have only one overlay layer or we have
- // all non-updating UI layers.
- // We can skip the composition of the UI layers.
- if ((currentLayerCount == 1) ||
- ((currentLayerCount - 1) == numLayersNotUpdating)) {
- return true;
- }
- } else {
- ctx->previousLayerCount = -1;
- }
- return false;
-}
-
-inline void getLayerResolution(const hwc_layer_t* layer, int& width, int& height)
-{
- hwc_rect_t displayFrame = layer->displayFrame;
-
- width = displayFrame.right - displayFrame.left;
- height = displayFrame.bottom - displayFrame.top;
-}
-
-static bool canUseCopybit(const framebuffer_device_t* fbDev, const hwc_layer_list_t* list) {
-
- if(!fbDev) {
- LOGE("ERROR: %s : fb device is invalid",__func__);
- return false;
- }
-
- if (!list)
- return false;
-
- int fb_w = fbDev->width;
- int fb_h = fbDev->height;
-
- /*
- * Use copybit only when we need to blit
- * max 2 full screen sized regions
- */
-
- unsigned int renderArea = 0;
-
- for(int i = 0; i < list->numHwLayers; i++ ) {
- int w, h;
- getLayerResolution(&list->hwLayers[i], w, h);
- renderArea += w*h;
- }
-
- return (renderArea <= (2 * fb_w * fb_h));
-}
-
-static void handleHDMIStateChange(hwc_composer_device_t *dev, int externaltype) {
-#if defined HDMI_DUAL_DISPLAY
- hwc_context_t* ctx = (hwc_context_t*)(dev);
- private_hwc_module_t* hwcModule = reinterpret_cast<private_hwc_module_t*>(
- dev->common.module);
- //Route the event to fbdev only if we are in default mirror mode
- if(ExtDispOnly::isModeOn() == false) {
- framebuffer_device_t *fbDev = hwcModule->fbDevice;
- if (fbDev) {
- fbDev->enableHDMIOutput(fbDev, externaltype);
- }
-
- if(ctx && ctx->mOverlayLibObject) {
- overlay::Overlay *ovLibObject = ctx->mOverlayLibObject;
- if (!externaltype) {
- // Close the external overlay channels if HDMI is disconnected
- ovLibObject->closeExternalChannel();
- }
- }
- }
-#endif
-}
-
-/*
- * function to set the status of external display in hwc
- * Just mark flags and do stuff after eglSwapBuffers
- * externaltype - can be HDMI, WIFI or OFF
- */
-static void hwc_enableHDMIOutput(hwc_composer_device_t *dev, int externaltype) {
-#if defined HDMI_DUAL_DISPLAY
- hwc_context_t* ctx = (hwc_context_t*)(dev);
- private_hwc_module_t* hwcModule = reinterpret_cast<private_hwc_module_t*>(
- dev->common.module);
- framebuffer_device_t *fbDev = hwcModule->fbDevice;
- overlay::Overlay *ovLibObject = ctx->mOverlayLibObject;
- if(externaltype && ctx->mHDMIEnabled &&
- (externaltype != ctx->mHDMIEnabled)) {
- // Close the current external display - as the SF will
- // prioritize and send the correct external display HDMI/WFD
- handleHDMIStateChange(dev, 0);
- }
- // Store the external display
- ctx->mHDMIEnabled = (external_display)externaltype;
- if(ctx->mHDMIEnabled) { //On connect, allow bypass to draw once to FB
- ctx->pendingHDMI = true;
- } else { //On disconnect, close immediately (there will be no bypass)
- handleHDMIStateChange(dev, ctx->mHDMIEnabled);
- }
-#endif
-}
-
-static bool isValidDestination(const framebuffer_device_t* fbDev, const hwc_rect_t& rect)
-{
- if (!fbDev) {
- LOGE("%s: fbDev is null", __FUNCTION__);
- return false;
- }
-
- int dest_width = (rect.right - rect.left);
- int dest_height = (rect.bottom - rect.top);
-
- if (rect.left < 0 || rect.right < 0 || rect.top < 0 || rect.bottom < 0
- || dest_width <= 0 || dest_height <= 0) {
- LOGE("%s: destination: left=%d right=%d top=%d bottom=%d width=%d"
- "height=%d", __FUNCTION__, rect.left, rect.right, rect.top,
- rect.bottom, dest_width, dest_height);
- return false;
- }
-
- if ((rect.left+dest_width) > fbDev->width || (rect.top+dest_height) > fbDev->height) {
- LOGE("%s: destination out of bound params", __FUNCTION__);
- return false;
- }
-
- return true;
-}
-
-static int getYUVBufferCount (const hwc_layer_list_t* list) {
- int yuvBufferCount = 0;
- if (list) {
- for (size_t i=0 ; i<list->numHwLayers; i++) {
- private_handle_t *hnd = (private_handle_t *)list->hwLayers[i].handle;
- if (hnd && (hnd->bufferType == BUFFER_TYPE_VIDEO) &&
- !(list->hwLayers[i].flags & HWC_DO_NOT_USE_OVERLAY)) {
- yuvBufferCount++;
- if (yuvBufferCount > 1) {
- break;
- }
- }
- }
- }
- return yuvBufferCount;
-}
-
-static int getS3DVideoFormat (const hwc_layer_list_t* list) {
- int s3dFormat = 0;
- if (list) {
- for (size_t i=0; i<list->numHwLayers; i++) {
- private_handle_t *hnd = (private_handle_t *)list->hwLayers[i].handle;
- if (hnd && (hnd->bufferType == BUFFER_TYPE_VIDEO))
- s3dFormat = FORMAT_3D_INPUT(hnd->format);
- if (s3dFormat)
- break;
- }
- }
- return s3dFormat;
-}
-
-static int getS3DFormat (const hwc_layer_list_t* list) {
- int s3dFormat = 0;
- if (list) {
- for (size_t i=0; i<list->numHwLayers; i++) {
- private_handle_t *hnd = (private_handle_t *)list->hwLayers[i].handle;
- if (hnd)
- s3dFormat = FORMAT_3D_INPUT(hnd->format);
- if (s3dFormat)
- break;
- }
- }
- return s3dFormat;
-}
-
-
-static int getLayerS3DFormat (hwc_layer_t &layer) {
- int s3dFormat = 0;
- private_handle_t *hnd = (private_handle_t *)layer.handle;
- if (hnd)
- s3dFormat = FORMAT_3D_INPUT(hnd->format);
- return s3dFormat;
-}
-static bool isS3DCompositionRequired() {
-#ifdef HDMI_AS_PRIMARY
- return overlay::is3DTV();
-#endif
- return false;
-}
-
-static void markUILayerForS3DComposition (hwc_layer_t &layer, int s3dVideoFormat) {
-#ifdef HDMI_AS_PRIMARY
- layer.compositionType = HWC_FRAMEBUFFER;
- switch(s3dVideoFormat) {
- case HAL_3D_IN_SIDE_BY_SIDE_L_R:
- case HAL_3D_IN_SIDE_BY_SIDE_R_L:
- layer.hints |= HWC_HINT_DRAW_S3D_SIDE_BY_SIDE;
- break;
- case HAL_3D_IN_TOP_BOTTOM:
- layer.hints |= HWC_HINT_DRAW_S3D_TOP_BOTTOM;
- break;
- default:
- LOGE("%s: Unknown S3D input format 0x%x", __FUNCTION__, s3dVideoFormat);
- break;
- }
-#endif
- return;
-}
-
-static int getLayersNotUpdatingCount(const hwc_layer_list_t* list) {
- int numLayersNotUpdating = 0;
- if (list) {
- for (size_t i=0 ; i<list->numHwLayers; i++) {
- private_handle_t *hnd = (private_handle_t *)list->hwLayers[i].handle;
- if (hnd && (hnd->bufferType != BUFFER_TYPE_VIDEO) &&
- list->hwLayers[i].flags & HWC_LAYER_NOT_UPDATING)
- numLayersNotUpdating++;
- }
- }
- return numLayersNotUpdating;
-}
-
-static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) {
-
- hwc_context_t* ctx = (hwc_context_t*)(dev);
-
- if(!ctx) {
- LOGE("hwc_prepare invalid context");
- return -1;
- }
-
- private_hwc_module_t* hwcModule = reinterpret_cast<private_hwc_module_t*>(
- dev->common.module);
- if (!hwcModule) {
- LOGE("hwc_prepare invalid module");
-#ifdef COMPOSITION_BYPASS
- unlockPreviousBypassBuffers(ctx);
- unsetBypassBufferLockState(ctx);
-#endif
- unlockPreviousOverlayBuffer(ctx);
- ExtDispOnly::close();
- return -1;
- }
-
- int yuvBufferCount = 0;
- int layerType = 0;
- bool isS3DCompositionNeeded = false;
- int s3dVideoFormat = 0;
- int numLayersNotUpdating = 0;
- bool useCopybit = false;
- bool isSkipLayerPresent = false;
- bool skipComposition = false;
-
- if (list) {
- useCopybit = canUseCopybit(hwcModule->fbDevice, list);
- yuvBufferCount = getYUVBufferCount(list);
- numLayersNotUpdating = getLayersNotUpdatingCount(list);
- skipComposition = canSkipComposition(ctx, yuvBufferCount,
- list->numHwLayers, numLayersNotUpdating);
-
- if (yuvBufferCount == 1) {
- s3dVideoFormat = getS3DVideoFormat(list);
- if (s3dVideoFormat)
- isS3DCompositionNeeded = isS3DCompositionRequired();
- } else if((s3dVideoFormat = getS3DFormat(list))){
- if (s3dVideoFormat)
- isS3DCompositionNeeded = isS3DCompositionRequired();
- } else {
- unlockPreviousOverlayBuffer(ctx);
- }
-
- if (list->flags & HWC_GEOMETRY_CHANGED) {
- if (yuvBufferCount == 1) {
- // Inform the gralloc of the current video overlay status
- setVideoOverlayStatusInGralloc(ctx, true);
- }
- }
-
- for (size_t i=0 ; i<list->numHwLayers ; i++) {
- private_handle_t *hnd = (private_handle_t *)list->hwLayers[i].handle;
-
- // If there is a single Fullscreen layer, we can bypass it - TBD
- // If there is only one video/camera buffer, we can bypass itn
- if (list->hwLayers[i].flags & HWC_SKIP_LAYER) {
- // During the animaton UI layers are marked as SKIP
- // need to still mark the layer for S3D composition
- isSkipLayerPresent = true;
- skipComposition = false;
- //Reset count, so that we end up composing once after animation
- //is over, in case of overlay.
- ctx->previousLayerCount = -1;
-
- if (isS3DCompositionNeeded)
- markUILayerForS3DComposition(list->hwLayers[i], s3dVideoFormat);
-
-// LGE_CHANGE_E, [G1_Player][bokyung.kim@lge.com], 20120201, Apply SR 00744210 to fix screen flicker {
- ssize_t layer_countdown = ((ssize_t)i) - 1;
- // Mark every layer below the SKIP layer to be composed by the GPU
- while (layer_countdown >= 0)
- {
- private_handle_t *countdown_handle =
- (private_handle_t *)list->hwLayers[layer_countdown].handle;
- if (countdown_handle && (countdown_handle->bufferType == BUFFER_TYPE_VIDEO)
- && (yuvBufferCount == 1)) {
- unlockPreviousOverlayBuffer(ctx);
- }
- list->hwLayers[layer_countdown].compositionType = HWC_FRAMEBUFFER;
- list->hwLayers[layer_countdown].hints &= ~HWC_HINT_CLEAR_FB;
- layer_countdown--;
- }
-// LGE_CHANGE_E, [G1_Player][bokyung.kim@lge.com], 20120201, Apply SR 00744210 to fix screen flicker }
- continue;
- }
- if (hnd && (hnd->bufferType == BUFFER_TYPE_VIDEO) && (yuvBufferCount == 1)) {
- int flags = WAIT_FOR_VSYNC;
- flags |= (hnd->flags &
- private_handle_t::PRIV_FLAGS_SECURE_BUFFER)?
- SECURE_OVERLAY_SESSION : 0;
- flags |= (1 == list->numHwLayers) ? DISABLE_FRAMEBUFFER_FETCH : 0;
- if (!isValidDestination(hwcModule->fbDevice, list->hwLayers[i].displayFrame)) {
- list->hwLayers[i].compositionType = HWC_FRAMEBUFFER;
- //Even though there are no skip layers, animation is still
- //ON and in its final stages.
- //Reset count, so that we end up composing once after animation
- //is done, if overlay is used.
- ctx->previousLayerCount = -1;
- skipComposition = false;
-#ifdef USE_OVERLAY
- } else if(prepareOverlay(ctx, &(list->hwLayers[i]), flags) == 0) {
- list->hwLayers[i].compositionType = HWC_USE_OVERLAY;
- list->hwLayers[i].hints |= HWC_HINT_CLEAR_FB;
- // We've opened the channel. Set the state to open.
- ctx->hwcOverlayStatus = HWC_OVERLAY_OPEN;
-#endif
- } else if (hwcModule->compositionType & (COMPOSITION_TYPE_C2D|
- COMPOSITION_TYPE_MDP)) {
- //Fail safe path: If drawing with overlay fails,
-
- //Use C2D if available.
- list->hwLayers[i].compositionType = HWC_USE_COPYBIT;
- } else {
- //If C2D is not enabled fall back to GPU.
- list->hwLayers[i].compositionType = HWC_FRAMEBUFFER;
- }
- if (HWC_USE_OVERLAY != list->hwLayers[i].compositionType) {
- unlockPreviousOverlayBuffer(ctx);
- skipComposition = false;
- }
- } else if (getLayerS3DFormat(list->hwLayers[i])) {
- int flags = WAIT_FOR_VSYNC;
- flags |= (1 == list->numHwLayers) ? DISABLE_FRAMEBUFFER_FETCH : 0;
- flags |= (hnd->flags &
- private_handle_t::PRIV_FLAGS_SECURE_BUFFER)?
- SECURE_OVERLAY_SESSION : 0;
-#ifdef USE_OVERLAY
- if(prepareOverlay(ctx, &(list->hwLayers[i]), flags) == 0) {
- list->hwLayers[i].compositionType = HWC_USE_OVERLAY;
- list->hwLayers[i].hints |= HWC_HINT_CLEAR_FB;
- // We've opened the channel. Set the state to open.
- ctx->hwcOverlayStatus = HWC_OVERLAY_OPEN;
- }
-#endif
- } else if (isS3DCompositionNeeded) {
- markUILayerForS3DComposition(list->hwLayers[i], s3dVideoFormat);
- } else if (list->hwLayers[i].flags & HWC_USE_ORIGINAL_RESOLUTION) {
- list->hwLayers[i].compositionType = HWC_USE_OVERLAY;
- list->hwLayers[i].hints |= HWC_HINT_CLEAR_FB;
- layerType |= HWC_ORIG_RESOLUTION;
- } else if (hnd && hnd->flags & private_handle_t::PRIV_FLAGS_EXTERNAL_ONLY) {
- //handle later after other layers are handled
- } else if (hnd && (hwcModule->compositionType &
- (COMPOSITION_TYPE_C2D|COMPOSITION_TYPE_MDP))) {
- list->hwLayers[i].compositionType = HWC_USE_COPYBIT;
- } else if ((hwcModule->compositionType == COMPOSITION_TYPE_DYN)
- && useCopybit) {
- list->hwLayers[i].compositionType = HWC_USE_COPYBIT;
- }
- else {
- list->hwLayers[i].compositionType = HWC_FRAMEBUFFER;
- }
- }
-
- //Update the stats and pipe config for external-only layers
- ExtDispOnly::update(ctx, list);
-
- if (skipComposition) {
- list->flags |= HWC_SKIP_COMPOSITION;
- } else {
- list->flags &= ~HWC_SKIP_COMPOSITION;
- }
-
-#ifdef COMPOSITION_BYPASS
- bool isBypassUsed = true;
- bool isDoable = isBypassDoable(dev, yuvBufferCount, list);
- //Check if bypass is feasible
- if(isDoable && !isSkipLayerPresent) {
- if(setupBypass(ctx, list)) {
- setBypassLayerFlags(ctx, list);
- ctx->bypassState = BYPASS_ON;
- } else {
- LOGE_IF(BYPASS_DEBUG,"%s: Bypass setup Failed",__FUNCTION__);
- isBypassUsed = false;
- }
- } else {
- LOGE_IF(BYPASS_DEBUG,"%s: Bypass not possible[%d,%d]",__FUNCTION__,
- isDoable, !isSkipLayerPresent );
- isBypassUsed = false;
- }
-
- //Reset bypass states
- if(!isBypassUsed) {
- ctx->nPipesUsed = 0;
- unsetBypassLayerFlags(list);
- if(ctx->bypassState == BYPASS_ON) {
- ctx->bypassState = BYPASS_OFF_PENDING;
- }
- }
-#endif
- } else {
-#ifdef COMPOSITION_BYPASS
- unlockPreviousBypassBuffers(ctx);
- unsetBypassBufferLockState(ctx);
-#endif
- unlockPreviousOverlayBuffer(ctx);
- }
- return 0;
-}
-// ---------------------------------------------------------------------------
-struct range {
- int current;
- int end;
-};
-struct region_iterator : public copybit_region_t {
-
- region_iterator(hwc_region_t region) {
- mRegion = region;
- r.end = region.numRects;
- r.current = 0;
- this->next = iterate;
- }
-
-private:
- static int iterate(copybit_region_t const * self, copybit_rect_t* rect) {
- if (!self || !rect) {
- LOGE("iterate invalid parameters");
- return 0;
- }
-
- region_iterator const* me = static_cast<region_iterator const*>(self);
- if (me->r.current != me->r.end) {
- rect->l = me->mRegion.rects[me->r.current].left;
- rect->t = me->mRegion.rects[me->r.current].top;
- rect->r = me->mRegion.rects[me->r.current].right;
- rect->b = me->mRegion.rects[me->r.current].bottom;
- me->r.current++;
- return 1;
- }
- return 0;
- }
-
- hwc_region_t mRegion;
- mutable range r;
-};
-
-static int drawLayerUsingCopybit(hwc_composer_device_t *dev, hwc_layer_t *layer, EGLDisplay dpy,
- EGLSurface surface)
-{
- hwc_context_t* ctx = (hwc_context_t*)(dev);
- if(!ctx) {
- LOGE("drawLayerUsingCopybit null context ");
- return -1;
- }
-
- private_hwc_module_t* hwcModule = reinterpret_cast<private_hwc_module_t*>(dev->common.module);
- if(!hwcModule) {
- LOGE("drawLayerUsingCopybit null module ");
- return -1;
- }
-
- private_handle_t *hnd = (private_handle_t *)layer->handle;
- if(!hnd) {
- LOGE("drawLayerUsingCopybit invalid handle");
- return -1;
- }
-
- // Lock this buffer for read.
- genlock_lock_type lockType = GENLOCK_READ_LOCK;
- int err = genlock_lock_buffer(hnd, lockType, GENLOCK_MAX_TIMEOUT);
- if (GENLOCK_FAILURE == err) {
- LOGE("%s: genlock_lock_buffer(READ) failed", __FUNCTION__);
- return -1;
- }
- //render buffer
- android_native_buffer_t *renderBuffer = (android_native_buffer_t *)eglGetRenderBufferANDROID(dpy, surface);
- if (!renderBuffer) {
- LOGE("eglGetRenderBufferANDROID returned NULL buffer");
- genlock_unlock_buffer(hnd);
- return -1;
- }
- private_handle_t *fbHandle = (private_handle_t *)renderBuffer->handle;
- if(!fbHandle) {
- LOGE("Framebuffer handle is NULL");
- genlock_unlock_buffer(hnd);
- return -1;
- }
- int alignment = 32;
- if( HAL_PIXEL_FORMAT_RGB_565 == fbHandle->format )
- alignment = 16;
- // Set the copybit source:
- copybit_image_t src;
- src.w = ALIGN(hnd->width, alignment);
- src.h = hnd->height;
- src.format = hnd->format;
- src.base = (void *)hnd->base;
- src.handle = (native_handle_t *)layer->handle;
- src.horiz_padding = src.w - hnd->width;
- // Initialize vertical padding to zero for now,
- // this needs to change to accomodate vertical stride
- // if needed in the future
- src.vert_padding = 0;
-
- // Copybit source rect
- hwc_rect_t sourceCrop = layer->sourceCrop;
- copybit_rect_t srcRect = {sourceCrop.left, sourceCrop.top,
- sourceCrop.right,
- sourceCrop.bottom};
-
- // Copybit destination rect
- hwc_rect_t displayFrame = layer->displayFrame;
- copybit_rect_t dstRect = {displayFrame.left, displayFrame.top,
- displayFrame.right,
- displayFrame.bottom};
-
- // Copybit dst
- copybit_image_t dst;
- dst.w = ALIGN(fbHandle->width,alignment);
- dst.h = fbHandle->height;
- dst.format = fbHandle->format;
- dst.base = (void *)fbHandle->base;
- dst.handle = (native_handle_t *)renderBuffer->handle;
-
- copybit_device_t *copybit = hwcModule->copybitEngine;
-
- int32_t screen_w = displayFrame.right - displayFrame.left;
- int32_t screen_h = displayFrame.bottom - displayFrame.top;
- int32_t src_crop_width = sourceCrop.right - sourceCrop.left;
- int32_t src_crop_height = sourceCrop.bottom -sourceCrop.top;
-
- float copybitsMaxScale = (float)copybit->get(copybit,COPYBIT_MAGNIFICATION_LIMIT);
- float copybitsMinScale = (float)copybit->get(copybit,COPYBIT_MINIFICATION_LIMIT);
-
- if((layer->transform == HWC_TRANSFORM_ROT_90) ||
- (layer->transform == HWC_TRANSFORM_ROT_270)) {
- //swap screen width and height
- int tmp = screen_w;
- screen_w = screen_h;
- screen_h = tmp;
- }
- private_handle_t *tmpHnd = NULL;
-
- if(screen_w <=0 || screen_h<=0 ||src_crop_width<=0 || src_crop_height<=0 ) {
- LOGE("%s: wrong params for display screen_w=%d src_crop_width=%d screen_w=%d \
- src_crop_width=%d", __FUNCTION__, screen_w,
- src_crop_width,screen_w,src_crop_width);
- genlock_unlock_buffer(hnd);
- return -1;
- }
-
- float dsdx = (float)screen_w/src_crop_width;
- float dtdy = (float)screen_h/src_crop_height;
-
- float scaleLimitMax = copybitsMaxScale * copybitsMaxScale;
- float scaleLimitMin = copybitsMinScale * copybitsMinScale;
- if(dsdx > scaleLimitMax || dtdy > scaleLimitMax || dsdx < 1/scaleLimitMin || dtdy < 1/scaleLimitMin) {
- LOGE("%s: greater than max supported size dsdx=%f dtdy=%f scaleLimitMax=%f scaleLimitMin=%f", __FUNCTION__,dsdx,dtdy,scaleLimitMax,1/scaleLimitMin);
- genlock_unlock_buffer(hnd);
- return -1;
- }
- if(dsdx > copybitsMaxScale || dtdy > copybitsMaxScale || dsdx < 1/copybitsMinScale || dtdy < 1/copybitsMinScale){
- // The requested scale is out of the range the hardware
- // can support.
- LOGD("%s:%d::Need to scale twice dsdx=%f, dtdy=%f,copybitsMaxScale=%f,copybitsMinScale=%f,screen_w=%d,screen_h=%d \
- src_crop_width=%d src_crop_height=%d",__FUNCTION__,__LINE__,
- dsdx,dtdy,copybitsMaxScale,1/copybitsMinScale,screen_w,screen_h,src_crop_width,src_crop_height);
-
- //Driver makes width and height as even
- //that may cause wrong calculation of the ratio
- //in display and crop.Hence we make
- //crop width and height as even.
- src_crop_width = (src_crop_width/2)*2;
- src_crop_height = (src_crop_height/2)*2;
-
- int tmp_w = src_crop_width;
- int tmp_h = src_crop_height;
-
- if (dsdx > copybitsMaxScale || dtdy > copybitsMaxScale ){
- tmp_w = src_crop_width*copybitsMaxScale;
- tmp_h = src_crop_height*copybitsMaxScale;
- }else if (dsdx < 1/copybitsMinScale ||dtdy < 1/copybitsMinScale ){
- tmp_w = src_crop_width/copybitsMinScale;
- tmp_h = src_crop_height/copybitsMinScale;
- tmp_w = (tmp_w/2)*2;
- tmp_h = (tmp_h/2)*2;
- }
- LOGD("%s:%d::tmp_w = %d,tmp_h = %d",__FUNCTION__,__LINE__,tmp_w,tmp_h);
-
- int usage = GRALLOC_USAGE_PRIVATE_ADSP_HEAP |
- GRALLOC_USAGE_PRIVATE_MM_HEAP;
-
- if (0 == alloc_buffer(&tmpHnd, tmp_w, tmp_h, fbHandle->format, usage)){
- copybit_image_t tmp_dst;
- copybit_rect_t tmp_rect;
- tmp_dst.w = tmp_w;
- tmp_dst.h = tmp_h;
- tmp_dst.format = tmpHnd->format;
- tmp_dst.handle = tmpHnd;
- tmp_dst.horiz_padding = src.horiz_padding;
- tmp_dst.vert_padding = src.vert_padding;
- tmp_rect.l = 0;
- tmp_rect.t = 0;
- tmp_rect.r = tmp_dst.w;
- tmp_rect.b = tmp_dst.h;
- //create one clip region
- hwc_rect tmp_hwc_rect = {0,0,tmp_rect.r,tmp_rect.b};
- hwc_region_t tmp_hwc_reg = {1,(hwc_rect_t const*)&tmp_hwc_rect};
- region_iterator tmp_it(tmp_hwc_reg);
- copybit->set_parameter(copybit,COPYBIT_TRANSFORM,0);
- copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA,
- (layer->blending == HWC_BLENDING_NONE) ? -1 : layer->alpha);
- err = copybit->stretch(copybit,&tmp_dst, &src, &tmp_rect, &srcRect, &tmp_it);
- if(err < 0){
- LOGE("%s:%d::tmp copybit stretch failed",__FUNCTION__,__LINE__);
- if(tmpHnd)
- free_buffer(tmpHnd);
- genlock_unlock_buffer(hnd);
- return err;
- }
- // copy new src and src rect crop
- src = tmp_dst;
- srcRect = tmp_rect;
- }
- }
- // Copybit region
- hwc_region_t region = layer->visibleRegionScreen;
- region_iterator copybitRegion(region);
-
- copybit->set_parameter(copybit, COPYBIT_FRAMEBUFFER_WIDTH, renderBuffer->width);
- copybit->set_parameter(copybit, COPYBIT_FRAMEBUFFER_HEIGHT, renderBuffer->height);
- copybit->set_parameter(copybit, COPYBIT_TRANSFORM, layer->transform);
- copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA,
- (layer->blending == HWC_BLENDING_NONE) ? -1 : layer->alpha);
- copybit->set_parameter(copybit, COPYBIT_PREMULTIPLIED_ALPHA,
- (layer->blending == HWC_BLENDING_PREMULT)? COPYBIT_ENABLE : COPYBIT_DISABLE);
- copybit->set_parameter(copybit, COPYBIT_DITHER,
- (dst.format == HAL_PIXEL_FORMAT_RGB_565)? COPYBIT_ENABLE : COPYBIT_DISABLE);
- err = copybit->stretch(copybit, &dst, &src, &dstRect, &srcRect, ©bitRegion);
-
- if(tmpHnd)
- free_buffer(tmpHnd);
-
- if(err < 0)
- LOGE("%s: copybit stretch failed",__FUNCTION__);
-
- // Unlock this buffer since copybit is done with it.
- err = genlock_unlock_buffer(hnd);
- if (GENLOCK_FAILURE == err) {
- LOGE("%s: genlock_unlock_buffer failed", __FUNCTION__);
- }
-
- return err;
-}
-
-static int drawLayerUsingOverlay(hwc_context_t *ctx, hwc_layer_t *layer)
-{
- if (ctx && ctx->mOverlayLibObject) {
- private_hwc_module_t* hwcModule = reinterpret_cast<private_hwc_module_t*>(ctx->device.common.module);
- if (!hwcModule) {
- LOGE("drawLayerUsingLayer null module ");
- return -1;
- }
- private_handle_t *hnd = (private_handle_t *)layer->handle;
- overlay::Overlay *ovLibObject = ctx->mOverlayLibObject;
- int ret = 0;
-
- // Lock this buffer for read.
- if (GENLOCK_NO_ERROR != genlock_lock_buffer(hnd, GENLOCK_READ_LOCK,
- GENLOCK_MAX_TIMEOUT)) {
- LOGE("%s: genlock_lock_buffer(READ) failed", __FUNCTION__);
- return -1;
- }
-
- ret = ovLibObject->queueBuffer(hnd);
-
- // Unlock the previously locked buffer, since the overlay has completed reading the buffer
- unlockPreviousOverlayBuffer(ctx);
-
- if (!ret) {
- LOGE("drawLayerUsingOverlay queueBuffer failed");
- // Unlock the buffer handle
- genlock_unlock_buffer(hnd);
- ctx->previousOverlayHandle = NULL;
- } else {
- // Store the current buffer handle as the one that is to be unlocked after
- // the next overlay play call.
- ctx->previousOverlayHandle = hnd;
- hnd->flags |= private_handle_t::PRIV_FLAGS_HWC_LOCK;
- }
-
- return ret;
- }
- return -1;
-}
-
-#ifdef COMPOSITION_BYPASS
-static int drawLayerUsingBypass(hwc_context_t *ctx, hwc_layer_t *layer, int layer_index) {
-
- int index = getLayerbypassIndex(layer);
-
- if(index < 0) {
- LOGE("%s: Invalid bypass index (%d)", __FUNCTION__, index);
- return -1;
- }
-
- if (ctx && ctx->mOvUI[index]) {
- overlay::OverlayUI *ovUI = ctx->mOvUI[index];
- int ret = 0;
-
- private_handle_t *hnd = (private_handle_t *)layer->handle;
- if(!hnd) {
- LOGE("%s handle null", __FUNCTION__);
- return -1;
- }
-
- ctx->bypassBufferLockState[index] = BYPASS_BUFFER_UNLOCKED;
-
- if (GENLOCK_FAILURE == genlock_lock_buffer(hnd, GENLOCK_READ_LOCK,
- GENLOCK_MAX_TIMEOUT)) {
- LOGE("%s: genlock_lock_buffer(READ) failed", __FUNCTION__);
- return -1;
- }
-
- ctx->bypassBufferLockState[index] = BYPASS_BUFFER_LOCKED;
-
- LOGE_IF(BYPASS_DEBUG,"%s: Bypassing layer: %p using pipe: %d",__FUNCTION__, layer, index );
-
- ret = ovUI->queueBuffer(hnd);
-
- if (ret) {
- // Unlock the locked buffer
- if (GENLOCK_FAILURE == genlock_unlock_buffer(hnd)) {
- LOGE("%s: genlock_unlock_buffer failed", __FUNCTION__);
- }
- ctx->bypassBufferLockState[index] = BYPASS_BUFFER_UNLOCKED;
- return -1;
- }
- }
- return 0;
-}
-#endif
-
-static int hwc_set(hwc_composer_device_t *dev,
- hwc_display_t dpy,
- hwc_surface_t sur,
- hwc_layer_list_t* list)
-{
- hwc_context_t* ctx = (hwc_context_t*)(dev);
- if(!ctx) {
- LOGE("hwc_set invalid context");
- ExtDispOnly::close();
- return -1;
- }
-
- private_hwc_module_t* hwcModule = reinterpret_cast<private_hwc_module_t*>(
- dev->common.module);
- if (!hwcModule) {
- LOGE("hwc_set invalid module");
-#ifdef COMPOSITION_BYPASS
- unlockPreviousBypassBuffers(ctx);
- unsetBypassBufferLockState(ctx);
-#endif
- ExtDispOnly::close();
- unlockPreviousOverlayBuffer(ctx);
- return -1;
- }
-
- int ret = 0;
- if (list) {
- bool bDumpLayers = needToDumpLayers(); // Check need for debugging dumps
- for (size_t i=0; i<list->numHwLayers; i++) {
- if (bDumpLayers)
- dumpLayer(hwcModule->compositionType, list->flags, i, list->hwLayers);
- if (list->hwLayers[i].flags & HWC_SKIP_LAYER) {
- continue;
- } else if(list->hwLayers[i].flags & HWC_USE_EXT_ONLY) {
- continue;
- //Draw after layers for primary are drawn
-#ifdef COMPOSITION_BYPASS
- } else if (list->hwLayers[i].flags & HWC_COMP_BYPASS) {
- drawLayerUsingBypass(ctx, &(list->hwLayers[i]), i);
-#endif
- } else if (list->hwLayers[i].compositionType == HWC_USE_OVERLAY) {
- drawLayerUsingOverlay(ctx, &(list->hwLayers[i]));
- } else if (list->flags & HWC_SKIP_COMPOSITION) {
-// LGE_CHANGE_S, [G1_Player][mukyung.jung@lge.com], 20120206, Apply SR 00718706 to fix noise of QCIF contents {
- //break;
- continue;
-// LGE_CHANGE_E, [G1_Player][mukyung.jung@lge.com], 20120206, Apply SR 00718706 to fix noise of QCIF contents }
- } else if (list->hwLayers[i].compositionType == HWC_USE_COPYBIT) {
- drawLayerUsingCopybit(dev, &(list->hwLayers[i]), (EGLDisplay)dpy, (EGLSurface)sur);
- }
- }
- } else {
- //Device in suspended state. Close all the MDP pipes
-#ifdef COMPOSITION_BYPASS
- ctx->nPipesUsed = 0;
-#endif
- ctx->hwcOverlayStatus = HWC_OVERLAY_PREPARE_TO_CLOSE;
- }
-
- bool canSkipComposition = list && list->flags & HWC_SKIP_COMPOSITION;
- //Draw External-only layers
- if(ExtDispOnly::draw(ctx, list) != overlay::NO_ERROR) {
- ExtDispOnly::close();
- }
-
-#ifdef COMPOSITION_BYPASS
- unlockPreviousBypassBuffers(ctx);
- storeLockedBypassHandle(list, ctx);
- // We have stored the handles, unset the current lock states in the context.
- unsetBypassBufferLockState(ctx);
- closeExtraPipes(ctx);
-#if BYPASS_DEBUG
- if(canSkipComposition)
- LOGE("%s: skipping eglSwapBuffer call", __FUNCTION__);
-#endif
-#endif
- // Do not call eglSwapBuffers if we the skip composition flag is set on the list.
- if (dpy && sur && !canSkipComposition) {
- EGLBoolean sucess = eglSwapBuffers((EGLDisplay)dpy, (EGLSurface)sur);
- if (!sucess) {
- ret = HWC_EGL_ERROR;
- } else {
- CALC_FPS();
- }
- }
-#if defined HDMI_DUAL_DISPLAY
- if(ctx->pendingHDMI) {
- handleHDMIStateChange(dev, ctx->mHDMIEnabled);
- ctx->pendingHDMI = false;
- }
-#endif
-
- hwc_closeOverlayChannels(ctx);
- int yuvBufferCount = getYUVBufferCount(list);
- setHWCOverlayStatus(ctx, yuvBufferCount);
-
- return ret;
-}
-
-static int hwc_device_close(struct hw_device_t *dev)
-{
- if(!dev) {
- LOGE("hwc_device_close null device pointer");
- return -1;
- }
-
- struct hwc_context_t* ctx = (struct hwc_context_t*)dev;
-
- private_hwc_module_t* hwcModule = reinterpret_cast<private_hwc_module_t*>(
- ctx->device.common.module);
- // Close the overlay and copybit modules
- if(hwcModule->copybitEngine) {
- copybit_close(hwcModule->copybitEngine);
- hwcModule->copybitEngine = NULL;
- }
- if(hwcModule->fbDevice) {
- framebuffer_close(hwcModule->fbDevice);
- hwcModule->fbDevice = NULL;
- }
-
- unlockPreviousOverlayBuffer(ctx);
-
- if (ctx) {
- delete ctx->mOverlayLibObject;
- ctx->mOverlayLibObject = NULL;
-#ifdef COMPOSITION_BYPASS
- for(int i = 0; i < MAX_BYPASS_LAYERS; i++) {
- delete ctx->mOvUI[i];
- }
- unlockPreviousBypassBuffers(ctx);
- unsetBypassBufferLockState(ctx);
-#endif
- ExtDispOnly::close();
- ExtDispOnly::destroy();
-
- free(ctx);
- }
- return 0;
-}
-
-/*****************************************************************************/
-static int hwc_module_initialize(struct private_hwc_module_t* hwcModule)
-{
-
- // Open the overlay and copybit modules
- hw_module_t const *module;
- if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &module) == 0) {
- copybit_open(module, &(hwcModule->copybitEngine));
- }
- if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) {
- framebuffer_open(module, &(hwcModule->fbDevice));
- }
-
- // get the current composition type
- char property[PROPERTY_VALUE_MAX];
- if (property_get("debug.sf.hw", property, NULL) > 0) {
- if(atoi(property) == 0) {
- //debug.sf.hw = 0
- hwcModule->compositionType = COMPOSITION_TYPE_CPU;
- } else { //debug.sf.hw = 1
- // Get the composition type
- property_get("debug.composition.type", property, NULL);
- if (property == NULL) {
- hwcModule->compositionType = COMPOSITION_TYPE_GPU;
- } else if ((strncmp(property, "mdp", 3)) == 0) {
- hwcModule->compositionType = COMPOSITION_TYPE_MDP;
- } else if ((strncmp(property, "c2d", 3)) == 0) {
- hwcModule->compositionType = COMPOSITION_TYPE_C2D;
- } else if ((strncmp(property, "dyn", 3)) == 0) {
- hwcModule->compositionType = COMPOSITION_TYPE_DYN;
- } else {
- hwcModule->compositionType = COMPOSITION_TYPE_GPU;
- }
-
- if(!hwcModule->copybitEngine)
- hwcModule->compositionType = COMPOSITION_TYPE_GPU;
- }
- } else { //debug.sf.hw is not set. Use cpu composition
- hwcModule->compositionType = COMPOSITION_TYPE_CPU;
- }
-
- //Check if composition bypass is enabled
- if(property_get("ro.sf.compbypass.enable", property, NULL) > 0) {
- if(atoi(property) == 1) {
- hwcModule->isBypassEnabled = true;
- }
- }
-
- CALC_INIT();
-
- return 0;
-}
-
-
-static int hwc_device_open(const struct hw_module_t* module, const char* name,
- struct hw_device_t** device)
-{
- int status = -EINVAL;
-
- if (!strcmp(name, HWC_HARDWARE_COMPOSER)) {
- private_hwc_module_t* hwcModule = reinterpret_cast<private_hwc_module_t*>
- (const_cast<hw_module_t*>(module));
- hwc_module_initialize(hwcModule);
- struct hwc_context_t *dev;
- dev = (hwc_context_t*)malloc(sizeof(*dev));
-
- /* initialize our state here */
- memset(dev, 0, sizeof(*dev));
-#ifdef USE_OVERLAY
- dev->mOverlayLibObject = new overlay::Overlay();
- if(overlay::initOverlay() == -1)
- LOGE("overlay::initOverlay() ERROR!!");
-#else
- dev->mOverlayLibObject = NULL;
-#endif
-#ifdef COMPOSITION_BYPASS
- for(int i = 0; i < MAX_BYPASS_LAYERS; i++) {
- dev->mOvUI[i] = new overlay::OverlayUI();
- dev->previousBypassHandle[i] = NULL;
- }
- unsetBypassBufferLockState(dev);
- dev->bypassState = BYPASS_OFF;
-#endif
- ExtDispOnly::init();
-#if defined HDMI_DUAL_DISPLAY
- dev->mHDMIEnabled = EXT_DISPLAY_OFF;
- dev->pendingHDMI = false;
-#endif
- dev->previousOverlayHandle = NULL;
- dev->hwcOverlayStatus = HWC_OVERLAY_CLOSED;
- dev->previousLayerCount = -1;
- /* initialize the procs */
- dev->device.common.tag = HARDWARE_DEVICE_TAG;
- dev->device.common.version = 0;
- dev->device.common.module = const_cast<hw_module_t*>(module);
- dev->device.common.close = hwc_device_close;
-
- dev->device.prepare = hwc_prepare;
- dev->device.set = hwc_set;
- dev->device.enableHDMIOutput = hwc_enableHDMIOutput;
- *device = &dev->device.common;
-
- status = 0;
- }
- return status;
-}
diff --git a/liboverlay/Android.mk b/liboverlay/Android.mk
old mode 100755
new mode 100644
index 79e4256..63d7780
--- a/liboverlay/Android.mk
+++ b/liboverlay/Android.mk
@@ -1,43 +1,20 @@
-# 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)
-
include $(CLEAR_VARS)
-LOCAL_PRELINK_MODULE := false
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)
-LOCAL_SHARED_LIBRARIES := liblog libcutils libutils libmemalloc
-LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
-LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
-LOCAL_C_INCLUDES += hardware/qcom/display/libgralloc
+LOCAL_SHARED_LIBRARIES := liblog
+LOCAL_SHARED_LIBRARIES += libcutils
+LOCAL_SHARED_LIBRARIES += libutils
+LOCAL_SHARED_LIBRARIES += libmemalloc
+LOCAL_C_INCLUDES := hardware/qcom/display/libgralloc
LOCAL_SRC_FILES := \
- overlayLib.cpp \
- overlayLibUI.cpp \
-LOCAL_CFLAGS:= -DLOG_TAG=\"OverlayLib\"
+ overlay.cpp \
+ overlayCtrl.cpp \
+ overlayUtils.cpp \
+ overlayMdp.cpp \
+ overlayRotator.cpp \
+ overlayTransitions.cpp
-ifeq ($(TARGET_USE_HDMI_AS_PRIMARY),true)
-LOCAL_CFLAGS += -DHDMI_AS_PRIMARY
-endif
-ifeq ($(TARGET_USES_POST_PROCESSING),true)
-LOCAL_CFLAGS += -DUSES_POST_PROCESSING
-LOCAL_SHARED_LIBRARIES += libmm-abl
-LOCAL_C_INCLUDES += $(TARGET_OUT_HEADERS)/pp/inc
-LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/lib/
-endif
+LOCAL_CFLAGS:= -DLOG_TAG=\"overlay2\"
LOCAL_MODULE := liboverlay
-
-#LGE_CHANGE, for userdebug mode
LOCAL_MODULE_TAGS := optional
include $(BUILD_SHARED_LIBRARY)
diff --git a/liboverlay/mdpWrapper.h b/liboverlay/mdpWrapper.h
new file mode 100644
index 0000000..4cfd3e0
--- /dev/null
+++ b/liboverlay/mdpWrapper.h
@@ -0,0 +1,270 @@
+/*
+* Copyright (c) 2011-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 MDP_WRAPPER_H
+#define MDP_WRAPPER_H
+
+/*
+* In order to make overlay::mdp_wrapper shorter, please do something like:
+* namespace mdpwrap = overlay::mdp_wrapper;
+* */
+
+#include <linux/msm_mdp.h>
+#include <linux/msm_rotator.h>
+#include <sys/ioctl.h>
+#include <utils/Log.h>
+#include <errno.h>
+#include "overlayUtils.h"
+
+namespace overlay{
+
+namespace mdp_wrapper{
+/* FBIOGET_FSCREENINFO */
+bool getFScreenInfo(int fd, fb_fix_screeninfo& finfo);
+
+/* FBIOGET_VSCREENINFO */
+bool getVScreenInfo(int fd, fb_var_screeninfo& vinfo);
+
+/* FBIOPUT_VSCREENINFO */
+bool setVScreenInfo(int fd, fb_var_screeninfo& vinfo);
+
+/* MSM_ROTATOR_IOCTL_START */
+bool startRotator(int fd, msm_rotator_img_info& rot);
+
+/* MSM_ROTATOR_IOCTL_ROTATE */
+bool rotate(int fd, msm_rotator_data_info& rot);
+
+/* MSMFB_OVERLAY_SET */
+bool setOverlay(int fd, mdp_overlay& ov);
+
+/* MSM_ROTATOR_IOCTL_FINISH */
+bool endRotator(int fd, int sessionId);
+
+/* MSMFB_OVERLAY_UNSET */
+bool unsetOverlay(int fd, int ovId);
+
+/* MSMFB_OVERLAY_GET */
+bool getOverlay(int fd, mdp_overlay& ov);
+
+/* MSMFB_OVERLAY_PLAY */
+bool play(int fd, msmfb_overlay_data& od);
+
+/* MSMFB_OVERLAY_PLAY_WAIT */
+bool playWait(int fd, msmfb_overlay_data& od);
+
+/* MSMFB_OVERLAY_3D */
+bool set3D(int fd, msmfb_overlay_3d& ov);
+
+/* the following are helper functions for dumping
+ * msm_mdp and friends*/
+void dump(const char* const s, const msmfb_overlay_data& ov);
+void dump(const char* const s, const msmfb_data& ov);
+void dump(const char* const s, const mdp_overlay& ov);
+void dump(const char* const s, const msmfb_overlay_3d& ov);
+void dump(const char* const s, const uint32_t u[], uint32_t cnt);
+void dump(const char* const s, const msmfb_img& ov);
+void dump(const char* const s, const mdp_rect& ov);
+
+/* and rotator */
+void dump(const char* const s, const msm_rotator_img_info& rot);
+void dump(const char* const s, const msm_rotator_data_info& rot);
+
+/* info */
+void dump(const char* const s, const fb_fix_screeninfo& finfo);
+void dump(const char* const s, const fb_var_screeninfo& vinfo);
+
+//---------------Inlines -------------------------------------
+
+inline bool getFScreenInfo(int fd, fb_fix_screeninfo& finfo) {
+ if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1) {
+ ALOGE("Failed to call ioctl FBIOGET_FSCREENINFO err=%d", errno);
+ return false;
+ }
+ return true;
+}
+
+inline bool getVScreenInfo(int fd, fb_var_screeninfo& vinfo) {
+ if (ioctl(fd, FBIOGET_VSCREENINFO, &vinfo) == -1) {
+ ALOGE("Failed to call ioctl FBIOGET_VSCREENINFO err=%d", errno);
+ return false;
+ }
+ return true;
+}
+
+inline bool setVScreenInfo(int fd, fb_var_screeninfo& vinfo) {
+ if (ioctl(fd, FBIOPUT_VSCREENINFO, &vinfo) == -1) {
+ ALOGE("Failed to call ioctl FBIOPUT_VSCREENINFO err=%d", errno);
+ return false;
+ }
+ return true;
+}
+
+inline bool startRotator(int fd, msm_rotator_img_info& rot) {
+ if (ioctl(fd, MSM_ROTATOR_IOCTL_START, &rot) == -1){
+ ALOGE("Failed to call ioctl MSM_ROTATOR_IOCTL_START err=%d", errno);
+ return false;
+ }
+ return true;
+}
+
+inline bool rotate(int fd, msm_rotator_data_info& rot) {
+ if (ioctl(fd, MSM_ROTATOR_IOCTL_ROTATE, &rot) == -1) {
+ ALOGE("Failed to call ioctl MSM_ROTATOR_IOCTL_ROTATE err=%d", errno);
+ return false;
+ }
+ return true;
+}
+
+inline bool setOverlay(int fd, mdp_overlay& ov) {
+ if (ioctl(fd, MSMFB_OVERLAY_SET, &ov) == -1) {
+ ALOGE("Failed to call ioctl MSMFB_OVERLAY_SET err=%d", errno);
+ return false;
+ }
+ return true;
+}
+
+inline bool endRotator(int fd, int sessionId) {
+ if (ioctl(fd, MSM_ROTATOR_IOCTL_FINISH, &sessionId) == -1) {
+ ALOGE("Failed to call ioctl MSM_ROTATOR_IOCTL_FINISH err=%d", errno);
+ return false;
+ }
+ return true;
+}
+
+inline bool unsetOverlay(int fd, int ovId) {
+ if (ioctl(fd, MSMFB_OVERLAY_UNSET, &ovId) == -1) {
+ ALOGE("Failed to call ioctl MSMFB_OVERLAY_UNSET err=%d", errno);
+ return false;
+ }
+ return true;
+}
+
+inline bool getOverlay(int fd, mdp_overlay& ov) {
+ if (ioctl(fd, MSMFB_OVERLAY_GET, &ov) == -1) {
+ ALOGE("Failed to call ioctl MSMFB_OVERLAY_GET err=%d", errno);
+ return false;
+ }
+ return true;
+}
+
+inline bool play(int fd, msmfb_overlay_data& od) {
+ if (ioctl(fd, MSMFB_OVERLAY_PLAY, &od) == -1) {
+ ALOGE("Failed to call ioctl MSMFB_OVERLAY_PLAY err=%d", errno);
+ return false;
+ }
+ return true;
+}
+
+inline bool playWait(int fd, msmfb_overlay_data& od) {
+ if (ioctl(fd, MSMFB_OVERLAY_PLAY_WAIT, &od) == -1) {
+ ALOGE("Failed to call ioctl MSMFB_OVERLAY_PLAY_WAIT err=%d", errno);
+ return false;
+ }
+ return true;
+}
+
+inline bool set3D(int fd, msmfb_overlay_3d& ov) {
+ if (ioctl(fd, MSMFB_OVERLAY_3D, &ov) == -1) {
+ ALOGE("Failed to call ioctl MSMFB_OVERLAY_3D err=%d", errno);
+ return false;
+ }
+ return true;
+}
+
+/* dump funcs */
+inline void dump(const char* const s, const msmfb_overlay_data& ov) {
+ ALOGE("%s msmfb_overlay_data id=%d",
+ s, ov.id);
+ dump("data", ov.data);
+}
+inline void dump(const char* const s, const msmfb_data& ov) {
+ ALOGE("%s msmfb_data offset=%d memid=%d id=%d flags=0x%x priv=%d",
+ s, ov.offset, ov.memory_id, ov.id, ov.flags, ov.priv);
+}
+inline void dump(const char* const s, const mdp_overlay& ov) {
+ ALOGE("%s mdp_overlay z=%d fg=%d alpha=%d mask=%d flags=0x%x id=%d",
+ s, ov.z_order, ov.is_fg, ov.alpha,
+ ov.transp_mask, ov.flags, ov.id);
+ dump("src", ov.src);
+ dump("src_rect", ov.src_rect);
+ dump("dst_rect", ov.dst_rect);
+ dump("user_data", ov.user_data,
+ sizeof(ov.user_data)/sizeof(ov.user_data[0]));
+}
+inline void dump(const char* const s, const msmfb_img& ov) {
+ ALOGE("%s msmfb_img w=%d h=%d format=%d %s",
+ s, ov.width, ov.height, ov.format,
+ overlay::utils::getFormatString(ov.format));
+}
+inline void dump(const char* const s, const mdp_rect& ov) {
+ ALOGE("%s mdp_rect x=%d y=%d w=%d h=%d",
+ s, ov.x, ov.y, ov.w, ov.h);
+}
+
+inline void dump(const char* const s, const msmfb_overlay_3d& ov) {
+ ALOGE("%s msmfb_overlay_3d 3d=%d w=%d h=%d",
+ s, ov.is_3d, ov.width, ov.height);
+
+}
+inline void dump(const char* const s, const uint32_t u[], uint32_t cnt) {
+ ALOGE("%s user_data cnt=%d", s, cnt);
+ for(uint32_t i=0; i < cnt; ++i) {
+ ALOGE("i=%d val=%d", i, u[i]);
+ }
+}
+inline void dump(const char* const s, const msm_rotator_img_info& rot) {
+ ALOGE("%s msm_rotator_img_info sessid=%d dstx=%d dsty=%d rot=%d, ena=%d",
+ s, rot.session_id, rot.dst_x, rot.dst_y,
+ rot.rotations, rot.enable);
+ dump("src", rot.src);
+ dump("dst", rot.dst);
+ dump("src_rect", rot.src_rect);
+}
+inline void dump(const char* const s, const msm_rotator_data_info& rot) {
+ ALOGE("%s msm_rotator_data_info sessid=%d verkey=%d",
+ s, rot.session_id, rot.version_key);
+ dump("src", rot.src);
+ dump("dst", rot.dst);
+ dump("src_chroma", rot.src_chroma);
+ dump("dst_chroma", rot.dst_chroma);
+}
+inline void dump(const char* const s, const fb_fix_screeninfo& finfo) {
+ ALOGE("%s fb_fix_screeninfo type=%d", s, finfo.type);
+}
+inline void dump(const char* const s, const fb_var_screeninfo& vinfo) {
+ ALOGE("%s fb_var_screeninfo xres=%d yres=%d",
+ s, vinfo.xres, vinfo.yres);
+}
+
+
+} // mdp_wrapper
+
+} // overlay
+
+#endif // MDP_WRAPPER_H
diff --git a/liboverlay/overlay.cpp b/liboverlay/overlay.cpp
new file mode 100644
index 0000000..ed968c1
--- /dev/null
+++ b/liboverlay/overlay.cpp
@@ -0,0 +1,455 @@
+/*
+* Copyright (c) 2011-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.
+*/
+
+#include "overlayUtils.h"
+#include "overlayImpl.h"
+#include "overlay.h"
+
+// MDP related FIXME move to state
+#include "overlayMdp.h"
+#include "overlayCtrlData.h"
+#include "overlayRotator.h"
+
+namespace overlay {
+
+Overlay::Overlay(): mOv(0) {
+}
+
+Overlay::~Overlay() {
+ if(mState.state() == utils::OV_CLOSED) return;
+ close();
+ delete mOv;
+ mOv = 0;
+}
+
+bool Overlay::open() {
+ // We need an empty open to just open the bare minimum for business
+ return true;
+}
+
+void Overlay::reset(){
+ if(mOv && !mOv->close()) {
+ ALOGE("%s Overlay failed", __FUNCTION__);
+ }
+
+ delete mOv;
+ mOv = 0;
+}
+
+bool Overlay::close()
+{
+ OVASSERT(mOv,
+ "%s Overlay and Rotator should be init at this point",
+ __FUNCTION__);
+ // FIXME that one needs to move to the state machine class
+ utils::eOverlayState st = mState.state();
+ switch (st) {
+ case utils::OV_CLOSED:
+ // try to close any partially opened items
+ break;
+ case utils::OV_2D_VIDEO_ON_PANEL:
+ case utils::OV_2D_VIDEO_ON_PANEL_TV:
+ case utils::OV_3D_VIDEO_ON_2D_PANEL:
+ case utils::OV_3D_VIDEO_ON_3D_PANEL:
+ case utils::OV_3D_VIDEO_ON_3D_TV:
+ case utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV:
+ case utils::OV_UI_MIRROR:
+ case utils::OV_2D_TRUE_UI_MIRROR:
+ case utils::OV_BYPASS_1_LAYER:
+ case utils::OV_BYPASS_2_LAYER:
+ case utils::OV_BYPASS_3_LAYER:
+ mOv = mState.handleEvent(utils::OV_CLOSED, mOv);
+ this->reset();
+ break;
+ default:
+ OVASSERT(false, "close Unknown state %d", st);
+ return false;
+ }
+ return true;
+}
+
+bool Overlay::commit(utils::eDest dest)
+{
+ OVASSERT(mOv,
+ "%s Overlay and Rotator should be init at this point",
+ __FUNCTION__);
+ // FIXME that one needs to move to the state machine class
+ utils::eOverlayState st = mState.state();
+ switch (st) {
+ case utils::OV_2D_VIDEO_ON_PANEL:
+ case utils::OV_2D_VIDEO_ON_PANEL_TV:
+ case utils::OV_3D_VIDEO_ON_2D_PANEL:
+ case utils::OV_3D_VIDEO_ON_3D_PANEL:
+ case utils::OV_3D_VIDEO_ON_3D_TV:
+ case utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV:
+ case utils::OV_UI_MIRROR:
+ case utils::OV_2D_TRUE_UI_MIRROR:
+ case utils::OV_BYPASS_1_LAYER:
+ case utils::OV_BYPASS_2_LAYER:
+ case utils::OV_BYPASS_3_LAYER:
+ if(!mOv->commit(dest)) {
+ ALOGE("Overlay %s failed", __FUNCTION__);
+ return false;
+ }
+ break;
+ default:
+ OVASSERT(false, "%s Unknown state %d", __FUNCTION__, st);
+ return false;
+ }
+ return true;
+}
+
+bool Overlay::queueBuffer(uint32_t offset,
+ utils::eDest dest)
+{
+ OVASSERT(mOv,
+ "%s Overlay and Rotator should be init at this point",
+ __FUNCTION__);
+ // FIXME that one needs to move to the state machine class
+ utils::eOverlayState st = mState.state();
+ switch (st) {
+ case utils::OV_2D_VIDEO_ON_PANEL:
+ case utils::OV_2D_VIDEO_ON_PANEL_TV:
+ case utils::OV_3D_VIDEO_ON_2D_PANEL:
+ case utils::OV_3D_VIDEO_ON_3D_PANEL:
+ case utils::OV_3D_VIDEO_ON_3D_TV:
+ case utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV:
+ case utils::OV_UI_MIRROR:
+ case utils::OV_2D_TRUE_UI_MIRROR:
+ case utils::OV_BYPASS_1_LAYER:
+ case utils::OV_BYPASS_2_LAYER:
+ case utils::OV_BYPASS_3_LAYER:
+ if(!mOv->queueBuffer(offset, dest)) {
+ ALOGE("Overlay %s failed", __FUNCTION__);
+ return false;
+ }
+ break;
+ default:
+ OVASSERT(false, "%s Unknown state %d", __FUNCTION__, st);
+ return false;
+ }
+ return true;
+}
+
+bool Overlay::dequeueBuffer(void*& buf,
+ utils::eDest dest)
+{
+ OVASSERT(mOv,
+ "%s Overlay and Rotator should be init at this point",
+ __FUNCTION__);
+ // FIXME that one needs to move to the state machine class
+ utils::eOverlayState st = mState.state();
+ switch (st) {
+ case utils::OV_2D_VIDEO_ON_PANEL:
+ case utils::OV_2D_VIDEO_ON_PANEL_TV:
+ case utils::OV_3D_VIDEO_ON_2D_PANEL:
+ case utils::OV_3D_VIDEO_ON_3D_PANEL:
+ case utils::OV_3D_VIDEO_ON_3D_TV:
+ case utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV:
+ case utils::OV_UI_MIRROR:
+ case utils::OV_2D_TRUE_UI_MIRROR:
+ case utils::OV_BYPASS_1_LAYER:
+ case utils::OV_BYPASS_2_LAYER:
+ case utils::OV_BYPASS_3_LAYER:
+ if(!mOv->dequeueBuffer(buf, dest)) {
+ ALOGE("Overlay %s failed", __FUNCTION__);
+ return false;
+ }
+ break;
+ default:
+ OVASSERT(false, "%s Unknown state %d", __FUNCTION__, st);
+ return false;
+ }
+ return true;
+}
+
+bool Overlay::waitForVsync(utils::eDest dest)
+{
+ OVASSERT(mOv,
+ "%s Overlay and Rotator should be init at this point",
+ __FUNCTION__);
+ // FIXME that one needs to move to the state machine class
+ utils::eOverlayState st = mState.state();
+ switch (st) {
+ case utils::OV_2D_VIDEO_ON_PANEL:
+ case utils::OV_2D_VIDEO_ON_PANEL_TV:
+ case utils::OV_3D_VIDEO_ON_2D_PANEL:
+ case utils::OV_3D_VIDEO_ON_3D_PANEL:
+ case utils::OV_3D_VIDEO_ON_3D_TV:
+ case utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV:
+ case utils::OV_UI_MIRROR:
+ case utils::OV_2D_TRUE_UI_MIRROR:
+ case utils::OV_BYPASS_1_LAYER:
+ case utils::OV_BYPASS_2_LAYER:
+ case utils::OV_BYPASS_3_LAYER:
+ if(!mOv->waitForVsync(dest)) {
+ ALOGE("Overlay %s failed", __FUNCTION__);
+ return false;
+ }
+ break;
+ default:
+ OVASSERT(false, "%s Unknown state %d", __FUNCTION__, st);
+ return false;
+ }
+ return true;
+}
+
+bool Overlay::setCrop(const utils::Dim& d,
+ utils::eDest dest)
+{
+ OVASSERT(mOv,
+ "%s Overlay and Rotator should be init at this point",
+ __FUNCTION__);
+ // FIXME that one needs to move to the state machine class
+ utils::eOverlayState st = mState.state();
+ switch (st) {
+ case utils::OV_2D_VIDEO_ON_PANEL:
+ case utils::OV_2D_VIDEO_ON_PANEL_TV:
+ case utils::OV_3D_VIDEO_ON_2D_PANEL:
+ case utils::OV_3D_VIDEO_ON_3D_PANEL:
+ case utils::OV_3D_VIDEO_ON_3D_TV:
+ case utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV:
+ case utils::OV_UI_MIRROR:
+ case utils::OV_2D_TRUE_UI_MIRROR:
+ case utils::OV_BYPASS_1_LAYER:
+ case utils::OV_BYPASS_2_LAYER:
+ case utils::OV_BYPASS_3_LAYER:
+ if(!mOv->setCrop(d, dest)) {
+ ALOGE("Overlay %s failed", __FUNCTION__);
+ return false;
+ }
+ break;
+ default:
+ OVASSERT(false, "%s Unknown state %d", __FUNCTION__, st);
+ return false;
+ }
+ return true;
+}
+bool Overlay::setPosition(const utils::Dim& d,
+ utils::eDest dest)
+{
+ OVASSERT(mOv,
+ "%s Overlay and Rotator should be init at this point",
+ __FUNCTION__);
+ // FIXME that one needs to move to the state machine class
+ utils::eOverlayState st = mState.state();
+ switch (st) {
+ case utils::OV_2D_VIDEO_ON_PANEL:
+ case utils::OV_2D_VIDEO_ON_PANEL_TV:
+ case utils::OV_3D_VIDEO_ON_2D_PANEL:
+ case utils::OV_3D_VIDEO_ON_3D_PANEL:
+ case utils::OV_3D_VIDEO_ON_3D_TV:
+ case utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV:
+ case utils::OV_UI_MIRROR:
+ case utils::OV_2D_TRUE_UI_MIRROR:
+ case utils::OV_BYPASS_1_LAYER:
+ case utils::OV_BYPASS_2_LAYER:
+ case utils::OV_BYPASS_3_LAYER:
+ if(!mOv->setPosition(d, dest)) {
+ ALOGE("Overlay %s failed", __FUNCTION__);
+ return false;
+ }
+ break;
+ default:
+ OVASSERT(false, "setPos Unknown state %d", st);
+ return false;
+ }
+ return true;
+}
+bool Overlay::setParameter(const utils::Params& param,
+ utils::eDest dest)
+{
+ OVASSERT(mOv,
+ "%s Overlay and Rotator should be init at this point",
+ __FUNCTION__);
+ // FIXME that one needs to move to the state machine class
+ utils::eOverlayState st = mState.state();
+ switch (st) {
+ case utils::OV_2D_VIDEO_ON_PANEL:
+ case utils::OV_2D_VIDEO_ON_PANEL_TV:
+ case utils::OV_3D_VIDEO_ON_2D_PANEL:
+ case utils::OV_3D_VIDEO_ON_3D_PANEL:
+ case utils::OV_3D_VIDEO_ON_3D_TV:
+ case utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV:
+ case utils::OV_UI_MIRROR:
+ case utils::OV_2D_TRUE_UI_MIRROR:
+ case utils::OV_BYPASS_1_LAYER:
+ case utils::OV_BYPASS_2_LAYER:
+ case utils::OV_BYPASS_3_LAYER:
+ if(!mOv->setParameter(param, dest)) {
+ ALOGE("Overlay %s failed", __FUNCTION__);
+ return false;
+ }
+ break;
+ default:
+ OVASSERT(false, "%s Unknown state %d", __FUNCTION__ , st);
+ return false;
+ }
+ return true;
+}
+bool Overlay::setSource(const utils::PipeArgs args[utils::MAX_PIPES],
+ utils::eDest dest)
+{
+ // FIXME that one needs to move to the state machine class
+ utils::PipeArgs margs[utils::MAX_PIPES] = {
+ args[0], args[1], args[2] };
+ utils::eOverlayState st = mState.state();
+
+ switch (st) {
+ case utils::OV_CLOSED:
+ // if we get setSource when we are closed, then
+ // we will assume tranistion to OV_2D_VIDEO_ON_PANEL
+ // returns overlay
+ mOv = mState.handle_closed(utils::OV_2D_VIDEO_ON_PANEL);
+ if (!mOv) {
+ ALOGE("Overlay %s failed", __FUNCTION__);
+ this->reset(); // cleanup
+ return false;
+ }
+ break;
+ case utils::OV_2D_VIDEO_ON_PANEL:
+ case utils::OV_3D_VIDEO_ON_2D_PANEL:
+ case utils::OV_UI_MIRROR:
+ case utils::OV_BYPASS_1_LAYER:
+ case utils::OV_BYPASS_2_LAYER:
+ case utils::OV_BYPASS_3_LAYER:
+ // no tweaking
+ break;
+ case utils::OV_3D_VIDEO_ON_3D_PANEL:
+ case utils::OV_3D_VIDEO_ON_3D_TV:
+ margs[utils::CHANNEL_1].zorder = utils::ZORDER_1;
+ break;
+ case utils::OV_2D_VIDEO_ON_PANEL_TV:
+ case utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV:
+ // If displaying on both, external VG pipe set to be no wait
+ margs[utils::CHANNEL_1].wait = utils::NO_WAIT;
+ break;
+ case utils::OV_2D_TRUE_UI_MIRROR:
+ // Set zorder -- external VG pipe (video) gets 0, RGB pipe (UI) gets 1
+ margs[utils::CHANNEL_1].zorder = utils::ZORDER_0;
+ margs[utils::CHANNEL_2].zorder = utils::ZORDER_1;
+ // External VG (video) and RGB (UI) pipe set to be no wait
+ margs[utils::CHANNEL_0].wait = utils::WAIT;
+ margs[utils::CHANNEL_1].wait = utils::NO_WAIT;
+ margs[utils::CHANNEL_2].wait = utils::NO_WAIT;
+ break;
+ default:
+ OVASSERT(false, "%s Unknown state %d", __FUNCTION__, st);
+ return false;
+ }
+
+ if (!mOv->setSource(margs, dest)) {
+ ALOGE("Overlay %s failed", __FUNCTION__);
+ return false;
+ }
+
+ return true;
+}
+void Overlay::setMemoryId(int id, utils::eDest dest)
+{
+ OVASSERT(mOv,
+ "%s Overlay and Rotator should be init at this point",
+ __FUNCTION__);
+ // FIXME that one needs to move to the state machine class
+ utils::eOverlayState st = mState.state();
+ switch (st) {
+ case utils::OV_2D_VIDEO_ON_PANEL:
+ case utils::OV_2D_VIDEO_ON_PANEL_TV:
+ case utils::OV_3D_VIDEO_ON_2D_PANEL:
+ case utils::OV_3D_VIDEO_ON_3D_PANEL:
+ case utils::OV_3D_VIDEO_ON_3D_TV:
+ case utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV:
+ case utils::OV_UI_MIRROR:
+ case utils::OV_2D_TRUE_UI_MIRROR:
+ case utils::OV_BYPASS_1_LAYER:
+ case utils::OV_BYPASS_2_LAYER:
+ case utils::OV_BYPASS_3_LAYER:
+ mOv->setMemoryId(id, dest);
+ break;
+ default:
+ OVASSERT(false, "setMemId Unknown state %d", st);
+ }
+}
+
+
+void Overlay::dump() const
+{
+ OVASSERT(mOv,
+ "%s Overlay and Rotator should be init at this point",
+ __FUNCTION__);
+ // FIXME dump tate object, factory
+ ALOGE("== Dump Overlay start ==");
+ mState.dump();
+ mOv->dump();
+ ALOGE("== Dump Overlay end ==");
+}
+
+void Overlay::setState(utils::eOverlayState s) {
+ mOv = mState.handleEvent(s, mOv);
+}
+
+utils::eOverlayState Overlay::getState() const {
+ return mState.state();
+}
+
+Overlay *Overlay::sInstance = 0;
+
+Overlay* Overlay::getInstance() {
+ if(sInstance == NULL)
+ sInstance = new Overlay();
+ return sInstance;
+}
+
+/**** NullPipe ****/
+
+bool NullPipe::open(RotatorBase*) {
+ ALOGE_IF(DEBUG_OVERLAY, "NullPipe open");
+ return true;
+}
+bool NullPipe::close() { return true; }
+bool NullPipe::commit() { return true; }
+bool NullPipe::start(const utils::PipeArgs&) { return true; }
+bool NullPipe::setCrop(const utils::Dim&) { return true; }
+bool NullPipe::setPosition(const utils::Dim&) { return true; }
+bool NullPipe::setParameter(const utils::Params&) { return true; }
+bool NullPipe::setSource(const utils::PipeArgs&) { return true; }
+bool NullPipe::queueBuffer(uint32_t offset) { return true; }
+bool NullPipe::dequeueBuffer(void*&) { return true; }
+bool NullPipe::waitForVsync() { return true; }
+void NullPipe::setMemoryId(int) {}
+// NullPipe will return by val here as opposed to other Pipes.
+utils::PipeArgs NullPipe::getArgs() const { return utils::PipeArgs(); }
+utils::eOverlayPipeType NullPipe::getOvPipeType() const {
+ return utils::OV_PIPE_TYPE_NULL;
+}
+void NullPipe::dump() const {
+ ALOGE("== NullPipe (null) start/end ==");
+}
+
+} // overlay
diff --git a/liboverlay/overlay.h b/liboverlay/overlay.h
new file mode 100644
index 0000000..e2ee6cd
--- /dev/null
+++ b/liboverlay/overlay.h
@@ -0,0 +1,103 @@
+/*
+* Copyright (c) 2011-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 OVERLAY_H
+#define OVERLAY_H
+
+#include "overlayUtils.h"
+#include "overlayState.h"
+#include "overlayImpl.h"
+
+namespace overlay {
+/**/
+class Overlay : utils::NoCopy {
+public:
+ /* dtor close */
+ ~Overlay();
+
+ /* Overlay related func */
+
+ /* We need an empty open to just open the bare minimum for
+ * business. */
+ bool open();
+
+ /* close rotator, state, overlayimpl*/
+ bool close();
+
+ /* Following is the same as the pure virt interface in ov impl */
+
+ bool commit(utils::eDest dest = utils::OV_PIPE_ALL);
+
+ bool queueBuffer(uint32_t offset,
+ utils::eDest dest = utils::OV_PIPE_ALL);
+ bool dequeueBuffer(void*& buf,
+ utils::eDest dest = utils::OV_PIPE_ALL);
+ bool waitForVsync(utils::eDest dest = utils::OV_PIPE1);
+ bool setCrop(const utils::Dim& d,
+ utils::eDest dest = utils::OV_PIPE_ALL);
+ bool setPosition(const utils::Dim& dim,
+ utils::eDest dest = utils::OV_PIPE_ALL);
+ bool setParameter(const utils::Params& param,
+ utils::eDest dest = utils::OV_PIPE_ALL);
+ bool setSource(const utils::PipeArgs args[utils::MAX_PIPES],
+ utils::eDest dest = utils::OV_PIPE_ALL);
+ void setMemoryId(int id, utils::eDest dest = utils::OV_PIPE_ALL);
+ void dump() const;
+
+ /* state related functions */
+ void setState(utils::eOverlayState s);
+
+ /* expose state */
+ utils::eOverlayState getState() const;
+
+ /* Returns the singleton instance of overlay */
+ static Overlay* getInstance();
+
+private:
+ /* Ctor setup */
+ Overlay();
+
+ /* reset all pointers */
+ void reset();
+
+ /* Holds the state, state transition logic
+ * In the meantime, using simple enum rather than
+ * a class */
+ OverlayState mState;
+
+ /* Holds the actual overlay impl, set when changing state*/
+ OverlayImplBase *mOv;
+
+ /* Singleton Instance*/
+ static Overlay *sInstance;
+};
+
+} // overlay
+
+#endif // OVERLAY_H
diff --git a/liboverlay/overlayCtrl.cpp b/liboverlay/overlayCtrl.cpp
new file mode 100644
index 0000000..6f84d07
--- /dev/null
+++ b/liboverlay/overlayCtrl.cpp
@@ -0,0 +1,349 @@
+/*
+* 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.
+*/
+
+#include <cutils/properties.h>
+#include "overlayCtrlData.h"
+#include "fb_priv.h"
+
+namespace overlay{
+
+bool Ctrl::open(uint32_t fbnum,
+ RotatorBase* rot) {
+ // MDP/FD open
+ if(!mMdp.open(fbnum)) {
+ ALOGE("Ctrl failed to open fbnum=%d", fbnum);
+ return false;
+ }
+
+ if(!getScreenInfo(mInfo)) {
+ ALOGE("Ctrl failed to getScreenInfo");
+ return false;
+ }
+
+ OVASSERT(rot, "rot is null");
+ mRot = rot;
+ // rot should be already opened
+
+ return true;
+}
+
+bool Ctrl::start(const utils::PipeArgs& args)
+{
+ int colorFormat = utils::getColorFormat(args.whf.format);
+ utils::eMdpFlags flags = args.mdpFlags;
+
+ //XXX: Support for interlaced content
+ if (0) {
+
+ setMdpFlags(flags, utils::OV_MDP_DEINTERLACE);
+
+ // Get the actual format
+ colorFormat = args.whf.format ^ HAL_PIXEL_FORMAT_INTERLACE;
+ }
+ utils::Whf hwwhf(args.whf);
+ int fmt = utils::getMdpFormat(colorFormat);
+ // FIXME format should probably be int and not uint
+ if (fmt < 0) {
+ ALOGE("Ctrl failed getMdpFormat unsopported "
+ "colorFormat=%d format=%d flags=%d",
+ colorFormat, fmt, flags);
+ return false;
+ }
+ hwwhf.format = fmt;
+
+ // devices should be already opened
+ // (by calling open earlier in the flow)
+
+ const utils::PipeArgs newargs(flags, // mdp flags
+ args.orientation, // trans
+ hwwhf,
+ args.wait,
+ args.zorder,
+ args.isFg,
+ args.rotFlags);
+ if (!setInfo(newargs)) {
+ ALOGE("Ctrl failed to setInfo mdpflags=%d wait=%d zorder=%d",
+ newargs.mdpFlags, newargs.wait, newargs.zorder);
+ hwwhf.dump();
+ return false;
+ }
+
+ // FIXME, can we remove that and have it in
+ // setSource only when source changed?
+ if(!mRot->start(newargs)) {
+ ALOGE("Ctrl failed to start Rotation session");
+ return false;
+ }
+
+ // if geom is different, we need to prepare a new rot buffers.
+ // remap on demand when the current orientation is 90,180, etc.
+ // and the prev orientation was 0. It means we go from orient
+ if(!mRot->remap(utils::ROT_NUM_BUFS, newargs)) {
+ ALOGE("%s Error in remapping", __FUNCTION__);
+ }
+
+ if(!mMdp.set()) {
+ ALOGE("Ctrl start failed set overlay");
+ return false;
+ }
+
+ // cache the src to be the current mCrop vals
+ mCrop.w = hwwhf.w;
+ mCrop.h = hwwhf.h;
+
+ return true;
+}
+
+inline void Ctrl::updateSource(RotatorBase* r,
+ const utils::PipeArgs& args,
+ utils::ScreenInfo& info)
+{
+ mMdp.updateSource(r, args, info);
+}
+
+bool Ctrl::setSource(const utils::PipeArgs& args)
+{
+ mMdp.setWait(args.wait);
+
+ utils::PipeArgs newargs(args);
+ utils::Whf whf(args.whf);
+ // check geom change
+ if(mOvBufInfo != whf) {
+ // whf.format is given as HAL, that is why it is
+ // needed to be MDP fmt.
+ whf.format = utils::getColorFormat(whf.format);
+ int fmt = utils::getMdpFormat(whf.format);
+ OVASSERT(-1 != fmt, "Ctrl setSource format is -1");
+ whf.format = fmt;
+ newargs.whf = whf;
+ updateSource(mRot, newargs, mInfo);
+ mMdp.setUserData(0);
+ if(!mRot->start(newargs)) {
+ ALOGE("%s failed start rot", __FUNCTION__);
+ return false;
+ }
+
+ // if geom is different, we need to prepare a new rot buffers.
+ // remap on demand when the current orientation is 90,180, etc.
+ // and the prev orientation was 0. It means we go from orient
+ if(!mRot->remap(utils::ROT_NUM_BUFS, newargs)) {
+ ALOGE("%s Error in remapping", __FUNCTION__);
+ }
+ }
+
+ // needed for setSource
+ mOrient = args.orientation;
+
+ // cache last whf from gralloc hnd
+ mOvBufInfo = args.whf;
+
+ // orign impl is returning false here
+ // because they will close the overlay and reopen it.
+ // New design would not do that.
+ return true;
+}
+
+bool Ctrl::setPosition(const utils::Dim& dim)
+{
+ if(!dim.check(mInfo.mFBWidth, mInfo.mFBHeight)) {
+ ALOGE("Ctrl setPosition error in dim");
+ dim.dump();
+ return false;
+ }
+
+ if(!mMdp.setPosition(dim, mInfo.mFBWidth, mInfo.mFBHeight)) {
+ ALOGE("Ctrl failed MDP setPosition");
+ return false;
+ }
+ return true;
+}
+
+bool Ctrl::setParameter(const utils::Params& p)
+{
+ if (utils::OVERLAY_TRANSFORM == p.param &&
+ p.value == mMdp.getUserData()) {
+ // nothing to do here
+ return true;
+ }
+
+ utils::eTransform trns = static_cast<utils::eTransform>(p.value);
+ switch (p.param) {
+ case utils::OVERLAY_DITHER:
+ // nothing here today
+ ALOGE("Ctrl setParameter OVERLAY_DITHER not impl");
+ return true;
+ case utils::OVERLAY_TRANSFORM:
+ if(!mRot->overlayTransform(mMdp, trns)) {
+ ALOGE("Ctrl setParameter failed Rot overlayTransform");
+ return false;
+ }
+ break;
+ default:
+ ALOGE("Ctrl setParameter unknown param %d", p.param);
+ return false;
+ }
+ return true;
+}
+
+bool Ctrl::setCrop(const utils::Dim& d)
+{
+ // FIXME check channel validity
+ if(!mMdp.setCrop(d)) {
+ ALOGE("Data setCrop failed in MDP setCrop");
+ return false;
+ }
+ mCrop = d;
+ return true;
+}
+
+utils::Dim Ctrl::getAspectRatio(const utils::Whf& whf) const
+{
+ utils::Whf inWhf(whf.w, whf.h, mMdp.getSrcWhf().format);
+ utils::Whf tmpwhf(inWhf);
+ uint32_t fbWidth = mInfo.mFBWidth;
+ uint32_t fbHeight = mInfo.mFBHeight;
+
+ /* Calculate the width and height if it is YUV TILE format*/
+ if (inWhf.format == HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED) {
+ tmpwhf.w = whf.w - (utils::alignup(whf.w, 64) - whf.w);
+ tmpwhf.h = whf.h - (utils::alignup(whf.h, 32) - whf.h);
+ }
+ if (inWhf.w * fbHeight > fbWidth * inWhf.h) {
+ inWhf.h = fbWidth * inWhf.h / inWhf.w;
+ utils::even_out(inWhf.h);
+ inWhf.w = fbWidth;
+ } else if (inWhf.w * fbHeight < fbWidth * inWhf.h) {
+ inWhf.w = fbHeight * inWhf.w / inWhf.h;
+ utils::even_out(inWhf.w);
+ inWhf.h = fbHeight;
+ } else {
+ inWhf.w = fbWidth;
+ inWhf.h = fbHeight;
+ }
+ /* Scaling of upto a max of 8 times supported */
+ if (inWhf.w > (tmpwhf.w * utils::HW_OV_MAGNIFICATION_LIMIT)){
+ inWhf.w = utils::HW_OV_MAGNIFICATION_LIMIT * tmpwhf.w;
+ }
+ if(inWhf.h > (tmpwhf.h * utils::HW_OV_MAGNIFICATION_LIMIT)) {
+ inWhf.h = utils::HW_OV_MAGNIFICATION_LIMIT * tmpwhf.h;
+ }
+ if (inWhf.w > fbWidth) inWhf.w = fbWidth;
+ if (inWhf.h > fbHeight) inWhf.h = fbHeight;
+
+ char value[PROPERTY_VALUE_MAX];
+ property_get("hw.actionsafe.width", value, "0");
+ float asWidth = atof(value);
+ property_get("hw.actionsafe.height", value, "0");
+ float asHeight = atof(value);
+ inWhf.w = inWhf.w * (1.0f - asWidth / 100.0f);
+ inWhf.h = inWhf.h * (1.0f - asHeight / 100.0f);
+
+ uint32_t x = (fbWidth - inWhf.w) / 2.0;
+ uint32_t y = (fbHeight - inWhf.h) / 2.0;
+ return utils::Dim(x, y, inWhf.w, inWhf.h);
+}
+
+utils::FrameBufferInfo* utils::FrameBufferInfo::sFBInfoInstance = 0;
+
+// This function gets the destination position for external display
+// based on the position and aspect ratio of the primary
+utils::Dim Ctrl::getAspectRatio(const utils::Dim& dim) const {
+ float priWidth = utils::FrameBufferInfo::getInstance()->getWidth();
+ float priHeight = utils::FrameBufferInfo::getInstance()->getHeight();
+ float fbWidth = mInfo.mFBWidth;
+ float fbHeight = mInfo.mFBHeight;
+ float wRatio = 1.0;
+ float hRatio = 1.0;
+ float xRatio = 1.0;
+ float yRatio = 1.0;
+ utils::Dim inDim(dim);
+
+ int xPos = 0;
+ int yPos = 0;
+ int tmp = 0;
+ utils::Dim tmpDim;
+ switch(inDim.o) {
+ case MDP_ROT_NOP:
+ case MDP_ROT_180:
+ {
+ utils::Whf whf((uint32_t) priWidth, (uint32_t) priHeight, 0);
+ tmpDim = getAspectRatio(whf);
+ xPos = tmpDim.x;
+ yPos = tmpDim.y;
+ fbWidth = tmpDim.w;
+ fbHeight = tmpDim.h;
+
+ if (inDim.o == MDP_ROT_180) {
+ inDim.x = priWidth - (inDim.x + inDim.w);
+ inDim.y = priHeight - (inDim.y + inDim.h);
+ }
+ break;
+ }
+ case MDP_ROT_90:
+ case MDP_ROT_270:
+ {
+ if(inDim.o == MDP_ROT_90) {
+ tmp = inDim.y;
+ inDim.y = priWidth - (inDim.x + inDim.w);
+ inDim.x = tmp;
+ }
+ else if (inDim.o == MDP_ROT_270) {
+ tmp = inDim.x;
+ inDim.x = priHeight - (inDim.y + inDim.h);
+ inDim.y = tmp;
+ }
+
+ // Swap the destination width/height
+ utils::swapWidthHeight(inDim.w, inDim.h);
+ // Swap width/height for primary
+ utils::swapWidthHeight(priWidth, priHeight);
+ utils::Whf whf((uint32_t) priWidth, (uint32_t) priHeight, 0);
+ tmpDim = getAspectRatio(whf);
+ xPos = tmpDim.x;
+ yPos = tmpDim.y;
+ fbWidth = tmpDim.w;
+ fbHeight = tmpDim.h;
+ break;
+ }
+ default:
+ ALOGE("%s: Unknown Orientation", __FUNCTION__);
+ break;
+ }
+
+ // Calculate the position
+ xRatio = inDim.x/priWidth;
+ yRatio = inDim.y/priHeight;
+ wRatio = inDim.w/priWidth;
+ hRatio = inDim.h/priHeight;
+
+ return utils::Dim((xRatio * fbWidth) + xPos, // x
+ (yRatio * fbHeight) + yPos, // y
+ (wRatio * fbWidth), // width
+ (hRatio * fbHeight), // height
+ inDim.o); // orientation
+}
+
+void Ctrl::dump() const {
+ ALOGE("== Dump Ctrl start ==");
+ ALOGE("orient=%d", mOrient);
+ mInfo.dump("mInfo");
+ mMdp.dump();
+ mRot->dump();
+ ALOGE("== Dump Ctrl end ==");
+}
+
+} // overlay
diff --git a/liboverlay/overlayCtrlData.h b/liboverlay/overlayCtrlData.h
new file mode 100644
index 0000000..fbd701a
--- /dev/null
+++ b/liboverlay/overlayCtrlData.h
@@ -0,0 +1,365 @@
+/*
+* Copyright (c) 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 OVERLAY_CTRLDATA_H
+#define OVERLAY_CTRLDATA_H
+
+#include "overlayUtils.h"
+#include "overlayMdp.h"
+#include "gralloc_priv.h" // INTERLACE_MASK
+
+namespace ovutils = overlay::utils;
+
+namespace overlay {
+
+// FIXME make int to be uint32 whenever possible
+
+class RotatorBase;
+
+/*
+* FIXME do we want rot to be template parameter?
+* It's already using inheritance...
+*
+* Sequence to use:
+* open
+* start
+* setXXX
+* close
+*
+* Can call setRot anytime to replace rotator on-the-fly
+* */
+class Ctrl : utils::NoCopy {
+public:
+
+ /* ctor */
+ explicit Ctrl();
+
+ /* dtor close */
+ ~Ctrl();
+
+ /* should open devices? or start()? */
+ bool open(uint32_t fbnum, RotatorBase* rot);
+
+ /* close underlying mdp */
+ bool close();
+
+ /* Invoke methods for opening underlying devices
+ * flags - PIPE SHARED
+ * wait - WAIT, NO_WAIT */
+ bool start(const utils::PipeArgs& args);
+
+ /* Dynamically set rotator*/
+ void setRot(RotatorBase* rot);
+
+ /* set mdp posision using dim */
+ bool setPosition(const utils::Dim& dim);
+
+ /* set param using Params (param,value pair) */
+ bool setParameter(const utils::Params& p);
+
+ /* set source using whf, orient and wait flag */
+ bool setSource(const utils::PipeArgs& args);
+
+ /* set crop info and pass it down to mdp */
+ bool setCrop(const utils::Dim& d);
+
+ /* mdp set overlay/commit changes */
+ bool commit();
+
+ /* ctrl id */
+ int getId() const;
+ /* ctrl fd */
+ int getFd() const;
+ bool getRotSessId(int& id) const;
+ utils::Dim getAspectRatio(const utils::Whf& whf) const;
+ utils::Dim getAspectRatio(const utils::Dim& dim) const;
+
+ /* access for screen info */
+ utils::ScreenInfo getScreenInfo() const;
+
+ /* retrieve cached crop data */
+ utils::Dim getCrop() const;
+
+ /* dump the state of the object */
+ void dump() const;
+
+private:
+ /* Retrieve screen info from underlying mdp */
+ bool getScreenInfo(utils::ScreenInfo& info);
+
+ /* calls underlying mdp set info */
+ bool setInfo(const utils::PipeArgs& args);
+
+ /* given whf, update src */
+ void updateSource(RotatorBase* r,
+ const utils::PipeArgs& args,
+ utils::ScreenInfo& info);
+
+ // mdp ctrl struct(info e.g.)
+ MdpCtrl mMdp;
+
+ // Rotator
+ RotatorBase* mRot;
+
+ /* Cache cropped value */
+ utils::Dim mCrop;
+
+ /* Screen info */
+ utils::ScreenInfo mInfo;
+
+ /* orientation cache FIXME */
+ utils::eTransform mOrient;
+
+ /* Cache last known whfz.
+ * That would help us compare to a previous
+ * source that was submitted */
+ utils::Whf mOvBufInfo;
+};
+
+
+/*
+* MDP = DataMdp, ROT = CtrlMdp usually since Rotator<>
+* is instansiated with Ctrl data structure.
+* */
+class Data : utils::NoCopy {
+public:
+ /* init, reset */
+ explicit Data();
+
+ /* calls close */
+ ~Data();
+
+ /* should open devices? or start()? */
+ bool open(uint32_t fbnum, RotatorBase* rot);
+
+ /* calls underlying mdp close */
+ bool close();
+
+ /* set the rotator */
+ void setRot(RotatorBase* rot);
+
+ /* set memory id in the mdp struct */
+ void setMemoryId(int id);
+
+ /* set overlay id in the mdp struct */
+ void setId(int id);
+
+ /* get overlay id in the mdp struct */
+ int getId() const;
+
+ /* queue buffer to the overlay */
+ bool queueBuffer(uint32_t offset);
+
+ /* wait for vsync to be done */
+ bool waitForVsync();
+
+ /* sump the state of the obj */
+ void dump() const;
+private:
+ /* play wrapper */
+ bool play();
+
+ /* playWait wrapper */
+ bool playWait();
+
+ // mdp data struct
+ MdpData mMdp;
+
+ // Rotator
+ RotatorBase* mRot;
+};
+
+/* This class just creates a Ctrl Data pair to be used by a pipe.
+ * Although this was legacy design, this separation still makes sense, since we
+ * need to use the Ctrl channel in hwc_prepare (i.e config stage) and Data
+ * channel in hwc_set (i.e draw stage)
+ */
+struct CtrlData {
+ Ctrl ctrl;
+ Data data;
+};
+
+//-------------Inlines-------------------------------
+
+inline Ctrl::Ctrl() : mRot(0), mOrient(utils::OVERLAY_TRANSFORM_0) {
+ mMdp.reset();
+}
+
+inline Ctrl::~Ctrl() {
+ close();
+}
+
+inline bool Ctrl::close() {
+ // do not close the rotator
+ if(!mMdp.close())
+ return false;
+ return true;
+}
+
+inline bool Ctrl::commit() {
+ if(!mMdp.set()) {
+ ALOGE("Ctrl commit failed set overlay");
+ return false;
+ }
+ return true;
+}
+
+inline bool Ctrl::getScreenInfo(utils::ScreenInfo& info) {
+ if(!mMdp.getScreenInfo(info)){
+ ALOGE("Ctrl failed to get screen info");
+ return false;
+ }
+ return true;
+}
+
+inline bool Ctrl::setInfo(const utils::PipeArgs& args)
+{
+ // FIXME set flags, zorder and wait separtly
+ if(!mMdp.setInfo(mRot, args, mInfo)){
+ ALOGE("Ctrl failed to setInfo wait=%d mdpflags=%d "
+ "zorder=%d", args.wait, args.mdpFlags, args.zorder);
+ return false;
+ }
+ return true;
+}
+
+inline int Ctrl::getId() const {
+ // FIXME check channel up?
+ return mMdp.getId();
+}
+
+inline int Ctrl::getFd() const {
+ // FIXME check channel up?
+ return mMdp.getFd();
+}
+
+inline bool Ctrl::getRotSessId(int& id) const {
+ // FIXME check channel up?
+ // should be -1 in case of no rot session active
+ id = mRot->getSessId();
+ return true;
+}
+
+inline utils::ScreenInfo Ctrl::getScreenInfo() const {
+ return mInfo;
+}
+
+inline utils::Dim Ctrl::getCrop() const {
+ return mCrop;
+}
+
+
+
+inline Data::Data() : mRot(0) {
+ mMdp.reset();
+}
+
+inline Data::~Data() { close(); }
+
+inline void Data::setRot(RotatorBase* rot) { mRot = rot; }
+
+inline void Data::setMemoryId(int id) { mMdp.setMemoryId(id); }
+
+// really a reqid
+inline void Data::setId(int id) { mMdp.setId(id); }
+
+inline int Data::getId() const { return mMdp.getId(); }
+
+inline bool Data::open(uint32_t fbnum,
+ RotatorBase* rot) {
+ if(!mMdp.open(fbnum)) {
+ ALOGE("Data cannot open mdp");
+ return false;
+ }
+
+ OVASSERT(rot, "rot is null");
+ mRot = rot;
+
+ // rotator should be already opened here
+ return true;
+}
+
+inline bool Data::close() {
+ if(!mMdp.close()) {
+ ALOGE("Data close failed");
+ return false;
+ }
+ return true;
+}
+
+inline bool Data::queueBuffer(uint32_t offset) {
+ // FIXME asserts on state validity
+
+ mMdp.setOffset(offset);
+ mRot->setRotDataSrcMemId(mMdp.getMemoryId());
+ // will play if succeeded
+ if(!mRot->prepareQueueBuf(offset)) {
+ ALOGE("Data failed to prepareQueueBuf");
+ return false;
+ }
+ // Play can go either from mdp or rot
+ if(!this->play()){
+ ALOGE("Data error in MDP/ROT play");
+ return false;
+ }
+
+ return true;
+}
+
+inline bool Data::waitForVsync() {
+
+ // Call mdp playWait
+ if(!this->playWait()){
+ ALOGE("Error in MDP playWait");
+ return false;
+ }
+
+ return true;
+}
+
+inline bool Data::play() {
+ int fd = mMdp.getFd();
+ return mRot->enabled() ? mRot->play(fd) : mMdp.play();
+}
+
+inline bool Data::playWait() {
+ return mMdp.playWait();
+}
+
+inline void Data::dump() const {
+ ALOGE("== Dump Data MDP start ==");
+ mMdp.dump();
+ mRot->dump();
+ ALOGE("== Dump Data MDP end ==");
+}
+
+
+} // overlay
+
+#endif
diff --git a/liboverlay/overlayImpl.h b/liboverlay/overlayImpl.h
new file mode 100644
index 0000000..5f999f2
--- /dev/null
+++ b/liboverlay/overlayImpl.h
@@ -0,0 +1,742 @@
+/*
+* Copyright (c) 2011-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 OVERLAY_IMPL_H
+#define OVERLAY_IMPL_H
+
+#include "overlayUtils.h"
+#include "overlayRotator.h"
+
+// FIXME make int to be uint32 whenever possible
+
+namespace overlay {
+
+// Interface only. No member, no definiton (except ~ which can
+// also be =0 with impl in cpp)
+class OverlayImplBase {
+public:
+ /* empty dtor. can be =0 with cpp impl*/
+ virtual ~OverlayImplBase() {}
+
+ /* Open pipe/rot for one dest */
+ virtual bool openPipe(RotatorBase* rot, utils::eDest dest) = 0;
+
+ /* Close pipe/rot for all specified dest */
+ virtual bool closePipe(utils::eDest dest) = 0;
+
+ /* Copy specified pipe/rot from ov passed in (used by state machine only) */
+ virtual bool copyOvPipe(OverlayImplBase* ov, utils::eDest dest) = 0;
+
+ /* TODO open func customized for RGBx pipes */
+
+ /* Open all pipes
+ * To open just one pipe, use openPipe()
+ * */
+ virtual bool open(RotatorBase* rot0,
+ RotatorBase* rot1,
+ RotatorBase* rot2) = 0;
+
+ /* Close all pipes
+ * To close just one pipe, use closePipe()
+ * */
+ virtual bool close() = 0;
+
+ /*
+ * Commit changes to the overlay
+ * */
+ virtual bool commit(utils::eDest dest = utils::OV_PIPE_ALL) = 0;
+
+ /* Queue buffer with offset*/
+ virtual bool queueBuffer(uint32_t offset,
+ utils::eDest dest = utils::OV_PIPE_ALL) = 0;
+
+ /* For RGBx pipes, dequeue buffer (that is fb chunk)*/
+ virtual bool dequeueBuffer(void*& buf,
+ utils::eDest dest = utils::OV_PIPE_ALL) = 0;
+
+ /* Wait for vsync to be done on dest */
+ virtual bool waitForVsync(utils::eDest dest = utils::OV_PIPE1) = 0;
+
+ /* Crop existing destination using Dim coordinates */
+ virtual bool setCrop(const utils::Dim& d,
+ utils::eDest dest = utils::OV_PIPE_ALL) = 0;
+
+ /* Set new position using Dim */
+ virtual bool setPosition(const utils::Dim& dim,
+ utils::eDest dest = utils::OV_PIPE_ALL) = 0;
+
+ /* Set parameters - usually needed for Rotator, but would
+ * be passed down the stack as well */
+ virtual bool setParameter(const utils::Params& param,
+ utils::eDest dest = utils::OV_PIPE_ALL) = 0;
+
+ /* Set new source including orientation */
+ virtual bool setSource(const utils::PipeArgs[utils::MAX_PIPES],
+ utils::eDest dest = utils::OV_PIPE_ALL) = 0;
+
+ /* set memory id to the underlying pipes */
+ virtual void setMemoryId(int id, utils::eDest dest = utils::OV_PIPE_ALL) = 0;
+
+ /* Get the overlay pipe type */
+ virtual utils::eOverlayPipeType getOvPipeType(utils::eDest dest) const = 0;
+
+ /* Dump underlying state */
+ virtual void dump() const = 0;
+};
+
+class NullPipe {
+public:
+ /* TODO open func customized for RGBx pipes */
+ bool open(RotatorBase* rot);
+ bool close();
+ bool start(const utils::PipeArgs& args);
+ bool commit();
+ bool setCrop(const utils::Dim& d);
+ bool setPosition(const utils::Dim& dim);
+ bool setParameter(const utils::Params& param);
+ bool setSource(const utils::PipeArgs& args);
+ bool queueBuffer(uint32_t offset);
+ bool dequeueBuffer(void*& buf);
+ bool waitForVsync();
+ void setMemoryId(int id);
+ utils::PipeArgs getArgs() const;
+ utils::eOverlayPipeType getOvPipeType() const;
+ void dump() const;
+};
+
+/*
+* Each pipe is not specific to a display (primary/external). The order in the
+* template params, will setup the priorities of the pipes.
+* */
+template <class P0, class P1=NullPipe, class P2=NullPipe>
+class OverlayImpl : public OverlayImplBase {
+public:
+ typedef P0 pipe0;
+ typedef P1 pipe1;
+ typedef P2 pipe2;
+
+ /* ctor */
+ OverlayImpl();
+ OverlayImpl(P0* p0, P1* p1, P2* p2);
+
+ /*
+ * Comments of the below functions are the same as the one
+ * in OverlayImplBase.
+ * */
+ virtual ~OverlayImpl();
+
+ virtual bool openPipe(RotatorBase* rot, utils::eDest dest);
+ virtual bool closePipe(utils::eDest dest);
+ virtual bool copyOvPipe(OverlayImplBase* ov, utils::eDest dest);
+
+ /* TODO open func customized for RGBx pipes */
+ virtual bool open(RotatorBase* rot0,
+ RotatorBase* rot1,
+ RotatorBase* rot2);
+ virtual bool close();
+ virtual bool commit(utils::eDest dest = utils::OV_PIPE_ALL);
+ virtual bool setCrop(const utils::Dim& d,
+ utils::eDest dest = utils::OV_PIPE_ALL);
+ virtual bool setPosition(const utils::Dim& dim,
+ utils::eDest dest = utils::OV_PIPE_ALL);
+ virtual bool setParameter(const utils::Params& param,
+ utils::eDest dest = utils::OV_PIPE_ALL);
+ virtual bool setSource(const utils::PipeArgs[utils::MAX_PIPES],
+ utils::eDest dest = utils::OV_PIPE_ALL);
+ virtual bool queueBuffer(uint32_t offset,
+ utils::eDest dest = utils::OV_PIPE_ALL);
+ virtual bool dequeueBuffer(void*& buf,
+ utils::eDest dest = utils::OV_PIPE_ALL);
+ virtual bool waitForVsync(utils::eDest dest = utils::OV_PIPE1);
+ virtual void setMemoryId(int id, utils::eDest dest = utils::OV_PIPE_ALL);
+ virtual utils::eOverlayPipeType getOvPipeType(utils::eDest dest) const;
+ virtual void dump() const;
+
+private:
+ P0* mPipe0;
+ P1* mPipe1;
+ P2* mPipe2;
+ // More Px here in the future as needed
+
+ /* */
+
+ /* Each Px has it's own Rotator here.
+ * will pass rotator to the lower layer in stack
+ * but only overlay is allowed to control the lifetime
+ * of the rotator instace */
+ RotatorBase* mRotP0;
+ RotatorBase* mRotP1;
+ RotatorBase* mRotP2;
+};
+
+
+
+
+
+//-----------Inlines and Template defn---------------------------------
+
+template <class P0, class P1, class P2>
+OverlayImpl<P0, P1, P2>::OverlayImpl() :
+ mPipe0(new P0), mPipe1(new P1), mPipe2(new P2),
+ mRotP0(0), mRotP1(0), mRotP2(0)
+{}
+
+template <class P0, class P1, class P2>
+OverlayImpl<P0, P1, P2>::OverlayImpl(P0* p0, P1* p1, P2* p2) :
+ mPipe0(p0), mPipe1(p1), mPipe2(p2),
+ mRotP0(0), mRotP1(0), mRotP2(0)
+{}
+
+template <class P0, class P1, class P2>
+OverlayImpl<P0, P1, P2>::~OverlayImpl()
+{
+ // no op in the meantime. needed to be clean
+ // since state machine will do delete. so we
+ // do not want to close/delete pipes here
+}
+
+/* Open only one pipe/rot pair per call */
+template <class P0, class P1, class P2>
+bool OverlayImpl<P0, P1, P2>::openPipe(RotatorBase* rot, utils::eDest dest)
+{
+ OVASSERT(rot, "%s: OverlayImpl rot is null", __FUNCTION__);
+ OVASSERT(utils::isValidDest(dest), "%s: OverlayImpl invalid dest=%d",
+ __FUNCTION__, dest);
+
+ // Need to down case rotator to mdp one.
+ // we assume p0/p1/p2/px all use the _same_ underlying mdp structure.
+ // FIXME STATIC_ASSERT here
+
+ bool ret = true;
+
+ if (utils::OV_PIPE0 & dest) {
+ OVASSERT(mPipe0, "%s: OverlayImpl pipe0 is null", __FUNCTION__);
+ ALOGE_IF(DEBUG_OVERLAY, "Open pipe0");
+ ret = mPipe0->open(rot);
+ mRotP0 = rot;
+ if(!ret) {
+ ALOGE("%s: OverlayImpl pipe0 failed to open", __FUNCTION__);
+ }
+ return ret;
+ }
+
+ if (utils::OV_PIPE1 & dest) {
+ OVASSERT(mPipe1, "%s: OverlayImpl pipe1 is null", __FUNCTION__);
+ ALOGE_IF(DEBUG_OVERLAY, "Open pipe1");
+ ret = mPipe1->open(rot);
+ mRotP1 = rot;
+ if(!ret) {
+ ALOGE("%s: OverlayImpl pipe1 failed to open", __FUNCTION__);
+ }
+ return ret;
+ }
+
+ if (utils::OV_PIPE2 & dest) {
+ OVASSERT(mPipe2, "%s: OverlayImpl pipe2 is null", __FUNCTION__);
+ ALOGE_IF(DEBUG_OVERLAY, "Open pipe2");
+ ret = mPipe2->open(rot);
+ mRotP2 = rot;
+ if(!ret) {
+ ALOGE("%s: OverlayImpl pipe2 failed to open", __FUNCTION__);
+ }
+ return ret;
+ }
+
+ // Should have returned by here
+ return false;
+}
+
+/* Close pipe/rot for all specified dest */
+template <class P0, class P1, class P2>
+bool OverlayImpl<P0, P1, P2>::closePipe(utils::eDest dest)
+{
+ OVASSERT(utils::isValidDest(dest), "%s: OverlayImpl invalid dest=%d",
+ __FUNCTION__, dest);
+
+ if (utils::OV_PIPE0 & dest) {
+ // Close pipe0
+ OVASSERT(mPipe0, "%s: OverlayImpl pipe0 is null", __FUNCTION__);
+ ALOGE_IF(DEBUG_OVERLAY, "Close pipe0");
+ if (!mPipe0->close()) {
+ ALOGE("%s: OverlayImpl failed to close pipe0", __FUNCTION__);
+ return false;
+ }
+ delete mPipe0;
+ mPipe0 = 0;
+
+ // Close the rotator for pipe0
+ OVASSERT(mRotP0, "%s: OverlayImpl rot0 is null", __FUNCTION__);
+ if (!mRotP0->close()) {
+ ALOGE("%s: OverlayImpl failed to close rot for pipe0", __FUNCTION__);
+ }
+ delete mRotP0;
+ mRotP0 = 0;
+ }
+
+ if (utils::OV_PIPE1 & dest) {
+ // Close pipe1
+ OVASSERT(mPipe1, "%s: OverlayImpl pipe1 is null", __FUNCTION__);
+ ALOGE_IF(DEBUG_OVERLAY, "Close pipe1");
+ if (!mPipe1->close()) {
+ ALOGE("%s: OverlayImpl failed to close pipe1", __FUNCTION__);
+ return false;
+ }
+ delete mPipe1;
+ mPipe1 = 0;
+
+ // Close the rotator for pipe1
+ OVASSERT(mRotP1, "%s: OverlayImpl rot1 is null", __FUNCTION__);
+ if (!mRotP1->close()) {
+ ALOGE("%s: OverlayImpl failed to close rot for pipe1", __FUNCTION__);
+ }
+ delete mRotP1;
+ mRotP1 = 0;
+ }
+
+ if (utils::OV_PIPE2 & dest) {
+ // Close pipe2
+ OVASSERT(mPipe2, "%s: OverlayImpl pipe2 is null", __FUNCTION__);
+ ALOGE_IF(DEBUG_OVERLAY, "Close pipe2");
+ if (!mPipe2->close()) {
+ ALOGE("%s: OverlayImpl failed to close pipe2", __FUNCTION__);
+ return false;
+ }
+ delete mPipe2;
+ mPipe2 = 0;
+
+ // Close the rotator for pipe2
+ OVASSERT(mRotP2, "%s: OverlayImpl rot2 is null", __FUNCTION__);
+ if (!mRotP2->close()) {
+ ALOGE("%s: OverlayImpl failed to close rot for pipe2", __FUNCTION__);
+ }
+ delete mRotP2;
+ mRotP2 = 0;
+ }
+
+ return true;
+}
+
+/* Copy pipe/rot from ov for all specified dest */
+template <class P0, class P1, class P2>
+bool OverlayImpl<P0, P1, P2>::copyOvPipe(OverlayImplBase* ov,
+ utils::eDest dest)
+{
+ OVASSERT(ov, "%s: OverlayImpl ov is null", __FUNCTION__);
+ OVASSERT(utils::isValidDest(dest), "%s: OverlayImpl invalid dest=%d",
+ __FUNCTION__, dest);
+
+ OverlayImpl<P0, P1, P2>* ovimpl = static_cast<OverlayImpl<P0, P1, P2>*>(ov);
+
+ if (utils::OV_PIPE0 & dest) {
+ mPipe0 = ovimpl->mPipe0;
+ mRotP0 = ovimpl->mRotP0;
+ }
+
+ if (utils::OV_PIPE1 & dest) {
+ mPipe1 = ovimpl->mPipe1;
+ mRotP1 = ovimpl->mRotP1;
+ }
+
+ if (utils::OV_PIPE2 & dest) {
+ mPipe2 = ovimpl->mPipe2;
+ mRotP2 = ovimpl->mRotP2;
+ }
+
+ return true;
+}
+
+/* TODO open func customized for RGBx pipes */
+
+/* Open all pipes/rot */
+template <class P0, class P1, class P2>
+bool OverlayImpl<P0, P1, P2>::open(RotatorBase* rot0,
+ RotatorBase* rot1,
+ RotatorBase* rot2)
+{
+ if (!this->openPipe(rot0, utils::OV_PIPE0)) {
+ if (!this->close()) {
+ ALOGE("%s: failed to close at least one pipe", __FUNCTION__);
+ }
+ return false;
+ }
+
+ if (!this->openPipe(rot1, utils::OV_PIPE1)) {
+ if (!this->close()) {
+ ALOGE("%s: failed to close at least one pipe", __FUNCTION__);
+ }
+ return false;
+ }
+
+ if (!this->openPipe(rot2, utils::OV_PIPE2)) {
+ if (!this->close()) {
+ ALOGE("%s: failed to close at least one pipe", __FUNCTION__);
+ }
+ return false;
+ }
+
+ return true;
+}
+
+/* Close all pipes/rot */
+template <class P0, class P1, class P2>
+bool OverlayImpl<P0, P1, P2>::close()
+{
+ if (!this->closePipe(utils::OV_PIPE_ALL)) {
+ return false;
+ }
+
+ return true;
+}
+
+template <class P0, class P1, class P2>
+bool OverlayImpl<P0, P1, P2>::commit(utils::eDest dest)
+{
+ OVASSERT(mPipe0 && mPipe1 && mPipe2,
+ "%s: Pipes are null p0=%p p1=%p p2=%p",
+ __FUNCTION__, mPipe0, mPipe1, mPipe2);
+
+ if (utils::OV_PIPE0 & dest) {
+ if(!mPipe0->commit()) {
+ ALOGE("OverlayImpl p0 failed to commit");
+ return false;
+ }
+ }
+
+ if (utils::OV_PIPE1 & dest) {
+ if(!mPipe1->commit()) {
+ ALOGE("OverlayImpl p1 failed to commit");
+ return false;
+ }
+ }
+
+ if (utils::OV_PIPE2 & dest) {
+ if(!mPipe2->commit()) {
+ ALOGE("OverlayImpl p2 failed to commit");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+template <class P0, class P1, class P2>
+bool OverlayImpl<P0, P1, P2>::setCrop(const utils::Dim& d, utils::eDest dest)
+{
+ OVASSERT(mPipe0 && mPipe1 && mPipe2,
+ "%s: Pipes are null p0=%p p1=%p p2=%p",
+ __FUNCTION__, mPipe0, mPipe1, mPipe2);
+
+ if (utils::OV_PIPE0 & dest) {
+ if(!mPipe0->setCrop(d)) {
+ ALOGE("OverlayImpl p0 failed to crop");
+ return false;
+ }
+ }
+
+ if (utils::OV_PIPE1 & dest) {
+ if(!mPipe1->setCrop(d)) {
+ ALOGE("OverlayImpl p1 failed to crop");
+ return false;
+ }
+ }
+
+ if (utils::OV_PIPE2 & dest) {
+ if(!mPipe2->setCrop(d)) {
+ ALOGE("OverlayImpl p2 failed to crop");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+template <class P0, class P1, class P2>
+bool OverlayImpl<P0, P1, P2>::setPosition(const utils::Dim& d,
+ utils::eDest dest)
+{
+ OVASSERT(mPipe0 && mPipe1 && mPipe2,
+ "%s: Pipes are null p0=%p p1=%p p2=%p",
+ __FUNCTION__, mPipe0, mPipe1, mPipe2);
+
+ if (utils::OV_PIPE0 & dest) {
+ if(!mPipe0->setPosition(d)) {
+ ALOGE("OverlayImpl p0 failed to setpos");
+ return false;
+ }
+ }
+
+ if (utils::OV_PIPE1 & dest) {
+ if(!mPipe1->setPosition(d)) {
+ ALOGE("OverlayImpl p1 failed to setpos");
+ return false;
+ }
+ }
+
+ if (utils::OV_PIPE2 & dest) {
+ if(!mPipe2->setPosition(d)) {
+ ALOGE("OverlayImpl p2 failed to setpos");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+template <class P0, class P1, class P2>
+bool OverlayImpl<P0, P1, P2>::setParameter(const utils::Params& param,
+ utils::eDest dest)
+{
+ OVASSERT(mPipe0 && mPipe1 && mPipe2,
+ "%s: Pipes are null p0=%p p1=%p p2=%p",
+ __FUNCTION__, mPipe0, mPipe1, mPipe2);
+
+ if (utils::OV_PIPE0 & dest) {
+ if(!mPipe0->setParameter(param)) {
+ ALOGE("OverlayImpl p0 failed to setparam");
+ return false;
+ }
+ }
+
+ if (utils::OV_PIPE1 & dest) {
+ if(!mPipe1->setParameter(param)) {
+ ALOGE("OverlayImpl p1 failed to setparam");
+ return false;
+ }
+ }
+
+ if (utils::OV_PIPE2 & dest) {
+ if(!mPipe2->setParameter(param)) {
+ ALOGE("OverlayImpl p2 failed to setparam");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+template <class P0, class P1, class P2>
+bool OverlayImpl<P0, P1, P2>::setSource(const utils::PipeArgs args[utils::MAX_PIPES],
+ utils::eDest dest)
+{
+ OVASSERT(mPipe0 && mPipe1 && mPipe2,
+ "%s: Pipes are null p0=%p p1=%p p2=%p",
+ __FUNCTION__, mPipe0, mPipe1, mPipe2);
+
+ if (utils::OV_PIPE0 & dest) {
+ if(!mPipe0->setSource(args[0])) {
+ ALOGE("OverlayImpl p0 failed to setsrc");
+ return false;
+ }
+ }
+
+ if (utils::OV_PIPE1 & dest) {
+ if(!mPipe1->setSource(args[1])) {
+ ALOGE("OverlayImpl p1 failed to setsrc");
+ return false;
+ }
+ }
+
+ if (utils::OV_PIPE2 & dest) {
+ if(!mPipe2->setSource(args[2])) {
+ ALOGE("OverlayImpl p2 failed to setsrc");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+template <class P0, class P1, class P2>
+bool OverlayImpl<P0, P1, P2>::queueBuffer(uint32_t offset, utils::eDest dest)
+{
+ OVASSERT(mPipe0 && mPipe1 && mPipe2,
+ "%s: Pipes are null p0=%p p1=%p p2=%p",
+ __FUNCTION__, mPipe0, mPipe1, mPipe2);
+
+ if (utils::OV_PIPE0 & dest) {
+ if(!mPipe0->queueBuffer(offset)) {
+ ALOGE("OverlayImpl p0 failed to queueBuffer");
+ return false;
+ }
+ }
+
+ if (utils::OV_PIPE1 & dest) {
+ if(!mPipe1->queueBuffer(offset)) {
+ ALOGE("OverlayImpl p1 failed to queueBuffer");
+ return false;
+ }
+ }
+
+ if (utils::OV_PIPE2 & dest) {
+ if(!mPipe2->queueBuffer(offset)) {
+ ALOGE("OverlayImpl p2 failed to queueBuffer");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+template <class P0, class P1, class P2>
+bool OverlayImpl<P0, P1, P2>::dequeueBuffer(void*& buf, utils::eDest dest)
+{
+ OVASSERT(mPipe0 && mPipe1 && mPipe2,
+ "%s: Pipes are null p0=%p p1=%p p2=%p",
+ __FUNCTION__, mPipe0, mPipe1, mPipe2);
+
+ if (utils::OV_PIPE0 & dest) {
+ if(!mPipe0->dequeueBuffer(buf)) {
+ ALOGE("OverlayImpl p0 failed to dequeueBuffer");
+ return false;
+ }
+ }
+
+ if (utils::OV_PIPE1 & dest) {
+ if(!mPipe1->dequeueBuffer(buf)) {
+ ALOGE("OverlayImpl p1 failed to dequeueBuffer");
+ return false;
+ }
+ }
+
+ if (utils::OV_PIPE2 & dest) {
+ if(!mPipe2->dequeueBuffer(buf)) {
+ ALOGE("OverlayImpl p2 failed to dequeueBuffer");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+template <class P0, class P1, class P2>
+bool OverlayImpl<P0, P1, P2>::waitForVsync(utils::eDest dest)
+{
+ OVASSERT(mPipe0 && mPipe1 && mPipe2,
+ "%s: Pipes are null p0=%p p1=%p p2=%p",
+ __FUNCTION__, mPipe0, mPipe1, mPipe2);
+
+ if (utils::OV_PIPE0 & dest) {
+ if(!mPipe0->waitForVsync()) {
+ ALOGE("OverlayImpl p0 failed to waitForVsync");
+ return false;
+ }
+ }
+
+ if (utils::OV_PIPE1 & dest) {
+ if(!mPipe1->waitForVsync()) {
+ ALOGE("OverlayImpl p1 failed to waitForVsync");
+ return false;
+ }
+ }
+
+ if (utils::OV_PIPE2 & dest) {
+ if(!mPipe2->waitForVsync()) {
+ ALOGE("OverlayImpl p2 failed to waitForVsync");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+template <class P0, class P1, class P2>
+void OverlayImpl<P0, P1, P2>::setMemoryId(int id, utils::eDest dest)
+{
+ OVASSERT(mPipe0 && mPipe1 && mPipe2,
+ "%s: Pipes are null p0=%p p1=%p p2=%p",
+ __FUNCTION__, mPipe0, mPipe1, mPipe2);
+
+ if (utils::OV_PIPE0 & dest) {
+ mPipe0->setMemoryId(id);
+ }
+
+ if (utils::OV_PIPE1 & dest) {
+ mPipe1->setMemoryId(id);
+ }
+
+ if (utils::OV_PIPE2 & dest) {
+ mPipe2->setMemoryId(id);
+ }
+}
+
+template <class P0, class P1, class P2>
+utils::eOverlayPipeType OverlayImpl<P0, P1, P2>::getOvPipeType(utils::eDest dest) const
+{
+ OVASSERT(utils::isValidDest(dest), "%s: OverlayImpl invalid dest=%d",
+ __FUNCTION__, dest);
+
+ if (utils::OV_PIPE0 & dest) {
+ OVASSERT(mPipe0, "%s: OverlayImpl pipe0 is null", __FUNCTION__);
+ return mPipe0->getOvPipeType();
+ }
+
+ if (utils::OV_PIPE1 & dest) {
+ OVASSERT(mPipe1, "%s: OverlayImpl pipe1 is null", __FUNCTION__);
+ return mPipe1->getOvPipeType();
+ }
+
+ if (utils::OV_PIPE2 & dest) {
+ OVASSERT(mPipe2, "%s: OverlayImpl pipe2 is null", __FUNCTION__);
+ return mPipe2->getOvPipeType();
+ }
+
+ // Should never get here
+ return utils::OV_PIPE_TYPE_NULL;
+}
+
+template <class P0, class P1, class P2>
+void OverlayImpl<P0, P1, P2>::dump() const
+{
+ OVASSERT(mPipe0 && mPipe1 && mPipe2,
+ "%s: Pipes are null p0=%p p1=%p p2=%p",
+ __FUNCTION__, mPipe0, mPipe1, mPipe2);
+ ALOGE("== Dump OverlayImpl dump start ROT p0 ==");
+ mRotP0->dump();
+ ALOGE("== Dump OverlayImpl dump end ROT p0 ==");
+ ALOGE("== Dump OverlayImpl dump start ROT p1 ==");
+ mRotP1->dump();
+ ALOGE("== Dump OverlayImpl dump end ROT p1 ==");
+ ALOGE("== Dump OverlayImpl dump start ROT p2 ==");
+ mRotP2->dump();
+ ALOGE("== Dump OverlayImpl dump end ROT p2 ==");
+ ALOGE("== Dump OverlayImpl dump start p0 ==");
+ mPipe0->dump();
+ ALOGE("== Dump OverlayImpl dump end p0 ==");
+ ALOGE("== Dump OverlayImpl dump start p1 ==");
+ mPipe1->dump();
+ ALOGE("== Dump OverlayImpl dump end p1 ==");
+ ALOGE("== Dump OverlayImpl dump start p2 ==");
+ mPipe2->dump();
+ ALOGE("== Dump OverlayImpl dump end p2 ==");
+}
+
+
+} // overlay
+
+#endif // OVERLAY_IMPL_H
diff --git a/liboverlay/overlayLib.cpp b/liboverlay/overlayLib.cpp
deleted file mode 100755
index fe5c3d3..0000000
--- a/liboverlay/overlayLib.cpp
+++ /dev/null
@@ -1,2352 +0,0 @@
-/*
- * 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.
- */
-
-#include "overlayLib.h"
-#include "gralloc_priv.h"
-
-#define INTERLACE_MASK 0x80
-#define DEBUG_OVERLAY true
-/* Helper functions */
-static inline size_t ALIGN(size_t x, size_t align) {
- return (x + align-1) & ~(align-1);
-}
-
-using namespace overlay;
-using android::sp;
-using gralloc::IMemAlloc;
-using gralloc::IonController;
-using gralloc::alloc_data;
-
-#ifdef HDMI_AS_PRIMARY
-bool Overlay::sHDMIAsPrimary = true;
-#else
-bool Overlay::sHDMIAsPrimary = false;
-#endif
-
-template <class Type>
-void swapWidthHeight(Type& width, Type& height) {
- Type tmp = width;
- width = height;
- height = tmp;
-}
-
-int overlay::get_mdp_format(int format) {
- switch (format) {
- case HAL_PIXEL_FORMAT_RGBA_8888 :
- return MDP_RGBA_8888;
- case HAL_PIXEL_FORMAT_BGRA_8888:
- return MDP_BGRA_8888;
- case HAL_PIXEL_FORMAT_RGB_565:
- return MDP_RGB_565;
- case HAL_PIXEL_FORMAT_RGBX_8888:
- return MDP_RGBX_8888;
- case HAL_PIXEL_FORMAT_YCbCr_422_SP:
- return MDP_Y_CBCR_H2V1;
- case HAL_PIXEL_FORMAT_YCbCr_420_SP:
- return MDP_Y_CRCB_H2V2;
- case HAL_PIXEL_FORMAT_YCrCb_420_SP:
- return MDP_Y_CBCR_H2V2;
- case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
- return MDP_Y_CRCB_H2V2_TILE;
- case HAL_PIXEL_FORMAT_YV12:
- return MDP_Y_CR_CB_GH2V2;
- default:
- LOGE("%s: unknown color format [0x%x]", __FUNCTION__, format);
- return -1;
- }
- return -1;
-}
-
-int overlay::get_mdp_orientation(int value) {
- switch(value) {
- case 0: return 0;
- case HAL_TRANSFORM_FLIP_V: return MDP_FLIP_UD;
- case HAL_TRANSFORM_FLIP_H: return MDP_FLIP_LR;
- case HAL_TRANSFORM_ROT_90: return MDP_ROT_90;
- case HAL_TRANSFORM_ROT_90|HAL_TRANSFORM_FLIP_V:
- return MDP_ROT_90|MDP_FLIP_LR;
- case HAL_TRANSFORM_ROT_90|HAL_TRANSFORM_FLIP_H:
- return MDP_ROT_90|MDP_FLIP_UD;
- case HAL_TRANSFORM_ROT_180: return MDP_ROT_180;
- case HAL_TRANSFORM_ROT_270: return MDP_ROT_270;
- default:
- LOGE("%s: invalid rotation value (value = 0x%x",
- __FUNCTION__, value);
- return -1;
- }
- return -1;
-}
-
-// Rotator - input to output mapping
-int overlay::get_rot_output_format(int format) {
- switch (format) {
- case MDP_Y_CRCB_H2V2_TILE:
- return MDP_Y_CRCB_H2V2;
- case MDP_Y_CB_CR_H2V2:
- return MDP_Y_CBCR_H2V2;
- case MDP_Y_CR_CB_GH2V2:
- return MDP_Y_CRCB_H2V2;
- default:
- return format;
- }
- return -1;
-}
-
-// This function normalizes the crop values to be all even
-void overlay::normalize_crop(uint32_t& xy, uint32_t& wh) {
-
- if (xy & 0x0001) {
- // x or y is odd, increment it's value
- xy += 1;
- // Since we've incremented x(y), we need to decrement
- // w(h) accordingly
- if (wh & 0x0001) {
- // w or h is odd, decrement it by 1, to make it even
- EVEN_OUT(wh);
- } else {
- // w(h) is already even, hence we decrement by 2
- wh -=2;
- }
- } else {
- EVEN_OUT(wh);
- }
-}
-
-#define LOG_TAG "OverlayLIB"
-static void reportError(const char* message) {
- LOGE( "%s", message);
-}
-
-void overlay::dump(mdp_overlay& mOVInfo) {
- if (!DEBUG_OVERLAY)
- return;
- LOGE("mOVInfo:");
- LOGE("src: width %d height %d format %s user_data[0] %d", mOVInfo.src.width,
- mOVInfo.src.height, getFormatString(mOVInfo.src.format),
- mOVInfo.user_data[0]);
- LOGE("src_rect: x %d y %d w %d h %d", mOVInfo.src_rect.x,
- mOVInfo.src_rect.y, mOVInfo.src_rect.w, mOVInfo.src_rect.h);
- LOGE("dst_rect: x %d y %d w %d h %d", mOVInfo.dst_rect.x,
- mOVInfo.dst_rect.y, mOVInfo.dst_rect.w, mOVInfo.dst_rect.h);
- LOGE("z_order %d is_fg %d alpha %d transp_mask %d flags %x id %d",
- mOVInfo.z_order, mOVInfo.is_fg, mOVInfo.alpha, mOVInfo.transp_mask,
- mOVInfo.flags, mOVInfo.id);
-}
-
-void overlay::dump(msm_rotator_img_info& mRotInfo) {
- if (!DEBUG_OVERLAY)
- return;
- LOGE("mRotInfo:");
- LOGE("session_id %d dst_x %d dst_y %d rotations %d enable %d",
- mRotInfo.session_id, mRotInfo.dst_x, mRotInfo.dst_y,
- mRotInfo.rotations, mRotInfo.enable);
- LOGE("src: width %d height %d format %s", mRotInfo.src.width,
- mRotInfo.src.height, getFormatString(mRotInfo.src.format));
- LOGE("dst: width %d height %d format %s", mRotInfo.dst.width,
- mRotInfo.dst.height, getFormatString(mRotInfo.src.format));
- LOGE("src_rect: x %d y %d w %d h %d", mRotInfo.src_rect.x,
- mRotInfo.src_rect.y, mRotInfo.src_rect.w, mRotInfo.src_rect.h);
-}
-
-const char* overlay::getFormatString(int format){
- static const char* formats[] = {
- "MDP_RGB_565",
- "MDP_XRGB_8888",
- "MDP_Y_CBCR_H2V2",
- "MDP_ARGB_8888",
- "MDP_RGB_888",
- "MDP_Y_CRCB_H2V2",
- "MDP_YCRYCB_H2V1",
- "MDP_Y_CRCB_H2V1",
- "MDP_Y_CBCR_H2V1",
- "MDP_RGBA_8888",
- "MDP_BGRA_8888",
- "MDP_RGBX_8888",
- "MDP_Y_CRCB_H2V2_TILE",
- "MDP_Y_CBCR_H2V2_TILE",
- "MDP_Y_CR_CB_H2V2",
- "MDP_Y_CR_CB_GH2V2",
- "MDP_Y_CB_CR_H2V2",
- "MDP_Y_CRCB_H1V1",
- "MDP_Y_CBCR_H1V1",
- "MDP_IMGTYPE_LIMIT",
- "MDP_BGR_565",
- "MDP_FB_FORMAT",
- "MDP_IMGTYPE_LIMIT2"
- };
- return formats[format];
-}
-ZOrderManager* ZOrderManager::sInstance = 0;
-FrameBufferInfo* FrameBufferInfo::sFBInfoInstance = 0;
-
-int ZOrderManager::getZ(int fbnum){
- int zorder = NO_PIPE;;
- Mutex::Autolock objLock(mObjMutex);
- if(mPipesInuse == mMaxPipes) {
- LOGE("No free pipes available.. inUse = %d ", mPipesInuse);
- return NO_PIPE;
- }
- switch(fbnum) {
- case FRAMEBUFFER_0:
- for (int i = 0;i < NUM_CHANNELS; i++) {
- if(mFB0Pipes[i] == false) {
- mFB0Pipes[i]= true;
- zorder = i;
- break;
- }
- }
- break;
- case FRAMEBUFFER_1:
- case FRAMEBUFFER_2:
- for (int i = 0;i < mMaxPipes; i++) {
- if(mFB1Pipes[i] == false) {
- mFB1Pipes[i]= true;
- zorder = i;
- break;
- }
- }
- break;
- default:
- LOGE("getZ: Invalid framebuffer..");
- break;
- }
- mPipesInuse++;
- LOGE("getZ: return zorder = %d for fbdev = %d, pipesinUse = %d",
- zorder, fbnum, mPipesInuse);
- return zorder;
-}
-
-void ZOrderManager::decZ(int fbnum, int zorder){
- Mutex::Autolock objLock(mObjMutex);
- switch(fbnum) {
- case FRAMEBUFFER_0:
- LOG_ASSERT(!mFB0Pipes[zorder],"channel with ZOrder does not exist");
- LOGE("decZ: freeing the pipe with zorder = %d for fbdev = %d", zorder, fbnum);
- mFB0Pipes[zorder] = false;
- break;
- case FRAMEBUFFER_1:
- case FRAMEBUFFER_2:
- LOG_ASSERT(!mFB1Pipes[zorder],"channel with ZOrder does not exist");
- LOGE("decZ: freeing the pipe with zorder = %d for fbdev = %d", zorder, fbnum);
- mFB1Pipes[zorder] = false;
- break;
- default:
- LOGE("decZ: Invalid framebuffer ");
- break;
- }
- if(mPipesInuse > 0)
- mPipesInuse--;
- LOGE("decZ: Pipes in use = %d", mPipesInuse);
-}
-
-bool overlay::isHDMIConnected () {
- char value[PROPERTY_VALUE_MAX];
- property_get("hw.hdmiON", value, "0");
- int isHDMI = atoi(value);
- return isHDMI ? true : false;
-}
-
-bool overlay::is3DTV() {
- char is3DTV = '0';
- FILE *fp = fopen(EDID_3D_INFO_FILE, "r");
- if (fp) {
- fread(&is3DTV, 1, 1, fp);
- fclose(fp);
- }
- LOGI("3DTV EDID flag: %c", is3DTV);
- return (is3DTV == '0') ? false : true;
-}
-
-bool overlay::isPanel3D() {
- int fd = open("/dev/graphics/fb0", O_RDWR, 0);
- if (fd < 0) {
- reportError("Can't open framebuffer 0");
- return false;
- }
- fb_fix_screeninfo finfo;
- if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1) {
- reportError("FBIOGET_FSCREENINFO on fb0 failed");
- close(fd);
- fd = -1;
- return false;
- }
- close(fd);
- return (FB_TYPE_3D_PANEL == finfo.type) ? true : false;
-}
-
-bool overlay::usePanel3D() {
- if (Overlay::sHDMIAsPrimary)
- return is3DTV();
-
- if(!isPanel3D())
- return false;
- char value[PROPERTY_VALUE_MAX];
- property_get("persist.user.panel3D", value, "0");
- int usePanel3D = atoi(value);
- return usePanel3D ? true : false;
-}
-
-bool overlay::send3DInfoPacket (unsigned int format3D) {
- FILE *fp = fopen(FORMAT_3D_FILE, "wb");
- if (fp) {
- fprintf(fp, "%d", format3D);
- fclose(fp);
- fp = NULL;
- return true;
- }
- LOGE("%s:no sysfs entry for setting 3d mode!", __FUNCTION__);
- return false;
-}
-
-bool overlay::enableBarrier (unsigned int orientation) {
- FILE *fp = fopen(BARRIER_FILE, "wb");
- if (fp) {
- fprintf(fp, "%d", orientation);
- fclose(fp);
- fp = NULL;
- return true;
- }
- LOGE("%s:no sysfs entry for enabling barriers on 3D panel!", __FUNCTION__);
- return false;
-}
-
-int overlay::getColorFormat(int format)
-{
- if (format == HAL_PIXEL_FORMAT_YV12)
- return format;
- else if (format & INTERLACE_MASK)
- return format ^ HAL_PIXEL_FORMAT_INTERLACE;
- else
- return COLOR_FORMAT(format);
-}
-
-bool overlay::isInterlacedContent(int format)
-{
- if ((format != HAL_PIXEL_FORMAT_YV12) &&
- (format & INTERLACE_MASK))
- return true;
-
- return false;
-}
-
-unsigned int overlay::getOverlayConfig (unsigned int format3D, bool poll,
- bool isHDMI) {
- bool isTV3D = false;
- unsigned int curState = 0;
- if (poll)
- isHDMI = isHDMIConnected();
- if (isHDMI) {
- LOGD("%s: HDMI connected... checking the TV type", __FUNCTION__);
- if (format3D) {
- if (is3DTV())
- curState = OV_3D_VIDEO_3D_TV;
- else
- curState = OV_3D_VIDEO_2D_TV;
- } else
- curState = OV_2D_VIDEO_ON_TV;
- } else {
- LOGD("%s: HDMI not connected...", __FUNCTION__);
- if(format3D) {
- if (usePanel3D())
- curState = OV_3D_VIDEO_3D_PANEL;
- else
- curState = OV_3D_VIDEO_2D_PANEL;
- }
- else
- curState = OV_2D_VIDEO_ON_PANEL;
- }
- return curState;
-}
-
-/* clears any VG pipes allocated to the fb devices */
-int overlay::initOverlay() {
- msmfb_mixer_info_req req;
- mdp_mixer_info *minfo = NULL;
- char name[64];
- int fd = -1;
- for(int i = 0; i < NUM_FB_DEVICES; i++) {
- snprintf(name, 64, FB_DEVICE_TEMPLATE, i);
- LOGD("initoverlay:: opening the device:: %s", name);
- fd = open(name, O_RDWR, 0);
- if(fd < 0) {
- LOGE("cannot open framebuffer(%d)", i);
- return -1;
- }
- //Get the mixer configuration */
- req.mixer_num = i;
- if (ioctl(fd, MSMFB_MIXER_INFO, &req) == -1) {
- LOGE("ERROR: MSMFB_MIXER_INFO ioctl failed");
- close(fd);
- return -1;
- }
- minfo = req.info;
- for (int j = 0; j < req.cnt; j++) {
- LOGD("ndx=%d num=%d z_order=%d", minfo->pndx, minfo->pnum,
- minfo->z_order);
- // except the RGB base layer with z_order of -1, clear any
- // other pipes connected to mixer.
- if((minfo->z_order) != -1) {
- int index = minfo->pndx;
- LOGD("Unset overlay with index: %d at mixer %d", index, i);
- if(ioctl(fd, MSMFB_OVERLAY_UNSET, &index) == -1) {
- LOGE("ERROR: MSMFB_OVERLAY_UNSET failed");
- close(fd);
- return -1;
- }
- }
- minfo++;
- }
- close(fd);
- fd = -1;
- }
- return 0;
-}
-
-Overlay::Overlay() : mChannelUP(false), mExternalDisplay(false),
- mS3DFormat(0), mCroppedSrcWidth(0),
- mCroppedSrcHeight(0), mState(-1) {
- mOVBufferInfo.width = mOVBufferInfo.height = 0;
- mOVBufferInfo.format = mOVBufferInfo.size = 0;
-}
-
-Overlay::~Overlay() {
- closeChannel();
-}
-
-int Overlay::getFBWidth(int channel) const {
- return objOvCtrlChannel[channel].getFBWidth();
-}
-
-int Overlay::getFBHeight(int channel) const {
- return objOvCtrlChannel[channel].getFBHeight();
-}
-
-bool Overlay::startChannel(const overlay_buffer_info& info, int fbnum,
- bool norot, bool uichannel,
- unsigned int format3D, int channel,
- int flags, int num_buffers) {
- int zorder = 0;
- mCroppedSrcWidth = info.width;
- mCroppedSrcHeight = info.height;
- if (format3D)
- zorder = channel;
- if (mState == -1)
- mState = OV_UI_MIRROR_TV;
-
- mChannelUP = objOvCtrlChannel[channel].startControlChannel(info, fbnum,
- norot, uichannel,
- format3D, zorder, flags);
- if (!mChannelUP) {
- LOGE("startChannel for fb%d failed", fbnum);
- return mChannelUP;
- }
- bool secure = flags & SECURE_OVERLAY_SESSION;
- objOvCtrlChannel[channel].setSize(info.size);
- return objOvDataChannel[channel].startDataChannel(objOvCtrlChannel[channel], fbnum,
- norot, secure, uichannel, num_buffers);
-}
-
-bool Overlay::closeChannel() {
-
- if (!mChannelUP)
- return true;
-
- if(mS3DFormat) {
- if (mExternalDisplay)
- overlay::send3DInfoPacket(0);
- else if (mState == OV_3D_VIDEO_3D_PANEL) {
- if (sHDMIAsPrimary)
- overlay::send3DInfoPacket(0);
- else
- enableBarrier(0);
- }
- }
- for (int i = 0; i < NUM_CHANNELS; i++) {
- objOvCtrlChannel[i].closeControlChannel();
- objOvDataChannel[i].closeDataChannel();
- }
- mChannelUP = false;
- mS3DFormat = 0;
- mOVBufferInfo.width = 0;
- mOVBufferInfo.height = 0;
- mOVBufferInfo.format = 0;
- mOVBufferInfo.size = 0;
- mState = -1;
- return true;
-}
-
-void Overlay::closeExternalChannel() {
- if (objOvCtrlChannel[VG1_PIPE].isChannelUP()) {
- objOvCtrlChannel[VG1_PIPE].closeControlChannel();
- objOvDataChannel[VG1_PIPE].closeDataChannel();
- }
-}
-
-bool Overlay::getPosition(int& x, int& y, uint32_t& w, uint32_t& h, int channel) {
- return objOvCtrlChannel[channel].getPosition(x, y, w, h);
-}
-
-bool Overlay::getOrientation(int& orientation, int channel) const {
- return objOvCtrlChannel[channel].getOrientation(orientation);
-}
-
-bool Overlay::setDeviceOrientation(int orientation) {
- // Use this to calculate the position on HDMI
- mDevOrientation = orientation;
- return true;
-}
-
-bool Overlay::setPosition(int x, int y, uint32_t w, uint32_t h) {
- bool ret = false;
- overlay_rect secDest;
- overlay_rect priDest;
- int currX, currY;
- uint32_t currW, currH;
- // Set even destination co-ordinates
- EVEN_OUT(x); EVEN_OUT(y);
- EVEN_OUT(w); EVEN_OUT(h);
- objOvCtrlChannel[VG0_PIPE].getPosition(currX, currY, currW, currH);
- priDest.x = x, priDest.y = y;
- priDest.w = w, priDest.h = h;
- if(x != currX || y != currY || w != currW || h != currH) {
- switch (mState) {
- case OV_UI_MIRROR_TV:
- case OV_2D_VIDEO_ON_PANEL:
- case OV_3D_VIDEO_2D_PANEL:
- return setChannelPosition(x, y, w, h, VG0_PIPE);
- break;
- case OV_2D_VIDEO_ON_TV:
- if (FrameBufferInfo::getInstance()->canSupportTrueMirroring()) {
- objOvCtrlChannel[VG1_PIPE].getAspectRatioPosition(
- mCroppedSrcWidth, mCroppedSrcHeight, mDevOrientation,
- &priDest, &secDest);
- } else {
- objOvCtrlChannel[VG1_PIPE].getAspectRatioPosition(
- mCroppedSrcWidth, mCroppedSrcHeight, &secDest);
- }
- setChannelPosition(secDest.x, secDest.y, secDest.w, secDest.h,
- VG1_PIPE);
- return setChannelPosition(x, y, w, h, VG0_PIPE);
- break;
- case OV_3D_VIDEO_3D_PANEL:
- for (int i = 0; i < NUM_CHANNELS; i++) {
- if (sHDMIAsPrimary)
- objOvCtrlChannel[i].getPositionS3D(i, mS3DFormat, &secDest);
- else {
- if (!objOvCtrlChannel[i].useVirtualFB()) {
- LOGE("%s: failed virtual fb for channel %d", __FUNCTION__, i);
- return false;
- }
- objOvCtrlChannel[i].getPositionS3D(i, 0x1, &secDest);
- }
- if(!setChannelPosition(secDest.x, secDest.y, secDest.w,
- secDest.h, i)) {
- LOGE("%s: failed for channel %d", __FUNCTION__, i);
- return false;
- }
- }
- break;
- case OV_3D_VIDEO_2D_TV:
- case OV_3D_VIDEO_3D_TV:
- for (int i = 0; i < NUM_CHANNELS; i++) {
- ret = objOvCtrlChannel[i].getPositionS3D(i, mS3DFormat,
- &secDest);
- if (!ret)
- ret = setChannelPosition(x, y, w, h, i);
- else
- ret = setChannelPosition(secDest.x, secDest.y, secDest.w,
- secDest.h, i);
- if (!ret) {
- LOGE("%s: failed for channel %d", __FUNCTION__, i);
- return ret;
- }
- }
- break;
- default:
- LOGE("%s:Unknown state %d", __FUNCTION__, mState);
- break;
- }
- }
- return true;
-}
-
-bool Overlay::setChannelPosition(int x, int y, uint32_t w, uint32_t h, int channel) {
- return objOvCtrlChannel[channel].setPosition(x, y, w, h);
-}
-
-bool Overlay::updateOverlaySource(const overlay_buffer_info& info, int orientation,
- int flags) {
- bool ret = false;
- int currentFlags = 0;
-
- bool needUpdateFlags = false;
- if (objOvCtrlChannel[0].isChannelUP()) {
- needUpdateFlags = objOvCtrlChannel[0].doFlagsNeedUpdate(flags);
- }
-
- bool geometryChanged = true;
- if (info.width == mOVBufferInfo.width &&
- info.height == mOVBufferInfo.height &&
- info.format == mOVBufferInfo.format) {
- geometryChanged = false;
- }
-
- if (sHDMIAsPrimary)
- needUpdateFlags = false;
-
- if ((false == needUpdateFlags) && (false == geometryChanged)) {
- return true;
- }
-
- // Disable rotation for the HDMI channels
- int orientHdmi = 0;
- int orientPrimary = sHDMIAsPrimary ? 0 : orientation;
- int orient[2] = {orientPrimary, orientHdmi};
- // disable waitForVsync on HDMI, since we call the wait ioctl
- int ovFlagsExternal = 0;
- int ovFlagsPrimary = sHDMIAsPrimary ? (flags |= WAIT_FOR_VSYNC): flags;
- int ovFlags[2] = {flags, ovFlagsExternal};
- switch(mState) {
- case OV_3D_VIDEO_3D_PANEL:
- orient[1] = sHDMIAsPrimary ? 0 : orientation;
- break;
- case OV_3D_VIDEO_3D_TV:
- orient[0] = 0;
- break;
- default:
- break;
- }
-
- int numChannelsToUpdate = NUM_CHANNELS;
- if (!geometryChanged) {
- // Only update the primary channel - we only need to update the
- // wait/no-wait flags
- if (objOvCtrlChannel[0].isChannelUP()) {
- return objOvCtrlChannel[0].updateOverlayFlags(flags);
- }
- }
-
- // Set the overlay source info
- for (int i = 0; i < NUM_CHANNELS; i++) {
- if (objOvCtrlChannel[i].isChannelUP()) {
- ret = objOvCtrlChannel[i].updateOverlaySource(info, orient[i], ovFlags[i]);
- if (!ret) {
- LOGE("objOvCtrlChannel[%d].updateOverlaySource failed", i);
- return false;
- }
- objOvCtrlChannel[i].setSize(info.size);
- ret = objOvDataChannel[i].updateDataChannel(info.size);
- }
- }
- if (ret) {
- mOVBufferInfo = info;
- } else
- LOGE("update failed");
- return ret;
-}
-
-bool Overlay::getAspectRatioPosition(int w, int h, overlay_rect *rect, int channel) {
- return objOvCtrlChannel[channel].getAspectRatioPosition(w, h, rect);
-}
-
-int Overlay::getS3DFormat(int format) {
- // The S3D is part of the HAL_PIXEL_FORMAT_YV12 value. Add
- // an explicit check for the format
- if (format == HAL_PIXEL_FORMAT_YV12) {
- return 0;
- }
- int format3D = FORMAT_3D(format);
- int fIn3D = FORMAT_3D_INPUT(format3D); // MSB 2 bytes are input format
- int fOut3D = FORMAT_3D_OUTPUT(format3D); // LSB 2 bytes are output format
- format3D = fIn3D | fOut3D;
- if (!fIn3D) {
- format3D |= fOut3D << SHIFT_3D; //Set the input format
- }
- if (!fOut3D) {
- format3D |= fIn3D >> SHIFT_3D; //Set the output format
- }
- return format3D;
-}
-
-bool Overlay::setSource(const overlay_buffer_info& info, int orientation,
- int hdmiConnected, int flags, int num_buffers) {
- // Separate the color format from the 3D format.
- // If there is 3D content; the effective format passed by the client is:
- // effectiveFormat = 3D_IN | 3D_OUT | ColorFormat
- int newState = mState;
- bool stateChange = false, ret = true;
- bool isHDMIStateChange = (mExternalDisplay != hdmiConnected) && (mState != -1);
- unsigned int format3D = getS3DFormat(info.format);
- int colorFormat = getColorFormat(info.format);
- if (isHDMIStateChange || -1 == mState) {
- // we were mirroring UI. Also HDMI state stored was stale
- newState = getOverlayConfig (format3D, false, hdmiConnected);
- stateChange = (mState == newState) ? false : true;
- }
-
- if (stateChange) {
- mExternalDisplay = hdmiConnected;
- mState = newState;
- mS3DFormat = format3D;
- if (mState == OV_3D_VIDEO_2D_PANEL || mState == OV_3D_VIDEO_2D_TV) {
- LOGI("3D content on 2D display: set the output format as monoscopic");
- mS3DFormat = FORMAT_3D_INPUT(format3D) | HAL_3D_OUT_MONOSCOPIC_MASK;
- }
- // We always enable the rotator for the primary.
- bool noRot = false;
- bool uiChannel = false;
- int fbnum = 0;
- switch(mState) {
- case OV_2D_VIDEO_ON_PANEL:
- if(isHDMIStateChange) {
- //close HDMI Only
- closeExternalChannel();
- break;
- }
- case OV_3D_VIDEO_2D_PANEL:
- closeChannel();
- return startChannel(info, FRAMEBUFFER_0, noRot, false,
- mS3DFormat, VG0_PIPE, flags, num_buffers);
- break;
- case OV_3D_VIDEO_3D_PANEL:
- closeChannel();
- if (sHDMIAsPrimary) {
- noRot = true;
- flags |= WAIT_FOR_VSYNC;
- send3DInfoPacket(mS3DFormat & OUTPUT_MASK_3D);
- }
- for (int i=0; i<NUM_CHANNELS; i++) {
- if(!startChannel(info, FRAMEBUFFER_0, noRot, uiChannel,
- mS3DFormat, i, flags, num_buffers)) {
- LOGE("%s:failed to open channel %d", __FUNCTION__, i);
- return false;
- }
- }
- break;
- case OV_2D_VIDEO_ON_TV:
- if(isHDMIStateChange) {
- //start only HDMI channel
- noRot = true;
- bool waitForVsync = true;
- // External display connected, start corresponding channel
- // mExternalDisplay will hold the fbnum
- if(!startChannel(info, mExternalDisplay, noRot, false, mS3DFormat,
- VG1_PIPE, waitForVsync, num_buffers)) {
- LOGE("%s:failed to open channel %d", __func__, VG1_PIPE);
- return false;
- }
- int currX, currY;
- uint32_t currW, currH;
- overlay_rect priDest;
- overlay_rect secDest;
- objOvCtrlChannel[VG0_PIPE].getPosition(currX, currY, currW, currH);
- priDest.x = currX, priDest.y = currY;
- priDest.w = currW, priDest.h = currH;
- if (FrameBufferInfo::getInstance()->canSupportTrueMirroring()) {
- objOvCtrlChannel[VG1_PIPE].getAspectRatioPosition(
- mCroppedSrcWidth, mCroppedSrcHeight, mDevOrientation,
- &priDest, &secDest);
- } else {
- objOvCtrlChannel[VG1_PIPE].getAspectRatioPosition(
- mCroppedSrcWidth, mCroppedSrcHeight, &secDest);
- }
- return setChannelPosition(secDest.x, secDest.y, secDest.w, secDest.h, VG1_PIPE);
- }
- case OV_3D_VIDEO_2D_TV:
- closeChannel();
- for (int i=0; i<NUM_CHANNELS; i++) {
- fbnum = i;
- //start two channels for one for primary and external.
- if (fbnum) {
- // Disable rotation for external
- noRot = true;
- //set fbnum to hdmiConnected, which holds the ext display
- fbnum = hdmiConnected;
- flags &= ~WAIT_FOR_VSYNC;
- }
- if(!startChannel(info, fbnum, noRot, false, mS3DFormat,
- i, flags, num_buffers)) {
- LOGE("%s:failed to open channel %d", __FUNCTION__, i);
- return false;
- }
- }
- return true;
- break;
- case OV_3D_VIDEO_3D_TV:
- closeChannel();
- for (int i=0; i<NUM_CHANNELS; i++) {
- if(!startChannel(info, FRAMEBUFFER_1, true, false,
- mS3DFormat, i, flags, num_buffers)) {
- LOGE("%s:failed to open channel %d", __FUNCTION__, i);
- return false;
- }
- send3DInfoPacket(mS3DFormat & OUTPUT_MASK_3D);
- }
- break;
- default:
- LOGE("%s:Unknown state %d", __FUNCTION__, mState);
- break;
- }
- } else {
- ret = updateOverlaySource(info, orientation, flags);
-// LGE_CHANGE_S, [G1_Player][mukyung.jung@lge.com], 20120206, Apply SR 00718706 to fix noise of QCIF contents {
- return ret;
-// LGE_CHANGE_E, [G1_Player][mukyung.jung@lge.com], 20120206, Apply SR 00718706 to fix noise of QCIF contents }
- }
- return true;
-}
-
-bool Overlay::setCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h) {
- if (!mChannelUP) {
- LOGE("%s: channel not set", __FUNCTION__);
- return false;
- }
- overlay_rect rect, inRect;
- inRect.x = x; inRect.y = y; inRect.w = w; inRect.h = h;
- mCroppedSrcWidth = w;
- mCroppedSrcHeight = h;
- switch (mState) {
- case OV_UI_MIRROR_TV:
- case OV_2D_VIDEO_ON_PANEL:
- return setChannelCrop(x, y, w, h, VG0_PIPE);
- break;
- case OV_3D_VIDEO_2D_PANEL:
- objOvDataChannel[VG0_PIPE].getCropS3D(&inRect, VG0_PIPE, mS3DFormat, &rect);
- return setChannelCrop(rect.x, rect.y, rect.w, rect.h, VG0_PIPE);
- break;
- case OV_2D_VIDEO_ON_TV:
- for (int i=0; i<NUM_CHANNELS; i++) {
- if(!setChannelCrop(x, y, w, h, i)) {
- LOGE("%s: failed for pipe %d", __FUNCTION__, i);
- return false;
- }
- }
- break;
- case OV_3D_VIDEO_3D_PANEL:
- case OV_3D_VIDEO_2D_TV:
- case OV_3D_VIDEO_3D_TV:
- for (int i=0; i<NUM_CHANNELS; i++) {
- objOvDataChannel[i].getCropS3D(&inRect, i, mS3DFormat, &rect);
- if(!setChannelCrop(rect.x, rect.y, rect.w, rect.h, i)) {
- LOGE("%s: failed for pipe %d", __FUNCTION__, i);
- return false;
- }
- }
- break;
- default:
- LOGE("%s:Unknown state %d", __FUNCTION__, mState);
- break;
- }
- return true;
-}
-
-bool Overlay::setChannelCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h, int channel) {
- return objOvDataChannel[channel].setCrop(x, y, w, h);
-}
-
-bool Overlay::updateOverlayFlags(int flags) {
- return objOvCtrlChannel[VG0_PIPE].updateOverlayFlags(flags);
-}
-
-bool Overlay::setTransform(int value) {
- int barrier = 0;
- switch (mState) {
- case OV_UI_MIRROR_TV:
- case OV_2D_VIDEO_ON_PANEL:
- case OV_3D_VIDEO_2D_PANEL:
- return objOvCtrlChannel[VG0_PIPE].setTransform(value);
- break;
- case OV_2D_VIDEO_ON_TV:
- case OV_3D_VIDEO_2D_TV:
- case OV_3D_VIDEO_3D_TV:
- for (int i=0; i<NUM_CHANNELS; i++) {
- if(!objOvCtrlChannel[i].setTransform(value)) {
- LOGE("%s:failed for channel %d", __FUNCTION__, i);
- return false;
- }
- }
- break;
- case OV_3D_VIDEO_3D_PANEL:
- switch (value) {
- case HAL_TRANSFORM_ROT_90:
- case HAL_TRANSFORM_ROT_270:
- barrier = BARRIER_LANDSCAPE;
- break;
- default:
- barrier = BARRIER_PORTRAIT;
- break;
- if(!enableBarrier(barrier))
- LOGE("%s:failed to enable barriers for 3D video", __FUNCTION__);
- }
- for (int i=0; i<NUM_CHANNELS; i++) {
- if(!objOvCtrlChannel[i].setTransform(value)) {
- LOGE("%s:failed for channel %d", __FUNCTION__, i);
- return false;
- }
- }
- break;
- default:
- LOGE("%s:Unknown state %d", __FUNCTION__, mState);
- break;
- }
- return true;
-}
-
-bool Overlay::setFd(int fd, int channel) {
- return objOvDataChannel[channel].setFd(fd);
-}
-
-bool Overlay::queueBuffer(uint32_t offset, int channel) {
- return objOvDataChannel[channel].queueBuffer(offset);
-}
-
-bool Overlay::waitForHdmiVsync(int channel) {
- return objOvDataChannel[channel].waitForHdmiVsync();
-}
-
-bool Overlay::queueBuffer(buffer_handle_t buffer) {
- private_handle_t const* hnd = reinterpret_cast
- <private_handle_t const*>(buffer);
- if (!hnd) {
- LOGE("Overlay::queueBuffer invalid handle");
- return false;
- }
- const size_t offset = hnd->offset;
- const int fd = hnd->fd;
- switch (mState) {
- case OV_UI_MIRROR_TV:
- case OV_2D_VIDEO_ON_PANEL:
- case OV_3D_VIDEO_2D_PANEL:
- if(!queueBuffer(fd, offset, VG0_PIPE)) {
- LOGE("%s:failed for channel 0", __FUNCTION__);
- return false;
- }
- break;
- case OV_2D_VIDEO_ON_TV:
- case OV_3D_VIDEO_3D_PANEL:
- case OV_3D_VIDEO_2D_TV:
- case OV_3D_VIDEO_3D_TV:
- for (int i=NUM_CHANNELS-1; i>=0; i--) {
- if(!queueBuffer(fd, offset, i)) {
- LOGE("%s:failed for channel %d", __FUNCTION__, i);
- return false;
- }
- }
- //Wait for HDMI done..
- if(!waitForHdmiVsync(VG1_PIPE)) {
- LOGE("%s: waitforHdmiVsync failed", __FUNCTION__);
- return false;
- }
- break;
- default:
- LOGE("%s:Unknown state %d", __FUNCTION__, mState);
- break;
- }
- return true;
-}
-
-bool Overlay::queueBuffer(int fd, uint32_t offset, int channel) {
- bool ret = false;
- ret = setFd(fd, channel);
- if(!ret) {
- LOGE("Overlay::queueBuffer channel %d setFd failed", channel);
- return false;
- }
- ret = queueBuffer(offset, channel);
- if(!ret) {
- LOGE("Overlay::queueBuffer channel %d queueBuffer failed", channel);
- return false;
- }
- return ret;
-}
-
-OverlayControlChannel::OverlayControlChannel() : mNoRot(false), mFD(-1), mRotFD(-1),
- mFormat3D(0), mIsChannelUpdated(true) {
- memset(&mOVInfo, 0, sizeof(mOVInfo));
- memset(&m3DOVInfo, 0, sizeof(m3DOVInfo));
- memset(&mRotInfo, 0, sizeof(mRotInfo));
-}
-
-
-OverlayControlChannel::~OverlayControlChannel() {
- closeControlChannel();
-}
-
-bool OverlayControlChannel::getAspectRatioPosition(int w, int h, overlay_rect *rect)
-{
- int width = w, height = h, x, y;
- int fbWidth = getFBWidth();
- int fbHeight = getFBHeight();
- // width and height for YUV TILE format
- int tempWidth = w, tempHeight = h;
- /* Calculate the width and height if it is YUV TILE format*/
- if(getFormat() == HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED) {
- tempWidth = w - ( (((w-1)/64 +1)*64) - w);
- tempHeight = h - ((((h-1)/32 +1)*32) - h);
- }
- if (width * fbHeight > fbWidth * height) {
- height = fbWidth * height / width;
- EVEN_OUT(height);
- width = fbWidth;
- } else if (width * fbHeight < fbWidth * height) {
- width = fbHeight * width / height;
- EVEN_OUT(width);
- height = fbHeight;
- } else {
- width = fbWidth;
- height = fbHeight;
- }
- /* Scaling of upto a max of 8 times supported */
- if(width >(tempWidth * HW_OVERLAY_MAGNIFICATION_LIMIT)){
- width = HW_OVERLAY_MAGNIFICATION_LIMIT * tempWidth;
- }
- if(height >(tempHeight*HW_OVERLAY_MAGNIFICATION_LIMIT)) {
- height = HW_OVERLAY_MAGNIFICATION_LIMIT * tempHeight;
- }
- if (width > fbWidth) width = fbWidth;
- if (height > fbHeight) height = fbHeight;
-
- char value[PROPERTY_VALUE_MAX];
- property_get("hw.actionsafe.width", value, "0");
- float asWidth = atof(value);
- property_get("hw.actionsafe.height", value, "0");
- float asHeight = atof(value);
- width = width * (1.0f - asWidth / 100.0f);
- height = height * (1.0f - asHeight / 100.0f);
-
- x = (fbWidth - width) / 2;
- y = (fbHeight - height) / 2;
- rect->x = x;
- rect->y = y;
- rect->w = width;
- rect->h = height;
- return true;
-}
-
-
-// This function gets the destination position for Seconday display
-// based on the position and aspect ratio of the primary
-bool OverlayControlChannel::getAspectRatioPosition(int w, int h, int orientation,
- overlay_rect *inRect, overlay_rect *outRect) {
- float priWidth = FrameBufferInfo::getInstance()->getWidth();
- float priHeight = FrameBufferInfo::getInstance()->getHeight();
- float fbWidth = getFBWidth();
- float fbHeight = getFBHeight();
- float wRatio = 1.0;
- float hRatio = 1.0;
- float xRatio = 1.0;
- float yRatio = 1.0;
-
- int xPos = 0;
- int yPos = 0;
- int tmp = 0;
- overlay_rect rect;
- switch(orientation) {
- case MDP_ROT_NOP:
- case MDP_ROT_180:
- getAspectRatioPosition((int)priWidth, (int)priHeight, &rect);
- xPos = rect.x;
- yPos = rect.y;
- fbWidth = rect.w;
- fbHeight = rect.h;
-
- if(orientation == MDP_ROT_180) {
- inRect->x = priWidth - (inRect->x + inRect->w);
- inRect->y = priHeight - (inRect->y + inRect->h);
- }
- break;
- case MDP_ROT_90:
- case MDP_ROT_270:
- if(orientation == MDP_ROT_90) {
- tmp = inRect->y;
- inRect->y = priWidth - (inRect->x + inRect->w);
- inRect->x = tmp;
- }
- else if(orientation == MDP_ROT_270) {
- tmp = inRect->x;
- inRect->x = priHeight - (inRect->y + inRect->h);
- inRect->y = tmp;
- }
- //Swap the destination width/height
- swapWidthHeight(inRect->w, inRect->h);
- // Swap width/height for primary
- swapWidthHeight(priWidth, priHeight);
- getAspectRatioPosition((int)priWidth, (int)priHeight, &rect);
- xPos = rect.x;
- yPos = rect.y;
- fbWidth = rect.w;
- fbHeight = rect.h;
- break;
- default:
- LOGE("In %s: Unknown Orientation", __FUNCTION__);
- break;
- }
- //Calculate the position...
- xRatio = inRect->x/priWidth;
- yRatio = inRect->y/priHeight;
-
- wRatio = inRect->w/priWidth;
- hRatio = inRect->h/priHeight;
- outRect->x = (xRatio * fbWidth) + xPos;
- outRect->y = (yRatio * fbHeight) + yPos;
-
- outRect->w = (wRatio * fbWidth);
- outRect->h = hRatio * fbHeight;
- LOGD("Calculated AS Position for HDMI: X= %d, y = %d w = %d h = %d",
- outRect->x, outRect->y,outRect->w, outRect->h);
- return true;
-}
-
-
-bool OverlayControlChannel::getPositionS3D(int channel, int format, overlay_rect *rect) {
- int wDisp = getFBWidth();
- int hDisp = getFBHeight();
- switch (format & OUTPUT_MASK_3D) {
- case HAL_3D_OUT_SIDE_BY_SIDE_MASK:
- if (channel == VG0_PIPE) {
- rect->x = 0;
- rect->y = 0;
- rect->w = wDisp/2;
- rect->h = hDisp;
- } else {
- rect->x = wDisp/2;
- rect->y = 0;
- rect->w = wDisp/2;
- rect->h = hDisp;
- }
- break;
- case HAL_3D_OUT_TOP_BOTTOM_MASK:
- if (channel == VG0_PIPE) {
- rect->x = 0;
- rect->y = 0;
- rect->w = wDisp;
- rect->h = hDisp/2;
- } else {
- rect->x = 0;
- rect->y = hDisp/2;
- rect->w = wDisp;
- rect->h = hDisp/2;
- }
- break;
- case HAL_3D_OUT_MONOSCOPIC_MASK:
- if (channel == VG1_PIPE) {
- rect->x = 0;
- rect->y = 0;
- rect->w = wDisp;
- rect->h = hDisp;
- }
- else
- return false;
- break;
- case HAL_3D_OUT_INTERLEAVE_MASK:
- break;
- default:
- reportError("Unsupported 3D output format");
- break;
- }
- return true;
-}
-
-bool OverlayControlChannel::openDevices(int fbnum) {
- if (fbnum < 0)
- return false;
-
- char dev_name[64];
- snprintf(dev_name, 64, FB_DEVICE_TEMPLATE, fbnum);
- mFD = open(dev_name, O_RDWR, 0);
- if (mFD < 0) {
- reportError("Cant open framebuffer ");
- return false;
- }
-
- fb_fix_screeninfo finfo;
- if (ioctl(mFD, FBIOGET_FSCREENINFO, &finfo) == -1) {
- reportError("FBIOGET_FSCREENINFO on fb1 failed");
- close(mFD);
- mFD = -1;
- return false;
- }
-
- fb_var_screeninfo vinfo;
- if (ioctl(mFD, FBIOGET_VSCREENINFO, &vinfo) == -1) {
- reportError("FBIOGET_VSCREENINFO on fb1 failed");
- close(mFD);
- mFD = -1;
- return false;
- }
- mFBWidth = vinfo.xres;
- mFBHeight = vinfo.yres;
- mFBbpp = vinfo.bits_per_pixel;
- mFBystride = finfo.line_length;
-
- if (!mNoRot) {
- mRotFD = open("/dev/msm_rotator", O_RDWR, 0);
- if (mRotFD < 0) {
- reportError("Cant open rotator device");
- close(mFD);
- mFD = -1;
- return false;
- }
- }
-
- return true;
-}
-
-bool OverlayControlChannel::setOverlayInformation(const overlay_buffer_info& info,
- int zorder, int flags, int requestType) {
- int w = info.width;
- int h = info.height;
- int format = info.format;
-
- mOVInfo.src.width = w;
- mOVInfo.src.height = h;
- mOVInfo.src_rect.x = 0;
- mOVInfo.src_rect.y = 0;
- mOVInfo.dst_rect.x = 0;
- mOVInfo.dst_rect.y = 0;
- mOVInfo.dst_rect.w = w;
- mOVInfo.dst_rect.h = h;
- if(format == MDP_Y_CRCB_H2V2_TILE) {
- if (mNoRot) {
- mOVInfo.src_rect.w = w - ((((w-1)/64 +1)*64) - w);
- mOVInfo.src_rect.h = h - ((((h-1)/32 +1)*32) - h);
- } else {
- mOVInfo.src_rect.w = w;
- mOVInfo.src_rect.h = h;
- mOVInfo.src.width = (((w-1)/64 +1)*64);
- mOVInfo.src.height = (((h-1)/32 +1)*32);
- mOVInfo.src_rect.x = mOVInfo.src.width - w;
- mOVInfo.src_rect.y = mOVInfo.src.height - h;
- }
- } else {
- mOVInfo.src_rect.w = w;
- mOVInfo.src_rect.h = h;
- }
-
- mOVInfo.src.format = format;
- int dst_w = w;
- int dst_h = h;
-
- if (dst_w > mFBWidth) {
- dst_w = mFBWidth;
- dst_h = dst_h * mFBWidth / w;
- }
- if (dst_h > mFBHeight) {
- dst_h = mFBHeight;
- dst_w = dst_w * mFBHeight / h;
- }
- mOVInfo.dst_rect.w = dst_w;
- mOVInfo.dst_rect.h = dst_h;
- mOVInfo.user_data[0] = 0;
- if (requestType == NEW_REQUEST) {
- mOVInfo.id = MSMFB_NEW_REQUEST;
- mOVInfo.z_order = zorder;
- mOVInfo.alpha = 0xff;
- mOVInfo.transp_mask = 0xffffffff;
- }
- mOVInfo.flags = 0;
- setInformationFromFlags(flags, mOVInfo);
- mOVInfo.dpp.sharp_strength = 0;
- return true;
-}
-
-void OverlayControlChannel::setInformationFromFlags(int flags, mdp_overlay& ov)
-{
- if (flags & INTERLACED_CONTENT) {
- mOVInfo.flags |= MDP_DEINTERLACE;
- } else {
- mOVInfo.flags &= ~MDP_DEINTERLACE;
- }
-
- if ((flags & WAIT_FOR_VSYNC) == 0)
- mOVInfo.flags |= MDP_OV_PLAY_NOWAIT;
- else
- mOVInfo.flags &= ~MDP_OV_PLAY_NOWAIT;
-
- if(flags & SECURE_OVERLAY_SESSION)
- mOVInfo.flags |= MDP_SECURE_OVERLAY_SESSION;
- else
- mOVInfo.flags &= ~MDP_SECURE_OVERLAY_SESSION;
-
- //set the default sharpening settings
- mOVInfo.flags |= MDP_SHARPENING;
-
- if (flags & DISABLE_FRAMEBUFFER_FETCH)
- mOVInfo.is_fg = 1;
- else
- mOVInfo.is_fg = 0;
-
- if (flags & OVERLAY_PIPE_SHARE) {
- mOVInfo.flags |= MDP_OV_PIPE_SHARE;
- } else {
- mOVInfo.flags &= ~MDP_OV_PIPE_SHARE;
- }
- mOVInfo.dpp.sharp_strength = 0;
-
-}
-
-bool OverlayControlChannel::doFlagsNeedUpdate(int flags) {
- bool needUpdate = false;
-
- if ((flags & WAIT_FOR_VSYNC) == 0) {
- if (!(mOVInfo.flags & MDP_OV_PLAY_NOWAIT)) {
- needUpdate = true;
- }
- }
- if (flags & WAIT_FOR_VSYNC) {
- if (mOVInfo.flags & MDP_OV_PLAY_NOWAIT) {
- needUpdate = true;
- }
- }
-
- if ((flags & DISABLE_FRAMEBUFFER_FETCH) == 0) {
- if (mOVInfo.is_fg == 1) {
- needUpdate = true;
- }
- }
- if (flags & DISABLE_FRAMEBUFFER_FETCH) {
- if (mOVInfo.is_fg == 0) {
- needUpdate = true;
- }
- }
- return needUpdate;
-}
-
-bool OverlayControlChannel::startOVRotatorSessions(
- const overlay_buffer_info& info,
- int requestType) {
- bool ret = true;
- int w = info.width;
- int h = info.height;
- int format = info.format;
-
- if (!mNoRot) {
- mRotInfo.src.format = format;
- mRotInfo.src.width = w;
- mRotInfo.src.height = h;
- mRotInfo.src_rect.w = w;
- mRotInfo.src_rect.h = h;
- mRotInfo.dst.width = w;
- mRotInfo.dst.height = h;
- if(format == MDP_Y_CRCB_H2V2_TILE) {
- mRotInfo.src.width = (((w-1)/64 +1)*64);
- mRotInfo.src.height = (((h-1)/32 +1)*32);
- mRotInfo.src_rect.w = (((w-1)/64 +1)*64);
- mRotInfo.src_rect.h = (((h-1)/32 +1)*32);
- mRotInfo.dst.width = (((w-1)/64 +1)*64);
- mRotInfo.dst.height = (((h-1)/32 +1)*32);
- mRotInfo.dst.format = MDP_Y_CRCB_H2V2;
- }
- mRotInfo.dst.format = get_rot_output_format(format);
- mRotInfo.dst_x = 0;
- mRotInfo.dst_y = 0;
- mRotInfo.src_rect.x = 0;
- mRotInfo.src_rect.y = 0;
- mRotInfo.rotations = 0;
-
- if (requestType == NEW_REQUEST) {
- mRotInfo.enable = 0;
- if(mUIChannel)
- mRotInfo.enable = 1;
- mRotInfo.session_id = 0;
- } else
- mRotInfo.enable = 1;
-
- int result = ioctl(mRotFD, MSM_ROTATOR_IOCTL_START, &mRotInfo);
- if (result) {
- reportError("Rotator session failed");
- dump(mRotInfo);
- ret = false;
- }
- }
-
- if (ret && ioctl(mFD, MSMFB_OVERLAY_SET, &mOVInfo)) {
- reportError("startOVRotatorSessions, Overlay set failed");
- dump(mOVInfo);
- ret = false;
- }
-
- if (!ret)
- closeControlChannel();
- else
- mIsChannelUpdated = true;
- return ret;
-}
-
-bool OverlayControlChannel::updateOverlaySource(const overlay_buffer_info& info,
- int orientation, int flags)
-{
- int colorFormat = getColorFormat(info.format);
- int hw_format = get_mdp_format(colorFormat);
- overlay_buffer_info ovBufInfo;
- ovBufInfo.width = info.width;
- ovBufInfo.height = info.height;
- ovBufInfo.format = hw_format;
-
- if (isInterlacedContent(info.format)) {
- flags |= INTERLACED_CONTENT;
- }
- if (!setOverlayInformation(ovBufInfo, 0, flags,
- UPDATE_REQUEST))
- return false;
-
- return startOVRotatorSessions(ovBufInfo, UPDATE_REQUEST);
-}
-
-bool OverlayControlChannel::startControlChannel(const overlay_buffer_info& info,
- int fbnum, bool norot,
- bool uichannel,
- unsigned int format3D, int zorder,
- int flags) {
- int colorFormat = getColorFormat(info.format);
- mNoRot = norot;
- mFormat = colorFormat;
- mUIChannel = uichannel;
- mFBNum = fbnum;
- fb_fix_screeninfo finfo;
- fb_var_screeninfo vinfo;
- int hw_format;
-
- // The interlace mask is part of the HAL_PIXEL_FORMAT_YV12 value. Add
- // an explicit check for the format
- if (isInterlacedContent(colorFormat)) {
- flags |= MDP_DEINTERLACE;
-
- // Get the actual format
- colorFormat = colorFormat ^ HAL_PIXEL_FORMAT_INTERLACE;
- }
- hw_format = get_mdp_format(colorFormat);
- if (hw_format < 0) {
- reportError("Unsupported format");
- return false;
- }
-
- mFormat3D = format3D;
- if ( !mFormat3D || (mFormat3D & HAL_3D_OUT_MONOSCOPIC_MASK) ) {
- // Set the share bit for sharing the VG pipe
- flags |= OVERLAY_PIPE_SHARE;
- }
- //do not set the PIPE SHARE bit for true mirroring
- if(uichannel && FrameBufferInfo::getInstance()->canSupportTrueMirroring())
- flags &= ~OVERLAY_PIPE_SHARE;
- if (!openDevices(fbnum))
- return false;
-
- //get Z order
- zorder = ZOrderManager::getInstance()->getZ(fbnum);
- if (zorder == NO_PIPE)
- return false;
-
- overlay_buffer_info ovBufInfo;
- ovBufInfo.width = info.width;
- ovBufInfo.height = info.height;
- ovBufInfo.format = hw_format;
- if (!setOverlayInformation(ovBufInfo, zorder, flags, NEW_REQUEST))
- return false;
-
- return startOVRotatorSessions(ovBufInfo, NEW_REQUEST);
-}
-
-bool OverlayControlChannel::closeControlChannel() {
- if (!isChannelUP())
- return true;
-
- if (!mNoRot && mRotFD > 0) {
- ioctl(mRotFD, MSM_ROTATOR_IOCTL_FINISH, &(mRotInfo.session_id));
- close(mRotFD);
- mRotFD = -1;
- }
-
- int ovid = mOVInfo.id;
- ioctl(mFD, MSMFB_OVERLAY_UNSET, &ovid);
- if (m3DOVInfo.is_3d) {
- m3DOVInfo.is_3d = 0;
- ioctl(mFD, MSMFB_OVERLAY_3D, &m3DOVInfo);
- }
-
- close(mFD);
-
- if(NO_PIPE != mOVInfo.z_order){
- ZOrderManager::getInstance()->decZ(mFBNum, mOVInfo.z_order);
- }
- memset(&mOVInfo, 0, sizeof(mOVInfo));
- memset(&mRotInfo, 0, sizeof(mRotInfo));
- memset(&m3DOVInfo, 0, sizeof(m3DOVInfo));
-
- mOVInfo.z_order = NO_PIPE;
- mFD = -1;
-
- return true;
-}
-
-bool OverlayControlChannel::updateOverlayFlags(int flags) {
- if ((flags & WAIT_FOR_VSYNC) == 0)
- mOVInfo.flags |= MDP_OV_PLAY_NOWAIT;
- else
- mOVInfo.flags &= ~MDP_OV_PLAY_NOWAIT;
-
- if (flags & DISABLE_FRAMEBUFFER_FETCH)
- mOVInfo.is_fg = 1;
- else
- mOVInfo.is_fg = 0;
-
- if (ioctl(mFD, MSMFB_OVERLAY_SET, &mOVInfo)) {
- LOGE("%s: OVERLAY_SET failed", __FUNCTION__);
- dump(mOVInfo);
- return false;
- }
- return true;
-}
-
-bool OverlayControlChannel::setPosition(int x, int y, uint32_t w, uint32_t h) {
-
- if (!isChannelUP() ||
- (x < 0) || (y < 0) || ((x + w) > mFBWidth) ||
- ((y + h) > mFBHeight)) {
- reportError("setPosition failed");
- LOGW("x %d y %d (x+w) %d (y+h) %d FBWidth %d FBHeight %d", x, y, x+w, y+h,
- mFBWidth,mFBHeight);
- return false;
- }
- if( x != mOVInfo.dst_rect.x || y != mOVInfo.dst_rect.y ||
- w != mOVInfo.dst_rect.w || h != mOVInfo.dst_rect.h ) {
- mdp_overlay ov;
- ov.id = mOVInfo.id;
- if (ioctl(mFD, MSMFB_OVERLAY_GET, &ov)) {
- reportError("setPosition, overlay GET failed");
- return false;
- }
-
-// LGE_CHANGE_S, [G1_Player][mukyung.jung@lge.com], 20120206, Apply SR 00718706 to fix noise of QCIF contents {
- // can not scale-up 8 times over original source
- // return false to compose with GPU
-#if 1
- if(w > (ov.src_rect.w * HW_OVERLAY_MAGNIFICATION_LIMIT)){
- LOGE("[TJ] setPosition : too big width, back to GPU comp %d => %d", ov.src_rect.w, w);
- return false;
- }
- if(h > (ov.src_rect.h * HW_OVERLAY_MAGNIFICATION_LIMIT)) {
- LOGE("[TJ] setPosition : too big height, back to GPU comp %d => %d", ov.src_rect.h, h);
- return false;
- }
-#else
-// LGE_CHANGE_E, [G1_Player][mukyung.jung@lge.com], 20120206, Apply SR 00718706 to fix noise of QCIF contents }
-
- /* Scaling of upto a max of 8 times supported */
- if(w >(ov.src_rect.w * HW_OVERLAY_MAGNIFICATION_LIMIT)){
- w = HW_OVERLAY_MAGNIFICATION_LIMIT * ov.src_rect.w;
- x = (mFBWidth - w) / 2;
- }
- if(h >(ov.src_rect.h * HW_OVERLAY_MAGNIFICATION_LIMIT)) {
- h = HW_OVERLAY_MAGNIFICATION_LIMIT * ov.src_rect.h;
- y = (mFBHeight - h) / 2;
- }
-// LGE_CHANGE_S, [G1_Player][mukyung.jung@lge.com], 20120206, Apply SR 00718706 to fix noise of QCIF contents {
-#endif
-// LGE_CHANGE_E, [G1_Player][mukyung.jung@lge.com], 20120206, Apply SR 00718706 to fix noise of QCIF contents }
-
- ov.dst_rect.x = x;
- ov.dst_rect.y = y;
- ov.dst_rect.w = w;
- ov.dst_rect.h = h;
- if (ioctl(mFD, MSMFB_OVERLAY_SET, &ov)) {
- reportError("setPosition, Overlay SET failed");
- dump(ov);
- return false;
- }
- mOVInfo = ov;
-// LGE_CHANGE_S, [G1_Player][mukyung.jung@lge.com], 20120206, Apply SR 00718706 to fix noise of QCIF contents {
- LOGE("setPosition");
- dump(ov);
-// LGE_CHANGE_E, [G1_Player][mukyung.jung@lge.com], 20120206, Apply SR 00718706 to fix noise of QCIF contents }
- }
- return true;
-}
-
-void OverlayControlChannel::swapOVRotWidthHeight() {
- int tmp = mOVInfo.src.width;
- mOVInfo.src.width = mOVInfo.src.height;
- mOVInfo.src.height = tmp;
-
- tmp = mOVInfo.src_rect.h;
- mOVInfo.src_rect.h = mOVInfo.src_rect.w;
- mOVInfo.src_rect.w = tmp;
-
- tmp = mRotInfo.dst.width;
- mRotInfo.dst.width = mRotInfo.dst.height;
- mRotInfo.dst.height = tmp;
-}
-
-bool OverlayControlChannel::useVirtualFB() {
- if(!m3DOVInfo.is_3d) {
- m3DOVInfo.is_3d = 1;
- mFBWidth *= 2;
- mFBHeight /= 2;
- m3DOVInfo.width = mFBWidth;
- m3DOVInfo.height = mFBHeight;
- return ioctl(mFD, MSMFB_OVERLAY_3D, &m3DOVInfo) ? false : true;
- }
- return true;
-}
-
-bool OverlayControlChannel::setTransform(int value, bool fetch) {
- if (!isChannelUP()) {
- LOGE("%s: channel is not up", __FUNCTION__);
- return false;
- }
-
- mdp_overlay ov = mOVInfo;
- if (fetch && ioctl(mFD, MSMFB_OVERLAY_GET, &ov)) {
- reportError("setParameter, overlay GET failed");
- return false;
- }
- mOVInfo = ov;
- if (!mIsChannelUpdated) {
- int orientation = get_mdp_orientation(value);
- if (orientation == mOVInfo.user_data[0]) {
- return true;
- }
- }
- mIsChannelUpdated = false;
-
- int val = mOVInfo.user_data[0];
- if (mNoRot)
- return true;
-
- int rot = value;
-
- switch(rot) {
- case 0:
- case HAL_TRANSFORM_FLIP_H:
- case HAL_TRANSFORM_FLIP_V:
- {
- if (val == MDP_ROT_90) {
- int tmp = mOVInfo.src_rect.y;
- mOVInfo.src_rect.y = mOVInfo.src.width -
- (mOVInfo.src_rect.x + mOVInfo.src_rect.w);
- mOVInfo.src_rect.x = tmp;
- swapOVRotWidthHeight();
- }
- else if (val == MDP_ROT_270) {
- int tmp = mOVInfo.src_rect.x;
- mOVInfo.src_rect.x = mOVInfo.src.height - (
- mOVInfo.src_rect.y + mOVInfo.src_rect.h);
- mOVInfo.src_rect.y = tmp;
- swapOVRotWidthHeight();
- }
- break;
- }
- case HAL_TRANSFORM_ROT_90:
- case (HAL_TRANSFORM_ROT_90|HAL_TRANSFORM_FLIP_H):
- case (HAL_TRANSFORM_ROT_90|HAL_TRANSFORM_FLIP_V):
- {
- if (val == MDP_ROT_270) {
- mOVInfo.src_rect.x = mOVInfo.src.width - (
- mOVInfo.src_rect.x + mOVInfo.src_rect.w);
- mOVInfo.src_rect.y = mOVInfo.src.height - (
- mOVInfo.src_rect.y + mOVInfo.src_rect.h);
- }
- else if (val == MDP_ROT_NOP || val == MDP_ROT_180) {
- int tmp = mOVInfo.src_rect.x;
- mOVInfo.src_rect.x = mOVInfo.src.height -
- (mOVInfo.src_rect.y + mOVInfo.src_rect.h);
- mOVInfo.src_rect.y = tmp;
- swapOVRotWidthHeight();
- }
- break;
- }
- case HAL_TRANSFORM_ROT_180:
- {
- if (val == MDP_ROT_270) {
- int tmp = mOVInfo.src_rect.y;
- mOVInfo.src_rect.y = mOVInfo.src.width -
- (mOVInfo.src_rect.x + mOVInfo.src_rect.w);
- mOVInfo.src_rect.x = tmp;
- swapOVRotWidthHeight();
- }
- else if (val == MDP_ROT_90) {
- int tmp = mOVInfo.src_rect.x;
- mOVInfo.src_rect.x = mOVInfo.src.height - (
- mOVInfo.src_rect.y + mOVInfo.src_rect.h);
- mOVInfo.src_rect.y = tmp;
- swapOVRotWidthHeight();
- }
- break;
- }
- case HAL_TRANSFORM_ROT_270:
- {
- if (val == MDP_ROT_90) {
- mOVInfo.src_rect.y = mOVInfo.src.height -
- (mOVInfo.src_rect.y + mOVInfo.src_rect.h);
- mOVInfo.src_rect.x = mOVInfo.src.width -
- (mOVInfo.src_rect.x + mOVInfo.src_rect.w);
- }
- else if (val == MDP_ROT_NOP || val == MDP_ROT_180) {
- int tmp = mOVInfo.src_rect.y;
- mOVInfo.src_rect.y = mOVInfo.src.width - (
- mOVInfo.src_rect.x + mOVInfo.src_rect.w);
- mOVInfo.src_rect.x = tmp;
- swapOVRotWidthHeight();
- }
- break;
- }
- default: return false;
- }
-
- int mdp_rotation = get_mdp_orientation(rot);
- if (mdp_rotation == -1)
- return false;
-
- mOVInfo.user_data[0] = mdp_rotation;
- mRotInfo.rotations = mOVInfo.user_data[0];
-
- /* Rotator always outputs non-tiled formats.
- If rotator is used, set Overlay input to non-tiled
- Else, overlay input remains tiled */
- if (mOVInfo.user_data[0]) {
- mOVInfo.src.format = get_rot_output_format(mRotInfo.src.format);
- mRotInfo.enable = 1;
- }
- else {
- //We can switch between rotator ON and OFF. Reset overlay
- //i/p format whenever this happens
- if(mRotInfo.dst.format == mOVInfo.src.format)
- mOVInfo.src.format = mRotInfo.src.format;
- mRotInfo.enable = 0;
- //Always enable rotation for UI mirror usecase
- if(mUIChannel)
- mRotInfo.enable = 1;
- }
-
-// LGE_CHANGE_S, [G1_Player][mukyung.jung@lge.com], 20120206, Apply SR 00718706 to fix noise of QCIF contents {
- // can not scale-up 8 times over original source
- // return false to compose with GPU
-#if 1
- if(mOVInfo.dst_rect.w > (mOVInfo.src_rect.w * HW_OVERLAY_MAGNIFICATION_LIMIT)){
- LOGE("[TJ] setTransform : too big width, back to GPU comp %d => %d", mOVInfo.src_rect.w, mOVInfo.dst_rect.w);
- return false;
- }
- if(mOVInfo.dst_rect.h > (mOVInfo.src_rect.h * HW_OVERLAY_MAGNIFICATION_LIMIT)) {
- LOGE("[TJ] setTransform : too big height, back to GPU comp %d => %d", mOVInfo.src_rect.h, mOVInfo.dst_rect.h);
- return false;
- }
-#endif
-// LGE_CHANGE_E, [G1_Player][mukyung.jung@lge.com], 20120206, Apply SR 00718706 to fix noise of QCIF contents }
-
- //dump(mRotInfo); // TJ
- if (ioctl(mRotFD, MSM_ROTATOR_IOCTL_START, &mRotInfo)) {
- reportError("setTransform, rotator start failed");
- dump(mRotInfo);
- return false;
- }
-
- if ((mOVInfo.user_data[0] == MDP_ROT_90) ||
- (mOVInfo.user_data[0] == MDP_ROT_270))
- mOVInfo.flags |= MDP_SOURCE_ROTATED_90;
- else
- mOVInfo.flags &= ~MDP_SOURCE_ROTATED_90;
-
-// LGE_CHANGE_S, [G1_Player][mukyung.jung@lge.com], 20120206, Apply SR 00718706 to fix noise of QCIF contents {
- LOGE("setTransform"); // TJ
- dump(mOVInfo); // TJ
-// LGE_CHANGE_E, [G1_Player][mukyung.jung@lge.com], 20120206, Apply SR 00718706 to fix noise of QCIF contents }
-
- if (ioctl(mFD, MSMFB_OVERLAY_SET, &mOVInfo)) {
- reportError("setTransform, overlay set failed");
- dump(mOVInfo);
- return false;
- }
-
- return true;
-}
-
-bool OverlayControlChannel::getPosition(int& x, int& y,
- uint32_t& w, uint32_t& h) {
- if (!isChannelUP())
- return false;
- //mOVInfo has the current Overlay Position
- x = mOVInfo.dst_rect.x;
- y = mOVInfo.dst_rect.y;
- w = mOVInfo.dst_rect.w;
- h = mOVInfo.dst_rect.h;
-
- return true;
-}
-
-bool OverlayControlChannel::getOrientation(int& orientation) const {
- if (!isChannelUP())
- return false;
- // mOVInfo has the current orientation
- orientation = mOVInfo.user_data[0];
- return true;
-}
-bool OverlayControlChannel::getOvSessionID(int& sessionID) const {
- if (!isChannelUP())
- return false;
- sessionID = mOVInfo.id;
- return true;
-}
-
-bool OverlayControlChannel::getRotSessionID(int& sessionID) const {
- if (!isChannelUP())
- return false;
- sessionID = mRotInfo.session_id;
- return true;
-}
-
-bool OverlayControlChannel::getSize(int& size) const {
- if (!isChannelUP())
- return false;
- size = mSize;
- return true;
-}
-
-OverlayDataChannel::OverlayDataChannel() : mNoRot(false), mFD(-1), mRotFD(-1),
- mPmemFD(-1), mPmemAddr(0), mUpdateDataChannel(false)
-{
- //XXX: getInstance(false) implies that it should only
- // use the kernel allocator. Change it to something
- // more descriptive later.
- mAlloc = gralloc::IAllocController::getInstance(false);
-}
-
-OverlayDataChannel::~OverlayDataChannel() {
- closeDataChannel();
-}
-
-bool OverlayDataChannel::startDataChannel(
- const OverlayControlChannel& objOvCtrlChannel,
- int fbnum, bool norot, bool secure, bool uichannel,
- int num_buffers) {
- int ovid, rotid, size;
- mNoRot = norot;
- mSecure = secure;
- memset(&mOvData, 0, sizeof(mOvData));
- memset(&mOvDataRot, 0, sizeof(mOvDataRot));
- memset(&mRotData, 0, sizeof(mRotData));
- if (objOvCtrlChannel.getOvSessionID(ovid) &&
- objOvCtrlChannel.getRotSessionID(rotid) &&
- objOvCtrlChannel.getSize(size)) {
- return startDataChannel(ovid, rotid, size, fbnum,
- norot, uichannel, num_buffers);
- }
- else
- return false;
-}
-
-bool OverlayDataChannel::openDevices(int fbnum, bool uichannel, int num_buffers) {
- if (fbnum < 0)
- return false;
- char dev_name[64];
- snprintf(dev_name, 64, FB_DEVICE_TEMPLATE, fbnum);
-
- mFD = open(dev_name, O_RDWR, 0);
- if (mFD < 0) {
- reportError("Cant open framebuffer ");
- return false;
- }
- if (!mNoRot) {
- mRotFD = open("/dev/msm_rotator", O_RDWR, 0);
- if (mRotFD < 0) {
- reportError("Cant open rotator device");
- close(mFD);
- mFD = -1;
- return false;
- }
-
- return mapRotatorMemory(num_buffers, uichannel, NEW_REQUEST);
- }
- return true;
-}
-
-bool OverlayDataChannel::mapRotatorMemory(int num_buffers, bool uiChannel, int requestType)
-{
- mPmemAddr = MAP_FAILED;
-
- alloc_data data;
- data.base = 0;
- data.fd = -1;
- data.offset = 0;
- data.size = mPmemOffset * num_buffers;
- data.align = getpagesize();
- data.uncached = true;
-
- int allocFlags = GRALLOC_USAGE_PRIVATE_MM_HEAP |
- GRALLOC_USAGE_PRIVATE_WRITEBACK_HEAP|
- GRALLOC_USAGE_PRIVATE_DO_NOT_MAP;
-
- if(mSecure) {
- allocFlags |= GRALLOC_USAGE_PROTECTED;
- } else {
- allocFlags |= GRALLOC_USAGE_PRIVATE_ADSP_HEAP |
- GRALLOC_USAGE_PRIVATE_IOMMU_HEAP;
- if((requestType == NEW_REQUEST) && !uiChannel)
- allocFlags |= GRALLOC_USAGE_PRIVATE_SMI_HEAP;
- }
-
- int err = mAlloc->allocate(data, allocFlags, 0);
- if(err) {
- reportError("Cant allocate rotatory memory");
- close(mFD);
- mFD = -1;
- close(mRotFD);
- mRotFD = -1;
- return false;
- }
- mPmemFD = data.fd;
- mPmemAddr = data.base;
- mBufferType = data.allocType;
-
- // Set this flag if source memory is fb
- if(uiChannel)
- mRotData.src.flags |= MDP_MEMORY_ID_TYPE_FB;
-
- mOvDataRot.data.memory_id = mPmemFD;
- mRotData.dst.memory_id = mPmemFD;
- mRotData.dst.offset = 0;
- mNumBuffers = num_buffers;
- mCurrentItem = 0;
- for (int i = 0; i < num_buffers; i++)
- mRotOffset[i] = i * mPmemOffset;
-
- return true;
-}
-
-bool OverlayDataChannel::updateDataChannel(int size) {
- mUpdateDataChannel = true;
- mNewPmemOffset = size;
- return true;
-}
-
-bool OverlayDataChannel::startDataChannel(int ovid, int rotid, int size,
- int fbnum, bool norot,
- bool uichannel, int num_buffers) {
- memset(&mOvData, 0, sizeof(mOvData));
- memset(&mOvDataRot, 0, sizeof(mOvDataRot));
- memset(&mRotData, 0, sizeof(mRotData));
- mNoRot = norot;
- mOvData.data.memory_id = -1;
- mOvData.id = ovid;
- mOvDataRot = mOvData;
- mPmemOffset = size;
- mRotData.session_id = rotid;
- mNumBuffers = 0;
- mCurrentItem = 0;
-
- return openDevices(fbnum, uichannel, num_buffers);
-}
-
-bool OverlayDataChannel::closeDataChannel() {
- if (!isChannelUP())
- return true;
-
- if (!mNoRot && mRotFD > 0) {
- sp<IMemAlloc> memalloc = mAlloc->getAllocator(mBufferType);
- memalloc->free_buffer(mPmemAddr, mPmemOffset * mNumBuffers, 0, mPmemFD);
- close(mPmemFD);
- mPmemFD = -1;
- close(mRotFD);
- mRotFD = -1;
- }
- close(mFD);
- mFD = -1;
- memset(&mOvData, 0, sizeof(mOvData));
- memset(&mOvDataRot, 0, sizeof(mOvDataRot));
- memset(&mRotData, 0, sizeof(mRotData));
-
- mNumBuffers = 0;
- mCurrentItem = 0;
-
- return true;
-}
-
-bool OverlayDataChannel::setFd(int fd) {
- mOvData.data.memory_id = fd;
- return true;
-}
-
-bool OverlayDataChannel::queueBuffer(uint32_t offset) {
- if ((!isChannelUP()) || mOvData.data.memory_id < 0) {
- reportError("QueueBuffer failed, either channel is not set or no file descriptor to read from");
- return false;
- }
-
- int oldPmemFD = -1;
- void* oldPmemAddr = MAP_FAILED;
- uint32_t oldPmemOffset = -1;
- bool result;
- if (!mNoRot) {
- if (mUpdateDataChannel) {
- oldPmemFD = mPmemFD;
- oldPmemAddr = mPmemAddr;
- oldPmemOffset = mPmemOffset;
- mPmemOffset = mNewPmemOffset;
- mNewPmemOffset = -1;
- // Map the new PMEM memory
- result = mapRotatorMemory(mNumBuffers, 0, UPDATE_REQUEST);
- if (!result) {
- LOGE("queueBuffer: mapRotatorMemory failed");
- return false;
- }
- mUpdateDataChannel = false;
- }
- }
-
- result = queue(offset);
-
- // Unmap the old PMEM memory after the queueBuffer has returned
- if (oldPmemFD != -1 && oldPmemAddr != MAP_FAILED) {
- sp<IMemAlloc> memalloc = mAlloc->getAllocator(mBufferType);
- memalloc->free_buffer(oldPmemAddr, oldPmemOffset * mNumBuffers, 0, oldPmemFD);
- oldPmemFD = -1;
- }
- return result;
-}
-
-bool OverlayDataChannel::queue(uint32_t offset) {
- msmfb_overlay_data *odPtr;
- mOvData.data.offset = offset;
- odPtr = &mOvData;
- if (!mNoRot) {
- mRotData.src.memory_id = mOvData.data.memory_id;
- mRotData.src.offset = offset;
- mRotData.dst.offset = (mRotData.dst.offset) ? 0 : mPmemOffset;
- mRotData.dst.offset = mRotOffset[mCurrentItem];
- mCurrentItem = (mCurrentItem + 1) % mNumBuffers;
-
- int result = ioctl(mRotFD,
- MSM_ROTATOR_IOCTL_ROTATE, &mRotData);
-
- if (!result) {
- mOvDataRot.data.offset = (uint32_t) mRotData.dst.offset;
- odPtr = &mOvDataRot;
- }
- }
-
- if (ioctl(mFD, MSMFB_OVERLAY_PLAY, odPtr)) {
- reportError("overlay play failed.");
- return false;
- }
-
- return true;
-}
-
-bool OverlayDataChannel::waitForHdmiVsync() {
- if (!isChannelUP()) {
- LOGE("%s: channel not up", __FUNCTION__);
- return false;
- }
- if (ioctl(mFD, MSMFB_OVERLAY_PLAY_WAIT, &mOvData)) {
- LOGE("%s: MSMFB_OVERLAY_PLAY_WAIT failed", __FUNCTION__);
- return false;
- }
- return true;
-}
-
-bool OverlayDataChannel::getCropS3D(overlay_rect *inRect, int channel, int format,
- overlay_rect *rect) {
- // for the 3D usecase extract channels from a frame
- switch (format & INPUT_MASK_3D) {
- case HAL_3D_IN_SIDE_BY_SIDE_L_R:
- if(channel == 0) {
- rect->x = 0;
- rect->y = 0;
- rect->w = inRect->w/2;
- rect->h = inRect->h;
- } else {
- rect->x = inRect->w/2;
- rect->y = 0;
- rect->w = inRect->w/2;
- rect->h = inRect->h;
- }
- break;
- case HAL_3D_IN_SIDE_BY_SIDE_R_L:
- if(channel == 1) {
- rect->x = 0;
- rect->y = 0;
- rect->w = inRect->w/2;
- rect->h = inRect->h;
- } else {
- rect->x = inRect->w/2;
- rect->y = 0;
- rect->w = inRect->w/2;
- rect->h = inRect->h;
- }
- break;
- case HAL_3D_IN_TOP_BOTTOM:
- if(channel == 0) {
- rect->x = 0;
- rect->y = 0;
- rect->w = inRect->w;
- rect->h = inRect->h/2;
- } else {
- rect->x = 0;
- rect->y = inRect->h/2;
- rect->w = inRect->w;
- rect->h = inRect->h/2;
- }
- break;
- case HAL_3D_IN_INTERLEAVE:
- break;
- default:
- reportError("Unsupported 3D format...");
- break;
- }
- return true;
-}
-
-bool OverlayDataChannel::setCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h) {
- if (!isChannelUP()) {
- reportError("Channel not set");
- return false;
- }
-
- mdp_overlay ov;
- ov.id = mOvData.id;
- if (ioctl(mFD, MSMFB_OVERLAY_GET, &ov)) {
- reportError("setCrop, overlay GET failed");
- return false;
- }
-
- if ((ov.user_data[0] == MDP_ROT_90) ||
- (ov.user_data[0] == (MDP_ROT_90 | MDP_FLIP_UD)) ||
- (ov.user_data[0] == (MDP_ROT_90 | MDP_FLIP_LR))){
- if (ov.src.width < (y + h))
- return false;
-
- uint32_t tmp = x;
- x = ov.src.width - (y + h);
- y = tmp;
-
- tmp = w;
- w = h;
- h = tmp;
- }
- else if (ov.user_data[0] == MDP_ROT_270) {
- if (ov.src.height < (x + w))
- return false;
-
- uint32_t tmp = y;
- y = ov.src.height - (x + w);
- x = tmp;
-
- tmp = w;
- w = h;
- h = tmp;
- }
- else if(ov.user_data[0] == MDP_ROT_180) {
- if ((ov.src.height < (y + h)) || (ov.src.width < ( x + w)))
- return false;
-
- x = ov.src.width - (x + w);
- y = ov.src.height - (y + h);
- }
-
-
- normalize_crop(x, w);
- normalize_crop(y, h);
-
- if ((ov.src_rect.x == x) &&
- (ov.src_rect.y == y) &&
- (ov.src_rect.w == w) &&
- (ov.src_rect.h == h))
- return true;
-
- ov.src_rect.x = x;
- ov.src_rect.y = y;
- ov.src_rect.w = w;
- ov.src_rect.h = h;
-
-// LGE_CHANGE_S, [G1_Player][mukyung.jung@lge.com], 20120206, Apply SR 00718706 to fix noise of QCIF contents {
- // can not scale-up 8 times over original source
- // return false to compose with GPU
-#if 1
- if(ov.dst_rect.w > (ov.src_rect.w * HW_OVERLAY_MAGNIFICATION_LIMIT)){
- LOGE("[TJ] setCrop : too big width, back to GPU comp %d => %d", ov.src_rect.w, ov.dst_rect.w);
- return false;
- }
- if(ov.dst_rect.h > (ov.src_rect.h * HW_OVERLAY_MAGNIFICATION_LIMIT)) {
- LOGE("[TJ] setCrop : too big height, back to GPU comp %d => %d", ov.src_rect.h, ov.dst_rect.h);
- return false;
- }
-#else
-// LGE_CHANGE_E, [G1_Player][mukyung.jung@lge.com], 20120206, Apply SR 00718706 to fix noise of QCIF contents }
-
- /* Scaling of upto a max of 8 times supported */
- if(ov.dst_rect.w >(ov.src_rect.w * HW_OVERLAY_MAGNIFICATION_LIMIT)){
- ov.dst_rect.w = HW_OVERLAY_MAGNIFICATION_LIMIT * ov.src_rect.w;
- }
- if(ov.dst_rect.h >(ov.src_rect.h * HW_OVERLAY_MAGNIFICATION_LIMIT)) {
- ov.dst_rect.h = HW_OVERLAY_MAGNIFICATION_LIMIT * ov.src_rect.h;
- }
-// LGE_CHANGE_S, [G1_Player][mukyung.jung@lge.com], 20120206, Apply SR 00718706 to fix noise of QCIF contents {
-#endif
-
- LOGE("setCrop");
- dump(ov);
-// LGE_CHANGE_E, [G1_Player][mukyung.jung@lge.com], 20120206, Apply SR 00718706 to fix noise of QCIF contents }
-
- if (ioctl(mFD, MSMFB_OVERLAY_SET, &ov)) {
- reportError("setCrop, overlay set error");
- dump(ov);
- return false;
- }
-
- return true;
-}
-
-/* setVisualParam can be called to set the configuration value of a post
- * processing feature (HUE,SATURATION,BRIGHTNESS,CONTRAST,SMOOTHING/SHARPENING)
- * for the first 4, the setting will stay set until the parameter is changed
- * by another call to setVisualParam with that same paramType */
-void Overlay::setVisualParam(int8_t paramType, float paramValue) {
- switch (mState) {
- case OV_UI_MIRROR_TV:
- case OV_2D_VIDEO_ON_PANEL:
- case OV_3D_VIDEO_2D_PANEL:
- // set the parameter value for the given parameter type.
- if(!objOvCtrlChannel[VG0_PIPE].setVisualParam(paramType, paramValue)) {
- LOGE("Failed to set param %d for value %f", paramType, paramValue);
- }
- break;
- case OV_2D_VIDEO_ON_TV:
- case OV_3D_VIDEO_3D_PANEL:
- case OV_3D_VIDEO_2D_TV:
- case OV_3D_VIDEO_3D_TV:
- for (int i=0; i<NUM_CHANNELS; i++) {
- //setting the value for the given parameter on each pipe (i.e. for
- //both video pipes)
- if(!objOvCtrlChannel[i].setVisualParam(paramType, paramValue)) {
- LOGE("Failed to set param %d for value %f", paramType, paramValue);
- }
- }
- break;
- default:
- break;
- }
-}
-
-/* Finalizes the parameter value in the hsic_cfg structure*/
-int OverlayControlChannel::commitVisualParam(int8_t paramType, float paramValue) {
-#ifdef USES_POST_PROCESSING
- switch(paramType) {
- case SET_HUE:
- //API expects param within range -180 - 180
- CAP_RANGE(paramValue, HUE_RANGE, -HUE_RANGE);
- hsic_cfg.hue = (int32_t) paramValue;
- break;
- case SET_BRIGHTNESS:
- //API expects param within range -255 - 255
- CAP_RANGE(paramValue, BRIGHTNESS_RANGE, -BRIGHTNESS_RANGE);
- hsic_cfg.intensity = (int32_t) paramValue;
- break;
- case SET_SATURATION:
- //API expects param within range -1 - 1
- CAP_RANGE(paramValue, CON_SAT_RANGE, -CON_SAT_RANGE);
- hsic_cfg.sat = paramValue;
- break;
- case SET_CONTRAST:
- //API expects param within range -1 - 1
- CAP_RANGE(paramValue, CON_SAT_RANGE, -CON_SAT_RANGE);
- hsic_cfg.contrast = paramValue;
- break;
- default:
- return -1;
- }
- return 0;
-#endif
- return -1;
-}
-
-/* Converts paramValue to the expected range for each paramType, */
-bool OverlayControlChannel::setVisualParam(int8_t paramType, float paramValue)
-{
- if (!isChannelUP()) {
- LOGE("%s: Channel not set", __FUNCTION__);
- return false;
- }
-
- bool setFlag = false;
-
- //Sharpness values range from -128 to 127
- //Integer values must be converted accordingly
-
- int8_t value;
- if (paramType == SET_SHARPNESS) {
- //binding paramValue to the limits of its range.
- CAP_RANGE(paramValue, SHARPNESS_RANGE, -SHARPNESS_RANGE);
- value = paramValue * NUM_SHARPNESS_VALS - (NUM_SHARPNESS_VALS / 2);
- }
-
- uint32_t block = MDP_BLOCK_MAX;
-
- //tranlate mOVInfo.id into block type for pp_conv
- switch(mOVInfo.id) {
- case 3:
- // 3 is the pipe_ndx given when OVERLAY_PIPE_VG1 is used
- block = MDP_BLOCK_VG_1;
- break;
- case 4:
- // 4 is the pipe_ndx given when OVERLAY_PIPE_VG2 is used
- block = MDP_BLOCK_VG_2;
- break;
- default:
- LOGE("%s: Invalid HSIC overlay id",__FUNCTION__);
- }
-
- //save the paramValue to hsic_cfg
- commitVisualParam(paramType, paramValue);
-#ifdef USES_POST_PROCESSING
- //calling our user space library to configure the post processing color
- //conversion (does Hue, Saturation, Brightness, and Contrast adjustment)
- display_pp_conv_set_cfg(block, &hsic_cfg);
-#endif
- mdp_overlay overlay;
-
- switch(paramType) {
- case SET_NONE:
- return true;
- case SET_SHARPNESS:
- if (ioctl(mFD, MSMFB_OVERLAY_GET, &overlay)) {
- reportError("setVisualParam, overlay GET failed");
- return false;
- }
- if (overlay.dpp.sharp_strength != value) {
- mOVInfo.flags |= MDP_SHARPENING;
- mOVInfo.dpp.sharp_strength = value;
- setFlag = true;
- }
- break;
- case RESET_ALL:
- //set all visual params to a default value
- //passed in from the app
- mOVInfo.flags |= MDP_SHARPENING;
- mOVInfo.dpp.sharp_strength = value;
- setFlag = true;
- break;
- default:
- return false;
- }
- if (setFlag) {
- if (ioctl(mFD, MSMFB_OVERLAY_SET, &mOVInfo)) {
- reportError("setVisualParam, overlay set failed");
- dump(mOVInfo);
- return false;
- }
- }
- return true;
-}
diff --git a/liboverlay/overlayLib.h b/liboverlay/overlayLib.h
deleted file mode 100755
index 65b134c..0000000
--- a/liboverlay/overlayLib.h
+++ /dev/null
@@ -1,451 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef INCLUDE_OVERLAY_LIB
-#define INCLUDE_OVERLAY_LIB
-
-#include <cutils/log.h>
-#include <cutils/properties.h>
-#include <cutils/atomic.h>
-
-#include <hardware/hardware.h>
-#include <hardware/gralloc.h>
-
-#include <dlfcn.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <string.h>
-#include <stdlib.h>
-#include <pthread.h>
-
-#include <linux/fb.h>
-#include <linux/msm_mdp.h>
-#include <linux/msm_rotator.h>
-#include <linux/android_pmem.h>
-
-#include <sys/mman.h>
-#include <sys/ioctl.h>
-#include <utils/threads.h>
-#include <utils/RefBase.h>
-#include <alloc_controller.h>
-#include <memalloc.h>
-
-#ifdef USES_POST_PROCESSING
-#include "lib-postproc.h"
-#endif
-
-#define HW_OVERLAY_MAGNIFICATION_LIMIT 8
-#define HW_OVERLAY_MINIFICATION_LIMIT HW_OVERLAY_MAGNIFICATION_LIMIT
-
-#define EVEN_OUT(x) if (x & 0x0001) {x--;}
-#define NO_PIPE -1
-#define VG0_PIPE 0
-#define VG1_PIPE 1
-#define NUM_CHANNELS 2
-#define NUM_FB_DEVICES 3
-#define FRAMEBUFFER_0 0
-#define FRAMEBUFFER_1 1
-#define FRAMEBUFFER_2 2
-#define NUM_SHARPNESS_VALS 256
-#define SHARPNESS_RANGE 1.0f
-#define HUE_RANGE 180
-#define BRIGHTNESS_RANGE 255
-#define CON_SAT_RANGE 1.0f
-#define CAP_RANGE(value,max,min) do { if (value - min < -0.0001)\
- {value = min;}\
- else if(value - max > 0.0001)\
- {value = max;}\
- } while(0);
-
-enum {
- HDMI_OFF,
- HDMI_ON
-};
-
-enum {
- OVERLAY_CHANNEL_DOWN,
- OVERLAY_CHANNEL_UP
-};
-
-enum {
- NEW_REQUEST,
- UPDATE_REQUEST
-};
-
-enum {
- WAIT_FOR_VSYNC = 1<<0,
- DISABLE_FRAMEBUFFER_FETCH = 1<<1,
- INTERLACED_CONTENT = 1<<2,
- OVERLAY_PIPE_SHARE = 1<<3,
- SECURE_OVERLAY_SESSION = 1<<4,
-};
-
-/* ------------------------------- 3D defines ---------------------------------------*/
-// The compound format passed to the overlay is
-// ABCCC where A is the input 3D format,
-// B is the output 3D format
-// CCC is the color format e.g YCbCr420SP YCrCb420SP etc.
-#define FORMAT_3D(x) (x & 0xFF000)
-#define COLOR_FORMAT(x) (x & 0xFFF)
-// in the final 3D format, the MSB 2Bytes are the input format and the
-// LSB 2bytes are the output format. Shift the output byte 12 bits.
-#define SHIFT_OUTPUT_3D 12
-#define FORMAT_3D_OUTPUT(x) ((x & 0xF000) >> SHIFT_OUTPUT_3D)
-#define FORMAT_3D_INPUT(x) (x & 0xF0000)
-#define INPUT_MASK_3D 0xFFFF0000
-#define OUTPUT_MASK_3D 0x0000FFFF
-#define SHIFT_3D 16
-// The output format is the 2MSB bytes. Shift the format by 12 to reflect this
-#define HAL_3D_OUT_SIDE_BY_SIDE_MASK (HAL_3D_OUT_SIDE_BY_SIDE >> SHIFT_OUTPUT_3D)
-#define HAL_3D_OUT_TOP_BOTTOM_MASK (HAL_3D_OUT_TOP_BOTTOM >> SHIFT_OUTPUT_3D)
-#define HAL_3D_OUT_INTERLEAVE_MASK (HAL_3D_OUT_INTERLEAVE >> SHIFT_OUTPUT_3D)
-#define HAL_3D_OUT_MONOSCOPIC_MASK (HAL_3D_OUT_MONOSCOPIC >> SHIFT_OUTPUT_3D)
-
-// 3D panel barrier orientation
-#define BARRIER_LANDSCAPE 1
-#define BARRIER_PORTRAIT 2
-
-#ifdef HDMI_AS_PRIMARY
-#define FORMAT_3D_FILE "/sys/class/graphics/fb0/format_3d"
-#define EDID_3D_INFO_FILE "/sys/class/graphics/fb0/3d_present"
-#else
-#define FORMAT_3D_FILE "/sys/class/graphics/fb1/format_3d"
-#define EDID_3D_INFO_FILE "/sys/class/graphics/fb1/3d_present"
-#endif
-#define BARRIER_FILE "/sys/devices/platform/mipi_novatek.0/enable_3d_barrier"
-/* -------------------------- end 3D defines ----------------------------------------*/
-
-// Struct to hold the buffer info: geometry and size
-struct overlay_buffer_info {
- int width;
- int height;
- int format;
- int size;
-};
-
-using android::Mutex;
-namespace overlay {
-
-#define FB_DEVICE_TEMPLATE "/dev/graphics/fb%u"
-
- //Utility Class to query the framebuffer info
- class FrameBufferInfo {
- int mFBWidth;
- int mFBHeight;
- bool mBorderFillSupported;
- static FrameBufferInfo *sFBInfoInstance;
-
- FrameBufferInfo():mFBWidth(0),mFBHeight(0), mBorderFillSupported(false) {
- char const * const device_name =
- "/dev/graphics/fb0";
- int fd = open(device_name, O_RDWR, 0);
- mdp_overlay ov;
- memset(&ov, 0, sizeof(ov));
- if (fd < 0) {
- LOGE("FrameBufferInfo: Cant open framebuffer ");
- return;
- }
- fb_var_screeninfo vinfo;
- if (ioctl(fd, FBIOGET_VSCREENINFO, &vinfo) == -1) {
- LOGE("FrameBufferInfo: FBIOGET_VSCREENINFO on fb0 failed");
- close(fd);
- fd = -1;
- return;
- }
- ov.id = 1;
- if(ioctl(fd, MSMFB_OVERLAY_GET, &ov)) {
- LOGE("FrameBufferInfo: MSMFB_OVERLAY_GET on fb0 failed");
- close(fd);
- fd = -1;
- return;
- }
- close(fd);
- fd = -1;
- mFBWidth = vinfo.xres;
- mFBHeight = vinfo.yres;
- mBorderFillSupported = (ov.flags & MDP_BORDERFILL_SUPPORTED) ?
- true : false;
- }
- public:
- static FrameBufferInfo* getInstance(){
- if (!sFBInfoInstance){
- sFBInfoInstance = new FrameBufferInfo;
- }
- return sFBInfoInstance;
- }
- int getWidth() const { return mFBWidth; }
- int getHeight() const { return mFBHeight; }
- bool canSupportTrueMirroring() const {
- return mBorderFillSupported; }
- };
-
-enum {
- OV_UI_MIRROR_TV = 0,
- OV_2D_VIDEO_ON_PANEL,
- OV_2D_VIDEO_ON_TV,
- OV_3D_VIDEO_2D_PANEL,
- OV_3D_VIDEO_2D_TV,
- OV_3D_VIDEO_3D_PANEL,
- OV_3D_VIDEO_3D_TV
-};
-bool isHDMIConnected();
-bool is3DTV();
-bool isPanel3D();
-bool usePanel3D();
-bool send3DInfoPacket(unsigned int format3D);
-bool enableBarrier(unsigned int orientation);
-unsigned int getOverlayConfig (unsigned int format3D, bool poll = true,
- bool isHDMI = false);
-int getColorFormat(int format);
-bool isInterlacedContent(int format);
-int get_mdp_format(int format);
-int get_size(int format, int w, int h);
-int get_rot_output_format(int format);
-int get_mdp_orientation(int value);
-void normalize_crop(uint32_t& xy, uint32_t& wh);
-//Initializes the overlay - cleans up any existing overlay pipes
-int initOverlay();
-
-/* Print values being sent to driver in case of ioctl failures
- These logs are enabled only if DEBUG_OVERLAY is true */
-void dump(msm_rotator_img_info& mRotInfo);
-void dump(mdp_overlay& mOvInfo);
-const char* getFormatString(int format);
-
- //singleton class to decide the z order of new overlay surfaces
- class ZOrderManager {
- bool mFB0Pipes[NUM_CHANNELS];
- bool mFB1Pipes[NUM_CHANNELS+1]; //FB1 can have 3 pipes
- int mPipesInuse; // Holds the number of pipes in use
- int mMaxPipes; // Max number of pipes
- static ZOrderManager *sInstance;
- Mutex *mObjMutex;
- ZOrderManager(){
- mPipesInuse = 0;
- // for true mirroring support there can be 3 pipes on secondary
- mMaxPipes = FrameBufferInfo::getInstance()->canSupportTrueMirroring()?
- NUM_CHANNELS+1 : NUM_CHANNELS;
- for (int i = 0; i < NUM_CHANNELS; i++)
- mFB0Pipes[i] = false;
- for (int j = 0; j < mMaxPipes; j++)
- mFB1Pipes[j] = false;
- mObjMutex = new Mutex();
- }
- ~ZOrderManager() {
- delete sInstance;
- delete mObjMutex;
- }
- public:
- static ZOrderManager* getInstance(){
- if (!sInstance){
- sInstance = new ZOrderManager;
- }
- return sInstance;
- }
- int getZ(int fbnum);
- void decZ(int fbnum, int zorder);
- };
-const int max_num_buffers = 3;
-typedef struct mdp_rect overlay_rect;
-
-class OverlayControlChannel {
-
-enum {
- SET_NONE = 0,
- SET_SHARPNESS,
-#ifdef USES_POST_PROCESSING
- SET_HUE,
- SET_BRIGHTNESS,
- SET_SATURATION,
- SET_CONTRAST,
-#endif
- RESET_ALL,
-};
- bool mNoRot;
- int mFBNum;
- int mFBWidth;
- int mFBHeight;
- int mFBbpp;
- int mFBystride;
- int mFormat;
- int mFD;
- int mRotFD;
- int mSize;
- int mOrientation;
- unsigned int mFormat3D;
- bool mUIChannel;
-#ifdef USES_POST_PROCESSING
- struct display_pp_conv_cfg hsic_cfg;
-#endif
- mdp_overlay mOVInfo;
- msm_rotator_img_info mRotInfo;
- msmfb_overlay_3d m3DOVInfo;
- bool mIsChannelUpdated;
- bool openDevices(int fbnum = -1);
- bool setOverlayInformation(const overlay_buffer_info& info,
- int zorder = 0, int flags = 0,
- int requestType = NEW_REQUEST);
- bool startOVRotatorSessions(const overlay_buffer_info& info, int requestType);
- void swapOVRotWidthHeight();
- int commitVisualParam(int8_t paramType, float paramValue);
- void setInformationFromFlags(int flags, mdp_overlay& ov);
-
-public:
- OverlayControlChannel();
- ~OverlayControlChannel();
- bool startControlChannel(const overlay_buffer_info& info,
- int fbnum, bool norot = false,
- bool uichannel = false,
- unsigned int format3D = 0, int zorder = 0,
- int flags = 0);
- bool closeControlChannel();
- bool setPosition(int x, int y, uint32_t w, uint32_t h);
- bool setTransform(int value, bool fetch = true);
- void setSize (int size) { mSize = size; }
- bool getPosition(int& x, int& y, uint32_t& w, uint32_t& h);
- bool getOvSessionID(int& sessionID) const;
- bool getRotSessionID(int& sessionID) const;
- bool getSize(int& size) const;
- bool isChannelUP() const { return (mFD > 0); }
- int getFBWidth() const { return mFBWidth; }
- int getFBHeight() const { return mFBHeight; }
- int getFormat3D() const { return mFormat3D; }
- bool getOrientation(int& orientation) const;
- bool updateOverlayFlags(int flags);
- bool getAspectRatioPosition(int w, int h, overlay_rect *rect);
- // Calculates the aspect ratio for video on HDMI based on primary
- // aspect ratio used in case of true mirroring
- bool getAspectRatioPosition(int w, int h, int orientation,
- overlay_rect *inRect, overlay_rect *outRect);
- bool getPositionS3D(int channel, int format, overlay_rect *rect);
- bool updateOverlaySource(const overlay_buffer_info& info, int orientation, int flags);
- bool getFormat() const { return mFormat; }
- bool setVisualParam(int8_t paramType, float paramValue);
- bool useVirtualFB ();
- bool doFlagsNeedUpdate(int flags);
-};
-
-class OverlayDataChannel {
-
- bool mNoRot;
- bool mSecure;
- int mFD;
- int mRotFD;
- int mPmemFD;
- void* mPmemAddr;
- uint32_t mPmemOffset;
- uint32_t mNewPmemOffset;
- msmfb_overlay_data mOvData;
- msmfb_overlay_data mOvDataRot;
- msm_rotator_data_info mRotData;
- int mRotOffset[max_num_buffers];
- int mCurrentItem;
- int mNumBuffers;
- bool mUpdateDataChannel;
- android::sp<gralloc::IAllocController> mAlloc;
- int mBufferType;
-
- bool openDevices(int fbnum = -1, bool uichannel = false, int num_buffers = 2);
- bool mapRotatorMemory(int num_buffers, bool uiChannel, int requestType);
- bool queue(uint32_t offset);
-
-public:
- OverlayDataChannel();
- ~OverlayDataChannel();
- bool startDataChannel(const OverlayControlChannel& objOvCtrlChannel,
- int fbnum, bool norot = false, bool secure = false,
- bool uichannel = false, int num_buffers = 2);
- bool startDataChannel(int ovid, int rotid, int size,
- int fbnum, bool norot = false, bool uichannel = false,
- int num_buffers = 2);
- bool closeDataChannel();
- bool setFd(int fd);
- bool queueBuffer(uint32_t offset);
- bool waitForHdmiVsync();
- bool setCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h);
- bool getCropS3D(overlay_rect *inRect, int channel, int format, overlay_rect *rect);
- bool isChannelUP() const { return (mFD > 0); }
- bool updateDataChannel(int size);
-};
-
-/*
- * Overlay class for single thread application
- * A multiple thread/process application need to use Overlay HAL
- */
-class Overlay {
-
- bool mChannelUP;
- //stores the connected external display Ex: HDMI(1) WFD(2)
- int mExternalDisplay;
- unsigned int mS3DFormat;
- //Actual cropped source width and height of overlay
- int mCroppedSrcWidth;
- int mCroppedSrcHeight;
- overlay_buffer_info mOVBufferInfo;
- int mState;
- // Stores the current device orientation
- int mDevOrientation;
- OverlayControlChannel objOvCtrlChannel[2];
- OverlayDataChannel objOvDataChannel[2];
-
-public:
- Overlay();
- ~Overlay();
-
- static bool sHDMIAsPrimary;
- bool startChannel(const overlay_buffer_info& info, int fbnum, bool norot = false,
- bool uichannel = false, unsigned int format3D = 0,
- int channel = 0, int flags = 0,
- int num_buffers = 2);
- bool closeChannel();
- bool setDeviceOrientation(int orientation);
- bool setPosition(int x, int y, uint32_t w, uint32_t h);
- bool setTransform(int value);
- bool setOrientation(int value, int channel = 0);
- bool setFd(int fd, int channel = 0);
- bool queueBuffer(uint32_t offset, int channel = 0);
- bool getPosition(int& x, int& y, uint32_t& w, uint32_t& h, int channel = 0);
- bool isChannelUP() const { return mChannelUP; }
- int getFBWidth(int channel = 0) const;
- int getFBHeight(int channel = 0) const;
- bool getOrientation(int& orientation, int channel = 0) const;
- bool queueBuffer(buffer_handle_t buffer);
- bool setSource(const overlay_buffer_info& info, int orientation, int hdmiConnected,
- int flags, int numBuffers = 2);
- bool getAspectRatioPosition(int w, int h, overlay_rect *rect, int channel = 0);
- bool setCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h);
- bool updateOverlayFlags(int flags);
- void setVisualParam(int8_t paramType, float paramValue);
- bool waitForHdmiVsync(int channel);
- int getChannelStatus() const { return (mChannelUP ? OVERLAY_CHANNEL_UP: OVERLAY_CHANNEL_DOWN); }
- void closeExternalChannel();
-private:
- bool setChannelPosition(int x, int y, uint32_t w, uint32_t h, int channel = 0);
- bool setChannelCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h, int channel);
- bool queueBuffer(int fd, uint32_t offset, int channel);
- bool updateOverlaySource(const overlay_buffer_info& info, int orientation, int flags);
- int getS3DFormat(int format);
-};
-
-struct overlay_shared_data {
- volatile bool isControlSetup;
- unsigned int state;
- int rotid[2];
- int ovid[2];
-};
-};
-#endif
diff --git a/liboverlay/overlayLibUI.cpp b/liboverlay/overlayLibUI.cpp
deleted file mode 100755
index d3fd80a..0000000
--- a/liboverlay/overlayLibUI.cpp
+++ /dev/null
@@ -1,482 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- * Copyright (c) 2011-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.
- */
-
-#include "overlayLibUI.h"
-#include "gralloc_priv.h"
-#define LOG_TAG "OverlayUI"
-
-using android::sp;
-using gralloc::IMemAlloc;
-using gralloc::alloc_data;
-
-namespace {
-/* helper functions */
-void swapOVRotWidthHeight(msm_rotator_img_info& rotInfo,
- mdp_overlay& ovInfo) {
- int srcWidth = ovInfo.src.width;
- ovInfo.src.width = ovInfo.src.height;
- ovInfo.src.height = srcWidth;
-
- int srcRectWidth = ovInfo.src_rect.w;
- ovInfo.src_rect.w = ovInfo.src_rect.h;
- ovInfo.src_rect.h = srcRectWidth;
-
- int dstWidth = rotInfo.dst.width;
- rotInfo.dst.width = rotInfo.dst.height;
- rotInfo.dst.height = dstWidth;
-}
-
-bool isRGBType(int format) {
- bool ret = false;
- switch(format) {
- case MDP_RGBA_8888:
- case MDP_BGRA_8888:
- case MDP_RGBX_8888:
- case MDP_RGB_565:
- ret = true;
- break;
- default:
- ret = false;
- break;
- }
- return ret;
-}
-
-int getRGBBpp(int format) {
- int ret = -1;
- switch(format) {
- case MDP_RGBA_8888:
- case MDP_BGRA_8888:
- case MDP_RGBX_8888:
- ret = 4;
- break;
- case MDP_RGB_565:
- ret = 2;
- break;
- default:
- ret = -1;
- break;
- }
-
- return ret;
-}
-
-bool turnOFFVSync() {
- static int swapIntervalPropVal = -1;
- if (swapIntervalPropVal == -1) {
- char pval[PROPERTY_VALUE_MAX];
- property_get("debug.gr.swapinterval", pval, "1");
- swapIntervalPropVal = atoi(pval);
- }
- return (swapIntervalPropVal == 0);
-}
-
-};
-
-namespace overlay {
-
-status_t Display::openDisplay(int fbnum) {
- if (mFD != NO_INIT)
- return NO_ERROR;
-
- status_t ret = NO_INIT;
- char dev_name[64];
- snprintf(dev_name, 64, FB_DEVICE_TEMPLATE, fbnum);
-
- mFD = open(dev_name, O_RDWR, 0);
- if (mFD < 0) {
- LOGE("Failed to open FB %d", fbnum);
- return ret;
- }
-
- fb_var_screeninfo vinfo;
- if (ioctl(mFD, FBIOGET_VSCREENINFO, &vinfo)) {
- LOGE("FBIOGET_VSCREENINFO on failed on FB %d", fbnum);
- close(mFD);
- mFD = NO_INIT;
- return ret;
- }
-
- mFBWidth = vinfo.xres;
- mFBHeight = vinfo.yres;
- mFBBpp = vinfo.bits_per_pixel;
- ret = NO_ERROR;
-
- return ret;
-}
-
-void Display::closeDisplay() {
- close(mFD);
- mFD = NO_INIT;
-}
-
-Rotator::Rotator() : mFD(NO_INIT), mSessionID(NO_INIT), mPmemFD(NO_INIT)
-{
- mAlloc = gralloc::IAllocController::getInstance(false);
-}
-
-Rotator::~Rotator()
-{
- closeRotSession();
-}
-
-status_t Rotator::startRotSession(msm_rotator_img_info& rotInfo,
- int size, int numBuffers) {
- status_t ret = NO_ERROR;
- if (mSessionID == NO_INIT && mFD == NO_INIT) {
- mNumBuffers = numBuffers;
- mFD = open("/dev/msm_rotator", O_RDWR, 0);
- if (mFD < 0) {
- LOGE("Couldnt open rotator device");
- return NO_INIT;
- }
-
- if (ioctl(mFD, MSM_ROTATOR_IOCTL_START, &rotInfo)) {
- close(mFD);
- mFD = NO_INIT;
- return NO_INIT;
- }
-
- mSessionID = rotInfo.session_id;
- alloc_data data;
- data.base = 0;
- data.fd = -1;
- data.offset = 0;
- data.size = mSize * mNumBuffers;
- data.align = getpagesize();
- data.uncached = true;
-
- int allocFlags = GRALLOC_USAGE_PRIVATE_MM_HEAP |
- GRALLOC_USAGE_PRIVATE_WRITEBACK_HEAP |
- GRALLOC_USAGE_PRIVATE_ADSP_HEAP |
- GRALLOC_USAGE_PRIVATE_IOMMU_HEAP |
- GRALLOC_USAGE_PRIVATE_SMI_HEAP |
- GRALLOC_USAGE_PRIVATE_DO_NOT_MAP;
-
- int err = mAlloc->allocate(data, allocFlags, 0);
-
- if(err) {
- LOGE("%s: Can't allocate rotator memory", __func__);
- closeRotSession();
- return NO_INIT;
- }
- mPmemFD = data.fd;
- mPmemAddr = data.base;
- mBufferType = data.allocType;
-
- mCurrentItem = 0;
- for (int i = 0; i < mNumBuffers; i++)
- mRotOffset[i] = i * mSize;
- ret = NO_ERROR;
- }
- return ret;
-}
-
-status_t Rotator::closeRotSession() {
- if (mSessionID != NO_INIT && mFD != NO_INIT) {
- ioctl(mFD, MSM_ROTATOR_IOCTL_FINISH, &mSessionID);
- close(mFD);
- if (NO_INIT != mPmemFD) {
- sp<IMemAlloc> memalloc = mAlloc->getAllocator(mBufferType);
- memalloc->free_buffer(mPmemAddr, mSize * mNumBuffers, 0, mPmemFD);
- close(mPmemFD);
- }
- }
-
- mFD = NO_INIT;
- mSessionID = NO_INIT;
- mPmemFD = NO_INIT;
- mPmemAddr = MAP_FAILED;
-
- return NO_ERROR;
-}
-
-status_t Rotator::rotateBuffer(msm_rotator_data_info& rotData) {
- status_t ret = NO_INIT;
- if (mSessionID != NO_INIT) {
- rotData.dst.memory_id = mPmemFD;
- rotData.dst.offset = mRotOffset[mCurrentItem];
- rotData.session_id = mSessionID;
- mCurrentItem = (mCurrentItem + 1) % mNumBuffers;
- if (ioctl(mFD, MSM_ROTATOR_IOCTL_ROTATE, &rotData)) {
- LOGE("Rotator failed to rotate");
- return BAD_VALUE;
- }
- return NO_ERROR;
- }
-
- return ret;
-}
-
-//===================== OverlayUI =================//
-
-OverlayUI::OverlayUI() : mChannelState(CLOSED), mOrientation(NO_INIT),
- mFBNum(NO_INIT), mZorder(NO_INIT), mWaitForVsync(false), mIsFg(false),
- mSessionID(NO_INIT), mParamsChanged(false) {
- memset(&mOvInfo, 0, sizeof(mOvInfo));
- memset(&mRotInfo, 0, sizeof(mRotInfo));
-}
-
-OverlayUI::~OverlayUI() {
- closeChannel();
-}
-
-void OverlayUI::setSource(const overlay_buffer_info& info, int orientation) {
- status_t ret = NO_INIT;
- int format3D = FORMAT_3D(info.format);
- int colorFormat = COLOR_FORMAT(info.format);
- int format = get_mdp_format(colorFormat);
-
- if (format3D || !isRGBType(format)) {
- LOGE("%s: Unsupported format", __func__);
- return;
- }
-
- mParamsChanged |= (mSource.width ^ info.width) ||
- (mSource.height ^ info.height) ||
- (mSource.format ^ format) ||
- (mSource.size ^ info.size) ||
- (mOrientation ^ orientation);
-
- mSource.width = info.width;
- mSource.height = info.height;
- mSource.format = format;
- mSource.size = info.size;
- mOrientation = orientation;
- setupOvRotInfo();
-}
-
-void OverlayUI::setDisplayParams(int fbNum, bool waitForVsync, bool isFg, int
- zorder, bool isVGPipe) {
- int flags = 0;
-
- if(false == waitForVsync)
- flags |= MDP_OV_PLAY_NOWAIT;
- else
- flags &= ~MDP_OV_PLAY_NOWAIT;
-
- if(isVGPipe)
- flags |= MDP_OV_PIPE_SHARE;
- else
- flags &= ~MDP_OV_PIPE_SHARE;
-
- if (turnOFFVSync())
- flags |= MDP_OV_PLAY_NOWAIT;
-
- mParamsChanged |= (mFBNum ^ fbNum) ||
- (mOvInfo.is_fg ^ isFg) ||
- (mOvInfo.flags ^ flags) ||
- (mOvInfo.z_order ^ zorder);
-
- mFBNum = fbNum;
- mOvInfo.is_fg = isFg;
- mOvInfo.flags = flags;
- mOvInfo.z_order = zorder;
-
- mobjDisplay.openDisplay(mFBNum);
-}
-
-void OverlayUI::setPosition(int x, int y, int w, int h) {
- mParamsChanged |= (mOvInfo.dst_rect.x ^ x) ||
- (mOvInfo.dst_rect.y ^ y) ||
- (mOvInfo.dst_rect.w ^ w) ||
- (mOvInfo.dst_rect.h ^ h);
-
- mOvInfo.dst_rect.x = x;
- mOvInfo.dst_rect.y = y;
- mOvInfo.dst_rect.w = w;
- mOvInfo.dst_rect.h = h;
-}
-
-void OverlayUI::setCrop(int x, int y, int w, int h) {
- mParamsChanged |= (mOvInfo.src_rect.x ^ x) ||
- (mOvInfo.src_rect.y ^ y) ||
- (mOvInfo.src_rect.w ^ w) ||
- (mOvInfo.src_rect.h ^ h);
-
- mOvInfo.src_rect.x = x;
- mOvInfo.src_rect.y = y;
- mOvInfo.src_rect.w = w;
- mOvInfo.src_rect.h = h;
-}
-
-void OverlayUI::setupOvRotInfo() {
- int w = mSource.width;
- int h = mSource.height;
- int format = mSource.format;
- int srcw = (w + 31) & ~31;
- int srch = (h + 31) & ~31;
- mOvInfo.src.width = srcw;
- mOvInfo.src.height = srch;
- mOvInfo.src.format = format;
- mOvInfo.src_rect.w = w;
- mOvInfo.src_rect.h = h;
- mOvInfo.alpha = 0xff;
- mOvInfo.transp_mask = 0xffffffff;
- mRotInfo.src.format = format;
- mRotInfo.dst.format = format;
- mRotInfo.src.width = srcw;
- mRotInfo.src.height = srch;
- mRotInfo.src_rect.w = srcw;
- mRotInfo.src_rect.h = srch;
- mRotInfo.dst.width = srcw;
- mRotInfo.dst.height = srch;
-
- int rot = mOrientation;
- switch(rot) {
- case 0:
- case HAL_TRANSFORM_FLIP_H:
- case HAL_TRANSFORM_FLIP_V:
- rot = 0;
- break;
- case HAL_TRANSFORM_ROT_90:
- case (HAL_TRANSFORM_ROT_90|HAL_TRANSFORM_FLIP_H):
- case (HAL_TRANSFORM_ROT_90|HAL_TRANSFORM_FLIP_V): {
- int tmp = mOvInfo.src_rect.x;
- mOvInfo.src_rect.x = mOvInfo.src.height -
- (mOvInfo.src_rect.y + mOvInfo.src_rect.h);
- mOvInfo.src_rect.y = tmp;
- swapOVRotWidthHeight(mRotInfo, mOvInfo);
- rot = HAL_TRANSFORM_ROT_90;
- break;
- }
- case HAL_TRANSFORM_ROT_180:
- break;
- case HAL_TRANSFORM_ROT_270: {
- int tmp = mOvInfo.src_rect.y;
- mOvInfo.src_rect.y = mOvInfo.src.width -
- (mOvInfo.src_rect.x + mOvInfo.src_rect.w);
- mOvInfo.src_rect.x = tmp;
- swapOVRotWidthHeight(mRotInfo, mOvInfo);
- break;
- }
- default:
- break;
- }
- int mdp_rotation = overlay::get_mdp_orientation(rot);
- if (mdp_rotation < 0)
- mdp_rotation = 0;
- mOvInfo.user_data[0] = mdp_rotation;
- mRotInfo.rotations = mOvInfo.user_data[0];
- if (mdp_rotation)
- mRotInfo.enable = 1;
-}
-
-status_t OverlayUI::commit() {
- status_t ret = BAD_VALUE;
- if(mChannelState != UP)
- mOvInfo.id = MSMFB_NEW_REQUEST;
- ret = startOVSession();
- if (ret == NO_ERROR && mOrientation) {
- ret = mobjRotator.startRotSession(mRotInfo, mSource.size);
- }
- if (ret == NO_ERROR) {
- mChannelState = UP;
- } else {
- LOGE("start channel failed.");
- }
- return ret;
-}
-
-status_t OverlayUI::closeChannel() {
- if( mChannelState != UP ) {
- return NO_ERROR;
- }
- if(NO_ERROR != closeOVSession()) {
- LOGE("%s: closeOVSession() failed.", __FUNCTION__);
- return BAD_VALUE;
- }
- if(NO_ERROR != mobjRotator.closeRotSession()) {
- LOGE("%s: closeRotSession() failed.", __FUNCTION__);
- return BAD_VALUE;
- }
- mChannelState = CLOSED;
- mParamsChanged = false;
- memset(&mOvInfo, 0, sizeof(mOvInfo));
- memset(&mRotInfo, 0, sizeof(mRotInfo));
- return NO_ERROR;
-}
-
-status_t OverlayUI::startOVSession() {
- status_t ret = NO_INIT;
- ret = mobjDisplay.openDisplay(mFBNum);
-
- if (ret != NO_ERROR)
- return ret;
-
- if(mParamsChanged) {
- mParamsChanged = false;
- mdp_overlay ovInfo = mOvInfo;
- if (ioctl(mobjDisplay.getFD(), MSMFB_OVERLAY_SET, &ovInfo)) {
- LOGE("Overlay set failed..");
- ret = BAD_VALUE;
- } else {
- mSessionID = ovInfo.id;
- mOvInfo = ovInfo;
- ret = NO_ERROR;
- }
- }
- return ret;
-}
-
-status_t OverlayUI::closeOVSession() {
- status_t ret = NO_ERROR;
- int err = 0;
- if(err = ioctl(mobjDisplay.getFD(), MSMFB_OVERLAY_UNSET, &mSessionID)) {
- LOGE("%s: MSMFB_OVERLAY_UNSET failed. (%d)", __FUNCTION__, err);
- ret = BAD_VALUE;
- } else {
- mobjDisplay.closeDisplay();
- mSessionID = NO_INIT;
- }
- return ret;
-}
-
-status_t OverlayUI::queueBuffer(buffer_handle_t buffer) {
- status_t ret = NO_INIT;
-
- if (mChannelState != UP)
- return ret;
-
- msmfb_overlay_data ovData;
- memset(&ovData, 0, sizeof(ovData));
-
- private_handle_t const* hnd = reinterpret_cast
- <private_handle_t const*>(buffer);
- ovData.data.memory_id = hnd->fd;
- ovData.data.offset = hnd->offset;
- if (mOrientation) {
- msm_rotator_data_info rotData;
- memset(&rotData, 0, sizeof(rotData));
- rotData.src.memory_id = hnd->fd;
- rotData.src.offset = hnd->offset;
- if (mobjRotator.rotateBuffer(rotData) != NO_ERROR) {
- LOGE("Rotator failed.. ");
- return BAD_VALUE;
- }
- ovData.data.memory_id = rotData.dst.memory_id;
- ovData.data.offset = rotData.dst.offset;
- }
- ovData.id = mSessionID;
- if (ioctl(mobjDisplay.getFD(), MSMFB_OVERLAY_PLAY, &ovData)) {
- LOGE("Queuebuffer failed ");
- return BAD_VALUE;
- }
- return NO_ERROR;
-}
-
-};
diff --git a/liboverlay/overlayLibUI.h b/liboverlay/overlayLibUI.h
deleted file mode 100644
index d16a968..0000000
--- a/liboverlay/overlayLibUI.h
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- * Copyright (c) 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.
- */
-
-#ifndef INCLUDE_OVERLAY_LIB_UI
-#define INCLUDE_OVERLAY_LIB_UI
-
-#include <errno.h>
-
-#include "overlayLib.h"
-
-namespace overlay {
-
-enum channel_state_t { UP, CLOSED, PENDING_CLOSE };
-enum status_t {
- NO_ERROR,
- INVALID_OPERATION = -ENOSYS,
- BAD_VALUE = -EINVAL,
- NO_INIT = -ENODEV,
- ALREADY_EXISTS = -EEXIST
- };
-
-/*
- * Display class provides following services
- * Open FB
- * FB information (Width, Height and Bpp)
- */
-
-class Display {
- int mFD;
- int mFBWidth;
- int mFBHeight;
- int mFBBpp;
- Display(const Display& objDisplay);
- Display& operator=(const Display& objDisplay);
-
-public:
- explicit Display() : mFD(NO_INIT) { };
- ~Display() { close(mFD); };
- int getFD() const { return mFD; };
- int getFBWidth() const { return mFBWidth; };
- int getFBHeight() const { return mFBHeight; };
- int getFBBpp() const { return mFBBpp; };
- status_t openDisplay(int fbnum);
- void closeDisplay();
-};
-
-/*
- * Rotator class, manages rotation of the buffers
- * It communicates with Rotator driver, provides following services
- * Start rotator session
- * Rotate buffer
- */
-
-class Rotator {
- int mFD;
- int mSessionID;
- int mPmemFD;
- void* mPmemAddr;
- int mRotOffset[max_num_buffers];
- int mCurrentItem;
- int mNumBuffers;
- int mSize;
- android::sp<gralloc::IAllocController> mAlloc;
- int mBufferType;
- Rotator(const Rotator& objROtator);
- Rotator& operator=(const Rotator& objRotator);
-
-public:
- explicit Rotator();
- ~Rotator();
- status_t startRotSession(msm_rotator_img_info& rotInfo, int size,
- int numBuffers = max_num_buffers);
- status_t closeRotSession();
- status_t rotateBuffer(msm_rotator_data_info& rotData);
-};
-
-/*
- * Overlay class for Comp. Bypass
- * We merge control and data channel classes.
- */
-
-class OverlayUI {
- channel_state_t mChannelState;
- overlay_buffer_info mSource;
- int mZorder;
- int mOrientation;
- int mFBNum;
- bool mWaitForVsync;
- bool mIsFg;
- int mSessionID;
- Display mobjDisplay;
- Rotator mobjRotator;
-
- mdp_overlay mOvInfo;
- msm_rotator_img_info mRotInfo;
-
- bool mParamsChanged;
-
- OverlayUI(const OverlayUI& objOverlay);
- OverlayUI& operator=(const OverlayUI& objOverlay);
-
- status_t startOVSession();
- status_t closeOVSession();
- void setupOvRotInfo();
-
-public:
-
- enum fbnum_t { FB0, FB1 };
-
- OverlayUI();
- ~OverlayUI();
- void setSource(const overlay_buffer_info& info, int orientation);
- void setPosition(int x, int y, int w, int h);
- void setCrop(int x, int y, int w, int h);
- void setDisplayParams(int fbNum, bool waitForVsync, bool isFg, int zorder,
- bool isVGPipe);
- status_t commit();
- status_t closeChannel();
- channel_state_t isChannelUP() const { return mChannelState; };
- int getFBWidth() const { return mobjDisplay.getFBWidth(); };
- int getFBHeight() const { return mobjDisplay.getFBHeight(); };
- status_t queueBuffer(buffer_handle_t buffer);
-};
-
-};
-#endif
diff --git a/liboverlay/overlayMdp.cpp b/liboverlay/overlayMdp.cpp
new file mode 100644
index 0000000..09499c0
--- /dev/null
+++ b/liboverlay/overlayMdp.cpp
@@ -0,0 +1,289 @@
+/*
+* 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.
+*/
+
+#include "overlayUtils.h"
+#include "overlayMdp.h"
+
+#undef ALOG_TAG
+#define ALOG_TAG "overlay"
+
+namespace ovutils = overlay::utils;
+namespace overlay {
+bool MdpCtrl::open(uint32_t fbnum) {
+ // FD open
+ if(!utils::openDev(mFd, fbnum,
+ Res::devTemplate, O_RDWR)){
+ ALOGE("Ctrl failed to open fbnum=%d", fbnum);
+ return false;
+ }
+ return true;
+}
+
+void MdpCtrl::reset() {
+ utils::memset0(mOVInfo);
+ utils::memset0(mLkgo);
+ mOVInfo.id = -1;
+ mLkgo.id = -1;
+}
+
+bool MdpCtrl::close() {
+ if(-1 == static_cast<int>(mOVInfo.id)) return true;
+ if(!mdp_wrapper::unsetOverlay(mFd.getFD(), mOVInfo.id)) {
+ ALOGE("MdpCtrl close error in unset");
+ return false;
+ }
+ reset();
+ if(!mFd.close()) {
+ return false;
+ }
+ return true;
+}
+
+bool MdpCtrl::getScreenInfo(overlay::utils::ScreenInfo& info) {
+ fb_fix_screeninfo finfo;
+ if (!mdp_wrapper::getFScreenInfo(mFd.getFD(), finfo)) {
+ return false;
+ }
+
+ fb_var_screeninfo vinfo;
+ if (!mdp_wrapper::getVScreenInfo(mFd.getFD(), vinfo)) {
+ return false;
+ }
+ info.mFBWidth = vinfo.xres;
+ info.mFBHeight = vinfo.yres;
+ info.mFBbpp = vinfo.bits_per_pixel;
+ info.mFBystride = finfo.line_length;
+ return true;
+}
+
+bool MdpCtrl::get() {
+ mdp_overlay ov;
+ ov.id = mOVInfo.id;
+ if (!mdp_wrapper::getOverlay(mFd.getFD(), ov)) {
+ ALOGE("MdpCtrl get failed");
+ return false;
+ }
+ mOVInfo = ov;
+ return true;
+}
+
+// that is the second part of original setParameter function
+void MdpCtrl::setSrcFormat(const utils::Whf& whf) {
+
+ //By default mdp src format is the same as buffer's
+ mOVInfo.src.format = whf.format;
+
+ //If rotation is used and input formats are tiled then output of rotator is
+ //non-tiled.
+ // FIXME mRotInfo.enable = 1; for enable
+ if (getUserData()) { // if rotations enabled in MdpCtrl
+ if (whf.format == MDP_Y_CRCB_H2V2_TILE)
+ mOVInfo.src.format = MDP_Y_CRCB_H2V2;
+ else if (whf.format == MDP_Y_CBCR_H2V2_TILE)
+ mOVInfo.src.format = MDP_Y_CBCR_H2V2;
+ return;
+ }
+
+}
+
+bool MdpCtrl::set() {
+ if(!this->ovChanged()) {
+ return true; // nothing todo here.
+ }
+
+ if(!mdp_wrapper::setOverlay(mFd.getFD(), mOVInfo)) {
+ ALOGE("MdpCtrl failed to setOverlay, restoring last known "
+ "good ov info");
+ mdp_wrapper::dump("== Bad OVInfo is: ", mOVInfo);
+ mdp_wrapper::dump("== Last good known OVInfo is: ", mLkgo);
+ this->restore();
+ // FIXME, do we need to set the old one?
+ return false;
+ }
+ this->save();
+ return true;
+}
+
+bool MdpCtrl::setPosition(const overlay::utils::Dim& d,
+ int fbw, int fbh)
+{
+ // Validatee against FB size
+ if(!d.check(fbw, fbh)) {
+ ALOGE("MdpCtrl setPosition failed dest dim violate screen limits");
+ return false;
+ }
+
+ ovutils::Dim dim(d);
+ ovutils::Dim ovsrcdim = getSrcRectDim();
+ // Scaling of upto a max of 8 times supported
+ if(dim.w >(ovsrcdim.w * ovutils::HW_OV_MAGNIFICATION_LIMIT)){
+ dim.w = ovutils::HW_OV_MAGNIFICATION_LIMIT * ovsrcdim.w;
+ dim.x = (fbw - dim.w) / 2;
+ }
+ if(dim.h >(ovsrcdim.h * ovutils::HW_OV_MAGNIFICATION_LIMIT)) {
+ dim.h = ovutils::HW_OV_MAGNIFICATION_LIMIT * ovsrcdim.h;
+ dim.y = (fbh - dim.h) / 2;
+ }
+
+ //dim.even_out();
+ setDstRectDim(dim);
+ return true;
+}
+
+void MdpCtrl::updateSource(RotatorBase* r,
+ const utils::PipeArgs& args,
+ const utils::ScreenInfo& info) {
+ utils::Whf whf(args.whf);
+ mOVInfo.src.width = whf.w;
+ mOVInfo.src.height = whf.h;
+ mOVInfo.src_rect.x = 0;
+ mOVInfo.src_rect.y = 0;
+ mOVInfo.dst_rect.x = 0;
+ mOVInfo.dst_rect.y = 0;
+ mOVInfo.dst_rect.w = whf.w;
+ mOVInfo.dst_rect.h = whf.h;
+ mOVInfo.src.format = whf.format;
+
+ if(whf.format == MDP_Y_CRCB_H2V2_TILE ||
+ (whf.format == MDP_Y_CBCR_H2V2_TILE)) {
+ // passing by value, setInfo fills it and return by val
+ mOVInfo = r->setInfo(args, mOVInfo);
+ } else {
+ mOVInfo.src_rect.w = whf.w;
+ mOVInfo.src_rect.h = whf.h;
+ }
+
+ if (whf.w > info.mFBWidth)
+ mOVInfo.dst_rect.w = info.mFBWidth;
+ if (whf.h > info.mFBHeight)
+ mOVInfo.dst_rect.h = info.mFBHeight;
+ mSize = whf.size;
+}
+
+
+bool MdpCtrl::setInfo(RotatorBase* r,
+ const utils::PipeArgs& args,
+ const utils::ScreenInfo& info)
+{
+ // new request
+ utils::Whf whf(args.whf);
+ mOVInfo.id = MSMFB_NEW_REQUEST;
+
+ updateSource(r, args, info);
+
+ setUserData(0);
+ mOVInfo.alpha = 0xff;
+ mOVInfo.transp_mask = 0xffffffff;
+ setZ(args.zorder);
+ setFlags(args.mdpFlags);
+ setWait(args.wait);
+ setIsFg(args.isFg);
+ mSize = whf.size;
+ return true;
+}
+
+bool MdpCtrl::setCrop(const utils::Dim& cdim) {
+ utils::Dim d(cdim);
+ const utils::Whf ovwhf = getSrcWhf();
+ int udata = getUserData();
+ switch(udata) {
+ case MDP_ROT_NOP:
+ break; // nothing to do here
+ case MDP_ROT_90:
+ case MDP_ROT_90 | MDP_FLIP_UD:
+ case MDP_ROT_90 | MDP_FLIP_LR:
+ {
+ if (ovwhf.w < (d.y + d.h)) {
+ ALOGE("MdpCtrl setCrop failed ROT 90 udata=%d",
+ udata);
+ d.dump();
+ this->dump();
+ return false;
+ }
+ uint32_t tmp = d.x;
+ d.x = ovwhf.w - (d.y + d.h);
+ d.y = tmp;
+ utils::swap(d.w, d.h);
+ }break;
+ case MDP_ROT_270:
+ {
+ if (ovwhf.h < (d.x + d.w)) {
+ ALOGE("MdpCtrl setCrop failed ROT 270 udata=%d",
+ udata);
+ d.dump();
+ this->dump();
+ return false;
+ }
+ uint32_t tmp = d.y;
+ d.y = ovwhf.h - (d.x + d.w);
+ d.x = tmp;
+ utils::swap(d.w, d.h);
+ }break;
+ case MDP_ROT_180:
+ {
+ if ((ovwhf.h < (d.y + d.h)) ||
+ (ovwhf.w < ( d.x + d.w))) {
+ ALOGE("MdpCtrl setCrop failed ROT 180 udata=%d",
+ udata);
+ d.dump();
+ this->dump();
+ return false;
+ }
+ d.x = ovwhf.w - (d.x + d.w);
+ d.y = ovwhf.h - (d.y + d.h);
+ }break;
+ default:
+ if(!(udata & (MDP_FLIP_UD | MDP_FLIP_LR))) {
+ ALOGE("MdpCtrl setCrop unknown rot %d", udata);
+ return false;
+ }
+ }
+
+ if(getSrcRectDim() == d) {
+ return true; // Nothing to do here
+ }
+
+ utils::normalizeCrop(d.x, d.w);
+ utils::normalizeCrop(d.y, d.h);
+
+ setSrcRectDim(d);
+
+ return true;
+}
+
+void MdpCtrl::dump() const {
+ ALOGE("== Dump MdpCtrl start ==");
+ ALOGE("size=%d", mSize);
+ mFd.dump();
+ mdp_wrapper::dump("mOVInfo", mOVInfo);
+ ALOGE("== Dump MdpCtrl end ==");
+}
+
+void MdpData::dump() const {
+ ALOGE("== Dump MdpData start ==");
+ mFd.dump();
+ mdp_wrapper::dump("mOvData", mOvData);
+ ALOGE("== Dump MdpData end ==");
+}
+
+void MdpCtrl3D::dump() const {
+ ALOGE("== Dump MdpCtrl start ==");
+ mFd.dump();
+ ALOGE("== Dump MdpCtrl end ==");
+}
+
+} // overlay
diff --git a/liboverlay/overlayMdp.h b/liboverlay/overlayMdp.h
new file mode 100644
index 0000000..29f8fd5
--- /dev/null
+++ b/liboverlay/overlayMdp.h
@@ -0,0 +1,489 @@
+/*
+* 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.
+*/
+
+#ifndef OVERLAY_MDP_H
+#define OVERLAY_MDP_H
+
+#include <linux/msm_mdp.h>
+
+#include "overlayUtils.h"
+#include "mdpWrapper.h"
+#include "overlayRotator.h"
+
+namespace overlay{
+
+class RotatorBase;
+
+/*
+* Mdp Ctrl holds corresponding fd and MDP related struct.
+* It is simple wrapper to MDP services
+* */
+class MdpCtrl {
+public:
+ /* ctor reset */
+ explicit MdpCtrl();
+
+ /* dtor close */
+ ~MdpCtrl();
+
+ /* Open underlying device using fbnum */
+ bool open(uint32_t fbnum);
+
+ /* unset overlay, reset and close fd */
+ bool close();
+
+ /* reset and set ov id to -1*/
+ void reset();
+
+ /* get orient / user_data[0] */
+ int getOrient() const;
+
+ /* returns session id */
+ int getId() const;
+
+ /* returns the fd associated to ctrl*/
+ int getFd() const;
+
+ /* Get screen info. out: info*/
+ bool getScreenInfo(utils::ScreenInfo& info);
+
+ /* overlay get */
+ bool get();
+
+ /* returns flags from mdp structure.
+ * Flags are WAIT/NOWAIT/PIPE SHARED*/
+ int getFlags() const;
+
+ /* set flags to mdp structure */
+ void setFlags(int f);
+
+ /* code taken from OverlayControlChannel::setOverlayInformation */
+ bool setInfo(RotatorBase* r,
+ const utils::PipeArgs& args,
+ const utils::ScreenInfo& info);
+
+ /* given whf, update src */
+ void updateSource(RotatorBase* r,
+ const utils::PipeArgs& args,
+ const utils::ScreenInfo& info);
+
+ /* set z order */
+ void setZ(utils::eZorder z);
+
+ /* set Wait/nowait */
+ void setWait(utils::eWait wait);
+
+ /* set isFg flag */
+ void setIsFg(utils::eIsFg isFg);
+
+ /* calls overlay set
+ * Set would always consult last good known ov instance.
+ * Only if it is different, set would actually exectue ioctl.
+ * On a sucess ioctl. last good known ov instance is updated */
+ bool set();
+
+ /* return a copy of src whf*/
+ utils::Whf getSrcWhf() const;
+
+ /* set src whf */
+ void setSrcWhf(const utils::Whf& whf);
+
+ /* set source format based on rot info */
+ void setSrcFormat(const utils::Whf& whf);
+
+ /* swap src w/h*/
+ void swapSrcWH();
+
+ /* swap src rect w/h */
+ void swapSrcRectWH();
+
+ /* returns a copy to src rect dim */
+ utils::Dim getSrcRectDim() const;
+
+ /* set src/dst rect dim */
+ void setSrcRectDim(const utils::Dim d);
+ void setDstRectDim(const utils::Dim d);
+
+ /* returns a copy ro dst rect dim */
+ utils::Dim getDstRectDim() const;
+
+ /* returns user_data[0]*/
+ int getUserData() const;
+
+ /* sets user_data[0] */
+ void setUserData(int v);
+
+ /* return true if current overlay is different
+ * than lask known good overlay */
+ bool ovChanged() const;
+
+ /* save mOVInfo to be last known good ov*/
+ void save();
+
+ /* restore last known good ov to be the current */
+ void restore();
+
+ /*
+ * Sets ROI, the unpadded region, for source buffer.
+ * Should be called before a setPosition, for small clips.
+ * Dim - ROI dimensions.
+ */
+ bool setCrop(const utils::Dim& d);
+
+ /* given a dim and w/h, set overlay dim */
+ bool setPosition(const utils::Dim& dim, int w, int h);
+
+ /* using user_data, sets/unsets roationvalue in mdp flags */
+ void setRotationFlags();
+
+ /* dump state of the object */
+ void dump() const;
+private:
+
+ /* last good known ov info */
+ mdp_overlay mLkgo;
+
+ /* Actual overlay mdp structure */
+ mdp_overlay mOVInfo;
+
+ /* FD for the mdp fbnum */
+ OvFD mFd;
+
+ /* cached size FIXME do we need it? */
+ uint32_t mSize;
+};
+
+
+/* MDP 3D related ctrl */
+class MdpCtrl3D {
+public:
+ /* ctor reset data */
+ MdpCtrl3D();
+ /* calls MSMFB_OVERLAY_3D */
+ bool close();
+ /* set w/h. format is ignored*/
+ void setWh(const utils::Whf& whf);
+ /* set is_3d calls MSMFB_OVERLAY_3D */
+ bool useVirtualFB();
+ /* set fd to be used in ioctl */
+ void setFd(int fd);
+ /* dump */
+ void dump() const;
+private:
+ /* reset */
+ void reset();
+ /* actual MSM 3D info */
+ msmfb_overlay_3d m3DOVInfo;
+ /* FD for the mdp 3D */
+ OvFD mFd;
+};
+
+/* MDP data */
+class MdpData {
+public:
+ /* ctor reset data */
+ explicit MdpData();
+
+ /* dtor close*/
+ ~MdpData();
+
+ /* open FD */
+ bool open(uint32_t fbnum);
+
+ /* memset0 the underlying mdp object */
+ void reset();
+
+ /* close fd, and reset */
+ bool close();
+
+ /* Set FD / memid */
+ void setMemoryId(int id);
+
+ /* set id of mdp data */
+ void setId(int id);
+
+ /* return ses id of data */
+ int getId() const;
+
+ /* get underlying fd*/
+ int getFd() const;
+
+ /* get memory_id */
+ int getMemoryId() const;
+
+ /* set offset in underlying mdp obj */
+ void setOffset(uint32_t o);
+
+ /* calls wrapper play */
+ bool play();
+
+ /* calls wrapper playWait */
+ bool playWait();
+
+ /* dump state of the object */
+ void dump() const;
+private:
+
+ /* actual overlay mdp data */
+ msmfb_overlay_data mOvData;
+
+ /* fd to mdp fbnum */
+ OvFD mFd;
+};
+
+//--------------Inlines---------------------------------
+namespace utils {
+ inline bool openDev(OvFD& fd, int fb,
+ const char* const s,
+ int flags) {
+ return overlay::open(fd, fb, Res::devTemplate, O_RDWR);
+ }
+}
+
+template <class T>
+ inline void init(T& t) {
+ memset(&t, 0, sizeof(T));
+ }
+
+///// MdpCtrl //////
+
+inline MdpCtrl::MdpCtrl() : mSize(0) {
+ reset();
+}
+
+inline MdpCtrl::~MdpCtrl() {
+ close();
+}
+
+inline int MdpCtrl::getOrient() const {
+ return getUserData();
+}
+
+inline int MdpCtrl::getId() const {
+ return mOVInfo.id;
+}
+
+inline int MdpCtrl::getFd() const {
+ return mFd.getFD();
+}
+
+inline int MdpCtrl::getFlags() const {
+ return mOVInfo.flags;
+}
+
+inline void MdpCtrl::setFlags(int f) {
+ mOVInfo.flags = f;
+}
+
+inline void MdpCtrl::setZ(overlay::utils::eZorder z) {
+ mOVInfo.z_order = z;
+}
+
+inline void MdpCtrl::setWait(overlay::utils::eWait wait) {
+ mOVInfo.flags = utils::setWait(wait, mOVInfo.flags);
+}
+
+inline void MdpCtrl::setIsFg(overlay::utils::eIsFg isFg) {
+ mOVInfo.is_fg = isFg;
+}
+
+inline bool MdpCtrl::ovChanged() const {
+ // 0 means same
+ if(0 == ::memcmp(&mOVInfo, &mLkgo, sizeof (mdp_overlay))) {
+ return false;
+ }
+ return true;
+}
+
+inline void MdpCtrl::save() {
+ if(static_cast<ssize_t>(mOVInfo.id) == -1) {
+ ALOGE("MdpCtrl current ov has id -1, will not save");
+ // FIXME dump both?
+ return;
+ }
+ mLkgo = mOVInfo;
+}
+
+inline void MdpCtrl::restore() {
+ if(static_cast<ssize_t>(mLkgo.id) == -1) {
+ ALOGE("MdpCtrl Lkgo ov has id -1, will not restore");
+ // FIXME dump both?
+ return;
+ }
+ mOVInfo = mLkgo;
+}
+
+inline overlay::utils::Whf MdpCtrl::getSrcWhf() const {
+ return utils::Whf(mOVInfo.src.width,
+ mOVInfo.src.height,
+ mOVInfo.src.format);
+}
+
+inline void MdpCtrl::setSrcWhf(const overlay::utils::Whf& whf) {
+ mOVInfo.src.width = whf.w;
+ mOVInfo.src.height = whf.h;
+ mOVInfo.src.format = whf.format;
+}
+
+inline overlay::utils::Dim MdpCtrl::getSrcRectDim() const {
+ return utils::Dim(mOVInfo.src_rect.x,
+ mOVInfo.src_rect.y,
+ mOVInfo.src_rect.w,
+ mOVInfo.src_rect.h);
+}
+
+inline void MdpCtrl::setSrcRectDim(const overlay::utils::Dim d) {
+ mOVInfo.src_rect.x = d.x;
+ mOVInfo.src_rect.y = d.y;
+ mOVInfo.src_rect.w = d.w;
+ mOVInfo.src_rect.h = d.h;
+}
+
+inline overlay::utils::Dim MdpCtrl::getDstRectDim() const {
+ return utils::Dim(mOVInfo.dst_rect.x,
+ mOVInfo.dst_rect.y,
+ mOVInfo.dst_rect.w,
+ mOVInfo.dst_rect.h);
+}
+
+inline void MdpCtrl::setDstRectDim(const overlay::utils::Dim d) {
+ mOVInfo.dst_rect.x = d.x;
+ mOVInfo.dst_rect.y = d.y;
+ mOVInfo.dst_rect.w = d.w;
+ mOVInfo.dst_rect.h = d.h;
+}
+
+inline int MdpCtrl::getUserData() const { return mOVInfo.user_data[0]; }
+
+inline void MdpCtrl::setUserData(int v) { mOVInfo.user_data[0] = v; }
+
+inline void MdpCtrl::setRotationFlags() {
+ const int u = getUserData();
+ if (u == MDP_ROT_90 || u == MDP_ROT_270)
+ mOVInfo.flags |= MDP_SOURCE_ROTATED_90;
+ else
+ mOVInfo.flags &= ~MDP_SOURCE_ROTATED_90;
+}
+
+
+inline void MdpCtrl::swapSrcWH() {
+ utils::swap(mOVInfo.src.width,
+ mOVInfo.src.height); }
+
+inline void MdpCtrl::swapSrcRectWH() {
+ utils::swap(mOVInfo.src_rect.h,
+ mOVInfo.src_rect.w); }
+
+/////// MdpCtrl3D //////
+
+inline MdpCtrl3D::MdpCtrl3D() { reset(); }
+inline bool MdpCtrl3D::close() {
+ if (m3DOVInfo.is_3d) {
+ m3DOVInfo.is_3d = 0;
+ if(!mdp_wrapper::set3D(mFd.getFD(), m3DOVInfo)) {
+ ALOGE("MdpCtrl3D close failed set3D with 0");
+ return false;
+ }
+ }
+ reset();
+ return true;
+}
+inline void MdpCtrl3D::reset() {
+ utils::memset0(m3DOVInfo);
+}
+
+inline void MdpCtrl3D::setFd(int fd) {
+ mFd.copy(fd);
+ OVASSERT(mFd.valid(), "MdpCtrl3D setFd, FD should be valid");
+}
+
+inline void MdpCtrl3D::setWh(const utils::Whf& whf) {
+ // ignore fmt. Needed for useVirtualFB callflow
+ m3DOVInfo.width = whf.w;
+ m3DOVInfo.height = whf.h;
+}
+
+inline bool MdpCtrl3D::useVirtualFB() {
+ if(!m3DOVInfo.is_3d) {
+ m3DOVInfo.is_3d = 1;
+ if(!mdp_wrapper::set3D(mFd.getFD(), m3DOVInfo)) {
+ ALOGE("MdpCtrl3D close failed set3D with 0");
+ return false;
+ }
+ }
+ return true;
+}
+
+/////// MdpData //////
+
+inline MdpData::MdpData() { reset(); }
+
+inline MdpData::~MdpData() { close(); }
+
+inline bool MdpData::open(uint32_t fbnum) {
+ // FD open
+ if(!utils::openDev(mFd, fbnum, Res::devTemplate, O_RDWR)){
+ ALOGE("Ctrl failed to open fbnum=%d", fbnum);
+ return false;
+ }
+ return true;
+}
+
+inline void MdpData::reset() {
+ overlay::utils::memset0(mOvData);
+ mOvData.data.memory_id = -1;
+}
+
+inline bool MdpData::close() {
+ if(-1 == mOvData.data.memory_id) return true;
+ reset();
+ if(!mFd.close()) {
+ return false;
+ }
+ return true;
+}
+
+inline void MdpData::setMemoryId(int id) { mOvData.data.memory_id = id; }
+inline int MdpData::getMemoryId() const { return mOvData.data.memory_id; }
+
+inline void MdpData::setId(int id) { mOvData.id = id; }
+
+inline int MdpData::getId() const { return mOvData.id; }
+
+inline int MdpData::getFd() const { return mFd.getFD(); }
+
+inline void MdpData::setOffset(uint32_t o) { mOvData.data.offset = o; }
+
+inline bool MdpData::play() {
+ if(!mdp_wrapper::play(mFd.getFD(), mOvData)){
+ ALOGE("MdpData failed to play");
+ return false;
+ }
+ return true;
+}
+
+inline bool MdpData::playWait() {
+ if(!mdp_wrapper::playWait(mFd.getFD(), mOvData)){
+ ALOGE("MdpData failed to playWait");
+ return false;
+ }
+ return true;
+}
+
+} // overlay
+
+#endif // OVERLAY_MDP_H
diff --git a/liboverlay/overlayMem.h b/liboverlay/overlayMem.h
new file mode 100644
index 0000000..7c04890
--- /dev/null
+++ b/liboverlay/overlayMem.h
@@ -0,0 +1,205 @@
+/*
+* Copyright (c) 2011-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 OVERLAY_MEM_H
+#define OVERLAY_MEM_H
+
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <alloc_controller.h>
+#include <memalloc.h>
+
+#include "gralloc_priv.h"
+#include "overlayUtils.h"
+
+namespace overlay {
+
+/*
+* Holds base address, offset and the fd
+* */
+class OvMem {
+public:
+ /* ctor init*/
+ explicit OvMem();
+
+ /* dtor DO NOT call close so it can be copied */
+ ~OvMem();
+
+ /* Use libgralloc to retrieve fd, base addr, alloc type */
+ bool open(uint32_t numbufs,
+ uint32_t bufSz, int flags = O_RDWR);
+
+ /* close fd. assign base address to invalid*/
+ bool close();
+
+ /* return underlying fd */
+ int getFD() const;
+
+ /* return true if fd is valid and base address is valid */
+ bool valid() const;
+
+ /* dump the state of the object */
+ void dump() const;
+
+ /* return underlying address */
+ void* addr() const;
+
+ /* return underlying offset */
+ uint32_t bufSz() const;
+
+ /* return number of bufs */
+ uint32_t numBufs() const ;
+
+private:
+ /* actual os fd */
+ int mFd;
+
+ /* points to base addr (mmap)*/
+ void* mBaseAddr;
+
+ /* allocated buffer type determined by gralloc (ashmem, ion, etc) */
+ int mAllocType;
+
+ /* holds buf size */
+ uint32_t mBufSz;
+
+ /* num of bufs */
+ uint32_t mNumBuffers;
+
+ /* gralloc alloc controller */
+ android::sp<gralloc::IAllocController> mAlloc;
+};
+
+//-------------------Inlines-----------------------------------
+
+using android::sp;
+using gralloc::IMemAlloc;
+using gralloc::alloc_data;
+
+inline OvMem::OvMem() {
+ mFd = -1;
+ mBaseAddr = MAP_FAILED;
+ mAllocType = 0;
+ mBufSz = 0;
+ mNumBuffers = 0;
+ mAlloc = gralloc::IAllocController::getInstance(false);
+}
+
+inline OvMem::~OvMem() { }
+
+inline bool OvMem::open(uint32_t numbufs,
+ uint32_t bufSz, int flags)
+{
+ alloc_data data;
+ //XXX: secure buffers and IOMMU heap
+ int allocFlags = GRALLOC_USAGE_PRIVATE_MM_HEAP |
+ GRALLOC_USAGE_PRIVATE_DO_NOT_MAP;
+ int err = 0;
+
+ OVASSERT(numbufs && bufSz, "numbufs=%d bufSz=%d", numbufs, bufSz);
+
+ mBufSz = bufSz;
+ mNumBuffers = numbufs;
+
+ data.base = 0;
+ data.fd = -1;
+ data.offset = 0;
+ data.size = mBufSz * mNumBuffers;
+ data.align = getpagesize();
+ data.uncached = true;
+
+ err = mAlloc->allocate(data, allocFlags, 0);
+ if (err != 0) {
+ ALOGE("OvMem: error allocating memory");
+ }
+
+ mFd = data.fd;
+ mBaseAddr = data.base;
+ mAllocType = data.allocType;
+
+ return true;
+}
+
+inline bool OvMem::close()
+{
+ int ret = 0;
+
+ if(!valid()) {
+ return true;
+ }
+
+ sp<IMemAlloc> memalloc = mAlloc->getAllocator(mAllocType);
+ ret = memalloc->free_buffer(mBaseAddr, mBufSz * mNumBuffers, 0, mFd);
+ if (ret != 0) {
+ ALOGE("OvMem: error freeing buffer");
+ }
+
+ mFd = -1;
+ mBaseAddr = MAP_FAILED;
+ mAllocType = 0;
+ mBufSz = 0;
+ mNumBuffers = 0;
+ return ret;
+}
+
+inline bool OvMem::valid() const
+{
+ return (mFd != -1) && (mBaseAddr != MAP_FAILED);
+}
+
+inline int OvMem::getFD() const
+{
+ return mFd;
+}
+
+inline void* OvMem::addr() const
+{
+ return mBaseAddr;
+}
+
+inline uint32_t OvMem::bufSz() const
+{
+ return mBufSz;
+}
+
+inline uint32_t OvMem::numBufs() const
+{
+ return mNumBuffers;
+}
+
+inline void OvMem::dump() const
+{
+ ALOGE("%s: fd=%d addr=%p type=%d bufsz=%u",
+ __FUNCTION__, mFd, mBaseAddr, mAllocType, mBufSz);
+}
+
+} // overlay
+
+#endif // OVERLAY_MEM_H
diff --git a/liboverlay/overlayRotator.cpp b/liboverlay/overlayRotator.cpp
new file mode 100644
index 0000000..30c5ea5
--- /dev/null
+++ b/liboverlay/overlayRotator.cpp
@@ -0,0 +1,430 @@
+/*
+* 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.
+*/
+
+#include "overlayRotator.h"
+#include "overlayUtils.h"
+#include "overlayMdp.h"
+
+namespace ovutils = overlay::utils;
+
+namespace overlay {
+
+namespace utils {
+inline mdp_overlay setInfoNullRot(const utils::PipeArgs& args,
+ const mdp_overlay& o)
+{
+ mdp_overlay ov = o;
+ utils::Whf whf(args.whf);
+ utils::Dim d(utils::getSrcRectDim(ov));
+
+ d.w = whf.w - (utils::alignup(whf.w, 64) - whf.w);
+ d.h = whf.h - (utils::alignup(whf.h, 32) - whf.h);
+ utils::setSrcRectDim(ov, d);
+ return ov;
+}
+
+inline mdp_overlay setInfoRot(const utils::PipeArgs& args,
+ const mdp_overlay& o)
+{
+ /* If there are no orientation, then we use setInfoRot
+ * That is even if we are a real rotator object (not null)
+ * Note, that if args.rotFlags are ENABLED
+ * it means we would still like to have rot
+ * even though it is ROT_0 */
+ if(OVERLAY_TRANSFORM_0 == args.orientation &&
+ utils::ROT_FLAG_ENABLED != args.rotFlags) {
+ return setInfoNullRot(args, o);
+ }
+
+ mdp_overlay ov = o;
+ utils::Whf whf(args.whf);
+ utils::Dim d(utils::getSrcRectDim(ov));
+ d.w = whf.w;
+ d.h = whf.h;
+ utils::Whf localwhf (utils::getSrcWhf(ov));
+ localwhf.w = utils::alignup(whf.w, 64);
+ localwhf.h = utils::alignup(whf.h, 32);
+ d.x = localwhf.w - whf.w;
+ d.y = localwhf.h - whf.h;
+ utils::setSrcRectDim(ov, d);
+ utils::setSrcWhf(ov, localwhf);
+ return ov;
+}
+
+} // utils
+
+bool MdpRot::open()
+{
+ if(!mFd.open(Res::rotPath, O_RDWR)){
+ ALOGE("MdpRot failed to open %s", Res::rotPath);
+ return false;
+ }
+ return true;
+}
+
+bool MdpRot::open_i(uint32_t numbufs, uint32_t bufsz)
+{
+ OvMem mem;
+
+ OVASSERT(MAP_FAILED == mem.addr(), "MAP failed in open_i");
+
+ if(!mem.open(numbufs, bufsz)){
+ ALOGE("%s: Failed to open", __func__);
+ mem.close();
+ return false;
+ }
+
+ OVASSERT(MAP_FAILED != mem.addr(), "MAP failed");
+ OVASSERT(mem.getFD() != -1, "getFd is -1");
+
+ mData.data.memory_id = mem.getFD();
+ mRotDataInfo.dst.memory_id = mem.getFD();
+ mRotDataInfo.dst.offset = 0;
+ mMem.curr().m = mem;
+ return true;
+}
+
+bool MdpRot::RotMem::close() {
+ bool ret = true;
+ for(uint32_t i=0; i < RotMem::MAX_ROT_MEM; ++i) {
+ // skip current, and if valid, close
+ if(m[i].valid() && (m[i].close() != 0)) {
+ ALOGE("%s error in closing prev rot mem %d", __FUNCTION__, i);
+ ret = false;
+ }
+ }
+ return ret;
+}
+
+bool MdpRot::close() {
+ bool success = true;
+ if(mFd.valid() && (getSessId() > 0)) {
+ if(!mdp_wrapper::endRotator(mFd.getFD(), getSessId())) {
+ ALOGE("Mdp Rot error endRotator, fd=%d sessId=%d",
+ mFd.getFD(), getSessId());
+ success = false;
+ }
+ }
+ if (!mFd.close()) {
+ ALOGE("Mdp Rot error closing fd");
+ success = false;
+ }
+ if (!mMem.close()) {
+ ALOGE("Mdp Rot error closing mem");
+ success = false;
+ }
+ reset();
+ return success;
+}
+
+bool MdpRot::unmapNonCurrent() {
+ bool ret = true;
+ for(uint32_t i=0; i < RotMem::MAX_ROT_MEM; ++i) {
+ // skip current, and if valid, close
+ if(i != mMem._curr % RotMem::MAX_ROT_MEM &&
+ mMem.m[i].valid() &&
+ !mMem.m[i].close()) {
+ ALOGE("%s error in closing prev rot mem %d", __FUNCTION__, i);
+ ret = false;
+ }
+ }
+ return ret;
+}
+
+bool MdpRot::remap(uint32_t numbufs,
+ const utils::PipeArgs& args) {
+ // if current size changed, remap
+ if(args.whf.size == mMem.curr().size()) {
+ ALOGE_IF(DEBUG_OVERLAY, "%s: same size %d", __FUNCTION__, args.whf.size);
+ return true;
+ }
+
+ // remap only if we have orientation.
+ // If rotFlags are ENABLED, it means we need rotation bufs
+ // even when orientation is 0
+ if(utils::OVERLAY_TRANSFORM_0 == args.orientation &&
+ utils::ROT_FLAG_ENABLED != args.rotFlags) {
+ ALOGE_IF(DEBUG_OVERLAY, "%s: orientation=%d, rotFlags=%d",
+ __FUNCTION__, args.orientation, args.rotFlags);
+ return true;
+ }
+
+ ALOGE_IF(DEBUG_OVERLAY, "%s: size changed - remapping", __FUNCTION__);
+ OVASSERT(!mMem.prev().valid(), "Prev should not be valid");
+
+ // remap and have the current to be the new one.
+ // ++mMem will make curr to be prev, and prev will be curr
+ ++mMem;
+ if(!open_i(numbufs, args.whf.size)) {
+ ALOGE("%s Error could not open", __FUNCTION__);
+ return false;
+ }
+ OVASSERT(numbufs <= ROT_MAX_BUF_OFFSET,
+ "Numbufs %d > ROT_MAX_BUF_OFFSET", numbufs);
+ for (uint32_t i = 0; i < numbufs; ++i) {
+ mMem.curr().mRotOffset[i] = i * args.whf.size;
+ }
+ return true;
+}
+
+bool MdpRot::start() {
+ if(!overlay::mdp_wrapper::startRotator(mFd.getFD(), mRotImgInfo)) {
+ ALOGE("MdpRot start failed");
+ this->dump();
+ return false;
+ }
+ mRotDataInfo.session_id = mRotImgInfo.session_id;
+ return true;
+}
+
+void MdpRot::reset() {
+ ovutils::memset0(mRotImgInfo);
+ ovutils::memset0(mRotDataInfo);
+ ovutils::memset0(mData);
+ ovutils::memset0(mMem.curr().mRotOffset);
+ ovutils::memset0(mMem.prev().mRotOffset);
+ mMem.curr().mCurrOffset = 0;
+ mMem.prev().mCurrOffset = 0;
+ isSrcFB = false;
+}
+
+bool MdpRot::prepareQueueBuf(uint32_t offset) {
+ // FIXME if it fails, what happens to the above current item?
+ if(enabled()) {
+ OVASSERT(mMem.curr().m.numBufs(),
+ "prepareQueueBuf numbufs is 0");
+
+ // If the rotator source is FB
+ if(isSrcFB) {
+ mRotDataInfo.src.flags |= MDP_MEMORY_ID_TYPE_FB;
+ }
+
+ mRotDataInfo.src.offset = offset;
+ mRotDataInfo.dst.offset =
+ mMem.curr().mRotOffset[mMem.curr().mCurrOffset];
+ mMem.curr().mCurrOffset =
+ (mMem.curr().mCurrOffset + 1) % mMem.curr().m.numBufs();
+ if(!overlay::mdp_wrapper::rotate(mFd.getFD(), mRotDataInfo)) {
+ ALOGE("MdpRot failed rotate");
+ return false;
+ }
+ mData.data.offset = mRotDataInfo.dst.offset;
+ }
+ return true;
+}
+
+
+bool MdpRot::play(int fd) {
+ if(!overlay::mdp_wrapper::play(fd, mData)) {
+ ALOGE("MdpRot failed to play with fd=%d", fd);
+ return false;
+ }
+
+ // if the prev mem is valid, we need to close
+ if(mMem.prev().valid()) {
+ // FIXME FIXME FIXME if no wait for vsync the above
+ // play will return immediatly and might cause
+ // tearing when prev.close is called.
+ if(!mMem.prev().close()) {
+ ALOGE("%s error in closing prev rot mem", __FUNCTION__);
+ }
+ }
+ return true;
+}
+
+///// Null Rot ////
+
+mdp_overlay NullRotator::setInfo(
+ const utils::PipeArgs& args,
+ const mdp_overlay& o) {
+ return utils::setInfoNullRot(args, o);
+}
+
+///// Rotator ////
+
+mdp_overlay Rotator::setInfo(
+ const utils::PipeArgs& args,
+ const mdp_overlay& o)
+{
+ return utils::setInfoRot(args, o);
+}
+
+bool Rotator::overlayTransform(MdpCtrl& mdp,
+ utils::eTransform& rot)
+{
+ ALOGE_IF(DEBUG_OVERLAY, "%s: rot=%d", __FUNCTION__, rot);
+ switch(int(rot)) {
+ case 0:
+ case HAL_TRANSFORM_FLIP_H:
+ case HAL_TRANSFORM_FLIP_V:
+ overlayTransFlipHV(mdp, rot);
+ break;
+ case HAL_TRANSFORM_ROT_90:
+ case (HAL_TRANSFORM_ROT_90|HAL_TRANSFORM_FLIP_H):
+ case (HAL_TRANSFORM_ROT_90|HAL_TRANSFORM_FLIP_V):
+ overlayTransFlipRot90(mdp, rot);
+ break;
+ case HAL_TRANSFORM_ROT_180:
+ overlayTransFlipRot180(mdp);
+ break;
+ case HAL_TRANSFORM_ROT_270:
+ overlayTransFlipRot270(mdp);
+ break;
+ default:
+ ALOGE("%s: Error due to unknown rot value %d", __FUNCTION__, rot);
+ return false;
+ }
+
+ /* everything below is rotation related */
+ int r = utils::getMdpOrient(rot);
+ ALOGE_IF(DEBUG_OVERLAY, "%s: r=%d", __FUNCTION__, r);
+ if (r == -1) {
+ ALOGE("Ctrl setParameter rot it -1");
+ return false;
+ }
+
+ // Need to have both in sync
+ mdp.setUserData(r);
+ this->setRotations(r);
+ this->setDisable();
+ if(r) {
+ this->setEnable();
+ }
+
+ /* set src format using rotation info
+ * e.g. (12-->5 in case of rotation) */
+ mdp.setSrcFormat(this->getSrcWhf());
+
+ // based on 90/270 set flags
+ mdp.setRotationFlags();
+ return true;
+}
+
+void Rotator::overlayTransFlipHV(MdpCtrl& mdp,
+ utils::eTransform& rot)
+{
+ int val = mdp.getUserData();
+ ALOGE_IF(DEBUG_OVERLAY, "%s: prev=%d", __FUNCTION__, val);
+ utils::Dim d = mdp.getSrcRectDim();
+ utils::Whf whf = mdp.getSrcWhf();
+ if (val == MDP_ROT_90) {
+ int tmp = d.y;
+ d.y = compute(whf.w,
+ d.x,
+ d.w);
+ d.x = tmp;
+ mdp.setSrcRectDim(d);
+ utils::swapOVRotWidthHeight(mRot, mdp);
+ }
+ else if (val == MDP_ROT_270) {
+ int tmp = d.x;
+ d.x = compute(whf.h,
+ d.y,
+ d.h);
+ d.y = tmp;
+ mdp.setSrcRectDim(d);
+ utils::swapOVRotWidthHeight(mRot, mdp);
+ }
+}
+
+void Rotator::overlayTransFlipRot90(MdpCtrl& mdp,
+ utils::eTransform& rot)
+{
+ int val = mdp.getUserData();
+ ALOGE_IF(DEBUG_OVERLAY, "%s: prev=%d", __FUNCTION__, val);
+ utils::Dim d = mdp.getSrcRectDim();
+ utils::Whf whf = mdp.getSrcWhf();
+ if (val == MDP_ROT_270) {
+ d.x = compute(whf.w,
+ d.x,
+ d.w);
+ d.y = compute(whf.h,
+ d.y,
+ d.h);
+ }
+ else if (val == MDP_ROT_NOP || val == MDP_ROT_180) {
+ int tmp = d.x;
+ d.x = compute(whf.h,
+ d.y,
+ d.h);
+ d.y = tmp;
+ mdp.setSrcRectDim(d);
+ utils::swapOVRotWidthHeight(mRot, mdp);
+ }
+}
+
+void Rotator::overlayTransFlipRot180(MdpCtrl& mdp)
+{
+ int val = mdp.getUserData();
+ ALOGE_IF(DEBUG_OVERLAY, "%s: prev=%d", __FUNCTION__, val);
+ utils::Dim d = mdp.getSrcRectDim();
+ utils::Whf whf = mdp.getSrcWhf();
+ if (val == MDP_ROT_270) {
+ int tmp = d.y;
+ d.y = compute(whf.w,
+ d.x,
+ d.w);
+ d.x = tmp;
+ mdp.setSrcRectDim(d);
+ utils::swapOVRotWidthHeight(mRot, mdp);
+ }
+ else if (val == MDP_ROT_90) {
+ int tmp = d.x;
+ d.x = compute(whf.h,
+ d.y,
+ d.h);
+ d.y = tmp;
+ mdp.setSrcRectDim(d);
+ utils::swapOVRotWidthHeight(mRot, mdp);
+ }
+}
+
+void Rotator::overlayTransFlipRot270(MdpCtrl& mdp)
+{
+ int val = mdp.getUserData();
+ ALOGE_IF(DEBUG_OVERLAY, "%s: prev=%d", __FUNCTION__, val);
+ utils::Dim d = mdp.getSrcRectDim();
+ utils::Whf whf = mdp.getSrcWhf();
+ if (val == MDP_ROT_90) {
+ d.y = compute(whf.h,
+ d.y,
+ d.h);
+ d.x = compute(whf.w,
+ d.x,
+ d.w);
+ }
+ else if (val == MDP_ROT_NOP || val == MDP_ROT_180) {
+ int tmp = d.y;
+ d.y = compute(whf.w,
+ d.x,
+ d.w);
+ d.x = tmp;
+ mdp.setSrcRectDim(d);
+ utils::swapOVRotWidthHeight(mRot, mdp);
+ }
+}
+
+void MdpRot::dump() const {
+ ALOGE("== Dump MdpRot start ==");
+ mFd.dump();
+ mMem.curr().m.dump();
+ mdp_wrapper::dump("mRotImgInfo", mRotImgInfo);
+ mdp_wrapper::dump("mRotDataInfo", mRotDataInfo);
+ mdp_wrapper::dump("mData", mData);
+ ALOGE("== Dump MdpRot end ==");
+}
+}
diff --git a/liboverlay/overlayRotator.h b/liboverlay/overlayRotator.h
new file mode 100644
index 0000000..39c4f0c
--- /dev/null
+++ b/liboverlay/overlayRotator.h
@@ -0,0 +1,554 @@
+/*
+* Copyright (c) 2011-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 OVERLAY_ROTATOR_H
+#define OVERLAY_ROTATOR_H
+
+#include <stdlib.h>
+
+#include "mdpWrapper.h"
+#include "overlayUtils.h"
+#include "overlayMem.h"
+
+namespace overlay {
+ class MdpCtrl;
+/*
+* MDP rot holds MDP's rotation related structures.
+*
+* */
+class MdpRot {
+public:
+ /* ctor */
+ explicit MdpRot();
+
+ /* open fd for rotator. map bufs is defered */
+ bool open();
+
+ /* remap rot buffers */
+ bool remap(uint32_t numbufs, const utils::PipeArgs& args);
+
+ /* Unmap everything that is not current */
+ bool unmapNonCurrent();
+
+ /* close fd, mem */
+ bool close();
+
+ /* reset underlying data, basically memset 0 */
+ void reset();
+
+ /* calls underlying wrappers to start rotator */
+ bool start();
+
+ /* start underlying but use given whf and flags */
+ bool start(const utils::PipeArgs& args);
+
+ /* start underlying but use given whf and flags.
+ * Has the ability to parameterize the dst fmt */
+ template <int ROT_OUT_FMT>
+ bool start(const utils::PipeArgs& args);
+
+ /* assign memory id to mdp structure */
+ void setDataMemId(int fd);
+ void setRotDataSrcMemId(int fd);
+
+ /* Mark src as FB (non-ION) */
+ void setSrcFB(bool);
+
+ /* get dst (for offset and memory id) non-virt */
+ int getDstMemId() const;
+ uint32_t getDstOffset() const;
+
+ /* set enable/disable flag */
+ void setEnable();
+ void setDisable();
+ bool enabled() const;
+
+ /* set rotator flag*/
+ void setRotations(uint32_t r);
+
+ /* set the req data id in mData */
+ void setDataReqId(int id);
+
+ /* swap rot info dst w/h */
+ void swapDstWH();
+
+ /* returns a copy of src whf */
+ utils::Whf getSrcWhf() const;
+
+ /* setup rotator data before queue buf calls
+ * call play if rotate call succeed. return false if failed */
+ bool prepareQueueBuf(uint32_t offset);
+
+ /* call play on mdp*/
+ bool play(int fd);
+
+ /* set src whf */
+ void setSrcWhf(const utils::Whf& whf);
+
+ /* returns rotator session id */
+ int getSessId() const;
+
+ /* dump the state of the object */
+ void dump() const;
+
+private:
+ bool open_i(uint32_t numbufs, uint32_t bufsz);
+
+ /* max buf no for offset */
+ enum { ROT_MAX_BUF_OFFSET = 2 };
+ /* rot info*/
+ msm_rotator_img_info mRotImgInfo;
+ /* rot data */
+ msm_rotator_data_info mRotDataInfo;
+ /* data needed for rotator */
+ msmfb_overlay_data mData;
+ /* rotator fd */
+ OvFD mFd;
+ /* Array of memory map for rotator
+ * The array enable us to change rot buffers/mapping
+ * on the fly*/
+ struct RotMem {
+ enum {MAX_ROT_MEM = 2};
+ struct Mem {
+ Mem() : mCurrOffset(0) {utils::memset0(mRotOffset); }
+ bool valid() { return m.valid(); }
+ bool close() { return m.close(); }
+ uint32_t size() const { return m.bufSz(); }
+ /* rotator data info dst offset */
+ uint32_t mRotOffset[ROT_MAX_BUF_OFFSET];
+ /* current offset slot from mRotOffset */
+ uint32_t mCurrOffset;
+ OvMem m;
+ };
+ RotMem() : _curr(0) {}
+ Mem& curr() { return m[_curr % MAX_ROT_MEM]; }
+ const Mem& curr() const { return m[_curr % MAX_ROT_MEM]; }
+ Mem& prev() { return m[(_curr+1) % MAX_ROT_MEM]; }
+ RotMem& operator++() { ++_curr; return *this; }
+ bool close();
+ uint32_t _curr;
+ Mem m[MAX_ROT_MEM];
+ } mMem;
+ bool isSrcFB;
+};
+
+/*
+* RotatorBase. No memebers, just interface.
+* ~ can also be =0 with empty impl in cpp.
+* */
+class RotatorBase {
+public:
+ /* Most of the below are No op funcs for RotatorBase */
+ virtual ~RotatorBase() {}
+ virtual bool open() = 0;
+ virtual bool remap(uint32_t numbufs, const utils::PipeArgs& args) = 0;
+ virtual bool close() = 0;
+ virtual bool start(const utils::PipeArgs& args) = 0;
+ virtual bool start() = 0;
+ virtual mdp_overlay setInfo(const utils::PipeArgs& args,
+ const mdp_overlay& o) = 0;
+ virtual bool overlayTransform(MdpCtrl& mdp,
+ utils::eTransform& rot) = 0;
+ virtual void setSrcWhf(const utils::Whf& wfh) = 0;
+ virtual utils::Whf getSrcWhf() const = 0;
+ virtual void setRotations(uint32_t r) = 0;
+ virtual void setDataReqId(int id) = 0;
+ virtual bool prepareQueueBuf(uint32_t offset) = 0;
+ virtual bool play(int fd) = 0;
+ virtual void setEnable() = 0;
+ virtual void setDisable() = 0;
+ virtual bool enabled() const = 0;
+ virtual void setDataMemId(int fd) = 0;
+ virtual void setRotDataSrcMemId(int fd) = 0;
+ virtual void setSrcFB(bool) = 0;
+ virtual int getSessId() const = 0;
+ virtual void dump() const = 0;
+};
+
+/*
+* Null/Empty impl of RotatorBase
+* */
+class NullRotator : public RotatorBase {
+public:
+ /* Most of the below are No op funcs for RotatorBase */
+ virtual ~NullRotator();
+ virtual bool open();
+ virtual bool remap(uint32_t numbufs, const utils::PipeArgs& args);
+ virtual bool close();
+ virtual bool start(const utils::PipeArgs& args);
+ virtual bool start();
+ /* null rotator behavior should set info in a specific way */
+ virtual mdp_overlay setInfo(const utils::PipeArgs& args,
+ const mdp_overlay& o);
+ virtual bool overlayTransform(MdpCtrl& o,
+ utils::eTransform& rot);
+ virtual void setSrcWhf(const utils::Whf& wfh);
+ virtual utils::Whf getSrcWhf() const;
+ virtual void setRotations(uint32_t r);
+ virtual void setDataReqId(int id);
+ virtual bool prepareQueueBuf(uint32_t offset);
+ virtual bool play(int fd);
+ virtual void setEnable();
+ virtual void setDisable();
+ virtual bool enabled () const;
+ virtual void setDataMemId(int fd);
+ virtual void setRotDataSrcMemId(int fd);
+ virtual void setSrcFB(bool);
+ virtual int getSessId() const;
+ virtual void dump() const;
+};
+
+
+/*
+* Rotator impl.
+* */
+class Rotator : public RotatorBase
+{
+public:
+ /* construct underlying object */
+ explicit Rotator();
+
+ /* close underlying rot */
+ virtual ~Rotator();
+
+ /* calls underlying open */
+ virtual bool open();
+
+ /* remap rot buffers */
+ virtual bool remap(uint32_t numbufs, const utils::PipeArgs& args);
+
+ /* calls underlying close */
+ virtual bool close();
+
+ /* calls underlying start */
+ virtual bool start();
+
+ /* calls underlying start with whf and flags */
+ virtual bool start(const utils::PipeArgs& args);
+
+ /* non virtual - calls underlying start with whf and flags.
+ * Has the ability to parameterize the dst */
+ template <int ROT_OUT_FMT>
+ bool start(const utils::PipeArgs& args);
+
+ /* Unmap everything that is not current */
+ bool unmapNonCurrent();
+
+ /* set info using whf and given mdp */
+ virtual mdp_overlay setInfo(const utils::PipeArgs& args,
+ const mdp_overlay& o);
+
+ /* transform function for the MDP */
+ virtual bool overlayTransform(MdpCtrl& mdp,
+ utils::eTransform& rot);
+
+ /* set src whf */
+ virtual void setSrcWhf(const utils::Whf& wfh);
+
+ /* set Rotations */
+ virtual void setRotations(uint32_t r);
+
+ /* set the req data id in mData */
+ virtual void setDataReqId(int id);
+
+ /* set memory_id */
+ virtual void setDataMemId(int fd);
+ virtual void setRotDataSrcMemId(int fd);
+
+ /* Mark the src for rotator as FB. usually set by UI mirroing cases */
+ virtual void setSrcFB(bool);
+
+ /* get dst (for offset and memory id) non-virt */
+ int getDstMemId() const;
+ uint32_t getDstOffset() const;
+
+ /* set enable/disable flag */
+ virtual void setEnable();
+ virtual void setDisable();
+ virtual bool enabled () const;
+
+ /* return rotator sess id */
+ virtual int getSessId() const;
+
+ /* return a copy of src whf*/
+ virtual utils::Whf getSrcWhf() const;
+
+ /* prepare rot for queue buf*/
+ virtual bool prepareQueueBuf(uint32_t offset);
+
+ /* call play on mdp*/
+ virtual bool play(int fd);
+
+ /* dump the state of the object */
+ virtual void dump() const;
+private:
+ /* helper functions for overlayTransform */
+ void overlayTransFlipHV(MdpCtrl& mdp,
+ utils::eTransform& rot);
+ void overlayTransFlipRot90(MdpCtrl& mdp,
+ utils::eTransform& rot);
+ void overlayTransFlipRot180(MdpCtrl& mdp);
+ void overlayTransFlipRot270(MdpCtrl& mdp);
+
+ /* underlying rotator MDP object */
+ MdpRot mRot;
+};
+
+
+//--------------inlines------------------------------------
+//// MdpRot ////
+inline MdpRot::MdpRot() { reset(); }
+inline bool MdpRot::start(const utils::PipeArgs& args) {
+ return this->start<utils::ROT_OUT_FMT_DEFAULT>(args);
+}
+
+inline void MdpRot::setDataMemId(int fd) { mData.data.memory_id = fd; }
+inline void MdpRot::setRotDataSrcMemId(int fd) {
+ mRotDataInfo.src.memory_id = fd; }
+
+inline void MdpRot::setEnable() { mRotImgInfo.enable = 1; }
+inline void MdpRot::setDisable() { mRotImgInfo.enable = 0; }
+inline bool MdpRot::enabled() const { return mRotImgInfo.enable; }
+
+inline void MdpRot::setRotations(uint32_t r) { mRotImgInfo.rotations = r; }
+inline void MdpRot::setDataReqId(int id) { mData.id = id; }
+inline void MdpRot::swapDstWH() {
+ overlay::utils::swap(mRotImgInfo.dst.width,
+ mRotImgInfo.dst.height); }
+
+inline overlay::utils::Whf MdpRot::getSrcWhf() const {
+ return overlay::utils::Whf(mRotImgInfo.src.width,
+ mRotImgInfo.src.height,
+ mRotImgInfo.src.format);
+}
+
+inline int MdpRot::getDstMemId() const {
+ return mRotDataInfo.dst.memory_id;
+}
+inline uint32_t MdpRot::getDstOffset() const {
+ return mRotDataInfo.dst.offset;
+}
+
+inline void MdpRot::setSrcWhf(const overlay::utils::Whf& whf) {
+ mRotImgInfo.src.width = whf.w;
+ mRotImgInfo.src.height = whf.h;
+ mRotImgInfo.src.format = whf.format;
+}
+
+inline int MdpRot::getSessId() const { return mRotImgInfo.session_id; }
+
+inline void MdpRot::setSrcFB(bool mark) { isSrcFB = mark; }
+
+///// Null Rotator /////
+inline NullRotator::~NullRotator() {}
+inline bool NullRotator::open() {
+ return true; }
+inline bool NullRotator::remap(uint32_t numbufs,
+ const utils::PipeArgs& args){
+ return true; }
+inline bool NullRotator::close() { return true; }
+inline bool NullRotator::start(const utils::PipeArgs& args)
+{ return true; }
+
+inline bool NullRotator::start() { return true; }
+inline bool NullRotator::overlayTransform(MdpCtrl& o,
+ utils::eTransform& rot)
+{ return true; }
+inline void NullRotator::setSrcWhf(const overlay::utils::Whf& wfh) {}
+inline void NullRotator::setRotations(uint32_t) {}
+inline void NullRotator::setDataReqId(int id) {}
+inline void NullRotator::setEnable() {}
+inline void NullRotator::setDisable() {}
+inline bool NullRotator::enabled() const { return false; }
+inline int NullRotator::getSessId() const { return -1; }
+inline overlay::utils::Whf NullRotator::getSrcWhf() const {
+ return overlay::utils::Whf(); }
+inline bool NullRotator::prepareQueueBuf(uint32_t offset)
+{ return true; }
+inline bool NullRotator::play(int fd)
+{ return true; }
+inline void NullRotator::setDataMemId(int fd) {}
+inline void NullRotator::setRotDataSrcMemId(int fd) {}
+inline void NullRotator::setSrcFB(bool) {}
+inline void NullRotator::dump() const {
+ ALOGE("== Dump NullRotator dump (null) start/end ==");
+}
+
+///// Rotator /////
+inline Rotator::Rotator() { }
+
+inline Rotator::~Rotator() {
+ mRot.close(); // also will do reset
+}
+
+inline bool Rotator::open() {
+ if(!mRot.open()) {
+ ALOGE("Rotator::open failed");
+ return false;
+ }
+ return true;
+}
+
+template <int ROT_OUT_FMT>
+inline bool Rotator::start(const utils::PipeArgs& args) {
+ return mRot.start<ROT_OUT_FMT>(args);
+}
+
+inline bool Rotator::remap(uint32_t numbufs,
+ const utils::PipeArgs& args){
+ if(!mRot.remap(numbufs, args)) {
+ ALOGE("%s failed", __FUNCTION__);
+ return false;
+ }
+ return true;
+}
+
+inline bool Rotator::close() {
+ return mRot.close();
+}
+
+inline bool Rotator::start() {
+ return mRot.start();
+}
+
+inline bool Rotator::start(const utils::PipeArgs& args) {
+ return mRot.start(args);
+}
+
+inline bool Rotator::unmapNonCurrent() {
+ return mRot.unmapNonCurrent();
+}
+
+inline void Rotator::setEnable(){ mRot.setEnable(); }
+inline void Rotator::setDisable(){ mRot.setDisable(); }
+inline bool Rotator::enabled() const { return mRot.enabled(); }
+inline void Rotator::setDataMemId(int fd) {
+ mRot.setDataMemId(fd); }
+
+inline void Rotator::setRotDataSrcMemId(int fd) {
+ mRot.setRotDataSrcMemId(fd);
+}
+
+inline void Rotator::setSrcFB(bool mark) { mRot.setSrcFB(mark); }
+
+inline int Rotator::getDstMemId() const {
+ return mRot.getDstMemId();
+}
+inline uint32_t Rotator::getDstOffset() const {
+ return mRot.getDstOffset();
+}
+
+inline void Rotator::setDataReqId(int id) {
+ mRot.setDataReqId(id);
+}
+
+inline void Rotator::setSrcWhf(
+ const overlay::utils::Whf& whf) {
+ mRot.setSrcWhf(whf);
+}
+
+inline void Rotator::setRotations(uint32_t rot) {
+ mRot.setRotations (rot);
+}
+
+inline int Rotator::getSessId() const {
+ return mRot.getSessId(); }
+
+inline void Rotator::dump() const {
+ ALOGE("== Dump Rotator start ==");
+ mRot.dump();
+ ALOGE("== Dump Rotator end ==");
+}
+
+inline overlay::utils::Whf Rotator::getSrcWhf() const {
+ return mRot.getSrcWhf(); }
+
+inline bool Rotator::prepareQueueBuf(uint32_t offset)
+{
+ return mRot.prepareQueueBuf(offset);
+}
+
+inline bool Rotator::play(int fd)
+{
+ return mRot.play(fd);
+}
+
+template <int ROT_OUT_FMT>
+bool MdpRot::start(const utils::PipeArgs& args) {
+ // Do nothing when no orientation
+ if(utils::OVERLAY_TRANSFORM_0 == args.orientation &&
+ utils::ROT_FLAG_ENABLED != args.rotFlags) {
+ return true;
+ }
+ utils::Whf whf(args.whf);
+ mRotImgInfo.src.format = whf.format;
+ mRotImgInfo.src.width = whf.w;
+ mRotImgInfo.src.height = whf.h;
+ mRotImgInfo.src_rect.w = whf.w;
+ mRotImgInfo.src_rect.h = whf.h;
+ mRotImgInfo.dst.width = whf.w;
+ mRotImgInfo.dst.height = whf.h;
+ if(whf.format == MDP_Y_CRCB_H2V2_TILE ||
+ whf.format == MDP_Y_CBCR_H2V2_TILE) {
+ mRotImgInfo.src.width = utils::alignup(whf.w, 64);
+ mRotImgInfo.src.height = utils::alignup(whf.h, 32);
+ mRotImgInfo.src_rect.w = utils::alignup(whf.w, 64);
+ mRotImgInfo.src_rect.h = utils::alignup(whf.h, 32);
+ mRotImgInfo.dst.width = utils::alignup(whf.w, 64);
+ mRotImgInfo.dst.height = utils::alignup(whf.h, 32);
+ mRotImgInfo.dst.format = MDP_Y_CRCB_H2V2;
+ }
+ // either utils::getRotOutFmt(whf.format); or supplied fmt
+ // utils::RotOutFmt<ROT_OUT_FMT_DEFAULT>::fmt;
+ mRotImgInfo.dst.format = utils::RotOutFmt<ROT_OUT_FMT>::fmt(whf.format);
+ mRotImgInfo.dst_x = 0;
+ mRotImgInfo.dst_y = 0;
+ mRotImgInfo.src_rect.x = 0;
+ mRotImgInfo.src_rect.y = 0;
+ mRotImgInfo.rotations = 0;
+ // ROT_FLAG_DISABLED / ENABLED
+ // Refer to overlayUtils.h eRotFlags
+ // for more info
+ mRotImgInfo.enable = args.rotFlags;
+ mRotImgInfo.session_id = mRotImgInfo.session_id ?
+ mRotImgInfo.session_id : 0;
+
+ return start();
+}
+
+} // overlay
+
+namespace {
+// just a helper func for Rotator common operations x-(y+z)
+int compute(uint32_t x, uint32_t y, uint32_t z) {
+ return x-(y+z);
+}
+}
+
+#endif // OVERLAY_ROTATOR_H
diff --git a/liboverlay/overlayState.h b/liboverlay/overlayState.h
new file mode 100644
index 0000000..1d13a2e
--- /dev/null
+++ b/liboverlay/overlayState.h
@@ -0,0 +1,907 @@
+/*
+* Copyright (c) 2011-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 OVERLAY_STATE_H
+#define OVERLAY_STATE_H
+
+#include "overlayUtils.h"
+#include "overlayImpl.h"
+#include "overlayRotator.h"
+#include "pipes/overlayGenPipe.h"
+#include "pipes/overlayBypassPipe.h"
+#include "pipes/overlayHdmiPipe.h"
+#include "pipes/overlayUIMirrorPipe.h"
+#include "pipes/overlay3DPipe.h"
+
+// FIXME make int to be uint32 whenever possible
+
+namespace overlay {
+
+/*
+* Used by Overlay class. Invokes each event
+* */
+
+/* TODO case of RGBx will call mOv open with diff
+* params customized for RGBx pipes */
+
+class OverlayState : utils::NoCopy {
+public:
+ /**/
+ explicit OverlayState();
+
+ /**/
+ ~OverlayState();
+
+ /* return current state */
+ utils::eOverlayState state() const;
+
+ /* Overlay Event */
+
+ /* Hard reset to a new state. If the state is the same
+ * as the current one, it would be a no-op */
+ OverlayImplBase* reset(utils::eOverlayState s);
+
+ /* Caller pass the state to the handleEvent function.
+ * The input is the current OverlayImplBase*, and output is
+ * a pointer to (possibly new) instance of OverlayImplBase
+ * The eFormat can be 2D/3D etc. */
+ OverlayImplBase* handleEvent(utils::eOverlayState s,
+ OverlayImplBase* ov);
+
+ /* Transitions from XXX to XXX */
+ OverlayImplBase* handle_closed(utils::eOverlayState s);
+ OverlayImplBase* handle_2D_2DPanel(utils::eOverlayState s,
+ OverlayImplBase* ov);
+ OverlayImplBase* handle_2D_2DTV(utils::eOverlayState s,
+ OverlayImplBase* ov);
+ OverlayImplBase* handle_3D_2DPanel(utils::eOverlayState s,
+ OverlayImplBase* ov);
+ OverlayImplBase* handle_3D_3DPanel(utils::eOverlayState s,
+ OverlayImplBase* ov);
+ OverlayImplBase* handle_3D_3DTV(utils::eOverlayState s,
+ OverlayImplBase* ov);
+ OverlayImplBase* handle_3D_2DTV(utils::eOverlayState s,
+ OverlayImplBase* ov);
+ OverlayImplBase* handle_UI_Mirror(utils::eOverlayState s,
+ OverlayImplBase* ov);
+ OverlayImplBase* handle_2D_trueUI_Mirror(utils::eOverlayState s,
+ OverlayImplBase* ov);
+ OverlayImplBase* handle_bypass(utils::eOverlayState s,
+ OverlayImplBase* ov);
+
+ /* Transition from any state to 2D video on 2D panel */
+ OverlayImplBase* handle_xxx_to_2D_2DPanel(OverlayImplBase* ov);
+
+ /* Transition from any state to 2D video on 2D panel and 2D TV */
+ OverlayImplBase* handle_xxx_to_2D_2DTV(OverlayImplBase* ov);
+
+ /* Transition from any state to 3D video on 2D panel */
+ OverlayImplBase* handle_xxx_to_3D_2DPanel(OverlayImplBase* ov);
+
+ /* Transition from any state to 3D video on 2D panel and 2D TV */
+ OverlayImplBase* handle_xxx_to_3D_2DTV(OverlayImplBase* ov);
+
+ /* Transition from any state to 2D video true UI mirroring (2D video + UI) */
+ OverlayImplBase* handle_xxx_to_2D_trueUI_Mirror(OverlayImplBase* ov);
+
+ /* Transitions from any state to 1 layer composition bypass */
+ OverlayImplBase* handle_xxx_to_bypass1(OverlayImplBase* ov);
+
+ /* Transitions from any state to 2 layers composition bypass */
+ OverlayImplBase* handle_xxx_to_bypass2(OverlayImplBase* ov);
+
+ /* Transitions from any state to 3 layers composition bypass */
+ OverlayImplBase* handle_xxx_to_bypass3(OverlayImplBase* ov);
+
+ /* Dump */
+ void dump() const;
+private:
+ /* States here */
+ utils::eOverlayState mState;
+};
+
+//------------------------State Traits --------------------------
+
+// primary has nothing
+template <int STATE> struct StateTraits {};
+
+/*
+ * For 3D_xxx we need channel ID besides the FBx since
+ * get crop/position 3D need that to determine pos/crop
+ * info.
+ * */
+
+template <> struct StateTraits<utils::OV_2D_VIDEO_ON_PANEL>
+{
+ typedef overlay::GenericPipe<utils::PRIMARY> pipe0;
+ typedef overlay::NullPipe pipe1; // place holder
+ typedef overlay::NullPipe pipe2; // place holder
+
+ typedef Rotator rot0;
+ typedef NullRotator rot1;
+ typedef NullRotator rot2;
+
+ typedef overlay::OverlayImpl<pipe0> ovimpl;
+};
+
+template <> struct StateTraits<utils::OV_2D_VIDEO_ON_PANEL_TV>
+{
+ typedef overlay::GenericPipe<utils::PRIMARY> pipe0;
+ typedef overlay::HdmiPipe pipe1;
+ typedef overlay::NullPipe pipe2; // place holder
+
+ typedef Rotator rot0;
+ typedef NullRotator rot1;
+ typedef NullRotator rot2;
+
+ typedef overlay::OverlayImpl<pipe0, pipe1> ovimpl;
+};
+
+template <> struct StateTraits<utils::OV_3D_VIDEO_ON_2D_PANEL>
+{
+ typedef overlay::M3DPrimaryPipe<utils::OV_PIPE0> pipe0;
+ typedef overlay::NullPipe pipe1; // place holder
+ typedef overlay::NullPipe pipe2; // place holder
+
+ typedef Rotator rot0;
+ typedef NullRotator rot1;
+ typedef NullRotator rot2;
+
+ typedef overlay::OverlayImpl<pipe0> ovimpl;
+};
+
+template <> struct StateTraits<utils::OV_3D_VIDEO_ON_3D_PANEL>
+{
+ typedef overlay::S3DPrimaryPipe<utils::OV_PIPE0> pipe0;
+ typedef overlay::S3DPrimaryPipe<utils::OV_PIPE1> pipe1;
+ typedef overlay::NullPipe pipe2; // place holder
+
+ typedef Rotator rot0;
+ typedef Rotator rot1;
+ typedef NullRotator rot2;
+
+ typedef overlay::OverlayImpl<pipe0, pipe1> ovimpl;
+};
+
+template <> struct StateTraits<utils::OV_3D_VIDEO_ON_3D_TV>
+{
+ typedef overlay::S3DExtPipe<utils::OV_PIPE0> pipe0;
+ typedef overlay::S3DExtPipe<utils::OV_PIPE1> pipe1;
+ typedef overlay::NullPipe pipe2; // place holder
+
+ typedef NullRotator rot0;
+ typedef NullRotator rot1;
+ typedef NullRotator rot2;
+
+ typedef overlay::OverlayImpl<pipe0, pipe1> ovimpl;
+};
+
+template <> struct StateTraits<utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV>
+{
+ typedef overlay::M3DPrimaryPipe<utils::OV_PIPE0> pipe0;
+ typedef overlay::M3DExtPipe<utils::OV_PIPE1> pipe1;
+ typedef overlay::NullPipe pipe2; // place holder
+
+ typedef Rotator rot0;
+ typedef NullRotator rot1;
+ typedef NullRotator rot2;
+
+ typedef overlay::OverlayImpl<pipe0, pipe1> ovimpl;
+};
+
+template <> struct StateTraits<utils::OV_UI_MIRROR>
+{
+ typedef overlay::UIMirrorPipe pipe0;
+ typedef overlay::NullPipe pipe1; // place holder
+ typedef overlay::NullPipe pipe2; // place holder
+
+ typedef Rotator rot0;
+ typedef NullRotator rot1;
+ typedef NullRotator rot2;
+
+ typedef overlay::OverlayImpl<pipe0> ovimpl;
+};
+
+template <> struct StateTraits<utils::OV_2D_TRUE_UI_MIRROR>
+{
+ typedef overlay::GenericPipe<utils::PRIMARY> pipe0;
+ typedef overlay::HdmiPipe pipe1;
+ typedef overlay::UIMirrorPipe pipe2;
+
+ typedef Rotator rot0;
+ typedef NullRotator rot1;
+ typedef Rotator rot2;
+
+ typedef overlay::OverlayImpl<pipe0, pipe1, pipe2> ovimpl;
+};
+
+template <> struct StateTraits<utils::OV_BYPASS_1_LAYER>
+{
+ typedef overlay::BypassPipe<utils::OV_MDP_PIPE_VG, utils::IS_FG_SET, utils::WAIT, utils::ZORDER_0> pipe0;
+ typedef overlay::NullPipe pipe1; // place holder
+ typedef overlay::NullPipe pipe2; // place holder
+
+ typedef NullRotator rot0;
+ typedef NullRotator rot1;
+ typedef NullRotator rot2;
+
+ typedef overlay::OverlayImpl<pipe0> ovimpl;
+};
+
+template <> struct StateTraits<utils::OV_BYPASS_2_LAYER>
+{
+ typedef overlay::BypassPipe<utils::OV_MDP_PIPE_VG, utils::IS_FG_SET, utils::NO_WAIT, utils::ZORDER_0> pipe0;
+ typedef overlay::BypassPipe<utils::OV_MDP_PIPE_VG, utils::IS_FG_OFF, utils::WAIT, utils::ZORDER_1> pipe1;
+ typedef overlay::NullPipe pipe2; // place holder
+
+ typedef NullRotator rot0;
+ typedef NullRotator rot1;
+ typedef NullRotator rot2;
+
+ typedef overlay::OverlayImpl<pipe0, pipe1> ovimpl;
+};
+
+template <> struct StateTraits<utils::OV_BYPASS_3_LAYER>
+{
+ typedef overlay::BypassPipe<utils::OV_MDP_PIPE_VG, utils::IS_FG_SET, utils::NO_WAIT, utils::ZORDER_0> pipe0;
+ typedef overlay::BypassPipe<utils::OV_MDP_PIPE_VG, utils::IS_FG_OFF, utils::NO_WAIT, utils::ZORDER_1> pipe1;
+ typedef overlay::BypassPipe<utils::OV_MDP_PIPE_RGB, utils::IS_FG_OFF, utils::WAIT, utils::ZORDER_2> pipe2;
+
+ typedef NullRotator rot0;
+ typedef NullRotator rot1;
+ typedef NullRotator rot2;
+
+ typedef overlay::OverlayImpl<pipe0, pipe1, pipe2> ovimpl;
+};
+
+
+//------------------------Inlines --------------------------------
+
+inline OverlayState::OverlayState() : mState(utils::OV_CLOSED)
+{}
+
+inline OverlayState::~OverlayState() {}
+
+inline utils::eOverlayState OverlayState::state() const
+{
+ return mState;
+}
+
+inline OverlayImplBase* OverlayState::reset(utils::eOverlayState s)
+{
+ return handleEvent(s, 0);
+}
+
+inline void OverlayState::dump() const
+{
+ ALOGE("== Dump state %d start/end ==", mState);
+}
+
+template <int STATE>
+inline OverlayImplBase* handle_closed_to_xxx()
+{
+ OverlayImplBase* ov = new typename StateTraits<STATE>::ovimpl;
+ RotatorBase* rot0 = new typename StateTraits<STATE>::rot0;
+ RotatorBase* rot1 = new typename StateTraits<STATE>::rot1;
+ RotatorBase* rot2 = new typename StateTraits<STATE>::rot2;
+ if(!ov->open(rot0, rot1, rot2)) {
+ ALOGE("Overlay failed to open in state %d", STATE);
+ return 0;
+ }
+ return ov;
+}
+
+inline OverlayImplBase* handle_xxx_to_closed(OverlayImplBase* ov)
+{
+ OVASSERT(ov, "%s: ov is null", __FUNCTION__);
+
+ if(!ov->close()) {
+ ALOGE("%s: Failed to ov close", __FUNCTION__);
+ }
+ delete ov;
+ ov = 0;
+ return 0;
+}
+
+/* Hard transitions from any state to any state will close and then open */
+template <int STATE>
+inline OverlayImplBase* handle_xxx_to_xxx(OverlayImplBase* ov)
+{
+ OVASSERT(ov, "%s: ov is null", __FUNCTION__);
+
+ handle_xxx_to_closed(ov);
+ return handle_closed_to_xxx<STATE>();
+}
+
+inline OverlayImplBase* OverlayState::handleEvent(utils::eOverlayState newState,
+ OverlayImplBase* ov)
+{
+ OverlayImplBase* newov = ov; // at least, we return the same
+ if (mState != newState) {
+ ALOGE_IF(DEBUG_OVERLAY, "%s: state changed %s-->%s",
+ __FUNCTION__, getStateString(mState), getStateString(newState));
+ } else {
+ ALOGE_IF(DEBUG_OVERLAY, "%s: no state change, state=%s",
+ __FUNCTION__, getStateString(newState));
+ return newov;
+ }
+
+ switch(mState)
+ {
+ case utils::OV_CLOSED:
+ newov = handle_closed(newState);
+ break;
+ case utils::OV_2D_VIDEO_ON_PANEL:
+ newov = handle_2D_2DPanel(newState, ov);
+ break;
+ case utils::OV_2D_VIDEO_ON_PANEL_TV:
+ newov = handle_2D_2DTV(newState, ov);
+ break;
+ case utils::OV_3D_VIDEO_ON_2D_PANEL:
+ newov = handle_3D_2DPanel(newState, ov);
+ break;
+ case utils::OV_3D_VIDEO_ON_3D_PANEL:
+ newov = handle_3D_3DPanel(newState, ov);
+ break;
+ case utils::OV_3D_VIDEO_ON_3D_TV:
+ newov = handle_3D_3DTV(newState, ov);
+ break;
+ case utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV:
+ newov = handle_3D_2DTV(newState, ov);
+ break;
+ case utils::OV_UI_MIRROR:
+ newov = handle_UI_Mirror(newState, ov);
+ break;
+ case utils::OV_2D_TRUE_UI_MIRROR:
+ newov = handle_2D_trueUI_Mirror(newState, ov);
+ break;
+ case utils::OV_BYPASS_1_LAYER:
+ case utils::OV_BYPASS_2_LAYER:
+ case utils::OV_BYPASS_3_LAYER:
+ newov = handle_bypass(newState, ov);
+ break;
+ default:
+ ALOGE("%s: unknown state=%d", __FUNCTION__, mState);
+ }
+
+ // FIXME, how to communicate bad transition?
+ // Should we have bool returned from transition func?
+
+ return newov;
+}
+
+// Transitions from closed to XXX
+inline OverlayImplBase* OverlayState::handle_closed(utils::eOverlayState s)
+{
+ OverlayImplBase* ov = 0;
+ switch(s)
+ {
+ case utils::OV_CLOSED:
+ // no state change
+ break;
+ case utils::OV_2D_VIDEO_ON_PANEL:
+ ov = handle_closed_to_xxx<utils::OV_2D_VIDEO_ON_PANEL>();
+ break;
+ case utils::OV_2D_VIDEO_ON_PANEL_TV:
+ ov = handle_closed_to_xxx<utils::OV_2D_VIDEO_ON_PANEL_TV>();
+ break;
+ case utils::OV_3D_VIDEO_ON_2D_PANEL:
+ ov = handle_closed_to_xxx<utils::OV_3D_VIDEO_ON_2D_PANEL>();
+ break;
+ case utils::OV_3D_VIDEO_ON_3D_PANEL:
+ ov = handle_closed_to_xxx<utils::OV_3D_VIDEO_ON_3D_PANEL>();
+ break;
+ case utils::OV_3D_VIDEO_ON_3D_TV:
+ ov = handle_closed_to_xxx<utils::OV_3D_VIDEO_ON_3D_TV>();
+ break;
+ case utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV:
+ ov = handle_closed_to_xxx<utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV>();
+ break;
+ case utils::OV_UI_MIRROR:
+ ov = handle_closed_to_xxx<utils::OV_UI_MIRROR>();
+ break;
+ case utils::OV_2D_TRUE_UI_MIRROR:
+ ov = handle_closed_to_xxx<utils::OV_2D_TRUE_UI_MIRROR>();
+ break;
+ case utils::OV_BYPASS_1_LAYER:
+ ov = handle_closed_to_xxx<utils::OV_BYPASS_1_LAYER>();
+ break;
+ case utils::OV_BYPASS_2_LAYER:
+ ov = handle_closed_to_xxx<utils::OV_BYPASS_2_LAYER>();
+ break;
+ case utils::OV_BYPASS_3_LAYER:
+ ov = handle_closed_to_xxx<utils::OV_BYPASS_3_LAYER>();
+ break;
+ default:
+ ALOGE("%s: unknown state=%d", __FUNCTION__, s);
+ }
+ mState = s;
+ return ov;
+}
+
+// Transitions from 2D video on 2D panel to XXX
+inline OverlayImplBase* OverlayState::handle_2D_2DPanel(
+ utils::eOverlayState s,
+ OverlayImplBase* ov)
+{
+ OverlayImplBase* newov = ov;
+ switch(s)
+ {
+ case utils::OV_CLOSED:
+ newov = handle_xxx_to_closed(ov);
+ break;
+ case utils::OV_2D_VIDEO_ON_PANEL:
+ // no state change
+ break;
+ case utils::OV_2D_VIDEO_ON_PANEL_TV:
+ newov = handle_xxx_to_2D_2DTV(ov);
+ break;
+ case utils::OV_3D_VIDEO_ON_2D_PANEL:
+ newov = handle_xxx_to_xxx<utils::OV_3D_VIDEO_ON_2D_PANEL>(ov);
+ break;
+ case utils::OV_3D_VIDEO_ON_3D_PANEL:
+ newov = handle_xxx_to_xxx<utils::OV_3D_VIDEO_ON_3D_PANEL>(ov);
+ break;
+ case utils::OV_3D_VIDEO_ON_3D_TV:
+ newov = handle_xxx_to_xxx<utils::OV_3D_VIDEO_ON_3D_TV>(ov);
+ break;
+ case utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV:
+ newov = handle_xxx_to_xxx<utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV>(ov);
+ break;
+ case utils::OV_UI_MIRROR:
+ newov = handle_xxx_to_xxx<utils::OV_UI_MIRROR>(ov);
+ break;
+ case utils::OV_2D_TRUE_UI_MIRROR:
+ newov = handle_xxx_to_2D_trueUI_Mirror(ov);
+ break;
+ case utils::OV_BYPASS_1_LAYER:
+ newov = handle_xxx_to_xxx<utils::OV_BYPASS_1_LAYER>(ov);
+ break;
+ case utils::OV_BYPASS_2_LAYER:
+ newov = handle_xxx_to_xxx<utils::OV_BYPASS_2_LAYER>(ov);
+ break;
+ case utils::OV_BYPASS_3_LAYER:
+ newov = handle_xxx_to_xxx<utils::OV_BYPASS_3_LAYER>(ov);
+ break;
+ default:
+ ALOGE("%s: unknown state=%d", __FUNCTION__, s);
+ }
+ mState = s;
+ return newov;
+}
+
+// Transitions from 2D video on 2D panel and 2D TV to XXX
+inline OverlayImplBase* OverlayState::handle_2D_2DTV(
+ utils::eOverlayState s,
+ OverlayImplBase* ov)
+{
+ OverlayImplBase* newov = ov;
+ switch(s)
+ {
+ case utils::OV_CLOSED:
+ newov = handle_xxx_to_closed(ov);
+ break;
+ case utils::OV_2D_VIDEO_ON_PANEL:
+ newov = handle_xxx_to_2D_2DPanel(ov);
+ break;
+ case utils::OV_2D_VIDEO_ON_PANEL_TV:
+ // no state change
+ break;
+ case utils::OV_3D_VIDEO_ON_2D_PANEL:
+ newov = handle_xxx_to_xxx<utils::OV_3D_VIDEO_ON_2D_PANEL>(ov);
+ break;
+ case utils::OV_3D_VIDEO_ON_3D_PANEL:
+ newov = handle_xxx_to_xxx<utils::OV_3D_VIDEO_ON_3D_PANEL>(ov);
+ break;
+ case utils::OV_3D_VIDEO_ON_3D_TV:
+ newov = handle_xxx_to_xxx<utils::OV_3D_VIDEO_ON_3D_TV>(ov);
+ break;
+ case utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV:
+ newov = handle_xxx_to_xxx<utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV>(ov);
+ break;
+ case utils::OV_UI_MIRROR:
+ newov = handle_xxx_to_xxx<utils::OV_UI_MIRROR>(ov);
+ break;
+ case utils::OV_2D_TRUE_UI_MIRROR:
+ newov = handle_xxx_to_2D_trueUI_Mirror(ov);
+ break;
+ case utils::OV_BYPASS_1_LAYER:
+ newov = handle_xxx_to_xxx<utils::OV_BYPASS_1_LAYER>(ov);
+ break;
+ case utils::OV_BYPASS_2_LAYER:
+ newov = handle_xxx_to_xxx<utils::OV_BYPASS_2_LAYER>(ov);
+ break;
+ case utils::OV_BYPASS_3_LAYER:
+ newov = handle_xxx_to_xxx<utils::OV_BYPASS_3_LAYER>(ov);
+ break;
+ default:
+ ALOGE("%s: unknown state=%d", __FUNCTION__, s);
+ }
+ mState = s;
+ return newov;
+}
+
+// Transitions from 3D video on 2D panel to XXX
+inline OverlayImplBase* OverlayState::handle_3D_2DPanel(
+ utils::eOverlayState s,
+ OverlayImplBase* ov)
+{
+ OverlayImplBase* newov = ov;
+ switch(s)
+ {
+ case utils::OV_CLOSED:
+ newov = handle_xxx_to_closed(ov);
+ break;
+ case utils::OV_2D_VIDEO_ON_PANEL:
+ newov = handle_xxx_to_xxx<utils::OV_2D_VIDEO_ON_PANEL>(ov);
+ break;
+ case utils::OV_2D_VIDEO_ON_PANEL_TV:
+ newov = handle_xxx_to_xxx<utils::OV_2D_VIDEO_ON_PANEL_TV>(ov);
+ break;
+ case utils::OV_3D_VIDEO_ON_2D_PANEL:
+ // no state change
+ break;
+ case utils::OV_3D_VIDEO_ON_3D_PANEL:
+ newov = handle_xxx_to_xxx<utils::OV_3D_VIDEO_ON_3D_PANEL>(ov);
+ break;
+ case utils::OV_3D_VIDEO_ON_3D_TV:
+ newov = handle_xxx_to_xxx<utils::OV_3D_VIDEO_ON_3D_TV>(ov);
+ break;
+ case utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV:
+ newov = handle_xxx_to_3D_2DTV(ov);
+ break;
+ case utils::OV_UI_MIRROR:
+ newov = handle_xxx_to_xxx<utils::OV_UI_MIRROR>(ov);
+ break;
+ case utils::OV_2D_TRUE_UI_MIRROR:
+ newov = handle_xxx_to_xxx<utils::OV_2D_TRUE_UI_MIRROR>(ov);
+ break;
+ case utils::OV_BYPASS_1_LAYER:
+ newov = handle_xxx_to_xxx<utils::OV_BYPASS_1_LAYER>(ov);
+ break;
+ case utils::OV_BYPASS_2_LAYER:
+ newov = handle_xxx_to_xxx<utils::OV_BYPASS_2_LAYER>(ov);
+ break;
+ case utils::OV_BYPASS_3_LAYER:
+ newov = handle_xxx_to_xxx<utils::OV_BYPASS_3_LAYER>(ov);
+ break;
+ default:
+ ALOGE("%s: unknown state=%d", __FUNCTION__, s);
+ }
+ mState = s;
+ return newov;
+}
+
+// Transitions from 3D video on 3D panel to XXX
+inline OverlayImplBase* OverlayState::handle_3D_3DPanel(
+ utils::eOverlayState s,
+ OverlayImplBase* ov)
+{
+ OverlayImplBase* newov = ov;
+ switch(s)
+ {
+ case utils::OV_CLOSED:
+ newov = handle_xxx_to_closed(ov);
+ break;
+ case utils::OV_2D_VIDEO_ON_PANEL:
+ newov = handle_xxx_to_xxx<utils::OV_2D_VIDEO_ON_PANEL>(ov);
+ break;
+ case utils::OV_2D_VIDEO_ON_PANEL_TV:
+ newov = handle_xxx_to_xxx<utils::OV_2D_VIDEO_ON_PANEL_TV>(ov);
+ break;
+ case utils::OV_3D_VIDEO_ON_2D_PANEL:
+ newov = handle_xxx_to_xxx<utils::OV_3D_VIDEO_ON_2D_PANEL>(ov);
+ break;
+ case utils::OV_3D_VIDEO_ON_3D_PANEL:
+ // no state change
+ break;
+ case utils::OV_3D_VIDEO_ON_3D_TV:
+ newov = handle_xxx_to_xxx<utils::OV_3D_VIDEO_ON_3D_TV>(ov);
+ break;
+ case utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV:
+ newov = handle_xxx_to_xxx<utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV>(ov);
+ break;
+ case utils::OV_UI_MIRROR:
+ newov = handle_xxx_to_xxx<utils::OV_UI_MIRROR>(ov);
+ break;
+ case utils::OV_2D_TRUE_UI_MIRROR:
+ newov = handle_xxx_to_xxx<utils::OV_2D_TRUE_UI_MIRROR>(ov);
+ break;
+ case utils::OV_BYPASS_1_LAYER:
+ newov = handle_xxx_to_xxx<utils::OV_BYPASS_1_LAYER>(ov);
+ break;
+ case utils::OV_BYPASS_2_LAYER:
+ newov = handle_xxx_to_xxx<utils::OV_BYPASS_2_LAYER>(ov);
+ break;
+ case utils::OV_BYPASS_3_LAYER:
+ newov = handle_xxx_to_xxx<utils::OV_BYPASS_3_LAYER>(ov);
+ break;
+ default:
+ ALOGE("%s: unknown state=%d", __FUNCTION__, s);
+ }
+ mState = s;
+ return newov;
+}
+
+// Transitions from 3D video on 3D TV to XXX
+inline OverlayImplBase* OverlayState::handle_3D_3DTV(
+ utils::eOverlayState s,
+ OverlayImplBase* ov)
+{
+ OverlayImplBase* newov = ov;
+ switch(s)
+ {
+ case utils::OV_CLOSED:
+ newov = handle_xxx_to_closed(ov);
+ break;
+ case utils::OV_2D_VIDEO_ON_PANEL:
+ newov = handle_xxx_to_xxx<utils::OV_2D_VIDEO_ON_PANEL>(ov);
+ break;
+ case utils::OV_2D_VIDEO_ON_PANEL_TV:
+ newov = handle_xxx_to_xxx<utils::OV_2D_VIDEO_ON_PANEL_TV>(ov);
+ break;
+ case utils::OV_3D_VIDEO_ON_2D_PANEL:
+ newov = handle_xxx_to_xxx<utils::OV_3D_VIDEO_ON_2D_PANEL>(ov);
+ break;
+ case utils::OV_3D_VIDEO_ON_3D_PANEL:
+ newov = handle_xxx_to_xxx<utils::OV_3D_VIDEO_ON_3D_PANEL>(ov);
+ break;
+ case utils::OV_3D_VIDEO_ON_3D_TV:
+ // no state change
+ break;
+ case utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV:
+ newov = handle_xxx_to_xxx<utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV>(ov);
+ break;
+ case utils::OV_UI_MIRROR:
+ newov = handle_xxx_to_xxx<utils::OV_UI_MIRROR>(ov);
+ break;
+ case utils::OV_2D_TRUE_UI_MIRROR:
+ newov = handle_xxx_to_xxx<utils::OV_2D_TRUE_UI_MIRROR>(ov);
+ break;
+ case utils::OV_BYPASS_1_LAYER:
+ newov = handle_xxx_to_xxx<utils::OV_BYPASS_1_LAYER>(ov);
+ break;
+ case utils::OV_BYPASS_2_LAYER:
+ newov = handle_xxx_to_xxx<utils::OV_BYPASS_2_LAYER>(ov);
+ break;
+ case utils::OV_BYPASS_3_LAYER:
+ newov = handle_xxx_to_xxx<utils::OV_BYPASS_3_LAYER>(ov);
+ break;
+ default:
+ ALOGE("%s: unknown state=%d", __FUNCTION__, s);
+ }
+ mState = s;
+ return newov;
+}
+
+// Transitions from 3D video on 2D panel and 2D TV to XXX
+inline OverlayImplBase* OverlayState::handle_3D_2DTV(
+ utils::eOverlayState s,
+ OverlayImplBase* ov)
+{
+ OverlayImplBase* newov = ov;
+ switch(s)
+ {
+ case utils::OV_CLOSED:
+ newov = handle_xxx_to_closed(ov);
+ break;
+ case utils::OV_2D_VIDEO_ON_PANEL:
+ newov = handle_xxx_to_xxx<utils::OV_2D_VIDEO_ON_PANEL>(ov);
+ break;
+ case utils::OV_2D_VIDEO_ON_PANEL_TV:
+ newov = handle_xxx_to_xxx<utils::OV_2D_VIDEO_ON_PANEL_TV>(ov);
+ break;
+ case utils::OV_3D_VIDEO_ON_2D_PANEL:
+ newov = handle_xxx_to_3D_2DPanel(ov);
+ break;
+ case utils::OV_3D_VIDEO_ON_3D_PANEL:
+ newov = handle_xxx_to_xxx<utils::OV_3D_VIDEO_ON_3D_PANEL>(ov);
+ break;
+ case utils::OV_3D_VIDEO_ON_3D_TV:
+ newov = handle_xxx_to_xxx<utils::OV_3D_VIDEO_ON_3D_TV>(ov);
+ break;
+ case utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV:
+ // no state change
+ break;
+ case utils::OV_UI_MIRROR:
+ newov = handle_xxx_to_xxx<utils::OV_UI_MIRROR>(ov);
+ break;
+ case utils::OV_2D_TRUE_UI_MIRROR:
+ newov = handle_xxx_to_xxx<utils::OV_2D_TRUE_UI_MIRROR>(ov);
+ break;
+ case utils::OV_BYPASS_1_LAYER:
+ newov = handle_xxx_to_xxx<utils::OV_BYPASS_1_LAYER>(ov);
+ break;
+ case utils::OV_BYPASS_2_LAYER:
+ newov = handle_xxx_to_xxx<utils::OV_BYPASS_2_LAYER>(ov);
+ break;
+ case utils::OV_BYPASS_3_LAYER:
+ newov = handle_xxx_to_xxx<utils::OV_BYPASS_3_LAYER>(ov);
+ break;
+ default:
+ ALOGE("%s: unknown state=%d", __FUNCTION__, s);
+ }
+ mState = s;
+ return newov;
+}
+
+// Transitions from UI mirroring to XXX
+inline OverlayImplBase* OverlayState::handle_UI_Mirror(utils::eOverlayState s,
+ OverlayImplBase* ov)
+{
+ OverlayImplBase* newov = ov;
+ switch(s)
+ {
+ case utils::OV_CLOSED:
+ newov = handle_xxx_to_closed(ov);
+ break;
+ case utils::OV_2D_VIDEO_ON_PANEL:
+ newov = handle_xxx_to_xxx<utils::OV_2D_VIDEO_ON_PANEL>(ov);
+ break;
+ case utils::OV_2D_VIDEO_ON_PANEL_TV:
+ newov = handle_xxx_to_xxx<utils::OV_2D_VIDEO_ON_PANEL_TV>(ov);
+ break;
+ case utils::OV_3D_VIDEO_ON_2D_PANEL:
+ newov = handle_xxx_to_xxx<utils::OV_3D_VIDEO_ON_2D_PANEL>(ov);
+ break;
+ case utils::OV_3D_VIDEO_ON_3D_PANEL:
+ newov = handle_xxx_to_xxx<utils::OV_3D_VIDEO_ON_3D_PANEL>(ov);
+ break;
+ case utils::OV_3D_VIDEO_ON_3D_TV:
+ newov = handle_xxx_to_xxx<utils::OV_3D_VIDEO_ON_3D_TV>(ov);
+ break;
+ case utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV:
+ newov = handle_xxx_to_xxx<utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV>(ov);
+ break;
+ case utils::OV_UI_MIRROR:
+ // no state change
+ break;
+ case utils::OV_2D_TRUE_UI_MIRROR:
+ newov = handle_xxx_to_xxx<utils::OV_2D_TRUE_UI_MIRROR>(ov);
+ break;
+ case utils::OV_BYPASS_1_LAYER:
+ newov = handle_xxx_to_xxx<utils::OV_BYPASS_1_LAYER>(ov);
+ break;
+ case utils::OV_BYPASS_2_LAYER:
+ newov = handle_xxx_to_xxx<utils::OV_BYPASS_2_LAYER>(ov);
+ break;
+ case utils::OV_BYPASS_3_LAYER:
+ newov = handle_xxx_to_xxx<utils::OV_BYPASS_3_LAYER>(ov);
+ break;
+ default:
+ ALOGE("%s: unknown state=%d", __FUNCTION__, s);
+ }
+ mState = s;
+ return newov;
+}
+
+// Transitions from 2D video true UI mirroring (2D video + UI) to XXX
+inline OverlayImplBase* OverlayState::handle_2D_trueUI_Mirror(utils::eOverlayState s,
+ OverlayImplBase* ov)
+{
+ OverlayImplBase* newov = ov;
+ switch(s)
+ {
+ case utils::OV_CLOSED:
+ newov = handle_xxx_to_closed(ov);
+ break;
+ case utils::OV_2D_VIDEO_ON_PANEL:
+ newov = handle_xxx_to_2D_2DPanel(ov);
+ break;
+ case utils::OV_2D_VIDEO_ON_PANEL_TV:
+ newov = handle_xxx_to_2D_2DTV(ov);
+ break;
+ case utils::OV_3D_VIDEO_ON_2D_PANEL:
+ newov = handle_xxx_to_xxx<utils::OV_3D_VIDEO_ON_2D_PANEL>(ov);
+ break;
+ case utils::OV_3D_VIDEO_ON_3D_PANEL:
+ newov = handle_xxx_to_xxx<utils::OV_3D_VIDEO_ON_3D_PANEL>(ov);
+ break;
+ case utils::OV_3D_VIDEO_ON_3D_TV:
+ newov = handle_xxx_to_xxx<utils::OV_3D_VIDEO_ON_3D_TV>(ov);
+ break;
+ case utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV:
+ newov = handle_xxx_to_xxx<utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV>(ov);
+ break;
+ case utils::OV_UI_MIRROR:
+ newov = handle_xxx_to_xxx<utils::OV_UI_MIRROR>(ov);
+ break;
+ case utils::OV_2D_TRUE_UI_MIRROR:
+ // no state change
+ break;
+ case utils::OV_BYPASS_1_LAYER:
+ newov = handle_xxx_to_xxx<utils::OV_BYPASS_1_LAYER>(ov);
+ break;
+ case utils::OV_BYPASS_2_LAYER:
+ newov = handle_xxx_to_xxx<utils::OV_BYPASS_2_LAYER>(ov);
+ break;
+ case utils::OV_BYPASS_3_LAYER:
+ newov = handle_xxx_to_xxx<utils::OV_BYPASS_3_LAYER>(ov);
+ break;
+ default:
+ ALOGE("%s: unknown state=%d", __FUNCTION__, s);
+ }
+ mState = s;
+ return newov;
+}
+
+// Transitions from composition bypass to XXX
+inline OverlayImplBase* OverlayState::handle_bypass(utils::eOverlayState s,
+ OverlayImplBase* ov)
+{
+ OverlayImplBase* newov = ov;
+ switch(s)
+ {
+ case utils::OV_CLOSED:
+ newov = handle_xxx_to_closed(ov);
+ break;
+ case utils::OV_2D_VIDEO_ON_PANEL:
+ newov = handle_xxx_to_xxx<utils::OV_2D_VIDEO_ON_PANEL>(ov);
+ break;
+ case utils::OV_2D_VIDEO_ON_PANEL_TV:
+ newov = handle_xxx_to_xxx<utils::OV_2D_VIDEO_ON_PANEL_TV>(ov);
+ break;
+ case utils::OV_3D_VIDEO_ON_2D_PANEL:
+ newov = handle_xxx_to_xxx<utils::OV_3D_VIDEO_ON_2D_PANEL>(ov);
+ break;
+ case utils::OV_3D_VIDEO_ON_3D_PANEL:
+ newov = handle_xxx_to_xxx<utils::OV_3D_VIDEO_ON_3D_PANEL>(ov);
+ break;
+ case utils::OV_3D_VIDEO_ON_3D_TV:
+ newov = handle_xxx_to_xxx<utils::OV_3D_VIDEO_ON_3D_TV>(ov);
+ break;
+ case utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV:
+ newov = handle_xxx_to_xxx<utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV>(ov);
+ break;
+ case utils::OV_UI_MIRROR:
+ newov = handle_xxx_to_xxx<utils::OV_UI_MIRROR>(ov);
+ break;
+ case utils::OV_2D_TRUE_UI_MIRROR:
+ newov = handle_xxx_to_xxx<utils::OV_2D_TRUE_UI_MIRROR>(ov);
+ break;
+ case utils::OV_BYPASS_1_LAYER:
+ newov = handle_xxx_to_bypass1(ov);
+ break;
+ case utils::OV_BYPASS_2_LAYER:
+ newov = handle_xxx_to_bypass2(ov);
+ break;
+ case utils::OV_BYPASS_3_LAYER:
+ newov = handle_xxx_to_bypass3(ov);
+ break;
+ default:
+ ALOGE("%s: unknown state=%d", __FUNCTION__, s);
+ }
+ mState = s;
+ return newov;
+}
+
+
+} // overlay
+
+#endif // OVERLAY_STATE_H
diff --git a/liboverlay/overlayTransitions.cpp b/liboverlay/overlayTransitions.cpp
new file mode 100644
index 0000000..45d3720
--- /dev/null
+++ b/liboverlay/overlayTransitions.cpp
@@ -0,0 +1,503 @@
+/*
+* Copyright (c) 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.
+*/
+
+#include "overlayState.h"
+
+namespace overlay {
+
+/*
+ * Transition from any state to 2D video on 2D panel
+ */
+OverlayImplBase* OverlayState::handle_xxx_to_2D_2DPanel(
+ OverlayImplBase* ov)
+{
+ OVASSERT(ov, "%s: ov is null", __FUNCTION__);
+ ALOGE("%s", __FUNCTION__);
+
+ // Create new ovimpl based on new state
+ typedef StateTraits<utils::OV_2D_VIDEO_ON_PANEL> NewState;
+ OverlayImplBase* newov = new NewState::ovimpl;
+
+ //===========================================================
+ // For each pipe:
+ // - If pipe matches, copy from previous into new ovimpl
+ // - Otherwise open for new and delete from previous ovimpl
+ //===========================================================
+
+ // pipe0/rot0 (GenericPipe)
+ if (ov->getOvPipeType(utils::OV_PIPE0) == utils::OV_PIPE_TYPE_GENERIC) {
+ ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe0 (GenericPipe)", __FUNCTION__);
+ newov->copyOvPipe(ov, utils::OV_PIPE0);
+ } else {
+ ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe0 (GenericPipe)", __FUNCTION__);
+ RotatorBase* rot0 = new NewState::rot0;
+ ov->closePipe(utils::OV_PIPE0);
+ newov->openPipe(rot0, utils::OV_PIPE0);
+ }
+
+ // pipe1/rot1 (NullPipe)
+ if (ov->getOvPipeType(utils::OV_PIPE1) == utils::OV_PIPE_TYPE_NULL) {
+ ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe1 (NullPipe)", __FUNCTION__);
+ newov->copyOvPipe(ov, utils::OV_PIPE1);
+ } else {
+ ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe1 (NullPipe)", __FUNCTION__);
+ RotatorBase* rot1 = new NewState::rot1;
+ ov->closePipe(utils::OV_PIPE1);
+ newov->openPipe(rot1, utils::OV_PIPE1);
+ }
+
+ // pipe2/rot2 (NullPipe)
+ if (ov->getOvPipeType(utils::OV_PIPE2) == utils::OV_PIPE_TYPE_NULL) {
+ ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe2 (NullPipe)", __FUNCTION__);
+ newov->copyOvPipe(ov, utils::OV_PIPE2);
+ } else {
+ ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe2 (NullPipe)", __FUNCTION__);
+ RotatorBase* rot2 = new NewState::rot2;
+ ov->closePipe(utils::OV_PIPE2);
+ newov->openPipe(rot2, utils::OV_PIPE2);
+ }
+
+ // All pipes are copied or deleted so no more need for previous ovimpl
+ delete ov;
+ ov = 0;
+
+ return newov;
+}
+
+/*
+ * Transition from any state to 2D video on 2D panel and 2D TV
+ */
+OverlayImplBase* OverlayState::handle_xxx_to_2D_2DTV(
+ OverlayImplBase* ov)
+{
+ OVASSERT(ov, "%s: ov is null", __FUNCTION__);
+ ALOGE("%s", __FUNCTION__);
+
+ // Create new ovimpl based on new state
+ typedef StateTraits<utils::OV_2D_VIDEO_ON_PANEL_TV> NewState;
+ OverlayImplBase* newov = new NewState::ovimpl;
+
+ //===========================================================
+ // For each pipe:
+ // - If pipe matches, copy from previous into new ovimpl
+ // - Otherwise open for new and delete from previous ovimpl
+ //===========================================================
+
+ // pipe0/rot0 (GenericPipe)
+ if (ov->getOvPipeType(utils::OV_PIPE0) == utils::OV_PIPE_TYPE_GENERIC) {
+ ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe0 (GenericPipe)", __FUNCTION__);
+ newov->copyOvPipe(ov, utils::OV_PIPE0);
+ } else {
+ ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe0 (GenericPipe)", __FUNCTION__);
+ RotatorBase* rot0 = new NewState::rot0;
+ ov->closePipe(utils::OV_PIPE0);
+ newov->openPipe(rot0, utils::OV_PIPE0);
+ }
+
+ // pipe1/rot1 (HdmiPipe)
+ if (ov->getOvPipeType(utils::OV_PIPE1) == utils::OV_PIPE_TYPE_HDMI) {
+ ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe1 (HdmiPipe)", __FUNCTION__);
+ newov->copyOvPipe(ov, utils::OV_PIPE1);
+ } else {
+ ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe1 (HdmiPipe)", __FUNCTION__);
+ RotatorBase* rot1 = new NewState::rot1;
+ ov->closePipe(utils::OV_PIPE1);
+ newov->openPipe(rot1, utils::OV_PIPE1);
+ }
+
+ // pipe2/rot2 (NullPipe)
+ if (ov->getOvPipeType(utils::OV_PIPE2) == utils::OV_PIPE_TYPE_NULL) {
+ ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe2 (NullPipe)", __FUNCTION__);
+ newov->copyOvPipe(ov, utils::OV_PIPE2);
+ } else {
+ ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe2 (NullPipe)", __FUNCTION__);
+ RotatorBase* rot2 = new NewState::rot2;
+ ov->closePipe(utils::OV_PIPE2);
+ newov->openPipe(rot2, utils::OV_PIPE2);
+ }
+
+ // All pipes are copied or deleted so no more need for previous ovimpl
+ delete ov;
+ ov = 0;
+
+ return newov;
+}
+
+/*
+ * Transition from any state to 3D video on 2D panel
+ */
+OverlayImplBase* OverlayState::handle_xxx_to_3D_2DPanel(
+ OverlayImplBase* ov)
+{
+ OVASSERT(ov, "%s: ov is null", __FUNCTION__);
+ ALOGE("%s", __FUNCTION__);
+
+ // Create new ovimpl based on new state
+ typedef StateTraits<utils::OV_3D_VIDEO_ON_2D_PANEL> NewState;
+ OverlayImplBase* newov = new NewState::ovimpl;
+
+ //===========================================================
+ // For each pipe:
+ // - If pipe matches, copy from previous into new ovimpl
+ // - Otherwise open for new and delete from previous ovimpl
+ //===========================================================
+
+ // pipe0/rot0 (M3DPrimaryPipe)
+ if (ov->getOvPipeType(utils::OV_PIPE0) == utils::OV_PIPE_TYPE_M3D_PRIMARY) {
+ ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe0 (M3DPrimaryPipe)", __FUNCTION__);
+ newov->copyOvPipe(ov, utils::OV_PIPE0);
+ } else {
+ ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe0 (M3DPrimaryPipe)", __FUNCTION__);
+ RotatorBase* rot0 = new NewState::rot0;
+ ov->closePipe(utils::OV_PIPE0);
+ newov->openPipe(rot0, utils::OV_PIPE0);
+ }
+
+ // pipe1/rot1 (NullPipe)
+ if (ov->getOvPipeType(utils::OV_PIPE1) == utils::OV_PIPE_TYPE_NULL) {
+ ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe1 (NullPipe)", __FUNCTION__);
+ newov->copyOvPipe(ov, utils::OV_PIPE1);
+ } else {
+ ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe1 (NullPipe)", __FUNCTION__);
+ RotatorBase* rot1 = new NewState::rot1;
+ ov->closePipe(utils::OV_PIPE1);
+ newov->openPipe(rot1, utils::OV_PIPE1);
+ }
+
+ // pipe2/rot2 (NullPipe)
+ if (ov->getOvPipeType(utils::OV_PIPE2) == utils::OV_PIPE_TYPE_NULL) {
+ ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe2 (NullPipe)", __FUNCTION__);
+ newov->copyOvPipe(ov, utils::OV_PIPE2);
+ } else {
+ ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe2 (NullPipe)", __FUNCTION__);
+ RotatorBase* rot2 = new NewState::rot2;
+ ov->closePipe(utils::OV_PIPE2);
+ newov->openPipe(rot2, utils::OV_PIPE2);
+ }
+
+ // All pipes are copied or deleted so no more need for previous ovimpl
+ delete ov;
+ ov = 0;
+
+ return newov;
+}
+
+/*
+ * Transition from any state to 3D video on 2D panel and 2D TV
+ */
+OverlayImplBase* OverlayState::handle_xxx_to_3D_2DTV(
+ OverlayImplBase* ov)
+{
+ OVASSERT(ov, "%s: ov is null", __FUNCTION__);
+ ALOGE("%s", __FUNCTION__);
+
+ // Create new ovimpl based on new state
+ typedef StateTraits<utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV> NewState;
+ OverlayImplBase* newov = new NewState::ovimpl;
+
+ //===========================================================
+ // For each pipe:
+ // - If pipe matches, copy from previous into new ovimpl
+ // - Otherwise open for new and delete from previous ovimpl
+ //===========================================================
+
+ // pipe0/rot0 (M3DPrimaryPipe)
+ if (ov->getOvPipeType(utils::OV_PIPE0) == utils::OV_PIPE_TYPE_M3D_PRIMARY) {
+ ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe0 (M3DPrimaryPipe)", __FUNCTION__);
+ newov->copyOvPipe(ov, utils::OV_PIPE0);
+ } else {
+ ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe0 (M3DPrimaryPipe)", __FUNCTION__);
+ RotatorBase* rot0 = new NewState::rot0;
+ ov->closePipe(utils::OV_PIPE0);
+ newov->openPipe(rot0, utils::OV_PIPE0);
+ }
+
+ // pipe1/rot1 (M3DExtPipe)
+ if (ov->getOvPipeType(utils::OV_PIPE1) == utils::OV_PIPE_TYPE_M3D_EXTERNAL) {
+ ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe1 (M3DExtPipe)", __FUNCTION__);
+ newov->copyOvPipe(ov, utils::OV_PIPE1);
+ } else {
+ ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe1 (M3DExtPipe)", __FUNCTION__);
+ RotatorBase* rot1 = new NewState::rot1;
+ ov->closePipe(utils::OV_PIPE1);
+ newov->openPipe(rot1, utils::OV_PIPE1);
+ }
+
+ // pipe2/rot2 (NullPipe)
+ if (ov->getOvPipeType(utils::OV_PIPE2) == utils::OV_PIPE_TYPE_NULL) {
+ ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe2 (NullPipe)", __FUNCTION__);
+ newov->copyOvPipe(ov, utils::OV_PIPE2);
+ } else {
+ ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe2 (NullPipe)", __FUNCTION__);
+ RotatorBase* rot2 = new NewState::rot2;
+ ov->closePipe(utils::OV_PIPE2);
+ newov->openPipe(rot2, utils::OV_PIPE2);
+ }
+
+ // All pipes are copied or deleted so no more need for previous ovimpl
+ delete ov;
+ ov = 0;
+
+ return newov;
+}
+
+/*
+ * Transition from any state to 2D true UI mirroring (2D video + UI)
+ */
+OverlayImplBase* OverlayState::handle_xxx_to_2D_trueUI_Mirror(
+ OverlayImplBase* ov)
+{
+ OVASSERT(ov, "%s: ov is null", __FUNCTION__);
+ ALOGE("%s", __FUNCTION__);
+
+ // Create new ovimpl based on new state
+ typedef StateTraits<utils::OV_2D_TRUE_UI_MIRROR> NewState;
+ OverlayImplBase* newov = new NewState::ovimpl;
+
+ //===========================================================
+ // For each pipe:
+ // - If pipe matches, copy from previous into new ovimpl
+ // - Otherwise open for new and delete from previous ovimpl
+ //===========================================================
+
+ // pipe0/rot0 (GenericPipe)
+ if (ov->getOvPipeType(utils::OV_PIPE0) == utils::OV_PIPE_TYPE_GENERIC) {
+ ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe0 (GenericPipe)", __FUNCTION__);
+ newov->copyOvPipe(ov, utils::OV_PIPE0);
+ } else {
+ ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe0 (GenericPipe)", __FUNCTION__);
+ RotatorBase* rot0 = new NewState::rot0;
+ ov->closePipe(utils::OV_PIPE0);
+ newov->openPipe(rot0, utils::OV_PIPE0);
+ }
+
+ // pipe1/rot1 (HdmiPipe)
+ if (ov->getOvPipeType(utils::OV_PIPE1) == utils::OV_PIPE_TYPE_HDMI) {
+ ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe1 (HdmiPipe)", __FUNCTION__);
+ newov->copyOvPipe(ov, utils::OV_PIPE1);
+ } else {
+ ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe1 (HdmiPipe)", __FUNCTION__);
+ RotatorBase* rot1 = new NewState::rot1;
+ ov->closePipe(utils::OV_PIPE1);
+ newov->openPipe(rot1, utils::OV_PIPE1);
+ }
+
+ // pipe2/rot2 (UIMirrorPipe)
+ if (ov->getOvPipeType(utils::OV_PIPE2) == utils::OV_PIPE_TYPE_UI_MIRROR) {
+ ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe2 (UIMirrorPipe)", __FUNCTION__);
+ newov->copyOvPipe(ov, utils::OV_PIPE2);
+ } else {
+ ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe2 (UIMirrorPipe)", __FUNCTION__);
+ RotatorBase* rot2 = new NewState::rot2;
+ ov->closePipe(utils::OV_PIPE2);
+ newov->openPipe(rot2, utils::OV_PIPE2);
+ }
+
+ // All pipes are copied or deleted so no more need for previous ovimpl
+ delete ov;
+ ov = 0;
+
+ return newov;
+}
+
+/*
+ * Transitions from any state to 1 layer composition bypass
+ */
+OverlayImplBase* OverlayState::handle_xxx_to_bypass1(OverlayImplBase* ov)
+{
+ OVASSERT(ov, "%s: ov is null", __FUNCTION__);
+ ALOGE("%s", __FUNCTION__);
+
+ // Create new ovimpl based on new state
+ typedef StateTraits<utils::OV_BYPASS_1_LAYER> NewState;
+ OverlayImplBase* newov = new NewState::ovimpl;
+
+ //===========================================================
+ // For each pipe:
+ // - If pipe matches, copy from previous into new ovimpl
+ // - Otherwise open for new and delete from previous ovimpl
+ //===========================================================
+
+ // pipe0/rot0 (BypassPipe)
+ if (ov->getOvPipeType(utils::OV_PIPE0) == utils::OV_PIPE_TYPE_BYPASS) {
+ ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe0 (BypassPipe)", __FUNCTION__);
+ newov->copyOvPipe(ov, utils::OV_PIPE0);
+ } else {
+ ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe0 (BypassPipe)", __FUNCTION__);
+ RotatorBase* rot0 = new NewState::rot0;
+ ov->closePipe(utils::OV_PIPE0);
+ newov->openPipe(rot0, utils::OV_PIPE0);
+ }
+
+ // pipe1/rot1 (NullPipe)
+ if (ov->getOvPipeType(utils::OV_PIPE1) == utils::OV_PIPE_TYPE_NULL) {
+ ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe1 (NullPipe)", __FUNCTION__);
+ newov->copyOvPipe(ov, utils::OV_PIPE1);
+ } else {
+ ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe1 (NullPipe)", __FUNCTION__);
+ RotatorBase* rot1 = new NewState::rot1;
+ ov->closePipe(utils::OV_PIPE1);
+ newov->openPipe(rot1, utils::OV_PIPE1);
+ }
+
+ // pipe2/rot2 (NullPipe)
+ if (ov->getOvPipeType(utils::OV_PIPE2) == utils::OV_PIPE_TYPE_NULL) {
+ ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe2 (NullPipe)", __FUNCTION__);
+ newov->copyOvPipe(ov, utils::OV_PIPE2);
+ } else {
+ ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe2 (NullPipe)", __FUNCTION__);
+ RotatorBase* rot2 = new NewState::rot2;
+ ov->closePipe(utils::OV_PIPE2);
+ newov->openPipe(rot2, utils::OV_PIPE2);
+ }
+
+ // All pipes are copied or deleted so no more need for previous ovimpl
+ delete ov;
+ ov = 0;
+
+ return newov;
+}
+
+/*
+ * Transitions from any state to 2 layers composition bypass
+ */
+OverlayImplBase* OverlayState::handle_xxx_to_bypass2(OverlayImplBase* ov)
+{
+ OVASSERT(ov, "%s: ov is null", __FUNCTION__);
+ ALOGE("%s", __FUNCTION__);
+
+ // Create new ovimpl based on new state
+ typedef StateTraits<utils::OV_BYPASS_2_LAYER> NewState;
+ OverlayImplBase* newov = new NewState::ovimpl;
+
+ //===========================================================
+ // For each pipe:
+ // - If pipe matches, copy from previous into new ovimpl
+ // - Otherwise open for new and delete from previous ovimpl
+ //===========================================================
+
+ // pipe0/rot0 (BypassPipe)
+ if (ov->getOvPipeType(utils::OV_PIPE0) == utils::OV_PIPE_TYPE_BYPASS) {
+ ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe0 (BypassPipe)", __FUNCTION__);
+ newov->copyOvPipe(ov, utils::OV_PIPE0);
+ } else {
+ ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe0 (BypassPipe)", __FUNCTION__);
+ RotatorBase* rot0 = new NewState::rot0;
+ ov->closePipe(utils::OV_PIPE0);
+ newov->openPipe(rot0, utils::OV_PIPE0);
+ }
+
+ // pipe1/rot1 (BypassPipe)
+ if (ov->getOvPipeType(utils::OV_PIPE1) == utils::OV_PIPE_TYPE_BYPASS) {
+ ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe1 (BypassPipe)", __FUNCTION__);
+ newov->copyOvPipe(ov, utils::OV_PIPE1);
+ } else {
+ ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe1 (BypassPipe)", __FUNCTION__);
+ RotatorBase* rot1 = new NewState::rot1;
+ ov->closePipe(utils::OV_PIPE1);
+ newov->openPipe(rot1, utils::OV_PIPE1);
+ }
+
+ // pipe2/rot2 (NullPipe)
+ if (ov->getOvPipeType(utils::OV_PIPE2) == utils::OV_PIPE_TYPE_NULL) {
+ ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe2 (NullPipe)", __FUNCTION__);
+ newov->copyOvPipe(ov, utils::OV_PIPE2);
+ } else {
+ ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe2 (NullPipe)", __FUNCTION__);
+ RotatorBase* rot2 = new NewState::rot2;
+ ov->closePipe(utils::OV_PIPE2);
+ newov->openPipe(rot2, utils::OV_PIPE2);
+ }
+
+ // All pipes are copied or deleted so no more need for previous ovimpl
+ delete ov;
+ ov = 0;
+
+ return newov;
+}
+
+/*
+ * Transitions from any state to 3 layers composition bypass
+ */
+OverlayImplBase* OverlayState::handle_xxx_to_bypass3(OverlayImplBase* ov)
+{
+ OVASSERT(ov, "%s: ov is null", __FUNCTION__);
+ ALOGE("%s", __FUNCTION__);
+
+ // Create new ovimpl based on new state
+ typedef StateTraits<utils::OV_BYPASS_3_LAYER> NewState;
+ OverlayImplBase* newov = new NewState::ovimpl;
+
+ //===========================================================
+ // For each pipe:
+ // - If pipe matches, copy from previous into new ovimpl
+ // - Otherwise open for new and delete from previous ovimpl
+ //===========================================================
+
+ // pipe0/rot0 (BypassPipe)
+ if (ov->getOvPipeType(utils::OV_PIPE0) == utils::OV_PIPE_TYPE_BYPASS) {
+ ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe0 (BypassPipe)", __FUNCTION__);
+ newov->copyOvPipe(ov, utils::OV_PIPE0);
+ } else {
+ ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe0 (BypassPipe)", __FUNCTION__);
+ RotatorBase* rot0 = new NewState::rot0;
+ ov->closePipe(utils::OV_PIPE0);
+ newov->openPipe(rot0, utils::OV_PIPE0);
+ }
+
+ // pipe1/rot1 (BypassPipe)
+ if (ov->getOvPipeType(utils::OV_PIPE1) == utils::OV_PIPE_TYPE_BYPASS) {
+ ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe1 (BypassPipe)", __FUNCTION__);
+ newov->copyOvPipe(ov, utils::OV_PIPE1);
+ } else {
+ ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe1 (BypassPipe)", __FUNCTION__);
+ RotatorBase* rot1 = new NewState::rot1;
+ ov->closePipe(utils::OV_PIPE1);
+ newov->openPipe(rot1, utils::OV_PIPE1);
+ }
+
+ // pipe2/rot2 (BypassPipe)
+ if (ov->getOvPipeType(utils::OV_PIPE2) == utils::OV_PIPE_TYPE_BYPASS) {
+ ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe2 (BypassPipe)", __FUNCTION__);
+ newov->copyOvPipe(ov, utils::OV_PIPE2);
+ } else {
+ ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe2 (BypassPipe)", __FUNCTION__);
+ RotatorBase* rot2 = new NewState::rot2;
+ ov->closePipe(utils::OV_PIPE2);
+ newov->openPipe(rot2, utils::OV_PIPE2);
+ }
+
+ // All pipes are copied or deleted so no more need for previous ovimpl
+ delete ov;
+ ov = 0;
+
+ return newov;
+}
+
+} // overlay
diff --git a/liboverlay/overlayUtils.cpp b/liboverlay/overlayUtils.cpp
new file mode 100644
index 0000000..38e3ab2
--- /dev/null
+++ b/liboverlay/overlayUtils.cpp
@@ -0,0 +1,337 @@
+/*
+* Copyright (c) 2011-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.
+*/
+
+#include <stdlib.h>
+#include <utils/Log.h>
+#include <linux/msm_mdp.h>
+#include <cutils/properties.h>
+#include "gralloc_priv.h"
+#include "fb_priv.h"
+#include "overlayUtils.h"
+#include "mdpWrapper.h"
+
+// just a helper static thingy
+namespace {
+struct IOFile {
+ IOFile(const char* s, const char* mode) : fp(0) {
+ fp = ::fopen(s, mode);
+ if(!fp) {
+ ALOGE("Failed open %s", s);
+ }
+ }
+ template <class T>
+ size_t read(T& r, size_t elem) {
+ if(fp) {
+ return ::fread(&r, sizeof(T), elem, fp);
+ }
+ return 0;
+ }
+ size_t write(const char* s, uint32_t val) {
+ if(fp) {
+ return ::fprintf(fp, s, val);
+ }
+ return 0;
+ }
+ bool valid() const { return fp != 0; }
+ ~IOFile() {
+ if(fp) ::fclose(fp);
+ fp=0;
+ }
+ FILE* fp;
+};
+}
+
+namespace overlay {
+
+//----------From class Res ------------------------------
+const char* const Res::devTemplate = "/dev/graphics/fb%u";
+const char* const Res::rotPath = "/dev/msm_rotator";
+const char* const Res::format3DFile =
+ "/sys/class/graphics/fb1/format_3d";
+const char* const Res::edid3dInfoFile =
+ "/sys/class/graphics/fb1/3d_present";
+const char* const Res::barrierFile =
+ "/sys/devices/platform/mipi_novatek.0/enable_3d_barrier";
+//--------------------------------------------------------
+
+
+
+namespace utils {
+//--------------------------------------------------------
+FrameBufferInfo::FrameBufferInfo() {
+ mFBWidth = 0;
+ mFBHeight = 0;
+ mBorderFillSupported = false;
+
+ OvFD mFd;
+
+ // Use open defined in overlayFD file to open fd for fb0
+ if(!overlay::open(mFd, 0, Res::devTemplate)) {
+ ALOGE("FrameBufferInfo: failed to open fd");
+ return;
+ }
+
+ if (!mFd.valid()) {
+ ALOGE("FrameBufferInfo: FD not valid");
+ return;
+ }
+
+ fb_var_screeninfo vinfo;
+ if (!mdp_wrapper::getVScreenInfo(mFd.getFD(), vinfo)) {
+ ALOGE("FrameBufferInfo: failed getVScreenInfo on fb0");
+ mFd.close();
+ return;
+ }
+
+ mdp_overlay ov;
+ memset(&ov, 0, sizeof(ov));
+ ov.id = 1;
+ if (!mdp_wrapper::getOverlay(mFd.getFD(), ov)) {
+ ALOGE("FrameBufferInfo: failed getOverlay on fb0");
+ mFd.close();
+ return;
+ }
+
+ mFd.close();
+
+ mFBWidth = vinfo.xres;
+ mFBHeight = vinfo.yres;
+ mBorderFillSupported = (ov.flags & MDP_BORDERFILL_SUPPORTED) ?
+ true : false;
+}
+
+FrameBufferInfo* FrameBufferInfo::getInstance() {
+ if (!sFBInfoInstance) {
+ sFBInfoInstance = new FrameBufferInfo;
+ }
+ return sFBInfoInstance;
+}
+
+int FrameBufferInfo::getWidth() const {
+ return mFBWidth;
+}
+
+int FrameBufferInfo::getHeight() const {
+ return mFBHeight;
+}
+
+bool FrameBufferInfo::supportTrueMirroring() const {
+ return mBorderFillSupported;
+}
+
+//--------------------------------------------------------
+uint32_t getSize(const Whf& whf) {
+ int aligned_height=0, pitch=0;
+
+ uint32_t size = whf.w * whf.h;
+ switch (whf.format) {
+ case MDP_RGBA_8888:
+ case MDP_BGRA_8888:
+ case MDP_RGBX_8888:
+ size *= 4;
+ break;
+ case MDP_RGB_565:
+ case MDP_Y_CBCR_H2V1:
+ size *= 2;
+ break;
+ case MDP_Y_CBCR_H2V2:
+ case MDP_Y_CRCB_H2V2:
+ size = (size * 3) / 2;
+ break;
+ case MDP_Y_CRCB_H2V2_TILE:
+ case MDP_Y_CBCR_H2V2_TILE:
+ aligned_height = align(whf.h , 32);
+ pitch = align(whf.w, 128);
+ size = pitch * aligned_height;
+ size = align(size, 8192);
+
+ aligned_height = align(whf.h >> 1, 32);
+ size += pitch * aligned_height;
+ size = align(size, 8192);
+ break;
+ default:
+ ALOGE("getSize unknown format %d", whf.format);
+ return 0;
+ }
+ return size;
+}
+
+int getMdpFormat(int format) {
+ switch (format) {
+ case HAL_PIXEL_FORMAT_RGBA_8888 :
+ return MDP_RGBA_8888;
+ case HAL_PIXEL_FORMAT_BGRA_8888:
+ return MDP_BGRA_8888;
+ case HAL_PIXEL_FORMAT_RGB_565:
+ return MDP_RGB_565;
+ case HAL_PIXEL_FORMAT_RGBX_8888:
+ return MDP_RGBX_8888;
+ case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+ return MDP_Y_CBCR_H2V1;
+ case HAL_PIXEL_FORMAT_YCrCb_422_SP:
+ return MDP_Y_CRCB_H2V1;
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+ return MDP_Y_CBCR_H2V2;
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+ return MDP_Y_CRCB_H2V2;
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
+ return MDP_Y_CBCR_H2V2_TILE;
+ case HAL_PIXEL_FORMAT_YV12:
+ return MDP_Y_CR_CB_H2V2;
+ default:
+ ALOGE("Error getMdpFormat format=%d", format);
+ return -1;
+ }
+ // not reached
+ return -1;
+}
+
+bool isHDMIConnected () {
+ char value[PROPERTY_VALUE_MAX] = {0};
+ property_get("hw.hdmiON", value, "0");
+ int isHDMI = atoi(value);
+ return isHDMI ? true : false;
+}
+
+bool is3DTV() {
+ char is3DTV = '0';
+ IOFile fp(Res::edid3dInfoFile, "r");
+ (void)fp.read(is3DTV, 1);
+ ALOGI("3DTV EDID flag: %d", is3DTV);
+ return (is3DTV == '0') ? false : true;
+}
+
+bool isPanel3D() {
+ OvFD fd;
+ if(!overlay::open(fd, 0 /*fb*/, Res::devTemplate)){
+ ALOGE("isPanel3D Can't open framebuffer 0");
+ return false;
+ }
+ fb_fix_screeninfo finfo;
+ if(!mdp_wrapper::getFScreenInfo(fd.getFD(), finfo)) {
+ ALOGE("isPanel3D read fb0 failed");
+ }
+ fd.close();
+ return (FB_TYPE_3D_PANEL == finfo.type) ? true : false;
+}
+
+bool usePanel3D() {
+ if(!isPanel3D())
+ return false;
+ char value[PROPERTY_VALUE_MAX];
+ property_get("persist.user.panel3D", value, "0");
+ int usePanel3D = atoi(value);
+ return usePanel3D ? true : false;
+}
+
+bool send3DInfoPacket (uint32_t format3D) {
+ IOFile fp(Res::format3DFile, "wb");
+ (void)fp.write("%d", format3D);
+ if(!fp.valid()) {
+ ALOGE("send3DInfoPacket: no sysfs entry for setting 3d mode");
+ return false;
+ }
+ return true;
+}
+
+bool enableBarrier (uint32_t orientation) {
+ IOFile fp(Res::barrierFile, "wb");
+ (void)fp.write("%d", orientation);
+ if(!fp.valid()) {
+ ALOGE("enableBarrier no sysfs entry for "
+ "enabling barriers on 3D panel");
+ return false;
+ }
+ return true;
+}
+
+uint32_t getS3DFormat(uint32_t fmt) {
+ // The S3D is part of the HAL_PIXEL_FORMAT_YV12 value. Add
+ // an explicit check for the format
+ if (fmt == HAL_PIXEL_FORMAT_YV12) {
+ return 0;
+ }
+ uint32_t fmt3D = format3D(fmt);
+ uint32_t fIn3D = format3DInput(fmt3D); // MSB 2 bytes - inp
+ uint32_t fOut3D = format3DOutput(fmt3D); // LSB 2 bytes - out
+ fmt3D = fIn3D | fOut3D;
+ if (!fIn3D) {
+ fmt3D |= fOut3D << SHIFT_TOT_3D; //Set the input format
+ }
+ if (!fOut3D) {
+ switch (fIn3D) {
+ case HAL_3D_IN_SIDE_BY_SIDE_L_R:
+ case HAL_3D_IN_SIDE_BY_SIDE_R_L:
+ // For all side by side formats, set the output
+ // format as Side-by-Side i.e 0x1
+ fmt3D |= HAL_3D_IN_SIDE_BY_SIDE_L_R >> SHIFT_TOT_3D;
+ break;
+ default:
+ fmt3D |= fIn3D >> SHIFT_TOT_3D; //Set the output format
+ }
+ }
+ return fmt3D;
+}
+
+void normalizeCrop(uint32_t& xy, uint32_t& wh) {
+ if (xy & 0x0001) {
+ // x or y is odd, increment it's value
+ xy += 1;
+ // Since we've incremented x(y), we need to decrement
+ // w(h) accordingly
+ if (wh & 0x0001) {
+ // w or h is odd, decrement it by 1, to make it even
+ even_out(wh);
+ } else {
+ // w(h) is already even, hence we decrement by 2
+ wh -=2;
+ }
+ } else {
+ even_out(wh);
+ }
+}
+
+void scale(mdp_overlay& ov)
+{
+ /* Scaling of upto a max of 8 times supported */
+ overlay::utils::Dim dst(overlay::utils::getDstRectDim(ov));
+ overlay::utils::Dim src(overlay::utils::getSrcRectDim(ov));
+ if(dst.w >(src.w * overlay::utils::HW_OV_MAGNIFICATION_LIMIT)) {
+ dst.w = overlay::utils::HW_OV_MAGNIFICATION_LIMIT * src.w;
+ }
+ if(dst.h >(src.h * overlay::utils::HW_OV_MAGNIFICATION_LIMIT)) {
+ dst.h = overlay::utils::HW_OV_MAGNIFICATION_LIMIT * src.h;
+ }
+
+ setDstRectDim(dst, ov);
+}
+
+} // utils
+
+} // overlay
diff --git a/liboverlay/overlayUtils.h b/liboverlay/overlayUtils.h
new file mode 100644
index 0000000..089d3fb
--- /dev/null
+++ b/liboverlay/overlayUtils.h
@@ -0,0 +1,1112 @@
+/*
+* Copyright (c) 2011-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 OVERLAY_UTILS_H
+#define OVERLAY_UTILS_H
+
+#include <cutils/log.h> // ALOGE, etc
+#include <errno.h>
+#include <fcntl.h> // open, O_RDWR, etc
+#include <hardware/hardware.h>
+#include <hardware/gralloc.h> // buffer_handle_t
+#include <linux/msm_mdp.h> // MDP_OV_PLAY_NOWAIT etc ...
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <utils/Log.h>
+
+/*
+*
+* Collection of utilities functions/structs/enums etc...
+*
+* */
+
+// comment that out if you want to remove asserts
+// or put it as -D in Android.mk. your choice.
+#define OVERLAY_HAS_ASSERT
+
+#ifdef OVERLAY_HAS_ASSERT
+# define OVASSERT(x, ...) if(!(x)) { ALOGE(__VA_ARGS__); abort(); }
+#else
+# define OVASSERT(x, ...) ALOGE_IF(!(x), __VA_ARGS__)
+#endif // OVERLAY_HAS_ASSERT
+
+#define DEBUG_OVERLAY 0
+#define PROFILE_OVERLAY 0
+
+namespace overlay {
+
+// fwd
+class Overlay;
+
+namespace utils {
+struct Whf;
+struct Dim;
+template <class T>
+ inline void even_out(T& x) { if (x & 0x0001) --x; }
+
+inline uint32_t getBit(uint32_t x, uint32_t mask) {
+ return (x & mask);
+}
+
+inline uint32_t setBit(uint32_t x, uint32_t mask) {
+ return (x | mask);
+}
+
+inline uint32_t clrBit(uint32_t x, uint32_t mask) {
+ return (x & ~mask);
+}
+
+/* Utility class to help avoid copying instances by making the copy ctor
+* and assignment operator private
+*
+* Usage:
+* * class SomeClass : utils::NoCopy {...};
+*/
+class NoCopy {
+protected:
+ NoCopy(){}
+ ~NoCopy() {}
+private:
+ NoCopy(const NoCopy&);
+ const NoCopy& operator=(const NoCopy&);
+};
+
+/*
+* Utility class to query the framebuffer info for primary display
+*
+* Usage:
+* Outside of functions:
+* utils::FrameBufferInfo* utils::FrameBufferInfo::sFBInfoInstance = 0;
+* Inside functions:
+* utils::FrameBufferInfo::getInstance()->supportTrueMirroring()
+*/
+class FrameBufferInfo {
+
+public:
+ /* ctor init */
+ explicit FrameBufferInfo();
+
+ /* Gets an instance if one does not already exist */
+ static FrameBufferInfo* getInstance();
+
+ /* Gets width of primary framebuffer */
+ int getWidth() const;
+
+ /* Gets height of primary framebuffer */
+ int getHeight() const;
+
+ /* Indicates whether true mirroring is supported */
+ bool supportTrueMirroring() const;
+
+private:
+ int mFBWidth;
+ int mFBHeight;
+ bool mBorderFillSupported;
+ static FrameBufferInfo *sFBInfoInstance;
+};
+
+/* 3D related utils, defines etc...
+ * The compound format passed to the overlay is
+ * ABCCC where A is the input 3D format
+ * B is the output 3D format
+ * CCC is the color format e.g YCbCr420SP YCrCb420SP etc */
+enum { SHIFT_OUT_3D = 12,
+ SHIFT_TOT_3D = 16 };
+enum { INPUT_3D_MASK = 0xFFFF0000,
+ OUTPUT_3D_MASK = 0x0000FFFF };
+enum { BARRIER_LAND = 1,
+ BARRIER_PORT = 2 };
+
+inline uint32_t format3D(uint32_t x) { return x & 0xFF000; }
+inline uint32_t colorFormat(uint32_t x) { return x & 0xFFF; }
+inline uint32_t format3DOutput(uint32_t x) {
+ return (x & 0xF000) >> SHIFT_OUT_3D; }
+inline uint32_t format3DInput(uint32_t x) { return x & 0xF0000; }
+uint32_t getColorFormat(uint32_t format);
+
+bool isHDMIConnected ();
+bool is3DTV();
+bool isPanel3D();
+bool usePanel3D();
+bool send3DInfoPacket (uint32_t fmt);
+bool enableBarrier (uint32_t orientation);
+uint32_t getS3DFormat(uint32_t fmt);
+template <int CHAN>
+ bool getPositionS3D(const Whf& whf, Dim& out);
+template <int CHAN>
+ bool getCropS3D(const Dim& in, Dim& out, uint32_t fmt);
+template <class Type>
+ void swapWidthHeight(Type& width, Type& height);
+
+struct Dim {
+ Dim () : x(0), y(0),
+ w(0), h(0),
+ o(0) {}
+ Dim(uint32_t _x, uint32_t _y, uint32_t _w, uint32_t _h) :
+ x(_x), y(_y),
+ w(_w), h(_h) {}
+ Dim(uint32_t _x, uint32_t _y, uint32_t _w, uint32_t _h, uint32_t _o) :
+ x(_x), y(_y),
+ w(_w), h(_h),
+ o(_o) {}
+ bool check(uint32_t _w, uint32_t _h) const {
+ return (x+w <= _w && y+h <= _h);
+
+ }
+
+ bool operator==(const Dim& d) const {
+ return d.x == x && d.y == y &&
+ d.w == w && d.h == h &&
+ d.o == o;
+ }
+
+ bool operator!=(const Dim& d) const {
+ return !operator==(d);
+ }
+
+ void even_out() {
+ utils::even_out(x);
+ utils::even_out(y);
+ utils::even_out(w);
+ utils::even_out(h);
+ }
+
+ void dump() const;
+ uint32_t x;
+ uint32_t y;
+ uint32_t w;
+ uint32_t h;
+ uint32_t o;
+};
+
+// TODO have Whfz
+
+struct Whf {
+ Whf() : w(0), h(0), format(0), size(0) {}
+ Whf(uint32_t wi, uint32_t he, uint32_t f) :
+ w(wi), h(he), format(f), size(0) {}
+ Whf(uint32_t wi, uint32_t he, uint32_t f, uint32_t s) :
+ w(wi), h(he), format(f), size(s) {}
+ // FIXME not comparing size at the moment
+ bool operator==(const Whf& whf) const {
+ return whf.w == w && whf.h == h &&
+ whf.format == format;
+ }
+ bool operator!=(const Whf& whf) const {
+ return !operator==(whf);
+ }
+ void dump() const;
+ uint32_t w;
+ uint32_t h;
+ // FIXME need to be int32_t ?
+ uint32_t format;
+ uint32_t size;
+};
+
+enum { MAX_PATH_LEN = 256 };
+
+enum eParams {
+ OVERLAY_DITHER,
+ OVERLAY_TRANSFORM,
+ OVERLAY_TRANSFORM_UI
+};
+
+struct Params{
+ Params(eParams p, int v) : param(p), value(v) {}
+ eParams param;
+ int value;
+};
+
+
+/**
+ * Rotator flags: not to be confused with orientation flags.
+ * Ususally, you want to open the rotator to make sure it is
+ * ready for business.
+ * ROT_FLAG_DISABLED: Rotator would not kick in. (ioctl will emit errors).
+ * ROT_FLAG_ENABLED: and when rotation is needed.
+ * (prim video playback)
+ * (UI mirroring on HDMI w/ 0 degree rotator. - just memcpy)
+ * In HDMI UI mirroring, rotator is always used.
+ * Even when w/o orienation change on primary,
+ * we do 0 rotation on HDMI and using rotator buffers.
+ * That is because we might see tearing otherwise. so
+ * we use another buffer (rotator).
+ * When a simple video playback on HDMI, no rotator is being used.(null r).
+ * */
+enum eRotFlags {
+ ROT_FLAG_DISABLED = 0,
+ ROT_FLAG_ENABLED = 1 // needed in rot
+};
+
+/* Used for rotator open.
+ * FIXME that is default, might be configs */
+enum { ROT_NUM_BUFS = 2 };
+
+/* Wait/No wait for waiting for vsync
+ * WAIT - wait for vsync, ignore fb (no need to compose w/ fb)
+ * NO_WAIT - do not wait for vsync and return immediatly since
+ * we need to run composition code */
+enum eWait {
+ WAIT,
+ NO_WAIT
+};
+
+/* The values for is_fg flag for control alpha and transp
+ * IS_FG_OFF means is_fg = 0
+ * IS_FG_SET means is_fg = 1
+ */
+enum eIsFg {
+ IS_FG_OFF = 0,
+ IS_FG_SET = 1
+};
+
+/*
+ * Various mdp flags like PIPE SHARE, DEINTERLACE etc...
+ * kernel/common/linux/msm_mdp.h
+ * INTERLACE_MASK: hardware/qcom/display/libgralloc/badger/fb_priv.h
+ * */
+enum eMdpFlags {
+ OV_MDP_FLAGS_NONE = 0,
+ OV_MDP_PIPE_SHARE = MDP_OV_PIPE_SHARE,
+ OV_MDP_DEINTERLACE = MDP_DEINTERLACE,
+ OV_MDP_PLAY_NOWAIT = MDP_OV_PLAY_NOWAIT,
+ OV_MDP_SECURE_OVERLAY_SESSION = MDP_SECURE_OVERLAY_SESSION
+};
+
+enum eOverlayPipeType {
+ OV_PIPE_TYPE_NULL,
+ OV_PIPE_TYPE_BYPASS,
+ OV_PIPE_TYPE_GENERIC,
+ OV_PIPE_TYPE_HDMI,
+ OV_PIPE_TYPE_M3D_EXTERNAL,
+ OV_PIPE_TYPE_M3D_PRIMARY,
+ OV_PIPE_TYPE_RGB,
+ OV_PIPE_TYPE_S3D_EXTERNAL,
+ OV_PIPE_TYPE_S3D_PRIMARY,
+ OV_PIPE_TYPE_UI_MIRROR
+};
+
+enum eZorder {
+ ZORDER_0,
+ ZORDER_1,
+ ZORDER_2,
+ Z_SYSTEM_ALLOC = 0xFFFF
+};
+
+enum eMdpPipeType {
+ OV_MDP_PIPE_RGB,
+ OV_MDP_PIPE_VG
+};
+
+/* Corresponds to pipes in eDest */
+enum eChannel {
+ CHANNEL_0,
+ CHANNEL_1,
+ CHANNEL_2
+};
+
+// Max pipes via overlay (VG0, VG1, RGB1)
+enum { MAX_PIPES = 3 };
+
+/* Used to identify destination channels and
+ * also 3D channels e.g. when in 3D mode with 2
+ * pipes opened and it is used in get crop/pos 3D
+ *
+ * PLEASE NOTE : DO NOT USE eDest FOR ARRAYS
+ * i.e. args[OV_PIPE1] since it is a BIT MASK
+ * use CHANNELS enum instead. Each OV_PIPEX is
+ * not specific to a display (primary/external).
+ * */
+enum eDest {
+ OV_PIPE0 = 1 << 0,
+ OV_PIPE1 = 1 << 1,
+ OV_PIPE2 = 1 << 2,
+ OV_PIPE_ALL = (OV_PIPE0 | OV_PIPE1 | OV_PIPE2)
+};
+
+/* values for copybit_set_parameter(OVERLAY_TRANSFORM) */
+enum eTransform {
+ /* No rot */
+ OVERLAY_TRANSFORM_0 = 0x0,
+ /* flip source image horizontally */
+ OVERLAY_TRANSFORM_FLIP_H = HAL_TRANSFORM_FLIP_H,
+ /* flip source image vertically */
+ OVERLAY_TRANSFORM_FLIP_V = HAL_TRANSFORM_FLIP_V,
+ /* rotate source image 90 degrees */
+ OVERLAY_TRANSFORM_ROT_90 = HAL_TRANSFORM_ROT_90,
+ /* rotate source image 180 degrees
+ * It is basically bit-or-ed H | V == 0x3 */
+ OVERLAY_TRANSFORM_ROT_180 = HAL_TRANSFORM_ROT_180,
+ /* rotate source image 270 degrees
+ * Basically 180 | 90 == 0x7 */
+ OVERLAY_TRANSFORM_ROT_270 = HAL_TRANSFORM_ROT_270,
+ /* rotate invalid like in Transform.h */
+ OVERLAY_TRANSFORM_INV = 0x80
+};
+
+/* offset and fd are play info */
+struct PlayInfo {
+ PlayInfo() : fd(-1), offset(0) {}
+ PlayInfo(int _fd, uint32_t _offset) :
+ fd(_fd), offset(_offset) {}
+ bool operator==(const PlayInfo& p) {
+ return (fd == p.fd && offset == p.offset);
+ }
+ int fd;
+ uint32_t offset;
+};
+
+// Used to consolidate pipe params
+struct PipeArgs {
+ PipeArgs() : mdpFlags(OV_MDP_FLAGS_NONE),
+ orientation(OVERLAY_TRANSFORM_0),
+ wait(NO_WAIT),
+ zorder(Z_SYSTEM_ALLOC),
+ isFg(IS_FG_OFF),
+ rotFlags(ROT_FLAG_DISABLED){
+ }
+
+ PipeArgs(eMdpFlags f, eTransform o,
+ Whf _whf, eWait w,
+ eZorder z, eIsFg fg, eRotFlags r) :
+ mdpFlags(f),
+ orientation(o),
+ whf(_whf),
+ wait(w),
+ zorder(z),
+ isFg(fg),
+ rotFlags(r) {
+ }
+
+ eMdpFlags mdpFlags; // for mdp_overlay flags PIPE_SHARE, NO_WAIT, etc
+ eTransform orientation; // FIXME docs
+ Whf whf;
+ eWait wait; // flags WAIT/NO_WAIT
+ eZorder zorder; // stage number
+ eIsFg isFg; // control alpha & transp
+ eRotFlags rotFlags;
+ PlayInfo play;
+};
+
+enum eOverlayState{
+ /* No pipes from overlay open */
+ OV_CLOSED = 0,
+
+ /* 2D Video */
+ OV_2D_VIDEO_ON_PANEL,
+ OV_2D_VIDEO_ON_PANEL_TV,
+
+ /* 3D Video on one display (panel or TV) */
+ OV_3D_VIDEO_ON_2D_PANEL,
+ OV_3D_VIDEO_ON_3D_PANEL,
+ OV_3D_VIDEO_ON_3D_TV,
+
+ /* 3D Video on two displays (panel and TV) */
+ OV_3D_VIDEO_ON_2D_PANEL_2D_TV,
+
+ /* UI Mirroring */
+ OV_UI_MIRROR,
+ OV_2D_TRUE_UI_MIRROR,
+ OV_M3D_TRUE_UI_MIRROR, // Not yet supported
+
+ /* Composition Bypass */
+ OV_BYPASS_1_LAYER,
+ OV_BYPASS_2_LAYER,
+ OV_BYPASS_3_LAYER,
+};
+
+inline void setMdpFlags(eMdpFlags& f, eMdpFlags v) {
+ f = static_cast<eMdpFlags>(setBit(f, v));
+}
+
+inline void clearMdpFlags(eMdpFlags& f, eMdpFlags v) {
+ f = static_cast<eMdpFlags>(clrBit(f, v));
+}
+
+// fb 0/1/2
+enum { FB0, FB1, FB2 };
+
+//Panels could be categorized as primary and external
+enum { PRIMARY, EXTERNAL };
+
+//External Panels could use HDMI or WFD
+enum {
+ HDMI = 1,
+ WFD = 2
+};
+
+static int sExtType = HDMI; //HDMI or WFD
+
+//Set by client as HDMI/WFD
+static inline void setExtType(const int& type) {
+ if(type != HDMI || type != WFD) {
+ ALOGE("%s: Unrecognized type %d", __func__, type);
+ return;
+ }
+ sExtType = type;
+}
+
+//Return External panel type set by client.
+static inline int getExtType() {
+ return sExtType;
+}
+
+//Gets the FB number for the external type.
+//As of now, HDMI always has fb1, WFD could use fb1 or fb2
+//Assumes Ext type set by setExtType() from client.
+static int getFBForPanel(int panel) { // PRIMARY OR EXTERNAL
+ switch(panel) {
+ case PRIMARY: return FB0;
+ break;
+ case EXTERNAL:
+ switch(getExtType()) {
+ case HDMI: return FB1;
+ break;
+ case WFD: return FB2;//Hardcoding fb2 for wfd. Will change.
+ break;
+ }
+ break;
+ default:
+ ALOGE("%s: Unrecognized PANEL category %d", __func__, panel);
+ break;
+ }
+ return -1;
+}
+
+// number of rgb pipes bufs (max)
+// 2 for rgb0/1 double bufs
+enum { RGB_PIPE_NUM_BUFS = 2 };
+
+struct ScreenInfo {
+ ScreenInfo() : mFBWidth(0),
+ mFBHeight(0),
+ mFBbpp(0),
+ mFBystride(0) {}
+ void dump(const char* const s) const;
+ uint32_t mFBWidth;
+ uint32_t mFBHeight;
+ uint32_t mFBbpp;
+ uint32_t mFBystride;
+};
+
+int getMdpFormat(int format);
+int getRotOutFmt(uint32_t format);
+/* flip is upside down and such. V, H flip
+ * rotation is 90, 180 etc
+ * It returns MDP related enum/define that match rot+flip*/
+int getMdpOrient(eTransform rotation);
+uint32_t getSize(const Whf& whf);
+uint32_t getSizeByMdp(const Whf& whf);
+const char* getFormatString(uint32_t format);
+const char* getStateString(eOverlayState state);
+
+inline int setWait(eWait wait, int flags) {
+ return (wait == WAIT) ?
+ flags &= ~MDP_OV_PLAY_NOWAIT :
+ flags |= MDP_OV_PLAY_NOWAIT;
+}
+/* possible overlay formats libhardware/include/hardware/hardware.h */
+enum eFormat {
+ OVERLAY_FORMAT_RGBA_8888 = HAL_PIXEL_FORMAT_RGBA_8888,
+ OVERLAY_FORMAT_RGB_565 = HAL_PIXEL_FORMAT_RGB_565,
+ OVERLAY_FORMAT_BGRA_8888 = HAL_PIXEL_FORMAT_BGRA_8888,
+ OVERLAY_FORMAT_YCbYCr_422_I = 0x14,
+ OVERLAY_FORMAT_CbYCrY_422_I = 0x16,
+ OVERLAY_FORMAT_DEFAULT = 99 // The actual color format is
+ // determined by the overlay
+};
+
+// Cannot use HW_OVERLAY_MAGNIFICATION_LIMIT, since at the time
+// of integration, HW_OVERLAY_MAGNIFICATION_LIMIT was a define
+enum { HW_OV_MAGNIFICATION_LIMIT = 20,
+ HW_OV_MINIFICATION_LIMIT = 8
+};
+
+inline bool rotated(int orie) {
+ return (orie == OVERLAY_TRANSFORM_ROT_90 ||
+ orie == OVERLAY_TRANSFORM_ROT_270);
+}
+
+/* used by crop funcs in order to
+ * normalizes the crop values to be all even */
+void normalizeCrop(uint32_t& xy, uint32_t& wh);
+
+template <class T>
+ inline void memset0(T& t) { ::memset(&t, 0, sizeof(T)); }
+
+template <class ROT, class MDP>
+ inline void swapOVRotWidthHeight(ROT& rot, MDP& mdp)
+ {
+ mdp.swapSrcWH();
+ mdp.swapSrcRectWH();
+ rot.swapDstWH();
+ }
+
+template <class T> inline void swap ( T& a, T& b )
+{
+ T c(a); a=b; b=c;
+}
+
+inline int alignup(int value, int a) {
+ //if align = 0, return the value. Else, do alignment.
+ return a ? ((((value - 1) / a) + 1) * a) : value;
+}
+
+// FIXME that align should replace the upper one.
+inline int align(int value, int a) {
+ //if align = 0, return the value. Else, do alignment.
+ return a ? ((value + (a-1)) & ~(a-1)) : value;
+}
+
+
+template <class MDP>
+inline utils::Dim getSrcRectDim(const MDP& ov) {
+ return utils::Dim(ov.src_rect.x,
+ ov.src_rect.y,
+ ov.src_rect.w,
+ ov.src_rect.h);
+}
+
+template <class MDP>
+inline utils::Whf getSrcWhf(const MDP& ov) {
+ return utils::Whf(ov.src.width,
+ ov.src.height,
+ ov.src.format);
+}
+template <class MDP>
+inline void setSrcRectDim(MDP& ov, const utils::Dim& d) {
+ ov.src_rect.x = d.x;
+ ov.src_rect.y = d.y;
+ ov.src_rect.w = d.w;
+ ov.src_rect.h = d.h;
+}
+template <class MDP>
+inline void setSrcWhf(MDP& ov, const utils::Whf& whf) {
+ ov.src.width = whf.w;
+ ov.src.height = whf.h;
+ ov.src.format = whf.format;
+}
+
+enum eRotOutFmt {
+ ROT_OUT_FMT_DEFAULT,
+ ROT_OUT_FMT_Y_CRCB_H2V2
+};
+
+template <int ROT_OUT_FMT> struct RotOutFmt;
+
+// FIXME, taken from gralloc_priv.h. Need to
+// put it back as soon as overlay takes place of the old one
+/* possible formats for 3D content*/
+enum {
+ HAL_NO_3D = 0x0000,
+ HAL_3D_IN_SIDE_BY_SIDE_L_R = 0x10000,
+ HAL_3D_IN_TOP_BOTTOM = 0x20000,
+ HAL_3D_IN_INTERLEAVE = 0x40000,
+ HAL_3D_IN_SIDE_BY_SIDE_R_L = 0x80000,
+ HAL_3D_OUT_SIDE_BY_SIDE = 0x1000,
+ HAL_3D_OUT_TOP_BOTTOM = 0x2000,
+ HAL_3D_OUT_INTERLEAVE = 0x4000,
+ HAL_3D_OUT_MONOSCOPIC = 0x8000
+};
+
+enum { HAL_3D_OUT_SBS_MASK =
+ HAL_3D_OUT_SIDE_BY_SIDE >> overlay::utils::SHIFT_OUT_3D,
+ HAL_3D_OUT_TOP_BOT_MASK =
+ HAL_3D_OUT_TOP_BOTTOM >> overlay::utils::SHIFT_OUT_3D,
+ HAL_3D_OUT_INTERL_MASK =
+ HAL_3D_OUT_INTERLEAVE >> overlay::utils::SHIFT_OUT_3D,
+ HAL_3D_OUT_MONOS_MASK =
+ HAL_3D_OUT_MONOSCOPIC >> overlay::utils::SHIFT_OUT_3D
+};
+
+
+inline bool isYuv(uint32_t format) {
+ switch(format){
+ case MDP_Y_CBCR_H2V1:
+ case MDP_Y_CBCR_H2V2:
+ case MDP_Y_CRCB_H2V2:
+ case MDP_Y_CRCB_H2V2_TILE:
+ case MDP_Y_CBCR_H2V2_TILE:
+ return true;
+ default:
+ return false;
+ }
+ return false;
+}
+
+inline bool isRgb(uint32_t format) {
+ switch(format) {
+ case MDP_RGBA_8888:
+ case MDP_BGRA_8888:
+ case MDP_RGBX_8888:
+ case MDP_RGB_565:
+ return true;
+ default:
+ return false;
+ }
+ return false;
+}
+
+inline bool isValidDest(eDest dest)
+{
+ if ((OV_PIPE0 & dest) ||
+ (OV_PIPE1 & dest) ||
+ (OV_PIPE2 & dest)) {
+ return true;
+ }
+ return false;
+}
+
+inline const char* getFormatString(uint32_t format){
+ static const char* const formats[] = {
+ "MDP_RGB_565",
+ "MDP_XRGB_8888",
+ "MDP_Y_CBCR_H2V2",
+ "MDP_ARGB_8888",
+ "MDP_RGB_888",
+ "MDP_Y_CRCB_H2V2",
+ "MDP_YCRYCB_H2V1",
+ "MDP_Y_CRCB_H2V1",
+ "MDP_Y_CBCR_H2V1",
+ "MDP_RGBA_8888",
+ "MDP_BGRA_8888",
+ "MDP_RGBX_8888",
+ "MDP_Y_CRCB_H2V2_TILE",
+ "MDP_Y_CBCR_H2V2_TILE",
+ "MDP_Y_CR_CB_H2V2",
+ "MDP_Y_CB_CR_H2V2",
+ "MDP_IMGTYPE_LIMIT",
+ "MDP_BGR_565",
+ "MDP_FB_FORMAT",
+ "MDP_IMGTYPE_LIMIT2"
+ };
+ OVASSERT(format < sizeof(formats) / sizeof(formats[0]),
+ "getFormatString wrong fmt %d", format);
+ return formats[format];
+}
+
+inline const char* getStateString(eOverlayState state){
+ switch (state) {
+ case OV_CLOSED:
+ return "OV_CLOSED";
+ case OV_2D_VIDEO_ON_PANEL:
+ return "OV_2D_VIDEO_ON_PANEL";
+ case OV_2D_VIDEO_ON_PANEL_TV:
+ return "OV_2D_VIDEO_ON_PANEL_TV";
+ case OV_3D_VIDEO_ON_2D_PANEL:
+ return "OV_3D_VIDEO_ON_2D_PANEL";
+ case OV_3D_VIDEO_ON_3D_PANEL:
+ return "OV_3D_VIDEO_ON_3D_PANEL";
+ case OV_3D_VIDEO_ON_3D_TV:
+ return "OV_3D_VIDEO_ON_3D_TV";
+ case OV_3D_VIDEO_ON_2D_PANEL_2D_TV:
+ return "OV_3D_VIDEO_ON_2D_PANEL_2D_TV";
+ case OV_UI_MIRROR:
+ return "OV_UI_MIRROR";
+ case OV_2D_TRUE_UI_MIRROR:
+ return "OV_2D_TRUE_UI_MIRROR";
+ case OV_BYPASS_1_LAYER:
+ return "OV_BYPASS_1_LAYER";
+ case OV_BYPASS_2_LAYER:
+ return "OV_BYPASS_2_LAYER";
+ case OV_BYPASS_3_LAYER:
+ return "OV_BYPASS_3_LAYER";
+ default:
+ return "UNKNOWN_STATE";
+ }
+ return "BAD_STATE";
+}
+
+inline uint32_t getSizeByMdp(const Whf& whf) {
+ Whf _whf(whf);
+ int fmt = getMdpFormat(whf.format);
+ OVASSERT(-1 != fmt, "getSizeByMdp error in format %d",
+ whf.format);
+ _whf.format = fmt;
+ return getSize(_whf);
+}
+
+inline void Whf::dump() const {
+ ALOGE("== Dump WHF w=%d h=%d f=%d s=%d start/end ==",
+ w, h, format, size);
+}
+
+inline void Dim::dump() const {
+ ALOGE("== Dump Dim x=%d y=%d w=%d h=%d start/end ==", x, y, w, h);
+}
+
+inline int getMdpOrient(eTransform rotation) {
+ ALOGE_IF(DEBUG_OVERLAY, "%s: rot=%d", __FUNCTION__, rotation);
+ switch(int(rotation))
+ {
+ case OVERLAY_TRANSFORM_0 : return 0;
+ case HAL_TRANSFORM_FLIP_V: return MDP_FLIP_UD;
+ case HAL_TRANSFORM_FLIP_H: return MDP_FLIP_LR;
+ case HAL_TRANSFORM_ROT_90: return MDP_ROT_90;
+ case HAL_TRANSFORM_ROT_90|HAL_TRANSFORM_FLIP_V:
+ return MDP_ROT_90|MDP_FLIP_LR;
+ case HAL_TRANSFORM_ROT_90|HAL_TRANSFORM_FLIP_H:
+ return MDP_ROT_90|MDP_FLIP_UD;
+ case HAL_TRANSFORM_ROT_180: return MDP_ROT_180;
+ case HAL_TRANSFORM_ROT_270: return MDP_ROT_270;
+ default:
+ ALOGE("%s: invalid rotation value (value = 0x%x",
+ __FUNCTION__, rotation);
+ }
+ return -1;
+}
+
+inline int getRotOutFmt(uint32_t format) {
+ switch (format) {
+ case MDP_Y_CRCB_H2V2_TILE:
+ return MDP_Y_CRCB_H2V2;
+ case MDP_Y_CBCR_H2V2_TILE:
+ return MDP_Y_CBCR_H2V2;
+ case MDP_Y_CB_CR_H2V2:
+ return MDP_Y_CBCR_H2V2;
+ default:
+ return format;
+ }
+ // not reached
+ OVASSERT(false, "%s not reached", __FUNCTION__);
+ return -1;
+}
+
+template<>
+struct RotOutFmt<ROT_OUT_FMT_DEFAULT>
+{
+ static inline int fmt(uint32_t format) {
+ return getRotOutFmt(format);
+ }
+};
+
+template<>
+struct RotOutFmt<ROT_OUT_FMT_Y_CRCB_H2V2>
+{
+ static inline int fmt(uint32_t) {
+ return MDP_Y_CRCB_H2V2;
+ }
+};
+
+inline uint32_t getColorFormat(uint32_t format)
+{
+ return (format == HAL_PIXEL_FORMAT_YV12) ?
+ format : colorFormat(format);
+}
+
+// FB0
+template <int CHAN>
+inline Dim getPositionS3DImpl(const Whf& whf)
+{
+ switch (whf.format & OUTPUT_3D_MASK)
+ {
+ case HAL_3D_OUT_SBS_MASK:
+ // x, y, w, h
+ return Dim(0, 0, whf.w/2, whf.h);
+ case HAL_3D_OUT_TOP_BOT_MASK:
+ return Dim(0, 0, whf.w, whf.h/2);
+ case HAL_3D_OUT_MONOS_MASK:
+ return Dim();
+ case HAL_3D_OUT_INTERL_MASK:
+ // FIXME error?
+ ALOGE("%s HAL_3D_OUT_INTERLEAVE_MASK", __FUNCTION__);
+ return Dim();
+ default:
+ ALOGE("%s Unsupported 3D output format %d", __FUNCTION__,
+ whf.format);
+ }
+ return Dim();
+}
+
+template <>
+inline Dim getPositionS3DImpl<utils::OV_PIPE1>(const Whf& whf)
+{
+ switch (whf.format & OUTPUT_3D_MASK)
+ {
+ case HAL_3D_OUT_SBS_MASK:
+ return Dim(whf.w/2, 0, whf.w/2, whf.h);
+ case HAL_3D_OUT_TOP_BOT_MASK:
+ return Dim(0, whf.h/2, whf.w, whf.h/2);
+ case HAL_3D_OUT_MONOS_MASK:
+ return Dim(0, 0, whf.w, whf.h);
+ case HAL_3D_OUT_INTERL_MASK:
+ // FIXME error?
+ ALOGE("%s HAL_3D_OUT_INTERLEAVE_MASK", __FUNCTION__);
+ return Dim();
+ default:
+ ALOGE("%s Unsupported 3D output format %d", __FUNCTION__,
+ whf.format);
+ }
+ return Dim();
+}
+
+template <int CHAN>
+inline bool getPositionS3D(const Whf& whf, Dim& out) {
+ out = getPositionS3DImpl<CHAN>(whf);
+ return (out != Dim());
+}
+
+template <int CHAN>
+inline Dim getCropS3DImpl(const Dim& in, uint32_t fmt) {
+ switch (fmt & INPUT_3D_MASK)
+ {
+ case HAL_3D_IN_SIDE_BY_SIDE_L_R:
+ return Dim(0, 0, in.w/2, in.h);
+ case HAL_3D_IN_SIDE_BY_SIDE_R_L:
+ return Dim(in.w/2, 0, in.w/2, in.h);
+ case HAL_3D_IN_TOP_BOTTOM:
+ return Dim(0, 0, in.w, in.h/2);
+ case HAL_3D_IN_INTERLEAVE:
+ ALOGE("%s HAL_3D_IN_INTERLEAVE", __FUNCTION__);
+ break;
+ default:
+ ALOGE("%s Unsupported 3D format %d", __FUNCTION__, fmt);
+ break;
+ }
+ return Dim();
+}
+
+template <>
+inline Dim getCropS3DImpl<utils::OV_PIPE1>(const Dim& in, uint32_t fmt) {
+ switch (fmt & INPUT_3D_MASK)
+ {
+ case HAL_3D_IN_SIDE_BY_SIDE_L_R:
+ return Dim(in.w/2, 0, in.w/2, in.h);
+ case HAL_3D_IN_SIDE_BY_SIDE_R_L:
+ return Dim(0, 0, in.w/2, in.h);
+ case HAL_3D_IN_TOP_BOTTOM:
+ return Dim(0, in.h/2, in.w, in.h/2);
+ case HAL_3D_IN_INTERLEAVE:
+ ALOGE("%s HAL_3D_IN_INTERLEAVE", __FUNCTION__);
+ break;
+ default:
+ ALOGE("%s Unsupported 3D format %d", __FUNCTION__, fmt);
+ break;
+ }
+ return Dim();
+}
+
+template <int CHAN>
+inline bool getCropS3D(const Dim& in, Dim& out, uint32_t fmt)
+{
+ out = getCropS3DImpl<CHAN>(in, fmt);
+ return (out != Dim());
+}
+
+template <class Type>
+void swapWidthHeight(Type& width, Type& height) {
+ Type tmp = width;
+ width = height;
+ height = tmp;
+}
+
+inline void ScreenInfo::dump(const char* const s) const {
+ ALOGE("== Dump %s ScreenInfo w=%d h=%d"
+ " bpp=%d stride=%d start/end ==",
+ s, mFBWidth, mFBHeight, mFBbpp, mFBystride);
+}
+
+inline void setSrcRectDim(const overlay::utils::Dim d,
+ mdp_overlay& ov) {
+ ov.src_rect.x = d.x;
+ ov.src_rect.y = d.y;
+ ov.src_rect.w = d.w;
+ ov.src_rect.h = d.h;
+}
+
+inline void setDstRectDim(const overlay::utils::Dim d,
+ mdp_overlay& ov) {
+ ov.dst_rect.x = d.x;
+ ov.dst_rect.y = d.y;
+ ov.dst_rect.w = d.w;
+ ov.dst_rect.h = d.h;
+}
+
+inline overlay::utils::Whf getSrcWhf(const mdp_overlay& ov) {
+ return overlay::utils::Whf(ov.src.width,
+ ov.src.height,
+ ov.src.format);
+}
+
+inline overlay::utils::Dim getSrcRectDim(const mdp_overlay& ov) {
+ return overlay::utils::Dim(ov.src_rect.x,
+ ov.src_rect.y,
+ ov.src_rect.w,
+ ov.src_rect.h);
+}
+
+inline overlay::utils::Dim getDstRectDim(const mdp_overlay& ov) {
+ return overlay::utils::Dim(ov.dst_rect.x,
+ ov.dst_rect.y,
+ ov.dst_rect.w,
+ ov.dst_rect.h);
+}
+
+
+} // namespace utils ends
+
+//--------------------Class Res stuff (namespace overlay only) -----------
+
+class Res {
+public:
+ // /dev/graphics/fb%u
+ static const char* const devTemplate;
+ // /dev/msm_rotator
+ static const char* const rotPath;
+ // /sys/class/graphics/fb1/format_3d
+ static const char* const format3DFile;
+ // /sys/class/graphics/fb1/3d_present
+ static const char* const edid3dInfoFile;
+ // /sys/devices/platform/mipi_novatek.0/enable_3d_barrier
+ static const char* const barrierFile;
+};
+
+
+//--------------------Class OvFD stuff (namespace overlay only) -----------
+
+class OvFD;
+
+/* helper function to open by using fbnum */
+bool open(OvFD& fd, uint32_t fbnum, const char* const dev,
+ int flags = O_RDWR);
+
+/*
+* Holds one FD
+* Dtor will NOT close the underlying FD.
+* That enables us to copy that object around
+* */
+class OvFD {
+public:
+ /* Ctor */
+ explicit OvFD();
+
+ /* dtor will NOT close the underlying FD */
+ ~OvFD();
+
+ /* Open fd using the path given by dev.
+ * return false in failure */
+ bool open(const char* const dev,
+ int flags = O_RDWR);
+
+ /* populate path */
+ void setPath(const char* const dev);
+
+ /* Close fd if we have a valid fd. */
+ bool close();
+
+ /* returns underlying fd.*/
+ int getFD() const;
+
+ /* returns true if fd is valid */
+ bool valid() const;
+
+ /* like operator= */
+ void copy(int fd);
+
+ /* dump the state of the instance */
+ void dump() const;
+private:
+ /* helper enum for determine valid/invalid fd */
+ enum { INVAL = -1 };
+
+ /* actual os fd */
+ int mFD;
+
+ /* path, for debugging */
+ char mPath[utils::MAX_PATH_LEN];
+};
+
+//-------------------Inlines--------------------------
+
+inline bool open(OvFD& fd, uint32_t fbnum, const char* const dev, int flags)
+{
+ char dev_name[64] = {0};
+ snprintf(dev_name, sizeof(dev_name), dev, fbnum);
+ return fd.open(dev_name, flags);
+}
+
+inline OvFD::OvFD() : mFD (INVAL) {
+ mPath[0] = 0;
+}
+
+inline OvFD::~OvFD() { /* no op in the meantime */ }
+
+inline bool OvFD::open(const char* const dev, int flags)
+{
+ mFD = ::open(dev, flags, 0);
+ if (mFD < 0) {
+ // FIXME errno, strerror in bionic?
+ ALOGE("Cant open device %s err=%d", dev, errno);
+ return false;
+ }
+ setPath(dev);
+ return true;
+}
+
+inline void OvFD::setPath(const char* const dev)
+{
+ ::strncpy(mPath, dev, utils::MAX_PATH_LEN);
+}
+
+inline bool OvFD::close()
+{
+ int ret = 0;
+ if(valid()) {
+ ret = ::close(mFD);
+ mFD = INVAL;
+ }
+ return (ret == 0);
+}
+
+inline bool OvFD::valid() const
+{
+ return (mFD != INVAL);
+}
+
+inline int OvFD::getFD() const { return mFD; }
+
+inline void OvFD::copy(int fd) {
+ mFD = fd;
+}
+
+inline void OvFD::dump() const
+{
+ ALOGE("== Dump OvFD fd=%d path=%s start/end ==",
+ mFD, mPath);
+}
+
+//--------------- class OvFD stuff ends ---------------------
+
+} // overlay
+
+
+#endif // OVERLAY_UTILS_H
diff --git a/liboverlay/pipes/overlay3DPipe.h b/liboverlay/pipes/overlay3DPipe.h
new file mode 100644
index 0000000..dce4bf4
--- /dev/null
+++ b/liboverlay/pipes/overlay3DPipe.h
@@ -0,0 +1,617 @@
+/*
+* Copyright (c) 2011-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 OVERLAY_M3D_EXT_PIPE_H
+#define OVERLAY_M3D_EXT_PIPE_H
+
+#include "overlayGenPipe.h"
+#include "overlayUtils.h"
+
+namespace overlay {
+
+///////////// M3DExt Pipe ////////////////////////////
+/**
+* A specific impl of GenericPipe for 3D.
+* Whenever needed to have a pass through - we do it.
+* If there is a special need for special/diff behavior
+* do it here
+* PANEL is always EXTERNAL for this pipe.
+* CHAN = 0,1 it's either Channel 1 or channel 2 needed for
+* 3D crop and position */
+template <int CHAN>
+class M3DExtPipe : utils::NoCopy {
+public:
+ /* Please look at overlayGenPipe.h for info */
+ explicit M3DExtPipe();
+ ~M3DExtPipe();
+ bool open(RotatorBase* rot);
+ bool close();
+ bool commit();
+ void setId(int id);
+ void setMemoryId(int id);
+ bool queueBuffer(uint32_t offset);
+ bool dequeueBuffer(void*& buf);
+ bool waitForVsync();
+ bool setCrop(const utils::Dim& d);
+ bool start(const utils::PipeArgs& args);
+ bool setPosition(const utils::Dim& dim);
+ bool setParameter(const utils::Params& param);
+ bool setSource(const utils::PipeArgs& args);
+ const utils::PipeArgs& getArgs() const;
+ utils::eOverlayPipeType getOvPipeType() const;
+ void dump() const;
+private:
+ overlay::GenericPipe<utils::EXTERNAL> mM3d;
+ // Cache the M3D format
+ uint32_t mM3Dfmt;
+};
+
+///////////// M3DPrimary Pipe ////////////////////////////
+/**
+* A specific impl of GenericPipe for 3D.
+* Whenever needed to have a pass through - we do it.
+* If there is a special need for special/diff behavior
+* do it here
+* PANEL is always PRIMARY for this pipe.
+* CHAN = 0,1 it's either Channel 1 or channel 2 needed for
+* 3D crop and position */
+template <int CHAN>
+class M3DPrimaryPipe : utils::NoCopy {
+public:
+ /* Please look at overlayGenPipe.h for info */
+ explicit M3DPrimaryPipe();
+ ~M3DPrimaryPipe();
+ bool open(RotatorBase* rot);
+ bool close();
+ bool commit();
+ void setId(int id);
+ void setMemoryId(int id);
+ bool queueBuffer(uint32_t offset);
+ bool dequeueBuffer(void*& buf);
+ bool waitForVsync();
+ bool setCrop(const utils::Dim& d);
+ bool start(const utils::PipeArgs& args);
+ bool setPosition(const utils::Dim& dim);
+ bool setParameter(const utils::Params& param);
+ bool setSource(const utils::PipeArgs& args);
+ const utils::PipeArgs& getArgs() const;
+ utils::eOverlayPipeType getOvPipeType() const;
+ void dump() const;
+private:
+ overlay::GenericPipe<utils::PRIMARY> mM3d;
+ // Cache the M3D format
+ uint32_t mM3Dfmt;
+};
+
+///////////// S3DExt Pipe ////////////////////////////////
+/**
+* A specific impl of GenericPipe for 3D.
+* Whenever needed to have a pass through - we do it.
+* If there is a special need for special/diff behavior
+* do it here.
+* PANEL is always EXTERNAL for this pipe.
+* CHAN = 0,1 it's either Channel 1 or channel 2 needed for
+* 3D crop and position */
+template <int CHAN>
+class S3DExtPipe : utils::NoCopy {
+public:
+ /* Please look at overlayGenPipe.h for info */
+ explicit S3DExtPipe();
+ ~S3DExtPipe();
+ bool open(RotatorBase* rot);
+ bool close();
+ bool commit();
+ void setId(int id);
+ void setMemoryId(int id);
+ bool queueBuffer(uint32_t offset);
+ bool dequeueBuffer(void*& buf);
+ bool waitForVsync();
+ bool setCrop(const utils::Dim& d);
+ bool start(const utils::PipeArgs& args);
+ bool setPosition(const utils::Dim& dim);
+ bool setParameter(const utils::Params& param);
+ bool setSource(const utils::PipeArgs& args);
+ const utils::PipeArgs& getArgs() const;
+ utils::eOverlayPipeType getOvPipeType() const;
+ void dump() const;
+private:
+ overlay::GenericPipe<utils::EXTERNAL> mS3d;
+ // Cache the 3D format
+ uint32_t mS3Dfmt;
+};
+
+///////////// S3DPrimary Pipe ////////////////////////////
+/**
+* A specific impl of GenericPipe for 3D.
+* Whenever needed to have a pass through - we do it.
+* If there is a special need for special/diff behavior
+* do it here
+* PANEL is always PRIMARY for this pipe.
+* CHAN = 0,1 it's either Channel 1 or channel 2 needed for
+* 3D crop and position */
+template <int CHAN>
+class S3DPrimaryPipe : utils::NoCopy {
+public:
+ /* Please look at overlayGenPipe.h for info */
+ explicit S3DPrimaryPipe();
+ ~S3DPrimaryPipe();
+ bool open(RotatorBase* rot);
+ bool close();
+ bool commit();
+ void setId(int id);
+ void setMemoryId(int id);
+ bool queueBuffer(uint32_t offset);
+ bool dequeueBuffer(void*& buf);
+ bool waitForVsync();
+ bool setCrop(const utils::Dim& d);
+ bool start(const utils::PipeArgs& args);
+ bool setPosition(const utils::Dim& dim);
+ bool setParameter(const utils::Params& param);
+ bool setSource(const utils::PipeArgs& args);
+ const utils::PipeArgs& getArgs() const;
+ utils::eOverlayPipeType getOvPipeType() const;
+ void dump() const;
+private:
+ /* needed for 3D related IOCTL */
+ MdpCtrl3D mCtrl3D;
+ overlay::GenericPipe<utils::PRIMARY> mS3d;
+ // Cache the 3D format
+ uint32_t mS3Dfmt;
+};
+
+
+
+
+//------------------------Inlines and Templates--------------------------
+
+
+///////////// M3DExt Pipe ////////////////////////////
+template <int CHAN>
+inline M3DExtPipe<CHAN>::M3DExtPipe() : mM3Dfmt(0) {}
+template <int CHAN>
+inline M3DExtPipe<CHAN>::~M3DExtPipe() { close(); }
+template <int CHAN>
+inline bool M3DExtPipe<CHAN>::open(RotatorBase* rot) {
+ ALOGE_IF(DEBUG_OVERLAY, "M3DExtPipe open");
+ if(!mM3d.open(rot)) {
+ ALOGE("3Dpipe failed to open");
+ return false;
+ }
+ return true;
+}
+template <int CHAN>
+inline bool M3DExtPipe<CHAN>::close() {
+ return mM3d.close();
+}
+template <int CHAN>
+inline bool M3DExtPipe<CHAN>::commit() { return mM3d.commit(); }
+template <int CHAN>
+inline void M3DExtPipe<CHAN>::setId(int id) { mM3d.setId(id); }
+template <int CHAN>
+inline void M3DExtPipe<CHAN>::setMemoryId(int id) { mM3d.setMemoryId(id); }
+template <int CHAN>
+inline bool M3DExtPipe<CHAN>::queueBuffer(uint32_t offset) {
+ return mM3d.queueBuffer(offset); }
+template <int CHAN>
+inline bool M3DExtPipe<CHAN>::dequeueBuffer(void*& buf) {
+ return mM3d.dequeueBuffer(buf); }
+template <int CHAN>
+inline bool M3DExtPipe<CHAN>::waitForVsync() {
+ return mM3d.waitForVsync(); }
+template <int CHAN>
+inline bool M3DExtPipe<CHAN>::setCrop(const utils::Dim& d) {
+ utils::Dim _dim;
+ if(!utils::getCropS3D<CHAN>(d, _dim, mM3Dfmt)){
+ ALOGE("M3DExtPipe setCrop failed to getCropS3D");
+ _dim = d;
+ }
+ return mM3d.setCrop(_dim);
+}
+template <int CHAN>
+inline bool M3DExtPipe<CHAN>::start(const utils::PipeArgs& args) {
+ if(!mM3d.start(args)) {
+ ALOGE("M3DExtPipe start failed");
+ return false;
+ }
+ return true;
+}
+template <int CHAN>
+inline bool M3DExtPipe<CHAN>::setPosition(const utils::Dim& d) {
+ utils::Dim _dim;
+ // original setPositionHandleState has getPositionS3D(...,true)
+ // which means format is HAL_3D_OUT_SBS_MASK
+ // HAL_3D_OUT_SBS_MASK is 0x1000 >> 12 == 0x1 as the orig
+ // code suggets
+ utils::Whf _whf(mM3d.getScreenInfo().mFBWidth,
+ mM3d.getScreenInfo().mFBHeight,
+ mM3Dfmt);
+ if(!utils::getPositionS3D<CHAN>(_whf, _dim)) {
+ ALOGE("S3DPrimaryPipe setPosition err in getPositionS3D");
+ _dim = d;
+ }
+ return mM3d.setPosition(_dim);
+}
+template <int CHAN>
+inline bool M3DExtPipe<CHAN>::setParameter(const utils::Params& param) {
+ return mM3d.setParameter(param);
+}
+template <int CHAN>
+inline bool M3DExtPipe<CHAN>::setSource(const utils::PipeArgs& args)
+{
+ // extract 3D fmt
+ mM3Dfmt = utils::format3DInput(utils::getS3DFormat(args.whf.format)) |
+ utils::HAL_3D_OUT_MONOS_MASK;
+ if(mM3d.isClosed()){
+ if(!this->start(args)) {
+ ALOGE("M3DExtPipe setSource failed to start");
+ return false;
+ }
+ }
+ return mM3d.setSource(args);
+}
+template <int CHAN>
+inline const utils::PipeArgs& M3DExtPipe<CHAN>::getArgs() const {
+ return mM3d.getArgs();
+}
+template <int CHAN>
+inline utils::eOverlayPipeType M3DExtPipe<CHAN>::getOvPipeType() const {
+ return utils::OV_PIPE_TYPE_M3D_EXTERNAL;
+}
+template <int CHAN>
+inline void M3DExtPipe<CHAN>::dump() const {
+ ALOGE("M3DExtPipe Pipe fmt=%d", mM3Dfmt);
+ mM3d.dump();
+}
+
+
+///////////// M3DPrimary Pipe ////////////////////////////
+template <int CHAN>
+inline M3DPrimaryPipe<CHAN>::M3DPrimaryPipe() : mM3Dfmt(0) {}
+template <int CHAN>
+inline M3DPrimaryPipe<CHAN>::~M3DPrimaryPipe() { close(); }
+template <int CHAN>
+inline bool M3DPrimaryPipe<CHAN>::open(RotatorBase* rot) {
+ ALOGE_IF(DEBUG_OVERLAY, "M3DPrimaryPipe open");
+ if(!mM3d.open(rot)) {
+ ALOGE("3Dpipe failed to open");
+ return false;
+ }
+ return true;
+}
+template <int CHAN>
+inline bool M3DPrimaryPipe<CHAN>::close() {
+ return mM3d.close();
+}
+template <int CHAN>
+inline bool M3DPrimaryPipe<CHAN>::commit() { return mM3d.commit(); }
+template <int CHAN>
+inline void M3DPrimaryPipe<CHAN>::setId(int id) { mM3d.setId(id); }
+template <int CHAN>
+inline void M3DPrimaryPipe<CHAN>::setMemoryId(int id) { mM3d.setMemoryId(id); }
+template <int CHAN>
+inline bool M3DPrimaryPipe<CHAN>::queueBuffer(uint32_t offset) {
+ return mM3d.queueBuffer(offset); }
+template <int CHAN>
+inline bool M3DPrimaryPipe<CHAN>::dequeueBuffer(void*& buf) {
+ return mM3d.dequeueBuffer(buf); }
+template <int CHAN>
+inline bool M3DPrimaryPipe<CHAN>::waitForVsync() {
+ return mM3d.waitForVsync(); }
+template <int CHAN>
+inline bool M3DPrimaryPipe<CHAN>::setCrop(const utils::Dim& d) {
+ utils::Dim _dim;
+ if(!utils::getCropS3D<CHAN>(d, _dim, mM3Dfmt)){
+ ALOGE("M3DPrimaryPipe setCrop failed to getCropS3D");
+ _dim = d;
+ }
+ return mM3d.setCrop(_dim);
+}
+template <int CHAN>
+inline bool M3DPrimaryPipe<CHAN>::start(const utils::PipeArgs& args) {
+ if(!mM3d.start(args)) {
+ ALOGE("M3DPrimaryPipe start failed");
+ return false;
+ }
+ return true;
+}
+template <int CHAN>
+inline bool M3DPrimaryPipe<CHAN>::setPosition(const utils::Dim& d) {
+ return mM3d.setPosition(d);
+}
+template <int CHAN>
+inline bool M3DPrimaryPipe<CHAN>::setParameter(const utils::Params& param) {
+ return mM3d.setParameter(param);
+}
+template <int CHAN>
+inline bool M3DPrimaryPipe<CHAN>::setSource(const utils::PipeArgs& args)
+{
+ // extract 3D fmt
+ mM3Dfmt = utils::format3DInput(utils::getS3DFormat(args.whf.format)) |
+ utils::HAL_3D_OUT_MONOS_MASK;
+ if (mM3d.isClosed()) {
+ if (!this->start(args)) {
+ ALOGE("M3DPrimaryPipe setSource failed to start");
+ return false;
+ }
+ }
+ return mM3d.setSource(args);
+}
+template <int CHAN>
+inline const utils::PipeArgs& M3DPrimaryPipe<CHAN>::getArgs() const {
+ return mM3d.getArgs();
+}
+template <int CHAN>
+inline utils::eOverlayPipeType M3DPrimaryPipe<CHAN>::getOvPipeType() const {
+ return utils::OV_PIPE_TYPE_M3D_PRIMARY;
+}
+template <int CHAN>
+inline void M3DPrimaryPipe<CHAN>::dump() const {
+ ALOGE("M3DPrimaryPipe Pipe fmt=%d", mM3Dfmt);
+ mM3d.dump();
+}
+
+///////////// S3DExt Pipe ////////////////////////////////
+template <int CHAN>
+inline S3DExtPipe<CHAN>::S3DExtPipe() : mS3Dfmt(0) {}
+template <int CHAN>
+inline S3DExtPipe<CHAN>::~S3DExtPipe() { close(); }
+template <int CHAN>
+inline bool S3DExtPipe<CHAN>::open(RotatorBase* rot) {
+ ALOGE_IF(DEBUG_OVERLAY, "S3DExtPipe open");
+ if(!mS3d.open(rot)) {
+ ALOGE("3Dpipe failed to open");
+ return false;
+ }
+ return true;
+}
+template <int CHAN>
+inline bool S3DExtPipe<CHAN>::close() {
+ if(!utils::send3DInfoPacket(0)) {
+ ALOGE("S3DExtPipe close failed send3D info packet");
+ }
+ return mS3d.close();
+}
+template <int CHAN>
+inline bool S3DExtPipe<CHAN>::commit() { return mS3d.commit(); }
+template <int CHAN>
+inline void S3DExtPipe<CHAN>::setId(int id) { mS3d.setId(id); }
+template <int CHAN>
+inline void S3DExtPipe<CHAN>::setMemoryId(int id) { mS3d.setMemoryId(id); }
+template <int CHAN>
+inline bool S3DExtPipe<CHAN>::queueBuffer(uint32_t offset) {
+ //this->dump();
+ return mS3d.queueBuffer(offset); }
+template <int CHAN>
+inline bool S3DExtPipe<CHAN>::dequeueBuffer(void*& buf) {
+ return mS3d.dequeueBuffer(buf); }
+template <int CHAN>
+inline bool S3DExtPipe<CHAN>::waitForVsync() {
+ return mS3d.waitForVsync(); }
+template <int CHAN>
+inline bool S3DExtPipe<CHAN>::setCrop(const utils::Dim& d) {
+ utils::Dim _dim;
+ if(!utils::getCropS3D<CHAN>(d, _dim, mS3Dfmt)){
+ ALOGE("S3DExtPipe setCrop failed to getCropS3D");
+ _dim = d;
+ }
+ return mS3d.setCrop(_dim);
+}
+template <int CHAN>
+inline bool S3DExtPipe<CHAN>::start(const utils::PipeArgs& args) {
+ OVASSERT(mS3Dfmt, "S3DExtPipe mS3Dfmt should not be 0 here");
+ if(!mS3d.start(args)) {
+ ALOGE("S3DExtPipe start failed");
+ return false;
+ }
+ uint32_t fmt = mS3Dfmt & utils::OUTPUT_3D_MASK;
+ if(!utils::send3DInfoPacket(fmt)){
+ ALOGE("Error S3DExtPipe start error send3DInfoPacket %d", fmt);
+ return false;
+ }
+ return true;
+}
+template <int CHAN>
+inline bool S3DExtPipe<CHAN>::setPosition(const utils::Dim& d)
+{
+ utils::Dim _dim;
+ utils::Whf _whf(mS3d.getScreenInfo().mFBWidth,
+ mS3d.getScreenInfo().mFBHeight,
+ mS3Dfmt);
+ if(!utils::getPositionS3D<CHAN>(_whf, _dim)) {
+ ALOGE("S3DExtPipe setPosition err in getPositionS3D");
+ _dim = d;
+ }
+ return mS3d.setPosition(_dim);
+}
+template <int CHAN>
+inline bool S3DExtPipe<CHAN>::setParameter(const utils::Params& param) {
+ return mS3d.setParameter(param);
+}
+template <int CHAN>
+inline bool S3DExtPipe<CHAN>::setSource(const utils::PipeArgs& args) {
+ mS3Dfmt = utils::getS3DFormat(args.whf.format);
+ if(mS3d.isClosed()){
+ if(!this->start(args)) {
+ ALOGE("S3DExtPipe setSource failed to start");
+ return false;
+ }
+ }
+ return mS3d.setSource(args);
+}
+template <int CHAN>
+inline const utils::PipeArgs& S3DExtPipe<CHAN>::getArgs() const {
+ return mS3d.getArgs();
+}
+template <int CHAN>
+inline utils::eOverlayPipeType S3DExtPipe<CHAN>::getOvPipeType() const {
+ return utils::OV_PIPE_TYPE_S3D_EXTERNAL;
+}
+template <int CHAN>
+inline void S3DExtPipe<CHAN>::dump() const {
+ ALOGE("S3DExtPipe Pipe fmt=%d", mS3Dfmt);
+ mS3d.dump();
+}
+
+///////////// S3DPrimary Pipe ////////////////////////////
+template <int CHAN>
+inline S3DPrimaryPipe<CHAN>::S3DPrimaryPipe() : mS3Dfmt(0) {}
+template <int CHAN>
+inline S3DPrimaryPipe<CHAN>::~S3DPrimaryPipe() { close(); }
+template <int CHAN>
+inline bool S3DPrimaryPipe<CHAN>::open(RotatorBase* rot) {
+ ALOGE_IF(DEBUG_OVERLAY, "S3DPrimaryPipe open");
+ if(!mS3d.open(rot)) {
+ ALOGE("3Dpipe failed to open");
+ return false;
+ }
+ // set the ctrl fd
+ mCtrl3D.setFd(mS3d.getCtrlFd());
+ return true;
+}
+template <int CHAN>
+inline bool S3DPrimaryPipe<CHAN>::close() {
+ if(!utils::enableBarrier(0)) {
+ ALOGE("S3DExtPipe close failed enable barrier");
+ }
+ mCtrl3D.close();
+ return mS3d.close();
+}
+template <int CHAN>
+inline bool S3DPrimaryPipe<CHAN>::commit() { return mS3d.commit(); }
+template <int CHAN>
+inline void S3DPrimaryPipe<CHAN>::setId(int id) { mS3d.setId(id); }
+template <int CHAN>
+inline void S3DPrimaryPipe<CHAN>::setMemoryId(int id) { mS3d.setMemoryId(id); }
+template <int CHAN>
+inline bool S3DPrimaryPipe<CHAN>::queueBuffer(uint32_t offset) {
+ return mS3d.queueBuffer(offset); }
+template <int CHAN>
+inline bool S3DPrimaryPipe<CHAN>::dequeueBuffer(void*& buf) {
+ return mS3d.dequeueBuffer(buf); }
+template <int CHAN>
+inline bool S3DPrimaryPipe<CHAN>::waitForVsync() {
+ return mS3d.waitForVsync(); }
+template <int CHAN>
+inline bool S3DPrimaryPipe<CHAN>::setCrop(const utils::Dim& d) {
+ utils::Dim _dim;
+ if(!utils::getCropS3D<CHAN>(d, _dim, mS3Dfmt)){
+ ALOGE("S3DPrimaryPipe setCrop failed to getCropS3D");
+ _dim = d;
+ }
+ return mS3d.setCrop(_dim);
+}
+template <int CHAN>
+inline bool S3DPrimaryPipe<CHAN>::start(const utils::PipeArgs& args) {
+ if(!mS3d.start(args)) {
+ ALOGE("S3DPrimaryPipe start failed");
+ return false;
+ }
+ return true;
+}
+template <int CHAN>
+inline bool S3DPrimaryPipe<CHAN>::setPosition(const utils::Dim& d)
+{
+ utils::Whf fbwhf(mS3d.getScreenInfo().mFBWidth,
+ mS3d.getScreenInfo().mFBHeight,
+ 0 /* fmt dont care*/);
+ mCtrl3D.setWh(fbwhf);
+ if(!mCtrl3D.useVirtualFB()) {
+ ALOGE("Failed to use VFB on %d (non fatal)", utils::FB0);
+ return false;
+ }
+ utils::Dim _dim;
+ // original setPositionHandleState has getPositionS3D(...,true)
+ // which means format is HAL_3D_OUT_SBS_MASK
+ // HAL_3D_OUT_SBS_MASK is 0x1000 >> 12 == 0x1 as the orig
+ // code suggets
+ utils::Whf _whf(d.w, d.h, utils::HAL_3D_OUT_SBS_MASK);
+ if(!utils::getPositionS3D<CHAN>(_whf, _dim)) {
+ ALOGE("S3DPrimaryPipe setPosition err in getPositionS3D");
+ _dim = d;
+ }
+ return mS3d.setPosition(_dim);
+}
+
+/* for S3DPrimaryPipe, we need to have barriers once
+* So the easiest way to achieve it, is to make sure FB0 is having it before
+* setParam is running */
+template <>
+inline bool S3DPrimaryPipe<utils::OV_PIPE0>::setParameter(
+ const utils::Params& param) {
+ if(utils::OVERLAY_TRANSFORM == param.param){
+ uint32_t barrier=0;
+ switch(param.value) {
+ case HAL_TRANSFORM_ROT_90:
+ case HAL_TRANSFORM_ROT_270:
+ barrier = utils::BARRIER_LAND;
+ break;
+ default:
+ barrier = utils::BARRIER_PORT;
+ break;
+ }
+ if(!utils::enableBarrier(barrier)) {
+ ALOGE("S3DPrimaryPipe setParameter failed to enable barrier");
+ }
+ }
+ return mS3d.setParameter(param);
+}
+
+template <int CHAN>
+inline bool S3DPrimaryPipe<CHAN>::setParameter(const utils::Params& param) {
+ return mS3d.setParameter(param);
+}
+template <int CHAN>
+inline bool S3DPrimaryPipe<CHAN>::setSource(const utils::PipeArgs& args)
+{
+ mS3Dfmt = utils::getS3DFormat(args.whf.format);
+ if(mS3d.isClosed()){
+ if(!this->start(args)) {
+ ALOGE("S3DPrimaryPipe setSource failed to start");
+ return false;
+ }
+ }
+ return mS3d.setSource(args);
+}
+template <int CHAN>
+inline const utils::PipeArgs& S3DPrimaryPipe<CHAN>::getArgs() const {
+ return mS3d.getArgs();
+}
+template <int CHAN>
+inline utils::eOverlayPipeType S3DPrimaryPipe<CHAN>::getOvPipeType() const {
+ return utils::OV_PIPE_TYPE_S3D_PRIMARY;
+}
+template <int CHAN>
+inline void S3DPrimaryPipe<CHAN>::dump() const {
+ ALOGE("S3DPrimaryPipe Pipe fmt=%d", mS3Dfmt);
+ mS3d.dump();
+}
+
+} // overlay
+
+#endif // OVERLAY_M3D_EXT_PIPE_H
diff --git a/liboverlay/pipes/overlayBypassPipe.h b/liboverlay/pipes/overlayBypassPipe.h
new file mode 100644
index 0000000..593a693
--- /dev/null
+++ b/liboverlay/pipes/overlayBypassPipe.h
@@ -0,0 +1,213 @@
+/*
+* Copyright (c) 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 OVERLAY_BYPASS_PIPE_H
+#define OVERLAY_BYPASS_PIPE_H
+
+#include "overlayGenPipe.h"
+#include "overlayUtils.h"
+#include "overlayCtrlData.h"
+#include "overlayMdp.h"
+#include "overlayRotator.h"
+
+namespace overlay {
+
+/* A specific impl of GenericPipe
+* Whenever needed to have a pass through - we do it.
+* If there is a special need for a different behavior - do it here
+* PipeType = 0 (RGB), 1 (VG) */
+template <utils::eMdpPipeType PipeType, utils::eIsFg IsFg, utils::eWait Wait,
+ utils::eZorder Zorder>
+class BypassPipe : utils::NoCopy {
+public:
+ /* Please look at overlayGenPipe.h for info */
+ explicit BypassPipe();
+ ~BypassPipe();
+ bool open(RotatorBase* rot);
+ bool close();
+ bool commit();
+ void setId(int id);
+ void setMemoryId(int id);
+ bool queueBuffer(uint32_t offset);
+ bool dequeueBuffer(void*& buf);
+ bool waitForVsync();
+ bool setCrop(const utils::Dim& dim);
+ bool start(const utils::PipeArgs& args);
+ bool setPosition(const utils::Dim& dim);
+ bool setParameter(const utils::Params& param);
+ bool setSource(const utils::PipeArgs& args);
+ const utils::PipeArgs& getArgs() const;
+ utils::eOverlayPipeType getOvPipeType() const;
+ void dump() const;
+private:
+ overlay::GenericPipe<ovutils::PRIMARY> mBypass;
+};
+
+//------------------Inlines and Templates---------------------
+
+template <utils::eMdpPipeType PipeType, utils::eIsFg IsFg, utils::eWait Wait,
+ utils::eZorder Zorder>
+inline BypassPipe<PipeType, IsFg, Wait, Zorder>::BypassPipe() {}
+
+template <utils::eMdpPipeType PipeType, utils::eIsFg IsFg, utils::eWait Wait,
+ utils::eZorder Zorder>
+inline BypassPipe<PipeType, IsFg, Wait, Zorder>::~BypassPipe() {
+ close();
+}
+
+template <utils::eMdpPipeType PipeType, utils::eIsFg IsFg, utils::eWait Wait,
+ utils::eZorder Zorder>
+inline bool BypassPipe<PipeType, IsFg, Wait, Zorder>::open(RotatorBase* rot) {
+ ALOGE_IF(DEBUG_OVERLAY, "BypassPipe open");
+ return mBypass.open(rot);
+}
+
+template <utils::eMdpPipeType PipeType, utils::eIsFg IsFg, utils::eWait Wait,
+ utils::eZorder Zorder>
+inline bool BypassPipe<PipeType, IsFg, Wait, Zorder>::close() {
+ return mBypass.close();
+}
+
+template <utils::eMdpPipeType PipeType, utils::eIsFg IsFg, utils::eWait Wait,
+ utils::eZorder Zorder>
+inline bool BypassPipe<PipeType, IsFg, Wait, Zorder>::commit() {
+ return mBypass.commit();
+}
+
+template <utils::eMdpPipeType PipeType, utils::eIsFg IsFg, utils::eWait Wait,
+ utils::eZorder Zorder>
+inline void BypassPipe<PipeType, IsFg, Wait, Zorder>::setId(int id) {
+ mBypass.setId(id);
+}
+
+template <utils::eMdpPipeType PipeType, utils::eIsFg IsFg, utils::eWait Wait,
+ utils::eZorder Zorder>
+inline void BypassPipe<PipeType, IsFg, Wait, Zorder>::setMemoryId(int id) {
+ mBypass.setMemoryId(id);
+}
+
+template <utils::eMdpPipeType PipeType, utils::eIsFg IsFg, utils::eWait Wait,
+ utils::eZorder Zorder>
+inline bool BypassPipe<PipeType, IsFg, Wait, Zorder>::queueBuffer(
+ uint32_t offset) {
+ return mBypass.queueBuffer(offset);
+}
+
+template <utils::eMdpPipeType PipeType, utils::eIsFg IsFg, utils::eWait Wait,
+ utils::eZorder Zorder>
+inline bool BypassPipe<PipeType, IsFg, Wait, Zorder>::dequeueBuffer(
+ void*& buf) {
+ return mBypass.dequeueBuffer(buf);
+}
+
+template <utils::eMdpPipeType PipeType, utils::eIsFg IsFg, utils::eWait Wait,
+ utils::eZorder Zorder>
+inline bool BypassPipe<PipeType, IsFg, Wait, Zorder>::waitForVsync() {
+ return mBypass.waitForVsync();
+}
+
+template <utils::eMdpPipeType PipeType, utils::eIsFg IsFg, utils::eWait Wait,
+ utils::eZorder Zorder>
+inline bool BypassPipe<PipeType, IsFg, Wait, Zorder>::setCrop(
+ const utils::Dim& dim) {
+ return mBypass.setCrop(dim);
+}
+
+template <utils::eMdpPipeType PipeType, utils::eIsFg IsFg, utils::eWait Wait,
+ utils::eZorder Zorder>
+inline bool BypassPipe<PipeType, IsFg, Wait, Zorder>::start(
+ const utils::PipeArgs& args) {
+ return mBypass.start(args);
+}
+
+template <utils::eMdpPipeType PipeType, utils::eIsFg IsFg, utils::eWait Wait,
+ utils::eZorder Zorder>
+inline bool BypassPipe<PipeType, IsFg, Wait, Zorder>::setPosition(
+ const utils::Dim& dim) {
+ return mBypass.setPosition(dim);
+}
+
+template <utils::eMdpPipeType PipeType, utils::eIsFg IsFg, utils::eWait Wait,
+ utils::eZorder Zorder>
+inline bool BypassPipe<PipeType, IsFg, Wait, Zorder>::setParameter(
+ const utils::Params& param) {
+ return mBypass.setParameter(param);
+}
+
+template <utils::eMdpPipeType PipeType, utils::eIsFg IsFg, utils::eWait Wait,
+ utils::eZorder Zorder>
+inline bool BypassPipe<PipeType, IsFg, Wait, Zorder>::setSource(
+ const utils::PipeArgs& args) {
+ utils::PipeArgs arg(args);
+
+ // Stride aligned to 32
+ arg.whf.w = utils::align(arg.whf.w, 32);
+ arg.whf.h = utils::align(arg.whf.h, 32);
+
+ // VG or RG pipe
+ if (PipeType == utils::OV_MDP_PIPE_VG) {
+ setMdpFlags(arg.mdpFlags, utils::OV_MDP_PIPE_SHARE);
+ }
+
+ // Set is_fg flag
+ arg.isFg = IsFg;
+
+ // Wait or no wait
+ arg.wait = Wait;
+
+ // Z-order
+ arg.zorder = Zorder;
+
+ return mBypass.setSource(arg);
+}
+
+template <utils::eMdpPipeType PipeType, utils::eIsFg IsFg, utils::eWait Wait,
+ utils::eZorder Zorder>
+inline const utils::PipeArgs& BypassPipe<PipeType, IsFg, Wait,
+ Zorder>::getArgs() const {
+ return mBypass.getArgs();
+}
+
+template <utils::eMdpPipeType PipeType, utils::eIsFg IsFg, utils::eWait Wait,
+ utils::eZorder Zorder>
+inline utils::eOverlayPipeType BypassPipe<PipeType, IsFg, Wait,
+ Zorder>::getOvPipeType() const {
+ return utils::OV_PIPE_TYPE_BYPASS;
+}
+
+template <utils::eMdpPipeType PipeType, utils::eIsFg IsFg, utils::eWait Wait,
+ utils::eZorder Zorder>
+inline void BypassPipe<PipeType, IsFg, Wait, Zorder>::dump() const {
+ ALOGE("Bypass VG Pipe");
+ mBypass.dump();
+}
+
+} // overlay
+
+#endif // OVERLAY_BYPASS_PIPE_H
diff --git a/liboverlay/pipes/overlayGenPipe.h b/liboverlay/pipes/overlayGenPipe.h
new file mode 100644
index 0000000..1fd4a4f
--- /dev/null
+++ b/liboverlay/pipes/overlayGenPipe.h
@@ -0,0 +1,403 @@
+/*
+* Copyright (c) 2011-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 OVERLAY_GENERIC_PIPE_H
+#define OVERLAY_GENERIC_PIPE_H
+
+#include "overlayUtils.h"
+#include "overlayRotator.h"
+#include "overlayCtrlData.h"
+
+// FIXME make int to be uint32 whenever possible
+
+namespace overlay {
+
+template <int PANEL>
+class GenericPipe : utils::NoCopy {
+public:
+ /* ctor init */
+ explicit GenericPipe();
+
+ /* dtor close */
+ ~GenericPipe();
+
+ /* CTRL/DATA/ROT open */
+ bool open(RotatorBase* rot);
+
+ /* CTRL/DATA close. Not owning rotator, will not close it */
+ bool close();
+
+ /* commit changes to the overlay "set"*/
+ bool commit();
+
+ /* "Data" related interface */
+
+ /* set ID directly to data channel */
+ void setId(int id);
+
+ /* Set FD / memid */
+ void setMemoryId(int id);
+
+ /* queue buffer to the overlay */
+ bool queueBuffer(uint32_t offset);
+
+ /* dequeue buffer to the overlay NOTSUPPORTED */
+ bool dequeueBuffer(void*& buf);
+
+ /* wait for vsync to be done */
+ bool waitForVsync();
+
+ /* set crop data FIXME setROI (Region Of Intrest) */
+ bool setCrop(const utils::Dim& d);
+
+ /* "Ctrl" related interface */
+
+ /*
+ * Start a session, opens the rotator
+ * FIXME, we might want to open the rotator separately
+ */
+ bool start(const utils::PipeArgs& args);
+
+ /* set mdp posision using dim */
+ bool setPosition(const utils::Dim& dim);
+
+ /* set param using Params (param,value pair) */
+ bool setParameter(const utils::Params& param);
+
+ /* set source using whf, orient and wait flag */
+ bool setSource(const utils::PipeArgs& args);
+
+ /* return cached startup args */
+ const utils::PipeArgs& getArgs() const;
+
+ /* retrieve screen info */
+ utils::ScreenInfo getScreenInfo() const;
+
+ /* retrieve cached crop data */
+ utils::Dim getCrop() const;
+
+ /* return aspect ratio from ctrl data */
+ utils::Dim getAspectRatio(const utils::Whf& whf) const;
+
+ /* return aspect ratio from ctrl data for true UI mirroring */
+ utils::Dim getAspectRatio(const utils::Dim& dim) const;
+
+ /* is closed */
+ bool isClosed() const;
+
+ /* is open */
+ bool isOpen() const;
+
+ /* return Ctrl fd. Used for S3D */
+ int getCtrlFd() const;
+
+ /* Get the overlay pipe type */
+ utils::eOverlayPipeType getOvPipeType() const;
+
+ /* dump the state of the object */
+ void dump() const;
+private:
+ /* set Closed channel */
+ bool setClosed();
+ // kick off rotator.
+ bool startRotator();
+
+ /* Ctrl/Data aggregator */
+ CtrlData mCtrlData;
+
+ /* caching startup params. useful when need
+ * to have the exact copy of that pipe.
+ * For example when HDMI is connected, and we would
+ * like to open/start the pipe with the args */
+ utils::PipeArgs mArgs;
+
+ /* rotator mdp base
+ * Can point to NullRotator or to Rotator*/
+ RotatorBase* mRot;
+
+ /* my flags */
+ enum { CLOSED = 1<<0 };
+ uint32_t mFlags;
+};
+
+//------------------------Inlines and Templates ----------------------
+
+template <int PANEL>
+GenericPipe<PANEL>::GenericPipe() : mRot(0), mFlags(CLOSED) {}
+
+template <int PANEL>
+GenericPipe<PANEL>::~GenericPipe() {
+ close();
+}
+
+template <int PANEL>
+bool GenericPipe<PANEL>::open(RotatorBase* rot)
+{
+ OVASSERT(rot, "rot is null");
+ // open ctrl and data
+ uint32_t fbnum = utils::getFBForPanel(PANEL);
+ ALOGE_IF(DEBUG_OVERLAY, "GenericPipe open");
+ if(!mCtrlData.ctrl.open(fbnum, rot)) {
+ ALOGE("GenericPipe failed to open ctrl");
+ return false;
+ }
+ if(!mCtrlData.data.open(fbnum, rot)) {
+ ALOGE("GenericPipe failed to open data");
+ return false;
+ }
+ mRot = rot;
+
+ // NOTE: we won't have the flags as non CLOSED since we
+ // consider the pipe opened for business only when we call
+ // start()
+
+ return true;
+}
+
+template <int PANEL>
+bool GenericPipe<PANEL>::close() {
+ if(isClosed()) return true;
+ bool ret = true;
+ if(!mCtrlData.ctrl.close()) {
+ ALOGE("GenericPipe failed to close ctrl");
+ ret = false;
+ }
+ if (!mCtrlData.data.close()) {
+ ALOGE("GenericPipe failed to close data");
+ ret = false;
+ }
+ setClosed();
+ return ret;
+}
+
+template <int PANEL>
+inline bool GenericPipe<PANEL>::commit(){
+ OVASSERT(isOpen(), "State is closed, cannot commit");
+ return mCtrlData.ctrl.commit();
+}
+
+template <int PANEL>
+inline void GenericPipe<PANEL>::setMemoryId(int id) {
+ OVASSERT(isOpen(), "State is closed, cannot setMemoryId");
+ mCtrlData.data.setMemoryId(id);
+}
+
+template <int PANEL>
+inline void GenericPipe<PANEL>::setId(int id) {
+ mCtrlData.data.setId(id); }
+
+template <int PANEL>
+inline int GenericPipe<PANEL>::getCtrlFd() const {
+ return mCtrlData.ctrl.getFd();
+}
+
+template <int PANEL>
+inline bool GenericPipe<PANEL>::setCrop(
+ const overlay::utils::Dim& d) {
+ OVASSERT(isOpen(), "State is closed, cannot setCrop");
+ return mCtrlData.ctrl.setCrop(d);
+}
+
+template <int PANEL>
+bool GenericPipe<PANEL>::start(const utils::PipeArgs& args)
+{
+ /* open before your start control rotator */
+ uint32_t sz = args.whf.size; //utils::getSizeByMdp(args.whf);
+ OVASSERT(sz, "GenericPipe sz=%d", sz);
+ if(!mRot->open()) {
+ ALOGE("GenericPipe start failed to open rot");
+ return false;
+ }
+
+ if(!mCtrlData.ctrl.start(args)){
+ ALOGE("GenericPipe failed to start");
+ return false;
+ }
+
+ int ctrlId = mCtrlData.ctrl.getId();
+ OVASSERT(-1 != ctrlId, "Ctrl ID should not be -1");
+ // set ID requeset to assoc ctrl to data
+ setId(ctrlId);
+ // set ID request to assoc MDP data to ROT MDP data
+ mRot->setDataReqId(mCtrlData.data.getId());
+
+ // cache the args for future reference.
+ mArgs = args;
+
+ // we got here so we are open+start and good to go
+ mFlags = 0; // clear flags from CLOSED
+ // TODO make it more robust when more flags
+ // are added
+
+ return true;
+}
+
+template <int PANEL>
+inline const utils::PipeArgs& GenericPipe<PANEL>::getArgs() const
+{
+ return mArgs;
+}
+
+template <int PANEL>
+bool GenericPipe<PANEL>::startRotator() {
+ // kick off rotator
+ if(!mRot->start()) {
+ ALOGE("GenericPipe failed to start rotator");
+ return false;
+ }
+ return true;
+}
+
+template <int PANEL>
+inline bool GenericPipe<PANEL>::queueBuffer(uint32_t offset) {
+ OVASSERT(isOpen(), "State is closed, cannot queueBuffer");
+ return mCtrlData.data.queueBuffer(offset);
+}
+
+template <int PANEL>
+inline bool GenericPipe<PANEL>::dequeueBuffer(void*&) {
+ OVASSERT(isOpen(), "State is closed, cannot dequeueBuffer");
+ // can also set error to NOTSUPPORTED in the future
+ return false;
+}
+
+template <int PANEL>
+inline bool GenericPipe<PANEL>::waitForVsync() {
+ OVASSERT(isOpen(), "State is closed, cannot waitForVsync");
+
+ return mCtrlData.data.waitForVsync();
+}
+
+template <int PANEL>
+inline bool GenericPipe<PANEL>::setPosition(const utils::Dim& dim)
+{
+ OVASSERT(isOpen(), "State is closed, cannot setPosition");
+ return mCtrlData.ctrl.setPosition(dim);
+}
+
+template <int PANEL>
+inline bool GenericPipe<PANEL>::setParameter(
+ const utils::Params& param)
+{
+ OVASSERT(isOpen(), "State is closed, cannot setParameter");
+ // Currently setParameter would start rotator
+ if(!mCtrlData.ctrl.setParameter(param)) {
+ ALOGE("GenericPipe failed to setparam");
+ return false;
+ }
+ // if rot flags are ENABLED it means we would always
+ // like to have rot. Even with 0 rot. (solves tearing)
+ if(utils::ROT_FLAG_ENABLED == mArgs.rotFlags) {
+ mRot->setEnable();
+ }
+ return startRotator();
+}
+
+template <int PANEL>
+inline bool GenericPipe<PANEL>::setSource(
+ const utils::PipeArgs& args)
+{
+ // cache the recent args.
+ mArgs = args;
+ // setSource is the 1st thing that is being called on a pipe.
+ // If pipe is closed, we should start everything.
+ // we assume it is being opened with the correct FDs.
+ if(isClosed()) {
+ if(!this->start(args)) {
+ ALOGE("GenericPipe setSource failed to start");
+ return false;
+ }
+ return true;
+ }
+
+ return mCtrlData.ctrl.setSource(args);
+}
+
+template <int PANEL>
+inline utils::Dim GenericPipe<PANEL>::getAspectRatio(
+ const utils::Whf& whf) const
+{
+ return mCtrlData.ctrl.getAspectRatio(whf);
+}
+
+template <int PANEL>
+inline utils::Dim GenericPipe<PANEL>::getAspectRatio(
+ const utils::Dim& dim) const
+{
+ return mCtrlData.ctrl.getAspectRatio(dim);
+}
+
+template <int PANEL>
+inline utils::ScreenInfo GenericPipe<PANEL>::getScreenInfo() const
+{
+ return mCtrlData.ctrl.getScreenInfo();
+}
+
+template <int PANEL>
+inline utils::Dim GenericPipe<PANEL>::getCrop() const
+{
+ return mCtrlData.ctrl.getCrop();
+}
+
+template <int PANEL>
+inline utils::eOverlayPipeType GenericPipe<PANEL>::getOvPipeType() const {
+ return utils::OV_PIPE_TYPE_GENERIC;
+}
+
+template <int PANEL>
+void GenericPipe<PANEL>::dump() const
+{
+ ALOGE("== Dump Generic pipe start ==");
+ ALOGE("flags=0x%x", mFlags);
+ OVASSERT(mRot, "GenericPipe should have a valid Rot");
+ mCtrlData.ctrl.dump();
+ mCtrlData.data.dump();
+ mRot->dump();
+ ALOGE("== Dump Generic pipe end ==");
+}
+
+template <int PANEL>
+inline bool GenericPipe<PANEL>::isClosed() const {
+ return utils::getBit(mFlags, CLOSED);
+}
+
+template <int PANEL>
+inline bool GenericPipe<PANEL>::isOpen() const {
+ return !isClosed();
+}
+
+template <int PANEL>
+inline bool GenericPipe<PANEL>::setClosed() {
+ return utils::setBit(mFlags, CLOSED);
+}
+
+
+} //namespace overlay
+
+#endif // OVERLAY_GENERIC_PIPE_H
diff --git a/liboverlay/pipes/overlayHdmiPipe.h b/liboverlay/pipes/overlayHdmiPipe.h
new file mode 100644
index 0000000..48c3817
--- /dev/null
+++ b/liboverlay/pipes/overlayHdmiPipe.h
@@ -0,0 +1,128 @@
+/*
+* Copyright (c) 2011-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 OVERLAY_HDMI_PIPE_H
+#define OVERLAY_HDMI_PIPE_H
+
+#include "overlayGenPipe.h"
+#include "overlayUtils.h"
+#include "overlayCtrlData.h"
+#include "overlayMdp.h"
+#include "overlayRotator.h"
+
+namespace overlay {
+
+/* A specific impl of GenericPipe
+* Whenever needed to have a pass through - we do it.
+* If there is a special need for a different behavior - do it here */
+class HdmiPipe : utils::NoCopy {
+public:
+ /* Please look at overlayGenPipe.h for info */
+ explicit HdmiPipe();
+ ~HdmiPipe();
+ bool open(RotatorBase* rot);
+ bool close();
+ bool commit();
+ void setId(int id);
+ void setMemoryId(int id);
+ bool queueBuffer(uint32_t offset);
+ bool dequeueBuffer(void*& buf);
+ bool waitForVsync();
+ bool setCrop(const utils::Dim& dim);
+ bool start(const utils::PipeArgs& args);
+ bool setPosition(const utils::Dim& dim);
+ bool setParameter(const utils::Params& param);
+ bool setSource(const utils::PipeArgs& args);
+ const utils::PipeArgs& getArgs() const;
+ utils::eOverlayPipeType getOvPipeType() const;
+ void dump() const;
+private:
+ overlay::GenericPipe<ovutils::EXTERNAL> mHdmi;
+};
+
+//------------------Inlines -----------------------------
+
+inline HdmiPipe::HdmiPipe() {}
+inline HdmiPipe::~HdmiPipe() { close(); }
+inline bool HdmiPipe::open(RotatorBase* rot) {
+ ALOGE_IF(DEBUG_OVERLAY, "HdmiPipe open");
+ return mHdmi.open(rot);
+}
+inline bool HdmiPipe::close() { return mHdmi.close(); }
+inline bool HdmiPipe::commit() { return mHdmi.commit(); }
+inline void HdmiPipe::setId(int id) { mHdmi.setId(id); }
+inline void HdmiPipe::setMemoryId(int id) { mHdmi.setMemoryId(id); }
+inline bool HdmiPipe::queueBuffer(uint32_t offset) {
+ return mHdmi.queueBuffer(offset); }
+inline bool HdmiPipe::dequeueBuffer(void*& buf) {
+ return mHdmi.dequeueBuffer(buf); }
+inline bool HdmiPipe::waitForVsync() {
+ return mHdmi.waitForVsync(); }
+inline bool HdmiPipe::setCrop(const utils::Dim& dim) {
+ return mHdmi.setCrop(dim); }
+inline bool HdmiPipe::start(const utils::PipeArgs& args) {
+ return mHdmi.start(args); }
+inline bool HdmiPipe::setPosition(const utils::Dim& dim)
+{
+ utils::Dim d;
+ // Need to change dim to aspect ratio
+ if (utils::FrameBufferInfo::getInstance()->supportTrueMirroring()) {
+ // Use dim info to calculate aspect ratio for true UI mirroring
+ d = mHdmi.getAspectRatio(dim);
+ } else {
+ // Use cached crop data to get aspect ratio
+ utils::Dim crop = mHdmi.getCrop();
+ utils::Whf whf(crop.w, crop.h, 0);
+ d = mHdmi.getAspectRatio(whf);
+ }
+ ALOGE_IF(DEBUG_OVERLAY, "Calculated aspect ratio for HDMI: x=%d, y=%d, w=%d, h=%d, o=%d",
+ d.x, d.y, d.w, d.h, d.o);
+ return mHdmi.setPosition(d);
+}
+inline bool HdmiPipe::setParameter(const utils::Params& param) {
+ return mHdmi.setParameter(param); }
+inline bool HdmiPipe::setSource(const utils::PipeArgs& args) {
+ utils::PipeArgs arg(args);
+ return mHdmi.setSource(arg);
+}
+inline const utils::PipeArgs& HdmiPipe::getArgs() const {
+ return mHdmi.getArgs();
+}
+inline utils::eOverlayPipeType HdmiPipe::getOvPipeType() const {
+ return utils::OV_PIPE_TYPE_HDMI;
+}
+inline void HdmiPipe::dump() const {
+ ALOGE("HDMI Pipe");
+ mHdmi.dump();
+}
+
+
+} // overlay
+
+#endif // OVERLAY_HDMI_PIPE_H
diff --git a/liboverlay/pipes/overlayUIMirrorPipe.h b/liboverlay/pipes/overlayUIMirrorPipe.h
new file mode 100644
index 0000000..47fbc37
--- /dev/null
+++ b/liboverlay/pipes/overlayUIMirrorPipe.h
@@ -0,0 +1,192 @@
+/*
+* Copyright (c) 2011-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 OVERLAY_UI_PIPE_H
+#define OVERLAY_UI_PIPE_H
+
+#include "overlayGenPipe.h"
+#include "overlayUtils.h"
+#include "overlayCtrlData.h"
+#include "overlayMdp.h"
+#include "overlayRotator.h"
+
+namespace overlay {
+
+/* A specific impl of GenericPipe
+* Whenever needed to have a pass through - we do it.
+* If there is a special need for a different behavior - do it here */
+class UIMirrorPipe : utils::NoCopy {
+public:
+ /* Please look at overlayGenPipe.h for info */
+ explicit UIMirrorPipe();
+ ~UIMirrorPipe();
+ bool open(RotatorBase* rot);
+ bool close();
+ bool commit();
+ void setId(int id);
+ void setMemoryId(int id);
+ bool queueBuffer(uint32_t offset);
+ bool dequeueBuffer(void*& buf);
+ bool waitForVsync();
+ bool setCrop(const utils::Dim& dim);
+ bool start(const utils::PipeArgs& args);
+ bool setPosition(const utils::Dim& dim);
+ bool setParameter(const utils::Params& param);
+ bool setSource(const utils::PipeArgs& args);
+ const utils::PipeArgs& getArgs() const;
+ utils::eOverlayPipeType getOvPipeType() const;
+ void dump() const;
+private:
+ overlay::GenericPipe<ovutils::EXTERNAL> mUI;
+};
+
+//----------------------------Inlines -----------------------------
+
+inline UIMirrorPipe::UIMirrorPipe() {}
+inline UIMirrorPipe::~UIMirrorPipe() { close(); }
+inline bool UIMirrorPipe::open(RotatorBase* rot) {
+ ALOGE_IF(DEBUG_OVERLAY, "UIMirrorPipe open");
+ bool ret = mUI.open(rot);
+ //If source to rotator is framebuffer, which is the case we UI Mirror pipe,
+ //we need to inform driver during playback. Since FB does not use ION.
+ rot->setSrcFB(true);
+ return ret;
+}
+inline bool UIMirrorPipe::close() { return mUI.close(); }
+inline bool UIMirrorPipe::commit() { return mUI.commit(); }
+inline void UIMirrorPipe::setId(int id) { mUI.setId(id); }
+inline void UIMirrorPipe::setMemoryId(int id) { mUI.setMemoryId(id); }
+inline bool UIMirrorPipe::queueBuffer(uint32_t offset) {
+ return mUI.queueBuffer(offset); }
+inline bool UIMirrorPipe::dequeueBuffer(void*& buf) {
+ return mUI.dequeueBuffer(buf); }
+inline bool UIMirrorPipe::waitForVsync() {
+ return mUI.waitForVsync(); }
+inline bool UIMirrorPipe::setCrop(const utils::Dim& dim) {
+ return mUI.setCrop(dim); }
+inline bool UIMirrorPipe::start(const utils::PipeArgs& args) {
+ if(!mUI.start(args)) {
+ ALOGE("%s failed to start", __FUNCTION__);
+ return false;
+ }
+ return true;
+}
+inline bool UIMirrorPipe::setPosition(const utils::Dim& dim) {
+
+ ovutils::Dim pdim;
+ switch (dim.o) {
+ case 0:
+ case HAL_TRANSFORM_ROT_180:
+ {
+ ovutils::Whf whf(dim.x, dim.y, 0);
+ pdim = mUI.getAspectRatio(whf);
+ break;
+ }
+ case HAL_TRANSFORM_ROT_90:
+ case HAL_TRANSFORM_ROT_270:
+ {
+ // Calculate the Aspectratio for the UI in the landscape mode
+ // Width and height will be swapped as there is rotation
+ ovutils::Whf whf(dim.y, dim.x, 0);
+ pdim = mUI.getAspectRatio(whf);
+ break;
+ }
+ default:
+ ALOGE("%s: Unknown orientation %d", __FUNCTION__, dim.o);
+ return false;
+ }
+
+ ovutils::even_out(pdim.x);
+ ovutils::even_out(pdim.y);
+ ovutils::even_out(pdim.w);
+ ovutils::even_out(pdim.h);
+ return mUI.setPosition(pdim);
+}
+inline bool UIMirrorPipe::setParameter(const utils::Params& param) {
+
+ OVASSERT(utils::OVERLAY_TRANSFORM_UI == param.param,
+ "%p Expecting OVERLAY_TRANSFORM_UI", __FUNCTION__);
+
+ int orientation = param.value;
+
+ // Figure out orientation to transform to
+ switch (param.value) {
+ case 0:
+ orientation = 0;
+ break;
+ case HAL_TRANSFORM_ROT_180:
+ orientation = HAL_TRANSFORM_ROT_180;
+ break;
+ case HAL_TRANSFORM_ROT_90:
+ orientation = HAL_TRANSFORM_ROT_270;
+ break;
+ case HAL_TRANSFORM_ROT_270:
+ orientation = HAL_TRANSFORM_ROT_90;
+ break;
+ default:
+ ALOGE("%s: Unknown orientation %d", __FUNCTION__, param.value);
+ return false;
+ }
+
+ ovutils::eTransform transform =
+ static_cast<ovutils::eTransform>(orientation);
+ const ovutils::Params prms (ovutils::OVERLAY_TRANSFORM, transform);
+ return mUI.setParameter(prms);
+}
+
+inline bool UIMirrorPipe::setSource(const utils::PipeArgs& args) {
+ utils::PipeArgs arg(args);
+
+ // Rotator flag enabled because buffer comes from fb
+ arg.rotFlags = utils::ROT_FLAG_ENABLED;
+
+ // For true UI mirroring, want the UI to go through available RGB pipe
+ // so do not set the PIPE SHARE flag which allocates VG pipe
+ if (utils::FrameBufferInfo::getInstance()->supportTrueMirroring()) {
+ arg.mdpFlags = static_cast<utils::eMdpFlags>(
+ arg.mdpFlags & ~utils::OV_MDP_PIPE_SHARE);
+ }
+
+ return mUI.setSource(arg);
+}
+inline const utils::PipeArgs& UIMirrorPipe::getArgs() const {
+ return mUI.getArgs();
+}
+inline utils::eOverlayPipeType UIMirrorPipe::getOvPipeType() const {
+ return utils::OV_PIPE_TYPE_UI_MIRROR;
+}
+inline void UIMirrorPipe::dump() const {
+ ALOGE("UI Mirror Pipe");
+ mUI.dump();
+}
+
+
+} // overlay
+
+#endif // OVERLAY_UI_PIPE_H
diff --git a/libqcomui/Android.mk b/libqcomui/Android.mk
index deb868c..d79929e 100644
--- a/libqcomui/Android.mk
+++ b/libqcomui/Android.mk
@@ -1,19 +1,19 @@
LOCAL_PATH := $(call my-dir)
+
+#Headers to export
include $(CLEAR_VARS)
-LOCAL_SRC_FILES := \
- qcom_ui.cpp
+LOCAL_SRC_FILES := qcomutils/profiler.cpp \
+ qcomutils/IdleInvalidator.cpp
LOCAL_SHARED_LIBRARIES := \
libutils \
libcutils \
libui \
- libEGL
+ libEGL \
-LOCAL_C_INCLUDES := $(TOP)/hardware/qcom/display/libgralloc \
- $(TOP)/frameworks/native/services/surfaceflinger \
- $(TOP)/external/skia/include/core \
- $(TOP)/external/skia/include/images
+LOCAL_C_INCLUDES := hardware/qcom/display/libgralloc \
+ frameworks/base/services/surfaceflinger \
LOCAL_CFLAGS := -DLOG_TAG=\"libQcomUI\"
@@ -23,6 +23,10 @@
LOCAL_SHARED_LIBRARIES += libmemalloc
endif
+ifeq ($(TARGET_USES_MDP3), true)
+ LOCAL_CFLAGS += -DUSE_MDP3
+endif
+
LOCAL_CFLAGS += -DDEBUG_CALC_FPS
LOCAL_MODULE := libQcomUI
diff --git a/libqcomui/qcom_ui.cpp b/libqcomui/qcom_ui.cpp
index 9fdd562..d060439 100644
--- a/libqcomui/qcom_ui.cpp
+++ b/libqcomui/qcom_ui.cpp
@@ -30,86 +30,78 @@
#include <cutils/log.h>
#include <cutils/memory.h>
#include <qcom_ui.h>
+#include <utils/comptype.h>
#include <gralloc_priv.h>
#include <alloc_controller.h>
#include <memalloc.h>
#include <errno.h>
#include <EGL/eglext.h>
#include <sys/stat.h>
-#if 0
#include <SkBitmap.h>
#include <SkImageEncoder.h>
-#endif
#include <Transform.h>
-#include <EGL/egl.h>
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-
using gralloc::IMemAlloc;
using gralloc::IonController;
using gralloc::alloc_data;
using android::sp;
-
-static int sCompositionType = -1;
-
namespace {
- static android::sp<gralloc::IAllocController> sAlloc = 0;
+static android::sp<gralloc::IAllocController> sAlloc = 0;
- int reallocate_memory(native_handle_t *buffer_handle, int mReqSize, int usage)
- {
- int ret = 0;
+int reallocate_memory(native_handle_t *buffer_handle, int mReqSize, int usage)
+{
+ int ret = 0;
#ifndef NON_QCOM_TARGET
- if (sAlloc == 0) {
- sAlloc = gralloc::IAllocController::getInstance(true);
- }
- if (sAlloc == 0) {
- ALOGE("sAlloc is still NULL");
- return -EINVAL;
- }
-
- // Dealloc the old memory
- private_handle_t *hnd = (private_handle_t *)buffer_handle;
- sp<IMemAlloc> memalloc = sAlloc->getAllocator(hnd->flags);
- ret = memalloc->free_buffer((void*)hnd->base, hnd->size, hnd->offset, hnd->fd);
-
- if (ret) {
- ALOGE("%s: free_buffer failed", __FUNCTION__);
- return -1;
- }
-
- // Realloc new memory
- alloc_data data;
- data.base = 0;
- data.fd = -1;
- data.offset = 0;
- data.size = mReqSize;
- data.align = getpagesize();
- data.uncached = true;
- int allocFlags = usage;
-
- switch (hnd->format) {
- case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
- case (HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED^HAL_PIXEL_FORMAT_INTERLACE): {
- data.align = 8192;
- } break;
- default: break;
- }
- ret = sAlloc->allocate(data, allocFlags, 0);
- if (ret == 0) {
- hnd->fd = data.fd;
- hnd->base = (int)data.base;
- hnd->offset = data.offset;
- hnd->size = data.size;
- } else {
- ALOGE("%s: allocate failed", __FUNCTION__);
- return -EINVAL;
- }
-#endif
- return ret;
+ if (sAlloc == 0) {
+ sAlloc = gralloc::IAllocController::getInstance(true);
}
+ if (sAlloc == 0) {
+ LOGE("sAlloc is still NULL");
+ return -EINVAL;
+ }
+
+ // Dealloc the old memory
+ private_handle_t *hnd = (private_handle_t *)buffer_handle;
+ sp<IMemAlloc> memalloc = sAlloc->getAllocator(hnd->flags);
+ ret = memalloc->free_buffer((void*)hnd->base, hnd->size, hnd->offset, hnd->fd);
+
+ if (ret) {
+ LOGE("%s: free_buffer failed", __FUNCTION__);
+ return -1;
+ }
+
+ // Realloc new memory
+ alloc_data data;
+ data.base = 0;
+ data.fd = -1;
+ data.offset = 0;
+ data.size = mReqSize;
+ data.align = getpagesize();
+ data.uncached = true;
+ int allocFlags = usage;
+
+ switch (hnd->format) {
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
+ case (HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED^HAL_PIXEL_FORMAT_INTERLACE): {
+ data.align = 8192;
+ } break;
+ default: break;
+ }
+ ret = sAlloc->allocate(data, allocFlags, 0);
+ if (ret == 0) {
+ hnd->fd = data.fd;
+ hnd->base = (int)data.base;
+ hnd->offset = data.offset;
+ hnd->size = data.size;
+ } else {
+ LOGE("%s: allocate failed", __FUNCTION__);
+ return -EINVAL;
+ }
+#endif
+ return ret;
+}
}; // ANONYNMOUS NAMESPACE
/*
@@ -128,8 +120,11 @@
case NATIVE_WINDOW_UPDATE_BUFFERS_GEOMETRY:
num_args = 3;
break;
- default: ALOGE("%s: invalid operation(0x%x)", __FUNCTION__, operation);
+ case NATIVE_WINDOW_SET_PIXEL_ASPECT_RATIO:
+ num_args = 2;
break;
+ default: LOGE("%s: invalid operation(0x%x)", __FUNCTION__, operation);
+ break;
};
return num_args;
}
@@ -146,43 +141,20 @@
// We check the YV12 formats, since some Qcom specific formats
// could have the bits set.
return true;
+ } else if ((format == HAL_PIXEL_FORMAT_RGB_888) ||
+ (format == HAL_PIXEL_FORMAT_YCrCb_422_SP) ||
+ (format == HAL_PIXEL_FORMAT_YCbCr_422_SP)){
+ return false;
} else if (format & INTERLACE_MASK) {
// Interlaced content
return false;
} else if (format & S3D_FORMAT_MASK) {
// S3D Formats are not supported by the GPU
- return false;
+ return false;
}
return true;
}
-/* decide the texture target dynamically, based on the pixel format*/
-
-int decideTextureTarget(int pixel_format)
-{
-
- // Default the return value to GL_TEXTURE_EXTERAL_OES
- int retVal = GL_TEXTURE_EXTERNAL_OES;
-
- // Change texture target to TEXTURE_2D for RGB formats
- switch (pixel_format) {
-
- case HAL_PIXEL_FORMAT_RGBA_8888:
- case HAL_PIXEL_FORMAT_RGBX_8888:
- case HAL_PIXEL_FORMAT_RGB_888:
- case HAL_PIXEL_FORMAT_RGB_565:
- case HAL_PIXEL_FORMAT_BGRA_8888:
- case HAL_PIXEL_FORMAT_RGBA_5551:
- case HAL_PIXEL_FORMAT_RGBA_4444:
- retVal = GL_TEXTURE_2D;
- break;
- default:
- retVal = GL_TEXTURE_EXTERNAL_OES;
- break;
- }
- return retVal;
-}
-
/*
* Function to check if the allocated buffer is of the correct size.
* Reallocate the buffer with the correct size, if the size doesn't
@@ -203,7 +175,7 @@
// Validate the handle
if (private_handle_t::validate(buffer_handle)) {
- ALOGE("%s: handle is invalid", __FUNCTION__);
+ LOGE("%s: handle is invalid", __FUNCTION__);
return -EINVAL;
}
@@ -255,7 +227,7 @@
int updateBufferGeometry(sp<GraphicBuffer> buffer, const qBufGeometry updatedGeometry)
{
if (buffer == 0) {
- ALOGE("%s: graphic buffer is NULL", __FUNCTION__);
+ LOGE("%s: graphic buffer is NULL", __FUNCTION__);
return -EINVAL;
}
@@ -273,7 +245,7 @@
// Validate the handle
if (private_handle_t::validate(buffer->handle)) {
- ALOGE("%s: handle is invalid", __FUNCTION__);
+ LOGE("%s: handle is invalid", __FUNCTION__);
return -EINVAL;
}
buffer->width = updatedGeometry.width;
@@ -285,7 +257,7 @@
hnd->height = updatedGeometry.height;
hnd->format = updatedGeometry.format;
} else {
- ALOGE("%s: hnd is NULL", __FUNCTION__);
+ LOGE("%s: hnd is NULL", __FUNCTION__);
return -EINVAL;
}
@@ -293,14 +265,14 @@
}
/* Update the S3D format of this buffer.
-*
-* @param: buffer whosei S3D format needs to be updated.
-* @param: Updated buffer S3D format
-*/
+ *
+ * @param: buffer whosei S3D format needs to be updated.
+ * @param: Updated buffer S3D format
+ */
int updateBufferS3DFormat(sp<GraphicBuffer> buffer, const int s3dFormat)
{
if (buffer == 0) {
- ALOGE("%s: graphic buffer is NULL", __FUNCTION__);
+ LOGE("%s: graphic buffer is NULL", __FUNCTION__);
return -EINVAL;
}
@@ -331,7 +303,7 @@
else
currentFlags &= ~LAYER_ASYNCHRONOUS;
} break;
- default: ALOGE("%s: invalid attribute(0x%x)", __FUNCTION__, attribute);
+ default: LOGE("%s: invalid attribute(0x%x)", __FUNCTION__, attribute);
break;
}
return ret;
@@ -375,43 +347,12 @@
case HWC_USE_COPYBIT:
return true;
default:
- ALOGE("%s: invalid composition type(%d)", __FUNCTION__, compositionType);
+ LOGE("%s: invalid composition type(%d)", __FUNCTION__, compositionType);
return false;
};
}
/*
- * Get the current composition Type
- *
- * @return the compositon Type
- */
-int getCompositionType() {
- char property[PROPERTY_VALUE_MAX];
- int compositionType = 0;
- if (property_get("debug.sf.hw", property, NULL) > 0) {
- if(atoi(property) == 0) {
- compositionType = COMPOSITION_TYPE_CPU;
- } else { //debug.sf.hw = 1
- property_get("debug.composition.type", property, NULL);
- if (property == NULL) {
- compositionType = COMPOSITION_TYPE_GPU;
- } else if ((strncmp(property, "mdp", 3)) == 0) {
- compositionType = COMPOSITION_TYPE_MDP;
- } else if ((strncmp(property, "c2d", 3)) == 0) {
- compositionType = COMPOSITION_TYPE_C2D;
- } else if ((strncmp(property, "dyn", 3)) == 0) {
- compositionType = COMPOSITION_TYPE_DYN;
- } else {
- compositionType = COMPOSITION_TYPE_GPU;
- }
- }
- } else { //debug.sf.hw is not set. Use cpu composition
- compositionType = COMPOSITION_TYPE_CPU;
- }
- return compositionType;
-}
-
-/*
* Clear Region implementation for C2D/MDP versions.
*
* @param: region to be cleared
@@ -422,31 +363,27 @@
*/
int qcomuiClearRegion(Region region, EGLDisplay dpy, EGLSurface sur)
{
-#if 0 /* FIXME DIE */
int ret = 0;
+ int compositionType = QCCompositionType::getInstance().getCompositionType();
- if (-1 == sCompositionType) {
- sCompositionType = getCompositionType();
- }
-
- if ((COMPOSITION_TYPE_MDP != sCompositionType) &&
- (COMPOSITION_TYPE_C2D != sCompositionType) &&
- (COMPOSITION_TYPE_CPU != sCompositionType)) {
- // For non CPU/C2D/MDP composition, return an error, so that SF can use
+ if (compositionType & COMPOSITION_TYPE_GPU ||
+ (compositionType == COMPOSITION_TYPE_DYN|COMPOSITION_TYPE_C2D))
+ {
+ // For GPU or DYN comp. with C2D, return an error, so that SF can use
// the GPU to draw the wormhole.
return -1;
}
android_native_buffer_t *renderBuffer = (android_native_buffer_t *)
- eglGetRenderBufferANDROID(dpy, sur);
+ eglGetRenderBufferANDROID(dpy, sur);
if (!renderBuffer) {
- ALOGE("%s: eglGetRenderBufferANDROID returned NULL buffer",
- __FUNCTION__);
- return -1;
+ LOGE("%s: eglGetRenderBufferANDROID returned NULL buffer",
+ __FUNCTION__);
+ return -1;
}
private_handle_t *fbHandle = (private_handle_t *)renderBuffer->handle;
if(!fbHandle) {
- ALOGE("%s: Framebuffer handle is NULL", __FUNCTION__);
+ LOGE("%s: Framebuffer handle is NULL", __FUNCTION__);
return -1;
}
@@ -461,7 +398,7 @@
while (it != end) {
const Rect& r = *it++;
uint8_t* dst = (uint8_t*) fbHandle->base +
- (r.left + r.top*renderBuffer->stride)*bytesPerPixel;
+ (r.left + r.top*renderBuffer->stride)*bytesPerPixel;
int w = r.width()*bytesPerPixel;
int h = r.height();
do {
@@ -472,42 +409,45 @@
dst += stride;
} while(--h);
}
-#endif
return 0;
}
/*
* Handles the externalDisplay event
* HDMI has highest priority compared to WifiDisplay
- * Based on the current and the new display event, decides the
+ * Based on the current and the new display type, decides the
* external display to be enabled
*
- * @param: newEvent - new external event
- * @param: currEvent - currently enabled external event
- * @return: external display to be enabled
+ * @param: disp - external display type(wfd/hdmi)
+ * @param: value - external event(0/1)
+ * @param: currdispType - Current enabled external display Type
+ * @return: external display type to be enabled
*
*/
-external_display handleEventHDMI(external_display newState, external_display
- currState)
+external_display_type handleEventHDMI(external_display_type disp, int value,
+ external_display_type currDispType)
{
- external_display retState = currState;
- switch(newState) {
- case EXT_DISPLAY_HDMI:
- retState = EXT_DISPLAY_HDMI;
+ external_display_type retDispType = currDispType;
+ switch(disp) {
+ case EXT_TYPE_HDMI:
+ if(value)
+ retDispType = EXT_TYPE_HDMI;
+ else
+ retDispType = EXT_TYPE_NONE;
break;
- case EXT_DISPLAY_WIFI:
- if(currState != EXT_DISPLAY_HDMI) {
- retState = EXT_DISPLAY_WIFI;
+ case EXT_TYPE_WIFI:
+ if(currDispType != EXT_TYPE_HDMI) {
+ if(value)
+ retDispType = EXT_TYPE_WIFI;
+ else
+ retDispType = EXT_TYPE_NONE;
}
break;
- case EXT_DISPLAY_OFF:
- retState = EXT_DISPLAY_OFF;
- break;
default:
- ALOGE("handleEventHDMI: unknown Event");
+ LOGE("%s: Unknown External Display Type!!");
break;
}
- return retState;
+ return retDispType;
}
// Using global variables for layer dumping since "property_set("debug.sf.dump",
@@ -532,25 +472,25 @@
localtime_r(&timenow, &sfdump_time);
if ((property_get("debug.sf.dump.png", sfdump_propstr, NULL) > 0) &&
- (strncmp(sfdump_propstr, sfdump_propstr_persist_png,
- PROPERTY_VALUE_MAX - 1))) {
+ (strncmp(sfdump_propstr, sfdump_propstr_persist_png,
+ PROPERTY_VALUE_MAX - 1))) {
// Strings exist & not equal implies it has changed, so trigger a dump
strncpy(sfdump_propstr_persist_png, sfdump_propstr,
- PROPERTY_VALUE_MAX - 1);
+ PROPERTY_VALUE_MAX - 1);
sfdump_countlimit_png = atoi(sfdump_propstr);
sfdump_countlimit_png = (sfdump_countlimit_png < 0) ? 0:
- (sfdump_countlimit_png >= LONG_MAX) ? (LONG_MAX - 1):
- sfdump_countlimit_png;
+ (sfdump_countlimit_png >= LONG_MAX) ? (LONG_MAX - 1):
+ sfdump_countlimit_png;
if (sfdump_countlimit_png) {
sprintf(sfdumpdir_png,"/data/sfdump.png%04d%02d%02d.%02d%02d%02d",
- sfdump_time.tm_year + 1900, sfdump_time.tm_mon + 1,
- sfdump_time.tm_mday, sfdump_time.tm_hour,
- sfdump_time.tm_min, sfdump_time.tm_sec);
+ sfdump_time.tm_year + 1900, sfdump_time.tm_mon + 1,
+ sfdump_time.tm_mday, sfdump_time.tm_hour,
+ sfdump_time.tm_min, sfdump_time.tm_sec);
if (0 == mkdir(sfdumpdir_png, 0777))
sfdump_counter_png = 0;
else
- ALOGE("sfdump: Error: %s. Failed to create sfdump directory"
- ": %s", strerror(errno), sfdumpdir_png);
+ LOGE("sfdump: Error: %s. Failed to create sfdump directory"
+ ": %s", strerror(errno), sfdumpdir_png);
}
}
@@ -558,25 +498,25 @@
sfdump_counter_png++;
if ((property_get("debug.sf.dump", sfdump_propstr, NULL) > 0) &&
- (strncmp(sfdump_propstr, sfdump_propstr_persist_raw,
- PROPERTY_VALUE_MAX - 1))) {
+ (strncmp(sfdump_propstr, sfdump_propstr_persist_raw,
+ PROPERTY_VALUE_MAX - 1))) {
// Strings exist & not equal implies it has changed, so trigger a dump
strncpy(sfdump_propstr_persist_raw, sfdump_propstr,
- PROPERTY_VALUE_MAX - 1);
+ PROPERTY_VALUE_MAX - 1);
sfdump_countlimit_raw = atoi(sfdump_propstr);
sfdump_countlimit_raw = (sfdump_countlimit_raw < 0) ? 0:
- (sfdump_countlimit_raw >= LONG_MAX) ? (LONG_MAX - 1):
- sfdump_countlimit_raw;
+ (sfdump_countlimit_raw >= LONG_MAX) ? (LONG_MAX - 1):
+ sfdump_countlimit_raw;
if (sfdump_countlimit_raw) {
sprintf(sfdumpdir_raw,"/data/sfdump.raw%04d%02d%02d.%02d%02d%02d",
- sfdump_time.tm_year + 1900, sfdump_time.tm_mon + 1,
- sfdump_time.tm_mday, sfdump_time.tm_hour,
- sfdump_time.tm_min, sfdump_time.tm_sec);
+ sfdump_time.tm_year + 1900, sfdump_time.tm_mon + 1,
+ sfdump_time.tm_mday, sfdump_time.tm_hour,
+ sfdump_time.tm_min, sfdump_time.tm_sec);
if (0 == mkdir(sfdumpdir_raw, 0777))
sfdump_counter_raw = 0;
else
- ALOGE("sfdump: Error: %s. Failed to create sfdump directory"
- ": %s", strerror(errno), sfdumpdir_raw);
+ LOGE("sfdump: Error: %s. Failed to create sfdump directory"
+ ": %s", strerror(errno), sfdumpdir_raw);
}
}
@@ -593,85 +533,85 @@
return;
switch(format) {
- case HAL_PIXEL_FORMAT_RGBA_8888:
- strcpy(pixelformatstr, "RGBA_8888");
- break;
- case HAL_PIXEL_FORMAT_RGBX_8888:
- strcpy(pixelformatstr, "RGBX_8888");
- break;
- case HAL_PIXEL_FORMAT_RGB_888:
- strcpy(pixelformatstr, "RGB_888");
- break;
- case HAL_PIXEL_FORMAT_RGB_565:
- strcpy(pixelformatstr, "RGB_565");
- break;
- case HAL_PIXEL_FORMAT_BGRA_8888:
- strcpy(pixelformatstr, "BGRA_8888");
- break;
- case HAL_PIXEL_FORMAT_RGBA_5551:
- strcpy(pixelformatstr, "RGBA_5551");
- break;
- case HAL_PIXEL_FORMAT_RGBA_4444:
- strcpy(pixelformatstr, "RGBA_4444");
- break;
- case HAL_PIXEL_FORMAT_YV12:
- strcpy(pixelformatstr, "YV12");
- break;
- case HAL_PIXEL_FORMAT_YCbCr_422_SP:
- strcpy(pixelformatstr, "YCbCr_422_SP_NV16");
- break;
- case HAL_PIXEL_FORMAT_YCrCb_420_SP:
- strcpy(pixelformatstr, "YCrCb_420_SP_NV21");
- break;
- case HAL_PIXEL_FORMAT_YCbCr_422_I:
- strcpy(pixelformatstr, "YCbCr_422_I_YUY2");
- break;
- case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
- strcpy(pixelformatstr, "NV12_ENCODEABLE");
- break;
- case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
- strcpy(pixelformatstr, "YCbCr_420_SP_TILED_TILE_4x2");
- break;
- case HAL_PIXEL_FORMAT_YCbCr_420_SP:
- strcpy(pixelformatstr, "YCbCr_420_SP");
- break;
- case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO:
- strcpy(pixelformatstr, "YCrCb_420_SP_ADRENO");
- break;
- case HAL_PIXEL_FORMAT_YCrCb_422_SP:
- strcpy(pixelformatstr, "YCrCb_422_SP");
- break;
- case HAL_PIXEL_FORMAT_R_8:
- strcpy(pixelformatstr, "R_8");
- break;
- case HAL_PIXEL_FORMAT_RG_88:
- strcpy(pixelformatstr, "RG_88");
- break;
- case HAL_PIXEL_FORMAT_INTERLACE:
- strcpy(pixelformatstr, "INTERLACE");
- break;
- default:
- sprintf(pixelformatstr, "Unknown0x%X", format);
- break;
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ strcpy(pixelformatstr, "RGBA_8888");
+ break;
+ case HAL_PIXEL_FORMAT_RGBX_8888:
+ strcpy(pixelformatstr, "RGBX_8888");
+ break;
+ case HAL_PIXEL_FORMAT_RGB_888:
+ strcpy(pixelformatstr, "RGB_888");
+ break;
+ case HAL_PIXEL_FORMAT_RGB_565:
+ strcpy(pixelformatstr, "RGB_565");
+ break;
+ case HAL_PIXEL_FORMAT_BGRA_8888:
+ strcpy(pixelformatstr, "BGRA_8888");
+ break;
+ case HAL_PIXEL_FORMAT_RGBA_5551:
+ strcpy(pixelformatstr, "RGBA_5551");
+ break;
+ case HAL_PIXEL_FORMAT_RGBA_4444:
+ strcpy(pixelformatstr, "RGBA_4444");
+ break;
+ case HAL_PIXEL_FORMAT_YV12:
+ strcpy(pixelformatstr, "YV12");
+ break;
+ case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+ strcpy(pixelformatstr, "YCbCr_422_SP_NV16");
+ break;
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+ strcpy(pixelformatstr, "YCrCb_420_SP_NV21");
+ break;
+ case HAL_PIXEL_FORMAT_YCbCr_422_I:
+ strcpy(pixelformatstr, "YCbCr_422_I_YUY2");
+ break;
+ case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+ strcpy(pixelformatstr, "NV12_ENCODEABLE");
+ break;
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
+ strcpy(pixelformatstr, "YCbCr_420_SP_TILED_TILE_4x2");
+ break;
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+ strcpy(pixelformatstr, "YCbCr_420_SP");
+ break;
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO:
+ strcpy(pixelformatstr, "YCrCb_420_SP_ADRENO");
+ break;
+ case HAL_PIXEL_FORMAT_YCrCb_422_SP:
+ strcpy(pixelformatstr, "YCrCb_422_SP");
+ break;
+ case HAL_PIXEL_FORMAT_R_8:
+ strcpy(pixelformatstr, "R_8");
+ break;
+ case HAL_PIXEL_FORMAT_RG_88:
+ strcpy(pixelformatstr, "RG_88");
+ break;
+ case HAL_PIXEL_FORMAT_INTERLACE:
+ strcpy(pixelformatstr, "INTERLACE");
+ break;
+ default:
+ sprintf(pixelformatstr, "Unknown0x%X", format);
+ break;
}
}
void dumpLayer(int moduleCompositionType, int listFlags, size_t layerIndex,
- hwc_layer_t hwLayers[])
+ hwc_layer_t hwLayers[])
{
char dumplogstr_png[128] = "";
char dumplogstr_raw[128] = "";
if (sfdump_counter_png <= sfdump_countlimit_png) {
sprintf(dumplogstr_png, "[png-dump-frame: %03d of %03d] ",
- sfdump_counter_png, sfdump_countlimit_png);
+ sfdump_counter_png, sfdump_countlimit_png);
}
if (sfdump_counter_raw <= sfdump_countlimit_raw) {
sprintf(dumplogstr_raw, "[raw-dump-frame: %03d of %03d]",
- sfdump_counter_raw, sfdump_countlimit_raw);
+ sfdump_counter_raw, sfdump_countlimit_raw);
}
if (NULL == hwLayers) {
- ALOGE("sfdump: Error.%s%sLayer[%d] No hwLayers to dump.",
- dumplogstr_raw, dumplogstr_png, layerIndex);
+ LOGE("sfdump: Error.%s%sLayer[%d] No hwLayers to dump.",
+ dumplogstr_raw, dumplogstr_png, layerIndex);
return;
}
hwc_layer *layer = &hwLayers[layerIndex];
@@ -679,263 +619,245 @@
hwc_rect_t displayFrame = layer->displayFrame;
private_handle_t *hnd = (private_handle_t *)layer->handle;
char pixelformatstr[32] = "None";
+ uint32_t transform = layer->transform & FINAL_TRANSFORM_MASK;
if (hnd)
getHalPixelFormatStr(hnd->format, pixelformatstr);
-#if 0
- ALOGE("sfdump: %s%s[%s]-Composition, Layer[%d] SrcBuff[%dx%d] "
- "SrcCrop[%dl, %dt, %dr, %db] "
- "DispFrame[%dl, %dt, %dr, %db] Composition-type = %s, Format = %s, "
- "Orientation = %s, Flags = %s%s%s%s%s%s%s%s%s%s",
- dumplogstr_raw, dumplogstr_png,
- (moduleCompositionType == COMPOSITION_TYPE_GPU)? "GPU":
- (moduleCompositionType == COMPOSITION_TYPE_MDP)? "MDP":
- (moduleCompositionType == COMPOSITION_TYPE_C2D)? "C2D":
- (moduleCompositionType == COMPOSITION_TYPE_CPU)? "CPU":
- (moduleCompositionType == COMPOSITION_TYPE_DYN)? "DYN": "???",
- layerIndex,
- (hnd)? hnd->width : -1, (hnd)? hnd->height : -1,
- sourceCrop.left, sourceCrop.top,
- sourceCrop.right, sourceCrop.bottom,
- displayFrame.left, displayFrame.top,
- displayFrame.right, displayFrame.bottom,
- (layer->compositionType == HWC_FRAMEBUFFER)? "Framebuffer (OpenGL ES)":
- (layer->compositionType == HWC_OVERLAY)? "Overlay":
- (layer->compositionType == HWC_USE_COPYBIT)? "Copybit": "???",
- pixelformatstr,
- (layer->transform == Transform::ROT_0)? "ROT_0":
- (layer->transform == Transform::FLIP_H)? "FLIP_H":
- (layer->transform == Transform::FLIP_V)? "FLIP_V":
- (layer->transform == Transform::ROT_90)? "ROT_90":
- (layer->transform == Transform::ROT_180)? "ROT_180":
- (layer->transform == Transform::ROT_270)? "ROT_270":
- (layer->transform == Transform::ROT_INVALID)? "ROT_INVALID":"???",
- (layer->flags == 0)? "[None]":"",
- (layer->flags & HWC_SKIP_LAYER)? "[Skip layer]":"",
- (layer->flags & HWC_LAYER_NOT_UPDATING)? "[Layer not updating]":"",
- (layer->flags & HWC_USE_ORIGINAL_RESOLUTION)? "[Original Resolution]":"",
- (layer->flags & HWC_DO_NOT_USE_OVERLAY)? "[Do not use Overlay]":"",
- (layer->flags & HWC_COMP_BYPASS)? "[Bypass]":"",
- (layer->flags & HWC_BYPASS_RESERVE_0)? "[Bypass Reserve 0]":"",
- (layer->flags & HWC_BYPASS_RESERVE_1)? "[Bypass Reserve 1]":"",
- (listFlags & HWC_GEOMETRY_CHANGED)? "[List: Geometry Changed]":"",
- (listFlags & HWC_SKIP_COMPOSITION)? "[List: Skip Composition]":"");
-#endif
- if (NULL == hnd) {
- ALOGE("sfdump: %s%sLayer[%d] private-handle is invalid.",
- dumplogstr_raw, dumplogstr_png, layerIndex);
- return;
- }
- if ((sfdump_counter_png <= sfdump_countlimit_png) && hnd->base) {
-#if 0
- bool bResult = false;
- char sfdumpfile_name[256];
- SkBitmap *tempSkBmp = new SkBitmap();
- SkBitmap::Config tempSkBmpConfig = SkBitmap::kNo_Config;
- sprintf(sfdumpfile_name, "%s/sfdump%03d_layer%d.png", sfdumpdir_png,
- sfdump_counter_png, layerIndex);
+ LOGE("sfdump: %s%s[%s]-Composition, Layer[%d] SrcBuff[%dx%d] "
+ "SrcCrop[%dl, %dt, %dr, %db] "
+ "DispFrame[%dl, %dt, %dr, %db] Composition-type = %s, Format = %s, "
+ "Orientation = %s, Flags = %s%s%s%s%s%s%s%s%s%s",
+ dumplogstr_raw, dumplogstr_png,
+ (moduleCompositionType == COMPOSITION_TYPE_GPU)? "GPU":
+ (moduleCompositionType == COMPOSITION_TYPE_MDP)? "MDP":
+ (moduleCompositionType == COMPOSITION_TYPE_C2D)? "C2D":
+ (moduleCompositionType == COMPOSITION_TYPE_CPU)? "CPU":
+ (moduleCompositionType == COMPOSITION_TYPE_DYN)? "DYN": "???",
+ layerIndex,
+ (hnd)? hnd->width : -1, (hnd)? hnd->height : -1,
+ sourceCrop.left, sourceCrop.top,
+ sourceCrop.right, sourceCrop.bottom,
+ displayFrame.left, displayFrame.top,
+ displayFrame.right, displayFrame.bottom,
+ (layer->compositionType == HWC_FRAMEBUFFER)? "Framebuffer (OpenGL ES)":
+ (layer->compositionType == HWC_OVERLAY)? "Overlay":
+ (layer->compositionType == HWC_USE_COPYBIT)? "Copybit": "???",
+ pixelformatstr,
+ (transform == Transform::ROT_0)? "ROT_0":
+ (transform == Transform::FLIP_H)? "FLIP_H":
+ (transform == Transform::FLIP_V)? "FLIP_V":
+ (transform == Transform::ROT_90)? "ROT_90":
+ (transform == Transform::ROT_180)? "ROT_180":
+ (transform == Transform::ROT_270)? "ROT_270":
+ (transform == Transform::ROT_INVALID)? "ROT_INVALID":"???",
+ (layer->flags == 0)? "[None]":"",
+ (layer->flags & HWC_SKIP_LAYER)? "[Skip layer]":"",
+ (layer->flags & HWC_LAYER_NOT_UPDATING)? "[Layer not updating]":"",
+ (layer->flags & HWC_COMP_BYPASS)? "[Bypass]":"",
+ (layer->flags & HWC_BYPASS_RESERVE_0)? "[Bypass Reserve 0]":"",
+ (layer->flags & HWC_BYPASS_RESERVE_1)? "[Bypass Reserve 1]":"",
+ (listFlags & HWC_GEOMETRY_CHANGED)? "[List: Geometry Changed]":"",
+ (listFlags & HWC_SKIP_COMPOSITION)? "[List: Skip Composition]":"");
- switch (hnd->format) {
- case HAL_PIXEL_FORMAT_RGBA_8888:
- case HAL_PIXEL_FORMAT_RGBX_8888:
- case HAL_PIXEL_FORMAT_BGRA_8888:
- tempSkBmpConfig = SkBitmap::kARGB_8888_Config;
- break;
- case HAL_PIXEL_FORMAT_RGB_565:
- case HAL_PIXEL_FORMAT_RGBA_5551:
- case HAL_PIXEL_FORMAT_RGBA_4444:
- tempSkBmpConfig = SkBitmap::kRGB_565_Config;
- break;
- case HAL_PIXEL_FORMAT_RGB_888:
- default:
- tempSkBmpConfig = SkBitmap::kNo_Config;
- break;
- }
- if (SkBitmap::kNo_Config != tempSkBmpConfig) {
- tempSkBmp->setConfig(tempSkBmpConfig, hnd->width, hnd->height);
- tempSkBmp->setPixels((void*)hnd->base);
- bResult = SkImageEncoder::EncodeFile(sfdumpfile_name,
- *tempSkBmp, SkImageEncoder::kPNG_Type, 100);
- ALOGE("sfdump: %sDumped Layer[%d] to %s: %s", dumplogstr_png,
- layerIndex, sfdumpfile_name, bResult ? "Success" : "Fail");
- }
- else {
- ALOGE("sfdump: %sSkipping Layer[%d] dump: Unsupported layer "
- "format %s for png encoder.", dumplogstr_png, layerIndex,
- pixelformatstr);
- }
- delete tempSkBmp; // Calls SkBitmap::freePixels() internally.
-#endif
- }
-
- if ((sfdump_counter_raw <= sfdump_countlimit_raw) && hnd->base) {
- char sfdumpfile_name[256];
- bool bResult = false;
- sprintf(sfdumpfile_name, "%s/sfdump%03d_layer%d_%dx%d_%s.raw",
- sfdumpdir_raw,
- sfdump_counter_raw, layerIndex, hnd->width, hnd->height,
- pixelformatstr);
- FILE* fp = fopen(sfdumpfile_name, "w+");
- if (fp != NULL) {
- bResult = (bool) fwrite((void*)hnd->base, hnd->size, 1, fp);
- fclose(fp);
- }
- ALOGE("sfdump: %s Dumped Layer[%d] to %s: %s", dumplogstr_raw,
- layerIndex, sfdumpfile_name, bResult ? "Success" : "Fail");
- }
-}
-
-#ifdef DEBUG_CALC_FPS
-ANDROID_SINGLETON_STATIC_INSTANCE(CalcFps) ;
-
-CalcFps::CalcFps() {
- debug_fps_level = 0;
- Init();
-}
-
-CalcFps::~CalcFps() {
-}
-
-void CalcFps::Init() {
- char prop[PROPERTY_VALUE_MAX];
- property_get("debug.gr.calcfps", prop, "0");
- debug_fps_level = atoi(prop);
- if (debug_fps_level > MAX_DEBUG_FPS_LEVEL) {
- ALOGW("out of range value for debug.gr.calcfps, using 0");
- debug_fps_level = 0;
- }
-
- ALOGE("DEBUG_CALC_FPS: %d", debug_fps_level);
- populate_debug_fps_metadata();
-}
-
-void CalcFps::Fps() {
- if (debug_fps_level > 0)
- calc_fps(ns2us(systemTime()));
-}
-
-void CalcFps::populate_debug_fps_metadata(void)
-{
- char prop[PROPERTY_VALUE_MAX];
-
- /*defaults calculation of fps to based on number of frames*/
- property_get("debug.gr.calcfps.type", prop, "0");
- debug_fps_metadata.type = (debug_fps_metadata_t::DfmType) atoi(prop);
-
- /*defaults to 1000ms*/
- property_get("debug.gr.calcfps.timeperiod", prop, "1000");
- debug_fps_metadata.time_period = atoi(prop);
-
- property_get("debug.gr.calcfps.period", prop, "10");
- debug_fps_metadata.period = atoi(prop);
-
- if (debug_fps_metadata.period > MAX_FPS_CALC_PERIOD_IN_FRAMES) {
- debug_fps_metadata.period = MAX_FPS_CALC_PERIOD_IN_FRAMES;
- }
-
- /* default ignorethresh_us: 500 milli seconds */
- property_get("debug.gr.calcfps.ignorethresh_us", prop, "500000");
- debug_fps_metadata.ignorethresh_us = atoi(prop);
-
- debug_fps_metadata.framearrival_steps =
- (debug_fps_metadata.ignorethresh_us / 16666);
-
- if (debug_fps_metadata.framearrival_steps > MAX_FRAMEARRIVAL_STEPS) {
- debug_fps_metadata.framearrival_steps = MAX_FRAMEARRIVAL_STEPS;
- debug_fps_metadata.ignorethresh_us =
- debug_fps_metadata.framearrival_steps * 16666;
- }
-
- /* 2ms margin of error for the gettimeofday */
- debug_fps_metadata.margin_us = 2000;
-
- for (unsigned int i = 0; i < MAX_FRAMEARRIVAL_STEPS; i++)
- debug_fps_metadata.accum_framearrivals[i] = 0;
-
- ALOGE("period: %d", debug_fps_metadata.period);
- ALOGE("ignorethresh_us: %lld", debug_fps_metadata.ignorethresh_us);
-}
-
-void CalcFps::print_fps(float fps)
-{
- if (debug_fps_metadata_t::DFM_FRAMES == debug_fps_metadata.type)
- ALOGE("FPS for last %d frames: %3.2f", debug_fps_metadata.period, fps);
- else
- ALOGE("FPS for last (%f ms, %d frames): %3.2f",
- debug_fps_metadata.time_elapsed,
- debug_fps_metadata.curr_frame, fps);
-
- debug_fps_metadata.curr_frame = 0;
- debug_fps_metadata.time_elapsed = 0.0;
-
- if (debug_fps_level > 1) {
- ALOGE("Frame Arrival Distribution:");
- for (unsigned int i = 0;
- i < ((debug_fps_metadata.framearrival_steps / 6) + 1);
- i++) {
- ALOGE("%lld %lld %lld %lld %lld %lld",
- debug_fps_metadata.accum_framearrivals[i*6],
- debug_fps_metadata.accum_framearrivals[i*6+1],
- debug_fps_metadata.accum_framearrivals[i*6+2],
- debug_fps_metadata.accum_framearrivals[i*6+3],
- debug_fps_metadata.accum_framearrivals[i*6+4],
- debug_fps_metadata.accum_framearrivals[i*6+5]);
- }
-
- /* We are done with displaying, now clear the stats */
- for (unsigned int i = 0;
- i < debug_fps_metadata.framearrival_steps;
- i++)
- debug_fps_metadata.accum_framearrivals[i] = 0;
- }
- return;
-}
-
-void CalcFps::calc_fps(nsecs_t currtime_us)
-{
- static nsecs_t oldtime_us = 0;
-
- nsecs_t diff = currtime_us - oldtime_us;
-
- oldtime_us = currtime_us;
-
- if (debug_fps_metadata_t::DFM_FRAMES == debug_fps_metadata.type &&
- diff > debug_fps_metadata.ignorethresh_us) {
+ if (NULL == hnd) {
+ LOGE("sfdump: %s%sLayer[%d] private-handle is invalid.",
+ dumplogstr_raw, dumplogstr_png, layerIndex);
return;
}
- if (debug_fps_metadata.curr_frame < MAX_FPS_CALC_PERIOD_IN_FRAMES) {
- debug_fps_metadata.framearrivals[debug_fps_metadata.curr_frame] = diff;
- }
+ if ((sfdump_counter_png <= sfdump_countlimit_png) && hnd->base) {
+ bool bResult = false;
+ char sfdumpfile_name[256];
+ SkBitmap *tempSkBmp = new SkBitmap();
+ SkBitmap::Config tempSkBmpConfig = SkBitmap::kNo_Config;
+ sprintf(sfdumpfile_name, "%s/sfdump%03d_layer%d.png", sfdumpdir_png,
+ sfdump_counter_png, layerIndex);
- debug_fps_metadata.curr_frame++;
-
- if (debug_fps_level > 1) {
- unsigned int currstep = (diff + debug_fps_metadata.margin_us) / 16666;
-
- if (currstep < debug_fps_metadata.framearrival_steps) {
- debug_fps_metadata.accum_framearrivals[currstep-1]++;
+ switch (hnd->format) {
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ case HAL_PIXEL_FORMAT_RGBX_8888:
+ case HAL_PIXEL_FORMAT_BGRA_8888:
+ tempSkBmpConfig = SkBitmap::kARGB_8888_Config;
+ break;
+ case HAL_PIXEL_FORMAT_RGB_565:
+ case HAL_PIXEL_FORMAT_RGBA_5551:
+ case HAL_PIXEL_FORMAT_RGBA_4444:
+ tempSkBmpConfig = SkBitmap::kRGB_565_Config;
+ break;
+ case HAL_PIXEL_FORMAT_RGB_888:
+ default:
+ tempSkBmpConfig = SkBitmap::kNo_Config;
+ break;
}
+ if (SkBitmap::kNo_Config != tempSkBmpConfig) {
+ tempSkBmp->setConfig(tempSkBmpConfig, hnd->width, hnd->height);
+ tempSkBmp->setPixels((void*)hnd->base);
+ bResult = SkImageEncoder::EncodeFile(sfdumpfile_name,
+ *tempSkBmp, SkImageEncoder::kPNG_Type, 100);
+ LOGE("sfdump: %sDumped Layer[%d] to %s: %s", dumplogstr_png,
+ layerIndex, sfdumpfile_name, bResult ? "Success" : "Fail");
+ }
+ else {
+ LOGE("sfdump: %sSkipping Layer[%d] dump: Unsupported layer "
+ "format %s for png encoder.", dumplogstr_png, layerIndex,
+ pixelformatstr);
+ }
+ delete tempSkBmp; // Calls SkBitmap::freePixels() internally.
}
- if (debug_fps_metadata_t::DFM_FRAMES == debug_fps_metadata.type) {
- if (debug_fps_metadata.curr_frame == debug_fps_metadata.period) {
- /* time to calculate and display FPS */
- nsecs_t sum = 0;
- for (unsigned int i = 0; i < debug_fps_metadata.period; i++)
- sum += debug_fps_metadata.framearrivals[i];
- print_fps((debug_fps_metadata.period * float(1000000))/float(sum));
+ if ((sfdump_counter_raw <= sfdump_countlimit_raw) && hnd->base) {
+ char sfdumpfile_name[256];
+ bool bResult = false;
+ sprintf(sfdumpfile_name, "%s/sfdump%03d_layer%d_%dx%d_%s.raw",
+ sfdumpdir_raw,
+ sfdump_counter_raw, layerIndex, hnd->width, hnd->height,
+ pixelformatstr);
+ FILE* fp = fopen(sfdumpfile_name, "w+");
+ if (fp != NULL) {
+ bResult = (bool) fwrite((void*)hnd->base, hnd->size, 1, fp);
+ fclose(fp);
}
+ LOGE("sfdump: %s Dumped Layer[%d] to %s: %s", dumplogstr_raw,
+ layerIndex, sfdumpfile_name, bResult ? "Success" : "Fail");
}
- else if (debug_fps_metadata_t::DFM_TIME == debug_fps_metadata.type) {
- debug_fps_metadata.time_elapsed += ((float)diff/1000.0);
- if (debug_fps_metadata.time_elapsed >= debug_fps_metadata.time_period) {
- float fps = (1000.0 * debug_fps_metadata.curr_frame)/
- (float)debug_fps_metadata.time_elapsed;
- print_fps(fps);
- }
- }
- return;
}
-#endif
+
+bool needsAspectRatio (int wRatio, int hRatio) {
+ return ((wRatio != DEFAULT_WIDTH_RATIO) || (hRatio != DEFAULT_HEIGHT_RATIO));
+}
+
+void applyPixelAspectRatio (int wRatio, int hRatio, int orientation, int maxWidth,
+ int maxHeight, Rect& visibleRect, GLfloat mVertices[][2]) {
+
+ if ((wRatio == 0) || (hRatio == 0))
+ return;
+
+ float wDelta = 0;
+ float hDelta = 0;
+ float aspectRatio;
+ float displayRatio;
+ float new_width, new_height;
+ float old_width = abs(visibleRect.right - visibleRect.left);
+ float old_height = abs(visibleRect.bottom - visibleRect.top);
+
+ if (orientation == Transform::ROT_INVALID) {
+ // During animation, no defined orientation, rely on mTransformedBounds
+ if (old_width >= old_height)
+ orientation = Transform::ROT_0;
+ else
+ orientation = Transform::ROT_90;
+ }
+
+ switch (orientation) {
+
+ case Transform::ROT_0:
+ case Transform::ROT_180:
+
+ // Calculated Aspect Ratio = Original Aspect Ratio x Pixel Aspect Ratio
+ aspectRatio = (old_width * wRatio) / (old_height * hRatio);
+ displayRatio = (float)maxWidth / (float)maxHeight;
+
+ if (aspectRatio >= displayRatio) {
+ new_height = old_width / aspectRatio;
+ if (new_height > maxHeight) {
+ new_height = maxHeight;
+ new_width = new_height * aspectRatio;
+ wDelta = (new_width - old_width) / 2;
+ }
+ hDelta = (new_height - old_height) / 2;
+ } else {
+ new_width = old_height * aspectRatio;
+ if (new_width > maxWidth) {
+ new_width = maxWidth;
+ new_height = new_width / aspectRatio;
+ hDelta = (new_height - old_height) / 2;
+ }
+ wDelta = (new_width - old_width) / 2;
+ }
+
+ if (hDelta != 0) {
+ visibleRect.top -= hDelta;
+ visibleRect.bottom += hDelta;
+
+ // Set mVertices for GPU fallback (During rotation)
+ if (orientation == Transform::ROT_0) {
+ mVertices[1][1] = mVertices[2][1] = visibleRect.top;
+ mVertices[0][1] = mVertices[3][1] = visibleRect.bottom;
+ } else {
+ mVertices[0][1] = mVertices[3][1] = visibleRect.top;
+ mVertices[1][1] = mVertices[2][1] = visibleRect.bottom;
+ }
+ }
+
+ if (wDelta != 0) {
+ visibleRect.left -= wDelta;
+ visibleRect.right += wDelta;
+
+ // Set mVertices for GPU fallback (During rotation)
+ mVertices[0][0] = mVertices[1][0] = visibleRect.left;
+ mVertices[2][0] = mVertices[3][0] = visibleRect.right;
+ }
+ break;
+
+ case Transform::ROT_90:
+ case Transform::ROT_270:
+
+ // Calculated Aspect Ratio = Original Aspect Ratio x Pixel Aspect Ratio
+ aspectRatio = (old_height * wRatio) / (old_width * hRatio);
+ displayRatio = (float)maxHeight / (float)maxWidth;
+
+ if (aspectRatio >= displayRatio) {
+ new_height = old_width * aspectRatio;
+ if (new_height > maxHeight) {
+ new_height = maxHeight;
+ new_width = new_height / aspectRatio;
+ wDelta = (new_width - old_width) / 2;
+ }
+ hDelta = (new_height - old_height) / 2;
+ } else {
+ new_width = old_height / aspectRatio;
+ if (new_width > maxWidth) {
+ new_width = maxWidth;
+ new_height = new_width * aspectRatio;
+ hDelta = (new_height - old_height) / 2;
+ }
+ wDelta = (new_width - old_width) / 2;
+ }
+
+ if (hDelta != 0) {
+ visibleRect.top -= hDelta;
+ visibleRect.bottom += hDelta;
+
+ // Set mVertices for GPU fallback (During rotation)
+ if (orientation == Transform::ROT_90) {
+ mVertices[2][1] = mVertices[3][1] = visibleRect.top;
+ mVertices[0][1] = mVertices[1][1] = visibleRect.bottom;
+ } else {
+ mVertices[0][1] = mVertices[1][1] = visibleRect.top;
+ mVertices[2][1] = mVertices[3][1] = visibleRect.bottom;
+ }
+ }
+
+ if (wDelta != 0) {
+ visibleRect.left -= wDelta;
+ visibleRect.right += wDelta;
+
+ // Set mVertices for GPU fallback (During rotation)
+ if (orientation == Transform::ROT_90) {
+ mVertices[1][0] = mVertices[2][0] = visibleRect.left;
+ mVertices[0][0] = mVertices[3][0] = visibleRect.right;
+ } else {
+ mVertices[0][0] = mVertices[3][0] = visibleRect.left;
+ mVertices[1][0] = mVertices[2][0] = visibleRect.right;
+ }
+ }
+ break;
+
+ default: // Handled above.
+ break;
+
+ }
+}
+
+
diff --git a/libqcomui/qcom_ui.h b/libqcomui/qcom_ui.h
index 88462cc..89974bd 100644
--- a/libqcomui/qcom_ui.h
+++ b/libqcomui/qcom_ui.h
@@ -33,18 +33,19 @@
#include <cutils/native_handle.h>
#include <ui/GraphicBuffer.h>
#include <hardware/hwcomposer.h>
-#include <hardware/hwcomposer_defs.h>
#include <ui/Region.h>
#include <EGL/egl.h>
+#include <GLES/gl.h>
#include <utils/Singleton.h>
#include <cutils/properties.h>
-#include "../libgralloc/gralloc_priv.h"
using namespace android;
using android::sp;
using android::GraphicBuffer;
#define HWC_BYPASS_INDEX_MASK 0x00000030
+#define DEFAULT_WIDTH_RATIO 1
+#define DEFAULT_HEIGHT_RATIO 1
/*
* Qcom specific Native Window perform operations
@@ -53,15 +54,7 @@
NATIVE_WINDOW_SET_BUFFERS_SIZE = 0x10000000,
NATIVE_WINDOW_UPDATE_BUFFERS_GEOMETRY = 0x20000000,
NATIVE_WINDOW_SET_S3D_FORMAT = 0x40000000,
-};
-
-// Enum containing the supported composition types
-enum {
- COMPOSITION_TYPE_GPU = 0,
- COMPOSITION_TYPE_MDP = 0x1,
- COMPOSITION_TYPE_C2D = 0x2,
- COMPOSITION_TYPE_CPU = 0x4,
- COMPOSITION_TYPE_DYN = 0x8
+ NATIVE_WINDOW_SET_PIXEL_ASPECT_RATIO = 0x80000000,
};
/*
@@ -81,16 +74,21 @@
};
/*
+ * Layer Transformation - refers to Layer::setGeometry()
+ */
+#define SHIFT_SRC_TRANSFORM 4
+#define SRC_TRANSFORM_MASK 0x00F0
+#define FINAL_TRANSFORM_MASK 0x000F
+
+/*
* Flags set by the layer and sent to HWC
*/
enum {
HWC_LAYER_NOT_UPDATING = 0x00000002,
HWC_LAYER_ASYNCHRONOUS = 0x00000004,
- HWC_USE_ORIGINAL_RESOLUTION = 0x10000000,
- HWC_DO_NOT_USE_OVERLAY = 0x20000000,
- HWC_COMP_BYPASS = 0x40000000,
- HWC_USE_EXT_ONLY = 0x80000000, //Layer displayed on external only
- HWC_USE_EXT_BLOCK = 0x01000000, //Layer displayed on external only
+ HWC_COMP_BYPASS = 0x10000000,
+ HWC_USE_EXT_ONLY = 0x20000000, //Layer displayed on external only
+ HWC_USE_EXT_BLOCK = 0x40000000, //Layer displayed on external only
HWC_BYPASS_RESERVE_0 = 0x00000010,
HWC_BYPASS_RESERVE_1 = 0x00000020,
};
@@ -101,10 +99,41 @@
HWC_USE_COPYBIT // This layer is to be handled by copybit
};
-enum external_display {
- EXT_DISPLAY_OFF,
- EXT_DISPLAY_HDMI,
- EXT_DISPLAY_WIFI
+enum external_display_type {
+ EXT_TYPE_NONE,
+ EXT_TYPE_HDMI,
+ EXT_TYPE_WIFI
+};
+
+/* Events to the Display HAL perform function
+ As of now used for external display related such as
+ connect, disconnect, orientation, video started etc.,
+ */
+enum {
+ EVENT_EXTERNAL_DISPLAY, // External display on/off Event
+ EVENT_VIDEO_OVERLAY, // Video Overlay start/stop Event
+ EVENT_ORIENTATION_CHANGE, // Orientation Change Event
+ EVENT_OVERLAY_STATE_CHANGE, // Overlay State Change Event
+ EVENT_OPEN_SECURE_START, // Start of secure session setup config by stagefright
+ EVENT_OPEN_SECURE_END, // End of secure session setup config by stagefright
+ EVENT_CLOSE_SECURE_START, // Start of secure session teardown config
+ EVENT_CLOSE_SECURE_END, // End of secure session teardown config
+ EVENT_RESET_POSTBUFFER, // Reset post framebuffer mutex
+ EVENT_WAIT_POSTBUFFER, // Wait until post framebuffer returns
+};
+
+// Video information sent to framebuffer HAl
+// used for handling UI mirroring.
+enum {
+ VIDEO_OVERLAY_ENDED = 0,
+ VIDEO_2D_OVERLAY_STARTED,
+ VIDEO_3D_OVERLAY_STARTED
+};
+
+// Information about overlay state change
+enum {
+ OVERLAY_STATE_CHANGE_START = 0,
+ OVERLAY_STATE_CHANGE_END
};
/*
@@ -115,86 +144,18 @@
int height;
int format;
void set(int w, int h, int f) {
- width = w;
- height = h;
- format = f;
+ width = w;
+ height = h;
+ format = f;
}
};
-#ifndef DEBUG_CALC_FPS
-#define CALC_FPS() ((void)0)
-#define CALC_INIT() ((void)0)
-#else
-#define CALC_FPS() CalcFps::getInstance().Fps()
-#define CALC_INIT() CalcFps::getInstance().Init()
-
-class CalcFps : public Singleton<CalcFps> {
-public:
- CalcFps();
- ~CalcFps();
-
- void Init();
- void Fps();
-
-private:
- static const unsigned int MAX_FPS_CALC_PERIOD_IN_FRAMES = 128;
- static const unsigned int MAX_FRAMEARRIVAL_STEPS = 50;
- static const unsigned int MAX_DEBUG_FPS_LEVEL = 2;
-
- struct debug_fps_metadata_t {
- /*fps calculation based on time or number of frames*/
- enum DfmType {
- DFM_FRAMES = 0,
- DFM_TIME = 1,
- };
-
- DfmType type;
-
- /* indicates how much time do we wait till we calculate FPS */
- unsigned long time_period;
-
- /*indicates how much time elapsed since we report fps*/
- float time_elapsed;
-
- /* indicates how many frames do we wait till we calculate FPS */
- unsigned int period;
- /* current frame, will go upto period, and then reset */
- unsigned int curr_frame;
- /* frame will arrive at a multiple of 16666 us at the display.
- This indicates how many steps to consider for our calculations.
- For example, if framearrival_steps = 10, then the frame that arrived
- after 166660 us or more will be ignored.
- */
- unsigned int framearrival_steps;
- /* ignorethresh_us = framearrival_steps * 16666 */
- nsecs_t ignorethresh_us;
- /* used to calculate the actual frame arrival step, the times might not be
- accurate
- */
- unsigned int margin_us;
-
- /* actual data storage */
- nsecs_t framearrivals[MAX_FPS_CALC_PERIOD_IN_FRAMES];
- nsecs_t accum_framearrivals[MAX_FRAMEARRIVAL_STEPS];
- };
-
-private:
- void populate_debug_fps_metadata(void);
- void print_fps(float fps);
- void calc_fps(nsecs_t currtime_us);
-
-private:
- debug_fps_metadata_t debug_fps_metadata;
- unsigned int debug_fps_level;
-};
-#endif
-
#if 0
class QCBaseLayer
{
-// int mS3DFormat;
+ // int mS3DFormat;
int32_t mComposeS3DFormat;
-public:
+ public:
QCBaseLayer()
{
mComposeS3DFormat = 0;
@@ -203,10 +164,10 @@
eS3D_SIDE_BY_SIDE = 0x10000,
eS3D_TOP_BOTTOM = 0x20000
};
-/*
- virtual status_t setStereoscopic3DFormat(int format) { mS3DFormat = format; return 0; }
- virtual int getStereoscopic3DFormat() const { return mS3DFormat; }
- */
+ /*
+ virtual status_t setStereoscopic3DFormat(int format) { mS3DFormat = format; return 0; }
+ virtual int getStereoscopic3DFormat() const { return mS3DFormat; }
+ */
void setS3DComposeFormat (int32_t hints)
{
if (hints & HWC_HINT_DRAW_S3D_SIDE_BY_SIDE)
@@ -242,21 +203,6 @@
*/
bool isGPUSupportedFormat(int format);
-/*
- * Adreno is not optimized for GL_TEXTURE_EXTERNAL_OES
- * texure target. DO NOT choose TEXTURE_EXTERNAL_OES
- * target for RGB formats.
- *
- * Based on the pixel format, decide the texture target.
- *
- * @param : pixel format to check
- *
- * @return : GL_TEXTURE_2D for RGB formats, and
- * GL_TEXTURE_EXTERNAL_OES for YUV formats.
- *
-*/
-
-int decideTextureTarget (const int pixel_format);
/*
* Gets the number of arguments required for this operation.
@@ -277,8 +223,8 @@
* @return True if a memory reallocation is required.
*/
bool needNewBuffer(const qBufGeometry currentGeometry,
- const qBufGeometry requiredGeometry,
- const qBufGeometry updatedGeometry);
+ const qBufGeometry requiredGeometry,
+ const qBufGeometry updatedGeometry);
/*
* Update the geometry of this buffer without reallocation.
@@ -327,13 +273,6 @@
bool isUpdatingFB(HWCCompositionType compositionType);
/*
- * Get the current composition Type
- *
- * @return the compositon Type
- */
-int getCompositionType();
-
-/*
* Clear region implementation for C2D/MDP versions.
*
* @param: region to be cleared
@@ -355,9 +294,8 @@
* @return: external display to be enabled
*
*/
-external_display handleEventHDMI(external_display newEvent, external_display
- currEvent);
-
+external_display_type handleEventHDMI(external_display_type disp, int value,
+ external_display_type currDispType);
/*
* Checks if layers need to be dumped based on system property "debug.sf.dump"
* for raw dumps and "debug.sf.dump.png" for png dumps.
@@ -389,6 +327,10 @@
*
*/
void dumpLayer(int moduleCompositionType, int listFlags, size_t layerIndex,
- hwc_layer_t hwLayers[]);
+ hwc_layer_t hwLayers[]);
+
+bool needsAspectRatio (int wRatio, int hRatio);
+void applyPixelAspectRatio (int wRatio, int hRatio, int orientation, int fbWidth,
+ int fbHeight, Rect& visibleRect, GLfloat vertices[][2]);
#endif // INCLUDE_LIBQCOM_UI
diff --git a/libqcomui/qcomutils/IdleInvalidator.cpp b/libqcomui/qcomutils/IdleInvalidator.cpp
new file mode 100755
index 0000000..0b98e11
--- /dev/null
+++ b/libqcomui/qcomutils/IdleInvalidator.cpp
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 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.
+ */
+
+#include "IdleInvalidator.h"
+#include <unistd.h>
+
+#define II_DEBUG 1
+
+static const char *threadName = "Invalidator";
+InvalidatorHandler IdleInvalidator::mHandler = NULL;
+android::sp<IdleInvalidator> IdleInvalidator::sInstance(0);
+
+IdleInvalidator::IdleInvalidator(): Thread(false), mHwcContext(0),
+ mSleepAgain(false), mSleepTime(0) {
+ ALOGE_IF(II_DEBUG, "shs %s", __func__);
+ }
+
+int IdleInvalidator::init(InvalidatorHandler reg_handler, void* user_data,
+ unsigned int idleSleepTime) {
+ ALOGE_IF(II_DEBUG, "shs %s", __func__);
+
+ /* store registered handler */
+ mHandler = reg_handler;
+ mHwcContext = user_data;
+ mSleepTime = idleSleepTime; //Time in millis
+ return 0;
+}
+
+bool IdleInvalidator::threadLoop() {
+ ALOGE_IF(II_DEBUG, "shs %s", __func__);
+ usleep(mSleepTime * 1000);
+ if(mSleepAgain) {
+ //We need to sleep again!
+ mSleepAgain = false;
+ return true;
+ }
+
+ mHandler((void*)mHwcContext);
+ return false;
+}
+
+int IdleInvalidator::readyToRun() {
+ ALOGE_IF(II_DEBUG, "shs %s", __func__);
+ return 0; /*NO_ERROR*/
+}
+
+void IdleInvalidator::onFirstRef() {
+ ALOGE_IF(II_DEBUG, "shs %s", __func__);
+}
+
+void IdleInvalidator::markForSleep() {
+ mSleepAgain = true;
+ //Triggers the threadLoop to run, if not already running.
+ run(threadName, android::PRIORITY_AUDIO);
+}
+
+IdleInvalidator *IdleInvalidator::getInstance() {
+ ALOGE_IF(II_DEBUG, "shs %s", __func__);
+ if(sInstance.get() == NULL)
+ sInstance = new IdleInvalidator();
+ return sInstance.get();
+}
diff --git a/libqcomui/qcomutils/IdleInvalidator.h b/libqcomui/qcomutils/IdleInvalidator.h
new file mode 100755
index 0000000..930cd35
--- /dev/null
+++ b/libqcomui/qcomutils/IdleInvalidator.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 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 INCLUDE_IDLEINVALIDATOR
+#define INCLUDE_IDLEINVALIDATOR
+
+#include <cutils/log.h>
+#include <utils/threads.h>
+
+typedef void (*InvalidatorHandler)(void*);
+
+class IdleInvalidator : public android::Thread {
+ void *mHwcContext;
+ bool mSleepAgain;
+ unsigned int mSleepTime;
+ static InvalidatorHandler mHandler;
+ static android::sp<IdleInvalidator> sInstance;
+
+ public:
+ IdleInvalidator();
+ /* init timer obj */
+ int init(InvalidatorHandler reg_handler, void* user_data, unsigned int
+ idleSleepTime);
+ void markForSleep();
+ /*Overrides*/
+ virtual bool threadLoop();
+ virtual int readyToRun();
+ virtual void onFirstRef();
+ static IdleInvalidator *getInstance();
+};
+
+#endif // INCLUDE_IDLEINVALIDATOR
diff --git a/libqcomui/qcomutils/comptype.h b/libqcomui/qcomutils/comptype.h
new file mode 100644
index 0000000..603e143
--- /dev/null
+++ b/libqcomui/qcomutils/comptype.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 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 INCLUDE_LIBQCOM_COMPTYPES
+#define INCLUDE_LIBQCOM_COMPTYPES
+
+#include <stdint.h>
+#include <utils/Singleton.h>
+#include <cutils/properties.h>
+
+using namespace android;
+
+// Enum containing the supported composition types
+enum {
+ COMPOSITION_TYPE_GPU = 0,
+ COMPOSITION_TYPE_MDP = 0x1,
+ COMPOSITION_TYPE_C2D = 0x2,
+ COMPOSITION_TYPE_CPU = 0x4,
+ COMPOSITION_TYPE_DYN = 0x8
+};
+
+/* This class caches the composition type
+ */
+class QCCompositionType : public Singleton <QCCompositionType>
+{
+ public:
+ QCCompositionType();
+ ~QCCompositionType() { }
+ int getCompositionType() {return mCompositionType;}
+ private:
+ int mCompositionType;
+
+};
+
+ANDROID_SINGLETON_STATIC_INSTANCE(QCCompositionType);
+inline QCCompositionType::QCCompositionType()
+{
+ char property[PROPERTY_VALUE_MAX];
+ mCompositionType = 0;
+ if (property_get("debug.sf.hw", property, NULL) > 0) {
+ if(atoi(property) == 0) {
+ mCompositionType = COMPOSITION_TYPE_CPU;
+ } else { //debug.sf.hw = 1
+ property_get("debug.composition.type", property, NULL);
+ if (property == NULL) {
+ mCompositionType = COMPOSITION_TYPE_GPU;
+ } else if ((strncmp(property, "mdp", 3)) == 0) {
+ mCompositionType = COMPOSITION_TYPE_MDP;
+ } else if ((strncmp(property, "c2d", 3)) == 0) {
+ mCompositionType = COMPOSITION_TYPE_C2D;
+ } else if ((strncmp(property, "dyn", 3)) == 0) {
+#ifdef USE_MDP3
+ mCompositionType = COMPOSITION_TYPE_DYN | COMPOSITION_TYPE_MDP;
+#else
+ mCompositionType = COMPOSITION_TYPE_DYN | COMPOSITION_TYPE_C2D;
+#endif
+ } else {
+ mCompositionType = COMPOSITION_TYPE_GPU;
+ }
+ }
+ } else { //debug.sf.hw is not set. Use cpu composition
+ mCompositionType = COMPOSITION_TYPE_CPU;
+ }
+
+}
+#endif //INCLUDE_LIBQCOM_COMPTYPES
diff --git a/libqcomui/qcomutils/profiler.cpp b/libqcomui/qcomutils/profiler.cpp
new file mode 100755
index 0000000..73854bc
--- /dev/null
+++ b/libqcomui/qcomutils/profiler.cpp
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2011-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.
+ */
+
+#include "profiler.h"
+
+#ifdef DEBUG_CALC_FPS
+
+#define LOG_TAG "CALCFPS"
+#define LOG_NDDEBUG 0
+
+ANDROID_SINGLETON_STATIC_INSTANCE(CalcFps) ;
+
+CalcFps::CalcFps() {
+ debug_fps_level = 0;
+ Init();
+}
+
+CalcFps::~CalcFps() {
+}
+
+void CalcFps::Init() {
+ char prop[PROPERTY_VALUE_MAX];
+ property_get("debug.gr.calcfps", prop, "0");
+ debug_fps_level = atoi(prop);
+ if (debug_fps_level > MAX_DEBUG_FPS_LEVEL) {
+ ALOGW("out of range value for debug.gr.calcfps, using 0");
+ debug_fps_level = 0;
+ }
+
+ ALOGD("DEBUG_CALC_FPS: %d", debug_fps_level);
+ populate_debug_fps_metadata();
+}
+
+void CalcFps::Fps() {
+ if (debug_fps_level > 0)
+ calc_fps(ns2us(systemTime()));
+}
+
+void CalcFps::populate_debug_fps_metadata(void)
+{
+ char prop[PROPERTY_VALUE_MAX];
+
+ /*defaults calculation of fps to based on number of frames*/
+ property_get("debug.gr.calcfps.type", prop, "0");
+ debug_fps_metadata.type = (debug_fps_metadata_t::DfmType) atoi(prop);
+
+ /*defaults to 1000ms*/
+ property_get("debug.gr.calcfps.timeperiod", prop, "1000");
+ debug_fps_metadata.time_period = atoi(prop);
+
+ property_get("debug.gr.calcfps.period", prop, "10");
+ debug_fps_metadata.period = atoi(prop);
+
+ if (debug_fps_metadata.period > MAX_FPS_CALC_PERIOD_IN_FRAMES) {
+ debug_fps_metadata.period = MAX_FPS_CALC_PERIOD_IN_FRAMES;
+ }
+
+ /* default ignorethresh_us: 500 milli seconds */
+ property_get("debug.gr.calcfps.ignorethresh_us", prop, "500000");
+ debug_fps_metadata.ignorethresh_us = atoi(prop);
+
+ debug_fps_metadata.framearrival_steps =
+ (debug_fps_metadata.ignorethresh_us / 16666);
+
+ if (debug_fps_metadata.framearrival_steps > MAX_FRAMEARRIVAL_STEPS) {
+ debug_fps_metadata.framearrival_steps = MAX_FRAMEARRIVAL_STEPS;
+ debug_fps_metadata.ignorethresh_us =
+ debug_fps_metadata.framearrival_steps * 16666;
+ }
+
+ /* 2ms margin of error for the gettimeofday */
+ debug_fps_metadata.margin_us = 2000;
+
+ for (unsigned int i = 0; i < MAX_FRAMEARRIVAL_STEPS; i++)
+ debug_fps_metadata.accum_framearrivals[i] = 0;
+
+ ALOGD("period: %d", debug_fps_metadata.period);
+ ALOGD("ignorethresh_us: %lld", debug_fps_metadata.ignorethresh_us);
+}
+
+void CalcFps::print_fps(float fps)
+{
+ if (debug_fps_metadata_t::DFM_FRAMES == debug_fps_metadata.type)
+ ALOGD("FPS for last %d frames: %3.2f", debug_fps_metadata.period, fps);
+ else
+ ALOGD("FPS for last (%f ms, %d frames): %3.2f",
+ debug_fps_metadata.time_elapsed,
+ debug_fps_metadata.curr_frame, fps);
+
+ debug_fps_metadata.curr_frame = 0;
+ debug_fps_metadata.time_elapsed = 0.0;
+
+ if (debug_fps_level > 1) {
+ ALOGD("Frame Arrival Distribution:");
+ for (unsigned int i = 0;
+ i < ((debug_fps_metadata.framearrival_steps / 6) + 1);
+ i++) {
+ ALOGD("%lld %lld %lld %lld %lld %lld",
+ debug_fps_metadata.accum_framearrivals[i*6],
+ debug_fps_metadata.accum_framearrivals[i*6+1],
+ debug_fps_metadata.accum_framearrivals[i*6+2],
+ debug_fps_metadata.accum_framearrivals[i*6+3],
+ debug_fps_metadata.accum_framearrivals[i*6+4],
+ debug_fps_metadata.accum_framearrivals[i*6+5]);
+ }
+
+ /* We are done with displaying, now clear the stats */
+ for (unsigned int i = 0;
+ i < debug_fps_metadata.framearrival_steps;
+ i++)
+ debug_fps_metadata.accum_framearrivals[i] = 0;
+ }
+ return;
+}
+
+void CalcFps::calc_fps(nsecs_t currtime_us)
+{
+ static nsecs_t oldtime_us = 0;
+
+ nsecs_t diff = currtime_us - oldtime_us;
+
+ oldtime_us = currtime_us;
+
+ if (debug_fps_metadata_t::DFM_FRAMES == debug_fps_metadata.type &&
+ diff > debug_fps_metadata.ignorethresh_us) {
+ return;
+ }
+
+ if (debug_fps_metadata.curr_frame < MAX_FPS_CALC_PERIOD_IN_FRAMES) {
+ debug_fps_metadata.framearrivals[debug_fps_metadata.curr_frame] = diff;
+ }
+
+ debug_fps_metadata.curr_frame++;
+
+ if (debug_fps_level > 1) {
+ unsigned int currstep = (diff + debug_fps_metadata.margin_us) / 16666;
+
+ if (currstep < debug_fps_metadata.framearrival_steps) {
+ debug_fps_metadata.accum_framearrivals[currstep-1]++;
+ }
+ }
+
+ if (debug_fps_metadata_t::DFM_FRAMES == debug_fps_metadata.type) {
+ if (debug_fps_metadata.curr_frame == debug_fps_metadata.period) {
+ /* time to calculate and display FPS */
+ nsecs_t sum = 0;
+ for (unsigned int i = 0; i < debug_fps_metadata.period; i++)
+ sum += debug_fps_metadata.framearrivals[i];
+ print_fps((debug_fps_metadata.period * float(1000000))/float(sum));
+ }
+ }
+ else if (debug_fps_metadata_t::DFM_TIME == debug_fps_metadata.type) {
+ debug_fps_metadata.time_elapsed += ((float)diff/1000.0);
+ if (debug_fps_metadata.time_elapsed >= debug_fps_metadata.time_period) {
+ float fps = (1000.0 * debug_fps_metadata.curr_frame)/
+ (float)debug_fps_metadata.time_elapsed;
+ print_fps(fps);
+ }
+ }
+ return;
+}
+#endif
diff --git a/libqcomui/qcomutils/profiler.h b/libqcomui/qcomutils/profiler.h
new file mode 100755
index 0000000..394f490
--- /dev/null
+++ b/libqcomui/qcomutils/profiler.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2011-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 INCLUDE_PROFILER
+#define INCLUDE_PROFILER
+
+#include <stdio.h>
+#include <utils/Singleton.h>
+#include <cutils/properties.h>
+#include <cutils/log.h>
+using namespace android;
+
+#ifndef DEBUG_CALC_FPS
+#define CALC_FPS() ((void)0)
+#define CALC_INIT() ((void)0)
+#else
+#define CALC_FPS() CalcFps::getInstance().Fps()
+#define CALC_INIT() CalcFps::getInstance().Init()
+
+class CalcFps : public Singleton<CalcFps> {
+ public:
+ CalcFps();
+ ~CalcFps();
+
+ void Init();
+ void Fps();
+
+ private:
+ static const unsigned int MAX_FPS_CALC_PERIOD_IN_FRAMES = 128;
+ static const unsigned int MAX_FRAMEARRIVAL_STEPS = 50;
+ static const unsigned int MAX_DEBUG_FPS_LEVEL = 2;
+
+ struct debug_fps_metadata_t {
+ /*fps calculation based on time or number of frames*/
+ enum DfmType {
+ DFM_FRAMES = 0,
+ DFM_TIME = 1,
+ };
+
+ DfmType type;
+
+ /* indicates how much time do we wait till we calculate FPS */
+ unsigned long time_period;
+
+ /*indicates how much time elapsed since we report fps*/
+ float time_elapsed;
+
+ /* indicates how many frames do we wait till we calculate FPS */
+ unsigned int period;
+ /* current frame, will go upto period, and then reset */
+ unsigned int curr_frame;
+ /* frame will arrive at a multiple of 16666 us at the display.
+ This indicates how many steps to consider for our calculations.
+ For example, if framearrival_steps = 10, then the frame that arrived
+ after 166660 us or more will be ignored.
+ */
+ unsigned int framearrival_steps;
+ /* ignorethresh_us = framearrival_steps * 16666 */
+ nsecs_t ignorethresh_us;
+ /* used to calculate the actual frame arrival step, the times might not be
+ accurate
+ */
+ unsigned int margin_us;
+
+ /* actual data storage */
+ nsecs_t framearrivals[MAX_FPS_CALC_PERIOD_IN_FRAMES];
+ nsecs_t accum_framearrivals[MAX_FRAMEARRIVAL_STEPS];
+ };
+
+ private:
+ void populate_debug_fps_metadata(void);
+ void print_fps(float fps);
+ void calc_fps(nsecs_t currtime_us);
+
+ private:
+ debug_fps_metadata_t debug_fps_metadata;
+ unsigned int debug_fps_level;
+};
+#endif
+
+#endif // INCLUDE_PROFILER
diff --git a/libtilerenderer/tilerenderer.cpp b/libtilerenderer/tilerenderer.cpp
index 6e8f847..4ed6895 100644
--- a/libtilerenderer/tilerenderer.cpp
+++ b/libtilerenderer/tilerenderer.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2010 The Android Open Source Project
- * Copyright (c) 2011 Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-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.
@@ -52,7 +52,7 @@
if (!left && !right && !top && !bottom) {
//can't do tile rendering
- LOGE("can't tile render; drity region, width, height not available");
+ ALOGE("can't tile render; drity region, width, height not available");
return;
}
diff --git a/libtilerenderer/tilerenderer.h b/libtilerenderer/tilerenderer.h
index bec225d..7f8d608 100644
--- a/libtilerenderer/tilerenderer.h
+++ b/libtilerenderer/tilerenderer.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2010 The Android Open Source Project
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-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.
@@ -25,14 +25,14 @@
class OpenGLRenderer;
class TileRenderer: public Singleton<TileRenderer> {
-public:
+ public:
TileRenderer();
~TileRenderer();
void startTileRendering(OpenGLRenderer* renderer, int left, int top, int right, int bottom);
void endTileRendering(OpenGLRenderer*);
-private:
+ private:
bool mIsTiled;
};