display: Move HALs to new location
Change-Id: Ib1d843b4cfd71f5bbb0e5184277cbe7497180f8e
This commit is contained in:
commit
cbb0b78679
1
Android.mk
Normal file
1
Android.mk
Normal file
@ -0,0 +1 @@
|
||||
# Empty Android.mk
|
73
libcopybit/Android.mk
Normal file
73
libcopybit/Android.mk
Normal file
@ -0,0 +1,73 @@
|
||||
# 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
|
||||
LOCAL_SRC_FILES := copybit_c2d.cpp
|
||||
LOCAL_MODULE := copybit.$(TARGET_BOARD_PLATFORM)
|
||||
LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
|
||||
LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
|
||||
LOCAL_C_INCLUDES += hardware/msm7k/libgralloc-qsd8k
|
||||
LOCAL_CFLAGS += -DCOPYBIT_Z180=1 -DC2D_SUPPORT_DISPLAY=1
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
else
|
||||
ifneq "$(findstring msm7630,$(TARGET_PRODUCT))" "msm7630"
|
||||
ifeq ($(TARGET_BOARD_PLATFORM),msm7k)
|
||||
include $(CLEAR_VARS)
|
||||
ifeq ($(TARGET_GRALLOC_USES_ASHMEM),true)
|
||||
LOCAL_CFLAGS += -DUSE_ASHMEM
|
||||
ifeq "$(findstring msm7627,$(TARGET_PRODUCT))" "msm7627"
|
||||
LOCAL_CFLAGS += -DTARGET_7x27
|
||||
endif
|
||||
endif
|
||||
|
||||
LOCAL_PRELINK_MODULE := false
|
||||
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
|
||||
LOCAL_SHARED_LIBRARIES := liblog
|
||||
LOCAL_SRC_FILES := copybit.cpp
|
||||
LOCAL_MODULE := copybit.msm7k
|
||||
LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
|
||||
LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
|
||||
LOCAL_C_INCLUDES += hardware/msm7k/libgralloc-qsd8k
|
||||
LOCAL_CFLAGS += -DCOPYBIT_MSM7K=1
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
endif
|
||||
|
||||
ifeq ($(TARGET_BOARD_PLATFORM),qsd8k)
|
||||
include $(CLEAR_VARS)
|
||||
ifeq ($(TARGET_GRALLOC_USES_ASHMEM),true)
|
||||
LOCAL_CFLAGS += -DUSE_ASHMEM
|
||||
endif
|
||||
|
||||
LOCAL_PRELINK_MODULE := false
|
||||
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
|
||||
LOCAL_SHARED_LIBRARIES := liblog
|
||||
LOCAL_SRC_FILES := copybit.cpp
|
||||
LOCAL_MODULE := copybit.qsd8k
|
||||
LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
|
||||
LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
|
||||
LOCAL_C_INCLUDES += hardware/msm7k/libgralloc-qsd8k
|
||||
LOCAL_CFLAGS += -DCOPYBIT_QSD8K=1
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
endif
|
||||
endif
|
||||
endif
|
0
libcopybit/MODULE_LICENSE_APACHE2
Normal file
0
libcopybit/MODULE_LICENSE_APACHE2
Normal file
190
libcopybit/NOTICE
Normal file
190
libcopybit/NOTICE
Normal file
@ -0,0 +1,190 @@
|
||||
|
||||
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, 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
|
||||
|
||||
#include <EGL/egl.h> /* for EGL surfaces */
|
||||
|
||||
#ifndef C2D_API
|
||||
#define C2D_API /* define API export as needed */
|
||||
#endif
|
||||
#ifndef int32
|
||||
typedef int int32;
|
||||
#endif
|
||||
#ifndef uint32
|
||||
typedef unsigned int uint32;
|
||||
#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 COMP_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_EGL = 0, /* Arbitrary EGL surface */
|
||||
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 allready mapped */
|
||||
/* this bit is valid with HOST types */
|
||||
} C2D_SURFACE_TYPE;
|
||||
|
||||
/* Structure for registering an EGL surface as a blit surface */
|
||||
typedef struct {
|
||||
EGLDisplay display; /* EGL display */
|
||||
EGLContext context; /* EGL context, reserved - pass EGL_NO_CONTEXT */
|
||||
EGLSurface surface; /* EGL surface */
|
||||
} C2D_EGL_SURFACE_DEF;
|
||||
|
||||
/* 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.
|
||||
|
||||
* arbitrary EGL surface (including proprietary Command List Surface):
|
||||
* surface_type = C2D_SURFACE_EGL
|
||||
* surface_definition = C2D_EGL_SURFACE_DEF
|
||||
* all fields in definition structure should be set
|
||||
* context field is reserved and can be ignored
|
||||
|
||||
* 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);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __c2d2_h_ */
|
498
libcopybit/copybit.cpp
Normal file
498
libcopybit/copybit.cpp
Normal file
@ -0,0 +1,498 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
#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 <hardware/copybit.h>
|
||||
|
||||
#include "gralloc_priv.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;
|
||||
uint8_t 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;
|
||||
}
|
||||
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;
|
||||
img->width = rhs->w;
|
||||
img->height = rhs->h;
|
||||
img->format = get_format(rhs->format);
|
||||
img->offset = hnd->offset;
|
||||
#if defined(COPYBIT_MSM7K)
|
||||
#if defined(USE_ASHMEM) && (TARGET_7x27)
|
||||
img->memory_id = hnd->fd;
|
||||
#else //USE_ASHMEM not defined
|
||||
img->memory_id = hnd->fd;
|
||||
#endif //end USE_ASHMEM
|
||||
#else
|
||||
img->memory_id = hnd->fd;
|
||||
#endif
|
||||
}
|
||||
/** 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;
|
||||
if (dev->mFlags & COPYBIT_TRANSFORM_ROT_90) {
|
||||
e->src_rect.x = (clip.t - dst->t) + src->t;
|
||||
e->src_rect.y = (dst->r - clip.r) + src->l;
|
||||
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 {
|
||||
e->src_rect.x = (clip.l - dst->l) + src->l;
|
||||
e->src_rect.y = (clip.t - dst->t) + src->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(&e->src_rect.x, &e->src_rect.w, src->r - src->l, W);
|
||||
MULDIV(&e->src_rect.y, &e->src_rect.h, src->b - src->t, H);
|
||||
|
||||
if (dev->mFlags & COPYBIT_TRANSFORM_FLIP_V) {
|
||||
if (dev->mFlags & COPYBIT_TRANSFORM_ROT_90) {
|
||||
e->src_rect.x = e->src.width - (e->src_rect.x + e->src_rect.w) - horiz_padding;
|
||||
}else{
|
||||
e->src_rect.y = e->src.height - (e->src_rect.y + e->src_rect.h) - vert_padding;
|
||||
}
|
||||
}
|
||||
|
||||
if (dev->mFlags & COPYBIT_TRANSFORM_FLIP_H) {
|
||||
if (dev->mFlags & COPYBIT_TRANSFORM_ROT_90) {
|
||||
e->src_rect.y = e->src.height - (e->src_rect.y + e->src_rect.h) - vert_padding;
|
||||
}else{
|
||||
e->src_rect.x = e->src.width - (e->src_rect.x + e->src_rect.w) - horiz_padding;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** 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);
|
||||
LOGE_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++) {
|
||||
LOGD("%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:
|
||||
LOGE("Invalid value for COPYBIT_ROTATION_DEG");
|
||||
status = -EINVAL;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case COPYBIT_PLANE_ALPHA:
|
||||
if (value < 0) value = 0;
|
||||
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_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;
|
||||
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:
|
||||
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
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (src->w > MAX_DIMENSION || src->h > MAX_DIMENSION)
|
||||
return -EINVAL;
|
||||
|
||||
if (dst->w > MAX_DIMENSION || dst->h > MAX_DIMENSION)
|
||||
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;
|
||||
|
||||
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 {
|
||||
status = -EINVAL;
|
||||
}
|
||||
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;
|
||||
LOGE("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 {
|
||||
LOGE("Error not msm frame buffer");
|
||||
status = -EINVAL;
|
||||
}
|
||||
} else {
|
||||
LOGE("Error executing ioctl for screen info");
|
||||
status = -errno;
|
||||
}
|
||||
}
|
||||
|
||||
if (status == 0) {
|
||||
*device = &ctx->device.common;
|
||||
} else {
|
||||
close_copybit(&ctx->device.common);
|
||||
}
|
||||
return status;
|
||||
}
|
1036
libcopybit/copybit_c2d.cpp
Normal file
1036
libcopybit/copybit_c2d.cpp
Normal file
File diff suppressed because it is too large
Load Diff
66
libgralloc-qsd8k/Android.mk
Normal file
66
libgralloc-qsd8k/Android.mk
Normal file
@ -0,0 +1,66 @@
|
||||
# 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.
|
||||
ifneq ($(TARGET_USES_ION),true)
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
# HAL module implemenation, not prelinked and stored in
|
||||
# hw/<OVERLAY_HARDWARE_MODULE_ID>.<ro.product.board>.so
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_PRELINK_MODULE := false
|
||||
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
|
||||
LOCAL_SHARED_LIBRARIES := liblog libcutils libGLESv1_CM libutils
|
||||
|
||||
LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include \
|
||||
hardware/qcom/display/libgralloc
|
||||
LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
|
||||
LOCAL_SRC_FILES := \
|
||||
allocator.cpp \
|
||||
framebuffer.cpp \
|
||||
gpu.cpp \
|
||||
gralloc.cpp \
|
||||
mapper.cpp \
|
||||
pmemalloc.cpp
|
||||
|
||||
LOCAL_MODULE := gralloc.$(TARGET_BOARD_PLATFORM)
|
||||
LOCAL_CFLAGS:= -DLOG_TAG=\"$(TARGET_BOARD_PLATFORM).gralloc\" -DHOST -DDEBUG_CALC_FPS
|
||||
|
||||
ifneq (, $(filter msm7625_ffa msm7625_surf msm7627_ffa msm7627_surf msm7627_7x_ffa msm7627_7x_surf, $(QCOM_TARGET_PRODUCT)))
|
||||
LOCAL_CFLAGS += -DTARGET_MSM7x27
|
||||
endif
|
||||
|
||||
ifeq ($(TARGET_HAVE_HDMI_OUT),true)
|
||||
LOCAL_CFLAGS += -DHDMI_DUAL_DISPLAY
|
||||
LOCAL_C_INCLUDES += $(LOCAL_PATH)/../liboverlay
|
||||
LOCAL_SHARED_LIBRARIES += liboverlay
|
||||
endif
|
||||
|
||||
ifeq ($(TARGET_GRALLOC_USES_ASHMEM),true)
|
||||
LOCAL_CFLAGS += -DUSE_ASHMEM
|
||||
endif
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
||||
|
||||
# Build a host library for testing
|
||||
ifeq ($(HOST_OS),linux)
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_SRC_FILES := \
|
||||
gpu.cpp \
|
||||
pmemalloc.cpp
|
||||
|
||||
LOCAL_MODULE_TAGS := tests
|
||||
LOCAL_MODULE := libgralloc_qsd8k_host
|
||||
LOCAL_CFLAGS:= -DLOG_TAG=\"gralloc-qsd8k\"
|
||||
include $(BUILD_HOST_STATIC_LIBRARY)
|
||||
endif
|
||||
endif
|
0
libgralloc-qsd8k/MODULE_LICENSE_APACHE2
Normal file
0
libgralloc-qsd8k/MODULE_LICENSE_APACHE2
Normal file
190
libgralloc-qsd8k/NOTICE
Normal file
190
libgralloc-qsd8k/NOTICE
Normal file
@ -0,0 +1,190 @@
|
||||
|
||||
Copyright (c) 2008-2009, 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
|
||||
|
165
libgralloc-qsd8k/allocator.cpp
Normal file
165
libgralloc-qsd8k/allocator.cpp
Normal file
@ -0,0 +1,165 @@
|
||||
/*
|
||||
* Copyright (C) 2009 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <cutils/log.h>
|
||||
|
||||
#include "allocator.h"
|
||||
|
||||
|
||||
// align all the memory blocks on a cache-line boundary
|
||||
const int SimpleBestFitAllocator::kMemoryAlign = 32;
|
||||
|
||||
SimpleBestFitAllocator::SimpleBestFitAllocator()
|
||||
: mHeapSize(0)
|
||||
{
|
||||
}
|
||||
|
||||
SimpleBestFitAllocator::SimpleBestFitAllocator(size_t size)
|
||||
: mHeapSize(0)
|
||||
{
|
||||
setSize(size);
|
||||
}
|
||||
|
||||
SimpleBestFitAllocator::~SimpleBestFitAllocator()
|
||||
{
|
||||
while(!mList.isEmpty()) {
|
||||
delete mList.remove(mList.head());
|
||||
}
|
||||
}
|
||||
|
||||
ssize_t SimpleBestFitAllocator::setSize(size_t size)
|
||||
{
|
||||
Locker::Autolock _l(mLock);
|
||||
if (mHeapSize != 0) return -EINVAL;
|
||||
size_t pagesize = getpagesize();
|
||||
mHeapSize = ((size + pagesize-1) & ~(pagesize-1));
|
||||
chunk_t* node = new chunk_t(0, mHeapSize / kMemoryAlign);
|
||||
mList.insertHead(node);
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
size_t SimpleBestFitAllocator::size() const
|
||||
{
|
||||
return mHeapSize;
|
||||
}
|
||||
|
||||
ssize_t SimpleBestFitAllocator::allocate(size_t size, uint32_t flags)
|
||||
{
|
||||
Locker::Autolock _l(mLock);
|
||||
if (mHeapSize == 0) return -EINVAL;
|
||||
ssize_t offset = alloc(size, flags);
|
||||
return offset;
|
||||
}
|
||||
|
||||
ssize_t SimpleBestFitAllocator::deallocate(size_t offset)
|
||||
{
|
||||
Locker::Autolock _l(mLock);
|
||||
if (mHeapSize == 0) return -EINVAL;
|
||||
chunk_t const * const freed = dealloc(offset);
|
||||
if (freed) {
|
||||
return 0;
|
||||
}
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
ssize_t SimpleBestFitAllocator::alloc(size_t size, uint32_t flags)
|
||||
{
|
||||
if (size == 0) {
|
||||
return 0;
|
||||
}
|
||||
size = (size + kMemoryAlign-1) / kMemoryAlign;
|
||||
chunk_t* free_chunk = 0;
|
||||
chunk_t* cur = mList.head();
|
||||
|
||||
size_t pagesize = getpagesize();
|
||||
while (cur) {
|
||||
int extra = ( -cur->start & ((pagesize/kMemoryAlign)-1) ) ;
|
||||
|
||||
// best fit
|
||||
if (cur->free && (cur->size >= (size+extra))) {
|
||||
if ((!free_chunk) || (cur->size < free_chunk->size)) {
|
||||
free_chunk = cur;
|
||||
}
|
||||
if (cur->size == size) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
cur = cur->next;
|
||||
}
|
||||
|
||||
if (free_chunk) {
|
||||
const size_t free_size = free_chunk->size;
|
||||
free_chunk->free = 0;
|
||||
free_chunk->size = size;
|
||||
if (free_size > size) {
|
||||
int extra = ( -free_chunk->start & ((pagesize/kMemoryAlign)-1) ) ;
|
||||
if (extra) {
|
||||
chunk_t* split = new chunk_t(free_chunk->start, extra);
|
||||
free_chunk->start += extra;
|
||||
mList.insertBefore(free_chunk, split);
|
||||
}
|
||||
|
||||
LOGE_IF(((free_chunk->start*kMemoryAlign)&(pagesize-1)),
|
||||
"page is not aligned!!!");
|
||||
|
||||
const ssize_t tail_free = free_size - (size+extra);
|
||||
if (tail_free > 0) {
|
||||
chunk_t* split = new chunk_t(
|
||||
free_chunk->start + free_chunk->size, tail_free);
|
||||
mList.insertAfter(free_chunk, split);
|
||||
}
|
||||
}
|
||||
return (free_chunk->start)*kMemoryAlign;
|
||||
}
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
SimpleBestFitAllocator::chunk_t* SimpleBestFitAllocator::dealloc(size_t start)
|
||||
{
|
||||
start = start / kMemoryAlign;
|
||||
chunk_t* cur = mList.head();
|
||||
while (cur) {
|
||||
if (cur->start == start) {
|
||||
LOG_FATAL_IF(cur->free,
|
||||
"block at offset 0x%08lX of size 0x%08lX already freed",
|
||||
cur->start*kMemoryAlign, cur->size*kMemoryAlign);
|
||||
|
||||
// merge freed blocks together
|
||||
chunk_t* freed = cur;
|
||||
cur->free = 1;
|
||||
do {
|
||||
chunk_t* const p = cur->prev;
|
||||
chunk_t* const n = cur->next;
|
||||
if (p && (p->free || !cur->size)) {
|
||||
freed = p;
|
||||
p->size += cur->size;
|
||||
mList.remove(cur);
|
||||
delete cur;
|
||||
}
|
||||
cur = n;
|
||||
} while (cur && cur->free);
|
||||
|
||||
LOG_FATAL_IF(!freed->free,
|
||||
"freed block at offset 0x%08lX of size 0x%08lX is not free!",
|
||||
freed->start * kMemoryAlign, freed->size * kMemoryAlign);
|
||||
|
||||
return freed;
|
||||
}
|
||||
cur = cur->next;
|
||||
}
|
||||
return 0;
|
||||
}
|
130
libgralloc-qsd8k/allocator.h
Normal file
130
libgralloc-qsd8k/allocator.h
Normal file
@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright (C) 2009 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 GRALLOC_ALLOCATOR_H_
|
||||
#define GRALLOC_ALLOCATOR_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "gr.h"
|
||||
#include "pmemalloc.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* A simple templatized doubly linked-list implementation
|
||||
*/
|
||||
|
||||
template <typename NODE>
|
||||
class LinkedList
|
||||
{
|
||||
NODE* mFirst;
|
||||
NODE* mLast;
|
||||
|
||||
public:
|
||||
LinkedList() : mFirst(0), mLast(0) { }
|
||||
bool isEmpty() const { return mFirst == 0; }
|
||||
NODE const* head() const { return mFirst; }
|
||||
NODE* head() { return mFirst; }
|
||||
NODE const* tail() const { return mLast; }
|
||||
NODE* tail() { return mLast; }
|
||||
|
||||
void insertAfter(NODE* node, NODE* newNode) {
|
||||
newNode->prev = node;
|
||||
newNode->next = node->next;
|
||||
if (node->next == 0) mLast = newNode;
|
||||
else node->next->prev = newNode;
|
||||
node->next = newNode;
|
||||
}
|
||||
|
||||
void insertBefore(NODE* node, NODE* newNode) {
|
||||
newNode->prev = node->prev;
|
||||
newNode->next = node;
|
||||
if (node->prev == 0) mFirst = newNode;
|
||||
else node->prev->next = newNode;
|
||||
node->prev = newNode;
|
||||
}
|
||||
|
||||
void insertHead(NODE* newNode) {
|
||||
if (mFirst == 0) {
|
||||
mFirst = mLast = newNode;
|
||||
newNode->prev = newNode->next = 0;
|
||||
} else {
|
||||
newNode->prev = 0;
|
||||
newNode->next = mFirst;
|
||||
mFirst->prev = newNode;
|
||||
mFirst = newNode;
|
||||
}
|
||||
}
|
||||
|
||||
void insertTail(NODE* newNode) {
|
||||
if (mLast == 0) {
|
||||
insertHead(newNode);
|
||||
} else {
|
||||
newNode->prev = mLast;
|
||||
newNode->next = 0;
|
||||
mLast->next = newNode;
|
||||
mLast = newNode;
|
||||
}
|
||||
}
|
||||
|
||||
NODE* remove(NODE* node) {
|
||||
if (node->prev == 0) mFirst = node->next;
|
||||
else node->prev->next = node->next;
|
||||
if (node->next == 0) mLast = node->prev;
|
||||
else node->next->prev = node->prev;
|
||||
return node;
|
||||
}
|
||||
};
|
||||
|
||||
class SimpleBestFitAllocator : public PmemUserspaceAllocator::Deps::Allocator
|
||||
{
|
||||
public:
|
||||
|
||||
SimpleBestFitAllocator();
|
||||
SimpleBestFitAllocator(size_t size);
|
||||
virtual ~SimpleBestFitAllocator();
|
||||
|
||||
virtual ssize_t setSize(size_t size);
|
||||
|
||||
virtual ssize_t allocate(size_t size, uint32_t flags = 0);
|
||||
virtual ssize_t deallocate(size_t offset);
|
||||
virtual size_t size() const;
|
||||
|
||||
private:
|
||||
struct chunk_t {
|
||||
chunk_t(size_t start, size_t size)
|
||||
: start(start), size(size), free(1), prev(0), next(0) {
|
||||
}
|
||||
size_t start;
|
||||
size_t size : 28;
|
||||
int free : 4;
|
||||
mutable chunk_t* prev;
|
||||
mutable chunk_t* next;
|
||||
};
|
||||
|
||||
ssize_t alloc(size_t size, uint32_t flags);
|
||||
chunk_t* dealloc(size_t start);
|
||||
|
||||
static const int kMemoryAlign;
|
||||
mutable Locker mLock;
|
||||
LinkedList<chunk_t> mList;
|
||||
size_t mHeapSize;
|
||||
};
|
||||
|
||||
#endif /* GRALLOC_ALLOCATOR_H_ */
|
1130
libgralloc-qsd8k/framebuffer.cpp
Normal file
1130
libgralloc-qsd8k/framebuffer.cpp
Normal file
File diff suppressed because it is too large
Load Diff
505
libgralloc-qsd8k/gpu.cpp
Executable file
505
libgralloc-qsd8k/gpu.cpp
Executable file
@ -0,0 +1,505 @@
|
||||
/*
|
||||
* Copyright (C) 2010 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include <cutils/properties.h>
|
||||
#ifdef HOST
|
||||
#include <linux/ashmem.h>
|
||||
#endif
|
||||
|
||||
#include "gr.h"
|
||||
#include "gpu.h"
|
||||
|
||||
static const int OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00;
|
||||
static const int QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka = 0x7FA30C03;
|
||||
static const int QOMX_INTERLACE_FLAG = 0x49283654;
|
||||
static const int QOMX_3D_VIDEO_FLAG = 0x23784238;
|
||||
|
||||
gpu_context_t::gpu_context_t(Deps& deps, PmemAllocator& pmemAllocator,
|
||||
PmemAllocator& pmemAdspAllocator, const private_module_t* module) :
|
||||
deps(deps),
|
||||
pmemAllocator(pmemAllocator),
|
||||
pmemAdspAllocator(pmemAdspAllocator)
|
||||
{
|
||||
// Zero out the alloc_device_t
|
||||
memset(static_cast<alloc_device_t*>(this), 0, sizeof(alloc_device_t));
|
||||
|
||||
char property[PROPERTY_VALUE_MAX];
|
||||
if (property_get("debug.sf.hw", property, NULL) > 0) {
|
||||
if(atoi(property) == 0) {
|
||||
//debug.sf.hw = 0
|
||||
compositionType = CPU_COMPOSITION;
|
||||
} else { //debug.sf.hw = 1
|
||||
// Get the composition type
|
||||
property_get("debug.composition.type", property, NULL);
|
||||
if (property == NULL) {
|
||||
compositionType = GPU_COMPOSITION;
|
||||
} else if ((strncmp(property, "mdp", 3)) == 0) {
|
||||
compositionType = MDP_COMPOSITION;
|
||||
} else if ((strncmp(property, "c2d", 3)) == 0) {
|
||||
compositionType = C2D_COMPOSITION;
|
||||
} else {
|
||||
compositionType = GPU_COMPOSITION;
|
||||
}
|
||||
}
|
||||
} else { //debug.sf.hw is not set. Use cpu composition
|
||||
compositionType = CPU_COMPOSITION;
|
||||
}
|
||||
|
||||
// Initialize the procs
|
||||
common.tag = HARDWARE_DEVICE_TAG;
|
||||
common.version = 0;
|
||||
common.module = const_cast<hw_module_t*>(&module->base.common);
|
||||
common.close = gralloc_close;
|
||||
alloc = gralloc_alloc;
|
||||
allocSize = gralloc_alloc_size;
|
||||
free = gralloc_free;
|
||||
}
|
||||
|
||||
int gpu_context_t::gralloc_alloc_framebuffer_locked(size_t size, int usage,
|
||||
buffer_handle_t* pHandle)
|
||||
{
|
||||
private_module_t* m = reinterpret_cast<private_module_t*>(common.module);
|
||||
|
||||
// we don't support allocations with both the FB and PMEM_ADSP flags
|
||||
if (usage & GRALLOC_USAGE_PRIVATE_ADSP_HEAP) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
// allocate the framebuffer
|
||||
if (m->framebuffer == NULL) {
|
||||
// initialize the framebuffer, the framebuffer is mapped once
|
||||
// and forever.
|
||||
int err = deps.mapFrameBufferLocked(m);
|
||||
if (err < 0) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
const uint32_t bufferMask = m->bufferMask;
|
||||
const uint32_t numBuffers = m->numBuffers;
|
||||
const size_t bufferSize = m->finfo.line_length * m->info.yres;
|
||||
if (numBuffers == 1) {
|
||||
// If we have only one buffer, we never use page-flipping. Instead,
|
||||
// we return a regular buffer which will be memcpy'ed to the main
|
||||
// screen when post is called.
|
||||
int newUsage = (usage & ~GRALLOC_USAGE_HW_FB) | GRALLOC_USAGE_HW_2D;
|
||||
return gralloc_alloc_buffer(bufferSize, newUsage, pHandle, BUFFER_TYPE_UI, m->fbFormat, m->info.xres, m->info.yres);
|
||||
}
|
||||
|
||||
if (bufferMask >= ((1LU<<numBuffers)-1)) {
|
||||
// We ran out of buffers.
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
// create a "fake" handles for it
|
||||
intptr_t vaddr = intptr_t(m->framebuffer->base);
|
||||
private_handle_t* hnd = new private_handle_t(dup(m->framebuffer->fd), bufferSize,
|
||||
private_handle_t::PRIV_FLAGS_USES_PMEM |
|
||||
private_handle_t::PRIV_FLAGS_FRAMEBUFFER,
|
||||
BUFFER_TYPE_UI, m->fbFormat, m->info.xres, m->info.yres);
|
||||
|
||||
// find a free slot
|
||||
for (uint32_t i=0 ; i<numBuffers ; i++) {
|
||||
if ((bufferMask & (1LU<<i)) == 0) {
|
||||
m->bufferMask |= (1LU<<i);
|
||||
break;
|
||||
}
|
||||
vaddr += bufferSize;
|
||||
}
|
||||
|
||||
hnd->base = vaddr;
|
||||
hnd->offset = vaddr - intptr_t(m->framebuffer->base);
|
||||
*pHandle = hnd;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int gpu_context_t::gralloc_alloc_framebuffer(size_t size, int usage,
|
||||
buffer_handle_t* pHandle)
|
||||
{
|
||||
private_module_t* m = reinterpret_cast<private_module_t*>(common.module);
|
||||
pthread_mutex_lock(&m->lock);
|
||||
int err = gralloc_alloc_framebuffer_locked(size, usage, pHandle);
|
||||
pthread_mutex_unlock(&m->lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
int gpu_context_t::alloc_ashmem_buffer(size_t size, unsigned int postfix, void** pBase,
|
||||
int* pOffset, int* pFd)
|
||||
{
|
||||
int err = 0;
|
||||
int fd = -1;
|
||||
void* base = 0;
|
||||
int offset = 0;
|
||||
|
||||
char name[ASHMEM_NAME_LEN];
|
||||
snprintf(name, ASHMEM_NAME_LEN, "gralloc-buffer-%x", postfix);
|
||||
int prot = PROT_READ | PROT_WRITE;
|
||||
fd = ashmem_create_region(name, size);
|
||||
if (fd < 0) {
|
||||
LOGE("couldn't create ashmem (%s)", strerror(errno));
|
||||
err = -errno;
|
||||
} else {
|
||||
if (ashmem_set_prot_region(fd, prot) < 0) {
|
||||
LOGE("ashmem_set_prot_region(fd=%d, prot=%x) failed (%s)",
|
||||
fd, prot, strerror(errno));
|
||||
close(fd);
|
||||
err = -errno;
|
||||
} else {
|
||||
base = mmap(0, size, prot, MAP_SHARED|MAP_POPULATE|MAP_LOCKED, fd, 0);
|
||||
if (base == MAP_FAILED) {
|
||||
LOGE("alloc mmap(fd=%d, size=%d, prot=%x) failed (%s)",
|
||||
fd, size, prot, strerror(errno));
|
||||
close(fd);
|
||||
err = -errno;
|
||||
} else {
|
||||
memset((char*)base + offset, 0, size);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(err == 0) {
|
||||
*pFd = fd;
|
||||
*pBase = base;
|
||||
*pOffset = offset;
|
||||
#ifdef HOST
|
||||
if (ioctl(fd, ASHMEM_CACHE_INV_RANGE, NULL)) {
|
||||
LOGE("ASHMEM_CACHE_INV_RANGE failed fd = %d", fd);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int gpu_context_t::gralloc_alloc_buffer(size_t size, int usage, buffer_handle_t* pHandle,
|
||||
int bufferType, int format, int width, int height)
|
||||
{
|
||||
int err = 0;
|
||||
int flags = 0;
|
||||
|
||||
int fd = -1;
|
||||
void* base = 0; // XXX JMG: This should change to just get an address from
|
||||
// the PmemAllocator rather than getting the base & offset separately
|
||||
int offset = 0;
|
||||
int lockState = 0;
|
||||
|
||||
size = roundUpToPageSize(size);
|
||||
#ifndef USE_ASHMEM
|
||||
if (usage & GRALLOC_USAGE_HW_TEXTURE) {
|
||||
// enable pmem in that case, so our software GL can fallback to
|
||||
// the copybit module.
|
||||
flags |= private_handle_t::PRIV_FLAGS_USES_PMEM;
|
||||
}
|
||||
|
||||
if (usage & GRALLOC_USAGE_HW_2D) {
|
||||
flags |= private_handle_t::PRIV_FLAGS_USES_PMEM;
|
||||
}
|
||||
#else
|
||||
// Enable use of PMEM only when MDP composition is used (and other conditions apply).
|
||||
// Else fall back on using ASHMEM
|
||||
if ((get_composition_type() == MDP_COMPOSITION) &&
|
||||
((usage & GRALLOC_USAGE_HW_TEXTURE) || (usage & GRALLOC_USAGE_HW_2D)) ) {
|
||||
flags |= private_handle_t::PRIV_FLAGS_USES_PMEM;
|
||||
}
|
||||
|
||||
if (usage & GRALLOC_USAGE_PRIVATE_EBI_HEAP) {
|
||||
flags |= private_handle_t::PRIV_FLAGS_USES_PMEM;
|
||||
}
|
||||
#endif
|
||||
if ((usage & GRALLOC_USAGE_PRIVATE_ADSP_HEAP) || (usage & GRALLOC_USAGE_PRIVATE_SMI_HEAP)
|
||||
|| (usage & GRALLOC_USAGE_EXTERNAL_DISP) || (usage & GRALLOC_USAGE_PROTECTED)) {
|
||||
flags |= private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP;
|
||||
flags &= ~private_handle_t::PRIV_FLAGS_USES_PMEM;
|
||||
}
|
||||
|
||||
private_module_t* m = reinterpret_cast<private_module_t*>(common.module);
|
||||
if((flags & private_handle_t::PRIV_FLAGS_USES_PMEM) == 0 &&
|
||||
(flags & private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP) == 0) {
|
||||
flags |= private_handle_t::PRIV_FLAGS_USES_ASHMEM;
|
||||
err = alloc_ashmem_buffer(size, (unsigned int)pHandle, &base, &offset, &fd);
|
||||
if(err >= 0)
|
||||
lockState |= private_handle_t::LOCK_STATE_MAPPED;
|
||||
}
|
||||
else if ((flags & private_handle_t::PRIV_FLAGS_USES_PMEM) != 0 ||
|
||||
(flags & private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP) != 0) {
|
||||
|
||||
PmemAllocator* pma = 0;
|
||||
|
||||
if ((flags & private_handle_t::PRIV_FLAGS_USES_PMEM) != 0) {
|
||||
if ((flags & private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP) != 0) {
|
||||
LOGE("attempting to allocate a gralloc buffer with both the "
|
||||
"USES_PMEM and USES_PMEM_ADSP flags. Unsetting the "
|
||||
"USES_PMEM_ADSP flag.");
|
||||
flags &= ~private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP;
|
||||
}
|
||||
pma = &pmemAllocator;
|
||||
} else { // (flags & private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP) != 0
|
||||
pma = &pmemAdspAllocator;
|
||||
}
|
||||
|
||||
// PMEM buffers are always mmapped
|
||||
lockState |= private_handle_t::LOCK_STATE_MAPPED;
|
||||
|
||||
err = pma->alloc_pmem_buffer(size, usage, &base, &offset, &fd, format);
|
||||
if (err < 0) {
|
||||
// Pmem allocation failed. Try falling back to ashmem iff we are:
|
||||
// a. not using MDP composition
|
||||
// b. not allocating memory for a buffer to be used by overlays
|
||||
// c. The client has not explicitly requested a PMEM buffer
|
||||
if ((get_composition_type() != MDP_COMPOSITION) &&
|
||||
(bufferType != BUFFER_TYPE_VIDEO) &&
|
||||
((usage & GRALLOC_USAGE_PRIVATE_EBI_HEAP) == 0) &&
|
||||
((usage & GRALLOC_USAGE_PRIVATE_ADSP_HEAP) == 0)) {
|
||||
// the caller didn't request PMEM, so we can try something else
|
||||
flags &= ~private_handle_t::PRIV_FLAGS_USES_PMEM;
|
||||
err = 0;
|
||||
LOGE("Pmem allocation failed. Trying ashmem");
|
||||
goto try_ashmem;
|
||||
} else {
|
||||
LOGE("couldn't open pmem (%s)", strerror(errno));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
try_ashmem:
|
||||
err = alloc_ashmem_buffer(size, (unsigned int)pHandle, &base, &offset, &fd);
|
||||
if (err >= 0) {
|
||||
lockState |= private_handle_t::LOCK_STATE_MAPPED;
|
||||
flags |= private_handle_t::PRIV_FLAGS_USES_ASHMEM;
|
||||
} else {
|
||||
LOGE("Ashmem fallback failed");
|
||||
}
|
||||
}
|
||||
|
||||
if (err == 0) {
|
||||
private_handle_t* hnd = new private_handle_t(fd, size, flags, bufferType, format, width, height);
|
||||
hnd->offset = offset;
|
||||
hnd->base = int(base)+offset;
|
||||
hnd->lockState = lockState;
|
||||
*pHandle = hnd;
|
||||
}
|
||||
|
||||
LOGE_IF(err, "gralloc failed err=%s", strerror(-err));
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static inline size_t ALIGN(size_t x, size_t align) {
|
||||
return (x + align-1) & ~(align-1);
|
||||
}
|
||||
|
||||
void gpu_context_t::getGrallocInformationFromFormat(int inputFormat, int *colorFormat, int *bufferType)
|
||||
{
|
||||
*bufferType = BUFFER_TYPE_VIDEO;
|
||||
*colorFormat = inputFormat;
|
||||
|
||||
if (inputFormat == HAL_PIXEL_FORMAT_YV12) {
|
||||
*bufferType = BUFFER_TYPE_VIDEO;
|
||||
} else if (inputFormat & S3D_FORMAT_MASK) {
|
||||
// S3D format
|
||||
*colorFormat = COLOR_FORMAT(inputFormat);
|
||||
} else if (inputFormat & INTERLACE_MASK) {
|
||||
// Interlaced
|
||||
*colorFormat = inputFormat ^ HAL_PIXEL_FORMAT_INTERLACE;
|
||||
} else if (inputFormat < 0x7) {
|
||||
// RGB formats
|
||||
*colorFormat = inputFormat;
|
||||
*bufferType = BUFFER_TYPE_UI;
|
||||
} else if ((inputFormat == HAL_PIXEL_FORMAT_R_8) ||
|
||||
(inputFormat == HAL_PIXEL_FORMAT_RG_88)) {
|
||||
*colorFormat = inputFormat;
|
||||
*bufferType = BUFFER_TYPE_UI;
|
||||
}
|
||||
}
|
||||
|
||||
int gpu_context_t::alloc_impl(int w, int h, int format, int usage,
|
||||
buffer_handle_t* pHandle, int* pStride, int bufferSize) {
|
||||
if (!pHandle || !pStride)
|
||||
return -EINVAL;
|
||||
|
||||
size_t size, alignedw, alignedh;
|
||||
|
||||
alignedw = ALIGN(w, 32);
|
||||
alignedh = ALIGN(h, 32);
|
||||
int colorFormat, bufferType;
|
||||
getGrallocInformationFromFormat(format, &colorFormat, &bufferType);
|
||||
|
||||
switch (colorFormat) {
|
||||
case HAL_PIXEL_FORMAT_RGBA_8888:
|
||||
case HAL_PIXEL_FORMAT_RGBX_8888:
|
||||
case HAL_PIXEL_FORMAT_BGRA_8888:
|
||||
size = alignedw * alignedh * 4;
|
||||
break;
|
||||
case HAL_PIXEL_FORMAT_RGB_888:
|
||||
size = alignedw * alignedh * 3;
|
||||
break;
|
||||
case HAL_PIXEL_FORMAT_RGB_565:
|
||||
case HAL_PIXEL_FORMAT_RGBA_5551:
|
||||
case HAL_PIXEL_FORMAT_RGBA_4444:
|
||||
size = alignedw * alignedh * 2;
|
||||
break;
|
||||
|
||||
// adreno formats
|
||||
case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO: // NV21
|
||||
size = ALIGN(alignedw*alignedh, 4096);
|
||||
size += ALIGN(2 * ALIGN(w/2, 32) * ALIGN(h/2, 32), 4096);
|
||||
break;
|
||||
case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: // NV12
|
||||
// The chroma plane is subsampled,
|
||||
// but the pitch in bytes is unchanged
|
||||
// The GPU needs 4K alignment, but the video decoder needs 8K
|
||||
alignedw = ALIGN(w, 128);
|
||||
size = ALIGN( alignedw * alignedh, 8192);
|
||||
size += ALIGN( alignedw * ALIGN(h/2, 32), 8192);
|
||||
break;
|
||||
case HAL_PIXEL_FORMAT_YCbCr_420_SP:
|
||||
case HAL_PIXEL_FORMAT_YCrCb_420_SP:
|
||||
case HAL_PIXEL_FORMAT_YV12:
|
||||
if ((w&1) || (h&1)) {
|
||||
LOGE("w or h is odd for the YUV format");
|
||||
return -EINVAL;
|
||||
}
|
||||
alignedw = ALIGN(w, 16);
|
||||
alignedh = h;
|
||||
size = alignedw*alignedh +
|
||||
(ALIGN(alignedw/2, 16) * (alignedh/2))*2;
|
||||
size = ALIGN(size, 4096);
|
||||
break;
|
||||
|
||||
default:
|
||||
LOGE("unrecognized pixel format: %d", format);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((ssize_t)size <= 0)
|
||||
return -EINVAL;
|
||||
|
||||
size = (bufferSize >= size)? bufferSize : size;
|
||||
|
||||
// All buffers marked as protected or for external
|
||||
// display need to go to overlay
|
||||
if ((usage & GRALLOC_USAGE_EXTERNAL_DISP) ||
|
||||
(usage & GRALLOC_USAGE_PROTECTED)) {
|
||||
bufferType = BUFFER_TYPE_VIDEO;
|
||||
}
|
||||
int err;
|
||||
if (usage & GRALLOC_USAGE_HW_FB) {
|
||||
err = gralloc_alloc_framebuffer(size, usage, pHandle);
|
||||
} else {
|
||||
err = gralloc_alloc_buffer(size, usage, pHandle, bufferType, format, alignedw, alignedh);
|
||||
}
|
||||
|
||||
if (err < 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
*pStride = alignedw;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gpu_context_t::free_impl(private_handle_t const* hnd) {
|
||||
private_module_t* m = reinterpret_cast<private_module_t*>(common.module);
|
||||
if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) {
|
||||
// free this buffer
|
||||
const size_t bufferSize = m->finfo.line_length * m->info.yres;
|
||||
int index = (hnd->base - m->framebuffer->base) / bufferSize;
|
||||
m->bufferMask &= ~(1<<index);
|
||||
} else {
|
||||
PmemAllocator* pmem_allocator = 0;
|
||||
if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_PMEM) {
|
||||
pmem_allocator = &pmemAllocator;
|
||||
} else if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP) {
|
||||
pmem_allocator = &pmemAdspAllocator;
|
||||
} else if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ASHMEM) {
|
||||
// free ashmem
|
||||
if (hnd->fd >= 0) {
|
||||
if (hnd->base) {
|
||||
int err = munmap((void*)hnd->base, hnd->size);
|
||||
LOGE_IF(err<0, "ASHMEM_UNMAP failed (%s), "
|
||||
"fd=%d, sub.offset=%d, sub.size=%d",
|
||||
strerror(errno), hnd->fd, hnd->offset, hnd->size);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pmem_allocator) {
|
||||
pmem_allocator->free_pmem_buffer(hnd->size, (void*)hnd->base,
|
||||
hnd->offset, hnd->fd);
|
||||
}
|
||||
|
||||
deps.terminateBuffer(&m->base, const_cast<private_handle_t*>(hnd));
|
||||
}
|
||||
|
||||
deps.close(hnd->fd);
|
||||
delete hnd; // XXX JMG: move this to the deps
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Static functions
|
||||
*****************************************************************************/
|
||||
|
||||
int gpu_context_t::gralloc_alloc(alloc_device_t* dev, int w, int h, int format,
|
||||
int usage, buffer_handle_t* pHandle, int* pStride)
|
||||
{
|
||||
if (!dev) {
|
||||
return -EINVAL;
|
||||
}
|
||||
gpu_context_t* gpu = reinterpret_cast<gpu_context_t*>(dev);
|
||||
return gpu->alloc_impl(w, h, format, usage, pHandle, pStride, 0);
|
||||
}
|
||||
|
||||
int gpu_context_t::gralloc_alloc_size(alloc_device_t* dev, int w, int h, int format,
|
||||
int usage, buffer_handle_t* pHandle, int* pStride, int bufferSize)
|
||||
{
|
||||
if (!dev) {
|
||||
return -EINVAL;
|
||||
}
|
||||
gpu_context_t* gpu = reinterpret_cast<gpu_context_t*>(dev);
|
||||
return gpu->alloc_impl(w, h, format, usage, pHandle, pStride, bufferSize);
|
||||
}
|
||||
|
||||
int gpu_context_t::gralloc_free(alloc_device_t* dev,
|
||||
buffer_handle_t handle)
|
||||
{
|
||||
if (private_handle_t::validate(handle) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
private_handle_t const* hnd = reinterpret_cast<private_handle_t const*>(handle);
|
||||
gpu_context_t* gpu = reinterpret_cast<gpu_context_t*>(dev);
|
||||
return gpu->free_impl(hnd);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
int gpu_context_t::gralloc_close(struct hw_device_t *dev)
|
||||
{
|
||||
gpu_context_t* ctx = reinterpret_cast<gpu_context_t*>(dev);
|
||||
if (ctx) {
|
||||
/* TODO: keep a list of all buffer_handle_t created, and free them
|
||||
* all here.
|
||||
*/
|
||||
delete ctx;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
gpu_context_t::Deps::~Deps() {}
|
84
libgralloc-qsd8k/gpu.h
Executable file
84
libgralloc-qsd8k/gpu.h
Executable file
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* 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 GRALLOC_QSD8K_GPU_H_
|
||||
#define GRALLOC_QSD8K_GPU_H_
|
||||
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <cutils/log.h>
|
||||
#include <cutils/ashmem.h>
|
||||
|
||||
#include "gralloc_priv.h"
|
||||
#include "pmemalloc.h"
|
||||
|
||||
|
||||
class gpu_context_t : public alloc_device_t {
|
||||
public:
|
||||
|
||||
class Deps {
|
||||
public:
|
||||
|
||||
virtual ~Deps();
|
||||
|
||||
// ashmem
|
||||
virtual int ashmem_create_region(const char *name, size_t size) = 0;
|
||||
|
||||
// POSIX
|
||||
virtual int close(int fd) = 0;
|
||||
|
||||
// Framebuffer (locally defined)
|
||||
virtual int mapFrameBufferLocked(struct private_module_t* module) = 0;
|
||||
virtual int terminateBuffer(gralloc_module_t const* module,
|
||||
private_handle_t* hnd) = 0;
|
||||
};
|
||||
|
||||
gpu_context_t(Deps& deps, PmemAllocator& pmemAllocator,
|
||||
PmemAllocator& pmemAdspAllocator, const private_module_t* module);
|
||||
|
||||
int gralloc_alloc_framebuffer_locked(size_t size, int usage,
|
||||
buffer_handle_t* pHandle);
|
||||
int gralloc_alloc_framebuffer(size_t size, int usage,
|
||||
buffer_handle_t* pHandle);
|
||||
int gralloc_alloc_buffer(size_t size, int usage, buffer_handle_t* pHandle, int bufferType, int format,
|
||||
int width, int height);
|
||||
int free_impl(private_handle_t const* hnd);
|
||||
int alloc_impl(int w, int h, int format, int usage,
|
||||
buffer_handle_t* pHandle, int* pStride, int bufferSize = 0);
|
||||
|
||||
static int gralloc_alloc(alloc_device_t* dev, int w, int h, int format,
|
||||
int usage, buffer_handle_t* pHandle, int* pStride);
|
||||
static int gralloc_free(alloc_device_t* dev, buffer_handle_t handle);
|
||||
static int gralloc_alloc_size(alloc_device_t* dev, int w, int h, int format,
|
||||
int usage, buffer_handle_t* pHandle, int* pStride, int bufferSize);
|
||||
static int gralloc_close(struct hw_device_t *dev);
|
||||
int get_composition_type() const { return compositionType; }
|
||||
|
||||
private:
|
||||
|
||||
Deps& deps;
|
||||
PmemAllocator& pmemAllocator;
|
||||
PmemAllocator& pmemAdspAllocator;
|
||||
int compositionType;
|
||||
int alloc_ashmem_buffer(size_t size, unsigned int postfix, void** pBase,
|
||||
int* pOffset, int* pFd);
|
||||
void getGrallocInformationFromFormat(int inputFormat, int *colorFormat, int *bufferType);
|
||||
};
|
||||
|
||||
#endif // GRALLOC_QSD8K_GPU_H
|
69
libgralloc-qsd8k/gr.h
Normal file
69
libgralloc-qsd8k/gr.h
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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 GR_H_
|
||||
#define GR_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#ifdef HAVE_ANDROID_OS // just want PAGE_SIZE define
|
||||
# include <asm/page.h>
|
||||
#else
|
||||
# include <sys/user.h>
|
||||
#endif
|
||||
#include <limits.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include <hardware/gralloc.h>
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <cutils/native_handle.h>
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
struct private_module_t;
|
||||
struct private_handle_t;
|
||||
|
||||
inline size_t roundUpToPageSize(size_t x) {
|
||||
return (x + (PAGE_SIZE-1)) & ~(PAGE_SIZE-1);
|
||||
}
|
||||
|
||||
#define FALSE 0
|
||||
#define TRUE 1
|
||||
|
||||
int mapFrameBufferLocked(struct private_module_t* module);
|
||||
int terminateBuffer(gralloc_module_t const* module, private_handle_t* hnd);
|
||||
size_t calculateBufferSize(int width, int height, int format);
|
||||
int decideBufferHandlingMechanism(int format, const char *compositionUsed,
|
||||
int hasBlitEngine, int *needConversion,
|
||||
int *useBufferDirectly);
|
||||
/*****************************************************************************/
|
||||
|
||||
class Locker {
|
||||
pthread_mutex_t mutex;
|
||||
public:
|
||||
class Autolock {
|
||||
Locker& locker;
|
||||
public:
|
||||
inline Autolock(Locker& locker) : locker(locker) { locker.lock(); }
|
||||
inline ~Autolock() { locker.unlock(); }
|
||||
};
|
||||
inline Locker() { pthread_mutex_init(&mutex, 0); }
|
||||
inline ~Locker() { pthread_mutex_destroy(&mutex); }
|
||||
inline void lock() { pthread_mutex_lock(&mutex); }
|
||||
inline void unlock() { pthread_mutex_unlock(&mutex); }
|
||||
};
|
||||
|
||||
#endif /* GR_H_ */
|
231
libgralloc-qsd8k/gralloc.cpp
Executable file
231
libgralloc-qsd8k/gralloc.cpp
Executable file
@ -0,0 +1,231 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <linux/android_pmem.h>
|
||||
|
||||
#include "allocator.h"
|
||||
#include "gr.h"
|
||||
#include "gpu.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static int gralloc_alloc_buffer(alloc_device_t* dev,
|
||||
size_t size, int usage, buffer_handle_t* pHandle);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
int fb_device_open(const hw_module_t* module, const char* name,
|
||||
hw_device_t** device);
|
||||
|
||||
static int gralloc_device_open(const hw_module_t* module, const char* name,
|
||||
hw_device_t** device);
|
||||
|
||||
extern int gralloc_lock(gralloc_module_t const* module,
|
||||
buffer_handle_t handle, int usage,
|
||||
int l, int t, int w, int h,
|
||||
void** vaddr);
|
||||
|
||||
extern int gralloc_unlock(gralloc_module_t const* module,
|
||||
buffer_handle_t handle);
|
||||
|
||||
extern int gralloc_register_buffer(gralloc_module_t const* module,
|
||||
buffer_handle_t handle);
|
||||
|
||||
extern int gralloc_unregister_buffer(gralloc_module_t const* module,
|
||||
buffer_handle_t handle);
|
||||
|
||||
extern int gralloc_perform(struct gralloc_module_t const* module,
|
||||
int operation, ... );
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* On-device dependency implementation */
|
||||
class PmemAllocatorDepsDeviceImpl : public PmemUserspaceAllocator::Deps,
|
||||
public PmemKernelAllocator::Deps {
|
||||
|
||||
const private_module_t* module;
|
||||
|
||||
virtual size_t getPmemTotalSize(int fd, size_t* size) {
|
||||
int err = 0;
|
||||
#ifndef TARGET_MSM7x27
|
||||
pmem_region region;
|
||||
err = ioctl(fd, PMEM_GET_TOTAL_SIZE, ®ion);
|
||||
if (err == 0) {
|
||||
*size = region.len;
|
||||
}
|
||||
#else
|
||||
#ifdef USE_ASHMEM
|
||||
if(module != NULL)
|
||||
*size = module->info.xres * module->info.yres * 2 * 2;
|
||||
else
|
||||
return -ENOMEM;
|
||||
#else
|
||||
*size = 23<<20; //23MB for 7x27
|
||||
#endif
|
||||
#endif
|
||||
return err;
|
||||
}
|
||||
|
||||
virtual int connectPmem(int fd, int master_fd) {
|
||||
return ioctl(fd, PMEM_CONNECT, master_fd);
|
||||
}
|
||||
|
||||
virtual int mapPmem(int fd, int offset, size_t size) {
|
||||
struct pmem_region sub = { offset, size };
|
||||
return ioctl(fd, PMEM_MAP, &sub);
|
||||
}
|
||||
|
||||
virtual int unmapPmem(int fd, int offset, size_t size) {
|
||||
struct pmem_region sub = { offset, size };
|
||||
return ioctl(fd, PMEM_UNMAP, &sub);
|
||||
}
|
||||
|
||||
virtual int alignPmem(int fd, size_t size, int align) {
|
||||
struct pmem_allocation allocation;
|
||||
allocation.size = size;
|
||||
allocation.align = align;
|
||||
return ioctl(fd, PMEM_ALLOCATE_ALIGNED, &allocation);
|
||||
}
|
||||
|
||||
virtual int cleanPmem(int fd, unsigned long base, int offset, size_t size) {
|
||||
struct pmem_addr pmem_addr;
|
||||
pmem_addr.vaddr = base;
|
||||
pmem_addr.offset = offset;
|
||||
pmem_addr.length = size;
|
||||
return ioctl(fd, PMEM_CLEAN_INV_CACHES, &pmem_addr);
|
||||
}
|
||||
|
||||
virtual int getErrno() {
|
||||
return errno;
|
||||
}
|
||||
|
||||
virtual void* mmap(void* start, size_t length, int prot, int flags, int fd,
|
||||
off_t offset) {
|
||||
return ::mmap(start, length, prot, flags, fd, offset);
|
||||
}
|
||||
|
||||
virtual int munmap(void* start, size_t length) {
|
||||
return ::munmap(start, length);
|
||||
}
|
||||
|
||||
virtual int open(const char* pathname, int flags, int mode) {
|
||||
return ::open(pathname, flags, mode);
|
||||
}
|
||||
|
||||
virtual int close(int fd) {
|
||||
return ::close(fd);
|
||||
}
|
||||
|
||||
public:
|
||||
void setModule(const private_module_t* m) {
|
||||
module = m;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class GpuContextDepsDeviceImpl : public gpu_context_t::Deps {
|
||||
|
||||
public:
|
||||
|
||||
virtual int ashmem_create_region(const char *name, size_t size) {
|
||||
return ::ashmem_create_region(name, size);
|
||||
}
|
||||
|
||||
virtual int mapFrameBufferLocked(struct private_module_t* module) {
|
||||
return ::mapFrameBufferLocked(module);
|
||||
}
|
||||
|
||||
virtual int terminateBuffer(gralloc_module_t const* module,
|
||||
private_handle_t* hnd) {
|
||||
return ::terminateBuffer(module, hnd);
|
||||
}
|
||||
|
||||
virtual int close(int fd) {
|
||||
return ::close(fd);
|
||||
}
|
||||
};
|
||||
|
||||
static PmemAllocatorDepsDeviceImpl pmemAllocatorDeviceDepsImpl;
|
||||
static GpuContextDepsDeviceImpl gpuContextDeviceDepsImpl;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static SimpleBestFitAllocator pmemAllocMgr;
|
||||
static PmemUserspaceAllocator pmemAllocator(pmemAllocatorDeviceDepsImpl, pmemAllocMgr,
|
||||
"/dev/pmem");
|
||||
|
||||
static PmemKernelAllocator pmemAdspAllocator(pmemAllocatorDeviceDepsImpl);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static struct hw_module_methods_t gralloc_module_methods = {
|
||||
open: gralloc_device_open
|
||||
};
|
||||
|
||||
struct private_module_t HAL_MODULE_INFO_SYM = {
|
||||
base: {
|
||||
common: {
|
||||
tag: HARDWARE_MODULE_TAG,
|
||||
version_major: 1,
|
||||
version_minor: 0,
|
||||
id: GRALLOC_HARDWARE_MODULE_ID,
|
||||
name: "Graphics Memory Allocator Module",
|
||||
author: "The Android Open Source Project",
|
||||
methods: &gralloc_module_methods
|
||||
},
|
||||
registerBuffer: gralloc_register_buffer,
|
||||
unregisterBuffer: gralloc_unregister_buffer,
|
||||
lock: gralloc_lock,
|
||||
unlock: gralloc_unlock,
|
||||
perform: gralloc_perform,
|
||||
},
|
||||
framebuffer: 0,
|
||||
fbFormat: 0,
|
||||
flags: 0,
|
||||
numBuffers: 0,
|
||||
bufferMask: 0,
|
||||
lock: PTHREAD_MUTEX_INITIALIZER,
|
||||
currentBuffer: 0,
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
int gralloc_device_open(const hw_module_t* module, const char* name,
|
||||
hw_device_t** device)
|
||||
{
|
||||
int status = -EINVAL;
|
||||
if (!strcmp(name, GRALLOC_HARDWARE_GPU0)) {
|
||||
const private_module_t* m = reinterpret_cast<const private_module_t*>(
|
||||
module);
|
||||
pmemAllocatorDeviceDepsImpl.setModule(m);
|
||||
gpu_context_t *dev;
|
||||
dev = new gpu_context_t(gpuContextDeviceDepsImpl, pmemAllocator,
|
||||
pmemAdspAllocator, m);
|
||||
*device = &dev->common;
|
||||
status = 0;
|
||||
} else {
|
||||
status = fb_device_open(module, name, device);
|
||||
}
|
||||
return status;
|
||||
}
|
344
libgralloc-qsd8k/gralloc_priv.h
Executable file
344
libgralloc-qsd8k/gralloc_priv.h
Executable file
@ -0,0 +1,344 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef GRALLOC_PRIV_H_
|
||||
#define GRALLOC_PRIV_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <limits.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include <hardware/gralloc.h>
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <cutils/native_handle.h>
|
||||
|
||||
#include <linux/fb.h>
|
||||
|
||||
#if defined(__cplusplus) && defined(HDMI_DUAL_DISPLAY)
|
||||
#include "overlayLib.h"
|
||||
using namespace overlay;
|
||||
#endif
|
||||
|
||||
enum {
|
||||
/* gralloc usage bits indicating the type
|
||||
* of allocation that should be used */
|
||||
GRALLOC_USAGE_PRIVATE_ADSP_HEAP = GRALLOC_USAGE_PRIVATE_0,
|
||||
GRALLOC_USAGE_PRIVATE_EBI_HEAP = GRALLOC_USAGE_PRIVATE_1,
|
||||
GRALLOC_USAGE_PRIVATE_SMI_HEAP = GRALLOC_USAGE_PRIVATE_2,
|
||||
GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP = GRALLOC_USAGE_PRIVATE_3,
|
||||
/* Set this for allocating uncached memory (using O_DSYNC)
|
||||
* cannot be used with the system heap */
|
||||
GRALLOC_USAGE_PRIVATE_UNCACHED = 0x00010000,
|
||||
};
|
||||
|
||||
enum {
|
||||
GPU_COMPOSITION,
|
||||
C2D_COMPOSITION,
|
||||
MDP_COMPOSITION,
|
||||
CPU_COMPOSITION,
|
||||
};
|
||||
|
||||
/* numbers of max buffers for page flipping */
|
||||
#define NUM_FRAMEBUFFERS_MIN 2
|
||||
#define NUM_FRAMEBUFFERS_MAX 3
|
||||
|
||||
/* number of default bufers for page flipping */
|
||||
#define NUM_DEF_FRAME_BUFFERS 2
|
||||
#define NO_SURFACEFLINGER_SWAPINTERVAL
|
||||
#define INTERLACE_MASK 0x80
|
||||
#define S3D_FORMAT_MASK 0xFF000
|
||||
#define COLOR_FORMAT(x) (x & 0xFFF) // Max range for colorFormats is 0 - FFF
|
||||
#define DEVICE_PMEM_ADSP "/dev/pmem_adsp"
|
||||
#define DEVICE_PMEM_SMIPOOL "/dev/pmem_smipool"
|
||||
/*****************************************************************************/
|
||||
#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()) {
|
||||
LOGE("Error can't get head of empty queue");
|
||||
return *dummy;
|
||||
}
|
||||
return front->data;
|
||||
}
|
||||
|
||||
bool isEmpty() const //returns true if no elements are in the queue
|
||||
{
|
||||
return (front == NULL);
|
||||
}
|
||||
|
||||
size_t size() const //returns the amount of elements in the queue
|
||||
{
|
||||
return len;
|
||||
}
|
||||
|
||||
private:
|
||||
Node<T> *front;
|
||||
Node<T> *back;
|
||||
size_t len;
|
||||
void clear()
|
||||
{
|
||||
while (!isEmpty())
|
||||
pop();
|
||||
}
|
||||
T *dummy;
|
||||
};
|
||||
#endif
|
||||
|
||||
enum {
|
||||
/* OEM specific HAL formats */
|
||||
//HAL_PIXEL_FORMAT_YCbCr_422_SP = 0x100, // defined in hardware.h
|
||||
//HAL_PIXEL_FORMAT_YCrCb_420_SP = 0x101, // defined in hardware.h
|
||||
HAL_PIXEL_FORMAT_YCbCr_422_P = 0x102,
|
||||
HAL_PIXEL_FORMAT_YCbCr_420_P = 0x103,
|
||||
//HAL_PIXEL_FORMAT_YCbCr_422_I = 0x104, // defined in hardware.h
|
||||
HAL_PIXEL_FORMAT_YCbCr_420_I = 0x105,
|
||||
HAL_PIXEL_FORMAT_CbYCrY_422_I = 0x106,
|
||||
HAL_PIXEL_FORMAT_CbYCrY_420_I = 0x107,
|
||||
HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED = 0x108,
|
||||
HAL_PIXEL_FORMAT_YCbCr_420_SP = 0x109,
|
||||
HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO = 0x10A,
|
||||
HAL_PIXEL_FORMAT_YCrCb_422_SP = 0x10B,
|
||||
HAL_PIXEL_FORMAT_R_8 = 0x10D,
|
||||
HAL_PIXEL_FORMAT_RG_88 = 0x10E,
|
||||
HAL_PIXEL_FORMAT_INTERLACE = 0x180,
|
||||
|
||||
};
|
||||
|
||||
/* possible formats for 3D content*/
|
||||
enum {
|
||||
HAL_NO_3D = 0x0000,
|
||||
HAL_3D_IN_SIDE_BY_SIDE_L_R = 0x10000,
|
||||
HAL_3D_IN_TOP_BOTTOM = 0x20000,
|
||||
HAL_3D_IN_INTERLEAVE = 0x40000,
|
||||
HAL_3D_IN_SIDE_BY_SIDE_R_L = 0x80000,
|
||||
HAL_3D_OUT_SIDE_BY_SIDE = 0x1000,
|
||||
HAL_3D_OUT_TOP_BOTTOM = 0x2000,
|
||||
HAL_3D_OUT_INTERLEAVE = 0x4000,
|
||||
HAL_3D_OUT_MONOSCOPIC = 0x8000
|
||||
};
|
||||
|
||||
enum {
|
||||
BUFFER_TYPE_UI = 0,
|
||||
BUFFER_TYPE_VIDEO
|
||||
};
|
||||
/*****************************************************************************/
|
||||
|
||||
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;
|
||||
bool enableHDMIOutput;
|
||||
bool exitHDMIUILoop;
|
||||
float actionsafeWidthRatio;
|
||||
float actionsafeHeightRatio;
|
||||
bool hdmiStateChanged;
|
||||
pthread_mutex_t overlayLock;
|
||||
pthread_cond_t overlayPost;
|
||||
#endif
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
struct private_handle_t : public native_handle {
|
||||
#else
|
||||
struct private_handle_t {
|
||||
native_handle_t nativeHandle;
|
||||
#endif
|
||||
|
||||
enum {
|
||||
PRIV_FLAGS_FRAMEBUFFER = 0x00000001,
|
||||
PRIV_FLAGS_USES_PMEM = 0x00000002,
|
||||
PRIV_FLAGS_USES_PMEM_ADSP = 0x00000004,
|
||||
PRIV_FLAGS_USES_ION = 0x00000008,
|
||||
PRIV_FLAGS_USES_ASHMEM = 0x00000010,
|
||||
PRIV_FLAGS_NEEDS_FLUSH = 0x00000020,
|
||||
PRIV_FLAGS_DO_NOT_FLUSH = 0x00000040,
|
||||
};
|
||||
|
||||
enum {
|
||||
LOCK_STATE_WRITE = 1<<31,
|
||||
LOCK_STATE_MAPPED = 1<<30,
|
||||
LOCK_STATE_READ_MASK = 0x3FFFFFFF
|
||||
};
|
||||
|
||||
// file-descriptors
|
||||
int fd;
|
||||
// ints
|
||||
int magic;
|
||||
int flags;
|
||||
int size;
|
||||
int offset;
|
||||
int bufferType;
|
||||
|
||||
// FIXME: the attributes below should be out-of-line
|
||||
int base;
|
||||
int lockState;
|
||||
int writeOwner;
|
||||
int gpuaddr; // The gpu address mapped into the mmu. If using ashmem, set to 0 They don't care
|
||||
int pid;
|
||||
int format;
|
||||
int width;
|
||||
int height;
|
||||
|
||||
#ifdef __cplusplus
|
||||
static const int sNumInts = 13;
|
||||
static const int sNumFds = 1;
|
||||
static const int sMagic = 'gmsm';
|
||||
|
||||
private_handle_t(int fd, int size, int flags, int bufferType, int format, int width, int height) :
|
||||
fd(fd), magic(sMagic), flags(flags), size(size), offset(0), bufferType(bufferType),
|
||||
base(0), lockState(0), writeOwner(0), gpuaddr(0), pid(getpid()), format(format), width(width),
|
||||
height(height)
|
||||
{
|
||||
version = sizeof(native_handle);
|
||||
numInts = sNumInts;
|
||||
numFds = sNumFds;
|
||||
}
|
||||
~private_handle_t() {
|
||||
magic = 0;
|
||||
}
|
||||
|
||||
bool usesPhysicallyContiguousMemory() {
|
||||
return (flags & PRIV_FLAGS_USES_PMEM) != 0;
|
||||
}
|
||||
|
||||
static int validate(const native_handle* h) {
|
||||
const private_handle_t* hnd = (const private_handle_t*)h;
|
||||
if (!h || h->version != sizeof(native_handle) ||
|
||||
h->numInts != sNumInts || h->numFds != sNumFds ||
|
||||
hnd->magic != sMagic)
|
||||
{
|
||||
LOGE("invalid gralloc handle (at %p)", h);
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static private_handle_t* dynamicCast(const native_handle* in) {
|
||||
if (validate(in) == 0) {
|
||||
return (private_handle_t*) in;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif /* GRALLOC_PRIV_H_ */
|
386
libgralloc-qsd8k/mapper.cpp
Executable file
386
libgralloc-qsd8k/mapper.cpp
Executable file
@ -0,0 +1,386 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/ashmem.h>
|
||||
|
||||
#include <cutils/log.h>
|
||||
#include <cutils/atomic.h>
|
||||
#include <cutils/ashmem.h>
|
||||
|
||||
#include <hardware/hardware.h>
|
||||
#include <hardware/gralloc.h>
|
||||
|
||||
#include <linux/android_pmem.h>
|
||||
|
||||
#include "gralloc_priv.h"
|
||||
#include "gr.h"
|
||||
|
||||
// we need this for now because pmem cannot mmap at an offset
|
||||
#define PMEM_HACK 1
|
||||
|
||||
/* desktop Linux needs a little help with gettid() */
|
||||
#if defined(ARCH_X86) && !defined(HAVE_ANDROID_OS)
|
||||
#define __KERNEL__
|
||||
# include <linux/unistd.h>
|
||||
pid_t gettid() { return syscall(__NR_gettid);}
|
||||
#undef __KERNEL__
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static int gralloc_map(gralloc_module_t const* module,
|
||||
buffer_handle_t handle,
|
||||
void** vaddr)
|
||||
{
|
||||
private_handle_t* hnd = (private_handle_t*)handle;
|
||||
void *mappedAddress;
|
||||
if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
|
||||
size_t size = hnd->size;
|
||||
#if PMEM_HACK
|
||||
size += hnd->offset;
|
||||
#endif
|
||||
if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ASHMEM) {
|
||||
mappedAddress = mmap(0, size,
|
||||
PROT_READ|PROT_WRITE, MAP_SHARED | MAP_POPULATE, hnd->fd, 0);
|
||||
} else {
|
||||
mappedAddress = mmap(0, size,
|
||||
PROT_READ|PROT_WRITE, MAP_SHARED, hnd->fd, 0);
|
||||
}
|
||||
if (mappedAddress == MAP_FAILED) {
|
||||
LOGE("Could not mmap handle %p, fd=%d (%s)",
|
||||
handle, hnd->fd, strerror(errno));
|
||||
hnd->base = 0;
|
||||
return -errno;
|
||||
}
|
||||
hnd->base = intptr_t(mappedAddress) + hnd->offset;
|
||||
//LOGD("gralloc_map() succeeded fd=%d, off=%d, size=%d, vaddr=%p",
|
||||
// hnd->fd, hnd->offset, hnd->size, mappedAddress);
|
||||
}
|
||||
*vaddr = (void*)hnd->base;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gralloc_unmap(gralloc_module_t const* module,
|
||||
buffer_handle_t handle)
|
||||
{
|
||||
private_handle_t* hnd = (private_handle_t*)handle;
|
||||
if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
|
||||
void* base = (void*)hnd->base;
|
||||
size_t size = hnd->size;
|
||||
#if PMEM_HACK
|
||||
base = (void*)(intptr_t(base) - hnd->offset);
|
||||
size += hnd->offset;
|
||||
#endif
|
||||
//LOGD("unmapping from %p, size=%d", base, size);
|
||||
if (munmap(base, size) < 0) {
|
||||
LOGE("Could not unmap %s", strerror(errno));
|
||||
}
|
||||
}
|
||||
hnd->base = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static pthread_mutex_t sMapLock = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
int gralloc_register_buffer(gralloc_module_t const* module,
|
||||
buffer_handle_t handle)
|
||||
{
|
||||
if (private_handle_t::validate(handle) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
// In this implementation, we don't need to do anything here
|
||||
|
||||
/* NOTE: we need to initialize the buffer as not mapped/not locked
|
||||
* because it shouldn't when this function is called the first time
|
||||
* in a new process. Ideally these flags shouldn't be part of the
|
||||
* handle, but instead maintained in the kernel or at least
|
||||
* out-of-line
|
||||
*/
|
||||
|
||||
// if this handle was created in this process, then we keep it as is.
|
||||
private_handle_t* hnd = (private_handle_t*)handle;
|
||||
if (hnd->pid != getpid()) {
|
||||
hnd->base = 0;
|
||||
hnd->lockState = 0;
|
||||
hnd->writeOwner = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gralloc_unregister_buffer(gralloc_module_t const* module,
|
||||
buffer_handle_t handle)
|
||||
{
|
||||
if (private_handle_t::validate(handle) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* If the buffer has been mapped during a lock operation, it's time
|
||||
* to un-map it. It's an error to be here with a locked buffer.
|
||||
* NOTE: the framebuffer is handled differently and is never unmapped.
|
||||
*/
|
||||
|
||||
private_handle_t* hnd = (private_handle_t*)handle;
|
||||
|
||||
LOGE_IF(hnd->lockState & private_handle_t::LOCK_STATE_READ_MASK,
|
||||
"[unregister] handle %p still locked (state=%08x)",
|
||||
hnd, hnd->lockState);
|
||||
|
||||
// never unmap buffers that were created in this process
|
||||
if (hnd->pid != getpid()) {
|
||||
if (hnd->lockState & private_handle_t::LOCK_STATE_MAPPED) {
|
||||
gralloc_unmap(module, handle);
|
||||
}
|
||||
hnd->base = 0;
|
||||
hnd->lockState = 0;
|
||||
hnd->writeOwner = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int terminateBuffer(gralloc_module_t const* module,
|
||||
private_handle_t* hnd)
|
||||
{
|
||||
/*
|
||||
* If the buffer has been mapped during a lock operation, it's time
|
||||
* to un-map it. It's an error to be here with a locked buffer.
|
||||
*/
|
||||
|
||||
LOGE_IF(hnd->lockState & private_handle_t::LOCK_STATE_READ_MASK,
|
||||
"[terminate] handle %p still locked (state=%08x)",
|
||||
hnd, hnd->lockState);
|
||||
|
||||
if (hnd->lockState & private_handle_t::LOCK_STATE_MAPPED) {
|
||||
// this buffer was mapped, unmap it now
|
||||
if (hnd->flags & (private_handle_t::PRIV_FLAGS_USES_PMEM |
|
||||
private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP |
|
||||
private_handle_t::PRIV_FLAGS_USES_ASHMEM)) {
|
||||
if (hnd->pid != getpid()) {
|
||||
// ... unless it's a "master" pmem buffer, that is a buffer
|
||||
// mapped in the process it's been allocated.
|
||||
// (see gralloc_alloc_buffer())
|
||||
gralloc_unmap(module, hnd);
|
||||
}
|
||||
} else {
|
||||
LOGE("terminateBuffer: unmapping a non pmem/ashmem buffer flags = 0x%x", hnd->flags);
|
||||
gralloc_unmap(module, hnd);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gralloc_lock(gralloc_module_t const* module,
|
||||
buffer_handle_t handle, int usage,
|
||||
int l, int t, int w, int h,
|
||||
void** vaddr)
|
||||
{
|
||||
if (private_handle_t::validate(handle) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
int err = 0;
|
||||
private_handle_t* hnd = (private_handle_t*)handle;
|
||||
int32_t current_value, new_value;
|
||||
int retry;
|
||||
|
||||
do {
|
||||
current_value = hnd->lockState;
|
||||
new_value = current_value;
|
||||
|
||||
if (current_value & private_handle_t::LOCK_STATE_WRITE) {
|
||||
// already locked for write
|
||||
LOGE("handle %p already locked for write", handle);
|
||||
return -EBUSY;
|
||||
} else if (current_value & private_handle_t::LOCK_STATE_READ_MASK) {
|
||||
// already locked for read
|
||||
if (usage & (GRALLOC_USAGE_SW_WRITE_MASK | GRALLOC_USAGE_HW_RENDER)) {
|
||||
LOGE("handle %p already locked for read", handle);
|
||||
return -EBUSY;
|
||||
} else {
|
||||
// this is not an error
|
||||
//LOGD("%p already locked for read... count = %d",
|
||||
// handle, (current_value & ~(1<<31)));
|
||||
}
|
||||
}
|
||||
|
||||
// not currently locked
|
||||
if (usage & (GRALLOC_USAGE_SW_WRITE_MASK | GRALLOC_USAGE_HW_RENDER)) {
|
||||
// locking for write
|
||||
new_value |= private_handle_t::LOCK_STATE_WRITE;
|
||||
}
|
||||
new_value++;
|
||||
|
||||
retry = android_atomic_cmpxchg(current_value, new_value,
|
||||
(volatile int32_t*)&hnd->lockState);
|
||||
} while (retry);
|
||||
|
||||
if (new_value & private_handle_t::LOCK_STATE_WRITE) {
|
||||
// locking for write, store the tid
|
||||
hnd->writeOwner = gettid();
|
||||
}
|
||||
|
||||
// if requesting sw write for non-framebuffer handles, flag for
|
||||
// flushing at unlock
|
||||
|
||||
if ((usage & GRALLOC_USAGE_SW_WRITE_MASK) &&
|
||||
!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
|
||||
hnd->flags |= private_handle_t::PRIV_FLAGS_NEEDS_FLUSH;
|
||||
}
|
||||
|
||||
if (usage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) {
|
||||
if (!(current_value & private_handle_t::LOCK_STATE_MAPPED)) {
|
||||
// we need to map for real
|
||||
pthread_mutex_t* const lock = &sMapLock;
|
||||
pthread_mutex_lock(lock);
|
||||
if (!(hnd->lockState & private_handle_t::LOCK_STATE_MAPPED)) {
|
||||
err = gralloc_map(module, handle, vaddr);
|
||||
if (err == 0) {
|
||||
android_atomic_or(private_handle_t::LOCK_STATE_MAPPED,
|
||||
(volatile int32_t*)&(hnd->lockState));
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(lock);
|
||||
}
|
||||
*vaddr = (void*)hnd->base;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int gralloc_unlock(gralloc_module_t const* module,
|
||||
buffer_handle_t handle)
|
||||
{
|
||||
if (private_handle_t::validate(handle) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
private_handle_t* hnd = (private_handle_t*)handle;
|
||||
int32_t current_value, new_value;
|
||||
|
||||
if (hnd->flags & private_handle_t::PRIV_FLAGS_NEEDS_FLUSH) {
|
||||
int err;
|
||||
if (hnd->flags & (private_handle_t::PRIV_FLAGS_USES_PMEM |
|
||||
private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP)) {
|
||||
struct pmem_addr pmem_addr;
|
||||
pmem_addr.vaddr = hnd->base;
|
||||
pmem_addr.offset = hnd->offset;
|
||||
pmem_addr.length = hnd->size;
|
||||
err = ioctl( hnd->fd, PMEM_CLEAN_CACHES, &pmem_addr);
|
||||
} else if ((hnd->flags & private_handle_t::PRIV_FLAGS_USES_ASHMEM)) {
|
||||
unsigned long addr = hnd->base + hnd->offset;
|
||||
err = ioctl(hnd->fd, ASHMEM_CACHE_FLUSH_RANGE, NULL);
|
||||
}
|
||||
|
||||
LOGE_IF(err < 0, "cannot flush handle %p (offs=%x len=%x, flags = 0x%x) err=%s\n",
|
||||
hnd, hnd->offset, hnd->size, hnd->flags, strerror(errno));
|
||||
hnd->flags &= ~private_handle_t::PRIV_FLAGS_NEEDS_FLUSH;
|
||||
}
|
||||
|
||||
do {
|
||||
current_value = hnd->lockState;
|
||||
new_value = current_value;
|
||||
|
||||
if (current_value & private_handle_t::LOCK_STATE_WRITE) {
|
||||
// locked for write
|
||||
if (hnd->writeOwner == gettid()) {
|
||||
hnd->writeOwner = 0;
|
||||
new_value &= ~private_handle_t::LOCK_STATE_WRITE;
|
||||
}
|
||||
}
|
||||
|
||||
if ((new_value & private_handle_t::LOCK_STATE_READ_MASK) == 0) {
|
||||
LOGE("handle %p not locked", handle);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
new_value--;
|
||||
|
||||
} while (android_atomic_cmpxchg(current_value, new_value,
|
||||
(volatile int32_t*)&hnd->lockState));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
int gralloc_perform(struct gralloc_module_t const* module,
|
||||
int operation, ... )
|
||||
{
|
||||
int res = -EINVAL;
|
||||
va_list args;
|
||||
va_start(args, operation);
|
||||
|
||||
switch (operation) {
|
||||
case GRALLOC_MODULE_PERFORM_CREATE_HANDLE_FROM_BUFFER: {
|
||||
int fd = va_arg(args, int);
|
||||
size_t size = va_arg(args, size_t);
|
||||
size_t offset = va_arg(args, size_t);
|
||||
void* base = va_arg(args, void*);
|
||||
|
||||
// validate that it's indeed a pmem buffer
|
||||
pmem_region region;
|
||||
if (ioctl(fd, PMEM_GET_SIZE, ®ion) < 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
native_handle_t** handle = va_arg(args, native_handle_t**);
|
||||
private_handle_t* hnd = (private_handle_t*)native_handle_create(
|
||||
private_handle_t::sNumFds, private_handle_t::sNumInts);
|
||||
hnd->magic = private_handle_t::sMagic;
|
||||
hnd->fd = fd;
|
||||
hnd->flags = private_handle_t::PRIV_FLAGS_USES_PMEM;
|
||||
hnd->size = size;
|
||||
hnd->offset = offset;
|
||||
hnd->base = intptr_t(base) + offset;
|
||||
hnd->lockState = private_handle_t::LOCK_STATE_MAPPED;
|
||||
hnd->gpuaddr = 0;
|
||||
*handle = (native_handle_t *)hnd;
|
||||
res = 0;
|
||||
break;
|
||||
}
|
||||
case GRALLOC_MODULE_PERFORM_UPDATE_BUFFER_HANDLE: {
|
||||
native_handle_t* handle = va_arg(args, native_handle_t*);
|
||||
int w = va_arg(args, int);
|
||||
int h = va_arg(args, int);
|
||||
int f = va_arg(args, int);
|
||||
private_handle_t* hnd = (private_handle_t*)handle;
|
||||
hnd->width = w;
|
||||
hnd->height = h;
|
||||
if (hnd->format != f) {
|
||||
hnd->format = f;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
va_end(args);
|
||||
return res;
|
||||
}
|
360
libgralloc-qsd8k/pmemalloc.cpp
Executable file
360
libgralloc-qsd8k/pmemalloc.cpp
Executable file
@ -0,0 +1,360 @@
|
||||
/*
|
||||
* Copyright (C) 2010 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
//#define LOG_NDEBUG 0
|
||||
|
||||
#include <limits.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <pthread.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include <cutils/log.h>
|
||||
#include <cutils/ashmem.h>
|
||||
|
||||
#include "gralloc_priv.h"
|
||||
#include "pmemalloc.h"
|
||||
|
||||
|
||||
#define BEGIN_FUNC LOGV("%s begin", __PRETTY_FUNCTION__)
|
||||
#define END_FUNC LOGV("%s end", __PRETTY_FUNCTION__)
|
||||
|
||||
|
||||
static int get_open_flags(int usage) {
|
||||
int openFlags = O_RDWR | O_SYNC;
|
||||
uint32_t uread = usage & GRALLOC_USAGE_SW_READ_MASK;
|
||||
uint32_t uwrite = usage & GRALLOC_USAGE_SW_WRITE_MASK;
|
||||
if (uread == GRALLOC_USAGE_SW_READ_OFTEN ||
|
||||
uwrite == GRALLOC_USAGE_SW_WRITE_OFTEN) {
|
||||
openFlags &= ~O_SYNC;
|
||||
}
|
||||
return openFlags;
|
||||
}
|
||||
|
||||
PmemAllocator::~PmemAllocator()
|
||||
{
|
||||
BEGIN_FUNC;
|
||||
END_FUNC;
|
||||
}
|
||||
|
||||
|
||||
PmemUserspaceAllocator::PmemUserspaceAllocator(Deps& deps, Deps::Allocator& allocator, const char* pmemdev):
|
||||
deps(deps),
|
||||
allocator(allocator),
|
||||
pmemdev(pmemdev),
|
||||
master_fd(MASTER_FD_INIT)
|
||||
{
|
||||
BEGIN_FUNC;
|
||||
pthread_mutex_init(&lock, NULL);
|
||||
END_FUNC;
|
||||
}
|
||||
|
||||
|
||||
PmemUserspaceAllocator::~PmemUserspaceAllocator()
|
||||
{
|
||||
BEGIN_FUNC;
|
||||
END_FUNC;
|
||||
}
|
||||
|
||||
|
||||
void* PmemUserspaceAllocator::get_base_address() {
|
||||
BEGIN_FUNC;
|
||||
END_FUNC;
|
||||
return master_base;
|
||||
}
|
||||
|
||||
|
||||
int PmemUserspaceAllocator::init_pmem_area_locked()
|
||||
{
|
||||
BEGIN_FUNC;
|
||||
int err = 0;
|
||||
int fd = deps.open(pmemdev, O_RDWR, 0);
|
||||
if (fd >= 0) {
|
||||
size_t size = 0;
|
||||
err = deps.getPmemTotalSize(fd, &size);
|
||||
if (err < 0) {
|
||||
LOGE("%s: PMEM_GET_TOTAL_SIZE failed (%d), limp mode", pmemdev,
|
||||
err);
|
||||
size = 8<<20; // 8 MiB
|
||||
}
|
||||
allocator.setSize(size);
|
||||
|
||||
void* base = deps.mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd,
|
||||
0);
|
||||
if (base == MAP_FAILED) {
|
||||
LOGE("%s: failed to map pmem master fd: %s", pmemdev,
|
||||
strerror(deps.getErrno()));
|
||||
err = -deps.getErrno();
|
||||
base = 0;
|
||||
deps.close(fd);
|
||||
fd = -1;
|
||||
} else {
|
||||
master_fd = fd;
|
||||
master_base = base;
|
||||
}
|
||||
} else {
|
||||
LOGE("%s: failed to open pmem device: %s", pmemdev,
|
||||
strerror(deps.getErrno()));
|
||||
err = -deps.getErrno();
|
||||
}
|
||||
END_FUNC;
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
int PmemUserspaceAllocator::init_pmem_area()
|
||||
{
|
||||
BEGIN_FUNC;
|
||||
pthread_mutex_lock(&lock);
|
||||
int err = master_fd;
|
||||
if (err == MASTER_FD_INIT) {
|
||||
// first time, try to initialize pmem
|
||||
err = init_pmem_area_locked();
|
||||
if (err) {
|
||||
LOGE("%s: failed to initialize pmem area", pmemdev);
|
||||
master_fd = err;
|
||||
}
|
||||
} else if (err < 0) {
|
||||
// pmem couldn't be initialized, never use it
|
||||
} else {
|
||||
// pmem OK
|
||||
err = 0;
|
||||
}
|
||||
pthread_mutex_unlock(&lock);
|
||||
END_FUNC;
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
int PmemUserspaceAllocator::alloc_pmem_buffer(size_t size, int usage,
|
||||
void** pBase, int* pOffset, int* pFd, int format)
|
||||
{
|
||||
BEGIN_FUNC;
|
||||
int err = init_pmem_area();
|
||||
if (err == 0) {
|
||||
void* base = master_base;
|
||||
int offset = allocator.allocate(size);
|
||||
if (offset < 0) {
|
||||
// no more pmem memory
|
||||
LOGE("%s: no more pmem available", pmemdev);
|
||||
err = -ENOMEM;
|
||||
} else {
|
||||
int openFlags = get_open_flags(usage);
|
||||
|
||||
//LOGD("%s: allocating pmem at offset 0x%p", pmemdev, offset);
|
||||
|
||||
// now create the "sub-heap"
|
||||
int fd = deps.open(pmemdev, openFlags, 0);
|
||||
err = fd < 0 ? fd : 0;
|
||||
|
||||
// and connect to it
|
||||
if (err == 0)
|
||||
err = deps.connectPmem(fd, master_fd);
|
||||
|
||||
// and make it available to the client process
|
||||
if (err == 0)
|
||||
err = deps.mapPmem(fd, offset, size);
|
||||
|
||||
if (err < 0) {
|
||||
LOGE("%s: failed to initialize pmem sub-heap: %d", pmemdev,
|
||||
err);
|
||||
err = -deps.getErrno();
|
||||
deps.close(fd);
|
||||
allocator.deallocate(offset);
|
||||
fd = -1;
|
||||
} else {
|
||||
LOGV("%s: mapped fd %d at offset %d, size %d", pmemdev, fd, offset, size);
|
||||
memset((char*)base + offset, 0, size);
|
||||
//Clean cache before flushing to ensure pmem is properly flushed
|
||||
err = deps.cleanPmem(fd, (unsigned long) base + offset, offset, size);
|
||||
if (err < 0) {
|
||||
LOGE("cleanPmem failed: (%s)", strerror(deps.getErrno()));
|
||||
}
|
||||
#ifdef HOST
|
||||
cacheflush(intptr_t(base) + offset, intptr_t(base) + offset + size, 0);
|
||||
#endif
|
||||
*pBase = base;
|
||||
*pOffset = offset;
|
||||
*pFd = fd;
|
||||
}
|
||||
//LOGD_IF(!err, "%s: allocating pmem size=%d, offset=%d", pmemdev, size, offset);
|
||||
}
|
||||
}
|
||||
END_FUNC;
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
int PmemUserspaceAllocator::free_pmem_buffer(size_t size, void* base, int offset, int fd)
|
||||
{
|
||||
BEGIN_FUNC;
|
||||
int err = 0;
|
||||
if (fd >= 0) {
|
||||
int err = deps.unmapPmem(fd, offset, size);
|
||||
LOGE_IF(err<0, "PMEM_UNMAP failed (%s), fd=%d, sub.offset=%u, "
|
||||
"sub.size=%u", strerror(deps.getErrno()), fd, offset, size);
|
||||
if (err == 0) {
|
||||
// we can't deallocate the memory in case of UNMAP failure
|
||||
// because it would give that process access to someone else's
|
||||
// surfaces, which would be a security breach.
|
||||
allocator.deallocate(offset);
|
||||
}
|
||||
}
|
||||
END_FUNC;
|
||||
return err;
|
||||
}
|
||||
|
||||
PmemUserspaceAllocator::Deps::Allocator::~Allocator()
|
||||
{
|
||||
BEGIN_FUNC;
|
||||
END_FUNC;
|
||||
}
|
||||
|
||||
PmemUserspaceAllocator::Deps::~Deps()
|
||||
{
|
||||
BEGIN_FUNC;
|
||||
END_FUNC;
|
||||
}
|
||||
|
||||
PmemKernelAllocator::PmemKernelAllocator(Deps& deps):
|
||||
deps(deps)
|
||||
{
|
||||
BEGIN_FUNC;
|
||||
END_FUNC;
|
||||
}
|
||||
|
||||
|
||||
PmemKernelAllocator::~PmemKernelAllocator()
|
||||
{
|
||||
BEGIN_FUNC;
|
||||
END_FUNC;
|
||||
}
|
||||
|
||||
|
||||
void* PmemKernelAllocator::get_base_address() {
|
||||
BEGIN_FUNC;
|
||||
END_FUNC;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static unsigned clp2(unsigned x) {
|
||||
x = x - 1;
|
||||
x = x | (x >> 1);
|
||||
x = x | (x >> 2);
|
||||
x = x | (x >> 4);
|
||||
x = x | (x >> 8);
|
||||
x = x | (x >>16);
|
||||
return x + 1;
|
||||
}
|
||||
|
||||
|
||||
int PmemKernelAllocator::alloc_pmem_buffer(size_t size, int usage,
|
||||
void** pBase,int* pOffset, int* pFd, int format)
|
||||
{
|
||||
BEGIN_FUNC;
|
||||
|
||||
*pBase = 0;
|
||||
*pOffset = 0;
|
||||
*pFd = -1;
|
||||
|
||||
int err, offset = 0;
|
||||
int openFlags = get_open_flags(usage);
|
||||
const char *device;
|
||||
|
||||
if (usage & GRALLOC_USAGE_PRIVATE_ADSP_HEAP) {
|
||||
device = DEVICE_PMEM_ADSP;
|
||||
} else if (usage & GRALLOC_USAGE_PRIVATE_SMI_HEAP) {
|
||||
device = DEVICE_PMEM_SMIPOOL;
|
||||
} else if ((usage & GRALLOC_USAGE_EXTERNAL_DISP) ||
|
||||
(usage & GRALLOC_USAGE_PROTECTED)) {
|
||||
int tempFd = deps.open(DEVICE_PMEM_SMIPOOL, openFlags, 0);
|
||||
if (tempFd < 0) {
|
||||
device = DEVICE_PMEM_ADSP;
|
||||
} else {
|
||||
close(tempFd);
|
||||
device = DEVICE_PMEM_SMIPOOL;
|
||||
}
|
||||
} else {
|
||||
LOGE("Invalid device");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int fd = deps.open(device, openFlags, 0);
|
||||
if (fd < 0) {
|
||||
err = -deps.getErrno();
|
||||
END_FUNC;
|
||||
LOGE("Error opening %s", device);
|
||||
return err;
|
||||
}
|
||||
|
||||
// The size should already be page aligned, now round it up to a power of 2.
|
||||
//size = clp2(size);
|
||||
|
||||
if (format == HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED) {
|
||||
// Tile format buffers need physical alignment to 8K
|
||||
err = deps.alignPmem(fd, size, 8192);
|
||||
if (err < 0) {
|
||||
LOGE("alignPmem failed");
|
||||
}
|
||||
}
|
||||
|
||||
void* base = deps.mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
if (base == MAP_FAILED) {
|
||||
LOGE("%s: failed to map pmem fd: %s", device,
|
||||
strerror(deps.getErrno()));
|
||||
err = -deps.getErrno();
|
||||
deps.close(fd);
|
||||
END_FUNC;
|
||||
return err;
|
||||
}
|
||||
memset(base, 0, size);
|
||||
|
||||
*pBase = base;
|
||||
*pOffset = 0;
|
||||
*pFd = fd;
|
||||
|
||||
END_FUNC;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int PmemKernelAllocator::free_pmem_buffer(size_t size, void* base, int offset, int fd)
|
||||
{
|
||||
BEGIN_FUNC;
|
||||
// The size should already be page aligned, now round it up to a power of 2
|
||||
// like we did when allocating.
|
||||
//size = clp2(size);
|
||||
|
||||
int err = deps.munmap(base, size);
|
||||
if (err < 0) {
|
||||
err = deps.getErrno();
|
||||
LOGW("error unmapping pmem fd: %s", strerror(err));
|
||||
return -err;
|
||||
}
|
||||
|
||||
END_FUNC;
|
||||
return 0;
|
||||
}
|
||||
|
||||
PmemKernelAllocator::Deps::~Deps()
|
||||
{
|
||||
BEGIN_FUNC;
|
||||
END_FUNC;
|
||||
}
|
161
libgralloc-qsd8k/pmemalloc.h
Executable file
161
libgralloc-qsd8k/pmemalloc.h
Executable file
@ -0,0 +1,161 @@
|
||||
/*
|
||||
* Copyright (C) 2010 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef GRALLOC_QSD8K_PMEMALLOC_H
|
||||
#define GRALLOC_QSD8K_PMEMALLOC_H
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
/**
|
||||
* An interface to the PMEM allocators.
|
||||
*/
|
||||
class PmemAllocator {
|
||||
|
||||
public:
|
||||
|
||||
virtual ~PmemAllocator();
|
||||
|
||||
// Only valid after init_pmem_area() has completed successfully.
|
||||
virtual void* get_base_address() = 0;
|
||||
|
||||
virtual int alloc_pmem_buffer(size_t size, int usage, void** pBase,
|
||||
int* pOffset, int* pFd, int format) = 0;
|
||||
virtual int free_pmem_buffer(size_t size, void* base, int offset, int fd) = 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A PMEM allocator that allocates the entire pmem memory from the kernel and
|
||||
* then uses a user-space allocator to suballocate from that. This requires
|
||||
* that the PMEM device driver have kernel allocation disabled.
|
||||
*/
|
||||
class PmemUserspaceAllocator: public PmemAllocator {
|
||||
|
||||
public:
|
||||
|
||||
class Deps {
|
||||
public:
|
||||
|
||||
class Allocator {
|
||||
public:
|
||||
virtual ~Allocator();
|
||||
virtual ssize_t setSize(size_t size) = 0;
|
||||
virtual size_t size() const = 0;
|
||||
virtual ssize_t allocate(size_t size, uint32_t flags = 0) = 0;
|
||||
virtual ssize_t deallocate(size_t offset) = 0;
|
||||
};
|
||||
|
||||
virtual ~Deps();
|
||||
|
||||
// pmem
|
||||
virtual size_t getPmemTotalSize(int fd, size_t* size) = 0;
|
||||
virtual int connectPmem(int fd, int master_fd) = 0;
|
||||
virtual int mapPmem(int fd, int offset, size_t size) = 0;
|
||||
virtual int unmapPmem(int fd, int offset, size_t size) = 0;
|
||||
virtual int cleanPmem(int fd, unsigned long base, int offset, size_t size) = 0;
|
||||
|
||||
// C99
|
||||
virtual int getErrno() = 0;
|
||||
|
||||
// POSIX
|
||||
virtual void* mmap(void* start, size_t length, int prot, int flags, int fd,
|
||||
off_t offset) = 0;
|
||||
virtual int open(const char* pathname, int flags, int mode) = 0;
|
||||
virtual int close(int fd) = 0;
|
||||
};
|
||||
|
||||
PmemUserspaceAllocator(Deps& deps, Deps::Allocator& allocator, const char* pmemdev);
|
||||
virtual ~PmemUserspaceAllocator();
|
||||
|
||||
// Only valid after init_pmem_area() has completed successfully.
|
||||
virtual void* get_base_address();
|
||||
|
||||
virtual int init_pmem_area_locked();
|
||||
virtual int init_pmem_area();
|
||||
virtual int alloc_pmem_buffer(size_t size, int usage, void** pBase,
|
||||
int* pOffset, int* pFd, int format);
|
||||
virtual int free_pmem_buffer(size_t size, void* base, int offset, int fd);
|
||||
|
||||
#ifndef ANDROID_OS
|
||||
// DO NOT USE: For testing purposes only.
|
||||
void set_master_values(int fd, void* base) {
|
||||
master_fd = fd;
|
||||
master_base = base;
|
||||
}
|
||||
#endif // ANDROID_OS
|
||||
|
||||
private:
|
||||
|
||||
enum {
|
||||
MASTER_FD_INIT = -1,
|
||||
};
|
||||
|
||||
Deps& deps;
|
||||
Deps::Allocator& allocator;
|
||||
|
||||
pthread_mutex_t lock;
|
||||
const char* pmemdev;
|
||||
int master_fd;
|
||||
void* master_base;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A PMEM allocator that allocates each individual allocation from the kernel
|
||||
* (using the kernel's allocator). This requires the kernel driver for the
|
||||
* particular PMEM device being allocated from to support kernel allocation.
|
||||
*/
|
||||
class PmemKernelAllocator: public PmemAllocator {
|
||||
|
||||
public:
|
||||
|
||||
class Deps {
|
||||
public:
|
||||
|
||||
virtual ~Deps();
|
||||
|
||||
// C99
|
||||
virtual int getErrno() = 0;
|
||||
|
||||
// POSIX
|
||||
virtual void* mmap(void* start, size_t length, int prot, int flags, int fd,
|
||||
off_t offset) = 0;
|
||||
virtual int munmap(void* start, size_t length) = 0;
|
||||
virtual int open(const char* pathname, int flags, int mode) = 0;
|
||||
virtual int close(int fd) = 0;
|
||||
virtual int alignPmem(int fd, size_t size, int align) = 0;
|
||||
};
|
||||
|
||||
PmemKernelAllocator(Deps& deps);
|
||||
virtual ~PmemKernelAllocator();
|
||||
|
||||
// Only valid after init_pmem_area() has completed successfully.
|
||||
virtual void* get_base_address();
|
||||
|
||||
virtual int alloc_pmem_buffer(size_t size, int usage, void** pBase,
|
||||
int* pOffset, int* pFd, int format);
|
||||
virtual int free_pmem_buffer(size_t size, void* base, int offset, int fd);
|
||||
|
||||
private:
|
||||
|
||||
Deps& deps;
|
||||
};
|
||||
|
||||
#endif // GRALLOC_QSD8K_PMEMALLOC_H
|
55
libgralloc-qsd8k/tests/Android.mk
Normal file
55
libgralloc-qsd8k/tests/Android.mk
Normal file
@ -0,0 +1,55 @@
|
||||
# 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)
|
||||
|
||||
# you can use EXTRA_CFLAGS to indicate additional CFLAGS to use
|
||||
# in the build. The variables will be cleaned on exit
|
||||
#
|
||||
#
|
||||
|
||||
libgralloc_test_includes:= \
|
||||
bionic/libstdc++/include \
|
||||
external/astl/include \
|
||||
external/gtest/include \
|
||||
$(LOCAL_PATH)/..
|
||||
|
||||
libgralloc_test_static_libs := \
|
||||
libgralloc_qsd8k_host \
|
||||
libgtest_main_host \
|
||||
libgtest_host \
|
||||
libastl_host \
|
||||
liblog
|
||||
|
||||
define host-test
|
||||
$(foreach file,$(1), \
|
||||
$(eval include $(CLEAR_VARS)) \
|
||||
$(eval LOCAL_CPP_EXTENSION := .cpp) \
|
||||
$(eval LOCAL_SRC_FILES := $(file)) \
|
||||
$(eval LOCAL_C_INCLUDES := $(libgralloc_test_includes)) \
|
||||
$(eval LOCAL_MODULE := $(notdir $(file:%.cpp=%))) \
|
||||
$(eval LOCAL_CFLAGS += $(EXTRA_CFLAGS)) \
|
||||
$(eval LOCAL_LDLIBS += $(EXTRA_LDLIBS)) \
|
||||
$(eval LOCAL_STATIC_LIBRARIES := $(libgralloc_test_static_libs)) \
|
||||
$(eval LOCAL_MODULE_TAGS := eng tests) \
|
||||
$(eval include $(BUILD_HOST_EXECUTABLE)) \
|
||||
) \
|
||||
$(eval EXTRA_CFLAGS :=) \
|
||||
$(eval EXTRA_LDLIBS :=)
|
||||
endef
|
||||
|
||||
TEST_SRC_FILES := \
|
||||
pmemalloc_test.cpp
|
||||
|
||||
$(call host-test, $(TEST_SRC_FILES))
|
601
libgralloc-qsd8k/tests/pmemalloc_test.cpp
Normal file
601
libgralloc-qsd8k/tests/pmemalloc_test.cpp
Normal file
@ -0,0 +1,601 @@
|
||||
/*
|
||||
* Copyright (C) 2010 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include "pmemalloc.h"
|
||||
|
||||
class DepsStub : public PmemUserspaceAllocator::Deps, public PmemKernelAllocator::Deps {
|
||||
|
||||
public:
|
||||
|
||||
virtual size_t getPmemTotalSize(int fd, size_t* size) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual int connectPmem(int fd, int master_fd) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual int mapPmem(int fd, int offset, size_t size) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual int unmapPmem(int fd, int offset, size_t size) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual int getErrno() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual void* mmap(void* start, size_t length, int prot, int flags, int fd,
|
||||
off_t offset) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual int munmap(void* start, size_t length) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual int open(const char* pathname, int flags, int mode) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual int close(int fd) {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
class AllocatorStub : public PmemUserspaceAllocator::Deps::Allocator {
|
||||
virtual ssize_t setSize(size_t size) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual size_t size() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual ssize_t allocate(size_t size, uint32_t flags = 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual ssize_t deallocate(size_t offset) {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
static const char* fakePmemDev = "/foo/bar";
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
struct Deps_InitPmemAreaLockedWithSuccessfulCompletion : public DepsStub {
|
||||
|
||||
virtual int open(const char* pathname, int flags, int mode) {
|
||||
EXPECT_EQ(fakePmemDev, pathname);
|
||||
EXPECT_EQ(O_RDWR, flags);
|
||||
EXPECT_EQ(0, mode);
|
||||
return 1234;
|
||||
}
|
||||
|
||||
virtual size_t getPmemTotalSize(int fd, size_t* size) {
|
||||
EXPECT_EQ(1234, fd);
|
||||
*size = 16 << 20;
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual void* mmap(void* start, size_t length, int prot, int flags, int fd,
|
||||
off_t offset) {
|
||||
EXPECT_EQ(1234, fd);
|
||||
return (void*)0x87654321;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
struct Allocator_InitPmemAreaLockedWithSuccessfulCompletion : public AllocatorStub {
|
||||
|
||||
virtual ssize_t setSize(size_t size) {
|
||||
EXPECT_EQ(size_t(16 << 20), size);
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
TEST(test_pmem_userspace_allocator, testInitPmemAreaLockedWithSuccessfulCompletion) {
|
||||
Deps_InitPmemAreaLockedWithSuccessfulCompletion depsMock;
|
||||
Allocator_InitPmemAreaLockedWithSuccessfulCompletion allocMock;
|
||||
PmemUserspaceAllocator pma(depsMock, allocMock, fakePmemDev);
|
||||
|
||||
int result = pma.init_pmem_area_locked();
|
||||
ASSERT_EQ(0, result);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
struct Deps_InitPmemAreaLockedWithEnomemOnMmap : public DepsStub {
|
||||
|
||||
virtual int open(const char* pathname, int flags, int mode) {
|
||||
EXPECT_EQ(fakePmemDev, pathname);
|
||||
EXPECT_EQ(O_RDWR, flags);
|
||||
EXPECT_EQ(0, mode);
|
||||
return 1234;
|
||||
}
|
||||
|
||||
virtual size_t getPmemTotalSize(int fd, size_t* size) {
|
||||
EXPECT_EQ(1234, fd);
|
||||
*size = 16 << 20;
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual int getErrno() {
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
virtual void* mmap(void* start, size_t length, int prot, int flags, int fd,
|
||||
off_t offset) {
|
||||
return (void*)MAP_FAILED;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
struct Allocator_InitPmemAreaLockedWithEnomemOnMmap : public AllocatorStub {
|
||||
|
||||
virtual ssize_t setSize(size_t size) {
|
||||
EXPECT_EQ(size_t(16 << 20), size);
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
TEST(test_pmem_userspace_allocator, testInitPmemAreaLockedWthEnomemOnMmap) {
|
||||
Deps_InitPmemAreaLockedWithEnomemOnMmap depsMock;
|
||||
Allocator_InitPmemAreaLockedWithEnomemOnMmap allocMock;
|
||||
PmemUserspaceAllocator pma(depsMock, allocMock, fakePmemDev);
|
||||
|
||||
int result = pma.init_pmem_area_locked();
|
||||
ASSERT_EQ(-ENOMEM, result);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
struct Deps_InitPmemAreaLockedWithEaccesOnGetPmemTotalSize : public DepsStub {
|
||||
|
||||
virtual int open(const char* pathname, int flags, int mode) {
|
||||
EXPECT_EQ(fakePmemDev, pathname);
|
||||
EXPECT_EQ(O_RDWR, flags);
|
||||
EXPECT_EQ(0, mode);
|
||||
return 1234;
|
||||
}
|
||||
|
||||
virtual size_t getPmemTotalSize(int fd, size_t* size) {
|
||||
EXPECT_EQ(1234, fd);
|
||||
return -EACCES;
|
||||
}
|
||||
};
|
||||
|
||||
TEST(test_pmem_userspace_allocator, testInitPmemAreaLockedWthEaccesOnGetPmemTotalSize) {
|
||||
Deps_InitPmemAreaLockedWithEaccesOnGetPmemTotalSize depsMock;
|
||||
AllocatorStub allocStub;
|
||||
PmemUserspaceAllocator pma(depsMock, allocStub, fakePmemDev);
|
||||
|
||||
int result = pma.init_pmem_area_locked();
|
||||
ASSERT_EQ(-EACCES, result);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
struct Deps_InitPmemAreaLockedWithEaccesOnOpen : public DepsStub {
|
||||
|
||||
virtual int getErrno() {
|
||||
return EACCES;
|
||||
}
|
||||
|
||||
virtual int open(const char* pathname, int flags, int mode) {
|
||||
EXPECT_EQ(fakePmemDev, pathname);
|
||||
EXPECT_EQ(O_RDWR, flags);
|
||||
EXPECT_EQ(0, mode);
|
||||
return -1;
|
||||
}
|
||||
};
|
||||
|
||||
TEST(test_pmem_userspace_allocator, testInitPmemAreaLockedWithEaccesOnOpenMaster) {
|
||||
Deps_InitPmemAreaLockedWithEaccesOnOpen depsMock;
|
||||
AllocatorStub allocStub;
|
||||
PmemUserspaceAllocator pma(depsMock, allocStub, fakePmemDev);
|
||||
|
||||
int result = pma.init_pmem_area_locked();
|
||||
ASSERT_EQ(-EACCES, result);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
typedef Deps_InitPmemAreaLockedWithSuccessfulCompletion Deps_InitPmemAreaWithSuccessfulInitialCompletion;
|
||||
|
||||
TEST(test_pmem_userspace_allocator, testInitPmemAreaWithSuccessfulInitialCompletion) {
|
||||
Deps_InitPmemAreaWithSuccessfulInitialCompletion depsMock;
|
||||
AllocatorStub allocStub;
|
||||
PmemUserspaceAllocator pma(depsMock, allocStub, fakePmemDev);
|
||||
|
||||
int result = pma.init_pmem_area();
|
||||
ASSERT_EQ(0, result);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
typedef Deps_InitPmemAreaLockedWithEaccesOnOpen Deps_InitPmemAreaWithEaccesOnInitLocked;
|
||||
|
||||
TEST(test_pmem_userspace_allocator, testInitPmemAreaWithEaccesOnInitLocked) {
|
||||
Deps_InitPmemAreaWithEaccesOnInitLocked depsMock;
|
||||
AllocatorStub allocStub;
|
||||
PmemUserspaceAllocator pma(depsMock, allocStub, fakePmemDev);
|
||||
|
||||
int result = pma.init_pmem_area();
|
||||
ASSERT_EQ(-EACCES, result);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
TEST(test_pmem_userspace_allocator, testInitPmemAreaAfterSuccessfulInitialCompletion) {
|
||||
DepsStub depsStub;
|
||||
AllocatorStub allocStub;
|
||||
PmemUserspaceAllocator pma(depsStub, allocStub, fakePmemDev);
|
||||
|
||||
pma.set_master_values(1234, 0); // Indicate that the pma has been successfully init'd
|
||||
|
||||
int result = pma.init_pmem_area();
|
||||
ASSERT_EQ(0, result);
|
||||
//XXX JMG: Add this back in maybe? ASSERT_EQ(1234, pmi.master); // Make sure the master fd wasn't changed
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
TEST(test_pmem_userspace_allocator, testInitPmemAreaAfterFailedInit) {
|
||||
DepsStub depsStub;
|
||||
AllocatorStub allocStub;
|
||||
PmemUserspaceAllocator pma(depsStub, allocStub, fakePmemDev);
|
||||
|
||||
pma.set_master_values(-EACCES, 0); // Indicate that the pma has failed init
|
||||
|
||||
int result = pma.init_pmem_area();
|
||||
ASSERT_EQ(-EACCES, result);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
struct Deps_InitPmemAreaLockedWithSuccessfulCompletionWithNoFlags : public DepsStub {
|
||||
|
||||
virtual int open(const char* pathname, int flags, int mode) {
|
||||
EXPECT_EQ(fakePmemDev, pathname);
|
||||
EXPECT_EQ(O_RDWR, flags & O_RDWR);
|
||||
EXPECT_EQ(0, mode);
|
||||
return 5678;
|
||||
}
|
||||
|
||||
virtual int connectPmem(int fd, int master_fd) {
|
||||
EXPECT_EQ(5678, fd);
|
||||
EXPECT_EQ(1234, master_fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual int mapPmem(int fd, int offset, size_t size) {
|
||||
EXPECT_EQ(5678, fd);
|
||||
EXPECT_EQ(0x300, offset);
|
||||
EXPECT_EQ(size_t(0x100), size);
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct Allocator_AllocPmemBufferWithSuccessfulCompletionWithNoFlags : public AllocatorStub {
|
||||
|
||||
virtual ssize_t allocate(size_t size, uint32_t flags = 0) {
|
||||
EXPECT_EQ(size_t(0x100), size);
|
||||
EXPECT_EQ(uint32_t(0x0), flags);
|
||||
return 0x300;
|
||||
}
|
||||
};
|
||||
|
||||
TEST(test_pmem_userspace_allocator, testAllocPmemBufferWithSuccessfulCompletionWithNoFlags) {
|
||||
Deps_InitPmemAreaLockedWithSuccessfulCompletionWithNoFlags depsMock;
|
||||
Allocator_AllocPmemBufferWithSuccessfulCompletionWithNoFlags allocMock;
|
||||
PmemUserspaceAllocator pma(depsMock, allocMock, fakePmemDev);
|
||||
|
||||
uint8_t buf[0x300 + 0x100]; // Create a buffer to get memzero'd
|
||||
pma.set_master_values(1234, buf); // Indicate that the pma has been successfully init'd
|
||||
|
||||
void* base = 0;
|
||||
int offset = -9182, fd = -9182;
|
||||
int size = 0x100;
|
||||
int flags = 0;
|
||||
int result = pma.alloc_pmem_buffer(size, flags, &base, &offset, &fd);
|
||||
ASSERT_EQ(0, result);
|
||||
ASSERT_EQ(0x300, offset);
|
||||
ASSERT_EQ(5678, fd);
|
||||
for (int i = 0x300; i < 0x400; ++i) {
|
||||
ASSERT_EQ(uint8_t(0), buf[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
typedef Deps_InitPmemAreaLockedWithSuccessfulCompletionWithNoFlags Deps_InitPmemAreaLockedWithSuccessfulCompletionWithAllFlags;
|
||||
|
||||
typedef Allocator_AllocPmemBufferWithSuccessfulCompletionWithNoFlags Allocator_AllocPmemBufferWithSuccessfulCompletionWithAllFlags;
|
||||
|
||||
TEST(test_pmem_userspace_allocator, testAllocPmemBufferWithSuccessfulCompletionWithAllFlags) {
|
||||
Deps_InitPmemAreaLockedWithSuccessfulCompletionWithAllFlags depsMock;
|
||||
Allocator_AllocPmemBufferWithSuccessfulCompletionWithAllFlags allocMock;
|
||||
PmemUserspaceAllocator pma(depsMock, allocMock, fakePmemDev);
|
||||
|
||||
uint8_t buf[0x300 + 0x100]; // Create a buffer to get memzero'd
|
||||
pma.set_master_values(1234, buf); // Indicate that the pma has been successfully init'd
|
||||
|
||||
void* base = 0;
|
||||
int offset = -9182, fd = -9182;
|
||||
int size = 0x100;
|
||||
int flags = ~0;
|
||||
int result = pma.alloc_pmem_buffer(size, flags, &base, &offset, &fd);
|
||||
ASSERT_EQ(0, result);
|
||||
ASSERT_EQ(0x300, offset);
|
||||
ASSERT_EQ(5678, fd);
|
||||
for (int i = 0x300; i < 0x400; ++i) {
|
||||
ASSERT_EQ(0, buf[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
struct Deps_InitPmemAreaLockedWithEnodevOnOpen : public Deps_InitPmemAreaLockedWithSuccessfulCompletionWithNoFlags {
|
||||
|
||||
virtual int getErrno() {
|
||||
return ENODEV;
|
||||
}
|
||||
|
||||
virtual int open(const char* pathname, int flags, int mode) {
|
||||
EXPECT_EQ(fakePmemDev, pathname);
|
||||
EXPECT_EQ(O_RDWR, flags & O_RDWR);
|
||||
EXPECT_EQ(0, mode);
|
||||
return -1;
|
||||
}
|
||||
};
|
||||
|
||||
typedef Allocator_AllocPmemBufferWithSuccessfulCompletionWithNoFlags Allocator_AllocPmemBufferWithEnodevOnOpen;
|
||||
|
||||
TEST(test_pmem_userspace_allocator, testAllocPmemBufferWithSuccessfulCompletionWithEnodevOnOpen) {
|
||||
Deps_InitPmemAreaLockedWithEnodevOnOpen depsMock;
|
||||
Allocator_AllocPmemBufferWithEnodevOnOpen allocMock;
|
||||
PmemUserspaceAllocator pma(depsMock, allocMock, fakePmemDev);
|
||||
|
||||
uint8_t buf[0x300 + 0x100]; // Create a buffer to get memzero'd
|
||||
pma.set_master_values(1234, buf); // Indicate that the pma has been successfully init'd
|
||||
|
||||
void* base = 0;
|
||||
int offset = -9182, fd = -9182;
|
||||
int size = 0x100;
|
||||
int flags = ~0;
|
||||
int result = pma.alloc_pmem_buffer(size, flags, &base, &offset, &fd);
|
||||
ASSERT_EQ(-ENODEV, result);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
struct Deps_InitPmemAreaLockedWithEnomemOnConnectPmem : public Deps_InitPmemAreaLockedWithSuccessfulCompletionWithNoFlags {
|
||||
|
||||
virtual int getErrno() {
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
virtual int connectPmem(int fd, int master_fd) {
|
||||
EXPECT_EQ(5678, fd);
|
||||
EXPECT_EQ(1234, master_fd);
|
||||
return -1;
|
||||
}
|
||||
};
|
||||
|
||||
typedef Allocator_AllocPmemBufferWithSuccessfulCompletionWithNoFlags Allocator_AllocPmemBufferWithEnomemOnConnectPmem;
|
||||
|
||||
TEST(test_pmem_userspace_allocator, testAllocPmemBufferWithSuccessfulCompletionWithEnomemOnConnectPmem) {
|
||||
Deps_InitPmemAreaLockedWithEnomemOnConnectPmem depsMock;
|
||||
Allocator_AllocPmemBufferWithEnomemOnConnectPmem allocMock;
|
||||
PmemUserspaceAllocator pma(depsMock, allocMock, fakePmemDev);
|
||||
|
||||
uint8_t buf[0x300 + 0x100]; // Create a buffer to get memzero'd
|
||||
pma.set_master_values(1234, buf); // Indicate that the pma has been successfully init'd
|
||||
|
||||
void* base = 0;
|
||||
int offset = -9182, fd = -9182;
|
||||
int size = 0x100;
|
||||
int flags = ~0;
|
||||
int result = pma.alloc_pmem_buffer(size, flags, &base, &offset, &fd);
|
||||
ASSERT_EQ(-ENOMEM, result);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
struct Deps_InitPmemAreaLockedWithEnomemOnMapPmem : public Deps_InitPmemAreaLockedWithSuccessfulCompletionWithNoFlags {
|
||||
|
||||
virtual int getErrno() {
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
virtual int mapPmem(int fd, int offset, size_t size) {
|
||||
EXPECT_EQ(5678, fd);
|
||||
EXPECT_EQ(0x300, offset);
|
||||
EXPECT_EQ(size_t(0x100), size);
|
||||
return -1;
|
||||
}
|
||||
};
|
||||
|
||||
typedef Allocator_AllocPmemBufferWithSuccessfulCompletionWithNoFlags Allocator_AllocPmemBufferWithEnomemOnMapPmem;
|
||||
|
||||
TEST(test_pmem_userspace_allocator, testAllocPmemBufferWithEnomemOnMapPmem) {
|
||||
Deps_InitPmemAreaLockedWithEnomemOnMapPmem depsMock;
|
||||
Allocator_AllocPmemBufferWithEnomemOnMapPmem allocMock;
|
||||
PmemUserspaceAllocator pma(depsMock, allocMock, fakePmemDev);
|
||||
|
||||
uint8_t buf[0x300 + 0x100]; // Create a buffer to get memzero'd
|
||||
pma.set_master_values(1234, buf); // Indicate that the pma has been successfully init'd
|
||||
|
||||
void* base = 0;
|
||||
int offset = -9182, fd = -9182;
|
||||
int size = 0x100;
|
||||
int flags = ~0;
|
||||
int result = pma.alloc_pmem_buffer(size, flags, &base, &offset, &fd);
|
||||
ASSERT_EQ(-ENOMEM, result);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
struct Deps_KernelAllocPmemBufferWithSuccessfulCompletionWithNoFlags : public DepsStub {
|
||||
|
||||
void* mmapResult;
|
||||
|
||||
Deps_KernelAllocPmemBufferWithSuccessfulCompletionWithNoFlags(void* mmapResult) :
|
||||
mmapResult(mmapResult) {}
|
||||
|
||||
virtual int open(const char* pathname, int flags, int mode) {
|
||||
EXPECT_EQ(fakePmemDev, pathname);
|
||||
EXPECT_EQ(O_RDWR, flags & O_RDWR);
|
||||
EXPECT_EQ(0, mode);
|
||||
return 5678;
|
||||
}
|
||||
|
||||
virtual void* mmap(void* start, size_t length, int prot, int flags, int fd,
|
||||
off_t offset) {
|
||||
EXPECT_EQ(5678, fd);
|
||||
return mmapResult;
|
||||
}
|
||||
};
|
||||
|
||||
TEST(test_pmem_kernel_allocator, testAllocPmemBufferWithSuccessfulCompletionWithNoFlags) {
|
||||
uint8_t buf[0x100]; // Create a buffer to get memzero'd
|
||||
Deps_KernelAllocPmemBufferWithSuccessfulCompletionWithNoFlags depsMock(buf);
|
||||
PmemKernelAllocator pma(depsMock, fakePmemDev);
|
||||
|
||||
void* base = 0;
|
||||
int offset = -9182, fd = -9182;
|
||||
int size = 0x100;
|
||||
int flags = 0;
|
||||
int result = pma.alloc_pmem_buffer(size, flags, &base, &offset, &fd);
|
||||
ASSERT_EQ(0, result);
|
||||
ASSERT_EQ(buf, base);
|
||||
ASSERT_EQ(0, offset);
|
||||
ASSERT_EQ(5678, fd);
|
||||
for (int i = 0; i < 0x100; ++i) {
|
||||
ASSERT_EQ(0, buf[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
typedef Deps_KernelAllocPmemBufferWithSuccessfulCompletionWithNoFlags Deps_KernelAllocPmemBufferWithSuccessfulCompletionWithAllFlags;
|
||||
|
||||
TEST(test_pmem_kernel_allocator, testAllocPmemBufferWithSuccessfulCompletionWithAllFlags) {
|
||||
uint8_t buf[0x100]; // Create a buffer to get memzero'd
|
||||
Deps_KernelAllocPmemBufferWithSuccessfulCompletionWithAllFlags depsMock(buf);
|
||||
PmemKernelAllocator pma(depsMock, fakePmemDev);
|
||||
|
||||
void* base = 0;
|
||||
int offset = -9182, fd = -9182;
|
||||
int size = 0x100;
|
||||
int flags = ~0;
|
||||
int result = pma.alloc_pmem_buffer(size, flags, &base, &offset, &fd);
|
||||
ASSERT_EQ(0, result);
|
||||
ASSERT_EQ(buf, base);
|
||||
ASSERT_EQ(0, offset);
|
||||
ASSERT_EQ(5678, fd);
|
||||
for (int i = 0; i < 0x100; ++i) {
|
||||
ASSERT_EQ(0, buf[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
struct Deps_KernelAllocPmemBufferWithEpermOnOpen : public DepsStub {
|
||||
|
||||
virtual int getErrno() {
|
||||
return EPERM;
|
||||
}
|
||||
|
||||
virtual int open(const char* pathname, int flags, int mode) {
|
||||
EXPECT_EQ(fakePmemDev, pathname);
|
||||
EXPECT_EQ(O_RDWR, flags & O_RDWR);
|
||||
EXPECT_EQ(0, mode);
|
||||
return -1;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
TEST(test_pmem_kernel_allocator, testAllocPmemBufferWithEpermOnOpen) {
|
||||
Deps_KernelAllocPmemBufferWithEpermOnOpen depsMock;
|
||||
PmemKernelAllocator pma(depsMock, fakePmemDev);
|
||||
|
||||
void* base = 0;
|
||||
int offset = -9182, fd = -9182;
|
||||
int size = 0x100;
|
||||
int flags = ~0;
|
||||
int result = pma.alloc_pmem_buffer(size, flags, &base, &offset, &fd);
|
||||
ASSERT_EQ(-EPERM, result);
|
||||
ASSERT_EQ(0, base);
|
||||
ASSERT_EQ(0, offset);
|
||||
ASSERT_EQ(-1, fd);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
struct Deps_KernelAllocPmemBufferWithEnomemOnMmap : DepsStub {
|
||||
|
||||
virtual int open(const char* pathname, int flags, int mode) {
|
||||
EXPECT_EQ(fakePmemDev, pathname);
|
||||
EXPECT_EQ(O_RDWR, flags & O_RDWR);
|
||||
EXPECT_EQ(0, mode);
|
||||
return 5678;
|
||||
}
|
||||
|
||||
virtual void* mmap(void* start, size_t length, int prot, int flags, int fd,
|
||||
off_t offset) {
|
||||
return (void*)MAP_FAILED;
|
||||
}
|
||||
|
||||
virtual int getErrno() {
|
||||
return ENOMEM;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
TEST(test_pmem_kernel_allocator, testAllocPmemBufferWithEnomemOnMmap) {
|
||||
Deps_KernelAllocPmemBufferWithEnomemOnMmap depsMock;
|
||||
PmemKernelAllocator pma(depsMock, fakePmemDev);
|
||||
|
||||
void* base = 0;
|
||||
int offset = -9182, fd = -9182;
|
||||
int size = 0x100;
|
||||
int flags = ~0;
|
||||
int result = pma.alloc_pmem_buffer(size, flags, &base, &offset, &fd);
|
||||
ASSERT_EQ(-ENOMEM, result);
|
||||
ASSERT_EQ(0, base);
|
||||
ASSERT_EQ(0, offset);
|
||||
ASSERT_EQ(-1, fd);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
28
libhwcomposer/Android.mk
Normal file
28
libhwcomposer/Android.mk
Normal file
@ -0,0 +1,28 @@
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
# HAL module implemenation, not prelinked and stored in
|
||||
# hw/<OVERLAY_HARDWARE_MODULE_ID>.<ro.product.board>.so
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_PRELINK_MODULE := false
|
||||
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
|
||||
LOCAL_SHARED_LIBRARIES := liblog libcutils libEGL libhardware libutils liboverlay
|
||||
|
||||
LOCAL_SRC_FILES := \
|
||||
hwcomposer.cpp
|
||||
|
||||
LOCAL_MODULE := hwcomposer.$(TARGET_BOARD_PLATFORM)
|
||||
LOCAL_CFLAGS:= -DLOG_TAG=\"$(TARGET_BOARD_PLATFORM).hwcomposer\"
|
||||
LOCAL_C_INCLUDES += hardware/qcom/display/libgralloc
|
||||
LOCAL_C_INCLUDES += hardware/msm7k/liboverlay
|
||||
LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
|
||||
LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
|
||||
ifeq ($(TARGET_HAVE_HDMI_OUT),true)
|
||||
LOCAL_CFLAGS += -DHDMI_DUAL_DISPLAY
|
||||
endif
|
||||
ifeq ($(TARGET_HAVE_BYPASS),true)
|
||||
LOCAL_CFLAGS += -DCOMPOSITION_BYPASS
|
||||
endif
|
||||
ifeq ($(TARGET_USE_HDMI_AS_PRIMARY),true)
|
||||
LOCAL_CFLAGS += -DHDMI_AS_PRIMARY
|
||||
endif
|
||||
include $(BUILD_SHARED_LIBRARY)
|
1162
libhwcomposer/hwcomposer.cpp
Normal file
1162
libhwcomposer/hwcomposer.cpp
Normal file
File diff suppressed because it is too large
Load Diff
53
liboverlay/Android.mk
Normal file
53
liboverlay/Android.mk
Normal file
@ -0,0 +1,53 @@
|
||||
# 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
|
||||
#
|
||||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_PRELINK_MODULE := false
|
||||
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)
|
||||
LOCAL_SHARED_LIBRARIES := liblog libcutils libutils
|
||||
LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
|
||||
LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
|
||||
LOCAL_C_INCLUDES += hardware/qcom/display/libgralloc
|
||||
LOCAL_SRC_FILES := \
|
||||
overlayLib.cpp \
|
||||
overlayLibUI.cpp \
|
||||
LOCAL_CFLAGS:= -DLOG_TAG=\"OverlayLib\"
|
||||
|
||||
ifeq ($(TARGET_USES_ION),true)
|
||||
LOCAL_CFLAGS += -DUSE_ION
|
||||
LOCAL_SHARED_LIBRARIES += libmemalloc
|
||||
endif
|
||||
|
||||
ifeq ($(TARGET_USE_HDMI_AS_PRIMARY),true)
|
||||
LOCAL_CFLAGS += -DHDMI_AS_PRIMARY
|
||||
endif
|
||||
LOCAL_MODULE := liboverlay
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
||||
# HAL module implemenation, not prelinked and stored in
|
||||
# hw/<OVERLAY_HARDWARE_MODULE_ID>.<ro.product.board>.so
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_PRELINK_MODULE := false
|
||||
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
|
||||
LOCAL_SHARED_LIBRARIES := liblog liboverlay libcutils
|
||||
LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
|
||||
LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
|
||||
LOCAL_C_INCLUDES += hardware/qcom/display/libgralloc
|
||||
LOCAL_SRC_FILES := overlay.cpp
|
||||
LOCAL_MODULE := overlay.default
|
||||
include $(BUILD_SHARED_LIBRARY)
|
1197
liboverlay/overlay.cpp
Normal file
1197
liboverlay/overlay.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1799
liboverlay/overlayLib.cpp
Normal file
1799
liboverlay/overlayLib.cpp
Normal file
File diff suppressed because it is too large
Load Diff
306
liboverlay/overlayLib.h
Normal file
306
liboverlay/overlayLib.h
Normal file
@ -0,0 +1,306 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#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 <hardware/overlay.h>
|
||||
#include <utils/RefBase.h>
|
||||
#include <alloc_controller.h>
|
||||
#include <memalloc.h>
|
||||
|
||||
#define HW_OVERLAY_MAGNIFICATION_LIMIT 8
|
||||
#define HW_OVERLAY_MINIFICATION_LIMIT HW_OVERLAY_MAGNIFICATION_LIMIT
|
||||
|
||||
#define EVEN_OUT(x) if (x & 0x0001) {x--;}
|
||||
#define VG0_PIPE 0
|
||||
#define VG1_PIPE 1
|
||||
#define NUM_CHANNELS 2
|
||||
#define FRAMEBUFFER_0 0
|
||||
#define FRAMEBUFFER_1 1
|
||||
|
||||
enum {
|
||||
HDMI_OFF,
|
||||
HDMI_ON
|
||||
};
|
||||
|
||||
enum {
|
||||
OVERLAY_CHANNEL_DOWN,
|
||||
OVERLAY_CHANNEL_UP
|
||||
};
|
||||
|
||||
enum {
|
||||
NEW_REQUEST,
|
||||
UPDATE_REQUEST
|
||||
};
|
||||
/* ------------------------------- 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;
|
||||
};
|
||||
|
||||
namespace overlay {
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
/* 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);
|
||||
|
||||
const int max_num_buffers = 3;
|
||||
typedef struct mdp_rect overlay_rect;
|
||||
|
||||
class OverlayControlChannel {
|
||||
|
||||
bool mNoRot;
|
||||
|
||||
int mFBWidth;
|
||||
int mFBHeight;
|
||||
int mFBbpp;
|
||||
int mFBystride;
|
||||
int mFormat;
|
||||
int mFD;
|
||||
int mRotFD;
|
||||
int mSize;
|
||||
int mOrientation;
|
||||
unsigned int mFormat3D;
|
||||
bool mUIChannel;
|
||||
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 flags, int orientation, int zorder = 0, bool ignoreFB = false,
|
||||
int requestType = NEW_REQUEST);
|
||||
bool startOVRotatorSessions(const overlay_buffer_info& info, int orientation, int requestType);
|
||||
void swapOVRotWidthHeight();
|
||||
|
||||
public:
|
||||
OverlayControlChannel();
|
||||
~OverlayControlChannel();
|
||||
bool startControlChannel(int w, int h, int format,
|
||||
int fbnum, bool norot = false,
|
||||
bool uichannel = false,
|
||||
unsigned int format3D = 0, int zorder = 0,
|
||||
bool ignoreFB = false);
|
||||
bool closeControlChannel();
|
||||
bool setPosition(int x, int y, uint32_t w, uint32_t h);
|
||||
bool setParameter(int param, 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 updateWaitForVsyncFlags(bool waitForVsync);
|
||||
bool getAspectRatioPosition(int w, int h, overlay_rect *rect);
|
||||
bool getPositionS3D(int channel, int format, overlay_rect *rect);
|
||||
bool updateOverlaySource(const overlay_buffer_info& info, int orientation, bool waitForVsync);
|
||||
bool getFormat() const { return mFormat; }
|
||||
bool useVirtualFB ();
|
||||
int getOverlayFlags() const { return mOVInfo.flags; }
|
||||
};
|
||||
|
||||
class OverlayDataChannel {
|
||||
|
||||
bool mNoRot;
|
||||
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;
|
||||
int 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 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 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 updateStatus, int size);
|
||||
};
|
||||
|
||||
/*
|
||||
* Overlay class for single thread application
|
||||
* A multiple thread/process application need to use Overlay HAL
|
||||
*/
|
||||
class Overlay {
|
||||
|
||||
bool mChannelUP;
|
||||
bool mHDMIConnected;
|
||||
unsigned int mS3DFormat;
|
||||
//Actual cropped source width and height of overlay
|
||||
int mCroppedSrcWidth;
|
||||
int mCroppedSrcHeight;
|
||||
overlay_buffer_info mOVBufferInfo;
|
||||
int mState;
|
||||
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, bool ignoreFB = false,
|
||||
int num_buffers = 2);
|
||||
bool closeChannel();
|
||||
bool setPosition(int x, int y, uint32_t w, uint32_t h);
|
||||
bool setParameter(int param, 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, bool hdmiConnected,
|
||||
bool ignoreFB = false, int numBuffers = 2);
|
||||
bool setCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h);
|
||||
int getChannelStatus() const { return (mChannelUP ? OVERLAY_CHANNEL_UP: OVERLAY_CHANNEL_DOWN); }
|
||||
void setHDMIStatus (bool isHDMIConnected) { mHDMIConnected = isHDMIConnected; mState = -1; }
|
||||
int getHDMIStatus() const {return (mHDMIConnected ? HDMI_ON : HDMI_OFF); }
|
||||
|
||||
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, bool waitForVsync);
|
||||
int getS3DFormat(int format);
|
||||
};
|
||||
|
||||
struct overlay_shared_data {
|
||||
volatile bool isControlSetup;
|
||||
unsigned int state;
|
||||
int rotid[2];
|
||||
int ovid[2];
|
||||
};
|
||||
};
|
||||
#endif
|
524
liboverlay/overlayLibUI.cpp
Normal file
524
liboverlay/overlayLibUI.cpp
Normal file
@ -0,0 +1,524 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "overlayLibUI.h"
|
||||
#include "gralloc_priv.h"
|
||||
#define LOG_TAG "OverlayUI"
|
||||
|
||||
using android::sp;
|
||||
using gralloc::IMemAlloc;
|
||||
using gralloc::alloc_data;
|
||||
|
||||
namespace {
|
||||
/* helper functions */
|
||||
bool checkOVState(int w, int h, int format, int orientation,
|
||||
int zorder, const mdp_overlay& ov) {
|
||||
switch(orientation) {
|
||||
case OVERLAY_TRANSFORM_ROT_90:
|
||||
case OVERLAY_TRANSFORM_ROT_270: {
|
||||
int tmp = w;
|
||||
w = h;
|
||||
h = tmp;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
int srcw = (w + 31) & ~31;
|
||||
int srch = (h + 31) & ~31;
|
||||
bool displayAttrsCheck = ((srcw == ov.src.width) && (srch == ov.src.height) &&
|
||||
(format == ov.src.format));
|
||||
bool zOrderCheck = (ov.z_order == zorder);
|
||||
|
||||
if (displayAttrsCheck && zorder == overlay::NO_INIT)
|
||||
return true;
|
||||
|
||||
if (displayAttrsCheck && zorder != overlay::NO_INIT
|
||||
&& ov.z_order == zorder)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void setupOvRotInfo(int w, int h, int format, int orientation,
|
||||
mdp_overlay& ovInfo, msm_rotator_img_info& rotInfo) {
|
||||
memset(&ovInfo, 0, sizeof(ovInfo));
|
||||
memset(&rotInfo, 0, sizeof(rotInfo));
|
||||
ovInfo.id = MSMFB_NEW_REQUEST;
|
||||
int srcw = (w + 31) & ~31;
|
||||
int srch = (h + 31) & ~31;
|
||||
ovInfo.src.width = srcw;
|
||||
ovInfo.src.height = srch;
|
||||
ovInfo.src.format = format;
|
||||
ovInfo.src_rect.w = w;
|
||||
ovInfo.src_rect.h = h;
|
||||
ovInfo.alpha = 0xff;
|
||||
ovInfo.transp_mask = 0xffffffff;
|
||||
rotInfo.src.format = format;
|
||||
rotInfo.dst.format = format;
|
||||
rotInfo.src.width = srcw;
|
||||
rotInfo.src.height = srch;
|
||||
rotInfo.src_rect.w = srcw;
|
||||
rotInfo.src_rect.h = srch;
|
||||
rotInfo.dst.width = srcw;
|
||||
rotInfo.dst.height = srch;
|
||||
|
||||
int rot = orientation;
|
||||
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 = ovInfo.src_rect.x;
|
||||
ovInfo.src_rect.x = ovInfo.src.height -
|
||||
(ovInfo.src_rect.y + ovInfo.src_rect.h);
|
||||
ovInfo.src_rect.y = tmp;
|
||||
swapOVRotWidthHeight(rotInfo, ovInfo);
|
||||
rot = HAL_TRANSFORM_ROT_90;
|
||||
break;
|
||||
}
|
||||
case HAL_TRANSFORM_ROT_180:
|
||||
break;
|
||||
case HAL_TRANSFORM_ROT_270: {
|
||||
int tmp = ovInfo.src_rect.y;
|
||||
ovInfo.src_rect.y = ovInfo.src.width -
|
||||
(ovInfo.src_rect.x + ovInfo.src_rect.w);
|
||||
ovInfo.src_rect.x = tmp;
|
||||
swapOVRotWidthHeight(rotInfo, ovInfo);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
int mdp_rotation = overlay::get_mdp_orientation(rot);
|
||||
if (mdp_rotation < 0)
|
||||
mdp_rotation = 0;
|
||||
ovInfo.user_data[0] = mdp_rotation;
|
||||
rotInfo.rotations = ovInfo.user_data[0];
|
||||
if (mdp_rotation)
|
||||
rotInfo.enable = 1;
|
||||
ovInfo.dst_rect.w = ovInfo.src_rect.w;
|
||||
ovInfo.dst_rect.h = ovInfo.src_rect.h;
|
||||
}
|
||||
|
||||
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 ALREADY_EXISTS;
|
||||
|
||||
status_t ret = NO_INIT;
|
||||
char const * const device_template =
|
||||
"/dev/graphics/fb%u";
|
||||
char dev_name[64];
|
||||
snprintf(dev_name, 64, 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;
|
||||
}
|
||||
|
||||
status_t OVHelper::startOVSession(mdp_overlay& ovInfo, int fbnum) {
|
||||
status_t ret = NO_INIT;
|
||||
|
||||
if (mSessionID == NO_INIT) {
|
||||
ret = mobjDisplay.openDisplay(fbnum);
|
||||
if (ret != NO_ERROR)
|
||||
return ret;
|
||||
|
||||
if (ioctl(mobjDisplay.getFD(), MSMFB_OVERLAY_SET, &ovInfo)) {
|
||||
LOGE("OVerlay set failed..");
|
||||
mobjDisplay.closeDisplay();
|
||||
ret = BAD_VALUE;
|
||||
}
|
||||
else {
|
||||
mSessionID = ovInfo.id;
|
||||
mOVInfo = ovInfo;
|
||||
ret = NO_ERROR;
|
||||
}
|
||||
}
|
||||
else
|
||||
ret = ALREADY_EXISTS;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
status_t OVHelper::queueBuffer(msmfb_overlay_data ovData) {
|
||||
if (mSessionID == NO_INIT)
|
||||
return NO_INIT;
|
||||
|
||||
ovData.id = mSessionID;
|
||||
if (ioctl(mobjDisplay.getFD(), MSMFB_OVERLAY_PLAY, &ovData))
|
||||
return BAD_VALUE;
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
status_t OVHelper::closeOVSession() {
|
||||
if (mSessionID != NO_INIT) {
|
||||
ioctl(mobjDisplay.getFD(), MSMFB_OVERLAY_UNSET, &mSessionID);
|
||||
mobjDisplay.closeDisplay();
|
||||
}
|
||||
|
||||
mSessionID = NO_INIT;
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
status_t OVHelper::setPosition(int x, int y, int w, int h) {
|
||||
status_t ret = BAD_VALUE;
|
||||
if (mSessionID != NO_INIT) {
|
||||
int fd = mobjDisplay.getFD();
|
||||
if (x < 0 || y < 0 || ((x + w) > getFBWidth())) {
|
||||
LOGE("set position failed, invalid argument");
|
||||
return ret;
|
||||
}
|
||||
|
||||
mdp_overlay ov;
|
||||
ov.id = mSessionID;
|
||||
if (!ioctl(fd, MSMFB_OVERLAY_GET, &ov)) {
|
||||
if (x != ov.dst_rect.x || y != ov.dst_rect.y ||
|
||||
w != ov.dst_rect.w || h != ov.dst_rect.h) {
|
||||
ov.dst_rect.x = x;
|
||||
ov.dst_rect.y = y;
|
||||
ov.dst_rect.w = w;
|
||||
ov.dst_rect.h = h;
|
||||
if (ioctl(fd, MSMFB_OVERLAY_SET, &ov)) {
|
||||
LOGE("set position failed");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
mOVInfo = ov;
|
||||
return NO_ERROR;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
return NO_INIT;
|
||||
}
|
||||
|
||||
status_t OVHelper::getOVInfo(mdp_overlay& ovInfo) {
|
||||
if (mSessionID == NO_INIT)
|
||||
return NO_INIT;
|
||||
ovInfo = mOVInfo;
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
status_t Rotator::startRotSession(msm_rotator_img_info& rotInfo,
|
||||
int size, int numBuffers) {
|
||||
status_t ret = ALREADY_EXISTS;
|
||||
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 (int check = ioctl(mFD, MSM_ROTATOR_IOCTL_START, &rotInfo)) {
|
||||
close(mFD);
|
||||
mFD = NO_INIT;
|
||||
return NO_INIT;
|
||||
}
|
||||
|
||||
#ifdef USE_ION
|
||||
alloc_data data;
|
||||
data.base = 0;
|
||||
data.fd = -1;
|
||||
data.offset = 0;
|
||||
data.size = mSize * mNumBuffers;
|
||||
data.align = getpagesize();
|
||||
data.uncached = true;
|
||||
|
||||
int err = mAlloc->allocate(data, GRALLOC_USAGE_PRIVATE_ADSP_HEAP|
|
||||
GRALLOC_USAGE_PRIVATE_SMI_HEAP, 0);
|
||||
|
||||
if(err) {
|
||||
LOGE("Cant allocate from ION");
|
||||
closeRotSession();
|
||||
return NO_INIT;
|
||||
}
|
||||
mPmemFD = data.fd;
|
||||
mPmemAddr = data.base;
|
||||
mBufferType = data.allocType;
|
||||
#else
|
||||
mSessionID = rotInfo.session_id;
|
||||
mPmemFD = open("/dev/pmem_adsp", O_RDWR | O_SYNC);
|
||||
if (mPmemFD < 0) {
|
||||
closeRotSession();
|
||||
return NO_INIT;
|
||||
}
|
||||
|
||||
mSize = size;
|
||||
mPmemAddr = (void *) mmap(NULL, mSize* mNumBuffers, PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED, mPmemFD, 0);
|
||||
if (mPmemAddr == MAP_FAILED) {
|
||||
closeRotSession();
|
||||
return NO_INIT;
|
||||
}
|
||||
#endif
|
||||
|
||||
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);
|
||||
#ifdef USE_ION
|
||||
sp<IMemAlloc> memalloc = mAlloc->getAllocator(mBufferType);
|
||||
memalloc->free_buffer(mPmemAddr, mSize * mNumBuffers, 0, mPmemFD);
|
||||
#else
|
||||
munmap(mPmemAddr, mSize * mNumBuffers);
|
||||
close(mPmemFD);
|
||||
#endif
|
||||
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;
|
||||
}
|
||||
|
||||
status_t OverlayUI::closeChannel() {
|
||||
mobjOVHelper.closeOVSession();
|
||||
mobjRotator.closeRotSession();
|
||||
mChannelState = CLOSED;
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
status_t OverlayUI::setSource(const overlay_buffer_info& info, int orientation,
|
||||
bool useVGPipe, bool ignoreFB,
|
||||
int fbnum, int zorder) {
|
||||
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))
|
||||
return ret;
|
||||
|
||||
if (mChannelState == PENDING_CLOSE)
|
||||
closeChannel();
|
||||
|
||||
if (mChannelState == UP) {
|
||||
mdp_overlay ov;
|
||||
if (mobjOVHelper.getOVInfo(ov) == NO_ERROR) {
|
||||
if (mOrientation == orientation &&
|
||||
mFBNum == fbnum &&
|
||||
checkOVState(info.width, info.height, format, orientation, zorder, ov))
|
||||
return NO_ERROR;
|
||||
else
|
||||
mChannelState = PENDING_CLOSE;
|
||||
}
|
||||
else
|
||||
mChannelState = PENDING_CLOSE;
|
||||
return ret;
|
||||
}
|
||||
|
||||
mOrientation = orientation;
|
||||
mdp_overlay ovInfo;
|
||||
msm_rotator_img_info rotInfo;
|
||||
setupOvRotInfo(info.width, info.height, format, orientation, ovInfo, rotInfo);
|
||||
|
||||
int flags = 0;
|
||||
if (ignoreFB)
|
||||
ovInfo.is_fg = 1;
|
||||
else
|
||||
flags |= MDP_OV_PLAY_NOWAIT;
|
||||
|
||||
if (turnOFFVSync())
|
||||
flags |= MDP_OV_PLAY_NOWAIT;
|
||||
|
||||
if (useVGPipe ||
|
||||
(fbnum == FB0 && getRGBBpp(format) != mobjOVHelper.getFBBpp()))
|
||||
flags |= MDP_OV_PIPE_SHARE;
|
||||
|
||||
ovInfo.flags = flags;
|
||||
if (zorder != NO_INIT)
|
||||
ovInfo.z_order = zorder;
|
||||
|
||||
ret = startChannel(fbnum, ovInfo, rotInfo, info.size);
|
||||
return ret;
|
||||
}
|
||||
|
||||
status_t OverlayUI::startChannel(int fbnum, mdp_overlay& ovInfo,
|
||||
msm_rotator_img_info& rotInfo, int size) {
|
||||
status_t ret = BAD_VALUE;
|
||||
if (mChannelState == UP)
|
||||
return ret;
|
||||
|
||||
ret = mobjOVHelper.startOVSession(ovInfo, fbnum);
|
||||
if (ret == NO_ERROR && mOrientation) {
|
||||
ret = mobjRotator.startRotSession(rotInfo, size);
|
||||
}
|
||||
|
||||
if (ret == NO_ERROR) {
|
||||
mChannelState = UP;
|
||||
mFBNum = fbnum;
|
||||
}
|
||||
else
|
||||
LOGE("start channel failed.");
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
ret = mobjOVHelper.queueBuffer(ovData);
|
||||
if (ret != NO_ERROR)
|
||||
LOGE("Queuebuffer failed ");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
};
|
160
liboverlay/overlayLibUI.h
Normal file
160
liboverlay/overlayLibUI.h
Normal file
@ -0,0 +1,160 @@
|
||||
/*
|
||||
* 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() { close(mFD); mFD = NO_INIT; };
|
||||
};
|
||||
|
||||
/*
|
||||
* OVHelper class, provides apis related to Overlay
|
||||
* It communicates with MDP driver, provides following services
|
||||
* Start overlay session
|
||||
* Set position of the destination on to display
|
||||
*/
|
||||
|
||||
class OVHelper {
|
||||
int mSessionID;
|
||||
Display mobjDisplay;
|
||||
mdp_overlay mOVInfo;
|
||||
OVHelper(const OVHelper& objOVHelper);
|
||||
OVHelper& operator=(const OVHelper& objOVHelper);
|
||||
|
||||
public:
|
||||
explicit OVHelper() : mSessionID(NO_INIT) { };
|
||||
~OVHelper() { closeOVSession(); };
|
||||
status_t startOVSession(mdp_overlay& ovInfo, int fbnum);
|
||||
status_t closeOVSession();
|
||||
status_t queueBuffer(msmfb_overlay_data ovData);
|
||||
int getFBWidth() const { return mobjDisplay.getFBWidth(); };
|
||||
int getFBHeight() const { return mobjDisplay.getFBHeight(); };
|
||||
int getFBBpp() const { return mobjDisplay.getFBBpp(); };
|
||||
status_t setPosition(int x, int y, int w, int h);
|
||||
status_t getOVInfo(mdp_overlay& ovInfo);
|
||||
};
|
||||
|
||||
/*
|
||||
* 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() : mFD(NO_INIT), mSessionID(NO_INIT), mPmemFD(-1)
|
||||
{
|
||||
#ifdef USE_ION
|
||||
mAlloc = gralloc::IAllocController::getInstance();
|
||||
#endif
|
||||
}
|
||||
~Rotator() { closeRotSession(); }
|
||||
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;
|
||||
int mOrientation;
|
||||
int mFBNum;
|
||||
OVHelper mobjOVHelper;
|
||||
Rotator mobjRotator;
|
||||
|
||||
OverlayUI(const OverlayUI& objOverlay);
|
||||
OverlayUI& operator=(const OverlayUI& objOverlay);
|
||||
|
||||
status_t startChannel(int fbnum, mdp_overlay& ovInfo,
|
||||
msm_rotator_img_info& rotInfo, int size);
|
||||
public:
|
||||
|
||||
enum fbnum_t { FB0, FB1 };
|
||||
|
||||
explicit OverlayUI() : mChannelState(CLOSED), mOrientation(NO_INIT), mFBNum(NO_INIT) { };
|
||||
~OverlayUI() { closeChannel(); };
|
||||
status_t setSource(const overlay_buffer_info& info, int orientation,
|
||||
bool useVGPipe = false, bool ignoreFB = true,
|
||||
int fbnum = FB0, int zorder = NO_INIT);
|
||||
status_t setPosition(int x, int y, int w, int h) {
|
||||
return mobjOVHelper.setPosition(x, y, w, h);
|
||||
};
|
||||
status_t closeChannel();
|
||||
channel_state_t isChannelUP() const { return mChannelState; };
|
||||
int getFBWidth() const { return mobjOVHelper.getFBWidth(); };
|
||||
int getFBHeight() const { return mobjOVHelper.getFBHeight(); };
|
||||
status_t queueBuffer(buffer_handle_t buffer);
|
||||
};
|
||||
|
||||
};
|
||||
#endif
|
1109
liboverlay/overlayState.cpp
Normal file
1109
liboverlay/overlayState.cpp
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user