qcom/display: Update HALs
- Update the display HAL from Code Aurora Forum - Add updated overlay library - Enable HWC with basic video going through overlay - Cleanup some files Change-Id: I65c687c51be458cee71213c79e03eeda962d9086
This commit is contained in:
committed by
Iliyan Malchev
parent
06ff498a7c
commit
29a26818d7
@@ -1,11 +1,9 @@
|
|||||||
#Enables the listed display HAL modules
|
#Enables the listed display HAL modules
|
||||||
|
|
||||||
#Libs to be built for all targets (including SDK)
|
|
||||||
display-hals := libqcomui
|
display-hals := libqcomui
|
||||||
|
|
||||||
#libs to be built for QCOM targets only
|
#libs to be built for QCOM targets only
|
||||||
#ifeq ($(call is-vendor-board-platform,QCOM),true)
|
#ifeq ($(call is-vendor-board-platform,QCOM),true)
|
||||||
display-hals += libgralloc libgenlock libcopybit
|
display-hals += libgralloc libgenlock libcopybit libhwcomposer liboverlay
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
include $(call all-named-subdir-makefiles,$(display-hals))
|
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_PRELINK_MODULE := false
|
||||||
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)
|
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)
|
||||||
LOCAL_SHARED_LIBRARIES := liblog libcutils
|
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_ADDITIONAL_DEPENDENCIES :=
|
||||||
LOCAL_SRC_FILES := genlock.cpp
|
LOCAL_SRC_FILES := genlock.cpp
|
||||||
LOCAL_CFLAGS:= -DLOG_TAG=\"libgenlock\"
|
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
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are
|
* modification, are permitted provided that the following conditions are
|
||||||
|
|||||||
@@ -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
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are
|
* modification, are permitted provided that the following conditions are
|
||||||
|
|||||||
@@ -11,8 +11,6 @@
|
|||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
# Use this flag until pmem/ashmem is implemented in the new gralloc
|
|
||||||
LOCAL_PATH := $(call my-dir)
|
LOCAL_PATH := $(call my-dir)
|
||||||
|
|
||||||
# HAL module implemenation, not prelinked and stored in
|
# HAL module implemenation, not prelinked and stored in
|
||||||
@@ -20,56 +18,41 @@ LOCAL_PATH := $(call my-dir)
|
|||||||
include $(CLEAR_VARS)
|
include $(CLEAR_VARS)
|
||||||
LOCAL_PRELINK_MODULE := false
|
LOCAL_PRELINK_MODULE := false
|
||||||
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
|
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
|
||||||
LOCAL_SHARED_LIBRARIES := liblog libcutils libGLESv1_CM libutils libmemalloc libQcomUI
|
LOCAL_SHARED_LIBRARIES := liblog libcutils libutils libmemalloc
|
||||||
LOCAL_SHARED_LIBRARIES += libgenlock
|
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/libgenlock
|
||||||
LOCAL_C_INCLUDES += hardware/qcom/display/libqcomui
|
LOCAL_C_INCLUDES += hardware/qcom/display/libqcomui
|
||||||
LOCAL_ADDITIONAL_DEPENDENCIES +=
|
|
||||||
LOCAL_SRC_FILES := framebuffer.cpp \
|
|
||||||
gpu.cpp \
|
|
||||||
gralloc.cpp \
|
|
||||||
mapper.cpp
|
|
||||||
|
|
||||||
LOCAL_MODULE := gralloc.$(TARGET_BOARD_PLATFORM)
|
LOCAL_MODULE := gralloc.$(TARGET_BOARD_PLATFORM)
|
||||||
LOCAL_MODULE_TAGS := optional
|
LOCAL_MODULE_TAGS := optional
|
||||||
LOCAL_CFLAGS:= -DLOG_TAG=\"$(TARGET_BOARD_PLATFORM).gralloc\" -DHOST -DDEBUG_CALC_FPS
|
LOCAL_CFLAGS := -DLOG_TAG=\"$(TARGET_BOARD_PLATFORM).gralloc\" \
|
||||||
|
-DDEBUG_CALC_FPS
|
||||||
|
LOCAL_SRC_FILES := gpu.cpp gralloc.cpp framebuffer.cpp mapper.cpp
|
||||||
|
|
||||||
ifeq ($(call is-board-platform,msm7627_surf msm7627_6x),true)
|
ifeq ($(TARGET_USES_POST_PROCESSING),true)
|
||||||
LOCAL_CFLAGS += -DTARGET_MSM7x27
|
LOCAL_CFLAGS += -DUSES_POST_PROCESSING
|
||||||
|
LOCAL_C_INCLUDES += $(TARGET_OUT_HEADERS)/pp/inc
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(TARGET_USES_MDP3), true)
|
||||||
|
LOCAL_CFLAGS += -DUSE_MDP3
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(TARGET_HAVE_HDMI_OUT),true)
|
ifeq ($(TARGET_HAVE_HDMI_OUT),true)
|
||||||
LOCAL_CFLAGS += -DHDMI_DUAL_DISPLAY
|
LOCAL_CFLAGS += -DHDMI_DUAL_DISPLAY
|
||||||
LOCAL_C_INCLUDES += hardware/qcom/display/liboverlay
|
|
||||||
LOCAL_SHARED_LIBRARIES += liboverlay
|
LOCAL_SHARED_LIBRARIES += liboverlay
|
||||||
endif
|
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)
|
include $(BUILD_SHARED_LIBRARY)
|
||||||
|
|
||||||
#MemAlloc Library
|
#MemAlloc Library
|
||||||
include $(CLEAR_VARS)
|
include $(CLEAR_VARS)
|
||||||
LOCAL_PRELINK_MODULE := false
|
LOCAL_PRELINK_MODULE := false
|
||||||
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)
|
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)
|
||||||
LOCAL_C_INCLUDES += hardware/qcom/display/libqcomui
|
LOCAL_C_INCLUDES := hardware/qcom/display/libqcomui
|
||||||
LOCAL_ADDITIONAL_DEPENDENCIES +=
|
|
||||||
LOCAL_SHARED_LIBRARIES := liblog libcutils libutils
|
LOCAL_SHARED_LIBRARIES := liblog libcutils libutils
|
||||||
LOCAL_SRC_FILES := ionalloc.cpp \
|
LOCAL_SRC_FILES := ionalloc.cpp alloc_controller.cpp
|
||||||
alloc_controller.cpp
|
|
||||||
LOCAL_CFLAGS:= -DLOG_TAG=\"memalloc\"
|
LOCAL_CFLAGS:= -DLOG_TAG=\"memalloc\"
|
||||||
|
|
||||||
ifeq ($(TARGET_USES_ION),true)
|
|
||||||
LOCAL_CFLAGS += -DUSE_ION
|
LOCAL_CFLAGS += -DUSE_ION
|
||||||
endif
|
|
||||||
|
|
||||||
LOCAL_MODULE := libmemalloc
|
LOCAL_MODULE := libmemalloc
|
||||||
LOCAL_MODULE_TAGS := optional
|
LOCAL_MODULE_TAGS := optional
|
||||||
include $(BUILD_SHARED_LIBRARY)
|
include $(BUILD_SHARED_LIBRARY)
|
||||||
|
|||||||
@@ -34,8 +34,10 @@
|
|||||||
#include "alloc_controller.h"
|
#include "alloc_controller.h"
|
||||||
#include "memalloc.h"
|
#include "memalloc.h"
|
||||||
#include "ionalloc.h"
|
#include "ionalloc.h"
|
||||||
|
#include "pmemalloc.h"
|
||||||
#include "ashmemalloc.h"
|
#include "ashmemalloc.h"
|
||||||
#include "gr.h"
|
#include "gr.h"
|
||||||
|
#include "qcomutils/comptype.h"
|
||||||
|
|
||||||
using namespace gralloc;
|
using namespace gralloc;
|
||||||
using android::sp;
|
using android::sp;
|
||||||
@@ -51,7 +53,7 @@ const int GRALLOC_HEAP_MASK = GRALLOC_USAGE_PRIVATE_ADSP_HEAP |
|
|||||||
|
|
||||||
|
|
||||||
//Common functions
|
//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
|
// Fallback to system heap when alloc fails unless
|
||||||
// 1. Composition type is MDP
|
// 1. Composition type is MDP
|
||||||
@@ -60,11 +62,12 @@ static bool canFallback(int compositionType, int usage, bool triedSystem)
|
|||||||
// 4. The heap type is protected
|
// 4. The heap type is protected
|
||||||
// 5. The buffer is meant for external display only
|
// 5. The buffer is meant for external display only
|
||||||
|
|
||||||
if(compositionType == MDP_COMPOSITION)
|
if(QCCompositionType::getInstance().getCompositionType() & COMPOSITION_TYPE_MDP)
|
||||||
return false;
|
return false;
|
||||||
if(triedSystem)
|
if(triedSystem)
|
||||||
return false;
|
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;
|
return false;
|
||||||
if(usage & (GRALLOC_HEAP_MASK | GRALLOC_USAGE_EXTERNAL_ONLY))
|
if(usage & (GRALLOC_HEAP_MASK | GRALLOC_USAGE_EXTERNAL_ONLY))
|
||||||
return false;
|
return false;
|
||||||
@@ -114,6 +117,8 @@ int IonController::allocate(alloc_data& data, int usage,
|
|||||||
bool noncontig = false;
|
bool noncontig = false;
|
||||||
|
|
||||||
data.uncached = useUncached(usage);
|
data.uncached = useUncached(usage);
|
||||||
|
data.allocType = 0;
|
||||||
|
|
||||||
if(usage & GRALLOC_USAGE_PRIVATE_UI_CONTIG_HEAP)
|
if(usage & GRALLOC_USAGE_PRIVATE_UI_CONTIG_HEAP)
|
||||||
ionFlags |= ION_HEAP(ION_SF_HEAP_ID);
|
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)
|
if(usage & GRALLOC_USAGE_PRIVATE_CAMERA_HEAP)
|
||||||
ionFlags |= ION_HEAP(ION_CAMERA_HEAP_ID);
|
ionFlags |= ION_HEAP(ION_CAMERA_HEAP_ID);
|
||||||
|
|
||||||
if(usage & GRALLOC_USAGE_PROTECTED)
|
if(usage & GRALLOC_USAGE_PRIVATE_CP_BUFFER)
|
||||||
ionFlags |= ION_SECURE;
|
ionFlags |= ION_SECURE;
|
||||||
|
|
||||||
if(usage & GRALLOC_USAGE_PRIVATE_DO_NOT_MAP)
|
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
|
// if no flags are set, default to
|
||||||
// SF + IOMMU heaps, so that bypass can work
|
// SF + IOMMU heaps, so that bypass can work
|
||||||
@@ -149,9 +156,9 @@ int IonController::allocate(alloc_data& data, int usage,
|
|||||||
|
|
||||||
data.flags = ionFlags;
|
data.flags = ionFlags;
|
||||||
ret = mIonAlloc->alloc_buffer(data);
|
ret = mIonAlloc->alloc_buffer(data);
|
||||||
|
|
||||||
// Fallback
|
// Fallback
|
||||||
if(ret < 0 && canFallback(compositionType,
|
if(ret < 0 && canFallback(usage,
|
||||||
usage,
|
|
||||||
(ionFlags & ION_SYSTEM_HEAP_ID)))
|
(ionFlags & ION_SYSTEM_HEAP_ID)))
|
||||||
{
|
{
|
||||||
ALOGW("Falling back to system heap");
|
ALOGW("Falling back to system heap");
|
||||||
@@ -161,7 +168,7 @@ int IonController::allocate(alloc_data& data, int usage,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(ret >= 0 ) {
|
if(ret >= 0 ) {
|
||||||
data.allocType = private_handle_t::PRIV_FLAGS_USES_ION;
|
data.allocType |= private_handle_t::PRIV_FLAGS_USES_ION;
|
||||||
if(noncontig)
|
if(noncontig)
|
||||||
data.allocType |= private_handle_t::PRIV_FLAGS_NONCONTIGUOUS_MEM;
|
data.allocType |= private_handle_t::PRIV_FLAGS_NONCONTIGUOUS_MEM;
|
||||||
if(ionFlags & ION_SECURE)
|
if(ionFlags & ION_SECURE)
|
||||||
@@ -183,9 +190,9 @@ sp<IMemAlloc> IonController::getAllocator(int flags)
|
|||||||
return memalloc;
|
return memalloc;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
//-------------- PmemKernelController-----------------------//
|
//-------------- PmemKernelController-----------------------//
|
||||||
|
//XXX: Remove - we're not using pmem anymore
|
||||||
|
#if 0
|
||||||
PmemKernelController::PmemKernelController()
|
PmemKernelController::PmemKernelController()
|
||||||
{
|
{
|
||||||
mPmemAdspAlloc = new PmemKernelAlloc(DEVICE_PMEM_ADSP);
|
mPmemAdspAlloc = new PmemKernelAlloc(DEVICE_PMEM_ADSP);
|
||||||
@@ -261,6 +268,7 @@ int PmemAshmemController::allocate(alloc_data& data, int usage,
|
|||||||
int compositionType)
|
int compositionType)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
data.allocType = 0;
|
||||||
|
|
||||||
// Make buffers cacheable by default
|
// Make buffers cacheable by default
|
||||||
data.uncached = false;
|
data.uncached = false;
|
||||||
@@ -298,7 +306,7 @@ int PmemAshmemController::allocate(alloc_data& data, int usage,
|
|||||||
// Fallback
|
// Fallback
|
||||||
if(ret >= 0 ) {
|
if(ret >= 0 ) {
|
||||||
data.allocType = private_handle_t::PRIV_FLAGS_USES_PMEM;
|
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");
|
ALOGW("Falling back to ashmem");
|
||||||
ret = mAshmemAlloc->alloc_buffer(data);
|
ret = mAshmemAlloc->alloc_buffer(data);
|
||||||
if(ret >= 0) {
|
if(ret >= 0) {
|
||||||
@@ -327,7 +335,6 @@ sp<IMemAlloc> PmemAshmemController::getAllocator(int flags)
|
|||||||
return memalloc;
|
return memalloc;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
size_t getBufferSizeAndDimensions(int width, int height, int format,
|
size_t getBufferSizeAndDimensions(int width, int height, int format,
|
||||||
int& alignedw, int &alignedh)
|
int& alignedw, int &alignedh)
|
||||||
{
|
{
|
||||||
@@ -383,9 +390,18 @@ size_t getBufferSizeAndDimensions(int width, int height, int format,
|
|||||||
}
|
}
|
||||||
size = ALIGN(size, 4096);
|
size = ALIGN(size, 4096);
|
||||||
break;
|
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:
|
default:
|
||||||
ALOGE("unrecognized pixel format: %d", format);
|
ALOGE("unrecognized pixel format: 0x%x", format);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are
|
* modification, are permitted provided that the following conditions are
|
||||||
|
|||||||
@@ -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
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are
|
* modification, are permitted provided that the following conditions are
|
||||||
|
|||||||
@@ -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
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are
|
* modification, are permitted provided that the following conditions are
|
||||||
|
|||||||
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 */
|
||||||
@@ -17,15 +17,11 @@
|
|||||||
|
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
|
||||||
#include <dlfcn.h>
|
|
||||||
|
|
||||||
#include <cutils/ashmem.h>
|
|
||||||
#include <cutils/log.h>
|
#include <cutils/log.h>
|
||||||
#include <cutils/properties.h>
|
#include <cutils/properties.h>
|
||||||
#include <utils/Timers.h>
|
#include <dlfcn.h>
|
||||||
|
|
||||||
#include <hardware/hardware.h>
|
#include <hardware/hardware.h>
|
||||||
#include <hardware/gralloc.h>
|
|
||||||
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
@@ -33,9 +29,6 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <utils/Timers.h>
|
|
||||||
|
|
||||||
#include <cutils/log.h>
|
|
||||||
#include <cutils/atomic.h>
|
#include <cutils/atomic.h>
|
||||||
|
|
||||||
#include <linux/fb.h>
|
#include <linux/fb.h>
|
||||||
@@ -44,18 +37,15 @@
|
|||||||
#include <GLES/gl.h>
|
#include <GLES/gl.h>
|
||||||
|
|
||||||
#include "gralloc_priv.h"
|
#include "gralloc_priv.h"
|
||||||
|
#include "fb_priv.h"
|
||||||
#include "gr.h"
|
#include "gr.h"
|
||||||
#ifdef NO_SURFACEFLINGER_SWAPINTERVAL
|
|
||||||
#include <cutils/properties.h>
|
#include <cutils/properties.h>
|
||||||
#endif
|
#include <qcomutils/profiler.h>
|
||||||
|
|
||||||
#include <qcom_ui.h>
|
#include "overlay.h"
|
||||||
|
namespace ovutils = overlay::utils;
|
||||||
|
|
||||||
#define FB_DEBUG 0
|
|
||||||
|
|
||||||
#if defined(HDMI_DUAL_DISPLAY)
|
|
||||||
#define EVEN_OUT(x) if (x & 0x0001) {x--;}
|
#define EVEN_OUT(x) if (x & 0x0001) {x--;}
|
||||||
using overlay::Overlay;
|
|
||||||
/** min of int a, b */
|
/** min of int a, b */
|
||||||
static inline int min(int a, int b) {
|
static inline int min(int a, int b) {
|
||||||
return (a<b) ? a : b;
|
return (a<b) ? a : b;
|
||||||
@@ -64,20 +54,9 @@ static inline int min(int a, int b) {
|
|||||||
static inline int max(int a, int b) {
|
static inline int max(int a, int b) {
|
||||||
return (a>b) ? a : b;
|
return (a>b) ? a : b;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
char framebufferStateName[] = {'S', 'R', 'A'};
|
char framebufferStateName[] = {'S', 'R', 'A'};
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
|
|
||||||
enum {
|
|
||||||
MDDI_PANEL = '1',
|
|
||||||
EBI2_PANEL = '2',
|
|
||||||
LCDC_PANEL = '3',
|
|
||||||
EXT_MDDI_PANEL = '4',
|
|
||||||
TV_PANEL = '5'
|
|
||||||
};
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
PAGE_FLIP = 0x00000001,
|
PAGE_FLIP = 0x00000001,
|
||||||
LOCKED = 0x00000002
|
LOCKED = 0x00000002
|
||||||
@@ -87,20 +66,12 @@ struct fb_context_t {
|
|||||||
framebuffer_device_t device;
|
framebuffer_device_t device;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int neworientation;
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
|
|
||||||
static void
|
|
||||||
msm_copy_buffer(buffer_handle_t handle, int fd,
|
|
||||||
int width, int height, int format,
|
|
||||||
int x, int y, int w, int h);
|
|
||||||
|
|
||||||
static int fb_setSwapInterval(struct framebuffer_device_t* dev,
|
static int fb_setSwapInterval(struct framebuffer_device_t* dev,
|
||||||
int interval)
|
int interval)
|
||||||
{
|
{
|
||||||
char pval[PROPERTY_VALUE_MAX];
|
char pval[PROPERTY_VALUE_MAX];
|
||||||
property_get("debug.gr.swapinterval", pval, "-1");
|
property_get("debug.egl.swapinterval", pval, "-1");
|
||||||
int property_interval = atoi(pval);
|
int property_interval = atoi(pval);
|
||||||
if (property_interval >= 0)
|
if (property_interval >= 0)
|
||||||
interval = property_interval;
|
interval = property_interval;
|
||||||
@@ -173,28 +144,30 @@ static void *disp_loop(void *ptr)
|
|||||||
int nxtAvail = ((nxtBuf.idx + 1) % m->numBuffers);
|
int nxtAvail = ((nxtBuf.idx + 1) % m->numBuffers);
|
||||||
pthread_mutex_lock(&(m->avail[nxtBuf.idx].lock));
|
pthread_mutex_lock(&(m->avail[nxtBuf.idx].lock));
|
||||||
m->avail[nxtBuf.idx].is_avail = true;
|
m->avail[nxtBuf.idx].is_avail = true;
|
||||||
m->avail[nxtBuf.idx].state = REF;
|
m->avail[nxtBuf.idx].state = SUB;
|
||||||
pthread_cond_broadcast(&(m->avail[nxtBuf.idx].cond));
|
pthread_cond_signal(&(m->avail[nxtBuf.idx].cond));
|
||||||
pthread_mutex_unlock(&(m->avail[nxtBuf.idx].lock));
|
pthread_mutex_unlock(&(m->avail[nxtBuf.idx].lock));
|
||||||
} else {
|
} else {
|
||||||
|
#if 0 //XXX: Triple FB
|
||||||
pthread_mutex_lock(&(m->avail[nxtBuf.idx].lock));
|
pthread_mutex_lock(&(m->avail[nxtBuf.idx].lock));
|
||||||
if (m->avail[nxtBuf.idx].state != SUB) {
|
if (m->avail[nxtBuf.idx].state != SUB) {
|
||||||
ALOGE_IF(m->swapInterval != 0, "[%d] state %c, expected %c", nxtBuf.idx,
|
ALOGE_IF(m->swapInterval != 0, "[%d] state %c, expected %c", nxtBuf.idx,
|
||||||
framebufferStateName[m->avail[nxtBuf.idx].state],
|
framebufferStateName[m->avail[nxtBuf.idx].state],
|
||||||
framebufferStateName[SUB]);
|
framebufferStateName[SUB]);
|
||||||
}
|
}
|
||||||
|
|
||||||
m->avail[nxtBuf.idx].state = REF;
|
m->avail[nxtBuf.idx].state = REF;
|
||||||
pthread_mutex_unlock(&(m->avail[nxtBuf.idx].lock));
|
pthread_mutex_unlock(&(m->avail[nxtBuf.idx].lock));
|
||||||
|
|
||||||
pthread_mutex_lock(&(m->avail[cur_buf].lock));
|
|
||||||
m->avail[cur_buf].is_avail = true;
|
|
||||||
if (m->avail[cur_buf].state != REF) {
|
if (m->avail[cur_buf].state != REF) {
|
||||||
ALOGE_IF(m->swapInterval != 0, "[%d] state %c, expected %c", cur_buf,
|
ALOGE_IF(m->swapInterval != 0, "[%d] state %c, expected %c", cur_buf,
|
||||||
framebufferStateName[m->avail[cur_buf].state],
|
framebufferStateName[m->avail[cur_buf].state],
|
||||||
framebufferStateName[REF]);
|
framebufferStateName[SUB]);
|
||||||
}
|
}
|
||||||
m->avail[cur_buf].state = AVL;
|
m->avail[cur_buf].state = AVL;
|
||||||
pthread_cond_broadcast(&(m->avail[cur_buf].cond));
|
#endif
|
||||||
|
pthread_mutex_lock(&(m->avail[cur_buf].lock));
|
||||||
|
m->avail[cur_buf].is_avail = true;
|
||||||
|
pthread_cond_signal(&(m->avail[cur_buf].cond));
|
||||||
pthread_mutex_unlock(&(m->avail[cur_buf].lock));
|
pthread_mutex_unlock(&(m->avail[cur_buf].lock));
|
||||||
}
|
}
|
||||||
cur_buf = nxtBuf.idx;
|
cur_buf = nxtBuf.idx;
|
||||||
@@ -205,12 +178,17 @@ static void *disp_loop(void *ptr)
|
|||||||
#if defined(HDMI_DUAL_DISPLAY)
|
#if defined(HDMI_DUAL_DISPLAY)
|
||||||
static int closeHDMIChannel(private_module_t* m)
|
static int closeHDMIChannel(private_module_t* m)
|
||||||
{
|
{
|
||||||
|
// XXX - when enabling HDMI
|
||||||
|
#if 0
|
||||||
Overlay* pTemp = m->pobjOverlay;
|
Overlay* pTemp = m->pobjOverlay;
|
||||||
if(pTemp != NULL)
|
if(pTemp != NULL)
|
||||||
pTemp->closeChannel();
|
pTemp->closeChannel();
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// XXX - Complete when enabling HDMI
|
||||||
|
#if 0
|
||||||
static void getSecondaryDisplayDestinationInfo(private_module_t* m, overlay_rect&
|
static void getSecondaryDisplayDestinationInfo(private_module_t* m, overlay_rect&
|
||||||
rect, int& orientation)
|
rect, int& orientation)
|
||||||
{
|
{
|
||||||
@@ -252,82 +230,175 @@ static void getSecondaryDisplayDestinationInfo(private_module_t* m, overlay_rect
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Determine overlay state based on whether hardware supports true UI
|
||||||
|
mirroring and whether video is playing or not */
|
||||||
|
static ovutils::eOverlayState getOverlayState(struct private_module_t* module)
|
||||||
|
{
|
||||||
|
overlay2::Overlay& ov = *(Overlay::getInstance());
|
||||||
|
|
||||||
|
// Default to existing state
|
||||||
|
ovutils::eOverlayState state = ov.getState();
|
||||||
|
|
||||||
|
// Sanity check
|
||||||
|
if (!module) {
|
||||||
|
ALOGE("%s: NULL module", __FUNCTION__);
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if video is playing or not
|
||||||
|
if (module->videoOverlay) {
|
||||||
|
// Video is playing, check if hardware supports true UI mirroring
|
||||||
|
if (module->trueMirrorSupport) {
|
||||||
|
// True UI mirroring is supported by hardware
|
||||||
|
if (ov.getState() == ovutils::OV_2D_VIDEO_ON_PANEL) {
|
||||||
|
// Currently playing 2D video
|
||||||
|
state = ovutils::OV_2D_TRUE_UI_MIRROR;
|
||||||
|
} else if (ov.getState() == ovutils::OV_3D_VIDEO_ON_2D_PANEL) {
|
||||||
|
// Currently playing M3D video
|
||||||
|
// FIXME: Support M3D true UI mirroring
|
||||||
|
state = ovutils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// True UI mirroring is not supported by hardware
|
||||||
|
if (ov.getState() == ovutils::OV_2D_VIDEO_ON_PANEL) {
|
||||||
|
// Currently playing 2D video
|
||||||
|
state = ovutils::OV_2D_VIDEO_ON_PANEL_TV;
|
||||||
|
} else if (ov.getState() == ovutils::OV_3D_VIDEO_ON_2D_PANEL) {
|
||||||
|
// Currently playing M3D video
|
||||||
|
state = ovutils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Video is not playing, true UI mirroring support is irrelevant
|
||||||
|
state = ovutils::OV_UI_MIRROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set overlay state */
|
||||||
|
static void setOverlayState(ovutils::eOverlayState state)
|
||||||
|
{
|
||||||
|
overlay2::Overlay& ov = *(Overlay::getInstance());
|
||||||
|
ov.setState(state);
|
||||||
|
}
|
||||||
|
|
||||||
static void *hdmi_ui_loop(void *ptr)
|
static void *hdmi_ui_loop(void *ptr)
|
||||||
{
|
{
|
||||||
private_module_t* m = reinterpret_cast<private_module_t*>(
|
private_module_t* m = reinterpret_cast<private_module_t*>(ptr);
|
||||||
ptr);
|
|
||||||
while (1) {
|
while (1) {
|
||||||
pthread_mutex_lock(&m->overlayLock);
|
pthread_mutex_lock(&m->overlayLock);
|
||||||
while(!(m->hdmiStateChanged))
|
while(!(m->hdmiStateChanged))
|
||||||
pthread_cond_wait(&(m->overlayPost), &(m->overlayLock));
|
pthread_cond_wait(&(m->overlayPost), &(m->overlayLock));
|
||||||
|
|
||||||
m->hdmiStateChanged = false;
|
m->hdmiStateChanged = false;
|
||||||
if (m->exitHDMIUILoop) {
|
if (m->exitHDMIUILoop) {
|
||||||
pthread_mutex_unlock(&m->overlayLock);
|
pthread_mutex_unlock(&m->overlayLock);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
bool waitForVsync = true;
|
|
||||||
int flags = WAIT_FOR_VSYNC;
|
// No need to mirror UI if HDMI is not on
|
||||||
if (m->pobjOverlay) {
|
if (!m->enableHDMIOutput) {
|
||||||
Overlay* pTemp = m->pobjOverlay;
|
ALOGE_IF(FB_DEBUG, "%s: hdmi not ON", __FUNCTION__);
|
||||||
if (m->hdmiMirroringState == HDMI_NO_MIRRORING)
|
pthread_mutex_unlock(&m->overlayLock);
|
||||||
closeHDMIChannel(m);
|
continue;
|
||||||
else if(m->hdmiMirroringState == HDMI_UI_MIRRORING) {
|
}
|
||||||
if (!pTemp->isChannelUP()) {
|
|
||||||
|
overlay2::OverlayMgr* ovMgr =
|
||||||
|
overlay2::OverlayMgrSingleton::getOverlayMgr();
|
||||||
|
overlay2::Overlay& ov = ovMgr->ov();
|
||||||
|
|
||||||
|
// Set overlay state
|
||||||
|
ovutils::eOverlayState state = getOverlayState(m);
|
||||||
|
setOverlayState(state);
|
||||||
|
|
||||||
|
// Determine the RGB pipe for UI depending on the state
|
||||||
|
ovutils::eDest dest = ovutils::OV_PIPE_ALL;
|
||||||
|
if (state == ovutils::OV_2D_TRUE_UI_MIRROR) {
|
||||||
|
// True UI mirroring state: external RGB pipe is OV_PIPE2
|
||||||
|
dest = ovutils::OV_PIPE2;
|
||||||
|
} else if (state == ovutils::OV_UI_MIRROR) {
|
||||||
|
// UI-only mirroring state: external RGB pipe is OV_PIPE0
|
||||||
|
dest = ovutils::OV_PIPE0;
|
||||||
|
} else {
|
||||||
|
// No UI in this case
|
||||||
|
pthread_mutex_unlock(&m->overlayLock);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m->hdmiMirroringState == HDMI_UI_MIRRORING) {
|
||||||
int alignedW = ALIGN(m->info.xres, 32);
|
int alignedW = ALIGN(m->info.xres, 32);
|
||||||
|
|
||||||
private_handle_t const* hnd =
|
private_handle_t const* hnd =
|
||||||
reinterpret_cast<private_handle_t const*>(m->framebuffer);
|
reinterpret_cast<private_handle_t const*>(m->framebuffer);
|
||||||
overlay_buffer_info info;
|
unsigned int width = alignedW;
|
||||||
info.width = alignedW;
|
unsigned int height = hnd->height;
|
||||||
info.height = hnd->height;
|
unsigned int format = hnd->format;
|
||||||
info.format = hnd->format;
|
unsigned int size = hnd->size/m->numBuffers;
|
||||||
info.size = hnd->size;
|
|
||||||
|
|
||||||
if (m->trueMirrorSupport)
|
ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
|
||||||
flags &= ~WAIT_FOR_VSYNC;
|
// External display connected during secure video playback
|
||||||
// start the overlay Channel for mirroring
|
// Open secure UI session
|
||||||
// m->enableHDMIOutput corresponds to the fbnum
|
// NOTE: when external display is already connected and then secure
|
||||||
if (pTemp->startChannel(info, m->enableHDMIOutput,
|
// playback is started, we dont have to do anything
|
||||||
false, true, 0, VG0_PIPE, flags)) {
|
if (m->secureVideoOverlay) {
|
||||||
pTemp->setFd(m->framebuffer->fd);
|
ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
|
||||||
pTemp->setCrop(0, 0, m->info.xres, m->info.yres);
|
|
||||||
} else
|
|
||||||
closeHDMIChannel(m);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pTemp->isChannelUP()) {
|
ovutils::Whf whf(width, height, format, size);
|
||||||
overlay_rect destRect;
|
ovutils::PipeArgs parg(mdpFlags,
|
||||||
int rot = 0;
|
ovutils::OVERLAY_TRANSFORM_0,
|
||||||
int currOrientation = 0;
|
whf,
|
||||||
getSecondaryDisplayDestinationInfo(m, destRect, rot);
|
ovutils::WAIT,
|
||||||
pTemp->getOrientation(currOrientation);
|
ovutils::ZORDER_0,
|
||||||
if(rot != currOrientation) {
|
ovutils::IS_FG_OFF,
|
||||||
pTemp->setTransform(rot);
|
ovutils::ROT_FLAG_ENABLED);
|
||||||
|
ovutils::PipeArgs pargs[ovutils::MAX_PIPES] = { parg, parg, parg };
|
||||||
|
bool ret = ov.setSource(pargs, dest);
|
||||||
|
if (!ret) {
|
||||||
|
ALOGE("%s setSource failed", __FUNCTION__);
|
||||||
}
|
}
|
||||||
EVEN_OUT(destRect.x);
|
|
||||||
EVEN_OUT(destRect.y);
|
// we need to communicate m->orientation that will get some
|
||||||
EVEN_OUT(destRect.w);
|
// modifications within setParameter func.
|
||||||
EVEN_OUT(destRect.h);
|
// FIXME that is ugly.
|
||||||
int currentX = 0, currentY = 0;
|
const ovutils::Params prms (ovutils::OVERLAY_TRANSFORM_UI,
|
||||||
uint32_t currentW = 0, currentH = 0;
|
m->orientation);
|
||||||
if (pTemp->getPosition(currentX, currentY, currentW, currentH)) {
|
ov.setParameter(prms, dest);
|
||||||
if ((currentX != destRect.x) || (currentY != destRect.y) ||
|
if (!ret) {
|
||||||
(currentW != destRect.w) || (currentH != destRect.h)) {
|
ALOGE("%s setParameter failed transform", __FUNCTION__);
|
||||||
pTemp->setPosition(destRect.x, destRect.y, destRect.w,
|
|
||||||
destRect.h);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// x,y,w,h
|
||||||
|
ovutils::Dim dcrop(0, 0, m->info.xres, m->info.yres);
|
||||||
|
ov.setMemoryId(m->framebuffer->fd, dest);
|
||||||
|
ret = ov.setCrop(dcrop, dest);
|
||||||
|
if (!ret) {
|
||||||
|
ALOGE("%s setCrop failed", __FUNCTION__);
|
||||||
}
|
}
|
||||||
if (m->trueMirrorSupport) {
|
|
||||||
// if video is started the UI channel should be NO_WAIT.
|
ovutils::Dim pdim (m->info.xres,
|
||||||
flags = !m->videoOverlay ? WAIT_FOR_VSYNC : 0;
|
m->info.yres,
|
||||||
pTemp->updateOverlayFlags(flags);
|
0,
|
||||||
|
0,
|
||||||
|
m->orientation);
|
||||||
|
ret = ov.setPosition(pdim, dest);
|
||||||
|
if (!ret) {
|
||||||
|
ALOGE("%s setPosition failed", __FUNCTION__);
|
||||||
}
|
}
|
||||||
pTemp->queueBuffer(m->currentOffset);
|
|
||||||
|
if (!ov.commit(dest)) {
|
||||||
|
ALOGE("%s commit fails", __FUNCTION__);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = ov.queueBuffer(m->currentOffset, dest);
|
||||||
|
if (!ret) {
|
||||||
|
ALOGE("%s queueBuffer failed", __FUNCTION__);
|
||||||
}
|
}
|
||||||
else
|
} else {
|
||||||
closeHDMIChannel(m);
|
setOverlayState(ovutils::OV_CLOSED);
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&m->overlayLock);
|
pthread_mutex_unlock(&m->overlayLock);
|
||||||
}
|
}
|
||||||
@@ -336,20 +407,30 @@ static void *hdmi_ui_loop(void *ptr)
|
|||||||
|
|
||||||
static int fb_videoOverlayStarted(struct framebuffer_device_t* dev, int started)
|
static int fb_videoOverlayStarted(struct framebuffer_device_t* dev, int started)
|
||||||
{
|
{
|
||||||
|
ALOGE_IF(FB_DEBUG, "%s started=%d", __FUNCTION__, started);
|
||||||
private_module_t* m = reinterpret_cast<private_module_t*>(
|
private_module_t* m = reinterpret_cast<private_module_t*>(
|
||||||
dev->common.module);
|
dev->common.module);
|
||||||
pthread_mutex_lock(&m->overlayLock);
|
pthread_mutex_lock(&m->overlayLock);
|
||||||
Overlay* pTemp = m->pobjOverlay;
|
|
||||||
if(started != m->videoOverlay) {
|
if(started != m->videoOverlay) {
|
||||||
m->videoOverlay = started;
|
m->videoOverlay = started;
|
||||||
if (!m->trueMirrorSupport) {
|
|
||||||
m->hdmiStateChanged = true;
|
m->hdmiStateChanged = true;
|
||||||
if (started && pTemp) {
|
if (!m->trueMirrorSupport) {
|
||||||
|
if (started) {
|
||||||
m->hdmiMirroringState = HDMI_NO_MIRRORING;
|
m->hdmiMirroringState = HDMI_NO_MIRRORING;
|
||||||
closeHDMIChannel(m);
|
ovutils::eOverlayState state = getOverlayState(m);
|
||||||
|
setOverlayState(state);
|
||||||
} else if (m->enableHDMIOutput)
|
} else if (m->enableHDMIOutput)
|
||||||
m->hdmiMirroringState = HDMI_UI_MIRRORING;
|
m->hdmiMirroringState = HDMI_UI_MIRRORING;
|
||||||
pthread_cond_signal(&(m->overlayPost));
|
} else {
|
||||||
|
if (m->videoOverlay == VIDEO_3D_OVERLAY_STARTED) {
|
||||||
|
ALOGE_IF(FB_DEBUG, "3D Video Started, stop mirroring!");
|
||||||
|
m->hdmiMirroringState = HDMI_NO_MIRRORING;
|
||||||
|
ovutils::eOverlayState state = getOverlayState(m);
|
||||||
|
setOverlayState(state);
|
||||||
|
}
|
||||||
|
else if (m->enableHDMIOutput) {
|
||||||
|
m->hdmiMirroringState = HDMI_UI_MIRRORING;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&m->overlayLock);
|
pthread_mutex_unlock(&m->overlayLock);
|
||||||
@@ -358,14 +439,13 @@ static int fb_videoOverlayStarted(struct framebuffer_device_t* dev, int started)
|
|||||||
|
|
||||||
static int fb_enableHDMIOutput(struct framebuffer_device_t* dev, int externaltype)
|
static int fb_enableHDMIOutput(struct framebuffer_device_t* dev, int externaltype)
|
||||||
{
|
{
|
||||||
|
ALOGE_IF(FB_DEBUG, "%s externaltype=%d", __FUNCTION__, externaltype);
|
||||||
private_module_t* m = reinterpret_cast<private_module_t*>(
|
private_module_t* m = reinterpret_cast<private_module_t*>(
|
||||||
dev->common.module);
|
dev->common.module);
|
||||||
pthread_mutex_lock(&m->overlayLock);
|
pthread_mutex_lock(&m->overlayLock);
|
||||||
Overlay* pTemp = m->pobjOverlay;
|
|
||||||
//Check if true mirroring can be supported
|
//Check if true mirroring can be supported
|
||||||
m->trueMirrorSupport = FrameBufferInfo::getInstance()->canSupportTrueMirroring();
|
m->trueMirrorSupport = ovutils::FrameBufferInfo::getInstance()->supportTrueMirroring();
|
||||||
m->enableHDMIOutput = externaltype;
|
m->enableHDMIOutput = externaltype;
|
||||||
ALOGE("In fb_enableHDMIOutput: externaltype = %d", m->enableHDMIOutput);
|
|
||||||
if(externaltype) {
|
if(externaltype) {
|
||||||
if (m->trueMirrorSupport) {
|
if (m->trueMirrorSupport) {
|
||||||
m->hdmiMirroringState = HDMI_UI_MIRRORING;
|
m->hdmiMirroringState = HDMI_UI_MIRRORING;
|
||||||
@@ -373,9 +453,11 @@ static int fb_enableHDMIOutput(struct framebuffer_device_t* dev, int externaltyp
|
|||||||
if(!m->videoOverlay)
|
if(!m->videoOverlay)
|
||||||
m->hdmiMirroringState = HDMI_UI_MIRRORING;
|
m->hdmiMirroringState = HDMI_UI_MIRRORING;
|
||||||
}
|
}
|
||||||
} else if (!externaltype && pTemp) {
|
} else if (!externaltype) {
|
||||||
|
// Either HDMI is disconnected or suspend occurred
|
||||||
m->hdmiMirroringState = HDMI_NO_MIRRORING;
|
m->hdmiMirroringState = HDMI_NO_MIRRORING;
|
||||||
closeHDMIChannel(m);
|
ovutils::eOverlayState state = getOverlayState(m);
|
||||||
|
setOverlayState(state);
|
||||||
}
|
}
|
||||||
m->hdmiStateChanged = true;
|
m->hdmiStateChanged = true;
|
||||||
pthread_cond_signal(&(m->overlayPost));
|
pthread_cond_signal(&(m->overlayPost));
|
||||||
@@ -383,27 +465,6 @@ static int fb_enableHDMIOutput(struct framebuffer_device_t* dev, int externaltyp
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int fb_setActionSafeWidthRatio(struct framebuffer_device_t* dev, float asWidthRatio)
|
|
||||||
{
|
|
||||||
private_module_t* m = reinterpret_cast<private_module_t*>(
|
|
||||||
dev->common.module);
|
|
||||||
pthread_mutex_lock(&m->overlayLock);
|
|
||||||
m->actionsafeWidthRatio = asWidthRatio;
|
|
||||||
pthread_mutex_unlock(&m->overlayLock);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int fb_setActionSafeHeightRatio(struct framebuffer_device_t* dev, float asHeightRatio)
|
|
||||||
{
|
|
||||||
private_module_t* m = reinterpret_cast<private_module_t*>(
|
|
||||||
dev->common.module);
|
|
||||||
pthread_mutex_lock(&m->overlayLock);
|
|
||||||
m->actionsafeHeightRatio = asHeightRatio;
|
|
||||||
pthread_mutex_unlock(&m->overlayLock);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int fb_orientationChanged(struct framebuffer_device_t* dev, int orientation)
|
static int fb_orientationChanged(struct framebuffer_device_t* dev, int orientation)
|
||||||
{
|
{
|
||||||
private_module_t* m = reinterpret_cast<private_module_t*>(
|
private_module_t* m = reinterpret_cast<private_module_t*>(
|
||||||
@@ -413,14 +474,110 @@ static int fb_orientationChanged(struct framebuffer_device_t* dev, int orientati
|
|||||||
pthread_mutex_unlock(&m->overlayLock);
|
pthread_mutex_unlock(&m->overlayLock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int handle_open_secure_start(private_module_t* m) {
|
||||||
|
pthread_mutex_lock(&m->overlayLock);
|
||||||
|
m->hdmiMirroringState = HDMI_NO_MIRRORING;
|
||||||
|
m->secureVideoOverlay = true;
|
||||||
|
pthread_mutex_unlock(&m->overlayLock);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int handle_open_secure_end(private_module_t* m) {
|
||||||
|
pthread_mutex_lock(&m->overlayLock);
|
||||||
|
if (m->enableHDMIOutput) {
|
||||||
|
if (m->trueMirrorSupport) {
|
||||||
|
m->hdmiMirroringState = HDMI_UI_MIRRORING;
|
||||||
|
} else if(!m->videoOverlay) {
|
||||||
|
m->hdmiMirroringState = HDMI_UI_MIRRORING;
|
||||||
|
}
|
||||||
|
m->hdmiStateChanged = true;
|
||||||
|
pthread_cond_signal(&(m->overlayPost));
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&m->overlayLock);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int handle_close_secure_start(private_module_t* m) {
|
||||||
|
pthread_mutex_lock(&m->overlayLock);
|
||||||
|
m->hdmiMirroringState = HDMI_NO_MIRRORING;
|
||||||
|
m->secureVideoOverlay = false;
|
||||||
|
pthread_mutex_unlock(&m->overlayLock);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int handle_close_secure_end(private_module_t* m) {
|
||||||
|
pthread_mutex_lock(&m->overlayLock);
|
||||||
|
if (m->enableHDMIOutput) {
|
||||||
|
if (m->trueMirrorSupport) {
|
||||||
|
m->hdmiMirroringState = HDMI_UI_MIRRORING;
|
||||||
|
} else if(!m->videoOverlay) {
|
||||||
|
m->hdmiMirroringState = HDMI_UI_MIRRORING;
|
||||||
|
}
|
||||||
|
m->hdmiStateChanged = true;
|
||||||
|
pthread_cond_signal(&(m->overlayPost));
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&m->overlayLock);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* fb_perform - used to add custom event and handle them in fb HAL
|
||||||
|
* Used for external display related functions as of now
|
||||||
|
*/
|
||||||
|
static int fb_perform(struct framebuffer_device_t* dev, int event, int value)
|
||||||
|
{
|
||||||
|
private_module_t* m = reinterpret_cast<private_module_t*>(
|
||||||
|
dev->common.module);
|
||||||
|
switch(event) {
|
||||||
|
#if defined(HDMI_DUAL_DISPLAY)
|
||||||
|
case EVENT_EXTERNAL_DISPLAY:
|
||||||
|
fb_enableHDMIOutput(dev, value);
|
||||||
|
break;
|
||||||
|
case EVENT_VIDEO_OVERLAY:
|
||||||
|
fb_videoOverlayStarted(dev, value);
|
||||||
|
break;
|
||||||
|
case EVENT_ORIENTATION_CHANGE:
|
||||||
|
fb_orientationChanged(dev, value);
|
||||||
|
break;
|
||||||
|
case EVENT_OVERLAY_STATE_CHANGE:
|
||||||
|
if (value == OVERLAY_STATE_CHANGE_START) {
|
||||||
|
// When state change starts, get a lock on overlay
|
||||||
|
pthread_mutex_lock(&m->overlayLock);
|
||||||
|
} else if (value == OVERLAY_STATE_CHANGE_END) {
|
||||||
|
// When state change is complete, unlock overlay
|
||||||
|
pthread_mutex_unlock(&m->overlayLock);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EVENT_OPEN_SECURE_START:
|
||||||
|
handle_open_secure_start(m);
|
||||||
|
break;
|
||||||
|
case EVENT_OPEN_SECURE_END:
|
||||||
|
handle_open_secure_end(m);
|
||||||
|
break;
|
||||||
|
case EVENT_CLOSE_SECURE_START:
|
||||||
|
handle_close_secure_start(m);
|
||||||
|
break;
|
||||||
|
case EVENT_CLOSE_SECURE_END:
|
||||||
|
handle_close_secure_end(m);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
ALOGE("In %s: UNKNOWN Event = %d!!!", __FUNCTION__, event);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer)
|
static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer)
|
||||||
{
|
{
|
||||||
if (private_handle_t::validate(buffer) < 0)
|
if (private_handle_t::validate(buffer) < 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
int nxtIdx, futureIdx = -1;
|
int nxtIdx;//, futureIdx = -1;
|
||||||
bool reuse;
|
bool reuse;
|
||||||
struct qbuf_t qb;
|
struct qbuf_t qb;
|
||||||
fb_context_t* ctx = (fb_context_t*)dev;
|
fb_context_t* ctx = (fb_context_t*)dev;
|
||||||
@@ -433,8 +590,7 @@ static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer)
|
|||||||
|
|
||||||
reuse = false;
|
reuse = false;
|
||||||
nxtIdx = (m->currentIdx + 1) % m->numBuffers;
|
nxtIdx = (m->currentIdx + 1) % m->numBuffers;
|
||||||
futureIdx = (nxtIdx + 1) % m->numBuffers;
|
//futureIdx = (nxtIdx + 1) % m->numBuffers;
|
||||||
|
|
||||||
if (m->swapInterval == 0) {
|
if (m->swapInterval == 0) {
|
||||||
// if SwapInterval = 0 and no buffers available then reuse
|
// if SwapInterval = 0 and no buffers available then reuse
|
||||||
// current buf for next rendering so don't post new buffer
|
// current buf for next rendering so don't post new buffer
|
||||||
@@ -450,17 +606,17 @@ static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer)
|
|||||||
if(!reuse){
|
if(!reuse){
|
||||||
// unlock previous ("current") Buffer and lock the new buffer
|
// unlock previous ("current") Buffer and lock the new buffer
|
||||||
m->base.lock(&m->base, buffer,
|
m->base.lock(&m->base, buffer,
|
||||||
private_module_t::PRIV_USAGE_LOCKED_FOR_POST,
|
PRIV_USAGE_LOCKED_FOR_POST,
|
||||||
0,0, m->info.xres, m->info.yres, NULL);
|
0,0, m->info.xres, m->info.yres, NULL);
|
||||||
|
|
||||||
// post/queue the new buffer
|
// post/queue the new buffer
|
||||||
pthread_mutex_lock(&(m->avail[nxtIdx].lock));
|
pthread_mutex_lock(&(m->avail[nxtIdx].lock));
|
||||||
|
m->avail[nxtIdx].is_avail = false;
|
||||||
|
#if 0 //XXX: Triple FB
|
||||||
if (m->avail[nxtIdx].is_avail != true) {
|
if (m->avail[nxtIdx].is_avail != true) {
|
||||||
ALOGE_IF(m->swapInterval != 0, "Found %d buf to be not avail", nxtIdx);
|
ALOGE_IF(m->swapInterval != 0, "Found %d buf to be not avail", nxtIdx);
|
||||||
}
|
}
|
||||||
|
|
||||||
m->avail[nxtIdx].is_avail = false;
|
|
||||||
|
|
||||||
if (m->avail[nxtIdx].state != AVL) {
|
if (m->avail[nxtIdx].state != AVL) {
|
||||||
ALOGD("[%d] state %c, expected %c", nxtIdx,
|
ALOGD("[%d] state %c, expected %c", nxtIdx,
|
||||||
framebufferStateName[m->avail[nxtIdx].state],
|
framebufferStateName[m->avail[nxtIdx].state],
|
||||||
@@ -468,6 +624,7 @@ static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
m->avail[nxtIdx].state = SUB;
|
m->avail[nxtIdx].state = SUB;
|
||||||
|
#endif
|
||||||
pthread_mutex_unlock(&(m->avail[nxtIdx].lock));
|
pthread_mutex_unlock(&(m->avail[nxtIdx].lock));
|
||||||
|
|
||||||
qb.idx = nxtIdx;
|
qb.idx = nxtIdx;
|
||||||
@@ -486,40 +643,12 @@ static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer)
|
|||||||
if (m->currentBuffer)
|
if (m->currentBuffer)
|
||||||
m->base.unlock(&m->base, m->currentBuffer);
|
m->base.unlock(&m->base, m->currentBuffer);
|
||||||
m->base.lock(&m->base, buffer,
|
m->base.lock(&m->base, buffer,
|
||||||
private_module_t::PRIV_USAGE_LOCKED_FOR_POST,
|
PRIV_USAGE_LOCKED_FOR_POST,
|
||||||
0,0, m->info.xres, m->info.yres, NULL);
|
0,0, m->info.xres, m->info.yres, NULL);
|
||||||
m->currentBuffer = buffer;
|
m->currentBuffer = buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
|
||||||
void* fb_vaddr;
|
|
||||||
void* buffer_vaddr;
|
|
||||||
m->base.lock(&m->base, m->framebuffer,
|
|
||||||
GRALLOC_USAGE_SW_WRITE_RARELY,
|
|
||||||
0, 0, m->info.xres, m->info.yres,
|
|
||||||
&fb_vaddr);
|
|
||||||
|
|
||||||
m->base.lock(&m->base, buffer,
|
|
||||||
GRALLOC_USAGE_SW_READ_RARELY,
|
|
||||||
0, 0, m->info.xres, m->info.yres,
|
|
||||||
&buffer_vaddr);
|
|
||||||
|
|
||||||
//memcpy(fb_vaddr, buffer_vaddr, m->finfo.line_length * m->info.yres);
|
|
||||||
|
|
||||||
msm_copy_buffer(
|
|
||||||
m->framebuffer, m->framebuffer->fd,
|
|
||||||
m->info.xres, m->info.yres, m->fbFormat,
|
|
||||||
m->info.xoffset, m->info.yoffset,
|
|
||||||
m->info.width, m->info.height);
|
|
||||||
|
|
||||||
m->base.unlock(&m->base, buffer);
|
|
||||||
m->base.unlock(&m->base, m->framebuffer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ALOGD_IF(FB_DEBUG, "Framebuffer state: [0] = %c [1] = %c [2] = %c",
|
|
||||||
framebufferStateName[m->avail[0].state],
|
|
||||||
framebufferStateName[m->avail[1].state],
|
|
||||||
framebufferStateName[m->avail[2].state]);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -550,8 +679,6 @@ static int fb_lockBuffer(struct framebuffer_device_t* dev, int index)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
|
|
||||||
int mapFrameBufferLocked(struct private_module_t* module)
|
int mapFrameBufferLocked(struct private_module_t* module)
|
||||||
{
|
{
|
||||||
// already initialized...
|
// already initialized...
|
||||||
@@ -617,7 +744,8 @@ int mapFrameBufferLocked(struct private_module_t* module)
|
|||||||
* RGBA instead of RGBX. */
|
* RGBA instead of RGBX. */
|
||||||
if (property_get("debug.sf.hw", property, NULL) > 0 && atoi(property) == 0)
|
if (property_get("debug.sf.hw", property, NULL) > 0 && atoi(property) == 0)
|
||||||
module->fbFormat = HAL_PIXEL_FORMAT_RGBX_8888;
|
module->fbFormat = HAL_PIXEL_FORMAT_RGBX_8888;
|
||||||
else if(property_get("debug.composition.type", property, NULL) > 0 && (strncmp(property, "mdp", 3) == 0))
|
else if(property_get("debug.composition.type", property, NULL) > 0 &&
|
||||||
|
(strncmp(property, "mdp", 3) == 0))
|
||||||
module->fbFormat = HAL_PIXEL_FORMAT_RGBX_8888;
|
module->fbFormat = HAL_PIXEL_FORMAT_RGBX_8888;
|
||||||
else
|
else
|
||||||
module->fbFormat = HAL_PIXEL_FORMAT_RGBA_8888;
|
module->fbFormat = HAL_PIXEL_FORMAT_RGBA_8888;
|
||||||
@@ -641,7 +769,7 @@ int mapFrameBufferLocked(struct private_module_t* module)
|
|||||||
int size = roundUpToPageSize(info.yres * info.xres * (info.bits_per_pixel/8));
|
int size = roundUpToPageSize(info.yres * info.xres * (info.bits_per_pixel/8));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Request NUM_BUFFERS screens (at lest 2 for page flipping)
|
* Request NUM_BUFFERS screens (at least 2 for page flipping)
|
||||||
*/
|
*/
|
||||||
int numberOfBuffers = (int)(finfo.smem_len/size);
|
int numberOfBuffers = (int)(finfo.smem_len/size);
|
||||||
ALOGV("num supported framebuffers in kernel = %d", numberOfBuffers);
|
ALOGV("num supported framebuffers in kernel = %d", numberOfBuffers);
|
||||||
@@ -739,12 +867,12 @@ int mapFrameBufferLocked(struct private_module_t* module)
|
|||||||
char pval[PROPERTY_VALUE_MAX];
|
char pval[PROPERTY_VALUE_MAX];
|
||||||
property_get("debug.gr.swapinterval", pval, "1");
|
property_get("debug.gr.swapinterval", pval, "1");
|
||||||
module->swapInterval = atoi(pval);
|
module->swapInterval = atoi(pval);
|
||||||
if (module->swapInterval < private_module_t::PRIV_MIN_SWAP_INTERVAL ||
|
if (module->swapInterval < PRIV_MIN_SWAP_INTERVAL ||
|
||||||
module->swapInterval > private_module_t::PRIV_MAX_SWAP_INTERVAL) {
|
module->swapInterval > PRIV_MAX_SWAP_INTERVAL) {
|
||||||
module->swapInterval = 1;
|
module->swapInterval = 1;
|
||||||
ALOGW("Out of range (%d to %d) value for debug.gr.swapinterval, using 1",
|
ALOGW("Out of range (%d to %d) value for debug.gr.swapinterval, using 1",
|
||||||
private_module_t::PRIV_MIN_SWAP_INTERVAL,
|
PRIV_MIN_SWAP_INTERVAL,
|
||||||
private_module_t::PRIV_MAX_SWAP_INTERVAL);
|
PRIV_MAX_SWAP_INTERVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
@@ -765,8 +893,8 @@ int mapFrameBufferLocked(struct private_module_t* module)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* create display update thread */
|
/* create display update thread */
|
||||||
pthread_t thread1;
|
pthread_t disp_thread;
|
||||||
if (pthread_create(&thread1, NULL, &disp_loop, (void *) module)) {
|
if (pthread_create(&disp_thread, NULL, &disp_loop, (void *) module)) {
|
||||||
return -errno;
|
return -errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -778,9 +906,11 @@ int mapFrameBufferLocked(struct private_module_t* module)
|
|||||||
module->numBuffers = info.yres_virtual / info.yres;
|
module->numBuffers = info.yres_virtual / info.yres;
|
||||||
module->bufferMask = 0;
|
module->bufferMask = 0;
|
||||||
//adreno needs page aligned offsets. Align the fbsize to pagesize.
|
//adreno needs page aligned offsets. Align the fbsize to pagesize.
|
||||||
size_t fbSize = roundUpToPageSize(finfo.line_length * info.yres) * module->numBuffers;
|
size_t fbSize = roundUpToPageSize(finfo.line_length * info.yres)*
|
||||||
|
module->numBuffers;
|
||||||
module->framebuffer = new private_handle_t(fd, fbSize,
|
module->framebuffer = new private_handle_t(fd, fbSize,
|
||||||
private_handle_t::PRIV_FLAGS_USES_PMEM, BUFFER_TYPE_UI,
|
private_handle_t::PRIV_FLAGS_USES_PMEM,
|
||||||
|
BUFFER_TYPE_UI,
|
||||||
module->fbFormat, info.xres, info.yres);
|
module->fbFormat, info.xres, info.yres);
|
||||||
void* vaddr = mmap(0, fbSize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
|
void* vaddr = mmap(0, fbSize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
|
||||||
if (vaddr == MAP_FAILED) {
|
if (vaddr == MAP_FAILED) {
|
||||||
@@ -794,7 +924,6 @@ int mapFrameBufferLocked(struct private_module_t* module)
|
|||||||
/* Overlay for HDMI*/
|
/* Overlay for HDMI*/
|
||||||
pthread_mutex_init(&(module->overlayLock), NULL);
|
pthread_mutex_init(&(module->overlayLock), NULL);
|
||||||
pthread_cond_init(&(module->overlayPost), NULL);
|
pthread_cond_init(&(module->overlayPost), NULL);
|
||||||
module->pobjOverlay = new Overlay();
|
|
||||||
module->currentOffset = 0;
|
module->currentOffset = 0;
|
||||||
module->exitHDMIUILoop = false;
|
module->exitHDMIUILoop = false;
|
||||||
module->hdmiStateChanged = false;
|
module->hdmiStateChanged = false;
|
||||||
@@ -857,14 +986,6 @@ int fb_device_open(hw_module_t const* module, const char* name,
|
|||||||
dev->device.post = fb_post;
|
dev->device.post = fb_post;
|
||||||
dev->device.setUpdateRect = 0;
|
dev->device.setUpdateRect = 0;
|
||||||
dev->device.compositionComplete = fb_compositionComplete;
|
dev->device.compositionComplete = fb_compositionComplete;
|
||||||
//dev->device.lockBuffer = fb_lockBuffer;
|
|
||||||
#if defined(HDMI_DUAL_DISPLAY)
|
|
||||||
dev->device.orientationChanged = fb_orientationChanged;
|
|
||||||
dev->device.videoOverlayStarted = fb_videoOverlayStarted;
|
|
||||||
dev->device.enableHDMIOutput = fb_enableHDMIOutput;
|
|
||||||
dev->device.setActionSafeWidthRatio = fb_setActionSafeWidthRatio;
|
|
||||||
dev->device.setActionSafeHeightRatio = fb_setActionSafeHeightRatio;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
private_module_t* m = (private_module_t*)module;
|
private_module_t* m = (private_module_t*)module;
|
||||||
status = mapFrameBuffer(m);
|
status = mapFrameBuffer(m);
|
||||||
@@ -878,9 +999,8 @@ int fb_device_open(hw_module_t const* module, const char* name,
|
|||||||
const_cast<float&>(dev->device.xdpi) = m->xdpi;
|
const_cast<float&>(dev->device.xdpi) = m->xdpi;
|
||||||
const_cast<float&>(dev->device.ydpi) = m->ydpi;
|
const_cast<float&>(dev->device.ydpi) = m->ydpi;
|
||||||
const_cast<float&>(dev->device.fps) = m->fps;
|
const_cast<float&>(dev->device.fps) = m->fps;
|
||||||
const_cast<int&>(dev->device.minSwapInterval) = private_module_t::PRIV_MIN_SWAP_INTERVAL;
|
const_cast<int&>(dev->device.minSwapInterval) = PRIV_MIN_SWAP_INTERVAL;
|
||||||
const_cast<int&>(dev->device.maxSwapInterval) = private_module_t::PRIV_MAX_SWAP_INTERVAL;
|
const_cast<int&>(dev->device.maxSwapInterval) = PRIV_MAX_SWAP_INTERVAL;
|
||||||
//const_cast<int&>(dev->device.numFramebuffers) = m->numBuffers;
|
|
||||||
if (m->finfo.reserved[0] == 0x5444 &&
|
if (m->finfo.reserved[0] == 0x5444 &&
|
||||||
m->finfo.reserved[1] == 0x5055) {
|
m->finfo.reserved[1] == 0x5055) {
|
||||||
dev->device.setUpdateRect = fb_setUpdateRect;
|
dev->device.setUpdateRect = fb_setUpdateRect;
|
||||||
@@ -895,43 +1015,3 @@ int fb_device_open(hw_module_t const* module, const char* name,
|
|||||||
}
|
}
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy a pmem buffer to the framebuffer */
|
|
||||||
|
|
||||||
static void
|
|
||||||
msm_copy_buffer(buffer_handle_t handle, int fd,
|
|
||||||
int width, int height, int format,
|
|
||||||
int x, int y, int w, int h)
|
|
||||||
{
|
|
||||||
struct {
|
|
||||||
unsigned int count;
|
|
||||||
mdp_blit_req req;
|
|
||||||
} blit;
|
|
||||||
private_handle_t *priv = (private_handle_t*) handle;
|
|
||||||
|
|
||||||
memset(&blit, 0, sizeof(blit));
|
|
||||||
blit.count = 1;
|
|
||||||
|
|
||||||
blit.req.flags = 0;
|
|
||||||
blit.req.alpha = 0xff;
|
|
||||||
blit.req.transp_mask = 0xffffffff;
|
|
||||||
|
|
||||||
blit.req.src.width = width;
|
|
||||||
blit.req.src.height = height;
|
|
||||||
blit.req.src.offset = 0;
|
|
||||||
blit.req.src.memory_id = priv->fd;
|
|
||||||
|
|
||||||
blit.req.dst.width = width;
|
|
||||||
blit.req.dst.height = height;
|
|
||||||
blit.req.dst.offset = 0;
|
|
||||||
blit.req.dst.memory_id = fd;
|
|
||||||
blit.req.dst.format = format;
|
|
||||||
|
|
||||||
blit.req.src_rect.x = blit.req.dst_rect.x = x;
|
|
||||||
blit.req.src_rect.y = blit.req.dst_rect.y = y;
|
|
||||||
blit.req.src_rect.w = blit.req.dst_rect.w = w;
|
|
||||||
blit.req.src_rect.h = blit.req.dst_rect.h = h;
|
|
||||||
|
|
||||||
if (ioctl(fd, MSMFB_BLIT, &blit))
|
|
||||||
ALOGE("MSMFB_BLIT failed = %d", -errno);
|
|
||||||
}
|
|
||||||
|
|||||||
44
libgralloc/gpu.cpp
Executable file → Normal file
44
libgralloc/gpu.cpp
Executable file → Normal file
@@ -38,28 +38,6 @@ gpu_context_t::gpu_context_t(const private_module_t* module,
|
|||||||
// Zero out the alloc_device_t
|
// Zero out the alloc_device_t
|
||||||
memset(static_cast<alloc_device_t*>(this), 0, sizeof(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
|
// Initialize the procs
|
||||||
common.tag = HARDWARE_DEVICE_TAG;
|
common.tag = HARDWARE_DEVICE_TAG;
|
||||||
common.version = 0;
|
common.version = 0;
|
||||||
@@ -162,7 +140,7 @@ int gpu_context_t::gralloc_alloc_buffer(size_t size, int usage,
|
|||||||
else
|
else
|
||||||
data.align = getpagesize();
|
data.align = getpagesize();
|
||||||
data.pHandle = (unsigned int) pHandle;
|
data.pHandle = (unsigned int) pHandle;
|
||||||
err = mAllocCtrl->allocate(data, usage, compositionType);
|
err = mAllocCtrl->allocate(data, usage, 0);
|
||||||
|
|
||||||
if (usage & GRALLOC_USAGE_PRIVATE_UNSYNCHRONIZED) {
|
if (usage & GRALLOC_USAGE_PRIVATE_UNSYNCHRONIZED) {
|
||||||
flags |= private_handle_t::PRIV_FLAGS_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) {
|
if (err == 0) {
|
||||||
flags |= data.allocType;
|
flags |= data.allocType;
|
||||||
private_handle_t* hnd = new private_handle_t(data.fd, size, flags,
|
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->offset = data.offset;
|
||||||
hnd->base = int(data.base) + 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,
|
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)
|
if (!pHandle || !pStride)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
@@ -234,7 +214,8 @@ int gpu_context_t::alloc_impl(int w, int h, int format, int usage,
|
|||||||
// All buffers marked as protected or for external
|
// All buffers marked as protected or for external
|
||||||
// display need to go to overlay
|
// display need to go to overlay
|
||||||
if ((usage & GRALLOC_USAGE_EXTERNAL_DISP) ||
|
if ((usage & GRALLOC_USAGE_EXTERNAL_DISP) ||
|
||||||
(usage & GRALLOC_USAGE_PROTECTED)) {
|
(usage & GRALLOC_USAGE_PROTECTED) ||
|
||||||
|
(usage & GRALLOC_USAGE_PRIVATE_CP_BUFFER)) {
|
||||||
bufferType = BUFFER_TYPE_VIDEO;
|
bufferType = BUFFER_TYPE_VIDEO;
|
||||||
}
|
}
|
||||||
int err;
|
int err;
|
||||||
@@ -268,12 +249,12 @@ int gpu_context_t::free_impl(private_handle_t const* hnd) {
|
|||||||
int index = (hnd->base - m->framebuffer->base) / bufferSize;
|
int index = (hnd->base - m->framebuffer->base) / bufferSize;
|
||||||
m->bufferMask &= ~(1<<index);
|
m->bufferMask &= ~(1<<index);
|
||||||
} else {
|
} else {
|
||||||
|
terminateBuffer(&m->base, const_cast<private_handle_t*>(hnd));
|
||||||
sp<IMemAlloc> memalloc = mAllocCtrl->getAllocator(hnd->flags);
|
sp<IMemAlloc> memalloc = mAllocCtrl->getAllocator(hnd->flags);
|
||||||
int err = memalloc->free_buffer((void*)hnd->base, (size_t) hnd->size,
|
int err = memalloc->free_buffer((void*)hnd->base, (size_t) hnd->size,
|
||||||
hnd->offset, hnd->fd);
|
hnd->offset, hnd->fd);
|
||||||
if(err)
|
if(err)
|
||||||
return err;
|
return err;
|
||||||
terminateBuffer(&m->base, const_cast<private_handle_t*>(hnd));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Release the genlock
|
// 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 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) {
|
if (!dev) {
|
||||||
return -EINVAL;
|
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);
|
gpu_context_t* gpu = reinterpret_cast<gpu_context_t*>(dev);
|
||||||
return gpu->alloc_impl(w, h, format, usage, pHandle, pStride, 0);
|
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 gpu_context_t::gralloc_alloc_size(alloc_device_t* dev, int w, int h,
|
||||||
int usage, buffer_handle_t* pHandle, int* pStride, int bufferSize)
|
int format, int usage,
|
||||||
|
buffer_handle_t* pHandle, int* pStride,
|
||||||
|
int bufferSize)
|
||||||
{
|
{
|
||||||
if (!dev) {
|
if (!dev) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2008 The Android Open Source Project
|
* 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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -28,6 +28,7 @@
|
|||||||
#include <utils/RefBase.h>
|
#include <utils/RefBase.h>
|
||||||
|
|
||||||
#include "gralloc_priv.h"
|
#include "gralloc_priv.h"
|
||||||
|
#include <fb_priv.h>
|
||||||
|
|
||||||
namespace gralloc {
|
namespace gralloc {
|
||||||
class IAllocController;
|
class IAllocController;
|
||||||
@@ -67,12 +68,8 @@ namespace gralloc {
|
|||||||
|
|
||||||
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:
|
private:
|
||||||
android::sp<IAllocController> mAllocCtrl;
|
android::sp<IAllocController> mAllocCtrl;
|
||||||
int compositionType;
|
|
||||||
void getGrallocInformationFromFormat(int inputFormat,
|
void getGrallocInformationFromFormat(int inputFormat,
|
||||||
int *colorFormat,
|
int *colorFormat,
|
||||||
int *bufferType);
|
int *bufferType);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2008 The Android Open Source Project
|
* 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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2008, The Android Open Source Project
|
* 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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|||||||
@@ -28,13 +28,6 @@
|
|||||||
|
|
||||||
#include <cutils/native_handle.h>
|
#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>
|
#include <cutils/log.h>
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@@ -87,6 +80,14 @@ enum {
|
|||||||
* other EXTERNAL_ONLY buffers are available. Used during suspend.
|
* other EXTERNAL_ONLY buffers are available. Used during suspend.
|
||||||
*/
|
*/
|
||||||
GRALLOC_USAGE_EXTERNAL_BLOCK = 0x00020000,
|
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 {
|
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 INTERLACE_MASK 0x80
|
||||||
#define S3D_FORMAT_MASK 0xFF000
|
#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 "/dev/pmem"
|
||||||
#define DEVICE_PMEM_ADSP "/dev/pmem_adsp"
|
#define DEVICE_PMEM_ADSP "/dev/pmem_adsp"
|
||||||
#define DEVICE_PMEM_SMIPOOL "/dev/pmem_smipool"
|
#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 {
|
enum {
|
||||||
/* OEM specific HAL formats */
|
/* OEM specific HAL formats */
|
||||||
HAL_PIXEL_FORMAT_NV12_ENCODEABLE = 0x102,
|
HAL_PIXEL_FORMAT_NV12_ENCODEABLE = 0x102,
|
||||||
@@ -206,6 +112,8 @@ enum {
|
|||||||
HAL_PIXEL_FORMAT_YCrCb_422_SP = 0x10B,
|
HAL_PIXEL_FORMAT_YCrCb_422_SP = 0x10B,
|
||||||
HAL_PIXEL_FORMAT_R_8 = 0x10D,
|
HAL_PIXEL_FORMAT_R_8 = 0x10D,
|
||||||
HAL_PIXEL_FORMAT_RG_88 = 0x10E,
|
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,
|
HAL_PIXEL_FORMAT_INTERLACE = 0x180,
|
||||||
|
|
||||||
};
|
};
|
||||||
@@ -228,87 +136,6 @@ enum {
|
|||||||
BUFFER_TYPE_VIDEO
|
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
|
|
||||||
};
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
@@ -327,41 +154,51 @@ struct private_handle_t {
|
|||||||
PRIV_FLAGS_DO_NOT_FLUSH = 0x00000040,
|
PRIV_FLAGS_DO_NOT_FLUSH = 0x00000040,
|
||||||
PRIV_FLAGS_SW_LOCK = 0x00000080,
|
PRIV_FLAGS_SW_LOCK = 0x00000080,
|
||||||
PRIV_FLAGS_NONCONTIGUOUS_MEM = 0x00000100,
|
PRIV_FLAGS_NONCONTIGUOUS_MEM = 0x00000100,
|
||||||
PRIV_FLAGS_HWC_LOCK = 0x00000200, // Set by HWC when storing the handle
|
// Set by HWC when storing the handle
|
||||||
|
PRIV_FLAGS_HWC_LOCK = 0x00000200,
|
||||||
PRIV_FLAGS_SECURE_BUFFER = 0x00000400,
|
PRIV_FLAGS_SECURE_BUFFER = 0x00000400,
|
||||||
PRIV_FLAGS_UNSYNCHRONIZED = 0x00000800, // For explicit synchronization
|
// For explicit synchronization
|
||||||
PRIV_FLAGS_NOT_MAPPED = 0x00001000, // Not mapped in userspace
|
PRIV_FLAGS_UNSYNCHRONIZED = 0x00000800,
|
||||||
PRIV_FLAGS_EXTERNAL_ONLY = 0x00002000, // Display on external only
|
// Not mapped in userspace
|
||||||
PRIV_FLAGS_EXTERNAL_BLOCK = 0x00004000, // Display only this buffer on external
|
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
|
// file-descriptors
|
||||||
int fd;
|
int fd;
|
||||||
int genlockHandle; // genlock handle to be dup'd by the binder
|
// genlock handle to be dup'd by the binder
|
||||||
|
int genlockHandle;
|
||||||
// ints
|
// ints
|
||||||
int magic;
|
int magic;
|
||||||
int flags;
|
int flags;
|
||||||
int size;
|
int size;
|
||||||
int offset;
|
int offset;
|
||||||
int bufferType;
|
int bufferType;
|
||||||
|
|
||||||
// FIXME: the attributes below should be out-of-line
|
|
||||||
int base;
|
int base;
|
||||||
int gpuaddr; // The gpu address mapped into the mmu. If using ashmem, set to 0 They don't care
|
// The gpu address mapped into the mmu.
|
||||||
|
// If using ashmem, set to 0, they don't care
|
||||||
|
int gpuaddr;
|
||||||
int pid;
|
int pid;
|
||||||
int format;
|
int format;
|
||||||
int width;
|
int width;
|
||||||
int height;
|
int height;
|
||||||
int genlockPrivFd; // local fd of the genlock device.
|
// local fd of the genlock device.
|
||||||
|
int genlockPrivFd;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
static const int sNumInts = 12;
|
static const int sNumInts = 12;
|
||||||
static const int sNumFds = 2;
|
static const int sNumFds = 2;
|
||||||
static const int sMagic = 'gmsm';
|
static const int sMagic = 'gmsm';
|
||||||
|
|
||||||
private_handle_t(int fd, int size, int flags, int bufferType, int format, int width, int height) :
|
private_handle_t(int fd, int size, int flags, int bufferType,
|
||||||
fd(fd), genlockHandle(-1), magic(sMagic), flags(flags), size(size), offset(0),
|
int format,int width, int height) :
|
||||||
bufferType(bufferType), base(0), gpuaddr(0), pid(getpid()), format(format),
|
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)
|
width(width), height(height), genlockPrivFd(-1)
|
||||||
{
|
{
|
||||||
version = sizeof(native_handle);
|
version = sizeof(native_handle);
|
||||||
@@ -382,7 +219,24 @@ struct private_handle_t {
|
|||||||
h->numInts != sNumInts || h->numFds != sNumFds ||
|
h->numInts != sNumInts || h->numFds != sNumFds ||
|
||||||
hnd->magic != sMagic)
|
hnd->magic != sMagic)
|
||||||
{
|
{
|
||||||
ALOGE("invalid gralloc handle (at %p)", h);
|
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 -EINVAL;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -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
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are
|
* modification, are permitted provided that the following conditions are
|
||||||
@@ -64,6 +64,7 @@ void IonAlloc::close_device()
|
|||||||
|
|
||||||
int IonAlloc::alloc_buffer(alloc_data& data)
|
int IonAlloc::alloc_buffer(alloc_data& data)
|
||||||
{
|
{
|
||||||
|
Locker::Autolock _l(mLock);
|
||||||
int err = 0;
|
int err = 0;
|
||||||
int ionSyncFd = FD_INIT;
|
int ionSyncFd = FD_INIT;
|
||||||
int iFd = FD_INIT;
|
int iFd = FD_INIT;
|
||||||
@@ -84,9 +85,8 @@ int IonAlloc::alloc_buffer(alloc_data& data)
|
|||||||
if(data.uncached) {
|
if(data.uncached) {
|
||||||
// Use the sync FD to alloc and map
|
// Use the sync FD to alloc and map
|
||||||
// when we need uncached memory
|
// when we need uncached memory
|
||||||
// FIX: О–DSYNC defined to open uncached - add that in kernel
|
// XXX: Change O_SYNC to O_DSYNC when available in bionic
|
||||||
//ionSyncFd = open(ION_DEVICE, O_RDONLY|O_DSYNC);
|
ionSyncFd = open(ION_DEVICE, O_RDONLY|O_SYNC);
|
||||||
ionSyncFd = open(ION_DEVICE, O_RDONLY);
|
|
||||||
if(ionSyncFd < 0) {
|
if(ionSyncFd < 0) {
|
||||||
ALOGE("%s: Failed to open ion device - %s",
|
ALOGE("%s: Failed to open ion device - %s",
|
||||||
__FUNCTION__, strerror(errno));
|
__FUNCTION__, strerror(errno));
|
||||||
@@ -119,8 +119,8 @@ int IonAlloc::alloc_buffer(alloc_data& data)
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
//if(!(data.flags & ION_SECURE) &&
|
if(!(data.flags & ION_SECURE) &&
|
||||||
if(!(data.allocType & private_handle_t::PRIV_FLAGS_NOT_MAPPED)) {
|
!(data.allocType & private_handle_t::PRIV_FLAGS_NOT_MAPPED)) {
|
||||||
|
|
||||||
base = mmap(0, ionAllocData.len, PROT_READ|PROT_WRITE,
|
base = mmap(0, ionAllocData.len, PROT_READ|PROT_WRITE,
|
||||||
MAP_SHARED, fd_data.fd, 0);
|
MAP_SHARED, fd_data.fd, 0);
|
||||||
@@ -153,6 +153,7 @@ int IonAlloc::alloc_buffer(alloc_data& data)
|
|||||||
|
|
||||||
int IonAlloc::free_buffer(void* base, size_t size, int offset, int fd)
|
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",
|
ALOGD("ion: Freeing buffer base:%p size:%d fd:%d",
|
||||||
base, size, fd);
|
base, size, fd);
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|||||||
@@ -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
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are
|
* modification, are permitted provided that the following conditions are
|
||||||
@@ -31,6 +31,9 @@
|
|||||||
#define GRALLOC_IONALLOC_H
|
#define GRALLOC_IONALLOC_H
|
||||||
|
|
||||||
#include "memalloc.h"
|
#include "memalloc.h"
|
||||||
|
#include "gr.h"
|
||||||
|
//#include <linux/ion.h>
|
||||||
|
//XXX: Move to bionic
|
||||||
#include "ion_msm.h"
|
#include "ion_msm.h"
|
||||||
|
|
||||||
namespace gralloc {
|
namespace gralloc {
|
||||||
@@ -63,6 +66,8 @@ namespace gralloc {
|
|||||||
|
|
||||||
void close_device();
|
void close_device();
|
||||||
|
|
||||||
|
mutable Locker mLock;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
7
libgralloc/mapper.cpp
Executable file → Normal file
7
libgralloc/mapper.cpp
Executable file → Normal file
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2008 The Android Open Source Project
|
* 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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -83,7 +83,7 @@ static int gralloc_map(gralloc_module_t const* module,
|
|||||||
return -errno;
|
return -errno;
|
||||||
}
|
}
|
||||||
hnd->base = intptr_t(mappedAddress) + hnd->offset;
|
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);
|
// hnd->fd, hnd->offset, hnd->size, mappedAddress);
|
||||||
}
|
}
|
||||||
*vaddr = (void*)hnd->base;
|
*vaddr = (void*)hnd->base;
|
||||||
@@ -215,7 +215,8 @@ int terminateBuffer(gralloc_module_t const* module,
|
|||||||
gralloc_unmap(module, hnd);
|
gralloc_unmap(module, hnd);
|
||||||
}
|
}
|
||||||
} else {
|
} 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);
|
gralloc_unmap(module, 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
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are
|
* modification, are permitted provided that the following conditions are
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2009 The Android Open Source Project
|
* 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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -113,7 +113,7 @@ ssize_t SimpleBestFitAllocator::alloc(size_t size, uint32_t flags)
|
|||||||
mList.insertBefore(free_chunk, split);
|
mList.insertBefore(free_chunk, split);
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGE_IF(((free_chunk->start*kMemoryAlign)&(pagesize-1)),
|
ALOGE_IF(((free_chunk->start*kMemoryAlign)&(pagesize-1)),
|
||||||
"page is not aligned!!!");
|
"page is not aligned!!!");
|
||||||
|
|
||||||
const ssize_t tail_free = free_size - (size+extra);
|
const ssize_t tail_free = free_size - (size+extra);
|
||||||
@@ -128,15 +128,15 @@ ssize_t SimpleBestFitAllocator::alloc(size_t size, uint32_t flags)
|
|||||||
// we are out of PMEM. Print pmem stats
|
// we are out of PMEM. Print pmem stats
|
||||||
// check if there is any leak or fragmentation
|
// check if there is any leak or fragmentation
|
||||||
|
|
||||||
LOGD (" Out of PMEM. Dumping PMEM stats for debugging");
|
ALOGD (" Out of PMEM. Dumping PMEM stats for debugging");
|
||||||
LOGD (" ------------- PRINT PMEM STATS --------------");
|
ALOGD (" ------------- PRINT PMEM STATS --------------");
|
||||||
|
|
||||||
cur = mList.head();
|
cur = mList.head();
|
||||||
static uint32_t node_count;
|
static uint32_t node_count;
|
||||||
static uint64_t allocated, free_space;
|
static uint64_t allocated, free_space;
|
||||||
|
|
||||||
while (cur) {
|
while (cur) {
|
||||||
LOGD (" Node %d -> Start Address : %u Size %u Free info %d",\
|
ALOGD (" Node %d -> Start Address : %u Size %u Free info %d",\
|
||||||
node_count++, cur->start, cur->size, cur->free);
|
node_count++, cur->start, cur->size, cur->free);
|
||||||
|
|
||||||
// if cur-> free is 1 , the node is free
|
// if cur-> free is 1 , the node is free
|
||||||
@@ -149,12 +149,12 @@ ssize_t SimpleBestFitAllocator::alloc(size_t size, uint32_t flags)
|
|||||||
// read next node
|
// read next node
|
||||||
cur = cur->next;
|
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;
|
node_count = 0;
|
||||||
allocated = 0;
|
allocated = 0;
|
||||||
free_space = 0;
|
free_space = 0;
|
||||||
LOGD ("----------------------------------------------");
|
ALOGD ("----------------------------------------------");
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,7 +164,7 @@ SimpleBestFitAllocator::chunk_t* SimpleBestFitAllocator::dealloc(size_t start)
|
|||||||
chunk_t* cur = mList.head();
|
chunk_t* cur = mList.head();
|
||||||
while (cur) {
|
while (cur) {
|
||||||
if (cur->start == start) {
|
if (cur->start == start) {
|
||||||
LOG_FATAL_IF(cur->free,
|
ALOG_FATAL_IF(cur->free,
|
||||||
"block at offset 0x%08lX of size 0x%08lX already freed",
|
"block at offset 0x%08lX of size 0x%08lX already freed",
|
||||||
cur->start*kMemoryAlign, cur->size*kMemoryAlign);
|
cur->start*kMemoryAlign, cur->size*kMemoryAlign);
|
||||||
|
|
||||||
@@ -183,7 +183,7 @@ SimpleBestFitAllocator::chunk_t* SimpleBestFitAllocator::dealloc(size_t start)
|
|||||||
cur = n;
|
cur = n;
|
||||||
} while (cur && cur->free);
|
} while (cur && cur->free);
|
||||||
|
|
||||||
LOG_FATAL_IF(!freed->free,
|
ALOG_FATAL_IF(!freed->free,
|
||||||
"freed block at offset 0x%08lX of size 0x%08lX is not free!",
|
"freed block at offset 0x%08lX of size 0x%08lX is not free!",
|
||||||
freed->start * kMemoryAlign, freed->size * kMemoryAlign);
|
freed->start * kMemoryAlign, freed->size * kMemoryAlign);
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2009 The Android Open Source Project
|
* 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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|||||||
@@ -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
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are
|
* modification, are permitted provided that the following conditions are
|
||||||
@@ -275,7 +275,6 @@ int PmemUserspaceAlloc::unmap_buffer(void *base, size_t size, int offset)
|
|||||||
ALOGD("%s: Unmapping buffer base:%p size:%d offset:%d",
|
ALOGD("%s: Unmapping buffer base:%p size:%d offset:%d",
|
||||||
mPmemDev , base, size, offset);
|
mPmemDev , base, size, offset);
|
||||||
if (munmap(base, size) < 0) {
|
if (munmap(base, size) < 0) {
|
||||||
|
|
||||||
err = -errno;
|
err = -errno;
|
||||||
ALOGE("%s: Failed to unmap memory at %p :%s",
|
ALOGE("%s: Failed to unmap memory at %p :%s",
|
||||||
mPmemDev, base, strerror(errno));
|
mPmemDev, base, strerror(errno));
|
||||||
|
|||||||
@@ -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
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are
|
* modification, are permitted provided that the following conditions are
|
||||||
|
|||||||
@@ -1,39 +1,18 @@
|
|||||||
LOCAL_PATH := $(call my-dir)
|
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)
|
include $(CLEAR_VARS)
|
||||||
LOCAL_PRELINK_MODULE := false
|
LOCAL_PRELINK_MODULE := false
|
||||||
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
|
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
|
||||||
LOCAL_SHARED_LIBRARIES := liblog libcutils libEGL libhardware libutils liboverlay
|
LOCAL_SHARED_LIBRARIES := liblog libcutils libhardware libutils
|
||||||
LOCAL_SHARED_LIBRARIES += libgenlock libQcomUI libmemalloc
|
LOCAL_SHARED_LIBRARIES += libEGL liboverlay libgenlock
|
||||||
|
LOCAL_SRC_FILES := hwc.cpp \
|
||||||
LOCAL_SRC_FILES := \
|
hwc_overlay.cpp \
|
||||||
hwcomposer.cpp \
|
hwc_utils.cpp
|
||||||
external_display_only.h
|
|
||||||
|
|
||||||
LOCAL_MODULE := hwcomposer.$(TARGET_BOARD_PLATFORM)
|
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/libgralloc
|
|
||||||
LOCAL_C_INCLUDES += hardware/qcom/display/liboverlay
|
|
||||||
LOCAL_C_INCLUDES += hardware/qcom/display/libcopybit
|
|
||||||
LOCAL_C_INCLUDES += hardware/qcom/display/libgenlock
|
LOCAL_C_INCLUDES += hardware/qcom/display/libgenlock
|
||||||
|
LOCAL_C_INCLUDES += hardware/qcom/display/liboverlay
|
||||||
LOCAL_C_INCLUDES += hardware/qcom/display/libqcomui
|
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
|
LOCAL_MODULE_TAGS := optional
|
||||||
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
|
|
||||||
include $(BUILD_SHARED_LIBRARY)
|
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)
|
LOCAL_PATH := $(call my-dir)
|
||||||
|
|
||||||
include $(CLEAR_VARS)
|
include $(CLEAR_VARS)
|
||||||
LOCAL_PRELINK_MODULE := false
|
|
||||||
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)
|
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)
|
||||||
LOCAL_SHARED_LIBRARIES := liblog libcutils libutils libmemalloc
|
LOCAL_SHARED_LIBRARIES := liblog
|
||||||
LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
|
LOCAL_SHARED_LIBRARIES += libcutils
|
||||||
LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
|
LOCAL_SHARED_LIBRARIES += libutils
|
||||||
LOCAL_C_INCLUDES += hardware/qcom/display/libgralloc
|
LOCAL_SHARED_LIBRARIES += libmemalloc
|
||||||
|
LOCAL_C_INCLUDES := hardware/qcom/display/libgralloc
|
||||||
LOCAL_SRC_FILES := \
|
LOCAL_SRC_FILES := \
|
||||||
overlayLib.cpp \
|
overlay.cpp \
|
||||||
overlayLibUI.cpp \
|
overlayCtrl.cpp \
|
||||||
LOCAL_CFLAGS:= -DLOG_TAG=\"OverlayLib\"
|
overlayUtils.cpp \
|
||||||
|
overlayMdp.cpp \
|
||||||
|
overlayRotator.cpp \
|
||||||
|
overlayTransitions.cpp
|
||||||
|
|
||||||
ifeq ($(TARGET_USE_HDMI_AS_PRIMARY),true)
|
LOCAL_CFLAGS:= -DLOG_TAG=\"overlay2\"
|
||||||
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_MODULE := liboverlay
|
LOCAL_MODULE := liboverlay
|
||||||
|
|
||||||
#LGE_CHANGE, for userdebug mode
|
|
||||||
LOCAL_MODULE_TAGS := optional
|
LOCAL_MODULE_TAGS := optional
|
||||||
include $(BUILD_SHARED_LIBRARY)
|
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)
|
LOCAL_PATH := $(call my-dir)
|
||||||
|
|
||||||
|
#Headers to export
|
||||||
include $(CLEAR_VARS)
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
LOCAL_SRC_FILES := \
|
LOCAL_SRC_FILES := qcomutils/profiler.cpp \
|
||||||
qcom_ui.cpp
|
qcomutils/IdleInvalidator.cpp
|
||||||
|
|
||||||
LOCAL_SHARED_LIBRARIES := \
|
LOCAL_SHARED_LIBRARIES := \
|
||||||
libutils \
|
libutils \
|
||||||
libcutils \
|
libcutils \
|
||||||
libui \
|
libui \
|
||||||
libEGL
|
libEGL \
|
||||||
|
|
||||||
LOCAL_C_INCLUDES := $(TOP)/hardware/qcom/display/libgralloc \
|
LOCAL_C_INCLUDES := hardware/qcom/display/libgralloc \
|
||||||
$(TOP)/frameworks/native/services/surfaceflinger \
|
frameworks/base/services/surfaceflinger \
|
||||||
$(TOP)/external/skia/include/core \
|
|
||||||
$(TOP)/external/skia/include/images
|
|
||||||
|
|
||||||
LOCAL_CFLAGS := -DLOG_TAG=\"libQcomUI\"
|
LOCAL_CFLAGS := -DLOG_TAG=\"libQcomUI\"
|
||||||
|
|
||||||
@@ -23,6 +23,10 @@ else
|
|||||||
LOCAL_SHARED_LIBRARIES += libmemalloc
|
LOCAL_SHARED_LIBRARIES += libmemalloc
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(TARGET_USES_MDP3), true)
|
||||||
|
LOCAL_CFLAGS += -DUSE_MDP3
|
||||||
|
endif
|
||||||
|
|
||||||
LOCAL_CFLAGS += -DDEBUG_CALC_FPS
|
LOCAL_CFLAGS += -DDEBUG_CALC_FPS
|
||||||
|
|
||||||
LOCAL_MODULE := libQcomUI
|
LOCAL_MODULE := libQcomUI
|
||||||
|
|||||||
@@ -30,29 +30,21 @@
|
|||||||
#include <cutils/log.h>
|
#include <cutils/log.h>
|
||||||
#include <cutils/memory.h>
|
#include <cutils/memory.h>
|
||||||
#include <qcom_ui.h>
|
#include <qcom_ui.h>
|
||||||
|
#include <utils/comptype.h>
|
||||||
#include <gralloc_priv.h>
|
#include <gralloc_priv.h>
|
||||||
#include <alloc_controller.h>
|
#include <alloc_controller.h>
|
||||||
#include <memalloc.h>
|
#include <memalloc.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <EGL/eglext.h>
|
#include <EGL/eglext.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#if 0
|
|
||||||
#include <SkBitmap.h>
|
#include <SkBitmap.h>
|
||||||
#include <SkImageEncoder.h>
|
#include <SkImageEncoder.h>
|
||||||
#endif
|
|
||||||
#include <Transform.h>
|
#include <Transform.h>
|
||||||
|
|
||||||
#include <EGL/egl.h>
|
|
||||||
#include <GLES2/gl2.h>
|
|
||||||
#include <GLES2/gl2ext.h>
|
|
||||||
|
|
||||||
using gralloc::IMemAlloc;
|
using gralloc::IMemAlloc;
|
||||||
using gralloc::IonController;
|
using gralloc::IonController;
|
||||||
using gralloc::alloc_data;
|
using gralloc::alloc_data;
|
||||||
using android::sp;
|
using android::sp;
|
||||||
|
|
||||||
static int sCompositionType = -1;
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
static android::sp<gralloc::IAllocController> sAlloc = 0;
|
static android::sp<gralloc::IAllocController> sAlloc = 0;
|
||||||
@@ -66,7 +58,7 @@ namespace {
|
|||||||
sAlloc = gralloc::IAllocController::getInstance(true);
|
sAlloc = gralloc::IAllocController::getInstance(true);
|
||||||
}
|
}
|
||||||
if (sAlloc == 0) {
|
if (sAlloc == 0) {
|
||||||
ALOGE("sAlloc is still NULL");
|
LOGE("sAlloc is still NULL");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,7 +68,7 @@ namespace {
|
|||||||
ret = memalloc->free_buffer((void*)hnd->base, hnd->size, hnd->offset, hnd->fd);
|
ret = memalloc->free_buffer((void*)hnd->base, hnd->size, hnd->offset, hnd->fd);
|
||||||
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
ALOGE("%s: free_buffer failed", __FUNCTION__);
|
LOGE("%s: free_buffer failed", __FUNCTION__);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,7 +96,7 @@ namespace {
|
|||||||
hnd->offset = data.offset;
|
hnd->offset = data.offset;
|
||||||
hnd->size = data.size;
|
hnd->size = data.size;
|
||||||
} else {
|
} else {
|
||||||
ALOGE("%s: allocate failed", __FUNCTION__);
|
LOGE("%s: allocate failed", __FUNCTION__);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -128,7 +120,10 @@ int getNumberOfArgsForOperation(int operation) {
|
|||||||
case NATIVE_WINDOW_UPDATE_BUFFERS_GEOMETRY:
|
case NATIVE_WINDOW_UPDATE_BUFFERS_GEOMETRY:
|
||||||
num_args = 3;
|
num_args = 3;
|
||||||
break;
|
break;
|
||||||
default: ALOGE("%s: invalid operation(0x%x)", __FUNCTION__, operation);
|
case NATIVE_WINDOW_SET_PIXEL_ASPECT_RATIO:
|
||||||
|
num_args = 2;
|
||||||
|
break;
|
||||||
|
default: LOGE("%s: invalid operation(0x%x)", __FUNCTION__, operation);
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
return num_args;
|
return num_args;
|
||||||
@@ -146,6 +141,10 @@ bool isGPUSupportedFormat(int format) {
|
|||||||
// We check the YV12 formats, since some Qcom specific formats
|
// We check the YV12 formats, since some Qcom specific formats
|
||||||
// could have the bits set.
|
// could have the bits set.
|
||||||
return true;
|
return true;
|
||||||
|
} else if ((format == HAL_PIXEL_FORMAT_RGB_888) ||
|
||||||
|
(format == HAL_PIXEL_FORMAT_YCrCb_422_SP) ||
|
||||||
|
(format == HAL_PIXEL_FORMAT_YCbCr_422_SP)){
|
||||||
|
return false;
|
||||||
} else if (format & INTERLACE_MASK) {
|
} else if (format & INTERLACE_MASK) {
|
||||||
// Interlaced content
|
// Interlaced content
|
||||||
return false;
|
return false;
|
||||||
@@ -156,33 +155,6 @@ bool isGPUSupportedFormat(int format) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* decide the texture target dynamically, based on the pixel format*/
|
|
||||||
|
|
||||||
int decideTextureTarget(int pixel_format)
|
|
||||||
{
|
|
||||||
|
|
||||||
// Default the return value to GL_TEXTURE_EXTERAL_OES
|
|
||||||
int retVal = GL_TEXTURE_EXTERNAL_OES;
|
|
||||||
|
|
||||||
// Change texture target to TEXTURE_2D for RGB formats
|
|
||||||
switch (pixel_format) {
|
|
||||||
|
|
||||||
case HAL_PIXEL_FORMAT_RGBA_8888:
|
|
||||||
case HAL_PIXEL_FORMAT_RGBX_8888:
|
|
||||||
case HAL_PIXEL_FORMAT_RGB_888:
|
|
||||||
case HAL_PIXEL_FORMAT_RGB_565:
|
|
||||||
case HAL_PIXEL_FORMAT_BGRA_8888:
|
|
||||||
case HAL_PIXEL_FORMAT_RGBA_5551:
|
|
||||||
case HAL_PIXEL_FORMAT_RGBA_4444:
|
|
||||||
retVal = GL_TEXTURE_2D;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
retVal = GL_TEXTURE_EXTERNAL_OES;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return retVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Function to check if the allocated buffer is of the correct size.
|
* Function to check if the allocated buffer is of the correct size.
|
||||||
* Reallocate the buffer with the correct size, if the size doesn't
|
* Reallocate the buffer with the correct size, if the size doesn't
|
||||||
@@ -203,7 +175,7 @@ int checkBuffer(native_handle_t *buffer_handle, int size, int usage)
|
|||||||
|
|
||||||
// Validate the handle
|
// Validate the handle
|
||||||
if (private_handle_t::validate(buffer_handle)) {
|
if (private_handle_t::validate(buffer_handle)) {
|
||||||
ALOGE("%s: handle is invalid", __FUNCTION__);
|
LOGE("%s: handle is invalid", __FUNCTION__);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -255,7 +227,7 @@ bool needNewBuffer(const qBufGeometry currentGeometry,
|
|||||||
int updateBufferGeometry(sp<GraphicBuffer> buffer, const qBufGeometry updatedGeometry)
|
int updateBufferGeometry(sp<GraphicBuffer> buffer, const qBufGeometry updatedGeometry)
|
||||||
{
|
{
|
||||||
if (buffer == 0) {
|
if (buffer == 0) {
|
||||||
ALOGE("%s: graphic buffer is NULL", __FUNCTION__);
|
LOGE("%s: graphic buffer is NULL", __FUNCTION__);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -273,7 +245,7 @@ int updateBufferGeometry(sp<GraphicBuffer> buffer, const qBufGeometry updatedGeo
|
|||||||
|
|
||||||
// Validate the handle
|
// Validate the handle
|
||||||
if (private_handle_t::validate(buffer->handle)) {
|
if (private_handle_t::validate(buffer->handle)) {
|
||||||
ALOGE("%s: handle is invalid", __FUNCTION__);
|
LOGE("%s: handle is invalid", __FUNCTION__);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
buffer->width = updatedGeometry.width;
|
buffer->width = updatedGeometry.width;
|
||||||
@@ -285,7 +257,7 @@ int updateBufferGeometry(sp<GraphicBuffer> buffer, const qBufGeometry updatedGeo
|
|||||||
hnd->height = updatedGeometry.height;
|
hnd->height = updatedGeometry.height;
|
||||||
hnd->format = updatedGeometry.format;
|
hnd->format = updatedGeometry.format;
|
||||||
} else {
|
} else {
|
||||||
ALOGE("%s: hnd is NULL", __FUNCTION__);
|
LOGE("%s: hnd is NULL", __FUNCTION__);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -300,7 +272,7 @@ int updateBufferGeometry(sp<GraphicBuffer> buffer, const qBufGeometry updatedGeo
|
|||||||
int updateBufferS3DFormat(sp<GraphicBuffer> buffer, const int s3dFormat)
|
int updateBufferS3DFormat(sp<GraphicBuffer> buffer, const int s3dFormat)
|
||||||
{
|
{
|
||||||
if (buffer == 0) {
|
if (buffer == 0) {
|
||||||
ALOGE("%s: graphic buffer is NULL", __FUNCTION__);
|
LOGE("%s: graphic buffer is NULL", __FUNCTION__);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -331,7 +303,7 @@ int updateLayerQcomFlags(eLayerAttrib attribute, bool enable, int& currentFlags)
|
|||||||
else
|
else
|
||||||
currentFlags &= ~LAYER_ASYNCHRONOUS;
|
currentFlags &= ~LAYER_ASYNCHRONOUS;
|
||||||
} break;
|
} break;
|
||||||
default: ALOGE("%s: invalid attribute(0x%x)", __FUNCTION__, attribute);
|
default: LOGE("%s: invalid attribute(0x%x)", __FUNCTION__, attribute);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
@@ -375,42 +347,11 @@ bool isUpdatingFB(HWCCompositionType compositionType)
|
|||||||
case HWC_USE_COPYBIT:
|
case HWC_USE_COPYBIT:
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
ALOGE("%s: invalid composition type(%d)", __FUNCTION__, compositionType);
|
LOGE("%s: invalid composition type(%d)", __FUNCTION__, compositionType);
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Get the current composition Type
|
|
||||||
*
|
|
||||||
* @return the compositon Type
|
|
||||||
*/
|
|
||||||
int getCompositionType() {
|
|
||||||
char property[PROPERTY_VALUE_MAX];
|
|
||||||
int compositionType = 0;
|
|
||||||
if (property_get("debug.sf.hw", property, NULL) > 0) {
|
|
||||||
if(atoi(property) == 0) {
|
|
||||||
compositionType = COMPOSITION_TYPE_CPU;
|
|
||||||
} else { //debug.sf.hw = 1
|
|
||||||
property_get("debug.composition.type", property, NULL);
|
|
||||||
if (property == NULL) {
|
|
||||||
compositionType = COMPOSITION_TYPE_GPU;
|
|
||||||
} else if ((strncmp(property, "mdp", 3)) == 0) {
|
|
||||||
compositionType = COMPOSITION_TYPE_MDP;
|
|
||||||
} else if ((strncmp(property, "c2d", 3)) == 0) {
|
|
||||||
compositionType = COMPOSITION_TYPE_C2D;
|
|
||||||
} else if ((strncmp(property, "dyn", 3)) == 0) {
|
|
||||||
compositionType = COMPOSITION_TYPE_DYN;
|
|
||||||
} else {
|
|
||||||
compositionType = COMPOSITION_TYPE_GPU;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else { //debug.sf.hw is not set. Use cpu composition
|
|
||||||
compositionType = COMPOSITION_TYPE_CPU;
|
|
||||||
}
|
|
||||||
return compositionType;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Clear Region implementation for C2D/MDP versions.
|
* Clear Region implementation for C2D/MDP versions.
|
||||||
*
|
*
|
||||||
@@ -422,17 +363,13 @@ int getCompositionType() {
|
|||||||
*/
|
*/
|
||||||
int qcomuiClearRegion(Region region, EGLDisplay dpy, EGLSurface sur)
|
int qcomuiClearRegion(Region region, EGLDisplay dpy, EGLSurface sur)
|
||||||
{
|
{
|
||||||
#if 0 /* FIXME DIE */
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
int compositionType = QCCompositionType::getInstance().getCompositionType();
|
||||||
|
|
||||||
if (-1 == sCompositionType) {
|
if (compositionType & COMPOSITION_TYPE_GPU ||
|
||||||
sCompositionType = getCompositionType();
|
(compositionType == COMPOSITION_TYPE_DYN|COMPOSITION_TYPE_C2D))
|
||||||
}
|
{
|
||||||
|
// For GPU or DYN comp. with C2D, return an error, so that SF can use
|
||||||
if ((COMPOSITION_TYPE_MDP != sCompositionType) &&
|
|
||||||
(COMPOSITION_TYPE_C2D != sCompositionType) &&
|
|
||||||
(COMPOSITION_TYPE_CPU != sCompositionType)) {
|
|
||||||
// For non CPU/C2D/MDP composition, return an error, so that SF can use
|
|
||||||
// the GPU to draw the wormhole.
|
// the GPU to draw the wormhole.
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -440,13 +377,13 @@ int qcomuiClearRegion(Region region, EGLDisplay dpy, EGLSurface sur)
|
|||||||
android_native_buffer_t *renderBuffer = (android_native_buffer_t *)
|
android_native_buffer_t *renderBuffer = (android_native_buffer_t *)
|
||||||
eglGetRenderBufferANDROID(dpy, sur);
|
eglGetRenderBufferANDROID(dpy, sur);
|
||||||
if (!renderBuffer) {
|
if (!renderBuffer) {
|
||||||
ALOGE("%s: eglGetRenderBufferANDROID returned NULL buffer",
|
LOGE("%s: eglGetRenderBufferANDROID returned NULL buffer",
|
||||||
__FUNCTION__);
|
__FUNCTION__);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
private_handle_t *fbHandle = (private_handle_t *)renderBuffer->handle;
|
private_handle_t *fbHandle = (private_handle_t *)renderBuffer->handle;
|
||||||
if(!fbHandle) {
|
if(!fbHandle) {
|
||||||
ALOGE("%s: Framebuffer handle is NULL", __FUNCTION__);
|
LOGE("%s: Framebuffer handle is NULL", __FUNCTION__);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -472,42 +409,45 @@ int qcomuiClearRegion(Region region, EGLDisplay dpy, EGLSurface sur)
|
|||||||
dst += stride;
|
dst += stride;
|
||||||
} while(--h);
|
} while(--h);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Handles the externalDisplay event
|
* Handles the externalDisplay event
|
||||||
* HDMI has highest priority compared to WifiDisplay
|
* HDMI has highest priority compared to WifiDisplay
|
||||||
* Based on the current and the new display event, decides the
|
* Based on the current and the new display type, decides the
|
||||||
* external display to be enabled
|
* external display to be enabled
|
||||||
*
|
*
|
||||||
* @param: newEvent - new external event
|
* @param: disp - external display type(wfd/hdmi)
|
||||||
* @param: currEvent - currently enabled external event
|
* @param: value - external event(0/1)
|
||||||
* @return: external display to be enabled
|
* @param: currdispType - Current enabled external display Type
|
||||||
|
* @return: external display type to be enabled
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
external_display handleEventHDMI(external_display newState, external_display
|
external_display_type handleEventHDMI(external_display_type disp, int value,
|
||||||
currState)
|
external_display_type currDispType)
|
||||||
{
|
{
|
||||||
external_display retState = currState;
|
external_display_type retDispType = currDispType;
|
||||||
switch(newState) {
|
switch(disp) {
|
||||||
case EXT_DISPLAY_HDMI:
|
case EXT_TYPE_HDMI:
|
||||||
retState = EXT_DISPLAY_HDMI;
|
if(value)
|
||||||
|
retDispType = EXT_TYPE_HDMI;
|
||||||
|
else
|
||||||
|
retDispType = EXT_TYPE_NONE;
|
||||||
break;
|
break;
|
||||||
case EXT_DISPLAY_WIFI:
|
case EXT_TYPE_WIFI:
|
||||||
if(currState != EXT_DISPLAY_HDMI) {
|
if(currDispType != EXT_TYPE_HDMI) {
|
||||||
retState = EXT_DISPLAY_WIFI;
|
if(value)
|
||||||
|
retDispType = EXT_TYPE_WIFI;
|
||||||
|
else
|
||||||
|
retDispType = EXT_TYPE_NONE;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case EXT_DISPLAY_OFF:
|
|
||||||
retState = EXT_DISPLAY_OFF;
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
ALOGE("handleEventHDMI: unknown Event");
|
LOGE("%s: Unknown External Display Type!!");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return retState;
|
return retDispType;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Using global variables for layer dumping since "property_set("debug.sf.dump",
|
// Using global variables for layer dumping since "property_set("debug.sf.dump",
|
||||||
@@ -549,7 +489,7 @@ bool needToDumpLayers()
|
|||||||
if (0 == mkdir(sfdumpdir_png, 0777))
|
if (0 == mkdir(sfdumpdir_png, 0777))
|
||||||
sfdump_counter_png = 0;
|
sfdump_counter_png = 0;
|
||||||
else
|
else
|
||||||
ALOGE("sfdump: Error: %s. Failed to create sfdump directory"
|
LOGE("sfdump: Error: %s. Failed to create sfdump directory"
|
||||||
": %s", strerror(errno), sfdumpdir_png);
|
": %s", strerror(errno), sfdumpdir_png);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -575,7 +515,7 @@ bool needToDumpLayers()
|
|||||||
if (0 == mkdir(sfdumpdir_raw, 0777))
|
if (0 == mkdir(sfdumpdir_raw, 0777))
|
||||||
sfdump_counter_raw = 0;
|
sfdump_counter_raw = 0;
|
||||||
else
|
else
|
||||||
ALOGE("sfdump: Error: %s. Failed to create sfdump directory"
|
LOGE("sfdump: Error: %s. Failed to create sfdump directory"
|
||||||
": %s", strerror(errno), sfdumpdir_raw);
|
": %s", strerror(errno), sfdumpdir_raw);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -670,7 +610,7 @@ void dumpLayer(int moduleCompositionType, int listFlags, size_t layerIndex,
|
|||||||
sfdump_counter_raw, sfdump_countlimit_raw);
|
sfdump_counter_raw, sfdump_countlimit_raw);
|
||||||
}
|
}
|
||||||
if (NULL == hwLayers) {
|
if (NULL == hwLayers) {
|
||||||
ALOGE("sfdump: Error.%s%sLayer[%d] No hwLayers to dump.",
|
LOGE("sfdump: Error.%s%sLayer[%d] No hwLayers to dump.",
|
||||||
dumplogstr_raw, dumplogstr_png, layerIndex);
|
dumplogstr_raw, dumplogstr_png, layerIndex);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -679,11 +619,12 @@ void dumpLayer(int moduleCompositionType, int listFlags, size_t layerIndex,
|
|||||||
hwc_rect_t displayFrame = layer->displayFrame;
|
hwc_rect_t displayFrame = layer->displayFrame;
|
||||||
private_handle_t *hnd = (private_handle_t *)layer->handle;
|
private_handle_t *hnd = (private_handle_t *)layer->handle;
|
||||||
char pixelformatstr[32] = "None";
|
char pixelformatstr[32] = "None";
|
||||||
|
uint32_t transform = layer->transform & FINAL_TRANSFORM_MASK;
|
||||||
|
|
||||||
if (hnd)
|
if (hnd)
|
||||||
getHalPixelFormatStr(hnd->format, pixelformatstr);
|
getHalPixelFormatStr(hnd->format, pixelformatstr);
|
||||||
#if 0
|
|
||||||
ALOGE("sfdump: %s%s[%s]-Composition, Layer[%d] SrcBuff[%dx%d] "
|
LOGE("sfdump: %s%s[%s]-Composition, Layer[%d] SrcBuff[%dx%d] "
|
||||||
"SrcCrop[%dl, %dt, %dr, %db] "
|
"SrcCrop[%dl, %dt, %dr, %db] "
|
||||||
"DispFrame[%dl, %dt, %dr, %db] Composition-type = %s, Format = %s, "
|
"DispFrame[%dl, %dt, %dr, %db] Composition-type = %s, Format = %s, "
|
||||||
"Orientation = %s, Flags = %s%s%s%s%s%s%s%s%s%s",
|
"Orientation = %s, Flags = %s%s%s%s%s%s%s%s%s%s",
|
||||||
@@ -703,32 +644,29 @@ void dumpLayer(int moduleCompositionType, int listFlags, size_t layerIndex,
|
|||||||
(layer->compositionType == HWC_OVERLAY)? "Overlay":
|
(layer->compositionType == HWC_OVERLAY)? "Overlay":
|
||||||
(layer->compositionType == HWC_USE_COPYBIT)? "Copybit": "???",
|
(layer->compositionType == HWC_USE_COPYBIT)? "Copybit": "???",
|
||||||
pixelformatstr,
|
pixelformatstr,
|
||||||
(layer->transform == Transform::ROT_0)? "ROT_0":
|
(transform == Transform::ROT_0)? "ROT_0":
|
||||||
(layer->transform == Transform::FLIP_H)? "FLIP_H":
|
(transform == Transform::FLIP_H)? "FLIP_H":
|
||||||
(layer->transform == Transform::FLIP_V)? "FLIP_V":
|
(transform == Transform::FLIP_V)? "FLIP_V":
|
||||||
(layer->transform == Transform::ROT_90)? "ROT_90":
|
(transform == Transform::ROT_90)? "ROT_90":
|
||||||
(layer->transform == Transform::ROT_180)? "ROT_180":
|
(transform == Transform::ROT_180)? "ROT_180":
|
||||||
(layer->transform == Transform::ROT_270)? "ROT_270":
|
(transform == Transform::ROT_270)? "ROT_270":
|
||||||
(layer->transform == Transform::ROT_INVALID)? "ROT_INVALID":"???",
|
(transform == Transform::ROT_INVALID)? "ROT_INVALID":"???",
|
||||||
(layer->flags == 0)? "[None]":"",
|
(layer->flags == 0)? "[None]":"",
|
||||||
(layer->flags & HWC_SKIP_LAYER)? "[Skip layer]":"",
|
(layer->flags & HWC_SKIP_LAYER)? "[Skip layer]":"",
|
||||||
(layer->flags & HWC_LAYER_NOT_UPDATING)? "[Layer not updating]":"",
|
(layer->flags & HWC_LAYER_NOT_UPDATING)? "[Layer not updating]":"",
|
||||||
(layer->flags & HWC_USE_ORIGINAL_RESOLUTION)? "[Original Resolution]":"",
|
|
||||||
(layer->flags & HWC_DO_NOT_USE_OVERLAY)? "[Do not use Overlay]":"",
|
|
||||||
(layer->flags & HWC_COMP_BYPASS)? "[Bypass]":"",
|
(layer->flags & HWC_COMP_BYPASS)? "[Bypass]":"",
|
||||||
(layer->flags & HWC_BYPASS_RESERVE_0)? "[Bypass Reserve 0]":"",
|
(layer->flags & HWC_BYPASS_RESERVE_0)? "[Bypass Reserve 0]":"",
|
||||||
(layer->flags & HWC_BYPASS_RESERVE_1)? "[Bypass Reserve 1]":"",
|
(layer->flags & HWC_BYPASS_RESERVE_1)? "[Bypass Reserve 1]":"",
|
||||||
(listFlags & HWC_GEOMETRY_CHANGED)? "[List: Geometry Changed]":"",
|
(listFlags & HWC_GEOMETRY_CHANGED)? "[List: Geometry Changed]":"",
|
||||||
(listFlags & HWC_SKIP_COMPOSITION)? "[List: Skip Composition]":"");
|
(listFlags & HWC_SKIP_COMPOSITION)? "[List: Skip Composition]":"");
|
||||||
#endif
|
|
||||||
if (NULL == hnd) {
|
if (NULL == hnd) {
|
||||||
ALOGE("sfdump: %s%sLayer[%d] private-handle is invalid.",
|
LOGE("sfdump: %s%sLayer[%d] private-handle is invalid.",
|
||||||
dumplogstr_raw, dumplogstr_png, layerIndex);
|
dumplogstr_raw, dumplogstr_png, layerIndex);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((sfdump_counter_png <= sfdump_countlimit_png) && hnd->base) {
|
if ((sfdump_counter_png <= sfdump_countlimit_png) && hnd->base) {
|
||||||
#if 0
|
|
||||||
bool bResult = false;
|
bool bResult = false;
|
||||||
char sfdumpfile_name[256];
|
char sfdumpfile_name[256];
|
||||||
SkBitmap *tempSkBmp = new SkBitmap();
|
SkBitmap *tempSkBmp = new SkBitmap();
|
||||||
@@ -757,16 +695,15 @@ void dumpLayer(int moduleCompositionType, int listFlags, size_t layerIndex,
|
|||||||
tempSkBmp->setPixels((void*)hnd->base);
|
tempSkBmp->setPixels((void*)hnd->base);
|
||||||
bResult = SkImageEncoder::EncodeFile(sfdumpfile_name,
|
bResult = SkImageEncoder::EncodeFile(sfdumpfile_name,
|
||||||
*tempSkBmp, SkImageEncoder::kPNG_Type, 100);
|
*tempSkBmp, SkImageEncoder::kPNG_Type, 100);
|
||||||
ALOGE("sfdump: %sDumped Layer[%d] to %s: %s", dumplogstr_png,
|
LOGE("sfdump: %sDumped Layer[%d] to %s: %s", dumplogstr_png,
|
||||||
layerIndex, sfdumpfile_name, bResult ? "Success" : "Fail");
|
layerIndex, sfdumpfile_name, bResult ? "Success" : "Fail");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ALOGE("sfdump: %sSkipping Layer[%d] dump: Unsupported layer "
|
LOGE("sfdump: %sSkipping Layer[%d] dump: Unsupported layer "
|
||||||
"format %s for png encoder.", dumplogstr_png, layerIndex,
|
"format %s for png encoder.", dumplogstr_png, layerIndex,
|
||||||
pixelformatstr);
|
pixelformatstr);
|
||||||
}
|
}
|
||||||
delete tempSkBmp; // Calls SkBitmap::freePixels() internally.
|
delete tempSkBmp; // Calls SkBitmap::freePixels() internally.
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((sfdump_counter_raw <= sfdump_countlimit_raw) && hnd->base) {
|
if ((sfdump_counter_raw <= sfdump_countlimit_raw) && hnd->base) {
|
||||||
@@ -781,161 +718,146 @@ void dumpLayer(int moduleCompositionType, int listFlags, size_t layerIndex,
|
|||||||
bResult = (bool) fwrite((void*)hnd->base, hnd->size, 1, fp);
|
bResult = (bool) fwrite((void*)hnd->base, hnd->size, 1, fp);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
}
|
}
|
||||||
ALOGE("sfdump: %s Dumped Layer[%d] to %s: %s", dumplogstr_raw,
|
LOGE("sfdump: %s Dumped Layer[%d] to %s: %s", dumplogstr_raw,
|
||||||
layerIndex, sfdumpfile_name, bResult ? "Success" : "Fail");
|
layerIndex, sfdumpfile_name, bResult ? "Success" : "Fail");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_CALC_FPS
|
bool needsAspectRatio (int wRatio, int hRatio) {
|
||||||
ANDROID_SINGLETON_STATIC_INSTANCE(CalcFps) ;
|
return ((wRatio != DEFAULT_WIDTH_RATIO) || (hRatio != DEFAULT_HEIGHT_RATIO));
|
||||||
|
|
||||||
CalcFps::CalcFps() {
|
|
||||||
debug_fps_level = 0;
|
|
||||||
Init();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CalcFps::~CalcFps() {
|
void applyPixelAspectRatio (int wRatio, int hRatio, int orientation, int maxWidth,
|
||||||
}
|
int maxHeight, Rect& visibleRect, GLfloat mVertices[][2]) {
|
||||||
|
|
||||||
void CalcFps::Init() {
|
if ((wRatio == 0) || (hRatio == 0))
|
||||||
char prop[PROPERTY_VALUE_MAX];
|
return;
|
||||||
property_get("debug.gr.calcfps", prop, "0");
|
|
||||||
debug_fps_level = atoi(prop);
|
|
||||||
if (debug_fps_level > MAX_DEBUG_FPS_LEVEL) {
|
|
||||||
ALOGW("out of range value for debug.gr.calcfps, using 0");
|
|
||||||
debug_fps_level = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ALOGE("DEBUG_CALC_FPS: %d", debug_fps_level);
|
float wDelta = 0;
|
||||||
populate_debug_fps_metadata();
|
float hDelta = 0;
|
||||||
}
|
float aspectRatio;
|
||||||
|
float displayRatio;
|
||||||
|
float new_width, new_height;
|
||||||
|
float old_width = abs(visibleRect.right - visibleRect.left);
|
||||||
|
float old_height = abs(visibleRect.bottom - visibleRect.top);
|
||||||
|
|
||||||
void CalcFps::Fps() {
|
if (orientation == Transform::ROT_INVALID) {
|
||||||
if (debug_fps_level > 0)
|
// During animation, no defined orientation, rely on mTransformedBounds
|
||||||
calc_fps(ns2us(systemTime()));
|
if (old_width >= old_height)
|
||||||
}
|
orientation = Transform::ROT_0;
|
||||||
|
|
||||||
void CalcFps::populate_debug_fps_metadata(void)
|
|
||||||
{
|
|
||||||
char prop[PROPERTY_VALUE_MAX];
|
|
||||||
|
|
||||||
/*defaults calculation of fps to based on number of frames*/
|
|
||||||
property_get("debug.gr.calcfps.type", prop, "0");
|
|
||||||
debug_fps_metadata.type = (debug_fps_metadata_t::DfmType) atoi(prop);
|
|
||||||
|
|
||||||
/*defaults to 1000ms*/
|
|
||||||
property_get("debug.gr.calcfps.timeperiod", prop, "1000");
|
|
||||||
debug_fps_metadata.time_period = atoi(prop);
|
|
||||||
|
|
||||||
property_get("debug.gr.calcfps.period", prop, "10");
|
|
||||||
debug_fps_metadata.period = atoi(prop);
|
|
||||||
|
|
||||||
if (debug_fps_metadata.period > MAX_FPS_CALC_PERIOD_IN_FRAMES) {
|
|
||||||
debug_fps_metadata.period = MAX_FPS_CALC_PERIOD_IN_FRAMES;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* default ignorethresh_us: 500 milli seconds */
|
|
||||||
property_get("debug.gr.calcfps.ignorethresh_us", prop, "500000");
|
|
||||||
debug_fps_metadata.ignorethresh_us = atoi(prop);
|
|
||||||
|
|
||||||
debug_fps_metadata.framearrival_steps =
|
|
||||||
(debug_fps_metadata.ignorethresh_us / 16666);
|
|
||||||
|
|
||||||
if (debug_fps_metadata.framearrival_steps > MAX_FRAMEARRIVAL_STEPS) {
|
|
||||||
debug_fps_metadata.framearrival_steps = MAX_FRAMEARRIVAL_STEPS;
|
|
||||||
debug_fps_metadata.ignorethresh_us =
|
|
||||||
debug_fps_metadata.framearrival_steps * 16666;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 2ms margin of error for the gettimeofday */
|
|
||||||
debug_fps_metadata.margin_us = 2000;
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i < MAX_FRAMEARRIVAL_STEPS; i++)
|
|
||||||
debug_fps_metadata.accum_framearrivals[i] = 0;
|
|
||||||
|
|
||||||
ALOGE("period: %d", debug_fps_metadata.period);
|
|
||||||
ALOGE("ignorethresh_us: %lld", debug_fps_metadata.ignorethresh_us);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CalcFps::print_fps(float fps)
|
|
||||||
{
|
|
||||||
if (debug_fps_metadata_t::DFM_FRAMES == debug_fps_metadata.type)
|
|
||||||
ALOGE("FPS for last %d frames: %3.2f", debug_fps_metadata.period, fps);
|
|
||||||
else
|
else
|
||||||
ALOGE("FPS for last (%f ms, %d frames): %3.2f",
|
orientation = Transform::ROT_90;
|
||||||
debug_fps_metadata.time_elapsed,
|
|
||||||
debug_fps_metadata.curr_frame, fps);
|
|
||||||
|
|
||||||
debug_fps_metadata.curr_frame = 0;
|
|
||||||
debug_fps_metadata.time_elapsed = 0.0;
|
|
||||||
|
|
||||||
if (debug_fps_level > 1) {
|
|
||||||
ALOGE("Frame Arrival Distribution:");
|
|
||||||
for (unsigned int i = 0;
|
|
||||||
i < ((debug_fps_metadata.framearrival_steps / 6) + 1);
|
|
||||||
i++) {
|
|
||||||
ALOGE("%lld %lld %lld %lld %lld %lld",
|
|
||||||
debug_fps_metadata.accum_framearrivals[i*6],
|
|
||||||
debug_fps_metadata.accum_framearrivals[i*6+1],
|
|
||||||
debug_fps_metadata.accum_framearrivals[i*6+2],
|
|
||||||
debug_fps_metadata.accum_framearrivals[i*6+3],
|
|
||||||
debug_fps_metadata.accum_framearrivals[i*6+4],
|
|
||||||
debug_fps_metadata.accum_framearrivals[i*6+5]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We are done with displaying, now clear the stats */
|
switch (orientation) {
|
||||||
for (unsigned int i = 0;
|
|
||||||
i < debug_fps_metadata.framearrival_steps;
|
case Transform::ROT_0:
|
||||||
i++)
|
case Transform::ROT_180:
|
||||||
debug_fps_metadata.accum_framearrivals[i] = 0;
|
|
||||||
|
// Calculated Aspect Ratio = Original Aspect Ratio x Pixel Aspect Ratio
|
||||||
|
aspectRatio = (old_width * wRatio) / (old_height * hRatio);
|
||||||
|
displayRatio = (float)maxWidth / (float)maxHeight;
|
||||||
|
|
||||||
|
if (aspectRatio >= displayRatio) {
|
||||||
|
new_height = old_width / aspectRatio;
|
||||||
|
if (new_height > maxHeight) {
|
||||||
|
new_height = maxHeight;
|
||||||
|
new_width = new_height * aspectRatio;
|
||||||
|
wDelta = (new_width - old_width) / 2;
|
||||||
}
|
}
|
||||||
return;
|
hDelta = (new_height - old_height) / 2;
|
||||||
|
} else {
|
||||||
|
new_width = old_height * aspectRatio;
|
||||||
|
if (new_width > maxWidth) {
|
||||||
|
new_width = maxWidth;
|
||||||
|
new_height = new_width / aspectRatio;
|
||||||
|
hDelta = (new_height - old_height) / 2;
|
||||||
|
}
|
||||||
|
wDelta = (new_width - old_width) / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CalcFps::calc_fps(nsecs_t currtime_us)
|
if (hDelta != 0) {
|
||||||
{
|
visibleRect.top -= hDelta;
|
||||||
static nsecs_t oldtime_us = 0;
|
visibleRect.bottom += hDelta;
|
||||||
|
|
||||||
nsecs_t diff = currtime_us - oldtime_us;
|
// Set mVertices for GPU fallback (During rotation)
|
||||||
|
if (orientation == Transform::ROT_0) {
|
||||||
oldtime_us = currtime_us;
|
mVertices[1][1] = mVertices[2][1] = visibleRect.top;
|
||||||
|
mVertices[0][1] = mVertices[3][1] = visibleRect.bottom;
|
||||||
if (debug_fps_metadata_t::DFM_FRAMES == debug_fps_metadata.type &&
|
} else {
|
||||||
diff > debug_fps_metadata.ignorethresh_us) {
|
mVertices[0][1] = mVertices[3][1] = visibleRect.top;
|
||||||
return;
|
mVertices[1][1] = mVertices[2][1] = visibleRect.bottom;
|
||||||
}
|
|
||||||
|
|
||||||
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 (wDelta != 0) {
|
||||||
if (debug_fps_metadata.curr_frame == debug_fps_metadata.period) {
|
visibleRect.left -= wDelta;
|
||||||
/* time to calculate and display FPS */
|
visibleRect.right += wDelta;
|
||||||
nsecs_t sum = 0;
|
|
||||||
for (unsigned int i = 0; i < debug_fps_metadata.period; i++)
|
// Set mVertices for GPU fallback (During rotation)
|
||||||
sum += debug_fps_metadata.framearrivals[i];
|
mVertices[0][0] = mVertices[1][0] = visibleRect.left;
|
||||||
print_fps((debug_fps_metadata.period * float(1000000))/float(sum));
|
mVertices[2][0] = mVertices[3][0] = visibleRect.right;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Transform::ROT_90:
|
||||||
|
case Transform::ROT_270:
|
||||||
|
|
||||||
|
// Calculated Aspect Ratio = Original Aspect Ratio x Pixel Aspect Ratio
|
||||||
|
aspectRatio = (old_height * wRatio) / (old_width * hRatio);
|
||||||
|
displayRatio = (float)maxHeight / (float)maxWidth;
|
||||||
|
|
||||||
|
if (aspectRatio >= displayRatio) {
|
||||||
|
new_height = old_width * aspectRatio;
|
||||||
|
if (new_height > maxHeight) {
|
||||||
|
new_height = maxHeight;
|
||||||
|
new_width = new_height / aspectRatio;
|
||||||
|
wDelta = (new_width - old_width) / 2;
|
||||||
|
}
|
||||||
|
hDelta = (new_height - old_height) / 2;
|
||||||
|
} else {
|
||||||
|
new_width = old_height / aspectRatio;
|
||||||
|
if (new_width > maxWidth) {
|
||||||
|
new_width = maxWidth;
|
||||||
|
new_height = new_width * aspectRatio;
|
||||||
|
hDelta = (new_height - old_height) / 2;
|
||||||
|
}
|
||||||
|
wDelta = (new_width - old_width) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hDelta != 0) {
|
||||||
|
visibleRect.top -= hDelta;
|
||||||
|
visibleRect.bottom += hDelta;
|
||||||
|
|
||||||
|
// Set mVertices for GPU fallback (During rotation)
|
||||||
|
if (orientation == Transform::ROT_90) {
|
||||||
|
mVertices[2][1] = mVertices[3][1] = visibleRect.top;
|
||||||
|
mVertices[0][1] = mVertices[1][1] = visibleRect.bottom;
|
||||||
|
} else {
|
||||||
|
mVertices[0][1] = mVertices[1][1] = visibleRect.top;
|
||||||
|
mVertices[2][1] = mVertices[3][1] = visibleRect.bottom;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (debug_fps_metadata_t::DFM_TIME == debug_fps_metadata.type) {
|
|
||||||
debug_fps_metadata.time_elapsed += ((float)diff/1000.0);
|
if (wDelta != 0) {
|
||||||
if (debug_fps_metadata.time_elapsed >= debug_fps_metadata.time_period) {
|
visibleRect.left -= wDelta;
|
||||||
float fps = (1000.0 * debug_fps_metadata.curr_frame)/
|
visibleRect.right += wDelta;
|
||||||
(float)debug_fps_metadata.time_elapsed;
|
|
||||||
print_fps(fps);
|
// Set mVertices for GPU fallback (During rotation)
|
||||||
|
if (orientation == Transform::ROT_90) {
|
||||||
|
mVertices[1][0] = mVertices[2][0] = visibleRect.left;
|
||||||
|
mVertices[0][0] = mVertices[3][0] = visibleRect.right;
|
||||||
|
} else {
|
||||||
|
mVertices[0][0] = mVertices[3][0] = visibleRect.left;
|
||||||
|
mVertices[1][0] = mVertices[2][0] = visibleRect.right;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
break;
|
||||||
|
|
||||||
|
default: // Handled above.
|
||||||
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -33,18 +33,19 @@
|
|||||||
#include <cutils/native_handle.h>
|
#include <cutils/native_handle.h>
|
||||||
#include <ui/GraphicBuffer.h>
|
#include <ui/GraphicBuffer.h>
|
||||||
#include <hardware/hwcomposer.h>
|
#include <hardware/hwcomposer.h>
|
||||||
#include <hardware/hwcomposer_defs.h>
|
|
||||||
#include <ui/Region.h>
|
#include <ui/Region.h>
|
||||||
#include <EGL/egl.h>
|
#include <EGL/egl.h>
|
||||||
|
#include <GLES/gl.h>
|
||||||
#include <utils/Singleton.h>
|
#include <utils/Singleton.h>
|
||||||
#include <cutils/properties.h>
|
#include <cutils/properties.h>
|
||||||
#include "../libgralloc/gralloc_priv.h"
|
|
||||||
|
|
||||||
using namespace android;
|
using namespace android;
|
||||||
using android::sp;
|
using android::sp;
|
||||||
using android::GraphicBuffer;
|
using android::GraphicBuffer;
|
||||||
|
|
||||||
#define HWC_BYPASS_INDEX_MASK 0x00000030
|
#define HWC_BYPASS_INDEX_MASK 0x00000030
|
||||||
|
#define DEFAULT_WIDTH_RATIO 1
|
||||||
|
#define DEFAULT_HEIGHT_RATIO 1
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Qcom specific Native Window perform operations
|
* Qcom specific Native Window perform operations
|
||||||
@@ -53,15 +54,7 @@ enum {
|
|||||||
NATIVE_WINDOW_SET_BUFFERS_SIZE = 0x10000000,
|
NATIVE_WINDOW_SET_BUFFERS_SIZE = 0x10000000,
|
||||||
NATIVE_WINDOW_UPDATE_BUFFERS_GEOMETRY = 0x20000000,
|
NATIVE_WINDOW_UPDATE_BUFFERS_GEOMETRY = 0x20000000,
|
||||||
NATIVE_WINDOW_SET_S3D_FORMAT = 0x40000000,
|
NATIVE_WINDOW_SET_S3D_FORMAT = 0x40000000,
|
||||||
};
|
NATIVE_WINDOW_SET_PIXEL_ASPECT_RATIO = 0x80000000,
|
||||||
|
|
||||||
// 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
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -80,17 +73,22 @@ enum {
|
|||||||
LAYER_ASYNCHRONOUS = 1<<1,
|
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
|
* Flags set by the layer and sent to HWC
|
||||||
*/
|
*/
|
||||||
enum {
|
enum {
|
||||||
HWC_LAYER_NOT_UPDATING = 0x00000002,
|
HWC_LAYER_NOT_UPDATING = 0x00000002,
|
||||||
HWC_LAYER_ASYNCHRONOUS = 0x00000004,
|
HWC_LAYER_ASYNCHRONOUS = 0x00000004,
|
||||||
HWC_USE_ORIGINAL_RESOLUTION = 0x10000000,
|
HWC_COMP_BYPASS = 0x10000000,
|
||||||
HWC_DO_NOT_USE_OVERLAY = 0x20000000,
|
HWC_USE_EXT_ONLY = 0x20000000, //Layer displayed on external only
|
||||||
HWC_COMP_BYPASS = 0x40000000,
|
HWC_USE_EXT_BLOCK = 0x40000000, //Layer displayed on external only
|
||||||
HWC_USE_EXT_ONLY = 0x80000000, //Layer displayed on external only
|
|
||||||
HWC_USE_EXT_BLOCK = 0x01000000, //Layer displayed on external only
|
|
||||||
HWC_BYPASS_RESERVE_0 = 0x00000010,
|
HWC_BYPASS_RESERVE_0 = 0x00000010,
|
||||||
HWC_BYPASS_RESERVE_1 = 0x00000020,
|
HWC_BYPASS_RESERVE_1 = 0x00000020,
|
||||||
};
|
};
|
||||||
@@ -101,10 +99,41 @@ enum HWCCompositionType {
|
|||||||
HWC_USE_COPYBIT // This layer is to be handled by copybit
|
HWC_USE_COPYBIT // This layer is to be handled by copybit
|
||||||
};
|
};
|
||||||
|
|
||||||
enum external_display {
|
enum external_display_type {
|
||||||
EXT_DISPLAY_OFF,
|
EXT_TYPE_NONE,
|
||||||
EXT_DISPLAY_HDMI,
|
EXT_TYPE_HDMI,
|
||||||
EXT_DISPLAY_WIFI
|
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
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -121,74 +150,6 @@ struct qBufGeometry {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#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
|
#if 0
|
||||||
class QCBaseLayer
|
class QCBaseLayer
|
||||||
{
|
{
|
||||||
@@ -242,21 +203,6 @@ int checkBuffer(native_handle_t *buffer_handle, int size, int usage);
|
|||||||
*/
|
*/
|
||||||
bool isGPUSupportedFormat(int format);
|
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.
|
* Gets the number of arguments required for this operation.
|
||||||
@@ -326,13 +272,6 @@ int getPerFrameFlags(int hwclFlags, int layerFlags);
|
|||||||
|
|
||||||
bool isUpdatingFB(HWCCompositionType compositionType);
|
bool isUpdatingFB(HWCCompositionType compositionType);
|
||||||
|
|
||||||
/*
|
|
||||||
* Get the current composition Type
|
|
||||||
*
|
|
||||||
* @return the compositon Type
|
|
||||||
*/
|
|
||||||
int getCompositionType();
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Clear region implementation for C2D/MDP versions.
|
* 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
|
* @return: external display to be enabled
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
external_display handleEventHDMI(external_display newEvent, external_display
|
external_display_type handleEventHDMI(external_display_type disp, int value,
|
||||||
currEvent);
|
external_display_type currDispType);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Checks if layers need to be dumped based on system property "debug.sf.dump"
|
* 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.
|
* for raw dumps and "debug.sf.dump.png" for png dumps.
|
||||||
@@ -391,4 +329,8 @@ bool needToDumpLayers();
|
|||||||
void dumpLayer(int moduleCompositionType, int listFlags, size_t layerIndex,
|
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
|
#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) 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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with 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) {
|
if (!left && !right && !top && !bottom) {
|
||||||
//can't do tile rendering
|
//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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2010 The Android Open Source Project
|
* 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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|||||||
Reference in New Issue
Block a user