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: Ia53650759d4fe99bde395b7b4e8e02e6e65845e0
This commit is contained in:
parent
2d968bf0cc
commit
7341799797
@ -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))
|
||||
|
59
libcopybit/Android.mk
Normal file
59
libcopybit/Android.mk
Normal file
@ -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
|
0
libcopybit/MODULE_LICENSE_APACHE2
Normal file
0
libcopybit/MODULE_LICENSE_APACHE2
Normal file
189
libcopybit/NOTICE
Normal file
189
libcopybit/NOTICE
Normal file
@ -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
|
618
libcopybit/c2d2.h
Normal file
618
libcopybit/c2d2.h
Normal file
@ -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_ */
|
553
libcopybit/copybit.cpp
Normal file
553
libcopybit/copybit.cpp
Normal file
@ -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;
|
||||
}
|
230
libcopybit/copybit.h
Normal file
230
libcopybit/copybit.h
Normal file
@ -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
|
1477
libcopybit/copybit_c2d.cpp
Normal file
1477
libcopybit/copybit_c2d.cpp
Normal file
File diff suppressed because it is too large
Load Diff
56
libcopybit/copybit_priv.h
Normal file
56
libcopybit/copybit_priv.h
Normal file
@ -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;
|
||||
};
|
263
libcopybit/software_converter.cpp
Normal file
263
libcopybit/software_converter.cpp
Normal file
@ -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;
|
||||
}
|
62
libcopybit/software_converter.h
Normal file
62
libcopybit/software_converter.h
Normal file
@ -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);
|
@ -4,8 +4,7 @@ include $(CLEAR_VARS)
|
||||
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\"
|
||||
|
@ -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 @@ namespace {
|
||||
|
||||
/* 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 @@ namespace {
|
||||
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 @@ namespace {
|
||||
|
||||
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 @@ genlock_status_t genlock_create_lock(native_handle_t *buffer_handle)
|
||||
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_status_t genlock_create_lock(native_handle_t *buffer_handle)
|
||||
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 @@ genlock_status_t genlock_create_lock(native_handle_t *buffer_handle)
|
||||
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 @@ genlock_status_t genlock_attach_lock(native_handle_t *buffer_handle)
|
||||
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 @@ genlock_status_t genlock_attach_lock(native_handle_t *buffer_handle)
|
||||
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 @@ genlock_status_t genlock_attach_lock(native_handle_t *buffer_handle)
|
||||
* @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 @@ genlock_status_t genlock_lock_buffer(native_handle_t *buffer_handle,
|
||||
*
|
||||
* @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;
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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 @@ static bool canFallback(int compositionType, int usage, bool triedSystem)
|
||||
// 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 @@ IonController::IonController()
|
||||
}
|
||||
|
||||
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 @@ int IonController::allocate(alloc_data& data, int usage,
|
||||
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 @@ int IonController::allocate(alloc_data& data, int usage,
|
||||
|
||||
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 @@ int IonController::allocate(alloc_data& data, int usage,
|
||||
}
|
||||
|
||||
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 @@ sp<IMemAlloc> IonController::getAllocator(int flags)
|
||||
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 @@ PmemKernelController::~PmemKernelController()
|
||||
}
|
||||
|
||||
int PmemKernelController::allocate(alloc_data& data, int usage,
|
||||
int compositionType)
|
||||
int compositionType)
|
||||
{
|
||||
int ret = 0;
|
||||
bool adspFallback = false;
|
||||
@ -258,12 +265,13 @@ PmemAshmemController::~PmemAshmemController()
|
||||
}
|
||||
|
||||
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 @@ int PmemAshmemController::allocate(alloc_data& data, int usage,
|
||||
// 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 @@ sp<IMemAlloc> PmemAshmemController::getAllocator(int flags)
|
||||
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 @@ size_t getBufferSizeAndDimensions(int width, int height, int format,
|
||||
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 @@ size_t getBufferSizeAndDimensions(int width, int height, int format,
|
||||
// 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)
|
||||
|
@ -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
|
||||
|
@ -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 @@ int AshmemAlloc::alloc_buffer(alloc_data& data)
|
||||
} 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 @@ int AshmemAlloc::alloc_buffer(alloc_data& data)
|
||||
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::alloc_buffer(alloc_data& data)
|
||||
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 @@ int AshmemAlloc::map_buffer(void **pBase, size_t size, int offset, int fd)
|
||||
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 AshmemAlloc::unmap_buffer(void *base, size_t size, int offset)
|
||||
int err = munmap(base, size);
|
||||
if(err) {
|
||||
ALOGE("ashmem: Failed to unmap memory at %p: %s",
|
||||
base, strerror(errno));
|
||||
base, strerror(errno));
|
||||
}
|
||||
return err;
|
||||
|
||||
|
@ -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 */
|
||||
|
181
libgralloc/fb_priv.h
Normal file
181
libgralloc/fb_priv.h
Normal file
@ -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 */
|
File diff suppressed because it is too large
Load Diff
56
libgralloc/gpu.cpp
Executable file → Normal file
56
libgralloc/gpu.cpp
Executable file → Normal file
@ -32,34 +32,12 @@ using namespace gralloc;
|
||||
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 @@ gpu_context_t::gpu_context_t(const private_module_t* module,
|
||||
}
|
||||
|
||||
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_locked(size_t size, int usage,
|
||||
|
||||
|
||||
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 @@ int gpu_context_t::gralloc_alloc_buffer(size_t size, int usage,
|
||||
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 @@ int gpu_context_t::gralloc_alloc_buffer(size_t size, int usage,
|
||||
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 @@ void gpu_context_t::getGrallocInformationFromFormat(int inputFormat,
|
||||
}
|
||||
|
||||
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 @@ int gpu_context_t::alloc_impl(int w, int h, int format, int usage,
|
||||
// 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 gpu_context_t::free_impl(private_handle_t const* hnd) {
|
||||
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::free_impl(private_handle_t const* hnd) {
|
||||
}
|
||||
|
||||
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 @@ int gpu_context_t::gralloc_alloc(alloc_device_t* dev, int w, int h, int format,
|
||||
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_alloc_size(alloc_device_t* dev, int w, int h, int for
|
||||
|
||||
|
||||
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;
|
||||
|
@ -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
|
||||
|
@ -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 @@ inline size_t ALIGN(size_t x, size_t align) {
|
||||
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 @@ void free_buffer(private_handle_t *hnd);
|
||||
|
||||
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(); }
|
||||
};
|
||||
|
@ -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 namespace gralloc;
|
||||
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);
|
||||
|
@ -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 @@ enum {
|
||||
* 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 {
|
||||
};
|
||||
|
||||
|
||||
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 @@ enum {
|
||||
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 {
|
||||
};
|
||||
|
||||
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 @@ struct private_module_t {
|
||||
#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_ */
|
||||
|
@ -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 @@ int IonAlloc::open_device()
|
||||
|
||||
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 @@ void IonAlloc::close_device()
|
||||
|
||||
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 @@ int IonAlloc::alloc_buffer(alloc_data& data)
|
||||
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 @@ int IonAlloc::alloc_buffer(alloc_data& data)
|
||||
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 @@ int IonAlloc::alloc_buffer(alloc_data& data)
|
||||
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 @@ int IonAlloc::alloc_buffer(alloc_data& data)
|
||||
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 @@ int IonAlloc::map_buffer(void **pBase, size_t size, int offset, int fd)
|
||||
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 @@ int IonAlloc::unmap_buffer(void *base, size_t size, int offset)
|
||||
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 @@ int IonAlloc::clean_buffer(void *base, size_t size, int offset, int fd)
|
||||
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 @@ int IonAlloc::clean_buffer(void *base, size_t size, int offset, int fd)
|
||||
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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
53
libgralloc/mapper.cpp
Executable file → Normal file
53
libgralloc/mapper.cpp
Executable file → Normal file
@ -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 sp<IMemAlloc> getAllocator(int flags)
|
||||
}
|
||||
|
||||
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 @@ static int gralloc_map(gralloc_module_t const* module,
|
||||
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_map(gralloc_module_t const* module,
|
||||
}
|
||||
|
||||
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 @@ static pthread_mutex_t sMapLock = PTHREAD_MUTEX_INITIALIZER;
|
||||
/*****************************************************************************/
|
||||
|
||||
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_register_buffer(gralloc_module_t const* module,
|
||||
}
|
||||
|
||||
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 gralloc_unregister_buffer(gralloc_module_t const* module,
|
||||
}
|
||||
|
||||
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 @@ int terminateBuffer(gralloc_module_t const* module,
|
||||
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 terminateBuffer(gralloc_module_t const* module,
|
||||
}
|
||||
|
||||
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 gralloc_lock(gralloc_module_t const* module,
|
||||
|
||||
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_lock(gralloc_module_t const* module,
|
||||
}
|
||||
|
||||
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 gralloc_unlock(gralloc_module_t const* module,
|
||||
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_unlock(gralloc_module_t const* module,
|
||||
/*****************************************************************************/
|
||||
|
||||
int gralloc_perform(struct gralloc_module_t const* module,
|
||||
int operation, ... )
|
||||
int operation, ... )
|
||||
{
|
||||
int res = -EINVAL;
|
||||
va_list args;
|
||||
@ -324,12 +325,12 @@ int gralloc_perform(struct gralloc_module_t const* module,
|
||||
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 @@ int gralloc_perform(struct gralloc_module_t const* module,
|
||||
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;
|
||||
|
@ -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
|
||||
|
@ -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 @@ ssize_t SimpleBestFitAllocator::alloc(size_t size, uint32_t flags)
|
||||
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 @@ ssize_t SimpleBestFitAllocator::alloc(size_t size, uint32_t flags)
|
||||
// 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 @@ SimpleBestFitAllocator::chunk_t* SimpleBestFitAllocator::dealloc(size_t start)
|
||||
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 @@ SimpleBestFitAllocator::chunk_t* SimpleBestFitAllocator::dealloc(size_t start)
|
||||
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;
|
||||
}
|
||||
|
@ -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 @@ class LinkedList
|
||||
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 @@ public:
|
||||
}
|
||||
|
||||
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 @@ public:
|
||||
|
||||
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_ */
|
||||
|
@ -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 @@ int PmemUserspaceAlloc::init_pmem_area_locked()
|
||||
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 @@ int PmemUserspaceAlloc::init_pmem_area_locked()
|
||||
} else {
|
||||
err = -errno;
|
||||
ALOGE("%s: Failed to open pmem device: %s", mPmemDev,
|
||||
strerror(errno));
|
||||
strerror(errno));
|
||||
}
|
||||
return err;
|
||||
}
|
||||
@ -203,13 +203,13 @@ int PmemUserspaceAlloc::alloc_buffer(alloc_data& data)
|
||||
|
||||
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::alloc_buffer(alloc_data& data)
|
||||
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 PmemUserspaceAlloc::map_buffer(void **pBase, size_t size, int offset, int fd
|
||||
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 @@ int PmemUserspaceAlloc::unmap_buffer(void *base, size_t size, int offset)
|
||||
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 @@ int PmemKernelAlloc::alloc_buffer(alloc_data& data)
|
||||
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 @@ int PmemKernelAlloc::alloc_buffer(alloc_data& data)
|
||||
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::alloc_buffer(alloc_data& data)
|
||||
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 PmemKernelAlloc::map_buffer(void **pBase, size_t size, int offset, int fd)
|
||||
{
|
||||
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 @@ int PmemKernelAlloc::unmap_buffer(void *base, size_t size, int offset)
|
||||
if (munmap(base, size)) {
|
||||
err = -errno;
|
||||
ALOGW("%s: Error unmapping memory at %p: %s",
|
||||
mPmemDev, base, strerror(err));
|
||||
mPmemDev, base, strerror(err));
|
||||
}
|
||||
return err;
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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)
|
||||
|
@ -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
|
145
libhwcomposer/hwc.cpp
Normal file
145
libhwcomposer/hwc.cpp
Normal file
@ -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;
|
||||
}
|
294
libhwcomposer/hwc_overlay.cpp
Normal file
294
libhwcomposer/hwc_overlay.cpp
Normal file
@ -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
|
114
libhwcomposer/hwc_qbuf.h
Normal file
114
libhwcomposer/hwc_qbuf.h
Normal file
@ -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
|
||||
|
96
libhwcomposer/hwc_utils.cpp
Normal file
96
libhwcomposer/hwc_utils.cpp
Normal file
@ -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
|
111
libhwcomposer/hwc_utils.h
Normal file
111
libhwcomposer/hwc_utils.h
Normal file
@ -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
|
File diff suppressed because it is too large
Load Diff
47
liboverlay/Android.mk
Executable file → Normal file
47
liboverlay/Android.mk
Executable file → Normal file
@ -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)
|
||||
|
270
liboverlay/mdpWrapper.h
Normal file
270
liboverlay/mdpWrapper.h
Normal file
@ -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
|
455
liboverlay/overlay.cpp
Normal file
455
liboverlay/overlay.cpp
Normal file
@ -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
|
103
liboverlay/overlay.h
Normal file
103
liboverlay/overlay.h
Normal file
@ -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
|
349
liboverlay/overlayCtrl.cpp
Normal file
349
liboverlay/overlayCtrl.cpp
Normal file
@ -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
|
365
liboverlay/overlayCtrlData.h
Normal file
365
liboverlay/overlayCtrlData.h
Normal file
@ -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
|
742
liboverlay/overlayImpl.h
Normal file
742
liboverlay/overlayImpl.h
Normal file
@ -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
|
File diff suppressed because it is too large
Load Diff
@ -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
|
@ -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;
|
||||
}
|
||||
|
||||
};
|
@ -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
|
289
liboverlay/overlayMdp.cpp
Normal file
289
liboverlay/overlayMdp.cpp
Normal file
@ -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
|
489
liboverlay/overlayMdp.h
Normal file
489
liboverlay/overlayMdp.h
Normal file
@ -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
|
205
liboverlay/overlayMem.h
Normal file
205
liboverlay/overlayMem.h
Normal file
@ -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
|
430
liboverlay/overlayRotator.cpp
Normal file
430
liboverlay/overlayRotator.cpp
Normal file
@ -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 ==");
|
||||
}
|
||||
}
|
554
liboverlay/overlayRotator.h
Normal file
554
liboverlay/overlayRotator.h
Normal file
@ -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
|
907
liboverlay/overlayState.h
Normal file
907
liboverlay/overlayState.h
Normal file
@ -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
|
503
liboverlay/overlayTransitions.cpp
Normal file
503
liboverlay/overlayTransitions.cpp
Normal file
@ -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
|
337
liboverlay/overlayUtils.cpp
Normal file
337
liboverlay/overlayUtils.cpp
Normal file
@ -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
|
1112
liboverlay/overlayUtils.h
Normal file
1112
liboverlay/overlayUtils.h
Normal file
File diff suppressed because it is too large
Load Diff
617
liboverlay/pipes/overlay3DPipe.h
Normal file
617
liboverlay/pipes/overlay3DPipe.h
Normal file
@ -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
|
213
liboverlay/pipes/overlayBypassPipe.h
Normal file
213
liboverlay/pipes/overlayBypassPipe.h
Normal file
@ -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
|
403
liboverlay/pipes/overlayGenPipe.h
Normal file
403
liboverlay/pipes/overlayGenPipe.h
Normal file
@ -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
|
128
liboverlay/pipes/overlayHdmiPipe.h
Normal file
128
liboverlay/pipes/overlayHdmiPipe.h
Normal file
@ -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
|
192
liboverlay/pipes/overlayUIMirrorPipe.h
Normal file
192
liboverlay/pipes/overlayUIMirrorPipe.h
Normal file
@ -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
|
@ -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 @@ else
|
||||
LOCAL_SHARED_LIBRARIES += libmemalloc
|
||||
endif
|
||||
|
||||
ifeq ($(TARGET_USES_MDP3), true)
|
||||
LOCAL_CFLAGS += -DUSE_MDP3
|
||||
endif
|
||||
|
||||
LOCAL_CFLAGS += -DDEBUG_CALC_FPS
|
||||
|
||||
LOCAL_MODULE := libQcomUI
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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 @@ enum {
|
||||
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,
|
||||
};
|
||||
|
||||
/*
|
||||
@ -80,17 +73,22 @@ enum {
|
||||
LAYER_ASYNCHRONOUS = 1<<1,
|
||||
};
|
||||
|
||||
/*
|
||||
* 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 @@ enum HWCCompositionType {
|
||||
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 @@ struct qBufGeometry {
|
||||
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 @@ public:
|
||||
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 @@ int checkBuffer(native_handle_t *buffer_handle, int size, int usage);
|
||||
*/
|
||||
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 @@ int getNumberOfArgsForOperation(int operation);
|
||||
* @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.
|
||||
@ -326,13 +272,6 @@ int getPerFrameFlags(int hwclFlags, int layerFlags);
|
||||
|
||||
bool isUpdatingFB(HWCCompositionType compositionType);
|
||||
|
||||
/*
|
||||
* Get the current composition Type
|
||||
*
|
||||
* @return the compositon Type
|
||||
*/
|
||||
int getCompositionType();
|
||||
|
||||
/*
|
||||
* Clear region implementation for C2D/MDP versions.
|
||||
*
|
||||
@ -355,9 +294,8 @@ int qcomuiClearRegion(Region region, EGLDisplay dpy, EGLSurface sur);
|
||||
* @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 @@ bool needToDumpLayers();
|
||||
*
|
||||
*/
|
||||
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
|
||||
|
88
libqcomui/qcomutils/IdleInvalidator.cpp
Executable file
88
libqcomui/qcomutils/IdleInvalidator.cpp
Executable file
@ -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();
|
||||
}
|
58
libqcomui/qcomutils/IdleInvalidator.h
Executable file
58
libqcomui/qcomutils/IdleInvalidator.h
Executable file
@ -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
|
92
libqcomui/qcomutils/comptype.h
Normal file
92
libqcomui/qcomutils/comptype.h
Normal file
@ -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
|
188
libqcomui/qcomutils/profiler.cpp
Executable file
188
libqcomui/qcomutils/profiler.cpp
Executable file
@ -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
|
107
libqcomui/qcomutils/profiler.h
Executable file
107
libqcomui/qcomutils/profiler.h
Executable file
@ -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
|
@ -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 @@ void TileRenderer::startTileRendering(OpenGLRenderer* renderer,
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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 @@ namespace uirenderer {
|
||||
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;
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user